@iworkforces/tracelattice 2.0.8 → 2.1.1
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 +88 -64
- package/dist/ServerConfig.d.ts +1 -1
- package/dist/ServerConfig.js.map +1 -1
- package/dist/cli.js +18 -73
- package/dist/cli.js.map +1 -1
- package/dist/config/ConfigLoader.d.ts +29 -26
- package/dist/config/ConfigLoader.d.ts.map +1 -1
- package/dist/config/ConfigLoader.js +40 -36
- package/dist/config/ConfigLoader.js.map +1 -1
- package/dist/contracts/PersistenceBackend.d.ts +7 -108
- package/dist/contracts/PersistenceBackend.d.ts.map +1 -1
- package/dist/contracts/PersistenceBackend.js +1 -6
- package/dist/contracts/calibrator.d.ts +6 -6
- package/dist/contracts/calibrator.d.ts.map +1 -1
- package/dist/contracts/ids.d.ts +1 -8
- package/dist/contracts/ids.d.ts.map +1 -1
- package/dist/contracts/ids.js +2 -3
- package/dist/contracts/ids.js.map +1 -1
- package/dist/contracts/interfaces.d.ts +4 -6
- package/dist/contracts/interfaces.d.ts.map +1 -1
- package/dist/contracts/persistence-work.d.ts +2 -3
- package/dist/contracts/persistence-work.d.ts.map +1 -1
- package/dist/core/HistoryManager.d.ts +12 -16
- package/dist/core/HistoryManager.d.ts.map +1 -1
- package/dist/core/HistoryManager.js +19 -40
- package/dist/core/HistoryManager.js.map +1 -1
- package/dist/core/IHistoryManager.d.ts +22 -30
- package/dist/core/IHistoryManager.d.ts.map +1 -1
- package/dist/core/InputNormalizer.d.ts +7 -24
- package/dist/core/InputNormalizer.d.ts.map +1 -1
- package/dist/core/InputNormalizer.js +3 -9
- package/dist/core/InputNormalizer.js.map +1 -1
- package/dist/core/PersistenceBuffer.d.ts +3 -20
- package/dist/core/PersistenceBuffer.d.ts.map +1 -1
- package/dist/core/PersistenceBuffer.js +1 -4
- package/dist/core/PersistenceBuffer.js.map +1 -1
- package/dist/core/PersistenceRestore.d.ts.map +1 -1
- package/dist/core/PersistenceRestore.js +4 -10
- package/dist/core/PersistenceRestore.js.map +1 -1
- package/dist/core/PersistenceWriter.d.ts.map +1 -1
- package/dist/core/PersistenceWriter.js +3 -12
- package/dist/core/PersistenceWriter.js.map +1 -1
- package/dist/core/SessionErrors.d.ts +0 -11
- package/dist/core/SessionErrors.d.ts.map +1 -1
- package/dist/core/SessionErrors.js +1 -14
- package/dist/core/SessionErrors.js.map +1 -1
- package/dist/core/SessionLock.d.ts +4 -5
- package/dist/core/SessionLock.d.ts.map +1 -1
- package/dist/core/SessionLock.js +5 -10
- package/dist/core/SessionLock.js.map +1 -1
- package/dist/core/SessionManager.d.ts +0 -2
- package/dist/core/SessionManager.d.ts.map +1 -1
- package/dist/core/SessionManager.js +3 -5
- package/dist/core/SessionManager.js.map +1 -1
- package/dist/core/SessionResetCoordinator.d.ts +10 -7
- package/dist/core/SessionResetCoordinator.d.ts.map +1 -1
- package/dist/core/SessionResetCoordinator.js +10 -28
- package/dist/core/SessionResetCoordinator.js.map +1 -1
- package/dist/core/ThoughtEvaluator.d.ts +5 -5
- package/dist/core/ThoughtEvaluator.d.ts.map +1 -1
- package/dist/core/ThoughtEvaluator.js +4 -40
- package/dist/core/ThoughtEvaluator.js.map +1 -1
- package/dist/core/ThoughtProcessor.d.ts +10 -3
- package/dist/core/ThoughtProcessor.d.ts.map +1 -1
- package/dist/core/ThoughtProcessor.js +34 -38
- package/dist/core/ThoughtProcessor.js.map +1 -1
- package/dist/core/VerificationOutcomeAdmission.d.ts.map +1 -1
- package/dist/core/VerificationOutcomeAdmission.js +5 -7
- package/dist/core/VerificationOutcomeAdmission.js.map +1 -1
- package/dist/core/evaluator/Calibrator.d.ts +1 -1
- package/dist/core/evaluator/Calibrator.d.ts.map +1 -1
- package/dist/core/evaluator/Calibrator.js +2 -5
- package/dist/core/evaluator/Calibrator.js.map +1 -1
- package/dist/core/evaluator/internals.d.ts +0 -4
- package/dist/core/evaluator/internals.d.ts.map +1 -1
- package/dist/core/evaluator/internals.js +1 -3
- package/dist/core/evaluator/internals.js.map +1 -1
- package/dist/core/graph/Edge.d.ts +1 -1
- package/dist/core/graph/EdgeEmitter.d.ts +2 -4
- package/dist/core/graph/EdgeEmitter.d.ts.map +1 -1
- package/dist/core/graph/EdgeEmitter.js +2 -4
- package/dist/core/graph/EdgeEmitter.js.map +1 -1
- package/dist/core/reasoning/OutcomeRecorder.d.ts +0 -1
- package/dist/core/reasoning/OutcomeRecorder.d.ts.map +1 -1
- package/dist/core/reasoning/OutcomeRecorder.js.map +1 -1
- package/dist/core/reasoning/strategies/SequentialStrategy.d.ts +3 -3
- package/dist/core/reasoning/strategies/SequentialStrategy.js.map +1 -1
- package/dist/core/thought.d.ts +2 -1
- package/dist/core/thought.d.ts.map +1 -1
- package/dist/errors.d.ts +4 -20
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +2 -28
- package/dist/errors.js.map +1 -1
- package/dist/lib.d.ts +13 -20
- package/dist/lib.d.ts.map +1 -1
- package/dist/lib.js +4 -7
- package/dist/lib.js.map +1 -1
- package/dist/logger/NullLogger.d.ts +9 -11
- package/dist/logger/NullLogger.d.ts.map +1 -1
- package/dist/logger/NullLogger.js.map +1 -1
- package/dist/persistence/FilePersistence.d.ts +3 -12
- package/dist/persistence/FilePersistence.d.ts.map +1 -1
- package/dist/persistence/FilePersistence.js +9 -61
- package/dist/persistence/FilePersistence.js.map +1 -1
- package/dist/persistence/FileSnapshotV2.d.ts +2 -2
- package/dist/persistence/FileSnapshotV2.js +2 -2
- package/dist/persistence/FileSnapshotV2.js.map +1 -1
- package/dist/persistence/FileWriter.d.ts +1 -0
- package/dist/persistence/FileWriter.d.ts.map +1 -1
- package/dist/persistence/FileWriter.js +3 -3
- package/dist/persistence/FileWriter.js.map +1 -1
- package/dist/persistence/MemoryPersistence.d.ts +5 -15
- package/dist/persistence/MemoryPersistence.d.ts.map +1 -1
- package/dist/persistence/MemoryPersistence.js +6 -40
- package/dist/persistence/MemoryPersistence.js.map +1 -1
- package/dist/persistence/PersistenceCodec.js +1 -3
- package/dist/persistence/PersistenceCodec.js.map +1 -1
- package/dist/persistence/PersistenceErrors.d.ts +0 -6
- package/dist/persistence/PersistenceErrors.d.ts.map +1 -1
- package/dist/persistence/PersistenceErrors.js +1 -9
- package/dist/persistence/PersistenceErrors.js.map +1 -1
- package/dist/persistence/PersistenceScope.d.ts.map +1 -1
- package/dist/persistence/PersistenceScope.js +2 -2
- package/dist/persistence/PersistenceScope.js.map +1 -1
- package/dist/persistence/SqlitePersistence.d.ts +3 -10
- package/dist/persistence/SqlitePersistence.d.ts.map +1 -1
- package/dist/persistence/SqlitePersistence.js +2 -26
- package/dist/persistence/SqlitePersistence.js.map +1 -1
- package/dist/persistence/SqliteSchemaV2.d.ts.map +1 -1
- package/dist/persistence/SqliteSchemaV2.js +3 -12
- package/dist/persistence/SqliteSchemaV2.js.map +1 -1
- package/dist/pool/ConnectionPool.d.ts +3 -12
- package/dist/pool/ConnectionPool.d.ts.map +1 -1
- package/dist/pool/ConnectionPool.js +5 -8
- package/dist/pool/ConnectionPool.js.map +1 -1
- package/dist/pool/IConnectionPool.d.ts +3 -9
- package/dist/pool/IConnectionPool.d.ts.map +1 -1
- package/dist/registry/SkillRegistry.d.ts +1 -7
- package/dist/registry/SkillRegistry.d.ts.map +1 -1
- package/dist/registry/SkillRegistry.js +0 -15
- package/dist/registry/SkillRegistry.js.map +1 -1
- package/dist/registry/ToolRegistry.d.ts +1 -9
- package/dist/registry/ToolRegistry.d.ts.map +1 -1
- package/dist/registry/ToolRegistry.js +0 -21
- package/dist/registry/ToolRegistry.js.map +1 -1
- package/dist/schema.d.ts +2 -1
- package/dist/schema.d.ts.map +1 -1
- package/dist/schema.js +3 -3
- package/dist/schema.js.map +1 -1
- package/dist/transport/BaseTransport.d.ts +0 -9
- package/dist/transport/BaseTransport.d.ts.map +1 -1
- package/dist/transport/BaseTransport.js +0 -11
- package/dist/transport/BaseTransport.js.map +1 -1
- package/dist/watchers/SkillWatcher.d.ts.map +1 -1
- package/dist/watchers/SkillWatcher.js +1 -1
- package/dist/watchers/SkillWatcher.js.map +1 -1
- package/package.json +1 -1
- package/dist/contracts/PersistenceBackend.js.map +0 -1
- package/dist/persistence/FileLegacyImport.d.ts +0 -2
- package/dist/persistence/FileLegacyImport.d.ts.map +0 -1
- package/dist/persistence/FileLegacyImport.js +0 -183
- package/dist/persistence/FileLegacyImport.js.map +0 -1
- package/dist/persistence/SessionScopedPersistence.d.ts +0 -4
- package/dist/persistence/SessionScopedPersistence.d.ts.map +0 -1
- package/dist/persistence/SessionScopedPersistence.js +0 -9
- package/dist/persistence/SessionScopedPersistence.js.map +0 -1
- package/dist/persistence/SqliteLegacyImport.d.ts +0 -14
- package/dist/persistence/SqliteLegacyImport.d.ts.map +0 -1
- package/dist/persistence/SqliteLegacyImport.js +0 -136
- package/dist/persistence/SqliteLegacyImport.js.map +0 -1
- package/dist/persistence/SqliteLegacySchema.d.ts +0 -15
- package/dist/persistence/SqliteLegacySchema.d.ts.map +0 -1
- package/dist/persistence/SqliteLegacySchema.js +0 -72
- package/dist/persistence/SqliteLegacySchema.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SessionErrors.d.ts","sourceRoot":"","sources":["../../src/core/SessionErrors.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,EAAe,uBAAuB,EAAE,MAAM,cAAc,CAAC;AAEpE,iEAAiE;AACjE,MAAM,MAAM,2BAA2B,GACpC,WAAW,GACX,cAAc,GACd,UAAU,GACV,iBAAiB,GACjB,eAAe,GACf,SAAS,GACT,iBAAiB,CAAC;AAErB,mFAAmF;AACnF,qBAAa,2BAA4B,SAAQ,uBAAuB;IACvE,wFAAwF;IACxF,SAAgB,SAAS,EAAE,SAAS,GAAG,SAAS,CAAC;IACjD,+CAA+C;IAC/C,SAAgB,KAAK,EAAE,2BAA2B,CAAC;gBAEhC,SAAS,EAAE,SAAS,GAAG,SAAS,EAAE,KAAK,EAAE,2BAA2B;CAUvF;AAED,6EAA6E;AAC7E,qBAAa,gBAAiB,SAAQ,uBAAuB;IAC5D,SAAgB,SAAS,EAAE,SAAS,CAAC;IACrC,SAAgB,SAAS,EAAE,MAAM,CAAC;gBAEtB,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM;CAMnD;AAED,8DAA8D;AAC9D,qBAAa,wBAAyB,SAAQ,uBAAuB;IACpE,SAAgB,SAAS,EAAE,SAAS,CAAC;IACrC,SAAgB,aAAa,EAAE,MAAM,CAAC;IACtC,SAAgB,WAAW,EAAE,MAAM,GAAG,SAAS,CAAC;gBAEpC,SAAS,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM;CAU7E
|
|
1
|
+
{"version":3,"file":"SessionErrors.d.ts","sourceRoot":"","sources":["../../src/core/SessionErrors.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,EAAe,uBAAuB,EAAE,MAAM,cAAc,CAAC;AAEpE,iEAAiE;AACjE,MAAM,MAAM,2BAA2B,GACpC,WAAW,GACX,cAAc,GACd,UAAU,GACV,iBAAiB,GACjB,eAAe,GACf,SAAS,GACT,iBAAiB,CAAC;AAErB,mFAAmF;AACnF,qBAAa,2BAA4B,SAAQ,uBAAuB;IACvE,wFAAwF;IACxF,SAAgB,SAAS,EAAE,SAAS,GAAG,SAAS,CAAC;IACjD,+CAA+C;IAC/C,SAAgB,KAAK,EAAE,2BAA2B,CAAC;gBAEhC,SAAS,EAAE,SAAS,GAAG,SAAS,EAAE,KAAK,EAAE,2BAA2B;CAUvF;AAED,6EAA6E;AAC7E,qBAAa,gBAAiB,SAAQ,uBAAuB;IAC5D,SAAgB,SAAS,EAAE,SAAS,CAAC;IACrC,SAAgB,SAAS,EAAE,MAAM,CAAC;gBAEtB,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM;CAMnD;AAED,8DAA8D;AAC9D,qBAAa,wBAAyB,SAAQ,uBAAuB;IACpE,SAAgB,SAAS,EAAE,SAAS,CAAC;IACrC,SAAgB,aAAa,EAAE,MAAM,CAAC;IACtC,SAAgB,WAAW,EAAE,MAAM,GAAG,SAAS,CAAC;gBAEpC,SAAS,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM;CAU7E"}
|
|
@@ -32,19 +32,6 @@ class SessionAccessDeniedError extends SequentialThinkingError {
|
|
|
32
32
|
this.actualOwner = actualOwner;
|
|
33
33
|
}
|
|
34
34
|
}
|
|
35
|
-
|
|
36
|
-
scope;
|
|
37
|
-
sessionId;
|
|
38
|
-
reason;
|
|
39
|
-
constructor(scope, sessionId, reason = 'persistent'){
|
|
40
|
-
const target = 'session' === scope ? `session '${sessionId}'` : 'all sessions';
|
|
41
|
-
super(`Synchronous clear cannot reset ${reason} ${target}; use the awaitable ${'session' === scope ? 'resetSession()' : 'resetAll()'} API`, ERROR_CODES.ASYNC_RESET_REQUIRED);
|
|
42
|
-
this.name = 'AsyncResetRequiredError';
|
|
43
|
-
this.scope = scope;
|
|
44
|
-
this.sessionId = sessionId;
|
|
45
|
-
this.reason = reason;
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
export { AsyncResetRequiredError, LockTimeoutError, SessionAccessDeniedError, SessionLifecycleClosedError };
|
|
35
|
+
export { LockTimeoutError, SessionAccessDeniedError, SessionLifecycleClosedError };
|
|
49
36
|
|
|
50
37
|
//# sourceMappingURL=SessionErrors.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"core/SessionErrors.js","sources":["../../src/core/SessionErrors.ts"],"sourcesContent":["import type { SessionId } from '../contracts/ids.js';\nimport { ERROR_CODES, SequentialThinkingError } from '../errors.js';\n\n/** Lifecycle phase that can close ordinary session admission. */\nexport type SessionLifecycleClosedPhase =\n\t| 'resetting'\n\t| 'reset_failed'\n\t| 'evicting'\n\t| 'eviction_failed'\n\t| 'shutting_down'\n\t| 'stopped'\n\t| 'shutdown_failed';\n\n/** Error thrown when an operation arrives after lifecycle admission has closed. */\nexport class SessionLifecycleClosedError extends SequentialThinkingError {\n\t/** Session whose admission is closed, or `undefined` for a global exclusive request. */\n\tpublic readonly sessionId: SessionId | undefined;\n\t/** Lifecycle phase that rejected admission. */\n\tpublic readonly phase: SessionLifecycleClosedPhase;\n\n\tpublic constructor(sessionId: SessionId | undefined, phase: SessionLifecycleClosedPhase) {\n\t\tconst scope = sessionId === undefined ? 'Global' : `Session '${sessionId}'`;\n\t\tsuper(\n\t\t\t`${scope} lifecycle admission is closed in phase '${phase}'`,\n\t\t\tERROR_CODES.SESSION_LIFECYCLE_CLOSED\n\t\t);\n\t\tthis.name = 'SessionLifecycleClosedError';\n\t\tthis.sessionId = sessionId;\n\t\tthis.phase = phase;\n\t}\n}\n\n/** Error thrown when a per-session async lock cannot be acquired in time. */\nexport class LockTimeoutError extends SequentialThinkingError {\n\tpublic readonly sessionId: SessionId;\n\tpublic readonly timeoutMs: number;\n\n\tconstructor(sessionId: SessionId, timeoutMs: number) {\n\t\tsuper(`Lock timeout for session '${sessionId}' after ${timeoutMs}ms`, ERROR_CODES.LOCK_TIMEOUT);\n\t\tthis.name = 'LockTimeoutError';\n\t\tthis.sessionId = sessionId;\n\t\tthis.timeoutMs = timeoutMs;\n\t}\n}\n\n/** Error thrown when a session is accessed by a non-owner. */\nexport class SessionAccessDeniedError extends SequentialThinkingError {\n\tpublic readonly sessionId: SessionId;\n\tpublic readonly expectedOwner: string;\n\tpublic readonly actualOwner: string | undefined;\n\n\tconstructor(sessionId: SessionId, expectedOwner: string, actualOwner?: string) {\n\t\tsuper(\n\t\t\t`Access denied to session '${sessionId}': owned by '${expectedOwner}', accessed by '${actualOwner ?? 'anonymous'}'`,\n\t\t\tERROR_CODES.SESSION_ACCESS_DENIED\n\t\t);\n\t\tthis.name = 'SessionAccessDeniedError';\n\t\tthis.sessionId = sessionId;\n\t\tthis.expectedOwner = expectedOwner;\n\t\tthis.actualOwner = actualOwner;\n\t}\n}\n
|
|
1
|
+
{"version":3,"file":"core/SessionErrors.js","sources":["../../src/core/SessionErrors.ts"],"sourcesContent":["import type { SessionId } from '../contracts/ids.js';\nimport { ERROR_CODES, SequentialThinkingError } from '../errors.js';\n\n/** Lifecycle phase that can close ordinary session admission. */\nexport type SessionLifecycleClosedPhase =\n\t| 'resetting'\n\t| 'reset_failed'\n\t| 'evicting'\n\t| 'eviction_failed'\n\t| 'shutting_down'\n\t| 'stopped'\n\t| 'shutdown_failed';\n\n/** Error thrown when an operation arrives after lifecycle admission has closed. */\nexport class SessionLifecycleClosedError extends SequentialThinkingError {\n\t/** Session whose admission is closed, or `undefined` for a global exclusive request. */\n\tpublic readonly sessionId: SessionId | undefined;\n\t/** Lifecycle phase that rejected admission. */\n\tpublic readonly phase: SessionLifecycleClosedPhase;\n\n\tpublic constructor(sessionId: SessionId | undefined, phase: SessionLifecycleClosedPhase) {\n\t\tconst scope = sessionId === undefined ? 'Global' : `Session '${sessionId}'`;\n\t\tsuper(\n\t\t\t`${scope} lifecycle admission is closed in phase '${phase}'`,\n\t\t\tERROR_CODES.SESSION_LIFECYCLE_CLOSED\n\t\t);\n\t\tthis.name = 'SessionLifecycleClosedError';\n\t\tthis.sessionId = sessionId;\n\t\tthis.phase = phase;\n\t}\n}\n\n/** Error thrown when a per-session async lock cannot be acquired in time. */\nexport class LockTimeoutError extends SequentialThinkingError {\n\tpublic readonly sessionId: SessionId;\n\tpublic readonly timeoutMs: number;\n\n\tconstructor(sessionId: SessionId, timeoutMs: number) {\n\t\tsuper(`Lock timeout for session '${sessionId}' after ${timeoutMs}ms`, ERROR_CODES.LOCK_TIMEOUT);\n\t\tthis.name = 'LockTimeoutError';\n\t\tthis.sessionId = sessionId;\n\t\tthis.timeoutMs = timeoutMs;\n\t}\n}\n\n/** Error thrown when a session is accessed by a non-owner. */\nexport class SessionAccessDeniedError extends SequentialThinkingError {\n\tpublic readonly sessionId: SessionId;\n\tpublic readonly expectedOwner: string;\n\tpublic readonly actualOwner: string | undefined;\n\n\tconstructor(sessionId: SessionId, expectedOwner: string, actualOwner?: string) {\n\t\tsuper(\n\t\t\t`Access denied to session '${sessionId}': owned by '${expectedOwner}', accessed by '${actualOwner ?? 'anonymous'}'`,\n\t\t\tERROR_CODES.SESSION_ACCESS_DENIED\n\t\t);\n\t\tthis.name = 'SessionAccessDeniedError';\n\t\tthis.sessionId = sessionId;\n\t\tthis.expectedOwner = expectedOwner;\n\t\tthis.actualOwner = actualOwner;\n\t}\n}\n"],"names":["SessionLifecycleClosedError","SequentialThinkingError","sessionId","phase","scope","undefined","ERROR_CODES","LockTimeoutError","timeoutMs","SessionAccessDeniedError","expectedOwner","actualOwner"],"mappings":";AAcO,MAAMA,oCAAoCC;IAEhC,UAAiC;IAEjC,MAAmC;IAEnD,YAAmBC,SAAgC,EAAEC,KAAkC,CAAE;QACxF,MAAMC,QAAQF,AAAcG,WAAdH,YAA0B,WAAW,CAAC,SAAS,EAAEA,UAAU,CAAC,CAAC;QAC3E,KAAK,CACJ,GAAGE,MAAM,yCAAyC,EAAED,MAAM,CAAC,CAAC,EAC5DG,YAAY,wBAAwB;QAErC,IAAI,CAAC,IAAI,GAAG;QACZ,IAAI,CAAC,SAAS,GAAGJ;QACjB,IAAI,CAAC,KAAK,GAAGC;IACd;AACD;AAGO,MAAMI,yBAAyBN;IACrB,UAAqB;IACrB,UAAkB;IAElC,YAAYC,SAAoB,EAAEM,SAAiB,CAAE;QACpD,KAAK,CAAC,CAAC,0BAA0B,EAAEN,UAAU,QAAQ,EAAEM,UAAU,EAAE,CAAC,EAAEF,YAAY,YAAY;QAC9F,IAAI,CAAC,IAAI,GAAG;QACZ,IAAI,CAAC,SAAS,GAAGJ;QACjB,IAAI,CAAC,SAAS,GAAGM;IAClB;AACD;AAGO,MAAMC,iCAAiCR;IAC7B,UAAqB;IACrB,cAAsB;IACtB,YAAgC;IAEhD,YAAYC,SAAoB,EAAEQ,aAAqB,EAAEC,WAAoB,CAAE;QAC9E,KAAK,CACJ,CAAC,0BAA0B,EAAET,UAAU,aAAa,EAAEQ,cAAc,gBAAgB,EAAEC,eAAe,YAAY,CAAC,CAAC,EACnHL,YAAY,qBAAqB;QAElC,IAAI,CAAC,IAAI,GAAG;QACZ,IAAI,CAAC,SAAS,GAAGJ;QACjB,IAAI,CAAC,aAAa,GAAGQ;QACrB,IAAI,CAAC,WAAW,GAAGC;IACpB;AACD"}
|
|
@@ -6,8 +6,7 @@
|
|
|
6
6
|
* (when no waiters chained on top), preventing unbounded memory growth.
|
|
7
7
|
*
|
|
8
8
|
* Different sessions are fully independent: locks for distinct session
|
|
9
|
-
* ids never block each other.
|
|
10
|
-
* single global slot.
|
|
9
|
+
* ids never block each other.
|
|
11
10
|
*
|
|
12
11
|
* @module session-lock
|
|
13
12
|
*/
|
|
@@ -41,7 +40,7 @@ export declare class SessionLock implements ISessionLock {
|
|
|
41
40
|
*/
|
|
42
41
|
get size(): number;
|
|
43
42
|
/** Returns whether a session currently has a holder or queued operation. */
|
|
44
|
-
isActive(sessionId: SessionId
|
|
43
|
+
isActive(sessionId: SessionId): boolean;
|
|
45
44
|
/**
|
|
46
45
|
* Execute `fn` while holding the lock for the given session.
|
|
47
46
|
*
|
|
@@ -49,11 +48,11 @@ export declare class SessionLock implements ISessionLock {
|
|
|
49
48
|
* different sessions run in parallel. The lock is always released
|
|
50
49
|
* (via `finally`) even if `fn` throws.
|
|
51
50
|
*
|
|
52
|
-
* @param sessionId - Session to lock.
|
|
51
|
+
* @param sessionId - Session to lock.
|
|
53
52
|
* @param fn - Critical section to run while holding the lock.
|
|
54
53
|
* @param timeoutMs - Maximum time to wait for the lock (default 5000ms).
|
|
55
54
|
* @throws {LockTimeoutError} When the lock cannot be acquired within `timeoutMs`.
|
|
56
55
|
*/
|
|
57
|
-
withLock<T>(sessionId: SessionId
|
|
56
|
+
withLock<T>(sessionId: SessionId, fn: () => Promise<T>, timeoutMs?: number): Promise<T>;
|
|
58
57
|
}
|
|
59
58
|
//# sourceMappingURL=SessionLock.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SessionLock.d.ts","sourceRoot":"","sources":["../../src/core/SessionLock.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"SessionLock.d.ts","sourceRoot":"","sources":["../../src/core/SessionLock.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAC/D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAKrD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,qBAAa,WAAY,YAAW,YAAY;IAC/C,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAuC;IAE9D;;;OAGG;IACH,IAAW,IAAI,IAAI,MAAM,CAExB;IAED,4EAA4E;IACrE,QAAQ,CAAC,SAAS,EAAE,SAAS,GAAG,OAAO;IAI9C;;;;;;;;;;;OAWG;IACU,QAAQ,CAAC,CAAC,EACtB,SAAS,EAAE,SAAS,EACpB,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EACpB,SAAS,GAAE,MAAgC,GACzC,OAAO,CAAC,CAAC,CAAC;CAoCb"}
|
package/dist/core/SessionLock.js
CHANGED
|
@@ -1,30 +1,25 @@
|
|
|
1
|
-
import { GLOBAL_SESSION_ID } from "../contracts/ids.js";
|
|
2
1
|
import { LockTimeoutError } from "./SessionErrors.js";
|
|
3
2
|
const DEFAULT_LOCK_TIMEOUT_MS = 5000;
|
|
4
|
-
function lockKey(sessionId) {
|
|
5
|
-
return sessionId && sessionId.length > 0 ? sessionId : GLOBAL_SESSION_ID;
|
|
6
|
-
}
|
|
7
3
|
class SessionLock {
|
|
8
4
|
_locks = new Map();
|
|
9
5
|
get size() {
|
|
10
6
|
return this._locks.size;
|
|
11
7
|
}
|
|
12
8
|
isActive(sessionId) {
|
|
13
|
-
return this._locks.has(
|
|
9
|
+
return this._locks.has(sessionId);
|
|
14
10
|
}
|
|
15
11
|
async withLock(sessionId, fn, timeoutMs = DEFAULT_LOCK_TIMEOUT_MS) {
|
|
16
|
-
const
|
|
17
|
-
const previous = this._locks.get(key) ?? Promise.resolve();
|
|
12
|
+
const previous = this._locks.get(sessionId) ?? Promise.resolve();
|
|
18
13
|
const release = Promise.withResolvers();
|
|
19
14
|
const next = previous.then(()=>release.promise, ()=>release.promise);
|
|
20
|
-
this._locks.set(
|
|
15
|
+
this._locks.set(sessionId, next);
|
|
21
16
|
next.then(()=>{
|
|
22
|
-
if (this._locks.get(
|
|
17
|
+
if (this._locks.get(sessionId) === next) this._locks.delete(sessionId);
|
|
23
18
|
});
|
|
24
19
|
let timeoutId;
|
|
25
20
|
try {
|
|
26
21
|
await new Promise((resolve, reject)=>{
|
|
27
|
-
timeoutId = setTimeout(()=>reject(new LockTimeoutError(
|
|
22
|
+
timeoutId = setTimeout(()=>reject(new LockTimeoutError(sessionId, timeoutMs)), timeoutMs);
|
|
28
23
|
previous.then(()=>resolve(), ()=>resolve());
|
|
29
24
|
});
|
|
30
25
|
return await fn();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"core/SessionLock.js","sources":["../../src/core/SessionLock.ts"],"sourcesContent":["/**\n * Per-session async lock to prevent concurrent state mutations.\n *\n * Uses chained promises: each lock acquisition waits for the previous\n * holder's promise to resolve. The lock map entry is purged after release\n * (when no waiters chained on top), preventing unbounded memory growth.\n *\n * Different sessions are fully independent: locks for distinct session\n * ids never block each other
|
|
1
|
+
{"version":3,"file":"core/SessionLock.js","sources":["../../src/core/SessionLock.ts"],"sourcesContent":["/**\n * Per-session async lock to prevent concurrent state mutations.\n *\n * Uses chained promises: each lock acquisition waits for the previous\n * holder's promise to resolve. The lock map entry is purged after release\n * (when no waiters chained on top), preventing unbounded memory growth.\n *\n * Different sessions are fully independent: locks for distinct session\n * ids never block each other.\n *\n * @module session-lock\n */\n\nimport type { ISessionLock } from '../contracts/interfaces.js';\nimport type { SessionId } from '../contracts/ids.js';\nimport { LockTimeoutError } from './SessionErrors.js';\n\nconst DEFAULT_LOCK_TIMEOUT_MS = 5000;\n\n/**\n * In-memory implementation of {@link ISessionLock}.\n *\n * Maintains a `Map<string, Promise<void>>` where each value is the tail\n * of the lock chain for that session. New acquisitions chain onto the\n * tail and replace it; once they release, the entry is purged unless a\n * later acquisition chained on top.\n *\n * Lock chain integrity is preserved across timeouts and `fn` errors: a\n * waiter's slot is only released after the previous holder actually\n * finishes, even if the waiter aborted via {@link LockTimeoutError}.\n *\n * @example\n * ```typescript\n * const lock = new SessionLock();\n * await lock.withLock('session-a', async () => {\n * // critical section — concurrent calls for 'session-a' wait\n * });\n * ```\n */\nexport class SessionLock implements ISessionLock {\n\tprivate readonly _locks = new Map<SessionId, Promise<void>>();\n\n\t/**\n\t * Number of currently held lock chains. Useful for diagnostics\n\t * and leak assertions in tests.\n\t */\n\tpublic get size(): number {\n\t\treturn this._locks.size;\n\t}\n\n\t/** Returns whether a session currently has a holder or queued operation. */\n\tpublic isActive(sessionId: SessionId): boolean {\n\t\treturn this._locks.has(sessionId);\n\t}\n\n\t/**\n\t * Execute `fn` while holding the lock for the given session.\n\t *\n\t * Concurrent calls for the same session are serialized. Calls for\n\t * different sessions run in parallel. The lock is always released\n\t * (via `finally`) even if `fn` throws.\n\t *\n\t * @param sessionId - Session to lock.\n\t * @param fn - Critical section to run while holding the lock.\n\t * @param timeoutMs - Maximum time to wait for the lock (default 5000ms).\n\t * @throws {LockTimeoutError} When the lock cannot be acquired within `timeoutMs`.\n\t */\n\tpublic async withLock<T>(\n\t\tsessionId: SessionId,\n\t\tfn: () => Promise<T>,\n\t\ttimeoutMs: number = DEFAULT_LOCK_TIMEOUT_MS\n\t): Promise<T> {\n\t\tconst previous = this._locks.get(sessionId) ?? Promise.resolve();\n\n\t\t// `next` is the tail this acquirer publishes to the chain. It only\n\t\t// resolves after `previous` settles, guaranteeing serialization even\n\t\t// when the current acquirer times out before holding the lock.\n\t\tconst release = Promise.withResolvers<void>();\n\t\tconst next = previous.then(\n\t\t\t() => release.promise,\n\t\t\t() => release.promise\n\t\t);\n\t\tthis._locks.set(sessionId, next);\n\t\t// Identity protects a later acquisition from an earlier tail's cleanup.\n\t\tvoid next.then(() => {\n\t\t\tif (this._locks.get(sessionId) === next) {\n\t\t\t\tthis._locks.delete(sessionId);\n\t\t\t}\n\t\t});\n\n\t\tlet timeoutId: ReturnType<typeof setTimeout> | undefined;\n\t\ttry {\n\t\t\tawait new Promise<void>((resolve, reject) => {\n\t\t\t\ttimeoutId = setTimeout(() => reject(new LockTimeoutError(sessionId, timeoutMs)), timeoutMs);\n\t\t\t\tprevious.then(\n\t\t\t\t\t() => resolve(),\n\t\t\t\t\t() => resolve() // previous holder's failure must not poison the chain\n\t\t\t\t);\n\t\t\t});\n\t\t\treturn await fn();\n\t\t} finally {\n\t\t\tif (timeoutId !== undefined) {\n\t\t\t\tclearTimeout(timeoutId);\n\t\t\t}\n\t\t\trelease.resolve();\n\t\t}\n\t}\n}\n"],"names":["DEFAULT_LOCK_TIMEOUT_MS","SessionLock","Map","sessionId","fn","timeoutMs","previous","Promise","release","next","timeoutId","resolve","reject","setTimeout","LockTimeoutError","undefined","clearTimeout"],"mappings":";AAiBA,MAAMA,0BAA0B;AAsBzB,MAAMC;IACK,SAAS,IAAIC,MAAgC;IAM9D,IAAW,OAAe;QACzB,OAAO,IAAI,CAAC,MAAM,CAAC,IAAI;IACxB;IAGO,SAASC,SAAoB,EAAW;QAC9C,OAAO,IAAI,CAAC,MAAM,CAAC,GAAG,CAACA;IACxB;IAcA,MAAa,SACZA,SAAoB,EACpBC,EAAoB,EACpBC,YAAoBL,uBAAuB,EAC9B;QACb,MAAMM,WAAW,IAAI,CAAC,MAAM,CAAC,GAAG,CAACH,cAAcI,QAAQ,OAAO;QAK9D,MAAMC,UAAUD,QAAQ,aAAa;QACrC,MAAME,OAAOH,SAAS,IAAI,CACzB,IAAME,QAAQ,OAAO,EACrB,IAAMA,QAAQ,OAAO;QAEtB,IAAI,CAAC,MAAM,CAAC,GAAG,CAACL,WAAWM;QAEtBA,KAAK,IAAI,CAAC;YACd,IAAI,IAAI,CAAC,MAAM,CAAC,GAAG,CAACN,eAAeM,MAClC,IAAI,CAAC,MAAM,CAAC,MAAM,CAACN;QAErB;QAEA,IAAIO;QACJ,IAAI;YACH,MAAM,IAAIH,QAAc,CAACI,SAASC;gBACjCF,YAAYG,WAAW,IAAMD,OAAO,IAAIE,iBAAiBX,WAAWE,aAAaA;gBACjFC,SAAS,IAAI,CACZ,IAAMK,WACN,IAAMA;YAER;YACA,OAAO,MAAMP;QACd,SAAU;YACT,IAAIM,AAAcK,WAAdL,WACHM,aAAaN;YAEdF,QAAQ,OAAO;QAChB;IACD;AACD"}
|
|
@@ -15,7 +15,6 @@ export interface SessionLike {
|
|
|
15
15
|
export type SessionEligibility<S extends SessionLike> = (sessionId: SessionId, session: S) => boolean;
|
|
16
16
|
/** Configuration options for {@link SessionManager}. */
|
|
17
17
|
export interface SessionManagerConfig {
|
|
18
|
-
readonly defaultSessionId: SessionId;
|
|
19
18
|
readonly sessionTtlMs: number;
|
|
20
19
|
readonly cleanupIntervalMs: number;
|
|
21
20
|
readonly getMaxSessions: () => number;
|
|
@@ -31,7 +30,6 @@ export interface SessionManagerConfig {
|
|
|
31
30
|
* ```
|
|
32
31
|
*/
|
|
33
32
|
export declare class SessionManager<S extends SessionLike> {
|
|
34
|
-
private readonly _defaultSessionId;
|
|
35
33
|
private readonly _sessionTtlMs;
|
|
36
34
|
private readonly _cleanupIntervalMs;
|
|
37
35
|
private readonly _getMaxSessions;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SessionManager.d.ts","sourceRoot":"","sources":["../../src/core/SessionManager.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAErD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,+BAA+B,CAAC;AAE5D,+DAA+D;AAC/D,MAAM,WAAW,WAAW;IAC3B,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,UAAU,CAAC,EAAE,UAAU,CAAC;CACjC;AAED,qEAAqE;AACrE,MAAM,MAAM,kBAAkB,CAAC,CAAC,SAAS,WAAW,IAAI,CACvD,SAAS,EAAE,SAAS,EACpB,OAAO,EAAE,CAAC,KACN,OAAO,CAAC;AAEb,wDAAwD;AACxD,MAAM,WAAW,oBAAoB;IACpC,QAAQ,CAAC,
|
|
1
|
+
{"version":3,"file":"SessionManager.d.ts","sourceRoot":"","sources":["../../src/core/SessionManager.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAErD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,+BAA+B,CAAC;AAE5D,+DAA+D;AAC/D,MAAM,WAAW,WAAW;IAC3B,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,UAAU,CAAC,EAAE,UAAU,CAAC;CACjC;AAED,qEAAqE;AACrE,MAAM,MAAM,kBAAkB,CAAC,CAAC,SAAS,WAAW,IAAI,CACvD,SAAS,EAAE,SAAS,EACpB,OAAO,EAAE,CAAC,KACN,OAAO,CAAC;AAEb,wDAAwD;AACxD,MAAM,WAAW,oBAAoB;IACpC,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAC;IACnC,QAAQ,CAAC,cAAc,EAAE,MAAM,MAAM,CAAC;IACtC,QAAQ,CAAC,mBAAmB,CAAC,EAAE,MAAM,CAAC;IACtC,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;CACzB;AAQD;;;;;;;GAOG;AACH,qBAAa,cAAc,CAAC,CAAC,SAAS,WAAW;IAChD,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAS;IACvC,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAS;IAC5C,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAe;IAC/C,OAAO,CAAC,QAAQ,CAAC,oBAAoB,CAAS;IAC9C,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,aAAa,CAA+C;gBAEjD,MAAM,EAAE,oBAAoB;IAQ/C,wDAAwD;IACxD,IAAW,KAAK,IAAI,UAAU,CAAC,OAAO,WAAW,CAAC,GAAG,IAAI,CAExD;IAED;;OAEG;IACI,iBAAiB,CACvB,QAAQ,EAAE,GAAG,CAAC,SAAS,EAAE,CAAC,CAAC,EAC3B,UAAU,EAAE,kBAAkB,CAAC,CAAC,CAAC,EACjC,OAAO,EAAE,CAAC,UAAU,EAAE,SAAS,SAAS,EAAE,KAAK,OAAO,CAAC,IAAI,CAAC,GAC1D,IAAI;IAgBP,wCAAwC;IACjC,gBAAgB,IAAI,IAAI;IAM/B;;;;;;OAMG;IACI,wBAAwB,CAC9B,QAAQ,EAAE,WAAW,CAAC,SAAS,EAAE,CAAC,CAAC,EACnC,KAAK,EAAE,MAAM,GAAG,SAAS,EACzB,UAAU,EAAE,kBAAkB,CAAC,CAAC,CAAC,GAC/B,SAAS,SAAS,EAAE,GAAG,SAAS;IA8BnC,mFAAmF;IAC5E,sBAAsB,CAC5B,QAAQ,EAAE,WAAW,CAAC,SAAS,EAAE,CAAC,CAAC,EACnC,UAAU,EAAE,kBAAkB,CAAC,CAAC,CAAC,EACjC,GAAG,GAAE,MAAmB,GACtB,SAAS,SAAS,EAAE;IAUvB,OAAO,CAAC,sBAAsB;CAe9B"}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { NullLogger } from "../logger/NullLogger.js";
|
|
2
2
|
class SessionManager {
|
|
3
|
-
_defaultSessionId;
|
|
4
3
|
_sessionTtlMs;
|
|
5
4
|
_cleanupIntervalMs;
|
|
6
5
|
_getMaxSessions;
|
|
@@ -8,7 +7,6 @@ class SessionManager {
|
|
|
8
7
|
_logger;
|
|
9
8
|
_cleanupTimer = null;
|
|
10
9
|
constructor(config){
|
|
11
|
-
this._defaultSessionId = config.defaultSessionId;
|
|
12
10
|
this._sessionTtlMs = config.sessionTtlMs;
|
|
13
11
|
this._cleanupIntervalMs = config.cleanupIntervalMs;
|
|
14
12
|
this._getMaxSessions = config.getMaxSessions;
|
|
@@ -42,19 +40,19 @@ class SessionManager {
|
|
|
42
40
|
if (void 0 !== owner) {
|
|
43
41
|
const ownerCount = live.filter((candidate)=>candidate.session.owner === owner).length;
|
|
44
42
|
const ownerNeed = Math.max(0, ownerCount + 1 - this._maxSessionsPerOwner);
|
|
45
|
-
selected.push(...live.filter((candidate)=>candidate.session.owner === owner &&
|
|
43
|
+
selected.push(...live.filter((candidate)=>candidate.session.owner === owner && isEligible(candidate.sessionId, candidate.session)).slice(0, ownerNeed));
|
|
46
44
|
if (selected.length < ownerNeed) return;
|
|
47
45
|
}
|
|
48
46
|
const globalNeed = Math.max(0, live.length + 1 - this._getMaxSessions());
|
|
49
47
|
const remainingNeed = Math.max(0, globalNeed - selected.length);
|
|
50
48
|
const selectedIds = new Set(selected.map((candidate)=>candidate.sessionId));
|
|
51
|
-
const alternatives = live.filter((candidate)
|
|
49
|
+
const alternatives = live.filter((candidate)=>!selectedIds.has(candidate.sessionId) && isEligible(candidate.sessionId, candidate.session));
|
|
52
50
|
if (alternatives.length < remainingNeed) return;
|
|
53
51
|
selected.push(...alternatives.slice(0, remainingNeed));
|
|
54
52
|
return selected.map((candidate)=>candidate.sessionId);
|
|
55
53
|
}
|
|
56
54
|
staleSessionCandidates(sessions, isEligible, now = Date.now()) {
|
|
57
|
-
return this._orderedLiveCandidates(sessions).filter((candidate)=>
|
|
55
|
+
return this._orderedLiveCandidates(sessions).filter((candidate)=>now - candidate.session.lastAccessedAt > this._sessionTtlMs && isEligible(candidate.sessionId, candidate.session)).map((candidate)=>candidate.sessionId);
|
|
58
56
|
}
|
|
59
57
|
_orderedLiveCandidates(sessions) {
|
|
60
58
|
const candidates = [];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"core/SessionManager.js","sources":["../../src/core/SessionManager.ts"],"sourcesContent":["/**\n * Deterministic session cleanup candidate policy and periodic timer.\n *\n * @module SessionManager\n */\n\nimport type { SessionId } from '../contracts/ids.js';\nimport { NullLogger } from '../logger/NullLogger.js';\nimport type { Logger } from '../logger/StructuredLogger.js';\n\n/** Minimal session facts needed by capacity and TTL policy. */\nexport interface SessionLike {\n\treadonly lastAccessedAt: number;\n\treadonly owner?: string;\n\treadonly provenance?: 'restored';\n}\n\n/** Determines whether a candidate can be removed at this instant. */\nexport type SessionEligibility<S extends SessionLike> = (\n\tsessionId: SessionId,\n\tsession: S\n) => boolean;\n\n/** Configuration options for {@link SessionManager}. */\nexport interface SessionManagerConfig {\n\treadonly
|
|
1
|
+
{"version":3,"file":"core/SessionManager.js","sources":["../../src/core/SessionManager.ts"],"sourcesContent":["/**\n * Deterministic session cleanup candidate policy and periodic timer.\n *\n * @module SessionManager\n */\n\nimport type { SessionId } from '../contracts/ids.js';\nimport { NullLogger } from '../logger/NullLogger.js';\nimport type { Logger } from '../logger/StructuredLogger.js';\n\n/** Minimal session facts needed by capacity and TTL policy. */\nexport interface SessionLike {\n\treadonly lastAccessedAt: number;\n\treadonly owner?: string;\n\treadonly provenance?: 'restored';\n}\n\n/** Determines whether a candidate can be removed at this instant. */\nexport type SessionEligibility<S extends SessionLike> = (\n\tsessionId: SessionId,\n\tsession: S\n) => boolean;\n\n/** Configuration options for {@link SessionManager}. */\nexport interface SessionManagerConfig {\n\treadonly sessionTtlMs: number;\n\treadonly cleanupIntervalMs: number;\n\treadonly getMaxSessions: () => number;\n\treadonly maxSessionsPerOwner?: number;\n\treadonly logger?: Logger;\n}\n\ntype Candidate<S extends SessionLike> = {\n\treadonly sessionId: SessionId;\n\treadonly session: S;\n\treadonly insertionOrder: number;\n};\n\n/**\n * Produces complete candidate sets but never mutates the caller-owned session map.\n *\n * @example\n * ```ts\n * const victims = manager.planProspectiveAdmission(sessions, owner, lifecycle.isIdle);\n * ```\n */\nexport class SessionManager<S extends SessionLike> {\n\tprivate readonly _sessionTtlMs: number;\n\tprivate readonly _cleanupIntervalMs: number;\n\tprivate readonly _getMaxSessions: () => number;\n\tprivate readonly _maxSessionsPerOwner: number;\n\tprivate readonly _logger: Logger;\n\tprivate _cleanupTimer: ReturnType<typeof setInterval> | null = null;\n\n\tpublic constructor(config: SessionManagerConfig) {\n\t\tthis._sessionTtlMs = config.sessionTtlMs;\n\t\tthis._cleanupIntervalMs = config.cleanupIntervalMs;\n\t\tthis._getMaxSessions = config.getMaxSessions;\n\t\tthis._maxSessionsPerOwner = config.maxSessionsPerOwner ?? 50;\n\t\tthis._logger = config.logger ?? new NullLogger();\n\t}\n\n\t/** @returns The periodic cleanup timer, when active. */\n\tpublic get timer(): ReturnType<typeof setInterval> | null {\n\t\treturn this._cleanupTimer;\n\t}\n\n\t/**\n\t * Starts periodic TTL candidate cleanup and observes every asynchronous rejection.\n\t */\n\tpublic startCleanupTimer(\n\t\tsessions: Map<SessionId, S>,\n\t\tisEligible: SessionEligibility<S>,\n\t\tcleanup: (sessionIds: readonly SessionId[]) => Promise<void>\n\t): void {\n\t\tif (this._cleanupTimer !== null) return;\n\t\tthis._cleanupTimer = setInterval(() => {\n\t\t\tconst candidates = this.staleSessionCandidates(sessions, isEligible);\n\t\t\tif (candidates.length === 0) return;\n\t\t\tvoid Promise.resolve()\n\t\t\t\t.then(() => cleanup(candidates))\n\t\t\t\t.catch((error: unknown) => {\n\t\t\t\t\tthis._logger.error('Session cleanup failed', { error });\n\t\t\t\t});\n\t\t}, this._cleanupIntervalMs);\n\t\tif (typeof this._cleanupTimer === 'object' && 'unref' in this._cleanupTimer) {\n\t\t\tthis._cleanupTimer.unref();\n\t\t}\n\t}\n\n\t/** Stops the periodic cleanup timer. */\n\tpublic stopCleanupTimer(): void {\n\t\tif (this._cleanupTimer === null) return;\n\t\tclearInterval(this._cleanupTimer);\n\t\tthis._cleanupTimer = null;\n\t}\n\n\t/**\n\t * Plans the complete victim union required before admitting one prospective session.\n\t *\n\t * Owner quota need is selected first. Those victims also satisfy global need, then\n\t * oldest globally eligible alternatives fill any remainder. `undefined` means no\n\t * complete eligible set exists; the input map is never modified.\n\t */\n\tpublic planProspectiveAdmission(\n\t\tsessions: ReadonlyMap<SessionId, S>,\n\t\towner: string | undefined,\n\t\tisEligible: SessionEligibility<S>\n\t): readonly SessionId[] | undefined {\n\t\tconst live = this._orderedLiveCandidates(sessions);\n\t\tconst selected: Candidate<S>[] = [];\n\t\tif (owner !== undefined) {\n\t\t\tconst ownerCount = live.filter((candidate) => candidate.session.owner === owner).length;\n\t\t\tconst ownerNeed = Math.max(0, ownerCount + 1 - this._maxSessionsPerOwner);\n\t\t\tselected.push(\n\t\t\t\t...live\n\t\t\t\t\t.filter(\n\t\t\t\t\t\t(candidate) =>\n\t\t\t\t\t\t\tcandidate.session.owner === owner &&\n\t\t\t\t\t\t\tisEligible(candidate.sessionId, candidate.session)\n\t\t\t\t\t)\n\t\t\t\t\t.slice(0, ownerNeed)\n\t\t\t);\n\t\t\tif (selected.length < ownerNeed) return undefined;\n\t\t}\n\n\t\tconst globalNeed = Math.max(0, live.length + 1 - this._getMaxSessions());\n\t\tconst remainingNeed = Math.max(0, globalNeed - selected.length);\n\t\tconst selectedIds = new Set(selected.map((candidate) => candidate.sessionId));\n\t\tconst alternatives = live.filter(\n\t\t\t(candidate) =>\n\t\t\t\t!selectedIds.has(candidate.sessionId) && isEligible(candidate.sessionId, candidate.session)\n\t\t);\n\t\tif (alternatives.length < remainingNeed) return undefined;\n\t\tselected.push(...alternatives.slice(0, remainingNeed));\n\t\treturn selected.map((candidate) => candidate.sessionId);\n\t}\n\n\t/** Returns stable oldest-first TTL candidates under the same eligibility rules. */\n\tpublic staleSessionCandidates(\n\t\tsessions: ReadonlyMap<SessionId, S>,\n\t\tisEligible: SessionEligibility<S>,\n\t\tnow: number = Date.now()\n\t): readonly SessionId[] {\n\t\treturn this._orderedLiveCandidates(sessions)\n\t\t\t.filter(\n\t\t\t\t(candidate) =>\n\t\t\t\t\tnow - candidate.session.lastAccessedAt > this._sessionTtlMs &&\n\t\t\t\t\tisEligible(candidate.sessionId, candidate.session)\n\t\t\t)\n\t\t\t.map((candidate) => candidate.sessionId);\n\t}\n\n\tprivate _orderedLiveCandidates(sessions: ReadonlyMap<SessionId, S>): Candidate<S>[] {\n\t\tconst candidates: Candidate<S>[] = [];\n\t\tlet insertionOrder = 0;\n\t\tfor (const [sessionId, session] of sessions) {\n\t\t\tif (session.provenance !== 'restored') {\n\t\t\t\tcandidates.push({ sessionId, session, insertionOrder });\n\t\t\t}\n\t\t\tinsertionOrder += 1;\n\t\t}\n\t\treturn candidates.sort(\n\t\t\t(left, right) =>\n\t\t\t\tleft.session.lastAccessedAt - right.session.lastAccessedAt ||\n\t\t\t\tleft.insertionOrder - right.insertionOrder\n\t\t);\n\t}\n}\n"],"names":["SessionManager","config","NullLogger","sessions","isEligible","cleanup","setInterval","candidates","Promise","error","clearInterval","owner","live","selected","undefined","ownerCount","candidate","ownerNeed","Math","globalNeed","remainingNeed","selectedIds","Set","alternatives","now","Date","insertionOrder","sessionId","session","left","right"],"mappings":";AA8CO,MAAMA;IACK,cAAsB;IACtB,mBAA2B;IAC3B,gBAA8B;IAC9B,qBAA6B;IAC7B,QAAgB;IACzB,gBAAuD,KAAK;IAEpE,YAAmBC,MAA4B,CAAE;QAChD,IAAI,CAAC,aAAa,GAAGA,OAAO,YAAY;QACxC,IAAI,CAAC,kBAAkB,GAAGA,OAAO,iBAAiB;QAClD,IAAI,CAAC,eAAe,GAAGA,OAAO,cAAc;QAC5C,IAAI,CAAC,oBAAoB,GAAGA,OAAO,mBAAmB,IAAI;QAC1D,IAAI,CAAC,OAAO,GAAGA,OAAO,MAAM,IAAI,IAAIC;IACrC;IAGA,IAAW,QAA+C;QACzD,OAAO,IAAI,CAAC,aAAa;IAC1B;IAKO,kBACNC,QAA2B,EAC3BC,UAAiC,EACjCC,OAA4D,EACrD;QACP,IAAI,AAAuB,SAAvB,IAAI,CAAC,aAAa,EAAW;QACjC,IAAI,CAAC,aAAa,GAAGC,YAAY;YAChC,MAAMC,aAAa,IAAI,CAAC,sBAAsB,CAACJ,UAAUC;YACzD,IAAIG,AAAsB,MAAtBA,WAAW,MAAM,EAAQ;YACxBC,QAAQ,OAAO,GAClB,IAAI,CAAC,IAAMH,QAAQE,aACnB,KAAK,CAAC,CAACE;gBACP,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,0BAA0B;oBAAEA;gBAAM;YACtD;QACF,GAAG,IAAI,CAAC,kBAAkB;QAC1B,IAAI,AAA8B,YAA9B,OAAO,IAAI,CAAC,aAAa,IAAiB,WAAW,IAAI,CAAC,aAAa,EAC1E,IAAI,CAAC,aAAa,CAAC,KAAK;IAE1B;IAGO,mBAAyB;QAC/B,IAAI,AAAuB,SAAvB,IAAI,CAAC,aAAa,EAAW;QACjCC,cAAc,IAAI,CAAC,aAAa;QAChC,IAAI,CAAC,aAAa,GAAG;IACtB;IASO,yBACNP,QAAmC,EACnCQ,KAAyB,EACzBP,UAAiC,EACE;QACnC,MAAMQ,OAAO,IAAI,CAAC,sBAAsB,CAACT;QACzC,MAAMU,WAA2B,EAAE;QACnC,IAAIF,AAAUG,WAAVH,OAAqB;YACxB,MAAMI,aAAaH,KAAK,MAAM,CAAC,CAACI,YAAcA,UAAU,OAAO,CAAC,KAAK,KAAKL,OAAO,MAAM;YACvF,MAAMM,YAAYC,KAAK,GAAG,CAAC,GAAGH,aAAa,IAAI,IAAI,CAAC,oBAAoB;YACxEF,SAAS,IAAI,IACTD,KACD,MAAM,CACN,CAACI,YACAA,UAAU,OAAO,CAAC,KAAK,KAAKL,SAC5BP,WAAWY,UAAU,SAAS,EAAEA,UAAU,OAAO,GAElD,KAAK,CAAC,GAAGC;YAEZ,IAAIJ,SAAS,MAAM,GAAGI,WAAW;QAClC;QAEA,MAAME,aAAaD,KAAK,GAAG,CAAC,GAAGN,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,eAAe;QACrE,MAAMQ,gBAAgBF,KAAK,GAAG,CAAC,GAAGC,aAAaN,SAAS,MAAM;QAC9D,MAAMQ,cAAc,IAAIC,IAAIT,SAAS,GAAG,CAAC,CAACG,YAAcA,UAAU,SAAS;QAC3E,MAAMO,eAAeX,KAAK,MAAM,CAC/B,CAACI,YACA,CAACK,YAAY,GAAG,CAACL,UAAU,SAAS,KAAKZ,WAAWY,UAAU,SAAS,EAAEA,UAAU,OAAO;QAE5F,IAAIO,aAAa,MAAM,GAAGH,eAAe;QACzCP,SAAS,IAAI,IAAIU,aAAa,KAAK,CAAC,GAAGH;QACvC,OAAOP,SAAS,GAAG,CAAC,CAACG,YAAcA,UAAU,SAAS;IACvD;IAGO,uBACNb,QAAmC,EACnCC,UAAiC,EACjCoB,MAAcC,KAAK,GAAG,EAAE,EACD;QACvB,OAAO,IAAI,CAAC,sBAAsB,CAACtB,UACjC,MAAM,CACN,CAACa,YACAQ,MAAMR,UAAU,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,aAAa,IAC3DZ,WAAWY,UAAU,SAAS,EAAEA,UAAU,OAAO,GAElD,GAAG,CAAC,CAACA,YAAcA,UAAU,SAAS;IACzC;IAEQ,uBAAuBb,QAAmC,EAAkB;QACnF,MAAMI,aAA6B,EAAE;QACrC,IAAImB,iBAAiB;QACrB,KAAK,MAAM,CAACC,WAAWC,QAAQ,IAAIzB,SAAU;YAC5C,IAAIyB,AAAuB,eAAvBA,QAAQ,UAAU,EACrBrB,WAAW,IAAI,CAAC;gBAAEoB;gBAAWC;gBAASF;YAAe;YAEtDA,kBAAkB;QACnB;QACA,OAAOnB,WAAW,IAAI,CACrB,CAACsB,MAAMC,QACND,KAAK,OAAO,CAAC,cAAc,GAAGC,MAAM,OAAO,CAAC,cAAc,IAC1DD,KAAK,cAAc,GAAGC,MAAM,cAAc;IAE7C;AACD"}
|
|
@@ -7,26 +7,29 @@ interface ResetBarrier {
|
|
|
7
7
|
withSessionResetBarrier(sessionId: SessionId, operation: () => Promise<void>): Promise<void>;
|
|
8
8
|
withGlobalResetBarrier(operation: () => Promise<void>): Promise<void>;
|
|
9
9
|
}
|
|
10
|
-
|
|
11
|
-
readonly persistence: PersistenceBackend | null;
|
|
12
|
-
readonly barrier: ResetBarrier | null;
|
|
10
|
+
interface SessionResetCoordinatorBaseConfig<SessionState> {
|
|
13
11
|
readonly edgeStore?: IEdgeStore;
|
|
14
12
|
readonly summaryStore?: ISummaryStore;
|
|
15
13
|
readonly sessions: Map<SessionId, SessionState>;
|
|
16
14
|
readonly createSessionState: (owner: string | undefined) => SessionState;
|
|
17
15
|
readonly logger: Logger;
|
|
18
16
|
}
|
|
17
|
+
type ResetDurability = {
|
|
18
|
+
readonly persistence: null;
|
|
19
|
+
readonly barrier: null;
|
|
20
|
+
} | {
|
|
21
|
+
readonly persistence: PersistenceBackend;
|
|
22
|
+
readonly barrier: ResetBarrier;
|
|
23
|
+
};
|
|
24
|
+
export type SessionResetCoordinatorConfig<SessionState> = SessionResetCoordinatorBaseConfig<SessionState> & ResetDurability;
|
|
19
25
|
export declare class SessionResetCoordinator<SessionState> {
|
|
20
|
-
private readonly
|
|
21
|
-
private readonly _barrier;
|
|
26
|
+
private readonly _durability;
|
|
22
27
|
private readonly _edgeStore?;
|
|
23
28
|
private readonly _summaryStore?;
|
|
24
29
|
private readonly _sessions;
|
|
25
30
|
private readonly _createSessionState;
|
|
26
31
|
private readonly _logger;
|
|
27
32
|
constructor(config: SessionResetCoordinatorConfig<SessionState>);
|
|
28
|
-
clearSession(sessionId: SessionId): void;
|
|
29
|
-
clearAll(): void;
|
|
30
33
|
resetSession(sessionId: SessionId, preservedOwner: string | undefined, clearAuxiliaryState?: () => void): Promise<void>;
|
|
31
34
|
resetAll(clearAuxiliaryState?: () => void): Promise<void>;
|
|
32
35
|
private _replaceLiveSession;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SessionResetCoordinator.d.ts","sourceRoot":"","sources":["../../src/core/SessionResetCoordinator.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,oCAAoC,CAAC;AAC7E,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;AAC7D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAC7D,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,+BAA+B,CAAC;
|
|
1
|
+
{"version":3,"file":"SessionResetCoordinator.d.ts","sourceRoot":"","sources":["../../src/core/SessionResetCoordinator.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,oCAAoC,CAAC;AAC7E,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;AAC7D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAC7D,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,+BAA+B,CAAC;AAC5D,UAAU,YAAY;IACrB,uBAAuB,CAAC,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7F,sBAAsB,CAAC,SAAS,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACtE;AAED,UAAU,iCAAiC,CAAC,YAAY;IACvD,QAAQ,CAAC,SAAS,CAAC,EAAE,UAAU,CAAC;IAChC,QAAQ,CAAC,YAAY,CAAC,EAAE,aAAa,CAAC;IACtC,QAAQ,CAAC,QAAQ,EAAE,GAAG,CAAC,SAAS,EAAE,YAAY,CAAC,CAAC;IAChD,QAAQ,CAAC,kBAAkB,EAAE,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,KAAK,YAAY,CAAC;IACzE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACxB;AAED,KAAK,eAAe,GACjB;IAAE,QAAQ,CAAC,WAAW,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,IAAI,CAAA;CAAE,GACtD;IAAE,QAAQ,CAAC,WAAW,EAAE,kBAAkB,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,YAAY,CAAA;CAAE,CAAC;AAEhF,MAAM,MAAM,6BAA6B,CAAC,YAAY,IACrD,iCAAiC,CAAC,YAAY,CAAC,GAAG,eAAe,CAAC;AAEnE,qBAAa,uBAAuB,CAAC,YAAY;IAChD,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAkB;IAC9C,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAa;IACzC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAgB;IAC/C,OAAO,CAAC,QAAQ,CAAC,SAAS,CAA+B;IACzD,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAA8C;IAClF,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;gBAErB,MAAM,EAAE,6BAA6B,CAAC,YAAY,CAAC;IASzD,YAAY,CACjB,SAAS,EAAE,SAAS,EACpB,cAAc,EAAE,MAAM,GAAG,SAAS,EAClC,mBAAmB,CAAC,EAAE,MAAM,IAAI,GAC9B,OAAO,CAAC,IAAI,CAAC;IAcV,QAAQ,CAAC,mBAAmB,CAAC,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAc/D,OAAO,CAAC,mBAAmB;IAM3B,OAAO,CAAC,mBAAmB;IAK3B,OAAO,CAAC,kBAAkB;CAM1B"}
|
|
@@ -1,58 +1,40 @@
|
|
|
1
|
-
import { requireSessionScopedPersistence } from "../persistence/SessionScopedPersistence.js";
|
|
2
|
-
import { AsyncResetRequiredError } from "./SessionErrors.js";
|
|
3
1
|
class SessionResetCoordinator {
|
|
4
|
-
|
|
5
|
-
_barrier;
|
|
2
|
+
_durability;
|
|
6
3
|
_edgeStore;
|
|
7
4
|
_summaryStore;
|
|
8
5
|
_sessions;
|
|
9
6
|
_createSessionState;
|
|
10
7
|
_logger;
|
|
11
8
|
constructor(config){
|
|
12
|
-
this.
|
|
13
|
-
this._barrier = config.barrier;
|
|
9
|
+
this._durability = config;
|
|
14
10
|
this._edgeStore = config.edgeStore;
|
|
15
11
|
this._summaryStore = config.summaryStore;
|
|
16
12
|
this._sessions = config.sessions;
|
|
17
13
|
this._createSessionState = config.createSessionState;
|
|
18
14
|
this._logger = config.logger;
|
|
19
15
|
}
|
|
20
|
-
clearSession(sessionId) {
|
|
21
|
-
if (null !== this._persistence) throw new AsyncResetRequiredError('session', sessionId);
|
|
22
|
-
this._clearSessionStores(sessionId);
|
|
23
|
-
this._sessions.delete(sessionId);
|
|
24
|
-
this._logger.info('Session cleared', {
|
|
25
|
-
sessionId
|
|
26
|
-
});
|
|
27
|
-
}
|
|
28
|
-
clearAll() {
|
|
29
|
-
if (null !== this._persistence) throw new AsyncResetRequiredError('all');
|
|
30
|
-
this._clearAllLiveState();
|
|
31
|
-
}
|
|
32
16
|
async resetSession(sessionId, preservedOwner, clearAuxiliaryState) {
|
|
33
|
-
|
|
17
|
+
const durability = this._durability;
|
|
18
|
+
if (null === durability.persistence) {
|
|
34
19
|
this._replaceLiveSession(sessionId, preservedOwner);
|
|
35
20
|
clearAuxiliaryState?.();
|
|
36
21
|
return;
|
|
37
22
|
}
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
await this._barrier.withSessionResetBarrier(sessionId, async ()=>{
|
|
41
|
-
await scopedPersistence.clearSession(sessionId);
|
|
23
|
+
await durability.barrier.withSessionResetBarrier(sessionId, async ()=>{
|
|
24
|
+
await durability.persistence.clearSession(sessionId);
|
|
42
25
|
this._replaceLiveSession(sessionId, preservedOwner);
|
|
43
26
|
clearAuxiliaryState?.();
|
|
44
27
|
});
|
|
45
28
|
}
|
|
46
29
|
async resetAll(clearAuxiliaryState) {
|
|
47
|
-
const
|
|
48
|
-
if (null === persistence) {
|
|
30
|
+
const durability = this._durability;
|
|
31
|
+
if (null === durability.persistence) {
|
|
49
32
|
this._clearAllLiveState();
|
|
50
33
|
clearAuxiliaryState?.();
|
|
51
34
|
return;
|
|
52
35
|
}
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
await persistence.clear();
|
|
36
|
+
await durability.barrier.withGlobalResetBarrier(async ()=>{
|
|
37
|
+
await durability.persistence.clearAll();
|
|
56
38
|
this._clearAllLiveState();
|
|
57
39
|
clearAuxiliaryState?.();
|
|
58
40
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"core/SessionResetCoordinator.js","sources":["../../src/core/SessionResetCoordinator.ts"],"sourcesContent":["import type { PersistenceBackend } from '../contracts/PersistenceBackend.js';\nimport type { IEdgeStore } from '../contracts/interfaces.js';\nimport type { SessionId } from '../contracts/ids.js';\nimport type { ISummaryStore } from '../contracts/summary.js';\nimport type { Logger } from '../logger/StructuredLogger.js';\
|
|
1
|
+
{"version":3,"file":"core/SessionResetCoordinator.js","sources":["../../src/core/SessionResetCoordinator.ts"],"sourcesContent":["import type { PersistenceBackend } from '../contracts/PersistenceBackend.js';\nimport type { IEdgeStore } from '../contracts/interfaces.js';\nimport type { SessionId } from '../contracts/ids.js';\nimport type { ISummaryStore } from '../contracts/summary.js';\nimport type { Logger } from '../logger/StructuredLogger.js';\ninterface ResetBarrier {\n\twithSessionResetBarrier(sessionId: SessionId, operation: () => Promise<void>): Promise<void>;\n\twithGlobalResetBarrier(operation: () => Promise<void>): Promise<void>;\n}\n\ninterface SessionResetCoordinatorBaseConfig<SessionState> {\n\treadonly edgeStore?: IEdgeStore;\n\treadonly summaryStore?: ISummaryStore;\n\treadonly sessions: Map<SessionId, SessionState>;\n\treadonly createSessionState: (owner: string | undefined) => SessionState;\n\treadonly logger: Logger;\n}\n\ntype ResetDurability =\n\t| { readonly persistence: null; readonly barrier: null }\n\t| { readonly persistence: PersistenceBackend; readonly barrier: ResetBarrier };\n\nexport type SessionResetCoordinatorConfig<SessionState> =\n\tSessionResetCoordinatorBaseConfig<SessionState> & ResetDurability;\n\nexport class SessionResetCoordinator<SessionState> {\n\tprivate readonly _durability: ResetDurability;\n\tprivate readonly _edgeStore?: IEdgeStore;\n\tprivate readonly _summaryStore?: ISummaryStore;\n\tprivate readonly _sessions: Map<SessionId, SessionState>;\n\tprivate readonly _createSessionState: (owner: string | undefined) => SessionState;\n\tprivate readonly _logger: Logger;\n\n\tconstructor(config: SessionResetCoordinatorConfig<SessionState>) {\n\t\tthis._durability = config;\n\t\tthis._edgeStore = config.edgeStore;\n\t\tthis._summaryStore = config.summaryStore;\n\t\tthis._sessions = config.sessions;\n\t\tthis._createSessionState = config.createSessionState;\n\t\tthis._logger = config.logger;\n\t}\n\n\tasync resetSession(\n\t\tsessionId: SessionId,\n\t\tpreservedOwner: string | undefined,\n\t\tclearAuxiliaryState?: () => void\n\t): Promise<void> {\n\t\tconst durability = this._durability;\n\t\tif (durability.persistence === null) {\n\t\t\tthis._replaceLiveSession(sessionId, preservedOwner);\n\t\t\tclearAuxiliaryState?.();\n\t\t\treturn;\n\t\t}\n\t\tawait durability.barrier.withSessionResetBarrier(sessionId, async () => {\n\t\t\tawait durability.persistence.clearSession(sessionId);\n\t\t\tthis._replaceLiveSession(sessionId, preservedOwner);\n\t\t\tclearAuxiliaryState?.();\n\t\t});\n\t}\n\n\tasync resetAll(clearAuxiliaryState?: () => void): Promise<void> {\n\t\tconst durability = this._durability;\n\t\tif (durability.persistence === null) {\n\t\t\tthis._clearAllLiveState();\n\t\t\tclearAuxiliaryState?.();\n\t\t\treturn;\n\t\t}\n\t\tawait durability.barrier.withGlobalResetBarrier(async () => {\n\t\t\tawait durability.persistence.clearAll();\n\t\t\tthis._clearAllLiveState();\n\t\t\tclearAuxiliaryState?.();\n\t\t});\n\t}\n\n\tprivate _replaceLiveSession(sessionId: SessionId, owner: string | undefined): void {\n\t\tthis._clearSessionStores(sessionId);\n\t\tthis._sessions.set(sessionId, this._createSessionState(owner));\n\t\tthis._logger.info('Session reset', { sessionId });\n\t}\n\n\tprivate _clearSessionStores(sessionId: SessionId): void {\n\t\tthis._edgeStore?.clearSession(sessionId);\n\t\tthis._summaryStore?.clearSession(sessionId);\n\t}\n\n\tprivate _clearAllLiveState(): void {\n\t\tthis._edgeStore?.clearAll();\n\t\tthis._summaryStore?.clearAll();\n\t\tthis._sessions.clear();\n\t\tthis._logger.info('History cleared (all sessions)');\n\t}\n}\n"],"names":["SessionResetCoordinator","config","sessionId","preservedOwner","clearAuxiliaryState","durability","owner"],"mappings":"AAyBO,MAAMA;IACK,YAA6B;IAC7B,WAAwB;IACxB,cAA8B;IAC9B,UAAwC;IACxC,oBAAiE;IACjE,QAAgB;IAEjC,YAAYC,MAAmD,CAAE;QAChE,IAAI,CAAC,WAAW,GAAGA;QACnB,IAAI,CAAC,UAAU,GAAGA,OAAO,SAAS;QAClC,IAAI,CAAC,aAAa,GAAGA,OAAO,YAAY;QACxC,IAAI,CAAC,SAAS,GAAGA,OAAO,QAAQ;QAChC,IAAI,CAAC,mBAAmB,GAAGA,OAAO,kBAAkB;QACpD,IAAI,CAAC,OAAO,GAAGA,OAAO,MAAM;IAC7B;IAEA,MAAM,aACLC,SAAoB,EACpBC,cAAkC,EAClCC,mBAAgC,EAChB;QAChB,MAAMC,aAAa,IAAI,CAAC,WAAW;QACnC,IAAIA,AAA2B,SAA3BA,WAAW,WAAW,EAAW;YACpC,IAAI,CAAC,mBAAmB,CAACH,WAAWC;YACpCC;YACA;QACD;QACA,MAAMC,WAAW,OAAO,CAAC,uBAAuB,CAACH,WAAW;YAC3D,MAAMG,WAAW,WAAW,CAAC,YAAY,CAACH;YAC1C,IAAI,CAAC,mBAAmB,CAACA,WAAWC;YACpCC;QACD;IACD;IAEA,MAAM,SAASA,mBAAgC,EAAiB;QAC/D,MAAMC,aAAa,IAAI,CAAC,WAAW;QACnC,IAAIA,AAA2B,SAA3BA,WAAW,WAAW,EAAW;YACpC,IAAI,CAAC,kBAAkB;YACvBD;YACA;QACD;QACA,MAAMC,WAAW,OAAO,CAAC,sBAAsB,CAAC;YAC/C,MAAMA,WAAW,WAAW,CAAC,QAAQ;YACrC,IAAI,CAAC,kBAAkB;YACvBD;QACD;IACD;IAEQ,oBAAoBF,SAAoB,EAAEI,KAAyB,EAAQ;QAClF,IAAI,CAAC,mBAAmB,CAACJ;QACzB,IAAI,CAAC,SAAS,CAAC,GAAG,CAACA,WAAW,IAAI,CAAC,mBAAmB,CAACI;QACvD,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,iBAAiB;YAAEJ;QAAU;IAChD;IAEQ,oBAAoBA,SAAoB,EAAQ;QACvD,IAAI,CAAC,UAAU,EAAE,aAAaA;QAC9B,IAAI,CAAC,aAAa,EAAE,aAAaA;IAClC;IAEQ,qBAA2B;QAClC,IAAI,CAAC,UAAU,EAAE;QACjB,IAAI,CAAC,aAAa,EAAE;QACpB,IAAI,CAAC,SAAS,CAAC,KAAK;QACpB,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC;IACnB;AACD"}
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
* @module core/ThoughtEvaluator
|
|
9
9
|
*/
|
|
10
10
|
import type { ICalibrator } from '../contracts/calibrator.js';
|
|
11
|
-
import {
|
|
11
|
+
import type { SessionId } from '../contracts/ids.js';
|
|
12
12
|
import type { ConfidenceSignals, PatternSignal, ReasoningStats } from './reasoning.js';
|
|
13
13
|
import type { ThoughtData } from './thought.js';
|
|
14
14
|
/** Explicit thought and canonical session used for response calibration. */
|
|
@@ -26,8 +26,8 @@ export interface ConfidenceSignalContext {
|
|
|
26
26
|
*
|
|
27
27
|
* @example
|
|
28
28
|
* ```typescript
|
|
29
|
-
* const evaluator = new ThoughtEvaluator();
|
|
30
|
-
* const signals = evaluator.computeConfidenceSignals(history, branches);
|
|
29
|
+
* const evaluator = new ThoughtEvaluator(calibrator);
|
|
30
|
+
* const signals = evaluator.computeConfidenceSignals(history, branches, context);
|
|
31
31
|
* const stats = evaluator.computeReasoningStats(history, branches);
|
|
32
32
|
* const patterns = evaluator.computePatternSignals(history, branches);
|
|
33
33
|
* ```
|
|
@@ -37,9 +37,9 @@ export declare class ThoughtEvaluator {
|
|
|
37
37
|
private readonly _aggregator;
|
|
38
38
|
private readonly _patternDetector;
|
|
39
39
|
private readonly _calibrator;
|
|
40
|
-
constructor(calibrator
|
|
40
|
+
constructor(calibrator: ICalibrator);
|
|
41
41
|
/** Compute confidence signals from history context. Pure computation. */
|
|
42
|
-
computeConfidenceSignals(history: ThoughtData[], branches: Record<string, ThoughtData[]>, context
|
|
42
|
+
computeConfidenceSignals(history: ThoughtData[], branches: Record<string, ThoughtData[]>, context: ConfidenceSignalContext): ConfidenceSignals;
|
|
43
43
|
/** Compute aggregated reasoning analytics. Pure computation. */
|
|
44
44
|
computeReasoningStats(history: ThoughtData[], branches: Record<string, ThoughtData[]>): ReasoningStats;
|
|
45
45
|
/** Detect reasoning patterns (anti-patterns and positive signals). Pure computation. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ThoughtEvaluator.d.ts","sourceRoot":"","sources":["../../src/core/ThoughtEvaluator.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"ThoughtEvaluator.d.ts","sourceRoot":"","sources":["../../src/core/ThoughtEvaluator.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AAC9D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,KAAK,EAAE,iBAAiB,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AACvF,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAKhD,4EAA4E;AAC5E,MAAM,WAAW,uBAAuB;IACvC,QAAQ,CAAC,cAAc,EAAE,WAAW,CAAC;IACrC,QAAQ,CAAC,SAAS,EAAE,SAAS,CAAC;CAC9B;AAED;;;;;;;;;;;;;;;GAeG;AACH,qBAAa,gBAAgB;IAC5B,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAiB;IACjD,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAa;IACzC,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAkB;IACnD,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAc;gBAE9B,UAAU,EAAE,WAAW;IAOnC,yEAAyE;IAClE,wBAAwB,CAC9B,OAAO,EAAE,WAAW,EAAE,EACtB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,EAAE,CAAC,EACvC,OAAO,EAAE,uBAAuB,GAC9B,iBAAiB;IAqBpB,gEAAgE;IACzD,qBAAqB,CAC3B,OAAO,EAAE,WAAW,EAAE,EACtB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,EAAE,CAAC,GACrC,cAAc;IAKjB,wFAAwF;IACjF,qBAAqB,CAC3B,OAAO,EAAE,WAAW,EAAE,EACtB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,EAAE,CAAC,GACrC,aAAa,EAAE;CAIlB"}
|
|
@@ -1,42 +1,6 @@
|
|
|
1
|
-
import { GLOBAL_SESSION_ID } from "../contracts/ids.js";
|
|
2
1
|
import { Aggregator } from "./evaluator/Aggregator.js";
|
|
3
2
|
import { PatternDetector } from "./evaluator/PatternDetector.js";
|
|
4
3
|
import { SignalComputer } from "./evaluator/SignalComputer.js";
|
|
5
|
-
class NoOpCalibrator {
|
|
6
|
-
enabled = false;
|
|
7
|
-
calibrate(rawConfidence, _type, _sessionId) {
|
|
8
|
-
const raw = Math.min(1, Math.max(0, rawConfidence));
|
|
9
|
-
return {
|
|
10
|
-
raw,
|
|
11
|
-
calibrated: raw,
|
|
12
|
-
temperature: 1.0,
|
|
13
|
-
priorWeight: 0
|
|
14
|
-
};
|
|
15
|
-
}
|
|
16
|
-
metrics(_sessionId) {
|
|
17
|
-
return {
|
|
18
|
-
brierScore: null,
|
|
19
|
-
ece: null,
|
|
20
|
-
sampleCount: 0,
|
|
21
|
-
perTypeBrier: {
|
|
22
|
-
regular: null,
|
|
23
|
-
hypothesis: null,
|
|
24
|
-
verification: null,
|
|
25
|
-
critique: null,
|
|
26
|
-
synthesis: null,
|
|
27
|
-
meta: null,
|
|
28
|
-
tool_call: null,
|
|
29
|
-
tool_observation: null,
|
|
30
|
-
assumption: null,
|
|
31
|
-
decomposition: null,
|
|
32
|
-
backtrack: null
|
|
33
|
-
}
|
|
34
|
-
};
|
|
35
|
-
}
|
|
36
|
-
refit(_sessionId) {}
|
|
37
|
-
clearSession(_sessionId) {}
|
|
38
|
-
clearAll() {}
|
|
39
|
-
}
|
|
40
4
|
class ThoughtEvaluator {
|
|
41
5
|
_signalComputer;
|
|
42
6
|
_aggregator;
|
|
@@ -46,15 +10,15 @@ class ThoughtEvaluator {
|
|
|
46
10
|
this._signalComputer = new SignalComputer();
|
|
47
11
|
this._aggregator = new Aggregator();
|
|
48
12
|
this._patternDetector = new PatternDetector();
|
|
49
|
-
this._calibrator = calibrator
|
|
13
|
+
this._calibrator = calibrator;
|
|
50
14
|
}
|
|
51
15
|
computeConfidenceSignals(history, branches, context) {
|
|
52
16
|
const { history: h, branches: b } = filterRetracted(history, branches);
|
|
53
17
|
const signals = this._signalComputer.computeConfidenceSignals(h, b);
|
|
54
18
|
if (!this._calibrator.enabled) return signals;
|
|
55
|
-
const thought = context
|
|
56
|
-
if (
|
|
57
|
-
const sessionId = context
|
|
19
|
+
const thought = context.currentThought;
|
|
20
|
+
if (void 0 === thought.confidence) return signals;
|
|
21
|
+
const sessionId = context.sessionId;
|
|
58
22
|
const result = this._calibrator.calibrate(thought.confidence, thought.thought_type ?? 'regular', sessionId);
|
|
59
23
|
return {
|
|
60
24
|
...signals,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"core/ThoughtEvaluator.js","sources":["../../src/core/ThoughtEvaluator.ts"],"sourcesContent":["/**\n * Quality signal computation for sequential thinking.\n *\n * Thin facade that composes the extracted evaluator submodules\n * ({@link SignalComputer}, {@link Aggregator}, {@link PatternDetector})\n * to preserve the original {@link ThoughtEvaluator} public API.\n *\n * @module core/ThoughtEvaluator\n */\n\nimport type {
|
|
1
|
+
{"version":3,"file":"core/ThoughtEvaluator.js","sources":["../../src/core/ThoughtEvaluator.ts"],"sourcesContent":["/**\n * Quality signal computation for sequential thinking.\n *\n * Thin facade that composes the extracted evaluator submodules\n * ({@link SignalComputer}, {@link Aggregator}, {@link PatternDetector})\n * to preserve the original {@link ThoughtEvaluator} public API.\n *\n * @module core/ThoughtEvaluator\n */\n\nimport type { ICalibrator } from '../contracts/calibrator.js';\nimport type { SessionId } from '../contracts/ids.js';\nimport type { ConfidenceSignals, PatternSignal, ReasoningStats } from './reasoning.js';\nimport type { ThoughtData } from './thought.js';\nimport { Aggregator } from './evaluator/Aggregator.js';\nimport { PatternDetector } from './evaluator/PatternDetector.js';\nimport { SignalComputer } from './evaluator/SignalComputer.js';\n\n/** Explicit thought and canonical session used for response calibration. */\nexport interface ConfidenceSignalContext {\n\treadonly currentThought: ThoughtData;\n\treadonly sessionId: SessionId;\n}\n\n/**\n * Stateless service that computes quality signals and reasoning analytics\n * from thought history and branch data.\n *\n * @remarks\n * All methods are pure computations — no side effects, no I/O, no internal state.\n * Designed to be registered as transient in the DI container.\n *\n * @example\n * ```typescript\n * const evaluator = new ThoughtEvaluator(calibrator);\n * const signals = evaluator.computeConfidenceSignals(history, branches, context);\n * const stats = evaluator.computeReasoningStats(history, branches);\n * const patterns = evaluator.computePatternSignals(history, branches);\n * ```\n */\nexport class ThoughtEvaluator {\n\tprivate readonly _signalComputer: SignalComputer;\n\tprivate readonly _aggregator: Aggregator;\n\tprivate readonly _patternDetector: PatternDetector;\n\tprivate readonly _calibrator: ICalibrator;\n\n\tconstructor(calibrator: ICalibrator) {\n\t\tthis._signalComputer = new SignalComputer();\n\t\tthis._aggregator = new Aggregator();\n\t\tthis._patternDetector = new PatternDetector();\n\t\tthis._calibrator = calibrator;\n\t}\n\n\t/** Compute confidence signals from history context. Pure computation. */\n\tpublic computeConfidenceSignals(\n\t\thistory: ThoughtData[],\n\t\tbranches: Record<string, ThoughtData[]>,\n\t\tcontext: ConfidenceSignalContext\n\t): ConfidenceSignals {\n\t\tconst { history: h, branches: b } = filterRetracted(history, branches);\n\t\tconst signals = this._signalComputer.computeConfidenceSignals(h, b);\n\t\tif (!this._calibrator.enabled) return signals;\n\n\t\tconst thought = context.currentThought;\n\t\tif (thought.confidence === undefined) return signals;\n\t\tconst sessionId = context.sessionId;\n\n\t\tconst result = this._calibrator.calibrate(\n\t\t\tthought.confidence,\n\t\t\tthought.thought_type ?? 'regular',\n\t\t\tsessionId\n\t\t);\n\t\treturn {\n\t\t\t...signals,\n\t\t\tcalibrated_confidence: result.calibrated,\n\t\t\tcalibration_metrics: this._calibrator.metrics(sessionId),\n\t\t};\n\t}\n\n\t/** Compute aggregated reasoning analytics. Pure computation. */\n\tpublic computeReasoningStats(\n\t\thistory: ThoughtData[],\n\t\tbranches: Record<string, ThoughtData[]>\n\t): ReasoningStats {\n\t\tconst { history: h, branches: b } = filterRetracted(history, branches);\n\t\treturn this._aggregator.computeReasoningStats(h, b);\n\t}\n\n\t/** Detect reasoning patterns (anti-patterns and positive signals). Pure computation. */\n\tpublic computePatternSignals(\n\t\thistory: ThoughtData[],\n\t\tbranches: Record<string, ThoughtData[]>\n\t): PatternSignal[] {\n\t\tconst { history: h, branches: b } = filterRetracted(history, branches);\n\t\treturn this._patternDetector.computePatternSignals(h, b);\n\t}\n}\n\n/**\n * Filters out logically retracted thoughts from history and branches.\n * Retracted thoughts remain in storage (event-sourcing) but are excluded\n * from quality signal calculations.\n */\nfunction filterRetracted(\n\thistory: ThoughtData[],\n\tbranches: Record<string, ThoughtData[]>\n): { history: ThoughtData[]; branches: Record<string, ThoughtData[]> } {\n\tconst h = history.filter((t) => !t.retracted);\n\tconst b: Record<string, ThoughtData[]> = {};\n\tfor (const [id, list] of Object.entries(branches)) {\n\t\tb[id] = list.filter((t) => !t.retracted);\n\t}\n\treturn { history: h, branches: b };\n}\n"],"names":["ThoughtEvaluator","calibrator","SignalComputer","Aggregator","PatternDetector","history","branches","context","h","b","filterRetracted","signals","thought","undefined","sessionId","result","t","id","list","Object"],"mappings":";;;AAwCO,MAAMA;IACK,gBAAgC;IAChC,YAAwB;IACxB,iBAAkC;IAClC,YAAyB;IAE1C,YAAYC,UAAuB,CAAE;QACpC,IAAI,CAAC,eAAe,GAAG,IAAIC;QAC3B,IAAI,CAAC,WAAW,GAAG,IAAIC;QACvB,IAAI,CAAC,gBAAgB,GAAG,IAAIC;QAC5B,IAAI,CAAC,WAAW,GAAGH;IACpB;IAGO,yBACNI,OAAsB,EACtBC,QAAuC,EACvCC,OAAgC,EACZ;QACpB,MAAM,EAAE,SAASC,CAAC,EAAE,UAAUC,CAAC,EAAE,GAAGC,gBAAgBL,SAASC;QAC7D,MAAMK,UAAU,IAAI,CAAC,eAAe,CAAC,wBAAwB,CAACH,GAAGC;QACjE,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,OAAO,EAAE,OAAOE;QAEtC,MAAMC,UAAUL,QAAQ,cAAc;QACtC,IAAIK,AAAuBC,WAAvBD,QAAQ,UAAU,EAAgB,OAAOD;QAC7C,MAAMG,YAAYP,QAAQ,SAAS;QAEnC,MAAMQ,SAAS,IAAI,CAAC,WAAW,CAAC,SAAS,CACxCH,QAAQ,UAAU,EAClBA,QAAQ,YAAY,IAAI,WACxBE;QAED,OAAO;YACN,GAAGH,OAAO;YACV,uBAAuBI,OAAO,UAAU;YACxC,qBAAqB,IAAI,CAAC,WAAW,CAAC,OAAO,CAACD;QAC/C;IACD;IAGO,sBACNT,OAAsB,EACtBC,QAAuC,EACtB;QACjB,MAAM,EAAE,SAASE,CAAC,EAAE,UAAUC,CAAC,EAAE,GAAGC,gBAAgBL,SAASC;QAC7D,OAAO,IAAI,CAAC,WAAW,CAAC,qBAAqB,CAACE,GAAGC;IAClD;IAGO,sBACNJ,OAAsB,EACtBC,QAAuC,EACrB;QAClB,MAAM,EAAE,SAASE,CAAC,EAAE,UAAUC,CAAC,EAAE,GAAGC,gBAAgBL,SAASC;QAC7D,OAAO,IAAI,CAAC,gBAAgB,CAAC,qBAAqB,CAACE,GAAGC;IACvD;AACD;AAOA,SAASC,gBACRL,OAAsB,EACtBC,QAAuC;IAEvC,MAAME,IAAIH,QAAQ,MAAM,CAAC,CAACW,IAAM,CAACA,EAAE,SAAS;IAC5C,MAAMP,IAAmC,CAAC;IAC1C,KAAK,MAAM,CAACQ,IAAIC,KAAK,IAAIC,OAAO,OAAO,CAACb,UACvCG,CAAC,CAACQ,GAAG,GAAGC,KAAK,MAAM,CAAC,CAACF,IAAM,CAACA,EAAE,SAAS;IAExC,OAAO;QAAE,SAASR;QAAG,UAAUC;IAAE;AAClC"}
|
|
@@ -63,7 +63,13 @@ export interface CallToolResult extends Record<string, unknown> {
|
|
|
63
63
|
* @example
|
|
64
64
|
* ```typescript
|
|
65
65
|
* const processor = new ThoughtProcessor(historyManager, formatter, new ThoughtEvaluator());
|
|
66
|
-
* const result = await processor.process({
|
|
66
|
+
* const result = await processor.process({
|
|
67
|
+
* thought: '...',
|
|
68
|
+
* thought_number: 1,
|
|
69
|
+
* total_thoughts: 5,
|
|
70
|
+
* next_thought_needed: true,
|
|
71
|
+
* session_id: asSessionId('analysis')
|
|
72
|
+
* });
|
|
67
73
|
* ```
|
|
68
74
|
*/
|
|
69
75
|
export declare class ThoughtProcessor {
|
|
@@ -161,7 +167,8 @@ export declare class ThoughtProcessor {
|
|
|
161
167
|
* thought: 'I should read the README file',
|
|
162
168
|
* thought_number: 1,
|
|
163
169
|
* total_thoughts: 3,
|
|
164
|
-
* next_thought_needed: true
|
|
170
|
+
* next_thought_needed: true,
|
|
171
|
+
* session_id: asSessionId('analysis')
|
|
165
172
|
* });
|
|
166
173
|
*
|
|
167
174
|
* console.log(result.content[0].text);
|
|
@@ -195,7 +202,7 @@ export declare class ThoughtProcessor {
|
|
|
195
202
|
/**
|
|
196
203
|
* Locate the root thought id for a branch.
|
|
197
204
|
* Prefers GraphView.branchThoughts() when an EdgeStore is available;
|
|
198
|
-
* falls back to historyManager.getBranches()[branchId][0].id.
|
|
205
|
+
* falls back to historyManager.getBranches(sessionId)[branchId][0].id.
|
|
199
206
|
* @private
|
|
200
207
|
*/
|
|
201
208
|
private _findBranchRoot;
|