@skrr-ai/cli 0.1.83 → 0.1.84

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 (48) hide show
  1. package/README.md +2 -2
  2. package/dist/base-command.js +2 -2
  3. package/dist/commands/agents/endpoint/connect.d.ts +24 -0
  4. package/dist/commands/agents/endpoint/connect.js +93 -0
  5. package/dist/commands/agents/endpoint/disable.d.ts +18 -0
  6. package/dist/commands/agents/endpoint/disable.js +44 -0
  7. package/dist/commands/agents/endpoint/enable.d.ts +18 -0
  8. package/dist/commands/agents/endpoint/enable.js +46 -0
  9. package/dist/commands/agents/endpoint/show.d.ts +16 -0
  10. package/dist/commands/agents/endpoint/show.js +45 -0
  11. package/dist/commands/harnesses/install-token.d.ts +4 -4
  12. package/dist/commands/harnesses/install-token.js +4 -4
  13. package/dist/commands/store/acquisitions/list.d.ts +18 -0
  14. package/dist/commands/store/acquisitions/list.js +58 -0
  15. package/dist/commands/store/governance/requests.js +6 -0
  16. package/dist/commands/store/maintainers/remove.d.ts +8 -1
  17. package/dist/commands/store/maintainers/remove.js +29 -4
  18. package/dist/commands/store/reports/confirm-ban.d.ts +19 -0
  19. package/dist/commands/store/reports/confirm-ban.js +57 -0
  20. package/dist/commands/store/reports/disposition.d.ts +21 -0
  21. package/dist/commands/store/reports/disposition.js +76 -0
  22. package/dist/commands/store/reports/list.d.ts +17 -0
  23. package/dist/commands/store/reports/list.js +79 -0
  24. package/dist/commands/store/reports/withdraw-ban.d.ts +18 -0
  25. package/dist/commands/store/reports/withdraw-ban.js +48 -0
  26. package/dist/commands/store/updates.js +9 -5
  27. package/dist/commands/workspaces/audit.d.ts +30 -0
  28. package/dist/commands/workspaces/audit.js +145 -0
  29. package/dist/lib/agent-endpoints.d.ts +62 -0
  30. package/dist/lib/agent-endpoints.js +64 -0
  31. package/dist/lib/auth-storage.d.ts +1 -1
  32. package/dist/lib/auth-storage.js +1 -1
  33. package/dist/lib/daemonBroker.d.ts +1 -1
  34. package/dist/lib/daemonBroker.js +3 -4
  35. package/dist/lib/harness-context.js +1 -5
  36. package/dist/lib/store-acquisition.d.ts +2 -0
  37. package/dist/lib/store-acquisition.js +18 -1
  38. package/dist/lib/store-moderation.d.ts +95 -0
  39. package/dist/lib/store-moderation.js +51 -0
  40. package/dist/lib/workspaces.d.ts +73 -0
  41. package/dist/lib/workspaces.js +21 -0
  42. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/daemonPair.js +1 -1
  43. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/daemonPair.js +1 -1
  44. package/dist/node_modules/@skrr-ai/data-provider/index.js +4324 -4294
  45. package/oclif.manifest.json +22000 -21244
  46. package/package.json +4 -3
  47. package/dist/commands/pair.d.ts +0 -67
  48. package/dist/commands/pair.js +0 -351
@@ -0,0 +1,76 @@
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
+ * Disposition one Store listing report as a `store_curation` curator
8
+ * (OSK-12597). warn / delist / ban are the same disposition the admin control
9
+ * plane's governed command applies: the listing changes and the publisher is
10
+ * told the outcome with per-reason counts, never who reported or what they
11
+ * wrote. The server refuses a curator conflicted on the listing.
12
+ */
13
+ class StoreReportsDisposition extends base_command_1.BaseCommand {
14
+ static description = 'Disposition a Store listing report: dismiss, warn, delist or ban (store_curation curators only)';
15
+ static examples = [
16
+ '<%= config.bin %> store reports disposition 6abdd6fde81800ed380ad3b2 --action warn --note "Confirmed calendar spam"',
17
+ '<%= config.bin %> store reports disposition 6abdd6fde81800ed380ad3b2 --action dismiss --note "Not reproducible on 1.1"',
18
+ ];
19
+ static args = {
20
+ reportId: core_1.Args.string({
21
+ description: 'The report (from `store reports list`)',
22
+ required: true,
23
+ ignoreStdin: true,
24
+ }),
25
+ };
26
+ static flags = {
27
+ action: core_1.Flags.string({
28
+ description: store_moderation_1.STORE_REPORT_DISPOSITIONS.map((action) => `${action}: ${store_moderation_1.STORE_REPORT_DISPOSITION_EFFECTS[action]}`).join(' · '),
29
+ options: [...store_moderation_1.STORE_REPORT_DISPOSITIONS],
30
+ required: true,
31
+ }),
32
+ note: core_1.Flags.string({
33
+ description: 'Why (kept on the record; not shown to the publisher)',
34
+ required: true,
35
+ }),
36
+ json: core_1.Flags.boolean({ description: 'Output as JSON' }),
37
+ };
38
+ async run() {
39
+ this.requireAuth();
40
+ const { args, flags } = await this.parse(StoreReportsDisposition);
41
+ const action = flags.action;
42
+ let result;
43
+ try {
44
+ result = await (0, store_moderation_1.dispositionStoreReport)(args.reportId, { action, note: flags.note });
45
+ }
46
+ catch (error) {
47
+ this.handleApiError(error);
48
+ return;
49
+ }
50
+ if (flags.json) {
51
+ this.log(JSON.stringify(result, null, 2));
52
+ return;
53
+ }
54
+ const d = result.disposition;
55
+ if (d.pendingConfirmation) {
56
+ // A ban is never applied by one curator. Say so plainly, so nobody reads
57
+ // "Recorded" as "banned".
58
+ this.log(`Ban requested on report ${d.reportId} (${d.agentId}). NOT applied yet: the listing is unchanged and the publisher was not told.`);
59
+ this.log(`A different Store curator must run \`store reports confirm-ban ${d.reportId} --note ...\`; \`store reports withdraw-ban ${d.reportId}\` cancels it.`);
60
+ return;
61
+ }
62
+ this.log(`${d.replayed ? 'Already recorded' : 'Recorded'}: report ${d.reportId} on ${d.agentId} -> ${d.action} (report ${d.reportStatus}${d.listingState ? `, listing ${d.listingState}` : ''}).`);
63
+ if (d.action === 'dismiss') {
64
+ this.log('The listing is unchanged and the publisher was not told.');
65
+ }
66
+ else if (d.replayed) {
67
+ this.log('Nothing new was sent to the publisher.');
68
+ }
69
+ else {
70
+ this.log(d.publisherNotified
71
+ ? 'The publisher was told the outcome (counts only, never who reported).'
72
+ : 'The listing change is in effect, but the publisher notice could not be confirmed.');
73
+ }
74
+ }
75
+ }
76
+ exports.default = StoreReportsDisposition;
@@ -0,0 +1,17 @@
1
+ import { BaseCommand } from '../../../base-command';
2
+ /**
3
+ * The Store report moderation queue (OSK-12597) — every report still waiting
4
+ * on a disposition, for a `store_curation` curator. `skrr store reports` (no
5
+ * subcommand) is something else: the reports YOU filed.
6
+ */
7
+ export default class StoreReportsList extends BaseCommand {
8
+ static description: string;
9
+ static examples: string[];
10
+ static flags: {
11
+ agent: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
12
+ limit: import("@oclif/core/lib/interfaces").OptionFlag<number, import("@oclif/core/lib/interfaces").CustomOptions>;
13
+ skip: import("@oclif/core/lib/interfaces").OptionFlag<number, import("@oclif/core/lib/interfaces").CustomOptions>;
14
+ json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
15
+ };
16
+ run(): Promise<void>;
17
+ }
@@ -0,0 +1,79 @@
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
+ const store_moderation_1 = require("../../../lib/store-moderation");
8
+ /**
9
+ * The Store report moderation queue (OSK-12597) — every report still waiting
10
+ * on a disposition, for a `store_curation` curator. `skrr store reports` (no
11
+ * subcommand) is something else: the reports YOU filed.
12
+ */
13
+ class StoreReportsList extends base_command_1.BaseCommand {
14
+ static description = 'List Store listing reports awaiting a disposition (store_curation curators only). For the reports you filed, run `store reports`.';
15
+ static examples = [
16
+ '<%= config.bin %> store reports list',
17
+ '<%= config.bin %> store reports list --agent agent_abc --json',
18
+ ];
19
+ static flags = {
20
+ agent: core_1.Flags.string({ description: 'Only reports on this listing' }),
21
+ limit: core_1.Flags.integer({ description: 'At most this many (1-100)', default: 50 }),
22
+ skip: core_1.Flags.integer({ description: 'Skip this many (paging)', default: 0 }),
23
+ json: core_1.Flags.boolean({ description: 'Output as JSON' }),
24
+ };
25
+ async run() {
26
+ this.requireAuth();
27
+ const { flags } = await this.parse(StoreReportsList);
28
+ let queue;
29
+ try {
30
+ queue = await (0, store_moderation_1.listCuratorStoreReports)({
31
+ agentId: flags.agent,
32
+ limit: flags.limit,
33
+ skip: flags.skip,
34
+ });
35
+ }
36
+ catch (err) {
37
+ this.handleApiError(err);
38
+ return;
39
+ }
40
+ if (flags.json) {
41
+ this.log(JSON.stringify(queue, null, 2));
42
+ return;
43
+ }
44
+ const reports = queue?.reports ?? [];
45
+ if (reports.length === 0) {
46
+ this.log('No Store reports are waiting for a disposition.');
47
+ return;
48
+ }
49
+ (0, format_1.renderTable)(reports.map((report) => ({
50
+ report: report.reportId,
51
+ agent: report.agentId,
52
+ reason: (0, data_provider_1.storeReportReasonLabel)(report.reason),
53
+ version: report.versionLabel ?? '-',
54
+ filed: report.createdAt ? String(report.createdAt).slice(0, 10) : '-',
55
+ // A conflicted curator is told why they cannot act, not the report text.
56
+ detail: [
57
+ report.banRequest
58
+ ? `BAN WAITING for a second curator (requested by ${report.banRequest.requestedBy})`
59
+ : null,
60
+ report.conflict
61
+ ? `conflicted (${report.conflict}) - another curator must decide`
62
+ : (report.description ?? '-'),
63
+ ]
64
+ .filter(Boolean)
65
+ .join(' | '),
66
+ })), [
67
+ { key: 'report', header: 'REPORT', verbatim: true },
68
+ { key: 'agent', header: 'LISTING', verbatim: true },
69
+ { key: 'reason', header: 'REASON' },
70
+ { key: 'version', header: 'VERSION' },
71
+ { key: 'filed', header: 'FILED' },
72
+ { key: 'detail', header: 'DETAIL', maxWidth: 60 },
73
+ ], (line) => this.log(line));
74
+ if (queue && queue.total > queue.skip + reports.length) {
75
+ this.log(`${queue.total - queue.skip - reports.length} more; page with --skip ${queue.skip + reports.length}.`);
76
+ }
77
+ }
78
+ }
79
+ exports.default = StoreReportsList;
@@ -0,0 +1,18 @@
1
+ import { BaseCommand } from '../../../base-command';
2
+ /**
3
+ * Withdraw a Store report ban that is still waiting for a second curator
4
+ * (OSK-12597). The listing was never touched, and the report goes back to
5
+ * waiting for a disposition.
6
+ */
7
+ export default class StoreReportsWithdrawBan extends BaseCommand {
8
+ static description: string;
9
+ static examples: string[];
10
+ static args: {
11
+ reportId: import("@oclif/core/lib/interfaces").Arg<string, Record<string, unknown>>;
12
+ };
13
+ static flags: {
14
+ note: import("@oclif/core/lib/interfaces").OptionFlag<string | 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,48 @@
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
+ * Withdraw a Store report ban that is still waiting for a second curator
8
+ * (OSK-12597). The listing was never touched, and the report goes back to
9
+ * waiting for a disposition.
10
+ */
11
+ class StoreReportsWithdrawBan extends base_command_1.BaseCommand {
12
+ static description = 'Withdraw a Store report ban still waiting for a second curator (store_curation curators only)';
13
+ static examples = [
14
+ '<%= config.bin %> store reports withdraw-ban 6abdd6fde81800ed380ad3b2 --note "Requested on the wrong listing"',
15
+ ];
16
+ static args = {
17
+ reportId: core_1.Args.string({
18
+ description: 'The report whose ban is waiting',
19
+ required: true,
20
+ ignoreStdin: true,
21
+ }),
22
+ };
23
+ static flags = {
24
+ note: core_1.Flags.string({ description: 'Why (kept on the record)' }),
25
+ json: core_1.Flags.boolean({ description: 'Output as JSON' }),
26
+ };
27
+ async run() {
28
+ this.requireAuth();
29
+ const { args, flags } = await this.parse(StoreReportsWithdrawBan);
30
+ let result;
31
+ try {
32
+ result = await (0, store_moderation_1.withdrawStoreReportBan)(args.reportId, flags.note ? { note: flags.note } : {});
33
+ }
34
+ catch (error) {
35
+ this.handleApiError(error);
36
+ return;
37
+ }
38
+ if (flags.json) {
39
+ this.log(JSON.stringify(result, null, 2));
40
+ return;
41
+ }
42
+ const w = result.withdrawal;
43
+ this.log(w.withdrawn
44
+ ? `Withdrawn: the ban on report ${w.reportId} (requested by ${w.withdrawnRequest?.requestedBy ?? '-'}) will not be applied. The report is waiting for a disposition again.`
45
+ : `No ban was waiting on report ${w.reportId}; nothing changed.`);
46
+ }
47
+ }
48
+ exports.default = StoreReportsWithdrawBan;
@@ -60,11 +60,15 @@ class StoreUpdates extends base_command_1.BaseCommand {
60
60
  waiting: update.versionLabel ?? '-',
61
61
  detail: pending?.reason === 'conflict'
62
62
  ? `you both changed ${(pending.conflicts ?? []).join(', ') || 'a field'}`
63
- : pending?.reason === 'capability_widened'
64
- ? `adds capabilities: ${(pending.capabilities ?? [])
65
- .map((row) => `${row.field} (${row.added.join(', ')})`)
66
- .join('; ') || 'new powers'}`
67
- : 'the version your copy came from is unknown',
63
+ : pending?.reason === 'dependency_unresolved'
64
+ ? `requires a Skill you have not installed: ${(pending.missingDependencies ?? [])
65
+ .map((dep) => dep.name || dep.entityId)
66
+ .join(', ') || 'a required Skill'}`
67
+ : pending?.reason === 'capability_widened'
68
+ ? `adds capabilities: ${(pending.capabilities ?? [])
69
+ .map((row) => `${row.field} (${row.added.join(', ')})`)
70
+ .join('; ') || 'new powers'}`
71
+ : 'the version your copy came from is unknown',
68
72
  });
69
73
  }
70
74
  if (update?.state === 'buy') {
@@ -0,0 +1,30 @@
1
+ import { BaseCommand } from '../../base-command';
2
+ import { type WorkspaceAgentAuditEvent } from '../../lib/workspaces';
3
+ /**
4
+ * `skrr workspaces audit <workspace-id>` — the workspace's third-party (Store)
5
+ * agent audit trail: installs, updates and rollbacks, uninstalls, licenses that
6
+ * lapsed or were restored, and members' decisions on purchases an agent asked
7
+ * for (OSK-12588).
8
+ *
9
+ * Owner/admin only, and it needs no audit export configured: it reads the same
10
+ * enterprise audit rows the S3 export would ship.
11
+ */
12
+ export default class WorkspacesAudit extends BaseCommand {
13
+ static description: string;
14
+ static examples: string[];
15
+ static args: {
16
+ workspaceId: import("@oclif/core/lib/interfaces").Arg<string, Record<string, unknown>>;
17
+ };
18
+ static flags: {
19
+ kind: import("@oclif/core/lib/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
20
+ since: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
21
+ until: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
22
+ limit: import("@oclif/core/lib/interfaces").OptionFlag<number | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
23
+ cursor: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
24
+ all: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
25
+ json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
26
+ };
27
+ run(): Promise<void>;
28
+ }
29
+ export declare function describeAuditKind(event: WorkspaceAgentAuditEvent): string;
30
+ export declare function describeAuditActor(event: WorkspaceAgentAuditEvent): string;
@@ -0,0 +1,145 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.describeAuditKind = describeAuditKind;
4
+ exports.describeAuditActor = describeAuditActor;
5
+ const core_1 = require("@oclif/core");
6
+ const base_command_1 = require("../../base-command");
7
+ const format_1 = require("../../lib/format");
8
+ const workspaces_1 = require("../../lib/workspaces");
9
+ /** `--all` follows cursors, but never without bound. */
10
+ const MAX_PAGES = 50;
11
+ /**
12
+ * `skrr workspaces audit <workspace-id>` — the workspace's third-party (Store)
13
+ * agent audit trail: installs, updates and rollbacks, uninstalls, licenses that
14
+ * lapsed or were restored, and members' decisions on purchases an agent asked
15
+ * for (OSK-12588).
16
+ *
17
+ * Owner/admin only, and it needs no audit export configured: it reads the same
18
+ * enterprise audit rows the S3 export would ship.
19
+ */
20
+ class WorkspacesAudit extends base_command_1.BaseCommand {
21
+ static description = "List a workspace's third-party agent audit events (install, update/rollback, uninstall, lapse/restore, purchase approvals). Owner or admin only.";
22
+ static examples = [
23
+ '<%= config.bin %> workspaces audit <workspace-id>',
24
+ '<%= config.bin %> workspaces audit <workspace-id> --kind installed --kind updated',
25
+ '<%= config.bin %> workspaces audit <workspace-id> --since 2026-09-01T00:00:00Z --all --json',
26
+ ];
27
+ static args = {
28
+ workspaceId: core_1.Args.string({ description: 'Workspace ID', required: true, ignoreStdin: true }),
29
+ };
30
+ static flags = {
31
+ kind: core_1.Flags.string({
32
+ description: 'Only these kinds (repeatable or comma-separated): installed, updated, uninstalled, lapsed, restored, acquisition_decided',
33
+ multiple: true,
34
+ }),
35
+ since: core_1.Flags.string({ description: 'Events at or after this ISO-8601 time' }),
36
+ until: core_1.Flags.string({ description: 'Events before this ISO-8601 time' }),
37
+ limit: core_1.Flags.integer({ description: 'Events per page (1-200, default 50)' }),
38
+ cursor: core_1.Flags.string({ description: 'Continue from a previous page (nextCursor)' }),
39
+ all: core_1.Flags.boolean({ description: `Follow every page (up to ${MAX_PAGES})` }),
40
+ json: core_1.Flags.boolean({ description: 'Output as JSON' }),
41
+ };
42
+ async run() {
43
+ this.requireAuth();
44
+ const { args, flags } = await this.parse(WorkspacesAudit);
45
+ const kinds = (flags.kind ?? [])
46
+ .flatMap((value) => value.split(','))
47
+ .map((value) => value.trim())
48
+ .filter(Boolean);
49
+ const events = [];
50
+ let last;
51
+ let cursor = flags.cursor;
52
+ try {
53
+ for (let page = 0; page < (flags.all ? MAX_PAGES : 1); page += 1) {
54
+ last = await (0, workspaces_1.listWorkspaceAgentAudit)(args.workspaceId, {
55
+ kinds,
56
+ since: flags.since,
57
+ until: flags.until,
58
+ limit: flags.limit,
59
+ cursor,
60
+ });
61
+ events.push(...last.events);
62
+ if (!last.hasMore || !last.nextCursor || last.nextCursor === cursor)
63
+ break;
64
+ cursor = last.nextCursor;
65
+ }
66
+ }
67
+ catch (err) {
68
+ this.handleApiError(err);
69
+ return;
70
+ }
71
+ const nextCursor = last?.hasMore ? (last.nextCursor ?? null) : null;
72
+ if (flags.json) {
73
+ this.log(JSON.stringify({
74
+ workspaceId: args.workspaceId,
75
+ events,
76
+ hasMore: Boolean(last?.hasMore),
77
+ nextCursor,
78
+ coverage: last?.coverage ?? null,
79
+ }, null, 2));
80
+ return;
81
+ }
82
+ if (events.length === 0) {
83
+ this.log('No third-party agent audit events match.');
84
+ }
85
+ else {
86
+ (0, format_1.renderTable)(events.map(toRow), [
87
+ { key: 'at', header: 'AT' },
88
+ { key: 'kind', header: 'KIND' },
89
+ { key: 'actor', header: 'ACTOR' },
90
+ { key: 'member', header: 'MEMBER' },
91
+ { key: 'listing', header: 'LISTING' },
92
+ { key: 'copy', header: 'COPY' },
93
+ { key: 'release', header: 'RELEASE' },
94
+ ], (line) => this.log(line));
95
+ }
96
+ // Say what the trail does not record, so silence is not read as "nothing happened".
97
+ const notRecorded = last?.coverage?.notRecorded ?? [];
98
+ if (notRecorded.length) {
99
+ this.log('');
100
+ this.log(`Not recorded in this trail: ${notRecorded.join(', ')}.`);
101
+ }
102
+ if (nextCursor) {
103
+ this.log(`More events: --cursor ${nextCursor}`);
104
+ }
105
+ }
106
+ }
107
+ exports.default = WorkspacesAudit;
108
+ function describeAuditKind(event) {
109
+ if (event.kind === 'updated' && event.release?.direction === 'rollback')
110
+ return 'rolled back';
111
+ if (event.kind === 'acquisition_decided') {
112
+ const decision = event.outcome?.decision;
113
+ return typeof decision === 'string' ? `purchase ${decision}` : 'purchase decided';
114
+ }
115
+ return event.kind;
116
+ }
117
+ function describeAuditActor(event) {
118
+ const { actor } = event;
119
+ let who;
120
+ if (actor.kind === 'user')
121
+ who = `user ${actor.userId ?? '?'}`;
122
+ else if (actor.kind === 'agent')
123
+ who = `agent ${actor.agentId ?? '?'}`;
124
+ else
125
+ who = `system ${actor.process ?? ''}`.trim();
126
+ if (actor.confirmedBy?.userId)
127
+ who += `, confirmed by user ${actor.confirmedBy.userId}`;
128
+ return who;
129
+ }
130
+ function toRow(event) {
131
+ const subject = event.subject;
132
+ const release = event.release;
133
+ const version = release?.fromVersionLabel && release.versionLabel
134
+ ? `${release.fromVersionLabel} -> ${release.versionLabel}`
135
+ : (release?.versionLabel ?? '');
136
+ return {
137
+ at: event.at,
138
+ kind: describeAuditKind(event),
139
+ actor: describeAuditActor(event),
140
+ member: subject.memberUserId ?? '',
141
+ listing: subject.listingName ?? subject.listingId ?? subject.teamOrderId ?? '',
142
+ copy: subject.installedAgentName ?? subject.installedAgentId ?? '',
143
+ release: version,
144
+ };
145
+ }
@@ -0,0 +1,62 @@
1
+ /**
2
+ * agent-endpoints.ts — request client for `/api/agent-endpoints` (OSK-12611).
3
+ *
4
+ * An agent's hosted endpoint is `/v1/agents/:id/mcp`: an MCP server (Streamable
5
+ * HTTP) that runs YOUR agent — one you published to the Managed Agents API, or a
6
+ * Store agent you installed — in skrr's cloud, as you. These routes are the
7
+ * owner's control surface for it; the endpoint itself is called with an `osk_*`
8
+ * key carrying the `agents:invoke` scope.
9
+ *
10
+ * Paths are inline literals on purpose: `domain-api-parity` resolves a command
11
+ * to an endpoint by reading these strings.
12
+ */
13
+ /** The API's own snake_case projection (`routes/agentEndpoints.js`). */
14
+ export interface AgentEndpoint {
15
+ agent_id: string;
16
+ agent_name: string | null;
17
+ /** `self_authored` | `store_instance` | `not_eligible` */
18
+ kind: string;
19
+ url: string | null;
20
+ transport: string;
21
+ scope: string;
22
+ enabled: boolean;
23
+ enabled_at?: string | null;
24
+ switchable: boolean;
25
+ ready: boolean;
26
+ /** The gate that would refuse a turn right now (see docs/cli/SKRR_AGENT_ENDPOINTS.md). */
27
+ blocked_by: {
28
+ code: string;
29
+ message: string;
30
+ } | null;
31
+ release?: {
32
+ id: string;
33
+ version_label: string | null;
34
+ number?: number;
35
+ } | null;
36
+ payer?: {
37
+ label: string;
38
+ payerKind: string;
39
+ summary: string;
40
+ } | null;
41
+ capabilities?: {
42
+ status: string;
43
+ [key: string]: unknown;
44
+ };
45
+ workspace_id?: string | null;
46
+ }
47
+ export declare function getAgentEndpoint(agentId: string): Promise<AgentEndpoint>;
48
+ /** Turn a Store instance's endpoint on or off. Owner only, enforced server-side. */
49
+ export declare function setAgentEndpointEnabled(agentId: string, enabled: boolean): Promise<AgentEndpoint>;
50
+ /** The scope a key needs to call an endpoint — and the only thing it grants. */
51
+ export declare const AGENT_ENDPOINT_SCOPE = "agents:invoke";
52
+ /**
53
+ * What to tell an MCP client. Claude Code takes a remote HTTP server with a
54
+ * header; any other client needs the same two facts (URL, bearer key).
55
+ */
56
+ export declare function mcpClientCommand(endpoint: AgentEndpoint, secret: string): string;
57
+ /** One human line for the state an endpoint is in. */
58
+ export declare function describeEndpointState(endpoint: AgentEndpoint): string;
59
+ /** The human rendering every `agents endpoint` command prints. */
60
+ export declare function printAgentEndpoint(cmd: {
61
+ log: (line: string) => void;
62
+ }, endpoint: AgentEndpoint): void;
@@ -0,0 +1,64 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.AGENT_ENDPOINT_SCOPE = void 0;
4
+ exports.getAgentEndpoint = getAgentEndpoint;
5
+ exports.setAgentEndpointEnabled = setAgentEndpointEnabled;
6
+ exports.mcpClientCommand = mcpClientCommand;
7
+ exports.describeEndpointState = describeEndpointState;
8
+ exports.printAgentEndpoint = printAgentEndpoint;
9
+ const api_fetch_1 = require("./api-fetch");
10
+ async function getAgentEndpoint(agentId) {
11
+ return (0, api_fetch_1.apiFetch)(`/api/agent-endpoints/${encodeURIComponent(agentId)}`);
12
+ }
13
+ /** Turn a Store instance's endpoint on or off. Owner only, enforced server-side. */
14
+ async function setAgentEndpointEnabled(agentId, enabled) {
15
+ return (0, api_fetch_1.apiFetch)(`/api/agent-endpoints/${encodeURIComponent(agentId)}`, {
16
+ method: 'PUT',
17
+ body: { enabled },
18
+ });
19
+ }
20
+ /** The scope a key needs to call an endpoint — and the only thing it grants. */
21
+ exports.AGENT_ENDPOINT_SCOPE = 'agents:invoke';
22
+ /**
23
+ * What to tell an MCP client. Claude Code takes a remote HTTP server with a
24
+ * header; any other client needs the same two facts (URL, bearer key).
25
+ */
26
+ function mcpClientCommand(endpoint, secret) {
27
+ const name = `skrr-${endpoint.agent_id}`.replace(/[^A-Za-z0-9_-]/g, '-');
28
+ return `claude mcp add --transport http ${name} ${endpoint.url} --header "Authorization: Bearer ${secret}"`;
29
+ }
30
+ /** One human line for the state an endpoint is in. */
31
+ function describeEndpointState(endpoint) {
32
+ if (endpoint.kind === 'not_eligible') {
33
+ return endpoint.blocked_by?.message || 'This agent has no hosted endpoint.';
34
+ }
35
+ if (!endpoint.enabled) {
36
+ return 'off — turn it on with `skrr agents endpoint enable`';
37
+ }
38
+ if (endpoint.blocked_by) {
39
+ return `on, but turns are refused: ${endpoint.blocked_by.code} — ${endpoint.blocked_by.message}`;
40
+ }
41
+ return 'on';
42
+ }
43
+ /** The human rendering every `agents endpoint` command prints. */
44
+ function printAgentEndpoint(cmd, endpoint) {
45
+ cmd.log(`Agent ${endpoint.agent_id}${endpoint.agent_name ? ` (${endpoint.agent_name})` : ''}`);
46
+ cmd.log(`Kind ${endpoint.kind.replace(/_/g, ' ')}`);
47
+ cmd.log(`Endpoint ${describeEndpointState(endpoint)}`);
48
+ if (endpoint.url) {
49
+ cmd.log(`URL ${endpoint.url} (MCP, ${endpoint.transport})`);
50
+ cmd.log(`Key scope ${endpoint.scope}`);
51
+ }
52
+ if (endpoint.release) {
53
+ cmd.log(`Release ${endpoint.release.version_label || 'unlabelled'} (${endpoint.release.id})`);
54
+ }
55
+ if (endpoint.payer) {
56
+ cmd.log(`Who pays ${endpoint.payer.summary}`);
57
+ }
58
+ else if (endpoint.kind !== 'not_eligible') {
59
+ cmd.log('Who pays unknown right now (the billing resolver could not be read)');
60
+ }
61
+ if (endpoint.capabilities) {
62
+ cmd.log(`Manifest ${endpoint.capabilities.status}`);
63
+ }
64
+ }
@@ -22,7 +22,7 @@ export interface AuthBundle {
22
22
  * How a stored refresh family came to exist.
23
23
  *
24
24
  * - `user_login`: a person signed in on purpose (`skrr login` in any of its
25
- * flows, `skrr pair`). On a Dedicated guest this is the one stored family
25
+ * flows). On a Dedicated guest this is the one stored family
26
26
  * the broker-mode retirement must never touch: the person asked for it.
27
27
  * - `daemon_broker`: the local daemon minted it through its hand-off.
28
28
  *
@@ -779,7 +779,7 @@ function writeToBackend(bundle, options = {}) {
779
779
  persistedBundle = { ...bundle, serverOrigin: normalized };
780
780
  }
781
781
  // Always stamp THIS config as the owner — a bundle read back and re-written
782
- // (e.g. `pair`) must not carry a record forward from wherever it came from.
782
+ // must not carry a record forward from wherever it came from.
783
783
  persistedBundle = { ...persistedBundle, owner: ownerFor(persistedBundle) };
784
784
  // Provenance: an explicit one wins (a login or a broker mint creates a new
785
785
  // family); otherwise this is a rotation of the stored family and keeps what
@@ -405,7 +405,7 @@ export declare function findBrokeredHandoffDescriptor(profile?: string): LocalBo
405
405
  * 2. `~/.skrr/cli-auth.json` reads cleanly and carries a refresh token,
406
406
  * 3. its stored `serverOrigin` matches the descriptor's `serverUrl`,
407
407
  * 4. it is not marked `provenance: 'user_login'`. Since OSK-12293 every
408
- * explicit sign-in (`skrr login`, `skrr pair`) records that marker in
408
+ * explicit sign-in (`skrr login`, in any of its flows) records that marker in
409
409
  * the file, so a login the person made seconds ago is kept and used;
410
410
  * an unmarked file was written by a CLI that predates the marker.
411
411
  *
@@ -1024,7 +1024,7 @@ function findBrokeredHandoffDescriptor(profile = 'default') {
1024
1024
  * 2. `~/.skrr/cli-auth.json` reads cleanly and carries a refresh token,
1025
1025
  * 3. its stored `serverOrigin` matches the descriptor's `serverUrl`,
1026
1026
  * 4. it is not marked `provenance: 'user_login'`. Since OSK-12293 every
1027
- * explicit sign-in (`skrr login`, `skrr pair`) records that marker in
1027
+ * explicit sign-in (`skrr login`, in any of its flows) records that marker in
1028
1028
  * the file, so a login the person made seconds ago is kept and used;
1029
1029
  * an unmarked file was written by a CLI that predates the marker.
1030
1030
  *
@@ -1070,7 +1070,7 @@ function retirableCliAuthFamily(descriptorServerUrl) {
1070
1070
  if (!stored?.refreshToken)
1071
1071
  return null;
1072
1072
  // A family a person signed in for on purpose is never a pre-broker
1073
- // leftover: `skrr login` / `skrr pair` stamp it, and a refresh carries the
1073
+ // leftover: `skrr login` stamps it, and a refresh carries the
1074
1074
  // stamp forward. Retiring it undid an explicit guest login on the very next
1075
1075
  // command (OSK-12293). Only an UNMARKED file — written by a CLI that
1076
1076
  // predates the marker — or a daemon-minted one is retired.
@@ -1223,7 +1223,7 @@ async function attemptDaemonBrokerLoginAndPersist(opts) {
1223
1223
  // ---------------------------------------------------------------------
1224
1224
  /**
1225
1225
  * Commands that manage their own auth lifecycle. The auto-broker MUST
1226
- * NOT fire for these — `login` and `pair` run their own minting flows
1226
+ * NOT fire for these — `login` runs its own minting flows
1227
1227
  * (auto-brokering first would burn a needless server round-trip and
1228
1228
  * mint a token that `cliLogin()` would immediately supersede), and
1229
1229
  * `logout` is about CLEARING auth (auto-brokering first would mint a
@@ -1237,7 +1237,6 @@ async function attemptDaemonBrokerLoginAndPersist(opts) {
1237
1237
  const AUTH_SELF_MANAGED_COMMANDS = new Set([
1238
1238
  'login',
1239
1239
  'logout',
1240
- 'pair',
1241
1240
  'generate-recovery-code',
1242
1241
  ]);
1243
1242
  /**
@@ -48,8 +48,4 @@ class HarnessCredentialPersistRefused extends Error {
48
48
  }
49
49
  exports.HarnessCredentialPersistRefused = HarnessCredentialPersistRefused;
50
50
  /** The commands a harness-context process may not run (they own the stored session). */
51
- exports.HARNESS_REFUSED_AUTH_COMMANDS = new Set([
52
- 'login',
53
- 'logout',
54
- 'pair',
55
- ]);
51
+ exports.HARNESS_REFUSED_AUTH_COMMANDS = new Set(['login', 'logout']);
@@ -9,3 +9,5 @@ import type { StoreAcquisitionRequest } from '@skrr-ai/data-provider';
9
9
  * terminal and the card cannot describe one request two ways.
10
10
  */
11
11
  export declare function describeAcquisitionRequestLines(request: StoreAcquisitionRequest): string[];
12
+ /** One request as one line, for `skrr store acquisitions list`. */
13
+ export declare function describeAcquisitionRequestRow(request: StoreAcquisitionRequest): string;