@llblab/pi-actors 0.54.0 → 0.56.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 +110 -20
- package/BACKLOG.md +207 -4
- package/CHANGELOG.md +17 -0
- package/README.md +33 -3
- package/dist/index.js +2 -1
- package/dist/lib/async-runs.d.ts +37 -0
- package/dist/lib/async-runs.js +131 -62
- package/dist/lib/automatic-review-runtime.d.ts +2 -0
- package/dist/lib/automatic-review-runtime.js +3 -2
- package/dist/lib/command-templates.d.ts +37 -0
- package/dist/lib/command-templates.js +263 -129
- package/dist/lib/execution-files.d.ts +32 -0
- package/dist/lib/execution-files.js +128 -0
- package/dist/lib/execution-output.js +5 -4
- package/dist/lib/execution-sessions.d.ts +19 -1
- package/dist/lib/execution-sessions.js +62 -26
- package/dist/lib/execution.d.ts +4 -1
- package/dist/lib/execution.js +6 -1
- package/dist/lib/extension-runtime.d.ts +10 -2
- package/dist/lib/extension-runtime.js +95 -14
- package/dist/lib/file-state.js +21 -2
- package/dist/lib/inspector-command.js +2 -2
- package/dist/lib/inspector-overlay.d.ts +25 -7
- package/dist/lib/inspector-overlay.js +562 -262
- package/dist/lib/inspector.d.ts +20 -10
- package/dist/lib/inspector.js +80 -91
- package/dist/lib/limits.d.ts +1 -0
- package/dist/lib/limits.js +1 -0
- package/dist/lib/observability.d.ts +15 -1
- package/dist/lib/observability.js +216 -99
- package/dist/lib/pi.d.ts +9 -3
- package/dist/lib/pi.js +80 -12
- package/dist/lib/recipe-projection.d.ts +18 -0
- package/dist/lib/recipe-projection.js +220 -0
- package/dist/lib/recipes-context.d.ts +2 -0
- package/dist/lib/recipes-context.js +30 -6
- package/dist/lib/registry.js +270 -36
- package/dist/lib/run-delivery.d.ts +213 -5
- package/dist/lib/run-delivery.js +1909 -40
- package/dist/lib/run-supervision.d.ts +107 -0
- package/dist/lib/run-supervision.js +412 -0
- package/dist/lib/run-ui-runtime.d.ts +10 -2
- package/dist/lib/run-ui-runtime.js +347 -124
- package/dist/lib/runs-artifacts.d.ts +26 -1
- package/dist/lib/runs-artifacts.js +68 -2
- package/dist/lib/runs-context-exports.d.ts +451 -0
- package/dist/lib/runs-context-exports.js +2315 -0
- package/dist/lib/runs-context-index.d.ts +97 -0
- package/dist/lib/runs-context-index.js +368 -0
- package/dist/lib/runs-control-delivery.js +46 -7
- package/dist/lib/runs-control.d.ts +78 -2
- package/dist/lib/runs-control.js +334 -2
- package/dist/lib/runs-controls.js +4 -1
- package/dist/lib/runs-descendant-launches.d.ts +80 -0
- package/dist/lib/runs-descendant-launches.js +287 -0
- package/dist/lib/runs-execution-evidence.d.ts +110 -0
- package/dist/lib/runs-execution-evidence.js +282 -0
- package/dist/lib/runs-index.d.ts +66 -1
- package/dist/lib/runs-index.js +349 -13
- package/dist/lib/runs-native-launches.d.ts +73 -0
- package/dist/lib/runs-native-launches.js +227 -0
- package/dist/lib/runs-outcomes.d.ts +141 -0
- package/dist/lib/runs-outcomes.js +292 -0
- package/dist/lib/runs-ownership.d.ts +10 -1
- package/dist/lib/runs-ownership.js +36 -4
- package/dist/lib/runs-process-windows-mi.d.ts +46 -0
- package/dist/lib/runs-process-windows-mi.js +114 -0
- package/dist/lib/runs-process.d.ts +34 -1
- package/dist/lib/runs-process.js +158 -26
- package/dist/lib/runs-results.d.ts +116 -0
- package/dist/lib/runs-results.js +518 -0
- package/dist/lib/runs-retention.d.ts +15 -2
- package/dist/lib/runs-retention.js +148 -9
- package/dist/lib/runs-session-exports.d.ts +95 -0
- package/dist/lib/runs-session-exports.js +470 -0
- package/dist/lib/runs-snapshot.d.ts +58 -0
- package/dist/lib/runs-snapshot.js +92 -0
- package/dist/lib/runs-start.d.ts +2 -0
- package/dist/lib/runs-start.js +44 -3
- package/dist/lib/runs-status.d.ts +15 -1
- package/dist/lib/runs-status.js +337 -13
- package/dist/lib/runs-supervision.d.ts +105 -0
- package/dist/lib/runs-supervision.js +501 -0
- package/dist/lib/runs-trace.d.ts +1 -0
- package/dist/lib/runs-trace.js +14 -3
- package/dist/lib/runtime.js +22 -3
- package/dist/lib/session-evidence.d.ts +37 -0
- package/dist/lib/session-evidence.js +59 -3
- package/dist/lib/state-readers.d.ts +4 -1
- package/dist/lib/state-readers.js +14 -8
- package/dist/lib/temp.d.ts +2 -4
- package/dist/lib/temp.js +4 -56
- package/dist/lib/tools-access.d.ts +3 -0
- package/dist/lib/tools-access.js +13 -0
- package/dist/lib/tools-inspect.d.ts +1 -0
- package/dist/lib/tools-inspect.js +110 -43
- package/dist/lib/tools-local.d.ts +3 -0
- package/dist/lib/tools-local.js +18 -6
- package/dist/lib/tools-message.d.ts +4 -1
- package/dist/lib/tools-message.js +126 -31
- package/dist/lib/tools-response.d.ts +31 -3
- package/dist/lib/tools-response.js +311 -47
- package/dist/lib/tools-spawn.d.ts +3 -0
- package/dist/lib/tools-spawn.js +29 -7
- package/dist/lib/trace-projection.d.ts +20 -0
- package/dist/lib/trace-projection.js +192 -43
- package/dist/scripts/async-runner.mjs +272 -194
- package/dist/scripts/conformance.mjs +14 -2
- package/dist/skills/actors/SKILL.md +47 -3
- package/dist/skills/actors/references/diagnostics.md +40 -0
- package/dist/skills/actors/references/runs.md +56 -2
- package/docs/README.md +9 -1
- package/docs/actor-inspector.md +84 -15
- package/docs/agent-experience.md +216 -0
- package/docs/async-runs.md +21 -3
- package/docs/composition-transport.md +103 -0
- package/docs/coordinator-delivery.md +226 -24
- package/docs/inspection.md +38 -2
- package/docs/output-projection-map.md +130 -0
- package/docs/releasing.md +19 -2
- package/docs/run-supervision.md +1622 -0
- package/docs/template-recipes.md +4 -0
- package/docs/windows-process-observation.md +248 -0
- package/index.ts +2 -1
- package/lib/async-runs.ts +164 -73
- package/lib/automatic-review-runtime.ts +4 -2
- package/lib/command-templates.ts +287 -138
- package/lib/execution-files.ts +118 -0
- package/lib/execution-output.ts +4 -4
- package/lib/execution-sessions.ts +57 -27
- package/lib/execution.ts +8 -0
- package/lib/extension-runtime.ts +106 -12
- package/lib/file-state.ts +16 -2
- package/lib/inspector-command.ts +2 -2
- package/lib/inspector-overlay.ts +524 -261
- package/lib/inspector.ts +101 -130
- package/lib/limits.ts +1 -0
- package/lib/observability.ts +235 -116
- package/lib/pi.ts +89 -17
- package/lib/recipe-projection.ts +232 -0
- package/lib/recipes-context.ts +27 -6
- package/lib/registry.ts +266 -36
- package/lib/run-delivery.ts +1737 -49
- package/lib/run-supervision.ts +411 -0
- package/lib/run-ui-runtime.ts +293 -126
- package/lib/runs-artifacts.ts +73 -1
- package/lib/runs-context-exports.ts +1871 -0
- package/lib/runs-context-index.ts +372 -0
- package/lib/runs-control-delivery.ts +36 -18
- package/lib/runs-control.ts +297 -1
- package/lib/runs-controls.ts +3 -1
- package/lib/runs-descendant-launches.ts +338 -0
- package/lib/runs-execution-evidence.ts +302 -0
- package/lib/runs-index.ts +345 -17
- package/lib/runs-native-launches.ts +270 -0
- package/lib/runs-outcomes.ts +377 -0
- package/lib/runs-ownership.ts +37 -4
- package/lib/runs-process-windows-mi.ts +113 -0
- package/lib/runs-process.ts +210 -34
- package/lib/runs-results.ts +601 -0
- package/lib/runs-retention.ts +134 -10
- package/lib/runs-session-exports.ts +406 -0
- package/lib/runs-snapshot.ts +143 -0
- package/lib/runs-start.ts +44 -2
- package/lib/runs-status.ts +252 -10
- package/lib/runs-supervision.ts +394 -0
- package/lib/runs-trace.ts +14 -3
- package/lib/runtime.ts +22 -3
- package/lib/session-evidence.ts +76 -4
- package/lib/state-readers.ts +16 -7
- package/lib/temp.ts +3 -56
- package/lib/tools-access.ts +13 -0
- package/lib/tools-inspect.ts +110 -51
- package/lib/tools-local.ts +37 -24
- package/lib/tools-message.ts +120 -37
- package/lib/tools-response.ts +273 -50
- package/lib/tools-spawn.ts +31 -10
- package/lib/trace-projection.ts +165 -42
- package/package.json +10 -6
- package/scripts/async-runner.mjs +272 -194
- package/scripts/conformance.mjs +14 -2
- package/skills/actors/SKILL.md +47 -3
- package/skills/actors/references/diagnostics.md +40 -0
- package/skills/actors/references/runs.md +56 -2
- package/banner.jpg +0 -0
- package/dist/lib/inspector-actions.d.ts +0 -16
- package/dist/lib/inspector-actions.js +0 -57
- package/lib/inspector-actions.ts +0 -79
package/lib/tools-local.ts
CHANGED
|
@@ -15,12 +15,15 @@ import * as RecipesReferences from "./recipes-references.ts";
|
|
|
15
15
|
import * as RecipesUsage from "./recipes-usage.ts";
|
|
16
16
|
import * as Schema from "./schema.ts";
|
|
17
17
|
import * as ToolsResponse from "./tools-response.ts";
|
|
18
|
+
import { readRunFileNavigationForContext } from "./tools-access.ts";
|
|
18
19
|
|
|
19
20
|
type JsonSchema = Schema.JsonSchema;
|
|
20
21
|
|
|
21
22
|
export interface RuntimeToolContext extends ModelContext.CurrentModelContext {
|
|
22
23
|
recipeResolutionContext?: RecipeResolution.RecipeResolutionContext;
|
|
23
24
|
cwd: string;
|
|
25
|
+
/** Kernel-injected only; never sourced from tool input/actor values. */
|
|
26
|
+
onSupervisionClockCaptured?: AsyncRuns.AsyncRunStartOptions["onSupervisionClockCaptured"];
|
|
24
27
|
sessionManager?: { getSessionId?: () => string };
|
|
25
28
|
}
|
|
26
29
|
|
|
@@ -213,6 +216,11 @@ export function createRuntimeToolDefinition(
|
|
|
213
216
|
_onUpdate: unknown,
|
|
214
217
|
ctx: RuntimeToolContext,
|
|
215
218
|
) {
|
|
219
|
+
let dispatchEntered = false;
|
|
220
|
+
const execute: Execution.RegisteredToolExec = (...args) => {
|
|
221
|
+
dispatchEntered = true;
|
|
222
|
+
return exec(...args);
|
|
223
|
+
};
|
|
216
224
|
try {
|
|
217
225
|
if (
|
|
218
226
|
cfg.sourcePath &&
|
|
@@ -231,37 +239,40 @@ export function createRuntimeToolDefinition(
|
|
|
231
239
|
: typeof run_id === "string" && run_id.trim()
|
|
232
240
|
? run_id.trim()
|
|
233
241
|
: `${cfg.name}-${Date.now()}`;
|
|
242
|
+
const startParams: AsyncRuns.AsyncRunStartParams = {
|
|
243
|
+
...base,
|
|
244
|
+
launch_source: "tool",
|
|
245
|
+
launch_correlation: { tool_call_id: toolCallId },
|
|
246
|
+
...(transport_context &&
|
|
247
|
+
typeof transport_context === "object" &&
|
|
248
|
+
!Array.isArray(transport_context)
|
|
249
|
+
? {
|
|
250
|
+
transport_context: transport_context as Record<string, unknown>,
|
|
251
|
+
} : {}),
|
|
252
|
+
ownerId: getRunOwnerId(ctx),
|
|
253
|
+
run_id: runId,
|
|
254
|
+
tool: cfg.name,
|
|
255
|
+
policy_values: ModelContext.withCurrentModelValues(
|
|
256
|
+
{ ...(cfg.recipe?.values ?? {}), ...values },
|
|
257
|
+
ctx,
|
|
258
|
+
),
|
|
259
|
+
values: resolveRecipeToolValues(cfg, values, ctx),
|
|
260
|
+
};
|
|
261
|
+
dispatchEntered = true;
|
|
234
262
|
const meta = AsyncRuns.startRun(
|
|
235
|
-
|
|
236
|
-
...base,
|
|
237
|
-
launch_source: "tool",
|
|
238
|
-
launch_correlation: { tool_call_id: toolCallId },
|
|
239
|
-
...(transport_context &&
|
|
240
|
-
typeof transport_context === "object" &&
|
|
241
|
-
!Array.isArray(transport_context)
|
|
242
|
-
? {
|
|
243
|
-
transport_context: transport_context as Record<string, unknown>,
|
|
244
|
-
} : {}),
|
|
245
|
-
ownerId: getRunOwnerId(ctx),
|
|
246
|
-
run_id: runId,
|
|
247
|
-
tool: cfg.name,
|
|
248
|
-
policy_values: ModelContext.withCurrentModelValues(
|
|
249
|
-
{ ...(cfg.recipe?.values ?? {}), ...values },
|
|
250
|
-
ctx,
|
|
251
|
-
),
|
|
252
|
-
values: resolveRecipeToolValues(cfg, values, ctx),
|
|
253
|
-
},
|
|
263
|
+
startParams,
|
|
254
264
|
ctx.cwd,
|
|
255
|
-
{ skillContext: ctx.recipeResolutionContext?.activeSkills },
|
|
265
|
+
{ skillContext: ctx.recipeResolutionContext?.activeSkills, onSupervisionClockCaptured: ctx.onSupervisionClockCaptured },
|
|
256
266
|
);
|
|
267
|
+
const details = { ...meta, file_navigation: readRunFileNavigationForContext(meta, ctx) };
|
|
257
268
|
return {
|
|
258
269
|
content: [
|
|
259
270
|
{
|
|
260
271
|
type: "text" as const,
|
|
261
|
-
text: ToolsResponse.compactAsyncRunStatus(
|
|
272
|
+
text: ToolsResponse.compactAsyncRunStatus(details),
|
|
262
273
|
},
|
|
263
274
|
],
|
|
264
|
-
details
|
|
275
|
+
details,
|
|
265
276
|
};
|
|
266
277
|
}
|
|
267
278
|
if (isRecipe && recipeTemplate) {
|
|
@@ -272,7 +283,7 @@ export function createRuntimeToolDefinition(
|
|
|
272
283
|
params as Record<string, unknown>,
|
|
273
284
|
ctx,
|
|
274
285
|
),
|
|
275
|
-
|
|
286
|
+
execute,
|
|
276
287
|
ctx.cwd,
|
|
277
288
|
signal,
|
|
278
289
|
);
|
|
@@ -286,11 +297,13 @@ export function createRuntimeToolDefinition(
|
|
|
286
297
|
),
|
|
287
298
|
cfg.argTypes,
|
|
288
299
|
),
|
|
289
|
-
|
|
300
|
+
execute,
|
|
290
301
|
ctx.cwd,
|
|
291
302
|
signal,
|
|
292
303
|
);
|
|
293
304
|
} catch (error) {
|
|
305
|
+
// Dispatch entry is not effect/closure proof; matching error text cannot justify argument repair or retry.
|
|
306
|
+
if (dispatchEntered) throw error;
|
|
294
307
|
throw formatRuntimeToolArgumentError(
|
|
295
308
|
cfg,
|
|
296
309
|
error,
|
package/lib/tools-message.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Public Control facade under the stable `message` tool name.
|
|
3
|
-
* Zones: Control request validation, Run/runtime dispatch,
|
|
3
|
+
* Zones: Control request validation, Run/runtime dispatch, recipient-scoped receipts
|
|
4
4
|
* Owns public Control execution; journaling, delivery, and lifecycle mutation stay in Run domains.
|
|
5
5
|
*/
|
|
6
6
|
|
|
@@ -8,6 +8,7 @@ import * as AsyncRuns from "./async-runs.ts";
|
|
|
8
8
|
import * as Control from "./control.ts";
|
|
9
9
|
import * as Schema from "./schema.ts";
|
|
10
10
|
import * as ToolsAccess from "./tools-access.ts";
|
|
11
|
+
import * as Limits from "./limits.ts";
|
|
11
12
|
import * as ToolsResponse from "./tools-response.ts";
|
|
12
13
|
|
|
13
14
|
function asRecord(value: unknown): Record<string, unknown> {
|
|
@@ -16,32 +17,92 @@ function asRecord(value: unknown): Record<string, unknown> {
|
|
|
16
17
|
: {};
|
|
17
18
|
}
|
|
18
19
|
|
|
19
|
-
|
|
20
|
+
const controlField = ToolsResponse.formatMarkdownField;
|
|
21
|
+
|
|
22
|
+
/** Only the four compiler-owned guard sites below; never wraps dispatch/dependency errors. */
|
|
23
|
+
function controlGuardText(
|
|
24
|
+
request: Control.ControlRequest,
|
|
25
|
+
result: "unsupported runtime Control action" | "runtime Control is unavailable" | "Run generation unavailable" | "undeclared Run Control action",
|
|
26
|
+
options?: { key: "supported_actions" | "available_actions"; values: readonly string[] },
|
|
27
|
+
): string {
|
|
28
|
+
const key = request.target === "runtime" ? "target" : "run";
|
|
29
|
+
const identity = controlField(key, request.target === "runtime" ? request.target : request.target.slice(4));
|
|
30
|
+
const omittedIdentity = `- ${key}: [omitted]\n- ${key}_omission:\n - reason: response_too_large\n - shown: 0\n - omitted: 1\n - total: 1`;
|
|
31
|
+
const fixed = [controlField("action", request.action), controlField("result", result)];
|
|
32
|
+
let fullOptions = "", omittedOptions = "";
|
|
33
|
+
if (options) {
|
|
34
|
+
const rows: string[] = [];
|
|
35
|
+
let malformed = false;
|
|
36
|
+
// Values were selected by the original string filter, not by a new action grammar.
|
|
37
|
+
for (let index = 0; index < options.values.length; index++) {
|
|
38
|
+
const value = options.values[index];
|
|
39
|
+
if (!value.isWellFormed()) { malformed = true; break; }
|
|
40
|
+
rows.push(" - " + value.replaceAll(/\r\n|\r|\n/gu, newline => newline + " "));
|
|
41
|
+
}
|
|
42
|
+
omittedOptions = `- ${options.key}: [${malformed ? "unavailable" : "omitted"}]\n- ${options.key}_omission:\n - reason: ${malformed ? "malformed_selected_text" : "response_too_large"}\n - shown: 0\n - omitted: ${options.values.length}\n - total: ${options.values.length}`;
|
|
43
|
+
fullOptions = malformed ? omittedOptions : rows.length ? `- ${options.key}:\n${rows.join("\n")}` : controlField(options.key, "none");
|
|
44
|
+
}
|
|
45
|
+
// Start with the shorter complete-or-omitted rendering: adding an omission scaffold must
|
|
46
|
+
// never manufacture overflow when the complete small field would fit. Then grow only.
|
|
47
|
+
let selectedIdentity = Buffer.byteLength(identity) <= Buffer.byteLength(omittedIdentity) ? identity : omittedIdentity;
|
|
48
|
+
let selectedOptions = Buffer.byteLength(fullOptions) <= Buffer.byteLength(omittedOptions) ? fullOptions : omittedOptions;
|
|
49
|
+
const render = (target: string, choices: string) => ToolsResponse.withLeadingLineBreak(
|
|
50
|
+
[target, ...fixed, ...(options ? [choices] : [])].join("\n"));
|
|
51
|
+
if (Buffer.byteLength(render(identity, selectedOptions)) <= Limits.RUN_DELIVERY_MODEL_MAX_BYTES) selectedIdentity = identity;
|
|
52
|
+
if (options && Buffer.byteLength(render(selectedIdentity, fullOptions)) <= Limits.RUN_DELIVERY_MODEL_MAX_BYTES) selectedOptions = fullOptions;
|
|
53
|
+
return render(selectedIdentity, selectedOptions);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function controlNext(action: string): string {
|
|
57
|
+
const inspect = /^inspect target=([^\s]+) view=([^\s]+)$/u.exec(action);
|
|
58
|
+
return inspect ? ToolsResponse.formatInspectNextAction(inspect[1], inspect[2])
|
|
59
|
+
: "- next:\n" + controlField("instruction", action, 1);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/** Pure first-layer copy; legacy stopped/killed flags are not scope-closure proof. */
|
|
63
|
+
export function compactControlResult(
|
|
20
64
|
request: Control.ControlRequest,
|
|
21
65
|
result: Record<string, unknown>,
|
|
22
66
|
): string {
|
|
23
|
-
const
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
if (
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
);
|
|
67
|
+
const fields = [request.target.startsWith("run:") ? controlField("run", request.target.slice(4)) : controlField("target", request.target),
|
|
68
|
+
controlField("action", request.action)];
|
|
69
|
+
if (result.stopped === false || result.archived === false || result.pruned === false) {
|
|
70
|
+
fields.push(controlField("result", "not applied"));
|
|
71
|
+
if (typeof result.reason === "string") fields.push(controlField("reason", result.reason));
|
|
72
|
+
const observed = asRecord(result.status);
|
|
73
|
+
if (result.reason === "not running" && typeof observed.status === "string") fields.push(controlField("state", observed.status));
|
|
74
|
+
} else if (request.action === "kill" && result.stopped === true) {
|
|
75
|
+
fields.push(controlField("result", "kill attempted"), controlField("termination", "unconfirmed"));
|
|
76
|
+
} else if (result.archived === true) {
|
|
77
|
+
fields.push(controlField("result", "archived"));
|
|
78
|
+
} else if (result.pruned === true) {
|
|
79
|
+
fields.push(controlField("result", "pruned"));
|
|
80
|
+
} else if (result.delivery === "queued" || result.delivery === "delivered") {
|
|
81
|
+
fields.push(controlField("delivery", result.delivery), controlField("handling", "unconfirmed"));
|
|
82
|
+
} else {
|
|
83
|
+
fields.push(controlField(typeof result.delivery === "string" ? "delivery" : "result",
|
|
84
|
+
typeof result.delivery === "string" ? result.delivery : typeof result.status === "string" ? result.status : "accepted"));
|
|
85
|
+
if (typeof result.reason === "string") fields.push(controlField("reason", result.reason));
|
|
36
86
|
}
|
|
37
|
-
|
|
87
|
+
if (typeof result.control_id === "string") fields.push(controlField("control_id", result.control_id));
|
|
88
|
+
const actions = Array.isArray(result.next_actions) ? result.next_actions
|
|
89
|
+
: request.target.startsWith("run:") ? runNextActions(request.target.slice(4), result) : [];
|
|
90
|
+
const next = actions.find((action): action is string => typeof action === "string" && action.length > 0);
|
|
91
|
+
if (next) fields.push(controlNext(next));
|
|
92
|
+
return ToolsResponse.withLeadingLineBreak(fields.join("\n"));
|
|
38
93
|
}
|
|
39
94
|
|
|
40
95
|
function runNextActions(run: string, result: Record<string, unknown>): string[] {
|
|
96
|
+
if (result.stopped === true) return [`inspect target=run:${run} view=trace`];
|
|
97
|
+
if (result.stopped === false || result.archived === false || result.pruned === false) {
|
|
98
|
+
if (result.reason === "ownership changed" || result.reason === "run generation changed") {
|
|
99
|
+
return ["inspect target=runtime view=runs"];
|
|
100
|
+
}
|
|
101
|
+
if (result.stopped === false && result.reason !== "not running") return [`inspect target=run:${run} view=trace`];
|
|
102
|
+
}
|
|
41
103
|
if (result.delivery === "queued" || result.delivery === "delivered") {
|
|
42
104
|
return [`inspect target=run:${run} view=control`];
|
|
43
105
|
}
|
|
44
|
-
if (result.stopped === true) return [`inspect target=run:${run} view=control`];
|
|
45
106
|
return [];
|
|
46
107
|
}
|
|
47
108
|
|
|
@@ -85,12 +146,12 @@ export function createControlToolDefinition<TContext = unknown>(
|
|
|
85
146
|
let result: Record<string, unknown>;
|
|
86
147
|
if (request.target === "runtime") {
|
|
87
148
|
if (request.action !== "review.retry" && request.action !== "review.reset") {
|
|
88
|
-
throw new Error(
|
|
89
|
-
|
|
90
|
-
);
|
|
149
|
+
throw new Error(controlGuardText(request, "unsupported runtime Control action", {
|
|
150
|
+
key: "supported_actions", values: ["review.retry", "review.reset"],
|
|
151
|
+
}));
|
|
91
152
|
}
|
|
92
153
|
if (!deps.handleRuntimeControl) {
|
|
93
|
-
throw new Error("runtime Control is unavailable");
|
|
154
|
+
throw new Error(controlGuardText(request, "runtime Control is unavailable"));
|
|
94
155
|
}
|
|
95
156
|
result = deps.handleRuntimeControl(request.action, request.input);
|
|
96
157
|
} else {
|
|
@@ -106,7 +167,7 @@ export function createControlToolDefinition<TContext = unknown>(
|
|
|
106
167
|
typeof status.run_instance_id === "string"
|
|
107
168
|
? status.run_instance_id
|
|
108
169
|
: undefined;
|
|
109
|
-
if (!runInstanceId) throw new Error(
|
|
170
|
+
if (!runInstanceId) throw new Error(controlGuardText(request, "Run generation unavailable"));
|
|
110
171
|
if (request.action === "kill") {
|
|
111
172
|
result = AsyncRuns.killRun(run, {
|
|
112
173
|
...(typeof status.ownerId === "string"
|
|
@@ -144,23 +205,45 @@ export function createControlToolDefinition<TContext = unknown>(
|
|
|
144
205
|
)
|
|
145
206
|
: [];
|
|
146
207
|
if (!declared.includes(request.action)) {
|
|
147
|
-
throw
|
|
148
|
-
|
|
208
|
+
// The old join/template evaluation may itself throw or have observable hooks.
|
|
209
|
+
// Preserve it before the new presentation; it is not an action-list parser.
|
|
210
|
+
void `${declared.join(",") || "none"}`;
|
|
211
|
+
throw new Error(controlGuardText(request, "undeclared Run Control action", {
|
|
212
|
+
key: "available_actions", values: declared,
|
|
213
|
+
}));
|
|
214
|
+
}
|
|
215
|
+
try {
|
|
216
|
+
result = await AsyncRuns.sendRunControl(
|
|
217
|
+
run,
|
|
218
|
+
{
|
|
219
|
+
action: request.action,
|
|
220
|
+
...(request.input !== undefined ? { input: request.input } : {}),
|
|
221
|
+
run_instance_id: runInstanceId,
|
|
222
|
+
},
|
|
223
|
+
{
|
|
224
|
+
...(typeof status.ownerId === "string"
|
|
225
|
+
? { ownerId: status.ownerId }
|
|
226
|
+
: {}),
|
|
227
|
+
},
|
|
149
228
|
);
|
|
229
|
+
} catch (cause) {
|
|
230
|
+
// Admission-era correlation is not current reply-scope proof after an awaited dispatch.
|
|
231
|
+
const summary = [controlField("action", request.action), controlField("result", "request failed"),
|
|
232
|
+
controlField("delivery", "unconfirmed"), controlField("handling", "unconfirmed"),
|
|
233
|
+
controlField("warning", "Effects may already exist.\nDo not repeat automatically."),
|
|
234
|
+
controlNext("inspect target=runtime view=runs")].join("\n");
|
|
235
|
+
// Reserve both line breaks; display one whole caller-owned id or explicit whole-id omission.
|
|
236
|
+
const identity = controlField("run", run);
|
|
237
|
+
const target = Buffer.byteLength(identity) <= Limits.RUN_DELIVERY_MODEL_MAX_BYTES - Buffer.byteLength(summary) - 2
|
|
238
|
+
? identity
|
|
239
|
+
: "- run: [omitted]\n- run_omission:\n - reason: response_too_large\n - shown: 0\n - omitted: 1\n - total: 1";
|
|
240
|
+
throw new Error(ToolsResponse.withLeadingLineBreak(target + "\n" + summary), { cause });
|
|
150
241
|
}
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
run_instance_id: runInstanceId,
|
|
157
|
-
},
|
|
158
|
-
{
|
|
159
|
-
...(typeof status.ownerId === "string"
|
|
160
|
-
? { ownerId: status.ownerId }
|
|
161
|
-
: {}),
|
|
162
|
-
},
|
|
163
|
-
);
|
|
242
|
+
}
|
|
243
|
+
// A refused identity change must not publish the replacement's status, even in verbose/details.
|
|
244
|
+
if (result.reason === "ownership changed" || result.reason === "run generation changed") {
|
|
245
|
+
result = { ...result };
|
|
246
|
+
delete result.status;
|
|
164
247
|
}
|
|
165
248
|
const nextActions = runNextActions(run, result);
|
|
166
249
|
if (nextActions.length > 0) result = { ...result, next_actions: nextActions };
|