mixdog 0.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (404) hide show
  1. package/.claude-plugin/marketplace.json +31 -0
  2. package/.claude-plugin/plugin.json +20 -0
  3. package/.gitattributes +34 -0
  4. package/.mcp.json +14 -0
  5. package/ARCHITECTURE.md +77 -0
  6. package/CHANGELOG.md +7 -0
  7. package/CONTRIBUTING.md +45 -0
  8. package/DATA-FLOW.md +79 -0
  9. package/LICENSE +21 -0
  10. package/README.md +389 -0
  11. package/SECURITY.md +138 -0
  12. package/UNINSTALL.md +112 -0
  13. package/agents/maintenance.md +5 -0
  14. package/agents/memory-classification.md +30 -0
  15. package/agents/scheduler-task.md +18 -0
  16. package/agents/webhook-handler.md +27 -0
  17. package/agents/worker.md +24 -0
  18. package/bin/bridge +133 -0
  19. package/bin/statusline-launcher.mjs +78 -0
  20. package/bin/statusline-lib.mjs +550 -0
  21. package/bin/statusline.mjs +607 -0
  22. package/bun.lock +802 -0
  23. package/commands/config.md +16 -0
  24. package/commands/doctor.md +13 -0
  25. package/commands/setup.md +17 -0
  26. package/defaults/cycle3-review-prompt.md +90 -0
  27. package/defaults/hidden-roles.json +65 -0
  28. package/defaults/memory-chunk-prompt.md +63 -0
  29. package/defaults/memory-promote-prompt.md +135 -0
  30. package/defaults/mixdog-config.template.json +27 -0
  31. package/defaults/user-workflow.json +8 -0
  32. package/defaults/user-workflow.md +12 -0
  33. package/hooks/hooks.json +73 -0
  34. package/hooks/lib/active-instance.cjs +77 -0
  35. package/hooks/lib/permission-evaluator.cjs +411 -0
  36. package/hooks/lib/permission-route.cjs +63 -0
  37. package/hooks/lib/permission-rules.cjs +170 -0
  38. package/hooks/lib/settings-loader.cjs +116 -0
  39. package/hooks/post-tool-use.cjs +84 -0
  40. package/hooks/pre-mcp-sandbox.cjs +158 -0
  41. package/hooks/pre-tool-subagent.cjs +253 -0
  42. package/hooks/session-start.cjs +1372 -0
  43. package/hooks/turn-timer.cjs +82 -0
  44. package/lib/claude-md-writer.cjs +386 -0
  45. package/lib/config-cjs.cjs +61 -0
  46. package/lib/hook-pipe-path.cjs +10 -0
  47. package/lib/keychain-cjs.cjs +263 -0
  48. package/lib/plugin-paths.cjs +61 -0
  49. package/lib/rules-builder.cjs +241 -0
  50. package/lib/text-utils.cjs +61 -0
  51. package/native/README.md +117 -0
  52. package/native/prebuilt/linux-aarch64/mixdog-shim +0 -0
  53. package/native/prebuilt/linux-x86_64/mixdog-shim +0 -0
  54. package/native/prebuilt/macos-aarch64/mixdog-shim +0 -0
  55. package/native/prebuilt/macos-x86_64/mixdog-shim +0 -0
  56. package/native/prebuilt/windows-x86_64/mixdog-shim.exe +0 -0
  57. package/package.json +107 -0
  58. package/prompts/code-review.txt +16 -0
  59. package/prompts/security-audit.txt +17 -0
  60. package/rules/bridge/00-common.md +39 -0
  61. package/rules/bridge/20-skip-protocol.md +18 -0
  62. package/rules/bridge/30-explorer.md +33 -0
  63. package/rules/bridge/40-cycle1-agent.md +52 -0
  64. package/rules/bridge/41-cycle2-agent.md +62 -0
  65. package/rules/bridge/42-cycle3-agent.md +44 -0
  66. package/rules/lead/00-tool-lead.md +61 -0
  67. package/rules/lead/01-general.md +23 -0
  68. package/rules/lead/02-channels.md +49 -0
  69. package/rules/lead/03-team.md +27 -0
  70. package/rules/lead/04-workflow.md +20 -0
  71. package/rules/shared/00-language.md +14 -0
  72. package/rules/shared/01-tool.md +138 -0
  73. package/scripts/bootstrap.mjs +184 -0
  74. package/scripts/bridge-unify-smoke.mjs +308 -0
  75. package/scripts/build-runtime-linux.sh +348 -0
  76. package/scripts/build-runtime-macos.sh +217 -0
  77. package/scripts/build-runtime-windows.ps1 +242 -0
  78. package/scripts/builtin-utils-smoke.mjs +392 -0
  79. package/scripts/check-json.mjs +45 -0
  80. package/scripts/check-syntax-changed.mjs +102 -0
  81. package/scripts/check-syntax.mjs +58 -0
  82. package/scripts/code-graph-batch.test.mjs +33 -0
  83. package/scripts/config-preserve-smoke.mjs +180 -0
  84. package/scripts/doctor.mjs +484 -0
  85. package/scripts/edit-normalize-fuzz.mjs +130 -0
  86. package/scripts/edit-normalize-smoke.mjs +401 -0
  87. package/scripts/edit-operation-smoke.mjs +369 -0
  88. package/scripts/edit2-smoke.mjs +63 -0
  89. package/scripts/fuzzy-e2e.mjs +28 -0
  90. package/scripts/fuzzy-smoke.mjs +26 -0
  91. package/scripts/generate-runtime-manifest.mjs +166 -0
  92. package/scripts/guard-smoke.mjs +66 -0
  93. package/scripts/hidden-role-schema-smoke.mjs +162 -0
  94. package/scripts/hook-routing-smoke.mjs +29 -0
  95. package/scripts/inject-input.ps1 +204 -0
  96. package/scripts/io-complex-smoke.mjs +667 -0
  97. package/scripts/io-explore-bench.mjs +424 -0
  98. package/scripts/io-guardrails-smoke.mjs +205 -0
  99. package/scripts/io-mini-bench-baseline.json +11 -0
  100. package/scripts/io-mini-bench.mjs +216 -0
  101. package/scripts/io-route-harness.mjs +933 -0
  102. package/scripts/io-telemetry-report.mjs +691 -0
  103. package/scripts/mutation-bench.mjs +564 -0
  104. package/scripts/mutation-io-smoke.mjs +1081 -0
  105. package/scripts/native-patch-bridge-smoke.mjs +288 -0
  106. package/scripts/native-patch-smoke.mjs +304 -0
  107. package/scripts/patch-interior-context-smoke.mjs +49 -0
  108. package/scripts/patch-newline-utf8-smoke.mjs +157 -0
  109. package/scripts/perf-hook-smoke.mjs +71 -0
  110. package/scripts/permission-eval-smoke.mjs +426 -0
  111. package/scripts/prep-patch.mjs +53 -0
  112. package/scripts/prep-shim.mjs +96 -0
  113. package/scripts/provider-cache-smoke.mjs +687 -0
  114. package/scripts/report-runtime-health.mjs +132 -0
  115. package/scripts/run-mcp.mjs +1547 -0
  116. package/scripts/salvage-v4a-shatter.test.mjs +58 -0
  117. package/scripts/scoped-cache-io-smoke.mjs +103 -0
  118. package/scripts/shell-policy-round3-smoke.mjs +46 -0
  119. package/scripts/smoke-runtime-negative.ps1 +100 -0
  120. package/scripts/smoke-runtime-negative.sh +95 -0
  121. package/scripts/stall-policy-smoke.mjs +50 -0
  122. package/scripts/start-memory-worker.mjs +23 -0
  123. package/scripts/statusline-launcher-smoke.mjs +82 -0
  124. package/scripts/stress-atomic-write.mjs +1028 -0
  125. package/scripts/test-config-rmw-restore.mjs +122 -0
  126. package/scripts/test-fault-inject.mjs +164 -0
  127. package/scripts/test-large-file.mjs +174 -0
  128. package/scripts/tool-edge-smoke.mjs +209 -0
  129. package/scripts/uninstall.mjs +201 -0
  130. package/scripts/webhook-selfheal-smoke.mjs +29 -0
  131. package/scripts/write-overwrite-guard-smoke.mjs +56 -0
  132. package/server-main.mjs +3055 -0
  133. package/server.mjs +468 -0
  134. package/setup/config-merge.mjs +254 -0
  135. package/setup/install.mjs +120 -0
  136. package/setup/launch-core.mjs +507 -0
  137. package/setup/launch.mjs +101 -0
  138. package/setup/setup-server.mjs +3206 -0
  139. package/setup/setup.html +3693 -0
  140. package/skills/retro-skill-proposer/SKILL.md +92 -0
  141. package/skills/schedule-add/SKILL.md +77 -0
  142. package/skills/setup/SKILL.md +346 -0
  143. package/skills/webhook-add/SKILL.md +81 -0
  144. package/src/agent/bridge-stall-watchdog.mjs +337 -0
  145. package/src/agent/index.mjs +2138 -0
  146. package/src/agent/orchestrator/activity-bus.mjs +38 -0
  147. package/src/agent/orchestrator/ai-wrapped-dispatch.mjs +1010 -0
  148. package/src/agent/orchestrator/bridge-retry.mjs +220 -0
  149. package/src/agent/orchestrator/bridge-trace.mjs +583 -0
  150. package/src/agent/orchestrator/cache-mtime.mjs +58 -0
  151. package/src/agent/orchestrator/config.mjs +358 -0
  152. package/src/agent/orchestrator/context/collect.mjs +651 -0
  153. package/src/agent/orchestrator/dispatch-persist.mjs +549 -0
  154. package/src/agent/orchestrator/drain-registry.mjs +50 -0
  155. package/src/agent/orchestrator/explore-validator.mjs +8 -0
  156. package/src/agent/orchestrator/internal-roles.mjs +118 -0
  157. package/src/agent/orchestrator/internal-tools.mjs +88 -0
  158. package/src/agent/orchestrator/jobs.mjs +116 -0
  159. package/src/agent/orchestrator/mcp/client.mjs +364 -0
  160. package/src/agent/orchestrator/providers/anthropic-betas.mjs +21 -0
  161. package/src/agent/orchestrator/providers/anthropic-oauth.mjs +1745 -0
  162. package/src/agent/orchestrator/providers/anthropic.mjs +437 -0
  163. package/src/agent/orchestrator/providers/gemini.mjs +1175 -0
  164. package/src/agent/orchestrator/providers/grok-oauth.mjs +782 -0
  165. package/src/agent/orchestrator/providers/model-catalog.mjs +241 -0
  166. package/src/agent/orchestrator/providers/openai-compat.mjs +1467 -0
  167. package/src/agent/orchestrator/providers/openai-oauth-ws.mjs +1890 -0
  168. package/src/agent/orchestrator/providers/openai-oauth.mjs +1307 -0
  169. package/src/agent/orchestrator/providers/openai-ws.mjs +104 -0
  170. package/src/agent/orchestrator/providers/registry.mjs +192 -0
  171. package/src/agent/orchestrator/providers/retry-classifier.mjs +325 -0
  172. package/src/agent/orchestrator/session/abort-lookup.mjs +13 -0
  173. package/src/agent/orchestrator/session/cache/post-edit-marks.mjs +42 -0
  174. package/src/agent/orchestrator/session/cache/prefetch-cache.mjs +142 -0
  175. package/src/agent/orchestrator/session/cache/read-cache.mjs +319 -0
  176. package/src/agent/orchestrator/session/cache/scoped-cache-outcome.mjs +11 -0
  177. package/src/agent/orchestrator/session/cache/scoped-cache.mjs +361 -0
  178. package/src/agent/orchestrator/session/cache/util.mjs +49 -0
  179. package/src/agent/orchestrator/session/loop.mjs +1478 -0
  180. package/src/agent/orchestrator/session/manager.mjs +1975 -0
  181. package/src/agent/orchestrator/session/read-dedup.mjs +6 -0
  182. package/src/agent/orchestrator/session/result-classification.mjs +65 -0
  183. package/src/agent/orchestrator/session/save-session-worker.mjs +18 -0
  184. package/src/agent/orchestrator/session/store.mjs +624 -0
  185. package/src/agent/orchestrator/session/stream-watchdog.mjs +130 -0
  186. package/src/agent/orchestrator/session/tool-result-offload.mjs +166 -0
  187. package/src/agent/orchestrator/session/trim.mjs +491 -0
  188. package/src/agent/orchestrator/smart-bridge/CACHE-SHARD.md +115 -0
  189. package/src/agent/orchestrator/smart-bridge/bridge-llm.mjs +327 -0
  190. package/src/agent/orchestrator/smart-bridge/cache-obs.mjs +150 -0
  191. package/src/agent/orchestrator/smart-bridge/cache-strategy.mjs +228 -0
  192. package/src/agent/orchestrator/smart-bridge/index.mjs +215 -0
  193. package/src/agent/orchestrator/smart-bridge/profiles.mjs +37 -0
  194. package/src/agent/orchestrator/smart-bridge/registry.mjs +348 -0
  195. package/src/agent/orchestrator/smart-bridge/session-builder.mjs +116 -0
  196. package/src/agent/orchestrator/stall-policy.mjs +195 -0
  197. package/src/agent/orchestrator/tool-loop-guard.mjs +75 -0
  198. package/src/agent/orchestrator/tools/bash-policy-scan.mjs +77 -0
  199. package/src/agent/orchestrator/tools/bash-session.mjs +721 -0
  200. package/src/agent/orchestrator/tools/builtin/advisory-lock.mjs +171 -0
  201. package/src/agent/orchestrator/tools/builtin/arg-guard.mjs +455 -0
  202. package/src/agent/orchestrator/tools/builtin/atomic-write.mjs +236 -0
  203. package/src/agent/orchestrator/tools/builtin/bash-tool.mjs +480 -0
  204. package/src/agent/orchestrator/tools/builtin/binary-file.mjs +76 -0
  205. package/src/agent/orchestrator/tools/builtin/builtin-tools.mjs +256 -0
  206. package/src/agent/orchestrator/tools/builtin/cache-layers.mjs +386 -0
  207. package/src/agent/orchestrator/tools/builtin/cwd-utils.mjs +37 -0
  208. package/src/agent/orchestrator/tools/builtin/device-paths.mjs +154 -0
  209. package/src/agent/orchestrator/tools/builtin/diagnostics-tool.mjs +292 -0
  210. package/src/agent/orchestrator/tools/builtin/diff-utils.mjs +109 -0
  211. package/src/agent/orchestrator/tools/builtin/edit-base-guard.mjs +58 -0
  212. package/src/agent/orchestrator/tools/builtin/edit-byte-plan.mjs +240 -0
  213. package/src/agent/orchestrator/tools/builtin/edit-byte-utils.mjs +113 -0
  214. package/src/agent/orchestrator/tools/builtin/edit-commit.mjs +74 -0
  215. package/src/agent/orchestrator/tools/builtin/edit-context-utils.mjs +242 -0
  216. package/src/agent/orchestrator/tools/builtin/edit-diagnostics.mjs +211 -0
  217. package/src/agent/orchestrator/tools/builtin/edit-engine.mjs +1364 -0
  218. package/src/agent/orchestrator/tools/builtin/edit-failure-context.mjs +126 -0
  219. package/src/agent/orchestrator/tools/builtin/edit-hint.mjs +141 -0
  220. package/src/agent/orchestrator/tools/builtin/edit-match-utils.mjs +194 -0
  221. package/src/agent/orchestrator/tools/builtin/edit-partial-write.mjs +60 -0
  222. package/src/agent/orchestrator/tools/builtin/edit-stale-refresh.mjs +168 -0
  223. package/src/agent/orchestrator/tools/builtin/edit-tool.mjs +173 -0
  224. package/src/agent/orchestrator/tools/builtin/edit-utf8-guard.mjs +48 -0
  225. package/src/agent/orchestrator/tools/builtin/fs-reachability.mjs +48 -0
  226. package/src/agent/orchestrator/tools/builtin/fuzzy-match.mjs +99 -0
  227. package/src/agent/orchestrator/tools/builtin/glob-walk.mjs +170 -0
  228. package/src/agent/orchestrator/tools/builtin/grep-formatting.mjs +113 -0
  229. package/src/agent/orchestrator/tools/builtin/hash-utils.mjs +6 -0
  230. package/src/agent/orchestrator/tools/builtin/list-formatting.mjs +7 -0
  231. package/src/agent/orchestrator/tools/builtin/list-tool.mjs +593 -0
  232. package/src/agent/orchestrator/tools/builtin/native-edit-runner.mjs +89 -0
  233. package/src/agent/orchestrator/tools/builtin/notebook-edit-tool.mjs +300 -0
  234. package/src/agent/orchestrator/tools/builtin/open-config-tool.mjs +26 -0
  235. package/src/agent/orchestrator/tools/builtin/path-diagnostics.mjs +152 -0
  236. package/src/agent/orchestrator/tools/builtin/path-locks.mjs +35 -0
  237. package/src/agent/orchestrator/tools/builtin/path-utils.mjs +201 -0
  238. package/src/agent/orchestrator/tools/builtin/read-args.mjs +103 -0
  239. package/src/agent/orchestrator/tools/builtin/read-batch.mjs +172 -0
  240. package/src/agent/orchestrator/tools/builtin/read-constants.mjs +40 -0
  241. package/src/agent/orchestrator/tools/builtin/read-formatting.mjs +118 -0
  242. package/src/agent/orchestrator/tools/builtin/read-image-resize.mjs +189 -0
  243. package/src/agent/orchestrator/tools/builtin/read-image.mjs +88 -0
  244. package/src/agent/orchestrator/tools/builtin/read-lines.mjs +12 -0
  245. package/src/agent/orchestrator/tools/builtin/read-mode-tool.mjs +455 -0
  246. package/src/agent/orchestrator/tools/builtin/read-open.mjs +190 -0
  247. package/src/agent/orchestrator/tools/builtin/read-range-index.mjs +271 -0
  248. package/src/agent/orchestrator/tools/builtin/read-ranges.mjs +26 -0
  249. package/src/agent/orchestrator/tools/builtin/read-single-tool.mjs +728 -0
  250. package/src/agent/orchestrator/tools/builtin/read-snapshot-runtime.mjs +173 -0
  251. package/src/agent/orchestrator/tools/builtin/read-special-files.mjs +268 -0
  252. package/src/agent/orchestrator/tools/builtin/read-streaming.mjs +602 -0
  253. package/src/agent/orchestrator/tools/builtin/read-tool.mjs +530 -0
  254. package/src/agent/orchestrator/tools/builtin/read-windows.mjs +107 -0
  255. package/src/agent/orchestrator/tools/builtin/rename-tool.mjs +196 -0
  256. package/src/agent/orchestrator/tools/builtin/rg-runner.mjs +422 -0
  257. package/src/agent/orchestrator/tools/builtin/search-builders.mjs +158 -0
  258. package/src/agent/orchestrator/tools/builtin/search-tool.mjs +869 -0
  259. package/src/agent/orchestrator/tools/builtin/shell-analysis.mjs +653 -0
  260. package/src/agent/orchestrator/tools/builtin/shell-jobs.mjs +936 -0
  261. package/src/agent/orchestrator/tools/builtin/shell-output.mjs +36 -0
  262. package/src/agent/orchestrator/tools/builtin/shell-runtime.mjs +214 -0
  263. package/src/agent/orchestrator/tools/builtin/snapshot-helpers.mjs +143 -0
  264. package/src/agent/orchestrator/tools/builtin/snapshot-store.mjs +206 -0
  265. package/src/agent/orchestrator/tools/builtin/snapshot-validation.mjs +98 -0
  266. package/src/agent/orchestrator/tools/builtin/text-stats.mjs +69 -0
  267. package/src/agent/orchestrator/tools/builtin/windows-roots.mjs +23 -0
  268. package/src/agent/orchestrator/tools/builtin/write-tool.mjs +401 -0
  269. package/src/agent/orchestrator/tools/builtin.mjs +500 -0
  270. package/src/agent/orchestrator/tools/code-graph-prewarm-worker.mjs +39 -0
  271. package/src/agent/orchestrator/tools/code-graph-tool-defs.mjs +24 -0
  272. package/src/agent/orchestrator/tools/code-graph.mjs +4095 -0
  273. package/src/agent/orchestrator/tools/cwd-tool.mjs +298 -0
  274. package/src/agent/orchestrator/tools/destructive-warning.mjs +323 -0
  275. package/src/agent/orchestrator/tools/edit-normalize.mjs +603 -0
  276. package/src/agent/orchestrator/tools/env-scrub.mjs +100 -0
  277. package/src/agent/orchestrator/tools/graph-binary-fetcher.mjs +144 -0
  278. package/src/agent/orchestrator/tools/graph-manifest.json +26 -0
  279. package/src/agent/orchestrator/tools/host-input.mjs +204 -0
  280. package/src/agent/orchestrator/tools/mutation-content-cache.mjs +67 -0
  281. package/src/agent/orchestrator/tools/mutation-planner.mjs +75 -0
  282. package/src/agent/orchestrator/tools/next-call-utils.mjs +48 -0
  283. package/src/agent/orchestrator/tools/patch-binary-fetcher.mjs +133 -0
  284. package/src/agent/orchestrator/tools/patch-manifest.json +26 -0
  285. package/src/agent/orchestrator/tools/patch-tool-defs.mjs +20 -0
  286. package/src/agent/orchestrator/tools/patch.mjs +2754 -0
  287. package/src/agent/orchestrator/tools/progress-message.mjs +118 -0
  288. package/src/agent/orchestrator/tools/result-compression.mjs +279 -0
  289. package/src/agent/orchestrator/tools/shell-command.mjs +865 -0
  290. package/src/agent/orchestrator/tools/shell-exec-policy.mjs +89 -0
  291. package/src/agent/orchestrator/tools/shell-policy-danger-target.mjs +27 -0
  292. package/src/agent/orchestrator/tools/shell-policy-imports.mjs +7 -0
  293. package/src/agent/orchestrator/tools/shell-policy.mjs +345 -0
  294. package/src/agent/orchestrator/tools/shell-snapshot.mjs +313 -0
  295. package/src/agent/orchestrator/workflow-store.mjs +93 -0
  296. package/src/agent/tool-defs.mjs +103 -0
  297. package/src/channels/backends/discord.mjs +784 -0
  298. package/src/channels/data/voice-runtime-manifest.json +138 -0
  299. package/src/channels/index.mjs +3229 -0
  300. package/src/channels/lib/cli-worker-host.mjs +12 -0
  301. package/src/channels/lib/config-lock.mjs +13 -0
  302. package/src/channels/lib/config.mjs +292 -0
  303. package/src/channels/lib/drop-trace.mjs +71 -0
  304. package/src/channels/lib/event-pipeline.mjs +81 -0
  305. package/src/channels/lib/event-queue.mjs +345 -0
  306. package/src/channels/lib/executor.mjs +168 -0
  307. package/src/channels/lib/format.mjs +188 -0
  308. package/src/channels/lib/holidays.mjs +138 -0
  309. package/src/channels/lib/hook-pipe-server.mjs +802 -0
  310. package/src/channels/lib/interaction-workflows.mjs +184 -0
  311. package/src/channels/lib/memory-client.mjs +149 -0
  312. package/src/channels/lib/output-forwarder.mjs +765 -0
  313. package/src/channels/lib/runtime-paths.mjs +479 -0
  314. package/src/channels/lib/scheduler.mjs +723 -0
  315. package/src/channels/lib/session-control.mjs +36 -0
  316. package/src/channels/lib/session-discovery.mjs +103 -0
  317. package/src/channels/lib/settings.mjs +11 -0
  318. package/src/channels/lib/state-file.mjs +68 -0
  319. package/src/channels/lib/status-snapshot.mjs +219 -0
  320. package/src/channels/lib/tool-format.mjs +140 -0
  321. package/src/channels/lib/transcript-discovery.mjs +195 -0
  322. package/src/channels/lib/voice-runtime-fetcher.mjs +734 -0
  323. package/src/channels/lib/webhook.mjs +1179 -0
  324. package/src/channels/lib/whisper-server.mjs +477 -0
  325. package/src/channels/tool-defs.mjs +170 -0
  326. package/src/daemon/host.mjs +118 -0
  327. package/src/daemon/mcp-transport.mjs +47 -0
  328. package/src/daemon/session.mjs +100 -0
  329. package/src/daemon/thin-client.mjs +71 -0
  330. package/src/daemon/transport.mjs +163 -0
  331. package/src/memory/data/runtime-manifest.json +40 -0
  332. package/src/memory/index.mjs +3305 -0
  333. package/src/memory/lib/agent-ipc.mjs +93 -0
  334. package/src/memory/lib/bridge-trace-queries.mjs +120 -0
  335. package/src/memory/lib/core-memory-store.mjs +330 -0
  336. package/src/memory/lib/embedding-provider.mjs +269 -0
  337. package/src/memory/lib/embedding-worker.mjs +323 -0
  338. package/src/memory/lib/llm-worker-host.mjs +17 -0
  339. package/src/memory/lib/memory-cycle.mjs +11 -0
  340. package/src/memory/lib/memory-cycle1.mjs +641 -0
  341. package/src/memory/lib/memory-cycle2.mjs +1284 -0
  342. package/src/memory/lib/memory-cycle3.mjs +540 -0
  343. package/src/memory/lib/memory-embed.mjs +299 -0
  344. package/src/memory/lib/memory-extraction.mjs +5 -0
  345. package/src/memory/lib/memory-maintenance-store.mjs +32 -0
  346. package/src/memory/lib/memory-ops-policy.mjs +190 -0
  347. package/src/memory/lib/memory-recall-id-patch.mjs +15 -0
  348. package/src/memory/lib/memory-recall-read-query.mjs +7 -0
  349. package/src/memory/lib/memory-recall-scope-filter.mjs +63 -0
  350. package/src/memory/lib/memory-recall-store.mjs +621 -0
  351. package/src/memory/lib/memory-retrievers.mjs +112 -0
  352. package/src/memory/lib/memory-score.mjs +71 -0
  353. package/src/memory/lib/memory-text-utils.mjs +58 -0
  354. package/src/memory/lib/memory.mjs +412 -0
  355. package/src/memory/lib/model-profile.mjs +85 -0
  356. package/src/memory/lib/pg/adapter.mjs +308 -0
  357. package/src/memory/lib/pg/process.mjs +360 -0
  358. package/src/memory/lib/pg/supervisor.mjs +396 -0
  359. package/src/memory/lib/project-id-resolver.mjs +86 -0
  360. package/src/memory/lib/runtime-fetcher.mjs +442 -0
  361. package/src/memory/lib/trace-store.mjs +728 -0
  362. package/src/memory/tool-defs.mjs +79 -0
  363. package/src/search/index.mjs +1173 -0
  364. package/src/search/lib/backends/anthropic-oauth.mjs +98 -0
  365. package/src/search/lib/backends/exa.mjs +50 -0
  366. package/src/search/lib/backends/firecrawl.mjs +61 -0
  367. package/src/search/lib/backends/gemini-api.mjs +83 -0
  368. package/src/search/lib/backends/grok-oauth.mjs +86 -0
  369. package/src/search/lib/backends/index.mjs +150 -0
  370. package/src/search/lib/backends/openai-api.mjs +144 -0
  371. package/src/search/lib/backends/openai-oauth.mjs +98 -0
  372. package/src/search/lib/backends/openai-web-search.mjs +76 -0
  373. package/src/search/lib/backends/tavily.mjs +55 -0
  374. package/src/search/lib/backends/xai-api.mjs +113 -0
  375. package/src/search/lib/cache.mjs +131 -0
  376. package/src/search/lib/config.mjs +192 -0
  377. package/src/search/lib/formatter.mjs +115 -0
  378. package/src/search/lib/provider-usage.mjs +67 -0
  379. package/src/search/lib/providers.mjs +47 -0
  380. package/src/search/lib/search-intent.mjs +109 -0
  381. package/src/search/lib/setup-handler.mjs +261 -0
  382. package/src/search/lib/state.mjs +201 -0
  383. package/src/search/lib/web-tools.mjs +1207 -0
  384. package/src/search/tool-defs.mjs +83 -0
  385. package/src/setup/defender-exclusion.mjs +183 -0
  386. package/src/shared/abort-controller.mjs +15 -0
  387. package/src/shared/atomic-file.mjs +420 -0
  388. package/src/shared/config.mjs +350 -0
  389. package/src/shared/daemon-recycle.mjs +108 -0
  390. package/src/shared/disable-claude-builtins.mjs +88 -0
  391. package/src/shared/err-text.mjs +12 -0
  392. package/src/shared/llm/cost.mjs +66 -0
  393. package/src/shared/llm/http-agent.mjs +123 -0
  394. package/src/shared/llm/index.mjs +41 -0
  395. package/src/shared/llm/pid-cleanup.mjs +27 -0
  396. package/src/shared/llm/usage-log.mjs +47 -0
  397. package/src/shared/plugin-paths.mjs +58 -0
  398. package/src/shared/schedules-store.mjs +70 -0
  399. package/src/shared/seed.mjs +119 -0
  400. package/src/shared/user-cwd.mjs +213 -0
  401. package/src/shared/user-data-guard.mjs +238 -0
  402. package/src/status/aggregator.mjs +584 -0
  403. package/src/status/server.mjs +413 -0
  404. package/tools.json +1653 -0
@@ -0,0 +1,420 @@
1
+ import {
2
+ closeSync,
3
+ existsSync,
4
+ fsyncSync,
5
+ linkSync,
6
+ mkdirSync,
7
+ openSync,
8
+ readFileSync,
9
+ renameSync,
10
+ statSync,
11
+ unlinkSync,
12
+ writeFileSync,
13
+ } from 'fs';
14
+ import { dirname, basename, join } from 'path';
15
+ import { randomBytes } from 'crypto';
16
+ import { execFileSync } from 'child_process';
17
+
18
+ const RETRY_CODES = new Set(['EPERM', 'EACCES', 'EBUSY', 'EEXIST']);
19
+ const LOCK_WAIT_CODES = new Set(['EEXIST', 'EPERM', 'EACCES', 'EBUSY']);
20
+ const DEFAULT_BACKOFFS_MS = Object.freeze([25, 50, 100, 200, 400, 800, 1200, 1600]);
21
+ const DEFAULT_LOCK_TIMEOUT_MS = 8000;
22
+
23
+ function sleepSync(ms) {
24
+ try {
25
+ const buf = new SharedArrayBuffer(4);
26
+ Atomics.wait(new Int32Array(buf), 0, 0, Math.max(1, Number(ms) || 1));
27
+ } catch {
28
+ const end = Date.now() + Math.max(1, Number(ms) || 1);
29
+ while (Date.now() < end) {}
30
+ }
31
+ }
32
+
33
+ export function renameWithRetrySync(src, dst, opts = {}) {
34
+ const backoffs = Array.isArray(opts.backoffs) && opts.backoffs.length > 0
35
+ ? opts.backoffs
36
+ : DEFAULT_BACKOFFS_MS;
37
+ let lastErr = null;
38
+ for (let attempt = 0; attempt <= backoffs.length; attempt++) {
39
+ try {
40
+ renameSync(src, dst);
41
+ return true;
42
+ } catch (err) {
43
+ lastErr = err;
44
+ if (!RETRY_CODES.has(err?.code) || attempt >= backoffs.length) break;
45
+ const jitter = Math.floor(Math.random() * Math.min(50, Math.max(1, backoffs[attempt])));
46
+ sleepSync(backoffs[attempt] + jitter);
47
+ }
48
+ }
49
+ throw lastErr;
50
+ }
51
+
52
+ export function withFileLockSync(lockPath, fn, opts = {}) {
53
+ const timeoutMs = Number.isFinite(opts.timeoutMs) ? opts.timeoutMs : DEFAULT_LOCK_TIMEOUT_MS;
54
+ const staleMs = Number.isFinite(opts.staleMs) ? opts.staleMs : 30000;
55
+ const deadline = Date.now() + timeoutMs;
56
+ mkdirSync(dirname(lockPath), { recursive: true });
57
+ let attempt = 0;
58
+ let lastErr = null;
59
+ while (true) {
60
+ let fd;
61
+ try {
62
+ fd = openSync(lockPath, 'wx');
63
+ } catch (err) {
64
+ lastErr = err;
65
+ if (!LOCK_WAIT_CODES.has(err?.code)) throw err;
66
+ try {
67
+ const st = statSync(lockPath);
68
+ if (Date.now() - st.mtimeMs > staleMs) {
69
+ // Only steal a stale lock when we can prove the owner is
70
+ // gone. Reading the pid from the lock file and probing it
71
+ // with kill(pid, 0) protects a slow-but-live holder from
72
+ // having its lock yanked out from under it; the next
73
+ // process that acquires the lock would otherwise race
74
+ // against the original holder and clobber its write.
75
+ //
76
+ // Two-waiter stale-reclaim race: a pure rename "claim" is
77
+ // not enough. A waiter that proved pid D dead can stall;
78
+ // another waiter can then remove D and acquire a live lock,
79
+ // and the stalled waiter would rename that live lock away.
80
+ // Instead, serialize stale removal behind a tiny pid-stamped
81
+ // reclaim guard, then re-read the lock while the stale file
82
+ // is still present at lockPath. If the owner token no longer
83
+ // matches the pid we proved dead, treat the holder as live
84
+ // and back off. We never move or unlink a mismatched live-
85
+ // token file. Guard cleanup is only a best-effort unblocker:
86
+ // path unlink is not a portable unlink-if-token-still-matches
87
+ // primitive, so live-lock safety rests on the lockPath token
88
+ // reverify immediately before the lockPath unlink below.
89
+ const deadPid = _readLockOwnerPid(lockPath);
90
+ if (deadPid !== null && _pidIsDead(deadPid)) {
91
+ const reclaim = _tryAcquireReclaimGuard(lockPath, staleMs);
92
+ if (reclaim !== null) {
93
+ let reclaimed = false;
94
+ try {
95
+ const currentSt = statSync(lockPath);
96
+ if (Date.now() - currentSt.mtimeMs > staleMs) {
97
+ const currentPid = _readLockOwnerPid(lockPath);
98
+ if (currentPid === deadPid && _pidIsDead(currentPid)) {
99
+ try { unlinkSync(lockPath); reclaimed = true; } catch {}
100
+ }
101
+ }
102
+ } finally {
103
+ _releaseReclaimGuard(reclaim);
104
+ }
105
+ if (reclaimed) continue;
106
+ }
107
+ }
108
+ }
109
+ } catch {}
110
+ if (Date.now() >= deadline) break;
111
+ const base = DEFAULT_BACKOFFS_MS[Math.min(attempt, DEFAULT_BACKOFFS_MS.length - 1)];
112
+ const jitter = Math.floor(Math.random() * Math.min(75, Math.max(1, base)));
113
+ sleepSync(Math.min(Math.max(1, deadline - Date.now()), base + jitter));
114
+ attempt += 1;
115
+ continue;
116
+ }
117
+ // Stamp our pid into the lock so stale-lock recovery and the
118
+ // finally-unlink below can verify ownership instead of blindly
119
+ // deleting whatever lock file happens to be at this path.
120
+ try { writeFileSync(fd, `${process.pid} ${Date.now()}\n`, 'utf8'); } catch {}
121
+ // For secret-bearing critical sections, the lock file sits beside
122
+ // the secret in the same (shared-home) directory; clamp it owner-only
123
+ // too. Fail-closed: an unenforceable ACL aborts before fn() runs.
124
+ if (opts.secret === true) _enforceOwnerOnlyAclWin32(lockPath);
125
+ try { return fn(); }
126
+ finally {
127
+ try { closeSync(fd); } catch {}
128
+ // Only unlink if we still own the lock. If our hold exceeded
129
+ // staleMs and another process already stole + replaced the
130
+ // file, unconditionally unlinking here would destroy the new
131
+ // owner's lock and break mutual exclusion for whoever is
132
+ // queued behind it.
133
+ try {
134
+ if (_lockOwnedByPid(lockPath, process.pid)) unlinkSync(lockPath);
135
+ } catch {}
136
+ }
137
+ }
138
+ const timeoutErr = new Error(`atomic lock timeout after ${timeoutMs}ms: ${lockPath}`);
139
+ timeoutErr.code = 'ELOCKTIMEOUT';
140
+ timeoutErr.cause = lastErr;
141
+ throw timeoutErr;
142
+ }
143
+
144
+ // Lock-ownership helpers. The lock file's first whitespace-separated
145
+ // token is the owner pid (see the writeFileSync above). Best-effort
146
+ // only: a parse failure or stat error is treated as "not ours" /
147
+ // "owner unknown" so we err on the side of NOT stealing.
148
+ function _readLockOwnerPid(lockPath) {
149
+ try {
150
+ const raw = readFileSync(lockPath, 'utf8');
151
+ const tok = String(raw).trim().split(/\s+/)[0];
152
+ const pid = Number.parseInt(tok, 10);
153
+ return Number.isFinite(pid) && pid > 0 ? pid : null;
154
+ } catch {
155
+ return null;
156
+ }
157
+ }
158
+
159
+ function _pidIsDead(pid) {
160
+ // Unreadable / unparseable pid: be conservative — treat as alive so
161
+ // we wait instead of stealing.
162
+ if (pid === null) return false;
163
+ if (pid === process.pid) return false;
164
+ try {
165
+ process.kill(pid, 0);
166
+ return false; // signal delivered → process exists
167
+ } catch (err) {
168
+ // ESRCH = no such process → owner is gone, safe to steal.
169
+ // EPERM = process exists but we can't signal it → still alive,
170
+ // do NOT steal.
171
+ return err?.code === 'ESRCH';
172
+ }
173
+ }
174
+
175
+ function _lockOwnedByPid(lockPath, pid) {
176
+ return _readLockOwnerPid(lockPath) === pid;
177
+ }
178
+
179
+ function _reclaimGuardIsUnreadableAndStale(guardPath, staleMs) {
180
+ if (_readLockOwnerPid(guardPath) !== null) return false;
181
+ try {
182
+ const st = statSync(guardPath);
183
+ return Date.now() - st.mtimeMs > staleMs;
184
+ } catch {
185
+ return false;
186
+ }
187
+ }
188
+
189
+ function _reclaimGuardMatchesToken(guardPath, token) {
190
+ try {
191
+ return readFileSync(guardPath, 'utf8') === token;
192
+ } catch {
193
+ return false;
194
+ }
195
+ }
196
+
197
+ function _unlinkReclaimGuardIfPidMatches(guardPath, pid) {
198
+ if (_readLockOwnerPid(guardPath) !== pid) return false;
199
+ try { unlinkSync(guardPath); return true; } catch { return false; }
200
+ }
201
+
202
+ function _unlinkUnreadableStaleReclaimGuard(guardPath, staleMs) {
203
+ if (!_reclaimGuardIsUnreadableAndStale(guardPath, staleMs)) return false;
204
+ try { unlinkSync(guardPath); return true; } catch { return false; }
205
+ }
206
+
207
+ function _tryClearStaleReclaimGuard(guardPath, staleMs) {
208
+ const guardPid = _readLockOwnerPid(guardPath);
209
+ if (guardPid !== null) {
210
+ // Re-read the guard immediately before unlinking so a regenerated
211
+ // guard with a different owner is not removed by a stale decision.
212
+ // This is still not a serialized primitive: correctness comes from
213
+ // the lockPath owner-token reverify before unlinking lockPath, not
214
+ // from making guard cleanup itself authoritative.
215
+ if (_pidIsDead(guardPid)) _unlinkReclaimGuardIfPidMatches(guardPath, guardPid);
216
+ return;
217
+ }
218
+ // A crash between openSync('wx') and the pid write can leave an empty
219
+ // guard. There is no pid to prove dead, so clear only once the guard
220
+ // file itself is stale; any contender that proceeds must still prove
221
+ // the lockPath token dead before unlinking the lock.
222
+ _unlinkUnreadableStaleReclaimGuard(guardPath, staleMs);
223
+ }
224
+
225
+ function _tryAcquireReclaimGuard(lockPath, staleMs) {
226
+ const guardPath = `${lockPath}.reclaim`;
227
+ try {
228
+ const fd = openSync(guardPath, 'wx', 0o600);
229
+ const token = `${process.pid} ${Date.now()} ${randomBytes(8).toString('hex')}\n`;
230
+ try { writeFileSync(fd, token, 'utf8'); } catch {}
231
+ return { fd, guardPath, token };
232
+ } catch (err) {
233
+ if (LOCK_WAIT_CODES.has(err?.code)) {
234
+ _tryClearStaleReclaimGuard(guardPath, staleMs);
235
+ return null;
236
+ }
237
+ throw err;
238
+ }
239
+ }
240
+
241
+ function _releaseReclaimGuard(reclaim) {
242
+ try { closeSync(reclaim.fd); } catch {}
243
+ if (_reclaimGuardMatchesToken(reclaim.guardPath, reclaim.token)) {
244
+ try { unlinkSync(reclaim.guardPath); } catch {}
245
+ }
246
+ }
247
+
248
+ // ── Windows owner-only ACL enforcement (fail-closed) ─────────────────
249
+ // POSIX 0o600/0o700 mode bits are advisory-at-best on Windows: NTFS
250
+ // ignores them and the file inherits the parent ACL, which in shared or
251
+ // roaming-profile setups can be world-readable. For secret-bearing
252
+ // writes we MUST lock the file/dir down to the current user only. This
253
+ // is invariant-based and fail-closed: if we cannot prove the ACL was
254
+ // tightened (icacls missing, SystemRoot unset, user unresolvable, or a
255
+ // non-zero exit), we throw so the caller never persists a secret that
256
+ // might be left readable by other accounts.
257
+
258
+ let _cachedUserSid = null;
259
+
260
+ function _resolveCurrentUserPrincipal() {
261
+ // Prefer the current-user SID to avoid localized account-name parsing
262
+ // (e.g. "Administrators"/"Users" differ per locale). Resolve via
263
+ // `whoami /user` using the deterministic System32 binary path. This is
264
+ // fail-closed: if the SID cannot be proven we throw immediately rather
265
+ // than recovering from a (spoofable) account name.
266
+ const systemRoot = process.env.SystemRoot || process.env.windir;
267
+ if (systemRoot) {
268
+ const whoami = join(systemRoot, 'System32', 'whoami.exe');
269
+ if (existsSync(whoami)) {
270
+ try {
271
+ const out = execFileSync(whoami, ['/user', '/fo', 'csv', '/nh'], {
272
+ encoding: 'utf8',
273
+ stdio: ['ignore', 'pipe', 'ignore'],
274
+ windowsHide: true,
275
+ });
276
+ const m = String(out).match(/S-1-5-[0-9-]+/);
277
+ if (m) return m[0];
278
+ } catch {}
279
+ }
280
+ }
281
+ const err = new Error('cannot resolve current Windows user for owner-only ACL enforcement');
282
+ err.code = 'EACLNOUSER';
283
+ throw err;
284
+ }
285
+
286
+ function _icaclsPrincipal(principal) {
287
+ // icacls takes a raw SID prefixed with '*'; account names pass through.
288
+ return /^S-1-/.test(principal) ? `*${principal}` : principal;
289
+ }
290
+
291
+ function _enforceOwnerOnlyAclWin32(targetPath) {
292
+ if (process.platform !== 'win32') return;
293
+ const systemRoot = process.env.SystemRoot || process.env.windir;
294
+ if (!systemRoot) {
295
+ const err = new Error('SystemRoot not set; cannot locate icacls.exe for owner-only ACL enforcement');
296
+ err.code = 'EACLNOROOT';
297
+ throw err;
298
+ }
299
+ // DETERMINISTIC binary path — never rely on PATH lookup for a
300
+ // security-critical tool (PATH could resolve a planted icacls.exe).
301
+ const icacls = join(systemRoot, 'System32', 'icacls.exe');
302
+ if (!existsSync(icacls)) {
303
+ const err = new Error(`icacls.exe not found at ${icacls}; refusing to leave secret world-readable`);
304
+ err.code = 'EACLNOICACLS';
305
+ throw err;
306
+ }
307
+ if (_cachedUserSid === null) _cachedUserSid = _resolveCurrentUserPrincipal();
308
+ const principal = _icaclsPrincipal(_cachedUserSid);
309
+ try {
310
+ // STEP 1 — /reset discards ALL pre-existing EXPLICIT ACEs on the
311
+ // target, restoring it to the parent's inherited-only DACL. Without
312
+ // this, overwriting a previously-permissive file/dir keeps any
313
+ // explicit non-owner ACEs (which /inheritance:r alone does NOT
314
+ // touch — that flag only strips INHERITED ACEs), leaving the secret
315
+ // readable by others. execFileSync throws on a non-zero exit, which
316
+ // is exactly the fail-closed behaviour we want.
317
+ execFileSync(icacls, [targetPath, '/reset'], {
318
+ stdio: ['ignore', 'ignore', 'pipe'],
319
+ windowsHide: true,
320
+ });
321
+ // STEP 2 — /inheritance:r strips the now-inherited ACEs left by the
322
+ // reset; /grant:r replaces the principal's ACE so the resulting DACL
323
+ // grants ONLY the current user full control. After both steps no
324
+ // explicit or inherited non-owner ACE survives.
325
+ execFileSync(icacls, [targetPath, '/inheritance:r', '/grant:r', `${principal}:(F)`], {
326
+ stdio: ['ignore', 'ignore', 'pipe'],
327
+ windowsHide: true,
328
+ });
329
+ } catch (err) {
330
+ const e = new Error(`icacls failed to apply owner-only ACL to ${targetPath}: ${err?.message || err}`);
331
+ e.code = 'EACLFAIL';
332
+ e.cause = err;
333
+ throw e;
334
+ }
335
+ }
336
+
337
+ export function writeFileAtomicSync(filePath, data, opts = {}) {
338
+ const run = () => {
339
+ const dir = dirname(filePath);
340
+ mkdirSync(dir, { recursive: true });
341
+ const tmp = join(dir, `.${basename(filePath)}.${randomBytes(12).toString('hex')}.tmp`);
342
+ try {
343
+ const writeOpts = { encoding: opts.encoding || 'utf8', flag: 'wx', mode: opts.mode !== undefined ? opts.mode : 0o600 };
344
+ writeFileSync(tmp, data, writeOpts);
345
+ // Lock the temp down to the current user BEFORE it is published at
346
+ // filePath. On win32 an NTFS rename carries the file's explicit
347
+ // DACL, so tightening tmp here means the secret never appears at
348
+ // the final path with a permissive ACL. Fail-closed: if the ACL
349
+ // cannot be applied, the throw below unlinks tmp and aborts.
350
+ if (opts.secret === true) _enforceOwnerOnlyAclWin32(tmp);
351
+ if (opts.fsync !== false) {
352
+ let fd = null;
353
+ try {
354
+ fd = openSync(tmp, 'r');
355
+ fsyncSync(fd);
356
+ } catch (err) {
357
+ if (!['EPERM', 'ENOTSUP', 'EINVAL'].includes(err?.code)) throw err;
358
+ } finally {
359
+ try { if (fd !== null) closeSync(fd); } catch {}
360
+ }
361
+ }
362
+ if (opts.createOnly === true) {
363
+ // Atomic create-if-absent: linkSync fails with EEXIST if the
364
+ // target already exists at link time, so a concurrent
365
+ // non-locking writer (user/editor) that creates the file
366
+ // between any prior existsSync gate and this call still
367
+ // wins — we drop the temp and report `false` so the caller
368
+ // can record the path as skipped rather than overwriting.
369
+ try {
370
+ linkSync(tmp, filePath);
371
+ } catch (err) {
372
+ try { unlinkSync(tmp); } catch {}
373
+ if (err?.code === 'EEXIST') return false;
374
+ throw err;
375
+ }
376
+ try { unlinkSync(tmp); } catch {}
377
+ } else {
378
+ renameWithRetrySync(tmp, filePath, opts);
379
+ }
380
+ if (opts.secret === true) {
381
+ // Re-assert owner-only on the final path (createOnly's linkSync may
382
+ // not carry the temp DACL the same way a rename does). Throws
383
+ // fail-closed if the ACL cannot be enforced.
384
+ //
385
+ // NOTE: we deliberately do NOT clamp the parent dir. On win32
386
+ // `_enforceOwnerOnlyAclWin32` runs `icacls /inheritance:r /grant:r
387
+ // user:(F)` which is NOT the POSIX-0o700 analogue it looks like —
388
+ // on a directory it breaks inheritance and cascade-strips inherited
389
+ // ACEs from EVERY descendant, leaving the whole tree (e.g. ~/.claude
390
+ // when writing ~/.claude/.credentials.json) with empty DACLs and
391
+ // access-denied for everyone, owner included. The file ACL above
392
+ // already protects the secret's contents regardless of dir listing.
393
+ _enforceOwnerOnlyAclWin32(filePath);
394
+ }
395
+ if (opts.fsyncDir === true) {
396
+ let dfd = null;
397
+ try {
398
+ dfd = openSync(dir, 'r');
399
+ fsyncSync(dfd);
400
+ } catch (err) {
401
+ if (!['EPERM', 'ENOTSUP', 'EINVAL', 'EACCES'].includes(err?.code)) throw err;
402
+ } finally {
403
+ try { if (dfd !== null) closeSync(dfd); } catch {}
404
+ }
405
+ }
406
+ return true;
407
+ } catch (err) {
408
+ try { if (existsSync(tmp)) unlinkSync(tmp); } catch {}
409
+ throw err;
410
+ }
411
+ };
412
+ if (opts.lock === true) {
413
+ return withFileLockSync(`${filePath}.lock`, run, opts);
414
+ }
415
+ return run();
416
+ }
417
+
418
+ export function writeJsonAtomicSync(filePath, value, opts = {}) {
419
+ return writeFileAtomicSync(filePath, JSON.stringify(value, null, opts.compact ? 0 : 2) + '\n', opts);
420
+ }