@llblab/pi-actors 0.16.0 → 0.16.2
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/lib/recipe-discovery.ts +39 -1
- package/lib/runtime.ts +30 -3
- 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.2: Recipe Registry Diagnostics Hotfix
|
|
4
|
+
|
|
5
|
+
- `[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.
|
|
6
|
+
- `[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.
|
|
7
|
+
- `[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.
|
|
8
|
+
- `[Package]` Bumped package and packaged skill metadata to `0.16.2` for the hotfix release.
|
|
9
|
+
|
|
10
|
+
## 0.16.1: Recipe Registry Hotfix
|
|
11
|
+
|
|
12
|
+
- `[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.
|
|
13
|
+
- `[Recipe Discovery]` Excluded the legacy migration report file from recipe discovery. Impact: `actors-tools-migration-report.json` no longer appears as a broken recipe/tool candidate after migration.
|
|
14
|
+
- `[Package]` Bumped package and packaged skill metadata to `0.16.1` for the hotfix release.
|
|
15
|
+
|
|
3
16
|
## 0.16.0: File-Discovered Recipe Registry Migration
|
|
4
17
|
|
|
5
18
|
- `[Version]` Began the `0.16.0` breaking-change cycle and captured the file-discovered recipe registry migration plan in `BACKLOG.md`. Impact: the next release target is now explicit: replace `actors-tools.json` as live registry with validated recipe files, filename identity, `tool` exposure, override/disable semantics, migration reporting, registry inspection, and usage-informed cleanup.
|
package/lib/recipe-discovery.ts
CHANGED
|
@@ -41,10 +41,41 @@ 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 })
|
|
47
|
-
.filter(
|
|
73
|
+
.filter(
|
|
74
|
+
(entry) =>
|
|
75
|
+
entry.isFile() &&
|
|
76
|
+
entry.name.endsWith(".json") &&
|
|
77
|
+
entry.name !== "actors-tools-migration-report.json",
|
|
78
|
+
)
|
|
48
79
|
.map((entry) => join(root, entry.name))
|
|
49
80
|
.sort();
|
|
50
81
|
}
|
|
@@ -202,6 +233,13 @@ export function toRegisteredTool(entry: DiscoveredRecipe): RegisteredTool | unde
|
|
|
202
233
|
defaults: { ...(argTemplate.defaults ?? {}), ...(cfg.defaults ?? {}) },
|
|
203
234
|
}
|
|
204
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 ?? {});
|
|
205
243
|
const argTypes = Schema.getTemplateArgTypes(argTemplateConfig);
|
|
206
244
|
return {
|
|
207
245
|
name: entry.id,
|
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();
|
|
@@ -119,8 +140,14 @@ export function createAutoToolsRuntime(
|
|
|
119
140
|
warnings.push(...discovered.diagnostics);
|
|
120
141
|
tools.clear();
|
|
121
142
|
for (const entry of discovered.active.values()) {
|
|
122
|
-
|
|
123
|
-
|
|
143
|
+
try {
|
|
144
|
+
const cfg = RecipeDiscovery.toRegisteredTool(entry);
|
|
145
|
+
if (cfg) tools.set(cfg.name, cfg);
|
|
146
|
+
} catch (error) {
|
|
147
|
+
warnings.push(
|
|
148
|
+
`Recipe ${entry.id} could not be exposed as a tool: ${error instanceof Error ? error.message : String(error)}`,
|
|
149
|
+
);
|
|
150
|
+
}
|
|
124
151
|
}
|
|
125
152
|
deactivateMissingRuntimeTools(new Set(tools.keys()));
|
|
126
153
|
for (const cfg of tools.values()) {
|
|
@@ -132,7 +159,7 @@ export function createAutoToolsRuntime(
|
|
|
132
159
|
registerRuntimeTool(cfg);
|
|
133
160
|
}
|
|
134
161
|
if (warnings.length > 0) {
|
|
135
|
-
notify(ctx,
|
|
162
|
+
notify(ctx, formatRecipeToolWarnings(warnings), "warning");
|
|
136
163
|
}
|
|
137
164
|
}
|
|
138
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.2
|
|
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