@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,413 @@
|
|
|
1
|
+
import { describe, it, beforeEach, afterEach } from 'node:test';
|
|
2
|
+
import assert from 'node:assert/strict';
|
|
3
|
+
import { mkdtemp, mkdir, writeFile, rm } from 'node:fs/promises';
|
|
4
|
+
import { tmpdir } from 'node:os';
|
|
5
|
+
import { join } from 'node:path';
|
|
6
|
+
import { pathToFileURL } from 'node:url';
|
|
7
|
+
import { existsSync, mkdtempSync, readFileSync, writeFileSync } from 'node:fs';
|
|
8
|
+
import { AuditLog } from '@otto/coworker-utils';
|
|
9
|
+
import { CredentialInjector, LocalDataVault } from '@otto/coworker-vault';
|
|
10
|
+
import { ChildProcessRuntime } from './child-process-runtime.js';
|
|
11
|
+
import type { DataLoadDrawer } from './kernel-protocol.js';
|
|
12
|
+
import { encodeNamespace } from './namespace-codec.js';
|
|
13
|
+
|
|
14
|
+
let workspace: string;
|
|
15
|
+
let inputs: string;
|
|
16
|
+
let runtime: ChildProcessRuntime;
|
|
17
|
+
|
|
18
|
+
const delay = (ms: number): Promise<void> => new Promise((r) => setTimeout(r, ms));
|
|
19
|
+
|
|
20
|
+
describe('ChildProcessRuntime', () => {
|
|
21
|
+
beforeEach(async () => {
|
|
22
|
+
workspace = await mkdtemp(join(tmpdir(), 'cpr-ws-'));
|
|
23
|
+
inputs = join(workspace, '.otto', 'inputs');
|
|
24
|
+
await mkdir(inputs, { recursive: true });
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
afterEach(async () => {
|
|
28
|
+
await runtime?.dispose();
|
|
29
|
+
await rm(workspace, { recursive: true, force: true });
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
it('runs a cell and returns value + stdout after start()', async () => {
|
|
33
|
+
runtime = new ChildProcessRuntime({ workspace });
|
|
34
|
+
await runtime.start();
|
|
35
|
+
const { value, stdout } = await runtime.runCell("console.log('hello'); return 6 * 7;");
|
|
36
|
+
assert.equal(value, 42);
|
|
37
|
+
assert.equal(stdout, 'hello');
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
it('rejects with the cell error message when a cell throws', async () => {
|
|
41
|
+
runtime = new ChildProcessRuntime({ workspace });
|
|
42
|
+
await runtime.start();
|
|
43
|
+
await assert.rejects(() => runtime.runCell("throw new Error('kaboom');"), /kaboom/);
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
it('forwards a data_load drawer to onDataLoad when a cell loads via a collector', async () => {
|
|
47
|
+
await writeFile(join(inputs, 'cmdb.csv'), 'a,b\n1,2\n');
|
|
48
|
+
const uri = pathToFileURL(join(inputs, 'cmdb.csv')).href;
|
|
49
|
+
const drawers: DataLoadDrawer[] = [];
|
|
50
|
+
runtime = new ChildProcessRuntime({ workspace, onDataLoad: (d) => drawers.push(d) });
|
|
51
|
+
await runtime.start();
|
|
52
|
+
|
|
53
|
+
const { value } = await runtime.runCell(
|
|
54
|
+
`return await (await otto.collectors.open(${JSON.stringify(uri)})).load();`,
|
|
55
|
+
);
|
|
56
|
+
assert.equal(value, 'a,b\n1,2\n');
|
|
57
|
+
|
|
58
|
+
await delay(50);
|
|
59
|
+
assert.equal(drawers.length, 1);
|
|
60
|
+
assert.equal(drawers[0].kind, 'data_load');
|
|
61
|
+
assert.equal(drawers[0].collector, 'file');
|
|
62
|
+
assert.equal(drawers[0].uri, uri);
|
|
63
|
+
assert.equal(drawers[0].bytes, 8);
|
|
64
|
+
assert.equal(drawers[0].schema, null);
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
it('times out a hung cell on the total wall-clock cap and rejects', async () => {
|
|
68
|
+
runtime = new ChildProcessRuntime({ workspace, cellTimeoutMs: 200 });
|
|
69
|
+
await runtime.start();
|
|
70
|
+
await assert.rejects(() => runtime.runCell('return new Promise(() => {});'), /timed out/);
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
it('times out a silent-but-alive cell on the inactivity cap', async () => {
|
|
74
|
+
runtime = new ChildProcessRuntime({ workspace, inactivityTimeoutMs: 150, cellTimeoutMs: 10_000 });
|
|
75
|
+
await runtime.start();
|
|
76
|
+
await assert.rejects(() => runtime.runCell('return new Promise(() => {});'), /inactivity/);
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
it('progress() resets the inactivity timer so a long heartbeating cell completes', async () => {
|
|
80
|
+
runtime = new ChildProcessRuntime({ workspace, inactivityTimeoutMs: 150, cellTimeoutMs: 10_000 });
|
|
81
|
+
await runtime.start();
|
|
82
|
+
const { value } = await runtime.runCell(
|
|
83
|
+
"for (let i = 0; i < 4; i++) { progress('tick' + i); await new Promise((r) => setTimeout(r, 80)); } return 'done';",
|
|
84
|
+
);
|
|
85
|
+
assert.equal(value, 'done');
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
it('still enforces the total wall-clock cap even while progress() heartbeats', async () => {
|
|
89
|
+
runtime = new ChildProcessRuntime({
|
|
90
|
+
workspace, cellTimeoutMs: 250, inactivityTimeoutMs: 60_000, inactivityAfterProgressMs: 60_000,
|
|
91
|
+
});
|
|
92
|
+
await runtime.start();
|
|
93
|
+
await assert.rejects(
|
|
94
|
+
() => runtime.runCell("while (true) { progress('busy'); await new Promise((r) => setTimeout(r, 40)); }"),
|
|
95
|
+
/total wall-clock/,
|
|
96
|
+
);
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
it('cancel() rejects the active cell and the kernel restarts on the next call', async () => {
|
|
100
|
+
runtime = new ChildProcessRuntime({
|
|
101
|
+
workspace, cancelGraceMs: 100, inactivityTimeoutMs: 10_000, cellTimeoutMs: 10_000,
|
|
102
|
+
});
|
|
103
|
+
await runtime.start();
|
|
104
|
+
const p = runtime.runCell('return new Promise(() => {});');
|
|
105
|
+
await delay(50);
|
|
106
|
+
await runtime.cancel();
|
|
107
|
+
await assert.rejects(() => p, /cancelled/);
|
|
108
|
+
const { value } = await runtime.runCell('return 7;');
|
|
109
|
+
assert.equal(value, 7);
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
it('a stray SIGINT between cells is ignored (kernel state survives)', async () => {
|
|
113
|
+
runtime = new ChildProcessRuntime({ workspace });
|
|
114
|
+
await runtime.start();
|
|
115
|
+
await runtime.runCell('globalThis.x = 99;');
|
|
116
|
+
await runtime.cancel(); // nothing running: sends SIGINT, which the child ignores
|
|
117
|
+
const { value } = await runtime.runCell('return globalThis.x;');
|
|
118
|
+
assert.equal(value, 99); // 99 (not null) proves the kernel was NOT restarted
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
it('hard-fails after a second death without an intervening successful cell', async () => {
|
|
122
|
+
runtime = new ChildProcessRuntime({
|
|
123
|
+
workspace, cancelGraceMs: 80, inactivityTimeoutMs: 10_000, cellTimeoutMs: 10_000,
|
|
124
|
+
});
|
|
125
|
+
await runtime.start();
|
|
126
|
+
const p1 = runtime.runCell('return new Promise(() => {});');
|
|
127
|
+
await delay(30);
|
|
128
|
+
await runtime.cancel();
|
|
129
|
+
await assert.rejects(() => p1, /cancelled/);
|
|
130
|
+
|
|
131
|
+
const p2 = runtime.runCell('return new Promise(() => {});'); // triggers restart #1
|
|
132
|
+
await delay(30);
|
|
133
|
+
await runtime.cancel();
|
|
134
|
+
await assert.rejects(() => p2, /cancelled/);
|
|
135
|
+
|
|
136
|
+
await assert.rejects(() => runtime.runCell('return 1;'), /repeatedly crashed/);
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
it('hasActiveCell is true while a cell runs, false otherwise', async () => {
|
|
140
|
+
runtime = new ChildProcessRuntime({ workspace, inactivityTimeoutMs: 10_000, cellTimeoutMs: 10_000 });
|
|
141
|
+
await runtime.start();
|
|
142
|
+
assert.equal(runtime.hasActiveCell, false);
|
|
143
|
+
const p = runtime.runCell('await new Promise((r) => setTimeout(r, 150)); return 5;');
|
|
144
|
+
assert.equal(runtime.hasActiveCell, true);
|
|
145
|
+
assert.equal((await p).value, 5);
|
|
146
|
+
assert.equal(runtime.hasActiveCell, false);
|
|
147
|
+
});
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
describe('data-lib bindings inside a live kernel', () => {
|
|
151
|
+
let ws: string;
|
|
152
|
+
let rt: ChildProcessRuntime;
|
|
153
|
+
|
|
154
|
+
beforeEach(async () => {
|
|
155
|
+
ws = await mkdtemp(join(tmpdir(), 'cpr-libs-'));
|
|
156
|
+
await mkdir(join(ws, '.otto', 'inputs'), { recursive: true });
|
|
157
|
+
});
|
|
158
|
+
afterEach(async () => {
|
|
159
|
+
await rt?.dispose();
|
|
160
|
+
await rm(ws, { recursive: true, force: true });
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
it('polars / lodash / zod / date-fns / exceljs / axios / DuckDB are bound', async () => {
|
|
164
|
+
rt = new ChildProcessRuntime({ workspace: ws, inactivityTimeoutMs: 20_000, cellTimeoutMs: 20_000 });
|
|
165
|
+
await rt.start();
|
|
166
|
+
assert.equal((await rt.runCell('return polars.DataFrame({ a: [1, 2, 3] }).height;')).value, 3);
|
|
167
|
+
assert.equal((await rt.runCell('return lodash.chunk([1, 2, 3, 4], 2).length;')).value, 2);
|
|
168
|
+
assert.equal((await rt.runCell('return zod.string().parse("hi");')).value, 'hi');
|
|
169
|
+
assert.equal((await rt.runCell('return dateFns.format(new Date(1970, 0, 1), "yyyy");')).value, '1970');
|
|
170
|
+
assert.equal((await rt.runCell('const wb = new ExcelJS.Workbook(); wb.addWorksheet("s"); const buf = await wb.xlsx.writeBuffer(); return buf.byteLength > 0;')).value, true);
|
|
171
|
+
assert.equal((await rt.runCell('return typeof axios.get;')).value, 'function');
|
|
172
|
+
assert.equal((await rt.runCell('return typeof DuckDB.DuckDBInstance;')).value, 'function');
|
|
173
|
+
});
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
describe('ChildProcessRuntime — persistence (1d2)', () => {
|
|
177
|
+
let ws: string;
|
|
178
|
+
let sp: string;
|
|
179
|
+
let rt: ChildProcessRuntime;
|
|
180
|
+
|
|
181
|
+
beforeEach(async () => {
|
|
182
|
+
ws = await mkdtemp(join(tmpdir(), 'cpr-pers-ws-'));
|
|
183
|
+
await mkdir(join(ws, '.otto', 'inputs'), { recursive: true });
|
|
184
|
+
sp = await mkdtemp(join(tmpdir(), 'cpr-pers-sp-'));
|
|
185
|
+
});
|
|
186
|
+
afterEach(async () => {
|
|
187
|
+
await rt?.dispose();
|
|
188
|
+
await rm(ws, { recursive: true, force: true });
|
|
189
|
+
await rm(sp, { recursive: true, force: true });
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
it('binds otto.duckdb as a DuckDBInstance when scratchpadDir is set', async () => {
|
|
193
|
+
rt = new ChildProcessRuntime({ workspace: ws, scratchpadDir: sp, cellTimeoutMs: 30_000, inactivityTimeoutMs: 30_000 });
|
|
194
|
+
await rt.start();
|
|
195
|
+
const { value } = await rt.runCell(
|
|
196
|
+
'const c = await otto.duckdb.connect(); await c.run("CREATE TABLE t(x INT)"); await c.run("INSERT INTO t VALUES (42)"); const r = await c.runAndReadAll("SELECT x FROM t"); return r.getRows().length;',
|
|
197
|
+
);
|
|
198
|
+
assert.equal(value, 1);
|
|
199
|
+
assert.equal(existsSync(join(sp, 'kernel.db')), true);
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
it('DuckDB table survives dispose + fresh runtime on the same scratchpadDir', async () => {
|
|
203
|
+
rt = new ChildProcessRuntime({ workspace: ws, scratchpadDir: sp, cellTimeoutMs: 30_000, inactivityTimeoutMs: 30_000 });
|
|
204
|
+
await rt.start();
|
|
205
|
+
await rt.runCell(
|
|
206
|
+
'const c = await otto.duckdb.connect(); await c.run("CREATE TABLE t(x INT)"); await c.run("INSERT INTO t VALUES (1),(2),(3)");',
|
|
207
|
+
);
|
|
208
|
+
await rt.dispose();
|
|
209
|
+
|
|
210
|
+
rt = new ChildProcessRuntime({ workspace: ws, scratchpadDir: sp, cellTimeoutMs: 30_000, inactivityTimeoutMs: 30_000 });
|
|
211
|
+
await rt.start();
|
|
212
|
+
const { value } = await rt.runCell(
|
|
213
|
+
'const c = await otto.duckdb.connect(); const r = await c.runAndReadAll("SELECT COUNT(*) AS n FROM t"); return Number(r.getRows()[0][0]);',
|
|
214
|
+
);
|
|
215
|
+
assert.equal(value, 3);
|
|
216
|
+
});
|
|
217
|
+
|
|
218
|
+
it('restores globalThis from a pre-written namespace.json (Date + Map roundtrip)', async () => {
|
|
219
|
+
const m = new Map<string, number>([['a', 1], ['b', 2]]);
|
|
220
|
+
const d = new Date(1717180800000);
|
|
221
|
+
const { envelope } = encodeNamespace({ m, d, n: 42 }, () => 0);
|
|
222
|
+
writeFileSync(join(sp, 'namespace.json'), JSON.stringify(envelope));
|
|
223
|
+
|
|
224
|
+
rt = new ChildProcessRuntime({ workspace: ws, scratchpadDir: sp, cellTimeoutMs: 30_000, inactivityTimeoutMs: 30_000 });
|
|
225
|
+
await rt.start();
|
|
226
|
+
const a = (await rt.runCell('return globalThis.n;')).value;
|
|
227
|
+
const b = (await rt.runCell('return globalThis.m.get("b");')).value;
|
|
228
|
+
const c = (await rt.runCell('return globalThis.d instanceof Date && globalThis.d.getTime();')).value;
|
|
229
|
+
assert.equal(a, 42);
|
|
230
|
+
assert.equal(b, 2);
|
|
231
|
+
assert.equal(c, 1717180800000);
|
|
232
|
+
assert.deepEqual(rt.recoveryNotes, []);
|
|
233
|
+
});
|
|
234
|
+
|
|
235
|
+
it('records namespace-absent in recoveryNotes when namespace.json is missing', async () => {
|
|
236
|
+
rt = new ChildProcessRuntime({ workspace: ws, scratchpadDir: sp, cellTimeoutMs: 30_000, inactivityTimeoutMs: 30_000 });
|
|
237
|
+
await rt.start();
|
|
238
|
+
assert.deepEqual(rt.recoveryNotes, [{ kind: 'namespace-absent' }]);
|
|
239
|
+
});
|
|
240
|
+
|
|
241
|
+
it('records namespace-corrupt in recoveryNotes when namespace.json is malformed', async () => {
|
|
242
|
+
writeFileSync(join(sp, 'namespace.json'), '{not json');
|
|
243
|
+
rt = new ChildProcessRuntime({ workspace: ws, scratchpadDir: sp, cellTimeoutMs: 30_000, inactivityTimeoutMs: 30_000 });
|
|
244
|
+
await rt.start();
|
|
245
|
+
assert.equal(rt.recoveryNotes.length, 1);
|
|
246
|
+
assert.equal(rt.recoveryNotes[0].kind, 'namespace-corrupt');
|
|
247
|
+
assert.ok(
|
|
248
|
+
rt.recoveryNotes[0].kind === 'namespace-corrupt' &&
|
|
249
|
+
rt.recoveryNotes[0].message.length > 0,
|
|
250
|
+
'corrupt note should carry a non-empty parse error message',
|
|
251
|
+
);
|
|
252
|
+
});
|
|
253
|
+
|
|
254
|
+
it('legacy mode (no scratchpadDir) leaves otto.duckdb undefined and emits no recovery notes', async () => {
|
|
255
|
+
rt = new ChildProcessRuntime({ workspace: ws });
|
|
256
|
+
await rt.start();
|
|
257
|
+
const v = (await rt.runCell('return typeof otto.duckdb;')).value;
|
|
258
|
+
assert.equal(v, 'undefined');
|
|
259
|
+
assert.deepEqual(rt.recoveryNotes, []);
|
|
260
|
+
});
|
|
261
|
+
});
|
|
262
|
+
|
|
263
|
+
describe('ChildProcessRuntime — snapshot() (1d2)', () => {
|
|
264
|
+
let ws: string;
|
|
265
|
+
let sp: string;
|
|
266
|
+
let rt: ChildProcessRuntime;
|
|
267
|
+
|
|
268
|
+
beforeEach(async () => {
|
|
269
|
+
ws = await mkdtemp(join(tmpdir(), 'cpr-snap-ws-'));
|
|
270
|
+
await mkdir(join(ws, '.otto', 'inputs'), { recursive: true });
|
|
271
|
+
sp = await mkdtemp(join(tmpdir(), 'cpr-snap-sp-'));
|
|
272
|
+
});
|
|
273
|
+
afterEach(async () => {
|
|
274
|
+
await rt?.dispose();
|
|
275
|
+
await rm(ws, { recursive: true, force: true });
|
|
276
|
+
await rm(sp, { recursive: true, force: true });
|
|
277
|
+
});
|
|
278
|
+
|
|
279
|
+
it('snapshot() writes namespace.json from live globalThis state and returns ok', async () => {
|
|
280
|
+
rt = new ChildProcessRuntime({ workspace: ws, scratchpadDir: sp, cellTimeoutMs: 30_000, inactivityTimeoutMs: 30_000 });
|
|
281
|
+
await rt.start();
|
|
282
|
+
await rt.runCell('globalThis.cnt = 7; globalThis.who = "noc"; globalThis.when = new Date(0);');
|
|
283
|
+
const res = await rt.snapshot();
|
|
284
|
+
assert.equal(res.ok, true);
|
|
285
|
+
if (res.ok) {
|
|
286
|
+
assert.deepEqual(res.skipped, []);
|
|
287
|
+
assert.ok(typeof res.snapshotted_at === 'string');
|
|
288
|
+
}
|
|
289
|
+
const envelope = JSON.parse(readFileSync(join(sp, 'namespace.json'), 'utf8'));
|
|
290
|
+
assert.equal(envelope.schema_version, 1);
|
|
291
|
+
assert.equal(typeof envelope.snapshot_b64, 'string');
|
|
292
|
+
// Round-trip in a fresh runtime: globalThis.cnt comes back as 7.
|
|
293
|
+
await rt.dispose();
|
|
294
|
+
rt = new ChildProcessRuntime({ workspace: ws, scratchpadDir: sp, cellTimeoutMs: 30_000, inactivityTimeoutMs: 30_000 });
|
|
295
|
+
await rt.start();
|
|
296
|
+
const back = (await rt.runCell('return [globalThis.cnt, globalThis.who, globalThis.when.getTime()];')).value;
|
|
297
|
+
assert.deepEqual(back, [7, 'noc', 0]);
|
|
298
|
+
});
|
|
299
|
+
|
|
300
|
+
it('snapshot() records non-serializable values in skipped[]', async () => {
|
|
301
|
+
rt = new ChildProcessRuntime({ workspace: ws, scratchpadDir: sp, cellTimeoutMs: 30_000, inactivityTimeoutMs: 30_000 });
|
|
302
|
+
await rt.start();
|
|
303
|
+
// A function on globalThis is not v8-serializable.
|
|
304
|
+
await rt.runCell('globalThis.fn = function bad() { return 1; }; globalThis.ok = 1;');
|
|
305
|
+
const res = await rt.snapshot();
|
|
306
|
+
assert.equal(res.ok, true);
|
|
307
|
+
if (res.ok) {
|
|
308
|
+
assert.equal(res.skipped.length, 1);
|
|
309
|
+
assert.equal(res.skipped[0].key, 'fn');
|
|
310
|
+
assert.equal(res.skipped[0].ctor, 'Function');
|
|
311
|
+
}
|
|
312
|
+
});
|
|
313
|
+
|
|
314
|
+
it('snapshot() on a legacy runtime (no scratchpadDir) is a no-op and resolves ok', async () => {
|
|
315
|
+
rt = new ChildProcessRuntime({ workspace: ws });
|
|
316
|
+
await rt.start();
|
|
317
|
+
const res = await rt.snapshot();
|
|
318
|
+
assert.equal(res.ok, true);
|
|
319
|
+
if (res.ok) assert.deepEqual(res.skipped, []);
|
|
320
|
+
});
|
|
321
|
+
|
|
322
|
+
it('snapshot() on a disposed runtime resolves with ok:false (does NOT throw)', async () => {
|
|
323
|
+
rt = new ChildProcessRuntime({ workspace: ws, scratchpadDir: sp, cellTimeoutMs: 30_000, inactivityTimeoutMs: 30_000 });
|
|
324
|
+
await rt.start();
|
|
325
|
+
await rt.dispose();
|
|
326
|
+
const res = await rt.snapshot();
|
|
327
|
+
assert.equal(res.ok, false);
|
|
328
|
+
});
|
|
329
|
+
|
|
330
|
+
it('start() rejects with a startup_error/duckdb_open tagged error when kernel.db cannot be opened', async () => {
|
|
331
|
+
// Point scratchpadDir at a file (not a dir) so DuckDBInstance.create(join(file,"kernel.db")) fails.
|
|
332
|
+
const blocker = join(sp, 'blocker');
|
|
333
|
+
writeFileSync(blocker, 'x');
|
|
334
|
+
rt = new ChildProcessRuntime({ workspace: ws, scratchpadDir: blocker, cellTimeoutMs: 30_000, inactivityTimeoutMs: 30_000 });
|
|
335
|
+
await assert.rejects(rt.start(), (e: Error) => /startup_error\/duckdb_open/.test(e.name) || /duckdb/i.test(e.message));
|
|
336
|
+
});
|
|
337
|
+
});
|
|
338
|
+
|
|
339
|
+
describe('ChildProcessRuntime — vault env injection (Phase 2)', () => {
|
|
340
|
+
let ws: string;
|
|
341
|
+
let rt: ChildProcessRuntime;
|
|
342
|
+
|
|
343
|
+
beforeEach(async () => {
|
|
344
|
+
ws = await mkdtemp(join(tmpdir(), 'cpr-env-ws-'));
|
|
345
|
+
await mkdir(join(ws, '.otto', 'inputs'), { recursive: true });
|
|
346
|
+
});
|
|
347
|
+
afterEach(async () => {
|
|
348
|
+
await rt?.dispose();
|
|
349
|
+
await rm(ws, { recursive: true, force: true });
|
|
350
|
+
});
|
|
351
|
+
|
|
352
|
+
it('injects OTTO_DS_* env vars from bound vault entries into the spawned child only', async () => {
|
|
353
|
+
const root = mkdtempSync(join(tmpdir(), 'cpr-env-vault-'));
|
|
354
|
+
const audit = new AuditLog({ path: join(root, 'audit.jsonl') });
|
|
355
|
+
const vault = new LocalDataVault({ globalDir: join(root, 'global'), workspaceDir: undefined, audit });
|
|
356
|
+
await vault.set({ engine: 'jira', name: 'prod' }, { url: 'https://x', token: 't' });
|
|
357
|
+
const injector = new CredentialInjector({ vault, audit });
|
|
358
|
+
|
|
359
|
+
// Sanity: parent process must NOT have these env vars before spawn.
|
|
360
|
+
assert.equal(process.env.OTTO_DS_JIRA_PROD__URL, undefined);
|
|
361
|
+
assert.equal(process.env.OTTO_DS_JIRA_PROD__TOKEN, undefined);
|
|
362
|
+
|
|
363
|
+
rt = new ChildProcessRuntime({
|
|
364
|
+
workspace: ws,
|
|
365
|
+
cellTimeoutMs: 10_000,
|
|
366
|
+
inactivityTimeoutMs: 10_000,
|
|
367
|
+
injector,
|
|
368
|
+
bindings: ['jira:prod'],
|
|
369
|
+
scratchpadName: 'sp-env-test',
|
|
370
|
+
sessionId: 'sess-env-test',
|
|
371
|
+
});
|
|
372
|
+
await rt.start();
|
|
373
|
+
const { value } = await rt.runCell(
|
|
374
|
+
'return [process.env.OTTO_DS_JIRA_PROD__URL, process.env.OTTO_DS_JIRA_PROD__TOKEN];',
|
|
375
|
+
);
|
|
376
|
+
assert.deepEqual(value, ['https://x', 't']);
|
|
377
|
+
|
|
378
|
+
// Parent process must still be clean post-spawn.
|
|
379
|
+
assert.equal(process.env.OTTO_DS_JIRA_PROD__URL, undefined);
|
|
380
|
+
assert.equal(process.env.OTTO_DS_JIRA_PROD__TOKEN, undefined);
|
|
381
|
+
|
|
382
|
+
await rm(root, { recursive: true, force: true });
|
|
383
|
+
});
|
|
384
|
+
|
|
385
|
+
it('records spawnTime for staleness checks', async () => {
|
|
386
|
+
const root = mkdtempSync(join(tmpdir(), 'cpr-env-time-'));
|
|
387
|
+
const audit = new AuditLog({ path: join(root, 'audit.jsonl') });
|
|
388
|
+
const vault = new LocalDataVault({ globalDir: join(root, 'global'), workspaceDir: undefined, audit });
|
|
389
|
+
const injector = new CredentialInjector({ vault, audit });
|
|
390
|
+
|
|
391
|
+
rt = new ChildProcessRuntime({
|
|
392
|
+
workspace: ws,
|
|
393
|
+
cellTimeoutMs: 10_000,
|
|
394
|
+
inactivityTimeoutMs: 10_000,
|
|
395
|
+
injector,
|
|
396
|
+
bindings: [], // empty bindings: still tracks spawnTime, but skips injection
|
|
397
|
+
scratchpadName: 'sp-time-test',
|
|
398
|
+
sessionId: 'sess-time-test',
|
|
399
|
+
});
|
|
400
|
+
|
|
401
|
+
// Pre-start: spawnTime is the epoch placeholder.
|
|
402
|
+
assert.equal(rt.spawnTime.getTime(), 0);
|
|
403
|
+
|
|
404
|
+
const before = Date.now();
|
|
405
|
+
await rt.start();
|
|
406
|
+
const after = Date.now();
|
|
407
|
+
|
|
408
|
+
assert.ok(rt.spawnTime.getTime() >= before, 'spawnTime should be >= before start()');
|
|
409
|
+
assert.ok(rt.spawnTime.getTime() <= after, 'spawnTime should be <= after start()');
|
|
410
|
+
|
|
411
|
+
await rm(root, { recursive: true, force: true });
|
|
412
|
+
});
|
|
413
|
+
});
|