@llblab/pi-actors 0.16.1 → 0.16.3
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 +13 -0
- package/docs/template-recipes.md +1 -1
- package/lib/recipe-discovery.ts +33 -0
- package/lib/recipe-references.ts +7 -3
- package/lib/runtime.ts +22 -1
- package/lib/schema.ts +25 -9
- package/package.json +1 -1
- package/recipes/lens-swarm.json +68 -0
- package/skills/actors/SKILL.md +2 -2
- package/skills/swarm/SKILL.md +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,18 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.16.3: Recipe Import Path Placeholders
|
|
4
|
+
|
|
5
|
+
- `[Template Recipes]` Added static `{repo}` and `{agent}` expansion for recipe paths, including `imports` and `from` bindings. Impact: recipes can import sibling packaged/user recipes without hard-coded absolute paths while keeping imports load-time deterministic.
|
|
6
|
+
- `[Docs]` Documented `{repo}` and `{agent}` import path placeholders in the template recipe standard.
|
|
7
|
+
- `[Package]` Bumped package and packaged skill metadata to `0.16.3` for the hotfix release.
|
|
8
|
+
|
|
9
|
+
## 0.16.2: Recipe Registry Diagnostics Hotfix
|
|
10
|
+
|
|
11
|
+
- `[Schema]` Derived recipe tool arguments without expanding runtime-dependent repeat nodes. Impact: valid recipes using repeat expressions such as `{lenses.length}` can be exposed as tools instead of being skipped during startup schema generation.
|
|
12
|
+
- `[Runtime]` Replaced the dense semicolon warning with grouped recipe registry diagnostics and explicit spacing. Impact: startup diagnostics are easier to scan and do not visually run into adjacent text.
|
|
13
|
+
- `[Recipes]` Added a packaged `lens-swarm` recipe that composes the review coordinator without concrete model-version defaults. Impact: the standard library includes the general multi-lens review launcher instead of relying only on operator-local copies.
|
|
14
|
+
- `[Package]` Bumped package and packaged skill metadata to `0.16.2` for the hotfix release.
|
|
15
|
+
|
|
3
16
|
## 0.16.1: Recipe Registry Hotfix
|
|
4
17
|
|
|
5
18
|
- `[Runtime]` Prevented invalid user recipe files from aborting extension startup when tool-schema generation fails, surfacing a warning and skipping the offending tool instead. Impact: one bad recipe in `~/.pi/agent/recipes` no longer takes down the pi-actors extension.
|
package/docs/template-recipes.md
CHANGED
|
@@ -245,7 +245,7 @@ File-backed recipes may import other file-backed recipes at the recipe layer. Im
|
|
|
245
245
|
|
|
246
246
|
An import binding may be either a string recipe path/name or an object with:
|
|
247
247
|
|
|
248
|
-
- `from`: recipe path or bare name.
|
|
248
|
+
- `from`: recipe path or bare name. Import paths support static load-time placeholders: `{repo}` expands to the directory above the active recipe root, and `{agent}` expands to the pi agent directory. For a packaged recipe in `<repo>/recipes/name.json`, `{repo}/recipes/other.json` resolves to a sibling packaged recipe. For a user recipe in `~/.pi/agent/recipes/name.json`, `{repo}` and `{agent}` both resolve to `~/.pi/agent`.
|
|
249
249
|
- `defaults`: extra default values exposed through the import.
|
|
250
250
|
- `values`: explicit values for embedding that imported recipe.
|
|
251
251
|
|
package/lib/recipe-discovery.ts
CHANGED
|
@@ -41,6 +41,32 @@ export interface RecipeDiscoverySource {
|
|
|
41
41
|
mutableUsage?: boolean;
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
+
function assertToolSafeRepeatConfig(
|
|
45
|
+
config: unknown,
|
|
46
|
+
argTypes: Record<string, { kind: string }>,
|
|
47
|
+
defaults: Record<string, unknown>,
|
|
48
|
+
): void {
|
|
49
|
+
if (typeof config === "string" || config === undefined || config === null) return;
|
|
50
|
+
if (Array.isArray(config)) {
|
|
51
|
+
for (const step of config) assertToolSafeRepeatConfig(step, argTypes, defaults);
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
if (typeof config !== "object") return;
|
|
55
|
+
const node = config as { repeat?: unknown; template?: unknown; recover?: unknown };
|
|
56
|
+
if (typeof node.repeat === "string") {
|
|
57
|
+
const trimmed = node.repeat.trim();
|
|
58
|
+
if (!/^\d+$/.test(trimmed)) {
|
|
59
|
+
const match = trimmed.match(/^\{?([A-Za-z_][A-Za-z0-9_-]*)\.length\}?$/);
|
|
60
|
+
if (!match || (argTypes[match[1]]?.kind !== "array" && !Array.isArray(defaults[match[1]])))
|
|
61
|
+
throw new Error(
|
|
62
|
+
"Command template repeat must be a positive integer or {array.length} with an array argument/default.",
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
assertToolSafeRepeatConfig(node.template, argTypes, defaults);
|
|
67
|
+
assertToolSafeRepeatConfig(node.recover, argTypes, defaults);
|
|
68
|
+
}
|
|
69
|
+
|
|
44
70
|
function listRecipeFiles(root: string): string[] {
|
|
45
71
|
if (!existsSync(root)) return [];
|
|
46
72
|
return readdirSync(root, { withFileTypes: true })
|
|
@@ -207,6 +233,13 @@ export function toRegisteredTool(entry: DiscoveredRecipe): RegisteredTool | unde
|
|
|
207
233
|
defaults: { ...(argTemplate.defaults ?? {}), ...(cfg.defaults ?? {}) },
|
|
208
234
|
}
|
|
209
235
|
: { args: cfg.args, defaults: cfg.defaults ?? {}, template: argTemplate };
|
|
236
|
+
const explicitArgTypes = Object.fromEntries(
|
|
237
|
+
(cfg.args ?? []).map((arg) => {
|
|
238
|
+
const parsed = Schema.parseToolArgToken(String(arg));
|
|
239
|
+
return [parsed.arg, parsed.type];
|
|
240
|
+
}),
|
|
241
|
+
);
|
|
242
|
+
assertToolSafeRepeatConfig(argTemplateConfig, explicitArgTypes, cfg.defaults ?? {});
|
|
210
243
|
const argTypes = Schema.getTemplateArgTypes(argTemplateConfig);
|
|
211
244
|
return {
|
|
212
245
|
name: entry.id,
|
package/lib/recipe-references.ts
CHANGED
|
@@ -75,11 +75,15 @@ export function resolveRecipePath(
|
|
|
75
75
|
recipeRoot = Paths.getRecipeRoot(),
|
|
76
76
|
): string {
|
|
77
77
|
const trimmed = value.trim();
|
|
78
|
-
|
|
79
|
-
|
|
78
|
+
const repoRoot = resolve(recipeRoot, "..");
|
|
79
|
+
const expanded = trimmed
|
|
80
|
+
.replaceAll("{repo}", repoRoot)
|
|
81
|
+
.replaceAll("{agent}", Paths.getAgentDir());
|
|
82
|
+
if (expanded.startsWith("~/")) return resolve(homedir(), expanded.slice(2));
|
|
83
|
+
if (expanded.includes("/")) return resolve(expanded);
|
|
80
84
|
return resolve(
|
|
81
85
|
recipeRoot,
|
|
82
|
-
|
|
86
|
+
expanded.endsWith(".json") ? expanded : `${expanded}.json`,
|
|
83
87
|
);
|
|
84
88
|
}
|
|
85
89
|
|
package/lib/runtime.ts
CHANGED
|
@@ -98,6 +98,27 @@ export function createAutoToolsRuntime(
|
|
|
98
98
|
runtimeTools.add(cfg.name);
|
|
99
99
|
runtimeToolFingerprints.set(cfg.name, fingerprint);
|
|
100
100
|
}
|
|
101
|
+
function formatRecipeToolWarnings(warnings: string[]): string {
|
|
102
|
+
const shadowed = warnings.filter((warning) => warning.includes(" shadows "));
|
|
103
|
+
const skipped = warnings.filter((warning) => warning.includes(" could not be exposed as a tool:"));
|
|
104
|
+
const other = warnings.filter(
|
|
105
|
+
(warning) => !shadowed.includes(warning) && !skipped.includes(warning),
|
|
106
|
+
);
|
|
107
|
+
const lines = ["pi-actors recipe registry warning"];
|
|
108
|
+
if (shadowed.length > 0) {
|
|
109
|
+
lines.push("User recipes override packaged recipes:");
|
|
110
|
+
lines.push(...shadowed.map((warning) => `• ${warning}`));
|
|
111
|
+
}
|
|
112
|
+
if (skipped.length > 0) {
|
|
113
|
+
lines.push("Recipes skipped from tool exposure:");
|
|
114
|
+
lines.push(...skipped.map((warning) => `• ${warning}`));
|
|
115
|
+
}
|
|
116
|
+
if (other.length > 0) {
|
|
117
|
+
lines.push("Other registry diagnostics:");
|
|
118
|
+
lines.push(...other.map((warning) => `• ${warning}`));
|
|
119
|
+
}
|
|
120
|
+
return `${lines.join("\n")}\n`;
|
|
121
|
+
}
|
|
101
122
|
function loadTools(ctx: RuntimeContext) {
|
|
102
123
|
const warnings: string[] = [];
|
|
103
124
|
const recipeRoot = deps.recipeRoot ?? Paths.getRecipeRoot();
|
|
@@ -138,7 +159,7 @@ export function createAutoToolsRuntime(
|
|
|
138
159
|
registerRuntimeTool(cfg);
|
|
139
160
|
}
|
|
140
161
|
if (warnings.length > 0) {
|
|
141
|
-
notify(ctx,
|
|
162
|
+
notify(ctx, formatRecipeToolWarnings(warnings), "warning");
|
|
142
163
|
}
|
|
143
164
|
}
|
|
144
165
|
return {
|
package/lib/schema.ts
CHANGED
|
@@ -261,19 +261,35 @@ function collectWhenDeclarations(
|
|
|
261
261
|
declarations.push(parseToolArgToken(`${bareCondition[1]}:bool=false`));
|
|
262
262
|
}
|
|
263
263
|
|
|
264
|
+
function collectCommandTemplateConfigDeclarations(
|
|
265
|
+
config: CommandTemplates.CommandTemplateConfig | CommandTemplates.CommandTemplateValue,
|
|
266
|
+
declarations: ParsedToolArgToken[],
|
|
267
|
+
): void {
|
|
268
|
+
if (typeof config === "string") {
|
|
269
|
+
collectTemplatePlaceholderDeclarations(config, declarations);
|
|
270
|
+
return;
|
|
271
|
+
}
|
|
272
|
+
if (Array.isArray(config)) {
|
|
273
|
+
for (const step of config)
|
|
274
|
+
collectCommandTemplateConfigDeclarations(step, declarations);
|
|
275
|
+
return;
|
|
276
|
+
}
|
|
277
|
+
if (config.template !== undefined)
|
|
278
|
+
collectCommandTemplateConfigDeclarations(config.template, declarations);
|
|
279
|
+
if (config.recover !== undefined)
|
|
280
|
+
collectCommandTemplateConfigDeclarations(config.recover, declarations);
|
|
281
|
+
for (const field of [config.timeout, config.delay, config.retry, config.repeat]) {
|
|
282
|
+
if (typeof field === "string")
|
|
283
|
+
collectTemplatePlaceholderDeclarations(field, declarations);
|
|
284
|
+
}
|
|
285
|
+
if (typeof config.when === "string") collectWhenDeclarations(config.when, declarations);
|
|
286
|
+
}
|
|
287
|
+
|
|
264
288
|
function getTemplatePlaceholderDeclarations(
|
|
265
289
|
config: CommandTemplates.CommandTemplateConfig,
|
|
266
290
|
): ParsedToolArgToken[] {
|
|
267
291
|
const declarations: ParsedToolArgToken[] = [];
|
|
268
|
-
|
|
269
|
-
collectTemplatePlaceholderDeclarations(step.template, declarations);
|
|
270
|
-
for (const field of [step.timeout, step.delay, step.retry]) {
|
|
271
|
-
if (typeof field === "string")
|
|
272
|
-
collectTemplatePlaceholderDeclarations(field, declarations);
|
|
273
|
-
}
|
|
274
|
-
if (typeof step.when === "string")
|
|
275
|
-
collectWhenDeclarations(step.when, declarations);
|
|
276
|
-
}
|
|
292
|
+
collectCommandTemplateConfigDeclarations(config, declarations);
|
|
277
293
|
return declarations;
|
|
278
294
|
}
|
|
279
295
|
|
package/package.json
CHANGED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "lens-swarm",
|
|
3
|
+
"description": "General-purpose multi-lens review swarm. Launches independent reviewers by lens, then verifies, merges, judges, and normalizes the result.",
|
|
4
|
+
"tool": true,
|
|
5
|
+
"async": true,
|
|
6
|
+
"imports": {
|
|
7
|
+
"coordinator": "subagent-review-coordinator.json"
|
|
8
|
+
},
|
|
9
|
+
"args": [
|
|
10
|
+
"scope:string",
|
|
11
|
+
"lenses:array",
|
|
12
|
+
"model:string",
|
|
13
|
+
"thinking:string",
|
|
14
|
+
"tools:string",
|
|
15
|
+
"claim:string",
|
|
16
|
+
"evidence_policy:string",
|
|
17
|
+
"risk_policy:string",
|
|
18
|
+
"output_format:string"
|
|
19
|
+
],
|
|
20
|
+
"defaults": {
|
|
21
|
+
"lenses": [
|
|
22
|
+
"correctness",
|
|
23
|
+
"architecture",
|
|
24
|
+
"operator UX"
|
|
25
|
+
],
|
|
26
|
+
"thinking": "off",
|
|
27
|
+
"tools": "",
|
|
28
|
+
"claim": "The reviewed scope has clear, evidence-based findings, risks, and recommended next actions.",
|
|
29
|
+
"evidence_policy": "Cite inspected files, command outputs, or explicit uncertainty for every material claim.",
|
|
30
|
+
"risk_policy": "Preserve minority high-impact risks and ideas; separate confirmed issues from hypotheses.",
|
|
31
|
+
"output_format": "Markdown sections: Summary, Consensus Findings, Minority Findings, Verification, Judge Notes, Risks, Next Actions."
|
|
32
|
+
},
|
|
33
|
+
"mailbox": {
|
|
34
|
+
"accepts": [
|
|
35
|
+
"control.stop",
|
|
36
|
+
"control.cancel",
|
|
37
|
+
"control.kill"
|
|
38
|
+
],
|
|
39
|
+
"emits": [
|
|
40
|
+
"review.completed",
|
|
41
|
+
"verification.completed",
|
|
42
|
+
"merge.completed",
|
|
43
|
+
"judge.completed",
|
|
44
|
+
"command.done",
|
|
45
|
+
"run.done",
|
|
46
|
+
"run.failed"
|
|
47
|
+
]
|
|
48
|
+
},
|
|
49
|
+
"template": [
|
|
50
|
+
{
|
|
51
|
+
"name": "coordinator",
|
|
52
|
+
"values": {
|
|
53
|
+
"scope": "{scope}",
|
|
54
|
+
"lenses": "{lenses}",
|
|
55
|
+
"claim": "{claim}",
|
|
56
|
+
"reviewer_model": "{model}",
|
|
57
|
+
"verifier_model": "{model}",
|
|
58
|
+
"merger_model": "{model}",
|
|
59
|
+
"judge_model": "{model}",
|
|
60
|
+
"thinking": "{thinking}",
|
|
61
|
+
"tools": "{tools}",
|
|
62
|
+
"evidence_policy": "{evidence_policy}",
|
|
63
|
+
"risk_policy": "{risk_policy}",
|
|
64
|
+
"output_format": "{output_format}"
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
]
|
|
68
|
+
}
|
package/skills/actors/SKILL.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
name: actors
|
|
3
3
|
description: Highest-density practical guide for pi-actors. Read this skill whenever prompt and tools are not enough for spawn, message, inspect, actor runs, tools, recipes, command templates, async lifecycle, mailboxes, artifacts, and local orchestration mechanics.
|
|
4
4
|
metadata:
|
|
5
|
-
version: 0.16.
|
|
5
|
+
version: 0.16.3
|
|
6
6
|
---
|
|
7
7
|
|
|
8
8
|
# Actors (pi-actors)
|
|
@@ -216,7 +216,7 @@ Use packaged recipes by name with `spawn file=<name>` for async actors, or regis
|
|
|
216
216
|
- Review chain: [`subagent-review`](../../recipes/subagent-review.json), [`subagent-verify`](../../recipes/subagent-verify.json), [`subagent-merge`](../../recipes/subagent-merge.json), [`subagent-judge`](../../recipes/subagent-judge.json), [`subagent-normalize`](../../recipes/subagent-normalize.json).
|
|
217
217
|
- Planning/evidence: [`subagent-plan`](../../recipes/subagent-plan.json), [`subagent-task-card`](../../recipes/subagent-task-card.json), [`subagent-evidence-map`](../../recipes/subagent-evidence-map.json), [`subagent-contradiction-map`](../../recipes/subagent-contradiction-map.json), [`subagent-critic`](../../recipes/subagent-critic.json).
|
|
218
218
|
- Handoffs: [`subagent-checkpoint`](../../recipes/subagent-checkpoint.json), [`subagent-followup`](../../recipes/subagent-followup.json), [`subagent-message`](../../recipes/subagent-message.json), [`subagent-artifact`](../../recipes/subagent-artifact.json), [`subagent-conflict-report`](../../recipes/subagent-conflict-report.json).
|
|
219
|
-
- Composition: [`subagent-quorum`](../../recipes/subagent-quorum.json), [`subagent-review-coordinator`](../../recipes/subagent-review-coordinator.json).
|
|
219
|
+
- Composition: [`subagent-quorum`](../../recipes/subagent-quorum.json), [`subagent-review-coordinator`](../../recipes/subagent-review-coordinator.json), [`lens-swarm`](../../recipes/lens-swarm.json).
|
|
220
220
|
|
|
221
221
|
### Pipelines
|
|
222
222
|
|
package/skills/swarm/SKILL.md
CHANGED