@skrr-ai/cli 0.1.36 → 0.1.38
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +17 -4
- package/bin/dev-fallback.js +167 -4
- package/dist/base-command.js +46 -2
- package/dist/commands/agents/actions/create.d.ts +5 -0
- package/dist/commands/agents/actions/create.js +42 -5
- package/dist/commands/agents/actions/delete.d.ts +1 -0
- package/dist/commands/agents/actions/delete.js +7 -0
- package/dist/commands/agents/actions/update.d.ts +5 -0
- package/dist/commands/agents/actions/update.js +27 -1
- package/dist/commands/agents/api-actions/add.d.ts +41 -0
- package/dist/commands/agents/api-actions/add.js +205 -0
- package/dist/commands/agents/api-actions/index.d.ts +39 -0
- package/dist/commands/agents/api-actions/index.js +103 -0
- package/dist/commands/agents/api-actions/remove.d.ts +14 -0
- package/dist/commands/agents/api-actions/remove.js +36 -0
- package/dist/commands/agents/avatar/default/apply.d.ts +25 -0
- package/dist/commands/agents/avatar/default/apply.js +56 -0
- package/dist/commands/agents/avatar/default/index.d.ts +29 -0
- package/dist/commands/agents/avatar/default/index.js +61 -0
- package/dist/commands/agents/avatar/default/set.d.ts +24 -0
- package/dist/commands/agents/avatar/default/set.js +120 -0
- package/dist/commands/agents/avatar/library/delete.d.ts +20 -0
- package/dist/commands/agents/avatar/library/delete.js +47 -0
- package/dist/commands/agents/avatar/library/index.d.ts +16 -0
- package/dist/commands/agents/avatar/library/index.js +56 -0
- package/dist/commands/agents/avatar/presets.d.ts +19 -0
- package/dist/commands/agents/avatar/presets.js +56 -0
- package/dist/commands/agents/avatar/upload.js +7 -1
- package/dist/commands/agents/categories/create.d.ts +14 -0
- package/dist/commands/agents/categories/create.js +46 -0
- package/dist/commands/agents/categories/delete.d.ts +13 -0
- package/dist/commands/agents/categories/delete.js +41 -0
- package/dist/commands/agents/categories/index.d.ts +36 -0
- package/dist/commands/agents/categories/index.js +135 -0
- package/dist/commands/agents/categories/update.d.ts +22 -0
- package/dist/commands/agents/categories/update.js +59 -0
- package/dist/commands/agents/chat.d.ts +21 -0
- package/dist/commands/agents/chat.js +94 -7
- package/dist/commands/agents/create.d.ts +10 -0
- package/dist/commands/agents/create.js +64 -3
- package/dist/commands/agents/ensure-default.d.ts +27 -0
- package/dist/commands/agents/ensure-default.js +65 -0
- package/dist/commands/agents/list.d.ts +15 -0
- package/dist/commands/agents/list.js +31 -1
- package/dist/commands/agents/mute.d.ts +16 -0
- package/dist/commands/agents/mute.js +38 -0
- package/dist/commands/agents/pin.d.ts +16 -0
- package/dist/commands/agents/pin.js +38 -0
- package/dist/commands/agents/scene-background/upload.d.ts +30 -0
- package/dist/commands/agents/scene-background/upload.js +97 -0
- package/dist/commands/agents/show.js +13 -0
- package/dist/commands/agents/tools/auth.d.ts +19 -0
- package/dist/commands/agents/tools/auth.js +41 -0
- package/dist/commands/agents/tools/calls.d.ts +36 -0
- package/dist/commands/agents/tools/calls.js +117 -0
- package/dist/commands/agents/tools/index.d.ts +20 -0
- package/dist/commands/agents/tools/index.js +77 -0
- package/dist/commands/agents/unmute.d.ts +16 -0
- package/dist/commands/agents/unmute.js +38 -0
- package/dist/commands/agents/unpin.d.ts +16 -0
- package/dist/commands/agents/unpin.js +38 -0
- package/dist/commands/agents/update.d.ts +12 -0
- package/dist/commands/agents/update.js +74 -3
- package/dist/commands/code/{oversky-agent.d.ts → skrr-agent.d.ts} +3 -3
- package/dist/commands/code/{oversky-agent.js → skrr-agent.js} +11 -8
- package/dist/commands/convos/messages.d.ts +13 -0
- package/dist/commands/convos/messages.js +40 -16
- package/dist/commands/daemon/index.js +8 -1
- package/dist/commands/daemon/logs.d.ts +26 -0
- package/dist/commands/daemon/logs.js +56 -0
- package/dist/commands/daemon/uninstall.js +1 -1
- package/dist/commands/followups/act.d.ts +22 -0
- package/dist/commands/followups/act.js +103 -0
- package/dist/commands/followups/cancel.d.ts +20 -0
- package/dist/commands/followups/cancel.js +50 -0
- package/dist/commands/followups/checkin.d.ts +27 -0
- package/dist/commands/followups/checkin.js +107 -0
- package/dist/commands/followups/list.d.ts +24 -0
- package/dist/commands/followups/list.js +90 -0
- package/dist/commands/followups/observability.d.ts +23 -0
- package/dist/commands/followups/observability.js +114 -0
- package/dist/commands/followups/remind.d.ts +26 -0
- package/dist/commands/followups/remind.js +106 -0
- package/dist/commands/followups/reschedule.d.ts +15 -0
- package/dist/commands/followups/reschedule.js +48 -0
- package/dist/commands/followups/resolve.d.ts +23 -0
- package/dist/commands/followups/resolve.js +54 -0
- package/dist/commands/followups/show.d.ts +12 -0
- package/dist/commands/followups/show.js +46 -0
- package/dist/commands/followups/watch.d.ts +51 -0
- package/dist/commands/followups/watch.js +211 -0
- package/dist/commands/goals/labels/add.js +19 -2
- package/dist/commands/goals/labels/remove.js +22 -2
- package/dist/commands/harnesses/forget.js +28 -0
- package/dist/commands/harnesses/install.d.ts +41 -0
- package/dist/commands/harnesses/install.js +165 -0
- package/dist/commands/harnesses/installers.d.ts +45 -0
- package/dist/commands/harnesses/installers.js +155 -0
- package/dist/commands/harnesses/list.d.ts +82 -1
- package/dist/commands/harnesses/list.js +104 -12
- package/dist/commands/harnesses/models.js +10 -1
- package/dist/commands/harnesses/show.d.ts +15 -0
- package/dist/commands/harnesses/show.js +44 -3
- package/dist/commands/harnesses/update.js +1 -1
- package/dist/commands/harnesses/usage.d.ts +25 -0
- package/dist/commands/harnesses/usage.js +24 -2
- package/dist/commands/instructions/status.js +13 -1
- package/dist/commands/labels/list.d.ts +24 -1
- package/dist/commands/labels/list.js +62 -19
- package/dist/commands/machines/dedicated/catalog.js +4 -15
- package/dist/commands/machines/dedicated/create.d.ts +8 -0
- package/dist/commands/machines/dedicated/create.js +58 -1
- package/dist/commands/machines/dedicated/destroy.js +18 -4
- package/dist/commands/machines/dedicated/list.js +9 -6
- package/dist/commands/machines/hosted/list.js +12 -0
- package/dist/commands/machines/list.js +11 -0
- package/dist/commands/machines/show.d.ts +1 -0
- package/dist/commands/machines/show.js +40 -11
- package/dist/commands/memory/governance/index.d.ts +21 -0
- package/dist/commands/memory/governance/index.js +64 -0
- package/dist/commands/memory/governance/set.d.ts +24 -0
- package/dist/commands/memory/governance/set.js +95 -0
- package/dist/commands/memory/provenance.d.ts +18 -0
- package/dist/commands/memory/provenance.js +66 -0
- package/dist/commands/profiles/list.d.ts +23 -0
- package/dist/commands/profiles/list.js +96 -0
- package/dist/commands/search/skills.d.ts +11 -1
- package/dist/commands/search/skills.js +26 -8
- package/dist/commands/skills/details.d.ts +2 -0
- package/dist/commands/skills/details.js +24 -1
- package/dist/commands/skills/import-as-actions.d.ts +32 -0
- package/dist/commands/skills/import-as-actions.js +175 -0
- package/dist/commands/skills/install.d.ts +2 -0
- package/dist/commands/skills/install.js +24 -1
- package/dist/commands/skills/invocable.js +6 -2
- package/dist/commands/skills/local.d.ts +40 -0
- package/dist/commands/skills/local.js +160 -0
- package/dist/commands/skills/search.d.ts +11 -1
- package/dist/commands/skills/search.js +29 -8
- package/dist/commands/spaces/actions/add.js +23 -5
- package/dist/commands/spaces/actions/available.js +3 -0
- package/dist/commands/spaces/actions/list.d.ts +5 -0
- package/dist/commands/spaces/actions/list.js +49 -3
- package/dist/commands/spaces/actions/run.d.ts +28 -0
- package/dist/commands/spaces/actions/run.js +146 -0
- package/dist/commands/spaces/actions/update.js +27 -5
- package/dist/commands/spaces/create.d.ts +3 -0
- package/dist/commands/spaces/create.js +32 -2
- package/dist/commands/spaces/label-summaries.d.ts +27 -0
- package/dist/commands/spaces/label-summaries.js +64 -0
- package/dist/commands/spaces/labels/add.js +19 -2
- package/dist/commands/spaces/labels/remove.js +22 -2
- package/dist/commands/spaces/show.js +2 -0
- package/dist/commands/spaces/task-rollups.d.ts +5 -0
- package/dist/commands/spaces/task-rollups.js +15 -4
- package/dist/commands/spaces/update.d.ts +5 -0
- package/dist/commands/spaces/update.js +41 -4
- package/dist/commands/spaces/workflows/lifecycle-diagnostics.d.ts +11 -0
- package/dist/commands/spaces/workflows/lifecycle-diagnostics.js +105 -0
- package/dist/commands/tasks/actions/attach.js +32 -7
- package/dist/commands/tasks/complete.d.ts +1 -0
- package/dist/commands/tasks/complete.js +21 -1
- package/dist/commands/tasks/create.d.ts +3 -0
- package/dist/commands/tasks/create.js +34 -2
- package/dist/commands/tasks/events/append.js +29 -6
- package/dist/commands/tasks/expectations/assess.d.ts +12 -0
- package/dist/commands/tasks/expectations/assess.js +123 -14
- package/dist/commands/tasks/expectations.js +95 -17
- package/dist/commands/tasks/follow-up.js +2 -2
- package/dist/commands/tasks/labels/attach.js +20 -3
- package/dist/commands/tasks/labels/detach.js +21 -3
- package/dist/commands/tasks/lifecycle/attach.d.ts +14 -0
- package/dist/commands/tasks/lifecycle/attach.js +47 -0
- package/dist/commands/tasks/lifecycle/definitions.d.ts +11 -0
- package/dist/commands/tasks/lifecycle/definitions.js +59 -0
- package/dist/commands/tasks/lifecycle/detach.d.ts +19 -0
- package/dist/commands/tasks/lifecycle/detach.js +72 -0
- package/dist/commands/tasks/lifecycle/history.d.ts +13 -0
- package/dist/commands/tasks/lifecycle/history.js +38 -0
- package/dist/commands/tasks/lifecycle/migrate.d.ts +14 -0
- package/dist/commands/tasks/lifecycle/migrate.js +68 -0
- package/dist/commands/tasks/lifecycle/reconcile.d.ts +11 -0
- package/dist/commands/tasks/lifecycle/reconcile.js +27 -0
- package/dist/commands/tasks/lifecycle/reopen.d.ts +15 -0
- package/dist/commands/tasks/lifecycle/reopen.js +71 -0
- package/dist/commands/tasks/lifecycle/show.d.ts +11 -0
- package/dist/commands/tasks/lifecycle/show.js +27 -0
- package/dist/commands/tasks/lifecycle/start.d.ts +12 -0
- package/dist/commands/tasks/lifecycle/start.js +30 -0
- package/dist/commands/tasks/lifecycle/transition.d.ts +15 -0
- package/dist/commands/tasks/lifecycle/transition.js +109 -0
- package/dist/commands/tasks/list.js +16 -9
- package/dist/commands/tasks/move.d.ts +1 -0
- package/dist/commands/tasks/move.js +29 -0
- package/dist/commands/tasks/result/submit.js +11 -1
- package/dist/commands/tasks/review-queue.d.ts +44 -0
- package/dist/commands/tasks/review-queue.js +314 -0
- package/dist/commands/tasks/show.d.ts +11 -0
- package/dist/commands/tasks/show.js +139 -4
- package/dist/commands/tasks/trust.js +7 -2
- package/dist/commands/tasks/update.d.ts +1 -0
- package/dist/commands/tasks/update.js +83 -0
- package/dist/commands/tasks/updates/add.js +1 -1
- package/dist/commands/token/list.d.ts +22 -0
- package/dist/commands/token/list.js +68 -0
- package/dist/commands/token/revoke.d.ts +23 -0
- package/dist/commands/token/revoke.js +53 -0
- package/dist/lib/agent-actions.d.ts +92 -11
- package/dist/lib/agent-actions.js +171 -25
- package/dist/lib/agent-config.d.ts +11 -0
- package/dist/lib/agent-config.js +85 -3
- package/dist/lib/agent-pin-mute.d.ts +29 -0
- package/dist/lib/agent-pin-mute.js +30 -0
- package/dist/lib/agent-visual-refs.d.ts +33 -0
- package/dist/lib/agent-visual-refs.js +267 -0
- package/dist/lib/agentic-stream.d.ts +6 -0
- package/dist/lib/agentic-stream.js +34 -3
- package/dist/lib/assignee-resolver.d.ts +1 -1
- package/dist/lib/assignee-resolver.js +8 -0
- package/dist/lib/bulk-task-targets.d.ts +12 -0
- package/dist/lib/bulk-task-targets.js +34 -1
- package/dist/lib/cli-installers.d.ts +130 -0
- package/dist/lib/cli-installers.js +145 -0
- package/dist/lib/command-miss.js +55 -7
- package/dist/lib/dedicated-lease-command.d.ts +13 -0
- package/dist/lib/dedicated-lease-command.js +22 -1
- package/dist/lib/dedicated-machines.d.ts +95 -1
- package/dist/lib/dedicated-machines.js +236 -2
- package/dist/lib/failed-lookup.d.ts +3 -0
- package/dist/lib/failed-lookup.js +40 -0
- package/dist/lib/first-party-harness-agent.js +16 -2
- package/dist/lib/first-party-harness-doctor.d.ts +15 -0
- package/dist/lib/first-party-harness-doctor.js +126 -27
- package/dist/lib/followups.d.ts +115 -0
- package/dist/lib/followups.js +127 -0
- package/dist/lib/harnesses.d.ts +8 -0
- package/dist/lib/instruction-input.d.ts +19 -1
- package/dist/lib/instruction-input.js +52 -1
- package/dist/lib/label-ref.d.ts +95 -0
- package/dist/lib/label-ref.js +163 -0
- package/dist/lib/label-scope.d.ts +17 -2
- package/dist/lib/label-scope.js +27 -7
- package/dist/lib/local-skills.d.ts +98 -0
- package/dist/lib/local-skills.js +195 -0
- package/dist/lib/machines.d.ts +10 -10
- package/dist/lib/machines.js +23 -1
- package/dist/lib/search-query.d.ts +19 -0
- package/dist/lib/search-query.js +35 -0
- package/dist/lib/space-custom-actions.d.ts +72 -0
- package/dist/lib/space-custom-actions.js +117 -0
- package/dist/lib/space-resolver.d.ts +1 -21
- package/dist/lib/space-resolver.js +19 -10
- package/dist/lib/task-closure.d.ts +33 -0
- package/dist/lib/task-closure.js +104 -0
- package/dist/lib/task-lifecycle-output.d.ts +14 -0
- package/dist/lib/task-lifecycle-output.js +209 -0
- package/dist/lib/task-ref-resolver.d.ts +1 -17
- package/dist/lib/task-ref-resolver.js +18 -8
- package/dist/lib/tasks.d.ts +3 -0
- package/dist/lib/tasks.js +40 -3
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/harnessTrust.js +4 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/harnessTrust.js +4 -0
- package/dist/node_modules/@skrr-ai/auth-core/package.json +1 -1
- package/dist/node_modules/@skrr-ai/data-provider/index.js +5559 -4897
- package/oclif.manifest.json +33890 -28690
- package/package.json +24 -6
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { BaseCommand } from '../../base-command';
|
|
2
|
+
/**
|
|
3
|
+
* `skrr followups resolve <id>` — settle with the honest outcome.
|
|
4
|
+
*
|
|
5
|
+
* Distinct from `cancel` on purpose: "the thing I was waiting for happened"
|
|
6
|
+
* (`resolved`) and "never mind" (`abandoned`) are different facts, and a
|
|
7
|
+
* system that cannot tell them apart cannot tell a working watch from a
|
|
8
|
+
* pointless one. The runtime's own terminals (expired/exhausted/escalated)
|
|
9
|
+
* are not accepted here.
|
|
10
|
+
*/
|
|
11
|
+
export default class FollowupsResolve extends BaseCommand {
|
|
12
|
+
static description: string;
|
|
13
|
+
static examples: string[];
|
|
14
|
+
static args: {
|
|
15
|
+
id: import("@oclif/core/lib/interfaces").Arg<string, Record<string, unknown>>;
|
|
16
|
+
};
|
|
17
|
+
static flags: {
|
|
18
|
+
outcome: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
19
|
+
note: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
20
|
+
json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
21
|
+
};
|
|
22
|
+
run(): Promise<void>;
|
|
23
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const core_1 = require("@oclif/core");
|
|
4
|
+
const base_command_1 = require("../../base-command");
|
|
5
|
+
const followups_1 = require("../../lib/followups");
|
|
6
|
+
/**
|
|
7
|
+
* `skrr followups resolve <id>` — settle with the honest outcome.
|
|
8
|
+
*
|
|
9
|
+
* Distinct from `cancel` on purpose: "the thing I was waiting for happened"
|
|
10
|
+
* (`resolved`) and "never mind" (`abandoned`) are different facts, and a
|
|
11
|
+
* system that cannot tell them apart cannot tell a working watch from a
|
|
12
|
+
* pointless one. The runtime's own terminals (expired/exhausted/escalated)
|
|
13
|
+
* are not accepted here.
|
|
14
|
+
*/
|
|
15
|
+
class FollowupsResolve extends base_command_1.BaseCommand {
|
|
16
|
+
static description = 'Settle a follow-up with its honest outcome — resolved (it paid off) or abandoned (never mind; `cancel` is the shortcut)';
|
|
17
|
+
static examples = [
|
|
18
|
+
'<%= config.bin %> followups resolve fu_abc --outcome resolved --note "the deploy landed"',
|
|
19
|
+
'<%= config.bin %> followups resolve fu_abc --outcome abandoned --note "no longer needed"',
|
|
20
|
+
];
|
|
21
|
+
static args = {
|
|
22
|
+
id: followups_1.followUpIdArg,
|
|
23
|
+
};
|
|
24
|
+
static flags = {
|
|
25
|
+
outcome: core_1.Flags.string({
|
|
26
|
+
description: 'How it ended',
|
|
27
|
+
options: [...followups_1.FOLLOWUP_RESOLVE_OUTCOMES],
|
|
28
|
+
required: true,
|
|
29
|
+
}),
|
|
30
|
+
note: core_1.Flags.string({ description: 'What happened, for the audit' }),
|
|
31
|
+
json: core_1.Flags.boolean({ description: 'Output as JSON' }),
|
|
32
|
+
};
|
|
33
|
+
async run() {
|
|
34
|
+
this.requireAuth();
|
|
35
|
+
const { args, flags } = await this.parse(FollowupsResolve);
|
|
36
|
+
let result;
|
|
37
|
+
try {
|
|
38
|
+
result = (await followups_1.followupsApi.resolve(args.id, {
|
|
39
|
+
outcome: flags.outcome,
|
|
40
|
+
...(flags.note ? { note: flags.note } : {}),
|
|
41
|
+
}));
|
|
42
|
+
}
|
|
43
|
+
catch (err) {
|
|
44
|
+
this.handleApiError(err);
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
if (flags.json) {
|
|
48
|
+
this.log(JSON.stringify(result, null, 2));
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
this.log(`Follow-up ${args.id} settled: ${flags.outcome}.`);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
exports.default = FollowupsResolve;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { BaseCommand } from '../../base-command';
|
|
2
|
+
/** `skrr followups show <id>` — one follow-up, the same shape as the list rows. */
|
|
3
|
+
export default class FollowupsShow extends BaseCommand {
|
|
4
|
+
static description: string;
|
|
5
|
+
static args: {
|
|
6
|
+
id: import("@oclif/core/lib/interfaces").Arg<string, Record<string, unknown>>;
|
|
7
|
+
};
|
|
8
|
+
static flags: {
|
|
9
|
+
json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
10
|
+
};
|
|
11
|
+
run(): Promise<void>;
|
|
12
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const core_1 = require("@oclif/core");
|
|
4
|
+
const base_command_1 = require("../../base-command");
|
|
5
|
+
const followups_1 = require("../../lib/followups");
|
|
6
|
+
/** `skrr followups show <id>` — one follow-up, the same shape as the list rows. */
|
|
7
|
+
class FollowupsShow extends base_command_1.BaseCommand {
|
|
8
|
+
static description = 'Show one follow-up';
|
|
9
|
+
static args = {
|
|
10
|
+
id: followups_1.followUpIdArg,
|
|
11
|
+
};
|
|
12
|
+
static flags = {
|
|
13
|
+
json: core_1.Flags.boolean({ description: 'Output as JSON' }),
|
|
14
|
+
};
|
|
15
|
+
async run() {
|
|
16
|
+
this.requireAuth();
|
|
17
|
+
const { args, flags } = await this.parse(FollowupsShow);
|
|
18
|
+
let response;
|
|
19
|
+
try {
|
|
20
|
+
response = await followups_1.followupsApi.show(args.id);
|
|
21
|
+
}
|
|
22
|
+
catch (err) {
|
|
23
|
+
this.handleApiError(err);
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
if (flags.json) {
|
|
27
|
+
this.log(JSON.stringify(response, null, 2));
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
const row = response.followup;
|
|
31
|
+
this.log((0, followups_1.followupSummaryLine)(row));
|
|
32
|
+
for (const [label, value] of [
|
|
33
|
+
['says', row.content],
|
|
34
|
+
['why', row.why],
|
|
35
|
+
['intent', row.intentKey],
|
|
36
|
+
['producer', row.producer],
|
|
37
|
+
['terminal', row.terminal ? `${row.terminal} (${row.terminalReason ?? '—'})` : undefined],
|
|
38
|
+
['deadline', row.deadlineAt],
|
|
39
|
+
['escalated to', row.escalatedInitiativeId],
|
|
40
|
+
]) {
|
|
41
|
+
if (value)
|
|
42
|
+
this.log(` ${label}: ${value}`);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
exports.default = FollowupsShow;
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { BaseCommand } from '../../base-command';
|
|
2
|
+
/**
|
|
3
|
+
* `skrr followups watch` — a `watch` follow-up: keep an eye on an
|
|
4
|
+
* asynchronous tail until a condition settles or a stop fires.
|
|
5
|
+
*
|
|
6
|
+
* Two forms, matching the service vocabulary exactly:
|
|
7
|
+
*
|
|
8
|
+
* predicate `--url` + `--until <json>` — a machine-settled observation of
|
|
9
|
+
* an HTTPS endpoint. Free (no agent turn per check), termination
|
|
10
|
+
* guaranteed by `--deadline`. Prefer this when the thing watched
|
|
11
|
+
* is a URL whose response can answer the question.
|
|
12
|
+
* recipe `--check` + `--success` + `--abort` + `--wait <kind>` — a
|
|
13
|
+
* deterministic check a future agent turn runs. One turn per
|
|
14
|
+
* check; the abort criterion is mandatory because a watch that
|
|
15
|
+
* cannot stop is a leak.
|
|
16
|
+
*/
|
|
17
|
+
export default class FollowupsWatch extends BaseCommand {
|
|
18
|
+
static description: string;
|
|
19
|
+
static examples: string[];
|
|
20
|
+
static flags: {
|
|
21
|
+
subject: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
22
|
+
why: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
23
|
+
agent: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
24
|
+
url: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
25
|
+
until: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
26
|
+
grant: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
27
|
+
deadline: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
28
|
+
'check-every': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
29
|
+
'max-checks': import("@oclif/core/lib/interfaces").OptionFlag<number | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
30
|
+
'root-path': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
31
|
+
'resume-prompt': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
32
|
+
check: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
33
|
+
success: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
34
|
+
abort: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
35
|
+
wait: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
36
|
+
'wait-at': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
37
|
+
'wait-entity': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
38
|
+
'wait-event': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
39
|
+
'wait-filter-field': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
40
|
+
'wait-filter-mode': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
41
|
+
'wait-filter-value': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
42
|
+
'wait-interval-seconds': import("@oclif/core/lib/interfaces").OptionFlag<number | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
43
|
+
'wait-max-attempts': import("@oclif/core/lib/interfaces").OptionFlag<number | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
44
|
+
'wait-fallback': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
45
|
+
endpoint: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
46
|
+
'endpoint-target': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
47
|
+
pin: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
48
|
+
json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
49
|
+
};
|
|
50
|
+
run(): Promise<void>;
|
|
51
|
+
}
|
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const core_1 = require("@oclif/core");
|
|
4
|
+
const base_command_1 = require("../../base-command");
|
|
5
|
+
const followups_1 = require("../../lib/followups");
|
|
6
|
+
const agent_resolver_1 = require("../../lib/agent-resolver");
|
|
7
|
+
const triggers_1 = require("../../lib/triggers");
|
|
8
|
+
/**
|
|
9
|
+
* `skrr followups watch` — a `watch` follow-up: keep an eye on an
|
|
10
|
+
* asynchronous tail until a condition settles or a stop fires.
|
|
11
|
+
*
|
|
12
|
+
* Two forms, matching the service vocabulary exactly:
|
|
13
|
+
*
|
|
14
|
+
* predicate `--url` + `--until <json>` — a machine-settled observation of
|
|
15
|
+
* an HTTPS endpoint. Free (no agent turn per check), termination
|
|
16
|
+
* guaranteed by `--deadline`. Prefer this when the thing watched
|
|
17
|
+
* is a URL whose response can answer the question.
|
|
18
|
+
* recipe `--check` + `--success` + `--abort` + `--wait <kind>` — a
|
|
19
|
+
* deterministic check a future agent turn runs. One turn per
|
|
20
|
+
* check; the abort criterion is mandatory because a watch that
|
|
21
|
+
* cannot stop is a leak.
|
|
22
|
+
*/
|
|
23
|
+
class FollowupsWatch extends base_command_1.BaseCommand {
|
|
24
|
+
static description = 'Watch an asynchronous tail until it settles — the watch follow-up';
|
|
25
|
+
static examples = [
|
|
26
|
+
'<%= config.bin %> followups watch --subject task:OSK-42 --why "deploy still running" --url https://ci.example.com/api/build/9 --until \'{"path":"status","op":"equals","value":"done"}\' --deadline 6h',
|
|
27
|
+
'<%= config.bin %> followups watch --subject task:OSK-42 --why "pr review" --check "gh pr view 42 --json state" --success "state == MERGED" --abort "state == CLOSED" --wait event --wait-entity github --wait-event pull_request_merged --wait-fallback 2h',
|
|
28
|
+
'<%= config.bin %> followups watch --subject conversation:abc --why "vendor reply" --check "check inbox" --success "reply arrived" --abort "3 days" --wait clock --wait-at 2026-09-20T09:00:00Z',
|
|
29
|
+
];
|
|
30
|
+
static flags = {
|
|
31
|
+
subject: core_1.Flags.string({ description: 'Subject ref: type:externalKey', required: true }),
|
|
32
|
+
why: core_1.Flags.string({ description: 'Why this watch exists, in one line', required: true }),
|
|
33
|
+
agent: core_1.Flags.string({ description: 'Agent ID (default: bound session agent)' }),
|
|
34
|
+
// predicate form
|
|
35
|
+
url: core_1.Flags.string({ description: 'HTTPS endpoint to observe (predicate form)' }),
|
|
36
|
+
until: core_1.Flags.string({
|
|
37
|
+
description: 'Predicate tree as JSON (predicate form): a leaf {"path","op","value"} or {"all"|"any": [...]}. op is equals, not_equals, contains, starts_with, in, gt, lt, exists, … — an unknown op is refused with the full list',
|
|
38
|
+
}),
|
|
39
|
+
grant: core_1.Flags.string({ description: 'Grant id supplying the watch credentials' }),
|
|
40
|
+
deadline: core_1.Flags.string({ description: 'When the watch must stop (predicate form, required)' }),
|
|
41
|
+
'check-every': core_1.Flags.string({ description: 'Observation interval (predicate form)' }),
|
|
42
|
+
'max-checks': core_1.Flags.integer({ description: 'Observation cap (predicate form)' }),
|
|
43
|
+
'root-path': core_1.Flags.string({ description: 'JSON root path inside the response' }),
|
|
44
|
+
'resume-prompt': core_1.Flags.string({ description: 'What to tell the settling turn' }),
|
|
45
|
+
// recipe form
|
|
46
|
+
check: core_1.Flags.string({ description: 'The deterministic check to run (recipe form)' }),
|
|
47
|
+
success: core_1.Flags.string({ description: 'What state means the wait resolved (recipe form)' }),
|
|
48
|
+
abort: core_1.Flags.string({ description: 'When to stop and escalate (recipe form)' }),
|
|
49
|
+
wait: core_1.Flags.string({
|
|
50
|
+
description: 'Wait kind (recipe form)',
|
|
51
|
+
options: [...followups_1.WATCH_WAIT_KINDS],
|
|
52
|
+
}),
|
|
53
|
+
'wait-at': core_1.Flags.string({ description: 'Instant/duration for --wait clock' }),
|
|
54
|
+
'wait-entity': core_1.Flags.string({ description: 'Entity type for --wait event' }),
|
|
55
|
+
'wait-event': core_1.Flags.string({ description: 'Event type for --wait event' }),
|
|
56
|
+
'wait-filter-field': core_1.Flags.string({ description: 'Payload field for an event filter' }),
|
|
57
|
+
'wait-filter-mode': core_1.Flags.string({
|
|
58
|
+
description: 'Event filter mode',
|
|
59
|
+
options: ['equals', 'contains', 'in_set'],
|
|
60
|
+
}),
|
|
61
|
+
'wait-filter-value': core_1.Flags.string({ description: 'Event filter value' }),
|
|
62
|
+
'wait-interval-seconds': core_1.Flags.integer({ description: 'Poll interval for --wait poll_until' }),
|
|
63
|
+
'wait-max-attempts': core_1.Flags.integer({ description: 'Attempt cap for --wait poll_until' }),
|
|
64
|
+
'wait-fallback': core_1.Flags.string({
|
|
65
|
+
description: 'SLA backstop — required for --wait event (an event may never arrive), optional for poll_until',
|
|
66
|
+
}),
|
|
67
|
+
// delivery
|
|
68
|
+
endpoint: core_1.Flags.string({ description: 'Delivery endpoint id (EndpointRegistry)' }),
|
|
69
|
+
'endpoint-target': core_1.Flags.string({ description: 'Channel target for channel endpoints' }),
|
|
70
|
+
pin: core_1.Flags.string({ description: 'Conversation id the watch was authored in' }),
|
|
71
|
+
json: core_1.Flags.boolean({ description: 'Output as JSON' }),
|
|
72
|
+
};
|
|
73
|
+
async run() {
|
|
74
|
+
this.requireAuth();
|
|
75
|
+
const { flags } = await this.parse(FollowupsWatch);
|
|
76
|
+
let agent;
|
|
77
|
+
try {
|
|
78
|
+
agent = (0, followups_1.resolveFollowUpAgent)(flags.agent);
|
|
79
|
+
}
|
|
80
|
+
catch (err) {
|
|
81
|
+
const failure = (0, agent_resolver_1.agentResolutionFailure)(err);
|
|
82
|
+
this.failWithCliError({
|
|
83
|
+
message: failure.message,
|
|
84
|
+
code: failure.code,
|
|
85
|
+
exit: 2,
|
|
86
|
+
retryable: false,
|
|
87
|
+
details: { suggestion: failure.suggestion, context: failure.details },
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
const predicate = flags.url !== undefined || flags.until !== undefined;
|
|
91
|
+
const recipe = flags.check !== undefined || flags.success !== undefined || flags.abort !== undefined;
|
|
92
|
+
if (predicate && recipe) {
|
|
93
|
+
this.failWithCliError({
|
|
94
|
+
message: 'Predicate and recipe flags cannot mix. A watch is either an observed URL (--url/--until) or a checked recipe (--check/--success/--abort/--wait).',
|
|
95
|
+
code: 'FOLLOWUP_INVALID_FORM',
|
|
96
|
+
exit: 2,
|
|
97
|
+
retryable: false,
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
if (!predicate && !recipe) {
|
|
101
|
+
this.failWithCliError({
|
|
102
|
+
message: 'A watch needs a form: --url + --until for a predicate watch, or --check + --success + --abort + --wait for a recipe watch.',
|
|
103
|
+
code: 'FOLLOWUP_INVALID_FORM',
|
|
104
|
+
exit: 2,
|
|
105
|
+
retryable: false,
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
const body = {
|
|
109
|
+
kind: 'watch',
|
|
110
|
+
producer: agent.boundToSession ? 'agent_in_turn' : 'user_explicit',
|
|
111
|
+
agentId: agent.id,
|
|
112
|
+
subject: (0, followups_1.parseSubjectRef)(flags.subject),
|
|
113
|
+
why: flags.why,
|
|
114
|
+
...(flags.endpoint ? { endpointId: flags.endpoint } : {}),
|
|
115
|
+
...(flags['endpoint-target'] ? { endpointTarget: flags['endpoint-target'] } : {}),
|
|
116
|
+
...(flags.pin ? { pinnedConversationId: flags.pin } : {}),
|
|
117
|
+
};
|
|
118
|
+
if (predicate) {
|
|
119
|
+
if (!flags.url || !flags.until) {
|
|
120
|
+
this.failWithCliError({
|
|
121
|
+
message: 'A predicate watch needs both --url <https> and --until <predicate-json>.',
|
|
122
|
+
code: 'FOLLOWUP_KIND_FIELD_MISSING',
|
|
123
|
+
exit: 2,
|
|
124
|
+
retryable: false,
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
if (!flags.deadline) {
|
|
128
|
+
this.failWithCliError({
|
|
129
|
+
message: '--deadline is required — a watch that cannot stop is a leak.',
|
|
130
|
+
code: 'FOLLOWUP_KIND_FIELD_MISSING',
|
|
131
|
+
exit: 2,
|
|
132
|
+
retryable: false,
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
Object.assign(body, {
|
|
136
|
+
form: 'predicate',
|
|
137
|
+
url: flags.url,
|
|
138
|
+
until: (0, triggers_1.parseJsonObject)(flags.until, '--until'),
|
|
139
|
+
grantId: flags.grant,
|
|
140
|
+
deadline: flags.deadline,
|
|
141
|
+
checkEvery: flags['check-every'],
|
|
142
|
+
maxChecks: flags['max-checks'],
|
|
143
|
+
rootPath: flags['root-path'],
|
|
144
|
+
resumePrompt: flags['resume-prompt'],
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
else {
|
|
148
|
+
for (const field of ['check', 'success', 'abort', 'wait']) {
|
|
149
|
+
if (!flags[field]) {
|
|
150
|
+
this.failWithCliError({
|
|
151
|
+
message: `A recipe watch needs --${field}.`,
|
|
152
|
+
code: 'FOLLOWUP_KIND_FIELD_MISSING',
|
|
153
|
+
exit: 2,
|
|
154
|
+
retryable: false,
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
const wait = { kind: flags.wait };
|
|
159
|
+
if (flags.wait === 'clock') {
|
|
160
|
+
wait.at = flags['wait-at'];
|
|
161
|
+
}
|
|
162
|
+
else if (flags.wait === 'event') {
|
|
163
|
+
Object.assign(wait, {
|
|
164
|
+
entityType: flags['wait-entity'],
|
|
165
|
+
eventType: flags['wait-event'],
|
|
166
|
+
filterField: flags['wait-filter-field'],
|
|
167
|
+
filterMode: flags['wait-filter-mode'],
|
|
168
|
+
filterValue: flags['wait-filter-value'],
|
|
169
|
+
fallback: flags['wait-fallback'],
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
else {
|
|
173
|
+
Object.assign(wait, {
|
|
174
|
+
intervalSeconds: flags['wait-interval-seconds'],
|
|
175
|
+
maxAttempts: flags['wait-max-attempts'],
|
|
176
|
+
fallback: flags['wait-fallback'],
|
|
177
|
+
});
|
|
178
|
+
}
|
|
179
|
+
Object.assign(body, {
|
|
180
|
+
form: 'recipe',
|
|
181
|
+
check: flags.check,
|
|
182
|
+
success: flags.success,
|
|
183
|
+
abort: flags.abort,
|
|
184
|
+
wait,
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
let response;
|
|
188
|
+
try {
|
|
189
|
+
response = await followups_1.followupsApi.create(body);
|
|
190
|
+
}
|
|
191
|
+
catch (err) {
|
|
192
|
+
this.handleApiError(err);
|
|
193
|
+
return;
|
|
194
|
+
}
|
|
195
|
+
if (flags.json) {
|
|
196
|
+
this.log(JSON.stringify(response, null, 2));
|
|
197
|
+
return;
|
|
198
|
+
}
|
|
199
|
+
const row = response.followup;
|
|
200
|
+
if (response.reused) {
|
|
201
|
+
this.log(`Already armed: ${row?.id} — an identical watch exists and was not duplicated.`);
|
|
202
|
+
return;
|
|
203
|
+
}
|
|
204
|
+
if (response.dropped) {
|
|
205
|
+
this.log('Dropped by the daily watch budget — no watch was armed.');
|
|
206
|
+
return;
|
|
207
|
+
}
|
|
208
|
+
this.log(`Watch armed: ${row?.id}${row?.deadlineAt ? `, deadline ${row.deadlineAt}` : ''}.`);
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
exports.default = FollowupsWatch;
|
|
@@ -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 label_ref_1 = require("../../../lib/label-ref");
|
|
6
7
|
class GoalsLabelsAdd extends base_command_1.BaseCommand {
|
|
7
8
|
static description = 'Attach a label to a goal';
|
|
8
9
|
static examples = [
|
|
@@ -15,7 +16,7 @@ class GoalsLabelsAdd extends base_command_1.BaseCommand {
|
|
|
15
16
|
static flags = {
|
|
16
17
|
json: core_1.Flags.boolean({ description: 'Output the updated goal as JSON' }),
|
|
17
18
|
label: core_1.Flags.string({
|
|
18
|
-
description: 'Label
|
|
19
|
+
description: 'Label — id, or a name from `skrr labels list --applicable-to goal`. An unknown name is refused, never created.',
|
|
19
20
|
required: true,
|
|
20
21
|
}),
|
|
21
22
|
};
|
|
@@ -25,9 +26,25 @@ class GoalsLabelsAdd extends base_command_1.BaseCommand {
|
|
|
25
26
|
// `goals update` deliberately refuses labelIds — the server routes label
|
|
26
27
|
// changes through this atomic endpoint so exclusive-group eviction and
|
|
27
28
|
// usage counters stay correct. Re-attaching an attached label is a no-op.
|
|
29
|
+
// A name is resolved against the DECLARED vocabulary; an unknown one is
|
|
30
|
+
// refused with the near misses named, never created. See lib/label-ref.
|
|
31
|
+
let labelId = flags.label;
|
|
32
|
+
try {
|
|
33
|
+
[labelId] = await (0, label_ref_1.resolveLabelRefs)([flags.label], {
|
|
34
|
+
applicableTo: 'goal',
|
|
35
|
+
...(process.env.OVERSKY_WORKSPACE_ID
|
|
36
|
+
? { workspaceId: process.env.OVERSKY_WORKSPACE_ID }
|
|
37
|
+
: {}),
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
catch (err) {
|
|
41
|
+
if (err instanceof label_ref_1.LabelRefError)
|
|
42
|
+
this.error(err.message, { exit: 1 });
|
|
43
|
+
this.handleApiError(err);
|
|
44
|
+
}
|
|
28
45
|
let result;
|
|
29
46
|
try {
|
|
30
|
-
result = await data_provider_1.dataService.addLabelToGoal({ goalId: args.id, labelId
|
|
47
|
+
result = await data_provider_1.dataService.addLabelToGoal({ goalId: args.id, labelId });
|
|
31
48
|
}
|
|
32
49
|
catch (err) {
|
|
33
50
|
this.handleApiError(err);
|
|
@@ -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 label_ref_1 = require("../../../lib/label-ref");
|
|
6
7
|
class GoalsLabelsRemove extends base_command_1.BaseCommand {
|
|
7
8
|
static description = 'Detach a label from a goal';
|
|
8
9
|
static examples = [
|
|
@@ -14,16 +15,35 @@ class GoalsLabelsRemove extends base_command_1.BaseCommand {
|
|
|
14
15
|
};
|
|
15
16
|
static flags = {
|
|
16
17
|
json: core_1.Flags.boolean({ description: 'Output the updated goal as JSON' }),
|
|
17
|
-
label: core_1.Flags.string({
|
|
18
|
+
label: core_1.Flags.string({
|
|
19
|
+
description: 'Label — id, or a name from `skrr labels list --applicable-to goal`. An unknown name is refused, never created.',
|
|
20
|
+
required: true,
|
|
21
|
+
}),
|
|
18
22
|
};
|
|
19
23
|
async run() {
|
|
20
24
|
this.requireAuth();
|
|
21
25
|
const { args, flags } = await this.parse(GoalsLabelsRemove);
|
|
22
26
|
// Detach is intentionally permissive server-side: you can remove a label
|
|
23
27
|
// you can no longer read, so a revoked label never gets stuck on a goal.
|
|
28
|
+
// A name is resolved against the DECLARED vocabulary; an unknown one is
|
|
29
|
+
// refused with the near misses named, never created. See lib/label-ref.
|
|
30
|
+
let labelId = flags.label;
|
|
31
|
+
try {
|
|
32
|
+
[labelId] = await (0, label_ref_1.resolveLabelRefs)([flags.label], {
|
|
33
|
+
applicableTo: 'goal',
|
|
34
|
+
...(process.env.OVERSKY_WORKSPACE_ID
|
|
35
|
+
? { workspaceId: process.env.OVERSKY_WORKSPACE_ID }
|
|
36
|
+
: {}),
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
catch (err) {
|
|
40
|
+
if (err instanceof label_ref_1.LabelRefError)
|
|
41
|
+
this.error(err.message, { exit: 1 });
|
|
42
|
+
this.handleApiError(err);
|
|
43
|
+
}
|
|
24
44
|
let result;
|
|
25
45
|
try {
|
|
26
|
-
result = await data_provider_1.dataService.removeLabelFromGoal({ goalId: args.id, labelId
|
|
46
|
+
result = await data_provider_1.dataService.removeLabelFromGoal({ goalId: args.id, labelId });
|
|
27
47
|
}
|
|
28
48
|
catch (err) {
|
|
29
49
|
this.handleApiError(err);
|
|
@@ -3,6 +3,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
const core_1 = require("@oclif/core");
|
|
4
4
|
const base_command_1 = require("../../base-command");
|
|
5
5
|
const harnesses_1 = require("../../lib/harnesses");
|
|
6
|
+
const api_fetch_1 = require("../../lib/api-fetch");
|
|
7
|
+
const show_1 = require("./show");
|
|
6
8
|
/**
|
|
7
9
|
* Forget an harness — `forget`, not `delete`.
|
|
8
10
|
*
|
|
@@ -26,6 +28,24 @@ class HarnessesForget extends base_command_1.BaseCommand {
|
|
|
26
28
|
async run() {
|
|
27
29
|
this.requireAuth();
|
|
28
30
|
const { args, flags } = await this.parse(HarnessesForget);
|
|
31
|
+
// Refuse a reference that cannot name a harness BEFORE asking anything.
|
|
32
|
+
//
|
|
33
|
+
// The confirmation used to run first, so `harnesses forget notanid` asked
|
|
34
|
+
// whether to delete something that could never exist, and a scripted caller
|
|
35
|
+
// who added `--yes` to get past it then hit a second, different failure:
|
|
36
|
+
// a bare `Invalid harness ID / HTTP_400` from the server. Two round trips
|
|
37
|
+
// for one typo, on the command where a typo matters most.
|
|
38
|
+
//
|
|
39
|
+
// The sibling `harnesses show` already explains this class of mistake
|
|
40
|
+
// (`describeWrongHarnessRef` names which KIND of id you passed and which
|
|
41
|
+
// command takes it). `forget` is the DESTRUCTIVE one and had the worse
|
|
42
|
+
// message; it now shares the explanation.
|
|
43
|
+
if (!/^[0-9a-f]{24}$/i.test(args.harness.trim())) {
|
|
44
|
+
this.error(`Not a harness id: ${args.harness}\n${(0, show_1.describeWrongHarnessRef)(args.harness)}`, {
|
|
45
|
+
exit: 1,
|
|
46
|
+
});
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
29
49
|
// Name it before removing it. An id alone does not tell the operator which
|
|
30
50
|
// of their machines they are about to drop from the fleet.
|
|
31
51
|
if (!flags.yes) {
|
|
@@ -52,6 +72,14 @@ class HarnessesForget extends base_command_1.BaseCommand {
|
|
|
52
72
|
this.log(`Forgot ${args.harness}.`);
|
|
53
73
|
}
|
|
54
74
|
catch (err) {
|
|
75
|
+
// A well-formed id the server still rejects: say so in the same words
|
|
76
|
+
// `show` uses, rather than relaying `Invalid harness ID`.
|
|
77
|
+
if (err instanceof api_fetch_1.ApiFetchError && err.status === 400) {
|
|
78
|
+
this.error(`Not a harness id: ${args.harness}\n${(0, show_1.describeWrongHarnessRef)(args.harness)}`, {
|
|
79
|
+
exit: 1,
|
|
80
|
+
});
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
55
83
|
this.handleApiError(err);
|
|
56
84
|
}
|
|
57
85
|
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { BaseCommand } from '../../base-command';
|
|
2
|
+
/**
|
|
3
|
+
* Install one managed coding-agent CLI on a machine.
|
|
4
|
+
*
|
|
5
|
+
* ## Why this did not exist
|
|
6
|
+
*
|
|
7
|
+
* The daemon has installed any of seven providers since `d878b79581`, and
|
|
8
|
+
* `POST /api/daemons/:id/cli-installers/:provider/install` is the request the
|
|
9
|
+
* web app's Install button sends. From the CLI only ONE of them was reachable:
|
|
10
|
+
* `skrr code install`, whose provider is a constant. Everything else had to be
|
|
11
|
+
* installed by hand, or from the web app.
|
|
12
|
+
*
|
|
13
|
+
* `skrr harnesses install-token` made that worse rather than neutral. It is the
|
|
14
|
+
* only entry in `harnesses --help` with "install" in its name, so a user
|
|
15
|
+
* scanning for "how do I install a harness" lands on it — and it mints a daemon
|
|
16
|
+
* enrolment token for another machine, which is a different thing entirely.
|
|
17
|
+
*
|
|
18
|
+
* ## The provider name is validated here, against the shared vocabulary
|
|
19
|
+
*
|
|
20
|
+
* Unlike `harnesses list --provider`, where the set is open because a daemon
|
|
21
|
+
* registers a row per capability it detects, the INSTALLABLE set is closed and
|
|
22
|
+
* owned: `MANAGED_CLI_PROVIDER_IDS` in `@skrr-ai/data-provider`, which the
|
|
23
|
+
* daemon's own list is pinned against by `managedCliProviders.spec.ts`. So a
|
|
24
|
+
* typo can be rejected with the real options, rather than sent to the daemon to
|
|
25
|
+
* come back as an opaque refusal.
|
|
26
|
+
*/
|
|
27
|
+
export default class HarnessesInstall extends BaseCommand {
|
|
28
|
+
static description: string;
|
|
29
|
+
static examples: string[];
|
|
30
|
+
static args: {
|
|
31
|
+
provider: import("@oclif/core/lib/interfaces").Arg<string, Record<string, unknown>>;
|
|
32
|
+
};
|
|
33
|
+
static flags: {
|
|
34
|
+
json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
35
|
+
daemon: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
36
|
+
};
|
|
37
|
+
run(): Promise<void>;
|
|
38
|
+
/** What the daemon says about this provider right now, best effort. */
|
|
39
|
+
private installerNote;
|
|
40
|
+
private daemonIdFor;
|
|
41
|
+
}
|