@bastani/atomic 0.9.54 → 0.9.55

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.
Files changed (38) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/dist/builtin/intercom/CHANGELOG.md +14 -0
  3. package/dist/builtin/intercom/README.md +2 -1
  4. package/dist/builtin/intercom/broker/announce-on-import.ts +5 -0
  5. package/dist/builtin/intercom/broker/broker.ts +28 -0
  6. package/dist/builtin/intercom/broker/client.ts +48 -3
  7. package/dist/builtin/intercom/broker/paths.ts +9 -0
  8. package/dist/builtin/intercom/broker/socket-writes.ts +5 -0
  9. package/dist/builtin/intercom/broker/spawn.ts +58 -6
  10. package/dist/builtin/intercom/broker/start-announcement.ts +77 -0
  11. package/dist/builtin/intercom/broker/startup-timeout.ts +23 -0
  12. package/dist/builtin/intercom/index.bundle.mjs +184 -73
  13. package/dist/builtin/intercom/package.json +1 -1
  14. package/dist/builtin/intercom/recoverable-disconnect.ts +38 -2
  15. package/dist/builtin/mcp/package.json +1 -1
  16. package/dist/builtin/subagents/package.json +1 -1
  17. package/dist/builtin/web-access/package.json +1 -1
  18. package/dist/builtin/workflows/CHANGELOG.md +26 -0
  19. package/dist/builtin/workflows/package.json +1 -1
  20. package/dist/builtin/workflows/src/durable/journal/resolution.d.ts +7 -0
  21. package/dist/builtin/workflows/src/extension/index.bundle.mjs +8458 -7874
  22. package/dist/builtin/workflows/src/extension/local-worker-entry.mjs +687 -111
  23. package/dist/builtin/workflows/src/index.js +834 -264
  24. package/dist/builtin/workflows/src/local-worker-entry.mjs +687 -111
  25. package/dist/builtin/workflows/src/workers/public-options.d.ts +8 -0
  26. package/dist/core/extension-startup-failure.d.ts.map +1 -1
  27. package/dist/core/extension-startup-failure.js +1 -0
  28. package/dist/core/extension-startup-failure.js.map +1 -1
  29. package/dist/core/storage/session/jsonl-session-store.d.ts +27 -0
  30. package/dist/core/storage/session/jsonl-session-store.d.ts.map +1 -1
  31. package/dist/core/storage/session/jsonl-session-store.js +99 -7
  32. package/dist/core/storage/session/jsonl-session-store.js.map +1 -1
  33. package/docs/settings.md +2 -2
  34. package/docs/storage.md +2 -0
  35. package/docs/workflows/api-reference.md +3 -3
  36. package/docs/workflows/operations.md +3 -3
  37. package/npm-shrinkwrap.json +32 -32
  38. package/package.json +3 -3
@@ -24,6 +24,14 @@ export interface LocalWorkerOptions {
24
24
  }
25
25
  export interface WorkflowExecutionResources {
26
26
  readonly localWorkers?: LocalWorkerOptions;
27
+ /**
28
+ * Set when the root's journal is in another database than the pool's: the machine whose pool database holds the
29
+ * root's work queue and leases, which only that machine's coordinator can see, and the name of that database.
30
+ */
31
+ readonly coordinator?: {
32
+ readonly host: string;
33
+ readonly database: string;
34
+ };
27
35
  readonly admission?: WorkflowAdmissionOptions;
28
36
  readonly definitions?: readonly {
29
37
  readonly path: string;
@@ -1 +1 @@
1
- {"version":3,"file":"extension-startup-failure.d.ts","sourceRoot":"","sources":["../../src/core/extension-startup-failure.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,eAAO,MAAM,6BAA6B,2BAA2B,CAAC;AAEtE,MAAM,WAAW,uBAAuB;IACvC,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CACzB;AAMD,qBAAa,qBAAsB,SAAQ,cAAc;IACxD,QAAQ,CAAC,IAAI,4BAAiC;IAC9C,QAAQ,CAAC,QAAQ,EAAE,SAAS,uBAAuB,EAAE,CAAC;IAEtD,YAAY,QAAQ,EAAE,SAAS,uBAAuB,EAAE,EAOvD;CACD;AA0BD,yEAAyE;AACzE,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAEjE;AAED;;;;GAIG;AACH,wBAAgB,kCAAkC,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAQ1E;AAED,kGAAkG;AAClG,wBAAgB,4BAA4B,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,OAAO,EAAE,GAAG,MAAM,CAGhG"}
1
+ {"version":3,"file":"extension-startup-failure.d.ts","sourceRoot":"","sources":["../../src/core/extension-startup-failure.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,eAAO,MAAM,6BAA6B,2BAA2B,CAAC;AAEtE,MAAM,WAAW,uBAAuB;IACvC,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CACzB;AAMD,qBAAa,qBAAsB,SAAQ,cAAc;IACxD,QAAQ,CAAC,IAAI,4BAAiC;IAC9C,QAAQ,CAAC,QAAQ,EAAE,SAAS,uBAAuB,EAAE,CAAC;IAEtD,YAAY,QAAQ,EAAE,SAAS,uBAAuB,EAAE,EAOvD;CACD;AA2BD,yEAAyE;AACzE,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAEjE;AAED;;;;GAIG;AACH,wBAAgB,kCAAkC,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAQ1E;AAED,kGAAkG;AAClG,wBAAgB,4BAA4B,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,OAAO,EAAE,GAAG,MAAM,CAGhG"}
@@ -26,6 +26,7 @@ const TRANSIENT_EXTENSION_STARTUP_PATTERNS = [
26
26
  /\bconnect ENOENT\b/,
27
27
  /\bconnection closed\b|\bsocket hang up\b|\bclosed before registration\b/i,
28
28
  /\bexited before startup\b/i,
29
+ /\bbroker is retiring\b/i,
29
30
  ];
30
31
  function isExtensionStartupError(error) {
31
32
  return (error instanceof AggregateError &&
@@ -1 +1 @@
1
- {"version":3,"file":"extension-startup-failure.js","sourceRoot":"","sources":["../../src/core/extension-startup-failure.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,MAAM,CAAC,MAAM,6BAA6B,GAAG,wBAAwB,CAAC;AAQtE,SAAS,eAAe,CAAC,OAAgC;IACxD,OAAO,GAAG,OAAO,CAAC,aAAa,KAAK,OAAO,CAAC,OAAO,EAAE,CAAC;AACvD,CAAC;AAED,MAAM,OAAO,qBAAsB,SAAQ,cAAc;IAC/C,IAAI,GAAG,6BAA6B,CAAC;IACrC,QAAQ,CAAqC;IAEtD,YAAY,QAA4C;QACvD,KAAK,CACJ,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,IAAI,KAAK,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC,CAAC,EAC9D,6BAA6B,QAAQ,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CACvE,CAAC;QACF,IAAI,CAAC,IAAI,GAAG,uBAAuB,CAAC;QACpC,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;IAC1B,CAAC;CACD;AAED,yHAAyH;AACzH,MAAM,oCAAoC,GAAsB;IAC/D,kCAAkC;IAClC,oGAAoG;IACpG,oBAAoB;IACpB,0EAA0E;IAC1E,4BAA4B;CAC5B,CAAC;AAEF,SAAS,uBAAuB,CAAC,KAAc;IAC9C,OAAO,CACN,KAAK,YAAY,cAAc;QAC9B,KAAwC,CAAC,IAAI,KAAK,6BAA6B;QAChF,KAAK,CAAC,OAAO,CAAE,KAAwC,CAAC,QAAQ,CAAC,CACjE,CAAC;AACH,CAAC;AAED,SAAS,+BAA+B,CAAC,KAAc,EAAE,IAAkB;IAC1E,IAAI,CAAC,CAAC,KAAK,YAAY,cAAc,CAAC,IAAI,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IACxE,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IAChB,IAAI,uBAAuB,CAAC,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IAChD,OAAO,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,KAAc,EAAE,EAAE,CAAC,+BAA+B,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC,CAAC;AAC5F,CAAC;AAED,yEAAyE;AACzE,MAAM,UAAU,yBAAyB,CAAC,KAAc;IACvD,OAAO,+BAA+B,CAAC,KAAK,EAAE,IAAI,GAAG,EAAE,CAAC,CAAC;AAC1D,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,kCAAkC,CAAC,KAAc;IAChE,OAAO,CACN,uBAAuB,CAAC,KAAK,CAAC;QAC9B,KAAK,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC;QACzB,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,OAAO,EAAE,EAAE,CAChC,oCAAoC,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CACrF,CACD,CAAC;AACH,CAAC;AAED,kGAAkG;AAClG,MAAM,UAAU,4BAA4B,CAAC,OAAe,EAAE,MAA0B;IACvF,MAAM,OAAO,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAChG,OAAO,GAAG,OAAO,KAAK,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;AAC5C,CAAC","sourcesContent":["/**\n * Extension startup failures.\n *\n * A session whose extensions fail `session_start` or `resources_discover` is\n * rolled back and rejects with one `ExtensionStartupError`. Its message and\n * `failures` name every failing extension and its own error, so callers can\n * report and classify the failure without reading `AggregateError.errors`.\n */\n\nexport const EXTENSION_STARTUP_FAILED_CODE = \"ExtensionStartupFailed\";\n\nexport interface ExtensionStartupFailure {\n\treadonly extensionPath: string;\n\treadonly event: string;\n\treadonly message: string;\n}\n\nfunction describeFailure(failure: ExtensionStartupFailure): string {\n\treturn `${failure.extensionPath}: ${failure.message}`;\n}\n\nexport class ExtensionStartupError extends AggregateError {\n\treadonly code = EXTENSION_STARTUP_FAILED_CODE;\n\treadonly failures: readonly ExtensionStartupFailure[];\n\n\tconstructor(failures: readonly ExtensionStartupFailure[]) {\n\t\tsuper(\n\t\t\tfailures.map((failure) => new Error(describeFailure(failure))),\n\t\t\t`Extension startup failed: ${failures.map(describeFailure).join(\"; \")}`,\n\t\t);\n\t\tthis.name = \"ExtensionStartupError\";\n\t\tthis.failures = failures;\n\t}\n}\n\n/** Load- and timing-dependent errors, such as an Intercom broker that could not start or accept a connection in time. */\nconst TRANSIENT_EXTENSION_STARTUP_PATTERNS: readonly RegExp[] = [\n\t/\\btime[sd]?\\s*out\\b|\\btimeout\\b/i,\n\t/\\b(?:ECONNREFUSED|ECONNRESET|ECONNABORTED|EPIPE|EAGAIN|EBUSY|ETIMEDOUT|EMFILE|ENFILE|EADDRINUSE)\\b/,\n\t/\\bconnect ENOENT\\b/,\n\t/\\bconnection closed\\b|\\bsocket hang up\\b|\\bclosed before registration\\b/i,\n\t/\\bexited before startup\\b/i,\n];\n\nfunction isExtensionStartupError(error: unknown): error is ExtensionStartupError {\n\treturn (\n\t\terror instanceof AggregateError &&\n\t\t(error as Partial<ExtensionStartupError>).code === EXTENSION_STARTUP_FAILED_CODE &&\n\t\tArray.isArray((error as Partial<ExtensionStartupError>).failures)\n\t);\n}\n\nfunction aggregatesExtensionStartupError(error: unknown, seen: Set<unknown>): boolean {\n\tif (!(error instanceof AggregateError) || seen.has(error)) return false;\n\tseen.add(error);\n\tif (isExtensionStartupError(error)) return true;\n\treturn error.errors.some((inner: unknown) => aggregatesExtensionStartupError(inner, seen));\n}\n\n/** True when `error` is, or aggregates, an extension startup failure. */\nexport function isExtensionStartupFailure(error: unknown): boolean {\n\treturn aggregatesExtensionStartupError(error, new Set());\n}\n\n/**\n * True when a fresh session may succeed: every failing extension reported a\n * load- or timing-dependent error. A startup failure whose rollback also failed\n * is never transient, so its ownership problems are not retried over.\n */\nexport function isTransientExtensionStartupFailure(error: unknown): boolean {\n\treturn (\n\t\tisExtensionStartupError(error) &&\n\t\terror.failures.length > 0 &&\n\t\terror.failures.every((failure) =>\n\t\t\tTRANSIENT_EXTENSION_STARTUP_PATTERNS.some((pattern) => pattern.test(failure.message)),\n\t\t)\n\t);\n}\n\n/** Message for an aggregate that wraps a startup failure with the errors its cleanup reported. */\nexport function startupCleanupFailureMessage(summary: string, errors: readonly unknown[]): string {\n\tconst details = errors.map((error) => (error instanceof Error ? error.message : String(error)));\n\treturn `${summary}: ${details.join(\"; \")}`;\n}\n"]}
1
+ {"version":3,"file":"extension-startup-failure.js","sourceRoot":"","sources":["../../src/core/extension-startup-failure.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,MAAM,CAAC,MAAM,6BAA6B,GAAG,wBAAwB,CAAC;AAQtE,SAAS,eAAe,CAAC,OAAgC;IACxD,OAAO,GAAG,OAAO,CAAC,aAAa,KAAK,OAAO,CAAC,OAAO,EAAE,CAAC;AACvD,CAAC;AAED,MAAM,OAAO,qBAAsB,SAAQ,cAAc;IAC/C,IAAI,GAAG,6BAA6B,CAAC;IACrC,QAAQ,CAAqC;IAEtD,YAAY,QAA4C;QACvD,KAAK,CACJ,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,IAAI,KAAK,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC,CAAC,EAC9D,6BAA6B,QAAQ,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CACvE,CAAC;QACF,IAAI,CAAC,IAAI,GAAG,uBAAuB,CAAC;QACpC,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;IAC1B,CAAC;CACD;AAED,yHAAyH;AACzH,MAAM,oCAAoC,GAAsB;IAC/D,kCAAkC;IAClC,oGAAoG;IACpG,oBAAoB;IACpB,0EAA0E;IAC1E,4BAA4B;IAC5B,yBAAyB;CACzB,CAAC;AAEF,SAAS,uBAAuB,CAAC,KAAc;IAC9C,OAAO,CACN,KAAK,YAAY,cAAc;QAC9B,KAAwC,CAAC,IAAI,KAAK,6BAA6B;QAChF,KAAK,CAAC,OAAO,CAAE,KAAwC,CAAC,QAAQ,CAAC,CACjE,CAAC;AACH,CAAC;AAED,SAAS,+BAA+B,CAAC,KAAc,EAAE,IAAkB;IAC1E,IAAI,CAAC,CAAC,KAAK,YAAY,cAAc,CAAC,IAAI,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IACxE,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IAChB,IAAI,uBAAuB,CAAC,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IAChD,OAAO,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,KAAc,EAAE,EAAE,CAAC,+BAA+B,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC,CAAC;AAC5F,CAAC;AAED,yEAAyE;AACzE,MAAM,UAAU,yBAAyB,CAAC,KAAc;IACvD,OAAO,+BAA+B,CAAC,KAAK,EAAE,IAAI,GAAG,EAAE,CAAC,CAAC;AAC1D,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,kCAAkC,CAAC,KAAc;IAChE,OAAO,CACN,uBAAuB,CAAC,KAAK,CAAC;QAC9B,KAAK,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC;QACzB,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,OAAO,EAAE,EAAE,CAChC,oCAAoC,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CACrF,CACD,CAAC;AACH,CAAC;AAED,kGAAkG;AAClG,MAAM,UAAU,4BAA4B,CAAC,OAAe,EAAE,MAA0B;IACvF,MAAM,OAAO,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAChG,OAAO,GAAG,OAAO,KAAK,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;AAC5C,CAAC","sourcesContent":["/**\n * Extension startup failures.\n *\n * A session whose extensions fail `session_start` or `resources_discover` is\n * rolled back and rejects with one `ExtensionStartupError`. Its message and\n * `failures` name every failing extension and its own error, so callers can\n * report and classify the failure without reading `AggregateError.errors`.\n */\n\nexport const EXTENSION_STARTUP_FAILED_CODE = \"ExtensionStartupFailed\";\n\nexport interface ExtensionStartupFailure {\n\treadonly extensionPath: string;\n\treadonly event: string;\n\treadonly message: string;\n}\n\nfunction describeFailure(failure: ExtensionStartupFailure): string {\n\treturn `${failure.extensionPath}: ${failure.message}`;\n}\n\nexport class ExtensionStartupError extends AggregateError {\n\treadonly code = EXTENSION_STARTUP_FAILED_CODE;\n\treadonly failures: readonly ExtensionStartupFailure[];\n\n\tconstructor(failures: readonly ExtensionStartupFailure[]) {\n\t\tsuper(\n\t\t\tfailures.map((failure) => new Error(describeFailure(failure))),\n\t\t\t`Extension startup failed: ${failures.map(describeFailure).join(\"; \")}`,\n\t\t);\n\t\tthis.name = \"ExtensionStartupError\";\n\t\tthis.failures = failures;\n\t}\n}\n\n/** Load- and timing-dependent errors, such as an Intercom broker that could not start or accept a connection in time. */\nconst TRANSIENT_EXTENSION_STARTUP_PATTERNS: readonly RegExp[] = [\n\t/\\btime[sd]?\\s*out\\b|\\btimeout\\b/i,\n\t/\\b(?:ECONNREFUSED|ECONNRESET|ECONNABORTED|EPIPE|EAGAIN|EBUSY|ETIMEDOUT|EMFILE|ENFILE|EADDRINUSE)\\b/,\n\t/\\bconnect ENOENT\\b/,\n\t/\\bconnection closed\\b|\\bsocket hang up\\b|\\bclosed before registration\\b/i,\n\t/\\bexited before startup\\b/i,\n\t/\\bbroker is retiring\\b/i,\n];\n\nfunction isExtensionStartupError(error: unknown): error is ExtensionStartupError {\n\treturn (\n\t\terror instanceof AggregateError &&\n\t\t(error as Partial<ExtensionStartupError>).code === EXTENSION_STARTUP_FAILED_CODE &&\n\t\tArray.isArray((error as Partial<ExtensionStartupError>).failures)\n\t);\n}\n\nfunction aggregatesExtensionStartupError(error: unknown, seen: Set<unknown>): boolean {\n\tif (!(error instanceof AggregateError) || seen.has(error)) return false;\n\tseen.add(error);\n\tif (isExtensionStartupError(error)) return true;\n\treturn error.errors.some((inner: unknown) => aggregatesExtensionStartupError(inner, seen));\n}\n\n/** True when `error` is, or aggregates, an extension startup failure. */\nexport function isExtensionStartupFailure(error: unknown): boolean {\n\treturn aggregatesExtensionStartupError(error, new Set());\n}\n\n/**\n * True when a fresh session may succeed: every failing extension reported a\n * load- or timing-dependent error. A startup failure whose rollback also failed\n * is never transient, so its ownership problems are not retried over.\n */\nexport function isTransientExtensionStartupFailure(error: unknown): boolean {\n\treturn (\n\t\tisExtensionStartupError(error) &&\n\t\terror.failures.length > 0 &&\n\t\terror.failures.every((failure) =>\n\t\t\tTRANSIENT_EXTENSION_STARTUP_PATTERNS.some((pattern) => pattern.test(failure.message)),\n\t\t)\n\t);\n}\n\n/** Message for an aggregate that wraps a startup failure with the errors its cleanup reported. */\nexport function startupCleanupFailureMessage(summary: string, errors: readonly unknown[]): string {\n\tconst details = errors.map((error) => (error instanceof Error ? error.message : String(error)));\n\treturn `${summary}: ${details.join(\"; \")}`;\n}\n"]}
@@ -12,6 +12,17 @@ export declare class JsonlStoragePoisonedError extends Error {
12
12
  readonly rollbackCause: Error;
13
13
  constructor(location: string, cause: Error, rollbackCause: Error);
14
14
  }
15
+ /**
16
+ * The file-system calls the session lock makes, replaceable so a test can fail the ones that only
17
+ * fail on Windows. `rmdir` and `stat` are also what this store uses to clear a lock it could not release.
18
+ */
19
+ export interface SessionLockFs {
20
+ mkdir: typeof import("node:fs").mkdir;
21
+ rmdir: typeof import("node:fs").rmdir;
22
+ stat: typeof import("node:fs").stat;
23
+ utimes: typeof import("node:fs").utimes;
24
+ realpath: typeof import("node:fs").realpath;
25
+ }
15
26
  export declare class JsonlSessionStore implements SessionStore {
16
27
  private queue;
17
28
  private closed;
@@ -19,10 +30,18 @@ export declare class JsonlSessionStore implements SessionStore {
19
30
  private readonly directory;
20
31
  private readonly fileStates;
21
32
  private readonly exactDirectory;
33
+ private readonly lockFs;
34
+ /**
35
+ * Lock directories this store acquired and could not remove, by path, with the modification time they had
36
+ * then. Nothing refreshes them any more, so another process may take them only once they are stale; until
37
+ * then the store removes its own, recognised by that time, rather than waiting out the stale window.
38
+ */
39
+ private readonly unreleased;
22
40
  private constructor();
23
41
  static open(directory: string, options?: {
24
42
  exactDirectory?: boolean;
25
43
  scanExisting?: boolean;
44
+ lockFs?: SessionLockFs;
26
45
  }): Promise<JsonlSessionStore>;
27
46
  locationFor(header: SessionRecordHeader): string;
28
47
  get descriptor(): StorageDescriptor;
@@ -51,6 +70,14 @@ export declare class JsonlSessionStore implements SessionStore {
51
70
  close(): Promise<void>;
52
71
  private run;
53
72
  private exclusive;
73
+ /**
74
+ * Releases the lock. The directory removal is retried when Windows refuses it for a moment. If it never
75
+ * succeeds the work is still done, so the failure is not reported over it: the lock is remembered so this
76
+ * store's next acquire removes it at once, instead of waiting for it to go stale.
77
+ */
78
+ private release;
79
+ /** Removes a lock directory this store failed to release, if it still has the time it had then. */
80
+ private clearUnreleased;
54
81
  private checkAbort;
55
82
  private paths;
56
83
  private locate;
@@ -1 +1 @@
1
- {"version":3,"file":"jsonl-session-store.d.ts","sourceRoot":"","sources":["../../../../src/core/storage/session/jsonl-session-store.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"jsonl-session-store.d.ts","sourceRoot":"","sources":["../../../../src/core/storage/session/jsonl-session-store.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  import { createHash, randomUUID } from "node:crypto";
2
- import { createReadStream } from "node:fs";
2
+ import { createReadStream, rmdir as rmdirCallback, stat as statCallback } from "node:fs";
3
3
  import { appendFile, copyFile, link, mkdir, open, readdir, rename, stat, truncate, unlink, writeFile, } from "node:fs/promises";
4
4
  import { basename, dirname, join, resolve } from "node:path";
5
5
  import { createInterface } from "node:readline";
@@ -25,6 +25,10 @@ export class JsonlStoragePoisonedError extends Error {
25
25
  this.rollbackCause = rollbackCause;
26
26
  }
27
27
  }
28
+ /** Removing a lock directory fails with these on Windows while another handle, such as a scanner or indexer, holds it. */
29
+ const TRANSIENT_RELEASE_CODES = new Set(["EPERM", "EBUSY", "EACCES", "ENOTEMPTY"]);
30
+ /** Waits between attempts to remove the lock directory, about 1.5 s in all, far inside the lock's 10 s stale window. */
31
+ const RELEASE_BACKOFF_MS = [10, 20, 50, 100, 200, 400, 700];
28
32
  export class JsonlSessionStore {
29
33
  queue = Promise.resolve();
30
34
  closed = false;
@@ -32,12 +36,20 @@ export class JsonlSessionStore {
32
36
  directory;
33
37
  fileStates = new Map();
34
38
  exactDirectory;
35
- constructor(directory, exactDirectory) {
39
+ lockFs;
40
+ /**
41
+ * Lock directories this store acquired and could not remove, by path, with the modification time they had
42
+ * then. Nothing refreshes them any more, so another process may take them only once they are stale; until
43
+ * then the store removes its own, recognised by that time, rather than waiting out the stale window.
44
+ */
45
+ unreleased = new Map();
46
+ constructor(directory, exactDirectory, lockFs) {
36
47
  this.exactDirectory = exactDirectory;
37
48
  this.directory = resolve(directory);
49
+ this.lockFs = lockFs;
38
50
  }
39
51
  static async open(directory, options) {
40
- const store = new JsonlSessionStore(directory, options?.exactDirectory === true);
52
+ const store = new JsonlSessionStore(directory, options?.exactDirectory === true, options?.lockFs);
41
53
  await store.run(() => mkdir(store.directory, { recursive: true }).then(() => { }), false);
42
54
  if (options?.scanExisting !== false) {
43
55
  await store.run(async () => {
@@ -285,12 +297,14 @@ export class JsonlSessionStore {
285
297
  return result;
286
298
  }
287
299
  async exclusive(operation, signal, directory = this.directory) {
300
+ const lockfilePath = join(directory, ".session.lock");
288
301
  let release;
289
302
  for (;;) {
290
303
  this.checkAbort(signal);
291
304
  try {
292
305
  release = await lockfile.lock(directory, {
293
- lockfilePath: join(directory, ".session.lock"),
306
+ lockfilePath,
307
+ ...(this.lockFs ? { fs: this.lockFs } : {}),
294
308
  onCompromised: (cause) => {
295
309
  this.poisoned = new StorageUnavailableError(this.descriptor, cause);
296
310
  },
@@ -300,21 +314,84 @@ export class JsonlSessionStore {
300
314
  catch (cause) {
301
315
  if (cause.code !== "ELOCKED")
302
316
  throw cause;
317
+ if (await this.clearUnreleased(lockfilePath))
318
+ continue;
303
319
  await delay(5);
304
320
  }
305
321
  }
322
+ let result;
306
323
  try {
307
324
  this.checkAbort(signal);
308
325
  if (this.poisoned)
309
326
  throw this.poisoned;
310
- const result = await operation();
327
+ result = await operation();
311
328
  if (this.poisoned)
312
329
  throw this.poisoned;
313
- return result;
314
330
  }
315
- finally {
331
+ catch (cause) {
332
+ await this.release(release, lockfilePath);
333
+ throw cause;
334
+ }
335
+ await this.release(release, lockfilePath);
336
+ return result;
337
+ }
338
+ /**
339
+ * Releases the lock. The directory removal is retried when Windows refuses it for a moment. If it never
340
+ * succeeds the work is still done, so the failure is not reported over it: the lock is remembered so this
341
+ * store's next acquire removes it at once, instead of waiting for it to go stale.
342
+ */
343
+ async release(release, lockfilePath) {
344
+ const fs = this.lockFs ?? { rmdir: rmdirCallback, stat: statCallback };
345
+ try {
316
346
  await release();
347
+ return;
348
+ }
349
+ catch (cause) {
350
+ if (!TRANSIENT_RELEASE_CODES.has(cause.code ?? ""))
351
+ throw cause;
352
+ }
353
+ // proper-lockfile has already forgotten the lock, so removing the directory is all that is left.
354
+ for (const wait of RELEASE_BACKOFF_MS) {
355
+ await delay(wait);
356
+ try {
357
+ await removeDirectory(fs, lockfilePath);
358
+ return;
359
+ }
360
+ catch (cause) {
361
+ if (!TRANSIENT_RELEASE_CODES.has(cause.code ?? ""))
362
+ throw cause;
363
+ }
364
+ }
365
+ const modified = await statMtimeMs(fs, lockfilePath);
366
+ if (modified !== undefined)
367
+ this.unreleased.set(lockfilePath, modified);
368
+ }
369
+ /** Removes a lock directory this store failed to release, if it still has the time it had then. */
370
+ async clearUnreleased(lockfilePath) {
371
+ const expected = this.unreleased.get(lockfilePath);
372
+ if (expected === undefined)
373
+ return false;
374
+ const fs = this.lockFs ?? { rmdir: rmdirCallback, stat: statCallback };
375
+ const modified = await statMtimeMs(fs, lockfilePath);
376
+ if (modified === undefined) {
377
+ this.unreleased.delete(lockfilePath);
378
+ return true;
379
+ }
380
+ // Another process took the lock over once it went stale: it is theirs now.
381
+ if (modified !== expected) {
382
+ this.unreleased.delete(lockfilePath);
383
+ return false;
317
384
  }
385
+ try {
386
+ await removeDirectory(fs, lockfilePath);
387
+ }
388
+ catch (cause) {
389
+ if (!TRANSIENT_RELEASE_CODES.has(cause.code ?? ""))
390
+ throw cause;
391
+ return false;
392
+ }
393
+ this.unreleased.delete(lockfilePath);
394
+ return true;
318
395
  }
319
396
  checkAbort(signal) {
320
397
  if (signal?.aborted)
@@ -597,4 +674,19 @@ export class JsonlSessionStore {
597
674
  return `${[JSON.stringify({ type: "session", ...header }), ...entries.map((entry) => JSON.stringify(entry))].join("\n")}\n`;
598
675
  }
599
676
  }
677
+ function removeDirectory(fs, path) {
678
+ return new Promise((resolve, reject) => {
679
+ fs.rmdir(path, (error) => {
680
+ if (error && error.code !== "ENOENT")
681
+ reject(error);
682
+ else
683
+ resolve();
684
+ });
685
+ });
686
+ }
687
+ function statMtimeMs(fs, path) {
688
+ return new Promise((resolve) => {
689
+ fs.stat(path, (error, stats) => resolve(error ? undefined : stats.mtimeMs));
690
+ });
691
+ }
600
692
  //# sourceMappingURL=jsonl-session-store.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"jsonl-session-store.js","sourceRoot":"","sources":["../../../../src/core/storage/session/jsonl-session-store.ts"],"names":[],"mappings":"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","sourcesContent":["import { createHash, randomUUID } from \"node:crypto\";\nimport { type BigIntStats, createReadStream } from \"node:fs\";\nimport {\n\tappendFile,\n\tcopyFile,\n\tlink,\n\tmkdir,\n\topen,\n\treaddir,\n\trename,\n\tstat,\n\ttruncate,\n\tunlink,\n\twriteFile,\n} from \"node:fs/promises\";\nimport { basename, dirname, join, resolve } from \"node:path\";\nimport { createInterface } from \"node:readline\";\nimport { setTimeout as delay } from \"node:timers/promises\";\nimport lockfile from \"proper-lockfile\";\nimport { createSessionCwdMatcher } from \"../../../utils/canonical-path.ts\";\nimport type { SessionEntry } from \"../../session-manager-types.ts\";\nimport { validateSessionEntryStructure } from \"./entry-structure.js\";\nimport {\n\tSessionConflictError,\n\tSessionExistsError,\n\tSessionFormatVersionError,\n\tSessionIdMismatchError,\n\tSessionInvalidTextError,\n\tSessionInvalidTimestampError,\n\ttype SessionJsonValue,\n\tSessionNotFoundError,\n\tStorageUnavailableError,\n\tStoreClosedError,\n} from \"./errors.js\";\nimport {\n\tisCurrentSessionHeader,\n\ttype StoredSessionHeader,\n\tupgradeLegacySessionEntries,\n\tupgradeLegacySessionHeader,\n} from \"./legacy-format.js\";\nimport { summarizeSession } from \"./session-summary.js\";\nimport type {\n\tSessionListQuery,\n\tSessionRecordHeader,\n\tSessionSnapshot,\n\tSessionStore,\n\tSessionSummary,\n\tSessionWriteOptions,\n\tStorageDescriptor,\n} from \"./types.js\";\nimport { validateSessionEntries, validateSessionHeader, validateSessionText } from \"./validation.js\";\n\ninterface SessionFileState {\n\treadonly stamp: string;\n\treadonly identity: string;\n\treadonly headerStamp: string;\n\treadonly headerId: string;\n\treadonly lastEntryId: string | undefined;\n\treadonly witness: Buffer;\n\treadonly size: number;\n\treadonly lastSeq: number;\n\treadonly terminated: boolean;\n}\n\ntype JsonValue = SessionJsonValue;\n\nconst SCAN_FIRST_LINE_CHUNK_BYTES = 4096;\n\nexport interface JsonlSessionFile {\n\treadonly location: string;\n\treadonly header: SessionRecordHeader;\n\tread(): Promise<SessionSnapshot>;\n}\n\nexport { SessionFormatVersionError } from \"./errors.js\";\n\nexport class JsonlStoragePoisonedError extends Error {\n\treadonly location: string;\n\toverride readonly cause: Error;\n\treadonly rollbackCause: Error;\n\n\tconstructor(location: string, cause: Error, rollbackCause: Error) {\n\t\tsuper(`Session append and rollback failed at ${location}`, { cause });\n\t\tthis.name = \"JsonlStoragePoisonedError\";\n\t\tthis.location = location;\n\t\tthis.cause = cause;\n\t\tthis.rollbackCause = rollbackCause;\n\t}\n}\n\nexport class JsonlSessionStore implements SessionStore {\n\tprivate queue: Promise<void> = Promise.resolve();\n\tprivate closed = false;\n\tprivate poisoned: JsonlStoragePoisonedError | StorageUnavailableError | undefined;\n\tprivate readonly directory: string;\n\tprivate readonly fileStates = new Map<string, SessionFileState>();\n\n\tprivate readonly exactDirectory: boolean;\n\n\tprivate constructor(directory: string, exactDirectory: boolean) {\n\t\tthis.exactDirectory = exactDirectory;\n\t\tthis.directory = resolve(directory);\n\t}\n\n\tstatic async open(\n\t\tdirectory: string,\n\t\toptions?: { exactDirectory?: boolean; scanExisting?: boolean },\n\t): Promise<JsonlSessionStore> {\n\t\tconst store = new JsonlSessionStore(directory, options?.exactDirectory === true);\n\t\tawait store.run(() => mkdir(store.directory, { recursive: true }).then(() => {}), false);\n\t\tif (options?.scanExisting !== false) {\n\t\t\tawait store.run(async () => {\n\t\t\t\tfor (const path of await store.paths()) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tawait store.readSnapshot(path);\n\t\t\t\t\t} catch {\n\t\t\t\t\t\tstore.fileStates.delete(path);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t\treturn store;\n\t}\n\n\tlocationFor(header: SessionRecordHeader): string {\n\t\tconst projectName = `--${resolve(header.cwd)\n\t\t\t.replace(/^[/\\\\]/, \"\")\n\t\t\t.replace(/[/\\\\:]/g, \"-\")}--`;\n\t\tconst project = this.exactDirectory\n\t\t\t? this.directory\n\t\t\t: join(this.directory, Buffer.byteLength(projectName) <= 180 ? projectName : `--${this.key(header.cwd)}--`);\n\t\treturn join(project, `${header.createdAt.replace(/[:.]/g, \"-\")}_${this.key(header.id)}.jsonl`);\n\t}\n\n\tget descriptor(): StorageDescriptor {\n\t\treturn { adapter: \"jsonl\", location: this.directory };\n\t}\n\n\tcreate(\n\t\theader: SessionRecordHeader,\n\t\tentries: readonly SessionEntry[],\n\t\tlocation?: string,\n\t): Promise<{ readonly lastSeq: number }> {\n\t\treturn this.run(async () => {\n\t\t\tvalidateSessionHeader(header);\n\t\t\tvalidateSessionEntries(entries);\n\t\t\tconst existing = await this.locate(header.id);\n\t\t\tif (existing) throw new SessionExistsError(header.id);\n\t\t\tconst payload = this.encode(header, entries);\n\t\t\tconst path = location === undefined ? this.locationFor(header) : resolve(location);\n\t\t\tawait mkdir(resolve(path, \"..\"), { recursive: true });\n\t\t\tconst temporary = `${path}.${randomUUID()}.tmp`;\n\t\t\ttry {\n\t\t\t\tawait writeFile(temporary, payload, { flag: \"wx\" });\n\t\t\t\ttry {\n\t\t\t\t\tawait link(temporary, path);\n\t\t\t\t} catch (cause) {\n\t\t\t\t\tif ((cause as NodeJS.ErrnoException).code === \"EEXIST\") throw new SessionExistsError(header.id);\n\t\t\t\t\tthrow cause;\n\t\t\t\t}\n\t\t\t} finally {\n\t\t\t\tawait unlink(temporary).catch((cause: NodeJS.ErrnoException) => {\n\t\t\t\t\tif (cause.code !== \"ENOENT\") throw cause;\n\t\t\t\t});\n\t\t\t}\n\t\t\tawait this.remember(path, this.contentState(header, entries, payload));\n\t\t\treturn { lastSeq: entries.length };\n\t\t}, true);\n\t}\n\n\tappend(\n\t\tsessionId: string,\n\t\tentries: readonly SessionEntry[],\n\t\toptions: SessionWriteOptions,\n\t): Promise<{ readonly lastSeq: number }> {\n\t\treturn this.run(async () => {\n\t\t\tconst { path, state } = await this.forWrite(sessionId, options);\n\t\t\tvalidateSessionEntries(entries);\n\t\t\tif (entries.length === 0) return { lastSeq: state.lastSeq };\n\t\t\tlet payload = `${entries.map((entry) => JSON.stringify(entry)).join(\"\\n\")}\\n`;\n\t\t\tif (!state.terminated) payload = `\\n${payload}`;\n\t\t\tconst offset = state.size;\n\t\t\tif (entries.some((entry) => entry.type === \"compaction\")) {\n\t\t\t\tawait copyFile(\n\t\t\t\t\tpath,\n\t\t\t\t\t`${path}.${new Date().toISOString().replace(/[:.]/g, \"-\")}.${randomUUID()}.compact.bak`,\n\t\t\t\t);\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tawait appendFile(path, payload);\n\t\t\t} catch (cause) {\n\t\t\t\ttry {\n\t\t\t\t\tawait truncate(path, offset);\n\t\t\t\t} catch (rollbackCause) {\n\t\t\t\t\tthis.poisoned = new JsonlStoragePoisonedError(path, cause as Error, rollbackCause as Error);\n\t\t\t\t\tthrow this.poisoned;\n\t\t\t\t}\n\t\t\t\tthrow cause;\n\t\t\t}\n\t\t\tconst lastSeq = state.lastSeq + entries.length;\n\t\t\tawait this.remember(path, {\n\t\t\t\t...state,\n\t\t\t\tlastSeq,\n\t\t\t\tlastEntryId: entries.at(-1)?.id,\n\t\t\t\tterminated: true,\n\t\t\t\twitness: Buffer.from(Buffer.concat([state.witness, Buffer.from(payload)]).subarray(-64)),\n\t\t\t});\n\t\t\treturn { lastSeq };\n\t\t});\n\t}\n\n\treplace(\n\t\tsessionId: string,\n\t\theader: SessionRecordHeader,\n\t\tentries: readonly SessionEntry[],\n\t\toptions: SessionWriteOptions,\n\t): Promise<{ readonly lastSeq: number }> {\n\t\treturn this.run(async () => {\n\t\t\tconst { path } = await this.forWrite(sessionId, options);\n\t\t\tvalidateSessionHeader(header);\n\t\t\tvalidateSessionEntries(entries);\n\t\t\tif (header.id !== sessionId) throw new SessionIdMismatchError(sessionId, header.id);\n\t\t\tawait this.commit(path, header, entries);\n\t\t\treturn { lastSeq: entries.length };\n\t\t});\n\t}\n\n\tprivate async commit(path: string, header: SessionRecordHeader, entries: readonly SessionEntry[]): Promise<void> {\n\t\tconst payload = this.encode(header, entries);\n\t\tconst temporary = `${path}.${randomUUID()}.tmp`;\n\t\ttry {\n\t\t\tawait writeFile(temporary, payload, { flag: \"wx\" });\n\t\t\tawait rename(temporary, path);\n\t\t} finally {\n\t\t\tawait unlink(temporary).catch((cause: NodeJS.ErrnoException) => {\n\t\t\t\tif (cause.code !== \"ENOENT\") throw cause;\n\t\t\t});\n\t\t}\n\t\tawait this.remember(path, this.contentState(header, entries, payload));\n\t}\n\n\tload(sessionId: string): Promise<SessionSnapshot> {\n\t\treturn this.run(async () => {\n\t\t\tconst located = await this.locate(sessionId);\n\t\t\tif (!located) throw new SessionNotFoundError(sessionId);\n\t\t\treturn this.readPersisted(located.path, located.stored);\n\t\t});\n\t}\n\n\tloadFile(path: string): Promise<SessionSnapshot> {\n\t\treturn this.run(() => this.readPersisted(resolve(path)));\n\t}\n\n\tprivate async readPersisted(path: string, stored?: StoredSessionHeader): Promise<SessionSnapshot> {\n\t\tstored ??= await this.readFirstLine(path);\n\t\tconst directory = dirname(path);\n\t\tif (isCurrentSessionHeader(stored) || directory === this.directory) return this.readSnapshot(path, stored, true);\n\t\treturn this.exclusive(() => this.readSnapshot(path, undefined, true), undefined, directory);\n\t}\n\n\tfindFile(sessionId: string): Promise<string | undefined> {\n\t\treturn this.run(async () => (await this.locate(sessionId))?.path);\n\t}\n\n\treadHeader(sessionId: string): Promise<SessionRecordHeader | undefined> {\n\t\treturn this.run(async () => {\n\t\t\treturn (await this.locate(sessionId))?.header;\n\t\t});\n\t}\n\n\tdelete(sessionId: string): Promise<void> {\n\t\treturn this.run(async () => {\n\t\t\tconst known = [...this.fileStates.values()].some((state) => state.headerId === sessionId);\n\t\t\tconst located = await this.locate(sessionId);\n\t\t\tif (!located) {\n\t\t\t\tif (known) throw new SessionNotFoundError(sessionId);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tawait unlink(located.path);\n\t\t\tthis.fileStates.delete(located.path);\n\t\t});\n\t}\n\n\tasync *list(query: SessionListQuery): AsyncIterable<SessionSummary> {\n\t\tthis.checkAbort(query.signal);\n\t\tconst matchesCwd = query.cwd === undefined ? undefined : createSessionCwdMatcher(query.cwd);\n\t\tconst paths = await this.run(() => this.paths(), true, query.signal);\n\t\tfor (const path of paths) {\n\t\t\tconst summary = await this.run(\n\t\t\t\tasync () => {\n\t\t\t\t\tthis.checkAbort(query.signal);\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst header = await this.readHeaderAt(path);\n\t\t\t\t\t\tif (matchesCwd && !matchesCwd(header.cwd)) return undefined;\n\t\t\t\t\t\tif (!query.includeInternal && header.internal) return undefined;\n\t\t\t\t\t\treturn { ...summarizeSession(await this.readSnapshot(path)), location: path };\n\t\t\t\t\t} catch (cause) {\n\t\t\t\t\t\tconst error = cause as NodeJS.ErrnoException;\n\t\t\t\t\t\tif (error.path === path && (error.code === \"ENOENT\" || error.code === \"ENOTDIR\")) return undefined;\n\t\t\t\t\t\tif (\n\t\t\t\t\t\t\tcause instanceof SessionFormatVersionError ||\n\t\t\t\t\t\t\tcause instanceof SessionInvalidTextError ||\n\t\t\t\t\t\t\tcause instanceof SessionInvalidTimestampError ||\n\t\t\t\t\t\t\tcause instanceof SyntaxError\n\t\t\t\t\t\t)\n\t\t\t\t\t\t\treturn undefined;\n\t\t\t\t\t\tthrow cause;\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\ttrue,\n\t\t\t\tquery.signal,\n\t\t\t);\n\t\t\tthis.checkAbort(query.signal);\n\t\t\tif (summary) yield summary;\n\t\t}\n\t\tawait this.run(async () => this.checkAbort(query.signal), true, query.signal);\n\t}\n\n\tasync *scanFiles(): AsyncIterable<JsonlSessionFile> {\n\t\tfor (const location of await this.run(() => this.paths({ skipUnreadableDirectories: true }), false)) {\n\t\t\tlet header: SessionRecordHeader;\n\t\t\ttry {\n\t\t\t\theader = await this.run(\n\t\t\t\t\tasync () => this.readHeaderAt(location, await this.readFirstLine(location, SCAN_FIRST_LINE_CHUNK_BYTES)),\n\t\t\t\t\tfalse,\n\t\t\t\t);\n\t\t\t} catch {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tyield { location, header, read: () => this.run(() => this.readSnapshot(location), false) };\n\t\t}\n\t}\n\n\tasync findMostRecent(query: {\n\t\treadonly cwd: string;\n\t\treadonly includeInternal?: boolean;\n\t}): Promise<SessionSummary | undefined> {\n\t\tlet latest: SessionSummary | undefined;\n\t\tfor await (const summary of this.list(query)) {\n\t\t\tif (!latest || Date.parse(summary.modifiedAt) > Date.parse(latest.modifiedAt)) latest = summary;\n\t\t}\n\t\treturn latest;\n\t}\n\n\tclose(): Promise<void> {\n\t\tif (this.closed) return Promise.reject(new StoreClosedError(this.descriptor));\n\t\tthis.closed = true;\n\t\treturn this.queue;\n\t}\n\n\tprivate run<T>(operation: () => Promise<T>, locked = true, signal?: AbortSignal): Promise<T> {\n\t\tif (this.closed) return Promise.reject(new StoreClosedError(this.descriptor));\n\t\tconst result = this.queue.then(async () => {\n\t\t\tif (this.poisoned) throw this.poisoned;\n\t\t\ttry {\n\t\t\t\treturn await (locked ? this.exclusive(operation, signal) : operation());\n\t\t\t} catch (cause) {\n\t\t\t\tif (\n\t\t\t\t\tcause instanceof SessionConflictError ||\n\t\t\t\t\tcause instanceof SessionExistsError ||\n\t\t\t\t\tcause instanceof SessionNotFoundError ||\n\t\t\t\t\tcause instanceof SessionIdMismatchError ||\n\t\t\t\t\tcause instanceof SessionInvalidTextError ||\n\t\t\t\t\tcause instanceof SessionInvalidTimestampError ||\n\t\t\t\t\tcause instanceof SessionFormatVersionError ||\n\t\t\t\t\tcause instanceof JsonlStoragePoisonedError ||\n\t\t\t\t\tcause instanceof DOMException\n\t\t\t\t)\n\t\t\t\t\tthrow cause;\n\t\t\t\tthrow new StorageUnavailableError(this.descriptor, cause as Error);\n\t\t\t}\n\t\t});\n\t\tthis.queue = result.then(\n\t\t\t() => {},\n\t\t\t() => {},\n\t\t);\n\t\treturn result;\n\t}\n\n\tprivate async exclusive<T>(\n\t\toperation: () => Promise<T>,\n\t\tsignal?: AbortSignal,\n\t\tdirectory = this.directory,\n\t): Promise<T> {\n\t\tlet release: () => Promise<void>;\n\t\tfor (;;) {\n\t\t\tthis.checkAbort(signal);\n\t\t\ttry {\n\t\t\t\trelease = await lockfile.lock(directory, {\n\t\t\t\t\tlockfilePath: join(directory, \".session.lock\"),\n\t\t\t\t\tonCompromised: (cause) => {\n\t\t\t\t\t\tthis.poisoned = new StorageUnavailableError(this.descriptor, cause);\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t\tbreak;\n\t\t\t} catch (cause) {\n\t\t\t\tif ((cause as NodeJS.ErrnoException).code !== \"ELOCKED\") throw cause;\n\t\t\t\tawait delay(5);\n\t\t\t}\n\t\t}\n\t\ttry {\n\t\t\tthis.checkAbort(signal);\n\t\t\tif (this.poisoned) throw this.poisoned;\n\t\t\tconst result = await operation();\n\t\t\tif (this.poisoned) throw this.poisoned;\n\t\t\treturn result;\n\t\t} finally {\n\t\t\tawait release();\n\t\t}\n\t}\n\n\tprivate checkAbort(signal?: AbortSignal): void {\n\t\tif (signal?.aborted) throw new DOMException(\"Session listing aborted\", \"AbortError\");\n\t}\n\n\tprivate async paths(options: { readonly skipUnreadableDirectories?: boolean } = {}): Promise<string[]> {\n\t\tconst paths: string[] = [];\n\t\tfor (const entry of await readdir(this.directory, { withFileTypes: true })) {\n\t\t\tconst path = join(this.directory, entry.name);\n\t\t\tif ((entry.isDirectory() || entry.isSymbolicLink()) && !this.exactDirectory) {\n\t\t\t\tconst children = await readdir(path, { withFileTypes: true }).catch((cause: NodeJS.ErrnoException) => {\n\t\t\t\t\tif (cause.code === \"ENOENT\" || cause.code === \"ENOTDIR\") return [];\n\t\t\t\t\tif (options.skipUnreadableDirectories && (cause.code === \"EACCES\" || cause.code === \"EPERM\")) return [];\n\t\t\t\t\tthrow cause;\n\t\t\t\t});\n\t\t\t\tfor (const child of children) {\n\t\t\t\t\tif (child.isFile() && child.name.endsWith(\".jsonl\")) paths.push(join(path, child.name));\n\t\t\t\t}\n\t\t\t} else if (entry.isFile() && entry.name.endsWith(\".jsonl\")) paths.push(path);\n\t\t}\n\t\treturn paths;\n\t}\n\n\tprivate async locate(sessionId: string): Promise<\n\t\t| {\n\t\t\t\tpath: string;\n\t\t\t\theader: SessionRecordHeader;\n\t\t\t\tstored: StoredSessionHeader;\n\t\t\t\tstats: BigIntStats;\n\t\t\t\tstate: SessionFileState | undefined;\n\t\t }\n\t\t| undefined\n\t> {\n\t\tvalidateSessionText(\"sessionId\", sessionId);\n\t\tconst known = await this.locateKnown(sessionId);\n\t\tif (known) return known;\n\t\tconst suffix = `_${this.key(sessionId)}.jsonl`;\n\t\tconst paths = await this.paths();\n\t\tconst named = paths.filter((path) => basename(path).endsWith(suffix));\n\t\tconst others = paths.filter((path) => !named.includes(path));\n\t\treturn (await this.scan(sessionId, named)) ?? (await this.scan(sessionId, others));\n\t}\n\n\tprivate async scan(sessionId: string, paths: readonly string[]) {\n\t\tfor (const path of paths) {\n\t\t\tconst cached = this.fileStates.get(path);\n\t\t\tlet stored: StoredSessionHeader;\n\t\t\ttry {\n\t\t\t\tstored = await this.readFirstLine(path, SCAN_FIRST_LINE_CHUNK_BYTES);\n\t\t\t} catch (cause) {\n\t\t\t\t// Preserve requested-file errors only while its cached inode still owns the path.\n\t\t\t\tif (cached?.headerId === sessionId) {\n\t\t\t\t\tconst stats = await stat(path, { bigint: true });\n\t\t\t\t\tif (cached.identity === `${stats.dev}:${stats.ino}`) throw cause;\n\t\t\t\t\tthis.fileStates.delete(path);\n\t\t\t\t} else if (basename(path).match(/_([0-9a-f]{64})\\.jsonl$/)?.[1] === this.key(sessionId)) {\n\t\t\t\t\tthrow cause;\n\t\t\t\t}\n\t\t\t\t// An unidentifiable file cannot block lookup of unrelated sessions.\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (cached && cached.headerId !== stored.id) this.fileStates.delete(path);\n\t\t\tif (stored.id !== sessionId) continue;\n\t\t\tconst header = await this.readHeaderAt(path, stored);\n\t\t\tconst stats = await stat(path, { bigint: true });\n\t\t\tconst state = this.fileStates.get(path);\n\t\t\t// Keep same-ID baselines only as conflict evidence: forWrite checks the current inode\n\t\t\t// and rejects structural changes until an explicit load establishes a new baseline.\n\t\t\treturn { path, header, stored, stats, state };\n\t\t}\n\t\treturn undefined;\n\t}\n\n\tprivate async locateKnown(sessionId: string) {\n\t\tfor (const [path, cached] of this.fileStates) {\n\t\t\tif (cached.headerId !== sessionId) continue;\n\t\t\tconst parent = dirname(path);\n\t\t\tif (parent !== this.directory && (this.exactDirectory || dirname(parent) !== this.directory)) return undefined;\n\t\t\tlet stored: StoredSessionHeader;\n\t\t\ttry {\n\t\t\t\tstored = await this.readFirstLine(path);\n\t\t\t} catch (cause) {\n\t\t\t\tif ((cause as NodeJS.ErrnoException).code === \"ENOENT\") this.fileStates.delete(path);\n\t\t\t\treturn undefined;\n\t\t\t}\n\t\t\tif (stored.id !== sessionId) {\n\t\t\t\tthis.fileStates.delete(path);\n\t\t\t\treturn undefined;\n\t\t\t}\n\t\t\tconst header = await this.readHeaderAt(path, stored);\n\t\t\tconst stats = await stat(path, { bigint: true });\n\t\t\treturn { path, header, stored, stats, state: this.fileStates.get(path) };\n\t\t}\n\t\treturn undefined;\n\t}\n\n\tprivate key(sessionId: string): string {\n\t\treturn createHash(\"sha256\").update(sessionId).digest(\"hex\");\n\t}\n\n\tprivate async readFirstLine(path: string, chunkBytes = 1): Promise<StoredSessionHeader> {\n\t\tconst file = await open(path, \"r\");\n\t\ttry {\n\t\t\tconst chunks: Buffer[] = [];\n\t\t\tconst buffer = Buffer.alloc(chunkBytes);\n\t\t\twhile (true) {\n\t\t\t\tconst { bytesRead } = await file.read(buffer, 0, buffer.length, null);\n\t\t\t\tif (!bytesRead) break;\n\t\t\t\tconst newline = buffer.subarray(0, bytesRead).indexOf(10);\n\t\t\t\tchunks.push(Buffer.from(buffer.subarray(0, newline === -1 ? bytesRead : newline)));\n\t\t\t\tif (newline !== -1) break;\n\t\t\t}\n\t\t\tconst value = JSON.parse(Buffer.concat(chunks).toString(\"utf8\")) as JsonValue;\n\t\t\treturn value !== null && typeof value === \"object\" && !Array.isArray(value)\n\t\t\t\t? (value as StoredSessionHeader)\n\t\t\t\t: {};\n\t\t} finally {\n\t\t\tawait file.close();\n\t\t}\n\t}\n\n\tprivate async readHeaderAt(path: string, stored?: StoredSessionHeader): Promise<SessionRecordHeader> {\n\t\tstored ??= await this.readFirstLine(path);\n\t\tconst { type: _type, ...header } = isCurrentSessionHeader(stored)\n\t\t\t? (stored as SessionRecordHeader & { type: \"session\" })\n\t\t\t: upgradeLegacySessionHeader(stored, path);\n\t\tif (\n\t\t\t_type !== \"session\" ||\n\t\t\ttypeof header.id !== \"string\" ||\n\t\t\ttypeof header.cwd !== \"string\" ||\n\t\t\ttypeof header.createdAt !== \"string\"\n\t\t) {\n\t\t\tthrow new SessionFormatVersionError(path, stored.version);\n\t\t}\n\t\tvalidateSessionHeader(header);\n\t\treturn header;\n\t}\n\n\tprivate async readSnapshot(\n\t\tpath: string,\n\t\tstored?: StoredSessionHeader,\n\t\tpersistUpgrade = false,\n\t): Promise<SessionSnapshot> {\n\t\tstored ??= await this.readFirstLine(path);\n\t\tconst header = await this.readHeaderAt(path, stored);\n\t\tconst input = createReadStream(path);\n\t\tlet witness: Buffer = Buffer.alloc(0);\n\t\tlet terminated = false;\n\t\tinput.on(\"data\", (chunk: string | Buffer) => {\n\t\t\tconst bytes = typeof chunk === \"string\" ? Buffer.from(chunk) : chunk;\n\t\t\twitness = Buffer.from(Buffer.concat([witness, bytes]).subarray(-64));\n\t\t\tterminated = bytes.at(-1) === 10;\n\t\t});\n\t\tconst lines = createInterface({ input, crlfDelay: Infinity });\n\t\tconst entries: SessionEntry[] = [];\n\t\tlet first = true;\n\t\ttry {\n\t\t\tfor await (const line of lines) {\n\t\t\t\tif (first) {\n\t\t\t\t\tfirst = false;\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tif (line.trim()) entries.push(JSON.parse(line) as SessionEntry);\n\t\t\t}\n\t\t} finally {\n\t\t\tlines.close();\n\t\t\tinput.destroy();\n\t\t}\n\t\tif (!isCurrentSessionHeader(stored)) {\n\t\t\tconst upgraded = upgradeLegacySessionEntries(stored, entries, path).entries;\n\t\t\tvalidateSessionEntryStructure(upgraded, path);\n\t\t\tvalidateSessionEntries(upgraded);\n\t\t\tif (persistUpgrade) await this.commit(path, header, upgraded);\n\t\t\treturn { header, entries: upgraded, lastSeq: upgraded.length };\n\t\t}\n\t\tvalidateSessionEntryStructure(entries, path);\n\t\tvalidateSessionEntries(entries);\n\t\tawait this.remember(path, {\n\t\t\theaderStamp: JSON.stringify(header),\n\t\t\theaderId: header.id,\n\t\t\tlastSeq: entries.length,\n\t\t\tlastEntryId: entries.at(-1)?.id,\n\t\t\twitness,\n\t\t\tterminated,\n\t\t});\n\t\treturn { header, entries, lastSeq: entries.length };\n\t}\n\n\tprivate stamp(stats: BigIntStats): string {\n\t\treturn `${stats.dev}:${stats.ino}:${stats.size}:${stats.mtimeNs}:${stats.ctimeNs}`;\n\t}\n\n\tprivate contentState(\n\t\theader: SessionRecordHeader,\n\t\tentries: readonly SessionEntry[],\n\t\tcontent: string,\n\t): Omit<SessionFileState, \"stamp\" | \"identity\" | \"size\"> {\n\t\treturn {\n\t\t\theaderStamp: JSON.stringify(header),\n\t\t\tlastSeq: entries.length,\n\t\t\theaderId: header.id,\n\t\t\tlastEntryId: entries.at(-1)?.id,\n\t\t\tterminated: content.endsWith(\"\\n\"),\n\t\t\twitness: Buffer.from(Buffer.from(content).subarray(-64)),\n\t\t};\n\t}\n\n\tprivate async remember(path: string, state: Omit<SessionFileState, \"stamp\" | \"identity\" | \"size\">): Promise<void> {\n\t\tconst stats = await stat(path, { bigint: true });\n\t\tthis.fileStates.set(path, {\n\t\t\t...state,\n\t\t\tstamp: this.stamp(stats),\n\t\t\tidentity: `${stats.dev}:${stats.ino}`,\n\t\t\tsize: Number(stats.size),\n\t\t});\n\t}\n\n\t/**\n\t * Foreign appends read only the header, at most 64 known boundary bytes, and new bytes.\n\t * The witness detects a changed append boundary, not arbitrary edits in old history.\n\t * Structural changes require an explicit load; they never trigger a hidden full reread.\n\t */\n\tprivate async forWrite(\n\t\tsessionId: string,\n\t\toptions: SessionWriteOptions,\n\t): Promise<{ path: string; state: SessionFileState }> {\n\t\tconst located = await this.locate(sessionId);\n\t\tif (!located) throw new SessionNotFoundError(sessionId);\n\t\tconst { path, header, stored, stats } = located;\n\t\tif (!isCurrentSessionHeader(stored)) throw new SessionFormatVersionError(path, stored.version);\n\t\tlet state = located.state;\n\t\tif (!state) {\n\t\t\tawait this.readSnapshot(path);\n\t\t\tstate = this.fileStates.get(path)!;\n\t\t} else {\n\t\t\tconst lastSeq = state.lastSeq;\n\t\t\tconst stale = () => new SessionConflictError(sessionId, options.expectSeq, lastSeq);\n\t\t\tif (\n\t\t\t\tstate.identity !== `${stats.dev}:${stats.ino}` ||\n\t\t\t\tstate.headerStamp !== JSON.stringify(header) ||\n\t\t\t\tNumber(stats.size) < state.size\n\t\t\t)\n\t\t\t\tthrow stale();\n\t\t\tif (state.stamp !== this.stamp(stats)) {\n\t\t\t\tconst file = await open(path, \"r\");\n\t\t\t\tconst offset = state.size - state.witness.length;\n\t\t\t\tconst bytes = Buffer.alloc(Number(stats.size) - offset);\n\t\t\t\ttry {\n\t\t\t\t\tlet read = 0;\n\t\t\t\t\twhile (read < bytes.length) {\n\t\t\t\t\t\tconst { bytesRead } = await file.read(bytes, read, bytes.length - read, offset + read);\n\t\t\t\t\t\tif (!bytesRead) throw stale();\n\t\t\t\t\t\tread += bytesRead;\n\t\t\t\t\t}\n\t\t\t\t} finally {\n\t\t\t\t\tawait file.close();\n\t\t\t\t}\n\t\t\t\tif (!bytes.subarray(0, state.witness.length).equals(state.witness)) throw stale();\n\t\t\t\tlet appended = bytes.subarray(state.witness.length).toString(\"utf8\");\n\t\t\t\tif (appended && !state.terminated) {\n\t\t\t\t\tif (!appended.startsWith(\"\\n\")) throw stale();\n\t\t\t\t\tappended = appended.slice(1);\n\t\t\t\t}\n\t\t\t\tconst lines = appended.split(\"\\n\");\n\t\t\t\tif (lines.at(-1) === \"\") lines.pop();\n\t\t\t\tconst entries = lines.map((line) => JSON.parse(line) as SessionEntry);\n\t\t\t\tvalidateSessionEntryStructure(entries, path);\n\t\t\t\tvalidateSessionEntries(entries);\n\t\t\t\tstate = {\n\t\t\t\t\t...state,\n\t\t\t\t\tstamp: this.stamp(stats),\n\t\t\t\t\tsize: Number(stats.size),\n\t\t\t\t\tlastSeq: state.lastSeq + entries.length,\n\t\t\t\t\tlastEntryId: entries.at(-1)?.id ?? state.lastEntryId,\n\t\t\t\t\tterminated: bytes.at(-1) === 10,\n\t\t\t\t\twitness: Buffer.from(bytes.subarray(-64)),\n\t\t\t\t};\n\t\t\t\tthis.fileStates.set(path, state);\n\t\t\t}\n\t\t}\n\t\tif (state.lastSeq !== options.expectSeq)\n\t\t\tthrow new SessionConflictError(sessionId, options.expectSeq, state.lastSeq);\n\t\treturn { path, state };\n\t}\n\n\tprivate encode(header: SessionRecordHeader, entries: readonly SessionEntry[]): string {\n\t\treturn `${[JSON.stringify({ type: \"session\", ...header }), ...entries.map((entry) => JSON.stringify(entry))].join(\"\\n\")}\\n`;\n\t}\n}\n"]}
1
+ {"version":3,"file":"jsonl-session-store.js","sourceRoot":"","sources":["../../../../src/core/storage/session/jsonl-session-store.ts"],"names":[],"mappings":"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","sourcesContent":["import { createHash, randomUUID } from \"node:crypto\";\nimport { type BigIntStats, createReadStream, rmdir as rmdirCallback, stat as statCallback } from \"node:fs\";\nimport {\n\tappendFile,\n\tcopyFile,\n\tlink,\n\tmkdir,\n\topen,\n\treaddir,\n\trename,\n\tstat,\n\ttruncate,\n\tunlink,\n\twriteFile,\n} from \"node:fs/promises\";\nimport { basename, dirname, join, resolve } from \"node:path\";\nimport { createInterface } from \"node:readline\";\nimport { setTimeout as delay } from \"node:timers/promises\";\nimport lockfile from \"proper-lockfile\";\nimport { createSessionCwdMatcher } from \"../../../utils/canonical-path.ts\";\nimport type { SessionEntry } from \"../../session-manager-types.ts\";\nimport { validateSessionEntryStructure } from \"./entry-structure.js\";\nimport {\n\tSessionConflictError,\n\tSessionExistsError,\n\tSessionFormatVersionError,\n\tSessionIdMismatchError,\n\tSessionInvalidTextError,\n\tSessionInvalidTimestampError,\n\ttype SessionJsonValue,\n\tSessionNotFoundError,\n\tStorageUnavailableError,\n\tStoreClosedError,\n} from \"./errors.js\";\nimport {\n\tisCurrentSessionHeader,\n\ttype StoredSessionHeader,\n\tupgradeLegacySessionEntries,\n\tupgradeLegacySessionHeader,\n} from \"./legacy-format.js\";\nimport { summarizeSession } from \"./session-summary.js\";\nimport type {\n\tSessionListQuery,\n\tSessionRecordHeader,\n\tSessionSnapshot,\n\tSessionStore,\n\tSessionSummary,\n\tSessionWriteOptions,\n\tStorageDescriptor,\n} from \"./types.js\";\nimport { validateSessionEntries, validateSessionHeader, validateSessionText } from \"./validation.js\";\n\ninterface SessionFileState {\n\treadonly stamp: string;\n\treadonly identity: string;\n\treadonly headerStamp: string;\n\treadonly headerId: string;\n\treadonly lastEntryId: string | undefined;\n\treadonly witness: Buffer;\n\treadonly size: number;\n\treadonly lastSeq: number;\n\treadonly terminated: boolean;\n}\n\ntype JsonValue = SessionJsonValue;\n\nconst SCAN_FIRST_LINE_CHUNK_BYTES = 4096;\n\nexport interface JsonlSessionFile {\n\treadonly location: string;\n\treadonly header: SessionRecordHeader;\n\tread(): Promise<SessionSnapshot>;\n}\n\nexport { SessionFormatVersionError } from \"./errors.js\";\n\nexport class JsonlStoragePoisonedError extends Error {\n\treadonly location: string;\n\toverride readonly cause: Error;\n\treadonly rollbackCause: Error;\n\n\tconstructor(location: string, cause: Error, rollbackCause: Error) {\n\t\tsuper(`Session append and rollback failed at ${location}`, { cause });\n\t\tthis.name = \"JsonlStoragePoisonedError\";\n\t\tthis.location = location;\n\t\tthis.cause = cause;\n\t\tthis.rollbackCause = rollbackCause;\n\t}\n}\n\n/**\n * The file-system calls the session lock makes, replaceable so a test can fail the ones that only\n * fail on Windows. `rmdir` and `stat` are also what this store uses to clear a lock it could not release.\n */\nexport interface SessionLockFs {\n\tmkdir: typeof import(\"node:fs\").mkdir;\n\trmdir: typeof import(\"node:fs\").rmdir;\n\tstat: typeof import(\"node:fs\").stat;\n\tutimes: typeof import(\"node:fs\").utimes;\n\trealpath: typeof import(\"node:fs\").realpath;\n}\n\n/** Removing a lock directory fails with these on Windows while another handle, such as a scanner or indexer, holds it. */\nconst TRANSIENT_RELEASE_CODES = new Set([\"EPERM\", \"EBUSY\", \"EACCES\", \"ENOTEMPTY\"]);\n/** Waits between attempts to remove the lock directory, about 1.5 s in all, far inside the lock's 10 s stale window. */\nconst RELEASE_BACKOFF_MS = [10, 20, 50, 100, 200, 400, 700];\n\nexport class JsonlSessionStore implements SessionStore {\n\tprivate queue: Promise<void> = Promise.resolve();\n\tprivate closed = false;\n\tprivate poisoned: JsonlStoragePoisonedError | StorageUnavailableError | undefined;\n\tprivate readonly directory: string;\n\tprivate readonly fileStates = new Map<string, SessionFileState>();\n\n\tprivate readonly exactDirectory: boolean;\n\tprivate readonly lockFs: SessionLockFs | undefined;\n\t/**\n\t * Lock directories this store acquired and could not remove, by path, with the modification time they had\n\t * then. Nothing refreshes them any more, so another process may take them only once they are stale; until\n\t * then the store removes its own, recognised by that time, rather than waiting out the stale window.\n\t */\n\tprivate readonly unreleased = new Map<string, number>();\n\n\tprivate constructor(directory: string, exactDirectory: boolean, lockFs?: SessionLockFs) {\n\t\tthis.exactDirectory = exactDirectory;\n\t\tthis.directory = resolve(directory);\n\t\tthis.lockFs = lockFs;\n\t}\n\n\tstatic async open(\n\t\tdirectory: string,\n\t\toptions?: { exactDirectory?: boolean; scanExisting?: boolean; lockFs?: SessionLockFs },\n\t): Promise<JsonlSessionStore> {\n\t\tconst store = new JsonlSessionStore(directory, options?.exactDirectory === true, options?.lockFs);\n\t\tawait store.run(() => mkdir(store.directory, { recursive: true }).then(() => {}), false);\n\t\tif (options?.scanExisting !== false) {\n\t\t\tawait store.run(async () => {\n\t\t\t\tfor (const path of await store.paths()) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tawait store.readSnapshot(path);\n\t\t\t\t\t} catch {\n\t\t\t\t\t\tstore.fileStates.delete(path);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t\treturn store;\n\t}\n\n\tlocationFor(header: SessionRecordHeader): string {\n\t\tconst projectName = `--${resolve(header.cwd)\n\t\t\t.replace(/^[/\\\\]/, \"\")\n\t\t\t.replace(/[/\\\\:]/g, \"-\")}--`;\n\t\tconst project = this.exactDirectory\n\t\t\t? this.directory\n\t\t\t: join(this.directory, Buffer.byteLength(projectName) <= 180 ? projectName : `--${this.key(header.cwd)}--`);\n\t\treturn join(project, `${header.createdAt.replace(/[:.]/g, \"-\")}_${this.key(header.id)}.jsonl`);\n\t}\n\n\tget descriptor(): StorageDescriptor {\n\t\treturn { adapter: \"jsonl\", location: this.directory };\n\t}\n\n\tcreate(\n\t\theader: SessionRecordHeader,\n\t\tentries: readonly SessionEntry[],\n\t\tlocation?: string,\n\t): Promise<{ readonly lastSeq: number }> {\n\t\treturn this.run(async () => {\n\t\t\tvalidateSessionHeader(header);\n\t\t\tvalidateSessionEntries(entries);\n\t\t\tconst existing = await this.locate(header.id);\n\t\t\tif (existing) throw new SessionExistsError(header.id);\n\t\t\tconst payload = this.encode(header, entries);\n\t\t\tconst path = location === undefined ? this.locationFor(header) : resolve(location);\n\t\t\tawait mkdir(resolve(path, \"..\"), { recursive: true });\n\t\t\tconst temporary = `${path}.${randomUUID()}.tmp`;\n\t\t\ttry {\n\t\t\t\tawait writeFile(temporary, payload, { flag: \"wx\" });\n\t\t\t\ttry {\n\t\t\t\t\tawait link(temporary, path);\n\t\t\t\t} catch (cause) {\n\t\t\t\t\tif ((cause as NodeJS.ErrnoException).code === \"EEXIST\") throw new SessionExistsError(header.id);\n\t\t\t\t\tthrow cause;\n\t\t\t\t}\n\t\t\t} finally {\n\t\t\t\tawait unlink(temporary).catch((cause: NodeJS.ErrnoException) => {\n\t\t\t\t\tif (cause.code !== \"ENOENT\") throw cause;\n\t\t\t\t});\n\t\t\t}\n\t\t\tawait this.remember(path, this.contentState(header, entries, payload));\n\t\t\treturn { lastSeq: entries.length };\n\t\t}, true);\n\t}\n\n\tappend(\n\t\tsessionId: string,\n\t\tentries: readonly SessionEntry[],\n\t\toptions: SessionWriteOptions,\n\t): Promise<{ readonly lastSeq: number }> {\n\t\treturn this.run(async () => {\n\t\t\tconst { path, state } = await this.forWrite(sessionId, options);\n\t\t\tvalidateSessionEntries(entries);\n\t\t\tif (entries.length === 0) return { lastSeq: state.lastSeq };\n\t\t\tlet payload = `${entries.map((entry) => JSON.stringify(entry)).join(\"\\n\")}\\n`;\n\t\t\tif (!state.terminated) payload = `\\n${payload}`;\n\t\t\tconst offset = state.size;\n\t\t\tif (entries.some((entry) => entry.type === \"compaction\")) {\n\t\t\t\tawait copyFile(\n\t\t\t\t\tpath,\n\t\t\t\t\t`${path}.${new Date().toISOString().replace(/[:.]/g, \"-\")}.${randomUUID()}.compact.bak`,\n\t\t\t\t);\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tawait appendFile(path, payload);\n\t\t\t} catch (cause) {\n\t\t\t\ttry {\n\t\t\t\t\tawait truncate(path, offset);\n\t\t\t\t} catch (rollbackCause) {\n\t\t\t\t\tthis.poisoned = new JsonlStoragePoisonedError(path, cause as Error, rollbackCause as Error);\n\t\t\t\t\tthrow this.poisoned;\n\t\t\t\t}\n\t\t\t\tthrow cause;\n\t\t\t}\n\t\t\tconst lastSeq = state.lastSeq + entries.length;\n\t\t\tawait this.remember(path, {\n\t\t\t\t...state,\n\t\t\t\tlastSeq,\n\t\t\t\tlastEntryId: entries.at(-1)?.id,\n\t\t\t\tterminated: true,\n\t\t\t\twitness: Buffer.from(Buffer.concat([state.witness, Buffer.from(payload)]).subarray(-64)),\n\t\t\t});\n\t\t\treturn { lastSeq };\n\t\t});\n\t}\n\n\treplace(\n\t\tsessionId: string,\n\t\theader: SessionRecordHeader,\n\t\tentries: readonly SessionEntry[],\n\t\toptions: SessionWriteOptions,\n\t): Promise<{ readonly lastSeq: number }> {\n\t\treturn this.run(async () => {\n\t\t\tconst { path } = await this.forWrite(sessionId, options);\n\t\t\tvalidateSessionHeader(header);\n\t\t\tvalidateSessionEntries(entries);\n\t\t\tif (header.id !== sessionId) throw new SessionIdMismatchError(sessionId, header.id);\n\t\t\tawait this.commit(path, header, entries);\n\t\t\treturn { lastSeq: entries.length };\n\t\t});\n\t}\n\n\tprivate async commit(path: string, header: SessionRecordHeader, entries: readonly SessionEntry[]): Promise<void> {\n\t\tconst payload = this.encode(header, entries);\n\t\tconst temporary = `${path}.${randomUUID()}.tmp`;\n\t\ttry {\n\t\t\tawait writeFile(temporary, payload, { flag: \"wx\" });\n\t\t\tawait rename(temporary, path);\n\t\t} finally {\n\t\t\tawait unlink(temporary).catch((cause: NodeJS.ErrnoException) => {\n\t\t\t\tif (cause.code !== \"ENOENT\") throw cause;\n\t\t\t});\n\t\t}\n\t\tawait this.remember(path, this.contentState(header, entries, payload));\n\t}\n\n\tload(sessionId: string): Promise<SessionSnapshot> {\n\t\treturn this.run(async () => {\n\t\t\tconst located = await this.locate(sessionId);\n\t\t\tif (!located) throw new SessionNotFoundError(sessionId);\n\t\t\treturn this.readPersisted(located.path, located.stored);\n\t\t});\n\t}\n\n\tloadFile(path: string): Promise<SessionSnapshot> {\n\t\treturn this.run(() => this.readPersisted(resolve(path)));\n\t}\n\n\tprivate async readPersisted(path: string, stored?: StoredSessionHeader): Promise<SessionSnapshot> {\n\t\tstored ??= await this.readFirstLine(path);\n\t\tconst directory = dirname(path);\n\t\tif (isCurrentSessionHeader(stored) || directory === this.directory) return this.readSnapshot(path, stored, true);\n\t\treturn this.exclusive(() => this.readSnapshot(path, undefined, true), undefined, directory);\n\t}\n\n\tfindFile(sessionId: string): Promise<string | undefined> {\n\t\treturn this.run(async () => (await this.locate(sessionId))?.path);\n\t}\n\n\treadHeader(sessionId: string): Promise<SessionRecordHeader | undefined> {\n\t\treturn this.run(async () => {\n\t\t\treturn (await this.locate(sessionId))?.header;\n\t\t});\n\t}\n\n\tdelete(sessionId: string): Promise<void> {\n\t\treturn this.run(async () => {\n\t\t\tconst known = [...this.fileStates.values()].some((state) => state.headerId === sessionId);\n\t\t\tconst located = await this.locate(sessionId);\n\t\t\tif (!located) {\n\t\t\t\tif (known) throw new SessionNotFoundError(sessionId);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tawait unlink(located.path);\n\t\t\tthis.fileStates.delete(located.path);\n\t\t});\n\t}\n\n\tasync *list(query: SessionListQuery): AsyncIterable<SessionSummary> {\n\t\tthis.checkAbort(query.signal);\n\t\tconst matchesCwd = query.cwd === undefined ? undefined : createSessionCwdMatcher(query.cwd);\n\t\tconst paths = await this.run(() => this.paths(), true, query.signal);\n\t\tfor (const path of paths) {\n\t\t\tconst summary = await this.run(\n\t\t\t\tasync () => {\n\t\t\t\t\tthis.checkAbort(query.signal);\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst header = await this.readHeaderAt(path);\n\t\t\t\t\t\tif (matchesCwd && !matchesCwd(header.cwd)) return undefined;\n\t\t\t\t\t\tif (!query.includeInternal && header.internal) return undefined;\n\t\t\t\t\t\treturn { ...summarizeSession(await this.readSnapshot(path)), location: path };\n\t\t\t\t\t} catch (cause) {\n\t\t\t\t\t\tconst error = cause as NodeJS.ErrnoException;\n\t\t\t\t\t\tif (error.path === path && (error.code === \"ENOENT\" || error.code === \"ENOTDIR\")) return undefined;\n\t\t\t\t\t\tif (\n\t\t\t\t\t\t\tcause instanceof SessionFormatVersionError ||\n\t\t\t\t\t\t\tcause instanceof SessionInvalidTextError ||\n\t\t\t\t\t\t\tcause instanceof SessionInvalidTimestampError ||\n\t\t\t\t\t\t\tcause instanceof SyntaxError\n\t\t\t\t\t\t)\n\t\t\t\t\t\t\treturn undefined;\n\t\t\t\t\t\tthrow cause;\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\ttrue,\n\t\t\t\tquery.signal,\n\t\t\t);\n\t\t\tthis.checkAbort(query.signal);\n\t\t\tif (summary) yield summary;\n\t\t}\n\t\tawait this.run(async () => this.checkAbort(query.signal), true, query.signal);\n\t}\n\n\tasync *scanFiles(): AsyncIterable<JsonlSessionFile> {\n\t\tfor (const location of await this.run(() => this.paths({ skipUnreadableDirectories: true }), false)) {\n\t\t\tlet header: SessionRecordHeader;\n\t\t\ttry {\n\t\t\t\theader = await this.run(\n\t\t\t\t\tasync () => this.readHeaderAt(location, await this.readFirstLine(location, SCAN_FIRST_LINE_CHUNK_BYTES)),\n\t\t\t\t\tfalse,\n\t\t\t\t);\n\t\t\t} catch {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tyield { location, header, read: () => this.run(() => this.readSnapshot(location), false) };\n\t\t}\n\t}\n\n\tasync findMostRecent(query: {\n\t\treadonly cwd: string;\n\t\treadonly includeInternal?: boolean;\n\t}): Promise<SessionSummary | undefined> {\n\t\tlet latest: SessionSummary | undefined;\n\t\tfor await (const summary of this.list(query)) {\n\t\t\tif (!latest || Date.parse(summary.modifiedAt) > Date.parse(latest.modifiedAt)) latest = summary;\n\t\t}\n\t\treturn latest;\n\t}\n\n\tclose(): Promise<void> {\n\t\tif (this.closed) return Promise.reject(new StoreClosedError(this.descriptor));\n\t\tthis.closed = true;\n\t\treturn this.queue;\n\t}\n\n\tprivate run<T>(operation: () => Promise<T>, locked = true, signal?: AbortSignal): Promise<T> {\n\t\tif (this.closed) return Promise.reject(new StoreClosedError(this.descriptor));\n\t\tconst result = this.queue.then(async () => {\n\t\t\tif (this.poisoned) throw this.poisoned;\n\t\t\ttry {\n\t\t\t\treturn await (locked ? this.exclusive(operation, signal) : operation());\n\t\t\t} catch (cause) {\n\t\t\t\tif (\n\t\t\t\t\tcause instanceof SessionConflictError ||\n\t\t\t\t\tcause instanceof SessionExistsError ||\n\t\t\t\t\tcause instanceof SessionNotFoundError ||\n\t\t\t\t\tcause instanceof SessionIdMismatchError ||\n\t\t\t\t\tcause instanceof SessionInvalidTextError ||\n\t\t\t\t\tcause instanceof SessionInvalidTimestampError ||\n\t\t\t\t\tcause instanceof SessionFormatVersionError ||\n\t\t\t\t\tcause instanceof JsonlStoragePoisonedError ||\n\t\t\t\t\tcause instanceof DOMException\n\t\t\t\t)\n\t\t\t\t\tthrow cause;\n\t\t\t\tthrow new StorageUnavailableError(this.descriptor, cause as Error);\n\t\t\t}\n\t\t});\n\t\tthis.queue = result.then(\n\t\t\t() => {},\n\t\t\t() => {},\n\t\t);\n\t\treturn result;\n\t}\n\n\tprivate async exclusive<T>(\n\t\toperation: () => Promise<T>,\n\t\tsignal?: AbortSignal,\n\t\tdirectory = this.directory,\n\t): Promise<T> {\n\t\tconst lockfilePath = join(directory, \".session.lock\");\n\t\tlet release: () => Promise<void>;\n\t\tfor (;;) {\n\t\t\tthis.checkAbort(signal);\n\t\t\ttry {\n\t\t\t\trelease = await lockfile.lock(directory, {\n\t\t\t\t\tlockfilePath,\n\t\t\t\t\t...(this.lockFs ? { fs: this.lockFs } : {}),\n\t\t\t\t\tonCompromised: (cause) => {\n\t\t\t\t\t\tthis.poisoned = new StorageUnavailableError(this.descriptor, cause);\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t\tbreak;\n\t\t\t} catch (cause) {\n\t\t\t\tif ((cause as NodeJS.ErrnoException).code !== \"ELOCKED\") throw cause;\n\t\t\t\tif (await this.clearUnreleased(lockfilePath)) continue;\n\t\t\t\tawait delay(5);\n\t\t\t}\n\t\t}\n\t\tlet result: T;\n\t\ttry {\n\t\t\tthis.checkAbort(signal);\n\t\t\tif (this.poisoned) throw this.poisoned;\n\t\t\tresult = await operation();\n\t\t\tif (this.poisoned) throw this.poisoned;\n\t\t} catch (cause) {\n\t\t\tawait this.release(release, lockfilePath);\n\t\t\tthrow cause;\n\t\t}\n\t\tawait this.release(release, lockfilePath);\n\t\treturn result;\n\t}\n\n\t/**\n\t * Releases the lock. The directory removal is retried when Windows refuses it for a moment. If it never\n\t * succeeds the work is still done, so the failure is not reported over it: the lock is remembered so this\n\t * store's next acquire removes it at once, instead of waiting for it to go stale.\n\t */\n\tprivate async release(release: () => Promise<void>, lockfilePath: string): Promise<void> {\n\t\tconst fs: Pick<SessionLockFs, \"rmdir\" | \"stat\"> = this.lockFs ?? { rmdir: rmdirCallback, stat: statCallback };\n\t\ttry {\n\t\t\tawait release();\n\t\t\treturn;\n\t\t} catch (cause) {\n\t\t\tif (!TRANSIENT_RELEASE_CODES.has((cause as NodeJS.ErrnoException).code ?? \"\")) throw cause;\n\t\t}\n\t\t// proper-lockfile has already forgotten the lock, so removing the directory is all that is left.\n\t\tfor (const wait of RELEASE_BACKOFF_MS) {\n\t\t\tawait delay(wait);\n\t\t\ttry {\n\t\t\t\tawait removeDirectory(fs, lockfilePath);\n\t\t\t\treturn;\n\t\t\t} catch (cause) {\n\t\t\t\tif (!TRANSIENT_RELEASE_CODES.has((cause as NodeJS.ErrnoException).code ?? \"\")) throw cause;\n\t\t\t}\n\t\t}\n\t\tconst modified = await statMtimeMs(fs, lockfilePath);\n\t\tif (modified !== undefined) this.unreleased.set(lockfilePath, modified);\n\t}\n\n\t/** Removes a lock directory this store failed to release, if it still has the time it had then. */\n\tprivate async clearUnreleased(lockfilePath: string): Promise<boolean> {\n\t\tconst expected = this.unreleased.get(lockfilePath);\n\t\tif (expected === undefined) return false;\n\t\tconst fs: Pick<SessionLockFs, \"rmdir\" | \"stat\"> = this.lockFs ?? { rmdir: rmdirCallback, stat: statCallback };\n\t\tconst modified = await statMtimeMs(fs, lockfilePath);\n\t\tif (modified === undefined) {\n\t\t\tthis.unreleased.delete(lockfilePath);\n\t\t\treturn true;\n\t\t}\n\t\t// Another process took the lock over once it went stale: it is theirs now.\n\t\tif (modified !== expected) {\n\t\t\tthis.unreleased.delete(lockfilePath);\n\t\t\treturn false;\n\t\t}\n\t\ttry {\n\t\t\tawait removeDirectory(fs, lockfilePath);\n\t\t} catch (cause) {\n\t\t\tif (!TRANSIENT_RELEASE_CODES.has((cause as NodeJS.ErrnoException).code ?? \"\")) throw cause;\n\t\t\treturn false;\n\t\t}\n\t\tthis.unreleased.delete(lockfilePath);\n\t\treturn true;\n\t}\n\n\tprivate checkAbort(signal?: AbortSignal): void {\n\t\tif (signal?.aborted) throw new DOMException(\"Session listing aborted\", \"AbortError\");\n\t}\n\n\tprivate async paths(options: { readonly skipUnreadableDirectories?: boolean } = {}): Promise<string[]> {\n\t\tconst paths: string[] = [];\n\t\tfor (const entry of await readdir(this.directory, { withFileTypes: true })) {\n\t\t\tconst path = join(this.directory, entry.name);\n\t\t\tif ((entry.isDirectory() || entry.isSymbolicLink()) && !this.exactDirectory) {\n\t\t\t\tconst children = await readdir(path, { withFileTypes: true }).catch((cause: NodeJS.ErrnoException) => {\n\t\t\t\t\tif (cause.code === \"ENOENT\" || cause.code === \"ENOTDIR\") return [];\n\t\t\t\t\tif (options.skipUnreadableDirectories && (cause.code === \"EACCES\" || cause.code === \"EPERM\")) return [];\n\t\t\t\t\tthrow cause;\n\t\t\t\t});\n\t\t\t\tfor (const child of children) {\n\t\t\t\t\tif (child.isFile() && child.name.endsWith(\".jsonl\")) paths.push(join(path, child.name));\n\t\t\t\t}\n\t\t\t} else if (entry.isFile() && entry.name.endsWith(\".jsonl\")) paths.push(path);\n\t\t}\n\t\treturn paths;\n\t}\n\n\tprivate async locate(sessionId: string): Promise<\n\t\t| {\n\t\t\t\tpath: string;\n\t\t\t\theader: SessionRecordHeader;\n\t\t\t\tstored: StoredSessionHeader;\n\t\t\t\tstats: BigIntStats;\n\t\t\t\tstate: SessionFileState | undefined;\n\t\t }\n\t\t| undefined\n\t> {\n\t\tvalidateSessionText(\"sessionId\", sessionId);\n\t\tconst known = await this.locateKnown(sessionId);\n\t\tif (known) return known;\n\t\tconst suffix = `_${this.key(sessionId)}.jsonl`;\n\t\tconst paths = await this.paths();\n\t\tconst named = paths.filter((path) => basename(path).endsWith(suffix));\n\t\tconst others = paths.filter((path) => !named.includes(path));\n\t\treturn (await this.scan(sessionId, named)) ?? (await this.scan(sessionId, others));\n\t}\n\n\tprivate async scan(sessionId: string, paths: readonly string[]) {\n\t\tfor (const path of paths) {\n\t\t\tconst cached = this.fileStates.get(path);\n\t\t\tlet stored: StoredSessionHeader;\n\t\t\ttry {\n\t\t\t\tstored = await this.readFirstLine(path, SCAN_FIRST_LINE_CHUNK_BYTES);\n\t\t\t} catch (cause) {\n\t\t\t\t// Preserve requested-file errors only while its cached inode still owns the path.\n\t\t\t\tif (cached?.headerId === sessionId) {\n\t\t\t\t\tconst stats = await stat(path, { bigint: true });\n\t\t\t\t\tif (cached.identity === `${stats.dev}:${stats.ino}`) throw cause;\n\t\t\t\t\tthis.fileStates.delete(path);\n\t\t\t\t} else if (basename(path).match(/_([0-9a-f]{64})\\.jsonl$/)?.[1] === this.key(sessionId)) {\n\t\t\t\t\tthrow cause;\n\t\t\t\t}\n\t\t\t\t// An unidentifiable file cannot block lookup of unrelated sessions.\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (cached && cached.headerId !== stored.id) this.fileStates.delete(path);\n\t\t\tif (stored.id !== sessionId) continue;\n\t\t\tconst header = await this.readHeaderAt(path, stored);\n\t\t\tconst stats = await stat(path, { bigint: true });\n\t\t\tconst state = this.fileStates.get(path);\n\t\t\t// Keep same-ID baselines only as conflict evidence: forWrite checks the current inode\n\t\t\t// and rejects structural changes until an explicit load establishes a new baseline.\n\t\t\treturn { path, header, stored, stats, state };\n\t\t}\n\t\treturn undefined;\n\t}\n\n\tprivate async locateKnown(sessionId: string) {\n\t\tfor (const [path, cached] of this.fileStates) {\n\t\t\tif (cached.headerId !== sessionId) continue;\n\t\t\tconst parent = dirname(path);\n\t\t\tif (parent !== this.directory && (this.exactDirectory || dirname(parent) !== this.directory)) return undefined;\n\t\t\tlet stored: StoredSessionHeader;\n\t\t\ttry {\n\t\t\t\tstored = await this.readFirstLine(path);\n\t\t\t} catch (cause) {\n\t\t\t\tif ((cause as NodeJS.ErrnoException).code === \"ENOENT\") this.fileStates.delete(path);\n\t\t\t\treturn undefined;\n\t\t\t}\n\t\t\tif (stored.id !== sessionId) {\n\t\t\t\tthis.fileStates.delete(path);\n\t\t\t\treturn undefined;\n\t\t\t}\n\t\t\tconst header = await this.readHeaderAt(path, stored);\n\t\t\tconst stats = await stat(path, { bigint: true });\n\t\t\treturn { path, header, stored, stats, state: this.fileStates.get(path) };\n\t\t}\n\t\treturn undefined;\n\t}\n\n\tprivate key(sessionId: string): string {\n\t\treturn createHash(\"sha256\").update(sessionId).digest(\"hex\");\n\t}\n\n\tprivate async readFirstLine(path: string, chunkBytes = 1): Promise<StoredSessionHeader> {\n\t\tconst file = await open(path, \"r\");\n\t\ttry {\n\t\t\tconst chunks: Buffer[] = [];\n\t\t\tconst buffer = Buffer.alloc(chunkBytes);\n\t\t\twhile (true) {\n\t\t\t\tconst { bytesRead } = await file.read(buffer, 0, buffer.length, null);\n\t\t\t\tif (!bytesRead) break;\n\t\t\t\tconst newline = buffer.subarray(0, bytesRead).indexOf(10);\n\t\t\t\tchunks.push(Buffer.from(buffer.subarray(0, newline === -1 ? bytesRead : newline)));\n\t\t\t\tif (newline !== -1) break;\n\t\t\t}\n\t\t\tconst value = JSON.parse(Buffer.concat(chunks).toString(\"utf8\")) as JsonValue;\n\t\t\treturn value !== null && typeof value === \"object\" && !Array.isArray(value)\n\t\t\t\t? (value as StoredSessionHeader)\n\t\t\t\t: {};\n\t\t} finally {\n\t\t\tawait file.close();\n\t\t}\n\t}\n\n\tprivate async readHeaderAt(path: string, stored?: StoredSessionHeader): Promise<SessionRecordHeader> {\n\t\tstored ??= await this.readFirstLine(path);\n\t\tconst { type: _type, ...header } = isCurrentSessionHeader(stored)\n\t\t\t? (stored as SessionRecordHeader & { type: \"session\" })\n\t\t\t: upgradeLegacySessionHeader(stored, path);\n\t\tif (\n\t\t\t_type !== \"session\" ||\n\t\t\ttypeof header.id !== \"string\" ||\n\t\t\ttypeof header.cwd !== \"string\" ||\n\t\t\ttypeof header.createdAt !== \"string\"\n\t\t) {\n\t\t\tthrow new SessionFormatVersionError(path, stored.version);\n\t\t}\n\t\tvalidateSessionHeader(header);\n\t\treturn header;\n\t}\n\n\tprivate async readSnapshot(\n\t\tpath: string,\n\t\tstored?: StoredSessionHeader,\n\t\tpersistUpgrade = false,\n\t): Promise<SessionSnapshot> {\n\t\tstored ??= await this.readFirstLine(path);\n\t\tconst header = await this.readHeaderAt(path, stored);\n\t\tconst input = createReadStream(path);\n\t\tlet witness: Buffer = Buffer.alloc(0);\n\t\tlet terminated = false;\n\t\tinput.on(\"data\", (chunk: string | Buffer) => {\n\t\t\tconst bytes = typeof chunk === \"string\" ? Buffer.from(chunk) : chunk;\n\t\t\twitness = Buffer.from(Buffer.concat([witness, bytes]).subarray(-64));\n\t\t\tterminated = bytes.at(-1) === 10;\n\t\t});\n\t\tconst lines = createInterface({ input, crlfDelay: Infinity });\n\t\tconst entries: SessionEntry[] = [];\n\t\tlet first = true;\n\t\ttry {\n\t\t\tfor await (const line of lines) {\n\t\t\t\tif (first) {\n\t\t\t\t\tfirst = false;\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tif (line.trim()) entries.push(JSON.parse(line) as SessionEntry);\n\t\t\t}\n\t\t} finally {\n\t\t\tlines.close();\n\t\t\tinput.destroy();\n\t\t}\n\t\tif (!isCurrentSessionHeader(stored)) {\n\t\t\tconst upgraded = upgradeLegacySessionEntries(stored, entries, path).entries;\n\t\t\tvalidateSessionEntryStructure(upgraded, path);\n\t\t\tvalidateSessionEntries(upgraded);\n\t\t\tif (persistUpgrade) await this.commit(path, header, upgraded);\n\t\t\treturn { header, entries: upgraded, lastSeq: upgraded.length };\n\t\t}\n\t\tvalidateSessionEntryStructure(entries, path);\n\t\tvalidateSessionEntries(entries);\n\t\tawait this.remember(path, {\n\t\t\theaderStamp: JSON.stringify(header),\n\t\t\theaderId: header.id,\n\t\t\tlastSeq: entries.length,\n\t\t\tlastEntryId: entries.at(-1)?.id,\n\t\t\twitness,\n\t\t\tterminated,\n\t\t});\n\t\treturn { header, entries, lastSeq: entries.length };\n\t}\n\n\tprivate stamp(stats: BigIntStats): string {\n\t\treturn `${stats.dev}:${stats.ino}:${stats.size}:${stats.mtimeNs}:${stats.ctimeNs}`;\n\t}\n\n\tprivate contentState(\n\t\theader: SessionRecordHeader,\n\t\tentries: readonly SessionEntry[],\n\t\tcontent: string,\n\t): Omit<SessionFileState, \"stamp\" | \"identity\" | \"size\"> {\n\t\treturn {\n\t\t\theaderStamp: JSON.stringify(header),\n\t\t\tlastSeq: entries.length,\n\t\t\theaderId: header.id,\n\t\t\tlastEntryId: entries.at(-1)?.id,\n\t\t\tterminated: content.endsWith(\"\\n\"),\n\t\t\twitness: Buffer.from(Buffer.from(content).subarray(-64)),\n\t\t};\n\t}\n\n\tprivate async remember(path: string, state: Omit<SessionFileState, \"stamp\" | \"identity\" | \"size\">): Promise<void> {\n\t\tconst stats = await stat(path, { bigint: true });\n\t\tthis.fileStates.set(path, {\n\t\t\t...state,\n\t\t\tstamp: this.stamp(stats),\n\t\t\tidentity: `${stats.dev}:${stats.ino}`,\n\t\t\tsize: Number(stats.size),\n\t\t});\n\t}\n\n\t/**\n\t * Foreign appends read only the header, at most 64 known boundary bytes, and new bytes.\n\t * The witness detects a changed append boundary, not arbitrary edits in old history.\n\t * Structural changes require an explicit load; they never trigger a hidden full reread.\n\t */\n\tprivate async forWrite(\n\t\tsessionId: string,\n\t\toptions: SessionWriteOptions,\n\t): Promise<{ path: string; state: SessionFileState }> {\n\t\tconst located = await this.locate(sessionId);\n\t\tif (!located) throw new SessionNotFoundError(sessionId);\n\t\tconst { path, header, stored, stats } = located;\n\t\tif (!isCurrentSessionHeader(stored)) throw new SessionFormatVersionError(path, stored.version);\n\t\tlet state = located.state;\n\t\tif (!state) {\n\t\t\tawait this.readSnapshot(path);\n\t\t\tstate = this.fileStates.get(path)!;\n\t\t} else {\n\t\t\tconst lastSeq = state.lastSeq;\n\t\t\tconst stale = () => new SessionConflictError(sessionId, options.expectSeq, lastSeq);\n\t\t\tif (\n\t\t\t\tstate.identity !== `${stats.dev}:${stats.ino}` ||\n\t\t\t\tstate.headerStamp !== JSON.stringify(header) ||\n\t\t\t\tNumber(stats.size) < state.size\n\t\t\t)\n\t\t\t\tthrow stale();\n\t\t\tif (state.stamp !== this.stamp(stats)) {\n\t\t\t\tconst file = await open(path, \"r\");\n\t\t\t\tconst offset = state.size - state.witness.length;\n\t\t\t\tconst bytes = Buffer.alloc(Number(stats.size) - offset);\n\t\t\t\ttry {\n\t\t\t\t\tlet read = 0;\n\t\t\t\t\twhile (read < bytes.length) {\n\t\t\t\t\t\tconst { bytesRead } = await file.read(bytes, read, bytes.length - read, offset + read);\n\t\t\t\t\t\tif (!bytesRead) throw stale();\n\t\t\t\t\t\tread += bytesRead;\n\t\t\t\t\t}\n\t\t\t\t} finally {\n\t\t\t\t\tawait file.close();\n\t\t\t\t}\n\t\t\t\tif (!bytes.subarray(0, state.witness.length).equals(state.witness)) throw stale();\n\t\t\t\tlet appended = bytes.subarray(state.witness.length).toString(\"utf8\");\n\t\t\t\tif (appended && !state.terminated) {\n\t\t\t\t\tif (!appended.startsWith(\"\\n\")) throw stale();\n\t\t\t\t\tappended = appended.slice(1);\n\t\t\t\t}\n\t\t\t\tconst lines = appended.split(\"\\n\");\n\t\t\t\tif (lines.at(-1) === \"\") lines.pop();\n\t\t\t\tconst entries = lines.map((line) => JSON.parse(line) as SessionEntry);\n\t\t\t\tvalidateSessionEntryStructure(entries, path);\n\t\t\t\tvalidateSessionEntries(entries);\n\t\t\t\tstate = {\n\t\t\t\t\t...state,\n\t\t\t\t\tstamp: this.stamp(stats),\n\t\t\t\t\tsize: Number(stats.size),\n\t\t\t\t\tlastSeq: state.lastSeq + entries.length,\n\t\t\t\t\tlastEntryId: entries.at(-1)?.id ?? state.lastEntryId,\n\t\t\t\t\tterminated: bytes.at(-1) === 10,\n\t\t\t\t\twitness: Buffer.from(bytes.subarray(-64)),\n\t\t\t\t};\n\t\t\t\tthis.fileStates.set(path, state);\n\t\t\t}\n\t\t}\n\t\tif (state.lastSeq !== options.expectSeq)\n\t\t\tthrow new SessionConflictError(sessionId, options.expectSeq, state.lastSeq);\n\t\treturn { path, state };\n\t}\n\n\tprivate encode(header: SessionRecordHeader, entries: readonly SessionEntry[]): string {\n\t\treturn `${[JSON.stringify({ type: \"session\", ...header }), ...entries.map((entry) => JSON.stringify(entry))].join(\"\\n\")}\\n`;\n\t}\n}\n\nfunction removeDirectory(fs: Pick<SessionLockFs, \"rmdir\">, path: string): Promise<void> {\n\treturn new Promise((resolve, reject) => {\n\t\tfs.rmdir(path, (error) => {\n\t\t\tif (error && (error as NodeJS.ErrnoException).code !== \"ENOENT\") reject(error);\n\t\t\telse resolve();\n\t\t});\n\t});\n}\n\nfunction statMtimeMs(fs: Pick<SessionLockFs, \"stat\">, path: string): Promise<number | undefined> {\n\treturn new Promise((resolve) => {\n\t\tfs.stat(path, (error, stats) => resolve(error ? undefined : stats.mtimeMs));\n\t});\n}\n"]}
package/docs/settings.md CHANGED
@@ -608,9 +608,9 @@ Local worker pools are disabled unless `workflows.localWorkers` is set. With the
608
608
 
609
609
  `limits` caps agent sessions and managed tool processes for one root. Session permits cover creation through disposal, including fallback and delegated sessions. Process permits last until confirmed cleanup; yielding an observation wait does not free one. Processes outside Atomic's managed tools are not counted. `host` load and memory thresholds gate launches but do not impose hard OS limits.
610
610
 
611
- `userLimits` counts across runs only when all participating runs use the same canonical local SQLite journal. Set `userDatabase` to that exact path, and pass the admission options to participating non-pooled SDK runs. This coordinates processes for one local user; it is not a tenant isolation boundary.
611
+ `userLimits` counts across runs only when all participating runs use the same canonical local SQLite journal. Set `userDatabase` to that exact path, and pass the admission options to participating non-pooled SDK runs. When the pool's journal is a remote database or another journal that is not a default local SQLite file, omit `userDatabase`: the limit then counts across the pooled roots on this machine that use that journal. This coordinates processes for one local user; it is not a tenant isolation boundary.
612
612
 
613
- Workers require native process and boot identity and are currently supported only on Linux and macOS. Windows and hosts without those identities refuse activation, even if no process cap is configured. Remote workers are not supported. SDK callers cannot combine the pool with process-bound adapters, UI, persistence, or similar overrides. An unregistered or non-importable child fails; Atomic does not execute it locally as a fallback. Recovery may repeat external effects that occurred after a checkpoint, so use stable idempotency keys for operations that must not be repeated.
613
+ Workers require native process and boot identity and are currently supported only on Linux and macOS. Windows and hosts without those identities refuse activation, even if no process cap is configured. Workers always run on this machine, but the workflow journal can be a local SQLite file or a remote database selected through `workflows.journal` or `storage` (see [Selecting storage per process](/storage#selecting-storage-per-process)): the workers open the same journal, and the pool keeps its work queue and leases in a SQLite file in `~/.atomic/workflows/pool/`. Resume a pooled root on the machine where it ran; on another machine it fails with an error naming the original one. A memory journal cannot host workers. Remote workers (on other machines) are not supported. SDK callers cannot combine the pool with process-bound adapters, UI, persistence, or similar overrides. An unregistered or non-importable child fails; Atomic does not execute it locally as a fallback. Recovery may repeat external effects that occurred after a checkpoint, so use stable idempotency keys for operations that must not be repeated.
614
614
 
615
615
  Relative settings paths resolve against the Atomic home directory, normally `~/.atomic`, not the project directory. Precedence is SDK `RunOpts.journal` (or `createAgentSession({ journal })` for a session's `workflow` tool), `--storage` or `--storage-file`, `ATOMIC_WORKFLOWS_JOURNAL` or non-empty `ATOMIC_WORKFLOW_JOURNAL_PATH`, `ATOMIC_STORAGE`, `workflows.journal`, shared top-level `storage`, then the default journal file. An empty environment variable is ignored. SDK sessions read `workflows.journal` from the settings they were given, so `SettingsManager.inMemory(...)` selects a journal per session. A present empty journal block selects the journal default rather than inheriting shared storage. See [Selecting storage per process](/storage#selecting-storage-per-process).
616
616
 
package/docs/storage.md CHANGED
@@ -359,6 +359,8 @@ Selecting the same top-level `storage` on every host, in global settings or with
359
359
 
360
360
  The database stores sessions, workflow checkpoints, and, when Intercom brokers share it, Intercom messages and session routing state. To resume a run on another host, that host also needs the same workflow definition and the run's original working directory, including any worktrees and artifacts the run uses. Effects that were not checkpointed may run again after a takeover, so make external effects idempotent. Every checkpoint commits before it is reported, so a remote database adds network latency to each durable `ctx.*` step. Backends may also enforce payload limits that raise `StoragePayloadTooLargeError`.
361
361
 
362
+ [Local workflow workers](/workflows/operations#local-workflow-workers) work on a shared journal: the workers run on the machine that runs the root and open the same database, and the pool keeps its work queue and leases in a SQLite file on that machine, so a pooled run resumes on the machine where it started.
363
+
362
364
  Scale by running more workflows, not by splitting one: a single run and a single session each have one writer. The built-in journal uses SQLite SQL, so `openDatabase` adapters need a SQLite-compatible driver. For another kind of database, implement `openRunJournal` and `openSessionStore` and validate them with the conformance suites below.
363
365
 
364
366
  ## Storage errors
@@ -1266,13 +1266,13 @@ Only first-level child workflow subtrees are placed on workers. Nested children
1266
1266
 
1267
1267
  #### Local worker options
1268
1268
 
1269
- `RunOpts.localWorkers` enables a local process pool for this root. `count` must be a positive integer. `definitions` lists `{ path, exportName }` entries. The definitions are loaded in each worker from the local filesystem. The optional `startupTimeoutMs` is how long, in milliseconds, each worker process may take to become ready; it must be a positive integer no greater than `2147483647`. When it is unset, the deadline is 30000 ms scaled by (worker count + 1-minute load average) ÷ CPU cores, at least 30000 ms and at most 600000 ms. The optional `leaseMs` is how long, in milliseconds, a worker that is still running but has stopped responding keeps its child before the child is replayed on another worker; it must be an integer from `2000` to `2147483647` and defaults to `30000`. `RunOpts.admission` accepts `limits` for one root, `userLimits` across runs, a `userDatabase` canonical local SQLite path, and optional host thresholds `maxLoadPerCpu` and `minFreeMemoryBytes`.
1269
+ `RunOpts.localWorkers` enables a local process pool for this root. `count` must be a positive integer. `definitions` lists `{ path, exportName }` entries. The definitions are loaded in each worker from the local filesystem. The optional `startupTimeoutMs` is how long, in milliseconds, each worker process may take to become ready; it must be a positive integer no greater than `2147483647`. When it is unset, the deadline is 30000 ms scaled by (worker count + 1-minute load average) ÷ CPU cores, at least 30000 ms and at most 600000 ms. The optional `leaseMs` is how long, in milliseconds, a worker that is still running but has stopped responding keeps its child before the child is replayed on another worker; it must be an integer from `2000` to `2147483647` and defaults to `30000`. `RunOpts.admission` accepts `limits` for one root, `userLimits` across runs, a `userDatabase` canonical local SQLite path (omit it when the journal is not a local SQLite file; see below), and optional host thresholds `maxLoadPerCpu` and `minFreeMemoryBytes`.
1270
1270
 
1271
1271
  The option is off by default. Without it, Atomic creates no pool tables, worker processes, or polling loops. CLI users can set the same options under `workflows.localWorkers` and `workflows.admission` in settings. Settings paths resolve against the invocation working directory; SDK paths resolve against `cwd` (or the current directory). Effective settings and definition entry-module digests are persisted with the root and checked on resume. Changing them fails compatibility checks instead of silently changing placement. `startupTimeoutMs` and `leaseMs` are the exceptions: they are not persisted, and each start or resume uses the values it is given.
1272
1272
 
1273
- The pool runs children once any worker is ready and fails only when no worker starts. A worker that dies while it runs a child is replaced, and the child replays from its last committed checkpoint. Each worker's standard error is written to `worker-logs/<root run ID>/<worker ID>.log` in the journal's directory; worker failure errors name that file and include the end of its output. See [Worker startup and failures](/workflows/operations#worker-startup-and-failures).
1273
+ The pool runs children once any worker is ready and fails only when no worker starts. A worker that dies while it runs a child is replaced, and the child replays from its last committed checkpoint. Each worker's standard error is written to `worker-logs/<root run ID>/<worker ID>.log` in the journal's directory (for a journal in another database, in `workflows/pool/` beside the agent directory); worker failure errors name that file and include the end of its output. See [Worker startup and failures](/workflows/operations#worker-startup-and-failures).
1274
1274
 
1275
- Workers are supported only on Linux and macOS hosts with native process identity and boot identity. Windows and hosts without those capabilities refuse activation, including when no process cap is configured. Remote hosts are not supported. Pooled SDK runs reject process-bound adapters, UI, persistence, and similar runtime overrides before worker launch. `ui` is accepted: it answers the `ctx.ui` prompts (`input`, `confirm`, `select`, `editor`) of children on local workers, and each answer is sent to the worker that asked. If a `ui` call rejects, the prompt fails in that child with the same error. `stageUiBroker` is accepted: a stage on a local worker that asks `ask_user_question` raises the same form there, and its answer is sent to the worker that asked. A `ctx.ui.custom` prompt in a child on a local worker fails that child with an error, since its component cannot be shown outside the worker. `stageControlRegistry` is accepted: while a stage runs on a worker, the registry holds a handle for it whose `sendUserMessage`, `steer`, `followUp` and `subscribe` reach that stage and report the same delivery actions as an in-process stage. The handle streams the stage's events only while something subscribes or a message is on its way. The CLI keeps its host-specific bindings at the root and gives worker sessions their own adapters.
1275
+ Workers are supported only on Linux and macOS hosts with native process identity and boot identity. Windows and hosts without those capabilities refuse activation, including when no process cap is configured. Remote hosts and network workers are not supported: every worker runs on the root's machine. The root's journal need not be a local file. A journal selected with `RunOpts.journal`, `--storage`, `ATOMIC_WORKFLOWS_JOURNAL` or settings can be any [storage adapter](/storage), such as libSQL or Turso, or a SQLite file with a custom prefix; the workers open it through the same selection, and the pool keeps its queue, leases and admission state in a SQLite database on the machine that runs it. A root on such a journal resumes only on the machine whose pool database holds its work; resuming it elsewhere fails with an error naming that machine. A journal passed to the SDK as an object, and a memory journal, cannot host workers because the worker processes cannot open them. Pooled SDK runs reject process-bound adapters, UI, persistence, and similar runtime overrides before worker launch. `ui` is accepted: it answers the `ctx.ui` prompts (`input`, `confirm`, `select`, `editor`) of children on local workers, and each answer is sent to the worker that asked. If a `ui` call rejects, the prompt fails in that child with the same error. `stageUiBroker` is accepted: a stage on a local worker that asks `ask_user_question` raises the same form there, and its answer is sent to the worker that asked. A `ctx.ui.custom` prompt in a child on a local worker fails that child with an error, since its component cannot be shown outside the worker. `stageControlRegistry` is accepted: while a stage runs on a worker, the registry holds a handle for it whose `sendUserMessage`, `steer`, `followUp` and `subscribe` reach that stage and report the same delivery actions as an in-process stage. The handle streams the stage's events only while something subscribes or a message is on its way. The CLI keeps its host-specific bindings at the root and gives worker sessions their own adapters.
1276
1276
 
1277
1277
  Admission limits count actual resources: a session from creation through disposal, including fallback and delegated sessions, and a managed tool process until confirmed cleanup. Yielding an observation wait does not free a process permit. Subprocesses started outside Atomic's managed APIs are not counted. Host load and free-memory thresholds are launch gates, not hard OS limits. `userLimits` are reliable only when every participating run uses the configured canonical database path; they are local-user coordination, not a tenant security boundary.
1278
1278