orizu 0.5.50 → 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.
- package/dist/app-commands.d.ts.map +1 -1
- package/dist/app-commands.js +4 -12
- package/dist/auth-commands.d.ts.map +1 -1
- package/dist/auth-commands.js +13 -112
- package/dist/cli-write-commands.d.ts +143 -0
- package/dist/cli-write-commands.d.ts.map +1 -0
- package/dist/cli-write-commands.js +123 -0
- package/dist/credentials-transaction.d.ts +7 -0
- package/dist/credentials-transaction.d.ts.map +1 -0
- package/dist/credentials-transaction.js +60 -0
- package/dist/credentials.d.ts +19 -1
- package/dist/credentials.d.ts.map +1 -1
- package/dist/credentials.js +118 -73
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +44 -50
- package/dist/last-error-record.d.ts +7 -0
- package/dist/last-error-record.d.ts.map +1 -1
- package/dist/last-error-record.js +14 -2
- package/dist/login-flow.d.ts +37 -0
- package/dist/login-flow.d.ts.map +1 -0
- package/dist/login-flow.js +295 -0
- package/dist/logout-diagnostic.d.ts.map +1 -1
- package/dist/logout-diagnostic.js +2 -1
- package/dist/manifests-cli.d.ts.map +1 -1
- package/dist/manifests-cli.js +36 -22
- package/dist/one-request-write.d.ts +59 -0
- package/dist/one-request-write.d.ts.map +1 -0
- package/dist/one-request-write.js +157 -0
- package/dist/provider-write-workflow.d.ts +12 -0
- package/dist/provider-write-workflow.d.ts.map +1 -0
- package/dist/provider-write-workflow.js +110 -0
- package/dist/providers-cli.d.ts.map +1 -1
- package/dist/providers-cli.js +27 -23
- package/dist/scores-accept-cli.d.ts +1 -1
- package/dist/scores-accept-cli.d.ts.map +1 -1
- package/dist/scores-accept-cli.js +4 -28
- package/dist/stored-session-requests.d.ts.map +1 -1
- package/dist/stored-session-requests.js +8 -4
- package/dist/task-commands.d.ts.map +1 -1
- package/dist/task-commands.js +26 -62
- package/package.json +1 -1
- package/src/app-commands.ts +3 -18
- package/src/auth-commands.ts +17 -131
- package/src/cli-write-commands.ts +143 -0
- package/src/credentials-transaction.ts +73 -0
- package/src/credentials.ts +128 -86
- package/src/index.ts +23 -57
- package/src/last-error-record.ts +16 -2
- package/src/login-flow.ts +368 -0
- package/src/logout-diagnostic.ts +2 -1
- package/src/manifests-cli.ts +36 -23
- package/src/one-request-write.ts +192 -0
- package/src/provider-write-workflow.ts +117 -0
- package/src/providers-cli.ts +24 -17
- package/src/scores-accept-cli.ts +4 -46
- package/src/stored-session-requests.ts +7 -4
- package/src/task-commands.ts +22 -115
- package/dist/headless-login.d.ts +0 -19
- package/dist/headless-login.d.ts.map +0 -1
- package/dist/headless-login.js +0 -108
- package/src/headless-login.ts +0 -192
package/dist/credentials.js
CHANGED
|
@@ -9,6 +9,11 @@ import { canonicalServerUrl, normalizeBaseUrl } from './global-flags.js';
|
|
|
9
9
|
function isNodeError(error) {
|
|
10
10
|
return error instanceof Error;
|
|
11
11
|
}
|
|
12
|
+
// The system's short error code (EACCES, EPERM), never the message: messages
|
|
13
|
+
// from fs calls carry paths, and this one goes to the terminal.
|
|
14
|
+
function errorCode(error) {
|
|
15
|
+
return isNodeError(error) && typeof error.code === 'string' ? error.code : 'unknown error';
|
|
16
|
+
}
|
|
12
17
|
export function getConfigDir() {
|
|
13
18
|
if (process.env.ORIZU_CONFIG_DIR) {
|
|
14
19
|
return process.env.ORIZU_CONFIG_DIR;
|
|
@@ -20,7 +25,7 @@ function getCredentialsPath() {
|
|
|
20
25
|
}
|
|
21
26
|
const DEFAULT_CREDENTIALS_LOCK_TIMEOUT_MS = 2_000;
|
|
22
27
|
const MAX_CREDENTIALS_LOCK_TIMEOUT_MS = 10_000;
|
|
23
|
-
const CREDENTIALS_LOCK_RETRY_MS = 20;
|
|
28
|
+
export const CREDENTIALS_LOCK_RETRY_MS = 20;
|
|
24
29
|
let heldCredentialsLock = null;
|
|
25
30
|
const credentialsTransactionOwner = new AsyncLocalStorage();
|
|
26
31
|
function getCredentialsLockPath() {
|
|
@@ -38,58 +43,74 @@ function readLockDuration(name, fallback, maximum = Number.MAX_SAFE_INTEGER) {
|
|
|
38
43
|
function sleepSync(milliseconds) {
|
|
39
44
|
Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, milliseconds);
|
|
40
45
|
}
|
|
41
|
-
function
|
|
46
|
+
export function credentialsLockTimeoutMs() {
|
|
47
|
+
return readLockDuration('ORIZU_CREDENTIALS_LOCK_TIMEOUT_MS', DEFAULT_CREDENTIALS_LOCK_TIMEOUT_MS, MAX_CREDENTIALS_LOCK_TIMEOUT_MS);
|
|
48
|
+
}
|
|
49
|
+
export function credentialsLockTimeoutError(timeoutMs) {
|
|
50
|
+
return new Error(`ORIZU_CREDENTIALS_LOCK_TIMEOUT: credentials mutation did not acquire the lock within ${timeoutMs}ms. Verify no Orizu process is running, then remove credentials.json.lock manually.`);
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* One try at the cross-process lock. Returns null when another owner holds
|
|
54
|
+
* it. The waits between tries belong to the caller: a blocking one below for
|
|
55
|
+
* synchronous writers, an Effect sleep in credentials-transaction.ts.
|
|
56
|
+
*/
|
|
57
|
+
export function tryAcquireCredentialsLock() {
|
|
42
58
|
const dir = getConfigDir();
|
|
43
59
|
mkdirSync(dir, { recursive: true, mode: 0o700 });
|
|
44
60
|
chmodSync(dir, 0o700);
|
|
45
61
|
const lockPath = getCredentialsLockPath();
|
|
46
|
-
const
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
const tempPath = join(dir, `.credentials.json.lock.${process.pid}.${randomBytes(8).toString('hex')}.tmp`);
|
|
62
|
+
const metadata = JSON.stringify({
|
|
63
|
+
version: 1,
|
|
64
|
+
pid: process.pid,
|
|
65
|
+
hostname: hostname(),
|
|
66
|
+
createdAt: Date.now(),
|
|
67
|
+
instanceId: randomBytes(16).toString('hex'),
|
|
68
|
+
});
|
|
69
|
+
const tempPath = join(dir, `.credentials.json.lock.${process.pid}.${randomBytes(8).toString('hex')}.tmp`);
|
|
70
|
+
try {
|
|
71
|
+
const fd = openSync(tempPath, 'wx', 0o600);
|
|
57
72
|
try {
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
fsyncSync(fd);
|
|
62
|
-
chmodSync(tempPath, 0o600);
|
|
63
|
-
}
|
|
64
|
-
finally {
|
|
65
|
-
closeSync(fd);
|
|
66
|
-
}
|
|
67
|
-
try {
|
|
68
|
-
// link(2) publishes the already-complete inode without replacing an
|
|
69
|
-
// existing owner. No contender ever unlinks the canonical lock.
|
|
70
|
-
linkSync(tempPath, lockPath);
|
|
71
|
-
}
|
|
72
|
-
catch (error) {
|
|
73
|
-
if (!(isNodeError(error) && error.code === 'EEXIST'))
|
|
74
|
-
throw error;
|
|
75
|
-
if (Date.now() >= deadline) {
|
|
76
|
-
throw new Error(`ORIZU_CREDENTIALS_LOCK_TIMEOUT: credentials mutation did not acquire the lock within ${timeoutMs}ms. Verify no Orizu process is running, then remove credentials.json.lock manually.`);
|
|
77
|
-
}
|
|
78
|
-
sleepSync(Math.min(CREDENTIALS_LOCK_RETRY_MS, Math.max(1, deadline - Date.now())));
|
|
79
|
-
continue;
|
|
80
|
-
}
|
|
81
|
-
let resolveReleased = () => { };
|
|
82
|
-
const released = new Promise(resolve => { resolveReleased = resolve; });
|
|
83
|
-
return { path: lockPath, metadata, depth: 1, released, resolveReleased };
|
|
73
|
+
writeFileSync(fd, metadata, 'utf8');
|
|
74
|
+
fsyncSync(fd);
|
|
75
|
+
chmodSync(tempPath, 0o600);
|
|
84
76
|
}
|
|
85
77
|
finally {
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
78
|
+
closeSync(fd);
|
|
79
|
+
}
|
|
80
|
+
try {
|
|
81
|
+
// link(2) publishes the already-complete inode without replacing an
|
|
82
|
+
// existing owner. No contender ever unlinks the canonical lock.
|
|
83
|
+
linkSync(tempPath, lockPath);
|
|
84
|
+
}
|
|
85
|
+
catch (error) {
|
|
86
|
+
if (isNodeError(error) && error.code === 'EEXIST')
|
|
87
|
+
return null;
|
|
88
|
+
throw error;
|
|
89
89
|
}
|
|
90
|
+
let resolveReleased = () => { };
|
|
91
|
+
const released = new Promise(resolve => { resolveReleased = resolve; });
|
|
92
|
+
return { path: lockPath, metadata, depth: 1, released, resolveReleased };
|
|
93
|
+
}
|
|
94
|
+
finally {
|
|
95
|
+
// The unique owner-only preparation link is never retained, whether
|
|
96
|
+
// publication succeeds, loses to an owner, or fails unexpectedly.
|
|
97
|
+
rmSync(tempPath, { force: true });
|
|
90
98
|
}
|
|
91
99
|
}
|
|
92
|
-
|
|
100
|
+
/** Blocks the process between tries; only for synchronous writers. */
|
|
101
|
+
function acquireCredentialsLock() {
|
|
102
|
+
const timeoutMs = credentialsLockTimeoutMs();
|
|
103
|
+
const deadline = Date.now() + timeoutMs;
|
|
104
|
+
while (true) {
|
|
105
|
+
const lock = tryAcquireCredentialsLock();
|
|
106
|
+
if (lock)
|
|
107
|
+
return lock;
|
|
108
|
+
if (Date.now() >= deadline)
|
|
109
|
+
throw credentialsLockTimeoutError(timeoutMs);
|
|
110
|
+
sleepSync(Math.min(CREDENTIALS_LOCK_RETRY_MS, Math.max(1, deadline - Date.now())));
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
export function releaseCredentialsLock(lock) {
|
|
93
114
|
let currentMetadata;
|
|
94
115
|
try {
|
|
95
116
|
currentMetadata = readFileSync(lock.path, 'utf8');
|
|
@@ -129,17 +150,30 @@ export function withCredentialsTransactionLock(operation) {
|
|
|
129
150
|
}
|
|
130
151
|
const lock = acquireCredentialsLock();
|
|
131
152
|
heldCredentialsLock = lock;
|
|
153
|
+
let failed = false;
|
|
132
154
|
try {
|
|
133
155
|
return operation();
|
|
134
156
|
}
|
|
157
|
+
catch (error) {
|
|
158
|
+
failed = true;
|
|
159
|
+
throw error;
|
|
160
|
+
}
|
|
135
161
|
finally {
|
|
136
162
|
heldCredentialsLock = null;
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
163
|
+
endTransaction(lock, failed);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
/** Release the lock if it is still ours. A release error never hides the transaction's own error. */
|
|
167
|
+
function endTransaction(lock, failed) {
|
|
168
|
+
try {
|
|
169
|
+
releaseCredentialsLock(lock);
|
|
170
|
+
}
|
|
171
|
+
catch (releaseError) {
|
|
172
|
+
if (!failed)
|
|
173
|
+
throw releaseError;
|
|
174
|
+
}
|
|
175
|
+
finally {
|
|
176
|
+
lock.resolveReleased();
|
|
143
177
|
}
|
|
144
178
|
}
|
|
145
179
|
/**
|
|
@@ -147,7 +181,10 @@ export function withCredentialsTransactionLock(operation) {
|
|
|
147
181
|
* synchronous credential writes are admitted only from this transaction's
|
|
148
182
|
* async execution context; unrelated same-process work must wait or fail.
|
|
149
183
|
*/
|
|
150
|
-
export async function withCredentialsTransactionLockAsync(operation
|
|
184
|
+
export async function withCredentialsTransactionLockAsync(operation,
|
|
185
|
+
// How to wait for the cross-process lock. The default blocks the process
|
|
186
|
+
// between tries; stored-login commands pass credentials-transaction.ts's.
|
|
187
|
+
acquire = acquireCredentialsLock) {
|
|
151
188
|
const lockPath = getCredentialsLockPath();
|
|
152
189
|
const currentOwner = credentialsTransactionOwner.getStore();
|
|
153
190
|
if (heldCredentialsLock) {
|
|
@@ -163,7 +200,7 @@ export async function withCredentialsTransactionLockAsync(operation) {
|
|
|
163
200
|
heldCredentialsLock.depth -= 1;
|
|
164
201
|
}
|
|
165
202
|
}
|
|
166
|
-
const timeoutMs =
|
|
203
|
+
const timeoutMs = credentialsLockTimeoutMs();
|
|
167
204
|
let timer;
|
|
168
205
|
const didRelease = await Promise.race([
|
|
169
206
|
heldCredentialsLock.released.then(() => true),
|
|
@@ -171,26 +208,25 @@ export async function withCredentialsTransactionLockAsync(operation) {
|
|
|
171
208
|
]);
|
|
172
209
|
if (timer)
|
|
173
210
|
clearTimeout(timer);
|
|
174
|
-
if (!didRelease)
|
|
175
|
-
throw
|
|
176
|
-
|
|
177
|
-
return await withCredentialsTransactionLockAsync(operation);
|
|
211
|
+
if (!didRelease)
|
|
212
|
+
throw credentialsLockTimeoutError(timeoutMs);
|
|
213
|
+
return await withCredentialsTransactionLockAsync(operation, acquire);
|
|
178
214
|
}
|
|
179
|
-
const lock =
|
|
215
|
+
const lock = await acquire();
|
|
180
216
|
const owner = Symbol('credentials-transaction-owner');
|
|
181
217
|
lock.asyncOwner = owner;
|
|
182
218
|
heldCredentialsLock = lock;
|
|
219
|
+
let failed = false;
|
|
183
220
|
try {
|
|
184
221
|
return await credentialsTransactionOwner.run(owner, operation);
|
|
185
222
|
}
|
|
223
|
+
catch (error) {
|
|
224
|
+
failed = true;
|
|
225
|
+
throw error;
|
|
226
|
+
}
|
|
186
227
|
finally {
|
|
187
228
|
heldCredentialsLock = null;
|
|
188
|
-
|
|
189
|
-
releaseCredentialsLock(lock);
|
|
190
|
-
}
|
|
191
|
-
finally {
|
|
192
|
-
lock.resolveReleased();
|
|
193
|
-
}
|
|
229
|
+
endTransaction(lock, failed);
|
|
194
230
|
}
|
|
195
231
|
}
|
|
196
232
|
function assertCredentialsLockHeld() {
|
|
@@ -244,18 +280,24 @@ function writeCredentials(config) {
|
|
|
244
280
|
const tempPath = join(dir, `.credentials.json.${process.pid}.${randomBytes(8).toString('hex')}.tmp`);
|
|
245
281
|
const payload = JSON.stringify(config, null, 2) + '\n';
|
|
246
282
|
try {
|
|
247
|
-
const fd = openSync(tempPath, 'wx', 0o600);
|
|
248
283
|
try {
|
|
249
|
-
|
|
250
|
-
|
|
284
|
+
const fd = openSync(tempPath, 'wx', 0o600);
|
|
285
|
+
try {
|
|
286
|
+
writeFileSync(fd, payload, 'utf-8');
|
|
287
|
+
fsyncSync(fd);
|
|
288
|
+
}
|
|
289
|
+
finally {
|
|
290
|
+
closeSync(fd);
|
|
291
|
+
}
|
|
292
|
+
chmodSync(tempPath, 0o600);
|
|
293
|
+
// Never delete the destination to emulate replacement. If this platform
|
|
294
|
+
// cannot atomically replace it, preserve the old file and surface the error.
|
|
295
|
+
renameSync(tempPath, path);
|
|
251
296
|
}
|
|
252
|
-
|
|
253
|
-
|
|
297
|
+
catch (error) {
|
|
298
|
+
// Until the rename succeeds the saved file is untouched.
|
|
299
|
+
throw new Error(`ORIZU_CREDENTIALS_WRITE_FAILED: could not save sign-ins to ${path} (${errorCode(error)}). The saved file is unchanged.`, { cause: error });
|
|
254
300
|
}
|
|
255
|
-
chmodSync(tempPath, 0o600);
|
|
256
|
-
// Never delete the destination to emulate replacement. If this platform
|
|
257
|
-
// cannot atomically replace it, preserve the old file and surface the error.
|
|
258
|
-
renameSync(tempPath, path);
|
|
259
301
|
chmodSync(path, 0o600);
|
|
260
302
|
}
|
|
261
303
|
finally {
|
|
@@ -271,12 +313,15 @@ function createEmptyCredentialsConfig() {
|
|
|
271
313
|
servers: {},
|
|
272
314
|
};
|
|
273
315
|
}
|
|
316
|
+
// A missing file, invalid JSON or an unknown format start empty (the "log in
|
|
317
|
+
// again" recovery). A file that exists but cannot be read is never replaced:
|
|
318
|
+
// that would delete every other saved sign-in.
|
|
274
319
|
function loadCredentialsConfigForWrite() {
|
|
275
320
|
try {
|
|
276
321
|
return loadCredentialsConfig() || createEmptyCredentialsConfig();
|
|
277
322
|
}
|
|
278
|
-
catch {
|
|
279
|
-
|
|
323
|
+
catch (error) {
|
|
324
|
+
throw new Error(`ORIZU_CREDENTIALS_READ_FAILED: could not read ${getCredentialsPath()} (${errorCode(error)}). Saved sign-ins were not changed. Move it aside, then run \`orizu login\` again.`, { cause: error });
|
|
280
325
|
}
|
|
281
326
|
}
|
|
282
327
|
export function loadCredentialsConfig() {
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";
|
|
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
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
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
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
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
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
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,
|
|
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;
|
|
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"}
|
|
@@ -116,6 +116,19 @@ function serializeRecord(record) {
|
|
|
116
116
|
function isSerializedRecordTooLarge(record) {
|
|
117
117
|
return Buffer.byteLength(serializeRecord(record), 'utf8') > LAST_ERROR_FILE_MAX_BYTES;
|
|
118
118
|
}
|
|
119
|
+
/** Shorter values are left alone: replacing them would garble ordinary text. */
|
|
120
|
+
const MIN_ERROR_OUTPUT_SECRET_LENGTH = 8;
|
|
121
|
+
/**
|
|
122
|
+
* The values no error output may show: this process's remembered secrets, the
|
|
123
|
+
* current bearer and runner-forwarded keys. last-error.json and the terminal's
|
|
124
|
+
* error line both use this list. Longest first, so a secret inside another
|
|
125
|
+
* can't leave part of the longer one behind.
|
|
126
|
+
*/
|
|
127
|
+
export function errorOutputSecrets() {
|
|
128
|
+
return [...new Set([...resolveActiveProcessSecrets(), ...runnerForwardedSecretValues()])]
|
|
129
|
+
.filter(secret => typeof secret === 'string' && secret.length >= MIN_ERROR_OUTPUT_SECRET_LENGTH)
|
|
130
|
+
.sort((left, right) => right.length - left.length);
|
|
131
|
+
}
|
|
119
132
|
function resolveActiveProcessSecrets() {
|
|
120
133
|
const rememberedSecrets = getSecretsSeenThisProcess();
|
|
121
134
|
try {
|
|
@@ -230,8 +243,7 @@ export async function writeLastErrorRecord(input, options = {}) {
|
|
|
230
243
|
...input,
|
|
231
244
|
homeDir: input.homeDir === undefined ? resolveHomeDir() : input.homeDir,
|
|
232
245
|
secrets: [
|
|
233
|
-
...
|
|
234
|
-
...runnerForwardedSecretValues(),
|
|
246
|
+
...errorOutputSecrets(),
|
|
235
247
|
...(input.secrets ?? []),
|
|
236
248
|
],
|
|
237
249
|
});
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
export interface LoginFlowDependencies {
|
|
2
|
+
parseJsonResponse: <T>(response: Response, context: string) => Promise<T>;
|
|
3
|
+
printProgress: (message: string) => void;
|
|
4
|
+
sanitizeTerminalText: (text: string) => string;
|
|
5
|
+
validateBrowserUrl: (url: string, expectedOrigin?: string) => URL;
|
|
6
|
+
sleep?: (milliseconds: number) => Promise<void>;
|
|
7
|
+
}
|
|
8
|
+
export interface CompletedLogin {
|
|
9
|
+
apiKey: string;
|
|
10
|
+
user: {
|
|
11
|
+
id: string;
|
|
12
|
+
email: string | null;
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
export declare function shouldUseHeadlessLogin({ isForced, platform, environment, }: {
|
|
16
|
+
isForced: boolean;
|
|
17
|
+
platform?: NodeJS.Platform;
|
|
18
|
+
environment?: Record<string, string | undefined>;
|
|
19
|
+
}): boolean;
|
|
20
|
+
export declare const POLL_INTERVAL_MS = 2000;
|
|
21
|
+
/** For tests: the headless wait alone, returning the authorization code. */
|
|
22
|
+
export declare function waitForHeadlessAuthorization(input: {
|
|
23
|
+
baseUrl: string;
|
|
24
|
+
codeChallenge: string;
|
|
25
|
+
}, dependencies: LoginFlowDependencies, signal?: AbortSignal): Promise<string>;
|
|
26
|
+
/**
|
|
27
|
+
* Waits for the person to approve the login (in the browser, or by polling
|
|
28
|
+
* when headless), then exchanges the code. `callbackPort` undefined means
|
|
29
|
+
* headless. `signal` stops it, closing the loopback server.
|
|
30
|
+
*/
|
|
31
|
+
export declare function completeLogin(input: {
|
|
32
|
+
baseUrl: string;
|
|
33
|
+
codeVerifier: string;
|
|
34
|
+
codeChallenge: string;
|
|
35
|
+
callbackPort?: number;
|
|
36
|
+
}, dependencies: LoginFlowDependencies, signal?: AbortSignal): Promise<CompletedLogin>;
|
|
37
|
+
//# sourceMappingURL=login-flow.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"login-flow.d.ts","sourceRoot":"","sources":["../src/login-flow.ts"],"names":[],"mappings":"AAcA,MAAM,WAAW,qBAAqB;IACpC,iBAAiB,EAAE,CAAC,CAAC,EAAE,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,CAAC,CAAC,CAAA;IACzE,aAAa,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAA;IACxC,oBAAoB,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAA;IAC9C,kBAAkB,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,cAAc,CAAC,EAAE,MAAM,KAAK,GAAG,CAAA;IACjE,KAAK,CAAC,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;CAChD;AAED,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,MAAM,CAAA;IACd,IAAI,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,CAAA;CAC3C;AAED,wBAAgB,sBAAsB,CAAC,EACrC,QAAQ,EACR,QAA2B,EAC3B,WAAyB,GAC1B,EAAE;IACD,QAAQ,EAAE,OAAO,CAAA;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC,QAAQ,CAAA;IAC1B,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAA;CACjD,GAAG,OAAO,CAMV;AA2ID,eAAO,MAAM,gBAAgB,OAAQ,CAAA;AA2JrC,4EAA4E;AAC5E,wBAAgB,4BAA4B,CAC1C,KAAK,EAAE;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,aAAa,EAAE,MAAM,CAAA;CAAE,EACjD,YAAY,EAAE,qBAAqB,EACnC,MAAM,CAAC,EAAE,WAAW,GACnB,OAAO,CAAC,MAAM,CAAC,CAEjB;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAC3B,KAAK,EAAE;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,CAAC;IAAC,aAAa,EAAE,MAAM,CAAC;IAAC,YAAY,CAAC,EAAE,MAAM,CAAA;CAAE,EAC9F,YAAY,EAAE,qBAAqB,EACnC,MAAM,CAAC,EAAE,WAAW,GACnB,OAAO,CAAC,cAAc,CAAC,CAOzB"}
|