@caupulican/pi-adaptative 0.93.19 → 0.94.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (189) hide show
  1. package/CHANGELOG.md +30 -0
  2. package/README.md +3 -2
  3. package/dist/core/agent-paths.d.ts +2 -0
  4. package/dist/core/agent-paths.d.ts.map +1 -1
  5. package/dist/core/agent-paths.js +7 -0
  6. package/dist/core/agent-paths.js.map +1 -1
  7. package/dist/core/agent-session.d.ts.map +1 -1
  8. package/dist/core/agent-session.js +5 -1
  9. package/dist/core/agent-session.js.map +1 -1
  10. package/dist/core/background-lane-controller.d.ts +8 -0
  11. package/dist/core/background-lane-controller.d.ts.map +1 -1
  12. package/dist/core/background-lane-controller.js +75 -5
  13. package/dist/core/background-lane-controller.js.map +1 -1
  14. package/dist/core/background-tool-task-controller.d.ts +15 -0
  15. package/dist/core/background-tool-task-controller.d.ts.map +1 -1
  16. package/dist/core/background-tool-task-controller.js +122 -15
  17. package/dist/core/background-tool-task-controller.js.map +1 -1
  18. package/dist/core/context/long-term-memory-trigger.d.ts +3 -1
  19. package/dist/core/context/long-term-memory-trigger.d.ts.map +1 -1
  20. package/dist/core/context/long-term-memory-trigger.js +1 -1
  21. package/dist/core/context/long-term-memory-trigger.js.map +1 -1
  22. package/dist/core/context/okf-memory-provider.d.ts +3 -0
  23. package/dist/core/context/okf-memory-provider.d.ts.map +1 -1
  24. package/dist/core/context/okf-memory-provider.js +66 -31
  25. package/dist/core/context/okf-memory-provider.js.map +1 -1
  26. package/dist/core/context/okf-memory.d.ts +18 -1
  27. package/dist/core/context/okf-memory.d.ts.map +1 -1
  28. package/dist/core/context/okf-memory.js +48 -0
  29. package/dist/core/context/okf-memory.js.map +1 -1
  30. package/dist/core/delegation/worker-agent-control.d.ts +4 -0
  31. package/dist/core/delegation/worker-agent-control.d.ts.map +1 -1
  32. package/dist/core/delegation/worker-agent-control.js.map +1 -1
  33. package/dist/core/delegation/worker-execution-policy.d.ts.map +1 -1
  34. package/dist/core/delegation/worker-execution-policy.js +1 -1
  35. package/dist/core/delegation/worker-execution-policy.js.map +1 -1
  36. package/dist/core/delegation/worker-notification-coordinator.d.ts +10 -0
  37. package/dist/core/delegation/worker-notification-coordinator.d.ts.map +1 -1
  38. package/dist/core/delegation/worker-notification-coordinator.js +69 -3
  39. package/dist/core/delegation/worker-notification-coordinator.js.map +1 -1
  40. package/dist/core/extensions/loader.d.ts +0 -1
  41. package/dist/core/extensions/loader.d.ts.map +1 -1
  42. package/dist/core/extensions/loader.js +0 -1
  43. package/dist/core/extensions/loader.js.map +1 -1
  44. package/dist/core/extensions/types.d.ts +0 -4
  45. package/dist/core/extensions/types.d.ts.map +1 -1
  46. package/dist/core/extensions/types.js.map +1 -1
  47. package/dist/core/foreground-terminal-handoff-controller.d.ts +17 -0
  48. package/dist/core/foreground-terminal-handoff-controller.d.ts.map +1 -1
  49. package/dist/core/foreground-terminal-handoff-controller.js +78 -10
  50. package/dist/core/foreground-terminal-handoff-controller.js.map +1 -1
  51. package/dist/core/learning/learning-audit.d.ts +5 -1
  52. package/dist/core/learning/learning-audit.d.ts.map +1 -1
  53. package/dist/core/learning/learning-audit.js +32 -1
  54. package/dist/core/learning/learning-audit.js.map +1 -1
  55. package/dist/core/learning/reflection-engine.d.ts +20 -0
  56. package/dist/core/learning/reflection-engine.d.ts.map +1 -1
  57. package/dist/core/learning/reflection-engine.js +58 -0
  58. package/dist/core/learning/reflection-engine.js.map +1 -1
  59. package/dist/core/memory/okf-project-memory-store.d.ts +28 -0
  60. package/dist/core/memory/okf-project-memory-store.d.ts.map +1 -0
  61. package/dist/core/memory/okf-project-memory-store.js +111 -0
  62. package/dist/core/memory/okf-project-memory-store.js.map +1 -0
  63. package/dist/core/memory/providers/file-store.d.ts +42 -1
  64. package/dist/core/memory/providers/file-store.d.ts.map +1 -1
  65. package/dist/core/memory/providers/file-store.js +274 -13
  66. package/dist/core/memory/providers/file-store.js.map +1 -1
  67. package/dist/core/memory-controller.d.ts +10 -1
  68. package/dist/core/memory-controller.d.ts.map +1 -1
  69. package/dist/core/memory-controller.js +72 -8
  70. package/dist/core/memory-controller.js.map +1 -1
  71. package/dist/core/provider-prompt-contracts.d.ts.map +1 -1
  72. package/dist/core/provider-prompt-contracts.js +9 -19
  73. package/dist/core/provider-prompt-contracts.js.map +1 -1
  74. package/dist/core/reflection-controller.d.ts +7 -0
  75. package/dist/core/reflection-controller.d.ts.map +1 -1
  76. package/dist/core/reflection-controller.js +94 -15
  77. package/dist/core/reflection-controller.js.map +1 -1
  78. package/dist/core/tools/artifact-retrieve.d.ts.map +1 -1
  79. package/dist/core/tools/artifact-retrieve.js +0 -1
  80. package/dist/core/tools/artifact-retrieve.js.map +1 -1
  81. package/dist/core/tools/delegate-status.d.ts +2 -0
  82. package/dist/core/tools/delegate-status.d.ts.map +1 -1
  83. package/dist/core/tools/delegate-status.js +4 -0
  84. package/dist/core/tools/delegate-status.js.map +1 -1
  85. package/dist/core/tools/delegate.d.ts +2 -0
  86. package/dist/core/tools/delegate.d.ts.map +1 -1
  87. package/dist/core/tools/delegate.js +83 -21
  88. package/dist/core/tools/delegate.js.map +1 -1
  89. package/dist/core/tools/edit.d.ts.map +1 -1
  90. package/dist/core/tools/edit.js +0 -7
  91. package/dist/core/tools/edit.js.map +1 -1
  92. package/dist/core/tools/find.d.ts.map +1 -1
  93. package/dist/core/tools/find.js +0 -1
  94. package/dist/core/tools/find.js.map +1 -1
  95. package/dist/core/tools/grep.d.ts.map +1 -1
  96. package/dist/core/tools/grep.js +0 -1
  97. package/dist/core/tools/grep.js.map +1 -1
  98. package/dist/core/tools/ls.d.ts.map +1 -1
  99. package/dist/core/tools/ls.js +0 -1
  100. package/dist/core/tools/ls.js.map +1 -1
  101. package/dist/core/tools/skill-audit.d.ts.map +1 -1
  102. package/dist/core/tools/skill-audit.js +0 -1
  103. package/dist/core/tools/skill-audit.js.map +1 -1
  104. package/dist/core/tools/skill.d.ts.map +1 -1
  105. package/dist/core/tools/skill.js +0 -1
  106. package/dist/core/tools/skill.js.map +1 -1
  107. package/dist/core/tools/skillify.d.ts.map +1 -1
  108. package/dist/core/tools/skillify.js +0 -1
  109. package/dist/core/tools/skillify.js.map +1 -1
  110. package/dist/core/tools/tool-task.d.ts +1 -0
  111. package/dist/core/tools/tool-task.d.ts.map +1 -1
  112. package/dist/core/tools/tool-task.js +13 -8
  113. package/dist/core/tools/tool-task.js.map +1 -1
  114. package/dist/core/tools/write.d.ts.map +1 -1
  115. package/dist/core/tools/write.js +1 -2
  116. package/dist/core/tools/write.js.map +1 -1
  117. package/dist/core/util/atomic-file.d.ts +2 -0
  118. package/dist/core/util/atomic-file.d.ts.map +1 -1
  119. package/dist/core/util/atomic-file.js +4 -0
  120. package/dist/core/util/atomic-file.js.map +1 -1
  121. package/dist/modes/interactive/auto-learn-controller.d.ts.map +1 -1
  122. package/dist/modes/interactive/auto-learn-controller.js +2 -0
  123. package/dist/modes/interactive/auto-learn-controller.js.map +1 -1
  124. package/dist/modes/interactive/components/action-transcript.d.ts +24 -0
  125. package/dist/modes/interactive/components/action-transcript.d.ts.map +1 -0
  126. package/dist/modes/interactive/components/action-transcript.js +72 -0
  127. package/dist/modes/interactive/components/action-transcript.js.map +1 -0
  128. package/dist/modes/interactive/components/active-tool-call-registry.d.ts +12 -0
  129. package/dist/modes/interactive/components/active-tool-call-registry.d.ts.map +1 -0
  130. package/dist/modes/interactive/components/active-tool-call-registry.js +25 -0
  131. package/dist/modes/interactive/components/active-tool-call-registry.js.map +1 -0
  132. package/dist/modes/interactive/components/activity-lane.d.ts +1 -1
  133. package/dist/modes/interactive/components/activity-lane.d.ts.map +1 -1
  134. package/dist/modes/interactive/components/activity-lane.js +12 -23
  135. package/dist/modes/interactive/components/activity-lane.js.map +1 -1
  136. package/dist/modes/interactive/components/assistant-message.d.ts +2 -0
  137. package/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
  138. package/dist/modes/interactive/components/assistant-message.js +7 -1
  139. package/dist/modes/interactive/components/assistant-message.js.map +1 -1
  140. package/dist/modes/interactive/components/custom-message.d.ts.map +1 -1
  141. package/dist/modes/interactive/components/custom-message.js +125 -1
  142. package/dist/modes/interactive/components/custom-message.js.map +1 -1
  143. package/dist/modes/interactive/components/index.d.ts +0 -2
  144. package/dist/modes/interactive/components/index.d.ts.map +1 -1
  145. package/dist/modes/interactive/components/index.js +0 -2
  146. package/dist/modes/interactive/components/index.js.map +1 -1
  147. package/dist/modes/interactive/components/tool-execution.d.ts +0 -7
  148. package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  149. package/dist/modes/interactive/components/tool-execution.js +2 -76
  150. package/dist/modes/interactive/components/tool-execution.js.map +1 -1
  151. package/dist/modes/interactive/components/transcript-overlay.d.ts +3 -1
  152. package/dist/modes/interactive/components/transcript-overlay.d.ts.map +1 -1
  153. package/dist/modes/interactive/components/transcript-overlay.js +8 -5
  154. package/dist/modes/interactive/components/transcript-overlay.js.map +1 -1
  155. package/dist/modes/interactive/interactive-event-controller.d.ts +2 -3
  156. package/dist/modes/interactive/interactive-event-controller.d.ts.map +1 -1
  157. package/dist/modes/interactive/interactive-event-controller.js +9 -9
  158. package/dist/modes/interactive/interactive-event-controller.js.map +1 -1
  159. package/dist/modes/interactive/interactive-mode.d.ts +6 -6
  160. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  161. package/dist/modes/interactive/interactive-mode.js +50 -100
  162. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  163. package/dist/modes/interactive/settings-selector-flow.d.ts.map +1 -1
  164. package/dist/modes/interactive/settings-selector-flow.js +3 -4
  165. package/dist/modes/interactive/settings-selector-flow.js.map +1 -1
  166. package/docs/UI_POLISH_ORCHESTRATION.md +4 -4
  167. package/docs/extensions.md +4 -12
  168. package/docs/keybindings.md +2 -2
  169. package/docs/settings.md +1 -1
  170. package/docs/task-steps.md +3 -3
  171. package/docs/tool-repair.md +1 -1
  172. package/docs/usage.md +1 -1
  173. package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  174. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  175. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  176. package/examples/extensions/sandbox/package-lock.json +2 -2
  177. package/examples/extensions/sandbox/package.json +1 -1
  178. package/examples/extensions/with-deps/package-lock.json +2 -2
  179. package/examples/extensions/with-deps/package.json +1 -1
  180. package/npm-shrinkwrap.json +12 -12
  181. package/package.json +4 -4
  182. package/dist/modes/interactive/components/tool-group.d.ts +0 -28
  183. package/dist/modes/interactive/components/tool-group.d.ts.map +0 -1
  184. package/dist/modes/interactive/components/tool-group.js +0 -200
  185. package/dist/modes/interactive/components/tool-group.js.map +0 -1
  186. package/dist/modes/interactive/components/tool-panel-registry.d.ts +0 -30
  187. package/dist/modes/interactive/components/tool-panel-registry.d.ts.map +0 -1
  188. package/dist/modes/interactive/components/tool-panel-registry.js +0 -145
  189. package/dist/modes/interactive/components/tool-panel-registry.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"tool-task.d.ts","sourceRoot":"","sources":["../../../src/core/tools/tool-task.ts"],"names":[],"mappings":"AAAA,OAAO,EAAe,IAAI,EAAE,MAAM,SAAS,CAAC;AAC5C,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,uCAAuC,CAAC;AACtF,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAK7D,QAAA,MAAM,MAAM;;;EAcX,CAAC;AAIF,MAAM,WAAW,oBAAoB;IACpC,IAAI,IAAI,wBAAwB,EAAE,CAAC;IACnC,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,wBAAwB,CAAC,CAAC;IAC9E,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC;CAChC;AAED,MAAM,WAAW,eAAe;IAC/B,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,QAAQ,GAAG,OAAO,CAAC;IAC3C,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,wBAAwB,CAAC,QAAQ,CAAC,CAAC;IAC5C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;CAChB;AAmBD,wBAAgB,4BAA4B,CAAC,IAAI,EAAE,oBAAoB,GAAG,cAAc,CAAC,OAAO,MAAM,CAAC,CA4EtG"}
1
+ {"version":3,"file":"tool-task.d.ts","sourceRoot":"","sources":["../../../src/core/tools/tool-task.ts"],"names":[],"mappings":"AAAA,OAAO,EAAe,IAAI,EAAE,MAAM,SAAS,CAAC;AAC5C,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,uCAAuC,CAAC;AACtF,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAK7D,QAAA,MAAM,MAAM;;;EAcX,CAAC;AAIF,MAAM,WAAW,oBAAoB;IACpC,IAAI,IAAI,wBAAwB,EAAE,CAAC;IACnC,OAAO,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,GAAG,IAAI,CAAC;IAC1C,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,wBAAwB,CAAC,CAAC;IAC9E,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC;CAChC;AAED,MAAM,WAAW,eAAe;IAC/B,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,QAAQ,GAAG,OAAO,CAAC;IAC3C,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,wBAAwB,CAAC,QAAQ,CAAC,CAAC;IAC5C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;CAChB;AAyBD,wBAAgB,4BAA4B,CAAC,IAAI,EAAE,oBAAoB,GAAG,cAAc,CAAC,OAAO,MAAM,CAAC,CA8EtG"}
@@ -17,16 +17,19 @@ function validTaskId(value) {
17
17
  return undefined;
18
18
  return taskId;
19
19
  }
20
- function listText(records) {
20
+ function projectList(records) {
21
21
  if (records.length === 0)
22
- return "No background tool tasks in this session.";
22
+ return { included: [], text: "No background tool tasks in this session." };
23
23
  const included = records.slice(-MAX_LISTED_TASKS);
24
24
  const omitted = records.length - included.length;
25
- return [
26
- ...included.map((record) => `${record.taskId}: ${record.status} — ${record.summary}`),
27
- ...(omitted > 0 ? [`${omitted} older task(s) omitted from this bounded snapshot.`] : []),
28
- "Do not poll. Continue independent work, or call wait once only when a running task is a dependency.",
29
- ].join("\n");
25
+ return {
26
+ included,
27
+ text: [
28
+ ...included.map((record) => `${record.taskId}: ${record.status} — ${record.summary}`),
29
+ ...(omitted > 0 ? [`${omitted} older task(s) omitted from this bounded snapshot.`] : []),
30
+ "Do not poll. Continue independent work, or call wait once only when a running task is a dependency.",
31
+ ].join("\n"),
32
+ };
30
33
  }
31
34
  export function createToolTaskToolDefinition(deps) {
32
35
  return {
@@ -42,8 +45,10 @@ export function createToolTaskToolDefinition(deps) {
42
45
  async execute(_toolCallId, input, signal) {
43
46
  if (input.action === "list") {
44
47
  const records = deps.list();
48
+ const projection = projectList(records);
49
+ deps.observe(projection.included.map((record) => record.taskId));
45
50
  return {
46
- content: [{ type: "text", text: listText(records) }],
51
+ content: [{ type: "text", text: projection.text }],
47
52
  details: { kind: "list", count: records.length },
48
53
  };
49
54
  }
@@ -1 +1 @@
1
- {"version":3,"file":"tool-task.js","sourceRoot":"","sources":["../../../src/core/tools/tool-task.ts"],"names":[],"mappings":"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","sourcesContent":["import { type Static, Type } from \"typebox\";\nimport type { BackgroundToolTaskRecord } from \"../background-tool-task-controller.ts\";\nimport type { ToolDefinition } from \"../extensions/types.ts\";\n\nconst MAX_TASK_ID_CHARS = 128;\nconst MAX_LISTED_TASKS = 32;\n\nconst schema = Type.Object(\n\t{\n\t\taction: Type.String({\n\t\t\tenum: [\"list\", \"wait\", \"cancel\"],\n\t\t\tdescription: \"List once, wait once for a dependency, or cancel. Never poll.\",\n\t\t}),\n\t\ttaskId: Type.Optional(\n\t\t\tType.String({\n\t\t\t\tmaxLength: MAX_TASK_ID_CHARS,\n\t\t\t\tdescription: \"Task id; required for wait/cancel.\",\n\t\t\t}),\n\t\t),\n\t},\n\t{ additionalProperties: false },\n);\n\ntype Input = Static<typeof schema>;\n\nexport interface ToolTaskDependencies {\n\tlist(): BackgroundToolTaskRecord[];\n\twait(taskId: string, signal?: AbortSignal): Promise<BackgroundToolTaskRecord>;\n\tcancel(taskId: string): boolean;\n}\n\nexport interface ToolTaskDetails {\n\tkind: \"list\" | \"wait\" | \"cancel\" | \"error\";\n\tcount?: number;\n\ttaskId?: string;\n\tstatus?: BackgroundToolTaskRecord[\"status\"];\n\tartifactId?: string;\n\treason?: string;\n}\n\nfunction validTaskId(value: string | undefined): string | undefined {\n\tconst taskId = value?.trim();\n\tif (!taskId || taskId.length > MAX_TASK_ID_CHARS) return undefined;\n\treturn taskId;\n}\n\nfunction listText(records: readonly BackgroundToolTaskRecord[]): string {\n\tif (records.length === 0) return \"No background tool tasks in this session.\";\n\tconst included = records.slice(-MAX_LISTED_TASKS);\n\tconst omitted = records.length - included.length;\n\treturn [\n\t\t...included.map((record) => `${record.taskId}: ${record.status} — ${record.summary}`),\n\t\t...(omitted > 0 ? [`${omitted} older task(s) omitted from this bounded snapshot.`] : []),\n\t\t\"Do not poll. Continue independent work, or call wait once only when a running task is a dependency.\",\n\t].join(\"\\n\");\n}\n\nexport function createToolTaskToolDefinition(deps: ToolTaskDependencies): ToolDefinition<typeof schema> {\n\treturn {\n\t\tname: \"tool_task\",\n\t\tlabel: \"tool_task\",\n\t\tdescription:\n\t\t\t\"List, wait for, or cancel this session's background tool calls. Continue other work; wait is event-driven, never poll. Cite a completed taskId as goal evidence or task_steps evidence.\",\n\t\tpromptSnippet: \"Event-driven background tool control; wait once, never poll.\",\n\t\tpromptGuidelines: [\n\t\t\t\"Handoff is not completion. Need the result: wait once with taskId.\",\n\t\t\t\"Cite the taskId on the matching task_steps step and as goal add_evidence kind=tool uri.\",\n\t\t],\n\t\tparameters: schema,\n\t\tasync execute(_toolCallId, input: Input, signal) {\n\t\t\tif (input.action === \"list\") {\n\t\t\t\tconst records = deps.list();\n\t\t\t\treturn {\n\t\t\t\t\tcontent: [{ type: \"text\" as const, text: listText(records) }],\n\t\t\t\t\tdetails: { kind: \"list\" as const, count: records.length },\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tconst taskId = validTaskId(input.taskId);\n\t\t\tif (!taskId) {\n\t\t\t\treturn {\n\t\t\t\t\tcontent: [{ type: \"text\" as const, text: `${input.action} requires a valid taskId.` }],\n\t\t\t\t\tdetails: { kind: \"error\" as const, reason: \"invalid_task_id\" },\n\t\t\t\t\tisError: true,\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tif (input.action === \"cancel\") {\n\t\t\t\tconst canceled = deps.cancel(taskId);\n\t\t\t\treturn {\n\t\t\t\t\tcontent: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ttype: \"text\" as const,\n\t\t\t\t\t\t\ttext: canceled\n\t\t\t\t\t\t\t\t? `Cancellation requested for ${taskId}.`\n\t\t\t\t\t\t\t\t: `No running background tool task named ${taskId}.`,\n\t\t\t\t\t\t},\n\t\t\t\t\t],\n\t\t\t\t\tdetails: {\n\t\t\t\t\t\tkind: \"cancel\" as const,\n\t\t\t\t\t\ttaskId,\n\t\t\t\t\t\t...(canceled ? {} : { reason: \"not_running\" }),\n\t\t\t\t\t},\n\t\t\t\t};\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tconst record = await deps.wait(taskId, signal);\n\t\t\t\tconst isError = record.status === \"failed\" || record.status === \"canceled\";\n\t\t\t\tconst text =\n\t\t\t\t\trecord.status === \"running\"\n\t\t\t\t\t\t? `${record.summary}\\nWait watchdog elapsed; continue independent work. The terminal handoff will wake the session.`\n\t\t\t\t\t\t: record.output || record.summary;\n\t\t\t\treturn {\n\t\t\t\t\tcontent: [{ type: \"text\" as const, text }],\n\t\t\t\t\tdetails: {\n\t\t\t\t\t\tkind: \"wait\" as const,\n\t\t\t\t\t\ttaskId,\n\t\t\t\t\t\tstatus: record.status,\n\t\t\t\t\t\t...(record.artifactId ? { artifactId: record.artifactId } : {}),\n\t\t\t\t\t},\n\t\t\t\t\t...(isError ? { isError: true, errorKind: \"operation_outcome\" as const } : {}),\n\t\t\t\t};\n\t\t\t} catch (error) {\n\t\t\t\tconst reason = error instanceof Error ? error.message : String(error);\n\t\t\t\treturn {\n\t\t\t\t\tcontent: [{ type: \"text\" as const, text: reason }],\n\t\t\t\t\tdetails: { kind: \"error\" as const, taskId, reason },\n\t\t\t\t\tisError: true,\n\t\t\t\t};\n\t\t\t}\n\t\t},\n\t};\n}\n"]}
1
+ {"version":3,"file":"tool-task.js","sourceRoot":"","sources":["../../../src/core/tools/tool-task.ts"],"names":[],"mappings":"AAAA,OAAO,EAAe,IAAI,EAAE,MAAM,SAAS,CAAC;AAI5C,MAAM,iBAAiB,GAAG,GAAG,CAAC;AAC9B,MAAM,gBAAgB,GAAG,EAAE,CAAC;AAE5B,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CACzB;IACC,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC;QACnB,IAAI,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,CAAC;QAChC,WAAW,EAAE,+DAA+D;KAC5E,CAAC;IACF,MAAM,EAAE,IAAI,CAAC,QAAQ,CACpB,IAAI,CAAC,MAAM,CAAC;QACX,SAAS,EAAE,iBAAiB;QAC5B,WAAW,EAAE,oCAAoC;KACjD,CAAC,CACF;CACD,EACD,EAAE,oBAAoB,EAAE,KAAK,EAAE,CAC/B,CAAC;AAoBF,SAAS,WAAW,CAAC,KAAyB;IAC7C,MAAM,MAAM,GAAG,KAAK,EAAE,IAAI,EAAE,CAAC;IAC7B,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC,MAAM,GAAG,iBAAiB;QAAE,OAAO,SAAS,CAAC;IACnE,OAAO,MAAM,CAAC;AACf,CAAC;AAED,SAAS,WAAW,CAAC,OAA4C;IAIhE,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,IAAI,EAAE,2CAA2C,EAAE,CAAC;IACrG,MAAM,QAAQ,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,gBAAgB,CAAC,CAAC;IAClD,MAAM,OAAO,GAAG,OAAO,CAAC,MAAM,GAAG,QAAQ,CAAC,MAAM,CAAC;IACjD,OAAO;QACN,QAAQ;QACR,IAAI,EAAE;YACL,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,KAAK,MAAM,CAAC,MAAM,MAAM,MAAM,CAAC,OAAO,EAAE,CAAC;YACrF,GAAG,CAAC,OAAO,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,OAAO,oDAAoD,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;YACxF,qGAAqG;SACrG,CAAC,IAAI,CAAC,IAAI,CAAC;KACZ,CAAC;AACH,CAAC;AAED,MAAM,UAAU,4BAA4B,CAAC,IAA0B;IACtE,OAAO;QACN,IAAI,EAAE,WAAW;QACjB,KAAK,EAAE,WAAW;QAClB,WAAW,EACV,yLAAyL;QAC1L,aAAa,EAAE,8DAA8D;QAC7E,gBAAgB,EAAE;YACjB,oEAAoE;YACpE,yFAAyF;SACzF;QACD,UAAU,EAAE,MAAM;QAClB,KAAK,CAAC,OAAO,CAAC,WAAW,EAAE,KAAY,EAAE,MAAM;YAC9C,IAAI,KAAK,CAAC,MAAM,KAAK,MAAM,EAAE,CAAC;gBAC7B,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;gBAC5B,MAAM,UAAU,GAAG,WAAW,CAAC,OAAO,CAAC,CAAC;gBACxC,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC;gBACjE,OAAO;oBACN,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,UAAU,CAAC,IAAI,EAAE,CAAC;oBAC3D,OAAO,EAAE,EAAE,IAAI,EAAE,MAAe,EAAE,KAAK,EAAE,OAAO,CAAC,MAAM,EAAE;iBACzD,CAAC;YACH,CAAC;YAED,MAAM,MAAM,GAAG,WAAW,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;YACzC,IAAI,CAAC,MAAM,EAAE,CAAC;gBACb,OAAO;oBACN,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,GAAG,KAAK,CAAC,MAAM,2BAA2B,EAAE,CAAC;oBACtF,OAAO,EAAE,EAAE,IAAI,EAAE,OAAgB,EAAE,MAAM,EAAE,iBAAiB,EAAE;oBAC9D,OAAO,EAAE,IAAI;iBACb,CAAC;YACH,CAAC;YAED,IAAI,KAAK,CAAC,MAAM,KAAK,QAAQ,EAAE,CAAC;gBAC/B,MAAM,QAAQ,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;gBACrC,OAAO;oBACN,OAAO,EAAE;wBACR;4BACC,IAAI,EAAE,MAAe;4BACrB,IAAI,EAAE,QAAQ;gCACb,CAAC,CAAC,8BAA8B,MAAM,GAAG;gCACzC,CAAC,CAAC,yCAAyC,MAAM,GAAG;yBACrD;qBACD;oBACD,OAAO,EAAE;wBACR,IAAI,EAAE,QAAiB;wBACvB,MAAM;wBACN,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,aAAa,EAAE,CAAC;qBAC9C;iBACD,CAAC;YACH,CAAC;YAED,IAAI,CAAC;gBACJ,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;gBAC/C,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,KAAK,QAAQ,IAAI,MAAM,CAAC,MAAM,KAAK,UAAU,CAAC;gBAC3E,MAAM,IAAI,GACT,MAAM,CAAC,MAAM,KAAK,SAAS;oBAC1B,CAAC,CAAC,GAAG,MAAM,CAAC,OAAO,iGAAiG;oBACpH,CAAC,CAAC,MAAM,CAAC,MAAM,IAAI,MAAM,CAAC,OAAO,CAAC;gBACpC,OAAO;oBACN,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,CAAC;oBAC1C,OAAO,EAAE;wBACR,IAAI,EAAE,MAAe;wBACrB,MAAM;wBACN,MAAM,EAAE,MAAM,CAAC,MAAM;wBACrB,GAAG,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,MAAM,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;qBAC/D;oBACD,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,mBAA4B,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;iBAC9E,CAAC;YACH,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBAChB,MAAM,MAAM,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;gBACtE,OAAO;oBACN,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;oBAClD,OAAO,EAAE,EAAE,IAAI,EAAE,OAAgB,EAAE,MAAM,EAAE,MAAM,EAAE;oBACnD,OAAO,EAAE,IAAI;iBACb,CAAC;YACH,CAAC;QACF,CAAC;KACD,CAAC;AACH,CAAC","sourcesContent":["import { type Static, Type } from \"typebox\";\nimport type { BackgroundToolTaskRecord } from \"../background-tool-task-controller.ts\";\nimport type { ToolDefinition } from \"../extensions/types.ts\";\n\nconst MAX_TASK_ID_CHARS = 128;\nconst MAX_LISTED_TASKS = 32;\n\nconst schema = Type.Object(\n\t{\n\t\taction: Type.String({\n\t\t\tenum: [\"list\", \"wait\", \"cancel\"],\n\t\t\tdescription: \"List once, wait once for a dependency, or cancel. Never poll.\",\n\t\t}),\n\t\ttaskId: Type.Optional(\n\t\t\tType.String({\n\t\t\t\tmaxLength: MAX_TASK_ID_CHARS,\n\t\t\t\tdescription: \"Task id; required for wait/cancel.\",\n\t\t\t}),\n\t\t),\n\t},\n\t{ additionalProperties: false },\n);\n\ntype Input = Static<typeof schema>;\n\nexport interface ToolTaskDependencies {\n\tlist(): BackgroundToolTaskRecord[];\n\tobserve(taskIds: readonly string[]): void;\n\twait(taskId: string, signal?: AbortSignal): Promise<BackgroundToolTaskRecord>;\n\tcancel(taskId: string): boolean;\n}\n\nexport interface ToolTaskDetails {\n\tkind: \"list\" | \"wait\" | \"cancel\" | \"error\";\n\tcount?: number;\n\ttaskId?: string;\n\tstatus?: BackgroundToolTaskRecord[\"status\"];\n\tartifactId?: string;\n\treason?: string;\n}\n\nfunction validTaskId(value: string | undefined): string | undefined {\n\tconst taskId = value?.trim();\n\tif (!taskId || taskId.length > MAX_TASK_ID_CHARS) return undefined;\n\treturn taskId;\n}\n\nfunction projectList(records: readonly BackgroundToolTaskRecord[]): {\n\tincluded: readonly BackgroundToolTaskRecord[];\n\ttext: string;\n} {\n\tif (records.length === 0) return { included: [], text: \"No background tool tasks in this session.\" };\n\tconst included = records.slice(-MAX_LISTED_TASKS);\n\tconst omitted = records.length - included.length;\n\treturn {\n\t\tincluded,\n\t\ttext: [\n\t\t\t...included.map((record) => `${record.taskId}: ${record.status} — ${record.summary}`),\n\t\t\t...(omitted > 0 ? [`${omitted} older task(s) omitted from this bounded snapshot.`] : []),\n\t\t\t\"Do not poll. Continue independent work, or call wait once only when a running task is a dependency.\",\n\t\t].join(\"\\n\"),\n\t};\n}\n\nexport function createToolTaskToolDefinition(deps: ToolTaskDependencies): ToolDefinition<typeof schema> {\n\treturn {\n\t\tname: \"tool_task\",\n\t\tlabel: \"tool_task\",\n\t\tdescription:\n\t\t\t\"List, wait for, or cancel this session's background tool calls. Continue other work; wait is event-driven, never poll. Cite a completed taskId as goal evidence or task_steps evidence.\",\n\t\tpromptSnippet: \"Event-driven background tool control; wait once, never poll.\",\n\t\tpromptGuidelines: [\n\t\t\t\"Handoff is not completion. Need the result: wait once with taskId.\",\n\t\t\t\"Cite the taskId on the matching task_steps step and as goal add_evidence kind=tool uri.\",\n\t\t],\n\t\tparameters: schema,\n\t\tasync execute(_toolCallId, input: Input, signal) {\n\t\t\tif (input.action === \"list\") {\n\t\t\t\tconst records = deps.list();\n\t\t\t\tconst projection = projectList(records);\n\t\t\t\tdeps.observe(projection.included.map((record) => record.taskId));\n\t\t\t\treturn {\n\t\t\t\t\tcontent: [{ type: \"text\" as const, text: projection.text }],\n\t\t\t\t\tdetails: { kind: \"list\" as const, count: records.length },\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tconst taskId = validTaskId(input.taskId);\n\t\t\tif (!taskId) {\n\t\t\t\treturn {\n\t\t\t\t\tcontent: [{ type: \"text\" as const, text: `${input.action} requires a valid taskId.` }],\n\t\t\t\t\tdetails: { kind: \"error\" as const, reason: \"invalid_task_id\" },\n\t\t\t\t\tisError: true,\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tif (input.action === \"cancel\") {\n\t\t\t\tconst canceled = deps.cancel(taskId);\n\t\t\t\treturn {\n\t\t\t\t\tcontent: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ttype: \"text\" as const,\n\t\t\t\t\t\t\ttext: canceled\n\t\t\t\t\t\t\t\t? `Cancellation requested for ${taskId}.`\n\t\t\t\t\t\t\t\t: `No running background tool task named ${taskId}.`,\n\t\t\t\t\t\t},\n\t\t\t\t\t],\n\t\t\t\t\tdetails: {\n\t\t\t\t\t\tkind: \"cancel\" as const,\n\t\t\t\t\t\ttaskId,\n\t\t\t\t\t\t...(canceled ? {} : { reason: \"not_running\" }),\n\t\t\t\t\t},\n\t\t\t\t};\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tconst record = await deps.wait(taskId, signal);\n\t\t\t\tconst isError = record.status === \"failed\" || record.status === \"canceled\";\n\t\t\t\tconst text =\n\t\t\t\t\trecord.status === \"running\"\n\t\t\t\t\t\t? `${record.summary}\\nWait watchdog elapsed; continue independent work. The terminal handoff will wake the session.`\n\t\t\t\t\t\t: record.output || record.summary;\n\t\t\t\treturn {\n\t\t\t\t\tcontent: [{ type: \"text\" as const, text }],\n\t\t\t\t\tdetails: {\n\t\t\t\t\t\tkind: \"wait\" as const,\n\t\t\t\t\t\ttaskId,\n\t\t\t\t\t\tstatus: record.status,\n\t\t\t\t\t\t...(record.artifactId ? { artifactId: record.artifactId } : {}),\n\t\t\t\t\t},\n\t\t\t\t\t...(isError ? { isError: true, errorKind: \"operation_outcome\" as const } : {}),\n\t\t\t\t};\n\t\t\t} catch (error) {\n\t\t\t\tconst reason = error instanceof Error ? error.message : String(error);\n\t\t\t\treturn {\n\t\t\t\t\tcontent: [{ type: \"text\" as const, text: reason }],\n\t\t\t\t\tdetails: { kind: \"error\" as const, taskId, reason },\n\t\t\t\t\tisError: true,\n\t\t\t\t};\n\t\t\t}\n\t\t},\n\t};\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"write.d.ts","sourceRoot":"","sources":["../../../src/core/tools/write.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,SAAS,EAA2C,MAAM,iCAAiC,CAAC;AAE1G,OAAO,EAAE,KAAK,MAAM,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAG5C,OAAO,KAAK,EAAE,cAAc,EAA2B,MAAM,wBAAwB,CAAC;AACtF,OAAO,EAEN,KAAK,4BAA4B,EAIjC,MAAM,4BAA4B,CAAC;AACpC,OAAO,EAEN,4BAA4B,EAE5B,MAAM,2BAA2B,CAAC;AAOnC,QAAA,MAAM,WAAW;;;;;;;;;IAsBf,CAAC;AAEH,MAAM,MAAM,cAAc,GAAG,MAAM,CAAC,OAAO,WAAW,CAAC,CAAC;AAExD;;;GAGG;AACH,MAAM,WAAW,eAAe;IAC/B,oFAAoF;IACpF,UAAU,EAAE,CAAC,YAAY,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACrE,mCAAmC;IACnC,KAAK,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACtC;AAOD,MAAM,WAAW,gBAAgB;IAChC,oEAAoE;IACpE,UAAU,CAAC,EAAE,eAAe,CAAC;IAC7B,oFAAoF;IACpF,wBAAwB,CAAC,EAAE,4BAA4B,CAAC;IACxD,6EAA6E;IAC7E,gBAAgB,CAAC,EAAE,4BAA4B,CAAC;CAChD;AAED,MAAM,WAAW,gBAAgB;IAChC,KAAK,EAAE,SAAS,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;CACnB;AA6ND,wBAAgB,yBAAyB,CACxC,GAAG,EAAE,MAAM,EACX,OAAO,CAAC,EAAE,gBAAgB,GACxB,cAAc,CAAC,OAAO,WAAW,EAAE,gBAAgB,CAAC,CAiLtD;AAED,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,gBAAgB,GAAG,SAAS,CAAC,OAAO,WAAW,CAAC,CAEtG"}
1
+ {"version":3,"file":"write.d.ts","sourceRoot":"","sources":["../../../src/core/tools/write.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,SAAS,EAA2C,MAAM,iCAAiC,CAAC;AAE1G,OAAO,EAAE,KAAK,MAAM,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAG5C,OAAO,KAAK,EAAE,cAAc,EAA2B,MAAM,wBAAwB,CAAC;AACtF,OAAO,EAEN,KAAK,4BAA4B,EAIjC,MAAM,4BAA4B,CAAC;AACpC,OAAO,EAEN,4BAA4B,EAE5B,MAAM,2BAA2B,CAAC;AAOnC,QAAA,MAAM,WAAW;;;;;;;;;IAsBf,CAAC;AAEH,MAAM,MAAM,cAAc,GAAG,MAAM,CAAC,OAAO,WAAW,CAAC,CAAC;AAExD;;;GAGG;AACH,MAAM,WAAW,eAAe;IAC/B,oFAAoF;IACpF,UAAU,EAAE,CAAC,YAAY,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACrE,mCAAmC;IACnC,KAAK,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACtC;AAOD,MAAM,WAAW,gBAAgB;IAChC,oEAAoE;IACpE,UAAU,CAAC,EAAE,eAAe,CAAC;IAC7B,oFAAoF;IACpF,wBAAwB,CAAC,EAAE,4BAA4B,CAAC;IACxD,6EAA6E;IAC7E,gBAAgB,CAAC,EAAE,4BAA4B,CAAC;CAChD;AAED,MAAM,WAAW,gBAAgB;IAChC,KAAK,EAAE,SAAS,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;CACnB;AA6ND,wBAAgB,yBAAyB,CACxC,GAAG,EAAE,MAAM,EACX,OAAO,CAAC,EAAE,gBAAgB,GACxB,cAAc,CAAC,OAAO,WAAW,EAAE,gBAAgB,CAAC,CAgLtD;AAED,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,gBAAgB,GAAG,SAAS,CAAC,OAAO,WAAW,CAAC,CAEtG"}
@@ -204,7 +204,6 @@ export function createWriteToolDefinition(cwd, options) {
204
204
  return {
205
205
  name: "write",
206
206
  label: "write",
207
- toolGroup: "files",
208
207
  description: "Create a new file without overwriting. Send path and exactly one of content or contentRef. After a path-only collision, use the returned payloadRef with only a corrected path. The harness owns preflight, bounded payload retention, and atomic rechecks.",
209
208
  promptSnippet: "Preflight new paths; never overwrite",
210
209
  promptGuidelines: [
@@ -323,7 +322,7 @@ export function createWriteToolDefinition(cwd, options) {
323
322
  const fileContent = str(renderArgs?.content);
324
323
  const component = context.lastComponent ?? new WriteCallRenderComponent();
325
324
  if (fileContent !== null) {
326
- component.cache = getWriteHighlightCache(component.cache, args, rawPath, fileContent, context.argsComplete && !context.toolGroupSummary, context.expanded);
325
+ component.cache = getWriteHighlightCache(component.cache, args, rawPath, fileContent, context.argsComplete, context.expanded);
327
326
  }
328
327
  else {
329
328
  component.cache = undefined;
@@ -1 +1 @@
1
- {"version":3,"file":"write.js","sourceRoot":"","sources":["../../../src/core/tools/write.ts"],"names":[],"mappings":"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","sourcesContent":["import { mkdir as fsMkdir, writeFile as fsWriteFile } from \"node:fs/promises\";\nimport { dirname } from \"node:path\";\nimport { type AgentTool, createAgentToolFailureRecoveryAuthority } from \"@caupulican/pi-agent-core/types\";\nimport { Container, Text } from \"@caupulican/pi-tui\";\nimport { type Static, Type } from \"typebox\";\nimport { keyHint } from \"../../modes/interactive/components/keybinding-hints.ts\";\nimport { getLanguageFromPath, highlightCode, type Theme } from \"../../modes/interactive/theme/theme.ts\";\nimport type { ToolDefinition, ToolRenderResultOptions } from \"../extensions/types.ts\";\nimport {\n\tFILE_EXISTS_RECOVERY_TARGET_KIND,\n\ttype FileFailureRecoveryAuthority,\n\tselectFileFailureRecoveryAuthority,\n\tWORKSPACE_MUTATED_RECOVERY_TARGET_KIND,\n\tWRITE_RETARGET_RECOVERY_TARGET_KIND,\n} from \"./file-failure-recovery.ts\";\nimport {\n\ttype FileContentReference,\n\tFileMutationIntentController,\n\tFileMutationPreflightError,\n} from \"./file-mutation-intent.ts\";\nimport { withFileMutationQueue } from \"./file-mutation-queue.ts\";\nimport { resolveToCwd } from \"./path-utils.ts\";\nimport { normalizeDisplayText, renderToolPath, replaceTabs, str } from \"./render-utils.ts\";\nimport { wrapToolDefinition } from \"./tool-definition-wrapper.ts\";\n\nconst writePathSchema = Type.String({ minLength: 1 });\nconst writeSchema = Type.Union([\n\tType.Object(\n\t\t{\n\t\t\tpath: writePathSchema,\n\t\t\tcontent: Type.String(),\n\t\t},\n\t\t{ additionalProperties: false },\n\t),\n\tType.Object(\n\t\t{\n\t\t\tpath: writePathSchema,\n\t\t\tcontentRef: Type.String({ minLength: 1 }),\n\t\t},\n\t\t{ additionalProperties: false },\n\t),\n\tType.Object(\n\t\t{\n\t\t\tpath: writePathSchema,\n\t\t\tpayloadRef: Type.String({ minLength: 1 }),\n\t\t},\n\t\t{ additionalProperties: false },\n\t),\n]);\n\nexport type WriteToolInput = Static<typeof writeSchema>;\n\n/**\n * Pluggable operations for the write tool.\n * Override these to delegate file writing to remote systems (for example SSH).\n */\nexport interface WriteOperations {\n\t/** Atomically create a new file and fail if any entry already occupies the path. */\n\tcreateFile: (absolutePath: string, content: string) => Promise<void>;\n\t/** Create directory recursively */\n\tmkdir: (dir: string) => Promise<void>;\n}\n\nconst defaultWriteOperations: WriteOperations = {\n\tcreateFile: (path, content) => fsWriteFile(path, content, { encoding: \"utf-8\", flag: \"wx\" }),\n\tmkdir: (dir) => fsMkdir(dir, { recursive: true }).then(() => {}),\n};\n\nexport interface WriteToolOptions {\n\t/** Custom operations for file writing. Default: local filesystem */\n\toperations?: WriteOperations;\n\t/** Shared backend identity for exact cross-tool recovery with custom operations. */\n\tfailureRecoveryAuthority?: FileFailureRecoveryAuthority;\n\t/** Session-owned harness preflight and exact-content-reference authority. */\n\tintentController?: FileMutationIntentController;\n}\n\nexport interface WriteToolDetails {\n\tphase: \"written\";\n\tcontentRef?: string;\n\tbyteCount?: number;\n}\n\ntype WriteHighlightCache = {\n\targsRef: unknown;\n\trawPath: string | null;\n\tcountCompleteLines: boolean;\n\texpanded: boolean;\n\trenderedLines: string[];\n\ttotalLines?: number;\n\tcappedByCharacters: boolean;\n\tcappedByLines: boolean;\n};\n\nclass WriteCallRenderComponent extends Text {\n\tcache?: WriteHighlightCache;\n\n\tconstructor() {\n\t\tsuper(\"\", 0, 0);\n\t}\n}\n\nconst WRITE_COLLAPSED_PREVIEW_LINES = 10;\nconst WRITE_COLLAPSED_PREVIEW_CHARS = 8_192;\n\nfunction countWriteDisplayLines(fileContent: string): number {\n\tlet lastContentIndex = fileContent.length - 1;\n\twhile (lastContentIndex >= 0) {\n\t\tconst code = fileContent.charCodeAt(lastContentIndex);\n\t\tif (code !== 10 && code !== 13) break;\n\t\tlastContentIndex--;\n\t}\n\tif (lastContentIndex < 0) return 0;\n\n\tlet lines = 1;\n\tfor (let i = 0; i <= lastContentIndex; i++) {\n\t\tif (fileContent.charCodeAt(i) === 10) lines++;\n\t}\n\treturn lines;\n}\n\nfunction trimTrailingEmptyLines(lines: string[]): string[] {\n\tlet end = lines.length;\n\twhile (end > 0 && lines[end - 1] === \"\") {\n\t\tend--;\n\t}\n\treturn lines.slice(0, end);\n}\n\nfunction buildCollapsedWriteSource(fileContent: string): {\n\tsource: string;\n\tcappedByCharacters: boolean;\n\tcappedByLines: boolean;\n} {\n\tconst rawPrefix = fileContent.slice(0, WRITE_COLLAPSED_PREVIEW_CHARS);\n\tconst normalizedPrefix = replaceTabs(normalizeDisplayText(rawPrefix));\n\tlet end = normalizedPrefix.length;\n\tlet newlineCount = 0;\n\tfor (let i = 0; i < normalizedPrefix.length; i++) {\n\t\tif (normalizedPrefix.charCodeAt(i) !== 10) continue;\n\t\tnewlineCount++;\n\t\tif (newlineCount === WRITE_COLLAPSED_PREVIEW_LINES) {\n\t\t\tend = i;\n\t\t\tbreak;\n\t\t}\n\t}\n\tconst cappedByLines = end < normalizedPrefix.length;\n\treturn {\n\t\tsource: normalizedPrefix.slice(0, end),\n\t\tcappedByCharacters: !cappedByLines && rawPrefix.length < fileContent.length,\n\t\tcappedByLines,\n\t};\n}\n\nfunction buildWriteHighlightCache(\n\targsRef: unknown,\n\trawPath: string | null,\n\tfileContent: string,\n\tcountCompleteLines: boolean,\n\texpanded: boolean,\n): WriteHighlightCache {\n\tconst lang = rawPath ? getLanguageFromPath(rawPath) : undefined;\n\tif (expanded) {\n\t\tconst source = replaceTabs(normalizeDisplayText(fileContent));\n\t\tconst renderedLines = trimTrailingEmptyLines(lang ? highlightCode(source, lang) : source.split(\"\\n\"));\n\t\treturn {\n\t\t\targsRef,\n\t\t\trawPath,\n\t\t\tcountCompleteLines,\n\t\t\texpanded,\n\t\t\trenderedLines,\n\t\t\ttotalLines: renderedLines.length,\n\t\t\tcappedByCharacters: false,\n\t\t\tcappedByLines: false,\n\t\t};\n\t}\n\n\tconst preview = buildCollapsedWriteSource(fileContent);\n\tconst renderedLines = trimTrailingEmptyLines(\n\t\tlang ? highlightCode(preview.source, lang) : preview.source.split(\"\\n\"),\n\t);\n\treturn {\n\t\targsRef,\n\t\trawPath,\n\t\tcountCompleteLines,\n\t\texpanded,\n\t\trenderedLines,\n\t\ttotalLines: countCompleteLines ? countWriteDisplayLines(fileContent) : undefined,\n\t\tcappedByCharacters: preview.cappedByCharacters,\n\t\tcappedByLines: preview.cappedByLines,\n\t};\n}\n\nfunction getWriteHighlightCache(\n\tcache: WriteHighlightCache | undefined,\n\targsRef: unknown,\n\trawPath: string | null,\n\tfileContent: string,\n\tcountCompleteLines: boolean,\n\texpanded: boolean,\n): WriteHighlightCache {\n\tif (\n\t\tcache &&\n\t\tcache.argsRef === argsRef &&\n\t\tcache.rawPath === rawPath &&\n\t\tcache.countCompleteLines === countCompleteLines &&\n\t\tcache.expanded === expanded\n\t) {\n\t\treturn cache;\n\t}\n\treturn buildWriteHighlightCache(argsRef, rawPath, fileContent, countCompleteLines, expanded);\n}\n\nfunction formatWriteCall(\n\targs: { path?: string; file_path?: string; content?: string; contentRef?: string; payloadRef?: string } | undefined,\n\toptions: ToolRenderResultOptions,\n\ttheme: Theme,\n\tcache: WriteHighlightCache | undefined,\n\tcwd: string,\n): string {\n\tconst rawPath = str(args?.file_path ?? args?.path);\n\tconst fileContent = str(args?.content);\n\tconst hasContent = typeof args?.content === \"string\";\n\tconst pathDisplay = renderToolPath(rawPath, theme, cwd);\n\tlet text = `${theme.fg(\"toolTitle\", theme.bold(\"write\"))} ${pathDisplay}`;\n\n\tif (!hasContent && typeof args?.contentRef !== \"string\" && typeof args?.payloadRef !== \"string\") {\n\t\ttext += `\\n\\n${theme.fg(\"error\", \"[invalid content arg - expected string]\")}`;\n\t} else if (hasContent && fileContent) {\n\t\tconst lang = rawPath ? getLanguageFromPath(rawPath) : undefined;\n\t\tconst displayLines = cache?.renderedLines ?? [];\n\t\ttext += `\\n\\n${displayLines.map((line) => (lang ? line : theme.fg(\"toolOutput\", replaceTabs(line)))).join(\"\\n\")}`;\n\t\tif (!options.expanded && cache && (cache.cappedByCharacters || cache.cappedByLines)) {\n\t\t\tconst total = cache.totalLines;\n\t\t\tif (cache.cappedByCharacters) {\n\t\t\t\tconst totalSuffix = total === undefined ? \"\" : `; ${total} total line${total === 1 ? \"\" : \"s\"}`;\n\t\t\t\ttext += `${theme.fg(\"muted\", `\\n... (preview capped at ${WRITE_COLLAPSED_PREVIEW_CHARS} characters${totalSuffix},`)} ${keyHint(\"app.tools.expand\", \"to expand\")})`;\n\t\t\t} else if (total === undefined) {\n\t\t\t\ttext += `${theme.fg(\"muted\", \"\\n... (preview capped,\")} ${keyHint(\"app.tools.expand\", \"to expand\")})`;\n\t\t\t} else {\n\t\t\t\tconst remaining = Math.max(0, total - displayLines.length);\n\t\t\t\tif (remaining > 0) {\n\t\t\t\t\ttext += `${theme.fg(\"muted\", `\\n... (${remaining} more lines, ${total} total,`)} ${keyHint(\"app.tools.expand\", \"to expand\")})`;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t} else if (args?.contentRef) {\n\t\ttext += `\\n\\n${theme.fg(\"muted\", `reuse ${args.contentRef}`)}`;\n\t} else if (args?.payloadRef) {\n\t\ttext += `\\n\\n${theme.fg(\"muted\", `retarget ${args.payloadRef}`)}`;\n\t}\n\n\treturn text;\n}\n\nasync function writeCollisionWithRetainedPayload(\n\terror: FileMutationPreflightError,\n\tinput: WriteToolInput,\n\tintentController: FileMutationIntentController,\n\tsignal?: AbortSignal,\n): Promise<Error> {\n\tconst retargetError = (reference: string): Error =>\n\t\tnew Error(\n\t\t\t`PI_FILE_MUTATION_RETARGET write_collision: ${reference}. Choose only a corrected path; the exact valid write payload is retained.`,\n\t\t);\n\tif (\"contentRef\" in input) {\n\t\tawait intentController.assertContentReference(input.contentRef, signal);\n\t\treturn retargetError(`contentRef ${input.contentRef}`);\n\t}\n\tif (\"payloadRef\" in input) {\n\t\tawait intentController.assertMutationPayload(input.payloadRef, \"write\", signal);\n\t\treturn retargetError(`payloadRef ${input.payloadRef}`);\n\t}\n\n\ttry {\n\t\tconst retained = await intentController.retainMutationPayload(\"write\", input.content);\n\t\tif (retained) {\n\t\t\treturn retargetError(`payloadRef ${retained.payloadRef}`);\n\t\t}\n\t} catch {\n\t\t// The collision remains authoritative when the bounded retry cache is unavailable.\n\t}\n\treturn new Error(`${error.message} The payload could not be retained within the secure retry-cache bound.`);\n}\n\nfunction formatWriteResult(\n\tresult: { content: Array<{ type: string; text?: string; data?: string; mimeType?: string }>; isError?: boolean },\n\ttheme: Theme,\n): string | undefined {\n\tif (!result.isError) {\n\t\treturn undefined;\n\t}\n\tconst output = result.content\n\t\t.filter((c) => c.type === \"text\")\n\t\t.map((c) => c.text || \"\")\n\t\t.join(\"\\n\");\n\tif (!output) {\n\t\treturn undefined;\n\t}\n\treturn `\\n${theme.fg(\"error\", output)}`;\n}\n\nexport function createWriteToolDefinition(\n\tcwd: string,\n\toptions?: WriteToolOptions,\n): ToolDefinition<typeof writeSchema, WriteToolDetails> {\n\tconst ops = options?.operations ?? defaultWriteOperations;\n\tconst failureRecoveryAuthority = selectFileFailureRecoveryAuthority(\n\t\toptions?.operations !== undefined,\n\t\toptions?.failureRecoveryAuthority,\n\t);\n\tif (options?.operations && !options.intentController) {\n\t\tthrow new Error(\"Custom write operations require a matching file mutation intent controller.\");\n\t}\n\tconst intentController = options?.intentController ?? new FileMutationIntentController();\n\tconst retargetRecoveryAuthority = createAgentToolFailureRecoveryAuthority();\n\treturn {\n\t\tname: \"write\",\n\t\tlabel: \"write\",\n\t\ttoolGroup: \"files\",\n\t\tdescription:\n\t\t\t\"Create a new file without overwriting. Send path and exactly one of content or contentRef. After a path-only collision, use the returned payloadRef with only a corrected path. The harness owns preflight, bounded payload retention, and atomic rechecks.\",\n\t\tpromptSnippet: \"Preflight new paths; never overwrite\",\n\t\tpromptGuidelines: [\n\t\t\t\"Call once: path plus exactly one of content/contentRef; harness owns preparation/collision checks.\",\n\t\t\t\"Collision with payloadRef: choose new path, reuse reference; never regenerate content.\",\n\t\t\t\"write is create-only; edit existing files. Reuse contentRef for exact copies.\",\n\t\t],\n\t\tparameters: writeSchema,\n\t\tfailureRecovery: {\n\t\t\tgetFailureTargets: (params, failure) =>\n\t\t\t\tfailure.failureCode === \"mutation_retarget_required\"\n\t\t\t\t\t? [\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tauthority: retargetRecoveryAuthority,\n\t\t\t\t\t\t\t\tkind: WRITE_RETARGET_RECOVERY_TARGET_KIND,\n\t\t\t\t\t\t\t\tscope: resolveToCwd(params.path, cwd),\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t]\n\t\t\t\t\t: [],\n\t\t\tactions: [\n\t\t\t\t{\n\t\t\t\t\tkind: \"correct\",\n\t\t\t\t\tauthority: retargetRecoveryAuthority,\n\t\t\t\t\ttargetKind: WRITE_RETARGET_RECOVERY_TARGET_KIND,\n\t\t\t\t\tinstruction:\n\t\t\t\t\t\t\"Use write with the retained payloadRef and a corrected new path; write cannot overwrite an existing entry.\",\n\t\t\t\t},\n\t\t\t\t...(failureRecoveryAuthority\n\t\t\t\t\t? [\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tkind: \"repair\" as const,\n\t\t\t\t\t\t\t\tauthority: failureRecoveryAuthority.contractAuthority,\n\t\t\t\t\t\t\t\ttargetKind: FILE_EXISTS_RECOVERY_TARGET_KIND,\n\t\t\t\t\t\t\t\tinstruction:\n\t\t\t\t\t\t\t\t\t\"If the goal requires this exact missing file and its content is known, create it with write.\",\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tkind: \"repair\" as const,\n\t\t\t\t\t\t\t\tauthority: failureRecoveryAuthority.contractAuthority,\n\t\t\t\t\t\t\t\ttargetKind: WORKSPACE_MUTATED_RECOVERY_TARGET_KIND,\n\t\t\t\t\t\t\t\tinstruction:\n\t\t\t\t\t\t\t\t\t\"When a command failed because workspace contents need repair, create the required file and rerun that exact command.\",\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t]\n\t\t\t\t\t: []),\n\t\t\t],\n\t\t},\n\t\tasync execute(_toolCallId, input: WriteToolInput, signal?: AbortSignal, _onUpdate?, _ctx?) {\n\t\t\tconst { path } = input;\n\t\t\tconst absolutePath = resolveToCwd(path, cwd);\n\t\t\tconst content = \"content\" in input && typeof input.content === \"string\" ? input.content : undefined;\n\t\t\tconst contentRef =\n\t\t\t\t\"contentRef\" in input && typeof input.contentRef === \"string\" ? input.contentRef : undefined;\n\t\t\tconst payloadRef =\n\t\t\t\t\"payloadRef\" in input && typeof input.payloadRef === \"string\" ? input.payloadRef : undefined;\n\t\t\tif ([content, contentRef, payloadRef].filter((value) => value !== undefined).length !== 1) {\n\t\t\t\tthrow new Error(\"Write requires exactly one of content, contentRef, or payloadRef.\");\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tconst lease = await intentController.prepare(\"write\", absolutePath, signal, path);\n\t\t\t\treturn await withFileMutationQueue(absolutePath, async () => {\n\t\t\t\t\t// Do not reject from an abort event listener here: that would release the\n\t\t\t\t\t// mutation queue while an in-flight filesystem operation may still finish.\n\t\t\t\t\t// Checking signal.aborted after each await observes the same aborts while\n\t\t\t\t\t// keeping the queue locked until the current operation has settled.\n\t\t\t\t\tconst throwIfAborted = (): void => {\n\t\t\t\t\t\tif (signal?.aborted) throw new Error(\"Operation aborted\");\n\t\t\t\t\t};\n\n\t\t\t\t\tthrowIfAborted();\n\t\t\t\t\tawait intentController.assertCurrent(lease, signal);\n\t\t\t\t\tawait ops.mkdir(dirname(absolutePath));\n\t\t\t\t\tthrowIfAborted();\n\n\t\t\t\t\tlet contentReference: FileContentReference;\n\t\t\t\t\ttry {\n\t\t\t\t\t\tif (content !== undefined) {\n\t\t\t\t\t\t\tawait ops.createFile(absolutePath, content);\n\t\t\t\t\t\t\tcontentReference = intentController.rememberContent(absolutePath, content);\n\t\t\t\t\t\t} else if (contentRef !== undefined) {\n\t\t\t\t\t\t\tcontentReference = await intentController.copyReferencedContent(contentRef, absolutePath, signal);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tif (payloadRef === undefined) throw new Error(\"Write requires a payload reference.\");\n\t\t\t\t\t\t\tcontentReference = await intentController.copyMutationPayload(payloadRef, absolutePath, signal);\n\t\t\t\t\t\t}\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\tif (typeof error === \"object\" && error !== null && \"code\" in error && error.code === \"EEXIST\") {\n\t\t\t\t\t\t\tthrow new FileMutationPreflightError(\n\t\t\t\t\t\t\t\t\"write_collision\",\n\t\t\t\t\t\t\t\t`Write collision: ${path} already exists; no content was overwritten.`,\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tthrow error;\n\t\t\t\t\t}\n\t\t\t\t\tthrowIfAborted();\n\n\t\t\t\t\tconst byteCount = contentReference.byteLength;\n\t\t\t\t\treturn {\n\t\t\t\t\t\tcontent: [\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\ttype: \"text\" as const,\n\t\t\t\t\t\t\t\ttext: `Successfully wrote ${byteCount} bytes to ${path}; this write is complete, so do not call write again for this path. To copy these exact bytes to a different new path, call write once for that path with contentRef ${contentReference.contentRef}.`,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t],\n\t\t\t\t\t\tdetails: {\n\t\t\t\t\t\t\tphase: \"written\" as const,\n\t\t\t\t\t\t\tcontentRef: contentReference.contentRef,\n\t\t\t\t\t\t\tbyteCount,\n\t\t\t\t\t\t},\n\t\t\t\t\t};\n\t\t\t\t});\n\t\t\t} catch (error) {\n\t\t\t\tif (error instanceof FileMutationPreflightError && error.reason === \"write_collision\") {\n\t\t\t\t\tthrow await writeCollisionWithRetainedPayload(error, input, intentController, signal);\n\t\t\t\t}\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t},\n\t\trenderCall(args, theme, context) {\n\t\t\tconst renderArgs = args as\n\t\t\t\t| { path?: string; file_path?: string; content?: string; contentRef?: string; payloadRef?: string }\n\t\t\t\t| undefined;\n\t\t\tconst rawPath = str(renderArgs?.file_path ?? renderArgs?.path);\n\t\t\tconst fileContent = str(renderArgs?.content);\n\t\t\tconst component =\n\t\t\t\t(context.lastComponent as WriteCallRenderComponent | undefined) ?? new WriteCallRenderComponent();\n\t\t\tif (fileContent !== null) {\n\t\t\t\tcomponent.cache = getWriteHighlightCache(\n\t\t\t\t\tcomponent.cache,\n\t\t\t\t\targs,\n\t\t\t\t\trawPath,\n\t\t\t\t\tfileContent,\n\t\t\t\t\tcontext.argsComplete && !context.toolGroupSummary,\n\t\t\t\t\tcontext.expanded,\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\tcomponent.cache = undefined;\n\t\t\t}\n\t\t\tcomponent.setText(\n\t\t\t\tformatWriteCall(\n\t\t\t\t\trenderArgs,\n\t\t\t\t\t{ expanded: context.expanded, isPartial: context.isPartial },\n\t\t\t\t\ttheme,\n\t\t\t\t\tcomponent.cache,\n\t\t\t\t\tcontext.cwd,\n\t\t\t\t),\n\t\t\t);\n\t\t\treturn component;\n\t\t},\n\t\trenderResult(result, _options, theme, context) {\n\t\t\tconst output = formatWriteResult({ ...result, isError: context.isError }, theme);\n\t\t\tif (!output) {\n\t\t\t\tconst component = (context.lastComponent as Container | undefined) ?? new Container();\n\t\t\t\tcomponent.clear();\n\t\t\t\treturn component;\n\t\t\t}\n\t\t\tconst text = (context.lastComponent as Text | undefined) ?? new Text(\"\", 0, 0);\n\t\t\ttext.setText(output);\n\t\t\treturn text;\n\t\t},\n\t};\n}\n\nexport function createWriteTool(cwd: string, options?: WriteToolOptions): AgentTool<typeof writeSchema> {\n\treturn wrapToolDefinition(createWriteToolDefinition(cwd, options));\n}\n"]}
1
+ {"version":3,"file":"write.js","sourceRoot":"","sources":["../../../src/core/tools/write.ts"],"names":[],"mappings":"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","sourcesContent":["import { mkdir as fsMkdir, writeFile as fsWriteFile } from \"node:fs/promises\";\nimport { dirname } from \"node:path\";\nimport { type AgentTool, createAgentToolFailureRecoveryAuthority } from \"@caupulican/pi-agent-core/types\";\nimport { Container, Text } from \"@caupulican/pi-tui\";\nimport { type Static, Type } from \"typebox\";\nimport { keyHint } from \"../../modes/interactive/components/keybinding-hints.ts\";\nimport { getLanguageFromPath, highlightCode, type Theme } from \"../../modes/interactive/theme/theme.ts\";\nimport type { ToolDefinition, ToolRenderResultOptions } from \"../extensions/types.ts\";\nimport {\n\tFILE_EXISTS_RECOVERY_TARGET_KIND,\n\ttype FileFailureRecoveryAuthority,\n\tselectFileFailureRecoveryAuthority,\n\tWORKSPACE_MUTATED_RECOVERY_TARGET_KIND,\n\tWRITE_RETARGET_RECOVERY_TARGET_KIND,\n} from \"./file-failure-recovery.ts\";\nimport {\n\ttype FileContentReference,\n\tFileMutationIntentController,\n\tFileMutationPreflightError,\n} from \"./file-mutation-intent.ts\";\nimport { withFileMutationQueue } from \"./file-mutation-queue.ts\";\nimport { resolveToCwd } from \"./path-utils.ts\";\nimport { normalizeDisplayText, renderToolPath, replaceTabs, str } from \"./render-utils.ts\";\nimport { wrapToolDefinition } from \"./tool-definition-wrapper.ts\";\n\nconst writePathSchema = Type.String({ minLength: 1 });\nconst writeSchema = Type.Union([\n\tType.Object(\n\t\t{\n\t\t\tpath: writePathSchema,\n\t\t\tcontent: Type.String(),\n\t\t},\n\t\t{ additionalProperties: false },\n\t),\n\tType.Object(\n\t\t{\n\t\t\tpath: writePathSchema,\n\t\t\tcontentRef: Type.String({ minLength: 1 }),\n\t\t},\n\t\t{ additionalProperties: false },\n\t),\n\tType.Object(\n\t\t{\n\t\t\tpath: writePathSchema,\n\t\t\tpayloadRef: Type.String({ minLength: 1 }),\n\t\t},\n\t\t{ additionalProperties: false },\n\t),\n]);\n\nexport type WriteToolInput = Static<typeof writeSchema>;\n\n/**\n * Pluggable operations for the write tool.\n * Override these to delegate file writing to remote systems (for example SSH).\n */\nexport interface WriteOperations {\n\t/** Atomically create a new file and fail if any entry already occupies the path. */\n\tcreateFile: (absolutePath: string, content: string) => Promise<void>;\n\t/** Create directory recursively */\n\tmkdir: (dir: string) => Promise<void>;\n}\n\nconst defaultWriteOperations: WriteOperations = {\n\tcreateFile: (path, content) => fsWriteFile(path, content, { encoding: \"utf-8\", flag: \"wx\" }),\n\tmkdir: (dir) => fsMkdir(dir, { recursive: true }).then(() => {}),\n};\n\nexport interface WriteToolOptions {\n\t/** Custom operations for file writing. Default: local filesystem */\n\toperations?: WriteOperations;\n\t/** Shared backend identity for exact cross-tool recovery with custom operations. */\n\tfailureRecoveryAuthority?: FileFailureRecoveryAuthority;\n\t/** Session-owned harness preflight and exact-content-reference authority. */\n\tintentController?: FileMutationIntentController;\n}\n\nexport interface WriteToolDetails {\n\tphase: \"written\";\n\tcontentRef?: string;\n\tbyteCount?: number;\n}\n\ntype WriteHighlightCache = {\n\targsRef: unknown;\n\trawPath: string | null;\n\tcountCompleteLines: boolean;\n\texpanded: boolean;\n\trenderedLines: string[];\n\ttotalLines?: number;\n\tcappedByCharacters: boolean;\n\tcappedByLines: boolean;\n};\n\nclass WriteCallRenderComponent extends Text {\n\tcache?: WriteHighlightCache;\n\n\tconstructor() {\n\t\tsuper(\"\", 0, 0);\n\t}\n}\n\nconst WRITE_COLLAPSED_PREVIEW_LINES = 10;\nconst WRITE_COLLAPSED_PREVIEW_CHARS = 8_192;\n\nfunction countWriteDisplayLines(fileContent: string): number {\n\tlet lastContentIndex = fileContent.length - 1;\n\twhile (lastContentIndex >= 0) {\n\t\tconst code = fileContent.charCodeAt(lastContentIndex);\n\t\tif (code !== 10 && code !== 13) break;\n\t\tlastContentIndex--;\n\t}\n\tif (lastContentIndex < 0) return 0;\n\n\tlet lines = 1;\n\tfor (let i = 0; i <= lastContentIndex; i++) {\n\t\tif (fileContent.charCodeAt(i) === 10) lines++;\n\t}\n\treturn lines;\n}\n\nfunction trimTrailingEmptyLines(lines: string[]): string[] {\n\tlet end = lines.length;\n\twhile (end > 0 && lines[end - 1] === \"\") {\n\t\tend--;\n\t}\n\treturn lines.slice(0, end);\n}\n\nfunction buildCollapsedWriteSource(fileContent: string): {\n\tsource: string;\n\tcappedByCharacters: boolean;\n\tcappedByLines: boolean;\n} {\n\tconst rawPrefix = fileContent.slice(0, WRITE_COLLAPSED_PREVIEW_CHARS);\n\tconst normalizedPrefix = replaceTabs(normalizeDisplayText(rawPrefix));\n\tlet end = normalizedPrefix.length;\n\tlet newlineCount = 0;\n\tfor (let i = 0; i < normalizedPrefix.length; i++) {\n\t\tif (normalizedPrefix.charCodeAt(i) !== 10) continue;\n\t\tnewlineCount++;\n\t\tif (newlineCount === WRITE_COLLAPSED_PREVIEW_LINES) {\n\t\t\tend = i;\n\t\t\tbreak;\n\t\t}\n\t}\n\tconst cappedByLines = end < normalizedPrefix.length;\n\treturn {\n\t\tsource: normalizedPrefix.slice(0, end),\n\t\tcappedByCharacters: !cappedByLines && rawPrefix.length < fileContent.length,\n\t\tcappedByLines,\n\t};\n}\n\nfunction buildWriteHighlightCache(\n\targsRef: unknown,\n\trawPath: string | null,\n\tfileContent: string,\n\tcountCompleteLines: boolean,\n\texpanded: boolean,\n): WriteHighlightCache {\n\tconst lang = rawPath ? getLanguageFromPath(rawPath) : undefined;\n\tif (expanded) {\n\t\tconst source = replaceTabs(normalizeDisplayText(fileContent));\n\t\tconst renderedLines = trimTrailingEmptyLines(lang ? highlightCode(source, lang) : source.split(\"\\n\"));\n\t\treturn {\n\t\t\targsRef,\n\t\t\trawPath,\n\t\t\tcountCompleteLines,\n\t\t\texpanded,\n\t\t\trenderedLines,\n\t\t\ttotalLines: renderedLines.length,\n\t\t\tcappedByCharacters: false,\n\t\t\tcappedByLines: false,\n\t\t};\n\t}\n\n\tconst preview = buildCollapsedWriteSource(fileContent);\n\tconst renderedLines = trimTrailingEmptyLines(\n\t\tlang ? highlightCode(preview.source, lang) : preview.source.split(\"\\n\"),\n\t);\n\treturn {\n\t\targsRef,\n\t\trawPath,\n\t\tcountCompleteLines,\n\t\texpanded,\n\t\trenderedLines,\n\t\ttotalLines: countCompleteLines ? countWriteDisplayLines(fileContent) : undefined,\n\t\tcappedByCharacters: preview.cappedByCharacters,\n\t\tcappedByLines: preview.cappedByLines,\n\t};\n}\n\nfunction getWriteHighlightCache(\n\tcache: WriteHighlightCache | undefined,\n\targsRef: unknown,\n\trawPath: string | null,\n\tfileContent: string,\n\tcountCompleteLines: boolean,\n\texpanded: boolean,\n): WriteHighlightCache {\n\tif (\n\t\tcache &&\n\t\tcache.argsRef === argsRef &&\n\t\tcache.rawPath === rawPath &&\n\t\tcache.countCompleteLines === countCompleteLines &&\n\t\tcache.expanded === expanded\n\t) {\n\t\treturn cache;\n\t}\n\treturn buildWriteHighlightCache(argsRef, rawPath, fileContent, countCompleteLines, expanded);\n}\n\nfunction formatWriteCall(\n\targs: { path?: string; file_path?: string; content?: string; contentRef?: string; payloadRef?: string } | undefined,\n\toptions: ToolRenderResultOptions,\n\ttheme: Theme,\n\tcache: WriteHighlightCache | undefined,\n\tcwd: string,\n): string {\n\tconst rawPath = str(args?.file_path ?? args?.path);\n\tconst fileContent = str(args?.content);\n\tconst hasContent = typeof args?.content === \"string\";\n\tconst pathDisplay = renderToolPath(rawPath, theme, cwd);\n\tlet text = `${theme.fg(\"toolTitle\", theme.bold(\"write\"))} ${pathDisplay}`;\n\n\tif (!hasContent && typeof args?.contentRef !== \"string\" && typeof args?.payloadRef !== \"string\") {\n\t\ttext += `\\n\\n${theme.fg(\"error\", \"[invalid content arg - expected string]\")}`;\n\t} else if (hasContent && fileContent) {\n\t\tconst lang = rawPath ? getLanguageFromPath(rawPath) : undefined;\n\t\tconst displayLines = cache?.renderedLines ?? [];\n\t\ttext += `\\n\\n${displayLines.map((line) => (lang ? line : theme.fg(\"toolOutput\", replaceTabs(line)))).join(\"\\n\")}`;\n\t\tif (!options.expanded && cache && (cache.cappedByCharacters || cache.cappedByLines)) {\n\t\t\tconst total = cache.totalLines;\n\t\t\tif (cache.cappedByCharacters) {\n\t\t\t\tconst totalSuffix = total === undefined ? \"\" : `; ${total} total line${total === 1 ? \"\" : \"s\"}`;\n\t\t\t\ttext += `${theme.fg(\"muted\", `\\n... (preview capped at ${WRITE_COLLAPSED_PREVIEW_CHARS} characters${totalSuffix},`)} ${keyHint(\"app.tools.expand\", \"to expand\")})`;\n\t\t\t} else if (total === undefined) {\n\t\t\t\ttext += `${theme.fg(\"muted\", \"\\n... (preview capped,\")} ${keyHint(\"app.tools.expand\", \"to expand\")})`;\n\t\t\t} else {\n\t\t\t\tconst remaining = Math.max(0, total - displayLines.length);\n\t\t\t\tif (remaining > 0) {\n\t\t\t\t\ttext += `${theme.fg(\"muted\", `\\n... (${remaining} more lines, ${total} total,`)} ${keyHint(\"app.tools.expand\", \"to expand\")})`;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t} else if (args?.contentRef) {\n\t\ttext += `\\n\\n${theme.fg(\"muted\", `reuse ${args.contentRef}`)}`;\n\t} else if (args?.payloadRef) {\n\t\ttext += `\\n\\n${theme.fg(\"muted\", `retarget ${args.payloadRef}`)}`;\n\t}\n\n\treturn text;\n}\n\nasync function writeCollisionWithRetainedPayload(\n\terror: FileMutationPreflightError,\n\tinput: WriteToolInput,\n\tintentController: FileMutationIntentController,\n\tsignal?: AbortSignal,\n): Promise<Error> {\n\tconst retargetError = (reference: string): Error =>\n\t\tnew Error(\n\t\t\t`PI_FILE_MUTATION_RETARGET write_collision: ${reference}. Choose only a corrected path; the exact valid write payload is retained.`,\n\t\t);\n\tif (\"contentRef\" in input) {\n\t\tawait intentController.assertContentReference(input.contentRef, signal);\n\t\treturn retargetError(`contentRef ${input.contentRef}`);\n\t}\n\tif (\"payloadRef\" in input) {\n\t\tawait intentController.assertMutationPayload(input.payloadRef, \"write\", signal);\n\t\treturn retargetError(`payloadRef ${input.payloadRef}`);\n\t}\n\n\ttry {\n\t\tconst retained = await intentController.retainMutationPayload(\"write\", input.content);\n\t\tif (retained) {\n\t\t\treturn retargetError(`payloadRef ${retained.payloadRef}`);\n\t\t}\n\t} catch {\n\t\t// The collision remains authoritative when the bounded retry cache is unavailable.\n\t}\n\treturn new Error(`${error.message} The payload could not be retained within the secure retry-cache bound.`);\n}\n\nfunction formatWriteResult(\n\tresult: { content: Array<{ type: string; text?: string; data?: string; mimeType?: string }>; isError?: boolean },\n\ttheme: Theme,\n): string | undefined {\n\tif (!result.isError) {\n\t\treturn undefined;\n\t}\n\tconst output = result.content\n\t\t.filter((c) => c.type === \"text\")\n\t\t.map((c) => c.text || \"\")\n\t\t.join(\"\\n\");\n\tif (!output) {\n\t\treturn undefined;\n\t}\n\treturn `\\n${theme.fg(\"error\", output)}`;\n}\n\nexport function createWriteToolDefinition(\n\tcwd: string,\n\toptions?: WriteToolOptions,\n): ToolDefinition<typeof writeSchema, WriteToolDetails> {\n\tconst ops = options?.operations ?? defaultWriteOperations;\n\tconst failureRecoveryAuthority = selectFileFailureRecoveryAuthority(\n\t\toptions?.operations !== undefined,\n\t\toptions?.failureRecoveryAuthority,\n\t);\n\tif (options?.operations && !options.intentController) {\n\t\tthrow new Error(\"Custom write operations require a matching file mutation intent controller.\");\n\t}\n\tconst intentController = options?.intentController ?? new FileMutationIntentController();\n\tconst retargetRecoveryAuthority = createAgentToolFailureRecoveryAuthority();\n\treturn {\n\t\tname: \"write\",\n\t\tlabel: \"write\",\n\t\tdescription:\n\t\t\t\"Create a new file without overwriting. Send path and exactly one of content or contentRef. After a path-only collision, use the returned payloadRef with only a corrected path. The harness owns preflight, bounded payload retention, and atomic rechecks.\",\n\t\tpromptSnippet: \"Preflight new paths; never overwrite\",\n\t\tpromptGuidelines: [\n\t\t\t\"Call once: path plus exactly one of content/contentRef; harness owns preparation/collision checks.\",\n\t\t\t\"Collision with payloadRef: choose new path, reuse reference; never regenerate content.\",\n\t\t\t\"write is create-only; edit existing files. Reuse contentRef for exact copies.\",\n\t\t],\n\t\tparameters: writeSchema,\n\t\tfailureRecovery: {\n\t\t\tgetFailureTargets: (params, failure) =>\n\t\t\t\tfailure.failureCode === \"mutation_retarget_required\"\n\t\t\t\t\t? [\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tauthority: retargetRecoveryAuthority,\n\t\t\t\t\t\t\t\tkind: WRITE_RETARGET_RECOVERY_TARGET_KIND,\n\t\t\t\t\t\t\t\tscope: resolveToCwd(params.path, cwd),\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t]\n\t\t\t\t\t: [],\n\t\t\tactions: [\n\t\t\t\t{\n\t\t\t\t\tkind: \"correct\",\n\t\t\t\t\tauthority: retargetRecoveryAuthority,\n\t\t\t\t\ttargetKind: WRITE_RETARGET_RECOVERY_TARGET_KIND,\n\t\t\t\t\tinstruction:\n\t\t\t\t\t\t\"Use write with the retained payloadRef and a corrected new path; write cannot overwrite an existing entry.\",\n\t\t\t\t},\n\t\t\t\t...(failureRecoveryAuthority\n\t\t\t\t\t? [\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tkind: \"repair\" as const,\n\t\t\t\t\t\t\t\tauthority: failureRecoveryAuthority.contractAuthority,\n\t\t\t\t\t\t\t\ttargetKind: FILE_EXISTS_RECOVERY_TARGET_KIND,\n\t\t\t\t\t\t\t\tinstruction:\n\t\t\t\t\t\t\t\t\t\"If the goal requires this exact missing file and its content is known, create it with write.\",\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tkind: \"repair\" as const,\n\t\t\t\t\t\t\t\tauthority: failureRecoveryAuthority.contractAuthority,\n\t\t\t\t\t\t\t\ttargetKind: WORKSPACE_MUTATED_RECOVERY_TARGET_KIND,\n\t\t\t\t\t\t\t\tinstruction:\n\t\t\t\t\t\t\t\t\t\"When a command failed because workspace contents need repair, create the required file and rerun that exact command.\",\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t]\n\t\t\t\t\t: []),\n\t\t\t],\n\t\t},\n\t\tasync execute(_toolCallId, input: WriteToolInput, signal?: AbortSignal, _onUpdate?, _ctx?) {\n\t\t\tconst { path } = input;\n\t\t\tconst absolutePath = resolveToCwd(path, cwd);\n\t\t\tconst content = \"content\" in input && typeof input.content === \"string\" ? input.content : undefined;\n\t\t\tconst contentRef =\n\t\t\t\t\"contentRef\" in input && typeof input.contentRef === \"string\" ? input.contentRef : undefined;\n\t\t\tconst payloadRef =\n\t\t\t\t\"payloadRef\" in input && typeof input.payloadRef === \"string\" ? input.payloadRef : undefined;\n\t\t\tif ([content, contentRef, payloadRef].filter((value) => value !== undefined).length !== 1) {\n\t\t\t\tthrow new Error(\"Write requires exactly one of content, contentRef, or payloadRef.\");\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tconst lease = await intentController.prepare(\"write\", absolutePath, signal, path);\n\t\t\t\treturn await withFileMutationQueue(absolutePath, async () => {\n\t\t\t\t\t// Do not reject from an abort event listener here: that would release the\n\t\t\t\t\t// mutation queue while an in-flight filesystem operation may still finish.\n\t\t\t\t\t// Checking signal.aborted after each await observes the same aborts while\n\t\t\t\t\t// keeping the queue locked until the current operation has settled.\n\t\t\t\t\tconst throwIfAborted = (): void => {\n\t\t\t\t\t\tif (signal?.aborted) throw new Error(\"Operation aborted\");\n\t\t\t\t\t};\n\n\t\t\t\t\tthrowIfAborted();\n\t\t\t\t\tawait intentController.assertCurrent(lease, signal);\n\t\t\t\t\tawait ops.mkdir(dirname(absolutePath));\n\t\t\t\t\tthrowIfAborted();\n\n\t\t\t\t\tlet contentReference: FileContentReference;\n\t\t\t\t\ttry {\n\t\t\t\t\t\tif (content !== undefined) {\n\t\t\t\t\t\t\tawait ops.createFile(absolutePath, content);\n\t\t\t\t\t\t\tcontentReference = intentController.rememberContent(absolutePath, content);\n\t\t\t\t\t\t} else if (contentRef !== undefined) {\n\t\t\t\t\t\t\tcontentReference = await intentController.copyReferencedContent(contentRef, absolutePath, signal);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tif (payloadRef === undefined) throw new Error(\"Write requires a payload reference.\");\n\t\t\t\t\t\t\tcontentReference = await intentController.copyMutationPayload(payloadRef, absolutePath, signal);\n\t\t\t\t\t\t}\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\tif (typeof error === \"object\" && error !== null && \"code\" in error && error.code === \"EEXIST\") {\n\t\t\t\t\t\t\tthrow new FileMutationPreflightError(\n\t\t\t\t\t\t\t\t\"write_collision\",\n\t\t\t\t\t\t\t\t`Write collision: ${path} already exists; no content was overwritten.`,\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tthrow error;\n\t\t\t\t\t}\n\t\t\t\t\tthrowIfAborted();\n\n\t\t\t\t\tconst byteCount = contentReference.byteLength;\n\t\t\t\t\treturn {\n\t\t\t\t\t\tcontent: [\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\ttype: \"text\" as const,\n\t\t\t\t\t\t\t\ttext: `Successfully wrote ${byteCount} bytes to ${path}; this write is complete, so do not call write again for this path. To copy these exact bytes to a different new path, call write once for that path with contentRef ${contentReference.contentRef}.`,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t],\n\t\t\t\t\t\tdetails: {\n\t\t\t\t\t\t\tphase: \"written\" as const,\n\t\t\t\t\t\t\tcontentRef: contentReference.contentRef,\n\t\t\t\t\t\t\tbyteCount,\n\t\t\t\t\t\t},\n\t\t\t\t\t};\n\t\t\t\t});\n\t\t\t} catch (error) {\n\t\t\t\tif (error instanceof FileMutationPreflightError && error.reason === \"write_collision\") {\n\t\t\t\t\tthrow await writeCollisionWithRetainedPayload(error, input, intentController, signal);\n\t\t\t\t}\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t},\n\t\trenderCall(args, theme, context) {\n\t\t\tconst renderArgs = args as\n\t\t\t\t| { path?: string; file_path?: string; content?: string; contentRef?: string; payloadRef?: string }\n\t\t\t\t| undefined;\n\t\t\tconst rawPath = str(renderArgs?.file_path ?? renderArgs?.path);\n\t\t\tconst fileContent = str(renderArgs?.content);\n\t\t\tconst component =\n\t\t\t\t(context.lastComponent as WriteCallRenderComponent | undefined) ?? new WriteCallRenderComponent();\n\t\t\tif (fileContent !== null) {\n\t\t\t\tcomponent.cache = getWriteHighlightCache(\n\t\t\t\t\tcomponent.cache,\n\t\t\t\t\targs,\n\t\t\t\t\trawPath,\n\t\t\t\t\tfileContent,\n\t\t\t\t\tcontext.argsComplete,\n\t\t\t\t\tcontext.expanded,\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\tcomponent.cache = undefined;\n\t\t\t}\n\t\t\tcomponent.setText(\n\t\t\t\tformatWriteCall(\n\t\t\t\t\trenderArgs,\n\t\t\t\t\t{ expanded: context.expanded, isPartial: context.isPartial },\n\t\t\t\t\ttheme,\n\t\t\t\t\tcomponent.cache,\n\t\t\t\t\tcontext.cwd,\n\t\t\t\t),\n\t\t\t);\n\t\t\treturn component;\n\t\t},\n\t\trenderResult(result, _options, theme, context) {\n\t\t\tconst output = formatWriteResult({ ...result, isError: context.isError }, theme);\n\t\t\tif (!output) {\n\t\t\t\tconst component = (context.lastComponent as Container | undefined) ?? new Container();\n\t\t\t\tcomponent.clear();\n\t\t\t\treturn component;\n\t\t\t}\n\t\t\tconst text = (context.lastComponent as Text | undefined) ?? new Text(\"\", 0, 0);\n\t\t\ttext.setText(output);\n\t\t\treturn text;\n\t\t},\n\t};\n}\n\nexport function createWriteTool(cwd: string, options?: WriteToolOptions): AgentTool<typeof writeSchema> {\n\treturn wrapToolDefinition(createWriteToolDefinition(cwd, options));\n}\n"]}
@@ -61,6 +61,8 @@ export interface AtomicFileWriteOptions {
61
61
  */
62
62
  fs?: FaultableFs;
63
63
  }
64
+ /** Narrow an unknown Node filesystem failure without unsafe casts at every storage owner. */
65
+ export declare function isMissingFileError(error: unknown): boolean;
64
66
  /**
65
67
  * Existing auth/settings/trust paths historically used 10 total attempts separated by 20ms. Keep
66
68
  * that low-latency user-facing policy explicit while routing the mechanism through this module.
@@ -1 +1 @@
1
- {"version":3,"file":"atomic-file.d.ts","sourceRoot":"","sources":["../../../src/core/util/atomic-file.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAMH,OAAO,EAAE,KAAK,WAAW,EAAU,MAAM,mBAAmB,CAAC;AA4D7D,MAAM,WAAW,qBAAqB;IACrC;;;;;;;;;;;;;;;;;OAiBG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,+EAA+E;IAC/E,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,gFAAgF;IAChF,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,4EAA4E;IAC5E,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,iGAAiG;IACjG,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,sGAAsG;IACtG,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,+EAA+E;IAC/E,YAAY,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,sBAAsB;IACtC,oGAAoG;IACpG,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;;OAIG;IACH,EAAE,CAAC,EAAE,WAAW,CAAC;CACjB;AAcD;;;GAGG;AACH,eAAO,MAAM,6BAA6B,EAAE,QAAQ,CAAC,qBAAqB,CAIxE,CAAC;AAwGH;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,GAAE,qBAA0B,GAAG,MAAM,IAAI,CAkBrG;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,CAAC,EAAE,OAAO,CAAC,EAAE,qBAAqB,GAAG,CAAC,CAarG;AAED,0GAA0G;AAC1G,wBAAsB,YAAY,CAAC,CAAC,EACnC,QAAQ,EAAE,MAAM,EAChB,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,EACxB,OAAO,CAAC,EAAE,qBAAqB,GAC7B,OAAO,CAAC,CAAC,CAAC,CAqBZ;AA4CD,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,sBAAsB,GAAG,IAAI,CAa7G;AAED,wDAAwD;AACxD,wBAAsB,eAAe,CACpC,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE,sBAAsB,GAC9B,OAAO,CAAC,IAAI,CAAC,CAcf"}
1
+ {"version":3,"file":"atomic-file.d.ts","sourceRoot":"","sources":["../../../src/core/util/atomic-file.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAMH,OAAO,EAAE,KAAK,WAAW,EAAU,MAAM,mBAAmB,CAAC;AA4D7D,MAAM,WAAW,qBAAqB;IACrC;;;;;;;;;;;;;;;;;OAiBG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,+EAA+E;IAC/E,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,gFAAgF;IAChF,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,4EAA4E;IAC5E,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,iGAAiG;IACjG,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,sGAAsG;IACtG,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,+EAA+E;IAC/E,YAAY,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,sBAAsB;IACtC,oGAAoG;IACpG,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;;OAIG;IACH,EAAE,CAAC,EAAE,WAAW,CAAC;CACjB;AAED,6FAA6F;AAC7F,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAE1D;AAcD;;;GAGG;AACH,eAAO,MAAM,6BAA6B,EAAE,QAAQ,CAAC,qBAAqB,CAIxE,CAAC;AAwGH;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,GAAE,qBAA0B,GAAG,MAAM,IAAI,CAkBrG;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,CAAC,EAAE,OAAO,CAAC,EAAE,qBAAqB,GAAG,CAAC,CAarG;AAED,0GAA0G;AAC1G,wBAAsB,YAAY,CAAC,CAAC,EACnC,QAAQ,EAAE,MAAM,EAChB,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,EACxB,OAAO,CAAC,EAAE,qBAAqB,GAC7B,OAAO,CAAC,CAAC,CAAC,CAqBZ;AA4CD,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,sBAAsB,GAAG,IAAI,CAa7G;AAED,wDAAwD;AACxD,wBAAsB,eAAe,CACpC,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE,sBAAsB,GAC9B,OAAO,CAAC,IAAI,CAAC,CAcf"}
@@ -82,6 +82,10 @@ async function renameWithRetry(tmpPath, filePath) {
82
82
  }
83
83
  }
84
84
  }
85
+ /** Narrow an unknown Node filesystem failure without unsafe casts at every storage owner. */
86
+ export function isMissingFileError(error) {
87
+ return typeof error === "object" && error !== null && "code" in error && error.code === "ENOENT";
88
+ }
85
89
  const DEFAULT_RETRIES = 10;
86
90
  const DEFAULT_REALPATH = false;
87
91
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"atomic-file.js","sourceRoot":"","sources":["../../../src/core/util/atomic-file.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Shared atomic-file helper: a single lock+tmp+rename implementation reused by every\n * on-disk store that does a read-modify-write against a JSON/text file. Modeled on the pattern\n * already proven in `memory/providers/file-store.ts` (proper-lockfile advisory lock + write-tmp-\n * then-rename); before this helper existed the pattern was copy-pasted per store, and most copies\n * were missing either the lock, the atomic write, or both.\n *\n * Two call shapes:\n * - `withFileLock(Sync)` — hold an exclusive advisory lock across an arbitrary read-modify-write\n * callback. The lock spans BOTH the read and the write, closing the classic RMW race where two\n * writers each read the old content before either writes back.\n * - `writeFileAtomic(Sync)` — write-tmp-then-rename. Used INSIDE a `withFileLock` callback (or\n * standalone, for a pure overwrite that has no read step to race).\n *\n * Sync and async variants are both exported. Most existing stores expose a synchronous public API\n * called from hot, non-async paths (e.g. a per-token-stream perf sample), so the sync variant lets\n * them gain locking without forcing an async ripple through their callers; the async variant is for\n * call sites that are already async.\n */\n\nimport { randomUUID } from \"node:crypto\";\nimport { promises as fsPromises, mkdirSync, unlinkSync } from \"node:fs\";\nimport { dirname, resolve } from \"node:path\";\nimport lockfile from \"proper-lockfile\";\nimport { type FaultableFs, nodeFs } from \"./faultable-fs.ts\";\n\n/**\n * Bounded rename retry budget for the win32-only transient-rename handling below (see\n * {@link isTransientRenameErrorOnWin32}). Backoff doubles each attempt starting at\n * {@link RENAME_RETRY_MIN_TIMEOUT_MS} and capped at {@link RENAME_RETRY_MAX_TIMEOUT_MS}, mirroring\n * the doubling-backoff shape used for lock acquisition above. With {@link RENAME_RETRY_ATTEMPTS}\n * extra attempts (10, 20, 40, 80, ... capped at 200) the worst-case total wait is ~1.03s\n * (10+20+40+80+160+200+200+200+200 ~= 1110ms across 9 gaps), which comfortably covers the\n * millisecond-scale window Defender/the Windows Search indexer hold a freshly-written file open\n * without FILE_SHARE_DELETE before releasing it.\n */\nconst RENAME_RETRY_ATTEMPTS = 9;\nconst RENAME_RETRY_MIN_TIMEOUT_MS = 10;\nconst RENAME_RETRY_MAX_TIMEOUT_MS = 200;\n\n/**\n * On win32, antivirus (e.g. Windows Defender's real-time scanner) and the Windows Search indexer\n * routinely open a freshly-written file for a brief scan without `FILE_SHARE_DELETE`, which makes a\n * rename over/of that file fail transiently with EPERM/EACCES/EBUSY for a few milliseconds. This is\n * a well-documented platform semantic, not a bug in our write path — it's exactly why the\n * `graceful-fs` package ships its own win32 rename-retry wrapper. POSIX platforms never exhibit this\n * transient (a POSIX rename either succeeds or fails for a real, non-transient reason), so retry is\n * gated strictly to win32 to keep POSIX behavior byte-identical to a bare rename.\n */\nfunction isTransientRenameErrorOnWin32(err: unknown): boolean {\n\tif (process.platform !== \"win32\") return false;\n\tif (typeof err !== \"object\" || err === null) return false;\n\tconst code = (err as { code?: string }).code;\n\treturn code === \"EPERM\" || code === \"EACCES\" || code === \"EBUSY\";\n}\n\n/** Sync counterpart of the rename-retry policy; see {@link isTransientRenameErrorOnWin32}. */\nfunction renameSyncWithRetry(tmpPath: string, filePath: string, fs: FaultableFs): void {\n\tfor (let attempt = 0; attempt <= RENAME_RETRY_ATTEMPTS; attempt++) {\n\t\ttry {\n\t\t\tfs.renameSync(tmpPath, filePath);\n\t\t\treturn;\n\t\t} catch (err) {\n\t\t\tif (!isTransientRenameErrorOnWin32(err) || attempt === RENAME_RETRY_ATTEMPTS) throw err;\n\t\t\tconst backoffMs = Math.min(RENAME_RETRY_MIN_TIMEOUT_MS * 2 ** attempt, RENAME_RETRY_MAX_TIMEOUT_MS);\n\t\t\tblockingSleepMs(backoffMs);\n\t\t}\n\t}\n}\n\n/** Async counterpart of the rename-retry policy; see {@link isTransientRenameErrorOnWin32}. */\nasync function renameWithRetry(tmpPath: string, filePath: string): Promise<void> {\n\tfor (let attempt = 0; attempt <= RENAME_RETRY_ATTEMPTS; attempt++) {\n\t\ttry {\n\t\t\tawait fsPromises.rename(tmpPath, filePath);\n\t\t\treturn;\n\t\t} catch (err) {\n\t\t\tif (!isTransientRenameErrorOnWin32(err) || attempt === RENAME_RETRY_ATTEMPTS) throw err;\n\t\t\tconst backoffMs = Math.min(RENAME_RETRY_MIN_TIMEOUT_MS * 2 ** attempt, RENAME_RETRY_MAX_TIMEOUT_MS);\n\t\t\tawait new Promise((resolve) => setTimeout(resolve, backoffMs));\n\t\t}\n\t}\n}\n\nexport interface AtomicFileLockOptions {\n\t/**\n\t * Bounded retry attempts while waiting for a lock already held elsewhere. Both variants use a\n\t * SHORT, capped backoff (see {@link RETRY_MIN_TIMEOUT_MS}/{@link RETRY_MAX_TIMEOUT_MS}) — these\n\t * stores' critical sections are sub-millisecond reads+writes of small JSON/text files, so\n\t * contention should clear in milliseconds, not the multi-second-to-31-second worst case\n\t * proper-lockfile's OWN default backoff produces for a bare numeric `retries` (its default\n\t * `minTimeout` is 1000ms with factor 2 — see node_modules/retry/lib/retry.js). Passing a bare\n\t * number straight through would turn brief contention into a multi-second stall on a hot path\n\t * (e.g. a per-token-stream perf sample), so both variants instead build an explicit short-backoff\n\t * `retry` options object.\n\t * - Async (`withFileLock`): forwarded as `{retries, minTimeout, maxTimeout}` to proper-lockfile.\n\t * - Sync (`withFileLockSync`): proper-lockfile's sync API REJECTS `retries > 0` outright (it\n\t * requires the whole acquire flow to be synchronous — see proper-lockfile/lib/adapter.js\n\t * `toSyncOptions`, which throws `ESYNC`). So the sync path implements its own bounded retry\n\t * around single `lockfile.lockSync` attempts, blocking briefly between them (Atomics.wait) —\n\t * callers are already fully synchronous fs code, so a short blocking wait on contention matches\n\t * the existing execution model rather than introducing a new one.\n\t */\n\tretries?: number;\n\t/** Initial delay between sync/async acquisition attempts; defaults to 25ms. */\n\tminRetryDelayMs?: number;\n\t/** Maximum delay between sync/async acquisition attempts; defaults to 500ms. */\n\tmaxRetryDelayMs?: number;\n\t/** Retry-delay multiplier; defaults to 2. Set max=min for a fixed delay. */\n\tretryFactor?: number;\n\t/** Resolve symlinks before locking (proper-lockfile `realpath`); false matches file-store.ts. */\n\trealpath?: boolean;\n\t/** Lock staleness window in ms (proper-lockfile `stale`); omitted = proper-lockfile's own default. */\n\tstale?: number;\n\t/** Explicit proper-lockfile directory path; defaults to `${filePath}.lock`. */\n\tlockfilePath?: string;\n}\n\nexport interface AtomicFileWriteOptions {\n\t/** POSIX permission bits applied to the temporary file and inherited by the renamed destination. */\n\tmode?: number;\n\t/**\n\t * Injection seam for the mutating fs primitives this write issues (`mkdirSync`, `writeFileSync`,\n\t * `renameSync`). Defaults to real `node:fs` — omitting this option is a zero-behavior-change no-op.\n\t * Only the destructive-testing harness passes a fault-injecting implementation.\n\t */\n\tfs?: FaultableFs;\n}\n\nconst DEFAULT_RETRIES = 10;\nconst DEFAULT_REALPATH = false;\n/**\n * Capped doubling backoff shared by both variants — see {@link AtomicFileLockOptions.retries}.\n * With the current defaults (10 retries, 25ms floor, 500ms cap) the total worst-case contention\n * budget is ~3.3s (25+50+100+200+400+500+500+500+500+500), comfortably over the >= 2s floor this\n * needs to survive a loaded CI runner (e.g. the Windows CI mkdir/rmdir lock-directory churn under\n * two-real-OS-thread contention).\n */\nconst RETRY_MIN_TIMEOUT_MS = 25;\nconst RETRY_MAX_TIMEOUT_MS = 500;\n\n/**\n * Existing auth/settings/trust paths historically used 10 total attempts separated by 20ms. Keep\n * that low-latency user-facing policy explicit while routing the mechanism through this module.\n */\nexport const LOW_LATENCY_FILE_LOCK_OPTIONS: Readonly<AtomicFileLockOptions> = Object.freeze({\n\tretries: 9,\n\tminRetryDelayMs: 20,\n\tmaxRetryDelayMs: 20,\n});\n\nfunction lockDirectory(filePath: string, lockfilePath?: string): string {\n\treturn dirname(lockfilePath ?? filePath);\n}\n\nfunction ensureLockDirSync(filePath: string, lockfilePath?: string): void {\n\tmkdirSync(lockDirectory(filePath, lockfilePath), { recursive: true });\n}\n\nasync function ensureLockDir(filePath: string, lockfilePath?: string): Promise<void> {\n\tawait fsPromises.mkdir(lockDirectory(filePath, lockfilePath), { recursive: true });\n}\n\nfunction isLockedError(err: unknown): boolean {\n\tif (typeof err !== \"object\" || err === null) return false;\n\tconst code = (err as { code?: string }).code;\n\tif (code === \"ELOCKED\") return true;\n\t// On win32, mkdir-ing the lock directory can transiently surface EPERM (rather than the\n\t// expected EEXIST) when a previous incarnation of that directory is concurrently being\n\t// rmdir'd by the racing releaser — the mkdir lands mid-teardown and the OS reports \"operation\n\t// not permitted\" instead of \"already exists\". This is contention, not a real permissions\n\t// failure, so treat it identically to ELOCKED: retry with the existing backoff rather than\n\t// letting it escape as fatal. POSIX platforms don't exhibit this transient and keep surfacing\n\t// real EPERM (e.g. an actually unwritable directory) as fatal.\n\tif (code === \"EPERM\" && process.platform === \"win32\") return true;\n\treturn false;\n}\n\n/** Block the calling thread for `ms` without spinning the CPU (Atomics.wait on a private buffer). */\nfunction blockingSleepMs(ms: number): void {\n\tAtomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, ms);\n}\n\ntype PendingPathOperations = Map<string, Promise<void>>;\n\nconst pendingAsyncFileLockTails: PendingPathOperations = new Map();\nconst pendingAtomicWriteTails: PendingPathOperations = new Map();\n\nfunction pathOperationKey(filePath: string): string {\n\tconst absolutePath = resolve(filePath);\n\treturn process.platform === \"win32\" ? absolutePath.toLowerCase() : absolutePath;\n}\n\n/**\n * Queue only operations that target the same platform path. This prevents same-process callers\n * from entering synchronized OS retry storms without imposing a process-wide or cross-tenant\n * bottleneck. The tail always resolves and self-removes, including after a failed operation.\n */\nasync function withSerializedPathOperation<T>(\n\ttails: PendingPathOperations,\n\tfilePath: string,\n\tfn: () => Promise<T>,\n): Promise<T> {\n\tconst key = pathOperationKey(filePath);\n\tconst preceding = tails.get(key) ?? Promise.resolve();\n\tlet releaseTail: (() => void) | undefined;\n\tconst tail = new Promise<void>((resolveTail) => {\n\t\treleaseTail = resolveTail;\n\t});\n\ttails.set(key, tail);\n\n\tawait preceding;\n\ttry {\n\t\treturn await fn();\n\t} finally {\n\t\treleaseTail?.();\n\t\tif (tails.get(key) === tail) tails.delete(key);\n\t}\n}\n\n/**\n * Acquire a proper-lockfile sync lock with bounded retry on `ELOCKED` (proper-lockfile's sync API\n * itself forbids `retries > 0`; see {@link AtomicFileLockOptions.retries}).\n *\n * Backoff doubles each attempt (mirroring the `retry` module's own `factor: 2` default that the\n * async path gets for free from proper-lockfile), starting at {@link RETRY_MIN_TIMEOUT_MS} and\n * capped at {@link RETRY_MAX_TIMEOUT_MS}.\n *\n * This is budget PARITY between two implementations of the same lock-acquisition contract, not\n * flake-masking: `options.retries` (a count of RETRIES, i.e. attempts after the first) means the\n * same thing on both paths, so both must make `retries + 1` total acquisition attempts with the\n * same per-gap backoff schedule. The async path gets `retries + 1` attempts for free from the\n * `retry` module (it retries `options.retries` times after its initial attempt); the sync path\n * used to loop exactly `attempts` times total (one fewer gap, and one fewer attempt than the\n * async path for the same `retries` value), which under-budgeted it relative to its async sibling\n * and surfaced as spurious ELOCKED failures under real contention (e.g. two OS threads hammering\n * the same file, or mkdir/rmdir lock-directory churn on a loaded Windows CI runner).\n */\nfunction retryCount(options: AtomicFileLockOptions): number {\n\tconst configured = options.retries ?? DEFAULT_RETRIES;\n\treturn Number.isFinite(configured) ? Math.max(0, Math.floor(configured)) : DEFAULT_RETRIES;\n}\n\nfunction retryDelayMs(options: AtomicFileLockOptions, attempt: number): number {\n\tconst configuredMin = options.minRetryDelayMs ?? RETRY_MIN_TIMEOUT_MS;\n\tconst minDelay = Number.isFinite(configuredMin) ? Math.max(0, configuredMin) : RETRY_MIN_TIMEOUT_MS;\n\tconst configuredMax = options.maxRetryDelayMs ?? RETRY_MAX_TIMEOUT_MS;\n\tconst maxDelay = Number.isFinite(configuredMax) ? Math.max(minDelay, configuredMax) : RETRY_MAX_TIMEOUT_MS;\n\tconst configuredFactor = options.retryFactor ?? 2;\n\tconst factor = Number.isFinite(configuredFactor) ? Math.max(1, configuredFactor) : 2;\n\treturn Math.min(minDelay * factor ** (attempt - 1), maxDelay);\n}\n\n/**\n * Acquire a synchronous advisory file lock and return its release function. This is the shared\n * mechanism for coordinators that must hold several locks in a deterministic order before entering\n * one critical section; callers retain ownership of release ordering and release-error semantics.\n */\nexport function acquireFileLockSync(filePath: string, options: AtomicFileLockOptions = {}): () => void {\n\tensureLockDirSync(filePath, options.lockfilePath);\n\tconst attempts = retryCount(options) + 1;\n\tconst lockOptions = {\n\t\tlockfilePath: options.lockfilePath,\n\t\trealpath: options.realpath ?? DEFAULT_REALPATH,\n\t\tstale: options.stale,\n\t};\n\tfor (let attempt = 1; attempt <= attempts; attempt++) {\n\t\ttry {\n\t\t\treturn lockfile.lockSync(filePath, lockOptions);\n\t\t} catch (err) {\n\t\t\tif (!isLockedError(err) || attempt === attempts) throw err;\n\t\t\tblockingSleepMs(retryDelayMs(options, attempt));\n\t\t}\n\t}\n\t// Unreachable (the loop always returns or throws), but keeps the function's return type honest.\n\tthrow new Error(`Failed to acquire lock for ${filePath}`);\n}\n\n/**\n * Hold an exclusive advisory lock on `filePath` for the duration of `fn` (sync). Always releases,\n * including when `fn` throws.\n */\nexport function withFileLockSync<T>(filePath: string, fn: () => T, options?: AtomicFileLockOptions): T {\n\tconst release = acquireFileLockSync(filePath, options);\n\ttry {\n\t\treturn fn();\n\t} finally {\n\t\t// A lock-cleanup failure must never mask fn()'s result (or replace fn()'s own thrown error) —\n\t\t// by this point fn() has already durably committed or failed on its own terms.\n\t\ttry {\n\t\t\trelease();\n\t\t} catch {\n\t\t\t// best-effort cleanup; a stale lock self-expires via proper-lockfile's `stale` window\n\t\t}\n\t}\n}\n\n/** Async counterpart of {@link withFileLockSync}. Always releases, including when `fn` throws/rejects. */\nexport async function withFileLock<T>(\n\tfilePath: string,\n\tfn: () => Promise<T> | T,\n\toptions?: AtomicFileLockOptions,\n): Promise<T> {\n\treturn withSerializedPathOperation(pendingAsyncFileLockTails, options?.lockfilePath ?? filePath, async () => {\n\t\tawait ensureLockDir(filePath, options?.lockfilePath);\n\t\tconst release = await lockfile.lock(filePath, {\n\t\t\tlockfilePath: options?.lockfilePath,\n\t\t\trealpath: options?.realpath ?? DEFAULT_REALPATH,\n\t\t\tretries: {\n\t\t\t\tretries: retryCount(options ?? {}),\n\t\t\t\tfactor: options?.retryFactor ?? 2,\n\t\t\t\tminTimeout: options?.minRetryDelayMs ?? RETRY_MIN_TIMEOUT_MS,\n\t\t\t\tmaxTimeout: options?.maxRetryDelayMs ?? RETRY_MAX_TIMEOUT_MS,\n\t\t\t},\n\t\t\tstale: options?.stale,\n\t\t});\n\t\ttry {\n\t\t\treturn await fn();\n\t\t} finally {\n\t\t\t// See {@link withFileLockSync} — cleanup failures must not mask fn()'s outcome.\n\t\t\tawait release().catch(() => {});\n\t\t}\n\t});\n}\n\n/**\n * Write `content` to `filePath` via write-tmp-then-rename (sync); the rename is atomic on the same\n * filesystem, so a concurrent reader never observes a partially-written file. Does NOT itself lock —\n * call from inside {@link withFileLockSync} when the write follows a read that must not race another\n * writer's read+write; call standalone for an unconditional overwrite with no read step.\n */\nfunction temporaryPath(filePath: string): string {\n\treturn `${filePath}.${process.pid}.${randomUUID()}.tmp`;\n}\n\n/**\n * Async standalone overwrites can legitimately target the same file at once. Unique temporary\n * names prevent writers from corrupting each other's staging files, but Windows still serializes\n * replacement renames internally. Letting every writer retry in lockstep creates a thundering herd\n * that can exhaust the bounded Defender/indexer retry budget even though no external process owns\n * the destination. Keep one FIFO tail per destination inside this process so each destination has\n * one writer at a time; writes to different destinations remain fully parallel. The tail is always\n * resolved and removed, including after a failed write, so one failure cannot poison later writes\n * or retain tenant paths indefinitely. File-lock queues are separate from atomic-write queues so a\n * write inside a held advisory lock never waits on itself.\n */\nasync function withSerializedAtomicWrite<T>(filePath: string, fn: () => Promise<T>): Promise<T> {\n\treturn withSerializedPathOperation(pendingAtomicWriteTails, filePath, fn);\n}\n\n/** Remove one invocation's temporary path without masking the original write/rename failure. */\nfunction removeTemporaryPathSync(tmpPath: string): void {\n\ttry {\n\t\tunlinkSync(tmpPath);\n\t} catch {\n\t\t// The rename may have consumed the path, or another failure may have prevented its creation.\n\t}\n}\n\nasync function removeTemporaryPath(tmpPath: string): Promise<void> {\n\ttry {\n\t\tawait fsPromises.unlink(tmpPath);\n\t} catch {\n\t\t// The rename may have consumed the path, or another failure may have prevented its creation.\n\t}\n}\n\nexport function writeFileAtomicSync(filePath: string, content: string, options?: AtomicFileWriteOptions): void {\n\tconst fs = options?.fs ?? nodeFs;\n\tfs.mkdirSync(dirname(filePath), { recursive: true });\n\tconst tmpPath = temporaryPath(filePath);\n\tlet renamed = false;\n\ttry {\n\t\t// `wx` makes a nonce collision harmless: never truncate another writer's temporary file.\n\t\tfs.writeFileSync(tmpPath, content, { encoding: \"utf-8\", flag: \"wx\", mode: options?.mode });\n\t\trenameSyncWithRetry(tmpPath, filePath, fs);\n\t\trenamed = true;\n\t} finally {\n\t\tif (!renamed) removeTemporaryPathSync(tmpPath);\n\t}\n}\n\n/** Async counterpart of {@link writeFileAtomicSync}. */\nexport async function writeFileAtomic(\n\tfilePath: string,\n\tcontent: string,\n\toptions?: AtomicFileWriteOptions,\n): Promise<void> {\n\tawait withSerializedAtomicWrite(filePath, async () => {\n\t\tawait fsPromises.mkdir(dirname(filePath), { recursive: true });\n\t\tconst tmpPath = temporaryPath(filePath);\n\t\tlet renamed = false;\n\t\ttry {\n\t\t\t// `wx` makes a nonce collision harmless: never truncate another writer's temporary file.\n\t\t\tawait fsPromises.writeFile(tmpPath, content, { encoding: \"utf-8\", flag: \"wx\", mode: options?.mode });\n\t\t\tawait renameWithRetry(tmpPath, filePath);\n\t\t\trenamed = true;\n\t\t} finally {\n\t\t\tif (!renamed) await removeTemporaryPath(tmpPath);\n\t\t}\n\t});\n}\n"]}
1
+ {"version":3,"file":"atomic-file.js","sourceRoot":"","sources":["../../../src/core/util/atomic-file.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Shared atomic-file helper: a single lock+tmp+rename implementation reused by every\n * on-disk store that does a read-modify-write against a JSON/text file. Modeled on the pattern\n * already proven in `memory/providers/file-store.ts` (proper-lockfile advisory lock + write-tmp-\n * then-rename); before this helper existed the pattern was copy-pasted per store, and most copies\n * were missing either the lock, the atomic write, or both.\n *\n * Two call shapes:\n * - `withFileLock(Sync)` — hold an exclusive advisory lock across an arbitrary read-modify-write\n * callback. The lock spans BOTH the read and the write, closing the classic RMW race where two\n * writers each read the old content before either writes back.\n * - `writeFileAtomic(Sync)` — write-tmp-then-rename. Used INSIDE a `withFileLock` callback (or\n * standalone, for a pure overwrite that has no read step to race).\n *\n * Sync and async variants are both exported. Most existing stores expose a synchronous public API\n * called from hot, non-async paths (e.g. a per-token-stream perf sample), so the sync variant lets\n * them gain locking without forcing an async ripple through their callers; the async variant is for\n * call sites that are already async.\n */\n\nimport { randomUUID } from \"node:crypto\";\nimport { promises as fsPromises, mkdirSync, unlinkSync } from \"node:fs\";\nimport { dirname, resolve } from \"node:path\";\nimport lockfile from \"proper-lockfile\";\nimport { type FaultableFs, nodeFs } from \"./faultable-fs.ts\";\n\n/**\n * Bounded rename retry budget for the win32-only transient-rename handling below (see\n * {@link isTransientRenameErrorOnWin32}). Backoff doubles each attempt starting at\n * {@link RENAME_RETRY_MIN_TIMEOUT_MS} and capped at {@link RENAME_RETRY_MAX_TIMEOUT_MS}, mirroring\n * the doubling-backoff shape used for lock acquisition above. With {@link RENAME_RETRY_ATTEMPTS}\n * extra attempts (10, 20, 40, 80, ... capped at 200) the worst-case total wait is ~1.03s\n * (10+20+40+80+160+200+200+200+200 ~= 1110ms across 9 gaps), which comfortably covers the\n * millisecond-scale window Defender/the Windows Search indexer hold a freshly-written file open\n * without FILE_SHARE_DELETE before releasing it.\n */\nconst RENAME_RETRY_ATTEMPTS = 9;\nconst RENAME_RETRY_MIN_TIMEOUT_MS = 10;\nconst RENAME_RETRY_MAX_TIMEOUT_MS = 200;\n\n/**\n * On win32, antivirus (e.g. Windows Defender's real-time scanner) and the Windows Search indexer\n * routinely open a freshly-written file for a brief scan without `FILE_SHARE_DELETE`, which makes a\n * rename over/of that file fail transiently with EPERM/EACCES/EBUSY for a few milliseconds. This is\n * a well-documented platform semantic, not a bug in our write path — it's exactly why the\n * `graceful-fs` package ships its own win32 rename-retry wrapper. POSIX platforms never exhibit this\n * transient (a POSIX rename either succeeds or fails for a real, non-transient reason), so retry is\n * gated strictly to win32 to keep POSIX behavior byte-identical to a bare rename.\n */\nfunction isTransientRenameErrorOnWin32(err: unknown): boolean {\n\tif (process.platform !== \"win32\") return false;\n\tif (typeof err !== \"object\" || err === null) return false;\n\tconst code = (err as { code?: string }).code;\n\treturn code === \"EPERM\" || code === \"EACCES\" || code === \"EBUSY\";\n}\n\n/** Sync counterpart of the rename-retry policy; see {@link isTransientRenameErrorOnWin32}. */\nfunction renameSyncWithRetry(tmpPath: string, filePath: string, fs: FaultableFs): void {\n\tfor (let attempt = 0; attempt <= RENAME_RETRY_ATTEMPTS; attempt++) {\n\t\ttry {\n\t\t\tfs.renameSync(tmpPath, filePath);\n\t\t\treturn;\n\t\t} catch (err) {\n\t\t\tif (!isTransientRenameErrorOnWin32(err) || attempt === RENAME_RETRY_ATTEMPTS) throw err;\n\t\t\tconst backoffMs = Math.min(RENAME_RETRY_MIN_TIMEOUT_MS * 2 ** attempt, RENAME_RETRY_MAX_TIMEOUT_MS);\n\t\t\tblockingSleepMs(backoffMs);\n\t\t}\n\t}\n}\n\n/** Async counterpart of the rename-retry policy; see {@link isTransientRenameErrorOnWin32}. */\nasync function renameWithRetry(tmpPath: string, filePath: string): Promise<void> {\n\tfor (let attempt = 0; attempt <= RENAME_RETRY_ATTEMPTS; attempt++) {\n\t\ttry {\n\t\t\tawait fsPromises.rename(tmpPath, filePath);\n\t\t\treturn;\n\t\t} catch (err) {\n\t\t\tif (!isTransientRenameErrorOnWin32(err) || attempt === RENAME_RETRY_ATTEMPTS) throw err;\n\t\t\tconst backoffMs = Math.min(RENAME_RETRY_MIN_TIMEOUT_MS * 2 ** attempt, RENAME_RETRY_MAX_TIMEOUT_MS);\n\t\t\tawait new Promise((resolve) => setTimeout(resolve, backoffMs));\n\t\t}\n\t}\n}\n\nexport interface AtomicFileLockOptions {\n\t/**\n\t * Bounded retry attempts while waiting for a lock already held elsewhere. Both variants use a\n\t * SHORT, capped backoff (see {@link RETRY_MIN_TIMEOUT_MS}/{@link RETRY_MAX_TIMEOUT_MS}) — these\n\t * stores' critical sections are sub-millisecond reads+writes of small JSON/text files, so\n\t * contention should clear in milliseconds, not the multi-second-to-31-second worst case\n\t * proper-lockfile's OWN default backoff produces for a bare numeric `retries` (its default\n\t * `minTimeout` is 1000ms with factor 2 — see node_modules/retry/lib/retry.js). Passing a bare\n\t * number straight through would turn brief contention into a multi-second stall on a hot path\n\t * (e.g. a per-token-stream perf sample), so both variants instead build an explicit short-backoff\n\t * `retry` options object.\n\t * - Async (`withFileLock`): forwarded as `{retries, minTimeout, maxTimeout}` to proper-lockfile.\n\t * - Sync (`withFileLockSync`): proper-lockfile's sync API REJECTS `retries > 0` outright (it\n\t * requires the whole acquire flow to be synchronous — see proper-lockfile/lib/adapter.js\n\t * `toSyncOptions`, which throws `ESYNC`). So the sync path implements its own bounded retry\n\t * around single `lockfile.lockSync` attempts, blocking briefly between them (Atomics.wait) —\n\t * callers are already fully synchronous fs code, so a short blocking wait on contention matches\n\t * the existing execution model rather than introducing a new one.\n\t */\n\tretries?: number;\n\t/** Initial delay between sync/async acquisition attempts; defaults to 25ms. */\n\tminRetryDelayMs?: number;\n\t/** Maximum delay between sync/async acquisition attempts; defaults to 500ms. */\n\tmaxRetryDelayMs?: number;\n\t/** Retry-delay multiplier; defaults to 2. Set max=min for a fixed delay. */\n\tretryFactor?: number;\n\t/** Resolve symlinks before locking (proper-lockfile `realpath`); false matches file-store.ts. */\n\trealpath?: boolean;\n\t/** Lock staleness window in ms (proper-lockfile `stale`); omitted = proper-lockfile's own default. */\n\tstale?: number;\n\t/** Explicit proper-lockfile directory path; defaults to `${filePath}.lock`. */\n\tlockfilePath?: string;\n}\n\nexport interface AtomicFileWriteOptions {\n\t/** POSIX permission bits applied to the temporary file and inherited by the renamed destination. */\n\tmode?: number;\n\t/**\n\t * Injection seam for the mutating fs primitives this write issues (`mkdirSync`, `writeFileSync`,\n\t * `renameSync`). Defaults to real `node:fs` — omitting this option is a zero-behavior-change no-op.\n\t * Only the destructive-testing harness passes a fault-injecting implementation.\n\t */\n\tfs?: FaultableFs;\n}\n\n/** Narrow an unknown Node filesystem failure without unsafe casts at every storage owner. */\nexport function isMissingFileError(error: unknown): boolean {\n\treturn typeof error === \"object\" && error !== null && \"code\" in error && error.code === \"ENOENT\";\n}\n\nconst DEFAULT_RETRIES = 10;\nconst DEFAULT_REALPATH = false;\n/**\n * Capped doubling backoff shared by both variants — see {@link AtomicFileLockOptions.retries}.\n * With the current defaults (10 retries, 25ms floor, 500ms cap) the total worst-case contention\n * budget is ~3.3s (25+50+100+200+400+500+500+500+500+500), comfortably over the >= 2s floor this\n * needs to survive a loaded CI runner (e.g. the Windows CI mkdir/rmdir lock-directory churn under\n * two-real-OS-thread contention).\n */\nconst RETRY_MIN_TIMEOUT_MS = 25;\nconst RETRY_MAX_TIMEOUT_MS = 500;\n\n/**\n * Existing auth/settings/trust paths historically used 10 total attempts separated by 20ms. Keep\n * that low-latency user-facing policy explicit while routing the mechanism through this module.\n */\nexport const LOW_LATENCY_FILE_LOCK_OPTIONS: Readonly<AtomicFileLockOptions> = Object.freeze({\n\tretries: 9,\n\tminRetryDelayMs: 20,\n\tmaxRetryDelayMs: 20,\n});\n\nfunction lockDirectory(filePath: string, lockfilePath?: string): string {\n\treturn dirname(lockfilePath ?? filePath);\n}\n\nfunction ensureLockDirSync(filePath: string, lockfilePath?: string): void {\n\tmkdirSync(lockDirectory(filePath, lockfilePath), { recursive: true });\n}\n\nasync function ensureLockDir(filePath: string, lockfilePath?: string): Promise<void> {\n\tawait fsPromises.mkdir(lockDirectory(filePath, lockfilePath), { recursive: true });\n}\n\nfunction isLockedError(err: unknown): boolean {\n\tif (typeof err !== \"object\" || err === null) return false;\n\tconst code = (err as { code?: string }).code;\n\tif (code === \"ELOCKED\") return true;\n\t// On win32, mkdir-ing the lock directory can transiently surface EPERM (rather than the\n\t// expected EEXIST) when a previous incarnation of that directory is concurrently being\n\t// rmdir'd by the racing releaser — the mkdir lands mid-teardown and the OS reports \"operation\n\t// not permitted\" instead of \"already exists\". This is contention, not a real permissions\n\t// failure, so treat it identically to ELOCKED: retry with the existing backoff rather than\n\t// letting it escape as fatal. POSIX platforms don't exhibit this transient and keep surfacing\n\t// real EPERM (e.g. an actually unwritable directory) as fatal.\n\tif (code === \"EPERM\" && process.platform === \"win32\") return true;\n\treturn false;\n}\n\n/** Block the calling thread for `ms` without spinning the CPU (Atomics.wait on a private buffer). */\nfunction blockingSleepMs(ms: number): void {\n\tAtomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, ms);\n}\n\ntype PendingPathOperations = Map<string, Promise<void>>;\n\nconst pendingAsyncFileLockTails: PendingPathOperations = new Map();\nconst pendingAtomicWriteTails: PendingPathOperations = new Map();\n\nfunction pathOperationKey(filePath: string): string {\n\tconst absolutePath = resolve(filePath);\n\treturn process.platform === \"win32\" ? absolutePath.toLowerCase() : absolutePath;\n}\n\n/**\n * Queue only operations that target the same platform path. This prevents same-process callers\n * from entering synchronized OS retry storms without imposing a process-wide or cross-tenant\n * bottleneck. The tail always resolves and self-removes, including after a failed operation.\n */\nasync function withSerializedPathOperation<T>(\n\ttails: PendingPathOperations,\n\tfilePath: string,\n\tfn: () => Promise<T>,\n): Promise<T> {\n\tconst key = pathOperationKey(filePath);\n\tconst preceding = tails.get(key) ?? Promise.resolve();\n\tlet releaseTail: (() => void) | undefined;\n\tconst tail = new Promise<void>((resolveTail) => {\n\t\treleaseTail = resolveTail;\n\t});\n\ttails.set(key, tail);\n\n\tawait preceding;\n\ttry {\n\t\treturn await fn();\n\t} finally {\n\t\treleaseTail?.();\n\t\tif (tails.get(key) === tail) tails.delete(key);\n\t}\n}\n\n/**\n * Acquire a proper-lockfile sync lock with bounded retry on `ELOCKED` (proper-lockfile's sync API\n * itself forbids `retries > 0`; see {@link AtomicFileLockOptions.retries}).\n *\n * Backoff doubles each attempt (mirroring the `retry` module's own `factor: 2` default that the\n * async path gets for free from proper-lockfile), starting at {@link RETRY_MIN_TIMEOUT_MS} and\n * capped at {@link RETRY_MAX_TIMEOUT_MS}.\n *\n * This is budget PARITY between two implementations of the same lock-acquisition contract, not\n * flake-masking: `options.retries` (a count of RETRIES, i.e. attempts after the first) means the\n * same thing on both paths, so both must make `retries + 1` total acquisition attempts with the\n * same per-gap backoff schedule. The async path gets `retries + 1` attempts for free from the\n * `retry` module (it retries `options.retries` times after its initial attempt); the sync path\n * used to loop exactly `attempts` times total (one fewer gap, and one fewer attempt than the\n * async path for the same `retries` value), which under-budgeted it relative to its async sibling\n * and surfaced as spurious ELOCKED failures under real contention (e.g. two OS threads hammering\n * the same file, or mkdir/rmdir lock-directory churn on a loaded Windows CI runner).\n */\nfunction retryCount(options: AtomicFileLockOptions): number {\n\tconst configured = options.retries ?? DEFAULT_RETRIES;\n\treturn Number.isFinite(configured) ? Math.max(0, Math.floor(configured)) : DEFAULT_RETRIES;\n}\n\nfunction retryDelayMs(options: AtomicFileLockOptions, attempt: number): number {\n\tconst configuredMin = options.minRetryDelayMs ?? RETRY_MIN_TIMEOUT_MS;\n\tconst minDelay = Number.isFinite(configuredMin) ? Math.max(0, configuredMin) : RETRY_MIN_TIMEOUT_MS;\n\tconst configuredMax = options.maxRetryDelayMs ?? RETRY_MAX_TIMEOUT_MS;\n\tconst maxDelay = Number.isFinite(configuredMax) ? Math.max(minDelay, configuredMax) : RETRY_MAX_TIMEOUT_MS;\n\tconst configuredFactor = options.retryFactor ?? 2;\n\tconst factor = Number.isFinite(configuredFactor) ? Math.max(1, configuredFactor) : 2;\n\treturn Math.min(minDelay * factor ** (attempt - 1), maxDelay);\n}\n\n/**\n * Acquire a synchronous advisory file lock and return its release function. This is the shared\n * mechanism for coordinators that must hold several locks in a deterministic order before entering\n * one critical section; callers retain ownership of release ordering and release-error semantics.\n */\nexport function acquireFileLockSync(filePath: string, options: AtomicFileLockOptions = {}): () => void {\n\tensureLockDirSync(filePath, options.lockfilePath);\n\tconst attempts = retryCount(options) + 1;\n\tconst lockOptions = {\n\t\tlockfilePath: options.lockfilePath,\n\t\trealpath: options.realpath ?? DEFAULT_REALPATH,\n\t\tstale: options.stale,\n\t};\n\tfor (let attempt = 1; attempt <= attempts; attempt++) {\n\t\ttry {\n\t\t\treturn lockfile.lockSync(filePath, lockOptions);\n\t\t} catch (err) {\n\t\t\tif (!isLockedError(err) || attempt === attempts) throw err;\n\t\t\tblockingSleepMs(retryDelayMs(options, attempt));\n\t\t}\n\t}\n\t// Unreachable (the loop always returns or throws), but keeps the function's return type honest.\n\tthrow new Error(`Failed to acquire lock for ${filePath}`);\n}\n\n/**\n * Hold an exclusive advisory lock on `filePath` for the duration of `fn` (sync). Always releases,\n * including when `fn` throws.\n */\nexport function withFileLockSync<T>(filePath: string, fn: () => T, options?: AtomicFileLockOptions): T {\n\tconst release = acquireFileLockSync(filePath, options);\n\ttry {\n\t\treturn fn();\n\t} finally {\n\t\t// A lock-cleanup failure must never mask fn()'s result (or replace fn()'s own thrown error) —\n\t\t// by this point fn() has already durably committed or failed on its own terms.\n\t\ttry {\n\t\t\trelease();\n\t\t} catch {\n\t\t\t// best-effort cleanup; a stale lock self-expires via proper-lockfile's `stale` window\n\t\t}\n\t}\n}\n\n/** Async counterpart of {@link withFileLockSync}. Always releases, including when `fn` throws/rejects. */\nexport async function withFileLock<T>(\n\tfilePath: string,\n\tfn: () => Promise<T> | T,\n\toptions?: AtomicFileLockOptions,\n): Promise<T> {\n\treturn withSerializedPathOperation(pendingAsyncFileLockTails, options?.lockfilePath ?? filePath, async () => {\n\t\tawait ensureLockDir(filePath, options?.lockfilePath);\n\t\tconst release = await lockfile.lock(filePath, {\n\t\t\tlockfilePath: options?.lockfilePath,\n\t\t\trealpath: options?.realpath ?? DEFAULT_REALPATH,\n\t\t\tretries: {\n\t\t\t\tretries: retryCount(options ?? {}),\n\t\t\t\tfactor: options?.retryFactor ?? 2,\n\t\t\t\tminTimeout: options?.minRetryDelayMs ?? RETRY_MIN_TIMEOUT_MS,\n\t\t\t\tmaxTimeout: options?.maxRetryDelayMs ?? RETRY_MAX_TIMEOUT_MS,\n\t\t\t},\n\t\t\tstale: options?.stale,\n\t\t});\n\t\ttry {\n\t\t\treturn await fn();\n\t\t} finally {\n\t\t\t// See {@link withFileLockSync} — cleanup failures must not mask fn()'s outcome.\n\t\t\tawait release().catch(() => {});\n\t\t}\n\t});\n}\n\n/**\n * Write `content` to `filePath` via write-tmp-then-rename (sync); the rename is atomic on the same\n * filesystem, so a concurrent reader never observes a partially-written file. Does NOT itself lock —\n * call from inside {@link withFileLockSync} when the write follows a read that must not race another\n * writer's read+write; call standalone for an unconditional overwrite with no read step.\n */\nfunction temporaryPath(filePath: string): string {\n\treturn `${filePath}.${process.pid}.${randomUUID()}.tmp`;\n}\n\n/**\n * Async standalone overwrites can legitimately target the same file at once. Unique temporary\n * names prevent writers from corrupting each other's staging files, but Windows still serializes\n * replacement renames internally. Letting every writer retry in lockstep creates a thundering herd\n * that can exhaust the bounded Defender/indexer retry budget even though no external process owns\n * the destination. Keep one FIFO tail per destination inside this process so each destination has\n * one writer at a time; writes to different destinations remain fully parallel. The tail is always\n * resolved and removed, including after a failed write, so one failure cannot poison later writes\n * or retain tenant paths indefinitely. File-lock queues are separate from atomic-write queues so a\n * write inside a held advisory lock never waits on itself.\n */\nasync function withSerializedAtomicWrite<T>(filePath: string, fn: () => Promise<T>): Promise<T> {\n\treturn withSerializedPathOperation(pendingAtomicWriteTails, filePath, fn);\n}\n\n/** Remove one invocation's temporary path without masking the original write/rename failure. */\nfunction removeTemporaryPathSync(tmpPath: string): void {\n\ttry {\n\t\tunlinkSync(tmpPath);\n\t} catch {\n\t\t// The rename may have consumed the path, or another failure may have prevented its creation.\n\t}\n}\n\nasync function removeTemporaryPath(tmpPath: string): Promise<void> {\n\ttry {\n\t\tawait fsPromises.unlink(tmpPath);\n\t} catch {\n\t\t// The rename may have consumed the path, or another failure may have prevented its creation.\n\t}\n}\n\nexport function writeFileAtomicSync(filePath: string, content: string, options?: AtomicFileWriteOptions): void {\n\tconst fs = options?.fs ?? nodeFs;\n\tfs.mkdirSync(dirname(filePath), { recursive: true });\n\tconst tmpPath = temporaryPath(filePath);\n\tlet renamed = false;\n\ttry {\n\t\t// `wx` makes a nonce collision harmless: never truncate another writer's temporary file.\n\t\tfs.writeFileSync(tmpPath, content, { encoding: \"utf-8\", flag: \"wx\", mode: options?.mode });\n\t\trenameSyncWithRetry(tmpPath, filePath, fs);\n\t\trenamed = true;\n\t} finally {\n\t\tif (!renamed) removeTemporaryPathSync(tmpPath);\n\t}\n}\n\n/** Async counterpart of {@link writeFileAtomicSync}. */\nexport async function writeFileAtomic(\n\tfilePath: string,\n\tcontent: string,\n\toptions?: AtomicFileWriteOptions,\n): Promise<void> {\n\tawait withSerializedAtomicWrite(filePath, async () => {\n\t\tawait fsPromises.mkdir(dirname(filePath), { recursive: true });\n\t\tconst tmpPath = temporaryPath(filePath);\n\t\tlet renamed = false;\n\t\ttry {\n\t\t\t// `wx` makes a nonce collision harmless: never truncate another writer's temporary file.\n\t\t\tawait fsPromises.writeFile(tmpPath, content, { encoding: \"utf-8\", flag: \"wx\", mode: options?.mode });\n\t\t\tawait renameWithRetry(tmpPath, filePath);\n\t\t\trenamed = true;\n\t\t} finally {\n\t\t\tif (!renamed) await removeTemporaryPath(tmpPath);\n\t\t}\n\t});\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"auto-learn-controller.d.ts","sourceRoot":"","sources":["../../../src/modes/interactive/auto-learn-controller.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"auto-learn-controller.d.ts","sourceRoot":"","sources":["../../../src/modes/interactive/auto-learn-controller.ts"],"names":[],"mappings":"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"}
@@ -18,6 +18,7 @@ import { readAutoLearnSessionIdFromFile, reportCompletedAutoLearnUsageHelper } f
18
18
  import { analyzeReflectionTurn } from "../../core/learning/reflection-turn-analysis.js";
19
19
  import { isProcessAlive } from "../../core/process-liveness.js";
20
20
  import { describeInFlightWorkUnit, getInFlightWorkUnits, getPendingReloadBlockers, } from "../../core/reload-blockers.js";
21
+ import { PI_SESSION_ROLE_ENV } from "../../core/session-role.js";
21
22
  import { checkTaskStepsContract, INITIAL_TASK_CONTRACT_STREAK, } from "../../core/tasks/task-contract-monitor.js";
22
23
  import { getProcessWorkRun } from "../../utils/work-directory.js";
23
24
  import { theme } from "./theme/theme.js";
@@ -812,6 +813,7 @@ export class AutoLearnController {
812
813
  env: {
813
814
  ...process.env,
814
815
  PI_AUTO_LEARN_CHILD: "1",
816
+ [PI_SESSION_ROLE_ENV]: "worker",
815
817
  ...(sourceSessionFile ? { PI_AUTO_LEARN_SOURCE_SESSION_FILE: sourceSessionFile } : {}),
816
818
  },
817
819
  });