@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,57 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: music-player
|
|
3
|
+
description: Use for starting, resuming, inspecting, and controlling one persistent local music playback actor from caller-approved files, directories, URLs, or playlists.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Music Player
|
|
7
|
+
|
|
8
|
+
Use this Skill for one local music playback service. For generic Recipe execution, singleton Run lifecycle, persistent-tool setup, or diagnosis, follow `actors`; this Skill owns only playback-specific selection and controls.
|
|
9
|
+
|
|
10
|
+
## Interaction Routing
|
|
11
|
+
|
|
12
|
+
When a Telegram-originated turn or explicit Telegram-control question makes repeated player controls relevant, prefer the maintained Telegram view described below over synthesizing one-shot prompt buttons. If `telegram_bind` is available, load and follow the active operating guidance that owns Generative Apps, then bind or invoke the capability-owned adapter; do not re-author it or move playback authority into the view. If the runtime is unavailable or binding fails, report that boundary and fall back to ordinary model-mediated controls.
|
|
13
|
+
|
|
14
|
+
## Playback
|
|
15
|
+
|
|
16
|
+
`music-player/playback` is a singleton async controlled service with the canonical address `run:music-player`. The Recipe is the sole lifecycle owner: it starts the service, supervises it, and stops playback when the Run closes. The service owns queue, backend, checkpoint, and playback state. `playback-client.mjs` is a pure actor-neutral RPC client; it never starts, adopts, supervises, or signals a service. The executable also supports explicit foreground `serve` for development or a caller-owned standalone host, but Actor and standalone ownership of one state directory are mutually exclusive.
|
|
17
|
+
|
|
18
|
+
```text
|
|
19
|
+
spawn recipe=music-player/playback values={"source":"~/Music","player":"auto"}
|
|
20
|
+
message target=run:music-player action=pause
|
|
21
|
+
message target=run:music-player action=next
|
|
22
|
+
inspect target=run:music-player view=control
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
A repeated compatible spawn returns the healthy active singleton instead of launching a second player. A terminal or dead singleton restarts under the same Run id with a fresh fenced generation and restores its validated playback checkpoint when the source and configuration still match.
|
|
26
|
+
|
|
27
|
+
## Controls
|
|
28
|
+
|
|
29
|
+
Use only declared actions: `play`, `pause`, `resume`, `toggle`, `next`, `previous`, `seek`, `volume`, `stop`, and `status`.
|
|
30
|
+
|
|
31
|
+
- `play` and `resume` continue the current checkpointed track selection.
|
|
32
|
+
- `next` and `previous` update the checkpoint before the next backend launch.
|
|
33
|
+
- `seek` accepts Control input `{ "percent": 0..100 }`, resolves the current track duration, and restarts a supported backend at that percentage while preserving track identity and paused/playing intent. It fails when duration or backend seeking is unavailable.
|
|
34
|
+
- `volume` accepts Control input `{ "percent": 0..100 }` and sets any integer percentage. On Linux with WirePlumber, the helper resolves the exact current playback stream by process identity and changes its volume in place so the track continues; when no safe in-place control exists, it restarts the current track under the new volume while preserving paused/playing intent. UI adapters may expose coarse relative steps but must send the resolved absolute percentage.
|
|
35
|
+
- `status` is read-only and exposes bounded machine-readable player state, including the current absolute volume and a duration-derived progress percentage projected at read time.
|
|
36
|
+
- `stop` ends the live process without silently deleting the saved queue.
|
|
37
|
+
|
|
38
|
+
External local views use the actor-neutral playback client against the canonical service state directory. They must not read or edit Run files, signal playback processes, construct Actor Control records, or import pi-actors internals. The client validates bounded commands, exact service generation, structured responses, and active endpoint ownership before returning success.
|
|
39
|
+
|
|
40
|
+
## Maintained Telegram View
|
|
41
|
+
|
|
42
|
+
> [!NOTE]
|
|
43
|
+
> This Skill includes a ready Music Player Generative App at `genapps/music-player.mjs`. When `telegram_bind` is available and Telegram interaction is relevant, use it to copy and install the app as `music-player`; hot replacement keeps the same app name with `replace: true`.
|
|
44
|
+
|
|
45
|
+
Bind with absolute `control`, `stateDir`, and `node` arguments. The adapter reports whether the Actor control surface is actually available. Every mutating button queues a canonical Actor Control through `playback.mjs` and waits for that exact record to become handled or failed, so terminal evidence remains visible in the Run inspector and failures reach Telegram; bounded status projection is read-only. The adapter neither imports extension internals nor starts playback. Its stopped-state Start button returns to Pi so the composition root can spawn `music-player/playback`, while active controls remain deterministic Generative App actions that bypass the model. `pi-telegram` owns only the generic Generative App runtime.
|
|
46
|
+
|
|
47
|
+
## Sources And Backends
|
|
48
|
+
|
|
49
|
+
- `source` must name caller-approved local music, a readable directory, a playlist file, a URL, or an explicit `|`-separated list. Do not broaden it to unrelated directories.
|
|
50
|
+
- Directory and playlist resolution is owned by the playback helper; there is no separate public playlist Recipe.
|
|
51
|
+
- `player=auto` selects an available supported backend. Do not install or substitute a player silently.
|
|
52
|
+
- The checkpoint preserves source, resolved queue, current index/track, loop, volume, backend, and playback state. It does not promise within-track position restoration unless the selected backend can prove it.
|
|
53
|
+
- A changed source rebuilds the queue. Missing or corrupt checkpoint data fails visibly or rebuilds only under the helper's explicit recovery contract; never claim continuity without evidence.
|
|
54
|
+
|
|
55
|
+
## Stop Rules
|
|
56
|
+
|
|
57
|
+
Stop if the source is missing, unreadable, contains no playable audio, or no supported backend is available. Do not claim playback from process start alone; confirm through Run evidence or `status`. Prefer the declared `stop` action for a responsive player. If the service is unresponsive, return to `actors` for bounded Run recovery rather than shell process control.
|
|
@@ -0,0 +1,360 @@
|
|
|
1
|
+
import { basename, dirname, isAbsolute } from "node:path";
|
|
2
|
+
|
|
3
|
+
const ACTIONS = new Set([
|
|
4
|
+
"play",
|
|
5
|
+
"pause",
|
|
6
|
+
"resume",
|
|
7
|
+
"toggle",
|
|
8
|
+
"next",
|
|
9
|
+
"previous",
|
|
10
|
+
"stop",
|
|
11
|
+
]);
|
|
12
|
+
|
|
13
|
+
function requireAdapter(argument) {
|
|
14
|
+
if (!argument || typeof argument !== "object" || Array.isArray(argument)) {
|
|
15
|
+
throw new Error("music-player init requires an object argument");
|
|
16
|
+
}
|
|
17
|
+
const control = typeof argument.control === "string" ? argument.control : "";
|
|
18
|
+
const stateDir = typeof argument.stateDir === "string" ? argument.stateDir : "";
|
|
19
|
+
const node = typeof argument.node === "string" ? argument.node : process.execPath;
|
|
20
|
+
if (!isAbsolute(control) || !control.endsWith("playback.mjs")) {
|
|
21
|
+
throw new Error("music-player control must be an absolute playback.mjs path");
|
|
22
|
+
}
|
|
23
|
+
if (!isAbsolute(stateDir)) {
|
|
24
|
+
throw new Error("music-player stateDir must be an absolute path");
|
|
25
|
+
}
|
|
26
|
+
if (!isAbsolute(node)) {
|
|
27
|
+
throw new Error("music-player node executable must be an absolute path");
|
|
28
|
+
}
|
|
29
|
+
return { control, node, stateDir };
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function inline(value) {
|
|
33
|
+
return String(value ?? "").replaceAll("`", "'");
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function normalizePlayback(status) {
|
|
37
|
+
const actorAvailable = status.actor_available === true;
|
|
38
|
+
if (!actorAvailable) {
|
|
39
|
+
return {
|
|
40
|
+
actorAvailable: false,
|
|
41
|
+
count: null,
|
|
42
|
+
index: null,
|
|
43
|
+
pid: "",
|
|
44
|
+
player: "",
|
|
45
|
+
progressPercent: null,
|
|
46
|
+
seekPercent: 0,
|
|
47
|
+
state: "inactive",
|
|
48
|
+
track: "",
|
|
49
|
+
updatedAt: typeof status.updated_at === "string" ? status.updated_at : "",
|
|
50
|
+
volume: null,
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
return {
|
|
54
|
+
actorAvailable: true,
|
|
55
|
+
state: typeof status.state === "string" ? status.state : "unknown",
|
|
56
|
+
index: Number.isInteger(status.index) ? status.index : null,
|
|
57
|
+
count: Number.isInteger(status.count) ? status.count : null,
|
|
58
|
+
track: typeof status.track === "string" ? status.track : "",
|
|
59
|
+
player: typeof status.player === "string" ? status.player : "",
|
|
60
|
+
volume: Number.isInteger(status.volume) ? status.volume : null,
|
|
61
|
+
seekPercent: Number.isInteger(status.seek_percent) ? status.seek_percent : 0,
|
|
62
|
+
progressPercent: Number.isInteger(status.progress_percent) ? status.progress_percent : null,
|
|
63
|
+
pid: typeof status.pid === "string" || typeof status.pid === "number"
|
|
64
|
+
? String(status.pid)
|
|
65
|
+
: "",
|
|
66
|
+
updatedAt: typeof status.updated_at === "string" ? status.updated_at : "",
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
async function readPlayback(adapter, run) {
|
|
71
|
+
const result = await run({
|
|
72
|
+
command: adapter.node,
|
|
73
|
+
args: [adapter.control, "status", adapter.stateDir],
|
|
74
|
+
cwd: dirname(adapter.control),
|
|
75
|
+
timeoutMs: 5_000,
|
|
76
|
+
});
|
|
77
|
+
if (result.code !== 0) {
|
|
78
|
+
throw new Error(`music-player status failed: ${result.stderr.trim() || `exit ${result.code}`}`);
|
|
79
|
+
}
|
|
80
|
+
let status;
|
|
81
|
+
try {
|
|
82
|
+
status = JSON.parse(result.stdout);
|
|
83
|
+
} catch {
|
|
84
|
+
throw new Error("music-player status returned invalid JSON");
|
|
85
|
+
}
|
|
86
|
+
if (!status || typeof status !== "object" || Array.isArray(status)) {
|
|
87
|
+
throw new Error("music-player status returned an invalid object");
|
|
88
|
+
}
|
|
89
|
+
return normalizePlayback(status);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function withPlayback(state, playback) {
|
|
93
|
+
return { version: 1, adapter: state.adapter, playback };
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function mainControls(playback) {
|
|
97
|
+
if (!playback.actorAvailable || playback.state === "stopped" || playback.state === "unknown") {
|
|
98
|
+
return [
|
|
99
|
+
[{ label: "▶ Start", prompt: "Start the music player", selected_style: "success" }],
|
|
100
|
+
[{ label: "🔄 Status", prompt: "music-player::status", selected_style: "primary" }],
|
|
101
|
+
];
|
|
102
|
+
}
|
|
103
|
+
const primary = playback.state === "paused"
|
|
104
|
+
? { label: "▶ Play", prompt: "music-player::resume", selected_style: "success" }
|
|
105
|
+
: { label: "⏸ Pause", prompt: "music-player::pause", selected_style: "primary" };
|
|
106
|
+
const percentages = [0, 15, 30, 45, 60, 75, 90];
|
|
107
|
+
const seek = percentages.map((percent) => ({
|
|
108
|
+
label: percent === 0 ? "P0" : String(percent),
|
|
109
|
+
prompt: `music-player::seek_percent(${percent})`,
|
|
110
|
+
selected_style: percent === 0 ? "primary" : "success",
|
|
111
|
+
}));
|
|
112
|
+
const volume = percentages.map((percent) => ({
|
|
113
|
+
label: percent === 0 ? "V0" : String(percent),
|
|
114
|
+
prompt: `music-player::volume(${percent})`,
|
|
115
|
+
selected_style: percent === 0 ? "primary" : "success",
|
|
116
|
+
}));
|
|
117
|
+
return [
|
|
118
|
+
seek,
|
|
119
|
+
volume,
|
|
120
|
+
[
|
|
121
|
+
{ label: "⏮ Previous", prompt: "music-player::previous", selected_style: "primary" },
|
|
122
|
+
primary,
|
|
123
|
+
{ label: "⏭ Next", prompt: "music-player::next", selected_style: "success" },
|
|
124
|
+
],
|
|
125
|
+
[
|
|
126
|
+
{ label: "⏹ Stop", prompt: "music-player::stop", selected_style: "danger" },
|
|
127
|
+
{ label: "🔄 Status", prompt: "music-player::status", selected_style: "primary" },
|
|
128
|
+
],
|
|
129
|
+
];
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
function playbackLines(playback) {
|
|
133
|
+
const track = playback.track ? basename(playback.track) : "—";
|
|
134
|
+
const index = playback.index === null ? "—" : playback.index + 1;
|
|
135
|
+
const count = playback.count === null ? "—" : playback.count;
|
|
136
|
+
return [
|
|
137
|
+
`- **Actor:** \`${playback.actorAvailable ? "available" : "unavailable"}\``,
|
|
138
|
+
`- **State:** \`${inline(playback.state)}\``,
|
|
139
|
+
`- **Progress:** \`${playback.progressPercent === null ? "—" : `${playback.progressPercent}%`}\``,
|
|
140
|
+
`- **Volume:** \`${playback.volume === null ? "—" : `${playback.volume}%`}\``,
|
|
141
|
+
`- **Backend:** \`${inline(playback.player || "—")}\``,
|
|
142
|
+
`- **Queue:** \`${index}/${count}\``,
|
|
143
|
+
`- **Track:** \`${inline(track)}\``,
|
|
144
|
+
];
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
function render(playback) {
|
|
148
|
+
return [
|
|
149
|
+
"**🎵 Music Player**",
|
|
150
|
+
"",
|
|
151
|
+
...playbackLines(playback),
|
|
152
|
+
"",
|
|
153
|
+
`<!-- telegram_button ${JSON.stringify(mainControls(playback))} -->`,
|
|
154
|
+
].join("\n");
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
async function waitForTransition(adapter, run, before, action) {
|
|
158
|
+
for (let attempt = 0; attempt < 20; attempt += 1) {
|
|
159
|
+
const playback = await readPlayback(adapter, run);
|
|
160
|
+
const changed = action === "stop"
|
|
161
|
+
? playback.state === "stopped"
|
|
162
|
+
: action === "pause"
|
|
163
|
+
? playback.state === "paused"
|
|
164
|
+
: action === "play" || action === "resume"
|
|
165
|
+
? playback.state === "playing"
|
|
166
|
+
: action === "toggle"
|
|
167
|
+
? playback.state !== before.state
|
|
168
|
+
: playback.index !== before.index || playback.track !== before.track;
|
|
169
|
+
if (changed) return playback;
|
|
170
|
+
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
171
|
+
}
|
|
172
|
+
return await readPlayback(adapter, run);
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
function normalizeAbsoluteVolume(argument) {
|
|
176
|
+
const candidate =
|
|
177
|
+
argument && typeof argument === "object" && !Array.isArray(argument)
|
|
178
|
+
? argument.percent
|
|
179
|
+
: argument;
|
|
180
|
+
if (!Number.isInteger(candidate) || candidate < 0 || candidate > 100) {
|
|
181
|
+
throw new Error("music-player volume requires an integer percent 0..100");
|
|
182
|
+
}
|
|
183
|
+
return candidate;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
async function applyVolume(percent, context) {
|
|
187
|
+
const result = await context.run({
|
|
188
|
+
command: context.state.adapter.node,
|
|
189
|
+
args: [
|
|
190
|
+
context.state.adapter.control,
|
|
191
|
+
"volume",
|
|
192
|
+
context.state.adapter.stateDir,
|
|
193
|
+
String(percent),
|
|
194
|
+
],
|
|
195
|
+
cwd: dirname(context.state.adapter.control),
|
|
196
|
+
timeoutMs: 5_000,
|
|
197
|
+
});
|
|
198
|
+
if (result.code !== 0) {
|
|
199
|
+
throw new Error(`music-player volume failed: ${result.stderr.trim() || `exit ${result.code}`}`);
|
|
200
|
+
}
|
|
201
|
+
let playback;
|
|
202
|
+
for (let attempt = 0; attempt < 20; attempt += 1) {
|
|
203
|
+
playback = await readPlayback(context.state.adapter, context.run);
|
|
204
|
+
if (playback.volume === percent) break;
|
|
205
|
+
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
206
|
+
}
|
|
207
|
+
playback ??= await readPlayback(context.state.adapter, context.run);
|
|
208
|
+
return {
|
|
209
|
+
state: withPlayback(context.state, playback),
|
|
210
|
+
output: render(playback),
|
|
211
|
+
viewMode: "edit",
|
|
212
|
+
};
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
function normalizeSeekPercent(argument) {
|
|
216
|
+
if (!Number.isInteger(argument) || argument < 0 || argument > 100) {
|
|
217
|
+
throw new Error("music-player seek requires an integer percent 0..100");
|
|
218
|
+
}
|
|
219
|
+
return argument;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
async function applySeek(percent, context) {
|
|
223
|
+
const result = await context.run({
|
|
224
|
+
command: context.state.adapter.node,
|
|
225
|
+
args: [
|
|
226
|
+
context.state.adapter.control,
|
|
227
|
+
"seek",
|
|
228
|
+
context.state.adapter.stateDir,
|
|
229
|
+
String(percent),
|
|
230
|
+
],
|
|
231
|
+
cwd: dirname(context.state.adapter.control),
|
|
232
|
+
timeoutMs: 5_000,
|
|
233
|
+
});
|
|
234
|
+
if (result.code !== 0) {
|
|
235
|
+
throw new Error(`music-player seek failed: ${result.stderr.trim() || `exit ${result.code}`}`);
|
|
236
|
+
}
|
|
237
|
+
let playback;
|
|
238
|
+
for (let attempt = 0; attempt < 20; attempt += 1) {
|
|
239
|
+
playback = await readPlayback(context.state.adapter, context.run);
|
|
240
|
+
if (playback.seekPercent === percent && playback.pid) break;
|
|
241
|
+
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
242
|
+
}
|
|
243
|
+
playback ??= await readPlayback(context.state.adapter, context.run);
|
|
244
|
+
return {
|
|
245
|
+
state: withPlayback(context.state, playback),
|
|
246
|
+
output: render(playback),
|
|
247
|
+
viewMode: "edit",
|
|
248
|
+
};
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
async function apply(action, context) {
|
|
252
|
+
if (!ACTIONS.has(action)) throw new Error(`unsupported music-player action: ${action}`);
|
|
253
|
+
const before = await readPlayback(context.state.adapter, context.run);
|
|
254
|
+
const result = await context.run({
|
|
255
|
+
command: context.state.adapter.node,
|
|
256
|
+
args: [context.state.adapter.control, action, context.state.adapter.stateDir],
|
|
257
|
+
cwd: dirname(context.state.adapter.control),
|
|
258
|
+
timeoutMs: 5_000,
|
|
259
|
+
});
|
|
260
|
+
if (result.code !== 0) {
|
|
261
|
+
throw new Error(`music-player ${action} failed: ${result.stderr.trim() || `exit ${result.code}`}`);
|
|
262
|
+
}
|
|
263
|
+
const playback = await waitForTransition(
|
|
264
|
+
context.state.adapter,
|
|
265
|
+
context.run,
|
|
266
|
+
before,
|
|
267
|
+
action,
|
|
268
|
+
);
|
|
269
|
+
return {
|
|
270
|
+
state: withPlayback(context.state, playback),
|
|
271
|
+
output: render(playback),
|
|
272
|
+
viewMode: "edit",
|
|
273
|
+
};
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
export async function init({ argument, run }) {
|
|
277
|
+
const adapter = requireAdapter(argument);
|
|
278
|
+
const playback = await readPlayback(adapter, run);
|
|
279
|
+
return {
|
|
280
|
+
state: { version: 1, adapter, playback },
|
|
281
|
+
output: render(playback),
|
|
282
|
+
};
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
export async function status({ state, run }) {
|
|
286
|
+
const playback = await readPlayback(state.adapter, run);
|
|
287
|
+
const changed = JSON.stringify(playback) !== JSON.stringify(state.playback);
|
|
288
|
+
return {
|
|
289
|
+
...(changed ? { state: withPlayback(state, playback) } : {}),
|
|
290
|
+
output: render(playback),
|
|
291
|
+
viewMode: "edit",
|
|
292
|
+
};
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
export async function refresh({ state, run }) {
|
|
296
|
+
const playback = await readPlayback(state.adapter, run);
|
|
297
|
+
const changed = JSON.stringify(playback) !== JSON.stringify(state.playback);
|
|
298
|
+
return {
|
|
299
|
+
...(changed ? { state: withPlayback(state, playback) } : {}),
|
|
300
|
+
output: render(playback),
|
|
301
|
+
};
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
export async function main({ state, run }) {
|
|
305
|
+
const playback = await readPlayback(state.adapter, run);
|
|
306
|
+
const changed = JSON.stringify(playback) !== JSON.stringify(state.playback);
|
|
307
|
+
return {
|
|
308
|
+
...(changed ? { state: withPlayback(state, playback) } : {}),
|
|
309
|
+
output: render(playback),
|
|
310
|
+
viewMode: "edit",
|
|
311
|
+
};
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
export async function play(context) {
|
|
315
|
+
return await apply("resume", context);
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
export async function pause(context) {
|
|
319
|
+
return await apply("pause", context);
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
export async function resume(context) {
|
|
323
|
+
return await apply("resume", context);
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
export async function toggle(context) {
|
|
327
|
+
return await apply("toggle", context);
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
export async function next(context) {
|
|
331
|
+
return await apply("next", context);
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
export async function previous(context) {
|
|
335
|
+
return await apply("previous", context);
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
export async function seek_percent({ argument, ...context }) {
|
|
339
|
+
return await applySeek(normalizeSeekPercent(argument), context);
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
export async function volume({ argument, ...context }) {
|
|
343
|
+
return await applyVolume(normalizeAbsoluteVolume(argument), context);
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
export async function volume_delta({ argument, ...context }) {
|
|
347
|
+
if (!Number.isInteger(argument) || argument < -100 || argument > 100) {
|
|
348
|
+
throw new Error("music-player volume_delta requires an integer -100..100");
|
|
349
|
+
}
|
|
350
|
+
const playback = await readPlayback(context.state.adapter, context.run);
|
|
351
|
+
const current = playback.volume;
|
|
352
|
+
if (!Number.isInteger(current)) {
|
|
353
|
+
throw new Error("music-player current volume is unavailable");
|
|
354
|
+
}
|
|
355
|
+
return await applyVolume(Math.max(0, Math.min(100, current + argument)), context);
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
export async function stop(context) {
|
|
359
|
+
return await apply("stop", context);
|
|
360
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
{
|
|
2
|
+
"async": true,
|
|
3
|
+
"singleton": true,
|
|
4
|
+
"args": [
|
|
5
|
+
"source:string",
|
|
6
|
+
"loop:bool",
|
|
7
|
+
"volume:int",
|
|
8
|
+
"player:enum(auto,mpv,afplay,ffplay,cvlc,play,wmp)",
|
|
9
|
+
"state_dir:path"
|
|
10
|
+
],
|
|
11
|
+
"defaults": {
|
|
12
|
+
"loop": "true",
|
|
13
|
+
"volume": "70",
|
|
14
|
+
"player": "auto"
|
|
15
|
+
},
|
|
16
|
+
"control": [
|
|
17
|
+
"play",
|
|
18
|
+
"pause",
|
|
19
|
+
"resume",
|
|
20
|
+
"toggle",
|
|
21
|
+
"next",
|
|
22
|
+
"previous",
|
|
23
|
+
"seek",
|
|
24
|
+
"volume",
|
|
25
|
+
"stop",
|
|
26
|
+
"status"
|
|
27
|
+
],
|
|
28
|
+
"template": "{skill_dir}/scripts/playback.mjs play {source} {loop} {volume} {player} {state_dir}"
|
|
29
|
+
}
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Actor-neutral client for the local Music Player playback protocol.
|
|
5
|
+
*
|
|
6
|
+
* Reads portable JSON status and sends bounded generation-fenced commands to
|
|
7
|
+
* the playback service endpoint without reading pi-actors Run or Control state.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
11
|
+
import { createConnection } from "node:net";
|
|
12
|
+
import { homedir } from "node:os";
|
|
13
|
+
import { join } from "node:path";
|
|
14
|
+
|
|
15
|
+
const ACTIONS = new Set([
|
|
16
|
+
"play",
|
|
17
|
+
"resume",
|
|
18
|
+
"pause",
|
|
19
|
+
"toggle",
|
|
20
|
+
"next",
|
|
21
|
+
"previous",
|
|
22
|
+
"seek",
|
|
23
|
+
"volume",
|
|
24
|
+
"stop",
|
|
25
|
+
"status",
|
|
26
|
+
]);
|
|
27
|
+
|
|
28
|
+
function fail(message, code = 1) {
|
|
29
|
+
console.error(`music-player: ${message}`);
|
|
30
|
+
process.exit(code);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function expandPath(value) {
|
|
34
|
+
if (value === "~") return homedir();
|
|
35
|
+
if (value.startsWith("~/")) return join(homedir(), value.slice(2));
|
|
36
|
+
return value;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function readJson(path, fallback) {
|
|
40
|
+
try {
|
|
41
|
+
return JSON.parse(readFileSync(path, "utf8"));
|
|
42
|
+
} catch {
|
|
43
|
+
return fallback;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function parsePercent(value, label) {
|
|
48
|
+
if (!/^\d+$/.test(String(value))) {
|
|
49
|
+
fail(`${label} percent must be an integer 0..100`, 2);
|
|
50
|
+
}
|
|
51
|
+
const percent = Number(value);
|
|
52
|
+
if (percent < 0 || percent > 100) {
|
|
53
|
+
fail(`${label} percent must be an integer 0..100`, 2);
|
|
54
|
+
}
|
|
55
|
+
return percent;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function projectCurrentProgress(status, nowMs = Date.now()) {
|
|
59
|
+
const duration = Number(status.duration_seconds);
|
|
60
|
+
let position = Number(status.position_seconds);
|
|
61
|
+
const updatedAtMs = Number(status.position_updated_at_ms);
|
|
62
|
+
if (!Number.isFinite(position)) position = 0;
|
|
63
|
+
if (status.state === "playing" && Number.isFinite(updatedAtMs)) {
|
|
64
|
+
position += Math.max(0, nowMs - updatedAtMs) / 1000;
|
|
65
|
+
}
|
|
66
|
+
if (!Number.isFinite(duration) || duration <= 0) {
|
|
67
|
+
return { ...status, progress_percent: null };
|
|
68
|
+
}
|
|
69
|
+
position = Math.min(Math.max(position, 0), duration);
|
|
70
|
+
return {
|
|
71
|
+
...status,
|
|
72
|
+
progress_percent: Math.round((position / duration) * 100),
|
|
73
|
+
position_seconds: position,
|
|
74
|
+
position_updated_at_ms: nowMs,
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
async function sendCommand(endpoint, action, input) {
|
|
79
|
+
const payload = `${JSON.stringify({
|
|
80
|
+
action,
|
|
81
|
+
...(input !== undefined ? { input } : {}),
|
|
82
|
+
service_instance_id: endpoint.service_instance_id,
|
|
83
|
+
})}\n`;
|
|
84
|
+
const response = await new Promise((resolveResponse, rejectResponse) => {
|
|
85
|
+
const socket = createConnection(endpoint.path);
|
|
86
|
+
let content = "";
|
|
87
|
+
const timeout = setTimeout(() => {
|
|
88
|
+
socket.destroy();
|
|
89
|
+
rejectResponse(new Error("playback service command timed out"));
|
|
90
|
+
}, 5_000);
|
|
91
|
+
timeout.unref?.();
|
|
92
|
+
socket.setEncoding("utf8");
|
|
93
|
+
socket.on("connect", () => socket.write(payload));
|
|
94
|
+
socket.on("data", (chunk) => {
|
|
95
|
+
content += chunk;
|
|
96
|
+
if (Buffer.byteLength(content, "utf8") > 4096) {
|
|
97
|
+
socket.destroy(new Error("playback service response is too large"));
|
|
98
|
+
}
|
|
99
|
+
});
|
|
100
|
+
socket.on("error", rejectResponse);
|
|
101
|
+
socket.on("end", () => {
|
|
102
|
+
clearTimeout(timeout);
|
|
103
|
+
try {
|
|
104
|
+
resolveResponse(JSON.parse(content.trim()));
|
|
105
|
+
} catch {
|
|
106
|
+
rejectResponse(new Error("playback service returned invalid JSON"));
|
|
107
|
+
}
|
|
108
|
+
});
|
|
109
|
+
});
|
|
110
|
+
if (!response?.ok) {
|
|
111
|
+
throw new Error(response?.error || "playback service rejected the command");
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
const [action = "status", rawStateDir, ...actionArgs] = process.argv.slice(2);
|
|
116
|
+
if (!ACTIONS.has(action) || !rawStateDir) {
|
|
117
|
+
fail("usage: playback-client.mjs <status|play|resume|pause|toggle|next|previous|seek|volume|stop> <state-dir> [action args]", 2);
|
|
118
|
+
}
|
|
119
|
+
const stateDir = expandPath(rawStateDir);
|
|
120
|
+
if (action === "status") {
|
|
121
|
+
const status = readJson(join(stateDir, "player.json"), { state: "unknown" });
|
|
122
|
+
process.stdout.write(`${JSON.stringify(projectCurrentProgress(status))}\n`);
|
|
123
|
+
process.exit(0);
|
|
124
|
+
}
|
|
125
|
+
const endpointPath = join(stateDir, "playback-endpoint.json");
|
|
126
|
+
if (!existsSync(endpointPath)) fail(`playback service is not active: ${stateDir}`, 3);
|
|
127
|
+
const endpoint = readJson(endpointPath, {});
|
|
128
|
+
if (
|
|
129
|
+
typeof endpoint.path !== "string" ||
|
|
130
|
+
!endpoint.path ||
|
|
131
|
+
typeof endpoint.service_instance_id !== "string" ||
|
|
132
|
+
!endpoint.service_instance_id
|
|
133
|
+
) fail(`playback service endpoint is invalid: ${stateDir}`, 3);
|
|
134
|
+
let input;
|
|
135
|
+
if (action === "seek" || action === "volume") {
|
|
136
|
+
input = { percent: parsePercent(actionArgs[0], action) };
|
|
137
|
+
}
|
|
138
|
+
try {
|
|
139
|
+
await sendCommand(endpoint, action === "resume" ? "play" : action, input);
|
|
140
|
+
console.log(`music-player: command=${action} handled state_dir=${stateDir}`);
|
|
141
|
+
} catch (error) {
|
|
142
|
+
fail(error instanceof Error ? error.message : String(error), 3);
|
|
143
|
+
}
|