@jungjaehoon/mama-core 2.4.1 → 4.0.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/README.md +76 -239
- package/db/migrations/030-case-first-memory-substrate.sql +13 -98
- package/db/migrations/034-add-connector-event-scope-columns.sql +9 -13
- package/db/migrations/039-add-connector-event-operator-ingest-seq.sql +9 -95
- package/db/migrations/062-refresh-connector-event-sequences.sql +9 -113
- package/db/migrations/063-refresh-legacy-connector-event-updates.sql +9 -32
- package/db/migrations/067-add-connector-event-source-entity-id.sql +9 -13
- package/db/migrations/069-create-registry-nodes.sql +52 -0
- package/db/migrations/070-record-identity.sql +35 -0
- package/db/migrations/071-service-operation-origins.sql +187 -0
- package/db/migrations/072-observation-versions.sql +29 -0
- package/db/migrations/073-registry-corrections.sql +45 -0
- package/db/migrations/074-work-graph-ref-kinds.sql +39 -0
- package/db/migrations/075-agent-judgments.sql +58 -0
- package/db/migrations/076-scoped-checkpoint-bindings.sql +15 -0
- package/db/migrations/077-legacy-record-kind.sql +6 -0
- package/db/migrations/078-source-ingest-commands.sql +18 -0
- package/db/migrations/079-twin-edge-relations.sql +43 -0
- package/db/migrations/080-restore-duration-days.sql +7 -0
- package/db/migrations/081-mailbox.sql +61 -0
- package/db/migrations/082-commitments-row-id.sql +12 -0
- package/db/migrations/083-observation-is-the-evidence.sql +49 -0
- package/db/migrations/084-scope-kind-is-not-the-cores-to-list.sql +34 -0
- package/db/migrations/085-a-migration-has-a-source.sql +37 -0
- package/db/migrations/086-the-mailbox-is-generic.sql +110 -0
- package/db/migrations/087-mailbox-payload.sql +5 -0
- package/db/migrations/088-native-input-journal.sql +14 -0
- package/db/migrations/089-native-turn-receipt-lookup.sql +3 -0
- package/db/migrations/090-model-run-native-inputs.sql +29 -0
- package/db/migrations/091-native-turn-results.sql +11 -0
- package/db/migrations/092-restore-decision-fts.sql +34 -0
- package/db/migrations/093-native-turn-primary-kind.sql +14 -0
- package/db/migrations/094-commitment-run-provenance.sql +9 -0
- package/db/migrations/095-model-run-native-input-identity.sql +39 -0
- package/db/migrations/096-drop-connector-event-index-fts.sql +9 -0
- package/db/migrations/097-native-input-json-validity.sql +37 -0
- package/db/migrations/098-workflow-memory-kind.sql +105 -0
- package/dist/action-contracts.d.ts +212 -0
- package/dist/action-contracts.js +10 -0
- package/dist/api/catalog.d.ts +118 -0
- package/dist/api/catalog.js +1756 -0
- package/dist/api/dispatch.d.ts +76 -0
- package/dist/api/dispatch.js +372 -0
- package/dist/canonicalize.d.ts +2 -2
- package/dist/canonicalize.js +3 -3
- package/dist/client/client.d.ts +33 -0
- package/dist/client/client.js +123 -0
- package/dist/client/ipc.d.ts +81 -0
- package/dist/client/ipc.js +314 -0
- package/dist/db-adapter/base-adapter.d.ts +6 -66
- package/dist/db-adapter/base-adapter.js +6 -6
- package/dist/db-adapter/index.d.ts +5 -5
- package/dist/db-adapter/index.js +2 -5
- package/dist/db-adapter/node-sqlite-adapter.d.ts +85 -15
- package/dist/db-adapter/node-sqlite-adapter.js +1968 -570
- package/dist/db-manager.d.ts +53 -97
- package/dist/db-manager.js +121 -603
- package/dist/embedding/embedder.d.ts +132 -0
- package/dist/embedding/embedder.js +299 -0
- package/dist/identity/principal-repository.d.ts +2 -2
- package/dist/index.d.ts +43 -58
- package/dist/index.js +97 -145
- package/dist/{context-compile/channel-grant.d.ts → knowledge/access.d.ts} +12 -17
- package/dist/knowledge/access.js +663 -0
- package/dist/knowledge/case-errors.d.ts +31 -0
- package/dist/knowledge/case-errors.js +40 -0
- package/dist/{cases/search-rollup.d.ts → knowledge/case-search-rollup.d.ts} +5 -4
- package/dist/{cases/search-rollup.js → knowledge/case-search-rollup.js} +6 -8
- package/dist/{cases/store.d.ts → knowledge/case-store.d.ts} +3 -6
- package/dist/{cases/store.js → knowledge/case-store.js} +7 -42
- package/dist/{cases/timeline-range.d.ts → knowledge/case-timeline-range.d.ts} +3 -3
- package/dist/{cases/timeline-range.js → knowledge/case-timeline-range.js} +47 -25
- package/dist/{cases/types.d.ts → knowledge/case-types.d.ts} +8 -2
- package/dist/{cases/types.js → knowledge/case-types.js} +1 -1
- package/dist/knowledge/commitments.d.ts +188 -0
- package/dist/knowledge/commitments.js +370 -0
- package/dist/knowledge/decision-edges.d.ts +70 -0
- package/dist/knowledge/decision-edges.js +123 -0
- package/dist/{agent-graph/types.d.ts → knowledge/graph-query.d.ts} +80 -70
- package/dist/knowledge/graph-query.js +1585 -0
- package/dist/knowledge/identity.d.ts +16 -0
- package/dist/knowledge/identity.js +22 -0
- package/dist/knowledge/index.d.ts +47 -0
- package/dist/knowledge/index.js +90 -0
- package/dist/knowledge/judgments.d.ts +118 -0
- package/dist/knowledge/judgments.js +808 -0
- package/dist/knowledge/observations.d.ts +160 -0
- package/dist/knowledge/observations.js +449 -0
- package/dist/knowledge/question-type.d.ts +34 -0
- package/dist/knowledge/question-type.js +70 -0
- package/dist/{search → knowledge}/ranker-features.js +1 -1
- package/dist/{search → knowledge}/search-quality.d.ts +0 -1
- package/dist/knowledge/search.d.ts +38 -0
- package/dist/knowledge/search.js +91 -0
- package/dist/knowledge/source-ingest.d.ts +65 -0
- package/dist/knowledge/source-ingest.js +174 -0
- package/dist/{edges/types.d.ts → knowledge/twin-edge-types.d.ts} +31 -4
- package/dist/{edges/types.js → knowledge/twin-edge-types.js} +13 -2
- package/dist/knowledge/work-dates.d.ts +49 -0
- package/dist/knowledge/work-dates.js +120 -0
- package/dist/mama-api.d.ts +114 -778
- package/dist/mama-api.js +313 -2461
- package/dist/memory/api.d.ts +264 -24
- package/dist/memory/api.js +1633 -843
- package/dist/memory/bootstrap-builder.d.ts +2 -1
- package/dist/memory/bootstrap-builder.js +5 -5
- package/dist/memory/channel-summary-state-store.d.ts +3 -2
- package/dist/memory/channel-summary-state-store.js +53 -51
- package/dist/memory/channel-summary-store.d.ts +5 -3
- package/dist/memory/channel-summary-store.js +3 -8
- package/dist/memory/dashboard-read.d.ts +46 -0
- package/dist/memory/dashboard-read.js +94 -0
- package/dist/memory/event-store.d.ts +3 -3
- package/dist/memory/event-store.js +3 -10
- package/dist/memory/finding-store.d.ts +3 -2
- package/dist/memory/finding-store.js +2 -7
- package/dist/memory/graph-read.d.ts +52 -0
- package/dist/memory/graph-read.js +130 -0
- package/dist/memory/judgment-types.d.ts +394 -0
- package/dist/memory/judgment-types.js +16 -0
- package/dist/memory/provenance-audit.d.ts +5 -2
- package/dist/memory/provenance-audit.js +8 -14
- package/dist/memory/provenance-live.d.ts +141 -0
- package/dist/memory/provenance-live.js +409 -0
- package/dist/memory/provenance-query.d.ts +5 -4
- package/dist/memory/provenance-query.js +21 -29
- package/dist/memory/provenance-resolver.d.ts +191 -0
- package/dist/memory/provenance-resolver.js +155 -0
- package/dist/memory/provenance.d.ts +1 -11
- package/dist/memory/provenance.js +2 -33
- package/dist/memory/recall-sanitize.d.ts +55 -0
- package/dist/memory/recall-sanitize.js +144 -0
- package/dist/memory/secret-filter.d.ts +32 -0
- package/dist/memory/secret-filter.js +126 -0
- package/dist/memory/truth-store.d.ts +2 -1
- package/dist/memory/truth-store.js +1 -4
- package/dist/memory/types.d.ts +74 -24
- package/dist/memory/types.js +75 -5
- package/dist/memory/write-adapters.d.ts +98 -0
- package/dist/memory/write-adapters.js +242 -0
- package/dist/operations/owner-action-effects.d.ts +53 -0
- package/dist/operations/owner-action-effects.js +96 -0
- package/dist/provenance/source-ref.d.ts +1 -1
- package/dist/provenance/source-ref.js +0 -2
- package/dist/registry/corrections.d.ts +31 -0
- package/dist/registry/corrections.js +332 -0
- package/dist/registry/record-identity.d.ts +49 -0
- package/dist/registry/record-identity.js +133 -0
- package/dist/registry/store.d.ts +101 -0
- package/dist/registry/store.js +395 -0
- package/dist/registry/types.d.ts +28 -0
- package/dist/registry/types.js +5 -0
- package/dist/relevance-scorer.js +2 -2
- package/dist/runtime/agent-event-bus.d.ts +50 -0
- package/dist/runtime/agent-event-bus.js +101 -0
- package/dist/runtime/drivers/claude-cli-wrapper.d.ts +155 -0
- package/dist/runtime/drivers/claude-cli-wrapper.js +392 -0
- package/dist/runtime/drivers/cli-arg-redaction.d.ts +2 -0
- package/dist/runtime/drivers/cli-arg-redaction.js +18 -0
- package/dist/runtime/drivers/cli-secret-redaction.d.ts +17 -0
- package/dist/runtime/drivers/cli-secret-redaction.js +126 -0
- package/dist/runtime/drivers/codex-app-server-process.d.ts +277 -0
- package/dist/runtime/drivers/codex-app-server-process.js +2342 -0
- package/dist/runtime/drivers/codex-auxiliary-tools.d.ts +17 -0
- package/dist/runtime/drivers/codex-auxiliary-tools.js +267 -0
- package/dist/runtime/drivers/codex-home.d.ts +20 -0
- package/dist/runtime/drivers/codex-home.js +674 -0
- package/dist/runtime/drivers/codex-thread-registry.d.ts +63 -0
- package/dist/runtime/drivers/codex-thread-registry.js +433 -0
- package/dist/runtime/drivers/persistent-cli-adapter.d.ts +160 -0
- package/dist/runtime/drivers/persistent-cli-adapter.js +396 -0
- package/dist/runtime/drivers/persistent-cli-process.d.ts +424 -0
- package/dist/runtime/drivers/persistent-cli-process.js +1543 -0
- package/dist/runtime/drivers/types.d.ts +456 -0
- package/dist/runtime/drivers/types.js +110 -0
- package/dist/runtime/mailbox.d.ts +223 -0
- package/dist/runtime/mailbox.js +582 -0
- package/dist/runtime/model-run-store.d.ts +28 -0
- package/dist/{model-runs/store.js → runtime/model-run-store.js} +81 -41
- package/dist/{model-runs/types.d.ts → runtime/model-run-types.d.ts} +33 -4
- package/dist/{model-runs/types.js → runtime/model-run-types.js} +1 -1
- package/dist/runtime/native-effect-observer.d.ts +22 -0
- package/dist/runtime/native-effect-observer.js +103 -0
- package/dist/runtime/native-input-journal.d.ts +46 -0
- package/dist/runtime/native-input-journal.js +308 -0
- package/dist/runtime/native-prompt.d.ts +118 -0
- package/dist/runtime/native-prompt.js +496 -0
- package/dist/runtime/native-session.d.ts +10 -0
- package/dist/{agent-graph/index.js → runtime/native-session.js} +9 -6
- package/dist/runtime/native-tool-trace-observer.d.ts +5 -0
- package/dist/runtime/native-tool-trace-observer.js +65 -0
- package/dist/runtime/native-turn.d.ts +272 -0
- package/dist/runtime/native-turn.js +1041 -0
- package/dist/runtime/operations.d.ts +236 -0
- package/dist/runtime/operations.js +565 -0
- package/dist/runtime/post-tool-handler.d.ts +74 -0
- package/dist/runtime/post-tool-handler.js +137 -0
- package/dist/runtime/prompt-layers.d.ts +126 -0
- package/dist/runtime/prompt-layers.js +239 -0
- package/dist/runtime/runtime-process.d.ts +102 -0
- package/dist/runtime/runtime-process.js +206 -0
- package/dist/runtime/runtime.d.ts +278 -0
- package/dist/runtime/runtime.js +563 -0
- package/dist/runtime/session-pool.d.ts +176 -0
- package/dist/runtime/session-pool.js +369 -0
- package/dist/runtime/stimulus-payload.d.ts +5 -0
- package/dist/runtime/stimulus-payload.js +50 -0
- package/dist/runtime/subagent-bridge.d.ts +24 -0
- package/dist/{agent-graph/types.js → runtime/subagent-bridge.js} +1 -1
- package/dist/runtime/text-completion.d.ts +22 -0
- package/dist/{agent-situation/types.js → runtime/text-completion.js} +1 -1
- package/dist/runtime/token-estimator.d.ts +25 -0
- package/dist/runtime/token-estimator.js +75 -0
- package/dist/runtime/tool-trace-store.d.ts +22 -0
- package/dist/{model-runs → runtime}/tool-trace-store.js +46 -27
- package/dist/runtime/trace-summary.d.ts +5 -0
- package/dist/runtime/trace-summary.js +74 -0
- package/dist/runtime/turn-text.d.ts +23 -0
- package/dist/runtime/turn-text.js +41 -0
- package/dist/storage/database.d.ts +67 -0
- package/dist/storage/database.js +158 -0
- package/package.json +20 -34
- package/dist/agent-graph/alias-write.d.ts +0 -3
- package/dist/agent-graph/alias-write.js +0 -234
- package/dist/agent-graph/entity-resolve.d.ts +0 -3
- package/dist/agent-graph/entity-resolve.js +0 -271
- package/dist/agent-graph/errors.d.ts +0 -4
- package/dist/agent-graph/errors.js +0 -11
- package/dist/agent-graph/graph-query.d.ts +0 -5
- package/dist/agent-graph/graph-query.js +0 -360
- package/dist/agent-graph/index.d.ts +0 -6
- package/dist/agent-situation/builder.d.ts +0 -8
- package/dist/agent-situation/builder.js +0 -239
- package/dist/agent-situation/cache-key.d.ts +0 -4
- package/dist/agent-situation/cache-key.js +0 -64
- package/dist/agent-situation/index.d.ts +0 -7
- package/dist/agent-situation/index.js +0 -28
- package/dist/agent-situation/packet-store.d.ts +0 -27
- package/dist/agent-situation/packet-store.js +0 -228
- package/dist/agent-situation/ranking-policy.d.ts +0 -18
- package/dist/agent-situation/ranking-policy.js +0 -75
- package/dist/agent-situation/source-readers.d.ts +0 -52
- package/dist/agent-situation/source-readers.js +0 -300
- package/dist/agent-situation/types.d.ts +0 -195
- package/dist/cases/wiki-page-index.d.ts +0 -37
- package/dist/cases/wiki-page-index.js +0 -201
- package/dist/config-loader.d.ts +0 -68
- package/dist/config-loader.js +0 -239
- package/dist/connectors/event-index.d.ts +0 -24
- package/dist/connectors/event-index.js +0 -245
- package/dist/connectors/raw-query.d.ts +0 -40
- package/dist/connectors/raw-query.js +0 -412
- package/dist/connectors/types.d.ts +0 -117
- package/dist/connectors/types.js +0 -3
- package/dist/context-compile/boundary-defaults.d.ts +0 -12
- package/dist/context-compile/boundary-defaults.js +0 -105
- package/dist/context-compile/channel-grant.js +0 -66
- package/dist/context-compile/compiler-policy.d.ts +0 -39
- package/dist/context-compile/compiler-policy.js +0 -147
- package/dist/context-compile/compiler.d.ts +0 -18
- package/dist/context-compile/compiler.js +0 -404
- package/dist/context-compile/index.d.ts +0 -10
- package/dist/context-compile/index.js +0 -26
- package/dist/context-compile/packet-store.d.ts +0 -8
- package/dist/context-compile/packet-store.js +0 -239
- package/dist/context-compile/ref.d.ts +0 -7
- package/dist/context-compile/ref.js +0 -102
- package/dist/context-compile/source-readers.d.ts +0 -70
- package/dist/context-compile/source-readers.js +0 -840
- package/dist/context-compile/types.d.ts +0 -155
- package/dist/context-compile/types.js +0 -11
- package/dist/context-compile/visibility.d.ts +0 -21
- package/dist/context-compile/visibility.js +0 -224
- package/dist/decision-tracker.d.ts +0 -206
- package/dist/decision-tracker.js +0 -481
- package/dist/edges/ref-validation.d.ts +0 -7
- package/dist/edges/ref-validation.js +0 -321
- package/dist/edges/store.d.ts +0 -8
- package/dist/edges/store.js +0 -129
- package/dist/embedding-client.d.ts +0 -28
- package/dist/embedding-client.js +0 -53
- package/dist/embedding-server/index.d.ts +0 -67
- package/dist/embedding-server/index.js +0 -405
- package/dist/embedding-server/mobile/auth.d.ts +0 -44
- package/dist/embedding-server/mobile/auth.js +0 -150
- package/dist/embedding-server/mobile/daemon.d.ts +0 -129
- package/dist/embedding-server/mobile/daemon.js +0 -313
- package/dist/embedding-server/mobile/output-parser.d.ts +0 -115
- package/dist/embedding-server/mobile/output-parser.js +0 -241
- package/dist/embedding-server/mobile/session-api.d.ts +0 -57
- package/dist/embedding-server/mobile/session-api.js +0 -261
- package/dist/embedding-server/mobile/session-manager.d.ts +0 -138
- package/dist/embedding-server/mobile/session-manager.js +0 -378
- package/dist/embedding-server/mobile/websocket-handler.d.ts +0 -137
- package/dist/embedding-server/mobile/websocket-handler.js +0 -486
- package/dist/embeddings.d.ts +0 -68
- package/dist/embeddings.js +0 -244
- package/dist/entities/audit-metrics.d.ts +0 -68
- package/dist/entities/audit-metrics.js +0 -124
- package/dist/entities/candidate-generator.d.ts +0 -8
- package/dist/entities/candidate-generator.js +0 -24
- package/dist/entities/entity-linked-decision-counts.d.ts +0 -2
- package/dist/entities/entity-linked-decision-counts.js +0 -29
- package/dist/entities/entity-list.d.ts +0 -22
- package/dist/entities/entity-list.js +0 -3
- package/dist/entities/entity-orphan-list.d.ts +0 -17
- package/dist/entities/entity-orphan-list.js +0 -3
- package/dist/entities/entity-search.d.ts +0 -20
- package/dist/entities/entity-search.js +0 -3
- package/dist/entities/errors.d.ts +0 -55
- package/dist/entities/errors.js +0 -100
- package/dist/entities/lineage-store.d.ts +0 -28
- package/dist/entities/lineage-store.js +0 -204
- package/dist/entities/normalization.d.ts +0 -14
- package/dist/entities/normalization.js +0 -63
- package/dist/entities/policy-store.d.ts +0 -8
- package/dist/entities/policy-store.js +0 -75
- package/dist/entities/policy-types.d.ts +0 -72
- package/dist/entities/policy-types.js +0 -59
- package/dist/entities/projection.d.ts +0 -8
- package/dist/entities/projection.js +0 -82
- package/dist/entities/provenance-query.d.ts +0 -32
- package/dist/entities/provenance-query.js +0 -3
- package/dist/entities/read-identity.d.ts +0 -31
- package/dist/entities/read-identity.js +0 -264
- package/dist/entities/recall-bridge.d.ts +0 -5
- package/dist/entities/recall-bridge.js +0 -171
- package/dist/entities/resolution-engine.d.ts +0 -8
- package/dist/entities/resolution-engine.js +0 -3
- package/dist/entities/rollback-preview.d.ts +0 -35
- package/dist/entities/rollback-preview.js +0 -3
- package/dist/entities/source-locator.d.ts +0 -3
- package/dist/entities/source-locator.js +0 -32
- package/dist/entities/store.d.ts +0 -69
- package/dist/entities/store.js +0 -544
- package/dist/entities/types.d.ts +0 -166
- package/dist/entities/types.js +0 -30
- package/dist/memory/extraction-prompt.d.ts +0 -4
- package/dist/memory/extraction-prompt.js +0 -89
- package/dist/memory/scope-backfill.d.ts +0 -14
- package/dist/memory/scope-backfill.js +0 -3
- package/dist/memory/scope-store.d.ts +0 -4
- package/dist/memory/scope-store.js +0 -9
- package/dist/memory-store.d.ts +0 -87
- package/dist/memory-store.js +0 -78
- package/dist/model-runs/store.d.ts +0 -13
- package/dist/model-runs/tool-trace-store.d.ts +0 -8
- package/dist/notification-manager.d.ts +0 -7
- package/dist/notification-manager.js +0 -12
- package/dist/outcome-tracker.d.ts +0 -151
- package/dist/outcome-tracker.js +0 -271
- package/dist/query-intent.d.ts +0 -23
- package/dist/query-intent.js +0 -114
- package/dist/runtime/trusted-provenance.d.ts +0 -3
- package/dist/runtime/trusted-provenance.js +0 -6
- package/dist/search/question-type.d.ts +0 -5
- package/dist/search/question-type.js +0 -41
- package/dist/test-utils.d.ts +0 -80
- package/dist/test-utils.js +0 -218
- package/dist/tier-validator.d.ts +0 -43
- package/dist/tier-validator.js +0 -159
- package/dist/time-formatter.d.ts +0 -25
- package/dist/time-formatter.js +0 -93
- /package/dist/{search → knowledge}/feedback-store.d.ts +0 -0
- /package/dist/{search → knowledge}/feedback-store.js +0 -0
- /package/dist/{search → knowledge}/ranker-features.d.ts +0 -0
- /package/dist/{search → knowledge}/ranker-rescore.d.ts +0 -0
- /package/dist/{search → knowledge}/ranker-rescore.js +0 -0
- /package/dist/{search → knowledge}/ranker-trainer.d.ts +0 -0
- /package/dist/{search → knowledge}/ranker-trainer.js +0 -0
- /package/dist/{search → knowledge}/search-quality.js +0 -0
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Session Pool - Claude CLI Session Reuse Manager
|
|
3
|
+
*
|
|
4
|
+
* Manages Claude CLI session IDs per channel to enable conversation continuity.
|
|
5
|
+
* Instead of creating new sessions for each message, reuses existing sessions
|
|
6
|
+
* so Claude CLI maintains its own conversation history.
|
|
7
|
+
*
|
|
8
|
+
* Benefits:
|
|
9
|
+
* - 6x token reduction (no manual history injection needed)
|
|
10
|
+
* - Natural conversation flow (Claude remembers context)
|
|
11
|
+
* - Automatic summarization by Claude when context fills up
|
|
12
|
+
*/
|
|
13
|
+
/**
|
|
14
|
+
* Session entry with metadata
|
|
15
|
+
*/
|
|
16
|
+
interface SessionEntry {
|
|
17
|
+
/** Claude CLI session ID */
|
|
18
|
+
sessionId: string;
|
|
19
|
+
/** Last activity timestamp */
|
|
20
|
+
lastActive: number;
|
|
21
|
+
/** Message count in this session */
|
|
22
|
+
messageCount: number;
|
|
23
|
+
/** Creation timestamp */
|
|
24
|
+
createdAt: number;
|
|
25
|
+
/** Whether session is currently in use (locked) */
|
|
26
|
+
inUse: boolean;
|
|
27
|
+
/** Legacy context occupancy field; durable runtimes own compaction, so this stays zero */
|
|
28
|
+
totalInputTokens: number;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Session Pool configuration
|
|
32
|
+
*/
|
|
33
|
+
export interface SessionPoolConfig {
|
|
34
|
+
/** Session timeout in milliseconds (default: 30 minutes) */
|
|
35
|
+
sessionTimeoutMs?: number;
|
|
36
|
+
/** Maximum sessions to keep in pool (default: 100) */
|
|
37
|
+
maxSessions?: number;
|
|
38
|
+
/** Cleanup interval in milliseconds (default: 5 minutes) */
|
|
39
|
+
cleanupIntervalMs?: number;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Session Pool for Claude CLI session management
|
|
43
|
+
*
|
|
44
|
+
* Key design:
|
|
45
|
+
* - Channel key format: "{source}:{channelId}" (e.g., "discord:123456")
|
|
46
|
+
* - Sessions expire after timeout (default 30 min)
|
|
47
|
+
* - Automatic cleanup of stale sessions
|
|
48
|
+
*/
|
|
49
|
+
export declare class SessionPool {
|
|
50
|
+
private sessions;
|
|
51
|
+
private config;
|
|
52
|
+
private cleanupTimer;
|
|
53
|
+
constructor(config?: SessionPoolConfig);
|
|
54
|
+
/**
|
|
55
|
+
* Get or create session ID for a channel
|
|
56
|
+
*
|
|
57
|
+
* With --no-session-persistence flag, Claude CLI doesn't lock session IDs.
|
|
58
|
+
* This allows session reuse for conversation continuity.
|
|
59
|
+
*
|
|
60
|
+
* Durable backends own model-aware context compaction. This pool rotates only
|
|
61
|
+
* for explicit resets and session-lifecycle expiry.
|
|
62
|
+
* If session is in use, returns busy=true immediately (no waiting).
|
|
63
|
+
*
|
|
64
|
+
* @param channelKey - Channel identifier (format: "{source}:{channelId}")
|
|
65
|
+
* @returns Object with sessionId, isNew flag, and busy status
|
|
66
|
+
*/
|
|
67
|
+
getSession(channelKey: string): {
|
|
68
|
+
sessionId: string;
|
|
69
|
+
isNew: boolean;
|
|
70
|
+
busy: boolean;
|
|
71
|
+
};
|
|
72
|
+
/**
|
|
73
|
+
* Read-only check for session busy status
|
|
74
|
+
* Does NOT modify session state (no lock, no messageCount increment)
|
|
75
|
+
*
|
|
76
|
+
* @param channelKey - Channel identifier
|
|
77
|
+
* @returns Object with sessionId (if exists) and busy status
|
|
78
|
+
*/
|
|
79
|
+
peekSession(channelKey: string): {
|
|
80
|
+
sessionId?: string;
|
|
81
|
+
busy: boolean;
|
|
82
|
+
};
|
|
83
|
+
/**
|
|
84
|
+
* Preserve the legacy token-status interface without interpreting billing
|
|
85
|
+
* usage as context occupancy. Claude Code and the Codex app-server
|
|
86
|
+
* each compact from their own model-aware request state.
|
|
87
|
+
*
|
|
88
|
+
* @param channelKey - Channel identifier
|
|
89
|
+
* @param _inputTokens - Usage telemetry from this run; recorded separately by AgentLoop
|
|
90
|
+
* @param _backend - Runtime that owns the durable session
|
|
91
|
+
* @returns Zero occupancy because the host has no authoritative context-size signal
|
|
92
|
+
*/
|
|
93
|
+
updateTokens(channelKey: string, _inputTokens: number, _backend?: 'claude' | 'codex'): {
|
|
94
|
+
totalTokens: number;
|
|
95
|
+
nearThreshold: boolean;
|
|
96
|
+
};
|
|
97
|
+
/**
|
|
98
|
+
* Get current token usage for a session
|
|
99
|
+
*/
|
|
100
|
+
getTokenUsage(channelKey: string): number;
|
|
101
|
+
/**
|
|
102
|
+
* Legacy method for backward compatibility
|
|
103
|
+
* @deprecated Use getSession() instead
|
|
104
|
+
*/
|
|
105
|
+
getSessionId(channelKey: string): string;
|
|
106
|
+
/**
|
|
107
|
+
* Release a session after use
|
|
108
|
+
* This allows the session to be reused by future requests
|
|
109
|
+
*/
|
|
110
|
+
releaseSession(channelKey: string, expectedSessionId?: string): void;
|
|
111
|
+
/**
|
|
112
|
+
* Override session ID for a channel (e.g., when backend returns its own thread ID)
|
|
113
|
+
*/
|
|
114
|
+
setSessionId(channelKey: string, sessionId: string): void;
|
|
115
|
+
/**
|
|
116
|
+
* Create a new session for a channel
|
|
117
|
+
*/
|
|
118
|
+
private createSession;
|
|
119
|
+
/**
|
|
120
|
+
* Force create a new session (for /clear command)
|
|
121
|
+
*/
|
|
122
|
+
resetSession(channelKey: string): string;
|
|
123
|
+
/**
|
|
124
|
+
* Remove a session without creating a replacement.
|
|
125
|
+
*
|
|
126
|
+
* Use this after a failed reset attempt: the next request must observe a
|
|
127
|
+
* genuinely new session and rebuild its complete policy prompt.
|
|
128
|
+
*/
|
|
129
|
+
invalidateSession(channelKey: string, expectedSessionId?: string): void;
|
|
130
|
+
/**
|
|
131
|
+
* Check if a session exists and is active
|
|
132
|
+
*/
|
|
133
|
+
hasActiveSession(channelKey: string): boolean;
|
|
134
|
+
/**
|
|
135
|
+
* Get session info for a channel
|
|
136
|
+
*/
|
|
137
|
+
getSessionInfo(channelKey: string): SessionEntry | null;
|
|
138
|
+
/**
|
|
139
|
+
* Get all active sessions (for debugging/monitoring)
|
|
140
|
+
*/
|
|
141
|
+
listSessions(): Map<string, SessionEntry>;
|
|
142
|
+
/**
|
|
143
|
+
* Get active session count
|
|
144
|
+
*/
|
|
145
|
+
getActiveSessionCount(): number;
|
|
146
|
+
/**
|
|
147
|
+
* Evict the oldest (least recently used) session
|
|
148
|
+
*/
|
|
149
|
+
private evictOldestSession;
|
|
150
|
+
/**
|
|
151
|
+
* Clean up expired sessions and force-release stuck inUse sessions
|
|
152
|
+
*/
|
|
153
|
+
cleanup(): number;
|
|
154
|
+
/**
|
|
155
|
+
* Start periodic cleanup timer
|
|
156
|
+
*/
|
|
157
|
+
private startCleanupTimer;
|
|
158
|
+
/**
|
|
159
|
+
* Stop cleanup timer and clear all sessions
|
|
160
|
+
*/
|
|
161
|
+
dispose(): void;
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Get global session pool instance
|
|
165
|
+
*/
|
|
166
|
+
export declare function getSessionPool(): SessionPool;
|
|
167
|
+
/**
|
|
168
|
+
* Set global session pool instance (for testing)
|
|
169
|
+
*/
|
|
170
|
+
export declare function setSessionPool(pool: SessionPool): void;
|
|
171
|
+
/**
|
|
172
|
+
* Build channel key from source and channel ID
|
|
173
|
+
*/
|
|
174
|
+
export declare function buildChannelKey(source: string, channelId: string): string;
|
|
175
|
+
export {};
|
|
176
|
+
//# sourceMappingURL=session-pool.d.ts.map
|
|
@@ -0,0 +1,369 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Session Pool - Claude CLI Session Reuse Manager
|
|
4
|
+
*
|
|
5
|
+
* Manages Claude CLI session IDs per channel to enable conversation continuity.
|
|
6
|
+
* Instead of creating new sessions for each message, reuses existing sessions
|
|
7
|
+
* so Claude CLI maintains its own conversation history.
|
|
8
|
+
*
|
|
9
|
+
* Benefits:
|
|
10
|
+
* - 6x token reduction (no manual history injection needed)
|
|
11
|
+
* - Natural conversation flow (Claude remembers context)
|
|
12
|
+
* - Automatic summarization by Claude when context fills up
|
|
13
|
+
*/
|
|
14
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
15
|
+
if (k2 === undefined) k2 = k;
|
|
16
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
17
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
18
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
19
|
+
}
|
|
20
|
+
Object.defineProperty(o, k2, desc);
|
|
21
|
+
}) : (function(o, m, k, k2) {
|
|
22
|
+
if (k2 === undefined) k2 = k;
|
|
23
|
+
o[k2] = m[k];
|
|
24
|
+
}));
|
|
25
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
26
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
27
|
+
}) : function(o, v) {
|
|
28
|
+
o["default"] = v;
|
|
29
|
+
});
|
|
30
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
31
|
+
var ownKeys = function(o) {
|
|
32
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
33
|
+
var ar = [];
|
|
34
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
35
|
+
return ar;
|
|
36
|
+
};
|
|
37
|
+
return ownKeys(o);
|
|
38
|
+
};
|
|
39
|
+
return function (mod) {
|
|
40
|
+
if (mod && mod.__esModule) return mod;
|
|
41
|
+
var result = {};
|
|
42
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
43
|
+
__setModuleDefault(result, mod);
|
|
44
|
+
return result;
|
|
45
|
+
};
|
|
46
|
+
})();
|
|
47
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
48
|
+
exports.SessionPool = void 0;
|
|
49
|
+
exports.getSessionPool = getSessionPool;
|
|
50
|
+
exports.setSessionPool = setSessionPool;
|
|
51
|
+
exports.buildChannelKey = buildChannelKey;
|
|
52
|
+
const crypto_1 = require("crypto");
|
|
53
|
+
const debugLogger = __importStar(require("../debug-logger.js"));
|
|
54
|
+
const { DebugLogger } = debugLogger;
|
|
55
|
+
const logger = new DebugLogger('SessionPool');
|
|
56
|
+
// Defaults a caller that states nothing gets. The product reads its own
|
|
57
|
+
// config and passes the numbers; a pool does not open a config file.
|
|
58
|
+
const DEFAULT_SESSION_TIMEOUT_MS = 1_800_000;
|
|
59
|
+
const DEFAULT_MAX_SESSIONS = 100;
|
|
60
|
+
const DEFAULT_CLEANUP_INTERVAL_MS = 300_000;
|
|
61
|
+
/**
|
|
62
|
+
* Session Pool for Claude CLI session management
|
|
63
|
+
*
|
|
64
|
+
* Key design:
|
|
65
|
+
* - Channel key format: "{source}:{channelId}" (e.g., "discord:123456")
|
|
66
|
+
* - Sessions expire after timeout (default 30 min)
|
|
67
|
+
* - Automatic cleanup of stale sessions
|
|
68
|
+
*/
|
|
69
|
+
class SessionPool {
|
|
70
|
+
sessions = new Map();
|
|
71
|
+
config;
|
|
72
|
+
cleanupTimer = null;
|
|
73
|
+
constructor(config = {}) {
|
|
74
|
+
this.config = {
|
|
75
|
+
sessionTimeoutMs: config.sessionTimeoutMs ?? DEFAULT_SESSION_TIMEOUT_MS,
|
|
76
|
+
maxSessions: config.maxSessions ?? DEFAULT_MAX_SESSIONS,
|
|
77
|
+
cleanupIntervalMs: config.cleanupIntervalMs ?? DEFAULT_CLEANUP_INTERVAL_MS,
|
|
78
|
+
};
|
|
79
|
+
// Start periodic cleanup
|
|
80
|
+
this.startCleanupTimer();
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Get or create session ID for a channel
|
|
84
|
+
*
|
|
85
|
+
* With --no-session-persistence flag, Claude CLI doesn't lock session IDs.
|
|
86
|
+
* This allows session reuse for conversation continuity.
|
|
87
|
+
*
|
|
88
|
+
* Durable backends own model-aware context compaction. This pool rotates only
|
|
89
|
+
* for explicit resets and session-lifecycle expiry.
|
|
90
|
+
* If session is in use, returns busy=true immediately (no waiting).
|
|
91
|
+
*
|
|
92
|
+
* @param channelKey - Channel identifier (format: "{source}:{channelId}")
|
|
93
|
+
* @returns Object with sessionId, isNew flag, and busy status
|
|
94
|
+
*/
|
|
95
|
+
getSession(channelKey) {
|
|
96
|
+
const existing = this.sessions.get(channelKey);
|
|
97
|
+
const now = Date.now();
|
|
98
|
+
// Check if existing session is still valid
|
|
99
|
+
if (existing) {
|
|
100
|
+
const isExpired = now - existing.lastActive > this.config.sessionTimeoutMs;
|
|
101
|
+
if (isExpired) {
|
|
102
|
+
this.sessions.delete(channelKey);
|
|
103
|
+
logger.info(`Session expired for ${channelKey}, creating new one`);
|
|
104
|
+
}
|
|
105
|
+
else if (existing.inUse) {
|
|
106
|
+
// Session is currently in use - return busy immediately
|
|
107
|
+
// Still update lastActive and messageCount for queued messages
|
|
108
|
+
existing.lastActive = now;
|
|
109
|
+
existing.messageCount++;
|
|
110
|
+
logger.debug(`Session busy for ${channelKey}, will be queued`);
|
|
111
|
+
return { sessionId: existing.sessionId, isNew: false, busy: true };
|
|
112
|
+
}
|
|
113
|
+
else {
|
|
114
|
+
// Reuse existing session
|
|
115
|
+
existing.lastActive = now;
|
|
116
|
+
existing.messageCount++;
|
|
117
|
+
existing.inUse = true; // Lock the session
|
|
118
|
+
logger.debug(`Reusing session for ${channelKey}: ${existing.sessionId} (msg #${existing.messageCount})`);
|
|
119
|
+
return { sessionId: existing.sessionId, isNew: false, busy: false };
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
// Create new session
|
|
123
|
+
const sessionId = this.createSession(channelKey);
|
|
124
|
+
return { sessionId, isNew: true, busy: false };
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Read-only check for session busy status
|
|
128
|
+
* Does NOT modify session state (no lock, no messageCount increment)
|
|
129
|
+
*
|
|
130
|
+
* @param channelKey - Channel identifier
|
|
131
|
+
* @returns Object with sessionId (if exists) and busy status
|
|
132
|
+
*/
|
|
133
|
+
peekSession(channelKey) {
|
|
134
|
+
const existing = this.sessions.get(channelKey);
|
|
135
|
+
if (!existing) {
|
|
136
|
+
return { busy: false };
|
|
137
|
+
}
|
|
138
|
+
return { sessionId: existing.sessionId, busy: existing.inUse };
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Preserve the legacy token-status interface without interpreting billing
|
|
142
|
+
* usage as context occupancy. Claude Code and the Codex app-server
|
|
143
|
+
* each compact from their own model-aware request state.
|
|
144
|
+
*
|
|
145
|
+
* @param channelKey - Channel identifier
|
|
146
|
+
* @param _inputTokens - Usage telemetry from this run; recorded separately by AgentLoop
|
|
147
|
+
* @param _backend - Runtime that owns the durable session
|
|
148
|
+
* @returns Zero occupancy because the host has no authoritative context-size signal
|
|
149
|
+
*/
|
|
150
|
+
updateTokens(channelKey, _inputTokens, _backend) {
|
|
151
|
+
const existing = this.sessions.get(channelKey);
|
|
152
|
+
if (!existing) {
|
|
153
|
+
return { totalTokens: 0, nearThreshold: false };
|
|
154
|
+
}
|
|
155
|
+
existing.totalInputTokens = 0;
|
|
156
|
+
return { totalTokens: 0, nearThreshold: false };
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Get current token usage for a session
|
|
160
|
+
*/
|
|
161
|
+
getTokenUsage(channelKey) {
|
|
162
|
+
const existing = this.sessions.get(channelKey);
|
|
163
|
+
return existing?.totalInputTokens ?? 0;
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Legacy method for backward compatibility
|
|
167
|
+
* @deprecated Use getSession() instead
|
|
168
|
+
*/
|
|
169
|
+
getSessionId(channelKey) {
|
|
170
|
+
return this.getSession(channelKey).sessionId;
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Release a session after use
|
|
174
|
+
* This allows the session to be reused by future requests
|
|
175
|
+
*/
|
|
176
|
+
releaseSession(channelKey, expectedSessionId) {
|
|
177
|
+
const existing = this.sessions.get(channelKey);
|
|
178
|
+
if (existing && (!expectedSessionId || existing.sessionId === expectedSessionId)) {
|
|
179
|
+
existing.inUse = false;
|
|
180
|
+
console.log(`[SessionPool] Released session for ${channelKey}: ${existing.sessionId}`);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* Override session ID for a channel (e.g., when backend returns its own thread ID)
|
|
185
|
+
*/
|
|
186
|
+
setSessionId(channelKey, sessionId) {
|
|
187
|
+
const existing = this.sessions.get(channelKey);
|
|
188
|
+
const now = Date.now();
|
|
189
|
+
if (existing) {
|
|
190
|
+
existing.sessionId = sessionId;
|
|
191
|
+
existing.lastActive = now;
|
|
192
|
+
existing.inUse = true;
|
|
193
|
+
console.log(`[SessionPool] Updated session for ${channelKey}: ${sessionId}`);
|
|
194
|
+
return;
|
|
195
|
+
}
|
|
196
|
+
const entry = {
|
|
197
|
+
sessionId,
|
|
198
|
+
lastActive: now,
|
|
199
|
+
messageCount: 1,
|
|
200
|
+
createdAt: now,
|
|
201
|
+
inUse: true,
|
|
202
|
+
totalInputTokens: 0,
|
|
203
|
+
};
|
|
204
|
+
this.sessions.set(channelKey, entry);
|
|
205
|
+
console.log(`[SessionPool] Created session for ${channelKey}: ${sessionId}`);
|
|
206
|
+
}
|
|
207
|
+
/**
|
|
208
|
+
* Create a new session for a channel
|
|
209
|
+
*/
|
|
210
|
+
createSession(channelKey) {
|
|
211
|
+
const now = Date.now();
|
|
212
|
+
const sessionId = (0, crypto_1.randomUUID)();
|
|
213
|
+
// Enforce max sessions limit
|
|
214
|
+
if (this.sessions.size >= this.config.maxSessions) {
|
|
215
|
+
this.evictOldestSession();
|
|
216
|
+
}
|
|
217
|
+
const entry = {
|
|
218
|
+
sessionId,
|
|
219
|
+
lastActive: now,
|
|
220
|
+
messageCount: 1,
|
|
221
|
+
createdAt: now,
|
|
222
|
+
inUse: true, // Lock on creation
|
|
223
|
+
totalInputTokens: 0,
|
|
224
|
+
};
|
|
225
|
+
this.sessions.set(channelKey, entry);
|
|
226
|
+
console.log(`[SessionPool] Created new session for ${channelKey}: ${sessionId}`);
|
|
227
|
+
return sessionId;
|
|
228
|
+
}
|
|
229
|
+
/**
|
|
230
|
+
* Force create a new session (for /clear command)
|
|
231
|
+
*/
|
|
232
|
+
resetSession(channelKey) {
|
|
233
|
+
this.sessions.delete(channelKey);
|
|
234
|
+
return this.createSession(channelKey);
|
|
235
|
+
}
|
|
236
|
+
/**
|
|
237
|
+
* Remove a session without creating a replacement.
|
|
238
|
+
*
|
|
239
|
+
* Use this after a failed reset attempt: the next request must observe a
|
|
240
|
+
* genuinely new session and rebuild its complete policy prompt.
|
|
241
|
+
*/
|
|
242
|
+
invalidateSession(channelKey, expectedSessionId) {
|
|
243
|
+
const existing = this.sessions.get(channelKey);
|
|
244
|
+
if (existing && expectedSessionId && existing.sessionId !== expectedSessionId) {
|
|
245
|
+
return;
|
|
246
|
+
}
|
|
247
|
+
if (existing && this.sessions.delete(channelKey)) {
|
|
248
|
+
console.log(`[SessionPool] Invalidated session for ${channelKey}`);
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
/**
|
|
252
|
+
* Check if a session exists and is active
|
|
253
|
+
*/
|
|
254
|
+
hasActiveSession(channelKey) {
|
|
255
|
+
const existing = this.sessions.get(channelKey);
|
|
256
|
+
if (!existing) {
|
|
257
|
+
return false;
|
|
258
|
+
}
|
|
259
|
+
const isExpired = Date.now() - existing.lastActive > this.config.sessionTimeoutMs;
|
|
260
|
+
return !isExpired;
|
|
261
|
+
}
|
|
262
|
+
/**
|
|
263
|
+
* Get session info for a channel
|
|
264
|
+
*/
|
|
265
|
+
getSessionInfo(channelKey) {
|
|
266
|
+
return this.sessions.get(channelKey) || null;
|
|
267
|
+
}
|
|
268
|
+
/**
|
|
269
|
+
* Get all active sessions (for debugging/monitoring)
|
|
270
|
+
*/
|
|
271
|
+
listSessions() {
|
|
272
|
+
return new Map(this.sessions);
|
|
273
|
+
}
|
|
274
|
+
/**
|
|
275
|
+
* Get active session count
|
|
276
|
+
*/
|
|
277
|
+
getActiveSessionCount() {
|
|
278
|
+
return this.sessions.size;
|
|
279
|
+
}
|
|
280
|
+
/**
|
|
281
|
+
* Evict the oldest (least recently used) session
|
|
282
|
+
*/
|
|
283
|
+
evictOldestSession() {
|
|
284
|
+
let oldestKey = null;
|
|
285
|
+
let oldestTime = Infinity;
|
|
286
|
+
for (const [key, entry] of this.sessions) {
|
|
287
|
+
if (entry.lastActive < oldestTime) {
|
|
288
|
+
oldestTime = entry.lastActive;
|
|
289
|
+
oldestKey = key;
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
if (oldestKey) {
|
|
293
|
+
this.sessions.delete(oldestKey);
|
|
294
|
+
console.log(`[SessionPool] Evicted oldest session: ${oldestKey}`);
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
/**
|
|
298
|
+
* Clean up expired sessions and force-release stuck inUse sessions
|
|
299
|
+
*/
|
|
300
|
+
cleanup() {
|
|
301
|
+
const now = Date.now();
|
|
302
|
+
let cleaned = 0;
|
|
303
|
+
const STUCK_THRESHOLD_MS = 15 * 60 * 1000; // 15 minutes
|
|
304
|
+
for (const [key, entry] of this.sessions) {
|
|
305
|
+
if (now - entry.lastActive > this.config.sessionTimeoutMs) {
|
|
306
|
+
this.sessions.delete(key);
|
|
307
|
+
cleaned++;
|
|
308
|
+
}
|
|
309
|
+
else if (entry.inUse && now - entry.lastActive > STUCK_THRESHOLD_MS) {
|
|
310
|
+
entry.inUse = false;
|
|
311
|
+
console.log(`[SessionPool] Force-released stuck session for ${key} (inUse for ${Math.round((now - entry.lastActive) / 1000)}s)`);
|
|
312
|
+
cleaned++;
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
if (cleaned > 0) {
|
|
316
|
+
console.log(`[SessionPool] Cleaned up ${cleaned} expired/stuck sessions`);
|
|
317
|
+
}
|
|
318
|
+
return cleaned;
|
|
319
|
+
}
|
|
320
|
+
/**
|
|
321
|
+
* Start periodic cleanup timer
|
|
322
|
+
*/
|
|
323
|
+
startCleanupTimer() {
|
|
324
|
+
if (this.cleanupTimer)
|
|
325
|
+
return;
|
|
326
|
+
this.cleanupTimer = setInterval(() => {
|
|
327
|
+
this.cleanup();
|
|
328
|
+
}, this.config.cleanupIntervalMs);
|
|
329
|
+
// Don't prevent process exit
|
|
330
|
+
this.cleanupTimer.unref();
|
|
331
|
+
}
|
|
332
|
+
/**
|
|
333
|
+
* Stop cleanup timer and clear all sessions
|
|
334
|
+
*/
|
|
335
|
+
dispose() {
|
|
336
|
+
if (this.cleanupTimer) {
|
|
337
|
+
clearInterval(this.cleanupTimer);
|
|
338
|
+
this.cleanupTimer = null;
|
|
339
|
+
}
|
|
340
|
+
this.sessions.clear();
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
exports.SessionPool = SessionPool;
|
|
344
|
+
/**
|
|
345
|
+
* Global session pool instance
|
|
346
|
+
*/
|
|
347
|
+
let globalSessionPool = null;
|
|
348
|
+
/**
|
|
349
|
+
* Get global session pool instance
|
|
350
|
+
*/
|
|
351
|
+
function getSessionPool() {
|
|
352
|
+
if (!globalSessionPool) {
|
|
353
|
+
globalSessionPool = new SessionPool();
|
|
354
|
+
}
|
|
355
|
+
return globalSessionPool;
|
|
356
|
+
}
|
|
357
|
+
/**
|
|
358
|
+
* Set global session pool instance (for testing)
|
|
359
|
+
*/
|
|
360
|
+
function setSessionPool(pool) {
|
|
361
|
+
globalSessionPool = pool;
|
|
362
|
+
}
|
|
363
|
+
/**
|
|
364
|
+
* Build channel key from source and channel ID
|
|
365
|
+
*/
|
|
366
|
+
function buildChannelKey(source, channelId) {
|
|
367
|
+
return `${source}:${channelId}`;
|
|
368
|
+
}
|
|
369
|
+
//# sourceMappingURL=session-pool.js.map
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { JsonValue } from '../memory/judgment-types.js';
|
|
2
|
+
/** Reject lossy JavaScript values before a producer receives a durable receipt. */
|
|
3
|
+
export declare function encodeStimulusPayload(value: unknown): string | null;
|
|
4
|
+
export declare function decodeStimulusPayload(encoded: string | null): JsonValue | undefined;
|
|
5
|
+
//# sourceMappingURL=stimulus-payload.d.ts.map
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.encodeStimulusPayload = encodeStimulusPayload;
|
|
4
|
+
exports.decodeStimulusPayload = decodeStimulusPayload;
|
|
5
|
+
const canonicalize_js_1 = require("../canonicalize.js");
|
|
6
|
+
/** Reject lossy JavaScript values before a producer receives a durable receipt. */
|
|
7
|
+
function encodeStimulusPayload(value) {
|
|
8
|
+
if (value === undefined)
|
|
9
|
+
return null;
|
|
10
|
+
const ancestors = new Set();
|
|
11
|
+
const visit = (item) => {
|
|
12
|
+
if (item === null || typeof item === 'string' || typeof item === 'boolean')
|
|
13
|
+
return;
|
|
14
|
+
if (typeof item === 'number' && Number.isFinite(item))
|
|
15
|
+
return;
|
|
16
|
+
if (typeof item !== 'object' || item === null) {
|
|
17
|
+
throw new Error('Mailbox payload must contain only JSON values');
|
|
18
|
+
}
|
|
19
|
+
const array = Array.isArray(item);
|
|
20
|
+
const prototype = Object.getPrototypeOf(item);
|
|
21
|
+
if (!array && prototype !== Object.prototype && prototype !== null) {
|
|
22
|
+
throw new Error('Mailbox payload requires plain JSON objects');
|
|
23
|
+
}
|
|
24
|
+
if (ancestors.has(item))
|
|
25
|
+
throw new Error('Mailbox payload cannot contain cycles');
|
|
26
|
+
ancestors.add(item);
|
|
27
|
+
const keys = Reflect.ownKeys(item).filter((key) => !array || key !== 'length');
|
|
28
|
+
if (array && (keys.length !== item.length || keys.some((key, i) => key !== String(i)))) {
|
|
29
|
+
throw new Error('Mailbox payload requires dense JSON arrays');
|
|
30
|
+
}
|
|
31
|
+
for (const key of keys) {
|
|
32
|
+
const descriptor = Object.getOwnPropertyDescriptor(item, key);
|
|
33
|
+
if (typeof key !== 'string' || !descriptor.enumerable || !('value' in descriptor)) {
|
|
34
|
+
throw new Error('Mailbox payload requires enumerable JSON data properties');
|
|
35
|
+
}
|
|
36
|
+
visit(descriptor.value);
|
|
37
|
+
}
|
|
38
|
+
ancestors.delete(item);
|
|
39
|
+
};
|
|
40
|
+
visit(value);
|
|
41
|
+
return (0, canonicalize_js_1.canonicalizeJSON)(value);
|
|
42
|
+
}
|
|
43
|
+
function decodeStimulusPayload(encoded) {
|
|
44
|
+
if (encoded === null)
|
|
45
|
+
return undefined;
|
|
46
|
+
const value = JSON.parse(encoded);
|
|
47
|
+
encodeStimulusPayload(value);
|
|
48
|
+
return value;
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=stimulus-payload.js.map
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { HostToolBridge } from './drivers/types.js';
|
|
2
|
+
/** What the host is asked for when a native harness identifies a child. */
|
|
3
|
+
export interface SubagentBridgeRequest {
|
|
4
|
+
/** The PARENT's session key; a child never owns a session of its own. */
|
|
5
|
+
sessionKey: string;
|
|
6
|
+
parentThreadId: string;
|
|
7
|
+
agentThreadId: string;
|
|
8
|
+
agentPath: string;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* One child's own authority: its tools and the release that closes its run.
|
|
12
|
+
*
|
|
13
|
+
* The native transport chooses the terminal observation: Codex's child event or
|
|
14
|
+
* the enclosing Claude turn's settlement after its socket calls drain. `unknown`
|
|
15
|
+
* means completion was not confirmed and must not be recorded as success.
|
|
16
|
+
*/
|
|
17
|
+
export interface SubagentBridge {
|
|
18
|
+
bridge: HostToolBridge;
|
|
19
|
+
release: (outcome: {
|
|
20
|
+
status: 'completed' | 'failed' | 'interrupted' | 'unknown';
|
|
21
|
+
error?: string;
|
|
22
|
+
}) => Promise<void>;
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=subagent-bridge.d.ts.map
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The one model the runtime opens, as the shape a caller may ask it for text.
|
|
3
|
+
*
|
|
4
|
+
* `memory/api.ts` reached a local Ollama endpoint directly when a search asked
|
|
5
|
+
* for LLM reranking: a second place opening a model, decided inside the
|
|
6
|
+
* library rather than by whoever runs it (§2.1 — one place opens the model).
|
|
7
|
+
*
|
|
8
|
+
* A runner is stated by the host that starts the runtime and reaches an action
|
|
9
|
+
* through the catalog. A host that states none has no model for this, which is
|
|
10
|
+
* exactly what a host whose model is unreachable already had: the call falls
|
|
11
|
+
* back to the ranking it already computed and says so.
|
|
12
|
+
*/
|
|
13
|
+
export interface TextCompletionOptions {
|
|
14
|
+
/** 'json' asks the model to answer with JSON and nothing else. */
|
|
15
|
+
format?: 'json' | 'text';
|
|
16
|
+
temperature?: number;
|
|
17
|
+
maxTokens?: number;
|
|
18
|
+
timeoutMs?: number;
|
|
19
|
+
}
|
|
20
|
+
/** Ask the runtime's model for one completion. Rejects rather than answering falsely. */
|
|
21
|
+
export type TextCompletion = (prompt: string, options?: TextCompletionOptions) => Promise<string>;
|
|
22
|
+
//# sourceMappingURL=text-completion.d.ts.map
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TokenEstimator — singleton wrapper around js-tiktoken (cl100k_base).
|
|
3
|
+
*
|
|
4
|
+
* Provides accurate token counting for Korean + English text.
|
|
5
|
+
* Falls back to byte-length heuristic if WASM init fails or during loading.
|
|
6
|
+
*
|
|
7
|
+
* Uses dynamic import to avoid blocking vitest fork initialization.
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* Initialize the encoder asynchronously. Safe to call multiple times.
|
|
11
|
+
*/
|
|
12
|
+
export declare function initTokenEstimator(): Promise<void>;
|
|
13
|
+
/**
|
|
14
|
+
* Count tokens in text. Uses js-tiktoken if available, else byte fallback.
|
|
15
|
+
*/
|
|
16
|
+
export declare function countTokens(text: string): number;
|
|
17
|
+
/**
|
|
18
|
+
* Reset singleton state (for testing).
|
|
19
|
+
*/
|
|
20
|
+
export declare function resetTokenEstimator(): void;
|
|
21
|
+
/**
|
|
22
|
+
* Force fallback mode (for testing).
|
|
23
|
+
*/
|
|
24
|
+
export declare function forceFallbackMode(): void;
|
|
25
|
+
//# sourceMappingURL=token-estimator.d.ts.map
|