@jungjaehoon/mama-core 2.4.1 → 4.1.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/db/migrations/099-commitment-revision-graph.sql +2 -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 +1985 -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/commitment-revision-migration.d.ts +4 -0
- package/dist/knowledge/commitment-revision-migration.js +50 -0
- package/dist/knowledge/commitments.d.ts +192 -0
- package/dist/knowledge/commitments.js +386 -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/judgment-edge.d.ts +6 -0
- package/dist/knowledge/judgment-edge.js +22 -0
- package/dist/knowledge/judgments.d.ts +118 -0
- package/dist/knowledge/judgments.js +802 -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 +152 -0
- package/dist/runtime/drivers/claude-cli-wrapper.js +375 -0
- package/dist/runtime/drivers/claude-effort.d.ts +4 -0
- package/dist/runtime/drivers/claude-effort.js +16 -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 +425 -0
- package/dist/runtime/drivers/persistent-cli-process.js +1529 -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,63 @@
|
|
|
1
|
+
import { type Stats } from 'node:fs';
|
|
2
|
+
export interface CodexThreadRecord {
|
|
3
|
+
version: 1;
|
|
4
|
+
sessionKey: string;
|
|
5
|
+
keyHash: string;
|
|
6
|
+
threadId: string;
|
|
7
|
+
model: string;
|
|
8
|
+
cwd: string;
|
|
9
|
+
systemPromptFingerprint: string;
|
|
10
|
+
mcpConfigFingerprint: string;
|
|
11
|
+
createdAt: string;
|
|
12
|
+
lastUsedAt: string;
|
|
13
|
+
}
|
|
14
|
+
export type CodexThreadRecordInput = Omit<CodexThreadRecord, 'version' | 'keyHash' | 'createdAt' | 'lastUsedAt'>;
|
|
15
|
+
interface CodexThreadRegistryOptions {
|
|
16
|
+
rootDir: string;
|
|
17
|
+
fileSystem?: Partial<CodexThreadRegistryFileSystem>;
|
|
18
|
+
platform?: NodeJS.Platform;
|
|
19
|
+
}
|
|
20
|
+
interface CodexThreadRegistryFileSystem {
|
|
21
|
+
open(path: string, flags: number, mode?: number): number;
|
|
22
|
+
close(descriptor: number): void;
|
|
23
|
+
stat(descriptor: number): Stats;
|
|
24
|
+
chmod(descriptor: number, mode: number): void;
|
|
25
|
+
sync(descriptor: number): void;
|
|
26
|
+
read(descriptor: number): string;
|
|
27
|
+
write(descriptor: number, value: string): void;
|
|
28
|
+
lstat(path: string): Stats | undefined;
|
|
29
|
+
mkdir(path: string): void;
|
|
30
|
+
rename(source: string, destination: string, validateBoundary: () => void): void;
|
|
31
|
+
unlink(path: string, validateBoundary: () => void): void;
|
|
32
|
+
userId(): number | undefined;
|
|
33
|
+
}
|
|
34
|
+
export declare function fingerprintText(value: string): string;
|
|
35
|
+
export declare class CodexThreadRegistry {
|
|
36
|
+
private readonly rootDir;
|
|
37
|
+
private readonly parentDir;
|
|
38
|
+
private readonly fileSystem;
|
|
39
|
+
private readonly platform;
|
|
40
|
+
constructor(options: CodexThreadRegistryOptions);
|
|
41
|
+
load(sessionKey: string): CodexThreadRecord | undefined;
|
|
42
|
+
save(input: CodexThreadRecordInput): CodexThreadRecord;
|
|
43
|
+
remove(sessionKey: string): void;
|
|
44
|
+
private recordPath;
|
|
45
|
+
private withRootDirectory;
|
|
46
|
+
private withDirectory;
|
|
47
|
+
private assertBoundary;
|
|
48
|
+
private assertDirectoryIdentity;
|
|
49
|
+
private openRecordForRead;
|
|
50
|
+
private ensureSafeRecord;
|
|
51
|
+
private assertRecordIdentity;
|
|
52
|
+
private assertRecordPathNotSymlink;
|
|
53
|
+
private assertOpenedRecordPath;
|
|
54
|
+
private ensureTrustedParent;
|
|
55
|
+
private directoryOpenFlags;
|
|
56
|
+
private recordReadFlags;
|
|
57
|
+
private recordWriteFlags;
|
|
58
|
+
private withDescriptor;
|
|
59
|
+
private syncDirectory;
|
|
60
|
+
private removeTemporaryFileBestEffort;
|
|
61
|
+
}
|
|
62
|
+
export {};
|
|
63
|
+
//# sourceMappingURL=codex-thread-registry.d.ts.map
|
|
@@ -0,0 +1,433 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.CodexThreadRegistry = void 0;
|
|
4
|
+
exports.fingerprintText = fingerprintText;
|
|
5
|
+
const node_crypto_1 = require("node:crypto");
|
|
6
|
+
const node_fs_1 = require("node:fs");
|
|
7
|
+
const node_path_1 = require("node:path");
|
|
8
|
+
const nodeFileSystem = {
|
|
9
|
+
open(path, flags, mode) {
|
|
10
|
+
return mode === undefined ? (0, node_fs_1.openSync)(path, flags) : (0, node_fs_1.openSync)(path, flags, mode);
|
|
11
|
+
},
|
|
12
|
+
close: node_fs_1.closeSync,
|
|
13
|
+
stat: node_fs_1.fstatSync,
|
|
14
|
+
chmod: node_fs_1.fchmodSync,
|
|
15
|
+
sync: node_fs_1.fsyncSync,
|
|
16
|
+
read(descriptor) {
|
|
17
|
+
return (0, node_fs_1.readFileSync)(descriptor, 'utf8');
|
|
18
|
+
},
|
|
19
|
+
write(descriptor, value) {
|
|
20
|
+
(0, node_fs_1.writeFileSync)(descriptor, value, { encoding: 'utf8' });
|
|
21
|
+
},
|
|
22
|
+
lstat(path) {
|
|
23
|
+
return (0, node_fs_1.lstatSync)(path, { throwIfNoEntry: false });
|
|
24
|
+
},
|
|
25
|
+
mkdir(path) {
|
|
26
|
+
(0, node_fs_1.mkdirSync)(path, { mode: 0o700 });
|
|
27
|
+
},
|
|
28
|
+
rename(source, destination, validateBoundary) {
|
|
29
|
+
validateBoundary();
|
|
30
|
+
(0, node_fs_1.renameSync)(source, destination);
|
|
31
|
+
},
|
|
32
|
+
unlink(path, validateBoundary) {
|
|
33
|
+
validateBoundary();
|
|
34
|
+
(0, node_fs_1.unlinkSync)(path);
|
|
35
|
+
},
|
|
36
|
+
userId() {
|
|
37
|
+
return process.getuid?.();
|
|
38
|
+
},
|
|
39
|
+
};
|
|
40
|
+
function fingerprintText(value) {
|
|
41
|
+
return (0, node_crypto_1.createHash)('sha256').update(value, 'utf8').digest('hex');
|
|
42
|
+
}
|
|
43
|
+
function requireObject(value) {
|
|
44
|
+
if (typeof value !== 'object' || value === null || Array.isArray(value)) {
|
|
45
|
+
throw new Error('Codex thread registry record must be a JSON object');
|
|
46
|
+
}
|
|
47
|
+
return value;
|
|
48
|
+
}
|
|
49
|
+
function requireString(record, property) {
|
|
50
|
+
const value = record[property];
|
|
51
|
+
if (typeof value !== 'string') {
|
|
52
|
+
throw new Error(`Codex thread registry property ${property} must be a string`);
|
|
53
|
+
}
|
|
54
|
+
return value;
|
|
55
|
+
}
|
|
56
|
+
function parseRecord(value) {
|
|
57
|
+
const record = requireObject(value);
|
|
58
|
+
if (record.version !== 1) {
|
|
59
|
+
throw new Error(`Unsupported Codex thread registry schema version: ${String(record.version)}`);
|
|
60
|
+
}
|
|
61
|
+
return {
|
|
62
|
+
version: 1,
|
|
63
|
+
sessionKey: requireString(record, 'sessionKey'),
|
|
64
|
+
keyHash: requireString(record, 'keyHash'),
|
|
65
|
+
threadId: requireString(record, 'threadId'),
|
|
66
|
+
model: requireString(record, 'model'),
|
|
67
|
+
cwd: requireString(record, 'cwd'),
|
|
68
|
+
systemPromptFingerprint: requireString(record, 'systemPromptFingerprint'),
|
|
69
|
+
mcpConfigFingerprint: requireString(record, 'mcpConfigFingerprint'),
|
|
70
|
+
createdAt: requireString(record, 'createdAt'),
|
|
71
|
+
lastUsedAt: requireString(record, 'lastUsedAt'),
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
class CodexThreadRegistry {
|
|
75
|
+
rootDir;
|
|
76
|
+
parentDir;
|
|
77
|
+
fileSystem;
|
|
78
|
+
platform;
|
|
79
|
+
constructor(options) {
|
|
80
|
+
this.rootDir = (0, node_path_1.resolve)(options.rootDir);
|
|
81
|
+
this.parentDir = (0, node_path_1.dirname)(this.rootDir);
|
|
82
|
+
if (this.parentDir === this.rootDir) {
|
|
83
|
+
throw new Error('Codex thread registry directory must have a parent directory');
|
|
84
|
+
}
|
|
85
|
+
this.fileSystem = { ...nodeFileSystem, ...options.fileSystem };
|
|
86
|
+
this.platform = options.platform ?? process.platform;
|
|
87
|
+
this.withRootDirectory(() => undefined, true);
|
|
88
|
+
}
|
|
89
|
+
load(sessionKey) {
|
|
90
|
+
const keyHash = fingerprintText(sessionKey);
|
|
91
|
+
const path = this.recordPath(keyHash);
|
|
92
|
+
return this.withRootDirectory((root) => {
|
|
93
|
+
const descriptor = this.openRecordForRead(path, root);
|
|
94
|
+
if (descriptor === undefined) {
|
|
95
|
+
this.assertBoundary(root);
|
|
96
|
+
return undefined;
|
|
97
|
+
}
|
|
98
|
+
const source = this.withDescriptor(descriptor, () => {
|
|
99
|
+
const identity = this.fileSystem.stat(descriptor);
|
|
100
|
+
this.ensureSafeRecord(identity);
|
|
101
|
+
this.assertBoundary(root);
|
|
102
|
+
this.assertOpenedRecordPath(path, identity);
|
|
103
|
+
this.fileSystem.chmod(descriptor, 0o600);
|
|
104
|
+
this.assertBoundary(root);
|
|
105
|
+
this.assertOpenedRecordPath(path, identity);
|
|
106
|
+
return this.fileSystem.read(descriptor);
|
|
107
|
+
});
|
|
108
|
+
let parsed;
|
|
109
|
+
try {
|
|
110
|
+
parsed = JSON.parse(source);
|
|
111
|
+
}
|
|
112
|
+
catch (error) {
|
|
113
|
+
const detail = error instanceof Error ? error.message : String(error);
|
|
114
|
+
throw new Error(`Invalid JSON in Codex thread registry record: ${detail}`);
|
|
115
|
+
}
|
|
116
|
+
const record = parseRecord(parsed);
|
|
117
|
+
if (record.sessionKey !== sessionKey || record.keyHash !== keyHash) {
|
|
118
|
+
throw new Error('Codex thread registry key/digest mismatch');
|
|
119
|
+
}
|
|
120
|
+
return record;
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
save(input) {
|
|
124
|
+
const keyHash = fingerprintText(input.sessionKey);
|
|
125
|
+
const path = this.recordPath(keyHash);
|
|
126
|
+
const existing = this.load(input.sessionKey);
|
|
127
|
+
const now = new Date().toISOString();
|
|
128
|
+
const record = {
|
|
129
|
+
version: 1,
|
|
130
|
+
sessionKey: input.sessionKey,
|
|
131
|
+
keyHash,
|
|
132
|
+
threadId: input.threadId,
|
|
133
|
+
model: input.model,
|
|
134
|
+
cwd: input.cwd,
|
|
135
|
+
systemPromptFingerprint: input.systemPromptFingerprint,
|
|
136
|
+
mcpConfigFingerprint: input.mcpConfigFingerprint,
|
|
137
|
+
createdAt: existing?.createdAt ?? now,
|
|
138
|
+
lastUsedAt: now,
|
|
139
|
+
};
|
|
140
|
+
const temporaryPath = `${path}.${process.pid}.${(0, node_crypto_1.randomUUID)()}.tmp`;
|
|
141
|
+
this.withRootDirectory((root) => {
|
|
142
|
+
let temporaryCreated = false;
|
|
143
|
+
let renamed = false;
|
|
144
|
+
let temporaryIdentity;
|
|
145
|
+
try {
|
|
146
|
+
const descriptor = this.fileSystem.open(temporaryPath, this.recordWriteFlags(), 0o600);
|
|
147
|
+
temporaryCreated = true;
|
|
148
|
+
this.withDescriptor(descriptor, () => {
|
|
149
|
+
temporaryIdentity = this.fileSystem.stat(descriptor);
|
|
150
|
+
this.ensureSafeRecord(temporaryIdentity);
|
|
151
|
+
this.assertRecordIdentity(temporaryPath, temporaryIdentity);
|
|
152
|
+
this.fileSystem.chmod(descriptor, 0o600);
|
|
153
|
+
this.fileSystem.write(descriptor, `${JSON.stringify(record)}\n`);
|
|
154
|
+
this.fileSystem.sync(descriptor);
|
|
155
|
+
});
|
|
156
|
+
this.assertBoundary(root);
|
|
157
|
+
this.fileSystem.rename(temporaryPath, path, () => {
|
|
158
|
+
this.assertBoundary(root);
|
|
159
|
+
if (temporaryIdentity === undefined) {
|
|
160
|
+
throw new Error('Codex thread registry temporary file identity was not captured');
|
|
161
|
+
}
|
|
162
|
+
this.assertRecordIdentity(temporaryPath, temporaryIdentity);
|
|
163
|
+
});
|
|
164
|
+
renamed = true;
|
|
165
|
+
this.assertBoundary(root);
|
|
166
|
+
this.syncDirectory(root.root.descriptor);
|
|
167
|
+
}
|
|
168
|
+
catch (error) {
|
|
169
|
+
if (temporaryCreated && !renamed) {
|
|
170
|
+
this.removeTemporaryFileBestEffort(temporaryPath, root);
|
|
171
|
+
}
|
|
172
|
+
throw error;
|
|
173
|
+
}
|
|
174
|
+
});
|
|
175
|
+
return record;
|
|
176
|
+
}
|
|
177
|
+
remove(sessionKey) {
|
|
178
|
+
const path = this.recordPath(fingerprintText(sessionKey));
|
|
179
|
+
this.withRootDirectory((root) => {
|
|
180
|
+
const descriptor = this.openRecordForRead(path, root);
|
|
181
|
+
if (descriptor === undefined) {
|
|
182
|
+
this.assertBoundary(root);
|
|
183
|
+
return;
|
|
184
|
+
}
|
|
185
|
+
this.withDescriptor(descriptor, () => {
|
|
186
|
+
const identity = this.fileSystem.stat(descriptor);
|
|
187
|
+
this.ensureSafeRecord(identity);
|
|
188
|
+
this.assertBoundary(root);
|
|
189
|
+
this.assertRecordIdentity(path, identity);
|
|
190
|
+
this.fileSystem.unlink(path, () => {
|
|
191
|
+
this.assertBoundary(root);
|
|
192
|
+
this.assertRecordIdentity(path, identity);
|
|
193
|
+
});
|
|
194
|
+
this.assertBoundary(root);
|
|
195
|
+
});
|
|
196
|
+
this.syncDirectory(root.root.descriptor);
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
recordPath(keyHash) {
|
|
200
|
+
return (0, node_path_1.join)(this.rootDir, `${keyHash}.json`);
|
|
201
|
+
}
|
|
202
|
+
withRootDirectory(operation, syncParent = false) {
|
|
203
|
+
return this.withDirectory(this.parentDir, 'parent', (parent) => {
|
|
204
|
+
this.ensureTrustedParent(parent.identity);
|
|
205
|
+
let created = false;
|
|
206
|
+
if (this.fileSystem.lstat(this.rootDir) === undefined) {
|
|
207
|
+
this.assertDirectoryIdentity(this.parentDir, parent.identity, 'parent');
|
|
208
|
+
try {
|
|
209
|
+
this.fileSystem.mkdir(this.rootDir);
|
|
210
|
+
created = true;
|
|
211
|
+
}
|
|
212
|
+
catch (error) {
|
|
213
|
+
if (errorCode(error) !== 'EEXIST') {
|
|
214
|
+
throw error;
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
this.assertDirectoryIdentity(this.parentDir, parent.identity, 'parent');
|
|
218
|
+
}
|
|
219
|
+
return this.withDirectory(this.rootDir, 'registry', (root) => {
|
|
220
|
+
this.fileSystem.chmod(root.descriptor, 0o700);
|
|
221
|
+
const boundary = { parent, root };
|
|
222
|
+
this.assertBoundary(boundary);
|
|
223
|
+
if (created || syncParent) {
|
|
224
|
+
this.syncDirectory(parent.descriptor);
|
|
225
|
+
}
|
|
226
|
+
return operation(boundary);
|
|
227
|
+
});
|
|
228
|
+
});
|
|
229
|
+
}
|
|
230
|
+
withDirectory(path, label, operation) {
|
|
231
|
+
const before = this.fileSystem.lstat(path);
|
|
232
|
+
if (before === undefined) {
|
|
233
|
+
throw new Error(`Codex thread registry ${label} directory does not exist`);
|
|
234
|
+
}
|
|
235
|
+
if (before.isSymbolicLink()) {
|
|
236
|
+
throw new Error(`Codex thread registry ${label} directory must not be a symbolic link`);
|
|
237
|
+
}
|
|
238
|
+
let descriptor;
|
|
239
|
+
try {
|
|
240
|
+
descriptor = this.fileSystem.open(path, this.directoryOpenFlags());
|
|
241
|
+
}
|
|
242
|
+
catch (error) {
|
|
243
|
+
if (errorCode(error) === 'ELOOP' || this.fileSystem.lstat(path)?.isSymbolicLink()) {
|
|
244
|
+
throw new Error(`Codex thread registry ${label} directory must not be a symbolic link`, {
|
|
245
|
+
cause: error,
|
|
246
|
+
});
|
|
247
|
+
}
|
|
248
|
+
throw error;
|
|
249
|
+
}
|
|
250
|
+
return this.withDescriptor(descriptor, () => {
|
|
251
|
+
const identity = this.fileSystem.stat(descriptor);
|
|
252
|
+
if (!identity.isDirectory()) {
|
|
253
|
+
throw new Error(`Codex thread registry ${label} path must be a directory`);
|
|
254
|
+
}
|
|
255
|
+
if (!sameIdentity(before, identity)) {
|
|
256
|
+
throw new Error(`Codex thread registry ${label} directory identity changed during open`);
|
|
257
|
+
}
|
|
258
|
+
this.assertDirectoryIdentity(path, identity, label);
|
|
259
|
+
return operation({ descriptor, identity });
|
|
260
|
+
});
|
|
261
|
+
}
|
|
262
|
+
assertBoundary(boundary) {
|
|
263
|
+
this.assertDirectoryIdentity(this.parentDir, boundary.parent.identity, 'parent');
|
|
264
|
+
this.assertDirectoryIdentity(this.rootDir, boundary.root.identity, 'registry');
|
|
265
|
+
}
|
|
266
|
+
assertDirectoryIdentity(path, expected, label) {
|
|
267
|
+
const current = this.fileSystem.lstat(path);
|
|
268
|
+
if (current === undefined) {
|
|
269
|
+
throw new Error(`Codex thread registry ${label} directory disappeared during operation`);
|
|
270
|
+
}
|
|
271
|
+
if (current.isSymbolicLink()) {
|
|
272
|
+
throw new Error(`Codex thread registry ${label} directory must not be a symbolic link`);
|
|
273
|
+
}
|
|
274
|
+
if (!current.isDirectory() || !sameIdentity(current, expected)) {
|
|
275
|
+
throw new Error(`Codex thread registry ${label} directory identity changed during operation`);
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
openRecordForRead(path, boundary) {
|
|
279
|
+
try {
|
|
280
|
+
const before = this.fileSystem.lstat(path);
|
|
281
|
+
if (before === undefined) {
|
|
282
|
+
this.assertBoundary(boundary);
|
|
283
|
+
return undefined;
|
|
284
|
+
}
|
|
285
|
+
this.ensureSafeRecord(before);
|
|
286
|
+
const descriptor = this.fileSystem.open(path, this.recordReadFlags());
|
|
287
|
+
try {
|
|
288
|
+
const identity = this.fileSystem.stat(descriptor);
|
|
289
|
+
this.ensureSafeRecord(identity);
|
|
290
|
+
if (this.platform === 'win32' && !sameIdentity(before, identity)) {
|
|
291
|
+
throw new Error('Codex thread registry record identity changed during open');
|
|
292
|
+
}
|
|
293
|
+
this.assertOpenedRecordPath(path, identity);
|
|
294
|
+
return descriptor;
|
|
295
|
+
}
|
|
296
|
+
catch (error) {
|
|
297
|
+
try {
|
|
298
|
+
this.fileSystem.close(descriptor);
|
|
299
|
+
}
|
|
300
|
+
catch {
|
|
301
|
+
// Descriptor cleanup cannot replace the validation failure.
|
|
302
|
+
}
|
|
303
|
+
throw error;
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
catch (error) {
|
|
307
|
+
if (errorCode(error) === 'ENOENT') {
|
|
308
|
+
this.assertBoundary(boundary);
|
|
309
|
+
return undefined;
|
|
310
|
+
}
|
|
311
|
+
if (errorCode(error) === 'ELOOP' || this.fileSystem.lstat(path)?.isSymbolicLink()) {
|
|
312
|
+
throw new Error('Codex thread registry record must not be a symbolic link', {
|
|
313
|
+
cause: error,
|
|
314
|
+
});
|
|
315
|
+
}
|
|
316
|
+
throw error;
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
ensureSafeRecord(stats) {
|
|
320
|
+
if (stats.isSymbolicLink()) {
|
|
321
|
+
throw new Error('Codex thread registry record must not be a symbolic link');
|
|
322
|
+
}
|
|
323
|
+
if (!stats.isFile()) {
|
|
324
|
+
throw new Error('Codex thread registry record must be a regular file');
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
assertRecordIdentity(path, expected) {
|
|
328
|
+
const current = this.fileSystem.lstat(path);
|
|
329
|
+
if (current === undefined) {
|
|
330
|
+
throw new Error('Codex thread registry record disappeared during operation');
|
|
331
|
+
}
|
|
332
|
+
if (current.isSymbolicLink()) {
|
|
333
|
+
throw new Error('Codex thread registry record must not be a symbolic link');
|
|
334
|
+
}
|
|
335
|
+
if (!current.isFile() || !sameIdentity(current, expected)) {
|
|
336
|
+
throw new Error('Codex thread registry record identity changed during operation');
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
assertRecordPathNotSymlink(path) {
|
|
340
|
+
if (this.fileSystem.lstat(path)?.isSymbolicLink()) {
|
|
341
|
+
throw new Error('Codex thread registry record must not be a symbolic link');
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
assertOpenedRecordPath(path, expected) {
|
|
345
|
+
if (this.platform === 'win32') {
|
|
346
|
+
this.assertRecordIdentity(path, expected);
|
|
347
|
+
return;
|
|
348
|
+
}
|
|
349
|
+
this.assertRecordPathNotSymlink(path);
|
|
350
|
+
}
|
|
351
|
+
ensureTrustedParent(stats) {
|
|
352
|
+
if (this.platform === 'win32') {
|
|
353
|
+
// Node's Stats uid/mode do not describe Windows ACL trust. The caller must place the
|
|
354
|
+
// registry under an ACL-protected parent; descriptor/path identity and reparse-point
|
|
355
|
+
// validation enforce the topology guarantees that Node exposes portably.
|
|
356
|
+
return;
|
|
357
|
+
}
|
|
358
|
+
if ((stats.mode & 0o022) !== 0) {
|
|
359
|
+
throw new Error('Codex thread registry parent directory must not be group/world writable');
|
|
360
|
+
}
|
|
361
|
+
const userId = this.fileSystem.userId();
|
|
362
|
+
if (userId === undefined) {
|
|
363
|
+
throw new Error('Codex thread registry cannot validate the parent directory owner UID');
|
|
364
|
+
}
|
|
365
|
+
if (stats.uid !== userId && stats.uid !== 0) {
|
|
366
|
+
throw new Error('Codex thread registry parent directory has an untrusted owner UID');
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
directoryOpenFlags() {
|
|
370
|
+
if (this.platform === 'win32') {
|
|
371
|
+
return node_fs_1.constants.O_RDONLY;
|
|
372
|
+
}
|
|
373
|
+
return node_fs_1.constants.O_RDONLY | node_fs_1.constants.O_NOFOLLOW | node_fs_1.constants.O_DIRECTORY;
|
|
374
|
+
}
|
|
375
|
+
recordReadFlags() {
|
|
376
|
+
return this.platform === 'win32'
|
|
377
|
+
? node_fs_1.constants.O_RDONLY
|
|
378
|
+
: node_fs_1.constants.O_RDONLY | node_fs_1.constants.O_NOFOLLOW;
|
|
379
|
+
}
|
|
380
|
+
recordWriteFlags() {
|
|
381
|
+
const common = node_fs_1.constants.O_WRONLY | node_fs_1.constants.O_CREAT | node_fs_1.constants.O_EXCL;
|
|
382
|
+
return this.platform === 'win32' ? common : common | node_fs_1.constants.O_NOFOLLOW;
|
|
383
|
+
}
|
|
384
|
+
withDescriptor(descriptor, operation) {
|
|
385
|
+
let result;
|
|
386
|
+
try {
|
|
387
|
+
result = operation();
|
|
388
|
+
}
|
|
389
|
+
catch (error) {
|
|
390
|
+
try {
|
|
391
|
+
this.fileSystem.close(descriptor);
|
|
392
|
+
}
|
|
393
|
+
catch {
|
|
394
|
+
// Descriptor cleanup cannot replace the original operation failure.
|
|
395
|
+
}
|
|
396
|
+
throw error;
|
|
397
|
+
}
|
|
398
|
+
this.fileSystem.close(descriptor);
|
|
399
|
+
return result;
|
|
400
|
+
}
|
|
401
|
+
syncDirectory(descriptor) {
|
|
402
|
+
try {
|
|
403
|
+
this.fileSystem.sync(descriptor);
|
|
404
|
+
}
|
|
405
|
+
catch (error) {
|
|
406
|
+
const code = errorCode(error);
|
|
407
|
+
const unsupportedOnWindows = this.platform === 'win32' && (code === 'EINVAL' || code === 'ENOTSUP' || code === 'EBADF');
|
|
408
|
+
if (!unsupportedOnWindows) {
|
|
409
|
+
throw error;
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
removeTemporaryFileBestEffort(path, boundary) {
|
|
414
|
+
try {
|
|
415
|
+
this.fileSystem.unlink(path, () => this.assertBoundary(boundary));
|
|
416
|
+
}
|
|
417
|
+
catch {
|
|
418
|
+
// Cleanup cannot replace the original write/durability failure.
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
exports.CodexThreadRegistry = CodexThreadRegistry;
|
|
423
|
+
function sameIdentity(left, right) {
|
|
424
|
+
return left.dev === right.dev && left.ino === right.ino;
|
|
425
|
+
}
|
|
426
|
+
function errorCode(error) {
|
|
427
|
+
if (typeof error !== 'object' || error === null || !('code' in error)) {
|
|
428
|
+
return undefined;
|
|
429
|
+
}
|
|
430
|
+
const code = error.code;
|
|
431
|
+
return typeof code === 'string' ? code : undefined;
|
|
432
|
+
}
|
|
433
|
+
//# sourceMappingURL=codex-thread-registry.js.map
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Persistent CLI Adapter - Wraps PersistentClaudeProcess with ClaudeCLIWrapper interface
|
|
3
|
+
*
|
|
4
|
+
* WHY THIS EXISTS:
|
|
5
|
+
* - PersistentClaudeProcess uses stream-json for efficient multi-turn conversations
|
|
6
|
+
* - AgentLoop expects ClaudeCLIWrapper interface (prompt, setSessionId, setSystemPrompt)
|
|
7
|
+
* - This adapter bridges the two, enabling drop-in replacement
|
|
8
|
+
*
|
|
9
|
+
* KEY OPTIMIZATION:
|
|
10
|
+
* - Tool results sent via stdin (tool_result message)
|
|
11
|
+
* - Claude context preserved without re-sending full history
|
|
12
|
+
* - System prompt sent only once at process start
|
|
13
|
+
*/
|
|
14
|
+
import { EventEmitter } from 'events';
|
|
15
|
+
import type { ClaudeCLIWrapperOptions, PromptCallbacks, PromptResult, ToolUseBlock } from './claude-cli-wrapper.js';
|
|
16
|
+
import { type IModelRunner, type PromptOptions, type RunnerMetrics, type SessionPolicyStatus } from './types.js';
|
|
17
|
+
export type { ClaudeCLIWrapperOptions, PromptCallbacks, PromptResult, ToolUseBlock };
|
|
18
|
+
/**
|
|
19
|
+
* PersistentCLIAdapter - Drop-in replacement for ClaudeCLIWrapper
|
|
20
|
+
*
|
|
21
|
+
* Implements the same interface but uses persistent CLI processes under the hood.
|
|
22
|
+
* This enables efficient multi-turn conversations without re-sending system prompts.
|
|
23
|
+
*/
|
|
24
|
+
export declare class PersistentCLIAdapter extends EventEmitter implements IModelRunner {
|
|
25
|
+
readonly backendType: "claude";
|
|
26
|
+
/**
|
|
27
|
+
* The CLI's own delegation: `Agent` with `run_in_background: true`. The parent stream
|
|
28
|
+
* carries the spawn (`system/task_started` plus the launch tool_result that names the
|
|
29
|
+
* child), the child's tool calls, its final text, and the completion notification, so a
|
|
30
|
+
* spawn IS observable - PersistentClaudeProcess maps them and this adapter re-emits them
|
|
31
|
+
* as `subagent` events with the same shape the Codex runner uses.
|
|
32
|
+
*/
|
|
33
|
+
readonly supportsNativeSubagents = true;
|
|
34
|
+
private options;
|
|
35
|
+
private processPool;
|
|
36
|
+
private channelKey;
|
|
37
|
+
private currentProcess;
|
|
38
|
+
private currentProcessChannelKey;
|
|
39
|
+
private pendingToolResults;
|
|
40
|
+
private lastToolUseBlocks;
|
|
41
|
+
/** Processes whose subagent stream events are already wired to this adapter. */
|
|
42
|
+
private readonly wiredProcesses;
|
|
43
|
+
private readonly initializedProcesses;
|
|
44
|
+
private _requestCount;
|
|
45
|
+
private _failureCount;
|
|
46
|
+
private _totalLatencyMs;
|
|
47
|
+
private _lastRequestAt;
|
|
48
|
+
constructor(options: ClaudeCLIWrapperOptions);
|
|
49
|
+
/**
|
|
50
|
+
* Send a prompt to Claude
|
|
51
|
+
*
|
|
52
|
+
* This method:
|
|
53
|
+
* 1. Gets or creates a persistent process for this channel
|
|
54
|
+
* 2. Sends the message via stdin
|
|
55
|
+
* 3. Parses the response from stdout
|
|
56
|
+
* 4. Returns PromptResult compatible with ClaudeCLIWrapper
|
|
57
|
+
*/
|
|
58
|
+
prompt(content: string, callbacks?: PromptCallbacks, options?: PromptOptions): Promise<PromptResult>;
|
|
59
|
+
/**
|
|
60
|
+
* Re-emit one process's background-Agent stream events as runner-level events.
|
|
61
|
+
*
|
|
62
|
+
* `subagent` carries the SAME shape the Codex runner emits, so
|
|
63
|
+
* `attachSubagentWake` works unchanged. A completion the CLI answered with its own
|
|
64
|
+
* follow-up turn is emitted as `subagentObserved` instead: that turn IS the owner
|
|
65
|
+
* reacting, and a host wake on top of it would be a second turn for one child.
|
|
66
|
+
*/
|
|
67
|
+
private wireSubagentEvents;
|
|
68
|
+
/**
|
|
69
|
+
* Send a tool result back to Claude
|
|
70
|
+
*
|
|
71
|
+
* This is a new method not in ClaudeCLIWrapper that enables efficient tool loops.
|
|
72
|
+
* Instead of rebuilding the full history, we send just the tool result.
|
|
73
|
+
*/
|
|
74
|
+
sendToolResult(toolUseId: string, result: string, isError?: boolean, callbacks?: PromptCallbacks): Promise<PromptResult>;
|
|
75
|
+
/**
|
|
76
|
+
* Queue a tool result to be sent with the next message
|
|
77
|
+
*
|
|
78
|
+
* Use this when you want to collect multiple tool results before continuing.
|
|
79
|
+
*/
|
|
80
|
+
queueToolResult(toolUseId: string, result: string, isError?: boolean): void;
|
|
81
|
+
/**
|
|
82
|
+
* Check if there are pending tool results
|
|
83
|
+
*/
|
|
84
|
+
hasPendingToolResults(): boolean;
|
|
85
|
+
/**
|
|
86
|
+
* Get the last tool use blocks from the most recent response
|
|
87
|
+
*/
|
|
88
|
+
getLastToolUseBlocks(): ToolUseBlock[];
|
|
89
|
+
/**
|
|
90
|
+
* Get current session ID
|
|
91
|
+
*/
|
|
92
|
+
getSessionId(): string;
|
|
93
|
+
/**
|
|
94
|
+
* Create a new session (creates new process)
|
|
95
|
+
*/
|
|
96
|
+
resetSession(sessionId?: string): void;
|
|
97
|
+
/**
|
|
98
|
+
* Set session ID (for channel-specific conversations)
|
|
99
|
+
*
|
|
100
|
+
* Note: This creates a new channel key, effectively switching channels.
|
|
101
|
+
* The old process is kept alive for potential reuse.
|
|
102
|
+
* Callers should use resetSession() if the old process is no longer needed to avoid orphan processes.
|
|
103
|
+
*
|
|
104
|
+
* @deprecated - per-call sessionId via prompt() options; this mutates shared adapter state
|
|
105
|
+
*/
|
|
106
|
+
setSessionId(sessionId: string): void;
|
|
107
|
+
/**
|
|
108
|
+
* Set system prompt
|
|
109
|
+
*
|
|
110
|
+
* IMPORTANT: This only affects new processes. Existing processes keep their prompt.
|
|
111
|
+
* To apply a new system prompt, call resetSession() after setSystemPrompt().
|
|
112
|
+
*
|
|
113
|
+
* @deprecated - mutates shared spawn state; pass systemPrompt per prompt() call
|
|
114
|
+
*/
|
|
115
|
+
setSystemPrompt(prompt: string): void;
|
|
116
|
+
/**
|
|
117
|
+
* Get current options (for debugging)
|
|
118
|
+
*/
|
|
119
|
+
getOptions(): ClaudeCLIWrapperOptions;
|
|
120
|
+
getSessionPolicyStatus(options: PromptOptions): SessionPolicyStatus;
|
|
121
|
+
/**
|
|
122
|
+
* Check if the adapter has a live process ready to accept prompts.
|
|
123
|
+
*/
|
|
124
|
+
isHealthy(): boolean;
|
|
125
|
+
/**
|
|
126
|
+
* Collect runtime metrics.
|
|
127
|
+
*/
|
|
128
|
+
getMetrics(): RunnerMetrics;
|
|
129
|
+
/**
|
|
130
|
+
* Gracefully stop all processes (IModelRunner.stop).
|
|
131
|
+
*/
|
|
132
|
+
stop(): void;
|
|
133
|
+
/**
|
|
134
|
+
* Stop all processes (cleanup) — legacy name, delegates to stop().
|
|
135
|
+
*/
|
|
136
|
+
stopAll(): void;
|
|
137
|
+
/**
|
|
138
|
+
* Check if the adapter is in persistent mode (always true for this adapter)
|
|
139
|
+
*/
|
|
140
|
+
isPersistent(): boolean;
|
|
141
|
+
/**
|
|
142
|
+
* Get the current process state
|
|
143
|
+
*/
|
|
144
|
+
getProcessState(): string;
|
|
145
|
+
/**
|
|
146
|
+
* Get number of active processes in the pool
|
|
147
|
+
*/
|
|
148
|
+
getActiveProcessCount(): number;
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Factory function to create a ClaudeCLIWrapper-compatible adapter
|
|
152
|
+
*
|
|
153
|
+
* Usage:
|
|
154
|
+
* const wrapper = createPersistentCLIAdapter({ sessionId: 'discord-channel-123' });
|
|
155
|
+
* const result = await wrapper.prompt('Hello!');
|
|
156
|
+
*
|
|
157
|
+
* Each adapter instance maintains its own process pool. Processes are not shared across adapter instances.
|
|
158
|
+
*/
|
|
159
|
+
export declare function createPersistentCLIAdapter(options: ClaudeCLIWrapperOptions): PersistentCLIAdapter;
|
|
160
|
+
//# sourceMappingURL=persistent-cli-adapter.d.ts.map
|