@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,53 @@
|
|
|
1
|
+
import { describe, it } from 'node:test';
|
|
2
|
+
import assert from 'node:assert/strict';
|
|
3
|
+
import { StalenessBanner } from './staleness-banner.js';
|
|
4
|
+
|
|
5
|
+
describe('StalenessBanner', () => {
|
|
6
|
+
const lookup = (refToTs: Record<string, string>) => async (ref: string) => refToTs[ref] ?? null;
|
|
7
|
+
|
|
8
|
+
it('returns null when no binding is stale', async () => {
|
|
9
|
+
const sb = new StalenessBanner();
|
|
10
|
+
const banner = await sb.check({
|
|
11
|
+
scratchpadName: 'sp', sessionId: 's',
|
|
12
|
+
bindings: ['jira:prod'], spawnTime: new Date('2026-06-01T00:01:00.000Z'),
|
|
13
|
+
lookupLastModified: lookup({ 'jira:prod': '2026-06-01T00:00:00.000Z' }),
|
|
14
|
+
});
|
|
15
|
+
assert.equal(banner, null);
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
it('returns banner string when a binding was modified after spawnTime', async () => {
|
|
19
|
+
const sb = new StalenessBanner();
|
|
20
|
+
const banner = await sb.check({
|
|
21
|
+
scratchpadName: 'sp', sessionId: 's',
|
|
22
|
+
bindings: ['jira:prod'], spawnTime: new Date('2026-06-01T00:00:00.000Z'),
|
|
23
|
+
lookupLastModified: lookup({ 'jira:prod': '2026-06-01T00:05:00.000Z' }),
|
|
24
|
+
});
|
|
25
|
+
assert.ok(banner);
|
|
26
|
+
assert.match(banner, /jira:prod/);
|
|
27
|
+
assert.match(banner, /\/sp reset/);
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
it('returns null on the second check for the same (scratchpad, binding, session)', async () => {
|
|
31
|
+
const sb = new StalenessBanner();
|
|
32
|
+
const args = {
|
|
33
|
+
scratchpadName: 'sp', sessionId: 's',
|
|
34
|
+
bindings: ['jira:prod'], spawnTime: new Date('2026-06-01T00:00:00.000Z'),
|
|
35
|
+
lookupLastModified: lookup({ 'jira:prod': '2026-06-01T00:05:00.000Z' }),
|
|
36
|
+
};
|
|
37
|
+
assert.ok(await sb.check(args));
|
|
38
|
+
assert.equal(await sb.check(args), null);
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
it('re-fires after spawnTime advances (kernel respawn)', async () => {
|
|
42
|
+
const sb = new StalenessBanner();
|
|
43
|
+
const base = {
|
|
44
|
+
scratchpadName: 'sp', sessionId: 's', bindings: ['jira:prod'],
|
|
45
|
+
lookupLastModified: lookup({ 'jira:prod': '2026-06-01T00:05:00.000Z' }),
|
|
46
|
+
};
|
|
47
|
+
await sb.check({ ...base, spawnTime: new Date('2026-06-01T00:00:00.000Z') }); // shown once
|
|
48
|
+
await sb.check({ ...base, spawnTime: new Date('2026-06-01T00:00:00.000Z') }); // suppressed
|
|
49
|
+
sb.resetForRespawn('sp');
|
|
50
|
+
const banner = await sb.check({ ...base, spawnTime: new Date('2026-06-01T00:10:00.000Z') });
|
|
51
|
+
assert.equal(banner, null); // post-respawn lastModified < new spawnTime
|
|
52
|
+
});
|
|
53
|
+
});
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
export interface StalenessCheck {
|
|
2
|
+
scratchpadName: string;
|
|
3
|
+
sessionId: string;
|
|
4
|
+
bindings: string[];
|
|
5
|
+
spawnTime: Date;
|
|
6
|
+
lookupLastModified: (ref: string) => Promise<string | null>;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export class StalenessBanner {
|
|
10
|
+
private readonly shown = new Map<string, Set<string>>(); // scratchpadName → set of "session|ref"
|
|
11
|
+
|
|
12
|
+
async check(args: StalenessCheck): Promise<string | null> {
|
|
13
|
+
const stale: string[] = [];
|
|
14
|
+
for (const ref of args.bindings) {
|
|
15
|
+
const lm = await args.lookupLastModified(ref);
|
|
16
|
+
if (!lm) continue;
|
|
17
|
+
if (new Date(lm).getTime() <= args.spawnTime.getTime()) continue;
|
|
18
|
+
const key = `${args.sessionId}|${ref}`;
|
|
19
|
+
const set = this.shown.get(args.scratchpadName) ?? new Set<string>();
|
|
20
|
+
if (set.has(key)) continue;
|
|
21
|
+
set.add(key);
|
|
22
|
+
this.shown.set(args.scratchpadName, set);
|
|
23
|
+
stale.push(ref);
|
|
24
|
+
}
|
|
25
|
+
if (stale.length === 0) return null;
|
|
26
|
+
const list = stale.join(', ');
|
|
27
|
+
return `${list} was modified after this kernel was spawned; env vars are stale. Run /sp reset to respawn with current values.`;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
resetForRespawn(scratchpadName: string): void {
|
|
31
|
+
this.shown.delete(scratchpadName);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Project/App: OTTO
|
|
3
|
+
* File Purpose: End-to-end integration test for vault + scratchpad (Phase 2 Task 17).
|
|
4
|
+
*
|
|
5
|
+
* Exercises the four contract seams of the otto-vault pillar working together:
|
|
6
|
+
* 1. bindings → CredentialInjector → ChildProcessRuntime env → live cell
|
|
7
|
+
* 2. SecretScanner redaction on the journal copy of stdout (live result intact)
|
|
8
|
+
* 3. vault rotation produces a StalenessBanner hit on the next staleness check
|
|
9
|
+
* 4. workspace vault entry shadows global vault entry
|
|
10
|
+
*
|
|
11
|
+
* Uses ScratchpadManager + ChildProcessRuntime + LocalDataVault + CredentialInjector
|
|
12
|
+
* end-to-end (no stubs on the integration boundary). Tests 1–3 spawn a real kernel
|
|
13
|
+
* subprocess; test 4 is vault-only and does not spawn.
|
|
14
|
+
*/
|
|
15
|
+
import { describe, it, after } from 'node:test';
|
|
16
|
+
import assert from 'node:assert/strict';
|
|
17
|
+
import { mkdtempSync, readFileSync, rmSync } from 'node:fs';
|
|
18
|
+
import { mkdir } from 'node:fs/promises';
|
|
19
|
+
import { tmpdir } from 'node:os';
|
|
20
|
+
import { join } from 'node:path';
|
|
21
|
+
import { AuditLog } from '@otto/coworker-utils';
|
|
22
|
+
import { CredentialInjector, LocalDataVault } from '@otto/coworker-vault';
|
|
23
|
+
import { ScratchpadManager } from './scratchpad-manager.js';
|
|
24
|
+
import { StalenessBanner } from './staleness-banner.js';
|
|
25
|
+
|
|
26
|
+
interface E2EContext {
|
|
27
|
+
root: string;
|
|
28
|
+
audit: AuditLog;
|
|
29
|
+
vault: LocalDataVault;
|
|
30
|
+
injector: CredentialInjector;
|
|
31
|
+
manager: ScratchpadManager;
|
|
32
|
+
scratchpadsRoot: string;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
async function setup(): Promise<E2EContext> {
|
|
36
|
+
const root = mkdtempSync(join(tmpdir(), 'vault-e2e-'));
|
|
37
|
+
await mkdir(join(root, 'home'), { recursive: true });
|
|
38
|
+
await mkdir(join(root, 'workspace', '.otto', 'inputs'), { recursive: true });
|
|
39
|
+
const audit = new AuditLog({ path: join(root, 'audit.jsonl') });
|
|
40
|
+
const vault = new LocalDataVault({
|
|
41
|
+
globalDir: join(root, 'home'),
|
|
42
|
+
workspaceDir: undefined,
|
|
43
|
+
audit,
|
|
44
|
+
});
|
|
45
|
+
const injector = new CredentialInjector({ vault, audit });
|
|
46
|
+
await vault.set(
|
|
47
|
+
{ engine: 'jira', name: 'prod' },
|
|
48
|
+
{ url: 'https://x', email: 'a@b', token: 'tok' },
|
|
49
|
+
);
|
|
50
|
+
const scratchpadsRoot = join(root, 'scratchpads');
|
|
51
|
+
const manager = new ScratchpadManager({
|
|
52
|
+
workspace: join(root, 'workspace'),
|
|
53
|
+
root: scratchpadsRoot,
|
|
54
|
+
injector,
|
|
55
|
+
audit,
|
|
56
|
+
sessionId: 'sess-1',
|
|
57
|
+
// Keep the kernel responsive even under slow test machines.
|
|
58
|
+
runtimeOptions: { cellTimeoutMs: 30_000, inactivityTimeoutMs: 30_000 },
|
|
59
|
+
});
|
|
60
|
+
return { root, audit, vault, injector, manager, scratchpadsRoot };
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
async function teardown(ctx: E2EContext): Promise<void> {
|
|
64
|
+
await ctx.manager.disposeAll();
|
|
65
|
+
rmSync(ctx.root, { recursive: true, force: true });
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
async function readAuditRecords(audit: AuditLog): Promise<Array<{
|
|
69
|
+
producer: string; action: string; detail: Record<string, unknown>;
|
|
70
|
+
}>> {
|
|
71
|
+
const out: Array<{ producer: string; action: string; detail: Record<string, unknown> }> = [];
|
|
72
|
+
for await (const r of audit.read({})) {
|
|
73
|
+
out.push({ producer: r.producer, action: r.action, detail: r.detail });
|
|
74
|
+
}
|
|
75
|
+
return out;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
describe('vault + scratchpad end-to-end (Phase 2 Task 17)', () => {
|
|
79
|
+
// Hold contexts so a test-level failure still cleans up.
|
|
80
|
+
const contexts: E2EContext[] = [];
|
|
81
|
+
after(async () => {
|
|
82
|
+
for (const c of contexts) {
|
|
83
|
+
try { await teardown(c); } catch { /* best effort */ }
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
it('Test 1: --use binding injects OTTO_DS_* into kernel; cell reads it', async () => {
|
|
88
|
+
const ctx = await setup();
|
|
89
|
+
contexts.push(ctx);
|
|
90
|
+
await ctx.manager.create('p1', { bindings: ['jira:prod'] });
|
|
91
|
+
const rt = await ctx.manager.getOrAttach('p1');
|
|
92
|
+
const { value } = await rt.runCell(
|
|
93
|
+
'return [process.env.OTTO_DS_JIRA_PROD__URL, process.env.OTTO_DS_JIRA_PROD__TOKEN];',
|
|
94
|
+
);
|
|
95
|
+
assert.deepEqual(value, ['https://x', 'tok']);
|
|
96
|
+
// The parent process must not be polluted by the injection.
|
|
97
|
+
assert.equal(process.env.OTTO_DS_JIRA_PROD__URL, undefined);
|
|
98
|
+
assert.equal(process.env.OTTO_DS_JIRA_PROD__TOKEN, undefined);
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
it('Test 2: secret printed by cell is redacted in the journal but live result preserved', async () => {
|
|
102
|
+
const ctx = await setup();
|
|
103
|
+
contexts.push(ctx);
|
|
104
|
+
await ctx.manager.create('p2', { bindings: ['jira:prod'] });
|
|
105
|
+
// Run via the manager so the SecretScanner gate runs on the journal copy.
|
|
106
|
+
// AKIAABCDEFGHIJKLMNOP = AKIA + 16 alphanumeric => matches aws_access_key_id.
|
|
107
|
+
const result = await ctx.manager.runCell(
|
|
108
|
+
'p2',
|
|
109
|
+
'console.log("leaked AKIAABCDEFGHIJKLMNOP"); return 1;',
|
|
110
|
+
);
|
|
111
|
+
assert.equal(result.value, 1);
|
|
112
|
+
// Live stdout: redaction is journal-only, so the manager's returned stdout
|
|
113
|
+
// should still contain the raw secret string.
|
|
114
|
+
assert.ok(
|
|
115
|
+
result.stdout.includes('AKIAABCDEFGHIJKLMNOP'),
|
|
116
|
+
`live stdout should preserve real secret; got: ${JSON.stringify(result.stdout)}`,
|
|
117
|
+
);
|
|
118
|
+
|
|
119
|
+
// Journal: cells.jsonl's stdout field is the journal copy and must be redacted.
|
|
120
|
+
// NOTE: the cell's `code` field intentionally preserves the original source for
|
|
121
|
+
// reproducibility — redaction only covers stdout + error.message per Task 14's
|
|
122
|
+
// contract. The raw secret string therefore can appear in the `code` field;
|
|
123
|
+
// we explicitly assert against the `stdout` field by parsing the record.
|
|
124
|
+
const cellsPath = join(ctx.scratchpadsRoot, 'p2', 'cells.jsonl');
|
|
125
|
+
const cellsLines = readFileSync(cellsPath, 'utf8')
|
|
126
|
+
.split('\n')
|
|
127
|
+
.filter((l) => l.includes('"id"'));
|
|
128
|
+
assert.equal(cellsLines.length, 1, `expected exactly one cell record; got ${cellsLines.length}`);
|
|
129
|
+
const journalEntry = JSON.parse(cellsLines[0]!) as { stdout: string; code: string };
|
|
130
|
+
assert.ok(
|
|
131
|
+
journalEntry.stdout.includes('[REDACTED:aws_access_key_id]'),
|
|
132
|
+
`journal stdout should contain redaction marker; got: ${journalEntry.stdout}`,
|
|
133
|
+
);
|
|
134
|
+
assert.ok(
|
|
135
|
+
!journalEntry.stdout.includes('AKIAABCDEFGHIJKLMNOP'),
|
|
136
|
+
`journal stdout should NOT contain raw secret; got: ${journalEntry.stdout}`,
|
|
137
|
+
);
|
|
138
|
+
|
|
139
|
+
// Audit: at least one secret-scanner record should land in the shared audit.
|
|
140
|
+
const records = await readAuditRecords(ctx.audit);
|
|
141
|
+
const scan = records.filter((r) => r.producer === 'secret-scanner' && r.action === 'redact');
|
|
142
|
+
assert.ok(
|
|
143
|
+
scan.length >= 1,
|
|
144
|
+
`expected >=1 secret-scanner audit record; got ${scan.length} (records=${JSON.stringify(records)})`,
|
|
145
|
+
);
|
|
146
|
+
assert.equal(scan[0]!.detail.kind, 'aws_access_key_id');
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
it('Test 3: vault entry rotation triggers staleness banner on next check', async () => {
|
|
150
|
+
const ctx = await setup();
|
|
151
|
+
contexts.push(ctx);
|
|
152
|
+
await ctx.manager.create('p3', { bindings: ['jira:prod'] });
|
|
153
|
+
const rt = await ctx.manager.getOrAttach('p3');
|
|
154
|
+
|
|
155
|
+
// First cell — establishes a normal pre-rotation baseline.
|
|
156
|
+
const before = await rt.runCell('return 1;');
|
|
157
|
+
assert.equal(before.value, 1);
|
|
158
|
+
|
|
159
|
+
// No staleness yet — banner should be null.
|
|
160
|
+
const banner = new StalenessBanner();
|
|
161
|
+
const preCheck = await banner.check({
|
|
162
|
+
scratchpadName: 'p3',
|
|
163
|
+
sessionId: 'sess-1',
|
|
164
|
+
bindings: ['jira:prod'],
|
|
165
|
+
spawnTime: rt.spawnTime,
|
|
166
|
+
lookupLastModified: (ref) => ctx.vault.lookupLastModified(ref),
|
|
167
|
+
});
|
|
168
|
+
assert.equal(preCheck, null, `expected no banner before rotation; got: ${preCheck}`);
|
|
169
|
+
|
|
170
|
+
// Wait so last_modified_at advances past the recorded spawnTime.
|
|
171
|
+
await new Promise((r) => setTimeout(r, 25));
|
|
172
|
+
|
|
173
|
+
// Rotate the vault entry — bumps last_modified_at.
|
|
174
|
+
await ctx.vault.set(
|
|
175
|
+
{ engine: 'jira', name: 'prod' },
|
|
176
|
+
{ url: 'NEW', email: 'a@b', token: 'tok' },
|
|
177
|
+
);
|
|
178
|
+
|
|
179
|
+
const postCheck = await banner.check({
|
|
180
|
+
scratchpadName: 'p3',
|
|
181
|
+
sessionId: 'sess-1',
|
|
182
|
+
bindings: ['jira:prod'],
|
|
183
|
+
spawnTime: rt.spawnTime,
|
|
184
|
+
lookupLastModified: (ref) => ctx.vault.lookupLastModified(ref),
|
|
185
|
+
});
|
|
186
|
+
assert.ok(postCheck, `expected a staleness banner string after rotation; got null`);
|
|
187
|
+
assert.match(postCheck!, /jira:prod/);
|
|
188
|
+
assert.match(postCheck!, /\/sp reset/);
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
it('Test 4: workspace vault entry shadows global', async () => {
|
|
192
|
+
// Dedicated vault root with both global + workspace dirs (does not use setup()).
|
|
193
|
+
const root = mkdtempSync(join(tmpdir(), 'vault-e2e-shadow-'));
|
|
194
|
+
try {
|
|
195
|
+
const audit = new AuditLog({ path: join(root, 'audit.jsonl') });
|
|
196
|
+
const globalDir = join(root, 'home');
|
|
197
|
+
const workspaceDir = join(root, 'workspace');
|
|
198
|
+
const vault = new LocalDataVault({ globalDir, workspaceDir, audit });
|
|
199
|
+
|
|
200
|
+
// Write global entry first.
|
|
201
|
+
await vault.set(
|
|
202
|
+
{ engine: 'jira', name: 'prod' },
|
|
203
|
+
{ url: 'https://global', email: 'g@x', token: 'tok-global' },
|
|
204
|
+
);
|
|
205
|
+
|
|
206
|
+
// Write workspace entry second via forceWorkspace.
|
|
207
|
+
await vault.set(
|
|
208
|
+
{ engine: 'jira', name: 'prod' },
|
|
209
|
+
{ url: 'https://workspace', email: 'w@x', token: 'tok-workspace' },
|
|
210
|
+
{ forceWorkspace: true },
|
|
211
|
+
);
|
|
212
|
+
|
|
213
|
+
// get() should resolve workspace first.
|
|
214
|
+
const got = await vault.get({ engine: 'jira', name: 'prod' });
|
|
215
|
+
assert.equal(got.fields.url, 'https://workspace');
|
|
216
|
+
assert.equal(got.fields.token, 'tok-workspace');
|
|
217
|
+
} finally {
|
|
218
|
+
rmSync(root, { recursive: true, force: true });
|
|
219
|
+
}
|
|
220
|
+
});
|
|
221
|
+
});
|
|
@@ -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,31 @@
|
|
|
1
|
+
export type ArtifactKind = 'report' | 'workbook' | 'dataset';
|
|
2
|
+
export interface ArtifactHandle {
|
|
3
|
+
slug: string;
|
|
4
|
+
kind: ArtifactKind;
|
|
5
|
+
base_path: string;
|
|
6
|
+
created_at: string;
|
|
7
|
+
}
|
|
8
|
+
export interface FileWrite {
|
|
9
|
+
path: string;
|
|
10
|
+
content: string | Uint8Array;
|
|
11
|
+
}
|
|
12
|
+
export interface TurnEntry {
|
|
13
|
+
turn_id: string;
|
|
14
|
+
timestamp: string;
|
|
15
|
+
prompt_excerpt: string;
|
|
16
|
+
files_touched: string[];
|
|
17
|
+
}
|
|
18
|
+
export interface ProvenanceEntry {
|
|
19
|
+
session_id: string;
|
|
20
|
+
turns: TurnEntry[];
|
|
21
|
+
}
|
|
22
|
+
export interface ArtifactStore {
|
|
23
|
+
create(kind: ArtifactKind, name: string): Promise<ArtifactHandle>;
|
|
24
|
+
update(handle: ArtifactHandle, files: FileWrite[]): Promise<void>;
|
|
25
|
+
recordTurn(handle: ArtifactHandle, turn: {
|
|
26
|
+
turn_id: string;
|
|
27
|
+
prompt: string;
|
|
28
|
+
}): Promise<void>;
|
|
29
|
+
get(slug: string): Promise<ArtifactHandle | null>;
|
|
30
|
+
list(): Promise<ArtifactHandle[]>;
|
|
31
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { DrawerKind } from './memory.js';
|
|
2
|
+
export interface RecordEpisodeArgs {
|
|
3
|
+
sessionId: string;
|
|
4
|
+
room: string;
|
|
5
|
+
kind: DrawerKind;
|
|
6
|
+
content: string;
|
|
7
|
+
turnId: string;
|
|
8
|
+
metadata?: Record<string, unknown>;
|
|
9
|
+
}
|
|
10
|
+
export interface RecordCellArgs {
|
|
11
|
+
scratchpadName: string;
|
|
12
|
+
cellId: string;
|
|
13
|
+
code: string;
|
|
14
|
+
stdout: string;
|
|
15
|
+
error: {
|
|
16
|
+
type: string;
|
|
17
|
+
message: string;
|
|
18
|
+
} | null;
|
|
19
|
+
durationMs: number;
|
|
20
|
+
}
|
|
21
|
+
export type AccSeverity = 'low' | 'medium' | 'high';
|
|
22
|
+
export interface AccEventArgs {
|
|
23
|
+
sessionId: string;
|
|
24
|
+
kind: string;
|
|
25
|
+
detail: string;
|
|
26
|
+
severity: AccSeverity;
|
|
27
|
+
}
|
|
28
|
+
export interface MemoryRecorder {
|
|
29
|
+
recordEpisode(args: RecordEpisodeArgs): Promise<void>;
|
|
30
|
+
recordCell(args: RecordCellArgs): Promise<void>;
|
|
31
|
+
observeAccEvent(args: AccEventArgs): void;
|
|
32
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
export type Wing = string;
|
|
2
|
+
export type Room = string;
|
|
3
|
+
export type DrawerKind = 'turn' | 'paste' | 'file_load' | 'ticket' | 'email' | 'rca' | 'note';
|
|
4
|
+
export interface Drawer {
|
|
5
|
+
id: string;
|
|
6
|
+
wing: Wing;
|
|
7
|
+
room: Room;
|
|
8
|
+
kind: DrawerKind;
|
|
9
|
+
content: string;
|
|
10
|
+
metadata: Record<string, unknown>;
|
|
11
|
+
created_at: string;
|
|
12
|
+
parent_id?: string;
|
|
13
|
+
}
|
|
14
|
+
export interface RecallQuery {
|
|
15
|
+
query: string;
|
|
16
|
+
wing?: Wing;
|
|
17
|
+
room?: Room;
|
|
18
|
+
kind?: DrawerKind | DrawerKind[];
|
|
19
|
+
days_back?: number;
|
|
20
|
+
max_results?: number;
|
|
21
|
+
}
|
|
22
|
+
export interface Entity {
|
|
23
|
+
id: string;
|
|
24
|
+
type: string;
|
|
25
|
+
canonical: string;
|
|
26
|
+
aliases: string[];
|
|
27
|
+
metadata: Record<string, unknown>;
|
|
28
|
+
first_seen: string;
|
|
29
|
+
last_seen: string;
|
|
30
|
+
}
|
|
31
|
+
export interface EntityEdge {
|
|
32
|
+
subject: string;
|
|
33
|
+
predicate: string;
|
|
34
|
+
object: string;
|
|
35
|
+
valid_from: string;
|
|
36
|
+
valid_to?: string;
|
|
37
|
+
metadata?: Record<string, unknown>;
|
|
38
|
+
}
|
|
39
|
+
export interface EntityQuery {
|
|
40
|
+
entity_type?: string;
|
|
41
|
+
name?: string;
|
|
42
|
+
predicate?: string;
|
|
43
|
+
as_of?: string;
|
|
44
|
+
}
|
|
45
|
+
export interface BackendStatus {
|
|
46
|
+
backend_id: string;
|
|
47
|
+
drawer_count: number;
|
|
48
|
+
entity_count: number;
|
|
49
|
+
size_bytes: number;
|
|
50
|
+
last_write_at?: string;
|
|
51
|
+
}
|
|
52
|
+
export interface MemoryBackend {
|
|
53
|
+
recall(query: RecallQuery): Promise<Drawer[]>;
|
|
54
|
+
retain(drawer: Omit<Drawer, 'id' | 'created_at'>): Promise<Drawer>;
|
|
55
|
+
listRooms(wing?: Wing): Promise<Room[]>;
|
|
56
|
+
listWings(): Promise<Wing[]>;
|
|
57
|
+
entityQuery(query: EntityQuery): Promise<Entity[]>;
|
|
58
|
+
entityAssert(edge: EntityEdge): Promise<void>;
|
|
59
|
+
status(): Promise<BackendStatus>;
|
|
60
|
+
clear(): Promise<void>;
|
|
61
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
export type DataKind = 'csv' | 'xlsx' | 'json' | 'parquet' | 'txt' | 'md' | 'rest' | 'mcp-resource' | 'acp-stream';
|
|
2
|
+
export interface DataSourceRef {
|
|
3
|
+
collector: string;
|
|
4
|
+
uri: string;
|
|
5
|
+
kind: DataKind;
|
|
6
|
+
bytes?: number;
|
|
7
|
+
modified?: string;
|
|
8
|
+
metadata: Record<string, unknown>;
|
|
9
|
+
}
|
|
10
|
+
export interface DataSource {
|
|
11
|
+
ref: DataSourceRef;
|
|
12
|
+
load(): Promise<Buffer | string | object>;
|
|
13
|
+
stream?(): AsyncIterable<Buffer>;
|
|
14
|
+
}
|
|
15
|
+
export interface CollectorCapabilities {
|
|
16
|
+
supports_uris: string[];
|
|
17
|
+
supports_kinds: DataKind[];
|
|
18
|
+
supports_streaming: boolean;
|
|
19
|
+
supports_watching: boolean;
|
|
20
|
+
}
|
|
21
|
+
export interface ListOpts {
|
|
22
|
+
workspace?: string;
|
|
23
|
+
prefix?: string;
|
|
24
|
+
limit?: number;
|
|
25
|
+
}
|
|
26
|
+
export type Unsubscribe = () => void;
|
|
27
|
+
export interface Collector {
|
|
28
|
+
readonly id: string;
|
|
29
|
+
readonly kind: 'file' | 'api' | 'protocol';
|
|
30
|
+
describe(): CollectorCapabilities;
|
|
31
|
+
list(opts?: ListOpts): AsyncIterable<DataSourceRef>;
|
|
32
|
+
open(ref: DataSourceRef): Promise<DataSource>;
|
|
33
|
+
watch?(ref: DataSourceRef, onChange: (ref: DataSourceRef) => void): Unsubscribe;
|
|
34
|
+
}
|
|
35
|
+
export interface CollectorRegistry {
|
|
36
|
+
register(collector: Collector): void;
|
|
37
|
+
list(): Collector[];
|
|
38
|
+
get(id: string): Collector | null;
|
|
39
|
+
resolve(uri: string): Promise<{
|
|
40
|
+
collector: Collector;
|
|
41
|
+
ref: DataSourceRef;
|
|
42
|
+
} | null>;
|
|
43
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
export interface EngineField {
|
|
2
|
+
name: string;
|
|
3
|
+
secret: boolean;
|
|
4
|
+
description?: string;
|
|
5
|
+
default?: string;
|
|
6
|
+
name_from?: boolean;
|
|
7
|
+
}
|
|
8
|
+
export interface EngineDef {
|
|
9
|
+
slug: string;
|
|
10
|
+
display_name: string;
|
|
11
|
+
pip: string | null;
|
|
12
|
+
fields: EngineField[];
|
|
13
|
+
auth_methods: string[];
|
|
14
|
+
test_snippet?: string;
|
|
15
|
+
popular?: boolean;
|
|
16
|
+
custom?: boolean;
|
|
17
|
+
}
|
|
18
|
+
export interface VaultEntry {
|
|
19
|
+
engine: string;
|
|
20
|
+
name: string;
|
|
21
|
+
values: Record<string, string>;
|
|
22
|
+
secure_keys: string[];
|
|
23
|
+
created_at: string;
|
|
24
|
+
updated_at?: string;
|
|
25
|
+
}
|
|
26
|
+
export interface BoundClient<TClient = unknown> {
|
|
27
|
+
engine: string;
|
|
28
|
+
name: string;
|
|
29
|
+
client: TClient;
|
|
30
|
+
}
|
|
31
|
+
export interface CredentialInjector {
|
|
32
|
+
injectEnv(processEnv: NodeJS.ProcessEnv, vaultEntries: string[]): NodeJS.ProcessEnv;
|
|
33
|
+
loadForBinding<TClient = unknown>(serviceName: string): Promise<BoundClient<TClient> | null>;
|
|
34
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@otto/coworker-types",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "Shared types and contracts for Otto co-worker packages",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"otto": {
|
|
7
|
+
"linkable": true,
|
|
8
|
+
"scope": "@otto",
|
|
9
|
+
"name": "coworker-types"
|
|
10
|
+
},
|
|
11
|
+
"main": "./dist/index.js",
|
|
12
|
+
"types": "./dist/index.d.ts",
|
|
13
|
+
"exports": {
|
|
14
|
+
".": {
|
|
15
|
+
"types": "./dist/index.d.ts",
|
|
16
|
+
"import": "./dist/index.js"
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
"scripts": {
|
|
20
|
+
"build": "tsc -p tsconfig.json",
|
|
21
|
+
"build:publish": "tsc -p tsconfig.publish.json"
|
|
22
|
+
},
|
|
23
|
+
"files": ["dist"]
|
|
24
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { describe, it } from 'node:test';
|
|
2
|
+
import assert from 'node:assert/strict';
|
|
3
|
+
import type {
|
|
4
|
+
ArtifactKind, ArtifactHandle, FileWrite, ProvenanceEntry, TurnEntry,
|
|
5
|
+
ArtifactStore,
|
|
6
|
+
} from './artifacts.js';
|
|
7
|
+
|
|
8
|
+
describe('artifacts types', () => {
|
|
9
|
+
it('ArtifactKind is the v1 closed set', () => {
|
|
10
|
+
const kinds: ArtifactKind[] = ['report', 'workbook', 'dataset'];
|
|
11
|
+
assert.equal(kinds.length, 3);
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
it('ArtifactHandle carries slug + kind + base path', () => {
|
|
15
|
+
const h: ArtifactHandle = {
|
|
16
|
+
slug: 'rca-p1-1234',
|
|
17
|
+
kind: 'report',
|
|
18
|
+
base_path: '/workspace/.otto/artifacts/rca-p1-1234',
|
|
19
|
+
created_at: '2026-05-31T10:00:00Z',
|
|
20
|
+
};
|
|
21
|
+
assert.equal(h.slug, 'rca-p1-1234');
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
it('FileWrite carries relative path + bytes', () => {
|
|
25
|
+
const fw: FileWrite = { path: 'report.md', content: 'hello' };
|
|
26
|
+
assert.equal(fw.path, 'report.md');
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
it('ProvenanceEntry has session + turns array', () => {
|
|
30
|
+
const p: ProvenanceEntry = {
|
|
31
|
+
session_id: 'sess_001',
|
|
32
|
+
turns: [],
|
|
33
|
+
};
|
|
34
|
+
assert.equal(p.turns.length, 0);
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
it('TurnEntry has turn_id + prompt + files_touched', () => {
|
|
38
|
+
const t: TurnEntry = {
|
|
39
|
+
turn_id: 'turn_001',
|
|
40
|
+
timestamp: '2026-05-31T10:00:00Z',
|
|
41
|
+
prompt_excerpt: 'draft the rca',
|
|
42
|
+
files_touched: ['report.md'],
|
|
43
|
+
};
|
|
44
|
+
assert.equal(t.files_touched[0], 'report.md');
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
it('ArtifactStore has create/update/recordTurn signatures', () => {
|
|
48
|
+
const _check: keyof ArtifactStore = 'create';
|
|
49
|
+
const _methods: Array<keyof ArtifactStore> = ['create', 'update', 'recordTurn', 'get', 'list'];
|
|
50
|
+
assert.equal(_methods.length, 5);
|
|
51
|
+
});
|
|
52
|
+
});
|