@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
@@ -35,39 +35,73 @@ var __importStar = (this && this.__importStar) || (function () {
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
36
  exports.normalizeBaseUrl = normalizeBaseUrl;
37
37
  exports.isNudgeSuppressed = isNudgeSuppressed;
38
+ exports.isAutoUpdateSuppressed = isAutoUpdateSuppressed;
38
39
  exports.isOlderVersion = isOlderVersion;
40
+ exports.resolveCliPackageDir = resolveCliPackageDir;
41
+ exports.classifyCliInstall = classifyCliInstall;
39
42
  exports.buildNudgeLine = buildNudgeLine;
43
+ exports.decideCliUpdateAction = decideCliUpdateAction;
40
44
  exports.maybeWarnOutdatedCli = maybeWarnOutdatedCli;
45
+ const node_child_process_1 = require("node:child_process");
41
46
  const fs = __importStar(require("node:fs"));
42
47
  const os = __importStar(require("node:os"));
43
48
  const path = __importStar(require("node:path"));
49
+ const node_util_1 = require("node:util");
44
50
  /**
45
- * update-check.ts — non-blocking "a newer `skrr` is available" advisory.
51
+ * update-check.ts — non-blocking "a newer `skrr` is available" advisory AND
52
+ * background self-update for installs we own.
46
53
  *
47
- * The standalone `skrr` CLI (npm `@skrr-ai/cli`) has no self-update path,
48
- * so a user who installed it via npm has no signal that they are behind.
49
- * This module is the CLI-side analog of the daemon's server-driven
50
- * `daemon:update-available` advisory: on every command it decides — from a
51
- * ~4h on-disk cache, with ZERO added latency — whether to print a single
52
- * line to stderr, and refreshes that cache in the background.
54
+ * The standalone `skrr` CLI (npm `@skrr-ai/cli`) has no in-place update path
55
+ * of its own — the bytes belong to whatever installed them. On every command
56
+ * this module decides — from a ~4h on-disk cache, with ZERO added latency —
57
+ * what to do about version state, and refreshes that cache in the background:
53
58
  *
54
- * Hard guarantees (a version advisory must never make the CLI worse):
59
+ * - npm-global, writable install + outdated → AUTO-UPDATE: schedule a
60
+ * detached `npm install -g @skrr-ai/cli@<latest>` that runs after this
61
+ * command exits (so a mid-flight command never reads half-swapped files),
62
+ * once per TTL window, and print one stderr line saying so. If a later
63
+ * run still sees the old version the attempt failed and we fall back to
64
+ * the manual nudge.
65
+ * - every other install shape → NUDGE: a single stderr line telling the
66
+ * user the right update command for THEIR install (a project-local dep
67
+ * is updated inside its project; a dev checkout is rebuilt, not npm'd).
68
+ * - installs we must not touch → silence: the app-bundled CLI updates with
69
+ * the desktop app; image-baked installs (dedicated-runtime guest) are
70
+ * owned by the image.
71
+ *
72
+ * Hard guarantees (a version check must never make the CLI worse):
55
73
  * - Writes ONLY to stderr, never stdout, so `--json` output stays clean.
56
- * - Prints at most ONE line, and only on an interactive TTY (scripts /
57
- * CI / pipes never see it).
58
- * - Never blocks the command: the nudge decision is synchronous off the
59
- * cache; the network refresh is fire-and-forget and time-bounded.
74
+ * - Prints at most ONE line, and only on an interactive TTY — scripts, CI
75
+ * and pipes neither see the nudge nor trigger an auto-update.
76
+ * - Never blocks the command: the decision is synchronous off the cache;
77
+ * the network refresh and install classification are fire-and-forget
78
+ * and time-bounded; the actual `npm install` is deferred to process
79
+ * exit and detached.
60
80
  * - Never throws: every path is wrapped so a malformed cache, offline
61
- * API, or read-only home directory can't break a command.
81
+ * API, missing npm, or read-only home directory can't break a command.
82
+ * - Never escalates: a global prefix we cannot write stays a nudge; the
83
+ * CLI will not reach for sudo.
62
84
  * - Suppressible: `OVERSKY_NO_UPDATE_NUDGE` / `OVERSKY_SKIP_UPDATE_CHECK`
63
- * silence it; `OVERSKY_CLI_BUNDLED=1` (set by the desktop app's `skrr`
64
- * wrapper) suppresses it entirely — bundled installs auto-update with
65
- * the app, so an "npm update -g" nudge would be actively wrong there.
85
+ * silence everything; `OVERSKY_CLI_AUTO_UPDATE=0` keeps the nudge but
86
+ * skips the background install; `OVERSKY_CLI_BUNDLED=1` (set by the
87
+ * desktop app's `skrr` wrapper) suppresses it entirely.
66
88
  */
67
89
  /** How long a cached advisory stays fresh before a background refresh. */
68
90
  const CHECK_TTL_MS = 4 * 60 * 60 * 1000; // 4h
69
91
  /** Hard ceiling on the background refresh request. */
70
92
  const FETCH_TIMEOUT_MS = 1500;
93
+ /** Hard ceiling on the `npm root -g` classification probe. */
94
+ const NPM_ROOT_TIMEOUT_MS = 1500;
95
+ /** Marker written by the dedicated-runtime image bake — a guest's skrr is
96
+ * image-pinned and must never be told to `npm update -g`. */
97
+ const DEDICATED_RUNTIME_ENV_FILE = '/etc/skrr-dedicated-runtime.env';
98
+ /** Daemon-source values for image-pinned (hosted) runtime contexts. */
99
+ const HOSTED_RUNTIME_SOURCES = new Set([
100
+ 'dedicated-runtime',
101
+ 'hosted-machine',
102
+ 'cloud-coding',
103
+ ]);
104
+ const execFileAsync = (0, node_util_1.promisify)(node_child_process_1.execFile);
71
105
  function cacheFilePath() {
72
106
  return path.join(os.homedir(), '.skrr', 'cli-update-check.json');
73
107
  }
@@ -80,15 +114,41 @@ function isTruthyEnv(value) {
80
114
  return false;
81
115
  return ['1', 'true', 'on', 'yes'].includes(value.trim().toLowerCase());
82
116
  }
117
+ function isDisabledEnv(value) {
118
+ if (!value)
119
+ return false;
120
+ return ['0', 'false', 'off', 'no', 'disabled'].includes(value.trim().toLowerCase());
121
+ }
122
+ /** True when this process runs on an image-pinned hosted-runtime guest. The
123
+ * env marker covers the daemon unit's context; the env FILE is the reliable
124
+ * signal for interactive tenant shells that never inherit it. */
125
+ function isHostedRuntimeGuest(env) {
126
+ if (HOSTED_RUNTIME_SOURCES.has((env.OVERSKY_DAEMON_SOURCE ?? '').trim()))
127
+ return true;
128
+ try {
129
+ return fs.existsSync(DEDICATED_RUNTIME_ENV_FILE);
130
+ }
131
+ catch {
132
+ return false;
133
+ }
134
+ }
83
135
  /**
84
136
  * True when the advisory must stay silent regardless of version state:
85
- * explicit suppression, or a desktop-app-bundled CLI (which auto-updates
86
- * with the app and must not be told to `npm update -g`).
137
+ * explicit suppression, a desktop-app-bundled CLI (which auto-updates with
138
+ * the app and must not be told to `npm update -g`), or an image-baked install
139
+ * the control plane owns.
87
140
  */
88
141
  function isNudgeSuppressed(env = process.env) {
89
142
  return (isTruthyEnv(env.OVERSKY_NO_UPDATE_NUDGE) ||
90
143
  isTruthyEnv(env.OVERSKY_SKIP_UPDATE_CHECK) ||
91
- env.OVERSKY_CLI_BUNDLED === '1');
144
+ env.OVERSKY_CLI_BUNDLED === '1' ||
145
+ isHostedRuntimeGuest(env));
146
+ }
147
+ /** True when the background self-update is allowed to run at all. Suppression
148
+ * implies no auto-update — a user who asked for silence did not ask for a
149
+ * silent mutation of their global npm. */
150
+ function isAutoUpdateSuppressed(env = process.env) {
151
+ return isNudgeSuppressed(env) || isDisabledEnv(env.OVERSKY_CLI_AUTO_UPDATE);
92
152
  }
93
153
  /**
94
154
  * Parse the numeric release core of a version (`1.2.3-rc.1` → `[1,2,3]`),
@@ -130,18 +190,202 @@ function isOlderVersion(current, latest) {
130
190
  }
131
191
  return false;
132
192
  }
193
+ // ---------------------------------------------------------------------------
194
+ // Install-shape classification
195
+ // ---------------------------------------------------------------------------
196
+ const CLI_PACKAGE_DIR_RE = /^(.*[/\\]node_modules[/\\]@skrr-ai[/\\]cli)[/\\]/;
197
+ /**
198
+ * Resolve the package directory this process was launched from when it lives
199
+ * under `node_modules/@skrr-ai/cli` (any npm install — global or project-local),
200
+ * or null. Probes both the raw entry path and its realpath because the bin is
201
+ * usually a symlink into the package.
202
+ */
203
+ function resolveCliPackageDir(argv = process.argv) {
204
+ const entry = argv[1];
205
+ if (!entry)
206
+ return null;
207
+ const candidates = [entry];
208
+ try {
209
+ candidates.push(fs.realpathSync(entry));
210
+ }
211
+ catch {
212
+ /* entry may be virtual; the raw form is still probed */
213
+ }
214
+ for (const candidate of candidates) {
215
+ const match = candidate.match(CLI_PACKAGE_DIR_RE);
216
+ if (match)
217
+ return match[1];
218
+ }
219
+ return null;
220
+ }
221
+ function dirWritable(dir) {
222
+ try {
223
+ const st = fs.statSync(dir);
224
+ if (!st.isDirectory())
225
+ return false;
226
+ const probe = path.join(dir, `.skrr.write-probe.${process.pid}.${Date.now()}`);
227
+ fs.closeSync(fs.openSync(probe, 'w', 0o600));
228
+ fs.unlinkSync(probe);
229
+ return true;
230
+ }
231
+ catch {
232
+ return false;
233
+ }
234
+ }
235
+ /**
236
+ * Classify how this CLI was installed. `npmGlobalRoot` (from `npm root -g`)
237
+ * distinguishes a global install — which we may auto-update — from a
238
+ * project-local dependency, whose bytes belong to that project's package.json.
239
+ * `dev` is a checkout launched via its own `bin/run.js`: a `src/commands`
240
+ * dir beside `dist` exists only in a checkout — published packages ship
241
+ * `dist` and no `src`.
242
+ */
243
+ function classifyCliInstall(env, argv, npmGlobalRoot) {
244
+ if (env.OVERSKY_CLI_BUNDLED === '1' || isHostedRuntimeGuest(env)) {
245
+ return { kind: 'bundled' };
246
+ }
247
+ const packageDir = resolveCliPackageDir(argv);
248
+ if (!packageDir) {
249
+ // A dev checkout launches `cli/bin/run.js` directly — a `src/commands`
250
+ // sibling of `dist` exists only in a checkout (published packages ship
251
+ // `dist` and no `src`). Those bytes belong to git, not npm.
252
+ const entry = argv[1];
253
+ if (entry) {
254
+ try {
255
+ const cliRoot = path.resolve(path.dirname(entry), '..');
256
+ if (fs.existsSync(path.join(cliRoot, 'src', 'commands'))) {
257
+ return { kind: 'dev' };
258
+ }
259
+ }
260
+ catch {
261
+ /* fall through to other */
262
+ }
263
+ }
264
+ return { kind: 'other' };
265
+ }
266
+ const nodeModulesDir = path.dirname(path.dirname(packageDir)); // …/node_modules
267
+ if (npmGlobalRoot) {
268
+ let resolvedGlobal = npmGlobalRoot;
269
+ try {
270
+ resolvedGlobal = fs.realpathSync(npmGlobalRoot);
271
+ }
272
+ catch {
273
+ /* compare the raw form */
274
+ }
275
+ let resolvedNodeModules = nodeModulesDir;
276
+ try {
277
+ resolvedNodeModules = fs.realpathSync(nodeModulesDir);
278
+ }
279
+ catch {
280
+ /* compare the raw form */
281
+ }
282
+ if (resolvedNodeModules !== resolvedGlobal)
283
+ return { kind: 'npm-local' };
284
+ }
285
+ else if (!/[/\\](lib|npm)[/\\]node_modules$/.test(nodeModulesDir)) {
286
+ // `npm root -g` gave no answer, so prove the global shape from the path
287
+ // instead: npm's unix global root is always `<prefix>/lib/node_modules`
288
+ // (incl. nvm/volta) and on Windows `%APPDATA%\npm\node_modules`. A
289
+ // project-local `<project>/node_modules` never matches either — without
290
+ // proof we must not treat it as ours to auto-update.
291
+ return { kind: 'npm-local' };
292
+ }
293
+ return { kind: 'npm-global', writable: dirWritable(nodeModulesDir) };
294
+ }
295
+ /**
296
+ * Resolve `npm root -g` for install classification. Runs ONLY inside the
297
+ * background refresh — never on the command's hot path — and fails soft:
298
+ * no npm, a timeout, or an odd answer just leaves classification to the
299
+ * path shape alone.
300
+ */
301
+ async function resolveNpmGlobalRoot() {
302
+ try {
303
+ const npmBin = process.platform === 'win32' ? 'npm.cmd' : 'npm';
304
+ const { stdout } = await execFileAsync(npmBin, ['root', '-g'], {
305
+ timeout: NPM_ROOT_TIMEOUT_MS,
306
+ maxBuffer: 64 * 1024,
307
+ shell: process.platform === 'win32',
308
+ });
309
+ const root = stdout.trim();
310
+ return root && path.isAbsolute(root) ? root : null;
311
+ }
312
+ catch {
313
+ return null;
314
+ }
315
+ }
316
+ // ---------------------------------------------------------------------------
317
+ // Advisory copy — one line, per install shape
318
+ // ---------------------------------------------------------------------------
133
319
  /**
134
320
  * Build the one-line stderr advisory, or null when no nudge is warranted.
135
- * Exported for direct unit testing without touching disk or the network.
321
+ * `installKind` tailors the command to the bytes' owner: a project-local dep
322
+ * is updated inside its project, a dev checkout is rebuilt — telling either
323
+ * to `npm update -g` would fix the wrong install.
136
324
  */
137
- function buildNudgeLine(currentVersion, latest, npmPackage) {
325
+ function buildNudgeLine(currentVersion, latest, npmPackage, installKind) {
138
326
  if (!latest || !isOlderVersion(currentVersion, latest))
139
327
  return null;
140
328
  const pkg = npmPackage || '@skrr-ai/cli';
141
- return (`[skrr] Update available: ${currentVersion} → ${latest}. ` +
142
- `Run \`npm update -g ${pkg}\` (or update the skrr app). ` +
143
- `Silence with OVERSKY_NO_UPDATE_NUDGE=1.\n`);
329
+ const prefix = `[skrr] Update available: ${currentVersion} → ${latest}. `;
330
+ const suffix = ` Silence with OVERSKY_NO_UPDATE_NUDGE=1.\n`;
331
+ switch (installKind) {
332
+ case 'npm-local':
333
+ return `${prefix}Run \`npm update ${pkg}\` in the owning project.${suffix}`;
334
+ case 'dev':
335
+ return `${prefix}Rebuild your checkout (\`npm --prefix cli run build\`).${suffix}`;
336
+ case 'other':
337
+ return `${prefix}Update via your install method — see https://skrr.ai.${suffix}`;
338
+ case 'npm-global':
339
+ case 'bundled':
340
+ default:
341
+ return `${prefix}Run \`npm update -g ${pkg}\` (or update the skrr app).${suffix}`;
342
+ }
144
343
  }
344
+ /**
345
+ * Decide, synchronously and from cache alone, what this command should do
346
+ * about its version state. Pure — exported for direct unit testing.
347
+ *
348
+ * AUTO-UPDATE fires at most once per TTL window per target version, and only
349
+ * for a provably writable npm-global install on an interactive TTY. An attempt
350
+ * that didn't take (still outdated next run) falls back to the manual nudge
351
+ * rather than retrying immediately.
352
+ */
353
+ function decideCliUpdateAction(args) {
354
+ const { currentVersion, cache, env, isTTY } = args;
355
+ const now = args.now ?? Date.now();
356
+ if (!isTTY || isNudgeSuppressed(env))
357
+ return null;
358
+ if (!cache || !cache.latest || !isOlderVersion(currentVersion, cache.latest))
359
+ return null;
360
+ const install = cache.install ?? { kind: 'other' };
361
+ const pkg = cache.npmPackage || '@skrr-ai/cli';
362
+ const attempt = cache.autoUpdate;
363
+ const attemptFresh = attempt != null && attempt.version === cache.latest && now - attempt.attemptedAt < CHECK_TTL_MS;
364
+ if (install.kind === 'npm-global' && install.writable === true && !isAutoUpdateSuppressed(env)) {
365
+ if (!attemptFresh) {
366
+ return {
367
+ type: 'auto-update',
368
+ version: cache.latest,
369
+ pkg,
370
+ line: `[skrr] Updating ${currentVersion} → ${cache.latest} in the background ` +
371
+ `(\`npm install -g ${pkg}@${cache.latest}\`). Disable with OVERSKY_CLI_AUTO_UPDATE=0.\n`,
372
+ };
373
+ }
374
+ // We already tried this version within the window and the update did not
375
+ // take — tell the user the manual command instead of retrying every run.
376
+ return {
377
+ type: 'nudge',
378
+ line: `[skrr] Update available: ${currentVersion} → ${cache.latest}. ` +
379
+ `The background update did not take — run \`npm update -g ${pkg}\` manually.` +
380
+ ` Silence with OVERSKY_NO_UPDATE_NUDGE=1.\n`,
381
+ };
382
+ }
383
+ const line = buildNudgeLine(currentVersion, cache.latest, cache.npmPackage, install.kind);
384
+ return line ? { type: 'nudge', line } : null;
385
+ }
386
+ // ---------------------------------------------------------------------------
387
+ // Cache I/O
388
+ // ---------------------------------------------------------------------------
145
389
  function readCache() {
146
390
  try {
147
391
  const raw = fs.readFileSync(cacheFilePath(), 'utf8');
@@ -152,6 +396,19 @@ function readCache() {
152
396
  latest: typeof parsed.latest === 'string' ? parsed.latest : null,
153
397
  npmPackage: typeof parsed.npmPackage === 'string' ? parsed.npmPackage : null,
154
398
  baseURL: parsed.baseURL,
399
+ install: parsed.install && typeof parsed.install.kind === 'string'
400
+ ? {
401
+ kind: parsed.install.kind,
402
+ writable: typeof parsed.install.writable === 'boolean'
403
+ ? parsed.install.writable
404
+ : undefined,
405
+ }
406
+ : undefined,
407
+ autoUpdate: parsed.autoUpdate &&
408
+ typeof parsed.autoUpdate.attemptedAt === 'number' &&
409
+ typeof parsed.autoUpdate.version === 'string'
410
+ ? { attemptedAt: parsed.autoUpdate.attemptedAt, version: parsed.autoUpdate.version }
411
+ : undefined,
155
412
  };
156
413
  }
157
414
  }
@@ -172,6 +429,13 @@ function writeCache(cache) {
172
429
  // Best-effort — a read-only home just means we re-check next run.
173
430
  }
174
431
  }
432
+ /** Persist the auto-update attempt marker without losing the rest of the cache. */
433
+ function markAutoUpdateAttempt(version) {
434
+ const cache = readCache();
435
+ if (!cache)
436
+ return;
437
+ writeCache({ ...cache, autoUpdate: { attemptedAt: Date.now(), version } });
438
+ }
175
439
  async function refreshCache(baseURL) {
176
440
  try {
177
441
  const url = `${baseURL.replace(/\/+$/, '')}/api/config/cli-version`;
@@ -182,23 +446,80 @@ async function refreshCache(baseURL) {
182
446
  if (!res.ok)
183
447
  return;
184
448
  const body = (await res.json());
449
+ // Classify the install shape while we're already off the hot path — the
450
+ // `npm root -g` probe is the only piece that can cost real time and it is
451
+ // bounded by NPM_ROOT_TIMEOUT_MS. It only runs when the entry point even
452
+ // looks like an npm package dir.
453
+ let install;
454
+ if (resolveCliPackageDir()) {
455
+ install = classifyCliInstall(process.env, process.argv, await resolveNpmGlobalRoot());
456
+ }
457
+ else {
458
+ install = classifyCliInstall(process.env, process.argv, null);
459
+ }
460
+ // Preserve a pending auto-update marker across refreshes so the
461
+ // once-per-window gate survives the cache being rewritten.
462
+ const prior = readCache();
185
463
  writeCache({
186
464
  lastCheckAt: Date.now(),
187
465
  latest: typeof body.latest === 'string' ? body.latest : null,
188
466
  npmPackage: typeof body.npmPackage === 'string' ? body.npmPackage : null,
189
467
  baseURL: normalizeBaseUrl(baseURL),
468
+ install,
469
+ autoUpdate: prior?.autoUpdate,
190
470
  });
191
471
  }
192
472
  catch {
193
473
  // Offline / timeout / bad payload — leave the old cache, retry later.
194
474
  }
195
475
  }
476
+ // ---------------------------------------------------------------------------
477
+ // Deferred self-update
478
+ // ---------------------------------------------------------------------------
479
+ let autoUpdateScheduled = false;
480
+ /**
481
+ * Schedule `npm install -g <pkg>@<version>` to run AFTER this process exits.
482
+ *
483
+ * Why deferred: oclif lazily loads command modules from disk, so swapping the
484
+ * package while a command runs could hand it a mid-replace `dist/`. The child
485
+ * is detached + stdio-ignored so it outlives this process and holds no pipes.
486
+ * `spawn` inside an 'exit' handler works because the fork itself is
487
+ * synchronous; only its events would need the (already drained) loop.
488
+ *
489
+ * The version comes from our own release feed's `latest`, validated to a
490
+ * semver-ish token so the win32 shell path can't smuggle syntax.
491
+ */
492
+ function schedulePostExitSelfUpdate(pkg, version) {
493
+ if (autoUpdateScheduled)
494
+ return;
495
+ // Strict npm-name + semver-ish token validation — the win32 path spawns
496
+ // through a shell, so nothing with shell syntax may reach the spec.
497
+ const validPkg = /^@[a-z0-9][a-z0-9._-]*\/[a-z0-9][a-z0-9._-]*$/i.test(pkg) ||
498
+ /^[a-z0-9][a-z0-9._-]*$/i.test(pkg);
499
+ if (!validPkg || !/^[A-Za-z0-9._-]+$/.test(version))
500
+ return;
501
+ autoUpdateScheduled = true;
502
+ process.once('exit', () => {
503
+ try {
504
+ const npmBin = process.platform === 'win32' ? 'npm.cmd' : 'npm';
505
+ const child = (0, node_child_process_1.spawn)(npmBin, ['install', '-g', `${pkg}@${version}`], {
506
+ detached: true,
507
+ stdio: 'ignore',
508
+ shell: process.platform === 'win32',
509
+ });
510
+ child.unref();
511
+ }
512
+ catch {
513
+ /* a failed self-update just means the nudge returns next run */
514
+ }
515
+ });
516
+ }
196
517
  /**
197
518
  * Entry point, called once per command from `BaseCommand.init()`.
198
519
  *
199
- * Synchronous by design: it decides the nudge from the cache (no network
200
- * on the hot path) and only kicks off a background refresh when the cache
201
- * is stale, missing, or from a different server. Returns immediately.
520
+ * Synchronous by design: it decides from the cache (no network on the hot
521
+ * path) and only kicks off a background refresh when the cache is stale,
522
+ * missing, or from a different server. Returns immediately.
202
523
  */
203
524
  function maybeWarnOutdatedCli(opts) {
204
525
  try {
@@ -211,13 +532,24 @@ function maybeWarnOutdatedCli(opts) {
211
532
  const normalized = normalizeBaseUrl(opts.baseURL);
212
533
  const cache = readCache();
213
534
  // Decide from whatever we last saw. A STALE cache is still a valid
214
- // signal — CLI versions only move forward — so we nudge off it and
215
- // refresh in the background for next time. We only trust a cache that
216
- // was fetched against the same server the CLI is currently pointed at.
535
+ // signal — CLI versions only move forward — so we act on it and refresh
536
+ // in the background for next time. We only trust a cache that was fetched
537
+ // against the same server the CLI is currently pointed at.
217
538
  if (cache && cache.baseURL === normalized) {
218
- const line = buildNudgeLine(opts.currentVersion, cache.latest, cache.npmPackage);
219
- if (line)
220
- process.stderr.write(line);
539
+ const action = decideCliUpdateAction({
540
+ currentVersion: opts.currentVersion,
541
+ cache,
542
+ env: process.env,
543
+ isTTY: true,
544
+ });
545
+ if (action?.type === 'auto-update') {
546
+ // Record BEFORE scheduling so a same-second second invocation sees the
547
+ // attempt and doesn't double-spawn.
548
+ markAutoUpdateAttempt(action.version);
549
+ schedulePostExitSelfUpdate(action.pkg, action.version);
550
+ }
551
+ if (action)
552
+ process.stderr.write(action.line);
221
553
  }
222
554
  const stale = !cache || cache.baseURL !== normalized || Date.now() - cache.lastCheckAt > CHECK_TTL_MS;
223
555
  if (stale) {
@@ -29,29 +29,35 @@
29
29
  * never rename in place.
30
30
  */
31
31
  /**
32
- * The canonical daemon scope vocabulary. Six strings, frozen.
32
+ * The canonical daemon scope vocabulary. Seven strings, append-only.
33
33
  *
34
34
  * - `daemon:tools:bash` — bash tool execution
35
35
  * - `daemon:tools:fs:read` — Read tool (file read)
36
36
  * - `daemon:tools:fs:write` — Write + Edit tools (file mutation)
37
37
  * - `daemon:browser:cdp` — browser automation via CDP (reserved)
38
+ * - `daemon:native-ui:control` — native app GUI control via the helper
38
39
  * - `daemon:session:replay` — `daemon:session:replay` socket event
39
40
  * - `daemon:offline-queue` — daemon-initiated offline queue
40
41
  *
41
42
  * Order is the consent-screen render order: tools-first, I/O second,
42
43
  * control-flow last.
44
+ *
45
+ * `daemon:native-ui:control` is deliberately NOT folded into
46
+ * `daemon:tools:bash`: a token minted to run shell commands must not
47
+ * thereby be able to click around the user's desktop (OSK-11009).
43
48
  */
44
49
  export declare const SCOPES: Readonly<{
45
50
  readonly TOOLS_BASH: "daemon:tools:bash";
46
51
  readonly TOOLS_FS_READ: "daemon:tools:fs:read";
47
52
  readonly TOOLS_FS_WRITE: "daemon:tools:fs:write";
48
53
  readonly BROWSER_CDP: "daemon:browser:cdp";
54
+ readonly NATIVE_UI_CONTROL: "daemon:native-ui:control";
49
55
  readonly SESSION_REPLAY: "daemon:session:replay";
50
56
  readonly OFFLINE_QUEUE: "daemon:offline-queue";
51
57
  }>;
52
58
  export type DaemonScope = (typeof SCOPES)[keyof typeof SCOPES];
53
59
  /**
54
- * The six daemon scopes in canonical order. Frozen so consumers can
60
+ * The seven daemon scopes in canonical order. Frozen so consumers can
55
61
  * pass it directly to OAuth `scope` parameters without defensive
56
62
  * copies.
57
63
  */
@@ -64,7 +70,7 @@ export declare const VALID_DAEMON_SCOPE_SET: ReadonlySet<string>;
64
70
  export declare function isDaemonScope(s: unknown): s is DaemonScope;
65
71
  /**
66
72
  * `cli` — REST-only sign-in grant for first-party CLI clients. Peer
67
- * to the six daemon scopes; lives on `OAuthClient.allowedScopes` for
73
+ * to the daemon scopes; lives on `OAuthClient.allowedScopes` for
68
74
  * the `oversky-cli` client. See the data-schemas canonical for the
69
75
  * full reasoning behind keeping this OUT of `ALL_DAEMON_SCOPES` (the
70
76
  * grandfather sentinel `expandScopes(undefined)` would over-grant).
@@ -33,28 +33,34 @@ Object.defineProperty(exports, "__esModule", { value: true });
33
33
  exports.OAUTH_CLI_SCOPE = exports.VALID_DAEMON_SCOPE_SET = exports.ALL_DAEMON_SCOPES = exports.SCOPES = void 0;
34
34
  exports.isDaemonScope = isDaemonScope;
35
35
  /**
36
- * The canonical daemon scope vocabulary. Six strings, frozen.
36
+ * The canonical daemon scope vocabulary. Seven strings, append-only.
37
37
  *
38
38
  * - `daemon:tools:bash` — bash tool execution
39
39
  * - `daemon:tools:fs:read` — Read tool (file read)
40
40
  * - `daemon:tools:fs:write` — Write + Edit tools (file mutation)
41
41
  * - `daemon:browser:cdp` — browser automation via CDP (reserved)
42
+ * - `daemon:native-ui:control` — native app GUI control via the helper
42
43
  * - `daemon:session:replay` — `daemon:session:replay` socket event
43
44
  * - `daemon:offline-queue` — daemon-initiated offline queue
44
45
  *
45
46
  * Order is the consent-screen render order: tools-first, I/O second,
46
47
  * control-flow last.
48
+ *
49
+ * `daemon:native-ui:control` is deliberately NOT folded into
50
+ * `daemon:tools:bash`: a token minted to run shell commands must not
51
+ * thereby be able to click around the user's desktop (OSK-11009).
47
52
  */
48
53
  exports.SCOPES = Object.freeze({
49
54
  TOOLS_BASH: 'daemon:tools:bash',
50
55
  TOOLS_FS_READ: 'daemon:tools:fs:read',
51
56
  TOOLS_FS_WRITE: 'daemon:tools:fs:write',
52
57
  BROWSER_CDP: 'daemon:browser:cdp',
58
+ NATIVE_UI_CONTROL: 'daemon:native-ui:control',
53
59
  SESSION_REPLAY: 'daemon:session:replay',
54
60
  OFFLINE_QUEUE: 'daemon:offline-queue',
55
61
  });
56
62
  /**
57
- * The six daemon scopes in canonical order. Frozen so consumers can
63
+ * The seven daemon scopes in canonical order. Frozen so consumers can
58
64
  * pass it directly to OAuth `scope` parameters without defensive
59
65
  * copies.
60
66
  */
@@ -63,6 +69,7 @@ exports.ALL_DAEMON_SCOPES = Object.freeze([
63
69
  exports.SCOPES.TOOLS_FS_READ,
64
70
  exports.SCOPES.TOOLS_FS_WRITE,
65
71
  exports.SCOPES.BROWSER_CDP,
72
+ exports.SCOPES.NATIVE_UI_CONTROL,
66
73
  exports.SCOPES.SESSION_REPLAY,
67
74
  exports.SCOPES.OFFLINE_QUEUE,
68
75
  ]);
@@ -76,7 +83,7 @@ function isDaemonScope(s) {
76
83
  }
77
84
  /**
78
85
  * `cli` — REST-only sign-in grant for first-party CLI clients. Peer
79
- * to the six daemon scopes; lives on `OAuthClient.allowedScopes` for
86
+ * to the daemon scopes; lives on `OAuthClient.allowedScopes` for
80
87
  * the `oversky-cli` client. See the data-schemas canonical for the
81
88
  * full reasoning behind keeping this OUT of `ALL_DAEMON_SCOPES` (the
82
89
  * grandfather sentinel `expandScopes(undefined)` would over-grant).
@@ -320,6 +320,14 @@ declare const ENGINE_ENV_SUFFIXES: Readonly<{
320
320
  * engine must treat it as a hint: enforcement stays server-side.
321
321
  */
322
322
  maxInputTokens: "MAX_INPUT_TOKENS";
323
+ /**
324
+ * The session id the engine stamps into processes it spawns — the one
325
+ * variable on this table the engine WRITES rather than reads, so a child
326
+ * process (e.g. `skrr code handover --carry-session`) can name the session it
327
+ * is running inside without being told. Read with
328
+ * `readFirstPartyHarnessEngineEnv`: current namespace first, then legacy.
329
+ */
330
+ sessionId: "SESSION_ID";
323
331
  }>;
324
332
  export type FirstPartyHarnessEngineEnvKey = keyof typeof ENGINE_ENV_SUFFIXES;
325
333
  /**
@@ -357,7 +365,7 @@ export declare const FIRST_PARTY_HARNESS_ENGINE: Readonly<{
357
365
  * `readFirstPartyHarnessEngineEnv` to read one the way the engine does and
358
366
  * `firstPartyHarnessEngineEnvEntries` to set one every engine build honours.
359
367
  */
360
- env: Readonly<Record<"appName" | "serverPassword" | "serverUsername" | "home" | "config" | "scriptName" | "allowUpstreamEgress" | "compatOpencode" | "noCompatPrompts" | "maxInputTokens", string>>;
368
+ env: Readonly<Record<"appName" | "serverPassword" | "serverUsername" | "home" | "config" | "scriptName" | "allowUpstreamEgress" | "compatOpencode" | "noCompatPrompts" | "maxInputTokens" | "sessionId", string>>;
361
369
  }>;
362
370
  /**
363
371
  * Every name the engine reads for one purpose, current namespace first — the
@@ -457,6 +457,14 @@ const ENGINE_ENV_SUFFIXES = Object.freeze({
457
457
  * engine must treat it as a hint: enforcement stays server-side.
458
458
  */
459
459
  maxInputTokens: 'MAX_INPUT_TOKENS',
460
+ /**
461
+ * The session id the engine stamps into processes it spawns — the one
462
+ * variable on this table the engine WRITES rather than reads, so a child
463
+ * process (e.g. `skrr code handover --carry-session`) can name the session it
464
+ * is running inside without being told. Read with
465
+ * `readFirstPartyHarnessEngineEnv`: current namespace first, then legacy.
466
+ */
467
+ sessionId: 'SESSION_ID',
460
468
  });
461
469
  function engineEnvName(appName, key) {
462
470
  return `${appName.toUpperCase().replace(/-/g, '_')}_${ENGINE_ENV_SUFFIXES[key]}`;
@@ -11,7 +11,7 @@ export { configureAuthCore, getAuthLogger, getAuthConfigDir, getAuthKillSwitches
11
11
  export { PermanentAuthFailure, TransientAuthFailure, type PermanentAuthReason, type ReauthState, type TokenPair, } from './types.js';
12
12
  export { decodeJwtExpiry, decodeJwtPayload } from './jwtUtils.js';
13
13
  export { isAuthExpiredSseEvent, handleMidStreamAuthExpiry, type ParsedSseLike, type AuthExpiredCallbacks, type HandleMidStreamAuthExpiryResult, } from './authExpiredDetector.js';
14
- export { formatReauthMessage, EXIT_NEEDS_REAUTH, type AuthFailureReason } from './messages.js';
14
+ export { formatReauthMessage, reauthCommand, EXIT_NEEDS_REAUTH, type AuthFailureReason, } from './messages.js';
15
15
  export { classifyRefreshResponse, type RefreshResponseShape, type ClassifiedRefreshResult, type ClassifiedRefreshSuccess, type ClassifiedRefreshFailure, } from './refreshClassification.js';
16
16
  export { refreshDaemonToken, revokeDaemonRefreshSession, withAuthLock, persistReauthState, needsReauthState, clearReauthState, installLockExitHandlers, __refreshDiagnostics, __resetUnknown401StreaksForTest, UNKNOWN_401_BUDGET, } from './refresh.js';
17
17
  export { createRefreshScheduler, type RefreshScheduler, type RefreshSchedulerOptions, } from './refreshScheduler.js';