@skrr-ai/cli 0.1.40 → 0.1.41
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/base-command.d.ts +9 -0
- package/dist/base-command.js +18 -3
- package/dist/commands/agent-shares/list-for.js +4 -11
- package/dist/commands/agent-shares/received.js +4 -11
- package/dist/commands/agent-shares/sent.js +4 -11
- package/dist/commands/agent-shares/with.js +3 -10
- package/dist/commands/agents/activity.js +1 -1
- package/dist/commands/agents/api-actions/add.js +6 -0
- package/dist/commands/agents/chat.js +6 -1
- package/dist/commands/agents/create.js +6 -1
- package/dist/commands/agents/manager/ensure.d.ts +18 -0
- package/dist/commands/agents/manager/ensure.js +56 -0
- package/dist/commands/agents/show.js +4 -0
- package/dist/commands/agents/tools/auth.d.ts +6 -0
- package/dist/commands/agents/tools/auth.js +27 -1
- package/dist/commands/agents/tools/index.js +11 -1
- package/dist/commands/agents/update.js +6 -1
- package/dist/commands/code/install.d.ts +4 -2
- package/dist/commands/code/install.js +12 -10
- package/dist/commands/convos/list.js +1 -3
- package/dist/commands/convos/show.js +4 -11
- package/dist/commands/daemon/index.js +3 -3
- package/dist/commands/daemon/install.js +4 -4
- package/dist/commands/daemon/login.js +1 -1
- package/dist/commands/daemon/logs.d.ts +3 -1
- package/dist/commands/daemon/logs.js +16 -1
- package/dist/commands/daemon/start.js +3 -3
- package/dist/commands/daemon/status.d.ts +9 -0
- package/dist/commands/daemon/status.js +22 -0
- package/dist/commands/dm/messages.js +1 -11
- package/dist/commands/followups/cancel.js +1 -1
- package/dist/commands/followups/resolve.js +1 -1
- package/dist/commands/followups/show.js +16 -0
- package/dist/commands/harnesses/forget.js +20 -3
- package/dist/commands/harnesses/install.js +18 -6
- package/dist/commands/harnesses/installers.d.ts +1 -1
- package/dist/commands/harnesses/installers.js +36 -12
- package/dist/commands/harnesses/list.d.ts +74 -2
- package/dist/commands/harnesses/list.js +231 -15
- package/dist/commands/harnesses/ping.d.ts +2 -0
- package/dist/commands/harnesses/ping.js +21 -0
- package/dist/commands/harnesses/show.d.ts +22 -0
- package/dist/commands/harnesses/show.js +116 -17
- package/dist/commands/harnesses/update.d.ts +8 -0
- package/dist/commands/harnesses/update.js +25 -1
- package/dist/commands/harnesses/usage.d.ts +2 -0
- package/dist/commands/harnesses/usage.js +7 -2
- package/dist/commands/instructions/status.js +13 -0
- package/dist/commands/instructions/update-target.d.ts +1 -0
- package/dist/commands/instructions/update-target.js +11 -3
- package/dist/commands/login.js +5 -5
- package/dist/commands/machines/list.js +8 -9
- package/dist/commands/machines/show.js +46 -17
- package/dist/commands/messages/show.js +3 -10
- package/dist/commands/shares/get.js +2 -9
- package/dist/commands/shares/list.js +1 -9
- package/dist/commands/shortcuts/show.js +4 -11
- package/dist/commands/skills/local.js +6 -0
- package/dist/commands/spaces/actions/run.js +3 -4
- package/dist/commands/spaces/briefs/get.js +2 -9
- package/dist/commands/spaces/briefs/list.js +1 -9
- package/dist/commands/spaces/conversations.js +1 -9
- package/dist/commands/spaces/heartbeats/list.js +1 -9
- package/dist/commands/spaces/heartbeats/status.js +2 -9
- package/dist/commands/tasks/activity.js +1 -10
- package/dist/commands/tasks/approvals/list.js +1 -9
- package/dist/commands/tasks/attachments/list.js +1 -9
- package/dist/commands/tasks/comments/list.js +1 -9
- package/dist/commands/tasks/dri-status.js +2 -9
- package/dist/commands/tasks/events/append.js +9 -7
- package/dist/commands/tasks/execution-timeline.js +1 -9
- package/dist/commands/tasks/monitor.js +1 -9
- package/dist/commands/tasks/result/submit.js +9 -0
- package/dist/commands/tasks/runs.js +1 -9
- package/dist/commands/tasks/show.js +5 -12
- package/dist/commands/token/list.d.ts +8 -0
- package/dist/commands/token/list.js +51 -6
- package/dist/help.js +8 -12
- package/dist/lib/agent-home-workspace.d.ts +19 -0
- package/dist/lib/agent-home-workspace.js +39 -0
- package/dist/lib/agent-resolver.js +2 -2
- package/dist/lib/agentic-stream.d.ts +22 -1
- package/dist/lib/agentic-stream.js +48 -7
- package/dist/lib/cli-installers.d.ts +84 -2
- package/dist/lib/cli-installers.js +146 -13
- package/dist/lib/command-miss.d.ts +22 -0
- package/dist/lib/command-miss.js +78 -0
- package/dist/lib/daemon-setup.js +2 -2
- package/dist/lib/daemon-target.d.ts +14 -0
- package/dist/lib/daemon-target.js +32 -0
- package/dist/lib/daemonBroker.js +1 -1
- package/dist/lib/daemonHandoff.js +1 -1
- package/dist/lib/exec-runtime-binary.js +2 -2
- package/dist/lib/followups.d.ts +10 -0
- package/dist/lib/followups.js +14 -1
- package/dist/lib/format.d.ts +11 -0
- package/dist/lib/format.js +21 -0
- package/dist/lib/harness-labels.d.ts +39 -0
- package/dist/lib/harness-labels.js +60 -0
- package/dist/lib/harnesses.d.ts +6 -0
- package/dist/lib/instruction-input.d.ts +13 -0
- package/dist/lib/instruction-input.js +20 -1
- package/dist/lib/local-skills.d.ts +17 -1
- package/dist/lib/local-skills.js +20 -2
- package/dist/lib/login.js +5 -5
- package/dist/lib/machines.d.ts +6 -0
- package/dist/lib/machines.js +68 -2
- package/dist/lib/runtime-tool-support.d.ts +34 -0
- package/dist/lib/runtime-tool-support.js +77 -0
- package/dist/lib/share-rows.d.ts +17 -0
- package/dist/lib/share-rows.js +35 -0
- package/dist/node_modules/@skrr-ai/data-provider/index.js +5029 -5007
- package/oclif.manifest.json +2689 -2584
- package/package.json +6 -3
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { BaseCommand } from '../../base-command';
|
|
2
|
+
import { getHarness } from '../../lib/harnesses';
|
|
2
3
|
/**
|
|
3
4
|
* Rename an harness, or change how Claude Code runs on it.
|
|
4
5
|
*
|
|
@@ -23,3 +24,10 @@ export default class HarnessesUpdate extends BaseCommand {
|
|
|
23
24
|
};
|
|
24
25
|
run(): Promise<void>;
|
|
25
26
|
}
|
|
27
|
+
/**
|
|
28
|
+
* `--name` sets the name everyone sees. When YOUR alias covers it, you will not
|
|
29
|
+
* see the new name anywhere you look, and "Updated <name>." read as though the
|
|
30
|
+
* rename had not happened (OSK-10004). Best-effort: a failed re-read keeps the
|
|
31
|
+
* plain receipt rather than failing a write that succeeded.
|
|
32
|
+
*/
|
|
33
|
+
export declare function sharedRenameMessage(harnessId: string, name: string, read?: typeof getHarness): Promise<string>;
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.sharedRenameMessage = sharedRenameMessage;
|
|
3
4
|
const core_1 = require("@oclif/core");
|
|
4
5
|
const base_command_1 = require("../../base-command");
|
|
5
6
|
const harnesses_1 = require("../../lib/harnesses");
|
|
7
|
+
const harness_labels_1 = require("../../lib/harness-labels");
|
|
6
8
|
/**
|
|
7
9
|
* Rename an harness, or change how Claude Code runs on it.
|
|
8
10
|
*
|
|
@@ -53,7 +55,9 @@ class HarnessesUpdate extends base_command_1.BaseCommand {
|
|
|
53
55
|
this.log(JSON.stringify(response, null, 2));
|
|
54
56
|
return;
|
|
55
57
|
}
|
|
56
|
-
this.log(
|
|
58
|
+
this.log(flags.name === undefined
|
|
59
|
+
? `Updated ${response?.harness?.name || args.harness}.`
|
|
60
|
+
: await sharedRenameMessage(args.harness, flags.name));
|
|
57
61
|
}
|
|
58
62
|
catch (err) {
|
|
59
63
|
this.handleApiError(err);
|
|
@@ -61,3 +65,23 @@ class HarnessesUpdate extends base_command_1.BaseCommand {
|
|
|
61
65
|
}
|
|
62
66
|
}
|
|
63
67
|
exports.default = HarnessesUpdate;
|
|
68
|
+
/**
|
|
69
|
+
* `--name` sets the name everyone sees. When YOUR alias covers it, you will not
|
|
70
|
+
* see the new name anywhere you look, and "Updated <name>." read as though the
|
|
71
|
+
* rename had not happened (OSK-10004). Best-effort: a failed re-read keeps the
|
|
72
|
+
* plain receipt rather than failing a write that succeeded.
|
|
73
|
+
*/
|
|
74
|
+
async function sharedRenameMessage(harnessId, name, read = harnesses_1.getHarness) {
|
|
75
|
+
let row;
|
|
76
|
+
try {
|
|
77
|
+
row = (await read(harnessId))?.harness;
|
|
78
|
+
}
|
|
79
|
+
catch {
|
|
80
|
+
row = undefined;
|
|
81
|
+
}
|
|
82
|
+
if (row && (0, harness_labels_1.isAliasCoveringSharedName)(row)) {
|
|
83
|
+
return (`Updated the shared name to "${name}" — everyone this harness is shared with sees it.\n` +
|
|
84
|
+
`You still see your alias "${row.name}". \`skrr harnesses alias ${harnessId} --clear\` shows you the shared name too.`);
|
|
85
|
+
}
|
|
86
|
+
return `Updated ${name}.`;
|
|
87
|
+
}
|
|
@@ -17,6 +17,8 @@ export type UsageRow = {
|
|
|
17
17
|
inputTokens?: number;
|
|
18
18
|
outputTokens?: number;
|
|
19
19
|
cachedInputTokens?: number;
|
|
20
|
+
/** Prompt-cache writes; absent from usage recorded before OSK-10006. */
|
|
21
|
+
cacheCreationInputTokens?: number;
|
|
20
22
|
};
|
|
21
23
|
/**
|
|
22
24
|
* The rows to render, whichever spelling the server used.
|
|
@@ -42,7 +42,10 @@ function selectUsageRows(payload) {
|
|
|
42
42
|
/** The HARNESS cell, under either spelling of the id. */
|
|
43
43
|
function usageRowHarnessCell(row) {
|
|
44
44
|
const id = row.harnessId ?? row.runtimeId;
|
|
45
|
-
|
|
45
|
+
// The FULL id. Twelve characters looked tidy and named nothing: a daemon's
|
|
46
|
+
// rows share a long prefix, so `6a985ed278b7` matched six harnesses and no
|
|
47
|
+
// command took it back (OSK-10007).
|
|
48
|
+
return id ? String(id) : '-';
|
|
46
49
|
}
|
|
47
50
|
const SHARED_COLUMNS = [
|
|
48
51
|
{ key: 'provider', header: 'PROVIDER' },
|
|
@@ -51,6 +54,7 @@ const SHARED_COLUMNS = [
|
|
|
51
54
|
{ key: 'in', header: 'INPUT' },
|
|
52
55
|
{ key: 'out', header: 'OUTPUT' },
|
|
53
56
|
{ key: 'cached', header: 'CACHED' },
|
|
57
|
+
{ key: 'cacheWrite', header: 'CACHE WRITE' },
|
|
54
58
|
];
|
|
55
59
|
/**
|
|
56
60
|
* The rows differ as much as the two envelopes do.
|
|
@@ -73,6 +77,7 @@ function buildUsageTable(rows, perHarness) {
|
|
|
73
77
|
in: count(r.inputTokens),
|
|
74
78
|
out: count(r.outputTokens),
|
|
75
79
|
cached: count(r.cachedInputTokens),
|
|
80
|
+
cacheWrite: count(r.cacheCreationInputTokens),
|
|
76
81
|
});
|
|
77
82
|
if (perHarness) {
|
|
78
83
|
const buckets = [...rows].sort((a, b) => String(a.bucketHour ?? '') < String(b.bucketHour ?? '') ? 1 : -1);
|
|
@@ -143,7 +148,7 @@ class HarnessesUsage extends base_command_1.BaseCommand {
|
|
|
143
148
|
this.log('');
|
|
144
149
|
this.log(`Total: ${count(totals.sessions)} sessions · ${usd(totals.totalCostUsd)} · ` +
|
|
145
150
|
`${count(totals.inputTokens)} in / ${count(totals.outputTokens)} out / ` +
|
|
146
|
-
`${count(totals.cachedInputTokens)} cached`);
|
|
151
|
+
`${count(totals.cachedInputTokens)} cached / ${count(totals.cacheCreationInputTokens)} cache write`);
|
|
147
152
|
// SAY WHICH PROVIDERS THAT TOTAL COVERS.
|
|
148
153
|
//
|
|
149
154
|
// It was presented as the account total and is not: the ingestion path is
|
|
@@ -93,6 +93,19 @@ class InstructionsStatus extends base_command_1.BaseCommand {
|
|
|
93
93
|
// the sentence.
|
|
94
94
|
{ key: 'status', header: 'STATUS', maxWidth: 78 },
|
|
95
95
|
], (line) => this.log(line));
|
|
96
|
+
// The re-bind commands the STATUS column points at. Only for a target whose
|
|
97
|
+
// daemon is not live while another daemon on the SAME machine is: that is
|
|
98
|
+
// the case a re-install could never fix (OSK-9961).
|
|
99
|
+
const rebinds = response.targets
|
|
100
|
+
.filter((target) => target.desiredState === 'installed' && target.status === 'pending')
|
|
101
|
+
.map((target) => (0, instruction_input_1.rebindCommandFor)(target, liveDaemonIds))
|
|
102
|
+
.filter((command) => Boolean(command));
|
|
103
|
+
if (rebinds.length > 0) {
|
|
104
|
+
this.log('');
|
|
105
|
+
this.log('Re-bind these targets to the daemon now running on their machine:');
|
|
106
|
+
for (const command of rebinds)
|
|
107
|
+
this.log(` ${command}`);
|
|
108
|
+
}
|
|
96
109
|
// Where the text went.
|
|
97
110
|
//
|
|
98
111
|
// The count in the STATUS column says skrr overwrote something you
|
|
@@ -9,6 +9,7 @@ export default class InstructionsUpdateTarget extends BaseCommand {
|
|
|
9
9
|
tracking: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
10
10
|
pin: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
11
11
|
label: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
12
|
+
daemon: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
12
13
|
json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
13
14
|
};
|
|
14
15
|
run(): Promise<void>;
|
|
@@ -4,7 +4,7 @@ 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
6
|
class InstructionsUpdateTarget extends base_command_1.BaseCommand {
|
|
7
|
-
static description = 'Update a target prompt
|
|
7
|
+
static description = 'Update a target prompt, version policy, label, or the daemon on its machine that syncs it';
|
|
8
8
|
static args = {
|
|
9
9
|
target: core_1.Args.string({ description: 'Target ID', required: true, ignoreStdin: true }),
|
|
10
10
|
};
|
|
@@ -13,13 +13,20 @@ class InstructionsUpdateTarget extends base_command_1.BaseCommand {
|
|
|
13
13
|
tracking: core_1.Flags.string({ description: 'Version policy', options: ['latest', 'pinned'] }),
|
|
14
14
|
pin: core_1.Flags.string({ description: 'Pinned version ID (implies pinned tracking)' }),
|
|
15
15
|
label: core_1.Flags.string({ description: 'New target label' }),
|
|
16
|
+
daemon: core_1.Flags.string({
|
|
17
|
+
description: 'Re-bind the target to this daemon. It must run on the same machine: a target stays with its file.',
|
|
18
|
+
}),
|
|
16
19
|
json: core_1.Flags.boolean({ description: 'Output as JSON' }),
|
|
17
20
|
};
|
|
18
21
|
async run() {
|
|
19
22
|
this.requireAuth();
|
|
20
23
|
const { args, flags } = await this.parse(InstructionsUpdateTarget);
|
|
21
|
-
if (!flags.bundle &&
|
|
22
|
-
|
|
24
|
+
if (!flags.bundle &&
|
|
25
|
+
!flags.tracking &&
|
|
26
|
+
!flags.pin &&
|
|
27
|
+
flags.label === undefined &&
|
|
28
|
+
!flags.daemon) {
|
|
29
|
+
this.error('Provide --bundle, --tracking, --pin, --label, or --daemon', { exit: 2 });
|
|
23
30
|
}
|
|
24
31
|
const trackingMode = (flags.pin ? 'pinned' : flags.tracking);
|
|
25
32
|
let response;
|
|
@@ -29,6 +36,7 @@ class InstructionsUpdateTarget extends base_command_1.BaseCommand {
|
|
|
29
36
|
trackingMode,
|
|
30
37
|
pinnedVersionId: flags.pin,
|
|
31
38
|
label: flags.label,
|
|
39
|
+
daemonId: flags.daemon,
|
|
32
40
|
});
|
|
33
41
|
}
|
|
34
42
|
catch (error) {
|
package/dist/commands/login.js
CHANGED
|
@@ -40,8 +40,8 @@ const auth_storage_1 = require("../lib/auth-storage");
|
|
|
40
40
|
*/
|
|
41
41
|
class Login extends base_command_1.BaseCommand {
|
|
42
42
|
static description = 'Sign in to a skrr instance (PKCE localhost callback; device-code fallback). ' +
|
|
43
|
-
'On an interactive first login
|
|
44
|
-
'
|
|
43
|
+
'On an interactive first login on a computer without the skrr background service, skrr ' +
|
|
44
|
+
'offers to install it. Choose no, or set SKRR_SKIP_DAEMON_HANDOFF=1 before running this ' +
|
|
45
45
|
'command, to skip that optional setup.';
|
|
46
46
|
static examples = [
|
|
47
47
|
'<%= config.bin %> login',
|
|
@@ -56,7 +56,7 @@ class Login extends base_command_1.BaseCommand {
|
|
|
56
56
|
static flags = {
|
|
57
57
|
env: core_1.Flags.string({
|
|
58
58
|
description: 'Deployment to sign in to. Shorthand for the matching --base-url, and the same ' +
|
|
59
|
-
'environment names the
|
|
59
|
+
'environment names `skrrd`, the background service, accepts.',
|
|
60
60
|
options: Object.keys(config_1.ENVIRONMENT_BASE_URLS),
|
|
61
61
|
}),
|
|
62
62
|
'base-url': core_1.Flags.string({
|
|
@@ -64,7 +64,7 @@ class Login extends base_command_1.BaseCommand {
|
|
|
64
64
|
description: 'API base URL to save and use (e.g. https://skrr.ai)',
|
|
65
65
|
}),
|
|
66
66
|
server: core_1.Flags.string({
|
|
67
|
-
description: 'Alias for --base-url, matching the
|
|
67
|
+
description: 'Alias for --base-url, matching `skrrd`, the background service.',
|
|
68
68
|
}),
|
|
69
69
|
'device-code': core_1.Flags.boolean({
|
|
70
70
|
description: 'Force the device-code flow (skip the PKCE localhost callback).',
|
|
@@ -206,7 +206,7 @@ class Login extends base_command_1.BaseCommand {
|
|
|
206
206
|
handoff = await (0, daemonHandoff_1.handOffToLocalDaemon)(process.env, { loginFlow: result.flow });
|
|
207
207
|
}
|
|
208
208
|
else if (setup.status === 'failed') {
|
|
209
|
-
this.log(`Could not set up the
|
|
209
|
+
this.log(`Could not set up the background service: ${setup.detail}.`);
|
|
210
210
|
}
|
|
211
211
|
else {
|
|
212
212
|
this.log(`This machine is not set up — ${setup.detail}.`);
|
|
@@ -23,7 +23,7 @@ class MachinesList extends base_command_1.BaseCommand {
|
|
|
23
23
|
// with the one live machine at the top and a wall of dead ones after it
|
|
24
24
|
// (OSK-7639). A list exists so someone can pick a row.
|
|
25
25
|
all: core_1.Flags.boolean({
|
|
26
|
-
description: 'Include machines that are offline or terminated. Off by default — dead sandboxes ' +
|
|
26
|
+
description: 'Include machines that are offline, paused, stopped or terminated. Off by default — dead sandboxes ' +
|
|
27
27
|
'accumulate forever and bury the ones you can use.',
|
|
28
28
|
}),
|
|
29
29
|
};
|
|
@@ -48,7 +48,7 @@ class MachinesList extends base_command_1.BaseCommand {
|
|
|
48
48
|
const all = machines;
|
|
49
49
|
const shown = flags.all ? all : all.filter((m) => (0, machines_1.isReachableMachine)(m));
|
|
50
50
|
if (shown.length === 0) {
|
|
51
|
-
this.log(`No machine is reachable right now
|
|
51
|
+
this.log(`No machine is reachable right now (${(0, machines_1.hiddenMachinesSummary)(all)}) — see them with --all.`);
|
|
52
52
|
return;
|
|
53
53
|
}
|
|
54
54
|
(0, format_1.renderTable)(shown.map((m) => ({
|
|
@@ -67,16 +67,15 @@ class MachinesList extends base_command_1.BaseCommand {
|
|
|
67
67
|
// printed "7/23" beside a status of `online`.
|
|
68
68
|
harnesses: `${m.onlineHarnessCount}/${(0, machines_1.liveHarnessCount)(m)}`,
|
|
69
69
|
platform: m.platform ? `${m.platform}${m.arch ? `/${m.arch}` : ''}` : '-',
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
: '-',
|
|
70
|
+
// Local time with the zone in the header, as `harnesses list` prints it (OSK-10005).
|
|
71
|
+
seen: (0, format_1.localStamp)(m.lastSeenAt),
|
|
73
72
|
})), [
|
|
74
73
|
{ key: 'id', header: 'ID', verbatim: true },
|
|
75
74
|
{ key: 'name', header: 'NAME', maxWidth: 28 },
|
|
76
75
|
{ key: 'status', header: 'STATUS' },
|
|
77
76
|
{ key: 'harnesses', header: 'ONLINE' },
|
|
78
77
|
{ key: 'platform', header: 'PLATFORM' },
|
|
79
|
-
{ key: 'seen', header:
|
|
78
|
+
{ key: 'seen', header: `LAST SEEN (${(0, format_1.localZone)()})` },
|
|
80
79
|
], (line) => this.log(line));
|
|
81
80
|
// Why a machine is not `online`, under the table. `degraded` on its own is
|
|
82
81
|
// unactionable — the dogfood note on this output was "I still do not know
|
|
@@ -89,10 +88,10 @@ class MachinesList extends base_command_1.BaseCommand {
|
|
|
89
88
|
this.log(` ${m.preferences?.name || m.name}: ${m.statusReason}`);
|
|
90
89
|
}
|
|
91
90
|
}
|
|
92
|
-
|
|
93
|
-
|
|
91
|
+
if (shown.length < all.length) {
|
|
92
|
+
const hidden = all.filter((m) => !shown.includes(m));
|
|
94
93
|
this.log('');
|
|
95
|
-
this.log(`${hidden}
|
|
94
|
+
this.log(`${hidden.length} machine(s) hidden (${(0, machines_1.hiddenMachinesSummary)(hidden)}) — pass --all to include them.`);
|
|
96
95
|
}
|
|
97
96
|
}
|
|
98
97
|
}
|
|
@@ -4,6 +4,8 @@ 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 machines_1 = require("../../lib/machines");
|
|
7
|
+
const cli_installers_1 = require("../../lib/cli-installers");
|
|
8
|
+
const harness_labels_1 = require("../../lib/harness-labels");
|
|
7
9
|
/** One machine: its identity, its harnesses, and what you may do to it. */
|
|
8
10
|
class MachinesShow extends base_command_1.BaseCommand {
|
|
9
11
|
static description = 'Show one machine — its identity, harnesses, and available actions';
|
|
@@ -49,7 +51,10 @@ class MachinesShow extends base_command_1.BaseCommand {
|
|
|
49
51
|
this.log(`${machine.preferences?.name || machine.name}`);
|
|
50
52
|
this.log(` id ${machine.id}`);
|
|
51
53
|
this.log(` identity ${machine.identityKind}`);
|
|
52
|
-
|
|
54
|
+
// The label the lists print. A paused lease read `paused` in both tables and
|
|
55
|
+
// `offline` here, with the reason one line below (OSK-9996). `--json` keeps
|
|
56
|
+
// the server's `status`; the lease state rides beside it.
|
|
57
|
+
this.log(` status ${(0, machines_1.machineStateLabel)(machine)}`);
|
|
53
58
|
// The status alone does not say what to do. Naming the rows that decided it
|
|
54
59
|
// is the actionable half — bring that provider back, or forget the row.
|
|
55
60
|
if (machine.statusReason)
|
|
@@ -61,7 +66,11 @@ class MachinesShow extends base_command_1.BaseCommand {
|
|
|
61
66
|
if (machine.platform) {
|
|
62
67
|
this.log(` platform ${machine.platform}${machine.arch ? `/${machine.arch}` : ''}`);
|
|
63
68
|
}
|
|
64
|
-
|
|
69
|
+
// Local time, zone named — the same clock `harnesses list` prints. This line
|
|
70
|
+
// printed a raw UTC ISO string while the harness table below printed UTC
|
|
71
|
+
// with no marker, so one row read 15:26 in `harnesses list` and 22:26 here
|
|
72
|
+
// (OSK-10005).
|
|
73
|
+
this.log(` last seen ${machine.lastSeenAt ? `${(0, format_1.localStamp)(machine.lastSeenAt)} ${(0, format_1.localZone)()}` : '-'}`);
|
|
65
74
|
if (machine.preferences?.description) {
|
|
66
75
|
this.log(` description ${machine.preferences.description}`);
|
|
67
76
|
}
|
|
@@ -78,6 +87,28 @@ class MachinesShow extends base_command_1.BaseCommand {
|
|
|
78
87
|
// header whose count read like a summary of rows it then printed anyway
|
|
79
88
|
// (OSK-9389). `--all` shows them, and `--json` always carries every row.
|
|
80
89
|
const shown = flags.all ? harnesses : harnesses.filter((h) => !h.superseded);
|
|
90
|
+
// The daemon's own standing with skrr is ONE fact about the machine, not a
|
|
91
|
+
// per-provider one: it is written across every row of a daemon at once. It
|
|
92
|
+
// sat in a per-row column and answered `ok` for a Devin its CLI called
|
|
93
|
+
// "Not logged in" (OSK-9265), so it is printed once, here.
|
|
94
|
+
const daemonSignIn = harnesses.find((h) => !h.superseded && h.authStatus)?.authStatus;
|
|
95
|
+
if (daemonSignIn)
|
|
96
|
+
this.log(` daemon auth ${daemonSignIn} (the daemon's sign-in to skrr)`);
|
|
97
|
+
// Per-provider readiness — installed, too old, signed in — asked of the
|
|
98
|
+
// daemon itself, so only while it is connected. Best-effort: a daemon that
|
|
99
|
+
// cannot answer leaves the column out rather than failing the command.
|
|
100
|
+
// Keyed by DAEMON as well as provider: one machine can run several daemons
|
|
101
|
+
// (profiles), and each answers only for itself.
|
|
102
|
+
// The same read `harnesses list` makes (readinessForRows): one per daemon,
|
|
103
|
+
// in parallel and bounded.
|
|
104
|
+
const daemonIds = [
|
|
105
|
+
...new Set(shown
|
|
106
|
+
.filter((h) => h.status === 'online' && !h.superseded && h.daemonId)
|
|
107
|
+
.map((h) => h.daemonId)),
|
|
108
|
+
];
|
|
109
|
+
const rowReadiness = await (0, cli_installers_1.readinessForRows)(shown, this.resolvedCredential);
|
|
110
|
+
const readinessFor = rowReadiness.lookup;
|
|
111
|
+
const readiness = rowReadiness.answered > 0 ? rowReadiness : null;
|
|
81
112
|
this.log('');
|
|
82
113
|
this.log(`Harnesses (${machine.onlineHarnessCount}/${live} online` +
|
|
83
114
|
(flags.all && superseded > 0 ? `, ${superseded} superseded by newer registrations` : '') +
|
|
@@ -85,36 +116,34 @@ class MachinesShow extends base_command_1.BaseCommand {
|
|
|
85
116
|
if (shown.length > 0) {
|
|
86
117
|
(0, format_1.renderTable)(shown.map((h) => ({
|
|
87
118
|
id: (0, format_1.formatCell)(h.id),
|
|
88
|
-
|
|
119
|
+
// Canonical, and `none` for a no-engine placeholder — the stored
|
|
120
|
+
// `oversky` printed here after the harnesses list stopped (OSK-9649).
|
|
121
|
+
provider: (0, harness_labels_1.harnessProviderLabel)(h.provider),
|
|
89
122
|
// Liveness only. Whether a newer registration replaced the row is a
|
|
90
123
|
// different fact — a superseded row can have been online — so it
|
|
91
124
|
// gets its own column rather than overwriting this one.
|
|
92
125
|
status: (0, format_1.formatCell)(h.status),
|
|
93
126
|
registration: h.superseded ? 'superseded' : 'current',
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
// of a daemon at once (`HarnessService.markAuthOkAfterRegister` does
|
|
97
|
-
// one `updateMany({owner, daemonId})`), so it is structurally the
|
|
98
|
-
// same value for all of them and can never answer "is this harness
|
|
99
|
-
// signed in". Under a bare `AUTH` header it read as the second
|
|
100
|
-
// question and answered `ok` for a Devin whose own CLI said
|
|
101
|
-
// "Not logged in." The header now names what the value is.
|
|
102
|
-
auth: (0, format_1.formatCell)(h.authStatus),
|
|
103
|
-
seen: h.lastSeenAt
|
|
104
|
-
? new Date(h.lastSeenAt).toISOString().slice(0, 16).replace('T', ' ')
|
|
105
|
-
: '-',
|
|
127
|
+
readiness: readinessFor(h)?.label ?? '-',
|
|
128
|
+
seen: (0, format_1.localStamp)(h.lastSeenAt),
|
|
106
129
|
})), [
|
|
107
130
|
{ key: 'id', header: 'HARNESS ID' },
|
|
108
131
|
{ key: 'provider', header: 'PROVIDER' },
|
|
109
132
|
{ key: 'status', header: 'STATUS' },
|
|
110
133
|
...(flags.all ? [{ key: 'registration', header: 'REGISTRATION' }] : []),
|
|
111
|
-
{ key: '
|
|
112
|
-
{ key: 'seen', header:
|
|
134
|
+
...(readiness ? [{ key: 'readiness', header: 'READINESS' }] : []),
|
|
135
|
+
{ key: 'seen', header: `LAST SEEN (${(0, format_1.localZone)()})` },
|
|
113
136
|
], (line) => this.log(` ${line}`));
|
|
114
137
|
}
|
|
115
138
|
if (!flags.all && superseded > 0) {
|
|
116
139
|
this.log(` ${superseded} superseded registration(s) hidden — pass --all to include them.`);
|
|
117
140
|
}
|
|
141
|
+
if (readiness && shown.some((h) => !readinessFor(h))) {
|
|
142
|
+
this.log(' READINESS "-": offline, or its daemon does not report credential state for that provider.');
|
|
143
|
+
}
|
|
144
|
+
if (!readiness && daemonIds.length > 0) {
|
|
145
|
+
this.log(` Readiness per provider: skrr harnesses installers --daemon ${daemonIds[0]}`);
|
|
146
|
+
}
|
|
118
147
|
// Print what is PERMITTED, not the whole control map: a list of six
|
|
119
148
|
// booleans mostly reading false is noise, and the useful question is
|
|
120
149
|
// "what can I do to this machine right now".
|
|
@@ -5,6 +5,7 @@ const core_1 = require("@oclif/core");
|
|
|
5
5
|
const data_provider_1 = require("@skrr-ai/data-provider");
|
|
6
6
|
const base_command_1 = require("../../base-command");
|
|
7
7
|
const message_provenance_1 = require("../../lib/message-provenance");
|
|
8
|
+
const format_1 = require("../../lib/format");
|
|
8
9
|
/** The detail endpoint preserves the legacy raw-array response while the list
|
|
9
10
|
* endpoint returns an envelope. Accept both so an ID emitted by messages list
|
|
10
11
|
* is always usable by messages show. */
|
|
@@ -59,9 +60,9 @@ class MessagesShow extends base_command_1.BaseCommand {
|
|
|
59
60
|
this.log(`Model: ${msg.model ?? '-'}`);
|
|
60
61
|
this.log(`Endpoint: ${msg.endpoint ?? '-'}`);
|
|
61
62
|
if (msg.createdAt)
|
|
62
|
-
this.log(`Created: ${
|
|
63
|
+
this.log(`Created: ${(0, format_1.localTime)(msg.createdAt)}`);
|
|
63
64
|
if (msg.updatedAt)
|
|
64
|
-
this.log(`Updated: ${
|
|
65
|
+
this.log(`Updated: ${(0, format_1.localTime)(msg.updatedAt)}`);
|
|
65
66
|
if (msg.tokenCount !== undefined)
|
|
66
67
|
this.log(`Tokens: ${msg.tokenCount}`);
|
|
67
68
|
// OSK-7682 — an unattended run persists no user message, so this row is the
|
|
@@ -79,11 +80,3 @@ class MessagesShow extends base_command_1.BaseCommand {
|
|
|
79
80
|
}
|
|
80
81
|
}
|
|
81
82
|
exports.default = MessagesShow;
|
|
82
|
-
function formatTime(value) {
|
|
83
|
-
try {
|
|
84
|
-
return new Date(String(value)).toISOString().slice(0, 19).replace('T', ' ');
|
|
85
|
-
}
|
|
86
|
-
catch {
|
|
87
|
-
return String(value);
|
|
88
|
-
}
|
|
89
|
-
}
|
|
@@ -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 format_1 = require("../../lib/format");
|
|
6
7
|
class SharesGet extends base_command_1.BaseCommand {
|
|
7
8
|
static description = 'Show messages for a shared link by share ID';
|
|
8
9
|
static examples = [
|
|
@@ -37,7 +38,7 @@ class SharesGet extends base_command_1.BaseCommand {
|
|
|
37
38
|
this.log(`Public: ${r.isPublic === true ? 'yes' : 'no'}`);
|
|
38
39
|
this.log(`Message count: ${messages.length}`);
|
|
39
40
|
if (r.createdAt)
|
|
40
|
-
this.log(`Created: ${
|
|
41
|
+
this.log(`Created: ${(0, format_1.localTime)(r.createdAt)}`);
|
|
41
42
|
if (messages.length > 0) {
|
|
42
43
|
this.log('');
|
|
43
44
|
messages.forEach((msg, i) => {
|
|
@@ -49,14 +50,6 @@ class SharesGet extends base_command_1.BaseCommand {
|
|
|
49
50
|
}
|
|
50
51
|
}
|
|
51
52
|
exports.default = SharesGet;
|
|
52
|
-
function formatTime(value) {
|
|
53
|
-
try {
|
|
54
|
-
return new Date(String(value)).toISOString().slice(0, 19).replace('T', ' ');
|
|
55
|
-
}
|
|
56
|
-
catch {
|
|
57
|
-
return String(value);
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
53
|
function truncateText(s, max) {
|
|
61
54
|
if (s.length <= max)
|
|
62
55
|
return s;
|
|
@@ -58,7 +58,7 @@ class SharesList extends base_command_1.BaseCommand {
|
|
|
58
58
|
conversationId: String(link.conversationId ?? '-'),
|
|
59
59
|
title: String(link.title ?? '-'),
|
|
60
60
|
isPublic: link.isPublic ? 'yes' : 'no',
|
|
61
|
-
createdAt:
|
|
61
|
+
createdAt: (0, format_1.localTime)(link.createdAt),
|
|
62
62
|
}));
|
|
63
63
|
(0, format_1.renderTable)(rows, [
|
|
64
64
|
{ key: 'shareId', header: 'SHARE ID' },
|
|
@@ -74,11 +74,3 @@ class SharesList extends base_command_1.BaseCommand {
|
|
|
74
74
|
}
|
|
75
75
|
}
|
|
76
76
|
exports.default = SharesList;
|
|
77
|
-
function formatTime(value) {
|
|
78
|
-
try {
|
|
79
|
-
return new Date(String(value)).toISOString().slice(0, 19).replace('T', ' ');
|
|
80
|
-
}
|
|
81
|
-
catch {
|
|
82
|
-
return String(value);
|
|
83
|
-
}
|
|
84
|
-
}
|
|
@@ -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 format_1 = require("../../lib/format");
|
|
6
7
|
class ShortcutsShow extends base_command_1.BaseCommand {
|
|
7
8
|
static description = 'Show details for a single shortcut';
|
|
8
9
|
static examples = [
|
|
@@ -43,13 +44,13 @@ class ShortcutsShow extends base_command_1.BaseCommand {
|
|
|
43
44
|
this.log(`Order: ${s.order ?? 0}`);
|
|
44
45
|
this.log(`Triggers: ${s.triggerCount ?? 0}`);
|
|
45
46
|
if (s.lastTriggeredAt)
|
|
46
|
-
this.log(`Last fired: ${
|
|
47
|
+
this.log(`Last fired: ${(0, format_1.localTime)(s.lastTriggeredAt)}`);
|
|
47
48
|
this.log(`Author: ${s.author ?? '-'}`);
|
|
48
49
|
this.log(`Assignees: ${agents.length} agent(s)${agents.length > 0 ? ` — ${agents.join(', ')}` : ''}`);
|
|
49
50
|
if (s.createdAt)
|
|
50
|
-
this.log(`Created: ${
|
|
51
|
+
this.log(`Created: ${(0, format_1.localTime)(s.createdAt)}`);
|
|
51
52
|
if (s.updatedAt)
|
|
52
|
-
this.log(`Updated: ${
|
|
53
|
+
this.log(`Updated: ${(0, format_1.localTime)(s.updatedAt)}`);
|
|
53
54
|
if (s.description) {
|
|
54
55
|
this.log('');
|
|
55
56
|
this.log('Description:');
|
|
@@ -69,11 +70,3 @@ class ShortcutsShow extends base_command_1.BaseCommand {
|
|
|
69
70
|
}
|
|
70
71
|
}
|
|
71
72
|
exports.default = ShortcutsShow;
|
|
72
|
-
function formatTime(value) {
|
|
73
|
-
try {
|
|
74
|
-
return new Date(String(value)).toISOString().slice(0, 19).replace('T', ' ');
|
|
75
|
-
}
|
|
76
|
-
catch {
|
|
77
|
-
return String(value);
|
|
78
|
-
}
|
|
79
|
-
}
|
|
@@ -148,6 +148,12 @@ class SkillsLocal extends base_command_1.BaseCommand {
|
|
|
148
148
|
this.log(`${skills.length} skill${skills.length === 1 ? '' : 's'} on ${daemonId}` +
|
|
149
149
|
(response.deviceName ? ` (${response.deviceName})` : '') +
|
|
150
150
|
(response.online ? '' : ' — NOT CONNECTED, this inventory may be stale'));
|
|
151
|
+
if (response.online && response.cwdResolved !== true) {
|
|
152
|
+
// The list is the daemon's registration snapshot. A skill added to the
|
|
153
|
+
// machine since then is not in it until the daemon reconnects, and it
|
|
154
|
+
// read as "not on this machine" (OSK-10080).
|
|
155
|
+
this.log(`(as this daemon reported when it last connected — a skill added since appears after \`${(0, local_skills_1.daemonRestartCommand)(daemonId)}\` on that machine)`);
|
|
156
|
+
}
|
|
151
157
|
(0, format_1.renderTable)(rows, [
|
|
152
158
|
{ key: 'name', header: 'NAME' },
|
|
153
159
|
{ key: 'root', header: 'ROOT' },
|
|
@@ -114,6 +114,8 @@ class SpacesActionsRun extends base_command_1.BaseCommand {
|
|
|
114
114
|
...spec,
|
|
115
115
|
spaceId: space.id,
|
|
116
116
|
assigneeAgentIds: [assigneeAgentId],
|
|
117
|
+
// The server hides an ephemeral action's task once it completes.
|
|
118
|
+
hideWhenDone: outcome !== 'durable',
|
|
117
119
|
});
|
|
118
120
|
}
|
|
119
121
|
catch (err) {
|
|
@@ -133,10 +135,7 @@ class SpacesActionsRun extends base_command_1.BaseCommand {
|
|
|
133
135
|
if (created.conversationId)
|
|
134
136
|
this.log(`Conversation: ${created.conversationId}`);
|
|
135
137
|
if (created.started && outcome === 'ephemeral') {
|
|
136
|
-
|
|
137
|
-
// the tab that fired it. The CLI does not wait for the run, so say what
|
|
138
|
-
// will be different rather than let the task's staying look like a bug.
|
|
139
|
-
this.log(`This action is ephemeral. The web app hides its task when the run finishes; from the CLI it stays until you hide it: \`${bin} tasks move ${created.task.id} --status hidden\`.`);
|
|
138
|
+
this.log('This action is ephemeral: its task is hidden once the run finishes.');
|
|
140
139
|
}
|
|
141
140
|
}
|
|
142
141
|
if (!created.started)
|
|
@@ -4,6 +4,7 @@ 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
6
|
const space_output_1 = require("../../../lib/space-output");
|
|
7
|
+
const format_1 = require("../../../lib/format");
|
|
7
8
|
class SpacesBriefsGet extends base_command_1.BaseCommand {
|
|
8
9
|
static description = 'Get a specific member brief from a space';
|
|
9
10
|
static examples = [
|
|
@@ -39,7 +40,7 @@ class SpacesBriefsGet extends base_command_1.BaseCommand {
|
|
|
39
40
|
const b = result;
|
|
40
41
|
this.log(`Principal Type: ${b.principalType ?? flags.principal}`);
|
|
41
42
|
this.log(`Principal ID: ${b.principalId ?? flags.id}`);
|
|
42
|
-
this.log(`Updated: ${b.updatedAt ?
|
|
43
|
+
this.log(`Updated: ${b.updatedAt ? (0, format_1.localTime)(b.updatedAt) : '-'}`);
|
|
43
44
|
this.log('');
|
|
44
45
|
this.log('Content:');
|
|
45
46
|
const content = typeof b.content === 'string' ? b.content : '';
|
|
@@ -49,11 +50,3 @@ class SpacesBriefsGet extends base_command_1.BaseCommand {
|
|
|
49
50
|
}
|
|
50
51
|
}
|
|
51
52
|
exports.default = SpacesBriefsGet;
|
|
52
|
-
function formatTime(value) {
|
|
53
|
-
try {
|
|
54
|
-
return new Date(String(value)).toISOString().slice(0, 19).replace('T', ' ');
|
|
55
|
-
}
|
|
56
|
-
catch {
|
|
57
|
-
return String(value);
|
|
58
|
-
}
|
|
59
|
-
}
|
|
@@ -40,7 +40,7 @@ class SpacesBriefsList extends base_command_1.BaseCommand {
|
|
|
40
40
|
principalType: String(b.principalType ?? '-'),
|
|
41
41
|
principalId: String(b.principalId ?? '-'),
|
|
42
42
|
length: String(typeof b.content === 'string' ? b.content.length : 0),
|
|
43
|
-
updated: b.updatedAt ?
|
|
43
|
+
updated: b.updatedAt ? (0, format_1.localTime)(b.updatedAt) : '-',
|
|
44
44
|
}));
|
|
45
45
|
(0, format_1.renderTable)(rows, [
|
|
46
46
|
{ key: 'principalType', header: 'PRINCIPAL TYPE' },
|
|
@@ -51,11 +51,3 @@ class SpacesBriefsList extends base_command_1.BaseCommand {
|
|
|
51
51
|
}
|
|
52
52
|
}
|
|
53
53
|
exports.default = SpacesBriefsList;
|
|
54
|
-
function formatTime(value) {
|
|
55
|
-
try {
|
|
56
|
-
return new Date(String(value)).toISOString().slice(0, 19).replace('T', ' ');
|
|
57
|
-
}
|
|
58
|
-
catch {
|
|
59
|
-
return String(value);
|
|
60
|
-
}
|
|
61
|
-
}
|
|
@@ -59,7 +59,7 @@ class SpacesConversations extends base_command_1.BaseCommand {
|
|
|
59
59
|
title: String(c.title ?? '-'),
|
|
60
60
|
linkedTask: linked,
|
|
61
61
|
own,
|
|
62
|
-
updated: c.updatedAt ?
|
|
62
|
+
updated: c.updatedAt ? (0, format_1.localTime)(c.updatedAt) : '-',
|
|
63
63
|
};
|
|
64
64
|
});
|
|
65
65
|
(0, format_1.renderTable)(rows, [
|
|
@@ -76,11 +76,3 @@ class SpacesConversations extends base_command_1.BaseCommand {
|
|
|
76
76
|
}
|
|
77
77
|
}
|
|
78
78
|
exports.default = SpacesConversations;
|
|
79
|
-
function formatTime(value) {
|
|
80
|
-
try {
|
|
81
|
-
return new Date(String(value)).toISOString().slice(0, 19).replace('T', ' ');
|
|
82
|
-
}
|
|
83
|
-
catch {
|
|
84
|
-
return String(value);
|
|
85
|
-
}
|
|
86
|
-
}
|
|
@@ -33,7 +33,7 @@ function heartbeatRow(h) {
|
|
|
33
33
|
pattern: (0, format_1.formatCell)(pattern),
|
|
34
34
|
timezone: (0, format_1.formatCell)(schedule?.timezone),
|
|
35
35
|
enabled: h.enabled === true ? 'yes' : 'no',
|
|
36
|
-
updated: h.updatedAt ?
|
|
36
|
+
updated: h.updatedAt ? (0, format_1.localTime)(h.updatedAt) : '-',
|
|
37
37
|
};
|
|
38
38
|
}
|
|
39
39
|
class SpacesHeartbeatsList extends base_command_1.BaseCommand {
|
|
@@ -91,11 +91,3 @@ class SpacesHeartbeatsList extends base_command_1.BaseCommand {
|
|
|
91
91
|
}
|
|
92
92
|
}
|
|
93
93
|
exports.default = SpacesHeartbeatsList;
|
|
94
|
-
function formatTime(value) {
|
|
95
|
-
try {
|
|
96
|
-
return new Date(String(value)).toISOString().slice(0, 19).replace('T', ' ');
|
|
97
|
-
}
|
|
98
|
-
catch {
|
|
99
|
-
return String(value);
|
|
100
|
-
}
|
|
101
|
-
}
|