@bastani/atomic 0.9.19-alpha.5 → 0.9.19-alpha.7

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 (209) hide show
  1. package/CHANGELOG.md +32 -0
  2. package/README.md +2 -2
  3. package/dist/builtin/intercom/CHANGELOG.md +6 -0
  4. package/dist/builtin/intercom/broker/client.ts +19 -1
  5. package/dist/builtin/intercom/index.bundle.mjs +8 -1
  6. package/dist/builtin/intercom/package.json +1 -1
  7. package/dist/builtin/mcp/package.json +1 -1
  8. package/dist/builtin/subagents/CHANGELOG.md +6 -0
  9. package/dist/builtin/subagents/README.md +3 -1
  10. package/dist/builtin/subagents/agents/codebase-online-researcher.md +7 -7
  11. package/dist/builtin/subagents/package.json +1 -1
  12. package/dist/builtin/subagents/skills/subagent/SKILL.md +3 -1
  13. package/dist/builtin/subagents/src/extension/index.bundle.mjs +2 -1
  14. package/dist/builtin/web-access/CHANGELOG.md +13 -0
  15. package/dist/builtin/web-access/README.md +31 -24
  16. package/dist/builtin/web-access/index.bundle.mjs +16121 -80
  17. package/dist/builtin/web-access/package.json +2 -1
  18. package/dist/builtin/workflows/CHANGELOG.md +15 -0
  19. package/dist/builtin/workflows/README.md +1 -1
  20. package/dist/builtin/workflows/builtin/adversarial-verification.js +2 -2
  21. package/dist/builtin/workflows/builtin/{chunk-vhmnzdj9.js → chunk-1jth021m.js} +1 -1
  22. package/dist/builtin/workflows/builtin/{chunk-p8jjwfg6.js → chunk-2377r57g.js} +4 -2
  23. package/dist/builtin/workflows/builtin/{chunk-hbnwv56f.js → chunk-31j2gs7h.js} +2 -2
  24. package/dist/builtin/workflows/builtin/{chunk-n8zysf1t.js → chunk-ngkqkzej.js} +1 -1
  25. package/dist/builtin/workflows/builtin/{chunk-1nbq96fh.js → chunk-nkrafh9s.js} +1 -1
  26. package/dist/builtin/workflows/builtin/{chunk-1kx4aggw.js → chunk-wf741bv3.js} +2 -2
  27. package/dist/builtin/workflows/builtin/{chunk-t6x2d78s.js → chunk-z29qbehr.js} +1 -1
  28. package/dist/builtin/workflows/builtin/generate-and-filter.js +2 -2
  29. package/dist/builtin/workflows/builtin/goal.js +3 -3
  30. package/dist/builtin/workflows/builtin/index.js +7 -7
  31. package/dist/builtin/workflows/builtin/ralph.js +3 -3
  32. package/dist/builtin/workflows/builtin/tournament.js +2 -2
  33. package/dist/builtin/workflows/package.json +1 -1
  34. package/dist/builtin/workflows/src/extension/index.bundle.mjs +339 -31
  35. package/dist/builtin/workflows/src/index.js +67 -19
  36. package/dist/builtin/workflows/src/shared/authoring-contract-stage.d.ts +2 -0
  37. package/dist/core/agent-session-tool-registry.d.ts.map +1 -1
  38. package/dist/core/agent-session-tool-registry.js +10 -0
  39. package/dist/core/agent-session-tool-registry.js.map +1 -1
  40. package/dist/core/bash-executor.js.map +1 -1
  41. package/dist/core/tools/bash.d.ts +1 -1
  42. package/dist/core/tools/bash.d.ts.map +1 -1
  43. package/dist/core/tools/bash.js +3 -2
  44. package/dist/core/tools/bash.js.map +1 -1
  45. package/dist/core/tools/edit.d.ts +3 -0
  46. package/dist/core/tools/edit.d.ts.map +1 -1
  47. package/dist/core/tools/edit.js +91 -12
  48. package/dist/core/tools/edit.js.map +1 -1
  49. package/dist/core/tools/file-mutation-coordinator.d.ts +255 -0
  50. package/dist/core/tools/file-mutation-coordinator.d.ts.map +1 -0
  51. package/dist/core/tools/file-mutation-coordinator.js +300 -0
  52. package/dist/core/tools/file-mutation-coordinator.js.map +1 -0
  53. package/dist/core/tools/file-mutation-queue.d.ts +14 -1
  54. package/dist/core/tools/file-mutation-queue.d.ts.map +1 -1
  55. package/dist/core/tools/file-mutation-queue.js +15 -3
  56. package/dist/core/tools/file-mutation-queue.js.map +1 -1
  57. package/dist/core/tools/hashline.d.ts +9 -0
  58. package/dist/core/tools/hashline.d.ts.map +1 -1
  59. package/dist/core/tools/hashline.js +12 -1
  60. package/dist/core/tools/hashline.js.map +1 -1
  61. package/dist/core/tools/index.d.ts +9 -1
  62. package/dist/core/tools/index.d.ts.map +1 -1
  63. package/dist/core/tools/index.js +67 -12
  64. package/dist/core/tools/index.js.map +1 -1
  65. package/dist/core/tools/non-minting-snapshot-store.d.ts +49 -0
  66. package/dist/core/tools/non-minting-snapshot-store.d.ts.map +1 -0
  67. package/dist/core/tools/non-minting-snapshot-store.js +64 -0
  68. package/dist/core/tools/non-minting-snapshot-store.js.map +1 -0
  69. package/dist/core/tools/powershell.d.ts +2 -2
  70. package/dist/core/tools/powershell.d.ts.map +1 -1
  71. package/dist/core/tools/powershell.js +2 -5
  72. package/dist/core/tools/powershell.js.map +1 -1
  73. package/dist/core/tools/read-document-extract.js.map +1 -1
  74. package/dist/core/tools/render-utils.js.map +1 -1
  75. package/dist/core/tools/write.d.ts +30 -1
  76. package/dist/core/tools/write.d.ts.map +1 -1
  77. package/dist/core/tools/write.js +97 -8
  78. package/dist/core/tools/write.js.map +1 -1
  79. package/dist/index.d.ts +1 -1
  80. package/dist/index.d.ts.map +1 -1
  81. package/dist/index.js.map +1 -1
  82. package/dist/modes/interactive/components/bash-execution.js.map +1 -1
  83. package/dist/modes/interactive/components/task-live-transcript.d.ts +1 -1
  84. package/dist/modes/interactive/components/task-live-transcript.d.ts.map +1 -1
  85. package/dist/modes/interactive/components/task-live-transcript.js +19 -11
  86. package/dist/modes/interactive/components/task-live-transcript.js.map +1 -1
  87. package/dist/modes/interactive/interactive-mode-base.d.ts +1 -0
  88. package/dist/modes/interactive/interactive-mode-base.d.ts.map +1 -1
  89. package/dist/modes/interactive/interactive-mode-base.js +3 -1
  90. package/dist/modes/interactive/interactive-mode-base.js.map +1 -1
  91. package/dist/modes/interactive/interactive-mode-surface.d.ts +1 -1
  92. package/dist/modes/interactive/interactive-mode-surface.d.ts.map +1 -1
  93. package/dist/modes/interactive/interactive-mode-surface.js.map +1 -1
  94. package/dist/modes/interactive/interactive-render-chat.js +28 -4
  95. package/dist/modes/interactive/interactive-render-chat.js.map +1 -1
  96. package/dist/modes/interactive/interactive-startup.d.ts.map +1 -1
  97. package/dist/modes/interactive/interactive-startup.js +3 -0
  98. package/dist/modes/interactive/interactive-startup.js.map +1 -1
  99. package/dist/modes/interactive-engine/activity-watchdog.d.ts +2 -2
  100. package/dist/modes/interactive-engine/activity-watchdog.d.ts.map +1 -1
  101. package/dist/modes/interactive-engine/activity-watchdog.js.map +1 -1
  102. package/dist/modes/interactive-engine/engine-diagnostic-view.d.ts +3 -1
  103. package/dist/modes/interactive-engine/engine-diagnostic-view.d.ts.map +1 -1
  104. package/dist/modes/interactive-engine/engine-diagnostic-view.js +11 -0
  105. package/dist/modes/interactive-engine/engine-diagnostic-view.js.map +1 -1
  106. package/dist/modes/interactive-engine/isolated-runtime.js +2 -1
  107. package/dist/modes/interactive-engine/isolated-runtime.js.map +1 -1
  108. package/dist/modes/rpc/rpc-client-process.d.ts +2 -0
  109. package/dist/modes/rpc/rpc-client-process.d.ts.map +1 -1
  110. package/dist/modes/rpc/rpc-client-process.js +23 -1
  111. package/dist/modes/rpc/rpc-client-process.js.map +1 -1
  112. package/dist/modes/rpc/rpc-client.d.ts.map +1 -1
  113. package/dist/modes/rpc/rpc-client.js +20 -3
  114. package/dist/modes/rpc/rpc-client.js.map +1 -1
  115. package/dist/utils/markit.d.ts +2 -0
  116. package/dist/utils/markit.d.ts.map +1 -1
  117. package/dist/utils/markit.js +65 -5
  118. package/dist/utils/markit.js.map +1 -1
  119. package/docs/background-tasks.md +15 -11
  120. package/docs/build.md +51 -0
  121. package/docs/changelog.mdx +8 -8
  122. package/docs/compaction/reference.md +267 -0
  123. package/docs/compaction.md +36 -219
  124. package/docs/computer-use.md +35 -0
  125. package/docs/containerization.md +9 -5
  126. package/docs/custom-provider/api-reference.md +145 -0
  127. package/docs/custom-provider/oauth.md +131 -0
  128. package/docs/custom-provider/override.md +34 -0
  129. package/docs/custom-provider/registration.md +163 -0
  130. package/docs/custom-provider/streaming.md +214 -0
  131. package/docs/custom-provider.md +43 -607
  132. package/docs/development.md +87 -0
  133. package/docs/docs.json +199 -76
  134. package/docs/environment-variables.md +1 -1
  135. package/docs/extensions/api-reference.md +1001 -0
  136. package/docs/extensions/authoring.md +676 -0
  137. package/docs/extensions/events.md +793 -0
  138. package/docs/extensions/examples.md +94 -0
  139. package/docs/extensions/ui.md +470 -0
  140. package/docs/extensions.md +270 -2768
  141. package/docs/getting-started/authentication.md +55 -0
  142. package/docs/getting-started/first-session.md +172 -0
  143. package/docs/getting-started/installation.md +154 -0
  144. package/docs/getting-started/project-instructions.md +43 -0
  145. package/docs/guides/configuration.md +65 -0
  146. package/docs/guides/intercom.md +24 -0
  147. package/docs/guides/non-interactive.md +33 -0
  148. package/docs/guides/subagents.md +24 -0
  149. package/docs/guides/workflows.md +27 -0
  150. package/docs/guides.md +41 -0
  151. package/docs/index.md +13 -45
  152. package/docs/intercom/operations.md +178 -0
  153. package/docs/intercom/reference.md +146 -0
  154. package/docs/intercom.md +54 -259
  155. package/docs/json.md +17 -0
  156. package/docs/llama-cpp.md +5 -0
  157. package/docs/models/artificial-analysis-index.md +89 -0
  158. package/docs/models/evals.md +2 -2
  159. package/docs/models/model-selection.md +3 -3
  160. package/docs/models/pareto-efficiency.md +2 -2
  161. package/docs/models/reference.md +601 -0
  162. package/docs/models.md +45 -550
  163. package/docs/packages/authoring.md +88 -0
  164. package/docs/packages/reference.md +43 -0
  165. package/docs/packages.md +28 -107
  166. package/docs/programmatic.md +29 -0
  167. package/docs/prompt-templates.md +11 -0
  168. package/docs/providers/reference.md +23 -0
  169. package/docs/providers.md +10 -15
  170. package/docs/quickstart.md +44 -238
  171. package/docs/reference/cli.md +252 -0
  172. package/docs/reference.md +52 -0
  173. package/docs/rpc/examples.md +64 -0
  174. package/docs/rpc/extension-ui.md +198 -0
  175. package/docs/rpc/protocol.md +1341 -0
  176. package/docs/rpc.md +109 -1346
  177. package/docs/sdk/reference.md +1090 -0
  178. package/docs/sdk.md +56 -1002
  179. package/docs/session-format.md +2 -0
  180. package/docs/sessions.md +6 -10
  181. package/docs/settings.md +6 -45
  182. package/docs/skills/authoring.md +95 -0
  183. package/docs/skills/reference.md +60 -0
  184. package/docs/skills.md +20 -122
  185. package/docs/subagents/authoring.md +37 -0
  186. package/docs/subagents/reference.md +60 -0
  187. package/docs/subagents.md +42 -96
  188. package/docs/terminal-setup.md +1 -1
  189. package/docs/themes/reference.md +176 -0
  190. package/docs/themes.md +21 -135
  191. package/docs/tmux.md +5 -0
  192. package/docs/tools/edit.md +5 -0
  193. package/docs/tools.md +31 -0
  194. package/docs/tui/reference.md +343 -0
  195. package/docs/tui.md +23 -286
  196. package/docs/usage.md +26 -209
  197. package/docs/web-access.md +40 -0
  198. package/docs/windows.md +2 -1
  199. package/docs/workflows/api-reference.md +11 -4
  200. package/docs/workflows/authoring.md +4 -2
  201. package/docs/workflows/builtins.md +2 -2
  202. package/docs/workflows/operations.md +11 -7
  203. package/docs/workflows/reliable-design.md +21 -3
  204. package/docs/workflows/verification.md +8 -0
  205. package/examples/extensions/gondolin/index.ts +116 -148
  206. package/examples/extensions/gondolin/package.json +1 -1
  207. package/examples/extensions/ssh.ts +56 -34
  208. package/npm-shrinkwrap.json +33 -33
  209. package/package.json +4 -4
@@ -0,0 +1,64 @@
1
+ import { computeFileHash, SnapshotStore } from "./hashline-engine/index.js";
2
+ /**
3
+ * {@link SnapshotStore} decorator that answers every read from the session's real store but
4
+ * never persists anything through {@link NonMintingSnapshotStore.record}.
5
+ *
6
+ * It exists because building a hashline rejection mints provenance. `Patcher`'s mismatch path
7
+ * records the live file into the snapshot store before constructing the error, then hands the
8
+ * model that tag as `actualFileHash`. An identical retry quoting that tag validates, because
9
+ * the tag now names content the store has seen, even though the model never re-read the file.
10
+ * The rejection issues the credential that defeats it.
11
+ *
12
+ * The engine is vendored and must not be edited, so the fix is injected at the single
13
+ * `new Patcher(...)` construction site instead. That is safe because every record the patcher
14
+ * would make is either unreachable or redundant when it is driven by the edit tool:
15
+ *
16
+ * - `commit()`'s no-op branch never runs. `edit.ts` filters no-op sections and returns before
17
+ * `apply` is ever called.
18
+ * - `commit()`'s post-write record is duplicated by `recordHashlineSnapshot` in `edit.ts`,
19
+ * which is also what populates the display-header map the patcher bypasses. That call stays
20
+ * the single writer of provenance.
21
+ * - The mismatch record is the bug.
22
+ *
23
+ * Reads delegate, so `Recovery` still resolves stale tags against the real per-session history
24
+ * and in-session drift recovery is unchanged.
25
+ *
26
+ * @see https://github.com/bastani-inc/atomic/issues/2329
27
+ */
28
+ export class NonMintingSnapshotStore extends SnapshotStore {
29
+ #inner;
30
+ constructor(inner) {
31
+ super();
32
+ this.#inner = inner;
33
+ }
34
+ head(path) {
35
+ return this.#inner.head(path);
36
+ }
37
+ byHash(path, hash) {
38
+ return this.#inner.byHash(path, hash);
39
+ }
40
+ /**
41
+ * Delegated rather than inherited. The base implementation is derived from
42
+ * {@link SnapshotStore.byHash}, but `InMemorySnapshotStore` overrides it with different
43
+ * hash-collision semantics, and a decorator must present whichever the wrapped store
44
+ * actually implements.
45
+ */
46
+ byHashAndText(path, hash, text) {
47
+ return this.#inner.byHashAndText(path, hash, text);
48
+ }
49
+ /**
50
+ * Returns the tag the content would receive without retaining it, so a tag quoted back in
51
+ * an error never becomes valid provenance. Callers that legitimately need to record a
52
+ * snapshot do so against the session store directly.
53
+ */
54
+ record(_path, fullText) {
55
+ return computeFileHash(fullText);
56
+ }
57
+ invalidate(path) {
58
+ this.#inner.invalidate(path);
59
+ }
60
+ clear() {
61
+ this.#inner.clear();
62
+ }
63
+ }
64
+ //# sourceMappingURL=non-minting-snapshot-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"non-minting-snapshot-store.js","sourceRoot":"","sources":["../../../src/core/tools/non-minting-snapshot-store.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAiB,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAE3F;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,MAAM,OAAO,uBAAwB,SAAQ,aAAa;IAChD,MAAM,CAAgB;IAE/B,YAAY,KAAoB;QAC/B,KAAK,EAAE,CAAC;QACR,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC;IACrB,CAAC;IAED,IAAI,CAAC,IAAY;QAChB,OAAO,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC/B,CAAC;IAED,MAAM,CAAC,IAAY,EAAE,IAAY;QAChC,OAAO,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IACvC,CAAC;IAED;;;;;OAKG;IACM,aAAa,CAAC,IAAY,EAAE,IAAY,EAAE,IAAY;QAC9D,OAAO,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;IACpD,CAAC;IAED;;;;OAIG;IACH,MAAM,CAAC,KAAa,EAAE,QAAgB;QACrC,OAAO,eAAe,CAAC,QAAQ,CAAC,CAAC;IAClC,CAAC;IAED,UAAU,CAAC,IAAY;QACtB,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;IAC9B,CAAC;IAED,KAAK;QACJ,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;IACrB,CAAC;CACD","sourcesContent":["import { computeFileHash, type Snapshot, SnapshotStore } from \"./hashline-engine/index.ts\";\n\n/**\n * {@link SnapshotStore} decorator that answers every read from the session's real store but\n * never persists anything through {@link NonMintingSnapshotStore.record}.\n *\n * It exists because building a hashline rejection mints provenance. `Patcher`'s mismatch path\n * records the live file into the snapshot store before constructing the error, then hands the\n * model that tag as `actualFileHash`. An identical retry quoting that tag validates, because\n * the tag now names content the store has seen, even though the model never re-read the file.\n * The rejection issues the credential that defeats it.\n *\n * The engine is vendored and must not be edited, so the fix is injected at the single\n * `new Patcher(...)` construction site instead. That is safe because every record the patcher\n * would make is either unreachable or redundant when it is driven by the edit tool:\n *\n * - `commit()`'s no-op branch never runs. `edit.ts` filters no-op sections and returns before\n * `apply` is ever called.\n * - `commit()`'s post-write record is duplicated by `recordHashlineSnapshot` in `edit.ts`,\n * which is also what populates the display-header map the patcher bypasses. That call stays\n * the single writer of provenance.\n * - The mismatch record is the bug.\n *\n * Reads delegate, so `Recovery` still resolves stale tags against the real per-session history\n * and in-session drift recovery is unchanged.\n *\n * @see https://github.com/bastani-inc/atomic/issues/2329\n */\nexport class NonMintingSnapshotStore extends SnapshotStore {\n\treadonly #inner: SnapshotStore;\n\n\tconstructor(inner: SnapshotStore) {\n\t\tsuper();\n\t\tthis.#inner = inner;\n\t}\n\n\thead(path: string): Snapshot | null {\n\t\treturn this.#inner.head(path);\n\t}\n\n\tbyHash(path: string, hash: string): Snapshot | null {\n\t\treturn this.#inner.byHash(path, hash);\n\t}\n\n\t/**\n\t * Delegated rather than inherited. The base implementation is derived from\n\t * {@link SnapshotStore.byHash}, but `InMemorySnapshotStore` overrides it with different\n\t * hash-collision semantics, and a decorator must present whichever the wrapped store\n\t * actually implements.\n\t */\n\toverride byHashAndText(path: string, hash: string, text: string): Snapshot | null {\n\t\treturn this.#inner.byHashAndText(path, hash, text);\n\t}\n\n\t/**\n\t * Returns the tag the content would receive without retaining it, so a tag quoted back in\n\t * an error never becomes valid provenance. Callers that legitimately need to record a\n\t * snapshot do so against the session store directly.\n\t */\n\trecord(_path: string, fullText: string): string {\n\t\treturn computeFileHash(fullText);\n\t}\n\n\tinvalidate(path: string): void {\n\t\tthis.#inner.invalidate(path);\n\t}\n\n\tclear(): void {\n\t\tthis.#inner.clear();\n\t}\n}\n"]}
@@ -2,7 +2,7 @@ import { type BashOperations, type BashSpawnContext, type BashSpawnHook, type Ba
2
2
  import { type SupervisedCommandOwner } from "./bash-pty-native.js";
3
3
  export declare const powershellToolSystemPromptContribution: Readonly<{
4
4
  readonly snippet: "Execute PowerShell commands.";
5
- readonly guidelines: readonly ["You can inspect ATOMIC_* or PI_* environment variables for current model and session details.", "Use { action: \"wait\", id: taskId, budgetMs: 1000 } to observe an existing shell task without executing another command. Omit budgetMs for owner policy; zero polls. Waiting does not extend execution timeout or owner lifetime."];
5
+ readonly guidelines: readonly ["You can inspect ATOMIC_* or PI_* environment variables for current model and session details.", "Use { action: \"wait\", id: taskId } to observe an existing shell task with the owner policy. Avoid repeated short polls; await completion notifications when no dependent work is blocked. Never relaunch a yielded command. Waiting does not extend execution timeout or owner lifetime.", "For ordinary commands, omit wait to use the owner's observation policy (normally 10s). Do not routinely request one-second waits: premature yields add tool calls without making the command faster. Use a short budget only for a concrete responsiveness need, or explicit background observation when you have independent work to do. Explicit budgets, including zero for polling, remain available.", "Choose foreground or background shell observation as needed without asking the user each time. Background yields after admission; foreground waits for its optional budget then the same command continues in background. Omitted wait uses owner-configured automatic background yield (default 10s). Observation never changes the execution timeout, which stops the command. Background requires a supported task owner; unbound foreground waits until completion regardless of budget."];
6
6
  }>;
7
7
  export type PowerShellOperations = BashOperations;
8
8
  export type PowerShellToolDetails = BashToolDetails;
@@ -126,7 +126,7 @@ export declare function createPowerShellToolDefinition(cwd: string, options?: Po
126
126
  } & Partial<Record<"command" | "cwd" | "env" | "pty" | "timeout" | "wait", never>>), signal: AbortSignal | undefined, onUpdate: import("@earendil-works/pi-agent-core").AgentToolUpdateCallback<BashToolDetails | undefined> | undefined, ctx: import("../sdk-exports.ts").ExtensionContext): Promise<import("@earendil-works/pi-agent-core").AgentToolResult<BashToolDetails | undefined>>;
127
127
  description: string;
128
128
  promptSnippet: "Execute PowerShell commands.";
129
- promptGuidelines: ("Use { action: \"wait\", id: taskId, budgetMs: 1000 } to observe an existing shell task without executing another command. Omit budgetMs for owner policy; zero polls. Waiting does not extend execution timeout or owner lifetime." | "You can inspect ATOMIC_* or PI_* environment variables for current model and session details.")[] | undefined;
129
+ promptGuidelines: ("Choose foreground or background shell observation as needed without asking the user each time. Background yields after admission; foreground waits for its optional budget then the same command continues in background. Omitted wait uses owner-configured automatic background yield (default 10s). Observation never changes the execution timeout, which stops the command. Background requires a supported task owner; unbound foreground waits until completion regardless of budget." | "For ordinary commands, omit wait to use the owner's observation policy (normally 10s). Do not routinely request one-second waits: premature yields add tool calls without making the command faster. Use a short budget only for a concrete responsiveness need, or explicit background observation when you have independent work to do. Explicit budgets, including zero for polling, remain available." | "Use { action: \"wait\", id: taskId } to observe an existing shell task with the owner policy. Avoid repeated short polls; await completion notifications when no dependent work is blocked. Never relaunch a yielded command. Waiting does not extend execution timeout or owner lifetime." | "You can inspect ATOMIC_* or PI_* environment variables for current model and session details.")[] | undefined;
130
130
  };
131
131
  export declare function createPowerShellTool(cwd: string, options?: PowerShellToolOptions): import("@earendil-works/pi-agent-core").AgentTool<import("typebox").TUnsafe<({
132
132
  command: string;
@@ -1 +1 @@
1
- {"version":3,"file":"powershell.d.ts","sourceRoot":"","sources":["../../../src/core/tools/powershell.ts"],"names":[],"mappings":"AASA,OAAO,EACN,KAAK,cAAc,EACnB,KAAK,gBAAgB,EACrB,KAAK,aAAa,EAClB,KAAK,eAAe,EACpB,KAAK,aAAa,EAClB,KAAK,eAAe,EAIpB,MAAM,WAAW,CAAC;AACnB,OAAO,EAGN,KAAK,sBAAsB,EAE3B,MAAM,sBAAsB,CAAC;AAS9B,eAAO,MAAM,sCAAsC;sBACzC,8BAA8B;;EAK7B,CAAC;AACZ,MAAM,MAAM,oBAAoB,GAAG,cAAc,CAAC;AAClD,MAAM,MAAM,qBAAqB,GAAG,eAAe,CAAC;AACpD,MAAM,MAAM,mBAAmB,GAAG,aAAa,CAAC;AAChD,MAAM,WAAW,qBAChB,SAAQ,IAAI,CAAC,eAAe,EAAE,0BAA0B,GAAG,WAAW,GAAG,WAAW,CAAC;IACrF,UAAU,CAAC,EAAE,cAAc,CAAC;CAC5B;AACD,wBAAgB,+BAA+B,CAAC,OAAO,CAAC,EAAE;IACzD,SAAS,CAAC,EAAE,sBAAsB,CAAC;CACnC,GAAG,oBAAoB,CA0DvB;AACD,wBAAgB,8BAA8B,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,GAAE,qBAA0B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAgC9F;AACD,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,qBAAqB;;;;;;;;;;;;;;;mHAEhF;AACD,MAAM,MAAM,sBAAsB,GAAG,gBAAgB,CAAC;AACtD,MAAM,MAAM,mBAAmB,GAAG,aAAa,CAAC"}
1
+ {"version":3,"file":"powershell.d.ts","sourceRoot":"","sources":["../../../src/core/tools/powershell.ts"],"names":[],"mappings":"AASA,OAAO,EACN,KAAK,cAAc,EACnB,KAAK,gBAAgB,EACrB,KAAK,aAAa,EAClB,KAAK,eAAe,EACpB,KAAK,aAAa,EAClB,KAAK,eAAe,EAKpB,MAAM,WAAW,CAAC;AACnB,OAAO,EAGN,KAAK,sBAAsB,EAE3B,MAAM,sBAAsB,CAAC;AAS9B,eAAO,MAAM,sCAAsC;sBACzC,8BAA8B;;EAE7B,CAAC;AACZ,MAAM,MAAM,oBAAoB,GAAG,cAAc,CAAC;AAClD,MAAM,MAAM,qBAAqB,GAAG,eAAe,CAAC;AACpD,MAAM,MAAM,mBAAmB,GAAG,aAAa,CAAC;AAChD,MAAM,WAAW,qBAChB,SAAQ,IAAI,CAAC,eAAe,EAAE,0BAA0B,GAAG,WAAW,GAAG,WAAW,CAAC;IACrF,UAAU,CAAC,EAAE,cAAc,CAAC;CAC5B;AACD,wBAAgB,+BAA+B,CAAC,OAAO,CAAC,EAAE;IACzD,SAAS,CAAC,EAAE,sBAAsB,CAAC;CACnC,GAAG,oBAAoB,CA0DvB;AACD,wBAAgB,8BAA8B,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,GAAE,qBAA0B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAgC9F;AACD,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,qBAAqB;;;;;;;;;;;;;;;mHAEhF;AACD,MAAM,MAAM,sBAAsB,GAAG,gBAAgB,CAAC;AACtD,MAAM,MAAM,mBAAmB,GAAG,aAAa,CAAC"}
@@ -1,7 +1,7 @@
1
1
  import { APP_NAME } from "../../config.js";
2
2
  import { createChildProcessEnvironment, waitForChildProcess } from "../../utils/child-process.js";
3
3
  import { getPowerShellConfig, getShellEnv, killProcessTree, trackDetachedChildPid, untrackDetachedChildPid, } from "../../utils/shell.js";
4
- import { createBashToolDefinition, validateExplicitTimeoutSeconds, } from "./bash.js";
4
+ import { bashToolSystemPromptContribution, createBashToolDefinition, validateExplicitTimeoutSeconds, } from "./bash.js";
5
5
  import { executeNativePty, executeSupervisedCommand, validateBashWait, } from "./bash-pty-native.js";
6
6
  import { wrapToolDefinition } from "./tool-definition-wrapper.js";
7
7
  const POWERSHELL_PRESENTATION = {
@@ -11,10 +11,7 @@ const POWERSHELL_PRESENTATION = {
11
11
  const UTF8_OUTPUT_PREFIX = "try { [Console]::OutputEncoding=[System.Text.Encoding]::UTF8 } catch {}\n";
12
12
  export const powershellToolSystemPromptContribution = Object.freeze({
13
13
  snippet: "Execute PowerShell commands.",
14
- guidelines: Object.freeze([
15
- "You can inspect ATOMIC_* or PI_* environment variables for current model and session details.",
16
- 'Use { action: "wait", id: taskId, budgetMs: 1000 } to observe an existing shell task without executing another command. Omit budgetMs for owner policy; zero polls. Waiting does not extend execution timeout or owner lifetime.',
17
- ]),
14
+ guidelines: bashToolSystemPromptContribution.guidelines,
18
15
  });
19
16
  export function createLocalPowerShellOperations(binding) {
20
17
  return {
@@ -1 +1 @@
1
- {"version":3,"file":"powershell.js","sourceRoot":"","sources":["../../../src/core/tools/powershell.ts"],"names":[],"mappings":"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","sourcesContent":["import { APP_NAME } from \"../../config.js\";\nimport { createChildProcessEnvironment, waitForChildProcess } from \"../../utils/child-process.ts\";\nimport {\n\tgetPowerShellConfig,\n\tgetShellEnv,\n\tkillProcessTree,\n\ttrackDetachedChildPid,\n\tuntrackDetachedChildPid,\n} from \"../../utils/shell.ts\";\nimport {\n\ttype BashOperations,\n\ttype BashSpawnContext,\n\ttype BashSpawnHook,\n\ttype BashToolDetails,\n\ttype BashToolInput,\n\ttype BashToolOptions,\n\tcreateBashToolDefinition,\n\ttype ShellToolPresentation,\n\tvalidateExplicitTimeoutSeconds,\n} from \"./bash.js\";\nimport {\n\texecuteNativePty,\n\texecuteSupervisedCommand,\n\ttype SupervisedCommandOwner,\n\tvalidateBashWait,\n} from \"./bash-pty-native.js\";\nimport { wrapToolDefinition } from \"./tool-definition-wrapper.ts\";\n\nconst POWERSHELL_PRESENTATION: ShellToolPresentation = {\n\tprompt: \"PS>\",\n\ttempFilePrefix: `${APP_NAME}-powershell`,\n};\n\nconst UTF8_OUTPUT_PREFIX = \"try { [Console]::OutputEncoding=[System.Text.Encoding]::UTF8 } catch {}\\n\";\nexport const powershellToolSystemPromptContribution = Object.freeze({\n\tsnippet: \"Execute PowerShell commands.\",\n\tguidelines: Object.freeze([\n\t\t\"You can inspect ATOMIC_* or PI_* environment variables for current model and session details.\",\n\t\t'Use { action: \"wait\", id: taskId, budgetMs: 1000 } to observe an existing shell task without executing another command. Omit budgetMs for owner policy; zero polls. Waiting does not extend execution timeout or owner lifetime.',\n\t] as const),\n} as const);\nexport type PowerShellOperations = BashOperations;\nexport type PowerShellToolDetails = BashToolDetails;\nexport type PowerShellToolInput = BashToolInput;\nexport interface PowerShellToolOptions\n\textends Pick<BashToolOptions, \"exposeSessionEnvironment\" | \"spawnHook\" | \"taskOwner\"> {\n\toperations?: BashOperations;\n}\nexport function createLocalPowerShellOperations(binding?: {\n\ttaskOwner?: SupervisedCommandOwner;\n}): PowerShellOperations {\n\treturn {\n\t\texec: async (command, cwd, options) => {\n\t\t\tvalidateBashWait(options.wait, !!binding?.taskOwner);\n\t\t\tif (options.timeout !== undefined) validateExplicitTimeoutSeconds(options.timeout);\n\t\t\tif (options.signal?.aborted) throw new Error(\"aborted\");\n\t\t\tconst { shell, args } = getPowerShellConfig();\n\t\t\tconst pty = !!options.pty && process.env.PI_NO_PTY !== \"1\" && process.env.ATOMIC_NO_PTY !== \"1\";\n\t\t\tif (binding?.taskOwner || pty) {\n\t\t\t\t// EncodedCommand avoids native argument parsing differences between PowerShell 5 and 7.\n\t\t\t\tconst encoded = Buffer.from(`${UTF8_OUTPUT_PREFIX}${command}`, \"utf16le\").toString(\"base64\");\n\t\t\t\tconst execution = {\n\t\t\t\t\t...options,\n\t\t\t\t\tshellConfig: { shell, args: [...args.slice(0, -1), \"-EncodedCommand\"] },\n\t\t\t\t\tcommandDescription: command,\n\t\t\t\t\ttaskOwner: binding?.taskOwner,\n\t\t\t\t};\n\t\t\t\treturn binding?.taskOwner\n\t\t\t\t\t? executeSupervisedCommand(encoded, cwd, execution, pty)\n\t\t\t\t\t: executeNativePty(encoded, cwd, execution);\n\t\t\t}\n\t\t\tconst { spawn } = await import(\"node:child_process\");\n\t\t\tif (options.signal?.aborted) throw new Error(\"aborted\");\n\t\t\tconst child = spawn(shell, [...args, `${UTF8_OUTPUT_PREFIX}${command}`], {\n\t\t\t\tcwd,\n\t\t\t\tenv: createChildProcessEnvironment(undefined, options.env ?? getShellEnv()),\n\t\t\t\twindowsHide: true,\n\t\t\t});\n\t\t\tif (child.pid) trackDetachedChildPid(child.pid);\n\t\t\tlet timedOut = false;\n\t\t\tlet timeoutHandle: ReturnType<typeof setTimeout> | undefined;\n\t\t\tconst onAbort = () => {\n\t\t\t\tif (child.pid) killProcessTree(child.pid);\n\t\t\t};\n\t\t\ttry {\n\t\t\t\tif (options.timeout !== undefined && options.timeout > 0) {\n\t\t\t\t\ttimeoutHandle = setTimeout(() => {\n\t\t\t\t\t\ttimedOut = true;\n\t\t\t\t\t\tif (child.pid) killProcessTree(child.pid);\n\t\t\t\t\t}, options.timeout * 1000);\n\t\t\t\t}\n\t\t\t\tchild.stdout?.on(\"data\", (data: Buffer) => options.onData(data, \"stdout\"));\n\t\t\t\tchild.stderr?.on(\"data\", (data: Buffer) => options.onData(data, \"stderr\"));\n\t\t\t\tif (options.signal) {\n\t\t\t\t\tif (options.signal.aborted) onAbort();\n\t\t\t\t\telse options.signal.addEventListener(\"abort\", onAbort, { once: true });\n\t\t\t\t}\n\t\t\t\tconst exitCode = await waitForChildProcess(child);\n\t\t\t\tif (options.signal?.aborted) throw new Error(\"aborted\");\n\t\t\t\tif (timedOut) throw new Error(`timeout:${options.timeout}`);\n\t\t\t\treturn { exitCode };\n\t\t\t} finally {\n\t\t\t\tif (child.pid) untrackDetachedChildPid(child.pid);\n\t\t\t\tif (timeoutHandle) clearTimeout(timeoutHandle);\n\t\t\t\toptions.signal?.removeEventListener(\"abort\", onAbort);\n\t\t\t}\n\t\t},\n\t};\n}\nexport function createPowerShellToolDefinition(cwd: string, options: PowerShellToolOptions = {}) {\n\tconst definition = createBashToolDefinition(\n\t\tcwd,\n\t\t{\n\t\t\texposeSessionEnvironment: options.exposeSessionEnvironment,\n\t\t\tspawnHook: options.spawnHook,\n\t\t\t// Preserve lazy session ownership instead of reading an accessor at registration.\n\t\t\tget taskOwner() {\n\t\t\t\treturn options.taskOwner;\n\t\t\t},\n\t\t\tshellDialect: \"powershell\",\n\t\t\toperations: options.operations ?? createLocalPowerShellOperations({ taskOwner: options.taskOwner }),\n\t\t},\n\t\tPOWERSHELL_PRESENTATION,\n\t);\n\treturn {\n\t\t...definition,\n\t\tname: \"powershell\",\n\t\tlabel: \"powershell\",\n\t\tasync execute(...args: Parameters<typeof definition.execute>) {\n\t\t\t// The internal local adapter is not evidence of a supported owner.\n\t\t\tif (args[1].action === undefined) validateBashWait(args[1].wait, !!options.operations || !!options.taskOwner);\n\t\t\treturn definition.execute(...args);\n\t\t},\n\t\tdescription:\n\t\t\t'Execute a PowerShell command or observe an existing task with action: \"wait\", id, and optional budgetMs. Owner-bound commands automatically yield after 10s by default without stopping execution. Unbound commands wait for completion; background and existing-task waits require a task owner.',\n\t\tpromptSnippet: powershellToolSystemPromptContribution.snippet,\n\t\tpromptGuidelines:\n\t\t\toptions.exposeSessionEnvironment === false\n\t\t\t\t? undefined\n\t\t\t\t: [...powershellToolSystemPromptContribution.guidelines],\n\t};\n}\nexport function createPowerShellTool(cwd: string, options?: PowerShellToolOptions) {\n\treturn wrapToolDefinition(createPowerShellToolDefinition(cwd, options));\n}\nexport type PowerShellSpawnContext = BashSpawnContext;\nexport type PowerShellSpawnHook = BashSpawnHook;\n"]}
1
+ {"version":3,"file":"powershell.js","sourceRoot":"","sources":["../../../src/core/tools/powershell.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAC3C,OAAO,EAAE,6BAA6B,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AAClG,OAAO,EACN,mBAAmB,EACnB,WAAW,EACX,eAAe,EACf,qBAAqB,EACrB,uBAAuB,GACvB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAON,gCAAgC,EAChC,wBAAwB,EAExB,8BAA8B,GAC9B,MAAM,WAAW,CAAC;AACnB,OAAO,EACN,gBAAgB,EAChB,wBAAwB,EAExB,gBAAgB,GAChB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,kBAAkB,EAAE,MAAM,8BAA8B,CAAC;AAElE,MAAM,uBAAuB,GAA0B;IACtD,MAAM,EAAE,KAAK;IACb,cAAc,EAAE,GAAG,QAAQ,aAAa;CACxC,CAAC;AAEF,MAAM,kBAAkB,GAAG,2EAA2E,CAAC;AACvG,MAAM,CAAC,MAAM,sCAAsC,GAAG,MAAM,CAAC,MAAM,CAAC;IACnE,OAAO,EAAE,8BAA8B;IACvC,UAAU,EAAE,gCAAgC,CAAC,UAAU;CAC9C,CAAC,CAAC;AAQZ,MAAM,UAAU,+BAA+B,CAAC,OAE/C;IACA,OAAO;QACN,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,OAAO,EAAE,EAAE;YACrC,gBAAgB,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;YACrD,IAAI,OAAO,CAAC,OAAO,KAAK,SAAS;gBAAE,8BAA8B,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;YACnF,IAAI,OAAO,CAAC,MAAM,EAAE,OAAO;gBAAE,MAAM,IAAI,KAAK,CAAC,SAAS,CAAC,CAAC;YACxD,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,mBAAmB,EAAE,CAAC;YAC9C,MAAM,GAAG,GAAG,CAAC,CAAC,OAAO,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,CAAC,SAAS,KAAK,GAAG,IAAI,OAAO,CAAC,GAAG,CAAC,aAAa,KAAK,GAAG,CAAC;YAChG,IAAI,OAAO,EAAE,SAAS,IAAI,GAAG,EAAE,CAAC;gBAC/B,wFAAwF;gBACxF,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,GAAG,kBAAkB,GAAG,OAAO,EAAE,EAAE,SAAS,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;gBAC7F,MAAM,SAAS,GAAG;oBACjB,GAAG,OAAO;oBACV,WAAW,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,iBAAiB,CAAC,EAAE;oBACvE,kBAAkB,EAAE,OAAO;oBAC3B,SAAS,EAAE,OAAO,EAAE,SAAS;iBAC7B,CAAC;gBACF,OAAO,OAAO,EAAE,SAAS;oBACxB,CAAC,CAAC,wBAAwB,CAAC,OAAO,EAAE,GAAG,EAAE,SAAS,EAAE,GAAG,CAAC;oBACxD,CAAC,CAAC,gBAAgB,CAAC,OAAO,EAAE,GAAG,EAAE,SAAS,CAAC,CAAC;YAC9C,CAAC;YACD,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,MAAM,CAAC,oBAAoB,CAAC,CAAC;YACrD,IAAI,OAAO,CAAC,MAAM,EAAE,OAAO;gBAAE,MAAM,IAAI,KAAK,CAAC,SAAS,CAAC,CAAC;YACxD,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,EAAE,CAAC,GAAG,IAAI,EAAE,GAAG,kBAAkB,GAAG,OAAO,EAAE,CAAC,EAAE;gBACxE,GAAG;gBACH,GAAG,EAAE,6BAA6B,CAAC,SAAS,EAAE,OAAO,CAAC,GAAG,IAAI,WAAW,EAAE,CAAC;gBAC3E,WAAW,EAAE,IAAI;aACjB,CAAC,CAAC;YACH,IAAI,KAAK,CAAC,GAAG;gBAAE,qBAAqB,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YAChD,IAAI,QAAQ,GAAG,KAAK,CAAC;YACrB,IAAI,aAAwD,CAAC;YAC7D,MAAM,OAAO,GAAG,GAAG,EAAE;gBACpB,IAAI,KAAK,CAAC,GAAG;oBAAE,eAAe,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YAC3C,CAAC,CAAC;YACF,IAAI,CAAC;gBACJ,IAAI,OAAO,CAAC,OAAO,KAAK,SAAS,IAAI,OAAO,CAAC,OAAO,GAAG,CAAC,EAAE,CAAC;oBAC1D,aAAa,GAAG,UAAU,CAAC,GAAG,EAAE;wBAC/B,QAAQ,GAAG,IAAI,CAAC;wBAChB,IAAI,KAAK,CAAC,GAAG;4BAAE,eAAe,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;oBAC3C,CAAC,EAAE,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,CAAC;gBAC5B,CAAC;gBACD,KAAK,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,EAAE,CAAC,IAAY,EAAE,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC;gBAC3E,KAAK,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,EAAE,CAAC,IAAY,EAAE,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC;gBAC3E,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;oBACpB,IAAI,OAAO,CAAC,MAAM,CAAC,OAAO;wBAAE,OAAO,EAAE,CAAC;;wBACjC,OAAO,CAAC,MAAM,CAAC,gBAAgB,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;gBACxE,CAAC;gBACD,MAAM,QAAQ,GAAG,MAAM,mBAAmB,CAAC,KAAK,CAAC,CAAC;gBAClD,IAAI,OAAO,CAAC,MAAM,EAAE,OAAO;oBAAE,MAAM,IAAI,KAAK,CAAC,SAAS,CAAC,CAAC;gBACxD,IAAI,QAAQ;oBAAE,MAAM,IAAI,KAAK,CAAC,WAAW,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC;gBAC5D,OAAO,EAAE,QAAQ,EAAE,CAAC;YACrB,CAAC;oBAAS,CAAC;gBACV,IAAI,KAAK,CAAC,GAAG;oBAAE,uBAAuB,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;gBAClD,IAAI,aAAa;oBAAE,YAAY,CAAC,aAAa,CAAC,CAAC;gBAC/C,OAAO,CAAC,MAAM,EAAE,mBAAmB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;YACvD,CAAC;QACF,CAAC;KACD,CAAC;AACH,CAAC;AACD,MAAM,UAAU,8BAA8B,CAAC,GAAW,EAAE,OAAO,GAA0B,EAAE;IAC9F,MAAM,UAAU,GAAG,wBAAwB,CAC1C,GAAG,EACH;QACC,wBAAwB,EAAE,OAAO,CAAC,wBAAwB;QAC1D,SAAS,EAAE,OAAO,CAAC,SAAS;QAC5B,kFAAkF;QAClF,IAAI,SAAS;YACZ,OAAO,OAAO,CAAC,SAAS,CAAC;QAC1B,CAAC;QACD,YAAY,EAAE,YAAY;QAC1B,UAAU,EAAE,OAAO,CAAC,UAAU,IAAI,+BAA+B,CAAC,EAAE,SAAS,EAAE,OAAO,CAAC,SAAS,EAAE,CAAC;KACnG,EACD,uBAAuB,CACvB,CAAC;IACF,OAAO;QACN,GAAG,UAAU;QACb,IAAI,EAAE,YAAY;QAClB,KAAK,EAAE,YAAY;QACnB,KAAK,CAAC,OAAO,CAAC,GAAG,IAA2C;YAC3D,mEAAmE;YACnE,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM,KAAK,SAAS;gBAAE,gBAAgB,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,UAAU,IAAI,CAAC,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;YAC9G,OAAO,UAAU,CAAC,OAAO,CAAC,GAAG,IAAI,CAAC,CAAC;QACpC,CAAC;QACD,WAAW,EACV,mSAAmS;QACpS,aAAa,EAAE,sCAAsC,CAAC,OAAO;QAC7D,gBAAgB,EACf,OAAO,CAAC,wBAAwB,KAAK,KAAK;YACzC,CAAC,CAAC,SAAS;YACX,CAAC,CAAC,CAAC,GAAG,sCAAsC,CAAC,UAAU,CAAC;KAC1D,CAAC;AACH,CAAC;AACD,MAAM,UAAU,oBAAoB,CAAC,GAAW,EAAE,OAA+B;IAChF,OAAO,kBAAkB,CAAC,8BAA8B,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC,CAAC;AACzE,CAAC","sourcesContent":["import { APP_NAME } from \"../../config.js\";\nimport { createChildProcessEnvironment, waitForChildProcess } from \"../../utils/child-process.ts\";\nimport {\n\tgetPowerShellConfig,\n\tgetShellEnv,\n\tkillProcessTree,\n\ttrackDetachedChildPid,\n\tuntrackDetachedChildPid,\n} from \"../../utils/shell.ts\";\nimport {\n\ttype BashOperations,\n\ttype BashSpawnContext,\n\ttype BashSpawnHook,\n\ttype BashToolDetails,\n\ttype BashToolInput,\n\ttype BashToolOptions,\n\tbashToolSystemPromptContribution,\n\tcreateBashToolDefinition,\n\ttype ShellToolPresentation,\n\tvalidateExplicitTimeoutSeconds,\n} from \"./bash.js\";\nimport {\n\texecuteNativePty,\n\texecuteSupervisedCommand,\n\ttype SupervisedCommandOwner,\n\tvalidateBashWait,\n} from \"./bash-pty-native.js\";\nimport { wrapToolDefinition } from \"./tool-definition-wrapper.ts\";\n\nconst POWERSHELL_PRESENTATION: ShellToolPresentation = {\n\tprompt: \"PS>\",\n\ttempFilePrefix: `${APP_NAME}-powershell`,\n};\n\nconst UTF8_OUTPUT_PREFIX = \"try { [Console]::OutputEncoding=[System.Text.Encoding]::UTF8 } catch {}\\n\";\nexport const powershellToolSystemPromptContribution = Object.freeze({\n\tsnippet: \"Execute PowerShell commands.\",\n\tguidelines: bashToolSystemPromptContribution.guidelines,\n} as const);\nexport type PowerShellOperations = BashOperations;\nexport type PowerShellToolDetails = BashToolDetails;\nexport type PowerShellToolInput = BashToolInput;\nexport interface PowerShellToolOptions\n\textends Pick<BashToolOptions, \"exposeSessionEnvironment\" | \"spawnHook\" | \"taskOwner\"> {\n\toperations?: BashOperations;\n}\nexport function createLocalPowerShellOperations(binding?: {\n\ttaskOwner?: SupervisedCommandOwner;\n}): PowerShellOperations {\n\treturn {\n\t\texec: async (command, cwd, options) => {\n\t\t\tvalidateBashWait(options.wait, !!binding?.taskOwner);\n\t\t\tif (options.timeout !== undefined) validateExplicitTimeoutSeconds(options.timeout);\n\t\t\tif (options.signal?.aborted) throw new Error(\"aborted\");\n\t\t\tconst { shell, args } = getPowerShellConfig();\n\t\t\tconst pty = !!options.pty && process.env.PI_NO_PTY !== \"1\" && process.env.ATOMIC_NO_PTY !== \"1\";\n\t\t\tif (binding?.taskOwner || pty) {\n\t\t\t\t// EncodedCommand avoids native argument parsing differences between PowerShell 5 and 7.\n\t\t\t\tconst encoded = Buffer.from(`${UTF8_OUTPUT_PREFIX}${command}`, \"utf16le\").toString(\"base64\");\n\t\t\t\tconst execution = {\n\t\t\t\t\t...options,\n\t\t\t\t\tshellConfig: { shell, args: [...args.slice(0, -1), \"-EncodedCommand\"] },\n\t\t\t\t\tcommandDescription: command,\n\t\t\t\t\ttaskOwner: binding?.taskOwner,\n\t\t\t\t};\n\t\t\t\treturn binding?.taskOwner\n\t\t\t\t\t? executeSupervisedCommand(encoded, cwd, execution, pty)\n\t\t\t\t\t: executeNativePty(encoded, cwd, execution);\n\t\t\t}\n\t\t\tconst { spawn } = await import(\"node:child_process\");\n\t\t\tif (options.signal?.aborted) throw new Error(\"aborted\");\n\t\t\tconst child = spawn(shell, [...args, `${UTF8_OUTPUT_PREFIX}${command}`], {\n\t\t\t\tcwd,\n\t\t\t\tenv: createChildProcessEnvironment(undefined, options.env ?? getShellEnv()),\n\t\t\t\twindowsHide: true,\n\t\t\t});\n\t\t\tif (child.pid) trackDetachedChildPid(child.pid);\n\t\t\tlet timedOut = false;\n\t\t\tlet timeoutHandle: ReturnType<typeof setTimeout> | undefined;\n\t\t\tconst onAbort = () => {\n\t\t\t\tif (child.pid) killProcessTree(child.pid);\n\t\t\t};\n\t\t\ttry {\n\t\t\t\tif (options.timeout !== undefined && options.timeout > 0) {\n\t\t\t\t\ttimeoutHandle = setTimeout(() => {\n\t\t\t\t\t\ttimedOut = true;\n\t\t\t\t\t\tif (child.pid) killProcessTree(child.pid);\n\t\t\t\t\t}, options.timeout * 1000);\n\t\t\t\t}\n\t\t\t\tchild.stdout?.on(\"data\", (data: Buffer) => options.onData(data, \"stdout\"));\n\t\t\t\tchild.stderr?.on(\"data\", (data: Buffer) => options.onData(data, \"stderr\"));\n\t\t\t\tif (options.signal) {\n\t\t\t\t\tif (options.signal.aborted) onAbort();\n\t\t\t\t\telse options.signal.addEventListener(\"abort\", onAbort, { once: true });\n\t\t\t\t}\n\t\t\t\tconst exitCode = await waitForChildProcess(child);\n\t\t\t\tif (options.signal?.aborted) throw new Error(\"aborted\");\n\t\t\t\tif (timedOut) throw new Error(`timeout:${options.timeout}`);\n\t\t\t\treturn { exitCode };\n\t\t\t} finally {\n\t\t\t\tif (child.pid) untrackDetachedChildPid(child.pid);\n\t\t\t\tif (timeoutHandle) clearTimeout(timeoutHandle);\n\t\t\t\toptions.signal?.removeEventListener(\"abort\", onAbort);\n\t\t\t}\n\t\t},\n\t};\n}\nexport function createPowerShellToolDefinition(cwd: string, options: PowerShellToolOptions = {}) {\n\tconst definition = createBashToolDefinition(\n\t\tcwd,\n\t\t{\n\t\t\texposeSessionEnvironment: options.exposeSessionEnvironment,\n\t\t\tspawnHook: options.spawnHook,\n\t\t\t// Preserve lazy session ownership instead of reading an accessor at registration.\n\t\t\tget taskOwner() {\n\t\t\t\treturn options.taskOwner;\n\t\t\t},\n\t\t\tshellDialect: \"powershell\",\n\t\t\toperations: options.operations ?? createLocalPowerShellOperations({ taskOwner: options.taskOwner }),\n\t\t},\n\t\tPOWERSHELL_PRESENTATION,\n\t);\n\treturn {\n\t\t...definition,\n\t\tname: \"powershell\",\n\t\tlabel: \"powershell\",\n\t\tasync execute(...args: Parameters<typeof definition.execute>) {\n\t\t\t// The internal local adapter is not evidence of a supported owner.\n\t\t\tif (args[1].action === undefined) validateBashWait(args[1].wait, !!options.operations || !!options.taskOwner);\n\t\t\treturn definition.execute(...args);\n\t\t},\n\t\tdescription:\n\t\t\t'Execute a PowerShell command or observe an existing task with action: \"wait\", id, and optional budgetMs. Owner-bound commands automatically yield after 10s by default without stopping execution. Unbound commands wait for completion; background and existing-task waits require a task owner.',\n\t\tpromptSnippet: powershellToolSystemPromptContribution.snippet,\n\t\tpromptGuidelines:\n\t\t\toptions.exposeSessionEnvironment === false\n\t\t\t\t? undefined\n\t\t\t\t: [...powershellToolSystemPromptContribution.guidelines],\n\t};\n}\nexport function createPowerShellTool(cwd: string, options?: PowerShellToolOptions) {\n\treturn wrapToolDefinition(createPowerShellToolDefinition(cwd, options));\n}\nexport type PowerShellSpawnContext = BashSpawnContext;\nexport type PowerShellSpawnHook = BashSpawnHook;\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"read-document-extract.js","sourceRoot":"","sources":["../../../src/core/tools/read-document-extract.ts"],"names":[],"mappings":"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","sourcesContent":["import { existsSync } from \"node:fs\";\nimport { convertBufferWithMarkit, convertFileWithMarkit } from \"../../utils/markit.ts\";\nimport { type ReadLineRange, selectExactReadRanges, selectReadRanges } from \"./read-selectors.ts\";\n\nconst DOCUMENT_EXTENSIONS = /\\.(?:pdf|doc|docx|ppt|pptx|xls|xlsx|rtf|epub|ipynb)(?:$|[?#])/i;\nconst MARKIT_EXTENSIONS = /\\.(?:pdf|doc|docx|ppt|pptx|xls|xlsx|rtf|epub)(?:$|[?#])/i;\n\nexport function isDocumentPath(pathValue: string): boolean {\n\treturn DOCUMENT_EXTENSIONS.test(pathValue);\n}\n\nfunction documentExtensionFromContentType(contentType: string): string | undefined {\n\tif (/ipynb|jupyter/i.test(contentType)) return \".ipynb\";\n\tif (/pdf/i.test(contentType)) return \".pdf\";\n\tif (/msword/i.test(contentType)) return \".doc\";\n\tif (/wordprocessingml|officedocument\\.word/i.test(contentType)) return \".docx\";\n\tif (/presentationml|officedocument\\.presentation/i.test(contentType)) return \".pptx\";\n\tif (/ms-powerpoint|vnd\\.ms-powerpoint/i.test(contentType)) return \".ppt\";\n\tif (/spreadsheetml|officedocument\\.spreadsheet/i.test(contentType)) return \".xlsx\";\n\tif (/epub/i.test(contentType)) return \".epub\";\n\tif (/ms-excel|vnd\\.ms-excel/i.test(contentType)) return \".xls\";\n\tif (/rtf/i.test(contentType)) return \".rtf\";\n\treturn undefined;\n}\n\nfunction isHtmlWhitespace(char: string | undefined): boolean {\n\treturn char === \" \" || char === \"\\t\" || char === \"\\n\" || char === \"\\r\" || char === \"\\f\";\n}\n\nfunction findElementStart(lowerHtml: string, tagName: string, fromIndex: number): number {\n\tconst needle = `<${tagName}`;\n\tlet index = fromIndex;\n\tfor (;;) {\n\t\tconst found = lowerHtml.indexOf(needle, index);\n\t\tif (found < 0) return -1;\n\t\tconst next = lowerHtml[found + needle.length];\n\t\tif (next === undefined || next === \">\" || next === \"/\" || isHtmlWhitespace(next)) return found;\n\t\tindex = found + needle.length;\n\t}\n}\n\nfunction findClosingTag(lowerHtml: string, tagName: string, fromIndex: number): number {\n\tconst needle = `</${tagName}`;\n\tlet index = fromIndex;\n\tfor (;;) {\n\t\tconst found = lowerHtml.indexOf(needle, index);\n\t\tif (found < 0) return -1;\n\t\tlet cursor = found + needle.length;\n\t\twhile (isHtmlWhitespace(lowerHtml[cursor])) cursor++;\n\t\tif (lowerHtml[cursor] === \">\") return found;\n\t\tindex = found + needle.length;\n\t}\n}\n\nfunction stripElementBlocks(html: string, tagName: string): string {\n\tconst lowerHtml = html.toLowerCase();\n\tconst chunks: string[] = [];\n\tlet index = 0;\n\tfor (;;) {\n\t\tconst start = findElementStart(lowerHtml, tagName, index);\n\t\tif (start < 0) break;\n\t\tchunks.push(html.slice(index, start));\n\t\tconst startEnd = html.indexOf(\">\", start);\n\t\tif (startEnd < 0) {\n\t\t\tindex = html.length;\n\t\t\tbreak;\n\t\t}\n\t\tconst closeStart = findClosingTag(lowerHtml, tagName, startEnd + 1);\n\t\tif (closeStart < 0) {\n\t\t\tindex = html.length;\n\t\t\tbreak;\n\t\t}\n\t\tconst closeEnd = html.indexOf(\">\", closeStart);\n\t\tif (closeEnd < 0) {\n\t\t\tindex = html.length;\n\t\t\tbreak;\n\t\t}\n\t\tindex = closeEnd + 1;\n\t}\n\tchunks.push(html.slice(index));\n\treturn chunks.join(\"\");\n}\n\nfunction extractElementText(html: string, tagName: string): string | undefined {\n\tconst lowerHtml = html.toLowerCase();\n\tconst start = findElementStart(lowerHtml, tagName, 0);\n\tif (start < 0) return undefined;\n\tconst startEnd = html.indexOf(\">\", start);\n\tif (startEnd < 0) return undefined;\n\tconst closeStart = findClosingTag(lowerHtml, tagName, startEnd + 1);\n\treturn closeStart < 0 ? undefined : html.slice(startEnd + 1, closeStart);\n}\n\nfunction readTagName(tagContent: string): { closing: boolean; name: string } {\n\tlet index = 0;\n\twhile (isHtmlWhitespace(tagContent[index])) index++;\n\tconst closing = tagContent[index] === \"/\";\n\tif (closing) index++;\n\twhile (isHtmlWhitespace(tagContent[index])) index++;\n\tconst start = index;\n\twhile (index < tagContent.length) {\n\t\tconst char = tagContent[index];\n\t\tif (!char || (!(char >= \"a\" && char <= \"z\") && !(char >= \"A\" && char <= \"Z\") && !(char >= \"0\" && char <= \"9\")))\n\t\t\tbreak;\n\t\tindex++;\n\t}\n\treturn { closing, name: tagContent.slice(start, index).toLowerCase() };\n}\n\nfunction htmlMarkupToPlainText(html: string): string {\n\tlet output = \"\";\n\tlet index = 0;\n\twhile (index < html.length) {\n\t\tconst open = html.indexOf(\"<\", index);\n\t\tif (open < 0) {\n\t\t\toutput += html.slice(index);\n\t\t\tbreak;\n\t\t}\n\t\toutput += html.slice(index, open);\n\t\tconst close = html.indexOf(\">\", open + 1);\n\t\tif (close < 0) break;\n\t\tconst tag = readTagName(html.slice(open + 1, close));\n\t\tif (\n\t\t\ttag.name === \"br\" ||\n\t\t\t(tag.closing &&\n\t\t\t\t[\"h1\", \"h2\", \"h3\", \"h4\", \"h5\", \"h6\", \"p\", \"div\", \"li\", \"tr\", \"blockquote\", \"pre\"].includes(tag.name))\n\t\t)\n\t\t\toutput += \"\\n\";\n\t\telse if (!tag.closing && tag.name === \"li\") output += \"- \";\n\t\tindex = close + 1;\n\t}\n\treturn normalizeDecodedText(output);\n}\n\nfunction normalizeDecodedText(value: string): string {\n\treturn decodeEntities(value)\n\t\t.split(\"\\n\")\n\t\t.map((line) => line.trim())\n\t\t.filter(Boolean)\n\t\t.join(\"\\n\");\n}\n\nfunction htmlToReadableText(html: string): string {\n\tconst stripped = stripElementBlocks(stripElementBlocks(html, \"script\"), \"style\");\n\tconst title = extractElementText(stripped, \"title\");\n\tconst titleText = title ? htmlMarkupToPlainText(title).split(\"\\n\").join(\" \").trim() : undefined;\n\tconst text = htmlMarkupToPlainText(stripped);\n\treturn titleText && !text.startsWith(titleText) ? `# ${titleText}\\n\\n${text}` : text;\n}\n\nfunction decodeEntities(value: string): string {\n\tconst entities: Record<string, string> = { nbsp: \" \", amp: \"&\", lt: \"<\", gt: \">\", quot: '\"', \"#39\": \"'\" };\n\tlet output = \"\";\n\tlet index = 0;\n\twhile (index < value.length) {\n\t\tconst ampersand = value.indexOf(\"&\", index);\n\t\tif (ampersand < 0) {\n\t\t\toutput += value.slice(index);\n\t\t\tbreak;\n\t\t}\n\t\toutput += value.slice(index, ampersand);\n\t\tconst semicolon = value.indexOf(\";\", ampersand + 1);\n\t\tif (semicolon < 0 || semicolon - ampersand > 12) {\n\t\t\toutput += \"&\";\n\t\t\tindex = ampersand + 1;\n\t\t\tcontinue;\n\t\t}\n\t\tconst entity = value.slice(ampersand + 1, semicolon).toLowerCase();\n\t\tconst decoded = entities[entity];\n\t\toutput += decoded ?? value.slice(ampersand, semicolon + 1);\n\t\tindex = semicolon + 1;\n\t}\n\treturn output;\n}\n\nfunction notebookMarkdown(buffer: Buffer, source: string): string {\n\tconst nb = JSON.parse(buffer.toString(\"utf8\")) as {\n\t\tcells?: Array<{ cell_type?: string; source?: string | string[] }>;\n\t};\n\tconst cells = nb.cells ?? [];\n\treturn (\n\t\tcells\n\t\t\t.map((cell, index) => {\n\t\t\t\tconst sourceText = Array.isArray(cell.source) ? cell.source.join(\"\") : (cell.source ?? \"\");\n\t\t\t\treturn `# %% [${cell.cell_type ?? \"raw\"}] cell:${index}\\n${sourceText.trimEnd()}`;\n\t\t\t})\n\t\t\t.join(\"\\n\\n\") || `# ${source}\\n\\n(empty notebook)`\n\t);\n}\n\nfunction documentExtension(source: string): string {\n\treturn `.${source.match(/\\.(pdf|docx?|pptx?|xlsx?|rtf|epub)(?:$|[?#])/i)?.[1]?.toLowerCase() ?? \"bin\"}`;\n}\n\nasync function extractMarkitDocument(buffer: Buffer, source: string): Promise<string> {\n\tconst ext = documentExtension(source);\n\tconst result = existsSync(source) ? await convertFileWithMarkit(source) : await convertBufferWithMarkit(buffer, ext);\n\treturn result.ok ? result.content : `[Cannot read ${ext} file: ${result.error || \"conversion failed\"}]`;\n}\n\nexport async function extractDocumentMarkdown(buffer: Buffer, source: string): Promise<string> {\n\tif (/\\.ipynb(?:$|[?#])/i.test(source)) return notebookMarkdown(buffer, source);\n\tif (MARKIT_EXTENSIONS.test(source)) return extractMarkitDocument(buffer, source);\n\treturn buffer.toString(\"utf8\");\n}\n\nexport async function decodeReadableUrl(response: Response, url: string): Promise<string> {\n\tconst contentType = response.headers.get(\"content-type\") ?? \"\";\n\tconst buffer = Buffer.from(await response.arrayBuffer());\n\tconst contentTypeExtension = documentExtensionFromContentType(contentType);\n\tif (contentTypeExtension || isDocumentPath(url))\n\t\treturn extractDocumentMarkdown(\n\t\t\tbuffer,\n\t\t\tcontentTypeExtension && !isDocumentPath(url) ? `${url}${contentTypeExtension}` : url,\n\t\t);\n\tconst text = buffer.toString(\"utf8\");\n\tif (/html/i.test(contentType) || /<html[\\s>]/i.test(text)) return htmlToReadableText(text);\n\treturn text;\n}\n\nexport function applyReadLineSelection(\n\tallLines: string[],\n\tranges: ReadLineRange[] | undefined,\n\toffset?: number,\n\tlimit?: number,\n\texact = false,\n): { lines: string[]; firstLine: number } {\n\tconst rangeSelection = (exact ? selectExactReadRanges : selectReadRanges)(allLines, ranges);\n\tconst rangeStart = ranges?.[0]?.start;\n\tconst startLine = rangeSelection\n\t\t? (rangeSelection.selectedLines.length === 0\n\t\t\t\t? (rangeStart ?? rangeSelection.firstLine)\n\t\t\t\t: rangeSelection.firstLine) - 1\n\t\t: offset\n\t\t\t? Math.max(0, offset - 1)\n\t\t\t: 0;\n\tconst endLine = limit !== undefined ? Math.min(startLine + limit, allLines.length) : allLines.length;\n\treturn { lines: rangeSelection?.selectedLines ?? allLines.slice(startLine, endLine), firstLine: startLine + 1 };\n}\n"]}
1
+ {"version":3,"file":"read-document-extract.js","sourceRoot":"","sources":["../../../src/core/tools/read-document-extract.ts"],"names":[],"mappings":"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","sourcesContent":["import { existsSync } from \"node:fs\";\nimport { convertBufferWithMarkit, convertFileWithMarkit } from \"../../utils/markit.js\";\nimport { type ReadLineRange, selectExactReadRanges, selectReadRanges } from \"./read-selectors.ts\";\n\nconst DOCUMENT_EXTENSIONS = /\\.(?:pdf|doc|docx|ppt|pptx|xls|xlsx|rtf|epub|ipynb)(?:$|[?#])/i;\nconst MARKIT_EXTENSIONS = /\\.(?:pdf|doc|docx|ppt|pptx|xls|xlsx|rtf|epub)(?:$|[?#])/i;\n\nexport function isDocumentPath(pathValue: string): boolean {\n\treturn DOCUMENT_EXTENSIONS.test(pathValue);\n}\n\nfunction documentExtensionFromContentType(contentType: string): string | undefined {\n\tif (/ipynb|jupyter/i.test(contentType)) return \".ipynb\";\n\tif (/pdf/i.test(contentType)) return \".pdf\";\n\tif (/msword/i.test(contentType)) return \".doc\";\n\tif (/wordprocessingml|officedocument\\.word/i.test(contentType)) return \".docx\";\n\tif (/presentationml|officedocument\\.presentation/i.test(contentType)) return \".pptx\";\n\tif (/ms-powerpoint|vnd\\.ms-powerpoint/i.test(contentType)) return \".ppt\";\n\tif (/spreadsheetml|officedocument\\.spreadsheet/i.test(contentType)) return \".xlsx\";\n\tif (/epub/i.test(contentType)) return \".epub\";\n\tif (/ms-excel|vnd\\.ms-excel/i.test(contentType)) return \".xls\";\n\tif (/rtf/i.test(contentType)) return \".rtf\";\n\treturn undefined;\n}\n\nfunction isHtmlWhitespace(char: string | undefined): boolean {\n\treturn char === \" \" || char === \"\\t\" || char === \"\\n\" || char === \"\\r\" || char === \"\\f\";\n}\n\nfunction findElementStart(lowerHtml: string, tagName: string, fromIndex: number): number {\n\tconst needle = `<${tagName}`;\n\tlet index = fromIndex;\n\tfor (;;) {\n\t\tconst found = lowerHtml.indexOf(needle, index);\n\t\tif (found < 0) return -1;\n\t\tconst next = lowerHtml[found + needle.length];\n\t\tif (next === undefined || next === \">\" || next === \"/\" || isHtmlWhitespace(next)) return found;\n\t\tindex = found + needle.length;\n\t}\n}\n\nfunction findClosingTag(lowerHtml: string, tagName: string, fromIndex: number): number {\n\tconst needle = `</${tagName}`;\n\tlet index = fromIndex;\n\tfor (;;) {\n\t\tconst found = lowerHtml.indexOf(needle, index);\n\t\tif (found < 0) return -1;\n\t\tlet cursor = found + needle.length;\n\t\twhile (isHtmlWhitespace(lowerHtml[cursor])) cursor++;\n\t\tif (lowerHtml[cursor] === \">\") return found;\n\t\tindex = found + needle.length;\n\t}\n}\n\nfunction stripElementBlocks(html: string, tagName: string): string {\n\tconst lowerHtml = html.toLowerCase();\n\tconst chunks: string[] = [];\n\tlet index = 0;\n\tfor (;;) {\n\t\tconst start = findElementStart(lowerHtml, tagName, index);\n\t\tif (start < 0) break;\n\t\tchunks.push(html.slice(index, start));\n\t\tconst startEnd = html.indexOf(\">\", start);\n\t\tif (startEnd < 0) {\n\t\t\tindex = html.length;\n\t\t\tbreak;\n\t\t}\n\t\tconst closeStart = findClosingTag(lowerHtml, tagName, startEnd + 1);\n\t\tif (closeStart < 0) {\n\t\t\tindex = html.length;\n\t\t\tbreak;\n\t\t}\n\t\tconst closeEnd = html.indexOf(\">\", closeStart);\n\t\tif (closeEnd < 0) {\n\t\t\tindex = html.length;\n\t\t\tbreak;\n\t\t}\n\t\tindex = closeEnd + 1;\n\t}\n\tchunks.push(html.slice(index));\n\treturn chunks.join(\"\");\n}\n\nfunction extractElementText(html: string, tagName: string): string | undefined {\n\tconst lowerHtml = html.toLowerCase();\n\tconst start = findElementStart(lowerHtml, tagName, 0);\n\tif (start < 0) return undefined;\n\tconst startEnd = html.indexOf(\">\", start);\n\tif (startEnd < 0) return undefined;\n\tconst closeStart = findClosingTag(lowerHtml, tagName, startEnd + 1);\n\treturn closeStart < 0 ? undefined : html.slice(startEnd + 1, closeStart);\n}\n\nfunction readTagName(tagContent: string): { closing: boolean; name: string } {\n\tlet index = 0;\n\twhile (isHtmlWhitespace(tagContent[index])) index++;\n\tconst closing = tagContent[index] === \"/\";\n\tif (closing) index++;\n\twhile (isHtmlWhitespace(tagContent[index])) index++;\n\tconst start = index;\n\twhile (index < tagContent.length) {\n\t\tconst char = tagContent[index];\n\t\tif (!char || (!(char >= \"a\" && char <= \"z\") && !(char >= \"A\" && char <= \"Z\") && !(char >= \"0\" && char <= \"9\")))\n\t\t\tbreak;\n\t\tindex++;\n\t}\n\treturn { closing, name: tagContent.slice(start, index).toLowerCase() };\n}\n\nfunction htmlMarkupToPlainText(html: string): string {\n\tlet output = \"\";\n\tlet index = 0;\n\twhile (index < html.length) {\n\t\tconst open = html.indexOf(\"<\", index);\n\t\tif (open < 0) {\n\t\t\toutput += html.slice(index);\n\t\t\tbreak;\n\t\t}\n\t\toutput += html.slice(index, open);\n\t\tconst close = html.indexOf(\">\", open + 1);\n\t\tif (close < 0) break;\n\t\tconst tag = readTagName(html.slice(open + 1, close));\n\t\tif (\n\t\t\ttag.name === \"br\" ||\n\t\t\t(tag.closing &&\n\t\t\t\t[\"h1\", \"h2\", \"h3\", \"h4\", \"h5\", \"h6\", \"p\", \"div\", \"li\", \"tr\", \"blockquote\", \"pre\"].includes(tag.name))\n\t\t)\n\t\t\toutput += \"\\n\";\n\t\telse if (!tag.closing && tag.name === \"li\") output += \"- \";\n\t\tindex = close + 1;\n\t}\n\treturn normalizeDecodedText(output);\n}\n\nfunction normalizeDecodedText(value: string): string {\n\treturn decodeEntities(value)\n\t\t.split(\"\\n\")\n\t\t.map((line) => line.trim())\n\t\t.filter(Boolean)\n\t\t.join(\"\\n\");\n}\n\nfunction htmlToReadableText(html: string): string {\n\tconst stripped = stripElementBlocks(stripElementBlocks(html, \"script\"), \"style\");\n\tconst title = extractElementText(stripped, \"title\");\n\tconst titleText = title ? htmlMarkupToPlainText(title).split(\"\\n\").join(\" \").trim() : undefined;\n\tconst text = htmlMarkupToPlainText(stripped);\n\treturn titleText && !text.startsWith(titleText) ? `# ${titleText}\\n\\n${text}` : text;\n}\n\nfunction decodeEntities(value: string): string {\n\tconst entities: Record<string, string> = { nbsp: \" \", amp: \"&\", lt: \"<\", gt: \">\", quot: '\"', \"#39\": \"'\" };\n\tlet output = \"\";\n\tlet index = 0;\n\twhile (index < value.length) {\n\t\tconst ampersand = value.indexOf(\"&\", index);\n\t\tif (ampersand < 0) {\n\t\t\toutput += value.slice(index);\n\t\t\tbreak;\n\t\t}\n\t\toutput += value.slice(index, ampersand);\n\t\tconst semicolon = value.indexOf(\";\", ampersand + 1);\n\t\tif (semicolon < 0 || semicolon - ampersand > 12) {\n\t\t\toutput += \"&\";\n\t\t\tindex = ampersand + 1;\n\t\t\tcontinue;\n\t\t}\n\t\tconst entity = value.slice(ampersand + 1, semicolon).toLowerCase();\n\t\tconst decoded = entities[entity];\n\t\toutput += decoded ?? value.slice(ampersand, semicolon + 1);\n\t\tindex = semicolon + 1;\n\t}\n\treturn output;\n}\n\nfunction notebookMarkdown(buffer: Buffer, source: string): string {\n\tconst nb = JSON.parse(buffer.toString(\"utf8\")) as {\n\t\tcells?: Array<{ cell_type?: string; source?: string | string[] }>;\n\t};\n\tconst cells = nb.cells ?? [];\n\treturn (\n\t\tcells\n\t\t\t.map((cell, index) => {\n\t\t\t\tconst sourceText = Array.isArray(cell.source) ? cell.source.join(\"\") : (cell.source ?? \"\");\n\t\t\t\treturn `# %% [${cell.cell_type ?? \"raw\"}] cell:${index}\\n${sourceText.trimEnd()}`;\n\t\t\t})\n\t\t\t.join(\"\\n\\n\") || `# ${source}\\n\\n(empty notebook)`\n\t);\n}\n\nfunction documentExtension(source: string): string {\n\treturn `.${source.match(/\\.(pdf|docx?|pptx?|xlsx?|rtf|epub)(?:$|[?#])/i)?.[1]?.toLowerCase() ?? \"bin\"}`;\n}\n\nasync function extractMarkitDocument(buffer: Buffer, source: string): Promise<string> {\n\tconst ext = documentExtension(source);\n\tconst result = existsSync(source) ? await convertFileWithMarkit(source) : await convertBufferWithMarkit(buffer, ext);\n\treturn result.ok ? result.content : `[Cannot read ${ext} file: ${result.error || \"conversion failed\"}]`;\n}\n\nexport async function extractDocumentMarkdown(buffer: Buffer, source: string): Promise<string> {\n\tif (/\\.ipynb(?:$|[?#])/i.test(source)) return notebookMarkdown(buffer, source);\n\tif (MARKIT_EXTENSIONS.test(source)) return extractMarkitDocument(buffer, source);\n\treturn buffer.toString(\"utf8\");\n}\n\nexport async function decodeReadableUrl(response: Response, url: string): Promise<string> {\n\tconst contentType = response.headers.get(\"content-type\") ?? \"\";\n\tconst buffer = Buffer.from(await response.arrayBuffer());\n\tconst contentTypeExtension = documentExtensionFromContentType(contentType);\n\tif (contentTypeExtension || isDocumentPath(url))\n\t\treturn extractDocumentMarkdown(\n\t\t\tbuffer,\n\t\t\tcontentTypeExtension && !isDocumentPath(url) ? `${url}${contentTypeExtension}` : url,\n\t\t);\n\tconst text = buffer.toString(\"utf8\");\n\tif (/html/i.test(contentType) || /<html[\\s>]/i.test(text)) return htmlToReadableText(text);\n\treturn text;\n}\n\nexport function applyReadLineSelection(\n\tallLines: string[],\n\tranges: ReadLineRange[] | undefined,\n\toffset?: number,\n\tlimit?: number,\n\texact = false,\n): { lines: string[]; firstLine: number } {\n\tconst rangeSelection = (exact ? selectExactReadRanges : selectReadRanges)(allLines, ranges);\n\tconst rangeStart = ranges?.[0]?.start;\n\tconst startLine = rangeSelection\n\t\t? (rangeSelection.selectedLines.length === 0\n\t\t\t\t? (rangeStart ?? rangeSelection.firstLine)\n\t\t\t\t: rangeSelection.firstLine) - 1\n\t\t: offset\n\t\t\t? Math.max(0, offset - 1)\n\t\t\t: 0;\n\tconst endLine = limit !== undefined ? Math.min(startLine + limit, allLines.length) : allLines.length;\n\treturn { lines: rangeSelection?.selectedLines ?? allLines.slice(startLine, endLine), firstLine: startLine + 1 };\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"render-utils.js","sourceRoot":"","sources":["../../../src/core/tools/render-utils.ts"],"names":[],"mappings":"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","sourcesContent":["import * as os from \"node:os\";\nimport { pathToFileURL } from \"node:url\";\nimport type { ImageContent, TextContent } from \"@bastani/pi-ai/compat\";\nimport { getCapabilities, getImageDimensions, hyperlink, imageFallback } from \"@earendil-works/pi-tui\";\nimport type { ThemeColor } from \"../../modes/interactive/theme/theme.js\";\nimport { stripAnsi } from \"../../utils/ansi.ts\";\nimport { resolvePath } from \"../../utils/paths.ts\";\nimport { sanitizeBinaryOutput } from \"../../utils/shell.ts\";\n\nexport function shortenPath(path: unknown): string {\n\tif (typeof path !== \"string\") return \"\";\n\tconst home = os.homedir();\n\tif (path.startsWith(home)) {\n\t\treturn `~${path.slice(home.length)}`;\n\t}\n\treturn path;\n}\n\nexport function linkPath(styledText: string, rawPath: string, cwd: string): string {\n\tif (!getCapabilities().hyperlinks) return styledText;\n\tconst absolutePath = resolvePath(rawPath, cwd);\n\treturn hyperlink(styledText, pathToFileURL(absolutePath).href);\n}\n\nexport function renderToolPath(\n\trawPath: string | null,\n\ttheme: { fg: (name: ThemeColor, text: string) => string },\n\tcwd: string,\n\toptions?: { emptyFallback?: string },\n): string {\n\tif (rawPath === null) return invalidArgText(theme);\n\tconst value = rawPath || options?.emptyFallback;\n\tif (!value) return theme.fg(\"toolOutput\", \"...\");\n\treturn linkPath(theme.fg(\"accent\", shortenPath(value)), value, cwd);\n}\n\nexport function str(value: unknown): string | null {\n\tif (typeof value === \"string\") return value;\n\tif (value == null) return \"\";\n\treturn null;\n}\n\nexport function replaceTabs(text: string): string {\n\treturn text.replace(/\\t/g, \" \");\n}\n\nexport function normalizeDisplayText(text: string): string {\n\treturn text.replace(/\\r/g, \"\");\n}\n\nexport function getTextOutput(\n\tresult: { content: Array<{ type: string; text?: string; data?: string; mimeType?: string }> } | undefined,\n\tshowImages: boolean,\n): string {\n\tif (!result) return \"\";\n\n\tconst textBlocks = result.content.filter((c) => c.type === \"text\");\n\tconst imageBlocks = result.content.filter((c) => c.type === \"image\");\n\n\tlet output = textBlocks.map((c) => sanitizeBinaryOutput(stripAnsi(c.text || \"\")).replace(/\\r/g, \"\")).join(\"\\n\");\n\n\tconst caps = getCapabilities();\n\tif (imageBlocks.length > 0 && (!caps.images || !showImages)) {\n\t\tconst imageIndicators = imageBlocks\n\t\t\t.map((img) => {\n\t\t\t\tconst mimeType = img.mimeType ?? \"image/unknown\";\n\t\t\t\tconst dims =\n\t\t\t\t\timg.data && img.mimeType ? (getImageDimensions(img.data, img.mimeType) ?? undefined) : undefined;\n\t\t\t\treturn imageFallback(mimeType, dims);\n\t\t\t})\n\t\t\t.join(\"\\n\");\n\t\toutput = output ? `${output}\\n${imageIndicators}` : imageIndicators;\n\t}\n\n\treturn output;\n}\n\nexport type ToolRenderResultLike<TDetails> = {\n\tcontent: (TextContent | ImageContent)[];\n\tdetails: TDetails;\n};\n\nexport function invalidArgText(theme: { fg: (name: ThemeColor, text: string) => string }): string {\n\treturn theme.fg(\"error\", \"[invalid arg]\");\n}\n"]}
1
+ {"version":3,"file":"render-utils.js","sourceRoot":"","sources":["../../../src/core/tools/render-utils.ts"],"names":[],"mappings":"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","sourcesContent":["import * as os from \"node:os\";\nimport { pathToFileURL } from \"node:url\";\nimport type { ImageContent, TextContent } from \"@bastani/pi-ai/compat\";\nimport { getCapabilities, getImageDimensions, hyperlink, imageFallback } from \"@earendil-works/pi-tui\";\nimport type { ThemeColor } from \"../../modes/interactive/theme/theme.js\";\nimport { stripAnsi } from \"../../utils/ansi.js\";\nimport { resolvePath } from \"../../utils/paths.ts\";\nimport { sanitizeBinaryOutput } from \"../../utils/shell.ts\";\n\nexport function shortenPath(path: unknown): string {\n\tif (typeof path !== \"string\") return \"\";\n\tconst home = os.homedir();\n\tif (path.startsWith(home)) {\n\t\treturn `~${path.slice(home.length)}`;\n\t}\n\treturn path;\n}\n\nexport function linkPath(styledText: string, rawPath: string, cwd: string): string {\n\tif (!getCapabilities().hyperlinks) return styledText;\n\tconst absolutePath = resolvePath(rawPath, cwd);\n\treturn hyperlink(styledText, pathToFileURL(absolutePath).href);\n}\n\nexport function renderToolPath(\n\trawPath: string | null,\n\ttheme: { fg: (name: ThemeColor, text: string) => string },\n\tcwd: string,\n\toptions?: { emptyFallback?: string },\n): string {\n\tif (rawPath === null) return invalidArgText(theme);\n\tconst value = rawPath || options?.emptyFallback;\n\tif (!value) return theme.fg(\"toolOutput\", \"...\");\n\treturn linkPath(theme.fg(\"accent\", shortenPath(value)), value, cwd);\n}\n\nexport function str(value: unknown): string | null {\n\tif (typeof value === \"string\") return value;\n\tif (value == null) return \"\";\n\treturn null;\n}\n\nexport function replaceTabs(text: string): string {\n\treturn text.replace(/\\t/g, \" \");\n}\n\nexport function normalizeDisplayText(text: string): string {\n\treturn text.replace(/\\r/g, \"\");\n}\n\nexport function getTextOutput(\n\tresult: { content: Array<{ type: string; text?: string; data?: string; mimeType?: string }> } | undefined,\n\tshowImages: boolean,\n): string {\n\tif (!result) return \"\";\n\n\tconst textBlocks = result.content.filter((c) => c.type === \"text\");\n\tconst imageBlocks = result.content.filter((c) => c.type === \"image\");\n\n\tlet output = textBlocks.map((c) => sanitizeBinaryOutput(stripAnsi(c.text || \"\")).replace(/\\r/g, \"\")).join(\"\\n\");\n\n\tconst caps = getCapabilities();\n\tif (imageBlocks.length > 0 && (!caps.images || !showImages)) {\n\t\tconst imageIndicators = imageBlocks\n\t\t\t.map((img) => {\n\t\t\t\tconst mimeType = img.mimeType ?? \"image/unknown\";\n\t\t\t\tconst dims =\n\t\t\t\t\timg.data && img.mimeType ? (getImageDimensions(img.data, img.mimeType) ?? undefined) : undefined;\n\t\t\t\treturn imageFallback(mimeType, dims);\n\t\t\t})\n\t\t\t.join(\"\\n\");\n\t\toutput = output ? `${output}\\n${imageIndicators}` : imageIndicators;\n\t}\n\n\treturn output;\n}\n\nexport type ToolRenderResultLike<TDetails> = {\n\tcontent: (TextContent | ImageContent)[];\n\tdetails: TDetails;\n};\n\nexport function invalidArgText(theme: { fg: (name: ThemeColor, text: string) => string }): string {\n\treturn theme.fg(\"error\", \"[invalid arg]\");\n}\n"]}
@@ -1,6 +1,7 @@
1
1
  import type { AgentTool } from "@earendil-works/pi-agent-core";
2
2
  import { type Static, Type } from "typebox";
3
3
  import type { ToolDefinition } from "../extensions/types.ts";
4
+ import { type MutationRequesterResolver } from "./file-mutation-coordinator.ts";
4
5
  import { type HashlineSnapshotStore } from "./hashline.ts";
5
6
  declare const writeSchema: Type.TObject<{
6
7
  path: Type.TString;
@@ -20,19 +21,47 @@ export interface WriteToolDetails {
20
21
  };
21
22
  diagnostics?: unknown;
22
23
  }
24
+ /** Per-call options for {@link WriteOperations.writeFile}. */
25
+ export interface WriteFileOptions {
26
+ /**
27
+ * Create the file, failing with `EEXIST` if the path is already taken, rather than
28
+ * truncating whatever is there. Requested only when the tool has just established that the
29
+ * target was absent, so it closes the window between that check and the write.
30
+ *
31
+ * An implementation that cannot express exclusive create may ignore this and overwrite. It
32
+ * then loses only the race against writers outside Atomic, since the mutation queue already
33
+ * excludes writers inside it.
34
+ */
35
+ exclusive?: boolean;
36
+ }
23
37
  /**
24
38
  * Pluggable operations for the write tool.
25
39
  * Override these to delegate file writing to remote systems (for example SSH).
26
40
  */
27
41
  export interface WriteOperations {
28
42
  /** Write content to a file */
29
- writeFile: (absolutePath: string, content: string) => Promise<void>;
43
+ writeFile: (absolutePath: string, content: string, options?: WriteFileOptions) => Promise<void>;
30
44
  mkdir: (dir: string) => Promise<void>;
45
+ /**
46
+ * Current content of a path, or `undefined` when nothing is there.
47
+ *
48
+ * `write` reads before every write, to refuse generated files, to check that this session
49
+ * has observed what it is replacing, and to decide between creating and overwriting. Those
50
+ * checks have to see the same filesystem the write lands on, so this belongs here rather
51
+ * than being read from local disk behind an implementation's back.
52
+ *
53
+ * Report absence as `undefined` and **reject** for anything else. A path that exists but
54
+ * cannot be read is not the same as a free path: returning `undefined` for it would present
55
+ * an unreadable file as a fresh create and truncate it.
56
+ */
57
+ readFile: (absolutePath: string) => Promise<string | undefined>;
31
58
  }
32
59
  export interface WriteToolOptions {
33
60
  /** Custom operations for file writing. Default: local filesystem */
34
61
  operations?: WriteOperations;
35
62
  hashlineStore?: HashlineSnapshotStore;
63
+ /** Resolves who is being rejected when a mutation conflicts. Diagnostic only. */
64
+ resolveMutationRequester?: MutationRequesterResolver;
36
65
  }
37
66
  export declare function createWriteToolDefinition(cwd: string, options?: WriteToolOptions): ToolDefinition<typeof writeSchema, WriteToolDetails | undefined>;
38
67
  export declare function createWriteTool(cwd: string, options?: WriteToolOptions): AgentTool<typeof writeSchema>;
@@ -1 +1 @@
1
- {"version":3,"file":"write.d.ts","sourceRoot":"","sources":["../../../src/core/tools/write.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,+BAA+B,CAAC;AAW/D,OAAO,EAAE,KAAK,MAAM,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAG5C,OAAO,KAAK,EAAoB,cAAc,EAA2B,MAAM,wBAAwB,CAAC;AAGxG,OAAO,EAGN,KAAK,qBAAqB,EAI1B,MAAM,eAAe,CAAC;AAiBvB,QAAA,MAAM,WAAW;;;EAYhB,CAAC;AAEF,eAAO,MAAM,iCAAiC;sBACpC,+CAA+C;;EAI9C,CAAC;AACZ,MAAM,MAAM,cAAc,GAAG,MAAM,CAAC,OAAO,WAAW,CAAC,CAAC;AACxD,MAAM,WAAW,gBAAgB;IAChC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,IAAI,CAAC,EAAE;QAAE,UAAU,CAAC,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC;IACtD,WAAW,CAAC,EAAE,OAAO,CAAC;CACtB;AAED;;;GAGG;AACH,MAAM,WAAW,eAAe;IAC/B,8BAA8B;IAC9B,SAAS,EAAE,CAAC,YAAY,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACpE,KAAK,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACtC;AAwFD,MAAM,WAAW,gBAAgB;IAChC,oEAAoE;IACpE,UAAU,CAAC,EAAE,eAAe,CAAC;IAC7B,aAAa,CAAC,EAAE,qBAAqB,CAAC;CACtC;AA+ID,wBAAgB,yBAAyB,CACxC,GAAG,EAAE,MAAM,EACX,OAAO,CAAC,EAAE,gBAAgB,GACxB,cAAc,CAAC,OAAO,WAAW,EAAE,gBAAgB,GAAG,SAAS,CAAC,CAiNlE;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":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,+BAA+B,CAAC;AAW/D,OAAO,EAAE,KAAK,MAAM,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAG5C,OAAO,KAAK,EAAoB,cAAc,EAA2B,MAAM,wBAAwB,CAAC;AAExG,OAAO,EAQN,KAAK,yBAAyB,EAC9B,MAAM,gCAAgC,CAAC;AAExC,OAAO,EAGN,KAAK,qBAAqB,EAM1B,MAAM,eAAe,CAAC;AAiBvB,QAAA,MAAM,WAAW;;;EAYhB,CAAC;AAEF,eAAO,MAAM,iCAAiC;sBACpC,+CAA+C;;EAI9C,CAAC;AACZ,MAAM,MAAM,cAAc,GAAG,MAAM,CAAC,OAAO,WAAW,CAAC,CAAC;AACxD,MAAM,WAAW,gBAAgB;IAChC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,IAAI,CAAC,EAAE;QAAE,UAAU,CAAC,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC;IACtD,WAAW,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,8DAA8D;AAC9D,MAAM,WAAW,gBAAgB;IAChC;;;;;;;;OAQG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;CACpB;AAED;;;GAGG;AACH,MAAM,WAAW,eAAe;IAC/B,8BAA8B;IAC9B,SAAS,EAAE,CAAC,YAAY,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,gBAAgB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAChG,KAAK,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACtC;;;;;;;;;;;OAWG;IACH,QAAQ,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;CAChE;AAwGD,MAAM,WAAW,gBAAgB;IAChC,oEAAoE;IACpE,UAAU,CAAC,EAAE,eAAe,CAAC;IAC7B,aAAa,CAAC,EAAE,qBAAqB,CAAC;IACtC,iFAAiF;IACjF,wBAAwB,CAAC,EAAE,yBAAyB,CAAC;CACrD;AA+ID,wBAAgB,yBAAyB,CACxC,GAAG,EAAE,MAAM,EACX,OAAO,CAAC,EAAE,gBAAgB,GACxB,cAAc,CAAC,OAAO,WAAW,EAAE,gBAAgB,GAAG,SAAS,CAAC,CAqRlE;AAED,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,gBAAgB,GAAG,SAAS,CAAC,OAAO,WAAW,CAAC,CAEtG"}
@@ -5,8 +5,9 @@ import { Type } from "typebox";
5
5
  import { parenthesizedKeyHint } from "../../modes/interactive/components/keybinding-hints.js";
6
6
  import { getLanguageFromPath, highlightCode } from "../../modes/interactive/theme/theme.js";
7
7
  import { getRegisteredConflictBlocks, parseConflictBlocks } from "./conflict-registry.js";
8
+ import { assertPriorSessionObservation, computeLiveState, FileMutationConflict, filesystemErrorCode, isExclusiveCreateCollision, isMissingTargetError, } from "./file-mutation-coordinator.js";
8
9
  import { withFileMutationQueue } from "./file-mutation-queue.js";
9
- import { createHashlineSnapshotStore, formatHashlineContent, recordHashlineSnapshot, stripKnownHashlineCopiedContent, stripKnownHashlineCopiedContentWithMeta, } from "./hashline.js";
10
+ import { createHashlineSnapshotStore, formatHashlineContent, hashlineStoreKey, normalizeHashlineContent, recordHashlineSnapshot, stripKnownHashlineCopiedContent, stripKnownHashlineCopiedContentWithMeta, } from "./hashline.js";
10
11
  import { resolveToCwd } from "./path-utils.js";
11
12
  import { invalidArgText, normalizeDisplayText, replaceTabs, shortenPath, str } from "./render-utils.js";
12
13
  import { parseArchiveSelector, parseSqliteSelector, resolveArchiveSelector, resolveInternalSelector, sqliteSelectorForPath, writeArchiveSelector, writeInternalSelector, writeSqliteSelector, } from "./resource-selectors.js";
@@ -114,8 +115,25 @@ function hashlineHeaderForWrite(path, cwd, content, store) {
114
115
  return `[${snapshot.displayPath}#${snapshot.tag}]`;
115
116
  }
116
117
  const defaultWriteOperations = {
117
- writeFile: (path, content) => fsWriteFile(path, content, "utf-8"),
118
+ // `wx` is `O_CREAT | O_EXCL`, so the kernel decides the create race rather than this
119
+ // process. Without it the absence check above the write is advisory only.
120
+ writeFile: (path, content, options) => options?.exclusive
121
+ ? fsWriteFile(path, content, { encoding: "utf-8", flag: "wx" })
122
+ : fsWriteFile(path, content, "utf-8"),
118
123
  mkdir: (dir) => fsMkdir(dir, { recursive: true }).then(() => { }),
124
+ readFile: async (path) => {
125
+ try {
126
+ return await fsReadFile(path, "utf8");
127
+ }
128
+ catch (error) {
129
+ // Only a genuinely free path becomes `undefined`. A directory, a locked file, or a
130
+ // permissions failure keeps throwing, so the caller reports it rather than treating
131
+ // an occupied path as available and truncating it.
132
+ if (isMissingTargetError(error))
133
+ return undefined;
134
+ throw error;
135
+ }
136
+ },
119
137
  };
120
138
  class WriteCallRenderComponent extends Text {
121
139
  constructor() {
@@ -234,6 +252,7 @@ function formatWriteResult(result, theme) {
234
252
  export function createWriteToolDefinition(cwd, options) {
235
253
  const ops = options?.operations ?? defaultWriteOperations;
236
254
  const hashlineStore = options?.hashlineStore ?? createHashlineSnapshotStore();
255
+ const resolveMutationRequester = options?.resolveMutationRequester;
237
256
  return {
238
257
  name: "write",
239
258
  label: "write",
@@ -242,7 +261,7 @@ export function createWriteToolDefinition(cwd, options) {
242
261
  promptGuidelines: [...writeToolSystemPromptContribution.guidelines],
243
262
  constrainedSampling: { type: "json_schema", strict: "prefer" },
244
263
  parameters: writeSchema,
245
- async execute(_toolCallId, { path, content }, signal, _onUpdate, ctx) {
264
+ async execute(toolCallId, { path, content }, signal, _onUpdate, ctx) {
246
265
  const resourceCtx = ctx;
247
266
  const executionCwd = ctx?.cwd || cwd;
248
267
  const archive = parseArchiveSelector(path);
@@ -321,7 +340,7 @@ export function createWriteToolDefinition(cwd, options) {
321
340
  if (/^[a-z]+:\/\//i.test(path)) {
322
341
  const sourcePath = path.startsWith("local://") ? resolveInternalSelector(path, executionCwd) : undefined;
323
342
  if (sourcePath)
324
- return createWriteToolDefinition(executionCwd, options).execute(_toolCallId, { path: sourcePath, content }, signal, _onUpdate, ctx);
343
+ return createWriteToolDefinition(executionCwd, { ...options, hashlineStore }).execute(toolCallId, { path: sourcePath, content }, signal, _onUpdate, ctx);
325
344
  const stripped = stripKnownHashlineCopiedContentWithMeta(content, "", executionCwd, hashlineStore, path);
326
345
  await writeInternalSelector(path, executionCwd, stripped.content, resourceCtx);
327
346
  return {
@@ -336,7 +355,7 @@ export function createWriteToolDefinition(cwd, options) {
336
355
  }
337
356
  const absolutePath = resolveToCwd(path, executionCwd);
338
357
  const dir = dirname(absolutePath);
339
- return withFileMutationQueue(absolutePath, async () => {
358
+ return withFileMutationQueue(absolutePath, async (canonicalKey) => {
340
359
  // Do not reject from an abort event listener here: that would release the
341
360
  // mutation queue while an in-flight filesystem operation may still finish.
342
361
  // Checking signal.aborted after each await observes the same aborts while
@@ -349,13 +368,84 @@ export function createWriteToolDefinition(cwd, options) {
349
368
  // Create parent directories if needed.
350
369
  await ops.mkdir(dir);
351
370
  throwIfAborted();
352
- const existing = await fsReadFile(absolutePath, "utf8").catch(() => undefined);
371
+ const requester = resolveMutationRequester?.(toolCallId);
372
+ const conflict = (details) => new FileMutationConflict({
373
+ ...details,
374
+ path,
375
+ // Registration resolved this already, so a conflict names the target
376
+ // without paying for a second `realpath` while holding the lock.
377
+ canonicalKey,
378
+ ...(requester ? { requester } : {}),
379
+ });
380
+ let existing;
381
+ try {
382
+ existing = await ops.readFile(absolutePath);
383
+ }
384
+ catch (error) {
385
+ // The path is occupied by something this reader cannot open: a directory, a
386
+ // locked file, a permissions failure. Treating that as absence would present it
387
+ // as a fresh create and truncate it, so it is a conflict rather than a fallback.
388
+ const causeCode = filesystemErrorCode(error);
389
+ throw conflict({
390
+ reason: "target_unreadable",
391
+ // Nothing about the target can be described once the read fails, and
392
+ // inventing a size or a tag would be worse than omitting them.
393
+ ...(causeCode ? { causeCode } : {}),
394
+ });
395
+ }
353
396
  if (existing !== undefined && hasGeneratedMarker(existing))
354
397
  throw new Error(`Refusing to overwrite generated file: ${path}`);
398
+ if (existing !== undefined) {
399
+ // `write` replaces a whole file rather than anchoring to a section, so nothing
400
+ // in the call itself says what is being replaced. Having recorded that exact
401
+ // content is the only evidence this session ever saw it, and the store answers
402
+ // for this session alone, which is what makes another agent's file land here as
403
+ // a conflict instead of silently losing.
404
+ //
405
+ // The read above is reused deliberately: it already happened under the queue,
406
+ // so re-reading would only widen the window it closes.
407
+ assertPriorSessionObservation({
408
+ canonicalKey,
409
+ storeKey: hashlineStoreKey(absolutePath),
410
+ path,
411
+ store: hashlineStore.snapshots,
412
+ // Normalized because that is the form `record` stored. Comparing raw bytes
413
+ // would reject every CRLF file the session had read perfectly well.
414
+ live: normalizeHashlineContent(existing),
415
+ ...(requester ? { requester } : {}),
416
+ });
417
+ }
355
418
  const stripped = stripKnownHashlineCopiedContentWithMeta(content, absolutePath, executionCwd, hashlineStore, path);
356
419
  const writeContent = stripped.content;
357
- await ops.writeFile(absolutePath, writeContent);
420
+ if (existing === undefined) {
421
+ // Nothing was there a moment ago, so this is a create and says so to the
422
+ // filesystem. The mutation queue already excludes other Atomic writers; `O_EXCL`
423
+ // covers the rest, and turns what would have been a silent clobber of a file
424
+ // that appeared in between into a conflict that names it.
425
+ try {
426
+ await ops.writeFile(absolutePath, writeContent, { exclusive: true });
427
+ }
428
+ catch (error) {
429
+ if (!isExclusiveCreateCollision(error))
430
+ throw error;
431
+ const appeared = await ops.readFile(absolutePath).catch(() => undefined);
432
+ throw conflict({
433
+ reason: "target_exists",
434
+ // Only describe the file when it can still be read. `computeLiveState`
435
+ // renders absence for `undefined`, which would contradict the reason.
436
+ ...(appeared !== undefined ? { liveState: computeLiveState(appeared) } : {}),
437
+ });
438
+ }
439
+ }
440
+ else
441
+ await ops.writeFile(absolutePath, writeContent);
358
442
  invalidateNativeSearchCache(absolutePath);
443
+ // Recorded as soon as the bytes land, ahead of the abort check below, because an
444
+ // abort cancels reporting the result rather than undoing the write. Left until
445
+ // after it, a cancelled-but-written file would come back as someone else's work on
446
+ // the next overwrite. The hashline engine already records inside `commit` for the
447
+ // same reason.
448
+ const header = hashlineHeaderForWrite(absolutePath, executionCwd, writeContent, hashlineStore);
359
449
  let madeExecutable = false;
360
450
  if (writeContent.startsWith("#!")) {
361
451
  const mode = await fsStat(absolutePath)
@@ -367,7 +457,6 @@ export function createWriteToolDefinition(cwd, options) {
367
457
  }
368
458
  }
369
459
  throwIfAborted();
370
- const header = hashlineHeaderForWrite(absolutePath, executionCwd, writeContent, hashlineStore);
371
460
  return {
372
461
  content: [
373
462
  {