@llblab/pi-actors 0.56.1 → 0.57.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 +7 -7
- package/BACKLOG.md +4 -14
- package/CHANGELOG.md +13 -0
- package/README.md +7 -2
- package/dist/lib/execution-output.js +13 -2
- package/dist/lib/observability.js +9 -14
- package/dist/lib/registry.js +82 -117
- package/dist/lib/run-delivery.d.ts +1 -1
- package/dist/lib/run-delivery.js +146 -32
- package/dist/lib/run-ui-runtime.js +18 -27
- package/dist/lib/runs-process-windows-mi.d.ts +71 -0
- package/dist/lib/runs-process-windows-mi.js +146 -3
- package/dist/lib/tools-inspect.js +109 -59
- package/dist/lib/tools-local.js +16 -8
- package/dist/lib/tools-message.js +76 -65
- package/dist/lib/tools-response.d.ts +18 -0
- package/dist/lib/tools-response.js +88 -21
- package/dist/lib/tools-spawn.js +19 -12
- package/dist/skills/actors/SKILL.md +1 -1
- package/dist/skills/actors/references/diagnostics.md +3 -0
- package/dist/skills/actors/references/runs.md +1 -1
- package/docs/README.md +1 -0
- package/docs/actor-inspector.md +2 -2
- package/docs/agent-experience.md +51 -4
- package/docs/coordinator-delivery.md +2 -2
- package/docs/inactive-foundations-inventory.md +73 -0
- package/docs/inspection.md +9 -8
- package/docs/output-projection-map.md +19 -17
- package/docs/windows-process-observation.md +2 -2
- package/lib/execution-output.ts +13 -2
- package/lib/observability.ts +9 -11
- package/lib/registry.ts +89 -124
- package/lib/run-delivery.ts +130 -31
- package/lib/run-ui-runtime.ts +18 -34
- package/lib/runs-process-windows-mi.ts +167 -3
- package/lib/tools-inspect.ts +109 -59
- package/lib/tools-local.ts +26 -15
- package/lib/tools-message.ts +85 -58
- package/lib/tools-response.ts +97 -20
- package/lib/tools-spawn.ts +19 -12
- package/package.json +1 -1
- package/skills/actors/SKILL.md +1 -1
- package/skills/actors/references/diagnostics.md +3 -0
- package/skills/actors/references/runs.md +1 -1
package/dist/lib/registry.js
CHANGED
|
@@ -82,6 +82,19 @@ function registrationNextActions(tool, source, callableNow) {
|
|
|
82
82
|
: [recipeDoctorAction(source)]),
|
|
83
83
|
];
|
|
84
84
|
}
|
|
85
|
+
const REGISTRY_METADATA_BUDGET = Limits.RUN_DELIVERY_MODEL_MAX_BYTES - 1;
|
|
86
|
+
/** Bare block-YAML registry document; builders own whole-value/omission policy and the byte budget. */
|
|
87
|
+
function registryMetadataText(value) {
|
|
88
|
+
return ToolsResponse.renderYamlMetadata(value, REGISTRY_METADATA_BUDGET).text;
|
|
89
|
+
}
|
|
90
|
+
/** One opaque selected scalar as a whole value or an explicit whole-field omission, never a clip. */
|
|
91
|
+
function registrySelected(key, value) {
|
|
92
|
+
return ToolsResponse.selectYamlField(key, value, REGISTRY_METADATA_BUDGET);
|
|
93
|
+
}
|
|
94
|
+
/** Grow whole selected fields in priority order while the complete document still fits. */
|
|
95
|
+
function growRegistryDocument(render, order) {
|
|
96
|
+
return ToolsResponse.growYamlDocument(render, order, REGISTRY_METADATA_BUDGET);
|
|
97
|
+
}
|
|
85
98
|
/** Read-time text only: callers supply the original post-activation selections, not live ports. */
|
|
86
99
|
function registrationReceiptText(data) {
|
|
87
100
|
const budget = Limits.RUN_DELIVERY_MODEL_MAX_BYTES - 1;
|
|
@@ -144,78 +157,33 @@ function registryNoticeText(kind, name) {
|
|
|
144
157
|
return ToolsResponse.formatMarkdownField("report", report) + "\n" + selected;
|
|
145
158
|
}
|
|
146
159
|
function registrationTransactionFailureText(stage, generation, summary, error) {
|
|
147
|
-
const
|
|
148
|
-
const
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
return { full, selected: Buffer.byteLength(full) <= Buffer.byteLength(omitted) ? full : omitted };
|
|
153
|
-
};
|
|
154
|
-
const selectedGeneration = part("resolution_generation", generation);
|
|
155
|
-
const selectedSummary = part("active_skills_summary", summary);
|
|
156
|
-
const selectedError = part("error", error);
|
|
157
|
-
const render = () => [field("result", "Tool registration transaction failed."), field("stage", stage),
|
|
158
|
-
selectedGeneration.selected, selectedSummary.selected, selectedError.selected].join("\n");
|
|
160
|
+
const selectedGeneration = registrySelected("resolution_generation", generation);
|
|
161
|
+
const selectedSummary = registrySelected("active_skills_summary", summary);
|
|
162
|
+
const selectedError = registrySelected("error", error);
|
|
163
|
+
const render = () => ({ result: "Tool registration transaction failed.", stage,
|
|
164
|
+
...selectedGeneration.selected, ...selectedSummary.selected, ...selectedError.selected });
|
|
159
165
|
// Keep a fitting surfaced error before large optional resolution metadata.
|
|
160
|
-
|
|
161
|
-
if (current.selected === current.full)
|
|
162
|
-
continue;
|
|
163
|
-
const previous = current.selected;
|
|
164
|
-
current.selected = current.full;
|
|
165
|
-
if (Buffer.byteLength(render()) > Limits.RUN_DELIVERY_MODEL_MAX_BYTES - 1)
|
|
166
|
-
current.selected = previous;
|
|
167
|
-
}
|
|
168
|
-
return render();
|
|
166
|
+
return growRegistryDocument(render, [selectedError, selectedGeneration, selectedSummary]);
|
|
169
167
|
}
|
|
170
168
|
function candidateAdmissionFailureText(data) {
|
|
171
|
-
const
|
|
172
|
-
const
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
const diagnostics = part("diagnostics_summary", data.diagnostics);
|
|
179
|
-
const source = data.kind === "source" ? part("source", data.source, true) : undefined;
|
|
180
|
-
const summary = data.kind === "source" ? part("active_skills_summary", data.summary) : undefined;
|
|
181
|
-
const instruction = data.kind === "source" ? part("instruction", data.instruction) : undefined;
|
|
182
|
-
const render = () => [field("field", "recipe"), ...(source ? [source.selected] : []),
|
|
183
|
-
field("result", data.kind === "source" ? "Recipe source validation failed." : "Tool recipe validation failed."),
|
|
184
|
-
diagnostics.selected, ...(summary ? [summary.selected] : []), ...(instruction ? [instruction.selected] : [])].join("\n");
|
|
169
|
+
const diagnostics = registrySelected("diagnostics_summary", data.diagnostics);
|
|
170
|
+
const source = data.kind === "source" ? registrySelected("source", data.source) : undefined;
|
|
171
|
+
const summary = data.kind === "source" ? registrySelected("active_skills_summary", data.summary) : undefined;
|
|
172
|
+
const instruction = data.kind === "source" ? registrySelected("instruction", data.instruction) : undefined;
|
|
173
|
+
const render = () => ({ field: "recipe", ...(source ? source.selected : {}),
|
|
174
|
+
result: data.kind === "source" ? "Recipe source validation failed." : "Tool recipe validation failed.",
|
|
175
|
+
...diagnostics.selected, ...(summary ? summary.selected : {}), ...(instruction ? instruction.selected : {}) });
|
|
185
176
|
// Preserve fitting diagnostics before large optional source/context/advice fields.
|
|
186
|
-
|
|
187
|
-
if (!current || current.selected === current.full)
|
|
188
|
-
continue;
|
|
189
|
-
const previous = current.selected;
|
|
190
|
-
current.selected = current.full;
|
|
191
|
-
if (Buffer.byteLength(render()) > Limits.RUN_DELIVERY_MODEL_MAX_BYTES - 1)
|
|
192
|
-
current.selected = previous;
|
|
193
|
-
}
|
|
194
|
-
return render();
|
|
177
|
+
return growRegistryDocument(render, [diagnostics, ...(source ? [source] : []), ...(summary ? [summary] : []), ...(instruction ? [instruction] : [])]);
|
|
195
178
|
}
|
|
196
179
|
function sourceNormalizationFailureText(source, reason, summary, instruction) {
|
|
197
|
-
const
|
|
198
|
-
const
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
const selectedSource = part("source", source, true);
|
|
205
|
-
const selectedReason = part("reason", reason);
|
|
206
|
-
const selectedSummary = part("active_skills_summary", summary);
|
|
207
|
-
const selectedInstruction = part("instruction", instruction);
|
|
208
|
-
const render = () => [field("field", "from"), selectedSource.selected, field("result", "Recipe source is invalid."),
|
|
209
|
-
selectedReason.selected, selectedSummary.selected, selectedInstruction.selected].join("\n");
|
|
210
|
-
for (const current of [selectedSource, selectedReason, selectedSummary, selectedInstruction]) {
|
|
211
|
-
if (current.selected === current.full)
|
|
212
|
-
continue;
|
|
213
|
-
const previous = current.selected;
|
|
214
|
-
current.selected = current.full;
|
|
215
|
-
if (Buffer.byteLength(render()) > Limits.RUN_DELIVERY_MODEL_MAX_BYTES - 1)
|
|
216
|
-
current.selected = previous;
|
|
217
|
-
}
|
|
218
|
-
return render();
|
|
180
|
+
const selectedSource = registrySelected("source", source);
|
|
181
|
+
const selectedReason = registrySelected("reason", reason);
|
|
182
|
+
const selectedSummary = registrySelected("active_skills_summary", summary);
|
|
183
|
+
const selectedInstruction = registrySelected("instruction", instruction);
|
|
184
|
+
const render = () => ({ field: "from", ...selectedSource.selected, result: "Recipe source is invalid.",
|
|
185
|
+
...selectedReason.selected, ...selectedSummary.selected, ...selectedInstruction.selected });
|
|
186
|
+
return growRegistryDocument(render, [selectedSource, selectedReason, selectedSummary, selectedInstruction]);
|
|
219
187
|
}
|
|
220
188
|
function activeSkillSummary(resolutionContext) {
|
|
221
189
|
const names = Object.keys(RecipesReferences.getActiveSkillRecipeNamespaces(resolutionContext.activeSkills))
|
|
@@ -224,17 +192,11 @@ function activeSkillSummary(resolutionContext) {
|
|
|
224
192
|
return names.length > 0 ? names.join(", ") : "<none>";
|
|
225
193
|
}
|
|
226
194
|
function draftPathFailureText(kind, reference) {
|
|
227
|
-
const
|
|
228
|
-
const render = (
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
if (wellFormed) {
|
|
233
|
-
const complete = render(ToolsResponse.formatMarkdownField(key, ToolsResponse.formatLiteralBlock(reference)));
|
|
234
|
-
if (Buffer.byteLength(complete) <= Limits.RUN_DELIVERY_MODEL_MAX_BYTES - 1)
|
|
235
|
-
return complete;
|
|
236
|
-
}
|
|
237
|
-
return render(`- ${key}: [${wellFormed ? "omitted" : "unavailable"}]\n- ${key}_omission:\n - reason: ${wellFormed ? "response_too_large" : "malformed_selected_text"}\n - shown: 0\n - omitted: 1\n - total: 1`);
|
|
195
|
+
const selected = registrySelected(kind === "root" ? "allowed_root" : "path", reference);
|
|
196
|
+
const render = () => ({ field: "draft", ...selected.selected,
|
|
197
|
+
result: kind === "root" ? "Draft must be under the allowed root." : "Draft not found.",
|
|
198
|
+
...(kind === "root" ? { instruction: "Use inspect target=recipes view=summary to list drafts." } : {}) });
|
|
199
|
+
return growRegistryDocument(render, [selected]);
|
|
238
200
|
}
|
|
239
201
|
function assertDraftPath(deps, draft) {
|
|
240
202
|
const draftRoot = resolve(getRecipeRoot(deps), "drafts");
|
|
@@ -278,26 +240,15 @@ function draftReceiptText(result, tool, callable, next) {
|
|
|
278
240
|
return render().text;
|
|
279
241
|
}
|
|
280
242
|
function duplicateRegistrationText(value) {
|
|
281
|
-
const
|
|
282
|
-
const
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
if (Buffer.byteLength(complete) <= Limits.RUN_DELIVERY_MODEL_MAX_BYTES - 1)
|
|
286
|
-
return complete;
|
|
287
|
-
}
|
|
288
|
-
return render(`- value: [${wellFormed ? "omitted" : "unavailable"}]\n- value_omission:\n - reason: ${wellFormed ? "response_too_large" : "malformed_selected_text"}\n - shown: 0\n - omitted: 1\n - total: 1`);
|
|
243
|
+
const selected = registrySelected("value", value);
|
|
244
|
+
const render = () => ({ field: "name", ...selected.selected,
|
|
245
|
+
result: "Tool already registered.", instruction: "Use update=true to overwrite." });
|
|
246
|
+
return growRegistryDocument(render, [selected]);
|
|
289
247
|
}
|
|
290
248
|
function draftRecipeFailureText(key, value) {
|
|
291
|
-
const
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
const wellFormed = value.isWellFormed();
|
|
295
|
-
if (wellFormed) {
|
|
296
|
-
const complete = header + "\n" + ToolsResponse.formatMarkdownField(key, value);
|
|
297
|
-
if (Buffer.byteLength(complete) <= Limits.RUN_DELIVERY_MODEL_MAX_BYTES - 1)
|
|
298
|
-
return complete;
|
|
299
|
-
}
|
|
300
|
-
return header + `\n- ${key}: [${wellFormed ? "omitted" : "unavailable"}]\n- ${key}_omission:\n - reason: ${wellFormed ? "response_too_large" : "malformed_selected_text"}\n - shown: 0\n - omitted: 1\n - total: 1`;
|
|
249
|
+
const selected = value === undefined ? undefined : registrySelected(key, value);
|
|
250
|
+
const render = () => ({ field: "draft", result: "Draft recipe is invalid.", ...(selected ? selected.selected : {}) });
|
|
251
|
+
return growRegistryDocument(render, selected ? [selected] : []);
|
|
301
252
|
}
|
|
302
253
|
function promoteDraftRecipe(name, input, ctx, deps) {
|
|
303
254
|
const draftPath = assertDraftPath(deps, String(input.draft ?? ""));
|
|
@@ -438,7 +389,9 @@ function assertTemplateIsNotNestedRecipe(value) {
|
|
|
438
389
|
looksLikeRecipeReference(record.template) &&
|
|
439
390
|
(Object.keys(record).length === 1 ||
|
|
440
391
|
["artifacts", "async", "control", "description", "imports", "values"].some((key) => Object.hasOwn(record, key)))) {
|
|
441
|
-
throw new Error(ExecutionOutput.formatToolText(
|
|
392
|
+
throw new Error(ExecutionOutput.formatToolText(registryMetadataText({ field: "template",
|
|
393
|
+
result: "Nested Recipe-shaped templates are not a register_tool source mode.",
|
|
394
|
+
instruction: "retry with from=<skill>/<recipe> and defaults={...}." })));
|
|
442
395
|
}
|
|
443
396
|
}
|
|
444
397
|
function getInputTemplate(value) {
|
|
@@ -452,14 +405,15 @@ function getInputTemplate(value) {
|
|
|
452
405
|
template: value,
|
|
453
406
|
});
|
|
454
407
|
if (steps.length === 0)
|
|
455
|
-
throw new Error(ExecutionOutput.formatToolText(
|
|
408
|
+
throw new Error(ExecutionOutput.formatToolText(registryMetadataText({ field: "template", result: "Tool template sequence is empty." })));
|
|
456
409
|
return value;
|
|
457
410
|
}
|
|
458
411
|
if (value && typeof value === "object") {
|
|
459
412
|
CommandTemplates.expandCommandTemplateConfigs(value);
|
|
460
413
|
return value;
|
|
461
414
|
}
|
|
462
|
-
throw new Error(ExecutionOutput.formatToolText(
|
|
415
|
+
throw new Error(ExecutionOutput.formatToolText(registryMetadataText({ field: "template", result: "unsupported template type",
|
|
416
|
+
supported_types: ["string", "object", "sequence"] })));
|
|
463
417
|
}
|
|
464
418
|
function getRegistrationResolutionContext(ctx, deps) {
|
|
465
419
|
const runtimeContext = deps.getRecipeResolutionContext?.();
|
|
@@ -476,7 +430,7 @@ function normalizeDefaults(value) {
|
|
|
476
430
|
if (value === undefined)
|
|
477
431
|
return undefined;
|
|
478
432
|
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
479
|
-
throw new Error(ExecutionOutput.formatToolText(
|
|
433
|
+
throw new Error(ExecutionOutput.formatToolText(registryMetadataText({ field: "defaults", result: "Tool defaults must be an object." })));
|
|
480
434
|
}
|
|
481
435
|
return { ...value };
|
|
482
436
|
}
|
|
@@ -508,13 +462,17 @@ function buildAuthoredRecipe(input, existing, existingRecipe) {
|
|
|
508
462
|
const from = typeof input.from === "string" ? input.from.trim() : "";
|
|
509
463
|
const description = (input.description ?? existing?.description ?? "").trim();
|
|
510
464
|
if (!description && !from) {
|
|
511
|
-
throw new Error(ExecutionOutput.formatToolText(
|
|
465
|
+
throw new Error(ExecutionOutput.formatToolText(registryMetadataText({ field: "description",
|
|
466
|
+
result: "Tool description is required for command-template registration." })));
|
|
512
467
|
}
|
|
513
468
|
const inputDefaults = normalizeDefaults(input.defaults);
|
|
514
469
|
if (from) {
|
|
515
470
|
const runtimeOwnedDefault = Object.keys(inputDefaults ?? {}).find((key) => RecipesReferences.isRuntimeOwnedRecipeInput(key));
|
|
516
471
|
if (runtimeOwnedDefault) {
|
|
517
|
-
throw new Error(ExecutionOutput.formatToolText(
|
|
472
|
+
throw new Error(ExecutionOutput.formatToolText(registryMetadataText({ field: "defaults",
|
|
473
|
+
...registrySelected("key", runtimeOwnedDefault).selected,
|
|
474
|
+
result: "Tool defaults cannot set runtime-owned input.",
|
|
475
|
+
instruction: "remove that default and retry register_tool; the runtime supplies it." })));
|
|
518
476
|
}
|
|
519
477
|
const authored = {
|
|
520
478
|
...(description ? { description } : {}),
|
|
@@ -530,13 +488,13 @@ function buildAuthoredRecipe(input, existing, existingRecipe) {
|
|
|
530
488
|
}
|
|
531
489
|
const template = getInputTemplate(input.template);
|
|
532
490
|
if (template === null) {
|
|
533
|
-
throw new Error(ExecutionOutput.formatToolText(
|
|
491
|
+
throw new Error(ExecutionOutput.formatToolText(registryMetadataText({ field: "template", result: "Tool template cannot be null here." })));
|
|
534
492
|
}
|
|
535
493
|
const finalTemplate = template === undefined || template === ""
|
|
536
494
|
? existingRecipe?.template ?? existing?.template
|
|
537
495
|
: template;
|
|
538
496
|
if (!finalTemplate) {
|
|
539
|
-
throw new Error(ExecutionOutput.formatToolText(
|
|
497
|
+
throw new Error(ExecutionOutput.formatToolText(registryMetadataText({ field: "template", result: "Tool template is required." })));
|
|
540
498
|
}
|
|
541
499
|
const authored = {
|
|
542
500
|
...(existingRecipe ?? {}),
|
|
@@ -564,33 +522,38 @@ function buildAuthoredRecipe(input, existing, existingRecipe) {
|
|
|
564
522
|
function assertRegisterToolInputModes(input) {
|
|
565
523
|
const record = input;
|
|
566
524
|
if (Object.hasOwn(record, "values")) {
|
|
567
|
-
throw new Error(ExecutionOutput.formatToolText(
|
|
525
|
+
throw new Error(ExecutionOutput.formatToolText(registryMetadataText({ field: "values", result: "register_tool values was removed.",
|
|
526
|
+
replacement_fields: ["defaults", "from"],
|
|
527
|
+
instruction: "retry register_tool with defaults for caller inputs, or use from=<skill>/<recipe> for maintained composition." })));
|
|
568
528
|
}
|
|
569
529
|
const fromProvided = Object.hasOwn(record, "from");
|
|
570
530
|
if (fromProvided &&
|
|
571
531
|
(typeof input.from !== "string" || input.from.trim().length === 0)) {
|
|
572
|
-
throw new Error(ExecutionOutput.formatToolText(
|
|
532
|
+
throw new Error(ExecutionOutput.formatToolText(registryMetadataText({ field: "from",
|
|
533
|
+
result: "Tool from must be a non-empty Recipe reference.",
|
|
534
|
+
reference_forms: ["<skill>/<recipe>", "explicit .json path", "explicit .md path"],
|
|
535
|
+
instruction: "retry register_tool with from=<skill>/<recipe> or an explicit .json/.md path." })));
|
|
573
536
|
}
|
|
574
537
|
const draftProvided = typeof input.draft === "string" && input.draft.trim().length > 0;
|
|
575
538
|
const templateProvided = Object.hasOwn(record, "template");
|
|
576
539
|
const modeCount = Number(fromProvided) + Number(draftProvided) + Number(templateProvided);
|
|
577
540
|
if (modeCount > 1) {
|
|
578
|
-
throw new Error(ExecutionOutput.formatToolText(
|
|
541
|
+
throw new Error(ExecutionOutput.formatToolText(registryMetadataText({ result: "Use exactly one register_tool source mode.",
|
|
542
|
+
source_modes: ["from", "template", "draft"],
|
|
543
|
+
instruction: "remove the extra source fields and retry register_tool." })));
|
|
579
544
|
}
|
|
580
545
|
if (fromProvided &&
|
|
581
546
|
(Object.hasOwn(record, "args") || Object.hasOwn(record, "async"))) {
|
|
582
|
-
throw new Error(ExecutionOutput.formatToolText(
|
|
547
|
+
throw new Error(ExecutionOutput.formatToolText(registryMetadataText({ field: "from",
|
|
548
|
+
result: "register_tool from inherits args and async behavior.",
|
|
549
|
+
inherited_fields: ["args", "async"],
|
|
550
|
+
instruction: "retry register_tool with from and optional defaults only; omit args and async." })));
|
|
583
551
|
}
|
|
584
552
|
}
|
|
585
553
|
function reservedRegistrationNameText(value) {
|
|
586
|
-
const
|
|
587
|
-
const
|
|
588
|
-
|
|
589
|
-
const complete = render(ToolsResponse.formatMarkdownField("value", value));
|
|
590
|
-
if (Buffer.byteLength(complete) <= Limits.RUN_DELIVERY_MODEL_MAX_BYTES - 1)
|
|
591
|
-
return complete;
|
|
592
|
-
}
|
|
593
|
-
return render(`- value: [${wellFormed ? "omitted" : "unavailable"}]\n- value_omission:\n - reason: ${wellFormed ? "response_too_large" : "malformed_selected_text"}\n - shown: 0\n - omitted: 1\n - total: 1`);
|
|
554
|
+
const selected = registrySelected("value", value);
|
|
555
|
+
const render = () => ({ field: "name", ...selected.selected, result: "Reserved tool name." });
|
|
556
|
+
return growRegistryDocument(render, [selected]);
|
|
594
557
|
}
|
|
595
558
|
function executeRegisterToolUnlocked(params, ctx, deps) {
|
|
596
559
|
const rawInput = params && typeof params === "object"
|
|
@@ -602,7 +565,7 @@ function executeRegisterToolUnlocked(params, ctx, deps) {
|
|
|
602
565
|
return listTools(deps);
|
|
603
566
|
const name = Identity.normalizeToolName(input.name);
|
|
604
567
|
if (!name)
|
|
605
|
-
throw new Error(ExecutionOutput.formatToolText(
|
|
568
|
+
throw new Error(ExecutionOutput.formatToolText(registryMetadataText({ field: "name", result: "Invalid tool name." })));
|
|
606
569
|
if (deps.reservedToolNames.has(name)) {
|
|
607
570
|
throw new Error(ExecutionOutput.formatToolText(reservedRegistrationNameText(`${name}`)));
|
|
608
571
|
}
|
|
@@ -640,7 +603,9 @@ function executeRegisterToolUnlocked(params, ctx, deps) {
|
|
|
640
603
|
throw new Error(ExecutionOutput.formatToolText(duplicateRegistrationText(`${name}`)));
|
|
641
604
|
}
|
|
642
605
|
if (template === undefined && !input.from && !existing) {
|
|
643
|
-
throw new Error(ExecutionOutput.formatToolText(
|
|
606
|
+
throw new Error(ExecutionOutput.formatToolText(registryMetadataText({ result: "New registration requires exactly one source mode.",
|
|
607
|
+
source_modes: ["from", "template", "draft"],
|
|
608
|
+
instruction: "retry register_tool with one source field." })));
|
|
644
609
|
}
|
|
645
610
|
const recipePath = getToolRecipePath(deps, name);
|
|
646
611
|
const authoredRecipe = buildAuthoredRecipe(input, existing, authoritative.recipe);
|
|
@@ -66,7 +66,7 @@ export interface RunCompletionBatch {
|
|
|
66
66
|
/** Retained singleton capture; absence preserves older indexed bytes. Never a new-capture selector. */
|
|
67
67
|
readonly single_result?: true;
|
|
68
68
|
/** Captured record-list shape; no public format/version choice or source authority. */
|
|
69
|
-
readonly result_layout?: "records" | "run_headers" | "headings" | "headings_flat_omissions" | "headings_outcomes" | "headings_shared_results" | "headings_shared_kinds" | "frontmatter_v1" | "frontmatter_v2" | "completion_yaml_core_v1";
|
|
69
|
+
readonly result_layout?: "records" | "run_headers" | "headings" | "headings_flat_omissions" | "headings_outcomes" | "headings_shared_results" | "headings_shared_kinds" | "frontmatter_v1" | "frontmatter_v2" | "completion_yaml_core_v1" | "completion_yaml_files_v1";
|
|
70
70
|
/** Immutable scope/order/range data, not a caller-selected format or allocation authority. */
|
|
71
71
|
readonly numbering?: RunCompletionNumbering;
|
|
72
72
|
/** Formatting version/data only; no recipient ownership, read or publication capability. */
|