lorenz 0.1.5 → 0.1.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (301) hide show
  1. package/README.md +83 -20
  2. package/RELEASE-MANIFEST.json +6 -1
  3. package/node_modules/@lorenz/agent-sdk/dist/index.d.ts +1 -0
  4. package/node_modules/@lorenz/agent-sdk/dist/index.d.ts.map +1 -1
  5. package/node_modules/@lorenz/agent-sdk/dist/index.js +1 -0
  6. package/node_modules/@lorenz/agent-sdk/dist/index.js.map +1 -1
  7. package/node_modules/@lorenz/agent-sdk/dist/module.d.ts +38 -0
  8. package/node_modules/@lorenz/agent-sdk/dist/module.d.ts.map +1 -0
  9. package/node_modules/@lorenz/agent-sdk/dist/module.js +41 -0
  10. package/node_modules/@lorenz/agent-sdk/dist/module.js.map +1 -0
  11. package/node_modules/@lorenz/cli/dist/agentExecutorLoader.d.ts +30 -0
  12. package/node_modules/@lorenz/cli/dist/agentExecutorLoader.d.ts.map +1 -0
  13. package/node_modules/@lorenz/cli/dist/agentExecutorLoader.js +63 -0
  14. package/node_modules/@lorenz/cli/dist/agentExecutorLoader.js.map +1 -0
  15. package/node_modules/@lorenz/cli/dist/daemon.d.ts +42 -19
  16. package/node_modules/@lorenz/cli/dist/daemon.d.ts.map +1 -1
  17. package/node_modules/@lorenz/cli/dist/daemon.js +74 -28
  18. package/node_modules/@lorenz/cli/dist/daemon.js.map +1 -1
  19. package/node_modules/@lorenz/cli/dist/daemonLock.d.ts +59 -0
  20. package/node_modules/@lorenz/cli/dist/daemonLock.d.ts.map +1 -0
  21. package/node_modules/@lorenz/cli/dist/daemonLock.js +304 -0
  22. package/node_modules/@lorenz/cli/dist/daemonLock.js.map +1 -0
  23. package/node_modules/@lorenz/cli/dist/daemonStatus.d.ts +16 -0
  24. package/node_modules/@lorenz/cli/dist/daemonStatus.d.ts.map +1 -0
  25. package/node_modules/@lorenz/cli/dist/daemonStatus.js +21 -0
  26. package/node_modules/@lorenz/cli/dist/daemonStatus.js.map +1 -0
  27. package/node_modules/@lorenz/cli/dist/doctor.d.ts +6 -0
  28. package/node_modules/@lorenz/cli/dist/doctor.d.ts.map +1 -1
  29. package/node_modules/@lorenz/cli/dist/doctor.js +38 -1
  30. package/node_modules/@lorenz/cli/dist/doctor.js.map +1 -1
  31. package/node_modules/@lorenz/cli/dist/extensionLoader.d.ts +126 -0
  32. package/node_modules/@lorenz/cli/dist/extensionLoader.d.ts.map +1 -0
  33. package/node_modules/@lorenz/cli/dist/extensionLoader.js +187 -0
  34. package/node_modules/@lorenz/cli/dist/extensionLoader.js.map +1 -0
  35. package/node_modules/@lorenz/cli/dist/flags-manifest.d.ts +42 -0
  36. package/node_modules/@lorenz/cli/dist/flags-manifest.d.ts.map +1 -0
  37. package/node_modules/@lorenz/cli/dist/flags-manifest.js +67 -0
  38. package/node_modules/@lorenz/cli/dist/flags-manifest.js.map +1 -0
  39. package/node_modules/@lorenz/cli/dist/index.d.ts +6 -0
  40. package/node_modules/@lorenz/cli/dist/index.d.ts.map +1 -1
  41. package/node_modules/@lorenz/cli/dist/index.js +4 -0
  42. package/node_modules/@lorenz/cli/dist/index.js.map +1 -1
  43. package/node_modules/@lorenz/cli/dist/leadershipStore.d.ts +42 -0
  44. package/node_modules/@lorenz/cli/dist/leadershipStore.d.ts.map +1 -0
  45. package/node_modules/@lorenz/cli/dist/leadershipStore.js +2 -0
  46. package/node_modules/@lorenz/cli/dist/leadershipStore.js.map +1 -0
  47. package/node_modules/@lorenz/cli/dist/main.d.ts +11 -7
  48. package/node_modules/@lorenz/cli/dist/main.d.ts.map +1 -1
  49. package/node_modules/@lorenz/cli/dist/main.js +58 -8
  50. package/node_modules/@lorenz/cli/dist/main.js.map +1 -1
  51. package/node_modules/@lorenz/cli/dist/toolLoader.d.ts +28 -0
  52. package/node_modules/@lorenz/cli/dist/toolLoader.d.ts.map +1 -0
  53. package/node_modules/@lorenz/cli/dist/toolLoader.js +62 -0
  54. package/node_modules/@lorenz/cli/dist/toolLoader.js.map +1 -0
  55. package/node_modules/@lorenz/cli/dist/trackerLoader.d.ts +24 -0
  56. package/node_modules/@lorenz/cli/dist/trackerLoader.d.ts.map +1 -0
  57. package/node_modules/@lorenz/cli/dist/trackerLoader.js +34 -0
  58. package/node_modules/@lorenz/cli/dist/trackerLoader.js.map +1 -0
  59. package/node_modules/@lorenz/cli/dist/workerDriverLoader.d.ts +15 -55
  60. package/node_modules/@lorenz/cli/dist/workerDriverLoader.d.ts.map +1 -1
  61. package/node_modules/@lorenz/cli/dist/workerDriverLoader.js +26 -203
  62. package/node_modules/@lorenz/cli/dist/workerDriverLoader.js.map +1 -1
  63. package/node_modules/@lorenz/cli/package.json +1 -0
  64. package/node_modules/@lorenz/config/dist/index.d.ts +1 -1
  65. package/node_modules/@lorenz/config/dist/index.d.ts.map +1 -1
  66. package/node_modules/@lorenz/config/dist/index.js +1 -1
  67. package/node_modules/@lorenz/config/dist/index.js.map +1 -1
  68. package/node_modules/@lorenz/config/dist/parse.d.ts +17 -0
  69. package/node_modules/@lorenz/config/dist/parse.d.ts.map +1 -1
  70. package/node_modules/@lorenz/config/dist/parse.js +107 -11
  71. package/node_modules/@lorenz/config/dist/parse.js.map +1 -1
  72. package/node_modules/@lorenz/config/dist/schemas.d.ts +0 -2
  73. package/node_modules/@lorenz/config/dist/schemas.d.ts.map +1 -1
  74. package/node_modules/@lorenz/config/dist/schemas.js +5 -1
  75. package/node_modules/@lorenz/config/dist/schemas.js.map +1 -1
  76. package/node_modules/@lorenz/dispatch-coordinator/dist/coordinator.d.ts +55 -21
  77. package/node_modules/@lorenz/dispatch-coordinator/dist/coordinator.d.ts.map +1 -1
  78. package/node_modules/@lorenz/dispatch-coordinator/dist/coordinator.js +187 -82
  79. package/node_modules/@lorenz/dispatch-coordinator/dist/coordinator.js.map +1 -1
  80. package/node_modules/@lorenz/dispatch-coordinator/dist/gate.d.ts +6 -4
  81. package/node_modules/@lorenz/dispatch-coordinator/dist/gate.d.ts.map +1 -1
  82. package/node_modules/@lorenz/dispatch-coordinator/dist/gate.js +9 -6
  83. package/node_modules/@lorenz/dispatch-coordinator/dist/gate.js.map +1 -1
  84. package/node_modules/@lorenz/dispatch-coordinator/dist/index.d.ts +1 -1
  85. package/node_modules/@lorenz/dispatch-coordinator/dist/index.d.ts.map +1 -1
  86. package/node_modules/@lorenz/dispatch-coordinator/dist/index.js +5 -6
  87. package/node_modules/@lorenz/dispatch-coordinator/dist/index.js.map +1 -1
  88. package/node_modules/@lorenz/dispatch-coordinator/dist/mcpEndpointManager.d.ts +7 -5
  89. package/node_modules/@lorenz/dispatch-coordinator/dist/mcpEndpointManager.d.ts.map +1 -1
  90. package/node_modules/@lorenz/dispatch-coordinator/dist/mcpEndpointManager.js +12 -10
  91. package/node_modules/@lorenz/dispatch-coordinator/dist/mcpEndpointManager.js.map +1 -1
  92. package/node_modules/@lorenz/dispatch-coordinator/dist/nullEndpointManager.d.ts +11 -10
  93. package/node_modules/@lorenz/dispatch-coordinator/dist/nullEndpointManager.d.ts.map +1 -1
  94. package/node_modules/@lorenz/dispatch-coordinator/dist/nullEndpointManager.js +15 -22
  95. package/node_modules/@lorenz/dispatch-coordinator/dist/nullEndpointManager.js.map +1 -1
  96. package/node_modules/@lorenz/dispatch-coordinator/dist/types.d.ts +16 -15
  97. package/node_modules/@lorenz/dispatch-coordinator/dist/types.d.ts.map +1 -1
  98. package/node_modules/@lorenz/dispatch-coordinator/dist/types.js +6 -7
  99. package/node_modules/@lorenz/dispatch-coordinator/dist/types.js.map +1 -1
  100. package/node_modules/@lorenz/domain/dist/index.d.ts +75 -9
  101. package/node_modules/@lorenz/domain/dist/index.d.ts.map +1 -1
  102. package/node_modules/@lorenz/domain/dist/index.js +40 -0
  103. package/node_modules/@lorenz/domain/dist/index.js.map +1 -1
  104. package/node_modules/@lorenz/flags/dist/coerce.d.ts +12 -0
  105. package/node_modules/@lorenz/flags/dist/coerce.d.ts.map +1 -0
  106. package/node_modules/@lorenz/flags/dist/coerce.js +44 -0
  107. package/node_modules/@lorenz/flags/dist/coerce.js.map +1 -0
  108. package/node_modules/@lorenz/flags/dist/default.d.ts +6 -0
  109. package/node_modules/@lorenz/flags/dist/default.d.ts.map +1 -0
  110. package/node_modules/@lorenz/flags/dist/default.js +22 -0
  111. package/node_modules/@lorenz/flags/dist/default.js.map +1 -0
  112. package/node_modules/@lorenz/flags/dist/deprecations.d.ts +20 -0
  113. package/node_modules/@lorenz/flags/dist/deprecations.d.ts.map +1 -0
  114. package/node_modules/@lorenz/flags/dist/deprecations.js +42 -0
  115. package/node_modules/@lorenz/flags/dist/deprecations.js.map +1 -0
  116. package/node_modules/@lorenz/flags/dist/env.d.ts +17 -0
  117. package/node_modules/@lorenz/flags/dist/env.d.ts.map +1 -0
  118. package/node_modules/@lorenz/flags/dist/env.js +90 -0
  119. package/node_modules/@lorenz/flags/dist/env.js.map +1 -0
  120. package/node_modules/@lorenz/flags/dist/errors.d.ts +22 -0
  121. package/node_modules/@lorenz/flags/dist/errors.d.ts.map +1 -0
  122. package/node_modules/@lorenz/flags/dist/errors.js +61 -0
  123. package/node_modules/@lorenz/flags/dist/errors.js.map +1 -0
  124. package/node_modules/@lorenz/flags/dist/index.d.ts +8 -0
  125. package/node_modules/@lorenz/flags/dist/index.d.ts.map +1 -0
  126. package/node_modules/@lorenz/flags/dist/index.js +11 -0
  127. package/node_modules/@lorenz/flags/dist/index.js.map +1 -0
  128. package/node_modules/@lorenz/flags/dist/keys.d.ts +6 -0
  129. package/node_modules/@lorenz/flags/dist/keys.d.ts.map +1 -0
  130. package/node_modules/@lorenz/flags/dist/keys.js +15 -0
  131. package/node_modules/@lorenz/flags/dist/keys.js.map +1 -0
  132. package/node_modules/@lorenz/flags/dist/layers.d.ts +14 -0
  133. package/node_modules/@lorenz/flags/dist/layers.d.ts.map +1 -0
  134. package/node_modules/@lorenz/flags/dist/layers.js +107 -0
  135. package/node_modules/@lorenz/flags/dist/layers.js.map +1 -0
  136. package/node_modules/@lorenz/flags/dist/manifest.d.ts +71 -0
  137. package/node_modules/@lorenz/flags/dist/manifest.d.ts.map +1 -0
  138. package/node_modules/@lorenz/flags/dist/manifest.js +137 -0
  139. package/node_modules/@lorenz/flags/dist/manifest.js.map +1 -0
  140. package/node_modules/@lorenz/flags/dist/resolve.d.ts +8 -0
  141. package/node_modules/@lorenz/flags/dist/resolve.d.ts.map +1 -0
  142. package/node_modules/@lorenz/flags/dist/resolve.js +178 -0
  143. package/node_modules/@lorenz/flags/dist/resolve.js.map +1 -0
  144. package/node_modules/@lorenz/flags/dist/testing.d.ts +19 -0
  145. package/node_modules/@lorenz/flags/dist/testing.d.ts.map +1 -0
  146. package/node_modules/@lorenz/flags/dist/testing.js +68 -0
  147. package/node_modules/@lorenz/flags/dist/testing.js.map +1 -0
  148. package/node_modules/@lorenz/flags/dist/types.d.ts +93 -0
  149. package/node_modules/@lorenz/flags/dist/types.d.ts.map +1 -0
  150. package/node_modules/@lorenz/flags/dist/types.js +2 -0
  151. package/node_modules/@lorenz/flags/dist/types.js.map +1 -0
  152. package/node_modules/@lorenz/flags/package.json +16 -0
  153. package/node_modules/@lorenz/jira-tracker/dist/index.d.ts +1 -0
  154. package/node_modules/@lorenz/jira-tracker/dist/index.d.ts.map +1 -1
  155. package/node_modules/@lorenz/jira-tracker/dist/index.js +1 -0
  156. package/node_modules/@lorenz/jira-tracker/dist/index.js.map +1 -1
  157. package/node_modules/@lorenz/jira-tracker/dist/provider.d.ts.map +1 -1
  158. package/node_modules/@lorenz/jira-tracker/dist/provider.js +3 -36
  159. package/node_modules/@lorenz/jira-tracker/dist/provider.js.map +1 -1
  160. package/node_modules/@lorenz/jira-tracker/dist/register.d.ts +5 -3
  161. package/node_modules/@lorenz/jira-tracker/dist/register.d.ts.map +1 -1
  162. package/node_modules/@lorenz/jira-tracker/dist/register.js +9 -3
  163. package/node_modules/@lorenz/jira-tracker/dist/register.js.map +1 -1
  164. package/node_modules/@lorenz/jira-tracker/dist/tools.d.ts +18 -0
  165. package/node_modules/@lorenz/jira-tracker/dist/tools.d.ts.map +1 -0
  166. package/node_modules/@lorenz/{tracker-sdk/dist/toolPack.js → jira-tracker/dist/tools.js} +76 -78
  167. package/node_modules/@lorenz/jira-tracker/dist/tools.js.map +1 -0
  168. package/node_modules/@lorenz/jira-tracker/package.json +1 -0
  169. package/node_modules/@lorenz/linear-tracker/dist/provider.d.ts.map +1 -1
  170. package/node_modules/@lorenz/linear-tracker/dist/provider.js +0 -2
  171. package/node_modules/@lorenz/linear-tracker/dist/provider.js.map +1 -1
  172. package/node_modules/@lorenz/local-tracker/dist/provider.d.ts.map +1 -1
  173. package/node_modules/@lorenz/local-tracker/dist/provider.js +0 -2
  174. package/node_modules/@lorenz/local-tracker/dist/provider.js.map +1 -1
  175. package/node_modules/@lorenz/mcp/dist/agentEndpoint.d.ts +16 -3
  176. package/node_modules/@lorenz/mcp/dist/agentEndpoint.d.ts.map +1 -1
  177. package/node_modules/@lorenz/mcp/dist/agentEndpoint.js +105 -17
  178. package/node_modules/@lorenz/mcp/dist/agentEndpoint.js.map +1 -1
  179. package/node_modules/@lorenz/mcp/dist/auth.d.ts +88 -0
  180. package/node_modules/@lorenz/mcp/dist/auth.d.ts.map +1 -1
  181. package/node_modules/@lorenz/mcp/dist/auth.js +53 -0
  182. package/node_modules/@lorenz/mcp/dist/auth.js.map +1 -1
  183. package/node_modules/@lorenz/mcp/dist/index.d.ts +3 -2
  184. package/node_modules/@lorenz/mcp/dist/index.d.ts.map +1 -1
  185. package/node_modules/@lorenz/mcp/dist/index.js +1 -1
  186. package/node_modules/@lorenz/mcp/dist/index.js.map +1 -1
  187. package/node_modules/@lorenz/mcp/dist/server.d.ts +22 -0
  188. package/node_modules/@lorenz/mcp/dist/server.d.ts.map +1 -1
  189. package/node_modules/@lorenz/mcp/dist/server.js +85 -12
  190. package/node_modules/@lorenz/mcp/dist/server.js.map +1 -1
  191. package/node_modules/@lorenz/mcp/dist/tools.d.ts.map +1 -1
  192. package/node_modules/@lorenz/mcp/dist/tools.js +5 -8
  193. package/node_modules/@lorenz/mcp/dist/tools.js.map +1 -1
  194. package/node_modules/@lorenz/orchestrator/dist/claimStore.d.ts +157 -0
  195. package/node_modules/@lorenz/orchestrator/dist/claimStore.d.ts.map +1 -0
  196. package/node_modules/@lorenz/orchestrator/dist/claimStore.js +621 -0
  197. package/node_modules/@lorenz/orchestrator/dist/claimStore.js.map +1 -0
  198. package/node_modules/@lorenz/orchestrator/dist/codec.d.ts +38 -0
  199. package/node_modules/@lorenz/orchestrator/dist/codec.d.ts.map +1 -0
  200. package/node_modules/@lorenz/orchestrator/dist/codec.js +176 -0
  201. package/node_modules/@lorenz/orchestrator/dist/codec.js.map +1 -0
  202. package/node_modules/@lorenz/orchestrator/dist/index.d.ts +55 -51
  203. package/node_modules/@lorenz/orchestrator/dist/index.d.ts.map +1 -1
  204. package/node_modules/@lorenz/orchestrator/dist/index.js +285 -45
  205. package/node_modules/@lorenz/orchestrator/dist/index.js.map +1 -1
  206. package/node_modules/@lorenz/orchestrator/dist/sqlite.d.ts +34 -0
  207. package/node_modules/@lorenz/orchestrator/dist/sqlite.d.ts.map +1 -0
  208. package/node_modules/@lorenz/orchestrator/dist/sqlite.js +142 -0
  209. package/node_modules/@lorenz/orchestrator/dist/sqlite.js.map +1 -0
  210. package/node_modules/@lorenz/orchestrator/dist/state.d.ts +47 -0
  211. package/node_modules/@lorenz/orchestrator/dist/state.d.ts.map +1 -0
  212. package/node_modules/@lorenz/orchestrator/dist/state.js +15 -0
  213. package/node_modules/@lorenz/orchestrator/dist/state.js.map +1 -0
  214. package/node_modules/@lorenz/orchestrator/dist/turso.d.ts +28 -0
  215. package/node_modules/@lorenz/orchestrator/dist/turso.d.ts.map +1 -0
  216. package/node_modules/@lorenz/orchestrator/dist/turso.js +125 -0
  217. package/node_modules/@lorenz/orchestrator/dist/turso.js.map +1 -0
  218. package/node_modules/@lorenz/orchestrator/package.json +6 -2
  219. package/node_modules/@lorenz/presenter/dist/index.d.ts +14 -0
  220. package/node_modules/@lorenz/presenter/dist/index.d.ts.map +1 -1
  221. package/node_modules/@lorenz/presenter/dist/index.js +18 -0
  222. package/node_modules/@lorenz/presenter/dist/index.js.map +1 -1
  223. package/node_modules/@lorenz/projections/dist/index.d.ts.map +1 -1
  224. package/node_modules/@lorenz/projections/dist/index.js +1 -0
  225. package/node_modules/@lorenz/projections/dist/index.js.map +1 -1
  226. package/node_modules/@lorenz/runtime/dist/index.d.ts +27 -8
  227. package/node_modules/@lorenz/runtime/dist/index.d.ts.map +1 -1
  228. package/node_modules/@lorenz/runtime/dist/index.js +422 -98
  229. package/node_modules/@lorenz/runtime/dist/index.js.map +1 -1
  230. package/node_modules/@lorenz/runtime-events/dist/index.d.ts +14 -0
  231. package/node_modules/@lorenz/runtime-events/dist/index.d.ts.map +1 -1
  232. package/node_modules/@lorenz/slack-tracker/dist/client.d.ts +0 -7
  233. package/node_modules/@lorenz/slack-tracker/dist/client.d.ts.map +1 -1
  234. package/node_modules/@lorenz/slack-tracker/dist/client.js +4 -5
  235. package/node_modules/@lorenz/slack-tracker/dist/client.js.map +1 -1
  236. package/node_modules/@lorenz/slack-tracker/dist/index.d.ts +0 -1
  237. package/node_modules/@lorenz/slack-tracker/dist/index.d.ts.map +1 -1
  238. package/node_modules/@lorenz/slack-tracker/dist/index.js +0 -1
  239. package/node_modules/@lorenz/slack-tracker/dist/index.js.map +1 -1
  240. package/node_modules/@lorenz/slack-tracker/dist/provider.d.ts.map +1 -1
  241. package/node_modules/@lorenz/slack-tracker/dist/provider.js +0 -2
  242. package/node_modules/@lorenz/slack-tracker/dist/provider.js.map +1 -1
  243. package/node_modules/@lorenz/ssh/dist/index.d.ts +2 -0
  244. package/node_modules/@lorenz/ssh/dist/index.d.ts.map +1 -1
  245. package/node_modules/@lorenz/ssh/dist/index.js +2 -1
  246. package/node_modules/@lorenz/ssh/dist/index.js.map +1 -1
  247. package/node_modules/@lorenz/tool-sdk/dist/index.d.ts +1 -0
  248. package/node_modules/@lorenz/tool-sdk/dist/index.d.ts.map +1 -1
  249. package/node_modules/@lorenz/tool-sdk/dist/index.js +1 -0
  250. package/node_modules/@lorenz/tool-sdk/dist/index.js.map +1 -1
  251. package/node_modules/@lorenz/tool-sdk/dist/module.d.ts +38 -0
  252. package/node_modules/@lorenz/tool-sdk/dist/module.d.ts.map +1 -0
  253. package/node_modules/@lorenz/tool-sdk/dist/module.js +42 -0
  254. package/node_modules/@lorenz/tool-sdk/dist/module.js.map +1 -0
  255. package/node_modules/@lorenz/tracker-sdk/dist/index.d.ts +2 -2
  256. package/node_modules/@lorenz/tracker-sdk/dist/index.d.ts.map +1 -1
  257. package/node_modules/@lorenz/tracker-sdk/dist/index.js +1 -1
  258. package/node_modules/@lorenz/tracker-sdk/dist/index.js.map +1 -1
  259. package/node_modules/@lorenz/tracker-sdk/dist/module.d.ts +37 -0
  260. package/node_modules/@lorenz/tracker-sdk/dist/module.d.ts.map +1 -0
  261. package/node_modules/@lorenz/tracker-sdk/dist/module.js +38 -0
  262. package/node_modules/@lorenz/tracker-sdk/dist/module.js.map +1 -0
  263. package/node_modules/@lorenz/tracker-sdk/dist/provider.d.ts +11 -55
  264. package/node_modules/@lorenz/tracker-sdk/dist/provider.d.ts.map +1 -1
  265. package/node_modules/@lorenz/tracker-sdk/package.json +1 -2
  266. package/node_modules/@lorenz/worker-host-pool/dist/index.d.ts +34 -6
  267. package/node_modules/@lorenz/worker-host-pool/dist/index.d.ts.map +1 -1
  268. package/node_modules/@lorenz/worker-host-pool/dist/index.js +110 -143
  269. package/node_modules/@lorenz/worker-host-pool/dist/index.js.map +1 -1
  270. package/node_modules/@lorenz/worker-sdk/dist/index.d.ts +1 -0
  271. package/node_modules/@lorenz/worker-sdk/dist/index.d.ts.map +1 -1
  272. package/node_modules/@lorenz/worker-sdk/dist/index.js +1 -0
  273. package/node_modules/@lorenz/worker-sdk/dist/index.js.map +1 -1
  274. package/node_modules/@lorenz/worker-sdk/dist/local.d.ts +74 -0
  275. package/node_modules/@lorenz/worker-sdk/dist/local.d.ts.map +1 -0
  276. package/node_modules/@lorenz/worker-sdk/dist/local.js +112 -0
  277. package/node_modules/@lorenz/worker-sdk/dist/local.js.map +1 -0
  278. package/node_modules/@lorenz/worker-sdk/dist/module.d.ts +8 -16
  279. package/node_modules/@lorenz/worker-sdk/dist/module.d.ts.map +1 -1
  280. package/node_modules/@lorenz/worker-sdk/dist/module.js +15 -35
  281. package/node_modules/@lorenz/worker-sdk/dist/module.js.map +1 -1
  282. package/node_modules/@lorenz/workflow/dist/index.d.ts +11 -0
  283. package/node_modules/@lorenz/workflow/dist/index.d.ts.map +1 -1
  284. package/node_modules/@lorenz/workflow/dist/index.js +3 -0
  285. package/node_modules/@lorenz/workflow/dist/index.js.map +1 -1
  286. package/package.json +4 -1
  287. package/node_modules/@lorenz/linear-tracker/dist/toolOps.d.ts +0 -8
  288. package/node_modules/@lorenz/linear-tracker/dist/toolOps.d.ts.map +0 -1
  289. package/node_modules/@lorenz/linear-tracker/dist/toolOps.js +0 -251
  290. package/node_modules/@lorenz/linear-tracker/dist/toolOps.js.map +0 -1
  291. package/node_modules/@lorenz/local-tracker/dist/toolOps.d.ts +0 -9
  292. package/node_modules/@lorenz/local-tracker/dist/toolOps.d.ts.map +0 -1
  293. package/node_modules/@lorenz/local-tracker/dist/toolOps.js +0 -86
  294. package/node_modules/@lorenz/local-tracker/dist/toolOps.js.map +0 -1
  295. package/node_modules/@lorenz/slack-tracker/dist/toolOps.d.ts +0 -13
  296. package/node_modules/@lorenz/slack-tracker/dist/toolOps.d.ts.map +0 -1
  297. package/node_modules/@lorenz/slack-tracker/dist/toolOps.js +0 -76
  298. package/node_modules/@lorenz/slack-tracker/dist/toolOps.js.map +0 -1
  299. package/node_modules/@lorenz/tracker-sdk/dist/toolPack.d.ts +0 -10
  300. package/node_modules/@lorenz/tracker-sdk/dist/toolPack.d.ts.map +0 -1
  301. package/node_modules/@lorenz/tracker-sdk/dist/toolPack.js.map +0 -1
@@ -0,0 +1,42 @@
1
+ import { makeSdkModuleContract } from "@lorenz/domain";
2
+ /**
3
+ * The tool SDK version this build of the engine speaks. Out-of-tree tool-pack
4
+ * modules declare the version they target via {@link ToolProviderModule.sdkVersion};
5
+ * the loader rejects a mismatch before the module ever reaches the registry.
6
+ * Major-only: additive, backwards-compatible SDK changes never bump it.
7
+ */
8
+ export const TOOL_SDK_VERSION = 1;
9
+ const contract = makeSdkModuleContract({
10
+ errorPrefix: "tool_provider",
11
+ moduleNoun: "a tool provider module",
12
+ identityField: "name",
13
+ defineCall: "defineToolProvider({ name, sdkVersion, toolSpecs, executeTool })",
14
+ requiredFns: [
15
+ { field: "toolSpecs", signature: "toolSpecs(settings)", article: "a" },
16
+ { field: "executeTool", signature: "executeTool(name, input, context)", article: "an" },
17
+ ],
18
+ sdkVersion: TOOL_SDK_VERSION,
19
+ });
20
+ /**
21
+ * Structural check + version handshake for a dynamically loaded tool module.
22
+ * `source` names where the value came from so every error is actionable.
23
+ */
24
+ export const assertToolProviderModule = contract.assertModule;
25
+ /**
26
+ * Authoring sugar for out-of-tree tool modules: shape-asserts the module at
27
+ * definition time (so a typo fails in the author's tests, not the operator's
28
+ * daemon) and returns it unchanged. Usage:
29
+ *
30
+ * ```ts
31
+ * export default defineToolProvider({
32
+ * name: "acme",
33
+ * sdkVersion: 1,
34
+ * toolSpecs: (settings) => [...],
35
+ * executeTool: (name, input, context) => acmeExecute(name, input, context),
36
+ * });
37
+ * ```
38
+ */
39
+ export function defineToolProvider(module) {
40
+ return contract.defineModule(module, "defineToolProvider");
41
+ }
42
+ //# sourceMappingURL=module.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"module.js","sourceRoot":"","sources":["../src/module.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,gBAAgB,CAAC;AAIvD;;;;;GAKG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,CAAC;AAYlC,MAAM,QAAQ,GAAG,qBAAqB,CAAqB;IACzD,WAAW,EAAE,eAAe;IAC5B,UAAU,EAAE,wBAAwB;IACpC,aAAa,EAAE,MAAM;IACrB,UAAU,EAAE,kEAAkE;IAC9E,WAAW,EAAE;QACX,EAAE,KAAK,EAAE,WAAW,EAAE,SAAS,EAAE,qBAAqB,EAAE,OAAO,EAAE,GAAG,EAAE;QACtE,EAAE,KAAK,EAAE,aAAa,EAAE,SAAS,EAAE,mCAAmC,EAAE,OAAO,EAAE,IAAI,EAAE;KACxF;IACD,UAAU,EAAE,gBAAgB;CAC7B,CAAC,CAAC;AAEH;;;GAGG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAGM,QAAQ,CAAC,YAAY,CAAC;AAEjE;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,kBAAkB,CAAC,MAA0B;IAC3D,OAAO,QAAQ,CAAC,YAAY,CAAC,MAAM,EAAE,oBAAoB,CAAC,CAAC;AAC7D,CAAC"}
@@ -1,5 +1,5 @@
1
- export type { TrackerContext, TrackerComment, TrackerCreateIssueInput, TrackerOpsContext, TrackerProvider, TrackerQueryResult, TrackerToolOps, } from "./provider.js";
1
+ export type { TrackerContext, TrackerComment, TrackerProvider } from "./provider.js";
2
2
  export { TrackerRegistry, defaultTrackerRegistry } from "./registry.js";
3
3
  export { rejectUnknownOptions, resolveEnvReference, stringListOption, stringOption, } from "./options.js";
4
- export { createTrackerToolProvider } from "./toolPack.js";
4
+ export { TRACKER_SDK_VERSION, assertTrackerProviderModule, defineTrackerProvider, type TrackerProviderModule, } from "./module.js";
5
5
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,cAAc,EACd,cAAc,EACd,uBAAuB,EACvB,iBAAiB,EACjB,eAAe,EACf,kBAAkB,EAClB,cAAc,GACf,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,eAAe,EAAE,sBAAsB,EAAE,MAAM,eAAe,CAAC;AACxE,OAAO,EACL,oBAAoB,EACpB,mBAAmB,EACnB,gBAAgB,EAChB,YAAY,GACb,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,yBAAyB,EAAE,MAAM,eAAe,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,cAAc,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AACrF,OAAO,EAAE,eAAe,EAAE,sBAAsB,EAAE,MAAM,eAAe,CAAC;AACxE,OAAO,EACL,oBAAoB,EACpB,mBAAmB,EACnB,gBAAgB,EAChB,YAAY,GACb,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,mBAAmB,EACnB,2BAA2B,EAC3B,qBAAqB,EACrB,KAAK,qBAAqB,GAC3B,MAAM,aAAa,CAAC"}
@@ -1,4 +1,4 @@
1
1
  export { TrackerRegistry, defaultTrackerRegistry } from "./registry.js";
2
2
  export { rejectUnknownOptions, resolveEnvReference, stringListOption, stringOption, } from "./options.js";
3
- export { createTrackerToolProvider } from "./toolPack.js";
3
+ export { TRACKER_SDK_VERSION, assertTrackerProviderModule, defineTrackerProvider, } from "./module.js";
4
4
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,eAAe,EAAE,sBAAsB,EAAE,MAAM,eAAe,CAAC;AACxE,OAAO,EACL,oBAAoB,EACpB,mBAAmB,EACnB,gBAAgB,EAChB,YAAY,GACb,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,yBAAyB,EAAE,MAAM,eAAe,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,sBAAsB,EAAE,MAAM,eAAe,CAAC;AACxE,OAAO,EACL,oBAAoB,EACpB,mBAAmB,EACnB,gBAAgB,EAChB,YAAY,GACb,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,mBAAmB,EACnB,2BAA2B,EAC3B,qBAAqB,GAEtB,MAAM,aAAa,CAAC"}
@@ -0,0 +1,37 @@
1
+ import type { TrackerProvider } from "./provider.js";
2
+ /**
3
+ * The tracker SDK version this build of the engine speaks. Out-of-tree tracker
4
+ * modules declare the version they target via {@link TrackerProviderModule.sdkVersion};
5
+ * the loader rejects a mismatch before the module ever reaches the registry.
6
+ * Major-only: additive, backwards-compatible SDK changes never bump it.
7
+ */
8
+ export declare const TRACKER_SDK_VERSION = 1;
9
+ /**
10
+ * The unit an OUT-OF-TREE tracker module exports: a {@link TrackerProvider}
11
+ * carrying the SDK version it targets. A dynamically imported module crosses a
12
+ * version boundary the daemon cannot type-check, so the explicit `sdkVersion`
13
+ * handshake stands in for the compiler.
14
+ */
15
+ export interface TrackerProviderModule extends TrackerProvider {
16
+ readonly sdkVersion: number;
17
+ }
18
+ /**
19
+ * Structural check + version handshake for a dynamically loaded tracker module.
20
+ * `source` names where the value came from so every error is actionable.
21
+ */
22
+ export declare const assertTrackerProviderModule: (value: unknown, source: string) => asserts value is TrackerProviderModule;
23
+ /**
24
+ * Authoring sugar for out-of-tree tracker modules: shape-asserts the module at
25
+ * definition time (so a typo fails in the author's tests, not the operator's
26
+ * daemon) and returns it unchanged. Usage:
27
+ *
28
+ * ```ts
29
+ * export default defineTrackerProvider({
30
+ * kind: "acme",
31
+ * sdkVersion: 1,
32
+ * createClient: (settings, context) => new AcmeTrackerClient(settings, context),
33
+ * });
34
+ * ```
35
+ */
36
+ export declare function defineTrackerProvider(module: TrackerProviderModule): TrackerProviderModule;
37
+ //# sourceMappingURL=module.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"module.d.ts","sourceRoot":"","sources":["../src/module.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAErD;;;;;GAKG;AACH,eAAO,MAAM,mBAAmB,IAAI,CAAC;AAErC;;;;;GAKG;AACH,MAAM,WAAW,qBAAsB,SAAQ,eAAe;IAC5D,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;CAC7B;AAWD;;;GAGG;AACH,eAAO,MAAM,2BAA2B,EAAE,CACxC,KAAK,EAAE,OAAO,EACd,MAAM,EAAE,MAAM,KACX,OAAO,CAAC,KAAK,IAAI,qBAA6C,CAAC;AAEpE;;;;;;;;;;;;GAYG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,qBAAqB,GAAG,qBAAqB,CAE1F"}
@@ -0,0 +1,38 @@
1
+ import { makeSdkModuleContract } from "@lorenz/domain";
2
+ /**
3
+ * The tracker SDK version this build of the engine speaks. Out-of-tree tracker
4
+ * modules declare the version they target via {@link TrackerProviderModule.sdkVersion};
5
+ * the loader rejects a mismatch before the module ever reaches the registry.
6
+ * Major-only: additive, backwards-compatible SDK changes never bump it.
7
+ */
8
+ export const TRACKER_SDK_VERSION = 1;
9
+ const contract = makeSdkModuleContract({
10
+ errorPrefix: "tracker_provider",
11
+ moduleNoun: "a tracker provider module",
12
+ identityField: "kind",
13
+ defineCall: "defineTrackerProvider({ kind, sdkVersion, createClient })",
14
+ requiredFns: [{ field: "createClient", signature: "createClient(settings, context)", article: "a" }],
15
+ sdkVersion: TRACKER_SDK_VERSION,
16
+ });
17
+ /**
18
+ * Structural check + version handshake for a dynamically loaded tracker module.
19
+ * `source` names where the value came from so every error is actionable.
20
+ */
21
+ export const assertTrackerProviderModule = contract.assertModule;
22
+ /**
23
+ * Authoring sugar for out-of-tree tracker modules: shape-asserts the module at
24
+ * definition time (so a typo fails in the author's tests, not the operator's
25
+ * daemon) and returns it unchanged. Usage:
26
+ *
27
+ * ```ts
28
+ * export default defineTrackerProvider({
29
+ * kind: "acme",
30
+ * sdkVersion: 1,
31
+ * createClient: (settings, context) => new AcmeTrackerClient(settings, context),
32
+ * });
33
+ * ```
34
+ */
35
+ export function defineTrackerProvider(module) {
36
+ return contract.defineModule(module, "defineTrackerProvider");
37
+ }
38
+ //# sourceMappingURL=module.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"module.js","sourceRoot":"","sources":["../src/module.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,gBAAgB,CAAC;AAIvD;;;;;GAKG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,CAAC;AAYrC,MAAM,QAAQ,GAAG,qBAAqB,CAAwB;IAC5D,WAAW,EAAE,kBAAkB;IAC/B,UAAU,EAAE,2BAA2B;IACvC,aAAa,EAAE,MAAM;IACrB,UAAU,EAAE,2DAA2D;IACvE,WAAW,EAAE,CAAC,EAAE,KAAK,EAAE,cAAc,EAAE,SAAS,EAAE,iCAAiC,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC;IACpG,UAAU,EAAE,mBAAmB;CAChC,CAAC,CAAC;AAEH;;;GAGG;AACH,MAAM,CAAC,MAAM,2BAA2B,GAGM,QAAQ,CAAC,YAAY,CAAC;AAEpE;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,qBAAqB,CAAC,MAA6B;IACjE,OAAO,QAAQ,CAAC,YAAY,CAAC,MAAM,EAAE,uBAAuB,CAAC,CAAC;AAChE,CAAC"}
@@ -1,4 +1,4 @@
1
- import type { Issue, RuntimeTrackerClient, Settings } from "@lorenz/domain";
1
+ import type { RuntimeTrackerClient, Settings } from "@lorenz/domain";
2
2
  /** Ambient dependencies handed to provider hooks that must not touch process globals directly. */
3
3
  export interface TrackerContext {
4
4
  env: NodeJS.ProcessEnv;
@@ -8,25 +8,7 @@ export interface TrackerContext {
8
8
  */
9
9
  resolveSecret?: (value: string | undefined, fallbackEnvVar?: string) => string | undefined;
10
10
  }
11
- /** Dependencies for building the normalized tool operations of one tracker. */
12
- export interface TrackerOpsContext {
13
- fetchImpl: typeof fetch;
14
- }
15
- /** Input accepted by {@link TrackerToolOps.createIssue}. */
16
- export interface TrackerCreateIssueInput {
17
- title: string;
18
- body?: string | undefined;
19
- status?: string | undefined;
20
- /** Tracker user identity to assign the created issue to when the backend supports assignment. */
21
- assignee?: string | undefined;
22
- }
23
- /** Natively projected query payload returned by {@link TrackerToolOps.queryRows}. */
24
- export interface TrackerQueryResult {
25
- rows: Array<Record<string, unknown>>;
26
- total: number;
27
- skipped?: unknown[] | undefined;
28
- }
29
- /** Normalized tracker issue comment returned by the provider-neutral comment tools. */
11
+ /** Normalized tracker issue comment returned by tracker clients and their comment tools. */
30
12
  export interface TrackerComment {
31
13
  id: string;
32
14
  body: string;
@@ -35,35 +17,13 @@ export interface TrackerComment {
35
17
  updatedAt?: string | null | undefined;
36
18
  url?: string | null | undefined;
37
19
  }
38
- /**
39
- * Normalized issue operations backing the provider-neutral `tracker_*` tool pack. Every
40
- * member is optional: a missing member makes the corresponding tool report itself as
41
- * unsupported for this tracker instead of failing mid-call.
42
- *
43
- * Backends that filter and project natively (e.g. the local board's query DSL) implement
44
- * {@link queryRows}; backends that return whole issues implement {@link queryIssues} and let
45
- * the pack project rows with the shared select/filter helpers.
46
- */
47
- export interface TrackerToolOps {
48
- readIssue?(issueId: string): Promise<Issue>;
49
- /** Issues matching generic query args (`issueIds`, `states`, provider-native queries such as `jql`). */
50
- queryIssues?(args: Record<string, unknown>): Promise<Issue[]>;
51
- /** Pre-projected rows for backends with a native query surface; takes precedence over {@link queryIssues}. */
52
- queryRows?(args: Record<string, unknown>): Promise<TrackerQueryResult>;
53
- updateStatus?(issueId: string, status: string): Promise<Issue>;
54
- listComments?(issueId: string): Promise<TrackerComment[]>;
55
- addComment?(issueId: string, body: string): Promise<TrackerComment | void>;
56
- updateComment?(issueId: string, commentId: string, body: string): Promise<TrackerComment>;
57
- createIssue?(input: TrackerCreateIssueInput): Promise<Issue>;
58
- }
59
20
  /**
60
21
  * Everything Lorenz needs to know about one issue-tracker backend, bundled as a single
61
- * extension point. A provider owns its slice of the selected tracker bundle, the runtime
62
- * client that feeds issues into dispatch, and the normalized operations behind the
63
- * provider-neutral `tracker_*` tools. Agent-facing tool packs are a separate extension
64
- * point (`ToolProvider` in `@lorenz/tool-sdk`): a tracker package may ship one, declare
65
- * it as a default pack for this tracker, and a workflow may still mount other registered
66
- * packs explicitly through its `tools:` map.
22
+ * extension point. A provider owns its slice of the selected tracker bundle and the runtime
23
+ * client that feeds issues into dispatch. Agent-facing tool packs are a separate extension
24
+ * point (`ToolProvider` in `@lorenz/tool-sdk`): a tracker package may ship one and declare
25
+ * it through {@link defaultToolPacks} so it mounts when this tracker drives dispatch, and a
26
+ * workflow may still mount other registered packs explicitly through its `tools:` map.
67
27
  *
68
28
  * The core (config parsing, runtime, MCP server, CLI) is provider-agnostic and talks to
69
29
  * providers exclusively through this contract via a {@link TrackerRegistry}. Adding a new
@@ -99,14 +59,10 @@ export interface TrackerProvider {
99
59
  /** Build the runtime client that feeds candidate issues into the dispatch loop. */
100
60
  createClient(settings: Settings, context: TrackerContext): RuntimeTrackerClient;
101
61
  /**
102
- * Normalized operations backing the neutral `tracker_*` pack for this backend; return
103
- * `undefined` (or omit the member) when the backend exposes no agent-facing operations.
104
- */
105
- createToolOps?(settings: Settings, context: TrackerOpsContext): TrackerToolOps | undefined;
106
- /**
107
- * Provider-specific tool packs mounted by default when this tracker drives dispatch.
108
- * The core always mounts the neutral `tracker` pack separately; this hook declares any
109
- * additional minimum packs owned by the tracker extension.
62
+ * Tool packs mounted by default when this tracker drives dispatch. This is how a tracker
63
+ * extension exposes its agent-facing tools (e.g. Jira's `tracker_*` pack, Linear's
64
+ * `linear_graphql` pack); return the names of the registered {@link ToolProvider} packs the
65
+ * backend owns. Omit when the backend ships no agent tools.
110
66
  */
111
67
  defaultToolPacks?(settings: Settings): readonly string[];
112
68
  /** Operator-facing URL of the tracked project, shown in dashboards. */
@@ -1 +1 @@
1
- {"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../src/provider.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../src/provider.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAErE,kGAAkG;AAClG,MAAM,WAAW,cAAc;IAC7B,GAAG,EAAE,MAAM,CAAC,UAAU,CAAC;IACvB;;;OAGG;IACH,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,EAAE,cAAc,CAAC,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,CAAC;CAC5F;AAED,4FAA4F;AAC5F,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IACnC,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IACtC,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IACtC,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;CACjC;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,WAAW,eAAe;IAC9B,6FAA6F;IAC7F,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB;;;OAGG;IACH,QAAQ,CAAC,aAAa,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,GAAG,SAAS,CAAC;IACtE;;;OAGG;IACH,QAAQ,CAAC,YAAY,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,GAAG,SAAS,CAAC;IACrE,+DAA+D;IAC/D,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC9C;;;;OAIG;IACH,YAAY,CAAC,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,EAAE,cAAc,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAClG;;;OAGG;IACH,gBAAgB,CAAC,CAAC,QAAQ,EAAE,QAAQ,GAAG,IAAI,CAAC;IAC5C,mFAAmF;IACnF,YAAY,CAAC,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,cAAc,GAAG,oBAAoB,CAAC;IAChF;;;;;OAKG;IACH,gBAAgB,CAAC,CAAC,QAAQ,EAAE,QAAQ,GAAG,SAAS,MAAM,EAAE,CAAC;IACzD,uEAAuE;IACvE,UAAU,CAAC,CAAC,QAAQ,EAAE,QAAQ,GAAG,MAAM,GAAG,SAAS,CAAC;CACrD"}
@@ -9,7 +9,6 @@
9
9
  ".": "./dist/index.js"
10
10
  },
11
11
  "dependencies": {
12
- "@lorenz/domain": "0.1.1",
13
- "@lorenz/tool-sdk": "0.1.1"
12
+ "@lorenz/domain": "0.1.1"
14
13
  }
15
14
  }
@@ -9,16 +9,44 @@ export declare class WorkerHostPool {
9
9
  private readonly availableRemoteMcpPorts;
10
10
  private readonly remoteMcpTunnelsByEndpoint;
11
11
  private readonly remoteMcpTunnelEntriesByLeaseId;
12
- private readonly perRunMcpTunnels;
12
+ /**
13
+ * Monotonic generation per host:port tunnel slot, surviving entry teardown so
14
+ * a recreated entry gets a STRICTLY higher generation than the one it
15
+ * replaces. A `closeForRun` recorded against a prior generation is rejected.
16
+ */
17
+ private readonly remoteMcpTunnelGenerations;
18
+ /**
19
+ * Per-run holds on the SHARED per-host tunnels, keyed by `${workerHost}#${runKey}`.
20
+ * Each entry records which leaseId (and which generation) a run holds so
21
+ * `closeForRun` drops exactly that run's refcount - opening the tunnel on the
22
+ * first co-resident run and closing it at the last deref.
23
+ */
24
+ private readonly perRunTunnelHolds;
13
25
  acquireRemoteMcpTunnel(workerHost: string, localHost: string, localPort: number): Promise<RemoteMcpTunnelLease>;
14
26
  releaseRemoteMcpTunnel(lease: RemoteMcpTunnelLease): void;
27
+ /**
28
+ * Acquire a hold on the per-HOST reverse tunnel for one run. Co-resident runs
29
+ * on the SAME host share ONE `ssh -R` tunnel (opened on the first run, closed
30
+ * at the last `closeForRun`); they are kept apart by their per-run Token B
31
+ * claim, not by a distinct remote port. The generation captured here is what a
32
+ * later `closeForRun` is CAS-checked against, so a host:port recycle that bumps
33
+ * the slot's generation strands a stale late-close instead of decrementing the
34
+ * fresh entry.
35
+ */
15
36
  openForRun(workerHost: string, runKey: string, localHost: string, localPort: number): Promise<RemoteMcpTunnelLease>;
16
37
  closeForRun(workerHost: string, runKey: string): void;
17
- private allocateRemoteMcpPort;
18
- private isRemoteMcpPortLive;
19
- private confirmPerRunMcpTunnelReady;
20
- private handlePerRunMcpTunnelProcessEnd;
21
- private closePerRunMcpTunnel;
38
+ /**
39
+ * Drop one run's hold on its shared per-host tunnel. CAS late-close reject: if
40
+ * the live entry for the hold's endpoint has a STRICTLY higher generation than
41
+ * the hold recorded, the slot was recycled and a fresh owner holds the live
42
+ * ref - this stale release must NOT decrement the new entry's refcount. The
43
+ * hold's own leaseId either still maps to the original (same-generation) entry
44
+ * or was already cleared on that entry's teardown, so dropping it is otherwise
45
+ * idempotent.
46
+ */
47
+ private releasePerRunHold;
48
+ private ensureRemoteMcpTunnelEntry;
49
+ private dropRemoteMcpTunnelLease;
22
50
  private closeRemoteMcpTunnel;
23
51
  private handleRemoteMcpTunnelProcessEnd;
24
52
  private waitForRemoteMcpTunnelReady;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;CACpB;AAcD,qBAAa,cAAc;IACzB,OAAO,CAAC,iBAAiB,CAAU;IACnC,OAAO,CAAC,oBAAoB,CAAK;IACjC,OAAO,CAAC,QAAQ,CAAC,uBAAuB,CAAgB;IACxD,OAAO,CAAC,QAAQ,CAAC,0BAA0B,CAA2C;IACtF,OAAO,CAAC,QAAQ,CAAC,+BAA+B,CAA2C;IAI3F,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAA2C;IAEtE,sBAAsB,CAC1B,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,oBAAoB,CAAC;IAuChC,sBAAsB,CAAC,KAAK,EAAE,oBAAoB,GAAG,IAAI;IAYnD,UAAU,CACd,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,oBAAoB,CAAC;IA4ChC,WAAW,CAAC,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI;IAkBrD,OAAO,CAAC,qBAAqB;IAQ7B,OAAO,CAAC,mBAAmB;YAUb,2BAA2B;IAkBzC,OAAO,CAAC,+BAA+B;IAUvC,OAAO,CAAC,oBAAoB;IAwB5B,OAAO,CAAC,oBAAoB;IAyB5B,OAAO,CAAC,+BAA+B;YAUzB,2BAA2B;YAW3B,2BAA2B;IAezC,OAAO,CAAC,mCAAmC;IA+B3C,OAAO,CAAC,yBAAyB;IAMjC,OAAO,CAAC,oBAAoB;IAM5B,OAAO,CAAC,0BAA0B;IAYlC,OAAO,CAAC,0BAA0B;CAOnC;AAMD,eAAO,MAAM,cAAc,gBAAuB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;CACpB;AAqCD,qBAAa,cAAc;IACzB,OAAO,CAAC,iBAAiB,CAAU;IACnC,OAAO,CAAC,oBAAoB,CAAK;IACjC,OAAO,CAAC,QAAQ,CAAC,uBAAuB,CAAgB;IACxD,OAAO,CAAC,QAAQ,CAAC,0BAA0B,CAA2C;IACtF,OAAO,CAAC,QAAQ,CAAC,+BAA+B,CAA2C;IAC3F;;;;OAIG;IACH,OAAO,CAAC,QAAQ,CAAC,0BAA0B,CAA6B;IACxE;;;;;OAKG;IACH,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAuC;IAEnE,sBAAsB,CAC1B,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,oBAAoB,CAAC;IAMhC,sBAAsB,CAAC,KAAK,EAAE,oBAAoB,GAAG,IAAI;IASzD;;;;;;;;OAQG;IACG,UAAU,CACd,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,oBAAoB,CAAC;IAqChC,WAAW,CAAC,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI;IAIrD;;;;;;;;OAQG;IACH,OAAO,CAAC,iBAAiB;YAiBX,0BAA0B;IAkDxC,OAAO,CAAC,wBAAwB;IAQhC,OAAO,CAAC,oBAAoB;IAyB5B,OAAO,CAAC,+BAA+B;YAUzB,2BAA2B;YAW3B,2BAA2B;IAezC,OAAO,CAAC,mCAAmC;IA+B3C,OAAO,CAAC,yBAAyB;IAMjC,OAAO,CAAC,oBAAoB;IAM5B,OAAO,CAAC,0BAA0B;IAYlC,OAAO,CAAC,0BAA0B;CAOnC;AAMD,eAAO,MAAM,cAAc,gBAAuB,CAAC"}
@@ -5,49 +5,22 @@ export class WorkerHostPool {
5
5
  availableRemoteMcpPorts = [];
6
6
  remoteMcpTunnelsByEndpoint = new Map();
7
7
  remoteMcpTunnelEntriesByLeaseId = new Map();
8
- // Per-run tunnels are keyed by `${workerHost}#${runKey}`, NOT host-coalesced,
9
- // so each run owns a distinct entry (and distinct remote port). One run's
10
- // localPort change can never replace another run's entry.
11
- perRunMcpTunnels = new Map();
8
+ /**
9
+ * Monotonic generation per host:port tunnel slot, surviving entry teardown so
10
+ * a recreated entry gets a STRICTLY higher generation than the one it
11
+ * replaces. A `closeForRun` recorded against a prior generation is rejected.
12
+ */
13
+ remoteMcpTunnelGenerations = new Map();
14
+ /**
15
+ * Per-run holds on the SHARED per-host tunnels, keyed by `${workerHost}#${runKey}`.
16
+ * Each entry records which leaseId (and which generation) a run holds so
17
+ * `closeForRun` drops exactly that run's refcount - opening the tunnel on the
18
+ * first co-resident run and closing it at the last deref.
19
+ */
20
+ perRunTunnelHolds = new Map();
12
21
  async acquireRemoteMcpTunnel(workerHost, localHost, localPort) {
13
22
  const endpointKey = this.remoteMcpTunnelEndpointKey(workerHost, localHost, localPort);
14
- const current = this.remoteMcpTunnelsByEndpoint.get(endpointKey);
15
- if (current && !current.processEnded) {
16
- await this.waitForRemoteMcpTunnelReady(current);
17
- return this.createRemoteMcpTunnelLease(current);
18
- }
19
- if (current)
20
- this.closeRemoteMcpTunnel(current, true);
21
- const recycledPort = this.availableRemoteMcpPorts.shift();
22
- const remotePort = recycledPort ?? this.nextRemoteMcpPort;
23
- let process;
24
- try {
25
- process = startReverseTunnel(workerHost, remotePort, localHost, localPort);
26
- }
27
- catch (error) {
28
- if (recycledPort !== undefined)
29
- this.recycleRemoteMcpPort(recycledPort);
30
- throw error;
31
- }
32
- if (recycledPort === undefined)
33
- this.nextRemoteMcpPort += 1;
34
- const entry = {
35
- workerHost,
36
- localHost,
37
- localPort,
38
- process,
39
- leaseIds: new Set(),
40
- readyPromise: Promise.resolve(),
41
- remotePort,
42
- processEnded: false,
43
- recyclePortOnProcessEnd: false,
44
- };
45
- this.remoteMcpTunnelsByEndpoint.set(endpointKey, entry);
46
- process.on("close", () => this.handleRemoteMcpTunnelProcessEnd(entry, endpointKey));
47
- process.on("exit", () => this.handleRemoteMcpTunnelProcessEnd(entry, endpointKey));
48
- process.on("error", () => this.handleRemoteMcpTunnelProcessEnd(entry, endpointKey));
49
- entry.readyPromise = this.confirmRemoteMcpTunnelReady(entry);
50
- await this.waitForRemoteMcpTunnelReady(entry);
23
+ const entry = await this.ensureRemoteMcpTunnelEntry(workerHost, localHost, localPort, endpointKey);
51
24
  return this.createRemoteMcpTunnelLease(entry);
52
25
  }
53
26
  releaseRemoteMcpTunnel(lease) {
@@ -57,26 +30,89 @@ export class WorkerHostPool {
57
30
  if (entry.workerHost !== lease.workerHost || entry.remotePort !== lease.remotePort) {
58
31
  return;
59
32
  }
60
- this.remoteMcpTunnelEntriesByLeaseId.delete(lease.leaseId);
61
- entry.leaseIds.delete(lease.leaseId);
62
- if (entry.leaseIds.size > 0)
63
- return;
64
- this.closeRemoteMcpTunnel(entry, true);
33
+ this.dropRemoteMcpTunnelLease(entry, lease.leaseId);
65
34
  }
35
+ /**
36
+ * Acquire a hold on the per-HOST reverse tunnel for one run. Co-resident runs
37
+ * on the SAME host share ONE `ssh -R` tunnel (opened on the first run, closed
38
+ * at the last `closeForRun`); they are kept apart by their per-run Token B
39
+ * claim, not by a distinct remote port. The generation captured here is what a
40
+ * later `closeForRun` is CAS-checked against, so a host:port recycle that bumps
41
+ * the slot's generation strands a stale late-close instead of decrementing the
42
+ * fresh entry.
43
+ */
66
44
  async openForRun(workerHost, runKey, localHost, localPort) {
67
- const key = perRunKey(workerHost, runKey);
68
- const current = this.perRunMcpTunnels.get(key);
69
- if (current &&
70
- !current.processEnded &&
71
- current.localHost === localHost &&
72
- current.localPort === localPort) {
45
+ const holdKey = perRunKey(workerHost, runKey);
46
+ const endpointKey = this.remoteMcpTunnelEndpointKey(workerHost, localHost, localPort);
47
+ // Re-opening the SAME run (e.g. resume) reuses its existing hold when the
48
+ // shared host entry is still live - no second refcount/lease for one run.
49
+ const existingHold = this.perRunTunnelHolds.get(holdKey);
50
+ if (existingHold) {
51
+ const heldEntry = this.remoteMcpTunnelEntriesByLeaseId.get(existingHold.leaseId);
52
+ if (heldEntry &&
53
+ !heldEntry.processEnded &&
54
+ heldEntry.localHost === localHost &&
55
+ heldEntry.localPort === localPort) {
56
+ await this.waitForRemoteMcpTunnelReady(heldEntry);
57
+ return {
58
+ leaseId: existingHold.leaseId,
59
+ workerHost: heldEntry.workerHost,
60
+ remotePort: heldEntry.remotePort,
61
+ };
62
+ }
63
+ // The run's prior hold is stale (entry torn down or the local endpoint
64
+ // moved): drop it and take a fresh hold on the current shared entry.
65
+ this.releasePerRunHold(holdKey);
66
+ }
67
+ const entry = await this.ensureRemoteMcpTunnelEntry(workerHost, localHost, localPort, endpointKey);
68
+ const lease = this.createRemoteMcpTunnelLease(entry);
69
+ this.perRunTunnelHolds.set(holdKey, {
70
+ leaseId: lease.leaseId,
71
+ endpointKey,
72
+ generation: entry.generation,
73
+ });
74
+ return lease;
75
+ }
76
+ closeForRun(workerHost, runKey) {
77
+ this.releasePerRunHold(perRunKey(workerHost, runKey));
78
+ }
79
+ /**
80
+ * Drop one run's hold on its shared per-host tunnel. CAS late-close reject: if
81
+ * the live entry for the hold's endpoint has a STRICTLY higher generation than
82
+ * the hold recorded, the slot was recycled and a fresh owner holds the live
83
+ * ref - this stale release must NOT decrement the new entry's refcount. The
84
+ * hold's own leaseId either still maps to the original (same-generation) entry
85
+ * or was already cleared on that entry's teardown, so dropping it is otherwise
86
+ * idempotent.
87
+ */
88
+ releasePerRunHold(holdKey) {
89
+ const hold = this.perRunTunnelHolds.get(holdKey);
90
+ if (!hold)
91
+ return;
92
+ this.perRunTunnelHolds.delete(holdKey);
93
+ const liveGeneration = this.remoteMcpTunnelGenerations.get(hold.endpointKey);
94
+ if (liveGeneration !== undefined && hold.generation < liveGeneration) {
95
+ // Stale late-close against a recycled slot: never touch the live entry.
96
+ return;
97
+ }
98
+ const entry = this.remoteMcpTunnelEntriesByLeaseId.get(hold.leaseId);
99
+ if (!entry)
100
+ return;
101
+ this.dropRemoteMcpTunnelLease(entry, hold.leaseId);
102
+ }
103
+ // Reuse-or-open a host-keyed reverse tunnel entry. A live entry for this
104
+ // host:port is shared (refcounted by leases); a torn-down one is replaced by a
105
+ // fresh entry whose generation is STRICTLY higher than the slot's last value.
106
+ async ensureRemoteMcpTunnelEntry(workerHost, localHost, localPort, endpointKey) {
107
+ const current = this.remoteMcpTunnelsByEndpoint.get(endpointKey);
108
+ if (current && !current.processEnded) {
73
109
  await this.waitForRemoteMcpTunnelReady(current);
74
- return this.createRemoteMcpTunnelLease(current);
110
+ return current;
75
111
  }
76
112
  if (current)
77
- this.closePerRunMcpTunnel(key, current, true);
78
- const remotePort = this.allocateRemoteMcpPort();
79
- const recycledPort = remotePort < this.nextRemoteMcpPort ? remotePort : undefined;
113
+ this.closeRemoteMcpTunnel(current, true);
114
+ const recycledPort = this.availableRemoteMcpPorts.shift();
115
+ const remotePort = recycledPort ?? this.nextRemoteMcpPort;
80
116
  let process;
81
117
  try {
82
118
  process = startReverseTunnel(workerHost, remotePort, localHost, localPort);
@@ -88,6 +124,12 @@ export class WorkerHostPool {
88
124
  }
89
125
  if (recycledPort === undefined)
90
126
  this.nextRemoteMcpPort += 1;
127
+ // Bump the slot's generation when a brand-new entry replaces a torn-down
128
+ // one. The first entry for a host:port gets generation 1; each recycle is
129
+ // strictly higher, so a per-run hold recorded against the prior generation
130
+ // is fenced out of the new entry's refcount.
131
+ const generation = (this.remoteMcpTunnelGenerations.get(endpointKey) ?? 0) + 1;
132
+ this.remoteMcpTunnelGenerations.set(endpointKey, generation);
91
133
  const entry = {
92
134
  workerHost,
93
135
  localHost,
@@ -98,99 +140,24 @@ export class WorkerHostPool {
98
140
  remotePort,
99
141
  processEnded: false,
100
142
  recyclePortOnProcessEnd: false,
143
+ generation,
101
144
  };
102
- this.perRunMcpTunnels.set(key, entry);
103
- process.on("close", () => this.handlePerRunMcpTunnelProcessEnd(key, entry));
104
- process.on("exit", () => this.handlePerRunMcpTunnelProcessEnd(key, entry));
105
- process.on("error", () => this.handlePerRunMcpTunnelProcessEnd(key, entry));
106
- entry.readyPromise = this.confirmPerRunMcpTunnelReady(key, entry);
145
+ this.remoteMcpTunnelsByEndpoint.set(endpointKey, entry);
146
+ process.on("close", () => this.handleRemoteMcpTunnelProcessEnd(entry, endpointKey));
147
+ process.on("exit", () => this.handleRemoteMcpTunnelProcessEnd(entry, endpointKey));
148
+ process.on("error", () => this.handleRemoteMcpTunnelProcessEnd(entry, endpointKey));
149
+ entry.readyPromise = this.confirmRemoteMcpTunnelReady(entry);
107
150
  await this.waitForRemoteMcpTunnelReady(entry);
108
- return this.createRemoteMcpTunnelLease(entry);
151
+ return entry;
109
152
  }
110
- closeForRun(workerHost, runKey) {
111
- const key = perRunKey(workerHost, runKey);
112
- const entry = this.perRunMcpTunnels.get(key);
113
- if (!entry)
153
+ dropRemoteMcpTunnelLease(entry, leaseId) {
154
+ if (!entry.leaseIds.has(leaseId))
114
155
  return;
115
- // Each openForRun call on this run minted one lease; drop one per close
116
- // and keep the tunnel while other holders of the same run remain.
117
- const [leaseId] = entry.leaseIds;
118
- if (leaseId !== undefined) {
119
- entry.leaseIds.delete(leaseId);
120
- this.remoteMcpTunnelEntriesByLeaseId.delete(leaseId);
121
- }
156
+ this.remoteMcpTunnelEntriesByLeaseId.delete(leaseId);
157
+ entry.leaseIds.delete(leaseId);
122
158
  if (entry.leaseIds.size > 0)
123
159
  return;
124
- this.closePerRunMcpTunnel(key, entry, true);
125
- }
126
- // Allocate a remote port, reusing a recycled candidate only when no live
127
- // entry (host-keyed OR per-run) still holds it. This guards the
128
- // recycled-port-vs-stale-entry interaction under N concurrent live ports.
129
- allocateRemoteMcpPort() {
130
- while (this.availableRemoteMcpPorts.length > 0) {
131
- const candidate = this.availableRemoteMcpPorts.shift();
132
- if (!this.isRemoteMcpPortLive(candidate))
133
- return candidate;
134
- }
135
- return this.nextRemoteMcpPort;
136
- }
137
- isRemoteMcpPortLive(remotePort) {
138
- for (const entry of this.remoteMcpTunnelsByEndpoint.values()) {
139
- if (entry.remotePort === remotePort)
140
- return true;
141
- }
142
- for (const entry of this.perRunMcpTunnels.values()) {
143
- if (entry.remotePort === remotePort)
144
- return true;
145
- }
146
- return false;
147
- }
148
- async confirmPerRunMcpTunnelReady(key, entry) {
149
- const processEndWatcher = this.watchRemoteMcpTunnelSetupProcessEnd(entry);
150
- try {
151
- await Promise.race([
152
- waitForRemoteTcpPort(entry.workerHost, entry.remotePort),
153
- processEndWatcher.promise,
154
- ]);
155
- }
156
- catch (error) {
157
- this.closePerRunMcpTunnel(key, entry, true);
158
- throw error;
159
- }
160
- finally {
161
- processEndWatcher.dispose();
162
- }
163
- }
164
- handlePerRunMcpTunnelProcessEnd(key, entry) {
165
- if (entry.processEnded)
166
- return;
167
- entry.processEnded = true;
168
- if (this.perRunMcpTunnels.get(key) === entry) {
169
- this.closePerRunMcpTunnel(key, entry, true);
170
- return;
171
- }
172
- if (entry.recyclePortOnProcessEnd)
173
- this.recycleRemoteMcpPort(entry.remotePort);
174
- }
175
- closePerRunMcpTunnel(key, entry, recyclePort) {
176
- if (this.perRunMcpTunnels.get(key) === entry) {
177
- this.perRunMcpTunnels.delete(key);
178
- }
179
- for (const leaseId of entry.leaseIds) {
180
- this.remoteMcpTunnelEntriesByLeaseId.delete(leaseId);
181
- }
182
- entry.leaseIds.clear();
183
- if (recyclePort) {
184
- if (entry.processEnded) {
185
- this.recycleRemoteMcpPort(entry.remotePort);
186
- }
187
- else {
188
- entry.recyclePortOnProcessEnd = true;
189
- }
190
- }
191
- if (!entry.processEnded) {
192
- entry.process.kill();
193
- }
160
+ this.closeRemoteMcpTunnel(entry, true);
194
161
  }
195
162
  closeRemoteMcpTunnel(entry, recyclePort) {
196
163
  const endpointKey = this.remoteMcpTunnelEndpointKey(entry.workerHost, entry.localHost, entry.localPort);