@skrr-ai/cli 0.1.47 → 0.1.49

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 (286) 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/agent-worker.d.ts +12 -0
  5. package/dist/commands/agent-worker.js +140 -0
  6. package/dist/commands/agents/chat.d.ts +21 -0
  7. package/dist/commands/agents/chat.js +26 -9
  8. package/dist/commands/balance/usage/breakdown.d.ts +14 -0
  9. package/dist/commands/balance/usage/breakdown.js +68 -0
  10. package/dist/commands/balance/usage.js +24 -0
  11. package/dist/commands/commerce/entitlements/explain.d.ts +22 -0
  12. package/dist/commands/commerce/entitlements/explain.js +40 -0
  13. package/dist/commands/commerce/incidents/audit.d.ts +20 -0
  14. package/dist/commands/commerce/incidents/audit.js +37 -0
  15. package/dist/commands/commerce/incidents/list.d.ts +22 -0
  16. package/dist/commands/commerce/incidents/list.js +49 -0
  17. package/dist/commands/commerce/incidents/resolve.d.ts +23 -0
  18. package/dist/commands/commerce/incidents/resolve.js +45 -0
  19. package/dist/commands/commerce/incidents/retry.d.ts +22 -0
  20. package/dist/commands/commerce/incidents/retry.js +45 -0
  21. package/dist/commands/commerce/incidents/show.d.ts +13 -0
  22. package/dist/commands/commerce/incidents/show.js +30 -0
  23. package/dist/commands/commerce/offers/approve.d.ts +17 -0
  24. package/dist/commands/commerce/offers/approve.js +33 -0
  25. package/dist/commands/commerce/offers/create.d.ts +18 -0
  26. package/dist/commands/commerce/offers/create.js +34 -0
  27. package/dist/commands/commerce/offers/publish.d.ts +13 -0
  28. package/dist/commands/commerce/offers/publish.js +28 -0
  29. package/dist/commands/commerce/offers/retire.d.ts +17 -0
  30. package/dist/commands/commerce/offers/retire.js +32 -0
  31. package/dist/commands/commerce/offers/validate.d.ts +18 -0
  32. package/dist/commands/commerce/offers/validate.js +33 -0
  33. package/dist/commands/commerce/products/create.d.ts +10 -0
  34. package/dist/commands/commerce/products/create.js +25 -0
  35. package/dist/commands/commerce/promotions/redeem.d.ts +13 -0
  36. package/dist/commands/commerce/promotions/redeem.js +32 -0
  37. package/dist/commands/commerce/terms/accept.d.ts +18 -0
  38. package/dist/commands/commerce/terms/accept.js +39 -0
  39. package/dist/commands/commerce/terms/show.d.ts +10 -0
  40. package/dist/commands/commerce/terms/show.js +34 -0
  41. package/dist/commands/commerce/trials/conversion-preview.d.ts +18 -0
  42. package/dist/commands/commerce/trials/conversion-preview.js +39 -0
  43. package/dist/commands/commerce/trials/start.d.ts +23 -0
  44. package/dist/commands/commerce/trials/start.js +58 -0
  45. package/dist/commands/commitments/accounting.d.ts +39 -0
  46. package/dist/commands/commitments/accounting.js +116 -0
  47. package/dist/commands/commitments/action-history.d.ts +1 -0
  48. package/dist/commands/commitments/action-history.js +8 -1
  49. package/dist/commands/commitments/case.d.ts +1 -0
  50. package/dist/commands/commitments/case.js +19 -3
  51. package/dist/commands/commitments/cases.d.ts +1 -0
  52. package/dist/commands/commitments/cases.js +11 -1
  53. package/dist/commands/commitments/checks.d.ts +1 -0
  54. package/dist/commands/commitments/checks.js +5 -1
  55. package/dist/commands/commitments/cost.d.ts +62 -0
  56. package/dist/commands/commitments/cost.js +130 -0
  57. package/dist/commands/commitments/create.js +1 -1
  58. package/dist/commands/commitments/delete.d.ts +1 -0
  59. package/dist/commands/commitments/delete.js +56 -6
  60. package/dist/commands/commitments/feedback.js +9 -1
  61. package/dist/commands/commitments/handover.js +16 -0
  62. package/dist/commands/commitments/hypotheses.d.ts +1 -0
  63. package/dist/commands/commitments/hypotheses.js +17 -2
  64. package/dist/commands/commitments/links/list.js +4 -1
  65. package/dist/commands/commitments/liveness.d.ts +18 -0
  66. package/dist/commands/commitments/liveness.js +80 -0
  67. package/dist/commands/commitments/metrics.d.ts +1 -0
  68. package/dist/commands/commitments/metrics.js +8 -1
  69. package/dist/commands/commitments/next-tick.d.ts +39 -0
  70. package/dist/commands/commitments/next-tick.js +122 -0
  71. package/dist/commands/commitments/observations.d.ts +1 -0
  72. package/dist/commands/commitments/observations.js +19 -2
  73. package/dist/commands/commitments/pause.js +12 -0
  74. package/dist/commands/commitments/receipt.d.ts +2 -0
  75. package/dist/commands/commitments/receipt.js +16 -2
  76. package/dist/commands/commitments/remediation-proposal.js +6 -2
  77. package/dist/commands/commitments/remediation-proposals.js +5 -1
  78. package/dist/commands/commitments/restore.d.ts +25 -0
  79. package/dist/commands/commitments/restore.js +46 -0
  80. package/dist/commands/commitments/show.js +32 -0
  81. package/dist/commands/commitments/trigger-status.js +33 -0
  82. package/dist/commands/commitments/update.d.ts +1 -0
  83. package/dist/commands/commitments/update.js +31 -5
  84. package/dist/commands/commitments/wake-capabilities.d.ts +0 -1
  85. package/dist/commands/commitments/wake-capabilities.js +8 -4
  86. package/dist/commands/enterprise/budgets/create.d.ts +11 -0
  87. package/dist/commands/enterprise/budgets/create.js +27 -0
  88. package/dist/commands/enterprise/budgets/evaluate.d.ts +17 -0
  89. package/dist/commands/enterprise/budgets/evaluate.js +32 -0
  90. package/dist/commands/enterprise/budgets/publish.d.ts +14 -0
  91. package/dist/commands/enterprise/budgets/publish.js +30 -0
  92. package/dist/commands/enterprise/contracts/activate.d.ts +14 -0
  93. package/dist/commands/enterprise/contracts/activate.js +30 -0
  94. package/dist/commands/enterprise/contracts/create.d.ts +14 -0
  95. package/dist/commands/enterprise/contracts/create.js +32 -0
  96. package/dist/commands/enterprise/contracts/issue.d.ts +18 -0
  97. package/dist/commands/enterprise/contracts/issue.js +34 -0
  98. package/dist/commands/enterprise/domains/begin.d.ts +20 -0
  99. package/dist/commands/enterprise/domains/begin.js +39 -0
  100. package/dist/commands/enterprise/domains/verify.d.ts +14 -0
  101. package/dist/commands/enterprise/domains/verify.js +32 -0
  102. package/dist/commands/enterprise/external-config/activate.d.ts +22 -0
  103. package/dist/commands/enterprise/external-config/activate.js +49 -0
  104. package/dist/commands/enterprise/external-config/set.d.ts +25 -0
  105. package/dist/commands/enterprise/external-config/set.js +123 -0
  106. package/dist/commands/enterprise/external-config/show.d.ts +12 -0
  107. package/dist/commands/enterprise/external-config/show.js +39 -0
  108. package/dist/commands/enterprise/external-config/suspend.d.ts +13 -0
  109. package/dist/commands/enterprise/external-config/suspend.js +41 -0
  110. package/dist/commands/enterprise/finance/close-snapshot.d.ts +11 -0
  111. package/dist/commands/enterprise/finance/close-snapshot.js +28 -0
  112. package/dist/commands/enterprise/finance/record-document.d.ts +18 -0
  113. package/dist/commands/enterprise/finance/record-document.js +35 -0
  114. package/dist/commands/enterprise/profile.d.ts +20 -0
  115. package/dist/commands/enterprise/profile.js +38 -0
  116. package/dist/commands/login.d.ts +13 -0
  117. package/dist/commands/login.js +77 -0
  118. package/dist/commands/machines/dedicated/index.js +3 -0
  119. package/dist/commands/machines/dedicated/service/apply.d.ts +23 -0
  120. package/dist/commands/machines/dedicated/service/apply.js +99 -0
  121. package/dist/commands/machines/dedicated/service/approve.d.ts +23 -0
  122. package/dist/commands/machines/dedicated/service/approve.js +52 -0
  123. package/dist/commands/machines/dedicated/service/create.d.ts +55 -0
  124. package/dist/commands/machines/dedicated/service/create.js +222 -0
  125. package/dist/commands/machines/dedicated/service/edit.d.ts +30 -0
  126. package/dist/commands/machines/dedicated/service/edit.js +146 -0
  127. package/dist/commands/machines/dedicated/service/exec.d.ts +26 -0
  128. package/dist/commands/machines/dedicated/service/exec.js +92 -0
  129. package/dist/commands/machines/dedicated/service/export.d.ts +29 -0
  130. package/dist/commands/machines/dedicated/service/export.js +106 -0
  131. package/dist/commands/machines/dedicated/service/index.d.ts +14 -0
  132. package/dist/commands/machines/dedicated/service/index.js +49 -0
  133. package/dist/commands/machines/dedicated/service/logs.d.ts +33 -0
  134. package/dist/commands/machines/dedicated/service/logs.js +148 -0
  135. package/dist/commands/machines/dedicated/service/ls.d.ts +20 -0
  136. package/dist/commands/machines/dedicated/service/ls.js +80 -0
  137. package/dist/commands/machines/dedicated/service/restart.d.ts +14 -0
  138. package/dist/commands/machines/dedicated/service/restart.js +29 -0
  139. package/dist/commands/machines/dedicated/service/rm.d.ts +20 -0
  140. package/dist/commands/machines/dedicated/service/rm.js +33 -0
  141. package/dist/commands/machines/dedicated/service/secret/index.d.ts +14 -0
  142. package/dist/commands/machines/dedicated/service/secret/index.js +25 -0
  143. package/dist/commands/machines/dedicated/service/secret/rm.d.ts +22 -0
  144. package/dist/commands/machines/dedicated/service/secret/rm.js +54 -0
  145. package/dist/commands/machines/dedicated/service/secret/set.d.ts +22 -0
  146. package/dist/commands/machines/dedicated/service/secret/set.js +93 -0
  147. package/dist/commands/machines/dedicated/service/start.d.ts +14 -0
  148. package/dist/commands/machines/dedicated/service/start.js +29 -0
  149. package/dist/commands/machines/dedicated/service/status.d.ts +21 -0
  150. package/dist/commands/machines/dedicated/service/status.js +85 -0
  151. package/dist/commands/machines/dedicated/service/stop.d.ts +20 -0
  152. package/dist/commands/machines/dedicated/service/stop.js +35 -0
  153. package/dist/commands/machines/dedicated/service/top.d.ts +22 -0
  154. package/dist/commands/machines/dedicated/service/top.js +120 -0
  155. package/dist/commands/machines/dedicated/sign-in-status.d.ts +22 -0
  156. package/dist/commands/machines/dedicated/sign-in-status.js +79 -0
  157. package/dist/commands/machines/dedicated/ssh-config.d.ts +28 -0
  158. package/dist/commands/machines/dedicated/ssh-config.js +66 -0
  159. package/dist/commands/machines/dedicated/ssh-proxy.d.ts +22 -0
  160. package/dist/commands/machines/dedicated/ssh-proxy.js +62 -0
  161. package/dist/commands/machines/dedicated/ssh.d.ts +29 -0
  162. package/dist/commands/machines/dedicated/ssh.js +121 -0
  163. package/dist/commands/native/allow-all.d.ts +14 -0
  164. package/dist/commands/native/allow-all.js +25 -0
  165. package/dist/commands/native/allow.d.ts +24 -0
  166. package/dist/commands/native/allow.js +45 -0
  167. package/dist/commands/native/deny.d.ts +24 -0
  168. package/dist/commands/native/deny.js +43 -0
  169. package/dist/commands/native/disable.d.ts +17 -0
  170. package/dist/commands/native/disable.js +28 -0
  171. package/dist/commands/native/enable.d.ts +12 -0
  172. package/dist/commands/native/enable.js +29 -0
  173. package/dist/commands/native/list-apps.d.ts +19 -0
  174. package/dist/commands/native/list-apps.js +30 -0
  175. package/dist/commands/native/restrict-to.d.ts +22 -0
  176. package/dist/commands/native/restrict-to.js +41 -0
  177. package/dist/commands/native/status.d.ts +19 -0
  178. package/dist/commands/native/status.js +33 -0
  179. package/dist/commands/native.d.ts +39 -0
  180. package/dist/commands/native.js +76 -0
  181. package/dist/commands/service/index.d.ts +14 -0
  182. package/dist/commands/service/index.js +31 -0
  183. package/dist/commands/service/logs.d.ts +18 -0
  184. package/dist/commands/service/logs.js +53 -0
  185. package/dist/commands/service/ls.d.ts +13 -0
  186. package/dist/commands/service/ls.js +48 -0
  187. package/dist/commands/service/propose.d.ts +34 -0
  188. package/dist/commands/service/propose.js +113 -0
  189. package/dist/commands/service/status.d.ts +17 -0
  190. package/dist/commands/service/status.js +56 -0
  191. package/dist/commands/spaces/auto-executor/runs.d.ts +13 -0
  192. package/dist/commands/spaces/auto-executor/runs.js +56 -0
  193. package/dist/commands/store/governance/artifacts.d.ts +25 -0
  194. package/dist/commands/store/governance/artifacts.js +55 -0
  195. package/dist/commands/store/governance/assign.d.ts +16 -0
  196. package/dist/commands/store/governance/assign.js +54 -0
  197. package/dist/commands/store/governance/create-license.d.ts +18 -0
  198. package/dist/commands/store/governance/create-license.js +35 -0
  199. package/dist/commands/store/governance/install-plan.d.ts +25 -0
  200. package/dist/commands/store/governance/install-plan.js +56 -0
  201. package/dist/commands/store/governance/license-policy.d.ts +30 -0
  202. package/dist/commands/store/governance/license-policy.js +69 -0
  203. package/dist/commands/store/governance/policy.d.ts +25 -0
  204. package/dist/commands/store/governance/policy.js +65 -0
  205. package/dist/commands/store/governance/publish-release.d.ts +17 -0
  206. package/dist/commands/store/governance/publish-release.js +34 -0
  207. package/dist/commands/tasks/deliverable/add.d.ts +15 -0
  208. package/dist/commands/tasks/deliverable/add.js +174 -0
  209. package/dist/commands/tasks/deliverable/archive.d.ts +35 -0
  210. package/dist/commands/tasks/deliverable/archive.js +205 -0
  211. package/dist/commands/tasks/labels/detach.js +3 -0
  212. package/dist/commands/tasks/labels/suggest.d.ts +24 -0
  213. package/dist/commands/tasks/labels/suggest.js +69 -0
  214. package/dist/commands/tasks/list.d.ts +16 -2
  215. package/dist/commands/tasks/list.js +100 -24
  216. package/dist/commands/tasks/show.d.ts +23 -0
  217. package/dist/commands/tasks/show.js +51 -1
  218. package/dist/commands/wiki/rm.d.ts +22 -1
  219. package/dist/commands/wiki/rm.js +52 -3
  220. package/dist/lib/agentic-stream.js +10 -2
  221. package/dist/lib/balance.d.ts +6 -1
  222. package/dist/lib/balance.js +15 -0
  223. package/dist/lib/commerce-command.d.ts +48 -0
  224. package/dist/lib/commerce-command.js +70 -0
  225. package/dist/lib/commerce.d.ts +93 -0
  226. package/dist/lib/commerce.js +129 -0
  227. package/dist/lib/commitment-product.js +1 -1
  228. package/dist/lib/commitments.d.ts +202 -29
  229. package/dist/lib/commitments.js +300 -33
  230. package/dist/lib/daemon-installer.d.ts +6 -5
  231. package/dist/lib/daemon-installer.js +4 -17
  232. package/dist/lib/dedicated-lease-command.js +10 -0
  233. package/dist/lib/dedicated-machines.d.ts +37 -0
  234. package/dist/lib/dedicated-machines.js +47 -0
  235. package/dist/lib/dedicated-service-command.d.ts +60 -0
  236. package/dist/lib/dedicated-service-command.js +182 -0
  237. package/dist/lib/dedicated-service.d.ts +342 -0
  238. package/dist/lib/dedicated-service.js +741 -0
  239. package/dist/lib/dedicated-ssh.d.ts +136 -0
  240. package/dist/lib/dedicated-ssh.js +387 -0
  241. package/dist/lib/delegated-cli.js +51 -13
  242. package/dist/lib/enterprise-commerce.d.ts +67 -0
  243. package/dist/lib/enterprise-commerce.js +112 -0
  244. package/dist/lib/enterprise-external-configuration.d.ts +60 -0
  245. package/dist/lib/enterprise-external-configuration.js +58 -0
  246. package/dist/lib/first-party-harness.js +17 -3
  247. package/dist/lib/governed-store.d.ts +110 -0
  248. package/dist/lib/governed-store.js +79 -0
  249. package/dist/lib/guest-service-command.d.ts +16 -0
  250. package/dist/lib/guest-service-command.js +32 -0
  251. package/dist/lib/guest-service.d.ts +67 -0
  252. package/dist/lib/guest-service.js +112 -0
  253. package/dist/lib/prompt.d.ts +1 -0
  254. package/dist/lib/prompt.js +1 -0
  255. package/dist/lib/task-asset-upload.d.ts +20 -0
  256. package/dist/lib/task-asset-upload.js +30 -8
  257. package/dist/lib/task-extras.d.ts +23 -0
  258. package/dist/lib/task-extras.js +6 -0
  259. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/daemonScopes.d.ts +9 -3
  260. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/daemonScopes.js +10 -3
  261. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/firstPartyHarness.d.ts +1 -1
  262. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/firstPartyHarness.js +1 -1
  263. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/index.d.ts +2 -2
  264. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/index.js +8 -5
  265. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/messages.d.ts +16 -0
  266. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/messages.js +21 -4
  267. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/releaseManifest.d.ts +38 -0
  268. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/releaseManifest.js +66 -1
  269. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/spawnEnv.d.ts +1 -1
  270. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/spawnEnv.js +24 -2
  271. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/daemonScopes.d.ts +9 -3
  272. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/daemonScopes.js +10 -3
  273. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/firstPartyHarness.d.ts +1 -1
  274. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/firstPartyHarness.js +1 -1
  275. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/index.d.ts +2 -2
  276. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/index.js +2 -2
  277. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/messages.d.ts +16 -0
  278. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/messages.js +20 -4
  279. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/releaseManifest.d.ts +38 -0
  280. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/releaseManifest.js +64 -0
  281. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/spawnEnv.d.ts +1 -1
  282. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/spawnEnv.js +24 -2
  283. package/dist/node_modules/@skrr-ai/auth-core/package.json +1 -1
  284. package/dist/node_modules/@skrr-ai/data-provider/index.js +5060 -4827
  285. package/oclif.manifest.json +35194 -29157
  286. package/package.json +43 -1
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.DEDICATED_FILE_MAX_BYTES = exports.DEDICATED_FILE_CHUNK_BYTES = exports.DEDICATED_EXEC_DEFAULT_TIMEOUT_MS = exports.DEDICATED_EXEC_MAX_TIMEOUT_MS = exports.DEDICATED_MACHINE_PRODUCT = exports.DEDICATED_LEASE_ACTIONS = void 0;
4
+ exports.describeDedicatedCheckpoint = describeDedicatedCheckpoint;
4
5
  exports.describeDedicatedImageStanding = describeDedicatedImageStanding;
5
6
  exports.dedicatedRuntimeCreateInput = dedicatedRuntimeCreateInput;
6
7
  exports.isDedicatedRepositoryRef = isDedicatedRepositoryRef;
@@ -16,6 +17,7 @@ exports.setDedicatedRuntimeSpendingLimit = setDedicatedRuntimeSpendingLimit;
16
17
  exports.closeDedicatedRuntimeIncidentHold = closeDedicatedRuntimeIncidentHold;
17
18
  exports.destroyDedicatedRuntime = destroyDedicatedRuntime;
18
19
  exports.execDedicatedRuntime = execDedicatedRuntime;
20
+ exports.getDedicatedRuntimeSignInStatus = getDedicatedRuntimeSignInStatus;
19
21
  exports.startDedicatedRuntimeExecution = startDedicatedRuntimeExecution;
20
22
  exports.observeDedicatedRuntimeExecution = observeDedicatedRuntimeExecution;
21
23
  exports.readDedicatedRuntimeFileChunk = readDedicatedRuntimeFileChunk;
@@ -46,6 +48,7 @@ exports.dedicatedRuntimeApiErrorCode = dedicatedRuntimeApiErrorCode;
46
48
  exports.dedicatedRuntimeApiErrorDetails = dedicatedRuntimeApiErrorDetails;
47
49
  exports.formatDedicatedRuntimeApiError = formatDedicatedRuntimeApiError;
48
50
  const auth_core_1 = require("@skrr-ai/auth-core");
51
+ const data_provider_1 = require("@skrr-ai/data-provider");
49
52
  const api_fetch_1 = require("./api-fetch");
50
53
  const edge_error_page_1 = require("./edge-error-page");
51
54
  const harnesses_1 = require("./harnesses");
@@ -58,6 +61,17 @@ exports.DEDICATED_LEASE_ACTIONS = [
58
61
  'health-check',
59
62
  ];
60
63
  exports.DEDICATED_MACHINE_PRODUCT = 'dedicated-machine';
64
+ /**
65
+ * What an operation's guest checkpoint says, or null when the lease records
66
+ * none. One line, because the copy — and the judgement that this is a plain
67
+ * fact and not a warning — lives once in `@skrr-ai/data-provider`.
68
+ */
69
+ function describeDedicatedCheckpoint(lease) {
70
+ const operation = lease?.operation;
71
+ if (!operation)
72
+ return null;
73
+ return (0, data_provider_1.describeMachineCheckpointOutcome)(operation.checkpoint, { action: operation.action });
74
+ }
61
75
  /** One line saying where a machine's image stands and what the owner can do. */
62
76
  function describeDedicatedImageStanding(image, leaseId) {
63
77
  const last = image.lastUpdate;
@@ -304,6 +318,22 @@ async function execDedicatedRuntime(leaseId, input, scope = {}) {
304
318
  },
305
319
  });
306
320
  }
321
+ /**
322
+ * `GET /api/machines/dedicated/:leaseId/sign-in-status` — is this machine
323
+ * signed in to gh, Claude Code and Codex?
324
+ *
325
+ * Its own endpoint rather than a caller of `exec`, for the reason recorded
326
+ * beside the route: before it, the only way to find out was to START a sign-in
327
+ * against a credential that was already fine (OSK-10795). Read-only on the
328
+ * guest — three `… status` subcommands, no writes, no tokens read back.
329
+ *
330
+ * The vocabulary (`DedicatedRuntimeSignInStatus`, its states, the probe and its
331
+ * parser) is OWNED by `@skrr-ai/data-provider` and re-exported here. A second
332
+ * declaration is how a surface drifts from the server that answers it.
333
+ */
334
+ async function getDedicatedRuntimeSignInStatus(leaseId, scope = {}) {
335
+ return (0, api_fetch_1.apiFetch)(withDedicatedScope(`/api/machines/dedicated/${encodeURIComponent(leaseId)}/sign-in-status`, scope));
336
+ }
307
337
  /**
308
338
  * Start one command. `requestId` is the idempotency key: the same id, for the
309
339
  * same command on the same lease, returns the execution it already started —
@@ -586,6 +616,23 @@ function describeDedicatedLease(lease, harnesses = []) {
586
616
  if (hold?.status === 'open') {
587
617
  row('incident', `hold open since ${hold.heldAt || '?'} — the failed source volume is billed until \`incident-close\``);
588
618
  }
619
+ // The lease's last (or current) operation, and — the reason this row exists —
620
+ // whether the machine saved its workspace for it. A stop that paused the work
621
+ // first and a stop that gave up waiting are different facts about whether the
622
+ // owner's last writes landed, and until OSK-11023 the server recorded the
623
+ // difference and no surface printed it. Dated, because on a machine that has
624
+ // since started again the sentence is about a past operation.
625
+ const operation = lease.operation;
626
+ if (operation?.action || operation?.status) {
627
+ const settledAt = operation.completedAt || operation.startedAt;
628
+ // The payload's own spelling, minus the underscore: this row is read by a
629
+ // person, and `in_progress` beside a plain English sentence reads as a code.
630
+ const status = operation.status === 'in_progress' ? 'in progress' : operation.status;
631
+ row('operation', [operation.action, status, settledAt].filter(Boolean).join(' '));
632
+ const checkpoint = describeDedicatedCheckpoint(lease);
633
+ if (checkpoint)
634
+ lines.push(` ${''.padEnd(13)}${checkpoint.sentence}`);
635
+ }
589
636
  const engines = dedicatedLeaseHarnesses(lease, harnesses);
590
637
  if (engines.length > 0) {
591
638
  row('engines', engines.map((harness) => `${harness.provider} (${harness.status || 'unknown'})`).join(', '));
@@ -0,0 +1,60 @@
1
+ import { DedicatedLeaseCommand } from './dedicated-lease-command';
2
+ import { DedicatedServiceChannel, type ServiceVerb } from './dedicated-service';
3
+ /**
4
+ * The flag set `service create`/`apply` and guest `service propose` share —
5
+ * one definition so the three surfaces cannot drift apart on what a spec
6
+ * accepts. `--file` and the argv tail remain per-command because their
7
+ * mutual-exclusion rules differ.
8
+ */
9
+ export declare const serviceSpecFlags: {
10
+ name: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
11
+ cwd: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
12
+ env: import("@oclif/core/lib/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
13
+ restart: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
14
+ notify: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
15
+ 'stop-timeout': import("@oclif/core/lib/interfaces").OptionFlag<number | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
16
+ 'limit-memory': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
17
+ 'limit-cpu': import("@oclif/core/lib/interfaces").OptionFlag<number | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
18
+ 'limit-pids': import("@oclif/core/lib/interfaces").OptionFlag<number | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
19
+ };
20
+ /** The lease arg every service command takes, with `self` support. */
21
+ export declare const SERVICE_LEASE_ARG_DESCRIPTION = "Dedicated Runtime lease id, or `self` when running on the machine itself";
22
+ /**
23
+ * `stop|restart|remove` wait for the guest's full graceful-stop sequence —
24
+ * up to stopTimeoutSeconds (120s max) plus the kill/confirm tail.
25
+ */
26
+ export declare const SERVICE_ACTION_TIMEOUT_MS = 150000;
27
+ /**
28
+ * `skrr machines dedicated service …` — commands that act on one lease's
29
+ * declared services through the admitted `dedicated:service:*` socket lane.
30
+ *
31
+ * Unlike the lease REST calls these commands' verbs are socket events with a
32
+ * requestId/ack round-trip, so they open a channel per invocation rather than
33
+ * going through apiFetch. Every refusal — a refused ack, a missing
34
+ * capability, a dropped socket — lands on `this.error` with an actionable
35
+ * sentence, the same convention `callDedicated` gives the REST lane.
36
+ */
37
+ export declare abstract class DedicatedServiceCommand extends DedicatedLeaseCommand {
38
+ private svcChannel;
39
+ /** The shared channel for this invocation, opened on first use. */
40
+ protected serviceChannel(): Promise<DedicatedServiceChannel>;
41
+ /** Emit one verb and return the daemon's `result`, or throw as a CLI error. */
42
+ protected callService<T = unknown>(verb: ServiceVerb, payload: Record<string, unknown>, timeoutMs?: number): Promise<T | undefined>;
43
+ /**
44
+ * `start|stop|restart|rm` — the shared `dedicated:service:action` round
45
+ * trip and its printout. `rm` maps to the `remove` action on the wire (the
46
+ * doc's verb name); the CLI spells it `rm` because that is what a person
47
+ * deleting a declaration types.
48
+ */
49
+ protected runServiceAction(leaseId: string, name: string, action: 'start' | 'stop' | 'restart' | 'remove', flags: {
50
+ json?: boolean;
51
+ workspace?: string;
52
+ }): Promise<void>;
53
+ protected closeServiceChannel(): void;
54
+ /**
55
+ * Turn a service-lane failure into the command's exit — the refusal
56
+ * sentence the relay sent, or the clean capability-missing path the SSH
57
+ * lane established for a missing `sshBridge`.
58
+ */
59
+ protected reportServiceError(err: unknown): never;
60
+ }
@@ -0,0 +1,182 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DedicatedServiceCommand = exports.SERVICE_ACTION_TIMEOUT_MS = exports.SERVICE_LEASE_ARG_DESCRIPTION = exports.serviceSpecFlags = void 0;
4
+ const core_1 = require("@oclif/core");
5
+ const dedicated_lease_command_1 = require("./dedicated-lease-command");
6
+ const dedicated_service_1 = require("./dedicated-service");
7
+ /**
8
+ * The flag set `service create`/`apply` and guest `service propose` share —
9
+ * one definition so the three surfaces cannot drift apart on what a spec
10
+ * accepts. `--file` and the argv tail remain per-command because their
11
+ * mutual-exclusion rules differ.
12
+ */
13
+ exports.serviceSpecFlags = {
14
+ name: core_1.Flags.string({
15
+ description: 'Service name — ^[a-z0-9][a-z0-9-]{0,62}$, unique per machine',
16
+ }),
17
+ cwd: core_1.Flags.string({
18
+ description: 'Absolute working directory under the workspace, e.g. /workspace/repos/app',
19
+ }),
20
+ env: core_1.Flags.string({
21
+ description: 'Environment variable as NAME=VALUE; repeat for several',
22
+ multiple: true,
23
+ }),
24
+ restart: core_1.Flags.string({
25
+ description: 'Restart policy: always | on-failure | never (default always)',
26
+ options: ['always', 'on-failure', 'never'],
27
+ }),
28
+ notify: core_1.Flags.boolean({
29
+ description: 'Notify the owner when the service reaches failed (default on)',
30
+ allowNo: true,
31
+ }),
32
+ 'stop-timeout': core_1.Flags.integer({
33
+ description: 'Seconds SIGTERM gets before the service’s cgroup is killed (1-120, default 10)',
34
+ min: 1,
35
+ max: 120,
36
+ }),
37
+ 'limit-memory': core_1.Flags.string({
38
+ description: 'Per-service memory ceiling, e.g. 512M or 2G (clamped to the workload slice)',
39
+ }),
40
+ 'limit-cpu': core_1.Flags.integer({
41
+ description: 'Per-service CPU quota as a percent of one core, e.g. 100 for one core',
42
+ min: 1,
43
+ }),
44
+ 'limit-pids': core_1.Flags.integer({
45
+ description: 'Per-service max process count',
46
+ min: 1,
47
+ }),
48
+ };
49
+ /** The lease arg every service command takes, with `self` support. */
50
+ exports.SERVICE_LEASE_ARG_DESCRIPTION = 'Dedicated Runtime lease id, or `self` when running on the machine itself';
51
+ /**
52
+ * `stop|restart|remove` wait for the guest's full graceful-stop sequence —
53
+ * up to stopTimeoutSeconds (120s max) plus the kill/confirm tail.
54
+ */
55
+ exports.SERVICE_ACTION_TIMEOUT_MS = 150_000;
56
+ /**
57
+ * `skrr machines dedicated service …` — commands that act on one lease's
58
+ * declared services through the admitted `dedicated:service:*` socket lane.
59
+ *
60
+ * Unlike the lease REST calls these commands' verbs are socket events with a
61
+ * requestId/ack round-trip, so they open a channel per invocation rather than
62
+ * going through apiFetch. Every refusal — a refused ack, a missing
63
+ * capability, a dropped socket — lands on `this.error` with an actionable
64
+ * sentence, the same convention `callDedicated` gives the REST lane.
65
+ */
66
+ class DedicatedServiceCommand extends dedicated_lease_command_1.DedicatedLeaseCommand {
67
+ svcChannel = null;
68
+ /** The shared channel for this invocation, opened on first use. */
69
+ async serviceChannel() {
70
+ if (this.svcChannel?.isConnected)
71
+ return this.svcChannel;
72
+ this.svcChannel?.close();
73
+ const channel = new dedicated_service_1.DedicatedServiceChannel({
74
+ baseURL: this.cliConfig.baseURL,
75
+ token: this.resolvedCredential.token,
76
+ });
77
+ try {
78
+ await channel.open();
79
+ }
80
+ catch (err) {
81
+ this.reportServiceError(err);
82
+ }
83
+ this.svcChannel = channel;
84
+ return channel;
85
+ }
86
+ /** Emit one verb and return the daemon's `result`, or throw as a CLI error. */
87
+ async callService(verb, payload, timeoutMs) {
88
+ try {
89
+ const channel = await this.serviceChannel();
90
+ const { result } = await channel.call(verb, payload, timeoutMs);
91
+ return result;
92
+ }
93
+ catch (err) {
94
+ this.reportServiceError(err);
95
+ }
96
+ }
97
+ /**
98
+ * `start|stop|restart|rm` — the shared `dedicated:service:action` round
99
+ * trip and its printout. `rm` maps to the `remove` action on the wire (the
100
+ * doc's verb name); the CLI spells it `rm` because that is what a person
101
+ * deleting a declaration types.
102
+ */
103
+ async runServiceAction(leaseId, name, action, flags) {
104
+ // A graceful stop can take up to stopTimeoutSeconds (max 120s) plus the
105
+ // kill/confirm tail — the action ack waits for all of it, so the call
106
+ // window must outlive the longest legitimate stop or it reports a false
107
+ // connectivity failure while the machine is still working.
108
+ const result = await this.callService('action', {
109
+ leaseId,
110
+ name,
111
+ action,
112
+ ...this.scopeFrom(flags),
113
+ }, action === 'start' ? undefined : exports.SERVICE_ACTION_TIMEOUT_MS);
114
+ this.closeServiceChannel();
115
+ if (flags.json) {
116
+ this.log(JSON.stringify(result ?? { name, action }, null, 2));
117
+ return;
118
+ }
119
+ const sentences = {
120
+ start: {
121
+ done: 'is starting',
122
+ hint: 'The machine will keep it running per its restart policy.',
123
+ },
124
+ stop: {
125
+ done: 'is stopping',
126
+ hint: 'Desired state is stopped — it stays stopped across machine restarts until you `service start` it.',
127
+ },
128
+ restart: { done: 'is restarting' },
129
+ remove: {
130
+ done: 'was removed',
131
+ hint: 'The declaration is gone; the machine will not bring it back.',
132
+ },
133
+ };
134
+ const sentence = sentences[action];
135
+ this.log(`Service ${name} ${sentence.done}.`);
136
+ if (sentence.hint)
137
+ this.log(sentence.hint);
138
+ }
139
+ closeServiceChannel() {
140
+ this.svcChannel?.close();
141
+ this.svcChannel = null;
142
+ }
143
+ /**
144
+ * Turn a service-lane failure into the command's exit — the refusal
145
+ * sentence the relay sent, or the clean capability-missing path the SSH
146
+ * lane established for a missing `sshBridge`.
147
+ */
148
+ reportServiceError(err) {
149
+ if (err instanceof dedicated_service_1.DedicatedServiceError) {
150
+ if ((0, dedicated_service_1.isServiceUnsupportedCode)(err.code)) {
151
+ this.failWithCliError({
152
+ message: err.message,
153
+ code: 'DEDICATED_RUNTIME_SERVICES_UNSUPPORTED',
154
+ exit: 1,
155
+ retryable: false,
156
+ });
157
+ }
158
+ if (err.code === 'SERVICE_CONNECT_FAILED') {
159
+ this.failWithCliError({
160
+ message: err.message,
161
+ code: err.code,
162
+ exit: 1,
163
+ retryable: true,
164
+ });
165
+ }
166
+ // Usage-shape failures (bad spec, bad flags) are the caller's to fix.
167
+ const usage = [
168
+ 'SPEC_JSON',
169
+ 'SPEC_INVALID',
170
+ 'SPEC_FILE',
171
+ 'TEMPLATE_JSON',
172
+ 'TEMPLATE_INVALID',
173
+ 'TEMPLATE_NAME_INVALID',
174
+ 'TEMPLATE_PARAM_MISSING',
175
+ 'TEMPLATE_PARAM_UNKNOWN',
176
+ ].includes(err.code);
177
+ this.error(err.message, { exit: usage ? 2 : 1, code: err.code });
178
+ }
179
+ this.handleApiError(err);
180
+ }
181
+ }
182
+ exports.DedicatedServiceCommand = DedicatedServiceCommand;
@@ -0,0 +1,342 @@
1
+ import { io, type Socket } from 'socket.io-client';
2
+ /**
3
+ * Declared services on a Dedicated Runtime — the CLI half of
4
+ * docs/architecture/dedicated-runtime-always-on-workloads-2026-09-21.md (§5.3
5
+ * spec, §5.4 wire surface, §5.6 agent proposals).
6
+ *
7
+ * A service is a spec the daemon keeps reconciling: command, restart policy,
8
+ * env, per-service cgroup limits. The CLI never talks to the machine's
9
+ * registry — every verb rides the same admitted channel the terminal and SSH
10
+ * lanes use, as a `dedicated:service:*` socket event relayed by the API to the
11
+ * lease's daemon. What crosses the wire is exactly what the design doc names;
12
+ * anything not in the spec is refused by the daemon, not by us.
13
+ *
14
+ * Wire vocabulary (client side, mirrored from daemon:service:*):
15
+ *
16
+ * client → API dedicated:service:list|get|create|update|action|logs|
17
+ * logs:stop|approve|secret {…payload, requestId}
18
+ * API → client dedicated:service:ack {requestId, ok, error?, code?, result?}
19
+ * dedicated:service:state {name, status, detail?, ts}
20
+ * dedicated:service:log {name, streamId, data(b64), ts}
21
+ * dedicated:service:log:closed {name, streamId, reason}
22
+ * dedicated:service:proposed {name, spec, createdBy}
23
+ * dedicated:templates:ack {requestId, ok, error?, code?, result?}
24
+ */
25
+ export declare const DEDICATED_SERVICE_EVENTS: {
26
+ readonly list: "dedicated:service:list";
27
+ readonly get: "dedicated:service:get";
28
+ readonly create: "dedicated:service:create";
29
+ readonly update: "dedicated:service:update";
30
+ readonly action: "dedicated:service:action";
31
+ readonly logs: "dedicated:service:logs";
32
+ readonly logsStop: "dedicated:service:logs:stop";
33
+ readonly approve: "dedicated:service:approve";
34
+ readonly secret: "dedicated:service:secret";
35
+ /** Phase-2 verbs — wired now; an old daemon refuses them cleanly. */
36
+ readonly exec: "dedicated:service:exec";
37
+ readonly templatesList: "dedicated:templates:list";
38
+ readonly templatesGet: "dedicated:templates:get";
39
+ readonly ack: "dedicated:service:ack";
40
+ readonly templatesAck: "dedicated:templates:ack";
41
+ readonly state: "dedicated:service:state";
42
+ readonly log: "dedicated:service:log";
43
+ readonly logClosed: "dedicated:service:log:closed";
44
+ readonly proposed: "dedicated:service:proposed";
45
+ };
46
+ /** How long a verb has to answer before the machine is declared unreachable. */
47
+ export declare const SERVICE_CALL_TIMEOUT_MS = 30000;
48
+ /** §5.3 — the scope name `skrr-svc-<name>` derives from it. */
49
+ export declare const SERVICE_NAME_PATTERN: RegExp;
50
+ /** Secret names — the daemon's grammar; checked client-side so a bad name
51
+ * is a usage error here, not a refusal that names the wrong object. */
52
+ export declare const SERVICE_SECRET_NAME_PATTERN: RegExp;
53
+ /** Leaf names a service may never claim (the wrapper routes them itself). */
54
+ export declare const SERVICE_RESERVED_NAMES: Set<string>;
55
+ export declare const SERVICE_RESTART_POLICIES: Set<string>;
56
+ export declare const SERVICE_ACTIONS: Set<string>;
57
+ /**
58
+ * The declared-service spec — §5.3's record shape. Unknown fields are kept:
59
+ * the forward-compat rule is a read/write rule (a spec written by a newer
60
+ * daemon must round-trip through an older client unmangled), so `apply` and
61
+ * `export` carry whatever the daemon returned rather than a known-fields
62
+ * projection. The phase-2/horizon names (`schedule`, `timezone`,
63
+ * `missedFire`, `probe`, `hooks`, `replicas`, `dependsOn`) are listed only so
64
+ * the type reads them; the index signature is what preserves them.
65
+ */
66
+ export interface DedicatedServiceSpec {
67
+ version?: number;
68
+ name?: string;
69
+ command?: string[];
70
+ shell?: string;
71
+ cwd?: string;
72
+ env?: Record<string, string>;
73
+ restart?: 'always' | 'on-failure' | 'never' | string;
74
+ backoff?: {
75
+ initialMs?: number;
76
+ maxMs?: number;
77
+ budget?: number;
78
+ windowMs?: number;
79
+ };
80
+ stopTimeoutSeconds?: number;
81
+ notify?: boolean;
82
+ limits?: {
83
+ memoryMax?: string;
84
+ cpuQuotaPercent?: number;
85
+ pidsMax?: number;
86
+ };
87
+ disabled?: boolean;
88
+ createdBy?: string;
89
+ revision?: number;
90
+ createdAt?: string;
91
+ updatedAt?: string;
92
+ schedule?: string;
93
+ timezone?: string;
94
+ missedFire?: string;
95
+ probe?: unknown;
96
+ hooks?: unknown;
97
+ replicas?: number;
98
+ dependsOn?: string[];
99
+ [key: string]: unknown;
100
+ }
101
+ /** One computed-state row, as `list`/`get` return it. Status is derived, never stored. */
102
+ export interface DedicatedServiceRow {
103
+ /** Present on state pushes and some relay shapes; list/get rows name the service only under `spec.name`. */
104
+ name?: string;
105
+ status?: string;
106
+ /** A plain string or the daemon's structured detail ({reason, exitCode, …}). */
107
+ detail?: string | Record<string, unknown>;
108
+ restart?: string;
109
+ createdBy?: string;
110
+ disabled?: boolean;
111
+ spec?: DedicatedServiceSpec;
112
+ /** Phase-2: per-scope metrics the daemon may attach (`cpu.stat` et al). */
113
+ stats?: DedicatedServiceStats;
114
+ [key: string]: unknown;
115
+ }
116
+ export interface DedicatedServiceStats {
117
+ cpuPercent?: number;
118
+ memoryBytes?: number;
119
+ memoryMaxBytes?: number;
120
+ pidsCurrent?: number;
121
+ pidsMax?: number;
122
+ [key: string]: unknown;
123
+ }
124
+ /** An agent proposal awaiting the owner — `status: proposed`, per §5.6. */
125
+ export interface DedicatedServiceProposal {
126
+ name?: string;
127
+ proposalId?: string;
128
+ spec?: DedicatedServiceSpec;
129
+ createdBy?: string;
130
+ proposedAt?: string;
131
+ [key: string]: unknown;
132
+ }
133
+ export interface DedicatedServiceGetResult {
134
+ spec?: DedicatedServiceSpec;
135
+ status?: string;
136
+ detail?: string | Record<string, unknown>;
137
+ stats?: DedicatedServiceStats;
138
+ /** Bounded ring of recent exits: {exitCode, signal, at}. */
139
+ exits?: Array<{
140
+ exitCode?: number | null;
141
+ signal?: string | null;
142
+ at?: string;
143
+ }>;
144
+ [key: string]: unknown;
145
+ }
146
+ export interface DedicatedServiceAck {
147
+ requestId?: string;
148
+ ok?: boolean;
149
+ error?: string;
150
+ code?: string;
151
+ result?: unknown;
152
+ }
153
+ export declare class DedicatedServiceError extends Error {
154
+ readonly code: string;
155
+ constructor(message: string, code: string);
156
+ }
157
+ /** True for every refusal that says "this machine has no services support". */
158
+ export declare function isServiceUnsupportedCode(code: string | undefined): boolean;
159
+ /**
160
+ * A service refusal in words that say what to do — the same register
161
+ * `describeSshStartRefusal` uses for the SSH lane. The capability-missing
162
+ * branch mirrors the sshBridge fallback: an old image or an old daemon is a
163
+ * named condition with a next step, not a crash.
164
+ */
165
+ export declare function describeServiceRefusal(ack: Pick<DedicatedServiceAck, 'code' | 'error'>, context?: {
166
+ leaseId?: string;
167
+ verb?: string;
168
+ name?: string;
169
+ }): string;
170
+ /** Validation that costs the daemon nothing to re-check — §5.3's table, enforced client-side first. */
171
+ export declare function validateServiceSpec(doc: unknown, options?: {
172
+ requireName?: boolean;
173
+ requireCommand?: boolean;
174
+ }): string[];
175
+ /**
176
+ * Parse a `service.json` document, refusing with every problem named at once
177
+ * rather than the first — a file you are editing deserves the whole list.
178
+ */
179
+ export declare function parseServiceSpecDocument(raw: string, source: string, options?: {
180
+ requireName?: boolean;
181
+ requireCommand?: boolean;
182
+ }): DedicatedServiceSpec;
183
+ /** The spec a mutation carries: the document minus the fields the daemon owns. */
184
+ export declare function specPayload(spec: DedicatedServiceSpec): Record<string, unknown>;
185
+ /**
186
+ * The repo `service.json` form of a stored spec — `export`'s output. The
187
+ * document the daemon returned minus its bookkeeping, unknown fields kept
188
+ * verbatim so forward fields survive the round-trip.
189
+ */
190
+ export declare function specExportDocument(spec: DedicatedServiceSpec): Record<string, unknown>;
191
+ /** `--env KEY=VALUE` entries, one flag instance each. */
192
+ export declare function parseEnvEntries(entries: readonly string[] | undefined): Record<string, string>;
193
+ /** `name=value` pairs for --param; the value stays a string — templates interpolate text. */
194
+ export declare function parseParamEntries(entries: readonly string[] | undefined): Record<string, string>;
195
+ /** A spec assembled from create/propose flags rather than a file. */
196
+ export declare function specFromFlags(input: {
197
+ name?: string;
198
+ argv?: string[];
199
+ cwd?: string;
200
+ env?: Record<string, string>;
201
+ restart?: string;
202
+ notify?: boolean;
203
+ stopTimeoutSeconds?: number;
204
+ limits?: {
205
+ memoryMax?: string;
206
+ cpuQuotaPercent?: number;
207
+ pidsMax?: number;
208
+ };
209
+ }): DedicatedServiceSpec;
210
+ export interface DedicatedServiceSocketOptions {
211
+ baseURL: string;
212
+ token: string;
213
+ /** Injected for tests. */
214
+ connect?: (url: string, opts: Parameters<typeof io>[1]) => Socket;
215
+ }
216
+ export type ServiceVerb = 'list' | 'get' | 'create' | 'update' | 'action' | 'logs' | 'logs:stop' | 'approve' | 'secret' | 'exec';
217
+ /**
218
+ * One admitted socket for a run of service verbs. `call` emits
219
+ * `dedicated:service:<verb>` with a fresh requestId and resolves on the
220
+ * matching `dedicated:service:ack`; push events (`state`, `log`,
221
+ * `log:closed`, `proposed`) are exposed via `on` for the follow loop.
222
+ */
223
+ export declare class DedicatedServiceChannel {
224
+ private options;
225
+ private socket;
226
+ private connected;
227
+ private dead;
228
+ private pending;
229
+ private onDead;
230
+ constructor(options: DedicatedServiceSocketOptions);
231
+ /** Resolves once the transport is up; rejects on connect failure. */
232
+ open(): Promise<void>;
233
+ /** A socket dying mid-follow ends the follow cleanly rather than hanging. */
234
+ setOnDead(handler: (() => void) | null): void;
235
+ get isConnected(): boolean;
236
+ /**
237
+ * Emit a verb and await its ack. A refusal ack is a DedicatedServiceError
238
+ * whose message is the actionable sentence; the raw code rides along so a
239
+ * caller can branch on `conflict` or a missing capability.
240
+ */
241
+ call<T = unknown>(verb: ServiceVerb, payload: Record<string, unknown>, timeoutMs?: number): Promise<{
242
+ result: T | undefined;
243
+ ack: DedicatedServiceAck;
244
+ }>;
245
+ /**
246
+ * A read against the template gallery — `dedicated:templates:list|get`,
247
+ * answered on `dedicated:templates:ack`. Same requestId/ack discipline as
248
+ * the service verbs; the event family is the only difference.
249
+ */
250
+ callTemplates<T = unknown>(verb: 'list' | 'get', payload: Record<string, unknown>, timeoutMs?: number): Promise<{
251
+ result: T | undefined;
252
+ ack: DedicatedServiceAck;
253
+ }>;
254
+ /** The shared request/ack round-trip. */
255
+ private callEvent;
256
+ /** Subscribe to a server-pushed frame (`state`, `log`, `log:closed`, `proposed`). */
257
+ on(event: string, handler: (frame: Record<string, unknown>) => void): void;
258
+ off(event: string, handler: (frame: Record<string, unknown>) => void): void;
259
+ /** Emit without waiting for an ack (logs:stop — the stream may already be gone). */
260
+ send(event: string, payload: Record<string, unknown>): void;
261
+ close(): void;
262
+ }
263
+ export interface ServiceLogFrame {
264
+ name?: string;
265
+ streamId?: string;
266
+ data?: string;
267
+ ts?: number | string;
268
+ }
269
+ export interface ServiceLogClosedFrame {
270
+ name?: string;
271
+ streamId?: string;
272
+ reason?: string;
273
+ }
274
+ export interface StreamServiceLogsOptions extends DedicatedServiceSocketOptions {
275
+ leaseId: string;
276
+ name: string;
277
+ follow: boolean;
278
+ /** Bytes from the end of the log to replay first. */
279
+ tailBytes?: number;
280
+ output: NodeJS.WritableStream;
281
+ errorOutput: NodeJS.WritableStream;
282
+ /** Frame sink for tests; defaults to output.write. */
283
+ write?: (bytes: Buffer) => void;
284
+ }
285
+ /**
286
+ * `service logs` — tail the stored log, then follow live
287
+ * `dedicated:service:log` frames until `log:closed`, a SIGINT, or the socket
288
+ * dies. Resolves with the exit code the command should use (0 unless the
289
+ * stream failed). The follow is closed with `dedicated:service:logs:stop` so
290
+ * the daemon does not keep piping to a dead reader.
291
+ */
292
+ export declare function streamServiceLogs(options: StreamServiceLogsOptions): Promise<number>;
293
+ /**
294
+ * A service template — §10.2's spec-with-holes. `${param}` slots inside
295
+ * `spec` are substituted with --param values or the param's default.
296
+ */
297
+ export interface DedicatedServiceTemplate {
298
+ version?: number;
299
+ name?: string;
300
+ description?: string;
301
+ params?: Array<{
302
+ name: string;
303
+ required?: boolean;
304
+ default?: string;
305
+ description?: string;
306
+ }>;
307
+ spec?: Record<string, unknown>;
308
+ [key: string]: unknown;
309
+ }
310
+ export declare function serviceTemplatesDir(home?: string): string;
311
+ /**
312
+ * `~/.skrr/templates/<name>.json`, or null when absent. A template file that
313
+ * will not parse is an error, not a miss — silent fall-through to the gallery
314
+ * would hide a broken local file.
315
+ */
316
+ export declare function loadLocalServiceTemplate(name: string, home?: string): DedicatedServiceTemplate | null;
317
+ /**
318
+ * Merge a template with its params into a concrete spec. Required params
319
+ * without a value or a default refuse before any substitution runs — a
320
+ * half-merged spec is a worse failure than a named missing param.
321
+ */
322
+ export declare function mergeServiceTemplate(template: DedicatedServiceTemplate, given: Record<string, string>, source?: string): DedicatedServiceSpec;
323
+ /**
324
+ * The wire's `detail` is a string or the daemon's structured object
325
+ * ({reason, exitCode, signal, restarts, detail}) — render the fields for a
326
+ * status line, never "[object Object]". Shared by the owner-lane and
327
+ * guest-local status commands so both read the same shape.
328
+ */
329
+ export declare function serviceDetailText(detail: unknown): string | undefined;
330
+ /** The daemon's workload-facing service socket on a Dedicated Runtime guest. */
331
+ export declare const GUEST_SERVICE_SOCKET_PATH = "/run/skrr-dedicated-runtime/service-propose/service-propose.sock";
332
+ /**
333
+ * True when this process is running on a Dedicated Runtime guest — the
334
+ * workload-uid test, or the guest markers the image/daemon own. An SSH
335
+ * session may not carry the wrapper's env stamp, so the filesystem markers
336
+ * count too; the socket itself remains the authority.
337
+ */
338
+ export declare function runningOnDedicatedRuntimeGuest(env?: NodeJS.ProcessEnv, getuid?: (() => number) | undefined, paths?: {
339
+ socketPath?: string;
340
+ attestationPath?: string;
341
+ runtimeDir?: string;
342
+ }): boolean;