@skrr-ai/cli 0.1.46 → 0.1.48

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 (305) hide show
  1. package/README.md +1 -1
  2. package/dist/base-command.d.ts +18 -0
  3. package/dist/base-command.js +61 -1
  4. package/dist/commands/agents/chat.d.ts +21 -0
  5. package/dist/commands/agents/chat.js +26 -9
  6. package/dist/commands/balance/usage/breakdown.d.ts +14 -0
  7. package/dist/commands/balance/usage/breakdown.js +68 -0
  8. package/dist/commands/balance/usage.js +24 -0
  9. package/dist/commands/code/handover.d.ts +2 -2
  10. package/dist/commands/code/handover.js +12 -13
  11. package/dist/commands/code/install.js +31 -0
  12. package/dist/commands/code/update.d.ts +46 -0
  13. package/dist/commands/code/update.js +242 -0
  14. package/dist/commands/commerce/entitlements/explain.d.ts +22 -0
  15. package/dist/commands/commerce/entitlements/explain.js +40 -0
  16. package/dist/commands/commerce/incidents/audit.d.ts +20 -0
  17. package/dist/commands/commerce/incidents/audit.js +37 -0
  18. package/dist/commands/commerce/incidents/list.d.ts +22 -0
  19. package/dist/commands/commerce/incidents/list.js +49 -0
  20. package/dist/commands/commerce/incidents/resolve.d.ts +23 -0
  21. package/dist/commands/commerce/incidents/resolve.js +45 -0
  22. package/dist/commands/commerce/incidents/retry.d.ts +22 -0
  23. package/dist/commands/commerce/incidents/retry.js +45 -0
  24. package/dist/commands/commerce/incidents/show.d.ts +13 -0
  25. package/dist/commands/commerce/incidents/show.js +30 -0
  26. package/dist/commands/commerce/offers/approve.d.ts +17 -0
  27. package/dist/commands/commerce/offers/approve.js +33 -0
  28. package/dist/commands/commerce/offers/create.d.ts +18 -0
  29. package/dist/commands/commerce/offers/create.js +34 -0
  30. package/dist/commands/commerce/offers/publish.d.ts +13 -0
  31. package/dist/commands/commerce/offers/publish.js +28 -0
  32. package/dist/commands/commerce/offers/retire.d.ts +17 -0
  33. package/dist/commands/commerce/offers/retire.js +32 -0
  34. package/dist/commands/commerce/offers/validate.d.ts +18 -0
  35. package/dist/commands/commerce/offers/validate.js +33 -0
  36. package/dist/commands/commerce/products/create.d.ts +10 -0
  37. package/dist/commands/commerce/products/create.js +25 -0
  38. package/dist/commands/commerce/promotions/redeem.d.ts +13 -0
  39. package/dist/commands/commerce/promotions/redeem.js +32 -0
  40. package/dist/commands/commerce/terms/accept.d.ts +18 -0
  41. package/dist/commands/commerce/terms/accept.js +39 -0
  42. package/dist/commands/commerce/terms/show.d.ts +10 -0
  43. package/dist/commands/commerce/terms/show.js +34 -0
  44. package/dist/commands/commerce/trials/conversion-preview.d.ts +18 -0
  45. package/dist/commands/commerce/trials/conversion-preview.js +39 -0
  46. package/dist/commands/commerce/trials/start.d.ts +23 -0
  47. package/dist/commands/commerce/trials/start.js +58 -0
  48. package/dist/commands/commitments/accounting.d.ts +39 -0
  49. package/dist/commands/commitments/accounting.js +116 -0
  50. package/dist/commands/commitments/action-history.d.ts +1 -0
  51. package/dist/commands/commitments/action-history.js +8 -1
  52. package/dist/commands/commitments/case.d.ts +1 -0
  53. package/dist/commands/commitments/case.js +19 -3
  54. package/dist/commands/commitments/cases.d.ts +1 -0
  55. package/dist/commands/commitments/cases.js +11 -1
  56. package/dist/commands/commitments/checks.d.ts +1 -0
  57. package/dist/commands/commitments/checks.js +5 -1
  58. package/dist/commands/commitments/cost.d.ts +62 -0
  59. package/dist/commands/commitments/cost.js +130 -0
  60. package/dist/commands/commitments/create.js +1 -1
  61. package/dist/commands/commitments/delete.d.ts +1 -0
  62. package/dist/commands/commitments/delete.js +56 -6
  63. package/dist/commands/commitments/feedback.js +9 -1
  64. package/dist/commands/commitments/handover.js +16 -0
  65. package/dist/commands/commitments/hypotheses.d.ts +1 -0
  66. package/dist/commands/commitments/hypotheses.js +17 -2
  67. package/dist/commands/commitments/links/list.js +4 -1
  68. package/dist/commands/commitments/liveness.d.ts +18 -0
  69. package/dist/commands/commitments/liveness.js +80 -0
  70. package/dist/commands/commitments/metrics.d.ts +1 -0
  71. package/dist/commands/commitments/metrics.js +8 -1
  72. package/dist/commands/commitments/next-tick.d.ts +39 -0
  73. package/dist/commands/commitments/next-tick.js +122 -0
  74. package/dist/commands/commitments/observations.d.ts +1 -0
  75. package/dist/commands/commitments/observations.js +19 -2
  76. package/dist/commands/commitments/pause.js +12 -0
  77. package/dist/commands/commitments/receipt.d.ts +2 -0
  78. package/dist/commands/commitments/receipt.js +16 -2
  79. package/dist/commands/commitments/remediation-proposal.js +6 -2
  80. package/dist/commands/commitments/remediation-proposals.js +5 -1
  81. package/dist/commands/commitments/restore.d.ts +25 -0
  82. package/dist/commands/commitments/restore.js +46 -0
  83. package/dist/commands/commitments/show.js +32 -0
  84. package/dist/commands/commitments/trigger-status.js +33 -0
  85. package/dist/commands/commitments/update.d.ts +1 -0
  86. package/dist/commands/commitments/update.js +31 -5
  87. package/dist/commands/commitments/wake-capabilities.d.ts +0 -1
  88. package/dist/commands/commitments/wake-capabilities.js +8 -4
  89. package/dist/commands/convos/handover.d.ts +1 -0
  90. package/dist/commands/convos/handover.js +4 -0
  91. package/dist/commands/daemon/index.js +2 -0
  92. package/dist/commands/daemon/update.d.ts +19 -0
  93. package/dist/commands/daemon/update.js +48 -0
  94. package/dist/commands/enterprise/budgets/create.d.ts +11 -0
  95. package/dist/commands/enterprise/budgets/create.js +27 -0
  96. package/dist/commands/enterprise/budgets/evaluate.d.ts +17 -0
  97. package/dist/commands/enterprise/budgets/evaluate.js +32 -0
  98. package/dist/commands/enterprise/budgets/publish.d.ts +14 -0
  99. package/dist/commands/enterprise/budgets/publish.js +30 -0
  100. package/dist/commands/enterprise/contracts/activate.d.ts +14 -0
  101. package/dist/commands/enterprise/contracts/activate.js +30 -0
  102. package/dist/commands/enterprise/contracts/create.d.ts +14 -0
  103. package/dist/commands/enterprise/contracts/create.js +32 -0
  104. package/dist/commands/enterprise/contracts/issue.d.ts +18 -0
  105. package/dist/commands/enterprise/contracts/issue.js +34 -0
  106. package/dist/commands/enterprise/domains/begin.d.ts +20 -0
  107. package/dist/commands/enterprise/domains/begin.js +39 -0
  108. package/dist/commands/enterprise/domains/verify.d.ts +14 -0
  109. package/dist/commands/enterprise/domains/verify.js +32 -0
  110. package/dist/commands/enterprise/external-config/activate.d.ts +22 -0
  111. package/dist/commands/enterprise/external-config/activate.js +49 -0
  112. package/dist/commands/enterprise/external-config/set.d.ts +25 -0
  113. package/dist/commands/enterprise/external-config/set.js +123 -0
  114. package/dist/commands/enterprise/external-config/show.d.ts +12 -0
  115. package/dist/commands/enterprise/external-config/show.js +39 -0
  116. package/dist/commands/enterprise/external-config/suspend.d.ts +13 -0
  117. package/dist/commands/enterprise/external-config/suspend.js +41 -0
  118. package/dist/commands/enterprise/finance/close-snapshot.d.ts +11 -0
  119. package/dist/commands/enterprise/finance/close-snapshot.js +28 -0
  120. package/dist/commands/enterprise/finance/record-document.d.ts +18 -0
  121. package/dist/commands/enterprise/finance/record-document.js +35 -0
  122. package/dist/commands/enterprise/profile.d.ts +20 -0
  123. package/dist/commands/enterprise/profile.js +38 -0
  124. package/dist/commands/login.d.ts +13 -0
  125. package/dist/commands/login.js +77 -0
  126. package/dist/commands/machines/dedicated/index.js +3 -0
  127. package/dist/commands/machines/dedicated/service/apply.d.ts +23 -0
  128. package/dist/commands/machines/dedicated/service/apply.js +99 -0
  129. package/dist/commands/machines/dedicated/service/approve.d.ts +23 -0
  130. package/dist/commands/machines/dedicated/service/approve.js +52 -0
  131. package/dist/commands/machines/dedicated/service/create.d.ts +55 -0
  132. package/dist/commands/machines/dedicated/service/create.js +222 -0
  133. package/dist/commands/machines/dedicated/service/edit.d.ts +30 -0
  134. package/dist/commands/machines/dedicated/service/edit.js +146 -0
  135. package/dist/commands/machines/dedicated/service/exec.d.ts +26 -0
  136. package/dist/commands/machines/dedicated/service/exec.js +92 -0
  137. package/dist/commands/machines/dedicated/service/export.d.ts +29 -0
  138. package/dist/commands/machines/dedicated/service/export.js +106 -0
  139. package/dist/commands/machines/dedicated/service/index.d.ts +14 -0
  140. package/dist/commands/machines/dedicated/service/index.js +49 -0
  141. package/dist/commands/machines/dedicated/service/logs.d.ts +33 -0
  142. package/dist/commands/machines/dedicated/service/logs.js +148 -0
  143. package/dist/commands/machines/dedicated/service/ls.d.ts +20 -0
  144. package/dist/commands/machines/dedicated/service/ls.js +80 -0
  145. package/dist/commands/machines/dedicated/service/restart.d.ts +14 -0
  146. package/dist/commands/machines/dedicated/service/restart.js +29 -0
  147. package/dist/commands/machines/dedicated/service/rm.d.ts +20 -0
  148. package/dist/commands/machines/dedicated/service/rm.js +33 -0
  149. package/dist/commands/machines/dedicated/service/secret/index.d.ts +14 -0
  150. package/dist/commands/machines/dedicated/service/secret/index.js +25 -0
  151. package/dist/commands/machines/dedicated/service/secret/rm.d.ts +22 -0
  152. package/dist/commands/machines/dedicated/service/secret/rm.js +54 -0
  153. package/dist/commands/machines/dedicated/service/secret/set.d.ts +22 -0
  154. package/dist/commands/machines/dedicated/service/secret/set.js +93 -0
  155. package/dist/commands/machines/dedicated/service/start.d.ts +14 -0
  156. package/dist/commands/machines/dedicated/service/start.js +29 -0
  157. package/dist/commands/machines/dedicated/service/status.d.ts +21 -0
  158. package/dist/commands/machines/dedicated/service/status.js +85 -0
  159. package/dist/commands/machines/dedicated/service/stop.d.ts +20 -0
  160. package/dist/commands/machines/dedicated/service/stop.js +35 -0
  161. package/dist/commands/machines/dedicated/service/top.d.ts +22 -0
  162. package/dist/commands/machines/dedicated/service/top.js +120 -0
  163. package/dist/commands/machines/dedicated/sign-in-status.d.ts +22 -0
  164. package/dist/commands/machines/dedicated/sign-in-status.js +79 -0
  165. package/dist/commands/machines/dedicated/ssh-config.d.ts +28 -0
  166. package/dist/commands/machines/dedicated/ssh-config.js +66 -0
  167. package/dist/commands/machines/dedicated/ssh-proxy.d.ts +22 -0
  168. package/dist/commands/machines/dedicated/ssh-proxy.js +62 -0
  169. package/dist/commands/machines/dedicated/ssh.d.ts +29 -0
  170. package/dist/commands/machines/dedicated/ssh.js +121 -0
  171. package/dist/commands/native/allow-all.d.ts +14 -0
  172. package/dist/commands/native/allow-all.js +25 -0
  173. package/dist/commands/native/allow.d.ts +24 -0
  174. package/dist/commands/native/allow.js +45 -0
  175. package/dist/commands/native/deny.d.ts +24 -0
  176. package/dist/commands/native/deny.js +43 -0
  177. package/dist/commands/native/disable.d.ts +17 -0
  178. package/dist/commands/native/disable.js +28 -0
  179. package/dist/commands/native/enable.d.ts +12 -0
  180. package/dist/commands/native/enable.js +29 -0
  181. package/dist/commands/native/list-apps.d.ts +19 -0
  182. package/dist/commands/native/list-apps.js +30 -0
  183. package/dist/commands/native/restrict-to.d.ts +22 -0
  184. package/dist/commands/native/restrict-to.js +41 -0
  185. package/dist/commands/native/status.d.ts +19 -0
  186. package/dist/commands/native/status.js +33 -0
  187. package/dist/commands/native.d.ts +39 -0
  188. package/dist/commands/native.js +76 -0
  189. package/dist/commands/service/index.d.ts +14 -0
  190. package/dist/commands/service/index.js +31 -0
  191. package/dist/commands/service/logs.d.ts +18 -0
  192. package/dist/commands/service/logs.js +53 -0
  193. package/dist/commands/service/ls.d.ts +13 -0
  194. package/dist/commands/service/ls.js +48 -0
  195. package/dist/commands/service/propose.d.ts +34 -0
  196. package/dist/commands/service/propose.js +113 -0
  197. package/dist/commands/service/status.d.ts +17 -0
  198. package/dist/commands/service/status.js +56 -0
  199. package/dist/commands/spaces/auto-executor/runs.d.ts +13 -0
  200. package/dist/commands/spaces/auto-executor/runs.js +56 -0
  201. package/dist/commands/spaces/briefs/get.js +8 -0
  202. package/dist/commands/spaces/briefs/list.js +2 -0
  203. package/dist/commands/spaces/briefs/set.d.ts +3 -0
  204. package/dist/commands/spaces/briefs/set.js +78 -13
  205. package/dist/commands/spaces/expertise-suggestions.d.ts +12 -0
  206. package/dist/commands/spaces/expertise-suggestions.js +71 -0
  207. package/dist/commands/spaces/members/add.d.ts +1 -0
  208. package/dist/commands/spaces/members/add.js +11 -3
  209. package/dist/commands/spaces/members/list.js +11 -0
  210. package/dist/commands/store/governance/artifacts.d.ts +25 -0
  211. package/dist/commands/store/governance/artifacts.js +55 -0
  212. package/dist/commands/store/governance/assign.d.ts +16 -0
  213. package/dist/commands/store/governance/assign.js +54 -0
  214. package/dist/commands/store/governance/create-license.d.ts +18 -0
  215. package/dist/commands/store/governance/create-license.js +35 -0
  216. package/dist/commands/store/governance/install-plan.d.ts +25 -0
  217. package/dist/commands/store/governance/install-plan.js +56 -0
  218. package/dist/commands/store/governance/license-policy.d.ts +30 -0
  219. package/dist/commands/store/governance/license-policy.js +69 -0
  220. package/dist/commands/store/governance/policy.d.ts +25 -0
  221. package/dist/commands/store/governance/policy.js +65 -0
  222. package/dist/commands/store/governance/publish-release.d.ts +17 -0
  223. package/dist/commands/store/governance/publish-release.js +34 -0
  224. package/dist/commands/tasks/assign.d.ts +9 -0
  225. package/dist/commands/tasks/assign.js +108 -1
  226. package/dist/commands/tasks/deliverable/add.d.ts +15 -0
  227. package/dist/commands/tasks/deliverable/add.js +174 -0
  228. package/dist/commands/tasks/deliverable/archive.d.ts +35 -0
  229. package/dist/commands/tasks/deliverable/archive.js +205 -0
  230. package/dist/commands/tasks/labels/detach.js +3 -0
  231. package/dist/commands/tasks/labels/suggest.d.ts +24 -0
  232. package/dist/commands/tasks/labels/suggest.js +69 -0
  233. package/dist/commands/tasks/list.d.ts +16 -2
  234. package/dist/commands/tasks/list.js +100 -24
  235. package/dist/commands/tasks/show.d.ts +23 -0
  236. package/dist/commands/tasks/show.js +51 -1
  237. package/dist/commands/wiki/rm.d.ts +22 -1
  238. package/dist/commands/wiki/rm.js +52 -3
  239. package/dist/lib/agentic-stream.js +10 -2
  240. package/dist/lib/assignee-resolver.d.ts +22 -0
  241. package/dist/lib/assignee-resolver.js +26 -0
  242. package/dist/lib/balance.d.ts +6 -1
  243. package/dist/lib/balance.js +15 -0
  244. package/dist/lib/code-handover.d.ts +0 -10
  245. package/dist/lib/code-handover.js +20 -5
  246. package/dist/lib/commerce-command.d.ts +48 -0
  247. package/dist/lib/commerce-command.js +70 -0
  248. package/dist/lib/commerce.d.ts +93 -0
  249. package/dist/lib/commerce.js +129 -0
  250. package/dist/lib/commitment-product.js +1 -1
  251. package/dist/lib/commitments.d.ts +202 -29
  252. package/dist/lib/commitments.js +300 -33
  253. package/dist/lib/dedicated-lease-command.js +10 -0
  254. package/dist/lib/dedicated-machines.d.ts +37 -0
  255. package/dist/lib/dedicated-machines.js +47 -0
  256. package/dist/lib/dedicated-service-command.d.ts +60 -0
  257. package/dist/lib/dedicated-service-command.js +182 -0
  258. package/dist/lib/dedicated-service.d.ts +342 -0
  259. package/dist/lib/dedicated-service.js +741 -0
  260. package/dist/lib/dedicated-ssh.d.ts +136 -0
  261. package/dist/lib/dedicated-ssh.js +387 -0
  262. package/dist/lib/delegated-cli.js +51 -13
  263. package/dist/lib/enterprise-commerce.d.ts +67 -0
  264. package/dist/lib/enterprise-commerce.js +112 -0
  265. package/dist/lib/enterprise-external-configuration.d.ts +60 -0
  266. package/dist/lib/enterprise-external-configuration.js +58 -0
  267. package/dist/lib/first-party-harness.js +17 -3
  268. package/dist/lib/governed-store.d.ts +110 -0
  269. package/dist/lib/governed-store.js +79 -0
  270. package/dist/lib/guest-service-command.d.ts +16 -0
  271. package/dist/lib/guest-service-command.js +32 -0
  272. package/dist/lib/guest-service.d.ts +67 -0
  273. package/dist/lib/guest-service.js +112 -0
  274. package/dist/lib/prompt.d.ts +1 -0
  275. package/dist/lib/prompt.js +1 -0
  276. package/dist/lib/task-asset-upload.d.ts +20 -0
  277. package/dist/lib/task-asset-upload.js +30 -8
  278. package/dist/lib/task-extras.d.ts +23 -0
  279. package/dist/lib/task-extras.js +6 -0
  280. package/dist/lib/update-check.d.ts +80 -7
  281. package/dist/lib/update-check.js +365 -33
  282. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/daemonScopes.d.ts +9 -3
  283. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/daemonScopes.js +10 -3
  284. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/firstPartyHarness.d.ts +9 -1
  285. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/firstPartyHarness.js +8 -0
  286. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/index.d.ts +1 -1
  287. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/index.js +6 -5
  288. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/messages.d.ts +16 -0
  289. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/messages.js +21 -4
  290. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/spawnEnv.d.ts +1 -1
  291. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/spawnEnv.js +24 -2
  292. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/daemonScopes.d.ts +9 -3
  293. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/daemonScopes.js +10 -3
  294. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/firstPartyHarness.d.ts +9 -1
  295. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/firstPartyHarness.js +8 -0
  296. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/index.d.ts +1 -1
  297. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/index.js +1 -1
  298. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/messages.d.ts +16 -0
  299. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/messages.js +20 -4
  300. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/spawnEnv.d.ts +1 -1
  301. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/spawnEnv.js +24 -2
  302. package/dist/node_modules/@skrr-ai/auth-core/package.json +1 -1
  303. package/dist/node_modules/@skrr-ai/data-provider/index.js +5067 -4821
  304. package/oclif.manifest.json +34877 -28659
  305. package/package.json +43 -1
@@ -0,0 +1,146 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const node_fs_1 = require("node:fs");
7
+ const node_os_1 = require("node:os");
8
+ const node_path_1 = __importDefault(require("node:path"));
9
+ const node_child_process_1 = require("node:child_process");
10
+ const core_1 = require("@oclif/core");
11
+ const dedicated_service_command_1 = require("../../../../lib/dedicated-service-command");
12
+ const dedicated_service_1 = require("../../../../lib/dedicated-service");
13
+ /** How many times a CAS conflict re-seeds the editor before giving up. */
14
+ const EDIT_CONFLICT_ROUNDS = 3;
15
+ /**
16
+ * `skrr machines dedicated service edit` — change a running declaration in
17
+ * $EDITOR, applied as a compare-and-swap update.
18
+ *
19
+ * The round-trip is honest about the race it cannot hide: the daemon owns the
20
+ * spec and increments `revision` on every write, so an edit made against a
21
+ * stale read is refused `conflict`, never merged. When that happens your edit
22
+ * is saved to a named file, the editor re-opens on the CURRENT spec, and you
23
+ * re-apply — three rounds, then the command gives up with the file named.
24
+ */
25
+ class DedicatedServiceEdit extends dedicated_service_command_1.DedicatedServiceCommand {
26
+ static summary = 'Edit a service spec in $EDITOR and apply it (CAS update)';
27
+ static examples = [
28
+ '<%= config.bin %> machines dedicated service edit <lease-id> <name>',
29
+ ];
30
+ static args = {
31
+ lease: core_1.Args.string({
32
+ description: dedicated_service_command_1.SERVICE_LEASE_ARG_DESCRIPTION,
33
+ required: true,
34
+ ignoreStdin: true,
35
+ }),
36
+ name: core_1.Args.string({ description: 'Service name', required: true, ignoreStdin: true }),
37
+ };
38
+ static flags = {
39
+ editor: core_1.Flags.string({ description: 'Editor to use (default $VISUAL, $EDITOR, then vi)' }),
40
+ json: core_1.Flags.boolean({ description: 'Output the updated spec as JSON' }),
41
+ };
42
+ async run() {
43
+ this.requireAuth();
44
+ const { args, flags } = await this.parse(DedicatedServiceEdit);
45
+ const leaseId = await this.resolveLeaseArg(args.lease);
46
+ const editor = flags.editor ?? process.env.VISUAL ?? process.env.EDITOR ?? 'vi';
47
+ const channel = await this.serviceChannel();
48
+ const dir = (0, node_fs_1.mkdtempSync)(node_path_1.default.join((0, node_os_1.tmpdir)(), 'skrr-svc-edit-'));
49
+ const file = node_path_1.default.join(dir, `${args.name}.json`);
50
+ // Set on every path that NAMES the temp file for the user — an error that
51
+ // says "your edit is at <file>" must leave the file standing.
52
+ let keepDir = false;
53
+ try {
54
+ for (let round = 1; round <= EDIT_CONFLICT_ROUNDS; round += 1) {
55
+ const { result } = await channel.call('get', {
56
+ leaseId,
57
+ name: args.name,
58
+ ...this.scopeFrom(flags),
59
+ });
60
+ const spec = result?.spec;
61
+ if (!spec) {
62
+ this.error(`No service named ${args.name} on ${leaseId}.`, { exit: 1 });
63
+ }
64
+ const baseRevision = typeof spec.revision === 'number' ? spec.revision : undefined;
65
+ (0, node_fs_1.writeFileSync)(file, `${JSON.stringify(spec, null, 2)}\n`);
66
+ const edited = await this.editFile(file, editor);
67
+ if (edited === null) {
68
+ this.log('Unchanged — nothing applied.');
69
+ return;
70
+ }
71
+ let next;
72
+ try {
73
+ next = (0, dedicated_service_1.parseServiceSpecDocument)(edited, file);
74
+ }
75
+ catch (err) {
76
+ keepDir = true;
77
+ // Keep the file so the person can fix it by hand and apply it.
78
+ this.error(`${err instanceof Error ? err.message : err}\nYour edit is still at ${file} — fix it and run \`${this.config.bin} machines dedicated service apply ${leaseId} --file ${file}\`, or re-run edit.`, { exit: 2 });
79
+ }
80
+ try {
81
+ const { result: updated } = await channel.call('update', {
82
+ leaseId,
83
+ name: args.name,
84
+ patch: (0, dedicated_service_1.specPayload)(next),
85
+ baseRevision,
86
+ ...this.scopeFrom(flags),
87
+ });
88
+ this.closeServiceChannel();
89
+ if (flags.json) {
90
+ this.log(JSON.stringify(updated ?? (0, dedicated_service_1.specPayload)(next), null, 2));
91
+ return;
92
+ }
93
+ this.log(`Service ${args.name} updated on ${leaseId}.`);
94
+ return;
95
+ }
96
+ catch (err) {
97
+ if (!(err instanceof dedicated_service_1.DedicatedServiceError && err.code === 'conflict')) {
98
+ this.reportServiceError(err);
99
+ }
100
+ // CAS lost: preserve the edit, say where, and re-seed the editor
101
+ // with the spec as it actually is now.
102
+ const rejected = `${file}.rejected-${round}.json`;
103
+ (0, node_fs_1.writeFileSync)(rejected, edited);
104
+ if (round === EDIT_CONFLICT_ROUNDS) {
105
+ keepDir = true;
106
+ this.error(`The spec changed underneath the edit ${EDIT_CONFLICT_ROUNDS} times in a row. ` +
107
+ `Your last edit is at ${rejected} — apply it by hand with \`${this.config.bin} machines dedicated service apply ${leaseId} --file ${rejected}\` once the machine settles.`, { exit: 1 });
108
+ }
109
+ keepDir = true;
110
+ process.stderr.write(`[edit] the spec changed since you opened it; your edit is saved at ${rejected} and the editor re-opens on the current spec.\n`);
111
+ }
112
+ }
113
+ }
114
+ finally {
115
+ if (!keepDir) {
116
+ try {
117
+ (0, node_fs_1.rmSync)(dir, { recursive: true, force: true });
118
+ }
119
+ catch {
120
+ /* a file the user still needs is worth more than a clean tmpdir */
121
+ }
122
+ }
123
+ }
124
+ }
125
+ /**
126
+ * Run the editor over the temp file. Returns the new contents, or null when
127
+ * the file is byte-identical — an unopened or untouched edit applies
128
+ * nothing, which is the honest answer to "I looked and left".
129
+ */
130
+ async editFile(file, editor) {
131
+ const before = (0, node_fs_1.readFileSync)(file, 'utf8');
132
+ // sh -c so "code --wait" and friends work as one flag value.
133
+ const spawned = (0, node_child_process_1.spawnSync)('sh', ['-c', `${editor} "$1"`, 'sh', file], {
134
+ stdio: 'inherit',
135
+ });
136
+ if (spawned.error) {
137
+ this.error(`Could not run ${editor}: ${spawned.error.message}`, { exit: 1 });
138
+ }
139
+ if (spawned.status !== 0) {
140
+ this.error(`${editor} exited ${spawned.status}; nothing was applied.`, { exit: 1 });
141
+ }
142
+ const after = (0, node_fs_1.readFileSync)(file, 'utf8');
143
+ return after === before ? null : after;
144
+ }
145
+ }
146
+ exports.default = DedicatedServiceEdit;
@@ -0,0 +1,26 @@
1
+ import { DedicatedServiceCommand } from '../../../../lib/dedicated-service-command';
2
+ /**
3
+ * `skrr machines dedicated service exec` — a one-off command inside a
4
+ * service's context (phase 2).
5
+ *
6
+ * The spawn carries the service's cwd, env and cgroup scope, so it lands in
7
+ * the service's process tree and shares its fate — the honest way to debug a
8
+ * service whose environment the daemon holds. A daemon that predates the
9
+ * extension refuses cleanly; `machines dedicated exec` is the always-there
10
+ * fallback for ad-hoc commands.
11
+ */
12
+ export default class DedicatedServiceExec extends DedicatedServiceCommand {
13
+ static summary: string;
14
+ static examples: string[];
15
+ static usage: string;
16
+ static args: {
17
+ lease: import("@oclif/core/lib/interfaces").Arg<string, Record<string, unknown>>;
18
+ name: import("@oclif/core/lib/interfaces").Arg<string, Record<string, unknown>>;
19
+ command: import("@oclif/core/lib/interfaces").Arg<string[] | undefined, Record<string, unknown>>;
20
+ };
21
+ static flags: {
22
+ json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
23
+ timeout: import("@oclif/core/lib/interfaces").OptionFlag<number | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
24
+ };
25
+ run(): Promise<void>;
26
+ }
@@ -0,0 +1,92 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const core_1 = require("@oclif/core");
4
+ const dedicated_service_command_1 = require("../../../../lib/dedicated-service-command");
5
+ const exec_1 = require("../../hosted/exec");
6
+ /**
7
+ * `skrr machines dedicated service exec` — a one-off command inside a
8
+ * service's context (phase 2).
9
+ *
10
+ * The spawn carries the service's cwd, env and cgroup scope, so it lands in
11
+ * the service's process tree and shares its fate — the honest way to debug a
12
+ * service whose environment the daemon holds. A daemon that predates the
13
+ * extension refuses cleanly; `machines dedicated exec` is the always-there
14
+ * fallback for ad-hoc commands.
15
+ */
16
+ class DedicatedServiceExec extends dedicated_service_command_1.DedicatedServiceCommand {
17
+ static summary = 'Run a one-off command in a service’s context (phase 2)';
18
+ static examples = [
19
+ '<%= config.bin %> machines dedicated service exec <lease-id> <name> -- printenv',
20
+ '<%= config.bin %> machines dedicated service exec <lease-id> <name> -- cat /workspace/services/name/state.json',
21
+ ];
22
+ static usage = 'machines dedicated service exec <lease-id> <name> -- <command...>';
23
+ static args = {
24
+ lease: core_1.Args.string({
25
+ description: dedicated_service_command_1.SERVICE_LEASE_ARG_DESCRIPTION,
26
+ required: true,
27
+ ignoreStdin: true,
28
+ }),
29
+ name: core_1.Args.string({ description: 'Service name', required: true, ignoreStdin: true }),
30
+ command: core_1.Args.string({
31
+ description: 'The command and its arguments, after --',
32
+ multiple: true,
33
+ required: false,
34
+ ignoreStdin: true,
35
+ }),
36
+ };
37
+ static flags = {
38
+ json: core_1.Flags.boolean({ description: 'Output the result as JSON' }),
39
+ timeout: core_1.Flags.integer({
40
+ description: 'Seconds the command may run on the machine (1-600, default 300)',
41
+ min: 1,
42
+ max: 600,
43
+ }),
44
+ };
45
+ async run() {
46
+ this.requireAuth();
47
+ const { head, tail } = (0, exec_1.splitExecArgv)(this.argv);
48
+ const { args, flags } = await this.parse(DedicatedServiceExec, head);
49
+ const argv = tail ?? args.command ?? [];
50
+ if (argv.length === 0) {
51
+ this.error('Command is required — pass it after --.', { exit: 2 });
52
+ }
53
+ const leaseId = await this.resolveLeaseArg(args.lease);
54
+ // Phase-2 verb: `dedicated:service:exec {leaseId, name, argv}`. A daemon
55
+ // without the extension answers with the unsupported path — the command
56
+ // degrades, it does not improvise.
57
+ const timeoutSeconds = flags.timeout ?? 300;
58
+ const result = await this.callService('exec', {
59
+ leaseId,
60
+ name: args.name,
61
+ argv,
62
+ timeoutSeconds,
63
+ ...this.scopeFrom(flags),
64
+ },
65
+ // The relay waits timeoutSeconds+30s; the caller must outlive that or a
66
+ // legitimately long exec reports a false connectivity failure.
67
+ (timeoutSeconds + 45) * 1000);
68
+ this.closeServiceChannel();
69
+ if (flags.json) {
70
+ this.log(JSON.stringify(result ?? {}, null, 2));
71
+ }
72
+ else {
73
+ // Binary-safe: the wire contract is base64 — write the decoded bytes
74
+ // verbatim; a debug verb that utf8-mangles or appends newlines lies
75
+ // about what the service emitted.
76
+ const stdout = result?.stdoutBase64
77
+ ? Buffer.from(result.stdoutBase64, 'base64')
78
+ : Buffer.from(result?.stdout ?? '', 'utf8');
79
+ const stderr = result?.stderrBase64
80
+ ? Buffer.from(result.stderrBase64, 'base64')
81
+ : Buffer.from(result?.stderr ?? '', 'utf8');
82
+ if (stdout.length > 0)
83
+ process.stdout.write(stdout);
84
+ if (stderr.length > 0)
85
+ process.stderr.write(stderr);
86
+ }
87
+ const exitCode = typeof result?.exitCode === 'number' ? result.exitCode : 0;
88
+ if (exitCode !== 0)
89
+ this.exit(exitCode);
90
+ }
91
+ }
92
+ exports.default = DedicatedServiceExec;
@@ -0,0 +1,29 @@
1
+ import { DedicatedServiceCommand } from '../../../../lib/dedicated-service-command';
2
+ /** Shape written by `service export` and accepted by `service apply --file`. */
3
+ export declare const SERVICE_SPEC_EXPORT_VERSION = 1;
4
+ /**
5
+ * `skrr machines dedicated service export` — the stored spec as a repo
6
+ * `service.json` (phase 2).
7
+ *
8
+ * The artifact is the apply-able document: the daemon's bookkeeping
9
+ * (`revision`, `createdBy`, timestamps) is stripped, forward fields are kept
10
+ * verbatim, so `--output service.json` is exactly what
11
+ * `service apply --file service.json` takes on this machine or another one.
12
+ * Like every export verb it asks for a destination — `--summary`,
13
+ * `--output <path>` or `--output -` for deliberate stdout — rather than
14
+ * spilling a spec onto the terminal because a flag was forgotten.
15
+ */
16
+ export default class DedicatedServiceExport extends DedicatedServiceCommand {
17
+ static summary: string;
18
+ static examples: string[];
19
+ static args: {
20
+ lease: import("@oclif/core/lib/interfaces").Arg<string, Record<string, unknown>>;
21
+ name: import("@oclif/core/lib/interfaces").Arg<string, Record<string, unknown>>;
22
+ };
23
+ static flags: {
24
+ summary: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
25
+ output: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
26
+ json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
27
+ };
28
+ run(): Promise<void>;
29
+ }
@@ -0,0 +1,106 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SERVICE_SPEC_EXPORT_VERSION = void 0;
4
+ const core_1 = require("@oclif/core");
5
+ const dedicated_service_command_1 = require("../../../../lib/dedicated-service-command");
6
+ const dedicated_service_1 = require("../../../../lib/dedicated-service");
7
+ const artifact_export_1 = require("../../../../lib/artifact-export");
8
+ /** Shape written by `service export` and accepted by `service apply --file`. */
9
+ exports.SERVICE_SPEC_EXPORT_VERSION = 1;
10
+ /**
11
+ * `skrr machines dedicated service export` — the stored spec as a repo
12
+ * `service.json` (phase 2).
13
+ *
14
+ * The artifact is the apply-able document: the daemon's bookkeeping
15
+ * (`revision`, `createdBy`, timestamps) is stripped, forward fields are kept
16
+ * verbatim, so `--output service.json` is exactly what
17
+ * `service apply --file service.json` takes on this machine or another one.
18
+ * Like every export verb it asks for a destination — `--summary`,
19
+ * `--output <path>` or `--output -` for deliberate stdout — rather than
20
+ * spilling a spec onto the terminal because a flag was forgotten.
21
+ */
22
+ class DedicatedServiceExport extends dedicated_service_command_1.DedicatedServiceCommand {
23
+ static summary = 'Export a stored spec in the repo service.json form';
24
+ static examples = [
25
+ '<%= config.bin %> machines dedicated service export <lease-id> <name> --output service.json',
26
+ '<%= config.bin %> machines dedicated service export <lease-id> <name> --output - | jq .',
27
+ '<%= config.bin %> machines dedicated service export <lease-id> <name> --summary',
28
+ ];
29
+ static args = {
30
+ lease: core_1.Args.string({
31
+ description: dedicated_service_command_1.SERVICE_LEASE_ARG_DESCRIPTION,
32
+ required: true,
33
+ ignoreStdin: true,
34
+ }),
35
+ name: core_1.Args.string({ description: 'Service name', required: true, ignoreStdin: true }),
36
+ };
37
+ static flags = {
38
+ ...(0, artifact_export_1.standardExportFlags)(),
39
+ };
40
+ async run() {
41
+ this.requireAuth();
42
+ const { args, flags } = await this.parse(DedicatedServiceExport);
43
+ let selection;
44
+ try {
45
+ selection = (0, artifact_export_1.resolveExportSelection)(flags);
46
+ }
47
+ catch (err) {
48
+ if (err instanceof artifact_export_1.ExportContractError) {
49
+ this.failWithCliError({
50
+ message: err.message,
51
+ code: err.code,
52
+ exit: 2,
53
+ retryable: false,
54
+ });
55
+ }
56
+ throw err;
57
+ }
58
+ const leaseId = await this.resolveLeaseArg(args.lease);
59
+ const result = await this.callService('get', {
60
+ leaseId,
61
+ name: args.name,
62
+ ...this.scopeFrom(flags),
63
+ });
64
+ this.closeServiceChannel();
65
+ if (!result?.spec) {
66
+ this.error(`No service named ${args.name} on ${leaseId}.`, { exit: 1 });
67
+ }
68
+ if (selection.summary) {
69
+ const summary = (0, artifact_export_1.contentFreeSummary)({
70
+ command: 'machines dedicated service export',
71
+ artifactSchemaVersion: exports.SERVICE_SPEC_EXPORT_VERSION,
72
+ itemCount: 1,
73
+ counts: { services: 1 },
74
+ });
75
+ this.log(selection.json ? JSON.stringify(summary, null, 2) : (0, artifact_export_1.humanExportSummary)(summary));
76
+ return;
77
+ }
78
+ const serialized = (0, artifact_export_1.serializedArtifact)((0, dedicated_service_1.specExportDocument)(result.spec));
79
+ if (selection.output === '-') {
80
+ this.log(serialized.trimEnd());
81
+ return;
82
+ }
83
+ let receipt;
84
+ try {
85
+ receipt = await (0, artifact_export_1.writeExportArtifact)({
86
+ command: 'machines dedicated service export',
87
+ artifactSchemaVersion: exports.SERVICE_SPEC_EXPORT_VERSION,
88
+ format: 'json',
89
+ output: selection.output,
90
+ content: serialized,
91
+ itemCount: 1,
92
+ });
93
+ }
94
+ catch (err) {
95
+ this.failWithCliError({
96
+ message: `Could not write ${selection.output}: ${err.message}`,
97
+ code: 'SERVICE_SPEC_EXPORT_WRITE_FAILED',
98
+ exit: 1,
99
+ retryable: false,
100
+ details: { path: selection.output },
101
+ });
102
+ }
103
+ this.log(selection.json ? JSON.stringify(receipt, null, 2) : (0, artifact_export_1.humanExportReceipt)(receipt));
104
+ }
105
+ }
106
+ exports.default = DedicatedServiceExport;
@@ -0,0 +1,14 @@
1
+ import { Command } from '@oclif/core';
2
+ /**
3
+ * `skrr machines dedicated service` — declared, always-on workloads.
4
+ *
5
+ * A detached process dies at every machine boundary; a declared service is
6
+ * restarted by the machine's daemon across crashes, daemon restarts,
7
+ * checkpoints, stop→start and instance replacement. This topic is how the
8
+ * owner declares them.
9
+ */
10
+ export default class DedicatedMachinesService extends Command {
11
+ static description: string;
12
+ static examples: string[];
13
+ run(): Promise<void>;
14
+ }
@@ -0,0 +1,49 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const core_1 = require("@oclif/core");
4
+ /**
5
+ * `skrr machines dedicated service` — declared, always-on workloads.
6
+ *
7
+ * A detached process dies at every machine boundary; a declared service is
8
+ * restarted by the machine's daemon across crashes, daemon restarts,
9
+ * checkpoints, stop→start and instance replacement. This topic is how the
10
+ * owner declares them.
11
+ */
12
+ class DedicatedMachinesService extends core_1.Command {
13
+ static description = 'Declared services on a Dedicated Runtime — workloads the machine keeps running across restarts, checkpoints and replacements';
14
+ static examples = [
15
+ '<%= config.bin %> machines dedicated service create <lease-id> --name worker --cwd /workspace/repos/app -- node dist/worker.js',
16
+ '<%= config.bin %> machines dedicated service apply <lease-id> --file service.json',
17
+ '<%= config.bin %> machines dedicated service ls <lease-id>',
18
+ '<%= config.bin %> machines dedicated service status <lease-id> <name>',
19
+ '<%= config.bin %> machines dedicated service logs <lease-id> <name> -f',
20
+ '<%= config.bin %> machines dedicated service approve <lease-id> <name>',
21
+ ];
22
+ async run() {
23
+ const rows = [
24
+ ['create', 'declare a service (argv after --, or --file service.json)'],
25
+ ['apply', 'create or update a service from a spec file, idempotently'],
26
+ ['ls', 'list services and pending agent proposals'],
27
+ ['status', 'one service: spec, computed status and recent exits'],
28
+ ['edit', 'edit the spec in $EDITOR and apply it (CAS update)'],
29
+ ['logs', 'print a service log; -f follows'],
30
+ ['start', 'set desired state to running'],
31
+ ['stop', 'set desired state to stopped; survives machine restarts'],
32
+ ['restart', 'restart the service now'],
33
+ ['rm', 'remove the declaration'],
34
+ ['approve', 'approve (--reject to refuse) an agent-proposed service'],
35
+ ['exec', 'run a one-off command inside a service’s context (phase 2)'],
36
+ ['top', 'per-service cpu/mem/pids (phase 2)'],
37
+ ['export', 'print the repo service.json form of a stored spec'],
38
+ ['secret', 'set or remove a secret a spec can reference (phase 2)'],
39
+ ];
40
+ this.log('skrr machines dedicated service commands:');
41
+ for (const [name, summary] of rows) {
42
+ this.log(` skrr machines dedicated service ${name.padEnd(8)} ${summary}`);
43
+ }
44
+ this.log('');
45
+ this.log('Every command takes a lease id (or `self` on the machine) and --json. ' +
46
+ 'Agents on the machine propose services instead: `skrr service propose`.');
47
+ }
48
+ }
49
+ exports.default = DedicatedMachinesService;
@@ -0,0 +1,33 @@
1
+ import { DedicatedServiceCommand } from '../../../../lib/dedicated-service-command';
2
+ /**
3
+ * `skrr machines dedicated service logs` — tail the service's log, or follow it.
4
+ *
5
+ * The daemon rotates a bounded `current` log per service; `logs` replays a
6
+ * byte tail of it and `-f` keeps the stream open on live
7
+ * `dedicated:service:log` frames. Ctrl-C ends the follow cleanly — the
8
+ * stream is closed with `logs:stop`, the service keeps running.
9
+ *
10
+ * While a follow is open, an agent proposal arriving on the same channel is
11
+ * surfaced on stderr: the owner watching logs is exactly the owner who can
12
+ * approve it.
13
+ */
14
+ export default class DedicatedServiceLogs extends DedicatedServiceCommand {
15
+ static summary: string;
16
+ static examples: string[];
17
+ static args: {
18
+ lease: import("@oclif/core/lib/interfaces").Arg<string, Record<string, unknown>>;
19
+ name: import("@oclif/core/lib/interfaces").Arg<string, Record<string, unknown>>;
20
+ };
21
+ static flags: {
22
+ follow: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
23
+ tail: import("@oclif/core/lib/interfaces").OptionFlag<number | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
24
+ json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
25
+ };
26
+ run(): Promise<void>;
27
+ /**
28
+ * The machine-readable follow: each log frame is one JSON line. An ack's
29
+ * refusal surfaces through the same channel.call error path as every other
30
+ * verb (a `--json` caller reads the CLI error envelope).
31
+ */
32
+ private followJson;
33
+ }
@@ -0,0 +1,148 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const core_1 = require("@oclif/core");
4
+ const dedicated_service_command_1 = require("../../../../lib/dedicated-service-command");
5
+ const dedicated_service_1 = require("../../../../lib/dedicated-service");
6
+ /**
7
+ * `skrr machines dedicated service logs` — tail the service's log, or follow it.
8
+ *
9
+ * The daemon rotates a bounded `current` log per service; `logs` replays a
10
+ * byte tail of it and `-f` keeps the stream open on live
11
+ * `dedicated:service:log` frames. Ctrl-C ends the follow cleanly — the
12
+ * stream is closed with `logs:stop`, the service keeps running.
13
+ *
14
+ * While a follow is open, an agent proposal arriving on the same channel is
15
+ * surfaced on stderr: the owner watching logs is exactly the owner who can
16
+ * approve it.
17
+ */
18
+ class DedicatedServiceLogs extends dedicated_service_command_1.DedicatedServiceCommand {
19
+ static summary = 'Print a service’s log; -f follows live output';
20
+ static examples = [
21
+ '<%= config.bin %> machines dedicated service logs <lease-id> <name>',
22
+ '<%= config.bin %> machines dedicated service logs <lease-id> <name> -f',
23
+ '<%= config.bin %> machines dedicated service logs <lease-id> <name> --tail 65536',
24
+ ];
25
+ static args = {
26
+ lease: core_1.Args.string({
27
+ description: dedicated_service_command_1.SERVICE_LEASE_ARG_DESCRIPTION,
28
+ required: true,
29
+ ignoreStdin: true,
30
+ }),
31
+ name: core_1.Args.string({ description: 'Service name', required: true, ignoreStdin: true }),
32
+ };
33
+ static flags = {
34
+ follow: core_1.Flags.boolean({
35
+ description: 'Keep the stream open on live log frames (Ctrl-C ends the follow, not the service)',
36
+ char: 'f',
37
+ }),
38
+ tail: core_1.Flags.integer({
39
+ description: 'Bytes from the end of the stored log to print first (daemon rotates at 8 MiB)',
40
+ min: 0,
41
+ }),
42
+ json: core_1.Flags.boolean({ description: 'Emit log frames as JSON objects' }),
43
+ };
44
+ async run() {
45
+ this.requireAuth();
46
+ const { args, flags } = await this.parse(DedicatedServiceLogs);
47
+ const leaseId = await this.resolveLeaseArg(args.lease);
48
+ if (flags.json) {
49
+ // --json emits one frame per line — a follow a program can consume.
50
+ // Proposals surface as frames too rather than stderr prose.
51
+ const code = await this.followJson(leaseId, args.name, flags);
52
+ if (code !== 0)
53
+ this.exit(code);
54
+ return;
55
+ }
56
+ let code;
57
+ try {
58
+ code = await (0, dedicated_service_1.streamServiceLogs)({
59
+ baseURL: this.cliConfig.baseURL,
60
+ token: this.resolvedCredential.token,
61
+ leaseId,
62
+ name: args.name,
63
+ follow: flags.follow,
64
+ tailBytes: flags.tail,
65
+ output: process.stdout,
66
+ errorOutput: process.stderr,
67
+ });
68
+ }
69
+ catch (err) {
70
+ this.reportServiceError(err);
71
+ }
72
+ if (code !== 0)
73
+ this.exit(code);
74
+ }
75
+ /**
76
+ * The machine-readable follow: each log frame is one JSON line. An ack's
77
+ * refusal surfaces through the same channel.call error path as every other
78
+ * verb (a `--json` caller reads the CLI error envelope).
79
+ */
80
+ async followJson(leaseId, name, flags) {
81
+ const channel = new dedicated_service_1.DedicatedServiceChannel({
82
+ baseURL: this.cliConfig.baseURL,
83
+ token: this.resolvedCredential.token,
84
+ });
85
+ return new Promise((resolve, reject) => {
86
+ let streamId = null;
87
+ let finished = false;
88
+ let closedByServer = false;
89
+ const onSigint = () => finish(0);
90
+ const finish = (code) => {
91
+ if (finished)
92
+ return;
93
+ finished = true;
94
+ process.off('SIGINT', onSigint);
95
+ if (streamId && flags.follow && !closedByServer) {
96
+ channel.send(dedicated_service_1.DEDICATED_SERVICE_EVENTS.logsStop, { leaseId, name, streamId });
97
+ }
98
+ channel.close();
99
+ resolve(code);
100
+ };
101
+ channel.setOnDead(() => finish(1));
102
+ channel
103
+ .open()
104
+ .then(async () => {
105
+ process.on('SIGINT', onSigint);
106
+ channel.on(dedicated_service_1.DEDICATED_SERVICE_EVENTS.log, (frame) => {
107
+ if (streamId && frame.streamId && frame.streamId !== streamId)
108
+ return;
109
+ if (frame.name && frame.name !== name)
110
+ return;
111
+ this.log(JSON.stringify({ type: 'log', ...frame }));
112
+ });
113
+ channel.on(dedicated_service_1.DEDICATED_SERVICE_EVENTS.logClosed, (frame) => {
114
+ if (streamId && frame.streamId && frame.streamId !== streamId)
115
+ return;
116
+ closedByServer = true;
117
+ this.log(JSON.stringify({ type: 'closed', ...frame }));
118
+ finish(0);
119
+ });
120
+ channel.on(dedicated_service_1.DEDICATED_SERVICE_EVENTS.proposed, (frame) => {
121
+ this.log(JSON.stringify({ type: 'proposed', ...frame }));
122
+ });
123
+ const { result } = await channel.call('logs', {
124
+ leaseId,
125
+ name,
126
+ follow: flags.follow,
127
+ ...(flags.tail !== undefined ? { tailBytes: flags.tail } : {}),
128
+ ...this.scopeFrom(flags),
129
+ });
130
+ streamId = typeof result?.streamId === 'string' ? result.streamId : null;
131
+ if (typeof result?.data === 'string' && result.data.length > 0) {
132
+ this.log(JSON.stringify({ type: 'tail', name, data: result.data }));
133
+ }
134
+ if (!flags.follow)
135
+ finish(0);
136
+ })
137
+ .catch((err) => {
138
+ // Reject BEFORE closing — disconnect() fires onDead → finish(1),
139
+ // which would otherwise win the settlement race and mask the refusal.
140
+ finished = true;
141
+ process.off('SIGINT', onSigint);
142
+ reject(err);
143
+ channel.close();
144
+ });
145
+ });
146
+ }
147
+ }
148
+ exports.default = DedicatedServiceLogs;