@skrr-ai/cli 0.1.65 → 0.1.67
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/agents/visibility.d.ts +9 -0
- package/dist/commands/agents/visibility.js +30 -0
- package/dist/commands/logout.js +32 -63
- package/dist/commands/memory/mounts/resolve.js +1 -2
- package/dist/commands/memory/save.d.ts +1 -0
- package/dist/commands/memory/save.js +16 -55
- package/dist/commands/memory/stores/list.js +1 -2
- package/dist/commands/store/admissions/approve.js +7 -5
- package/dist/commands/store/admissions/list.js +17 -3
- package/dist/commands/store/admissions/refuse.js +7 -5
- package/dist/commands/store/install.js +5 -5
- package/dist/commands/store/update.js +5 -1
- package/dist/commands/store/updates.d.ts +1 -1
- package/dist/commands/store/updates.js +3 -3
- package/dist/lib/auth-core-init.js +21 -15
- package/dist/lib/keychain.d.ts +7 -5
- package/dist/lib/keychain.js +10 -10
- package/dist/lib/refresh.d.ts +2 -0
- package/dist/lib/refresh.js +20 -2
- package/dist/lib/scoped-memory-command.d.ts +4 -2
- package/dist/lib/scoped-memory-command.js +27 -3
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/deviceIdentityBridge.d.ts +7 -5
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/deviceIdentityBridge.js +36 -4
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/deviceIdentityBridge.d.ts +7 -5
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/deviceIdentityBridge.js +36 -4
- package/dist/node_modules/@skrr-ai/data-provider/index.js +12 -4
- package/oclif.manifest.json +28195 -28186
- package/package.json +1 -1
|
@@ -10,6 +10,14 @@ export declare function parseCapabilityRationales(entries: readonly string[] | u
|
|
|
10
10
|
rationales?: Record<string, string>;
|
|
11
11
|
error?: string;
|
|
12
12
|
};
|
|
13
|
+
export declare function parseReleaseDependencies(entries: readonly string[] | undefined): {
|
|
14
|
+
dependencies?: Array<{
|
|
15
|
+
entityType: 'skill' | 'action';
|
|
16
|
+
entityId: string;
|
|
17
|
+
artifactVersionId: string;
|
|
18
|
+
}>;
|
|
19
|
+
error?: string;
|
|
20
|
+
};
|
|
13
21
|
export default class AgentsVisibility extends BaseCommand {
|
|
14
22
|
static description: string;
|
|
15
23
|
static examples: string[];
|
|
@@ -27,6 +35,7 @@ export default class AgentsVisibility extends BaseCommand {
|
|
|
27
35
|
'version-minor': import("@oclif/core/lib/interfaces").OptionFlag<number | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
28
36
|
'capability-rationale': import("@oclif/core/lib/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
29
37
|
language: import("@oclif/core/lib/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
38
|
+
dependency: import("@oclif/core/lib/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
30
39
|
};
|
|
31
40
|
run(): Promise<void>;
|
|
32
41
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.parseCapabilityRationales = parseCapabilityRationales;
|
|
4
|
+
exports.parseReleaseDependencies = parseReleaseDependencies;
|
|
4
5
|
const core_1 = require("@oclif/core");
|
|
5
6
|
const data_provider_1 = require("@skrr-ai/data-provider");
|
|
6
7
|
const base_command_1 = require("../../base-command");
|
|
@@ -28,6 +29,23 @@ function parseCapabilityRationales(entries) {
|
|
|
28
29
|
}
|
|
29
30
|
return { rationales };
|
|
30
31
|
}
|
|
32
|
+
function parseReleaseDependencies(entries) {
|
|
33
|
+
if (!entries?.length)
|
|
34
|
+
return {};
|
|
35
|
+
const dependencies = [];
|
|
36
|
+
for (const entry of entries) {
|
|
37
|
+
const match = /^(skill|action):([^@]+)@(store_release_[A-Za-z0-9_-]+)$/.exec(entry);
|
|
38
|
+
if (!match) {
|
|
39
|
+
return { error: `--dependency expects skill:<id>@<store-release-id> or action:<id>@<store-release-id>, got "${entry}".` };
|
|
40
|
+
}
|
|
41
|
+
dependencies.push({
|
|
42
|
+
entityType: match[1],
|
|
43
|
+
entityId: match[2],
|
|
44
|
+
artifactVersionId: match[3],
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
return { dependencies };
|
|
48
|
+
}
|
|
31
49
|
class AgentsVisibility extends base_command_1.BaseCommand {
|
|
32
50
|
static description = 'Set the visibility of an agent (accounts with 2FA need recent step-up for public publishing)';
|
|
33
51
|
static examples = [
|
|
@@ -37,6 +55,7 @@ class AgentsVisibility extends base_command_1.BaseCommand {
|
|
|
37
55
|
'<%= config.bin %> agents visibility <agent-id> --public --json',
|
|
38
56
|
'<%= config.bin %> agents visibility <agent-id> --public --capability-rationale "network:*=Looks up flight prices on the web"',
|
|
39
57
|
'<%= config.bin %> agents visibility <agent-id> --public --language en --language zh-Hans',
|
|
58
|
+
'<%= config.bin %> agents visibility <agent-id> --public --dependency skill:<skill-id>@<store-release-id>',
|
|
40
59
|
];
|
|
41
60
|
static args = {
|
|
42
61
|
id: core_1.Args.string({ description: 'Agent ID', required: true, ignoreStdin: true }),
|
|
@@ -72,6 +91,10 @@ class AgentsVisibility extends base_command_1.BaseCommand {
|
|
|
72
91
|
description: 'A language the release works in, as a BCP 47 tag such as en or zh-Hans (repeatable). Shown on the listing as declared by you; the platform does not check it.',
|
|
73
92
|
multiple: true,
|
|
74
93
|
}),
|
|
94
|
+
dependency: core_1.Flags.string({
|
|
95
|
+
description: 'Pin an attached Skill or Action to its immutable Store release: skill:<id>@<store-release-id> (repeatable)',
|
|
96
|
+
multiple: true,
|
|
97
|
+
}),
|
|
75
98
|
};
|
|
76
99
|
async run() {
|
|
77
100
|
this.requireAuth();
|
|
@@ -84,6 +107,12 @@ class AgentsVisibility extends base_command_1.BaseCommand {
|
|
|
84
107
|
if (rationaleError) {
|
|
85
108
|
this.error(rationaleError, { exit: 1 });
|
|
86
109
|
}
|
|
110
|
+
const { dependencies, error: dependencyError } = parseReleaseDependencies(flags.dependency);
|
|
111
|
+
if (dependencyError)
|
|
112
|
+
this.error(dependencyError, { exit: 1 });
|
|
113
|
+
if (dependencies && !isPublic) {
|
|
114
|
+
this.error('--dependency declares pins on a public release; pass it with --public.', { exit: 1 });
|
|
115
|
+
}
|
|
87
116
|
if (capabilityRationales && !isPublic) {
|
|
88
117
|
this.error('--capability-rationale applies only when publishing with --public.', {
|
|
89
118
|
exit: 1,
|
|
@@ -131,6 +160,7 @@ class AgentsVisibility extends base_command_1.BaseCommand {
|
|
|
131
160
|
versionMinor: flags['version-minor'],
|
|
132
161
|
capabilityRationales,
|
|
133
162
|
supportedLanguages: flags.language,
|
|
163
|
+
dependencies,
|
|
134
164
|
});
|
|
135
165
|
}
|
|
136
166
|
catch (err) {
|
package/dist/commands/logout.js
CHANGED
|
@@ -35,9 +35,6 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
36
|
exports.shouldSkipLocalLogout = shouldSkipLocalLogout;
|
|
37
37
|
const core_1 = require("@oclif/core");
|
|
38
|
-
const fs = __importStar(require("node:fs"));
|
|
39
|
-
const os = __importStar(require("node:os"));
|
|
40
|
-
const path = __importStar(require("node:path"));
|
|
41
38
|
const base_command_1 = require("../base-command");
|
|
42
39
|
const config_1 = require("../lib/config");
|
|
43
40
|
const first_party_harness_managed_1 = require("../lib/first-party-harness-managed");
|
|
@@ -112,21 +109,6 @@ function shouldSkipLocalLogout(input) {
|
|
|
112
109
|
function platformManagedHandoff() {
|
|
113
110
|
return (0, dedicated_service_1.runningOnDedicatedRuntimeGuest)() && Boolean((0, daemonBroker_1.findBrokeredHandoffDescriptor)());
|
|
114
111
|
}
|
|
115
|
-
/**
|
|
116
|
-
* Whether this computer has a configured skrr background service — the file
|
|
117
|
-
* `skrr daemon install` writes, which a logout deliberately does not remove
|
|
118
|
-
* (the service's OWN credential is what becomes unreadable; OSK-12483).
|
|
119
|
-
* The daemon's profile dir is `~/.skrr/profiles/<name>` for every profile,
|
|
120
|
-
* including `default`.
|
|
121
|
-
*/
|
|
122
|
-
function daemonConfigPresent(profile) {
|
|
123
|
-
try {
|
|
124
|
-
return fs.existsSync(path.join(os.homedir(), '.skrr', 'profiles', profile, 'daemon.json'));
|
|
125
|
-
}
|
|
126
|
-
catch {
|
|
127
|
-
return false;
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
112
|
const SIGN_IN_AGAIN = 'To sign in again, run `skrr login`.';
|
|
131
113
|
class Logout extends base_command_1.BaseCommand {
|
|
132
114
|
static description = 'Sign out and clear locally-stored tokens. ' +
|
|
@@ -214,39 +196,36 @@ class Logout extends base_command_1.BaseCommand {
|
|
|
214
196
|
(0, auth_storage_1.clearAllBackends)();
|
|
215
197
|
// Sweep the credentials this product wrote under its PREVIOUS brand.
|
|
216
198
|
//
|
|
217
|
-
//
|
|
218
|
-
//
|
|
219
|
-
//
|
|
220
|
-
//
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
//
|
|
225
|
-
//
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
}
|
|
248
|
-
catch {
|
|
249
|
-
/* best-effort */
|
|
199
|
+
// Ordinary logout clears retired CLI slots only. The explicit
|
|
200
|
+
// all-devices operation also clears retired daemon credentials and KEKs.
|
|
201
|
+
// Removing those during a CLI-only logout would break a running daemon's
|
|
202
|
+
// next restart or refresh (OSK-12483).
|
|
203
|
+
const sweptLegacy = keychain.deleteLegacyBrandEntries({
|
|
204
|
+
includeMachineCredentials: flags['all-devices'],
|
|
205
|
+
});
|
|
206
|
+
// Device identity and the wrapped DEK belong to the daemon as well as the
|
|
207
|
+
// CLI. Preserve both for a CLI-only logout. An explicit all-devices logout
|
|
208
|
+
// revokes daemon sessions and may then clear this profile's machine keys.
|
|
209
|
+
if (flags['all-devices']) {
|
|
210
|
+
const profile = keychain.getActiveProfile();
|
|
211
|
+
try {
|
|
212
|
+
await (0, device_identity_1.resetDeviceIdentity)({ profile, clearOnDisk: true });
|
|
213
|
+
}
|
|
214
|
+
catch {
|
|
215
|
+
/* best-effort */
|
|
216
|
+
}
|
|
217
|
+
try {
|
|
218
|
+
(0, device_identity_1.clearEnrollmentMarker)(profile);
|
|
219
|
+
}
|
|
220
|
+
catch {
|
|
221
|
+
/* best-effort */
|
|
222
|
+
}
|
|
223
|
+
try {
|
|
224
|
+
await (0, cred_envelope_1.resetCredEnvelope)({ profile, clearOnDisk: true });
|
|
225
|
+
}
|
|
226
|
+
catch {
|
|
227
|
+
/* best-effort */
|
|
228
|
+
}
|
|
250
229
|
}
|
|
251
230
|
// Strip any stray token/refreshToken from cli-config.json too —
|
|
252
231
|
// `migrateAuthOutOfConfig` should have done this at init time, but
|
|
@@ -300,18 +279,8 @@ class Logout extends base_command_1.BaseCommand {
|
|
|
300
279
|
}
|
|
301
280
|
else {
|
|
302
281
|
this.log(SIGN_IN_AGAIN);
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
// running daemon keeps working on its in-memory copy, but its next start
|
|
306
|
-
// cannot read the stored one and needs `skrr daemon login` — a plain
|
|
307
|
-
// `skrr login` mints a cli-scope credential and does not re-enroll it.
|
|
308
|
-
// Say that now, while the person is still looking at a screen; otherwise
|
|
309
|
-
// the daemon simply never comes back and nothing anywhere names why.
|
|
310
|
-
// `daemon.json` is written when the service is installed/configured and
|
|
311
|
-
// survives this logout.
|
|
312
|
-
if (daemonConfigPresent(keychain.getActiveProfile())) {
|
|
313
|
-
this.log("This also signs out this computer's skrr background service — it will need " +
|
|
314
|
-
'`skrr daemon login` before it runs again.');
|
|
282
|
+
if (!flags['all-devices']) {
|
|
283
|
+
this.log('The skrr background service keeps its own sign-in and may provide CLI access.');
|
|
315
284
|
}
|
|
316
285
|
}
|
|
317
286
|
if (sweptLegacy.length > 0) {
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
const core_1 = require("@oclif/core");
|
|
4
|
-
const data_schemas_1 = require("@skrr-ai/data-schemas");
|
|
5
4
|
const scoped_memory_command_1 = require("../../../lib/scoped-memory-command");
|
|
6
5
|
class MemoryMountsResolve extends scoped_memory_command_1.ScopedMemoryCommand {
|
|
7
6
|
static description = 'Resolve the ACL-aware Memory mounts for an Agent session';
|
|
@@ -14,7 +13,7 @@ class MemoryMountsResolve extends scoped_memory_command_1.ScopedMemoryCommand {
|
|
|
14
13
|
this.requireAuth();
|
|
15
14
|
const { flags } = await this.parse(MemoryMountsResolve);
|
|
16
15
|
const response = await this.memoryApi(flags.agent, `/mounts${this.query(flags)}`);
|
|
17
|
-
const result = { mounts: response.mounts.map(
|
|
16
|
+
const result = { mounts: response.mounts.map(scoped_memory_command_1.parseMemoryMount) };
|
|
18
17
|
if (flags.json)
|
|
19
18
|
return this.log(JSON.stringify(result, null, 2));
|
|
20
19
|
for (const mount of result.mounts) {
|
|
@@ -1,72 +1,33 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
const core_1 = require("@oclif/core");
|
|
4
|
-
const data_provider_1 = require("@skrr-ai/data-provider");
|
|
5
4
|
const base_command_1 = require("../../base-command");
|
|
6
|
-
const prompt_1 = require("../../lib/prompt");
|
|
7
5
|
const memory_scope_1 = require("../../lib/memory-scope");
|
|
8
|
-
|
|
6
|
+
/** Compatibility entry point for a write API removed by canonical Memory Stores. */
|
|
9
7
|
class MemorySave extends base_command_1.BaseCommand {
|
|
10
|
-
static description = '
|
|
8
|
+
static description = 'Retired flat memory write; use memory maintain remember or memory topics create';
|
|
11
9
|
static examples = [
|
|
12
|
-
'<%= config.bin %> memory
|
|
13
|
-
'<%= config.bin %> memory
|
|
14
|
-
'<%= config.bin %> memory save --key "note" --value "remember this" --json',
|
|
15
|
-
'<%= config.bin %> memory save --key "team-norm" --value "ship on fridays" --tier workspace --pool-workspace ws_123',
|
|
16
|
-
'<%= config.bin %> memory maintain remember \'{"path":"/notes","claim":"remember this"}\' --agent agent_abc123',
|
|
10
|
+
'<%= config.bin %> memory maintain remember \'{"path":"/notes","claim":"Remember this."}\' --agent agent_abc123',
|
|
11
|
+
'<%= config.bin %> memory topics create --help',
|
|
17
12
|
];
|
|
18
13
|
static flags = {
|
|
19
|
-
json: core_1.Flags.boolean({ description: 'Output
|
|
20
|
-
'from-json': core_1.Flags.string({
|
|
21
|
-
|
|
22
|
-
}),
|
|
23
|
-
key: core_1.Flags.string({ description: 'Memory key (required unless set via --from-json)' }),
|
|
24
|
-
value: core_1.Flags.string({ description: 'Memory value (required unless set via --from-json)' }),
|
|
14
|
+
json: core_1.Flags.boolean({ description: 'Output errors as JSON' }),
|
|
15
|
+
'from-json': core_1.Flags.string({ description: 'Retired flat memory input' }),
|
|
16
|
+
key: core_1.Flags.string({ description: 'Retired flat memory key' }),
|
|
17
|
+
value: core_1.Flags.string({ description: 'Retired flat memory value' }),
|
|
25
18
|
...memory_scope_1.memoryScopeFlags,
|
|
26
19
|
};
|
|
27
20
|
async run() {
|
|
28
|
-
this.requireAuth();
|
|
29
21
|
const { flags } = await this.parse(MemorySave);
|
|
30
|
-
const
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
const payload = (0, prompt_1.mergeDefined)(body, {
|
|
39
|
-
key: flags.key,
|
|
40
|
-
value: flags.value,
|
|
22
|
+
const next = flags.agent
|
|
23
|
+
? `skrr memory maintain remember '{"path":"/notes","claim":"your memory"}' --agent ${flags.agent}`
|
|
24
|
+
: 'skrr memory topics create --help (choose an Agent or Space Store)';
|
|
25
|
+
this.failWithCliError({
|
|
26
|
+
code: 'LEGACY_MEMORY_WRITE_REMOVED',
|
|
27
|
+
message: `Flat memory writes have been retired. Use canonical Memory Stores. Run: ${next}`,
|
|
28
|
+
exit: 5,
|
|
29
|
+
retryable: false,
|
|
41
30
|
});
|
|
42
|
-
if (!payload.key || typeof payload.key !== 'string') {
|
|
43
|
-
this.error('A key is required. Pass --key "..." or include it in --from-json.', { exit: 1 });
|
|
44
|
-
}
|
|
45
|
-
if (!payload.value || typeof payload.value !== 'string') {
|
|
46
|
-
this.error('A value is required. Pass --value "..." or include it in --from-json.', {
|
|
47
|
-
exit: 1,
|
|
48
|
-
});
|
|
49
|
-
}
|
|
50
|
-
let result;
|
|
51
|
-
try {
|
|
52
|
-
result = await data_provider_1.dataService.createMemory({
|
|
53
|
-
key: payload.key,
|
|
54
|
-
value: payload.value,
|
|
55
|
-
}, scope);
|
|
56
|
-
}
|
|
57
|
-
catch (err) {
|
|
58
|
-
this.handleApiError(err);
|
|
59
|
-
}
|
|
60
|
-
const guidance = scope.agentId ? (0, memory_workspace_guidance_1.semanticWorkspaceGuidance)(scope.agentId) : undefined;
|
|
61
|
-
if (flags.json) {
|
|
62
|
-
this.log(JSON.stringify(guidance ? { ...result, semanticWorkspace: guidance } : result, null, 2));
|
|
63
|
-
return;
|
|
64
|
-
}
|
|
65
|
-
this.log(`Saved memory ${result.memory.key}`);
|
|
66
|
-
if (guidance) {
|
|
67
|
-
this.log(`\n${guidance.message}`);
|
|
68
|
-
this.log(`To include a fact in that context, run:\n${guidance.nextCommand}`);
|
|
69
|
-
}
|
|
70
31
|
}
|
|
71
32
|
}
|
|
72
33
|
exports.default = MemorySave;
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
const core_1 = require("@oclif/core");
|
|
4
|
-
const data_schemas_1 = require("@skrr-ai/data-schemas");
|
|
5
4
|
const scoped_memory_command_1 = require("../../../lib/scoped-memory-command");
|
|
6
5
|
class MemoryStoresList extends scoped_memory_command_1.ScopedMemoryCommand {
|
|
7
6
|
static description = 'List Memory Stores mounted for an Agent session';
|
|
@@ -15,7 +14,7 @@ class MemoryStoresList extends scoped_memory_command_1.ScopedMemoryCommand {
|
|
|
15
14
|
const { flags } = await this.parse(MemoryStoresList);
|
|
16
15
|
const response = await this.memoryApi(flags.agent, `/stores${this.query(flags)}`);
|
|
17
16
|
const result = {
|
|
18
|
-
stores: response.stores.map(
|
|
17
|
+
stores: response.stores.map(scoped_memory_command_1.parseMountedMemoryStore),
|
|
19
18
|
};
|
|
20
19
|
if (flags.json)
|
|
21
20
|
return this.log(JSON.stringify(result, null, 2));
|
|
@@ -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 --kind artifact',
|
|
16
17
|
'<%= config.bin %> store admissions approve store_release_abc123 --artifact',
|
|
17
18
|
];
|
|
18
19
|
static args = {
|
|
@@ -25,8 +26,8 @@ class StoreAdmissionsApprove extends base_command_1.BaseCommand {
|
|
|
25
26
|
static flags = {
|
|
26
27
|
artifact: core_1.Flags.boolean({ description: 'The id is a Skill or Action artifact release' }),
|
|
27
28
|
kind: core_1.Flags.string({
|
|
28
|
-
description: 'The id is a listing
|
|
29
|
-
options: ['skill', 'action'],
|
|
29
|
+
description: 'The id is a skill/action listing or a Store artifact release',
|
|
30
|
+
options: ['skill', 'action', 'artifact'],
|
|
30
31
|
}),
|
|
31
32
|
note: core_1.Flags.string({ description: 'Decision note' }),
|
|
32
33
|
json: core_1.Flags.boolean({ description: 'Output as JSON' }),
|
|
@@ -35,9 +36,10 @@ class StoreAdmissionsApprove extends base_command_1.BaseCommand {
|
|
|
35
36
|
this.requireAuth();
|
|
36
37
|
const { args, flags } = await this.parse(StoreAdmissionsApprove);
|
|
37
38
|
try {
|
|
38
|
-
if (flags.artifact && flags.kind)
|
|
39
|
-
this.error('Use either --artifact or --kind');
|
|
40
|
-
|
|
39
|
+
if (flags.artifact && flags.kind && flags.kind !== 'artifact') {
|
|
40
|
+
this.error('Use either --artifact or a listing --kind');
|
|
41
|
+
}
|
|
42
|
+
const result = flags.artifact || flags.kind === 'artifact'
|
|
41
43
|
? await data_provider_1.dataService.approveStoreArtifactAdmission(args.id, flags.note)
|
|
42
44
|
: flags.kind
|
|
43
45
|
? await data_provider_1.dataService.approveStoreListingAdmission(flags.kind, args.id, flags.note)
|
|
@@ -9,7 +9,7 @@ const base_command_1 = require("../../../base-command");
|
|
|
9
9
|
* not the publisher.
|
|
10
10
|
*/
|
|
11
11
|
class StoreAdmissionsList extends base_command_1.BaseCommand {
|
|
12
|
-
static description = 'List releases and listings awaiting capability-tiered review (store_curation)';
|
|
12
|
+
static description = 'List Agent releases, artifact releases and listings awaiting capability-tiered review (store_curation)';
|
|
13
13
|
static examples = [
|
|
14
14
|
'<%= config.bin %> store admissions list',
|
|
15
15
|
'<%= config.bin %> store admissions list --state refused --json',
|
|
@@ -28,8 +28,22 @@ class StoreAdmissionsList extends base_command_1.BaseCommand {
|
|
|
28
28
|
const result = await data_provider_1.dataService.getStoreReleaseAdmissions({
|
|
29
29
|
state: flags.state === 'refused' ? 'refused' : 'pending_review',
|
|
30
30
|
});
|
|
31
|
+
const artifacts = [...(result.artifacts || [])];
|
|
32
|
+
let after = result.artifactNextCursor;
|
|
33
|
+
const seen = new Set();
|
|
34
|
+
while (after) {
|
|
35
|
+
if (seen.has(after))
|
|
36
|
+
throw new Error('Artifact admission queue returned a repeated cursor');
|
|
37
|
+
seen.add(after);
|
|
38
|
+
const page = await data_provider_1.dataService.getStoreReleaseAdmissions({
|
|
39
|
+
state: flags.state === 'refused' ? 'refused' : 'pending_review',
|
|
40
|
+
artifactAfter: after,
|
|
41
|
+
});
|
|
42
|
+
artifacts.push(...(page.artifacts || []));
|
|
43
|
+
after = page.artifactNextCursor;
|
|
44
|
+
}
|
|
31
45
|
if (flags.json) {
|
|
32
|
-
this.log(JSON.stringify(result, null, 2));
|
|
46
|
+
this.log(JSON.stringify({ ...result, artifacts, artifactNextCursor: null }, null, 2));
|
|
33
47
|
return;
|
|
34
48
|
}
|
|
35
49
|
const rows = [
|
|
@@ -45,7 +59,7 @@ class StoreAdmissionsList extends base_command_1.BaseCommand {
|
|
|
45
59
|
name: l.name || '',
|
|
46
60
|
facets: (l.admission?.facets || []).join(','),
|
|
47
61
|
})),
|
|
48
|
-
...
|
|
62
|
+
...artifacts.map((a) => ({
|
|
49
63
|
kind: `${a.entityType} artifact`,
|
|
50
64
|
id: a.releaseId,
|
|
51
65
|
name: `${a.entityId} v${a.versionLabel}`,
|
|
@@ -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 --kind artifact --note "reason"',
|
|
15
16
|
'<%= config.bin %> store admissions refuse store_release_abc123 --artifact --note "reason"',
|
|
16
17
|
];
|
|
17
18
|
static args = {
|
|
@@ -24,8 +25,8 @@ class StoreAdmissionsRefuse extends base_command_1.BaseCommand {
|
|
|
24
25
|
static flags = {
|
|
25
26
|
artifact: core_1.Flags.boolean({ description: 'The id is a Skill or Action artifact release' }),
|
|
26
27
|
kind: core_1.Flags.string({
|
|
27
|
-
description: 'The id is a listing
|
|
28
|
-
options: ['skill', 'action'],
|
|
28
|
+
description: 'The id is a skill/action listing or a Store artifact release',
|
|
29
|
+
options: ['skill', 'action', 'artifact'],
|
|
29
30
|
}),
|
|
30
31
|
note: core_1.Flags.string({ description: 'Why the refusal — required', required: true }),
|
|
31
32
|
json: core_1.Flags.boolean({ description: 'Output as JSON' }),
|
|
@@ -34,9 +35,10 @@ class StoreAdmissionsRefuse extends base_command_1.BaseCommand {
|
|
|
34
35
|
this.requireAuth();
|
|
35
36
|
const { args, flags } = await this.parse(StoreAdmissionsRefuse);
|
|
36
37
|
try {
|
|
37
|
-
if (flags.artifact && flags.kind)
|
|
38
|
-
this.error('Use either --artifact or --kind');
|
|
39
|
-
|
|
38
|
+
if (flags.artifact && flags.kind && flags.kind !== 'artifact') {
|
|
39
|
+
this.error('Use either --artifact or a listing --kind');
|
|
40
|
+
}
|
|
41
|
+
const result = flags.artifact || flags.kind === 'artifact'
|
|
40
42
|
? await data_provider_1.dataService.refuseStoreArtifactAdmission(args.id, flags.note || '')
|
|
41
43
|
: flags.kind
|
|
42
44
|
? await data_provider_1.dataService.refuseStoreListingAdmission(flags.kind, args.id, flags.note || '')
|
|
@@ -60,18 +60,18 @@ class StoreInstall extends base_command_1.BaseCommand {
|
|
|
60
60
|
// The server still refuses a second install of a listing you own — this is
|
|
61
61
|
// the friendly read that says so before a quote or a prompt (OSK-12287:
|
|
62
62
|
// `installs` is the read model; `purchased` answers membership cheaply).
|
|
63
|
+
let alreadyInstalled = false;
|
|
63
64
|
try {
|
|
64
65
|
const owned = await data_provider_1.dataService.getPurchasedAgents();
|
|
65
|
-
|
|
66
|
-
this.error(`${args.agentId} is already installed. See it: skrr store updates, or update it: skrr store update ${args.agentId}`, { exit: 1 });
|
|
67
|
-
}
|
|
66
|
+
alreadyInstalled = (owned?.purchasedAgentIds ?? []).includes(args.agentId);
|
|
68
67
|
}
|
|
69
68
|
catch (err) {
|
|
70
69
|
// A read failure must not block an install — the server re-checks anyway.
|
|
71
|
-
if (err.exit)
|
|
72
|
-
throw err;
|
|
73
70
|
this.warn(`Could not check what you own (${err.message}); continuing.`);
|
|
74
71
|
}
|
|
72
|
+
if (alreadyInstalled) {
|
|
73
|
+
this.error(`${args.agentId} is already installed. See it: skrr store updates, or update it: skrr store update ${args.agentId}`, { exit: 1 });
|
|
74
|
+
}
|
|
75
75
|
// What installing would charge NOW, resolved by the server the way the
|
|
76
76
|
// install resolves it (OSK-12240). The install then pins what was shown, so
|
|
77
77
|
// a listing whose price moved in between is refused rather than charged.
|
|
@@ -51,7 +51,7 @@ class StoreUpdate extends base_command_1.BaseCommand {
|
|
|
51
51
|
if (!status?.purchased) {
|
|
52
52
|
this.error(`${args.agentId} is not installed from the Store. Install it first: skrr store install ${args.agentId}`, { exit: 1 });
|
|
53
53
|
}
|
|
54
|
-
if (status.pendingUpdate && !flags.decline) {
|
|
54
|
+
if (status.pendingUpdate && !flags.decline && !flags.json) {
|
|
55
55
|
this.log(`A ${status.pendingUpdate.versionLabel ?? 'new'} release is waiting for review ` +
|
|
56
56
|
`(${status.pendingUpdate.reason}).`);
|
|
57
57
|
}
|
|
@@ -71,6 +71,10 @@ class StoreUpdate extends base_command_1.BaseCommand {
|
|
|
71
71
|
// hands back the body as TEXT, so reading `err.body` as an object never
|
|
72
72
|
// saw a code at all and both answers below fell through to a bare error.
|
|
73
73
|
const body = (0, http_error_1.httpBodyOf)(err);
|
|
74
|
+
// The shared error renderer keeps the server's typed refusal in one JSON
|
|
75
|
+
// envelope. Human guidance below would corrupt stdout in --json mode.
|
|
76
|
+
if (flags.json)
|
|
77
|
+
this.handleApiError(err);
|
|
74
78
|
// Not an update: a new major is a separate purchase. Say which version
|
|
75
79
|
// keeps its free updates, and offer no command — none sells a second
|
|
76
80
|
// major of a listing yet, and `store install` refuses one you own.
|
|
@@ -9,7 +9,7 @@ import { BaseCommand } from '../../base-command';
|
|
|
9
9
|
*
|
|
10
10
|
* Three states, kept apart because they ask for three different things:
|
|
11
11
|
*
|
|
12
|
-
* ready a same-major release
|
|
12
|
+
* ready a same-major release is available; eligibility is checked on apply
|
|
13
13
|
* review one that could not be applied on its own — you and the publisher
|
|
14
14
|
* both changed the same field, the release widened capabilities, or
|
|
15
15
|
* the version your copy came from is unknown
|
|
@@ -14,7 +14,7 @@ const format_1 = require("../../lib/format");
|
|
|
14
14
|
*
|
|
15
15
|
* Three states, kept apart because they ask for three different things:
|
|
16
16
|
*
|
|
17
|
-
* ready a same-major release
|
|
17
|
+
* ready a same-major release is available; eligibility is checked on apply
|
|
18
18
|
* review one that could not be applied on its own — you and the publisher
|
|
19
19
|
* both changed the same field, the release widened capabilities, or
|
|
20
20
|
* the version your copy came from is unknown
|
|
@@ -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: 'available;
|
|
85
|
+
detail: 'available; checked on apply',
|
|
86
86
|
});
|
|
87
87
|
}
|
|
88
88
|
if (install.stopReason) {
|
|
@@ -122,7 +122,7 @@ class StoreUpdates extends base_command_1.BaseCommand {
|
|
|
122
122
|
{ key: 'detail', header: 'WHY', maxWidth: 46 },
|
|
123
123
|
], (line) => this.log(line));
|
|
124
124
|
this.log('');
|
|
125
|
-
this.log('ready → skrr store update <agent>');
|
|
125
|
+
this.log('ready → available; checks run on apply: skrr store update <agent>');
|
|
126
126
|
this.log('review → skrr store update <agent> --strategy replace (takes the publisher version)');
|
|
127
127
|
this.log('widened → skrr store update <agent> --accept-capabilities (or --decline to keep yours)');
|
|
128
128
|
// No command: `store install` refuses a listing you already own, and
|