@llblab/pi-actors 0.44.0 → 0.45.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/CHANGELOG.md +7 -0
- package/README.md +3 -1
- package/dist/index.js +7 -3
- package/dist/lib/async-runs.d.ts +2 -0
- package/dist/lib/async-runs.js +33 -4
- package/dist/lib/config.js +1 -0
- package/dist/lib/inspector.js +8 -2
- package/dist/lib/recipes-discovery.js +20 -3
- package/dist/lib/recipes-references.d.ts +10 -0
- package/dist/lib/recipes-references.js +168 -5
- package/dist/lib/schema.d.ts +3 -0
- package/dist/lib/schema.js +34 -1
- package/dist/lib/tools-inspect.js +10 -0
- package/dist/lib/tools-local.js +27 -10
- package/dist/lib/tools-spawn.js +2 -2
- package/dist/scripts/release-gates.mjs +1 -1
- package/dist/skills/actors/SKILL.md +2 -2
- package/docs/command-templates.md +2 -2
- package/docs/recipe-library.md +2 -0
- package/docs/template-recipes.md +10 -4
- package/docs/tool-registry.md +1 -1
- package/index.ts +9 -3
- package/lib/async-runs.ts +43 -9
- package/lib/config.ts +4 -0
- package/lib/inspector.ts +16 -2
- package/lib/recipes-discovery.ts +23 -3
- package/lib/recipes-references.ts +227 -7
- package/lib/schema.ts +53 -1
- package/lib/tools-inspect.ts +11 -0
- package/lib/tools-local.ts +49 -19
- package/lib/tools-spawn.ts +2 -2
- package/package.json +1 -1
- package/scripts/release-gates.mjs +1 -1
- package/skills/actors/SKILL.md +2 -2
package/dist/lib/tools-local.js
CHANGED
|
@@ -45,11 +45,16 @@ function shouldAddRuntimeToolUsageHint(error) {
|
|
|
45
45
|
}
|
|
46
46
|
function formatRuntimeToolUsageHint(cfg, required, includeRunId) {
|
|
47
47
|
const optional = cfg.args.filter((arg) => !required.includes(arg));
|
|
48
|
+
const exampleDefaults = {
|
|
49
|
+
...Schema.getExplicitToolArgDefaults(cfg.recipe?.args),
|
|
50
|
+
...cfg.defaults,
|
|
51
|
+
...(cfg.recipe?.values ?? {}),
|
|
52
|
+
};
|
|
48
53
|
const example = {};
|
|
49
54
|
for (const arg of required)
|
|
50
|
-
example[arg] = sampleValueForArg(arg, cfg.argTypes?.[arg],
|
|
55
|
+
example[arg] = sampleValueForArg(arg, cfg.argTypes?.[arg], exampleDefaults);
|
|
51
56
|
for (const arg of optional)
|
|
52
|
-
example[arg] = sampleValueForArg(arg, cfg.argTypes?.[arg],
|
|
57
|
+
example[arg] = sampleValueForArg(arg, cfg.argTypes?.[arg], exampleDefaults);
|
|
53
58
|
if (includeRunId)
|
|
54
59
|
example.run_id = `${cfg.name}-1`;
|
|
55
60
|
const lines = [
|
|
@@ -62,6 +67,21 @@ function formatRuntimeToolUsageHint(cfg, required, includeRunId) {
|
|
|
62
67
|
lines.push(`Optional: ${[...optional, ...(includeRunId ? ["run_id"] : [])].join(", ")}`);
|
|
63
68
|
return lines.join("\n");
|
|
64
69
|
}
|
|
70
|
+
function resolveRecipeToolValues(cfg, callerValues, ctx) {
|
|
71
|
+
const recipeRuntimeValues = {
|
|
72
|
+
...(cfg.recipe?.recipe_dir
|
|
73
|
+
? { recipe_dir: cfg.recipe.recipe_dir }
|
|
74
|
+
: {}),
|
|
75
|
+
...(cfg.recipe?.skill_dir ? { skill_dir: cfg.recipe.skill_dir } : {}),
|
|
76
|
+
};
|
|
77
|
+
return Schema.normalizeRuntimeValues(ModelContext.withCurrentModelValues({
|
|
78
|
+
...Schema.getExplicitToolArgDefaults(cfg.recipe?.args),
|
|
79
|
+
...cfg.defaults,
|
|
80
|
+
...(cfg.recipe?.values ?? {}),
|
|
81
|
+
...callerValues,
|
|
82
|
+
...recipeRuntimeValues,
|
|
83
|
+
}, ctx), cfg.argTypes);
|
|
84
|
+
}
|
|
65
85
|
function formatRuntimeToolArgumentError(cfg, error, required, includeRunId) {
|
|
66
86
|
const message = error instanceof Error ? error.message : String(error);
|
|
67
87
|
if (!shouldAddRuntimeToolUsageHint(error))
|
|
@@ -87,8 +107,10 @@ export function createRuntimeToolDefinition(cfg, exec) {
|
|
|
87
107
|
defaults: cfg.defaults,
|
|
88
108
|
template: requiredTemplate,
|
|
89
109
|
};
|
|
110
|
+
const recipeInlineDefaults = Schema.getExplicitToolArgDefaults(cfg.recipe?.args);
|
|
90
111
|
const requiredArgs = isRecipe && cfg.storedArgs !== undefined
|
|
91
|
-
? new Set(cfg.args.filter((arg) => !Object.hasOwn(cfg.defaults, arg)
|
|
112
|
+
? new Set(cfg.args.filter((arg) => !Object.hasOwn(cfg.defaults, arg) &&
|
|
113
|
+
!Object.hasOwn(recipeInlineDefaults, arg)))
|
|
92
114
|
: RecipesReferences.isRecipeReference(cfg.template) && !recipeTemplate
|
|
93
115
|
? new Set(cfg.args.filter((arg) => !Object.hasOwn(cfg.defaults, arg)))
|
|
94
116
|
: Schema.getRequiredToolArgNames(requiredTemplateConfig);
|
|
@@ -137,7 +159,7 @@ export function createRuntimeToolDefinition(cfg, exec) {
|
|
|
137
159
|
run_id: runId,
|
|
138
160
|
tool: cfg.name,
|
|
139
161
|
policy_values: ModelContext.withCurrentModelValues({ ...(cfg.recipe?.values ?? {}), ...values }, ctx),
|
|
140
|
-
values:
|
|
162
|
+
values: resolveRecipeToolValues(cfg, values, ctx),
|
|
141
163
|
}, ctx.cwd);
|
|
142
164
|
return {
|
|
143
165
|
content: [
|
|
@@ -150,12 +172,7 @@ export function createRuntimeToolDefinition(cfg, exec) {
|
|
|
150
172
|
};
|
|
151
173
|
}
|
|
152
174
|
if (isRecipe && recipeTemplate) {
|
|
153
|
-
|
|
154
|
-
...(cfg.recipe?.values ?? {}),
|
|
155
|
-
...cfg.defaults,
|
|
156
|
-
...params,
|
|
157
|
-
}, ctx);
|
|
158
|
-
return await Execution.executeRegisteredTool({ ...cfg, template: recipeTemplate }, Schema.normalizeRuntimeValues(paramsWithDefaults, cfg.argTypes), exec, ctx.cwd, signal);
|
|
175
|
+
return await Execution.executeRegisteredTool({ ...cfg, template: recipeTemplate }, resolveRecipeToolValues(cfg, params, ctx), exec, ctx.cwd, signal);
|
|
159
176
|
}
|
|
160
177
|
return await Execution.executeRegisteredTool(cfg, Schema.normalizeRuntimeValues(ModelContext.withCurrentModelValues(params, ctx), cfg.argTypes), exec, ctx.cwd, signal);
|
|
161
178
|
}
|
package/dist/lib/tools-spawn.js
CHANGED
|
@@ -90,8 +90,8 @@ export function createSpawnToolDefinition() {
|
|
|
90
90
|
parameters: Schema.objectSchema({
|
|
91
91
|
artifacts: Schema.looseObjectSchema("Optional named artifact paths for the spawned Run."),
|
|
92
92
|
as: Schema.stringSchema("Optional Run identity in exact run:<id> form."),
|
|
93
|
-
file: Schema.stringSchema("Optional template
|
|
94
|
-
recipe: Schema.stringSchema("Alias for file;
|
|
93
|
+
file: Schema.stringSchema("Optional template Recipe reference. Supports paths, bare user/adjacent/std names, std:<name>, and skill:<skill>/<recipe>."),
|
|
94
|
+
recipe: Schema.stringSchema("Alias for file; qualified Skill/std or ordinary Recipe reference to spawn."),
|
|
95
95
|
template: Schema.unionSchema([
|
|
96
96
|
Schema.stringSchema("Inline command template string"),
|
|
97
97
|
Schema.arraySchema("Inline command-template sequence or parallel tree"),
|
|
@@ -198,7 +198,7 @@ try {
|
|
|
198
198
|
);
|
|
199
199
|
console.log("[release] zero-warning Recipe QA gate checked");
|
|
200
200
|
|
|
201
|
-
const maximumShippedLines =
|
|
201
|
+
const maximumShippedLines = 29_767;
|
|
202
202
|
const shippedPath = /^(?:lib\/|scripts\/|recipes\/|docs\/|skills\/)/u;
|
|
203
203
|
const shippedLines = files
|
|
204
204
|
.filter((path) => shippedPath.test(path))
|
|
@@ -25,11 +25,11 @@ A Run target exposes exactly three inspect views: `recipe`, `trace`, and `contro
|
|
|
25
25
|
|
|
26
26
|
## Recipe
|
|
27
27
|
|
|
28
|
-
A Recipe defines execution. It may declare args,
|
|
28
|
+
A Recipe defines execution. It may declare named typed args, inline fallbacks, configuration `defaults`, composition `values`, imports, artifacts, command-template flags, and `control: ["action"]` when a long-lived service actually consumes actor-local inputs.
|
|
29
29
|
|
|
30
30
|
Do not declare Control for ordinary one-shot work. Runtime lifecycle actions such as `kill` stay runtime-owned and must not appear in Recipe Control declarations. Imported Recipes act as local definitions inside one Run; they do not create nested Runs unless execution explicitly spawns them.
|
|
31
31
|
|
|
32
|
-
Prefer maintained packaged Recipes over ad hoc wrappers. Keep model, thinking, mission, concurrency, quorum, and timeout choices caller-owned unless a Recipe documents a stable policy.
|
|
32
|
+
Prefer maintained packaged Recipes over ad hoc wrappers. Use `std:<recipe>` for exact packaged lookup and `skill:<skill>/<recipe-path>` for a component bundled with a Pi-active Skill. File-backed Recipes own `{recipe_dir}` and Skill Recipes own `{skill_dir}`; callers never pass or override these origins. Skill Recipes are components, not automatic tools. Keep model, thinking, mission, concurrency, quorum, and timeout choices caller-owned unless a Recipe documents a stable policy.
|
|
33
33
|
|
|
34
34
|
## Trace
|
|
35
35
|
|
|
@@ -53,7 +53,7 @@ Common object fields:
|
|
|
53
53
|
- `concurrency`: Optional positive integer cap for a `parallel: true` node. Omit it to launch all children at once.
|
|
54
54
|
- `min_successful`: Optional non-negative integer evidence threshold for a `parallel: true` node. Usable branches are successful branches with non-empty stdout; joins include a `parallel_status` header when this is set.
|
|
55
55
|
- `when`: Optional node guard. A false guard skips the node; strings may be `flag`, `!flag`, or `{flag?yes:no}` style expressions.
|
|
56
|
-
- `args`: Optional placeholder declarations. Untyped names remain valid; compact typed forms such as `file:path`, `request_timeout:int`, `speed:number`, `dry_run:bool`, `prompts:array`, and `mode:enum(check,fix)` are valid when the host supports typed tool schemas.
|
|
56
|
+
- `args`: Optional placeholder declarations. Untyped names remain valid; compact typed forms such as `file:path`, `request_timeout:int`, `speed:number`, `dry_run:bool`, `prompts:array`, and `mode:enum(check,fix)` are valid when the host supports typed tool schemas. `name:type=value` is an optional argument with an inline fallback. Hosts reject duplicate names and conflicting declared/placeholder types rather than selecting one silently.
|
|
57
57
|
- `defaults`: Placeholder default values by name.
|
|
58
58
|
- `timeout`: Optional execution timeout in milliseconds. Omit it, or set `0`, to leave the command unbounded. Set an explicit positive timeout when a tool must fail closed instead of waiting indefinitely. Numeric control fields may be literal numbers or placeholders such as `"{timeout_ms}"`.
|
|
59
59
|
- `delay`: Optional wait in milliseconds before starting this node. Default is no delay. It may be a literal number or placeholder.
|
|
@@ -104,7 +104,7 @@ With runtime values `{ "text": "hello" }`, argv is:
|
|
|
104
104
|
["--text", "hello", "--lang", "ru", "--rate", "+30%"]
|
|
105
105
|
```
|
|
106
106
|
|
|
107
|
-
Use `defaults` for visible configuration
|
|
107
|
+
Use `defaults` for visible fallback configuration, `values` for composition binding, and inline defaults for compact local literals. Named resolution uses caller values before composition values, explicit defaults, and inline defaults; the final selected value is type/enum validated. Prefer flag-style examples such as `/path/to/tool --file {file} --lang {lang=ru}` for readability, but positional forms such as `/path/to/tool {file} {lang=ru}` are valid when the invoked script defines that CLI contract.
|
|
108
108
|
|
|
109
109
|
Use `{env??dev}` for fallback values and `{all?--all:}` to map boolean args to optional text.
|
|
110
110
|
|
package/docs/recipe-library.md
CHANGED
|
@@ -45,6 +45,8 @@ Subagent components provide reusable command-template cells for normalization, p
|
|
|
45
45
|
|
|
46
46
|
Imports compose these definitions inside one parent Run. They are not independently addressable peers. Parent template flags control sequencing, parallelism, retries, failure scope, recovery, and repeated execution.
|
|
47
47
|
|
|
48
|
+
Packaged components can be selected exactly as `std:<recipe-name>`. Recipes bundled under a Pi-active Skill are selected as `skill:<skill-name>/<recipe-path>` and receive runtime-owned `{skill_dir}` plus `{recipe_dir}`. Active Skill components are namespaced library entries, never automatic tools; expose one intentionally through a user Recipe wrapper when a direct tool is desired.
|
|
49
|
+
|
|
48
50
|
## Utility Recipes
|
|
49
51
|
|
|
50
52
|
Utilities wrap deterministic local capabilities such as:
|
package/docs/template-recipes.md
CHANGED
|
@@ -44,7 +44,7 @@ Fences marked `template`, `command-template`, `json`, or `recipe` can define exe
|
|
|
44
44
|
Common Recipe fields:
|
|
45
45
|
|
|
46
46
|
- `name`, `description`, `disabled`;
|
|
47
|
-
- `args`, typed arg declarations, and `
|
|
47
|
+
- `args`, typed arg declarations, inline defaults, `defaults`, and composition `values`;
|
|
48
48
|
- `imports` with optional binding defaults/values;
|
|
49
49
|
- `template`;
|
|
50
50
|
- `async`;
|
|
@@ -71,7 +71,9 @@ Common Recipe fields:
|
|
|
71
71
|
}
|
|
72
72
|
```
|
|
73
73
|
|
|
74
|
-
Imports are local definitions. Named nodes call imported templates inside the same execution graph and Run.
|
|
74
|
+
Imports are local definitions. Named nodes call imported templates inside the same execution graph and Run. Effective values follow `caller > node/import/Recipe values > defaults > inline arg default > missing-value error`, then the selected value is checked against its declared type or enum.
|
|
75
|
+
|
|
76
|
+
Bare references preserve user → adjacent → packaged resolution. `std:<name>` selects a packaged Recipe exactly. `skill:<skill-name>/<recipe-path>` selects a component under the `recipes/` tree of a Skill currently active through Pi resource discovery. Skill Recipes never become tools merely by existing, and duplicate active Skill names fail as ambiguous rather than shadowing silently.
|
|
75
77
|
|
|
76
78
|
Direct delegation can use another Recipe as the entire template. The delegated Recipe remains the source of truth while the wrapper may narrow args/defaults or override selected lifecycle metadata.
|
|
77
79
|
|
|
@@ -102,9 +104,13 @@ Actions must be lowercase ASCII, unique, non-reserved, and at most 64 characters
|
|
|
102
104
|
|
|
103
105
|
Artifact paths resolve under containment policy and appear in Run inspection. Recipes should write declared artifacts deterministically and fail when the requested write policy cannot be honored.
|
|
104
106
|
|
|
107
|
+
## File Origins
|
|
108
|
+
|
|
109
|
+
Every file-backed Recipe receives immutable `{recipe_dir}`. A Recipe under an active Skill also receives `{skill_dir}`, resolved to the directory containing that Skill's `SKILL.md`; using `{skill_dir}` elsewhere fails clearly. These runtime values cannot be declared in `args`, `defaults`, or `values`, and caller input cannot override them. They expand in templates, recursive defaults/values, imports, and artifacts while existing `./` executable behavior remains relative to invocation `cwd`.
|
|
110
|
+
|
|
105
111
|
## Context and Provenance
|
|
106
112
|
|
|
107
|
-
File-backed Runs capture Recipe context records for the entry and imports. The captured bundle explains composition identity and remains generation-local evidence. It does not override the authored task prompt.
|
|
113
|
+
File-backed Runs capture Recipe context records for the entry and imports, including qualified `std:` or `skill:` identity when applicable. The captured bundle explains composition identity and remains generation-local evidence. Runtime origin paths remain in local Run provenance but are omitted from model-facing launch values. It does not override the authored task prompt.
|
|
108
114
|
|
|
109
115
|
Recipes that need a minimal child prompt may opt out of injected Recipe context through the documented `actor_context` launch option.
|
|
110
116
|
|
|
@@ -125,7 +131,7 @@ Resolution fails before launch when required current policy is unavailable. The
|
|
|
125
131
|
|
|
126
132
|
## Resolution and Shadowing
|
|
127
133
|
|
|
128
|
-
User Recipes under `~/.pi/agent/recipes` take priority over packaged Recipes. An invalid active file blocks fallback and reports both paths. Disabled Recipes cannot launch. Registry watchers converge after atomic changes without executing partial definitions.
|
|
134
|
+
User Recipes under `~/.pi/agent/recipes` take priority over adjacent and packaged Recipes for compatible bare lookup. Exact `std:` and `skill:` references bypass that ambiguous space. The active Skill namespace converges from Pi's loaded Skill metadata on startup/reload; pi-actors does not scan ambient Skill roots independently. An invalid active file blocks fallback and reports both paths. Disabled Recipes cannot launch. Registry watchers converge after atomic changes without executing partial definitions.
|
|
129
135
|
|
|
130
136
|
## Validation
|
|
131
137
|
|
package/docs/tool-registry.md
CHANGED
|
@@ -61,7 +61,7 @@ Usage and lineage live in locked metadata ledgers rather than authored Recipe fi
|
|
|
61
61
|
|
|
62
62
|
## Wrapping Existing Recipes
|
|
63
63
|
|
|
64
|
-
Prefer a small user-root wrapper that imports a maintained
|
|
64
|
+
Prefer a small user-root wrapper that imports a maintained Recipe by exact `std:<recipe>` or `skill:<skill>/<recipe-path>` identity and delegates by alias. Skill Recipes remain components and are never exposed merely because their Skill is active. Do not duplicate executable templates, defaults, Control declarations, artifacts, or runtime-owned `{recipe_dir}`/`{skill_dir}`. Install only specific capabilities; internal automatic-review Recipes must not become user-callable tools.
|
|
65
65
|
|
|
66
66
|
## Safety
|
|
67
67
|
|
package/index.ts
CHANGED
|
@@ -11,6 +11,7 @@ import * as InspectorCommand from "./lib/inspector-command.ts";
|
|
|
11
11
|
import * as Paths from "./lib/paths.ts";
|
|
12
12
|
import * as Pi from "./lib/pi.ts";
|
|
13
13
|
import * as Prompts from "./lib/prompts.ts";
|
|
14
|
+
import * as RecipesReferences from "./lib/recipes-references.ts";
|
|
14
15
|
import * as RunUiRuntime from "./lib/run-ui-runtime.ts";
|
|
15
16
|
import * as Runtime from "./lib/runtime.ts";
|
|
16
17
|
import * as Temp from "./lib/temp.ts";
|
|
@@ -98,9 +99,14 @@ export default function toolRegistryExtension(pi: Pi.ExtensionAPI) {
|
|
|
98
99
|
runUiRuntime.shutdown(event.reason, ctx);
|
|
99
100
|
});
|
|
100
101
|
InspectorCommand.registerActorInspectorCommand(pi, getRunOwnerId);
|
|
101
|
-
pi.on("before_agent_start", async (event) =>
|
|
102
|
-
|
|
103
|
-
|
|
102
|
+
pi.on("before_agent_start", async (event) => {
|
|
103
|
+
RecipesReferences.setActiveSkillRecipeSources(
|
|
104
|
+
event.systemPromptOptions.skills ?? [],
|
|
105
|
+
);
|
|
106
|
+
return {
|
|
107
|
+
systemPrompt: `${event.systemPrompt}\n\n${Prompts.ONBOARDING_SYSTEM_PROMPT}`,
|
|
108
|
+
};
|
|
109
|
+
});
|
|
104
110
|
Pi.registerToolDefinitions(
|
|
105
111
|
pi,
|
|
106
112
|
Tools.createCoreActorToolDefinitions<Pi.ExtensionContext>({
|
package/lib/async-runs.ts
CHANGED
|
@@ -33,6 +33,7 @@ import {
|
|
|
33
33
|
import * as Paths from "./paths.ts";
|
|
34
34
|
import * as RecipesReferences from "./recipes-references.ts";
|
|
35
35
|
import * as RecipesUsage from "./recipes-usage.ts";
|
|
36
|
+
import * as Schema from "./schema.ts";
|
|
36
37
|
import {
|
|
37
38
|
resolveArtifactManifest,
|
|
38
39
|
resolveArtifactPaths,
|
|
@@ -128,6 +129,8 @@ export interface AsyncRunStartParams {
|
|
|
128
129
|
template?: CommandTemplateValue;
|
|
129
130
|
args?: string[];
|
|
130
131
|
defaults?: Record<string, unknown>;
|
|
132
|
+
recipe_dir?: string;
|
|
133
|
+
skill_dir?: string;
|
|
131
134
|
parallel?: boolean;
|
|
132
135
|
concurrency?: number | string;
|
|
133
136
|
min_successful?: number | string;
|
|
@@ -309,7 +312,14 @@ function resolveStartParams(params: AsyncRunStartParams): AsyncRunStartParams {
|
|
|
309
312
|
fileParams.run_id ||
|
|
310
313
|
fileParams.name ||
|
|
311
314
|
getRunIdFromFile(fileParams.file),
|
|
312
|
-
values: {
|
|
315
|
+
values: {
|
|
316
|
+
...(fileParams.values ?? {}),
|
|
317
|
+
...(params.values ?? {}),
|
|
318
|
+
...(fileParams.recipe_dir
|
|
319
|
+
? { recipe_dir: fileParams.recipe_dir }
|
|
320
|
+
: {}),
|
|
321
|
+
...(fileParams.skill_dir ? { skill_dir: fileParams.skill_dir } : {}),
|
|
322
|
+
},
|
|
313
323
|
};
|
|
314
324
|
}
|
|
315
325
|
|
|
@@ -477,13 +487,37 @@ export function startRun(
|
|
|
477
487
|
!isAbsolute(recipeRelation)
|
|
478
488
|
? dirname(packagedRecipeRoot)
|
|
479
489
|
: undefined;
|
|
480
|
-
const
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
}
|
|
490
|
+
const argSpec = Schema.parseToolArgDeclarationList(startParams.args ?? []);
|
|
491
|
+
if (argSpec.error) throw new Error(argSpec.error);
|
|
492
|
+
const declaredArgs = new Set(argSpec.args);
|
|
493
|
+
for (const key of Object.keys(startParams.defaults ?? {})) {
|
|
494
|
+
if (declaredArgs.size > 0 && !declaredArgs.has(key))
|
|
495
|
+
throw new Error(`Unknown Recipe default argument: ${key}`);
|
|
496
|
+
}
|
|
497
|
+
const values = Schema.normalizeRuntimeValues(
|
|
498
|
+
{
|
|
499
|
+
...argSpec.defaults,
|
|
500
|
+
...(startParams.defaults || {}),
|
|
501
|
+
...(packagedRepo ? { repo: packagedRepo } : {}),
|
|
502
|
+
...(startParams.values || {}),
|
|
503
|
+
run_id: run,
|
|
504
|
+
state_dir: stateDir,
|
|
505
|
+
trace_file: join(stateDir, "trace.jsonl"),
|
|
506
|
+
},
|
|
507
|
+
argSpec.argTypes,
|
|
508
|
+
);
|
|
509
|
+
const runtimeTemplate =
|
|
510
|
+
resolved.template &&
|
|
511
|
+
typeof resolved.template === "object" &&
|
|
512
|
+
!Array.isArray(resolved.template)
|
|
513
|
+
? {
|
|
514
|
+
...resolved.template,
|
|
515
|
+
defaults: {
|
|
516
|
+
...(resolved.template.defaults ?? {}),
|
|
517
|
+
...values,
|
|
518
|
+
},
|
|
519
|
+
}
|
|
520
|
+
: resolved.template;
|
|
487
521
|
const modelPolicy = describeCurrentPolicyProvenance({
|
|
488
522
|
defaults: startParams.defaults,
|
|
489
523
|
template: resolved.template,
|
|
@@ -557,7 +591,7 @@ export function startRun(
|
|
|
557
591
|
state_schema: RuntimeIdentity.RUN_STATE_SCHEMA,
|
|
558
592
|
status: "running",
|
|
559
593
|
...(startParams.tool ? { tool: startParams.tool } : {}),
|
|
560
|
-
template:
|
|
594
|
+
template: runtimeTemplate,
|
|
561
595
|
values,
|
|
562
596
|
model_policy: modelPolicy,
|
|
563
597
|
...(artifacts ? { artifacts } : {}),
|
package/lib/config.ts
CHANGED
|
@@ -188,6 +188,10 @@ export function normalizeStoredTool(
|
|
|
188
188
|
template: argTemplate,
|
|
189
189
|
};
|
|
190
190
|
const inferredArgTypes = Schema.getTemplateArgTypes(argTemplateConfig);
|
|
191
|
+
Schema.assertCompatibleToolArgTypes(
|
|
192
|
+
inferredArgTypes,
|
|
193
|
+
declarations.argTypes,
|
|
194
|
+
);
|
|
191
195
|
const argTypes = { ...inferredArgTypes, ...declarations.argTypes };
|
|
192
196
|
const cfg = {
|
|
193
197
|
name,
|
package/lib/inspector.ts
CHANGED
|
@@ -105,9 +105,22 @@ export function readActorInspectorRecipe(
|
|
|
105
105
|
const redactedRecord = (value: Record<string, unknown>): Record<string, unknown> =>
|
|
106
106
|
SessionEvidence.redactSessionEvidenceValue(
|
|
107
107
|
Object.fromEntries(
|
|
108
|
-
Object.entries(value).filter(
|
|
108
|
+
Object.entries(value).filter(
|
|
109
|
+
([key, entry]) =>
|
|
110
|
+
entry !== undefined &&
|
|
111
|
+
key !== "recipe_dir" &&
|
|
112
|
+
key !== "skill_dir",
|
|
113
|
+
),
|
|
109
114
|
),
|
|
110
115
|
) as Record<string, unknown>;
|
|
116
|
+
const launchValues =
|
|
117
|
+
meta.values && typeof meta.values === "object" && !Array.isArray(meta.values)
|
|
118
|
+
? Object.fromEntries(
|
|
119
|
+
Object.entries(meta.values as Record<string, unknown>).filter(
|
|
120
|
+
([key]) => key !== "recipe_dir" && key !== "skill_dir",
|
|
121
|
+
),
|
|
122
|
+
)
|
|
123
|
+
: meta.values;
|
|
111
124
|
return {
|
|
112
125
|
composition: contexts.map((entry) =>
|
|
113
126
|
redactedRecord({
|
|
@@ -116,6 +129,7 @@ export function readActorInspectorRecipe(
|
|
|
116
129
|
file: entry.file,
|
|
117
130
|
import_path: entry.import_path,
|
|
118
131
|
name: entry.name,
|
|
132
|
+
qualified_name: entry.qualified_name,
|
|
119
133
|
}),
|
|
120
134
|
),
|
|
121
135
|
...(definition ? { definition: redactedRecord(definition) } : {}),
|
|
@@ -129,7 +143,7 @@ export function readActorInspectorRecipe(
|
|
|
129
143
|
launch: redactedRecord({
|
|
130
144
|
cwd: meta.cwd,
|
|
131
145
|
template: meta.template,
|
|
132
|
-
values:
|
|
146
|
+
values: launchValues,
|
|
133
147
|
model_policy: meta.model_policy,
|
|
134
148
|
control: meta.control,
|
|
135
149
|
artifacts: meta.artifacts,
|
package/lib/recipes-discovery.ts
CHANGED
|
@@ -122,6 +122,25 @@ function getRecipeCommandTemplateConfig(
|
|
|
122
122
|
: config) as CommandTemplates.CommandTemplateConfig;
|
|
123
123
|
}
|
|
124
124
|
|
|
125
|
+
function getRecipeDiagnosticTemplateConfig(
|
|
126
|
+
config: TemplateRecipeConfig,
|
|
127
|
+
): CommandTemplates.CommandTemplateObjectConfig {
|
|
128
|
+
const templateConfig = getRecipeCommandTemplateConfig(config);
|
|
129
|
+
return typeof templateConfig === "object" && !Array.isArray(templateConfig)
|
|
130
|
+
? {
|
|
131
|
+
...templateConfig,
|
|
132
|
+
defaults: {
|
|
133
|
+
...(templateConfig.defaults ?? {}),
|
|
134
|
+
...(config.defaults ?? {}),
|
|
135
|
+
...(config.values ?? {}),
|
|
136
|
+
},
|
|
137
|
+
}
|
|
138
|
+
: {
|
|
139
|
+
defaults: { ...(config.defaults ?? {}), ...(config.values ?? {}) },
|
|
140
|
+
template: templateConfig,
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
|
|
125
144
|
function getRecipeConfigDiagnostics(
|
|
126
145
|
file: string,
|
|
127
146
|
config: TemplateRecipeConfig | undefined,
|
|
@@ -131,7 +150,7 @@ function getRecipeConfigDiagnostics(
|
|
|
131
150
|
return [`Invalid recipe: ${file}${reason ? `: ${reason}` : ""}`];
|
|
132
151
|
}
|
|
133
152
|
return CommandTemplates.getCommandTemplateWarnings(
|
|
134
|
-
|
|
153
|
+
getRecipeDiagnosticTemplateConfig(config),
|
|
135
154
|
).map((warning) => `Recipe ${file}: ${warning}`);
|
|
136
155
|
}
|
|
137
156
|
|
|
@@ -141,7 +160,7 @@ function getRecipeRiskLabels(
|
|
|
141
160
|
if (!config) return [];
|
|
142
161
|
const labels = new Set(
|
|
143
162
|
CommandTemplates.getCommandTemplateRiskLabels(
|
|
144
|
-
|
|
163
|
+
getRecipeDiagnosticTemplateConfig(config),
|
|
145
164
|
),
|
|
146
165
|
);
|
|
147
166
|
if (config.async === true) labels.add("risk.long_running");
|
|
@@ -846,9 +865,10 @@ export function toRegisteredTool(
|
|
|
846
865
|
assertToolSafeRepeatConfig(
|
|
847
866
|
argTemplateConfig,
|
|
848
867
|
explicitArgTypes,
|
|
849
|
-
cfg.defaults ?? {},
|
|
868
|
+
{ ...(cfg.defaults ?? {}), ...(cfg.values ?? {}) },
|
|
850
869
|
);
|
|
851
870
|
const argTypes = Schema.getTemplateArgTypes(argTemplateConfig);
|
|
871
|
+
Schema.assertCompatibleToolArgTypes(explicitArgTypes, argTypes);
|
|
852
872
|
return {
|
|
853
873
|
name: entry.id,
|
|
854
874
|
description,
|