@llblab/pi-actors 0.33.0 → 0.34.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 +22 -11
- package/BACKLOG.md +1 -1
- package/CHANGELOG.md +22 -1
- package/dist/index.js +10 -10
- package/dist/lib/async-runs.d.ts +23 -75
- package/dist/lib/async-runs.js +49 -801
- package/dist/lib/command-templates.d.ts +3 -3
- package/dist/lib/command-templates.js +3 -3
- package/dist/lib/config.d.ts +2 -2
- package/dist/lib/config.js +5 -5
- package/dist/lib/{output.d.ts → execution-output.d.ts} +3 -3
- package/dist/lib/{output.js → execution-output.js} +3 -3
- package/dist/lib/execution.js +1 -1
- package/dist/lib/{actor-inspector-tui.d.ts → inspector.d.ts} +3 -2
- package/dist/lib/{actor-inspector-tui.js → inspector.js} +3 -2
- package/dist/lib/mailbox-loop.d.ts +3 -3
- package/dist/lib/mailbox-loop.js +3 -3
- package/dist/lib/{actor-messages.d.ts → messages.d.ts} +3 -3
- package/dist/lib/{actor-messages.js → messages.js} +3 -3
- package/dist/lib/{actor-recipe-context.d.ts → recipes-context.d.ts} +3 -2
- package/dist/lib/{actor-recipe-context.js → recipes-context.js} +2 -1
- package/dist/lib/{recipe-discovery.d.ts → recipes-discovery.d.ts} +8 -8
- package/dist/lib/{recipe-discovery.js → recipes-discovery.js} +6 -6
- package/dist/lib/registry.d.ts +1 -1
- package/dist/lib/registry.js +22 -22
- package/dist/lib/{actor-rooms.d.ts → rooms.d.ts} +4 -4
- package/dist/lib/{actor-rooms.js → rooms.js} +3 -3
- package/dist/lib/runs-artifacts.d.ts +21 -0
- package/dist/lib/runs-artifacts.js +68 -0
- package/dist/lib/runs-control.d.ts +13 -0
- package/dist/lib/runs-control.js +59 -0
- package/dist/lib/runs-identity.d.ts +5 -0
- package/dist/lib/runs-identity.js +11 -0
- package/dist/lib/runs-index.d.ts +18 -0
- package/dist/lib/runs-index.js +119 -0
- package/dist/lib/runs-mailbox.d.ts +25 -0
- package/dist/lib/runs-mailbox.js +146 -0
- package/dist/lib/runs-messages.d.ts +15 -0
- package/dist/lib/runs-messages.js +179 -0
- package/dist/lib/runs-outbox.d.ts +41 -0
- package/dist/lib/runs-outbox.js +87 -0
- package/dist/lib/runs-process.d.ts +7 -0
- package/dist/lib/runs-process.js +36 -0
- package/dist/lib/runs-retention.d.ts +8 -0
- package/dist/lib/runs-retention.js +56 -0
- package/dist/lib/runs-start.d.ts +9 -0
- package/dist/lib/runs-start.js +67 -0
- package/dist/lib/runs-status.d.ts +8 -0
- package/dist/lib/runs-status.js +60 -0
- package/dist/lib/runtime.d.ts +2 -2
- package/dist/lib/runtime.js +5 -5
- package/dist/lib/schema.d.ts +9 -0
- package/dist/lib/schema.js +40 -0
- package/dist/lib/tools-access.d.ts +19 -0
- package/dist/lib/tools-access.js +44 -0
- package/dist/lib/tools-inspect.d.ts +11 -0
- package/dist/lib/tools-inspect.js +534 -0
- package/dist/lib/tools-local.d.ts +14 -0
- package/dist/lib/tools-local.js +156 -0
- package/dist/lib/tools-mailbox.d.ts +8 -0
- package/dist/lib/tools-mailbox.js +48 -0
- package/dist/lib/tools-message.d.ts +9 -0
- package/dist/lib/tools-message.js +346 -0
- package/dist/lib/tools-register.d.ts +18 -0
- package/dist/lib/tools-register.js +40 -0
- package/dist/lib/tools-response.d.ts +21 -0
- package/dist/lib/tools-response.js +219 -0
- package/dist/lib/tools-spawn.d.ts +12 -0
- package/dist/lib/tools-spawn.js +159 -0
- package/dist/lib/tools.d.ts +8 -39
- package/dist/lib/tools.js +11 -1490
- package/dist/recipes/utility-coordinator-lock-snapshot.json +1 -1
- package/dist/scripts/actor-worker.mjs +186 -7
- package/dist/scripts/async-runner.mjs +171 -8
- package/dist/scripts/build-dist.mjs +1 -1
- package/dist/scripts/conformance.mjs +3 -3
- package/dist/scripts/coordinator.mjs +733 -11
- package/dist/scripts/locker.mjs +345 -16
- package/dist/scripts/recipe-utils.mjs +478 -14
- package/dist/scripts/validate-recipe.mjs +110 -10
- package/dist/skills/actors/SKILL.md +1 -1
- package/dist/skills/swarm/SKILL.md +1 -1
- package/docs/recipe-library.md +1 -1
- package/docs/template-recipes.md +1 -1
- package/index.ts +11 -18
- package/lib/async-runs.ts +124 -1016
- package/lib/command-templates.ts +3 -3
- package/lib/config.ts +7 -7
- package/lib/{output.ts → execution-output.ts} +3 -3
- package/lib/execution.ts +5 -1
- package/lib/{actor-inspector-tui.ts → inspector.ts} +4 -3
- package/lib/mailbox-loop.ts +3 -3
- package/lib/{actor-messages.ts → messages.ts} +3 -3
- package/lib/{actor-recipe-context.ts → recipes-context.ts} +3 -2
- package/lib/{recipe-discovery.ts → recipes-discovery.ts} +19 -19
- package/lib/{recipe-usage.ts → recipes-usage.ts} +2 -2
- package/lib/registry.ts +37 -24
- package/lib/{actor-rooms.ts → rooms.ts} +4 -4
- package/lib/runs-artifacts.ts +96 -0
- package/lib/runs-control.ts +85 -0
- package/lib/runs-identity.ts +14 -0
- package/lib/runs-index.ts +156 -0
- package/lib/runs-mailbox.ts +208 -0
- package/lib/runs-messages.ts +252 -0
- package/lib/runs-outbox.ts +144 -0
- package/lib/runs-process.ts +51 -0
- package/lib/runs-retention.ts +77 -0
- package/lib/runs-start.ts +98 -0
- package/lib/runs-status.ts +78 -0
- package/lib/runtime.ts +6 -6
- package/lib/schema.ts +55 -0
- package/lib/tools-access.ts +68 -0
- package/lib/tools-inspect.ts +735 -0
- package/lib/tools-local.ts +234 -0
- package/lib/tools-mailbox.ts +56 -0
- package/lib/tools-message.ts +483 -0
- package/lib/tools-register.ts +64 -0
- package/lib/tools-response.ts +267 -0
- package/lib/tools-spawn.ts +240 -0
- package/lib/tools.ts +20 -2040
- package/package.json +1 -1
- package/recipes/utility-coordinator-lock-snapshot.json +1 -1
- package/scripts/actor-worker.mjs +186 -7
- package/scripts/async-runner.mjs +171 -8
- package/scripts/build-dist.mjs +1 -1
- package/scripts/conformance.mjs +3 -3
- package/scripts/coordinator.mjs +733 -11
- package/scripts/locker.mjs +345 -16
- package/scripts/recipe-utils.mjs +478 -14
- package/scripts/validate-recipe.mjs +110 -10
- package/skills/actors/SKILL.md +1 -1
- package/skills/swarm/SKILL.md +1 -1
- package/dist/lib/actor-worker.d.ts +0 -16
- package/dist/lib/actor-worker.js +0 -134
- package/dist/lib/async-runner.d.ts +0 -5
- package/dist/lib/async-runner.js +0 -134
- package/dist/lib/coordinator.d.ts +0 -5
- package/dist/lib/coordinator.js +0 -660
- package/dist/lib/locker.d.ts +0 -5
- package/dist/lib/locker.js +0 -310
- package/dist/lib/recipe-utils.d.ts +0 -5
- package/dist/lib/recipe-utils.js +0 -385
- package/dist/lib/validate-recipe.d.ts +0 -6
- package/dist/lib/validate-recipe.js +0 -104
- package/lib/actor-worker.ts +0 -174
- package/lib/async-runner.ts +0 -173
- package/lib/coordinator.ts +0 -742
- package/lib/locker.ts +0 -340
- package/lib/recipe-utils.ts +0 -486
- package/lib/validate-recipe.ts +0 -110
- /package/dist/lib/{recipe-references.d.ts → recipes-references.d.ts} +0 -0
- /package/dist/lib/{recipe-references.js → recipes-references.js} +0 -0
- /package/dist/lib/{recipe-usage.d.ts → recipes-usage.d.ts} +0 -0
- /package/dist/lib/{recipe-usage.js → recipes-usage.js} +0 -0
- /package/lib/{recipe-references.ts → recipes-references.ts} +0 -0
|
@@ -0,0 +1,534 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Public inspect tool behavior
|
|
3
|
+
* Zones: actor observation, recipe registry inspection, room/session/tool/run views
|
|
4
|
+
* Owns the public inspect execution path and compact observation responses
|
|
5
|
+
*/
|
|
6
|
+
import { execFileSync } from "node:child_process";
|
|
7
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
8
|
+
import { dirname, join } from "node:path";
|
|
9
|
+
import * as AsyncRuns from "./async-runs.js";
|
|
10
|
+
import * as Limits from "./limits.js";
|
|
11
|
+
import * as Messages from "./messages.js";
|
|
12
|
+
import * as Paths from "./paths.js";
|
|
13
|
+
import * as RecipesDiscovery from "./recipes-discovery.js";
|
|
14
|
+
import * as Rooms from "./rooms.js";
|
|
15
|
+
import * as Schema from "./schema.js";
|
|
16
|
+
import * as ToolsAccess from "./tools-access.js";
|
|
17
|
+
import * as ToolsMailbox from "./tools-mailbox.js";
|
|
18
|
+
import * as ToolsResponse from "./tools-response.js";
|
|
19
|
+
const asRecord = ToolsResponse.asRecord;
|
|
20
|
+
const maybeJsonText = ToolsResponse.maybeJsonText;
|
|
21
|
+
function compactRunMessages(messages) {
|
|
22
|
+
if (messages.length === 0)
|
|
23
|
+
return "\n(no actor messages)";
|
|
24
|
+
return `\n${messages
|
|
25
|
+
.map((message) => [
|
|
26
|
+
`run=${message.run}`,
|
|
27
|
+
`type=${message.event}`,
|
|
28
|
+
`level=${message.level}`,
|
|
29
|
+
`summary=${message.summary.replaceAll(/\s+/g, "_")}`,
|
|
30
|
+
].join(" "))
|
|
31
|
+
.join("\n")}`;
|
|
32
|
+
}
|
|
33
|
+
function compactRoomPreviews(previews) {
|
|
34
|
+
if (previews.length === 0)
|
|
35
|
+
return "\n(no room message previews)";
|
|
36
|
+
return `\n${previews
|
|
37
|
+
.map((preview) => [
|
|
38
|
+
`ts=${preview.timestamp}`,
|
|
39
|
+
preview.from ? `from=${preview.from}` : "",
|
|
40
|
+
`to=${preview.to}`,
|
|
41
|
+
`type=${preview.type}`,
|
|
42
|
+
preview.summary
|
|
43
|
+
? `summary=${ToolsResponse.compactPreview(preview.summary)}`
|
|
44
|
+
: "",
|
|
45
|
+
preview.body_preview
|
|
46
|
+
? `body=${ToolsResponse.compactPreview(preview.body_preview)}`
|
|
47
|
+
: "",
|
|
48
|
+
]
|
|
49
|
+
.filter(Boolean)
|
|
50
|
+
.join(" "))
|
|
51
|
+
.join("\n")}`;
|
|
52
|
+
}
|
|
53
|
+
function compactRoomMessages(messages) {
|
|
54
|
+
if (messages.length === 0)
|
|
55
|
+
return "\n(no room messages)";
|
|
56
|
+
return `\n${messages
|
|
57
|
+
.map((message) => [
|
|
58
|
+
`ts=${message.received_at}`,
|
|
59
|
+
`from=${String(message.from ?? "<unknown>")}`,
|
|
60
|
+
`to=${message.to}`,
|
|
61
|
+
`type=${message.type}`,
|
|
62
|
+
`summary=${String(message.summary ?? "").replaceAll(/\s+/g, "_")}`,
|
|
63
|
+
ToolsResponse.compactPreview(message.body)
|
|
64
|
+
? `body=${ToolsResponse.compactPreview(message.body)}`
|
|
65
|
+
: "",
|
|
66
|
+
]
|
|
67
|
+
.filter(Boolean)
|
|
68
|
+
.join(" "))
|
|
69
|
+
.join("\n")}`;
|
|
70
|
+
}
|
|
71
|
+
function compactRoomContacts(contacts) {
|
|
72
|
+
if (contacts.length === 0)
|
|
73
|
+
return "\n(no room contacts)";
|
|
74
|
+
return `\n${contacts
|
|
75
|
+
.map((contact) => [
|
|
76
|
+
`address=${contact.address}`,
|
|
77
|
+
contact.role !== undefined ? `role=${String(contact.role)}` : "",
|
|
78
|
+
contact.parent !== undefined ? `parent=${String(contact.parent)}` : "",
|
|
79
|
+
contact.caps !== undefined
|
|
80
|
+
? `caps=${Array.isArray(contact.caps) ? contact.caps.join(",") : String(contact.caps)}`
|
|
81
|
+
: "",
|
|
82
|
+
contact.claim !== undefined
|
|
83
|
+
? `claim=${String(contact.claim).replaceAll(/\s+/g, "_")}`
|
|
84
|
+
: "",
|
|
85
|
+
contact.status !== undefined ? `status=${String(contact.status)}` : "",
|
|
86
|
+
]
|
|
87
|
+
.filter(Boolean)
|
|
88
|
+
.join(" "))
|
|
89
|
+
.join("\n")}`;
|
|
90
|
+
}
|
|
91
|
+
function compactRoomRoster(roster) {
|
|
92
|
+
const members = Object.values(roster);
|
|
93
|
+
if (members.length === 0)
|
|
94
|
+
return "\n(no room members)";
|
|
95
|
+
return `\n${members
|
|
96
|
+
.map((member) => [
|
|
97
|
+
`address=${member.address}`,
|
|
98
|
+
`role=${String(member.role ?? "")}`,
|
|
99
|
+
member.parent !== undefined ? `parent=${String(member.parent)}` : "",
|
|
100
|
+
member.caps !== undefined
|
|
101
|
+
? `caps=${Array.isArray(member.caps) ? member.caps.join(",") : String(member.caps)}`
|
|
102
|
+
: "",
|
|
103
|
+
member.claim !== undefined
|
|
104
|
+
? `claim=${String(member.claim).replaceAll(/\s+/g, "_")}`
|
|
105
|
+
: "",
|
|
106
|
+
`status=${String(member.status ?? "")}`,
|
|
107
|
+
`last_seen=${member.last_seen}`,
|
|
108
|
+
].join(" "))
|
|
109
|
+
.join("\n")}`;
|
|
110
|
+
}
|
|
111
|
+
function compactRoomStatus(status) {
|
|
112
|
+
return `\nroom=${status.room} messages=${status.message_count} roster=${status.roster_count}${status.diagnostics_count ? ` diagnostics=${status.diagnostics_count}` : ""}${status.last_message_at ? ` last_message_at=${status.last_message_at}` : ""}${status.last_message_from ? ` last_from=${status.last_message_from}` : ""}${status.last_message_type ? ` last_type=${status.last_message_type}` : ""}${status.last_message_summary ? ` last_summary=${ToolsResponse.compactPreview(status.last_message_summary)}` : ""}`;
|
|
113
|
+
}
|
|
114
|
+
function compactCommunicationSnapshot(snapshot) {
|
|
115
|
+
if (!snapshot)
|
|
116
|
+
return "\n(no communication snapshot)";
|
|
117
|
+
return `\nself=${snapshot.self} root=${snapshot.root} rooms=${snapshot.rooms.length} updated_at=${snapshot.updated_at}`;
|
|
118
|
+
}
|
|
119
|
+
function compactArtifactPath(value) {
|
|
120
|
+
if (typeof value === "string")
|
|
121
|
+
return value;
|
|
122
|
+
const record = asRecord(value);
|
|
123
|
+
return String(record.path ?? "<missing>");
|
|
124
|
+
}
|
|
125
|
+
function compactActorFiles(status) {
|
|
126
|
+
const run = String(status.run ?? "<unknown>");
|
|
127
|
+
const artifacts = asRecord(status.artifacts);
|
|
128
|
+
const files = [
|
|
129
|
+
status.stdoutLog,
|
|
130
|
+
status.stderrLog,
|
|
131
|
+
status.eventsFile,
|
|
132
|
+
status.outboxFile,
|
|
133
|
+
status.state_dir
|
|
134
|
+
? `${String(status.state_dir)}/communication.json`
|
|
135
|
+
: undefined,
|
|
136
|
+
status.state_dir ? `${String(status.state_dir)}/result.json` : undefined,
|
|
137
|
+
].filter((file) => typeof file === "string");
|
|
138
|
+
const artifactText = Object.keys(artifacts).length
|
|
139
|
+
? ` artifacts=${Object.entries(artifacts)
|
|
140
|
+
.map(([key, value]) => `${key}:${compactArtifactPath(value)}`)
|
|
141
|
+
.join(",")}`
|
|
142
|
+
: "";
|
|
143
|
+
const nextActions = ToolsResponse.artifactNextActions(run, artifacts);
|
|
144
|
+
const nextText = nextActions.length
|
|
145
|
+
? ` next=${nextActions.map((action) => action.replaceAll(/\s+/g, "_")).join("|")}`
|
|
146
|
+
: "";
|
|
147
|
+
return `\nrun=${run}${artifactText}${files.length ? ` files=${files.join(",")}` : ""}${nextText}`;
|
|
148
|
+
}
|
|
149
|
+
function summarizeOtherSessions(currentSession, allRuns) {
|
|
150
|
+
const otherRuns = allRuns.filter((run) => run.ownerId && run.ownerId !== currentSession);
|
|
151
|
+
return {
|
|
152
|
+
other_runs: otherRuns.length,
|
|
153
|
+
other_sessions: new Set(otherRuns.map((run) => run.ownerId)).size,
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
function compactSessionRuns(session, runs, summary = {}) {
|
|
157
|
+
const suffix = [
|
|
158
|
+
summary.other_sessions !== undefined
|
|
159
|
+
? `other_sessions=${String(summary.other_sessions)}`
|
|
160
|
+
: "",
|
|
161
|
+
summary.other_runs !== undefined
|
|
162
|
+
? `other_runs=${String(summary.other_runs)}`
|
|
163
|
+
: "",
|
|
164
|
+
]
|
|
165
|
+
.filter(Boolean)
|
|
166
|
+
.join(" ");
|
|
167
|
+
if (runs.length === 0)
|
|
168
|
+
return `\nsession=${session} runs=0${suffix ? ` ${suffix}` : ""}`;
|
|
169
|
+
return `\nsession=${session} runs=${runs.length}${suffix ? ` ${suffix}` : ""}\n${runs
|
|
170
|
+
.map((run) => {
|
|
171
|
+
const tokens = [
|
|
172
|
+
`run=${String(run.run ?? "")}`,
|
|
173
|
+
`status=${String(run.status ?? "")}`,
|
|
174
|
+
];
|
|
175
|
+
if (run.recipe)
|
|
176
|
+
tokens.push(`recipe=${String(run.recipe)}`);
|
|
177
|
+
if (run.retire_when)
|
|
178
|
+
tokens.push(`retire_when=${String(run.retire_when)}`);
|
|
179
|
+
return tokens.join(" ");
|
|
180
|
+
})
|
|
181
|
+
.join("\n")}`;
|
|
182
|
+
}
|
|
183
|
+
function getPiActorsRuntimeStatus() {
|
|
184
|
+
const packagedRecipeRoot = Paths.getPackagedRecipeRoot();
|
|
185
|
+
const packageRoot = dirname(packagedRecipeRoot);
|
|
186
|
+
const packageJsonPath = join(packageRoot, "package.json");
|
|
187
|
+
const packageJson = existsSync(packageJsonPath)
|
|
188
|
+
? JSON.parse(readFileSync(packageJsonPath, "utf8"))
|
|
189
|
+
: {};
|
|
190
|
+
let git_commit;
|
|
191
|
+
try {
|
|
192
|
+
git_commit = execFileSync("git", ["-C", packageRoot, "rev-parse", "--short", "HEAD"], {
|
|
193
|
+
encoding: "utf8",
|
|
194
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
195
|
+
}).trim();
|
|
196
|
+
}
|
|
197
|
+
catch {
|
|
198
|
+
git_commit = undefined;
|
|
199
|
+
}
|
|
200
|
+
const entrypoint = new URL(import.meta.url).pathname;
|
|
201
|
+
return {
|
|
202
|
+
entrypoint,
|
|
203
|
+
git_commit,
|
|
204
|
+
mode: entrypoint.includes("/dist/") ? "dist" : "source",
|
|
205
|
+
package_name: packageJson.name ?? "@llblab/pi-actors",
|
|
206
|
+
package_root: packageRoot,
|
|
207
|
+
recipe_root: Paths.getRecipeRoot(),
|
|
208
|
+
packaged_recipe_root: packagedRecipeRoot,
|
|
209
|
+
version: packageJson.version ?? "unknown",
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
function compactPiActorsRuntimeStatus(status) {
|
|
213
|
+
return `\npi-actors version=${String(status.version)} mode=${String(status.mode)} path=${String(status.package_root)} entrypoint=${String(status.entrypoint)}${status.git_commit ? ` git=${String(status.git_commit)}` : ""}`;
|
|
214
|
+
}
|
|
215
|
+
function compactToolActor(name, tool) {
|
|
216
|
+
const parameters = asRecord(tool.parameters);
|
|
217
|
+
const required = Array.isArray(parameters.required)
|
|
218
|
+
? parameters.required.join(",")
|
|
219
|
+
: "";
|
|
220
|
+
const properties = asRecord(parameters.properties);
|
|
221
|
+
return `\ntool=${name} description=${String(tool.description ?? "").replaceAll(/\s+/g, "_")} args=${Object.keys(properties).join(",")} required=${required}`;
|
|
222
|
+
}
|
|
223
|
+
export function createInspectToolDefinition(deps = {}) {
|
|
224
|
+
return {
|
|
225
|
+
name: "inspect",
|
|
226
|
+
label: "Inspect",
|
|
227
|
+
description: "Intentionally inspect actors at decision points, after follow-ups, or during diagnosis instead of polling. Core targets are run:<id> and tool:<name>; advanced targets include branch:<run>/<branch>, room:<run>, coordinator, session:<id>, and session:all.",
|
|
228
|
+
parameters: Schema.objectSchema({
|
|
229
|
+
lines: Schema.stringSchema("Line count for tail/messages views. Default 40."),
|
|
230
|
+
status: Schema.stringSchema("Optional session run filter: all, running, active, terminal, done, failed, cancelled, killed, or exited."),
|
|
231
|
+
target: Schema.stringSchema("Actor address to inspect, e.g. run:<id> or tool:<name>; advanced: branch:<run>/<branch>, room:<run>, coordinator, session:<id>, session:all."),
|
|
232
|
+
verbose: Schema.booleanSchema("Return full JSON instead of compact text where available."),
|
|
233
|
+
view: Schema.stringSchema("Inspection view. Core run views: status, tail, messages, artifacts, files, mailbox. Advanced views include communication, roster, and contacts."),
|
|
234
|
+
}, ["target", "view"]),
|
|
235
|
+
async execute(_toolCallId, params, _signal, _onUpdate, ctx) {
|
|
236
|
+
const input = asRecord(params);
|
|
237
|
+
const target = String(input.target ?? "");
|
|
238
|
+
const view = String(input.view ?? "");
|
|
239
|
+
if (target === "recipes" || target === "recipe-registry") {
|
|
240
|
+
if (view !== "status" &&
|
|
241
|
+
view !== "summary" &&
|
|
242
|
+
view !== "doctor" &&
|
|
243
|
+
view !== "imports") {
|
|
244
|
+
throw new Error("inspect recipes supports view=status, view=summary, view=doctor, or view=imports.");
|
|
245
|
+
}
|
|
246
|
+
const discovered = RecipesDiscovery.discoverRecipeSources([
|
|
247
|
+
{
|
|
248
|
+
root: deps.recipeRoot ?? Paths.getRecipeRoot(),
|
|
249
|
+
defaultTool: true,
|
|
250
|
+
mutableUsage: true,
|
|
251
|
+
},
|
|
252
|
+
{ root: deps.packagedRecipeRoot ?? Paths.getPackagedRecipeRoot() },
|
|
253
|
+
]);
|
|
254
|
+
const recipeRoot = deps.recipeRoot ?? Paths.getRecipeRoot();
|
|
255
|
+
const summaryBase = {
|
|
256
|
+
...RecipesDiscovery.summarizeDiscovery(discovered),
|
|
257
|
+
drafts: RecipesDiscovery.listDraftRecipes(join(recipeRoot, "drafts")),
|
|
258
|
+
};
|
|
259
|
+
const summary = {
|
|
260
|
+
...summaryBase,
|
|
261
|
+
next_actions: ToolsResponse.recipeRegistryNextActions(summaryBase, view),
|
|
262
|
+
};
|
|
263
|
+
return {
|
|
264
|
+
content: [
|
|
265
|
+
{
|
|
266
|
+
type: "text",
|
|
267
|
+
text: maybeJsonText(summary, input.verbose === true, view === "doctor"
|
|
268
|
+
? ToolsResponse.compactRecipeDoctor(summary)
|
|
269
|
+
: view === "imports"
|
|
270
|
+
? ToolsResponse.compactRecipeImports(summary)
|
|
271
|
+
: ToolsResponse.compactRecipeRegistry(summary)),
|
|
272
|
+
},
|
|
273
|
+
],
|
|
274
|
+
details: summary,
|
|
275
|
+
};
|
|
276
|
+
}
|
|
277
|
+
const address = Messages.parseActorAddress(target);
|
|
278
|
+
if (address.kind === "coordinator") {
|
|
279
|
+
if (view !== "status" && view !== "runs") {
|
|
280
|
+
throw new Error("inspect coordinator supports view=status or view=runs.");
|
|
281
|
+
}
|
|
282
|
+
const session = ToolsAccess.requireContextSessionId(ctx, "inspect coordinator");
|
|
283
|
+
const allRuns = AsyncRuns.listRuns(undefined, typeof input.status === "string" ? input.status : undefined).map((run) => AsyncRuns.getRunStatus(String(run.state_dir)));
|
|
284
|
+
const runs = allRuns.filter((run) => run.ownerId === session);
|
|
285
|
+
const sessionSummary = summarizeOtherSessions(session, allRuns);
|
|
286
|
+
return {
|
|
287
|
+
content: [
|
|
288
|
+
{
|
|
289
|
+
type: "text",
|
|
290
|
+
text: maybeJsonText({ session, runs, ...sessionSummary }, input.verbose === true, compactSessionRuns(session, runs, sessionSummary)),
|
|
291
|
+
},
|
|
292
|
+
],
|
|
293
|
+
details: { session, runs, ...sessionSummary },
|
|
294
|
+
};
|
|
295
|
+
}
|
|
296
|
+
if (address.kind === "session") {
|
|
297
|
+
if (view !== "status" && view !== "runs") {
|
|
298
|
+
throw new Error("inspect session:<id> supports view=status or view=runs.");
|
|
299
|
+
}
|
|
300
|
+
const allRuns = AsyncRuns.listRuns(undefined, typeof input.status === "string" ? input.status : undefined).map((run) => AsyncRuns.getRunStatus(String(run.state_dir)));
|
|
301
|
+
const runs = allRuns.filter((run) => address.value === "all" || run.ownerId === address.value);
|
|
302
|
+
const sessionSummary = address.value === "all"
|
|
303
|
+
? {}
|
|
304
|
+
: summarizeOtherSessions(address.value || "", allRuns);
|
|
305
|
+
return {
|
|
306
|
+
content: [
|
|
307
|
+
{
|
|
308
|
+
type: "text",
|
|
309
|
+
text: maybeJsonText({ session: address.value, runs, ...sessionSummary }, input.verbose === true, compactSessionRuns(address.value || "", runs, sessionSummary)),
|
|
310
|
+
},
|
|
311
|
+
],
|
|
312
|
+
details: { session: address.value, runs, ...sessionSummary },
|
|
313
|
+
};
|
|
314
|
+
}
|
|
315
|
+
if (address.kind === "tool" && address.value) {
|
|
316
|
+
if (address.value === "pi-actors") {
|
|
317
|
+
if (view !== "status") {
|
|
318
|
+
throw new Error("inspect tool:pi-actors supports view=status.");
|
|
319
|
+
}
|
|
320
|
+
const details = getPiActorsRuntimeStatus();
|
|
321
|
+
return {
|
|
322
|
+
content: [
|
|
323
|
+
{
|
|
324
|
+
type: "text",
|
|
325
|
+
text: maybeJsonText(details, input.verbose === true, compactPiActorsRuntimeStatus(details)),
|
|
326
|
+
},
|
|
327
|
+
],
|
|
328
|
+
details,
|
|
329
|
+
};
|
|
330
|
+
}
|
|
331
|
+
if (view !== "status" && view !== "schema") {
|
|
332
|
+
throw new Error("inspect tool:<name> supports view=status or view=schema.");
|
|
333
|
+
}
|
|
334
|
+
const tool = deps.getTool?.(address.value);
|
|
335
|
+
if (!tool)
|
|
336
|
+
throw new Error(`tool actor not found: ${address.value}`);
|
|
337
|
+
const details = {
|
|
338
|
+
name: address.value,
|
|
339
|
+
description: tool.description,
|
|
340
|
+
parameters: tool.parameters,
|
|
341
|
+
promptSnippet: tool.promptSnippet,
|
|
342
|
+
};
|
|
343
|
+
return {
|
|
344
|
+
content: [
|
|
345
|
+
{
|
|
346
|
+
type: "text",
|
|
347
|
+
text: maybeJsonText(details, input.verbose === true || view === "schema", compactToolActor(address.value, details)),
|
|
348
|
+
},
|
|
349
|
+
],
|
|
350
|
+
details,
|
|
351
|
+
};
|
|
352
|
+
}
|
|
353
|
+
if (address.kind === "room" && address.value && address.room) {
|
|
354
|
+
const status = ToolsAccess.assertRunAccessibleToContext(address.value, ctx);
|
|
355
|
+
const stateDir = String(status.state_dir ?? "");
|
|
356
|
+
if (!stateDir)
|
|
357
|
+
throw new Error(`room:${address.value} has no run state directory.`);
|
|
358
|
+
if (view === "status") {
|
|
359
|
+
const status = Rooms.getRoomStatus(stateDir, address.room);
|
|
360
|
+
return {
|
|
361
|
+
content: [
|
|
362
|
+
{
|
|
363
|
+
type: "text",
|
|
364
|
+
text: maybeJsonText(status, input.verbose === true, compactRoomStatus(status)),
|
|
365
|
+
},
|
|
366
|
+
],
|
|
367
|
+
details: status,
|
|
368
|
+
};
|
|
369
|
+
}
|
|
370
|
+
if (view === "previews") {
|
|
371
|
+
const previews = Rooms.readRoomMessagePreviews(stateDir, address.room, Number(input.lines || Limits.DEFAULT_INSPECT_LINES));
|
|
372
|
+
return {
|
|
373
|
+
content: [
|
|
374
|
+
{
|
|
375
|
+
type: "text",
|
|
376
|
+
text: maybeJsonText(previews, input.verbose === true, compactRoomPreviews(previews)),
|
|
377
|
+
},
|
|
378
|
+
],
|
|
379
|
+
details: { previews },
|
|
380
|
+
};
|
|
381
|
+
}
|
|
382
|
+
if (view === "messages") {
|
|
383
|
+
const messages = Rooms.readRoomMessages(stateDir, address.room, Number(input.lines || Limits.DEFAULT_INSPECT_LINES));
|
|
384
|
+
return {
|
|
385
|
+
content: [
|
|
386
|
+
{
|
|
387
|
+
type: "text",
|
|
388
|
+
text: maybeJsonText(messages, input.verbose === true, compactRoomMessages(messages)),
|
|
389
|
+
},
|
|
390
|
+
],
|
|
391
|
+
details: { messages },
|
|
392
|
+
};
|
|
393
|
+
}
|
|
394
|
+
if (view === "contacts") {
|
|
395
|
+
const contacts = Rooms.readRoomContacts(stateDir, address.room);
|
|
396
|
+
return {
|
|
397
|
+
content: [
|
|
398
|
+
{
|
|
399
|
+
type: "text",
|
|
400
|
+
text: maybeJsonText(contacts, input.verbose === true, compactRoomContacts(contacts)),
|
|
401
|
+
},
|
|
402
|
+
],
|
|
403
|
+
details: { contacts },
|
|
404
|
+
};
|
|
405
|
+
}
|
|
406
|
+
if (view === "roster") {
|
|
407
|
+
const roster = Rooms.readRoomRoster(stateDir, address.room);
|
|
408
|
+
return {
|
|
409
|
+
content: [
|
|
410
|
+
{
|
|
411
|
+
type: "text",
|
|
412
|
+
text: maybeJsonText(roster, input.verbose === true, compactRoomRoster(roster)),
|
|
413
|
+
},
|
|
414
|
+
],
|
|
415
|
+
details: { roster },
|
|
416
|
+
};
|
|
417
|
+
}
|
|
418
|
+
throw new Error("inspect room:<run> supports view=status, view=messages, view=previews, view=roster, or view=contacts.");
|
|
419
|
+
}
|
|
420
|
+
const runId = address.kind === "run" || address.kind === "branch"
|
|
421
|
+
? address.value
|
|
422
|
+
: undefined;
|
|
423
|
+
if (!runId)
|
|
424
|
+
throw new Error("inspect target must be run:<id>, branch:<run>/<branch>, coordinator, session:<id>, or tool:<name>.");
|
|
425
|
+
if (address.kind === "branch") {
|
|
426
|
+
if (view !== "mailbox")
|
|
427
|
+
throw new Error("inspect branch:<run>/<branch> supports view=mailbox.");
|
|
428
|
+
const status = ToolsAccess.assertRunAccessibleToContext(runId, ctx);
|
|
429
|
+
const branchInbox = Rooms.readBranchInboxDiagnostics(String(status.state_dir ?? ""), runId, target, Number(input.lines || Limits.DEFAULT_INSPECT_LINES));
|
|
430
|
+
const messages = branchInbox.messages;
|
|
431
|
+
return {
|
|
432
|
+
content: [
|
|
433
|
+
{
|
|
434
|
+
type: "text",
|
|
435
|
+
text: maybeJsonText(input.verbose === true ? branchInbox : messages, input.verbose === true, `${ToolsResponse.compactBranchInbox(messages.map((message) => ({ ...message })))}${branchInbox.corrupted > 0 ? `\ncorrupted=${branchInbox.corrupted}` : ""}`),
|
|
436
|
+
},
|
|
437
|
+
],
|
|
438
|
+
details: { corrupted: branchInbox.corrupted, messages },
|
|
439
|
+
};
|
|
440
|
+
}
|
|
441
|
+
switch (view) {
|
|
442
|
+
case "status": {
|
|
443
|
+
const status = ToolsAccess.assertRunAccessibleToContext(runId, ctx);
|
|
444
|
+
return {
|
|
445
|
+
content: [
|
|
446
|
+
{
|
|
447
|
+
type: "text",
|
|
448
|
+
text: maybeJsonText(status, input.verbose === true, ToolsResponse.compactAsyncRunStatus(status)),
|
|
449
|
+
},
|
|
450
|
+
],
|
|
451
|
+
details: status,
|
|
452
|
+
};
|
|
453
|
+
}
|
|
454
|
+
case "tail": {
|
|
455
|
+
ToolsAccess.assertRunAccessibleToContext(runId, ctx);
|
|
456
|
+
const text = AsyncRuns.tailRun(runId, Number(input.lines || Limits.DEFAULT_INSPECT_LINES));
|
|
457
|
+
return {
|
|
458
|
+
content: [{ type: "text", text: `\n${text}` }],
|
|
459
|
+
details: {},
|
|
460
|
+
};
|
|
461
|
+
}
|
|
462
|
+
case "messages": {
|
|
463
|
+
ToolsAccess.assertRunAccessibleToContext(runId, ctx);
|
|
464
|
+
const messages = AsyncRuns.readRunEvents(runId, Number(input.lines || Limits.DEFAULT_INSPECT_LINES));
|
|
465
|
+
return {
|
|
466
|
+
content: [
|
|
467
|
+
{
|
|
468
|
+
type: "text",
|
|
469
|
+
text: maybeJsonText(messages, input.verbose === true, compactRunMessages(messages)),
|
|
470
|
+
},
|
|
471
|
+
],
|
|
472
|
+
details: { messages },
|
|
473
|
+
};
|
|
474
|
+
}
|
|
475
|
+
case "artifacts":
|
|
476
|
+
case "files": {
|
|
477
|
+
const status = ToolsAccess.assertRunAccessibleToContext(runId, ctx);
|
|
478
|
+
const artifactManifest = AsyncRuns.resolveArtifactManifest(status.artifacts);
|
|
479
|
+
const details = artifactManifest
|
|
480
|
+
? {
|
|
481
|
+
...status,
|
|
482
|
+
artifact_manifest: artifactManifest,
|
|
483
|
+
next_actions: ToolsResponse.artifactNextActions(status.run ?? runId, asRecord(status.artifacts)),
|
|
484
|
+
}
|
|
485
|
+
: status;
|
|
486
|
+
return {
|
|
487
|
+
content: [
|
|
488
|
+
{
|
|
489
|
+
type: "text",
|
|
490
|
+
text: maybeJsonText(details, input.verbose === true, compactActorFiles(status)),
|
|
491
|
+
},
|
|
492
|
+
],
|
|
493
|
+
details,
|
|
494
|
+
};
|
|
495
|
+
}
|
|
496
|
+
case "mailbox": {
|
|
497
|
+
const status = ToolsAccess.assertRunAccessibleToContext(runId, ctx);
|
|
498
|
+
const mailbox = asRecord(status.mailbox);
|
|
499
|
+
const normalizedMailbox = ToolsMailbox.normalizeMailboxContracts(mailbox);
|
|
500
|
+
const messages = AsyncRuns.readRunInboxMessages(runId, Number(input.lines || Limits.DEFAULT_INSPECT_LINES));
|
|
501
|
+
const details = {
|
|
502
|
+
mailbox,
|
|
503
|
+
normalized_mailbox: normalizedMailbox,
|
|
504
|
+
messages,
|
|
505
|
+
};
|
|
506
|
+
return {
|
|
507
|
+
content: [
|
|
508
|
+
{
|
|
509
|
+
type: "text",
|
|
510
|
+
text: maybeJsonText(details, input.verbose === true, ToolsResponse.compactRunMailbox(String(status.run ?? runId), mailbox, messages)),
|
|
511
|
+
},
|
|
512
|
+
],
|
|
513
|
+
details,
|
|
514
|
+
};
|
|
515
|
+
}
|
|
516
|
+
case "communication": {
|
|
517
|
+
const status = ToolsAccess.assertRunAccessibleToContext(runId, ctx);
|
|
518
|
+
const snapshot = Rooms.readCommunicationSnapshot(String(status.state_dir ?? ""));
|
|
519
|
+
return {
|
|
520
|
+
content: [
|
|
521
|
+
{
|
|
522
|
+
type: "text",
|
|
523
|
+
text: maybeJsonText(snapshot ?? {}, input.verbose === true, compactCommunicationSnapshot(snapshot)),
|
|
524
|
+
},
|
|
525
|
+
],
|
|
526
|
+
details: { communication: snapshot },
|
|
527
|
+
};
|
|
528
|
+
}
|
|
529
|
+
default:
|
|
530
|
+
throw new Error("inspect view must be one of: status, tail, messages, artifacts, files, mailbox, communication; branch targets support mailbox.");
|
|
531
|
+
}
|
|
532
|
+
},
|
|
533
|
+
};
|
|
534
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Local tool definition behavior
|
|
3
|
+
* Zones: user recipe tools, generated schemas, async recipe launch
|
|
4
|
+
* Owns wrapping saved local capabilities as executable pi tools
|
|
5
|
+
*/
|
|
6
|
+
import type { RegisteredTool } from "./config.ts";
|
|
7
|
+
import * as Execution from "./execution.ts";
|
|
8
|
+
export interface RuntimeToolContext {
|
|
9
|
+
cwd: string;
|
|
10
|
+
sessionManager?: {
|
|
11
|
+
getSessionId?: () => string;
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
export declare function createRuntimeToolDefinition(cfg: RegisteredTool, exec: Execution.RegisteredToolExec): any;
|