@skrr-ai/cli 0.1.63 → 0.1.65
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/commands/goals/plan-now.d.ts +6 -0
- package/dist/commands/goals/plan-now.js +25 -0
- package/dist/commands/memory/approvals/issue.js +6 -3
- package/dist/commands/memory/stores/update.js +6 -3
- package/dist/commands/skills/visibility.d.ts +15 -0
- package/dist/commands/skills/visibility.js +49 -0
- package/dist/commands/store/admissions/approve.d.ts +1 -0
- package/dist/commands/store/admissions/approve.js +9 -3
- package/dist/commands/store/admissions/list.js +6 -0
- package/dist/commands/store/admissions/refuse.d.ts +1 -0
- package/dist/commands/store/admissions/refuse.js +9 -3
- package/dist/commands/store/artifacts/release.d.ts +3 -0
- package/dist/commands/store/artifacts/release.js +42 -0
- package/dist/commands/store/installs.d.ts +10 -0
- package/dist/commands/store/installs.js +54 -0
- package/dist/commands/store/updates.js +1 -1
- package/dist/commands/tasks/comments/list.d.ts +10 -0
- package/dist/commands/tasks/comments/list.js +53 -9
- package/dist/commands/tasks/comments/react.js +3 -1
- package/dist/commands/tasks/deliverable/add.d.ts +1 -0
- package/dist/commands/tasks/deliverable/add.js +13 -2
- package/dist/commands/tasks/deliverable/list.js +15 -1
- package/dist/commands/tasks/lifecycle/transition.js +6 -3
- package/dist/commands/tasks/plan/run-update.js +1 -1
- package/dist/commands/tasks/result/submit.js +1 -1
- package/dist/commands/tasks/resume/save.js +6 -3
- package/dist/commands/tasks/updates/add.js +11 -1
- package/dist/lib/file-mime.js +1 -0
- package/dist/lib/live-runtime-binary.d.ts +6 -0
- package/dist/lib/live-runtime-binary.js +32 -1
- package/dist/lib/node-adapter.js +10 -5
- package/dist/lib/prompt.d.ts +7 -0
- package/dist/lib/prompt.js +16 -0
- package/dist/lib/task-asset-upload.d.ts +5 -0
- package/dist/lib/task-asset-upload.js +4 -0
- package/dist/lib/task-closure.d.ts +3 -1
- package/dist/lib/task-closure.js +14 -4
- package/dist/node_modules/@skrr-ai/data-provider/index.js +10 -2
- package/oclif.manifest.json +24195 -24018
- package/package.json +1 -1
|
@@ -23,6 +23,12 @@ export declare function describePlannerReason(reason: string | null | undefined)
|
|
|
23
23
|
* saying so.
|
|
24
24
|
*/
|
|
25
25
|
export declare function plannerTickDidNotRun(result: GoalPlanNowResponse | undefined): boolean;
|
|
26
|
+
/**
|
|
27
|
+
* HTTP 202: the tick was handed to the planner worker rather than awaited in
|
|
28
|
+
* the request. `processed` is absent by design — it is neither a success to
|
|
29
|
+
* count nor a skip to fail on, it is a hand-off (OSK-12748).
|
|
30
|
+
*/
|
|
31
|
+
export declare function plannerTickAccepted(result: GoalPlanNowResponse | undefined): boolean;
|
|
26
32
|
/** Did the REQUEST give up, as opposed to the tick failing? */
|
|
27
33
|
export declare function isPlannerRequestTimeout(err: unknown): boolean;
|
|
28
34
|
/**
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.describePlannerReason = describePlannerReason;
|
|
4
4
|
exports.plannerTickDidNotRun = plannerTickDidNotRun;
|
|
5
|
+
exports.plannerTickAccepted = plannerTickAccepted;
|
|
5
6
|
exports.isPlannerRequestTimeout = isPlannerRequestTimeout;
|
|
6
7
|
exports.plannerTimeoutMessage = plannerTimeoutMessage;
|
|
7
8
|
const core_1 = require("@oclif/core");
|
|
@@ -85,6 +86,14 @@ function describePlannerReason(reason) {
|
|
|
85
86
|
function plannerTickDidNotRun(result) {
|
|
86
87
|
return result?.ok === false || result?.processed === false;
|
|
87
88
|
}
|
|
89
|
+
/**
|
|
90
|
+
* HTTP 202: the tick was handed to the planner worker rather than awaited in
|
|
91
|
+
* the request. `processed` is absent by design — it is neither a success to
|
|
92
|
+
* count nor a skip to fail on, it is a hand-off (OSK-12748).
|
|
93
|
+
*/
|
|
94
|
+
function plannerTickAccepted(result) {
|
|
95
|
+
return result?.accepted === true;
|
|
96
|
+
}
|
|
88
97
|
/** Did the REQUEST give up, as opposed to the tick failing? */
|
|
89
98
|
function isPlannerRequestTimeout(err) {
|
|
90
99
|
const status = err?.status;
|
|
@@ -163,6 +172,22 @@ class GoalsPlanNow extends base_command_1.BaseCommand {
|
|
|
163
172
|
}
|
|
164
173
|
const r = result;
|
|
165
174
|
const reasonText = describePlannerReason(r?.reason);
|
|
175
|
+
if (plannerTickAccepted(r)) {
|
|
176
|
+
// HTTP 202: the tick was handed to the planner worker — no counts exist
|
|
177
|
+
// yet, and that is the honest thing to print (OSK-12748). A 502 here used
|
|
178
|
+
// to mean "gateway gave up mid-run"; accepted means the request ended
|
|
179
|
+
// BEFORE the run, so nothing was left ambiguously in flight.
|
|
180
|
+
if (flags.json) {
|
|
181
|
+
this.log(JSON.stringify(r, null, 2));
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
184
|
+
this.log(`Planner tick accepted for goal ${args.id} — running in the background.`);
|
|
185
|
+
if (r.backfilledCount) {
|
|
186
|
+
this.log(` backfilled: ${r.backfilledCount} existing task(s) tagged to the space.`);
|
|
187
|
+
}
|
|
188
|
+
this.log(` Watch \`${this.config.bin} goals tasks ${args.id}\` for what it creates.`);
|
|
189
|
+
return;
|
|
190
|
+
}
|
|
166
191
|
if (plannerTickDidNotRun(r)) {
|
|
167
192
|
// The backfill runs BEFORE planning and unconditionally, so a skipped
|
|
168
193
|
// tick can still have moved rows. Saying "nothing happened" would be the
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
const core_1 = require("@oclif/core");
|
|
4
4
|
const scoped_memory_command_1 = require("../../../lib/scoped-memory-command");
|
|
5
|
+
const prompt_1 = require("../../../lib/prompt");
|
|
5
6
|
class MemoryApprovalsIssue extends scoped_memory_command_1.ScopedMemoryCommand {
|
|
6
7
|
static description = 'Issue a short-lived user approval for Space PII or Agent-to-Space promotion';
|
|
7
8
|
static flags = {
|
|
@@ -35,10 +36,12 @@ class MemoryApprovalsIssue extends scoped_memory_command_1.ScopedMemoryCommand {
|
|
|
35
36
|
this.error('--payload JSON is required for --purpose space_pii.', { exit: 2 });
|
|
36
37
|
}
|
|
37
38
|
try {
|
|
38
|
-
payload =
|
|
39
|
+
payload = (0, prompt_1.parseJsonFlag)(flags.payload, '--payload');
|
|
39
40
|
}
|
|
40
|
-
catch {
|
|
41
|
-
this.error('--payload must be valid JSON.', {
|
|
41
|
+
catch (err) {
|
|
42
|
+
this.error(err instanceof Error ? err.message : '--payload must be valid JSON.', {
|
|
43
|
+
exit: 2,
|
|
44
|
+
});
|
|
42
45
|
}
|
|
43
46
|
}
|
|
44
47
|
else if (!flags['source-store'] || !flags['source-memory'] || !flags['source-version']) {
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
const core_1 = require("@oclif/core");
|
|
4
4
|
const scoped_memory_command_1 = require("../../../lib/scoped-memory-command");
|
|
5
|
+
const prompt_1 = require("../../../lib/prompt");
|
|
5
6
|
class MemoryStoresUpdate extends scoped_memory_command_1.ScopedMemoryCommand {
|
|
6
7
|
static description = 'Update Memory Store metadata with revision CAS';
|
|
7
8
|
static flags = {
|
|
@@ -18,10 +19,12 @@ class MemoryStoresUpdate extends scoped_memory_command_1.ScopedMemoryCommand {
|
|
|
18
19
|
const store = await this.resolveStore(flags, { write: true });
|
|
19
20
|
let attributes;
|
|
20
21
|
try {
|
|
21
|
-
attributes =
|
|
22
|
+
attributes = (0, prompt_1.parseJsonFlag)(flags.attributes, '--attributes');
|
|
22
23
|
}
|
|
23
|
-
catch {
|
|
24
|
-
this.error('--attributes must be valid JSON.', {
|
|
24
|
+
catch (err) {
|
|
25
|
+
this.error(err instanceof Error ? err.message : '--attributes must be valid JSON.', {
|
|
26
|
+
exit: 2,
|
|
27
|
+
});
|
|
25
28
|
}
|
|
26
29
|
const body = {
|
|
27
30
|
attributes,
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { BaseCommand } from '../../base-command';
|
|
2
|
+
export default class SkillsVisibility extends BaseCommand {
|
|
3
|
+
static description: string;
|
|
4
|
+
static examples: string[];
|
|
5
|
+
static args: {
|
|
6
|
+
id: import("@oclif/core/lib/interfaces").Arg<string, Record<string, unknown>>;
|
|
7
|
+
};
|
|
8
|
+
static flags: {
|
|
9
|
+
public: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
10
|
+
private: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
11
|
+
price: import("@oclif/core/lib/interfaces").OptionFlag<number | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
12
|
+
json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
13
|
+
};
|
|
14
|
+
run(): Promise<void>;
|
|
15
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
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
|
+
class SkillsVisibility extends base_command_1.BaseCommand {
|
|
7
|
+
static description = 'Publish or unpublish an owned skill with a governed Store release';
|
|
8
|
+
static examples = [
|
|
9
|
+
'<%= config.bin %> store artifacts release skill <skill-id> --versionLabel 1.0 --artifactRef skill:<skill-id> --permission-manifest <json>',
|
|
10
|
+
'<%= config.bin %> skills visibility <skill-id> --public',
|
|
11
|
+
'<%= config.bin %> skills visibility <skill-id> --private',
|
|
12
|
+
];
|
|
13
|
+
static args = {
|
|
14
|
+
id: core_1.Args.string({ description: 'Skill ID', required: true, ignoreStdin: true }),
|
|
15
|
+
};
|
|
16
|
+
static flags = {
|
|
17
|
+
public: core_1.Flags.boolean({ description: 'Publish the skill', exclusive: ['private'] }),
|
|
18
|
+
private: core_1.Flags.boolean({ description: 'Unpublish the skill', exclusive: ['public'] }),
|
|
19
|
+
price: core_1.Flags.integer({ description: 'Listing price in micro-USD' }),
|
|
20
|
+
json: core_1.Flags.boolean({ description: 'Output the result as JSON' }),
|
|
21
|
+
};
|
|
22
|
+
async run() {
|
|
23
|
+
this.requireAuth();
|
|
24
|
+
const { args, flags } = await this.parse(SkillsVisibility);
|
|
25
|
+
if (!flags.public && !flags.private) {
|
|
26
|
+
this.error('Pass either --public or --private.', { exit: 2 });
|
|
27
|
+
}
|
|
28
|
+
if (flags.private && flags.price !== undefined) {
|
|
29
|
+
this.error('--price applies only when publishing with --public.', { exit: 2 });
|
|
30
|
+
}
|
|
31
|
+
let result;
|
|
32
|
+
try {
|
|
33
|
+
result = await data_provider_1.dataService.setSkillVisibility({
|
|
34
|
+
skillId: args.id,
|
|
35
|
+
isPublic: flags.public === true,
|
|
36
|
+
...(flags.price !== undefined ? { price: flags.price } : {}),
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
catch (error) {
|
|
40
|
+
this.handleApiError(error);
|
|
41
|
+
}
|
|
42
|
+
if (flags.json) {
|
|
43
|
+
this.log(JSON.stringify(result, null, 2));
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
this.log(`Set skill ${args.id} visibility: ${flags.public ? 'public' : 'private'}`);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
exports.default = SkillsVisibility;
|
|
@@ -11,6 +11,7 @@ export default class StoreAdmissionsApprove extends BaseCommand {
|
|
|
11
11
|
id: import("@oclif/core/lib/interfaces").Arg<string, Record<string, unknown>>;
|
|
12
12
|
};
|
|
13
13
|
static flags: {
|
|
14
|
+
artifact: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
14
15
|
kind: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
15
16
|
note: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
16
17
|
json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
@@ -13,6 +13,7 @@ class StoreAdmissionsApprove extends base_command_1.BaseCommand {
|
|
|
13
13
|
static examples = [
|
|
14
14
|
'<%= config.bin %> store admissions approve ar_abc123',
|
|
15
15
|
'<%= config.bin %> store admissions approve skill_abc123 --kind skill',
|
|
16
|
+
'<%= config.bin %> store admissions approve store_release_abc123 --artifact',
|
|
16
17
|
];
|
|
17
18
|
static args = {
|
|
18
19
|
id: core_1.Args.string({
|
|
@@ -22,6 +23,7 @@ class StoreAdmissionsApprove extends base_command_1.BaseCommand {
|
|
|
22
23
|
}),
|
|
23
24
|
};
|
|
24
25
|
static flags = {
|
|
26
|
+
artifact: core_1.Flags.boolean({ description: 'The id is a Skill or Action artifact release' }),
|
|
25
27
|
kind: core_1.Flags.string({
|
|
26
28
|
description: 'The id is a listing, not a release',
|
|
27
29
|
options: ['skill', 'action'],
|
|
@@ -33,9 +35,13 @@ class StoreAdmissionsApprove extends base_command_1.BaseCommand {
|
|
|
33
35
|
this.requireAuth();
|
|
34
36
|
const { args, flags } = await this.parse(StoreAdmissionsApprove);
|
|
35
37
|
try {
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
38
|
+
if (flags.artifact && flags.kind)
|
|
39
|
+
this.error('Use either --artifact or --kind');
|
|
40
|
+
const result = flags.artifact
|
|
41
|
+
? await data_provider_1.dataService.approveStoreArtifactAdmission(args.id, flags.note)
|
|
42
|
+
: flags.kind
|
|
43
|
+
? await data_provider_1.dataService.approveStoreListingAdmission(flags.kind, args.id, flags.note)
|
|
44
|
+
: await data_provider_1.dataService.approveStoreReleaseAdmission(args.id, flags.note);
|
|
39
45
|
if (flags.json) {
|
|
40
46
|
this.log(JSON.stringify(result, null, 2));
|
|
41
47
|
return;
|
|
@@ -45,6 +45,12 @@ class StoreAdmissionsList extends base_command_1.BaseCommand {
|
|
|
45
45
|
name: l.name || '',
|
|
46
46
|
facets: (l.admission?.facets || []).join(','),
|
|
47
47
|
})),
|
|
48
|
+
...(result.artifacts || []).map((a) => ({
|
|
49
|
+
kind: `${a.entityType} artifact`,
|
|
50
|
+
id: a.releaseId,
|
|
51
|
+
name: `${a.entityId} v${a.versionLabel}`,
|
|
52
|
+
facets: (a.admission?.facets || []).join(','),
|
|
53
|
+
})),
|
|
48
54
|
];
|
|
49
55
|
if (!rows.length) {
|
|
50
56
|
this.log('Nothing waiting for review.');
|
|
@@ -10,6 +10,7 @@ export default class StoreAdmissionsRefuse extends BaseCommand {
|
|
|
10
10
|
id: import("@oclif/core/lib/interfaces").Arg<string, Record<string, unknown>>;
|
|
11
11
|
};
|
|
12
12
|
static flags: {
|
|
13
|
+
artifact: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
13
14
|
kind: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
14
15
|
note: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
15
16
|
json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
@@ -12,6 +12,7 @@ class StoreAdmissionsRefuse extends base_command_1.BaseCommand {
|
|
|
12
12
|
static examples = [
|
|
13
13
|
'<%= config.bin %> store admissions refuse ar_abc123 --note "unbounded network egress"',
|
|
14
14
|
'<%= config.bin %> store admissions refuse act_abc123 --kind action --note "reason"',
|
|
15
|
+
'<%= config.bin %> store admissions refuse store_release_abc123 --artifact --note "reason"',
|
|
15
16
|
];
|
|
16
17
|
static args = {
|
|
17
18
|
id: core_1.Args.string({
|
|
@@ -21,6 +22,7 @@ class StoreAdmissionsRefuse extends base_command_1.BaseCommand {
|
|
|
21
22
|
}),
|
|
22
23
|
};
|
|
23
24
|
static flags = {
|
|
25
|
+
artifact: core_1.Flags.boolean({ description: 'The id is a Skill or Action artifact release' }),
|
|
24
26
|
kind: core_1.Flags.string({
|
|
25
27
|
description: 'The id is a listing, not a release',
|
|
26
28
|
options: ['skill', 'action'],
|
|
@@ -32,9 +34,13 @@ class StoreAdmissionsRefuse extends base_command_1.BaseCommand {
|
|
|
32
34
|
this.requireAuth();
|
|
33
35
|
const { args, flags } = await this.parse(StoreAdmissionsRefuse);
|
|
34
36
|
try {
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
37
|
+
if (flags.artifact && flags.kind)
|
|
38
|
+
this.error('Use either --artifact or --kind');
|
|
39
|
+
const result = flags.artifact
|
|
40
|
+
? await data_provider_1.dataService.refuseStoreArtifactAdmission(args.id, flags.note || '')
|
|
41
|
+
: flags.kind
|
|
42
|
+
? await data_provider_1.dataService.refuseStoreListingAdmission(flags.kind, args.id, flags.note || '')
|
|
43
|
+
: await data_provider_1.dataService.refuseStoreReleaseAdmission(args.id, flags.note || '');
|
|
38
44
|
if (flags.json) {
|
|
39
45
|
this.log(JSON.stringify(result, null, 2));
|
|
40
46
|
return;
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { BaseCommand } from '../../../base-command';
|
|
2
|
+
export declare function parsePermissionManifest(value: string): Record<string, string[]>;
|
|
2
3
|
export default class StoreArtifactsRelease extends BaseCommand {
|
|
3
4
|
static description: string;
|
|
5
|
+
static examples: string[];
|
|
4
6
|
static args: {
|
|
5
7
|
entityType: import("@oclif/core/lib/interfaces").Arg<string, Record<string, unknown>>;
|
|
6
8
|
entityId: import("@oclif/core/lib/interfaces").Arg<string, Record<string, unknown>>;
|
|
@@ -8,6 +10,7 @@ export default class StoreArtifactsRelease extends BaseCommand {
|
|
|
8
10
|
static flags: {
|
|
9
11
|
versionLabel: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
10
12
|
artifactRef: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
13
|
+
'permission-manifest': import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
11
14
|
price: import("@oclif/core/lib/interfaces").OptionFlag<number | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
12
15
|
workspaceId: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
13
16
|
json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
@@ -1,10 +1,38 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.parsePermissionManifest = parsePermissionManifest;
|
|
3
4
|
const core_1 = require("@oclif/core");
|
|
4
5
|
const data_provider_1 = require("@skrr-ai/data-provider");
|
|
5
6
|
const base_command_1 = require("../../../base-command");
|
|
7
|
+
const permissionFields = [
|
|
8
|
+
'tools',
|
|
9
|
+
'connectors',
|
|
10
|
+
'dataScopes',
|
|
11
|
+
'networkDomains',
|
|
12
|
+
'secretNames',
|
|
13
|
+
];
|
|
14
|
+
function parsePermissionManifest(value) {
|
|
15
|
+
const parsed = JSON.parse(value);
|
|
16
|
+
if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {
|
|
17
|
+
throw new Error('The permission manifest must be an object');
|
|
18
|
+
}
|
|
19
|
+
const manifest = parsed;
|
|
20
|
+
if (Object.keys(manifest).some((key) => !permissionFields.includes(key)) ||
|
|
21
|
+
permissionFields.some((key) => {
|
|
22
|
+
const entries = manifest[key];
|
|
23
|
+
return (!Array.isArray(entries) ||
|
|
24
|
+
!entries.every((entry) => typeof entry === 'string' && entry.trim() === entry && entry.length > 0) ||
|
|
25
|
+
new Set(entries).size !== entries.length);
|
|
26
|
+
})) {
|
|
27
|
+
throw new Error('The permission manifest must explicitly declare five arrays of unique, non-empty strings');
|
|
28
|
+
}
|
|
29
|
+
return manifest;
|
|
30
|
+
}
|
|
6
31
|
class StoreArtifactsRelease extends base_command_1.BaseCommand {
|
|
7
32
|
static description = 'Publish an immutable dependency release for your own skill or action';
|
|
33
|
+
static examples = [
|
|
34
|
+
'<%= config.bin %> store artifacts release skill <skill-id> --versionLabel 1.0 --artifactRef skill:<skill-id> --permission-manifest <json>',
|
|
35
|
+
];
|
|
8
36
|
static args = {
|
|
9
37
|
entityType: core_1.Args.string({ required: true, ignoreStdin: true }),
|
|
10
38
|
entityId: core_1.Args.string({ required: true, ignoreStdin: true }),
|
|
@@ -12,6 +40,10 @@ class StoreArtifactsRelease extends base_command_1.BaseCommand {
|
|
|
12
40
|
static flags = {
|
|
13
41
|
versionLabel: core_1.Flags.string({ required: true }),
|
|
14
42
|
artifactRef: core_1.Flags.string({ required: true }),
|
|
43
|
+
'permission-manifest': core_1.Flags.string({
|
|
44
|
+
required: true,
|
|
45
|
+
description: 'Explicit JSON declaration of tools, connectors, dataScopes, networkDomains, and secretNames used by this release',
|
|
46
|
+
}),
|
|
15
47
|
price: core_1.Flags.integer({ description: 'Price in micro-USD; omit for zero-price' }),
|
|
16
48
|
workspaceId: core_1.Flags.string({ description: 'Publish as this workspace' }),
|
|
17
49
|
json: core_1.Flags.boolean({ description: 'Output JSON' }),
|
|
@@ -19,9 +51,19 @@ class StoreArtifactsRelease extends base_command_1.BaseCommand {
|
|
|
19
51
|
async run() {
|
|
20
52
|
this.requireAuth();
|
|
21
53
|
const { args, flags } = await this.parse(StoreArtifactsRelease);
|
|
54
|
+
let permissionManifest;
|
|
55
|
+
try {
|
|
56
|
+
permissionManifest = parsePermissionManifest(flags['permission-manifest']);
|
|
57
|
+
}
|
|
58
|
+
catch {
|
|
59
|
+
this.error('--permission-manifest must declare tools, connectors, dataScopes, networkDomains, and secretNames as string arrays', {
|
|
60
|
+
exit: 2,
|
|
61
|
+
});
|
|
62
|
+
}
|
|
22
63
|
const result = await data_provider_1.dataService.publishStoreArtifactRelease(args.entityType, args.entityId, {
|
|
23
64
|
versionLabel: flags.versionLabel,
|
|
24
65
|
artifactRef: flags.artifactRef,
|
|
66
|
+
permissionManifest,
|
|
25
67
|
...(flags.price !== undefined ? { price: flags.price } : {}),
|
|
26
68
|
...(flags.workspaceId ? { publishAs: { workspaceId: flags.workspaceId } } : {}),
|
|
27
69
|
});
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { BaseCommand } from '../../base-command';
|
|
2
|
+
/** The buyer's installed copies, including stopped copies and their source releases. */
|
|
3
|
+
export default class StoreInstalls extends BaseCommand {
|
|
4
|
+
static description: string;
|
|
5
|
+
static examples: string[];
|
|
6
|
+
static flags: {
|
|
7
|
+
json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
8
|
+
};
|
|
9
|
+
run(): Promise<void>;
|
|
10
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
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 format_1 = require("../../lib/format");
|
|
7
|
+
/** The buyer's installed copies, including stopped copies and their source releases. */
|
|
8
|
+
class StoreInstalls extends base_command_1.BaseCommand {
|
|
9
|
+
static description = 'List your Store installs and the releases they came from';
|
|
10
|
+
static examples = [
|
|
11
|
+
'<%= config.bin %> store installs',
|
|
12
|
+
'<%= config.bin %> store installs --json',
|
|
13
|
+
];
|
|
14
|
+
static flags = {
|
|
15
|
+
json: core_1.Flags.boolean({ description: 'Output as JSON' }),
|
|
16
|
+
};
|
|
17
|
+
async run() {
|
|
18
|
+
this.requireAuth();
|
|
19
|
+
const { flags } = await this.parse(StoreInstalls);
|
|
20
|
+
let response;
|
|
21
|
+
try {
|
|
22
|
+
response = await data_provider_1.dataService.getStoreInstalls();
|
|
23
|
+
}
|
|
24
|
+
catch (error) {
|
|
25
|
+
this.handleApiError(error);
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
const installs = response?.installs ?? [];
|
|
29
|
+
if (flags.json) {
|
|
30
|
+
this.log(JSON.stringify({ object: 'list', data: installs }, null, 2));
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
if (installs.length === 0) {
|
|
34
|
+
this.log('No Store installs found.');
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
(0, format_1.renderTable)(installs.map((install) => ({
|
|
38
|
+
agent: install.agentId,
|
|
39
|
+
copy: install.installedAgentId ?? '-',
|
|
40
|
+
release: install.installedReleaseId ?? '-',
|
|
41
|
+
version: install.installedVersionLabel ?? '-',
|
|
42
|
+
state: install.copyMissing ? 'copy missing' : install.stopReason ? 'stopped' : 'installed',
|
|
43
|
+
reason: install.stopReason ?? '-',
|
|
44
|
+
})), [
|
|
45
|
+
{ key: 'agent', header: 'LISTING' },
|
|
46
|
+
{ key: 'copy', header: 'YOUR COPY' },
|
|
47
|
+
{ key: 'release', header: 'RELEASE' },
|
|
48
|
+
{ key: 'version', header: 'VERSION' },
|
|
49
|
+
{ key: 'state', header: 'STATE' },
|
|
50
|
+
{ key: 'reason', header: 'REASON', maxWidth: 40 },
|
|
51
|
+
], (line) => this.log(line));
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
exports.default = StoreInstalls;
|
|
@@ -82,7 +82,7 @@ class StoreUpdates extends base_command_1.BaseCommand {
|
|
|
82
82
|
channel: install.updatePolicy ?? 'manual',
|
|
83
83
|
have,
|
|
84
84
|
waiting: update.versionLabel ?? '-',
|
|
85
|
-
detail: '
|
|
85
|
+
detail: 'available; changes and capabilities are checked when you update',
|
|
86
86
|
});
|
|
87
87
|
}
|
|
88
88
|
if (install.stopReason) {
|
|
@@ -1,4 +1,14 @@
|
|
|
1
1
|
import { BaseCommand } from '../../../base-command';
|
|
2
|
+
/**
|
|
3
|
+
* Comments arrive flat. Re-thread them so a reply prints under its parent —
|
|
4
|
+
* the flattened order hid which remark a reply answered (OSK-12743). Each
|
|
5
|
+
* level keeps the page's own order; a reply whose parent is on another page
|
|
6
|
+
* (or deleted) keeps its position as a root rather than vanishing.
|
|
7
|
+
*/
|
|
8
|
+
export declare function threadComments(items: Array<Record<string, unknown>>): Array<{
|
|
9
|
+
c: Record<string, unknown>;
|
|
10
|
+
depth: number;
|
|
11
|
+
}>;
|
|
2
12
|
export default class TasksCommentsList extends BaseCommand {
|
|
3
13
|
static description: string;
|
|
4
14
|
static examples: string[];
|
|
@@ -1,11 +1,46 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.threadComments = threadComments;
|
|
3
4
|
const core_1 = require("@oclif/core");
|
|
4
5
|
const data_provider_1 = require("@skrr-ai/data-provider");
|
|
5
6
|
const base_command_1 = require("../../../base-command");
|
|
6
7
|
const format_1 = require("../../../lib/format");
|
|
7
8
|
const principal_display_1 = require("../../../lib/principal-display");
|
|
8
9
|
const task_resolver_1 = require("../../../lib/task-resolver");
|
|
10
|
+
/**
|
|
11
|
+
* Comments arrive flat. Re-thread them so a reply prints under its parent —
|
|
12
|
+
* the flattened order hid which remark a reply answered (OSK-12743). Each
|
|
13
|
+
* level keeps the page's own order; a reply whose parent is on another page
|
|
14
|
+
* (or deleted) keeps its position as a root rather than vanishing.
|
|
15
|
+
*/
|
|
16
|
+
function threadComments(items) {
|
|
17
|
+
const byId = new Map(items.map((c) => [String(c.id ?? c._id), c]));
|
|
18
|
+
const children = new Map();
|
|
19
|
+
const roots = [];
|
|
20
|
+
for (const c of items) {
|
|
21
|
+
const parentId = c.parentCommentId ? String(c.parentCommentId) : null;
|
|
22
|
+
if (parentId && byId.has(parentId)) {
|
|
23
|
+
const siblings = children.get(parentId) ?? [];
|
|
24
|
+
siblings.push(c);
|
|
25
|
+
children.set(parentId, siblings);
|
|
26
|
+
}
|
|
27
|
+
else {
|
|
28
|
+
roots.push(c);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
const threaded = [];
|
|
32
|
+
const emit = (c, depth) => {
|
|
33
|
+
threaded.push({ c, depth });
|
|
34
|
+
// The list arrives newest-first; inside a thread, oldest→newest reads as
|
|
35
|
+
// the conversation happened.
|
|
36
|
+
for (const child of (children.get(String(c.id ?? c._id)) ?? []).slice().reverse()) {
|
|
37
|
+
emit(child, depth + 1);
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
for (const root of roots)
|
|
41
|
+
emit(root, 0);
|
|
42
|
+
return threaded;
|
|
43
|
+
}
|
|
9
44
|
class TasksCommentsList extends base_command_1.BaseCommand {
|
|
10
45
|
static description = 'List comments on a task';
|
|
11
46
|
static examples = [
|
|
@@ -72,15 +107,24 @@ class TasksCommentsList extends base_command_1.BaseCommand {
|
|
|
72
107
|
// space roster (or the caller's own record) can see them; ids that cannot
|
|
73
108
|
// resolve print unchanged.
|
|
74
109
|
const principalNames = await (0, principal_display_1.resolvePrincipalNames)(items.map((c) => c.authorAgentId ?? c.authorUserId ?? c.author));
|
|
75
|
-
const
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
110
|
+
const threaded = threadComments(items);
|
|
111
|
+
const rows = threaded.map(({ c, depth }) => {
|
|
112
|
+
const reactions = c.reactions
|
|
113
|
+
?.map((r) => `${r.emoji ?? ''}${r.count ?? ''}`)
|
|
114
|
+
.filter(Boolean)
|
|
115
|
+
.join(' ');
|
|
116
|
+
const state = c.status === 'resolved' || c.resolvedAt ? 'resolved' : undefined;
|
|
117
|
+
const suffix = [state, reactions].filter(Boolean).join(' · ');
|
|
118
|
+
return {
|
|
119
|
+
time: (0, format_1.localTime)(c.createdAt),
|
|
120
|
+
// The server enriches authors directly (_authorUserName/_authorAgentName);
|
|
121
|
+
// the roster lookup is the fallback for a deployment that predates it.
|
|
122
|
+
author: String(c._authorUserName ?? c._authorAgentName ?? '') ||
|
|
123
|
+
(0, principal_display_1.displayPrincipal)(c.authorAgentId ?? c.authorUserId ?? c.author, principalNames),
|
|
124
|
+
body: (0, format_1.truncate)(String(c.body ?? c.content ?? '-'), 60) + (suffix ? ` [${suffix}]` : ''),
|
|
125
|
+
id: `${depth > 0 ? ' '.repeat(depth) + '↳ ' : ''}${String(c.id ?? c._id ?? '-')}`,
|
|
126
|
+
};
|
|
127
|
+
});
|
|
84
128
|
(0, format_1.renderTable)(rows, [
|
|
85
129
|
{ key: 'time', header: 'TIME' },
|
|
86
130
|
{ key: 'author', header: 'AUTHOR', maxWidth: 30 },
|
|
@@ -14,7 +14,9 @@ class TasksCommentsReact extends base_command_1.BaseCommand {
|
|
|
14
14
|
commentId: core_1.Args.string({ description: 'Comment UUID', required: true, ignoreStdin: true }),
|
|
15
15
|
};
|
|
16
16
|
static flags = {
|
|
17
|
-
task: core_1.Flags.string({
|
|
17
|
+
task: core_1.Flags.string({
|
|
18
|
+
description: 'Task ID; required when not running inside a daemon task session (OSK-12742)',
|
|
19
|
+
}),
|
|
18
20
|
emoji: core_1.Flags.string({ description: 'Emoji reaction (up to 16 characters)', required: true }),
|
|
19
21
|
json: core_1.Flags.boolean({ description: 'Output the raw response as JSON' }),
|
|
20
22
|
};
|
|
@@ -33,6 +33,7 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
33
33
|
};
|
|
34
34
|
})();
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.defaultDeliverableIdempotencyKey = defaultDeliverableIdempotencyKey;
|
|
36
37
|
const fs = __importStar(require("node:fs"));
|
|
37
38
|
const path = __importStar(require("node:path"));
|
|
38
39
|
const core_1 = require("@oclif/core");
|
|
@@ -43,6 +44,11 @@ const outbox_1 = require("../../../lib/outbox");
|
|
|
43
44
|
const api_fetch_1 = require("../../../lib/api-fetch");
|
|
44
45
|
const session_task_endpoints_1 = require("../../../lib/session-task-endpoints");
|
|
45
46
|
const tasks_1 = require("../../../lib/tasks");
|
|
47
|
+
function defaultDeliverableIdempotencyKey(task, payload) {
|
|
48
|
+
// A retry of one exact observation keeps its key. A new version, provider,
|
|
49
|
+
// digest, or expectation binding is a different observation.
|
|
50
|
+
return (0, outbox_1.idempotencyKeyFor)('task-deliverable', task, JSON.stringify(payload));
|
|
51
|
+
}
|
|
46
52
|
/**
|
|
47
53
|
* `skrr tasks deliverable add <task> <kind>:<identity>[@<location>]`
|
|
48
54
|
*
|
|
@@ -155,6 +161,7 @@ class TasksDeliverableAdd extends base_command_1.BaseCommand {
|
|
|
155
161
|
taskId: args.task,
|
|
156
162
|
filePath: archivePath,
|
|
157
163
|
identity: parsed.value.identity,
|
|
164
|
+
kind: parsed.value.kind,
|
|
158
165
|
title: flags.title,
|
|
159
166
|
expectationIds: flags.expectation,
|
|
160
167
|
requestedStatus: status,
|
|
@@ -170,7 +177,7 @@ class TasksDeliverableAdd extends base_command_1.BaseCommand {
|
|
|
170
177
|
}
|
|
171
178
|
let result;
|
|
172
179
|
try {
|
|
173
|
-
const
|
|
180
|
+
const observation = {
|
|
174
181
|
...parsed.value,
|
|
175
182
|
...(status ? { status } : {}),
|
|
176
183
|
title: flags.title,
|
|
@@ -179,8 +186,11 @@ class TasksDeliverableAdd extends base_command_1.BaseCommand {
|
|
|
179
186
|
contentDigest: flags['content-digest'],
|
|
180
187
|
expectationIds: flags.expectation,
|
|
181
188
|
runId: flags['run-id'],
|
|
189
|
+
};
|
|
190
|
+
const payload = {
|
|
191
|
+
...observation,
|
|
182
192
|
idempotencyKey: flags['idempotency-key'] ||
|
|
183
|
-
(
|
|
193
|
+
defaultDeliverableIdempotencyKey(args.task, observation),
|
|
184
194
|
};
|
|
185
195
|
const sessionPath = await (0, session_task_endpoints_1.sessionScopedTaskPath)('deliverable');
|
|
186
196
|
result = sessionPath
|
|
@@ -249,6 +259,7 @@ class TasksDeliverableAdd extends base_command_1.BaseCommand {
|
|
|
249
259
|
role: 'deliverable',
|
|
250
260
|
ledger: {
|
|
251
261
|
identity: opts.identity,
|
|
262
|
+
kind: opts.kind,
|
|
252
263
|
title: opts.title,
|
|
253
264
|
expectationIds: opts.expectationIds,
|
|
254
265
|
},
|
|
@@ -23,6 +23,20 @@ function fidelityLabel(value) {
|
|
|
23
23
|
return value || 'unknown fidelity';
|
|
24
24
|
}
|
|
25
25
|
}
|
|
26
|
+
/**
|
|
27
|
+
* One coordinate CAN name several pinned versions — v1 and v2 of the same
|
|
28
|
+
* report share title and locator, so without a discriminator the rows look
|
|
29
|
+
* identical (OSK-12798). The content digest is the honest one when pinned;
|
|
30
|
+
* otherwise the version's own id suffix is the distinguisher.
|
|
31
|
+
*/
|
|
32
|
+
function versionLabel(item) {
|
|
33
|
+
if (item.contentDigest) {
|
|
34
|
+
const [algo, hex] = item.contentDigest.split(':');
|
|
35
|
+
return `digest ${algo}:${(hex || '').slice(0, 12)}`;
|
|
36
|
+
}
|
|
37
|
+
const id = (item.resourceVersionId || '').replace(/^wrv_/, '');
|
|
38
|
+
return id ? `version ${id.slice(0, 12)}` : 'version unpinned';
|
|
39
|
+
}
|
|
26
40
|
class TasksDeliverableList extends base_command_1.BaseCommand {
|
|
27
41
|
static description = 'List Deliverables with exact version, location, and evidence state';
|
|
28
42
|
static args = {
|
|
@@ -51,7 +65,7 @@ class TasksDeliverableList extends base_command_1.BaseCommand {
|
|
|
51
65
|
this.log(`${item.linkId} · ${item.kind}${item.format ? `/${item.format}` : ''} · ` +
|
|
52
66
|
`${item.title || item.identity || '(untitled)'}\n` +
|
|
53
67
|
` ${item.location || 'no locator'} · ${fidelityLabel(item.versionFidelity)} · ` +
|
|
54
|
-
`${item.status} · ${item.evidenceLevel}`);
|
|
68
|
+
`${versionLabel(item)} · ${item.status} · ${item.evidenceLevel}`);
|
|
55
69
|
}
|
|
56
70
|
}
|
|
57
71
|
}
|