@cleocode/core 2026.6.12 → 2026.6.13
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/conduit/local-transport.d.ts +12 -0
- package/dist/conduit/local-transport.d.ts.map +1 -1
- package/dist/conduit/local-transport.js +53 -23
- package/dist/conduit/local-transport.js.map +1 -1
- package/dist/crypto/credentials.d.ts +37 -0
- package/dist/crypto/credentials.d.ts.map +1 -1
- package/dist/crypto/credentials.js +110 -0
- package/dist/crypto/credentials.js.map +1 -1
- package/dist/dispatch/contracts/derive-output-contract.d.ts +86 -0
- package/dist/dispatch/contracts/derive-output-contract.d.ts.map +1 -0
- package/dist/dispatch/contracts/derive-output-contract.js +347 -0
- package/dist/dispatch/contracts/derive-output-contract.js.map +1 -0
- package/dist/dispatch/contracts/ensures-schema.d.ts +77 -0
- package/dist/dispatch/contracts/ensures-schema.d.ts.map +1 -0
- package/dist/dispatch/contracts/ensures-schema.js +91 -0
- package/dist/dispatch/contracts/ensures-schema.js.map +1 -0
- package/dist/dispatch/contracts/output-contracts.d.ts +27 -5
- package/dist/dispatch/contracts/output-contracts.d.ts.map +1 -1
- package/dist/dispatch/contracts/output-contracts.js +29 -6
- package/dist/dispatch/contracts/output-contracts.js.map +1 -1
- package/dist/docs/export-document.js +2294 -1250
- package/dist/docs/export-document.js.map +3 -3
- package/dist/go/driver.d.ts +132 -7
- package/dist/go/driver.d.ts.map +1 -1
- package/dist/go/driver.js +135 -10
- package/dist/go/driver.js.map +1 -1
- package/dist/go/index.d.ts +1 -1
- package/dist/go/index.d.ts.map +1 -1
- package/dist/go/index.js +1 -1
- package/dist/go/index.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -1
- package/dist/internal.d.ts +13 -10
- package/dist/internal.d.ts.map +1 -1
- package/dist/internal.js +11 -11
- package/dist/internal.js.map +1 -1
- package/dist/lifecycle/engine-ops.d.ts.map +1 -1
- package/dist/lifecycle/engine-ops.js +7 -4
- package/dist/lifecycle/engine-ops.js.map +1 -1
- package/dist/lifecycle/ivtr-loop.d.ts +108 -183
- package/dist/lifecycle/ivtr-loop.d.ts.map +1 -1
- package/dist/lifecycle/ivtr-loop.js +207 -522
- package/dist/lifecycle/ivtr-loop.js.map +1 -1
- package/dist/llm/auxiliary-fallback.js +1 -1
- package/dist/llm/auxiliary-fallback.js.map +1 -1
- package/dist/llm/cli-ops.d.ts +14 -1
- package/dist/llm/cli-ops.d.ts.map +1 -1
- package/dist/llm/cli-ops.js +41 -12
- package/dist/llm/cli-ops.js.map +1 -1
- package/dist/llm/concrete-session.d.ts.map +1 -1
- package/dist/llm/concrete-session.js +4 -0
- package/dist/llm/concrete-session.js.map +1 -1
- package/dist/llm/credentials.d.ts +35 -0
- package/dist/llm/credentials.d.ts.map +1 -1
- package/dist/llm/credentials.js +49 -0
- package/dist/llm/credentials.js.map +1 -1
- package/dist/llm/index.d.ts +4 -0
- package/dist/llm/index.d.ts.map +1 -1
- package/dist/llm/index.js +4 -0
- package/dist/llm/index.js.map +1 -1
- package/dist/llm/pi/gondolin-loader.d.ts +241 -0
- package/dist/llm/pi/gondolin-loader.d.ts.map +1 -0
- package/dist/llm/pi/gondolin-loader.js +195 -0
- package/dist/llm/pi/gondolin-loader.js.map +1 -0
- package/dist/llm/pi/index.d.ts +28 -0
- package/dist/llm/pi/index.d.ts.map +1 -0
- package/dist/llm/pi/index.js +27 -0
- package/dist/llm/pi/index.js.map +1 -0
- package/dist/llm/pi/pi-agent-adapter.d.ts +135 -0
- package/dist/llm/pi/pi-agent-adapter.d.ts.map +1 -0
- package/dist/llm/pi/pi-agent-adapter.js +329 -0
- package/dist/llm/pi/pi-agent-adapter.js.map +1 -0
- package/dist/llm/pi/pi-errors.d.ts +161 -0
- package/dist/llm/pi/pi-errors.d.ts.map +1 -0
- package/dist/llm/pi/pi-errors.js +296 -0
- package/dist/llm/pi/pi-errors.js.map +1 -0
- package/dist/llm/pi/pi-execution-env.d.ts +286 -0
- package/dist/llm/pi/pi-execution-env.d.ts.map +1 -0
- package/dist/llm/pi/pi-execution-env.js +406 -0
- package/dist/llm/pi/pi-execution-env.js.map +1 -0
- package/dist/llm/pi/pi-gondolin-env.d.ts +227 -0
- package/dist/llm/pi/pi-gondolin-env.d.ts.map +1 -0
- package/dist/llm/pi/pi-gondolin-env.js +541 -0
- package/dist/llm/pi/pi-gondolin-env.js.map +1 -0
- package/dist/llm/pi/pi-session-storage.d.ts +154 -0
- package/dist/llm/pi/pi-session-storage.d.ts.map +1 -0
- package/dist/llm/pi/pi-session-storage.js +314 -0
- package/dist/llm/pi/pi-session-storage.js.map +1 -0
- package/dist/llm/pi/pi-stream-fn.d.ts +124 -0
- package/dist/llm/pi/pi-stream-fn.d.ts.map +1 -0
- package/dist/llm/pi/pi-stream-fn.js +504 -0
- package/dist/llm/pi/pi-stream-fn.js.map +1 -0
- package/dist/llm/pi/pi-tool-bridge.d.ts +99 -0
- package/dist/llm/pi/pi-tool-bridge.d.ts.map +1 -0
- package/dist/llm/pi/pi-tool-bridge.js +117 -0
- package/dist/llm/pi/pi-tool-bridge.js.map +1 -0
- package/dist/llm/pi/pi-types.d.ts +56 -0
- package/dist/llm/pi/pi-types.d.ts.map +1 -0
- package/dist/llm/pi/pi-types.js +16 -0
- package/dist/llm/pi/pi-types.js.map +1 -0
- package/dist/llm/pi/resolve-execution-env.d.ts +194 -0
- package/dist/llm/pi/resolve-execution-env.d.ts.map +1 -0
- package/dist/llm/pi/resolve-execution-env.js +132 -0
- package/dist/llm/pi/resolve-execution-env.js.map +1 -0
- package/dist/llm/plugin-facade.js +2253 -1151
- package/dist/llm/plugin-facade.js.map +3 -3
- package/dist/llm/role-executor.d.ts.map +1 -1
- package/dist/llm/role-executor.js +8 -5
- package/dist/llm/role-executor.js.map +1 -1
- package/dist/llm/role-resolver.d.ts +46 -14
- package/dist/llm/role-resolver.d.ts.map +1 -1
- package/dist/llm/role-resolver.js +178 -20
- package/dist/llm/role-resolver.js.map +1 -1
- package/dist/llm/sealed-credential.d.ts +125 -0
- package/dist/llm/sealed-credential.d.ts.map +1 -0
- package/dist/llm/sealed-credential.js +133 -0
- package/dist/llm/sealed-credential.js.map +1 -0
- package/dist/llm/session-factory.d.ts.map +1 -1
- package/dist/llm/session-factory.js +6 -2
- package/dist/llm/session-factory.js.map +1 -1
- package/dist/llm/system-key.d.ts +67 -0
- package/dist/llm/system-key.d.ts.map +1 -0
- package/dist/llm/system-key.js +87 -0
- package/dist/llm/system-key.js.map +1 -0
- package/dist/llm/system-of-use-registry.d.ts +119 -0
- package/dist/llm/system-of-use-registry.d.ts.map +1 -0
- package/dist/llm/system-of-use-registry.js +200 -0
- package/dist/llm/system-of-use-registry.js.map +1 -0
- package/dist/llm/system-resolver.d.ts +32 -10
- package/dist/llm/system-resolver.d.ts.map +1 -1
- package/dist/llm/system-resolver.js +70 -18
- package/dist/llm/system-resolver.js.map +1 -1
- package/dist/memory/brain-writer-thread.d.ts.map +1 -1
- package/dist/memory/brain-writer-thread.js +116 -11
- package/dist/memory/brain-writer-thread.js.map +1 -1
- package/dist/memory/claude-mem-migration.d.ts.map +1 -1
- package/dist/memory/claude-mem-migration.js +21 -0
- package/dist/memory/claude-mem-migration.js.map +1 -1
- package/dist/memory/graph-memory-bridge.d.ts.map +1 -1
- package/dist/memory/graph-memory-bridge.js +32 -25
- package/dist/memory/graph-memory-bridge.js.map +1 -1
- package/dist/memory/llm-backend-resolver.js +23 -5
- package/dist/memory/llm-backend-resolver.js.map +1 -1
- package/dist/nexus/migrations/M-split-graph.d.ts.map +1 -1
- package/dist/nexus/migrations/M-split-graph.js +60 -53
- package/dist/nexus/migrations/M-split-graph.js.map +1 -1
- package/dist/orchestrate/pivot.d.ts.map +1 -1
- package/dist/orchestrate/pivot.js +20 -2
- package/dist/orchestrate/pivot.js.map +1 -1
- package/dist/release/engine-ops.js +2 -2
- package/dist/release/engine-ops.js.map +1 -1
- package/dist/routing/capability-matrix.d.ts.map +1 -1
- package/dist/routing/capability-matrix.js +0 -57
- package/dist/routing/capability-matrix.js.map +1 -1
- package/dist/selfimprove/budget.d.ts +206 -0
- package/dist/selfimprove/budget.d.ts.map +1 -0
- package/dist/selfimprove/budget.js +203 -0
- package/dist/selfimprove/budget.js.map +1 -0
- package/dist/selfimprove/dhq-adapter.d.ts +105 -0
- package/dist/selfimprove/dhq-adapter.d.ts.map +1 -0
- package/dist/selfimprove/dhq-adapter.js +95 -0
- package/dist/selfimprove/dhq-adapter.js.map +1 -0
- package/dist/selfimprove/draft-pr.d.ts +129 -0
- package/dist/selfimprove/draft-pr.d.ts.map +1 -0
- package/dist/selfimprove/draft-pr.js +158 -0
- package/dist/selfimprove/draft-pr.js.map +1 -0
- package/dist/selfimprove/envelope-diff.d.ts +162 -0
- package/dist/selfimprove/envelope-diff.d.ts.map +1 -0
- package/dist/selfimprove/envelope-diff.js +321 -0
- package/dist/selfimprove/envelope-diff.js.map +1 -0
- package/dist/selfimprove/replay.d.ts +121 -0
- package/dist/selfimprove/replay.d.ts.map +1 -0
- package/dist/selfimprove/replay.js +109 -0
- package/dist/selfimprove/replay.js.map +1 -0
- package/dist/selfimprove/run-loop.d.ts +148 -0
- package/dist/selfimprove/run-loop.d.ts.map +1 -0
- package/dist/selfimprove/run-loop.js +240 -0
- package/dist/selfimprove/run-loop.js.map +1 -0
- package/dist/selfimprove/scenario.d.ts +145 -0
- package/dist/selfimprove/scenario.d.ts.map +1 -0
- package/dist/selfimprove/scenario.js +243 -0
- package/dist/selfimprove/scenario.js.map +1 -0
- package/dist/sentient/daemon-entry.js +5 -0
- package/dist/sentient/daemon-entry.js.map +1 -1
- package/dist/sentient/daemon.d.ts.map +1 -1
- package/dist/sentient/daemon.js +19 -0
- package/dist/sentient/daemon.js.map +1 -1
- package/dist/sentient/hygiene-scan.d.ts.map +1 -1
- package/dist/sentient/hygiene-scan.js +14 -6
- package/dist/sentient/hygiene-scan.js.map +1 -1
- package/dist/sessions/briefing.d.ts.map +1 -1
- package/dist/sessions/briefing.js +13 -9
- package/dist/sessions/briefing.js.map +1 -1
- package/dist/sessions/connection-session-handle.d.ts +161 -0
- package/dist/sessions/connection-session-handle.d.ts.map +1 -0
- package/dist/sessions/connection-session-handle.js +168 -0
- package/dist/sessions/connection-session-handle.js.map +1 -0
- package/dist/sessions/handoff.d.ts.map +1 -1
- package/dist/sessions/handoff.js +9 -0
- package/dist/sessions/handoff.js.map +1 -1
- package/dist/sessions/index.d.ts +4 -1
- package/dist/sessions/index.d.ts.map +1 -1
- package/dist/sessions/index.js +31 -1
- package/dist/sessions/index.js.map +1 -1
- package/dist/sessions/session-id.d.ts +34 -0
- package/dist/sessions/session-id.d.ts.map +1 -1
- package/dist/sessions/session-id.js +37 -0
- package/dist/sessions/session-id.js.map +1 -1
- package/dist/sessions/session-manifest-mirror.d.ts +115 -0
- package/dist/sessions/session-manifest-mirror.d.ts.map +1 -0
- package/dist/sessions/session-manifest-mirror.js +250 -0
- package/dist/sessions/session-manifest-mirror.js.map +1 -0
- package/dist/sessions/session-switch.d.ts.map +1 -1
- package/dist/sessions/session-switch.js +5 -2
- package/dist/sessions/session-switch.js.map +1 -1
- package/dist/store/converters.d.ts.map +1 -1
- package/dist/store/converters.js +2 -0
- package/dist/store/converters.js.map +1 -1
- package/dist/store/db-helpers.d.ts.map +1 -1
- package/dist/store/db-helpers.js +2 -0
- package/dist/store/db-helpers.js.map +1 -1
- package/dist/store/dual-scope-db.d.ts.map +1 -1
- package/dist/store/dual-scope-db.js +87 -47
- package/dist/store/dual-scope-db.js.map +1 -1
- package/dist/store/pi-session-store.d.ts +151 -0
- package/dist/store/pi-session-store.d.ts.map +1 -0
- package/dist/store/pi-session-store.js +166 -0
- package/dist/store/pi-session-store.js.map +1 -0
- package/dist/store/safety-data-accessor.d.ts +1 -0
- package/dist/store/safety-data-accessor.d.ts.map +1 -1
- package/dist/store/safety-data-accessor.js +5 -0
- package/dist/store/safety-data-accessor.js.map +1 -1
- package/dist/store/schema/cleo-global/accounts.d.ts +357 -0
- package/dist/store/schema/cleo-global/accounts.d.ts.map +1 -0
- package/dist/store/schema/cleo-global/accounts.js +136 -0
- package/dist/store/schema/cleo-global/accounts.js.map +1 -0
- package/dist/store/schema/cleo-global/index.d.ts +2 -0
- package/dist/store/schema/cleo-global/index.d.ts.map +1 -1
- package/dist/store/schema/cleo-global/index.js +2 -0
- package/dist/store/schema/cleo-global/index.js.map +1 -1
- package/dist/store/schema/cleo-global/session-manifest.d.ts +217 -0
- package/dist/store/schema/cleo-global/session-manifest.d.ts.map +1 -0
- package/dist/store/schema/cleo-global/session-manifest.js +99 -0
- package/dist/store/schema/cleo-global/session-manifest.js.map +1 -0
- package/dist/store/schema/cleo-project/tasks-core.d.ts +16 -0
- package/dist/store/schema/cleo-project/tasks-core.d.ts.map +1 -1
- package/dist/store/schema/cleo-project/tasks-core.js +14 -0
- package/dist/store/schema/cleo-project/tasks-core.js.map +1 -1
- package/dist/store/schema/tasks.d.ts +16 -0
- package/dist/store/schema/tasks.d.ts.map +1 -1
- package/dist/store/schema/tasks.js +10 -0
- package/dist/store/schema/tasks.js.map +1 -1
- package/dist/store/selfimprove-dhq-schema.d.ts +284 -0
- package/dist/store/selfimprove-dhq-schema.d.ts.map +1 -0
- package/dist/store/selfimprove-dhq-schema.js +128 -0
- package/dist/store/selfimprove-dhq-schema.js.map +1 -0
- package/dist/store/selfimprove-dhq-store.d.ts +175 -0
- package/dist/store/selfimprove-dhq-store.d.ts.map +1 -0
- package/dist/store/selfimprove-dhq-store.js +182 -0
- package/dist/store/selfimprove-dhq-store.js.map +1 -0
- package/dist/store/session-store.d.ts +52 -13
- package/dist/store/session-store.d.ts.map +1 -1
- package/dist/store/session-store.js +71 -13
- package/dist/store/session-store.js.map +1 -1
- package/dist/store/sqlite-data-accessor.d.ts.map +1 -1
- package/dist/store/sqlite-data-accessor.js +7 -0
- package/dist/store/sqlite-data-accessor.js.map +1 -1
- package/dist/store/umbrella-data-accessor.d.ts +1 -0
- package/dist/store/umbrella-data-accessor.d.ts.map +1 -1
- package/dist/store/umbrella-data-accessor.js +5 -0
- package/dist/store/umbrella-data-accessor.js.map +1 -1
- package/dist/store/validation-schemas.d.ts +32 -0
- package/dist/store/validation-schemas.d.ts.map +1 -1
- package/dist/store/writer-lease-schema.d.ts +392 -0
- package/dist/store/writer-lease-schema.d.ts.map +1 -0
- package/dist/store/writer-lease-schema.js +142 -0
- package/dist/store/writer-lease-schema.js.map +1 -0
- package/dist/store/writer-lease.d.ts +368 -0
- package/dist/store/writer-lease.d.ts.map +1 -0
- package/dist/store/writer-lease.js +1002 -0
- package/dist/store/writer-lease.js.map +1 -0
- package/dist/tasks/backfill-child-projections.d.ts.map +1 -1
- package/dist/tasks/backfill-child-projections.js +14 -9
- package/dist/tasks/backfill-child-projections.js.map +1 -1
- package/dist/tasks/complete.d.ts.map +1 -1
- package/dist/tasks/complete.js +7 -10
- package/dist/tasks/complete.js.map +1 -1
- package/dist/tasks/duplicate-detector.d.ts.map +1 -1
- package/dist/tasks/duplicate-detector.js +14 -7
- package/dist/tasks/duplicate-detector.js.map +1 -1
- package/dist/telemetry/index.d.ts.map +1 -1
- package/dist/telemetry/index.js +10 -4
- package/dist/telemetry/index.js.map +1 -1
- package/dist/tools/agent-registry.d.ts +250 -0
- package/dist/tools/agent-registry.d.ts.map +1 -0
- package/dist/tools/agent-registry.js +292 -0
- package/dist/tools/agent-registry.js.map +1 -0
- package/dist/tools/agent-tool-families.d.ts +107 -0
- package/dist/tools/agent-tool-families.d.ts.map +1 -0
- package/dist/tools/agent-tool-families.js +527 -0
- package/dist/tools/agent-tool-families.js.map +1 -0
- package/dist/tools/browser-driver.d.ts +183 -0
- package/dist/tools/browser-driver.d.ts.map +1 -0
- package/dist/tools/browser-driver.js +242 -0
- package/dist/tools/browser-driver.js.map +1 -0
- package/dist/tools/builtin-agent-tools.d.ts +36 -0
- package/dist/tools/builtin-agent-tools.d.ts.map +1 -0
- package/dist/tools/builtin-agent-tools.js +150 -0
- package/dist/tools/builtin-agent-tools.js.map +1 -0
- package/dist/tools/dispatch.d.ts +370 -0
- package/dist/tools/dispatch.d.ts.map +1 -0
- package/dist/tools/dispatch.js +505 -0
- package/dist/tools/dispatch.js.map +1 -0
- package/dist/tools/env-scrub.d.ts +93 -0
- package/dist/tools/env-scrub.d.ts.map +1 -0
- package/dist/tools/env-scrub.js +176 -0
- package/dist/tools/env-scrub.js.map +1 -0
- package/dist/tools/fs.d.ts +30 -0
- package/dist/tools/fs.d.ts.map +1 -1
- package/dist/tools/fs.js +55 -2
- package/dist/tools/fs.js.map +1 -1
- package/dist/tools/guard.d.ts +15 -0
- package/dist/tools/guard.d.ts.map +1 -1
- package/dist/tools/guard.js +49 -12
- package/dist/tools/guard.js.map +1 -1
- package/dist/tools/index.d.ts +10 -0
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +37 -0
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/pty.d.ts +45 -0
- package/dist/tools/pty.d.ts.map +1 -0
- package/dist/tools/pty.js +166 -0
- package/dist/tools/pty.js.map +1 -0
- package/dist/tools/schema-gen.d.ts +57 -0
- package/dist/tools/schema-gen.d.ts.map +1 -0
- package/dist/tools/schema-gen.js +52 -0
- package/dist/tools/schema-gen.js.map +1 -0
- package/dist/tools/shell.d.ts +12 -0
- package/dist/tools/shell.d.ts.map +1 -1
- package/dist/tools/shell.js +14 -1
- package/dist/tools/shell.js.map +1 -1
- package/dist/tools/web-agent-tools.d.ts +72 -0
- package/dist/tools/web-agent-tools.d.ts.map +1 -0
- package/dist/tools/web-agent-tools.js +393 -0
- package/dist/tools/web-agent-tools.js.map +1 -0
- package/dist/tools/web-search-backends.d.ts +156 -0
- package/dist/tools/web-search-backends.d.ts.map +1 -0
- package/dist/tools/web-search-backends.js +290 -0
- package/dist/tools/web-search-backends.js.map +1 -0
- package/dist/validation/ops.d.ts +1 -15
- package/dist/validation/ops.d.ts.map +1 -1
- package/dist/validation/ops.js +0 -20
- package/dist/validation/ops.js.map +1 -1
- package/migrations/drizzle-cleo-global/20260607000000_t11891-writer-leases/migration.sql +55 -0
- package/migrations/drizzle-cleo-global/20260607010000_t11639-session-manifest/migration.sql +43 -0
- package/migrations/drizzle-cleo-global/20260608000000_t11899-pi-session-tree/migration.sql +52 -0
- package/migrations/drizzle-cleo-global/20260608010000_t11709-accounts-credential-pool/migration.sql +72 -0
- package/migrations/drizzle-cleo-global/20260608020000_t11889-selfimprove-dhq/migration.sql +64 -0
- package/migrations/drizzle-cleo-project/20260607000000_t11891-writer-leases/migration.sql +55 -0
- package/migrations/drizzle-cleo-project/20260607010000_t11639-session-parent/migration.sql +22 -0
- package/migrations/drizzle-cleo-project/20260608000000_t11899-pi-session-tree/migration.sql +52 -0
- package/migrations/drizzle-cleo-project/20260608020000_t11889-selfimprove-dhq/migration.sql +64 -0
- package/package.json +15 -13
- package/dist/lifecycle/chain-composition.d.ts +0 -30
- package/dist/lifecycle/chain-composition.d.ts.map +0 -1
- package/dist/lifecycle/chain-composition.js +0 -152
- package/dist/lifecycle/chain-composition.js.map +0 -1
- package/dist/lifecycle/chain-store.d.ts +0 -70
- package/dist/lifecycle/chain-store.d.ts.map +0 -1
- package/dist/lifecycle/chain-store.js +0 -246
- package/dist/lifecycle/chain-store.js.map +0 -1
- package/dist/lifecycle/default-chain.d.ts +0 -39
- package/dist/lifecycle/default-chain.d.ts.map +0 -1
- package/dist/lifecycle/default-chain.js +0 -176
- package/dist/lifecycle/default-chain.js.map +0 -1
- package/dist/lifecycle/tessera-engine.d.ts +0 -48
- package/dist/lifecycle/tessera-engine.d.ts.map +0 -1
- package/dist/lifecycle/tessera-engine.js +0 -249
- package/dist/lifecycle/tessera-engine.js.map +0 -1
- package/dist/validation/chain-validation.d.ts +0 -43
- package/dist/validation/chain-validation.d.ts.map +0 -1
- package/dist/validation/chain-validation.js +0 -146
- package/dist/validation/chain-validation.js.map +0 -1
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `CleoSessionStorage` — durable Pi `SessionStorage` over `cleo.db` (T11761 · S3 · T11899).
|
|
3
|
+
*
|
|
4
|
+
* The flag-ON, durable half of the Pi session-persistence seam. It implements
|
|
5
|
+
* Pi's tree-structured `SessionStorage` interface
|
|
6
|
+
* (`@earendil-works/pi-agent-core`) over the PROJECT-scope consolidated
|
|
7
|
+
* `cleo.db`, with ZERO write authority:
|
|
8
|
+
*
|
|
9
|
+
* - **All durable writes go through {@link withWriterLease}** (`writer-lease.ts`,
|
|
10
|
+
* PROJECT scope + `bulk` lane) — the daemon remains the sole arbitrated
|
|
11
|
+
* Drizzle writer. This adapter NEVER opens a raw DB writer (Gate 3): it calls
|
|
12
|
+
* the store-layer accessor ({@link import('../../store/pi-session-store.js')}),
|
|
13
|
+
* which extracts the native handle the chokepoint already holds.
|
|
14
|
+
* - **Identity is daemon-stamped, never minted.** The owning `sessionId` is
|
|
15
|
+
* supplied at construction from `resolveCurrentSessionId` / `CLEO_SESSION_ID`
|
|
16
|
+
* (resolved in `pi-agent-adapter.ts`). Unlike `InMemorySessionStorage`, this
|
|
17
|
+
* storage NEVER calls `uuidv7()` to mint an id.
|
|
18
|
+
*
|
|
19
|
+
* {@link InMemorySessionStorage} (from `pi-agent-core`) remains the flag-OFF
|
|
20
|
+
* default that the S2 adapter body uses; this durable storage activates only when
|
|
21
|
+
* the Pi-runner flag is enabled AND a durable session is requested.
|
|
22
|
+
*
|
|
23
|
+
* The tree semantics mirror the upstream `InMemorySessionStorage` reference
|
|
24
|
+
* (memory-storage.ts) byte-for-byte — `appendEntry` advances the leaf via
|
|
25
|
+
* `leafIdAfterEntry`, `setLeafId` appends a synthetic `leaf` entry, label-cache
|
|
26
|
+
* and `getPathToRoot` walk parent chains — so a session tree written here reads
|
|
27
|
+
* back identical to the in-memory implementation. The ONLY difference is the
|
|
28
|
+
* backing store (durable cleo.db rows vs in-RAM arrays) and the lease boundary.
|
|
29
|
+
*
|
|
30
|
+
* @module
|
|
31
|
+
* @task T11899
|
|
32
|
+
* @task T11761
|
|
33
|
+
* @epic T10403
|
|
34
|
+
*/
|
|
35
|
+
import type { SessionMetadata, SessionStorage, SessionTreeEntry } from '@earendil-works/pi-agent-core';
|
|
36
|
+
/**
|
|
37
|
+
* Construction options for {@link CleoSessionStorage}.
|
|
38
|
+
*/
|
|
39
|
+
export interface CleoSessionStorageOptions {
|
|
40
|
+
/**
|
|
41
|
+
* The daemon-stamped owning session id. MUST be a real, env-resolved id —
|
|
42
|
+
* never a freshly-minted one. The S2 adapter reads it from
|
|
43
|
+
* `resolveCurrentSessionId` / `CLEO_SESSION_ID` and passes it here.
|
|
44
|
+
*/
|
|
45
|
+
readonly sessionId: string;
|
|
46
|
+
/**
|
|
47
|
+
* Project working directory for `cleo.db` resolution. Defaults to `cwd` inside
|
|
48
|
+
* the store accessor.
|
|
49
|
+
*/
|
|
50
|
+
readonly cwd?: string;
|
|
51
|
+
/**
|
|
52
|
+
* Wall-clock provider (injectable for deterministic tests). Defaults to
|
|
53
|
+
* `() => new Date().toISOString()`.
|
|
54
|
+
*/
|
|
55
|
+
readonly now?: () => string;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Durable Pi `SessionStorage` backed by the PROJECT-scope `cleo.db`.
|
|
59
|
+
*
|
|
60
|
+
* Every mutating method ({@link appendEntry}, {@link setLeafId}) runs its write
|
|
61
|
+
* inside `withWriterLease('project', 'bulk', …)`; read methods operate directly
|
|
62
|
+
* on the shared native handle (no lease — readers do not contend the writer
|
|
63
|
+
* arbitration row). The session id is fixed at construction and never minted.
|
|
64
|
+
*/
|
|
65
|
+
export declare class CleoSessionStorage implements SessionStorage {
|
|
66
|
+
#private;
|
|
67
|
+
/**
|
|
68
|
+
* @param options - The daemon-stamped session id + optional cwd / clock.
|
|
69
|
+
*/
|
|
70
|
+
constructor(options: CleoSessionStorageOptions);
|
|
71
|
+
/**
|
|
72
|
+
* Return the session metadata. The `id` is ALWAYS the daemon-stamped id this
|
|
73
|
+
* storage was constructed with (never minted); `createdAt` is the persisted
|
|
74
|
+
* leaf-row anchor, lazily created on first read so a never-written session
|
|
75
|
+
* still yields stable metadata.
|
|
76
|
+
*
|
|
77
|
+
* @returns The session metadata.
|
|
78
|
+
*/
|
|
79
|
+
getMetadata(): Promise<SessionMetadata>;
|
|
80
|
+
/**
|
|
81
|
+
* Return the active leaf id, or `null` when none is set.
|
|
82
|
+
*
|
|
83
|
+
* @returns The leaf id or `null`.
|
|
84
|
+
* @throws {SessionError} `invalid_session` when the recorded leaf entry is missing.
|
|
85
|
+
*/
|
|
86
|
+
getLeafId(): Promise<string | null>;
|
|
87
|
+
/**
|
|
88
|
+
* Persist a leaf entry that records the active session-tree leaf.
|
|
89
|
+
*
|
|
90
|
+
* Mirrors the upstream reference: appends a synthetic `leaf` entry (parented at
|
|
91
|
+
* the current leaf) THEN advances the leaf pointer to `leafId`. The whole
|
|
92
|
+
* mutation runs inside ONE leased section.
|
|
93
|
+
*
|
|
94
|
+
* @param leafId - The new active leaf entry id, or `null` to reset to root.
|
|
95
|
+
* @throws {SessionError} `not_found` when `leafId` names no existing entry.
|
|
96
|
+
*/
|
|
97
|
+
setLeafId(leafId: string | null): Promise<void>;
|
|
98
|
+
/**
|
|
99
|
+
* Allocate a fresh, unused entry id for this session.
|
|
100
|
+
*
|
|
101
|
+
* Read-only (no persistence until {@link appendEntry}) — matches the upstream
|
|
102
|
+
* `createEntryId`.
|
|
103
|
+
*
|
|
104
|
+
* @returns A fresh unused entry id.
|
|
105
|
+
*/
|
|
106
|
+
createEntryId(): Promise<string>;
|
|
107
|
+
/**
|
|
108
|
+
* Append a tree entry and advance the leaf pointer (leased write).
|
|
109
|
+
*
|
|
110
|
+
* @param entry - The entry to persist.
|
|
111
|
+
*/
|
|
112
|
+
appendEntry(entry: SessionTreeEntry): Promise<void>;
|
|
113
|
+
/**
|
|
114
|
+
* Return an entry by id, or `undefined` when absent.
|
|
115
|
+
*
|
|
116
|
+
* @param id - The entry id.
|
|
117
|
+
* @returns The entry or `undefined`.
|
|
118
|
+
*/
|
|
119
|
+
getEntry(id: string): Promise<SessionTreeEntry | undefined>;
|
|
120
|
+
/**
|
|
121
|
+
* Return all entries of a given type in append order.
|
|
122
|
+
*
|
|
123
|
+
* @param type - The entry-type discriminator to filter on.
|
|
124
|
+
* @returns The matching entries.
|
|
125
|
+
*/
|
|
126
|
+
findEntries<TType extends SessionTreeEntry['type']>(type: TType): Promise<Array<Extract<SessionTreeEntry, {
|
|
127
|
+
type: TType;
|
|
128
|
+
}>>>;
|
|
129
|
+
/**
|
|
130
|
+
* Return the most-recent label applied to an entry, or `undefined`.
|
|
131
|
+
*
|
|
132
|
+
* Computed from the `label` entries (last write wins; an empty label clears),
|
|
133
|
+
* mirroring the upstream label cache.
|
|
134
|
+
*
|
|
135
|
+
* @param id - The target entry id.
|
|
136
|
+
* @returns The label or `undefined`.
|
|
137
|
+
*/
|
|
138
|
+
getLabel(id: string): Promise<string | undefined>;
|
|
139
|
+
/**
|
|
140
|
+
* Walk from a leaf to the root, returning the path in root→leaf order.
|
|
141
|
+
*
|
|
142
|
+
* @param leafId - The leaf to walk from, or `null` for an empty path.
|
|
143
|
+
* @returns The root→leaf entry path.
|
|
144
|
+
* @throws {SessionError} `not_found` / `invalid_session` on a broken chain.
|
|
145
|
+
*/
|
|
146
|
+
getPathToRoot(leafId: string | null): Promise<SessionTreeEntry[]>;
|
|
147
|
+
/**
|
|
148
|
+
* Return all entries for this session in stable append order.
|
|
149
|
+
*
|
|
150
|
+
* @returns The ordered entries.
|
|
151
|
+
*/
|
|
152
|
+
getEntries(): Promise<SessionTreeEntry[]>;
|
|
153
|
+
}
|
|
154
|
+
//# sourceMappingURL=pi-session-storage.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pi-session-storage.d.ts","sourceRoot":"","sources":["../../../src/llm/pi/pi-session-storage.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AAGH,OAAO,KAAK,EACV,eAAe,EACf,cAAc,EACd,gBAAgB,EACjB,MAAM,+BAA+B,CAAC;AAwBvC;;GAEG;AACH,MAAM,WAAW,yBAAyB;IACxC;;;;OAIG;IACH,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B;;;OAGG;IACH,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IACtB;;;OAGG;IACH,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;CAC7B;AA8DD;;;;;;;GAOG;AACH,qBAAa,kBAAmB,YAAW,cAAc;;IAKvD;;OAEG;gBACS,OAAO,EAAE,yBAAyB;IAM9C;;;;;;;OAOG;IACG,WAAW,IAAI,OAAO,CAAC,eAAe,CAAC;IAU7C;;;;;OAKG;IACG,SAAS,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAUzC;;;;;;;;;OASG;IACG,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAoBrD;;;;;;;OAOG;IACG,aAAa,IAAI,OAAO,CAAC,MAAM,CAAC;IAKtC;;;;OAIG;IACG,WAAW,CAAC,KAAK,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC;IAezD;;;;;OAKG;IACG,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,GAAG,SAAS,CAAC;IAMjE;;;;;OAKG;IACG,WAAW,CAAC,KAAK,SAAS,gBAAgB,CAAC,MAAM,CAAC,EACtD,IAAI,EAAE,KAAK,GACV,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,gBAAgB,EAAE;QAAE,IAAI,EAAE,KAAK,CAAA;KAAE,CAAC,CAAC,CAAC;IAO7D;;;;;;;;OAQG;IACG,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC;IAWvD;;;;;;OAMG;IACG,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,gBAAgB,EAAE,CAAC;IAwBvE;;;;OAIG;IACG,UAAU,IAAI,OAAO,CAAC,gBAAgB,EAAE,CAAC;CA0BhD"}
|
|
@@ -0,0 +1,314 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `CleoSessionStorage` — durable Pi `SessionStorage` over `cleo.db` (T11761 · S3 · T11899).
|
|
3
|
+
*
|
|
4
|
+
* The flag-ON, durable half of the Pi session-persistence seam. It implements
|
|
5
|
+
* Pi's tree-structured `SessionStorage` interface
|
|
6
|
+
* (`@earendil-works/pi-agent-core`) over the PROJECT-scope consolidated
|
|
7
|
+
* `cleo.db`, with ZERO write authority:
|
|
8
|
+
*
|
|
9
|
+
* - **All durable writes go through {@link withWriterLease}** (`writer-lease.ts`,
|
|
10
|
+
* PROJECT scope + `bulk` lane) — the daemon remains the sole arbitrated
|
|
11
|
+
* Drizzle writer. This adapter NEVER opens a raw DB writer (Gate 3): it calls
|
|
12
|
+
* the store-layer accessor ({@link import('../../store/pi-session-store.js')}),
|
|
13
|
+
* which extracts the native handle the chokepoint already holds.
|
|
14
|
+
* - **Identity is daemon-stamped, never minted.** The owning `sessionId` is
|
|
15
|
+
* supplied at construction from `resolveCurrentSessionId` / `CLEO_SESSION_ID`
|
|
16
|
+
* (resolved in `pi-agent-adapter.ts`). Unlike `InMemorySessionStorage`, this
|
|
17
|
+
* storage NEVER calls `uuidv7()` to mint an id.
|
|
18
|
+
*
|
|
19
|
+
* {@link InMemorySessionStorage} (from `pi-agent-core`) remains the flag-OFF
|
|
20
|
+
* default that the S2 adapter body uses; this durable storage activates only when
|
|
21
|
+
* the Pi-runner flag is enabled AND a durable session is requested.
|
|
22
|
+
*
|
|
23
|
+
* The tree semantics mirror the upstream `InMemorySessionStorage` reference
|
|
24
|
+
* (memory-storage.ts) byte-for-byte — `appendEntry` advances the leaf via
|
|
25
|
+
* `leafIdAfterEntry`, `setLeafId` appends a synthetic `leaf` entry, label-cache
|
|
26
|
+
* and `getPathToRoot` walk parent chains — so a session tree written here reads
|
|
27
|
+
* back identical to the in-memory implementation. The ONLY difference is the
|
|
28
|
+
* backing store (durable cleo.db rows vs in-RAM arrays) and the lease boundary.
|
|
29
|
+
*
|
|
30
|
+
* @module
|
|
31
|
+
* @task T11899
|
|
32
|
+
* @task T11761
|
|
33
|
+
* @epic T10403
|
|
34
|
+
*/
|
|
35
|
+
import { randomUUID } from 'node:crypto';
|
|
36
|
+
import { SessionError } from '@earendil-works/pi-agent-core';
|
|
37
|
+
import { getLogger } from '../../logger.js';
|
|
38
|
+
import { getPiSessionNativeDb, insertPiSessionEntry, readPiSessionEntries, readPiSessionEntry, readPiSessionLeaf, upsertPiSessionLeaf, } from '../../store/pi-session-store.js';
|
|
39
|
+
import { withWriterLease } from '../../store/writer-lease.js';
|
|
40
|
+
/**
|
|
41
|
+
* Lazily-memoized module logger (import-time side-effect-free per the page-2 /
|
|
42
|
+
* mocked-import-graph invariant — see `writer-lease.ts` rationale).
|
|
43
|
+
*/
|
|
44
|
+
let _log = null;
|
|
45
|
+
function log() {
|
|
46
|
+
if (_log === null)
|
|
47
|
+
_log = getLogger('pi-session-storage');
|
|
48
|
+
return _log;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Generate a fresh 8-char entry id NOT already present in `existing`.
|
|
52
|
+
*
|
|
53
|
+
* Mirrors the upstream `generateEntryId` (memory-storage.ts): up to 100 attempts
|
|
54
|
+
* at an 8-char `uuidv7` prefix, falling back to a full id. We avoid importing
|
|
55
|
+
* Pi's internal `uuidv7` (not a barrel export) and use `node:crypto`'s
|
|
56
|
+
* `randomUUID()` —
|
|
57
|
+
* the id is an opaque tree-node handle, NOT a session identity (which is always
|
|
58
|
+
* daemon-stamped), so its generator is irrelevant to the identity contract.
|
|
59
|
+
*
|
|
60
|
+
* @param existing - The set of ids already in use for this session.
|
|
61
|
+
* @returns A fresh unused entry id.
|
|
62
|
+
*/
|
|
63
|
+
function generateEntryId(existing) {
|
|
64
|
+
for (let i = 0; i < 100; i++) {
|
|
65
|
+
const id = randomUUID().replace(/-/g, '').slice(0, 8);
|
|
66
|
+
if (!existing.has(id))
|
|
67
|
+
return id;
|
|
68
|
+
}
|
|
69
|
+
return randomUUID();
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Columnized fields hoisted out of a {@link SessionTreeEntry} into dedicated
|
|
73
|
+
* columns; the remainder is JSON-serialized into `payload_json`.
|
|
74
|
+
*/
|
|
75
|
+
const COLUMNIZED_KEYS = ['id', 'parentId', 'type', 'timestamp'];
|
|
76
|
+
/** Split a Pi entry into its columnized fields + JSON residue. */
|
|
77
|
+
function encodeEntry(sessionId, entry) {
|
|
78
|
+
const residue = {};
|
|
79
|
+
for (const [key, value] of Object.entries(entry)) {
|
|
80
|
+
if (!COLUMNIZED_KEYS.includes(key))
|
|
81
|
+
residue[key] = value;
|
|
82
|
+
}
|
|
83
|
+
return {
|
|
84
|
+
sessionId,
|
|
85
|
+
entryId: entry.id,
|
|
86
|
+
parentId: entry.parentId,
|
|
87
|
+
type: entry.type,
|
|
88
|
+
payloadJson: JSON.stringify(residue),
|
|
89
|
+
ts: entry.timestamp,
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
/** Re-hydrate a full Pi entry by merging columns back over the JSON residue. */
|
|
93
|
+
function decodeEntry(row) {
|
|
94
|
+
const residue = JSON.parse(row.payloadJson);
|
|
95
|
+
return {
|
|
96
|
+
...residue,
|
|
97
|
+
id: row.entryId,
|
|
98
|
+
parentId: row.parentId,
|
|
99
|
+
type: row.type,
|
|
100
|
+
timestamp: row.ts,
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
/** The leaf id an entry establishes (leaf entries point at `targetId`; others at own id). */
|
|
104
|
+
function leafIdAfterEntry(entry) {
|
|
105
|
+
return entry.type === 'leaf' ? entry.targetId : entry.id;
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Durable Pi `SessionStorage` backed by the PROJECT-scope `cleo.db`.
|
|
109
|
+
*
|
|
110
|
+
* Every mutating method ({@link appendEntry}, {@link setLeafId}) runs its write
|
|
111
|
+
* inside `withWriterLease('project', 'bulk', …)`; read methods operate directly
|
|
112
|
+
* on the shared native handle (no lease — readers do not contend the writer
|
|
113
|
+
* arbitration row). The session id is fixed at construction and never minted.
|
|
114
|
+
*/
|
|
115
|
+
export class CleoSessionStorage {
|
|
116
|
+
#sessionId;
|
|
117
|
+
#cwd;
|
|
118
|
+
#now;
|
|
119
|
+
/**
|
|
120
|
+
* @param options - The daemon-stamped session id + optional cwd / clock.
|
|
121
|
+
*/
|
|
122
|
+
constructor(options) {
|
|
123
|
+
this.#sessionId = options.sessionId;
|
|
124
|
+
this.#cwd = options.cwd;
|
|
125
|
+
this.#now = options.now ?? (() => new Date().toISOString());
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Return the session metadata. The `id` is ALWAYS the daemon-stamped id this
|
|
129
|
+
* storage was constructed with (never minted); `createdAt` is the persisted
|
|
130
|
+
* leaf-row anchor, lazily created on first read so a never-written session
|
|
131
|
+
* still yields stable metadata.
|
|
132
|
+
*
|
|
133
|
+
* @returns The session metadata.
|
|
134
|
+
*/
|
|
135
|
+
async getMetadata() {
|
|
136
|
+
const native = await getPiSessionNativeDb(this.#cwd);
|
|
137
|
+
const leaf = readPiSessionLeaf(native, this.#sessionId);
|
|
138
|
+
if (leaf)
|
|
139
|
+
return { id: this.#sessionId, createdAt: leaf.createdAt };
|
|
140
|
+
// No row yet — establish the createdAt anchor durably (leaf stays null).
|
|
141
|
+
const ts = this.#now();
|
|
142
|
+
await this.#leasedWrite((db) => upsertPiSessionLeaf(db, this.#sessionId, null, ts, ts));
|
|
143
|
+
return { id: this.#sessionId, createdAt: ts };
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Return the active leaf id, or `null` when none is set.
|
|
147
|
+
*
|
|
148
|
+
* @returns The leaf id or `null`.
|
|
149
|
+
* @throws {SessionError} `invalid_session` when the recorded leaf entry is missing.
|
|
150
|
+
*/
|
|
151
|
+
async getLeafId() {
|
|
152
|
+
const native = await getPiSessionNativeDb(this.#cwd);
|
|
153
|
+
const leaf = readPiSessionLeaf(native, this.#sessionId);
|
|
154
|
+
const leafId = leaf?.leafId ?? null;
|
|
155
|
+
if (leafId !== null && readPiSessionEntry(native, this.#sessionId, leafId) === null) {
|
|
156
|
+
throw new SessionError('invalid_session', `Entry ${leafId} not found`);
|
|
157
|
+
}
|
|
158
|
+
return leafId;
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Persist a leaf entry that records the active session-tree leaf.
|
|
162
|
+
*
|
|
163
|
+
* Mirrors the upstream reference: appends a synthetic `leaf` entry (parented at
|
|
164
|
+
* the current leaf) THEN advances the leaf pointer to `leafId`. The whole
|
|
165
|
+
* mutation runs inside ONE leased section.
|
|
166
|
+
*
|
|
167
|
+
* @param leafId - The new active leaf entry id, or `null` to reset to root.
|
|
168
|
+
* @throws {SessionError} `not_found` when `leafId` names no existing entry.
|
|
169
|
+
*/
|
|
170
|
+
async setLeafId(leafId) {
|
|
171
|
+
await this.#leasedWrite((native) => {
|
|
172
|
+
if (leafId !== null && readPiSessionEntry(native, this.#sessionId, leafId) === null) {
|
|
173
|
+
throw new SessionError('not_found', `Entry ${leafId} not found`);
|
|
174
|
+
}
|
|
175
|
+
const ids = this.#entryIdSet(native);
|
|
176
|
+
const currentLeaf = readPiSessionLeaf(native, this.#sessionId);
|
|
177
|
+
const ts = this.#now();
|
|
178
|
+
const synthetic = {
|
|
179
|
+
type: 'leaf',
|
|
180
|
+
id: generateEntryId(ids),
|
|
181
|
+
parentId: currentLeaf?.leafId ?? null,
|
|
182
|
+
timestamp: ts,
|
|
183
|
+
targetId: leafId,
|
|
184
|
+
};
|
|
185
|
+
insertPiSessionEntry(native, encodeEntry(this.#sessionId, synthetic));
|
|
186
|
+
upsertPiSessionLeaf(native, this.#sessionId, leafId, currentLeaf?.createdAt ?? ts, ts);
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* Allocate a fresh, unused entry id for this session.
|
|
191
|
+
*
|
|
192
|
+
* Read-only (no persistence until {@link appendEntry}) — matches the upstream
|
|
193
|
+
* `createEntryId`.
|
|
194
|
+
*
|
|
195
|
+
* @returns A fresh unused entry id.
|
|
196
|
+
*/
|
|
197
|
+
async createEntryId() {
|
|
198
|
+
const native = await getPiSessionNativeDb(this.#cwd);
|
|
199
|
+
return generateEntryId(this.#entryIdSet(native));
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* Append a tree entry and advance the leaf pointer (leased write).
|
|
203
|
+
*
|
|
204
|
+
* @param entry - The entry to persist.
|
|
205
|
+
*/
|
|
206
|
+
async appendEntry(entry) {
|
|
207
|
+
await this.#leasedWrite((native) => {
|
|
208
|
+
insertPiSessionEntry(native, encodeEntry(this.#sessionId, entry));
|
|
209
|
+
const existing = readPiSessionLeaf(native, this.#sessionId);
|
|
210
|
+
const ts = this.#now();
|
|
211
|
+
upsertPiSessionLeaf(native, this.#sessionId, leafIdAfterEntry(entry), existing?.createdAt ?? ts, ts);
|
|
212
|
+
});
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* Return an entry by id, or `undefined` when absent.
|
|
216
|
+
*
|
|
217
|
+
* @param id - The entry id.
|
|
218
|
+
* @returns The entry or `undefined`.
|
|
219
|
+
*/
|
|
220
|
+
async getEntry(id) {
|
|
221
|
+
const native = await getPiSessionNativeDb(this.#cwd);
|
|
222
|
+
const row = readPiSessionEntry(native, this.#sessionId, id);
|
|
223
|
+
return row === null ? undefined : decodeEntry(row);
|
|
224
|
+
}
|
|
225
|
+
/**
|
|
226
|
+
* Return all entries of a given type in append order.
|
|
227
|
+
*
|
|
228
|
+
* @param type - The entry-type discriminator to filter on.
|
|
229
|
+
* @returns The matching entries.
|
|
230
|
+
*/
|
|
231
|
+
async findEntries(type) {
|
|
232
|
+
const entries = await this.getEntries();
|
|
233
|
+
return entries.filter((e) => e.type === type);
|
|
234
|
+
}
|
|
235
|
+
/**
|
|
236
|
+
* Return the most-recent label applied to an entry, or `undefined`.
|
|
237
|
+
*
|
|
238
|
+
* Computed from the `label` entries (last write wins; an empty label clears),
|
|
239
|
+
* mirroring the upstream label cache.
|
|
240
|
+
*
|
|
241
|
+
* @param id - The target entry id.
|
|
242
|
+
* @returns The label or `undefined`.
|
|
243
|
+
*/
|
|
244
|
+
async getLabel(id) {
|
|
245
|
+
const entries = await this.getEntries();
|
|
246
|
+
let label;
|
|
247
|
+
for (const entry of entries) {
|
|
248
|
+
if (entry.type !== 'label' || entry.targetId !== id)
|
|
249
|
+
continue;
|
|
250
|
+
const trimmed = entry.label?.trim();
|
|
251
|
+
label = trimmed ? trimmed : undefined;
|
|
252
|
+
}
|
|
253
|
+
return label;
|
|
254
|
+
}
|
|
255
|
+
/**
|
|
256
|
+
* Walk from a leaf to the root, returning the path in root→leaf order.
|
|
257
|
+
*
|
|
258
|
+
* @param leafId - The leaf to walk from, or `null` for an empty path.
|
|
259
|
+
* @returns The root→leaf entry path.
|
|
260
|
+
* @throws {SessionError} `not_found` / `invalid_session` on a broken chain.
|
|
261
|
+
*/
|
|
262
|
+
async getPathToRoot(leafId) {
|
|
263
|
+
if (leafId === null)
|
|
264
|
+
return [];
|
|
265
|
+
const native = await getPiSessionNativeDb(this.#cwd);
|
|
266
|
+
const byId = new Map(readPiSessionEntries(native, this.#sessionId).map((r) => {
|
|
267
|
+
const entry = decodeEntry(r);
|
|
268
|
+
return [entry.id, entry];
|
|
269
|
+
}));
|
|
270
|
+
const path = [];
|
|
271
|
+
let current = byId.get(leafId);
|
|
272
|
+
if (!current)
|
|
273
|
+
throw new SessionError('not_found', `Entry ${leafId} not found`);
|
|
274
|
+
while (current) {
|
|
275
|
+
path.unshift(current);
|
|
276
|
+
if (!current.parentId)
|
|
277
|
+
break;
|
|
278
|
+
const parent = byId.get(current.parentId);
|
|
279
|
+
if (!parent) {
|
|
280
|
+
throw new SessionError('invalid_session', `Entry ${current.parentId} not found`);
|
|
281
|
+
}
|
|
282
|
+
current = parent;
|
|
283
|
+
}
|
|
284
|
+
return path;
|
|
285
|
+
}
|
|
286
|
+
/**
|
|
287
|
+
* Return all entries for this session in stable append order.
|
|
288
|
+
*
|
|
289
|
+
* @returns The ordered entries.
|
|
290
|
+
*/
|
|
291
|
+
async getEntries() {
|
|
292
|
+
const native = await getPiSessionNativeDb(this.#cwd);
|
|
293
|
+
return readPiSessionEntries(native, this.#sessionId).map(decodeEntry);
|
|
294
|
+
}
|
|
295
|
+
/** The set of entry ids already in use for this session (collision avoidance). */
|
|
296
|
+
#entryIdSet(native) {
|
|
297
|
+
return new Set(readPiSessionEntries(native, this.#sessionId).map((r) => r.entryId));
|
|
298
|
+
}
|
|
299
|
+
/**
|
|
300
|
+
* Run `fn` against the native handle while holding the PROJECT/`bulk` writer
|
|
301
|
+
* lease — the ONLY durable-write path. The daemon stays the sole arbitrated
|
|
302
|
+
* writer; the adapter never opens a raw writer (Gate 3).
|
|
303
|
+
*
|
|
304
|
+
* @param fn - The synchronous write body to run under the lease.
|
|
305
|
+
*/
|
|
306
|
+
async #leasedWrite(fn) {
|
|
307
|
+
const native = await getPiSessionNativeDb(this.#cwd);
|
|
308
|
+
await withWriterLease('project', 'bulk', async () => {
|
|
309
|
+
fn(native);
|
|
310
|
+
});
|
|
311
|
+
log().debug({ sessionId: this.#sessionId }, 'pi session leased write committed');
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
//# sourceMappingURL=pi-session-storage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pi-session-storage.js","sourceRoot":"","sources":["../../../src/llm/pi/pi-session-storage.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cleo-owned Pi `StreamFn` — the Gate-13-respecting LLM route (T11761 · S2 · T11898).
|
|
3
|
+
*
|
|
4
|
+
* Pi's agent loop performs every LLM call through a single pluggable seam: the
|
|
5
|
+
* `streamFn` passed as the 6th positional arg to `runAgentLoop`. The DEFAULT
|
|
6
|
+
* streamFn (`pi-ai`'s `streamSimple`) resolves a provider from `pi-ai`'s own
|
|
7
|
+
* registry and falls back to reading `process.env[<PROVIDER>_API_KEY]` when no
|
|
8
|
+
* explicit key is supplied — a credential-resolution path OUTSIDE Cleo's E9
|
|
9
|
+
* chokepoint, and a Gate-13 violation.
|
|
10
|
+
*
|
|
11
|
+
* {@link createPiStreamFn} supplies a Cleo-owned replacement that routes the
|
|
12
|
+
* loop's LLM calls through {@link resolveLLMForSystem} (the E9 resolution
|
|
13
|
+
* chokepoint) → {@link ModelRunner.build} (the single SSoT transport factory).
|
|
14
|
+
* Passing this streamFn to `runAgentLoop` means `pi-ai`'s `stream.ts` /
|
|
15
|
+
* `withEnvApiKey` is NEVER reached for the loop — the registry env-fallback
|
|
16
|
+
* cannot fire (foundation §5.1, the single most important suppression lever).
|
|
17
|
+
*
|
|
18
|
+
* ## Detached-producer teardown (T11898)
|
|
19
|
+
*
|
|
20
|
+
* The returned `StreamFn` MUST return its stream synchronously, so the async
|
|
21
|
+
* producer is detached (`void produce(...)`). To stop that producer outliving
|
|
22
|
+
* the call that started it, `ctx.signal` (the `wrapPiCall`-managed loop abort
|
|
23
|
+
* signal) is threaded into the per-call `SendOptions.signal` AND the producer's
|
|
24
|
+
* consumption loop bails on `signal.aborted` and explicitly returns the
|
|
25
|
+
* iterator. Teardown therefore holds even against a transport that ignores the
|
|
26
|
+
* signal option — closing the residual exit-escape window the daemon exit-guard
|
|
27
|
+
* (`installDaemonExitGuard`) backstops.
|
|
28
|
+
*
|
|
29
|
+
* ## Gate-13 cleanliness (verified)
|
|
30
|
+
*
|
|
31
|
+
* This file CALLS `resolveLLMForSystem` + `ModelRunner.build` only. It constructs
|
|
32
|
+
* NO transport (`new *Transport`), NO SDK client (`createAnthropic` /
|
|
33
|
+
* `new Anthropic`), reads NO `*_API_KEY` env var, and carries NO hardcoded model
|
|
34
|
+
* literal — all of that stays inside `model-runner.ts` / `transports/**` (the
|
|
35
|
+
* Gate-13 allowlist). The descriptor's `model` comes from the resolver
|
|
36
|
+
* (registry / role-config), never a literal here.
|
|
37
|
+
*
|
|
38
|
+
* ## Tool wire-through (T1739 — registry consumability)
|
|
39
|
+
*
|
|
40
|
+
* The Pi loop carries its tools (the agent registry's `toOpenAITools()` output) on
|
|
41
|
+
* `Context.tools`. {@link toTransportTools} projects them onto the per-call
|
|
42
|
+
* `SendOptions.tools`, which `ConcreteSession._buildRequest` forwards onto
|
|
43
|
+
* `TransportRequest.tools` — so the wire-level transport advertises them to the
|
|
44
|
+
* model. This closes the streamFn → transport tool link: registry tools given to
|
|
45
|
+
* the loop are reachable by the model. (Tool-CALL *execution* — binding Pi's
|
|
46
|
+
* `ExecutionEnv` onto the guarded surface — is a later subtask; only the schema
|
|
47
|
+
* advertisement flows here.)
|
|
48
|
+
*
|
|
49
|
+
* ## Zod ↔ TypeBox quarantine (Gate 10)
|
|
50
|
+
*
|
|
51
|
+
* Pi tool schemas are TypeBox, but `pi-ai`'s `validateToolArguments` also accepts
|
|
52
|
+
* plain JSON-schema tools. Cleo tool definitions are Zod (live in `core/src/llm/`).
|
|
53
|
+
* {@link zodToolToTransportTool} converts a Zod schema → JSON Schema via Zod v4's
|
|
54
|
+
* native `z.toJSONSchema` (NO `zod-to-json-schema` dep, NO typebox value-import),
|
|
55
|
+
* so the cleo↔Pi tool boundary carries ZERO typebox. {@link toTransportTools}
|
|
56
|
+
* passes the loop's Pi `Tool.parameters` (a TypeBox `TSchema` that is structurally
|
|
57
|
+
* a JSON Schema object) through verbatim — also WITHOUT a typebox value-import.
|
|
58
|
+
* typebox remains a transitive dep used only INSIDE `pi-agent-core`; it never
|
|
59
|
+
* appears in cleo source and never reaches `packages/contracts/`.
|
|
60
|
+
*
|
|
61
|
+
* @epic T10403
|
|
62
|
+
* @task T11761
|
|
63
|
+
* @task T11898
|
|
64
|
+
* @task T1739
|
|
65
|
+
*/
|
|
66
|
+
import type { TransportTool } from '@cleocode/contracts/llm/normalized-response.js';
|
|
67
|
+
import type { StreamFn } from '@earendil-works/pi-agent-core';
|
|
68
|
+
import type { z } from 'zod';
|
|
69
|
+
import type { PiAgentRunContext } from './pi-types.js';
|
|
70
|
+
/**
|
|
71
|
+
* A Cleo tool definition in the form the Pi streamFn bridges to Pi's loop.
|
|
72
|
+
*
|
|
73
|
+
* Cleo tools carry a Zod parameter schema; {@link createPiStreamFn} converts it
|
|
74
|
+
* to a JSON-schema {@link TransportTool} so NO typebox value-import is needed at
|
|
75
|
+
* the boundary (Gate 10). The bridge is intentionally one-directional: cleo →
|
|
76
|
+
* Pi as JSON-schema; Pi validates internally; cleo re-validates received args
|
|
77
|
+
* against the Zod schema at the guard boundary (defense in depth, S3+).
|
|
78
|
+
*/
|
|
79
|
+
export interface PiZodTool {
|
|
80
|
+
/** Tool name as Pi/the provider will see it. */
|
|
81
|
+
readonly name: string;
|
|
82
|
+
/** Human-readable description for the model. */
|
|
83
|
+
readonly description: string;
|
|
84
|
+
/** Zod schema for the tool's input parameters. */
|
|
85
|
+
readonly parameters: z.ZodType;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Convert a Cleo Zod-schema tool into a JSON-schema {@link TransportTool}.
|
|
89
|
+
*
|
|
90
|
+
* Thin wrapper over the SINGLE shared generator
|
|
91
|
+
* {@link zodSchemaToOpenAITool} (`core/src/tools/schema-gen.ts`) so the Pi bridge
|
|
92
|
+
* and the agent registry (T1739 · AC3) share ONE conversion doctrine and cannot
|
|
93
|
+
* drift (DRY). Uses Zod v4's native `z.toJSONSchema` — no `zod-to-json-schema`
|
|
94
|
+
* dependency and, crucially, NO typebox value-import. The resulting `inputSchema`
|
|
95
|
+
* is a plain JSON Schema object the transport passes through verbatim.
|
|
96
|
+
*
|
|
97
|
+
* @param tool - The Cleo Zod tool.
|
|
98
|
+
* @returns The transport-shaped JSON-schema tool.
|
|
99
|
+
*/
|
|
100
|
+
export declare function zodToolToTransportTool(tool: PiZodTool): TransportTool;
|
|
101
|
+
/**
|
|
102
|
+
* Build a Cleo-owned {@link StreamFn} for one Pi agent run.
|
|
103
|
+
*
|
|
104
|
+
* The returned function matches Pi's `StreamFn` contract structurally:
|
|
105
|
+
* `(model, context, options?) => AssistantMessageEventStream`. It MUST NOT throw
|
|
106
|
+
* — every failure is encoded as a terminal `error` event on the returned stream
|
|
107
|
+
* (Pi's never-throw streaming contract).
|
|
108
|
+
*
|
|
109
|
+
* Flow per call:
|
|
110
|
+
* 1. `resolveLLMForSystem(ctx.system)` — the E9 resolution chokepoint.
|
|
111
|
+
* 2. Build a clean {@link ResolvedLLMDescriptor} from the resolved fields.
|
|
112
|
+
* 3. `ModelRunner.build(descriptor)` — the single SSoT transport factory.
|
|
113
|
+
* 4. Stream `NormalizedDelta` chunks from the built transport session and
|
|
114
|
+
* project them onto Pi's `AssistantMessageEvent` protocol, terminating with
|
|
115
|
+
* a `done` (success) or `error` (failure) event.
|
|
116
|
+
*
|
|
117
|
+
* `pi-ai`'s `stream.ts` / `withEnvApiKey` is never reached — the registry
|
|
118
|
+
* env-fallback cannot fire for the loop.
|
|
119
|
+
*
|
|
120
|
+
* @param ctx - The Pi run context (system-of-use label + identity + signal).
|
|
121
|
+
* @returns A Cleo-owned `StreamFn`.
|
|
122
|
+
*/
|
|
123
|
+
export declare function createPiStreamFn(ctx: PiAgentRunContext): StreamFn;
|
|
124
|
+
//# sourceMappingURL=pi-stream-fn.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pi-stream-fn.d.ts","sourceRoot":"","sources":["../../../src/llm/pi/pi-stream-fn.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgEG;AAIH,OAAO,KAAK,EAEV,aAAa,EACd,MAAM,gDAAgD,CAAC;AACxD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,+BAA+B,CAAC;AA0B9D,OAAO,KAAK,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAM7B,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAEvD;;;;;;;;GAQG;AACH,MAAM,WAAW,SAAS;IACxB,gDAAgD;IAChD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,gDAAgD;IAChD,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,kDAAkD;IAClD,QAAQ,CAAC,UAAU,EAAE,CAAC,CAAC,OAAO,CAAC;CAChC;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,SAAS,GAAG,aAAa,CAErE;AAID;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,iBAAiB,GAAG,QAAQ,CAYjE"}
|