@llblab/pi-kit 0.1.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 +35 -0
- package/BACKLOG.md +3 -0
- package/CHANGELOG.md +9 -0
- package/LICENSE +21 -0
- package/README.md +43 -0
- package/node_modules/@llblab/pi-actors/AGENTS.md +150 -0
- package/node_modules/@llblab/pi-actors/BACKLOG.md +6 -0
- package/node_modules/@llblab/pi-actors/CHANGELOG.md +865 -0
- package/node_modules/@llblab/pi-actors/README.md +231 -0
- package/node_modules/@llblab/pi-actors/banner.jpg +0 -0
- package/node_modules/@llblab/pi-actors/dist/fixtures/protocol/artifact-manifest.json +9 -0
- package/node_modules/@llblab/pi-actors/dist/fixtures/protocol/control-endpoint.json +6 -0
- package/node_modules/@llblab/pi-actors/dist/fixtures/protocol/control-record.json +9 -0
- package/node_modules/@llblab/pi-actors/dist/fixtures/protocol/recipe-summary.json +8 -0
- package/node_modules/@llblab/pi-actors/dist/fixtures/protocol/run-state.json +10 -0
- package/node_modules/@llblab/pi-actors/dist/fixtures/protocol/trace-event.json +9 -0
- package/node_modules/@llblab/pi-actors/dist/index.d.ts +7 -0
- package/node_modules/@llblab/pi-actors/dist/index.js +17 -0
- package/node_modules/@llblab/pi-actors/dist/lib/async-runs.d.ts +146 -0
- package/node_modules/@llblab/pi-actors/dist/lib/async-runs.js +800 -0
- package/node_modules/@llblab/pi-actors/dist/lib/automatic-review-runtime.d.ts +20 -0
- package/node_modules/@llblab/pi-actors/dist/lib/automatic-review-runtime.js +103 -0
- package/node_modules/@llblab/pi-actors/dist/lib/command-templates.d.ts +85 -0
- package/node_modules/@llblab/pi-actors/dist/lib/command-templates.js +804 -0
- package/node_modules/@llblab/pi-actors/dist/lib/config.d.ts +34 -0
- package/node_modules/@llblab/pi-actors/dist/lib/config.js +216 -0
- package/node_modules/@llblab/pi-actors/dist/lib/control-projection.d.ts +20 -0
- package/node_modules/@llblab/pi-actors/dist/lib/control-projection.js +66 -0
- package/node_modules/@llblab/pi-actors/dist/lib/control.d.ts +15 -0
- package/node_modules/@llblab/pi-actors/dist/lib/control.js +97 -0
- package/node_modules/@llblab/pi-actors/dist/lib/draft-consolidation-transaction.d.ts +65 -0
- package/node_modules/@llblab/pi-actors/dist/lib/draft-consolidation-transaction.js +610 -0
- package/node_modules/@llblab/pi-actors/dist/lib/draft-consolidation.d.ts +35 -0
- package/node_modules/@llblab/pi-actors/dist/lib/draft-consolidation.js +126 -0
- package/node_modules/@llblab/pi-actors/dist/lib/draft-review.d.ts +56 -0
- package/node_modules/@llblab/pi-actors/dist/lib/draft-review.js +254 -0
- package/node_modules/@llblab/pi-actors/dist/lib/draft-sleep.d.ts +65 -0
- package/node_modules/@llblab/pi-actors/dist/lib/draft-sleep.js +467 -0
- package/node_modules/@llblab/pi-actors/dist/lib/execution-output.d.ts +25 -0
- package/node_modules/@llblab/pi-actors/dist/lib/execution-output.js +88 -0
- package/node_modules/@llblab/pi-actors/dist/lib/execution-sessions.d.ts +17 -0
- package/node_modules/@llblab/pi-actors/dist/lib/execution-sessions.js +85 -0
- package/node_modules/@llblab/pi-actors/dist/lib/execution.d.ts +99 -0
- package/node_modules/@llblab/pi-actors/dist/lib/execution.js +725 -0
- package/node_modules/@llblab/pi-actors/dist/lib/extension-runtime.d.ts +21 -0
- package/node_modules/@llblab/pi-actors/dist/lib/extension-runtime.js +141 -0
- package/node_modules/@llblab/pi-actors/dist/lib/file-state.d.ts +18 -0
- package/node_modules/@llblab/pi-actors/dist/lib/file-state.js +310 -0
- package/node_modules/@llblab/pi-actors/dist/lib/identity.d.ts +9 -0
- package/node_modules/@llblab/pi-actors/dist/lib/identity.js +27 -0
- package/node_modules/@llblab/pi-actors/dist/lib/inspector-actions.d.ts +16 -0
- package/node_modules/@llblab/pi-actors/dist/lib/inspector-actions.js +57 -0
- package/node_modules/@llblab/pi-actors/dist/lib/inspector-command.d.ts +7 -0
- package/node_modules/@llblab/pi-actors/dist/lib/inspector-command.js +37 -0
- package/node_modules/@llblab/pi-actors/dist/lib/inspector-overlay.d.ts +100 -0
- package/node_modules/@llblab/pi-actors/dist/lib/inspector-overlay.js +824 -0
- package/node_modules/@llblab/pi-actors/dist/lib/inspector.d.ts +20 -0
- package/node_modules/@llblab/pi-actors/dist/lib/inspector.js +136 -0
- package/node_modules/@llblab/pi-actors/dist/lib/limits.d.ts +28 -0
- package/node_modules/@llblab/pi-actors/dist/lib/limits.js +28 -0
- package/node_modules/@llblab/pi-actors/dist/lib/model-context.d.ts +56 -0
- package/node_modules/@llblab/pi-actors/dist/lib/model-context.js +220 -0
- package/node_modules/@llblab/pi-actors/dist/lib/observability.d.ts +186 -0
- package/node_modules/@llblab/pi-actors/dist/lib/observability.js +951 -0
- package/node_modules/@llblab/pi-actors/dist/lib/paths.d.ts +27 -0
- package/node_modules/@llblab/pi-actors/dist/lib/paths.js +72 -0
- package/node_modules/@llblab/pi-actors/dist/lib/pi.d.ts +19 -0
- package/node_modules/@llblab/pi-actors/dist/lib/pi.js +21 -0
- package/node_modules/@llblab/pi-actors/dist/lib/preflight-diagnostics.d.ts +27 -0
- package/node_modules/@llblab/pi-actors/dist/lib/preflight-diagnostics.js +86 -0
- package/node_modules/@llblab/pi-actors/dist/lib/prompts.d.ts +24 -0
- package/node_modules/@llblab/pi-actors/dist/lib/prompts.js +49 -0
- package/node_modules/@llblab/pi-actors/dist/lib/recipe-control.d.ts +7 -0
- package/node_modules/@llblab/pi-actors/dist/lib/recipe-control.js +43 -0
- package/node_modules/@llblab/pi-actors/dist/lib/recipes-context.d.ts +36 -0
- package/node_modules/@llblab/pi-actors/dist/lib/recipes-context.js +197 -0
- package/node_modules/@llblab/pi-actors/dist/lib/recipes-discovery.d.ts +77 -0
- package/node_modules/@llblab/pi-actors/dist/lib/recipes-discovery.js +783 -0
- package/node_modules/@llblab/pi-actors/dist/lib/recipes-references.d.ts +113 -0
- package/node_modules/@llblab/pi-actors/dist/lib/recipes-references.js +1108 -0
- package/node_modules/@llblab/pi-actors/dist/lib/recipes-usage.d.ts +21 -0
- package/node_modules/@llblab/pi-actors/dist/lib/recipes-usage.js +494 -0
- package/node_modules/@llblab/pi-actors/dist/lib/registry.d.ts +67 -0
- package/node_modules/@llblab/pi-actors/dist/lib/registry.js +504 -0
- package/node_modules/@llblab/pi-actors/dist/lib/review-control.d.ts +14 -0
- package/node_modules/@llblab/pi-actors/dist/lib/review-control.js +110 -0
- package/node_modules/@llblab/pi-actors/dist/lib/review-diagnostics.d.ts +11 -0
- package/node_modules/@llblab/pi-actors/dist/lib/review-diagnostics.js +148 -0
- package/node_modules/@llblab/pi-actors/dist/lib/review-projection.d.ts +14 -0
- package/node_modules/@llblab/pi-actors/dist/lib/review-projection.js +166 -0
- package/node_modules/@llblab/pi-actors/dist/lib/run-evidence-policy.d.ts +95 -0
- package/node_modules/@llblab/pi-actors/dist/lib/run-evidence-policy.js +177 -0
- package/node_modules/@llblab/pi-actors/dist/lib/run-ui-runtime.d.ts +18 -0
- package/node_modules/@llblab/pi-actors/dist/lib/run-ui-runtime.js +125 -0
- package/node_modules/@llblab/pi-actors/dist/lib/runs-artifacts.d.ts +21 -0
- package/node_modules/@llblab/pi-actors/dist/lib/runs-artifacts.js +68 -0
- package/node_modules/@llblab/pi-actors/dist/lib/runs-control-delivery.d.ts +28 -0
- package/node_modules/@llblab/pi-actors/dist/lib/runs-control-delivery.js +150 -0
- package/node_modules/@llblab/pi-actors/dist/lib/runs-control.d.ts +21 -0
- package/node_modules/@llblab/pi-actors/dist/lib/runs-control.js +89 -0
- package/node_modules/@llblab/pi-actors/dist/lib/runs-controls.d.ts +39 -0
- package/node_modules/@llblab/pi-actors/dist/lib/runs-controls.js +283 -0
- package/node_modules/@llblab/pi-actors/dist/lib/runs-identity.d.ts +5 -0
- package/node_modules/@llblab/pi-actors/dist/lib/runs-identity.js +11 -0
- package/node_modules/@llblab/pi-actors/dist/lib/runs-index.d.ts +27 -0
- package/node_modules/@llblab/pi-actors/dist/lib/runs-index.js +142 -0
- package/node_modules/@llblab/pi-actors/dist/lib/runs-ownership.d.ts +7 -0
- package/node_modules/@llblab/pi-actors/dist/lib/runs-ownership.js +96 -0
- package/node_modules/@llblab/pi-actors/dist/lib/runs-parent-teardown.d.ts +51 -0
- package/node_modules/@llblab/pi-actors/dist/lib/runs-parent-teardown.js +172 -0
- package/node_modules/@llblab/pi-actors/dist/lib/runs-process.d.ts +22 -0
- package/node_modules/@llblab/pi-actors/dist/lib/runs-process.js +125 -0
- package/node_modules/@llblab/pi-actors/dist/lib/runs-retention.d.ts +18 -0
- package/node_modules/@llblab/pi-actors/dist/lib/runs-retention.js +108 -0
- package/node_modules/@llblab/pi-actors/dist/lib/runs-start.d.ts +12 -0
- package/node_modules/@llblab/pi-actors/dist/lib/runs-start.js +68 -0
- package/node_modules/@llblab/pi-actors/dist/lib/runs-status.d.ts +10 -0
- package/node_modules/@llblab/pi-actors/dist/lib/runs-status.js +68 -0
- package/node_modules/@llblab/pi-actors/dist/lib/runs-trace.d.ts +48 -0
- package/node_modules/@llblab/pi-actors/dist/lib/runs-trace.js +491 -0
- package/node_modules/@llblab/pi-actors/dist/lib/runtime-identity.d.ts +7 -0
- package/node_modules/@llblab/pi-actors/dist/lib/runtime-identity.js +35 -0
- package/node_modules/@llblab/pi-actors/dist/lib/runtime-triage.d.ts +29 -0
- package/node_modules/@llblab/pi-actors/dist/lib/runtime-triage.js +60 -0
- package/node_modules/@llblab/pi-actors/dist/lib/runtime.d.ts +69 -0
- package/node_modules/@llblab/pi-actors/dist/lib/runtime.js +339 -0
- package/node_modules/@llblab/pi-actors/dist/lib/schema.d.ts +60 -0
- package/node_modules/@llblab/pi-actors/dist/lib/schema.js +428 -0
- package/node_modules/@llblab/pi-actors/dist/lib/session-evidence.d.ts +45 -0
- package/node_modules/@llblab/pi-actors/dist/lib/session-evidence.js +204 -0
- package/node_modules/@llblab/pi-actors/dist/lib/state-readers.d.ts +21 -0
- package/node_modules/@llblab/pi-actors/dist/lib/state-readers.js +74 -0
- package/node_modules/@llblab/pi-actors/dist/lib/temp.d.ts +10 -0
- package/node_modules/@llblab/pi-actors/dist/lib/temp.js +90 -0
- package/node_modules/@llblab/pi-actors/dist/lib/tool-review-lineage-transaction.d.ts +27 -0
- package/node_modules/@llblab/pi-actors/dist/lib/tool-review-lineage-transaction.js +597 -0
- package/node_modules/@llblab/pi-actors/dist/lib/tool-review-lineage.d.ts +24 -0
- package/node_modules/@llblab/pi-actors/dist/lib/tool-review-lineage.js +98 -0
- package/node_modules/@llblab/pi-actors/dist/lib/tool-review-scheduler.d.ts +80 -0
- package/node_modules/@llblab/pi-actors/dist/lib/tool-review-scheduler.js +494 -0
- package/node_modules/@llblab/pi-actors/dist/lib/tool-review-transaction.d.ts +50 -0
- package/node_modules/@llblab/pi-actors/dist/lib/tool-review-transaction.js +362 -0
- package/node_modules/@llblab/pi-actors/dist/lib/tool-review.d.ts +56 -0
- package/node_modules/@llblab/pi-actors/dist/lib/tool-review.js +197 -0
- package/node_modules/@llblab/pi-actors/dist/lib/tools-access.d.ts +19 -0
- package/node_modules/@llblab/pi-actors/dist/lib/tools-access.js +44 -0
- package/node_modules/@llblab/pi-actors/dist/lib/tools-inspect.d.ts +15 -0
- package/node_modules/@llblab/pi-actors/dist/lib/tools-inspect.js +532 -0
- package/node_modules/@llblab/pi-actors/dist/lib/tools-local.d.ts +17 -0
- package/node_modules/@llblab/pi-actors/dist/lib/tools-local.js +191 -0
- package/node_modules/@llblab/pi-actors/dist/lib/tools-message.d.ts +9 -0
- package/node_modules/@llblab/pi-actors/dist/lib/tools-message.js +139 -0
- package/node_modules/@llblab/pi-actors/dist/lib/tools-register.d.ts +18 -0
- package/node_modules/@llblab/pi-actors/dist/lib/tools-register.js +41 -0
- package/node_modules/@llblab/pi-actors/dist/lib/tools-response.d.ts +20 -0
- package/node_modules/@llblab/pi-actors/dist/lib/tools-response.js +243 -0
- package/node_modules/@llblab/pi-actors/dist/lib/tools-spawn.d.ts +15 -0
- package/node_modules/@llblab/pi-actors/dist/lib/tools-spawn.js +133 -0
- package/node_modules/@llblab/pi-actors/dist/lib/tools.d.ts +28 -0
- package/node_modules/@llblab/pi-actors/dist/lib/tools.js +49 -0
- package/node_modules/@llblab/pi-actors/dist/lib/trace-projection.d.ts +22 -0
- package/node_modules/@llblab/pi-actors/dist/lib/trace-projection.js +231 -0
- package/node_modules/@llblab/pi-actors/dist/pi-actors/index.js +1 -0
- package/node_modules/@llblab/pi-actors/dist/scripts/async-runner.mjs +555 -0
- package/node_modules/@llblab/pi-actors/dist/scripts/build-dist.mjs +60 -0
- package/node_modules/@llblab/pi-actors/dist/scripts/conformance.mjs +63 -0
- package/node_modules/@llblab/pi-actors/dist/skills/actors/SKILL.md +126 -0
- package/node_modules/@llblab/pi-actors/dist/skills/actors/recipes/command-validate.json +13 -0
- package/node_modules/@llblab/pi-actors/dist/skills/actors/recipes/jsonl-tail.json +10 -0
- package/node_modules/@llblab/pi-actors/dist/skills/actors/recipes/recipe-validate.json +11 -0
- package/node_modules/@llblab/pi-actors/dist/skills/actors/recipes/resource-locker-snapshot.json +11 -0
- package/node_modules/@llblab/pi-actors/dist/skills/actors/recipes/resource-locker.json +25 -0
- package/node_modules/@llblab/pi-actors/dist/skills/actors/recipes/run-ops-snapshot.json +15 -0
- package/node_modules/@llblab/pi-actors/dist/skills/actors/recipes/run-state-files.json +13 -0
- package/node_modules/@llblab/pi-actors/dist/skills/actors/recipes/run-summary.json +9 -0
- package/node_modules/@llblab/pi-actors/dist/skills/actors/references/diagnostics.md +44 -0
- package/node_modules/@llblab/pi-actors/dist/skills/actors/references/persistent-tools.md +76 -0
- package/node_modules/@llblab/pi-actors/dist/skills/actors/references/recipes.md +51 -0
- package/node_modules/@llblab/pi-actors/dist/skills/actors/references/runs.md +41 -0
- package/node_modules/@llblab/pi-actors/dist/skills/actors/scripts/resource-locker.mjs +425 -0
- package/node_modules/@llblab/pi-actors/dist/skills/actors/scripts/run-utils.mjs +164 -0
- package/node_modules/@llblab/pi-actors/dist/skills/actors/scripts/validate-recipe.mjs +370 -0
- package/node_modules/@llblab/pi-actors/dist/skills/artifacts/SKILL.md +33 -0
- package/node_modules/@llblab/pi-actors/dist/skills/artifacts/recipes/bundle.json +77 -0
- package/node_modules/@llblab/pi-actors/dist/skills/artifacts/recipes/file-write.json +14 -0
- package/node_modules/@llblab/pi-actors/dist/skills/artifacts/recipes/manifest.json +14 -0
- package/node_modules/@llblab/pi-actors/dist/skills/artifacts/recipes/report.json +39 -0
- package/node_modules/@llblab/pi-actors/dist/skills/artifacts/recipes/write.json +53 -0
- package/node_modules/@llblab/pi-actors/dist/skills/artifacts/scripts/artifact-utils.mjs +63 -0
- package/node_modules/@llblab/pi-actors/dist/skills/music-player/SKILL.md +57 -0
- package/node_modules/@llblab/pi-actors/dist/skills/music-player/genapps/music-player.mjs +360 -0
- package/node_modules/@llblab/pi-actors/dist/skills/music-player/recipes/playback.json +29 -0
- package/node_modules/@llblab/pi-actors/dist/skills/music-player/scripts/playback-client.mjs +143 -0
- package/node_modules/@llblab/pi-actors/dist/skills/music-player/scripts/playback.mjs +1446 -0
- package/node_modules/@llblab/pi-actors/dist/skills/project-work/SKILL.md +37 -0
- package/node_modules/@llblab/pi-actors/dist/skills/project-work/recipes/changelog-head.json +11 -0
- package/node_modules/@llblab/pi-actors/dist/skills/project-work/recipes/changelog-section.json +11 -0
- package/node_modules/@llblab/pi-actors/dist/skills/project-work/recipes/docs-maintenance.json +66 -0
- package/node_modules/@llblab/pi-actors/dist/skills/project-work/recipes/git-log.json +11 -0
- package/node_modules/@llblab/pi-actors/dist/skills/project-work/recipes/git-status.json +9 -0
- package/node_modules/@llblab/pi-actors/dist/skills/project-work/recipes/markdown-index.json +14 -0
- package/node_modules/@llblab/pi-actors/dist/skills/project-work/recipes/package-summary.json +9 -0
- package/node_modules/@llblab/pi-actors/dist/skills/project-work/recipes/release-readiness.json +115 -0
- package/node_modules/@llblab/pi-actors/dist/skills/project-work/recipes/release-summary.json +74 -0
- package/node_modules/@llblab/pi-actors/dist/skills/project-work/recipes/repo-health.json +75 -0
- package/node_modules/@llblab/pi-actors/dist/skills/project-work/recipes/run-ops.json +56 -0
- package/node_modules/@llblab/pi-actors/dist/skills/project-work/recipes/skill-summary.json +11 -0
- package/node_modules/@llblab/pi-actors/dist/skills/project-work/scripts/project-utils.mjs +89 -0
- package/node_modules/@llblab/pi-actors/dist/skills/recipe-memory/SKILL.md +36 -0
- package/node_modules/@llblab/pi-actors/dist/skills/recipe-memory/recipes/draft-review.json +14 -0
- package/node_modules/@llblab/pi-actors/dist/skills/recipe-memory/recipes/tool-review.json +14 -0
- package/node_modules/@llblab/pi-actors/dist/skills/swarm/SKILL.md +84 -0
- package/node_modules/@llblab/pi-actors/dist/skills/swarm/recipes/architect.json +82 -0
- package/node_modules/@llblab/pi-actors/dist/skills/swarm/recipes/checkpoint-continuation.json +51 -0
- package/node_modules/@llblab/pi-actors/dist/skills/swarm/recipes/development-tasking.json +67 -0
- package/node_modules/@llblab/pi-actors/dist/skills/swarm/recipes/lens-review.json +63 -0
- package/node_modules/@llblab/pi-actors/dist/skills/swarm/recipes/quorum-review.json +65 -0
- package/node_modules/@llblab/pi-actors/dist/skills/swarm/recipes/research-synthesis.json +81 -0
- package/node_modules/@llblab/pi-actors/dist/skills/swarm/recipes/review-readiness.json +59 -0
- package/node_modules/@llblab/pi-actors/dist/skills/swarm/recipes/subagent-artifact.json +21 -0
- package/node_modules/@llblab/pi-actors/dist/skills/swarm/recipes/subagent-checkpoint.json +21 -0
- package/node_modules/@llblab/pi-actors/dist/skills/swarm/recipes/subagent-conflict-report.json +19 -0
- package/node_modules/@llblab/pi-actors/dist/skills/swarm/recipes/subagent-contradiction-map.json +20 -0
- package/node_modules/@llblab/pi-actors/dist/skills/swarm/recipes/subagent-critic.json +22 -0
- package/node_modules/@llblab/pi-actors/dist/skills/swarm/recipes/subagent-evidence-map.json +20 -0
- package/node_modules/@llblab/pi-actors/dist/skills/swarm/recipes/subagent-followup.json +21 -0
- package/node_modules/@llblab/pi-actors/dist/skills/swarm/recipes/subagent-judge.json +22 -0
- package/node_modules/@llblab/pi-actors/dist/skills/swarm/recipes/subagent-merge.json +24 -0
- package/node_modules/@llblab/pi-actors/dist/skills/swarm/recipes/subagent-normalize.json +20 -0
- package/node_modules/@llblab/pi-actors/dist/skills/swarm/recipes/subagent-plan.json +20 -0
- package/node_modules/@llblab/pi-actors/dist/skills/swarm/recipes/subagent-preflight.json +18 -0
- package/node_modules/@llblab/pi-actors/dist/skills/swarm/recipes/subagent-prompt.json +16 -0
- package/node_modules/@llblab/pi-actors/dist/skills/swarm/recipes/subagent-prompts.json +39 -0
- package/node_modules/@llblab/pi-actors/dist/skills/swarm/recipes/subagent-quorum.json +31 -0
- package/node_modules/@llblab/pi-actors/dist/skills/swarm/recipes/subagent-review-coordinator.json +170 -0
- package/node_modules/@llblab/pi-actors/dist/skills/swarm/recipes/subagent-review.json +26 -0
- package/node_modules/@llblab/pi-actors/dist/skills/swarm/recipes/subagent-task-card.json +22 -0
- package/node_modules/@llblab/pi-actors/dist/skills/swarm/recipes/subagent-tools.json +15 -0
- package/node_modules/@llblab/pi-actors/dist/skills/swarm/recipes/subagent-verify.json +23 -0
- package/node_modules/@llblab/pi-actors/dist/skills/swarm/references/development-swarm.md +189 -0
- package/node_modules/@llblab/pi-actors/dist/skills/swarm/references/review-swarms.md +115 -0
- package/node_modules/@llblab/pi-actors/docs/README.md +20 -0
- package/node_modules/@llblab/pi-actors/docs/actor-inspector.md +50 -0
- package/node_modules/@llblab/pi-actors/docs/async-runs.md +141 -0
- package/node_modules/@llblab/pi-actors/docs/command-templates.md +321 -0
- package/node_modules/@llblab/pi-actors/docs/recipe-library.md +89 -0
- package/node_modules/@llblab/pi-actors/docs/releasing.md +28 -0
- package/node_modules/@llblab/pi-actors/docs/template-recipes.md +175 -0
- package/node_modules/@llblab/pi-actors/docs/tool-registry.md +90 -0
- package/node_modules/@llblab/pi-actors/fixtures/protocol/artifact-manifest.json +9 -0
- package/node_modules/@llblab/pi-actors/fixtures/protocol/control-endpoint.json +6 -0
- package/node_modules/@llblab/pi-actors/fixtures/protocol/control-record.json +9 -0
- package/node_modules/@llblab/pi-actors/fixtures/protocol/recipe-summary.json +8 -0
- package/node_modules/@llblab/pi-actors/fixtures/protocol/run-state.json +10 -0
- package/node_modules/@llblab/pi-actors/fixtures/protocol/trace-event.json +9 -0
- package/node_modules/@llblab/pi-actors/index.ts +30 -0
- package/node_modules/@llblab/pi-actors/lib/async-runs.ts +1245 -0
- package/node_modules/@llblab/pi-actors/lib/automatic-review-runtime.ts +148 -0
- package/node_modules/@llblab/pi-actors/lib/command-templates.ts +1116 -0
- package/node_modules/@llblab/pi-actors/lib/config.ts +261 -0
- package/node_modules/@llblab/pi-actors/lib/control-projection.ts +105 -0
- package/node_modules/@llblab/pi-actors/lib/control.ts +117 -0
- package/node_modules/@llblab/pi-actors/lib/draft-consolidation-transaction.ts +821 -0
- package/node_modules/@llblab/pi-actors/lib/draft-consolidation.ts +181 -0
- package/node_modules/@llblab/pi-actors/lib/draft-review.ts +325 -0
- package/node_modules/@llblab/pi-actors/lib/draft-sleep.ts +575 -0
- package/node_modules/@llblab/pi-actors/lib/execution-output.ts +123 -0
- package/node_modules/@llblab/pi-actors/lib/execution-sessions.ts +111 -0
- package/node_modules/@llblab/pi-actors/lib/execution.ts +1153 -0
- package/node_modules/@llblab/pi-actors/lib/extension-runtime.ts +181 -0
- package/node_modules/@llblab/pi-actors/lib/file-state.ts +306 -0
- package/node_modules/@llblab/pi-actors/lib/identity.ts +29 -0
- package/node_modules/@llblab/pi-actors/lib/inspector-actions.ts +79 -0
- package/node_modules/@llblab/pi-actors/lib/inspector-command.ts +54 -0
- package/node_modules/@llblab/pi-actors/lib/inspector-overlay.ts +901 -0
- package/node_modules/@llblab/pi-actors/lib/inspector.ts +204 -0
- package/node_modules/@llblab/pi-actors/lib/limits.ts +29 -0
- package/node_modules/@llblab/pi-actors/lib/model-context.ts +359 -0
- package/node_modules/@llblab/pi-actors/lib/observability.ts +1337 -0
- package/node_modules/@llblab/pi-actors/lib/paths.ts +111 -0
- package/node_modules/@llblab/pi-actors/lib/pi.ts +47 -0
- package/node_modules/@llblab/pi-actors/lib/preflight-diagnostics.ts +132 -0
- package/node_modules/@llblab/pi-actors/lib/prompts.ts +69 -0
- package/node_modules/@llblab/pi-actors/lib/recipe-control.ts +52 -0
- package/node_modules/@llblab/pi-actors/lib/recipes-context.ts +268 -0
- package/node_modules/@llblab/pi-actors/lib/recipes-discovery.ts +1060 -0
- package/node_modules/@llblab/pi-actors/lib/recipes-references.ts +1598 -0
- package/node_modules/@llblab/pi-actors/lib/recipes-usage.ts +638 -0
- package/node_modules/@llblab/pi-actors/lib/registry.ts +806 -0
- package/node_modules/@llblab/pi-actors/lib/review-control.ts +136 -0
- package/node_modules/@llblab/pi-actors/lib/review-diagnostics.ts +164 -0
- package/node_modules/@llblab/pi-actors/lib/review-projection.ts +196 -0
- package/node_modules/@llblab/pi-actors/lib/run-evidence-policy.ts +242 -0
- package/node_modules/@llblab/pi-actors/lib/run-ui-runtime.ts +155 -0
- package/node_modules/@llblab/pi-actors/lib/runs-artifacts.ts +96 -0
- package/node_modules/@llblab/pi-actors/lib/runs-control-delivery.ts +209 -0
- package/node_modules/@llblab/pi-actors/lib/runs-control.ts +148 -0
- package/node_modules/@llblab/pi-actors/lib/runs-controls.ts +282 -0
- package/node_modules/@llblab/pi-actors/lib/runs-identity.ts +14 -0
- package/node_modules/@llblab/pi-actors/lib/runs-index.ts +192 -0
- package/node_modules/@llblab/pi-actors/lib/runs-ownership.ts +136 -0
- package/node_modules/@llblab/pi-actors/lib/runs-parent-teardown.ts +257 -0
- package/node_modules/@llblab/pi-actors/lib/runs-process.ts +174 -0
- package/node_modules/@llblab/pi-actors/lib/runs-retention.ts +140 -0
- package/node_modules/@llblab/pi-actors/lib/runs-start.ts +113 -0
- package/node_modules/@llblab/pi-actors/lib/runs-status.ts +101 -0
- package/node_modules/@llblab/pi-actors/lib/runs-trace.ts +611 -0
- package/node_modules/@llblab/pi-actors/lib/runtime-identity.ts +39 -0
- package/node_modules/@llblab/pi-actors/lib/runtime-triage.ts +106 -0
- package/node_modules/@llblab/pi-actors/lib/runtime.ts +430 -0
- package/node_modules/@llblab/pi-actors/lib/schema.ts +525 -0
- package/node_modules/@llblab/pi-actors/lib/session-evidence.ts +302 -0
- package/node_modules/@llblab/pi-actors/lib/state-readers.ts +93 -0
- package/node_modules/@llblab/pi-actors/lib/temp.ts +99 -0
- package/node_modules/@llblab/pi-actors/lib/tool-review-lineage-transaction.ts +881 -0
- package/node_modules/@llblab/pi-actors/lib/tool-review-lineage.ts +145 -0
- package/node_modules/@llblab/pi-actors/lib/tool-review-scheduler.ts +635 -0
- package/node_modules/@llblab/pi-actors/lib/tool-review-transaction.ts +563 -0
- package/node_modules/@llblab/pi-actors/lib/tool-review.ts +270 -0
- package/node_modules/@llblab/pi-actors/lib/tools-access.ts +68 -0
- package/node_modules/@llblab/pi-actors/lib/tools-inspect.ts +673 -0
- package/node_modules/@llblab/pi-actors/lib/tools-local.ts +303 -0
- package/node_modules/@llblab/pi-actors/lib/tools-message.ts +176 -0
- package/node_modules/@llblab/pi-actors/lib/tools-register.ts +63 -0
- package/node_modules/@llblab/pi-actors/lib/tools-response.ts +285 -0
- package/node_modules/@llblab/pi-actors/lib/tools-spawn.ts +212 -0
- package/node_modules/@llblab/pi-actors/lib/tools.ts +88 -0
- package/node_modules/@llblab/pi-actors/lib/trace-projection.ts +306 -0
- package/node_modules/@llblab/pi-actors/package.json +76 -0
- package/node_modules/@llblab/pi-actors/scripts/async-runner.mjs +555 -0
- package/node_modules/@llblab/pi-actors/scripts/build-dist.mjs +60 -0
- package/node_modules/@llblab/pi-actors/scripts/conformance.mjs +63 -0
- package/node_modules/@llblab/pi-actors/skills/actors/SKILL.md +126 -0
- package/node_modules/@llblab/pi-actors/skills/actors/recipes/command-validate.json +13 -0
- package/node_modules/@llblab/pi-actors/skills/actors/recipes/jsonl-tail.json +10 -0
- package/node_modules/@llblab/pi-actors/skills/actors/recipes/recipe-validate.json +11 -0
- package/node_modules/@llblab/pi-actors/skills/actors/recipes/resource-locker-snapshot.json +11 -0
- package/node_modules/@llblab/pi-actors/skills/actors/recipes/resource-locker.json +25 -0
- package/node_modules/@llblab/pi-actors/skills/actors/recipes/run-ops-snapshot.json +15 -0
- package/node_modules/@llblab/pi-actors/skills/actors/recipes/run-state-files.json +13 -0
- package/node_modules/@llblab/pi-actors/skills/actors/recipes/run-summary.json +9 -0
- package/node_modules/@llblab/pi-actors/skills/actors/references/diagnostics.md +44 -0
- package/node_modules/@llblab/pi-actors/skills/actors/references/persistent-tools.md +76 -0
- package/node_modules/@llblab/pi-actors/skills/actors/references/recipes.md +51 -0
- package/node_modules/@llblab/pi-actors/skills/actors/references/runs.md +41 -0
- package/node_modules/@llblab/pi-actors/skills/actors/scripts/resource-locker.mjs +425 -0
- package/node_modules/@llblab/pi-actors/skills/actors/scripts/run-utils.mjs +164 -0
- package/node_modules/@llblab/pi-actors/skills/actors/scripts/validate-recipe.mjs +370 -0
- package/node_modules/@llblab/pi-actors/skills/artifacts/SKILL.md +33 -0
- package/node_modules/@llblab/pi-actors/skills/artifacts/recipes/bundle.json +77 -0
- package/node_modules/@llblab/pi-actors/skills/artifacts/recipes/file-write.json +14 -0
- package/node_modules/@llblab/pi-actors/skills/artifacts/recipes/manifest.json +14 -0
- package/node_modules/@llblab/pi-actors/skills/artifacts/recipes/report.json +39 -0
- package/node_modules/@llblab/pi-actors/skills/artifacts/recipes/write.json +53 -0
- package/node_modules/@llblab/pi-actors/skills/artifacts/scripts/artifact-utils.mjs +63 -0
- package/node_modules/@llblab/pi-actors/skills/music-player/SKILL.md +57 -0
- package/node_modules/@llblab/pi-actors/skills/music-player/genapps/music-player.mjs +360 -0
- package/node_modules/@llblab/pi-actors/skills/music-player/recipes/playback.json +29 -0
- package/node_modules/@llblab/pi-actors/skills/music-player/scripts/playback-client.mjs +143 -0
- package/node_modules/@llblab/pi-actors/skills/music-player/scripts/playback.mjs +1446 -0
- package/node_modules/@llblab/pi-actors/skills/project-work/SKILL.md +37 -0
- package/node_modules/@llblab/pi-actors/skills/project-work/recipes/changelog-head.json +11 -0
- package/node_modules/@llblab/pi-actors/skills/project-work/recipes/changelog-section.json +11 -0
- package/node_modules/@llblab/pi-actors/skills/project-work/recipes/docs-maintenance.json +66 -0
- package/node_modules/@llblab/pi-actors/skills/project-work/recipes/git-log.json +11 -0
- package/node_modules/@llblab/pi-actors/skills/project-work/recipes/git-status.json +9 -0
- package/node_modules/@llblab/pi-actors/skills/project-work/recipes/markdown-index.json +14 -0
- package/node_modules/@llblab/pi-actors/skills/project-work/recipes/package-summary.json +9 -0
- package/node_modules/@llblab/pi-actors/skills/project-work/recipes/release-readiness.json +115 -0
- package/node_modules/@llblab/pi-actors/skills/project-work/recipes/release-summary.json +74 -0
- package/node_modules/@llblab/pi-actors/skills/project-work/recipes/repo-health.json +75 -0
- package/node_modules/@llblab/pi-actors/skills/project-work/recipes/run-ops.json +56 -0
- package/node_modules/@llblab/pi-actors/skills/project-work/recipes/skill-summary.json +11 -0
- package/node_modules/@llblab/pi-actors/skills/project-work/scripts/project-utils.mjs +89 -0
- package/node_modules/@llblab/pi-actors/skills/recipe-memory/SKILL.md +36 -0
- package/node_modules/@llblab/pi-actors/skills/recipe-memory/recipes/draft-review.json +14 -0
- package/node_modules/@llblab/pi-actors/skills/recipe-memory/recipes/tool-review.json +14 -0
- package/node_modules/@llblab/pi-actors/skills/swarm/SKILL.md +84 -0
- package/node_modules/@llblab/pi-actors/skills/swarm/recipes/architect.json +82 -0
- package/node_modules/@llblab/pi-actors/skills/swarm/recipes/checkpoint-continuation.json +51 -0
- package/node_modules/@llblab/pi-actors/skills/swarm/recipes/development-tasking.json +67 -0
- package/node_modules/@llblab/pi-actors/skills/swarm/recipes/lens-review.json +63 -0
- package/node_modules/@llblab/pi-actors/skills/swarm/recipes/quorum-review.json +65 -0
- package/node_modules/@llblab/pi-actors/skills/swarm/recipes/research-synthesis.json +81 -0
- package/node_modules/@llblab/pi-actors/skills/swarm/recipes/review-readiness.json +59 -0
- package/node_modules/@llblab/pi-actors/skills/swarm/recipes/subagent-artifact.json +21 -0
- package/node_modules/@llblab/pi-actors/skills/swarm/recipes/subagent-checkpoint.json +21 -0
- package/node_modules/@llblab/pi-actors/skills/swarm/recipes/subagent-conflict-report.json +19 -0
- package/node_modules/@llblab/pi-actors/skills/swarm/recipes/subagent-contradiction-map.json +20 -0
- package/node_modules/@llblab/pi-actors/skills/swarm/recipes/subagent-critic.json +22 -0
- package/node_modules/@llblab/pi-actors/skills/swarm/recipes/subagent-evidence-map.json +20 -0
- package/node_modules/@llblab/pi-actors/skills/swarm/recipes/subagent-followup.json +21 -0
- package/node_modules/@llblab/pi-actors/skills/swarm/recipes/subagent-judge.json +22 -0
- package/node_modules/@llblab/pi-actors/skills/swarm/recipes/subagent-merge.json +24 -0
- package/node_modules/@llblab/pi-actors/skills/swarm/recipes/subagent-normalize.json +20 -0
- package/node_modules/@llblab/pi-actors/skills/swarm/recipes/subagent-plan.json +20 -0
- package/node_modules/@llblab/pi-actors/skills/swarm/recipes/subagent-preflight.json +18 -0
- package/node_modules/@llblab/pi-actors/skills/swarm/recipes/subagent-prompt.json +16 -0
- package/node_modules/@llblab/pi-actors/skills/swarm/recipes/subagent-prompts.json +39 -0
- package/node_modules/@llblab/pi-actors/skills/swarm/recipes/subagent-quorum.json +31 -0
- package/node_modules/@llblab/pi-actors/skills/swarm/recipes/subagent-review-coordinator.json +170 -0
- package/node_modules/@llblab/pi-actors/skills/swarm/recipes/subagent-review.json +26 -0
- package/node_modules/@llblab/pi-actors/skills/swarm/recipes/subagent-task-card.json +22 -0
- package/node_modules/@llblab/pi-actors/skills/swarm/recipes/subagent-tools.json +15 -0
- package/node_modules/@llblab/pi-actors/skills/swarm/recipes/subagent-verify.json +23 -0
- package/node_modules/@llblab/pi-actors/skills/swarm/references/development-swarm.md +189 -0
- package/node_modules/@llblab/pi-actors/skills/swarm/references/review-swarms.md +115 -0
- package/node_modules/@llblab/pi-codex-usage/AGENTS.md +17 -0
- package/node_modules/@llblab/pi-codex-usage/BACKLOG.md +8 -0
- package/node_modules/@llblab/pi-codex-usage/CHANGELOG.md +80 -0
- package/node_modules/@llblab/pi-codex-usage/LICENSE +22 -0
- package/node_modules/@llblab/pi-codex-usage/README.md +113 -0
- package/node_modules/@llblab/pi-codex-usage/banner.jpg +0 -0
- package/node_modules/@llblab/pi-codex-usage/index.ts +1525 -0
- package/node_modules/@llblab/pi-codex-usage/package.json +59 -0
- package/node_modules/@llblab/pi-grow-loop/AGENTS.md +56 -0
- package/node_modules/@llblab/pi-grow-loop/BACKLOG.md +3 -0
- package/node_modules/@llblab/pi-grow-loop/CHANGELOG.md +126 -0
- package/node_modules/@llblab/pi-grow-loop/README.md +216 -0
- package/node_modules/@llblab/pi-grow-loop/banner.jpg +0 -0
- package/node_modules/@llblab/pi-grow-loop/index.ts +219 -0
- package/node_modules/@llblab/pi-grow-loop/package.json +64 -0
- package/node_modules/@llblab/pi-grow-loop/skills/grow-loop/SKILL.md +131 -0
- package/node_modules/@llblab/pi-grow-loop/skills/while-true/SKILL.md +233 -0
- package/node_modules/@llblab/pi-telegram/AGENTS.md +157 -0
- package/node_modules/@llblab/pi-telegram/BACKLOG.md +15 -0
- package/node_modules/@llblab/pi-telegram/CHANGELOG.md +886 -0
- package/node_modules/@llblab/pi-telegram/README.md +330 -0
- package/node_modules/@llblab/pi-telegram/api/activity.ts +15 -0
- package/node_modules/@llblab/pi-telegram/api/commands.ts +11 -0
- package/node_modules/@llblab/pi-telegram/api/delivery.ts +21 -0
- package/node_modules/@llblab/pi-telegram/api/inbound.ts +14 -0
- package/node_modules/@llblab/pi-telegram/api/keyboard.ts +11 -0
- package/node_modules/@llblab/pi-telegram/api/outbound.ts +11 -0
- package/node_modules/@llblab/pi-telegram/api/sections.ts +17 -0
- package/node_modules/@llblab/pi-telegram/api/status.ts +12 -0
- package/node_modules/@llblab/pi-telegram/api/updates.ts +16 -0
- package/node_modules/@llblab/pi-telegram/api/voice.ts +24 -0
- package/node_modules/@llblab/pi-telegram/docs/README.md +25 -0
- package/node_modules/@llblab/pi-telegram/docs/activity.md +304 -0
- package/node_modules/@llblab/pi-telegram/docs/architecture.md +418 -0
- package/node_modules/@llblab/pi-telegram/docs/callback-namespaces.md +48 -0
- package/node_modules/@llblab/pi-telegram/docs/command-templates.md +365 -0
- package/node_modules/@llblab/pi-telegram/docs/compact-matrix-literal.md +176 -0
- package/node_modules/@llblab/pi-telegram/docs/delivery.md +225 -0
- package/node_modules/@llblab/pi-telegram/docs/generative-apps.md +310 -0
- package/node_modules/@llblab/pi-telegram/docs/inbound.md +136 -0
- package/node_modules/@llblab/pi-telegram/docs/multi-instance-bus.md +467 -0
- package/node_modules/@llblab/pi-telegram/docs/outbound.md +193 -0
- package/node_modules/@llblab/pi-telegram/docs/public-api.md +599 -0
- package/node_modules/@llblab/pi-telegram/docs/sections.md +452 -0
- package/node_modules/@llblab/pi-telegram/docs/ui-style.md +256 -0
- package/node_modules/@llblab/pi-telegram/docs/updates.md +171 -0
- package/node_modules/@llblab/pi-telegram/docs/voice.md +217 -0
- package/node_modules/@llblab/pi-telegram/index.ts +1336 -0
- package/node_modules/@llblab/pi-telegram/lib/activity-verbosity.ts +714 -0
- package/node_modules/@llblab/pi-telegram/lib/activity.ts +782 -0
- package/node_modules/@llblab/pi-telegram/lib/agent-messages.ts +121 -0
- package/node_modules/@llblab/pi-telegram/lib/bindings.ts +1129 -0
- package/node_modules/@llblab/pi-telegram/lib/bus-api.ts +379 -0
- package/node_modules/@llblab/pi-telegram/lib/bus-follower.ts +1941 -0
- package/node_modules/@llblab/pi-telegram/lib/bus-leader.ts +2119 -0
- package/node_modules/@llblab/pi-telegram/lib/bus-transport.ts +244 -0
- package/node_modules/@llblab/pi-telegram/lib/bus.ts +2645 -0
- package/node_modules/@llblab/pi-telegram/lib/command-templates.ts +954 -0
- package/node_modules/@llblab/pi-telegram/lib/commands.ts +1854 -0
- package/node_modules/@llblab/pi-telegram/lib/config.ts +1143 -0
- package/node_modules/@llblab/pi-telegram/lib/delivery.ts +891 -0
- package/node_modules/@llblab/pi-telegram/lib/generative-app-worker.mjs +104 -0
- package/node_modules/@llblab/pi-telegram/lib/generative-apps.ts +958 -0
- package/node_modules/@llblab/pi-telegram/lib/inbound.ts +824 -0
- package/node_modules/@llblab/pi-telegram/lib/journal.ts +3140 -0
- package/node_modules/@llblab/pi-telegram/lib/keyboard.ts +59 -0
- package/node_modules/@llblab/pi-telegram/lib/lifecycle.ts +623 -0
- package/node_modules/@llblab/pi-telegram/lib/locks.ts +1422 -0
- package/node_modules/@llblab/pi-telegram/lib/logs.ts +393 -0
- package/node_modules/@llblab/pi-telegram/lib/media.ts +921 -0
- package/node_modules/@llblab/pi-telegram/lib/menu-model.ts +1182 -0
- package/node_modules/@llblab/pi-telegram/lib/menu-queue.ts +926 -0
- package/node_modules/@llblab/pi-telegram/lib/menu-settings.ts +876 -0
- package/node_modules/@llblab/pi-telegram/lib/menu-status.ts +274 -0
- package/node_modules/@llblab/pi-telegram/lib/menu-thinking.ts +185 -0
- package/node_modules/@llblab/pi-telegram/lib/menu.ts +867 -0
- package/node_modules/@llblab/pi-telegram/lib/model.ts +672 -0
- package/node_modules/@llblab/pi-telegram/lib/outbound-attachments.ts +981 -0
- package/node_modules/@llblab/pi-telegram/lib/outbound-buttons.ts +331 -0
- package/node_modules/@llblab/pi-telegram/lib/outbound-markup.ts +515 -0
- package/node_modules/@llblab/pi-telegram/lib/outbound-voice.ts +285 -0
- package/node_modules/@llblab/pi-telegram/lib/outbound.ts +1007 -0
- package/node_modules/@llblab/pi-telegram/lib/ownership.ts +298 -0
- package/node_modules/@llblab/pi-telegram/lib/paths.ts +127 -0
- package/node_modules/@llblab/pi-telegram/lib/pi.ts +197 -0
- package/node_modules/@llblab/pi-telegram/lib/polling.ts +1588 -0
- package/node_modules/@llblab/pi-telegram/lib/preview.ts +846 -0
- package/node_modules/@llblab/pi-telegram/lib/prompt-templates.ts +158 -0
- package/node_modules/@llblab/pi-telegram/lib/prompts.ts +218 -0
- package/node_modules/@llblab/pi-telegram/lib/queue.ts +3075 -0
- package/node_modules/@llblab/pi-telegram/lib/recovery.ts +464 -0
- package/node_modules/@llblab/pi-telegram/lib/rendering.ts +1213 -0
- package/node_modules/@llblab/pi-telegram/lib/replies.ts +892 -0
- package/node_modules/@llblab/pi-telegram/lib/routing.ts +2889 -0
- package/node_modules/@llblab/pi-telegram/lib/runtime.ts +628 -0
- package/node_modules/@llblab/pi-telegram/lib/sections.ts +710 -0
- package/node_modules/@llblab/pi-telegram/lib/setup.ts +220 -0
- package/node_modules/@llblab/pi-telegram/lib/skills.ts +21 -0
- package/node_modules/@llblab/pi-telegram/lib/status.ts +1550 -0
- package/node_modules/@llblab/pi-telegram/lib/sync.ts +883 -0
- package/node_modules/@llblab/pi-telegram/lib/target.ts +49 -0
- package/node_modules/@llblab/pi-telegram/lib/telegram-api.ts +1747 -0
- package/node_modules/@llblab/pi-telegram/lib/text-groups.ts +487 -0
- package/node_modules/@llblab/pi-telegram/lib/thread-reconciler.ts +1002 -0
- package/node_modules/@llblab/pi-telegram/lib/threads.ts +3183 -0
- package/node_modules/@llblab/pi-telegram/lib/time-injection.ts +78 -0
- package/node_modules/@llblab/pi-telegram/lib/turns.ts +753 -0
- package/node_modules/@llblab/pi-telegram/lib/updates.ts +4950 -0
- package/node_modules/@llblab/pi-telegram/lib/voice.ts +340 -0
- package/node_modules/@llblab/pi-telegram/package.json +83 -0
- package/node_modules/@llblab/pi-telegram/screenshot.png +0 -0
- package/node_modules/@llblab/pi-telegram/scripts/check-downgrade.mjs +435 -0
- package/node_modules/@llblab/pi-telegram/skills/generated-control-surface/SKILL.md +241 -0
- package/node_modules/@llblab/pi-telegram/skills/generative-apps/SKILL.md +114 -0
- package/node_modules/@llblab/pi-telegram/skills/telegram-bridge/SKILL.md +149 -0
- package/package.json +67 -0
|
@@ -0,0 +1,1108 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Template recipe reference helpers
|
|
3
|
+
* Zones: registry config, async runs, path resolution
|
|
4
|
+
* Owns detection, loading, and recipe-layer expansion for template recipe files
|
|
5
|
+
*/
|
|
6
|
+
import { existsSync, readFileSync, readdirSync, statSync } from "node:fs";
|
|
7
|
+
import { basename, dirname, extname, isAbsolute, join, relative, resolve } from "node:path";
|
|
8
|
+
import * as CommandTemplates from "./command-templates.js";
|
|
9
|
+
import * as Paths from "./paths.js";
|
|
10
|
+
import * as RecipeControl from "./recipe-control.js";
|
|
11
|
+
import * as Schema from "./schema.js";
|
|
12
|
+
const MAX_RECIPE_FILE_BYTES = 1024 * 1024;
|
|
13
|
+
const MAX_RECIPE_IMPORT_DEPTH = 32;
|
|
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();
|
|
34
|
+
for (const skill of skills) {
|
|
35
|
+
const name = skill.name.trim();
|
|
36
|
+
const skillDir = skill.baseDir
|
|
37
|
+
? resolve(skill.baseDir)
|
|
38
|
+
: skill.filePath
|
|
39
|
+
? dirname(resolve(skill.filePath))
|
|
40
|
+
: undefined;
|
|
41
|
+
if (!name || !skillDir)
|
|
42
|
+
continue;
|
|
43
|
+
const roots = rootsByName.get(name) ?? new Set();
|
|
44
|
+
roots.add(resolve(skillDir, "recipes"));
|
|
45
|
+
rootsByName.set(name, roots);
|
|
46
|
+
}
|
|
47
|
+
const namespaces = Object.fromEntries([...rootsByName.entries()]
|
|
48
|
+
.sort(([left], [right]) => left.localeCompare(right))
|
|
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.length} active definitions); exact Recipe resolution is ambiguous. Next: inspect target=recipes view=doctor identity=${skill}/<recipe>`,
|
|
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;
|
|
158
|
+
}
|
|
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) {
|
|
161
|
+
const path = resolve(file);
|
|
162
|
+
for (const [skillName, roots] of Object.entries(context.namespaces)) {
|
|
163
|
+
if (roots.length !== 1)
|
|
164
|
+
continue;
|
|
165
|
+
const root = roots[0];
|
|
166
|
+
const relation = relative(root, path);
|
|
167
|
+
if (relation &&
|
|
168
|
+
dirname(relation) === "." &&
|
|
169
|
+
!relation.startsWith("..") &&
|
|
170
|
+
!isAbsolute(relation)) {
|
|
171
|
+
return `${skillName}/${basename(relation, extname(relation))}`;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
return undefined;
|
|
175
|
+
}
|
|
176
|
+
function assertRecipeReferencePrefixWasNotRemoved(value) {
|
|
177
|
+
if (value.startsWith("std:")) {
|
|
178
|
+
throw new Error("std: Recipe references were removed in pi-actors 0.46. Use <skill>/<recipe> or an explicit .json/.md file path. Next: inspect target=recipes view=status to identify the active owning Skill.");
|
|
179
|
+
}
|
|
180
|
+
if (value.startsWith("skill:")) {
|
|
181
|
+
const identity = value.slice("skill:".length);
|
|
182
|
+
throw new Error(`skill: Recipe references were removed in pi-actors 0.46. Use ${identity} without a prefix. Next: inspect target=recipes view=doctor identity=${identity}`);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
function skillRecipeCandidates(value, context) {
|
|
186
|
+
const match = SKILL_RECIPE_REFERENCE.exec(value);
|
|
187
|
+
if (!match)
|
|
188
|
+
return undefined;
|
|
189
|
+
const [, skillName, recipeName] = match;
|
|
190
|
+
const roots = [...(context.namespaces[skillName] ?? [])];
|
|
191
|
+
if (roots.length === 0)
|
|
192
|
+
throw new Error(`Active Skill Recipe not found: ${skillName}/${recipeName}. Owning Skill "${skillName}" is not active. Next: activate Skill ${skillName}, then inspect target=recipes view=doctor identity=${skillName}/${recipeName}`);
|
|
193
|
+
if (roots.length > 1)
|
|
194
|
+
throw new Error(`Duplicate active Skill identity ${skillName} (${roots.length} active definitions); ${skillName}/${recipeName} cannot resolve unambiguously. Next: inspect target=recipes view=doctor identity=${skillName}/${recipeName}`);
|
|
195
|
+
const root = roots[0];
|
|
196
|
+
const candidates = ["json", "md"].map((extension) => resolve(root, `${recipeName}.${extension}`));
|
|
197
|
+
const existing = candidates.filter((candidate) => existsSync(candidate));
|
|
198
|
+
if (existing.length === 0) {
|
|
199
|
+
throw new Error(`Skill Recipe component not found: ${skillName}/${recipeName}; owning Skill "${skillName}" is active. Next: inspect target=recipes view=doctor identity=${skillName}/${recipeName}`);
|
|
200
|
+
}
|
|
201
|
+
if (existing.length > 1) {
|
|
202
|
+
throw new Error(`Skill Recipe stem collision: ${skillName}/${recipeName} has both .json and .md files`);
|
|
203
|
+
}
|
|
204
|
+
return candidates;
|
|
205
|
+
}
|
|
206
|
+
function recipeReferenceCandidates(value, baseDir, context) {
|
|
207
|
+
const trimmed = value.trim();
|
|
208
|
+
if (!trimmed)
|
|
209
|
+
return undefined;
|
|
210
|
+
assertRecipeReferencePrefixWasNotRemoved(trimmed);
|
|
211
|
+
if (trimmed.endsWith(".json") || trimmed.endsWith(".md")) {
|
|
212
|
+
return [resolve(baseDir, trimmed)];
|
|
213
|
+
}
|
|
214
|
+
return skillRecipeCandidates(trimmed, context);
|
|
215
|
+
}
|
|
216
|
+
function findOwningSkillDir(recipeFile) {
|
|
217
|
+
let current = dirname(recipeFile);
|
|
218
|
+
while (true) {
|
|
219
|
+
if (existsSync(resolve(current, "SKILL.md")))
|
|
220
|
+
return current;
|
|
221
|
+
const parent = dirname(current);
|
|
222
|
+
if (parent === current)
|
|
223
|
+
return undefined;
|
|
224
|
+
current = parent;
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
function assertRecipeHasNoDeclaredName(raw) {
|
|
228
|
+
if (!Object.hasOwn(raw, "name"))
|
|
229
|
+
return;
|
|
230
|
+
throw new Error("Recipe.name was removed in pi-actors 0.46. File-backed Recipe identity is derived from its file name. Next: remove the name field, keep the intended filename stem, then inspect target=recipes view=doctor.");
|
|
231
|
+
}
|
|
232
|
+
function assertRuntimeRecipeValuesNotDeclared(raw) {
|
|
233
|
+
const args = Array.isArray(raw.args)
|
|
234
|
+
? Schema.getExplicitToolArgNames(raw.args.map(String))
|
|
235
|
+
: [];
|
|
236
|
+
for (const name of RESERVED_AUTHORED_RECIPE_VALUE_NAMES) {
|
|
237
|
+
if (args.includes(name) ||
|
|
238
|
+
(isRecord(raw.defaults) && Object.hasOwn(raw.defaults, name)) ||
|
|
239
|
+
(isRecord(raw.values) && Object.hasOwn(raw.values, name))) {
|
|
240
|
+
throw new Error(`Recipe runtime value is reserved: ${name}`);
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
export function resolveRecipePath(value, baseDir = Paths.getRecipeRoot()) {
|
|
245
|
+
const candidates = recipeReferenceCandidates(value, baseDir, EMPTY_ACTIVE_SKILL_RECIPE_CONTEXT);
|
|
246
|
+
if (!candidates || candidates.length !== 1) {
|
|
247
|
+
throw new Error(`Recipe file reference must be an explicit .json or .md path: ${value}`);
|
|
248
|
+
}
|
|
249
|
+
return candidates[0];
|
|
250
|
+
}
|
|
251
|
+
function resolveRecipeImportPath(value, recipeDir, context) {
|
|
252
|
+
const candidates = recipeReferenceCandidates(value, recipeDir, context);
|
|
253
|
+
if (!candidates) {
|
|
254
|
+
throw new Error(`Recipe import must use <skill>/<recipe> or an explicit .json/.md file path: ${value}`);
|
|
255
|
+
}
|
|
256
|
+
return candidates.find((candidate) => existsSync(candidate)) ?? candidates[0];
|
|
257
|
+
}
|
|
258
|
+
export function resolveRecipeReferencePath(value, baseDir = Paths.getRecipeRoot(), context = EMPTY_ACTIVE_SKILL_RECIPE_CONTEXT) {
|
|
259
|
+
if (typeof value !== "string")
|
|
260
|
+
return undefined;
|
|
261
|
+
const candidates = recipeReferenceCandidates(value, baseDir, context);
|
|
262
|
+
return candidates?.find((candidate) => existsSync(candidate));
|
|
263
|
+
}
|
|
264
|
+
export function getRecipePath(value, baseDir = Paths.getRecipeRoot(), context = EMPTY_ACTIVE_SKILL_RECIPE_CONTEXT) {
|
|
265
|
+
return resolveRecipeReferencePath(value, baseDir, context);
|
|
266
|
+
}
|
|
267
|
+
function isImportNode(value) {
|
|
268
|
+
if (!isRecord(value) || Object.hasOwn(value, "template"))
|
|
269
|
+
return false;
|
|
270
|
+
return typeof value.name === "string";
|
|
271
|
+
}
|
|
272
|
+
function isValidRecipeTemplateNode(value) {
|
|
273
|
+
if (isImportNode(value))
|
|
274
|
+
return true;
|
|
275
|
+
if (isRecord(value)) {
|
|
276
|
+
if (isImportNode(value.template))
|
|
277
|
+
return true;
|
|
278
|
+
if (Array.isArray(value.template))
|
|
279
|
+
return isValidRecipeTemplateArray(value.template);
|
|
280
|
+
}
|
|
281
|
+
return (CommandTemplates.expandCommandTemplateConfigs(value).length > 0);
|
|
282
|
+
}
|
|
283
|
+
function isValidRecipeTemplateArray(value) {
|
|
284
|
+
return (value.length > 0 && value.every((item) => isValidRecipeTemplateNode(item)));
|
|
285
|
+
}
|
|
286
|
+
function normalizeRecipeTemplate(value) {
|
|
287
|
+
if (typeof value === "string")
|
|
288
|
+
return value.trim() || undefined;
|
|
289
|
+
if (Array.isArray(value)) {
|
|
290
|
+
const template = value;
|
|
291
|
+
return isValidRecipeTemplateArray(template) ? template : undefined;
|
|
292
|
+
}
|
|
293
|
+
if (isImportNode(value))
|
|
294
|
+
return value;
|
|
295
|
+
if (value && typeof value === "object") {
|
|
296
|
+
const template = value;
|
|
297
|
+
if (Array.isArray(template.template) &&
|
|
298
|
+
isValidRecipeTemplateArray(template.template))
|
|
299
|
+
return template;
|
|
300
|
+
if (isImportNode(template.template))
|
|
301
|
+
return template;
|
|
302
|
+
return CommandTemplates.expandCommandTemplateConfigs(template).length > 0
|
|
303
|
+
? template
|
|
304
|
+
: undefined;
|
|
305
|
+
}
|
|
306
|
+
return undefined;
|
|
307
|
+
}
|
|
308
|
+
function getRecipeCommandTemplate(raw) {
|
|
309
|
+
const template = raw.template;
|
|
310
|
+
const envelope = {};
|
|
311
|
+
for (const key of [
|
|
312
|
+
"args",
|
|
313
|
+
"defaults",
|
|
314
|
+
"parallel",
|
|
315
|
+
"concurrency",
|
|
316
|
+
"min_successful",
|
|
317
|
+
"label",
|
|
318
|
+
"when",
|
|
319
|
+
"timeout",
|
|
320
|
+
"delay",
|
|
321
|
+
"accept_output",
|
|
322
|
+
"output",
|
|
323
|
+
"retry",
|
|
324
|
+
"failure",
|
|
325
|
+
"recover",
|
|
326
|
+
"repeat",
|
|
327
|
+
]) {
|
|
328
|
+
if (raw[key] !== undefined)
|
|
329
|
+
envelope[key] = raw[key];
|
|
330
|
+
}
|
|
331
|
+
if (Object.keys(envelope).length === 0)
|
|
332
|
+
return normalizeRecipeTemplate(template);
|
|
333
|
+
if (template && typeof template === "object" && !Array.isArray(template)) {
|
|
334
|
+
return normalizeRecipeTemplate({
|
|
335
|
+
...envelope,
|
|
336
|
+
...template,
|
|
337
|
+
});
|
|
338
|
+
}
|
|
339
|
+
return normalizeRecipeTemplate({ ...envelope, template });
|
|
340
|
+
}
|
|
341
|
+
function parseMarkdownScalar(value) {
|
|
342
|
+
const trimmed = value.trim();
|
|
343
|
+
if (!trimmed)
|
|
344
|
+
return "";
|
|
345
|
+
if ((trimmed.startsWith("{") && trimmed.endsWith("}")) ||
|
|
346
|
+
(trimmed.startsWith("[") && trimmed.endsWith("]"))) {
|
|
347
|
+
try {
|
|
348
|
+
return JSON.parse(trimmed);
|
|
349
|
+
}
|
|
350
|
+
catch {
|
|
351
|
+
return trimmed;
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
const quoted = trimmed.match(/^(?:"([^"]*)"|'([^']*)')$/);
|
|
355
|
+
if (quoted)
|
|
356
|
+
return quoted[1] ?? quoted[2] ?? "";
|
|
357
|
+
if (trimmed === "true")
|
|
358
|
+
return true;
|
|
359
|
+
if (trimmed === "false")
|
|
360
|
+
return false;
|
|
361
|
+
if (trimmed === "null")
|
|
362
|
+
return null;
|
|
363
|
+
if (/^-?\d+(?:\.\d+)?$/.test(trimmed))
|
|
364
|
+
return Number(trimmed);
|
|
365
|
+
return trimmed;
|
|
366
|
+
}
|
|
367
|
+
function parseMarkdownFrontmatterObject(lines) {
|
|
368
|
+
if (lines.every((line) => /^\s*-\s+/.test(line))) {
|
|
369
|
+
return lines.map((line) => parseMarkdownScalar(line.replace(/^\s*-\s+/, "")));
|
|
370
|
+
}
|
|
371
|
+
const result = {};
|
|
372
|
+
for (let index = 0; index < lines.length; index += 1) {
|
|
373
|
+
const match = lines[index].match(/^\s{2}([A-Za-z_][A-Za-z0-9_.-]*):\s*(.*)$/);
|
|
374
|
+
if (!match)
|
|
375
|
+
continue;
|
|
376
|
+
if (match[2]) {
|
|
377
|
+
result[match[1]] = parseMarkdownScalar(match[2]);
|
|
378
|
+
continue;
|
|
379
|
+
}
|
|
380
|
+
const nested = [];
|
|
381
|
+
while (index + 1 < lines.length && /^\s{4}/.test(lines[index + 1])) {
|
|
382
|
+
index += 1;
|
|
383
|
+
nested.push(lines[index].slice(2));
|
|
384
|
+
}
|
|
385
|
+
result[match[1]] = parseMarkdownFrontmatterObject(nested);
|
|
386
|
+
}
|
|
387
|
+
return result;
|
|
388
|
+
}
|
|
389
|
+
function normalizeMarkdownFrontmatterField(key, value) {
|
|
390
|
+
if (key === "args" && typeof value === "string") {
|
|
391
|
+
return value
|
|
392
|
+
.split(",")
|
|
393
|
+
.map((item) => item.trim())
|
|
394
|
+
.filter(Boolean);
|
|
395
|
+
}
|
|
396
|
+
if (key === "defaults" && Array.isArray(value)) {
|
|
397
|
+
return Object.fromEntries(value
|
|
398
|
+
.filter((item) => typeof item === "string")
|
|
399
|
+
.map((item) => {
|
|
400
|
+
const separator = item.indexOf(":");
|
|
401
|
+
return separator < 0
|
|
402
|
+
? [item.trim(), ""]
|
|
403
|
+
: [
|
|
404
|
+
item.slice(0, separator).trim(),
|
|
405
|
+
parseMarkdownScalar(item.slice(separator + 1)),
|
|
406
|
+
];
|
|
407
|
+
})
|
|
408
|
+
.filter(([name]) => Boolean(name)));
|
|
409
|
+
}
|
|
410
|
+
return value;
|
|
411
|
+
}
|
|
412
|
+
function parseMarkdownFrontmatter(value) {
|
|
413
|
+
const result = {};
|
|
414
|
+
const lines = value.split(/\r?\n/);
|
|
415
|
+
for (let index = 0; index < lines.length; index += 1) {
|
|
416
|
+
const line = lines[index];
|
|
417
|
+
if (!line.trim() || line.trim().startsWith("#"))
|
|
418
|
+
continue;
|
|
419
|
+
const match = line.match(/^([A-Za-z_][A-Za-z0-9_.-]*):\s*(.*)$/);
|
|
420
|
+
if (!match)
|
|
421
|
+
continue;
|
|
422
|
+
if (match[2]) {
|
|
423
|
+
result[match[1]] = normalizeMarkdownFrontmatterField(match[1], parseMarkdownScalar(match[2]));
|
|
424
|
+
continue;
|
|
425
|
+
}
|
|
426
|
+
const nested = [];
|
|
427
|
+
while (index + 1 < lines.length && /^\s+/.test(lines[index + 1])) {
|
|
428
|
+
index += 1;
|
|
429
|
+
nested.push(lines[index]);
|
|
430
|
+
}
|
|
431
|
+
result[match[1]] = normalizeMarkdownFrontmatterField(match[1], parseMarkdownFrontmatterObject(nested));
|
|
432
|
+
}
|
|
433
|
+
return result;
|
|
434
|
+
}
|
|
435
|
+
function findMarkdownRecipeFence(body) {
|
|
436
|
+
const pattern = /```([^\n`]*)\n([\s\S]*?)```/g;
|
|
437
|
+
for (const match of body.matchAll(pattern)) {
|
|
438
|
+
const info = match[1].trim().toLowerCase();
|
|
439
|
+
if (info.includes("recipe") ||
|
|
440
|
+
info.includes("template") ||
|
|
441
|
+
info.includes("command") ||
|
|
442
|
+
info.includes("json")) {
|
|
443
|
+
return { info, body: match[2].trim() };
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
return undefined;
|
|
447
|
+
}
|
|
448
|
+
function parseMarkdownRecipeConfig(content) {
|
|
449
|
+
const lines = content.split(/\r?\n/);
|
|
450
|
+
if (lines[0]?.trim() !== "---")
|
|
451
|
+
return undefined;
|
|
452
|
+
const end = lines.findIndex((line, index) => index > 0 && line.trim() === "---");
|
|
453
|
+
if (end === -1)
|
|
454
|
+
return undefined;
|
|
455
|
+
const frontmatter = parseMarkdownFrontmatter(lines.slice(1, end).join("\n"));
|
|
456
|
+
const fence = findMarkdownRecipeFence(lines.slice(end + 1).join("\n"));
|
|
457
|
+
if (!fence)
|
|
458
|
+
return Object.hasOwn(frontmatter, "template") ? frontmatter : undefined;
|
|
459
|
+
const text = fence.body.trim();
|
|
460
|
+
if (!text)
|
|
461
|
+
return undefined;
|
|
462
|
+
if (fence.info.includes("json") ||
|
|
463
|
+
fence.info.includes("recipe") ||
|
|
464
|
+
text.startsWith("{") ||
|
|
465
|
+
text.startsWith("[") ||
|
|
466
|
+
text.startsWith('"')) {
|
|
467
|
+
try {
|
|
468
|
+
const parsed = JSON.parse(text);
|
|
469
|
+
if (isRecord(parsed) && Object.hasOwn(parsed, "template"))
|
|
470
|
+
return { ...frontmatter, ...parsed };
|
|
471
|
+
return { ...frontmatter, template: parsed };
|
|
472
|
+
}
|
|
473
|
+
catch {
|
|
474
|
+
if (fence.info.includes("json") || fence.info.includes("recipe"))
|
|
475
|
+
return undefined;
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
return { ...frontmatter, template: text };
|
|
479
|
+
}
|
|
480
|
+
export function diagnoseRawRecipeConfigFailure(path) {
|
|
481
|
+
if (!existsSync(path))
|
|
482
|
+
return "file does not exist";
|
|
483
|
+
const size = statSync(path).size;
|
|
484
|
+
if (size > MAX_RECIPE_FILE_BYTES) {
|
|
485
|
+
return `file exceeds size limit ${MAX_RECIPE_FILE_BYTES} bytes`;
|
|
486
|
+
}
|
|
487
|
+
try {
|
|
488
|
+
const content = readFileSync(path, "utf8");
|
|
489
|
+
if (path.endsWith(".md")) {
|
|
490
|
+
const lines = content.split(/\r?\n/);
|
|
491
|
+
if (lines[0]?.trim() !== "---") {
|
|
492
|
+
return "Markdown recipe must start with frontmatter";
|
|
493
|
+
}
|
|
494
|
+
const end = lines.findIndex((line, index) => index > 0 && line.trim() === "---");
|
|
495
|
+
if (end === -1)
|
|
496
|
+
return "Markdown recipe frontmatter is not closed";
|
|
497
|
+
const parsed = parseMarkdownRecipeConfig(content);
|
|
498
|
+
if (!parsed)
|
|
499
|
+
return "Markdown recipe has no executable recipe/template fence";
|
|
500
|
+
if (!Object.hasOwn(parsed, "template"))
|
|
501
|
+
return "recipe must define template";
|
|
502
|
+
return undefined;
|
|
503
|
+
}
|
|
504
|
+
const raw = JSON.parse(content);
|
|
505
|
+
if (!raw || typeof raw !== "object" || Array.isArray(raw)) {
|
|
506
|
+
return "JSON recipe must be an object";
|
|
507
|
+
}
|
|
508
|
+
if (!Object.hasOwn(raw, "template"))
|
|
509
|
+
return "recipe must define template";
|
|
510
|
+
return undefined;
|
|
511
|
+
}
|
|
512
|
+
catch (error) {
|
|
513
|
+
return error instanceof Error ? error.message : String(error);
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
export function readRawRecipeConfig(path) {
|
|
517
|
+
if (!existsSync(path))
|
|
518
|
+
return undefined;
|
|
519
|
+
const size = statSync(path).size;
|
|
520
|
+
if (size > MAX_RECIPE_FILE_BYTES) {
|
|
521
|
+
throw new Error(`Recipe file exceeds size limit ${MAX_RECIPE_FILE_BYTES} bytes: ${path}`);
|
|
522
|
+
}
|
|
523
|
+
try {
|
|
524
|
+
const content = readFileSync(path, "utf8");
|
|
525
|
+
if (path.endsWith(".md"))
|
|
526
|
+
return parseMarkdownRecipeConfig(content);
|
|
527
|
+
const raw = JSON.parse(content);
|
|
528
|
+
return raw && typeof raw === "object" ? raw : undefined;
|
|
529
|
+
}
|
|
530
|
+
catch {
|
|
531
|
+
return undefined;
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
export function getRecipeIdFromPath(file) {
|
|
535
|
+
return basename(file, extname(file));
|
|
536
|
+
}
|
|
537
|
+
function readRecipeConfig(value) {
|
|
538
|
+
const path = resolveRecipeReferencePath(value);
|
|
539
|
+
return path ? readResolvedRecipeConfig(path) : undefined;
|
|
540
|
+
}
|
|
541
|
+
function isRecord(value) {
|
|
542
|
+
return Boolean(value && typeof value === "object" && !Array.isArray(value));
|
|
543
|
+
}
|
|
544
|
+
function getRecipeImports(raw) {
|
|
545
|
+
if (!isRecord(raw.imports))
|
|
546
|
+
return {};
|
|
547
|
+
const result = {};
|
|
548
|
+
for (const [alias, value] of Object.entries(raw.imports)) {
|
|
549
|
+
if (!/^[A-Za-z0-9_.-]+$/.test(alias))
|
|
550
|
+
throw new Error(`Invalid recipe import alias: ${alias}`);
|
|
551
|
+
if (typeof value === "string") {
|
|
552
|
+
result[alias] = value;
|
|
553
|
+
continue;
|
|
554
|
+
}
|
|
555
|
+
if (!isRecord(value))
|
|
556
|
+
throw new Error(`Recipe import must be a string or object: ${alias}`);
|
|
557
|
+
const from = typeof value.from === "string" ? value.from.trim() : "";
|
|
558
|
+
if (!from)
|
|
559
|
+
throw new Error(`Recipe import must define from: ${alias}`);
|
|
560
|
+
result[alias] = {
|
|
561
|
+
from,
|
|
562
|
+
...(isRecord(value.defaults) ? { defaults: value.defaults } : {}),
|
|
563
|
+
...(isRecord(value.values) ? { values: value.values } : {}),
|
|
564
|
+
};
|
|
565
|
+
}
|
|
566
|
+
return result;
|
|
567
|
+
}
|
|
568
|
+
function getImportFrom(value) {
|
|
569
|
+
return typeof value === "string" ? value : (value.from ?? "");
|
|
570
|
+
}
|
|
571
|
+
function getPathValue(source, path) {
|
|
572
|
+
if (!path)
|
|
573
|
+
return source;
|
|
574
|
+
let current = source;
|
|
575
|
+
for (const key of path.split(".")) {
|
|
576
|
+
if (!key)
|
|
577
|
+
continue;
|
|
578
|
+
if (!isRecord(current) || !Object.hasOwn(current, key))
|
|
579
|
+
return undefined;
|
|
580
|
+
current = current[key];
|
|
581
|
+
}
|
|
582
|
+
return current;
|
|
583
|
+
}
|
|
584
|
+
function resolveImportRef(ref, imports, allowMissing = false) {
|
|
585
|
+
for (const [alias, imported] of Object.entries(imports)) {
|
|
586
|
+
const prefix = `${alias}.`;
|
|
587
|
+
if (!ref.startsWith(prefix))
|
|
588
|
+
continue;
|
|
589
|
+
const rest = ref.slice(prefix.length);
|
|
590
|
+
const match = /^(name|file|defaults|values)(?:\.(.+))?$/.exec(rest);
|
|
591
|
+
if (!match)
|
|
592
|
+
return { matched: false, value: undefined };
|
|
593
|
+
const section = match[1];
|
|
594
|
+
if (section === "name")
|
|
595
|
+
return { matched: true, value: imported.name };
|
|
596
|
+
if (section === "file")
|
|
597
|
+
return { matched: true, value: imported.file };
|
|
598
|
+
const value = section === "defaults" ? imported.defaults : imported.values;
|
|
599
|
+
const resolved = getPathValue(value, match[2]);
|
|
600
|
+
if (resolved === undefined && !allowMissing)
|
|
601
|
+
throw new Error(`Unknown recipe import reference: ${ref}`);
|
|
602
|
+
return { matched: true, value: resolved };
|
|
603
|
+
}
|
|
604
|
+
return { matched: false, value: undefined };
|
|
605
|
+
}
|
|
606
|
+
function isFalsyImportValue(value) {
|
|
607
|
+
return (value === undefined ||
|
|
608
|
+
value === null ||
|
|
609
|
+
value === false ||
|
|
610
|
+
value === 0 ||
|
|
611
|
+
value === "");
|
|
612
|
+
}
|
|
613
|
+
function parseImportLiteral(value, imports) {
|
|
614
|
+
const trimmed = value.trim();
|
|
615
|
+
const quoted = trimmed.match(/^(["'])(.*)\1$/);
|
|
616
|
+
if (quoted)
|
|
617
|
+
return quoted[2];
|
|
618
|
+
const resolved = resolveImportRef(trimmed, imports, true);
|
|
619
|
+
return resolved.matched ? resolved.value : trimmed;
|
|
620
|
+
}
|
|
621
|
+
function evaluateImportExpression(content, imports) {
|
|
622
|
+
const trimmed = content.trim();
|
|
623
|
+
const ternary = trimmed.match(/^(.+?)\?([^:]*):(.*)$/);
|
|
624
|
+
if (ternary) {
|
|
625
|
+
const condition = resolveImportRef(ternary[1].trim(), imports, true);
|
|
626
|
+
if (!condition.matched)
|
|
627
|
+
return { matched: false, value: undefined };
|
|
628
|
+
return {
|
|
629
|
+
matched: true,
|
|
630
|
+
value: parseImportLiteral(isFalsyImportValue(condition.value) ? ternary[3] : ternary[2], imports),
|
|
631
|
+
};
|
|
632
|
+
}
|
|
633
|
+
const fallback = trimmed.match(/^([^=]+)=(.*)$/);
|
|
634
|
+
if (fallback) {
|
|
635
|
+
const resolved = resolveImportRef(fallback[1].trim(), imports, true);
|
|
636
|
+
if (!resolved.matched)
|
|
637
|
+
return { matched: false, value: undefined };
|
|
638
|
+
return {
|
|
639
|
+
matched: true,
|
|
640
|
+
value: resolved.value === undefined || resolved.value === null
|
|
641
|
+
? parseImportLiteral(fallback[2], imports)
|
|
642
|
+
: resolved.value,
|
|
643
|
+
};
|
|
644
|
+
}
|
|
645
|
+
return resolveImportRef(trimmed, imports);
|
|
646
|
+
}
|
|
647
|
+
function substituteImportRefs(value, imports) {
|
|
648
|
+
if (typeof value === "string") {
|
|
649
|
+
const exact = /^\{([^{}]+)\}$/.exec(value);
|
|
650
|
+
if (exact) {
|
|
651
|
+
const resolved = evaluateImportExpression(exact[1], imports);
|
|
652
|
+
if (resolved.matched)
|
|
653
|
+
return resolved.value;
|
|
654
|
+
}
|
|
655
|
+
return value.replaceAll(/\{([^{}]+)\}/g, (token, ref) => {
|
|
656
|
+
const resolved = evaluateImportExpression(String(ref), imports);
|
|
657
|
+
return resolved.matched ? String(resolved.value ?? "") : token;
|
|
658
|
+
});
|
|
659
|
+
}
|
|
660
|
+
if (Array.isArray(value))
|
|
661
|
+
return value.map((item) => substituteImportRefs(item, imports));
|
|
662
|
+
if (isRecord(value)) {
|
|
663
|
+
const result = {};
|
|
664
|
+
for (const [key, child] of Object.entries(value))
|
|
665
|
+
result[key] = substituteImportRefs(child, imports);
|
|
666
|
+
return result;
|
|
667
|
+
}
|
|
668
|
+
return value;
|
|
669
|
+
}
|
|
670
|
+
function mergeDefaults(...items) {
|
|
671
|
+
const merged = Object.assign({}, ...items.filter(Boolean));
|
|
672
|
+
return Object.keys(merged).length > 0 ? merged : undefined;
|
|
673
|
+
}
|
|
674
|
+
function assertRecipeDefaultsDeclared(args, defaults, label) {
|
|
675
|
+
const spec = Schema.parseToolArgDeclarationList(args ?? []);
|
|
676
|
+
if (spec.error)
|
|
677
|
+
throw new Error(spec.error);
|
|
678
|
+
if (spec.args.length === 0)
|
|
679
|
+
return;
|
|
680
|
+
const declared = new Set(spec.args);
|
|
681
|
+
for (const key of Object.keys(defaults ?? {})) {
|
|
682
|
+
if (!declared.has(key))
|
|
683
|
+
throw new Error(`Unknown ${label} argument: ${key}`);
|
|
684
|
+
}
|
|
685
|
+
}
|
|
686
|
+
function assertRecipeArgumentContract(config, label = "Recipe default") {
|
|
687
|
+
assertRecipeDefaultsDeclared(config.args, config.defaults, label);
|
|
688
|
+
const spec = Schema.parseToolArgDeclarationList(config.args ?? []);
|
|
689
|
+
if (spec.error)
|
|
690
|
+
throw new Error(spec.error);
|
|
691
|
+
Schema.assertCompatibleToolArgTypes(spec.argTypes, Schema.getTemplateArgTypes({ template: config.template }));
|
|
692
|
+
const staticValues = Object.fromEntries(Object.entries({ ...config.defaults, ...config.values }).filter(([, value]) => typeof value !== "string" || !/\{[^{}]+\}/.test(value)));
|
|
693
|
+
Schema.normalizeRuntimeValues(staticValues, spec.argTypes);
|
|
694
|
+
}
|
|
695
|
+
function resolveRecipeValueLayers(args, ...layers) {
|
|
696
|
+
const spec = Schema.parseToolArgDeclarationList(args ?? []);
|
|
697
|
+
if (spec.error)
|
|
698
|
+
throw new Error(spec.error);
|
|
699
|
+
const merged = mergeDefaults(spec.defaults, ...layers);
|
|
700
|
+
if (!merged)
|
|
701
|
+
return undefined;
|
|
702
|
+
const staticValues = Object.fromEntries(Object.entries(merged).filter(([, value]) => typeof value !== "string" || !/\{[^{}]+\}/.test(value)));
|
|
703
|
+
return {
|
|
704
|
+
...merged,
|
|
705
|
+
...Schema.normalizeRuntimeValues(staticValues, spec.argTypes),
|
|
706
|
+
};
|
|
707
|
+
}
|
|
708
|
+
function applyDefaultsToTemplate(template, defaults, overrides) {
|
|
709
|
+
const cleanOverrides = { ...overrides };
|
|
710
|
+
delete cleanOverrides.name;
|
|
711
|
+
delete cleanOverrides.template;
|
|
712
|
+
delete cleanOverrides.values;
|
|
713
|
+
delete cleanOverrides.defaults;
|
|
714
|
+
if (typeof template === "object" && !Array.isArray(template)) {
|
|
715
|
+
return {
|
|
716
|
+
...template,
|
|
717
|
+
...cleanOverrides,
|
|
718
|
+
...(mergeDefaults(template.defaults, defaults, isRecord(cleanOverrides.defaults) ? cleanOverrides.defaults : undefined)
|
|
719
|
+
? {
|
|
720
|
+
defaults: mergeDefaults(template.defaults, defaults, isRecord(cleanOverrides.defaults)
|
|
721
|
+
? cleanOverrides.defaults
|
|
722
|
+
: undefined),
|
|
723
|
+
}
|
|
724
|
+
: {}),
|
|
725
|
+
};
|
|
726
|
+
}
|
|
727
|
+
return {
|
|
728
|
+
...cleanOverrides,
|
|
729
|
+
...(defaults ? { defaults } : {}),
|
|
730
|
+
template,
|
|
731
|
+
};
|
|
732
|
+
}
|
|
733
|
+
function withActorRecipeContext(value, context) {
|
|
734
|
+
if (typeof value === "object" && !Array.isArray(value)) {
|
|
735
|
+
return { ...value, actorRecipeContext: context };
|
|
736
|
+
}
|
|
737
|
+
return { actorRecipeContext: context, template: value };
|
|
738
|
+
}
|
|
739
|
+
function loadDelegatedRecipe(value, currentRecipeFile, stack, options) {
|
|
740
|
+
const path = resolveRecipeReferencePath(value, dirname(currentRecipeFile), options.skillContext);
|
|
741
|
+
if (!path)
|
|
742
|
+
return undefined;
|
|
743
|
+
const config = readResolvedRecipeConfig(path, [...stack, currentRecipeFile], options);
|
|
744
|
+
if (!config)
|
|
745
|
+
throw new Error(`Template recipe must define template: ${path}`);
|
|
746
|
+
if (config.disabled === true)
|
|
747
|
+
throw new Error(`Template recipe is disabled: ${path}`);
|
|
748
|
+
return config;
|
|
749
|
+
}
|
|
750
|
+
function applyDelegatedRecipeToNode(delegated, overrides = {}) {
|
|
751
|
+
const nodeDefaults = isRecord(overrides.defaults)
|
|
752
|
+
? overrides.defaults
|
|
753
|
+
: undefined;
|
|
754
|
+
const nodeValues = isRecord(overrides.values) ? overrides.values : undefined;
|
|
755
|
+
const values = resolveRecipeValueLayers(delegated.args, delegated.defaults, delegated.values, nodeDefaults, nodeValues, {
|
|
756
|
+
...(delegated.recipe_dir ? { recipe_dir: delegated.recipe_dir } : {}),
|
|
757
|
+
...(delegated.skill_dir ? { skill_dir: delegated.skill_dir } : {}),
|
|
758
|
+
});
|
|
759
|
+
return applyDefaultsToTemplate(delegated.template, values, overrides);
|
|
760
|
+
}
|
|
761
|
+
function expandRecipeDelegations(value, currentRecipeFile, stack, options = {}) {
|
|
762
|
+
if (typeof value === "string") {
|
|
763
|
+
const delegated = loadDelegatedRecipe(value, currentRecipeFile, stack, options);
|
|
764
|
+
return delegated ? applyDelegatedRecipeToNode(delegated) : value;
|
|
765
|
+
}
|
|
766
|
+
if (Array.isArray(value)) {
|
|
767
|
+
return value.map((item) => expandRecipeDelegations(item, currentRecipeFile, stack, options));
|
|
768
|
+
}
|
|
769
|
+
const record = value;
|
|
770
|
+
if (typeof record.template === "string") {
|
|
771
|
+
const delegated = loadDelegatedRecipe(record.template, currentRecipeFile, stack, options);
|
|
772
|
+
if (delegated)
|
|
773
|
+
return applyDelegatedRecipeToNode(delegated, record);
|
|
774
|
+
}
|
|
775
|
+
if (Array.isArray(record.template)) {
|
|
776
|
+
return {
|
|
777
|
+
...record,
|
|
778
|
+
template: record.template.map((item) => expandRecipeDelegations(item, currentRecipeFile, stack, options)),
|
|
779
|
+
};
|
|
780
|
+
}
|
|
781
|
+
if (record.template && typeof record.template === "object") {
|
|
782
|
+
return {
|
|
783
|
+
...record,
|
|
784
|
+
template: expandRecipeDelegations(record.template, currentRecipeFile, stack, options),
|
|
785
|
+
};
|
|
786
|
+
}
|
|
787
|
+
return value;
|
|
788
|
+
}
|
|
789
|
+
function getDirectDelegatedRecipe(value, currentRecipeFile, stack, options = {}) {
|
|
790
|
+
if (typeof value === "string")
|
|
791
|
+
return loadDelegatedRecipe(value, currentRecipeFile, stack, options);
|
|
792
|
+
if (!Array.isArray(value) && typeof value.template === "string") {
|
|
793
|
+
return loadDelegatedRecipe(value.template, currentRecipeFile, stack, options);
|
|
794
|
+
}
|
|
795
|
+
return undefined;
|
|
796
|
+
}
|
|
797
|
+
function resolveDirectDelegationArgs(delegated, wrapperArgs, wrapperDefaults) {
|
|
798
|
+
if (!Array.isArray(delegated.args))
|
|
799
|
+
return Array.isArray(wrapperArgs) ? wrapperArgs.map(String) : undefined;
|
|
800
|
+
const delegatedSpec = Schema.parseToolArgDeclarationList(delegated.args);
|
|
801
|
+
if (delegatedSpec.error)
|
|
802
|
+
throw new Error(delegatedSpec.error);
|
|
803
|
+
const wrapperDeclarations = Array.isArray(wrapperArgs)
|
|
804
|
+
? wrapperArgs.map(String)
|
|
805
|
+
: [];
|
|
806
|
+
const wrapperSpec = Schema.parseToolArgDeclarationList(wrapperDeclarations);
|
|
807
|
+
if (wrapperSpec.error)
|
|
808
|
+
throw new Error(wrapperSpec.error);
|
|
809
|
+
const declared = new Set(delegatedSpec.args);
|
|
810
|
+
for (const arg of wrapperSpec.args) {
|
|
811
|
+
if (!declared.has(arg))
|
|
812
|
+
throw new Error(`Unknown delegated Recipe argument: ${arg}`);
|
|
813
|
+
}
|
|
814
|
+
Schema.assertCompatibleToolArgTypes(delegatedSpec.argTypes, wrapperSpec.argTypes);
|
|
815
|
+
assertRecipeDefaultsDeclared(delegated.args, wrapperDefaults, "delegated Recipe default");
|
|
816
|
+
Schema.normalizeRuntimeValues(Object.fromEntries(Object.entries(wrapperDefaults ?? {}).filter(([, value]) => typeof value !== "string" || !/\{[^{}]+\}/.test(value))), delegatedSpec.argTypes);
|
|
817
|
+
return delegated.args;
|
|
818
|
+
}
|
|
819
|
+
function expandImportNodes(value, imports, options = {}) {
|
|
820
|
+
if (typeof value === "string")
|
|
821
|
+
return value;
|
|
822
|
+
if (Array.isArray(value)) {
|
|
823
|
+
return value.map((item) => expandImportNodes(item, imports, options));
|
|
824
|
+
}
|
|
825
|
+
const record = value;
|
|
826
|
+
const importAlias = !Object.hasOwn(record, "template") && typeof record.name === "string"
|
|
827
|
+
? record.name
|
|
828
|
+
: undefined;
|
|
829
|
+
if (importAlias) {
|
|
830
|
+
const imported = imports[importAlias];
|
|
831
|
+
if (!imported)
|
|
832
|
+
throw new Error(`Unknown recipe import: ${importAlias}`);
|
|
833
|
+
const nodeDefaults = isRecord(record.defaults)
|
|
834
|
+
? record.defaults
|
|
835
|
+
: undefined;
|
|
836
|
+
const nodeValues = isRecord(record.values) ? record.values : undefined;
|
|
837
|
+
const defaults = resolveRecipeValueLayers(imported.config.args, imported.defaults, imported.values, nodeDefaults, nodeValues);
|
|
838
|
+
const expanded = applyDefaultsToTemplate(imported.config.template, defaults, record);
|
|
839
|
+
return options.includeActorRecipeContext
|
|
840
|
+
? withActorRecipeContext(expanded, {
|
|
841
|
+
alias: imported.alias,
|
|
842
|
+
file: imported.file,
|
|
843
|
+
name: imported.name,
|
|
844
|
+
path: imported.alias,
|
|
845
|
+
role: "import",
|
|
846
|
+
})
|
|
847
|
+
: expanded;
|
|
848
|
+
}
|
|
849
|
+
if (Array.isArray(record.template)) {
|
|
850
|
+
return {
|
|
851
|
+
...record,
|
|
852
|
+
template: record.template.map((item) => expandImportNodes(item, imports, options)),
|
|
853
|
+
};
|
|
854
|
+
}
|
|
855
|
+
if (record.template && typeof record.template === "object") {
|
|
856
|
+
return {
|
|
857
|
+
...record,
|
|
858
|
+
template: expandImportNodes(record.template, imports, options),
|
|
859
|
+
};
|
|
860
|
+
}
|
|
861
|
+
return value;
|
|
862
|
+
}
|
|
863
|
+
export function readResolvedRecipeConfig(file, stack = [], options = {}) {
|
|
864
|
+
const path = resolveRecipePath(file, stack.length > 0 ? dirname(stack.at(-1)) : Paths.getRecipeRoot());
|
|
865
|
+
if (stack.includes(path)) {
|
|
866
|
+
throw new Error(`Cyclic recipe import: ${[...stack, path].join(" -> ")}`);
|
|
867
|
+
}
|
|
868
|
+
if (stack.length >= MAX_RECIPE_IMPORT_DEPTH) {
|
|
869
|
+
throw new Error(`Recipe import depth exceeds limit ${MAX_RECIPE_IMPORT_DEPTH}: ${[...stack, path].join(" -> ")}`);
|
|
870
|
+
}
|
|
871
|
+
const raw = options.authoredEntry?.path === path
|
|
872
|
+
? options.authoredEntry.recipe
|
|
873
|
+
: readRawRecipeConfig(path);
|
|
874
|
+
if (!raw || !Object.hasOwn(raw, "template"))
|
|
875
|
+
return undefined;
|
|
876
|
+
assertRecipeHasNoDeclaredName(raw);
|
|
877
|
+
RecipeControl.assertRecipeHasNoMailbox(raw);
|
|
878
|
+
assertRuntimeRecipeValuesNotDeclared(raw);
|
|
879
|
+
assertRecipeArgumentContract(raw);
|
|
880
|
+
const imports = {};
|
|
881
|
+
for (const [alias, binding] of Object.entries(getRecipeImports(raw))) {
|
|
882
|
+
const importPath = resolveRecipeImportPath(getImportFrom(binding), dirname(path), options.skillContext ?? EMPTY_ACTIVE_SKILL_RECIPE_CONTEXT);
|
|
883
|
+
const config = readResolvedRecipeConfig(importPath, [...stack, path], options);
|
|
884
|
+
if (!config)
|
|
885
|
+
throw new Error(`Recipe import not found: ${alias}`);
|
|
886
|
+
const bindingDefaults = typeof binding === "string" ? undefined : binding.defaults;
|
|
887
|
+
const bindingValues = typeof binding === "string" ? undefined : binding.values;
|
|
888
|
+
assertRecipeDefaultsDeclared(config.args, bindingDefaults, `Recipe import ${alias} default`);
|
|
889
|
+
imports[alias] = {
|
|
890
|
+
alias,
|
|
891
|
+
file: importPath,
|
|
892
|
+
name: getRecipeIdFromPath(importPath),
|
|
893
|
+
config,
|
|
894
|
+
defaults: { ...(config.defaults ?? {}), ...(bindingDefaults ?? {}) },
|
|
895
|
+
values: {
|
|
896
|
+
...(bindingValues ?? {}),
|
|
897
|
+
...(config.recipe_dir ? { recipe_dir: config.recipe_dir } : {}),
|
|
898
|
+
...(config.skill_dir ? { skill_dir: config.skill_dir } : {}),
|
|
899
|
+
},
|
|
900
|
+
};
|
|
901
|
+
}
|
|
902
|
+
const substituted = substituteImportRefs(raw, imports);
|
|
903
|
+
const template = getRecipeCommandTemplate(substituted);
|
|
904
|
+
if (!template)
|
|
905
|
+
return undefined;
|
|
906
|
+
const expandedImportsTemplate = expandImportNodes(template, imports, options);
|
|
907
|
+
const delegated = getDirectDelegatedRecipe(expandedImportsTemplate, path, stack, options);
|
|
908
|
+
const expandedTemplate = delegated
|
|
909
|
+
? applyDelegatedRecipeToNode(delegated, typeof expandedImportsTemplate === "object" &&
|
|
910
|
+
!Array.isArray(expandedImportsTemplate)
|
|
911
|
+
? expandedImportsTemplate
|
|
912
|
+
: {})
|
|
913
|
+
: expandRecipeDelegations(expandedImportsTemplate, path, stack, options);
|
|
914
|
+
const recipeName = getRecipeIdFromPath(path);
|
|
915
|
+
const recipeDir = dirname(path);
|
|
916
|
+
const skillDir = findOwningSkillDir(path);
|
|
917
|
+
if (!skillDir &&
|
|
918
|
+
JSON.stringify({
|
|
919
|
+
artifacts: substituted.artifacts,
|
|
920
|
+
defaults: substituted.defaults,
|
|
921
|
+
template: substituted.template,
|
|
922
|
+
values: substituted.values,
|
|
923
|
+
}).includes("{skill_dir}")) {
|
|
924
|
+
throw new Error(`Recipe uses {skill_dir} outside an owning Skill directory: ${path}`);
|
|
925
|
+
}
|
|
926
|
+
const templateWithContext = options.includeActorRecipeContext
|
|
927
|
+
? withActorRecipeContext(expandedTemplate, {
|
|
928
|
+
file: path,
|
|
929
|
+
name: recipeName,
|
|
930
|
+
path: recipeName,
|
|
931
|
+
role: stack.length > 0 ? "import" : "entry",
|
|
932
|
+
})
|
|
933
|
+
: expandedTemplate;
|
|
934
|
+
const wrapperDefaults = isRecord(substituted.defaults)
|
|
935
|
+
? substituted.defaults
|
|
936
|
+
: undefined;
|
|
937
|
+
const mergedDefaults = mergeDefaults(delegated?.defaults, wrapperDefaults);
|
|
938
|
+
const effectiveArgs = delegated
|
|
939
|
+
? resolveDirectDelegationArgs(delegated, substituted.args, wrapperDefaults)
|
|
940
|
+
: Array.isArray(substituted.args)
|
|
941
|
+
? substituted.args
|
|
942
|
+
: undefined;
|
|
943
|
+
const artifactSource = isRecord(substituted.artifacts)
|
|
944
|
+
? substituted.artifacts
|
|
945
|
+
: delegated?.artifacts;
|
|
946
|
+
const control = RecipeControl.normalizeRecipeControl(Object.hasOwn(substituted, "control")
|
|
947
|
+
? substituted.control
|
|
948
|
+
: delegated?.control);
|
|
949
|
+
return {
|
|
950
|
+
name: recipeName,
|
|
951
|
+
recipe_dir: recipeDir,
|
|
952
|
+
...(skillDir ? { skill_dir: skillDir } : {}),
|
|
953
|
+
...(typeof substituted.description === "string" &&
|
|
954
|
+
substituted.description.trim()
|
|
955
|
+
? { description: substituted.description.trim() }
|
|
956
|
+
: typeof delegated?.description === "string"
|
|
957
|
+
? { description: delegated.description }
|
|
958
|
+
: {}),
|
|
959
|
+
...(typeof substituted.disabled === "boolean"
|
|
960
|
+
? { disabled: substituted.disabled }
|
|
961
|
+
: typeof delegated?.disabled === "boolean"
|
|
962
|
+
? { disabled: delegated.disabled }
|
|
963
|
+
: {}),
|
|
964
|
+
...(substituted.async === true
|
|
965
|
+
? { async: true }
|
|
966
|
+
: substituted.async === false
|
|
967
|
+
? { async: false }
|
|
968
|
+
: delegated?.async === true
|
|
969
|
+
? { async: true }
|
|
970
|
+
: delegated?.async === false
|
|
971
|
+
? { async: false }
|
|
972
|
+
: {}),
|
|
973
|
+
...(substituted.singleton === true || delegated?.singleton === true
|
|
974
|
+
? {
|
|
975
|
+
singleton: true,
|
|
976
|
+
singleton_run_id: delegated?.singleton === true
|
|
977
|
+
? delegated.singleton_run_id
|
|
978
|
+
: skillDir
|
|
979
|
+
? basename(skillDir)
|
|
980
|
+
: undefined,
|
|
981
|
+
singleton_recipe_id: delegated?.singleton === true
|
|
982
|
+
? delegated.singleton_recipe_id
|
|
983
|
+
: skillDir
|
|
984
|
+
? `${basename(skillDir)}/${recipeName}`
|
|
985
|
+
: undefined,
|
|
986
|
+
}
|
|
987
|
+
: {}),
|
|
988
|
+
...(Object.keys(imports).length > 0
|
|
989
|
+
? { imports: getRecipeImports(raw) }
|
|
990
|
+
: {}),
|
|
991
|
+
template: templateWithContext,
|
|
992
|
+
...(effectiveArgs ? { args: effectiveArgs } : {}),
|
|
993
|
+
...(mergedDefaults ? { defaults: mergedDefaults } : {}),
|
|
994
|
+
...(typeof substituted.parallel === "boolean"
|
|
995
|
+
? { parallel: substituted.parallel }
|
|
996
|
+
: {}),
|
|
997
|
+
...(typeof substituted.concurrency === "number" ||
|
|
998
|
+
typeof substituted.concurrency === "string"
|
|
999
|
+
? { concurrency: substituted.concurrency }
|
|
1000
|
+
: {}),
|
|
1001
|
+
...(typeof substituted.min_successful === "number" ||
|
|
1002
|
+
typeof substituted.min_successful === "string"
|
|
1003
|
+
? { min_successful: substituted.min_successful }
|
|
1004
|
+
: {}),
|
|
1005
|
+
...(typeof substituted.label === "string"
|
|
1006
|
+
? { label: substituted.label }
|
|
1007
|
+
: {}),
|
|
1008
|
+
...(typeof substituted.when === "string" ||
|
|
1009
|
+
typeof substituted.when === "boolean"
|
|
1010
|
+
? { when: substituted.when }
|
|
1011
|
+
: {}),
|
|
1012
|
+
...(typeof substituted.timeout === "number" ||
|
|
1013
|
+
typeof substituted.timeout === "string"
|
|
1014
|
+
? { timeout: substituted.timeout }
|
|
1015
|
+
: {}),
|
|
1016
|
+
...(typeof substituted.delay === "number" ||
|
|
1017
|
+
typeof substituted.delay === "string"
|
|
1018
|
+
? { delay: substituted.delay }
|
|
1019
|
+
: {}),
|
|
1020
|
+
...(substituted.accept_output === "review_evidence"
|
|
1021
|
+
? { accept_output: substituted.accept_output }
|
|
1022
|
+
: {}),
|
|
1023
|
+
...(typeof substituted.output === "string"
|
|
1024
|
+
? { output: substituted.output }
|
|
1025
|
+
: {}),
|
|
1026
|
+
...(isRecord(artifactSource)
|
|
1027
|
+
? {
|
|
1028
|
+
artifacts: Object.fromEntries(Object.entries(artifactSource).filter((entry) => typeof entry[1] === "string")),
|
|
1029
|
+
}
|
|
1030
|
+
: {}),
|
|
1031
|
+
...(control !== undefined ? { control } : {}),
|
|
1032
|
+
...(substituted.retire_when === "children_terminal" ||
|
|
1033
|
+
delegated?.retire_when === "children_terminal"
|
|
1034
|
+
? { retire_when: "children_terminal" }
|
|
1035
|
+
: {}),
|
|
1036
|
+
...(typeof substituted.retry === "number" ||
|
|
1037
|
+
typeof substituted.retry === "string"
|
|
1038
|
+
? { retry: substituted.retry }
|
|
1039
|
+
: {}),
|
|
1040
|
+
...(substituted.failure === "continue" ||
|
|
1041
|
+
substituted.failure === "branch" ||
|
|
1042
|
+
substituted.failure === "root"
|
|
1043
|
+
? { failure: substituted.failure }
|
|
1044
|
+
: {}),
|
|
1045
|
+
...(substituted.recover !== undefined
|
|
1046
|
+
? { recover: substituted.recover }
|
|
1047
|
+
: {}),
|
|
1048
|
+
...(typeof substituted.repeat === "number"
|
|
1049
|
+
? { repeat: substituted.repeat }
|
|
1050
|
+
: {}),
|
|
1051
|
+
values: {
|
|
1052
|
+
...(isRecord(substituted.values) ? substituted.values : {}),
|
|
1053
|
+
recipe_dir: recipeDir,
|
|
1054
|
+
...(skillDir ? { skill_dir: skillDir } : {}),
|
|
1055
|
+
},
|
|
1056
|
+
...(isRecord(substituted.usage) ? { usage: substituted.usage } : {}),
|
|
1057
|
+
};
|
|
1058
|
+
}
|
|
1059
|
+
function collectRecipeContextRecords(file, stack, importPath, context, alias) {
|
|
1060
|
+
const path = resolveRecipePath(file, stack.length > 0 ? dirname(stack.at(-1)) : Paths.getRecipeRoot());
|
|
1061
|
+
if (stack.includes(path)) {
|
|
1062
|
+
throw new Error(`Cyclic recipe import: ${[...stack, path].join(" -> ")}`);
|
|
1063
|
+
}
|
|
1064
|
+
if (stack.length >= MAX_RECIPE_IMPORT_DEPTH) {
|
|
1065
|
+
throw new Error(`Recipe import depth exceeds limit ${MAX_RECIPE_IMPORT_DEPTH}: ${[...stack, path].join(" -> ")}`);
|
|
1066
|
+
}
|
|
1067
|
+
const raw = readRawRecipeConfig(path);
|
|
1068
|
+
if (!raw || !Object.hasOwn(raw, "template"))
|
|
1069
|
+
return [];
|
|
1070
|
+
assertRecipeHasNoDeclaredName(raw);
|
|
1071
|
+
const qualifiedName = qualifiedRecipeNameForFile(path, context);
|
|
1072
|
+
const skill = qualifiedName?.split("/", 1)[0];
|
|
1073
|
+
const record = {
|
|
1074
|
+
...(alias ? { alias } : {}),
|
|
1075
|
+
depth: stack.length,
|
|
1076
|
+
import_path: importPath,
|
|
1077
|
+
logical_reference: qualifiedName ?? basename(path),
|
|
1078
|
+
name: getRecipeIdFromPath(path),
|
|
1079
|
+
recipe: raw,
|
|
1080
|
+
role: stack.length === 0 ? "entry" : "import",
|
|
1081
|
+
...(skill ? { skill } : {}),
|
|
1082
|
+
source_file: path,
|
|
1083
|
+
source_kind: qualifiedName
|
|
1084
|
+
? "active_skill_component"
|
|
1085
|
+
: "explicit_file_recipe",
|
|
1086
|
+
};
|
|
1087
|
+
const imports = getRecipeImports(raw);
|
|
1088
|
+
const children = Object.entries(imports).flatMap(([childAlias, binding]) => {
|
|
1089
|
+
const importFile = resolveRecipeImportPath(getImportFrom(binding), dirname(path), context);
|
|
1090
|
+
return collectRecipeContextRecords(importFile, [...stack, path], [...importPath, childAlias], context, childAlias);
|
|
1091
|
+
});
|
|
1092
|
+
return [record, ...children];
|
|
1093
|
+
}
|
|
1094
|
+
export function buildRecipeContextRecords(file, context = EMPTY_ACTIVE_SKILL_RECIPE_CONTEXT) {
|
|
1095
|
+
return collectRecipeContextRecords(file, [], [], context);
|
|
1096
|
+
}
|
|
1097
|
+
export function getRecipeTemplate(value) {
|
|
1098
|
+
return readRecipeConfig(value)?.template;
|
|
1099
|
+
}
|
|
1100
|
+
export function isRecipeReference(value) {
|
|
1101
|
+
return getRecipePath(value) !== undefined;
|
|
1102
|
+
}
|
|
1103
|
+
export function isAsyncRecipeReference(value) {
|
|
1104
|
+
return readRecipeConfig(value)?.async === true;
|
|
1105
|
+
}
|
|
1106
|
+
export function isRecipeTool(template, recipe) {
|
|
1107
|
+
return recipe !== undefined || isRecipeReference(template);
|
|
1108
|
+
}
|