@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,133 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sealed credential handle — runtime implementation (E10 · T11753).
|
|
3
|
+
*
|
|
4
|
+
* The {@link SealedCredential} **type** lives in `@cleocode/contracts`
|
|
5
|
+
* (`llm/sealed-credential.ts`, types-only for Gate 10 purity). Its `fetch()` is
|
|
6
|
+
* a function-TYPED interface field; the concrete body — the on-demand
|
|
7
|
+
* materialization of the plaintext token — lives HERE in `@cleocode/core`.
|
|
8
|
+
*
|
|
9
|
+
* ## Why this module exists
|
|
10
|
+
*
|
|
11
|
+
* Before E10, {@link import('./role-resolver.js').resolveLLMForRole} returned
|
|
12
|
+
* the resolved credential's plaintext `apiKey` **inline** on its envelope. That
|
|
13
|
+
* bare secret string travelled up the entire resolution call stack
|
|
14
|
+
* (`resolveLLMForRole` → `resolveLLMForSystem` → consumers) where any layer that
|
|
15
|
+
* merely *routed* it to the wire could accidentally log it, serialize it into a
|
|
16
|
+
* LAFS envelope, or copy it into a diagnostic.
|
|
17
|
+
*
|
|
18
|
+
* {@link makeSealedCredential} inverts that. The resolver builds an opaque
|
|
19
|
+
* {@link SealedCredential} handle whose `fetch()` closure captures a
|
|
20
|
+
* `resolveToken` thunk. The plaintext is materialized **only** when a wire
|
|
21
|
+
* boundary (`transportForProvider` / `session-factory.ts`) or daemon
|
|
22
|
+
* worker-injection invokes `fetch()`. Between the resolver and those boundaries,
|
|
23
|
+
* NO layer holds a plaintext secret — it holds a handle.
|
|
24
|
+
*
|
|
25
|
+
* ## The brand chokepoint
|
|
26
|
+
*
|
|
27
|
+
* {@link brandDecryptedToken} is the SOLE place a {@link DecryptedToken} is
|
|
28
|
+
* minted from a raw string. Because `DecryptedToken` is a phantom-branded type
|
|
29
|
+
* (contracts), a plain `string` cannot be widened into one anywhere else — so an
|
|
30
|
+
* audit of "who mints a token" reduces to "who calls `brandDecryptedToken`",
|
|
31
|
+
* and that is exclusively this module (invoked inside `fetch()`).
|
|
32
|
+
*
|
|
33
|
+
* @module llm/sealed-credential
|
|
34
|
+
* @task T11753
|
|
35
|
+
* @epic T11746
|
|
36
|
+
* @see ADR-072 §Type lock-in
|
|
37
|
+
*/
|
|
38
|
+
/**
|
|
39
|
+
* Build the non-secret, redacted preview of a credential string.
|
|
40
|
+
*
|
|
41
|
+
* SECURITY: this is the SOLE token→preview redaction chokepoint for the sealed
|
|
42
|
+
* handle. It reveals at most the last 4 characters of the token plus an
|
|
43
|
+
* auth-scheme marker (`oat-…` for OAuth, `…` otherwise) — never enough to
|
|
44
|
+
* reconstruct the secret. It is computed ONCE at seal time and stored on the
|
|
45
|
+
* handle's {@link SealedCredential.tokenPreview}; the full plaintext is NOT
|
|
46
|
+
* retained for it.
|
|
47
|
+
*
|
|
48
|
+
* The preview is the ONLY credential-derived string that may cross a
|
|
49
|
+
* logging/diagnostic/envelope boundary (E10 · T11754 · AC3); everything else
|
|
50
|
+
* goes through {@link SealedCredential.fetch} at the wire and is discarded.
|
|
51
|
+
*
|
|
52
|
+
* @param token - The plaintext secret (read transiently; not retained).
|
|
53
|
+
* @param authType - Auth scheme, used only to pick the cosmetic prefix.
|
|
54
|
+
* @returns A redacted preview safe to log and serialize.
|
|
55
|
+
* @task T11754
|
|
56
|
+
*/
|
|
57
|
+
export function tokenPreview(token, authType) {
|
|
58
|
+
const prefix = authType === 'oauth' ? 'oat-…' : '…';
|
|
59
|
+
if (!token)
|
|
60
|
+
return prefix;
|
|
61
|
+
if (token.length <= 4)
|
|
62
|
+
return `${prefix}${token}`;
|
|
63
|
+
return `${prefix}${token.slice(-4)}`;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Mint a {@link DecryptedToken} from a raw plaintext secret.
|
|
67
|
+
*
|
|
68
|
+
* SECURITY: this is the ONE chokepoint that produces a branded
|
|
69
|
+
* {@link DecryptedToken}. It MUST be called only from inside a
|
|
70
|
+
* {@link SealedCredential.fetch} closure (see {@link makeSealedCredential}) —
|
|
71
|
+
* i.e. at the wire / daemon worker-injection boundary — never to surface a
|
|
72
|
+
* plaintext up the resolver stack.
|
|
73
|
+
*
|
|
74
|
+
* The brand is phantom (compile-time only); at runtime this returns a frozen
|
|
75
|
+
* object `{ value }`. The `__decryptedToken` marker is never materialized at
|
|
76
|
+
* runtime — the cast below is the deliberate, single, audited point where a
|
|
77
|
+
* `string` becomes a `DecryptedToken`.
|
|
78
|
+
*
|
|
79
|
+
* @param value - The materialized plaintext secret (API key / OAuth bearer).
|
|
80
|
+
* @returns The branded token, valid only for immediate wire/daemon use.
|
|
81
|
+
* @internal
|
|
82
|
+
*/
|
|
83
|
+
function brandDecryptedToken(value) {
|
|
84
|
+
// The single, audited string→DecryptedToken mint. `Object.freeze` prevents a
|
|
85
|
+
// consumer from mutating `value` in place after fetch().
|
|
86
|
+
return Object.freeze({ value });
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Build a {@link SealedCredential} handle from a provider/account and an
|
|
90
|
+
* on-demand token resolver.
|
|
91
|
+
*
|
|
92
|
+
* The returned handle carries ONLY the non-secret `provider` + `account`
|
|
93
|
+
* inline. Its `fetch()` closure captures {@link MakeSealedCredentialParams.resolveToken}
|
|
94
|
+
* and brands the result — the plaintext exists transiently inside `fetch()` and
|
|
95
|
+
* is NEVER attached to the handle object, so the handle can be logged or
|
|
96
|
+
* serialized without leaking the secret.
|
|
97
|
+
*
|
|
98
|
+
* @example
|
|
99
|
+
* ```ts
|
|
100
|
+
* // In the resolver — capture the already-resolved token in the closure but do
|
|
101
|
+
* // NOT place it on the returned envelope:
|
|
102
|
+
* const sealed = makeSealedCredential({
|
|
103
|
+
* provider: 'anthropic',
|
|
104
|
+
* account: usedLabel ?? 'default',
|
|
105
|
+
* tokenPreview: tokenPreview(token, authType), // non-secret; safe to log
|
|
106
|
+
* resolveToken: () => token, // captured, not surfaced
|
|
107
|
+
* });
|
|
108
|
+
* // At the wire — the ONLY place fetch() runs (via authHeadersFromSealed):
|
|
109
|
+
* const headers = await authHeadersFromSealed(sealed, authType);
|
|
110
|
+
* // the plaintext never escapes authHeadersFromSealed; only headers come out.
|
|
111
|
+
* ```
|
|
112
|
+
*
|
|
113
|
+
* @param params - Provider, account label, and the on-demand token resolver.
|
|
114
|
+
* @returns An opaque sealed-credential handle.
|
|
115
|
+
* @task T11753
|
|
116
|
+
*/
|
|
117
|
+
export function makeSealedCredential(params) {
|
|
118
|
+
const { provider, account, tokenPreview: preview, resolveToken } = params;
|
|
119
|
+
return {
|
|
120
|
+
provider,
|
|
121
|
+
account,
|
|
122
|
+
tokenPreview: preview,
|
|
123
|
+
fetch: async () => {
|
|
124
|
+
// The SOLE decrypt/materialize point. `resolveToken` re-obtains (or, in
|
|
125
|
+
// T11754, decrypts) the plaintext on demand; we brand it and hand it to
|
|
126
|
+
// the wire. The plaintext never escapes this closure except as the
|
|
127
|
+
// branded return value the caller is contractually bound to discard.
|
|
128
|
+
const plaintext = await resolveToken();
|
|
129
|
+
return brandDecryptedToken(plaintext);
|
|
130
|
+
},
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
//# sourceMappingURL=sealed-credential.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sealed-credential.js","sourceRoot":"","sources":["../../src/llm/sealed-credential.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AAIH;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,UAAU,YAAY,CAAC,KAAa,EAAE,QAA6B;IACvE,MAAM,MAAM,GAAG,QAAQ,KAAK,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC;IACpD,IAAI,CAAC,KAAK;QAAE,OAAO,MAAM,CAAC;IAC1B,IAAI,KAAK,CAAC,MAAM,IAAI,CAAC;QAAE,OAAO,GAAG,MAAM,GAAG,KAAK,EAAE,CAAC;IAClD,OAAO,GAAG,MAAM,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;AACvC,CAAC;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,SAAS,mBAAmB,CAAC,KAAa;IACxC,6EAA6E;IAC7E,yDAAyD;IACzD,OAAO,MAAM,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,CAAmB,CAAC;AACpD,CAAC;AAuCD;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,MAAM,UAAU,oBAAoB,CAAC,MAAkC;IACrE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,YAAY,EAAE,OAAO,EAAE,YAAY,EAAE,GAAG,MAAM,CAAC;IAC1E,OAAO;QACL,QAAQ;QACR,OAAO;QACP,YAAY,EAAE,OAAO;QACrB,KAAK,EAAE,KAAK,IAA6B,EAAE;YACzC,wEAAwE;YACxE,wEAAwE;YACxE,mEAAmE;YACnE,qEAAqE;YACrE,MAAM,SAAS,GAAG,MAAM,YAAY,EAAE,CAAC;YACvC,OAAO,mBAAmB,CAAC,SAAS,CAAC,CAAC;QACxC,CAAC;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session-factory.d.ts","sourceRoot":"","sources":["../../src/llm/session-factory.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EACV,UAAU,EACV,iBAAiB,EACjB,WAAW,EACX,qBAAqB,EACtB,MAAM,uCAAuC,CAAC;AAC/C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gDAAgD,CAAC;AACnF,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,wCAAwC,CAAC;AACtE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,gDAAgD,CAAC;AAIzF,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAMxD;;;;;;;;;;;;;;;;;GAiBG;AACH,iBAAS,oBAAoB,CAC3B,QAAQ,EAAE,cAAc,EACxB,UAAU,EAAE,kBAAkB,EAC9B,OAAO,CAAC,EAAE,OAAO,GAChB,YAAY,CAEd;AAuCD;;;;;;;;;;;;;GAaG;AACH,qBAAa,wBAAyB,YAAW,iBAAiB;IAChE,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAA0B;IAE9D;;;OAGG;gBACS,IAAI,CAAC,EAAE;QAAE,WAAW,CAAC,EAAE,WAAW,CAAA;KAAE;IAIhD;;;;;;;;;OASG;IACG,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC;IAItD;;;;;;;;;;OAUG;IACG,MAAM,CAAC,IAAI,EAAE,qBAAqB,GAAG,OAAO,CAAC,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"session-factory.d.ts","sourceRoot":"","sources":["../../src/llm/session-factory.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EACV,UAAU,EACV,iBAAiB,EACjB,WAAW,EACX,qBAAqB,EACtB,MAAM,uCAAuC,CAAC;AAC/C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gDAAgD,CAAC;AACnF,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,wCAAwC,CAAC;AACtE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,gDAAgD,CAAC;AAIzF,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAMxD;;;;;;;;;;;;;;;;;GAiBG;AACH,iBAAS,oBAAoB,CAC3B,QAAQ,EAAE,cAAc,EACxB,UAAU,EAAE,kBAAkB,EAC9B,OAAO,CAAC,EAAE,OAAO,GAChB,YAAY,CAEd;AAuCD;;;;;;;;;;;;;GAaG;AACH,qBAAa,wBAAyB,YAAW,iBAAiB;IAChE,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAA0B;IAE9D;;;OAGG;gBACS,IAAI,CAAC,EAAE;QAAE,WAAW,CAAC,EAAE,WAAW,CAAA;KAAE;IAIhD;;;;;;;;;OASG;IACG,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC;IAItD;;;;;;;;;;OAUG;IACG,MAAM,CAAC,IAAI,EAAE,qBAAqB,GAAG,OAAO,CAAC,UAAU,CAAC;CA8C/D;AAMD;;;;;;GAMG;AACH,OAAO,EAAE,oBAAoB,IAAI,+BAA+B,EAAE,CAAC"}
|
|
@@ -118,12 +118,16 @@ export class DefaultLlmSessionFactory {
|
|
|
118
118
|
}
|
|
119
119
|
if (opts.role) {
|
|
120
120
|
const resolved = await resolveLLMForRole(opts.role);
|
|
121
|
-
if (!resolved.credential
|
|
121
|
+
if (!resolved.sealedCredential || !resolved.credential) {
|
|
122
122
|
throw new Error(`No credential available for role '${opts.role}' / provider '${resolved.provider}'`);
|
|
123
123
|
}
|
|
124
|
+
// E10 (T11753): materialize the plaintext from the sealed handle ONLY here,
|
|
125
|
+
// at the wire — `transportForProvider` is one of the two sanctioned decrypt
|
|
126
|
+
// boundaries. The token is wired into the transport and never surfaced.
|
|
127
|
+
const token = (await resolved.sealedCredential.fetch()).value;
|
|
124
128
|
const resolvedCredential = credentialResultToResolved({
|
|
125
129
|
provider: resolved.provider,
|
|
126
|
-
apiKey:
|
|
130
|
+
apiKey: token,
|
|
127
131
|
authType: resolved.credential.authType,
|
|
128
132
|
label: resolved.credentialLabel,
|
|
129
133
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session-factory.js","sourceRoot":"","sources":["../../src/llm/session-factory.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAWH,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAGvD,8EAA8E;AAC9E,oBAAoB;AACpB,8EAA8E;AAE9E;;;;;;;;;;;;;;;;;GAiBG;AACH,SAAS,oBAAoB,CAC3B,QAAwB,EACxB,UAA8B,EAC9B,OAAiB;IAEjB,OAAO,WAAW,CAAC,4BAA4B,CAAC,QAAQ,EAAE,UAAU,EAAE,OAAO,CAAC,CAAC;AACjF,CAAC;AAED,8EAA8E;AAC9E,6BAA6B;AAC7B,8EAA8E;AAE9E;;;;;;;;;GASG;AACH,SAAS,0BAA0B,CAAC,MAKnC;IACC,OAAO;QACL,QAAQ,EAAE,MAAM,CAAC,QAAQ;QACzB,KAAK,EAAE,MAAM,CAAC,KAAK,IAAI,SAAS;QAChC,KAAK,EAAE,MAAM,CAAC,MAAM;QACpB,QAAQ,EAAE,MAAM,CAAC,QAAQ;QACzB,SAAS,EAAE,IAAI;QACf,YAAY,EAAE,IAAI;QAClB,YAAY,EAAE,EAAE;QAChB,OAAO,EAAE,IAAI;QACb,UAAU,EAAE,IAAI;KACjB,CAAC;AACJ,CAAC;AAED,8EAA8E;AAC9E,2BAA2B;AAC3B,8EAA8E;AAE9E;;;;;;;;;;;;;GAaG;AACH,MAAM,OAAO,wBAAwB;IAClB,mBAAmB,CAA0B;IAE9D;;;OAGG;IACH,YAAY,IAAoC;QAC9C,IAAI,CAAC,mBAAmB,GAAG,IAAI,EAAE,WAAW,CAAC;IAC/C,CAAC;IAED;;;;;;;;;OASG;IACH,KAAK,CAAC,aAAa,CAAC,IAAY;QAC9B,OAAO,IAAI,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC;IAC/B,CAAC;IAED;;;;;;;;;;OAUG;IACH,KAAK,CAAC,MAAM,CAAC,IAA2B;QACtC,IAAI,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,CAAC,IAAI,CAAC,UAAU,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;YACpD,MAAM,IAAI,KAAK,CACb,kFAAkF,CACnF,CAAC;QACJ,CAAC;QAED,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;YACd,MAAM,QAAQ,GAAG,MAAM,iBAAiB,CACtC,IAAI,CAAC,IAA+C,CACrD,CAAC;YAEF,IAAI,CAAC,QAAQ,CAAC,
|
|
1
|
+
{"version":3,"file":"session-factory.js","sourceRoot":"","sources":["../../src/llm/session-factory.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAWH,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAGvD,8EAA8E;AAC9E,oBAAoB;AACpB,8EAA8E;AAE9E;;;;;;;;;;;;;;;;;GAiBG;AACH,SAAS,oBAAoB,CAC3B,QAAwB,EACxB,UAA8B,EAC9B,OAAiB;IAEjB,OAAO,WAAW,CAAC,4BAA4B,CAAC,QAAQ,EAAE,UAAU,EAAE,OAAO,CAAC,CAAC;AACjF,CAAC;AAED,8EAA8E;AAC9E,6BAA6B;AAC7B,8EAA8E;AAE9E;;;;;;;;;GASG;AACH,SAAS,0BAA0B,CAAC,MAKnC;IACC,OAAO;QACL,QAAQ,EAAE,MAAM,CAAC,QAAQ;QACzB,KAAK,EAAE,MAAM,CAAC,KAAK,IAAI,SAAS;QAChC,KAAK,EAAE,MAAM,CAAC,MAAM;QACpB,QAAQ,EAAE,MAAM,CAAC,QAAQ;QACzB,SAAS,EAAE,IAAI;QACf,YAAY,EAAE,IAAI;QAClB,YAAY,EAAE,EAAE;QAChB,OAAO,EAAE,IAAI;QACb,UAAU,EAAE,IAAI;KACjB,CAAC;AACJ,CAAC;AAED,8EAA8E;AAC9E,2BAA2B;AAC3B,8EAA8E;AAE9E;;;;;;;;;;;;;GAaG;AACH,MAAM,OAAO,wBAAwB;IAClB,mBAAmB,CAA0B;IAE9D;;;OAGG;IACH,YAAY,IAAoC;QAC9C,IAAI,CAAC,mBAAmB,GAAG,IAAI,EAAE,WAAW,CAAC;IAC/C,CAAC;IAED;;;;;;;;;OASG;IACH,KAAK,CAAC,aAAa,CAAC,IAAY;QAC9B,OAAO,IAAI,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC;IAC/B,CAAC;IAED;;;;;;;;;;OAUG;IACH,KAAK,CAAC,MAAM,CAAC,IAA2B;QACtC,IAAI,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,CAAC,IAAI,CAAC,UAAU,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;YACpD,MAAM,IAAI,KAAK,CACb,kFAAkF,CACnF,CAAC;QACJ,CAAC;QAED,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;YACd,MAAM,QAAQ,GAAG,MAAM,iBAAiB,CACtC,IAAI,CAAC,IAA+C,CACrD,CAAC;YAEF,IAAI,CAAC,QAAQ,CAAC,gBAAgB,IAAI,CAAC,QAAQ,CAAC,UAAU,EAAE,CAAC;gBACvD,MAAM,IAAI,KAAK,CACb,qCAAqC,IAAI,CAAC,IAAI,iBAAiB,QAAQ,CAAC,QAAQ,GAAG,CACpF,CAAC;YACJ,CAAC;YAED,4EAA4E;YAC5E,4EAA4E;YAC5E,wEAAwE;YACxE,MAAM,KAAK,GAAG,CAAC,MAAM,QAAQ,CAAC,gBAAgB,CAAC,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC;YAC9D,MAAM,kBAAkB,GAAG,0BAA0B,CAAC;gBACpD,QAAQ,EAAE,QAAQ,CAAC,QAAQ;gBAC3B,MAAM,EAAE,KAAK;gBACb,QAAQ,EAAE,QAAQ,CAAC,UAAU,CAAC,QAAQ;gBACtC,KAAK,EAAE,QAAQ,CAAC,eAAe;aAChC,CAAC,CAAC;YAEH,MAAM,SAAS,GAAG,oBAAoB,CAAC,QAAQ,CAAC,QAAQ,EAAE,kBAAkB,CAAC,CAAC;YAE9E,OAAO,IAAI,eAAe,CAAC;gBACzB,SAAS;gBACT,KAAK,EAAE,QAAQ,CAAC,KAAK;gBACrB,UAAU,EAAE,kBAAkB;gBAC9B,WAAW,EAAE,IAAI,CAAC,WAAW,IAAI,IAAI,CAAC,mBAAmB;aAC1D,CAAC,CAAC;QACL,CAAC;QAED,iFAAiF;QACjF,mEAAmE;QACnE,MAAM,IAAI,KAAK,CACb,yFAAyF;YACvF,mFAAmF,CACtF,CAAC;IACJ,CAAC;CACF;AAED,8EAA8E;AAC9E,iCAAiC;AACjC,8EAA8E;AAE9E;;;;;;GAMG;AACH,OAAO,EAAE,oBAAoB,IAAI,+BAA+B,EAAE,CAAC"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Runtime encode/decode for {@link SystemOfUse} string keys (E9 · T11751).
|
|
3
|
+
*
|
|
4
|
+
* The structured `{ kind, id }` {@link SystemOfUse} descriptor must cross
|
|
5
|
+
* string-only boundaries (config keys under `llm.systems[...]`, CLI args, audit
|
|
6
|
+
* logs, the runtime registry in `system-of-use-registry.ts`). This module is the
|
|
7
|
+
* single canonical codec between the descriptor and its flat string form.
|
|
8
|
+
*
|
|
9
|
+
* Encoding rules (driven entirely by the {@link OPEN_SYSTEM_KEY_PREFIXES} DATA
|
|
10
|
+
* declared in `@cleocode/contracts`, so the prefix set never drifts):
|
|
11
|
+
*
|
|
12
|
+
* - OPEN axes (`tool` / `skill` / `cantbook-node` / `spawn-unit`) →
|
|
13
|
+
* `<prefix><id>` (e.g. `{ kind: 'tool', id: 'web-search' }` ↔ `'tool:web-search'`).
|
|
14
|
+
* - CLOSED axes (`role` / `orchestration` / `aux`) → the bare `id`
|
|
15
|
+
* (e.g. `{ kind: 'aux', id: 'sentient' }` ↔ `'sentient'`). The flat label
|
|
16
|
+
* vocabulary the resolver already accepts (`SystemOfUseLabel`) IS the closed
|
|
17
|
+
* `aux`/`role` id, so closed keys round-trip without a prefix.
|
|
18
|
+
*
|
|
19
|
+
* Contracts-purity (Gate 10): this runtime codec lives in `@cleocode/core`, NOT
|
|
20
|
+
* in the type-only contracts package — it only READS the
|
|
21
|
+
* {@link OPEN_SYSTEM_KEY_PREFIXES} data map.
|
|
22
|
+
*
|
|
23
|
+
* @module llm/system-key
|
|
24
|
+
* @task T11751
|
|
25
|
+
* @epic T11745
|
|
26
|
+
*/
|
|
27
|
+
import { type SystemOfUse, type SystemOfUseKind } from '@cleocode/contracts';
|
|
28
|
+
/**
|
|
29
|
+
* Encode a structured {@link SystemOfUse} descriptor into its canonical string
|
|
30
|
+
* key (the form stored in `llm.systems[...]` and the runtime registry).
|
|
31
|
+
*
|
|
32
|
+
* Open-axis descriptors gain their {@link OPEN_SYSTEM_KEY_PREFIXES} prefix;
|
|
33
|
+
* closed-axis descriptors (`role` / `orchestration` / `aux`) encode to the bare
|
|
34
|
+
* `id` so they round-trip with the flat resolver label vocabulary.
|
|
35
|
+
*
|
|
36
|
+
* @param system - The descriptor to encode.
|
|
37
|
+
* @returns The canonical string key.
|
|
38
|
+
* @task T11751
|
|
39
|
+
*/
|
|
40
|
+
export declare function formatSystemKey(system: SystemOfUse): string;
|
|
41
|
+
/**
|
|
42
|
+
* Decode an open-axis string key back into its {@link SystemOfUse} descriptor.
|
|
43
|
+
*
|
|
44
|
+
* Returns `undefined` for a bare key with NO recognised open prefix — such keys
|
|
45
|
+
* are closed-axis ids (`role` / `orchestration` / `aux`) whose `kind` cannot be
|
|
46
|
+
* inferred from the string alone (the same `'sentient'` is an `aux` id and a
|
|
47
|
+
* resolver label). Callers that need the closed-axis descriptor must consult the
|
|
48
|
+
* value SSoTs (`AUX_SYSTEM_IDS` / `ROLE_SYSTEM_IDS` / `ORCHESTRATION_TIER_IDS`).
|
|
49
|
+
*
|
|
50
|
+
* @param key - The string key to decode.
|
|
51
|
+
* @returns The open-axis descriptor, or `undefined` for an un-prefixed key.
|
|
52
|
+
* @task T11751
|
|
53
|
+
*/
|
|
54
|
+
export declare function parseSystemKey(key: string): SystemOfUse | undefined;
|
|
55
|
+
/**
|
|
56
|
+
* The {@link SystemOfUseKind} a string key encodes, inferred from its prefix.
|
|
57
|
+
*
|
|
58
|
+
* Open-prefixed keys return their open kind; un-prefixed keys are reported as
|
|
59
|
+
* `'aux'` (the closed lane the flat resolver labels live in). Pure inspection —
|
|
60
|
+
* does not assert the id is registered.
|
|
61
|
+
*
|
|
62
|
+
* @param key - The string key to inspect.
|
|
63
|
+
* @returns The inferred kind.
|
|
64
|
+
* @task T11751
|
|
65
|
+
*/
|
|
66
|
+
export declare function systemKeyKind(key: string): SystemOfUseKind;
|
|
67
|
+
//# sourceMappingURL=system-key.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"system-key.d.ts","sourceRoot":"","sources":["../../src/llm/system-key.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,OAAO,EAIL,KAAK,WAAW,EAChB,KAAK,eAAe,EACrB,MAAM,qBAAqB,CAAC;AAE7B;;;;;;;;;;;GAWG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,WAAW,GAAG,MAAM,CAM3D;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,WAAW,GAAG,SAAS,CAUnE;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,eAAe,CAG1D"}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Runtime encode/decode for {@link SystemOfUse} string keys (E9 · T11751).
|
|
3
|
+
*
|
|
4
|
+
* The structured `{ kind, id }` {@link SystemOfUse} descriptor must cross
|
|
5
|
+
* string-only boundaries (config keys under `llm.systems[...]`, CLI args, audit
|
|
6
|
+
* logs, the runtime registry in `system-of-use-registry.ts`). This module is the
|
|
7
|
+
* single canonical codec between the descriptor and its flat string form.
|
|
8
|
+
*
|
|
9
|
+
* Encoding rules (driven entirely by the {@link OPEN_SYSTEM_KEY_PREFIXES} DATA
|
|
10
|
+
* declared in `@cleocode/contracts`, so the prefix set never drifts):
|
|
11
|
+
*
|
|
12
|
+
* - OPEN axes (`tool` / `skill` / `cantbook-node` / `spawn-unit`) →
|
|
13
|
+
* `<prefix><id>` (e.g. `{ kind: 'tool', id: 'web-search' }` ↔ `'tool:web-search'`).
|
|
14
|
+
* - CLOSED axes (`role` / `orchestration` / `aux`) → the bare `id`
|
|
15
|
+
* (e.g. `{ kind: 'aux', id: 'sentient' }` ↔ `'sentient'`). The flat label
|
|
16
|
+
* vocabulary the resolver already accepts (`SystemOfUseLabel`) IS the closed
|
|
17
|
+
* `aux`/`role` id, so closed keys round-trip without a prefix.
|
|
18
|
+
*
|
|
19
|
+
* Contracts-purity (Gate 10): this runtime codec lives in `@cleocode/core`, NOT
|
|
20
|
+
* in the type-only contracts package — it only READS the
|
|
21
|
+
* {@link OPEN_SYSTEM_KEY_PREFIXES} data map.
|
|
22
|
+
*
|
|
23
|
+
* @module llm/system-key
|
|
24
|
+
* @task T11751
|
|
25
|
+
* @epic T11745
|
|
26
|
+
*/
|
|
27
|
+
import { isOpenSystemKind, OPEN_SYSTEM_KEY_PREFIXES, } from '@cleocode/contracts';
|
|
28
|
+
/**
|
|
29
|
+
* Encode a structured {@link SystemOfUse} descriptor into its canonical string
|
|
30
|
+
* key (the form stored in `llm.systems[...]` and the runtime registry).
|
|
31
|
+
*
|
|
32
|
+
* Open-axis descriptors gain their {@link OPEN_SYSTEM_KEY_PREFIXES} prefix;
|
|
33
|
+
* closed-axis descriptors (`role` / `orchestration` / `aux`) encode to the bare
|
|
34
|
+
* `id` so they round-trip with the flat resolver label vocabulary.
|
|
35
|
+
*
|
|
36
|
+
* @param system - The descriptor to encode.
|
|
37
|
+
* @returns The canonical string key.
|
|
38
|
+
* @task T11751
|
|
39
|
+
*/
|
|
40
|
+
export function formatSystemKey(system) {
|
|
41
|
+
if (isOpenSystemKind(system.kind)) {
|
|
42
|
+
return `${OPEN_SYSTEM_KEY_PREFIXES[system.kind]}${system.id}`;
|
|
43
|
+
}
|
|
44
|
+
// Closed axes (role / orchestration / aux) encode to the bare id.
|
|
45
|
+
return system.id;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Decode an open-axis string key back into its {@link SystemOfUse} descriptor.
|
|
49
|
+
*
|
|
50
|
+
* Returns `undefined` for a bare key with NO recognised open prefix — such keys
|
|
51
|
+
* are closed-axis ids (`role` / `orchestration` / `aux`) whose `kind` cannot be
|
|
52
|
+
* inferred from the string alone (the same `'sentient'` is an `aux` id and a
|
|
53
|
+
* resolver label). Callers that need the closed-axis descriptor must consult the
|
|
54
|
+
* value SSoTs (`AUX_SYSTEM_IDS` / `ROLE_SYSTEM_IDS` / `ORCHESTRATION_TIER_IDS`).
|
|
55
|
+
*
|
|
56
|
+
* @param key - The string key to decode.
|
|
57
|
+
* @returns The open-axis descriptor, or `undefined` for an un-prefixed key.
|
|
58
|
+
* @task T11751
|
|
59
|
+
*/
|
|
60
|
+
export function parseSystemKey(key) {
|
|
61
|
+
for (const kind of Object.keys(OPEN_SYSTEM_KEY_PREFIXES)) {
|
|
62
|
+
const prefix = OPEN_SYSTEM_KEY_PREFIXES[kind];
|
|
63
|
+
if (key.startsWith(prefix)) {
|
|
64
|
+
const id = key.slice(prefix.length);
|
|
65
|
+
if (!id)
|
|
66
|
+
return undefined;
|
|
67
|
+
return { kind, id };
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
return undefined;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* The {@link SystemOfUseKind} a string key encodes, inferred from its prefix.
|
|
74
|
+
*
|
|
75
|
+
* Open-prefixed keys return their open kind; un-prefixed keys are reported as
|
|
76
|
+
* `'aux'` (the closed lane the flat resolver labels live in). Pure inspection —
|
|
77
|
+
* does not assert the id is registered.
|
|
78
|
+
*
|
|
79
|
+
* @param key - The string key to inspect.
|
|
80
|
+
* @returns The inferred kind.
|
|
81
|
+
* @task T11751
|
|
82
|
+
*/
|
|
83
|
+
export function systemKeyKind(key) {
|
|
84
|
+
const parsed = parseSystemKey(key);
|
|
85
|
+
return parsed ? parsed.kind : 'aux';
|
|
86
|
+
}
|
|
87
|
+
//# sourceMappingURL=system-key.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"system-key.js","sourceRoot":"","sources":["../../src/llm/system-key.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,OAAO,EACL,gBAAgB,EAChB,wBAAwB,GAIzB,MAAM,qBAAqB,CAAC;AAE7B;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,eAAe,CAAC,MAAmB;IACjD,IAAI,gBAAgB,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC;QAClC,OAAO,GAAG,wBAAwB,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,EAAE,EAAE,CAAC;IAChE,CAAC;IACD,kEAAkE;IAClE,OAAO,MAAM,CAAC,EAAE,CAAC;AACnB,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,cAAc,CAAC,GAAW;IACxC,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,IAAI,CAAC,wBAAwB,CAAqB,EAAE,CAAC;QAC7E,MAAM,MAAM,GAAG,wBAAwB,CAAC,IAAI,CAAC,CAAC;QAC9C,IAAI,GAAG,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;YAC3B,MAAM,EAAE,GAAG,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;YACpC,IAAI,CAAC,EAAE;gBAAE,OAAO,SAAS,CAAC;YAC1B,OAAO,EAAE,IAAI,EAAE,EAAE,EAAiB,CAAC;QACrC,CAAC;IACH,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,aAAa,CAAC,GAAW;IACvC,MAAM,MAAM,GAAG,cAAc,CAAC,GAAG,CAAC,CAAC;IACnC,OAAO,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC;AACtC,CAAC"}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `registerSystemOfUse` — runtime extension point for the E9 system-of-use
|
|
3
|
+
* taxonomy (T11751 · AC1).
|
|
4
|
+
*
|
|
5
|
+
* ## Why a runtime registry
|
|
6
|
+
*
|
|
7
|
+
* {@link BUILTIN_SYSTEMS_OF_USE} is the static, closed-axis registry of the
|
|
8
|
+
* well-known systems (orchestration tiers + roles + aux subsystems). Plugins,
|
|
9
|
+
* extensions, and downstream packages need to declare NEW systems-of-use (e.g.
|
|
10
|
+
* a `tool:my-search` or a bespoke `aux`-like subsystem) and give each a default
|
|
11
|
+
* provider/model binding — WITHOUT editing the contracts SSoT.
|
|
12
|
+
*
|
|
13
|
+
* `registerSystemOfUse(key, displayName, defaults)` adds such a system to a
|
|
14
|
+
* process-level registry. The registered default binding is consulted by the
|
|
15
|
+
* single E9 resolution chokepoint (`resolveLLMForSystem` → `resolveLLMForRole`)
|
|
16
|
+
* **strictly BELOW user config** — after `llm.systems[key]`, `llm.default`, and
|
|
17
|
+
* `llm.defaultProfile` — so the user ALWAYS wins (AC1). A registered default
|
|
18
|
+
* only supplies a binding when the user has configured nothing for that key.
|
|
19
|
+
*
|
|
20
|
+
* ## Import-time purity
|
|
21
|
+
*
|
|
22
|
+
* This module performs NO registration at import time — the registry starts
|
|
23
|
+
* empty and is populated only by explicit `registerSystemOfUse(...)` calls. It
|
|
24
|
+
* holds no I/O, no config reads, and no side effects on load (so importing it
|
|
25
|
+
* is always safe). It is the runtime half intentionally split out of the
|
|
26
|
+
* type-only `@cleocode/contracts` (Gate 10).
|
|
27
|
+
*
|
|
28
|
+
* @module llm/system-of-use-registry
|
|
29
|
+
* @task T11751
|
|
30
|
+
* @epic T11745
|
|
31
|
+
*/
|
|
32
|
+
import { type RegisteredSystemOfUse, type SystemOfUseDefaults, type SystemOfUseKind, type SystemOfUsePickerEntry } from '@cleocode/contracts';
|
|
33
|
+
import { formatSystemKey } from './system-key.js';
|
|
34
|
+
/**
|
|
35
|
+
* A registered system-of-use whose `defaults` carry neither a `profile` nor a
|
|
36
|
+
* complete `provider`+`model` tuple is structurally incomplete: it can declare
|
|
37
|
+
* presence in the picker but cannot supply a resolution binding. Such a default
|
|
38
|
+
* is skipped at resolution time (the chain falls through) — never an error.
|
|
39
|
+
*
|
|
40
|
+
* @param defaults - The candidate default binding.
|
|
41
|
+
* @returns `true` when the default can actually bind a provider/model.
|
|
42
|
+
* @task T11751
|
|
43
|
+
*/
|
|
44
|
+
export declare function isResolvableSystemDefault(defaults: SystemOfUseDefaults): boolean;
|
|
45
|
+
/**
|
|
46
|
+
* Register a new system-of-use with a default provider/model binding (AC1).
|
|
47
|
+
*
|
|
48
|
+
* The registration is merged UNDER user config: the resolver consults
|
|
49
|
+
* `defaults` only when the user has configured nothing more specific for `key`
|
|
50
|
+
* (no `llm.systems[key]`, no `llm.default`, no `llm.defaultProfile`). Re-calling
|
|
51
|
+
* with the same `key` REPLACES the prior registration (last-write-wins) so a
|
|
52
|
+
* package can update its own default idempotently.
|
|
53
|
+
*
|
|
54
|
+
* `key` MAY be a flat label (e.g. `'sentient'`) or an open-axis encoded key
|
|
55
|
+
* (`'tool:web-search'`). Passing a structured `SystemOfUse` descriptor is also
|
|
56
|
+
* supported via {@link registerSystemOfUseDescriptor}.
|
|
57
|
+
*
|
|
58
|
+
* @param key - Encoded system-of-use key (non-empty).
|
|
59
|
+
* @param displayName - Human-readable name for the picker surface (non-empty).
|
|
60
|
+
* @param defaults - Default binding consulted strictly below user config.
|
|
61
|
+
* @returns The stored {@link RegisteredSystemOfUse} record.
|
|
62
|
+
* @throws {RangeError} When `key` or `displayName` is empty.
|
|
63
|
+
* @task T11751
|
|
64
|
+
* @epic T11745
|
|
65
|
+
*/
|
|
66
|
+
export declare function registerSystemOfUse(key: string, displayName: string, defaults: SystemOfUseDefaults): RegisteredSystemOfUse;
|
|
67
|
+
/**
|
|
68
|
+
* Register a system-of-use from a structured {@link SystemOfUse} descriptor,
|
|
69
|
+
* encoding it to its canonical string key via {@link formatSystemKey}.
|
|
70
|
+
*
|
|
71
|
+
* Convenience wrapper over {@link registerSystemOfUse} for callers that already
|
|
72
|
+
* hold a `{ kind, id }` descriptor (e.g. plugin-declared tools/skills).
|
|
73
|
+
*
|
|
74
|
+
* @param system - The structured descriptor to register.
|
|
75
|
+
* @param displayName - Human-readable name for the picker surface.
|
|
76
|
+
* @param defaults - Default binding consulted strictly below user config.
|
|
77
|
+
* @returns The stored {@link RegisteredSystemOfUse} record.
|
|
78
|
+
* @task T11751
|
|
79
|
+
*/
|
|
80
|
+
export declare function registerSystemOfUseDescriptor(system: Parameters<typeof formatSystemKey>[0], displayName: string, defaults: SystemOfUseDefaults): RegisteredSystemOfUse;
|
|
81
|
+
/**
|
|
82
|
+
* Look up the runtime-registered default binding for an encoded system key.
|
|
83
|
+
*
|
|
84
|
+
* Returns `undefined` when no system is registered under `key` OR when its
|
|
85
|
+
* default is structurally incomplete (so the resolver falls through). This is
|
|
86
|
+
* the read surface the E9 resolver calls AFTER exhausting all user-config tiers.
|
|
87
|
+
*
|
|
88
|
+
* @param key - Encoded system-of-use key (may be undefined — returns undefined).
|
|
89
|
+
* @returns The resolvable {@link SystemOfUseDefaults}, or `undefined`.
|
|
90
|
+
* @task T11751
|
|
91
|
+
*/
|
|
92
|
+
export declare function getRegisteredSystemDefault(key: string | undefined): SystemOfUseDefaults | undefined;
|
|
93
|
+
/**
|
|
94
|
+
* Enumerate every system-of-use for the TUI / Studio profile picker (AC2):
|
|
95
|
+
* the static {@link BUILTIN_SYSTEMS_OF_USE} table followed by every
|
|
96
|
+
* runtime-registered system, de-duplicated by key (a registration for a builtin
|
|
97
|
+
* key overrides the builtin entry — "user/runtime wins" for the picker label).
|
|
98
|
+
*
|
|
99
|
+
* Each entry carries its encoded `key`, a `displayName`, the discriminant
|
|
100
|
+
* `kind`, and its `source` (`'builtin'` | `'registered'`) so the picker can
|
|
101
|
+
* render and group them. Registered entries also surface their `defaults`.
|
|
102
|
+
*
|
|
103
|
+
* @param kind - Optional kind filter — when set, only that axis is returned.
|
|
104
|
+
* @returns The merged, ordered picker entries.
|
|
105
|
+
* @task T11751
|
|
106
|
+
* @epic T11745
|
|
107
|
+
*/
|
|
108
|
+
export declare function listSystemsOfUse(kind?: SystemOfUseKind): SystemOfUsePickerEntry[];
|
|
109
|
+
/**
|
|
110
|
+
* Clear all runtime registrations.
|
|
111
|
+
*
|
|
112
|
+
* Intended for test isolation — production code never needs to un-register a
|
|
113
|
+
* system. Builtins are unaffected (they live in the contracts SSoT, not here).
|
|
114
|
+
*
|
|
115
|
+
* @internal
|
|
116
|
+
* @task T11751
|
|
117
|
+
*/
|
|
118
|
+
export declare function clearRegisteredSystemsOfUse(): void;
|
|
119
|
+
//# sourceMappingURL=system-of-use-registry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"system-of-use-registry.d.ts","sourceRoot":"","sources":["../../src/llm/system-of-use-registry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAEH,OAAO,EAEL,KAAK,qBAAqB,EAC1B,KAAK,mBAAmB,EACxB,KAAK,eAAe,EACpB,KAAK,sBAAsB,EAC5B,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EAAE,eAAe,EAAiB,MAAM,iBAAiB,CAAC;AAajE;;;;;;;;;GASG;AACH,wBAAgB,yBAAyB,CAAC,QAAQ,EAAE,mBAAmB,GAAG,OAAO,CAGhF;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,mBAAmB,CACjC,GAAG,EAAE,MAAM,EACX,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,mBAAmB,GAC5B,qBAAqB,CAyBvB;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,6BAA6B,CAC3C,MAAM,EAAE,UAAU,CAAC,OAAO,eAAe,CAAC,CAAC,CAAC,CAAC,EAC7C,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,mBAAmB,GAC5B,qBAAqB,CAEvB;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,0BAA0B,CACxC,GAAG,EAAE,MAAM,GAAG,SAAS,GACtB,mBAAmB,GAAG,SAAS,CAMjC;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,CAAC,EAAE,eAAe,GAAG,sBAAsB,EAAE,CA2BjF;AAED;;;;;;;;GAQG;AACH,wBAAgB,2BAA2B,IAAI,IAAI,CAElD"}
|
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `registerSystemOfUse` — runtime extension point for the E9 system-of-use
|
|
3
|
+
* taxonomy (T11751 · AC1).
|
|
4
|
+
*
|
|
5
|
+
* ## Why a runtime registry
|
|
6
|
+
*
|
|
7
|
+
* {@link BUILTIN_SYSTEMS_OF_USE} is the static, closed-axis registry of the
|
|
8
|
+
* well-known systems (orchestration tiers + roles + aux subsystems). Plugins,
|
|
9
|
+
* extensions, and downstream packages need to declare NEW systems-of-use (e.g.
|
|
10
|
+
* a `tool:my-search` or a bespoke `aux`-like subsystem) and give each a default
|
|
11
|
+
* provider/model binding — WITHOUT editing the contracts SSoT.
|
|
12
|
+
*
|
|
13
|
+
* `registerSystemOfUse(key, displayName, defaults)` adds such a system to a
|
|
14
|
+
* process-level registry. The registered default binding is consulted by the
|
|
15
|
+
* single E9 resolution chokepoint (`resolveLLMForSystem` → `resolveLLMForRole`)
|
|
16
|
+
* **strictly BELOW user config** — after `llm.systems[key]`, `llm.default`, and
|
|
17
|
+
* `llm.defaultProfile` — so the user ALWAYS wins (AC1). A registered default
|
|
18
|
+
* only supplies a binding when the user has configured nothing for that key.
|
|
19
|
+
*
|
|
20
|
+
* ## Import-time purity
|
|
21
|
+
*
|
|
22
|
+
* This module performs NO registration at import time — the registry starts
|
|
23
|
+
* empty and is populated only by explicit `registerSystemOfUse(...)` calls. It
|
|
24
|
+
* holds no I/O, no config reads, and no side effects on load (so importing it
|
|
25
|
+
* is always safe). It is the runtime half intentionally split out of the
|
|
26
|
+
* type-only `@cleocode/contracts` (Gate 10).
|
|
27
|
+
*
|
|
28
|
+
* @module llm/system-of-use-registry
|
|
29
|
+
* @task T11751
|
|
30
|
+
* @epic T11745
|
|
31
|
+
*/
|
|
32
|
+
import { BUILTIN_SYSTEMS_OF_USE, } from '@cleocode/contracts';
|
|
33
|
+
import { getLogger } from '../logger.js';
|
|
34
|
+
import { formatSystemKey, systemKeyKind } from './system-key.js';
|
|
35
|
+
const logger = getLogger('llm-system-of-use-registry');
|
|
36
|
+
/**
|
|
37
|
+
* Process-level registry of runtime-registered systems-of-use, keyed by encoded
|
|
38
|
+
* system key. Starts EMPTY — populated only by {@link registerSystemOfUse}.
|
|
39
|
+
*
|
|
40
|
+
* Module-private: callers reach it through the exported functions so the
|
|
41
|
+
* "user wins" / "register vs read" contract is enforced in one place.
|
|
42
|
+
*/
|
|
43
|
+
const REGISTRY = new Map();
|
|
44
|
+
/**
|
|
45
|
+
* A registered system-of-use whose `defaults` carry neither a `profile` nor a
|
|
46
|
+
* complete `provider`+`model` tuple is structurally incomplete: it can declare
|
|
47
|
+
* presence in the picker but cannot supply a resolution binding. Such a default
|
|
48
|
+
* is skipped at resolution time (the chain falls through) — never an error.
|
|
49
|
+
*
|
|
50
|
+
* @param defaults - The candidate default binding.
|
|
51
|
+
* @returns `true` when the default can actually bind a provider/model.
|
|
52
|
+
* @task T11751
|
|
53
|
+
*/
|
|
54
|
+
export function isResolvableSystemDefault(defaults) {
|
|
55
|
+
if (defaults.profile)
|
|
56
|
+
return true;
|
|
57
|
+
return Boolean(defaults.provider && defaults.model);
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Register a new system-of-use with a default provider/model binding (AC1).
|
|
61
|
+
*
|
|
62
|
+
* The registration is merged UNDER user config: the resolver consults
|
|
63
|
+
* `defaults` only when the user has configured nothing more specific for `key`
|
|
64
|
+
* (no `llm.systems[key]`, no `llm.default`, no `llm.defaultProfile`). Re-calling
|
|
65
|
+
* with the same `key` REPLACES the prior registration (last-write-wins) so a
|
|
66
|
+
* package can update its own default idempotently.
|
|
67
|
+
*
|
|
68
|
+
* `key` MAY be a flat label (e.g. `'sentient'`) or an open-axis encoded key
|
|
69
|
+
* (`'tool:web-search'`). Passing a structured `SystemOfUse` descriptor is also
|
|
70
|
+
* supported via {@link registerSystemOfUseDescriptor}.
|
|
71
|
+
*
|
|
72
|
+
* @param key - Encoded system-of-use key (non-empty).
|
|
73
|
+
* @param displayName - Human-readable name for the picker surface (non-empty).
|
|
74
|
+
* @param defaults - Default binding consulted strictly below user config.
|
|
75
|
+
* @returns The stored {@link RegisteredSystemOfUse} record.
|
|
76
|
+
* @throws {RangeError} When `key` or `displayName` is empty.
|
|
77
|
+
* @task T11751
|
|
78
|
+
* @epic T11745
|
|
79
|
+
*/
|
|
80
|
+
export function registerSystemOfUse(key, displayName, defaults) {
|
|
81
|
+
if (!key.trim()) {
|
|
82
|
+
throw new RangeError('registerSystemOfUse: `key` must be a non-empty string');
|
|
83
|
+
}
|
|
84
|
+
if (!displayName.trim()) {
|
|
85
|
+
throw new RangeError('registerSystemOfUse: `displayName` must be a non-empty string');
|
|
86
|
+
}
|
|
87
|
+
const record = {
|
|
88
|
+
key,
|
|
89
|
+
displayName,
|
|
90
|
+
// Defensive copy — the registry owns its records and never aliases the
|
|
91
|
+
// caller's object (so a later caller mutation cannot rewrite a binding).
|
|
92
|
+
defaults: { ...defaults },
|
|
93
|
+
};
|
|
94
|
+
REGISTRY.set(key, record);
|
|
95
|
+
if (!isResolvableSystemDefault(defaults)) {
|
|
96
|
+
logger.debug({ key }, 'registerSystemOfUse: registered with a non-binding default (picker-only) ' +
|
|
97
|
+
'— resolution will fall through past this entry');
|
|
98
|
+
}
|
|
99
|
+
return record;
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Register a system-of-use from a structured {@link SystemOfUse} descriptor,
|
|
103
|
+
* encoding it to its canonical string key via {@link formatSystemKey}.
|
|
104
|
+
*
|
|
105
|
+
* Convenience wrapper over {@link registerSystemOfUse} for callers that already
|
|
106
|
+
* hold a `{ kind, id }` descriptor (e.g. plugin-declared tools/skills).
|
|
107
|
+
*
|
|
108
|
+
* @param system - The structured descriptor to register.
|
|
109
|
+
* @param displayName - Human-readable name for the picker surface.
|
|
110
|
+
* @param defaults - Default binding consulted strictly below user config.
|
|
111
|
+
* @returns The stored {@link RegisteredSystemOfUse} record.
|
|
112
|
+
* @task T11751
|
|
113
|
+
*/
|
|
114
|
+
export function registerSystemOfUseDescriptor(system, displayName, defaults) {
|
|
115
|
+
return registerSystemOfUse(formatSystemKey(system), displayName, defaults);
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Look up the runtime-registered default binding for an encoded system key.
|
|
119
|
+
*
|
|
120
|
+
* Returns `undefined` when no system is registered under `key` OR when its
|
|
121
|
+
* default is structurally incomplete (so the resolver falls through). This is
|
|
122
|
+
* the read surface the E9 resolver calls AFTER exhausting all user-config tiers.
|
|
123
|
+
*
|
|
124
|
+
* @param key - Encoded system-of-use key (may be undefined — returns undefined).
|
|
125
|
+
* @returns The resolvable {@link SystemOfUseDefaults}, or `undefined`.
|
|
126
|
+
* @task T11751
|
|
127
|
+
*/
|
|
128
|
+
export function getRegisteredSystemDefault(key) {
|
|
129
|
+
if (!key)
|
|
130
|
+
return undefined;
|
|
131
|
+
const record = REGISTRY.get(key);
|
|
132
|
+
if (!record)
|
|
133
|
+
return undefined;
|
|
134
|
+
if (!isResolvableSystemDefault(record.defaults))
|
|
135
|
+
return undefined;
|
|
136
|
+
return record.defaults;
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Enumerate every system-of-use for the TUI / Studio profile picker (AC2):
|
|
140
|
+
* the static {@link BUILTIN_SYSTEMS_OF_USE} table followed by every
|
|
141
|
+
* runtime-registered system, de-duplicated by key (a registration for a builtin
|
|
142
|
+
* key overrides the builtin entry — "user/runtime wins" for the picker label).
|
|
143
|
+
*
|
|
144
|
+
* Each entry carries its encoded `key`, a `displayName`, the discriminant
|
|
145
|
+
* `kind`, and its `source` (`'builtin'` | `'registered'`) so the picker can
|
|
146
|
+
* render and group them. Registered entries also surface their `defaults`.
|
|
147
|
+
*
|
|
148
|
+
* @param kind - Optional kind filter — when set, only that axis is returned.
|
|
149
|
+
* @returns The merged, ordered picker entries.
|
|
150
|
+
* @task T11751
|
|
151
|
+
* @epic T11745
|
|
152
|
+
*/
|
|
153
|
+
export function listSystemsOfUse(kind) {
|
|
154
|
+
const byKey = new Map();
|
|
155
|
+
// 1. Builtins first (stable order from the contracts SSoT).
|
|
156
|
+
for (const sys of BUILTIN_SYSTEMS_OF_USE) {
|
|
157
|
+
const key = formatSystemKey(sys);
|
|
158
|
+
byKey.set(key, {
|
|
159
|
+
key,
|
|
160
|
+
displayName: defaultDisplayName(sys.kind, sys.id),
|
|
161
|
+
kind: sys.kind,
|
|
162
|
+
source: 'builtin',
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
// 2. Runtime registrations override/extend (registered wins on key collision).
|
|
166
|
+
for (const record of REGISTRY.values()) {
|
|
167
|
+
byKey.set(record.key, {
|
|
168
|
+
key: record.key,
|
|
169
|
+
displayName: record.displayName,
|
|
170
|
+
kind: systemKeyKind(record.key),
|
|
171
|
+
source: 'registered',
|
|
172
|
+
defaults: record.defaults,
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
const entries = [...byKey.values()];
|
|
176
|
+
return kind ? entries.filter((e) => e.kind === kind) : entries;
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* Clear all runtime registrations.
|
|
180
|
+
*
|
|
181
|
+
* Intended for test isolation — production code never needs to un-register a
|
|
182
|
+
* system. Builtins are unaffected (they live in the contracts SSoT, not here).
|
|
183
|
+
*
|
|
184
|
+
* @internal
|
|
185
|
+
* @task T11751
|
|
186
|
+
*/
|
|
187
|
+
export function clearRegisteredSystemsOfUse() {
|
|
188
|
+
REGISTRY.clear();
|
|
189
|
+
}
|
|
190
|
+
// ---------------------------------------------------------------------------
|
|
191
|
+
// Internal helpers
|
|
192
|
+
// ---------------------------------------------------------------------------
|
|
193
|
+
/**
|
|
194
|
+
* Derive a human-readable default display name for a builtin system. Plain
|
|
195
|
+
* id-with-kind-prefix; the picker may localise/override on top of this.
|
|
196
|
+
*/
|
|
197
|
+
function defaultDisplayName(kind, id) {
|
|
198
|
+
return `${kind}: ${id}`;
|
|
199
|
+
}
|
|
200
|
+
//# sourceMappingURL=system-of-use-registry.js.map
|