@llblab/pi-actors 0.42.3 → 0.43.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 +127 -175
- package/BACKLOG.md +189 -1
- package/CHANGELOG.md +183 -292
- package/README.md +115 -276
- package/dist/fixtures/protocol/control-endpoint.json +6 -0
- package/dist/fixtures/protocol/control-record.json +9 -0
- package/dist/fixtures/protocol/recipe-summary.json +4 -12
- package/dist/fixtures/protocol/trace-event.json +9 -0
- package/dist/index.js +1 -1
- package/dist/lib/async-runs.d.ts +15 -38
- package/dist/lib/async-runs.js +173 -111
- package/dist/lib/automatic-review-runtime.d.ts +1 -1
- package/dist/lib/automatic-review-runtime.js +5 -5
- package/dist/lib/command-templates.d.ts +2 -0
- package/dist/lib/command-templates.js +38 -4
- package/dist/lib/control-projection.d.ts +20 -0
- package/dist/lib/control-projection.js +66 -0
- package/dist/lib/control.d.ts +15 -0
- package/dist/lib/control.js +97 -0
- package/dist/lib/draft-sleep.js +3 -3
- package/dist/lib/execution-sessions.d.ts +17 -0
- package/dist/lib/execution-sessions.js +85 -0
- package/dist/lib/file-state.d.ts +2 -0
- package/dist/lib/file-state.js +114 -46
- package/dist/lib/inspector-actions.d.ts +2 -2
- package/dist/lib/inspector-actions.js +2 -2
- package/dist/lib/inspector-command.js +3 -3
- package/dist/lib/inspector-overlay.d.ts +54 -70
- package/dist/lib/inspector-overlay.js +576 -910
- package/dist/lib/inspector.d.ts +3 -71
- package/dist/lib/inspector.js +19 -665
- package/dist/lib/limits.d.ts +7 -3
- package/dist/lib/limits.js +7 -3
- package/dist/lib/observability.d.ts +16 -16
- package/dist/lib/observability.js +43 -82
- package/dist/lib/prompts.d.ts +1 -1
- package/dist/lib/prompts.js +3 -3
- package/dist/lib/recipe-control.d.ts +7 -0
- package/dist/lib/recipe-control.js +43 -0
- package/dist/lib/recipes-discovery.js +2 -0
- package/dist/lib/recipes-references.d.ts +1 -14
- package/dist/lib/recipes-references.js +6 -21
- package/dist/lib/review-control.d.ts +1 -1
- package/dist/lib/review-control.js +4 -5
- package/dist/lib/review-projection.js +1 -5
- package/dist/lib/run-ui-runtime.js +2 -2
- package/dist/lib/runs-control-delivery.d.ts +28 -0
- package/dist/lib/runs-control-delivery.js +150 -0
- package/dist/lib/runs-controls.d.ts +37 -0
- package/dist/lib/runs-controls.js +146 -0
- package/dist/lib/runs-retention.d.ts +7 -0
- package/dist/lib/runs-retention.js +27 -3
- package/dist/lib/runs-start.js +4 -2
- package/dist/lib/runs-status.js +11 -6
- package/dist/lib/runs-trace.d.ts +24 -0
- package/dist/lib/runs-trace.js +102 -0
- package/dist/lib/runtime-identity.d.ts +7 -0
- package/dist/lib/runtime-identity.js +35 -0
- package/dist/lib/runtime-notifier.d.ts +1 -1
- package/dist/lib/runtime-notifier.js +1 -1
- package/dist/lib/runtime-triage.d.ts +29 -0
- package/dist/lib/runtime-triage.js +76 -0
- package/dist/lib/tool-review-scheduler.js +7 -7
- package/dist/lib/tools-inspect.d.ts +3 -3
- package/dist/lib/tools-inspect.js +241 -707
- package/dist/lib/tools-local.js +2 -10
- package/dist/lib/tools-message.d.ts +6 -7
- package/dist/lib/tools-message.js +95 -396
- package/dist/lib/tools-response.d.ts +1 -5
- package/dist/lib/tools-response.js +5 -48
- package/dist/lib/tools-spawn.js +16 -28
- package/dist/lib/tools.d.ts +1 -1
- package/dist/lib/tools.js +2 -3
- package/dist/lib/trace-projection.d.ts +22 -0
- package/dist/lib/trace-projection.js +185 -0
- package/dist/recipes/draft-review.json +0 -10
- package/dist/recipes/lens-swarm.json +0 -14
- package/dist/recipes/music-player.json +10 -19
- package/dist/recipes/pipeline-architect-coordinator.json +0 -11
- package/dist/recipes/pipeline-artifact-bundle.json +1 -22
- package/dist/recipes/pipeline-artifact-report.json +1 -18
- package/dist/recipes/pipeline-artifact-write.json +1 -18
- package/dist/recipes/pipeline-async-run-ops.json +0 -12
- package/dist/recipes/pipeline-checkpoint-continuation.json +0 -14
- package/dist/recipes/pipeline-development-tasking.json +0 -12
- package/dist/recipes/pipeline-docs-maintenance.json +0 -12
- package/dist/recipes/pipeline-media-library.json +0 -12
- package/dist/recipes/pipeline-quorum-review.json +0 -12
- package/dist/recipes/pipeline-release-readiness.json +0 -12
- package/dist/recipes/pipeline-release-summary.json +0 -12
- package/dist/recipes/pipeline-repo-health.json +0 -12
- package/dist/recipes/pipeline-research-synthesis.json +0 -11
- package/dist/recipes/pipeline-review-readiness.json +0 -12
- package/dist/recipes/resource-locker.json +27 -0
- package/dist/recipes/subagent-artifact.json +0 -9
- package/dist/recipes/subagent-checkpoint.json +0 -10
- package/dist/recipes/subagent-conflict-report.json +0 -11
- package/dist/recipes/subagent-contradiction-map.json +0 -11
- package/dist/recipes/subagent-critic.json +0 -11
- package/dist/recipes/subagent-evidence-map.json +0 -11
- package/dist/recipes/subagent-followup.json +0 -10
- package/dist/recipes/subagent-judge.json +0 -11
- package/dist/recipes/subagent-merge.json +0 -11
- package/dist/recipes/subagent-normalize.json +0 -11
- package/dist/recipes/subagent-plan.json +0 -11
- package/dist/recipes/subagent-preflight.json +0 -11
- package/dist/recipes/subagent-prompt.json +0 -10
- package/dist/recipes/subagent-quorum.json +0 -10
- package/dist/recipes/subagent-review-coordinator.json +0 -14
- package/dist/recipes/subagent-review.json +0 -11
- package/dist/recipes/subagent-task-card.json +0 -11
- package/dist/recipes/subagent-tools.json +0 -10
- package/dist/recipes/subagent-verify.json +0 -11
- package/dist/recipes/subagents-prompts.json +0 -10
- package/dist/recipes/tool-review.json +0 -10
- package/dist/scripts/async-runner.mjs +25 -25
- package/dist/scripts/conformance.mjs +4 -2
- package/dist/scripts/locker.mjs +196 -69
- package/dist/scripts/music-player.mjs +162 -159
- package/dist/scripts/recipe-utils.mjs +6 -96
- package/dist/scripts/release-gates.mjs +91 -0
- package/dist/scripts/validate-recipe.mjs +8 -57
- package/dist/skills/actors/SKILL.md +57 -265
- package/dist/skills/swarm/SKILL.md +10 -34
- package/docs/0.43-baseline.md +39 -0
- package/docs/README.md +4 -6
- package/docs/actor-inspector.md +26 -64
- package/docs/async-runs.md +81 -328
- package/docs/command-templates.md +8 -118
- package/docs/recipe-library.md +55 -182
- package/docs/releasing.md +28 -0
- package/docs/template-recipes.md +76 -289
- package/docs/tool-registry.md +41 -161
- package/fixtures/protocol/control-endpoint.json +6 -0
- package/fixtures/protocol/control-record.json +9 -0
- package/fixtures/protocol/recipe-summary.json +4 -12
- package/fixtures/protocol/trace-event.json +9 -0
- package/index.ts +1 -1
- package/lib/async-runs.ts +218 -204
- package/lib/automatic-review-runtime.ts +7 -7
- package/lib/command-templates.ts +44 -4
- package/lib/control-projection.ts +105 -0
- package/lib/control.ts +117 -0
- package/lib/draft-sleep.ts +3 -3
- package/lib/execution-sessions.ts +111 -0
- package/lib/file-state.ts +84 -64
- package/lib/inspector-actions.ts +2 -2
- package/lib/inspector-command.ts +3 -3
- package/lib/inspector-overlay.ts +617 -1126
- package/lib/inspector.ts +46 -979
- package/lib/limits.ts +7 -3
- package/lib/observability.ts +60 -101
- package/lib/prompts.ts +3 -3
- package/lib/recipe-control.ts +52 -0
- package/lib/recipes-discovery.ts +2 -0
- package/lib/recipes-references.ts +9 -45
- package/lib/review-control.ts +4 -5
- package/lib/review-projection.ts +1 -5
- package/lib/run-ui-runtime.ts +2 -2
- package/lib/runs-control-delivery.ts +209 -0
- package/lib/runs-controls.ts +213 -0
- package/lib/runs-retention.ts +38 -3
- package/lib/runs-start.ts +4 -2
- package/lib/runs-status.ts +11 -6
- package/lib/runs-trace.ts +136 -0
- package/lib/runtime-identity.ts +39 -0
- package/lib/runtime-notifier.ts +1 -1
- package/lib/runtime-triage.ts +120 -0
- package/lib/tool-review-scheduler.ts +7 -7
- package/lib/tools-inspect.ts +283 -900
- package/lib/tools-local.ts +2 -12
- package/lib/tools-message.ts +112 -520
- package/lib/tools-response.ts +5 -64
- package/lib/tools-spawn.ts +16 -32
- package/lib/tools.ts +5 -6
- package/lib/trace-projection.ts +244 -0
- package/package.json +2 -1
- package/recipes/draft-review.json +0 -10
- package/recipes/lens-swarm.json +0 -14
- package/recipes/music-player.json +10 -19
- package/recipes/pipeline-architect-coordinator.json +0 -11
- package/recipes/pipeline-artifact-bundle.json +1 -22
- package/recipes/pipeline-artifact-report.json +1 -18
- package/recipes/pipeline-artifact-write.json +1 -18
- package/recipes/pipeline-async-run-ops.json +0 -12
- package/recipes/pipeline-checkpoint-continuation.json +0 -14
- package/recipes/pipeline-development-tasking.json +0 -12
- package/recipes/pipeline-docs-maintenance.json +0 -12
- package/recipes/pipeline-media-library.json +0 -12
- package/recipes/pipeline-quorum-review.json +0 -12
- package/recipes/pipeline-release-readiness.json +0 -12
- package/recipes/pipeline-release-summary.json +0 -12
- package/recipes/pipeline-repo-health.json +0 -12
- package/recipes/pipeline-research-synthesis.json +0 -11
- package/recipes/pipeline-review-readiness.json +0 -12
- package/recipes/resource-locker.json +27 -0
- package/recipes/subagent-artifact.json +0 -9
- package/recipes/subagent-checkpoint.json +0 -10
- package/recipes/subagent-conflict-report.json +0 -11
- package/recipes/subagent-contradiction-map.json +0 -11
- package/recipes/subagent-critic.json +0 -11
- package/recipes/subagent-evidence-map.json +0 -11
- package/recipes/subagent-followup.json +0 -10
- package/recipes/subagent-judge.json +0 -11
- package/recipes/subagent-merge.json +0 -11
- package/recipes/subagent-normalize.json +0 -11
- package/recipes/subagent-plan.json +0 -11
- package/recipes/subagent-preflight.json +0 -11
- package/recipes/subagent-prompt.json +0 -10
- package/recipes/subagent-quorum.json +0 -10
- package/recipes/subagent-review-coordinator.json +0 -14
- package/recipes/subagent-review.json +0 -11
- package/recipes/subagent-task-card.json +0 -11
- package/recipes/subagent-tools.json +0 -10
- package/recipes/subagent-verify.json +0 -11
- package/recipes/subagents-prompts.json +0 -10
- package/recipes/tool-review.json +0 -10
- package/scripts/async-runner.mjs +25 -25
- package/scripts/conformance.mjs +4 -2
- package/scripts/locker.mjs +196 -69
- package/scripts/music-player.mjs +162 -159
- package/scripts/recipe-utils.mjs +6 -96
- package/scripts/release-gates.mjs +91 -0
- package/scripts/validate-recipe.mjs +8 -57
- package/skills/actors/SKILL.md +57 -265
- package/skills/swarm/SKILL.md +10 -34
- package/dist/fixtures/protocol/actor-message-branch.json +0 -13
- package/dist/fixtures/protocol/mailbox-contract.json +0 -15
- package/dist/fixtures/protocol/room-message.json +0 -11
- package/dist/fixtures/protocol/room-roster.json +0 -11
- package/dist/fixtures/protocol/run-inbox-message.json +0 -9
- package/dist/fixtures/protocol/run-outbox-event.json +0 -9
- package/dist/lib/mailbox-loop.d.ts +0 -41
- package/dist/lib/mailbox-loop.js +0 -60
- package/dist/lib/messages.d.ts +0 -25
- package/dist/lib/messages.js +0 -122
- package/dist/lib/rooms.d.ts +0 -104
- package/dist/lib/rooms.js +0 -647
- package/dist/lib/runs-mailbox.d.ts +0 -25
- package/dist/lib/runs-mailbox.js +0 -146
- package/dist/lib/runs-messages.d.ts +0 -15
- package/dist/lib/runs-messages.js +0 -179
- package/dist/lib/runs-outbox.d.ts +0 -41
- package/dist/lib/runs-outbox.js +0 -87
- package/dist/lib/tools-mailbox.d.ts +0 -8
- package/dist/lib/tools-mailbox.js +0 -48
- package/dist/recipes/actor-worker.json +0 -39
- package/dist/recipes/coordinator-locker.json +0 -45
- package/dist/recipes/locker.json +0 -45
- package/dist/recipes/pipeline-room-swarm.json +0 -50
- package/dist/recipes/subagent-message.json +0 -32
- package/dist/recipes/utility-actor-message.json +0 -23
- package/dist/scripts/actor-worker.mjs +0 -214
- package/dist/scripts/coordinator.mjs +0 -799
- package/docs/actor-messages.md +0 -225
- package/docs/actors-deep-reference.md +0 -66
- package/docs/component-recipes.md +0 -148
- package/docs/task-first-recipes.md +0 -263
- package/fixtures/protocol/actor-message-branch.json +0 -13
- package/fixtures/protocol/mailbox-contract.json +0 -15
- package/fixtures/protocol/room-message.json +0 -11
- package/fixtures/protocol/room-roster.json +0 -11
- package/fixtures/protocol/run-inbox-message.json +0 -9
- package/fixtures/protocol/run-outbox-event.json +0 -9
- package/lib/mailbox-loop.ts +0 -144
- package/lib/messages.ts +0 -151
- package/lib/rooms.ts +0 -939
- package/lib/runs-mailbox.ts +0 -208
- package/lib/runs-messages.ts +0 -252
- package/lib/runs-outbox.ts +0 -144
- package/lib/tools-mailbox.ts +0 -56
- package/recipes/actor-worker.json +0 -39
- package/recipes/coordinator-locker.json +0 -45
- package/recipes/locker.json +0 -45
- package/recipes/pipeline-room-swarm.json +0 -50
- package/recipes/subagent-message.json +0 -32
- package/recipes/utility-actor-message.json +0 -23
- package/scripts/actor-worker.mjs +0 -214
- package/scripts/coordinator.mjs +0 -799
package/lib/tools-inspect.ts
CHANGED
|
@@ -1,489 +1,311 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Public inspect tool behavior
|
|
3
|
-
* Zones:
|
|
4
|
-
* Owns
|
|
2
|
+
* Public inspect tool behavior.
|
|
3
|
+
* Zones: Run Recipe/Trace/Control views and runtime/recipe/tool diagnostics
|
|
4
|
+
* Owns exact inspect target/view dispatch; source projection stays in domain modules.
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
import {
|
|
8
|
-
import { existsSync, readFileSync } from "node:fs";
|
|
9
|
-
import { dirname, join } from "node:path";
|
|
10
|
-
import { fileURLToPath } from "node:url";
|
|
7
|
+
import { join } from "node:path";
|
|
11
8
|
|
|
12
9
|
import * as AsyncRuns from "./async-runs.ts";
|
|
10
|
+
import * as ControlProjection from "./control-projection.ts";
|
|
11
|
+
import * as Inspector from "./inspector.ts";
|
|
13
12
|
import * as Limits from "./limits.ts";
|
|
14
|
-
import * as Messages from "./messages.ts";
|
|
15
13
|
import * as Paths from "./paths.ts";
|
|
16
14
|
import * as RecipesDiscovery from "./recipes-discovery.ts";
|
|
17
15
|
import * as ReviewDiagnostics from "./review-diagnostics.ts";
|
|
18
|
-
import * as
|
|
16
|
+
import * as RunsControls from "./runs-controls.ts";
|
|
17
|
+
import * as RunControlDelivery from "./runs-control-delivery.ts";
|
|
18
|
+
import * as RunsTrace from "./runs-trace.ts";
|
|
19
|
+
import * as RuntimeIdentity from "./runtime-identity.ts";
|
|
20
|
+
import * as RuntimeTriage from "./runtime-triage.ts";
|
|
19
21
|
import * as Schema from "./schema.ts";
|
|
20
22
|
import * as ToolsAccess from "./tools-access.ts";
|
|
21
|
-
import * as ToolsMailbox from "./tools-mailbox.ts";
|
|
22
23
|
import * as ToolsResponse from "./tools-response.ts";
|
|
24
|
+
import * as TraceProjection from "./trace-projection.ts";
|
|
23
25
|
|
|
24
26
|
const asRecord = ToolsResponse.asRecord;
|
|
25
27
|
const maybeJsonText = ToolsResponse.maybeJsonText;
|
|
26
28
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
`automatic_reviews draft=${String(draft.phase ?? "idle")} tool=${String(tool.phase ?? "idle")}`,
|
|
34
|
-
`lineages=${String(diagnostics.lineage_count ?? 0)} revision_snapshots=${String(diagnostics.revision_snapshots ?? 0)}`,
|
|
35
|
-
].join("\n");
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
function compactRunMessages(messages: AsyncRuns.RunOutboxEvent[]): string {
|
|
39
|
-
if (messages.length === 0) return "\n(no actor messages)";
|
|
40
|
-
return `\n${messages
|
|
41
|
-
.map((message) =>
|
|
42
|
-
[
|
|
43
|
-
`run=${message.run}`,
|
|
44
|
-
`type=${message.event}`,
|
|
45
|
-
`level=${message.level}`,
|
|
46
|
-
`summary=${message.summary.replaceAll(/\s+/g, "_")}`,
|
|
47
|
-
].join(" "),
|
|
48
|
-
)
|
|
49
|
-
.join("\n")}`;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
function compactRoomPreviews(previews: Rooms.RoomMessagePreview[]): string {
|
|
53
|
-
if (previews.length === 0) return "\n(no room message previews)";
|
|
54
|
-
return `\n${previews
|
|
55
|
-
.map((preview) =>
|
|
56
|
-
[
|
|
57
|
-
`ts=${preview.timestamp}`,
|
|
58
|
-
preview.from ? `from=${preview.from}` : "",
|
|
59
|
-
`to=${preview.to}`,
|
|
60
|
-
`type=${preview.type}`,
|
|
61
|
-
preview.summary
|
|
62
|
-
? `summary=${ToolsResponse.compactPreview(preview.summary)}`
|
|
63
|
-
: "",
|
|
64
|
-
preview.body_preview
|
|
65
|
-
? `body=${ToolsResponse.compactPreview(preview.body_preview)}`
|
|
66
|
-
: "",
|
|
67
|
-
]
|
|
68
|
-
.filter(Boolean)
|
|
69
|
-
.join(" "),
|
|
70
|
-
)
|
|
71
|
-
.join("\n")}`;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
function compactRoomMessages(messages: Rooms.RoomTimelineEntry[]): string {
|
|
75
|
-
if (messages.length === 0) return "\n(no room messages)";
|
|
76
|
-
return `\n${messages
|
|
77
|
-
.map((message) =>
|
|
78
|
-
[
|
|
79
|
-
`ts=${message.received_at}`,
|
|
80
|
-
`from=${String(message.from ?? "<unknown>")}`,
|
|
81
|
-
`to=${message.to}`,
|
|
82
|
-
`type=${message.type}`,
|
|
83
|
-
`summary=${String(message.summary ?? "").replaceAll(/\s+/g, "_")}`,
|
|
84
|
-
ToolsResponse.compactPreview(message.body)
|
|
85
|
-
? `body=${ToolsResponse.compactPreview(message.body)}`
|
|
86
|
-
: "",
|
|
87
|
-
]
|
|
88
|
-
.filter(Boolean)
|
|
89
|
-
.join(" "),
|
|
90
|
-
)
|
|
91
|
-
.join("\n")}`;
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
function compactRoomContacts(contacts: Rooms.RoomContact[]): string {
|
|
95
|
-
if (contacts.length === 0) return "\n(no room contacts)";
|
|
96
|
-
return `\n${contacts
|
|
97
|
-
.map((contact) =>
|
|
98
|
-
[
|
|
99
|
-
`address=${contact.address}`,
|
|
100
|
-
contact.role !== undefined ? `role=${String(contact.role)}` : "",
|
|
101
|
-
contact.parent !== undefined ? `parent=${String(contact.parent)}` : "",
|
|
102
|
-
contact.caps !== undefined
|
|
103
|
-
? `caps=${Array.isArray(contact.caps) ? contact.caps.join(",") : String(contact.caps)}`
|
|
104
|
-
: "",
|
|
105
|
-
contact.claim !== undefined
|
|
106
|
-
? `claim=${String(contact.claim).replaceAll(/\s+/g, "_")}`
|
|
107
|
-
: "",
|
|
108
|
-
contact.status !== undefined ? `status=${String(contact.status)}` : "",
|
|
109
|
-
]
|
|
110
|
-
.filter(Boolean)
|
|
111
|
-
.join(" "),
|
|
112
|
-
)
|
|
113
|
-
.join("\n")}`;
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
function compactRoomRoster(roster: Record<string, Rooms.RoomMember>): string {
|
|
117
|
-
const members = Object.values(roster);
|
|
118
|
-
if (members.length === 0) return "\n(no room members)";
|
|
119
|
-
return `\n${members
|
|
120
|
-
.map((member) =>
|
|
121
|
-
[
|
|
122
|
-
`address=${member.address}`,
|
|
123
|
-
`role=${String(member.role ?? "")}`,
|
|
124
|
-
member.parent !== undefined ? `parent=${String(member.parent)}` : "",
|
|
125
|
-
member.caps !== undefined
|
|
126
|
-
? `caps=${Array.isArray(member.caps) ? member.caps.join(",") : String(member.caps)}`
|
|
127
|
-
: "",
|
|
128
|
-
member.claim !== undefined
|
|
129
|
-
? `claim=${String(member.claim).replaceAll(/\s+/g, "_")}`
|
|
130
|
-
: "",
|
|
131
|
-
`status=${String(member.status ?? "")}`,
|
|
132
|
-
`last_seen=${member.last_seen}`,
|
|
133
|
-
].join(" "),
|
|
134
|
-
)
|
|
135
|
-
.join("\n")}`;
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
function compactRoomStatus(status: Rooms.RoomStatus): string {
|
|
139
|
-
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)}` : ""}`;
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
function compactCommunicationSnapshot(
|
|
143
|
-
snapshot: Rooms.ActorCommunicationSnapshot | undefined,
|
|
144
|
-
): string {
|
|
145
|
-
if (!snapshot) return "\n(no communication snapshot)";
|
|
146
|
-
return `\nself=${snapshot.self} root=${snapshot.root} rooms=${snapshot.rooms.length} updated_at=${snapshot.updated_at}`;
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
function compactArtifactPath(value: unknown): string {
|
|
150
|
-
if (typeof value === "string") return value;
|
|
151
|
-
const record = asRecord(value);
|
|
152
|
-
return String(record.path ?? "<missing>");
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
function readBoundedReviewEvidence(
|
|
156
|
-
status: Record<string, unknown>,
|
|
157
|
-
limit: number,
|
|
158
|
-
): Record<string, unknown> | undefined {
|
|
159
|
-
const evidenceFile = status.evidenceFile;
|
|
160
|
-
if (typeof evidenceFile !== "string" || !existsSync(evidenceFile))
|
|
161
|
-
return undefined;
|
|
162
|
-
try {
|
|
163
|
-
const manifest = asRecord(JSON.parse(readFileSync(evidenceFile, "utf8")));
|
|
164
|
-
const commands = Array.isArray(manifest.commands) ? manifest.commands : [];
|
|
165
|
-
const bounded = commands.slice(-Math.max(1, limit));
|
|
166
|
-
return {
|
|
167
|
-
...manifest,
|
|
168
|
-
commands: bounded,
|
|
169
|
-
commands_total: commands.length,
|
|
170
|
-
...(bounded.length < commands.length ? { commands_truncated: true } : {}),
|
|
171
|
-
};
|
|
172
|
-
} catch {
|
|
173
|
-
return {
|
|
174
|
-
status: "invalid",
|
|
175
|
-
error: "review evidence manifest is unreadable",
|
|
176
|
-
};
|
|
177
|
-
}
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
function compactActorFiles(status: Record<string, unknown>): string {
|
|
181
|
-
const run = String(status.run ?? "<unknown>");
|
|
182
|
-
const artifacts = asRecord(status.artifacts);
|
|
183
|
-
const files = [
|
|
184
|
-
status.stdoutLog,
|
|
185
|
-
status.stderrLog,
|
|
186
|
-
status.eventsFile,
|
|
187
|
-
status.outboxFile,
|
|
188
|
-
status.evidenceFile,
|
|
189
|
-
status.state_dir
|
|
190
|
-
? `${String(status.state_dir)}/communication.json`
|
|
191
|
-
: undefined,
|
|
192
|
-
status.state_dir ? `${String(status.state_dir)}/result.json` : undefined,
|
|
193
|
-
].filter((file): file is string => typeof file === "string");
|
|
194
|
-
const artifactText = Object.keys(artifacts).length
|
|
195
|
-
? ` artifacts=${Object.entries(artifacts)
|
|
196
|
-
.map(([key, value]) => `${key}:${compactArtifactPath(value)}`)
|
|
197
|
-
.join(",")}`
|
|
198
|
-
: "";
|
|
199
|
-
const nextActions = ToolsResponse.artifactNextActions(run, artifacts);
|
|
200
|
-
const nextText = nextActions.length
|
|
201
|
-
? ` next=${nextActions.map((action) => action.replaceAll(/\s+/g, "_")).join("|")}`
|
|
202
|
-
: "";
|
|
203
|
-
return `\nrun=${run}${artifactText}${files.length ? ` files=${files.join(",")}` : ""}${nextText}`;
|
|
29
|
+
export interface InspectToolDeps<TContext = unknown> {
|
|
30
|
+
getRunStatus?: (runOrDir: string) => Record<string, any>;
|
|
31
|
+
getTool?: (name: string) => any | undefined;
|
|
32
|
+
listRuns?: () => Array<Record<string, any>>;
|
|
33
|
+
packagedRecipeRoot?: string;
|
|
34
|
+
recipeRoot?: string;
|
|
204
35
|
}
|
|
205
36
|
|
|
206
|
-
function
|
|
207
|
-
currentSession: string,
|
|
208
|
-
allRuns: Array<Record<string, unknown>>,
|
|
209
|
-
): Record<string, unknown> {
|
|
210
|
-
const otherRuns = allRuns.filter(
|
|
211
|
-
(run) => run.ownerId && run.ownerId !== currentSession,
|
|
212
|
-
);
|
|
37
|
+
function runtimeStatus(): Record<string, unknown> {
|
|
213
38
|
return {
|
|
214
|
-
|
|
215
|
-
|
|
39
|
+
automatic_review: process.env.PI_ACTORS_AUTOMATIC_REVIEW !== "off",
|
|
40
|
+
run_root: Paths.getRunStateRoot(),
|
|
41
|
+
state_schema: RuntimeIdentity.RUN_STATE_SCHEMA,
|
|
42
|
+
version: RuntimeIdentity.getPackageVersion(),
|
|
216
43
|
};
|
|
217
44
|
}
|
|
218
45
|
|
|
219
|
-
function
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
): string {
|
|
224
|
-
const
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
? `other_runs=${String(summary.other_runs)}`
|
|
230
|
-
: "",
|
|
231
|
-
]
|
|
232
|
-
.filter(Boolean)
|
|
233
|
-
.join(" ");
|
|
234
|
-
if (runs.length === 0)
|
|
235
|
-
return `\nsession=${session} runs=0${suffix ? ` ${suffix}` : ""}`;
|
|
236
|
-
return `\nsession=${session} runs=${runs.length}${suffix ? ` ${suffix}` : ""}\n${runs
|
|
46
|
+
function runtimeRuns(
|
|
47
|
+
ctx: unknown,
|
|
48
|
+
deps: InspectToolDeps,
|
|
49
|
+
status: string | undefined,
|
|
50
|
+
): Record<string, unknown> {
|
|
51
|
+
const session = ToolsAccess.getContextSessionId(ctx);
|
|
52
|
+
const listed = deps.listRuns
|
|
53
|
+
? deps.listRuns()
|
|
54
|
+
: AsyncRuns.listRuns(undefined, status);
|
|
55
|
+
const runs = listed
|
|
237
56
|
.map((run) => {
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
return tokens.join(" ");
|
|
57
|
+
try {
|
|
58
|
+
return deps.getRunStatus
|
|
59
|
+
? deps.getRunStatus(String(run.state_dir ?? run.run))
|
|
60
|
+
: AsyncRuns.getRunStatus(String(run.state_dir ?? run.run));
|
|
61
|
+
} catch {
|
|
62
|
+
return run;
|
|
63
|
+
}
|
|
246
64
|
})
|
|
247
|
-
.
|
|
65
|
+
.filter((run) => !session || !run.ownerId || run.ownerId === session);
|
|
66
|
+
return { ...(session ? { owner_session: session } : {}), runs };
|
|
248
67
|
}
|
|
249
68
|
|
|
250
|
-
function
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
const
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
69
|
+
function runtimeTriage(
|
|
70
|
+
ctx: unknown,
|
|
71
|
+
deps: InspectToolDeps,
|
|
72
|
+
): Record<string, unknown> {
|
|
73
|
+
const inventory = runtimeRuns(ctx, deps, undefined);
|
|
74
|
+
const runs = inventory.runs as Array<Record<string, unknown>>;
|
|
75
|
+
const failed = runs.filter((run) => run.status === "failed");
|
|
76
|
+
const pendingControls: RuntimeTriage.RuntimePendingControl[] = [];
|
|
77
|
+
const staleControls: RuntimeTriage.RuntimePendingControl[] = [];
|
|
78
|
+
const controlDiagnostics: Array<Record<string, unknown>> = [];
|
|
79
|
+
const nowMs = Date.now();
|
|
80
|
+
for (const run of runs) {
|
|
81
|
+
const stateDir = typeof run.state_dir === "string" ? run.state_dir : undefined;
|
|
82
|
+
if (!stateDir) continue;
|
|
83
|
+
const runId = String(run.run ?? "unknown");
|
|
84
|
+
const journal = RunsControls.readRunControlJournalFromStateDir(stateDir);
|
|
85
|
+
controlDiagnostics.push(...journal.diagnostics.map((diagnostic) => ({
|
|
86
|
+
...(diagnostic.line === undefined ? {} : { line: diagnostic.line }),
|
|
87
|
+
reason: diagnostic.line === undefined
|
|
88
|
+
? "unreadable_control_journal"
|
|
89
|
+
: "invalid_control_json",
|
|
90
|
+
run: runId,
|
|
91
|
+
})));
|
|
92
|
+
for (const control of journal.records) {
|
|
93
|
+
const classified = RuntimeTriage.classifyRuntimeControl(
|
|
94
|
+
{
|
|
95
|
+
run: runId,
|
|
96
|
+
...(typeof run.run_instance_id === "string"
|
|
97
|
+
? { runInstanceId: run.run_instance_id }
|
|
98
|
+
: {}),
|
|
99
|
+
status: String(run.status ?? "unknown"),
|
|
100
|
+
},
|
|
101
|
+
control,
|
|
102
|
+
nowMs,
|
|
103
|
+
);
|
|
104
|
+
if (classified.pending) pendingControls.push(classified.pending);
|
|
105
|
+
if (classified.stale) staleControls.push(classified.stale);
|
|
106
|
+
if (classified.diagnostic) controlDiagnostics.push({ ...classified.diagnostic });
|
|
107
|
+
}
|
|
272
108
|
}
|
|
273
|
-
const
|
|
109
|
+
const attentionEvents = runs.flatMap((run) => {
|
|
110
|
+
const stateDir = typeof run.state_dir === "string" ? run.state_dir : undefined;
|
|
111
|
+
if (!stateDir) return [];
|
|
112
|
+
return RunsTrace.readRunTraceEvents(stateDir)
|
|
113
|
+
.filter((event) => event.attention === "notify" || event.attention === "followup")
|
|
114
|
+
.map((event) => ({
|
|
115
|
+
run: run.run,
|
|
116
|
+
id: event.id,
|
|
117
|
+
kind: event.kind,
|
|
118
|
+
attention: event.attention,
|
|
119
|
+
summary: event.summary,
|
|
120
|
+
ts: event.ts,
|
|
121
|
+
}));
|
|
122
|
+
});
|
|
123
|
+
const boundedStaleControls = staleControls.slice(0, 40);
|
|
124
|
+
const staleKeys = new Set(boundedStaleControls.map((control) =>
|
|
125
|
+
`${control.run}\0${control.run_instance_id}\0${control.id}`,
|
|
126
|
+
));
|
|
127
|
+
const boundedPendingControls = [
|
|
128
|
+
...boundedStaleControls,
|
|
129
|
+
...pendingControls.filter((control) =>
|
|
130
|
+
!staleKeys.has(`${control.run}\0${control.run_instance_id}\0${control.id}`),
|
|
131
|
+
),
|
|
132
|
+
].slice(0, 40);
|
|
274
133
|
return {
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
134
|
+
...inventory,
|
|
135
|
+
failed_runs: failed,
|
|
136
|
+
pending_control_count: pendingControls.length,
|
|
137
|
+
pending_controls: boundedPendingControls,
|
|
138
|
+
stale_control_count: staleControls.length,
|
|
139
|
+
stale_controls: boundedStaleControls,
|
|
140
|
+
control_diagnostic_count: controlDiagnostics.length,
|
|
141
|
+
control_diagnostics: controlDiagnostics.slice(0, 40),
|
|
142
|
+
attention_events: attentionEvents.slice(-40).reverse(),
|
|
143
|
+
next_actions: [
|
|
144
|
+
...(failed.length ? ["inspect target=runtime view=runs status=failed"] : []),
|
|
145
|
+
...staleControls.slice(0, 3).map((entry) =>
|
|
146
|
+
`inspect target=run:${entry.run} view=control`,
|
|
147
|
+
),
|
|
148
|
+
...(attentionEvents.length
|
|
149
|
+
? attentionEvents.slice(-3).map((entry) =>
|
|
150
|
+
`inspect target=run:${String(entry.run)} view=trace source=runtime`,
|
|
151
|
+
)
|
|
152
|
+
: []),
|
|
153
|
+
],
|
|
284
154
|
};
|
|
285
155
|
}
|
|
286
156
|
|
|
287
|
-
function
|
|
288
|
-
|
|
289
|
-
}
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
return
|
|
157
|
+
function compactRuntime(view: string, details: Record<string, unknown>): string {
|
|
158
|
+
if (view === "runs") {
|
|
159
|
+
return `\nruntime runs=${(details.runs as unknown[] | undefined)?.length ?? 0}`;
|
|
160
|
+
}
|
|
161
|
+
if (view === "triage") {
|
|
162
|
+
return `\nruntime failed=${(details.failed_runs as unknown[] | undefined)?.length ?? 0} pending_controls=${Number(details.pending_control_count ?? 0)} stale_controls=${Number(details.stale_control_count ?? 0)} attention=${(details.attention_events as unknown[] | undefined)?.length ?? 0}`;
|
|
163
|
+
}
|
|
164
|
+
return `\nruntime version=${String(details.version)} state_schema=${String(details.state_schema)} automatic_review=${String(details.automatic_review)}`;
|
|
295
165
|
}
|
|
296
166
|
|
|
297
|
-
function
|
|
298
|
-
|
|
167
|
+
function inspectRuntime(
|
|
168
|
+
view: string,
|
|
169
|
+
input: Record<string, unknown>,
|
|
170
|
+
ctx: unknown,
|
|
171
|
+
deps: InspectToolDeps,
|
|
299
172
|
): Record<string, unknown> {
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
try {
|
|
308
|
-
for (const message of AsyncRuns.readRunInboxMessages(stateDir, 200)) {
|
|
309
|
-
if (!isStaleClaim(message, now)) continue;
|
|
310
|
-
staleClaims.push({
|
|
311
|
-
run: runId,
|
|
312
|
-
id: message.id,
|
|
313
|
-
claimed_at: message.claimed_at,
|
|
314
|
-
claimed_by: message.claimed_by,
|
|
315
|
-
type: message.type,
|
|
316
|
-
});
|
|
317
|
-
}
|
|
318
|
-
} catch {}
|
|
319
|
-
try {
|
|
320
|
-
for (const event of AsyncRuns.readRunEvents(stateDir, 80)) {
|
|
321
|
-
if (event.metadata?.requires_response !== true) continue;
|
|
322
|
-
attentionMessages.push({
|
|
323
|
-
run: runId,
|
|
324
|
-
id: event.id,
|
|
325
|
-
summary: event.summary,
|
|
326
|
-
type: event.type ?? event.event,
|
|
327
|
-
});
|
|
328
|
-
}
|
|
329
|
-
} catch {}
|
|
173
|
+
if (view === "status") return runtimeStatus();
|
|
174
|
+
if (view === "runs") {
|
|
175
|
+
return runtimeRuns(
|
|
176
|
+
ctx,
|
|
177
|
+
deps,
|
|
178
|
+
typeof input.status === "string" ? input.status : undefined,
|
|
179
|
+
);
|
|
330
180
|
}
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
function isTriageHighRiskRecipe(recipe: Record<string, unknown>): boolean {
|
|
335
|
-
if (recipe.tool !== true) return false;
|
|
336
|
-
const labels = Array.isArray(recipe.risk_labels)
|
|
337
|
-
? recipe.risk_labels.map((label) => String(label))
|
|
338
|
-
: [];
|
|
339
|
-
return labels.some((label) => label !== "risk.long_running");
|
|
181
|
+
if (view === "triage") return runtimeTriage(ctx, deps);
|
|
182
|
+
throw new Error("inspect runtime supports view=status, view=runs, or view=triage.");
|
|
340
183
|
}
|
|
341
184
|
|
|
342
|
-
function
|
|
343
|
-
|
|
185
|
+
function inspectRecipes(
|
|
186
|
+
view: string,
|
|
344
187
|
deps: InspectToolDeps,
|
|
345
188
|
): Record<string, unknown> {
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
}
|
|
357
|
-
const visibleRuns = currentSession
|
|
358
|
-
? allRuns.filter(
|
|
359
|
-
(run) => !run.ownerId || run.ownerId === currentSession,
|
|
360
|
-
)
|
|
361
|
-
: allRuns;
|
|
362
|
-
const activeRuns = visibleRuns.filter((run) => run.status === "running");
|
|
363
|
-
const failedRuns = visibleRuns.filter((run) => run.status === "failed");
|
|
364
|
-
const otherRuns = currentSession
|
|
365
|
-
? allRuns.filter((run) => run.ownerId && run.ownerId !== currentSession)
|
|
366
|
-
: [];
|
|
189
|
+
if (
|
|
190
|
+
view !== "status" &&
|
|
191
|
+
view !== "summary" &&
|
|
192
|
+
view !== "doctor" &&
|
|
193
|
+
view !== "imports" &&
|
|
194
|
+
view !== "reviews"
|
|
195
|
+
) {
|
|
196
|
+
throw new Error(
|
|
197
|
+
"inspect recipes supports view=status, view=summary, view=doctor, view=imports, or view=reviews.",
|
|
198
|
+
);
|
|
199
|
+
}
|
|
367
200
|
const recipeRoot = deps.recipeRoot ?? Paths.getRecipeRoot();
|
|
201
|
+
if (view === "reviews") {
|
|
202
|
+
return ReviewDiagnostics.readAutomaticReviewDiagnostics({ recipeRoot });
|
|
203
|
+
}
|
|
368
204
|
const discovered = RecipesDiscovery.discoverRecipeSources([
|
|
369
205
|
{ root: recipeRoot, defaultTool: true, mutableUsage: true },
|
|
370
206
|
{ root: deps.packagedRecipeRoot ?? Paths.getPackagedRecipeRoot() },
|
|
371
207
|
]);
|
|
372
|
-
const
|
|
208
|
+
const summary = {
|
|
373
209
|
...RecipesDiscovery.summarizeDiscovery(discovered),
|
|
374
210
|
drafts: RecipesDiscovery.listDraftRecipes(join(recipeRoot, "drafts")),
|
|
375
211
|
};
|
|
376
|
-
const activeRecipes = Array.isArray(recipeSummary.active)
|
|
377
|
-
? (recipeSummary.active as Array<Record<string, unknown>>)
|
|
378
|
-
: [];
|
|
379
|
-
const highRiskRecipes = activeRecipes.filter(isTriageHighRiskRecipe);
|
|
380
|
-
const signals = getRunTriageSignals(visibleRuns);
|
|
381
|
-
const attentionMessages = signals.attention_messages as Array<
|
|
382
|
-
Record<string, unknown>
|
|
383
|
-
>;
|
|
384
|
-
const staleClaims = signals.stale_claims as Array<Record<string, unknown>>;
|
|
385
|
-
const invalidRecipes = Array.isArray(recipeSummary.invalid)
|
|
386
|
-
? (recipeSummary.invalid as Array<Record<string, unknown>>)
|
|
387
|
-
: [];
|
|
388
|
-
const remediations = Array.isArray(recipeSummary.remediations)
|
|
389
|
-
? (recipeSummary.remediations as Array<Record<string, unknown>>)
|
|
390
|
-
: [];
|
|
391
|
-
const drafts = Array.isArray(recipeSummary.drafts)
|
|
392
|
-
? (recipeSummary.drafts as Array<Record<string, unknown>>)
|
|
393
|
-
: [];
|
|
394
|
-
const nextActions = [
|
|
395
|
-
invalidRecipes.length || remediations.length
|
|
396
|
-
? "inspect target=recipes view=doctor"
|
|
397
|
-
: "",
|
|
398
|
-
drafts.length ? "inspect target=recipes view=summary verbose=true" : "",
|
|
399
|
-
failedRuns[0]?.run
|
|
400
|
-
? `inspect target=run:${String(failedRuns[0].run)} view=tail lines=80`
|
|
401
|
-
: "",
|
|
402
|
-
attentionMessages[0]?.run
|
|
403
|
-
? `inspect target=run:${String(attentionMessages[0].run)} view=messages`
|
|
404
|
-
: "",
|
|
405
|
-
activeRuns.length
|
|
406
|
-
? "inspect target=session:all view=runs status=active"
|
|
407
|
-
: "",
|
|
408
|
-
].filter(Boolean);
|
|
409
212
|
return {
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
active_runs: activeRuns.map((run) => ({
|
|
413
|
-
run: run.run,
|
|
414
|
-
ownerId: run.ownerId,
|
|
415
|
-
recipe: run.recipe,
|
|
416
|
-
status: run.status,
|
|
417
|
-
})),
|
|
418
|
-
other_session_runs: otherRuns.length,
|
|
419
|
-
invalid_recipes: invalidRecipes,
|
|
420
|
-
blocking_recipes: remediations.filter((item) =>
|
|
421
|
-
String(item.kind ?? "").startsWith("blocking_"),
|
|
422
|
-
),
|
|
423
|
-
high_risk_recipes: highRiskRecipes.map((recipe) => ({
|
|
424
|
-
id: recipe.id,
|
|
425
|
-
path: recipe.path,
|
|
426
|
-
risk_labels: recipe.risk_labels,
|
|
427
|
-
})),
|
|
428
|
-
draft_recipes: drafts,
|
|
429
|
-
stale_claims: staleClaims,
|
|
430
|
-
recent_failed_runs: failedRuns.slice(0, 5).map((run) => ({
|
|
431
|
-
run: run.run,
|
|
432
|
-
recipe: run.recipe,
|
|
433
|
-
status: run.status,
|
|
434
|
-
})),
|
|
435
|
-
attention_messages: attentionMessages.slice(-10),
|
|
436
|
-
next_actions: [...new Set(nextActions)].slice(0, 5),
|
|
213
|
+
...summary,
|
|
214
|
+
next_actions: ToolsResponse.recipeRegistryNextActions(summary, view),
|
|
437
215
|
};
|
|
438
216
|
}
|
|
439
217
|
|
|
440
|
-
function
|
|
441
|
-
|
|
442
|
-
const
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
?
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
218
|
+
function parseRunTarget(target: string): string | undefined {
|
|
219
|
+
if (!target.startsWith("run:")) return undefined;
|
|
220
|
+
const run = target.slice(4);
|
|
221
|
+
return run && /^[A-Za-z0-9_.-]+$/.test(run) ? run : undefined;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
function inspectRun(
|
|
225
|
+
run: string,
|
|
226
|
+
view: string,
|
|
227
|
+
input: Record<string, unknown>,
|
|
228
|
+
ctx: unknown,
|
|
229
|
+
deps: InspectToolDeps,
|
|
230
|
+
): Record<string, unknown> {
|
|
231
|
+
if (view !== "recipe" && view !== "trace" && view !== "control") {
|
|
232
|
+
throw new Error("inspect run:<id> supports view=recipe, view=trace, or view=control.");
|
|
233
|
+
}
|
|
234
|
+
const status = deps.getRunStatus
|
|
235
|
+
? deps.getRunStatus(run)
|
|
236
|
+
: ToolsAccess.assertRunAccessibleToContext(run, ctx);
|
|
237
|
+
const stateDir = String(status.state_dir);
|
|
238
|
+
if (view === "recipe") {
|
|
239
|
+
return Inspector.readActorInspectorRecipe(stateDir) as unknown as Record<string, unknown>;
|
|
240
|
+
}
|
|
241
|
+
if (view === "trace") {
|
|
242
|
+
const source = typeof input.source === "string" ? input.source : "all";
|
|
243
|
+
if (
|
|
244
|
+
source !== "all" &&
|
|
245
|
+
source !== "lifecycle" &&
|
|
246
|
+
source !== "control" &&
|
|
247
|
+
source !== "process" &&
|
|
248
|
+
source !== "agent" &&
|
|
249
|
+
source !== "artifact" &&
|
|
250
|
+
source !== "runtime"
|
|
251
|
+
) {
|
|
252
|
+
throw new Error(`unsupported Trace source: ${source}`);
|
|
253
|
+
}
|
|
254
|
+
return {
|
|
255
|
+
run,
|
|
256
|
+
source,
|
|
257
|
+
items: TraceProjection.projectRunTrace(stateDir, {
|
|
258
|
+
artifacts: status.artifacts as
|
|
259
|
+
| Record<string, AsyncRuns.RunArtifactDeclaration>
|
|
260
|
+
| undefined,
|
|
261
|
+
limit: Number(input.lines || Limits.DEFAULT_INSPECT_LINES),
|
|
262
|
+
source,
|
|
263
|
+
}),
|
|
264
|
+
};
|
|
265
|
+
}
|
|
266
|
+
const runInstanceId = String(status.run_instance_id ?? "");
|
|
267
|
+
return {
|
|
268
|
+
run,
|
|
269
|
+
run_instance_id: runInstanceId,
|
|
270
|
+
status: status.status,
|
|
271
|
+
actor_actions: Array.isArray(status.control) ? status.control : [],
|
|
272
|
+
runtime_actions: status.status === "running" ? ["kill"] : ["archive", "prune"],
|
|
273
|
+
endpoint: runInstanceId
|
|
274
|
+
? RunControlDelivery.readRunControlEndpoint(stateDir, runInstanceId)
|
|
275
|
+
: undefined,
|
|
276
|
+
recent_controls: RunsControls.readRunControlsFromStateDir(stateDir)
|
|
277
|
+
.slice(-Math.max(1, Number(input.lines || 20)))
|
|
278
|
+
.reverse()
|
|
279
|
+
.map(ControlProjection.projectRunControl),
|
|
280
|
+
};
|
|
470
281
|
}
|
|
471
282
|
|
|
472
|
-
function
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
283
|
+
function inspectTool(
|
|
284
|
+
name: string,
|
|
285
|
+
view: string,
|
|
286
|
+
deps: InspectToolDeps,
|
|
287
|
+
): Record<string, unknown> {
|
|
288
|
+
if (!name || !/^[A-Za-z0-9_.-]+$/.test(name)) {
|
|
289
|
+
throw new Error(`invalid tool target: tool:${name}`);
|
|
290
|
+
}
|
|
291
|
+
if (view !== "status" && view !== "schema") {
|
|
292
|
+
throw new Error("inspect tool:<name> supports view=status or view=schema.");
|
|
293
|
+
}
|
|
294
|
+
const tool = deps.getTool?.(name);
|
|
295
|
+
if (!tool) throw new Error(`registered tool not found: ${name}`);
|
|
296
|
+
return {
|
|
297
|
+
name,
|
|
298
|
+
description: tool.description,
|
|
299
|
+
parameters: tool.parameters,
|
|
300
|
+
promptSnippet: tool.promptSnippet,
|
|
301
|
+
};
|
|
479
302
|
}
|
|
480
303
|
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
recipeRoot?: string;
|
|
304
|
+
function compactResult(target: string, view: string, details: Record<string, unknown>): string {
|
|
305
|
+
if (target === "runtime") return compactRuntime(view, details);
|
|
306
|
+
if (target === "recipes") return ToolsResponse.compactRecipeRegistry(details);
|
|
307
|
+
if (target.startsWith("tool:")) return `\ntool=${target.slice(5)} view=${view}`;
|
|
308
|
+
return `\nrun=${target.slice(4)} view=${view}`;
|
|
487
309
|
}
|
|
488
310
|
|
|
489
311
|
export function createInspectToolDefinition<TContext = unknown>(
|
|
@@ -493,23 +315,18 @@ export function createInspectToolDefinition<TContext = unknown>(
|
|
|
493
315
|
name: "inspect",
|
|
494
316
|
label: "Inspect",
|
|
495
317
|
description:
|
|
496
|
-
"
|
|
318
|
+
"Inspect a Run's Recipe, Trace, or Control evidence, or runtime/recipe/tool diagnostics.",
|
|
497
319
|
parameters: Schema.objectSchema(
|
|
498
320
|
{
|
|
499
|
-
lines: Schema.stringSchema(
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
status: Schema.stringSchema(
|
|
503
|
-
"Optional session run filter: all, running, active, terminal, done, failed, cancelled, killed, or exited.",
|
|
504
|
-
),
|
|
505
|
-
target: Schema.stringSchema(
|
|
506
|
-
"Actor address to inspect, e.g. run:<id> or tool:<name>; advanced: branch:<run>/<branch>, room:<run>, coordinator, session:<id>, session:all.",
|
|
507
|
-
),
|
|
508
|
-
verbose: Schema.booleanSchema(
|
|
509
|
-
"Return full JSON instead of compact text where available.",
|
|
321
|
+
lines: Schema.stringSchema("Bounded item count for Trace or recent Controls."),
|
|
322
|
+
source: Schema.stringSchema(
|
|
323
|
+
"Optional Trace source: all, lifecycle, control, process, agent, artifact, or runtime.",
|
|
510
324
|
),
|
|
325
|
+
status: Schema.stringSchema("Optional runtime Run status filter."),
|
|
326
|
+
target: Schema.stringSchema("Target: run:<id>, runtime, recipes, or tool:<name>."),
|
|
327
|
+
verbose: Schema.booleanSchema("Return full JSON instead of compact text."),
|
|
511
328
|
view: Schema.stringSchema(
|
|
512
|
-
"
|
|
329
|
+
"Run view recipe|trace|control, or target-specific management view.",
|
|
513
330
|
),
|
|
514
331
|
},
|
|
515
332
|
["target", "view"],
|
|
@@ -524,467 +341,33 @@ export function createInspectToolDefinition<TContext = unknown>(
|
|
|
524
341
|
const input = asRecord(params);
|
|
525
342
|
const target = String(input.target ?? "");
|
|
526
343
|
const view = String(input.view ?? "");
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
)
|
|
344
|
+
let details: Record<string, unknown>;
|
|
345
|
+
if (target === "runtime") {
|
|
346
|
+
details = inspectRuntime(view, input, ctx, deps);
|
|
347
|
+
} else if (target === "recipes") {
|
|
348
|
+
details = inspectRecipes(view, deps);
|
|
349
|
+
} else {
|
|
350
|
+
const run = parseRunTarget(target);
|
|
351
|
+
if (run) details = inspectRun(run, view, input, ctx, deps);
|
|
352
|
+
else if (target.startsWith("tool:")) {
|
|
353
|
+
details = inspectTool(target.slice(5), view, deps);
|
|
354
|
+
} else {
|
|
535
355
|
throw new Error(
|
|
536
|
-
|
|
356
|
+
`unsupported inspect target: ${target}; use run:<id>, runtime, recipes, or tool:<name>`,
|
|
537
357
|
);
|
|
538
358
|
}
|
|
539
|
-
if (view === "reviews") {
|
|
540
|
-
const diagnostics = ReviewDiagnostics.readAutomaticReviewDiagnostics({
|
|
541
|
-
recipeRoot: deps.recipeRoot ?? Paths.getRecipeRoot(),
|
|
542
|
-
});
|
|
543
|
-
return {
|
|
544
|
-
content: [{
|
|
545
|
-
type: "text" as const,
|
|
546
|
-
text: maybeJsonText(
|
|
547
|
-
diagnostics,
|
|
548
|
-
input.verbose === true,
|
|
549
|
-
compactAutomaticReviewDiagnostics(diagnostics),
|
|
550
|
-
),
|
|
551
|
-
}],
|
|
552
|
-
details: diagnostics,
|
|
553
|
-
};
|
|
554
|
-
}
|
|
555
|
-
const discovered = RecipesDiscovery.discoverRecipeSources([
|
|
556
|
-
{
|
|
557
|
-
root: deps.recipeRoot ?? Paths.getRecipeRoot(),
|
|
558
|
-
defaultTool: true,
|
|
559
|
-
mutableUsage: true,
|
|
560
|
-
},
|
|
561
|
-
{ root: deps.packagedRecipeRoot ?? Paths.getPackagedRecipeRoot() },
|
|
562
|
-
]);
|
|
563
|
-
const recipeRoot = deps.recipeRoot ?? Paths.getRecipeRoot();
|
|
564
|
-
const summaryBase = {
|
|
565
|
-
...RecipesDiscovery.summarizeDiscovery(discovered),
|
|
566
|
-
drafts: RecipesDiscovery.listDraftRecipes(join(recipeRoot, "drafts")),
|
|
567
|
-
};
|
|
568
|
-
const summary = {
|
|
569
|
-
...summaryBase,
|
|
570
|
-
next_actions: ToolsResponse.recipeRegistryNextActions(
|
|
571
|
-
summaryBase,
|
|
572
|
-
view,
|
|
573
|
-
),
|
|
574
|
-
};
|
|
575
|
-
return {
|
|
576
|
-
content: [
|
|
577
|
-
{
|
|
578
|
-
type: "text" as const,
|
|
579
|
-
text: maybeJsonText(
|
|
580
|
-
summary,
|
|
581
|
-
input.verbose === true,
|
|
582
|
-
view === "doctor"
|
|
583
|
-
? ToolsResponse.compactRecipeDoctor(summary)
|
|
584
|
-
: view === "imports"
|
|
585
|
-
? ToolsResponse.compactRecipeImports(summary)
|
|
586
|
-
: ToolsResponse.compactRecipeRegistry(summary),
|
|
587
|
-
),
|
|
588
|
-
},
|
|
589
|
-
],
|
|
590
|
-
details: summary,
|
|
591
|
-
};
|
|
592
359
|
}
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
"inspect coordinator supports view=status or view=runs.",
|
|
598
|
-
);
|
|
599
|
-
}
|
|
600
|
-
const session = ToolsAccess.requireContextSessionId(
|
|
601
|
-
ctx,
|
|
602
|
-
"inspect coordinator",
|
|
603
|
-
);
|
|
604
|
-
const allRuns = AsyncRuns.listRuns(
|
|
605
|
-
undefined,
|
|
606
|
-
typeof input.status === "string" ? input.status : undefined,
|
|
607
|
-
).map((run) => AsyncRuns.getRunStatus(String(run.state_dir)));
|
|
608
|
-
const runs = allRuns.filter((run) => run.ownerId === session);
|
|
609
|
-
const sessionSummary = summarizeOtherSessions(session, allRuns);
|
|
610
|
-
return {
|
|
611
|
-
content: [
|
|
612
|
-
{
|
|
613
|
-
type: "text" as const,
|
|
614
|
-
text: maybeJsonText(
|
|
615
|
-
{ session, runs, ...sessionSummary },
|
|
616
|
-
input.verbose === true,
|
|
617
|
-
compactSessionRuns(session, runs, sessionSummary),
|
|
618
|
-
),
|
|
619
|
-
},
|
|
620
|
-
],
|
|
621
|
-
details: { session, runs, ...sessionSummary },
|
|
622
|
-
};
|
|
623
|
-
}
|
|
624
|
-
if (address.kind === "session") {
|
|
625
|
-
if (view !== "status" && view !== "runs") {
|
|
626
|
-
throw new Error(
|
|
627
|
-
"inspect session:<id> supports view=status or view=runs.",
|
|
628
|
-
);
|
|
629
|
-
}
|
|
630
|
-
const allRuns = AsyncRuns.listRuns(
|
|
631
|
-
undefined,
|
|
632
|
-
typeof input.status === "string" ? input.status : undefined,
|
|
633
|
-
).map((run) => AsyncRuns.getRunStatus(String(run.state_dir)));
|
|
634
|
-
const runs = allRuns.filter(
|
|
635
|
-
(run) => address.value === "all" || run.ownerId === address.value,
|
|
636
|
-
);
|
|
637
|
-
const sessionSummary =
|
|
638
|
-
address.value === "all"
|
|
639
|
-
? {}
|
|
640
|
-
: summarizeOtherSessions(address.value || "", allRuns);
|
|
641
|
-
return {
|
|
642
|
-
content: [
|
|
643
|
-
{
|
|
644
|
-
type: "text" as const,
|
|
645
|
-
text: maybeJsonText(
|
|
646
|
-
{ session: address.value, runs, ...sessionSummary },
|
|
647
|
-
input.verbose === true,
|
|
648
|
-
compactSessionRuns(address.value || "", runs, sessionSummary),
|
|
649
|
-
),
|
|
650
|
-
},
|
|
651
|
-
],
|
|
652
|
-
details: { session: address.value, runs, ...sessionSummary },
|
|
653
|
-
};
|
|
654
|
-
}
|
|
655
|
-
if (address.kind === "tool" && address.value) {
|
|
656
|
-
if (address.value === "pi-actors") {
|
|
657
|
-
if (view !== "status" && view !== "triage") {
|
|
658
|
-
throw new Error(
|
|
659
|
-
"inspect tool:pi-actors supports view=status or view=triage.",
|
|
660
|
-
);
|
|
661
|
-
}
|
|
662
|
-
const details =
|
|
663
|
-
view === "triage"
|
|
664
|
-
? getPiActorsTriage(ctx, deps)
|
|
665
|
-
: getPiActorsRuntimeStatus();
|
|
666
|
-
return {
|
|
667
|
-
content: [
|
|
668
|
-
{
|
|
669
|
-
type: "text" as const,
|
|
670
|
-
text: maybeJsonText(
|
|
671
|
-
details,
|
|
672
|
-
input.verbose === true,
|
|
673
|
-
view === "triage"
|
|
674
|
-
? compactPiActorsTriage(details)
|
|
675
|
-
: compactPiActorsRuntimeStatus(details),
|
|
676
|
-
),
|
|
677
|
-
},
|
|
678
|
-
],
|
|
360
|
+
return {
|
|
361
|
+
content: [{
|
|
362
|
+
type: "text" as const,
|
|
363
|
+
text: maybeJsonText(
|
|
679
364
|
details,
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
}
|
|
687
|
-
const tool = deps.getTool?.(address.value);
|
|
688
|
-
if (!tool) throw new Error(`tool actor not found: ${address.value}`);
|
|
689
|
-
const details = {
|
|
690
|
-
name: address.value,
|
|
691
|
-
description: tool.description,
|
|
692
|
-
parameters: tool.parameters,
|
|
693
|
-
promptSnippet: tool.promptSnippet,
|
|
694
|
-
};
|
|
695
|
-
return {
|
|
696
|
-
content: [
|
|
697
|
-
{
|
|
698
|
-
type: "text" as const,
|
|
699
|
-
text: maybeJsonText(
|
|
700
|
-
details,
|
|
701
|
-
input.verbose === true || view === "schema",
|
|
702
|
-
compactToolActor(address.value, details),
|
|
703
|
-
),
|
|
704
|
-
},
|
|
705
|
-
],
|
|
706
|
-
details,
|
|
707
|
-
};
|
|
708
|
-
}
|
|
709
|
-
if (address.kind === "room" && address.value && address.room) {
|
|
710
|
-
const status = ToolsAccess.assertRunAccessibleToContext(
|
|
711
|
-
address.value,
|
|
712
|
-
ctx,
|
|
713
|
-
);
|
|
714
|
-
const stateDir = String(status.state_dir ?? "");
|
|
715
|
-
if (!stateDir)
|
|
716
|
-
throw new Error(`room:${address.value} has no run state directory.`);
|
|
717
|
-
if (view === "status") {
|
|
718
|
-
const status = Rooms.getRoomStatus(stateDir, address.room);
|
|
719
|
-
return {
|
|
720
|
-
content: [
|
|
721
|
-
{
|
|
722
|
-
type: "text" as const,
|
|
723
|
-
text: maybeJsonText(
|
|
724
|
-
status,
|
|
725
|
-
input.verbose === true,
|
|
726
|
-
compactRoomStatus(status),
|
|
727
|
-
),
|
|
728
|
-
},
|
|
729
|
-
],
|
|
730
|
-
details: status,
|
|
731
|
-
};
|
|
732
|
-
}
|
|
733
|
-
if (view === "previews") {
|
|
734
|
-
const previews = Rooms.readRoomMessagePreviews(
|
|
735
|
-
stateDir,
|
|
736
|
-
address.room,
|
|
737
|
-
Number(input.lines || Limits.DEFAULT_INSPECT_LINES),
|
|
738
|
-
);
|
|
739
|
-
return {
|
|
740
|
-
content: [
|
|
741
|
-
{
|
|
742
|
-
type: "text" as const,
|
|
743
|
-
text: maybeJsonText(
|
|
744
|
-
previews,
|
|
745
|
-
input.verbose === true,
|
|
746
|
-
compactRoomPreviews(previews),
|
|
747
|
-
),
|
|
748
|
-
},
|
|
749
|
-
],
|
|
750
|
-
details: { previews },
|
|
751
|
-
};
|
|
752
|
-
}
|
|
753
|
-
if (view === "messages") {
|
|
754
|
-
const messages = Rooms.readRoomMessages(
|
|
755
|
-
stateDir,
|
|
756
|
-
address.room,
|
|
757
|
-
Number(input.lines || Limits.DEFAULT_INSPECT_LINES),
|
|
758
|
-
);
|
|
759
|
-
return {
|
|
760
|
-
content: [
|
|
761
|
-
{
|
|
762
|
-
type: "text" as const,
|
|
763
|
-
text: maybeJsonText(
|
|
764
|
-
messages,
|
|
765
|
-
input.verbose === true,
|
|
766
|
-
compactRoomMessages(messages),
|
|
767
|
-
),
|
|
768
|
-
},
|
|
769
|
-
],
|
|
770
|
-
details: { messages },
|
|
771
|
-
};
|
|
772
|
-
}
|
|
773
|
-
if (view === "contacts") {
|
|
774
|
-
const contacts = Rooms.readRoomContacts(stateDir, address.room);
|
|
775
|
-
return {
|
|
776
|
-
content: [
|
|
777
|
-
{
|
|
778
|
-
type: "text" as const,
|
|
779
|
-
text: maybeJsonText(
|
|
780
|
-
contacts,
|
|
781
|
-
input.verbose === true,
|
|
782
|
-
compactRoomContacts(contacts),
|
|
783
|
-
),
|
|
784
|
-
},
|
|
785
|
-
],
|
|
786
|
-
details: { contacts },
|
|
787
|
-
};
|
|
788
|
-
}
|
|
789
|
-
if (view === "roster") {
|
|
790
|
-
const roster = Rooms.readRoomRoster(stateDir, address.room);
|
|
791
|
-
return {
|
|
792
|
-
content: [
|
|
793
|
-
{
|
|
794
|
-
type: "text" as const,
|
|
795
|
-
text: maybeJsonText(
|
|
796
|
-
roster,
|
|
797
|
-
input.verbose === true,
|
|
798
|
-
compactRoomRoster(roster),
|
|
799
|
-
),
|
|
800
|
-
},
|
|
801
|
-
],
|
|
802
|
-
details: { roster },
|
|
803
|
-
};
|
|
804
|
-
}
|
|
805
|
-
throw new Error(
|
|
806
|
-
"inspect room:<run> supports view=status, view=messages, view=previews, view=roster, or view=contacts.",
|
|
807
|
-
);
|
|
808
|
-
}
|
|
809
|
-
const runId =
|
|
810
|
-
address.kind === "run" || address.kind === "branch"
|
|
811
|
-
? address.value
|
|
812
|
-
: undefined;
|
|
813
|
-
if (!runId)
|
|
814
|
-
throw new Error(
|
|
815
|
-
"inspect target must be run:<id>, branch:<run>/<branch>, coordinator, session:<id>, or tool:<name>.",
|
|
816
|
-
);
|
|
817
|
-
if (address.kind === "branch") {
|
|
818
|
-
if (view !== "mailbox")
|
|
819
|
-
throw new Error(
|
|
820
|
-
"inspect branch:<run>/<branch> supports view=mailbox.",
|
|
821
|
-
);
|
|
822
|
-
const status = ToolsAccess.assertRunAccessibleToContext(runId, ctx);
|
|
823
|
-
const branchInbox = Rooms.readBranchInboxDiagnostics(
|
|
824
|
-
String(status.state_dir ?? ""),
|
|
825
|
-
runId,
|
|
826
|
-
target,
|
|
827
|
-
Number(input.lines || Limits.DEFAULT_INSPECT_LINES),
|
|
828
|
-
);
|
|
829
|
-
const messages = branchInbox.messages;
|
|
830
|
-
return {
|
|
831
|
-
content: [
|
|
832
|
-
{
|
|
833
|
-
type: "text" as const,
|
|
834
|
-
text: maybeJsonText(
|
|
835
|
-
input.verbose === true ? branchInbox : messages,
|
|
836
|
-
input.verbose === true,
|
|
837
|
-
`${ToolsResponse.compactBranchInbox(messages.map((message) => ({ ...message })))}${branchInbox.corrupted > 0 ? `\ncorrupted=${branchInbox.corrupted}` : ""}`,
|
|
838
|
-
),
|
|
839
|
-
},
|
|
840
|
-
],
|
|
841
|
-
details: { corrupted: branchInbox.corrupted, messages },
|
|
842
|
-
};
|
|
843
|
-
}
|
|
844
|
-
switch (view) {
|
|
845
|
-
case "status": {
|
|
846
|
-
const status = ToolsAccess.assertRunAccessibleToContext(runId, ctx);
|
|
847
|
-
return {
|
|
848
|
-
content: [
|
|
849
|
-
{
|
|
850
|
-
type: "text" as const,
|
|
851
|
-
text: maybeJsonText(
|
|
852
|
-
status,
|
|
853
|
-
input.verbose === true,
|
|
854
|
-
ToolsResponse.compactAsyncRunStatus(status),
|
|
855
|
-
),
|
|
856
|
-
},
|
|
857
|
-
],
|
|
858
|
-
details: status,
|
|
859
|
-
};
|
|
860
|
-
}
|
|
861
|
-
case "tail": {
|
|
862
|
-
ToolsAccess.assertRunAccessibleToContext(runId, ctx);
|
|
863
|
-
const text = AsyncRuns.tailRun(
|
|
864
|
-
runId,
|
|
865
|
-
Number(input.lines || Limits.DEFAULT_INSPECT_LINES),
|
|
866
|
-
);
|
|
867
|
-
return {
|
|
868
|
-
content: [{ type: "text" as const, text: `\n${text}` }],
|
|
869
|
-
details: {},
|
|
870
|
-
};
|
|
871
|
-
}
|
|
872
|
-
case "messages": {
|
|
873
|
-
ToolsAccess.assertRunAccessibleToContext(runId, ctx);
|
|
874
|
-
const messages = AsyncRuns.readRunEvents(
|
|
875
|
-
runId,
|
|
876
|
-
Number(input.lines || Limits.DEFAULT_INSPECT_LINES),
|
|
877
|
-
);
|
|
878
|
-
return {
|
|
879
|
-
content: [
|
|
880
|
-
{
|
|
881
|
-
type: "text" as const,
|
|
882
|
-
text: maybeJsonText(
|
|
883
|
-
messages,
|
|
884
|
-
input.verbose === true,
|
|
885
|
-
compactRunMessages(messages),
|
|
886
|
-
),
|
|
887
|
-
},
|
|
888
|
-
],
|
|
889
|
-
details: { messages },
|
|
890
|
-
};
|
|
891
|
-
}
|
|
892
|
-
case "artifacts":
|
|
893
|
-
case "files": {
|
|
894
|
-
const status = ToolsAccess.assertRunAccessibleToContext(runId, ctx);
|
|
895
|
-
const artifactManifest = AsyncRuns.resolveArtifactManifest(
|
|
896
|
-
status.artifacts as
|
|
897
|
-
| Record<string, AsyncRuns.RunArtifactDeclaration>
|
|
898
|
-
| undefined,
|
|
899
|
-
);
|
|
900
|
-
const reviewEvidence = readBoundedReviewEvidence(
|
|
901
|
-
status,
|
|
902
|
-
Number(input.lines || Limits.DEFAULT_INSPECT_LINES),
|
|
903
|
-
);
|
|
904
|
-
const details = artifactManifest
|
|
905
|
-
? {
|
|
906
|
-
...status,
|
|
907
|
-
...(reviewEvidence ? { review_evidence: reviewEvidence } : {}),
|
|
908
|
-
artifact_manifest: artifactManifest,
|
|
909
|
-
next_actions: ToolsResponse.artifactNextActions(
|
|
910
|
-
status.run ?? runId,
|
|
911
|
-
asRecord(status.artifacts),
|
|
912
|
-
),
|
|
913
|
-
}
|
|
914
|
-
: {
|
|
915
|
-
...status,
|
|
916
|
-
...(reviewEvidence ? { review_evidence: reviewEvidence } : {}),
|
|
917
|
-
};
|
|
918
|
-
return {
|
|
919
|
-
content: [
|
|
920
|
-
{
|
|
921
|
-
type: "text" as const,
|
|
922
|
-
text: maybeJsonText(
|
|
923
|
-
details,
|
|
924
|
-
input.verbose === true,
|
|
925
|
-
compactActorFiles(status),
|
|
926
|
-
),
|
|
927
|
-
},
|
|
928
|
-
],
|
|
929
|
-
details,
|
|
930
|
-
};
|
|
931
|
-
}
|
|
932
|
-
case "mailbox": {
|
|
933
|
-
const status = ToolsAccess.assertRunAccessibleToContext(runId, ctx);
|
|
934
|
-
const mailbox = asRecord(status.mailbox);
|
|
935
|
-
const normalizedMailbox =
|
|
936
|
-
ToolsMailbox.normalizeMailboxContracts(mailbox);
|
|
937
|
-
const messages = AsyncRuns.readRunInboxMessages(
|
|
938
|
-
runId,
|
|
939
|
-
Number(input.lines || Limits.DEFAULT_INSPECT_LINES),
|
|
940
|
-
);
|
|
941
|
-
const details = {
|
|
942
|
-
mailbox,
|
|
943
|
-
normalized_mailbox: normalizedMailbox,
|
|
944
|
-
messages,
|
|
945
|
-
};
|
|
946
|
-
return {
|
|
947
|
-
content: [
|
|
948
|
-
{
|
|
949
|
-
type: "text" as const,
|
|
950
|
-
text: maybeJsonText(
|
|
951
|
-
details,
|
|
952
|
-
input.verbose === true,
|
|
953
|
-
ToolsResponse.compactRunMailbox(
|
|
954
|
-
String(status.run ?? runId),
|
|
955
|
-
mailbox,
|
|
956
|
-
messages,
|
|
957
|
-
),
|
|
958
|
-
),
|
|
959
|
-
},
|
|
960
|
-
],
|
|
961
|
-
details,
|
|
962
|
-
};
|
|
963
|
-
}
|
|
964
|
-
case "communication": {
|
|
965
|
-
const status = ToolsAccess.assertRunAccessibleToContext(runId, ctx);
|
|
966
|
-
const snapshot = Rooms.readCommunicationSnapshot(
|
|
967
|
-
String(status.state_dir ?? ""),
|
|
968
|
-
);
|
|
969
|
-
return {
|
|
970
|
-
content: [
|
|
971
|
-
{
|
|
972
|
-
type: "text" as const,
|
|
973
|
-
text: maybeJsonText(
|
|
974
|
-
snapshot ?? {},
|
|
975
|
-
input.verbose === true,
|
|
976
|
-
compactCommunicationSnapshot(snapshot),
|
|
977
|
-
),
|
|
978
|
-
},
|
|
979
|
-
],
|
|
980
|
-
details: { communication: snapshot },
|
|
981
|
-
};
|
|
982
|
-
}
|
|
983
|
-
default:
|
|
984
|
-
throw new Error(
|
|
985
|
-
"inspect view must be one of: status, tail, messages, artifacts, files, mailbox, communication; branch targets support mailbox.",
|
|
986
|
-
);
|
|
987
|
-
}
|
|
365
|
+
input.verbose === true || (target.startsWith("tool:") && view === "schema"),
|
|
366
|
+
compactResult(target, view, details),
|
|
367
|
+
),
|
|
368
|
+
}],
|
|
369
|
+
details,
|
|
370
|
+
};
|
|
988
371
|
},
|
|
989
372
|
};
|
|
990
373
|
}
|