@skrr-ai/cli 0.1.36 → 0.1.38
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/README.md +17 -4
- package/bin/dev-fallback.js +167 -4
- package/dist/base-command.js +46 -2
- package/dist/commands/agents/actions/create.d.ts +5 -0
- package/dist/commands/agents/actions/create.js +42 -5
- package/dist/commands/agents/actions/delete.d.ts +1 -0
- package/dist/commands/agents/actions/delete.js +7 -0
- package/dist/commands/agents/actions/update.d.ts +5 -0
- package/dist/commands/agents/actions/update.js +27 -1
- package/dist/commands/agents/api-actions/add.d.ts +41 -0
- package/dist/commands/agents/api-actions/add.js +205 -0
- package/dist/commands/agents/api-actions/index.d.ts +39 -0
- package/dist/commands/agents/api-actions/index.js +103 -0
- package/dist/commands/agents/api-actions/remove.d.ts +14 -0
- package/dist/commands/agents/api-actions/remove.js +36 -0
- package/dist/commands/agents/avatar/default/apply.d.ts +25 -0
- package/dist/commands/agents/avatar/default/apply.js +56 -0
- package/dist/commands/agents/avatar/default/index.d.ts +29 -0
- package/dist/commands/agents/avatar/default/index.js +61 -0
- package/dist/commands/agents/avatar/default/set.d.ts +24 -0
- package/dist/commands/agents/avatar/default/set.js +120 -0
- package/dist/commands/agents/avatar/library/delete.d.ts +20 -0
- package/dist/commands/agents/avatar/library/delete.js +47 -0
- package/dist/commands/agents/avatar/library/index.d.ts +16 -0
- package/dist/commands/agents/avatar/library/index.js +56 -0
- package/dist/commands/agents/avatar/presets.d.ts +19 -0
- package/dist/commands/agents/avatar/presets.js +56 -0
- package/dist/commands/agents/avatar/upload.js +7 -1
- package/dist/commands/agents/categories/create.d.ts +14 -0
- package/dist/commands/agents/categories/create.js +46 -0
- package/dist/commands/agents/categories/delete.d.ts +13 -0
- package/dist/commands/agents/categories/delete.js +41 -0
- package/dist/commands/agents/categories/index.d.ts +36 -0
- package/dist/commands/agents/categories/index.js +135 -0
- package/dist/commands/agents/categories/update.d.ts +22 -0
- package/dist/commands/agents/categories/update.js +59 -0
- package/dist/commands/agents/chat.d.ts +21 -0
- package/dist/commands/agents/chat.js +94 -7
- package/dist/commands/agents/create.d.ts +10 -0
- package/dist/commands/agents/create.js +64 -3
- package/dist/commands/agents/ensure-default.d.ts +27 -0
- package/dist/commands/agents/ensure-default.js +65 -0
- package/dist/commands/agents/list.d.ts +15 -0
- package/dist/commands/agents/list.js +31 -1
- package/dist/commands/agents/mute.d.ts +16 -0
- package/dist/commands/agents/mute.js +38 -0
- package/dist/commands/agents/pin.d.ts +16 -0
- package/dist/commands/agents/pin.js +38 -0
- package/dist/commands/agents/scene-background/upload.d.ts +30 -0
- package/dist/commands/agents/scene-background/upload.js +97 -0
- package/dist/commands/agents/show.js +13 -0
- package/dist/commands/agents/tools/auth.d.ts +19 -0
- package/dist/commands/agents/tools/auth.js +41 -0
- package/dist/commands/agents/tools/calls.d.ts +36 -0
- package/dist/commands/agents/tools/calls.js +117 -0
- package/dist/commands/agents/tools/index.d.ts +20 -0
- package/dist/commands/agents/tools/index.js +77 -0
- package/dist/commands/agents/unmute.d.ts +16 -0
- package/dist/commands/agents/unmute.js +38 -0
- package/dist/commands/agents/unpin.d.ts +16 -0
- package/dist/commands/agents/unpin.js +38 -0
- package/dist/commands/agents/update.d.ts +12 -0
- package/dist/commands/agents/update.js +74 -3
- package/dist/commands/code/{oversky-agent.d.ts → skrr-agent.d.ts} +3 -3
- package/dist/commands/code/{oversky-agent.js → skrr-agent.js} +11 -8
- package/dist/commands/convos/messages.d.ts +13 -0
- package/dist/commands/convos/messages.js +40 -16
- package/dist/commands/daemon/index.js +8 -1
- package/dist/commands/daemon/logs.d.ts +26 -0
- package/dist/commands/daemon/logs.js +56 -0
- package/dist/commands/daemon/uninstall.js +1 -1
- package/dist/commands/followups/act.d.ts +22 -0
- package/dist/commands/followups/act.js +103 -0
- package/dist/commands/followups/cancel.d.ts +20 -0
- package/dist/commands/followups/cancel.js +50 -0
- package/dist/commands/followups/checkin.d.ts +27 -0
- package/dist/commands/followups/checkin.js +107 -0
- package/dist/commands/followups/list.d.ts +24 -0
- package/dist/commands/followups/list.js +90 -0
- package/dist/commands/followups/observability.d.ts +23 -0
- package/dist/commands/followups/observability.js +114 -0
- package/dist/commands/followups/remind.d.ts +26 -0
- package/dist/commands/followups/remind.js +106 -0
- package/dist/commands/followups/reschedule.d.ts +15 -0
- package/dist/commands/followups/reschedule.js +48 -0
- package/dist/commands/followups/resolve.d.ts +23 -0
- package/dist/commands/followups/resolve.js +54 -0
- package/dist/commands/followups/show.d.ts +12 -0
- package/dist/commands/followups/show.js +46 -0
- package/dist/commands/followups/watch.d.ts +51 -0
- package/dist/commands/followups/watch.js +211 -0
- package/dist/commands/goals/labels/add.js +19 -2
- package/dist/commands/goals/labels/remove.js +22 -2
- package/dist/commands/harnesses/forget.js +28 -0
- package/dist/commands/harnesses/install.d.ts +41 -0
- package/dist/commands/harnesses/install.js +165 -0
- package/dist/commands/harnesses/installers.d.ts +45 -0
- package/dist/commands/harnesses/installers.js +155 -0
- package/dist/commands/harnesses/list.d.ts +82 -1
- package/dist/commands/harnesses/list.js +104 -12
- package/dist/commands/harnesses/models.js +10 -1
- package/dist/commands/harnesses/show.d.ts +15 -0
- package/dist/commands/harnesses/show.js +44 -3
- package/dist/commands/harnesses/update.js +1 -1
- package/dist/commands/harnesses/usage.d.ts +25 -0
- package/dist/commands/harnesses/usage.js +24 -2
- package/dist/commands/instructions/status.js +13 -1
- package/dist/commands/labels/list.d.ts +24 -1
- package/dist/commands/labels/list.js +62 -19
- package/dist/commands/machines/dedicated/catalog.js +4 -15
- package/dist/commands/machines/dedicated/create.d.ts +8 -0
- package/dist/commands/machines/dedicated/create.js +58 -1
- package/dist/commands/machines/dedicated/destroy.js +18 -4
- package/dist/commands/machines/dedicated/list.js +9 -6
- package/dist/commands/machines/hosted/list.js +12 -0
- package/dist/commands/machines/list.js +11 -0
- package/dist/commands/machines/show.d.ts +1 -0
- package/dist/commands/machines/show.js +40 -11
- package/dist/commands/memory/governance/index.d.ts +21 -0
- package/dist/commands/memory/governance/index.js +64 -0
- package/dist/commands/memory/governance/set.d.ts +24 -0
- package/dist/commands/memory/governance/set.js +95 -0
- package/dist/commands/memory/provenance.d.ts +18 -0
- package/dist/commands/memory/provenance.js +66 -0
- package/dist/commands/profiles/list.d.ts +23 -0
- package/dist/commands/profiles/list.js +96 -0
- package/dist/commands/search/skills.d.ts +11 -1
- package/dist/commands/search/skills.js +26 -8
- package/dist/commands/skills/details.d.ts +2 -0
- package/dist/commands/skills/details.js +24 -1
- package/dist/commands/skills/import-as-actions.d.ts +32 -0
- package/dist/commands/skills/import-as-actions.js +175 -0
- package/dist/commands/skills/install.d.ts +2 -0
- package/dist/commands/skills/install.js +24 -1
- package/dist/commands/skills/invocable.js +6 -2
- package/dist/commands/skills/local.d.ts +40 -0
- package/dist/commands/skills/local.js +160 -0
- package/dist/commands/skills/search.d.ts +11 -1
- package/dist/commands/skills/search.js +29 -8
- package/dist/commands/spaces/actions/add.js +23 -5
- package/dist/commands/spaces/actions/available.js +3 -0
- package/dist/commands/spaces/actions/list.d.ts +5 -0
- package/dist/commands/spaces/actions/list.js +49 -3
- package/dist/commands/spaces/actions/run.d.ts +28 -0
- package/dist/commands/spaces/actions/run.js +146 -0
- package/dist/commands/spaces/actions/update.js +27 -5
- package/dist/commands/spaces/create.d.ts +3 -0
- package/dist/commands/spaces/create.js +32 -2
- package/dist/commands/spaces/label-summaries.d.ts +27 -0
- package/dist/commands/spaces/label-summaries.js +64 -0
- package/dist/commands/spaces/labels/add.js +19 -2
- package/dist/commands/spaces/labels/remove.js +22 -2
- package/dist/commands/spaces/show.js +2 -0
- package/dist/commands/spaces/task-rollups.d.ts +5 -0
- package/dist/commands/spaces/task-rollups.js +15 -4
- package/dist/commands/spaces/update.d.ts +5 -0
- package/dist/commands/spaces/update.js +41 -4
- package/dist/commands/spaces/workflows/lifecycle-diagnostics.d.ts +11 -0
- package/dist/commands/spaces/workflows/lifecycle-diagnostics.js +105 -0
- package/dist/commands/tasks/actions/attach.js +32 -7
- package/dist/commands/tasks/complete.d.ts +1 -0
- package/dist/commands/tasks/complete.js +21 -1
- package/dist/commands/tasks/create.d.ts +3 -0
- package/dist/commands/tasks/create.js +34 -2
- package/dist/commands/tasks/events/append.js +29 -6
- package/dist/commands/tasks/expectations/assess.d.ts +12 -0
- package/dist/commands/tasks/expectations/assess.js +123 -14
- package/dist/commands/tasks/expectations.js +95 -17
- package/dist/commands/tasks/follow-up.js +2 -2
- package/dist/commands/tasks/labels/attach.js +20 -3
- package/dist/commands/tasks/labels/detach.js +21 -3
- package/dist/commands/tasks/lifecycle/attach.d.ts +14 -0
- package/dist/commands/tasks/lifecycle/attach.js +47 -0
- package/dist/commands/tasks/lifecycle/definitions.d.ts +11 -0
- package/dist/commands/tasks/lifecycle/definitions.js +59 -0
- package/dist/commands/tasks/lifecycle/detach.d.ts +19 -0
- package/dist/commands/tasks/lifecycle/detach.js +72 -0
- package/dist/commands/tasks/lifecycle/history.d.ts +13 -0
- package/dist/commands/tasks/lifecycle/history.js +38 -0
- package/dist/commands/tasks/lifecycle/migrate.d.ts +14 -0
- package/dist/commands/tasks/lifecycle/migrate.js +68 -0
- package/dist/commands/tasks/lifecycle/reconcile.d.ts +11 -0
- package/dist/commands/tasks/lifecycle/reconcile.js +27 -0
- package/dist/commands/tasks/lifecycle/reopen.d.ts +15 -0
- package/dist/commands/tasks/lifecycle/reopen.js +71 -0
- package/dist/commands/tasks/lifecycle/show.d.ts +11 -0
- package/dist/commands/tasks/lifecycle/show.js +27 -0
- package/dist/commands/tasks/lifecycle/start.d.ts +12 -0
- package/dist/commands/tasks/lifecycle/start.js +30 -0
- package/dist/commands/tasks/lifecycle/transition.d.ts +15 -0
- package/dist/commands/tasks/lifecycle/transition.js +109 -0
- package/dist/commands/tasks/list.js +16 -9
- package/dist/commands/tasks/move.d.ts +1 -0
- package/dist/commands/tasks/move.js +29 -0
- package/dist/commands/tasks/result/submit.js +11 -1
- package/dist/commands/tasks/review-queue.d.ts +44 -0
- package/dist/commands/tasks/review-queue.js +314 -0
- package/dist/commands/tasks/show.d.ts +11 -0
- package/dist/commands/tasks/show.js +139 -4
- package/dist/commands/tasks/trust.js +7 -2
- package/dist/commands/tasks/update.d.ts +1 -0
- package/dist/commands/tasks/update.js +83 -0
- package/dist/commands/tasks/updates/add.js +1 -1
- package/dist/commands/token/list.d.ts +22 -0
- package/dist/commands/token/list.js +68 -0
- package/dist/commands/token/revoke.d.ts +23 -0
- package/dist/commands/token/revoke.js +53 -0
- package/dist/lib/agent-actions.d.ts +92 -11
- package/dist/lib/agent-actions.js +171 -25
- package/dist/lib/agent-config.d.ts +11 -0
- package/dist/lib/agent-config.js +85 -3
- package/dist/lib/agent-pin-mute.d.ts +29 -0
- package/dist/lib/agent-pin-mute.js +30 -0
- package/dist/lib/agent-visual-refs.d.ts +33 -0
- package/dist/lib/agent-visual-refs.js +267 -0
- package/dist/lib/agentic-stream.d.ts +6 -0
- package/dist/lib/agentic-stream.js +34 -3
- package/dist/lib/assignee-resolver.d.ts +1 -1
- package/dist/lib/assignee-resolver.js +8 -0
- package/dist/lib/bulk-task-targets.d.ts +12 -0
- package/dist/lib/bulk-task-targets.js +34 -1
- package/dist/lib/cli-installers.d.ts +130 -0
- package/dist/lib/cli-installers.js +145 -0
- package/dist/lib/command-miss.js +55 -7
- package/dist/lib/dedicated-lease-command.d.ts +13 -0
- package/dist/lib/dedicated-lease-command.js +22 -1
- package/dist/lib/dedicated-machines.d.ts +95 -1
- package/dist/lib/dedicated-machines.js +236 -2
- package/dist/lib/failed-lookup.d.ts +3 -0
- package/dist/lib/failed-lookup.js +40 -0
- package/dist/lib/first-party-harness-agent.js +16 -2
- package/dist/lib/first-party-harness-doctor.d.ts +15 -0
- package/dist/lib/first-party-harness-doctor.js +126 -27
- package/dist/lib/followups.d.ts +115 -0
- package/dist/lib/followups.js +127 -0
- package/dist/lib/harnesses.d.ts +8 -0
- package/dist/lib/instruction-input.d.ts +19 -1
- package/dist/lib/instruction-input.js +52 -1
- package/dist/lib/label-ref.d.ts +95 -0
- package/dist/lib/label-ref.js +163 -0
- package/dist/lib/label-scope.d.ts +17 -2
- package/dist/lib/label-scope.js +27 -7
- package/dist/lib/local-skills.d.ts +98 -0
- package/dist/lib/local-skills.js +195 -0
- package/dist/lib/machines.d.ts +10 -10
- package/dist/lib/machines.js +23 -1
- package/dist/lib/search-query.d.ts +19 -0
- package/dist/lib/search-query.js +35 -0
- package/dist/lib/space-custom-actions.d.ts +72 -0
- package/dist/lib/space-custom-actions.js +117 -0
- package/dist/lib/space-resolver.d.ts +1 -21
- package/dist/lib/space-resolver.js +19 -10
- package/dist/lib/task-closure.d.ts +33 -0
- package/dist/lib/task-closure.js +104 -0
- package/dist/lib/task-lifecycle-output.d.ts +14 -0
- package/dist/lib/task-lifecycle-output.js +209 -0
- package/dist/lib/task-ref-resolver.d.ts +1 -17
- package/dist/lib/task-ref-resolver.js +18 -8
- package/dist/lib/tasks.d.ts +3 -0
- package/dist/lib/tasks.js +40 -3
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/harnessTrust.js +4 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/harnessTrust.js +4 -0
- package/dist/node_modules/@skrr-ai/auth-core/package.json +1 -1
- package/dist/node_modules/@skrr-ai/data-provider/index.js +5559 -4897
- package/oclif.manifest.json +33890 -28690
- package/package.json +24 -6
|
@@ -21,6 +21,10 @@ exports.writeDedicatedRuntimeFileChunk = writeDedicatedRuntimeFileChunk;
|
|
|
21
21
|
exports.parseDedicatedCopyEndpoints = parseDedicatedCopyEndpoints;
|
|
22
22
|
exports.dedicatedLeaseId = dedicatedLeaseId;
|
|
23
23
|
exports.dedicatedLeaseState = dedicatedLeaseState;
|
|
24
|
+
exports.dedicatedDestroyRetentionNote = dedicatedDestroyRetentionNote;
|
|
25
|
+
exports.dedicatedScopeMonthSpendCents = dedicatedScopeMonthSpendCents;
|
|
26
|
+
exports.dedicatedLeaseCapCell = dedicatedLeaseCapCell;
|
|
27
|
+
exports.dedicatedLeaseStatusCell = dedicatedLeaseStatusCell;
|
|
24
28
|
exports.dedicatedLeaseDisplayName = dedicatedLeaseDisplayName;
|
|
25
29
|
exports.formatUsdCents = formatUsdCents;
|
|
26
30
|
exports.dedicatedSpendSummary = dedicatedSpendSummary;
|
|
@@ -33,6 +37,9 @@ exports.dedicatedLeaseIdForDaemon = dedicatedLeaseIdForDaemon;
|
|
|
33
37
|
exports.dedicatedTerminalHarness = dedicatedTerminalHarness;
|
|
34
38
|
exports.selectDedicatedAttachHarness = selectDedicatedAttachHarness;
|
|
35
39
|
exports.dedicatedCatalogFromProducts = dedicatedCatalogFromProducts;
|
|
40
|
+
exports.dedicatedCatalogSizeLines = dedicatedCatalogSizeLines;
|
|
41
|
+
exports.dedicatedCreateSummary = dedicatedCreateSummary;
|
|
42
|
+
exports.dedicatedCatalogPriceLineOutput = dedicatedCatalogPriceLineOutput;
|
|
36
43
|
exports.dedicatedRuntimeApiErrorCode = dedicatedRuntimeApiErrorCode;
|
|
37
44
|
exports.dedicatedRuntimeApiErrorDetails = dedicatedRuntimeApiErrorDetails;
|
|
38
45
|
exports.formatDedicatedRuntimeApiError = formatDedicatedRuntimeApiError;
|
|
@@ -300,6 +307,71 @@ function dedicatedLeaseId(lease) {
|
|
|
300
307
|
function dedicatedLeaseState(lease) {
|
|
301
308
|
return String(lease?.state ?? 'unknown');
|
|
302
309
|
}
|
|
310
|
+
/**
|
|
311
|
+
* What `destroy` should say when it keeps the workspace — or null when it does
|
|
312
|
+
* not.
|
|
313
|
+
*
|
|
314
|
+
* A destroy under retention class standard/extended archives the lease and keeps
|
|
315
|
+
* its workspace volume, which keeps billing storage until it is purged. Nothing
|
|
316
|
+
* said so at the moment it mattered: `destroy` printed the new state and exited,
|
|
317
|
+
* `list` showed `archived` in the same column as `terminated`, and the one way to
|
|
318
|
+
* find out was the bill (OSK-9593).
|
|
319
|
+
*/
|
|
320
|
+
function dedicatedDestroyRetentionNote(priorLease, opts) {
|
|
321
|
+
if (opts.purge || !priorLease)
|
|
322
|
+
return null;
|
|
323
|
+
if (priorLease.state === 'archived')
|
|
324
|
+
return null; // destroying an archived lease purges it
|
|
325
|
+
const retentionClass = String(priorLease.storage?.retentionClass || 'none');
|
|
326
|
+
if (!opts.retain && retentionClass === 'none')
|
|
327
|
+
return null;
|
|
328
|
+
const id = dedicatedLeaseId(priorLease) || '<lease-id>';
|
|
329
|
+
const why = opts.retain ? '--retain-storage' : `retention class ${retentionClass}`;
|
|
330
|
+
return (`The workspace is kept (${why}), and its storage keeps billing until you delete it: ` +
|
|
331
|
+
`${opts.bin} machines dedicated destroy ${id} --purge-storage`);
|
|
332
|
+
}
|
|
333
|
+
const DEDICATED_TERMINAL_STATES = new Set(['terminated', 'failed', 'lost']);
|
|
334
|
+
/**
|
|
335
|
+
* Month-to-date Dedicated Runtime spend for the scope a `list` shows.
|
|
336
|
+
*
|
|
337
|
+
* `billing.currentMonthSpendCents` is the SCOPE's spend for the product — the
|
|
338
|
+
* server aggregates by owner scope, not by lease — so every row carried the same
|
|
339
|
+
* figure, and a column headed MONTH/CAP on per-machine rows read as that
|
|
340
|
+
* machine's cost when it was every machine's (OSK-9576). It is said once instead.
|
|
341
|
+
*/
|
|
342
|
+
function dedicatedScopeMonthSpendCents(leases) {
|
|
343
|
+
for (const lease of leases) {
|
|
344
|
+
const cents = lease?.billing
|
|
345
|
+
?.currentMonthSpendCents;
|
|
346
|
+
if (typeof cents === 'number' && Number.isFinite(cents))
|
|
347
|
+
return cents;
|
|
348
|
+
}
|
|
349
|
+
return null;
|
|
350
|
+
}
|
|
351
|
+
/**
|
|
352
|
+
* A lease's own cap, marked when the scope's spend has reached it. The mark is
|
|
353
|
+
* left off a terminal lease: its cap can no longer stop anything, and
|
|
354
|
+
* "$11.06/$10.00 OVER" on a machine terminated days ago read as that machine
|
|
355
|
+
* having overrun.
|
|
356
|
+
*/
|
|
357
|
+
function dedicatedLeaseCapCell(lease) {
|
|
358
|
+
const billing = lease?.billing;
|
|
359
|
+
if (!billing || typeof billing.monthlySpendLimitCents !== 'number')
|
|
360
|
+
return '-';
|
|
361
|
+
const reached = billing.spendingLimitExceeded && !DEDICATED_TERMINAL_STATES.has(dedicatedLeaseState(lease));
|
|
362
|
+
return `${formatUsdCents(billing.monthlySpendLimitCents)}${reached ? ' · reached' : ''}`;
|
|
363
|
+
}
|
|
364
|
+
/**
|
|
365
|
+
* A lease's STATUS cell. `archived` and `terminated` are both "gone" to read, and
|
|
366
|
+
* only one of them is still charging — so a lease billing retained storage says
|
|
367
|
+
* so (OSK-9593).
|
|
368
|
+
*/
|
|
369
|
+
function dedicatedLeaseStatusCell(lease) {
|
|
370
|
+
const state = dedicatedLeaseState(lease);
|
|
371
|
+
const billableState = lease?.billing
|
|
372
|
+
?.billableState;
|
|
373
|
+
return billableState === 'storage' ? `${state} · billing storage` : state;
|
|
374
|
+
}
|
|
303
375
|
function dedicatedLeaseDisplayName(lease) {
|
|
304
376
|
return lease?.displayName ? String(lease.displayName) : '-';
|
|
305
377
|
}
|
|
@@ -310,7 +382,17 @@ function formatUsdCents(cents) {
|
|
|
310
382
|
const sign = cents < 0 ? '-' : '';
|
|
311
383
|
return `${sign}$${(Math.abs(cents) / 100).toFixed(2)}`;
|
|
312
384
|
}
|
|
313
|
-
/**
|
|
385
|
+
/**
|
|
386
|
+
* `$1.23 this month for machines of this type · $500.00 cap for this machine`,
|
|
387
|
+
* or why that sentence cannot be written.
|
|
388
|
+
*
|
|
389
|
+
* The two figures are different scopes and the sentence has to say so. The spend
|
|
390
|
+
* is a shared pot the server computes for (owner, team, machineProduct), so every
|
|
391
|
+
* lease of the same product reports the same number — a machine created minutes
|
|
392
|
+
* ago with no active seconds still reports the month's total. The cap is this
|
|
393
|
+
* lease's own. Printed as "$1.23 this month of $500.00 cap" the only available
|
|
394
|
+
* reading was that this machine had spent it.
|
|
395
|
+
*/
|
|
314
396
|
function dedicatedSpendSummary(lease) {
|
|
315
397
|
const billing = lease.billing;
|
|
316
398
|
if (!billing)
|
|
@@ -321,7 +403,10 @@ function dedicatedSpendSummary(lease) {
|
|
|
321
403
|
}
|
|
322
404
|
const spent = billing.currentMonthSpendCents;
|
|
323
405
|
const projected = billing.projectedCurrentMonthSpendCents;
|
|
324
|
-
const parts = [
|
|
406
|
+
const parts = [
|
|
407
|
+
`${formatUsdCents(spent)} this month for machines of this type`,
|
|
408
|
+
`${formatUsdCents(cap)} cap for this machine`,
|
|
409
|
+
];
|
|
325
410
|
if (typeof projected === 'number' && projected !== spent) {
|
|
326
411
|
parts.push(`projected ${formatUsdCents(projected)}`);
|
|
327
412
|
}
|
|
@@ -743,14 +828,128 @@ function dedicatedCatalogFromProducts(payload) {
|
|
|
743
828
|
: {}),
|
|
744
829
|
retentionClasses: configuration.retentionClasses || [],
|
|
745
830
|
backupProfiles: configuration.backupProfiles || [],
|
|
831
|
+
...(typeof configuration.defaultSizePreset === 'string'
|
|
832
|
+
? { defaultSizePreset: configuration.defaultSizePreset }
|
|
833
|
+
: {}),
|
|
834
|
+
...(typeof configuration.defaultRetentionClass === 'string'
|
|
835
|
+
? { defaultRetentionClass: configuration.defaultRetentionClass }
|
|
836
|
+
: {}),
|
|
837
|
+
...(typeof configuration.defaultBackupProfile === 'string'
|
|
838
|
+
? { defaultBackupProfile: configuration.defaultBackupProfile }
|
|
839
|
+
: {}),
|
|
746
840
|
defaultMonthlySpendingLimitCents: billing.defaultMonthlySpendingLimitCents,
|
|
747
841
|
maxUserMonthlySpendingLimitCents: billing.maxUserMonthlySpendingLimitCents,
|
|
748
842
|
priceLines: Array.isArray(presentation.priceLines)
|
|
749
843
|
? presentation.priceLines
|
|
750
844
|
: [],
|
|
845
|
+
...(typeof billing.priceBook?.version === 'string'
|
|
846
|
+
? { priceBookVersion: billing.priceBook.version }
|
|
847
|
+
: {}),
|
|
751
848
|
...(typeof presentation.headline === 'string' ? { headline: presentation.headline } : {}),
|
|
752
849
|
};
|
|
753
850
|
}
|
|
851
|
+
/**
|
|
852
|
+
* The catalog's size rows: spec, the size's own hourly price, and which one
|
|
853
|
+
* `create` uses by default. The rows used to carry spec alone, sorted by name,
|
|
854
|
+
* so the $1.40/hr tier came first with nothing saying what it cost or that
|
|
855
|
+
* $0.65/hr standard was the default; a reader had to join two blocks by name.
|
|
856
|
+
*/
|
|
857
|
+
function dedicatedCatalogSizeLines(catalog) {
|
|
858
|
+
return catalog.sizes.map((size) => {
|
|
859
|
+
const spec = [
|
|
860
|
+
size.vcpus ? `${size.vcpus} vCPU` : '',
|
|
861
|
+
size.memoryGiB ? `${size.memoryGiB} GiB RAM` : '',
|
|
862
|
+
size.accelerator || '',
|
|
863
|
+
typeof size.rateCentsPerHour === 'number' && size.rateCentsPerHour > 0
|
|
864
|
+
? `${formatUsdCents(size.rateCentsPerHour)}/hr`
|
|
865
|
+
: '',
|
|
866
|
+
]
|
|
867
|
+
.filter(Boolean)
|
|
868
|
+
.join(' · ');
|
|
869
|
+
const isDefault = size.id !== undefined && size.id === catalog.defaultSizePreset;
|
|
870
|
+
return ` ${String(size.id).padEnd(14)}${spec}${isDefault ? ' (default)' : ''}`;
|
|
871
|
+
});
|
|
872
|
+
}
|
|
873
|
+
/**
|
|
874
|
+
* What a create is about to buy, in the words and numbers the catalog uses.
|
|
875
|
+
*
|
|
876
|
+
* `create` provisioned a billable machine the moment it ran — no confirmation,
|
|
877
|
+
* no dry run, and every omitted flag silently took a paid default — while
|
|
878
|
+
* `destroy` asked first. A loop probing size validation bought two real
|
|
879
|
+
* machines, one of them $1.40/hr (OSK-9592). This is what `create` now shows
|
|
880
|
+
* before it asks, and what `--dry-run` prints instead of creating.
|
|
881
|
+
*
|
|
882
|
+
* Every default comes from the catalog, never from this file: a CLI that
|
|
883
|
+
* restates a default it does not own is how `--storage-gb` once billed twice the
|
|
884
|
+
* product's disk. A value the catalog does not declare is shown as "server
|
|
885
|
+
* default" rather than guessed.
|
|
886
|
+
*/
|
|
887
|
+
function dedicatedCreateSummary(catalog, choices) {
|
|
888
|
+
const size = catalog?.sizes.find((entry) => entry.id === choices.sizePreset);
|
|
889
|
+
const spec = size
|
|
890
|
+
? [
|
|
891
|
+
size.vcpus ? `${size.vcpus} vCPU` : '',
|
|
892
|
+
size.memoryGiB ? `${size.memoryGiB} GiB RAM` : '',
|
|
893
|
+
typeof size.rateCentsPerHour === 'number' && size.rateCentsPerHour > 0
|
|
894
|
+
? `${formatUsdCents(size.rateCentsPerHour)} per running hour`
|
|
895
|
+
: '',
|
|
896
|
+
]
|
|
897
|
+
.filter(Boolean)
|
|
898
|
+
.join(' · ')
|
|
899
|
+
: 'not in the catalog this server offers';
|
|
900
|
+
const storagePrice = catalog?.priceLines.find((line) => line.cadence === 'per-gb-month');
|
|
901
|
+
const storageGb = choices.storageGb ?? catalog?.storage?.defaultGb;
|
|
902
|
+
const storage = storageGb !== undefined
|
|
903
|
+
? `${storageGb} GiB${choices.storageGb === undefined ? ' (catalog default)' : ''}`
|
|
904
|
+
: 'server default';
|
|
905
|
+
const retentionClass = choices.retentionClass ?? catalog?.defaultRetentionClass;
|
|
906
|
+
const retention = retentionClass
|
|
907
|
+
? `${retentionClass}${choices.retentionClass === undefined ? ' (catalog default)' : ''}`
|
|
908
|
+
: 'server default';
|
|
909
|
+
const retains = retentionClass !== undefined && retentionClass !== 'none';
|
|
910
|
+
const capCents = choices.spendingLimitCents ?? catalog?.defaultMonthlySpendingLimitCents;
|
|
911
|
+
const cap = capCents !== undefined && capCents !== null
|
|
912
|
+
? `${formatUsdCents(capCents)} per month${choices.spendingLimitCents === undefined ? ' (catalog default)' : ''}`
|
|
913
|
+
: 'server default';
|
|
914
|
+
return [
|
|
915
|
+
`Create Dedicated Runtime "${choices.name}" — it bills while it runs:`,
|
|
916
|
+
` size ${choices.sizePreset} — ${spec}`,
|
|
917
|
+
` storage ${storage}${storagePrice?.display ? ` — ${storagePrice.display}` : ''}`,
|
|
918
|
+
` retention ${retention}${retains ? ' — destroy keeps the workspace, and its storage bills until you purge it' : ''}`,
|
|
919
|
+
` monthly cap ${cap}`,
|
|
920
|
+
];
|
|
921
|
+
}
|
|
922
|
+
/**
|
|
923
|
+
* The catalog's money lines, grouped by what each amount IS.
|
|
924
|
+
*
|
|
925
|
+
* A start hold and a monthly cap used to print under "Prices" beside the hourly
|
|
926
|
+
* rates, so starting a machine read as a 33c charge and "$500 default monthly
|
|
927
|
+
* cap" read as a bill (OSK-9536). A line with no `kind` comes from a server that
|
|
928
|
+
* predates it and is shown the way every line used to be: as a charge.
|
|
929
|
+
*/
|
|
930
|
+
function dedicatedCatalogPriceLineOutput(priceLines, priceBookVersion) {
|
|
931
|
+
// The version is what a charge dispute later cites; it was in the payload and
|
|
932
|
+
// the command dropped it (OSK-9562).
|
|
933
|
+
const pricesHeading = priceBookVersion ? `Prices (price book ${priceBookVersion})` : 'Prices';
|
|
934
|
+
const groups = [
|
|
935
|
+
{ kind: 'charge', heading: pricesHeading },
|
|
936
|
+
{ kind: 'hold', heading: 'Held against your cap at start (not billed)' },
|
|
937
|
+
{ kind: 'limit', heading: 'Monthly caps (--spending-limit-cents)' },
|
|
938
|
+
];
|
|
939
|
+
if (priceLines.length === 0)
|
|
940
|
+
return ['', pricesHeading, ' not published by this server'];
|
|
941
|
+
const output = [];
|
|
942
|
+
for (const group of groups) {
|
|
943
|
+
const lines = priceLines.filter((line) => (line.kind || 'charge') === group.kind);
|
|
944
|
+
if (lines.length === 0)
|
|
945
|
+
continue;
|
|
946
|
+
output.push('', group.heading);
|
|
947
|
+
for (const line of lines) {
|
|
948
|
+
output.push(` ${line.display || `${formatUsdCents(line.amountCents)} ${line.label || ''}`}`);
|
|
949
|
+
}
|
|
950
|
+
}
|
|
951
|
+
return output;
|
|
952
|
+
}
|
|
754
953
|
/**
|
|
755
954
|
* Dedicated Runtime commands are unusually likely to meet a server that has
|
|
756
955
|
* never heard of them.
|
|
@@ -867,9 +1066,44 @@ function dedicatedRuntimeApiErrorDetails(err) {
|
|
|
867
1066
|
*/
|
|
868
1067
|
function describeRefusalReasons(err) {
|
|
869
1068
|
const details = dedicatedRuntimeApiErrorDetails(err);
|
|
1069
|
+
const spend = describeSpendingCapRefusal(err.body, details);
|
|
1070
|
+
if (spend)
|
|
1071
|
+
return spend;
|
|
870
1072
|
const sentences = (0, harnesses_1.describeHealthReasonSentences)(details?.reasons, details?.state);
|
|
871
1073
|
return sentences ? ` Reasons: ${sentences}` : '';
|
|
872
1074
|
}
|
|
1075
|
+
/**
|
|
1076
|
+
* The numbers behind a cap refusal: the cap, this month's spend so far, and
|
|
1077
|
+
* where the refused action would have taken it — plus the command that raises
|
|
1078
|
+
* the cap. Without them "would exceed the monthly cap" left a user guessing by
|
|
1079
|
+
* how much, and which cap (OSK-9552).
|
|
1080
|
+
*/
|
|
1081
|
+
function describeSpendingCapRefusal(body, details) {
|
|
1082
|
+
let code;
|
|
1083
|
+
try {
|
|
1084
|
+
code = JSON.parse(body || '{}').code;
|
|
1085
|
+
}
|
|
1086
|
+
catch {
|
|
1087
|
+
return '';
|
|
1088
|
+
}
|
|
1089
|
+
if (code !== 'RUNTIME_SPENDING_LIMIT_EXCEEDED' || !details)
|
|
1090
|
+
return '';
|
|
1091
|
+
const cents = (key) => {
|
|
1092
|
+
const value = details[key];
|
|
1093
|
+
return typeof value === 'number' && Number.isFinite(value) ? value : null;
|
|
1094
|
+
};
|
|
1095
|
+
const limit = cents('limitCents');
|
|
1096
|
+
const spent = cents('currentSpendCents');
|
|
1097
|
+
const projected = cents('projectedCents');
|
|
1098
|
+
const parts = [
|
|
1099
|
+
limit !== null ? `Cap ${formatUsdCents(limit)}` : '',
|
|
1100
|
+
spent !== null ? `spent this month ${formatUsdCents(spent)}` : '',
|
|
1101
|
+
projected !== null ? `this would bring it to ${formatUsdCents(projected)}` : '',
|
|
1102
|
+
].filter(Boolean);
|
|
1103
|
+
if (parts.length === 0)
|
|
1104
|
+
return '';
|
|
1105
|
+
return ` ${parts.join('; ')}. Raise the cap with \`machines dedicated spending-limit <lease-id> --cents <n>\`.`;
|
|
1106
|
+
}
|
|
873
1107
|
function formatDedicatedRuntimeApiError(err) {
|
|
874
1108
|
if (!(err instanceof api_fetch_1.ApiFetchError) || !err.body) {
|
|
875
1109
|
return null;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.isFailedLookupValue = isFailedLookupValue;
|
|
4
|
+
exports.describeFailedLookupValue = describeFailedLookupValue;
|
|
5
|
+
/**
|
|
6
|
+
* Values a script produces when a lookup upstream has ALREADY failed.
|
|
7
|
+
*
|
|
8
|
+
* `jq -r .id` on a missing field prints `null`. A JavaScript value that was
|
|
9
|
+
* never set stringifies to `undefined`; an object to `[object Object]`. Python
|
|
10
|
+
* prints `None`, Ruby `nil`, and a boolean field read as an id gives `true` or
|
|
11
|
+
* `false`. No person types any of these as a reference to a Task, a Space or a
|
|
12
|
+
* member — and a script passes one exactly when its previous step went wrong.
|
|
13
|
+
*
|
|
14
|
+
* The reference resolvers are generous by design: a person can type part of a
|
|
15
|
+
* title, and when exactly one title contains it, that is the one they meant.
|
|
16
|
+
* The same generosity turned `tasks complete "$ID"` with `ID=null` into
|
|
17
|
+
* "complete whichever single task mentions null". So these are refused before
|
|
18
|
+
* any search runs. Matching is on the WHOLE trimmed value, case-insensitively:
|
|
19
|
+
* a real title that merely contains one of these words still resolves.
|
|
20
|
+
*/
|
|
21
|
+
const FAILED_LOOKUP_VALUES = new Set([
|
|
22
|
+
'null',
|
|
23
|
+
'undefined',
|
|
24
|
+
'none',
|
|
25
|
+
'nil',
|
|
26
|
+
'nan',
|
|
27
|
+
'true',
|
|
28
|
+
'false',
|
|
29
|
+
'[object object]',
|
|
30
|
+
]);
|
|
31
|
+
function isFailedLookupValue(value) {
|
|
32
|
+
return typeof value === 'string' && FAILED_LOOKUP_VALUES.has(value.trim().toLowerCase());
|
|
33
|
+
}
|
|
34
|
+
/** The shared explanation, so every resolver refuses in the same words. */
|
|
35
|
+
function describeFailedLookupValue(value, noun) {
|
|
36
|
+
return (`"${value.trim()}" is not a ${noun} reference — it is what a failed lookup prints ` +
|
|
37
|
+
'(for example `jq -r` on a missing field, or an unset variable). Refusing to search ' +
|
|
38
|
+
'names for it, because a single accidental match would be acted on.\n' +
|
|
39
|
+
' → check the step that produced this value; it most likely failed.');
|
|
40
|
+
}
|
|
@@ -242,10 +242,17 @@ async function resolveFirstPartyHarnessAgent(explicit, deps = {}, options = {})
|
|
|
242
242
|
// Asked, not told: the caller opted out of creation, so "no default" is a fact
|
|
243
243
|
// about this machine rather than a failure, and the remedy is a real command.
|
|
244
244
|
if (options.createDefault === false) {
|
|
245
|
-
throw new FirstPartyHarnessAgentError('agent-unset',
|
|
245
|
+
throw new FirstPartyHarnessAgentError('agent-unset',
|
|
246
|
+
// No roster here. The question was which agent a session runs as, and a
|
|
247
|
+
// hundred names in front of the one sentence that answers it buried the
|
|
248
|
+
// answer (OSK-9396). A person choosing one has `agents list` for that.
|
|
249
|
+
`nothing is configured and you have no ${auth_core_1.FIRST_PARTY_HARNESS.displayName} default agent yet. ` +
|
|
246
250
|
'One is created automatically the first time you run a managed session — ' +
|
|
247
251
|
`or make it now with \`${auth_core_1.FIRST_PARTY_HARNESS.command} skrr-agent --create\`` +
|
|
248
|
-
(rows.length
|
|
252
|
+
(rows.length
|
|
253
|
+
? `, or pick one of your ${rows.length} with ` +
|
|
254
|
+
`\`${auth_core_1.FIRST_PARTY_HARNESS.command} skrr-agent --set <id-or-name>\` (see \`skrr agents list\`)`
|
|
255
|
+
: ''));
|
|
249
256
|
}
|
|
250
257
|
// The endpoint answered without an agent. Nothing here can repair that, but
|
|
251
258
|
// the user still has every ordinary way to name one.
|
|
@@ -419,6 +426,13 @@ async function currentUserId(signal) {
|
|
|
419
426
|
* function only after the flag, the config key, and the sole-owned-agent branch
|
|
420
427
|
* have all declined, which is why the extra round trip is acceptable.
|
|
421
428
|
*/
|
|
429
|
+
/**
|
|
430
|
+
* Deliberately NOT `dataService.ensureDefaultAgent`, which `agents
|
|
431
|
+
* ensure-default` uses for the same endpoint. This path takes an `AbortSignal`
|
|
432
|
+
* and the caller below distinguishes an abort from a refusal — reporting "no
|
|
433
|
+
* default agent" for a caller whose deadline expired sends someone to fix the
|
|
434
|
+
* wrong thing. The shared helper cannot carry a signal, so this one stays.
|
|
435
|
+
*/
|
|
422
436
|
async function ensureDefaultAgent(harness, signal) {
|
|
423
437
|
const response = await (0, api_fetch_1.apiFetch)('/api/agents/default', {
|
|
424
438
|
method: 'POST',
|
|
@@ -35,6 +35,21 @@ export interface DoctorCheck {
|
|
|
35
35
|
detail: string;
|
|
36
36
|
/** What to do about it. Only present when there is something to do. */
|
|
37
37
|
remedy?: string;
|
|
38
|
+
/** The files and directories a check looked at, for `--json` consumers. */
|
|
39
|
+
sources?: DoctorSource[];
|
|
40
|
+
}
|
|
41
|
+
/** One place the engine reads instructions or skills from. */
|
|
42
|
+
export interface DoctorSource {
|
|
43
|
+
/** As a person would type it: relative for the project, `~/` for the user. */
|
|
44
|
+
path: string;
|
|
45
|
+
kind: 'instructions' | 'skills';
|
|
46
|
+
owner: 'engine' | 'compatibility';
|
|
47
|
+
scope: 'project' | 'user';
|
|
48
|
+
present: boolean;
|
|
49
|
+
/** Skill directories holding a SKILL.md; only for a present skill root. */
|
|
50
|
+
skills?: number;
|
|
51
|
+
/** Why the engine will not read it although it exists, when it will not. */
|
|
52
|
+
disabled?: string;
|
|
38
53
|
}
|
|
39
54
|
export interface DoctorReport {
|
|
40
55
|
checks: DoctorCheck[];
|
|
@@ -36,6 +36,7 @@ exports.projectStateDir = projectStateDir;
|
|
|
36
36
|
exports.runDoctor = runDoctor;
|
|
37
37
|
exports.formatReport = formatReport;
|
|
38
38
|
const node_fs_1 = require("node:fs");
|
|
39
|
+
const node_os_1 = require("node:os");
|
|
39
40
|
const node_path_1 = __importDefault(require("node:path"));
|
|
40
41
|
const first_party_harness_1 = require("./first-party-harness");
|
|
41
42
|
const auth_core_1 = require("@skrr-ai/auth-core");
|
|
@@ -285,40 +286,138 @@ function stateDirCheck(cwd, env) {
|
|
|
285
286
|
];
|
|
286
287
|
return { name: 'state-paths', status: 'ok', detail: parts.join('; ') };
|
|
287
288
|
}
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
289
|
+
/**
|
|
290
|
+
* Skill directories directly under `root` that hold a SKILL.md.
|
|
291
|
+
*
|
|
292
|
+
* A symlinked skill directory counts: installers and dotfile managers link
|
|
293
|
+
* skills in, and a count that skipped them reported 11 of a root's 31.
|
|
294
|
+
*/
|
|
295
|
+
function countSkills(root) {
|
|
296
|
+
try {
|
|
297
|
+
return (0, node_fs_1.readdirSync)(root).filter((name) => {
|
|
298
|
+
try {
|
|
299
|
+
return ((0, node_fs_1.statSync)(node_path_1.default.join(root, name)).isDirectory() &&
|
|
300
|
+
(0, node_fs_1.existsSync)(node_path_1.default.join(root, name, 'SKILL.md')));
|
|
301
|
+
}
|
|
302
|
+
catch {
|
|
303
|
+
return false;
|
|
304
|
+
}
|
|
305
|
+
}).length;
|
|
300
306
|
}
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
if ((0, node_fs_1.existsSync)(node_path_1.default.join(root, rel)))
|
|
304
|
-
compatibility.push(rel);
|
|
307
|
+
catch {
|
|
308
|
+
return 0;
|
|
305
309
|
}
|
|
306
|
-
|
|
310
|
+
}
|
|
311
|
+
function compatCheck(cwd, env) {
|
|
312
|
+
// Report every instruction and skill source the engine reads, owned and
|
|
313
|
+
// compatibility alike, so "where did this come from?" has an answer — a WL-2
|
|
314
|
+
// acceptance criterion.
|
|
315
|
+
//
|
|
316
|
+
// It named two skill roots, project-level only, as bare directory names: the
|
|
317
|
+
// user-level `~/.agents/skills` and `~/.claude/skills` the engine also reads
|
|
318
|
+
// were missing, an empty root and a full one looked the same, and nothing said
|
|
319
|
+
// why a machine's other roots (.devin, .windsurf, .codex, …) were absent — so
|
|
320
|
+
// a reader could not tell "not read" from "not reported" (OSK-9357). The set
|
|
321
|
+
// below is the engine's documented compatibility contract
|
|
322
|
+
// (opencode-white-label-implementation-plan §7.2); roots beyond it reach a
|
|
323
|
+
// session only when the daemon links them in, which `skrr skills local` shows.
|
|
324
|
+
const root = node_path_1.default.resolve(cwd);
|
|
325
|
+
const home = env.HOME || (0, node_os_1.homedir)();
|
|
326
|
+
const projectDir = auth_core_1.FIRST_PARTY_HARNESS_ENGINE.projectDirectory;
|
|
327
|
+
const noCompatPrompts = Boolean(env[auth_core_1.FIRST_PARTY_HARNESS_ENGINE.env.noCompatPrompts]);
|
|
328
|
+
const engineHomeDir = (0, first_party_harness_1.engineInstructionHome)(env);
|
|
329
|
+
const shown = (abs) => abs.startsWith(root + node_path_1.default.sep)
|
|
330
|
+
? node_path_1.default.relative(root, abs)
|
|
331
|
+
: abs.startsWith(home + node_path_1.default.sep)
|
|
332
|
+
? `~/${node_path_1.default.relative(home, abs)}`
|
|
333
|
+
: abs;
|
|
334
|
+
const declared = [
|
|
335
|
+
{
|
|
336
|
+
abs: node_path_1.default.join(root, projectDir, 'AGENTS.md'),
|
|
337
|
+
kind: 'instructions',
|
|
338
|
+
owner: 'engine',
|
|
339
|
+
scope: 'project',
|
|
340
|
+
},
|
|
341
|
+
{
|
|
342
|
+
abs: node_path_1.default.join(engineHomeDir, 'AGENTS.md'),
|
|
343
|
+
kind: 'instructions',
|
|
344
|
+
owner: 'engine',
|
|
345
|
+
scope: 'user',
|
|
346
|
+
},
|
|
347
|
+
{
|
|
348
|
+
abs: node_path_1.default.join(root, 'AGENTS.md'),
|
|
349
|
+
kind: 'instructions',
|
|
350
|
+
owner: 'compatibility',
|
|
351
|
+
scope: 'project',
|
|
352
|
+
},
|
|
353
|
+
{
|
|
354
|
+
abs: node_path_1.default.join(root, 'CLAUDE.md'),
|
|
355
|
+
kind: 'instructions',
|
|
356
|
+
owner: 'compatibility',
|
|
357
|
+
scope: 'project',
|
|
358
|
+
...(noCompatPrompts ? { disabled: auth_core_1.FIRST_PARTY_HARNESS_ENGINE.env.noCompatPrompts } : {}),
|
|
359
|
+
},
|
|
360
|
+
{
|
|
361
|
+
abs: node_path_1.default.join(home, '.claude', 'CLAUDE.md'),
|
|
362
|
+
kind: 'instructions',
|
|
363
|
+
owner: 'compatibility',
|
|
364
|
+
scope: 'user',
|
|
365
|
+
...(noCompatPrompts ? { disabled: auth_core_1.FIRST_PARTY_HARNESS_ENGINE.env.noCompatPrompts } : {}),
|
|
366
|
+
},
|
|
367
|
+
{
|
|
368
|
+
abs: node_path_1.default.join(root, '.agents', 'skills'),
|
|
369
|
+
kind: 'skills',
|
|
370
|
+
owner: 'compatibility',
|
|
371
|
+
scope: 'project',
|
|
372
|
+
},
|
|
373
|
+
{
|
|
374
|
+
abs: node_path_1.default.join(root, '.claude', 'skills'),
|
|
375
|
+
kind: 'skills',
|
|
376
|
+
owner: 'compatibility',
|
|
377
|
+
scope: 'project',
|
|
378
|
+
},
|
|
379
|
+
{
|
|
380
|
+
abs: node_path_1.default.join(home, '.agents', 'skills'),
|
|
381
|
+
kind: 'skills',
|
|
382
|
+
owner: 'compatibility',
|
|
383
|
+
scope: 'user',
|
|
384
|
+
},
|
|
385
|
+
{
|
|
386
|
+
abs: node_path_1.default.join(home, '.claude', 'skills'),
|
|
387
|
+
kind: 'skills',
|
|
388
|
+
owner: 'compatibility',
|
|
389
|
+
scope: 'user',
|
|
390
|
+
},
|
|
391
|
+
];
|
|
392
|
+
const sources = declared.map(({ abs, ...source }) => {
|
|
393
|
+
const present = (0, node_fs_1.existsSync)(abs);
|
|
307
394
|
return {
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
395
|
+
path: shown(abs),
|
|
396
|
+
...source,
|
|
397
|
+
present,
|
|
398
|
+
...(source.kind === 'skills' && present ? { skills: countSkills(abs) } : {}),
|
|
311
399
|
};
|
|
312
|
-
}
|
|
313
|
-
const
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
400
|
+
});
|
|
401
|
+
const describe = (source) => {
|
|
402
|
+
if (!source.present)
|
|
403
|
+
return `${source.path} (absent)`;
|
|
404
|
+
if (source.disabled)
|
|
405
|
+
return `${source.path} (off: ${source.disabled})`;
|
|
406
|
+
if (source.kind === 'skills') {
|
|
407
|
+
return `${source.path} (${source.skills} skill${source.skills === 1 ? '' : 's'})`;
|
|
408
|
+
}
|
|
409
|
+
return source.path;
|
|
410
|
+
};
|
|
411
|
+
const owned = sources.filter((source) => source.owner === 'engine');
|
|
412
|
+
const compatibility = sources.filter((source) => source.owner === 'compatibility');
|
|
318
413
|
return {
|
|
319
414
|
name: 'compat-sources',
|
|
320
415
|
status: 'ok',
|
|
321
|
-
detail:
|
|
416
|
+
detail: `${auth_core_1.FIRST_PARTY_HARNESS.displayName}-owned: ${owned.map(describe).join(', ')}; ` +
|
|
417
|
+
`compatibility (read-only): ${compatibility.map(describe).join(', ')}. ` +
|
|
418
|
+
'A daemon-hosted session also gets the skills its daemon discovers under other roots ' +
|
|
419
|
+
'(.devin, .windsurf, .codex, …) — `skrr skills local` lists them.',
|
|
420
|
+
sources,
|
|
322
421
|
};
|
|
323
422
|
}
|
|
324
423
|
function opencodeCheck(cwd) {
|