@llblab/pi-actors 0.40.1 → 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
@@ -43,7 +43,7 @@ Pi host
43
43
  - `recipes-references.ts`, `recipes-discovery.ts`, `recipes-usage.ts`: recipe graph, discovery, and usage metadata.
44
44
  - `async-runs.ts`: detached run lifecycle facade; `runs-*` subdomains own artifacts, start guards, status, indexes, inbox/outbox, delivery, process control, and retention internals.
45
45
  - `runtime-notifier.ts`, `mailbox-loop.ts`: wake notifications and reusable run/branch mailbox worker loops.
46
- - `messages.ts`, `rooms.ts`, `recipes-context.ts`, `inspector.ts`, `observability.ts`: addressed message protocol, rooms, recipe prompt context, communication previews, and ambient run status.
46
+ - `messages.ts`, `rooms.ts`, `recipes-context.ts`, `session-evidence.ts`, `inspector.ts`, `inspector-overlay.ts`, `observability.ts`: addressed message protocol, rooms, recipe prompt context, bounded/redacted child-session turns, inspector evidence/navigation, keyboard-driven overlay UI, and ambient run status.
47
47
  - `prompts.ts`, `temp.ts`: LLM-facing copy and temp cleanup.
48
48
  - `tools.ts`: public tool family composition and reserved tool names.
49
49
  - `tools-message.ts`: public `message` tool behavior, including run controls, branch/room routing, tool actor invocation, and delivery feedback.
@@ -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/CHANGELOG.md CHANGED
@@ -2,6 +2,38 @@
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
+
12
+ ## 0.41.0: Actor Inspector Overlay and Execution Observability
13
+
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.
15
+ - `[Inspector UX Polish]` Applied the shared focus treatment (`▶`, accent text, neutral background) to timeline rows, exposed non-default filters as compact tab-label suffixes, gave run lifecycle status semantic text color, and split true-empty from filtered-empty guidance. Impact: focus no longer changes visual language between controls and data, hidden filter state stays visible, and empty results explain whether data or the current query is absent.
16
+ - `[Inspector Detail Navigation]` Made Enter/→ open a focused timeline row and Escape/← return from detail; horizontal arrows no longer switch tabs from list focus. Updated contextual footer hints accordingly. Impact: nested list/detail navigation follows the same forward/backward key model as menus, while tab switching remains scoped to tab focus.
17
+ - `[Inspector Message Sender Filter]` Added `From: <actor>` to the Messages filter menu, populated from the selected run's roster, with `all` as the default. Impact: operators can isolate communication emitted by one actor while seeing the current sender scope before opening its values.
18
+ - `[Inspector Nested Menu Context]` Added current values to parent filter items (`Channel: value`, `State: value`, `Subagent: value`) and made unused corners between differently sized parent/value menus transparent to the striped timeline beneath. Impact: operators see filter state before opening alternatives, and nested overlays occlude only useful menu cells.
19
+ - `[Inspector Run And Filter Menus]` Added a top-level owned-run selector with live status, removed run metadata from timeline rows, and moved filters behind Enter on each tab. Filter parameters now open a second value submenu to the right while preserving the parent menu and one-level Escape navigation. Impact: run context stays explicit, the permanent filter row disappears, and Messages/Turns gain compact graphical two-level settings menus.
20
+ - `[Inspector Selection Markers]` Use stable blue brackets for selected Run/tab controls and reserve `▶` for focused menus, values, and timeline rows. Added a direct regression that verifies even timeline rows stay on the dark overlay surface while odd rows receive the neutral stripe background. Impact: selection and focus remain distinct without layout shifts or color-only meaning.
21
+ - `[Inspector List Navigation]` Restored stable even/odd striping by absolute timeline position, made Enter/→ open row detail, and made Escape/← return to the list, with contextual footer hints. Impact: row grouping remains visually stable while scrolling and horizontal navigation follows the same forward/back model as nested menus.
22
+ - `[Inspector Visual Contract]` Stabilized the dogfooded interaction model around top-bounded tabs, availability-aware filter/list navigation, blue current values, neutral focus backgrounds, key-colored footer hints, and filter-anchored nested option overlays that preserve underlying separator and timeline cells outside their rectangle. Impact: the TUI now behaves like a compact graphical tab/filter/select surface instead of a command panel.
23
+ - `[Inspector Naming]` Renamed the `Communications` tab to `Messages`. Impact: the tab now describes its concrete contents with a shorter label that balances visually with `Turns`.
24
+ - `[Inspector Filter UI]` Removed the permanent filter bar in favor of compact tab-anchored parameter/value menus that show current values, preserve the striped timeline beneath unused cells, and expose active non-default filters in the tab label. Impact: filtering stays visible and keyboard-driven without consuming a permanent content row.
25
+ - `[Inspector Turns UI]` Moved turn browsing and detail into the overlay with scrolling viewports, all/single-subagent scope, compact model/tool-count rows, and Enter-opened bounded provenance, prompt/context, user/assistant, persisted-thinking, usage/error, tool argument/result, truncation, and diagnostic evidence. Impact: operators can follow one subagent's complete persisted execution path without commands or leaving the overlay.
26
+ - `[Inspector Messages UI]` Moved message browsing into the overlay with compact striped routes/types/body previews, attention markers, unread/channel/sender filters, roster-derived From options, and bounded detail. Impact: actor communication investigation stays keyboard-driven and discoverable without consuming a row for unread dots or command grammar.
27
+ - `[Inspector Focus Navigation]` Added explicit Run/Tabs/Menu/List/Detail focus zones with availability-aware boundaries, blue selected values, brackets for top-level selection, triangles for focused rows, and contextual key hints. Impact: navigation always has one visible owner and moving focus never mutates filter state.
28
+ - `[Inspector Overlay Integrity]` Normalized persisted tabs and line breaks before every component row is handed to the overlay compositor. Impact: multiline actor messages, prompts, and turn text can no longer escape their assigned row and corrupt the underlying terminal layout during tab navigation.
29
+ - `[Inspector Overlay]` Replaced inspector subcommand handling with `/actors-inspector-toggle`, which opens a centered responsive overlay featuring Run selection, Messages/Turns tabs, nested filters, compact alternating rows, live refresh, distinct empty states, bounded detail, footer key hints, and Escape close. Removed the superseded command controller and below-editor widget lifecycle. Impact: operators can browse execution evidence without memorizing command grammar, and runtime state now has one authoritative UI path.
30
+ - `[Inspector Security]` Reset inspector selection/read state at every Pi session start, revalidate selected-run ownership before turn or roster reads, reject absolute/traversing/symlinked session evidence outside the owned run, and broaden structured/text plus communication-body redaction for common camelCase/private-key credentials. Impact: the upcoming overlay cannot inherit another session's selected evidence or escape its run boundary through mutable manifests.
31
+ - `[Coordinator Turn Provenance]` Replaced coordinator-managed room/swarm subagents' `--no-session` launches with isolated role/phase session directories under the owned run and made the inspector discover those JSONL files alongside command evidence. Impact: manual turn navigation covers coordinator-spawned participants and synthesis actors, not only direct recipe `pi -p` leaves.
32
+ - `[Inspector Turn Detail]` Added bounded manual turn detail for command/stage identity, session and prompt provenance, recipe context, user/assistant text, persisted thinking, stop reason, usage, errors, correlated tool arguments/results, unmatched results, truncation, and parse diagnostics. Impact: operators can inspect what each subagent actually received, produced, and called while missing reasoning stays explicitly unavailable and secret-bearing values remain redacted.
33
+ - `[Turn Evidence]` Added a resilient bounded reader for persisted child Pi sessions that follows the latest JSONL entry branch, groups assistant responses with correlated tool calls/results, retains model/usage/error and host-visible thinking metadata, redacts common secret-bearing fields/text, and diagnoses malformed or incomplete evidence. Impact: inspector navigation can consume one tested turn model instead of parsing raw session files or implying access to unavailable reasoning.
34
+ - `[Execution Observability]` Give every child `pi -p` command an isolated session directory under its owned run state unless the recipe already supplies explicit session policy, and record any resulting JSONL files in command events and review evidence. Impact: the inspector can attribute future turn/tool timelines to exact subagent commands without guessing from global session directories, while `--no-session`, resume, fork, and caller-owned session storage remain authoritative.
35
+ - `[Tool Output]` Separate every pi-actors tool result and thrown error from its rendered tool-call header with one blank line, including core `spawn`, `message`, `inspect`, `register_tool`, and recipe-backed tools. Impact: successful and failed calls remain visually scannable instead of running into the header.
36
+
5
37
  ## 0.40.1: Follow-up Delivery Hotfix
6
38
 
7
39
  - `[Coordinator Delivery]` Queue terminal and coordinator-bound actor notifications through Pi's `followUp` delivery mode instead of `steer`, while retaining `triggerTurn: true` for idle sessions. Impact: active coordinators finish their current work before actor results arrive, and Pi can apply its configured follow-up batching policy to concurrently completed runs instead of injecting each result between tool calls.
package/README.md CHANGED
@@ -131,7 +131,7 @@ Routing comes from `to`, actor ownership, and runtime policy. `type` describes i
131
131
  | Registry and recipe doctor | Discovered tools, overrides, drafts, invalid recipes, and advisory risk labels | Audit local capability memory before using or promoting it |
132
132
  | Draft promotion | Captured ad hoc spawn patterns can become explicit recipes after operator approval | Turn successful improvisation into durable local tools |
133
133
  | Review/swarm recipes | Maintained packaged pipelines with preflight, marked semantic evidence, quorum knobs, model/thinking inheritance, one-turn prompt-file transport, and diagnostics | Delegate reviews without rebuilding fanout commands |
134
- | Actor inspector | Compact TUI/debug views for active actor coordination, unread branch inboxes, room messages, and attention markers | Watch only the actor traffic that matters right now |
134
+ | Actor inspector | One manual `Messages or Turns → filtered timeline → detail` overlay for owned actor messages and persisted subagent sessions, with bounded/redacted prompt, model, thinking, tool, result, usage, and provenance evidence | Follow actor traffic and every persisted subagent turn without exposing another session or inventing hidden reasoning |
135
135
  | Packaged recipe QA | Installed-package-safe checks for helper paths, mailbox contracts, platform scope, artifacts, and recipe structure | Keep shipped actor components executable and diagnosable |
136
136
 
137
137
  ## Golden path: from local workflow to actor memory
@@ -340,6 +340,7 @@ Core docs:
340
340
  - [Template recipes](./docs/template-recipes.md)
341
341
  - [Async runs](./docs/async-runs.md)
342
342
  - [Actor messages](./docs/actor-messages.md)
343
+ - [Actor inspector](./docs/actor-inspector.md)
343
344
  - [Tool registry](./docs/tool-registry.md)
344
345
  - [Recipe library](./docs/recipe-library.md)
345
346
 
package/dist/index.js CHANGED
@@ -6,7 +6,7 @@
6
6
  */
7
7
  import * as AsyncRuns from "./lib/async-runs.js";
8
8
  import * as CommandTemplates from "./lib/command-templates.js";
9
- import * as Inspector from "./lib/inspector.js";
9
+ import * as InspectorOverlay from "./lib/inspector-overlay.js";
10
10
  import * as Observability from "./lib/observability.js";
11
11
  import * as Paths from "./lib/paths.js";
12
12
  import * as Pi from "./lib/pi.js";
@@ -14,13 +14,15 @@ import * as Prompts from "./lib/prompts.js";
14
14
  import * as Runtime from "./lib/runtime.js";
15
15
  import * as Temp from "./lib/temp.js";
16
16
  import * as Tools from "./lib/tools.js";
17
+ import * as ToolsResponse from "./lib/tools-response.js";
17
18
  export default function toolRegistryExtension(pi) {
18
19
  let runsAnimationInterval;
19
20
  let runsNotifyTimeout;
20
21
  let activeRunContext;
22
+ let lastRunWatcherDiagnosticId = 0;
21
23
  const runUi = Observability.createRunUiObservationState();
22
24
  const retirementAttempts = new Set();
23
- const actorInspector = Inspector.createActorInspectorControllerState();
25
+ const terminalNotificationsInFlight = new Set();
24
26
  const getRunOwnerId = Pi.getSessionId;
25
27
  const retireCandidateRuns = (ctx, summary) => {
26
28
  void Observability.executeRunRetirements(summary, {
@@ -34,33 +36,11 @@ export default function toolRegistryExtension(pi) {
34
36
  const ownerId = getRunOwnerId(ctx);
35
37
  const snapshot = Observability.readRunUiSnapshot(runUi, ownerId);
36
38
  ctx.ui.setStatus("zz-pi-actors-runs", snapshot.status ? ctx.ui.theme.fg("dim", snapshot.status) : undefined);
37
- ctx.ui.setWidget("zz-pi-actors-comms", actorInspector.visible
38
- ? () => ({
39
- invalidate() { },
40
- render(width) {
41
- return Inspector.renderActorInspectorPanel({
42
- stateRoot: Paths.EXTENSION_RUNTIME_PATHS.runStateRoot,
43
- state: actorInspector,
44
- ownerId,
45
- width,
46
- style: {
47
- actor: (text) => ctx.ui.theme.fg("accent", text),
48
- muted: (text) => ctx.ui.theme.fg("dim", text),
49
- preview: (text) => ctx.ui.theme.fg("text", text),
50
- stripe: (text) => text,
51
- stripeAlt: (text) => ctx.ui.theme.bg("customMessageBg", text),
52
- target: (text) => ctx.ui.theme.fg("success", text),
53
- type: (text) => ctx.ui.theme.fg("warning", text),
54
- },
55
- });
56
- },
57
- })
58
- : undefined, { placement: "belowEditor" });
59
39
  if (!notify)
60
40
  return;
61
41
  const notificationSink = Pi.createNotificationSink(pi, ctx);
62
42
  retireCandidateRuns(ctx, snapshot.summary);
63
- Observability.deliverRunTransitionNotifications(snapshot.transitions, notificationSink);
43
+ Observability.deliverRunTransitionNotifications(snapshot.transitions, notificationSink, terminalNotificationsInFlight);
64
44
  Observability.pruneRunUiObservationState(runUi, snapshot);
65
45
  if (!terminalOnly) {
66
46
  Observability.deliverRunOutboxNotifications(snapshot.outboxEvents, notificationSink);
@@ -68,22 +48,57 @@ export default function toolRegistryExtension(pi) {
68
48
  };
69
49
  const closeRunWatchers = () => {
70
50
  runWatcher.close();
51
+ terminalReconciliation.close();
71
52
  if (runsNotifyTimeout)
72
53
  clearTimeout(runsNotifyTimeout);
73
54
  runsNotifyTimeout = undefined;
74
55
  };
75
- 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 = () => {
76
65
  if (runsNotifyTimeout)
77
66
  clearTimeout(runsNotifyTimeout);
78
67
  runsNotifyTimeout = setTimeout(() => {
68
+ const ctx = activeRunContext;
69
+ if (!ctx)
70
+ return;
79
71
  runWatcher.refresh();
80
72
  updateRunUi(ctx, true);
73
+ reportRunWatcherDiagnostics(ctx);
81
74
  }, 50);
82
75
  runsNotifyTimeout.unref?.();
83
76
  };
84
77
  const runWatcher = Observability.createRunStateWatcher({
85
78
  stateRoot: Paths.EXTENSION_RUNTIME_PATHS.runStateRoot,
86
- 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(),
87
102
  });
88
103
  const actorToolDefinitions = new Map();
89
104
  const withCurrentThinkingContext = (definition) => {
@@ -92,7 +107,7 @@ export default function toolRegistryExtension(pi) {
92
107
  const execute = definition.execute;
93
108
  return {
94
109
  ...definition,
95
- execute: (...args) => {
110
+ execute: async (...args) => {
96
111
  const nextArgs = [...args];
97
112
  const ctx = nextArgs[4];
98
113
  if (ctx && typeof ctx === "object") {
@@ -101,7 +116,12 @@ export default function toolRegistryExtension(pi) {
101
116
  getThinkingLevel: () => pi.getThinkingLevel(),
102
117
  };
103
118
  }
104
- return execute(...nextArgs);
119
+ try {
120
+ return ToolsResponse.spaceToolResult(await execute(...nextArgs));
121
+ }
122
+ catch (error) {
123
+ throw ToolsResponse.spaceToolError(error);
124
+ }
105
125
  },
106
126
  };
107
127
  };
@@ -125,17 +145,25 @@ export default function toolRegistryExtension(pi) {
125
145
  return { skillPaths };
126
146
  });
127
147
  pi.on("session_start", async (_event, ctx) => {
148
+ // Clear the pre-overlay widget after hot reloads from older pi-actors builds.
149
+ ctx.ui.setWidget("zz-pi-actors-comms", undefined);
128
150
  activeRunContext = ctx;
151
+ closeRunWatchers();
152
+ recipeReload.close();
129
153
  await Temp.prepareExtensionTempDir(Paths.EXTENSION_RUNTIME_PATHS.tempDir);
154
+ if (activeRunContext !== ctx)
155
+ return;
130
156
  runtime.loadTools(ctx);
131
157
  updateRunUi(ctx, true, true);
132
- closeRunWatchers();
133
- recipeReload.close();
134
158
  runWatcher.refresh();
159
+ terminalReconciliation.start();
135
160
  recipeReload.watch(ctx);
136
161
  if (runsAnimationInterval)
137
162
  clearInterval(runsAnimationInterval);
138
- runsAnimationInterval = setInterval(() => updateRunUi(ctx, false), 1000);
163
+ runsAnimationInterval = setInterval(() => {
164
+ if (activeRunContext === ctx)
165
+ updateRunUi(ctx, false);
166
+ }, 1000);
139
167
  runsAnimationInterval.unref?.();
140
168
  });
141
169
  pi.on("session_shutdown", async () => {
@@ -146,32 +174,26 @@ export default function toolRegistryExtension(pi) {
146
174
  closeRunWatchers();
147
175
  recipeReload.close();
148
176
  });
149
- pi.registerCommand("actors-inspector-toggle", {
150
- description: Inspector.ACTOR_INSPECTOR_COMMAND_DESCRIPTIONS.toggle,
151
- handler: async (args, ctx) => {
152
- const result = Inspector.handleActorInspectorToggle(actorInspector, args);
153
- if (result.update)
154
- updateRunUi(ctx);
155
- ctx.ui.notify(result.notify, result.type);
156
- },
157
- });
158
- pi.registerCommand("actors-inspector-filter", {
159
- description: Inspector.ACTOR_INSPECTOR_COMMAND_DESCRIPTIONS.filter,
160
- handler: async (args, ctx) => {
161
- const result = Inspector.handleActorInspectorFilter(actorInspector, args);
162
- if (result.update)
163
- updateRunUi(ctx);
164
- ctx.ui.notify(result.notify, result.type);
165
- },
166
- });
167
- pi.registerCommand("actors-inspect", {
168
- description: Inspector.ACTOR_INSPECTOR_COMMAND_DESCRIPTIONS.inspect,
169
- handler: async (args, ctx) => {
170
- const previews = Inspector.readActorInspectorPreviews(Paths.EXTENSION_RUNTIME_PATHS.runStateRoot, actorInspector.rows, Inspector.getActorInspectorPreviewOptions(actorInspector, getRunOwnerId(ctx)));
171
- const result = Inspector.handleActorInspectorInspect(actorInspector, args, previews);
172
- if (result.update)
173
- updateRunUi(ctx);
174
- ctx.ui.notify(result.notify, result.type);
177
+ pi.registerCommand("actors-inspector", {
178
+ description: "Open the keyboard-driven actor inspector overlay",
179
+ handler: async (_args, ctx) => {
180
+ ctx.ui.setWidget("zz-pi-actors-comms", undefined);
181
+ await ctx.ui.custom((tui, theme, _keybindings, done) => new InspectorOverlay.ActorInspectorOverlay({
182
+ done,
183
+ ownerId: getRunOwnerId(ctx),
184
+ stateRoot: Paths.EXTENSION_RUNTIME_PATHS.runStateRoot,
185
+ theme,
186
+ tui,
187
+ }), {
188
+ overlay: true,
189
+ overlayOptions: {
190
+ anchor: "center",
191
+ width: "94%",
192
+ minWidth: 72,
193
+ maxHeight: "94%",
194
+ margin: 1,
195
+ },
196
+ });
175
197
  },
176
198
  });
177
199
  pi.on("before_agent_start", async (event) => ({
@@ -0,0 +1,95 @@
1
+ /**
2
+ * Keyboard-driven actor inspector overlay.
3
+ * Zones: overlay shell, tabs, owned-run/subagent selection, compact striped rows
4
+ * Owns interactive TUI navigation; evidence parsing remains in inspector/session domains.
5
+ */
6
+ import type { Theme } from "@earendil-works/pi-coding-agent";
7
+ import { type TUI } from "@earendil-works/pi-tui";
8
+ export type ActorInspectorOverlayTab = "communications" | "turns";
9
+ export interface ActorInspectorOverlayOptions {
10
+ done: () => void;
11
+ ownerId: string;
12
+ stateRoot: string;
13
+ theme: Theme;
14
+ tui: TUI;
15
+ }
16
+ export declare class ActorInspectorOverlay {
17
+ private readonly done;
18
+ private readonly ownerId;
19
+ private readonly stateRoot;
20
+ private readonly theme;
21
+ private readonly tui;
22
+ private readonly refreshTimer;
23
+ private runIndex;
24
+ private communicationChannel;
25
+ private communicationFrom;
26
+ private communicationUnread;
27
+ private contentStripeIndices;
28
+ private detailCommunication?;
29
+ private detailOpen;
30
+ private detailScroll;
31
+ private detailTurn?;
32
+ private detailView;
33
+ private readonly readKeys;
34
+ private focus;
35
+ private filterControlIndex;
36
+ private menuLevel;
37
+ private selectorIndex;
38
+ private rowIndex;
39
+ private selectedRun?;
40
+ private subagentIndex;
41
+ private tab;
42
+ constructor(options: ActorInspectorOverlayOptions);
43
+ handleInput(data: string): void;
44
+ render(width: number): string[];
45
+ invalidate(): void;
46
+ dispose(): void;
47
+ private runs;
48
+ private ensureSelectedRun;
49
+ private contentViewportRows;
50
+ private selectRun;
51
+ private cycleRun;
52
+ private listItemCount;
53
+ private selectorAnchor;
54
+ private renderKeyHints;
55
+ private renderRunControl;
56
+ private activeMessageFilters;
57
+ private renderTabs;
58
+ private renderRunSelector;
59
+ private renderTimeline;
60
+ private communicationPreviews;
61
+ private communicationActorLabel;
62
+ private communicationFromOptions;
63
+ private communicationRows;
64
+ private renderDetail;
65
+ private wrapDetailLines;
66
+ private detailSection;
67
+ private readableValueLines;
68
+ private turnEvidenceLines;
69
+ private readablePromptText;
70
+ private turnTranscriptLines;
71
+ private turnItems;
72
+ private turnRows;
73
+ private subagents;
74
+ private valueOptions;
75
+ private filterOptions;
76
+ private menuOptions;
77
+ private backMenu;
78
+ private openRunMenu;
79
+ private openFilterMenu;
80
+ private applyMenuOption;
81
+ private filterValue;
82
+ private currentFilterValue;
83
+ private renderMenuBox;
84
+ private renderFilterMenus;
85
+ private openDetail;
86
+ private backDetail;
87
+ private closeDetail;
88
+ private border;
89
+ private stripeBackground;
90
+ private stripedRow;
91
+ private row;
92
+ private takeVisiblePrefix;
93
+ private dropVisiblePrefix;
94
+ private fit;
95
+ }