mixdog 1.2.4 → 1.2.6

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 (292) hide show
  1. package/package.json +1 -1
  2. package/scripts/lib/gate-scheduler.mjs +2 -2
  3. package/scripts/lib/run-node-tests.mjs +5 -14
  4. package/scripts/mobile-release.mjs +5 -4
  5. package/scripts/provider-pingpong-live.mjs +9 -9
  6. package/src/agents/advisor/AGENT.md +4 -4
  7. package/src/agents/advisor/agent.json +1 -1
  8. package/src/agents/reviewer/AGENT.md +2 -3
  9. package/src/agents/reviewer/agent.json +1 -1
  10. package/src/defaults/shipped-history.json +11 -0
  11. package/src/defaults/skills/browser-use/SKILL.md +2 -1
  12. package/src/defaults/skills/computer-use/SKILL.md +3 -1
  13. package/src/defaults/skills/visualize/SKILL.md +3 -2
  14. package/src/lib/rules-builder.cjs +1 -1
  15. package/src/output-styles/common.md +22 -5
  16. package/src/output-styles/detailed.md +7 -5
  17. package/src/output-styles/minimal.md +7 -3
  18. package/src/output-styles/simple.md +2 -3
  19. package/src/rules/agent/AGENT.md +3 -1
  20. package/src/rules/lead/LEAD.md +10 -7
  21. package/src/rules/shared/10-tool-workflow.md +2 -1
  22. package/src/rules/shared/60-verification.md +4 -5
  23. package/src/runtime/agent/orchestrator/agent-runtime/cache-strategy.mjs +2 -1
  24. package/src/runtime/agent/orchestrator/config.mjs +6 -0
  25. package/src/runtime/agent/orchestrator/context/skill-catalog.mjs +1 -1
  26. package/src/runtime/agent/orchestrator/internal-agents.mjs +10 -0
  27. package/src/runtime/agent/orchestrator/mcp/child-tree.mjs +53 -60
  28. package/src/runtime/agent/orchestrator/mcp/client.mjs +7 -4
  29. package/src/runtime/agent/orchestrator/mcp/oauth-callback.mjs +2 -3
  30. package/src/runtime/agent/orchestrator/providers/account-pool.mjs +9 -2
  31. package/src/runtime/agent/orchestrator/providers/anthropic-oauth-credentials.mjs +40 -19
  32. package/src/runtime/agent/orchestrator/providers/anthropic-oauth.mjs +3 -2
  33. package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-events/content-block-start.mjs +4 -1
  34. package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-events.mjs +2 -0
  35. package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn.mjs +3 -0
  36. package/src/runtime/agent/orchestrator/providers/anthropic-sse.mjs +2 -1
  37. package/src/runtime/agent/orchestrator/providers/anthropic.mjs +3 -1
  38. package/src/runtime/agent/orchestrator/providers/antigravity-oauth-login.mjs +1 -2
  39. package/src/runtime/agent/orchestrator/providers/catalog-deadline.mjs +163 -0
  40. package/src/runtime/agent/orchestrator/providers/catalog-failures.mjs +34 -0
  41. package/src/runtime/agent/orchestrator/providers/grok-oauth-login.mjs +38 -14
  42. package/src/runtime/agent/orchestrator/providers/lib/oauth-page.mjs +100 -26
  43. package/src/runtime/agent/orchestrator/providers/lib/send-callbacks.mjs +24 -0
  44. package/src/runtime/agent/orchestrator/providers/oauth-credential-probes.mjs +13 -0
  45. package/src/runtime/agent/orchestrator/providers/oauth-usage.mjs +2 -1
  46. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-send.mjs +1 -0
  47. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/chunk-events.mjs +4 -0
  48. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/stream-state.mjs +3 -1
  49. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream.mjs +2 -0
  50. package/src/runtime/agent/orchestrator/providers/openai-compat-models.mjs +49 -4
  51. package/src/runtime/agent/orchestrator/providers/openai-compat-presets.mjs +0 -7
  52. package/src/runtime/agent/orchestrator/providers/openai-compat-responses-events.mjs +7 -1
  53. package/src/runtime/agent/orchestrator/providers/openai-compat-responses.mjs +1 -0
  54. package/src/runtime/agent/orchestrator/providers/openai-compat-stream.mjs +2 -0
  55. package/src/runtime/agent/orchestrator/providers/openai-compat-xai-send.mjs +1 -0
  56. package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-events.mjs +5 -1
  57. package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state.mjs +11 -2
  58. package/src/runtime/agent/orchestrator/providers/openai-oauth-http-sse.mjs +1 -0
  59. package/src/runtime/agent/orchestrator/providers/openai-oauth-login.mjs +45 -16
  60. package/src/runtime/agent/orchestrator/providers/openai-oauth-ws.mjs +1 -0
  61. package/src/runtime/agent/orchestrator/providers/openai-ws-connect.mjs +196 -0
  62. package/src/runtime/agent/orchestrator/providers/openai-ws-pool.mjs +74 -9
  63. package/src/runtime/agent/orchestrator/providers/openai-ws-stream/event-switch.mjs +14 -1
  64. package/src/runtime/agent/orchestrator/providers/openai-ws-stream.mjs +2 -0
  65. package/src/runtime/agent/orchestrator/providers/opencode-go-oauth-login.mjs +194 -0
  66. package/src/runtime/agent/orchestrator/providers/opencode-go-oauth-tokens.mjs +353 -0
  67. package/src/runtime/agent/orchestrator/providers/opencode-go-oauth.mjs +293 -0
  68. package/src/runtime/agent/orchestrator/providers/opencode-go-usage.mjs +33 -100
  69. package/src/runtime/agent/orchestrator/providers/opencode-go.mjs +23 -14
  70. package/src/runtime/agent/orchestrator/providers/registry.mjs +41 -27
  71. package/src/runtime/agent/orchestrator/runtime-core/ask-user-tool-defs.mjs +2 -3
  72. package/src/runtime/agent/orchestrator/runtime-core/orchestration.mjs +3 -8
  73. package/src/runtime/agent/orchestrator/session/agent-pool-progress.mjs +15 -3
  74. package/src/runtime/agent/orchestrator/session/compact/execution-tail.mjs +74 -13
  75. package/src/runtime/agent/orchestrator/session/compact/forked-summary.mjs +102 -0
  76. package/src/runtime/agent/orchestrator/session/compact/runner.mjs +8 -2
  77. package/src/runtime/agent/orchestrator/session/compact/summary.mjs +16 -0
  78. package/src/runtime/agent/orchestrator/session/lifecycle-scan.mjs +9 -0
  79. package/src/runtime/agent/orchestrator/session/loop/fresh-context.mjs +39 -2
  80. package/src/runtime/agent/orchestrator/session/loop/tool-exec/before-hook.mjs +9 -19
  81. package/src/runtime/agent/orchestrator/session/loop/tool-exec.mjs +2 -3
  82. package/src/runtime/agent/orchestrator/session/manager/ask-turn-loop-options.mjs +3 -0
  83. package/src/runtime/agent/orchestrator/session/manager/ask-turn-steering-drain.mjs +13 -5
  84. package/src/runtime/agent/orchestrator/session/manager/pending-message-entry.mjs +10 -7
  85. package/src/runtime/agent/orchestrator/session/manager/pending-messages.mjs +62 -22
  86. package/src/runtime/agent/orchestrator/session/manager/runtime-liveness.mjs +23 -1
  87. package/src/runtime/agent/orchestrator/session/manager/session-close.mjs +81 -34
  88. package/src/runtime/agent/orchestrator/session/manager.mjs +2 -2
  89. package/src/runtime/agent/orchestrator/session/request-fork.mjs +47 -0
  90. package/src/runtime/agent/orchestrator/session/side-question-store.mjs +16 -1
  91. package/src/runtime/agent/orchestrator/session/side-question.mjs +5 -43
  92. package/src/runtime/agent/orchestrator/session/store/fs-probe.mjs +10 -0
  93. package/src/runtime/agent/orchestrator/session/store/lifecycle-barriers.mjs +73 -6
  94. package/src/runtime/agent/orchestrator/session/store/load-session.mjs +40 -0
  95. package/src/runtime/agent/orchestrator/session/store/save-fault.mjs +15 -0
  96. package/src/runtime/agent/orchestrator/session/store/session-paths.mjs +12 -0
  97. package/src/runtime/agent/orchestrator/session/store-agent-worker-header.mjs +36 -0
  98. package/src/runtime/agent/orchestrator/session/store-agent-worker-rows.mjs +255 -32
  99. package/src/runtime/agent/orchestrator/session/store-record-strict-scan.mjs +306 -0
  100. package/src/runtime/agent/orchestrator/session/store-summary-catalog.mjs +70 -21
  101. package/src/runtime/agent/orchestrator/session/store-summary-reader.mjs +46 -30
  102. package/src/runtime/agent/orchestrator/session/store-transcript-cache.mjs +144 -45
  103. package/src/runtime/agent/orchestrator/session/store-transcript-projection.mjs +32 -13
  104. package/src/runtime/agent/orchestrator/session/store-transcript-worker.mjs +364 -38
  105. package/src/runtime/agent/orchestrator/session/store.mjs +9 -2
  106. package/src/runtime/agent/orchestrator/session/task-wait-control.mjs +43 -12
  107. package/src/runtime/agent/orchestrator/session/tool-result-offload.mjs +23 -6
  108. package/src/runtime/agent/orchestrator/tools/builtin/arg-guard.mjs +12 -6
  109. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/backgrounded-result.mjs +13 -7
  110. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/bashism-rewrite.mjs +1 -1
  111. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/benign-exit.mjs +7 -1
  112. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/completed-result.mjs +40 -7
  113. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/deadline-plan.mjs +37 -34
  114. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/inline-hoist.mjs +1 -1
  115. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/spawn-env.mjs +0 -4
  116. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool.mjs +6 -0
  117. package/src/runtime/agent/orchestrator/tools/builtin/builtin-tools.mjs +29 -27
  118. package/src/runtime/agent/orchestrator/tools/builtin/external-tool-adapters.mjs +1 -1
  119. package/src/runtime/agent/orchestrator/tools/builtin/find-files-tool.mjs +28 -11
  120. package/src/runtime/agent/orchestrator/tools/builtin/git-command-policy.mjs +12 -3
  121. package/src/runtime/agent/orchestrator/tools/builtin/git-command-tool.mjs +203 -101
  122. package/src/runtime/agent/orchestrator/tools/builtin/git-repo-rw-lock.mjs +90 -41
  123. package/src/runtime/agent/orchestrator/tools/builtin/lib/list-helpers.mjs +17 -1
  124. package/src/runtime/agent/orchestrator/tools/builtin/lib/shell-delivery.mjs +199 -0
  125. package/src/runtime/agent/orchestrator/tools/builtin/lib/shell-task-output.mjs +165 -39
  126. package/src/runtime/agent/orchestrator/tools/builtin/list-tool.mjs +25 -13
  127. package/src/runtime/agent/orchestrator/tools/builtin/read-batch.mjs +7 -6
  128. package/src/runtime/agent/orchestrator/tools/builtin/read-formatting.mjs +19 -4
  129. package/src/runtime/agent/orchestrator/tools/builtin/read-line-collector.mjs +5 -3
  130. package/src/runtime/agent/orchestrator/tools/builtin/read-single-render.mjs +25 -7
  131. package/src/runtime/agent/orchestrator/tools/builtin/read-special-files.mjs +2 -1
  132. package/src/runtime/agent/orchestrator/tools/builtin/read-tool/batch-render.mjs +3 -1
  133. package/src/runtime/agent/orchestrator/tools/builtin/search-glob-tool.mjs +12 -5
  134. package/src/runtime/agent/orchestrator/tools/builtin/search-grep-tool.mjs +61 -22
  135. package/src/runtime/agent/orchestrator/tools/builtin/search-path-diagnostics.mjs +32 -8
  136. package/src/runtime/agent/orchestrator/tools/builtin/shell-analysis.mjs +193 -19
  137. package/src/runtime/agent/orchestrator/tools/builtin/shell-direct-exe.mjs +57 -7
  138. package/src/runtime/agent/orchestrator/tools/builtin/shell-jobs.mjs +119 -32
  139. package/src/runtime/agent/orchestrator/tools/builtin/shell-lossless-compact.mjs +26 -1
  140. package/src/runtime/agent/orchestrator/tools/builtin/shell-output.mjs +13 -28
  141. package/src/runtime/agent/orchestrator/tools/builtin/task-tool.mjs +90 -11
  142. package/src/runtime/agent/orchestrator/tools/builtin/wait-budgets.mjs +23 -0
  143. package/src/runtime/agent/orchestrator/tools/builtin.mjs +54 -10
  144. package/src/runtime/agent/orchestrator/tools/code-graph/build.mjs +22 -28
  145. package/src/runtime/agent/orchestrator/tools/code-graph/dispatch.mjs +11 -7
  146. package/src/runtime/agent/orchestrator/tools/destructive-warning.mjs +126 -9
  147. package/src/runtime/agent/orchestrator/tools/graph-manifest.json +13 -13
  148. package/src/runtime/agent/orchestrator/tools/lib/owned-shell-trees.mjs +15 -6
  149. package/src/runtime/agent/orchestrator/tools/lib/shell-descendants.mjs +40 -2
  150. package/src/runtime/agent/orchestrator/tools/lib/shell-run-background/promote-job.mjs +2 -2
  151. package/src/runtime/agent/orchestrator/tools/lib/shell-run-background/promotion-results.mjs +13 -3
  152. package/src/runtime/agent/orchestrator/tools/lib/shell-run-settle.mjs +2 -0
  153. package/src/runtime/agent/orchestrator/tools/lib/shell-run-state.mjs +3 -1
  154. package/src/runtime/agent/orchestrator/tools/patch/v4a-convert.mjs +1 -1
  155. package/src/runtime/agent/orchestrator/tools/shell-command.mjs +35 -4
  156. package/src/runtime/agent/orchestrator/tools/shell-policy.mjs +7 -2
  157. package/src/runtime/agent/orchestrator/tools/shell-powershell.mjs +39 -23
  158. package/src/runtime/agent/orchestrator/tools/shell-snapshot.mjs +6 -2
  159. package/src/runtime/agent/orchestrator/tools/spawn-manifest.json +13 -13
  160. package/src/runtime/attachments/office-extract.mjs +11 -9
  161. package/src/runtime/memory/lib/embedding-tokenizer.mjs +32 -18
  162. package/src/runtime/memory/lib/runtime-fetcher.mjs +1 -1
  163. package/src/runtime/memory/lib/tool-call-handler.mjs +7 -5
  164. package/src/runtime/office/authoring/pptx-script-normalize.mjs +11 -8
  165. package/src/runtime/office/core/tabular.mjs +1 -1
  166. package/src/runtime/office/design/library/design-template-inspect.mjs +7 -4
  167. package/src/runtime/office/portable/docx-formatting.mjs +1 -1
  168. package/src/runtime/office/portable/docx-runs.mjs +1 -1
  169. package/src/runtime/office/portable/docx-tracked-edits.mjs +2 -2
  170. package/src/runtime/office/portable/portable-docx-edits.mjs +11 -10
  171. package/src/runtime/office/portable/portable-docx-operations.mjs +21 -17
  172. package/src/runtime/office/portable/portable-docx-parts.mjs +15 -9
  173. package/src/runtime/office/portable/portable-docx-styles.mjs +4 -1
  174. package/src/runtime/office/portable/portable-docx-xml.mjs +9 -9
  175. package/src/runtime/office/portable/portable-opc.mjs +27 -13
  176. package/src/runtime/office/portable/portable-pivot.mjs +3 -3
  177. package/src/runtime/office/portable/portable-pptx-chart.mjs +3 -3
  178. package/src/runtime/office/portable/portable-pptx-charts.mjs +24 -18
  179. package/src/runtime/office/portable/portable-pptx-core.mjs +5 -5
  180. package/src/runtime/office/portable/portable-pptx-deck.mjs +8 -4
  181. package/src/runtime/office/portable/portable-pptx-package.mjs +7 -4
  182. package/src/runtime/office/portable/portable-pptx-shapes.mjs +18 -9
  183. package/src/runtime/office/portable/portable-sheet-parts.mjs +9 -3
  184. package/src/runtime/office/portable/portable-sheet-xml.mjs +5 -5
  185. package/src/runtime/office/portable/portable-xlsx-charts.mjs +4 -1
  186. package/src/runtime/office/portable/portable-xlsx-drawings.mjs +10 -6
  187. package/src/runtime/office/portable/portable-xlsx-operations.mjs +8 -5
  188. package/src/runtime/office/portable/portable-xlsx-pivot-ops.mjs +1 -1
  189. package/src/runtime/office/portable/portable-xlsx-reference-shift.mjs +11 -7
  190. package/src/runtime/office/portable/portable-xlsx-sheet-edits.mjs +6 -3
  191. package/src/runtime/office/portable/portable-xml.mjs +1 -1
  192. package/src/runtime/shared/atomic-file.mjs +22 -13
  193. package/src/runtime/shared/background-tasks.mjs +60 -20
  194. package/src/runtime/shared/child-spawn-gate.mjs +26 -16
  195. package/src/runtime/shared/config.mjs +0 -10
  196. package/src/runtime/shared/file-lock.mjs +7 -1
  197. package/src/runtime/shared/file-permissions-worker.mjs +38 -0
  198. package/src/runtime/shared/file-permissions.d.mts +19 -4
  199. package/src/runtime/shared/file-permissions.mjs +310 -4
  200. package/src/runtime/shared/git-runner-worker.mjs +6 -78
  201. package/src/runtime/shared/llm/http-agent.mjs +7 -3
  202. package/src/runtime/shared/llm/provider-catalog-registry.mjs +10 -0
  203. package/src/runtime/shared/llm/usage-accounting.mjs +2 -0
  204. package/src/runtime/shared/llm/usage-ledger-import.mjs +32 -3
  205. package/src/runtime/shared/llm/usage-ledger-rollup.mjs +12 -5
  206. package/src/runtime/shared/llm/usage-ledger-worker.mjs +1 -1
  207. package/src/runtime/shared/llm/usage-ledger.mjs +20 -5
  208. package/src/runtime/shared/memory-snapshot.mjs +5 -1
  209. package/src/runtime/shared/notify-trace.mjs +8 -1
  210. package/src/runtime/shared/pristine-execution-contract.json +5 -1
  211. package/src/runtime/shared/process-runner-worker.mjs +7 -0
  212. package/src/runtime/shared/process-runner.mjs +38 -0
  213. package/src/runtime/shared/provider-accounts.mjs +2 -1
  214. package/src/runtime/shared/provider-api-key.mjs +0 -1
  215. package/src/runtime/shared/read-row-numbers.mjs +1 -1
  216. package/src/runtime/shared/resource-admission.mjs +60 -18
  217. package/src/runtime/shared/run-child.mjs +84 -0
  218. package/src/runtime/shared/session-activity-signal.mjs +23 -0
  219. package/src/runtime/shared/shell-output-summary.mjs +23 -0
  220. package/src/runtime/shared/singleton-owner.mjs +126 -42
  221. package/src/runtime/shared/tool-output-limit.mjs +4 -2
  222. package/src/runtime/shared/tool-output-marker.mjs +58 -0
  223. package/src/runtime/shared/user-data-guard.mjs +28 -9
  224. package/src/runtime/shared/worktrees/activity-gate.mjs +33 -8
  225. package/src/runtime/shared/worktrees/git-head.mjs +20 -2
  226. package/src/runtime/shared/worktrees/lock.mjs +3 -2
  227. package/src/runtime/terminal-bridge/tool-defs.mjs +1 -1
  228. package/src/runtime/tidy/runners/biome.mjs +3 -1
  229. package/src/runtime/tidy/shadow.mjs +2 -1
  230. package/src/runtime/web-search/index.mjs +5 -7
  231. package/src/runtime/web-search/lib/formatter.mjs +42 -6
  232. package/src/runtime/web-search/tool-defs.mjs +6 -1
  233. package/src/session-runtime/lifecycle/session-switch/context-switch.mjs +4 -3
  234. package/src/session-runtime/lifecycle/session-switch/resume.mjs +7 -4
  235. package/src/session-runtime/lifecycle/session-switch/session-delete.mjs +3 -3
  236. package/src/session-runtime/lifecycle/shared.mjs +19 -2
  237. package/src/session-runtime/lifecycle/teardown/session-close.mjs +2 -0
  238. package/src/session-runtime/lifecycle/teardown.mjs +5 -2
  239. package/src/session-runtime/lifecycle-api.mjs +3 -1
  240. package/src/session-runtime/provider-auth/login.mjs +10 -6
  241. package/src/session-runtime/provider-auth/setup.mjs +19 -2
  242. package/src/session-runtime/provider-catalog-cache.mjs +101 -25
  243. package/src/session-runtime/provider-models/catalog-load.mjs +14 -3
  244. package/src/session-runtime/provider-models/row-hydration.mjs +4 -0
  245. package/src/session-runtime/provider-models.mjs +76 -10
  246. package/src/session-runtime/provider-readiness.mjs +4 -0
  247. package/src/session-runtime/services/agent-tool/close-flow.mjs +2 -1
  248. package/src/session-runtime/services/agent-tool/job-views/agent-list.mjs +10 -2
  249. package/src/session-runtime/services/agent-tool/job-views/session-progress.mjs +13 -4
  250. package/src/session-runtime/services/agent-tool/notify.mjs +15 -4
  251. package/src/session-runtime/services/agent-tool/restart-notify.mjs +134 -0
  252. package/src/session-runtime/services/agent-tool/send-flow.mjs +24 -1
  253. package/src/session-runtime/services/agent-tool/spawn-flow/deferred-spawn.mjs +2 -1
  254. package/src/session-runtime/services/agent-tool/spawn-flow/job-start.mjs +4 -3
  255. package/src/session-runtime/services/agent-tool/spawn-flow/spawn-run.mjs +5 -1
  256. package/src/session-runtime/services/agent-tool/tag-registry/tag-lookup.mjs +8 -3
  257. package/src/session-runtime/services/agent-tool/tag-registry.mjs +3 -0
  258. package/src/session-runtime/services/agent-tool/worker-index/row-shape.mjs +4 -0
  259. package/src/session-runtime/services/agent-tool/worker-index.mjs +44 -10
  260. package/src/session-runtime/services/agent-tool.mjs +20 -0
  261. package/src/session-runtime/services/provider-admin.mjs +92 -20
  262. package/src/session-runtime/services/usage-dashboard-model.mjs +2 -2
  263. package/src/session-runtime/services/usage-dashboard.mjs +27 -69
  264. package/src/session-runtime/turn/session-ops.mjs +2 -2
  265. package/src/session-runtime/turn/turn-run/ask-callbacks.mjs +1 -0
  266. package/src/session-runtime/usage-stats-api.mjs +6 -1
  267. package/src/standalone/channel-transport/http-routes.mjs +10 -9
  268. package/src/standalone/daemon-desktop-runtime.mjs +20 -7
  269. package/src/standalone/daemon-owner.mjs +117 -25
  270. package/src/standalone/daemon.mjs +43 -13
  271. package/src/standalone/desktop-service-registry.mjs +32 -5
  272. package/src/standalone/session-call-cache.mjs +6 -0
  273. package/src/standalone/session-protocol.mjs +1 -1
  274. package/src/standalone/session-service/retention/busy.mjs +7 -2
  275. package/src/standalone/session-transport/routes.mjs +7 -6
  276. package/src/tui/app/model-options.mjs +39 -2
  277. package/src/tui/app/model-picker.mjs +16 -2
  278. package/src/tui/app/provider-setup-picker.mjs +1 -2
  279. package/src/tui/dist/index.mjs +436 -123
  280. package/src/tui/session/notice-text.mjs +0 -1
  281. package/src/tui/session/session-api/intake/submission.mjs +7 -13
  282. package/src/tui/session/session-api/integrations.mjs +1 -5
  283. package/src/tui/session/session-flow/drain.mjs +8 -0
  284. package/src/tui/session/session-flow/steering.mjs +46 -0
  285. package/src/tui/session/session-flow.mjs +2 -0
  286. package/src/tui/session/turn-stream.mjs +33 -0
  287. package/src/tui/session/turn.mjs +30 -3
  288. package/src/ui/statusline.mjs +1 -6
  289. package/src/ui/streaming-markdown-heal.mjs +94 -25
  290. package/src/vendor/statusline/bin/statusline-route.mjs +0 -1
  291. package/src/vendor/statusline/src/gateway/route-meta.mjs +0 -1
  292. package/src/workflows/default/WORKFLOW.md +9 -13
@@ -112,7 +112,10 @@ export async function handleAddCommentOrDeleteComment(context, op) {
112
112
  `<p:cm authorId="${authorId}" dt="${new Date().toISOString().replace(/\.\d+Z$/, 'Z')}" idx="${index}">` +
113
113
  `<p:pos x="${Math.max(0, toEmu(op.left ?? 12))}" y="${Math.max(0, toEmu(op.top ?? 12))}"/>` +
114
114
  `<p:text>${xmlEncode(text)}</p:text></p:cm>`;
115
- zip.file(part, xml.replace('</p:cmLst>', `${entry}</p:cmLst>`));
115
+ zip.file(
116
+ part,
117
+ xml.replace('</p:cmLst>', () => `${entry}</p:cmLst>`)
118
+ );
116
119
  return { op: op.op, changed: true, slide: Number(op.slide), comment: index };
117
120
  }
118
121
 
@@ -338,10 +341,11 @@ export async function handleSetLayout(context, op) {
338
341
  const target = posix.relative('ppt/slides', layout.path);
339
342
  const pattern = /<Relationship\b[^>]*\bType="[^"]*\/slideLayout"[^>]*\/>/;
340
343
  const next = pattern.test(rels)
341
- ? rels.replace(pattern, (block) => block.replace(/\bTarget="[^"]*"/, `Target="${xmlEncode(target)}"`))
344
+ ? rels.replace(pattern, (block) => block.replace(/\bTarget="[^"]*"/, () => `Target="${xmlEncode(target)}"`))
342
345
  : rels.replace(
343
346
  '</Relationships>',
344
- `<Relationship Id="${nextRelationshipId(rels)}" Type="${OFFICE_RELATIONSHIP_BASE}/slideLayout" Target="${xmlEncode(target)}"/></Relationships>`
347
+ () =>
348
+ `<Relationship Id="${nextRelationshipId(rels)}" Type="${OFFICE_RELATIONSHIP_BASE}/slideLayout" Target="${xmlEncode(target)}"/></Relationships>`
345
349
  );
346
350
  zip.file(relationships, next);
347
351
  return { op: op.op, changed: true, slide: Number(op.slide), layout: layout.name || layout.type };
@@ -398,7 +402,7 @@ export async function handleSetTransition(context, op) {
398
402
  const anchorEnd = anchor.index + anchor[0].length;
399
403
  next = `${stripped.slice(0, anchorEnd)}${element}${stripped.slice(anchorEnd)}`;
400
404
  } else if (element) {
401
- next = stripped.replace('</p:sld>', `${element}</p:sld>`);
405
+ next = stripped.replace('</p:sld>', () => `${element}</p:sld>`);
402
406
  }
403
407
  zip.file(path, next);
404
408
  return { op: op.op, changed: true, slide: Number(op.slide), effect: requested };
@@ -138,7 +138,7 @@ export function writeSlideIdList(presentation, entries) {
138
138
  }
139
139
  const size = /<p:sldSz\b/.exec(presentation);
140
140
  if (size) return `${presentation.slice(0, size.index)}${element}${presentation.slice(size.index)}`;
141
- return presentation.replace('</p:presentation>', `${element}</p:presentation>`);
141
+ return presentation.replace('</p:presentation>', () => `${element}</p:presentation>`);
142
142
  }
143
143
 
144
144
  export function slideIdEntries(presentation) {
@@ -355,7 +355,7 @@ async function ensureNotesMaster(zip) {
355
355
  presentationPath,
356
356
  anchor
357
357
  ? `${presentation.slice(0, anchor.index)}${element}${presentation.slice(anchor.index)}`
358
- : presentation.replace('</p:presentation>', `${element}</p:presentation>`)
358
+ : presentation.replace('</p:presentation>', () => `${element}</p:presentation>`)
359
359
  );
360
360
  }
361
361
  return part;
@@ -387,7 +387,10 @@ export async function ensureCommentAuthor(zip, author, initials) {
387
387
  const entry =
388
388
  `<p:cmAuthor id="${id}" name="${xmlEncode(author)}" initials="${xmlEncode(initials)}"` +
389
389
  ` lastIdx="1" clrIdx="${id}"/>`;
390
- zip.file(part, xml.replace('</p:cmAuthorLst>', `${entry}</p:cmAuthorLst>`));
390
+ zip.file(
391
+ part,
392
+ xml.replace('</p:cmAuthorLst>', () => `${entry}</p:cmAuthorLst>`)
393
+ );
391
394
  return id;
392
395
  }
393
396
 
@@ -438,7 +441,7 @@ export async function copySlideNotes(zip, sourcePath, targetPath) {
438
441
  zip.file(
439
442
  partRelationshipPath(notes),
440
443
  relationships.replace(/<Relationship\b[^>]*\/>/g, (entry) =>
441
- /\bType="[^"]*\/slide"/.test(entry) ? entry.replace(/\bTarget="[^"]*"/, `Target="${target}"`) : entry
444
+ /\bType="[^"]*\/slide"/.test(entry) ? entry.replace(/\bTarget="[^"]*"/, () => `Target="${target}"`) : entry
442
445
  )
443
446
  );
444
447
  }
@@ -427,7 +427,10 @@ async function frameInsideSlide(context, shapeXml, extent) {
427
427
  const width = Math.min(Number(extent[1]), Math.max(1, room(slide.width, offset[1])));
428
428
  const height = Math.min(Number(extent[2]), Math.max(1, room(slide.height, offset[2])));
429
429
  if (width === Number(extent[1]) && height === Number(extent[2])) return { xml: shapeXml, extent, clamped: false };
430
- const xml = shapeXml.replace(/(<a:ext\b[^>]*\bcx=")\d+("[^>]*\bcy=")\d+(")/, `$1${width}$2${height}$3`);
430
+ const xml = shapeXml.replace(
431
+ /(<a:ext\b[^>]*\bcx=")\d+("[^>]*\bcy=")\d+(")/,
432
+ (__m, __1, __2, __3) => `${__1}${width}${__2}${height}${__3}`
433
+ );
431
434
  return { xml, extent: [extent[0], String(width), String(height)], clamped: true };
432
435
  }
433
436
 
@@ -475,7 +478,10 @@ async function replacedPicture(zip, path, shape, op) {
475
478
  const previous = /<a:blip\b[^>]*\br:embed="([^"]*)"/.exec(shape.xml)?.[1];
476
479
  if (!previous) throw new Error(`PPTX picture ${op.shape} on slide ${op.slide} has no image reference`);
477
480
  const media = await addSlideImage(zip, path, op.path);
478
- let updated = shape.xml.replace(/(<a:blip\b[^>]*\br:embed=")[^"]*(")/, `$1${media.relationshipId}$2`);
481
+ let updated = shape.xml.replace(
482
+ /(<a:blip\b[^>]*\br:embed=")[^"]*(")/,
483
+ (__m, __1, __2) => `${__1}${media.relationshipId}${__2}`
484
+ );
479
485
  const detail = { image: media.part, replaced: previous };
480
486
  // The frame is the page's design and the new picture rarely shares its
481
487
  // ratio: stretched into it the photograph comes out squeezed (the audit's
@@ -499,7 +505,7 @@ async function replacedPicture(zip, path, shape, op) {
499
505
  : '';
500
506
  updated = updated
501
507
  .replace(/<a:srcRect\b[^>]*\/>/, '')
502
- .replace(/(<a:blip\b[^>]*?(?:\/>|>[\s\S]*?<\/a:blip>))/, `$1${rect}`);
508
+ .replace(/(<a:blip\b[^>]*?(?:\/>|>[\s\S]*?<\/a:blip>))/, (__m, __1) => `${__1}${rect}`);
503
509
  detail.cropped = cropped;
504
510
  }
505
511
  // The frame keeps the description of the picture that used to be in it, so
@@ -508,8 +514,8 @@ async function replacedPicture(zip, path, shape, op) {
508
514
  if (altText) {
509
515
  const encoded = xmlEncode(altText);
510
516
  updated = /<p:cNvPr\b[^>]*\bdescr="/.test(updated)
511
- ? updated.replace(/(<p:cNvPr\b[^>]*\bdescr=")[^"]*(")/, `$1${encoded}$2`)
512
- : updated.replace(/(<p:cNvPr\b[^>]*?)(\/?>)/, `$1 descr="${encoded}"$2`);
517
+ ? updated.replace(/(<p:cNvPr\b[^>]*\bdescr=")[^"]*(")/, (__m, __1, __2) => `${__1}${encoded}${__2}`)
518
+ : updated.replace(/(<p:cNvPr\b[^>]*?)(\/?>)/, (__m, __1, __2) => `${__1} descr="${encoded}"${__2}`);
513
519
  detail.altText = altText;
514
520
  }
515
521
  return { updated, detail };
@@ -524,7 +530,7 @@ function filledCellProperties(tcPr, fill, anchor) {
524
530
  let attributes = open[1];
525
531
  if (anchor)
526
532
  attributes = /\banchor="/.test(attributes)
527
- ? attributes.replace(/\banchor="[^"]*"/, `anchor="${anchor}"`)
533
+ ? attributes.replace(/\banchor="[^"]*"/, () => `anchor="${anchor}"`)
528
534
  : `${attributes} anchor="${anchor}"`;
529
535
  let children = open[2] ? '' : tcPr.slice(open[0].length, tcPr.lastIndexOf('</a:tcPr>'));
530
536
  if (fill) {
@@ -568,7 +574,7 @@ export async function handleSetTableCellStyle(context, op) {
568
574
  else if (properties.fillColor) fill = solidFillXml(properties.fillColor);
569
575
  const anchor = textAnchor(properties.verticalAlignment);
570
576
  // The cell's own text frame may name an anchor too (this writer's add_table sets one); it follows the cell's.
571
- if (anchor) styled = styled.replace(/(<a:bodyPr\b[^>]*?\banchor=")[^"]*"/, `$1${anchor}"`);
577
+ if (anchor) styled = styled.replace(/(<a:bodyPr\b[^>]*?\banchor=")[^"]*"/, (__m, __1) => `${__1}${anchor}"`);
572
578
  if (fill || anchor) {
573
579
  if (!/<a:tcPr\b/.test(styled)) styled = styled.replace('</a:tc>', '<a:tcPr/></a:tc>');
574
580
  styled = styled.replace(/<a:tcPr\b[^>]*?(?:\/>|>[\s\S]*?<\/a:tcPr>)/, (tcPr) =>
@@ -758,7 +764,7 @@ export async function handleCropImage(context, op) {
758
764
  const rect = `<a:srcRect l="${edge(op.left)}" t="${edge(op.top)}" r="${edge(op.right)}" b="${edge(op.bottom)}"/>`;
759
765
  const updated = shape.xml
760
766
  .replace(/<a:srcRect\b[^>]*\/>/, '')
761
- .replace(/(<a:blip\b[^>]*?(?:\/>|>[\s\S]*?<\/a:blip>))/, `$1${rect}`);
767
+ .replace(/(<a:blip\b[^>]*?(?:\/>|>[\s\S]*?<\/a:blip>))/, (__m, __1) => `${__1}${rect}`);
762
768
  writeShape(context, slide, shape, updated);
763
769
  return { op: op.op, changed: true, slide: Number(op.slide), shape: Number(op.shape) };
764
770
  }
@@ -871,7 +877,10 @@ export async function handleAddAnimation(context, op) {
871
877
  const id = () => nextId++;
872
878
  const timing = timingWithAnimation(existing, animationNodes(shapeId, request, id), request.trigger, id);
873
879
  const stripped = current.replace(/<p:timing>[\s\S]*?<\/p:timing>/, '');
874
- zip.file(path, stripped.replace('</p:sld>', `${timing}</p:sld>`));
880
+ zip.file(
881
+ path,
882
+ stripped.replace('</p:sld>', () => `${timing}</p:sld>`)
883
+ );
875
884
  return {
876
885
  op: op.op,
877
886
  changed: true,
@@ -141,7 +141,7 @@ export async function writeWorksheetNote(zip, sheet, worksheetXml, { cell, text,
141
141
  authorId = authors.length - 1;
142
142
  comments = comments.replace(
143
143
  /<authors>[\s\S]*?<\/authors>/,
144
- `<authors>${authors.map((entry) => `<author>${xmlEncode(entry)}</author>`).join('')}</authors>`
144
+ () => `<authors>${authors.map((entry) => `<author>${xmlEncode(entry)}</author>`).join('')}</authors>`
145
145
  );
146
146
  }
147
147
  const pattern = new RegExp(`<comment\\b[^>]*\\bref="${parsed.ref}"[^>]*>[\\s\\S]*?<\\/comment>`);
@@ -155,11 +155,17 @@ export async function writeWorksheetNote(zip, sheet, worksheetXml, { cell, text,
155
155
  const entry =
156
156
  `<comment ref="${parsed.ref}" authorId="${authorId}">` +
157
157
  `<text><r><t xml:space="preserve">${xmlEncode(body)}</t></r></text></comment>`;
158
- zip.file(context.commentsPart, comments.replace('</commentList>', `${entry}</commentList>`));
158
+ zip.file(
159
+ context.commentsPart,
160
+ comments.replace('</commentList>', () => `${entry}</commentList>`)
161
+ );
159
162
  if (!existing) {
160
163
  const vml = await zipText(zip, context.vmlPart);
161
164
  const shapeId = 1025 + (vml.match(/<v:shape\b/g) || []).length;
162
- zip.file(context.vmlPart, vml.replace('</xml>', `${vmlNoteShape(shapeId, parsed)}</xml>`));
165
+ zip.file(
166
+ context.vmlPart,
167
+ vml.replace('</xml>', () => `${vmlNoteShape(shapeId, parsed)}</xml>`)
168
+ );
163
169
  }
164
170
  return { worksheet: context.worksheet, changed: true, cell: parsed.ref };
165
171
  }
@@ -90,7 +90,7 @@ export function upsertWorksheetSection(xml, name, element) {
90
90
  const found = worksheetSection(base, candidate);
91
91
  if (found) return `${base.slice(0, found.index)}${element}${base.slice(found.index)}`;
92
92
  }
93
- return base.replace(/<\/worksheet>\s*$/, `${element}</worksheet>`);
93
+ return base.replace(/<\/worksheet>\s*$/, () => `${element}</worksheet>`);
94
94
  }
95
95
 
96
96
  export function mergedRanges(xml) {
@@ -158,7 +158,7 @@ export function shiftWorksheetColumns(xml, from, count) {
158
158
  if (count < 0 && column >= from && column < from - count) continue;
159
159
  const next = column >= from ? column + count : column;
160
160
  if (next < 1) continue;
161
- kept.push(cell.xml.replace(/(\br=")[A-Za-z]+(\d+")/, `$1${columnLabel(next)}$2`));
161
+ kept.push(cell.xml.replace(/(\br=")[A-Za-z]+(\d+")/, (__m, __1, __2) => `${__1}${columnLabel(next)}${__2}`));
162
162
  }
163
163
  return `<row${open[1]}>${kept.join('')}</row>`;
164
164
  });
@@ -217,13 +217,13 @@ export function appendDifferentialFormat(stylesXml, { color = '', fillColor = ''
217
217
  if (found >= 0) return { xml: stylesXml, id: found };
218
218
  items.push(dxf);
219
219
  const element = `<dxfs count="${items.length}">${items.join('')}</dxfs>`;
220
- if (section) return { xml: stylesXml.replace(section[0], element), id: items.length - 1 };
220
+ if (section) return { xml: stylesXml.replace(section[0], () => element), id: items.length - 1 };
221
221
  const styles = /<cellStyles\b[^>]*?(?:\/>|>[\s\S]*?<\/cellStyles>)/.exec(stylesXml);
222
222
  if (styles) {
223
223
  const position = styles.index + styles[0].length;
224
224
  return { xml: `${stylesXml.slice(0, position)}${element}${stylesXml.slice(position)}`, id: items.length - 1 };
225
225
  }
226
- return { xml: stylesXml.replace('</styleSheet>', `${element}</styleSheet>`), id: items.length - 1 };
226
+ return { xml: stylesXml.replace('</styleSheet>', () => `${element}</styleSheet>`), id: items.length - 1 };
227
227
  }
228
228
 
229
229
  export function mergedCellAnchor(xml, reference) {
@@ -629,5 +629,5 @@ export function upsertDefinedName(xml, entry, matches) {
629
629
  if (!element) return xml;
630
630
  const calculation = /<calcPr\b[^>]*?(?:\/>|>[\s\S]*?<\/calcPr>)/.exec(xml);
631
631
  if (calculation) return `${xml.slice(0, calculation.index)}${element}${xml.slice(calculation.index)}`;
632
- return xml.replace(/<\/workbook>\s*$/, `${element}</workbook>`);
632
+ return xml.replace(/<\/workbook>\s*$/, () => `${element}</workbook>`);
633
633
  }
@@ -310,7 +310,10 @@ export async function addWorksheetChart(zip, sheet, xml, op, sheets) {
310
310
  const anchorCount = countDrawingAnchors(drawingXml);
311
311
  const width = spannedWidth(xml, op, await workbookDigitWidth(zip)) ?? op.width;
312
312
  const anchor = chartFrameAnchor({ ...op, width }, anchorCount, chartRelationshipId);
313
- zip.file(drawingPart, drawingXml.replace('</xdr:wsDr>', `${anchor}</xdr:wsDr>`));
313
+ zip.file(
314
+ drawingPart,
315
+ drawingXml.replace('</xdr:wsDr>', () => `${anchor}</xdr:wsDr>`)
316
+ );
314
317
  return {
315
318
  op: op.op,
316
319
  changed: true,
@@ -122,7 +122,10 @@ export async function addWorksheetImage(zip, sheet, xml, op) {
122
122
  ...imagePlacementSize(op, data),
123
123
  altText: op.altText,
124
124
  });
125
- zip.file(drawing.part, drawingXml.replace('</xdr:wsDr>', `${anchor}</xdr:wsDr>`));
125
+ zip.file(
126
+ drawing.part,
127
+ drawingXml.replace('</xdr:wsDr>', () => `${anchor}</xdr:wsDr>`)
128
+ );
126
129
  zip.file(sheet.path, xml);
127
130
  return {
128
131
  op: op.op,
@@ -266,15 +269,15 @@ export async function setWorksheetDrawing(zip, sheet, xml, op) {
266
269
  const width = op.width !== undefined ? Number(op.width) : Math.max(1, to.x - from.x);
267
270
  const height = op.height !== undefined ? Number(op.height) : Math.max(1, to.y - from.y);
268
271
  body = body
269
- .replace(/<xdr:from>[\s\S]*?<\/xdr:from>/, write('from', at(left, top)))
270
- .replace(/<xdr:to>[\s\S]*?<\/xdr:to>/, write('to', at(left + width, top + height)));
272
+ .replace(/<xdr:from>[\s\S]*?<\/xdr:from>/, () => write('from', at(left, top)))
273
+ .replace(/<xdr:to>[\s\S]*?<\/xdr:to>/, () => write('to', at(left + width, top + height)));
271
274
  }
272
275
  if (target.kind !== 'twoCellAnchor' && (op.left !== undefined || op.top !== undefined)) {
273
276
  if (target.kind === 'absoluteAnchor') {
274
277
  const current = /<xdr:pos\b([^>]*)\/>/.exec(body)?.[1] || '';
275
278
  const x = op.left !== undefined ? emu(op.left) : Number(xmlAttribute(current, 'x')) || 0;
276
279
  const y = op.top !== undefined ? emu(op.top) : Number(xmlAttribute(current, 'y')) || 0;
277
- body = body.replace(/<xdr:pos\b[^>]*\/>/, `<xdr:pos x="${x}" y="${y}"/>`);
280
+ body = body.replace(/<xdr:pos\b[^>]*\/>/, () => `<xdr:pos x="${x}" y="${y}"/>`);
278
281
  } else {
279
282
  if (op.left === undefined || op.top === undefined) {
280
283
  throw new Error(`Drawing "${label}" hangs off a cell; set_drawing needs left and top together to move it.`);
@@ -282,7 +285,8 @@ export async function setWorksheetDrawing(zip, sheet, xml, op) {
282
285
  // Measuring the offset from A1 makes the point given the point drawn.
283
286
  body = body.replace(
284
287
  /<xdr:from>[\s\S]*?<\/xdr:from>/,
285
- `<xdr:from><xdr:col>0</xdr:col><xdr:colOff>${emu(op.left)}</xdr:colOff>` +
288
+ () =>
289
+ `<xdr:from><xdr:col>0</xdr:col><xdr:colOff>${emu(op.left)}</xdr:colOff>` +
286
290
  `<xdr:row>0</xdr:row><xdr:rowOff>${emu(op.top)}</xdr:rowOff></xdr:from>`
287
291
  );
288
292
  }
@@ -291,7 +295,7 @@ export async function setWorksheetDrawing(zip, sheet, xml, op) {
291
295
  const current = /<xdr:ext\b([^>]*)\/>/.exec(body)?.[1] || '';
292
296
  const cx = op.width !== undefined ? emu(op.width) : Number(xmlAttribute(current, 'cx')) || 0;
293
297
  const cy = op.height !== undefined ? emu(op.height) : Number(xmlAttribute(current, 'cy')) || 0;
294
- body = body.replace(/<xdr:ext\b[^>]*\/>/, `<xdr:ext cx="${cx}" cy="${cy}"/>`);
298
+ body = body.replace(/<xdr:ext\b[^>]*\/>/, () => `<xdr:ext cx="${cx}" cy="${cy}"/>`);
295
299
  }
296
300
  if (body === target.body) throw new Error(`XLSX ${op.op} needs left, top, width, or height`);
297
301
  zip.file(part, `${drawingXml.slice(0, target.start)}${body}${drawingXml.slice(target.end)}`);
@@ -107,7 +107,8 @@ export async function addWorksheet(zip, name) {
107
107
  relsPath,
108
108
  rels.replace(
109
109
  '</Relationships>',
110
- `<Relationship Id="${relationshipId}" Type="${WORKSHEET_RELATIONSHIP}" Target="worksheets/sheet${ordinal}.xml"/></Relationships>`
110
+ () =>
111
+ `<Relationship Id="${relationshipId}" Type="${WORKSHEET_RELATIONSHIP}" Target="worksheets/sheet${ordinal}.xml"/></Relationships>`
111
112
  )
112
113
  );
113
114
  const sheetIds = [...workbook.matchAll(/<sheet\b[^>]*\bsheetId="(\d+)"/g)].map((match) => Number(match[1]));
@@ -117,7 +118,7 @@ export async function addWorksheet(zip, name) {
117
118
  if (!sheetsSection) throw new Error('Workbook is missing its sheet list');
118
119
  const next = sheetsSection[0].endsWith('/>')
119
120
  ? `<sheets>${entry}</sheets>`
120
- : sheetsSection[0].replace('</sheets>', `${entry}</sheets>`);
121
+ : sheetsSection[0].replace('</sheets>', () => `${entry}</sheets>`);
121
122
  zip.file(
122
123
  workbookPath,
123
124
  `${workbook.slice(0, sheetsSection.index)}${next}${workbook.slice(sheetsSection.index + sheetsSection[0].length)}`
@@ -126,7 +127,7 @@ export async function addWorksheet(zip, name) {
126
127
  if (!types.includes(`PartName="/${part}"`)) {
127
128
  zip.file(
128
129
  '[Content_Types].xml',
129
- types.replace('</Types>', `<Override PartName="/${part}" ContentType="${WORKSHEET_CONTENT_TYPE}"/></Types>`)
130
+ types.replace('</Types>', () => `<Override PartName="/${part}" ContentType="${WORKSHEET_CONTENT_TYPE}"/></Types>`)
130
131
  );
131
132
  }
132
133
  return { name: label, path: part, sheetId };
@@ -142,7 +143,7 @@ export async function renameWorksheet(zip, sheet, name, sheets) {
142
143
  const rewritten = await renameSheetReferences(zip, sheets, sheet, label, 'rename_sheet');
143
144
  const workbook = await zipText(zip, workbookPath);
144
145
  const match = pattern.exec(workbook);
145
- const replaced = match[0].replace(/\bname="[^"]*"/, `name="${xmlEncode(label)}"`);
146
+ const replaced = match[0].replace(/\bname="[^"]*"/, () => `name="${xmlEncode(label)}"`);
146
147
  zip.file(
147
148
  workbookPath,
148
149
  `${workbook.slice(0, match.index)}${replaced}${workbook.slice(match.index + match[0].length)}`
@@ -171,7 +172,9 @@ export async function deleteWorksheet(zip, sheets, sheet) {
171
172
  workbook = upsertDefinedName(workbook, '', (item) => localSheetId(item) === index);
172
173
  workbook = workbook.replace(/<definedName\b[^>]*?(?:\/>|>[\s\S]*?<\/definedName>)/g, (item) => {
173
174
  const local = localSheetId(item);
174
- return local !== null && local > index ? item.replace(/\blocalSheetId="\d+"/, `localSheetId="${local - 1}"`) : item;
175
+ return local !== null && local > index
176
+ ? item.replace(/\blocalSheetId="\d+"/, () => `localSheetId="${local - 1}"`)
177
+ : item;
175
178
  });
176
179
  zip.file(workbookPath, workbook);
177
180
  const relsPath = 'xl/_rels/workbook.xml.rels';
@@ -99,7 +99,7 @@ async function formatPivotValues(zip, xml, area, destination, anchor, layout) {
99
99
  if (!id) return;
100
100
  table = table.replace(
101
101
  new RegExp(`(<dataField\\b[^>]*\\bfld="${field}")([^>]*?)(\\/?>)`),
102
- `$1$2 numFmtId="${id}"$3`
102
+ (__m, __1, __2, __3) => `${__1}${__2} numFmtId="${id}"${__3}`
103
103
  );
104
104
  });
105
105
  zip.file(layout.tablePart, table);
@@ -320,8 +320,8 @@ function movedSheetRanges(xml, move, refused) {
320
320
  const count = (kept.match(/<brk\b/g) || []).length;
321
321
  if (!count) return '';
322
322
  const manual = (kept.match(/<brk\b[^>]*\bman="(?:1|true)"/g) || []).length;
323
- let breakAttributes = attributes.replace(/\bcount="\d+"/, `count="${count}"`);
324
- breakAttributes = breakAttributes.replace(/\bmanualBreakCount="\d+"/, `manualBreakCount="${manual}"`);
323
+ let breakAttributes = attributes.replace(/\bcount="\d+"/, () => `count="${count}"`);
324
+ breakAttributes = breakAttributes.replace(/\bmanualBreakCount="\d+"/, () => `manualBreakCount="${manual}"`);
325
325
  return `<${breaks}${breakAttributes}>${kept}</${breaks}>`;
326
326
  });
327
327
  return next;
@@ -340,8 +340,8 @@ function movedAnchors(drawing, move) {
340
340
  return { index, next: moved ? moved - 1 : move.from - 1, reset: !moved };
341
341
  };
342
342
  const written = (block, index, reset) => {
343
- const moved = block.replace(indexPattern, `<xdr:${tag}>${index}</xdr:${tag}>`);
344
- return reset ? moved.replace(offsetPattern, `<xdr:${tag}Off>0</xdr:${tag}Off>`) : moved;
343
+ const moved = block.replace(indexPattern, () => `<xdr:${tag}>${index}</xdr:${tag}>`);
344
+ return reset ? moved.replace(offsetPattern, () => `<xdr:${tag}Off>0</xdr:${tag}Off>`) : moved;
345
345
  };
346
346
  return drawing.replace(
347
347
  /<xdr:(oneCellAnchor|twoCellAnchor)\b([^>]*)>([\s\S]*?)<\/xdr:\1>/g,
@@ -379,7 +379,7 @@ function movedNoteShape(shape, move) {
379
379
  if (moved === null) return '';
380
380
  const delta = moved - 1 - index;
381
381
  return shape
382
- .replace(pattern, `<x:${tag}>${moved - 1}</x:${tag}>`)
382
+ .replace(pattern, () => `<x:${tag}>${moved - 1}</x:${tag}>`)
383
383
  .replace(/<x:Anchor>([^<]*)<\/x:Anchor>/, (_whole, anchor) => {
384
384
  const corners = anchor.split(',').map((value) => value.trim());
385
385
  for (const position of move.rows ? [2, 6] : [0, 4]) corners[position] = String(Number(corners[position]) + delta);
@@ -598,7 +598,7 @@ async function duplicateOwnedPart(zip, part, rewriteChart) {
598
598
  if (override)
599
599
  zip.file(
600
600
  '[Content_Types].xml',
601
- types.replace('</Types>', `<Override PartName="/${copy}" ContentType="${override[1]}"/></Types>`)
601
+ types.replace('</Types>', () => `<Override PartName="/${copy}" ContentType="${override[1]}"/></Types>`)
602
602
  );
603
603
  await duplicateOwnedRelationships(zip, part, copy, rewriteChart);
604
604
  return copy;
@@ -661,7 +661,11 @@ export async function copySheetParts(zip, sheets, source, copy) {
661
661
  `<definedName${setXmlAttribute(attributes, 'localSheetId', sheets.length)}>${xmlEncode(repointed)}</definedName>`
662
662
  );
663
663
  }
664
- if (added.length) zip.file(workbookPath, workbook.replace('</definedNames>', `${added.join('')}</definedNames>`));
664
+ if (added.length)
665
+ zip.file(
666
+ workbookPath,
667
+ workbook.replace('</definedNames>', () => `${added.join('')}</definedNames>`)
668
+ );
665
669
  }
666
670
 
667
671
  // Excel's record of the order it last calculated formula cells in, by address. Cells that moved leave it naming
@@ -393,7 +393,7 @@ export async function setWorksheetVisibility(zip, sheet, _xml, op) {
393
393
  const attrs =
394
394
  state === 'visible'
395
395
  ? match[0].replace(/\s*\bstate="[^"]*"/, '')
396
- : match[0].replace(/\s*\bstate="[^"]*"/, '').replace(/\/>$/, ` state="${state}"/>`);
396
+ : match[0].replace(/\s*\bstate="[^"]*"/, '').replace(/\/>$/, () => ` state="${state}"/>`);
397
397
  zip.file(WORKBOOK_PATH, `${workbook.slice(0, match.index)}${attrs}${workbook.slice(match.index + match[0].length)}`);
398
398
  return { op: op.op, changed: true, sheet: sheet.name, visibility };
399
399
  }
@@ -460,7 +460,7 @@ export async function setRowHeightOrColumnWidth(zip, sheet, xml, op) {
460
460
  (tag) =>
461
461
  tag
462
462
  .replace(/\s*\b(?:ht|customHeight)="[^"]*"/g, '')
463
- .replace(/(\/?>)$/, ` ht="${Math.round(size * 100) / 100}" customHeight="1"$1`),
463
+ .replace(/(\/?>)$/, (__m, __1) => ` ht="${Math.round(size * 100) / 100}" customHeight="1"${__1}`),
464
464
  true
465
465
  );
466
466
  }
@@ -606,7 +606,10 @@ export async function copyWorksheet(zip, sheet, xml, op, sheets) {
606
606
  const workbook = await zipText(zip, WORKBOOK_PATH);
607
607
  const sheetIds = [...workbook.matchAll(/<sheet\b[^>]*\bsheetId="(\d+)"/g)].map((match) => Number(match[1]));
608
608
  const entry = `<sheet name="${xmlEncode(label)}" sheetId="${Math.max(0, ...sheetIds) + 1}" r:id="${relationshipId}"/>`;
609
- zip.file(WORKBOOK_PATH, workbook.replace('</sheets>', `${entry}</sheets>`));
609
+ zip.file(
610
+ WORKBOOK_PATH,
611
+ workbook.replace('</sheets>', () => `${entry}</sheets>`)
612
+ );
610
613
  await copySheetParts(zip, sheets, sheet, { name: label, path: copyPart });
611
614
  return { op: op.op, changed: true, sheet: label };
612
615
  }
@@ -306,7 +306,7 @@ export function containerInner(xml, tag, from = 0) {
306
306
  export function setXmlAttribute(attributes, name, value) {
307
307
  const pattern = new RegExp(`\\b${name}="[^"]*"`, 'i');
308
308
  return pattern.test(attributes)
309
- ? attributes.replace(pattern, `${name}="${value}"`)
309
+ ? attributes.replace(pattern, () => `${name}="${value}"`)
310
310
  : `${attributes} ${name}="${value}"`;
311
311
  }
312
312
 
@@ -88,21 +88,30 @@ function nextRenameDelayMs(err, attempt, backoffs) {
88
88
  return backoffs[attempt] + Math.floor(Math.random() * Math.min(50, Math.max(1, backoffs[attempt])));
89
89
  }
90
90
 
91
+ /**
92
+ * Attempt `attempt` (0-based) of the renameWithRetry schedule: null when the
93
+ * rename landed, else the delay before the next attempt. Throws the rename's
94
+ * own error when that error or the attempt count ends the loop — the same
95
+ * final error renameWithRetrySync throws. A caller that must not block waits
96
+ * the delay asynchronously between attempts.
97
+ */
98
+ export function renameAttempt(src, dst, attempt, opts = {}) {
99
+ try {
100
+ renameSync(src, dst);
101
+ return null;
102
+ } catch (err) {
103
+ const delayMs = nextRenameDelayMs(err, attempt, renameBackoffs(opts));
104
+ if (delayMs === null) throw err;
105
+ return delayMs;
106
+ }
107
+ }
108
+
91
109
  export function renameWithRetrySync(src, dst, opts = {}) {
92
- const backoffs = renameBackoffs(opts);
93
- let lastErr = null;
94
- for (let attempt = 0; attempt <= backoffs.length; attempt++) {
95
- try {
96
- renameSync(src, dst);
97
- return true;
98
- } catch (err) {
99
- lastErr = err;
100
- const delayMs = nextRenameDelayMs(err, attempt, backoffs);
101
- if (delayMs === null) break;
102
- sleepSync(delayMs);
103
- }
110
+ for (let attempt = 0; ; attempt++) {
111
+ const delayMs = renameAttempt(src, dst, attempt, opts);
112
+ if (delayMs === null) return true;
113
+ sleepSync(delayMs);
104
114
  }
105
- throw lastErr;
106
115
  }
107
116
 
108
117
  async function renameWithRetry(src, dst, opts = {}) {