@cmetech/otto 1.1.1 → 1.2.4
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/dist/coworker/persona-commands.d.ts +1 -0
- package/dist/coworker/persona-commands.js +5 -0
- package/dist/coworker/persona-commands.test.d.ts +1 -0
- package/dist/coworker/persona-commands.test.js +45 -0
- package/dist/resources/.managed-resources-content-hash +1 -1
- package/dist/resources/extensions/_coworker-paths.js +8 -0
- package/dist/resources/extensions/coworker-artifacts/artifacts-command.js +31 -0
- package/dist/resources/extensions/coworker-artifacts/artifacts-singleton.js +17 -0
- package/dist/resources/extensions/coworker-artifacts/extension-manifest.json +13 -0
- package/dist/resources/extensions/coworker-artifacts/index.js +125 -0
- package/dist/resources/extensions/coworker-artifacts/list-tool.js +27 -0
- package/dist/resources/extensions/coworker-artifacts/open-tool.js +25 -0
- package/dist/resources/extensions/coworker-memory/extension-manifest.json +13 -0
- package/dist/resources/extensions/coworker-memory/index.js +219 -0
- package/dist/resources/extensions/coworker-memory/memorize-tool.js +10 -0
- package/dist/resources/extensions/coworker-memory/memory-command.js +157 -0
- package/dist/resources/extensions/coworker-memory/memory-singleton.js +55 -0
- package/dist/resources/extensions/coworker-memory/recall-tool.js +18 -0
- package/dist/resources/extensions/coworker-memory/session-hooks.js +45 -0
- package/dist/resources/extensions/coworker-scratchpad/attach-banners.js +53 -0
- package/dist/resources/extensions/coworker-scratchpad/extension-manifest.json +13 -0
- package/dist/resources/extensions/coworker-scratchpad/format-age.js +9 -0
- package/dist/resources/extensions/coworker-scratchpad/helpers.js +38 -0
- package/dist/resources/extensions/coworker-scratchpad/index.js +199 -0
- package/dist/resources/extensions/coworker-scratchpad/mime-bundle.js +20 -0
- package/dist/resources/extensions/coworker-scratchpad/scratchpad-tool.js +118 -0
- package/dist/resources/extensions/coworker-scratchpad/session-sidecar.js +60 -0
- package/dist/resources/extensions/coworker-scratchpad/sp-command.js +597 -0
- package/dist/resources/extensions/coworker-scratchpad/workspace-pointer.js +41 -0
- package/dist/resources/extensions/coworker-scratchpad/workspace-root.js +17 -0
- package/dist/resources/extensions/coworker-vault/audit-command.js +35 -0
- package/dist/resources/extensions/coworker-vault/connect-command.js +42 -0
- package/dist/resources/extensions/coworker-vault/datasource-command.js +50 -0
- package/dist/resources/extensions/coworker-vault/extension-manifest.json +12 -0
- package/dist/resources/extensions/coworker-vault/index.js +171 -0
- package/dist/resources/extensions/coworker-vault/test-helpers.js +86 -0
- package/dist/resources/extensions/coworker-vault/vault-singleton.js +24 -0
- package/dist/resources/extensions/otto/commands/release-notes/_data.js +71 -0
- package/dist/resources/extensions/otto/commands/release-notes/command.js +15 -4
- package/dist/resources/extensions/subagent/index.js +8 -1
- package/dist/resources/extensions/subagent/launch.js +37 -5
- package/dist/resources/extensions/subagent/run-store.js +1 -0
- package/dist/resources/extensions/workflow/bootstrap/register-extension.js +2 -0
- package/dist/resources/extensions/workflow/bootstrap/register-hooks.js +10 -0
- package/dist/resources/extensions/workflow/persona-status.js +87 -0
- package/package.json +25 -10
- package/packages/contracts/package.json +1 -1
- package/packages/coworker-artifacts/dist/artifact-store.d.ts +25 -0
- package/packages/coworker-artifacts/dist/artifact-store.js +187 -0
- package/packages/coworker-artifacts/dist/dir-snapshot.d.ts +7 -0
- package/packages/coworker-artifacts/dist/dir-snapshot.js +54 -0
- package/packages/coworker-artifacts/dist/errors.d.ts +18 -0
- package/packages/coworker-artifacts/dist/errors.js +37 -0
- package/packages/coworker-artifacts/dist/index.d.ts +7 -0
- package/packages/coworker-artifacts/dist/index.js +7 -0
- package/packages/coworker-artifacts/dist/readme-renderer.d.ts +5 -0
- package/packages/coworker-artifacts/dist/readme-renderer.js +47 -0
- package/packages/coworker-artifacts/dist/resolve-uri.d.ts +3 -0
- package/packages/coworker-artifacts/dist/resolve-uri.js +29 -0
- package/packages/coworker-artifacts/dist/slug.d.ts +4 -0
- package/packages/coworker-artifacts/dist/slug.js +32 -0
- package/packages/coworker-artifacts/dist/types.d.ts +52 -0
- package/packages/coworker-artifacts/dist/types.js +1 -0
- package/packages/coworker-artifacts/package.json +20 -0
- package/packages/coworker-artifacts/src/artifact-store.test.ts +188 -0
- package/packages/coworker-artifacts/src/artifact-store.ts +206 -0
- package/packages/coworker-artifacts/src/artifacts-integration.test.ts +109 -0
- package/packages/coworker-artifacts/src/dir-snapshot.test.ts +71 -0
- package/packages/coworker-artifacts/src/dir-snapshot.ts +52 -0
- package/packages/coworker-artifacts/src/errors.test.ts +37 -0
- package/packages/coworker-artifacts/src/errors.ts +28 -0
- package/packages/coworker-artifacts/src/index.test.ts +22 -0
- package/packages/coworker-artifacts/src/index.ts +7 -0
- package/packages/coworker-artifacts/src/readme-renderer.test.ts +72 -0
- package/packages/coworker-artifacts/src/readme-renderer.ts +56 -0
- package/packages/coworker-artifacts/src/resolve-uri.test.ts +46 -0
- package/packages/coworker-artifacts/src/resolve-uri.ts +29 -0
- package/packages/coworker-artifacts/src/slug.test.ts +47 -0
- package/packages/coworker-artifacts/src/slug.ts +31 -0
- package/packages/coworker-artifacts/src/types.ts +61 -0
- package/packages/coworker-artifacts/tsconfig.json +15 -0
- package/packages/coworker-artifacts/tsconfig.publish.json +4 -0
- package/packages/coworker-memory/dist/context-injection.d.ts +9 -0
- package/packages/coworker-memory/dist/context-injection.js +41 -0
- package/packages/coworker-memory/dist/errors.d.ts +25 -0
- package/packages/coworker-memory/dist/errors.js +51 -0
- package/packages/coworker-memory/dist/index.d.ts +12 -0
- package/packages/coworker-memory/dist/index.js +12 -0
- package/packages/coworker-memory/dist/layer-a-store.d.ts +16 -0
- package/packages/coworker-memory/dist/layer-a-store.js +78 -0
- package/packages/coworker-memory/dist/local-sqlite-backend.d.ts +28 -0
- package/packages/coworker-memory/dist/local-sqlite-backend.js +167 -0
- package/packages/coworker-memory/dist/memory-backend.d.ts +14 -0
- package/packages/coworker-memory/dist/memory-backend.js +1 -0
- package/packages/coworker-memory/dist/memory-recorder.d.ts +50 -0
- package/packages/coworker-memory/dist/memory-recorder.js +69 -0
- package/packages/coworker-memory/dist/migrations/001-init.sql +38 -0
- package/packages/coworker-memory/dist/migrations/002-artifact-kind.sql +50 -0
- package/packages/coworker-memory/dist/paste-detector.d.ts +5 -0
- package/packages/coworker-memory/dist/paste-detector.js +14 -0
- package/packages/coworker-memory/dist/persona-seed.d.ts +10 -0
- package/packages/coworker-memory/dist/persona-seed.js +38 -0
- package/packages/coworker-memory/dist/recall-formatter.d.ts +2 -0
- package/packages/coworker-memory/dist/recall-formatter.js +14 -0
- package/packages/coworker-memory/dist/scope-resolver.d.ts +9 -0
- package/packages/coworker-memory/dist/scope-resolver.js +10 -0
- package/packages/coworker-memory/dist/types.d.ts +51 -0
- package/packages/coworker-memory/dist/types.js +2 -0
- package/packages/coworker-memory/dist/workspace-id.d.ts +3 -0
- package/packages/coworker-memory/dist/workspace-id.js +54 -0
- package/packages/coworker-memory/package.json +35 -0
- package/packages/coworker-memory/src/activator-integration.test.ts +141 -0
- package/packages/coworker-memory/src/context-injection.test.ts +72 -0
- package/packages/coworker-memory/src/context-injection.ts +57 -0
- package/packages/coworker-memory/src/errors.test.ts +45 -0
- package/packages/coworker-memory/src/errors.ts +42 -0
- package/packages/coworker-memory/src/index.test.ts +21 -0
- package/packages/coworker-memory/src/index.ts +12 -0
- package/packages/coworker-memory/src/layer-a-store.test.ts +85 -0
- package/packages/coworker-memory/src/layer-a-store.ts +88 -0
- package/packages/coworker-memory/src/local-sqlite-backend.test.ts +110 -0
- package/packages/coworker-memory/src/local-sqlite-backend.ts +185 -0
- package/packages/coworker-memory/src/memory-backend.ts +10 -0
- package/packages/coworker-memory/src/memory-integration.test.ts +89 -0
- package/packages/coworker-memory/src/memory-recorder.test.ts +101 -0
- package/packages/coworker-memory/src/memory-recorder.ts +95 -0
- package/packages/coworker-memory/src/migrations/001-init.sql +38 -0
- package/packages/coworker-memory/src/migrations/002-artifact-kind.sql +50 -0
- package/packages/coworker-memory/src/paste-detector.test.ts +23 -0
- package/packages/coworker-memory/src/paste-detector.ts +18 -0
- package/packages/coworker-memory/src/persona-seed.test.ts +57 -0
- package/packages/coworker-memory/src/persona-seed.ts +46 -0
- package/packages/coworker-memory/src/recall-formatter.test.ts +34 -0
- package/packages/coworker-memory/src/recall-formatter.ts +15 -0
- package/packages/coworker-memory/src/scope-resolver.test.ts +23 -0
- package/packages/coworker-memory/src/scope-resolver.ts +18 -0
- package/packages/coworker-memory/src/types.ts +61 -0
- package/packages/coworker-memory/src/workspace-id.test.ts +48 -0
- package/packages/coworker-memory/src/workspace-id.ts +56 -0
- package/packages/coworker-memory/tsconfig.json +15 -0
- package/packages/coworker-memory/tsconfig.publish.json +4 -0
- package/packages/coworker-persona/dist/commands.d.ts +7 -0
- package/packages/coworker-persona/dist/commands.js +35 -0
- package/packages/coworker-persona/dist/defaults/manifest.yaml +12 -0
- package/packages/coworker-persona/dist/defaults/steering/identity.md +3 -0
- package/packages/coworker-persona/dist/index.d.ts +3 -0
- package/packages/coworker-persona/dist/index.js +3 -0
- package/packages/coworker-persona/dist/manifest.d.ts +24 -0
- package/packages/coworker-persona/dist/manifest.js +21 -0
- package/packages/coworker-persona/dist/registry.d.ts +22 -0
- package/packages/coworker-persona/dist/registry.js +142 -0
- package/packages/coworker-persona/package.json +28 -0
- package/packages/coworker-persona/scripts/copy-defaults.cjs +17 -0
- package/packages/coworker-persona/src/commands.ts +47 -0
- package/packages/coworker-persona/src/defaults/manifest.yaml +12 -0
- package/packages/coworker-persona/src/defaults/steering/identity.md +3 -0
- package/packages/coworker-persona/src/index.ts +3 -0
- package/packages/coworker-persona/src/manifest.test.ts +67 -0
- package/packages/coworker-persona/src/manifest.ts +49 -0
- package/packages/coworker-persona/src/registry.test.ts +89 -0
- package/packages/coworker-persona/src/registry.ts +147 -0
- package/packages/coworker-persona/tsconfig.json +15 -0
- package/packages/coworker-persona/tsconfig.publish.json +4 -0
- package/packages/coworker-scratchpad/dist/cell-archive.d.ts +39 -0
- package/packages/coworker-scratchpad/dist/cell-archive.js +77 -0
- package/packages/coworker-scratchpad/dist/cell-tree.d.ts +14 -0
- package/packages/coworker-scratchpad/dist/cell-tree.js +72 -0
- package/packages/coworker-scratchpad/dist/child-process-runtime.d.ts +129 -0
- package/packages/coworker-scratchpad/dist/child-process-runtime.js +427 -0
- package/packages/coworker-scratchpad/dist/collector-registry.d.ts +12 -0
- package/packages/coworker-scratchpad/dist/collector-registry.js +29 -0
- package/packages/coworker-scratchpad/dist/detect-kind.d.ts +3 -0
- package/packages/coworker-scratchpad/dist/detect-kind.js +19 -0
- package/packages/coworker-scratchpad/dist/file-collector.d.ts +15 -0
- package/packages/coworker-scratchpad/dist/file-collector.js +99 -0
- package/packages/coworker-scratchpad/dist/index.d.ts +13 -0
- package/packages/coworker-scratchpad/dist/index.js +13 -0
- package/packages/coworker-scratchpad/dist/kernel-bindings.d.ts +49 -0
- package/packages/coworker-scratchpad/dist/kernel-bindings.js +220 -0
- package/packages/coworker-scratchpad/dist/kernel-entry.d.ts +1 -0
- package/packages/coworker-scratchpad/dist/kernel-entry.js +355 -0
- package/packages/coworker-scratchpad/dist/kernel-protocol.d.ts +171 -0
- package/packages/coworker-scratchpad/dist/kernel-protocol.js +48 -0
- package/packages/coworker-scratchpad/dist/kernel-spawn.d.ts +3 -0
- package/packages/coworker-scratchpad/dist/kernel-spawn.js +54 -0
- package/packages/coworker-scratchpad/dist/namespace-codec.d.ts +22 -0
- package/packages/coworker-scratchpad/dist/namespace-codec.js +61 -0
- package/packages/coworker-scratchpad/dist/scratchpad-lock.d.ts +24 -0
- package/packages/coworker-scratchpad/dist/scratchpad-lock.js +86 -0
- package/packages/coworker-scratchpad/dist/scratchpad-manager.d.ts +193 -0
- package/packages/coworker-scratchpad/dist/scratchpad-manager.js +866 -0
- package/packages/coworker-scratchpad/dist/staleness-banner.d.ts +12 -0
- package/packages/coworker-scratchpad/dist/staleness-banner.js +27 -0
- package/packages/coworker-scratchpad/package.json +31 -0
- package/packages/coworker-scratchpad/src/cell-archive.test.ts +150 -0
- package/packages/coworker-scratchpad/src/cell-archive.ts +97 -0
- package/packages/coworker-scratchpad/src/cell-tree.test.ts +105 -0
- package/packages/coworker-scratchpad/src/cell-tree.ts +90 -0
- package/packages/coworker-scratchpad/src/child-process-runtime.test.ts +413 -0
- package/packages/coworker-scratchpad/src/child-process-runtime.ts +493 -0
- package/packages/coworker-scratchpad/src/collector-registry.test.ts +69 -0
- package/packages/coworker-scratchpad/src/collector-registry.ts +33 -0
- package/packages/coworker-scratchpad/src/detect-kind.test.ts +33 -0
- package/packages/coworker-scratchpad/src/detect-kind.ts +22 -0
- package/packages/coworker-scratchpad/src/file-collector.test.ts +109 -0
- package/packages/coworker-scratchpad/src/file-collector.ts +114 -0
- package/packages/coworker-scratchpad/src/index.ts +74 -0
- package/packages/coworker-scratchpad/src/kernel-bindings.test.ts +188 -0
- package/packages/coworker-scratchpad/src/kernel-bindings.ts +279 -0
- package/packages/coworker-scratchpad/src/kernel-entry.test.ts +123 -0
- package/packages/coworker-scratchpad/src/kernel-entry.ts +390 -0
- package/packages/coworker-scratchpad/src/kernel-protocol.test.ts +105 -0
- package/packages/coworker-scratchpad/src/kernel-protocol.ts +230 -0
- package/packages/coworker-scratchpad/src/kernel-spawn.test.ts +60 -0
- package/packages/coworker-scratchpad/src/kernel-spawn.ts +54 -0
- package/packages/coworker-scratchpad/src/namespace-codec.test.ts +102 -0
- package/packages/coworker-scratchpad/src/namespace-codec.ts +90 -0
- package/packages/coworker-scratchpad/src/scratchpad-lock.test.ts +98 -0
- package/packages/coworker-scratchpad/src/scratchpad-lock.ts +102 -0
- package/packages/coworker-scratchpad/src/scratchpad-manager.test.ts +1343 -0
- package/packages/coworker-scratchpad/src/scratchpad-manager.ts +891 -0
- package/packages/coworker-scratchpad/src/staleness-banner.test.ts +53 -0
- package/packages/coworker-scratchpad/src/staleness-banner.ts +33 -0
- package/packages/coworker-scratchpad/src/vault-integration.test.ts +221 -0
- package/packages/coworker-scratchpad/tsconfig.json +15 -0
- package/packages/coworker-scratchpad/tsconfig.publish.json +4 -0
- package/packages/coworker-types/dist/artifacts.d.ts +31 -0
- package/packages/coworker-types/dist/artifacts.js +2 -0
- package/packages/coworker-types/dist/contracts.d.ts +32 -0
- package/packages/coworker-types/dist/contracts.js +1 -0
- package/packages/coworker-types/dist/index.d.ts +5 -0
- package/packages/coworker-types/dist/index.js +5 -0
- package/packages/coworker-types/dist/memory.d.ts +61 -0
- package/packages/coworker-types/dist/memory.js +3 -0
- package/packages/coworker-types/dist/scratchpad.d.ts +43 -0
- package/packages/coworker-types/dist/scratchpad.js +2 -0
- package/packages/coworker-types/dist/vault.d.ts +34 -0
- package/packages/coworker-types/dist/vault.js +2 -0
- package/packages/coworker-types/package.json +24 -0
- package/packages/coworker-types/src/artifacts.test.ts +52 -0
- package/packages/coworker-types/src/artifacts.ts +35 -0
- package/packages/coworker-types/src/contracts.test.ts +43 -0
- package/packages/coworker-types/src/contracts.ts +36 -0
- package/packages/coworker-types/src/index.ts +5 -0
- package/packages/coworker-types/src/memory.test.ts +50 -0
- package/packages/coworker-types/src/memory.ts +79 -0
- package/packages/coworker-types/src/scratchpad.test.ts +46 -0
- package/packages/coworker-types/src/scratchpad.ts +51 -0
- package/packages/coworker-types/src/smoke.test.ts +34 -0
- package/packages/coworker-types/src/vault.test.ts +49 -0
- package/packages/coworker-types/src/vault.ts +40 -0
- package/packages/coworker-types/tsconfig.json +15 -0
- package/packages/coworker-types/tsconfig.publish.json +4 -0
- package/packages/coworker-utils/dist/audit-log.d.ts +34 -0
- package/packages/coworker-utils/dist/audit-log.js +88 -0
- package/packages/coworker-utils/dist/index.d.ts +6 -0
- package/packages/coworker-utils/dist/index.js +6 -0
- package/packages/coworker-utils/dist/lease.d.ts +7 -0
- package/packages/coworker-utils/dist/lease.js +67 -0
- package/packages/coworker-utils/dist/logger.d.ts +13 -0
- package/packages/coworker-utils/dist/logger.js +26 -0
- package/packages/coworker-utils/dist/migration-runner.d.ts +7 -0
- package/packages/coworker-utils/dist/migration-runner.js +36 -0
- package/packages/coworker-utils/dist/ndjson-channel.d.ts +3 -0
- package/packages/coworker-utils/dist/ndjson-channel.js +38 -0
- package/packages/coworker-utils/dist/secret-scanner.d.ts +10 -0
- package/packages/coworker-utils/dist/secret-scanner.js +42 -0
- package/packages/coworker-utils/package.json +24 -0
- package/packages/coworker-utils/src/audit-log.test.ts +140 -0
- package/packages/coworker-utils/src/audit-log.ts +107 -0
- package/packages/coworker-utils/src/index.ts +6 -0
- package/packages/coworker-utils/src/lease.test.ts +64 -0
- package/packages/coworker-utils/src/lease.ts +76 -0
- package/packages/coworker-utils/src/logger.test.ts +50 -0
- package/packages/coworker-utils/src/logger.ts +45 -0
- package/packages/coworker-utils/src/migration-runner.test.ts +65 -0
- package/packages/coworker-utils/src/migration-runner.ts +50 -0
- package/packages/coworker-utils/src/ndjson-channel.test.ts +76 -0
- package/packages/coworker-utils/src/ndjson-channel.ts +41 -0
- package/packages/coworker-utils/src/secret-scanner.test.ts +61 -0
- package/packages/coworker-utils/src/secret-scanner.ts +56 -0
- package/packages/coworker-utils/tsconfig.json +15 -0
- package/packages/coworker-utils/tsconfig.publish.json +4 -0
- package/packages/coworker-vault/dist/data-vault.d.ts +41 -0
- package/packages/coworker-vault/dist/data-vault.js +223 -0
- package/packages/coworker-vault/dist/engine-registry.d.ts +34 -0
- package/packages/coworker-vault/dist/engine-registry.js +90 -0
- package/packages/coworker-vault/dist/engines/jira.yaml +17 -0
- package/packages/coworker-vault/dist/errors.d.ts +28 -0
- package/packages/coworker-vault/dist/errors.js +57 -0
- package/packages/coworker-vault/dist/index.d.ts +6 -0
- package/packages/coworker-vault/dist/index.js +6 -0
- package/packages/coworker-vault/dist/injector.d.ts +19 -0
- package/packages/coworker-vault/dist/injector.js +77 -0
- package/packages/coworker-vault/dist/types.d.ts +28 -0
- package/packages/coworker-vault/dist/types.js +1 -0
- package/packages/coworker-vault/dist/vault-keep.d.ts +4 -0
- package/packages/coworker-vault/dist/vault-keep.js +21 -0
- package/packages/coworker-vault/package.json +29 -0
- package/packages/coworker-vault/src/data-vault.test.ts +199 -0
- package/packages/coworker-vault/src/data-vault.ts +257 -0
- package/packages/coworker-vault/src/engine-registry.test.ts +120 -0
- package/packages/coworker-vault/src/engine-registry.ts +107 -0
- package/packages/coworker-vault/src/engines/jira.yaml +17 -0
- package/packages/coworker-vault/src/errors.test.ts +58 -0
- package/packages/coworker-vault/src/errors.ts +50 -0
- package/packages/coworker-vault/src/index.test.ts +24 -0
- package/packages/coworker-vault/src/index.ts +6 -0
- package/packages/coworker-vault/src/injector.test.ts +109 -0
- package/packages/coworker-vault/src/injector.ts +98 -0
- package/packages/coworker-vault/src/types.ts +33 -0
- package/packages/coworker-vault/src/vault-keep.test.ts +49 -0
- package/packages/coworker-vault/src/vault-keep.ts +31 -0
- package/packages/coworker-vault/tsconfig.json +15 -0
- package/packages/coworker-vault/tsconfig.publish.json +4 -0
- package/packages/daemon/package.json +3 -3
- package/packages/mcp-server/package.json +3 -3
- package/packages/mcp-server/tsconfig.tsbuildinfo +1 -1
- package/packages/native/package.json +1 -1
- package/packages/native/tsconfig.tsbuildinfo +1 -1
- package/packages/pi-agent-core/package.json +1 -1
- package/packages/pi-agent-core/tsconfig.tsbuildinfo +1 -1
- package/packages/pi-ai/package.json +1 -1
- package/packages/pi-ai/tsconfig.tsbuildinfo +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/runner.d.ts +6 -1
- package/packages/pi-coding-agent/dist/core/extensions/runner.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/runner.js +22 -3
- package/packages/pi-coding-agent/dist/core/extensions/runner.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/resolve-config-value.test.js +11 -0
- package/packages/pi-coding-agent/dist/core/resolve-config-value.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/rpc/raw-stdout.d.ts +47 -0
- package/packages/pi-coding-agent/dist/modes/rpc/raw-stdout.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/modes/rpc/raw-stdout.js +107 -0
- package/packages/pi-coding-agent/dist/modes/rpc/raw-stdout.js.map +1 -0
- package/packages/pi-coding-agent/dist/modes/rpc/raw-stdout.regression.test.d.ts +19 -0
- package/packages/pi-coding-agent/dist/modes/rpc/raw-stdout.regression.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/modes/rpc/raw-stdout.regression.test.js +121 -0
- package/packages/pi-coding-agent/dist/modes/rpc/raw-stdout.regression.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/rpc/rpc-mode.js +17 -1
- package/packages/pi-coding-agent/dist/modes/rpc/rpc-mode.js.map +1 -1
- package/packages/pi-coding-agent/package.json +2 -2
- package/packages/pi-coding-agent/src/core/extensions/runner.ts +22 -3
- package/packages/pi-coding-agent/src/core/resolve-config-value.test.ts +11 -0
- package/packages/pi-coding-agent/src/modes/rpc/raw-stdout.regression.test.ts +129 -0
- package/packages/pi-coding-agent/src/modes/rpc/raw-stdout.ts +117 -0
- package/packages/pi-coding-agent/src/modes/rpc/rpc-mode.ts +18 -1
- package/packages/pi-coding-agent/tsconfig.tsbuildinfo +1 -1
- package/packages/pi-tui/package.json +1 -1
- package/packages/pi-tui/tsconfig.tsbuildinfo +1 -1
- package/packages/rpc-client/package.json +2 -2
- package/packages/rpc-client/tsconfig.tsbuildinfo +1 -1
- package/pkg/package.json +1 -1
- package/scripts/install.js +6 -5
- package/src/resources/extensions/_coworker-paths.test.ts +40 -0
- package/src/resources/extensions/_coworker-paths.ts +10 -0
- package/src/resources/extensions/coworker-artifacts/artifacts-command.test.ts +54 -0
- package/src/resources/extensions/coworker-artifacts/artifacts-command.ts +43 -0
- package/src/resources/extensions/coworker-artifacts/artifacts-singleton.test.ts +25 -0
- package/src/resources/extensions/coworker-artifacts/artifacts-singleton.ts +29 -0
- package/src/resources/extensions/coworker-artifacts/extension-manifest.json +13 -0
- package/src/resources/extensions/coworker-artifacts/index.test.ts +46 -0
- package/src/resources/extensions/coworker-artifacts/index.ts +154 -0
- package/src/resources/extensions/coworker-artifacts/list-tool.test.ts +29 -0
- package/src/resources/extensions/coworker-artifacts/list-tool.ts +53 -0
- package/src/resources/extensions/coworker-artifacts/open-tool.test.ts +30 -0
- package/src/resources/extensions/coworker-artifacts/open-tool.ts +43 -0
- package/src/resources/extensions/coworker-memory/extension-manifest.json +13 -0
- package/src/resources/extensions/coworker-memory/index.test.ts +137 -0
- package/src/resources/extensions/coworker-memory/index.ts +257 -0
- package/src/resources/extensions/coworker-memory/memorize-tool.test.ts +41 -0
- package/src/resources/extensions/coworker-memory/memorize-tool.ts +20 -0
- package/src/resources/extensions/coworker-memory/memory-command.test.ts +134 -0
- package/src/resources/extensions/coworker-memory/memory-command.ts +131 -0
- package/src/resources/extensions/coworker-memory/memory-singleton.test.ts +41 -0
- package/src/resources/extensions/coworker-memory/memory-singleton.ts +89 -0
- package/src/resources/extensions/coworker-memory/recall-tool.test.ts +50 -0
- package/src/resources/extensions/coworker-memory/recall-tool.ts +35 -0
- package/src/resources/extensions/coworker-memory/session-hooks.test.ts +77 -0
- package/src/resources/extensions/coworker-memory/session-hooks.ts +61 -0
- package/src/resources/extensions/coworker-scratchpad/attach-banners.test.ts +124 -0
- package/src/resources/extensions/coworker-scratchpad/attach-banners.ts +67 -0
- package/src/resources/extensions/coworker-scratchpad/extension-manifest.json +13 -0
- package/src/resources/extensions/coworker-scratchpad/format-age.test.ts +30 -0
- package/src/resources/extensions/coworker-scratchpad/format-age.ts +6 -0
- package/src/resources/extensions/coworker-scratchpad/helpers.test.ts +93 -0
- package/src/resources/extensions/coworker-scratchpad/helpers.ts +42 -0
- package/src/resources/extensions/coworker-scratchpad/index.test.ts +514 -0
- package/src/resources/extensions/coworker-scratchpad/index.ts +207 -0
- package/src/resources/extensions/coworker-scratchpad/mime-bundle.test.ts +61 -0
- package/src/resources/extensions/coworker-scratchpad/mime-bundle.ts +23 -0
- package/src/resources/extensions/coworker-scratchpad/scratchpad-tool.test.ts +137 -0
- package/src/resources/extensions/coworker-scratchpad/scratchpad-tool.ts +165 -0
- package/src/resources/extensions/coworker-scratchpad/session-sidecar.test.ts +133 -0
- package/src/resources/extensions/coworker-scratchpad/session-sidecar.ts +68 -0
- package/src/resources/extensions/coworker-scratchpad/sp-command.test.ts +836 -0
- package/src/resources/extensions/coworker-scratchpad/sp-command.ts +602 -0
- package/src/resources/extensions/coworker-scratchpad/workspace-pointer.test.ts +74 -0
- package/src/resources/extensions/coworker-scratchpad/workspace-pointer.ts +55 -0
- package/src/resources/extensions/coworker-scratchpad/workspace-root.test.ts +51 -0
- package/src/resources/extensions/coworker-scratchpad/workspace-root.ts +16 -0
- package/src/resources/extensions/coworker-vault/audit-command.test.ts +109 -0
- package/src/resources/extensions/coworker-vault/audit-command.ts +56 -0
- package/src/resources/extensions/coworker-vault/connect-command.test.ts +103 -0
- package/src/resources/extensions/coworker-vault/connect-command.ts +69 -0
- package/src/resources/extensions/coworker-vault/datasource-command.test.ts +80 -0
- package/src/resources/extensions/coworker-vault/datasource-command.ts +81 -0
- package/src/resources/extensions/coworker-vault/extension-manifest.json +12 -0
- package/src/resources/extensions/coworker-vault/index.test.ts +82 -0
- package/src/resources/extensions/coworker-vault/index.ts +181 -0
- package/src/resources/extensions/coworker-vault/test-helpers.ts +120 -0
- package/src/resources/extensions/coworker-vault/vault-singleton.test.ts +27 -0
- package/src/resources/extensions/coworker-vault/vault-singleton.ts +40 -0
- package/src/resources/extensions/otto/commands/release-notes/_data.ts +85 -0
- package/src/resources/extensions/otto/commands/release-notes/command.ts +16 -3
- package/src/resources/extensions/subagent/index.ts +9 -0
- package/src/resources/extensions/subagent/launch.test.ts +97 -0
- package/src/resources/extensions/subagent/launch.ts +42 -5
- package/src/resources/extensions/subagent/run-store.ts +3 -1
- package/src/resources/extensions/workflow/bootstrap/register-extension.ts +2 -0
- package/src/resources/extensions/workflow/bootstrap/register-hooks.ts +10 -0
- package/src/resources/extensions/workflow/persona-status.ts +109 -0
- package/src/resources/extensions/workflow/tests/auto-recovery.test.ts +34 -0
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
// Persona manifest parser. See spec §2.5.
|
|
2
|
+
import { parse as parseYaml } from 'yaml';
|
|
3
|
+
|
|
4
|
+
export interface PersonaStatusLine {
|
|
5
|
+
label: string;
|
|
6
|
+
color: string; // hex
|
|
7
|
+
icon: string;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export interface PersonaMemorySeed {
|
|
11
|
+
apply_on_first_activation: boolean;
|
|
12
|
+
scope?: 'global' | 'per-project' | 'per-project-tagged';
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export interface PersonaManifest {
|
|
16
|
+
name: string;
|
|
17
|
+
display_name: string;
|
|
18
|
+
version: string;
|
|
19
|
+
description: string;
|
|
20
|
+
author: string;
|
|
21
|
+
otto_version_required: string;
|
|
22
|
+
steering: string[];
|
|
23
|
+
memory_seed?: PersonaMemorySeed;
|
|
24
|
+
engines?: string;
|
|
25
|
+
artifact_kinds?: string[];
|
|
26
|
+
skills_path?: string;
|
|
27
|
+
status_line: PersonaStatusLine;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// Order matters: tests assert the FIRST missing field reported, and the
|
|
31
|
+
// "missing version" case supplies only `name`, so `version` must be checked
|
|
32
|
+
// before `display_name`.
|
|
33
|
+
const REQUIRED: Array<keyof PersonaManifest> = [
|
|
34
|
+
'name', 'version', 'display_name', 'description', 'author',
|
|
35
|
+
'otto_version_required', 'steering', 'status_line',
|
|
36
|
+
];
|
|
37
|
+
|
|
38
|
+
export function parsePersonaManifest(yamlText: string): PersonaManifest {
|
|
39
|
+
const raw = parseYaml(yamlText) as Record<string, unknown> | null;
|
|
40
|
+
if (!raw || typeof raw !== 'object') {
|
|
41
|
+
throw new Error('persona manifest must be a YAML object');
|
|
42
|
+
}
|
|
43
|
+
for (const field of REQUIRED) {
|
|
44
|
+
if (!(field in raw)) {
|
|
45
|
+
throw new Error(`persona manifest missing required field: ${field}`);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
return raw as unknown as PersonaManifest;
|
|
49
|
+
}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { describe, it, beforeEach, afterEach } from 'node:test';
|
|
2
|
+
import assert from 'node:assert/strict';
|
|
3
|
+
import * as fs from 'node:fs/promises';
|
|
4
|
+
import * as path from 'node:path';
|
|
5
|
+
import * as os from 'node:os';
|
|
6
|
+
import { PersonaRegistry } from './registry.js';
|
|
7
|
+
|
|
8
|
+
let tmpHome: string;
|
|
9
|
+
|
|
10
|
+
describe('PersonaRegistry', () => {
|
|
11
|
+
beforeEach(async () => {
|
|
12
|
+
tmpHome = await fs.mkdtemp(path.join(os.tmpdir(), 'persona-test-'));
|
|
13
|
+
await fs.mkdir(path.join(tmpHome, 'personas'), { recursive: true });
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
afterEach(async () => {
|
|
17
|
+
await fs.rm(tmpHome, { recursive: true, force: true });
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
it('list returns built-in default persona on a fresh registry', async () => {
|
|
21
|
+
const r = new PersonaRegistry({ ottoHome: tmpHome });
|
|
22
|
+
await r.ensureDefaultInstalled();
|
|
23
|
+
const installed = await r.list();
|
|
24
|
+
assert.ok(installed.find(p => p.name === 'default'), 'default persona should be installed');
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
it('install copies a bundle directory into ~/.otto/personas/<name>', async () => {
|
|
28
|
+
const r = new PersonaRegistry({ ottoHome: tmpHome });
|
|
29
|
+
// Stage a fake persona bundle
|
|
30
|
+
const bundle = await fs.mkdtemp(path.join(os.tmpdir(), 'fake-bundle-'));
|
|
31
|
+
await fs.mkdir(path.join(bundle, 'steering'), { recursive: true });
|
|
32
|
+
await fs.writeFile(path.join(bundle, 'manifest.yaml'),
|
|
33
|
+
'name: noc-ops\ndisplay_name: NOC\nversion: 1.0.0\ndescription: x\nauthor: x\notto_version_required: ">=2.0.0"\nsteering: [steering/identity.md]\nstatus_line: { label: NOC, color: "#FAD22D", icon: "🛡" }\n');
|
|
34
|
+
await fs.writeFile(path.join(bundle, 'steering', 'identity.md'), 'noc identity');
|
|
35
|
+
|
|
36
|
+
await r.installFromPath(bundle);
|
|
37
|
+
const installed = await r.list();
|
|
38
|
+
assert.ok(installed.find(p => p.name === 'noc-ops'));
|
|
39
|
+
await fs.rm(bundle, { recursive: true, force: true });
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
it('install rejects a bundle missing manifest.yaml', async () => {
|
|
43
|
+
const r = new PersonaRegistry({ ottoHome: tmpHome });
|
|
44
|
+
const bad = await fs.mkdtemp(path.join(os.tmpdir(), 'bad-bundle-'));
|
|
45
|
+
await assert.rejects(() => r.installFromPath(bad), /manifest\.yaml/);
|
|
46
|
+
await fs.rm(bad, { recursive: true, force: true });
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
it('activateInWorkspace writes <workspace>/.otto/persona.json', async () => {
|
|
50
|
+
const r = new PersonaRegistry({ ottoHome: tmpHome });
|
|
51
|
+
await r.ensureDefaultInstalled();
|
|
52
|
+
const ws = await fs.mkdtemp(path.join(os.tmpdir(), 'ws-'));
|
|
53
|
+
await r.activateInWorkspace(ws, 'default');
|
|
54
|
+
const raw = await fs.readFile(path.join(ws, '.otto', 'persona.json'), 'utf8');
|
|
55
|
+
const data = JSON.parse(raw);
|
|
56
|
+
assert.equal(data.active, 'default');
|
|
57
|
+
assert.equal(typeof data.activated_at, 'string');
|
|
58
|
+
assert.equal(data.memory_seed_applied, false);
|
|
59
|
+
await fs.rm(ws, { recursive: true, force: true });
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
it('activeInWorkspace returns "default" when no persona.json exists', async () => {
|
|
63
|
+
const r = new PersonaRegistry({ ottoHome: tmpHome });
|
|
64
|
+
await r.ensureDefaultInstalled();
|
|
65
|
+
const ws = await fs.mkdtemp(path.join(os.tmpdir(), 'ws-'));
|
|
66
|
+
const active = await r.activeInWorkspace(ws);
|
|
67
|
+
assert.equal(active.name, 'default');
|
|
68
|
+
await fs.rm(ws, { recursive: true, force: true });
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
it('uninstall refuses if persona is currently active in any tracked workspace', async () => {
|
|
72
|
+
const r = new PersonaRegistry({ ottoHome: tmpHome });
|
|
73
|
+
await r.ensureDefaultInstalled();
|
|
74
|
+
// Stage + install a second persona, then activate it
|
|
75
|
+
const bundle = await fs.mkdtemp(path.join(os.tmpdir(), 'fake-bundle-'));
|
|
76
|
+
await fs.mkdir(path.join(bundle, 'steering'), { recursive: true });
|
|
77
|
+
await fs.writeFile(path.join(bundle, 'manifest.yaml'),
|
|
78
|
+
'name: noc-ops\ndisplay_name: NOC\nversion: 1.0.0\ndescription: x\nauthor: x\notto_version_required: ">=2.0.0"\nsteering: [steering/identity.md]\nstatus_line: { label: NOC, color: "#FAD22D", icon: "🛡" }\n');
|
|
79
|
+
await fs.writeFile(path.join(bundle, 'steering', 'identity.md'), 'noc');
|
|
80
|
+
await r.installFromPath(bundle);
|
|
81
|
+
|
|
82
|
+
const ws = await fs.mkdtemp(path.join(os.tmpdir(), 'ws-'));
|
|
83
|
+
await r.activateInWorkspace(ws, 'noc-ops');
|
|
84
|
+
await assert.rejects(() => r.uninstall('noc-ops', { trackedWorkspaces: [ws] }), /active/);
|
|
85
|
+
|
|
86
|
+
await fs.rm(bundle, { recursive: true, force: true });
|
|
87
|
+
await fs.rm(ws, { recursive: true, force: true });
|
|
88
|
+
});
|
|
89
|
+
});
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
// PersonaRegistry — install / list / activate / switch. Spec §2.5.
|
|
2
|
+
import * as fs from 'node:fs/promises';
|
|
3
|
+
import * as path from 'node:path';
|
|
4
|
+
import { parsePersonaManifest, type PersonaManifest } from './manifest.js';
|
|
5
|
+
|
|
6
|
+
export interface RegistryOptions {
|
|
7
|
+
ottoHome: string; // typically ~/.otto
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export interface ActiveRecord {
|
|
11
|
+
active: string;
|
|
12
|
+
activated_at: string;
|
|
13
|
+
memory_seed_applied: boolean;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
async function dirExists(p: string): Promise<boolean> {
|
|
17
|
+
try {
|
|
18
|
+
const s = await fs.stat(p);
|
|
19
|
+
return s.isDirectory();
|
|
20
|
+
} catch (err: unknown) {
|
|
21
|
+
if ((err as NodeJS.ErrnoException).code === 'ENOENT') return false;
|
|
22
|
+
throw err;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
async function copyDir(src: string, dst: string): Promise<void> {
|
|
27
|
+
await fs.mkdir(dst, { recursive: true });
|
|
28
|
+
const entries = await fs.readdir(src, { withFileTypes: true });
|
|
29
|
+
for (const e of entries) {
|
|
30
|
+
const s = path.join(src, e.name);
|
|
31
|
+
const d = path.join(dst, e.name);
|
|
32
|
+
if (e.isDirectory()) {
|
|
33
|
+
await copyDir(s, d);
|
|
34
|
+
} else {
|
|
35
|
+
await fs.copyFile(s, d);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export class PersonaRegistry {
|
|
41
|
+
#personasDir: string;
|
|
42
|
+
|
|
43
|
+
constructor(opts: RegistryOptions) {
|
|
44
|
+
this.#personasDir = path.join(opts.ottoHome, 'personas');
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
async ensureDefaultInstalled(): Promise<void> {
|
|
48
|
+
const target = path.join(this.#personasDir, 'default');
|
|
49
|
+
if (await dirExists(target)) return;
|
|
50
|
+
// Source: bundled defaults shipped with this package
|
|
51
|
+
const here = path.dirname(new URL(import.meta.url).pathname);
|
|
52
|
+
const source = path.join(here, 'defaults');
|
|
53
|
+
await copyDir(source, target);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
async list(): Promise<PersonaManifest[]> {
|
|
57
|
+
if (!(await dirExists(this.#personasDir))) return [];
|
|
58
|
+
const entries = await fs.readdir(this.#personasDir, { withFileTypes: true });
|
|
59
|
+
const out: PersonaManifest[] = [];
|
|
60
|
+
for (const e of entries) {
|
|
61
|
+
if (!e.isDirectory()) continue;
|
|
62
|
+
const manifestPath = path.join(this.#personasDir, e.name, 'manifest.yaml');
|
|
63
|
+
try {
|
|
64
|
+
const raw = await fs.readFile(manifestPath, 'utf8');
|
|
65
|
+
out.push(parsePersonaManifest(raw));
|
|
66
|
+
} catch {
|
|
67
|
+
// skip malformed bundles
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
return out;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
async installFromPath(bundlePath: string): Promise<PersonaManifest> {
|
|
74
|
+
const manifestPath = path.join(bundlePath, 'manifest.yaml');
|
|
75
|
+
let raw: string;
|
|
76
|
+
try {
|
|
77
|
+
raw = await fs.readFile(manifestPath, 'utf8');
|
|
78
|
+
} catch (err: unknown) {
|
|
79
|
+
if ((err as NodeJS.ErrnoException).code === 'ENOENT') {
|
|
80
|
+
throw new Error(`bundle missing manifest.yaml at ${manifestPath}`);
|
|
81
|
+
}
|
|
82
|
+
throw err;
|
|
83
|
+
}
|
|
84
|
+
const manifest = parsePersonaManifest(raw);
|
|
85
|
+
const target = path.join(this.#personasDir, manifest.name);
|
|
86
|
+
await fs.rm(target, { recursive: true, force: true });
|
|
87
|
+
await copyDir(bundlePath, target);
|
|
88
|
+
return manifest;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
async activateInWorkspace(workspaceRoot: string, name: string): Promise<void> {
|
|
92
|
+
const persona = await this.get(name);
|
|
93
|
+
if (!persona) throw new Error(`persona not installed: ${name}`);
|
|
94
|
+
const wsOtto = path.join(workspaceRoot, '.otto');
|
|
95
|
+
await fs.mkdir(wsOtto, { recursive: true });
|
|
96
|
+
const record: ActiveRecord = {
|
|
97
|
+
active: name,
|
|
98
|
+
activated_at: new Date().toISOString(),
|
|
99
|
+
memory_seed_applied: false,
|
|
100
|
+
};
|
|
101
|
+
await fs.writeFile(path.join(wsOtto, 'persona.json'), JSON.stringify(record, null, 2));
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
async activeInWorkspace(workspaceRoot: string): Promise<PersonaManifest> {
|
|
105
|
+
const recordPath = path.join(workspaceRoot, '.otto', 'persona.json');
|
|
106
|
+
try {
|
|
107
|
+
const raw = await fs.readFile(recordPath, 'utf8');
|
|
108
|
+
const record = JSON.parse(raw) as ActiveRecord;
|
|
109
|
+
const m = await this.get(record.active);
|
|
110
|
+
if (m) return m;
|
|
111
|
+
} catch {
|
|
112
|
+
// fall through to default
|
|
113
|
+
}
|
|
114
|
+
const def = await this.get('default');
|
|
115
|
+
if (!def) throw new Error('default persona not installed');
|
|
116
|
+
return def;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
async get(name: string): Promise<PersonaManifest | null> {
|
|
120
|
+
const manifestPath = path.join(this.#personasDir, name, 'manifest.yaml');
|
|
121
|
+
try {
|
|
122
|
+
const raw = await fs.readFile(manifestPath, 'utf8');
|
|
123
|
+
return parsePersonaManifest(raw);
|
|
124
|
+
} catch {
|
|
125
|
+
return null;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
async uninstall(name: string, opts: { trackedWorkspaces: string[] }): Promise<void> {
|
|
130
|
+
if (name === 'default') {
|
|
131
|
+
throw new Error('cannot uninstall the built-in default persona');
|
|
132
|
+
}
|
|
133
|
+
for (const ws of opts.trackedWorkspaces) {
|
|
134
|
+
try {
|
|
135
|
+
const raw = await fs.readFile(path.join(ws, '.otto', 'persona.json'), 'utf8');
|
|
136
|
+
const record = JSON.parse(raw) as ActiveRecord;
|
|
137
|
+
if (record.active === name) {
|
|
138
|
+
throw new Error(`persona ${name} is active in workspace ${ws}; switch first`);
|
|
139
|
+
}
|
|
140
|
+
} catch (err: unknown) {
|
|
141
|
+
if ((err as NodeJS.ErrnoException).code === 'ENOENT') continue;
|
|
142
|
+
if (err instanceof Error && err.message.startsWith('persona ')) throw err;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
await fs.rm(path.join(this.#personasDir, name), { recursive: true, force: true });
|
|
146
|
+
}
|
|
147
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"module": "NodeNext",
|
|
4
|
+
"moduleResolution": "NodeNext",
|
|
5
|
+
"target": "ES2022",
|
|
6
|
+
"outDir": "dist",
|
|
7
|
+
"rootDir": "src",
|
|
8
|
+
"strict": true,
|
|
9
|
+
"declaration": true,
|
|
10
|
+
"esModuleInterop": true,
|
|
11
|
+
"skipLibCheck": true
|
|
12
|
+
},
|
|
13
|
+
"include": ["src"],
|
|
14
|
+
"exclude": ["src/**/*.test.ts"]
|
|
15
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
export declare const CELLS_SCHEMA_VERSION = 1;
|
|
2
|
+
export interface CellEntry {
|
|
3
|
+
id: number;
|
|
4
|
+
parentId: number | null;
|
|
5
|
+
code: string;
|
|
6
|
+
ok: boolean;
|
|
7
|
+
value?: unknown;
|
|
8
|
+
error?: {
|
|
9
|
+
name: string;
|
|
10
|
+
message: string;
|
|
11
|
+
};
|
|
12
|
+
stdout: string;
|
|
13
|
+
ts: string;
|
|
14
|
+
}
|
|
15
|
+
export interface AppendInput {
|
|
16
|
+
code: string;
|
|
17
|
+
ok: boolean;
|
|
18
|
+
value?: unknown;
|
|
19
|
+
error?: {
|
|
20
|
+
name: string;
|
|
21
|
+
message: string;
|
|
22
|
+
};
|
|
23
|
+
stdout: string;
|
|
24
|
+
}
|
|
25
|
+
export declare class CellArchive {
|
|
26
|
+
#private;
|
|
27
|
+
private readonly dir;
|
|
28
|
+
private readonly now;
|
|
29
|
+
private readonly path;
|
|
30
|
+
private nextId;
|
|
31
|
+
constructor(dir: string, now?: () => number);
|
|
32
|
+
private scan;
|
|
33
|
+
private ensureHeader;
|
|
34
|
+
append(input: AppendInput): CellEntry;
|
|
35
|
+
get lastId(): number | null;
|
|
36
|
+
get leafId(): number | null;
|
|
37
|
+
setLeaf(id: number | null): void;
|
|
38
|
+
reset(): void;
|
|
39
|
+
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { appendFileSync, existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
export const CELLS_SCHEMA_VERSION = 1;
|
|
4
|
+
export class CellArchive {
|
|
5
|
+
dir;
|
|
6
|
+
now;
|
|
7
|
+
path;
|
|
8
|
+
nextId;
|
|
9
|
+
#lastId;
|
|
10
|
+
#leafId;
|
|
11
|
+
constructor(dir, now = Date.now) {
|
|
12
|
+
this.dir = dir;
|
|
13
|
+
this.now = now;
|
|
14
|
+
this.path = join(dir, 'cells.jsonl');
|
|
15
|
+
const { nextId, lastId } = this.scan();
|
|
16
|
+
this.nextId = nextId;
|
|
17
|
+
this.#lastId = lastId;
|
|
18
|
+
this.#leafId = lastId;
|
|
19
|
+
}
|
|
20
|
+
scan() {
|
|
21
|
+
if (!existsSync(this.path))
|
|
22
|
+
return { nextId: 1, lastId: null };
|
|
23
|
+
let lastId = null;
|
|
24
|
+
for (const line of readFileSync(this.path, 'utf8').split('\n')) {
|
|
25
|
+
if (!line.trim())
|
|
26
|
+
continue;
|
|
27
|
+
try {
|
|
28
|
+
const obj = JSON.parse(line);
|
|
29
|
+
if (typeof obj.id === 'number')
|
|
30
|
+
lastId = obj.id;
|
|
31
|
+
}
|
|
32
|
+
catch {
|
|
33
|
+
// header or corrupt line -> ignore
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
return { nextId: (lastId ?? 0) + 1, lastId };
|
|
37
|
+
}
|
|
38
|
+
ensureHeader() {
|
|
39
|
+
if (existsSync(this.path))
|
|
40
|
+
return;
|
|
41
|
+
mkdirSync(this.dir, { recursive: true });
|
|
42
|
+
appendFileSync(this.path, JSON.stringify({ type: 'header', version: CELLS_SCHEMA_VERSION }) + '\n');
|
|
43
|
+
}
|
|
44
|
+
append(input) {
|
|
45
|
+
this.ensureHeader();
|
|
46
|
+
const id = this.nextId++;
|
|
47
|
+
const entry = {
|
|
48
|
+
id,
|
|
49
|
+
parentId: this.#leafId,
|
|
50
|
+
code: input.code,
|
|
51
|
+
ok: input.ok,
|
|
52
|
+
...(input.ok ? { value: input.value } : { error: input.error }),
|
|
53
|
+
stdout: input.stdout,
|
|
54
|
+
ts: new Date(this.now()).toISOString(),
|
|
55
|
+
};
|
|
56
|
+
appendFileSync(this.path, JSON.stringify(entry) + '\n');
|
|
57
|
+
this.#lastId = id;
|
|
58
|
+
this.#leafId = id;
|
|
59
|
+
return entry;
|
|
60
|
+
}
|
|
61
|
+
get lastId() {
|
|
62
|
+
return this.#lastId;
|
|
63
|
+
}
|
|
64
|
+
get leafId() {
|
|
65
|
+
return this.#leafId;
|
|
66
|
+
}
|
|
67
|
+
setLeaf(id) {
|
|
68
|
+
this.#leafId = id;
|
|
69
|
+
}
|
|
70
|
+
reset() {
|
|
71
|
+
mkdirSync(this.dir, { recursive: true });
|
|
72
|
+
writeFileSync(this.path, JSON.stringify({ type: 'header', version: CELLS_SCHEMA_VERSION }) + '\n');
|
|
73
|
+
this.nextId = 1;
|
|
74
|
+
this.#lastId = null;
|
|
75
|
+
this.#leafId = null;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { CellEntry } from './cell-archive.js';
|
|
2
|
+
export interface TreeNode {
|
|
3
|
+
cell: CellEntry;
|
|
4
|
+
children: TreeNode[];
|
|
5
|
+
}
|
|
6
|
+
export interface CellTree {
|
|
7
|
+
root: TreeNode | null;
|
|
8
|
+
byId: Map<number, TreeNode>;
|
|
9
|
+
orphans: TreeNode[];
|
|
10
|
+
}
|
|
11
|
+
export declare function projectTree(cells: CellEntry[]): CellTree;
|
|
12
|
+
export declare function findLeaves(tree: CellTree): TreeNode[];
|
|
13
|
+
export declare function validateLeafId(tree: CellTree, id: number): void;
|
|
14
|
+
export declare function formatTreeText(tree: CellTree, currentLeaf?: number | null): string;
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
export function projectTree(cells) {
|
|
2
|
+
const byId = new Map();
|
|
3
|
+
for (const cell of cells)
|
|
4
|
+
byId.set(cell.id, { cell, children: [] });
|
|
5
|
+
const orphans = [];
|
|
6
|
+
const rootCandidates = [];
|
|
7
|
+
for (const cell of cells) {
|
|
8
|
+
const node = byId.get(cell.id);
|
|
9
|
+
if (cell.parentId === null) {
|
|
10
|
+
rootCandidates.push(node);
|
|
11
|
+
continue;
|
|
12
|
+
}
|
|
13
|
+
const parent = byId.get(cell.parentId);
|
|
14
|
+
if (parent)
|
|
15
|
+
parent.children.push(node);
|
|
16
|
+
else
|
|
17
|
+
orphans.push(node);
|
|
18
|
+
}
|
|
19
|
+
let root = null;
|
|
20
|
+
if (rootCandidates.length >= 1) {
|
|
21
|
+
root = rootCandidates[0];
|
|
22
|
+
// 1d/1d2 invariant: exactly one root. Defensive: extra roots become orphans.
|
|
23
|
+
for (let i = 1; i < rootCandidates.length; i++)
|
|
24
|
+
orphans.push(rootCandidates[i]);
|
|
25
|
+
}
|
|
26
|
+
return { root, byId, orphans };
|
|
27
|
+
}
|
|
28
|
+
export function findLeaves(tree) {
|
|
29
|
+
const out = [];
|
|
30
|
+
for (const node of tree.byId.values()) {
|
|
31
|
+
if (node.children.length === 0)
|
|
32
|
+
out.push(node);
|
|
33
|
+
}
|
|
34
|
+
return out;
|
|
35
|
+
}
|
|
36
|
+
export function validateLeafId(tree, id) {
|
|
37
|
+
if (!tree.byId.has(id)) {
|
|
38
|
+
throw new Error(`cell id ${id} not found`);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
function truncate(s, max) {
|
|
42
|
+
if (s.length <= max)
|
|
43
|
+
return s;
|
|
44
|
+
return s.slice(0, max - 1) + '…';
|
|
45
|
+
}
|
|
46
|
+
function summarizeCell(cell) {
|
|
47
|
+
const okFlag = cell.ok ? 'ok ' : 'err';
|
|
48
|
+
const detail = cell.ok
|
|
49
|
+
? `value=${truncate(JSON.stringify(cell.value ?? null), 40)}`
|
|
50
|
+
: `error=${truncate(cell.error?.message ?? '', 40)}`;
|
|
51
|
+
const codePreview = truncate(cell.code.split('\n')[0], 60);
|
|
52
|
+
return `#${cell.id} ${okFlag} ${detail.padEnd(45)} ${codePreview}`;
|
|
53
|
+
}
|
|
54
|
+
function renderNode(node, depth, lastSibling, currentLeaf, out) {
|
|
55
|
+
const indent = ' '.repeat(depth);
|
|
56
|
+
const connector = lastSibling ? '└─' : '├─';
|
|
57
|
+
const marker = currentLeaf === node.cell.id ? ' *' : '';
|
|
58
|
+
out.push(`${indent}${connector} ${summarizeCell(node.cell)}${marker}`);
|
|
59
|
+
const last = node.children.length - 1;
|
|
60
|
+
node.children.forEach((child, i) => renderNode(child, depth + 1, i === last, currentLeaf, out));
|
|
61
|
+
}
|
|
62
|
+
export function formatTreeText(tree, currentLeaf) {
|
|
63
|
+
const lines = [];
|
|
64
|
+
if (tree.root)
|
|
65
|
+
renderNode(tree.root, 0, true, currentLeaf ?? null, lines);
|
|
66
|
+
if (tree.orphans.length > 0) {
|
|
67
|
+
lines.push('# orphans:');
|
|
68
|
+
const last = tree.orphans.length - 1;
|
|
69
|
+
tree.orphans.forEach((o, i) => renderNode(o, 0, i === last, currentLeaf ?? null, lines));
|
|
70
|
+
}
|
|
71
|
+
return lines.join('\n');
|
|
72
|
+
}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import type { CredentialInjector } from '@otto/coworker-vault';
|
|
2
|
+
import type { ArtifactCreateDrawer, DataLoadDrawer, RecoveryNote, SnapshotResult } from './kernel-protocol.js';
|
|
3
|
+
export interface CellResult {
|
|
4
|
+
value: unknown;
|
|
5
|
+
stdout: string;
|
|
6
|
+
}
|
|
7
|
+
export interface ChildProcessRuntimeOptions {
|
|
8
|
+
workspace: string;
|
|
9
|
+
onDataLoad?: (drawer: DataLoadDrawer) => void;
|
|
10
|
+
cellTimeoutMs?: number;
|
|
11
|
+
inactivityTimeoutMs?: number;
|
|
12
|
+
inactivityAfterProgressMs?: number;
|
|
13
|
+
cancelGraceMs?: number;
|
|
14
|
+
entryPath?: string;
|
|
15
|
+
scratchpadDir?: string;
|
|
16
|
+
/**
|
|
17
|
+
* Phase 2 Task 13: optional vault credential injector. When provided alongside
|
|
18
|
+
* a non-empty `bindings`, the runtime adds OTTO_DS_* env vars to the spawned
|
|
19
|
+
* kernel's environment (after the existing env filter). Absent => no-op; the
|
|
20
|
+
* runtime behaves exactly as it did pre-Phase-2.
|
|
21
|
+
*/
|
|
22
|
+
injector?: CredentialInjector;
|
|
23
|
+
bindings?: string[];
|
|
24
|
+
/**
|
|
25
|
+
* Phase 2 Task 13: identifies this runtime's scratchpad for audit records the
|
|
26
|
+
* injector emits. The runtime itself doesn't otherwise use this field.
|
|
27
|
+
*/
|
|
28
|
+
scratchpadName?: string;
|
|
29
|
+
/**
|
|
30
|
+
* Phase 2 Task 13: session id stamped on audit records the injector emits.
|
|
31
|
+
* Empty string is a valid no-session value.
|
|
32
|
+
*/
|
|
33
|
+
sessionId?: string;
|
|
34
|
+
/**
|
|
35
|
+
* Phase 4 Task 10: Layer-B fan-out for artifact_create events. The kernel
|
|
36
|
+
* emits one of these after every successful otto.artifact.create RPC; the
|
|
37
|
+
* runtime forwards the drawer to this callback so the manager can record it
|
|
38
|
+
* into memory. Absent => artifact_create events are dropped.
|
|
39
|
+
*/
|
|
40
|
+
onArtifactCreate?: (drawer: ArtifactCreateDrawer) => void;
|
|
41
|
+
/**
|
|
42
|
+
* Phase 4 Task 10: parent-side handler for `artifact_create` RPC requests.
|
|
43
|
+
* The runtime calls this when it sees an `{type:'request', request:'artifact_create'}`
|
|
44
|
+
* frame on the child's stdout and writes the resolved response (or an error
|
|
45
|
+
* frame) back to the child's stdin. If absent, the request is rejected with
|
|
46
|
+
* "artifacts unavailable" so the cell fails fast instead of hanging.
|
|
47
|
+
*/
|
|
48
|
+
handleArtifactCreate?: (req: {
|
|
49
|
+
kind: string;
|
|
50
|
+
name: string;
|
|
51
|
+
}) => Promise<{
|
|
52
|
+
slug: string;
|
|
53
|
+
uri: string;
|
|
54
|
+
primary_path: string;
|
|
55
|
+
}>;
|
|
56
|
+
/**
|
|
57
|
+
* Phase 4 Task 10: parent-side handler for `artifact_update` RPC requests.
|
|
58
|
+
* Mirror of handleArtifactCreate for the update path.
|
|
59
|
+
*/
|
|
60
|
+
handleArtifactUpdate?: (req: {
|
|
61
|
+
slug: string;
|
|
62
|
+
files: Array<{
|
|
63
|
+
path: string;
|
|
64
|
+
content: string;
|
|
65
|
+
}>;
|
|
66
|
+
}) => Promise<{
|
|
67
|
+
files_touched: string[];
|
|
68
|
+
}>;
|
|
69
|
+
}
|
|
70
|
+
export declare class ChildProcessRuntime {
|
|
71
|
+
private readonly options;
|
|
72
|
+
private child;
|
|
73
|
+
private readonly pending;
|
|
74
|
+
private readonly pendingSnapshots;
|
|
75
|
+
private activeId;
|
|
76
|
+
private nextId;
|
|
77
|
+
private alive;
|
|
78
|
+
private childReady;
|
|
79
|
+
private disposed;
|
|
80
|
+
private restartsSinceSuccess;
|
|
81
|
+
private recoveryNotes_;
|
|
82
|
+
private resolveReady;
|
|
83
|
+
private rejectReady;
|
|
84
|
+
private ready;
|
|
85
|
+
/**
|
|
86
|
+
* Phase 2 Task 13: timestamp of the most recent successful spawn(). Used by
|
|
87
|
+
* higher-level staleness checks (Task 15) to decide whether a warm kernel's
|
|
88
|
+
* env-injected credentials need to be refreshed. Pre-start() value is epoch
|
|
89
|
+
* so callers can distinguish "never spawned" without nullable juggling.
|
|
90
|
+
*/
|
|
91
|
+
spawnTime: Date;
|
|
92
|
+
constructor(options: ChildProcessRuntimeOptions);
|
|
93
|
+
start(): Promise<void>;
|
|
94
|
+
/**
|
|
95
|
+
* Phase 2 Task 13: env construction split out so the injector hop has a clean
|
|
96
|
+
* seam to extend. Existing semantics unchanged: filterEnv applies the kernel's
|
|
97
|
+
* allowlist/denylist, then (when configured) the injector overlays OTTO_DS_*
|
|
98
|
+
* vars from vault entries. Only the spawned child sees the result; the parent
|
|
99
|
+
* process.env is never mutated.
|
|
100
|
+
*/
|
|
101
|
+
private buildBaseEnv;
|
|
102
|
+
private spawnChild;
|
|
103
|
+
private readLoop;
|
|
104
|
+
private resetInactivity;
|
|
105
|
+
private onInactivityTimeout;
|
|
106
|
+
private onTotalTimeout;
|
|
107
|
+
runCell(code: string): Promise<CellResult>;
|
|
108
|
+
cancel(): Promise<void>;
|
|
109
|
+
snapshot(): Promise<SnapshotResult>;
|
|
110
|
+
/**
|
|
111
|
+
* Phase 4 Task 10: service an `artifact_create` RPC request from the kernel.
|
|
112
|
+
* Calls the manager-supplied handler (if any), serializes the result into a
|
|
113
|
+
* `{type:'response', request:'artifact_create'}` frame, and writes it back
|
|
114
|
+
* to the child's stdin. Errors are surfaced to the kernel as `ok:false`
|
|
115
|
+
* frames so the awaiting cell rejects cleanly rather than hanging.
|
|
116
|
+
*/
|
|
117
|
+
private handleArtifactCreateRpc;
|
|
118
|
+
/**
|
|
119
|
+
* Phase 4 Task 10: service an `artifact_update` RPC request. Mirror of
|
|
120
|
+
* handleArtifactCreateRpc for the update path.
|
|
121
|
+
*/
|
|
122
|
+
private handleArtifactUpdateRpc;
|
|
123
|
+
private rejectActive;
|
|
124
|
+
private failAllPending;
|
|
125
|
+
private markDead;
|
|
126
|
+
get hasActiveCell(): boolean;
|
|
127
|
+
get recoveryNotes(): readonly RecoveryNote[];
|
|
128
|
+
dispose(): Promise<void>;
|
|
129
|
+
}
|