@stage5/lumine 0.2.53 → 0.2.55
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/README.md +66 -5
- package/lib/admin-workflows.js +759 -59
- package/lib/admin.js +268 -4
- package/lib/agent/providers/claude-code.js +104 -3
- package/lib/agent/providers/codex.js +118 -14
- package/lib/agent.js +9 -1
- package/lib/auth.js +15 -9
- package/lib/commands.js +76 -28
- package/lib/constants.js +1 -0
- package/lib/sponsor.js +1292 -0
- package/package.json +1 -1
- package/sdk/LUMINE_ADMIN.md +43 -6
|
@@ -77,7 +77,10 @@ export async function runCodexAgentPass({
|
|
|
77
77
|
tools: runtime.tools,
|
|
78
78
|
toolSession,
|
|
79
79
|
});
|
|
80
|
-
return {
|
|
80
|
+
return {
|
|
81
|
+
finalText: result.finalText,
|
|
82
|
+
provenance: result.provenance,
|
|
83
|
+
};
|
|
81
84
|
}
|
|
82
85
|
|
|
83
86
|
export async function reviewCodexAgentLoop({
|
|
@@ -120,6 +123,7 @@ async function runCodexAppServerTurn({
|
|
|
120
123
|
binary,
|
|
121
124
|
cwd: isolationDir,
|
|
122
125
|
environment: providerEnvironment,
|
|
126
|
+
signal: options.agentAbortSignal,
|
|
123
127
|
});
|
|
124
128
|
} catch (error) {
|
|
125
129
|
throw normalizeProviderLaunchError(error, binary, "Codex");
|
|
@@ -128,12 +132,22 @@ async function runCodexAppServerTurn({
|
|
|
128
132
|
cwd: isolationDir,
|
|
129
133
|
stdio: ["pipe", "pipe", "pipe"],
|
|
130
134
|
env: providerEnvironment,
|
|
135
|
+
...(options.agentAbortSignal ? { signal: options.agentAbortSignal } : {}),
|
|
131
136
|
});
|
|
132
137
|
child.stderr.on("data", (chunk) => process.stderr.write(chunk));
|
|
138
|
+
let childInputError = null;
|
|
139
|
+
child.stdin.on("error", (error) => {
|
|
140
|
+
childInputError ||= error;
|
|
141
|
+
});
|
|
133
142
|
|
|
134
143
|
let nextRequestId = 1;
|
|
135
144
|
const pendingRequests = new Map();
|
|
136
145
|
let completedTurn = null;
|
|
146
|
+
let initializedServer = null;
|
|
147
|
+
let startedThreadResult = null;
|
|
148
|
+
let latestThreadSettings = null;
|
|
149
|
+
let latestTokenUsage = null;
|
|
150
|
+
let reroutedModel = null;
|
|
137
151
|
let completedTurnResolve;
|
|
138
152
|
const completedTurnPromise = new Promise((resolve) => {
|
|
139
153
|
completedTurnResolve = resolve;
|
|
@@ -143,10 +157,19 @@ async function runCodexAppServerTurn({
|
|
|
143
157
|
const inheritedMcpServers = new Set();
|
|
144
158
|
|
|
145
159
|
function send(message) {
|
|
160
|
+
if (childInputError || child.stdin.destroyed || child.stdin.writableEnded) {
|
|
161
|
+
return false;
|
|
162
|
+
}
|
|
146
163
|
// App-server uses JSON-RPC semantics but intentionally omits the jsonrpc
|
|
147
164
|
// header on its JSONL wire format.
|
|
148
165
|
const { jsonrpc: _jsonrpc, ...wireMessage } = message;
|
|
149
|
-
|
|
166
|
+
try {
|
|
167
|
+
child.stdin.write(`${JSON.stringify(wireMessage)}\n`);
|
|
168
|
+
return true;
|
|
169
|
+
} catch (error) {
|
|
170
|
+
childInputError ||= error;
|
|
171
|
+
return false;
|
|
172
|
+
}
|
|
150
173
|
}
|
|
151
174
|
|
|
152
175
|
function request(method, params) {
|
|
@@ -154,7 +177,10 @@ async function runCodexAppServerTurn({
|
|
|
154
177
|
nextRequestId += 1;
|
|
155
178
|
return new Promise((resolve, reject) => {
|
|
156
179
|
pendingRequests.set(id, { resolve, reject });
|
|
157
|
-
send({ jsonrpc: "2.0", id, method, params })
|
|
180
|
+
if (!send({ jsonrpc: "2.0", id, method, params })) {
|
|
181
|
+
pendingRequests.delete(id);
|
|
182
|
+
reject(new Error("Codex app-server input closed."));
|
|
183
|
+
}
|
|
158
184
|
});
|
|
159
185
|
}
|
|
160
186
|
|
|
@@ -199,9 +225,7 @@ async function runCodexAppServerTurn({
|
|
|
199
225
|
jsonrpc: "2.0",
|
|
200
226
|
id: message.id,
|
|
201
227
|
result: {
|
|
202
|
-
contentItems: [
|
|
203
|
-
{ type: "inputText", text: JSON.stringify(output) },
|
|
204
|
-
],
|
|
228
|
+
contentItems: [{ type: "inputText", text: JSON.stringify(output) }],
|
|
205
229
|
success,
|
|
206
230
|
},
|
|
207
231
|
});
|
|
@@ -269,6 +293,18 @@ async function runCodexAppServerTurn({
|
|
|
269
293
|
}
|
|
270
294
|
return;
|
|
271
295
|
}
|
|
296
|
+
if (message.method === "thread/settings/updated") {
|
|
297
|
+
latestThreadSettings = message.params?.threadSettings || null;
|
|
298
|
+
return;
|
|
299
|
+
}
|
|
300
|
+
if (message.method === "thread/tokenUsage/updated") {
|
|
301
|
+
latestTokenUsage = message.params?.tokenUsage || null;
|
|
302
|
+
return;
|
|
303
|
+
}
|
|
304
|
+
if (message.method === "model/rerouted") {
|
|
305
|
+
reroutedModel = firstNonEmptyString(message.params?.toModel);
|
|
306
|
+
return;
|
|
307
|
+
}
|
|
272
308
|
if (
|
|
273
309
|
message.method === "item/completed" &&
|
|
274
310
|
message.params?.item?.type === "agentMessage"
|
|
@@ -296,7 +332,7 @@ async function runCodexAppServerTurn({
|
|
|
296
332
|
});
|
|
297
333
|
|
|
298
334
|
try {
|
|
299
|
-
await Promise.race([
|
|
335
|
+
initializedServer = await Promise.race([
|
|
300
336
|
request("initialize", {
|
|
301
337
|
clientInfo: {
|
|
302
338
|
name: "lumine-cli",
|
|
@@ -312,6 +348,7 @@ async function runCodexAppServerTurn({
|
|
|
312
348
|
send({ jsonrpc: "2.0", method: "initialized", params: {} });
|
|
313
349
|
const threadResult = await request("thread/start", {
|
|
314
350
|
...(options.model ? { model: options.model } : {}),
|
|
351
|
+
...(options.serviceTier ? { serviceTier: options.serviceTier } : {}),
|
|
315
352
|
cwd: isolationDir,
|
|
316
353
|
approvalPolicy: "never",
|
|
317
354
|
sandbox: "read-only",
|
|
@@ -322,6 +359,7 @@ async function runCodexAppServerTurn({
|
|
|
322
359
|
developerInstructions,
|
|
323
360
|
dynamicTools: toCodexDynamicTools(tools),
|
|
324
361
|
});
|
|
362
|
+
startedThreadResult = threadResult || null;
|
|
325
363
|
const threadId = String(threadResult?.thread?.id || "");
|
|
326
364
|
if (!threadId) throw new Error("Codex did not return a thread ID.");
|
|
327
365
|
await delay(250);
|
|
@@ -330,9 +368,8 @@ async function runCodexAppServerTurn({
|
|
|
330
368
|
detail: "toolsAndAuthOnly",
|
|
331
369
|
limit: 100,
|
|
332
370
|
});
|
|
333
|
-
const inheritedToolServers = (
|
|
334
|
-
? mcpInventory.data
|
|
335
|
-
: []
|
|
371
|
+
const inheritedToolServers = (
|
|
372
|
+
Array.isArray(mcpInventory?.data) ? mcpInventory.data : []
|
|
336
373
|
)
|
|
337
374
|
.filter((server) => Object.keys(server?.tools || {}).length > 0)
|
|
338
375
|
.map((server) => String(server?.name || "").trim())
|
|
@@ -364,7 +401,44 @@ async function runCodexAppServerTurn({
|
|
|
364
401
|
}
|
|
365
402
|
const finalText =
|
|
366
403
|
completedMessages.at(-1) || String(deltaText || "").trim();
|
|
367
|
-
|
|
404
|
+
const resolvedModel = firstNonEmptyString(
|
|
405
|
+
reroutedModel,
|
|
406
|
+
latestThreadSettings?.model,
|
|
407
|
+
startedThreadResult?.model,
|
|
408
|
+
startedThreadResult?.thread?.model,
|
|
409
|
+
);
|
|
410
|
+
const resolvedEffort = firstNonEmptyString(
|
|
411
|
+
latestThreadSettings?.effort,
|
|
412
|
+
startedThreadResult?.reasoningEffort,
|
|
413
|
+
startedThreadResult?.thread?.effort,
|
|
414
|
+
startedThreadResult?.thread?.reasoningEffort,
|
|
415
|
+
);
|
|
416
|
+
const resolvedServiceTier = firstNonEmptyString(
|
|
417
|
+
latestThreadSettings?.serviceTier,
|
|
418
|
+
startedThreadResult?.serviceTier,
|
|
419
|
+
startedThreadResult?.thread?.serviceTier,
|
|
420
|
+
startedThreadResult?.thread?.service_tier,
|
|
421
|
+
);
|
|
422
|
+
return {
|
|
423
|
+
finalText,
|
|
424
|
+
provenance: {
|
|
425
|
+
resolvedModel,
|
|
426
|
+
resolvedEffort,
|
|
427
|
+
resolvedServiceTier,
|
|
428
|
+
runtimeVersion: firstNonEmptyString(
|
|
429
|
+
initializedServer?.userAgent,
|
|
430
|
+
initializedServer?.serverInfo?.version,
|
|
431
|
+
initializedServer?.server_info?.version,
|
|
432
|
+
),
|
|
433
|
+
evidenceTier:
|
|
434
|
+
resolvedModel || resolvedEffort || resolvedServiceTier
|
|
435
|
+
? "runtime_observed"
|
|
436
|
+
: "requested_only",
|
|
437
|
+
usage: normalizeUsageEvidence(
|
|
438
|
+
latestTokenUsage?.last || latestTokenUsage?.total || turn?.usage,
|
|
439
|
+
),
|
|
440
|
+
},
|
|
441
|
+
};
|
|
368
442
|
} catch (error) {
|
|
369
443
|
throw normalizeProviderLaunchError(error, binary, "Codex");
|
|
370
444
|
} finally {
|
|
@@ -378,13 +452,33 @@ async function runCodexAppServerTurn({
|
|
|
378
452
|
}
|
|
379
453
|
}
|
|
380
454
|
|
|
381
|
-
|
|
455
|
+
function firstNonEmptyString(...values) {
|
|
456
|
+
for (const value of values) {
|
|
457
|
+
const normalized = String(value || "").trim();
|
|
458
|
+
if (normalized) return normalized.slice(0, 160);
|
|
459
|
+
}
|
|
460
|
+
return null;
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
function normalizeUsageEvidence(value) {
|
|
464
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return {};
|
|
465
|
+
return Object.fromEntries(
|
|
466
|
+
Object.entries(value)
|
|
467
|
+
.filter(([, amount]) =>
|
|
468
|
+
["number", "string", "boolean"].includes(typeof amount),
|
|
469
|
+
)
|
|
470
|
+
.slice(0, 30),
|
|
471
|
+
);
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
async function loadCodexIsolationArgs({ binary, cwd, environment, signal }) {
|
|
382
475
|
const [featureOutput, mcpOutput] = await Promise.all([
|
|
383
476
|
runCodexInspectionCommand({
|
|
384
477
|
binary,
|
|
385
478
|
args: ["features", "list"],
|
|
386
479
|
cwd,
|
|
387
480
|
environment,
|
|
481
|
+
signal,
|
|
388
482
|
label: "feature inventory",
|
|
389
483
|
}),
|
|
390
484
|
runCodexInspectionCommand({
|
|
@@ -392,13 +486,19 @@ async function loadCodexIsolationArgs({ binary, cwd, environment }) {
|
|
|
392
486
|
args: ["mcp", "list", "--json"],
|
|
393
487
|
cwd,
|
|
394
488
|
environment,
|
|
489
|
+
signal,
|
|
395
490
|
label: "MCP inventory",
|
|
396
491
|
}),
|
|
397
492
|
]);
|
|
398
493
|
const availableFeatures = new Set(
|
|
399
494
|
featureOutput
|
|
400
495
|
.split("\n")
|
|
401
|
-
.map(
|
|
496
|
+
.map(
|
|
497
|
+
(line) =>
|
|
498
|
+
String(line || "")
|
|
499
|
+
.trim()
|
|
500
|
+
.split(/\s+/)[0],
|
|
501
|
+
)
|
|
402
502
|
.filter((name) => /^[a-z][a-z0-9_]*$/.test(name)),
|
|
403
503
|
);
|
|
404
504
|
let mcpServers;
|
|
@@ -437,6 +537,7 @@ async function runCodexInspectionCommand({
|
|
|
437
537
|
args,
|
|
438
538
|
cwd,
|
|
439
539
|
environment,
|
|
540
|
+
signal,
|
|
440
541
|
label,
|
|
441
542
|
}) {
|
|
442
543
|
return await new Promise((resolve, reject) => {
|
|
@@ -444,13 +545,16 @@ async function runCodexInspectionCommand({
|
|
|
444
545
|
cwd,
|
|
445
546
|
stdio: ["ignore", "pipe", "pipe"],
|
|
446
547
|
env: environment,
|
|
548
|
+
...(signal ? { signal } : {}),
|
|
447
549
|
});
|
|
448
550
|
let stdout = "";
|
|
449
551
|
let settled = false;
|
|
450
552
|
const timeout = setTimeout(() => {
|
|
451
553
|
child.kill();
|
|
452
554
|
finish(
|
|
453
|
-
new Error(
|
|
555
|
+
new Error(
|
|
556
|
+
`Codex ${label} timed out; Lumine cannot prove tool isolation.`,
|
|
557
|
+
),
|
|
454
558
|
);
|
|
455
559
|
}, CODEX_PREFLIGHT_TIMEOUT_MS);
|
|
456
560
|
const finish = (error, value = "") => {
|
package/lib/agent.js
CHANGED
|
@@ -112,6 +112,8 @@ export async function agentCommand(options, { saveWorkspace }) {
|
|
|
112
112
|
let currentFiles = workspace.files;
|
|
113
113
|
let scopeBaseFiles = workspace.files;
|
|
114
114
|
let finalText = "";
|
|
115
|
+
const providerRuns = [];
|
|
116
|
+
let saveResult = null;
|
|
115
117
|
let scopeRepairAttempts = 0;
|
|
116
118
|
let validationRepairAttempts = 0;
|
|
117
119
|
|
|
@@ -160,6 +162,10 @@ export async function agentCommand(options, { saveWorkspace }) {
|
|
|
160
162
|
},
|
|
161
163
|
});
|
|
162
164
|
finalText = String(providerResult?.finalText || "").trim() || finalText;
|
|
165
|
+
providerRuns.push({
|
|
166
|
+
phase: runtime.phase,
|
|
167
|
+
...(providerResult?.provenance || {}),
|
|
168
|
+
});
|
|
163
169
|
await appendAgentTrace(artifacts.traceFile, {
|
|
164
170
|
type: "provider_completed",
|
|
165
171
|
provider: provider.id,
|
|
@@ -257,7 +263,7 @@ export async function agentCommand(options, { saveWorkspace }) {
|
|
|
257
263
|
|
|
258
264
|
const changedPaths = listChangedPaths(workspace.files, currentFiles);
|
|
259
265
|
if (changedPaths.length > 0) {
|
|
260
|
-
await saveWorkspace({
|
|
266
|
+
saveResult = await saveWorkspace({
|
|
261
267
|
...options,
|
|
262
268
|
dir: workspace.dir,
|
|
263
269
|
publish: false,
|
|
@@ -304,6 +310,8 @@ export async function agentCommand(options, { saveWorkspace }) {
|
|
|
304
310
|
finalText,
|
|
305
311
|
traceFile: artifacts.traceFile,
|
|
306
312
|
feedbackFile: feedback ? artifacts.feedbackFile : null,
|
|
313
|
+
saveResult,
|
|
314
|
+
providerRuns,
|
|
307
315
|
};
|
|
308
316
|
} catch (error) {
|
|
309
317
|
await appendAgentTrace(artifacts.traceFile, {
|
package/lib/auth.js
CHANGED
|
@@ -6,6 +6,9 @@ import { requestJson } from "./http.js";
|
|
|
6
6
|
import { sleep, trimTrailingSlash } from "./util.js";
|
|
7
7
|
|
|
8
8
|
export async function login(options) {
|
|
9
|
+
const report = options.loginProgressToStderr
|
|
10
|
+
? (...args) => console.error(...args)
|
|
11
|
+
: (...args) => console.log(...args);
|
|
9
12
|
const start = await requestJson({
|
|
10
13
|
method: "POST",
|
|
11
14
|
url: `${options.apiUrl}/cli/device/start`,
|
|
@@ -23,15 +26,15 @@ export async function login(options) {
|
|
|
23
26
|
});
|
|
24
27
|
|
|
25
28
|
const approvalUrl = start.verificationUriComplete || start.verificationUri;
|
|
26
|
-
|
|
29
|
+
report("Connect Lumine CLI to Twinkle.");
|
|
27
30
|
if (options.openBrowser && approvalUrl) {
|
|
28
|
-
|
|
31
|
+
report("Opening Twinkle in your browser...");
|
|
29
32
|
const opened = await openBrowser(approvalUrl);
|
|
30
|
-
if (!opened)
|
|
33
|
+
if (!opened) report("Could not open the browser automatically.");
|
|
31
34
|
}
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
+
report(`Approval link: ${approvalUrl}`);
|
|
36
|
+
report(`Code: ${start.userCode}`);
|
|
37
|
+
report("Leave this terminal open. Waiting for approval...");
|
|
35
38
|
|
|
36
39
|
const intervalMs = Math.max(Number(start.interval || 3), 1) * 1000;
|
|
37
40
|
const startedAt = Date.now();
|
|
@@ -52,10 +55,10 @@ export async function login(options) {
|
|
|
52
55
|
userId: tokenResponse.user?.id || null,
|
|
53
56
|
expiresAt: Date.now() + Number(tokenResponse.expiresIn || 0) * 1000,
|
|
54
57
|
});
|
|
55
|
-
|
|
58
|
+
report(
|
|
56
59
|
`Logged in${tokenResponse.user?.username ? ` as ${tokenResponse.user.username}` : ""}.`,
|
|
57
60
|
);
|
|
58
|
-
|
|
61
|
+
report("You can now run `lumine` to choose a project.");
|
|
59
62
|
return;
|
|
60
63
|
}
|
|
61
64
|
|
|
@@ -112,7 +115,10 @@ export async function ensureAuth(options) {
|
|
|
112
115
|
} catch (error) {
|
|
113
116
|
if (options.authToken || !isMissingLoginError(error)) throw error;
|
|
114
117
|
}
|
|
115
|
-
await login(
|
|
118
|
+
await login({
|
|
119
|
+
...options,
|
|
120
|
+
loginProgressToStderr: Boolean(options.json),
|
|
121
|
+
});
|
|
116
122
|
return await resolveAuth(options);
|
|
117
123
|
}
|
|
118
124
|
|
package/lib/commands.js
CHANGED
|
@@ -67,6 +67,7 @@ import { runBuildForumCommand } from "./forum.js";
|
|
|
67
67
|
import { agentCommand } from "./agent.js";
|
|
68
68
|
import { agentMcpCommand } from "./agent/mcp-server.js";
|
|
69
69
|
import { appMcpCommand } from "./app-mcp/server.js";
|
|
70
|
+
import { sponsorCommand } from "./sponsor.js";
|
|
70
71
|
import {
|
|
71
72
|
defaultMainCheckoutDir,
|
|
72
73
|
defaultReferenceDir,
|
|
@@ -130,6 +131,14 @@ export async function main() {
|
|
|
130
131
|
return;
|
|
131
132
|
}
|
|
132
133
|
|
|
134
|
+
if (options.command === "sponsor") {
|
|
135
|
+
await sponsorCommand(options, {
|
|
136
|
+
saveWorkspace: save,
|
|
137
|
+
pullWorkspace: pullBuildFiles,
|
|
138
|
+
});
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
|
|
133
142
|
if (options.command === "agent") {
|
|
134
143
|
await agentCommand(options, { saveWorkspace: save });
|
|
135
144
|
return;
|
|
@@ -1122,7 +1131,7 @@ export async function save(options) {
|
|
|
1122
1131
|
console.log(
|
|
1123
1132
|
"Saved to your branch. The project owner can merge or replace main from Twinkle.",
|
|
1124
1133
|
);
|
|
1125
|
-
return;
|
|
1134
|
+
return result;
|
|
1126
1135
|
}
|
|
1127
1136
|
const publish = await publishBuild({ options, buildId, auth });
|
|
1128
1137
|
if (publish.skipped) {
|
|
@@ -1135,6 +1144,7 @@ export async function save(options) {
|
|
|
1135
1144
|
);
|
|
1136
1145
|
console.log(`App: ${options.siteUrl}/app/${buildId}`);
|
|
1137
1146
|
}
|
|
1147
|
+
return result;
|
|
1138
1148
|
}
|
|
1139
1149
|
|
|
1140
1150
|
export async function check(options) {
|
|
@@ -1502,32 +1512,34 @@ export async function pullBuildFiles({ options, auth, buildId }) {
|
|
|
1502
1512
|
// exists (the workspace UI gives Lumine the same context). Never fail the
|
|
1503
1513
|
// pull over it.
|
|
1504
1514
|
let assetCount = null;
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
|
|
1515
|
+
if (!options.skipAssetManifest) {
|
|
1516
|
+
try {
|
|
1517
|
+
const { token } = await mintBuildApiToken({
|
|
1518
|
+
options,
|
|
1519
|
+
auth,
|
|
1520
|
+
buildId: Number(build.id || buildId),
|
|
1521
|
+
scopes: ["files:read"],
|
|
1522
|
+
});
|
|
1523
|
+
const { assets, usage, projectAssets } = await fetchAllRuntimeAssets({
|
|
1524
|
+
options,
|
|
1525
|
+
auth,
|
|
1526
|
+
buildId: Number(build.id || buildId),
|
|
1527
|
+
buildApiToken: token,
|
|
1528
|
+
});
|
|
1529
|
+
await writeAssetsManifest({
|
|
1530
|
+
dir,
|
|
1531
|
+
buildId: Number(build.id || buildId),
|
|
1532
|
+
assets,
|
|
1533
|
+
usage,
|
|
1534
|
+
projectAssets,
|
|
1535
|
+
codeFiles: files,
|
|
1536
|
+
});
|
|
1537
|
+
assetCount = assets.length + (projectAssets?.length || 0);
|
|
1538
|
+
} catch (error) {
|
|
1539
|
+
console.error(
|
|
1540
|
+
`lumine: skipped ${ASSETS_METADATA_FILE} (${error?.message || error})`,
|
|
1541
|
+
);
|
|
1542
|
+
}
|
|
1531
1543
|
}
|
|
1532
1544
|
return {
|
|
1533
1545
|
build,
|
|
@@ -2249,6 +2261,7 @@ export function parseArgs(args) {
|
|
|
2249
2261
|
"includeLegacy",
|
|
2250
2262
|
"includePrivateEvidence",
|
|
2251
2263
|
"noReviewLoop",
|
|
2264
|
+
"acceptAgreement",
|
|
2252
2265
|
]);
|
|
2253
2266
|
|
|
2254
2267
|
for (let i = 0; i < rest.length; i += 1) {
|
|
@@ -2366,10 +2379,33 @@ export function parseArgs(args) {
|
|
|
2366
2379
|
adminReviewContext: raw.reviewContext ? String(raw.reviewContext) : "",
|
|
2367
2380
|
adminSeverity: raw.severity ? String(raw.severity) : "",
|
|
2368
2381
|
adminStatus: raw.status ? String(raw.status) : "",
|
|
2382
|
+
adminDecision: raw.decision ? String(raw.decision) : "",
|
|
2369
2383
|
adminWaitMs: raw.waitMs ? String(raw.waitMs) : "",
|
|
2370
2384
|
adminBrowserPath: raw.browserPath ? String(raw.browserPath) : "",
|
|
2371
2385
|
adminEffort: raw.effort ? String(raw.effort) : "",
|
|
2372
2386
|
agentEffort: command === "agent" && raw.effort ? String(raw.effort) : "",
|
|
2387
|
+
sponsorArgs: command === "sponsor" ? positional : [],
|
|
2388
|
+
sponsorMotivation: raw.motivation ? String(raw.motivation) : "",
|
|
2389
|
+
sponsorAvailability: raw.availability ? String(raw.availability) : "",
|
|
2390
|
+
sponsorProviders: raw.providers
|
|
2391
|
+
? String(raw.providers)
|
|
2392
|
+
: raw.provider
|
|
2393
|
+
? String(raw.provider)
|
|
2394
|
+
: "",
|
|
2395
|
+
sponsorCapabilityNotes: raw.capabilityNotes
|
|
2396
|
+
? String(raw.capabilityNotes)
|
|
2397
|
+
: "",
|
|
2398
|
+
sponsorAcceptAgreement: Boolean(raw.acceptAgreement),
|
|
2399
|
+
sponsorPersona: raw.persona ? String(raw.persona) : "",
|
|
2400
|
+
sponsorConcurrency: raw.concurrency,
|
|
2401
|
+
sponsorHelpers: raw.helpers,
|
|
2402
|
+
sponsorDailyLimit: raw.dailyLimit,
|
|
2403
|
+
sponsorWeeklyLimit: raw.weeklyLimit,
|
|
2404
|
+
sponsorEffort: raw.effort ? String(raw.effort) : "",
|
|
2405
|
+
sponsorServiceTier: raw.serviceTier ? String(raw.serviceTier) : "",
|
|
2406
|
+
sponsorPollMs: raw.pollMs
|
|
2407
|
+
? Math.min(Math.max(Number(raw.pollMs) || 0, 1_000), 60_000)
|
|
2408
|
+
: 3_000,
|
|
2373
2409
|
provider: raw.provider ? String(raw.provider) : "",
|
|
2374
2410
|
providerPath: raw.providerPath ? String(raw.providerPath) : "",
|
|
2375
2411
|
agentPrompt:
|
|
@@ -2692,6 +2728,11 @@ export function printHelp() {
|
|
|
2692
2728
|
lumine whoami
|
|
2693
2729
|
lumine logout
|
|
2694
2730
|
lumine agent --provider <codex|claude-code> "<build request>"
|
|
2731
|
+
lumine sponsor agreement|apply|status|withdraw
|
|
2732
|
+
lumine sponsor capacity [--concurrency <n>] [--helpers <n>] [--daily-limit <n>] [--weekly-limit <n>]
|
|
2733
|
+
lumine sponsor duty start <zero|ciel> --provider <codex|claude-code> [--model <name>] [--effort <level>] [--service-tier <tier>]
|
|
2734
|
+
lumine sponsor duty pause|resume|stop <zero|ciel>
|
|
2735
|
+
lumine sponsor jobs
|
|
2695
2736
|
lumine app-mcp <published-app-url-or-id> [--no-open]
|
|
2696
2737
|
lumine new [title]
|
|
2697
2738
|
lumine rename [title] [--target <twinkle-build-url-or-id>]
|
|
@@ -2750,6 +2791,13 @@ export function printHelp() {
|
|
|
2750
2791
|
lumine admin todo list [--status pending|open|in_progress|blocked|completed|cancelled|all] [--limit <number>] [--json]
|
|
2751
2792
|
lumine admin todo add --title <title> --note <handoff-and-acceptance-criteria> [--kind task|experiment] [--status open|in_progress|blocked] [--json]
|
|
2752
2793
|
lumine admin todo update <todo-id> --status open|in_progress|blocked|completed|cancelled --note <progress-or-evidence> [--json]
|
|
2794
|
+
lumine admin sponsor applications list [--status pending|approved|rejected|withdrawn] [--json]
|
|
2795
|
+
lumine admin sponsor applications review <application-id> --decision approve|reject [--note <text>] [--json]
|
|
2796
|
+
lumine admin sponsor status set <user-id> --status probationary|trusted|suspended|revoked [--note <text>] [--json]
|
|
2797
|
+
lumine admin sponsor integrity status|scan [--json]
|
|
2798
|
+
lumine admin sponsor integrity cases [--status open|pending|held|flagged|cleared|disqualified] [--json]
|
|
2799
|
+
lumine admin sponsor integrity get <case-id> [--json]
|
|
2800
|
+
lumine admin sponsor integrity review <case-id> --decision clear|hold|flag|disqualify [--note <evidence>] [--json]
|
|
2753
2801
|
lumine admin recommendations list [--since-run|--after <date>|--include-legacy] [--all --checkpoint <file> [--resume]] [--content-types comment,dailyReflection] [--unviewed|--viewed] [--cursor <cursor>] [--json]
|
|
2754
2802
|
lumine admin builds candidates [--all --checkpoint <file> [--resume]] [--cursor <cursor>] [--limit <number>] [--json]
|
|
2755
2803
|
lumine admin builds review <build-url-or-id> [--output-dir <dir>] [--wait-ms <ms>] [--browser-path <path>] [--json]
|
|
@@ -2859,7 +2907,7 @@ Options:
|
|
|
2859
2907
|
--since-run Recommendations since the previous completed run (default)
|
|
2860
2908
|
--include-legacy Explicitly include the full historical recommendation queue
|
|
2861
2909
|
--all Automatically read every page in the canonical snapshot
|
|
2862
|
-
--checkpoint <file> Persist
|
|
2910
|
+
--checkpoint <file> Persist bounded pagination metadata or batch progress
|
|
2863
2911
|
--resume Resume the exact request recorded by --checkpoint
|
|
2864
2912
|
--output <file> Save an admin result or newspaper claim as JSON
|
|
2865
2913
|
--output-dir <dir> Directory for managed Build review evidence
|