orizu 0.5.51 → 0.5.52

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 (50) hide show
  1. package/dist/app-commands.d.ts.map +1 -1
  2. package/dist/app-commands.js +4 -12
  3. package/dist/auth-commands.d.ts.map +1 -1
  4. package/dist/auth-commands.js +3 -106
  5. package/dist/cli-write-commands.d.ts +143 -0
  6. package/dist/cli-write-commands.d.ts.map +1 -0
  7. package/dist/cli-write-commands.js +123 -0
  8. package/dist/index.d.ts.map +1 -1
  9. package/dist/index.js +44 -50
  10. package/dist/last-error-record.d.ts +7 -0
  11. package/dist/last-error-record.d.ts.map +1 -1
  12. package/dist/last-error-record.js +14 -2
  13. package/dist/login-flow.d.ts +37 -0
  14. package/dist/login-flow.d.ts.map +1 -0
  15. package/dist/login-flow.js +295 -0
  16. package/dist/logout-diagnostic.d.ts.map +1 -1
  17. package/dist/logout-diagnostic.js +2 -1
  18. package/dist/manifests-cli.d.ts.map +1 -1
  19. package/dist/manifests-cli.js +36 -22
  20. package/dist/one-request-write.d.ts +59 -0
  21. package/dist/one-request-write.d.ts.map +1 -0
  22. package/dist/one-request-write.js +157 -0
  23. package/dist/provider-write-workflow.d.ts +12 -0
  24. package/dist/provider-write-workflow.d.ts.map +1 -0
  25. package/dist/provider-write-workflow.js +110 -0
  26. package/dist/providers-cli.d.ts.map +1 -1
  27. package/dist/providers-cli.js +27 -23
  28. package/dist/scores-accept-cli.d.ts +1 -1
  29. package/dist/scores-accept-cli.d.ts.map +1 -1
  30. package/dist/scores-accept-cli.js +4 -28
  31. package/dist/task-commands.d.ts.map +1 -1
  32. package/dist/task-commands.js +26 -62
  33. package/package.json +1 -1
  34. package/src/app-commands.ts +3 -18
  35. package/src/auth-commands.ts +6 -125
  36. package/src/cli-write-commands.ts +143 -0
  37. package/src/index.ts +23 -57
  38. package/src/last-error-record.ts +16 -2
  39. package/src/login-flow.ts +368 -0
  40. package/src/logout-diagnostic.ts +2 -1
  41. package/src/manifests-cli.ts +36 -23
  42. package/src/one-request-write.ts +192 -0
  43. package/src/provider-write-workflow.ts +117 -0
  44. package/src/providers-cli.ts +24 -17
  45. package/src/scores-accept-cli.ts +4 -46
  46. package/src/task-commands.ts +22 -115
  47. package/dist/headless-login.d.ts +0 -19
  48. package/dist/headless-login.d.ts.map +0 -1
  49. package/dist/headless-login.js +0 -108
  50. package/src/headless-login.ts +0 -192
@@ -1 +1 @@
1
- {"version":3,"file":"app-commands.d.ts","sourceRoot":"","sources":["../src/app-commands.ts"],"names":[],"mappings":"AAuCA,iBAAe,QAAQ,kBActB;AAED,iBAAS,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAU/C;AAED,iBAAS,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAUhD;AAED,iBAAS,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAE9D;AAeD,iBAAS,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAElE;AAED,iBAAS,gBAAgB,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAG1F;AAED,iBAAS,gBAAgB,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAUjE;AAED,iBAAS,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,CAEjD;AAED,iBAAS,qBAAqB,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,SAAS,EAAE,MAAM,GAAG;IACpF,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,EAAE,MAAM,CAAA;IAChB,IAAI,EAAE,MAAM,CAAA;CACb,CAeA;AAED,iBAAS,kBAAkB,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,SAAS,EAAE,MAAM;;;;;IAoB/E;AAED,iBAAS,wBAAwB,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,QAGjE;AAED,iBAAS,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAEjE;AAyED,iBAAe,iBAAiB,kBAmG/B;AAED,iBAAe,kBAAkB,kBAiDhC;AAED,iBAAe,iBAAiB,kBAwF/B;AAED,iBAAe,cAAc,kBAgD5B;AA+CD,iBAAe,SAAS,kBA2CvB;AAED,yFAAyF;AACzF,wBAAgB,oBAAoB,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EAAE,eAAe,EAAE,MAAM,GAAG,MAAM,CAK3G;AAED,iBAAe,eAAe,kBAmD7B;AAED,OAAO,EACL,cAAc,EACd,YAAY,EACZ,gBAAgB,EAChB,qBAAqB,EACrB,kBAAkB,EAClB,gBAAgB,EAChB,QAAQ,EACR,gBAAgB,EAChB,wBAAwB,EACxB,SAAS,EACT,eAAe,EACf,QAAQ,EACR,iBAAiB,EACjB,kBAAkB,EAClB,iBAAiB,EACjB,cAAc,EACd,SAAS,EACT,eAAe,GAChB,CAAA"}
1
+ {"version":3,"file":"app-commands.d.ts","sourceRoot":"","sources":["../src/app-commands.ts"],"names":[],"mappings":"AAuCA,iBAAe,QAAQ,kBActB;AAED,iBAAS,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAU/C;AAED,iBAAS,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAUhD;AAED,iBAAS,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAE9D;AAeD,iBAAS,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAElE;AAED,iBAAS,gBAAgB,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAG1F;AAED,iBAAS,gBAAgB,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAUjE;AAED,iBAAS,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,CAEjD;AAED,iBAAS,qBAAqB,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,SAAS,EAAE,MAAM,GAAG;IACpF,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,EAAE,MAAM,CAAA;IAChB,IAAI,EAAE,MAAM,CAAA;CACb,CAeA;AAED,iBAAS,kBAAkB,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,SAAS,EAAE,MAAM;;;;;IAoB/E;AAED,iBAAS,wBAAwB,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,QAGjE;AAED,iBAAS,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAEjE;AAyED,iBAAe,iBAAiB,kBAmG/B;AAED,iBAAe,kBAAkB,kBAiDhC;AAED,iBAAe,iBAAiB,kBAwF/B;AAED,iBAAe,cAAc,kBAiC5B;AA+CD,iBAAe,SAAS,kBA2CvB;AAED,yFAAyF;AACzF,wBAAgB,oBAAoB,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EAAE,eAAe,EAAE,MAAM,GAAG,MAAM,CAK3G;AAED,iBAAe,eAAe,kBAmD7B;AAED,OAAO,EACL,cAAc,EACd,YAAY,EACZ,gBAAgB,EAChB,qBAAqB,EACrB,kBAAkB,EAClB,gBAAgB,EAChB,QAAQ,EACR,gBAAgB,EAChB,wBAAwB,EACxB,SAAS,EACT,eAAe,EACf,QAAQ,EACR,iBAAiB,EACjB,kBAAkB,EAClB,iBAAiB,EACjB,cAAc,EACd,SAAS,EACT,eAAe,GAChB,CAAA"}
@@ -433,18 +433,10 @@ async function linkAppDataset() {
433
433
  const selected = await selectAppIdInteractively(project);
434
434
  appId = selected.appId;
435
435
  }
436
- const response = await authedFetch(`/api/cli/apps/${encodeURIComponent(appId)}/link-dataset`, {
437
- method: 'POST',
438
- headers: { 'Content-Type': 'application/json' },
439
- body: JSON.stringify({
440
- datasetId,
441
- versionNum,
442
- }),
443
- });
444
- if (!response.ok) {
445
- throw new Error(`Failed to link dataset: ${await response.text()}`);
446
- }
447
- const data = await parseJsonResponse(response, 'App link dataset');
436
+ const writes = await import('./cli-write-commands.js');
437
+ const data = await writes.sendCommandWrite(writes.appLinkDataset(appId, { datasetId, ...(versionNum === undefined ? {} : { versionNum }) }), { json: hasJsonFlag(), print: printLine });
438
+ if (!data)
439
+ return;
448
440
  if (hasJsonFlag()) {
449
441
  printJson({ app: data.app, linkedDataset: data.linkedDataset, versionNum: data.versionNum });
450
442
  return;
@@ -1 +1 @@
1
- {"version":3,"file":"auth-commands.d.ts","sourceRoot":"","sources":["../src/auth-commands.ts"],"names":[],"mappings":"AA6BA,iBAAS,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,MAAM,CAAC,cAAc,CAEnE;AAMD,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAE5D;AAQD,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,EAAE,cAAc,CAAC,EAAE,MAAM,GAAG,GAAG,CAwB5E;AA6BD,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAgBtD;AAED,iBAAS,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEzC;AA4BD,iBAAe,KAAK,CAAC,eAAe,CAAC,EAAE,MAAM,iBAoC5C;AAoHD,iBAAe,MAAM,kBAWpB;AAED,iBAAe,MAAM,CAAC,eAAe,CAAC,EAAE,MAAM,iBAwC7C;AAED,iBAAe,QAAQ,kBA0BtB;AAED,OAAO,EAAE,WAAW,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAA"}
1
+ {"version":3,"file":"auth-commands.d.ts","sourceRoot":"","sources":["../src/auth-commands.ts"],"names":[],"mappings":"AAyBA,iBAAS,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,MAAM,CAAC,cAAc,CAEnE;AAMD,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAE5D;AAQD,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,EAAE,cAAc,CAAC,EAAE,MAAM,GAAG,GAAG,CAwB5E;AAED,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAgBtD;AAED,iBAAS,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEzC;AA4BD,iBAAe,KAAK,CAAC,eAAe,CAAC,EAAE,MAAM,iBAoC5C;AA4BD,iBAAe,MAAM,kBAWpB;AAED,iBAAe,MAAM,CAAC,eAAe,CAAC,EAAE,MAAM,iBAwC7C;AAED,iBAAe,QAAQ,kBA0BtB;AAED,OAAO,EAAE,WAAW,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAA"}
@@ -1,14 +1,10 @@
1
1
  // ORI-2044: moved from index.ts to keep auth commands together.
2
2
  import { randomBytes, createHash } from 'crypto';
3
- import { spawn } from 'child_process';
4
- import { createServer } from 'http';
5
3
  import { sanitizeTerminalText, parseJsonResponse } from './json-response.js';
6
4
  import { isInteractiveTerminal, hasArg, hasJsonFlag, getArg } from './command-line-arguments.js';
7
5
  import { getBaseUrl, resolveLoginTarget, resolveLogoutTarget, assertSecureTokenTransport, authedFetch, } from './http.js';
8
6
  import { clearUnreadableServerCredentials, hasResolvableAuth, rememberProcessSecret, saveServerCredentials, getServerCredentials, resolveAuthTokenForBaseUrl, } from './credentials.js';
9
7
  import { printJson, printLine, printLoginProgress } from './cli-console-output.js';
10
- import { shouldUseHeadlessLogin, waitForHeadlessAuthorization } from './headless-login.js';
11
- import { renderCliAuthBrowserPage } from './cli-auth-browser-page.js';
12
8
  import { resolveProjectSelection } from './account-directory.js';
13
9
  function isNodeError(error) {
14
10
  return error instanceof Error;
@@ -46,30 +42,6 @@ export function validateBrowserUrl(url, expectedOrigin) {
46
42
  }
47
43
  return parsed;
48
44
  }
49
- function openInBrowser(url) {
50
- const parsed = validateBrowserUrl(url);
51
- const platform = process.platform;
52
- const href = parsed.href;
53
- if (platform === 'darwin') {
54
- spawn('open', [href], {
55
- detached: true,
56
- stdio: 'ignore',
57
- }).unref();
58
- return;
59
- }
60
- if (platform === 'win32') {
61
- spawn('rundll32.exe', ['url.dll,FileProtocolHandler', href], {
62
- detached: true,
63
- stdio: 'ignore',
64
- windowsHide: true,
65
- }).unref();
66
- return;
67
- }
68
- spawn('xdg-open', [href], {
69
- detached: true,
70
- stdio: 'ignore',
71
- }).unref();
72
- }
73
45
  export function formatTerminalLink(url) {
74
46
  const safeUrl = sanitizeTerminalText(url);
75
47
  try {
@@ -154,85 +126,10 @@ async function authenticateAtBaseUrl(baseUrl) {
154
126
  }
155
127
  const codeVerifier = rememberProcessSecret(createCodeVerifier());
156
128
  const codeChallenge = createCodeChallenge(codeVerifier);
129
+ // Effect loads here, after the already-logged-in check (ORI-2422).
130
+ const { completeLogin, shouldUseHeadlessLogin } = await import('./login-flow.js');
157
131
  const isHeadlessLogin = shouldUseHeadlessLogin({ isForced: hasArg('--headless') });
158
- const callbackPort = isHeadlessLogin ? undefined : resolveAuthCallbackPort();
159
- const redirectUri = callbackPort === undefined ? undefined : `http://127.0.0.1:${callbackPort}/callback`;
160
- const callbackCode = isHeadlessLogin
161
- ? await waitForHeadlessAuthorization({ baseUrl, codeChallenge }, {
162
- parseJsonResponse,
163
- printProgress: printLoginProgress,
164
- sanitizeTerminalText,
165
- validateBrowserUrl,
166
- })
167
- : await new Promise((resolve, reject) => {
168
- const server = createServer((request, response) => {
169
- try {
170
- const url = new URL(request.url || '/', `http://127.0.0.1:${callbackPort}`);
171
- const code = url.searchParams.get('code');
172
- if (!code) {
173
- response.statusCode = 400;
174
- response.setHeader('content-type', 'text/html; charset=utf-8');
175
- response.end(renderCliAuthBrowserPage('error'));
176
- return;
177
- }
178
- response.statusCode = 200;
179
- response.setHeader('content-type', 'text/html; charset=utf-8');
180
- response.end(renderCliAuthBrowserPage('success'));
181
- server.close();
182
- resolve(code);
183
- }
184
- catch (error) {
185
- server.close();
186
- reject(error);
187
- }
188
- });
189
- server.on('error', (error) => {
190
- if (error.code === 'EADDRINUSE') {
191
- reject(new Error(`Port ${callbackPort} is already in use. Set ORIZU_AUTH_PORT to a different port (1024–65535) and retry.`));
192
- }
193
- else {
194
- reject(error);
195
- }
196
- });
197
- server.listen(callbackPort, '127.0.0.1', async () => {
198
- try {
199
- const response = await fetch(`${baseUrl}/api/cli/auth/start`, {
200
- method: 'POST',
201
- headers: { 'Content-Type': 'application/json' },
202
- body: JSON.stringify({ codeChallenge, redirectUri }),
203
- });
204
- if (!response.ok) {
205
- const text = await response.text();
206
- server.close();
207
- reject(new Error(`Failed to start login: ${text}`));
208
- return;
209
- }
210
- const { authorizeUrl } = await parseJsonResponse(response, 'CLI auth start');
211
- const safeAuthorizeUrl = validateBrowserUrl(authorizeUrl, baseUrl).href;
212
- printLoginProgress(`Opening browser for login: ${sanitizeTerminalText(safeAuthorizeUrl)}`);
213
- openInBrowser(safeAuthorizeUrl);
214
- }
215
- catch (error) {
216
- server.close();
217
- reject(error);
218
- }
219
- });
220
- });
221
- rememberProcessSecret(callbackCode);
222
- const exchangeResponse = await fetch(`${baseUrl}/api/cli/auth/exchange`, {
223
- method: 'POST',
224
- headers: { 'Content-Type': 'application/json' },
225
- body: JSON.stringify({ code: callbackCode, codeVerifier, redirectUri }),
226
- });
227
- if (!exchangeResponse.ok) {
228
- const text = await exchangeResponse.text();
229
- throw new Error(`Failed to exchange auth code: ${text}`);
230
- }
231
- const loginData = await parseJsonResponse(exchangeResponse, 'CLI auth exchange');
232
- if (!loginData.apiKey) {
233
- throw new Error('Server did not return an API key. Upgrade the Orizu server and run `orizu login` again.');
234
- }
235
- return { ...loginData, apiKey: loginData.apiKey };
132
+ return completeLogin({ baseUrl, codeVerifier, codeChallenge, callbackPort: isHeadlessLogin ? undefined : resolveAuthCallbackPort() }, { parseJsonResponse, printProgress: printLoginProgress, sanitizeTerminalText, validateBrowserUrl });
236
133
  }
237
134
  async function whoami() {
238
135
  const response = await authedFetch('/api/cli/auth/whoami');
@@ -0,0 +1,143 @@
1
+ import { Schema } from 'effect';
2
+ import { type OneRequestWrite } from './one-request-write.js';
3
+ type Write<A> = Pick<OneRequestWrite<A>, 'label' | 'name' | 'path' | 'method' | 'body' | 'reply' | 'mayAlreadyBeSaved' | 'describeError'>;
4
+ declare const TaskCreated: Schema.Struct<{
5
+ readonly task: Schema.Struct<{
6
+ readonly id: Schema.String;
7
+ readonly title: Schema.String;
8
+ readonly status: Schema.String;
9
+ readonly requiredAssignmentsPerRow: Schema.Number;
10
+ readonly versionId: Schema.String;
11
+ readonly versionNum: Schema.Number;
12
+ }>;
13
+ readonly assignmentsCreated: Schema.Number;
14
+ readonly assignmentShortfall: Schema.optionalKey<Schema.Number>;
15
+ readonly warning: Schema.optionalKey<Schema.String>;
16
+ }>;
17
+ /** Running it again makes a second task (and, with --publish, emails labellers again). */
18
+ export declare const taskCreate: (body: Record<string, unknown>, describeError: Write<typeof TaskCreated.Type>["describeError"]) => Write<typeof TaskCreated.Type>;
19
+ declare const TaskUpdated: Schema.Struct<{
20
+ readonly task: Schema.Struct<{
21
+ readonly id: Schema.String;
22
+ readonly title: Schema.optionalKey<Schema.NullOr<Schema.String>>;
23
+ readonly status: Schema.optionalKey<Schema.NullOr<Schema.String>>;
24
+ readonly dataset_id: Schema.optionalKey<Schema.NullOr<Schema.String>>;
25
+ readonly app_id: Schema.optionalKey<Schema.NullOr<Schema.String>>;
26
+ readonly version_id: Schema.optionalKey<Schema.NullOr<Schema.String>>;
27
+ readonly required_assignments_per_row: Schema.optionalKey<Schema.NullOr<Schema.Number>>;
28
+ }>;
29
+ readonly assignmentMode: Schema.optionalKey<Schema.String>;
30
+ readonly assignmentsCreated: Schema.optionalKey<Schema.Number>;
31
+ }>;
32
+ /** Sets the same values again, so a repeat is safe. */
33
+ export declare const taskUpdate: (id: string, body: Record<string, unknown>) => Write<typeof TaskUpdated.Type>;
34
+ declare const Discarded: Schema.Struct<{
35
+ readonly success: Schema.Boolean;
36
+ }>;
37
+ /** Once the draft is gone, a repeat is refused as "not found". */
38
+ export declare const taskDiscard: (id: string) => Write<typeof Discarded.Type>;
39
+ declare const Published: Schema.Struct<{
40
+ readonly assignmentsProcessed: Schema.Number;
41
+ readonly assignmentsCreated: Schema.Number;
42
+ readonly assignmentsRemoved: Schema.optionalKey<Schema.Number>;
43
+ readonly assignmentShortfall: Schema.optionalKey<Schema.Number>;
44
+ readonly warning: Schema.optionalKey<Schema.String>;
45
+ readonly task: Schema.Struct<{
46
+ readonly id: Schema.String;
47
+ readonly status: Schema.String;
48
+ }>;
49
+ }>;
50
+ /** Once published, a repeat is refused as "must be a draft". */
51
+ export declare const taskPublish: (id: string, body: Record<string, unknown>) => Write<typeof Published.Type>;
52
+ declare const Assigned: Schema.Struct<{
53
+ assignmentsCreated: Schema.Number;
54
+ assignmentsProcessed: Schema.optionalKey<Schema.Number>;
55
+ assignmentsRemoved: Schema.optionalKey<Schema.Number>;
56
+ assignmentShortfall: Schema.optionalKey<Schema.Number>;
57
+ warning: Schema.optionalKey<Schema.String>;
58
+ }>;
59
+ /** Adds only missing pairs and emails only new people, so a repeat is safe. */
60
+ export declare const taskAssign: (id: string, body: Record<string, unknown>) => Write<typeof Assigned.Type>;
61
+ declare const StatusChanged: Schema.Struct<{
62
+ readonly task: Schema.Struct<{
63
+ readonly id: Schema.String;
64
+ readonly status: Schema.String;
65
+ }>;
66
+ }>;
67
+ /** Setting the status a task already has changes nothing. */
68
+ export declare const taskStatus: (id: string, verb: string, status: string) => Write<typeof StatusChanged.Type>;
69
+ declare const RunStarted: Schema.Struct<{
70
+ readonly optimization_run_id: Schema.String;
71
+ readonly optimizationRun: Schema.Struct<{
72
+ readonly id: Schema.String;
73
+ readonly status: Schema.String;
74
+ readonly startedAt: Schema.optionalKey<Schema.NullOr<Schema.String>>;
75
+ readonly createdAt: Schema.optionalKey<Schema.NullOr<Schema.String>>;
76
+ }>;
77
+ }>;
78
+ /** The server picks a new run id per request, so running it again starts a second run. */
79
+ export declare const optimizationStart: (project: string, body: Record<string, unknown>) => Write<typeof RunStarted.Type>;
80
+ declare const RunChanged: Schema.Struct<{
81
+ readonly optimizationRun: Schema.Struct<{
82
+ readonly id: Schema.String;
83
+ readonly status: Schema.optionalKey<Schema.String>;
84
+ readonly startedAt: Schema.optionalKey<Schema.NullOr<Schema.String>>;
85
+ readonly finishedAt: Schema.optionalKey<Schema.NullOr<Schema.String>>;
86
+ readonly bestScore: Schema.optionalKey<Schema.NullOr<Schema.Number>>;
87
+ readonly bestCandidateId: Schema.optionalKey<Schema.NullOr<Schema.String>>;
88
+ readonly resultPromptVersionId: Schema.optionalKey<Schema.NullOr<Schema.String>>;
89
+ readonly metadata: Schema.optionalKey<Schema.$Record<Schema.String, Schema.Unknown>>;
90
+ }>;
91
+ readonly cancellationStatus: Schema.optionalKey<Schema.Literal<"already_terminal">>;
92
+ }>;
93
+ /** Writing the status a run already has again converges, so a repeat is safe. */
94
+ export declare const optimizationLifecycle: (runId: string, body: Record<string, unknown>) => Write<typeof RunChanged.Type>;
95
+ declare const EventLogged: Schema.Struct<{
96
+ readonly eventId: Schema.String;
97
+ }>;
98
+ /** A repeat with the same event id changes nothing; a new id is refused as a sequence clash. */
99
+ export declare const optimizationEvent: (runId: string, body: Record<string, unknown> & {
100
+ eventId: string;
101
+ }) => Write<typeof EventLogged.Type>;
102
+ declare const Linked: Schema.Struct<{
103
+ readonly app: Schema.Struct<{
104
+ readonly id: Schema.String;
105
+ readonly name: Schema.String;
106
+ }>;
107
+ readonly linkedDataset: Schema.Struct<{
108
+ readonly id: Schema.String;
109
+ readonly name: Schema.String;
110
+ }>;
111
+ readonly versionNum: Schema.Number;
112
+ }>;
113
+ /**
114
+ * A plain overwrite, so a repeat is safe; without --version it links the
115
+ * app's current version at the time, which may have moved on.
116
+ */
117
+ export declare const appLinkDataset: (appId: string, body: {
118
+ datasetId: string;
119
+ versionNum?: number;
120
+ }) => Write<typeof Linked.Type>;
121
+ declare const Accepted: Schema.Struct<{
122
+ readonly scoreRun: Schema.Struct<{
123
+ readonly id: Schema.String;
124
+ readonly provenance: Schema.String;
125
+ readonly acceptedByUserId: Schema.NullOr<Schema.String>;
126
+ readonly acceptedAt: Schema.NullOr<Schema.String>;
127
+ readonly alreadyAccepted: Schema.Boolean;
128
+ }>;
129
+ }>;
130
+ /** The first acceptance is kept and a repeat says "already accepted". */
131
+ export declare const scoreAccept: (project: string, scoreRunId: string) => Write<typeof Accepted.Type>;
132
+ declare const ManifestRejected: Schema.Struct<{
133
+ readonly manifest: Schema.$Record<Schema.String, Schema.Unknown>;
134
+ }>;
135
+ /** Once rejected, a repeat is refused, so the advice is to look first. */
136
+ export declare const manifestReject: (id: string) => Write<typeof ManifestRejected.Type>;
137
+ /** Sends a write with this command's `--json` setting and output. Ctrl-C sets the exit code and returns null. */
138
+ export declare function sendCommandWrite<A>(write: Write<A>, io: {
139
+ json: boolean;
140
+ print: (line: string) => void;
141
+ }): Promise<A | null>;
142
+ export {};
143
+ //# sourceMappingURL=cli-write-commands.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli-write-commands.d.ts","sourceRoot":"","sources":["../src/cli-write-commands.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,123 @@
1
+ import { Schema } from 'effect';
2
+ import { sendOneRequestWrite } from './one-request-write.js';
3
+ // ORI-2726: what each one-request write command sends, the reply it expects,
4
+ // and what to tell a person when the write may already be saved. The advice
5
+ // follows what the server does when the same request arrives twice. Loaded
6
+ // only through `await import(...)`, so commands that never write skip Effect.
7
+ const SAFE = 'running the same command again is safe';
8
+ const note = (thing, done, advice) => ({ thing, done, advice });
9
+ const task = (id) => `/api/cli/tasks/${encodeURIComponent(id)}`;
10
+ const Count = Schema.Number;
11
+ const Text = Schema.String;
12
+ const Assignments = {
13
+ assignmentsCreated: Count,
14
+ assignmentsProcessed: Schema.optionalKey(Count),
15
+ assignmentsRemoved: Schema.optionalKey(Count),
16
+ assignmentShortfall: Schema.optionalKey(Count),
17
+ warning: Schema.optionalKey(Text),
18
+ };
19
+ const TaskCreated = Schema.Struct({
20
+ task: Schema.Struct({ id: Text, title: Text, status: Text, requiredAssignmentsPerRow: Count, versionId: Text, versionNum: Count }),
21
+ assignmentsCreated: Count,
22
+ assignmentShortfall: Schema.optionalKey(Count),
23
+ warning: Schema.optionalKey(Text),
24
+ });
25
+ /** Running it again makes a second task (and, with --publish, emails labellers again). */
26
+ export const taskCreate = (body, describeError) => ({
27
+ label: 'create task', name: 'Task create', path: '/api/cli/tasks', method: 'POST', body, reply: TaskCreated, describeError,
28
+ mayAlreadyBeSaved: note('task', 'created', 'check `orizu tasks list` before creating it again (running it again makes a second task)'),
29
+ });
30
+ const Nullable = (schema) => Schema.optionalKey(Schema.NullOr(schema));
31
+ const TaskUpdated = Schema.Struct({
32
+ task: Schema.Struct({
33
+ id: Text, title: Nullable(Text), status: Nullable(Text), dataset_id: Nullable(Text), app_id: Nullable(Text),
34
+ version_id: Nullable(Text), required_assignments_per_row: Nullable(Count),
35
+ }),
36
+ assignmentMode: Schema.optionalKey(Text),
37
+ assignmentsCreated: Schema.optionalKey(Count),
38
+ });
39
+ /** Sets the same values again, so a repeat is safe. */
40
+ export const taskUpdate = (id, body) => ({
41
+ label: 'update task', name: 'Task update', path: task(id), method: 'PATCH', body, reply: TaskUpdated, mayAlreadyBeSaved: note('task change', 'saved', SAFE),
42
+ });
43
+ const Discarded = Schema.Struct({ success: Schema.Boolean });
44
+ /** Once the draft is gone, a repeat is refused as "not found". */
45
+ export const taskDiscard = (id) => ({
46
+ label: 'discard draft task', name: 'Draft discard', path: task(id), method: 'DELETE', reply: Discarded,
47
+ mayAlreadyBeSaved: note('draft', 'discarded', 'check `orizu tasks list`; once it is gone, running it again answers "Task not found or access denied"'),
48
+ });
49
+ const Published = Schema.Struct({ task: Schema.Struct({ id: Text, status: Text }), ...Assignments, assignmentsProcessed: Count });
50
+ /** Once published, a repeat is refused as "must be a draft". */
51
+ export const taskPublish = (id, body) => ({
52
+ label: 'publish task', name: 'Task publish', path: `${task(id)}/publish`, method: 'POST', body, reply: Published,
53
+ mayAlreadyBeSaved: note('task', 'published', `check \`orizu tasks status --task ${id}\`; once published, running it again answers "Task must be a draft before publishing"`),
54
+ });
55
+ const Assigned = Schema.Struct(Assignments);
56
+ /** Adds only missing pairs and emails only new people, so a repeat is safe. */
57
+ export const taskAssign = (id, body) => ({
58
+ label: 'assign task', name: 'Task assign', path: `${task(id)}/assign`, method: 'POST', body, reply: Assigned, mayAlreadyBeSaved: note('assignments', 'saved', SAFE),
59
+ });
60
+ const StatusChanged = Schema.Struct({ task: Schema.Struct({ id: Text, status: Text }) });
61
+ /** Setting the status a task already has changes nothing. */
62
+ export const taskStatus = (id, verb, status) => ({
63
+ label: `${verb} task`, name: `Task ${verb}`, path: `${task(id)}/status`, method: 'PATCH', body: { status }, reply: StatusChanged,
64
+ mayAlreadyBeSaved: note('task status change', 'saved', SAFE),
65
+ });
66
+ const RunStarted = Schema.Struct({
67
+ optimization_run_id: Text,
68
+ optimizationRun: Schema.Struct({ id: Text, status: Text, startedAt: Nullable(Text), createdAt: Nullable(Text) }),
69
+ });
70
+ /** The server picks a new run id per request, so running it again starts a second run. */
71
+ export const optimizationStart = (project, body) => ({
72
+ label: 'start optimization run', name: 'Optimization run start', path: `/api/cli/optimization-runs?project=${encodeURIComponent(project)}`, method: 'POST', body, reply: RunStarted,
73
+ mayAlreadyBeSaved: note('run', 'started', 'check `orizu optimizations list` before starting again (running it again starts a second run)'),
74
+ });
75
+ const RunChanged = Schema.Struct({
76
+ optimizationRun: Schema.Struct({
77
+ id: Text, status: Schema.optionalKey(Text), startedAt: Nullable(Text), finishedAt: Nullable(Text), bestScore: Nullable(Count),
78
+ bestCandidateId: Nullable(Text), resultPromptVersionId: Nullable(Text), metadata: Schema.optionalKey(Schema.Record(Text, Schema.Unknown)),
79
+ }),
80
+ cancellationStatus: Schema.optionalKey(Schema.Literal('already_terminal')),
81
+ });
82
+ /** Writing the status a run already has again converges, so a repeat is safe. */
83
+ export const optimizationLifecycle = (runId, body) => ({
84
+ label: 'update optimization run', name: 'Optimization run update', path: `/api/cli/optimization-runs/${encodeURIComponent(runId)}`, method: 'PATCH', body, reply: RunChanged,
85
+ mayAlreadyBeSaved: note('run status change', 'saved', SAFE),
86
+ });
87
+ const EventLogged = Schema.Struct({ eventId: Text });
88
+ /** A repeat with the same event id changes nothing; a new id is refused as a sequence clash. */
89
+ export const optimizationEvent = (runId, body) => ({
90
+ label: 'log event', name: 'Event log', path: `/api/cli/optimization-runs/${encodeURIComponent(runId)}/events`, method: 'POST', body, reply: EventLogged,
91
+ mayAlreadyBeSaved: note('event', 'logged', `run the same command again with \`--event-id ${body.eventId}\` (a new id would be refused as a clash)`),
92
+ });
93
+ const Linked = Schema.Struct({ app: Schema.Struct({ id: Text, name: Text }), linkedDataset: Schema.Struct({ id: Text, name: Text }), versionNum: Count });
94
+ /**
95
+ * A plain overwrite, so a repeat is safe; without --version it links the
96
+ * app's current version at the time, which may have moved on.
97
+ */
98
+ export const appLinkDataset = (appId, body) => ({
99
+ label: 'link dataset', name: 'Dataset link', path: `/api/cli/apps/${encodeURIComponent(appId)}/link-dataset`, method: 'POST', body, reply: Linked,
100
+ mayAlreadyBeSaved: note('link', 'saved', body.versionNum === undefined ? 'running it again with `--version <n>` for the version you meant is safe' : SAFE),
101
+ });
102
+ const Accepted = Schema.Struct({
103
+ scoreRun: Schema.Struct({ id: Text, provenance: Text, acceptedByUserId: Schema.NullOr(Text), acceptedAt: Schema.NullOr(Text), alreadyAccepted: Schema.Boolean }),
104
+ });
105
+ /** The first acceptance is kept and a repeat says "already accepted". */
106
+ export const scoreAccept = (project, scoreRunId) => ({
107
+ label: 'accept score run', name: 'Score run accept', path: `/api/cli/scores/accept?project=${encodeURIComponent(project)}`, method: 'POST', body: { scoreRunId }, reply: Accepted,
108
+ mayAlreadyBeSaved: note('acceptance', 'saved', SAFE),
109
+ });
110
+ const ManifestRejected = Schema.Struct({ manifest: Schema.Record(Text, Schema.Unknown) });
111
+ /** Once rejected, a repeat is refused, so the advice is to look first. */
112
+ export const manifestReject = (id) => ({
113
+ label: 'reject manifest', name: 'Manifest reject', path: `/api/cli/promotion-manifests/${encodeURIComponent(id)}`, method: 'POST', body: { action: 'reject' }, reply: ManifestRejected,
114
+ mayAlreadyBeSaved: note('manifest', 'rejected', `check \`orizu manifests show ${id}\``),
115
+ });
116
+ /** Sends a write with this command's `--json` setting and output. Ctrl-C sets the exit code and returns null. */
117
+ export async function sendCommandWrite(write, io) {
118
+ const outcome = await sendOneRequestWrite({ ...write, ...io });
119
+ if (outcome.kind === 'saved')
120
+ return outcome.reply;
121
+ process.exitCode = outcome.exitCode;
122
+ return null;
123
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAsLA,OAAO,EAAE,kBAAkB,EAAE,MAAM,6BAA6B,CAAA;AAEhE,eAAO,MAAM,wBAAwB,GAAI,iBAAiB,MAAM;;;EACJ,CAAA;AAE5D,OAAO,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAA;AAC5E,OAAO,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAA;AA+sCtD,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,MAAM,GAAG;IAAE,OAAO,EAAE,MAAM,EAAE,CAAC;IAAC,kBAAkB,CAAC,EAAE,MAAM,EAAE,CAAA;CAAE,CA0B1G;AAED,eAAO,MAAM,iBAAiB,SAAU,CAAA;AACxC,eAAO,MAAM,uBAAuB,QAAkB,CAAA;AACtD,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,iBAAiB,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC,UAAU,CAexH;AAmMD,wBAAsB,IAAI,CAAC,OAAO,WAAwB,iBAiiBzD;AA8DD,OAAO,EAAE,kBAAkB,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAA;AAEhF,OAAO,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAuLA,OAAO,EAAE,kBAAkB,EAAE,MAAM,6BAA6B,CAAA;AAEhE,eAAO,MAAM,wBAAwB,GAAI,iBAAiB,MAAM;;;EACJ,CAAA;AAE5D,OAAO,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAA;AAC5E,OAAO,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAA;AAmqCtD,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,MAAM,GAAG;IAAE,OAAO,EAAE,MAAM,EAAE,CAAC;IAAC,kBAAkB,CAAC,EAAE,MAAM,EAAE,CAAA;CAAE,CA0B1G;AAED,eAAO,MAAM,iBAAiB,SAAU,CAAA;AACxC,eAAO,MAAM,uBAAuB,QAAkB,CAAA;AACtD,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,iBAAiB,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC,UAAU,CAexH;AAmMD,wBAAsB,IAAI,CAAC,OAAO,WAAwB,iBAiiBzD;AAuED,OAAO,EAAE,kBAAkB,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAA;AAEhF,OAAO,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAA"}
package/dist/index.js CHANGED
@@ -62,7 +62,8 @@ import { killSwitchCommand } from './kill-switch-cli.js';
62
62
  import { egressAllowlistCommand } from './egress-allowlist-cli.js';
63
63
  import { teamConnectorsCommand } from './team-connectors-cli.js';
64
64
  import { inspectExistingWorkspaceTeam, getWorkspaceRoot } from './workspace.js';
65
- import { writeLastErrorRecord, extractLastErrorCode } from './last-error-record.js';
65
+ import { errorOutputSecrets, writeLastErrorRecord, extractLastErrorCode } from './last-error-record.js';
66
+ import { redactSecrets } from './secret-redaction.js';
66
67
  export { loadInstructionSet } from './instruction-set-loader.js';
67
68
  export const materializeRunnerVersion = (runnerVersionId) => materializeRegisteredRunnerVersion(runnerVersionId, false);
68
69
  export { parseJsonResponse, sanitizeTerminalText } from './json-response.js';
@@ -123,26 +124,21 @@ async function logOptimizationEvent() {
123
124
  if (!eventType || eventType.startsWith('--') || !runId || !Number.isInteger(sequence) || sequence <= 0) {
124
125
  throw new Error('Usage: orizu log <event_type> --run-id <id> --sequence <n> --payload @event.json');
125
126
  }
126
- const response = await authedFetch(`/api/cli/optimization-runs/${encodeURIComponent(runId)}/events`, {
127
- method: 'POST',
128
- headers: { 'Content-Type': 'application/json' },
129
- body: JSON.stringify({
130
- eventId: getArg('--event-id') || randomUUID(),
131
- sequence,
132
- eventType,
133
- eventLayer: getArg('--event-layer') || 'core',
134
- optimizerFamily: getArg('--optimizer-family'),
135
- iteration: getArg('--iteration') ? Number(getArg('--iteration')) : undefined,
136
- candidateId: getArg('--candidate-id'),
137
- parentCandidateId: getArg('--parent-candidate-id'),
138
- childCandidateId: getArg('--child-candidate-id'),
139
- payload,
140
- }),
141
- });
142
- if (!response.ok) {
143
- throw new Error(`Failed to log event: ${await response.text()}`);
144
- }
145
- const data = await parseJsonResponse(response, 'Optimization event log');
127
+ const writes = await import('./cli-write-commands.js');
128
+ const data = await writes.sendCommandWrite(writes.optimizationEvent(runId, {
129
+ eventId: getArg('--event-id') || randomUUID(),
130
+ sequence,
131
+ eventType,
132
+ eventLayer: getArg('--event-layer') || 'core',
133
+ optimizerFamily: getArg('--optimizer-family'),
134
+ iteration: getArg('--iteration') ? Number(getArg('--iteration')) : undefined,
135
+ candidateId: getArg('--candidate-id'),
136
+ parentCandidateId: getArg('--parent-candidate-id'),
137
+ childCandidateId: getArg('--child-candidate-id'),
138
+ payload,
139
+ }), { json: hasJsonFlag(), print: printLine });
140
+ if (!data)
141
+ return;
146
142
  if (hasJsonFlag()) {
147
143
  printJson({ eventId: data.eventId });
148
144
  return;
@@ -822,25 +818,20 @@ async function startOptimizationRun() {
822
818
  trackedScope: 'best_candidate',
823
819
  })),
824
820
  ];
825
- const response = await authedFetch(`/api/cli/optimization-runs?project=${encodeURIComponent(project)}`, {
826
- method: 'POST',
827
- headers: { 'Content-Type': 'application/json' },
828
- body: JSON.stringify({
829
- optimizerVersionId,
830
- promptVersionIds,
831
- judgeVersionIds,
832
- scorers,
833
- datasetVersionId,
834
- splitSetId,
835
- trainSplitName: getArg('--train-split') || undefined,
836
- validationSplitName: getArg('--validation-split') || undefined,
837
- metadata,
838
- }),
839
- });
840
- if (!response.ok) {
841
- throw new Error(`Failed to start optimization run: ${await response.text()}`);
842
- }
843
- const data = await parseJsonResponse(response, 'Optimization run start');
821
+ const writes = await import('./cli-write-commands.js');
822
+ const data = await writes.sendCommandWrite(writes.optimizationStart(project, {
823
+ optimizerVersionId,
824
+ promptVersionIds,
825
+ judgeVersionIds,
826
+ scorers,
827
+ datasetVersionId,
828
+ splitSetId,
829
+ trainSplitName: getArg('--train-split') || undefined,
830
+ validationSplitName: getArg('--validation-split') || undefined,
831
+ metadata,
832
+ }), { json: hasJsonFlag(), print: printLine });
833
+ if (!data)
834
+ return;
844
835
  if (hasJsonFlag()) {
845
836
  printJson(data);
846
837
  return;
@@ -897,15 +888,10 @@ async function updateOptimizationRunLifecycle(action) {
897
888
  body.resultPromptVersionId = resultPromptVersionId;
898
889
  }
899
890
  }
900
- const response = await authedFetch(`/api/cli/optimization-runs/${encodeURIComponent(runId)}`, {
901
- method: 'PATCH',
902
- headers: { 'Content-Type': 'application/json' },
903
- body: JSON.stringify(body),
904
- });
905
- if (!response.ok) {
906
- throw new Error(`Failed to update optimization run: ${await response.text()}`);
907
- }
908
- const data = await parseJsonResponse(response, 'Optimization run update');
891
+ const writes = await import('./cli-write-commands.js');
892
+ const data = await writes.sendCommandWrite(writes.optimizationLifecycle(runId, body), { json: hasJsonFlag(), print: printLine });
893
+ if (!data)
894
+ return;
909
895
  if (hasJsonFlag()) {
910
896
  printJson(data);
911
897
  return;
@@ -1805,9 +1791,17 @@ function isCliEntrypoint() {
1805
1791
  return false;
1806
1792
  }
1807
1793
  }
1794
+ // A secret this process holds (a login code, its verifier, a poll token, a
1795
+ // bearer, a forwarded runner key) is never printed, even when a server echoes
1796
+ // it back in an error. last-error.json hides the same values. Scrubbed again
1797
+ // after control characters are stripped, so one inside a secret can't hide it.
1798
+ function printErrorWithoutSecrets(message) {
1799
+ const secrets = errorOutputSecrets();
1800
+ printError(redactSecrets(sanitizeTerminalText(redactSecrets(message, { secrets })), { secrets }));
1801
+ }
1808
1802
  if (isCliEntrypoint()) {
1809
1803
  const rawArgs = process.argv.slice(2);
1810
- withPassiveUpdateNotice(rawArgs, getCliVersion, printError, args =>
1804
+ withPassiveUpdateNotice(rawArgs, getCliVersion, printErrorWithoutSecrets, args =>
1811
1805
  // ORI-2429: the process-boundary adapter stays a Promise (ADR-038 guide); the record write is Effect-owned and never replaces this error.
1812
1806
  main(args).catch(async (error) => {
1813
1807
  const message = error instanceof Error ? error.message : 'Unknown error';
@@ -29,6 +29,13 @@ export interface LastErrorRecordInput {
29
29
  export interface WriteLastErrorRecordOptions {
30
30
  configDir?: string;
31
31
  }
32
+ /**
33
+ * The values no error output may show: this process's remembered secrets, the
34
+ * current bearer and runner-forwarded keys. last-error.json and the terminal's
35
+ * error line both use this list. Longest first, so a secret inside another
36
+ * can't leave part of the longer one behind.
37
+ */
38
+ export declare function errorOutputSecrets(): string[];
32
39
  export declare function extractLastErrorCode(error: unknown): string | null;
33
40
  export declare function isStringWithinCap(value: unknown, maximumCharacters: number, wasTruncated: boolean): value is string;
34
41
  export declare function boundedServerBaseUrl(value: string | null | undefined): string | null;
@@ -1 +1 @@
1
- {"version":3,"file":"last-error-record.d.ts","sourceRoot":"","sources":["../src/last-error-record.ts"],"names":[],"mappings":"AAqBA,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,CAAC,CAAA;IACV,UAAU,EAAE,MAAM,CAAA;IAClB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;IACzB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;IACnB,aAAa,EAAE,MAAM,GAAG,IAAI,CAAA;IAC5B,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAA;IACvB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;IACtB,IAAI,EAAE,MAAM,EAAE,CAAA;IACd,aAAa,EAAE,OAAO,CAAA;IACtB,OAAO,EAAE,MAAM,CAAA;IACf,gBAAgB,EAAE,OAAO,CAAA;CAC1B;AAED,eAAO,MAAM,yBAAyB,IAAI,CAAA;AAC1C,eAAO,MAAM,mBAAmB,oBAAoB,CAAA;AACpD,eAAO,MAAM,4BAA4B,WAAa,CAAA;AACtD,eAAO,MAAM,4BAA4B,gBAAgB,CAAA;AAezD,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,SAAS,MAAM,EAAE,CAAA;IACvB,OAAO,EAAE,MAAM,CAAA;IACf,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;IACzB,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACpB,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC7B,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACvB,OAAO,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;IAC3B,GAAG,CAAC,EAAE,IAAI,CAAA;CACX;AAED,MAAM,WAAW,2BAA2B;IAC1C,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AA8ID,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAKlE;AAUD,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,OAAO,EACd,iBAAiB,EAAE,MAAM,EACzB,YAAY,EAAE,OAAO,GACpB,KAAK,IAAI,MAAM,CAMjB;AAED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,GAAG,IAAI,CAIpF;AAED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,oBAAoB,GAAG,eAAe,CA0DjF;AAED,wBAAgB,sBAAsB,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,CAEjE;AAED,wBAAsB,oBAAoB,CACxC,KAAK,EAAE,oBAAoB,EAC3B,OAAO,GAAE,2BAAgC,GACxC,OAAO,CAAC,IAAI,CAAC,CAqBf;AAED,wBAAsB,mBAAmB,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC,CAQ7F"}
1
+ {"version":3,"file":"last-error-record.d.ts","sourceRoot":"","sources":["../src/last-error-record.ts"],"names":[],"mappings":"AAqBA,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,CAAC,CAAA;IACV,UAAU,EAAE,MAAM,CAAA;IAClB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;IACzB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;IACnB,aAAa,EAAE,MAAM,GAAG,IAAI,CAAA;IAC5B,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAA;IACvB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;IACtB,IAAI,EAAE,MAAM,EAAE,CAAA;IACd,aAAa,EAAE,OAAO,CAAA;IACtB,OAAO,EAAE,MAAM,CAAA;IACf,gBAAgB,EAAE,OAAO,CAAA;CAC1B;AAED,eAAO,MAAM,yBAAyB,IAAI,CAAA;AAC1C,eAAO,MAAM,mBAAmB,oBAAoB,CAAA;AACpD,eAAO,MAAM,4BAA4B,WAAa,CAAA;AACtD,eAAO,MAAM,4BAA4B,gBAAgB,CAAA;AAezD,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,SAAS,MAAM,EAAE,CAAA;IACvB,OAAO,EAAE,MAAM,CAAA;IACf,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;IACzB,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACpB,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC7B,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACvB,OAAO,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;IAC3B,GAAG,CAAC,EAAE,IAAI,CAAA;CACX;AAED,MAAM,WAAW,2BAA2B;IAC1C,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AA6HD;;;;;GAKG;AACH,wBAAgB,kBAAkB,IAAI,MAAM,EAAE,CAI7C;AAsBD,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAKlE;AAUD,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,OAAO,EACd,iBAAiB,EAAE,MAAM,EACzB,YAAY,EAAE,OAAO,GACpB,KAAK,IAAI,MAAM,CAMjB;AAED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,GAAG,IAAI,CAIpF;AAED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,oBAAoB,GAAG,eAAe,CA0DjF;AAED,wBAAgB,sBAAsB,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,CAEjE;AAED,wBAAsB,oBAAoB,CACxC,KAAK,EAAE,oBAAoB,EAC3B,OAAO,GAAE,2BAAgC,GACxC,OAAO,CAAC,IAAI,CAAC,CAoBf;AAED,wBAAsB,mBAAmB,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC,CAQ7F"}