@skrr-ai/cli 0.1.60 → 0.1.62

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 (194) hide show
  1. package/dist/base-command.js +16 -0
  2. package/dist/commands/agents/create.d.ts +1 -0
  3. package/dist/commands/agents/create.js +8 -1
  4. package/dist/commands/agents/delete.d.ts +14 -0
  5. package/dist/commands/agents/delete.js +52 -4
  6. package/dist/commands/agents/eval/index.d.ts +38 -0
  7. package/dist/commands/agents/eval/index.js +157 -0
  8. package/dist/commands/agents/eval/list.d.ts +13 -0
  9. package/dist/commands/agents/eval/list.js +53 -0
  10. package/dist/commands/agents/eval/show.d.ts +13 -0
  11. package/dist/commands/agents/eval/show.js +36 -0
  12. package/dist/commands/agents/import.d.ts +37 -0
  13. package/dist/commands/agents/import.js +233 -0
  14. package/dist/commands/agents/pull.d.ts +27 -0
  15. package/dist/commands/agents/pull.js +82 -0
  16. package/dist/commands/agents/push.d.ts +28 -0
  17. package/dist/commands/agents/push.js +112 -0
  18. package/dist/commands/agents/releases/ci-publish.d.ts +32 -0
  19. package/dist/commands/agents/releases/ci-publish.js +99 -0
  20. package/dist/commands/agents/releases/create.d.ts +3 -0
  21. package/dist/commands/agents/releases/create.js +27 -6
  22. package/dist/commands/agents/releases/known-issues/add.d.ts +19 -0
  23. package/dist/commands/agents/releases/known-issues/add.js +43 -0
  24. package/dist/commands/agents/releases/known-issues/list.d.ts +17 -0
  25. package/dist/commands/agents/releases/known-issues/list.js +55 -0
  26. package/dist/commands/agents/releases/known-issues/update.d.ts +18 -0
  27. package/dist/commands/agents/releases/known-issues/update.js +47 -0
  28. package/dist/commands/agents/releases/list.js +25 -3
  29. package/dist/commands/agents/releases/rollback.js +12 -4
  30. package/dist/commands/agents/releases/test-install.d.ts +22 -0
  31. package/dist/commands/agents/releases/test-install.js +70 -0
  32. package/dist/commands/agents/releases/trusted-publishers/list.d.ts +17 -0
  33. package/dist/commands/agents/releases/trusted-publishers/list.js +55 -0
  34. package/dist/commands/agents/releases/trusted-publishers/remove.d.ts +17 -0
  35. package/dist/commands/agents/releases/trusted-publishers/remove.js +45 -0
  36. package/dist/commands/agents/releases/trusted-publishers/set.d.ts +27 -0
  37. package/dist/commands/agents/releases/trusted-publishers/set.js +82 -0
  38. package/dist/commands/agents/update.d.ts +1 -0
  39. package/dist/commands/agents/update.js +8 -1
  40. package/dist/commands/agents/usage-cap.d.ts +20 -0
  41. package/dist/commands/agents/usage-cap.js +76 -0
  42. package/dist/commands/agents/validate.d.ts +22 -0
  43. package/dist/commands/agents/validate.js +66 -0
  44. package/dist/commands/agents/visibility.d.ts +13 -0
  45. package/dist/commands/agents/visibility.js +84 -2
  46. package/dist/commands/commerce/fees/show.d.ts +19 -0
  47. package/dist/commands/commerce/fees/show.js +75 -0
  48. package/dist/commands/earnings/index.d.ts +15 -0
  49. package/dist/commands/earnings/index.js +46 -0
  50. package/dist/commands/earnings/payouts.d.ts +12 -0
  51. package/dist/commands/earnings/payouts.js +39 -0
  52. package/dist/commands/earnings/statements.d.ts +19 -0
  53. package/dist/commands/earnings/statements.js +70 -0
  54. package/dist/commands/goals/key-results/create.d.ts +1 -1
  55. package/dist/commands/goals/key-results/create.js +5 -1
  56. package/dist/commands/harnesses/show.js +11 -1
  57. package/dist/commands/logout.js +31 -0
  58. package/dist/commands/machines/show.js +10 -1
  59. package/dist/commands/managed-execution/show.d.ts +10 -0
  60. package/dist/commands/managed-execution/show.js +60 -0
  61. package/dist/commands/spaces/show.js +35 -1
  62. package/dist/commands/step-up.d.ts +23 -0
  63. package/dist/commands/step-up.js +96 -0
  64. package/dist/commands/store/acquisitions/approve.d.ts +30 -0
  65. package/dist/commands/store/acquisitions/approve.js +100 -0
  66. package/dist/commands/store/acquisitions/decline.d.ts +17 -0
  67. package/dist/commands/store/acquisitions/decline.js +47 -0
  68. package/dist/commands/store/acquisitions/show.d.ts +16 -0
  69. package/dist/commands/store/acquisitions/show.js +49 -0
  70. package/dist/commands/store/admissions/approve.d.ts +19 -0
  71. package/dist/commands/store/admissions/approve.js +50 -0
  72. package/dist/commands/store/admissions/list.d.ts +15 -0
  73. package/dist/commands/store/admissions/list.js +60 -0
  74. package/dist/commands/store/admissions/refuse.d.ts +18 -0
  75. package/dist/commands/store/admissions/refuse.js +49 -0
  76. package/dist/commands/store/advisories/artifact.d.ts +15 -0
  77. package/dist/commands/store/advisories/artifact.js +25 -0
  78. package/dist/commands/store/advisories/cancel.d.ts +13 -0
  79. package/dist/commands/store/advisories/cancel.js +34 -0
  80. package/dist/commands/store/advisories/close.d.ts +18 -0
  81. package/dist/commands/store/advisories/close.js +51 -0
  82. package/dist/commands/store/advisories/confirm.d.ts +17 -0
  83. package/dist/commands/store/advisories/confirm.js +40 -0
  84. package/dist/commands/store/advisories/issue.d.ts +20 -0
  85. package/dist/commands/store/advisories/issue.js +59 -0
  86. package/dist/commands/store/advisories/list.d.ts +15 -0
  87. package/dist/commands/store/advisories/list.js +49 -0
  88. package/dist/commands/store/advisories/show.d.ts +13 -0
  89. package/dist/commands/store/advisories/show.js +34 -0
  90. package/dist/commands/store/artifacts/release.d.ts +16 -0
  91. package/dist/commands/store/artifacts/release.js +31 -0
  92. package/dist/commands/store/artifacts/used-by.d.ts +12 -0
  93. package/dist/commands/store/artifacts/used-by.js +20 -0
  94. package/dist/commands/store/browse.d.ts +5 -0
  95. package/dist/commands/store/browse.js +28 -1
  96. package/dist/commands/store/channel.d.ts +21 -0
  97. package/dist/commands/store/channel.js +62 -0
  98. package/dist/commands/store/follow.d.ts +14 -0
  99. package/dist/commands/store/follow.js +45 -0
  100. package/dist/commands/store/governance/policy.d.ts +18 -5
  101. package/dist/commands/store/governance/policy.js +80 -12
  102. package/dist/commands/store/governance/requests.d.ts +28 -0
  103. package/dist/commands/store/governance/requests.js +116 -0
  104. package/dist/commands/store/install.d.ts +3 -0
  105. package/dist/commands/store/install.js +101 -2
  106. package/dist/commands/store/issues.d.ts +26 -0
  107. package/dist/commands/store/issues.js +118 -0
  108. package/dist/commands/store/maintainers/add.d.ts +13 -0
  109. package/dist/commands/store/maintainers/add.js +23 -0
  110. package/dist/commands/store/maintainers/remove.d.ts +13 -0
  111. package/dist/commands/store/maintainers/remove.js +22 -0
  112. package/dist/commands/store/publishers/approve.d.ts +11 -0
  113. package/dist/commands/store/publishers/approve.js +25 -0
  114. package/dist/commands/store/publishers/claim.d.ts +12 -0
  115. package/dist/commands/store/publishers/claim.js +20 -0
  116. package/dist/commands/store/publishers/confirm.d.ts +11 -0
  117. package/dist/commands/store/publishers/confirm.js +17 -0
  118. package/dist/commands/store/publishers/domains/begin.d.ts +12 -0
  119. package/dist/commands/store/publishers/domains/begin.js +20 -0
  120. package/dist/commands/store/publishers/domains/list.d.ts +9 -0
  121. package/dist/commands/store/publishers/domains/list.js +19 -0
  122. package/dist/commands/store/publishers/domains/verify.d.ts +12 -0
  123. package/dist/commands/store/publishers/domains/verify.js +20 -0
  124. package/dist/commands/store/publishers/namespaces.d.ts +8 -0
  125. package/dist/commands/store/publishers/namespaces.js +16 -0
  126. package/dist/commands/store/publishers/verified.d.ts +11 -0
  127. package/dist/commands/store/publishers/verified.js +34 -0
  128. package/dist/commands/store/refund.d.ts +22 -0
  129. package/dist/commands/store/refund.js +80 -0
  130. package/dist/commands/store/report.d.ts +20 -0
  131. package/dist/commands/store/report.js +59 -0
  132. package/dist/commands/store/reports.d.ts +11 -0
  133. package/dist/commands/store/reports.js +52 -0
  134. package/dist/commands/store/signals.d.ts +18 -0
  135. package/dist/commands/store/signals.js +43 -0
  136. package/dist/commands/store/star.d.ts +17 -0
  137. package/dist/commands/store/star.js +41 -0
  138. package/dist/commands/store/stars.d.ts +10 -0
  139. package/dist/commands/store/stars.js +33 -0
  140. package/dist/commands/store/trial.d.ts +11 -0
  141. package/dist/commands/store/trial.js +17 -0
  142. package/dist/commands/store/uninstall.d.ts +19 -0
  143. package/dist/commands/store/uninstall.js +118 -0
  144. package/dist/commands/store/update.d.ts +2 -0
  145. package/dist/commands/store/update.js +60 -2
  146. package/dist/commands/store/updates.d.ts +10 -4
  147. package/dist/commands/store/updates.js +60 -39
  148. package/dist/commands/store/watch.d.ts +18 -0
  149. package/dist/commands/store/watch.js +44 -0
  150. package/dist/commands/subscriptions/health.d.ts +12 -0
  151. package/dist/commands/subscriptions/health.js +39 -0
  152. package/dist/commands/subscriptions/list.js +3 -2
  153. package/dist/commands/subscriptions/status.js +7 -1
  154. package/dist/commands/subscriptions/subscribe.d.ts +9 -2
  155. package/dist/commands/subscriptions/subscribe.js +141 -12
  156. package/dist/commands/tasks/comments/list.js +9 -1
  157. package/dist/commands/tasks/labels/attach.js +15 -2
  158. package/dist/commands/tasks/show.js +17 -3
  159. package/dist/commands/tasks/update.js +15 -4
  160. package/dist/commands/tasks/updates/add.js +5 -1
  161. package/dist/lib/agent-config.js +1 -0
  162. package/dist/lib/agent-evals.d.ts +71 -0
  163. package/dist/lib/agent-evals.js +359 -0
  164. package/dist/lib/agent-spec.d.ts +28 -0
  165. package/dist/lib/agent-spec.js +58 -0
  166. package/dist/lib/auth-storage.d.ts +12 -0
  167. package/dist/lib/auth-storage.js +0 -33
  168. package/dist/lib/commerce.d.ts +8 -0
  169. package/dist/lib/commerce.js +10 -0
  170. package/dist/lib/earnings.d.ts +36 -0
  171. package/dist/lib/earnings.js +164 -0
  172. package/dist/lib/github-oidc.d.ts +13 -0
  173. package/dist/lib/github-oidc.js +41 -0
  174. package/dist/lib/governed-store.d.ts +43 -2
  175. package/dist/lib/governed-store.js +25 -1
  176. package/dist/lib/label-ref.js +16 -0
  177. package/dist/lib/managed-execution.d.ts +10 -0
  178. package/dist/lib/managed-execution.js +43 -0
  179. package/dist/lib/principal-display.d.ts +20 -0
  180. package/dist/lib/principal-display.js +64 -0
  181. package/dist/lib/space-template-source.d.ts +14 -0
  182. package/dist/lib/space-template-source.js +41 -0
  183. package/dist/lib/step-up.d.ts +21 -0
  184. package/dist/lib/step-up.js +44 -0
  185. package/dist/lib/store-acquisition.d.ts +11 -0
  186. package/dist/lib/store-acquisition.js +40 -0
  187. package/dist/lib/store-advisories.d.ts +50 -0
  188. package/dist/lib/store-advisories.js +62 -0
  189. package/dist/lib/task-closure.js +1 -1
  190. package/dist/lib/web-url.d.ts +11 -0
  191. package/dist/lib/web-url.js +14 -0
  192. package/dist/node_modules/@skrr-ai/data-provider/index.js +25471 -24177
  193. package/oclif.manifest.json +38931 -34119
  194. package/package.json +21 -3
@@ -0,0 +1,164 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PERIOD_PATTERN = exports.readPayouts = exports.readStatement = exports.readStatements = exports.readAutoPayout = exports.readEarnings = void 0;
4
+ exports.renderEarningsSummary = renderEarningsSummary;
5
+ exports.renderStatementList = renderStatementList;
6
+ exports.renderStatement = renderStatement;
7
+ exports.renderPayoutHistory = renderPayoutHistory;
8
+ const data_provider_1 = require("@skrr-ai/data-provider");
9
+ const format_1 = require("./format");
10
+ /**
11
+ * earnings.ts — the read-only publisher payout surface (OSK-12272).
12
+ *
13
+ * `skrr earnings` reads a publisher's balance, automatic-payout state, monthly
14
+ * statements and payout history from `/api/connect/*`. It is read-only on
15
+ * purpose: requesting a payout and switching automatic payouts on move money,
16
+ * and those routes refuse a daemon credential (`refuseDaemonScope`), so they
17
+ * stay in the web Earnings page where a signed-in person does them.
18
+ *
19
+ * Every read goes through `dataService`, so the path a command reaches is the
20
+ * same one the web page reads, and copy for server vocabularies comes from
21
+ * `@skrr-ai/data-provider` (`connectPayouts.ts`), shared with that page.
22
+ */
23
+ const readEarnings = () => data_provider_1.dataService.getConnectEarnings();
24
+ exports.readEarnings = readEarnings;
25
+ const readAutoPayout = () => data_provider_1.dataService.getConnectAutoPayout();
26
+ exports.readAutoPayout = readAutoPayout;
27
+ const readStatements = (params) => data_provider_1.dataService.getConnectStatements(params);
28
+ exports.readStatements = readStatements;
29
+ const readStatement = (period) => data_provider_1.dataService.getConnectStatement(period);
30
+ exports.readStatement = readStatement;
31
+ const readPayouts = (params) => data_provider_1.dataService.getConnectPayoutHistory(params);
32
+ exports.readPayouts = readPayouts;
33
+ exports.PERIOD_PATTERN = /^\d{4}-(0[1-9]|1[0-2])$/;
34
+ function dollars(usd) {
35
+ if (usd == null || usd === '')
36
+ return '-';
37
+ const trimmed = String(usd).replace(/^\$/, '');
38
+ return trimmed.startsWith('-') ? `-$${trimmed.slice(1)}` : `$${trimmed}`;
39
+ }
40
+ function day(value) {
41
+ if (!value)
42
+ return '-';
43
+ const date = value instanceof Date ? value : new Date(value);
44
+ return Number.isNaN(date.getTime()) ? '-' : date.toISOString().slice(0, 10);
45
+ }
46
+ /** `skrr earnings`: the balance, then how and when it is paid out. */
47
+ function renderEarningsSummary(earnings, autoPayout, log) {
48
+ log('Publisher earnings');
49
+ log(` Available: ${dollars(earnings.usd.available)}`);
50
+ log(` Pending: ${dollars(earnings.usd.pending)} (on hold until the refund window ends)`);
51
+ log(` Lifetime: ${dollars(earnings.usd.lifetimeEarnings)}`);
52
+ log('');
53
+ if (!earnings.connectOnboarded) {
54
+ log('Payouts: not set up — set up payouts on the Earnings page to be paid.');
55
+ return;
56
+ }
57
+ log(`Payouts: minimum ${dollars(earnings.minPayoutUsd)}, at most one per payout window`);
58
+ if (!autoPayout) {
59
+ return;
60
+ }
61
+ log(` Window: every ${autoPayout.cadenceDays} days`);
62
+ // The same state the web page reads: a date only while it is still ahead,
63
+ // and an open window says what it is waiting for when the balance is short.
64
+ const windowState = (0, data_provider_1.connectAutoPayoutWindowState)(autoPayout);
65
+ if (windowState === 'opens_later') {
66
+ log(` Next opens: ${day(autoPayout.windowOpensAt)}`);
67
+ }
68
+ else if (windowState === 'open') {
69
+ log(' Next opens: open now');
70
+ }
71
+ else {
72
+ log(` Next opens: open now — waiting for the available balance to reach ${dollars(autoPayout.minimumUsd)} (it is ${dollars(autoPayout.availableUsd)})`);
73
+ }
74
+ log(` Automatic: ${autoPayout.enabled
75
+ ? 'on — paid out within the hour the window opens, when the available balance meets the minimum'
76
+ : 'off — turn it on from the Earnings page'}`);
77
+ const last = (0, data_provider_1.describeConnectAutoPayoutAttempt)(autoPayout.lastAutoPayout);
78
+ if (last && autoPayout.lastAutoPayout) {
79
+ log(` Last automatic payout (${day(autoPayout.lastAutoPayout.at)}): ${last}`);
80
+ }
81
+ }
82
+ /** `skrr earnings statements`: one row per month, newest first. */
83
+ function renderStatementList(result, log) {
84
+ if (result.statements.length === 0) {
85
+ log('No statements yet. A statement is issued on the 1st for the month that just ended.');
86
+ return;
87
+ }
88
+ (0, format_1.renderTable)(result.statements.map((statement) => ({
89
+ period: statement.period,
90
+ opening: dollars(statement.openingBalance.totalUsd),
91
+ net: dollars(statement.netChangeUsd),
92
+ closing: dollars(statement.closingBalance.totalUsd),
93
+ available: dollars(statement.closingBalance.availableUsd),
94
+ reconciles: statement.unreconciled ? `off by ${dollars(statement.unreconciledUsd)}` : 'yes',
95
+ })), [
96
+ { key: 'period', header: 'MONTH' },
97
+ { key: 'opening', header: 'OPENING' },
98
+ { key: 'net', header: 'NET CHANGE' },
99
+ { key: 'closing', header: 'CLOSING' },
100
+ { key: 'available', header: 'OF WHICH AVAILABLE' },
101
+ { key: 'reconciles', header: 'RECONCILES' },
102
+ ], log);
103
+ if (result.hasNextPage && result.nextCursor) {
104
+ log('');
105
+ log(`More: skrr earnings statements --cursor ${result.nextCursor}`);
106
+ }
107
+ }
108
+ function balanceLine(label, balance) {
109
+ return `${label}${dollars(balance.totalUsd)} (available ${dollars(balance.availableUsd)}, pending ${dollars(balance.pendingUsd)})`;
110
+ }
111
+ /** `skrr earnings statements <YYYY-MM>`: the whole statement, opening to closing. */
112
+ function renderStatement(statement, log) {
113
+ log(`Statement for ${statement.period} (UTC)`);
114
+ log(balanceLine(' Opening balance ', statement.openingBalance));
115
+ log(` ${(0, data_provider_1.describeConnectStatementOpening)(statement.openingBasis)}`);
116
+ log('');
117
+ (0, format_1.renderTable)(data_provider_1.CONNECT_STATEMENT_LINES.map((line) => {
118
+ const entry = statement.activity[line.key];
119
+ const signed = line.sign === 0
120
+ ? dollars(entry.amountUsd)
121
+ : `${line.sign < 0 ? '-' : '+'}${dollars(entry.amountUsd)}`;
122
+ return {
123
+ line: line.label,
124
+ count: String(entry.count),
125
+ amount: line.sign === 0 ? `${signed} (moved, not added)` : signed,
126
+ };
127
+ }), [
128
+ { key: 'line', header: 'ACTIVITY' },
129
+ { key: 'count', header: 'COUNT' },
130
+ { key: 'amount', header: 'AMOUNT' },
131
+ ], log);
132
+ log('');
133
+ log(` Net change ${dollars(statement.netChangeUsd)}`);
134
+ log(balanceLine(' Closing balance ', statement.closingBalance));
135
+ const unreconciled = (0, data_provider_1.describeConnectStatementUnreconciled)(statement);
136
+ if (unreconciled) {
137
+ log('');
138
+ log(` ${unreconciled}`);
139
+ }
140
+ }
141
+ /** `skrr earnings payouts`: the payout ledger, newest first. */
142
+ function renderPayoutHistory(result, log) {
143
+ if (result.payouts.length === 0) {
144
+ log('No payouts yet.');
145
+ return;
146
+ }
147
+ (0, format_1.renderTable)(result.payouts.map((payout) => ({
148
+ requested: day(payout.requestedAt),
149
+ amount: dollars(payout.amountUsd),
150
+ status: payout.status,
151
+ settled: day(payout.platformSettledAt ?? payout.completedAt),
152
+ id: payout.id,
153
+ })), [
154
+ { key: 'requested', header: 'REQUESTED' },
155
+ { key: 'amount', header: 'AMOUNT' },
156
+ { key: 'status', header: 'STATUS' },
157
+ { key: 'settled', header: 'SETTLED' },
158
+ { key: 'id', header: 'ID', verbatim: true },
159
+ ], log);
160
+ if (result.hasNextPage && result.nextCursor) {
161
+ log('');
162
+ log(`More: skrr earnings payouts --cursor ${result.nextCursor}`);
163
+ }
164
+ }
@@ -0,0 +1,13 @@
1
+ /**
2
+ * GitHub Actions OIDC token acquisition for trusted publishing (OSK-12311).
3
+ *
4
+ * A workflow opts in with `permissions: id-token: write`; GitHub then exposes
5
+ * `ACTIONS_ID_TOKEN_REQUEST_URL` / `ACTIONS_ID_TOKEN_REQUEST_TOKEN` to the
6
+ * job, and this job-level URL is the only place a token can be requested —
7
+ * the response is what `POST /api/agents/:id/ci-releases` verifies.
8
+ *
9
+ * `audience` is what the token asserts it is FOR: the API checks it against
10
+ * `GITHUB_ACTIONS_OIDC_AUDIENCE` (else `DOMAIN_SERVER`, else `skrr`). Leave it
11
+ * unset to take the job's default, or pass the deployment's canonical origin.
12
+ */
13
+ export declare function fetchGitHubActionsOidcToken(audience?: string): Promise<string>;
@@ -0,0 +1,41 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.fetchGitHubActionsOidcToken = fetchGitHubActionsOidcToken;
4
+ /**
5
+ * GitHub Actions OIDC token acquisition for trusted publishing (OSK-12311).
6
+ *
7
+ * A workflow opts in with `permissions: id-token: write`; GitHub then exposes
8
+ * `ACTIONS_ID_TOKEN_REQUEST_URL` / `ACTIONS_ID_TOKEN_REQUEST_TOKEN` to the
9
+ * job, and this job-level URL is the only place a token can be requested —
10
+ * the response is what `POST /api/agents/:id/ci-releases` verifies.
11
+ *
12
+ * `audience` is what the token asserts it is FOR: the API checks it against
13
+ * `GITHUB_ACTIONS_OIDC_AUDIENCE` (else `DOMAIN_SERVER`, else `skrr`). Leave it
14
+ * unset to take the job's default, or pass the deployment's canonical origin.
15
+ */
16
+ async function fetchGitHubActionsOidcToken(audience) {
17
+ const requestUrl = process.env.ACTIONS_ID_TOKEN_REQUEST_URL;
18
+ const requestToken = process.env.ACTIONS_ID_TOKEN_REQUEST_TOKEN;
19
+ if (!requestUrl || !requestToken) {
20
+ throw new Error('No GitHub OIDC request context: run inside GitHub Actions with ' +
21
+ '`permissions: id-token: write`, or pass --oidc-token explicitly');
22
+ }
23
+ const url = new URL(requestUrl);
24
+ if (audience) {
25
+ url.searchParams.set('audience', audience);
26
+ }
27
+ const res = await fetch(url, {
28
+ headers: {
29
+ authorization: `bearer ${requestToken}`,
30
+ accept: 'application/json',
31
+ },
32
+ });
33
+ if (!res.ok) {
34
+ throw new Error(`GitHub OIDC token request failed (${res.status})`);
35
+ }
36
+ const body = (await res.json());
37
+ if (typeof body?.value !== 'string' || body.value.length === 0) {
38
+ throw new Error('GitHub OIDC token request returned no token');
39
+ }
40
+ return body.value;
41
+ }
@@ -90,15 +90,56 @@ export declare function updateOwnLicensePolicy(licenseId: string, body: BundleLi
90
90
  export declare function updateWorkspaceLicensePolicy(workspaceId: string, licenseId: string, body: BundleLicensePolicyInput): Promise<{
91
91
  license: unknown;
92
92
  }>;
93
- /** `PUT /workspaces/:workspaceId/policy` — which releases a workspace may run. */
93
+ /**
94
+ * The modes the server's workspace Store policy evaluator honours
95
+ * (`api/server/services/commerce/WorkspaceStorePolicy.js`). `open` is also
96
+ * what a workspace with no policy means.
97
+ */
98
+ export type WorkspaceStorePolicyMode = 'open' | 'deny_all' | 'allowlist';
99
+ /**
100
+ * The levels a workspace caps a release at (OSK-12262); each name is a mode
101
+ * the release's own capability manifest reports.
102
+ */
103
+ export interface StoreCapabilityCeiling {
104
+ builtinTools?: 'none' | 'allowlist' | 'platform_default';
105
+ platformCapabilities?: 'not_loaded' | 'listed' | 'unrestricted';
106
+ delegation?: 'none' | 'specific' | 'all';
107
+ proactive?: boolean;
108
+ firstContact?: boolean;
109
+ sharedData?: 'none' | 'bootstrap' | 'memory' | 'full';
110
+ /** Allowed `tool:|connector:|data:|network:|secret:` keys; `*` allows all. */
111
+ permissions?: string[];
112
+ }
113
+ /** `GET /workspaces/:workspaceId/policy` — members read the policy that governs them. */
114
+ export declare function getWorkspaceStorePolicy(workspaceId: string): Promise<{
115
+ policy: unknown;
116
+ }>;
117
+ /** `PUT /workspaces/:workspaceId/policy` — which releases a workspace may install and run. */
94
118
  export declare function setWorkspaceStorePolicy(workspaceId: string, body: {
95
- mode: 'deny_all' | 'allowlist';
119
+ mode: WorkspaceStorePolicyMode;
96
120
  allowedReleaseIds: string[];
121
+ capabilityCeiling?: StoreCapabilityCeiling | null;
97
122
  policyId?: string;
98
123
  expectedRevision?: number;
99
124
  }): Promise<{
100
125
  policy: unknown;
101
126
  }>;
127
+ /** `POST /workspaces/:workspaceId/store-requests` — a member asks for a refused release. */
128
+ export declare function submitStoreInstallRequest(workspaceId: string, body: {
129
+ releaseId: string;
130
+ note?: string;
131
+ requestId?: string;
132
+ }): Promise<{
133
+ request: unknown;
134
+ }>;
135
+ /** `GET /workspaces/:workspaceId/store-requests` — the queue (owner) or your own asks (member). */
136
+ export declare function listStoreInstallRequests(workspaceId: string, status?: string): Promise<{
137
+ requests: unknown[];
138
+ }>;
139
+ /** `POST …/store-requests/:requestId/approve|decline` — the owner's answer. */
140
+ export declare function decideStoreInstallRequest(workspaceId: string, requestId: string, decision: 'approve' | 'decline'): Promise<{
141
+ request: unknown;
142
+ }>;
102
143
  /** `POST /workspaces/:workspaceId/assignments` — give a seat to a member or Space. */
103
144
  export declare function assignWorkspaceStoreLicense(workspaceId: string, body: {
104
145
  licenseId: string;
@@ -6,7 +6,11 @@ exports.publishGovernedStoreRelease = publishGovernedStoreRelease;
6
6
  exports.createGovernedStoreLicense = createGovernedStoreLicense;
7
7
  exports.updateOwnLicensePolicy = updateOwnLicensePolicy;
8
8
  exports.updateWorkspaceLicensePolicy = updateWorkspaceLicensePolicy;
9
+ exports.getWorkspaceStorePolicy = getWorkspaceStorePolicy;
9
10
  exports.setWorkspaceStorePolicy = setWorkspaceStorePolicy;
11
+ exports.submitStoreInstallRequest = submitStoreInstallRequest;
12
+ exports.listStoreInstallRequests = listStoreInstallRequests;
13
+ exports.decideStoreInstallRequest = decideStoreInstallRequest;
10
14
  exports.assignWorkspaceStoreLicense = assignWorkspaceStoreLicense;
11
15
  const api_fetch_1 = require("./api-fetch");
12
16
  const triggers_1 = require("./triggers");
@@ -69,10 +73,30 @@ async function updateOwnLicensePolicy(licenseId, body) {
69
73
  async function updateWorkspaceLicensePolicy(workspaceId, licenseId, body) {
70
74
  return (0, api_fetch_1.apiFetch)(`/api/store/governance/workspaces/${encodeURIComponent(workspaceId)}/licenses/${encodeURIComponent(licenseId)}/update-policy`, { method: 'PATCH', body });
71
75
  }
72
- /** `PUT /workspaces/:workspaceId/policy` — which releases a workspace may run. */
76
+ /** `GET /workspaces/:workspaceId/policy` — members read the policy that governs them. */
77
+ async function getWorkspaceStorePolicy(workspaceId) {
78
+ return (0, api_fetch_1.apiFetch)(`/api/store/governance/workspaces/${encodeURIComponent(workspaceId)}/policy`, { method: 'GET' });
79
+ }
80
+ /** `PUT /workspaces/:workspaceId/policy` — which releases a workspace may install and run. */
73
81
  async function setWorkspaceStorePolicy(workspaceId, body) {
74
82
  return (0, api_fetch_1.apiFetch)(`/api/store/governance/workspaces/${encodeURIComponent(workspaceId)}/policy`, { method: 'PUT', body });
75
83
  }
84
+ /** `POST /workspaces/:workspaceId/store-requests` — a member asks for a refused release. */
85
+ async function submitStoreInstallRequest(workspaceId, body) {
86
+ return (0, api_fetch_1.apiFetch)(`/api/store/governance/workspaces/${encodeURIComponent(workspaceId)}/store-requests`, { method: 'POST', body });
87
+ }
88
+ /** `GET /workspaces/:workspaceId/store-requests` — the queue (owner) or your own asks (member). */
89
+ async function listStoreInstallRequests(workspaceId, status) {
90
+ return (0, api_fetch_1.apiFetch)((0, triggers_1.withQuery)(`/api/store/governance/workspaces/${encodeURIComponent(workspaceId)}/store-requests`, status ? { status } : {}), { method: 'GET' });
91
+ }
92
+ /** `POST …/store-requests/:requestId/approve|decline` — the owner's answer. */
93
+ async function decideStoreInstallRequest(workspaceId, requestId, decision) {
94
+ // Two literal paths — the parity checker reads route coverage from literals.
95
+ const path = decision === 'approve'
96
+ ? `/api/store/governance/workspaces/${encodeURIComponent(workspaceId)}/store-requests/${encodeURIComponent(requestId)}/approve`
97
+ : `/api/store/governance/workspaces/${encodeURIComponent(workspaceId)}/store-requests/${encodeURIComponent(requestId)}/decline`;
98
+ return (0, api_fetch_1.apiFetch)(path, { method: 'POST', body: {} });
99
+ }
76
100
  /** `POST /workspaces/:workspaceId/assignments` — give a seat to a member or Space. */
77
101
  async function assignWorkspaceStoreLicense(workspaceId, body) {
78
102
  return (0, api_fetch_1.apiFetch)(`/api/store/governance/workspaces/${encodeURIComponent(workspaceId)}/assignments`, { method: 'POST', body });
@@ -48,6 +48,17 @@ const UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/
48
48
  function looksLikeLabelId(ref) {
49
49
  return UUID_RE.test(ref.trim());
50
50
  }
51
+ /**
52
+ * A label id that lost characters in a copy — hex and dashes, but not the
53
+ * uuid shape. It can NEVER be a label name (names are human words), so it must
54
+ * not fall into the name path, where the refusal would tell the caller to
55
+ * create a label literally named `ed3f89d3-875b-…`. The honest message is
56
+ * "this looks like a truncated id".
57
+ */
58
+ const ID_SHAPED_RE = /^[0-9a-f-]{20,}$/i;
59
+ function looksLikeTruncatedLabelId(ref) {
60
+ return !looksLikeLabelId(ref) && ref.includes('-') && ID_SHAPED_RE.test(ref.trim());
61
+ }
51
62
  /** Levenshtein, iterative, two rows. Only ever runs on a refusal path. */
52
63
  function distance(a, b) {
53
64
  if (a === b)
@@ -148,6 +159,11 @@ async function resolveLabelRefs(refs, context) {
148
159
  resolved.push(ref);
149
160
  continue;
150
161
  }
162
+ if (looksLikeTruncatedLabelId(ref)) {
163
+ throw new LabelRefError(`"${ref}" looks like a label id but is not a complete one — ` +
164
+ `an id was probably truncated when copied. ` +
165
+ `Get the full id with \`labels list --json\`.`);
166
+ }
151
167
  const needle = ref.toLowerCase();
152
168
  const matches = vocabulary.filter((row) => (row.name ?? '').toLowerCase() === needle);
153
169
  if (matches.length === 1) {
@@ -0,0 +1,10 @@
1
+ export interface ManagedExecutionAgent {
2
+ id: string;
3
+ name: string;
4
+ position: number;
5
+ }
6
+ /**
7
+ * Agent Worker has no Machine row. The durable, user-visible relationship is
8
+ * an Agent's ordered execution policy, which this projection exposes.
9
+ */
10
+ export declare function managedExecutionAgents(response: unknown): ManagedExecutionAgent[];
@@ -0,0 +1,43 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.managedExecutionAgents = managedExecutionAgents;
4
+ function agentWorkerPosition(agent) {
5
+ const policy = agent.executionPolicy;
6
+ if (Array.isArray(policy?.targets)) {
7
+ const index = policy.targets.findIndex((target) => Boolean(target) &&
8
+ typeof target === 'object' &&
9
+ target.kind === 'agent-worker' &&
10
+ target.enabled !== false);
11
+ return index >= 0 ? index + 1 : null;
12
+ }
13
+ const executionOrder = agent.executionOrder;
14
+ if (!Array.isArray(executionOrder))
15
+ return null;
16
+ const index = executionOrder.findIndex((target) => Boolean(target) &&
17
+ typeof target === 'object' &&
18
+ target.kind === 'agent-worker');
19
+ return index >= 0 ? index + 1 : null;
20
+ }
21
+ /**
22
+ * Agent Worker has no Machine row. The durable, user-visible relationship is
23
+ * an Agent's ordered execution policy, which this projection exposes.
24
+ */
25
+ function managedExecutionAgents(response) {
26
+ const envelope = response;
27
+ const agents = Array.isArray(response)
28
+ ? response
29
+ : Array.isArray(envelope?.data)
30
+ ? envelope.data
31
+ : Array.isArray(envelope?.agents)
32
+ ? envelope.agents
33
+ : [];
34
+ return agents
35
+ .filter((agent) => Boolean(agent) && typeof agent === 'object')
36
+ .map((agent) => ({ agent, position: agentWorkerPosition(agent) }))
37
+ .filter((entry) => entry.position !== null)
38
+ .map(({ agent, position }) => {
39
+ const id = String(agent.id ?? agent._id ?? '');
40
+ return { id, name: String(agent.name ?? (id || 'Unnamed agent')), position };
41
+ })
42
+ .sort((a, b) => a.position - b.position || a.name.localeCompare(b.name));
43
+ }
@@ -0,0 +1,20 @@
1
+ /**
2
+ * principal-display.ts — render a principal as a name a person recognises.
3
+ *
4
+ * WHY
5
+ * ---
6
+ * `tasks show`, `comments list` and friends print author/assignee ids verbatim
7
+ * (`Author: 68ed5a0482dd30a0a610a916`). An id is correct on the wire and
8
+ * useless at a keyboard — the one thing the column is for is "who is this".
9
+ *
10
+ * Resolution is best-effort and bounded to two cheap sources: the caller's own
11
+ * record (`/api/user`) and the Space member roster (`GET
12
+ * /api/spaces/:id/members`) when the task has a Space. An unresolvable id
13
+ * prints unchanged — a roster read failure must never fail the command, so
14
+ * every fetch is caught.
15
+ */
16
+ export declare function resolvePrincipalNames(ids: ReadonlyArray<unknown>, options?: {
17
+ spaceId?: string | null;
18
+ }): Promise<Map<string, string>>;
19
+ /** The name when known, else the id unchanged — never blank. */
20
+ export declare function displayPrincipal(id: unknown, names: Map<string, string> | undefined): string;
@@ -0,0 +1,64 @@
1
+ "use strict";
2
+ /**
3
+ * principal-display.ts — render a principal as a name a person recognises.
4
+ *
5
+ * WHY
6
+ * ---
7
+ * `tasks show`, `comments list` and friends print author/assignee ids verbatim
8
+ * (`Author: 68ed5a0482dd30a0a610a916`). An id is correct on the wire and
9
+ * useless at a keyboard — the one thing the column is for is "who is this".
10
+ *
11
+ * Resolution is best-effort and bounded to two cheap sources: the caller's own
12
+ * record (`/api/user`) and the Space member roster (`GET
13
+ * /api/spaces/:id/members`) when the task has a Space. An unresolvable id
14
+ * prints unchanged — a roster read failure must never fail the command, so
15
+ * every fetch is caught.
16
+ */
17
+ Object.defineProperty(exports, "__esModule", { value: true });
18
+ exports.resolvePrincipalNames = resolvePrincipalNames;
19
+ exports.displayPrincipal = displayPrincipal;
20
+ const data_provider_1 = require("@skrr-ai/data-provider");
21
+ async function resolvePrincipalNames(ids, options = {}) {
22
+ const wanted = new Set(ids.filter((id) => typeof id === 'string' && id.length > 0));
23
+ const names = new Map();
24
+ if (wanted.size === 0)
25
+ return names;
26
+ const add = (id, display) => {
27
+ const key = typeof id === 'string' ? id : id != null ? String(id) : undefined;
28
+ const name = typeof display === 'string' && display.trim() ? display.trim() : undefined;
29
+ if (key && name && wanted.has(key) && !names.has(key))
30
+ names.set(key, name);
31
+ };
32
+ const reads = [
33
+ data_provider_1.dataService
34
+ .getUser()
35
+ .then((me) => {
36
+ const display = me?.name || me?.username || me?.email;
37
+ add(me?.id ?? me?._id, display);
38
+ })
39
+ .catch(() => undefined),
40
+ ];
41
+ if (options.spaceId) {
42
+ reads.push(data_provider_1.dataService
43
+ .getSpaceMembers(options.spaceId)
44
+ .then((members) => {
45
+ for (const member of members?.users ?? []) {
46
+ const display = member.user?.name || member.user?.username || member.user?.email;
47
+ add(member.userId, display);
48
+ add(member.user?._id, display);
49
+ }
50
+ for (const agent of members?.agents ?? []) {
51
+ add(agent.id, agent.name);
52
+ add(agent._id, agent.name);
53
+ }
54
+ })
55
+ .catch(() => undefined));
56
+ }
57
+ await Promise.all(reads);
58
+ return names;
59
+ }
60
+ /** The name when known, else the id unchanged — never blank. */
61
+ function displayPrincipal(id, names) {
62
+ const key = id == null ? '-' : String(id);
63
+ return names?.get(key) ?? key;
64
+ }
@@ -0,0 +1,14 @@
1
+ import type { SpaceTemplateSource, SpaceTemplateSourceResponse } from '@skrr-ai/data-provider';
2
+ /**
3
+ * The `Template:` / `Update:` lines `skrr spaces show` prints for a Space a
4
+ * template install created. The same states the web notice draws, and for the
5
+ * same reason each is spelled out: "up to date" is printed only when the check
6
+ * answered `current`, and a failed check says it failed rather than printing
7
+ * nothing — silence would read as "no update".
8
+ */
9
+ export declare function templateSourceLines({ source, check, checkError, baseURL, }: {
10
+ source: SpaceTemplateSource;
11
+ check?: SpaceTemplateSourceResponse | null;
12
+ checkError?: string;
13
+ baseURL: string;
14
+ }): string[];
@@ -0,0 +1,41 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.templateSourceLines = templateSourceLines;
4
+ const data_provider_1 = require("@skrr-ai/data-provider");
5
+ const web_url_1 = require("./web-url");
6
+ /**
7
+ * The `Template:` / `Update:` lines `skrr spaces show` prints for a Space a
8
+ * template install created. The same states the web notice draws, and for the
9
+ * same reason each is spelled out: "up to date" is printed only when the check
10
+ * answered `current`, and a failed check says it failed rather than printing
11
+ * nothing — silence would read as "no update".
12
+ */
13
+ function templateSourceLines({ source, check, checkError, baseURL, }) {
14
+ const title = source.templateTitle?.trim() || source.templateId;
15
+ const installed = (0, data_provider_1.spaceTemplateVersionLabel)(source);
16
+ const installedOn = typeof source.installedAt === 'string' ? source.installedAt.slice(0, 10) : undefined;
17
+ const lines = [
18
+ `Template: ${title}${installed ? ` · ${installed}` : ''}${installedOn ? ` (installed ${installedOn})` : ''}`,
19
+ ];
20
+ if (checkError) {
21
+ lines.push(`Update: check failed (${checkError})`);
22
+ return lines;
23
+ }
24
+ const link = (0, web_url_1.webUrl)(baseURL, { kind: 'spaceTemplate', templateId: source.templateId });
25
+ switch (check?.status) {
26
+ case 'update_available': {
27
+ const latest = (0, data_provider_1.spaceTemplateVersionLabel)(check.latest);
28
+ lines.push(`Update: ${latest ? `${latest} available` : 'the template changed since install'}${link ? ` — ${link}` : ''}`);
29
+ break;
30
+ }
31
+ case 'current':
32
+ lines.push('Update: up to date');
33
+ break;
34
+ case 'unavailable':
35
+ lines.push('Update: template no longer available');
36
+ break;
37
+ default:
38
+ lines.push('Update: not checked');
39
+ }
40
+ return lines;
41
+ }
@@ -0,0 +1,21 @@
1
+ /**
2
+ * What the CLI says about step-up authentication before Store publishing
3
+ * (OSK-12275).
4
+ *
5
+ * A public release reaches everyone who installs it, so the server refuses to
6
+ * publish one, or to move the release buyers are served, on the strength of a
7
+ * CLI token alone: it answers `STEP_UP_REQUIRED` until this same login has
8
+ * proved a second factor through `skrr step-up`. The vocabulary (the code, the
9
+ * reasons, the window) is `@skrr-ai/data-provider`'s; only the sentences live
10
+ * here, because each reason has a different next step and a refusal that says
11
+ * "forbidden" would leave a publisher guessing which one applies.
12
+ */
13
+ import type { TStepUpChallenge } from '@skrr-ai/data-provider';
14
+ /**
15
+ * The explanation printed when a command is refused with `STEP_UP_REQUIRED`.
16
+ * `challenge` may be `null` for a body this CLI could not read, which still
17
+ * gets the ordinary remedy rather than a bare status line.
18
+ */
19
+ export declare function describeStepUpRequired(challenge: TStepUpChallenge | null, bin: string): string;
20
+ /** The clock time a verification lasts until, in the reader's local time. */
21
+ export declare function formatStepUpExpiry(expiresAt: string | undefined): string;
@@ -0,0 +1,44 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.describeStepUpRequired = describeStepUpRequired;
4
+ exports.formatStepUpExpiry = formatStepUpExpiry;
5
+ const NOTHING_CHANGED = 'Nothing was published or changed.';
6
+ function windowPhrase(windowSeconds) {
7
+ const minutes = Math.max(1, Math.round((windowSeconds ?? 600) / 60));
8
+ return `${minutes} minute${minutes === 1 ? '' : 's'}`;
9
+ }
10
+ /**
11
+ * The explanation printed when a command is refused with `STEP_UP_REQUIRED`.
12
+ * `challenge` may be `null` for a body this CLI could not read, which still
13
+ * gets the ordinary remedy rather than a bare status line.
14
+ */
15
+ function describeStepUpRequired(challenge, bin) {
16
+ const window = windowPhrase(challenge?.windowSeconds);
17
+ switch (challenge?.reason) {
18
+ case 'two_factor_not_enabled':
19
+ return [
20
+ `Publishing to the Store needs two-factor authentication, and this account has none. ${NOTHING_CHANGED}`,
21
+ 'Turn it on in the web app (Settings → Account → Two-factor authentication),',
22
+ `then run \`${bin} step-up\` and run this command again within ${window}.`,
23
+ ].join('\n');
24
+ case 'credential_not_session_bound':
25
+ return [
26
+ `This credential is not tied to a sign-in session, so it cannot be verified for publishing. ${NOTHING_CHANGED}`,
27
+ `Run \`${bin} login\`, then \`${bin} step-up\`, and run this command again within ${window}.`,
28
+ ].join('\n');
29
+ default:
30
+ return [
31
+ `Publishing needs a fresh identity check: a public release reaches everyone who installs it, so this login alone is not enough. ${NOTHING_CHANGED}`,
32
+ `Run \`${bin} step-up\` and enter the code from your authenticator app, then run this command again within ${window}.`,
33
+ ].join('\n');
34
+ }
35
+ }
36
+ /** The clock time a verification lasts until, in the reader's local time. */
37
+ function formatStepUpExpiry(expiresAt) {
38
+ if (!expiresAt)
39
+ return 'the end of the verification window';
40
+ const date = new Date(expiresAt);
41
+ if (Number.isNaN(date.getTime()))
42
+ return 'the end of the verification window';
43
+ return date.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' });
44
+ }
@@ -0,0 +1,11 @@
1
+ import type { StoreAcquisitionRequest } from '@skrr-ai/data-provider';
2
+ /**
3
+ * A purchase an agent asked to make, as the lines a terminal shows (OSK-12240).
4
+ *
5
+ * The same server copy the web approval card renders: every field comes from
6
+ * `GET /api/store/acquisition-requests/:id`, which the fulfillment path built
7
+ * from the listing it resolved. Nothing the requesting agent wrote reaches
8
+ * these lines. The words themselves come from `@skrr-ai/data-provider`, so the
9
+ * terminal and the card cannot describe one request two ways.
10
+ */
11
+ export declare function describeAcquisitionRequestLines(request: StoreAcquisitionRequest): string[];