Skip to content

feat(palace): add ActivityEvent sink on PalaceBuilder (jcode shape) (mp-migration 5/8)#23

Merged
quangdang46 merged 1 commit into
mainfrom
feat/mp-pr5-activity-sink
Jun 3, 2026
Merged

feat(palace): add ActivityEvent sink on PalaceBuilder (jcode shape) (mp-migration 5/8)#23
quangdang46 merged 1 commit into
mainfrom
feat/mp-pr5-activity-sink

Conversation

@quangdang46
Copy link
Copy Markdown
Owner

Summary

Add the API shape for activity streaming — the type, the builder method, and the storage slot. The jcode adapter can already register a sink; emit-calls from the runtime are scoped to a follow-up.

// New types in palace.rs
pub struct ActivityEvent {
    pub state: ActivityState,
    pub detail: Option<String>,
    pub timestamp: chrono::DateTime<chrono::Utc>,
}

pub enum ActivityState {
    Idle, Embedding, SidecarChecking, FoundRelevant,
    Extracting, Maintaining,
    ToolAction { action: &'static str },
}

// New on PalaceBuilder
pub fn activity_sink(self, sink: Arc<dyn Fn(ActivityEvent) + Send + Sync>) -> Self;

// New on Palace (pub)
pub activity_sink: Option<Arc<dyn Fn(ActivityEvent) + Send + Sync>>;

Motivation

Required for the jcode → mempalace Mode C library migration (mp-migration 5/8). jcode's MemoryEventSink = Arc<dyn Fn(ServerEvent) + Send + Sync> drives the TUI info widget's MemoryActivity snapshot, which has 4 pipeline states (search → verify → inject → maintain) and 24 event kinds. jcode publishes transitions at every meaningful point and the TUI reads them to render the "memory is searching…" / "found 3 relevant" / "extracting from session…" indicators.

mempalace has the same internal concept (in background.rs via tracing::info!) but it's:

  • Not exposed on the public API
  • Not typed — just log strings
  • Not consumable by library users

This PR ships the type and the registration path. The emit-calls from the impl MemoryProvider for Palace methods (add_drawer, forget, search, extract_from_transcript, and the background.rs consolidation/lesson-decay loops) are scoped to a follow-up because they touch more lines.

This is PR 5/8 in the migration series. Independent of the trait-method PRs (1/2/4) — type and builder only.

Change

crates/core/src/palace.rs:

  • pub struct ActivityEvent + pub enum ActivityState (~50 lines, includes the 6 state variants)
  • Palace::activity_sink: Option<Arc<dyn Fn(ActivityEvent) + Send + Sync>> field
  • Palace::emit_activity(state, detail) private helper that no-ops when no sink is set

crates/core/src/palace/builder.rs:

  • PalaceBuilder::activity_sink: Option<Arc<dyn Fn(super::ActivityEvent) + Send + Sync>> field
  • PalaceBuilder::activity_sink(sink) builder method (~15 lines)
  • Wires the sink into Palace at open() time

Total: 93 lines added across 2 files.

Out of scope (deliberate follow-ups)

  1. Wire Palace::emit_activity(Embedding, …) at the start of search and search_with_embedding.
  2. Wire Palace::emit_activity(FoundRelevant { count }, …) after a non-empty result.
  3. Wire Palace::emit_activity(ToolAction { action }, …) from the trait mutation methods (PR Fix real-run CLI flows and formatting issues #1 + fix: bug fixes to Rust core #2) where applicable.
  4. Wire Palace::emit_activity(Extracting, …) from extract_from_transcript.
  5. Wire Palace::emit_activity(Maintaining, …) from background.rs::run_consolidation and run_lesson_decay.

These are individual self.emit_activity(...) calls at the right pipeline points; each is a 1-3 line change. Tracking them as separate PRs keeps this one focused on the API surface.

Test plan

  • cargo test -p mempalace-core --lib1127 passed, 0 failed (228s)
  • cargo check -p mempalace-core clean
  • cargo fmt --check -p mempalace-core clean
  • CI green on ubuntu/macos/windows

Series status

# Title Status
6 docs(palace): document Embedder reuse on search_with_embedding merged #16
7 feat(palace): add tags/trust/access_count/reinforcements/superseded_by to Drawer open #17
8 feat(palace): add MemoryProvider::graph_stats_legacy (jcode shape) open #18
1 feat(palace): add boost/decay/reinforce/supersede/set_metadata to MemoryProvider open #19
2 feat(palace): add tag/untag/link/list_tags to MemoryProvider open #20
4 feat(palace): add MemoryProvider::recent for retention-ranked recall open #21
3 feat(palace): add MemoryScope::All and Wing/Room variants open #22
5 feat(palace): add ActivityEvent sink on PalaceBuilder this PR

🤖 Generated with Claude Code

jcode's `MemoryEventSink = Arc<dyn Fn(ServerEvent) + Send + Sync>`
is the per-call activity stream that drives the TUI info widget's
`MemoryActivity` snapshot. The snapshot has 4 pipeline states
(search → verify → inject → maintain) and 24 event kinds; jcode
publishes transitions at every meaningful point.

mempalace has no equivalent on the public API today. The closest
is the internal `background.rs` `tracing::info!()` calls, which
aren't visible to library consumers and don't carry a typed
shape.

Add:

  - `pub struct ActivityEvent { state, detail, timestamp }`
  - `pub enum ActivityState { Idle, Embedding, SidecarChecking,
                                 FoundRelevant, Extracting,
                                 Maintaining, ToolAction { action } }`
  - `PalaceBuilder::activity_sink(sink)` builder method
  - `Palace::activity_sink` pub field
  - `Palace::emit_activity(state, detail)` private helper that
    no-ops when no sink is set

This PR is the **API shape** for activity streaming; it does NOT
yet wire the emit calls into the `impl MemoryProvider for Palace`
methods (that's a follow-up that touches `add_drawer`,
`forget`, `search`, `extract_from_transcript`, and the
`background.rs` consolidation/lesson-decay loops).

The jcode adapter can already use the API as-is to bridge its
`MemoryEventSink` — it will receive no events until the
follow-up lands, but the type and registration path are stable.

This is PR 5/8 in the jcode → mempalace Mode C library migration
series (the runtime-wiring half; PRs 1+2+3+4+6+7+8 are the trait-
method/field/type half).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@quangdang46 quangdang46 merged commit f572a23 into main Jun 3, 2026
4 checks passed
@quangdang46 quangdang46 deleted the feat/mp-pr5-activity-sink branch June 3, 2026 14:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant