@llblab/pi-actors 0.41.0 → 0.41.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/AGENTS.md CHANGED
@@ -70,7 +70,7 @@ Pi host
70
70
 
71
71
  - Prefer explicit operator action over silent user-config rewrites.
72
72
  - Keep published documentation portable: use `~`, `<repo>`, or relative paths instead of machine-local absolute paths.
73
- - Preserve runtime output discipline because tool output flows directly into agent context.
73
+ - Preserve runtime output discipline because tool output flows directly into agent context. Tool result/error text contributes exactly one leading line break; Pi's renderer contributes the other break after the call header, producing one empty separator row without doubled gaps.
74
74
  - Optimize every actor-facing surface for signal over volume: prefer compact state-backed hints and fewer concepts over broad explanatory prose or speculative guidance.
75
75
  - Split broad domains proactively when the current name becomes a generic bucket. Prefer concise domain names that match actual ownership. `tools.ts` is the public tool family owner; decomposed tool subdomains use `tools-<part>.ts` (`tools-message.ts`, `tools-inspect.ts`, `tools-spawn.ts`) under that family. Keep only genuinely cross-family domains unprefixed (`schema.ts`); tool-only helpers stay under `tools-*`. If a `tools-*` helper becomes reused by non-tools domains, remove the `tools-` prefix in the same slice and update ownership comments/imports so the name matches its broader responsibility. Avoid redundant internal `actor-` file prefixes in this actor-scoped package unless the file is deliberately tied to a public actor-named recipe/script/docs surface.
76
76
  - Until a stable release greater than `1.x.x`, favor context compression over compatibility shims: do not preserve legacy actor-facing names, aliases, fields, env vars, paths, or docs solely for backward compatibility when a clearer current term exists. Remove compatibility layers in the same slice that renames a concept, and record the break in `CHANGELOG.md`.
@@ -107,7 +107,7 @@ Pi host
107
107
  - Preserve node controls: `when`, positive `timeout`, `delay`, bounded `retry`, `failure`, and `recover` cleanup.
108
108
  - Persist every async command's complete byte-exact stdout/stderr under command- and retry-specific run-state paths while keeping returned tails bounded and pipeline stdin complete.
109
109
  - Keep async run state under `~/.pi/agent/tmp/pi-actors/runs` with injected `{run_id}` and `{state_dir}` values.
110
- - Preserve event-driven observability: durable retrying terminal follow-up notifications, coordinator-bound outbox messages, branch-aware triangles, process-tree expansion, and bounded body previews. Queue coordinator context through Pi follow-up delivery rather than steering so current work finishes before async results arrive and host follow-up batching policy can combine concurrent completions. Terminal delivery is at-least-once across the unavoidable send/handled-marker crash window.
110
+ - Preserve event-driven observability with bounded reconciliation: file watchers accelerate durable retrying terminal follow-up notifications, while a conservative terminal-only interval recovers missed watcher activity, rearms degraded watchers, and never replays outbox traffic. Queue coordinator context through Pi follow-up delivery rather than steering so current work finishes before async results arrive and host follow-up batching policy can combine concurrent completions. Terminal delivery is at-least-once across the unavoidable send/handled-marker crash window; watch-triggered and periodic delivery share one live-runtime in-flight guard.
111
111
  - When a deferred actor result gates the next step, wait for its terminal follow-up. Do not schedule continuation loops, repeatedly inspect, or mutate its reviewed scope while it runs; inspect early only on operator request, meaningful actor event, or diagnosis of an overdue/stuck run.
112
112
  - Do not restore busy-polling examples, duplicate terminal notifications, or duplicate notifications for handled `cancel`, `kill`, or control-stop actions.
113
113
 
package/BACKLOG.md CHANGED
@@ -43,25 +43,6 @@ Non-goals:
43
43
 
44
44
  - [ ] Add a manually invoked command that launches an agent-led consolidation cycle over `~/.pi/agent/recipes/drafts`. The cycle must inventory and classify every draft, propose a complete `promote`, `merge`, or `discard` plan, require explicit operator confirmation before mutations, normalize approved reusable capabilities into active recipe-backed tools under `~/.pi/agent/recipes`, and remove every handled source so the drafts directory finishes empty. It must never run automatically or promote tools silently; preserve evidence for each decision and add regressions for plan-only, confirmation, promotion, merge, discard, failure recovery, and empty-directory completion.
45
45
 
46
- ### Overlay actor inspector
47
-
48
- - [ ] Replace the command-driven inspector workflow with one large keyboard-driven overlay while preserving the compact striped information design. Stop conditions: `/actors-inspector-toggle` only toggles the overlay; an operator can select an owned run and subagent, switch `Messages` / `Turns` tabs, navigate rows, open/close detail, scroll bounded content, and understand keys/current scope without entering subcommands.
49
- - [x] Close the dogfood security prerequisites: reset selection across Pi sessions, revalidate ownership before every selected-run read, contain session evidence beneath the owned run state, broaden structured/text redaction, and add regressions.
50
- - [x] Build the centered responsive overlay shell with bordered header/footer, tabs, owned-run/subagent selector, active-scope summary, empty/loading/error states, and Escape close.
51
- - [x] Move compact striped Messages rows, filters, unread filtering/attention markers, roster context, and row detail into keyboard navigation.
52
- - [x] Move Turns rows and full bounded provenance/tool detail into keyboard navigation with scrolling and explicit persisted/unavailable reasoning labels.
53
- - [x] Remove the subcommand grammar and below-editor widget lifecycle, retain only the toggle command, and document discoverable key hints plus responsive behavior.
54
- - [ ] Run full package, conformance, and context validation, then close this item. Component input/render/width/scroll/tab/ownership/live-refresh regressions and iterative manual TUI dogfood now cover the accepted visual interaction contract.
55
-
56
- ### Inspector execution observability
57
-
58
- - [x] Consolidate the actor inspector into one manually opened, navigable operator surface for communication and execution evidence. Stop conditions: an operator can choose an owned run/subagent, switch between communication and turn timelines, open one bounded detail view, and inspect every persisted user/assistant/tool-result turn in source order without exposing another session or claiming unavailable hidden reasoning.
59
- - [x] Persist deterministic Pi session provenance for each child `pi -p` command under its owned run state, without overriding an explicitly supplied session policy; record the session path in command evidence and tolerate commands that never create a session.
60
- - [x] Add a resilient, bounded session-evidence reader that follows the active JSONL entry branch, groups assistant responses with correlated tool calls/results into turns, preserves model/usage/error metadata, redacts sensitive argument/content fields, and reports malformed or incomplete evidence honestly.
61
- - [x] Replace communication-specific inspector controller state with a shared navigation model: run selector → `communication` or `turns` timeline → numbered detail, with stable back/toggle/filter behavior and useful empty states for actors that never send messages.
62
- - [x] Render compact turn rows and bounded manual detail views for effective prompt/context references, assistant text, host-exposed thinking blocks, tool arguments/results, model/usage, and source-file provenance; label missing reasoning as unavailable rather than inferred.
63
- - [x] Add ownership, truncation, redaction, malformed JSONL, active-branch ordering, tool correlation, parallel tool completion, terminal run, coordinator-launched subagent, and communication-navigation regressions; update the Actors skill and inspector documentation after the interaction contract stabilizes.
64
-
65
46
  ## Backlog Curation Rules
66
47
 
67
48
  - Completed work belongs in `CHANGELOG.md`, not in `BACKLOG.md`.
package/CHANGELOG.md CHANGED
@@ -2,6 +2,13 @@
2
2
 
3
3
  ## Unreleased
4
4
 
5
+ ## 0.41.1: Actor Inspector and Delivery Hotfix
6
+
7
+ - `Terminal Delivery`: Added bounded ten-second terminal reconciliation and watcher rearm so owned terminal follow-ups converge without reload when file watching misses or fails. Delivery still uses Pi follow-ups with owner filtering, `triggerTurn`, no historical outbox replay, and the existing at-least-once handled-marker contract; routine run-directory removal stays quiet while real watcher degradation remains diagnostic.
8
+ - `Actor Inspector`: Finished the 0.41 overlay line around a compact meaning-first workflow. `/actors-inspector` now opens the latest numbered Run; Run, Message, and Turn lists show newest evidence first; bounded menus remain usable on short terminals; and humanized Turn rows lead into wrapped Evidence and a metadata-free readable transcript. Turn content now prioritizes User, Thinking, Assistant, and tool actions before Execution and Provenance, strips prompt transport wrappers in readable mode, keeps logical sections on one stripe, and removes false wraps, clipped values, redundant labels/separators, and blank rows.
9
+ - `Tool Output`: Normalized successful results and errors to contribute exactly one leading line break, preserving one empty separator row beneath Pi's rendered tool-call header without occasional double gaps.
10
+ - `Agent Guidance`: Kept Inspector behavior in user documentation and removed it from the bundled Actors skill, leaving that skill focused on agent-operational `spawn`, `message`, `inspect`, recipes, and lifecycle guidance.
11
+
5
12
  ## 0.41.0: Actor Inspector Overlay and Execution Observability
6
13
 
7
14
  - `[Inspector Menu Alignment]` Shifted value submenus one cell left so adjacent levels share a border, aligned Run and tab labels to one vertical grid, and made the Run dropdown begin immediately below Run by overlaying the tab row. Impact: nested menus read as one connected hierarchy and every top-level control follows the same anchored dropdown rhythm.
package/dist/index.js CHANGED
@@ -19,8 +19,10 @@ export default function toolRegistryExtension(pi) {
19
19
  let runsAnimationInterval;
20
20
  let runsNotifyTimeout;
21
21
  let activeRunContext;
22
+ let lastRunWatcherDiagnosticId = 0;
22
23
  const runUi = Observability.createRunUiObservationState();
23
24
  const retirementAttempts = new Set();
25
+ const terminalNotificationsInFlight = new Set();
24
26
  const getRunOwnerId = Pi.getSessionId;
25
27
  const retireCandidateRuns = (ctx, summary) => {
26
28
  void Observability.executeRunRetirements(summary, {
@@ -38,7 +40,7 @@ export default function toolRegistryExtension(pi) {
38
40
  return;
39
41
  const notificationSink = Pi.createNotificationSink(pi, ctx);
40
42
  retireCandidateRuns(ctx, snapshot.summary);
41
- Observability.deliverRunTransitionNotifications(snapshot.transitions, notificationSink);
43
+ Observability.deliverRunTransitionNotifications(snapshot.transitions, notificationSink, terminalNotificationsInFlight);
42
44
  Observability.pruneRunUiObservationState(runUi, snapshot);
43
45
  if (!terminalOnly) {
44
46
  Observability.deliverRunOutboxNotifications(snapshot.outboxEvents, notificationSink);
@@ -46,22 +48,57 @@ export default function toolRegistryExtension(pi) {
46
48
  };
47
49
  const closeRunWatchers = () => {
48
50
  runWatcher.close();
51
+ terminalReconciliation.close();
49
52
  if (runsNotifyTimeout)
50
53
  clearTimeout(runsNotifyTimeout);
51
54
  runsNotifyTimeout = undefined;
52
55
  };
53
- const scheduleRunEventUpdate = (ctx) => {
56
+ const reportRunWatcherDiagnostics = (ctx) => {
57
+ for (const diagnostic of runWatcher.getDiagnostics()) {
58
+ if (diagnostic.id <= lastRunWatcherDiagnosticId)
59
+ continue;
60
+ lastRunWatcherDiagnosticId = diagnostic.id;
61
+ ctx.ui.notify(diagnostic.message, diagnostic.code === "rearmed" ? "info" : "warning");
62
+ }
63
+ };
64
+ const scheduleRunEventUpdate = () => {
54
65
  if (runsNotifyTimeout)
55
66
  clearTimeout(runsNotifyTimeout);
56
67
  runsNotifyTimeout = setTimeout(() => {
68
+ const ctx = activeRunContext;
69
+ if (!ctx)
70
+ return;
57
71
  runWatcher.refresh();
58
72
  updateRunUi(ctx, true);
73
+ reportRunWatcherDiagnostics(ctx);
59
74
  }, 50);
60
75
  runsNotifyTimeout.unref?.();
61
76
  };
62
77
  const runWatcher = Observability.createRunStateWatcher({
63
78
  stateRoot: Paths.EXTENSION_RUNTIME_PATHS.runStateRoot,
64
- onChange: () => activeRunContext && scheduleRunEventUpdate(activeRunContext),
79
+ onChange: scheduleRunEventUpdate,
80
+ });
81
+ const terminalReconciliation = Observability.createRunTerminalReconciliationLoop({
82
+ onError: (error) => {
83
+ const ctx = activeRunContext;
84
+ if (!ctx)
85
+ return;
86
+ const message = error instanceof Error ? error.message : String(error);
87
+ ctx.ui.notify(`Actor terminal reconciliation failed: ${message}`, "error");
88
+ },
89
+ reconcile: () => {
90
+ const ctx = activeRunContext;
91
+ if (!ctx)
92
+ return;
93
+ Observability.reconcileRunTerminalNotifications({
94
+ inFlight: terminalNotificationsInFlight,
95
+ ownerId: getRunOwnerId(ctx),
96
+ sink: Pi.createNotificationSink(pi, ctx),
97
+ state: runUi,
98
+ });
99
+ reportRunWatcherDiagnostics(ctx);
100
+ },
101
+ refreshWatcher: () => runWatcher.refresh(),
65
102
  });
66
103
  const actorToolDefinitions = new Map();
67
104
  const withCurrentThinkingContext = (definition) => {
@@ -111,16 +148,22 @@ export default function toolRegistryExtension(pi) {
111
148
  // Clear the pre-overlay widget after hot reloads from older pi-actors builds.
112
149
  ctx.ui.setWidget("zz-pi-actors-comms", undefined);
113
150
  activeRunContext = ctx;
151
+ closeRunWatchers();
152
+ recipeReload.close();
114
153
  await Temp.prepareExtensionTempDir(Paths.EXTENSION_RUNTIME_PATHS.tempDir);
154
+ if (activeRunContext !== ctx)
155
+ return;
115
156
  runtime.loadTools(ctx);
116
157
  updateRunUi(ctx, true, true);
117
- closeRunWatchers();
118
- recipeReload.close();
119
158
  runWatcher.refresh();
159
+ terminalReconciliation.start();
120
160
  recipeReload.watch(ctx);
121
161
  if (runsAnimationInterval)
122
162
  clearInterval(runsAnimationInterval);
123
- runsAnimationInterval = setInterval(() => updateRunUi(ctx, false), 1000);
163
+ runsAnimationInterval = setInterval(() => {
164
+ if (activeRunContext === ctx)
165
+ updateRunUi(ctx, false);
166
+ }, 1000);
124
167
  runsAnimationInterval.unref?.();
125
168
  });
126
169
  pi.on("session_shutdown", async () => {
@@ -131,8 +174,8 @@ export default function toolRegistryExtension(pi) {
131
174
  closeRunWatchers();
132
175
  recipeReload.close();
133
176
  });
134
- pi.registerCommand("actors-inspector-toggle", {
135
- description: "Toggle the keyboard-driven actor inspector overlay",
177
+ pi.registerCommand("actors-inspector", {
178
+ description: "Open the keyboard-driven actor inspector overlay",
136
179
  handler: async (_args, ctx) => {
137
180
  ctx.ui.setWidget("zz-pi-actors-comms", undefined);
138
181
  await ctx.ui.custom((tui, theme, _keybindings, done) => new InspectorOverlay.ActorInspectorOverlay({
@@ -29,6 +29,7 @@ export declare class ActorInspectorOverlay {
29
29
  private detailOpen;
30
30
  private detailScroll;
31
31
  private detailTurn?;
32
+ private detailView;
32
33
  private readonly readKeys;
33
34
  private focus;
34
35
  private filterControlIndex;
@@ -45,6 +46,9 @@ export declare class ActorInspectorOverlay {
45
46
  dispose(): void;
46
47
  private runs;
47
48
  private ensureSelectedRun;
49
+ private contentViewportRows;
50
+ private selectRun;
51
+ private cycleRun;
48
52
  private listItemCount;
49
53
  private selectorAnchor;
50
54
  private renderKeyHints;
@@ -58,6 +62,12 @@ export declare class ActorInspectorOverlay {
58
62
  private communicationFromOptions;
59
63
  private communicationRows;
60
64
  private renderDetail;
65
+ private wrapDetailLines;
66
+ private detailSection;
67
+ private readableValueLines;
68
+ private turnEvidenceLines;
69
+ private readablePromptText;
70
+ private turnTranscriptLines;
61
71
  private turnItems;
62
72
  private turnRows;
63
73
  private subagents;
@@ -73,6 +83,7 @@ export declare class ActorInspectorOverlay {
73
83
  private renderMenuBox;
74
84
  private renderFilterMenus;
75
85
  private openDetail;
86
+ private backDetail;
76
87
  private closeDetail;
77
88
  private border;
78
89
  private stripeBackground;