@skrr-ai/cli 0.1.109 → 0.1.110
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.
- package/dist/base-command.d.ts +15 -0
- package/dist/base-command.js +64 -17
- package/dist/commands/agents/triggers/create.js +1 -1
- package/dist/commands/agents/triggers/update.js +1 -1
- package/dist/commands/agents/update.d.ts +11 -0
- package/dist/commands/agents/update.js +58 -2
- package/dist/commands/daemon/install.js +17 -1
- package/dist/commands/daemon/login.js +14 -0
- package/dist/commands/harnesses/prune.d.ts +26 -0
- package/dist/commands/harnesses/prune.js +172 -0
- package/dist/commands/login.js +11 -0
- package/dist/commands/spaces/workflows/start.js +3 -1
- package/dist/commands/spaces/workflows/validate.js +12 -2
- package/dist/commands/tasks/activity.js +11 -1
- package/dist/commands/tasks/list.js +6 -2
- package/dist/commands/tasks/rearm-recurrence.js +22 -3
- package/dist/commands/tasks/show.d.ts +8 -0
- package/dist/commands/tasks/show.js +64 -32
- package/dist/commands/tasks/unschedule.js +5 -1
- package/dist/commands/tasks/update.js +11 -1
- package/dist/commands/triggers/audit.js +12 -3
- package/dist/commands/triggers/create.js +1 -1
- package/dist/commands/triggers/fire-detail.d.ts +7 -0
- package/dist/commands/triggers/fire-detail.js +30 -12
- package/dist/commands/triggers/fire.js +13 -3
- package/dist/commands/triggers/parse-intent.js +1 -1
- package/dist/commands/triggers/update.js +1 -1
- package/dist/commands/workspaces/grants.js +1 -4
- package/dist/commands/workspaces/members.js +6 -6
- package/dist/lib/commitment-product.js +5 -2
- package/dist/lib/commitments.d.ts +2 -1
- package/dist/lib/commitments.js +40 -40
- package/dist/lib/daemon-machine-identity-copy.d.ts +14 -0
- package/dist/lib/daemon-machine-identity-copy.js +27 -0
- package/dist/lib/daemon-machine-identity.d.ts +27 -0
- package/dist/lib/daemon-machine-identity.js +61 -0
- package/dist/lib/daemonHandoff.d.ts +19 -1
- package/dist/lib/daemonHandoff.js +59 -0
- package/dist/lib/harnesses.d.ts +71 -0
- package/dist/lib/harnesses.js +70 -0
- package/dist/lib/list-output.d.ts +1 -1
- package/dist/lib/list-output.js +2 -0
- package/dist/lib/profile-machine-identity-guard.js +11 -1
- package/dist/lib/task-economics.d.ts +10 -0
- package/dist/lib/task-economics.js +24 -2
- package/dist/lib/triggers.d.ts +11 -0
- package/dist/lib/triggers.js +43 -1
- package/dist/lib/workflow-run-view.d.ts +4 -0
- package/dist/lib/workflow-run-view.js +5 -0
- package/dist/lib/workspaces.d.ts +24 -7
- package/dist/lib/workspaces.js +14 -2
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/index.d.ts +1 -1
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/index.js +5 -3
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/machineUuid.d.ts +60 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/machineUuid.js +130 -6
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/index.d.ts +1 -1
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/index.js +1 -1
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/machineUuid.d.ts +60 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/machineUuid.js +128 -6
- package/dist/node_modules/@skrr-ai/auth-core/package.json +1 -1
- package/dist/node_modules/@skrr-ai/data-provider/index.js +4003 -3968
- package/oclif.manifest.json +99 -9
- package/package.json +10 -1
|
@@ -218,7 +218,7 @@ function readPersistedChoice(file, hardware, profile, requireProfile = false) {
|
|
|
218
218
|
return null;
|
|
219
219
|
}
|
|
220
220
|
}
|
|
221
|
-
function persistChoice(dir, file, hardware, machineUuid, reason, profile) {
|
|
221
|
+
function persistChoice(dir, file, hardware, machineUuid, reason, profile, evidence) {
|
|
222
222
|
try {
|
|
223
223
|
fs.mkdirSync(dir, { recursive: true, mode: 0o700 });
|
|
224
224
|
const tmp = `${file}.${process.pid}.${Date.now()}.tmp`;
|
|
@@ -228,6 +228,12 @@ function persistChoice(dir, file, hardware, machineUuid, reason, profile) {
|
|
|
228
228
|
machineUuid,
|
|
229
229
|
profile,
|
|
230
230
|
reason,
|
|
231
|
+
// WHICH file made a profile "already hold credentials". The reason alone
|
|
232
|
+
// says a profile shares the default's machine row; this says what put it
|
|
233
|
+
// there, which is the difference between "an older Skrr set it up" and
|
|
234
|
+
// "its first credential was written before anything chose its identity".
|
|
235
|
+
// Additive: a reader that predates it ignores the field.
|
|
236
|
+
...(evidence && evidence.length > 0 ? { evidence: [...evidence] } : {}),
|
|
231
237
|
decidedAt: new Date().toISOString(),
|
|
232
238
|
};
|
|
233
239
|
fs.writeFileSync(tmp, `${JSON.stringify(body)}\n`, { mode: 0o600 });
|
|
@@ -267,7 +273,7 @@ function resolveProfileMachineUuid(profile, hardware) {
|
|
|
267
273
|
persistChoice(dir, file, hardware, chosen, 'restored_profile', profile);
|
|
268
274
|
}
|
|
269
275
|
if (!chosen) {
|
|
270
|
-
const
|
|
276
|
+
const evidence = PRE_EXISTING_PROFILE_EVIDENCE.filter((name) => {
|
|
271
277
|
try {
|
|
272
278
|
return fs.existsSync(path.join(dir, name));
|
|
273
279
|
}
|
|
@@ -275,8 +281,9 @@ function resolveProfileMachineUuid(profile, hardware) {
|
|
|
275
281
|
return false;
|
|
276
282
|
}
|
|
277
283
|
});
|
|
284
|
+
const preExisting = evidence.length > 0;
|
|
278
285
|
chosen = preExisting ? hardware : qualifyMachineUuid(hardware, profile);
|
|
279
|
-
persistChoice(dir, file, hardware, chosen, preExisting ? 'pre_existing_profile' : 'new_profile', profile);
|
|
286
|
+
persistChoice(dir, file, hardware, chosen, preExisting ? 'pre_existing_profile' : 'new_profile', profile, evidence);
|
|
280
287
|
}
|
|
281
288
|
preserveRecoveryChoice(profile, hardware, chosen);
|
|
282
289
|
profileChoiceCache.set(cacheKey, chosen);
|
|
@@ -296,14 +303,129 @@ function resolveProfileMachineUuid(profile, hardware) {
|
|
|
296
303
|
* profile that already held credentials; see the block above.
|
|
297
304
|
*/
|
|
298
305
|
export function getMachineUuid() {
|
|
306
|
+
return getMachineUuidForProfile(activeMachineProfile);
|
|
307
|
+
}
|
|
308
|
+
/**
|
|
309
|
+
* The `machineUuid` a process running as `profile` sends, WITHOUT changing which
|
|
310
|
+
* profile this process runs as.
|
|
311
|
+
*
|
|
312
|
+
* The CLI needs the answer for the profile it is about to hand a credential to,
|
|
313
|
+
* and asks the daemon binary what IT will send (`accept-handoff --print-id`).
|
|
314
|
+
* Two programs that compute one identity can only be known to agree by
|
|
315
|
+
* comparing them, and a daemon that predates per-profile identities does not
|
|
316
|
+
* agree: it sends the hardware value whatever the profile's
|
|
317
|
+
* `machine-identity.json` says, so a credential minted for what it reports
|
|
318
|
+
* registers the profile on the default machine's row (the OSK-13845 failure, now
|
|
319
|
+
* reached through version skew rather than through the rule). The comparison
|
|
320
|
+
* needs this: the expected value for the TARGET profile, which is not
|
|
321
|
+
* necessarily the one this process is running as.
|
|
322
|
+
*
|
|
323
|
+
* Decides and persists the profile's identity if nothing has yet — the same
|
|
324
|
+
* side effect `getMachineUuid()` has, for the same reason.
|
|
325
|
+
*/
|
|
326
|
+
export function getMachineUuidForProfile(profile) {
|
|
299
327
|
const hardware = getHardwareMachineUuid();
|
|
300
328
|
// A hosted runtime's identity is ISSUED and fenced by the control plane.
|
|
301
329
|
if (hostedRuntimeIdOverride('OVERSKY_MACHINE_UUID'))
|
|
302
330
|
return hardware;
|
|
303
|
-
const
|
|
304
|
-
if (!
|
|
331
|
+
const name = typeof profile === 'string' ? profile.trim() : '';
|
|
332
|
+
if (!name || name === DEFAULT_PROFILE_NAME)
|
|
305
333
|
return hardware;
|
|
306
|
-
return resolveProfileMachineUuid(
|
|
334
|
+
return resolveProfileMachineUuid(name, hardware);
|
|
335
|
+
}
|
|
336
|
+
function readRecordedChoice(profile) {
|
|
337
|
+
try {
|
|
338
|
+
const file = path.join(resolveConfigRoot(), 'profiles', profile, MACHINE_IDENTITY_FILENAME);
|
|
339
|
+
const parsed = JSON.parse(fs.readFileSync(file, 'utf-8'));
|
|
340
|
+
const reason = parsed.reason === 'new_profile' ||
|
|
341
|
+
parsed.reason === 'pre_existing_profile' ||
|
|
342
|
+
parsed.reason === 'restored_profile'
|
|
343
|
+
? parsed.reason
|
|
344
|
+
: null;
|
|
345
|
+
return {
|
|
346
|
+
reason,
|
|
347
|
+
evidence: Array.isArray(parsed.evidence)
|
|
348
|
+
? parsed.evidence.filter((e) => typeof e === 'string')
|
|
349
|
+
: [],
|
|
350
|
+
decidedAt: typeof parsed.decidedAt === 'string' ? parsed.decidedAt : null,
|
|
351
|
+
};
|
|
352
|
+
}
|
|
353
|
+
catch {
|
|
354
|
+
return { reason: null, evidence: [], decidedAt: null };
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
/**
|
|
358
|
+
* Which machine this process registers as, and WHY — the question a person has
|
|
359
|
+
* when two profiles turn up on one machine page and the logs say nothing.
|
|
360
|
+
*
|
|
361
|
+
* A read, not a decision: it reports the identity `getMachineUuid()` settled on
|
|
362
|
+
* (settling it if nothing has, exactly as any caller would) and the record that
|
|
363
|
+
* explains it. It never changes what a profile registers as.
|
|
364
|
+
*/
|
|
365
|
+
export function describeMachineIdentity() {
|
|
366
|
+
const hardware = getHardwareMachineUuid();
|
|
367
|
+
const machineUuid = getMachineUuid();
|
|
368
|
+
const active = activeMachineProfile;
|
|
369
|
+
const profile = active && active !== DEFAULT_PROFILE_NAME ? active : null;
|
|
370
|
+
const base = { profile, machineUuid, hardware };
|
|
371
|
+
if (hostedRuntimeIdOverride('OVERSKY_MACHINE_UUID')) {
|
|
372
|
+
return {
|
|
373
|
+
...base,
|
|
374
|
+
sharesDefaultMachine: false,
|
|
375
|
+
reason: 'hosted_runtime',
|
|
376
|
+
evidence: [],
|
|
377
|
+
decidedAt: null,
|
|
378
|
+
sentence: 'This runtime is hosted; its machine identity was issued by the control plane.',
|
|
379
|
+
};
|
|
380
|
+
}
|
|
381
|
+
if (!profile) {
|
|
382
|
+
return {
|
|
383
|
+
...base,
|
|
384
|
+
sharesDefaultMachine: false,
|
|
385
|
+
reason: 'default_profile',
|
|
386
|
+
evidence: [],
|
|
387
|
+
decidedAt: null,
|
|
388
|
+
sentence: "The default profile uses this computer's own machine identity.",
|
|
389
|
+
};
|
|
390
|
+
}
|
|
391
|
+
const recorded = readRecordedChoice(profile);
|
|
392
|
+
const sharesDefaultMachine = machineUuid === hardware;
|
|
393
|
+
const reason = recorded.reason ?? 'unrecorded';
|
|
394
|
+
const decided = recorded.decidedAt ? ` (decided ${recorded.decidedAt})` : '';
|
|
395
|
+
const held = recorded.evidence.length > 0 ? ` (${recorded.evidence.join(', ')})` : '';
|
|
396
|
+
let sentence;
|
|
397
|
+
if (reason === 'new_profile') {
|
|
398
|
+
sentence =
|
|
399
|
+
`Profile '${profile}' has its own machine identity: it held no credentials when that ` +
|
|
400
|
+
`identity was first chosen${decided}.`;
|
|
401
|
+
}
|
|
402
|
+
else if (reason === 'pre_existing_profile') {
|
|
403
|
+
sentence =
|
|
404
|
+
`Profile '${profile}' shares this computer's default machine identity: it already held ` +
|
|
405
|
+
`credentials${held} when its identity was first chosen${decided}, and the server ties ` +
|
|
406
|
+
'those credentials to that identity, so changing it would sign the profile out.';
|
|
407
|
+
}
|
|
408
|
+
else if (reason === 'restored_profile') {
|
|
409
|
+
sentence = sharesDefaultMachine
|
|
410
|
+
? `Profile '${profile}' shares this computer's default machine identity, restored from the ` +
|
|
411
|
+
`copy kept outside the profile after its state was removed${decided}.`
|
|
412
|
+
: `Profile '${profile}' has its own machine identity, restored from the copy kept outside ` +
|
|
413
|
+
`the profile after its state was removed${decided}.`;
|
|
414
|
+
}
|
|
415
|
+
else {
|
|
416
|
+
sentence = sharesDefaultMachine
|
|
417
|
+
? `Profile '${profile}' uses this computer's default machine identity; the record of why ` +
|
|
418
|
+
'could not be read.'
|
|
419
|
+
: `Profile '${profile}' has its own machine identity; the record of why could not be read.`;
|
|
420
|
+
}
|
|
421
|
+
return {
|
|
422
|
+
...base,
|
|
423
|
+
sharesDefaultMachine,
|
|
424
|
+
reason,
|
|
425
|
+
evidence: recorded.evidence,
|
|
426
|
+
decidedAt: recorded.decidedAt,
|
|
427
|
+
sentence,
|
|
428
|
+
};
|
|
307
429
|
}
|
|
308
430
|
/** @internal test seam — forget the cached value so the next call re-probes. */
|
|
309
431
|
export function __resetMachineUuidCacheForTest() {
|