@skrr-ai/cli 0.1.22 → 0.1.23
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 +83 -73
- package/bin/dev-fallback.js +221 -0
- package/bin/run.js +43 -0
- package/dist/base-command.d.ts +15 -0
- package/dist/base-command.js +71 -10
- package/dist/commands/agents/attach-harness.d.ts +37 -0
- package/dist/commands/agents/attach-harness.js +102 -3
- package/dist/commands/agents/chat.d.ts +69 -1
- package/dist/commands/agents/chat.js +202 -22
- package/dist/commands/agents/create.d.ts +38 -0
- package/dist/commands/agents/create.js +95 -2
- package/dist/commands/agents/schedule-trace.js +11 -0
- package/dist/commands/agents/show.js +29 -1
- package/dist/commands/api-keys/create.d.ts +24 -0
- package/dist/commands/api-keys/create.js +80 -0
- package/dist/commands/api-keys/list.d.ts +11 -0
- package/dist/commands/api-keys/list.js +42 -0
- package/dist/commands/api-keys/revoke.d.ts +14 -0
- package/dist/commands/api-keys/revoke.js +33 -0
- package/dist/commands/api-keys/rotate.d.ts +19 -0
- package/dist/commands/api-keys/rotate.js +42 -0
- package/dist/commands/balance/index.d.ts +18 -0
- package/dist/commands/balance/index.js +29 -0
- package/dist/commands/balance/show.d.ts +25 -0
- package/dist/commands/balance/show.js +60 -0
- package/dist/commands/balance/statement.d.ts +19 -0
- package/dist/commands/balance/statement.js +52 -0
- package/dist/commands/browser/doctor.d.ts +11 -0
- package/dist/commands/browser/doctor.js +11 -0
- package/dist/commands/code/jobs/approve.d.ts +25 -0
- package/dist/commands/code/jobs/approve.js +52 -0
- package/dist/commands/code/jobs/cancel.d.ts +12 -0
- package/dist/commands/code/jobs/cancel.js +39 -0
- package/dist/commands/code/jobs/index.d.ts +19 -0
- package/dist/commands/code/jobs/index.js +38 -0
- package/dist/commands/code/jobs/list.d.ts +12 -0
- package/dist/commands/code/jobs/list.js +87 -0
- package/dist/commands/code/jobs/run.d.ts +32 -0
- package/dist/commands/code/jobs/run.js +151 -0
- package/dist/commands/code/jobs/show.d.ts +12 -0
- package/dist/commands/code/jobs/show.js +86 -0
- package/dist/commands/commitments/preflight.js +18 -4
- package/dist/commands/commitments/receipt-metrics.d.ts +39 -0
- package/dist/commands/commitments/receipt-metrics.js +78 -0
- package/dist/commands/convos/search.js +5 -5
- package/dist/commands/harnesses/leases/list.d.ts +3 -0
- package/dist/commands/harnesses/leases/list.js +59 -12
- package/dist/commands/harnesses/leases/show.js +36 -0
- package/dist/commands/harnesses/list.d.ts +18 -0
- package/dist/commands/harnesses/list.js +30 -0
- package/dist/commands/harnesses/products.js +48 -3
- package/dist/commands/harnesses/quota.d.ts +16 -0
- package/dist/commands/harnesses/quota.js +26 -1
- package/dist/commands/harnesses/usage.js +17 -0
- package/dist/commands/inbox/index.d.ts +2 -1
- package/dist/commands/inbox/index.js +27 -4
- package/dist/commands/login.js +4 -1
- package/dist/commands/machines/list.d.ts +1 -0
- package/dist/commands/machines/list.js +33 -5
- package/dist/commands/memory/approvals/issue.d.ts +18 -0
- package/dist/commands/memory/approvals/issue.js +63 -0
- package/dist/commands/memory/commit.js +5 -2
- package/dist/commands/memory/context.d.ts +3 -2
- package/dist/commands/memory/context.js +9 -11
- package/dist/commands/memory/delete.d.ts +1 -1
- package/dist/commands/memory/list.d.ts +1 -1
- package/dist/commands/memory/list.js +1 -1
- package/dist/commands/memory/mounts/resolve.d.ts +10 -0
- package/dist/commands/memory/mounts/resolve.js +27 -0
- package/dist/commands/memory/proposals/commit.d.ts +18 -0
- package/dist/commands/memory/proposals/commit.js +32 -0
- package/dist/commands/memory/proposals/create.d.ts +18 -0
- package/dist/commands/memory/proposals/create.js +56 -0
- package/dist/commands/memory/proposals/list.d.ts +13 -0
- package/dist/commands/memory/proposals/list.js +31 -0
- package/dist/commands/memory/proposals/promote.d.ts +22 -0
- package/dist/commands/memory/proposals/promote.js +33 -0
- package/dist/commands/memory/proposals/reject.d.ts +16 -0
- package/dist/commands/memory/proposals/reject.js +28 -0
- package/dist/commands/memory/rebuild-index.d.ts +20 -0
- package/dist/commands/memory/rebuild-index.js +25 -0
- package/dist/commands/memory/save.d.ts +1 -1
- package/dist/commands/memory/save.js +1 -1
- package/dist/commands/memory/search.d.ts +6 -3
- package/dist/commands/memory/search.js +27 -3
- package/dist/commands/memory/show.d.ts +1 -1
- package/dist/commands/memory/stores/archive.d.ts +14 -0
- package/dist/commands/memory/stores/archive.js +31 -0
- package/dist/commands/memory/stores/create.d.ts +12 -0
- package/dist/commands/memory/stores/create.js +30 -0
- package/dist/commands/memory/stores/delete.d.ts +15 -0
- package/dist/commands/memory/stores/delete.js +38 -0
- package/dist/commands/memory/stores/list.d.ts +10 -0
- package/dist/commands/memory/stores/list.js +29 -0
- package/dist/commands/memory/stores/show.d.ts +12 -0
- package/dist/commands/memory/stores/show.js +14 -0
- package/dist/commands/memory/stores/update.d.ts +15 -0
- package/dist/commands/memory/stores/update.js +39 -0
- package/dist/commands/memory/sync/delete.d.ts +13 -0
- package/dist/commands/memory/sync/delete.js +35 -0
- package/dist/commands/memory/sync/pull.d.ts +19 -0
- package/dist/commands/memory/sync/pull.js +52 -0
- package/dist/commands/memory/sync/push.d.ts +18 -0
- package/dist/commands/memory/sync/push.js +115 -0
- package/dist/commands/memory/sync/resolve.d.ts +23 -0
- package/dist/commands/memory/sync/resolve.js +27 -0
- package/dist/commands/memory/sync/status.d.ts +9 -0
- package/dist/commands/memory/sync/status.js +22 -0
- package/dist/commands/memory/topics/archive.d.ts +20 -0
- package/dist/commands/memory/topics/archive.js +29 -0
- package/dist/commands/memory/topics/create.d.ts +23 -0
- package/dist/commands/memory/topics/create.js +46 -0
- package/dist/commands/memory/topics/delete.d.ts +22 -0
- package/dist/commands/memory/topics/delete.js +30 -0
- package/dist/commands/memory/topics/forget.d.ts +22 -0
- package/dist/commands/memory/topics/forget.js +29 -0
- package/dist/commands/memory/topics/list.d.ts +13 -0
- package/dist/commands/memory/topics/list.js +22 -0
- package/dist/commands/memory/topics/move.d.ts +22 -0
- package/dist/commands/memory/topics/move.js +26 -0
- package/dist/commands/memory/topics/show.d.ts +17 -0
- package/dist/commands/memory/topics/show.js +21 -0
- package/dist/commands/memory/topics/update.d.ts +23 -0
- package/dist/commands/memory/topics/update.js +27 -0
- package/dist/commands/memory/tree.d.ts +5 -2
- package/dist/commands/memory/tree.js +20 -2
- package/dist/commands/memory/update.d.ts +1 -1
- package/dist/commands/memory/versions/list.d.ts +16 -0
- package/dist/commands/memory/versions/list.js +22 -0
- package/dist/commands/memory/versions/redact.d.ts +21 -0
- package/dist/commands/memory/versions/redact.js +22 -0
- package/dist/commands/memory/versions/restore.d.ts +20 -0
- package/dist/commands/memory/versions/restore.js +16 -0
- package/dist/commands/memory/versions/show.d.ts +15 -0
- package/dist/commands/memory/versions/show.js +17 -0
- package/dist/commands/messages/list.js +25 -8
- package/dist/commands/messages/show.js +10 -0
- package/dist/commands/store/install.js +5 -1
- package/dist/commands/store/releases.js +1 -1
- package/dist/commands/store/update.js +5 -1
- package/dist/commands/subscriptions/cancel.js +5 -1
- package/dist/commands/subscriptions/health.js +5 -1
- package/dist/commands/subscriptions/status.js +5 -1
- package/dist/commands/subscriptions/subscribe.js +5 -1
- package/dist/commands/tasks/activity.d.ts +2 -3
- package/dist/commands/tasks/activity.js +15 -5
- package/dist/commands/tasks/complete.d.ts +18 -150
- package/dist/commands/tasks/complete.js +161 -600
- package/dist/commands/tasks/create.d.ts +5 -0
- package/dist/commands/tasks/create.js +107 -4
- package/dist/commands/tasks/deliverable/add.d.ts +8 -0
- package/dist/commands/tasks/deliverable/add.js +41 -8
- package/dist/commands/tasks/deliverable/confirm.d.ts +5 -5
- package/dist/commands/tasks/deliverable/confirm.js +9 -18
- package/dist/commands/tasks/deliverable/list.d.ts +12 -0
- package/dist/commands/tasks/deliverable/list.js +37 -0
- package/dist/commands/tasks/events/append.d.ts +2 -0
- package/dist/commands/tasks/events/append.js +11 -4
- package/dist/commands/tasks/events/list.d.ts +1 -0
- package/dist/commands/tasks/events/list.js +1 -0
- package/dist/commands/tasks/events/tail.d.ts +1 -0
- package/dist/commands/tasks/events/tail.js +1 -0
- package/dist/commands/tasks/expectations/assess.d.ts +21 -0
- package/dist/commands/tasks/expectations/assess.js +77 -0
- package/dist/commands/tasks/expectations.js +14 -18
- package/dist/commands/tasks/judge.d.ts +1 -0
- package/dist/commands/tasks/judge.js +2 -1
- package/dist/commands/tasks/output.d.ts +2 -11
- package/dist/commands/tasks/output.js +64 -145
- package/dist/commands/tasks/report.d.ts +3 -3
- package/dist/commands/tasks/report.js +64 -41
- package/dist/commands/tasks/resource/add.d.ts +23 -0
- package/dist/commands/tasks/resource/add.js +76 -0
- package/dist/commands/tasks/resource/list.d.ts +13 -0
- package/dist/commands/tasks/resource/list.js +41 -0
- package/dist/commands/tasks/result/show.d.ts +13 -0
- package/dist/commands/tasks/result/show.js +46 -0
- package/dist/commands/tasks/result/submit.d.ts +26 -0
- package/dist/commands/tasks/result/submit.js +134 -0
- package/dist/commands/tasks/resume/save.d.ts +16 -0
- package/dist/commands/tasks/resume/save.js +59 -0
- package/dist/commands/tasks/resume/show.d.ts +13 -0
- package/dist/commands/tasks/resume/show.js +35 -0
- package/dist/commands/tasks/review.d.ts +17 -0
- package/dist/commands/tasks/review.js +54 -0
- package/dist/commands/tasks/runs.js +5 -0
- package/dist/commands/tasks/timeline.d.ts +2 -2
- package/dist/commands/tasks/timeline.js +10 -23
- package/dist/commands/tasks/updates/add.d.ts +22 -0
- package/dist/commands/tasks/updates/add.js +101 -0
- package/dist/commands/tasks/updates/list.d.ts +15 -0
- package/dist/commands/tasks/updates/list.js +57 -0
- package/dist/commands/tasks/waive.d.ts +1 -0
- package/dist/commands/tasks/waive.js +2 -1
- package/dist/lib/agentic-stream.d.ts +257 -0
- package/dist/lib/agentic-stream.js +490 -33
- package/dist/lib/balance.d.ts +8 -0
- package/dist/lib/commitment-product.d.ts +10 -1
- package/dist/lib/commitment-product.js +66 -2
- package/dist/lib/commitments.d.ts +2 -1
- package/dist/lib/commitments.js +1 -0
- package/dist/lib/conversation-search.d.ts +3 -0
- package/dist/lib/conversation-search.js +75 -0
- package/dist/lib/execution-target.d.ts +21 -0
- package/dist/lib/execution-target.js +22 -6
- package/dist/lib/harnesses.d.ts +82 -6
- package/dist/lib/harnesses.js +30 -2
- package/dist/lib/hosted-machines.js +9 -0
- package/dist/lib/inbox.d.ts +2 -1
- package/dist/lib/machines.d.ts +17 -0
- package/dist/lib/machines.js +29 -0
- package/dist/lib/managed-agent-keys.d.ts +104 -0
- package/dist/lib/managed-agent-keys.js +50 -0
- package/dist/lib/memory-scope.d.ts +4 -3
- package/dist/lib/memory-scope.js +9 -9
- package/dist/lib/memory-sync.d.ts +114 -0
- package/dist/lib/memory-sync.js +730 -0
- package/dist/lib/message-provenance.d.ts +42 -0
- package/dist/lib/message-provenance.js +89 -0
- package/dist/lib/scoped-memory-command.d.ts +68 -0
- package/dist/lib/scoped-memory-command.js +183 -0
- package/dist/lib/session-task-endpoints.d.ts +1 -1
- package/dist/lib/session-task-endpoints.js +7 -0
- package/dist/lib/sky-code-broker.d.ts +47 -0
- package/dist/lib/sky-code-broker.js +50 -0
- package/dist/lib/sky-code-doctor.js +10 -1
- package/dist/lib/task-artifact-flags.d.ts +2 -0
- package/dist/lib/task-artifact-flags.js +7 -0
- package/dist/lib/task-execution.d.ts +4 -5
- package/dist/lib/task-execution.js +4 -5
- package/dist/lib/task-extras.d.ts +1 -5
- package/dist/lib/task-extras.js +1 -5
- package/dist/lib/task-transcript.d.ts +5 -7
- package/dist/lib/task-transcript.js +8 -16
- package/dist/lib/tasks.d.ts +7 -21
- package/dist/lib/tasks.js +17 -20
- package/dist/lib/triggers.d.ts +39 -1
- package/dist/lib/triggers.js +70 -2
- package/dist/lib/usage-discovery.d.ts +17 -1
- package/dist/lib/usage-discovery.js +17 -1
- package/dist/node_modules/@skrr-ai/data-provider/index.js +3733 -3618
- package/oclif.manifest.json +16201 -10377
- package/package.json +26 -5
|
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
const core_1 = require("@oclif/core");
|
|
4
4
|
const data_provider_1 = require("@skrr-ai/data-provider");
|
|
5
5
|
const base_command_1 = require("../../base-command");
|
|
6
|
+
const conversation_search_1 = require("../../lib/conversation-search");
|
|
6
7
|
const format_1 = require("../../lib/format");
|
|
7
8
|
/**
|
|
8
9
|
* Message-level search across the caller's own conversations.
|
|
@@ -51,13 +52,14 @@ class ConvosSearch extends base_command_1.BaseCommand {
|
|
|
51
52
|
}
|
|
52
53
|
const hits = Array.isArray(response?.messages) ? response.messages : [];
|
|
53
54
|
const shown = hits.slice(0, flags.limit);
|
|
55
|
+
const compactHits = shown.map((message) => (0, conversation_search_1.compactMessageSearchHit)(message, flags.snippet, query));
|
|
54
56
|
if (flags.json) {
|
|
55
57
|
this.log(JSON.stringify({
|
|
56
58
|
query,
|
|
57
59
|
total: hits.length,
|
|
58
60
|
shown: shown.length,
|
|
59
61
|
truncated: hits.length > shown.length,
|
|
60
|
-
hits:
|
|
62
|
+
hits: compactHits,
|
|
61
63
|
}, null, 2));
|
|
62
64
|
return;
|
|
63
65
|
}
|
|
@@ -65,13 +67,11 @@ class ConvosSearch extends base_command_1.BaseCommand {
|
|
|
65
67
|
this.log(`No messages matched "${query}".`);
|
|
66
68
|
return;
|
|
67
69
|
}
|
|
68
|
-
(0, format_1.renderTable)(
|
|
70
|
+
(0, format_1.renderTable)(compactHits.map((m) => ({
|
|
69
71
|
when: m.createdAt ? String(m.createdAt).slice(0, 10) : '-',
|
|
70
72
|
who: m.isCreatedByUser === true ? 'you' : (0, format_1.formatCell)(m.sender, 'agent'),
|
|
71
73
|
thread: (0, format_1.formatCell)(m.title, 'Untitled'),
|
|
72
|
-
snippet: String(m.text ?? '')
|
|
73
|
-
.replace(/\s+/g, ' ')
|
|
74
|
-
.slice(0, flags.snippet),
|
|
74
|
+
snippet: String(m.text ?? ''),
|
|
75
75
|
})), [
|
|
76
76
|
{ key: 'when', header: 'WHEN' },
|
|
77
77
|
{ key: 'who', header: 'WHO', maxWidth: 14 },
|
|
@@ -4,6 +4,9 @@ export default class HarnessesLeasesList extends BaseCommand {
|
|
|
4
4
|
static examples: string[];
|
|
5
5
|
static flags: {
|
|
6
6
|
json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
7
|
+
limit: import("@oclif/core/lib/interfaces").OptionFlag<number | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
8
|
+
state: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
9
|
+
product: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
7
10
|
};
|
|
8
11
|
run(): Promise<void>;
|
|
9
12
|
}
|
|
@@ -14,18 +14,38 @@ const base_command_1 = require("../../../base-command");
|
|
|
14
14
|
const format_1 = require("../../../lib/format");
|
|
15
15
|
const harnesses_1 = require("../../../lib/harnesses");
|
|
16
16
|
class HarnessesLeasesList extends base_command_1.BaseCommand {
|
|
17
|
-
static description = 'List your
|
|
17
|
+
static description = 'List your harness leases, newest first';
|
|
18
18
|
static examples = [
|
|
19
19
|
'<%= config.bin %> harnesses leases list',
|
|
20
|
+
'<%= config.bin %> harnesses leases list --state lost',
|
|
21
|
+
'<%= config.bin %> harnesses leases list --limit 100 --product hosted-machine',
|
|
20
22
|
'<%= config.bin %> harnesses leases list --json',
|
|
21
23
|
];
|
|
22
|
-
static flags = {
|
|
24
|
+
static flags = {
|
|
25
|
+
json: core_1.Flags.boolean({ description: 'Output as JSON' }),
|
|
26
|
+
limit: core_1.Flags.integer({
|
|
27
|
+
description: 'How many to return, newest first (1-100; the server defaults to 50)',
|
|
28
|
+
min: 1,
|
|
29
|
+
max: 100,
|
|
30
|
+
}),
|
|
31
|
+
state: core_1.Flags.string({
|
|
32
|
+
description: 'Only this lease state — e.g. active, paused, terminated, failed, lost. `lost` is the one worth asking for: it means the platform stopped tracking the machine, and it is billed for the whole gap.',
|
|
33
|
+
}),
|
|
34
|
+
product: core_1.Flags.string({
|
|
35
|
+
description: 'Only this machine product',
|
|
36
|
+
options: ['hosted-machine', 'hosted-job-machine'],
|
|
37
|
+
}),
|
|
38
|
+
};
|
|
23
39
|
async run() {
|
|
24
40
|
this.requireAuth();
|
|
25
41
|
const { flags } = await this.parse(HarnessesLeasesList);
|
|
26
42
|
let response;
|
|
27
43
|
try {
|
|
28
|
-
response = await (0, harnesses_1.listHarnessLeases)(
|
|
44
|
+
response = await (0, harnesses_1.listHarnessLeases)({
|
|
45
|
+
limit: flags.limit,
|
|
46
|
+
state: flags.state,
|
|
47
|
+
machineProduct: flags.product,
|
|
48
|
+
});
|
|
29
49
|
}
|
|
30
50
|
catch (err) {
|
|
31
51
|
this.handleApiError(err);
|
|
@@ -39,21 +59,48 @@ class HarnessesLeasesList extends base_command_1.BaseCommand {
|
|
|
39
59
|
if (leases.length === 0) {
|
|
40
60
|
// Say what empty MEANS. "No leases" reads as a failed query; the honest
|
|
41
61
|
// reading is that nothing hosted is running, and nothing is being billed.
|
|
42
|
-
|
|
62
|
+
// With a filter on, that reading would be a lie — the absence is about
|
|
63
|
+
// the filter, not the account.
|
|
64
|
+
const filters = [
|
|
65
|
+
flags.state ? `state ${flags.state}` : '',
|
|
66
|
+
flags.product ? `product ${flags.product}` : '',
|
|
67
|
+
].filter(Boolean);
|
|
68
|
+
this.log(filters.length
|
|
69
|
+
? `No leases matching ${filters.join(' and ')}. Without a filter this lists every lease, newest first.`
|
|
70
|
+
: 'No leases — nothing hosted is running, and nothing is accruing.');
|
|
43
71
|
return;
|
|
44
72
|
}
|
|
73
|
+
// The server caps at 100 and defaults to 50, so a full page is ambiguous:
|
|
74
|
+
// it may be all there is, or the newest of more. Say which rather than
|
|
75
|
+
// letting the reader assume.
|
|
76
|
+
if (!flags.json && leases.length === (flags.limit ?? 50)) {
|
|
77
|
+
this.log(`Showing the newest ${leases.length}. There may be more — raise \`--limit\` (max 100) or narrow with \`--state\`.`);
|
|
78
|
+
}
|
|
79
|
+
// Columns follow the payload, not a guess at it. PRODUCT is the one that
|
|
80
|
+
// tells a Hosted Machine lease from a Hosted Job Machine lease, and BILLING
|
|
81
|
+
// answers the question a lease list exists to answer: is this still
|
|
82
|
+
// charging me. There is no ENGINE or EXPIRES on a lease -- it carries no
|
|
83
|
+
// top-level runtime id and does not expire -- so those columns are gone
|
|
84
|
+
// rather than printed empty.
|
|
45
85
|
(0, format_1.renderTable)(leases.map((lease) => ({
|
|
46
|
-
id:
|
|
47
|
-
product:
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
86
|
+
id: (0, format_1.formatCell)(lease.id),
|
|
87
|
+
product: (0, format_1.formatCell)(lease.machineProduct),
|
|
88
|
+
name: (0, format_1.formatCell)(lease.displayName),
|
|
89
|
+
state: (0, format_1.formatCell)(lease.stateReason && lease.stateReason !== lease.state
|
|
90
|
+
? `${lease.state} (${lease.stateReason})`
|
|
91
|
+
: lease.state),
|
|
92
|
+
billing: (0, format_1.formatCell)(lease.billing?.billableState),
|
|
93
|
+
updated: (0, format_1.localStamp)(lease.updatedAt ?? lease.leaseTimestamps?.lastStateChangeAt),
|
|
51
94
|
})), [
|
|
52
95
|
{ key: 'id', header: 'LEASE' },
|
|
53
96
|
{ key: 'product', header: 'PRODUCT' },
|
|
54
|
-
{ key: '
|
|
55
|
-
|
|
56
|
-
|
|
97
|
+
{ key: 'name', header: 'NAME', maxWidth: 24 },
|
|
98
|
+
// The reason is the actionable half of a state, so it stays in the
|
|
99
|
+
// column rather than moving to `show` -- capped only so a long one
|
|
100
|
+
// cannot wrap the whole table on an 80-column terminal.
|
|
101
|
+
{ key: 'state', header: 'STATE', maxWidth: 30 },
|
|
102
|
+
{ key: 'billing', header: 'BILLING' },
|
|
103
|
+
{ key: 'updated', header: 'UPDATED' },
|
|
57
104
|
], (line) => this.log(line));
|
|
58
105
|
}
|
|
59
106
|
}
|
|
@@ -12,6 +12,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
12
12
|
const core_1 = require("@oclif/core");
|
|
13
13
|
const base_command_1 = require("../../../base-command");
|
|
14
14
|
const harnesses_1 = require("../../../lib/harnesses");
|
|
15
|
+
const balance_1 = require("../../../lib/balance");
|
|
15
16
|
class HarnessesLeasesShow extends base_command_1.BaseCommand {
|
|
16
17
|
static description = 'Show one harness lease';
|
|
17
18
|
static examples = ['<%= config.bin %> harnesses leases show <lease-id>'];
|
|
@@ -46,6 +47,8 @@ class HarnessesLeasesShow extends base_command_1.BaseCommand {
|
|
|
46
47
|
const line = (label, value) => {
|
|
47
48
|
if (value === undefined || value === null || value === '')
|
|
48
49
|
return;
|
|
50
|
+
// 14 columns. A longer label does not wrap, it collides with its own
|
|
51
|
+
// value — keep new labels inside it.
|
|
49
52
|
this.log(`${label.padEnd(14)}${String(value)}`);
|
|
50
53
|
};
|
|
51
54
|
// Only ever a PRIMITIVE reaches `line`. Falling back to the parent object
|
|
@@ -77,6 +80,39 @@ class HarnessesLeasesShow extends base_command_1.BaseCommand {
|
|
|
77
80
|
// Money last, and only when the server sent it — an absent billing block
|
|
78
81
|
// and a zero are different states.
|
|
79
82
|
line('Billing:', nested(lease.billing, 'billableState'));
|
|
83
|
+
// The monthly cap, which is what actually refuses a Hosted Machine.
|
|
84
|
+
//
|
|
85
|
+
// The server has computed and sent these on every lease read all along and
|
|
86
|
+
// the web renders them; the CLI printed only `billableState`. So a refusal
|
|
87
|
+
// said "spending limit exceeded" and the only number a CLI user could find
|
|
88
|
+
// was `skrr balance show`'s DAILY cap, sitting at full headroom — which
|
|
89
|
+
// made the refusal look like it was about something else (OSK-7920).
|
|
90
|
+
//
|
|
91
|
+
// Read through `nested` like every other sub-object here: these arrive on a
|
|
92
|
+
// permissive payload type, and the helper is what keeps a non-primitive
|
|
93
|
+
// from rendering as `[object Object]`.
|
|
94
|
+
const cents = (key) => {
|
|
95
|
+
const value = nested(lease.billing, key);
|
|
96
|
+
// `formatMicros` takes micro-dollars; these are cents.
|
|
97
|
+
return typeof value === 'number' ? (0, balance_1.formatMicros)(value * 10_000) : undefined;
|
|
98
|
+
};
|
|
99
|
+
if (nested(lease.billing, 'spendStatusUnavailable') === true) {
|
|
100
|
+
// Distinguish "we could not read it" from "you have headroom". Admission
|
|
101
|
+
// fails CLOSED on an unreadable status, so silence would be the most
|
|
102
|
+
// misleading thing to print.
|
|
103
|
+
line('Monthly cap:', 'unavailable — the spend status could not be read');
|
|
104
|
+
}
|
|
105
|
+
else if (cents('monthlySpendLimitCents')) {
|
|
106
|
+
line('Monthly cap:', cents('monthlySpendLimitCents'));
|
|
107
|
+
line('Spent:', cents('currentMonthSpendCents'));
|
|
108
|
+
line('Open leases:', cents('openUsageEstimateCents'));
|
|
109
|
+
// Projected is what admission compares against the cap, so it is the
|
|
110
|
+
// number that decides whether the next turn is refused.
|
|
111
|
+
const over = nested(lease.billing, 'spendingLimitExceeded') === true;
|
|
112
|
+
const projected = cents('projectedCurrentMonthSpendCents');
|
|
113
|
+
line('Projected:', projected ? `${projected}${over ? ' — over the cap' : ''}` : undefined);
|
|
114
|
+
line('Month began:', nested(lease.billing, 'monthStartedAt'));
|
|
115
|
+
}
|
|
80
116
|
this.log('');
|
|
81
117
|
this.log('Full record: --json');
|
|
82
118
|
}
|
|
@@ -14,6 +14,10 @@ export type HarnessRow = {
|
|
|
14
14
|
status?: string;
|
|
15
15
|
harnessLocation?: string;
|
|
16
16
|
lastSeenAt?: string;
|
|
17
|
+
metadata?: {
|
|
18
|
+
machineProduct?: string;
|
|
19
|
+
source?: string;
|
|
20
|
+
};
|
|
17
21
|
};
|
|
18
22
|
export type HarnessSelection = {
|
|
19
23
|
/** Rows to print, after every filter and the `--limit` slice. */
|
|
@@ -33,6 +37,20 @@ export type HarnessSelection = {
|
|
|
33
37
|
* cloud products never register through a daemon. Treating the missing field
|
|
34
38
|
* as cloud made a healthy, connected local harness disappear from the one CLI
|
|
35
39
|
* command intended to discover it.
|
|
40
|
+
*
|
|
41
|
+
* "Cloud products never register through a daemon" is no longer true, and that
|
|
42
|
+
* is why the product identity is checked FIRST. The Hosted Machine boots a
|
|
43
|
+
* daemon inside itself and registers through the ordinary local path, so its
|
|
44
|
+
* row carries `harnessLocation: 'local'` on a machine whose `compute.ownership`
|
|
45
|
+
* is `oversky-managed` — and it therefore appeared in the DEFAULT, local-only
|
|
46
|
+
* listing. `--local`'s documented meaning ("Only show local (daemon-backed)
|
|
47
|
+
* harnesses … pass --no-local to include cloud/hosted rows") did not hold: a
|
|
48
|
+
* user filtering to their own machines was silently shown a cloud one, and the
|
|
49
|
+
* flag that separates them separated nothing (OSK-7636).
|
|
50
|
+
*
|
|
51
|
+
* Read-side rather than a stored-value migration on purpose: existing rows
|
|
52
|
+
* already carry the wrong `harnessLocation`, and rewriting it would have to
|
|
53
|
+
* move the registration identity filter with it.
|
|
36
54
|
*/
|
|
37
55
|
export declare function isLocalHarnessRow(row: HarnessRow): boolean;
|
|
38
56
|
/**
|
|
@@ -7,14 +7,44 @@ const core_1 = require("@oclif/core");
|
|
|
7
7
|
const base_command_1 = require("../../base-command");
|
|
8
8
|
const api_fetch_1 = require("../../lib/api-fetch");
|
|
9
9
|
const format_1 = require("../../lib/format");
|
|
10
|
+
/**
|
|
11
|
+
* Products skrr provisions and owns. A row that says it is one of these is
|
|
12
|
+
* cloud, whatever `harnessLocation` reads.
|
|
13
|
+
*/
|
|
14
|
+
const MANAGED_MACHINE_PRODUCTS = new Set(['hosted-machine', 'hosted-job-machine']);
|
|
15
|
+
const MANAGED_REGISTRATION_SOURCES = new Set([
|
|
16
|
+
'hosted-machine',
|
|
17
|
+
'hosted-job-machine',
|
|
18
|
+
'cloud-coding',
|
|
19
|
+
]);
|
|
10
20
|
/**
|
|
11
21
|
* Harness rows created before `harnessLocation` was introduced do not carry that
|
|
12
22
|
* field. A daemon id is the durable discriminator for those legacy rows:
|
|
13
23
|
* cloud products never register through a daemon. Treating the missing field
|
|
14
24
|
* as cloud made a healthy, connected local harness disappear from the one CLI
|
|
15
25
|
* command intended to discover it.
|
|
26
|
+
*
|
|
27
|
+
* "Cloud products never register through a daemon" is no longer true, and that
|
|
28
|
+
* is why the product identity is checked FIRST. The Hosted Machine boots a
|
|
29
|
+
* daemon inside itself and registers through the ordinary local path, so its
|
|
30
|
+
* row carries `harnessLocation: 'local'` on a machine whose `compute.ownership`
|
|
31
|
+
* is `oversky-managed` — and it therefore appeared in the DEFAULT, local-only
|
|
32
|
+
* listing. `--local`'s documented meaning ("Only show local (daemon-backed)
|
|
33
|
+
* harnesses … pass --no-local to include cloud/hosted rows") did not hold: a
|
|
34
|
+
* user filtering to their own machines was silently shown a cloud one, and the
|
|
35
|
+
* flag that separates them separated nothing (OSK-7636).
|
|
36
|
+
*
|
|
37
|
+
* Read-side rather than a stored-value migration on purpose: existing rows
|
|
38
|
+
* already carry the wrong `harnessLocation`, and rewriting it would have to
|
|
39
|
+
* move the registration identity filter with it.
|
|
16
40
|
*/
|
|
17
41
|
function isLocalHarnessRow(row) {
|
|
42
|
+
const product = row.metadata?.machineProduct?.trim() ?? '';
|
|
43
|
+
if (MANAGED_MACHINE_PRODUCTS.has(product))
|
|
44
|
+
return false;
|
|
45
|
+
const source = row.metadata?.source?.trim() ?? '';
|
|
46
|
+
if (MANAGED_REGISTRATION_SOURCES.has(source))
|
|
47
|
+
return false;
|
|
18
48
|
return row.harnessLocation === 'local' || (row.harnessLocation == null && Boolean(row.daemonId));
|
|
19
49
|
}
|
|
20
50
|
/**
|
|
@@ -4,6 +4,34 @@ const core_1 = require("@oclif/core");
|
|
|
4
4
|
const base_command_1 = require("../../base-command");
|
|
5
5
|
const format_1 = require("../../lib/format");
|
|
6
6
|
const harnesses_1 = require("../../lib/harnesses");
|
|
7
|
+
/**
|
|
8
|
+
* How you actually start each product FROM HERE.
|
|
9
|
+
*
|
|
10
|
+
* The server sends a `userAction` (`start-hosted-machine`, …) and the table
|
|
11
|
+
* used to print it. That token is a launch-context assertion the API validates
|
|
12
|
+
* against `launchSurfaces` — it is not a command, and printing it in a column
|
|
13
|
+
* headed ACTION told a reader to run something that does not exist (OSK-7779).
|
|
14
|
+
*
|
|
15
|
+
* So the column names a real command instead. The map lives here rather than on
|
|
16
|
+
* the server because only the CLI knows its own command names; a product with
|
|
17
|
+
* no entry prints `-` and is called out below the table, which is the honest
|
|
18
|
+
* rendering of "you cannot start this from a terminal".
|
|
19
|
+
*/
|
|
20
|
+
const START_COMMAND = {
|
|
21
|
+
'byo-machine': 'harnesses install-token',
|
|
22
|
+
'hosted-machine': 'machines hosted start',
|
|
23
|
+
// Not `machines …`: a Hosted Job Machine is one-shot compute that exists for
|
|
24
|
+
// the duration of one job, so the job is what you create.
|
|
25
|
+
//
|
|
26
|
+
// `code jobs run`, not `code handover`. Both start this product, and the
|
|
27
|
+
// difference is the one the finding was actually about: `handover` clones a
|
|
28
|
+
// repository, works it and opens a pull request, so it cannot start the bare
|
|
29
|
+
// one-shot the product describes — `"continuity": {"semantics": "one-shot"}`
|
|
30
|
+
// with `stateRetention: false` on filesystem, memory and processes. Pointing
|
|
31
|
+
// a reader who wants compute at the repository flow is a smaller version of
|
|
32
|
+
// pointing them at a verb nobody implements.
|
|
33
|
+
'hosted-job-machine': 'code jobs run',
|
|
34
|
+
};
|
|
7
35
|
/**
|
|
8
36
|
* `availability` is a string on some rows and an object on others. The table
|
|
9
37
|
* has to render both, and a `[object Object]` cell in a catalogue listing is
|
|
@@ -43,17 +71,34 @@ class HarnessesProducts extends base_command_1.BaseCommand {
|
|
|
43
71
|
this.log('No harness products available.');
|
|
44
72
|
return;
|
|
45
73
|
}
|
|
74
|
+
const bin = this.config.bin;
|
|
46
75
|
(0, format_1.renderTable)(products.map((p) => ({
|
|
47
76
|
id: (0, format_1.formatCell)(p.id),
|
|
48
77
|
label: (0, format_1.formatCell)(p.label),
|
|
49
|
-
|
|
78
|
+
// What you are buying: `one-shot` and `true-resume` are the difference
|
|
79
|
+
// between compute that forgets everything and a workspace that resumes.
|
|
80
|
+
lifecycle: (0, format_1.formatCell)(p.lifecycleSemantics),
|
|
81
|
+
start: p.id && START_COMMAND[p.id] ? `${bin} ${START_COMMAND[p.id]}` : '-',
|
|
50
82
|
availability: availabilityLabel(p),
|
|
51
83
|
})), [
|
|
52
84
|
{ key: 'id', header: 'ID' },
|
|
53
|
-
{ key: 'label', header: 'LABEL', maxWidth:
|
|
54
|
-
{ key: '
|
|
85
|
+
{ key: 'label', header: 'LABEL', maxWidth: 26 },
|
|
86
|
+
{ key: 'lifecycle', header: 'LIFECYCLE' },
|
|
87
|
+
{ key: 'start', header: 'START' },
|
|
55
88
|
{ key: 'availability', header: 'AVAILABILITY' },
|
|
56
89
|
], (line) => this.log(line));
|
|
90
|
+
// A product the CLI cannot start is worth one line. Silence here is what
|
|
91
|
+
// made the old ACTION column misleading: `available` beside a verb nobody
|
|
92
|
+
// implements reads as "run this", and the reader learns otherwise by
|
|
93
|
+
// failing.
|
|
94
|
+
const unreachable = products.filter((p) => p.id && !START_COMMAND[p.id]);
|
|
95
|
+
if (unreachable.length > 0) {
|
|
96
|
+
this.log('');
|
|
97
|
+
for (const p of unreachable) {
|
|
98
|
+
const where = p.catalog?.launchSurfaces?.join(', ') || 'unknown';
|
|
99
|
+
this.log(`${p.id}: not startable from the CLI — launch surfaces: ${where}`);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
57
102
|
// The full record carries contract, billing, compute and lifecycle blocks.
|
|
58
103
|
// Pointing at --json is cheaper than a second table nobody asked for.
|
|
59
104
|
this.log('');
|
|
@@ -21,6 +21,22 @@ import { BaseCommand } from '../../base-command';
|
|
|
21
21
|
* cannot: is this window going to run out before it resets, which days were
|
|
22
22
|
* expensive, was last week's cap actually hit.
|
|
23
23
|
*/
|
|
24
|
+
/**
|
|
25
|
+
* WHY this window is empty — without asserting a cause we cannot know.
|
|
26
|
+
*
|
|
27
|
+
* OSK-7616 — this used to read "Runs started outside skrr still move the
|
|
28
|
+
* provider meter above, but cannot be priced here", which names one
|
|
29
|
+
* explanation as though it were the only one. In the reported case it was the
|
|
30
|
+
* wrong one: three Codex turns were started THROUGH skrr, completed, and were
|
|
31
|
+
* recorded at zero tokens because the harness reported an empty usage envelope.
|
|
32
|
+
* The reader was told, by the one screen whose job is answering "what is my
|
|
33
|
+
* agent costing me", that the cause was something they had not done.
|
|
34
|
+
*
|
|
35
|
+
* The second sentence is the one that was missing, and it is the actionable
|
|
36
|
+
* half: a run skrr saw and could not price is a reportable defect, not a
|
|
37
|
+
* property of the user's habits.
|
|
38
|
+
*/
|
|
39
|
+
export declare function unpricedWindowLines(): string[];
|
|
24
40
|
export default class HarnessesQuota extends BaseCommand {
|
|
25
41
|
static description: string;
|
|
26
42
|
static examples: string[];
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.unpricedWindowLines = unpricedWindowLines;
|
|
3
4
|
const core_1 = require("@oclif/core");
|
|
4
5
|
const base_command_1 = require("../../base-command");
|
|
5
6
|
const data_provider_1 = require("@skrr-ai/data-provider");
|
|
@@ -28,6 +29,28 @@ const quota_render_1 = require("../../lib/quota-render");
|
|
|
28
29
|
* cannot: is this window going to run out before it resets, which days were
|
|
29
30
|
* expensive, was last week's cap actually hit.
|
|
30
31
|
*/
|
|
32
|
+
/**
|
|
33
|
+
* WHY this window is empty — without asserting a cause we cannot know.
|
|
34
|
+
*
|
|
35
|
+
* OSK-7616 — this used to read "Runs started outside skrr still move the
|
|
36
|
+
* provider meter above, but cannot be priced here", which names one
|
|
37
|
+
* explanation as though it were the only one. In the reported case it was the
|
|
38
|
+
* wrong one: three Codex turns were started THROUGH skrr, completed, and were
|
|
39
|
+
* recorded at zero tokens because the harness reported an empty usage envelope.
|
|
40
|
+
* The reader was told, by the one screen whose job is answering "what is my
|
|
41
|
+
* agent costing me", that the cause was something they had not done.
|
|
42
|
+
*
|
|
43
|
+
* The second sentence is the one that was missing, and it is the actionable
|
|
44
|
+
* half: a run skrr saw and could not price is a reportable defect, not a
|
|
45
|
+
* property of the user's habits.
|
|
46
|
+
*/
|
|
47
|
+
function unpricedWindowLines() {
|
|
48
|
+
return [
|
|
49
|
+
'The provider meter above counts every run on this harness; this table counts only the runs skrr priced.',
|
|
50
|
+
'A run started outside skrr is never priced here. A run started THROUGH skrr should be — if one is missing, its harness reported no token usage, which is a bug worth reporting.',
|
|
51
|
+
' skrr harnesses usage # the runs skrr did see',
|
|
52
|
+
];
|
|
53
|
+
}
|
|
31
54
|
class HarnessesQuota extends base_command_1.BaseCommand {
|
|
32
55
|
static description = 'Claude Code / Codex subscription quota over time — windows, pace, and daily spend';
|
|
33
56
|
static examples = [
|
|
@@ -180,7 +203,9 @@ class HarnessesQuota extends base_command_1.BaseCommand {
|
|
|
180
203
|
// is a real and common state that must not read as "you spent nothing".
|
|
181
204
|
this.log('');
|
|
182
205
|
this.log('No skrr-recorded token spend in this window.');
|
|
183
|
-
|
|
206
|
+
for (const line of unpricedWindowLines()) {
|
|
207
|
+
this.log(line);
|
|
208
|
+
}
|
|
184
209
|
return;
|
|
185
210
|
}
|
|
186
211
|
this.log('');
|
|
@@ -122,6 +122,23 @@ class HarnessesUsage extends base_command_1.BaseCommand {
|
|
|
122
122
|
this.log(`Total: ${count(totals.sessions)} sessions · ${usd(totals.totalCostUsd)} · ` +
|
|
123
123
|
`${count(totals.inputTokens)} in / ${count(totals.outputTokens)} out / ` +
|
|
124
124
|
`${count(totals.cachedInputTokens)} cached`);
|
|
125
|
+
// SAY WHICH PROVIDERS THAT TOTAL COVERS.
|
|
126
|
+
//
|
|
127
|
+
// It was presented as the account total and is not: the ingestion path is
|
|
128
|
+
// fed by the Claude account-telemetry reader, so five completed Codex
|
|
129
|
+
// runs on the SAME daemon as a reported Claude harness produced no row at
|
|
130
|
+
// all, and `grandTotals.sessions: 150` was the Claude-only figure with no
|
|
131
|
+
// qualifier. A user reading it to answer "what has my automation cost me"
|
|
132
|
+
// gets a confidently wrong answer, and nothing hints that entire
|
|
133
|
+
// providers are missing (OSK-7672). Naming the providers present is not
|
|
134
|
+
// the whole fix — the missing producers are — but it is the difference
|
|
135
|
+
// between an incomplete number and a wrong one.
|
|
136
|
+
const providers = [...new Set(rows.map((r) => r.provider).filter(Boolean))].sort();
|
|
137
|
+
if (!args.harness && providers.length > 0) {
|
|
138
|
+
this.log(`Covers ${providers.join(', ')} only — usage is recorded per provider, and a harness ` +
|
|
139
|
+
'whose provider has no usage producer contributes nothing to this total. ' +
|
|
140
|
+
'This is NOT necessarily your whole account.');
|
|
141
|
+
}
|
|
125
142
|
}
|
|
126
143
|
}
|
|
127
144
|
}
|
|
@@ -4,7 +4,8 @@ import { BaseCommand } from '../../base-command';
|
|
|
4
4
|
*
|
|
5
5
|
* Gap analysis §3.3 (b). The CLI's 50 command groups were entirely pull-shaped,
|
|
6
6
|
* with nothing that surfaced an agent-initiated message. The reply direction
|
|
7
|
-
* already closed the loop (`skrr agents chat --conversation <id
|
|
7
|
+
* already closed the loop (`skrr agents chat <agent-id> --conversation <id>
|
|
8
|
+
* --prompt "…"` stamps
|
|
8
9
|
* `Message.intentId` and wakes the originating run) — so the missing half was
|
|
9
10
|
* literally "tell me it happened", and its absence is what made use case 3's
|
|
10
11
|
* "the agent messages me a couple of times like a person" a terminal dead end.
|
|
@@ -6,12 +6,14 @@ const data_provider_1 = require("@skrr-ai/data-provider");
|
|
|
6
6
|
const base_command_1 = require("../../base-command");
|
|
7
7
|
const inbox_1 = require("../../lib/inbox");
|
|
8
8
|
const format_1 = require("../../lib/format");
|
|
9
|
+
const agentic_stream_1 = require("../../lib/agentic-stream");
|
|
9
10
|
/**
|
|
10
11
|
* `skrr inbox` / `skrr inbox --follow` — what have my agents said to me?
|
|
11
12
|
*
|
|
12
13
|
* Gap analysis §3.3 (b). The CLI's 50 command groups were entirely pull-shaped,
|
|
13
14
|
* with nothing that surfaced an agent-initiated message. The reply direction
|
|
14
|
-
* already closed the loop (`skrr agents chat --conversation <id
|
|
15
|
+
* already closed the loop (`skrr agents chat <agent-id> --conversation <id>
|
|
16
|
+
* --prompt "…"` stamps
|
|
15
17
|
* `Message.intentId` and wakes the originating run) — so the missing half was
|
|
16
18
|
* literally "tell me it happened", and its absence is what made use case 3's
|
|
17
19
|
* "the agent messages me a couple of times like a person" a terminal dead end.
|
|
@@ -77,19 +79,33 @@ class Inbox extends base_command_1.BaseCommand {
|
|
|
77
79
|
}
|
|
78
80
|
(0, format_1.renderTable)(selected.map((dm) => ({
|
|
79
81
|
agent: dm.agentId,
|
|
82
|
+
// The reply command below needs this, and the row has carried it all
|
|
83
|
+
// along — it was simply never rendered, so the command printed under
|
|
84
|
+
// the table could not be completed from the table. `verbatim` because a
|
|
85
|
+
// clipped id is not an id (OSK-7621).
|
|
86
|
+
conversation: dm.conversationId,
|
|
80
87
|
unread: String(dm.unreadCount),
|
|
81
88
|
when: dm.lastMessageAt ? dm.lastMessageAt.slice(0, 19) : '-',
|
|
82
89
|
preview: (dm.lastMessagePreview || '').replace(/\s+/g, ' ').trim(),
|
|
83
90
|
})), [
|
|
84
91
|
{ key: 'agent', header: 'AGENT', verbatim: true },
|
|
92
|
+
{ key: 'conversation', header: 'CONVERSATION', verbatim: true },
|
|
85
93
|
{ key: 'unread', header: 'UNREAD', maxWidth: 6 },
|
|
86
94
|
{ key: 'when', header: 'LAST', maxWidth: 20 },
|
|
87
|
-
{ key: 'preview', header: 'PREVIEW', maxWidth:
|
|
95
|
+
{ key: 'preview', header: 'PREVIEW', maxWidth: 48 },
|
|
88
96
|
], (line) => this.log(line));
|
|
89
97
|
const totalUnread = selected.reduce((sum, dm) => sum + dm.unreadCount, 0);
|
|
90
98
|
if (totalUnread > 0) {
|
|
99
|
+
// The reply command must be RUNNABLE (OSK-7585/7594/7597). `agents chat`
|
|
100
|
+
// takes the agent as a required positional and `--prompt` as a required
|
|
101
|
+
// flag, so the argument-less form this used to print here (and, at the
|
|
102
|
+
// time those findings were filed, on every detach) exits with
|
|
103
|
+
// "Missing 1 required arg". A command a reader copies and cannot run is
|
|
104
|
+
// worse than no command: it costs them a round trip to learn the surface
|
|
105
|
+
// does not work the way it was just told them it does.
|
|
91
106
|
this.log(`\n${totalUnread} unread. \`skrr inbox --follow\` to watch, ` +
|
|
92
|
-
'`skrr agents chat --conversation <id
|
|
107
|
+
'`skrr agents chat <agent-id> --conversation <id> --prompt "<your reply>"` to reply ' +
|
|
108
|
+
'(the AGENT and CONVERSATION columns above carry both ids).');
|
|
93
109
|
}
|
|
94
110
|
}
|
|
95
111
|
/** The terminal projection reads the same Notification rows as the web task inbox. */
|
|
@@ -192,7 +208,14 @@ class Inbox extends base_command_1.BaseCommand {
|
|
|
192
208
|
cursors.set(dm.conversationId, newest);
|
|
193
209
|
}
|
|
194
210
|
};
|
|
195
|
-
|
|
211
|
+
// Hoist a web apex to its `api.` realtime host, exactly as the run-stream
|
|
212
|
+
// sibling does. Using `baseURL` raw sends the upgrade to the apex, which is
|
|
213
|
+
// CloudFront-fronted: it cannot carry a WebSocket, and its WAF refuses a
|
|
214
|
+
// handshake that sends no `User-Agent` — which `ws` never does. Measured:
|
|
215
|
+
// an upgrade to `skrr.ai` answers `403 Request blocked`, the same request
|
|
216
|
+
// to `api.skrr.ai` answers `101`. Nothing errors at the call site; the
|
|
217
|
+
// socket simply never connects, which reads as a network problem.
|
|
218
|
+
const wsURL = (0, agentic_stream_1.toWebSocketOrigin)(this.cliConfig.baseURL);
|
|
196
219
|
const socket = (0, socket_io_client_1.io)(wsURL, {
|
|
197
220
|
path: '/ws/agentic',
|
|
198
221
|
auth: {
|
package/dist/commands/login.js
CHANGED
|
@@ -134,9 +134,12 @@ class Login extends base_command_1.BaseCommand {
|
|
|
134
134
|
// terminal through the daemon broker, which is the case that matters
|
|
135
135
|
// most on a headless box, and a confirmation would break it.
|
|
136
136
|
const profile = (0, keychain_1.getActiveProfile)();
|
|
137
|
+
const isolationGuidance = profile === 'default'
|
|
138
|
+
? 'Sign in with `--profile <name>` instead to keep both.'
|
|
139
|
+
: `Only the named "${profile}" profile changes; the default and all other profiles remain untouched.`;
|
|
137
140
|
this.warn(`Pointing profile "${profile}" at ${(0, config_1.describeDeployment)(nextBaseURL)}. ` +
|
|
138
141
|
`Its ${(0, config_1.describeDeployment)(previousBaseURL)} session will be replaced — ` +
|
|
139
|
-
|
|
142
|
+
isolationGuidance);
|
|
140
143
|
undoBaseURL = () => {
|
|
141
144
|
// Re-read rather than reusing `existing`: the flow may have persisted
|
|
142
145
|
// other fields (cliId, migration markers) before failing, and this
|
|
@@ -8,6 +8,7 @@ export default class MachinesList extends BaseCommand {
|
|
|
8
8
|
static examples: string[];
|
|
9
9
|
static flags: {
|
|
10
10
|
json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
11
|
+
all: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
11
12
|
};
|
|
12
13
|
run(): Promise<void>;
|
|
13
14
|
}
|
|
@@ -14,7 +14,19 @@ class MachinesList extends base_command_1.BaseCommand {
|
|
|
14
14
|
'<%= config.bin %> machines list',
|
|
15
15
|
'<%= config.bin %> machines list --json',
|
|
16
16
|
];
|
|
17
|
-
static flags = {
|
|
17
|
+
static flags = {
|
|
18
|
+
json: core_1.Flags.boolean({ description: 'Output as JSON' }),
|
|
19
|
+
// `harnesses list` already learned this: "Offline rows accumulate forever,
|
|
20
|
+
// so they are hidden by default." The same reasoning was never applied
|
|
21
|
+
// here, and this listing returned 252 rows for one account — every
|
|
22
|
+
// ephemeral sandbox ever provisioned, months back, all rendered `offline`,
|
|
23
|
+
// with the one live machine at the top and a wall of dead ones after it
|
|
24
|
+
// (OSK-7639). A list exists so someone can pick a row.
|
|
25
|
+
all: core_1.Flags.boolean({
|
|
26
|
+
description: 'Include machines that are offline or terminated. Off by default — dead sandboxes ' +
|
|
27
|
+
'accumulate forever and bury the ones you can use.',
|
|
28
|
+
}),
|
|
29
|
+
};
|
|
18
30
|
async run() {
|
|
19
31
|
this.requireAuth();
|
|
20
32
|
const { flags } = await this.parse(MachinesList);
|
|
@@ -33,10 +45,21 @@ class MachinesList extends base_command_1.BaseCommand {
|
|
|
33
45
|
this.log('No machines. Install a daemon with `skrr harnesses install-token`.');
|
|
34
46
|
return;
|
|
35
47
|
}
|
|
36
|
-
|
|
37
|
-
|
|
48
|
+
const all = machines;
|
|
49
|
+
const shown = flags.all ? all : all.filter((m) => (0, machines_1.isReachableMachine)(m));
|
|
50
|
+
if (shown.length === 0) {
|
|
51
|
+
this.log(`No machine is reachable right now. ${all.length} offline/terminated — see them with --all.`);
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
(0, format_1.renderTable)(shown.map((m) => ({
|
|
55
|
+
// Printed in full. A hard 20-character slice with no ellipsis made
|
|
56
|
+
// `machine:03548116-d36` read like a complete id and it is not — and
|
|
57
|
+
// two different hosted machines rendered as byte-identical rows,
|
|
58
|
+
// so the one column a list exists to be picked from could not
|
|
59
|
+
// distinguish them (OSK-7621).
|
|
60
|
+
id: (0, format_1.formatCell)(m.id),
|
|
38
61
|
name: (0, format_1.formatCell)(m.preferences?.name || m.name),
|
|
39
|
-
status: (0, format_1.formatCell)(
|
|
62
|
+
status: (0, format_1.formatCell)((0, machines_1.machineStateLabel)(m)),
|
|
40
63
|
// Both numbers matter: "2/7" is a machine that is up with most of its
|
|
41
64
|
// harnesses signed out, which reads nothing like "7/7". The
|
|
42
65
|
// denominator counts LIVE rows, matching the population
|
|
@@ -48,13 +71,18 @@ class MachinesList extends base_command_1.BaseCommand {
|
|
|
48
71
|
? new Date(m.lastSeenAt).toISOString().slice(0, 16).replace('T', ' ')
|
|
49
72
|
: '-',
|
|
50
73
|
})), [
|
|
51
|
-
{ key: 'id', header: 'ID' },
|
|
74
|
+
{ key: 'id', header: 'ID', verbatim: true },
|
|
52
75
|
{ key: 'name', header: 'NAME', maxWidth: 28 },
|
|
53
76
|
{ key: 'status', header: 'STATUS' },
|
|
54
77
|
{ key: 'harnesses', header: 'ONLINE' },
|
|
55
78
|
{ key: 'platform', header: 'PLATFORM' },
|
|
56
79
|
{ key: 'seen', header: 'LAST SEEN' },
|
|
57
80
|
], (line) => this.log(line));
|
|
81
|
+
const hidden = all.length - shown.length;
|
|
82
|
+
if (hidden > 0) {
|
|
83
|
+
this.log('');
|
|
84
|
+
this.log(`${hidden} offline or terminated machine(s) hidden — pass --all to include them.`);
|
|
85
|
+
}
|
|
58
86
|
}
|
|
59
87
|
}
|
|
60
88
|
exports.default = MachinesList;
|