@skrr-ai/cli 0.1.109 → 0.1.111

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 (434) hide show
  1. package/bin/run.js +15 -1
  2. package/dist/base-command.d.ts +44 -1
  3. package/dist/base-command.js +194 -33
  4. package/dist/commands/actions/list.js +2 -1
  5. package/dist/commands/agenda/trigger/create.js +1 -1
  6. package/dist/commands/agenda/trigger/list.js +2 -1
  7. package/dist/commands/agent-groups/list.js +2 -1
  8. package/dist/commands/agents/actions/list.js +2 -1
  9. package/dist/commands/agents/always-on/status.js +5 -0
  10. package/dist/commands/agents/chat.js +4 -1
  11. package/dist/commands/agents/duplicate.js +4 -0
  12. package/dist/commands/agents/eval/list.js +2 -1
  13. package/dist/commands/agents/files/list.js +2 -1
  14. package/dist/commands/agents/folders/list.js +2 -1
  15. package/dist/commands/agents/goals/list.js +2 -1
  16. package/dist/commands/agents/intuitions/list.js +8 -5
  17. package/dist/commands/agents/list.d.ts +12 -0
  18. package/dist/commands/agents/list.js +45 -8
  19. package/dist/commands/agents/releases/known-issues/list.js +2 -1
  20. package/dist/commands/agents/releases/list.js +5 -1
  21. package/dist/commands/agents/releases/trusted-publishers/list.js +2 -1
  22. package/dist/commands/agents/roles/list.js +2 -1
  23. package/dist/commands/agents/skills/list.js +2 -1
  24. package/dist/commands/agents/todos/list.js +2 -1
  25. package/dist/commands/agents/triggers/create.js +1 -1
  26. package/dist/commands/agents/triggers/list.js +2 -1
  27. package/dist/commands/agents/triggers/update.js +1 -1
  28. package/dist/commands/agents/update.d.ts +11 -0
  29. package/dist/commands/agents/update.js +58 -2
  30. package/dist/commands/api-keys/list.js +2 -1
  31. package/dist/commands/apps/channel.d.ts +20 -0
  32. package/dist/commands/apps/channel.js +64 -0
  33. package/dist/commands/apps/check-draft.d.ts +12 -0
  34. package/dist/commands/apps/check-draft.js +41 -0
  35. package/dist/commands/apps/check.d.ts +42 -0
  36. package/dist/commands/apps/check.js +91 -0
  37. package/dist/commands/apps/create.d.ts +15 -0
  38. package/dist/commands/apps/create.js +59 -0
  39. package/dist/commands/apps/data/put.d.ts +18 -0
  40. package/dist/commands/apps/data/put.js +72 -0
  41. package/dist/commands/apps/data/query.d.ts +20 -0
  42. package/dist/commands/apps/data/query.js +88 -0
  43. package/dist/commands/apps/disclosure.d.ts +16 -0
  44. package/dist/commands/apps/disclosure.js +71 -0
  45. package/dist/commands/apps/file/cat.d.ts +15 -0
  46. package/dist/commands/apps/file/cat.js +50 -0
  47. package/dist/commands/apps/file/ls.d.ts +13 -0
  48. package/dist/commands/apps/file/ls.js +47 -0
  49. package/dist/commands/apps/file/mv.d.ts +15 -0
  50. package/dist/commands/apps/file/mv.js +49 -0
  51. package/dist/commands/apps/file/rm.d.ts +15 -0
  52. package/dist/commands/apps/file/rm.js +53 -0
  53. package/dist/commands/apps/file/write.d.ts +17 -0
  54. package/dist/commands/apps/file/write.js +81 -0
  55. package/dist/commands/apps/install.d.ts +19 -0
  56. package/dist/commands/apps/install.js +136 -0
  57. package/dist/commands/apps/installations/list.d.ts +11 -0
  58. package/dist/commands/apps/installations/list.js +49 -0
  59. package/dist/commands/apps/installations/show.d.ts +12 -0
  60. package/dist/commands/apps/installations/show.js +61 -0
  61. package/dist/commands/apps/layout/set.d.ts +11 -0
  62. package/dist/commands/apps/layout/set.js +125 -0
  63. package/dist/commands/apps/layout/show.d.ts +9 -0
  64. package/dist/commands/apps/layout/show.js +33 -0
  65. package/dist/commands/apps/list.d.ts +10 -0
  66. package/dist/commands/apps/list.js +45 -0
  67. package/dist/commands/apps/logs.d.ts +13 -0
  68. package/dist/commands/apps/logs.js +55 -0
  69. package/dist/commands/apps/preview.d.ts +12 -0
  70. package/dist/commands/apps/preview.js +39 -0
  71. package/dist/commands/apps/publish/propose.d.ts +14 -0
  72. package/dist/commands/apps/publish/propose.js +45 -0
  73. package/dist/commands/apps/pull.d.ts +14 -0
  74. package/dist/commands/apps/pull.js +56 -0
  75. package/dist/commands/apps/push.d.ts +15 -0
  76. package/dist/commands/apps/push.js +75 -0
  77. package/dist/commands/apps/reconsent.d.ts +13 -0
  78. package/dist/commands/apps/reconsent.js +67 -0
  79. package/dist/commands/apps/report.d.ts +20 -0
  80. package/dist/commands/apps/report.js +63 -0
  81. package/dist/commands/apps/resume.d.ts +12 -0
  82. package/dist/commands/apps/resume.js +36 -0
  83. package/dist/commands/apps/settings/set.d.ts +13 -0
  84. package/dist/commands/apps/settings/set.js +54 -0
  85. package/dist/commands/apps/settings/show.d.ts +11 -0
  86. package/dist/commands/apps/settings/show.js +31 -0
  87. package/dist/commands/apps/show.d.ts +12 -0
  88. package/dist/commands/apps/show.js +49 -0
  89. package/dist/commands/apps/suspend.d.ts +12 -0
  90. package/dist/commands/apps/suspend.js +35 -0
  91. package/dist/commands/apps/uninstall.d.ts +13 -0
  92. package/dist/commands/apps/uninstall.js +43 -0
  93. package/dist/commands/apps/upgrade.d.ts +14 -0
  94. package/dist/commands/apps/upgrade.js +49 -0
  95. package/dist/commands/apps/version/create.d.ts +14 -0
  96. package/dist/commands/apps/version/create.js +53 -0
  97. package/dist/commands/apps/version/show.d.ts +12 -0
  98. package/dist/commands/apps/version/show.js +39 -0
  99. package/dist/commands/apps/versions.d.ts +12 -0
  100. package/dist/commands/apps/versions.js +40 -0
  101. package/dist/commands/apps/webhooks/list.d.ts +12 -0
  102. package/dist/commands/apps/webhooks/list.js +47 -0
  103. package/dist/commands/characters/list.js +2 -1
  104. package/dist/commands/chats/files/list.js +2 -1
  105. package/dist/commands/chats/folders/list.js +2 -1
  106. package/dist/commands/chats/list.js +2 -1
  107. package/dist/commands/chats/spaces/list.js +2 -1
  108. package/dist/commands/chats/widgets/list.js +2 -1
  109. package/dist/commands/code/jobs/list.js +4 -1
  110. package/dist/commands/commerce/incidents/list.js +2 -1
  111. package/dist/commands/commitments/accounting.js +3 -0
  112. package/dist/commands/commitments/action-proposals.d.ts +8 -0
  113. package/dist/commands/commitments/action-proposals.js +17 -2
  114. package/dist/commands/commitments/cost.d.ts +11 -0
  115. package/dist/commands/commitments/cost.js +25 -0
  116. package/dist/commands/commitments/create.js +6 -1
  117. package/dist/commands/commitments/endpoints/list.js +2 -1
  118. package/dist/commands/commitments/links/list.js +2 -1
  119. package/dist/commands/commitments/list.js +2 -1
  120. package/dist/commands/commitments/liveness.d.ts +30 -0
  121. package/dist/commands/commitments/liveness.js +22 -5
  122. package/dist/commands/commitments/pack/list.js +2 -1
  123. package/dist/commands/commitments/preflight.js +6 -2
  124. package/dist/commands/commitments/update.js +10 -1
  125. package/dist/commands/compass/list.js +2 -1
  126. package/dist/commands/context.js +7 -1
  127. package/dist/commands/convos/list.js +3 -2
  128. package/dist/commands/daemon/install.js +17 -1
  129. package/dist/commands/daemon/login.js +14 -0
  130. package/dist/commands/dm/list.js +2 -1
  131. package/dist/commands/dm/work.d.ts +19 -0
  132. package/dist/commands/dm/work.js +54 -0
  133. package/dist/commands/feeds/list.js +2 -1
  134. package/dist/commands/followups/list.js +2 -1
  135. package/dist/commands/followups/plans/cancel.d.ts +13 -0
  136. package/dist/commands/followups/plans/cancel.js +26 -0
  137. package/dist/commands/followups/plans/create.d.ts +11 -0
  138. package/dist/commands/followups/plans/create.js +35 -0
  139. package/dist/commands/followups/plans/list.d.ts +13 -0
  140. package/dist/commands/followups/plans/list.js +50 -0
  141. package/dist/commands/followups/plans/observability.d.ts +11 -0
  142. package/dist/commands/followups/plans/observability.js +46 -0
  143. package/dist/commands/followups/plans/revise.d.ts +13 -0
  144. package/dist/commands/followups/plans/revise.js +35 -0
  145. package/dist/commands/followups/plans/show.d.ts +11 -0
  146. package/dist/commands/followups/plans/show.js +32 -0
  147. package/dist/commands/goals/key-results/list.js +2 -1
  148. package/dist/commands/goals/labels/list.js +3 -2
  149. package/dist/commands/goals/list.js +3 -2
  150. package/dist/commands/grants/list.js +2 -1
  151. package/dist/commands/harnesses/grants/list.js +2 -1
  152. package/dist/commands/harnesses/leases/list.js +2 -1
  153. package/dist/commands/harnesses/list.js +10 -1
  154. package/dist/commands/harnesses/prune.d.ts +26 -0
  155. package/dist/commands/harnesses/prune.js +172 -0
  156. package/dist/commands/ingress/list.js +2 -1
  157. package/dist/commands/initiatives/list.js +2 -1
  158. package/dist/commands/instruction-blocks/list.js +2 -1
  159. package/dist/commands/instructions/list.js +2 -1
  160. package/dist/commands/integrations/connections/list.js +2 -1
  161. package/dist/commands/integrations/tools/list.js +2 -1
  162. package/dist/commands/labels/list.js +3 -2
  163. package/dist/commands/learning/adapters.d.ts +16 -0
  164. package/dist/commands/learning/adapters.js +44 -0
  165. package/dist/commands/login.js +11 -0
  166. package/dist/commands/machines/dedicated/list.js +2 -1
  167. package/dist/commands/machines/hosted/list.js +2 -1
  168. package/dist/commands/machines/list.js +2 -1
  169. package/dist/commands/machines/show.js +5 -2
  170. package/dist/commands/measures/list.js +2 -1
  171. package/dist/commands/memory/list.js +2 -1
  172. package/dist/commands/memory/proposals/list.js +2 -1
  173. package/dist/commands/memory/stores/list.js +2 -1
  174. package/dist/commands/memory/topics/list.js +2 -1
  175. package/dist/commands/memory/versions/list.js +2 -1
  176. package/dist/commands/messages/list.js +2 -1
  177. package/dist/commands/northstars/intents/list.js +2 -1
  178. package/dist/commands/northstars/list.js +2 -1
  179. package/dist/commands/northstars/recommendations/list.js +2 -1
  180. package/dist/commands/outbox/list.js +2 -1
  181. package/dist/commands/profiles/list.js +2 -1
  182. package/dist/commands/projects/docs/list.js +8 -1
  183. package/dist/commands/projects/updates/list.js +2 -1
  184. package/dist/commands/proposals/list.js +2 -1
  185. package/dist/commands/requests/comments/list.js +2 -1
  186. package/dist/commands/requests/list.js +2 -1
  187. package/dist/commands/shares/list.js +2 -1
  188. package/dist/commands/shortcuts/list.js +2 -1
  189. package/dist/commands/signals/monitors/list.js +2 -1
  190. package/dist/commands/signals/schemas/list.js +2 -1
  191. package/dist/commands/signals/sources/list.js +2 -1
  192. package/dist/commands/space-directory-views/list.js +2 -1
  193. package/dist/commands/spaces/actions/list.js +4 -3
  194. package/dist/commands/spaces/briefs/list.js +2 -1
  195. package/dist/commands/spaces/cycles/list.js +2 -1
  196. package/dist/commands/spaces/files/folders/list.js +2 -1
  197. package/dist/commands/spaces/files/list.js +3 -2
  198. package/dist/commands/spaces/heartbeats/list.js +3 -2
  199. package/dist/commands/spaces/labels/list.js +3 -2
  200. package/dist/commands/spaces/list.d.ts +3 -18
  201. package/dist/commands/spaces/list.js +28 -35
  202. package/dist/commands/spaces/live/cards/list.js +2 -1
  203. package/dist/commands/spaces/members/list.d.ts +1 -0
  204. package/dist/commands/spaces/members/list.js +4 -1
  205. package/dist/commands/spaces/show.js +2 -2
  206. package/dist/commands/spaces/skills/list.js +6 -2
  207. package/dist/commands/spaces/states/list.js +2 -1
  208. package/dist/commands/spaces/views/list.js +2 -1
  209. package/dist/commands/spaces/widgets/list.js +3 -2
  210. package/dist/commands/spaces/workflow-templates/list.js +2 -1
  211. package/dist/commands/spaces/workflows/fixtures/list.js +2 -1
  212. package/dist/commands/spaces/workflows/list.js +3 -2
  213. package/dist/commands/spaces/workflows/proposals/list.js +2 -1
  214. package/dist/commands/spaces/workflows/start.js +3 -1
  215. package/dist/commands/spaces/workflows/triggers/list.js +2 -1
  216. package/dist/commands/spaces/workflows/validate.js +12 -2
  217. package/dist/commands/store/acquisitions/list.js +2 -1
  218. package/dist/commands/store/admissions/list.js +17 -1
  219. package/dist/commands/store/advisories/list.js +2 -1
  220. package/dist/commands/store/follows/list.js +2 -1
  221. package/dist/commands/store/publishers/domains/list.js +2 -1
  222. package/dist/commands/store/reports/list.js +2 -1
  223. package/dist/commands/subscriptions/list.js +2 -1
  224. package/dist/commands/tasks/actionability.js +7 -30
  225. package/dist/commands/tasks/activity.js +14 -8
  226. package/dist/commands/tasks/approvals/list.js +2 -1
  227. package/dist/commands/tasks/assign.d.ts +1 -0
  228. package/dist/commands/tasks/assign.js +43 -7
  229. package/dist/commands/tasks/attachments/list.js +2 -1
  230. package/dist/commands/tasks/chat/send.js +34 -0
  231. package/dist/commands/tasks/comments/add.js +6 -1
  232. package/dist/commands/tasks/comments/list.js +2 -1
  233. package/dist/commands/tasks/complete.js +26 -2
  234. package/dist/commands/tasks/continue.d.ts +18 -0
  235. package/dist/commands/tasks/continue.js +54 -0
  236. package/dist/commands/tasks/create-tree.d.ts +5 -0
  237. package/dist/commands/tasks/create-tree.js +399 -219
  238. package/dist/commands/tasks/create.d.ts +1 -0
  239. package/dist/commands/tasks/create.js +63 -11
  240. package/dist/commands/tasks/deliverable/add.js +10 -3
  241. package/dist/commands/tasks/deliverable/list.js +2 -1
  242. package/dist/commands/tasks/events/list.js +2 -1
  243. package/dist/commands/tasks/execution-state.d.ts +12 -0
  244. package/dist/commands/tasks/execution-state.js +28 -0
  245. package/dist/commands/tasks/expectations/assess.js +40 -5
  246. package/dist/commands/tasks/guide.d.ts +10 -0
  247. package/dist/commands/tasks/guide.js +20 -0
  248. package/dist/commands/tasks/labels/list.js +2 -1
  249. package/dist/commands/tasks/list.d.ts +19 -0
  250. package/dist/commands/tasks/list.js +103 -6
  251. package/dist/commands/tasks/move.js +10 -2
  252. package/dist/commands/tasks/preflight.d.ts +14 -0
  253. package/dist/commands/tasks/preflight.js +77 -0
  254. package/dist/commands/tasks/rearm-recurrence.js +22 -3
  255. package/dist/commands/tasks/resource/list.js +2 -1
  256. package/dist/commands/tasks/result/submit.js +10 -1
  257. package/dist/commands/tasks/review.js +6 -1
  258. package/dist/commands/tasks/revisions.d.ts +2 -0
  259. package/dist/commands/tasks/revisions.js +8 -1
  260. package/dist/commands/tasks/show.d.ts +8 -0
  261. package/dist/commands/tasks/show.js +81 -43
  262. package/dist/commands/tasks/start.d.ts +1 -0
  263. package/dist/commands/tasks/start.js +35 -0
  264. package/dist/commands/tasks/templates/list.js +2 -1
  265. package/dist/commands/tasks/timeline.d.ts +5 -0
  266. package/dist/commands/tasks/timeline.js +9 -1
  267. package/dist/commands/tasks/unschedule.js +5 -1
  268. package/dist/commands/tasks/update.d.ts +1 -0
  269. package/dist/commands/tasks/update.js +36 -3
  270. package/dist/commands/tasks/updates/add.js +6 -1
  271. package/dist/commands/tasks/updates/list.js +2 -1
  272. package/dist/commands/tasks/upsert.d.ts +1 -0
  273. package/dist/commands/tasks/upsert.js +8 -1
  274. package/dist/commands/token/list.js +2 -1
  275. package/dist/commands/tokens/list.js +2 -1
  276. package/dist/commands/tones/list.js +4 -2
  277. package/dist/commands/triggers/audit.js +12 -3
  278. package/dist/commands/triggers/create.js +1 -1
  279. package/dist/commands/triggers/fire-detail.d.ts +7 -0
  280. package/dist/commands/triggers/fire-detail.js +30 -12
  281. package/dist/commands/triggers/fire.js +13 -3
  282. package/dist/commands/triggers/list.js +2 -1
  283. package/dist/commands/triggers/parse-intent.js +1 -1
  284. package/dist/commands/triggers/update.js +1 -1
  285. package/dist/commands/views/list.js +2 -1
  286. package/dist/commands/webhooks/list.js +2 -1
  287. package/dist/commands/whoami.js +1 -1
  288. package/dist/commands/widgets/list.js +2 -1
  289. package/dist/commands/widgets/save-as-app.d.ts +13 -0
  290. package/dist/commands/widgets/save-as-app.js +65 -0
  291. package/dist/commands/work-views/list.js +2 -1
  292. package/dist/commands/worklog/list.js +2 -1
  293. package/dist/commands/workspaces/grants.js +1 -4
  294. package/dist/commands/workspaces/list.js +3 -2
  295. package/dist/commands/workspaces/members.d.ts +1 -0
  296. package/dist/commands/workspaces/members.js +10 -7
  297. package/dist/generated/managed-instruction-guides.json +2 -2
  298. package/dist/help.js +7 -0
  299. package/dist/lib/agent-proactive-baseline.d.ts +9 -0
  300. package/dist/lib/agent-proactive-baseline.js +44 -0
  301. package/dist/lib/agentic-stream.d.ts +4 -1
  302. package/dist/lib/agentic-stream.js +29 -4
  303. package/dist/lib/appData.d.ts +75 -0
  304. package/dist/lib/appData.js +274 -0
  305. package/dist/lib/appInstallations.d.ts +117 -0
  306. package/dist/lib/appInstallations.js +960 -0
  307. package/dist/lib/appSettings.d.ts +3 -0
  308. package/dist/lib/appSettings.js +71 -0
  309. package/dist/lib/appWebhooks.d.ts +7 -0
  310. package/dist/lib/appWebhooks.js +59 -0
  311. package/dist/lib/apps-command.d.ts +44 -0
  312. package/dist/lib/apps-command.js +164 -0
  313. package/dist/lib/apps.d.ts +45 -0
  314. package/dist/lib/apps.js +148 -0
  315. package/dist/lib/appsCheck.d.ts +12 -0
  316. package/dist/lib/appsCheck.js +173 -0
  317. package/dist/lib/appsFs.d.ts +58 -0
  318. package/dist/lib/appsFs.js +384 -0
  319. package/dist/lib/auth-failure.d.ts +20 -0
  320. package/dist/lib/auth-failure.js +40 -3
  321. package/dist/lib/cli-installers.d.ts +9 -2
  322. package/dist/lib/command-miss.js +107 -0
  323. package/dist/lib/commitment-loop-status.js +25 -3
  324. package/dist/lib/commitment-product.js +5 -2
  325. package/dist/lib/commitments.d.ts +45 -3
  326. package/dist/lib/commitments.js +139 -41
  327. package/dist/lib/compasses.d.ts +4 -0
  328. package/dist/lib/compasses.js +11 -0
  329. package/dist/lib/daemon-machine-identity-copy.d.ts +14 -0
  330. package/dist/lib/daemon-machine-identity-copy.js +27 -0
  331. package/dist/lib/daemon-machine-identity.d.ts +27 -0
  332. package/dist/lib/daemon-machine-identity.js +61 -0
  333. package/dist/lib/daemon-setup.js +7 -7
  334. package/dist/lib/daemonHandoff.d.ts +19 -1
  335. package/dist/lib/daemonHandoff.js +62 -2
  336. package/dist/lib/dedicated-ssh.d.ts +2 -0
  337. package/dist/lib/dedicated-ssh.js +98 -28
  338. package/dist/lib/harnesses.d.ts +71 -0
  339. package/dist/lib/harnesses.js +70 -0
  340. package/dist/lib/json-output.d.ts +33 -0
  341. package/dist/lib/json-output.js +37 -0
  342. package/dist/lib/list-output.d.ts +9 -4
  343. package/dist/lib/list-output.js +38 -9
  344. package/dist/lib/lookbackPlans.d.ts +13 -0
  345. package/dist/lib/lookbackPlans.js +68 -0
  346. package/dist/lib/machines.d.ts +27 -6
  347. package/dist/lib/machines.js +25 -14
  348. package/dist/lib/member-output.d.ts +20 -0
  349. package/dist/lib/member-output.js +57 -0
  350. package/dist/lib/preflight-copy.d.ts +7 -0
  351. package/dist/lib/preflight-copy.js +31 -0
  352. package/dist/lib/profile-machine-identity-guard.js +11 -1
  353. package/dist/lib/roles.d.ts +2 -2
  354. package/dist/lib/task-admission.d.ts +9 -0
  355. package/dist/lib/task-admission.js +35 -0
  356. package/dist/lib/task-batch.d.ts +4 -0
  357. package/dist/lib/task-batch.js +2 -0
  358. package/dist/lib/task-economics.d.ts +10 -0
  359. package/dist/lib/task-economics.js +24 -2
  360. package/dist/lib/task-operations.d.ts +25 -0
  361. package/dist/lib/task-operations.js +123 -0
  362. package/dist/lib/task-preflight.d.ts +35 -0
  363. package/dist/lib/task-preflight.js +121 -0
  364. package/dist/lib/task-resource-references.d.ts +23 -0
  365. package/dist/lib/task-resource-references.js +119 -0
  366. package/dist/lib/task-spec-verification.d.ts +42 -0
  367. package/dist/lib/task-spec-verification.js +101 -0
  368. package/dist/lib/task-work.d.ts +11 -0
  369. package/dist/lib/task-work.js +41 -0
  370. package/dist/lib/task-write-attribution.d.ts +26 -0
  371. package/dist/lib/task-write-attribution.js +47 -0
  372. package/dist/lib/tasks.d.ts +13 -0
  373. package/dist/lib/tasks.js +61 -8
  374. package/dist/lib/triggers.d.ts +18 -0
  375. package/dist/lib/triggers.js +97 -5
  376. package/dist/lib/usage-discovery.d.ts +4 -0
  377. package/dist/lib/usage-discovery.js +14 -4
  378. package/dist/lib/widgetApps.d.ts +10 -0
  379. package/dist/lib/widgetApps.js +47 -0
  380. package/dist/lib/widgetStaticScan.js +25 -1
  381. package/dist/lib/workflow-run-view.d.ts +4 -0
  382. package/dist/lib/workflow-run-view.js +5 -0
  383. package/dist/lib/workspaces.d.ts +33 -9
  384. package/dist/lib/workspaces.js +19 -3
  385. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/computerWire.d.ts +14 -1
  386. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/computerWire.js +47 -2
  387. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/daemonToolApproval.d.ts +49 -1
  388. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/daemonToolApproval.js +26 -0
  389. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/daemonWire.d.ts +118 -0
  390. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/daemonWire.js +614 -0
  391. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/index.d.ts +1 -1
  392. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/index.js +5 -3
  393. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/machineUuid.d.ts +60 -0
  394. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/machineUuid.js +130 -6
  395. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/refresh.d.ts +2 -0
  396. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/refresh.js +15 -2
  397. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/refreshClassification.d.ts +5 -0
  398. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/refreshClassification.js +3 -1
  399. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/sessionRevocation.d.ts +177 -0
  400. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/sessionRevocation.js +484 -0
  401. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/telemetryRedaction.d.ts +11 -0
  402. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/telemetryRedaction.js +46 -7
  403. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/toolApprovalSignature.d.ts +232 -0
  404. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/toolApprovalSignature.js +372 -0
  405. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/types.d.ts +17 -1
  406. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/types.js +12 -1
  407. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/computerWire.d.ts +14 -1
  408. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/computerWire.js +45 -2
  409. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/daemonToolApproval.d.ts +49 -1
  410. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/daemonToolApproval.js +24 -0
  411. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/daemonWire.d.ts +118 -0
  412. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/daemonWire.js +608 -0
  413. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/index.d.ts +1 -1
  414. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/index.js +1 -1
  415. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/machineUuid.d.ts +60 -0
  416. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/machineUuid.js +128 -6
  417. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/refresh.d.ts +2 -0
  418. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/refresh.js +15 -2
  419. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/refreshClassification.d.ts +5 -0
  420. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/refreshClassification.js +3 -1
  421. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/sessionRevocation.d.ts +177 -0
  422. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/sessionRevocation.js +472 -0
  423. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/telemetryRedaction.d.ts +11 -0
  424. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/telemetryRedaction.js +44 -6
  425. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/toolApprovalSignature.d.ts +232 -0
  426. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/toolApprovalSignature.js +360 -0
  427. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/types.d.ts +17 -1
  428. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/types.js +12 -1
  429. package/dist/node_modules/@skrr-ai/auth-core/package.json +31 -1
  430. package/dist/node_modules/@skrr-ai/data-provider/index.js +25255 -18711
  431. package/docs/v1/operations.md +52 -0
  432. package/docs/v1/space-search.md +19 -0
  433. package/oclif.manifest.json +4843 -513
  434. package/package.json +32 -2
@@ -8,6 +8,10 @@ export interface CompassInvariantTarget {
8
8
  maintainedState?: string[];
9
9
  successMetrics?: string[];
10
10
  boundaries?: string[];
11
+ learnedTactics?: Array<{
12
+ id?: string;
13
+ description?: string;
14
+ }>;
11
15
  freshness?: Record<string, unknown>;
12
16
  cadence?: Record<string, unknown>;
13
17
  escalation?: Record<string, unknown>;
@@ -44,6 +44,12 @@ exports.compassApi = {
44
44
  appendTactic: (id, body) => data_provider_2.request.post(`${base(id)}/tactics`, body),
45
45
  commitments: (id, query) => data_provider_2.request.get((0, triggers_1.withQuery)(`${base(id)}/commitments`, query)),
46
46
  };
47
+ const OVERFLOW_FIELD_LABEL = {
48
+ maintainedState: 'keeps-true entries',
49
+ successMetrics: 'success metrics',
50
+ boundaries: 'boundaries',
51
+ learnedTactics: 'learned tactics',
52
+ };
47
53
  function shortDate(value) {
48
54
  if (!value)
49
55
  return '—';
@@ -120,6 +126,11 @@ function renderCompass(compass, log) {
120
126
  if (target.successMetrics?.length) {
121
127
  log(` measured by: ${target.successMetrics.join('; ')}`);
122
128
  }
129
+ // The agent's prompt carries a bounded number of each list. Say which
130
+ // were cut, so the list above is not read as what the agent sees.
131
+ for (const overflow of (0, data_provider_1.describeCompassOverflow)(target)) {
132
+ log(` ! shown to the agent: ${overflow.rendered} of ${overflow.authored} ${OVERFLOW_FIELD_LABEL[overflow.field]} (${overflow.omitted} not shown)`);
133
+ }
123
134
  }
124
135
  }
125
136
  const tactics = compass.learnedTactics ?? [];
@@ -0,0 +1,14 @@
1
+ import type { DaemonMachineIdentitySkew } from './daemon-machine-identity';
2
+ /**
3
+ * What to tell someone whose installed background service would register their
4
+ * profile on the default profile's machine row (OSK-S-440).
5
+ *
6
+ * The consequence is stated before the remedy because the remedy costs something
7
+ * (updating a service) and the consequence is what justifies it: a second
8
+ * profile on the default's row replaces its Daemon and its device-key pin, and
9
+ * the default profile's next refresh is refused until it signs in again.
10
+ *
11
+ * Lives here, apart from the comparison, because this is copy and reads
12
+ * `BRAND.displayName`; the comparison is pure and imports nothing from it.
13
+ */
14
+ export declare function describeDaemonMachineIdentitySkew(skew: DaemonMachineIdentitySkew): string[];
@@ -0,0 +1,27 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.describeDaemonMachineIdentitySkew = describeDaemonMachineIdentitySkew;
4
+ const data_provider_1 = require("@skrr-ai/data-provider");
5
+ /**
6
+ * What to tell someone whose installed background service would register their
7
+ * profile on the default profile's machine row (OSK-S-440).
8
+ *
9
+ * The consequence is stated before the remedy because the remedy costs something
10
+ * (updating a service) and the consequence is what justifies it: a second
11
+ * profile on the default's row replaces its Daemon and its device-key pin, and
12
+ * the default profile's next refresh is refused until it signs in again.
13
+ *
14
+ * Lives here, apart from the comparison, because this is copy and reads
15
+ * `BRAND.displayName`; the comparison is pure and imports nothing from it.
16
+ */
17
+ function describeDaemonMachineIdentitySkew(skew) {
18
+ const product = data_provider_1.BRAND.displayName;
19
+ const said = skew.reported
20
+ ? `it reports machine identity ${skew.reported}, where profile '${skew.profile}' has ${skew.expected}`
21
+ : `it does not report a machine identity at all, so ${product} cannot tell which one it would use`;
22
+ return [
23
+ `The ${product} background service at ${skew.binary} does not support a separate machine identity per profile: ${said}.`,
24
+ `Using it for '${skew.profile}' would register that profile on the default profile's machine and could replace the default profile's device-key pin. Nothing was changed.`,
25
+ `Update the background service (skrr daemon update), or put a current skrrd first on your PATH, then run: skrr login --profile ${skew.profile}`,
26
+ ];
27
+ }
@@ -0,0 +1,27 @@
1
+ export interface DaemonMachineIdentitySkew {
2
+ /** The profile being signed in. */
3
+ profile: string;
4
+ /** The machine identity this profile has, as decided by the profile's own record. */
5
+ expected: string;
6
+ /** What the daemon binary says it will send; null when it said nothing. */
7
+ reported: string | null;
8
+ /** The `skrrd` that was asked. */
9
+ binary: string;
10
+ }
11
+ /**
12
+ * Null when the daemon will register this profile under the identity it has;
13
+ * otherwise what disagrees.
14
+ *
15
+ * Not applicable to the default profile (its identity is the hardware value in
16
+ * every version), to a hosted runtime (the control plane issues it), or when no
17
+ * profile is named.
18
+ *
19
+ * A daemon that reports NOTHING is a skew, not a pass: this check exists because
20
+ * an older binary cannot say, and "could not confirm" must not read as "fine" on
21
+ * the step that binds a credential to a machine row.
22
+ */
23
+ export declare function daemonMachineIdentitySkew(opts: {
24
+ profile: string | null | undefined;
25
+ binary: string;
26
+ reported: string | null | undefined;
27
+ }): DaemonMachineIdentitySkew | null;
@@ -0,0 +1,61 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.daemonMachineIdentitySkew = daemonMachineIdentitySkew;
4
+ /**
5
+ * daemon-machine-identity.ts — does the installed daemon give this profile the
6
+ * machine identity the CLI decided it has?
7
+ *
8
+ * Two programs compute one identity: the CLI (and the profile's persisted
9
+ * `machine-identity.json`) say a profile that started new has its own machine
10
+ * row, and the DAEMON is what registers. A daemon that predates per-profile
11
+ * identities (OSK-13845) does not read that file; it sends the hardware value
12
+ * whatever the profile is. Nothing noticed. The CLI minted the daemon's credential
13
+ * for what the daemon REPORTED (`accept-handoff --print-id`), so the credential
14
+ * was bound to the default machine's row, the service registered there, and the
15
+ * failure OSK-13845 exists to prevent happened anyway: two profiles on one Daemon
16
+ * row and one device-key pin, the second profile's interactive login re-pinning
17
+ * the first one's key (OSK-S-440, profile `aapexp`).
18
+ *
19
+ * Measured, not inferred: the same new profile, in an empty home, answered by
20
+ * two `skrrd` binaries. The current one reports `<hardware>:p-<hash>` and writes
21
+ * `machine-identity.json` and `daemon-identity.json`; the build that was first on
22
+ * the dogfooder's PATH (a checkout `dist` from before OSK-13845, whose version
23
+ * string still reads the checkout's package.json) reports the bare hardware value
24
+ * and writes neither. The profile it left behind had a `machine-identity.json`
25
+ * (the CLI's) and no `daemon-identity.json` after four daemon starts.
26
+ *
27
+ * The fix is to compare, not to guess a version: ask the binary what it will
28
+ * send, compare with what this profile's decided identity is, and refuse BEFORE
29
+ * anything is minted or installed when they differ. Comparing the value is the
30
+ * only test that cannot be wrong about a build that is older than its own
31
+ * version string says.
32
+ *
33
+ * Pure: the I/O (spawning the binary) is in `daemonHandoff.ts`, the copy in
34
+ * `daemon-machine-identity-copy.ts`.
35
+ */
36
+ const machine_uuid_1 = require("@skrr-ai/auth-core/machine-uuid");
37
+ const keychain_1 = require("./keychain");
38
+ /**
39
+ * Null when the daemon will register this profile under the identity it has;
40
+ * otherwise what disagrees.
41
+ *
42
+ * Not applicable to the default profile (its identity is the hardware value in
43
+ * every version), to a hosted runtime (the control plane issues it), or when no
44
+ * profile is named.
45
+ *
46
+ * A daemon that reports NOTHING is a skew, not a pass: this check exists because
47
+ * an older binary cannot say, and "could not confirm" must not read as "fine" on
48
+ * the step that binds a credential to a machine row.
49
+ */
50
+ function daemonMachineIdentitySkew(opts) {
51
+ const profile = opts.profile?.trim();
52
+ if (!profile || profile === keychain_1.DEFAULT_PROFILE)
53
+ return null;
54
+ if ((0, machine_uuid_1.hostedRuntimeIdOverride)('OVERSKY_MACHINE_UUID'))
55
+ return null;
56
+ const expected = (0, machine_uuid_1.getMachineUuidForProfile)(profile);
57
+ const reported = opts.reported?.trim() || null;
58
+ if (reported === expected)
59
+ return null;
60
+ return { profile, expected, reported, binary: opts.binary };
61
+ }
@@ -98,13 +98,13 @@ async function offerDaemonSetup(opts = {}) {
98
98
  log('');
99
99
  log(` This computer has no ${data_provider_1.BRAND.displayName} background service. It is what lets your agents work here —`);
100
100
  log(' running commands, editing files, and driving a browser on this machine.');
101
- // What it does UNASKED is part of the decision, and it used to be found
102
- // afterwards in a status table (OSK-16439). The defaults are the daemon's
103
- // (`DEFAULT_CONFIG.permissions`, pinned against this sentence by
104
- // `unattended-posture.spec.ts` in the daemon): reads, writes, shell commands
105
- // and Claude sessions run without a prompt until someone changes them.
106
- log(' Until you change it, agents can read files, edit files and run shell commands here');
107
- log(` without asking you first. To be asked before each call instead: \`${(0, daemon_command_hint_1.daemonCommandHint)('config', { extraArgs: '--require-approvals' })}\``);
101
+ // Disclose both the safe new-profile default and upgrade compatibility at
102
+ // the point where the person consents to a persistent local service.
103
+ log(' New local profiles require approval for file reads, edits and shell commands.');
104
+ log(' Cloud-started Claude Code sessions are refused until explicitly enabled.');
105
+ log(' Existing profiles keep their permission settings, which may allow tools without asking.');
106
+ log(` Require approvals for this profile: \`${(0, daemon_command_hint_1.daemonCommandHint)('config', { extraArgs: '--require-approvals' })}\``);
107
+ log(` Allow only a chosen category without asking: \`${(0, daemon_command_hint_1.daemonCommandHint)('config', { extraArgs: '--mode read=auto' })}\``);
108
108
  // This creates a persistent service with broad local capabilities, so a
109
109
  // bare Enter must visibly and behaviorally decline it. `confirm` names its
110
110
  // second argument `defaultNo`; passing false showed `[Y/n]` and accepted an
@@ -1,3 +1,4 @@
1
+ import { type DaemonMachineIdentitySkew } from './daemon-machine-identity';
1
2
  /**
2
3
  * Hand the local daemon a credential of its own, right after `skrr login`.
3
4
  *
@@ -40,8 +41,25 @@ export interface DaemonHandoffOutcome {
40
41
  * The two absent cases are separated because they need different work — one
41
42
  * needs a binary fetched, the other only needs the service registered.
42
43
  */
43
- reason?: 'opted-out' | 'brokered' | 'no-binary' | 'legacy-binary' | 'unsupported-daemon' | 'no-service' | 'foreign-root' | 'mint-refused' | 'platform-managed';
44
+ reason?: 'opted-out' | 'brokered' | 'no-binary' | 'legacy-binary' | 'unsupported-daemon' | 'no-service' | 'foreign-root' | 'mint-refused' | 'platform-managed' | 'machine-identity-skew';
45
+ /** Set with `reason: 'machine-identity-skew'`; the caller words it. */
46
+ skew?: DaemonMachineIdentitySkew;
44
47
  }
45
48
  export declare function handOffToLocalDaemon(env?: NodeJS.ProcessEnv, opts?: {
46
49
  loginFlow?: string;
47
50
  }): Promise<DaemonHandoffOutcome>;
51
+ /**
52
+ * Ask the installed daemon which machine identity it will register `profile`
53
+ * under, and say what disagrees with the profile's own (OSK-S-440).
54
+ *
55
+ * For the commands that install or sign in a daemon WITHOUT going through the
56
+ * credential hand-off (`skrr daemon install`, `skrr daemon login`): the same
57
+ * question, asked of the binary they are about to run. Null when the daemon
58
+ * agrees, when the profile is the default one, or when there is no binary to ask
59
+ * (the caller has its own answer for that).
60
+ *
61
+ * A binary that cannot be asked at all - too old to have `accept-handoff`, or
62
+ * one that fails the probe - is reported as a skew with no identity, because the
63
+ * point of asking is not to bind a profile to a machine row on a guess.
64
+ */
65
+ export declare function checkLocalDaemonMachineIdentity(profile: string | null | undefined, binary?: string | null): Promise<DaemonMachineIdentitySkew | null>;
@@ -1,10 +1,12 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.handOffToLocalDaemon = handOffToLocalDaemon;
4
+ exports.checkLocalDaemonMachineIdentity = checkLocalDaemonMachineIdentity;
4
5
  const node_child_process_1 = require("node:child_process");
5
6
  const data_provider_1 = require("@skrr-ai/data-provider");
6
7
  const config_1 = require("./config");
7
8
  const daemon_handoff_opt_out_1 = require("./daemon-handoff-opt-out");
9
+ const daemon_machine_identity_1 = require("./daemon-machine-identity");
8
10
  const dedicated_service_1 = require("./dedicated-service");
9
11
  const exec_runtime_binary_1 = require("./exec-runtime-binary");
10
12
  const keychain_1 = require("./keychain");
@@ -146,8 +148,9 @@ function describeDelivery(opts) {
146
148
  /**
147
149
  * Compare deployments, not spellings.
148
150
  *
149
- * `https://oversky.ai` and `https://skrr.ai` are one deployment under two names,
150
- * and the first is still what every daemon installed before the cutover carries.
151
+ * The pre-cutover production host and `https://skrr.ai` are one deployment under
152
+ * two names, and the first is still what every daemon installed before the cutover
153
+ * carries.
151
154
  * Trimming and lowercasing alone would report a move on every login from every
152
155
  * one of those machines — a warning that is wrong for the largest group of users
153
156
  * who would see it, which is how a signal becomes noise. `canonicalizeKnownBaseURL`
@@ -275,6 +278,26 @@ async function handOffToLocalDaemon(env = process.env, opts = {}) {
275
278
  };
276
279
  }
277
280
  const { idSource, machineUuid, daemonServer } = parseIdProvenance(printed.stderr);
281
+ // Before anything is minted or installed: does THIS binary register the profile
282
+ // under the machine identity the profile has? The mint below binds the
283
+ // credential to the machine uuid the daemon just REPORTED, so a binary that
284
+ // reports the hardware value for a profile that has its own would put it on the
285
+ // default profile's row - and the install that follows would run that same
286
+ // binary as a service. Nothing about the id or the provenance would look wrong.
287
+ const skew = (0, daemon_machine_identity_1.daemonMachineIdentitySkew)({
288
+ profile: (0, keychain_1.getActiveProfile)(),
289
+ binary,
290
+ reported: machineUuid,
291
+ });
292
+ if (skew) {
293
+ return {
294
+ status: 'failed',
295
+ reason: 'machine-identity-skew',
296
+ skew,
297
+ detail: `the installed daemon reports machine identity ${skew.reported ?? '(none)'} ` +
298
+ `where profile '${skew.profile}' has ${skew.expected}`,
299
+ };
300
+ }
278
301
  // A well-formed id is not the same as a real daemon. With no service installed
279
302
  // the daemon derives one from whatever directory this process is in, so the id
280
303
  // above names a daemon that does not exist and will not exist under that id if
@@ -354,3 +377,40 @@ async function handOffToLocalDaemon(env = process.env, opts = {}) {
354
377
  }),
355
378
  };
356
379
  }
380
+ /**
381
+ * Ask the installed daemon which machine identity it will register `profile`
382
+ * under, and say what disagrees with the profile's own (OSK-S-440).
383
+ *
384
+ * For the commands that install or sign in a daemon WITHOUT going through the
385
+ * credential hand-off (`skrr daemon install`, `skrr daemon login`): the same
386
+ * question, asked of the binary they are about to run. Null when the daemon
387
+ * agrees, when the profile is the default one, or when there is no binary to ask
388
+ * (the caller has its own answer for that).
389
+ *
390
+ * A binary that cannot be asked at all - too old to have `accept-handoff`, or
391
+ * one that fails the probe - is reported as a skew with no identity, because the
392
+ * point of asking is not to bind a profile to a machine row on a guess.
393
+ */
394
+ async function checkLocalDaemonMachineIdentity(profile, binary = (0, exec_runtime_binary_1.findRuntimeBinary)()) {
395
+ if (!profile || profile === keychain_1.DEFAULT_PROFILE || !binary)
396
+ return null;
397
+ const printed = await runOversky(binary, ['accept-handoff', '--print-id', '--profile', profile], {
398
+ timeoutMs: PROBE_TIMEOUT_MS,
399
+ });
400
+ if (!printed.ok) {
401
+ // A daemon too old to have `accept-handoff` answers "unknown command": it is
402
+ // older than per-profile identities too, which is the skew itself.
403
+ if (/unknown command/i.test(printed.stderr)) {
404
+ return (0, daemon_machine_identity_1.daemonMachineIdentitySkew)({ profile, binary, reported: null });
405
+ }
406
+ // Any other failed probe says nothing about the daemon's identity, and
407
+ // refusing a sign-in on a flaky probe would be a worse failure than the one
408
+ // this guards: let the command run and meet whatever the daemon itself says.
409
+ return null;
410
+ }
411
+ return (0, daemon_machine_identity_1.daemonMachineIdentitySkew)({
412
+ profile,
413
+ binary,
414
+ reported: parseIdProvenance(printed.stderr).machineUuid,
415
+ });
416
+ }
@@ -132,6 +132,8 @@ export interface SshProxyOptions {
132
132
  ttlSeconds?: number;
133
133
  getToken?: () => Promise<string>;
134
134
  recoveryMs?: number;
135
+ /** Process lifecycle; injectable so tests never signal the test runner. */
136
+ signalSource?: Pick<NodeJS.Process, 'on' | 'off'>;
135
137
  /** Injected for tests. */
136
138
  connect?: (url: string, opts: Parameters<typeof io>[1]) => Socket;
137
139
  /** Injected for tests. */
@@ -301,8 +301,11 @@ function runSshProxy(options) {
301
301
  let closing = false;
302
302
  let lastKeepaliveAt = 0;
303
303
  let pendingInput = null;
304
- const identityAuth = () => ({ ...(0, data_provider_1.getClientIdentityAuth)(), clientPlatform: 'cli',
305
- clientOs: process.platform === 'darwin' ? 'macos' : process.platform });
304
+ const identityAuth = () => ({
305
+ ...(0, data_provider_1.getClientIdentityAuth)(),
306
+ clientPlatform: 'cli',
307
+ clientOs: process.platform === 'darwin' ? 'macos' : process.platform,
308
+ });
306
309
  const wsOrigin = (0, agentic_stream_1.toWebSocketOrigin)(options.baseURL);
307
310
  const handshakeAuth = (token, callback) => {
308
311
  // Resolve a fresh proof after token renewal on every reconnect. Never
@@ -315,20 +318,30 @@ function runSshProxy(options) {
315
318
  };
316
319
  const socket = connect(wsOrigin, {
317
320
  path: '/ws/agentic',
318
- auth: options.getToken ? (callback) => {
319
- void options.getToken().then((token) => handshakeAuth(token, callback), () => {
320
- finish(1, 'Could not renew SSH authentication. Restore skrr login and connect again.');
321
- });
322
- } : (0, dpop_auth_1.socketAuthWithDpop)({ token: options.token, ...identityAuth() }, wsOrigin),
323
- transports: ['websocket'], reconnection: true,
324
- reconnectionDelay: 1000, reconnectionDelayMax: 2000,
321
+ auth: options.getToken
322
+ ? (callback) => {
323
+ void options.getToken().then((token) => handshakeAuth(token, callback), () => {
324
+ finish(1, 'Could not renew SSH authentication. Restore skrr login and connect again.');
325
+ });
326
+ }
327
+ : (0, dpop_auth_1.socketAuthWithDpop)({ token: options.token, ...identityAuth() }, wsOrigin),
328
+ transports: ['websocket'],
329
+ reconnection: true,
330
+ reconnectionDelay: 1000,
331
+ reconnectionDelayMax: 2000,
325
332
  });
326
333
  const startTimer = setTimeout(() => finish(1, 'The machine did not answer the SSH channel in time. Its daemon may be busy or offline.'), exports.SSH_START_TIMEOUT_MS);
327
334
  function sendPendingInput() {
328
335
  if (closing || !online || !attached || !pendingInput || finished)
329
336
  return;
330
- socket.emit('dedicated:ssh:data', { channelId, data: pendingInput.bytes.toString('base64'),
331
- resumeV2: true, epoch, generation, offset: pendingInput.offset });
337
+ socket.emit('dedicated:ssh:data', {
338
+ channelId,
339
+ data: pendingInput.bytes.toString('base64'),
340
+ resumeV2: true,
341
+ epoch,
342
+ generation,
343
+ offset: pendingInput.offset,
344
+ });
332
345
  }
333
346
  function pumpInput() {
334
347
  if (closing || !started || !resumable || !online || !attached || pendingInput || finished)
@@ -351,11 +364,23 @@ function runSshProxy(options) {
351
364
  };
352
365
  function sendResume() {
353
366
  if (online && started && resumable && !attached && !finished) {
354
- socket.emit('dedicated:ssh:resume', { leaseId: options.leaseId, channelId, resumeProof, epoch, generation, attachmentSeq });
367
+ socket.emit('dedicated:ssh:resume', {
368
+ leaseId: options.leaseId,
369
+ channelId,
370
+ resumeProof,
371
+ epoch,
372
+ generation,
373
+ attachmentSeq,
374
+ });
355
375
  }
356
376
  }
357
377
  function keepalive() {
358
- if (started && resumable && attached && online && !finished && Date.now() - lastKeepaliveAt >= 10_000) {
378
+ if (started &&
379
+ resumable &&
380
+ attached &&
381
+ online &&
382
+ !finished &&
383
+ Date.now() - lastKeepaliveAt >= 10_000) {
359
384
  lastKeepaliveAt = Date.now();
360
385
  socket.emit('dedicated:ssh:keepalive', { channelId, epoch });
361
386
  }
@@ -376,6 +401,10 @@ function runSshProxy(options) {
376
401
  keepalive();
377
402
  }, 2000);
378
403
  ticker.unref?.();
404
+ const signals = options.signalSource ?? process;
405
+ const onTermination = () => finish(0);
406
+ signals.on('SIGHUP', onTermination);
407
+ signals.on('SIGTERM', onTermination);
379
408
  const onInputEnded = () => finish(0);
380
409
  const onOutputError = () => finish(1);
381
410
  input.once('end', onInputEnded);
@@ -397,10 +426,24 @@ function runSshProxy(options) {
397
426
  if (notice)
398
427
  errorOutput.write(`${notice}\n`);
399
428
  // Never queue an offline stop that might arrive after another attachment.
400
- if (started && online)
401
- socket.emit('dedicated:ssh:stop', { channelId, ...(resumable ? { epoch } : {}) });
402
- socket.disconnect();
403
- resolve(code);
429
+ const disconnected = () => {
430
+ signals.off('SIGHUP', onTermination);
431
+ signals.off('SIGTERM', onTermination);
432
+ socket.disconnect();
433
+ resolve(code);
434
+ };
435
+ if (started && online) {
436
+ // OpenSSH may SIGHUP its ProxyCommand before stdio reaches EOF. Keep
437
+ // the transport alive until the API has forwarded stop. A bounded
438
+ // fallback also supports older servers without this receipt.
439
+ const closeTimer = setTimeout(disconnected, 1000);
440
+ socket.emit('dedicated:ssh:stop', { channelId, ...(resumable ? { epoch } : {}) }, () => {
441
+ clearTimeout(closeTimer);
442
+ disconnected();
443
+ });
444
+ }
445
+ else
446
+ disconnected();
404
447
  }
405
448
  socket.on('connect_error', (error) => {
406
449
  if (finished || (started && resumable))
@@ -420,9 +463,16 @@ function runSshProxy(options) {
420
463
  return;
421
464
  }
422
465
  startSent = true;
423
- socket.emit('dedicated:ssh:start', { leaseId: options.leaseId, channelId,
424
- keyType: identity.keyType, keyBlob: identity.keyBlob, receiverAckV1: true,
425
- resumeV2: true, resumeProof, epoch });
466
+ socket.emit('dedicated:ssh:start', {
467
+ leaseId: options.leaseId,
468
+ channelId,
469
+ keyType: identity.keyType,
470
+ keyBlob: identity.keyBlob,
471
+ receiverAckV1: true,
472
+ resumeV2: true,
473
+ resumeProof,
474
+ epoch,
475
+ });
426
476
  });
427
477
  socket.on('dedicated:ssh:start:ack', (ack) => {
428
478
  if (!ack || ack.channelId !== channelId || started || finished)
@@ -432,7 +482,9 @@ function runSshProxy(options) {
432
482
  return;
433
483
  }
434
484
  if (ack.resumeV2 === true) {
435
- if (ack.epoch !== epoch || !Number.isSafeInteger(ack.generation) || Number(ack.generation) < 1 ||
485
+ if (ack.epoch !== epoch ||
486
+ !Number.isSafeInteger(ack.generation) ||
487
+ Number(ack.generation) < 1 ||
436
488
  (generation !== null && generation !== ack.generation)) {
437
489
  finish(1, 'Invalid SSH stream admission.');
438
490
  return;
@@ -458,7 +510,13 @@ function runSshProxy(options) {
458
510
  }
459
511
  });
460
512
  socket.on('dedicated:ssh:resume:ack', (ack) => {
461
- if (!ack || ack.channelId !== channelId || ack.epoch !== epoch || !started || !resumable || finished || attached)
513
+ if (!ack ||
514
+ ack.channelId !== channelId ||
515
+ ack.epoch !== epoch ||
516
+ !started ||
517
+ !resumable ||
518
+ finished ||
519
+ attached)
462
520
  return;
463
521
  if (!ack.ok) {
464
522
  if (ack.retryable === true)
@@ -483,8 +541,14 @@ function runSshProxy(options) {
483
541
  pumpInput();
484
542
  });
485
543
  socket.on('dedicated:ssh:input:ack', (ack) => {
486
- if (finished || !resumable || !pendingInput || !attached || ack?.channelId !== channelId ||
487
- ack.epoch !== epoch || ack.generation !== generation || ack.offset !== pendingInput.offset)
544
+ if (finished ||
545
+ !resumable ||
546
+ !pendingInput ||
547
+ !attached ||
548
+ ack?.channelId !== channelId ||
549
+ ack.epoch !== epoch ||
550
+ ack.generation !== generation ||
551
+ ack.offset !== pendingInput.offset)
488
552
  return;
489
553
  if (!ack.ok) {
490
554
  finish(1, ack.error || 'The SSH input stream was refused.');
@@ -499,19 +563,25 @@ function runSshProxy(options) {
499
563
  pumpInput();
500
564
  });
501
565
  socket.on('dedicated:ssh:data', async (frame, receipt) => {
502
- if (!frame || frame.channelId !== channelId || finished || typeof frame.data !== 'string' || !frame.data.length)
566
+ if (!frame ||
567
+ frame.channelId !== channelId ||
568
+ finished ||
569
+ typeof frame.data !== 'string' ||
570
+ !frame.data.length)
503
571
  return;
504
572
  try {
505
573
  const bytes = Buffer.from(frame.data, 'base64');
506
574
  if (frame.resumeV2 === true) {
507
575
  if (frame.epoch !== epoch)
508
576
  return;
509
- if (!Number.isSafeInteger(frame.generation) || Number(frame.generation) < 1 ||
510
- (generation !== null && frame.generation !== generation) || bytes.toString('base64') !== frame.data) {
577
+ if (!Number.isSafeInteger(frame.generation) ||
578
+ Number(frame.generation) < 1 ||
579
+ (generation !== null && frame.generation !== generation) ||
580
+ bytes.toString('base64') !== frame.data) {
511
581
  throw new Error('invalid SSH output frame');
512
582
  }
513
583
  generation ??= frame.generation;
514
- const nextOffset = await receiver.receive(frame.offset, bytes, (value) => new Promise((done, reject) => output.write(value, (error) => error ? reject(error) : done())));
584
+ const nextOffset = await receiver.receive(frame.offset, bytes, (value) => new Promise((done, reject) => output.write(value, (error) => (error ? reject(error) : done()))));
515
585
  receipt?.({ channelId, ok: !finished, epoch: frame.epoch, nextOffset });
516
586
  }
517
587
  else {
@@ -238,6 +238,77 @@ export declare function updateHarness(id: string, patch: Record<string, unknown>
238
238
  harness?: Harness;
239
239
  }>;
240
240
  export declare function forgetHarness(id: string): Promise<unknown>;
241
+ /**
242
+ * Why a superseded-looking row is KEPT by `harnesses prune`. Declared by the
243
+ * server (`pruneSupersededHarnesses.js`, `REASONS`) and worded once, in
244
+ * `harnessPruneReasonSentence`, so the table and `--json` never disagree.
245
+ */
246
+ export type HarnessPruneReason = 'recent' | 'latest_registration' | 'no_live_sibling' | 'pinned' | 'granted' | 'default' | 'aliased' | 'changed_since_plan';
247
+ export interface HarnessPruneRow {
248
+ id: string;
249
+ daemonId: string | null;
250
+ provider: string | null;
251
+ name: string | null;
252
+ lastSeenAt: string | null;
253
+ machineUuid: string | null;
254
+ /** The live sibling that replaced a row this call removes (or would). */
255
+ supersededBy?: {
256
+ id: string;
257
+ daemonId: string | null;
258
+ lastSeenAt: string | null;
259
+ };
260
+ /** Set on kept rows. */
261
+ reason?: HarnessPruneReason;
262
+ /** For `pinned`: who holds the pin. Other people's agents are a count, never named. */
263
+ detail?: {
264
+ agents?: Array<{
265
+ id: string;
266
+ name: string | null;
267
+ }>;
268
+ moreAgents?: number;
269
+ otherAuthors?: number;
270
+ };
271
+ }
272
+ export interface HarnessPruneResult {
273
+ dryRun: boolean;
274
+ limit: number;
275
+ minUnseenMs: number;
276
+ scan: {
277
+ rows: number;
278
+ complete: boolean;
279
+ };
280
+ /** Rows this call removes (dry run: would remove). */
281
+ remove: HarnessPruneRow[];
282
+ /** Rows this call actually removed; 0 on a dry run. */
283
+ removedCount: number;
284
+ /** Removable rows beyond `limit`; the next call takes them. */
285
+ remaining: number;
286
+ kept: HarnessPruneRow[];
287
+ keptTruncated: boolean;
288
+ counts: Record<string, number>;
289
+ }
290
+ /**
291
+ * Remove the caller's superseded harness rows - or, by default, say which would go.
292
+ *
293
+ * ONE route for both: the server makes the decision once and this only asks for it
294
+ * to be shown (`dryRun: true`, also its own default) or carried out. The caller
295
+ * never lists rows and picks, so there is no client-side rule to drift from the
296
+ * server's. A write, so `apiFetch` gives it an idempotency key and a retried
297
+ * request replays the recorded answer instead of running again.
298
+ */
299
+ export declare function pruneHarnesses(options?: {
300
+ dryRun: boolean;
301
+ limit?: number;
302
+ minUnseenMs?: number;
303
+ }): Promise<HarnessPruneResult>;
304
+ /**
305
+ * `--older-than` takes a whole number with a unit: `90m`, `36h`, `7d`. A bare
306
+ * number is hours. Returns milliseconds. The server never goes below its offline
307
+ * window whatever this says.
308
+ */
309
+ export declare function parseHarnessPruneAge(value: string): number;
310
+ /** One sentence per reason a row was kept. The only place they are worded. */
311
+ export declare function harnessPruneReasonSentence(row: HarnessPruneRow): string;
241
312
  /**
242
313
  * A per-USER display name. Distinct from `updateHarness({name})`, which renames
243
314
  * the harness for everyone it is shared with — this only changes what YOU see,