@kosuke-ai/kosuke 1.0.0 → 1.0.2

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 (355) hide show
  1. package/CHANGELOG.md +66 -0
  2. package/README.md +198 -1
  3. package/dist/agent/http.js +18 -0
  4. package/dist/agent/summary.js +419 -0
  5. package/dist/commands/agent.js +22 -0
  6. package/dist/commands/auth.js +117 -0
  7. package/dist/commands/integrations.js +310 -0
  8. package/dist/commands/skill-runs.js +230 -0
  9. package/dist/commands/watch.js +167 -0
  10. package/dist/generated/commands/activity/list.js +73 -0
  11. package/dist/generated/commands/crons/artifacts-list.js +57 -0
  12. package/dist/generated/commands/crons/create.js +65 -0
  13. package/dist/generated/commands/crons/delete.js +18 -0
  14. package/dist/generated/commands/crons/get.js +19 -0
  15. package/dist/generated/commands/crons/list.js +54 -0
  16. package/dist/generated/commands/crons/projects-resume.js +21 -0
  17. package/dist/generated/commands/crons/run.js +37 -0
  18. package/dist/generated/commands/crons/runs-artifacts-get.js +23 -0
  19. package/dist/generated/commands/crons/runs-artifacts-list.js +22 -0
  20. package/dist/generated/commands/crons/runs-cancel.js +21 -0
  21. package/dist/generated/commands/crons/runs-diagnostics.js +23 -0
  22. package/dist/generated/commands/crons/runs-get.js +21 -0
  23. package/dist/generated/commands/crons/runs-list.js +58 -0
  24. package/dist/generated/commands/crons/runs-messages.js +21 -0
  25. package/dist/generated/commands/crons/update.js +73 -0
  26. package/dist/generated/commands/deploy/cancel.js +18 -0
  27. package/dist/generated/commands/deploy/list.js +33 -0
  28. package/dist/generated/commands/deploy/message.js +32 -0
  29. package/dist/generated/commands/deploy/messages.js +18 -0
  30. package/dist/generated/commands/deploy/queue-delete.js +19 -0
  31. package/dist/generated/commands/deploy/queue-list.js +19 -0
  32. package/dist/generated/commands/deploy/queue-move.js +31 -0
  33. package/dist/generated/commands/deploy/queue-resume.js +19 -0
  34. package/dist/generated/commands/deploy/queue-send.js +20 -0
  35. package/dist/generated/commands/deploy/queue-steer.js +20 -0
  36. package/dist/generated/commands/deploy/queue-update.js +56 -0
  37. package/dist/generated/commands/deploy/run.js +65 -0
  38. package/dist/generated/commands/deploy/set-model.js +28 -0
  39. package/dist/generated/commands/devices/list.js +18 -0
  40. package/dist/generated/commands/devices/request.js +31 -0
  41. package/dist/generated/commands/files/delete.js +18 -0
  42. package/dist/generated/commands/files/get.js +19 -0
  43. package/dist/generated/commands/files/list.js +25 -0
  44. package/dist/generated/commands/files/mkdir.js +28 -0
  45. package/dist/generated/commands/files/move.js +35 -0
  46. package/dist/generated/commands/files/put.js +92 -0
  47. package/dist/generated/commands/github/repositories.js +16 -0
  48. package/dist/generated/commands/github/status.js +16 -0
  49. package/dist/generated/commands/index.js +656 -0
  50. package/dist/generated/commands/integrations/execute.js +49 -0
  51. package/dist/generated/commands/integrations/tools.js +70 -0
  52. package/dist/generated/commands/mac/apps.js +30 -0
  53. package/dist/generated/commands/mac/ax-tree.js +65 -0
  54. package/dist/generated/commands/mac/browser-connection-check.js +69 -0
  55. package/dist/generated/commands/mac/browser-connections.js +30 -0
  56. package/dist/generated/commands/mac/browser-profiles.js +36 -0
  57. package/dist/generated/commands/mac/browser-sign-in.js +79 -0
  58. package/dist/generated/commands/mac/browser.js +44 -0
  59. package/dist/generated/commands/mac/click.js +72 -0
  60. package/dist/generated/commands/mac/file-delete.js +37 -0
  61. package/dist/generated/commands/mac/file-list.js +37 -0
  62. package/dist/generated/commands/mac/file-move.js +44 -0
  63. package/dist/generated/commands/mac/file-read.js +37 -0
  64. package/dist/generated/commands/mac/file-write.js +50 -0
  65. package/dist/generated/commands/mac/key.js +58 -0
  66. package/dist/generated/commands/mac/open.js +43 -0
  67. package/dist/generated/commands/mac/screenshot.js +51 -0
  68. package/dist/generated/commands/mac/scroll.js +70 -0
  69. package/dist/generated/commands/mac/shell.js +51 -0
  70. package/dist/generated/commands/mac/tools.js +18 -0
  71. package/dist/generated/commands/mac/type.js +64 -0
  72. package/dist/generated/commands/mac/windows.js +30 -0
  73. package/dist/generated/commands/members/list.js +24 -0
  74. package/dist/generated/commands/models/list.js +16 -0
  75. package/dist/generated/commands/personal-tasks/create.js +72 -0
  76. package/dist/generated/commands/personal-tasks/delete.js +17 -0
  77. package/dist/generated/commands/personal-tasks/get.js +20 -0
  78. package/dist/generated/commands/personal-tasks/list.js +71 -0
  79. package/dist/generated/commands/personal-tasks/move.js +31 -0
  80. package/dist/generated/commands/personal-tasks/start.js +69 -0
  81. package/dist/generated/commands/personal-tasks/update.js +81 -0
  82. package/dist/generated/commands/preview/get.js +26 -0
  83. package/dist/generated/commands/preview/health.js +26 -0
  84. package/dist/generated/commands/preview/reset.js +28 -0
  85. package/dist/generated/commands/preview/share-create.js +37 -0
  86. package/dist/generated/commands/preview/share-delete.js +26 -0
  87. package/dist/generated/commands/preview/share-get.js +27 -0
  88. package/dist/generated/commands/preview/shared-artifact.js +19 -0
  89. package/dist/generated/commands/preview/shared.js +17 -0
  90. package/dist/generated/commands/projects/backlog-items-create.js +35 -0
  91. package/dist/generated/commands/projects/backlog-items-delete.js +19 -0
  92. package/dist/generated/commands/projects/backlog-items-list.js +19 -0
  93. package/dist/generated/commands/projects/backlog-items-send.js +20 -0
  94. package/dist/generated/commands/projects/backlog-items-update.js +42 -0
  95. package/dist/generated/commands/projects/batch-merging-add-member.js +30 -0
  96. package/dist/generated/commands/projects/batch-merging-eject.js +37 -0
  97. package/dist/generated/commands/projects/batch-merging-finish.js +30 -0
  98. package/dist/generated/commands/projects/batch-merging-get.js +19 -0
  99. package/dist/generated/commands/projects/batch-merging-set.js +32 -0
  100. package/dist/generated/commands/projects/branches.js +31 -0
  101. package/dist/generated/commands/projects/create.js +72 -0
  102. package/dist/generated/commands/projects/delete.js +17 -0
  103. package/dist/generated/commands/projects/env-vars-add.js +22 -0
  104. package/dist/generated/commands/projects/env-vars-remove.js +21 -0
  105. package/dist/generated/commands/projects/get.js +18 -0
  106. package/dist/generated/commands/projects/labels-color.js +37 -0
  107. package/dist/generated/commands/projects/labels-delete.js +50 -0
  108. package/dist/generated/commands/projects/labels-usage.js +27 -0
  109. package/dist/generated/commands/projects/labels.js +18 -0
  110. package/dist/generated/commands/projects/list.js +16 -0
  111. package/dist/generated/commands/projects/live-logs.js +34 -0
  112. package/dist/generated/commands/projects/live-query.js +30 -0
  113. package/dist/generated/commands/projects/live-traffic.js +27 -0
  114. package/dist/generated/commands/projects/live-write-status.js +20 -0
  115. package/dist/generated/commands/projects/live-write.js +37 -0
  116. package/dist/generated/commands/projects/qa-guide-get.js +19 -0
  117. package/dist/generated/commands/projects/qa-guide-set.js +40 -0
  118. package/dist/generated/commands/projects/releases.js +18 -0
  119. package/dist/generated/commands/projects/services-add.js +88 -0
  120. package/dist/generated/commands/projects/services-list.js +19 -0
  121. package/dist/generated/commands/projects/services-remove.js +19 -0
  122. package/dist/generated/commands/projects/services-update.js +82 -0
  123. package/dist/generated/commands/projects/settings-get.js +19 -0
  124. package/dist/generated/commands/projects/settings-import.js +99 -0
  125. package/dist/generated/commands/projects/settings-update.js +85 -0
  126. package/dist/generated/commands/projects/skills.js +39 -0
  127. package/dist/generated/commands/projects/switch-workflow.js +34 -0
  128. package/dist/generated/commands/projects/update.js +28 -0
  129. package/dist/generated/commands/projects/versions.js +18 -0
  130. package/dist/generated/commands/sensei/cards-close.js +43 -0
  131. package/dist/generated/commands/sensei/cards-mark-read.js +30 -0
  132. package/dist/generated/commands/sensei/cards-put.js +152 -0
  133. package/dist/generated/commands/sensei/cards-send-reply.js +30 -0
  134. package/dist/generated/commands/sensei/cards.js +38 -0
  135. package/dist/generated/commands/sensei/chat.js +23 -0
  136. package/dist/generated/commands/sensei/connect.js +57 -0
  137. package/dist/generated/commands/sensei/delegates-get.js +21 -0
  138. package/dist/generated/commands/sensei/delegates-note.js +46 -0
  139. package/dist/generated/commands/sensei/delegates-start.js +51 -0
  140. package/dist/generated/commands/sensei/delegates-stop.js +21 -0
  141. package/dist/generated/commands/sensei/describe.js +36 -0
  142. package/dist/generated/commands/sensei/device-requests-decide.js +48 -0
  143. package/dist/generated/commands/sensei/device-requests-list.js +27 -0
  144. package/dist/generated/commands/sensei/memory-get.js +19 -0
  145. package/dist/generated/commands/sensei/memory-put.js +55 -0
  146. package/dist/generated/commands/sensei/merge-rule.js +36 -0
  147. package/dist/generated/commands/sensei/merge.js +36 -0
  148. package/dist/generated/commands/sensei/messages-reply.js +44 -0
  149. package/dist/generated/commands/sensei/messages-reroute.js +37 -0
  150. package/dist/generated/commands/sensei/messages-send.js +98 -0
  151. package/dist/generated/commands/sensei/notifications-open.js +19 -0
  152. package/dist/generated/commands/sensei/reels-activity.js +16 -0
  153. package/dist/generated/commands/sensei/reels-proposals.js +24 -0
  154. package/dist/generated/commands/sensei/reels-ranks.js +16 -0
  155. package/dist/generated/commands/sensei/reels-skips.js +32 -0
  156. package/dist/generated/commands/sensei/repository.js +36 -0
  157. package/dist/generated/commands/sensei/review-approve.js +37 -0
  158. package/dist/generated/commands/sensei/review-ask.js +44 -0
  159. package/dist/generated/commands/sensei/review-context.js +32 -0
  160. package/dist/generated/commands/sensei/sessions-assess.js +71 -0
  161. package/dist/generated/commands/sensei/sessions-facts.js +26 -0
  162. package/dist/generated/commands/sensei/suggest.js +36 -0
  163. package/dist/generated/commands/sensei/thread-done.js +21 -0
  164. package/dist/generated/commands/sensei/thread-move.js +30 -0
  165. package/dist/generated/commands/sensei/thread-read.js +41 -0
  166. package/dist/generated/commands/sensei/thread-split.js +30 -0
  167. package/dist/generated/commands/sensei/threads.js +47 -0
  168. package/dist/generated/commands/sensei/tickets-merge.js +51 -0
  169. package/dist/generated/commands/sensei/widgets.js +15 -0
  170. package/dist/generated/commands/sessions/activate.js +33 -0
  171. package/dist/generated/commands/sessions/all.js +142 -0
  172. package/dist/generated/commands/sessions/app-stack-start.js +20 -0
  173. package/dist/generated/commands/sessions/artifacts-attach.js +31 -0
  174. package/dist/generated/commands/sessions/artifacts-get.js +21 -0
  175. package/dist/generated/commands/sessions/artifacts-list.js +20 -0
  176. package/dist/generated/commands/sessions/create.js +234 -0
  177. package/dist/generated/commands/sessions/delete.js +21 -0
  178. package/dist/generated/commands/sessions/desktop-control.js +35 -0
  179. package/dist/generated/commands/sessions/desktop-start.js +19 -0
  180. package/dist/generated/commands/sessions/desktop.js +19 -0
  181. package/dist/generated/commands/sessions/diff-comments-add.js +65 -0
  182. package/dist/generated/commands/sessions/diff-comments-delete.js +21 -0
  183. package/dist/generated/commands/sessions/diff-comments-list.js +21 -0
  184. package/dist/generated/commands/sessions/diff-comments-update.js +25 -0
  185. package/dist/generated/commands/sessions/diff-commits.js +20 -0
  186. package/dist/generated/commands/sessions/diff-files.js +20 -0
  187. package/dist/generated/commands/sessions/diff-patch.js +87 -0
  188. package/dist/generated/commands/sessions/edit-prompt.js +81 -0
  189. package/dist/generated/commands/sessions/files-get.js +28 -0
  190. package/dist/generated/commands/sessions/files-list.js +20 -0
  191. package/dist/generated/commands/sessions/files-write.js +42 -0
  192. package/dist/generated/commands/sessions/get.js +19 -0
  193. package/dist/generated/commands/sessions/git-commit-message.js +20 -0
  194. package/dist/generated/commands/sessions/git-commit.js +30 -0
  195. package/dist/generated/commands/sessions/git-push.js +20 -0
  196. package/dist/generated/commands/sessions/git-state.js +20 -0
  197. package/dist/generated/commands/sessions/go-ahead-clear.js +22 -0
  198. package/dist/generated/commands/sessions/go-ahead-set.js +40 -0
  199. package/dist/generated/commands/sessions/jobs-cancel.js +21 -0
  200. package/dist/generated/commands/sessions/jobs-get.js +21 -0
  201. package/dist/generated/commands/sessions/jobs-list.js +35 -0
  202. package/dist/generated/commands/sessions/labels-edit.js +45 -0
  203. package/dist/generated/commands/sessions/labels-set.js +45 -0
  204. package/dist/generated/commands/sessions/list.js +130 -0
  205. package/dist/generated/commands/sessions/mark-read.js +19 -0
  206. package/dist/generated/commands/sessions/message.js +33 -0
  207. package/dist/generated/commands/sessions/messages.js +41 -0
  208. package/dist/generated/commands/sessions/needs-you.js +16 -0
  209. package/dist/generated/commands/sessions/qa-clear.js +22 -0
  210. package/dist/generated/commands/sessions/qa-set.js +33 -0
  211. package/dist/generated/commands/sessions/queue-delete.js +23 -0
  212. package/dist/generated/commands/sessions/queue-list.js +20 -0
  213. package/dist/generated/commands/sessions/queue-move.js +32 -0
  214. package/dist/generated/commands/sessions/queue-resume.js +20 -0
  215. package/dist/generated/commands/sessions/queue-send.js +21 -0
  216. package/dist/generated/commands/sessions/queue-steer.js +21 -0
  217. package/dist/generated/commands/sessions/queue-update.js +57 -0
  218. package/dist/generated/commands/sessions/runtime-command.js +39 -0
  219. package/dist/generated/commands/sessions/search.js +24 -0
  220. package/dist/generated/commands/sessions/send.js +138 -0
  221. package/dist/generated/commands/sessions/steer.js +36 -0
  222. package/dist/generated/commands/sessions/sync.js +37 -0
  223. package/dist/generated/commands/sessions/title-generate.js +29 -0
  224. package/dist/generated/commands/sessions/update.js +118 -0
  225. package/dist/generated/commands/tasks/all.js +112 -0
  226. package/dist/generated/commands/tasks/create.js +230 -0
  227. package/dist/generated/commands/tasks/delete.js +18 -0
  228. package/dist/generated/commands/tasks/get.js +19 -0
  229. package/dist/generated/commands/tasks/labels.js +18 -0
  230. package/dist/generated/commands/tasks/list.js +114 -0
  231. package/dist/generated/commands/tasks/start.js +68 -0
  232. package/dist/generated/commands/tasks/update.js +136 -0
  233. package/dist/generated/commands/user/auth-token-revoke.js +16 -0
  234. package/dist/generated/commands/user/crons-artifacts-list.js +59 -0
  235. package/dist/generated/commands/user/crons-create.js +65 -0
  236. package/dist/generated/commands/user/crons-get.js +21 -0
  237. package/dist/generated/commands/user/crons-list.js +41 -0
  238. package/dist/generated/commands/user/crons-run.js +21 -0
  239. package/dist/generated/commands/user/crons-runs-artifacts-get.js +25 -0
  240. package/dist/generated/commands/user/crons-runs-artifacts-list.js +24 -0
  241. package/dist/generated/commands/user/crons-runs-get.js +23 -0
  242. package/dist/generated/commands/user/crons-runs-list.js +52 -0
  243. package/dist/generated/commands/user/crons-update.js +73 -0
  244. package/dist/generated/commands/user/files-delete.js +18 -0
  245. package/dist/generated/commands/user/files-get.js +19 -0
  246. package/dist/generated/commands/user/files-list.js +24 -0
  247. package/dist/generated/commands/user/files-mkdir.js +27 -0
  248. package/dist/generated/commands/user/files-move.js +35 -0
  249. package/dist/generated/commands/user/files-put.js +91 -0
  250. package/dist/generated/commands/user/integrations-linkedin-connect.js +35 -0
  251. package/dist/generated/commands/user/integrations-linkedin-list.js +17 -0
  252. package/dist/generated/commands/user/integrations-linkedin-reconnect.js +19 -0
  253. package/dist/generated/commands/user/integrations-list.js +16 -0
  254. package/dist/generated/commands/user/integrations-remove.js +19 -0
  255. package/dist/generated/commands/user/integrations-x-connect.js +35 -0
  256. package/dist/generated/commands/user/integrations-x-list.js +17 -0
  257. package/dist/generated/commands/user/integrations-x-reconnect.js +19 -0
  258. package/dist/generated/commands/user/memory-list.js +16 -0
  259. package/dist/generated/commands/user/memory-put.js +36 -0
  260. package/dist/generated/commands/user/plugins-list.js +28 -0
  261. package/dist/generated/commands/user/plugins-update.js +29 -0
  262. package/dist/generated/commands/user/profile.js +16 -0
  263. package/dist/generated/commands/user/push-devices-register.js +76 -0
  264. package/dist/generated/commands/user/push-devices-remove.js +26 -0
  265. package/dist/generated/commands/user/skills-create.js +33 -0
  266. package/dist/generated/commands/user/skills-delete.js +18 -0
  267. package/dist/generated/commands/user/skills-get.js +19 -0
  268. package/dist/generated/commands/user/skills-list.js +17 -0
  269. package/dist/generated/commands/user/skills-update.js +35 -0
  270. package/dist/generated/commands/user/subscriptions-delete.js +18 -0
  271. package/dist/generated/commands/user/subscriptions-get.js +17 -0
  272. package/dist/generated/commands/user/subscriptions-grok-change.js +20 -0
  273. package/dist/generated/commands/user/subscriptions-grok-get.js +18 -0
  274. package/dist/generated/commands/user/subscriptions-login-antigravity-cancel.js +34 -0
  275. package/dist/generated/commands/user/subscriptions-login-antigravity-complete.js +40 -0
  276. package/dist/generated/commands/user/subscriptions-login-antigravity-start.js +28 -0
  277. package/dist/generated/commands/user/subscriptions-login-claude-complete.js +34 -0
  278. package/dist/generated/commands/user/subscriptions-login-claude-start.js +29 -0
  279. package/dist/generated/commands/user/subscriptions-login-codex-complete.js +28 -0
  280. package/dist/generated/commands/user/subscriptions-login-codex-start.js +29 -0
  281. package/dist/generated/commands/user/subscriptions-login-muse-complete.js +28 -0
  282. package/dist/generated/commands/user/subscriptions-login-muse-start.js +29 -0
  283. package/dist/generated/commands/user/subscriptions-logins-delete.js +20 -0
  284. package/dist/generated/commands/user/subscriptions-logins-recheck.js +19 -0
  285. package/dist/generated/commands/user/subscriptions-set-default-model.js +33 -0
  286. package/dist/generated/commands/user/subscriptions-set-key.js +35 -0
  287. package/dist/generated/commands/user/subscriptions-token-usage.js +17 -0
  288. package/dist/generated/commands/user/subscriptions-usage.js +52 -0
  289. package/dist/generated/commands/workspaces/access-status.js +30 -0
  290. package/dist/generated/commands/workspaces/ai-provider-get.js +19 -0
  291. package/dist/generated/commands/workspaces/ai-provider-google-delete-method.js +33 -0
  292. package/dist/generated/commands/workspaces/ai-provider-google-get.js +20 -0
  293. package/dist/generated/commands/workspaces/ai-provider-google-remove.js +19 -0
  294. package/dist/generated/commands/workspaces/ai-provider-google-save.js +38 -0
  295. package/dist/generated/commands/workspaces/ai-provider-google-select-method.js +39 -0
  296. package/dist/generated/commands/workspaces/ai-provider-google-usage.js +39 -0
  297. package/dist/generated/commands/workspaces/ai-provider-login-antigravity-cancel.js +36 -0
  298. package/dist/generated/commands/workspaces/ai-provider-login-antigravity-complete.js +42 -0
  299. package/dist/generated/commands/workspaces/ai-provider-login-antigravity-start.js +30 -0
  300. package/dist/generated/commands/workspaces/ai-provider-logins-recheck.js +41 -0
  301. package/dist/generated/commands/workspaces/ai-provider-remove.js +57 -0
  302. package/dist/generated/commands/workspaces/ai-provider-set.js +21 -0
  303. package/dist/generated/commands/workspaces/ai-provider-token-usage.js +19 -0
  304. package/dist/generated/commands/workspaces/ai-provider-usage-claude.js +39 -0
  305. package/dist/generated/commands/workspaces/ai-provider-usage-codex.js +39 -0
  306. package/dist/generated/commands/workspaces/ai-provider-usage-coding-plan.js +32 -0
  307. package/dist/generated/commands/workspaces/ai-provider-usage-deepseek.js +32 -0
  308. package/dist/generated/commands/workspaces/ai-provider-usage-grok.js +39 -0
  309. package/dist/generated/commands/workspaces/ai-provider-usage-kimi-code.js +32 -0
  310. package/dist/generated/commands/workspaces/ai-provider-usage-muse.js +39 -0
  311. package/dist/generated/commands/workspaces/artifacts.js +26 -0
  312. package/dist/generated/commands/workspaces/credits.js +18 -0
  313. package/dist/generated/commands/workspaces/get.js +18 -0
  314. package/dist/generated/commands/workspaces/grok-change.js +21 -0
  315. package/dist/generated/commands/workspaces/grok-get.js +19 -0
  316. package/dist/generated/commands/workspaces/integrations-get.js +20 -0
  317. package/dist/generated/commands/workspaces/integrations-list.js +37 -0
  318. package/dist/generated/commands/workspaces/integrations-remove.js +19 -0
  319. package/dist/generated/commands/workspaces/list.js +16 -0
  320. package/dist/generated/commands/workspaces/members.js +26 -0
  321. package/dist/generated/commands/workspaces/plugins-list.js +30 -0
  322. package/dist/generated/commands/workspaces/plugins-update.js +30 -0
  323. package/dist/generated/commands/workspaces/provider-login-claude-complete.js +35 -0
  324. package/dist/generated/commands/workspaces/provider-login-claude-start.js +30 -0
  325. package/dist/generated/commands/workspaces/provider-login-codex-complete.js +29 -0
  326. package/dist/generated/commands/workspaces/provider-login-codex-start.js +30 -0
  327. package/dist/generated/commands/workspaces/provider-login-muse-complete.js +29 -0
  328. package/dist/generated/commands/workspaces/provider-login-muse-start.js +30 -0
  329. package/dist/generated/commands/workspaces/sandbox-limit.js +18 -0
  330. package/dist/generated/commands/workspaces/skills-create.js +35 -0
  331. package/dist/generated/commands/workspaces/skills-delete.js +19 -0
  332. package/dist/generated/commands/workspaces/skills-get.js +20 -0
  333. package/dist/generated/commands/workspaces/skills-list.js +19 -0
  334. package/dist/generated/commands/workspaces/skills-update.js +36 -0
  335. package/dist/generated/commands/workspaces/stop-sandboxes.js +28 -0
  336. package/dist/generated/commands/workspaces/timezone-set.js +29 -0
  337. package/dist/generated/commands/workspaces/usage.js +33 -0
  338. package/dist/generated/providers.js +31 -0
  339. package/dist/index.js +7 -0
  340. package/dist/integrations/api.js +136 -0
  341. package/dist/integrations/render.js +59 -0
  342. package/dist/program.js +73 -0
  343. package/dist/runtime/agent-tokens.js +39 -0
  344. package/dist/runtime/attach.js +199 -0
  345. package/dist/runtime/attachments.js +63 -0
  346. package/dist/runtime/client.js +188 -0
  347. package/dist/runtime/config.js +49 -0
  348. package/dist/runtime/credentials.js +32 -0
  349. package/dist/runtime/descriptor.js +7 -0
  350. package/dist/runtime/invoke.js +152 -0
  351. package/dist/runtime/job-watch.js +374 -0
  352. package/dist/runtime/runtime.js +46 -0
  353. package/dist/runtime/version.js +5 -0
  354. package/openapi.json +26313 -0
  355. package/package.json +46 -4
@@ -0,0 +1,310 @@
1
+ import { readFile } from 'node:fs/promises';
2
+ import { InvalidArgumentError } from 'commander';
3
+ import { groupFor } from '../runtime/attach.js';
4
+ import { isTurnToken } from '../runtime/credentials.js';
5
+ import { connectionOf, failureOf, isRow, oneLine, readOverview, rowsOf, TOOLS_PATH, transportFailure, } from '../integrations/api.js';
6
+ import { choiceLines, renderOverview } from '../integrations/render.js';
7
+ /**
8
+ * `kosuke integrations list|describe|call`: the connected tools, listed and run
9
+ * from a laptop or an agent's shell. Hand-written because the output is text
10
+ * and the exit code says whether the tool worked, which the generated
11
+ * `integrations tools` and `integrations execute` (raw JSON passthroughs, kept
12
+ * beside these) cannot do.
13
+ *
14
+ * Tool descriptions, schemas and results come from third-party services: they
15
+ * are printed, never acted on.
16
+ */
17
+ const EXECUTE_PATH = '/api/agent-integrations/execute';
18
+ const READ_TIMEOUT_MS = 30_000;
19
+ /**
20
+ * One value for every call: the execute route's `maxDuration`, the longest the platform lets
21
+ * one run. The platform decides from the tool and the account where a call runs, so the CLI cannot
22
+ * give the others a shorter wait. They end sooner on the platform's side, a Composio read at its
23
+ * 60 s budget, and wait no longer than their answer takes.
24
+ */
25
+ const CALL_TIMEOUT_MS = 330_000;
26
+ const EXIT_FAILED = 1;
27
+ const EXIT_USAGE = 2;
28
+ const TOOLKIT_PATTERN = /^[a-z0-9_]{1,64}$/;
29
+ const MAX_SEARCH_CHARS = 100;
30
+ const MAX_ACCOUNT_CHARS = 100;
31
+ /** Wrong flags or arguments, found before any request. */
32
+ class UsageError extends Error {
33
+ }
34
+ async function readAllStdin() {
35
+ const chunks = [];
36
+ for await (const chunk of process.stdin)
37
+ chunks.push(Buffer.from(chunk));
38
+ return Buffer.concat(chunks).toString('utf8');
39
+ }
40
+ function toolkitSlug(raw) {
41
+ if (!TOOLKIT_PATTERN.test(raw)) {
42
+ throw new InvalidArgumentError('Expected a toolkit slug such as gmail, as `list` prints it.');
43
+ }
44
+ return raw;
45
+ }
46
+ function searchText(raw) {
47
+ if (raw.trim() === '' || raw.length > MAX_SEARCH_CHARS) {
48
+ throw new InvalidArgumentError(`Expected 1 to ${MAX_SEARCH_CHARS} characters.`);
49
+ }
50
+ return raw;
51
+ }
52
+ function accountText(raw) {
53
+ // A flag swallowed as the value (`--account --args`) shows as a leading dash.
54
+ if (raw.trim() === '' || raw.startsWith('-') || raw.length > MAX_ACCOUNT_CHARS) {
55
+ throw new InvalidArgumentError(`Expected an alias, a connection id or scope:label, up to ${MAX_ACCOUNT_CHARS} characters.`);
56
+ }
57
+ return raw;
58
+ }
59
+ function limitNumber(raw) {
60
+ if (!/^\d+$/.test(raw) || Number(raw) < 1 || Number(raw) > 100) {
61
+ throw new InvalidArgumentError('Expected a whole number from 1 to 100.');
62
+ }
63
+ return Number(raw);
64
+ }
65
+ const WORKSPACE_HELP = 'The workspace to use. Required with an API key, which is refused when you are not a member of it. ' +
66
+ 'Inside an agent turn the credential decides, and this is optional.';
67
+ /** A turn's token decides its workspace; a member's API key has to name one. */
68
+ function workspaceFor(runtime, given) {
69
+ if (given)
70
+ return given;
71
+ if (isTurnToken(runtime.credentials().apiKey))
72
+ return undefined;
73
+ throw new UsageError('--workspace <id> is required with an API key. `kosuke workspaces list` shows the ids.');
74
+ }
75
+ /** The 409 that asks for `--account`: its choices, one per line. */
76
+ function accountChoiceText(error, tool, given) {
77
+ if (!isRow(error))
78
+ return null;
79
+ const choices = rowsOf(isRow(error.details) ? error.details.choices : []).flatMap((row) => connectionOf(row) ?? []);
80
+ if (choices.length === 0)
81
+ return null;
82
+ return choicesSentence(error.code === 'INTEGRATION_INVALID_ACCOUNT', tool, given, choices);
83
+ }
84
+ function choicesSentence(invalid, tool, given, choices) {
85
+ const head = invalid
86
+ ? `No single account matches --account "${oneLine(given ?? '', 60)}". The accounts are:`
87
+ : `More than one account can run ${tool}. Pass --account with one of:`;
88
+ return `${head}\n${choiceLines(choices)}`;
89
+ }
90
+ /**
91
+ * The executor answers a tool failure as text. Its own refusals are
92
+ * `{"error": code, "message": sentence}`, shown as the sentence; anything else
93
+ * (a vendor's words included) is printed as received.
94
+ */
95
+ function failureText(text, choices, tool, given) {
96
+ let body;
97
+ try {
98
+ body = JSON.parse(text);
99
+ }
100
+ catch {
101
+ return text;
102
+ }
103
+ if (!isRow(body) || typeof body.message !== 'string' || typeof body.error !== 'string') {
104
+ return text;
105
+ }
106
+ if (body.error === 'account_required' || body.error === 'invalid_account') {
107
+ return choices.length > 0
108
+ ? choicesSentence(body.error === 'invalid_account', tool, given, choices)
109
+ : body.message.replace(/\bPass account\b/, 'Pass --account');
110
+ }
111
+ return body.message;
112
+ }
113
+ export function attachIntegrationsCommands(root, runtime, deps = {}) {
114
+ const { stdout = (text) => process.stdout.write(text), stderr = (text) => process.stderr.write(text), exit = (code) => {
115
+ process.exitCode = code;
116
+ }, readStdin = readAllStdin, readFile: readText = (path) => readFile(path, 'utf8'), readTimeoutMs = READ_TIMEOUT_MS, callTimeoutMs = CALL_TIMEOUT_MS, } = deps;
117
+ const fail = (failure, code = EXIT_FAILED) => {
118
+ stderr(`${typeof failure === 'string' ? failure : failure.message}\n`);
119
+ exit(code);
120
+ };
121
+ /** Runs one command; a usage error is reported and exits 2. */
122
+ const guarded = (run) => async (...args) => {
123
+ try {
124
+ await run(...args);
125
+ }
126
+ catch (error) {
127
+ if (!(error instanceof UsageError))
128
+ throw error;
129
+ fail(error.message, EXIT_USAGE);
130
+ }
131
+ };
132
+ const group = groupFor(root, ['integrations']);
133
+ group
134
+ .command('list')
135
+ .description('List the connected tools. With no filter, one block per toolkit: its connections (alias, ' +
136
+ 'scope, label, account, id) and how many read-only and write tools it has. --toolkit and ' +
137
+ '--search list the matching tools. A cut list says "N of M" and how to narrow it.')
138
+ .option('--toolkit <slug>', 'Only this toolkit, such as gmail.', toolkitSlug)
139
+ .option('--search <text>', 'Only tools whose name or description mention the text.', searchText)
140
+ .option('--account <account>', 'Only what one connection offers: an alias, id or scope:label.', accountText)
141
+ .option('--limit <n>', 'How many tools to list with --toolkit or --search. Default 40, at most 100.', limitNumber)
142
+ .option('--workspace <id>', WORKSPACE_HELP)
143
+ .option('--json', "Print the platform's answer as JSON.")
144
+ .addHelpText('after', '\nExit codes:\n 0 ok\n 1 the platform refused or could not answer\n 2 --workspace missing with an API key')
145
+ .action(guarded(async (flags) => {
146
+ const client = runtime.client();
147
+ const workspace = workspaceFor(runtime, flags.workspace);
148
+ const result = await readOverview(client, {
149
+ ...(workspace ? { workspace } : {}),
150
+ ...(flags.toolkit ? { toolkit: flags.toolkit } : {}),
151
+ ...(flags.search ? { search: flags.search } : {}),
152
+ ...(flags.account ? { account: flags.account } : {}),
153
+ ...(flags.limit ? { limit: flags.limit } : {}),
154
+ }, AbortSignal.timeout(readTimeoutMs));
155
+ if (!result.ok)
156
+ return fail(result);
157
+ if (flags.json) {
158
+ stdout(`${JSON.stringify(result.raw, null, 2)}\n`);
159
+ // stdout stays parseable, so the cut is told beside it.
160
+ if (result.overview.note)
161
+ stderr(`${result.overview.note}\n`);
162
+ return;
163
+ }
164
+ stdout(renderOverview(result.overview, Boolean(flags.toolkit || flags.search)));
165
+ }));
166
+ group
167
+ .command('describe')
168
+ .description("Print one tool's input schema and annotations as JSON.")
169
+ .argument('<name>', 'The tool, as `list` prints it.')
170
+ .option('--account <account>', 'The connection whose schema you want: an alias, id or scope:label. Needed when several can run the tool.', accountText)
171
+ .option('--workspace <id>', WORKSPACE_HELP)
172
+ .addHelpText('after', '\nExit codes:\n 0 ok\n 1 no such tool, a connection has to be named, or the platform refused\n 2 --workspace missing with an API key')
173
+ .action(guarded(async (name, flags) => {
174
+ const client = runtime.client();
175
+ const workspace = workspaceFor(runtime, flags.workspace);
176
+ try {
177
+ const { data, error, response } = await client.GET(TOOLS_PATH, {
178
+ params: {
179
+ query: {
180
+ name,
181
+ ...(flags.account ? { account: flags.account } : {}),
182
+ ...(workspace ? { workspace } : {}),
183
+ },
184
+ },
185
+ signal: AbortSignal.timeout(readTimeoutMs),
186
+ });
187
+ if (response.status === 404) {
188
+ return fail(`No connected tool is named ${oneLine(name, 80)}${flags.account ? ' for that account' : ''}. ` +
189
+ 'Run `kosuke integrations list` to see them.');
190
+ }
191
+ if (response.status === 409) {
192
+ const choices = accountChoiceText(error, oneLine(name, 80), flags.account);
193
+ if (choices)
194
+ return fail(choices);
195
+ }
196
+ if (!response.ok)
197
+ return fail(failureOf(response.status, error, 'GET'));
198
+ const tools = rowsOf(isRow(data) && isRow(data.data) ? data.data.tools : []);
199
+ // Matched here too: a platform that ignores `name` answers with every tool.
200
+ const tool = tools.find((entry) => typeof entry.name === 'string' && entry.name.toLowerCase() === name.toLowerCase());
201
+ if (!tool) {
202
+ return fail(`No connected tool is named ${oneLine(name, 80)}. Run \`kosuke integrations list\` to see them.`);
203
+ }
204
+ const { description, inputSchema, annotations } = tool;
205
+ stdout(`${JSON.stringify({ name: tool.name, description, inputSchema, annotations }, null, 2)}\n`);
206
+ }
207
+ catch (error) {
208
+ fail(transportFailure(error, 'GET'));
209
+ }
210
+ }));
211
+ group
212
+ .command('call')
213
+ .description('Run a tool with a JSON object of arguments and print its text result. The connection it ' +
214
+ 'ran on is named on stderr. A tool that reports an error exits 1.')
215
+ .argument('<name>', 'The tool, as `list` prints it.')
216
+ .argument('[stdin]', 'A lone - reads the JSON arguments from stdin.')
217
+ .option('--account <account>', 'The connection to run on: an alias, id or scope:label. Needed when several can run the tool.', accountText)
218
+ .option('--args <json>', 'The tool arguments, a JSON object. Default {}.')
219
+ .option('--args-file <path>', 'Read the arguments from a file, or - for stdin.')
220
+ .option('--workspace <id>', WORKSPACE_HELP)
221
+ .addHelpText('after', '\nWith an API key, a call runs only on your own personal connections; one on a workspace\n' +
222
+ "connection is refused (an agent's turn in the workspace can run it).\n" +
223
+ `\nA call waits up to ${CALL_TIMEOUT_MS / 1000} s for its answer, as long as the platform lets one run.\n` +
224
+ 'A call that gets no answer is never sent again: its outcome is unknown.\n' +
225
+ '\nExit codes:\n 0 the tool ran\n 1 the tool or the platform reported an error, or the outcome of a write is unknown\n 2 usage error: --workspace missing, or arguments that are not a JSON object')
226
+ .action(guarded(async (name, dash, flags) => {
227
+ const toolArguments = await readArguments(flags, dash);
228
+ const client = runtime.client({ answerTimeoutMs: callTimeoutMs });
229
+ const workspace = workspaceFor(runtime, flags.workspace);
230
+ let data;
231
+ try {
232
+ const result = await client.POST(EXECUTE_PATH, {
233
+ params: { query: workspace ? { workspace } : {} },
234
+ body: {
235
+ name,
236
+ arguments: toolArguments,
237
+ ...(flags.account ? { account: flags.account } : {}),
238
+ },
239
+ signal: AbortSignal.timeout(callTimeoutMs),
240
+ });
241
+ if (!result.response.ok) {
242
+ return fail(failureOf(result.response.status, result.error, 'POST'));
243
+ }
244
+ data = isRow(result.data) ? result.data.data : undefined;
245
+ }
246
+ catch (error) {
247
+ return fail(transportFailure(error, 'POST'));
248
+ }
249
+ report(name, flags.account, data);
250
+ }));
251
+ /** Reads `--args`, `--args-file` or a lone `-`: one source at most, and a JSON object. */
252
+ async function readArguments(flags, dash) {
253
+ if (dash !== undefined && dash !== '-')
254
+ throw new UsageError(`Unexpected argument: ${dash}`);
255
+ const fromStdin = dash === '-' || flags.argsFile === '-';
256
+ // Each flag and the positional `-` is its own source, even when two of them name stdin.
257
+ const sources = [flags.args !== undefined, flags.argsFile !== undefined, dash === '-'];
258
+ if (sources.filter(Boolean).length > 1)
259
+ throw new UsageError('Give the arguments one way only.');
260
+ if (!sources.includes(true))
261
+ return {};
262
+ let text;
263
+ if (flags.args !== undefined)
264
+ text = flags.args;
265
+ else if (fromStdin)
266
+ text = await readStdin();
267
+ else {
268
+ try {
269
+ text = await readText(flags.argsFile);
270
+ }
271
+ catch {
272
+ throw new UsageError(`Could not read the arguments file ${flags.argsFile}.`);
273
+ }
274
+ }
275
+ let parsed;
276
+ try {
277
+ parsed = JSON.parse(text);
278
+ }
279
+ catch {
280
+ throw new UsageError('The arguments are not valid JSON.');
281
+ }
282
+ if (!isRow(parsed))
283
+ throw new UsageError('The arguments must be a JSON object.');
284
+ return parsed;
285
+ }
286
+ /** The tool's text on stdout; which connection ran it, and any failure, on stderr. */
287
+ function report(name, account, data) {
288
+ const answer = isRow(data) ? data : {};
289
+ const content = rowsOf(answer.content);
290
+ if (content.length === 0 && !Array.isArray(answer.content)) {
291
+ return fail('Integration tools returned an unexpected response.');
292
+ }
293
+ const text = content
294
+ .map((block) => (typeof block.text === 'string' ? block.text : ''))
295
+ .join('\n');
296
+ const connection = isRow(answer.connection) ? connectionOf(answer.connection) : null;
297
+ // The alias may name a different connection tomorrow, so every call says which one it ran on.
298
+ if (connection) {
299
+ const identity = connection.accountIdentity ?? 'account unknown';
300
+ stderr(`Ran on ${connection.alias} (${connection.scope}, "${connection.label}", ${identity}).\n`);
301
+ }
302
+ if (answer.isError === true) {
303
+ const choices = rowsOf(answer.choices).flatMap((row) => connectionOf(row) ?? []);
304
+ const message = failureText(text, choices, oneLine(name, 80), account);
305
+ fail(message.endsWith('\n') ? message.slice(0, -1) : message);
306
+ return;
307
+ }
308
+ stdout(text.endsWith('\n') || text === '' ? text : `${text}\n`);
309
+ }
310
+ }
@@ -0,0 +1,230 @@
1
+ import { randomUUID } from 'node:crypto';
2
+ import { appendFile, lstat, readFile } from 'node:fs/promises';
3
+ import { isAbsolute } from 'node:path';
4
+ import { agentTokenOf } from '../runtime/agent-tokens.js';
5
+ const FLAGS = new Set([
6
+ '--fix',
7
+ '--sync',
8
+ '--no-review',
9
+ '--restart',
10
+ '--ready',
11
+ '-d',
12
+ '--draft',
13
+ '--target-branch',
14
+ '-r',
15
+ '--reviewers',
16
+ '-e',
17
+ '--evidence',
18
+ ]);
19
+ const RESULTS = new Set([
20
+ 'passed',
21
+ 'failed',
22
+ 'blocked',
23
+ 'skipped',
24
+ 'prototype',
25
+ 'question',
26
+ 'ready',
27
+ 'cancelled',
28
+ 'open_items',
29
+ ]);
30
+ const UUID = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
31
+ const DEADLINE_MS = 1500;
32
+ async function appendMarker(path, value) {
33
+ try {
34
+ const stat = await lstat(path).catch(() => null);
35
+ if (stat && (!stat.isFile() || stat.size > 512 * 1024))
36
+ return;
37
+ await appendFile(path, JSON.stringify(value) + '\n', { mode: 0o600 });
38
+ }
39
+ catch {
40
+ // A bridge failure must not stop the server from recording the marker.
41
+ }
42
+ }
43
+ async function identity(env) {
44
+ const projectId = env.KOSUKE_PROJECT_ID;
45
+ const sessionId = env.KOSUKE_SESSION_ID ?? env.KOSUKE_SANDBOX_KEY;
46
+ if (projectId && sessionId && UUID.test(projectId) && UUID.test(sessionId))
47
+ return { projectId, sessionId };
48
+ try {
49
+ const session = JSON.parse(await readFile('/tmp/kosuke-session.json', 'utf8'));
50
+ return typeof session.projectId === 'string' &&
51
+ UUID.test(session.projectId) &&
52
+ typeof session.sandboxKey === 'string' &&
53
+ UUID.test(session.sandboxKey)
54
+ ? { projectId: session.projectId, sessionId: session.sandboxKey }
55
+ : null;
56
+ }
57
+ catch {
58
+ return null;
59
+ }
60
+ }
61
+ async function receiptData(response) {
62
+ const reader = response.body?.getReader();
63
+ if (!reader)
64
+ return null;
65
+ let size = 0;
66
+ const chunks = [];
67
+ try {
68
+ for (;;) {
69
+ const { done, value } = await reader.read();
70
+ if (done)
71
+ break;
72
+ size += value.byteLength;
73
+ if (size > 8192)
74
+ return null;
75
+ chunks.push(value);
76
+ }
77
+ const parsed = JSON.parse(Buffer.concat(chunks).toString('utf8'));
78
+ if (!parsed || typeof parsed !== 'object' || !('data' in parsed))
79
+ return null;
80
+ const data = parsed.data;
81
+ return data !== null && typeof data === 'object' ? data : null;
82
+ }
83
+ finally {
84
+ await reader.cancel().catch(() => undefined);
85
+ }
86
+ }
87
+ /** Marker errors bypass Commander and the shared retrying client so they cannot stop agent work. */
88
+ export async function runSkillMarkerCommand(args, options = {}) {
89
+ if (args[0] !== 'sessions' || args[1] !== 'skill-runs')
90
+ return false;
91
+ const { env = process.env, fetch: request = globalThis.fetch, stdout = (text) => process.stdout.write(text), timeoutMs = DEADLINE_MS, } = options;
92
+ if (args.length === 3 && args[2] === '--capabilities') {
93
+ stdout('skill-markers-v1\n');
94
+ return true;
95
+ }
96
+ if (args.includes('--help') || args.includes('-h')) {
97
+ stdout('kosuke sessions skill-runs start <name> [--fix] [--sync] [--no-review]\nkosuke sessions skill-runs end <name> [--result <verdict>]\nBest effort: one request, 1.5-second deadline, always exits 0.\n');
98
+ return true;
99
+ }
100
+ const [, , action, rawName, ...rest] = args;
101
+ if ((action !== 'start' && action !== 'end') ||
102
+ !rawName ||
103
+ !/^(?:kosuke:)?[a-z][a-z0-9-]{0,79}$/.test(rawName))
104
+ return true;
105
+ const flags = [];
106
+ let result;
107
+ for (let index = 0; index < rest.length; index++) {
108
+ const value = rest[index];
109
+ if (value === '--result' && action === 'end' && result === undefined) {
110
+ result = rest[++index];
111
+ if (!result || !RESULTS.has(result))
112
+ return true;
113
+ }
114
+ else if (FLAGS.has(value)) {
115
+ if (!flags.includes(value))
116
+ flags.push(value);
117
+ }
118
+ else
119
+ return true;
120
+ }
121
+ const bridge = env.KOSUKE_SKILL_MARKER_FILE;
122
+ const clockId = env.KOSUKE_SKILL_CLOCK_ID;
123
+ if (!bridge ||
124
+ !isAbsolute(bridge) ||
125
+ !clockId ||
126
+ !UUID.test(clockId) ||
127
+ agentTokenOf(env.KOSUKE_API_KEY) !== 'sandboxToken' ||
128
+ !env.KOSUKE_API_URL)
129
+ return true;
130
+ const controller = new AbortController();
131
+ const budget = Math.max(1, Math.min(timeoutMs, DEADLINE_MS));
132
+ const requestTimer = setTimeout(() => controller.abort(), Math.max(1, budget - Math.min(100, budget / 2)));
133
+ let timer;
134
+ const deadline = new Promise((resolve) => {
135
+ timer = setTimeout(() => {
136
+ controller.abort();
137
+ resolve();
138
+ }, budget);
139
+ });
140
+ const operation = async () => {
141
+ const ids = await identity(env);
142
+ if (!ids || controller.signal.aborted)
143
+ return;
144
+ const marker = {
145
+ markerId: randomUUID(),
146
+ action,
147
+ name: rawName.startsWith('kosuke:') ? rawName : `kosuke:${rawName}`,
148
+ at: new Date().toISOString(),
149
+ monotonicMs: Number(process.hrtime.bigint()) / 1e6,
150
+ clockId,
151
+ ...(flags.length ? { flags } : {}),
152
+ ...(result ? { result } : {}),
153
+ };
154
+ await appendMarker(bridge, { kind: 'marker', ...marker });
155
+ if (controller.signal.aborted)
156
+ return;
157
+ let status = 'unknown';
158
+ let accepted = null;
159
+ try {
160
+ const response = await request(`${env.KOSUKE_API_URL.replace(/\/+$/, '')}/api/projects/${ids.projectId}/chat-sessions/${ids.sessionId}/skill-runs`, {
161
+ method: 'POST',
162
+ headers: {
163
+ authorization: `Bearer ${env.KOSUKE_API_KEY}`,
164
+ 'content-type': 'application/json',
165
+ },
166
+ body: JSON.stringify(marker),
167
+ signal: controller.signal,
168
+ redirect: 'error',
169
+ });
170
+ if (response.ok) {
171
+ accepted = await receiptData(response);
172
+ if (accepted?.accepted === true && accepted.markerId === marker.markerId)
173
+ status = 'accepted';
174
+ }
175
+ else {
176
+ status = 'rejected';
177
+ await response.body?.cancel();
178
+ }
179
+ }
180
+ catch {
181
+ /* A lost response does not prove the server rejected the marker. */
182
+ }
183
+ await appendMarker(bridge, {
184
+ kind: 'receipt',
185
+ markerId: marker.markerId,
186
+ status,
187
+ ...(status === 'accepted' &&
188
+ (accepted?.invocationId === null ||
189
+ (typeof accepted?.invocationId === 'string' && UUID.test(accepted.invocationId)))
190
+ ? { invocationId: accepted.invocationId }
191
+ : {}),
192
+ ...(status === 'accepted' && typeof accepted?.noop === 'boolean'
193
+ ? { noop: accepted.noop }
194
+ : {}),
195
+ });
196
+ };
197
+ try {
198
+ await Promise.race([operation().catch(() => undefined), deadline]);
199
+ }
200
+ finally {
201
+ clearTimeout(requestTimer);
202
+ if (timer)
203
+ clearTimeout(timer);
204
+ }
205
+ return true;
206
+ }
207
+ export function attachSkillMarkerCommands(program, options = {}) {
208
+ const sessions = program.commands.find((command) => command.name() === 'sessions') ??
209
+ program.command('sessions');
210
+ const skills = sessions.commands.find((command) => command.name() === 'skill-runs') ??
211
+ sessions.command('skill-runs');
212
+ skills
213
+ .description('Record best-effort Factory Skill start and end markers.')
214
+ .option('--capabilities', 'Print marker command capability.')
215
+ .action(async () => {
216
+ await runSkillMarkerCommand(['sessions', 'skill-runs', '--capabilities'], options);
217
+ });
218
+ for (const action of ['start', 'end']) {
219
+ const command = skills
220
+ .command(`${action} <name>`)
221
+ .description(`${action === 'start' ? 'Start' : 'End'} a Factory Skill in this sandbox Turn.`);
222
+ for (const flag of FLAGS)
223
+ command.option(flag);
224
+ if (action === 'end')
225
+ command.option('--result <verdict>', 'A known result, such as passed, failed, blocked, or ready.');
226
+ command.action(async (_name, _flags, cmd) => {
227
+ await runSkillMarkerCommand(cmd.parent.parent.parent.args, options);
228
+ });
229
+ }
230
+ }