stitchkit 0.94.0 → 0.94.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (346) hide show
  1. package/CHANGELOG.md +64 -0
  2. package/dist/agent-runtime/coding-shell-process.d.ts.map +1 -1
  3. package/dist/agent-runtime/coding-tool-listing.d.ts.map +1 -1
  4. package/dist/agent-runtime/coding-tool-search-patch.d.ts.map +1 -1
  5. package/dist/agent-runtime/contained-darwin.d.ts +38 -0
  6. package/dist/agent-runtime/contained-darwin.d.ts.map +1 -0
  7. package/dist/agent-runtime/contained-files.d.ts +11 -26
  8. package/dist/agent-runtime/contained-files.d.ts.map +1 -1
  9. package/dist/agent-runtime/contained-scan.d.ts +21 -0
  10. package/dist/agent-runtime/contained-scan.d.ts.map +1 -0
  11. package/dist/agent-runtime/contained-write.d.ts +9 -0
  12. package/dist/agent-runtime/contained-write.d.ts.map +1 -0
  13. package/dist/agent-runtime/deferred-tool-types.d.ts +3 -2
  14. package/dist/agent-runtime/deferred-tool-types.d.ts.map +1 -1
  15. package/dist/agent-runtime/harness-control.d.ts +0 -1
  16. package/dist/agent-runtime/harness-control.d.ts.map +1 -1
  17. package/dist/agent-runtime/harness.d.ts +0 -5
  18. package/dist/agent-runtime/harness.d.ts.map +1 -1
  19. package/dist/agent-runtime/managed-tools.d.ts +3 -2
  20. package/dist/agent-runtime/managed-tools.d.ts.map +1 -1
  21. package/dist/agent-runtime/runtime.d.ts +1 -1
  22. package/dist/agent-runtime/runtime.d.ts.map +1 -1
  23. package/dist/agent-runtime/schedule-records.d.ts +34 -0
  24. package/dist/agent-runtime/schedule-records.d.ts.map +1 -0
  25. package/dist/agent-runtime/schedules.d.ts +34 -0
  26. package/dist/agent-runtime/schedules.d.ts.map +1 -1
  27. package/dist/agent-runtime/store-conformance-lifecycle.d.ts +434 -0
  28. package/dist/agent-runtime/store-conformance-lifecycle.d.ts.map +1 -0
  29. package/dist/agent-runtime/store-conformance-ordering.d.ts +18 -0
  30. package/dist/agent-runtime/store-conformance-ordering.d.ts.map +1 -0
  31. package/dist/agent-runtime/store-conformance-support.d.ts +130 -0
  32. package/dist/agent-runtime/store-conformance-support.d.ts.map +1 -0
  33. package/dist/agent-runtime/store-conformance-terminal.d.ts +12 -0
  34. package/dist/agent-runtime/store-conformance-terminal.d.ts.map +1 -0
  35. package/dist/agent-runtime/store-conformance.d.ts.map +1 -1
  36. package/dist/application/admission-rate.d.ts +21 -0
  37. package/dist/application/admission-rate.d.ts.map +1 -0
  38. package/dist/application/admission-run.d.ts +8 -0
  39. package/dist/application/admission-run.d.ts.map +1 -0
  40. package/dist/application/admission.d.ts.map +1 -1
  41. package/dist/application/diagnostic-journal-lock.d.ts +9 -34
  42. package/dist/application/diagnostic-journal-lock.d.ts.map +1 -1
  43. package/dist/application/diagnostic-journal-manager.d.ts.map +1 -1
  44. package/dist/application/diagnostic-journal-storage.d.ts.map +1 -1
  45. package/dist/application/kernel-resource-context.d.ts.map +1 -1
  46. package/dist/application/notification-outbox.d.ts.map +1 -1
  47. package/dist/application/schedule.d.ts +0 -1
  48. package/dist/application/schedule.d.ts.map +1 -1
  49. package/dist/application/watch-hub-core.d.ts +122 -0
  50. package/dist/application/watch-hub-core.d.ts.map +1 -0
  51. package/dist/application/watch-hub.d.ts +2 -2
  52. package/dist/application/watch-hub.d.ts.map +1 -1
  53. package/dist/browser/client-executors.d.ts +14 -0
  54. package/dist/browser/client-executors.d.ts.map +1 -0
  55. package/dist/browser/client-multipart.d.ts +1 -1
  56. package/dist/browser/client-multipart.d.ts.map +1 -1
  57. package/dist/browser/client.d.ts +3 -2
  58. package/dist/browser/client.d.ts.map +1 -1
  59. package/dist/browser/http-fetch.d.ts +22 -0
  60. package/dist/browser/http-fetch.d.ts.map +1 -0
  61. package/dist/browser/http.d.ts +1 -3
  62. package/dist/browser/http.d.ts.map +1 -1
  63. package/dist/browser/live-state-core.d.ts +63 -0
  64. package/dist/browser/live-state-core.d.ts.map +1 -0
  65. package/dist/browser/live-state.d.ts.map +1 -1
  66. package/dist/browser/realtime-client.d.ts +26 -0
  67. package/dist/browser/realtime-client.d.ts.map +1 -0
  68. package/dist/browser/socket-io-connection.d.ts +82 -0
  69. package/dist/browser/socket-io-connection.d.ts.map +1 -0
  70. package/dist/browser/socket-io-peer.d.ts +20 -0
  71. package/dist/browser/socket-io-peer.d.ts.map +1 -0
  72. package/dist/browser/socket-io-trace.d.ts +31 -0
  73. package/dist/browser/socket-io-trace.d.ts.map +1 -0
  74. package/dist/browser/socket-io.d.ts +2 -18
  75. package/dist/browser/socket-io.d.ts.map +1 -1
  76. package/dist/contract/client-types.d.ts +134 -0
  77. package/dist/contract/client-types.d.ts.map +1 -0
  78. package/dist/contract/define-validation.d.ts +30 -0
  79. package/dist/contract/define-validation.d.ts.map +1 -0
  80. package/dist/contract/define.d.ts +3 -357
  81. package/dist/contract/define.d.ts.map +1 -1
  82. package/dist/contract/runtime-context.d.ts +131 -0
  83. package/dist/contract/runtime-context.d.ts.map +1 -0
  84. package/dist/contract/tool-options.d.ts +105 -0
  85. package/dist/contract/tool-options.d.ts.map +1 -0
  86. package/dist/contract/tool-view.d.ts +15 -2
  87. package/dist/contract/tool-view.d.ts.map +1 -1
  88. package/dist/durability/contract.d.ts +83 -0
  89. package/dist/durability/contract.d.ts.map +1 -1
  90. package/dist/durability/effect.d.ts +24 -0
  91. package/dist/durability/effect.d.ts.map +1 -0
  92. package/dist/durability/engine.d.ts +2 -2
  93. package/dist/durability/engine.d.ts.map +1 -1
  94. package/dist/durability/events.d.ts +2 -0
  95. package/dist/durability/events.d.ts.map +1 -1
  96. package/dist/durability/ledger.d.ts +11 -0
  97. package/dist/durability/ledger.d.ts.map +1 -1
  98. package/dist/durability/parks.d.ts +22 -0
  99. package/dist/durability/parks.d.ts.map +1 -0
  100. package/dist/durability/scheduler.d.ts +1 -0
  101. package/dist/durability/scheduler.d.ts.map +1 -1
  102. package/dist/entrypoints/agent-runtime/coding-tools.js +4 -4
  103. package/dist/entrypoints/agent-runtime/harness.js +127 -116
  104. package/dist/entrypoints/agent-runtime/sandbox.js +4 -4
  105. package/dist/entrypoints/agent-runtime/sqlite/bun.js +3 -3
  106. package/dist/entrypoints/agent-runtime/sqlite/node.js +3 -3
  107. package/dist/entrypoints/agent-runtime/testing.js +246 -214
  108. package/dist/entrypoints/agent-runtime.js +224 -203
  109. package/dist/entrypoints/application/diagnostic-journal.js +63 -203
  110. package/dist/entrypoints/application/opentelemetry.js +1 -1
  111. package/dist/entrypoints/application.js +361 -324
  112. package/dist/entrypoints/cli.d.ts +4 -1
  113. package/dist/entrypoints/cli.d.ts.map +1 -1
  114. package/dist/entrypoints/cli.js +57 -35
  115. package/dist/entrypoints/contract.d.ts +5 -2
  116. package/dist/entrypoints/contract.d.ts.map +1 -1
  117. package/dist/entrypoints/contract.js +3 -2
  118. package/dist/entrypoints/files.d.ts +2 -0
  119. package/dist/entrypoints/files.d.ts.map +1 -1
  120. package/dist/entrypoints/files.js +98 -2
  121. package/dist/entrypoints/index.d.ts +4 -2
  122. package/dist/entrypoints/index.d.ts.map +1 -1
  123. package/dist/entrypoints/index.js +348 -282
  124. package/dist/entrypoints/live.js +89 -71
  125. package/dist/entrypoints/node.d.ts +2 -1
  126. package/dist/entrypoints/node.d.ts.map +1 -1
  127. package/dist/entrypoints/node.js +13 -12
  128. package/dist/entrypoints/react.js +1 -1
  129. package/dist/entrypoints/remote.js +4 -4
  130. package/dist/entrypoints/server.d.ts +4 -2
  131. package/dist/entrypoints/server.d.ts.map +1 -1
  132. package/dist/entrypoints/server.js +293 -79
  133. package/dist/entrypoints/testing.d.ts +2 -1
  134. package/dist/entrypoints/testing.d.ts.map +1 -1
  135. package/dist/entrypoints/testing.js +288 -281
  136. package/dist/entrypoints/tools/connections.js +2 -2
  137. package/dist/entrypoints/tools/invoker.js +4 -4
  138. package/dist/entrypoints/tools.d.ts +6 -3
  139. package/dist/entrypoints/tools.d.ts.map +1 -1
  140. package/dist/entrypoints/tools.js +245 -202
  141. package/dist/entrypoints/tracking.js +325 -274
  142. package/dist/files/boundary.d.ts.map +1 -1
  143. package/dist/files/file-io.d.ts +14 -0
  144. package/dist/files/file-io.d.ts.map +1 -0
  145. package/dist/index-1j8pm5t0.js +412 -0
  146. package/dist/{index-kvj7f4hq.js → index-2bxbyab0.js} +10 -2
  147. package/dist/{index-xnj9bgxe.js → index-2gxzjvyr.js} +2 -162
  148. package/dist/index-4gcnakhx.js +82 -0
  149. package/dist/{index-j05z5gn4.js → index-55hkhm67.js} +136 -119
  150. package/dist/{index-cq4qfycf.js → index-79z7m7dt.js} +227 -59
  151. package/dist/{index-97ac4gph.js → index-7f68ghdn.js} +3 -3
  152. package/dist/{index-r7nmqpsg.js → index-7p1f0vp2.js} +1 -1
  153. package/dist/{index-dcpdvjsc.js → index-863ea9jb.js} +4 -4
  154. package/dist/index-8p52kd5p.js +242 -0
  155. package/dist/{index-2qzskm8h.js → index-dce5wxcq.js} +1 -1
  156. package/dist/index-e01r054k.js +105 -0
  157. package/dist/{index-sees8yf8.js → index-ensd0r74.js} +118 -111
  158. package/dist/{index-1nd48tm9.js → index-gxrt5h6v.js} +2 -1
  159. package/dist/{index-e87kakm4.js → index-ham5sz8m.js} +112 -110
  160. package/dist/{index-kj2wbeta.js → index-het2he5g.js} +280 -196
  161. package/dist/{index-vcvkq30w.js → index-hmp4800j.js} +3 -3
  162. package/dist/{index-gyr48nzg.js → index-k30h66yd.js} +71 -151
  163. package/dist/{index-2cr1cqhn.js → index-khtgb21r.js} +2 -2
  164. package/dist/{index-x4799c19.js → index-ndddxtyx.js} +11 -11
  165. package/dist/{index-dydjcp8z.js → index-np4m8hd3.js} +38 -36
  166. package/dist/{index-p81267c2.js → index-p3vsv1fb.js} +621 -357
  167. package/dist/{index-mp5sn43f.js → index-p9e0w8hs.js} +2 -2
  168. package/dist/{index-rewkc2hj.js → index-p9sh0xx4.js} +3 -3
  169. package/dist/{index-70yj2ebz.js → index-paz6sgdp.js} +107 -103
  170. package/dist/{index-bn2cjajt.js → index-px2gm2jp.js} +26 -102
  171. package/dist/index-s812ycat.js +65 -0
  172. package/dist/{index-xsqjkha9.js → index-sp1tzwnb.js} +2 -2
  173. package/dist/{index-n6hxg8as.js → index-t9rhjr9f.js} +615 -566
  174. package/dist/{index-zeemqhqx.js → index-v260df89.js} +88 -80
  175. package/dist/{index-fdp6hdxn.js → index-w906953s.js} +5 -1
  176. package/dist/{index-mdzh02yc.js → index-wdkt63w3.js} +1 -1
  177. package/dist/{index-58k4fp34.js → index-wsm5w4ee.js} +1 -1
  178. package/dist/{index-v38qyerb.js → index-xw3s75nj.js} +1 -1
  179. package/dist/internal/atomic-file.d.ts +23 -2
  180. package/dist/internal/atomic-file.d.ts.map +1 -1
  181. package/dist/internal/exclusive-lock.d.ts +51 -0
  182. package/dist/internal/exclusive-lock.d.ts.map +1 -0
  183. package/dist/internal/process-identity.d.ts +47 -0
  184. package/dist/internal/process-identity.d.ts.map +1 -0
  185. package/dist/internal/with-exclusive-lock.d.ts +67 -0
  186. package/dist/internal/with-exclusive-lock.d.ts.map +1 -0
  187. package/dist/live/watch-client.d.ts.map +1 -1
  188. package/dist/observability/audit.d.ts +2 -2
  189. package/dist/observability/audit.d.ts.map +1 -1
  190. package/dist/observability/event.d.ts +2 -1
  191. package/dist/observability/event.d.ts.map +1 -1
  192. package/dist/primitives/export-operation.d.ts +1 -1
  193. package/dist/primitives/export-operation.d.ts.map +1 -1
  194. package/dist/realtime/registry.d.ts +0 -5
  195. package/dist/realtime/registry.d.ts.map +1 -1
  196. package/dist/server/bun.d.ts +0 -1
  197. package/dist/server/bun.d.ts.map +1 -1
  198. package/dist/server/context-contribution.d.ts +1 -1
  199. package/dist/server/context-contribution.d.ts.map +1 -1
  200. package/dist/server/context.d.ts +1 -1
  201. package/dist/server/context.d.ts.map +1 -1
  202. package/dist/server/endpoint-response.d.ts +2 -1
  203. package/dist/server/endpoint-response.d.ts.map +1 -1
  204. package/dist/server/error-dispatch.d.ts +1 -1
  205. package/dist/server/error-dispatch.d.ts.map +1 -1
  206. package/dist/server/error-hook.d.ts +1 -1
  207. package/dist/server/error-hook.d.ts.map +1 -1
  208. package/dist/server/handler-state.d.ts +1 -1
  209. package/dist/server/handler-state.d.ts.map +1 -1
  210. package/dist/server/implement-registry.d.ts +54 -0
  211. package/dist/server/implement-registry.d.ts.map +1 -0
  212. package/dist/server/implement.d.ts +9 -55
  213. package/dist/server/implement.d.ts.map +1 -1
  214. package/dist/server/middleware/auth.d.ts +1 -31
  215. package/dist/server/middleware/auth.d.ts.map +1 -1
  216. package/dist/server/middleware/jwt.d.ts +31 -0
  217. package/dist/server/middleware/jwt.d.ts.map +1 -0
  218. package/dist/server/multipart-reader.d.ts +22 -0
  219. package/dist/server/multipart-reader.d.ts.map +1 -0
  220. package/dist/server/multipart.d.ts +1 -1
  221. package/dist/server/multipart.d.ts.map +1 -1
  222. package/dist/server/oauth/cimd.d.ts +88 -0
  223. package/dist/server/oauth/cimd.d.ts.map +1 -0
  224. package/dist/server/oauth/endpoints.d.ts +39 -0
  225. package/dist/server/oauth/endpoints.d.ts.map +1 -0
  226. package/dist/server/oauth/provider.d.ts +1 -68
  227. package/dist/server/oauth/provider.d.ts.map +1 -1
  228. package/dist/server/streaming-pump.d.ts +66 -0
  229. package/dist/server/streaming-pump.d.ts.map +1 -0
  230. package/dist/server/streaming-route.d.ts +12 -5
  231. package/dist/server/streaming-route.d.ts.map +1 -1
  232. package/dist/server/types.d.ts +4 -1
  233. package/dist/server/types.d.ts.map +1 -1
  234. package/dist/server/unix-client-bun.d.ts.map +1 -1
  235. package/dist/server/unix-client-http1.d.ts +76 -0
  236. package/dist/server/unix-client-http1.d.ts.map +1 -0
  237. package/dist/server/unix-client.d.ts.map +1 -1
  238. package/dist/testing/handler-clients.d.ts +2 -1
  239. package/dist/testing/handler-clients.d.ts.map +1 -1
  240. package/dist/testing/realtime-probe.d.ts +33 -0
  241. package/dist/testing/realtime-probe.d.ts.map +1 -0
  242. package/dist/testing/surface-conformance.d.ts +0 -31
  243. package/dist/testing/surface-conformance.d.ts.map +1 -1
  244. package/dist/testing/surface-manifest-digest.d.ts +44 -0
  245. package/dist/testing/surface-manifest-digest.d.ts.map +1 -0
  246. package/dist/testing/surface-manifest.d.ts.map +1 -1
  247. package/dist/tools/agent.d.ts +1 -1
  248. package/dist/tools/agent.d.ts.map +1 -1
  249. package/dist/tools/cli/args-fields.d.ts +31 -0
  250. package/dist/tools/cli/args-fields.d.ts.map +1 -0
  251. package/dist/tools/cli/args-route.d.ts +42 -0
  252. package/dist/tools/cli/args-route.d.ts.map +1 -0
  253. package/dist/tools/cli/args-view.d.ts +32 -0
  254. package/dist/tools/cli/args-view.d.ts.map +1 -0
  255. package/dist/tools/cli/args.d.ts +2 -65
  256. package/dist/tools/cli/args.d.ts.map +1 -1
  257. package/dist/tools/cli/argument-error.d.ts +5 -0
  258. package/dist/tools/cli/argument-error.d.ts.map +1 -0
  259. package/dist/tools/cli/checkpoint.d.ts.map +1 -1
  260. package/dist/tools/cli/command.d.ts +1 -1
  261. package/dist/tools/cli/command.d.ts.map +1 -1
  262. package/dist/tools/cli/config.d.ts +1 -1
  263. package/dist/tools/cli/config.d.ts.map +1 -1
  264. package/dist/tools/cli/format.d.ts +2 -1
  265. package/dist/tools/cli/format.d.ts.map +1 -1
  266. package/dist/tools/cli/invoke.d.ts +2 -1
  267. package/dist/tools/cli/invoke.d.ts.map +1 -1
  268. package/dist/tools/cli/managed-surface.d.ts +1 -1
  269. package/dist/tools/cli/managed-surface.d.ts.map +1 -1
  270. package/dist/tools/cli/policy.d.ts +1 -1
  271. package/dist/tools/cli/policy.d.ts.map +1 -1
  272. package/dist/tools/cli/prepare.d.ts.map +1 -1
  273. package/dist/tools/cli/run-managed.d.ts.map +1 -1
  274. package/dist/tools/cli/session.d.ts +1 -1
  275. package/dist/tools/cli/session.d.ts.map +1 -1
  276. package/dist/tools/cli/update.d.ts +19 -0
  277. package/dist/tools/cli/update.d.ts.map +1 -1
  278. package/dist/tools/cli/view.d.ts +1 -1
  279. package/dist/tools/cli/view.d.ts.map +1 -1
  280. package/dist/tools/cli/wait.d.ts +1 -1
  281. package/dist/tools/cli/wait.d.ts.map +1 -1
  282. package/dist/tools/connections/runtime.d.ts +1 -1
  283. package/dist/tools/connections/runtime.d.ts.map +1 -1
  284. package/dist/tools/execute-args.d.ts +23 -0
  285. package/dist/tools/execute-args.d.ts.map +1 -0
  286. package/dist/tools/execute-hooks.d.ts +146 -0
  287. package/dist/tools/execute-hooks.d.ts.map +1 -0
  288. package/dist/tools/execute-result.d.ts +40 -0
  289. package/dist/tools/execute-result.d.ts.map +1 -0
  290. package/dist/tools/execute.d.ts +4 -193
  291. package/dist/tools/execute.d.ts.map +1 -1
  292. package/dist/tools/internal/surface-projector.d.ts +2 -1
  293. package/dist/tools/internal/surface-projector.d.ts.map +1 -1
  294. package/dist/tools/invoker.d.ts +2 -1
  295. package/dist/tools/invoker.d.ts.map +1 -1
  296. package/dist/tools/lifecycle.d.ts +1 -1
  297. package/dist/tools/lifecycle.d.ts.map +1 -1
  298. package/dist/tools/mcp/mount.d.ts +1 -1
  299. package/dist/tools/mcp/mount.d.ts.map +1 -1
  300. package/dist/tools/mcp/prepare.d.ts +2 -1
  301. package/dist/tools/mcp/prepare.d.ts.map +1 -1
  302. package/dist/tools/mcp/progress.d.ts +1 -1
  303. package/dist/tools/mcp/progress.d.ts.map +1 -1
  304. package/dist/tools/mcp/register.d.ts +3 -2
  305. package/dist/tools/mcp/register.d.ts.map +1 -1
  306. package/dist/tools/mcp/round-context.d.ts +38 -0
  307. package/dist/tools/mcp/round-context.d.ts.map +1 -0
  308. package/dist/tools/mcp/round-policy.d.ts +1 -1
  309. package/dist/tools/mcp/round-policy.d.ts.map +1 -1
  310. package/dist/tools/mcp/round.d.ts +3 -11
  311. package/dist/tools/mcp/round.d.ts.map +1 -1
  312. package/dist/tools/mcp/runtime-tools.d.ts +2 -1
  313. package/dist/tools/mcp/runtime-tools.d.ts.map +1 -1
  314. package/dist/tools/mount.d.ts +3 -1
  315. package/dist/tools/mount.d.ts.map +1 -1
  316. package/dist/tools/native-definition.d.ts +2 -1
  317. package/dist/tools/native-definition.d.ts.map +1 -1
  318. package/dist/tools/operations/async-operation-runtime-tools.d.ts +2 -1
  319. package/dist/tools/operations/async-operation-runtime-tools.d.ts.map +1 -1
  320. package/dist/tools/operations/async-operation-runtime-types.d.ts +2 -1
  321. package/dist/tools/operations/async-operation-runtime-types.d.ts.map +1 -1
  322. package/dist/tools/remote.d.ts.map +1 -1
  323. package/dist/tools/runtime-tool.d.ts +3 -1
  324. package/dist/tools/runtime-tool.d.ts.map +1 -1
  325. package/dist/tools/tool-logger.d.ts +1 -1
  326. package/dist/tools/tool-logger.d.ts.map +1 -1
  327. package/dist/tracking/client-listeners.d.ts +30 -0
  328. package/dist/tracking/client-listeners.d.ts.map +1 -0
  329. package/dist/tracking/client-visit.d.ts +61 -0
  330. package/dist/tracking/client-visit.d.ts.map +1 -0
  331. package/dist/tracking/client.d.ts +3 -2
  332. package/dist/tracking/client.d.ts.map +1 -1
  333. package/llms/application.2.txt +266 -2
  334. package/llms/application.txt +8 -266
  335. package/llms/cli.2.txt +80 -0
  336. package/llms/cli.txt +45 -74
  337. package/llms/contract.txt +3 -3
  338. package/llms/files.txt +3 -0
  339. package/llms/tools.2.txt +88 -279
  340. package/llms/tools.3.txt +288 -0
  341. package/llms/tools.txt +27 -65
  342. package/llms-full.txt +108 -12
  343. package/llms.txt +5 -5
  344. package/package.json +1 -1
  345. package/dist/index-e2z3ahw9.js +0 -325
  346. package/dist/index-mkm15s49.js +0 -394
@@ -3,6 +3,7 @@ import { z } from "zod";
3
3
  var DURABILITY_STEP_EVENT_KIND = "durability/step";
4
4
  var DURABILITY_PARK_EVENT_KIND = "durability/park";
5
5
  var DURABILITY_EVENT_EVENT_KIND = "durability/event";
6
+ var DURABILITY_EFFECT_EVENT_KIND = "durability/effect";
6
7
  var StepEventPayloadSchema = z.object({
7
8
  runId: z.string().min(1),
8
9
  stepName: z.string().min(1),
@@ -30,6 +31,17 @@ var DeliveredEventPayloadSchema = z.object({
30
31
  id: z.string().min(1),
31
32
  encoded: z.string()
32
33
  });
34
+ var EffectIdentity = { runId: z.string().min(1), effectName: z.string().min(1) };
35
+ var EffectEventPayloadSchema = z.discriminatedUnion("phase", [
36
+ z.object({ ...EffectIdentity, phase: z.literal("intent") }),
37
+ z.object({
38
+ ...EffectIdentity,
39
+ phase: z.literal("accepted"),
40
+ encoded: z.string(),
41
+ via: z.enum(["run", "reconcile"])
42
+ }),
43
+ z.object({ ...EffectIdentity, phase: z.literal("uncertain") })
44
+ ]);
33
45
 
34
46
  class StepResultDecodeError extends Error {
35
47
  constructor(message, options) {
@@ -54,6 +66,17 @@ class StepAbortedError extends Error {
54
66
  }
55
67
  }
56
68
 
69
+ class EffectUnresolvedError extends Error {
70
+ effectName;
71
+ reason;
72
+ constructor(effectName, reason, options) {
73
+ super(`Effect "${effectName}" is unresolved (${reason}); its intent stands`, options);
74
+ this.effectName = effectName;
75
+ this.reason = reason;
76
+ this.name = "EffectUnresolvedError";
77
+ }
78
+ }
79
+
57
80
  class ParkRecordDecodeError extends Error {
58
81
  constructor(message, options) {
59
82
  super(message, options);
@@ -113,6 +136,9 @@ var DurableJsonSchema = z2.custom((value) => losslessJson(value), "Expected loss
113
136
  function stepKey(conversationId, runId, stepName) {
114
137
  return JSON.stringify([conversationId, runId, stepName]);
115
138
  }
139
+ function effectKey(conversationId, runId, effectName) {
140
+ return JSON.stringify([conversationId, runId, "effect", effectName]);
141
+ }
116
142
  function sleepParkKey(conversationId, runId, name) {
117
143
  return JSON.stringify([conversationId, runId, "sleep", name]);
118
144
  }
@@ -183,8 +209,25 @@ function decodeDeliveredResult(payload, event) {
183
209
  throw new ParkRecordDecodeError(`Delivered payload for "${payload.event}#${payload.id}" (run ${payload.runId}, ` + `event ${event.eventId}) is not decodable JSON`, { cause });
184
210
  }
185
211
  }
212
+ function decodeEffect(event) {
213
+ const parsed = EffectEventPayloadSchema.safeParse(event.payload);
214
+ if (!parsed.success) {
215
+ throw new StepResultDecodeError(`Recorded effect event ${event.eventId} in conversation ${event.conversationId} is malformed`, { cause: parsed.error });
216
+ }
217
+ const payload = parsed.data;
218
+ if (payload.phase === "intent")
219
+ return { payload, record: { outcome: undefined } };
220
+ if (payload.phase === "uncertain")
221
+ return { payload, record: { outcome: "uncertain" } };
222
+ try {
223
+ const proof = DurableJsonSchema.parse(JSON.parse(payload.encoded));
224
+ return { payload, record: { outcome: "accepted", proof } };
225
+ } catch (cause) {
226
+ throw new StepResultDecodeError(`Recorded proof for effect "${payload.effectName}" (run ${payload.runId}, ` + `event ${event.eventId}) is not decodable JSON`, { cause });
227
+ }
228
+ }
186
229
  async function readDurabilityLedger(store, conversationId, view) {
187
- const { steps, parks, deliveries } = view;
230
+ const { steps, effects, parks, deliveries } = view;
188
231
  let fromSeq = view.nextSeq;
189
232
  for (;; ) {
190
233
  const page = await store.readEvents({
@@ -199,6 +242,11 @@ async function readDurabilityLedger(store, conversationId, view) {
199
242
  } else if (event.kind === DURABILITY_PARK_EVENT_KIND) {
200
243
  const payload = decodeParkPayload(event);
201
244
  parks.set(parkEventKey(event.conversationId, payload), payload);
245
+ } else if (event.kind === DURABILITY_EFFECT_EVENT_KIND) {
246
+ const { payload, record } = decodeEffect(event);
247
+ const key = effectKey(event.conversationId, payload.runId, payload.effectName);
248
+ if (effects.get(key)?.outcome === undefined)
249
+ effects.set(key, record);
202
250
  } else if (event.kind === DURABILITY_EVENT_EVENT_KIND) {
203
251
  const payload = decodeDeliveredPayload(event);
204
252
  const key = waitParkKey(event.conversationId, payload.runId, payload.event, payload.id);
@@ -216,6 +264,95 @@ async function readDurabilityLedger(store, conversationId, view) {
216
264
  return view;
217
265
  }
218
266
 
267
+ // src/durability/effect.ts
268
+ var DEFAULT_RECONCILE_TIMEOUT_MS = 30000;
269
+ var MAX_PROOF_BYTES = 64 * 1024;
270
+ function encodeProof(name, proof) {
271
+ let encoded;
272
+ try {
273
+ encoded = encodeStepResult(name, proof);
274
+ } catch (cause) {
275
+ throw new EffectUnresolvedError(name, "proof-rejected", { cause });
276
+ }
277
+ const bytes = new TextEncoder().encode(encoded).byteLength;
278
+ if (bytes > MAX_PROOF_BYTES) {
279
+ throw new EffectUnresolvedError(name, "proof-rejected", {
280
+ cause: new RangeError(`the proof is ${bytes} bytes; at most ${MAX_PROOF_BYTES} are kept`)
281
+ });
282
+ }
283
+ return encoded;
284
+ }
285
+ function outcomeOf(encoded) {
286
+ return { outcome: "accepted", proof: JSON.parse(encoded) };
287
+ }
288
+ async function append(context, payload, name) {
289
+ await context.store.appendEvent({
290
+ conversationId: context.conversationId,
291
+ kind: DURABILITY_EFFECT_EVENT_KIND,
292
+ payload: { runId: context.runId, effectName: name, ...payload }
293
+ });
294
+ }
295
+ async function reconcile(context, name, handlers, timeoutMs) {
296
+ const controller = new AbortController;
297
+ let timer;
298
+ const deadline = new Promise((resolve) => {
299
+ timer = setTimeout(() => {
300
+ controller.abort(new Error(`reconcile did not finish within ${timeoutMs} ms`));
301
+ resolve("timeout");
302
+ }, timeoutMs);
303
+ });
304
+ let found;
305
+ try {
306
+ found = await Promise.race([
307
+ Promise.resolve().then(() => handlers.reconcile(controller.signal)),
308
+ deadline
309
+ ]);
310
+ } catch (cause) {
311
+ throw new EffectUnresolvedError(name, "reconcile-failed", { cause });
312
+ } finally {
313
+ clearTimeout(timer);
314
+ }
315
+ if (found === "timeout") {
316
+ throw new EffectUnresolvedError(name, "reconcile-timeout", {
317
+ cause: controller.signal.reason
318
+ });
319
+ }
320
+ if (found === null) {
321
+ await append(context, { phase: "uncertain" }, name);
322
+ return { outcome: "uncertain" };
323
+ }
324
+ const encoded = encodeProof(name, found);
325
+ await append(context, { phase: "accepted", encoded, via: "reconcile" }, name);
326
+ return outcomeOf(encoded);
327
+ }
328
+ async function executeEffect(context, name, handlers, options) {
329
+ const timeoutMs = options?.reconcileTimeoutMs ?? DEFAULT_RECONCILE_TIMEOUT_MS;
330
+ if (!Number.isFinite(timeoutMs) || timeoutMs <= 0) {
331
+ throw new TypeError(`reconcileTimeoutMs must be a positive finite number, got ${timeoutMs}`);
332
+ }
333
+ const key = effectKey(context.conversationId, context.runId, name);
334
+ const recorded = (await context.readLedger()).effects.get(key);
335
+ if (recorded?.outcome === "uncertain")
336
+ return { outcome: "uncertain" };
337
+ if (recorded?.outcome === "accepted") {
338
+ return outcomeOf(JSON.stringify(recorded.proof));
339
+ }
340
+ if (options?.signal?.aborted || context.signal?.aborted)
341
+ throw new StepAbortedError(name);
342
+ if (recorded)
343
+ return reconcile(context, name, handlers, timeoutMs);
344
+ await append(context, { phase: "intent" }, name);
345
+ let proof;
346
+ try {
347
+ proof = await handlers.run();
348
+ } catch (cause) {
349
+ throw new EffectUnresolvedError(name, "run-failed", { cause });
350
+ }
351
+ const encoded = encodeProof(name, proof);
352
+ await append(context, { phase: "accepted", encoded, via: "run" }, name);
353
+ return outcomeOf(encoded);
354
+ }
355
+
219
356
  // src/durability/scheduler.ts
220
357
  var systemClock = {
221
358
  now: () => Date.now(),
@@ -300,6 +437,64 @@ function createParkWaiter(parkWaiters, key, signal) {
300
437
  return { outcome, cancel: cleanup };
301
438
  }
302
439
 
440
+ // src/durability/parks.ts
441
+ async function executeSleep(park, name, seconds, runOptions) {
442
+ const key = sleepParkKey(park.conversationId, park.runId, name);
443
+ const signal = park.signal && runOptions?.signal ? AbortSignal.any([park.signal, runOptions.signal]) : runOptions?.signal ?? park.signal;
444
+ const ledger = await park.readLedger();
445
+ const existing = ledger.parks.get(key);
446
+ let deadline;
447
+ if (existing) {
448
+ if (existing.kind !== "sleep") {
449
+ throw new ParkRecordDecodeError(`Recorded park "${name}" is not a sleep record`);
450
+ }
451
+ deadline = existing.deadline;
452
+ } else {
453
+ deadline = park.clock.now() + seconds * 1000;
454
+ if (!Number.isSafeInteger(Math.ceil(deadline)))
455
+ throw new TypeError("Sleep deadline exceeds the supported clock range");
456
+ await park.store.appendEvent({
457
+ conversationId: park.conversationId,
458
+ kind: DURABILITY_PARK_EVENT_KIND,
459
+ payload: { runId: park.runId, kind: "sleep", name, deadline }
460
+ });
461
+ }
462
+ if (signal?.aborted)
463
+ throw new ParkAbortedError(name);
464
+ await waitForDeadline(park.clock, deadline, name, signal);
465
+ }
466
+ async function executeWait(park, eventName, id, runOptions) {
467
+ const key = waitParkKey(park.conversationId, park.runId, eventName, id);
468
+ const label = `${eventName}#${id}`;
469
+ const signal = park.signal && runOptions?.signal ? AbortSignal.any([park.signal, runOptions.signal]) : runOptions?.signal ?? park.signal;
470
+ for (;; ) {
471
+ if (signal?.aborted)
472
+ throw new ParkAbortedError(label);
473
+ const waiter = createParkWaiter(park.waiters, key, signal);
474
+ let unsubscribe;
475
+ try {
476
+ unsubscribe = park.subscribe?.(() => notifyWaiters(park.waiters, key));
477
+ const ledger = await park.readLedger();
478
+ if (ledger.deliveries.has(key)) {
479
+ return JSON.parse(JSON.stringify(ledger.deliveries.get(key)));
480
+ }
481
+ if (!ledger.parks.has(key)) {
482
+ await park.store.appendEvent({
483
+ conversationId: park.conversationId,
484
+ kind: DURABILITY_PARK_EVENT_KIND,
485
+ payload: { runId: park.runId, kind: "wait", event: eventName, id }
486
+ });
487
+ }
488
+ const outcome = await waiter.outcome;
489
+ if (outcome === "aborted")
490
+ throw new ParkAbortedError(label);
491
+ } finally {
492
+ waiter.cancel();
493
+ unsubscribe?.();
494
+ }
495
+ }
496
+ }
497
+
303
498
  // src/durability/engine.ts
304
499
  function releaseSettled(registry, key, pending) {
305
500
  const release = () => {
@@ -315,14 +510,21 @@ function createLocalStepDurability(options) {
315
510
  const { store, conversationId, runId } = options;
316
511
  const inFlight = stores.get(store) ?? {
317
512
  steps: new Map,
513
+ effects: new Map,
318
514
  parks: new Map,
319
515
  waiters: new Map
320
516
  };
321
517
  stores.set(store, inFlight);
322
- const { steps: inFlightSteps, parks: inFlightParks, waiters: parkWaiters } = inFlight;
518
+ const {
519
+ steps: inFlightSteps,
520
+ effects: inFlightEffects,
521
+ parks: inFlightParks,
522
+ waiters: parkWaiters
523
+ } = inFlight;
323
524
  const clock = options.clock ?? systemClock;
324
525
  const view = {
325
526
  steps: new Map,
527
+ effects: new Map,
326
528
  parks: new Map,
327
529
  deliveries: new Map,
328
530
  nextSeq: 1
@@ -332,6 +534,16 @@ function createLocalStepDurability(options) {
332
534
  reading = reading.catch(() => view).then(() => readDurabilityLedger(store, conversationId, view));
333
535
  return reading;
334
536
  };
537
+ const park = {
538
+ store,
539
+ conversationId,
540
+ runId,
541
+ signal: options.signal,
542
+ subscribe: options.subscribe,
543
+ clock,
544
+ waiters: parkWaiters,
545
+ readLedger
546
+ };
335
547
  const readRecordedStep = async (name) => {
336
548
  const key = stepKey(conversationId, runId, name);
337
549
  const records = await readLedger();
@@ -365,30 +577,16 @@ function createLocalStepDurability(options) {
365
577
  releaseSettled(inFlightSteps, key, pending);
366
578
  return detachedResult(pending);
367
579
  };
368
- const executeSleep = async (name, seconds, runOptions) => {
369
- const key = sleepParkKey(conversationId, runId, name);
370
- const signal = options.signal && runOptions?.signal ? AbortSignal.any([options.signal, runOptions.signal]) : runOptions?.signal ?? options.signal;
371
- const ledger = await readLedger();
372
- const existing = ledger.parks.get(key);
373
- let deadline;
580
+ const effect = (name, handlers, runOptions) => {
581
+ const key = effectKey(conversationId, runId, name);
582
+ const existing = inFlightEffects.get(key);
374
583
  if (existing) {
375
- if (existing.kind !== "sleep") {
376
- throw new ParkRecordDecodeError(`Recorded park "${name}" is not a sleep record`);
377
- }
378
- deadline = existing.deadline;
379
- } else {
380
- deadline = clock.now() + seconds * 1000;
381
- if (!Number.isSafeInteger(Math.ceil(deadline)))
382
- throw new TypeError("Sleep deadline exceeds the supported clock range");
383
- await store.appendEvent({
384
- conversationId,
385
- kind: DURABILITY_PARK_EVENT_KIND,
386
- payload: { runId, kind: "sleep", name, deadline }
387
- });
584
+ return detachedResult(existing);
388
585
  }
389
- if (signal?.aborted)
390
- throw new ParkAbortedError(name);
391
- await waitForDeadline(clock, deadline, name, signal);
586
+ const pending = executeEffect({ store, conversationId, runId, signal: options.signal, readLedger }, name, handlers, runOptions);
587
+ inFlightEffects.set(key, pending);
588
+ releaseSettled(inFlightEffects, key, pending);
589
+ return detachedResult(pending);
392
590
  };
393
591
  const sleep = (input, runOptions) => {
394
592
  const { seconds } = input;
@@ -401,49 +599,18 @@ function createLocalStepDurability(options) {
401
599
  if (existing) {
402
600
  return existing;
403
601
  }
404
- const pending = executeSleep(name, seconds, runOptions);
602
+ const pending = executeSleep(park, name, seconds, runOptions);
405
603
  inFlightParks.set(key, pending);
406
604
  releaseSettled(inFlightParks, key, pending);
407
605
  return pending;
408
606
  };
409
- const executeWait = async (eventName, id, runOptions) => {
410
- const key = waitParkKey(conversationId, runId, eventName, id);
411
- const park = `${eventName}#${id}`;
412
- const signal = options.signal && runOptions?.signal ? AbortSignal.any([options.signal, runOptions.signal]) : runOptions?.signal ?? options.signal;
413
- for (;; ) {
414
- if (signal?.aborted)
415
- throw new ParkAbortedError(park);
416
- const waiter = createParkWaiter(parkWaiters, key, signal);
417
- let unsubscribe;
418
- try {
419
- unsubscribe = options.subscribe?.(() => notifyWaiters(parkWaiters, key));
420
- const ledger = await readLedger();
421
- if (ledger.deliveries.has(key)) {
422
- return JSON.parse(JSON.stringify(ledger.deliveries.get(key)));
423
- }
424
- if (!ledger.parks.has(key)) {
425
- await store.appendEvent({
426
- conversationId,
427
- kind: DURABILITY_PARK_EVENT_KIND,
428
- payload: { runId, kind: "wait", event: eventName, id }
429
- });
430
- }
431
- const outcome = await waiter.outcome;
432
- if (outcome === "aborted")
433
- throw new ParkAbortedError(park);
434
- } finally {
435
- waiter.cancel();
436
- unsubscribe?.();
437
- }
438
- }
439
- };
440
607
  const waitFor = (input, runOptions) => {
441
608
  const key = waitParkKey(conversationId, runId, input.event, input.id);
442
609
  const existing = inFlightParks.get(key);
443
610
  if (existing) {
444
611
  return detachedResult(existing);
445
612
  }
446
- const pending = executeWait(input.event, input.id, runOptions);
613
+ const pending = executeWait(park, input.event, input.id, runOptions);
447
614
  inFlightParks.set(key, pending);
448
615
  releaseSettled(inFlightParks, key, pending);
449
616
  return detachedResult(pending);
@@ -467,7 +634,8 @@ function createLocalStepDurability(options) {
467
634
  hasRecordedStep: async (name) => await readRecordedStep(name) !== undefined,
468
635
  sleep,
469
636
  waitFor,
470
- deliver
637
+ deliver,
638
+ effect
471
639
  };
472
640
  }
473
641
 
@@ -504,4 +672,4 @@ function resolveToolDurability(context, callId, signal) {
504
672
  return contexts.get(context)?.(callId, signal);
505
673
  }
506
674
 
507
- export { DURABILITY_STEP_EVENT_KIND, StepResultDecodeError, StepResultNotSerializableError, StepAbortedError, ParkRecordDecodeError, ParkAbortedError, createLocalStepDurability, AgentToolError, isAgentToolError, createToolDurabilityContext, resolveToolDurability };
675
+ export { DURABILITY_STEP_EVENT_KIND, StepResultDecodeError, StepResultNotSerializableError, StepAbortedError, EffectUnresolvedError, ParkRecordDecodeError, ParkAbortedError, createLocalStepDurability, AgentToolError, isAgentToolError, createToolDurabilityContext, resolveToolDurability };
@@ -16,7 +16,7 @@ import {
16
16
  createToolChronology,
17
17
  isAssistantHistoryEvidence,
18
18
  isCompleteAgentHistoryTurn
19
- } from "./index-1nd48tm9.js";
19
+ } from "./index-gxrt5h6v.js";
20
20
  import {
21
21
  AgentAssistantPlaceholderSchema,
22
22
  AgentJsonObjectSchema,
@@ -33,11 +33,11 @@ import {
33
33
  createLocalStepDurability,
34
34
  createToolDurabilityContext,
35
35
  isAgentToolError
36
- } from "./index-cq4qfycf.js";
36
+ } from "./index-79z7m7dt.js";
37
37
  import {
38
38
  ToolExecutionControlError,
39
39
  isToolExecutionControlError
40
- } from "./index-j05z5gn4.js";
40
+ } from "./index-55hkhm67.js";
41
41
  import {
42
42
  isRecord,
43
43
  transportResult
@@ -4,7 +4,7 @@ import {
4
4
  } from "./index-rxfy4cq7.js";
5
5
  import {
6
6
  defineContract
7
- } from "./index-gyr48nzg.js";
7
+ } from "./index-k30h66yd.js";
8
8
  import {
9
9
  AppError,
10
10
  STITCH_ERROR_STATUS,
@@ -1,19 +1,19 @@
1
1
  import {
2
2
  AgentToolError,
3
3
  resolveToolDurability
4
- } from "./index-cq4qfycf.js";
4
+ } from "./index-79z7m7dt.js";
5
5
  import {
6
6
  collectToolSurface
7
- } from "./index-vcvkq30w.js";
7
+ } from "./index-hmp4800j.js";
8
8
  import {
9
9
  createToolRunner,
10
10
  formatToolError
11
- } from "./index-2cr1cqhn.js";
11
+ } from "./index-khtgb21r.js";
12
12
  import {
13
13
  isToolExecutionControlError,
14
14
  toolCauseFromResult,
15
15
  toolResultFromError
16
- } from "./index-j05z5gn4.js";
16
+ } from "./index-55hkhm67.js";
17
17
  import {
18
18
  isRecord
19
19
  } from "./index-hffjpmq9.js";
@@ -0,0 +1,242 @@
1
+ import {
2
+ isRecord
3
+ } from "./index-hffjpmq9.js";
4
+
5
+ // src/internal/exclusive-lock.ts
6
+ import { constants } from "node:fs";
7
+ import { lstat, open, unlink } from "node:fs/promises";
8
+ import { hostname } from "node:os";
9
+
10
+ // src/internal/process-identity.ts
11
+ import { execFile } from "node:child_process";
12
+ import { readFile } from "node:fs/promises";
13
+ import { platform } from "node:os";
14
+ import { promisify } from "node:util";
15
+ var detectedIdentity;
16
+ async function firstReadableLine(paths) {
17
+ for (const path of paths) {
18
+ try {
19
+ const text = (await readFile(path, "utf8")).trim();
20
+ if (text.length > 0)
21
+ return text;
22
+ } catch {}
23
+ }
24
+ return null;
25
+ }
26
+ var run = promisify(execFile);
27
+ function parsePlatformUuid(dump) {
28
+ return /"IOPlatformUUID"\s*=\s*"([^"]+)"/.exec(dump)?.[1] ?? null;
29
+ }
30
+ async function readDarwinPlatformUuid(command = "ioreg") {
31
+ try {
32
+ const { stdout } = await run(command, ["-rd1", "-c", "IOPlatformExpertDevice"], {
33
+ timeout: 2000,
34
+ maxBuffer: 1 << 20,
35
+ encoding: "utf8"
36
+ });
37
+ return parsePlatformUuid(stdout);
38
+ } catch {
39
+ return null;
40
+ }
41
+ }
42
+ async function machineIdentity(declared) {
43
+ if (declared !== undefined)
44
+ return declared;
45
+ if (detectedIdentity !== undefined)
46
+ return detectedIdentity;
47
+ detectedIdentity = platform() === "darwin" ? await readDarwinPlatformUuid() : await firstReadableLine(["/etc/machine-id", "/var/lib/dbus/machine-id"]);
48
+ return detectedIdentity;
49
+ }
50
+ async function probeLiveness(pid) {
51
+ try {
52
+ process.kill(pid, 0);
53
+ } catch (error) {
54
+ return isRecord(error) && error.code === "ESRCH" ? "gone" : "alive";
55
+ }
56
+ return await isZombieProcess(pid) ? "gone" : "alive";
57
+ }
58
+ async function isZombieProcess(pid, seam = {}) {
59
+ const { procRoot = "/proc", psCommand = "ps" } = seam;
60
+ try {
61
+ const stat = await readFile(`${procRoot}/${pid}/stat`, "utf8");
62
+ return stat.slice(stat.lastIndexOf(")") + 1).trimStart().startsWith("Z");
63
+ } catch {}
64
+ try {
65
+ const { stdout } = await run(psCommand, ["-o", "state=", "-p", String(pid)], {
66
+ timeout: 2000,
67
+ maxBuffer: 1 << 16,
68
+ encoding: "utf8"
69
+ });
70
+ return stdout.trim().startsWith("Z");
71
+ } catch {
72
+ return false;
73
+ }
74
+ }
75
+
76
+ // src/internal/exclusive-lock.ts
77
+ function isCode(error, code) {
78
+ return isRecord(error) && error.code === code;
79
+ }
80
+ function readOwner(text) {
81
+ let parsed;
82
+ try {
83
+ parsed = JSON.parse(text);
84
+ } catch {
85
+ return;
86
+ }
87
+ if (!isRecord(parsed))
88
+ return;
89
+ const { pid, host, acquiredAt, machine } = parsed;
90
+ if (typeof pid !== "number" || !Number.isSafeInteger(pid) || pid <= 0)
91
+ return;
92
+ if (typeof host !== "string" || host.length === 0)
93
+ return;
94
+ if (typeof acquiredAt !== "string")
95
+ return;
96
+ const identified = typeof machine === "string" && machine.length > 0 ? { machine } : {};
97
+ return { pid, host, acquiredAt, ...identified };
98
+ }
99
+ function attribute(owner, identity) {
100
+ if (identity !== null && owner.machine !== undefined) {
101
+ return owner.machine === identity ? "this-machine" : "another-machine";
102
+ }
103
+ return owner.host === hostname() ? "this-machine" : "unattributable";
104
+ }
105
+ async function diagnose(owner, declaredIdentity) {
106
+ if (!owner)
107
+ return { attribution: "unattributable", liveness: "not-probed", owner: null };
108
+ const attribution = attribute(owner, await machineIdentity(declaredIdentity));
109
+ if (attribution !== "this-machine")
110
+ return { attribution, liveness: "not-probed", owner };
111
+ return { attribution, liveness: await probeLiveness(owner.pid), owner };
112
+ }
113
+ async function readLockFile(path) {
114
+ let handle;
115
+ try {
116
+ handle = await open(path, constants.O_RDONLY | constants.O_NOFOLLOW);
117
+ const info = await handle.stat();
118
+ return {
119
+ owner: readOwner(await handle.readFile("utf8")),
120
+ ino: info.ino,
121
+ mtimeMs: info.mtimeMs
122
+ };
123
+ } catch {
124
+ return;
125
+ } finally {
126
+ await handle?.close().catch(() => {
127
+ return;
128
+ });
129
+ }
130
+ }
131
+ async function unlinkIfSame(path, ino) {
132
+ try {
133
+ if ((await lstat(path)).ino !== ino)
134
+ return;
135
+ await unlink(path);
136
+ } catch (error) {
137
+ if (!isCode(error, "ENOENT"))
138
+ throw error;
139
+ }
140
+ }
141
+ async function createOwned(path, options, reclaimed) {
142
+ const identity = await machineIdentity(options.machineIdentity);
143
+ const handle = await open(path, "wx", options.mode);
144
+ const owner = {
145
+ pid: process.pid,
146
+ host: hostname(),
147
+ acquiredAt: new Date().toISOString(),
148
+ ...identity !== null && { machine: identity }
149
+ };
150
+ let ino;
151
+ try {
152
+ await handle.writeFile(`${JSON.stringify(owner)}
153
+ `, "utf8");
154
+ ino = (await handle.stat()).ino;
155
+ } catch (error) {
156
+ await handle.close().catch(() => {
157
+ return;
158
+ });
159
+ await unlink(path).catch(() => {
160
+ return;
161
+ });
162
+ throw error;
163
+ }
164
+ let released = false;
165
+ return {
166
+ path,
167
+ owner,
168
+ reclaimed,
169
+ async release() {
170
+ if (released)
171
+ return;
172
+ released = true;
173
+ try {
174
+ await handle.close();
175
+ } finally {
176
+ await unlinkIfSame(path, ino);
177
+ }
178
+ }
179
+ };
180
+ }
181
+ function reclaimable(state, diagnosis, graceMs) {
182
+ if (state.owner)
183
+ return diagnosis.liveness === "gone";
184
+ return graceMs !== undefined && Date.now() - state.mtimeMs >= graceMs;
185
+ }
186
+ async function reclaimUnderGuard(path, options) {
187
+ const guardPath = `${path}.reclaim`;
188
+ let guard;
189
+ try {
190
+ guard = await createOwned(guardPath, options, false);
191
+ } catch (error) {
192
+ if (!isCode(error, "EEXIST"))
193
+ throw error;
194
+ const stale = await readLockFile(guardPath);
195
+ if (stale) {
196
+ const verdict = await diagnose(stale.owner, options.machineIdentity);
197
+ if (reclaimable(stale, verdict, options.ownerlessGraceMs ?? 5000)) {
198
+ await unlinkIfSame(guardPath, stale.ino);
199
+ }
200
+ }
201
+ return;
202
+ }
203
+ try {
204
+ const state = await readLockFile(path);
205
+ if (state) {
206
+ const diagnosis = await diagnose(state.owner, options.machineIdentity);
207
+ if (!reclaimable(state, diagnosis, options.ownerlessGraceMs))
208
+ return "refused";
209
+ await unlinkIfSame(path, state.ino);
210
+ }
211
+ return await createOwned(path, options, state !== undefined).catch((error) => {
212
+ if (isCode(error, "EEXIST"))
213
+ return "refused";
214
+ throw error;
215
+ });
216
+ } finally {
217
+ await guard.release().catch(() => {
218
+ return;
219
+ });
220
+ }
221
+ }
222
+ async function attemptExclusiveLock(path, options) {
223
+ try {
224
+ return { held: await createOwned(path, options, false) };
225
+ } catch (error) {
226
+ if (!isCode(error, "EEXIST"))
227
+ throw error;
228
+ if (!options.reclaim)
229
+ return { error };
230
+ const state = await readLockFile(path);
231
+ const diagnosis = await diagnose(state?.owner, options.machineIdentity);
232
+ if (!state || !reclaimable(state, diagnosis, options.ownerlessGraceMs)) {
233
+ return { error, diagnosis };
234
+ }
235
+ const reclaimed = await reclaimUnderGuard(path, options);
236
+ if (reclaimed !== undefined && reclaimed !== "refused")
237
+ return { held: reclaimed };
238
+ return { error, diagnosis };
239
+ }
240
+ }
241
+
242
+ export { attemptExclusiveLock };