@soleri/core 2.10.0 → 2.11.0
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/agency/agency-manager.d.ts +47 -0
- package/dist/agency/agency-manager.d.ts.map +1 -0
- package/dist/agency/agency-manager.js +281 -0
- package/dist/agency/agency-manager.js.map +1 -0
- package/dist/agency/index.d.ts +3 -0
- package/dist/agency/index.d.ts.map +1 -0
- package/dist/agency/index.js +2 -0
- package/dist/agency/index.js.map +1 -0
- package/dist/agency/types.d.ts +69 -0
- package/dist/agency/types.d.ts.map +1 -0
- package/dist/agency/types.js +5 -0
- package/dist/agency/types.js.map +1 -0
- package/dist/brain/brain.d.ts +0 -1
- package/dist/brain/brain.d.ts.map +1 -1
- package/dist/brain/brain.js +14 -0
- package/dist/brain/brain.js.map +1 -1
- package/dist/brain/intelligence.d.ts +5 -1
- package/dist/brain/intelligence.d.ts.map +1 -1
- package/dist/brain/intelligence.js +83 -0
- package/dist/brain/intelligence.js.map +1 -1
- package/dist/brain/types.d.ts +21 -0
- package/dist/brain/types.d.ts.map +1 -1
- package/dist/chat/agent-loop-types.d.ts +82 -0
- package/dist/chat/agent-loop-types.d.ts.map +1 -0
- package/dist/chat/agent-loop-types.js +8 -0
- package/dist/chat/agent-loop-types.js.map +1 -0
- package/dist/chat/agent-loop.d.ts +19 -0
- package/dist/chat/agent-loop.d.ts.map +1 -0
- package/dist/chat/agent-loop.js +261 -0
- package/dist/chat/agent-loop.js.map +1 -0
- package/dist/chat/auth-manager.d.ts +49 -0
- package/dist/chat/auth-manager.d.ts.map +1 -0
- package/dist/chat/auth-manager.js +152 -0
- package/dist/chat/auth-manager.js.map +1 -0
- package/dist/chat/browser-session.d.ts +86 -0
- package/dist/chat/browser-session.d.ts.map +1 -0
- package/dist/chat/browser-session.js +143 -0
- package/dist/chat/browser-session.js.map +1 -0
- package/dist/chat/cancellation.d.ts +54 -0
- package/dist/chat/cancellation.d.ts.map +1 -0
- package/dist/chat/cancellation.js +80 -0
- package/dist/chat/cancellation.js.map +1 -0
- package/dist/chat/chat-session.d.ts +86 -0
- package/dist/chat/chat-session.d.ts.map +1 -0
- package/dist/chat/chat-session.js +252 -0
- package/dist/chat/chat-session.js.map +1 -0
- package/dist/chat/file-handler.d.ts +63 -0
- package/dist/chat/file-handler.d.ts.map +1 -0
- package/dist/chat/file-handler.js +182 -0
- package/dist/chat/file-handler.js.map +1 -0
- package/dist/chat/fragment-buffer.d.ts +49 -0
- package/dist/chat/fragment-buffer.d.ts.map +1 -0
- package/dist/chat/fragment-buffer.js +130 -0
- package/dist/chat/fragment-buffer.js.map +1 -0
- package/dist/chat/index.d.ts +24 -0
- package/dist/chat/index.d.ts.map +1 -0
- package/dist/chat/index.js +15 -0
- package/dist/chat/index.js.map +1 -0
- package/dist/chat/mcp-bridge.d.ts +60 -0
- package/dist/chat/mcp-bridge.d.ts.map +1 -0
- package/dist/chat/mcp-bridge.js +111 -0
- package/dist/chat/mcp-bridge.js.map +1 -0
- package/dist/chat/notifications.d.ts +82 -0
- package/dist/chat/notifications.d.ts.map +1 -0
- package/dist/chat/notifications.js +119 -0
- package/dist/chat/notifications.js.map +1 -0
- package/dist/chat/output-compressor.d.ts +30 -0
- package/dist/chat/output-compressor.d.ts.map +1 -0
- package/dist/chat/output-compressor.js +95 -0
- package/dist/chat/output-compressor.js.map +1 -0
- package/dist/chat/queue.d.ts +91 -0
- package/dist/chat/queue.d.ts.map +1 -0
- package/dist/chat/queue.js +146 -0
- package/dist/chat/queue.js.map +1 -0
- package/dist/chat/response-chunker.d.ts +29 -0
- package/dist/chat/response-chunker.d.ts.map +1 -0
- package/dist/chat/response-chunker.js +163 -0
- package/dist/chat/response-chunker.js.map +1 -0
- package/dist/chat/self-update.d.ts +62 -0
- package/dist/chat/self-update.d.ts.map +1 -0
- package/dist/chat/self-update.js +90 -0
- package/dist/chat/self-update.js.map +1 -0
- package/dist/chat/types.d.ts +105 -0
- package/dist/chat/types.d.ts.map +1 -0
- package/dist/chat/types.js +8 -0
- package/dist/chat/types.js.map +1 -0
- package/dist/chat/voice.d.ts +39 -0
- package/dist/chat/voice.d.ts.map +1 -0
- package/dist/chat/voice.js +80 -0
- package/dist/chat/voice.js.map +1 -0
- package/dist/claudemd/compose.d.ts +31 -0
- package/dist/claudemd/compose.d.ts.map +1 -0
- package/dist/claudemd/compose.js +105 -0
- package/dist/claudemd/compose.js.map +1 -0
- package/dist/claudemd/index.d.ts +5 -0
- package/dist/claudemd/index.d.ts.map +1 -0
- package/dist/claudemd/index.js +3 -0
- package/dist/claudemd/index.js.map +1 -0
- package/dist/claudemd/inject.d.ts +31 -0
- package/dist/claudemd/inject.d.ts.map +1 -0
- package/dist/claudemd/inject.js +157 -0
- package/dist/claudemd/inject.js.map +1 -0
- package/dist/claudemd/types.d.ts +41 -0
- package/dist/claudemd/types.d.ts.map +1 -0
- package/dist/claudemd/types.js +5 -0
- package/dist/claudemd/types.js.map +1 -0
- package/dist/context/context-engine.d.ts +31 -0
- package/dist/context/context-engine.d.ts.map +1 -0
- package/dist/context/context-engine.js +245 -0
- package/dist/context/context-engine.js.map +1 -0
- package/dist/context/index.d.ts +3 -0
- package/dist/context/index.d.ts.map +1 -0
- package/dist/context/index.js +2 -0
- package/dist/context/index.js.map +1 -0
- package/dist/context/types.d.ts +54 -0
- package/dist/context/types.d.ts.map +1 -0
- package/dist/context/types.js +5 -0
- package/dist/context/types.js.map +1 -0
- package/dist/enforcement/adapters/claude-code.d.ts +18 -0
- package/dist/enforcement/adapters/claude-code.d.ts.map +1 -0
- package/dist/enforcement/adapters/claude-code.js +106 -0
- package/dist/enforcement/adapters/claude-code.js.map +1 -0
- package/dist/enforcement/adapters/index.d.ts +2 -0
- package/dist/enforcement/adapters/index.d.ts.map +1 -0
- package/dist/enforcement/adapters/index.js +2 -0
- package/dist/enforcement/adapters/index.js.map +1 -0
- package/dist/enforcement/index.d.ts +4 -0
- package/dist/enforcement/index.d.ts.map +1 -0
- package/dist/enforcement/index.js +3 -0
- package/dist/enforcement/index.js.map +1 -0
- package/dist/enforcement/registry.d.ts +23 -0
- package/dist/enforcement/registry.d.ts.map +1 -0
- package/dist/enforcement/registry.js +63 -0
- package/dist/enforcement/registry.js.map +1 -0
- package/dist/enforcement/types.d.ts +51 -0
- package/dist/enforcement/types.d.ts.map +1 -0
- package/dist/enforcement/types.js +8 -0
- package/dist/enforcement/types.js.map +1 -0
- package/dist/facades/facade-factory.d.ts +10 -3
- package/dist/facades/facade-factory.d.ts.map +1 -1
- package/dist/facades/facade-factory.js +94 -5
- package/dist/facades/facade-factory.js.map +1 -1
- package/dist/facades/types.d.ts +15 -1
- package/dist/facades/types.d.ts.map +1 -1
- package/dist/facades/types.js +6 -0
- package/dist/facades/types.js.map +1 -1
- package/dist/health/health-registry.d.ts +40 -0
- package/dist/health/health-registry.d.ts.map +1 -0
- package/dist/health/health-registry.js +134 -0
- package/dist/health/health-registry.js.map +1 -0
- package/dist/health/index.d.ts +5 -0
- package/dist/health/index.d.ts.map +1 -0
- package/dist/health/index.js +3 -0
- package/dist/health/index.js.map +1 -0
- package/dist/health/vault-integrity.d.ts +13 -0
- package/dist/health/vault-integrity.d.ts.map +1 -0
- package/dist/health/vault-integrity.js +49 -0
- package/dist/health/vault-integrity.js.map +1 -0
- package/dist/index.d.ts +67 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +51 -3
- package/dist/index.js.map +1 -1
- package/dist/intake/intake-pipeline.d.ts +0 -7
- package/dist/intake/intake-pipeline.d.ts.map +1 -1
- package/dist/intake/intake-pipeline.js +1 -1
- package/dist/intake/intake-pipeline.js.map +1 -1
- package/dist/intelligence/types.d.ts +1 -0
- package/dist/intelligence/types.d.ts.map +1 -1
- package/dist/migrations/index.d.ts +6 -0
- package/dist/migrations/index.d.ts.map +1 -0
- package/dist/migrations/index.js +5 -0
- package/dist/migrations/index.js.map +1 -0
- package/dist/migrations/migration-runner.d.ts +51 -0
- package/dist/migrations/migration-runner.d.ts.map +1 -0
- package/dist/migrations/migration-runner.js +141 -0
- package/dist/migrations/migration-runner.js.map +1 -0
- package/dist/packs/index.d.ts +10 -0
- package/dist/packs/index.d.ts.map +1 -0
- package/dist/packs/index.js +8 -0
- package/dist/packs/index.js.map +1 -0
- package/dist/packs/lockfile.d.ts +97 -0
- package/dist/packs/lockfile.d.ts.map +1 -0
- package/dist/packs/lockfile.js +129 -0
- package/dist/packs/lockfile.js.map +1 -0
- package/dist/packs/pack-installer.d.ts +41 -0
- package/dist/packs/pack-installer.d.ts.map +1 -0
- package/dist/packs/pack-installer.js +253 -0
- package/dist/packs/pack-installer.js.map +1 -0
- package/dist/packs/resolver.d.ts +51 -0
- package/dist/packs/resolver.d.ts.map +1 -0
- package/dist/packs/resolver.js +195 -0
- package/dist/packs/resolver.js.map +1 -0
- package/dist/packs/types.d.ts +186 -0
- package/dist/packs/types.d.ts.map +1 -0
- package/dist/packs/types.js +69 -0
- package/dist/packs/types.js.map +1 -0
- package/dist/persistence/postgres-provider.d.ts +42 -7
- package/dist/persistence/postgres-provider.d.ts.map +1 -1
- package/dist/persistence/postgres-provider.js +187 -46
- package/dist/persistence/postgres-provider.js.map +1 -1
- package/dist/playbooks/index.d.ts +2 -0
- package/dist/playbooks/index.d.ts.map +1 -1
- package/dist/playbooks/index.js +2 -0
- package/dist/playbooks/index.js.map +1 -1
- package/dist/playbooks/playbook-executor.d.ts +100 -0
- package/dist/playbooks/playbook-executor.d.ts.map +1 -0
- package/dist/playbooks/playbook-executor.js +207 -0
- package/dist/playbooks/playbook-executor.js.map +1 -0
- package/dist/plugins/index.d.ts +7 -0
- package/dist/plugins/index.d.ts.map +1 -0
- package/dist/plugins/index.js +7 -0
- package/dist/plugins/index.js.map +1 -0
- package/dist/plugins/plugin-loader.d.ts +28 -0
- package/dist/plugins/plugin-loader.d.ts.map +1 -0
- package/dist/plugins/plugin-loader.js +150 -0
- package/dist/plugins/plugin-loader.js.map +1 -0
- package/dist/plugins/plugin-registry.d.ts +58 -0
- package/dist/plugins/plugin-registry.d.ts.map +1 -0
- package/dist/plugins/plugin-registry.js +157 -0
- package/dist/plugins/plugin-registry.js.map +1 -0
- package/dist/plugins/types.d.ts +180 -0
- package/dist/plugins/types.d.ts.map +1 -0
- package/dist/plugins/types.js +48 -0
- package/dist/plugins/types.js.map +1 -0
- package/dist/runtime/admin-extra-ops.d.ts.map +1 -1
- package/dist/runtime/admin-extra-ops.js +181 -8
- package/dist/runtime/admin-extra-ops.js.map +1 -1
- package/dist/runtime/capture-ops.d.ts.map +1 -1
- package/dist/runtime/capture-ops.js +106 -7
- package/dist/runtime/capture-ops.js.map +1 -1
- package/dist/runtime/deprecation.d.ts +33 -0
- package/dist/runtime/deprecation.d.ts.map +1 -0
- package/dist/runtime/deprecation.js +41 -0
- package/dist/runtime/deprecation.js.map +1 -0
- package/dist/runtime/facades/admin-facade.d.ts.map +1 -1
- package/dist/runtime/facades/admin-facade.js +12 -1
- package/dist/runtime/facades/admin-facade.js.map +1 -1
- package/dist/runtime/facades/agency-facade.d.ts +7 -0
- package/dist/runtime/facades/agency-facade.d.ts.map +1 -0
- package/dist/runtime/facades/agency-facade.js +103 -0
- package/dist/runtime/facades/agency-facade.js.map +1 -0
- package/dist/runtime/facades/brain-facade.d.ts.map +1 -1
- package/dist/runtime/facades/brain-facade.js +58 -0
- package/dist/runtime/facades/brain-facade.js.map +1 -1
- package/dist/runtime/facades/chat-facade.d.ts +7 -0
- package/dist/runtime/facades/chat-facade.d.ts.map +1 -0
- package/dist/runtime/facades/chat-facade.js +808 -0
- package/dist/runtime/facades/chat-facade.js.map +1 -0
- package/dist/runtime/facades/context-facade.d.ts +7 -0
- package/dist/runtime/facades/context-facade.d.ts.map +1 -0
- package/dist/runtime/facades/context-facade.js +45 -0
- package/dist/runtime/facades/context-facade.js.map +1 -0
- package/dist/runtime/facades/index.d.ts.map +1 -1
- package/dist/runtime/facades/index.js +18 -0
- package/dist/runtime/facades/index.js.map +1 -1
- package/dist/runtime/facades/vault-facade.d.ts.map +1 -1
- package/dist/runtime/facades/vault-facade.js +247 -1
- package/dist/runtime/facades/vault-facade.js.map +1 -1
- package/dist/runtime/feature-flags.d.ts +18 -0
- package/dist/runtime/feature-flags.d.ts.map +1 -0
- package/dist/runtime/feature-flags.js +90 -0
- package/dist/runtime/feature-flags.js.map +1 -0
- package/dist/runtime/pack-ops.d.ts +9 -0
- package/dist/runtime/pack-ops.d.ts.map +1 -0
- package/dist/runtime/pack-ops.js +76 -0
- package/dist/runtime/pack-ops.js.map +1 -0
- package/dist/runtime/playbook-ops.d.ts +3 -7
- package/dist/runtime/playbook-ops.d.ts.map +1 -1
- package/dist/runtime/playbook-ops.js +101 -10
- package/dist/runtime/playbook-ops.js.map +1 -1
- package/dist/runtime/plugin-ops.d.ts +9 -0
- package/dist/runtime/plugin-ops.d.ts.map +1 -0
- package/dist/runtime/plugin-ops.js +235 -0
- package/dist/runtime/plugin-ops.js.map +1 -0
- package/dist/runtime/runtime.d.ts.map +1 -1
- package/dist/runtime/runtime.js +72 -5
- package/dist/runtime/runtime.js.map +1 -1
- package/dist/runtime/telemetry-ops.d.ts +10 -0
- package/dist/runtime/telemetry-ops.d.ts.map +1 -0
- package/dist/runtime/telemetry-ops.js +53 -0
- package/dist/runtime/telemetry-ops.js.map +1 -0
- package/dist/runtime/types.d.ts +35 -0
- package/dist/runtime/types.d.ts.map +1 -1
- package/dist/runtime/vault-sharing-ops.d.ts +13 -0
- package/dist/runtime/vault-sharing-ops.d.ts.map +1 -0
- package/dist/runtime/vault-sharing-ops.js +345 -0
- package/dist/runtime/vault-sharing-ops.js.map +1 -0
- package/dist/streams/index.d.ts +1 -1
- package/dist/streams/index.d.ts.map +1 -1
- package/dist/streams/index.js +1 -1
- package/dist/streams/index.js.map +1 -1
- package/dist/streams/replayable-stream.d.ts +13 -1
- package/dist/streams/replayable-stream.d.ts.map +1 -1
- package/dist/streams/replayable-stream.js +27 -3
- package/dist/streams/replayable-stream.js.map +1 -1
- package/dist/text/similarity.d.ts +0 -1
- package/dist/text/similarity.d.ts.map +1 -1
- package/dist/text/similarity.js +1 -1
- package/dist/text/similarity.js.map +1 -1
- package/dist/transport/http-server.d.ts +56 -0
- package/dist/transport/http-server.d.ts.map +1 -0
- package/dist/transport/http-server.js +210 -0
- package/dist/transport/http-server.js.map +1 -0
- package/dist/transport/index.d.ts +11 -0
- package/dist/transport/index.d.ts.map +1 -0
- package/dist/transport/index.js +10 -0
- package/dist/transport/index.js.map +1 -0
- package/dist/transport/lsp-server.d.ts +140 -0
- package/dist/transport/lsp-server.d.ts.map +1 -0
- package/dist/transport/lsp-server.js +239 -0
- package/dist/transport/lsp-server.js.map +1 -0
- package/dist/transport/rate-limiter.d.ts +35 -0
- package/dist/transport/rate-limiter.d.ts.map +1 -0
- package/dist/transport/rate-limiter.js +72 -0
- package/dist/transport/rate-limiter.js.map +1 -0
- package/dist/transport/session-manager.d.ts +49 -0
- package/dist/transport/session-manager.d.ts.map +1 -0
- package/dist/transport/session-manager.js +83 -0
- package/dist/transport/session-manager.js.map +1 -0
- package/dist/transport/token-auth.d.ts +29 -0
- package/dist/transport/token-auth.d.ts.map +1 -0
- package/dist/transport/token-auth.js +84 -0
- package/dist/transport/token-auth.js.map +1 -0
- package/dist/transport/types.d.ts +61 -0
- package/dist/transport/types.d.ts.map +1 -0
- package/dist/transport/types.js +5 -0
- package/dist/transport/types.js.map +1 -0
- package/dist/transport/ws-server.d.ts +78 -0
- package/dist/transport/ws-server.d.ts.map +1 -0
- package/dist/transport/ws-server.js +342 -0
- package/dist/transport/ws-server.js.map +1 -0
- package/dist/vault/git-vault-sync.d.ts +107 -0
- package/dist/vault/git-vault-sync.d.ts.map +1 -0
- package/dist/vault/git-vault-sync.js +251 -0
- package/dist/vault/git-vault-sync.js.map +1 -0
- package/dist/vault/knowledge-review.d.ts +67 -0
- package/dist/vault/knowledge-review.d.ts.map +1 -0
- package/dist/vault/knowledge-review.js +133 -0
- package/dist/vault/knowledge-review.js.map +1 -0
- package/dist/vault/obsidian-sync.d.ts +94 -0
- package/dist/vault/obsidian-sync.d.ts.map +1 -0
- package/dist/vault/obsidian-sync.js +247 -0
- package/dist/vault/obsidian-sync.js.map +1 -0
- package/dist/vault/scope-detector.d.ts +31 -0
- package/dist/vault/scope-detector.d.ts.map +1 -0
- package/dist/vault/scope-detector.js +182 -0
- package/dist/vault/scope-detector.js.map +1 -0
- package/dist/vault/vault-branching.d.ts +71 -0
- package/dist/vault/vault-branching.d.ts.map +1 -0
- package/dist/vault/vault-branching.js +180 -0
- package/dist/vault/vault-branching.js.map +1 -0
- package/dist/vault/vault-manager.d.ts +89 -0
- package/dist/vault/vault-manager.d.ts.map +1 -0
- package/dist/vault/vault-manager.js +199 -0
- package/dist/vault/vault-manager.js.map +1 -0
- package/dist/vault/vault-types.d.ts +30 -0
- package/dist/vault/vault-types.d.ts.map +1 -0
- package/dist/vault/vault-types.js +10 -0
- package/dist/vault/vault-types.js.map +1 -0
- package/dist/vault/vault.d.ts +10 -0
- package/dist/vault/vault.d.ts.map +1 -1
- package/dist/vault/vault.js +36 -3
- package/dist/vault/vault.js.map +1 -1
- package/package.json +1 -1
- package/src/__tests__/admin-extra-ops.test.ts +31 -11
- package/src/__tests__/agency-manager.test.ts +374 -0
- package/src/__tests__/agent-loop.test.ts +256 -0
- package/src/__tests__/capture-ops.test.ts +275 -0
- package/src/__tests__/chat-differentiators.test.ts +251 -0
- package/src/__tests__/chat-enhanced.test.ts +390 -0
- package/src/__tests__/chat-transport.test.ts +665 -0
- package/src/__tests__/claudemd.test.ts +282 -0
- package/src/__tests__/context-engine.test.ts +256 -0
- package/src/__tests__/core-ops.test.ts +97 -5
- package/src/__tests__/deprecation.test.ts +78 -0
- package/src/__tests__/enforcement.test.ts +153 -0
- package/src/__tests__/facade-factory.test.ts +271 -0
- package/src/__tests__/feature-flags.test.ts +138 -0
- package/src/__tests__/git-vault-sync.test.ts +230 -0
- package/src/__tests__/health-registry.test.ts +173 -0
- package/src/__tests__/knowledge-review.test.ts +104 -0
- package/src/__tests__/lsp-transport.test.ts +442 -0
- package/src/__tests__/migration-runner.test.ts +170 -0
- package/src/__tests__/normalize.test.ts +10 -0
- package/src/__tests__/obsidian-sync.test.ts +354 -0
- package/src/__tests__/pack-lockfile.test.ts +261 -0
- package/src/__tests__/pack-ops.test.ts +146 -0
- package/src/__tests__/pack-system.test.ts +423 -0
- package/src/__tests__/playbook-executor.test.ts +249 -0
- package/src/__tests__/playbook-ops-execution.test.ts +189 -0
- package/src/__tests__/plugin-ops.test.ts +411 -0
- package/src/__tests__/plugin-system.test.ts +509 -0
- package/src/__tests__/postgres-provider.test.ts +64 -6
- package/src/__tests__/replayable-stream.test.ts +112 -1
- package/src/__tests__/scope-detector.test.ts +121 -0
- package/src/__tests__/session-lifecycle.test.ts +259 -0
- package/src/__tests__/transport.test.ts +758 -0
- package/src/__tests__/vault-branching.test.ts +274 -0
- package/src/__tests__/vault-connect.test.ts +179 -0
- package/src/__tests__/vault-integrity.test.ts +71 -0
- package/src/__tests__/vault-manager.test.ts +238 -0
- package/src/__tests__/vault-scaling.test.ts +281 -0
- package/src/__tests__/vault-sharing.test.ts +270 -0
- package/src/__tests__/ws-transport.test.ts +479 -0
- package/src/agency/agency-manager.ts +326 -0
- package/src/agency/index.ts +13 -0
- package/src/agency/types.ts +88 -0
- package/src/brain/brain.ts +15 -11
- package/src/brain/intelligence.ts +103 -0
- package/src/brain/types.ts +26 -0
- package/src/chat/agent-loop-types.ts +99 -0
- package/src/chat/agent-loop.ts +357 -0
- package/src/chat/auth-manager.ts +171 -0
- package/src/chat/browser-session.ts +188 -0
- package/src/chat/cancellation.ts +99 -0
- package/src/chat/chat-session.ts +283 -0
- package/src/chat/file-handler.ts +230 -0
- package/src/chat/fragment-buffer.ts +160 -0
- package/src/chat/index.ts +72 -0
- package/src/chat/mcp-bridge.ts +135 -0
- package/src/chat/notifications.ts +164 -0
- package/src/chat/output-compressor.ts +116 -0
- package/src/chat/queue.ts +208 -0
- package/src/chat/response-chunker.ts +200 -0
- package/src/chat/self-update.ts +117 -0
- package/src/chat/types.ts +126 -0
- package/src/chat/voice.ts +134 -0
- package/src/claudemd/compose.ts +142 -0
- package/src/claudemd/index.ts +17 -0
- package/src/claudemd/inject.ts +170 -0
- package/src/claudemd/types.ts +45 -0
- package/src/context/context-engine.ts +302 -0
- package/src/context/index.ts +11 -0
- package/src/context/types.ts +69 -0
- package/src/enforcement/adapters/claude-code.ts +135 -0
- package/src/enforcement/adapters/index.ts +1 -0
- package/src/enforcement/index.ts +10 -0
- package/src/enforcement/registry.ts +82 -0
- package/src/enforcement/types.ts +56 -0
- package/src/facades/facade-factory.ts +138 -5
- package/src/facades/types.ts +21 -0
- package/src/health/health-registry.ts +165 -0
- package/src/health/index.ts +11 -0
- package/src/health/vault-integrity.ts +66 -0
- package/src/index.ts +294 -2
- package/src/intake/intake-pipeline.ts +1 -1
- package/src/intelligence/types.ts +1 -0
- package/src/migrations/index.ts +6 -0
- package/src/migrations/migration-runner.ts +185 -0
- package/src/packs/index.ts +20 -0
- package/src/packs/lockfile.ts +180 -0
- package/src/packs/pack-installer.ts +289 -0
- package/src/packs/resolver.ts +237 -0
- package/src/packs/types.ts +125 -0
- package/src/persistence/postgres-provider.ts +211 -58
- package/src/playbooks/index.ts +11 -0
- package/src/playbooks/playbook-executor.ts +301 -0
- package/src/plugins/index.ts +19 -0
- package/src/plugins/plugin-loader.ts +183 -0
- package/src/plugins/plugin-registry.ts +187 -0
- package/src/plugins/types.ts +119 -0
- package/src/runtime/admin-extra-ops.ts +193 -8
- package/src/runtime/capture-ops.ts +113 -8
- package/src/runtime/deprecation.ts +58 -0
- package/src/runtime/facades/admin-facade.ts +16 -1
- package/src/runtime/facades/agency-facade.ts +111 -0
- package/src/runtime/facades/brain-facade.ts +60 -0
- package/src/runtime/facades/chat-facade.ts +918 -0
- package/src/runtime/facades/context-facade.ts +55 -0
- package/src/runtime/facades/index.ts +22 -1
- package/src/runtime/facades/vault-facade.ts +261 -1
- package/src/runtime/feature-flags.ts +101 -0
- package/src/runtime/pack-ops.ts +85 -0
- package/src/runtime/playbook-ops.ts +113 -9
- package/src/runtime/plugin-ops.ts +258 -0
- package/src/runtime/runtime.ts +84 -5
- package/src/runtime/telemetry-ops.ts +57 -0
- package/src/runtime/types.ts +35 -0
- package/src/runtime/vault-sharing-ops.ts +372 -0
- package/src/streams/index.ts +1 -1
- package/src/streams/replayable-stream.ts +34 -3
- package/src/text/similarity.ts +1 -1
- package/src/transport/http-server.ts +269 -0
- package/src/transport/index.ts +48 -0
- package/src/transport/lsp-server.ts +401 -0
- package/src/transport/rate-limiter.ts +97 -0
- package/src/transport/session-manager.ts +120 -0
- package/src/transport/token-auth.ts +96 -0
- package/src/transport/types.ts +66 -0
- package/src/transport/ws-server.ts +415 -0
- package/src/vault/git-vault-sync.ts +318 -0
- package/src/vault/knowledge-review.ts +221 -0
- package/src/vault/obsidian-sync.ts +346 -0
- package/src/vault/scope-detector.ts +219 -0
- package/src/vault/vault-branching.ts +264 -0
- package/src/vault/vault-manager.ts +237 -0
- package/src/vault/vault-types.ts +50 -0
- package/src/vault/vault.ts +41 -3
- package/src/governance/index.ts +0 -18
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Browser Session Manager — per-chat Playwright isolation.
|
|
3
|
+
*
|
|
4
|
+
* Manages a pool of Playwright MCP client sessions, one per chat.
|
|
5
|
+
* Lazy initialization on first use, idle timeout eviction, FIFO
|
|
6
|
+
* eviction when max sessions reached.
|
|
7
|
+
*
|
|
8
|
+
* The actual Playwright MCP server is spawned as a child process
|
|
9
|
+
* via stdio transport. This module manages the lifecycle.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import { spawn, type ChildProcess } from 'node:child_process';
|
|
13
|
+
|
|
14
|
+
// ─── Types ────────────────────────────────────────────────────────────
|
|
15
|
+
|
|
16
|
+
export interface BrowserSessionConfig {
|
|
17
|
+
/** Idle timeout before closing a session (ms). Default: 5 minutes. */
|
|
18
|
+
idleTimeoutMs?: number;
|
|
19
|
+
/** Max concurrent browser sessions. Default: 3. */
|
|
20
|
+
maxSessions?: number;
|
|
21
|
+
/** Command to spawn Playwright MCP. Default: 'npx'. */
|
|
22
|
+
command?: string;
|
|
23
|
+
/** Args for the command. Default: ['@playwright/mcp', '--headless']. */
|
|
24
|
+
args?: string[];
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export interface BrowserSession {
|
|
28
|
+
chatId: string;
|
|
29
|
+
process: ChildProcess;
|
|
30
|
+
lastUsed: number;
|
|
31
|
+
idleTimer: ReturnType<typeof setTimeout> | null;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export interface BrowserTool {
|
|
35
|
+
name: string;
|
|
36
|
+
description: string;
|
|
37
|
+
inputSchema: Record<string, unknown>;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export interface BrowserToolResult {
|
|
41
|
+
content: Array<{ type: string; text?: string; data?: string; mimeType?: string }>;
|
|
42
|
+
isError?: boolean;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// ─── Session Manager ─────────────────────────────────────────────────
|
|
46
|
+
|
|
47
|
+
const DEFAULT_IDLE_TIMEOUT = 5 * 60 * 1000; // 5 minutes
|
|
48
|
+
const DEFAULT_MAX_SESSIONS = 3;
|
|
49
|
+
|
|
50
|
+
export class BrowserSessionManager {
|
|
51
|
+
private sessions = new Map<string, BrowserSession>();
|
|
52
|
+
private readonly idleTimeoutMs: number;
|
|
53
|
+
private readonly maxSessions: number;
|
|
54
|
+
private readonly command: string;
|
|
55
|
+
private readonly args: string[];
|
|
56
|
+
|
|
57
|
+
constructor(config: BrowserSessionConfig = {}) {
|
|
58
|
+
this.idleTimeoutMs = config.idleTimeoutMs ?? DEFAULT_IDLE_TIMEOUT;
|
|
59
|
+
this.maxSessions = config.maxSessions ?? DEFAULT_MAX_SESSIONS;
|
|
60
|
+
this.command = config.command ?? 'npx';
|
|
61
|
+
this.args = config.args ?? ['@playwright/mcp', '--headless'];
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Get or create a browser session for a chat.
|
|
66
|
+
* Returns the session, spawning a new process if needed.
|
|
67
|
+
*/
|
|
68
|
+
acquire(chatId: string): BrowserSession {
|
|
69
|
+
const existing = this.sessions.get(chatId);
|
|
70
|
+
if (existing) {
|
|
71
|
+
// Reset idle timer
|
|
72
|
+
if (existing.idleTimer) clearTimeout(existing.idleTimer);
|
|
73
|
+
existing.lastUsed = Date.now();
|
|
74
|
+
existing.idleTimer = setTimeout(() => this.release(chatId), this.idleTimeoutMs);
|
|
75
|
+
return existing;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// Evict if at capacity
|
|
79
|
+
if (this.sessions.size >= this.maxSessions) {
|
|
80
|
+
this.evictOldest();
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// Spawn new Playwright MCP process
|
|
84
|
+
const proc = spawn(this.command, this.args, {
|
|
85
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
86
|
+
env: { ...process.env },
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
const session: BrowserSession = {
|
|
90
|
+
chatId,
|
|
91
|
+
process: proc,
|
|
92
|
+
lastUsed: Date.now(),
|
|
93
|
+
idleTimer: setTimeout(() => this.release(chatId), this.idleTimeoutMs),
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
proc.on('exit', () => {
|
|
97
|
+
// Clean up if process dies unexpectedly
|
|
98
|
+
const s = this.sessions.get(chatId);
|
|
99
|
+
if (s && s.process === proc) {
|
|
100
|
+
if (s.idleTimer) clearTimeout(s.idleTimer);
|
|
101
|
+
this.sessions.delete(chatId);
|
|
102
|
+
}
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
this.sessions.set(chatId, session);
|
|
106
|
+
return session;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Release a browser session (close process, remove from pool).
|
|
111
|
+
*/
|
|
112
|
+
release(chatId: string): boolean {
|
|
113
|
+
const session = this.sessions.get(chatId);
|
|
114
|
+
if (!session) return false;
|
|
115
|
+
|
|
116
|
+
if (session.idleTimer) clearTimeout(session.idleTimer);
|
|
117
|
+
|
|
118
|
+
try {
|
|
119
|
+
session.process.kill();
|
|
120
|
+
} catch {
|
|
121
|
+
// Process may already be dead
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
this.sessions.delete(chatId);
|
|
125
|
+
return true;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Check if a chat has an active browser session.
|
|
130
|
+
*/
|
|
131
|
+
has(chatId: string): boolean {
|
|
132
|
+
return this.sessions.has(chatId);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Close all browser sessions.
|
|
137
|
+
*/
|
|
138
|
+
closeAll(): number {
|
|
139
|
+
let count = 0;
|
|
140
|
+
for (const chatId of this.sessions.keys()) {
|
|
141
|
+
if (this.release(chatId)) count++;
|
|
142
|
+
}
|
|
143
|
+
return count;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Get number of active sessions.
|
|
148
|
+
*/
|
|
149
|
+
get size(): number {
|
|
150
|
+
return this.sessions.size;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* List active session chat IDs.
|
|
155
|
+
*/
|
|
156
|
+
listSessions(): string[] {
|
|
157
|
+
return [...this.sessions.keys()];
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* Get session info.
|
|
162
|
+
*/
|
|
163
|
+
getInfo(chatId: string): { lastUsed: number; pid: number | null } | null {
|
|
164
|
+
const session = this.sessions.get(chatId);
|
|
165
|
+
if (!session) return null;
|
|
166
|
+
return {
|
|
167
|
+
lastUsed: session.lastUsed,
|
|
168
|
+
pid: session.process.pid ?? null,
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* Evict the oldest (least recently used) session.
|
|
174
|
+
*/
|
|
175
|
+
private evictOldest(): void {
|
|
176
|
+
let oldest: string | null = null;
|
|
177
|
+
let oldestTime = Infinity;
|
|
178
|
+
|
|
179
|
+
for (const [chatId, session] of this.sessions) {
|
|
180
|
+
if (session.lastUsed < oldestTime) {
|
|
181
|
+
oldestTime = session.lastUsed;
|
|
182
|
+
oldest = chatId;
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
if (oldest) this.release(oldest);
|
|
187
|
+
}
|
|
188
|
+
}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Task Cancellation Manager — per-chat AbortController management.
|
|
3
|
+
*
|
|
4
|
+
* Maps chat/session IDs to AbortControllers so running tasks can be
|
|
5
|
+
* cancelled from commands (e.g. /stop) or inline buttons.
|
|
6
|
+
*
|
|
7
|
+
* The agent loop already accepts AbortSignal — this provides the
|
|
8
|
+
* lifecycle management layer on top.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
export interface CancellationInfo {
|
|
12
|
+
/** The AbortController for this task. */
|
|
13
|
+
controller: AbortController;
|
|
14
|
+
/** Unix timestamp ms when the task started. */
|
|
15
|
+
startedAt: number;
|
|
16
|
+
/** Optional description of what's running. */
|
|
17
|
+
description?: string;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export class TaskCancellationManager {
|
|
21
|
+
private active = new Map<string, CancellationInfo>();
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Create a new AbortController for a chat/session.
|
|
25
|
+
* If one already exists, it is cancelled first.
|
|
26
|
+
*/
|
|
27
|
+
create(chatId: string, description?: string): AbortSignal {
|
|
28
|
+
// Cancel existing task if any
|
|
29
|
+
this.cancel(chatId);
|
|
30
|
+
|
|
31
|
+
const controller = new AbortController();
|
|
32
|
+
this.active.set(chatId, {
|
|
33
|
+
controller,
|
|
34
|
+
startedAt: Date.now(),
|
|
35
|
+
description,
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
return controller.signal;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Cancel the running task for a chat. Returns info about what was cancelled.
|
|
43
|
+
*/
|
|
44
|
+
cancel(chatId: string): CancellationInfo | null {
|
|
45
|
+
const info = this.active.get(chatId);
|
|
46
|
+
if (!info) return null;
|
|
47
|
+
|
|
48
|
+
info.controller.abort();
|
|
49
|
+
this.active.delete(chatId);
|
|
50
|
+
return info;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Mark a task as complete (remove without aborting).
|
|
55
|
+
*/
|
|
56
|
+
complete(chatId: string): void {
|
|
57
|
+
this.active.delete(chatId);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Check if a chat has a running task.
|
|
62
|
+
*/
|
|
63
|
+
isRunning(chatId: string): boolean {
|
|
64
|
+
return this.active.has(chatId);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Get info about a running task.
|
|
69
|
+
*/
|
|
70
|
+
getInfo(chatId: string): CancellationInfo | null {
|
|
71
|
+
return this.active.get(chatId) ?? null;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Get all running task IDs.
|
|
76
|
+
*/
|
|
77
|
+
listRunning(): string[] {
|
|
78
|
+
return [...this.active.keys()];
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Number of active tasks.
|
|
83
|
+
*/
|
|
84
|
+
get size(): number {
|
|
85
|
+
return this.active.size;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Cancel all running tasks.
|
|
90
|
+
*/
|
|
91
|
+
cancelAll(): number {
|
|
92
|
+
let count = 0;
|
|
93
|
+
for (const [chatId] of this.active) {
|
|
94
|
+
this.cancel(chatId);
|
|
95
|
+
count++;
|
|
96
|
+
}
|
|
97
|
+
return count;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
@@ -0,0 +1,283 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Chat Session Manager — per-conversation history with disk persistence.
|
|
3
|
+
*
|
|
4
|
+
* Ported from Salvador's session-manager.ts with improvements:
|
|
5
|
+
* - Transport-agnostic (no Telegram coupling)
|
|
6
|
+
* - Synchronous persistence (matches Soleri's better-sqlite3 heritage)
|
|
7
|
+
* - Simpler compaction (no personality tracking)
|
|
8
|
+
* - TTL-based reaping with unref'd timer
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { readFileSync, writeFileSync, existsSync, mkdirSync, rmSync, readdirSync } from 'node:fs';
|
|
12
|
+
import { join } from 'node:path';
|
|
13
|
+
import type { ChatSession, ChatSessionConfig, ChatMessage } from './types.js';
|
|
14
|
+
|
|
15
|
+
const DEFAULT_TTL_MS = 7_200_000; // 2 hours
|
|
16
|
+
const DEFAULT_COMPACTION_THRESHOLD = 100;
|
|
17
|
+
const DEFAULT_COMPACTION_KEEP = 40;
|
|
18
|
+
const REAPER_INTERVAL_MS = 60_000; // 1 minute
|
|
19
|
+
|
|
20
|
+
export class ChatSessionManager {
|
|
21
|
+
private sessions = new Map<string, ChatSession>();
|
|
22
|
+
private config: Required<ChatSessionConfig>;
|
|
23
|
+
private reaperTimer: ReturnType<typeof setInterval> | null = null;
|
|
24
|
+
|
|
25
|
+
constructor(config: ChatSessionConfig) {
|
|
26
|
+
this.config = {
|
|
27
|
+
storageDir: config.storageDir,
|
|
28
|
+
ttlMs: config.ttlMs ?? DEFAULT_TTL_MS,
|
|
29
|
+
compactionThreshold: config.compactionThreshold ?? DEFAULT_COMPACTION_THRESHOLD,
|
|
30
|
+
compactionKeep: config.compactionKeep ?? DEFAULT_COMPACTION_KEEP,
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
mkdirSync(this.config.storageDir, { recursive: true });
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// ─── Lifecycle ──────────────────────────────────────────────────
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Get or create a session. Loads from disk if not in memory.
|
|
40
|
+
*/
|
|
41
|
+
getOrCreate(sessionId: string): ChatSession {
|
|
42
|
+
let session = this.sessions.get(sessionId);
|
|
43
|
+
if (session) {
|
|
44
|
+
session.lastActiveAt = Date.now();
|
|
45
|
+
return session;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// Try loading from disk
|
|
49
|
+
session = this.loadFromDisk(sessionId);
|
|
50
|
+
if (session) {
|
|
51
|
+
session.lastActiveAt = Date.now();
|
|
52
|
+
this.sessions.set(sessionId, session);
|
|
53
|
+
return session;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// Create new
|
|
57
|
+
const now = Date.now();
|
|
58
|
+
session = {
|
|
59
|
+
id: sessionId,
|
|
60
|
+
messages: [],
|
|
61
|
+
createdAt: now,
|
|
62
|
+
lastActiveAt: now,
|
|
63
|
+
};
|
|
64
|
+
this.sessions.set(sessionId, session);
|
|
65
|
+
this.persistToDisk(session);
|
|
66
|
+
return session;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Get a session without creating one.
|
|
71
|
+
*/
|
|
72
|
+
get(sessionId: string): ChatSession | undefined {
|
|
73
|
+
return this.sessions.get(sessionId) ?? this.loadFromDisk(sessionId);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Check if a session exists (memory or disk).
|
|
78
|
+
*/
|
|
79
|
+
has(sessionId: string): boolean {
|
|
80
|
+
if (this.sessions.has(sessionId)) return true;
|
|
81
|
+
return existsSync(this.sessionPath(sessionId));
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// ─── Message Management ─────────────────────────────────────────
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Append a message and persist.
|
|
88
|
+
*/
|
|
89
|
+
appendMessage(sessionId: string, message: ChatMessage): void {
|
|
90
|
+
const session = this.getOrCreate(sessionId);
|
|
91
|
+
session.messages.push(message);
|
|
92
|
+
session.lastActiveAt = Date.now();
|
|
93
|
+
|
|
94
|
+
// Auto-compact if threshold exceeded
|
|
95
|
+
if (session.messages.length > this.config.compactionThreshold) {
|
|
96
|
+
this.compact(session);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
this.persistToDisk(session);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Append multiple messages (e.g. assistant response + tool blocks).
|
|
104
|
+
*/
|
|
105
|
+
appendMessages(sessionId: string, messages: ChatMessage[]): void {
|
|
106
|
+
const session = this.getOrCreate(sessionId);
|
|
107
|
+
session.messages.push(...messages);
|
|
108
|
+
session.lastActiveAt = Date.now();
|
|
109
|
+
|
|
110
|
+
if (session.messages.length > this.config.compactionThreshold) {
|
|
111
|
+
this.compact(session);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
this.persistToDisk(session);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Get message count for a session.
|
|
119
|
+
*/
|
|
120
|
+
messageCount(sessionId: string): number {
|
|
121
|
+
const session = this.sessions.get(sessionId);
|
|
122
|
+
return session?.messages.length ?? 0;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// ─── Session Operations ─────────────────────────────────────────
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Clear session history (keep session alive, wipe messages).
|
|
129
|
+
*/
|
|
130
|
+
clear(sessionId: string): void {
|
|
131
|
+
const session = this.sessions.get(sessionId);
|
|
132
|
+
if (session) {
|
|
133
|
+
session.messages = [];
|
|
134
|
+
session.lastActiveAt = Date.now();
|
|
135
|
+
this.persistToDisk(session);
|
|
136
|
+
} else {
|
|
137
|
+
// Remove from disk
|
|
138
|
+
this.removeFromDisk(sessionId);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Delete a session entirely (memory + disk).
|
|
144
|
+
*/
|
|
145
|
+
delete(sessionId: string): void {
|
|
146
|
+
this.sessions.delete(sessionId);
|
|
147
|
+
this.removeFromDisk(sessionId);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* List all active session IDs (memory only — disk sessions not loaded).
|
|
152
|
+
*/
|
|
153
|
+
listActive(): string[] {
|
|
154
|
+
return [...this.sessions.keys()];
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* List all session IDs (memory + disk).
|
|
159
|
+
*/
|
|
160
|
+
listAll(): string[] {
|
|
161
|
+
const memoryIds = new Set(this.sessions.keys());
|
|
162
|
+
try {
|
|
163
|
+
const files = readdirSync(this.config.storageDir);
|
|
164
|
+
for (const f of files) {
|
|
165
|
+
if (f.endsWith('.json')) {
|
|
166
|
+
memoryIds.add(f.replace('.json', ''));
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
} catch {
|
|
170
|
+
// Directory may not exist yet
|
|
171
|
+
}
|
|
172
|
+
return [...memoryIds];
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* Number of active (in-memory) sessions.
|
|
177
|
+
*/
|
|
178
|
+
get size(): number {
|
|
179
|
+
return this.sessions.size;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* Update session metadata.
|
|
184
|
+
*/
|
|
185
|
+
setMeta(sessionId: string, meta: Record<string, unknown>): void {
|
|
186
|
+
const session = this.getOrCreate(sessionId);
|
|
187
|
+
session.meta = { ...session.meta, ...meta };
|
|
188
|
+
this.persistToDisk(session);
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
// ─── Reaping (TTL cleanup) ─────────────────────────────────────
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* Start periodic TTL-based session cleanup.
|
|
195
|
+
*/
|
|
196
|
+
startReaper(): void {
|
|
197
|
+
if (this.reaperTimer) return;
|
|
198
|
+
this.reaperTimer = setInterval(() => this.reap(), REAPER_INTERVAL_MS);
|
|
199
|
+
this.reaperTimer.unref();
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
/**
|
|
203
|
+
* Stop the reaper.
|
|
204
|
+
*/
|
|
205
|
+
stopReaper(): void {
|
|
206
|
+
if (this.reaperTimer) {
|
|
207
|
+
clearInterval(this.reaperTimer);
|
|
208
|
+
this.reaperTimer = null;
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
/**
|
|
213
|
+
* Reap expired sessions. Returns number of sessions reaped.
|
|
214
|
+
*/
|
|
215
|
+
reap(): number {
|
|
216
|
+
if (this.config.ttlMs <= 0) return 0;
|
|
217
|
+
|
|
218
|
+
const now = Date.now();
|
|
219
|
+
const cutoff = now - this.config.ttlMs;
|
|
220
|
+
let reaped = 0;
|
|
221
|
+
|
|
222
|
+
for (const [id, session] of this.sessions) {
|
|
223
|
+
if (session.lastActiveAt < cutoff) {
|
|
224
|
+
this.sessions.delete(id);
|
|
225
|
+
this.removeFromDisk(id);
|
|
226
|
+
reaped++;
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
return reaped;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
/**
|
|
234
|
+
* Close all sessions and stop reaper.
|
|
235
|
+
*/
|
|
236
|
+
close(): void {
|
|
237
|
+
this.stopReaper();
|
|
238
|
+
this.sessions.clear();
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
// ─── Private ───────────────────────────────────────────────────
|
|
242
|
+
|
|
243
|
+
private compact(session: ChatSession): void {
|
|
244
|
+
const keep = this.config.compactionKeep;
|
|
245
|
+
if (session.messages.length <= keep) return;
|
|
246
|
+
session.messages = session.messages.slice(-keep);
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
private sessionPath(sessionId: string): string {
|
|
250
|
+
// Sanitize ID for filesystem safety
|
|
251
|
+
const safe = sessionId.replace(/[^a-zA-Z0-9_-]/g, '_');
|
|
252
|
+
return join(this.config.storageDir, `${safe}.json`);
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
private persistToDisk(session: ChatSession): void {
|
|
256
|
+
try {
|
|
257
|
+
writeFileSync(this.sessionPath(session.id), JSON.stringify(session), 'utf-8');
|
|
258
|
+
} catch {
|
|
259
|
+
// Disk write failure is non-critical — session lives in memory
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
private loadFromDisk(sessionId: string): ChatSession | undefined {
|
|
264
|
+
const path = this.sessionPath(sessionId);
|
|
265
|
+
if (!existsSync(path)) return undefined;
|
|
266
|
+
|
|
267
|
+
try {
|
|
268
|
+
const data = readFileSync(path, 'utf-8');
|
|
269
|
+
return JSON.parse(data) as ChatSession;
|
|
270
|
+
} catch {
|
|
271
|
+
return undefined;
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
private removeFromDisk(sessionId: string): void {
|
|
276
|
+
const path = this.sessionPath(sessionId);
|
|
277
|
+
try {
|
|
278
|
+
rmSync(path, { force: true });
|
|
279
|
+
} catch {
|
|
280
|
+
// Removal failure is non-critical
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
}
|