@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 +3 -3
- package/CHANGELOG.md +32 -0
- package/README.md +2 -1
- package/dist/index.js +80 -58
- package/dist/lib/inspector-overlay.d.ts +95 -0
- package/dist/lib/inspector-overlay.js +873 -0
- package/dist/lib/inspector.d.ts +17 -33
- package/dist/lib/inspector.js +101 -151
- package/dist/lib/limits.d.ts +3 -0
- package/dist/lib/limits.js +3 -0
- package/dist/lib/observability.d.ts +38 -3
- package/dist/lib/observability.js +151 -33
- package/dist/lib/recipes-context.d.ts +5 -0
- package/dist/lib/recipes-context.js +15 -0
- package/dist/lib/session-evidence.d.ts +45 -0
- package/dist/lib/session-evidence.js +204 -0
- package/dist/lib/tools-response.d.ts +3 -0
- package/dist/lib/tools-response.js +29 -0
- package/dist/scripts/async-runner.mjs +40 -5
- package/dist/scripts/coordinator.mjs +55 -9
- package/dist/skills/actors/SKILL.md +5 -11
- package/dist/skills/swarm/SKILL.md +1 -1
- package/docs/README.md +1 -0
- package/docs/actor-inspector.md +77 -0
- package/docs/async-runs.md +1 -1
- package/index.ts +80 -70
- package/lib/inspector-overlay.ts +1071 -0
- package/lib/inspector.ts +135 -204
- package/lib/limits.ts +3 -0
- package/lib/observability.ts +205 -39
- package/lib/recipes-context.ts +25 -0
- package/lib/session-evidence.ts +302 -0
- package/lib/tools-response.ts +32 -0
- package/package.json +1 -1
- package/scripts/async-runner.mjs +40 -5
- package/scripts/coordinator.mjs +55 -9
- package/skills/actors/SKILL.md +5 -11
- package/skills/swarm/SKILL.md +1 -1
package/index.ts
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
|
|
8
8
|
import * as AsyncRuns from "./lib/async-runs.ts";
|
|
9
9
|
import * as CommandTemplates from "./lib/command-templates.ts";
|
|
10
|
-
import * as
|
|
10
|
+
import * as InspectorOverlay from "./lib/inspector-overlay.ts";
|
|
11
11
|
import * as Observability from "./lib/observability.ts";
|
|
12
12
|
import * as Paths from "./lib/paths.ts";
|
|
13
13
|
import * as Pi from "./lib/pi.ts";
|
|
@@ -15,14 +15,16 @@ import * as Prompts from "./lib/prompts.ts";
|
|
|
15
15
|
import * as Runtime from "./lib/runtime.ts";
|
|
16
16
|
import * as Temp from "./lib/temp.ts";
|
|
17
17
|
import * as Tools from "./lib/tools.ts";
|
|
18
|
+
import * as ToolsResponse from "./lib/tools-response.ts";
|
|
18
19
|
|
|
19
20
|
export default function toolRegistryExtension(pi: Pi.ExtensionAPI) {
|
|
20
21
|
let runsAnimationInterval: NodeJS.Timeout | undefined;
|
|
21
22
|
let runsNotifyTimeout: NodeJS.Timeout | undefined;
|
|
22
23
|
let activeRunContext: Pi.ExtensionContext | undefined;
|
|
24
|
+
let lastRunWatcherDiagnosticId = 0;
|
|
23
25
|
const runUi = Observability.createRunUiObservationState();
|
|
24
26
|
const retirementAttempts = new Set<string>();
|
|
25
|
-
const
|
|
27
|
+
const terminalNotificationsInFlight = new Set<string>();
|
|
26
28
|
const getRunOwnerId = Pi.getSessionId;
|
|
27
29
|
const retireCandidateRuns = (
|
|
28
30
|
ctx: Pi.ExtensionContext,
|
|
@@ -47,39 +49,13 @@ export default function toolRegistryExtension(pi: Pi.ExtensionAPI) {
|
|
|
47
49
|
"zz-pi-actors-runs",
|
|
48
50
|
snapshot.status ? ctx.ui.theme.fg("dim", snapshot.status) : undefined,
|
|
49
51
|
);
|
|
50
|
-
ctx.ui.setWidget(
|
|
51
|
-
"zz-pi-actors-comms",
|
|
52
|
-
actorInspector.visible
|
|
53
|
-
? () => ({
|
|
54
|
-
invalidate() {},
|
|
55
|
-
render(width: number) {
|
|
56
|
-
return Inspector.renderActorInspectorPanel({
|
|
57
|
-
stateRoot: Paths.EXTENSION_RUNTIME_PATHS.runStateRoot,
|
|
58
|
-
state: actorInspector,
|
|
59
|
-
ownerId,
|
|
60
|
-
width,
|
|
61
|
-
style: {
|
|
62
|
-
actor: (text: string) => ctx.ui.theme.fg("accent", text),
|
|
63
|
-
muted: (text: string) => ctx.ui.theme.fg("dim", text),
|
|
64
|
-
preview: (text: string) => ctx.ui.theme.fg("text", text),
|
|
65
|
-
stripe: (text: string) => text,
|
|
66
|
-
stripeAlt: (text: string) =>
|
|
67
|
-
ctx.ui.theme.bg("customMessageBg", text),
|
|
68
|
-
target: (text: string) => ctx.ui.theme.fg("success", text),
|
|
69
|
-
type: (text: string) => ctx.ui.theme.fg("warning", text),
|
|
70
|
-
},
|
|
71
|
-
});
|
|
72
|
-
},
|
|
73
|
-
})
|
|
74
|
-
: undefined,
|
|
75
|
-
{ placement: "belowEditor" },
|
|
76
|
-
);
|
|
77
52
|
if (!notify) return;
|
|
78
53
|
const notificationSink = Pi.createNotificationSink(pi, ctx);
|
|
79
54
|
retireCandidateRuns(ctx, snapshot.summary);
|
|
80
55
|
Observability.deliverRunTransitionNotifications(
|
|
81
56
|
snapshot.transitions,
|
|
82
57
|
notificationSink,
|
|
58
|
+
terminalNotificationsInFlight,
|
|
83
59
|
);
|
|
84
60
|
Observability.pruneRunUiObservationState(runUi, snapshot);
|
|
85
61
|
if (!terminalOnly) {
|
|
@@ -91,22 +67,56 @@ export default function toolRegistryExtension(pi: Pi.ExtensionAPI) {
|
|
|
91
67
|
};
|
|
92
68
|
const closeRunWatchers = (): void => {
|
|
93
69
|
runWatcher.close();
|
|
70
|
+
terminalReconciliation.close();
|
|
94
71
|
if (runsNotifyTimeout) clearTimeout(runsNotifyTimeout);
|
|
95
72
|
runsNotifyTimeout = undefined;
|
|
96
73
|
};
|
|
97
|
-
const
|
|
74
|
+
const reportRunWatcherDiagnostics = (ctx: Pi.ExtensionContext): void => {
|
|
75
|
+
for (const diagnostic of runWatcher.getDiagnostics()) {
|
|
76
|
+
if (diagnostic.id <= lastRunWatcherDiagnosticId) continue;
|
|
77
|
+
lastRunWatcherDiagnosticId = diagnostic.id;
|
|
78
|
+
ctx.ui.notify(
|
|
79
|
+
diagnostic.message,
|
|
80
|
+
diagnostic.code === "rearmed" ? "info" : "warning",
|
|
81
|
+
);
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
const scheduleRunEventUpdate = (): void => {
|
|
98
85
|
if (runsNotifyTimeout) clearTimeout(runsNotifyTimeout);
|
|
99
86
|
runsNotifyTimeout = setTimeout(() => {
|
|
87
|
+
const ctx = activeRunContext;
|
|
88
|
+
if (!ctx) return;
|
|
100
89
|
runWatcher.refresh();
|
|
101
90
|
updateRunUi(ctx, true);
|
|
91
|
+
reportRunWatcherDiagnostics(ctx);
|
|
102
92
|
}, 50);
|
|
103
93
|
runsNotifyTimeout.unref?.();
|
|
104
94
|
};
|
|
105
95
|
const runWatcher = Observability.createRunStateWatcher({
|
|
106
96
|
stateRoot: Paths.EXTENSION_RUNTIME_PATHS.runStateRoot,
|
|
107
|
-
onChange:
|
|
108
|
-
activeRunContext && scheduleRunEventUpdate(activeRunContext),
|
|
97
|
+
onChange: scheduleRunEventUpdate,
|
|
109
98
|
});
|
|
99
|
+
const terminalReconciliation =
|
|
100
|
+
Observability.createRunTerminalReconciliationLoop({
|
|
101
|
+
onError: (error) => {
|
|
102
|
+
const ctx = activeRunContext;
|
|
103
|
+
if (!ctx) return;
|
|
104
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
105
|
+
ctx.ui.notify(`Actor terminal reconciliation failed: ${message}`, "error");
|
|
106
|
+
},
|
|
107
|
+
reconcile: () => {
|
|
108
|
+
const ctx = activeRunContext;
|
|
109
|
+
if (!ctx) return;
|
|
110
|
+
Observability.reconcileRunTerminalNotifications({
|
|
111
|
+
inFlight: terminalNotificationsInFlight,
|
|
112
|
+
ownerId: getRunOwnerId(ctx),
|
|
113
|
+
sink: Pi.createNotificationSink(pi, ctx),
|
|
114
|
+
state: runUi,
|
|
115
|
+
});
|
|
116
|
+
reportRunWatcherDiagnostics(ctx);
|
|
117
|
+
},
|
|
118
|
+
refreshWatcher: () => runWatcher.refresh(),
|
|
119
|
+
});
|
|
110
120
|
const actorToolDefinitions = new Map<string, Tools.ActorToolDefinition>();
|
|
111
121
|
const withCurrentThinkingContext = <T extends Tools.ActorToolDefinition>(
|
|
112
122
|
definition: T,
|
|
@@ -115,7 +125,7 @@ export default function toolRegistryExtension(pi: Pi.ExtensionAPI) {
|
|
|
115
125
|
const execute = definition.execute as (...args: unknown[]) => unknown;
|
|
116
126
|
return {
|
|
117
127
|
...definition,
|
|
118
|
-
execute: (...args: unknown[]) => {
|
|
128
|
+
execute: async (...args: unknown[]) => {
|
|
119
129
|
const nextArgs = [...args];
|
|
120
130
|
const ctx = nextArgs[4];
|
|
121
131
|
if (ctx && typeof ctx === "object") {
|
|
@@ -124,7 +134,11 @@ export default function toolRegistryExtension(pi: Pi.ExtensionAPI) {
|
|
|
124
134
|
getThinkingLevel: () => pi.getThinkingLevel(),
|
|
125
135
|
};
|
|
126
136
|
}
|
|
127
|
-
|
|
137
|
+
try {
|
|
138
|
+
return ToolsResponse.spaceToolResult(await execute(...nextArgs));
|
|
139
|
+
} catch (error) {
|
|
140
|
+
throw ToolsResponse.spaceToolError(error);
|
|
141
|
+
}
|
|
128
142
|
},
|
|
129
143
|
} as T;
|
|
130
144
|
};
|
|
@@ -147,16 +161,22 @@ export default function toolRegistryExtension(pi: Pi.ExtensionAPI) {
|
|
|
147
161
|
return { skillPaths };
|
|
148
162
|
});
|
|
149
163
|
pi.on("session_start", async (_event, ctx) => {
|
|
164
|
+
// Clear the pre-overlay widget after hot reloads from older pi-actors builds.
|
|
165
|
+
ctx.ui.setWidget("zz-pi-actors-comms", undefined);
|
|
150
166
|
activeRunContext = ctx;
|
|
167
|
+
closeRunWatchers();
|
|
168
|
+
recipeReload.close();
|
|
151
169
|
await Temp.prepareExtensionTempDir(Paths.EXTENSION_RUNTIME_PATHS.tempDir);
|
|
170
|
+
if (activeRunContext !== ctx) return;
|
|
152
171
|
runtime.loadTools(ctx);
|
|
153
172
|
updateRunUi(ctx, true, true);
|
|
154
|
-
closeRunWatchers();
|
|
155
|
-
recipeReload.close();
|
|
156
173
|
runWatcher.refresh();
|
|
174
|
+
terminalReconciliation.start();
|
|
157
175
|
recipeReload.watch(ctx);
|
|
158
176
|
if (runsAnimationInterval) clearInterval(runsAnimationInterval);
|
|
159
|
-
runsAnimationInterval = setInterval(() =>
|
|
177
|
+
runsAnimationInterval = setInterval(() => {
|
|
178
|
+
if (activeRunContext === ctx) updateRunUi(ctx, false);
|
|
179
|
+
}, 1000);
|
|
160
180
|
runsAnimationInterval.unref?.();
|
|
161
181
|
});
|
|
162
182
|
pi.on("session_shutdown", async () => {
|
|
@@ -166,40 +186,30 @@ export default function toolRegistryExtension(pi: Pi.ExtensionAPI) {
|
|
|
166
186
|
closeRunWatchers();
|
|
167
187
|
recipeReload.close();
|
|
168
188
|
});
|
|
169
|
-
pi.registerCommand("actors-inspector
|
|
170
|
-
description:
|
|
171
|
-
handler: async (
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
actorInspector,
|
|
193
|
-
getRunOwnerId(ctx),
|
|
194
|
-
),
|
|
195
|
-
);
|
|
196
|
-
const result = Inspector.handleActorInspectorInspect(
|
|
197
|
-
actorInspector,
|
|
198
|
-
args,
|
|
199
|
-
previews,
|
|
189
|
+
pi.registerCommand("actors-inspector", {
|
|
190
|
+
description: "Open the keyboard-driven actor inspector overlay",
|
|
191
|
+
handler: async (_args, ctx) => {
|
|
192
|
+
ctx.ui.setWidget("zz-pi-actors-comms", undefined);
|
|
193
|
+
await ctx.ui.custom<void>(
|
|
194
|
+
(tui, theme, _keybindings, done) =>
|
|
195
|
+
new InspectorOverlay.ActorInspectorOverlay({
|
|
196
|
+
done,
|
|
197
|
+
ownerId: getRunOwnerId(ctx),
|
|
198
|
+
stateRoot: Paths.EXTENSION_RUNTIME_PATHS.runStateRoot,
|
|
199
|
+
theme,
|
|
200
|
+
tui,
|
|
201
|
+
}),
|
|
202
|
+
{
|
|
203
|
+
overlay: true,
|
|
204
|
+
overlayOptions: {
|
|
205
|
+
anchor: "center",
|
|
206
|
+
width: "94%",
|
|
207
|
+
minWidth: 72,
|
|
208
|
+
maxHeight: "94%",
|
|
209
|
+
margin: 1,
|
|
210
|
+
},
|
|
211
|
+
},
|
|
200
212
|
);
|
|
201
|
-
if (result.update) updateRunUi(ctx);
|
|
202
|
-
ctx.ui.notify(result.notify, result.type);
|
|
203
213
|
},
|
|
204
214
|
});
|
|
205
215
|
pi.on("before_agent_start", async (event) => ({
|