@skrr-ai/cli 0.1.8 → 0.1.9

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 (169) hide show
  1. package/dist/base-command.d.ts +27 -0
  2. package/dist/base-command.js +83 -11
  3. package/dist/commands/agent/message/send.js +1 -1
  4. package/dist/commands/agents/chat.d.ts +1 -1
  5. package/dist/commands/agents/chat.js +1 -1
  6. package/dist/commands/browser/install.d.ts +1 -1
  7. package/dist/commands/browser/install.js +10 -2
  8. package/dist/commands/browser/mcp-config.js +3 -1
  9. package/dist/commands/browser/skill/show.js +1 -1
  10. package/dist/commands/browser/status.js +4 -1
  11. package/dist/commands/browser/uninstall.d.ts +1 -1
  12. package/dist/commands/browser/uninstall.js +10 -2
  13. package/dist/commands/browser.d.ts +1 -1
  14. package/dist/commands/browser.js +3 -3
  15. package/dist/commands/code/index.js +6 -3
  16. package/dist/commands/code/install.d.ts +61 -0
  17. package/dist/commands/code/install.js +247 -0
  18. package/dist/commands/code/oversky-agent.d.ts +2 -1
  19. package/dist/commands/code/oversky-agent.js +12 -8
  20. package/dist/commands/commands.js +1 -1
  21. package/dist/commands/context.js +1 -1
  22. package/dist/commands/create-token.js +1 -1
  23. package/dist/commands/daemon/byok.d.ts +1 -0
  24. package/dist/commands/daemon/byok.js +14 -1
  25. package/dist/commands/daemon/index.js +18 -7
  26. package/dist/commands/daemon/install.d.ts +1 -0
  27. package/dist/commands/daemon/install.js +22 -3
  28. package/dist/commands/daemon/logs.d.ts +1 -0
  29. package/dist/commands/daemon/logs.js +4 -0
  30. package/dist/commands/daemon/start.d.ts +1 -0
  31. package/dist/commands/daemon/start.js +15 -2
  32. package/dist/commands/daemon/status.d.ts +1 -0
  33. package/dist/commands/daemon/status.js +14 -1
  34. package/dist/commands/daemon/stop.d.ts +1 -0
  35. package/dist/commands/daemon/stop.js +14 -1
  36. package/dist/commands/daemon/uninstall.d.ts +1 -0
  37. package/dist/commands/daemon/uninstall.js +15 -2
  38. package/dist/commands/daemon/usage.d.ts +1 -0
  39. package/dist/commands/daemon/usage.js +5 -1
  40. package/dist/commands/doctor.js +2 -2
  41. package/dist/commands/github/allow-tools.d.ts +1 -0
  42. package/dist/commands/github/app/install.d.ts +1 -0
  43. package/dist/commands/github/app/status.d.ts +1 -0
  44. package/dist/commands/github/connect.d.ts +1 -0
  45. package/dist/commands/github/connections.d.ts +1 -0
  46. package/dist/commands/github/disconnect.d.ts +1 -0
  47. package/dist/commands/github/finalize.d.ts +1 -0
  48. package/dist/commands/github/reconnect.d.ts +1 -0
  49. package/dist/commands/github/run.d.ts +1 -0
  50. package/dist/commands/github/tools.d.ts +1 -0
  51. package/dist/commands/goals/create.js +2 -2
  52. package/dist/commands/goals/show.js +5 -0
  53. package/dist/commands/harnesses/list.js +14 -3
  54. package/dist/commands/harnesses/show.js +14 -0
  55. package/dist/commands/instructions/activate.js +1 -1
  56. package/dist/commands/instructions/archive-version.js +1 -1
  57. package/dist/commands/instructions/delete.js +1 -1
  58. package/dist/commands/instructions/diff.js +1 -1
  59. package/dist/commands/instructions/install.js +7 -1
  60. package/dist/commands/instructions/restore.js +1 -1
  61. package/dist/commands/instructions/show.js +17 -1
  62. package/dist/commands/instructions/update.js +1 -1
  63. package/dist/commands/integrations/connections/connect.d.ts +1 -0
  64. package/dist/commands/integrations/connections/disconnect.d.ts +1 -0
  65. package/dist/commands/integrations/connections/finalize.d.ts +1 -0
  66. package/dist/commands/integrations/connections/list.d.ts +1 -0
  67. package/dist/commands/integrations/connections/reconnect.d.ts +1 -0
  68. package/dist/commands/integrations/execute.d.ts +1 -0
  69. package/dist/commands/integrations/search.d.ts +1 -0
  70. package/dist/commands/integrations/toolkits.d.ts +1 -0
  71. package/dist/commands/integrations/tools/allow.d.ts +1 -0
  72. package/dist/commands/integrations/tools/list.d.ts +1 -0
  73. package/dist/commands/list-daemons.d.ts +2 -7
  74. package/dist/commands/list-daemons.js +13 -13
  75. package/dist/commands/login.js +73 -31
  76. package/dist/commands/logout.js +52 -1
  77. package/dist/commands/machines/hosted/start.js +1 -1
  78. package/dist/commands/pair.js +2 -2
  79. package/dist/commands/projects/create.js +6 -1
  80. package/dist/commands/projects/tasks.js +6 -1
  81. package/dist/commands/revoke-daemon.js +6 -2
  82. package/dist/commands/set-capabilities.js +6 -2
  83. package/dist/commands/skills/install.js +1 -1
  84. package/dist/commands/skills/library.js +2 -2
  85. package/dist/commands/spaces/create.js +6 -2
  86. package/dist/commands/tasks/complete.d.ts +1 -1
  87. package/dist/commands/tasks/complete.js +21 -8
  88. package/dist/commands/tasks/create.js +4 -1
  89. package/dist/commands/tasks/current.js +1 -1
  90. package/dist/commands/tasks/delete.d.ts +1 -0
  91. package/dist/commands/tasks/delete.js +9 -0
  92. package/dist/commands/tasks/export.js +5 -1
  93. package/dist/commands/tasks/follow-up.js +2 -1
  94. package/dist/commands/tasks/list.js +5 -1
  95. package/dist/commands/tasks/pr.js +1 -1
  96. package/dist/commands/tasks/show.js +10 -1
  97. package/dist/commands/tasks/triage.js +2 -1
  98. package/dist/commands/tasks/update.js +4 -1
  99. package/dist/commands/tasks/upsert.js +4 -1
  100. package/dist/commands/usage.js +1 -1
  101. package/dist/lib/agentic-stream.js +21 -1
  102. package/dist/lib/api-fetch.d.ts +1 -1
  103. package/dist/lib/api-fetch.js +1 -1
  104. package/dist/lib/auth-core-init.js +23 -3
  105. package/dist/lib/auth-storage.d.ts +0 -12
  106. package/dist/lib/auth-storage.js +37 -2
  107. package/dist/lib/config.d.ts +3 -3
  108. package/dist/lib/config.js +327 -26
  109. package/dist/lib/created-line.d.ts +22 -0
  110. package/dist/lib/created-line.js +25 -0
  111. package/dist/lib/daemon-binding.d.ts +29 -0
  112. package/dist/lib/daemon-binding.js +63 -0
  113. package/dist/lib/daemon-ref.d.ts +31 -0
  114. package/dist/lib/daemon-ref.js +47 -0
  115. package/dist/lib/daemonBroker.js +1 -1
  116. package/dist/lib/delegated-cli.js +3 -3
  117. package/dist/lib/exec-oversky.d.ts +18 -1
  118. package/dist/lib/exec-oversky.js +21 -4
  119. package/dist/lib/html-text.d.ts +15 -0
  120. package/dist/lib/html-text.js +40 -0
  121. package/dist/lib/keychain.d.ts +43 -0
  122. package/dist/lib/keychain.js +145 -4
  123. package/dist/lib/login.js +3 -3
  124. package/dist/lib/node-adapter.js +1 -1
  125. package/dist/lib/oauthLogin.js +17 -6
  126. package/dist/lib/sky-code-agent.d.ts +1 -1
  127. package/dist/lib/sky-code-agent.js +8 -8
  128. package/dist/lib/sky-code-broker.js +18 -2
  129. package/dist/lib/sky-code-doctor.js +120 -4
  130. package/dist/lib/sky-code-managed.d.ts +12 -0
  131. package/dist/lib/sky-code-managed.js +21 -7
  132. package/dist/lib/sky-code.d.ts +16 -1
  133. package/dist/lib/sky-code.js +102 -4
  134. package/dist/lib/task-execution.js +4 -11
  135. package/dist/lib/tasks.d.ts +1 -0
  136. package/dist/lib/tasks.js +9 -6
  137. package/dist/lib/update-check.js +1 -1
  138. package/dist/lib/usage-discovery.js +1 -1
  139. package/dist/lib/web-url.js +12 -1
  140. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/credentialResolver.d.ts +1 -1
  141. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/credentialResolver.js +2 -2
  142. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/index.d.ts +1 -0
  143. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/index.js +13 -1
  144. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/kek/linux.js +16 -3
  145. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/legacyStatePreflight.d.ts +0 -9
  146. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/legacyStatePreflight.js +18 -1
  147. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/loginLocalhost.js +3 -3
  148. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/messages.js +3 -3
  149. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/runtime.d.ts +7 -3
  150. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/skyCodeChannels.d.ts +96 -0
  151. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/skyCodeChannels.js +115 -0
  152. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/credentialResolver.d.ts +1 -1
  153. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/credentialResolver.js +2 -2
  154. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/index.d.ts +1 -0
  155. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/index.js +1 -0
  156. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/kek/linux.js +16 -3
  157. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/legacyStatePreflight.d.ts +0 -9
  158. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/legacyStatePreflight.js +18 -1
  159. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/loginLocalhost.js +3 -3
  160. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/messages.js +3 -3
  161. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/runtime.d.ts +7 -3
  162. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/skyCodeChannels.d.ts +96 -0
  163. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/skyCodeChannels.js +107 -0
  164. package/dist/node_modules/@skrr-ai/auth-core/package.json +1 -1
  165. package/dist/node_modules/@skrr-ai/data-provider/index.js +4206 -4191
  166. package/dist/node_modules/@skrr-ai/inference-broker/dist/cjs/managed-inference-broker.js +2 -2
  167. package/dist/node_modules/@skrr-ai/inference-broker/dist/esm/managed-inference-broker.js +2 -2
  168. package/oclif.manifest.json +9924 -3352
  169. package/package.json +22 -19
@@ -298,7 +298,7 @@ function createNodeAdapter(opts = {}) {
298
298
  else {
299
299
  // Refresh-token rotation rejected (revoked / family burned /
300
300
  // passwordChangedAt cutover). As a last resort, ask the local
301
- // oversky daemon to broker a fresh cli-scope family — covers
301
+ // skrr runtime to broker a fresh cli-scope family — covers
302
302
  // "user reset their account but daemon is still authed",
303
303
  // "stale pre-broker keychain token", and similar drift cases.
304
304
  const brokered = await tryDaemonBrokerRecovery();
@@ -45,6 +45,7 @@ const node_child_process_1 = require("node:child_process");
45
45
  const auth_storage_1 = require("./auth-storage");
46
46
  const config_1 = require("./config");
47
47
  const device_id_1 = require("./device-id");
48
+ const publicEndpoints_generated_1 = require("./publicEndpoints.generated");
48
49
  // ---------------------------------------------------------------------------
49
50
  // PKCE helpers
50
51
  // ---------------------------------------------------------------------------
@@ -64,17 +65,27 @@ function generateState() {
64
65
  // ---------------------------------------------------------------------------
65
66
  const CLIENT_ID = 'oversky-cli';
66
67
  const DEFAULT_SCOPES = Object.freeze(['cli']);
68
+ // Both directions are DERIVED from config/public-endpoints.json via the
69
+ // generated constant rather than hand-listed. The hand-listed pair predated the
70
+ // domain cutover and knew only `oversky.*`, so the CURRENT prod apex
71
+ // (`skrr.ai`) resolved to itself: a login against it would exchange tokens on
72
+ // the app origin instead of the API one. Mirrors the same derivation in
73
+ // `web-url.ts`, which needs the inverse map for exactly the same reason.
67
74
  const OAUTH_API_URL_FROM_WEB = {
75
+ ...Object.fromEntries(Object.values(publicEndpoints_generated_1.OVERSKY_ENVIRONMENT_ENDPOINTS).map((e) => [
76
+ e.appUrl.toLowerCase(),
77
+ e.realtimeUrl,
78
+ ])),
79
+ // Prod's retained previous origin, and the `www.` spelling of it.
68
80
  'https://oversky.ai': 'https://api.oversky.ai',
69
81
  'https://www.oversky.ai': 'https://api.oversky.ai',
70
- // Dev split onto its own apex (oversky.dev) with an ALB-direct api. subdomain.
71
- // Mirrors config/public-endpoints.json so `skrr login` against dev exchanges
72
- // tokens on the same origin family prod uses.
73
- 'https://oversky.dev': 'https://api.oversky.dev',
74
82
  };
75
83
  const OAUTH_WEB_URL_FROM_API = {
84
+ ...Object.fromEntries(Object.values(publicEndpoints_generated_1.OVERSKY_ENVIRONMENT_ENDPOINTS).map((e) => [
85
+ e.realtimeUrl.toLowerCase(),
86
+ e.appUrl,
87
+ ])),
76
88
  'https://api.oversky.ai': 'https://oversky.ai',
77
- 'https://api.oversky.dev': 'https://oversky.dev',
78
89
  };
79
90
  function resolveOAuthEndpoints(serverUrl) {
80
91
  const normalized = serverUrl.replace(/\/+$/, '');
@@ -351,7 +362,7 @@ async function runOAuthLogin(opts) {
351
362
  // refresh.ts:169 and :296. So the credential was rejected by its
352
363
  // own issuer check the instant it was written:
353
364
  //
354
- // [sky] Ignoring stored credentials issued by
365
+ // [skrr] Ignoring stored credentials issued by
355
366
  // https://api.oversky.ai; skrr is configured for
356
367
  // https://oversky.ai.
357
368
  //
@@ -113,7 +113,7 @@ export interface SkyCodeAgentOptions {
113
113
  * May resolution CREATE the default agent when nothing else answers?
114
114
  *
115
115
  * Defaults to true, because a session that cannot name an agent cannot run.
116
- * `skrr code oversky-agent` (with no `--create`) passes false: a command whose
116
+ * `skrr code skrr-agent` (with no `--create`) passes false: a command whose
117
117
  * job is to report what would happen must not make it happen.
118
118
  */
119
119
  createDefault?: boolean;
@@ -96,7 +96,7 @@ exports.SkyCodeAgentError = SkyCodeAgentError;
96
96
  */
97
97
  async function resolveSkyCodeAgent(explicit, deps = {}, options = {}) {
98
98
  const configured = deps.configuredAgentId ?? (() => (0, config_1.loadConfig)().skyCodeAgentId);
99
- const explicitLabel = options.explicitLabel ?? sky_code_managed_1.OVERSKY_AGENT_FLAG;
99
+ const explicitLabel = options.explicitLabel ?? sky_code_managed_1.SKRR_AGENT_FLAG;
100
100
  let cached = null;
101
101
  const roster = async () => {
102
102
  if (cached)
@@ -123,7 +123,7 @@ async function resolveSkyCodeAgent(explicit, deps = {}, options = {}) {
123
123
  }
124
124
  if (byName.length > 1) {
125
125
  throw new SkyCodeAgentError('agent-ambiguous', `${describeSource(source, ref, explicitLabel)} matches ${byName.length} agents. ` +
126
- `Pass ${sky_code_managed_1.OVERSKY_AGENT_FLAG} with an id instead: ${candidates(byName)}`);
126
+ `Pass ${sky_code_managed_1.SKRR_AGENT_FLAG} with an id instead: ${candidates(byName)}`);
127
127
  }
128
128
  // Not in the bounded roster. It may still be a real id belonging to a user with
129
129
  // more agents than the roster shows, so ask directly before refusing.
@@ -186,7 +186,7 @@ async function resolveSkyCodeAgent(explicit, deps = {}, options = {}) {
186
186
  // exactly this and belongs to nobody else.
187
187
  // `createDefault: false` makes this a READ: the endpoint is get-or-create
188
188
  // and has no read-only mode, so a caller that is only ASKING
189
- // (`skrr code oversky-agent`) recognises an existing default from the roster
189
+ // (`skrr code skrr-agent`) recognises an existing default from the roster
190
190
  // it has already fetched instead. `defaultForHarness` rides the same
191
191
  // summary projection `author` does, so this costs no extra request.
192
192
  //
@@ -220,8 +220,8 @@ async function resolveSkyCodeAgent(explicit, deps = {}, options = {}) {
220
220
  if (isAbortError(err))
221
221
  throw err;
222
222
  throw new SkyCodeAgentError('agent-unset', `could not establish your default skrr Code agent — ${message(err)}. ` +
223
- `Pass ${sky_code_managed_1.OVERSKY_AGENT_FLAG} <id-or-name>, or set one with ` +
224
- '`skrr code oversky-agent --set <id>`' +
223
+ `Pass ${sky_code_managed_1.SKRR_AGENT_FLAG} <id-or-name>, or set one with ` +
224
+ '`skrr code skrr-agent --set <id>`' +
225
225
  (rows.length ? `. Yours: ${candidates(rows)}` : ''));
226
226
  }
227
227
  // Asked, not told: the caller opted out of creation, so "no default" is a fact
@@ -229,14 +229,14 @@ async function resolveSkyCodeAgent(explicit, deps = {}, options = {}) {
229
229
  if (options.createDefault === false) {
230
230
  throw new SkyCodeAgentError('agent-unset', 'nothing is configured and you have no skrr Code default agent yet. ' +
231
231
  'One is created automatically the first time you run a managed session — ' +
232
- 'or make it now with `skrr code oversky-agent --create`' +
232
+ 'or make it now with `skrr code skrr-agent --create`' +
233
233
  (rows.length ? `. Yours: ${candidates(rows)}` : ''));
234
234
  }
235
235
  // The endpoint answered without an agent. Nothing here can repair that, but
236
236
  // the user still has every ordinary way to name one.
237
237
  throw new SkyCodeAgentError('agent-unset', rows.length
238
238
  ? `skrr Code has no default agent for you and will not pick one of your ${rows.length}. ` +
239
- `Pass ${sky_code_managed_1.OVERSKY_AGENT_FLAG} <id-or-name>, or set "${sky_code_managed_1.AGENT_CONFIG_KEY}" in ` +
239
+ `Pass ${sky_code_managed_1.SKRR_AGENT_FLAG} <id-or-name>, or set "${sky_code_managed_1.AGENT_CONFIG_KEY}" in ` +
240
240
  `${configPathHint()}. Yours: ${candidates(rows)}`
241
241
  : 'you have no agents and no default could be created, yet a managed skrr Code session ' +
242
242
  'runs as one. Create an agent in the skrr app first');
@@ -278,7 +278,7 @@ async function setConfiguredAgentId(ref, deps = {}, options = {}) {
278
278
  // Name the thing the user actually typed. Without this a bad `--set` value
279
279
  // is refused with "--oversky-agent \"typo\" is not an agent you can run",
280
280
  // pointing at a flag that was never on the command line.
281
- explicitLabel: 'skrr code oversky-agent --set',
281
+ explicitLabel: 'skrr code skrr-agent --set',
282
282
  ...options,
283
283
  });
284
284
  writeConfigKey(resolved.id);
@@ -239,7 +239,7 @@ async function acquireManagedSession(input = {}, deps = {}) {
239
239
  if (agent.createdNow) {
240
240
  input.log?.(`Created "${agent.name ?? agent.id}" as your default skrr Code agent — ` +
241
241
  'this session, and future ones, are attributed to it. ' +
242
- 'Change it with `skrr code oversky-agent --set <id-or-name>`.');
242
+ 'Change it with `skrr code skrr-agent --set <id-or-name>`.');
243
243
  }
244
244
  const minted = await mintSessionToken({ sessionId, processStartId, agentId: agent.id, actorId: newId() }, api, acquisition.signal);
245
245
  sessionToken = minted.token;
@@ -888,11 +888,27 @@ function describe(err) {
888
888
  *
889
889
  * The predicate is `hasProviderCredential`, the same one that decides what the
890
890
  * engine actually inherits (`sky-code.ts`), so the sentence and the spawn cannot
891
- * disagree.
891
+ * disagree. `strippedProviderCredentialNames` covers the third case that
892
+ * predicate cannot see: the machine HAS a provider credential and this run
893
+ * removes it, which reads as absence and is not.
892
894
  */
893
895
  function fallbackTail(env) {
894
896
  if ((0, sky_code_1.hasProviderCredential)(env))
895
897
  return 'Continuing with your own provider credentials.';
898
+ // Absence and removal are different problems, and the old sentence said the
899
+ // first when the second was true: on a machine whose only credential is an AWS
900
+ // profile the engine runs fine on its own and fails through `skrr code`,
901
+ // because `AWS_*` is stripped on the way in. Being told "no provider
902
+ // credential is set here" sends that user to buy a key they do not need.
903
+ const stripped = (0, sky_code_1.strippedProviderCredentialNames)(env);
904
+ if (stripped.length > 0) {
905
+ return (`${stripped.join(', ')} is set here, but this run does not pass it to the engine — ` +
906
+ 'it is stripped so a model-driven process opening other people\u2019s repositories cannot ' +
907
+ 'reuse a cloud credential. So the engine starts without one and its first request will ' +
908
+ 'fail. Export a provider key the engine may inherit (any `*_API_KEY`, e.g. ' +
909
+ 'OPENROUTER_API_KEY), resolve the reason above, or run the engine directly if you ' +
910
+ 'intend to spend that credential (`skrr code doctor` shows where it is).');
911
+ }
896
912
  return ('No provider credential is set here either, so the engine will start without one and ' +
897
913
  'its first request will fail — set OPENROUTER_API_KEY, or resolve the reason above ' +
898
914
  '(`skrr code doctor`).');
@@ -32,6 +32,7 @@ exports.formatReport = formatReport;
32
32
  const node_fs_1 = require("node:fs");
33
33
  const node_path_1 = __importDefault(require("node:path"));
34
34
  const sky_code_1 = require("./sky-code");
35
+ const auth_core_1 = require("@skrr-ai/auth-core");
35
36
  const harness_tiers_1 = require("./harness-tiers");
36
37
  const config_1 = require("./config");
37
38
  const sky_code_managed_1 = require("./sky-code-managed");
@@ -39,10 +40,124 @@ const sky_code_managed_1 = require("./sky-code-managed");
39
40
  function projectStateDir(cwd) {
40
41
  return node_path_1.default.join(node_path_1.default.resolve(cwd), '.sky-code');
41
42
  }
43
+ /**
44
+ * Which release channel this machine follows, and where its manifest lives.
45
+ *
46
+ * `notInstalledMessage()` has always ended by promising that this command names
47
+ * "which channel this machine follows and whether that channel has a published
48
+ * release", and nothing here knew what a channel was — the whole vocabulary sat
49
+ * in `daemon/src/sky-code/channels.ts`, whose only importer was the daemon's own
50
+ * installer. So the user with no engine, who is exactly the audience for that
51
+ * sentence, was sent to a command that could not answer (dogfood OSK-274).
52
+ *
53
+ * It reports the channel and the exact URL, and does NOT fetch it. The doctor is
54
+ * documented as safe to run in any context and reads only env, config and one
55
+ * `existsSync`; adding a network call to satisfy a sentence would trade a broken
56
+ * promise for a diagnostic that hangs on a captive portal. Printing the URL puts
57
+ * the answer one copy-paste away and keeps the property — and the promise is
58
+ * reworded to match what is delivered rather than the other way round.
59
+ *
60
+ * `warn` on an unrecognised channel, because `resolveSkyCodeChannel` falls back
61
+ * to the default rather than throwing: a typo must not brick updates, and a
62
+ * silent fallback must not look like agreement.
63
+ */
64
+ function releaseChannelCheck(env) {
65
+ const { channel, invalid } = (0, auth_core_1.resolveSkyCodeChannel)(env);
66
+ const url = (0, auth_core_1.resolveChannelManifestUrl)({
67
+ base: (0, auth_core_1.skyCodeFeedBase)(env),
68
+ manifestFilename: auth_core_1.SKY_CODE_MANIFEST_FILE,
69
+ channel,
70
+ });
71
+ if (invalid) {
72
+ return {
73
+ name: 'release-channel',
74
+ status: 'warn',
75
+ detail: `${auth_core_1.SKY_CODE_CHANNEL_ENV}='${invalid}' is not a channel; following '${channel}' instead — ${url}`,
76
+ remedy: `Set ${auth_core_1.SKY_CODE_CHANNEL_ENV} to one of internal, canary, beta, stable, or unset it to follow the default.`,
77
+ };
78
+ }
79
+ return {
80
+ name: 'release-channel',
81
+ status: 'ok',
82
+ detail: `${channel} — ${url}`,
83
+ remedy: `Fetch that URL to see whether the channel has a published release, and which version.`,
84
+ };
85
+ }
86
+ /**
87
+ * What the pre-rename engine directory still holds, for a machine that has moved on.
88
+ *
89
+ * Round 1 gave both readers a fallback to `~/.oversky/sky-code/bin` so nothing
90
+ * BREAKS on a machine that installed before the rename. Nothing was given the job
91
+ * of finishing the move: no installer sweep, and — once the current root wins —
92
+ * no mention anywhere. This machine converged on two engine directories and
93
+ * reported one, the older holding 713 MB across six binaries (dogfood OSK-278).
94
+ *
95
+ * Flat, never recursive, and failures are swallowed: this is a footnote on a
96
+ * diagnostic, and a doctor that throws while counting bytes it was only going to
97
+ * mention has made things worse than the clutter it was reporting.
98
+ */
99
+ function strandedLegacyEngine(env) {
100
+ const exeName = process.platform === 'win32' ? 'sky-code.exe' : 'sky-code';
101
+ const legacy = (0, sky_code_1.legacyManagedEnginePath)(exeName, env);
102
+ if (!legacy)
103
+ return null;
104
+ const dir = node_path_1.default.dirname(legacy);
105
+ try {
106
+ const entries = (0, node_fs_1.readdirSync)(dir);
107
+ let bytes = 0;
108
+ let files = 0;
109
+ for (const entry of entries) {
110
+ const stats = (0, node_fs_1.statSync)(node_path_1.default.join(dir, entry));
111
+ if (!stats.isFile())
112
+ continue;
113
+ files += 1;
114
+ bytes += stats.size;
115
+ }
116
+ return files > 0 ? { dir, files, bytes } : null;
117
+ }
118
+ catch {
119
+ return null;
120
+ }
121
+ }
122
+ /** Bytes as the size a human would say out loud. */
123
+ function humanBytes(bytes) {
124
+ const mb = bytes / 1024 / 1024;
125
+ return mb >= 1024 ? `${(mb / 1024).toFixed(1)} GB` : `${Math.round(mb)} MB`;
126
+ }
42
127
  function engineCheck(env) {
43
128
  const { path: bin, source } = (0, sky_code_1.resolveEngine)(env);
129
+ if (bin && source === 'legacy-managed') {
130
+ // `ok`, because it runs and this is the resolution the daemon has always
131
+ // made. The remedy is here because the resolution is SURPRISING: the path
132
+ // says `.oversky` on a CLI that says `skrr` everywhere else, and the next
133
+ // daemon-driven install will write to `~/.skrr` and leave two copies of a
134
+ // hundred-megabyte binary on disk with no hint which one is live.
135
+ return {
136
+ name: 'engine',
137
+ status: 'ok',
138
+ detail: `${bin} (resolved via ${source} — the pre-rename location)`,
139
+ remedy: 'It works, and nothing has to change today. Installing the engine again ' +
140
+ `through the daemon writes it to ${(0, sky_code_1.managedEnginePath)('sky-code', env)}; ` +
141
+ 'the copy above can be deleted once it does.',
142
+ };
143
+ }
44
144
  if (bin) {
45
- return { name: 'engine', status: 'ok', detail: `${bin} (resolved via ${source})` };
145
+ // The engine resolved from the current root and the pre-rename directory
146
+ // may still be sitting there. Said here rather than in its own check because
147
+ // it is a footnote on a healthy answer, not a finding of its own.
148
+ const stranded = strandedLegacyEngine(env);
149
+ return {
150
+ name: 'engine',
151
+ status: 'ok',
152
+ detail: `${bin} (resolved via ${source})`,
153
+ ...(stranded
154
+ ? {
155
+ remedy: `${stranded.dir} still holds ${stranded.files} file(s), ${humanBytes(stranded.bytes)}, ` +
156
+ 'from before the config root moved. Nothing reads it now that the engine above ' +
157
+ 'resolves, and nothing removes it either — delete it when you want the space back.',
158
+ }
159
+ : {}),
160
+ };
46
161
  }
47
162
  const override = env[sky_code_1.ENGINE_PATH_ENV];
48
163
  if (override && !node_path_1.default.isAbsolute(override)) {
@@ -461,7 +576,7 @@ function sessionAuthorityCheck(env) {
461
576
  remedy: 'Intended for local use, and nothing to fix. Worth knowing because it is NOT the same ' +
462
577
  'trust plane as a daemon-dispatched run — and neither plane is an OS-level sandbox ' +
463
578
  '(no seccomp, container, or namespace). An untrusted autonomous workload needs a hosted ' +
464
- 'or container profile; see the fork’s docs/sky-code/threat-model.md.',
579
+ 'or container profile; see sky-code/docs/sky-code/threat-model.md.',
465
580
  };
466
581
  }
467
582
  }
@@ -473,7 +588,7 @@ function sessionAuthorityCheck(env) {
473
588
  * a `/api/agents` read, and this module's whole contract is that it answers from
474
589
  * env, one config read and one `existsSync` — that is what lets `skrr code doctor`
475
590
  * run before the auth plane is configured, and on a machine with no network.
476
- * `skrr code oversky-agent` is the command that resolves for real.
591
+ * `skrr code skrr-agent` is the command that resolves for real.
477
592
  *
478
593
  * Never a `warn`. An unset value is the normal, supported state now that
479
594
  * resolution ends in a default agent rather than a refusal; flagging it would
@@ -507,12 +622,13 @@ function agentAttributionCheck() {
507
622
  name: 'agent',
508
623
  status: 'ok',
509
624
  detail: `no ${sky_code_managed_1.AGENT_CONFIG_KEY} set — sessions use your sole owned agent, else your default ${sky_code_managed_1.SKY_CODE_HARNESS} agent`,
510
- remedy: 'Run `skrr code oversky-agent` to see which, or `skrr code oversky-agent --set <id>` to pin one.',
625
+ remedy: 'Run `skrr code skrr-agent` to see which, or `skrr code skrr-agent --set <id>` to pin one.',
511
626
  };
512
627
  }
513
628
  function runDoctor(cwd = process.cwd(), env = process.env) {
514
629
  const checks = [
515
630
  engineCheck(env),
631
+ releaseChannelCheck(env),
516
632
  stateDirCheck(cwd, env),
517
633
  compatCheck(cwd, env),
518
634
  opencodeCheck(cwd),
@@ -46,7 +46,19 @@ export declare const MANAGED_ENV_FLAG = "OVERSKY_SKY_CODE_MANAGED";
46
46
  * `skrr code --agent reviewer` is the engine's flag and is pinned as such by
47
47
  * `sky-code-passthrough.spec.ts`. A bare `--agent` here would steal it.
48
48
  */
49
+ export declare const SKRR_AGENT_FLAG = "--skrr-agent";
50
+ /**
51
+ * The pre-rename spelling, still accepted.
52
+ *
53
+ * It is in muscle memory and in scripts, and `skrr code` forwards argv verbatim
54
+ * — so a flag this CLI stops recognising is not an error, it is silently handed
55
+ * to the engine, which rejects it with a message about a flag the user did not
56
+ * think they were passing. Accepting both is the only version of this rename
57
+ * that fails safely.
58
+ */
49
59
  export declare const OVERSKY_AGENT_FLAG = "--oversky-agent";
60
+ /** Every spelling the argv scanner honours, primary first. */
61
+ export declare const AGENT_FLAG_SPELLINGS: readonly ["--skrr-agent", "--oversky-agent"];
50
62
  /** The config key `skrr code` reads when the flag is absent. */
51
63
  export declare const AGENT_CONFIG_KEY = "skyCodeAgentId";
52
64
  /**
@@ -32,7 +32,7 @@
32
32
  * reason: the user is about to spend their own key and must know it.
33
33
  */
34
34
  Object.defineProperty(exports, "__esModule", { value: true });
35
- exports.BROKER_SOCKET_ENV = exports.MANAGED_SESSION_ENV = exports.SKY_CODE_HARNESS = exports.AGENT_CONFIG_KEY = exports.OVERSKY_AGENT_FLAG = exports.MANAGED_ENV_FLAG = void 0;
35
+ exports.BROKER_SOCKET_ENV = exports.MANAGED_SESSION_ENV = exports.SKY_CODE_HARNESS = exports.AGENT_CONFIG_KEY = exports.AGENT_FLAG_SPELLINGS = exports.OVERSKY_AGENT_FLAG = exports.SKRR_AGENT_FLAG = exports.MANAGED_ENV_FLAG = void 0;
36
36
  exports.resolveTrustPlane = resolveTrustPlane;
37
37
  exports.skyCodeServerUrl = skyCodeServerUrl;
38
38
  exports.managedSkipReason = managedSkipReason;
@@ -59,7 +59,19 @@ exports.MANAGED_ENV_FLAG = 'OVERSKY_SKY_CODE_MANAGED';
59
59
  * `skrr code --agent reviewer` is the engine's flag and is pinned as such by
60
60
  * `sky-code-passthrough.spec.ts`. A bare `--agent` here would steal it.
61
61
  */
62
+ exports.SKRR_AGENT_FLAG = '--skrr-agent';
63
+ /**
64
+ * The pre-rename spelling, still accepted.
65
+ *
66
+ * It is in muscle memory and in scripts, and `skrr code` forwards argv verbatim
67
+ * — so a flag this CLI stops recognising is not an error, it is silently handed
68
+ * to the engine, which rejects it with a message about a flag the user did not
69
+ * think they were passing. Accepting both is the only version of this rename
70
+ * that fails safely.
71
+ */
62
72
  exports.OVERSKY_AGENT_FLAG = '--oversky-agent';
73
+ /** Every spelling the argv scanner honours, primary first. */
74
+ exports.AGENT_FLAG_SPELLINGS = [exports.SKRR_AGENT_FLAG, exports.OVERSKY_AGENT_FLAG];
63
75
  /** The config key `skrr code` reads when the flag is absent. */
64
76
  exports.AGENT_CONFIG_KEY = 'skyCodeAgentId';
65
77
  /**
@@ -238,19 +250,21 @@ function takeOverskyAgentFlag(passthrough) {
238
250
  let agentRef;
239
251
  for (let i = 0; i < passthrough.length; i += 1) {
240
252
  const token = passthrough[i];
241
- if (token === exports.OVERSKY_AGENT_FLAG) {
242
- // Last one wins, matching how every argv parser treats a repeated flag.
253
+ if (exports.AGENT_FLAG_SPELLINGS.includes(token)) {
254
+ // Last one wins, matching how every argv parser treats a repeated flag
255
+ // and across spellings too, so `--oversky-agent a --skrr-agent b` is `b`.
243
256
  const value = passthrough[i + 1];
244
- // A trailing `--oversky-agent` with no value must not swallow the next
245
- // token (there is none) nor leave the flag in the argv.
257
+ // A trailing flag with no value must not swallow the next token (there is
258
+ // none) nor leave the flag in the argv.
246
259
  if (value !== undefined && !value.startsWith('-')) {
247
260
  agentRef = value;
248
261
  i += 1;
249
262
  }
250
263
  continue;
251
264
  }
252
- if (token.startsWith(`${exports.OVERSKY_AGENT_FLAG}=`)) {
253
- agentRef = token.slice(exports.OVERSKY_AGENT_FLAG.length + 1);
265
+ const inline = exports.AGENT_FLAG_SPELLINGS.find((f) => token.startsWith(`${f}=`));
266
+ if (inline) {
267
+ agentRef = token.slice(inline.length + 1);
254
268
  continue;
255
269
  }
256
270
  engineArgv.push(token);
@@ -31,9 +31,23 @@ export declare function skyCodeInstructionHome(env?: NodeJS.ProcessEnv): string;
31
31
  * `scripts/sky-code/build.mjs --install` all put the engine.
32
32
  */
33
33
  export declare function managedEnginePath(exeName: string, env?: NodeJS.ProcessEnv): string;
34
+ /**
35
+ * The same managed location under the PREVIOUS config root.
36
+ *
37
+ * The root moved `~/.oversky` → `~/.skrr` in the skrr rename, and an engine
38
+ * installed before that is still on disk under the old one. `daemon/src/
39
+ * binary-resolver.ts` was given this fallback and this module was not, so on
40
+ * the same machine the daemon found the engine and `skrr code` reported that no
41
+ * engine was installed — the same product, the same 106 MB binary, two answers.
42
+ *
43
+ * Returns null when an explicit `OVERSKY_CONFIG_DIR` is set, matching the
44
+ * daemon: that override names one root deliberately, and reaching past it to a
45
+ * hard-coded home would defeat the pinning {@link engineHome} relies on.
46
+ */
47
+ export declare function legacyManagedEnginePath(exeName: string, env?: NodeJS.ProcessEnv): string | null;
34
48
  export interface EngineResolution {
35
49
  path: string | null;
36
- source: 'env' | 'path' | 'managed' | 'fallback' | 'unresolved';
50
+ source: 'env' | 'path' | 'managed' | 'legacy-managed' | 'fallback' | 'unresolved';
37
51
  }
38
52
  /**
39
53
  * Resolve the engine binary, reporting WHERE it came from.
@@ -185,6 +199,7 @@ export interface EngineSpawnOptions {
185
199
  export declare function inheritedProviderCredentials(env: NodeJS.ProcessEnv): Record<string, string>;
186
200
  /** Whether an unmanaged run has anything to authenticate with. */
187
201
  export declare function hasProviderCredential(env?: NodeJS.ProcessEnv): boolean;
202
+ export declare function strippedProviderCredentialNames(env?: NodeJS.ProcessEnv): string[];
188
203
  /**
189
204
  * The environment the engine actually receives.
190
205
  *
@@ -21,11 +21,13 @@ exports.ENGINE_PATH_ENV = void 0;
21
21
  exports.engineHome = engineHome;
22
22
  exports.skyCodeInstructionHome = skyCodeInstructionHome;
23
23
  exports.managedEnginePath = managedEnginePath;
24
+ exports.legacyManagedEnginePath = legacyManagedEnginePath;
24
25
  exports.resolveEngine = resolveEngine;
25
26
  exports.buildEngineArgs = buildEngineArgs;
26
27
  exports.notInstalledMessage = notInstalledMessage;
27
28
  exports.inheritedProviderCredentials = inheritedProviderCredentials;
28
29
  exports.hasProviderCredential = hasProviderCredential;
30
+ exports.strippedProviderCredentialNames = strippedProviderCredentialNames;
29
31
  exports.engineSpawnEnv = engineSpawnEnv;
30
32
  exports.execEngine = execEngine;
31
33
  const node_child_process_1 = require("node:child_process");
@@ -70,6 +72,24 @@ function skyCodeInstructionHome(env = process.env) {
70
72
  function managedEnginePath(exeName, env = process.env) {
71
73
  return node_path_1.default.join(engineHome(env), 'bin', exeName);
72
74
  }
75
+ /**
76
+ * The same managed location under the PREVIOUS config root.
77
+ *
78
+ * The root moved `~/.oversky` → `~/.skrr` in the skrr rename, and an engine
79
+ * installed before that is still on disk under the old one. `daemon/src/
80
+ * binary-resolver.ts` was given this fallback and this module was not, so on
81
+ * the same machine the daemon found the engine and `skrr code` reported that no
82
+ * engine was installed — the same product, the same 106 MB binary, two answers.
83
+ *
84
+ * Returns null when an explicit `OVERSKY_CONFIG_DIR` is set, matching the
85
+ * daemon: that override names one root deliberately, and reaching past it to a
86
+ * hard-coded home would defeat the pinning {@link engineHome} relies on.
87
+ */
88
+ function legacyManagedEnginePath(exeName, env = process.env) {
89
+ if (env.OVERSKY_CONFIG_DIR?.trim())
90
+ return null;
91
+ return node_path_1.default.join((0, node_os_1.homedir)(), '.oversky', 'sky-code', 'bin', exeName);
92
+ }
73
93
  /**
74
94
  * Unmanaged well-known locations, checked after PATH.
75
95
  *
@@ -139,6 +159,15 @@ function resolveEngine(env = process.env) {
139
159
  const managed = managedEnginePath(exeName, env);
140
160
  if (isExecutable(managed))
141
161
  return { path: managed, source: 'managed' };
162
+ // The pre-rename managed location, SECOND. After the current one, so a fresh
163
+ // install always wins; before PATH, for the same WL-6.2 reason the current one
164
+ // beats PATH — a binary skrr installed outranks whatever happens to sit on the
165
+ // user's PATH, and which config root it was installed under does not change
166
+ // that. Reported as its own `source` so `skrr code doctor` can say where it
167
+ // came from rather than quietly resolving something surprising.
168
+ const legacy = legacyManagedEnginePath(exeName, env);
169
+ if (legacy && isExecutable(legacy))
170
+ return { path: legacy, source: 'legacy-managed' };
142
171
  const PATH = env.PATH ?? '';
143
172
  const sep = process.platform === 'win32' ? ';' : ':';
144
173
  const exeNames = process.platform === 'win32' ? ['sky-code.exe', 'sky-code.cmd'] : ['sky-code'];
@@ -198,15 +227,17 @@ function notInstalledMessage() {
198
227
  'The skrr Code engine (`sky-code`) is not installed on this machine.',
199
228
  '',
200
229
  'Install it through the daemon, which verifies the signed release:',
201
- ' • In the web app: the runtime menu beside the chat input → skrr Code → Install',
202
- ' • Make sure a daemon is running here first: `oversky status`',
230
+ ' • `skrr code install` — from here, no browser needed',
231
+ ' • Or in the web app: the runtime menu beside the chat input → skrr Code → Install',
232
+ ' • Either way a daemon must be running here: `skrr daemon status`',
203
233
  '',
204
234
  `Or point the CLI at an existing build: export ${exports.ENGINE_PATH_ENV}=/absolute/path/to/sky-code`,
205
235
  ' (an unsigned build runs, and since 2026-08-11 at the same trust tier as a',
206
236
  ' signed one — see `skrr code doctor` under trust-tier)',
207
237
  '',
208
- 'Run `skrr code doctor` for a full diagnosis, including which channel this',
209
- 'machine follows and whether that channel has a published release.',
238
+ 'Run `skrr code doctor` for a full diagnosis. Its `release-channel` line',
239
+ 'names the channel this machine follows and the exact manifest URL to check',
240
+ 'for a published release.',
210
241
  ].join('\n');
211
242
  }
212
243
  /**
@@ -220,6 +251,37 @@ function notInstalledMessage() {
220
251
  */
221
252
  const BYOK_CREDENTIAL_SUFFIXES = ['_API_KEY', '_AUTH_TOKEN'];
222
253
  const BYOK_CREDENTIAL_NAMES = new Set(['HUGGINGFACE_HUB_TOKEN']);
254
+ /**
255
+ * `AWS_*` names that are not credentials, and that Bedrock cannot run without.
256
+ *
257
+ * The `AWS_` prefix rule below exists for STS/IAM material — `AWS_ACCESS_KEY_ID`,
258
+ * `AWS_SECRET_ACCESS_KEY`, `AWS_SESSION_TOKEN`, `AWS_BEARER_TOKEN_BEDROCK` — and
259
+ * every one of those stays stripped. These three carry no secret: two are a
260
+ * region and one is the NAME of a profile whose credentials live in the AWS
261
+ * shared config, a file the engine can read anyway. Stripping them therefore
262
+ * protected nothing and cost an entire provider.
263
+ *
264
+ * Dogfooded as OSK-262, where `sky-code run "say hi"` answered on a Bedrock
265
+ * model and the identical run through `skrr code` died in the engine's generic
266
+ * error handler — because `AWS_PROFILE` did not survive the sanitizer.
267
+ * `env -u AWS_PROFILE` on the bare engine reproduced the failure exactly.
268
+ *
269
+ * An enumerated carve-out rather than a narrower prefix, so every future
270
+ * addition is a reviewable line that has to argue "this one is not a secret".
271
+ * The failure mode of the alternative is an exemption list that grows until the
272
+ * prefix rule means nothing.
273
+ *
274
+ * BYOK ONLY, and that is why it lives here rather than in `sanitizeSpawnEnv`.
275
+ * {@link engineSpawnEnv} re-admits nothing on a managed run, so a session
276
+ * spending a budgeted relay credential still cannot reach Bedrock directly and
277
+ * bill around its own budget. Putting the exemption in the shared sanitizer
278
+ * would hand it to the daemon's managed ACP path too, and lose that.
279
+ */
280
+ const BYOK_AWS_NON_SECRETS = new Set([
281
+ 'AWS_PROFILE',
282
+ 'AWS_REGION',
283
+ 'AWS_DEFAULT_REGION',
284
+ ]);
223
285
  /**
224
286
  * …and these are never inherited, whatever they look like.
225
287
  *
@@ -256,6 +318,11 @@ function inheritedProviderCredentials(env) {
256
318
  continue;
257
319
  if (ENGINE_NEVER_INHERITS.has(key))
258
320
  continue;
321
+ // Before the prefix rule, which would otherwise take these with the family.
322
+ if (BYOK_AWS_NON_SECRETS.has(key)) {
323
+ out[key] = value;
324
+ continue;
325
+ }
259
326
  if (ENGINE_NEVER_INHERITS_PREFIXES.some((prefix) => key.startsWith(prefix)))
260
327
  continue;
261
328
  if (BYOK_CREDENTIAL_NAMES.has(key) || BYOK_CREDENTIAL_SUFFIXES.some((s) => key.endsWith(s))) {
@@ -268,6 +335,37 @@ function inheritedProviderCredentials(env) {
268
335
  function hasProviderCredential(env = process.env) {
269
336
  return Object.keys(inheritedProviderCredentials(env)).length > 0;
270
337
  }
338
+ /**
339
+ * Provider-capable credentials this environment HAS and the engine will not get.
340
+ *
341
+ * `hasProviderCredential` answers "will the engine have a key", which is the
342
+ * right question for what to spawn and the wrong one for what to SAY. On a
343
+ * machine whose only credential is an AWS profile the two answers differ: the
344
+ * engine defaults to a Bedrock model and runs fine when launched directly, and
345
+ * `skrr code` — which strips `AWS_*` — reported "no provider credential is set
346
+ * here", sent the user to buy an OpenRouter key, and then died in the engine's
347
+ * generic error handler. The user had a working credential; this run removed it.
348
+ *
349
+ * "You have none" and "you have one and this run does not pass it on" are
350
+ * different problems with different fixes, so they must not share a sentence.
351
+ *
352
+ * Only the deny-listed names a PROVIDER could actually authenticate with are
353
+ * reported. `GH_TOKEN` and `NPM_TOKEN` are stripped too and are not model
354
+ * credentials, so naming them here would turn a precise sentence into noise.
355
+ */
356
+ const STRIPPED_PROVIDER_CREDENTIALS = [
357
+ // Bedrock's SECRET material only. `AWS_PROFILE` and the region variables are
358
+ // exempt ({@link BYOK_AWS_NON_SECRETS}) and now reach the engine, so naming
359
+ // them here would make this sentence contradict the spawn — which is the exact
360
+ // defect this reporter was added to end.
361
+ 'AWS_ACCESS_KEY_ID',
362
+ 'AWS_BEARER_TOKEN_BEDROCK',
363
+ // Anthropic OAuth, deny-listed by name in ENGINE_NEVER_INHERITS.
364
+ 'CLAUDE_CODE_OAUTH_TOKEN',
365
+ ];
366
+ function strippedProviderCredentialNames(env = process.env) {
367
+ return STRIPPED_PROVIDER_CREDENTIALS.filter((name) => (env[name] ?? '').trim() !== '');
368
+ }
271
369
  /**
272
370
  * The environment the engine actually receives.
273
371
  *
@@ -27,6 +27,7 @@ exports.sleep = sleep;
27
27
  exports.compactSnapshotSignature = compactSnapshotSignature;
28
28
  const data_provider_1 = require("@skrr-ai/data-provider");
29
29
  const tasks_1 = require("./tasks");
30
+ const html_text_1 = require("./html-text");
30
31
  /**
31
32
  * Statuses at which an execution is OVER — nothing further will move the task
32
33
  * without new input.
@@ -304,17 +305,9 @@ function compactSnapshotSignature(snapshot) {
304
305
  .sort()
305
306
  .join('|');
306
307
  }
307
- function stripHtml(value) {
308
- return value
309
- .replace(/<br\s*\/?>/gi, '\n')
310
- .replace(/<\/p>/gi, '\n')
311
- .replace(/<[^>]+>/g, ' ')
312
- .replace(/&nbsp;/g, ' ')
313
- .replace(/&#39;/g, "'")
314
- .replace(/&quot;/g, '"')
315
- .replace(/&amp;/g, '&')
316
- .replace(/[ \t]+/g, ' ');
317
- }
308
+ // Was a private copy here; it is the same job `tasks show` needs, and two
309
+ // slightly different HTML strippers is how the two surfaces drift.
310
+ const stripHtml = html_text_1.htmlToDisplayText;
318
311
  function stringValue(value) {
319
312
  return typeof value === 'string' && value.trim() ? value.trim() : undefined;
320
313
  }
@@ -1,3 +1,4 @@
1
+ export declare const TASK_PRIORITIES: readonly ["low", "medium", "high", "critical"];
1
2
  /**
2
3
  * The kinds `tasks events append --kind` will accept.
3
4
  *