@skrr-ai/cli 0.1.36 → 0.1.37
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/dist/commands/agents/actions/create.d.ts +5 -0
- package/dist/commands/agents/actions/create.js +26 -0
- package/dist/commands/agents/actions/update.d.ts +5 -0
- package/dist/commands/agents/actions/update.js +24 -0
- package/dist/commands/agents/api-actions/add.d.ts +41 -0
- package/dist/commands/agents/api-actions/add.js +202 -0
- package/dist/commands/agents/api-actions/index.d.ts +28 -0
- package/dist/commands/agents/api-actions/index.js +77 -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 +18 -0
- package/dist/commands/agents/avatar/default/index.js +44 -0
- package/dist/commands/agents/avatar/default/set.d.ts +23 -0
- package/dist/commands/agents/avatar/default/set.js +95 -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/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 +33 -0
- package/dist/commands/agents/categories/index.d.ts +20 -0
- package/dist/commands/agents/categories/index.js +82 -0
- package/dist/commands/agents/categories/update.d.ts +22 -0
- package/dist/commands/agents/categories/update.js +59 -0
- package/dist/commands/agents/create.d.ts +10 -0
- package/dist/commands/agents/create.js +57 -3
- package/dist/commands/agents/ensure-default.d.ts +27 -0
- package/dist/commands/agents/ensure-default.js +65 -0
- 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/tools/auth.d.ts +19 -0
- package/dist/commands/agents/tools/auth.js +41 -0
- package/dist/commands/agents/tools/calls.d.ts +18 -0
- package/dist/commands/agents/tools/calls.js +54 -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 +64 -3
- package/dist/commands/followups/act.d.ts +22 -0
- package/dist/commands/followups/act.js +102 -0
- package/dist/commands/followups/cancel.d.ts +17 -0
- package/dist/commands/followups/cancel.js +40 -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/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 +45 -0
- package/dist/commands/followups/watch.d.ts +51 -0
- package/dist/commands/followups/watch.js +207 -0
- package/dist/commands/goals/labels/add.js +19 -2
- package/dist/commands/goals/labels/remove.js +22 -2
- package/dist/commands/labels/list.d.ts +24 -1
- package/dist/commands/labels/list.js +62 -19
- 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/spaces/create.d.ts +3 -0
- package/dist/commands/spaces/create.js +32 -2
- 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/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 +45 -0
- package/dist/commands/tasks/complete.d.ts +1 -0
- package/dist/commands/tasks/complete.js +8 -1
- package/dist/commands/tasks/create.d.ts +3 -0
- package/dist/commands/tasks/create.js +34 -2
- package/dist/commands/tasks/expectations/assess.d.ts +11 -0
- package/dist/commands/tasks/expectations/assess.js +85 -14
- package/dist/commands/tasks/expectations.js +19 -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 +40 -0
- package/dist/commands/tasks/lifecycle/detach.d.ts +12 -0
- package/dist/commands/tasks/lifecycle/detach.js +32 -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 +12 -0
- package/dist/commands/tasks/lifecycle/migrate.js +29 -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 +13 -0
- package/dist/commands/tasks/lifecycle/reopen.js +34 -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 +78 -0
- package/dist/commands/tasks/move.d.ts +1 -0
- package/dist/commands/tasks/move.js +31 -0
- package/dist/commands/tasks/result/submit.js +11 -1
- package/dist/commands/tasks/review-queue.d.ts +29 -0
- package/dist/commands/tasks/review-queue.js +165 -0
- package/dist/commands/tasks/show.js +42 -0
- package/dist/commands/tasks/update.d.ts +1 -0
- package/dist/commands/tasks/update.js +47 -0
- package/dist/lib/agent-actions.d.ts +36 -10
- package/dist/lib/agent-actions.js +63 -9
- 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 +24 -0
- package/dist/lib/agent-pin-mute.js +17 -0
- package/dist/lib/agent-visual-refs.d.ts +6 -0
- package/dist/lib/agent-visual-refs.js +142 -0
- package/dist/lib/first-party-harness-agent.js +7 -0
- package/dist/lib/followups.d.ts +107 -0
- package/dist/lib/followups.js +102 -0
- package/dist/lib/label-ref.d.ts +95 -0
- package/dist/lib/label-ref.js +163 -0
- package/dist/lib/label-scope.d.ts +2 -2
- package/dist/lib/label-scope.js +3 -3
- package/dist/lib/task-closure.d.ts +32 -0
- package/dist/lib/task-closure.js +106 -0
- package/dist/lib/task-lifecycle-output.d.ts +14 -0
- package/dist/lib/task-lifecycle-output.js +101 -0
- package/dist/lib/tasks.d.ts +3 -0
- package/dist/lib/tasks.js +31 -0
- 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 +5079 -4546
- package/oclif.manifest.json +20216 -16002
- package/package.json +16 -4
|
@@ -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);
|
|
@@ -1,11 +1,34 @@
|
|
|
1
1
|
import { BaseCommand } from '../../base-command';
|
|
2
|
+
/**
|
|
3
|
+
* `labels list` — every label you can actually USE, by default.
|
|
4
|
+
*
|
|
5
|
+
* This used to default to `--scope user` and show one scope at a time, which
|
|
6
|
+
* is a faithful rendering of `GET /api/labels` and a poor answer to the
|
|
7
|
+
* question people ask. `scope` is an OWNERSHIP boundary, not a filter anyone
|
|
8
|
+
* browses by: a workspace-scoped label is attachable by every member, so
|
|
9
|
+
* leaving it out of the default view means the vocabulary you are told about
|
|
10
|
+
* is smaller than the one you have.
|
|
11
|
+
*
|
|
12
|
+
* It had a measurable cost. Three workspace-scoped labels existed and were
|
|
13
|
+
* invisible to the bare command, so nobody knew they were there — which is
|
|
14
|
+
* part of why the label system shipped complete and went unused, and why a
|
|
15
|
+
* second `dogfood` nearly got created beside one that already existed.
|
|
16
|
+
*
|
|
17
|
+
* `--scope` still narrows to exactly one scope, so every explicit invocation
|
|
18
|
+
* behaves as it always did. Only the bare command changed, and it changed to
|
|
19
|
+
* a superset.
|
|
20
|
+
*
|
|
21
|
+
* The merge itself is `lib/label-ref.collectLabelVocabulary` — the same
|
|
22
|
+
* function `--label <name>` resolves through. A separate copy here is how the
|
|
23
|
+
* name you can type and the name you can see start to disagree.
|
|
24
|
+
*/
|
|
2
25
|
export default class LabelsList extends BaseCommand {
|
|
3
26
|
static description: string;
|
|
4
27
|
static examples: string[];
|
|
5
28
|
static flags: {
|
|
29
|
+
scope: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
6
30
|
'applicable-to': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
7
31
|
'include-archived': import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
8
|
-
scope: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
9
32
|
'scope-id': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
10
33
|
json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
11
34
|
};
|
|
@@ -5,17 +5,48 @@ const data_provider_1 = require("@skrr-ai/data-provider");
|
|
|
5
5
|
const base_command_1 = require("../../base-command");
|
|
6
6
|
const format_1 = require("../../lib/format");
|
|
7
7
|
const label_scope_1 = require("../../lib/label-scope");
|
|
8
|
+
const label_ref_1 = require("../../lib/label-ref");
|
|
9
|
+
/**
|
|
10
|
+
* `labels list` — every label you can actually USE, by default.
|
|
11
|
+
*
|
|
12
|
+
* This used to default to `--scope user` and show one scope at a time, which
|
|
13
|
+
* is a faithful rendering of `GET /api/labels` and a poor answer to the
|
|
14
|
+
* question people ask. `scope` is an OWNERSHIP boundary, not a filter anyone
|
|
15
|
+
* browses by: a workspace-scoped label is attachable by every member, so
|
|
16
|
+
* leaving it out of the default view means the vocabulary you are told about
|
|
17
|
+
* is smaller than the one you have.
|
|
18
|
+
*
|
|
19
|
+
* It had a measurable cost. Three workspace-scoped labels existed and were
|
|
20
|
+
* invisible to the bare command, so nobody knew they were there — which is
|
|
21
|
+
* part of why the label system shipped complete and went unused, and why a
|
|
22
|
+
* second `dogfood` nearly got created beside one that already existed.
|
|
23
|
+
*
|
|
24
|
+
* `--scope` still narrows to exactly one scope, so every explicit invocation
|
|
25
|
+
* behaves as it always did. Only the bare command changed, and it changed to
|
|
26
|
+
* a superset.
|
|
27
|
+
*
|
|
28
|
+
* The merge itself is `lib/label-ref.collectLabelVocabulary` — the same
|
|
29
|
+
* function `--label <name>` resolves through. A separate copy here is how the
|
|
30
|
+
* name you can type and the name you can see start to disagree.
|
|
31
|
+
*/
|
|
8
32
|
class LabelsList extends base_command_1.BaseCommand {
|
|
9
|
-
static description = 'List labels
|
|
33
|
+
static description = 'List labels — every scope you can use, unless --scope narrows it';
|
|
10
34
|
static examples = [
|
|
11
35
|
'<%= config.bin %> labels list',
|
|
12
36
|
'<%= config.bin %> labels list --applicable-to space',
|
|
37
|
+
'<%= config.bin %> labels list --scope user',
|
|
13
38
|
'<%= config.bin %> labels list --scope workspace --scope-id <workspace-id>',
|
|
14
39
|
'<%= config.bin %> labels list --include-archived --json',
|
|
15
40
|
];
|
|
16
41
|
static flags = {
|
|
17
42
|
json: core_1.Flags.boolean({ description: 'Output as JSON' }),
|
|
18
43
|
...label_scope_1.labelScopeFlags,
|
|
44
|
+
// No default, unlike the shared flag: its absence is what selects the
|
|
45
|
+
// merged view, so "not passed" and "passed user" must stay distinguishable.
|
|
46
|
+
scope: core_1.Flags.string({
|
|
47
|
+
description: 'Narrow to ONE scope. Omit to list every scope you can use.',
|
|
48
|
+
options: ['user', 'workspace'],
|
|
49
|
+
}),
|
|
19
50
|
'applicable-to': core_1.Flags.string({
|
|
20
51
|
description: 'Only labels applicable to this entity type',
|
|
21
52
|
options: [...label_scope_1.LABEL_APPLICABLE],
|
|
@@ -25,38 +56,49 @@ class LabelsList extends base_command_1.BaseCommand {
|
|
|
25
56
|
async run() {
|
|
26
57
|
this.requireAuth();
|
|
27
58
|
const { flags } = await this.parse(LabelsList);
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
scope = (0, label_scope_1.resolveLabelScope)(flags);
|
|
31
|
-
}
|
|
32
|
-
catch (err) {
|
|
33
|
-
this.error(err.message, { exit: 1 });
|
|
34
|
-
}
|
|
35
|
-
let response;
|
|
59
|
+
const applicableTo = flags['applicable-to'];
|
|
60
|
+
let items = [];
|
|
36
61
|
try {
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
: {}),
|
|
42
|
-
|
|
43
|
-
|
|
62
|
+
if (flags.scope) {
|
|
63
|
+
const scope = (0, label_scope_1.resolveLabelScope)(flags);
|
|
64
|
+
const response = (await data_provider_1.dataService.getLabels({
|
|
65
|
+
...scope,
|
|
66
|
+
...(applicableTo ? { applicableTo } : {}),
|
|
67
|
+
...(flags['include-archived'] ? { includeArchived: true } : {}),
|
|
68
|
+
}));
|
|
69
|
+
items = response?.data ?? [];
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
items = await (0, label_ref_1.collectLabelVocabulary)({
|
|
73
|
+
...(applicableTo ? { applicableTo } : {}),
|
|
74
|
+
...(process.env.OVERSKY_WORKSPACE_ID
|
|
75
|
+
? { workspaceId: process.env.OVERSKY_WORKSPACE_ID }
|
|
76
|
+
: {}),
|
|
77
|
+
...(flags['include-archived'] ? { includeArchived: true } : {}),
|
|
78
|
+
});
|
|
79
|
+
}
|
|
44
80
|
}
|
|
45
81
|
catch (err) {
|
|
82
|
+
if (err instanceof Error && !('status' in err))
|
|
83
|
+
this.error(err.message, { exit: 1 });
|
|
46
84
|
this.handleApiError(err);
|
|
47
85
|
}
|
|
48
86
|
if (flags.json) {
|
|
49
|
-
this.log(JSON.stringify(
|
|
87
|
+
this.log(JSON.stringify({ data: items }, null, 2));
|
|
50
88
|
return;
|
|
51
89
|
}
|
|
52
|
-
const items = response?.data ?? [];
|
|
53
90
|
if (items.length === 0) {
|
|
54
|
-
this.log(
|
|
91
|
+
this.log(flags.scope
|
|
92
|
+
? 'No labels in this scope.'
|
|
93
|
+
: 'No labels you can use. Create one with `labels create --name <name> --applicable-to <entity>`.');
|
|
55
94
|
return;
|
|
56
95
|
}
|
|
57
96
|
const rows = items.map((l) => ({
|
|
58
97
|
id: String(l.id ?? '-'),
|
|
59
98
|
name: String(l.name ?? '-'),
|
|
99
|
+
// Where it lives decides who else sees it, and it is the one column the
|
|
100
|
+
// old single-scope view never had to show.
|
|
101
|
+
scope: String(l.scope ?? '-'),
|
|
60
102
|
color: String(l.color ?? '-'),
|
|
61
103
|
appliesTo: Array.isArray(l.applicableTo) ? l.applicableTo.join(',') : '-',
|
|
62
104
|
used: String(l.usageCount ?? 0),
|
|
@@ -65,6 +107,7 @@ class LabelsList extends base_command_1.BaseCommand {
|
|
|
65
107
|
(0, format_1.renderTable)(rows, [
|
|
66
108
|
{ key: 'id', header: 'ID' },
|
|
67
109
|
{ key: 'name', header: 'NAME', maxWidth: 32 },
|
|
110
|
+
{ key: 'scope', header: 'SCOPE' },
|
|
68
111
|
{ key: 'color', header: 'COLOR' },
|
|
69
112
|
{ key: 'appliesTo', header: 'APPLIES TO' },
|
|
70
113
|
{ key: 'used', header: 'USED' },
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { BaseCommand } from '../../../base-command';
|
|
2
|
+
/**
|
|
3
|
+
* An agent's memory POLICY: which pools its runtime may read and write, how long
|
|
4
|
+
* retained facts are governed, and what deletion means.
|
|
5
|
+
*
|
|
6
|
+
* Its own route rather than a corner of `PATCH /api/agents/:id`, and the CLI
|
|
7
|
+
* uses the same door the web does. The distinction the route draws — and this
|
|
8
|
+
* command surfaces — is between a policy an owner has DELIBERATELY saved and the
|
|
9
|
+
* defaults an unconfigured agent reads as. Mongoose materializes the leaf
|
|
10
|
+
* defaults on every new agent row, so "has a policy" cannot be answered by the
|
|
11
|
+
* field being present; only `updatedAt` says a human decided something.
|
|
12
|
+
*/
|
|
13
|
+
export default class MemoryGovernanceShow extends BaseCommand {
|
|
14
|
+
static description: string;
|
|
15
|
+
static examples: string[];
|
|
16
|
+
static flags: {
|
|
17
|
+
agent: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
18
|
+
json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
19
|
+
};
|
|
20
|
+
run(): Promise<void>;
|
|
21
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const core_1 = require("@oclif/core");
|
|
4
|
+
const data_provider_1 = require("@skrr-ai/data-provider");
|
|
5
|
+
const base_command_1 = require("../../../base-command");
|
|
6
|
+
const agent_resolver_1 = require("../../../lib/agent-resolver");
|
|
7
|
+
/**
|
|
8
|
+
* An agent's memory POLICY: which pools its runtime may read and write, how long
|
|
9
|
+
* retained facts are governed, and what deletion means.
|
|
10
|
+
*
|
|
11
|
+
* Its own route rather than a corner of `PATCH /api/agents/:id`, and the CLI
|
|
12
|
+
* uses the same door the web does. The distinction the route draws — and this
|
|
13
|
+
* command surfaces — is between a policy an owner has DELIBERATELY saved and the
|
|
14
|
+
* defaults an unconfigured agent reads as. Mongoose materializes the leaf
|
|
15
|
+
* defaults on every new agent row, so "has a policy" cannot be answered by the
|
|
16
|
+
* field being present; only `updatedAt` says a human decided something.
|
|
17
|
+
*/
|
|
18
|
+
class MemoryGovernanceShow extends base_command_1.BaseCommand {
|
|
19
|
+
static description = "Show an agent's memory governance policy";
|
|
20
|
+
static examples = [
|
|
21
|
+
'<%= config.bin %> memory governance --agent <agent-id>',
|
|
22
|
+
'<%= config.bin %> memory governance --agent <agent-id> --json',
|
|
23
|
+
];
|
|
24
|
+
static flags = {
|
|
25
|
+
agent: core_1.Flags.string({
|
|
26
|
+
description: 'Agent ID (falls back to OVERSKY_AGENT_ID, then your primary agent)',
|
|
27
|
+
}),
|
|
28
|
+
json: core_1.Flags.boolean({ description: 'Output as JSON' }),
|
|
29
|
+
};
|
|
30
|
+
async run() {
|
|
31
|
+
this.requireAuth();
|
|
32
|
+
const { flags } = await this.parse(MemoryGovernanceShow);
|
|
33
|
+
let agentId;
|
|
34
|
+
try {
|
|
35
|
+
agentId = await (0, agent_resolver_1.resolveAgentId)(flags.agent);
|
|
36
|
+
}
|
|
37
|
+
catch (err) {
|
|
38
|
+
this.error(err.message, { exit: 1 });
|
|
39
|
+
}
|
|
40
|
+
let policy;
|
|
41
|
+
try {
|
|
42
|
+
policy = await data_provider_1.dataService.getAgentMemoryGovernance(agentId);
|
|
43
|
+
}
|
|
44
|
+
catch (err) {
|
|
45
|
+
this.handleApiError(err);
|
|
46
|
+
}
|
|
47
|
+
if (flags.json) {
|
|
48
|
+
this.log(this.agentJson(agentId, policy));
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
const p = policy;
|
|
52
|
+
this.log(`Memory governance for agent ${agentId}`);
|
|
53
|
+
this.log(` Read scopes: ${(p.allowedReadScopes ?? []).join(', ') || '-'}`);
|
|
54
|
+
this.log(` Write scopes: ${(p.allowedWriteScopes ?? []).join(', ') || '-'}`);
|
|
55
|
+
this.log(` Retention: ${p.retentionDays ?? '-'} days`);
|
|
56
|
+
this.log(` On deletion: ${p.deletionMode ?? '-'}`);
|
|
57
|
+
this.log(` Shared memory: ${p.requireEvidenceForSharedMemory ? 'requires evidence' : 'no evidence required'}`);
|
|
58
|
+
this.log('');
|
|
59
|
+
this.log(p.updatedAt
|
|
60
|
+
? `Configured ${String(p.updatedAt).slice(0, 10)}.`
|
|
61
|
+
: 'Never configured — these are the defaults a run reads, not a saved policy.');
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
exports.default = MemoryGovernanceShow;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { BaseCommand } from '../../../base-command';
|
|
2
|
+
/**
|
|
3
|
+
* Change an agent's memory policy. Requires EDIT on the agent.
|
|
4
|
+
*
|
|
5
|
+
* PARTIAL by design and worth being explicit about: the route merges over the
|
|
6
|
+
* leaves an owner has actually set, so omitting a flag leaves that leaf unset
|
|
7
|
+
* rather than freezing today's default into the row. That is why `--read-scope`
|
|
8
|
+
* REPLACES the list instead of adding to it — a list flag that appended would
|
|
9
|
+
* make "only agent memory" unreachable once anything wider had been granted.
|
|
10
|
+
*/
|
|
11
|
+
export default class MemoryGovernanceSet extends BaseCommand {
|
|
12
|
+
static description: string;
|
|
13
|
+
static examples: string[];
|
|
14
|
+
static flags: {
|
|
15
|
+
agent: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
16
|
+
'read-scope': import("@oclif/core/lib/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
17
|
+
'write-scope': import("@oclif/core/lib/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
18
|
+
'retention-days': import("@oclif/core/lib/interfaces").OptionFlag<number | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
19
|
+
'deletion-mode': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
20
|
+
'require-evidence': import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
21
|
+
json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
22
|
+
};
|
|
23
|
+
run(): Promise<void>;
|
|
24
|
+
}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const core_1 = require("@oclif/core");
|
|
4
|
+
const data_provider_1 = require("@skrr-ai/data-provider");
|
|
5
|
+
const base_command_1 = require("../../../base-command");
|
|
6
|
+
const agent_resolver_1 = require("../../../lib/agent-resolver");
|
|
7
|
+
const MEMORY_SCOPES = ['agent', 'user', 'workspace'];
|
|
8
|
+
/**
|
|
9
|
+
* Change an agent's memory policy. Requires EDIT on the agent.
|
|
10
|
+
*
|
|
11
|
+
* PARTIAL by design and worth being explicit about: the route merges over the
|
|
12
|
+
* leaves an owner has actually set, so omitting a flag leaves that leaf unset
|
|
13
|
+
* rather than freezing today's default into the row. That is why `--read-scope`
|
|
14
|
+
* REPLACES the list instead of adding to it — a list flag that appended would
|
|
15
|
+
* make "only agent memory" unreachable once anything wider had been granted.
|
|
16
|
+
*/
|
|
17
|
+
class MemoryGovernanceSet extends base_command_1.BaseCommand {
|
|
18
|
+
static description = "Change an agent's memory governance policy (requires EDIT)";
|
|
19
|
+
static examples = [
|
|
20
|
+
'<%= config.bin %> memory governance set --agent <agent-id> --retention-days 90',
|
|
21
|
+
'<%= config.bin %> memory governance set --agent <agent-id> --read-scope agent --read-scope workspace',
|
|
22
|
+
'<%= config.bin %> memory governance set --agent <agent-id> --deletion-mode delete --no-require-evidence',
|
|
23
|
+
];
|
|
24
|
+
static flags = {
|
|
25
|
+
agent: core_1.Flags.string({ description: 'Agent ID' }),
|
|
26
|
+
'read-scope': core_1.Flags.string({
|
|
27
|
+
description: 'Memory pool the runtime may READ (repeatable; replaces the list)',
|
|
28
|
+
options: [...MEMORY_SCOPES],
|
|
29
|
+
multiple: true,
|
|
30
|
+
}),
|
|
31
|
+
'write-scope': core_1.Flags.string({
|
|
32
|
+
description: 'Memory pool the runtime may WRITE (repeatable; replaces the list)',
|
|
33
|
+
options: [...MEMORY_SCOPES],
|
|
34
|
+
multiple: true,
|
|
35
|
+
}),
|
|
36
|
+
'retention-days': core_1.Flags.integer({
|
|
37
|
+
description: 'How long retained facts are governed (1-3650)',
|
|
38
|
+
}),
|
|
39
|
+
'deletion-mode': core_1.Flags.string({
|
|
40
|
+
description: 'What deletion means for this agent',
|
|
41
|
+
options: ['archive', 'delete'],
|
|
42
|
+
}),
|
|
43
|
+
'require-evidence': core_1.Flags.boolean({
|
|
44
|
+
description: 'Require evidence before a fact enters shared memory',
|
|
45
|
+
allowNo: true,
|
|
46
|
+
}),
|
|
47
|
+
json: core_1.Flags.boolean({ description: 'Output as JSON' }),
|
|
48
|
+
};
|
|
49
|
+
async run() {
|
|
50
|
+
this.requireAuth();
|
|
51
|
+
const { flags } = await this.parse(MemoryGovernanceSet);
|
|
52
|
+
const patch = {
|
|
53
|
+
...(flags['read-scope'] === undefined
|
|
54
|
+
? {}
|
|
55
|
+
: { allowedReadScopes: flags['read-scope'] }),
|
|
56
|
+
...(flags['write-scope'] === undefined
|
|
57
|
+
? {}
|
|
58
|
+
: { allowedWriteScopes: flags['write-scope'] }),
|
|
59
|
+
...(flags['retention-days'] === undefined ? {} : { retentionDays: flags['retention-days'] }),
|
|
60
|
+
...(flags['deletion-mode'] === undefined
|
|
61
|
+
? {}
|
|
62
|
+
: { deletionMode: flags['deletion-mode'] }),
|
|
63
|
+
...(flags['require-evidence'] === undefined
|
|
64
|
+
? {}
|
|
65
|
+
: { requireEvidenceForSharedMemory: flags['require-evidence'] }),
|
|
66
|
+
};
|
|
67
|
+
if (Object.keys(patch).length === 0) {
|
|
68
|
+
this.error('Nothing to change. Pass at least one of --read-scope, --write-scope, ' +
|
|
69
|
+
'--retention-days, --deletion-mode, --require-evidence.', { exit: 1 });
|
|
70
|
+
}
|
|
71
|
+
let agentId;
|
|
72
|
+
try {
|
|
73
|
+
agentId = await (0, agent_resolver_1.resolveAgentId)(flags.agent);
|
|
74
|
+
}
|
|
75
|
+
catch (err) {
|
|
76
|
+
this.error(err.message, { exit: 1 });
|
|
77
|
+
}
|
|
78
|
+
let policy;
|
|
79
|
+
try {
|
|
80
|
+
policy = await data_provider_1.dataService.updateAgentMemoryGovernance(agentId, patch);
|
|
81
|
+
}
|
|
82
|
+
catch (err) {
|
|
83
|
+
this.handleApiError(err);
|
|
84
|
+
}
|
|
85
|
+
if (flags.json) {
|
|
86
|
+
this.log(this.agentJson(agentId, policy));
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
this.log(`Updated memory governance for agent ${agentId}.`);
|
|
90
|
+
this.log(` Read scopes: ${(policy.allowedReadScopes ?? []).join(', ') || '-'}`);
|
|
91
|
+
this.log(` Write scopes: ${(policy.allowedWriteScopes ?? []).join(', ') || '-'}`);
|
|
92
|
+
this.log(` Retention: ${policy.retentionDays ?? '-'} days`);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
exports.default = MemoryGovernanceSet;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { BaseCommand } from '../../base-command';
|
|
2
|
+
/**
|
|
3
|
+
* Where an agent's stored memories came from.
|
|
4
|
+
*
|
|
5
|
+
* The other half of governance: a policy says what a runtime MAY remember, and
|
|
6
|
+
* this says what it actually did and on whose evidence. Read-only, VIEW on the
|
|
7
|
+
* agent.
|
|
8
|
+
*/
|
|
9
|
+
export default class MemoryProvenance extends BaseCommand {
|
|
10
|
+
static description: string;
|
|
11
|
+
static examples: string[];
|
|
12
|
+
static flags: {
|
|
13
|
+
agent: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
14
|
+
limit: import("@oclif/core/lib/interfaces").OptionFlag<number | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
15
|
+
json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
16
|
+
};
|
|
17
|
+
run(): Promise<void>;
|
|
18
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const core_1 = require("@oclif/core");
|
|
4
|
+
const data_provider_1 = require("@skrr-ai/data-provider");
|
|
5
|
+
const base_command_1 = require("../../base-command");
|
|
6
|
+
const agent_resolver_1 = require("../../lib/agent-resolver");
|
|
7
|
+
const format_1 = require("../../lib/format");
|
|
8
|
+
/**
|
|
9
|
+
* Where an agent's stored memories came from.
|
|
10
|
+
*
|
|
11
|
+
* The other half of governance: a policy says what a runtime MAY remember, and
|
|
12
|
+
* this says what it actually did and on whose evidence. Read-only, VIEW on the
|
|
13
|
+
* agent.
|
|
14
|
+
*/
|
|
15
|
+
class MemoryProvenance extends base_command_1.BaseCommand {
|
|
16
|
+
static description = "Show where an agent's stored memories came from";
|
|
17
|
+
static examples = [
|
|
18
|
+
'<%= config.bin %> memory provenance --agent <agent-id>',
|
|
19
|
+
'<%= config.bin %> memory provenance --agent <agent-id> --limit 50 --json',
|
|
20
|
+
];
|
|
21
|
+
static flags = {
|
|
22
|
+
agent: core_1.Flags.string({ description: 'Agent ID' }),
|
|
23
|
+
limit: core_1.Flags.integer({ description: 'How many entries to return' }),
|
|
24
|
+
json: core_1.Flags.boolean({ description: 'Output as JSON' }),
|
|
25
|
+
};
|
|
26
|
+
async run() {
|
|
27
|
+
this.requireAuth();
|
|
28
|
+
const { flags } = await this.parse(MemoryProvenance);
|
|
29
|
+
let agentId;
|
|
30
|
+
try {
|
|
31
|
+
agentId = await (0, agent_resolver_1.resolveAgentId)(flags.agent);
|
|
32
|
+
}
|
|
33
|
+
catch (err) {
|
|
34
|
+
this.error(err.message, { exit: 1 });
|
|
35
|
+
}
|
|
36
|
+
let response;
|
|
37
|
+
try {
|
|
38
|
+
response = await data_provider_1.dataService.getAgentMemoryProvenance(agentId, flags.limit === undefined ? undefined : { limit: flags.limit });
|
|
39
|
+
}
|
|
40
|
+
catch (err) {
|
|
41
|
+
this.handleApiError(err);
|
|
42
|
+
}
|
|
43
|
+
if (flags.json) {
|
|
44
|
+
this.log(this.agentJson(agentId, response));
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
const payload = response;
|
|
48
|
+
const entries = Array.isArray(response)
|
|
49
|
+
? response
|
|
50
|
+
: (payload?.entries ?? []);
|
|
51
|
+
if (entries.length === 0) {
|
|
52
|
+
this.log(`No memory provenance recorded for agent ${agentId}.`);
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
(0, format_1.renderTable)(entries.map((entry) => ({
|
|
56
|
+
key: String(entry.key ?? '-'),
|
|
57
|
+
source: String(entry.source ?? entry.origin ?? '-'),
|
|
58
|
+
at: entry.updated_at ? String(entry.updated_at).slice(0, 10) : '-',
|
|
59
|
+
})), [
|
|
60
|
+
{ key: 'key', header: 'KEY', verbatim: true },
|
|
61
|
+
{ key: 'source', header: 'SOURCE', maxWidth: 30 },
|
|
62
|
+
{ key: 'at', header: 'UPDATED' },
|
|
63
|
+
], (line) => this.log(line));
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
exports.default = MemoryProvenance;
|
|
@@ -9,7 +9,10 @@ export default class SpacesCreate extends BaseCommand {
|
|
|
9
9
|
description: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
10
10
|
status: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
11
11
|
color: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
12
|
+
icon: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
13
|
+
'icon-color': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
12
14
|
'lead-agent': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
15
|
+
team: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
13
16
|
'target-date': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
14
17
|
goal: import("@oclif/core/lib/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
15
18
|
label: import("@oclif/core/lib/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
@@ -5,6 +5,7 @@ const data_provider_1 = require("@skrr-ai/data-provider");
|
|
|
5
5
|
const outbox_1 = require("../../lib/outbox");
|
|
6
6
|
const api_fetch_1 = require("../../lib/api-fetch");
|
|
7
7
|
const base_command_1 = require("../../base-command");
|
|
8
|
+
const label_ref_1 = require("../../lib/label-ref");
|
|
8
9
|
const web_url_1 = require("../../lib/web-url");
|
|
9
10
|
const prompt_1 = require("../../lib/prompt");
|
|
10
11
|
const created_line_1 = require("../../lib/created-line");
|
|
@@ -13,6 +14,7 @@ class SpacesCreate extends base_command_1.BaseCommand {
|
|
|
13
14
|
static examples = [
|
|
14
15
|
'<%= config.bin %> spaces create --title "Q2 Launch"',
|
|
15
16
|
'<%= config.bin %> spaces create --title "Support" --status in_progress --color "#4f46e5"',
|
|
17
|
+
'<%= config.bin %> spaces create --title "Launch" --icon Rocket --icon-color "#2DD4BF"',
|
|
16
18
|
'<%= config.bin %> spaces create --title "Research" --lead-agent <agent-id>',
|
|
17
19
|
'<%= config.bin %> spaces create --title "Frontend" --parent <space-id>',
|
|
18
20
|
'<%= config.bin %> spaces create --title "Private notes" --parent <space-id> --no-inherit-access',
|
|
@@ -27,11 +29,18 @@ class SpacesCreate extends base_command_1.BaseCommand {
|
|
|
27
29
|
description: core_1.Flags.string({ description: 'Space description' }),
|
|
28
30
|
status: core_1.Flags.string({ description: 'Space status', options: [...data_provider_1.SPACE_STATUSES] }),
|
|
29
31
|
color: core_1.Flags.string({ description: 'Space color (hex, e.g. #4f46e5)' }),
|
|
32
|
+
icon: core_1.Flags.string({
|
|
33
|
+
description: 'Space icon — a curated icon name (e.g. Rocket, Star) or an emoji',
|
|
34
|
+
}),
|
|
35
|
+
'icon-color': core_1.Flags.string({
|
|
36
|
+
description: 'Color applied to the space icon (hex, e.g. #2DD4BF)',
|
|
37
|
+
}),
|
|
30
38
|
'lead-agent': core_1.Flags.string({ description: 'Space Leader agent ID' }),
|
|
39
|
+
team: core_1.Flags.string({ description: 'Team ID to attach this space to' }),
|
|
31
40
|
'target-date': core_1.Flags.string({ description: 'Target date (ISO string)' }),
|
|
32
41
|
goal: core_1.Flags.string({ description: 'Goal ID to link (repeatable)', multiple: true }),
|
|
33
42
|
label: core_1.Flags.string({
|
|
34
|
-
description: 'Label
|
|
43
|
+
description: 'Label to attach (repeatable, max 50) — id, or a name from `skrr labels list --applicable-to space`. An unknown name is refused, never created. After creation use `spaces labels add/remove`.',
|
|
35
44
|
multiple: true,
|
|
36
45
|
}),
|
|
37
46
|
'group-chat': core_1.Flags.string({ description: 'Group chat ID to link this space to' }),
|
|
@@ -53,15 +62,36 @@ class SpacesCreate extends base_command_1.BaseCommand {
|
|
|
53
62
|
catch (err) {
|
|
54
63
|
this.error(err.message, { exit: 1 });
|
|
55
64
|
}
|
|
65
|
+
// A name is resolved against the DECLARED vocabulary before the create, so
|
|
66
|
+
// a typo fails here — cheaply, with the near misses named — rather than
|
|
67
|
+
// minting a second spelling of a label somebody already has.
|
|
68
|
+
let resolvedLabelIds;
|
|
69
|
+
try {
|
|
70
|
+
const ids = await (0, label_ref_1.resolveLabelRefs)(flags.label, {
|
|
71
|
+
applicableTo: 'space',
|
|
72
|
+
...(process.env.OVERSKY_WORKSPACE_ID
|
|
73
|
+
? { workspaceId: process.env.OVERSKY_WORKSPACE_ID }
|
|
74
|
+
: {}),
|
|
75
|
+
});
|
|
76
|
+
resolvedLabelIds = ids.length > 0 ? ids : undefined;
|
|
77
|
+
}
|
|
78
|
+
catch (err) {
|
|
79
|
+
if (err instanceof label_ref_1.LabelRefError)
|
|
80
|
+
this.error(err.message, { exit: 1 });
|
|
81
|
+
this.handleApiError(err);
|
|
82
|
+
}
|
|
56
83
|
const payload = (0, prompt_1.mergeDefined)(body, {
|
|
57
84
|
title: flags.title,
|
|
58
85
|
description: flags.description,
|
|
59
86
|
status: flags.status,
|
|
60
87
|
color: flags.color,
|
|
88
|
+
icon: flags.icon,
|
|
89
|
+
iconColor: flags['icon-color'],
|
|
61
90
|
leadAgentId: flags['lead-agent'],
|
|
91
|
+
teamId: flags.team,
|
|
62
92
|
targetDate: flags['target-date'],
|
|
63
93
|
goalIds: flags.goal,
|
|
64
|
-
labelIds:
|
|
94
|
+
labelIds: resolvedLabelIds,
|
|
65
95
|
groupChatId: flags['group-chat'],
|
|
66
96
|
parentSpaceId: flags.parent,
|
|
67
97
|
inheritAccess: flags['inherit-access'],
|
|
@@ -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
|
const web_url_1 = require("../../../lib/web-url");
|
|
7
8
|
class SpacesLabelsAdd extends base_command_1.BaseCommand {
|
|
8
9
|
static description = 'Attach a label to a space';
|
|
@@ -16,7 +17,7 @@ class SpacesLabelsAdd extends base_command_1.BaseCommand {
|
|
|
16
17
|
static flags = {
|
|
17
18
|
json: core_1.Flags.boolean({ description: 'Output the updated space as JSON' }),
|
|
18
19
|
label: core_1.Flags.string({
|
|
19
|
-
description: 'Label
|
|
20
|
+
description: 'Label — id, or a name from `skrr labels list --applicable-to space`. An unknown name is refused, never created.',
|
|
20
21
|
required: true,
|
|
21
22
|
}),
|
|
22
23
|
};
|
|
@@ -26,9 +27,25 @@ class SpacesLabelsAdd extends base_command_1.BaseCommand {
|
|
|
26
27
|
// `spaces update` deliberately refuses labelIds — the server routes label
|
|
27
28
|
// changes through this atomic $addToSet endpoint so concurrent edits can't
|
|
28
29
|
// clobber each other. Re-attaching an already-attached label is a no-op.
|
|
30
|
+
// A name is resolved against the DECLARED vocabulary; an unknown one is
|
|
31
|
+
// refused with the near misses named, never created. See lib/label-ref.
|
|
32
|
+
let labelId = flags.label;
|
|
33
|
+
try {
|
|
34
|
+
[labelId] = await (0, label_ref_1.resolveLabelRefs)([flags.label], {
|
|
35
|
+
applicableTo: 'space',
|
|
36
|
+
...(process.env.OVERSKY_WORKSPACE_ID
|
|
37
|
+
? { workspaceId: process.env.OVERSKY_WORKSPACE_ID }
|
|
38
|
+
: {}),
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
catch (err) {
|
|
42
|
+
if (err instanceof label_ref_1.LabelRefError)
|
|
43
|
+
this.error(err.message, { exit: 1 });
|
|
44
|
+
this.handleApiError(err);
|
|
45
|
+
}
|
|
29
46
|
let result;
|
|
30
47
|
try {
|
|
31
|
-
result = await data_provider_1.dataService.addLabelToSpace({ spaceId: args.id, labelId
|
|
48
|
+
result = await data_provider_1.dataService.addLabelToSpace({ spaceId: args.id, labelId });
|
|
32
49
|
}
|
|
33
50
|
catch (err) {
|
|
34
51
|
this.handleApiError(err);
|