@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,40 @@
|
|
|
1
|
+
import { describe, it, before, after } from 'node:test';
|
|
2
|
+
import assert from 'node:assert/strict';
|
|
3
|
+
import { homedir } from 'node:os';
|
|
4
|
+
import { join } from 'node:path';
|
|
5
|
+
import { getCoworkerGlobalDir, getScratchpadsRoot } from './_coworker-paths.js';
|
|
6
|
+
|
|
7
|
+
const ORIGINAL_GLOBAL = process.env.OTTO_COWORKER_GLOBAL_DIR;
|
|
8
|
+
const ORIGINAL_SCRATCH = process.env.OTTO_SCRATCHPAD_ROOT;
|
|
9
|
+
|
|
10
|
+
describe('_coworker-paths', () => {
|
|
11
|
+
before(() => {
|
|
12
|
+
delete process.env.OTTO_COWORKER_GLOBAL_DIR;
|
|
13
|
+
delete process.env.OTTO_SCRATCHPAD_ROOT;
|
|
14
|
+
});
|
|
15
|
+
after(() => {
|
|
16
|
+
if (ORIGINAL_GLOBAL !== undefined) process.env.OTTO_COWORKER_GLOBAL_DIR = ORIGINAL_GLOBAL;
|
|
17
|
+
else delete process.env.OTTO_COWORKER_GLOBAL_DIR;
|
|
18
|
+
if (ORIGINAL_SCRATCH !== undefined) process.env.OTTO_SCRATCHPAD_ROOT = ORIGINAL_SCRATCH;
|
|
19
|
+
else delete process.env.OTTO_SCRATCHPAD_ROOT;
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
it('getCoworkerGlobalDir defaults to ~/.otto', () => {
|
|
23
|
+
delete process.env.OTTO_COWORKER_GLOBAL_DIR;
|
|
24
|
+
assert.equal(getCoworkerGlobalDir(), join(homedir(), '.otto'));
|
|
25
|
+
});
|
|
26
|
+
it('getCoworkerGlobalDir respects OTTO_COWORKER_GLOBAL_DIR env', () => {
|
|
27
|
+
process.env.OTTO_COWORKER_GLOBAL_DIR = '/tmp/otto-test';
|
|
28
|
+
assert.equal(getCoworkerGlobalDir(), '/tmp/otto-test');
|
|
29
|
+
delete process.env.OTTO_COWORKER_GLOBAL_DIR;
|
|
30
|
+
});
|
|
31
|
+
it('getScratchpadsRoot defaults to ~/.otto/scratchpads', () => {
|
|
32
|
+
delete process.env.OTTO_SCRATCHPAD_ROOT;
|
|
33
|
+
assert.equal(getScratchpadsRoot(), join(homedir(), '.otto', 'scratchpads'));
|
|
34
|
+
});
|
|
35
|
+
it('getScratchpadsRoot respects OTTO_SCRATCHPAD_ROOT env', () => {
|
|
36
|
+
process.env.OTTO_SCRATCHPAD_ROOT = '/tmp/sp-test';
|
|
37
|
+
assert.equal(getScratchpadsRoot(), '/tmp/sp-test');
|
|
38
|
+
delete process.env.OTTO_SCRATCHPAD_ROOT;
|
|
39
|
+
});
|
|
40
|
+
});
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { homedir } from 'node:os';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
|
|
4
|
+
export function getCoworkerGlobalDir(): string {
|
|
5
|
+
return process.env.OTTO_COWORKER_GLOBAL_DIR ?? join(homedir(), '.otto');
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export function getScratchpadsRoot(): string {
|
|
9
|
+
return process.env.OTTO_SCRATCHPAD_ROOT ?? join(homedir(), '.otto', 'scratchpads');
|
|
10
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
// src/resources/extensions/coworker-artifacts/artifacts-command.test.ts
|
|
2
|
+
import { describe, it } from 'node:test';
|
|
3
|
+
import assert from 'node:assert/strict';
|
|
4
|
+
import { mkdtempSync, existsSync } from 'node:fs';
|
|
5
|
+
import { tmpdir } from 'node:os';
|
|
6
|
+
import { join } from 'node:path';
|
|
7
|
+
import { ArtifactStore } from '@otto/coworker-artifacts';
|
|
8
|
+
import { runArtifactsCommand } from './artifacts-command.js';
|
|
9
|
+
|
|
10
|
+
describe('/artifacts command', () => {
|
|
11
|
+
it('list returns markdown table', async () => {
|
|
12
|
+
const store = new ArtifactStore({ workspaceDir: mkdtempSync(join(tmpdir(), 'ac-')) });
|
|
13
|
+
await store.create('report', 'a');
|
|
14
|
+
const out = await runArtifactsCommand(store, ['list']);
|
|
15
|
+
assert.match(out.message, /### Artifacts \(1\)/);
|
|
16
|
+
});
|
|
17
|
+
it('bare invocation defaults to list', async () => {
|
|
18
|
+
const store = new ArtifactStore({ workspaceDir: mkdtempSync(join(tmpdir(), 'ac2-')) });
|
|
19
|
+
const out = await runArtifactsCommand(store, []);
|
|
20
|
+
assert.match(out.message, /### Artifacts \(0\)/);
|
|
21
|
+
});
|
|
22
|
+
it('show <slug> dumps content + provenance', async () => {
|
|
23
|
+
const store = new ArtifactStore({ workspaceDir: mkdtempSync(join(tmpdir(), 'ac3-')) });
|
|
24
|
+
const h = await store.create('report', 'r');
|
|
25
|
+
await store.update(h, [{ path: 'report.md', content: '# yo\n' }]);
|
|
26
|
+
const out = await runArtifactsCommand(store, ['show', 'r']);
|
|
27
|
+
assert.match(out.message, /# yo/);
|
|
28
|
+
});
|
|
29
|
+
it('remove --confirm deletes', async () => {
|
|
30
|
+
const ws = mkdtempSync(join(tmpdir(), 'ac4-'));
|
|
31
|
+
const store = new ArtifactStore({ workspaceDir: ws });
|
|
32
|
+
const h = await store.create('report', 'r');
|
|
33
|
+
const out = await runArtifactsCommand(store, ['remove', 'r', '--confirm']);
|
|
34
|
+
assert.match(out.message, /removed: r/);
|
|
35
|
+
assert.equal(existsSync(h.dir), false);
|
|
36
|
+
});
|
|
37
|
+
it('remove without --confirm errors', async () => {
|
|
38
|
+
const store = new ArtifactStore({ workspaceDir: mkdtempSync(join(tmpdir(), 'ac5-')) });
|
|
39
|
+
await store.create('report', 'r');
|
|
40
|
+
await assert.rejects(() => runArtifactsCommand(store, ['remove', 'r']));
|
|
41
|
+
});
|
|
42
|
+
it('unknown subcommand errors', async () => {
|
|
43
|
+
const store = new ArtifactStore({ workspaceDir: mkdtempSync(join(tmpdir(), 'ac6-')) });
|
|
44
|
+
await assert.rejects(() => runArtifactsCommand(store, ['banana']));
|
|
45
|
+
});
|
|
46
|
+
it('remove --confirm <slug> (flag-first) also deletes', async () => {
|
|
47
|
+
const ws = mkdtempSync(join(tmpdir(), 'ac-flag-'));
|
|
48
|
+
const store = new ArtifactStore({ workspaceDir: ws });
|
|
49
|
+
const h = await store.create('report', 'r');
|
|
50
|
+
const out = await runArtifactsCommand(store, ['remove', '--confirm', 'r']);
|
|
51
|
+
assert.match(out.message, /removed: r/);
|
|
52
|
+
assert.equal(existsSync(h.dir), false);
|
|
53
|
+
});
|
|
54
|
+
});
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
// src/resources/extensions/coworker-artifacts/artifacts-command.ts
|
|
2
|
+
//
|
|
3
|
+
// /artifacts slash command dispatcher. Subcommands:
|
|
4
|
+
// list (default) — markdown table of artifacts in this workspace
|
|
5
|
+
// show <slug> — body + recent provenance for one artifact
|
|
6
|
+
// remove <slug> --confirm — destructive delete, gated by --confirm
|
|
7
|
+
import type { ArtifactStore } from '@otto/coworker-artifacts';
|
|
8
|
+
import { runListArtifacts } from './list-tool.js';
|
|
9
|
+
import { runOpenArtifact } from './open-tool.js';
|
|
10
|
+
|
|
11
|
+
export interface ArtifactsCommandResult {
|
|
12
|
+
message: string;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export async function runArtifactsCommand(
|
|
16
|
+
store: ArtifactStore,
|
|
17
|
+
argv: string[],
|
|
18
|
+
): Promise<ArtifactsCommandResult> {
|
|
19
|
+
const [sub, ...rest] = argv;
|
|
20
|
+
switch (sub) {
|
|
21
|
+
case 'list':
|
|
22
|
+
case undefined: {
|
|
23
|
+
const out = await runListArtifacts(store);
|
|
24
|
+
return { message: out.markdown };
|
|
25
|
+
}
|
|
26
|
+
case 'show': {
|
|
27
|
+
const slug = rest[0];
|
|
28
|
+
if (!slug) throw new Error('Usage: /artifacts show <slug>');
|
|
29
|
+
const out = await runOpenArtifact(store, { slug });
|
|
30
|
+
return { message: out.markdown };
|
|
31
|
+
}
|
|
32
|
+
case 'remove': {
|
|
33
|
+
const slug = rest.find((a) => !a.startsWith('--'));
|
|
34
|
+
const confirm = rest.includes('--confirm');
|
|
35
|
+
if (!slug) throw new Error('Usage: /artifacts remove <slug> --confirm');
|
|
36
|
+
if (!confirm) throw new Error('Usage: /artifacts remove <slug> --confirm');
|
|
37
|
+
await store.remove(slug, true);
|
|
38
|
+
return { message: `removed: ${slug}` };
|
|
39
|
+
}
|
|
40
|
+
default:
|
|
41
|
+
throw new Error(`Unknown /artifacts subcommand: ${sub}. Try: list, show, remove.`);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
// src/resources/extensions/coworker-artifacts/artifacts-singleton.test.ts
|
|
2
|
+
import { describe, it } from 'node:test';
|
|
3
|
+
import assert from 'node:assert/strict';
|
|
4
|
+
import { mkdtempSync } from 'node:fs';
|
|
5
|
+
import { tmpdir } from 'node:os';
|
|
6
|
+
import { join } from 'node:path';
|
|
7
|
+
import { createArtifactsBundle } from './artifacts-singleton.js';
|
|
8
|
+
|
|
9
|
+
describe('createArtifactsBundle', () => {
|
|
10
|
+
it('returns bundle with ArtifactStore', async () => {
|
|
11
|
+
const ws = mkdtempSync(join(tmpdir(), 'art-bundle-'));
|
|
12
|
+
const b = await createArtifactsBundle({ workspaceDir: ws });
|
|
13
|
+
assert.ok(b.store);
|
|
14
|
+
assert.equal(b.workspaceDir, ws);
|
|
15
|
+
await b.dispose();
|
|
16
|
+
});
|
|
17
|
+
it('store creates an artifact in the workspace dir', async () => {
|
|
18
|
+
const ws = mkdtempSync(join(tmpdir(), 'art-b2-'));
|
|
19
|
+
const b = await createArtifactsBundle({ workspaceDir: ws });
|
|
20
|
+
const h = await b.store.create('report', 'test');
|
|
21
|
+
assert.equal(h.slug, 'test');
|
|
22
|
+
assert.match(h.dir, /\.otto\/artifacts\/test$/);
|
|
23
|
+
await b.dispose();
|
|
24
|
+
});
|
|
25
|
+
});
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
// src/resources/extensions/coworker-artifacts/artifacts-singleton.ts
|
|
2
|
+
//
|
|
3
|
+
// Factory for the per-session ArtifactStore bundle. Mirrors the Phase 3
|
|
4
|
+
// memory-singleton pattern so the activator can construct/dispose state in
|
|
5
|
+
// one place. dispose() is a no-op in v1 (ArtifactStore holds no async
|
|
6
|
+
// resources) but kept for pattern symmetry with memory + scratchpad bundles.
|
|
7
|
+
import { ArtifactStore } from '@otto/coworker-artifacts';
|
|
8
|
+
|
|
9
|
+
export interface ArtifactsBundleOptions {
|
|
10
|
+
workspaceDir: string;
|
|
11
|
+
now?: () => string;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export interface ArtifactsBundle {
|
|
15
|
+
store: ArtifactStore;
|
|
16
|
+
workspaceDir: string;
|
|
17
|
+
dispose(): Promise<void>;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export async function createArtifactsBundle(opts: ArtifactsBundleOptions): Promise<ArtifactsBundle> {
|
|
21
|
+
const store = new ArtifactStore({ workspaceDir: opts.workspaceDir, now: opts.now });
|
|
22
|
+
return {
|
|
23
|
+
store,
|
|
24
|
+
workspaceDir: opts.workspaceDir,
|
|
25
|
+
async dispose(): Promise<void> {
|
|
26
|
+
/* no async resources in v1 */
|
|
27
|
+
},
|
|
28
|
+
};
|
|
29
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "coworker-artifacts",
|
|
3
|
+
"name": "Co-worker Artifacts",
|
|
4
|
+
"version": "1.0.0",
|
|
5
|
+
"description": "Workspace-scoped artifact store: artifact://<slug> URIs, /artifacts slash, list_artifacts + open_artifact tools",
|
|
6
|
+
"tier": "bundled",
|
|
7
|
+
"requires": { "platform": ">=2.29.0" },
|
|
8
|
+
"provides": {
|
|
9
|
+
"tools": ["list_artifacts", "open_artifact"],
|
|
10
|
+
"commands": ["artifacts"],
|
|
11
|
+
"hooks": ["session_start", "session_shutdown"]
|
|
12
|
+
}
|
|
13
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
// src/resources/extensions/coworker-artifacts/index.test.ts
|
|
2
|
+
import { describe, it } from 'node:test';
|
|
3
|
+
import assert from 'node:assert/strict';
|
|
4
|
+
import { mkdtempSync } from 'node:fs';
|
|
5
|
+
import { tmpdir } from 'node:os';
|
|
6
|
+
import { join } from 'node:path';
|
|
7
|
+
import coworkerArtifactsExtension, { getArtifactStore } from './index.js';
|
|
8
|
+
import { makeFakeApi, fireSessionStart, fireSessionShutdown } from '../coworker-vault/test-helpers.js';
|
|
9
|
+
|
|
10
|
+
describe('coworker-artifacts activator', () => {
|
|
11
|
+
it('barrel exports key surface', () => {
|
|
12
|
+
assert.equal(typeof coworkerArtifactsExtension, 'function');
|
|
13
|
+
assert.equal(typeof getArtifactStore, 'function');
|
|
14
|
+
});
|
|
15
|
+
it('getArtifactStore is null before session_start', () => {
|
|
16
|
+
assert.equal(getArtifactStore(), null);
|
|
17
|
+
});
|
|
18
|
+
it('registers list_artifacts + open_artifact tools and /artifacts command', () => {
|
|
19
|
+
const api = makeFakeApi();
|
|
20
|
+
coworkerArtifactsExtension(api.api);
|
|
21
|
+
assert.ok(api.tools.has('list_artifacts'));
|
|
22
|
+
assert.ok(api.tools.has('open_artifact'));
|
|
23
|
+
assert.ok(api.commands.has('artifacts'));
|
|
24
|
+
});
|
|
25
|
+
it('session_start constructs bundle and getArtifactStore returns store', async () => {
|
|
26
|
+
const api = makeFakeApi();
|
|
27
|
+
coworkerArtifactsExtension(api.api);
|
|
28
|
+
const ws = mkdtempSync(join(tmpdir(), 'art-act-'));
|
|
29
|
+
await fireSessionStart(api, { cwd: ws });
|
|
30
|
+
assert.equal(api.notifyCalls.find((c) => /unavailable/.test(c.message)), undefined);
|
|
31
|
+
assert.ok(getArtifactStore());
|
|
32
|
+
await fireSessionShutdown(api);
|
|
33
|
+
assert.equal(getArtifactStore(), null);
|
|
34
|
+
});
|
|
35
|
+
it('command gates on bundle and notifies "not ready" when session_start never fires', async () => {
|
|
36
|
+
// ArtifactStore is lazy — its constructor doesn't fail even on an empty
|
|
37
|
+
// workspaceDir. The intended assertion of this test is the GATING path:
|
|
38
|
+
// a fresh activator whose session_start was never fired must respond to
|
|
39
|
+
// /artifacts with a "not ready" notify rather than crashing.
|
|
40
|
+
const fresh = makeFakeApi();
|
|
41
|
+
coworkerArtifactsExtension(fresh.api);
|
|
42
|
+
const cmd = fresh.commands.get('artifacts')!;
|
|
43
|
+
await cmd.handler('list', fresh.commandCtx);
|
|
44
|
+
assert.ok(fresh.notifyCalls.find((c) => /not ready/.test(c.message)));
|
|
45
|
+
});
|
|
46
|
+
});
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
// src/resources/extensions/coworker-artifacts/index.ts
|
|
2
|
+
//
|
|
3
|
+
// Coworker Artifacts production activator. Wires the Phase 4 artifact
|
|
4
|
+
// primitives (createArtifactsBundle, runListArtifacts, runOpenArtifact,
|
|
5
|
+
// runArtifactsCommand) into pi's ExtensionAPI so /artifacts, the
|
|
6
|
+
// list_artifacts + open_artifact tools, and the artifact://<slug> store
|
|
7
|
+
// light up in a live Otto session.
|
|
8
|
+
//
|
|
9
|
+
// Cross-pillar surface: the scratchpad activator imports getArtifactStore()
|
|
10
|
+
// from this module so its onArtifactCreate closure can resolve artifact://
|
|
11
|
+
// URIs and bind them to the active scratchpad turn (Phase 4 Task 12).
|
|
12
|
+
import type { ExtensionAPI } from '@otto/pi-coding-agent';
|
|
13
|
+
import { Type } from '@sinclair/typebox';
|
|
14
|
+
import { ArtifactStore } from '@otto/coworker-artifacts';
|
|
15
|
+
import { createArtifactsBundle, type ArtifactsBundle } from './artifacts-singleton.js';
|
|
16
|
+
import { runListArtifacts } from './list-tool.js';
|
|
17
|
+
import { runOpenArtifact } from './open-tool.js';
|
|
18
|
+
import { runArtifactsCommand } from './artifacts-command.js';
|
|
19
|
+
|
|
20
|
+
export { createArtifactsBundle };
|
|
21
|
+
export type { ArtifactsBundle, ArtifactsBundleOptions } from './artifacts-singleton.js';
|
|
22
|
+
|
|
23
|
+
// Cross-pillar export — null before session_start or after session_shutdown.
|
|
24
|
+
let activeStore: ArtifactStore | null = null;
|
|
25
|
+
export function getArtifactStore(): ArtifactStore | null {
|
|
26
|
+
return activeStore;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const LIST_PARAMS = Type.Object({});
|
|
30
|
+
const OPEN_PARAMS = Type.Object({
|
|
31
|
+
slug: Type.String({ description: 'The artifact slug (e.g. "report" or "report-2") to read.' }),
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
// Union TDetails so TS accepts both error and success branches of execute().
|
|
35
|
+
type ListDetails =
|
|
36
|
+
| { error: string; result_count?: undefined }
|
|
37
|
+
| { error?: undefined; result_count: number };
|
|
38
|
+
type OpenDetails =
|
|
39
|
+
| { error: string; slug?: undefined }
|
|
40
|
+
| { error?: undefined; slug: string };
|
|
41
|
+
|
|
42
|
+
export default function coworkerArtifactsExtension(api: ExtensionAPI): void {
|
|
43
|
+
let bundle: ArtifactsBundle | null = null;
|
|
44
|
+
let unavailable = false;
|
|
45
|
+
|
|
46
|
+
api.on('session_start', async (_event, ctx) => {
|
|
47
|
+
try {
|
|
48
|
+
bundle = await createArtifactsBundle({ workspaceDir: ctx.cwd });
|
|
49
|
+
activeStore = bundle.store;
|
|
50
|
+
unavailable = false;
|
|
51
|
+
} catch (err) {
|
|
52
|
+
unavailable = true;
|
|
53
|
+
bundle = null;
|
|
54
|
+
activeStore = null;
|
|
55
|
+
ctx.ui.notify(`artifacts unavailable: ${(err as Error).message}`, 'warning');
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
api.registerTool<typeof LIST_PARAMS, ListDetails>({
|
|
60
|
+
name: 'list_artifacts',
|
|
61
|
+
label: 'List artifacts',
|
|
62
|
+
description: 'List all artifacts in the current workspace.',
|
|
63
|
+
parameters: LIST_PARAMS,
|
|
64
|
+
async execute() {
|
|
65
|
+
if (!bundle) {
|
|
66
|
+
return {
|
|
67
|
+
content: [{ type: 'text', text: 'artifacts unavailable' }],
|
|
68
|
+
details: { error: 'unavailable' },
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
try {
|
|
72
|
+
const out = await runListArtifacts(bundle.store);
|
|
73
|
+
return {
|
|
74
|
+
content: [{ type: 'text', text: out.markdown }],
|
|
75
|
+
details: { result_count: out.artifacts.length },
|
|
76
|
+
};
|
|
77
|
+
} catch (err) {
|
|
78
|
+
return {
|
|
79
|
+
content: [{ type: 'text', text: `list failed: ${(err as Error).message}` }],
|
|
80
|
+
details: { error: (err as Error).message },
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
},
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
api.registerTool<typeof OPEN_PARAMS, OpenDetails>({
|
|
87
|
+
name: 'open_artifact',
|
|
88
|
+
label: 'Open artifact',
|
|
89
|
+
description: 'Read the contents of an artifact by slug. Returns markdown body + recent provenance.',
|
|
90
|
+
parameters: OPEN_PARAMS,
|
|
91
|
+
async execute(_toolCallId, params) {
|
|
92
|
+
if (!bundle) {
|
|
93
|
+
return {
|
|
94
|
+
content: [{ type: 'text', text: 'artifacts unavailable' }],
|
|
95
|
+
details: { error: 'unavailable' },
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
try {
|
|
99
|
+
const out = await runOpenArtifact(bundle.store, params);
|
|
100
|
+
return {
|
|
101
|
+
content: [{ type: 'text', text: out.markdown }],
|
|
102
|
+
details: { slug: params.slug },
|
|
103
|
+
};
|
|
104
|
+
} catch (err) {
|
|
105
|
+
return {
|
|
106
|
+
content: [{ type: 'text', text: `open failed: ${(err as Error).message}` }],
|
|
107
|
+
details: { error: (err as Error).message },
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
},
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
api.registerCommand('artifacts', {
|
|
114
|
+
description: 'Inspect artifacts: /artifacts list | show <slug> | remove <slug> --confirm',
|
|
115
|
+
getArgumentCompletions: (prefix) => {
|
|
116
|
+
const subs = [
|
|
117
|
+
{ label: 'list', description: 'List all artifacts' },
|
|
118
|
+
{ label: 'show', description: 'Show artifact body + provenance: /artifacts show <slug>' },
|
|
119
|
+
{ label: 'remove', description: 'Delete artifact: /artifacts remove <slug> --confirm' },
|
|
120
|
+
];
|
|
121
|
+
return subs
|
|
122
|
+
.filter((s) => s.label.startsWith(prefix))
|
|
123
|
+
.map((s) => ({ value: s.label, label: s.label, description: s.description }));
|
|
124
|
+
},
|
|
125
|
+
handler: async (args, ctx) => {
|
|
126
|
+
if (!bundle) {
|
|
127
|
+
ctx.ui.notify(
|
|
128
|
+
unavailable ? 'artifacts unavailable; chat continues without it.' : 'artifacts not ready yet.',
|
|
129
|
+
'warning',
|
|
130
|
+
);
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
const argv = args.trim().split(/\s+/).filter(Boolean);
|
|
134
|
+
try {
|
|
135
|
+
const result = await runArtifactsCommand(bundle.store, argv);
|
|
136
|
+
ctx.ui.notify(result.message, 'info');
|
|
137
|
+
} catch (err) {
|
|
138
|
+
ctx.ui.notify(`/artifacts failed: ${(err as Error).message}`, 'error');
|
|
139
|
+
}
|
|
140
|
+
},
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
api.on('session_shutdown', async () => {
|
|
144
|
+
if (bundle) {
|
|
145
|
+
try {
|
|
146
|
+
await bundle.dispose();
|
|
147
|
+
} catch {
|
|
148
|
+
/* best effort */
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
bundle = null;
|
|
152
|
+
activeStore = null;
|
|
153
|
+
});
|
|
154
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
// src/resources/extensions/coworker-artifacts/list-tool.test.ts
|
|
2
|
+
import { describe, it } from 'node:test';
|
|
3
|
+
import assert from 'node:assert/strict';
|
|
4
|
+
import { mkdtempSync } from 'node:fs';
|
|
5
|
+
import { tmpdir } from 'node:os';
|
|
6
|
+
import { join } from 'node:path';
|
|
7
|
+
import { ArtifactStore } from '@otto/coworker-artifacts';
|
|
8
|
+
import { runListArtifacts } from './list-tool.js';
|
|
9
|
+
|
|
10
|
+
describe('runListArtifacts', () => {
|
|
11
|
+
it('returns empty when no artifacts', async () => {
|
|
12
|
+
const store = new ArtifactStore({ workspaceDir: mkdtempSync(join(tmpdir(), 'lt-')) });
|
|
13
|
+
const out = await runListArtifacts(store);
|
|
14
|
+
assert.equal(out.artifacts.length, 0);
|
|
15
|
+
assert.match(out.markdown, /### Artifacts \(0\)/);
|
|
16
|
+
});
|
|
17
|
+
it('returns rows with markdown table for present artifacts', async () => {
|
|
18
|
+
const ws = mkdtempSync(join(tmpdir(), 'lt2-'));
|
|
19
|
+
const store = new ArtifactStore({ workspaceDir: ws });
|
|
20
|
+
await store.create('report', 'a');
|
|
21
|
+
await store.create('report', 'b');
|
|
22
|
+
const out = await runListArtifacts(store);
|
|
23
|
+
assert.equal(out.artifacts.length, 2);
|
|
24
|
+
assert.match(out.markdown, /### Artifacts \(2\)/);
|
|
25
|
+
assert.match(out.markdown, /\| slug \| kind \| turns \| last updated \| uri \|/);
|
|
26
|
+
assert.match(out.markdown, /artifact:\/\/a/);
|
|
27
|
+
assert.match(out.markdown, /artifact:\/\/b/);
|
|
28
|
+
});
|
|
29
|
+
});
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
// src/resources/extensions/coworker-artifacts/list-tool.ts
|
|
2
|
+
//
|
|
3
|
+
// `list_artifacts` LLM tool runner. Reads each artifact's metadata.json for
|
|
4
|
+
// the timestamp + turn_count fields not carried on ArtifactHandle, and emits
|
|
5
|
+
// both a structured payload and a markdown table for the assistant to surface.
|
|
6
|
+
import type { ArtifactStore } from '@otto/coworker-artifacts';
|
|
7
|
+
|
|
8
|
+
export interface ListedArtifact {
|
|
9
|
+
slug: string;
|
|
10
|
+
kind: string;
|
|
11
|
+
name: string;
|
|
12
|
+
uri: string;
|
|
13
|
+
created_at: string;
|
|
14
|
+
last_updated_at: string;
|
|
15
|
+
turn_count: number;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export interface ListToolOutput {
|
|
19
|
+
artifacts: ListedArtifact[];
|
|
20
|
+
markdown: string;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export async function runListArtifacts(store: ArtifactStore): Promise<ListToolOutput> {
|
|
24
|
+
const handles = await store.list();
|
|
25
|
+
// We need the metadata fields not on the handle — re-read each metadata.json.
|
|
26
|
+
const { readFileSync } = await import('node:fs');
|
|
27
|
+
const rows: ListedArtifact[] = handles.map((h) => {
|
|
28
|
+
const meta = JSON.parse(readFileSync(h.metadataPath, 'utf8')) as {
|
|
29
|
+
created_at: string;
|
|
30
|
+
last_updated_at: string;
|
|
31
|
+
turn_count: number;
|
|
32
|
+
};
|
|
33
|
+
return {
|
|
34
|
+
slug: h.slug,
|
|
35
|
+
kind: h.kind,
|
|
36
|
+
name: h.name,
|
|
37
|
+
uri: h.uri,
|
|
38
|
+
created_at: meta.created_at,
|
|
39
|
+
last_updated_at: meta.last_updated_at,
|
|
40
|
+
turn_count: meta.turn_count,
|
|
41
|
+
};
|
|
42
|
+
});
|
|
43
|
+
if (rows.length === 0) {
|
|
44
|
+
return { artifacts: [], markdown: '### Artifacts (0)\n' };
|
|
45
|
+
}
|
|
46
|
+
const lines: string[] = [`### Artifacts (${rows.length})`, ''];
|
|
47
|
+
lines.push('| slug | kind | turns | last updated | uri |');
|
|
48
|
+
lines.push('|---|---|---|---|---|');
|
|
49
|
+
for (const r of rows) {
|
|
50
|
+
lines.push(`| ${r.slug} | ${r.kind} | ${r.turn_count} | ${r.last_updated_at} | \`${r.uri}\` |`);
|
|
51
|
+
}
|
|
52
|
+
return { artifacts: rows, markdown: lines.join('\n') + '\n' };
|
|
53
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
// src/resources/extensions/coworker-artifacts/open-tool.test.ts
|
|
2
|
+
import { describe, it } from 'node:test';
|
|
3
|
+
import assert from 'node:assert/strict';
|
|
4
|
+
import { mkdtempSync } from 'node:fs';
|
|
5
|
+
import { tmpdir } from 'node:os';
|
|
6
|
+
import { join } from 'node:path';
|
|
7
|
+
import { ArtifactStore, ArtifactNotFound } from '@otto/coworker-artifacts';
|
|
8
|
+
import { runOpenArtifact } from './open-tool.js';
|
|
9
|
+
|
|
10
|
+
describe('runOpenArtifact', () => {
|
|
11
|
+
it('returns markdown with content + provenance tail', async () => {
|
|
12
|
+
const store = new ArtifactStore({ workspaceDir: mkdtempSync(join(tmpdir(), 'ot-')) });
|
|
13
|
+
const h = await store.create('report', 'r');
|
|
14
|
+
await store.update(h, [{ path: 'report.md', content: '# hello\n' }]);
|
|
15
|
+
await store.recordTurn(h, {
|
|
16
|
+
action: 'create',
|
|
17
|
+
turn_id: 't1',
|
|
18
|
+
user_prompt: 'draft',
|
|
19
|
+
files_touched: [],
|
|
20
|
+
});
|
|
21
|
+
const out = await runOpenArtifact(store, { slug: 'r' });
|
|
22
|
+
assert.match(out.markdown, /# hello/);
|
|
23
|
+
assert.match(out.markdown, /Recent provenance/);
|
|
24
|
+
assert.match(out.markdown, /turn `t1`/);
|
|
25
|
+
});
|
|
26
|
+
it('throws ArtifactNotFound for missing slug', async () => {
|
|
27
|
+
const store = new ArtifactStore({ workspaceDir: mkdtempSync(join(tmpdir(), 'ot2-')) });
|
|
28
|
+
await assert.rejects(() => runOpenArtifact(store, { slug: 'missing' }), ArtifactNotFound);
|
|
29
|
+
});
|
|
30
|
+
});
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
// src/resources/extensions/coworker-artifacts/open-tool.ts
|
|
2
|
+
//
|
|
3
|
+
// `open_artifact` LLM tool runner. Returns the primary file body wrapped in a
|
|
4
|
+
// fenced markdown block plus the tail 5 provenance entries so the assistant
|
|
5
|
+
// can summarise recent edits without flooding context with the full ledger.
|
|
6
|
+
import type { ArtifactStore } from '@otto/coworker-artifacts';
|
|
7
|
+
import { ArtifactNotFound } from '@otto/coworker-artifacts';
|
|
8
|
+
|
|
9
|
+
export interface OpenToolOutput {
|
|
10
|
+
markdown: string;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export async function runOpenArtifact(
|
|
14
|
+
store: ArtifactStore,
|
|
15
|
+
args: { slug: string },
|
|
16
|
+
): Promise<OpenToolOutput> {
|
|
17
|
+
const handle = await store.get(args.slug);
|
|
18
|
+
if (!handle) throw new ArtifactNotFound(args.slug);
|
|
19
|
+
const { readFileSync } = await import('node:fs');
|
|
20
|
+
const body = readFileSync(handle.primaryPath, 'utf8');
|
|
21
|
+
const provRaw = readFileSync(handle.provenancePath, 'utf8');
|
|
22
|
+
const prov = JSON.parse(provRaw) as Array<{
|
|
23
|
+
ts: string;
|
|
24
|
+
action: string;
|
|
25
|
+
turn_id: string;
|
|
26
|
+
user_prompt: string;
|
|
27
|
+
}>;
|
|
28
|
+
const tail = prov.slice(-5);
|
|
29
|
+
const lines: string[] = [];
|
|
30
|
+
lines.push(`### ${handle.name} (\`${handle.uri}\`)`);
|
|
31
|
+
lines.push('');
|
|
32
|
+
lines.push('```markdown');
|
|
33
|
+
lines.push(body);
|
|
34
|
+
lines.push('```');
|
|
35
|
+
lines.push('');
|
|
36
|
+
if (tail.length > 0) {
|
|
37
|
+
lines.push('**Recent provenance:**');
|
|
38
|
+
for (const e of tail) {
|
|
39
|
+
lines.push(`- ${e.ts} · ${e.action} · turn \`${e.turn_id}\` · ${e.user_prompt}`);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
return { markdown: lines.join('\n') + '\n' };
|
|
43
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "coworker-memory",
|
|
3
|
+
"name": "Co-worker Memory",
|
|
4
|
+
"version": "1.0.0",
|
|
5
|
+
"description": "Layered memory: Layer A (markdown rules/lessons) + Layer B (verbatim SQLite drawers) with /memory commands and memorize/recall tools",
|
|
6
|
+
"tier": "bundled",
|
|
7
|
+
"requires": { "platform": ">=2.29.0" },
|
|
8
|
+
"provides": {
|
|
9
|
+
"tools": ["memorize", "recall"],
|
|
10
|
+
"commands": ["memory"],
|
|
11
|
+
"hooks": ["session_start", "session_shutdown"]
|
|
12
|
+
}
|
|
13
|
+
}
|