@llblab/pi-actors 0.45.0 → 0.46.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/AGENTS.md +10 -6
- package/CHANGELOG.md +14 -1
- package/README.md +28 -12
- package/dist/fixtures/protocol/recipe-summary.json +1 -1
- package/dist/index.d.ts +1 -2
- package/dist/index.js +10 -110
- package/dist/lib/async-runs.d.ts +4 -1
- package/dist/lib/async-runs.js +22 -23
- 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/extension-runtime.d.ts +21 -0
- package/dist/lib/extension-runtime.js +122 -0
- package/dist/lib/inspector.js +45 -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 +2 -2
- package/dist/lib/recipes-context.js +2 -2
- package/dist/lib/recipes-references.d.ts +24 -9
- package/dist/lib/recipes-references.js +152 -126
- package/dist/lib/runtime.d.ts +0 -1
- package/dist/lib/runtime.js +1 -3
- package/dist/lib/tools-inspect.d.ts +0 -1
- package/dist/lib/tools-inspect.js +35 -8
- package/dist/lib/tools-local.d.ts +2 -0
- package/dist/lib/tools-local.js +1 -1
- package/dist/lib/tools-spawn.d.ts +2 -0
- package/dist/lib/tools-spawn.js +24 -52
- package/dist/scripts/async-runner.mjs +0 -16
- package/dist/scripts/build-dist.mjs +13 -4
- package/dist/skills/actors/SKILL.md +6 -6
- 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 -23
- package/dist/skills/actors/scripts/run-utils.mjs +164 -0
- package/{scripts → dist/skills/actors/scripts}/validate-recipe.mjs +134 -18
- 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 +30 -14
- package/docs/tool-registry.md +2 -2
- package/fixtures/protocol/recipe-summary.json +1 -1
- package/index.ts +18 -112
- package/lib/async-runs.ts +47 -24
- package/lib/automatic-review-runtime.ts +16 -3
- package/lib/draft-sleep.ts +0 -1
- package/lib/extension-runtime.ts +158 -0
- package/lib/inspector.ts +56 -11
- package/lib/paths.ts +0 -7
- package/lib/prompts.ts +2 -2
- package/lib/recipes-context.ts +2 -2
- package/lib/recipes-references.ts +223 -134
- package/lib/runtime.ts +1 -5
- package/lib/tools-inspect.ts +42 -9
- package/lib/tools-local.ts +2 -0
- package/lib/tools-spawn.ts +37 -74
- package/package.json +3 -5
- package/scripts/async-runner.mjs +0 -16
- package/scripts/build-dist.mjs +13 -4
- package/skills/actors/SKILL.md +6 -6
- 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 -23
- package/skills/actors/scripts/run-utils.mjs +164 -0
- package/{dist → skills/actors}/scripts/validate-recipe.mjs +134 -18
- 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/recipe-utils.mjs +0 -405
- package/dist/scripts/release-gates.mjs +0 -278
- 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/recipe-utils.mjs +0 -405
- package/scripts/release-gates.mjs +0 -278
- /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
package/docs/template-recipes.md
CHANGED
|
@@ -10,7 +10,7 @@ A Recipe stores a reusable command-template definition as JSON or Markdown.
|
|
|
10
10
|
"description": "Create a repository health artifact",
|
|
11
11
|
"args": ["repo:path", "artifact_path:path", "model:string"],
|
|
12
12
|
"defaults": { "artifact_path": "{state_dir}/health.md" },
|
|
13
|
-
"imports": { "review": "
|
|
13
|
+
"imports": { "review": "swarm/quorum-review" },
|
|
14
14
|
"artifacts": { "report": "{artifact_path}" },
|
|
15
15
|
"template": {
|
|
16
16
|
"name": "review",
|
|
@@ -39,11 +39,13 @@ summarize {file}
|
|
|
39
39
|
|
|
40
40
|
Fences marked `template`, `command-template`, `json`, or `recipe` can define execution. Frontmatter supports Recipe metadata and command-template flags.
|
|
41
41
|
|
|
42
|
+
Skill Recipe identity is `<active Skill name>/<Recipe filename stem>`. Recipe files have no top-level `name`; both JSON and Markdown fail with migration guidance when that removed field is present. `SKILL.md` `name` remains Pi host metadata and matches the Skill directory; pi-actors introduces no additional Skill identity field. The `name` field on a command-template node still selects an imported alias and is not Recipe self-identity.
|
|
43
|
+
|
|
42
44
|
## Fields
|
|
43
45
|
|
|
44
46
|
Common Recipe fields:
|
|
45
47
|
|
|
46
|
-
- `
|
|
48
|
+
- `description`, `disabled`;
|
|
47
49
|
- `args`, typed arg declarations, inline defaults, `defaults`, and composition `values`;
|
|
48
50
|
- `imports` with optional binding defaults/values;
|
|
49
51
|
- `template`;
|
|
@@ -58,25 +60,39 @@ Common Recipe fields:
|
|
|
58
60
|
```json
|
|
59
61
|
{
|
|
60
62
|
"imports": {
|
|
61
|
-
"review": "
|
|
62
|
-
"
|
|
63
|
-
"from": "
|
|
63
|
+
"review": "swarm/quorum-review",
|
|
64
|
+
"report": {
|
|
65
|
+
"from": "../shared/report.md",
|
|
64
66
|
"defaults": { "thinking": "medium" }
|
|
65
67
|
}
|
|
66
68
|
},
|
|
67
69
|
"template": [
|
|
68
70
|
{ "name": "review", "values": { "input": "{input}" } },
|
|
69
|
-
{ "name": "
|
|
71
|
+
{ "name": "report", "values": { "input": "Use prior output" } }
|
|
70
72
|
]
|
|
71
73
|
}
|
|
72
74
|
```
|
|
73
75
|
|
|
74
76
|
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
77
|
|
|
76
|
-
|
|
78
|
+
Imports accept exactly `<skill>/<recipe>` or an explicit `.json` / `.md` file path. A Skill reference selects one direct filename stem under the exact Skill currently active through Pi resource discovery; duplicate active Skill identities and JSON/Markdown stem collisions fail closed. Explicit paths may be relative (`./local-review.json`, `../shared/report.md`) or absolute (`/absolute/path/to/recipe.json`). An entry file path resolves from invocation `cwd`; a relative import resolves from the importing Recipe's directory. No bare or ambient lookup remains.
|
|
77
79
|
|
|
78
80
|
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.
|
|
79
81
|
|
|
82
|
+
A launched Run captures each entry/import role, filename-derived stem, logical reference, Skill identity when owned, and import alias ancestry. Private physical source paths remain execution provenance; Inspector and child-agent context expose logical identities rather than machine-local Skill locations.
|
|
83
|
+
|
|
84
|
+
## Migration from pre-0.46 references
|
|
85
|
+
|
|
86
|
+
```text
|
|
87
|
+
std:foo -> owning-skill/foo
|
|
88
|
+
skill:foo/bar -> foo/bar
|
|
89
|
+
root packaged foo -> owning-skill/new-file-stem
|
|
90
|
+
Recipe name field -> delete; filename is identity
|
|
91
|
+
nested skill path -> flatten filename or use explicit file path
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
Removed `std:` and `skill:` forms fail with migration guidance; they are not aliases. Root packaged Recipes no longer exist. Flatten a maintained Skill component to a direct filename, or reference a nested/local file explicitly when it is intentionally outside the Skill component namespace.
|
|
95
|
+
|
|
80
96
|
## Control
|
|
81
97
|
|
|
82
98
|
Only a process that consumes actor-local input declares actions:
|
|
@@ -85,7 +101,7 @@ Only a process that consumes actor-local input declares actions:
|
|
|
85
101
|
{
|
|
86
102
|
"async": true,
|
|
87
103
|
"control": ["pause", "resume", "stop"],
|
|
88
|
-
"template": "{
|
|
104
|
+
"template": "{skill_dir}/scripts/service.mjs --state-dir {state_dir}"
|
|
89
105
|
}
|
|
90
106
|
```
|
|
91
107
|
|
|
@@ -110,7 +126,7 @@ Every file-backed Recipe receives immutable `{recipe_dir}`. A Recipe under an ac
|
|
|
110
126
|
|
|
111
127
|
## Context and Provenance
|
|
112
128
|
|
|
113
|
-
File-backed Runs capture Recipe context records for the entry and imports
|
|
129
|
+
File-backed Runs capture Recipe context records for the entry and imports. File identity is the filename stem; a direct Recipe under an active Skill has the logical identity `<skill>/<stem>`. 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.
|
|
114
130
|
|
|
115
131
|
Recipes that need a minimal child prompt may opt out of injected Recipe context through the documented `actor_context` launch option.
|
|
116
132
|
|
|
@@ -129,18 +145,18 @@ Defaults can inherit current Pi policy:
|
|
|
129
145
|
|
|
130
146
|
Resolution fails before launch when required current policy is unavailable. The Run persists whether values were inherited or explicit.
|
|
131
147
|
|
|
132
|
-
## Resolution
|
|
148
|
+
## Resolution Context
|
|
133
149
|
|
|
134
|
-
User Recipes under `~/.pi/agent/recipes`
|
|
150
|
+
User Recipes under `~/.pi/agent/recipes` remain intentionally registered tools, not an ambient import namespace. Each session receives an immutable active-Skill resolution context from Pi's loaded Skill metadata; pi-actors does not scan ambient Skill roots independently or keep a process-global mutable namespace. A launch captures its resolved graph, so later Skill changes affect only future launches. An invalid or missing exact target fails without fallback. Disabled Recipes cannot launch. Registry watchers converge after atomic changes without executing partial definitions.
|
|
135
151
|
|
|
136
152
|
## Validation
|
|
137
153
|
|
|
138
154
|
```bash
|
|
139
|
-
node scripts/validate-recipe.mjs
|
|
140
|
-
node scripts/validate-recipe.mjs
|
|
155
|
+
node skills/actors/scripts/validate-recipe.mjs path/to/recipe.json --qa
|
|
156
|
+
node skills/actors/scripts/validate-recipe.mjs skills --skills --qa --summary
|
|
141
157
|
```
|
|
142
158
|
|
|
143
|
-
|
|
159
|
+
Skill validation recursively inventories every direct `<skill>/recipes/*.json|*.md` component, rejects nested files and duplicate stems, and checks filename identity, JSON/Markdown compilation, origins, imports, Control, artifacts, portable paths, helper targets, and platform notes. Files exceeding 1 MiB or import depth 32 fail closed.
|
|
144
160
|
|
|
145
161
|
## Related
|
|
146
162
|
|
package/docs/tool-registry.md
CHANGED
|
@@ -22,7 +22,7 @@ Promote an immutable captured draft only with its draft path and explicit target
|
|
|
22
22
|
|
|
23
23
|
## Resolution
|
|
24
24
|
|
|
25
|
-
User Recipes
|
|
25
|
+
User Recipes are the only file-discovered tool source. Invalid or disabled user entries fail closed. Active Skill Recipes remain exact components outside tool discovery. Runtime reload watches the user Recipe root and converges after atomic changes; stale watcher generations cannot replace current registration state.
|
|
26
26
|
|
|
27
27
|
Inspect registry state with:
|
|
28
28
|
|
|
@@ -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 Recipe by exact
|
|
64
|
+
Prefer a small user-root wrapper that imports a maintained Recipe by exact `<skill>/<recipe>` 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
|
@@ -1,124 +1,30 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* pi-actors — actor runtime and persistent local tool registry for pi.
|
|
3
3
|
* Zones: composition root, pi agent, actor runtime
|
|
4
|
-
*
|
|
5
|
-
* Wraps command templates as callable pi tools, stores durable user tools as recipe files, and exposes actor orchestration across reloads and sessions.
|
|
4
|
+
* Owns extension composition and Pi event registration, not domain behavior.
|
|
6
5
|
*/
|
|
7
6
|
|
|
8
|
-
import * as
|
|
9
|
-
import * as CommandTemplates from "./lib/command-templates.ts";
|
|
7
|
+
import * as ExtensionRuntime from "./lib/extension-runtime.ts";
|
|
10
8
|
import * as InspectorCommand from "./lib/inspector-command.ts";
|
|
11
|
-
import * as Paths from "./lib/paths.ts";
|
|
12
9
|
import * as Pi from "./lib/pi.ts";
|
|
13
|
-
import * as Prompts from "./lib/prompts.ts";
|
|
14
|
-
import * as RecipesReferences from "./lib/recipes-references.ts";
|
|
15
|
-
import * as RunUiRuntime from "./lib/run-ui-runtime.ts";
|
|
16
|
-
import * as Runtime from "./lib/runtime.ts";
|
|
17
|
-
import * as Temp from "./lib/temp.ts";
|
|
18
|
-
import * as Tools from "./lib/tools.ts";
|
|
19
|
-
import * as ToolsResponse from "./lib/tools-response.ts";
|
|
20
10
|
|
|
21
11
|
export default function toolRegistryExtension(pi: Pi.ExtensionAPI) {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
});
|
|
35
|
-
const actorToolDefinitions = new Map<string, Tools.ActorToolDefinition>();
|
|
36
|
-
const withCurrentThinkingContext = <T extends Tools.ActorToolDefinition>(
|
|
37
|
-
definition: T,
|
|
38
|
-
): T => {
|
|
39
|
-
if (typeof definition.execute !== "function") return definition;
|
|
40
|
-
const execute = definition.execute as (...args: unknown[]) => unknown;
|
|
41
|
-
return {
|
|
42
|
-
...definition,
|
|
43
|
-
execute: async (...args: unknown[]) => {
|
|
44
|
-
const nextArgs = [...args];
|
|
45
|
-
const ctx = nextArgs[4];
|
|
46
|
-
if (ctx && typeof ctx === "object") {
|
|
47
|
-
nextArgs[4] = {
|
|
48
|
-
...(ctx as Record<string, unknown>),
|
|
49
|
-
getThinkingLevel: () => pi.getThinkingLevel(),
|
|
50
|
-
};
|
|
51
|
-
}
|
|
52
|
-
try {
|
|
53
|
-
return ToolsResponse.spaceToolResult(await execute(...nextArgs));
|
|
54
|
-
} catch (error) {
|
|
55
|
-
throw ToolsResponse.spaceToolError(error);
|
|
56
|
-
}
|
|
57
|
-
},
|
|
58
|
-
} as T;
|
|
59
|
-
};
|
|
60
|
-
const runtime = Runtime.createAutoToolsRuntime({
|
|
61
|
-
configPath: Paths.EXTENSION_RUNTIME_PATHS.configPath,
|
|
62
|
-
exec: CommandTemplates.execCommandTemplate,
|
|
63
|
-
getActiveTools: () => pi.getActiveTools(),
|
|
64
|
-
registerTool: (definition) => {
|
|
65
|
-
const wrapped = withCurrentThinkingContext(definition);
|
|
66
|
-
actorToolDefinitions.set(wrapped.name, wrapped);
|
|
67
|
-
pi.registerTool(wrapped);
|
|
68
|
-
},
|
|
69
|
-
reservedToolNames: Tools.RESERVED_TOOL_NAMES,
|
|
70
|
-
setActiveTools: (toolNames) => pi.setActiveTools(toolNames),
|
|
71
|
-
});
|
|
72
|
-
const recipeReload = Runtime.createRecipeToolReloadWatcher(runtime);
|
|
73
|
-
pi.on("resources_discover", async () => {
|
|
74
|
-
const skillPaths = Paths.getExistingExtensionSkillPaths(import.meta.url);
|
|
75
|
-
if (skillPaths.length === 0) return;
|
|
76
|
-
return { skillPaths };
|
|
77
|
-
});
|
|
78
|
-
pi.on("session_start", async (_event, ctx) => {
|
|
79
|
-
// Clear the pre-overlay widget after hot reloads from older pi-actors builds.
|
|
80
|
-
ctx.ui.setWidget("zz-pi-actors-comms", undefined);
|
|
81
|
-
activeRunContext = ctx;
|
|
82
|
-
runUiRuntime.close();
|
|
83
|
-
automaticReview.close();
|
|
84
|
-
recipeReload.close();
|
|
85
|
-
await Temp.prepareExtensionTempDir(Paths.EXTENSION_RUNTIME_PATHS.tempDir);
|
|
86
|
-
if (activeRunContext !== ctx) return;
|
|
87
|
-
automaticReview.start(ctx);
|
|
88
|
-
runtime.loadTools(ctx);
|
|
89
|
-
runUiRuntime.start(ctx);
|
|
90
|
-
recipeReload.watch(ctx);
|
|
91
|
-
});
|
|
92
|
-
pi.on("agent_end", async (_event, ctx) => {
|
|
93
|
-
if (activeRunContext === ctx) automaticReview.schedule();
|
|
94
|
-
});
|
|
95
|
-
pi.on("session_shutdown", async (event, ctx) => {
|
|
96
|
-
activeRunContext = undefined;
|
|
97
|
-
automaticReview.close();
|
|
98
|
-
recipeReload.close();
|
|
99
|
-
runUiRuntime.shutdown(event.reason, ctx);
|
|
100
|
-
});
|
|
101
|
-
InspectorCommand.registerActorInspectorCommand(pi, getRunOwnerId);
|
|
102
|
-
pi.on("before_agent_start", async (event) => {
|
|
103
|
-
RecipesReferences.setActiveSkillRecipeSources(
|
|
12
|
+
const runtime = ExtensionRuntime.createActorExtensionRuntime(pi);
|
|
13
|
+
pi.on("resources_discover", async () =>
|
|
14
|
+
runtime.discoverResources(import.meta.url),
|
|
15
|
+
);
|
|
16
|
+
pi.on("session_start", async (_event, ctx) => runtime.onSessionStart(ctx));
|
|
17
|
+
pi.on("agent_end", async (_event, ctx) => runtime.onAgentEnd(ctx));
|
|
18
|
+
pi.on("session_shutdown", async (event, ctx) =>
|
|
19
|
+
runtime.onSessionShutdown(event.reason, ctx),
|
|
20
|
+
);
|
|
21
|
+
pi.on("before_agent_start", async (event, ctx) =>
|
|
22
|
+
runtime.beforeAgentStart(
|
|
23
|
+
event.systemPrompt,
|
|
104
24
|
event.systemPromptOptions.skills ?? [],
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
systemPrompt: `${event.systemPrompt}\n\n${Prompts.ONBOARDING_SYSTEM_PROMPT}`,
|
|
108
|
-
};
|
|
109
|
-
});
|
|
110
|
-
Pi.registerToolDefinitions(
|
|
111
|
-
pi,
|
|
112
|
-
Tools.createCoreActorToolDefinitions<Pi.ExtensionContext>({
|
|
113
|
-
configPath: Paths.EXTENSION_RUNTIME_PATHS.configPath,
|
|
114
|
-
getActiveTools: () => pi.getActiveTools(),
|
|
115
|
-
getRuntimeTool: (name) =>
|
|
116
|
-
Tools.resolveActiveRuntimeTool(name, runtime.getTools(), (activeName) =>
|
|
117
|
-
actorToolDefinitions.get(activeName),
|
|
118
|
-
),
|
|
119
|
-
handleRuntimeControl: automaticReview.handleControl,
|
|
120
|
-
registryRuntime: runtime,
|
|
121
|
-
setActiveTools: (toolNames) => pi.setActiveTools(toolNames),
|
|
122
|
-
}).map(withCurrentThinkingContext),
|
|
25
|
+
ctx,
|
|
26
|
+
),
|
|
123
27
|
);
|
|
28
|
+
InspectorCommand.registerActorInspectorCommand(pi, runtime.getRunOwnerId);
|
|
29
|
+
runtime.registerCoreTools();
|
|
124
30
|
}
|
package/lib/async-runs.ts
CHANGED
|
@@ -259,11 +259,23 @@ function assertNoActiveRunState(stateDir: string): void {
|
|
|
259
259
|
RunsStart.assertNoActiveRunState(stateDir, readJson, RUNNER_PATH);
|
|
260
260
|
}
|
|
261
261
|
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
262
|
+
export interface AsyncRunStartOptions {
|
|
263
|
+
skillContext?: RecipesReferences.ActiveSkillRecipeContext;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
function resolveRecipeFile(
|
|
267
|
+
file: string,
|
|
268
|
+
cwd: string,
|
|
269
|
+
options: AsyncRunStartOptions,
|
|
270
|
+
): string {
|
|
271
|
+
const path = RecipesReferences.resolveRecipeReferencePath(
|
|
272
|
+
file,
|
|
273
|
+
cwd,
|
|
274
|
+
options.skillContext,
|
|
275
|
+
);
|
|
276
|
+
if (path) return path;
|
|
277
|
+
throw new Error(
|
|
278
|
+
`Recipe reference not found. Use <skill>/<recipe> or an explicit .json/.md file path: ${file}`,
|
|
267
279
|
);
|
|
268
280
|
}
|
|
269
281
|
|
|
@@ -274,13 +286,18 @@ function isMutableUsageRecipeFile(file: string): boolean {
|
|
|
274
286
|
return relation !== "" && !relation.startsWith("..") && !isAbsolute(relation);
|
|
275
287
|
}
|
|
276
288
|
|
|
277
|
-
function readRecipeFile(
|
|
278
|
-
|
|
289
|
+
function readRecipeFile(
|
|
290
|
+
file: string,
|
|
291
|
+
cwd: string,
|
|
292
|
+
options: AsyncRunStartOptions,
|
|
293
|
+
): AsyncRunStartParams {
|
|
294
|
+
const path = resolveRecipeFile(file, cwd, options);
|
|
279
295
|
const raw = RecipesReferences.readRawRecipeConfig(path);
|
|
280
296
|
const includeActorRecipeContext =
|
|
281
297
|
raw?.actor_context !== false && raw?.actor_context !== "off";
|
|
282
298
|
const config = RecipesReferences.readResolvedRecipeConfig(path, [], {
|
|
283
299
|
includeActorRecipeContext,
|
|
300
|
+
skillContext: options.skillContext,
|
|
284
301
|
});
|
|
285
302
|
if (!config) {
|
|
286
303
|
throw new Error(`Template recipe must define template: ${path}`);
|
|
@@ -301,9 +318,13 @@ function getRunIdFromFile(file: string | undefined): string | undefined {
|
|
|
301
318
|
return name || undefined;
|
|
302
319
|
}
|
|
303
320
|
|
|
304
|
-
function resolveStartParams(
|
|
321
|
+
function resolveStartParams(
|
|
322
|
+
params: AsyncRunStartParams,
|
|
323
|
+
cwd: string,
|
|
324
|
+
options: AsyncRunStartOptions,
|
|
325
|
+
): AsyncRunStartParams {
|
|
305
326
|
if (!params.file) return params;
|
|
306
|
-
const fileParams = readRecipeFile(params.file);
|
|
327
|
+
const fileParams = readRecipeFile(params.file, cwd, options);
|
|
307
328
|
return {
|
|
308
329
|
...fileParams,
|
|
309
330
|
...params,
|
|
@@ -468,25 +489,15 @@ function prepareStateDirForStart(stateDir: string): void {
|
|
|
468
489
|
export function startRun(
|
|
469
490
|
params: AsyncRunStartParams,
|
|
470
491
|
cwd: string,
|
|
492
|
+
options: AsyncRunStartOptions = {},
|
|
471
493
|
): AsyncRunMeta {
|
|
472
|
-
const startParams = resolveStartParams(params);
|
|
494
|
+
const startParams = resolveStartParams(params, cwd, options);
|
|
473
495
|
const resolved = resolveRunTemplate(startParams);
|
|
474
496
|
const run = safeRunId(startParams.run_id);
|
|
475
497
|
const stateDir = resolveStateDir(startParams, run);
|
|
476
498
|
const recipeFile = startParams.file
|
|
477
|
-
? resolveRecipeFile(startParams.file)
|
|
499
|
+
? resolveRecipeFile(startParams.file, cwd, options)
|
|
478
500
|
: undefined;
|
|
479
|
-
const packagedRecipeRoot = resolve(Paths.getPackagedRecipeRoot());
|
|
480
|
-
const recipeRelation = recipeFile
|
|
481
|
-
? relative(packagedRecipeRoot, recipeFile)
|
|
482
|
-
: undefined;
|
|
483
|
-
const packagedRepo =
|
|
484
|
-
startParams.defaults?.repo === "~/.pi/agent/extensions/pi-actors" &&
|
|
485
|
-
recipeRelation &&
|
|
486
|
-
!recipeRelation.startsWith("..") &&
|
|
487
|
-
!isAbsolute(recipeRelation)
|
|
488
|
-
? dirname(packagedRecipeRoot)
|
|
489
|
-
: undefined;
|
|
490
501
|
const argSpec = Schema.parseToolArgDeclarationList(startParams.args ?? []);
|
|
491
502
|
if (argSpec.error) throw new Error(argSpec.error);
|
|
492
503
|
const declaredArgs = new Set(argSpec.args);
|
|
@@ -498,7 +509,6 @@ export function startRun(
|
|
|
498
509
|
{
|
|
499
510
|
...argSpec.defaults,
|
|
500
511
|
...(startParams.defaults || {}),
|
|
501
|
-
...(packagedRepo ? { repo: packagedRepo } : {}),
|
|
502
512
|
...(startParams.values || {}),
|
|
503
513
|
run_id: run,
|
|
504
514
|
state_dir: stateDir,
|
|
@@ -546,7 +556,20 @@ export function startRun(
|
|
|
546
556
|
startParams.actor_context !== "off";
|
|
547
557
|
const recipeContextRecords =
|
|
548
558
|
recipeFile && includeActorRecipeContext
|
|
549
|
-
? RecipesReferences.buildRecipeContextRecords(
|
|
559
|
+
? RecipesReferences.buildRecipeContextRecords(
|
|
560
|
+
recipeFile,
|
|
561
|
+
options.skillContext,
|
|
562
|
+
).map((record, index) =>
|
|
563
|
+
index === 0 &&
|
|
564
|
+
startParams.launch_source === "tool" &&
|
|
565
|
+
record.source_kind === "explicit_file_recipe"
|
|
566
|
+
? {
|
|
567
|
+
...record,
|
|
568
|
+
logical_reference: record.name,
|
|
569
|
+
source_kind: "user_registry_capability" as const,
|
|
570
|
+
}
|
|
571
|
+
: record,
|
|
572
|
+
)
|
|
550
573
|
: undefined;
|
|
551
574
|
if (
|
|
552
575
|
recipeFile &&
|
|
@@ -4,13 +4,14 @@
|
|
|
4
4
|
* Owns automatic-review lifecycle wiring without owning review decisions or filesystem transactions.
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
import {
|
|
7
|
+
import { fileURLToPath } from "node:url";
|
|
8
8
|
|
|
9
9
|
import * as AsyncRuns from "./async-runs.ts";
|
|
10
10
|
import * as DraftSleep from "./draft-sleep.ts";
|
|
11
11
|
import * as ModelContext from "./model-context.ts";
|
|
12
12
|
import * as Paths from "./paths.ts";
|
|
13
13
|
import type * as Pi from "./pi.ts";
|
|
14
|
+
import * as RecipesReferences from "./recipes-references.ts";
|
|
14
15
|
import * as ReviewControl from "./review-control.ts";
|
|
15
16
|
import * as ToolReviewScheduler from "./tool-review-scheduler.ts";
|
|
16
17
|
|
|
@@ -27,6 +28,16 @@ export interface AutomaticReviewRuntimeDeps {
|
|
|
27
28
|
getThinkingLevel(): unknown;
|
|
28
29
|
}
|
|
29
30
|
|
|
31
|
+
export const PACKAGE_RECIPE_MEMORY_CONTEXT =
|
|
32
|
+
RecipesReferences.createActiveSkillRecipeContext([
|
|
33
|
+
{
|
|
34
|
+
name: "recipe-memory",
|
|
35
|
+
filePath: fileURLToPath(
|
|
36
|
+
new URL("../skills/recipe-memory/SKILL.md", import.meta.url),
|
|
37
|
+
),
|
|
38
|
+
},
|
|
39
|
+
]);
|
|
40
|
+
|
|
30
41
|
export function createAutomaticReviewRuntime(
|
|
31
42
|
deps: AutomaticReviewRuntimeDeps,
|
|
32
43
|
): AutomaticReviewRuntime {
|
|
@@ -88,7 +99,7 @@ export function createAutomaticReviewRuntime(
|
|
|
88
99
|
}
|
|
89
100
|
return AsyncRuns.startRun(
|
|
90
101
|
{
|
|
91
|
-
file:
|
|
102
|
+
file: "recipe-memory/draft-review",
|
|
92
103
|
launch_source: "tool",
|
|
93
104
|
notification_policy: "silent",
|
|
94
105
|
ownerId: deps.getRunOwnerId(ctx),
|
|
@@ -97,6 +108,7 @@ export function createAutomaticReviewRuntime(
|
|
|
97
108
|
values: { input_path: batch.reviewerInputPath },
|
|
98
109
|
},
|
|
99
110
|
ctx.cwd,
|
|
111
|
+
{ skillContext: PACKAGE_RECIPE_MEMORY_CONTEXT },
|
|
100
112
|
);
|
|
101
113
|
},
|
|
102
114
|
process: (state) =>
|
|
@@ -113,7 +125,7 @@ export function createAutomaticReviewRuntime(
|
|
|
113
125
|
}
|
|
114
126
|
return AsyncRuns.startRun(
|
|
115
127
|
{
|
|
116
|
-
file:
|
|
128
|
+
file: "recipe-memory/tool-review",
|
|
117
129
|
launch_source: "tool",
|
|
118
130
|
notification_policy: "silent",
|
|
119
131
|
ownerId: deps.getRunOwnerId(ctx),
|
|
@@ -122,6 +134,7 @@ export function createAutomaticReviewRuntime(
|
|
|
122
134
|
values: { input_path: batch.reviewerInputPath },
|
|
123
135
|
},
|
|
124
136
|
ctx.cwd,
|
|
137
|
+
{ skillContext: PACKAGE_RECIPE_MEMORY_CONTEXT },
|
|
125
138
|
);
|
|
126
139
|
},
|
|
127
140
|
process: (state) =>
|
package/lib/draft-sleep.ts
CHANGED
|
@@ -96,7 +96,6 @@ function readState(path: string): DraftSleepState | undefined {
|
|
|
96
96
|
function defaultActiveTools(recipeRoot: string): DraftReviewActiveTool[] {
|
|
97
97
|
const discovered = RecipesDiscovery.discoverRecipeSources([
|
|
98
98
|
{ root: recipeRoot, defaultTool: true, mutableUsage: true },
|
|
99
|
-
{ root: Paths.getPackagedRecipeRoot() },
|
|
100
99
|
]);
|
|
101
100
|
return [...discovered.active.values()]
|
|
102
101
|
.filter((entry) => existsSync(entry.path))
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pi actor extension runtime coordinator.
|
|
3
|
+
* Zones: extension session lifecycle, host tool adaptation, runtime service composition
|
|
4
|
+
* Owns low-level Pi lifecycle effects and tool wrapping without owning event registration.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import * as AutomaticReviewRuntime from "./automatic-review-runtime.ts";
|
|
8
|
+
import * as CommandTemplates from "./command-templates.ts";
|
|
9
|
+
import * as Paths from "./paths.ts";
|
|
10
|
+
import * as Pi from "./pi.ts";
|
|
11
|
+
import * as Prompts from "./prompts.ts";
|
|
12
|
+
import * as RecipesReferences from "./recipes-references.ts";
|
|
13
|
+
import * as RunUiRuntime from "./run-ui-runtime.ts";
|
|
14
|
+
import * as Runtime from "./runtime.ts";
|
|
15
|
+
import * as Temp from "./temp.ts";
|
|
16
|
+
import * as Tools from "./tools.ts";
|
|
17
|
+
import * as ToolsResponse from "./tools-response.ts";
|
|
18
|
+
|
|
19
|
+
export interface ActorExtensionRuntime {
|
|
20
|
+
beforeAgentStart(
|
|
21
|
+
systemPrompt: string,
|
|
22
|
+
skills: RecipesReferences.ActiveSkillRecipeSource[],
|
|
23
|
+
ctx: Pi.ExtensionContext,
|
|
24
|
+
): { systemPrompt: string };
|
|
25
|
+
discoverResources(metaUrl: string): { skillPaths: string[] } | undefined;
|
|
26
|
+
getRunOwnerId(ctx: Pi.ExtensionContext): string;
|
|
27
|
+
onAgentEnd(ctx: Pi.ExtensionContext): void;
|
|
28
|
+
onSessionShutdown(reason: string, ctx: Pi.ExtensionContext): void;
|
|
29
|
+
onSessionStart(ctx: Pi.ExtensionContext): Promise<void>;
|
|
30
|
+
registerCoreTools(): void;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export function createActorExtensionRuntime(
|
|
34
|
+
pi: Pi.ExtensionAPI,
|
|
35
|
+
): ActorExtensionRuntime {
|
|
36
|
+
let activeRunContext: Pi.ExtensionContext | undefined;
|
|
37
|
+
const skillContextsBySession = new Map<
|
|
38
|
+
string,
|
|
39
|
+
RecipesReferences.ActiveSkillRecipeContext
|
|
40
|
+
>();
|
|
41
|
+
const getRunOwnerId = Pi.getSessionId;
|
|
42
|
+
const getSkillContext = (ctx: Pi.ExtensionContext) =>
|
|
43
|
+
skillContextsBySession.get(getRunOwnerId(ctx)) ??
|
|
44
|
+
RecipesReferences.EMPTY_ACTIVE_SKILL_RECIPE_CONTEXT;
|
|
45
|
+
const automaticReview = AutomaticReviewRuntime.createAutomaticReviewRuntime({
|
|
46
|
+
getActiveContext: () => activeRunContext,
|
|
47
|
+
getRunOwnerId,
|
|
48
|
+
getThinkingLevel: () => pi.getThinkingLevel(),
|
|
49
|
+
});
|
|
50
|
+
const runUiRuntime = RunUiRuntime.createRunUiRuntime({
|
|
51
|
+
getActiveContext: () => activeRunContext,
|
|
52
|
+
getRunOwnerId,
|
|
53
|
+
onRunEvent: automaticReview.schedule,
|
|
54
|
+
pi,
|
|
55
|
+
});
|
|
56
|
+
const actorToolDefinitions = new Map<string, Tools.ActorToolDefinition>();
|
|
57
|
+
const withCurrentThinkingContext = <T extends Tools.ActorToolDefinition>(
|
|
58
|
+
definition: T,
|
|
59
|
+
): T => {
|
|
60
|
+
if (typeof definition.execute !== "function") return definition;
|
|
61
|
+
const execute = definition.execute as (...args: unknown[]) => unknown;
|
|
62
|
+
return {
|
|
63
|
+
...definition,
|
|
64
|
+
execute: async (...args: unknown[]) => {
|
|
65
|
+
const nextArgs = [...args];
|
|
66
|
+
const ctx = nextArgs[4];
|
|
67
|
+
if (ctx && typeof ctx === "object") {
|
|
68
|
+
nextArgs[4] = {
|
|
69
|
+
...(ctx as Record<string, unknown>),
|
|
70
|
+
activeSkillRecipeContext: getSkillContext(
|
|
71
|
+
ctx as Pi.ExtensionContext,
|
|
72
|
+
),
|
|
73
|
+
getThinkingLevel: () => pi.getThinkingLevel(),
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
try {
|
|
77
|
+
return ToolsResponse.spaceToolResult(await execute(...nextArgs));
|
|
78
|
+
} catch (error) {
|
|
79
|
+
throw ToolsResponse.spaceToolError(error);
|
|
80
|
+
}
|
|
81
|
+
},
|
|
82
|
+
} as T;
|
|
83
|
+
};
|
|
84
|
+
const runtime = Runtime.createAutoToolsRuntime({
|
|
85
|
+
configPath: Paths.EXTENSION_RUNTIME_PATHS.configPath,
|
|
86
|
+
exec: CommandTemplates.execCommandTemplate,
|
|
87
|
+
getActiveTools: () => pi.getActiveTools(),
|
|
88
|
+
registerTool: (definition) => {
|
|
89
|
+
const wrapped = withCurrentThinkingContext(definition);
|
|
90
|
+
actorToolDefinitions.set(wrapped.name, wrapped);
|
|
91
|
+
pi.registerTool(wrapped);
|
|
92
|
+
},
|
|
93
|
+
reservedToolNames: Tools.RESERVED_TOOL_NAMES,
|
|
94
|
+
setActiveTools: (toolNames) => pi.setActiveTools(toolNames),
|
|
95
|
+
});
|
|
96
|
+
const recipeReload = Runtime.createRecipeToolReloadWatcher(runtime);
|
|
97
|
+
return {
|
|
98
|
+
beforeAgentStart(systemPrompt, skills, ctx) {
|
|
99
|
+
skillContextsBySession.set(
|
|
100
|
+
getRunOwnerId(ctx),
|
|
101
|
+
RecipesReferences.createActiveSkillRecipeContext(skills),
|
|
102
|
+
);
|
|
103
|
+
return {
|
|
104
|
+
systemPrompt: `${systemPrompt}\n\n${Prompts.ONBOARDING_SYSTEM_PROMPT}`,
|
|
105
|
+
};
|
|
106
|
+
},
|
|
107
|
+
discoverResources(metaUrl) {
|
|
108
|
+
const skillPaths = Paths.getExistingExtensionSkillPaths(metaUrl);
|
|
109
|
+
return skillPaths.length > 0 ? { skillPaths } : undefined;
|
|
110
|
+
},
|
|
111
|
+
getRunOwnerId,
|
|
112
|
+
onAgentEnd(ctx) {
|
|
113
|
+
if (activeRunContext === ctx) automaticReview.schedule();
|
|
114
|
+
},
|
|
115
|
+
onSessionShutdown(reason, ctx) {
|
|
116
|
+
skillContextsBySession.delete(getRunOwnerId(ctx));
|
|
117
|
+
activeRunContext = undefined;
|
|
118
|
+
automaticReview.close();
|
|
119
|
+
recipeReload.close();
|
|
120
|
+
runUiRuntime.shutdown(reason, ctx);
|
|
121
|
+
},
|
|
122
|
+
async onSessionStart(ctx) {
|
|
123
|
+
skillContextsBySession.set(
|
|
124
|
+
getRunOwnerId(ctx),
|
|
125
|
+
RecipesReferences.EMPTY_ACTIVE_SKILL_RECIPE_CONTEXT,
|
|
126
|
+
);
|
|
127
|
+
ctx.ui.setWidget("zz-pi-actors-comms", undefined);
|
|
128
|
+
activeRunContext = ctx;
|
|
129
|
+
runUiRuntime.close();
|
|
130
|
+
automaticReview.close();
|
|
131
|
+
recipeReload.close();
|
|
132
|
+
await Temp.prepareExtensionTempDir(Paths.EXTENSION_RUNTIME_PATHS.tempDir);
|
|
133
|
+
if (activeRunContext !== ctx) return;
|
|
134
|
+
automaticReview.start(ctx);
|
|
135
|
+
runtime.loadTools(ctx);
|
|
136
|
+
runUiRuntime.start(ctx);
|
|
137
|
+
recipeReload.watch(ctx);
|
|
138
|
+
},
|
|
139
|
+
registerCoreTools() {
|
|
140
|
+
Pi.registerToolDefinitions(
|
|
141
|
+
pi,
|
|
142
|
+
Tools.createCoreActorToolDefinitions<Pi.ExtensionContext>({
|
|
143
|
+
configPath: Paths.EXTENSION_RUNTIME_PATHS.configPath,
|
|
144
|
+
getActiveTools: () => pi.getActiveTools(),
|
|
145
|
+
getRuntimeTool: (name) =>
|
|
146
|
+
Tools.resolveActiveRuntimeTool(
|
|
147
|
+
name,
|
|
148
|
+
runtime.getTools(),
|
|
149
|
+
(activeName) => actorToolDefinitions.get(activeName),
|
|
150
|
+
),
|
|
151
|
+
handleRuntimeControl: automaticReview.handleControl,
|
|
152
|
+
registryRuntime: runtime,
|
|
153
|
+
setActiveTools: (toolNames) => pi.setActiveTools(toolNames),
|
|
154
|
+
}).map(withCurrentThinkingContext),
|
|
155
|
+
);
|
|
156
|
+
},
|
|
157
|
+
};
|
|
158
|
+
}
|