@chanlerdev/scorel 0.0.7 → 0.0.8
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/index.js +450 -11
- package/dist/index.js.map +3 -3
- package/docs/CHANGELOG.md +26 -0
- package/docs/ROADMAP.md +1 -0
- package/docs/spec/ship/S0109-scorel-run-headless-task-runner.md +172 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -5566,20 +5566,22 @@ var init_src4 = __esm({
|
|
|
5566
5566
|
}
|
|
5567
5567
|
async #handleLoadSession(connection, request) {
|
|
5568
5568
|
try {
|
|
5569
|
-
const lane =
|
|
5569
|
+
const lane = this.#sessions.get(request.sessionId);
|
|
5570
|
+
const session = lane?.session ?? await loadSession({ sessionsDir: this.#sessionsDir, sessionId: request.sessionId });
|
|
5570
5571
|
await this.#appendDiagnostic(request.sessionId, "session_loaded", { clientId: connection.clientId });
|
|
5571
5572
|
connection.sessionId = request.sessionId;
|
|
5572
|
-
const persistentEvents = [...
|
|
5573
|
+
const persistentEvents = [...session.tree];
|
|
5573
5574
|
const sessionEvents = this.#events.get(request.sessionId) ?? [];
|
|
5574
5575
|
if (sessionEvents.length === 0 && persistentEvents.length > 0) {
|
|
5575
5576
|
this.#events.set(request.sessionId, persistentEvents);
|
|
5576
5577
|
}
|
|
5578
|
+
this.#seqs.set(request.sessionId, Number(session.currentSeq));
|
|
5577
5579
|
this.#respond(connection, request, {
|
|
5578
5580
|
sessionId: request.sessionId,
|
|
5579
|
-
activeLeafId:
|
|
5580
|
-
currentSeq:
|
|
5581
|
+
activeLeafId: session.activeLeafId,
|
|
5582
|
+
currentSeq: session.currentSeq,
|
|
5581
5583
|
events: persistentEvents,
|
|
5582
|
-
meta:
|
|
5584
|
+
meta: session.header.meta
|
|
5583
5585
|
});
|
|
5584
5586
|
} catch (cause) {
|
|
5585
5587
|
connection.emit({
|
|
@@ -9814,7 +9816,7 @@ import { createInterface } from "node:readline/promises";
|
|
|
9814
9816
|
import { homedir as homedir9 } from "node:os";
|
|
9815
9817
|
import { fileURLToPath as fileURLToPath5 } from "node:url";
|
|
9816
9818
|
import { basename as basename4, dirname as dirname13, join as join17 } from "node:path";
|
|
9817
|
-
var cliAppName, cliClientDependency, cliDaemonDependency, defaultSessionsDir, defaultStateDir4, runCli, runProject, runLogs, runAttach, attachCacheScope, attachCacheFilePath, attachDiagnosticsFilePath, findAttachDiagnosticsFilePath, stateDirFromSessionsDir, AttachDiagnostics, readAttachCache, writeAttachCache, emptyAttachCacheSnapshot, mergePersistentEvents, highestSeq, highestCachedStreamSeq, updateAttachCacheSnapshot, removeCompletedTransients, isCachedTransientMessage, AsyncInputQueue, parseAttachOptions, parseLogsOptions, runChat, createSigintHandler, loadOrCreateSession, parseChatOptions, requireValue6, promptIfInteractive, writeUsage, writeProjectUsage, writeEventError, writeToolResult, redactDiagnosticFields, formatDiagnosticLine2, formatDiagnosticValue2, AttachEventRenderer, blocksToText, isCliEntrypoint;
|
|
9819
|
+
var cliAppName, cliClientDependency, cliDaemonDependency, defaultSessionsDir, defaultStateDir4, runCli, runProject, runLogs, runAttach, attachCacheScope, attachCacheFilePath, attachDiagnosticsFilePath, findAttachDiagnosticsFilePath, stateDirFromSessionsDir, AttachDiagnostics, readAttachCache, writeAttachCache, emptyAttachCacheSnapshot, mergePersistentEvents, highestSeq, highestCachedStreamSeq, updateAttachCacheSnapshot, removeCompletedTransients, isCachedTransientMessage, AsyncInputQueue, parseAttachOptions, parseLogsOptions, runChat, runHeadless, renderRunEvent, renderRunFinal, writeJsonLine, RunTimeoutError, withRunTimeout, makeRunSummary, writeRunSummary, readRunPrompt, resolveRunConfig, stripTrailingSlashes2, createSigintHandler, loadOrCreateSession, parseChatOptions, parseRunOptions, parseRunOutputFormat, parsePositiveInteger, parseModelSelection, parseRunProviderApi, requireValue6, promptIfInteractive, writeUsage, writeRunUsage, writeProjectUsage, writeEventError, writeToolResult, redactDiagnosticFields, formatDiagnosticLine2, formatDiagnosticValue2, AttachEventRenderer, blocksToText, isCliEntrypoint;
|
|
9818
9820
|
var init_index = __esm({
|
|
9819
9821
|
async "apps/cli/src/index.ts"() {
|
|
9820
9822
|
"use strict";
|
|
@@ -9848,6 +9850,19 @@ var init_index = __esm({
|
|
|
9848
9850
|
const sessionsDir = runOptions.sessionsDir ?? chatOptions.sessionsDir;
|
|
9849
9851
|
return runChat({ ...chatOptions, config: runOptions.config, sessionsDir, stateDir: stateDirFromSessionsDir(sessionsDir) }, io);
|
|
9850
9852
|
}
|
|
9853
|
+
if (command === "run") {
|
|
9854
|
+
if (rest.includes("--help") || rest.includes("-h")) {
|
|
9855
|
+
writeRunUsage(io.output);
|
|
9856
|
+
return 0;
|
|
9857
|
+
}
|
|
9858
|
+
try {
|
|
9859
|
+
return runHeadless(parseRunOptions(rest, runOptions), io);
|
|
9860
|
+
} catch (cause) {
|
|
9861
|
+
io.error.write(`scorel run error: ${cause instanceof Error ? cause.message : String(cause)}
|
|
9862
|
+
`);
|
|
9863
|
+
return 2;
|
|
9864
|
+
}
|
|
9865
|
+
}
|
|
9851
9866
|
if (command === "daemon") {
|
|
9852
9867
|
return runCliDaemon(rest, {
|
|
9853
9868
|
stateDir: stateDirFromSessionsDir(runOptions.sessionsDir),
|
|
@@ -10409,7 +10424,7 @@ var init_index = __esm({
|
|
|
10409
10424
|
process.on("SIGINT", sigintHandler);
|
|
10410
10425
|
try {
|
|
10411
10426
|
await client.connect(options.sessionId);
|
|
10412
|
-
const resumed = await loadOrCreateSession(client, options, project.projectId);
|
|
10427
|
+
const resumed = await loadOrCreateSession(client, options.sessionId, project.projectId);
|
|
10413
10428
|
io.error.write(`scorel chat ${resumed ? "resumed" : "created"} session ${options.sessionId}
|
|
10414
10429
|
`);
|
|
10415
10430
|
const rl = createInterface({ input: io.input, crlfDelay: Infinity });
|
|
@@ -10457,6 +10472,247 @@ var init_index = __esm({
|
|
|
10457
10472
|
await daemon.shutdown();
|
|
10458
10473
|
}
|
|
10459
10474
|
};
|
|
10475
|
+
runHeadless = async (options, io) => {
|
|
10476
|
+
const startedAt = Date.now();
|
|
10477
|
+
let projectId;
|
|
10478
|
+
const textParts = [];
|
|
10479
|
+
const prompt = await readRunPrompt(options, io);
|
|
10480
|
+
const runConfig = resolveRunConfig(options);
|
|
10481
|
+
const configScope = { scorelHomeDir: options.stateDir };
|
|
10482
|
+
const loadProjectConfig = async (project) => runConfig ?? options.config ?? await loadScorelConfig({ cwd: project.workDir, ...configScope });
|
|
10483
|
+
const loadProjectConfigProfile = async (project) => runConfig ?? options.config ?? await loadScorelConfigProfile({ cwd: project.workDir, ...configScope });
|
|
10484
|
+
const daemon = new ScorelHost({
|
|
10485
|
+
sessionsDir: options.sessionsDir,
|
|
10486
|
+
projectsPath: join17(options.stateDir, "projects.json"),
|
|
10487
|
+
deviceId: asDeviceId("device_local"),
|
|
10488
|
+
scorelHomeDir: options.stateDir,
|
|
10489
|
+
loadConfig: async ({ project }) => loadProjectConfig(project),
|
|
10490
|
+
loadConfigProfile: async ({ project }) => loadProjectConfigProfile(project),
|
|
10491
|
+
createRuntime: async ({ sessionId, project, selectedModel, purpose }) => createRealRuntime({
|
|
10492
|
+
cwd: project.workDir,
|
|
10493
|
+
config: await loadProjectConfig(project),
|
|
10494
|
+
sessionsDir: options.sessionsDir,
|
|
10495
|
+
sessionId,
|
|
10496
|
+
modelSelection: selectedModel ? { modelId: selectedModel.modelId, role: selectedModel.role } : void 0,
|
|
10497
|
+
includeTools: purpose === "chat"
|
|
10498
|
+
})
|
|
10499
|
+
});
|
|
10500
|
+
const client = new DaemonClient(createEmbeddedTransport(daemon), {
|
|
10501
|
+
clientId: asClientId("client_cli_run")
|
|
10502
|
+
});
|
|
10503
|
+
let unsubscribe;
|
|
10504
|
+
try {
|
|
10505
|
+
await daemon.start();
|
|
10506
|
+
const project = await daemon.registerProject(options.cwd);
|
|
10507
|
+
projectId = project.projectId;
|
|
10508
|
+
await client.connect(options.sessionId);
|
|
10509
|
+
await loadOrCreateSession(client, options.sessionId, project.projectId, options.modelSelection);
|
|
10510
|
+
unsubscribe = client.subscribe((event) => {
|
|
10511
|
+
if (event.type === "text_delta") {
|
|
10512
|
+
textParts.push(event.delta);
|
|
10513
|
+
}
|
|
10514
|
+
renderRunEvent(options, io, event);
|
|
10515
|
+
});
|
|
10516
|
+
const send = client.sendMessage(prompt, options.modelSelection ? { modelSelection: options.modelSelection } : void 0);
|
|
10517
|
+
const result = options.timeoutMs === void 0 ? await send : await withRunTimeout(send, options.timeoutMs, async () => {
|
|
10518
|
+
await client.cancel().catch(() => void 0);
|
|
10519
|
+
});
|
|
10520
|
+
const summary = makeRunSummary({
|
|
10521
|
+
options,
|
|
10522
|
+
startedAt,
|
|
10523
|
+
projectId,
|
|
10524
|
+
status: "completed",
|
|
10525
|
+
exitReason: "completed",
|
|
10526
|
+
userEventId: String(result.userEventId),
|
|
10527
|
+
assistantEventId: String(result.assistantEventId)
|
|
10528
|
+
});
|
|
10529
|
+
await writeRunSummary(options.summaryPath, summary);
|
|
10530
|
+
renderRunFinal(options, io, summary, textParts.join(""));
|
|
10531
|
+
return 0;
|
|
10532
|
+
} catch (cause) {
|
|
10533
|
+
const isTimeout = cause instanceof RunTimeoutError;
|
|
10534
|
+
const summary = makeRunSummary({
|
|
10535
|
+
options,
|
|
10536
|
+
startedAt,
|
|
10537
|
+
projectId,
|
|
10538
|
+
status: isTimeout ? "timeout" : "error",
|
|
10539
|
+
exitReason: isTimeout ? "timeout" : "error",
|
|
10540
|
+
error: cause instanceof Error ? cause : new Error(String(cause))
|
|
10541
|
+
});
|
|
10542
|
+
await writeRunSummary(options.summaryPath, summary).catch(() => void 0);
|
|
10543
|
+
renderRunFinal(options, io, summary, textParts.join(""));
|
|
10544
|
+
if (!options.quiet && options.outputFormat === "text") {
|
|
10545
|
+
io.error.write(`scorel run error: ${summary.error?.message ?? "unknown error"}
|
|
10546
|
+
`);
|
|
10547
|
+
}
|
|
10548
|
+
return isTimeout ? 124 : 1;
|
|
10549
|
+
} finally {
|
|
10550
|
+
unsubscribe?.();
|
|
10551
|
+
client.disconnect();
|
|
10552
|
+
await daemon.shutdown();
|
|
10553
|
+
}
|
|
10554
|
+
};
|
|
10555
|
+
renderRunEvent = (options, io, event) => {
|
|
10556
|
+
if (options.outputFormat === "none" || options.outputFormat === "json") {
|
|
10557
|
+
return;
|
|
10558
|
+
}
|
|
10559
|
+
if (options.outputFormat === "stream-json") {
|
|
10560
|
+
writeJsonLine(io.output, { type: "event", event });
|
|
10561
|
+
return;
|
|
10562
|
+
}
|
|
10563
|
+
if (event.type === "text_delta") {
|
|
10564
|
+
io.output.write(event.delta);
|
|
10565
|
+
}
|
|
10566
|
+
if (event.type === "tool_result") {
|
|
10567
|
+
writeToolResult(io.output, event);
|
|
10568
|
+
}
|
|
10569
|
+
if (event.type === "error") {
|
|
10570
|
+
writeEventError(io.error, event);
|
|
10571
|
+
}
|
|
10572
|
+
};
|
|
10573
|
+
renderRunFinal = (options, io, summary, text) => {
|
|
10574
|
+
if (options.outputFormat === "none") {
|
|
10575
|
+
return;
|
|
10576
|
+
}
|
|
10577
|
+
if (options.outputFormat === "json") {
|
|
10578
|
+
io.output.write(`${JSON.stringify({ ...summary, result: text })}
|
|
10579
|
+
`);
|
|
10580
|
+
return;
|
|
10581
|
+
}
|
|
10582
|
+
if (options.outputFormat === "stream-json") {
|
|
10583
|
+
writeJsonLine(io.output, { type: "result", summary, result: text });
|
|
10584
|
+
return;
|
|
10585
|
+
}
|
|
10586
|
+
if (!text.endsWith("\n")) {
|
|
10587
|
+
io.output.write("\n");
|
|
10588
|
+
}
|
|
10589
|
+
};
|
|
10590
|
+
writeJsonLine = (output, value) => {
|
|
10591
|
+
output.write(`${JSON.stringify(value)}
|
|
10592
|
+
`);
|
|
10593
|
+
};
|
|
10594
|
+
RunTimeoutError = class extends Error {
|
|
10595
|
+
constructor(timeoutMs) {
|
|
10596
|
+
super(`run timed out after ${timeoutMs}ms`);
|
|
10597
|
+
this.name = "RunTimeoutError";
|
|
10598
|
+
}
|
|
10599
|
+
};
|
|
10600
|
+
withRunTimeout = async (promise, timeoutMs, onTimeout) => {
|
|
10601
|
+
let timeout;
|
|
10602
|
+
try {
|
|
10603
|
+
return await Promise.race([
|
|
10604
|
+
promise,
|
|
10605
|
+
new Promise((_resolve, reject) => {
|
|
10606
|
+
timeout = setTimeout(() => {
|
|
10607
|
+
void onTimeout().finally(() => reject(new RunTimeoutError(timeoutMs)));
|
|
10608
|
+
}, timeoutMs);
|
|
10609
|
+
})
|
|
10610
|
+
]);
|
|
10611
|
+
} finally {
|
|
10612
|
+
if (timeout) {
|
|
10613
|
+
clearTimeout(timeout);
|
|
10614
|
+
}
|
|
10615
|
+
}
|
|
10616
|
+
};
|
|
10617
|
+
makeRunSummary = (input) => ({
|
|
10618
|
+
status: input.status,
|
|
10619
|
+
sessionId: String(input.options.sessionId),
|
|
10620
|
+
...input.projectId ? { projectId: String(input.projectId) } : {},
|
|
10621
|
+
cwd: input.options.cwd,
|
|
10622
|
+
stateDir: input.options.stateDir,
|
|
10623
|
+
sessionsDir: input.options.sessionsDir,
|
|
10624
|
+
sessionJsonl: join17(input.options.sessionsDir, `${input.options.sessionId}.jsonl`),
|
|
10625
|
+
outputFormat: input.options.outputFormat,
|
|
10626
|
+
elapsedMs: Date.now() - input.startedAt,
|
|
10627
|
+
exitReason: input.exitReason,
|
|
10628
|
+
...input.userEventId ? { userEventId: input.userEventId } : {},
|
|
10629
|
+
...input.assistantEventId ? { assistantEventId: input.assistantEventId } : {},
|
|
10630
|
+
...input.error ? { error: { message: input.error.message } } : {}
|
|
10631
|
+
});
|
|
10632
|
+
writeRunSummary = async (path, summary) => {
|
|
10633
|
+
if (!path) {
|
|
10634
|
+
return;
|
|
10635
|
+
}
|
|
10636
|
+
await mkdir8(dirname13(path), { recursive: true });
|
|
10637
|
+
await writeFile8(path, `${JSON.stringify(summary, null, 2)}
|
|
10638
|
+
`);
|
|
10639
|
+
};
|
|
10640
|
+
readRunPrompt = async (options, io) => {
|
|
10641
|
+
if (options.promptSource === "prompt-file") {
|
|
10642
|
+
return (await readFile14(options.promptFile, "utf8")).trim();
|
|
10643
|
+
}
|
|
10644
|
+
if (options.promptSource === "stdin") {
|
|
10645
|
+
const chunks = [];
|
|
10646
|
+
for await (const chunk of io.input) {
|
|
10647
|
+
chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(String(chunk)));
|
|
10648
|
+
}
|
|
10649
|
+
return Buffer.concat(chunks).toString("utf8").trim();
|
|
10650
|
+
}
|
|
10651
|
+
return (options.prompt ?? "").trim();
|
|
10652
|
+
};
|
|
10653
|
+
resolveRunConfig = (options) => {
|
|
10654
|
+
const override = options.providerOverride;
|
|
10655
|
+
if (!override || !override.provider && !override.api && !override.baseUrl && !override.apiKey) {
|
|
10656
|
+
return void 0;
|
|
10657
|
+
}
|
|
10658
|
+
if (!override.baseUrl) {
|
|
10659
|
+
throw new Error("--base-url is required when overriding the run provider");
|
|
10660
|
+
}
|
|
10661
|
+
if (!override.apiKey) {
|
|
10662
|
+
throw new Error("--api-key is required when overriding the run provider");
|
|
10663
|
+
}
|
|
10664
|
+
if (!options.modelSelection?.modelId) {
|
|
10665
|
+
throw new Error("--model <model-id> is required when overriding the run provider");
|
|
10666
|
+
}
|
|
10667
|
+
const providerId = "run";
|
|
10668
|
+
const providerModelId = "run_model";
|
|
10669
|
+
const availableModelId = options.modelSelection.modelId;
|
|
10670
|
+
return {
|
|
10671
|
+
providers: {
|
|
10672
|
+
[providerId]: {
|
|
10673
|
+
type: "custom",
|
|
10674
|
+
api: override.api ?? "openai-completions",
|
|
10675
|
+
provider: override.provider ?? "openai",
|
|
10676
|
+
baseUrl: stripTrailingSlashes2(override.baseUrl),
|
|
10677
|
+
apiKey: override.apiKey
|
|
10678
|
+
}
|
|
10679
|
+
},
|
|
10680
|
+
providerModels: {
|
|
10681
|
+
[providerModelId]: {
|
|
10682
|
+
provider: providerId,
|
|
10683
|
+
id: availableModelId,
|
|
10684
|
+
displayName: availableModelId
|
|
10685
|
+
}
|
|
10686
|
+
},
|
|
10687
|
+
models: {
|
|
10688
|
+
[availableModelId]: {
|
|
10689
|
+
model: providerModelId,
|
|
10690
|
+
displayName: availableModelId
|
|
10691
|
+
}
|
|
10692
|
+
},
|
|
10693
|
+
modelProfile: {
|
|
10694
|
+
roles: {
|
|
10695
|
+
primary: availableModelId,
|
|
10696
|
+
standard: availableModelId,
|
|
10697
|
+
auxiliary: availableModelId
|
|
10698
|
+
}
|
|
10699
|
+
},
|
|
10700
|
+
memory: {
|
|
10701
|
+
enabled: false,
|
|
10702
|
+
daily: false,
|
|
10703
|
+
sessionMemory: false,
|
|
10704
|
+
autoDream: false,
|
|
10705
|
+
promoteRoot: false,
|
|
10706
|
+
dreamIdleMinutes: 60,
|
|
10707
|
+
autoCompactThreshold: 0.8
|
|
10708
|
+
},
|
|
10709
|
+
runtime: {
|
|
10710
|
+
tokenSavingRtk: false
|
|
10711
|
+
},
|
|
10712
|
+
extensions: {}
|
|
10713
|
+
};
|
|
10714
|
+
};
|
|
10715
|
+
stripTrailingSlashes2 = (value) => value.replace(/\/+$/, "");
|
|
10460
10716
|
createSigintHandler = (options) => {
|
|
10461
10717
|
return () => {
|
|
10462
10718
|
if (options.isInFlight()) {
|
|
@@ -10467,14 +10723,14 @@ var init_index = __esm({
|
|
|
10467
10723
|
options.exit();
|
|
10468
10724
|
};
|
|
10469
10725
|
};
|
|
10470
|
-
loadOrCreateSession = async (client,
|
|
10726
|
+
loadOrCreateSession = async (client, sessionId, projectId, modelSelection) => {
|
|
10471
10727
|
try {
|
|
10472
|
-
await client.loadSession(
|
|
10728
|
+
await client.loadSession(sessionId);
|
|
10473
10729
|
return true;
|
|
10474
10730
|
} catch {
|
|
10475
10731
|
await client.createSession({
|
|
10476
|
-
sessionId
|
|
10477
|
-
meta: { projectId }
|
|
10732
|
+
sessionId,
|
|
10733
|
+
meta: { projectId, ...modelSelection ? { modelSelection } : {} }
|
|
10478
10734
|
});
|
|
10479
10735
|
return false;
|
|
10480
10736
|
}
|
|
@@ -10499,6 +10755,152 @@ var init_index = __esm({
|
|
|
10499
10755
|
const sessionsDir = defaultSessionsDir();
|
|
10500
10756
|
return { sessionId, sessionsDir, stateDir: stateDirFromSessionsDir(sessionsDir), cwd };
|
|
10501
10757
|
};
|
|
10758
|
+
parseRunOptions = (argv, runOptions) => {
|
|
10759
|
+
const promptSources = [];
|
|
10760
|
+
let sessionId = asSessionId(`ses_run_${Date.now().toString(36)}`);
|
|
10761
|
+
let cwd = process.cwd();
|
|
10762
|
+
let stateDir;
|
|
10763
|
+
let sessionsDir = runOptions.sessionsDir;
|
|
10764
|
+
let timeoutMs;
|
|
10765
|
+
let outputFormat = "text";
|
|
10766
|
+
let summaryPath;
|
|
10767
|
+
let quiet = false;
|
|
10768
|
+
let modelSelection;
|
|
10769
|
+
const providerOverride = {};
|
|
10770
|
+
const positional = [];
|
|
10771
|
+
for (let index = 0; index < argv.length; index += 1) {
|
|
10772
|
+
const arg = argv[index];
|
|
10773
|
+
if (arg === "--prompt") {
|
|
10774
|
+
promptSources.push({ promptSource: "prompt", prompt: requireValue6(argv, index, "--prompt") });
|
|
10775
|
+
index += 1;
|
|
10776
|
+
continue;
|
|
10777
|
+
}
|
|
10778
|
+
if (arg === "--prompt-file") {
|
|
10779
|
+
promptSources.push({ promptSource: "prompt-file", promptFile: requireValue6(argv, index, "--prompt-file") });
|
|
10780
|
+
index += 1;
|
|
10781
|
+
continue;
|
|
10782
|
+
}
|
|
10783
|
+
if (arg === "--stdin") {
|
|
10784
|
+
promptSources.push({ promptSource: "stdin" });
|
|
10785
|
+
continue;
|
|
10786
|
+
}
|
|
10787
|
+
if (arg === "--session") {
|
|
10788
|
+
sessionId = asSessionId(requireValue6(argv, index, "--session"));
|
|
10789
|
+
index += 1;
|
|
10790
|
+
continue;
|
|
10791
|
+
}
|
|
10792
|
+
if (arg === "--cwd") {
|
|
10793
|
+
cwd = requireValue6(argv, index, "--cwd");
|
|
10794
|
+
index += 1;
|
|
10795
|
+
continue;
|
|
10796
|
+
}
|
|
10797
|
+
if (arg === "--state-dir") {
|
|
10798
|
+
stateDir = requireValue6(argv, index, "--state-dir");
|
|
10799
|
+
index += 1;
|
|
10800
|
+
continue;
|
|
10801
|
+
}
|
|
10802
|
+
if (arg === "--sessions-dir") {
|
|
10803
|
+
sessionsDir = requireValue6(argv, index, "--sessions-dir");
|
|
10804
|
+
index += 1;
|
|
10805
|
+
continue;
|
|
10806
|
+
}
|
|
10807
|
+
if (arg === "--timeout-ms") {
|
|
10808
|
+
timeoutMs = parsePositiveInteger(requireValue6(argv, index, "--timeout-ms"), "--timeout-ms");
|
|
10809
|
+
index += 1;
|
|
10810
|
+
continue;
|
|
10811
|
+
}
|
|
10812
|
+
if (arg === "--output-format") {
|
|
10813
|
+
outputFormat = parseRunOutputFormat(requireValue6(argv, index, "--output-format"));
|
|
10814
|
+
index += 1;
|
|
10815
|
+
continue;
|
|
10816
|
+
}
|
|
10817
|
+
if (arg === "--summary") {
|
|
10818
|
+
summaryPath = requireValue6(argv, index, "--summary");
|
|
10819
|
+
index += 1;
|
|
10820
|
+
continue;
|
|
10821
|
+
}
|
|
10822
|
+
if (arg === "--quiet") {
|
|
10823
|
+
quiet = true;
|
|
10824
|
+
continue;
|
|
10825
|
+
}
|
|
10826
|
+
if (arg === "--model") {
|
|
10827
|
+
modelSelection = parseModelSelection(requireValue6(argv, index, "--model"));
|
|
10828
|
+
index += 1;
|
|
10829
|
+
continue;
|
|
10830
|
+
}
|
|
10831
|
+
if (arg === "--provider") {
|
|
10832
|
+
providerOverride.provider = requireValue6(argv, index, "--provider");
|
|
10833
|
+
index += 1;
|
|
10834
|
+
continue;
|
|
10835
|
+
}
|
|
10836
|
+
if (arg === "--api" || arg === "--protocol") {
|
|
10837
|
+
providerOverride.api = parseRunProviderApi(requireValue6(argv, index, arg));
|
|
10838
|
+
index += 1;
|
|
10839
|
+
continue;
|
|
10840
|
+
}
|
|
10841
|
+
if (arg === "--base-url" || arg === "--baseurl") {
|
|
10842
|
+
providerOverride.baseUrl = requireValue6(argv, index, arg);
|
|
10843
|
+
index += 1;
|
|
10844
|
+
continue;
|
|
10845
|
+
}
|
|
10846
|
+
if (arg === "--api-key" || arg === "--apikey") {
|
|
10847
|
+
providerOverride.apiKey = requireValue6(argv, index, arg);
|
|
10848
|
+
index += 1;
|
|
10849
|
+
continue;
|
|
10850
|
+
}
|
|
10851
|
+
if (arg.startsWith("-")) {
|
|
10852
|
+
throw new Error(`Unknown run option: ${arg}`);
|
|
10853
|
+
}
|
|
10854
|
+
positional.push(arg);
|
|
10855
|
+
}
|
|
10856
|
+
if (positional.length > 0) {
|
|
10857
|
+
promptSources.unshift({ promptSource: "argument", prompt: positional.join(" ") });
|
|
10858
|
+
}
|
|
10859
|
+
if (promptSources.length !== 1) {
|
|
10860
|
+
throw new Error("scorel run requires exactly one prompt source");
|
|
10861
|
+
}
|
|
10862
|
+
const resolvedStateDir = stateDir ?? stateDirFromSessionsDir(sessionsDir);
|
|
10863
|
+
const resolvedSessionsDir = sessionsDir ?? join17(resolvedStateDir, "sessions");
|
|
10864
|
+
return {
|
|
10865
|
+
...promptSources[0],
|
|
10866
|
+
sessionId,
|
|
10867
|
+
cwd,
|
|
10868
|
+
stateDir: resolvedStateDir,
|
|
10869
|
+
sessionsDir: resolvedSessionsDir,
|
|
10870
|
+
timeoutMs,
|
|
10871
|
+
outputFormat,
|
|
10872
|
+
summaryPath,
|
|
10873
|
+
quiet,
|
|
10874
|
+
modelSelection,
|
|
10875
|
+
providerOverride,
|
|
10876
|
+
config: runOptions.config
|
|
10877
|
+
};
|
|
10878
|
+
};
|
|
10879
|
+
parseRunOutputFormat = (value) => {
|
|
10880
|
+
if (value === "text" || value === "json" || value === "stream-json" || value === "none") {
|
|
10881
|
+
return value;
|
|
10882
|
+
}
|
|
10883
|
+
throw new Error("--output-format must be text, json, stream-json, or none");
|
|
10884
|
+
};
|
|
10885
|
+
parsePositiveInteger = (value, flag) => {
|
|
10886
|
+
const parsed = Number(value);
|
|
10887
|
+
if (!Number.isInteger(parsed) || parsed <= 0) {
|
|
10888
|
+
throw new Error(`${flag} must be a positive integer`);
|
|
10889
|
+
}
|
|
10890
|
+
return parsed;
|
|
10891
|
+
};
|
|
10892
|
+
parseModelSelection = (value) => {
|
|
10893
|
+
if (value === "primary" || value === "standard" || value === "auxiliary") {
|
|
10894
|
+
return { role: value };
|
|
10895
|
+
}
|
|
10896
|
+
return { modelId: value };
|
|
10897
|
+
};
|
|
10898
|
+
parseRunProviderApi = (value) => {
|
|
10899
|
+
if (value === "openai-completions" || value === "openai-responses" || value === "google-generative-ai" || value === "anthropic-messages") {
|
|
10900
|
+
return value;
|
|
10901
|
+
}
|
|
10902
|
+
throw new Error("--api must be openai-completions, openai-responses, google-generative-ai, or anthropic-messages");
|
|
10903
|
+
};
|
|
10502
10904
|
requireValue6 = (argv, index, flag) => {
|
|
10503
10905
|
const value = argv[index + 1];
|
|
10504
10906
|
if (!value) {
|
|
@@ -10516,6 +10918,12 @@ var init_index = __esm({
|
|
|
10516
10918
|
[
|
|
10517
10919
|
"Usage: scorel chat [--session <id>] [--cwd <dir>]",
|
|
10518
10920
|
" scorel [--session <id>] [--cwd <dir>]",
|
|
10921
|
+
" scorel run [prompt] [--prompt <text> | --prompt-file <path> | --stdin]",
|
|
10922
|
+
" [--cwd <dir>] [--state-dir <dir>] [--sessions-dir <dir>]",
|
|
10923
|
+
" [--session <id>] [--timeout-ms <ms>]",
|
|
10924
|
+
" [--output-format text|json|stream-json|none] [--summary <path>]",
|
|
10925
|
+
" [--provider <name>] [--api|--protocol <protocol>]",
|
|
10926
|
+
" [--base-url|--baseurl <url>] [--api-key|--apikey <key>] [--model <id>]",
|
|
10519
10927
|
" scorel attach --session <id> --remote <ws-url> --token <token>",
|
|
10520
10928
|
" scorel host start [--host <h>] [--port <p>] [--token <t>] [--project <dir>]",
|
|
10521
10929
|
" [--relay <relay-url> | --no-relay] [--replace] [--idle-timeout-ms <ms>]",
|
|
@@ -10538,6 +10946,37 @@ var init_index = __esm({
|
|
|
10538
10946
|
].join("\n") + "\n"
|
|
10539
10947
|
);
|
|
10540
10948
|
};
|
|
10949
|
+
writeRunUsage = (output) => {
|
|
10950
|
+
output.write(
|
|
10951
|
+
[
|
|
10952
|
+
"Usage: scorel run [prompt]",
|
|
10953
|
+
" scorel run --prompt <text>",
|
|
10954
|
+
" scorel run --prompt-file <path>",
|
|
10955
|
+
" scorel run --stdin",
|
|
10956
|
+
"",
|
|
10957
|
+
"Options:",
|
|
10958
|
+
" --cwd <dir>",
|
|
10959
|
+
" --state-dir <dir>",
|
|
10960
|
+
" --sessions-dir <dir>",
|
|
10961
|
+
" --session <id>",
|
|
10962
|
+
" --timeout-ms <ms>",
|
|
10963
|
+
" --output-format text|json|stream-json|none",
|
|
10964
|
+
" --summary <path>",
|
|
10965
|
+
" --quiet",
|
|
10966
|
+
" --model <primary|standard|auxiliary|model-id>",
|
|
10967
|
+
" --provider <name>",
|
|
10968
|
+
" --api, --protocol <openai-completions|openai-responses|google-generative-ai|anthropic-messages>",
|
|
10969
|
+
" --base-url, --baseurl <url>",
|
|
10970
|
+
" --api-key, --apikey <key>",
|
|
10971
|
+
"",
|
|
10972
|
+
"Examples:",
|
|
10973
|
+
' scorel run --prompt "Summarize this project" --output-format json',
|
|
10974
|
+
" scorel run --prompt-file /tmp/instruction.txt --cwd /workspace --state-dir /tmp/scorel-state \\",
|
|
10975
|
+
' --api openai-completions --baseurl http://127.0.0.1:4000/v1 --apikey "$API_KEY" \\',
|
|
10976
|
+
" --model gpt-5.4-mini --output-format none --summary /logs/agent/scorel-summary.json"
|
|
10977
|
+
].join("\n") + "\n"
|
|
10978
|
+
);
|
|
10979
|
+
};
|
|
10541
10980
|
writeProjectUsage = (output) => {
|
|
10542
10981
|
output.write("Usage: scorel project list | add <dir> | remove <project-id>\n");
|
|
10543
10982
|
};
|