@llblab/pi-actors 0.45.1 → 0.46.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 +9 -7
- package/BACKLOG.md +582 -0
- package/CHANGELOG.md +17 -1
- package/README.md +27 -13
- package/dist/fixtures/protocol/recipe-summary.json +1 -1
- package/dist/index.js +1 -1
- package/dist/lib/async-runs.d.ts +5 -1
- package/dist/lib/async-runs.js +26 -24
- package/dist/lib/automatic-review-runtime.d.ts +2 -0
- package/dist/lib/automatic-review-runtime.js +12 -5
- package/dist/lib/draft-sleep.js +0 -1
- package/dist/lib/execution.d.ts +1 -0
- package/dist/lib/execution.js +1 -0
- package/dist/lib/extension-runtime.d.ts +1 -1
- package/dist/lib/extension-runtime.js +26 -4
- package/dist/lib/inspector.js +46 -7
- package/dist/lib/paths.d.ts +0 -1
- package/dist/lib/paths.js +0 -7
- package/dist/lib/prompts.d.ts +1 -1
- package/dist/lib/prompts.js +4 -4
- package/dist/lib/recipes-context.d.ts +12 -3
- package/dist/lib/recipes-context.js +30 -6
- package/dist/lib/recipes-discovery.d.ts +18 -0
- package/dist/lib/recipes-discovery.js +95 -22
- package/dist/lib/recipes-references.d.ts +42 -9
- package/dist/lib/recipes-references.js +248 -135
- package/dist/lib/registry.d.ts +14 -1
- package/dist/lib/registry.js +110 -87
- package/dist/lib/runtime.d.ts +30 -4
- package/dist/lib/runtime.js +74 -12
- package/dist/lib/tools-inspect.d.ts +3 -1
- package/dist/lib/tools-inspect.js +56 -9
- package/dist/lib/tools-local.d.ts +2 -0
- package/dist/lib/tools-local.js +5 -2
- package/dist/lib/tools-response.js +2 -0
- package/dist/lib/tools-spawn.d.ts +2 -0
- package/dist/lib/tools-spawn.js +24 -52
- package/dist/lib/tools.d.ts +4 -1
- package/dist/lib/tools.js +2 -0
- package/dist/scripts/build-dist.mjs +13 -4
- package/dist/skills/actors/SKILL.md +8 -8
- package/dist/skills/actors/recipes/recipe-validate.json +11 -0
- package/{recipes/utility-coordinator-lock-snapshot.json → dist/skills/actors/recipes/resource-locker-snapshot.json} +1 -3
- package/dist/{recipes → skills/actors/recipes}/resource-locker.json +1 -3
- package/dist/{recipes/utility-run-ops-snapshot.json → skills/actors/recipes/run-ops-snapshot.json} +1 -3
- package/dist/skills/actors/recipes/run-summary.json +9 -0
- package/dist/{scripts/locker.mjs → skills/actors/scripts/resource-locker.mjs} +2 -2
- package/dist/skills/actors/scripts/run-utils.mjs +164 -0
- package/{scripts → dist/skills/actors/scripts}/validate-recipe.mjs +134 -17
- package/dist/skills/artifacts/SKILL.md +16 -0
- package/{recipes/pipeline-artifact-bundle.json → dist/skills/artifacts/recipes/bundle.json} +4 -4
- package/dist/{recipes/utility-artifact-write.json → skills/artifacts/recipes/file-write.json} +1 -3
- package/dist/{recipes/utility-artifact-manifest.json → skills/artifacts/recipes/manifest.json} +1 -3
- package/{recipes/pipeline-artifact-report.json → dist/skills/artifacts/recipes/report.json} +2 -2
- package/dist/{recipes/pipeline-artifact-write.json → skills/artifacts/recipes/write.json} +3 -3
- package/dist/skills/artifacts/scripts/artifact-utils.mjs +63 -0
- package/dist/skills/media/SKILL.md +16 -0
- package/dist/{recipes/pipeline-media-library.json → skills/media/recipes/library.json} +2 -2
- package/{recipes/music-player.json → dist/skills/media/recipes/player.json} +1 -3
- package/dist/{recipes/utility-playlist-build.json → skills/media/recipes/playlist-build.json} +1 -3
- package/dist/skills/media/scripts/media-utils.mjs +47 -0
- package/dist/{scripts → skills/media/scripts}/music-player.mjs +9 -3
- package/dist/skills/project-work/SKILL.md +16 -0
- package/dist/skills/project-work/recipes/changelog-section.json +11 -0
- package/{recipes/pipeline-docs-maintenance.json → dist/skills/project-work/recipes/docs-maintenance.json} +4 -4
- package/dist/skills/project-work/recipes/package-summary.json +9 -0
- package/{recipes/pipeline-release-readiness.json → dist/skills/project-work/recipes/release-readiness.json} +6 -6
- package/dist/{recipes/pipeline-release-summary.json → skills/project-work/recipes/release-summary.json} +5 -5
- package/{recipes/pipeline-repo-health.json → dist/skills/project-work/recipes/repo-health.json} +6 -6
- package/{recipes/pipeline-async-run-ops.json → dist/skills/project-work/recipes/run-ops.json} +3 -3
- package/dist/skills/project-work/recipes/skill-summary.json +11 -0
- package/dist/skills/project-work/scripts/project-utils.mjs +89 -0
- package/dist/skills/recipe-memory/SKILL.md +16 -0
- package/dist/skills/swarm/SKILL.md +4 -4
- package/{recipes/pipeline-architect-coordinator.json → dist/skills/swarm/recipes/architect.json} +5 -5
- package/{recipes/pipeline-checkpoint-continuation.json → dist/skills/swarm/recipes/checkpoint-continuation.json} +3 -3
- package/dist/{recipes/pipeline-development-tasking.json → skills/swarm/recipes/development-tasking.json} +4 -4
- package/dist/{recipes/lens-swarm.json → skills/swarm/recipes/lens-review.json} +1 -1
- package/dist/{recipes/pipeline-quorum-review.json → skills/swarm/recipes/quorum-review.json} +4 -4
- package/{recipes/pipeline-research-synthesis.json → dist/skills/swarm/recipes/research-synthesis.json} +6 -6
- package/{recipes/pipeline-review-readiness.json → dist/skills/swarm/recipes/review-readiness.json} +1 -1
- package/{recipes/subagents-prompts.json → dist/skills/swarm/recipes/subagent-prompts.json} +1 -1
- package/{recipes → dist/skills/swarm/recipes}/subagent-quorum.json +1 -1
- package/dist/{recipes → skills/swarm/recipes}/subagent-review-coordinator.json +6 -6
- package/docs/actor-inspector.md +4 -3
- package/docs/async-runs.md +2 -2
- package/docs/recipe-library.md +23 -23
- package/docs/releasing.md +2 -2
- package/docs/template-recipes.md +32 -14
- package/docs/tool-registry.md +10 -4
- package/fixtures/protocol/recipe-summary.json +1 -1
- package/index.ts +2 -1
- package/lib/async-runs.ts +52 -25
- package/lib/automatic-review-runtime.ts +16 -3
- package/lib/draft-sleep.ts +0 -1
- package/lib/execution.ts +2 -0
- package/lib/extension-runtime.ts +42 -4
- package/lib/inspector.ts +57 -11
- package/lib/paths.ts +0 -7
- package/lib/prompts.ts +4 -4
- package/lib/recipes-context.ts +51 -6
- package/lib/recipes-discovery.ts +164 -24
- package/lib/recipes-references.ts +359 -146
- package/lib/registry.ts +185 -94
- package/lib/runtime.ts +109 -17
- package/lib/tools-inspect.ts +77 -10
- package/lib/tools-local.ts +9 -1
- package/lib/tools-response.ts +2 -0
- package/lib/tools-spawn.ts +38 -74
- package/lib/tools.ts +4 -1
- package/package.json +2 -4
- package/scripts/build-dist.mjs +13 -4
- package/skills/actors/SKILL.md +8 -8
- package/skills/actors/recipes/recipe-validate.json +11 -0
- package/{dist/recipes/utility-coordinator-lock-snapshot.json → skills/actors/recipes/resource-locker-snapshot.json} +1 -3
- package/{recipes → skills/actors/recipes}/resource-locker.json +1 -3
- package/{recipes/utility-run-ops-snapshot.json → skills/actors/recipes/run-ops-snapshot.json} +1 -3
- package/skills/actors/recipes/run-summary.json +9 -0
- package/{scripts/locker.mjs → skills/actors/scripts/resource-locker.mjs} +2 -2
- package/skills/actors/scripts/run-utils.mjs +164 -0
- package/{dist → skills/actors}/scripts/validate-recipe.mjs +134 -17
- package/skills/artifacts/SKILL.md +16 -0
- package/{dist/recipes/pipeline-artifact-bundle.json → skills/artifacts/recipes/bundle.json} +4 -4
- package/{recipes/utility-artifact-write.json → skills/artifacts/recipes/file-write.json} +1 -3
- package/{recipes/utility-artifact-manifest.json → skills/artifacts/recipes/manifest.json} +1 -3
- package/{dist/recipes/pipeline-artifact-report.json → skills/artifacts/recipes/report.json} +2 -2
- package/{recipes/pipeline-artifact-write.json → skills/artifacts/recipes/write.json} +3 -3
- package/skills/artifacts/scripts/artifact-utils.mjs +63 -0
- package/skills/media/SKILL.md +16 -0
- package/{recipes/pipeline-media-library.json → skills/media/recipes/library.json} +2 -2
- package/{dist/recipes/music-player.json → skills/media/recipes/player.json} +1 -3
- package/{recipes/utility-playlist-build.json → skills/media/recipes/playlist-build.json} +1 -3
- package/skills/media/scripts/media-utils.mjs +47 -0
- package/{scripts → skills/media/scripts}/music-player.mjs +9 -3
- package/skills/project-work/SKILL.md +16 -0
- package/skills/project-work/recipes/changelog-section.json +11 -0
- package/{dist/recipes/pipeline-docs-maintenance.json → skills/project-work/recipes/docs-maintenance.json} +4 -4
- package/skills/project-work/recipes/package-summary.json +9 -0
- package/{dist/recipes/pipeline-release-readiness.json → skills/project-work/recipes/release-readiness.json} +6 -6
- package/{recipes/pipeline-release-summary.json → skills/project-work/recipes/release-summary.json} +5 -5
- package/{dist/recipes/pipeline-repo-health.json → skills/project-work/recipes/repo-health.json} +6 -6
- package/{dist/recipes/pipeline-async-run-ops.json → skills/project-work/recipes/run-ops.json} +3 -3
- package/skills/project-work/recipes/skill-summary.json +11 -0
- package/skills/project-work/scripts/project-utils.mjs +89 -0
- package/skills/recipe-memory/SKILL.md +16 -0
- package/skills/swarm/SKILL.md +4 -4
- package/{dist/recipes/pipeline-architect-coordinator.json → skills/swarm/recipes/architect.json} +5 -5
- package/{dist/recipes/pipeline-checkpoint-continuation.json → skills/swarm/recipes/checkpoint-continuation.json} +3 -3
- package/{recipes/pipeline-development-tasking.json → skills/swarm/recipes/development-tasking.json} +4 -4
- package/{recipes/lens-swarm.json → skills/swarm/recipes/lens-review.json} +1 -1
- package/{recipes/pipeline-quorum-review.json → skills/swarm/recipes/quorum-review.json} +4 -4
- package/{dist/recipes/pipeline-research-synthesis.json → skills/swarm/recipes/research-synthesis.json} +6 -6
- package/{dist/recipes/pipeline-review-readiness.json → skills/swarm/recipes/review-readiness.json} +1 -1
- package/{dist/recipes/subagents-prompts.json → skills/swarm/recipes/subagent-prompts.json} +1 -1
- package/{dist → skills/swarm}/recipes/subagent-quorum.json +1 -1
- package/{recipes → skills/swarm/recipes}/subagent-review-coordinator.json +6 -6
- package/dist/recipes/utility-changelog-section.json +0 -13
- package/dist/recipes/utility-package-summary.json +0 -11
- package/dist/recipes/utility-run-summary.json +0 -11
- package/dist/recipes/utility-skill-summary.json +0 -13
- package/dist/recipes/utility-validate-recipe.json +0 -13
- package/dist/scripts/executable-block-style.d.mts +0 -1
- package/dist/scripts/executable-block-style.mjs +0 -73
- package/dist/scripts/recipe-utils.mjs +0 -404
- package/dist/scripts/release-gates.mjs +0 -281
- package/recipes/utility-changelog-section.json +0 -13
- package/recipes/utility-package-summary.json +0 -11
- package/recipes/utility-run-summary.json +0 -11
- package/recipes/utility-skill-summary.json +0 -13
- package/recipes/utility-validate-recipe.json +0 -13
- package/scripts/executable-block-style.d.mts +0 -1
- package/scripts/executable-block-style.mjs +0 -73
- package/scripts/recipe-utils.mjs +0 -404
- package/scripts/release-gates.mjs +0 -281
- /package/dist/{recipes/utility-validation-wrapper.json → skills/actors/recipes/command-validate.json} +0 -0
- /package/dist/{recipes/utility-jsonl-tail.json → skills/actors/recipes/jsonl-tail.json} +0 -0
- /package/dist/{recipes/utility-run-state-files.json → skills/actors/recipes/run-state-files.json} +0 -0
- /package/dist/{recipes/utility-playlist-scan.json → skills/media/recipes/playlist-scan.json} +0 -0
- /package/dist/{recipes/utility-changelog-head.json → skills/project-work/recipes/changelog-head.json} +0 -0
- /package/dist/{recipes/utility-git-log.json → skills/project-work/recipes/git-log.json} +0 -0
- /package/dist/{recipes/utility-git-status.json → skills/project-work/recipes/git-status.json} +0 -0
- /package/dist/{recipes/utility-markdown-index.json → skills/project-work/recipes/markdown-index.json} +0 -0
- /package/dist/{recipes → skills/recipe-memory/recipes}/draft-review.json +0 -0
- /package/dist/{recipes → skills/recipe-memory/recipes}/tool-review.json +0 -0
- /package/dist/{recipes → skills/swarm/recipes}/subagent-artifact.json +0 -0
- /package/dist/{recipes → skills/swarm/recipes}/subagent-checkpoint.json +0 -0
- /package/dist/{recipes → skills/swarm/recipes}/subagent-conflict-report.json +0 -0
- /package/dist/{recipes → skills/swarm/recipes}/subagent-contradiction-map.json +0 -0
- /package/dist/{recipes → skills/swarm/recipes}/subagent-critic.json +0 -0
- /package/dist/{recipes → skills/swarm/recipes}/subagent-evidence-map.json +0 -0
- /package/dist/{recipes → skills/swarm/recipes}/subagent-followup.json +0 -0
- /package/dist/{recipes → skills/swarm/recipes}/subagent-judge.json +0 -0
- /package/dist/{recipes → skills/swarm/recipes}/subagent-merge.json +0 -0
- /package/dist/{recipes → skills/swarm/recipes}/subagent-normalize.json +0 -0
- /package/dist/{recipes → skills/swarm/recipes}/subagent-plan.json +0 -0
- /package/dist/{recipes → skills/swarm/recipes}/subagent-preflight.json +0 -0
- /package/dist/{recipes → skills/swarm/recipes}/subagent-prompt.json +0 -0
- /package/dist/{recipes → skills/swarm/recipes}/subagent-review.json +0 -0
- /package/dist/{recipes → skills/swarm/recipes}/subagent-task-card.json +0 -0
- /package/dist/{recipes → skills/swarm/recipes}/subagent-tools.json +0 -0
- /package/dist/{recipes → skills/swarm/recipes}/subagent-verify.json +0 -0
- /package/{recipes/utility-validation-wrapper.json → skills/actors/recipes/command-validate.json} +0 -0
- /package/{recipes/utility-jsonl-tail.json → skills/actors/recipes/jsonl-tail.json} +0 -0
- /package/{recipes/utility-run-state-files.json → skills/actors/recipes/run-state-files.json} +0 -0
- /package/{recipes/utility-playlist-scan.json → skills/media/recipes/playlist-scan.json} +0 -0
- /package/{recipes/utility-changelog-head.json → skills/project-work/recipes/changelog-head.json} +0 -0
- /package/{recipes/utility-git-log.json → skills/project-work/recipes/git-log.json} +0 -0
- /package/{recipes/utility-git-status.json → skills/project-work/recipes/git-status.json} +0 -0
- /package/{recipes/utility-markdown-index.json → skills/project-work/recipes/markdown-index.json} +0 -0
- /package/{recipes → skills/recipe-memory/recipes}/draft-review.json +0 -0
- /package/{recipes → skills/recipe-memory/recipes}/tool-review.json +0 -0
- /package/{recipes → skills/swarm/recipes}/subagent-artifact.json +0 -0
- /package/{recipes → skills/swarm/recipes}/subagent-checkpoint.json +0 -0
- /package/{recipes → skills/swarm/recipes}/subagent-conflict-report.json +0 -0
- /package/{recipes → skills/swarm/recipes}/subagent-contradiction-map.json +0 -0
- /package/{recipes → skills/swarm/recipes}/subagent-critic.json +0 -0
- /package/{recipes → skills/swarm/recipes}/subagent-evidence-map.json +0 -0
- /package/{recipes → skills/swarm/recipes}/subagent-followup.json +0 -0
- /package/{recipes → skills/swarm/recipes}/subagent-judge.json +0 -0
- /package/{recipes → skills/swarm/recipes}/subagent-merge.json +0 -0
- /package/{recipes → skills/swarm/recipes}/subagent-normalize.json +0 -0
- /package/{recipes → skills/swarm/recipes}/subagent-plan.json +0 -0
- /package/{recipes → skills/swarm/recipes}/subagent-preflight.json +0 -0
- /package/{recipes → skills/swarm/recipes}/subagent-prompt.json +0 -0
- /package/{recipes → skills/swarm/recipes}/subagent-review.json +0 -0
- /package/{recipes → skills/swarm/recipes}/subagent-task-card.json +0 -0
- /package/{recipes → skills/swarm/recipes}/subagent-tools.json +0 -0
- /package/{recipes → skills/swarm/recipes}/subagent-verify.json +0 -0
|
@@ -3,19 +3,34 @@
|
|
|
3
3
|
* Zones: registry config, async runs, path resolution
|
|
4
4
|
* Owns detection, loading, and recipe-layer expansion for template recipe files
|
|
5
5
|
*/
|
|
6
|
-
import { existsSync, readFileSync, statSync } from "node:fs";
|
|
7
|
-
import {
|
|
8
|
-
import { basename, dirname, extname, isAbsolute, relative, resolve } from "node:path";
|
|
6
|
+
import { existsSync, readFileSync, readdirSync, statSync } from "node:fs";
|
|
7
|
+
import { basename, dirname, extname, isAbsolute, join, relative, resolve } from "node:path";
|
|
9
8
|
import * as CommandTemplates from "./command-templates.js";
|
|
10
9
|
import * as Paths from "./paths.js";
|
|
11
10
|
import * as RecipeControl from "./recipe-control.js";
|
|
12
11
|
import * as Schema from "./schema.js";
|
|
13
12
|
const MAX_RECIPE_FILE_BYTES = 1024 * 1024;
|
|
14
13
|
const MAX_RECIPE_IMPORT_DEPTH = 32;
|
|
15
|
-
const
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
14
|
+
const RESERVED_AUTHORED_RECIPE_VALUE_NAMES = new Set([
|
|
15
|
+
"recipe_dir",
|
|
16
|
+
"skill_dir",
|
|
17
|
+
]);
|
|
18
|
+
export const RUNTIME_OWNED_RECIPE_INPUT_NAMES = Object.freeze([
|
|
19
|
+
"owner_id",
|
|
20
|
+
"recipe_dir",
|
|
21
|
+
"run_instance_id",
|
|
22
|
+
"runtime_state_root",
|
|
23
|
+
"session_id",
|
|
24
|
+
"skill_dir",
|
|
25
|
+
"state_dir",
|
|
26
|
+
"trace_file",
|
|
27
|
+
]);
|
|
28
|
+
const RUNTIME_OWNED_RECIPE_INPUT_SET = new Set(RUNTIME_OWNED_RECIPE_INPUT_NAMES);
|
|
29
|
+
export function isRuntimeOwnedRecipeInput(name) {
|
|
30
|
+
return RUNTIME_OWNED_RECIPE_INPUT_SET.has(name);
|
|
31
|
+
}
|
|
32
|
+
export function createActiveSkillRecipeContext(skills) {
|
|
33
|
+
const rootsByName = new Map();
|
|
19
34
|
for (const skill of skills) {
|
|
20
35
|
const name = skill.name.trim();
|
|
21
36
|
const skillDir = skill.baseDir
|
|
@@ -25,62 +40,174 @@ export function setActiveSkillRecipeSources(skills) {
|
|
|
25
40
|
: undefined;
|
|
26
41
|
if (!name || !skillDir)
|
|
27
42
|
continue;
|
|
28
|
-
const roots =
|
|
43
|
+
const roots = rootsByName.get(name) ?? new Set();
|
|
29
44
|
roots.add(resolve(skillDir, "recipes"));
|
|
30
|
-
|
|
45
|
+
rootsByName.set(name, roots);
|
|
31
46
|
}
|
|
32
|
-
|
|
33
|
-
export function getActiveSkillRecipeNamespaces() {
|
|
34
|
-
return Object.fromEntries([...activeSkillRecipeRoots.entries()]
|
|
47
|
+
const namespaces = Object.fromEntries([...rootsByName.entries()]
|
|
35
48
|
.sort(([left], [right]) => left.localeCompare(right))
|
|
36
|
-
.map(([name, roots]) => [name, [...roots].sort()]));
|
|
49
|
+
.map(([name, roots]) => [name, Object.freeze([...roots].sort())]));
|
|
50
|
+
return Object.freeze({ namespaces: Object.freeze(namespaces) });
|
|
51
|
+
}
|
|
52
|
+
export const EMPTY_ACTIVE_SKILL_RECIPE_CONTEXT = createActiveSkillRecipeContext([]);
|
|
53
|
+
export function getActiveSkillRecipeNamespaces(context) {
|
|
54
|
+
return Object.fromEntries(Object.entries(context.namespaces).map(([name, roots]) => [
|
|
55
|
+
name,
|
|
56
|
+
[...roots],
|
|
57
|
+
]));
|
|
58
|
+
}
|
|
59
|
+
function nestedRecipeFiles(root) {
|
|
60
|
+
if (!existsSync(root))
|
|
61
|
+
return [];
|
|
62
|
+
return readdirSync(root, { withFileTypes: true }).flatMap((entry) => {
|
|
63
|
+
const path = join(root, entry.name);
|
|
64
|
+
if (entry.isDirectory())
|
|
65
|
+
return nestedRecipeFiles(path);
|
|
66
|
+
return entry.isFile() && /\.(?:json|md)$/u.test(entry.name) ? [path] : [];
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
export function inventoryActiveSkillRecipeComponents(context) {
|
|
70
|
+
const components = [];
|
|
71
|
+
const rejected = [];
|
|
72
|
+
for (const [skill, roots] of Object.entries(context.namespaces)) {
|
|
73
|
+
if (roots.length > 1) {
|
|
74
|
+
rejected.push({
|
|
75
|
+
reason: `Duplicate active Skill identity ${skill}: ${roots.join(", ")}`,
|
|
76
|
+
skill,
|
|
77
|
+
});
|
|
78
|
+
continue;
|
|
79
|
+
}
|
|
80
|
+
const root = roots[0];
|
|
81
|
+
if (!root || !existsSync(root))
|
|
82
|
+
continue;
|
|
83
|
+
const direct = readdirSync(root, { withFileTypes: true });
|
|
84
|
+
for (const entry of direct.filter((candidate) => candidate.isDirectory())) {
|
|
85
|
+
const nested = nestedRecipeFiles(join(root, entry.name));
|
|
86
|
+
for (const file of nested) {
|
|
87
|
+
rejected.push({
|
|
88
|
+
file,
|
|
89
|
+
reason: `Nested Skill Recipe file is not addressable: ${file}`,
|
|
90
|
+
skill,
|
|
91
|
+
stem: getRecipeIdFromPath(file),
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
const files = direct
|
|
96
|
+
.filter((entry) => entry.isFile() && /\.(?:json|md)$/u.test(entry.name))
|
|
97
|
+
.map((entry) => join(root, entry.name));
|
|
98
|
+
const byStem = new Map();
|
|
99
|
+
for (const file of files) {
|
|
100
|
+
const stem = getRecipeIdFromPath(file);
|
|
101
|
+
const matches = byStem.get(stem) ?? [];
|
|
102
|
+
matches.push(file);
|
|
103
|
+
byStem.set(stem, matches);
|
|
104
|
+
}
|
|
105
|
+
for (const [stem, matches] of [...byStem].sort(([a], [b]) => a.localeCompare(b))) {
|
|
106
|
+
if (!/^[a-z][a-z0-9]*(?:-[a-z0-9]+)*$/u.test(stem)) {
|
|
107
|
+
rejected.push({
|
|
108
|
+
file: matches[0],
|
|
109
|
+
reason: `Invalid Skill Recipe filename stem: ${stem}`,
|
|
110
|
+
skill,
|
|
111
|
+
stem,
|
|
112
|
+
});
|
|
113
|
+
continue;
|
|
114
|
+
}
|
|
115
|
+
if (matches.length > 1) {
|
|
116
|
+
rejected.push({
|
|
117
|
+
file: matches[0],
|
|
118
|
+
reason: `Skill Recipe stem collision: ${skill}/${stem} has both .json and .md files`,
|
|
119
|
+
skill,
|
|
120
|
+
stem,
|
|
121
|
+
});
|
|
122
|
+
continue;
|
|
123
|
+
}
|
|
124
|
+
const file = matches[0];
|
|
125
|
+
try {
|
|
126
|
+
const raw = readRawRecipeConfig(file);
|
|
127
|
+
if (!raw || !Object.hasOwn(raw, "template"))
|
|
128
|
+
throw new Error(`Invalid Skill Recipe component: ${skill}/${stem}`);
|
|
129
|
+
assertRecipeHasNoDeclaredName(raw);
|
|
130
|
+
components.push({
|
|
131
|
+
file,
|
|
132
|
+
identity: `${skill}/${stem}`,
|
|
133
|
+
imports: Object.fromEntries(Object.entries(getRecipeImports(raw)).map(([alias, value]) => [
|
|
134
|
+
alias,
|
|
135
|
+
getImportFrom(value),
|
|
136
|
+
])),
|
|
137
|
+
skill,
|
|
138
|
+
stem,
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
catch (error) {
|
|
142
|
+
rejected.push({
|
|
143
|
+
file,
|
|
144
|
+
reason: error instanceof Error ? error.message : String(error),
|
|
145
|
+
skill,
|
|
146
|
+
stem,
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
return { components, partial: rejected.length > 0, rejected };
|
|
152
|
+
}
|
|
153
|
+
export function listActiveSkillRecipeComponents(context) {
|
|
154
|
+
const inventory = inventoryActiveSkillRecipeComponents(context);
|
|
155
|
+
if (inventory.rejected.length > 0)
|
|
156
|
+
throw new Error(inventory.rejected[0].reason);
|
|
157
|
+
return inventory.components;
|
|
37
158
|
}
|
|
38
|
-
|
|
159
|
+
const SKILL_RECIPE_REFERENCE = /^([a-z][a-z0-9]*(?:-[a-z0-9]+)*)\/([a-z][a-z0-9]*(?:-[a-z0-9]+)*)$/;
|
|
160
|
+
function qualifiedRecipeNameForFile(file, context) {
|
|
39
161
|
const path = resolve(file);
|
|
40
|
-
const
|
|
41
|
-
|
|
42
|
-
!stdRelation.startsWith("..") &&
|
|
43
|
-
!isAbsolute(stdRelation)) {
|
|
44
|
-
return `std:${stdRelation.replace(/\.(?:json|md)$/u, "")}`;
|
|
45
|
-
}
|
|
46
|
-
for (const [skillName, roots] of activeSkillRecipeRoots) {
|
|
47
|
-
if (roots.size !== 1)
|
|
162
|
+
for (const [skillName, roots] of Object.entries(context.namespaces)) {
|
|
163
|
+
if (roots.length !== 1)
|
|
48
164
|
continue;
|
|
49
|
-
const root =
|
|
165
|
+
const root = roots[0];
|
|
50
166
|
const relation = relative(root, path);
|
|
51
|
-
if (relation &&
|
|
52
|
-
|
|
167
|
+
if (relation &&
|
|
168
|
+
dirname(relation) === "." &&
|
|
169
|
+
!relation.startsWith("..") &&
|
|
170
|
+
!isAbsolute(relation)) {
|
|
171
|
+
return `${skillName}/${basename(relation, extname(relation))}`;
|
|
172
|
+
}
|
|
53
173
|
}
|
|
54
174
|
return undefined;
|
|
55
175
|
}
|
|
56
|
-
function
|
|
176
|
+
function assertRecipeReferencePrefixWasNotRemoved(value) {
|
|
57
177
|
if (value.startsWith("std:")) {
|
|
58
|
-
|
|
178
|
+
throw new Error("std: Recipe references were removed in pi-actors 0.46.\nUse <skill>/<recipe> or an explicit .json/.md file path.");
|
|
59
179
|
}
|
|
60
|
-
if (
|
|
180
|
+
if (value.startsWith("skill:")) {
|
|
181
|
+
throw new Error("skill: Recipe references were removed in pi-actors 0.46.\nUse <skill>/<recipe> without a prefix.");
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
function skillRecipeCandidates(value, context) {
|
|
185
|
+
const match = SKILL_RECIPE_REFERENCE.exec(value);
|
|
186
|
+
if (!match)
|
|
61
187
|
return undefined;
|
|
62
|
-
const
|
|
63
|
-
const
|
|
64
|
-
if (separator <= 0 || separator === qualified.length - 1)
|
|
65
|
-
throw new Error(`Invalid Skill Recipe reference: ${value}`);
|
|
66
|
-
const skillName = qualified.slice(0, separator);
|
|
67
|
-
const recipeName = qualified.slice(separator + 1);
|
|
68
|
-
const roots = [...(activeSkillRecipeRoots.get(skillName) ?? [])];
|
|
188
|
+
const [, skillName, recipeName] = match;
|
|
189
|
+
const roots = [...(context.namespaces[skillName] ?? [])];
|
|
69
190
|
if (roots.length === 0)
|
|
70
|
-
throw new Error(`Active Skill Recipe
|
|
191
|
+
throw new Error(`Active Skill Recipe not found: ${skillName}/${recipeName}`);
|
|
71
192
|
if (roots.length > 1)
|
|
72
|
-
throw new Error(`
|
|
193
|
+
throw new Error(`Duplicate active Skill identity ${skillName}: ${roots.join(", ")}`);
|
|
73
194
|
const root = roots[0];
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
});
|
|
195
|
+
const candidates = ["json", "md"].map((extension) => resolve(root, `${recipeName}.${extension}`));
|
|
196
|
+
const existing = candidates.filter((candidate) => existsSync(candidate));
|
|
197
|
+
if (existing.length > 1) {
|
|
198
|
+
throw new Error(`Skill Recipe stem collision: ${skillName}/${recipeName} has both .json and .md files`);
|
|
199
|
+
}
|
|
200
|
+
return candidates;
|
|
81
201
|
}
|
|
82
|
-
function
|
|
83
|
-
|
|
202
|
+
function recipeReferenceCandidates(value, baseDir, context) {
|
|
203
|
+
const trimmed = value.trim();
|
|
204
|
+
if (!trimmed)
|
|
205
|
+
return undefined;
|
|
206
|
+
assertRecipeReferencePrefixWasNotRemoved(trimmed);
|
|
207
|
+
if (trimmed.endsWith(".json") || trimmed.endsWith(".md")) {
|
|
208
|
+
return [resolve(baseDir, trimmed)];
|
|
209
|
+
}
|
|
210
|
+
return skillRecipeCandidates(trimmed, context);
|
|
84
211
|
}
|
|
85
212
|
function findOwningSkillDir(recipeFile) {
|
|
86
213
|
let current = dirname(recipeFile);
|
|
@@ -93,11 +220,16 @@ function findOwningSkillDir(recipeFile) {
|
|
|
93
220
|
current = parent;
|
|
94
221
|
}
|
|
95
222
|
}
|
|
223
|
+
function assertRecipeHasNoDeclaredName(raw) {
|
|
224
|
+
if (!Object.hasOwn(raw, "name"))
|
|
225
|
+
return;
|
|
226
|
+
throw new Error("Recipe.name was removed in pi-actors 0.46.\nFile-backed Recipe identity is derived from its file name.");
|
|
227
|
+
}
|
|
96
228
|
function assertRuntimeRecipeValuesNotDeclared(raw) {
|
|
97
229
|
const args = Array.isArray(raw.args)
|
|
98
230
|
? Schema.getExplicitToolArgNames(raw.args.map(String))
|
|
99
231
|
: [];
|
|
100
|
-
for (const name of
|
|
232
|
+
for (const name of RESERVED_AUTHORED_RECIPE_VALUE_NAMES) {
|
|
101
233
|
if (args.includes(name) ||
|
|
102
234
|
(isRecord(raw.defaults) && Object.hasOwn(raw.defaults, name)) ||
|
|
103
235
|
(isRecord(raw.values) && Object.hasOwn(raw.values, name))) {
|
|
@@ -105,82 +237,28 @@ function assertRuntimeRecipeValuesNotDeclared(raw) {
|
|
|
105
237
|
}
|
|
106
238
|
}
|
|
107
239
|
}
|
|
108
|
-
export function resolveRecipePath(value,
|
|
109
|
-
const
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
if (expanded.startsWith("~/"))
|
|
115
|
-
return resolve(homedir(), expanded.slice(2));
|
|
116
|
-
if (expanded.includes("/"))
|
|
117
|
-
return resolve(expanded);
|
|
118
|
-
return resolve(recipeRoot, expanded.endsWith(".json") || expanded.endsWith(".md")
|
|
119
|
-
? expanded
|
|
120
|
-
: `${expanded}.json`);
|
|
121
|
-
}
|
|
122
|
-
function isBareRecipeName(value) {
|
|
123
|
-
const trimmed = value.trim();
|
|
124
|
-
return (Boolean(trimmed) &&
|
|
125
|
-
!trimmed.includes("/") &&
|
|
126
|
-
!trimmed.startsWith("~") &&
|
|
127
|
-
!trimmed.includes("{"));
|
|
240
|
+
export function resolveRecipePath(value, baseDir = Paths.getRecipeRoot()) {
|
|
241
|
+
const candidates = recipeReferenceCandidates(value, baseDir, EMPTY_ACTIVE_SKILL_RECIPE_CONTEXT);
|
|
242
|
+
if (!candidates || candidates.length !== 1) {
|
|
243
|
+
throw new Error(`Recipe file reference must be an explicit .json or .md path: ${value}`);
|
|
244
|
+
}
|
|
245
|
+
return candidates[0];
|
|
128
246
|
}
|
|
129
|
-
function
|
|
130
|
-
const
|
|
131
|
-
if (
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
}
|
|
135
|
-
function recipeCandidatePaths(value, currentRecipeRoot) {
|
|
136
|
-
const qualified = qualifiedRecipeCandidates(value.trim());
|
|
137
|
-
if (qualified)
|
|
138
|
-
return qualified;
|
|
139
|
-
if (!isBareRecipeName(value))
|
|
140
|
-
return [resolveRecipePath(value, currentRecipeRoot)];
|
|
141
|
-
const roots = [
|
|
142
|
-
Paths.getRecipeRoot(),
|
|
143
|
-
currentRecipeRoot,
|
|
144
|
-
Paths.getPackagedRecipeRoot(),
|
|
145
|
-
];
|
|
146
|
-
return [
|
|
147
|
-
...new Set(roots.flatMap((root) => recipeNameFiles(value).map((file) => resolve(root, file)))),
|
|
148
|
-
];
|
|
149
|
-
}
|
|
150
|
-
function resolveRecipeImportPath(value, currentRecipeRoot) {
|
|
151
|
-
const candidates = recipeCandidatePaths(value, currentRecipeRoot);
|
|
247
|
+
function resolveRecipeImportPath(value, recipeDir, context) {
|
|
248
|
+
const candidates = recipeReferenceCandidates(value, recipeDir, context);
|
|
249
|
+
if (!candidates) {
|
|
250
|
+
throw new Error(`Recipe import must use <skill>/<recipe> or an explicit .json/.md file path: ${value}`);
|
|
251
|
+
}
|
|
152
252
|
return candidates.find((candidate) => existsSync(candidate)) ?? candidates[0];
|
|
153
253
|
}
|
|
154
|
-
export function resolveRecipeReferencePath(value,
|
|
254
|
+
export function resolveRecipeReferencePath(value, baseDir = Paths.getRecipeRoot(), context = EMPTY_ACTIVE_SKILL_RECIPE_CONTEXT) {
|
|
155
255
|
if (typeof value !== "string")
|
|
156
256
|
return undefined;
|
|
157
|
-
const
|
|
158
|
-
|
|
159
|
-
return undefined;
|
|
160
|
-
for (const path of recipeCandidatePaths(trimmed, currentRecipeRoot)) {
|
|
161
|
-
if (!existsSync(path))
|
|
162
|
-
continue;
|
|
163
|
-
try {
|
|
164
|
-
const raw = readRawRecipeConfig(path);
|
|
165
|
-
if (raw && typeof raw === "object" && Object.hasOwn(raw, "template"))
|
|
166
|
-
return path;
|
|
167
|
-
return path;
|
|
168
|
-
}
|
|
169
|
-
catch {
|
|
170
|
-
return path;
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
return undefined;
|
|
257
|
+
const candidates = recipeReferenceCandidates(value, baseDir, context);
|
|
258
|
+
return candidates?.find((candidate) => existsSync(candidate));
|
|
174
259
|
}
|
|
175
|
-
export function getRecipePath(value,
|
|
176
|
-
|
|
177
|
-
return undefined;
|
|
178
|
-
const trimmed = value.trim();
|
|
179
|
-
if (!trimmed || hasWhitespace(trimmed))
|
|
180
|
-
return undefined;
|
|
181
|
-
if (trimmed.endsWith(".json") || trimmed.endsWith(".md"))
|
|
182
|
-
return resolveRecipePath(trimmed, recipeRoot);
|
|
183
|
-
return resolveRecipeReferencePath(trimmed, recipeRoot);
|
|
260
|
+
export function getRecipePath(value, baseDir = Paths.getRecipeRoot(), context = EMPTY_ACTIVE_SKILL_RECIPE_CONTEXT) {
|
|
261
|
+
return resolveRecipeReferencePath(value, baseDir, context);
|
|
184
262
|
}
|
|
185
263
|
function isImportNode(value) {
|
|
186
264
|
if (!isRecord(value) || Object.hasOwn(value, "template"))
|
|
@@ -655,7 +733,7 @@ function withActorRecipeContext(value, context) {
|
|
|
655
733
|
return { actorRecipeContext: context, template: value };
|
|
656
734
|
}
|
|
657
735
|
function loadDelegatedRecipe(value, currentRecipeFile, stack, options) {
|
|
658
|
-
const path = resolveRecipeReferencePath(value, dirname(currentRecipeFile));
|
|
736
|
+
const path = resolveRecipeReferencePath(value, dirname(currentRecipeFile), options.skillContext);
|
|
659
737
|
if (!path)
|
|
660
738
|
return undefined;
|
|
661
739
|
const config = readResolvedRecipeConfig(path, [...stack, currentRecipeFile], options);
|
|
@@ -712,6 +790,28 @@ function getDirectDelegatedRecipe(value, currentRecipeFile, stack, options = {})
|
|
|
712
790
|
}
|
|
713
791
|
return undefined;
|
|
714
792
|
}
|
|
793
|
+
function resolveDirectDelegationArgs(delegated, wrapperArgs, wrapperDefaults) {
|
|
794
|
+
if (!Array.isArray(delegated.args))
|
|
795
|
+
return Array.isArray(wrapperArgs) ? wrapperArgs.map(String) : undefined;
|
|
796
|
+
const delegatedSpec = Schema.parseToolArgDeclarationList(delegated.args);
|
|
797
|
+
if (delegatedSpec.error)
|
|
798
|
+
throw new Error(delegatedSpec.error);
|
|
799
|
+
const wrapperDeclarations = Array.isArray(wrapperArgs)
|
|
800
|
+
? wrapperArgs.map(String)
|
|
801
|
+
: [];
|
|
802
|
+
const wrapperSpec = Schema.parseToolArgDeclarationList(wrapperDeclarations);
|
|
803
|
+
if (wrapperSpec.error)
|
|
804
|
+
throw new Error(wrapperSpec.error);
|
|
805
|
+
const declared = new Set(delegatedSpec.args);
|
|
806
|
+
for (const arg of wrapperSpec.args) {
|
|
807
|
+
if (!declared.has(arg))
|
|
808
|
+
throw new Error(`Unknown delegated Recipe argument: ${arg}`);
|
|
809
|
+
}
|
|
810
|
+
Schema.assertCompatibleToolArgTypes(delegatedSpec.argTypes, wrapperSpec.argTypes);
|
|
811
|
+
assertRecipeDefaultsDeclared(delegated.args, wrapperDefaults, "delegated Recipe default");
|
|
812
|
+
Schema.normalizeRuntimeValues(Object.fromEntries(Object.entries(wrapperDefaults ?? {}).filter(([, value]) => typeof value !== "string" || !/\{[^{}]+\}/.test(value))), delegatedSpec.argTypes);
|
|
813
|
+
return delegated.args;
|
|
814
|
+
}
|
|
715
815
|
function expandImportNodes(value, imports, options = {}) {
|
|
716
816
|
if (typeof value === "string")
|
|
717
817
|
return value;
|
|
@@ -764,15 +864,18 @@ export function readResolvedRecipeConfig(file, stack = [], options = {}) {
|
|
|
764
864
|
if (stack.length >= MAX_RECIPE_IMPORT_DEPTH) {
|
|
765
865
|
throw new Error(`Recipe import depth exceeds limit ${MAX_RECIPE_IMPORT_DEPTH}: ${[...stack, path].join(" -> ")}`);
|
|
766
866
|
}
|
|
767
|
-
const raw =
|
|
867
|
+
const raw = options.authoredEntry?.path === path
|
|
868
|
+
? options.authoredEntry.recipe
|
|
869
|
+
: readRawRecipeConfig(path);
|
|
768
870
|
if (!raw || !Object.hasOwn(raw, "template"))
|
|
769
871
|
return undefined;
|
|
872
|
+
assertRecipeHasNoDeclaredName(raw);
|
|
770
873
|
RecipeControl.assertRecipeHasNoMailbox(raw);
|
|
771
874
|
assertRuntimeRecipeValuesNotDeclared(raw);
|
|
772
875
|
assertRecipeArgumentContract(raw);
|
|
773
876
|
const imports = {};
|
|
774
877
|
for (const [alias, binding] of Object.entries(getRecipeImports(raw))) {
|
|
775
|
-
const importPath = resolveRecipeImportPath(getImportFrom(binding), dirname(path));
|
|
878
|
+
const importPath = resolveRecipeImportPath(getImportFrom(binding), dirname(path), options.skillContext ?? EMPTY_ACTIVE_SKILL_RECIPE_CONTEXT);
|
|
776
879
|
const config = readResolvedRecipeConfig(importPath, [...stack, path], options);
|
|
777
880
|
if (!config)
|
|
778
881
|
throw new Error(`Recipe import not found: ${alias}`);
|
|
@@ -782,7 +885,7 @@ export function readResolvedRecipeConfig(file, stack = [], options = {}) {
|
|
|
782
885
|
imports[alias] = {
|
|
783
886
|
alias,
|
|
784
887
|
file: importPath,
|
|
785
|
-
name:
|
|
888
|
+
name: getRecipeIdFromPath(importPath),
|
|
786
889
|
config,
|
|
787
890
|
defaults: { ...(config.defaults ?? {}), ...(bindingDefaults ?? {}) },
|
|
788
891
|
values: {
|
|
@@ -824,7 +927,15 @@ export function readResolvedRecipeConfig(file, stack = [], options = {}) {
|
|
|
824
927
|
role: stack.length > 0 ? "import" : "entry",
|
|
825
928
|
})
|
|
826
929
|
: expandedTemplate;
|
|
827
|
-
const
|
|
930
|
+
const wrapperDefaults = isRecord(substituted.defaults)
|
|
931
|
+
? substituted.defaults
|
|
932
|
+
: undefined;
|
|
933
|
+
const mergedDefaults = mergeDefaults(delegated?.defaults, wrapperDefaults);
|
|
934
|
+
const effectiveArgs = delegated
|
|
935
|
+
? resolveDirectDelegationArgs(delegated, substituted.args, wrapperDefaults)
|
|
936
|
+
: Array.isArray(substituted.args)
|
|
937
|
+
? substituted.args
|
|
938
|
+
: undefined;
|
|
828
939
|
const artifactSource = isRecord(substituted.artifacts)
|
|
829
940
|
? substituted.artifacts
|
|
830
941
|
: delegated?.artifacts;
|
|
@@ -859,11 +970,7 @@ export function readResolvedRecipeConfig(file, stack = [], options = {}) {
|
|
|
859
970
|
? { imports: getRecipeImports(raw) }
|
|
860
971
|
: {}),
|
|
861
972
|
template: templateWithContext,
|
|
862
|
-
...(
|
|
863
|
-
? { args: substituted.args }
|
|
864
|
-
: Array.isArray(delegated?.args)
|
|
865
|
-
? { args: delegated.args }
|
|
866
|
-
: {}),
|
|
973
|
+
...(effectiveArgs ? { args: effectiveArgs } : {}),
|
|
867
974
|
...(mergedDefaults ? { defaults: mergedDefaults } : {}),
|
|
868
975
|
...(typeof substituted.parallel === "boolean"
|
|
869
976
|
? { parallel: substituted.parallel }
|
|
@@ -930,7 +1037,7 @@ export function readResolvedRecipeConfig(file, stack = [], options = {}) {
|
|
|
930
1037
|
...(isRecord(substituted.usage) ? { usage: substituted.usage } : {}),
|
|
931
1038
|
};
|
|
932
1039
|
}
|
|
933
|
-
function collectRecipeContextRecords(file, stack, importPath, alias) {
|
|
1040
|
+
function collectRecipeContextRecords(file, stack, importPath, context, alias) {
|
|
934
1041
|
const path = resolveRecipePath(file, stack.length > 0 ? dirname(stack.at(-1)) : Paths.getRecipeRoot());
|
|
935
1042
|
if (stack.includes(path)) {
|
|
936
1043
|
throw new Error(`Cyclic recipe import: ${[...stack, path].join(" -> ")}`);
|
|
@@ -941,26 +1048,32 @@ function collectRecipeContextRecords(file, stack, importPath, alias) {
|
|
|
941
1048
|
const raw = readRawRecipeConfig(path);
|
|
942
1049
|
if (!raw || !Object.hasOwn(raw, "template"))
|
|
943
1050
|
return [];
|
|
944
|
-
|
|
1051
|
+
assertRecipeHasNoDeclaredName(raw);
|
|
1052
|
+
const qualifiedName = qualifiedRecipeNameForFile(path, context);
|
|
1053
|
+
const skill = qualifiedName?.split("/", 1)[0];
|
|
945
1054
|
const record = {
|
|
946
1055
|
...(alias ? { alias } : {}),
|
|
947
1056
|
depth: stack.length,
|
|
948
|
-
file: path,
|
|
949
1057
|
import_path: importPath,
|
|
1058
|
+
logical_reference: qualifiedName ?? basename(path),
|
|
950
1059
|
name: getRecipeIdFromPath(path),
|
|
951
|
-
...(qualifiedName ? { qualified_name: qualifiedName } : {}),
|
|
952
1060
|
recipe: raw,
|
|
953
1061
|
role: stack.length === 0 ? "entry" : "import",
|
|
1062
|
+
...(skill ? { skill } : {}),
|
|
1063
|
+
source_file: path,
|
|
1064
|
+
source_kind: qualifiedName
|
|
1065
|
+
? "active_skill_component"
|
|
1066
|
+
: "explicit_file_recipe",
|
|
954
1067
|
};
|
|
955
1068
|
const imports = getRecipeImports(raw);
|
|
956
1069
|
const children = Object.entries(imports).flatMap(([childAlias, binding]) => {
|
|
957
|
-
const importFile = resolveRecipeImportPath(getImportFrom(binding), dirname(path));
|
|
958
|
-
return collectRecipeContextRecords(importFile, [...stack, path], [...importPath, childAlias], childAlias);
|
|
1070
|
+
const importFile = resolveRecipeImportPath(getImportFrom(binding), dirname(path), context);
|
|
1071
|
+
return collectRecipeContextRecords(importFile, [...stack, path], [...importPath, childAlias], context, childAlias);
|
|
959
1072
|
});
|
|
960
1073
|
return [record, ...children];
|
|
961
1074
|
}
|
|
962
|
-
export function buildRecipeContextRecords(file) {
|
|
963
|
-
return collectRecipeContextRecords(file, [], []);
|
|
1075
|
+
export function buildRecipeContextRecords(file, context = EMPTY_ACTIVE_SKILL_RECIPE_CONTEXT) {
|
|
1076
|
+
return collectRecipeContextRecords(file, [], [], context);
|
|
964
1077
|
}
|
|
965
1078
|
export function getRecipeTemplate(value) {
|
|
966
1079
|
return readRecipeConfig(value)?.template;
|
package/dist/lib/registry.d.ts
CHANGED
|
@@ -16,16 +16,24 @@ export interface RegisterToolInput {
|
|
|
16
16
|
values?: Record<string, unknown>;
|
|
17
17
|
}
|
|
18
18
|
export interface RegisterToolResultDetails {
|
|
19
|
+
active_tool?: boolean;
|
|
20
|
+
activation?: "current_session" | "unverified";
|
|
19
21
|
args?: string[];
|
|
20
22
|
async?: boolean;
|
|
23
|
+
callable_now?: boolean;
|
|
21
24
|
config?: string;
|
|
22
25
|
defaults?: Record<string, string>;
|
|
23
26
|
draft?: string;
|
|
27
|
+
host_registered?: boolean;
|
|
28
|
+
persisted?: boolean;
|
|
24
29
|
promoted?: boolean;
|
|
30
|
+
registry_active?: boolean;
|
|
31
|
+
resolved?: boolean;
|
|
25
32
|
recipeName?: string;
|
|
26
33
|
template?: CommandTemplates.CommandTemplateValue;
|
|
27
34
|
templateWarnings?: string[];
|
|
28
35
|
tool: string;
|
|
36
|
+
validated?: boolean;
|
|
29
37
|
}
|
|
30
38
|
export interface RegisterToolResult {
|
|
31
39
|
content: Array<{
|
|
@@ -41,7 +49,12 @@ export interface RegisterToolRuntimeDeps<TContext> {
|
|
|
41
49
|
getTools: () => Map<string, Config.RegisteredTool>;
|
|
42
50
|
getActiveTools: () => string[];
|
|
43
51
|
notify: (ctx: TContext, message: string, type: "info" | "warning" | "error") => void;
|
|
44
|
-
registerRuntimeTool: (cfg: Config.RegisteredTool) =>
|
|
52
|
+
registerRuntimeTool: (cfg: Config.RegisteredTool) => {
|
|
53
|
+
active_tool: boolean;
|
|
54
|
+
activation: "current_session" | "unverified";
|
|
55
|
+
callable_now: boolean;
|
|
56
|
+
host_registered: boolean;
|
|
57
|
+
} | void;
|
|
45
58
|
reservedToolNames: Set<string>;
|
|
46
59
|
setActiveTools: (toolNames: string[]) => void;
|
|
47
60
|
}
|