@llblab/pi-actors 0.29.2 → 0.30.0
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 +16 -1
- package/BACKLOG.md +89 -206
- package/CHANGELOG.md +9 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.js +71 -315
- package/dist/lib/actor-inspector-tui.d.ts +35 -0
- package/dist/lib/actor-inspector-tui.js +159 -1
- package/dist/lib/observability.d.ts +34 -0
- package/dist/lib/observability.js +103 -1
- package/dist/lib/paths.d.ts +9 -0
- package/dist/lib/paths.js +15 -0
- package/dist/lib/pi.d.ts +19 -0
- package/dist/lib/pi.js +21 -0
- package/dist/lib/runtime.d.ts +5 -0
- package/dist/lib/runtime.js +48 -0
- package/dist/lib/tools.d.ts +9 -0
- package/dist/lib/tools.js +58 -8
- package/dist/skills/actors/SKILL.md +10 -116
- package/dist/skills/swarm/SKILL.md +20 -1
- package/docs/README.md +1 -0
- package/docs/actors-deep-reference.md +66 -0
- package/index.ts +99 -379
- package/lib/actor-inspector-tui.ts +221 -1
- package/lib/observability.ts +194 -34
- package/lib/paths.ts +27 -0
- package/lib/pi.ts +47 -0
- package/lib/runtime.ts +55 -0
- package/lib/tools.ts +119 -24
- package/package.json +1 -1
- package/skills/actors/SKILL.md +10 -116
- package/skills/swarm/SKILL.md +20 -1
package/index.ts
CHANGED
|
@@ -5,294 +5,106 @@
|
|
|
5
5
|
* Wraps command templates as callable pi tools, stores durable user tools as recipe files, and exposes actor orchestration across reloads and sessions.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
import { existsSync, readdirSync, watch, type FSWatcher } from "node:fs";
|
|
9
|
-
import { dirname, join } from "node:path";
|
|
10
|
-
import { fileURLToPath } from "node:url";
|
|
11
|
-
|
|
12
|
-
import type {
|
|
13
|
-
ExtensionAPI,
|
|
14
|
-
ExtensionContext,
|
|
15
|
-
} from "@earendil-works/pi-coding-agent";
|
|
16
|
-
|
|
17
8
|
import * as ActorInspectorTui from "./lib/actor-inspector-tui.ts";
|
|
18
9
|
import * as AsyncRuns from "./lib/async-runs.ts";
|
|
19
10
|
import * as CommandTemplates from "./lib/command-templates.ts";
|
|
20
11
|
import * as Observability from "./lib/observability.ts";
|
|
21
12
|
import * as Paths from "./lib/paths.ts";
|
|
13
|
+
import * as Pi from "./lib/pi.ts";
|
|
22
14
|
import * as Prompts from "./lib/prompts.ts";
|
|
23
15
|
import * as Runtime from "./lib/runtime.ts";
|
|
24
16
|
import * as Temp from "./lib/temp.ts";
|
|
25
17
|
import * as Tools from "./lib/tools.ts";
|
|
26
18
|
|
|
27
|
-
|
|
28
|
-
const EXTENSION_SKILLS_DIR = join(EXTENSION_DIR, "skills");
|
|
29
|
-
const CONFIG_PATH = Paths.getConfigPath();
|
|
30
|
-
const TEMP_DIR = Paths.getExtensionTmpDir();
|
|
31
|
-
const RUN_STATE_ROOT = Paths.getRunStateRoot();
|
|
32
|
-
const RESERVED_TOOL_NAMES = new Set([
|
|
33
|
-
"read",
|
|
34
|
-
"write",
|
|
35
|
-
"edit",
|
|
36
|
-
"bash",
|
|
37
|
-
"find",
|
|
38
|
-
"grep",
|
|
39
|
-
"ls",
|
|
40
|
-
"register_tool",
|
|
41
|
-
"message",
|
|
42
|
-
"spawn",
|
|
43
|
-
"inspect",
|
|
44
|
-
]);
|
|
45
|
-
|
|
46
|
-
export default function toolRegistryExtension(pi: ExtensionAPI) {
|
|
19
|
+
export default function toolRegistryExtension(pi: Pi.ExtensionAPI) {
|
|
47
20
|
let runsAnimationInterval: NodeJS.Timeout | undefined;
|
|
48
21
|
let runsNotifyTimeout: NodeJS.Timeout | undefined;
|
|
49
|
-
let
|
|
50
|
-
|
|
51
|
-
let stateRootWatcher: FSWatcher | undefined;
|
|
52
|
-
const runDirWatchers = new Map<string, FSWatcher>();
|
|
53
|
-
const observedRuns = new Map<string, Observability.RunObservedStatus>();
|
|
54
|
-
const observedRunEventLines = new Map<string, number>();
|
|
55
|
-
const observedRunOutboxEventIds = new Map<string, Set<string>>();
|
|
22
|
+
let activeRunContext: Pi.ExtensionContext | undefined;
|
|
23
|
+
const runUi = Observability.createRunUiObservationState();
|
|
56
24
|
const retirementAttempts = new Set<string>();
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
let actorInspectorChannels:
|
|
61
|
-
| ActorInspectorTui.ActorInspectorPreview["channel"][]
|
|
62
|
-
| undefined;
|
|
63
|
-
let actorInspectorMention: string | undefined;
|
|
64
|
-
let actorInspectorBranch: string | undefined;
|
|
65
|
-
let actorInspectorUnreadOnly = false;
|
|
66
|
-
let actorInspectorRoomLimitPerRun = 12;
|
|
67
|
-
let selectedInspectorSequence: number | undefined;
|
|
68
|
-
const actorInspectorReadKeys = new Set<string>();
|
|
69
|
-
let recipeWatcherFailureNotified = false;
|
|
70
|
-
const getRunOwnerId = (ctx: ExtensionContext): string =>
|
|
71
|
-
ctx.sessionManager.getSessionId();
|
|
25
|
+
const actorInspector =
|
|
26
|
+
ActorInspectorTui.createActorInspectorControllerState();
|
|
27
|
+
const getRunOwnerId = Pi.getSessionId;
|
|
72
28
|
const retireCandidateRuns = (
|
|
73
|
-
ctx: ExtensionContext,
|
|
29
|
+
ctx: Pi.ExtensionContext,
|
|
74
30
|
summary: Observability.RunSummary,
|
|
75
31
|
): void => {
|
|
76
32
|
void Observability.executeRunRetirements(summary, {
|
|
77
33
|
attempted: retirementAttempts,
|
|
78
34
|
cancelRun: (candidate) => AsyncRuns.cancelRun(candidate.stateDir),
|
|
79
35
|
notify: (message, level) => ctx.ui.notify(message, level),
|
|
80
|
-
sendStop: (candidate) =>
|
|
36
|
+
sendStop: (candidate) =>
|
|
37
|
+
AsyncRuns.sendRunMessage(candidate.stateDir, "stop"),
|
|
81
38
|
});
|
|
82
39
|
};
|
|
83
|
-
const updateRunUi = (ctx: ExtensionContext, notify = false): void => {
|
|
40
|
+
const updateRunUi = (ctx: Pi.ExtensionContext, notify = false): void => {
|
|
84
41
|
const ownerId = getRunOwnerId(ctx);
|
|
85
|
-
const
|
|
86
|
-
const status = Observability.renderRunStatus(summary, runStatusFrame++);
|
|
42
|
+
const snapshot = Observability.readRunUiSnapshot(runUi, ownerId);
|
|
87
43
|
ctx.ui.setStatus(
|
|
88
44
|
"zz-pi-actors-runs",
|
|
89
|
-
status ? ctx.ui.theme.fg("dim", status) : undefined,
|
|
45
|
+
snapshot.status ? ctx.ui.theme.fg("dim", snapshot.status) : undefined,
|
|
90
46
|
);
|
|
91
47
|
ctx.ui.setWidget(
|
|
92
48
|
"zz-pi-actors-comms",
|
|
93
|
-
|
|
94
|
-
? () => {
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
mention: actorInspectorMention,
|
|
116
|
-
ownerId,
|
|
117
|
-
readKeys: actorInspectorReadKeys,
|
|
118
|
-
roomLimitPerRun: actorInspectorRoomLimitPerRun,
|
|
119
|
-
unreadOnly: actorInspectorUnreadOnly,
|
|
120
|
-
},
|
|
121
|
-
);
|
|
122
|
-
const rows =
|
|
123
|
-
(selectedInspectorSequence !== undefined
|
|
124
|
-
? ActorInspectorTui.renderInspectorItemView(
|
|
125
|
-
previews,
|
|
126
|
-
width,
|
|
127
|
-
style,
|
|
128
|
-
{ sequence: selectedInspectorSequence },
|
|
129
|
-
)
|
|
130
|
-
: ActorInspectorTui.renderInspectorWidget(
|
|
131
|
-
previews,
|
|
132
|
-
width,
|
|
133
|
-
style,
|
|
134
|
-
)) ?? [];
|
|
135
|
-
const run = previews[0]?.run;
|
|
136
|
-
const roster =
|
|
137
|
-
selectedInspectorSequence === undefined && run
|
|
138
|
-
? ActorInspectorTui.renderInspectorRosterPanel(
|
|
139
|
-
ActorInspectorTui.readActorInspectorRoster(
|
|
140
|
-
RUN_STATE_ROOT,
|
|
141
|
-
run,
|
|
142
|
-
),
|
|
143
|
-
width,
|
|
144
|
-
style,
|
|
145
|
-
)
|
|
146
|
-
: undefined;
|
|
147
|
-
return roster ? [...roster, ...rows] : rows;
|
|
148
|
-
},
|
|
149
|
-
};
|
|
150
|
-
}
|
|
49
|
+
actorInspector.visible
|
|
50
|
+
? () => ({
|
|
51
|
+
invalidate() {},
|
|
52
|
+
render(width: number) {
|
|
53
|
+
return ActorInspectorTui.renderActorInspectorPanel({
|
|
54
|
+
stateRoot: Paths.EXTENSION_RUNTIME_PATHS.runStateRoot,
|
|
55
|
+
state: actorInspector,
|
|
56
|
+
ownerId,
|
|
57
|
+
width,
|
|
58
|
+
style: {
|
|
59
|
+
actor: (text: string) => ctx.ui.theme.fg("accent", text),
|
|
60
|
+
muted: (text: string) => ctx.ui.theme.fg("dim", text),
|
|
61
|
+
preview: (text: string) => ctx.ui.theme.fg("text", text),
|
|
62
|
+
stripe: (text: string) => text,
|
|
63
|
+
stripeAlt: (text: string) =>
|
|
64
|
+
ctx.ui.theme.bg("customMessageBg", text),
|
|
65
|
+
target: (text: string) => ctx.ui.theme.fg("success", text),
|
|
66
|
+
type: (text: string) => ctx.ui.theme.fg("warning", text),
|
|
67
|
+
},
|
|
68
|
+
});
|
|
69
|
+
},
|
|
70
|
+
})
|
|
151
71
|
: undefined,
|
|
152
72
|
{ placement: "belowEditor" },
|
|
153
73
|
);
|
|
154
|
-
const transitions = Observability.detectRunTransitions(
|
|
155
|
-
observedRuns,
|
|
156
|
-
summary,
|
|
157
|
-
);
|
|
158
|
-
const outboxEvents = Observability.detectRunOutboxEvents(
|
|
159
|
-
observedRunEventLines,
|
|
160
|
-
summary,
|
|
161
|
-
observedRunOutboxEventIds,
|
|
162
|
-
);
|
|
163
74
|
if (!notify) return;
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
customType: "pi-actors-run",
|
|
175
|
-
content: text,
|
|
176
|
-
display: true,
|
|
177
|
-
details: transition,
|
|
178
|
-
},
|
|
179
|
-
{ deliverAs: "followUp", triggerTurn: true },
|
|
180
|
-
);
|
|
181
|
-
}
|
|
182
|
-
Observability.pruneRunObservationState(
|
|
183
|
-
observedRuns,
|
|
184
|
-
observedRunEventLines,
|
|
185
|
-
summary,
|
|
186
|
-
transitions.map((transition) => transition.stateDir ?? transition.run),
|
|
187
|
-
observedRunOutboxEventIds,
|
|
75
|
+
const notificationSink = Pi.createNotificationSink(pi, ctx);
|
|
76
|
+
retireCandidateRuns(ctx, snapshot.summary);
|
|
77
|
+
Observability.deliverRunTransitionNotifications(
|
|
78
|
+
snapshot.transitions,
|
|
79
|
+
notificationSink,
|
|
80
|
+
);
|
|
81
|
+
Observability.pruneRunUiObservationState(runUi, snapshot);
|
|
82
|
+
Observability.deliverRunOutboxNotifications(
|
|
83
|
+
snapshot.outboxEvents,
|
|
84
|
+
notificationSink,
|
|
188
85
|
);
|
|
189
|
-
for (const event of outboxEvents) {
|
|
190
|
-
if (!Observability.shouldNotifyRunOutboxEvent(event)) continue;
|
|
191
|
-
const text = Observability.formatRunOutboxMessage(event);
|
|
192
|
-
const notificationType =
|
|
193
|
-
Observability.getRunOutboxNotificationType(event);
|
|
194
|
-
ctx.ui.notify(text, notificationType);
|
|
195
|
-
if (!Observability.shouldSendRunOutboxFollowUp(event)) continue;
|
|
196
|
-
pi.sendMessage(
|
|
197
|
-
{
|
|
198
|
-
customType: "pi-actors-run-message",
|
|
199
|
-
content: text,
|
|
200
|
-
display: true,
|
|
201
|
-
details: event,
|
|
202
|
-
},
|
|
203
|
-
{ deliverAs: "followUp", triggerTurn: true },
|
|
204
|
-
);
|
|
205
|
-
}
|
|
206
86
|
};
|
|
207
87
|
const closeRunWatchers = (): void => {
|
|
208
|
-
|
|
209
|
-
stateRootWatcher = undefined;
|
|
210
|
-
for (const watcher of runDirWatchers.values()) watcher.close();
|
|
211
|
-
runDirWatchers.clear();
|
|
88
|
+
runWatcher.close();
|
|
212
89
|
if (runsNotifyTimeout) clearTimeout(runsNotifyTimeout);
|
|
213
90
|
runsNotifyTimeout = undefined;
|
|
214
91
|
};
|
|
215
|
-
const scheduleRunEventUpdate = (ctx: ExtensionContext): void => {
|
|
92
|
+
const scheduleRunEventUpdate = (ctx: Pi.ExtensionContext): void => {
|
|
216
93
|
if (runsNotifyTimeout) clearTimeout(runsNotifyTimeout);
|
|
217
94
|
runsNotifyTimeout = setTimeout(() => {
|
|
218
|
-
|
|
95
|
+
runWatcher.refresh();
|
|
219
96
|
updateRunUi(ctx, true);
|
|
220
97
|
}, 50);
|
|
221
98
|
runsNotifyTimeout.unref?.();
|
|
222
99
|
};
|
|
223
|
-
const
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
watcher.close();
|
|
229
|
-
runDirWatchers.delete(stateDir);
|
|
230
|
-
});
|
|
231
|
-
runDirWatchers.set(stateDir, watcher);
|
|
232
|
-
} catch {
|
|
233
|
-
// Watching is best-effort; explicit inspect remains available.
|
|
234
|
-
}
|
|
235
|
-
};
|
|
236
|
-
function refreshRunWatchers(ctx: ExtensionContext): void {
|
|
237
|
-
if (!existsSync(RUN_STATE_ROOT)) return;
|
|
238
|
-
if (!stateRootWatcher) {
|
|
239
|
-
try {
|
|
240
|
-
stateRootWatcher = watch(RUN_STATE_ROOT, () =>
|
|
241
|
-
scheduleRunEventUpdate(ctx),
|
|
242
|
-
);
|
|
243
|
-
stateRootWatcher.on("error", () => {
|
|
244
|
-
stateRootWatcher?.close();
|
|
245
|
-
stateRootWatcher = undefined;
|
|
246
|
-
});
|
|
247
|
-
} catch {
|
|
248
|
-
// Watching is best-effort; explicit inspect remains available.
|
|
249
|
-
}
|
|
250
|
-
}
|
|
251
|
-
for (const entry of readdirSync(RUN_STATE_ROOT, { withFileTypes: true })) {
|
|
252
|
-
if (!entry.isDirectory()) continue;
|
|
253
|
-
watchRunDir(ctx, `${RUN_STATE_ROOT}/${entry.name}`);
|
|
254
|
-
}
|
|
255
|
-
}
|
|
256
|
-
const closeRecipeWatcher = (): void => {
|
|
257
|
-
recipeRootWatcher?.close();
|
|
258
|
-
recipeRootWatcher = undefined;
|
|
259
|
-
if (recipeReloadTimeout) clearTimeout(recipeReloadTimeout);
|
|
260
|
-
recipeReloadTimeout = undefined;
|
|
261
|
-
};
|
|
262
|
-
const notifyRecipeWatcherFailure = (ctx: ExtensionContext): void => {
|
|
263
|
-
if (recipeWatcherFailureNotified) return;
|
|
264
|
-
recipeWatcherFailureNotified = true;
|
|
265
|
-
ctx.ui.notify(
|
|
266
|
-
"Recipe live reload watcher failed; restart the session or use register_tool again to refresh recipe tools.",
|
|
267
|
-
"warning",
|
|
268
|
-
);
|
|
269
|
-
};
|
|
270
|
-
const scheduleRecipeReload = (ctx: ExtensionContext): void => {
|
|
271
|
-
recipeWatcherFailureNotified = false;
|
|
272
|
-
if (recipeReloadTimeout) clearTimeout(recipeReloadTimeout);
|
|
273
|
-
recipeReloadTimeout = setTimeout(() => {
|
|
274
|
-
runtime.loadTools(ctx);
|
|
275
|
-
ctx.ui.notify("Recipe tools refreshed from ~/.pi/agent/recipes", "info");
|
|
276
|
-
}, 150);
|
|
277
|
-
recipeReloadTimeout.unref?.();
|
|
278
|
-
};
|
|
279
|
-
const watchRecipeRoot = (ctx: ExtensionContext): void => {
|
|
280
|
-
const recipeRoot = Paths.getRecipeRoot();
|
|
281
|
-
if (recipeRootWatcher || !existsSync(recipeRoot)) return;
|
|
282
|
-
try {
|
|
283
|
-
recipeRootWatcher = watch(recipeRoot, () => scheduleRecipeReload(ctx));
|
|
284
|
-
recipeRootWatcher.on("error", () => {
|
|
285
|
-
recipeRootWatcher?.close();
|
|
286
|
-
recipeRootWatcher = undefined;
|
|
287
|
-
notifyRecipeWatcherFailure(ctx);
|
|
288
|
-
});
|
|
289
|
-
} catch {
|
|
290
|
-
notifyRecipeWatcherFailure(ctx);
|
|
291
|
-
}
|
|
292
|
-
};
|
|
100
|
+
const runWatcher = Observability.createRunStateWatcher({
|
|
101
|
+
stateRoot: Paths.EXTENSION_RUNTIME_PATHS.runStateRoot,
|
|
102
|
+
onChange: () =>
|
|
103
|
+
activeRunContext && scheduleRunEventUpdate(activeRunContext),
|
|
104
|
+
});
|
|
293
105
|
const actorToolDefinitions = new Map<string, any>();
|
|
294
106
|
const runtime = Runtime.createAutoToolsRuntime({
|
|
295
|
-
configPath:
|
|
107
|
+
configPath: Paths.EXTENSION_RUNTIME_PATHS.configPath,
|
|
296
108
|
exec: CommandTemplates.execCommandTemplate,
|
|
297
109
|
getActiveTools: () => pi.getActiveTools(),
|
|
298
110
|
getAllTools: () => pi.getAllTools(),
|
|
@@ -300,21 +112,24 @@ export default function toolRegistryExtension(pi: ExtensionAPI) {
|
|
|
300
112
|
actorToolDefinitions.set(definition.name, definition);
|
|
301
113
|
pi.registerTool(definition);
|
|
302
114
|
},
|
|
303
|
-
reservedToolNames: RESERVED_TOOL_NAMES,
|
|
115
|
+
reservedToolNames: Tools.RESERVED_TOOL_NAMES,
|
|
304
116
|
setActiveTools: (toolNames) => pi.setActiveTools(toolNames),
|
|
305
117
|
});
|
|
118
|
+
const recipeReload = Runtime.createRecipeToolReloadWatcher(runtime);
|
|
306
119
|
pi.on("resources_discover", async () => {
|
|
307
|
-
|
|
308
|
-
|
|
120
|
+
const skillPaths = Paths.getExistingExtensionSkillPaths(import.meta.url);
|
|
121
|
+
if (skillPaths.length === 0) return;
|
|
122
|
+
return { skillPaths };
|
|
309
123
|
});
|
|
310
124
|
pi.on("session_start", async (_event, ctx) => {
|
|
311
|
-
|
|
125
|
+
activeRunContext = ctx;
|
|
126
|
+
await Temp.prepareExtensionTempDir(Paths.EXTENSION_RUNTIME_PATHS.tempDir);
|
|
312
127
|
runtime.loadTools(ctx);
|
|
313
128
|
updateRunUi(ctx);
|
|
314
129
|
closeRunWatchers();
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
130
|
+
recipeReload.close();
|
|
131
|
+
runWatcher.refresh();
|
|
132
|
+
recipeReload.watch(ctx);
|
|
318
133
|
if (runsAnimationInterval) clearInterval(runsAnimationInterval);
|
|
319
134
|
runsAnimationInterval = setInterval(() => updateRunUi(ctx, false), 1000);
|
|
320
135
|
runsAnimationInterval.unref?.();
|
|
@@ -322,158 +137,63 @@ export default function toolRegistryExtension(pi: ExtensionAPI) {
|
|
|
322
137
|
pi.on("session_shutdown", async () => {
|
|
323
138
|
if (runsAnimationInterval) clearInterval(runsAnimationInterval);
|
|
324
139
|
runsAnimationInterval = undefined;
|
|
140
|
+
activeRunContext = undefined;
|
|
325
141
|
closeRunWatchers();
|
|
326
|
-
|
|
142
|
+
recipeReload.close();
|
|
327
143
|
});
|
|
328
144
|
pi.registerCommand("actors-inspector-toggle", {
|
|
329
|
-
description:
|
|
145
|
+
description: ActorInspectorTui.ACTOR_INSPECTOR_COMMAND_DESCRIPTIONS.toggle,
|
|
330
146
|
handler: async (args, ctx) => {
|
|
331
|
-
const
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
if (!Number.isFinite(rows) || rows <= 0) {
|
|
335
|
-
ctx.ui.notify(
|
|
336
|
-
"Usage: /actors-inspector-toggle [rows] where rows > 0",
|
|
337
|
-
"warning",
|
|
338
|
-
);
|
|
339
|
-
return;
|
|
340
|
-
}
|
|
341
|
-
actorInspectorRows = rows;
|
|
342
|
-
actorInspectorRoomLimitPerRun = rows;
|
|
343
|
-
selectedInspectorSequence = undefined;
|
|
344
|
-
communicationWidgetVisible = true;
|
|
345
|
-
updateRunUi(ctx);
|
|
346
|
-
ctx.ui.notify(`Actor inspector rows ${rows}`, "info");
|
|
347
|
-
return;
|
|
348
|
-
}
|
|
349
|
-
if (selectedInspectorSequence !== undefined) {
|
|
350
|
-
selectedInspectorSequence = undefined;
|
|
351
|
-
communicationWidgetVisible = true;
|
|
352
|
-
updateRunUi(ctx);
|
|
353
|
-
ctx.ui.notify("Actor inspector table", "info");
|
|
354
|
-
return;
|
|
355
|
-
}
|
|
356
|
-
if (communicationWidgetVisible) {
|
|
357
|
-
communicationWidgetVisible = false;
|
|
358
|
-
} else {
|
|
359
|
-
actorInspectorRows = 12;
|
|
360
|
-
actorInspectorRoomLimitPerRun = 12;
|
|
361
|
-
communicationWidgetVisible = true;
|
|
362
|
-
}
|
|
363
|
-
updateRunUi(ctx);
|
|
364
|
-
ctx.ui.notify(
|
|
365
|
-
`Actor inspector ${communicationWidgetVisible ? "shown" : "hidden"}`,
|
|
366
|
-
"info",
|
|
147
|
+
const result = ActorInspectorTui.handleActorInspectorToggle(
|
|
148
|
+
actorInspector,
|
|
149
|
+
args,
|
|
367
150
|
);
|
|
151
|
+
if (result.update) updateRunUi(ctx);
|
|
152
|
+
ctx.ui.notify(result.notify, result.type);
|
|
368
153
|
},
|
|
369
154
|
});
|
|
370
155
|
pi.registerCommand("actors-inspector-filter", {
|
|
371
|
-
description:
|
|
372
|
-
"Filter actor inspector rows: all, room, direct, broadcast, unread, branch <name>, mention <text>",
|
|
156
|
+
description: ActorInspectorTui.ACTOR_INSPECTOR_COMMAND_DESCRIPTIONS.filter,
|
|
373
157
|
handler: async (args, ctx) => {
|
|
374
|
-
const
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
if (
|
|
379
|
-
|
|
380
|
-
actorInspectorMention = undefined;
|
|
381
|
-
actorInspectorBranch = undefined;
|
|
382
|
-
actorInspectorUnreadOnly = false;
|
|
383
|
-
} else if (mode === "room" || mode === "direct" || mode === "broadcast") {
|
|
384
|
-
actorInspectorChannels = [mode];
|
|
385
|
-
actorInspectorMention = undefined;
|
|
386
|
-
} else if (mode === "unread") {
|
|
387
|
-
actorInspectorUnreadOnly = true;
|
|
388
|
-
} else if (mode === "branch" || mode === "current-branch") {
|
|
389
|
-
const branch = parts.slice(1).join(" ").trim();
|
|
390
|
-
if (!branch) {
|
|
391
|
-
ctx.ui.notify(
|
|
392
|
-
`Usage: /actors-inspector-filter ${mode} <branch-name>`,
|
|
393
|
-
"warning",
|
|
394
|
-
);
|
|
395
|
-
return;
|
|
396
|
-
}
|
|
397
|
-
actorInspectorBranch = branch;
|
|
398
|
-
} else if (mode === "mention") {
|
|
399
|
-
const mention = parts.slice(1).join(" ").trim();
|
|
400
|
-
if (!mention) {
|
|
401
|
-
ctx.ui.notify(
|
|
402
|
-
"Usage: /actors-inspector-filter mention <text>",
|
|
403
|
-
"warning",
|
|
404
|
-
);
|
|
405
|
-
return;
|
|
406
|
-
}
|
|
407
|
-
actorInspectorChannels = undefined;
|
|
408
|
-
actorInspectorMention = mention;
|
|
409
|
-
} else {
|
|
410
|
-
ctx.ui.notify(
|
|
411
|
-
"Usage: /actors-inspector-filter all|room|direct|broadcast|unread|branch <name>|mention <text>",
|
|
412
|
-
"warning",
|
|
413
|
-
);
|
|
414
|
-
return;
|
|
415
|
-
}
|
|
416
|
-
selectedInspectorSequence = undefined;
|
|
417
|
-
communicationWidgetVisible = true;
|
|
418
|
-
updateRunUi(ctx);
|
|
419
|
-
ctx.ui.notify(`Actor inspector filter ${mode || "all"}`, "info");
|
|
158
|
+
const result = ActorInspectorTui.handleActorInspectorFilter(
|
|
159
|
+
actorInspector,
|
|
160
|
+
args,
|
|
161
|
+
);
|
|
162
|
+
if (result.update) updateRunUi(ctx);
|
|
163
|
+
ctx.ui.notify(result.notify, result.type);
|
|
420
164
|
},
|
|
421
165
|
});
|
|
422
166
|
pi.registerCommand("actors-inspect", {
|
|
423
|
-
description:
|
|
167
|
+
description: ActorInspectorTui.ACTOR_INSPECTOR_COMMAND_DESCRIPTIONS.inspect,
|
|
424
168
|
handler: async (args, ctx) => {
|
|
425
|
-
const raw = Array.isArray(args) ? args[0] : String(args ?? "");
|
|
426
|
-
const sequence = Number.parseInt(String(raw), 10);
|
|
427
|
-
if (!Number.isFinite(sequence) || sequence <= 0) {
|
|
428
|
-
ctx.ui.notify("Usage: /actors-inspect <number>", "warning");
|
|
429
|
-
return;
|
|
430
|
-
}
|
|
431
169
|
const previews = ActorInspectorTui.readActorInspectorPreviews(
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
mention: actorInspectorMention,
|
|
439
|
-
ownerId: getRunOwnerId(ctx),
|
|
440
|
-
readKeys: actorInspectorReadKeys,
|
|
441
|
-
roomLimitPerRun: actorInspectorRoomLimitPerRun,
|
|
442
|
-
unreadOnly: actorInspectorUnreadOnly,
|
|
443
|
-
},
|
|
170
|
+
Paths.EXTENSION_RUNTIME_PATHS.runStateRoot,
|
|
171
|
+
actorInspector.rows,
|
|
172
|
+
ActorInspectorTui.getActorInspectorPreviewOptions(
|
|
173
|
+
actorInspector,
|
|
174
|
+
getRunOwnerId(ctx),
|
|
175
|
+
),
|
|
444
176
|
);
|
|
445
|
-
const
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
177
|
+
const result = ActorInspectorTui.handleActorInspectorInspect(
|
|
178
|
+
actorInspector,
|
|
179
|
+
args,
|
|
180
|
+
previews,
|
|
181
|
+
);
|
|
182
|
+
if (result.update) updateRunUi(ctx);
|
|
183
|
+
ctx.ui.notify(result.notify, result.type);
|
|
451
184
|
},
|
|
452
185
|
});
|
|
453
186
|
pi.on("before_agent_start", async (event) => ({
|
|
454
187
|
systemPrompt: `${event.systemPrompt}\n\n${Prompts.ONBOARDING_SYSTEM_PROMPT}`,
|
|
455
188
|
}));
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
189
|
+
Pi.registerToolDefinitions(
|
|
190
|
+
pi,
|
|
191
|
+
Tools.createCoreActorToolDefinitions<Pi.ExtensionContext>({
|
|
192
|
+
configPath: Paths.EXTENSION_RUNTIME_PATHS.configPath,
|
|
459
193
|
getActiveTools: () => pi.getActiveTools(),
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
notify: runtime.notify,
|
|
463
|
-
registerRuntimeTool: runtime.registerRuntimeTool,
|
|
464
|
-
reservedToolNames: RESERVED_TOOL_NAMES,
|
|
194
|
+
getRuntimeTool: (name) => actorToolDefinitions.get(name),
|
|
195
|
+
registryRuntime: runtime,
|
|
465
196
|
setActiveTools: (toolNames) => pi.setActiveTools(toolNames),
|
|
466
197
|
}),
|
|
467
198
|
);
|
|
468
|
-
pi.registerTool(Tools.createSpawnToolDefinition<ExtensionContext>());
|
|
469
|
-
pi.registerTool(
|
|
470
|
-
Tools.createActorMessageToolDefinition<ExtensionContext>({
|
|
471
|
-
getTool: (name) => actorToolDefinitions.get(name),
|
|
472
|
-
}),
|
|
473
|
-
);
|
|
474
|
-
pi.registerTool(
|
|
475
|
-
Tools.createInspectToolDefinition<ExtensionContext>({
|
|
476
|
-
getTool: (name) => actorToolDefinitions.get(name),
|
|
477
|
-
}),
|
|
478
|
-
);
|
|
479
199
|
}
|