@namzu/cli 0.0.2 → 0.1.0

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 (365) hide show
  1. package/LICENSE.md +110 -0
  2. package/dist/bin.js +4 -32
  3. package/dist/bin.js.map +1 -1
  4. package/dist/cli.d.ts +14 -0
  5. package/dist/cli.d.ts.map +1 -0
  6. package/dist/cli.js +124 -0
  7. package/dist/cli.js.map +1 -0
  8. package/dist/cli.test.d.ts +2 -0
  9. package/dist/cli.test.d.ts.map +1 -0
  10. package/dist/cli.test.js +94 -0
  11. package/dist/cli.test.js.map +1 -0
  12. package/dist/commands/doctor.d.ts +6 -0
  13. package/dist/commands/doctor.d.ts.map +1 -1
  14. package/dist/commands/doctor.js +10 -0
  15. package/dist/commands/doctor.js.map +1 -1
  16. package/dist/commands/providers.d.ts +17 -0
  17. package/dist/commands/providers.d.ts.map +1 -0
  18. package/dist/commands/providers.js +274 -0
  19. package/dist/commands/providers.js.map +1 -0
  20. package/dist/commands/registry.d.ts +11 -0
  21. package/dist/commands/registry.d.ts.map +1 -0
  22. package/dist/commands/registry.js +28 -0
  23. package/dist/commands/registry.js.map +1 -0
  24. package/dist/commands/run.d.ts +14 -0
  25. package/dist/commands/run.d.ts.map +1 -0
  26. package/dist/commands/run.js +73 -0
  27. package/dist/commands/run.js.map +1 -0
  28. package/dist/commands/stubs.d.ts +12 -0
  29. package/dist/commands/stubs.d.ts.map +1 -0
  30. package/dist/commands/stubs.js +32 -0
  31. package/dist/commands/stubs.js.map +1 -0
  32. package/dist/commands/tools.d.ts +16 -0
  33. package/dist/commands/tools.d.ts.map +1 -0
  34. package/dist/commands/tools.js +161 -0
  35. package/dist/commands/tools.js.map +1 -0
  36. package/dist/commands/types.d.ts +25 -0
  37. package/dist/commands/types.d.ts.map +1 -0
  38. package/dist/commands/types.js +2 -0
  39. package/dist/commands/types.js.map +1 -0
  40. package/dist/config/load.d.ts +25 -0
  41. package/dist/config/load.d.ts.map +1 -0
  42. package/dist/config/load.js +92 -0
  43. package/dist/config/load.js.map +1 -0
  44. package/dist/config/load.test.d.ts +2 -0
  45. package/dist/config/load.test.d.ts.map +1 -0
  46. package/dist/config/load.test.js +57 -0
  47. package/dist/config/load.test.js.map +1 -0
  48. package/dist/config/schema.d.ts +29 -0
  49. package/dist/config/schema.d.ts.map +1 -0
  50. package/dist/config/schema.js +13 -0
  51. package/dist/config/schema.js.map +1 -0
  52. package/dist/doctor/registry.d.ts.map +1 -1
  53. package/dist/doctor/registry.js +3 -1
  54. package/dist/doctor/registry.js.map +1 -1
  55. package/dist/doctor/registry.test.js +4 -1
  56. package/dist/doctor/registry.test.js.map +1 -1
  57. package/dist/index.d.ts +6 -0
  58. package/dist/index.d.ts.map +1 -1
  59. package/dist/index.js +7 -0
  60. package/dist/index.js.map +1 -1
  61. package/dist/integrations/clawtool/agents.d.ts +31 -0
  62. package/dist/integrations/clawtool/agents.d.ts.map +1 -0
  63. package/dist/integrations/clawtool/agents.js +30 -0
  64. package/dist/integrations/clawtool/agents.js.map +1 -0
  65. package/dist/integrations/clawtool/agents.test.d.ts +2 -0
  66. package/dist/integrations/clawtool/agents.test.d.ts.map +1 -0
  67. package/dist/integrations/clawtool/agents.test.js +79 -0
  68. package/dist/integrations/clawtool/agents.test.js.map +1 -0
  69. package/dist/integrations/clawtool/auth.d.ts +26 -0
  70. package/dist/integrations/clawtool/auth.d.ts.map +1 -0
  71. package/dist/integrations/clawtool/auth.js +56 -0
  72. package/dist/integrations/clawtool/auth.js.map +1 -0
  73. package/dist/integrations/clawtool/auth.test.d.ts +2 -0
  74. package/dist/integrations/clawtool/auth.test.d.ts.map +1 -0
  75. package/dist/integrations/clawtool/auth.test.js +40 -0
  76. package/dist/integrations/clawtool/auth.test.js.map +1 -0
  77. package/dist/integrations/clawtool/binary.d.ts +25 -0
  78. package/dist/integrations/clawtool/binary.d.ts.map +1 -0
  79. package/dist/integrations/clawtool/binary.js +50 -0
  80. package/dist/integrations/clawtool/binary.js.map +1 -0
  81. package/dist/integrations/clawtool/binary.test.d.ts +2 -0
  82. package/dist/integrations/clawtool/binary.test.d.ts.map +1 -0
  83. package/dist/integrations/clawtool/binary.test.js +42 -0
  84. package/dist/integrations/clawtool/binary.test.js.map +1 -0
  85. package/dist/integrations/clawtool/daemon.d.ts +37 -0
  86. package/dist/integrations/clawtool/daemon.d.ts.map +1 -0
  87. package/dist/integrations/clawtool/daemon.js +109 -0
  88. package/dist/integrations/clawtool/daemon.js.map +1 -0
  89. package/dist/integrations/clawtool/daemon.test.d.ts +11 -0
  90. package/dist/integrations/clawtool/daemon.test.d.ts.map +1 -0
  91. package/dist/integrations/clawtool/daemon.test.js +118 -0
  92. package/dist/integrations/clawtool/daemon.test.js.map +1 -0
  93. package/dist/integrations/clawtool/dispatch.d.ts +33 -0
  94. package/dist/integrations/clawtool/dispatch.d.ts.map +1 -0
  95. package/dist/integrations/clawtool/dispatch.js +155 -0
  96. package/dist/integrations/clawtool/dispatch.js.map +1 -0
  97. package/dist/integrations/clawtool/dispatch.test.d.ts +2 -0
  98. package/dist/integrations/clawtool/dispatch.test.d.ts.map +1 -0
  99. package/dist/integrations/clawtool/dispatch.test.js +138 -0
  100. package/dist/integrations/clawtool/dispatch.test.js.map +1 -0
  101. package/dist/integrations/clawtool/index.d.ts +11 -0
  102. package/dist/integrations/clawtool/index.d.ts.map +1 -0
  103. package/dist/integrations/clawtool/index.js +10 -0
  104. package/dist/integrations/clawtool/index.js.map +1 -0
  105. package/dist/integrations/clawtool/mcp.d.ts +51 -0
  106. package/dist/integrations/clawtool/mcp.d.ts.map +1 -0
  107. package/dist/integrations/clawtool/mcp.js +156 -0
  108. package/dist/integrations/clawtool/mcp.js.map +1 -0
  109. package/dist/integrations/clawtool/mcp.test.d.ts +2 -0
  110. package/dist/integrations/clawtool/mcp.test.d.ts.map +1 -0
  111. package/dist/integrations/clawtool/mcp.test.js +126 -0
  112. package/dist/integrations/clawtool/mcp.test.js.map +1 -0
  113. package/dist/integrations/clawtool/paths.d.ts +8 -0
  114. package/dist/integrations/clawtool/paths.d.ts.map +1 -0
  115. package/dist/integrations/clawtool/paths.js +19 -0
  116. package/dist/integrations/clawtool/paths.js.map +1 -0
  117. package/dist/integrations/clawtool/peers.d.ts +67 -0
  118. package/dist/integrations/clawtool/peers.d.ts.map +1 -0
  119. package/dist/integrations/clawtool/peers.js +150 -0
  120. package/dist/integrations/clawtool/peers.js.map +1 -0
  121. package/dist/integrations/clawtool/plugin.d.ts +42 -0
  122. package/dist/integrations/clawtool/plugin.d.ts.map +1 -0
  123. package/dist/integrations/clawtool/plugin.js +38 -0
  124. package/dist/integrations/clawtool/plugin.js.map +1 -0
  125. package/dist/integrations/clawtool/state.d.ts +11 -0
  126. package/dist/integrations/clawtool/state.d.ts.map +1 -0
  127. package/dist/integrations/clawtool/state.js +41 -0
  128. package/dist/integrations/clawtool/state.js.map +1 -0
  129. package/dist/integrations/clawtool/state.test.d.ts +2 -0
  130. package/dist/integrations/clawtool/state.test.d.ts.map +1 -0
  131. package/dist/integrations/clawtool/state.test.js +38 -0
  132. package/dist/integrations/clawtool/state.test.js.map +1 -0
  133. package/dist/integrations/clawtool/tooling.d.ts +50 -0
  134. package/dist/integrations/clawtool/tooling.d.ts.map +1 -0
  135. package/dist/integrations/clawtool/tooling.js +89 -0
  136. package/dist/integrations/clawtool/tooling.js.map +1 -0
  137. package/dist/integrations/clawtool/tooling.test.d.ts +2 -0
  138. package/dist/integrations/clawtool/tooling.test.d.ts.map +1 -0
  139. package/dist/integrations/clawtool/tooling.test.js +58 -0
  140. package/dist/integrations/clawtool/tooling.test.js.map +1 -0
  141. package/dist/integrations/clawtool/types.d.ts +41 -0
  142. package/dist/integrations/clawtool/types.d.ts.map +1 -0
  143. package/dist/integrations/clawtool/types.js +9 -0
  144. package/dist/integrations/clawtool/types.js.map +1 -0
  145. package/dist/integrations/clipboard/image.d.ts +18 -0
  146. package/dist/integrations/clipboard/image.d.ts.map +1 -0
  147. package/dist/integrations/clipboard/image.js +88 -0
  148. package/dist/integrations/clipboard/image.js.map +1 -0
  149. package/dist/integrations/providers/discover.d.ts +68 -0
  150. package/dist/integrations/providers/discover.d.ts.map +1 -0
  151. package/dist/integrations/providers/discover.js +108 -0
  152. package/dist/integrations/providers/discover.js.map +1 -0
  153. package/dist/integrations/providers/discover.test.d.ts +2 -0
  154. package/dist/integrations/providers/discover.test.d.ts.map +1 -0
  155. package/dist/integrations/providers/discover.test.js +120 -0
  156. package/dist/integrations/providers/discover.test.js.map +1 -0
  157. package/dist/integrations/providers/index.d.ts +10 -0
  158. package/dist/integrations/providers/index.d.ts.map +1 -0
  159. package/dist/integrations/providers/index.js +12 -0
  160. package/dist/integrations/providers/index.js.map +1 -0
  161. package/dist/integrations/providers/keychain.d.ts +44 -0
  162. package/dist/integrations/providers/keychain.d.ts.map +1 -0
  163. package/dist/integrations/providers/keychain.js +154 -0
  164. package/dist/integrations/providers/keychain.js.map +1 -0
  165. package/dist/integrations/providers/keychain.test.d.ts +2 -0
  166. package/dist/integrations/providers/keychain.test.d.ts.map +1 -0
  167. package/dist/integrations/providers/keychain.test.js +21 -0
  168. package/dist/integrations/providers/keychain.test.js.map +1 -0
  169. package/dist/integrations/providers/mask.d.ts +7 -0
  170. package/dist/integrations/providers/mask.d.ts.map +1 -0
  171. package/dist/integrations/providers/mask.js +14 -0
  172. package/dist/integrations/providers/mask.js.map +1 -0
  173. package/dist/integrations/providers/mask.test.d.ts +2 -0
  174. package/dist/integrations/providers/mask.test.d.ts.map +1 -0
  175. package/dist/integrations/providers/mask.test.js +20 -0
  176. package/dist/integrations/providers/mask.test.js.map +1 -0
  177. package/dist/integrations/providers/oauth.d.ts +28 -0
  178. package/dist/integrations/providers/oauth.d.ts.map +1 -0
  179. package/dist/integrations/providers/oauth.js +65 -0
  180. package/dist/integrations/providers/oauth.js.map +1 -0
  181. package/dist/integrations/providers/oauth.test.d.ts +2 -0
  182. package/dist/integrations/providers/oauth.test.d.ts.map +1 -0
  183. package/dist/integrations/providers/oauth.test.js +86 -0
  184. package/dist/integrations/providers/oauth.test.js.map +1 -0
  185. package/dist/integrations/providers/preferences.d.ts +43 -0
  186. package/dist/integrations/providers/preferences.d.ts.map +1 -0
  187. package/dist/integrations/providers/preferences.js +111 -0
  188. package/dist/integrations/providers/preferences.js.map +1 -0
  189. package/dist/integrations/providers/preferences.test.d.ts +2 -0
  190. package/dist/integrations/providers/preferences.test.d.ts.map +1 -0
  191. package/dist/integrations/providers/preferences.test.js +68 -0
  192. package/dist/integrations/providers/preferences.test.js.map +1 -0
  193. package/dist/integrations/providers/registry.d.ts +31 -0
  194. package/dist/integrations/providers/registry.d.ts.map +1 -0
  195. package/dist/integrations/providers/registry.js +79 -0
  196. package/dist/integrations/providers/registry.js.map +1 -0
  197. package/dist/integrations/providers/schema.d.ts +73 -0
  198. package/dist/integrations/providers/schema.d.ts.map +1 -0
  199. package/dist/integrations/providers/schema.js +70 -0
  200. package/dist/integrations/providers/schema.js.map +1 -0
  201. package/dist/integrations/providers/schema.test.d.ts +2 -0
  202. package/dist/integrations/providers/schema.test.d.ts.map +1 -0
  203. package/dist/integrations/providers/schema.test.js +43 -0
  204. package/dist/integrations/providers/schema.test.js.map +1 -0
  205. package/dist/integrations/providers/secrets.d.ts +37 -0
  206. package/dist/integrations/providers/secrets.d.ts.map +1 -0
  207. package/dist/integrations/providers/secrets.js +69 -0
  208. package/dist/integrations/providers/secrets.js.map +1 -0
  209. package/dist/integrations/providers/store.d.ts +32 -0
  210. package/dist/integrations/providers/store.d.ts.map +1 -0
  211. package/dist/integrations/providers/store.js +133 -0
  212. package/dist/integrations/providers/store.js.map +1 -0
  213. package/dist/integrations/providers/store.test.d.ts +2 -0
  214. package/dist/integrations/providers/store.test.d.ts.map +1 -0
  215. package/dist/integrations/providers/store.test.js +127 -0
  216. package/dist/integrations/providers/store.test.js.map +1 -0
  217. package/dist/integrations/sessions/store.d.ts +40 -0
  218. package/dist/integrations/sessions/store.d.ts.map +1 -0
  219. package/dist/integrations/sessions/store.js +90 -0
  220. package/dist/integrations/sessions/store.js.map +1 -0
  221. package/dist/integrations/subagents/runtime.d.ts +37 -0
  222. package/dist/integrations/subagents/runtime.d.ts.map +1 -0
  223. package/dist/integrations/subagents/runtime.js +183 -0
  224. package/dist/integrations/subagents/runtime.js.map +1 -0
  225. package/dist/integrations/trust/store.d.ts +16 -0
  226. package/dist/integrations/trust/store.d.ts.map +1 -0
  227. package/dist/integrations/trust/store.js +59 -0
  228. package/dist/integrations/trust/store.js.map +1 -0
  229. package/dist/integrations/trust/store.test.d.ts +2 -0
  230. package/dist/integrations/trust/store.test.d.ts.map +1 -0
  231. package/dist/integrations/trust/store.test.js +50 -0
  232. package/dist/integrations/trust/store.test.js.map +1 -0
  233. package/dist/integrations/updates.d.ts +27 -0
  234. package/dist/integrations/updates.d.ts.map +1 -0
  235. package/dist/integrations/updates.js +99 -0
  236. package/dist/integrations/updates.js.map +1 -0
  237. package/dist/memory/store.d.ts +29 -0
  238. package/dist/memory/store.d.ts.map +1 -0
  239. package/dist/memory/store.js +74 -0
  240. package/dist/memory/store.js.map +1 -0
  241. package/dist/memory/store.test.d.ts +2 -0
  242. package/dist/memory/store.test.d.ts.map +1 -0
  243. package/dist/memory/store.test.js +63 -0
  244. package/dist/memory/store.test.js.map +1 -0
  245. package/dist/output/formatter.d.ts +30 -0
  246. package/dist/output/formatter.d.ts.map +1 -0
  247. package/dist/output/formatter.js +16 -0
  248. package/dist/output/formatter.js.map +1 -0
  249. package/dist/output/formatter.test.d.ts +2 -0
  250. package/dist/output/formatter.test.d.ts.map +1 -0
  251. package/dist/output/formatter.test.js +88 -0
  252. package/dist/output/formatter.test.js.map +1 -0
  253. package/dist/output/index.d.ts +5 -0
  254. package/dist/output/index.d.ts.map +1 -0
  255. package/dist/output/index.js +22 -0
  256. package/dist/output/index.js.map +1 -0
  257. package/dist/output/json.d.ts +13 -0
  258. package/dist/output/json.d.ts.map +1 -0
  259. package/dist/output/json.js +51 -0
  260. package/dist/output/json.js.map +1 -0
  261. package/dist/output/text.d.ts +13 -0
  262. package/dist/output/text.d.ts.map +1 -0
  263. package/dist/output/text.js +36 -0
  264. package/dist/output/text.js.map +1 -0
  265. package/dist/output/yaml.d.ts +13 -0
  266. package/dist/output/yaml.d.ts.map +1 -0
  267. package/dist/output/yaml.js +26 -0
  268. package/dist/output/yaml.js.map +1 -0
  269. package/dist/skills/store.d.ts +49 -0
  270. package/dist/skills/store.d.ts.map +1 -0
  271. package/dist/skills/store.js +109 -0
  272. package/dist/skills/store.js.map +1 -0
  273. package/dist/skills/store.test.d.ts +2 -0
  274. package/dist/skills/store.test.d.ts.map +1 -0
  275. package/dist/skills/store.test.js +80 -0
  276. package/dist/skills/store.test.js.map +1 -0
  277. package/dist/tui/App.d.ts +18 -0
  278. package/dist/tui/App.d.ts.map +1 -0
  279. package/dist/tui/App.js +742 -0
  280. package/dist/tui/App.js.map +1 -0
  281. package/dist/tui/Composer.d.ts +17 -0
  282. package/dist/tui/Composer.d.ts.map +1 -0
  283. package/dist/tui/Composer.js +123 -0
  284. package/dist/tui/Composer.js.map +1 -0
  285. package/dist/tui/LiveActivity.d.ts +22 -0
  286. package/dist/tui/LiveActivity.d.ts.map +1 -0
  287. package/dist/tui/LiveActivity.js +46 -0
  288. package/dist/tui/LiveActivity.js.map +1 -0
  289. package/dist/tui/Markdown.d.ts +18 -0
  290. package/dist/tui/Markdown.d.ts.map +1 -0
  291. package/dist/tui/Markdown.js +68 -0
  292. package/dist/tui/Markdown.js.map +1 -0
  293. package/dist/tui/PermissionOverlay.d.ts +14 -0
  294. package/dist/tui/PermissionOverlay.d.ts.map +1 -0
  295. package/dist/tui/PermissionOverlay.js +22 -0
  296. package/dist/tui/PermissionOverlay.js.map +1 -0
  297. package/dist/tui/Picker.d.ts +20 -0
  298. package/dist/tui/Picker.d.ts.map +1 -0
  299. package/dist/tui/Picker.js +72 -0
  300. package/dist/tui/Picker.js.map +1 -0
  301. package/dist/tui/ResumePicker.d.ts +12 -0
  302. package/dist/tui/ResumePicker.d.ts.map +1 -0
  303. package/dist/tui/ResumePicker.js +26 -0
  304. package/dist/tui/ResumePicker.js.map +1 -0
  305. package/dist/tui/StatusBar.d.ts +22 -0
  306. package/dist/tui/StatusBar.d.ts.map +1 -0
  307. package/dist/tui/StatusBar.js +73 -0
  308. package/dist/tui/StatusBar.js.map +1 -0
  309. package/dist/tui/Transcript.d.ts +29 -0
  310. package/dist/tui/Transcript.d.ts.map +1 -0
  311. package/dist/tui/Transcript.js +105 -0
  312. package/dist/tui/Transcript.js.map +1 -0
  313. package/dist/tui/TrustPrompt.d.ts +11 -0
  314. package/dist/tui/TrustPrompt.d.ts.map +1 -0
  315. package/dist/tui/TrustPrompt.js +13 -0
  316. package/dist/tui/TrustPrompt.js.map +1 -0
  317. package/dist/tui/agent.d.ts +163 -0
  318. package/dist/tui/agent.d.ts.map +1 -0
  319. package/dist/tui/agent.js +684 -0
  320. package/dist/tui/agent.js.map +1 -0
  321. package/dist/tui/agent.test.d.ts +2 -0
  322. package/dist/tui/agent.test.d.ts.map +1 -0
  323. package/dist/tui/agent.test.js +225 -0
  324. package/dist/tui/agent.test.js.map +1 -0
  325. package/dist/tui/index.d.ts +7 -0
  326. package/dist/tui/index.d.ts.map +1 -0
  327. package/dist/tui/index.js +29 -0
  328. package/dist/tui/index.js.map +1 -0
  329. package/dist/tui/logo.d.ts +23 -0
  330. package/dist/tui/logo.d.ts.map +1 -0
  331. package/dist/tui/logo.js +35 -0
  332. package/dist/tui/logo.js.map +1 -0
  333. package/dist/tui/markdownParser.d.ts +45 -0
  334. package/dist/tui/markdownParser.d.ts.map +1 -0
  335. package/dist/tui/markdownParser.js +127 -0
  336. package/dist/tui/markdownParser.js.map +1 -0
  337. package/dist/tui/markdownParser.test.d.ts +2 -0
  338. package/dist/tui/markdownParser.test.d.ts.map +1 -0
  339. package/dist/tui/markdownParser.test.js +90 -0
  340. package/dist/tui/markdownParser.test.js.map +1 -0
  341. package/dist/tui/mentions.d.ts +22 -0
  342. package/dist/tui/mentions.d.ts.map +1 -0
  343. package/dist/tui/mentions.js +59 -0
  344. package/dist/tui/mentions.js.map +1 -0
  345. package/dist/tui/mentions.test.d.ts +2 -0
  346. package/dist/tui/mentions.test.d.ts.map +1 -0
  347. package/dist/tui/mentions.test.js +35 -0
  348. package/dist/tui/mentions.test.js.map +1 -0
  349. package/dist/tui/slashCommands.d.ts +64 -0
  350. package/dist/tui/slashCommands.d.ts.map +1 -0
  351. package/dist/tui/slashCommands.js +153 -0
  352. package/dist/tui/slashCommands.js.map +1 -0
  353. package/dist/tui/slashCommands.test.d.ts +2 -0
  354. package/dist/tui/slashCommands.test.d.ts.map +1 -0
  355. package/dist/tui/slashCommands.test.js +114 -0
  356. package/dist/tui/slashCommands.test.js.map +1 -0
  357. package/dist/tui/theme.d.ts +34 -0
  358. package/dist/tui/theme.d.ts.map +1 -0
  359. package/dist/tui/theme.js +32 -0
  360. package/dist/tui/theme.js.map +1 -0
  361. package/dist/tui/types.d.ts +27 -0
  362. package/dist/tui/types.d.ts.map +1 -0
  363. package/dist/tui/types.js +7 -0
  364. package/dist/tui/types.js.map +1 -0
  365. package/package.json +67 -57
@@ -0,0 +1,109 @@
1
+ /**
2
+ * `ensureDaemon` — TS port of clawtool's Go `daemon.Ensure(ctx)`.
3
+ *
4
+ * Contract:
5
+ * 1. Read the state file. If healthy (`/v1/health` returns 200), return
6
+ * its endpoint + token verbatim.
7
+ * 2. If missing OR unhealthy, spawn `clawtool daemon start` (detached,
8
+ * `cmd.unref()`), wait briefly for the state file + listener, then
9
+ * re-probe. Return on success or throw with the underlying reason.
10
+ *
11
+ * The spawn path requires `findBinary` to return a real executable. If
12
+ * `autoStart` is disabled in config and the daemon isn't running, throw
13
+ * without spawning — surface "daemon not running" to the user instead.
14
+ */
15
+ import { spawn } from 'node:child_process';
16
+ import { tryReadToken } from './auth.js';
17
+ import { ClawtoolBinaryError, findBinary } from './binary.js';
18
+ import { readDaemonState } from './state.js';
19
+ export class ClawtoolDaemonError extends Error {
20
+ cause;
21
+ constructor(message, cause) {
22
+ super(message);
23
+ this.cause = cause;
24
+ this.name = 'ClawtoolDaemonError';
25
+ }
26
+ }
27
+ const DEFAULT_READY_TIMEOUT_MS = 10_000;
28
+ const DEFAULT_POLL_INTERVAL_MS = 200;
29
+ export async function ensureDaemon(opts = {}) {
30
+ const fetchFn = opts.fetch ?? globalThis.fetch;
31
+ const autoStart = opts.autoStart ?? true;
32
+ // 1. If the user supplied both endpoint and token, trust them — no
33
+ // discovery, no spawn. Power-user escape hatch (e.g. remote daemon
34
+ // or test harness). An explicit empty-string token is honored so
35
+ // callers can address a `--no-auth` remote daemon without needing
36
+ // a synthetic placeholder; only `undefined` triggers discovery.
37
+ if (opts.endpoint !== undefined && opts.token !== undefined) {
38
+ return { baseUrl: normalizeUrl(opts.endpoint), token: opts.token };
39
+ }
40
+ // 2. Try state file first.
41
+ const fromState = await tryStateEndpoint(opts, fetchFn);
42
+ if (fromState)
43
+ return fromState;
44
+ // 3. Auto-spawn if allowed.
45
+ if (!autoStart) {
46
+ throw new ClawtoolDaemonError('clawtool daemon is not running and `clawtool.autoStart` is disabled — start it manually with `clawtool daemon start`');
47
+ }
48
+ await spawnDaemon(opts);
49
+ // 4. Poll for readiness.
50
+ const deadline = Date.now() + (opts.readyTimeoutMs ?? DEFAULT_READY_TIMEOUT_MS);
51
+ const interval = opts.pollIntervalMs ?? DEFAULT_POLL_INTERVAL_MS;
52
+ while (Date.now() < deadline) {
53
+ await sleep(interval);
54
+ const ready = await tryStateEndpoint(opts, fetchFn);
55
+ if (ready)
56
+ return ready;
57
+ }
58
+ throw new ClawtoolDaemonError(`clawtool daemon did not become ready within ${opts.readyTimeoutMs ?? DEFAULT_READY_TIMEOUT_MS}ms after spawn`);
59
+ }
60
+ async function tryStateEndpoint(opts, fetchFn) {
61
+ const state = readDaemonState();
62
+ if (!state)
63
+ return null;
64
+ const baseUrl = normalizeUrl(opts.endpoint ?? `http://127.0.0.1:${state.port}`);
65
+ if (!(await isHealthy(baseUrl, fetchFn)))
66
+ return null;
67
+ // Token is optional. The locally-managed daemon (`clawtool daemon start`)
68
+ // runs with `--no-auth` and writes no token file; bearer-mode tokens
69
+ // only appear when the user runs `clawtool serve` themselves. Empty
70
+ // token signals the MCP client to skip the Authorization header.
71
+ const token = opts.token ?? tryReadToken(state.token_file) ?? '';
72
+ return { baseUrl, token };
73
+ }
74
+ async function isHealthy(baseUrl, fetchFn) {
75
+ try {
76
+ const res = await fetchFn(`${baseUrl}/v1/health`, { method: 'GET' });
77
+ return res.ok;
78
+ }
79
+ catch {
80
+ return false;
81
+ }
82
+ }
83
+ async function spawnDaemon(opts) {
84
+ let binary;
85
+ try {
86
+ binary = findBinary({ override: opts.binary });
87
+ }
88
+ catch (err) {
89
+ if (err instanceof ClawtoolBinaryError) {
90
+ throw new ClawtoolDaemonError(err.message, err);
91
+ }
92
+ throw err;
93
+ }
94
+ const child = spawn(binary, ['daemon', 'start'], {
95
+ stdio: 'ignore',
96
+ detached: true,
97
+ });
98
+ child.on('error', (err) => {
99
+ throw new ClawtoolDaemonError(`failed to spawn ${binary}: ${err.message}`, err);
100
+ });
101
+ child.unref();
102
+ }
103
+ function normalizeUrl(u) {
104
+ return u.replace(/\/$/, '');
105
+ }
106
+ function sleep(ms) {
107
+ return new Promise((resolve) => setTimeout(resolve, ms));
108
+ }
109
+ //# sourceMappingURL=daemon.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"daemon.js","sourceRoot":"","sources":["../../../src/integrations/clawtool/daemon.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAA;AAE1C,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAA;AACxC,OAAO,EAAE,mBAAmB,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AAC7D,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AAG5C,MAAM,OAAO,mBAAoB,SAAQ,KAAK;IAGnC;IAFV,YACC,OAAe,EACN,KAAe;QAExB,KAAK,CAAC,OAAO,CAAC,CAAA;QAFL,UAAK,GAAL,KAAK,CAAU;QAGxB,IAAI,CAAC,IAAI,GAAG,qBAAqB,CAAA;IAClC,CAAC;CACD;AAmBD,MAAM,wBAAwB,GAAG,MAAM,CAAA;AACvC,MAAM,wBAAwB,GAAG,GAAG,CAAA;AAEpC,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,OAA4B,EAAE;IAChE,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,IAAI,UAAU,CAAC,KAAK,CAAA;IAC9C,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,IAAI,IAAI,CAAA;IAExC,mEAAmE;IACnE,sEAAsE;IACtE,oEAAoE;IACpE,qEAAqE;IACrE,mEAAmE;IACnE,IAAI,IAAI,CAAC,QAAQ,KAAK,SAAS,IAAI,IAAI,CAAC,KAAK,KAAK,SAAS,EAAE,CAAC;QAC7D,OAAO,EAAE,OAAO,EAAE,YAAY,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,CAAA;IACnE,CAAC;IAED,2BAA2B;IAC3B,MAAM,SAAS,GAAG,MAAM,gBAAgB,CAAC,IAAI,EAAE,OAAO,CAAC,CAAA;IACvD,IAAI,SAAS;QAAE,OAAO,SAAS,CAAA;IAE/B,4BAA4B;IAC5B,IAAI,CAAC,SAAS,EAAE,CAAC;QAChB,MAAM,IAAI,mBAAmB,CAC5B,sHAAsH,CACtH,CAAA;IACF,CAAC;IACD,MAAM,WAAW,CAAC,IAAI,CAAC,CAAA;IAEvB,yBAAyB;IACzB,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,CAAC,IAAI,CAAC,cAAc,IAAI,wBAAwB,CAAC,CAAA;IAC/E,MAAM,QAAQ,GAAG,IAAI,CAAC,cAAc,IAAI,wBAAwB,CAAA;IAChE,OAAO,IAAI,CAAC,GAAG,EAAE,GAAG,QAAQ,EAAE,CAAC;QAC9B,MAAM,KAAK,CAAC,QAAQ,CAAC,CAAA;QACrB,MAAM,KAAK,GAAG,MAAM,gBAAgB,CAAC,IAAI,EAAE,OAAO,CAAC,CAAA;QACnD,IAAI,KAAK;YAAE,OAAO,KAAK,CAAA;IACxB,CAAC;IACD,MAAM,IAAI,mBAAmB,CAC5B,+CAA+C,IAAI,CAAC,cAAc,IAAI,wBAAwB,gBAAgB,CAC9G,CAAA;AACF,CAAC;AAED,KAAK,UAAU,gBAAgB,CAC9B,IAAyB,EACzB,OAAqB;IAErB,MAAM,KAAK,GAAG,eAAe,EAAE,CAAA;IAC/B,IAAI,CAAC,KAAK;QAAE,OAAO,IAAI,CAAA;IACvB,MAAM,OAAO,GAAG,YAAY,CAAC,IAAI,CAAC,QAAQ,IAAI,oBAAoB,KAAK,CAAC,IAAI,EAAE,CAAC,CAAA;IAC/E,IAAI,CAAC,CAAC,MAAM,SAAS,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QAAE,OAAO,IAAI,CAAA;IACrD,0EAA0E;IAC1E,qEAAqE;IACrE,oEAAoE;IACpE,iEAAiE;IACjE,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,IAAI,YAAY,CAAC,KAAK,CAAC,UAAU,CAAC,IAAI,EAAE,CAAA;IAChE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,CAAA;AAC1B,CAAC;AAED,KAAK,UAAU,SAAS,CAAC,OAAe,EAAE,OAAqB;IAC9D,IAAI,CAAC;QACJ,MAAM,GAAG,GAAG,MAAM,OAAO,CAAC,GAAG,OAAO,YAAY,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAA;QACpE,OAAO,GAAG,CAAC,EAAE,CAAA;IACd,CAAC;IAAC,MAAM,CAAC;QACR,OAAO,KAAK,CAAA;IACb,CAAC;AACF,CAAC;AAED,KAAK,UAAU,WAAW,CAAC,IAAyB;IACnD,IAAI,MAAc,CAAA;IAClB,IAAI,CAAC;QACJ,MAAM,GAAG,UAAU,CAAC,EAAE,QAAQ,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC,CAAA;IAC/C,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACd,IAAI,GAAG,YAAY,mBAAmB,EAAE,CAAC;YACxC,MAAM,IAAI,mBAAmB,CAAC,GAAG,CAAC,OAAO,EAAE,GAAG,CAAC,CAAA;QAChD,CAAC;QACD,MAAM,GAAG,CAAA;IACV,CAAC;IACD,MAAM,KAAK,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,OAAO,CAAC,EAAE;QAChD,KAAK,EAAE,QAAQ;QACf,QAAQ,EAAE,IAAI;KACd,CAAC,CAAA;IACF,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,EAAE;QACzB,MAAM,IAAI,mBAAmB,CAAC,mBAAmB,MAAM,KAAK,GAAG,CAAC,OAAO,EAAE,EAAE,GAAG,CAAC,CAAA;IAChF,CAAC,CAAC,CAAA;IACF,KAAK,CAAC,KAAK,EAAE,CAAA;AACd,CAAC;AAED,SAAS,YAAY,CAAC,CAAS;IAC9B,OAAO,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAA;AAC5B,CAAC;AAED,SAAS,KAAK,CAAC,EAAU;IACxB,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAA;AACzD,CAAC"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Unit tests for `ensureDaemon`. We test every path that does NOT
3
+ * require spawning a real subprocess (state-file read, health-poll over
4
+ * mocked fetch, override pass-through, autoStart=false short-circuit).
5
+ * The actual spawn → external `clawtool daemon start` path is exercised
6
+ * by live end-to-end smoke against a real clawtool daemon; automating
7
+ * it cleanly requires a CI fixture that will land when we wire
8
+ * integration tests.
9
+ */
10
+ export {};
11
+ //# sourceMappingURL=daemon.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"daemon.test.d.ts","sourceRoot":"","sources":["../../../src/integrations/clawtool/daemon.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG"}
@@ -0,0 +1,118 @@
1
+ /**
2
+ * Unit tests for `ensureDaemon`. We test every path that does NOT
3
+ * require spawning a real subprocess (state-file read, health-poll over
4
+ * mocked fetch, override pass-through, autoStart=false short-circuit).
5
+ * The actual spawn → external `clawtool daemon start` path is exercised
6
+ * by live end-to-end smoke against a real clawtool daemon; automating
7
+ * it cleanly requires a CI fixture that will land when we wire
8
+ * integration tests.
9
+ */
10
+ import { mkdtempSync, writeFileSync } from 'node:fs';
11
+ import { tmpdir } from 'node:os';
12
+ import { join } from 'node:path';
13
+ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
14
+ import { ClawtoolDaemonError, ensureDaemon } from './daemon.js';
15
+ function stateFileFixture() {
16
+ const home = mkdtempSync(join(tmpdir(), 'namzu-daemon-'));
17
+ const configDir = join(home, '.config', 'clawtool');
18
+ const tokenPath = join(configDir, 'listener-token');
19
+ // Mirror what `clawtool daemon start` writes: state JSON + (sometimes) token.
20
+ const state = {
21
+ version: 1,
22
+ pid: 99999,
23
+ port: 51234,
24
+ started_at: '2026-05-24T12:00:00Z',
25
+ token_file: tokenPath,
26
+ log_file: join(home, '.local', 'state', 'clawtool', 'daemon.log'),
27
+ };
28
+ const fs = require('node:fs');
29
+ fs.mkdirSync(configDir, { recursive: true });
30
+ fs.writeFileSync(join(configDir, 'daemon.json'), JSON.stringify(state));
31
+ return { dir: home, tokenPath };
32
+ }
33
+ describe('ensureDaemon', () => {
34
+ let originalEnv;
35
+ beforeEach(() => {
36
+ originalEnv = process.env;
37
+ process.env = { ...originalEnv };
38
+ });
39
+ afterEach(() => {
40
+ process.env = originalEnv;
41
+ });
42
+ it('returns immediately when endpoint AND token are both overridden — no daemon, no probe', async () => {
43
+ const fetchMock = vi.fn();
44
+ const result = await ensureDaemon({
45
+ endpoint: 'http://daemon.example.com:9999',
46
+ token: 'preset-token',
47
+ fetch: fetchMock,
48
+ });
49
+ expect(result).toEqual({ baseUrl: 'http://daemon.example.com:9999', token: 'preset-token' });
50
+ expect(fetchMock).not.toHaveBeenCalled();
51
+ });
52
+ it('uses state-file endpoint when daemon is healthy and no token file present (no-auth mode)', async () => {
53
+ const { dir } = stateFileFixture();
54
+ process.env = { ...originalEnv, XDG_CONFIG_HOME: join(dir, '.config') };
55
+ const fetchMock = vi
56
+ .fn()
57
+ .mockResolvedValue(new Response('{"status":"ok"}', { status: 200 }));
58
+ const result = await ensureDaemon({ fetch: fetchMock });
59
+ expect(result.baseUrl).toBe('http://127.0.0.1:51234');
60
+ expect(result.token).toBe(''); // no token file = no-auth daemon
61
+ expect(fetchMock).toHaveBeenCalledWith('http://127.0.0.1:51234/v1/health', { method: 'GET' });
62
+ });
63
+ it('uses state-file endpoint with token from file when present', async () => {
64
+ const { dir, tokenPath } = stateFileFixture();
65
+ writeFileSync(tokenPath, 'deadbeef\n');
66
+ process.env = { ...originalEnv, XDG_CONFIG_HOME: join(dir, '.config') };
67
+ const fetchMock = vi
68
+ .fn()
69
+ .mockResolvedValue(new Response('{"status":"ok"}', { status: 200 }));
70
+ const result = await ensureDaemon({ fetch: fetchMock });
71
+ expect(result.token).toBe('deadbeef');
72
+ });
73
+ it('config.token wins over the file token', async () => {
74
+ const { dir, tokenPath } = stateFileFixture();
75
+ writeFileSync(tokenPath, 'file-token\n');
76
+ process.env = { ...originalEnv, XDG_CONFIG_HOME: join(dir, '.config') };
77
+ const fetchMock = vi
78
+ .fn()
79
+ .mockResolvedValue(new Response('{"status":"ok"}', { status: 200 }));
80
+ const result = await ensureDaemon({ fetch: fetchMock, token: 'override-token' });
81
+ expect(result.token).toBe('override-token');
82
+ });
83
+ it('config.endpoint overrides the state-file port', async () => {
84
+ const { dir } = stateFileFixture();
85
+ process.env = { ...originalEnv, XDG_CONFIG_HOME: join(dir, '.config') };
86
+ const fetchMock = vi
87
+ .fn()
88
+ .mockResolvedValue(new Response('{"status":"ok"}', { status: 200 }));
89
+ const result = await ensureDaemon({
90
+ fetch: fetchMock,
91
+ endpoint: 'http://my-remote-daemon:8765',
92
+ });
93
+ expect(result.baseUrl).toBe('http://my-remote-daemon:8765');
94
+ expect(fetchMock).toHaveBeenCalledWith('http://my-remote-daemon:8765/v1/health', {
95
+ method: 'GET',
96
+ });
97
+ });
98
+ it('throws ClawtoolDaemonError when autoStart=false and the daemon is unreachable', async () => {
99
+ // Point to an XDG dir with no state file → readDaemonState returns null
100
+ // → tryStateEndpoint returns null → autoStart short-circuits.
101
+ const empty = mkdtempSync(join(tmpdir(), 'namzu-daemon-empty-'));
102
+ process.env = { ...originalEnv, XDG_CONFIG_HOME: empty };
103
+ await expect(ensureDaemon({ autoStart: false, fetch: vi.fn() })).rejects.toThrow(ClawtoolDaemonError);
104
+ });
105
+ it('treats non-200 /v1/health as unhealthy and (with autoStart=false) gives up', async () => {
106
+ const { dir } = stateFileFixture();
107
+ process.env = { ...originalEnv, XDG_CONFIG_HOME: join(dir, '.config') };
108
+ const fetchMock = vi.fn().mockResolvedValue(new Response('', { status: 503 }));
109
+ await expect(ensureDaemon({ autoStart: false, fetch: fetchMock })).rejects.toThrow(ClawtoolDaemonError);
110
+ });
111
+ it('treats fetch error as unhealthy and (with autoStart=false) gives up', async () => {
112
+ const { dir } = stateFileFixture();
113
+ process.env = { ...originalEnv, XDG_CONFIG_HOME: join(dir, '.config') };
114
+ const fetchMock = vi.fn().mockRejectedValue(new Error('ECONNREFUSED'));
115
+ await expect(ensureDaemon({ autoStart: false, fetch: fetchMock })).rejects.toThrow(ClawtoolDaemonError);
116
+ });
117
+ });
118
+ //# sourceMappingURL=daemon.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"daemon.test.js","sourceRoot":"","sources":["../../../src/integrations/clawtool/daemon.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Client for clawtool's `POST /v1/send_message` — the canonical agent
3
+ * dispatcher. Returns an async iterable of normalized text frames so the
4
+ * TUI can stream tokens into the transcript without caring about the
5
+ * upstream CLI's exact wire format.
6
+ *
7
+ * The clawtool server passes through the upstream agent's NDJSON frames
8
+ * verbatim. Different families (claude, codex, gemini, …) emit different
9
+ * shapes. We do **best-effort normalization**: extract any `text` /
10
+ * `content` string fields as visible deltas; collapse `error` lines into
11
+ * error events; everything else (tool_use, tool_result, ping, message
12
+ * envelopes) is silently consumed for now — tool-call surfacing lands
13
+ * with the tool permission overlay.
14
+ */
15
+ import { type EnsureDaemonOptions } from './daemon.js';
16
+ export type DispatchEvent = {
17
+ readonly kind: 'delta';
18
+ readonly text: string;
19
+ } | {
20
+ readonly kind: 'done';
21
+ } | {
22
+ readonly kind: 'error';
23
+ readonly message: string;
24
+ };
25
+ export interface SendMessageOptions extends EnsureDaemonOptions {
26
+ readonly instance: string;
27
+ readonly prompt: string;
28
+ /** Pass-through dispatch options (e.g. session_id, model, format). */
29
+ readonly opts?: Record<string, unknown>;
30
+ readonly signal?: AbortSignal;
31
+ }
32
+ export declare function sendMessage(opts: SendMessageOptions): AsyncIterable<DispatchEvent>;
33
+ //# sourceMappingURL=dispatch.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dispatch.d.ts","sourceRoot":"","sources":["../../../src/integrations/clawtool/dispatch.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAE,KAAK,mBAAmB,EAAgB,MAAM,aAAa,CAAA;AAEpE,MAAM,MAAM,aAAa,GACtB;IAAE,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GACjD;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GACzB;IAAE,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAA;AAEvD,MAAM,WAAW,kBAAmB,SAAQ,mBAAmB;IAC9D,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,sEAAsE;IACtE,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IACvC,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,CAAA;CAC7B;AAED,wBAAuB,WAAW,CAAC,IAAI,EAAE,kBAAkB,GAAG,aAAa,CAAC,aAAa,CAAC,CAwFzF"}
@@ -0,0 +1,155 @@
1
+ /**
2
+ * Client for clawtool's `POST /v1/send_message` — the canonical agent
3
+ * dispatcher. Returns an async iterable of normalized text frames so the
4
+ * TUI can stream tokens into the transcript without caring about the
5
+ * upstream CLI's exact wire format.
6
+ *
7
+ * The clawtool server passes through the upstream agent's NDJSON frames
8
+ * verbatim. Different families (claude, codex, gemini, …) emit different
9
+ * shapes. We do **best-effort normalization**: extract any `text` /
10
+ * `content` string fields as visible deltas; collapse `error` lines into
11
+ * error events; everything else (tool_use, tool_result, ping, message
12
+ * envelopes) is silently consumed for now — tool-call surfacing lands
13
+ * with the tool permission overlay.
14
+ */
15
+ import { ensureDaemon } from './daemon.js';
16
+ export async function* sendMessage(opts) {
17
+ const endpoint = await ensureDaemon(opts);
18
+ const fetchFn = opts.fetch ?? globalThis.fetch;
19
+ const headers = { 'Content-Type': 'application/json' };
20
+ if (endpoint.token.length > 0) {
21
+ headers.Authorization = `Bearer ${endpoint.token}`;
22
+ }
23
+ const body = {
24
+ instance: opts.instance,
25
+ prompt: opts.prompt,
26
+ };
27
+ if (opts.opts)
28
+ body.opts = opts.opts;
29
+ let res;
30
+ try {
31
+ res = await fetchFn(`${endpoint.baseUrl}/v1/send_message`, {
32
+ method: 'POST',
33
+ headers,
34
+ body: JSON.stringify(body),
35
+ signal: opts.signal,
36
+ });
37
+ }
38
+ catch (err) {
39
+ yield {
40
+ kind: 'error',
41
+ message: `clawtool /v1/send_message request failed: ${err instanceof Error ? err.message : String(err)}`,
42
+ };
43
+ return;
44
+ }
45
+ if (!res.ok) {
46
+ // Best-effort: server may have returned a JSON error body.
47
+ let detail = `HTTP ${res.status}`;
48
+ try {
49
+ const errBody = (await res.json());
50
+ if (errBody?.error)
51
+ detail += `: ${errBody.error}`;
52
+ }
53
+ catch {
54
+ // non-JSON body, ignore
55
+ }
56
+ yield { kind: 'error', message: `clawtool /v1/send_message ${detail}` };
57
+ return;
58
+ }
59
+ if (!res.body) {
60
+ yield { kind: 'error', message: 'clawtool /v1/send_message returned no body' };
61
+ return;
62
+ }
63
+ const reader = res.body.getReader();
64
+ const decoder = new TextDecoder();
65
+ let buffer = '';
66
+ try {
67
+ while (true) {
68
+ const { done, value } = await reader.read();
69
+ if (done)
70
+ break;
71
+ buffer += decoder.decode(value, { stream: true });
72
+ let nl = buffer.indexOf('\n');
73
+ while (nl !== -1) {
74
+ const line = buffer.slice(0, nl).trim();
75
+ buffer = buffer.slice(nl + 1);
76
+ const event = parseFrame(line);
77
+ if (event)
78
+ yield event;
79
+ nl = buffer.indexOf('\n');
80
+ }
81
+ }
82
+ const tail = buffer.trim();
83
+ if (tail.length > 0) {
84
+ const event = parseFrame(tail);
85
+ if (event)
86
+ yield event;
87
+ }
88
+ yield { kind: 'done' };
89
+ }
90
+ catch (err) {
91
+ if (err.name === 'AbortError') {
92
+ yield { kind: 'error', message: 'aborted' };
93
+ return;
94
+ }
95
+ yield {
96
+ kind: 'error',
97
+ message: `dispatch stream failed: ${err instanceof Error ? err.message : String(err)}`,
98
+ };
99
+ }
100
+ finally {
101
+ try {
102
+ await reader.cancel();
103
+ }
104
+ catch {
105
+ // reader already closed by the runtime — ignore
106
+ }
107
+ }
108
+ }
109
+ function parseFrame(line) {
110
+ if (line.length === 0)
111
+ return null;
112
+ let frame;
113
+ try {
114
+ frame = JSON.parse(line);
115
+ }
116
+ catch {
117
+ // Some upstreams emit plain-text lines; treat them as deltas.
118
+ return { kind: 'delta', text: `${line}\n` };
119
+ }
120
+ if (typeof frame.error === 'string' && frame.error.length > 0) {
121
+ return { kind: 'error', message: frame.error };
122
+ }
123
+ // Best-effort text extraction across known frame shapes (text_delta,
124
+ // content_block_delta, message_start, etc.). Tool-call / tool-result
125
+ // frames are silently dropped here; the tool permission overlay
126
+ // will surface them when it lands.
127
+ const text = extractText(frame);
128
+ if (text !== null && text.length > 0) {
129
+ return { kind: 'delta', text };
130
+ }
131
+ return null;
132
+ }
133
+ function extractText(frame) {
134
+ if (typeof frame.text === 'string')
135
+ return frame.text;
136
+ if (typeof frame.content === 'string')
137
+ return frame.content;
138
+ // Anthropic streaming shape: { type: 'content_block_delta', delta: { text: '...' } }
139
+ if (frame.delta && typeof frame.delta === 'object') {
140
+ const delta = frame.delta;
141
+ if (typeof delta.text === 'string')
142
+ return delta.text;
143
+ if (typeof delta.content === 'string')
144
+ return delta.content;
145
+ }
146
+ // OpenAI-compatible: { choices: [{ delta: { content: '...' } }] }
147
+ const choices = frame.choices;
148
+ if (Array.isArray(choices) && choices[0]?.delta?.content) {
149
+ const v = choices[0].delta.content;
150
+ if (typeof v === 'string')
151
+ return v;
152
+ }
153
+ return null;
154
+ }
155
+ //# sourceMappingURL=dispatch.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dispatch.js","sourceRoot":"","sources":["../../../src/integrations/clawtool/dispatch.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAA4B,YAAY,EAAE,MAAM,aAAa,CAAA;AAepE,MAAM,CAAC,KAAK,SAAS,CAAC,CAAC,WAAW,CAAC,IAAwB;IAC1D,MAAM,QAAQ,GAAG,MAAM,YAAY,CAAC,IAAI,CAAC,CAAA;IACzC,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,IAAI,UAAU,CAAC,KAAK,CAAA;IAE9C,MAAM,OAAO,GAA2B,EAAE,cAAc,EAAE,kBAAkB,EAAE,CAAA;IAC9E,IAAI,QAAQ,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC/B,OAAO,CAAC,aAAa,GAAG,UAAU,QAAQ,CAAC,KAAK,EAAE,CAAA;IACnD,CAAC;IAED,MAAM,IAAI,GAA4B;QACrC,QAAQ,EAAE,IAAI,CAAC,QAAQ;QACvB,MAAM,EAAE,IAAI,CAAC,MAAM;KACnB,CAAA;IACD,IAAI,IAAI,CAAC,IAAI;QAAE,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,IAAI,CAAA;IAEpC,IAAI,GAAa,CAAA;IACjB,IAAI,CAAC;QACJ,GAAG,GAAG,MAAM,OAAO,CAAC,GAAG,QAAQ,CAAC,OAAO,kBAAkB,EAAE;YAC1D,MAAM,EAAE,MAAM;YACd,OAAO;YACP,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;YAC1B,MAAM,EAAE,IAAI,CAAC,MAAM;SACnB,CAAC,CAAA;IACH,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACd,MAAM;YACL,IAAI,EAAE,OAAO;YACb,OAAO,EAAE,6CAA6C,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE;SACxG,CAAA;QACD,OAAM;IACP,CAAC;IAED,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;QACb,2DAA2D;QAC3D,IAAI,MAAM,GAAG,QAAQ,GAAG,CAAC,MAAM,EAAE,CAAA;QACjC,IAAI,CAAC;YACJ,MAAM,OAAO,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAuB,CAAA;YACxD,IAAI,OAAO,EAAE,KAAK;gBAAE,MAAM,IAAI,KAAK,OAAO,CAAC,KAAK,EAAE,CAAA;QACnD,CAAC;QAAC,MAAM,CAAC;YACR,wBAAwB;QACzB,CAAC;QACD,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,6BAA6B,MAAM,EAAE,EAAE,CAAA;QACvE,OAAM;IACP,CAAC;IAED,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC;QACf,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,4CAA4C,EAAE,CAAA;QAC9E,OAAM;IACP,CAAC;IAED,MAAM,MAAM,GAAG,GAAG,CAAC,IAAI,CAAC,SAAS,EAAE,CAAA;IACnC,MAAM,OAAO,GAAG,IAAI,WAAW,EAAE,CAAA;IACjC,IAAI,MAAM,GAAG,EAAE,CAAA;IACf,IAAI,CAAC;QACJ,OAAO,IAAI,EAAE,CAAC;YACb,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,MAAM,MAAM,CAAC,IAAI,EAAE,CAAA;YAC3C,IAAI,IAAI;gBAAE,MAAK;YACf,MAAM,IAAI,OAAO,CAAC,MAAM,CAAC,KAAK,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAA;YACjD,IAAI,EAAE,GAAG,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAA;YAC7B,OAAO,EAAE,KAAK,CAAC,CAAC,EAAE,CAAC;gBAClB,MAAM,IAAI,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,CAAA;gBACvC,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,EAAE,GAAG,CAAC,CAAC,CAAA;gBAC7B,MAAM,KAAK,GAAG,UAAU,CAAC,IAAI,CAAC,CAAA;gBAC9B,IAAI,KAAK;oBAAE,MAAM,KAAK,CAAA;gBACtB,EAAE,GAAG,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAA;YAC1B,CAAC;QACF,CAAC;QACD,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,EAAE,CAAA;QAC1B,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACrB,MAAM,KAAK,GAAG,UAAU,CAAC,IAAI,CAAC,CAAA;YAC9B,IAAI,KAAK;gBAAE,MAAM,KAAK,CAAA;QACvB,CAAC;QACD,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,CAAA;IACvB,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACd,IAAK,GAAyB,CAAC,IAAI,KAAK,YAAY,EAAE,CAAC;YACtD,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,CAAA;YAC3C,OAAM;QACP,CAAC;QACD,MAAM;YACL,IAAI,EAAE,OAAO;YACb,OAAO,EAAE,2BAA2B,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE;SACtF,CAAA;IACF,CAAC;YAAS,CAAC;QACV,IAAI,CAAC;YACJ,MAAM,MAAM,CAAC,MAAM,EAAE,CAAA;QACtB,CAAC;QAAC,MAAM,CAAC;YACR,gDAAgD;QACjD,CAAC;IACF,CAAC;AACF,CAAC;AAED,SAAS,UAAU,CAAC,IAAY;IAC/B,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAA;IAClC,IAAI,KAA8B,CAAA;IAClC,IAAI,CAAC;QACJ,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAA4B,CAAA;IACpD,CAAC;IAAC,MAAM,CAAC;QACR,8DAA8D;QAC9D,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,GAAG,IAAI,IAAI,EAAE,CAAA;IAC5C,CAAC;IACD,IAAI,OAAO,KAAK,CAAC,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC/D,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,CAAC,KAAK,EAAE,CAAA;IAC/C,CAAC;IACD,qEAAqE;IACrE,qEAAqE;IACrE,gEAAgE;IAChE,mCAAmC;IACnC,MAAM,IAAI,GAAG,WAAW,CAAC,KAAK,CAAC,CAAA;IAC/B,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACtC,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,CAAA;IAC/B,CAAC;IACD,OAAO,IAAI,CAAA;AACZ,CAAC;AAED,SAAS,WAAW,CAAC,KAA8B;IAClD,IAAI,OAAO,KAAK,CAAC,IAAI,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC,IAAI,CAAA;IACrD,IAAI,OAAO,KAAK,CAAC,OAAO,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC,OAAO,CAAA;IAC3D,qFAAqF;IACrF,IAAI,KAAK,CAAC,KAAK,IAAI,OAAO,KAAK,CAAC,KAAK,KAAK,QAAQ,EAAE,CAAC;QACpD,MAAM,KAAK,GAAG,KAAK,CAAC,KAAgC,CAAA;QACpD,IAAI,OAAO,KAAK,CAAC,IAAI,KAAK,QAAQ;YAAE,OAAO,KAAK,CAAC,IAAI,CAAA;QACrD,IAAI,OAAO,KAAK,CAAC,OAAO,KAAK,QAAQ;YAAE,OAAO,KAAK,CAAC,OAAO,CAAA;IAC5D,CAAC;IACD,kEAAkE;IAClE,MAAM,OAAO,GAAG,KAAK,CAAC,OAA+D,CAAA;IACrF,IAAI,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC;QAC1D,MAAM,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAA;QAClC,IAAI,OAAO,CAAC,KAAK,QAAQ;YAAE,OAAO,CAAC,CAAA;IACpC,CAAC;IACD,OAAO,IAAI,CAAA;AACZ,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=dispatch.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dispatch.test.d.ts","sourceRoot":"","sources":["../../../src/integrations/clawtool/dispatch.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,138 @@
1
+ import { describe, expect, it, vi } from 'vitest';
2
+ import { sendMessage } from './dispatch.js';
3
+ /** Build a Response that streams `lines` as NDJSON. */
4
+ function ndjsonResponse(lines) {
5
+ const body = `${lines.join('\n')}\n`;
6
+ return new Response(body, {
7
+ status: 200,
8
+ headers: { 'content-type': 'application/x-ndjson' },
9
+ });
10
+ }
11
+ async function collect(it) {
12
+ const out = [];
13
+ for await (const ev of it)
14
+ out.push(ev);
15
+ return out;
16
+ }
17
+ describe('sendMessage', () => {
18
+ it('issues POST /v1/send_message with the right body + headers', async () => {
19
+ const fetchMock = vi.fn().mockResolvedValue(ndjsonResponse(['{"text":"hi"}']));
20
+ await collect(sendMessage({
21
+ endpoint: 'http://localhost:9999',
22
+ token: 'tok',
23
+ instance: 'claude',
24
+ prompt: 'hello',
25
+ fetch: fetchMock,
26
+ }));
27
+ const call = fetchMock.mock.calls[0];
28
+ expect(call?.[0]).toBe('http://localhost:9999/v1/send_message');
29
+ expect(call?.[1]?.method).toBe('POST');
30
+ const headers = call?.[1]?.headers;
31
+ expect(headers['Content-Type']).toBe('application/json');
32
+ expect(headers.Authorization).toBe('Bearer tok');
33
+ expect(JSON.parse(String(call?.[1]?.body))).toEqual({
34
+ instance: 'claude',
35
+ prompt: 'hello',
36
+ });
37
+ });
38
+ it('extracts `text` from each NDJSON line and ends with done', async () => {
39
+ const fetchMock = vi
40
+ .fn()
41
+ .mockResolvedValue(ndjsonResponse(['{"text":"hel"}', '{"text":"lo"}']));
42
+ const events = await collect(sendMessage({
43
+ endpoint: 'http://localhost:9999',
44
+ token: '',
45
+ instance: 'claude',
46
+ prompt: 'x',
47
+ fetch: fetchMock,
48
+ }));
49
+ expect(events).toEqual([
50
+ { kind: 'delta', text: 'hel' },
51
+ { kind: 'delta', text: 'lo' },
52
+ { kind: 'done' },
53
+ ]);
54
+ });
55
+ it('handles Anthropic-shaped content_block_delta frames', async () => {
56
+ const fetchMock = vi
57
+ .fn()
58
+ .mockResolvedValue(ndjsonResponse([
59
+ '{"type":"content_block_delta","delta":{"text":"foo"}}',
60
+ '{"type":"message_stop"}',
61
+ ]));
62
+ const events = await collect(sendMessage({
63
+ endpoint: 'http://localhost:9999',
64
+ token: '',
65
+ instance: 'claude',
66
+ prompt: 'x',
67
+ fetch: fetchMock,
68
+ }));
69
+ expect(events).toEqual([{ kind: 'delta', text: 'foo' }, { kind: 'done' }]);
70
+ });
71
+ it('handles OpenAI-shaped choices[0].delta.content frames', async () => {
72
+ const fetchMock = vi
73
+ .fn()
74
+ .mockResolvedValue(ndjsonResponse(['{"choices":[{"delta":{"content":"hi"}}]}']));
75
+ const events = await collect(sendMessage({
76
+ endpoint: 'http://localhost:9999',
77
+ token: '',
78
+ instance: 'codex',
79
+ prompt: 'x',
80
+ fetch: fetchMock,
81
+ }));
82
+ expect(events[0]).toEqual({ kind: 'delta', text: 'hi' });
83
+ });
84
+ it('falls back to plain-text passthrough for non-JSON lines', async () => {
85
+ const fetchMock = vi.fn().mockResolvedValue(ndjsonResponse(['raw text line']));
86
+ const events = await collect(sendMessage({
87
+ endpoint: 'http://localhost:9999',
88
+ token: '',
89
+ instance: 'aider',
90
+ prompt: 'x',
91
+ fetch: fetchMock,
92
+ }));
93
+ expect(events[0]).toEqual({ kind: 'delta', text: 'raw text line\n' });
94
+ });
95
+ it('surfaces an in-band `error` field as an error event', async () => {
96
+ const fetchMock = vi
97
+ .fn()
98
+ .mockResolvedValue(ndjsonResponse(['{"error":"upstream crashed"}']));
99
+ const events = await collect(sendMessage({
100
+ endpoint: 'http://localhost:9999',
101
+ token: '',
102
+ instance: 'claude',
103
+ prompt: 'x',
104
+ fetch: fetchMock,
105
+ }));
106
+ expect(events[0]).toEqual({ kind: 'error', message: 'upstream crashed' });
107
+ });
108
+ it('translates non-2xx into an error event including HTTP code', async () => {
109
+ const fetchMock = vi.fn().mockResolvedValue(new Response(JSON.stringify({ error: 'instance not callable' }), {
110
+ status: 400,
111
+ headers: { 'content-type': 'application/json' },
112
+ }));
113
+ const events = await collect(sendMessage({
114
+ endpoint: 'http://localhost:9999',
115
+ token: '',
116
+ instance: 'aider',
117
+ prompt: 'x',
118
+ fetch: fetchMock,
119
+ }));
120
+ expect(events[0]).toEqual({
121
+ kind: 'error',
122
+ message: 'clawtool /v1/send_message HTTP 400: instance not callable',
123
+ });
124
+ });
125
+ it('omits the Bearer header when the token is empty', async () => {
126
+ const fetchMock = vi.fn().mockResolvedValue(ndjsonResponse([]));
127
+ await collect(sendMessage({
128
+ endpoint: 'http://localhost:9999',
129
+ token: '',
130
+ instance: 'claude',
131
+ prompt: 'x',
132
+ fetch: fetchMock,
133
+ }));
134
+ const headers = fetchMock.mock.calls[0]?.[1]?.headers;
135
+ expect(headers.Authorization).toBeUndefined();
136
+ });
137
+ });
138
+ //# sourceMappingURL=dispatch.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dispatch.test.js","sourceRoot":"","sources":["../../../src/integrations/clawtool/dispatch.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ export { type Agent, listAgents, type ListAgentsOptions } from './agents.js';
2
+ export { ClawtoolAuthError, readToken, tryReadToken } from './auth.js';
3
+ export { ClawtoolBinaryError, findBinary, type FindBinaryOptions } from './binary.js';
4
+ export { ensureDaemon, ClawtoolDaemonError, type EnsureDaemonOptions } from './daemon.js';
5
+ export { type DispatchEvent, sendMessage, type SendMessageOptions } from './dispatch.js';
6
+ export { ClawtoolMcpClient, MCP_PROTOCOL_VERSION, McpProtocolError, type McpClientOptions, } from './mcp.js';
7
+ export { clawtoolConfigDir, daemonStatePath, listenerTokenPath, } from './paths.js';
8
+ export { createClawtoolPlugin, type ClawtoolPlugin, type ClawtoolProxyTool, type CreateClawtoolPluginOptions, } from './plugin.js';
9
+ export { readDaemonState } from './state.js';
10
+ export type { DaemonEndpoint, DaemonState, McpCallResult, McpTextContent, McpToolDescriptor, } from './types.js';
11
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/integrations/clawtool/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,KAAK,EAAE,UAAU,EAAE,KAAK,iBAAiB,EAAE,MAAM,aAAa,CAAA;AAC5E,OAAO,EAAE,iBAAiB,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,WAAW,CAAA;AACtE,OAAO,EAAE,mBAAmB,EAAE,UAAU,EAAE,KAAK,iBAAiB,EAAE,MAAM,aAAa,CAAA;AACrF,OAAO,EAAE,YAAY,EAAE,mBAAmB,EAAE,KAAK,mBAAmB,EAAE,MAAM,aAAa,CAAA;AACzF,OAAO,EAAE,KAAK,aAAa,EAAE,WAAW,EAAE,KAAK,kBAAkB,EAAE,MAAM,eAAe,CAAA;AACxF,OAAO,EACN,iBAAiB,EACjB,oBAAoB,EACpB,gBAAgB,EAChB,KAAK,gBAAgB,GACrB,MAAM,UAAU,CAAA;AACjB,OAAO,EACN,iBAAiB,EACjB,eAAe,EACf,iBAAiB,GACjB,MAAM,YAAY,CAAA;AACnB,OAAO,EACN,oBAAoB,EACpB,KAAK,cAAc,EACnB,KAAK,iBAAiB,EACtB,KAAK,2BAA2B,GAChC,MAAM,aAAa,CAAA;AACpB,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AAC5C,YAAY,EACX,cAAc,EACd,WAAW,EACX,aAAa,EACb,cAAc,EACd,iBAAiB,GACjB,MAAM,YAAY,CAAA"}