@skrr-ai/cli 0.1.12 → 0.1.14
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 +1 -39
- package/dist/base-command.js +36 -10
- package/dist/commands/agents/list.d.ts +10 -0
- package/dist/commands/agents/list.js +16 -1
- package/dist/commands/browser.js +5 -5
- package/dist/commands/commitments/create.d.ts +2 -0
- package/dist/commands/commitments/create.js +30 -13
- package/dist/commands/commitments/update.d.ts +2 -0
- package/dist/commands/commitments/update.js +24 -4
- package/dist/commands/daemon/byok.js +5 -5
- package/dist/commands/daemon/index.js +7 -4
- package/dist/commands/daemon/install.js +8 -5
- package/dist/commands/daemon/login.js +5 -5
- package/dist/commands/daemon/logs.js +5 -5
- package/dist/commands/daemon/restart.js +5 -5
- package/dist/commands/daemon/start.js +5 -5
- package/dist/commands/daemon/status.js +5 -5
- package/dist/commands/daemon/stop.js +5 -5
- package/dist/commands/daemon/uninstall.js +5 -5
- package/dist/commands/daemon/unlock.js +5 -5
- package/dist/commands/daemon/usage.js +6 -6
- package/dist/commands/login.js +7 -2
- package/dist/commands/spaces/list.d.ts +13 -0
- package/dist/commands/spaces/list.js +20 -1
- package/dist/commands/tasks/list.d.ts +11 -0
- package/dist/commands/tasks/list.js +82 -11
- package/dist/commands/wiki/cat.js +2 -1
- package/dist/commands/wiki/mv.js +5 -1
- package/dist/commands/wiki/write.js +5 -1
- package/dist/help.d.ts +20 -1
- package/dist/help.js +26 -1
- package/dist/lib/api-fetch.d.ts +2 -1
- package/dist/lib/api-fetch.js +9 -2
- package/dist/lib/commitments.d.ts +44 -0
- package/dist/lib/commitments.js +123 -0
- package/dist/lib/daemon-binding.d.ts +3 -4
- package/dist/lib/daemon-binding.js +11 -10
- package/dist/lib/daemon-handoff-opt-out.d.ts +8 -0
- package/dist/lib/daemon-handoff-opt-out.js +17 -0
- package/dist/lib/daemon-installer.d.ts +1 -1
- package/dist/lib/daemon-installer.js +2 -2
- package/dist/lib/daemon-setup.js +13 -7
- package/dist/lib/daemonHandoff.d.ts +1 -1
- package/dist/lib/daemonHandoff.js +20 -7
- package/dist/lib/delegated-cli.d.ts +0 -9
- package/dist/lib/delegated-cli.js +149 -6
- package/dist/lib/{exec-oversky.d.ts → exec-runtime-binary.d.ts} +15 -4
- package/dist/lib/{exec-oversky.js → exec-runtime-binary.js} +93 -37
- package/dist/lib/node-adapter.js +6 -0
- package/dist/lib/sky-code.d.ts +1 -1
- package/dist/lib/sky-code.js +1 -1
- package/dist/lib/usage-discovery.js +1 -1
- package/dist/lib/web-url.d.ts +16 -0
- package/dist/lib/web-url.js +25 -0
- package/dist/node_modules/@skrr-ai/data-provider/index.js +3931 -3884
- package/oclif.manifest.json +9932 -9904
- package/package.json +2 -2
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
const core_1 = require("@oclif/core");
|
|
4
|
-
const
|
|
4
|
+
const exec_runtime_binary_1 = require("../../lib/exec-runtime-binary");
|
|
5
5
|
class DaemonStop extends core_1.Command {
|
|
6
6
|
// `skrr daemons <sub>` — the plural is advertised as an alias for the
|
|
7
7
|
// whole topic, and without a per-command alias only the bare topic
|
|
8
8
|
// resolved: every subcommand under it failed.
|
|
9
9
|
static aliases = ['daemons:stop'];
|
|
10
10
|
static summary = 'Stop the local skrr daemon';
|
|
11
|
-
static description = (0,
|
|
11
|
+
static description = (0, exec_runtime_binary_1.forwardedFlagsNote)('stop');
|
|
12
12
|
static strict = false;
|
|
13
13
|
async run() {
|
|
14
14
|
// `this.argv`, NOT `this.parse()`. `strict = false` relaxes POSITIONAL
|
|
@@ -22,12 +22,12 @@ class DaemonStop extends core_1.Command {
|
|
|
22
22
|
// mistake, one directory over.
|
|
23
23
|
const argv = this.argv;
|
|
24
24
|
try {
|
|
25
|
-
const code = await (0,
|
|
25
|
+
const code = await (0, exec_runtime_binary_1.execRuntimeBinary)(['stop', ...argv]);
|
|
26
26
|
this.exit(code);
|
|
27
27
|
}
|
|
28
28
|
catch (err) {
|
|
29
|
-
if (err.message === '
|
|
30
|
-
this.log((0,
|
|
29
|
+
if (err.message === 'runtime-binary-not-installed') {
|
|
30
|
+
this.log((0, exec_runtime_binary_1.notInstalledMessage)());
|
|
31
31
|
this.exit(127);
|
|
32
32
|
}
|
|
33
33
|
throw err;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
const core_1 = require("@oclif/core");
|
|
4
|
-
const
|
|
4
|
+
const exec_runtime_binary_1 = require("../../lib/exec-runtime-binary");
|
|
5
5
|
/**
|
|
6
6
|
* `skrr daemon uninstall` — uninstall the local runtime's OS service.
|
|
7
7
|
*
|
|
@@ -20,7 +20,7 @@ class DaemonUninstall extends core_1.Command {
|
|
|
20
20
|
// resolved: every subcommand under it failed.
|
|
21
21
|
static aliases = ['daemons:uninstall'];
|
|
22
22
|
static summary = "Remove the local skrr runtime's background service (local state is left alone)";
|
|
23
|
-
static description = (0,
|
|
23
|
+
static description = (0, exec_runtime_binary_1.forwardedFlagsNote)('uninstall');
|
|
24
24
|
static strict = false; // forward all args verbatim — see run()
|
|
25
25
|
async run() {
|
|
26
26
|
// `this.argv`, NOT `this.parse()`. `strict = false` relaxes POSITIONAL
|
|
@@ -34,12 +34,12 @@ class DaemonUninstall extends core_1.Command {
|
|
|
34
34
|
// mistake, one directory over.
|
|
35
35
|
const argv = this.argv;
|
|
36
36
|
try {
|
|
37
|
-
const code = await (0,
|
|
37
|
+
const code = await (0, exec_runtime_binary_1.execRuntimeBinary)(['uninstall', ...argv]);
|
|
38
38
|
this.exit(code);
|
|
39
39
|
}
|
|
40
40
|
catch (err) {
|
|
41
|
-
if (err.message === '
|
|
42
|
-
this.log((0,
|
|
41
|
+
if (err.message === 'runtime-binary-not-installed') {
|
|
42
|
+
this.log((0, exec_runtime_binary_1.notInstalledMessage)());
|
|
43
43
|
this.exit(127);
|
|
44
44
|
}
|
|
45
45
|
throw err;
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
const core_1 = require("@oclif/core");
|
|
4
|
-
const
|
|
4
|
+
const exec_runtime_binary_1 = require("../../lib/exec-runtime-binary");
|
|
5
5
|
class DaemonUnlock extends core_1.Command {
|
|
6
6
|
// `skrr daemons <sub>` — the plural is advertised as an alias for the
|
|
7
7
|
// whole topic, and without a per-command alias only the bare topic
|
|
8
8
|
// resolved: every subcommand under it failed.
|
|
9
9
|
static aliases = ['daemons:unlock'];
|
|
10
10
|
static summary = 'Clear a stranded singleton lock (daemon.lock) left by a crashed skrr daemon';
|
|
11
|
-
static description = (0,
|
|
11
|
+
static description = (0, exec_runtime_binary_1.forwardedFlagsNote)('unlock');
|
|
12
12
|
static strict = false; // forward all args verbatim — see run()
|
|
13
13
|
static examples = ['<%= config.bin %> daemon unlock'];
|
|
14
14
|
async run() {
|
|
@@ -18,12 +18,12 @@ class DaemonUnlock extends core_1.Command {
|
|
|
18
18
|
// the verb lives on a second binary you have to learn about first.
|
|
19
19
|
const argv = this.argv;
|
|
20
20
|
try {
|
|
21
|
-
const code = await (0,
|
|
21
|
+
const code = await (0, exec_runtime_binary_1.execRuntimeBinary)(['unlock', ...argv]);
|
|
22
22
|
this.exit(code);
|
|
23
23
|
}
|
|
24
24
|
catch (err) {
|
|
25
|
-
if (err.message === '
|
|
26
|
-
this.log((0,
|
|
25
|
+
if (err.message === 'runtime-binary-not-installed') {
|
|
26
|
+
this.log((0, exec_runtime_binary_1.notInstalledMessage)());
|
|
27
27
|
this.exit(127);
|
|
28
28
|
}
|
|
29
29
|
throw err;
|
|
@@ -6,7 +6,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
6
6
|
exports.supportsDaemonUsage = supportsDaemonUsage;
|
|
7
7
|
const core_1 = require("@oclif/core");
|
|
8
8
|
const node_child_process_1 = require("node:child_process");
|
|
9
|
-
const
|
|
9
|
+
const exec_runtime_binary_1 = require("../../lib/exec-runtime-binary");
|
|
10
10
|
const index_1 = __importDefault(require("./index"));
|
|
11
11
|
/** Whether an `oversky --help` surface actually supports the usage command. */
|
|
12
12
|
function supportsDaemonUsage(helpText) {
|
|
@@ -29,9 +29,9 @@ class DaemonUsage extends index_1.default {
|
|
|
29
29
|
};
|
|
30
30
|
async run() {
|
|
31
31
|
const { flags } = await this.parse(DaemonUsage);
|
|
32
|
-
const binary = (0,
|
|
32
|
+
const binary = (0, exec_runtime_binary_1.findRuntimeBinary)();
|
|
33
33
|
if (!binary) {
|
|
34
|
-
this.log((0,
|
|
34
|
+
this.log((0, exec_runtime_binary_1.notInstalledMessage)());
|
|
35
35
|
this.exit(127);
|
|
36
36
|
}
|
|
37
37
|
// A stale PATH-first `oversky` (0.2.x is common on Homebrew installs) does
|
|
@@ -58,11 +58,11 @@ class DaemonUsage extends index_1.default {
|
|
|
58
58
|
if (flags.json)
|
|
59
59
|
args.push('--json');
|
|
60
60
|
try {
|
|
61
|
-
this.exit(await (0,
|
|
61
|
+
this.exit(await (0, exec_runtime_binary_1.execRuntimeBinary)(args));
|
|
62
62
|
}
|
|
63
63
|
catch (error) {
|
|
64
|
-
if (error.message === '
|
|
65
|
-
this.log((0,
|
|
64
|
+
if (error.message === 'runtime-binary-not-installed') {
|
|
65
|
+
this.log((0, exec_runtime_binary_1.notInstalledMessage)());
|
|
66
66
|
this.exit(127);
|
|
67
67
|
}
|
|
68
68
|
throw error;
|
package/dist/commands/login.js
CHANGED
|
@@ -38,7 +38,10 @@ const auth_storage_1 = require("../lib/auth-storage");
|
|
|
38
38
|
* `cliLoginWithRefreshToken` for the full rationale.
|
|
39
39
|
*/
|
|
40
40
|
class Login extends base_command_1.BaseCommand {
|
|
41
|
-
static description = 'Sign in to a skrr instance (PKCE localhost callback; device-code fallback)'
|
|
41
|
+
static description = 'Sign in to a skrr instance (PKCE localhost callback; device-code fallback). ' +
|
|
42
|
+
'On an interactive first login without a local runtime, skrr offers to install it as a ' +
|
|
43
|
+
'background service. Choose no, or set SKRR_SKIP_DAEMON_HANDOFF=1 before running this ' +
|
|
44
|
+
'command, to skip that optional setup.';
|
|
42
45
|
static examples = [
|
|
43
46
|
'<%= config.bin %> login',
|
|
44
47
|
'<%= config.bin %> login --env prod',
|
|
@@ -186,7 +189,9 @@ class Login extends base_command_1.BaseCommand {
|
|
|
186
189
|
// profile, and until this login there was no session to take them from.
|
|
187
190
|
// Keyed off `reason` rather than the sentence in `detail`, which is
|
|
188
191
|
// written for a person and expected to be reworded.
|
|
189
|
-
if (handoff.reason === 'no-binary' ||
|
|
192
|
+
if (handoff.reason === 'no-binary' ||
|
|
193
|
+
handoff.reason === 'legacy-binary' ||
|
|
194
|
+
handoff.reason === 'no-service') {
|
|
190
195
|
const setup = await (0, daemon_setup_1.offerDaemonSetup)({
|
|
191
196
|
binaryPresent: handoff.reason === 'no-service',
|
|
192
197
|
log: (line) => this.log(line),
|
|
@@ -17,6 +17,19 @@ import { BaseCommand } from '../../base-command';
|
|
|
17
17
|
* convention `describeResourceNotFound` follows in `base-command`.
|
|
18
18
|
*/
|
|
19
19
|
export declare function noSpacesMatchedMessage(q: string, bin?: string): string;
|
|
20
|
+
/**
|
|
21
|
+
* What the unfiltered zero-row case is allowed to say.
|
|
22
|
+
*
|
|
23
|
+
* A bare `No spaces.` on a fresh account is technically true and operationally
|
|
24
|
+
* useless: it names no next step, so the user reading `GETTING_STARTED.md`
|
|
25
|
+
* step 3 hits three of these in a row and concludes the product is inert.
|
|
26
|
+
* `commitments/list.ts` learned this the hard way and left the reasoning in a
|
|
27
|
+
* comment; the fix is to follow the same pattern here — one line naming the
|
|
28
|
+
* command that fixes it.
|
|
29
|
+
*
|
|
30
|
+
* Pure and exported so the wording is testable without an oclif runtime.
|
|
31
|
+
*/
|
|
32
|
+
export declare function noSpacesEmptyMessage(bin?: string): string;
|
|
20
33
|
export default class SpacesList extends BaseCommand {
|
|
21
34
|
static description: string;
|
|
22
35
|
static examples: string[];
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.noSpacesMatchedMessage = noSpacesMatchedMessage;
|
|
4
|
+
exports.noSpacesEmptyMessage = noSpacesEmptyMessage;
|
|
4
5
|
const core_1 = require("@oclif/core");
|
|
5
6
|
const data_provider_1 = require("@skrr-ai/data-provider");
|
|
6
7
|
const base_command_1 = require("../../base-command");
|
|
@@ -29,6 +30,22 @@ function noSpacesMatchedMessage(q, bin = 'skrr') {
|
|
|
29
30
|
'not a tokenized search, so word order matters.\n' +
|
|
30
31
|
` → retry with one distinctive word, or list them all with \`${bin} spaces list\`.`);
|
|
31
32
|
}
|
|
33
|
+
/**
|
|
34
|
+
* What the unfiltered zero-row case is allowed to say.
|
|
35
|
+
*
|
|
36
|
+
* A bare `No spaces.` on a fresh account is technically true and operationally
|
|
37
|
+
* useless: it names no next step, so the user reading `GETTING_STARTED.md`
|
|
38
|
+
* step 3 hits three of these in a row and concludes the product is inert.
|
|
39
|
+
* `commitments/list.ts` learned this the hard way and left the reasoning in a
|
|
40
|
+
* comment; the fix is to follow the same pattern here — one line naming the
|
|
41
|
+
* command that fixes it.
|
|
42
|
+
*
|
|
43
|
+
* Pure and exported so the wording is testable without an oclif runtime.
|
|
44
|
+
*/
|
|
45
|
+
function noSpacesEmptyMessage(bin = 'skrr') {
|
|
46
|
+
return ('No spaces yet.\n' +
|
|
47
|
+
` → Create your first one: \`${bin} spaces create --title "My workspace"\``);
|
|
48
|
+
}
|
|
32
49
|
class SpacesList extends base_command_1.BaseCommand {
|
|
33
50
|
static description = 'List spaces';
|
|
34
51
|
static examples = [
|
|
@@ -95,7 +112,9 @@ class SpacesList extends base_command_1.BaseCommand {
|
|
|
95
112
|
const r = response;
|
|
96
113
|
const items = r?.data ?? [];
|
|
97
114
|
if (items.length === 0) {
|
|
98
|
-
this.log(flags.q
|
|
115
|
+
this.log(flags.q
|
|
116
|
+
? noSpacesMatchedMessage(flags.q, this.config.bin)
|
|
117
|
+
: noSpacesEmptyMessage(this.config.bin));
|
|
99
118
|
return;
|
|
100
119
|
}
|
|
101
120
|
const rows = items.map((s) => ({
|
|
@@ -1,6 +1,17 @@
|
|
|
1
1
|
import type { TaskListParams } from '@skrr-ai/data-provider';
|
|
2
2
|
import { BaseCommand } from '../../base-command';
|
|
3
3
|
type ListFlags = Record<string, unknown>;
|
|
4
|
+
/**
|
|
5
|
+
* What the zero-row case is allowed to say. The bare `No tasks.` was step 3
|
|
6
|
+
* of `GETTING_STARTED.md` and named no next step; a new user reading it hit
|
|
7
|
+
* three of these in a row and concluded the product was empty. Follow the
|
|
8
|
+
* `commitments/list.ts` pattern: name the command that fixes THIS empty state,
|
|
9
|
+
* with the specific `--status in_progress` hint kept because a reaped run
|
|
10
|
+
* genuinely hides here (a real bug, not a first-run scenario).
|
|
11
|
+
*
|
|
12
|
+
* Exported and pure so the wording is testable without an oclif runtime.
|
|
13
|
+
*/
|
|
14
|
+
export declare function emptyTasksMessage(flags: ListFlags, bin?: string): string;
|
|
4
15
|
/**
|
|
5
16
|
* The task-list request bag is shared with import/export so every CLI list
|
|
6
17
|
* surface serializes the same server-side filters. Keep user-id resolution in
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.emptyTasksMessage = emptyTasksMessage;
|
|
3
4
|
exports.buildListParams = buildListParams;
|
|
4
5
|
const core_1 = require("@oclif/core");
|
|
5
6
|
const data_provider_1 = require("@skrr-ai/data-provider");
|
|
@@ -7,6 +8,86 @@ const base_command_1 = require("../../base-command");
|
|
|
7
8
|
const web_url_1 = require("../../lib/web-url");
|
|
8
9
|
const format_1 = require("../../lib/format");
|
|
9
10
|
const tasks_1 = require("../../lib/tasks");
|
|
11
|
+
/**
|
|
12
|
+
* Names of `tasks list` flags that narrow the result set. Used to distinguish
|
|
13
|
+
* "no tasks anywhere" from "no tasks matching your filters" — the first case
|
|
14
|
+
* wants a create-command hint, the second wants a loosen-filters hint. Kept
|
|
15
|
+
* as a set so a new filter added to `buildListParams` shows up here at review
|
|
16
|
+
* time rather than silently changing the empty state.
|
|
17
|
+
*/
|
|
18
|
+
const FILTER_FLAGS = new Set([
|
|
19
|
+
'goal',
|
|
20
|
+
'project',
|
|
21
|
+
'cycle',
|
|
22
|
+
'parent',
|
|
23
|
+
'status',
|
|
24
|
+
'status-type',
|
|
25
|
+
'execution-state',
|
|
26
|
+
'actionable-by',
|
|
27
|
+
'actionable-for-agent',
|
|
28
|
+
'needs-me',
|
|
29
|
+
'actionability-state',
|
|
30
|
+
'actionability-reason',
|
|
31
|
+
'priority',
|
|
32
|
+
'estimate',
|
|
33
|
+
'min-estimate',
|
|
34
|
+
'assignee-agent',
|
|
35
|
+
'assignee-user',
|
|
36
|
+
'dri',
|
|
37
|
+
'dri-kind',
|
|
38
|
+
'mine',
|
|
39
|
+
'explicit-only',
|
|
40
|
+
'subscribed',
|
|
41
|
+
'include-snoozed',
|
|
42
|
+
'external-key',
|
|
43
|
+
'blocked-by',
|
|
44
|
+
'blocks',
|
|
45
|
+
'due-before',
|
|
46
|
+
'due-after',
|
|
47
|
+
'overdue',
|
|
48
|
+
'tag',
|
|
49
|
+
'label-id',
|
|
50
|
+
'q',
|
|
51
|
+
]);
|
|
52
|
+
/**
|
|
53
|
+
* What the zero-row case is allowed to say. The bare `No tasks.` was step 3
|
|
54
|
+
* of `GETTING_STARTED.md` and named no next step; a new user reading it hit
|
|
55
|
+
* three of these in a row and concluded the product was empty. Follow the
|
|
56
|
+
* `commitments/list.ts` pattern: name the command that fixes THIS empty state,
|
|
57
|
+
* with the specific `--status in_progress` hint kept because a reaped run
|
|
58
|
+
* genuinely hides here (a real bug, not a first-run scenario).
|
|
59
|
+
*
|
|
60
|
+
* Exported and pure so the wording is testable without an oclif runtime.
|
|
61
|
+
*/
|
|
62
|
+
function emptyTasksMessage(flags, bin = 'skrr') {
|
|
63
|
+
const activeFilters = Array.from(FILTER_FLAGS).filter((name) => {
|
|
64
|
+
const value = flags[name];
|
|
65
|
+
if (value === undefined || value === null || value === false)
|
|
66
|
+
return false;
|
|
67
|
+
if (typeof value === 'string' && value.length === 0)
|
|
68
|
+
return false;
|
|
69
|
+
if (Array.isArray(value) && value.length === 0)
|
|
70
|
+
return false;
|
|
71
|
+
return true;
|
|
72
|
+
});
|
|
73
|
+
const lines = ['No tasks.'];
|
|
74
|
+
if (activeFilters.length === 0) {
|
|
75
|
+
lines.push('');
|
|
76
|
+
lines.push(` → Create your first one: \`${bin} tasks create --title "..." --space <space-id>\``);
|
|
77
|
+
lines.push(` → List spaces to find one: \`${bin} spaces list\``);
|
|
78
|
+
}
|
|
79
|
+
else if (flags.status === 'in_progress' && !flags['execution-state']) {
|
|
80
|
+
// `--status in_progress` filters the board column only. A run that was
|
|
81
|
+
// reaped/reset (e.g. a stuck-task timeout) is moved OFF `in_progress` but
|
|
82
|
+
// keeps its execution markers, so it hides here. Point the operator at
|
|
83
|
+
// the execution-state views that still surface it.
|
|
84
|
+
lines.push('');
|
|
85
|
+
lines.push('Note: `--status in_progress` shows only the board column. A reaped or reset run');
|
|
86
|
+
lines.push(' no longer has that status. Try `--execution-state active` (running now) or');
|
|
87
|
+
lines.push(` \`--execution-state recovered\` (reaped, startable), or \`${bin} tasks active\`.`);
|
|
88
|
+
}
|
|
89
|
+
return lines.join('\n');
|
|
90
|
+
}
|
|
10
91
|
/**
|
|
11
92
|
* The task-list request bag is shared with import/export so every CLI list
|
|
12
93
|
* surface serializes the same server-side filters. Keep user-id resolution in
|
|
@@ -303,17 +384,7 @@ class TasksList extends base_command_1.BaseCommand {
|
|
|
303
384
|
const r = response;
|
|
304
385
|
const items = r?.data ?? [];
|
|
305
386
|
if (items.length === 0) {
|
|
306
|
-
this.log(
|
|
307
|
-
// `--status in_progress` filters the board column only. A run that was
|
|
308
|
-
// reaped/reset (e.g. a stuck-task timeout) is moved OFF `in_progress` but
|
|
309
|
-
// keeps its execution markers, so it hides here. Point the operator at the
|
|
310
|
-
// execution-state views that still surface it.
|
|
311
|
-
if (flags.status === 'in_progress' && !flags['execution-state']) {
|
|
312
|
-
this.log('');
|
|
313
|
-
this.log('Note: `--status in_progress` shows only the board column. A reaped or reset run');
|
|
314
|
-
this.log(' no longer has that status. Try `--execution-state active` (running now) or');
|
|
315
|
-
this.log(' `--execution-state recovered` (reaped, startable), or `skrr tasks active`.');
|
|
316
|
-
}
|
|
387
|
+
this.log(emptyTasksMessage(flags, this.config.bin));
|
|
317
388
|
return;
|
|
318
389
|
}
|
|
319
390
|
const rows = items.map((t) => {
|
|
@@ -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 web_url_1 = require("../../lib/web-url");
|
|
6
7
|
class WikiCat extends base_command_1.BaseCommand {
|
|
7
8
|
static description = 'Print a wiki page (Markdown by default)';
|
|
8
9
|
static examples = [
|
|
@@ -41,7 +42,7 @@ class WikiCat extends base_command_1.BaseCommand {
|
|
|
41
42
|
this.handleApiError(err);
|
|
42
43
|
}
|
|
43
44
|
if (flags.json) {
|
|
44
|
-
this.log(JSON.stringify(page, null, 2));
|
|
45
|
+
this.log(JSON.stringify((0, web_url_1.withWikiPageUrl)(this.cliConfig.baseURL, page), null, 2));
|
|
45
46
|
return;
|
|
46
47
|
}
|
|
47
48
|
// Body only — so `skrr wiki cat ... > page.md` produces a clean file and
|
package/dist/commands/wiki/mv.js
CHANGED
|
@@ -6,6 +6,7 @@ const core_1 = require("@oclif/core");
|
|
|
6
6
|
const data_provider_1 = require("@skrr-ai/data-provider");
|
|
7
7
|
const base_command_1 = require("../../base-command");
|
|
8
8
|
const http_error_1 = require("../../lib/http-error");
|
|
9
|
+
const web_url_1 = require("../../lib/web-url");
|
|
9
10
|
const wiki_1 = require("../../lib/wiki");
|
|
10
11
|
const write_1 = require("./write");
|
|
11
12
|
/**
|
|
@@ -231,7 +232,10 @@ class WikiMv extends base_command_1.BaseCommand {
|
|
|
231
232
|
});
|
|
232
233
|
}
|
|
233
234
|
if (flags.json) {
|
|
234
|
-
this.log(JSON.stringify({
|
|
235
|
+
this.log(JSON.stringify({
|
|
236
|
+
kind: 'page',
|
|
237
|
+
...(0, web_url_1.withWikiPageUrl)(this.cliConfig.baseURL, moved),
|
|
238
|
+
}, null, 2));
|
|
235
239
|
return;
|
|
236
240
|
}
|
|
237
241
|
this.log(`Moved page ${source} → ${moved.path ?? args.destination}.`);
|
|
@@ -8,6 +8,7 @@ const core_1 = require("@oclif/core");
|
|
|
8
8
|
const data_provider_1 = require("@skrr-ai/data-provider");
|
|
9
9
|
const base_command_1 = require("../../base-command");
|
|
10
10
|
const http_error_1 = require("../../lib/http-error");
|
|
11
|
+
const web_url_1 = require("../../lib/web-url");
|
|
11
12
|
const wiki_1 = require("../../lib/wiki");
|
|
12
13
|
/**
|
|
13
14
|
* The page lookup below goes through `dataService`, whose adapter throws a
|
|
@@ -248,8 +249,9 @@ class WikiWrite extends base_command_1.BaseCommand {
|
|
|
248
249
|
`it creates. Retitle it with \`${this.config.bin} wiki update ${args.space} ${page.path ?? args.path} ` +
|
|
249
250
|
`--title ${JSON.stringify(flags.title)}\` (the slug is kept, so stored paths stay valid).`);
|
|
250
251
|
}
|
|
252
|
+
const withUrl = (0, web_url_1.withWikiPageUrl)(this.cliConfig.baseURL, page);
|
|
251
253
|
if (flags.json) {
|
|
252
|
-
this.log(JSON.stringify(
|
|
254
|
+
this.log(JSON.stringify(withUrl, null, 2));
|
|
253
255
|
return;
|
|
254
256
|
}
|
|
255
257
|
// Report what actually happened, not what we set out to do — a write that
|
|
@@ -260,6 +262,8 @@ class WikiWrite extends base_command_1.BaseCommand {
|
|
|
260
262
|
verb = flags.append ? 'Appended to' : 'Updated';
|
|
261
263
|
}
|
|
262
264
|
this.log(`${verb} ${page.path ?? args.path} (${page.pageId}).`);
|
|
265
|
+
if (withUrl.url)
|
|
266
|
+
this.log(`URL: ${withUrl.url}`);
|
|
263
267
|
}
|
|
264
268
|
}
|
|
265
269
|
exports.default = WikiWrite;
|
package/dist/help.d.ts
CHANGED
|
@@ -20,8 +20,27 @@ import { Help } from '@oclif/core';
|
|
|
20
20
|
* before running it. The audience most likely to need the good message was the
|
|
21
21
|
* audience reliably denied it.
|
|
22
22
|
*
|
|
23
|
-
*
|
|
23
|
+
* It also puts a GETTING STARTED block at the top of `skrr --help`.
|
|
24
|
+
*
|
|
25
|
+
* Dogfooding 0.1.12 found the root help teaching neither of the two commands
|
|
26
|
+
* the release exists to deliver: ~50 topics in alphabetical order, with `login`
|
|
27
|
+
* between `list-tokens` and `logout`, and nothing saying a runtime is needed or
|
|
28
|
+
* that `skrr` can fetch one. The shortest path to a working machine was
|
|
29
|
+
* undiscoverable from inside the tool that provides it — findable only by
|
|
30
|
+
* someone who read the docs, which is what the two-command flow exists to make
|
|
31
|
+
* unnecessary.
|
|
32
|
+
*
|
|
33
|
+
* Printed BEFORE the standard output rather than appended, because the thing it
|
|
34
|
+
* competes with is a fifty-line topic list. A signpost below that is a signpost
|
|
35
|
+
* for people who already knew.
|
|
24
36
|
*/
|
|
25
37
|
export default class SkrrHelp extends Help {
|
|
38
|
+
/**
|
|
39
|
+
* The two commands, before the topic list rather than after it.
|
|
40
|
+
*
|
|
41
|
+
* Deliberately not a tutorial: two lines, both runnable, in the order a new
|
|
42
|
+
* machine needs them.
|
|
43
|
+
*/
|
|
44
|
+
protected showRootHelp(): Promise<void>;
|
|
26
45
|
showHelp(argv: string[]): Promise<void>;
|
|
27
46
|
}
|
package/dist/help.js
CHANGED
|
@@ -23,9 +23,34 @@ const command_miss_1 = require("./lib/command-miss");
|
|
|
23
23
|
* before running it. The audience most likely to need the good message was the
|
|
24
24
|
* audience reliably denied it.
|
|
25
25
|
*
|
|
26
|
-
*
|
|
26
|
+
* It also puts a GETTING STARTED block at the top of `skrr --help`.
|
|
27
|
+
*
|
|
28
|
+
* Dogfooding 0.1.12 found the root help teaching neither of the two commands
|
|
29
|
+
* the release exists to deliver: ~50 topics in alphabetical order, with `login`
|
|
30
|
+
* between `list-tokens` and `logout`, and nothing saying a runtime is needed or
|
|
31
|
+
* that `skrr` can fetch one. The shortest path to a working machine was
|
|
32
|
+
* undiscoverable from inside the tool that provides it — findable only by
|
|
33
|
+
* someone who read the docs, which is what the two-command flow exists to make
|
|
34
|
+
* unnecessary.
|
|
35
|
+
*
|
|
36
|
+
* Printed BEFORE the standard output rather than appended, because the thing it
|
|
37
|
+
* competes with is a fifty-line topic list. A signpost below that is a signpost
|
|
38
|
+
* for people who already knew.
|
|
27
39
|
*/
|
|
28
40
|
class SkrrHelp extends core_1.Help {
|
|
41
|
+
/**
|
|
42
|
+
* The two commands, before the topic list rather than after it.
|
|
43
|
+
*
|
|
44
|
+
* Deliberately not a tutorial: two lines, both runnable, in the order a new
|
|
45
|
+
* machine needs them.
|
|
46
|
+
*/
|
|
47
|
+
async showRootHelp() {
|
|
48
|
+
this.log('GETTING STARTED');
|
|
49
|
+
this.log(' skrr login Sign in. Offers to set this machine up if it has no runtime.');
|
|
50
|
+
this.log(' skrr daemon install Install the runtime by hand (fetches the signed release).');
|
|
51
|
+
this.log('');
|
|
52
|
+
return super.showRootHelp();
|
|
53
|
+
}
|
|
29
54
|
async showHelp(argv) {
|
|
30
55
|
// Mirror oclif's own id resolution: the topic separator is a space here, so
|
|
31
56
|
// the id is the leading non-flag tokens joined with `:`.
|
package/dist/lib/api-fetch.d.ts
CHANGED
|
@@ -29,7 +29,8 @@ export declare class ApiFetchError extends Error {
|
|
|
29
29
|
readonly status: number;
|
|
30
30
|
readonly body?: string;
|
|
31
31
|
readonly code?: string;
|
|
32
|
-
|
|
32
|
+
readonly method?: string;
|
|
33
|
+
constructor(message: string, status: number, body?: string, code?: string, method?: string);
|
|
33
34
|
}
|
|
34
35
|
/**
|
|
35
36
|
* Call a skrr API endpoint with the current credential. Throws
|
package/dist/lib/api-fetch.js
CHANGED
|
@@ -46,12 +46,19 @@ class ApiFetchError extends Error {
|
|
|
46
46
|
status;
|
|
47
47
|
body;
|
|
48
48
|
code;
|
|
49
|
-
|
|
49
|
+
// The HTTP method of the failing request. The 403 branch of
|
|
50
|
+
// `handleApiError` needs to know whether the request even HAD a body before
|
|
51
|
+
// it can advise the user to "try again with less of the request body"
|
|
52
|
+
// (OSK-6765): `agents show` is a GET and had no body, and the advice was
|
|
53
|
+
// impossible to follow.
|
|
54
|
+
method;
|
|
55
|
+
constructor(message, status, body, code, method) {
|
|
50
56
|
super(message);
|
|
51
57
|
this.name = 'ApiFetchError';
|
|
52
58
|
this.status = status;
|
|
53
59
|
this.body = body;
|
|
54
60
|
this.code = code;
|
|
61
|
+
this.method = method;
|
|
55
62
|
}
|
|
56
63
|
}
|
|
57
64
|
exports.ApiFetchError = ApiFetchError;
|
|
@@ -189,7 +196,7 @@ async function apiFetch(pathOrUrl, opts = {}) {
|
|
|
189
196
|
catch {
|
|
190
197
|
/* ignore body read failures */
|
|
191
198
|
}
|
|
192
|
-
throw new ApiFetchError(`HTTP ${res.status} ${res.statusText} — ${method} ${pathOrUrl}`, res.status, text, code);
|
|
199
|
+
throw new ApiFetchError(`HTTP ${res.status} ${res.statusText} — ${method} ${pathOrUrl}`, res.status, text, code, method);
|
|
193
200
|
}
|
|
194
201
|
// 204/205 carry no body by definition; an empty body has no content-type
|
|
195
202
|
// worth judging. Neither is an error.
|
|
@@ -362,6 +362,29 @@ export declare const COMMITMENT_CREATE_KEYS: readonly ["agentId", "kind", "compa
|
|
|
362
362
|
*/
|
|
363
363
|
export declare function normalizeCreateBody(input: Record<string, unknown>): Record<string, unknown>;
|
|
364
364
|
export declare function parseIntervalToMs(input: string): number;
|
|
365
|
+
/**
|
|
366
|
+
* Assemble the `watchedSources` array from CLI flags — one place, so `create`
|
|
367
|
+
* and `update` agree on which flags carry what.
|
|
368
|
+
*
|
|
369
|
+
* The `space` and `monitor` sources need a scope id (`config.spaceId` /
|
|
370
|
+
* `config.monitorId`) that the flat `--watch` enum cannot carry. The API
|
|
371
|
+
* rejects the whole write when one is missing (`SPACE_SOURCE_SCOPE_REQUIRED` /
|
|
372
|
+
* `INVALID_MONITOR_REFERENCE`) — the same shape that made this a finding: the
|
|
373
|
+
* CLI advertised the source but had no way to satisfy it.
|
|
374
|
+
*
|
|
375
|
+
* The companion flags (`--watch-space`, `--watch-monitor`) fill that gap and
|
|
376
|
+
* implicitly opt the source in, so the enum and its config cannot disagree.
|
|
377
|
+
* Space refs must be RESOLVED to canonical ids by the caller — this helper
|
|
378
|
+
* does not do the network round trip, so it is unit-testable on its own.
|
|
379
|
+
*/
|
|
380
|
+
export type WatchFlagInputs = {
|
|
381
|
+
watch?: string[];
|
|
382
|
+
metricKey?: string[];
|
|
383
|
+
/** Already resolved to canonical space ids by the caller. */
|
|
384
|
+
spaceIds?: string[];
|
|
385
|
+
monitorIds?: string[];
|
|
386
|
+
};
|
|
387
|
+
export declare function buildWatchedSources(inputs: WatchFlagInputs): Array<Record<string, unknown>> | undefined;
|
|
365
388
|
/** The evidence-health shape carried on a check's `inputs`. */
|
|
366
389
|
export type EvidenceHealthView = {
|
|
367
390
|
state?: string | null;
|
|
@@ -429,6 +452,27 @@ export declare function effectiveAutonomyMode(check?: {
|
|
|
429
452
|
policyTrace?: Array<Record<string, unknown>>;
|
|
430
453
|
} | null;
|
|
431
454
|
} | null): string | undefined;
|
|
455
|
+
/**
|
|
456
|
+
* A `commitment_standstill` policyTrace entry, extracted from the latest
|
|
457
|
+
* check's decision. The arbiter appends it whenever a quiet posture is the
|
|
458
|
+
* ANSWER to "why nothing is happening" (`CommitmentControl/index.js` around
|
|
459
|
+
* the `record_only`/empty-action-plan branch). Every field except `reason` is
|
|
460
|
+
* optional, and old checks lack the entry entirely — so a missing entry means
|
|
461
|
+
* "the loop had nothing standstill-worthy to say", not "we don't know".
|
|
462
|
+
*
|
|
463
|
+
* Exported for tests.
|
|
464
|
+
*/
|
|
465
|
+
export declare function extractStandstillFromCheck(check?: {
|
|
466
|
+
decision?: {
|
|
467
|
+
policyTrace?: Array<Record<string, unknown>>;
|
|
468
|
+
} | null;
|
|
469
|
+
} | null): {
|
|
470
|
+
reason: string;
|
|
471
|
+
layer?: string;
|
|
472
|
+
owner?: string;
|
|
473
|
+
fix?: string;
|
|
474
|
+
alsoConstrained?: Array<Record<string, unknown>>;
|
|
475
|
+
} | null;
|
|
432
476
|
/**
|
|
433
477
|
* The `Autonomy:` line — the stated mode, annotated when the latest check
|
|
434
478
|
* actually ran at a STRICTER one (OSK-4881). Without the caveat, a commitment
|