@skrr-ai/cli 0.1.50 → 0.1.51

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 (100) hide show
  1. package/dist/base-command.js +59 -2
  2. package/dist/commands/agents/chat.d.ts +14 -0
  3. package/dist/commands/agents/chat.js +37 -1
  4. package/dist/commands/agents/show.d.ts +9 -0
  5. package/dist/commands/agents/show.js +53 -0
  6. package/dist/commands/agents/update.d.ts +9 -0
  7. package/dist/commands/agents/update.js +27 -0
  8. package/dist/commands/balance/show.d.ts +34 -0
  9. package/dist/commands/balance/show.js +92 -2
  10. package/dist/commands/commitments/doctor.d.ts +1 -0
  11. package/dist/commands/commitments/doctor.js +19 -4
  12. package/dist/commands/commitments/effective-policy.js +15 -1
  13. package/dist/commands/commitments/next-tick.js +3 -1
  14. package/dist/commands/commitments/preflight.js +10 -0
  15. package/dist/commands/commitments/show.js +11 -1
  16. package/dist/commands/daemon/config.d.ts +15 -0
  17. package/dist/commands/daemon/config.js +38 -0
  18. package/dist/commands/daemon/index.js +1 -0
  19. package/dist/commands/daemon/status.js +15 -1
  20. package/dist/commands/harnesses/models.d.ts +54 -0
  21. package/dist/commands/harnesses/models.js +100 -7
  22. package/dist/commands/harnesses/show.d.ts +11 -0
  23. package/dist/commands/harnesses/show.js +35 -0
  24. package/dist/commands/harnesses/update.d.ts +28 -1
  25. package/dist/commands/harnesses/update.js +73 -10
  26. package/dist/commands/outbox/list.d.ts +12 -1
  27. package/dist/commands/outbox/list.js +31 -2
  28. package/dist/commands/revoke-daemon.js +9 -0
  29. package/dist/commands/spaces/create.d.ts +1 -0
  30. package/dist/commands/spaces/create.js +17 -0
  31. package/dist/commands/spaces/show.js +5 -0
  32. package/dist/commands/spaces/update.d.ts +1 -0
  33. package/dist/commands/spaces/update.js +16 -0
  34. package/dist/commands/tasks/create.d.ts +1 -0
  35. package/dist/commands/tasks/create.js +5 -0
  36. package/dist/commands/tasks/show.js +45 -0
  37. package/dist/commands/tasks/update.d.ts +1 -0
  38. package/dist/commands/tasks/update.js +21 -0
  39. package/dist/commands/tasks/upsert.d.ts +1 -0
  40. package/dist/commands/tasks/upsert.js +16 -0
  41. package/dist/lib/agentic-stream.d.ts +68 -1
  42. package/dist/lib/agentic-stream.js +294 -7
  43. package/dist/lib/auth-core-init.d.ts +2 -10
  44. package/dist/lib/auth-core-init.js +20 -67
  45. package/dist/lib/auth-failure.d.ts +33 -0
  46. package/dist/lib/auth-failure.js +65 -0
  47. package/dist/lib/commitments.d.ts +21 -1
  48. package/dist/lib/commitments.js +34 -0
  49. package/dist/lib/daemonBroker.d.ts +14 -0
  50. package/dist/lib/daemonBroker.js +64 -12
  51. package/dist/lib/delegated-cli.js +4 -1
  52. package/dist/lib/exec-runtime-binary.d.ts +3 -1
  53. package/dist/lib/exec-runtime-binary.js +4 -2
  54. package/dist/lib/first-party-harness-broker.js +4 -1
  55. package/dist/lib/harnesses.d.ts +10 -0
  56. package/dist/lib/live-runtime-binary.d.ts +40 -0
  57. package/dist/lib/live-runtime-binary.js +193 -0
  58. package/dist/lib/login.d.ts +23 -0
  59. package/dist/lib/login.js +44 -10
  60. package/dist/lib/message-intent.js +3 -1
  61. package/dist/lib/tasks.d.ts +20 -0
  62. package/dist/lib/tasks.js +54 -0
  63. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/credentialEnvelopeBridge.d.ts +2 -0
  64. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/credentialEnvelopeBridge.js +26 -1
  65. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/daemonToolApproval.d.ts +28 -4
  66. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/daemonToolApproval.js +23 -5
  67. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/deviceIdentityBridge.js +41 -3
  68. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/index.d.ts +3 -1
  69. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/index.js +25 -3
  70. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/loopbackHttp.d.ts +32 -0
  71. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/loopbackHttp.js +268 -0
  72. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/machineId.d.ts +2 -2
  73. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/machineId.js +11 -10
  74. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/machineUuid.d.ts +36 -0
  75. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/machineUuid.js +156 -0
  76. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/refresh.d.ts +8 -0
  77. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/refresh.js +8 -1
  78. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/spawnEnv.d.ts +22 -0
  79. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/spawnEnv.js +61 -2
  80. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/credentialEnvelopeBridge.d.ts +2 -0
  81. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/credentialEnvelopeBridge.js +25 -1
  82. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/daemonToolApproval.d.ts +28 -4
  83. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/daemonToolApproval.js +22 -4
  84. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/deviceIdentityBridge.js +41 -3
  85. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/index.d.ts +3 -1
  86. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/index.js +10 -1
  87. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/loopbackHttp.d.ts +32 -0
  88. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/loopbackHttp.js +257 -0
  89. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/machineId.d.ts +2 -2
  90. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/machineId.js +11 -10
  91. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/machineUuid.d.ts +36 -0
  92. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/machineUuid.js +147 -0
  93. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/refresh.d.ts +8 -0
  94. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/refresh.js +8 -1
  95. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/spawnEnv.d.ts +22 -0
  96. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/spawnEnv.js +58 -1
  97. package/dist/node_modules/@skrr-ai/auth-core/package.json +21 -1
  98. package/dist/node_modules/@skrr-ai/data-provider/index.js +1928 -1924
  99. package/oclif.manifest.json +23832 -23688
  100. package/package.json +1 -1
@@ -0,0 +1,147 @@
1
+ /**
2
+ * machineUuid.ts — the ONE hardware machine identity sent to the server as
3
+ * `machineUuid`, shared by the daemon and the CLI.
4
+ *
5
+ * Server Daemon rows are keyed on this value (daemon register, device-key
6
+ * enrollment, token mint, pairing), so every binary on one machine must
7
+ * compute it identically. Until OSK-12063 the CLI sent its own UUIDv7 from
8
+ * `~/.skrr/daemon.id` (`ensureMachineDaemonId()`, a DIFFERENT identity) as
9
+ * `machineUuid` on device-key enrollment while the daemon sent the hardware
10
+ * UUID computed here, so every CLI enrollment matched no Daemon row, got
11
+ * 404 DAEMON_NOT_FOUND and backed off forever. Two implementations of one
12
+ * identity can only agree by being edited together; this file is the one
13
+ * implementation, and `daemon/src/registry-lite.ts` re-exports it.
14
+ *
15
+ * Deliberately dependency-free (node builtins only) and exposed as the
16
+ * `@skrr-ai/auth-core/machine-uuid` subpath: the packaged desktop imports the
17
+ * daemon's `registry-lite.js` directly, and loading the full auth-core index
18
+ * there would drag in the credential stack for a one-function need.
19
+ *
20
+ * Not to be confused with `ensureMachineDaemonId()` (`machineId.ts`), the
21
+ * minted per-home-dir UUIDv7 that anchors the daemon's `stableDaemonId`. That
22
+ * one survives an OS reinstall; this one survives a home-dir wipe. They are
23
+ * different facts and neither may stand in for the other on the wire.
24
+ */
25
+ import crypto from 'node:crypto';
26
+ import fs from 'node:fs';
27
+ import os from 'node:os';
28
+ import { execFileSync } from 'node:child_process';
29
+ /**
30
+ * Daemon sources whose identity is ISSUED by the control plane rather than
31
+ * derived from the host: the provisioner mints the daemon id and machine uuid
32
+ * before the daemon exists, and every binary on the runtime must use exactly
33
+ * those values.
34
+ *
35
+ * `dedicated-runtime` is here because the server's generation fence parses the
36
+ * lease generation out of the machine uuid (`dedicated-runtime:<lease>:<gen>`).
37
+ * A guest that fell back to `/etc/machine-id` would register under a uuid the
38
+ * fence cannot read, and every dispatch to it would be refused.
39
+ */
40
+ export const HOSTED_RUNTIME_MACHINE_SOURCES = new Set([
41
+ 'hosted-machine',
42
+ 'cloud-coding',
43
+ 'dedicated-runtime',
44
+ ]);
45
+ const HOSTED_RUNTIME_ID_RE = /^[A-Za-z0-9_.:-]{1,160}$/;
46
+ /**
47
+ * The control-plane-issued value of `name` (e.g. `OVERSKY_MACHINE_UUID`), or
48
+ * null when this process is not on a hosted runtime or the value is absent /
49
+ * malformed. Only honoured under a hosted `OVERSKY_DAEMON_SOURCE`, so a stray
50
+ * variable on a laptop cannot rename the machine.
51
+ */
52
+ export function hostedRuntimeIdOverride(name, env = process.env) {
53
+ if (!HOSTED_RUNTIME_MACHINE_SOURCES.has(env.OVERSKY_DAEMON_SOURCE ?? '')) {
54
+ return null;
55
+ }
56
+ const value = env[name]?.trim();
57
+ if (!value || !HOSTED_RUNTIME_ID_RE.test(value))
58
+ return null;
59
+ return value;
60
+ }
61
+ let cachedMachineUuid = null;
62
+ function readMachineUuidDarwin() {
63
+ try {
64
+ const out = execFileSync('ioreg', ['-rd1', '-c', 'IOPlatformExpertDevice'], {
65
+ encoding: 'utf-8',
66
+ timeout: 2_000,
67
+ stdio: ['ignore', 'pipe', 'ignore'],
68
+ });
69
+ const match = out.match(/IOPlatformUUID"?\s*=\s*"?([0-9A-F-]{36})/i);
70
+ return match ? match[1].toLowerCase() : null;
71
+ }
72
+ catch {
73
+ return null;
74
+ }
75
+ }
76
+ function readMachineUuidLinux() {
77
+ for (const p of ['/etc/machine-id', '/var/lib/dbus/machine-id']) {
78
+ try {
79
+ const raw = fs.readFileSync(p, 'utf-8').trim();
80
+ if (raw)
81
+ return raw.toLowerCase();
82
+ }
83
+ catch {
84
+ // Try the next candidate.
85
+ }
86
+ }
87
+ return null;
88
+ }
89
+ function readMachineUuidWindows() {
90
+ try {
91
+ const out = execFileSync('reg', ['query', 'HKLM\\SOFTWARE\\Microsoft\\Cryptography', '/v', 'MachineGuid'], { encoding: 'utf-8', timeout: 2_000, stdio: ['ignore', 'pipe', 'ignore'] });
92
+ const match = out.match(/MachineGuid\s+REG_SZ\s+([0-9A-Fa-f-]{36})/);
93
+ return match ? match[1].toLowerCase() : null;
94
+ }
95
+ catch {
96
+ return null;
97
+ }
98
+ }
99
+ /**
100
+ * Return a stable, machine-scoped UUID. Cached for the process lifetime.
101
+ *
102
+ * Callers should treat this as opaque: the format differs per platform
103
+ * (macOS IOPlatformUUID, Linux systemd machine-id, Windows MachineGuid).
104
+ * The guarantee is only: same machine -> same value across reboots, and the
105
+ * same value from every binary that calls this function.
106
+ *
107
+ * On a hosted runtime the control-plane-issued `OVERSKY_MACHINE_UUID` wins.
108
+ *
109
+ * Falls back to a deterministic hostname+username hash if the platform
110
+ * probe fails. This preserves server-side record continuity even on
111
+ * locked-down machines that refuse ioreg / registry access.
112
+ */
113
+ export function getMachineUuid() {
114
+ const hostedMachineUuid = hostedRuntimeIdOverride('OVERSKY_MACHINE_UUID');
115
+ if (hostedMachineUuid)
116
+ return hostedMachineUuid;
117
+ if (cachedMachineUuid !== null)
118
+ return cachedMachineUuid;
119
+ let detected = null;
120
+ switch (process.platform) {
121
+ case 'darwin':
122
+ detected = readMachineUuidDarwin();
123
+ break;
124
+ case 'linux':
125
+ detected = readMachineUuidLinux();
126
+ break;
127
+ case 'win32':
128
+ detected = readMachineUuidWindows();
129
+ break;
130
+ }
131
+ if (detected) {
132
+ cachedMachineUuid = detected;
133
+ return detected;
134
+ }
135
+ const fallback = 'fallback-' +
136
+ crypto
137
+ .createHash('sha256')
138
+ .update(`${os.hostname()}:${os.userInfo().username}`)
139
+ .digest('hex')
140
+ .slice(0, 32);
141
+ cachedMachineUuid = fallback;
142
+ return fallback;
143
+ }
144
+ /** @internal test seam — forget the cached value so the next call re-probes. */
145
+ export function __resetMachineUuidCacheForTest() {
146
+ cachedMachineUuid = null;
147
+ }
@@ -274,6 +274,14 @@ export declare function persistReauthState(state: ReauthState): void;
274
274
  export declare function needsReauthState(): {
275
275
  needed: boolean;
276
276
  reason?: string;
277
+ /**
278
+ * The server's own words for the refusal (`Refresh token bound to a different
279
+ * daemon`). The code alone collapses several distinct causes into one
280
+ * (`REFRESH_INVALID` is also "not recognized" and "issued without a
281
+ * daemonId"), and a surface that names only the code cannot tell the reader
282
+ * which one they hit (OSK-12116).
283
+ */
284
+ message?: string;
277
285
  since?: number;
278
286
  };
279
287
  export declare function clearReauthState(): void;
@@ -953,7 +953,14 @@ export function needsReauthState() {
953
953
  return { needed: false };
954
954
  const raw = fs.readFileSync(flagPath, 'utf-8');
955
955
  const state = JSON.parse(raw);
956
- return { needed: true, reason: state.code, since: state.at };
956
+ return {
957
+ needed: true,
958
+ reason: state.code,
959
+ ...(typeof state.message === 'string' && state.message.length > 0
960
+ ? { message: state.message }
961
+ : {}),
962
+ since: state.at,
963
+ };
957
964
  }
958
965
  catch {
959
966
  return { needed: false };
@@ -84,3 +84,25 @@ export declare const SENSITIVE_ENV_PREFIX_EXCEPTIONS: ReadonlySet<string>;
84
84
  * etc.) so legitimate tools keep working.
85
85
  */
86
86
  export declare function sanitizeSpawnEnv(env: NodeJS.ProcessEnv): NodeJS.ProcessEnv;
87
+ /**
88
+ * OSK-12134 — loopback names a spawned child must reach directly, never through
89
+ * a proxy. A harness talks to this machine constantly: the daemon's local
90
+ * bridges (browser, delegated CLI, message intents), the inference broker, and
91
+ * the engine's own loopback services (skrr Code's `session/new` reaches a local
92
+ * directory service and failed with "service failure" behind a shell proxy).
93
+ */
94
+ export declare const LOOPBACK_NO_PROXY_HOSTS: readonly string[];
95
+ /** True when `env` names a proxy some client in the child might honour. */
96
+ export declare function envHasProxy(env: Readonly<Record<string, string | undefined>>): boolean;
97
+ /**
98
+ * Return `env` with the loopback hosts appended to BOTH `NO_PROXY` and
99
+ * `no_proxy`, when (and only when) it names a proxy. Tools disagree on which
100
+ * spelling they read and whether they fall back to the other, so an unset
101
+ * spelling is seeded from the other one before the hosts are appended —
102
+ * seeding only the hosts would silently drop every existing exemption for a
103
+ * tool that prefers the unset spelling. Existing entries keep their order.
104
+ *
105
+ * Exported for a parent that layers a proxy onto the child's env AFTER
106
+ * {@link sanitizeSpawnEnv}: call it again on the final map.
107
+ */
108
+ export declare function withLoopbackNoProxy<T extends Record<string, string | undefined>>(env: T): T;
@@ -183,5 +183,62 @@ export function sanitizeSpawnEnv(env) {
183
183
  continue;
184
184
  out[key] = value;
185
185
  }
186
- return out;
186
+ return withLoopbackNoProxy(out);
187
+ }
188
+ /**
189
+ * OSK-12134 — loopback names a spawned child must reach directly, never through
190
+ * a proxy. A harness talks to this machine constantly: the daemon's local
191
+ * bridges (browser, delegated CLI, message intents), the inference broker, and
192
+ * the engine's own loopback services (skrr Code's `session/new` reaches a local
193
+ * directory service and failed with "service failure" behind a shell proxy).
194
+ */
195
+ export const LOOPBACK_NO_PROXY_HOSTS = ['127.0.0.1', 'localhost', '::1'];
196
+ const PROXY_ENV_VARS = [
197
+ 'HTTP_PROXY',
198
+ 'http_proxy',
199
+ 'HTTPS_PROXY',
200
+ 'https_proxy',
201
+ 'ALL_PROXY',
202
+ 'all_proxy',
203
+ ];
204
+ /** True when `env` names a proxy some client in the child might honour. */
205
+ export function envHasProxy(env) {
206
+ return PROXY_ENV_VARS.some((name) => typeof env[name] === 'string' && env[name].trim() !== '');
207
+ }
208
+ function appendNoProxyHosts(list, hosts) {
209
+ const entries = list
210
+ .split(',')
211
+ .map((entry) => entry.trim().toLowerCase())
212
+ .filter(Boolean);
213
+ // `*` already exempts everything, and some clients honour it only as the
214
+ // entire value, so appending to it would break them.
215
+ if (entries.includes('*'))
216
+ return list;
217
+ const missing = hosts.filter((host) => !entries.includes(host));
218
+ if (missing.length === 0)
219
+ return list;
220
+ const kept = list.replace(/[\s,]+$/, '');
221
+ return kept ? `${kept},${missing.join(',')}` : missing.join(',');
222
+ }
223
+ /**
224
+ * Return `env` with the loopback hosts appended to BOTH `NO_PROXY` and
225
+ * `no_proxy`, when (and only when) it names a proxy. Tools disagree on which
226
+ * spelling they read and whether they fall back to the other, so an unset
227
+ * spelling is seeded from the other one before the hosts are appended —
228
+ * seeding only the hosts would silently drop every existing exemption for a
229
+ * tool that prefers the unset spelling. Existing entries keep their order.
230
+ *
231
+ * Exported for a parent that layers a proxy onto the child's env AFTER
232
+ * {@link sanitizeSpawnEnv}: call it again on the final map.
233
+ */
234
+ export function withLoopbackNoProxy(env) {
235
+ if (!envHasProxy(env))
236
+ return env;
237
+ const upper = env.NO_PROXY?.trim() ? env.NO_PROXY : undefined;
238
+ const lower = env.no_proxy?.trim() ? env.no_proxy : undefined;
239
+ return {
240
+ ...env,
241
+ NO_PROXY: appendNoProxyHosts(upper ?? lower ?? '', LOOPBACK_NO_PROXY_HOSTS),
242
+ no_proxy: appendNoProxyHosts(lower ?? upper ?? '', LOOPBACK_NO_PROXY_HOSTS),
243
+ };
187
244
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@skrr-ai/auth-core",
3
- "version": "0.4.4",
3
+ "version": "0.4.5",
4
4
  "main": "dist/cjs/index.js",
5
5
  "types": "dist/esm/index.d.ts",
6
6
  "exports": {
@@ -83,6 +83,26 @@
83
83
  "types": "./dist/cjs/cliHandoffWire.d.ts",
84
84
  "default": "./dist/cjs/cliHandoffWire.js"
85
85
  }
86
+ },
87
+ "./loopback-http": {
88
+ "import": {
89
+ "types": "./dist/esm/loopbackHttp.d.ts",
90
+ "default": "./dist/esm/loopbackHttp.js"
91
+ },
92
+ "require": {
93
+ "types": "./dist/cjs/loopbackHttp.d.ts",
94
+ "default": "./dist/cjs/loopbackHttp.js"
95
+ }
96
+ },
97
+ "./machine-uuid": {
98
+ "import": {
99
+ "types": "./dist/esm/machineUuid.d.ts",
100
+ "default": "./dist/esm/machineUuid.js"
101
+ },
102
+ "require": {
103
+ "types": "./dist/cjs/machineUuid.d.ts",
104
+ "default": "./dist/cjs/machineUuid.js"
105
+ }
86
106
  }
87
107
  },
88
108
  "dependencies": {