@skrr-ai/cli 0.1.83 → 0.1.85

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.
Files changed (51) hide show
  1. package/README.md +2 -2
  2. package/dist/base-command.js +2 -2
  3. package/dist/commands/agents/chat.js +10 -3
  4. package/dist/commands/agents/endpoint/connect.d.ts +24 -0
  5. package/dist/commands/agents/endpoint/connect.js +93 -0
  6. package/dist/commands/agents/endpoint/disable.d.ts +18 -0
  7. package/dist/commands/agents/endpoint/disable.js +44 -0
  8. package/dist/commands/agents/endpoint/enable.d.ts +18 -0
  9. package/dist/commands/agents/endpoint/enable.js +46 -0
  10. package/dist/commands/agents/endpoint/show.d.ts +16 -0
  11. package/dist/commands/agents/endpoint/show.js +45 -0
  12. package/dist/commands/harnesses/install-token.d.ts +4 -4
  13. package/dist/commands/harnesses/install-token.js +4 -4
  14. package/dist/commands/store/acquisitions/list.d.ts +18 -0
  15. package/dist/commands/store/acquisitions/list.js +58 -0
  16. package/dist/commands/store/governance/requests.js +6 -0
  17. package/dist/commands/store/maintainers/remove.d.ts +8 -1
  18. package/dist/commands/store/maintainers/remove.js +29 -4
  19. package/dist/commands/store/reports/confirm-ban.d.ts +19 -0
  20. package/dist/commands/store/reports/confirm-ban.js +57 -0
  21. package/dist/commands/store/reports/disposition.d.ts +21 -0
  22. package/dist/commands/store/reports/disposition.js +76 -0
  23. package/dist/commands/store/reports/list.d.ts +17 -0
  24. package/dist/commands/store/reports/list.js +79 -0
  25. package/dist/commands/store/reports/withdraw-ban.d.ts +18 -0
  26. package/dist/commands/store/reports/withdraw-ban.js +48 -0
  27. package/dist/commands/store/updates.js +9 -5
  28. package/dist/commands/workspaces/audit.d.ts +30 -0
  29. package/dist/commands/workspaces/audit.js +145 -0
  30. package/dist/lib/agent-endpoints.d.ts +62 -0
  31. package/dist/lib/agent-endpoints.js +64 -0
  32. package/dist/lib/agentic-stream.d.ts +84 -17
  33. package/dist/lib/agentic-stream.js +207 -36
  34. package/dist/lib/auth-storage.d.ts +1 -1
  35. package/dist/lib/auth-storage.js +1 -1
  36. package/dist/lib/daemonBroker.d.ts +1 -1
  37. package/dist/lib/daemonBroker.js +3 -4
  38. package/dist/lib/harness-context.js +1 -5
  39. package/dist/lib/store-acquisition.d.ts +2 -0
  40. package/dist/lib/store-acquisition.js +18 -1
  41. package/dist/lib/store-moderation.d.ts +95 -0
  42. package/dist/lib/store-moderation.js +51 -0
  43. package/dist/lib/workspaces.d.ts +73 -0
  44. package/dist/lib/workspaces.js +19 -0
  45. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/daemonPair.js +1 -1
  46. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/daemonPair.js +1 -1
  47. package/dist/node_modules/@skrr-ai/data-provider/index.js +4324 -4294
  48. package/oclif.manifest.json +43429 -42673
  49. package/package.json +4 -3
  50. package/dist/commands/pair.d.ts +0 -67
  51. package/dist/commands/pair.js +0 -351
package/README.md CHANGED
@@ -404,7 +404,7 @@ PKCE / device-code flows. (The recovery-code path is unaffected.)
404
404
 
405
405
  ### Auto-broker on first use
406
406
 
407
- Every `sky` command (except `login`, `logout`, `pair`,
407
+ Every `sky` command (except `login`, `logout`,
408
408
  `generate-recovery-code`) runs the daemon-broker handoff transparently
409
409
  when no token is in the keychain. So:
410
410
 
@@ -424,7 +424,7 @@ There is no opt-in flag. The mechanism is the long-term default.
424
424
  controls auth out-of-band — CI runners, ephemeral containers)
425
425
  - `OVERSKY_SKIP_DAEMON_BROKER=1` (explicit escape hatch for debugging
426
426
  or testing the PKCE flow itself)
427
- - The command is one of `login`, `logout`, `pair`,
427
+ - The command is one of `login`, `logout`,
428
428
  `generate-recovery-code` — these manage their own auth lifecycle
429
429
 
430
430
  **Failure handling.** If the broker can't reach the daemon, can't read
@@ -355,9 +355,9 @@ class BaseCommand extends core_1.Command {
355
355
  flagToken: parsed.token,
356
356
  bareMode: this.bareMode,
357
357
  // Auth recovery/cleanup must stay reachable even when the persisted
358
- // envelope cannot initialize. Login/pair replace local authority;
358
+ // envelope cannot initialize. Login replaces local authority;
359
359
  // logout must always be able to erase it.
360
- allowUnreadableStoredCredential: this.id === 'login' || this.id === 'logout' || this.id === 'pair',
360
+ allowUnreadableStoredCredential: this.id === 'login' || this.id === 'logout',
361
361
  });
362
362
  let ignoredStoredCredential = null;
363
363
  if (!this.resolvedCredential.token && !this.bareMode && !parsed.token && !harnessContext) {
@@ -265,8 +265,13 @@ class AgentsChat extends base_command_1.BaseCommand {
265
265
  'so folding both doubles the answer: pick ONE lane. Inside a `session.output`, ' +
266
266
  '`envelopes[].__seq` is the dedupe key and the ordering key — the same envelope is ' +
267
267
  'delivered by more than one room, and a re-delivery repeats its `__seq`. A ' +
268
- '`stream.gap` event means envelopes in that seq range never arrived and the streamed ' +
269
- 'text is short; `run.result` and the persisted message remain authoritative. Tool ' +
268
+ '`stream.gap` event means envelopes in that seq range never arrived and replay from ' +
269
+ 'the server could not recover them; a hole replay fills, or one that held only ' +
270
+ 'invisible envelopes (`service`, `status`), emits nothing. When the persisted message ' +
271
+ 'could be checked, `verified` is true and `missing` names what the stream is short of ' +
272
+ '(`text`, `tool`), and the event arrives just before the terminal event; `verified: ' +
273
+ 'false` means it could not be checked and the text MAY be short. `run.result` and the ' +
274
+ 'persisted message remain authoritative. Tool ' +
270
275
  'calls arrive as `tool.started` / `tool.completed`, once per `toolUseId`, on cloud ' +
271
276
  'and local-harness runs alike. A `session.notice` with `notice: ' +
272
277
  '"harness-session-reset"` means the local harness could not resume its previous ' +
@@ -376,7 +381,9 @@ class AgentsChat extends base_command_1.BaseCommand {
376
381
  this.requireAuth();
377
382
  const { args, flags } = await this.parse(AgentsChat);
378
383
  if (flags.quick && flags.task)
379
- this.error('--task requires a runtime session; remove --quick to bind this turn.', { exit: 2 });
384
+ this.error('--task requires a runtime session; remove --quick to bind this turn.', {
385
+ exit: 2,
386
+ });
380
387
  if (flags.json && !flags['no-stream'] && !flags.quick) {
381
388
  this.error('--json is only supported with --no-stream or --quick; use --jsonl for streaming.', {
382
389
  exit: 2,
@@ -0,0 +1,24 @@
1
+ import { BaseCommand } from '../../../base-command';
2
+ /**
3
+ * Mint a key that can call this agent's hosted endpoint — and nothing else —
4
+ * and print the URL plus the line that registers it with an MCP client.
5
+ *
6
+ * The key carries ONLY `agents:invoke`: it cannot edit an agent, list sessions,
7
+ * or write environments. It belongs to a Space you own, and turns run as you,
8
+ * billed to the payer shown. The secret is shown once.
9
+ */
10
+ export default class AgentsEndpointConnect extends BaseCommand {
11
+ static description: string;
12
+ static examples: string[];
13
+ static args: {
14
+ id: import("@oclif/core/lib/interfaces").Arg<string, Record<string, unknown>>;
15
+ };
16
+ static flags: {
17
+ space: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
18
+ name: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
19
+ env: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
20
+ 'expires-at': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
21
+ json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
22
+ };
23
+ run(): Promise<void>;
24
+ }
@@ -0,0 +1,93 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const core_1 = require("@oclif/core");
4
+ const base_command_1 = require("../../../base-command");
5
+ const agent_endpoints_1 = require("../../../lib/agent-endpoints");
6
+ const managed_agent_keys_1 = require("../../../lib/managed-agent-keys");
7
+ /**
8
+ * Mint a key that can call this agent's hosted endpoint — and nothing else —
9
+ * and print the URL plus the line that registers it with an MCP client.
10
+ *
11
+ * The key carries ONLY `agents:invoke`: it cannot edit an agent, list sessions,
12
+ * or write environments. It belongs to a Space you own, and turns run as you,
13
+ * billed to the payer shown. The secret is shown once.
14
+ */
15
+ class AgentsEndpointConnect extends base_command_1.BaseCommand {
16
+ static description = "Mint an agents:invoke key for an agent's hosted MCP endpoint and print how to connect a client (secret shown once)";
17
+ static examples = [
18
+ '<%= config.bin %> agents endpoint connect <agent-id> --space <space-id>',
19
+ '<%= config.bin %> agents endpoint connect <agent-id> --space <space-id> --json',
20
+ ];
21
+ static args = {
22
+ id: core_1.Args.string({
23
+ description: 'Agent ID (for a Store agent, your installed copy)',
24
+ required: true,
25
+ ignoreStdin: true,
26
+ }),
27
+ };
28
+ static flags = {
29
+ space: core_1.Flags.string({
30
+ description: 'A Space you own; the key is held by it and turns run in its workspace',
31
+ required: true,
32
+ }),
33
+ name: core_1.Flags.string({ description: 'Label for the key (default: mcp <agent-id>)' }),
34
+ env: core_1.Flags.string({ description: 'Key environment', options: ['live', 'test'] }),
35
+ 'expires-at': core_1.Flags.string({ description: 'ISO 8601 expiry; must be in the future' }),
36
+ json: core_1.Flags.boolean({ description: 'Output as JSON' }),
37
+ };
38
+ async run() {
39
+ this.requireAuth();
40
+ const { args, flags } = await this.parse(AgentsEndpointConnect);
41
+ let endpoint;
42
+ try {
43
+ endpoint = await (0, agent_endpoints_1.getAgentEndpoint)(args.id);
44
+ }
45
+ catch (err) {
46
+ this.handleApiError(err);
47
+ }
48
+ if (!endpoint)
49
+ return;
50
+ if (!endpoint.url || endpoint.kind === 'not_eligible') {
51
+ this.error(endpoint.blocked_by?.message || 'This agent has no hosted endpoint.', { exit: 1 });
52
+ }
53
+ let minted;
54
+ try {
55
+ minted = await (0, managed_agent_keys_1.createManagedAgentKey)({
56
+ spaceId: flags.space,
57
+ name: flags.name || `mcp ${args.id}`.slice(0, 200),
58
+ env: flags.env,
59
+ scopes: [agent_endpoints_1.AGENT_ENDPOINT_SCOPE],
60
+ expiresAt: flags['expires-at'],
61
+ });
62
+ }
63
+ catch (err) {
64
+ this.handleApiError(err);
65
+ }
66
+ if (!minted)
67
+ return;
68
+ if (flags.json) {
69
+ this.log(JSON.stringify({ endpoint, key: minted, client_command: (0, agent_endpoints_1.mcpClientCommand)(endpoint, minted.secret) }, null, 2));
70
+ return;
71
+ }
72
+ (0, agent_endpoints_1.printAgentEndpoint)(this, endpoint);
73
+ this.log('');
74
+ this.log(`Key ${minted.id} (scope ${agent_endpoints_1.AGENT_ENDPOINT_SCOPE} only)`);
75
+ this.log(`Secret ${minted.secret}`);
76
+ this.log(minted.secret_warning ||
77
+ 'This is the only time the secret will be displayed. Store it securely.');
78
+ this.log('');
79
+ this.log('Register it with Claude Code:');
80
+ this.log(` ${(0, agent_endpoints_1.mcpClientCommand)(endpoint, minted.secret)}`);
81
+ if (!endpoint.enabled) {
82
+ this.log('');
83
+ this.log(`The endpoint is OFF. Turn it on with: skrr agents endpoint enable ${args.id}`);
84
+ }
85
+ else if (endpoint.blocked_by) {
86
+ this.log('');
87
+ this.log(`Turns are refused right now: ${endpoint.blocked_by.code} — ${endpoint.blocked_by.message}`);
88
+ }
89
+ this.log('');
90
+ this.log('Replies come from the agent’s configuration: treat them as untrusted tool output.');
91
+ }
92
+ }
93
+ exports.default = AgentsEndpointConnect;
@@ -0,0 +1,18 @@
1
+ import { BaseCommand } from '../../../base-command';
2
+ /**
3
+ * Turn OFF the hosted MCP endpoint of a Store agent you installed. Takes effect
4
+ * at the next turn: a session already created is refused with
5
+ * `endpoint_not_enabled`; its history stays readable. Keys are untouched —
6
+ * revoke them with `skrr api-keys revoke` if they should stop working anywhere.
7
+ */
8
+ export default class AgentsEndpointDisable extends BaseCommand {
9
+ static description: string;
10
+ static examples: string[];
11
+ static args: {
12
+ id: import("@oclif/core/lib/interfaces").Arg<string, Record<string, unknown>>;
13
+ };
14
+ static flags: {
15
+ json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
16
+ };
17
+ run(): Promise<void>;
18
+ }
@@ -0,0 +1,44 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const core_1 = require("@oclif/core");
4
+ const base_command_1 = require("../../../base-command");
5
+ const agent_endpoints_1 = require("../../../lib/agent-endpoints");
6
+ /**
7
+ * Turn OFF the hosted MCP endpoint of a Store agent you installed. Takes effect
8
+ * at the next turn: a session already created is refused with
9
+ * `endpoint_not_enabled`; its history stays readable. Keys are untouched —
10
+ * revoke them with `skrr api-keys revoke` if they should stop working anywhere.
11
+ */
12
+ class AgentsEndpointDisable extends base_command_1.BaseCommand {
13
+ static description = 'Turn off the hosted MCP endpoint of a Store agent you installed';
14
+ static examples = ['<%= config.bin %> agents endpoint disable <installed-agent-id>'];
15
+ static args = {
16
+ id: core_1.Args.string({
17
+ description: 'Your installed copy’s agent ID',
18
+ required: true,
19
+ ignoreStdin: true,
20
+ }),
21
+ };
22
+ static flags = {
23
+ json: core_1.Flags.boolean({ description: 'Output as JSON' }),
24
+ };
25
+ async run() {
26
+ this.requireAuth();
27
+ const { args, flags } = await this.parse(AgentsEndpointDisable);
28
+ let endpoint;
29
+ try {
30
+ endpoint = await (0, agent_endpoints_1.setAgentEndpointEnabled)(args.id, false);
31
+ }
32
+ catch (err) {
33
+ this.handleApiError(err);
34
+ }
35
+ if (!endpoint)
36
+ return;
37
+ if (flags.json) {
38
+ this.log(JSON.stringify(endpoint, null, 2));
39
+ return;
40
+ }
41
+ (0, agent_endpoints_1.printAgentEndpoint)(this, endpoint);
42
+ }
43
+ }
44
+ exports.default = AgentsEndpointDisable;
@@ -0,0 +1,18 @@
1
+ import { BaseCommand } from '../../../base-command';
2
+ /**
3
+ * Turn ON the hosted MCP endpoint of a Store agent you installed. Off by
4
+ * default: installing was consent to run the release, not to expose it to every
5
+ * harness holding one of your keys. A self-authored agent's endpoint follows
6
+ * its Managed Agents API publication and has no separate switch.
7
+ */
8
+ export default class AgentsEndpointEnable extends BaseCommand {
9
+ static description: string;
10
+ static examples: string[];
11
+ static args: {
12
+ id: import("@oclif/core/lib/interfaces").Arg<string, Record<string, unknown>>;
13
+ };
14
+ static flags: {
15
+ json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
16
+ };
17
+ run(): Promise<void>;
18
+ }
@@ -0,0 +1,46 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const core_1 = require("@oclif/core");
4
+ const base_command_1 = require("../../../base-command");
5
+ const agent_endpoints_1 = require("../../../lib/agent-endpoints");
6
+ /**
7
+ * Turn ON the hosted MCP endpoint of a Store agent you installed. Off by
8
+ * default: installing was consent to run the release, not to expose it to every
9
+ * harness holding one of your keys. A self-authored agent's endpoint follows
10
+ * its Managed Agents API publication and has no separate switch.
11
+ */
12
+ class AgentsEndpointEnable extends base_command_1.BaseCommand {
13
+ static description = 'Turn on the hosted MCP endpoint of a Store agent you installed (off by default)';
14
+ static examples = ['<%= config.bin %> agents endpoint enable <installed-agent-id>'];
15
+ static args = {
16
+ id: core_1.Args.string({
17
+ description: 'Your installed copy’s agent ID',
18
+ required: true,
19
+ ignoreStdin: true,
20
+ }),
21
+ };
22
+ static flags = {
23
+ json: core_1.Flags.boolean({ description: 'Output as JSON' }),
24
+ };
25
+ async run() {
26
+ this.requireAuth();
27
+ const { args, flags } = await this.parse(AgentsEndpointEnable);
28
+ let endpoint;
29
+ try {
30
+ endpoint = await (0, agent_endpoints_1.setAgentEndpointEnabled)(args.id, true);
31
+ }
32
+ catch (err) {
33
+ this.handleApiError(err);
34
+ }
35
+ if (!endpoint)
36
+ return;
37
+ if (flags.json) {
38
+ this.log(JSON.stringify(endpoint, null, 2));
39
+ return;
40
+ }
41
+ (0, agent_endpoints_1.printAgentEndpoint)(this, endpoint);
42
+ this.log('');
43
+ this.log('Connect a client with: skrr agents endpoint connect ' + args.id + ' --space <space-id>');
44
+ }
45
+ }
46
+ exports.default = AgentsEndpointEnable;
@@ -0,0 +1,16 @@
1
+ import { BaseCommand } from '../../../base-command';
2
+ /**
3
+ * Show an agent's hosted MCP endpoint: its URL, whether it is on, the exact
4
+ * release it runs, who pays, and the gate (if any) that would refuse a turn.
5
+ */
6
+ export default class AgentsEndpointShow extends BaseCommand {
7
+ static description: string;
8
+ static examples: string[];
9
+ static args: {
10
+ id: import("@oclif/core/lib/interfaces").Arg<string, Record<string, unknown>>;
11
+ };
12
+ static flags: {
13
+ json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
14
+ };
15
+ run(): Promise<void>;
16
+ }
@@ -0,0 +1,45 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const core_1 = require("@oclif/core");
4
+ const base_command_1 = require("../../../base-command");
5
+ const agent_endpoints_1 = require("../../../lib/agent-endpoints");
6
+ /**
7
+ * Show an agent's hosted MCP endpoint: its URL, whether it is on, the exact
8
+ * release it runs, who pays, and the gate (if any) that would refuse a turn.
9
+ */
10
+ class AgentsEndpointShow extends base_command_1.BaseCommand {
11
+ static description = "Show an agent's hosted MCP endpoint: URL, on/off, the release it runs, who pays, and what would refuse a turn";
12
+ static examples = [
13
+ '<%= config.bin %> agents endpoint show <agent-id>',
14
+ '<%= config.bin %> agents endpoint show <agent-id> --json',
15
+ ];
16
+ static args = {
17
+ id: core_1.Args.string({
18
+ description: 'Agent ID (for a Store agent, your installed copy)',
19
+ required: true,
20
+ ignoreStdin: true,
21
+ }),
22
+ };
23
+ static flags = {
24
+ json: core_1.Flags.boolean({ description: 'Output as JSON' }),
25
+ };
26
+ async run() {
27
+ this.requireAuth();
28
+ const { args, flags } = await this.parse(AgentsEndpointShow);
29
+ let endpoint;
30
+ try {
31
+ endpoint = await (0, agent_endpoints_1.getAgentEndpoint)(args.id);
32
+ }
33
+ catch (err) {
34
+ this.handleApiError(err);
35
+ }
36
+ if (!endpoint)
37
+ return;
38
+ if (flags.json) {
39
+ this.log(JSON.stringify(endpoint, null, 2));
40
+ return;
41
+ }
42
+ (0, agent_endpoints_1.printAgentEndpoint)(this, endpoint);
43
+ }
44
+ }
45
+ exports.default = AgentsEndpointShow;
@@ -2,10 +2,10 @@ import { BaseCommand } from '../../base-command';
2
2
  /**
3
3
  * Mint a token that installs a daemon on another machine.
4
4
  *
5
- * `skrr pair` is the interactive path and remains the one to reach for on a
6
- * machine you are sitting at. This exists for the case pair cannot serve: a
7
- * remote Linux host, provisioned from a script, where nobody will be present to
8
- * complete a browser flow.
5
+ * `skrr login` (or `skrrd pair` with a signed-in phone) is the interactive path
6
+ * and remains the one to reach for on a machine you are sitting at. This exists
7
+ * for the case neither can serve: a remote Linux host, provisioned from a
8
+ * script, where nobody will be present to complete a browser flow.
9
9
  *
10
10
  * The token is printed ONCE. It is a credential that adds a machine to your
11
11
  * fleet, so it is not stored and cannot be re-read.
@@ -6,10 +6,10 @@ const harnesses_1 = require("../../lib/harnesses");
6
6
  /**
7
7
  * Mint a token that installs a daemon on another machine.
8
8
  *
9
- * `skrr pair` is the interactive path and remains the one to reach for on a
10
- * machine you are sitting at. This exists for the case pair cannot serve: a
11
- * remote Linux host, provisioned from a script, where nobody will be present to
12
- * complete a browser flow.
9
+ * `skrr login` (or `skrrd pair` with a signed-in phone) is the interactive path
10
+ * and remains the one to reach for on a machine you are sitting at. This exists
11
+ * for the case neither can serve: a remote Linux host, provisioned from a
12
+ * script, where nobody will be present to complete a browser flow.
13
13
  *
14
14
  * The token is printed ONCE. It is a credential that adds a machine to your
15
15
  * fleet, so it is not stored and cannot be re-read.
@@ -0,0 +1,18 @@
1
+ import { BaseCommand } from '../../../base-command';
2
+ /**
3
+ * Every purchase or install an agent asked to make for you, newest first
4
+ * (OSK-13403). Before this, a request was only reachable by its id — one from
5
+ * a run nobody watched (a scheduled run, a Task run, a Slack message) could
6
+ * only be found by reading the database. Held requests, which a workspace
7
+ * Store policy refused and which wait for a human decision, are marked.
8
+ */
9
+ export default class StoreAcquisitionsList extends BaseCommand {
10
+ static description: string;
11
+ static examples: string[];
12
+ static flags: {
13
+ status: 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,58 @@
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 store_acquisition_1 = require("../../../lib/store-acquisition");
7
+ /**
8
+ * Every purchase or install an agent asked to make for you, newest first
9
+ * (OSK-13403). Before this, a request was only reachable by its id — one from
10
+ * a run nobody watched (a scheduled run, a Task run, a Slack message) could
11
+ * only be found by reading the database. Held requests, which a workspace
12
+ * Store policy refused and which wait for a human decision, are marked.
13
+ */
14
+ class StoreAcquisitionsList extends base_command_1.BaseCommand {
15
+ static description = 'List purchases and installs agents asked to make for you, including those held by a workspace Store policy';
16
+ static examples = [
17
+ '<%= config.bin %> store acquisitions list',
18
+ '<%= config.bin %> store acquisitions list --status pending',
19
+ '<%= config.bin %> store acquisitions list --json',
20
+ ];
21
+ static flags = {
22
+ status: core_1.Flags.string({
23
+ description: 'Only requests in this status',
24
+ options: [...data_provider_1.STORE_ACQUISITION_REQUEST_STATUSES],
25
+ }),
26
+ limit: core_1.Flags.integer({ description: 'How many to show (1-100)', min: 1, max: 100 }),
27
+ json: core_1.Flags.boolean({ description: 'Output as JSON' }),
28
+ };
29
+ async run() {
30
+ this.requireAuth();
31
+ const { flags } = await this.parse(StoreAcquisitionsList);
32
+ let result;
33
+ try {
34
+ result = await data_provider_1.dataService.listStoreAcquisitionRequests({
35
+ ...(flags.status ? { status: flags.status } : {}),
36
+ ...(flags.limit !== undefined ? { limit: flags.limit } : {}),
37
+ });
38
+ }
39
+ catch (err) {
40
+ this.handleApiError(err);
41
+ }
42
+ const requests = result?.requests ?? [];
43
+ if (flags.json) {
44
+ this.log(JSON.stringify(requests, null, 2));
45
+ return;
46
+ }
47
+ if (requests.length === 0) {
48
+ this.log(flags.status ? `No requests in status ${flags.status}.` : 'No requests.');
49
+ return;
50
+ }
51
+ for (const request of requests) {
52
+ this.log((0, store_acquisition_1.describeAcquisitionRequestRow)(request));
53
+ }
54
+ this.log('');
55
+ this.log('Show one with: skrr store acquisitions show <request-id>');
56
+ }
57
+ }
58
+ exports.default = StoreAcquisitionsList;
@@ -106,6 +106,12 @@ class StoreGovernanceRequests extends base_command_1.BaseCommand {
106
106
  this.log(`${request.requestId} ${request.releaseId} ${request.status} by ${request.requesterId}`);
107
107
  if (request.note)
108
108
  this.log(` note: ${request.note}`);
109
+ if (request.acquisitionRequestId) {
110
+ // Opened for an agent's install the policy refused (OSK-13403).
111
+ // Approving here admits the release; the buyer still decides the
112
+ // acquisition itself.
113
+ this.log(` for agent acquisition request: ${request.acquisitionRequestId}`);
114
+ }
109
115
  }
110
116
  }
111
117
  catch (error) {
@@ -1,12 +1,19 @@
1
1
  import { BaseCommand } from '../../../base-command';
2
+ /**
3
+ * `remove` names the user the same way `add` does — `--userId` (OSK-13413).
4
+ * The positional form it shipped with stays accepted, with a deprecation
5
+ * note, so scripts written against it keep working.
6
+ */
2
7
  export default class StoreMaintainersRemove extends BaseCommand {
3
8
  static description: string;
9
+ static examples: string[];
4
10
  static args: {
5
11
  entityType: import("@oclif/core/lib/interfaces").Arg<string, Record<string, unknown>>;
6
12
  entityId: import("@oclif/core/lib/interfaces").Arg<string, Record<string, unknown>>;
7
- userId: import("@oclif/core/lib/interfaces").Arg<string, Record<string, unknown>>;
13
+ userId: import("@oclif/core/lib/interfaces").Arg<string | undefined, Record<string, unknown>>;
8
14
  };
9
15
  static flags: {
16
+ userId: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
10
17
  json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
11
18
  };
12
19
  run(): Promise<void>;
@@ -1,21 +1,46 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const core_1 = require("@oclif/core");
4
- const core_2 = require("@oclif/core");
5
4
  const data_provider_1 = require("@skrr-ai/data-provider");
6
5
  const base_command_1 = require("../../../base-command");
6
+ /**
7
+ * `remove` names the user the same way `add` does — `--userId` (OSK-13413).
8
+ * The positional form it shipped with stays accepted, with a deprecation
9
+ * note, so scripts written against it keep working.
10
+ */
7
11
  class StoreMaintainersRemove extends base_command_1.BaseCommand {
8
12
  static description = 'Revoke a listing maintainer grant';
13
+ static examples = [
14
+ '<%= config.bin %> store maintainers remove skill <skill-id> --userId <user-id>',
15
+ ];
9
16
  static args = {
10
17
  entityType: core_1.Args.string({ required: true, ignoreStdin: true }),
11
18
  entityId: core_1.Args.string({ required: true, ignoreStdin: true }),
12
- userId: core_1.Args.string({ required: true, ignoreStdin: true }),
19
+ userId: core_1.Args.string({
20
+ required: false,
21
+ ignoreStdin: true,
22
+ description: 'Deprecated: pass --userId instead',
23
+ }),
24
+ };
25
+ static flags = {
26
+ userId: core_1.Flags.string({ description: 'The maintainer whose grant is revoked' }),
27
+ json: core_1.Flags.boolean({ description: 'Output JSON' }),
13
28
  };
14
- static flags = { json: core_2.Flags.boolean({ description: 'Output JSON' }) };
15
29
  async run() {
16
30
  this.requireAuth();
17
31
  const { args, flags } = await this.parse(StoreMaintainersRemove);
18
- const result = await data_provider_1.dataService.revokeStoreListingMaintainer(args.entityType, args.entityId, args.userId);
32
+ if (flags.userId && args.userId && flags.userId !== args.userId) {
33
+ this.error('--userId and the deprecated positional user id cannot disagree', { exit: 1 });
34
+ }
35
+ const userId = flags.userId || args.userId;
36
+ if (!userId) {
37
+ this.error('--userId is required', { exit: 1 });
38
+ return;
39
+ }
40
+ if (!flags.userId) {
41
+ this.warn('Passing the user id positionally is deprecated; use `--userId <id>`, as `store maintainers add` does.');
42
+ }
43
+ const result = await data_provider_1.dataService.revokeStoreListingMaintainer(args.entityType, args.entityId, userId);
19
44
  this.log(JSON.stringify(result, null, 2));
20
45
  }
21
46
  }
@@ -0,0 +1,19 @@
1
+ import { BaseCommand } from '../../../base-command';
2
+ /**
3
+ * The SECOND curator on a Store report ban (OSK-12597). A ban is permanent, so
4
+ * one curator's `store reports disposition --action ban` only records a
5
+ * request; this applies it. The server refuses the curator who requested it
6
+ * and any curator conflicted on the listing.
7
+ */
8
+ export default class StoreReportsConfirmBan extends BaseCommand {
9
+ static description: string;
10
+ static examples: string[];
11
+ static args: {
12
+ reportId: import("@oclif/core/lib/interfaces").Arg<string, Record<string, unknown>>;
13
+ };
14
+ static flags: {
15
+ note: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
16
+ json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
17
+ };
18
+ run(): Promise<void>;
19
+ }
@@ -0,0 +1,57 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const core_1 = require("@oclif/core");
4
+ const base_command_1 = require("../../../base-command");
5
+ const store_moderation_1 = require("../../../lib/store-moderation");
6
+ /**
7
+ * The SECOND curator on a Store report ban (OSK-12597). A ban is permanent, so
8
+ * one curator's `store reports disposition --action ban` only records a
9
+ * request; this applies it. The server refuses the curator who requested it
10
+ * and any curator conflicted on the listing.
11
+ */
12
+ class StoreReportsConfirmBan extends base_command_1.BaseCommand {
13
+ static description = 'Confirm a Store report ban another curator requested, which bans the listing (store_curation curators only; not the requester)';
14
+ static examples = [
15
+ '<%= config.bin %> store reports confirm-ban 6abdd6fde81800ed380ad3b2 --note "Verified the token leak"',
16
+ ];
17
+ static args = {
18
+ reportId: core_1.Args.string({
19
+ description: 'The report whose ban is waiting (from `store reports list`)',
20
+ required: true,
21
+ ignoreStdin: true,
22
+ }),
23
+ };
24
+ static flags = {
25
+ note: core_1.Flags.string({
26
+ description: 'Why you confirm (kept on the record; not shown to the publisher)',
27
+ required: true,
28
+ }),
29
+ json: core_1.Flags.boolean({ description: 'Output as JSON' }),
30
+ };
31
+ async run() {
32
+ this.requireAuth();
33
+ const { args, flags } = await this.parse(StoreReportsConfirmBan);
34
+ let result;
35
+ try {
36
+ result = await (0, store_moderation_1.confirmStoreReportBan)(args.reportId, { note: flags.note });
37
+ }
38
+ catch (error) {
39
+ this.handleApiError(error);
40
+ return;
41
+ }
42
+ if (flags.json) {
43
+ this.log(JSON.stringify(result, null, 2));
44
+ return;
45
+ }
46
+ const d = result.disposition;
47
+ if (d.replayed) {
48
+ this.log(`Already banned: report ${d.reportId} on ${d.agentId}. Nothing new was sent to the publisher.`);
49
+ return;
50
+ }
51
+ this.log(`Banned: ${d.agentId} (report ${d.reportId}${d.listingState ? `, listing ${d.listingState}` : ''}). Requested by ${d.requestedBy ?? '-'}, confirmed by you.`);
52
+ this.log(d.publisherNotified
53
+ ? 'The publisher was told the outcome (counts only, never who reported).'
54
+ : 'The ban is in effect, but the publisher notice could not be confirmed.');
55
+ }
56
+ }
57
+ exports.default = StoreReportsConfirmBan;