@lesscap/baton-cli 0.4.3 → 0.5.1
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/baton.mjs +69 -568
- package/package.json +1 -1
package/dist/baton.mjs
CHANGED
|
@@ -4777,30 +4777,30 @@ import { join } from "node:path";
|
|
|
4777
4777
|
var PROJECT_CONFIG_NAME = ".baton.json";
|
|
4778
4778
|
var projectConfigPath = (cwd = process.cwd()) => join(cwd, PROJECT_CONFIG_NAME);
|
|
4779
4779
|
var configPathFromArgs = (args, cwd) => args.config ?? projectConfigPath(cwd);
|
|
4780
|
-
var loadProjectConfig = (
|
|
4780
|
+
var loadProjectConfig = (path) => {
|
|
4781
4781
|
try {
|
|
4782
|
-
return JSON.parse(readFileSync(
|
|
4782
|
+
return JSON.parse(readFileSync(path, "utf8"));
|
|
4783
4783
|
} catch (err) {
|
|
4784
|
-
const cause = err.code === "ENOENT" ? `not found at ${
|
|
4784
|
+
const cause = err.code === "ENOENT" ? `not found at ${path}` : String(err);
|
|
4785
4785
|
throw new Error(`${PROJECT_CONFIG_NAME} ${cause} \u2014 run \`baton init\` first`);
|
|
4786
4786
|
}
|
|
4787
4787
|
};
|
|
4788
|
-
var loadProjectConfigOrNull = (
|
|
4789
|
-
if (!existsSync(
|
|
4788
|
+
var loadProjectConfigOrNull = (path) => {
|
|
4789
|
+
if (!existsSync(path)) return null;
|
|
4790
4790
|
try {
|
|
4791
|
-
return JSON.parse(readFileSync(
|
|
4791
|
+
return JSON.parse(readFileSync(path, "utf8"));
|
|
4792
4792
|
} catch {
|
|
4793
4793
|
return null;
|
|
4794
4794
|
}
|
|
4795
4795
|
};
|
|
4796
|
-
var saveProjectConfig = (
|
|
4797
|
-
writeFileSync(
|
|
4796
|
+
var saveProjectConfig = (path, config) => {
|
|
4797
|
+
writeFileSync(path, `${JSON.stringify(config, null, 2)}
|
|
4798
4798
|
`, "utf8");
|
|
4799
4799
|
};
|
|
4800
|
-
var patch = (
|
|
4801
|
-
saveProjectConfig(
|
|
4800
|
+
var patch = (path, fn) => {
|
|
4801
|
+
saveProjectConfig(path, fn(loadProjectConfig(path)));
|
|
4802
4802
|
};
|
|
4803
|
-
var setWorker = (
|
|
4803
|
+
var setWorker = (path, w) => patch(path, (cfg) => ({ ...cfg, worker: w }));
|
|
4804
4804
|
var requireBase = (cfg) => {
|
|
4805
4805
|
if (!cfg.server || !cfg.project || !cfg.worker)
|
|
4806
4806
|
throw new Error("project-config missing server/project/worker \u2014 run `baton worker register`");
|
|
@@ -5566,7 +5566,7 @@ var BY_EXT = {
|
|
|
5566
5566
|
".json": "application/json",
|
|
5567
5567
|
".csv": "text/csv"
|
|
5568
5568
|
};
|
|
5569
|
-
var contentTypeForPath = (
|
|
5569
|
+
var contentTypeForPath = (path) => BY_EXT[extname(path).toLowerCase()] ?? "application/octet-stream";
|
|
5570
5570
|
|
|
5571
5571
|
// src/commands/attach.ts
|
|
5572
5572
|
import { openAsBlob } from "node:fs";
|
|
@@ -5574,12 +5574,12 @@ import { basename } from "node:path";
|
|
|
5574
5574
|
var attachPaths = (raw) => (raw === void 0 ? [] : Array.isArray(raw) ? raw : [raw]).flatMap((p) => p.split(",")).map((p) => p.trim()).filter(Boolean);
|
|
5575
5575
|
var uploadAttachments = async (client, sessionId, paths) => {
|
|
5576
5576
|
const out = [];
|
|
5577
|
-
for (const
|
|
5578
|
-
const body = await openAsBlob(
|
|
5577
|
+
for (const path of paths) {
|
|
5578
|
+
const body = await openAsBlob(path, { type: contentTypeForPath(path) });
|
|
5579
5579
|
out.push(
|
|
5580
5580
|
await client.sessions.uploadAttachment(sessionId, {
|
|
5581
|
-
filename: basename(
|
|
5582
|
-
contentType: contentTypeForPath(
|
|
5581
|
+
filename: basename(path),
|
|
5582
|
+
contentType: contentTypeForPath(path),
|
|
5583
5583
|
body
|
|
5584
5584
|
})
|
|
5585
5585
|
);
|
|
@@ -5612,12 +5612,12 @@ var sendCommand = defineCommand({
|
|
|
5612
5612
|
if (text === void 0 && args.file) text = readFileSync2(args.file, "utf8");
|
|
5613
5613
|
if (text === void 0 && !process.stdin.isTTY) text = await readStdin();
|
|
5614
5614
|
const attachments = [];
|
|
5615
|
-
for (const
|
|
5615
|
+
for (const path of attachPaths(args.attach)) {
|
|
5616
5616
|
attachments.push(
|
|
5617
5617
|
await client.uploadAttachment(args.channel, {
|
|
5618
|
-
filename: basename2(
|
|
5619
|
-
contentType: contentTypeForPath(
|
|
5620
|
-
body: await openAsBlob2(
|
|
5618
|
+
filename: basename2(path),
|
|
5619
|
+
contentType: contentTypeForPath(path),
|
|
5620
|
+
body: await openAsBlob2(path, { type: contentTypeForPath(path) })
|
|
5621
5621
|
})
|
|
5622
5622
|
);
|
|
5623
5623
|
}
|
|
@@ -6411,6 +6411,26 @@ var additionalDirs = () => {
|
|
|
6411
6411
|
const dirs = raw.split(":").map((s) => s.trim()).filter((s) => s !== "" && isAbsolute(s) && existsSync3(s));
|
|
6412
6412
|
return dirs.length > 0 ? dirs : void 0;
|
|
6413
6413
|
};
|
|
6414
|
+
var truthy = (value) => {
|
|
6415
|
+
if (value === void 0) return void 0;
|
|
6416
|
+
const normalized = value.trim().toLowerCase();
|
|
6417
|
+
if (["1", "true", "yes", "on"].includes(normalized)) return true;
|
|
6418
|
+
if (["0", "false", "no", "off"].includes(normalized)) return false;
|
|
6419
|
+
return void 0;
|
|
6420
|
+
};
|
|
6421
|
+
var codexNetworkAccess = () => truthy(process.env.BATON_CODEX_NETWORK_ACCESS);
|
|
6422
|
+
var codexSandboxMode = (planMode) => {
|
|
6423
|
+
if (planMode) return "read-only";
|
|
6424
|
+
const raw = process.env.BATON_CODEX_SANDBOX_MODE;
|
|
6425
|
+
if (raw === "read-only" || raw === "workspace-write" || raw === "danger-full-access") return raw;
|
|
6426
|
+
return "workspace-write";
|
|
6427
|
+
};
|
|
6428
|
+
var codexApprovalPolicy = () => {
|
|
6429
|
+
const raw = process.env.BATON_CODEX_APPROVAL_POLICY;
|
|
6430
|
+
if (raw === "never" || raw === "on-request" || raw === "on-failure" || raw === "untrusted")
|
|
6431
|
+
return raw;
|
|
6432
|
+
return "never";
|
|
6433
|
+
};
|
|
6414
6434
|
|
|
6415
6435
|
// src/session/runner/transcript.ts
|
|
6416
6436
|
import { readdirSync, readFileSync as readFileSync4, statSync } from "node:fs";
|
|
@@ -6463,10 +6483,10 @@ var parseFirstExchange = (content) => {
|
|
|
6463
6483
|
return userText || assistantText ? { userText, assistantText } : null;
|
|
6464
6484
|
};
|
|
6465
6485
|
var readFirstExchange = (agentSessionId) => {
|
|
6466
|
-
const
|
|
6467
|
-
if (!
|
|
6486
|
+
const path = findTranscriptPath(agentSessionId);
|
|
6487
|
+
if (!path) return null;
|
|
6468
6488
|
try {
|
|
6469
|
-
return parseFirstExchange(readFileSync4(
|
|
6489
|
+
return parseFirstExchange(readFileSync4(path, "utf8"));
|
|
6470
6490
|
} catch {
|
|
6471
6491
|
return null;
|
|
6472
6492
|
}
|
|
@@ -6523,534 +6543,8 @@ var augmentPrompt = (text, relPaths, labels) => {
|
|
|
6523
6543
|
${text}` : header;
|
|
6524
6544
|
};
|
|
6525
6545
|
|
|
6526
|
-
// ../../node_modules/.pnpm/@openai+codex-sdk@0.142.5/node_modules/@openai/codex-sdk/dist/index.js
|
|
6527
|
-
import { promises as fs } from "fs";
|
|
6528
|
-
import os from "os";
|
|
6529
|
-
import path from "path";
|
|
6530
|
-
import { spawn } from "child_process";
|
|
6531
|
-
import { statSync as statSync2 } from "fs";
|
|
6532
|
-
import path2 from "path";
|
|
6533
|
-
import readline2 from "readline";
|
|
6534
|
-
import { createRequire } from "module";
|
|
6535
|
-
async function createOutputSchemaFile(schema) {
|
|
6536
|
-
if (schema === void 0) {
|
|
6537
|
-
return { cleanup: async () => {
|
|
6538
|
-
} };
|
|
6539
|
-
}
|
|
6540
|
-
if (!isJsonObject(schema)) {
|
|
6541
|
-
throw new Error("outputSchema must be a plain JSON object");
|
|
6542
|
-
}
|
|
6543
|
-
const schemaDir = await fs.mkdtemp(path.join(os.tmpdir(), "codex-output-schema-"));
|
|
6544
|
-
const schemaPath = path.join(schemaDir, "schema.json");
|
|
6545
|
-
const cleanup = async () => {
|
|
6546
|
-
try {
|
|
6547
|
-
await fs.rm(schemaDir, { recursive: true, force: true });
|
|
6548
|
-
} catch {
|
|
6549
|
-
}
|
|
6550
|
-
};
|
|
6551
|
-
try {
|
|
6552
|
-
await fs.writeFile(schemaPath, JSON.stringify(schema), "utf8");
|
|
6553
|
-
return { schemaPath, cleanup };
|
|
6554
|
-
} catch (error) {
|
|
6555
|
-
await cleanup();
|
|
6556
|
-
throw error;
|
|
6557
|
-
}
|
|
6558
|
-
}
|
|
6559
|
-
function isJsonObject(value) {
|
|
6560
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
6561
|
-
}
|
|
6562
|
-
var Thread = class {
|
|
6563
|
-
_exec;
|
|
6564
|
-
_options;
|
|
6565
|
-
_id;
|
|
6566
|
-
_threadOptions;
|
|
6567
|
-
/** Returns the ID of the thread. Populated after the first turn starts. */
|
|
6568
|
-
get id() {
|
|
6569
|
-
return this._id;
|
|
6570
|
-
}
|
|
6571
|
-
/* @internal */
|
|
6572
|
-
constructor(exec, options, threadOptions, id = null) {
|
|
6573
|
-
this._exec = exec;
|
|
6574
|
-
this._options = options;
|
|
6575
|
-
this._id = id;
|
|
6576
|
-
this._threadOptions = threadOptions;
|
|
6577
|
-
}
|
|
6578
|
-
/** Provides the input to the agent and streams events as they are produced during the turn. */
|
|
6579
|
-
async runStreamed(input, turnOptions = {}) {
|
|
6580
|
-
return { events: this.runStreamedInternal(input, turnOptions) };
|
|
6581
|
-
}
|
|
6582
|
-
async *runStreamedInternal(input, turnOptions = {}) {
|
|
6583
|
-
const { schemaPath, cleanup } = await createOutputSchemaFile(turnOptions.outputSchema);
|
|
6584
|
-
const options = this._threadOptions;
|
|
6585
|
-
const { prompt, images } = normalizeInput(input);
|
|
6586
|
-
const generator = this._exec.run({
|
|
6587
|
-
input: prompt,
|
|
6588
|
-
baseUrl: this._options.baseUrl,
|
|
6589
|
-
apiKey: this._options.apiKey,
|
|
6590
|
-
threadId: this._id,
|
|
6591
|
-
images,
|
|
6592
|
-
model: options?.model,
|
|
6593
|
-
sandboxMode: options?.sandboxMode,
|
|
6594
|
-
workingDirectory: options?.workingDirectory,
|
|
6595
|
-
skipGitRepoCheck: options?.skipGitRepoCheck,
|
|
6596
|
-
outputSchemaFile: schemaPath,
|
|
6597
|
-
modelReasoningEffort: options?.modelReasoningEffort,
|
|
6598
|
-
signal: turnOptions.signal,
|
|
6599
|
-
networkAccessEnabled: options?.networkAccessEnabled,
|
|
6600
|
-
webSearchMode: options?.webSearchMode,
|
|
6601
|
-
webSearchEnabled: options?.webSearchEnabled,
|
|
6602
|
-
approvalPolicy: options?.approvalPolicy,
|
|
6603
|
-
additionalDirectories: options?.additionalDirectories
|
|
6604
|
-
});
|
|
6605
|
-
try {
|
|
6606
|
-
for await (const item of generator) {
|
|
6607
|
-
let parsed;
|
|
6608
|
-
try {
|
|
6609
|
-
parsed = JSON.parse(item);
|
|
6610
|
-
} catch (error) {
|
|
6611
|
-
throw new Error(`Failed to parse item: ${item}`, { cause: error });
|
|
6612
|
-
}
|
|
6613
|
-
if (parsed.type === "thread.started") {
|
|
6614
|
-
this._id = parsed.thread_id;
|
|
6615
|
-
}
|
|
6616
|
-
yield parsed;
|
|
6617
|
-
}
|
|
6618
|
-
} finally {
|
|
6619
|
-
await cleanup();
|
|
6620
|
-
}
|
|
6621
|
-
}
|
|
6622
|
-
/** Provides the input to the agent and returns the completed turn. */
|
|
6623
|
-
async run(input, turnOptions = {}) {
|
|
6624
|
-
const generator = this.runStreamedInternal(input, turnOptions);
|
|
6625
|
-
const items = [];
|
|
6626
|
-
let finalResponse = "";
|
|
6627
|
-
let usage = null;
|
|
6628
|
-
let turnFailure = null;
|
|
6629
|
-
for await (const event of generator) {
|
|
6630
|
-
if (event.type === "item.completed") {
|
|
6631
|
-
if (event.item.type === "agent_message") {
|
|
6632
|
-
finalResponse = event.item.text;
|
|
6633
|
-
}
|
|
6634
|
-
items.push(event.item);
|
|
6635
|
-
} else if (event.type === "turn.completed") {
|
|
6636
|
-
usage = event.usage;
|
|
6637
|
-
} else if (event.type === "turn.failed") {
|
|
6638
|
-
turnFailure = event.error;
|
|
6639
|
-
break;
|
|
6640
|
-
}
|
|
6641
|
-
}
|
|
6642
|
-
if (turnFailure) {
|
|
6643
|
-
throw new Error(turnFailure.message);
|
|
6644
|
-
}
|
|
6645
|
-
return { items, finalResponse, usage };
|
|
6646
|
-
}
|
|
6647
|
-
};
|
|
6648
|
-
function normalizeInput(input) {
|
|
6649
|
-
if (typeof input === "string") {
|
|
6650
|
-
return { prompt: input, images: [] };
|
|
6651
|
-
}
|
|
6652
|
-
const promptParts = [];
|
|
6653
|
-
const images = [];
|
|
6654
|
-
for (const item of input) {
|
|
6655
|
-
if (item.type === "text") {
|
|
6656
|
-
promptParts.push(item.text);
|
|
6657
|
-
} else if (item.type === "local_image") {
|
|
6658
|
-
images.push(item.path);
|
|
6659
|
-
}
|
|
6660
|
-
}
|
|
6661
|
-
return { prompt: promptParts.join("\n\n"), images };
|
|
6662
|
-
}
|
|
6663
|
-
var INTERNAL_ORIGINATOR_ENV = "CODEX_INTERNAL_ORIGINATOR_OVERRIDE";
|
|
6664
|
-
var TYPESCRIPT_SDK_ORIGINATOR = "codex_sdk_ts";
|
|
6665
|
-
var CODEX_NPM_NAME = "@openai/codex";
|
|
6666
|
-
var PLATFORM_PACKAGE_BY_TARGET = {
|
|
6667
|
-
"x86_64-unknown-linux-musl": "@openai/codex-linux-x64",
|
|
6668
|
-
"aarch64-unknown-linux-musl": "@openai/codex-linux-arm64",
|
|
6669
|
-
"x86_64-apple-darwin": "@openai/codex-darwin-x64",
|
|
6670
|
-
"aarch64-apple-darwin": "@openai/codex-darwin-arm64",
|
|
6671
|
-
"x86_64-pc-windows-msvc": "@openai/codex-win32-x64",
|
|
6672
|
-
"aarch64-pc-windows-msvc": "@openai/codex-win32-arm64"
|
|
6673
|
-
};
|
|
6674
|
-
var moduleRequire = createRequire(import.meta.url);
|
|
6675
|
-
var CodexExec = class {
|
|
6676
|
-
executablePath;
|
|
6677
|
-
pathDirs;
|
|
6678
|
-
envOverride;
|
|
6679
|
-
configOverrides;
|
|
6680
|
-
constructor(executablePath = null, env, configOverrides) {
|
|
6681
|
-
if (executablePath) {
|
|
6682
|
-
this.executablePath = executablePath;
|
|
6683
|
-
this.pathDirs = [];
|
|
6684
|
-
} else {
|
|
6685
|
-
const resolved = findCodexPath();
|
|
6686
|
-
this.executablePath = resolved.executablePath;
|
|
6687
|
-
this.pathDirs = resolved.pathDirs;
|
|
6688
|
-
}
|
|
6689
|
-
this.envOverride = env;
|
|
6690
|
-
this.configOverrides = configOverrides;
|
|
6691
|
-
}
|
|
6692
|
-
async *run(args) {
|
|
6693
|
-
const commandArgs = ["exec", "--experimental-json"];
|
|
6694
|
-
if (this.configOverrides) {
|
|
6695
|
-
for (const override of serializeConfigOverrides(this.configOverrides)) {
|
|
6696
|
-
commandArgs.push("--config", override);
|
|
6697
|
-
}
|
|
6698
|
-
}
|
|
6699
|
-
if (args.baseUrl) {
|
|
6700
|
-
commandArgs.push(
|
|
6701
|
-
"--config",
|
|
6702
|
-
`openai_base_url=${toTomlValue(args.baseUrl, "openai_base_url")}`
|
|
6703
|
-
);
|
|
6704
|
-
}
|
|
6705
|
-
if (args.model) {
|
|
6706
|
-
commandArgs.push("--model", args.model);
|
|
6707
|
-
}
|
|
6708
|
-
if (args.sandboxMode) {
|
|
6709
|
-
commandArgs.push("--sandbox", args.sandboxMode);
|
|
6710
|
-
}
|
|
6711
|
-
if (args.workingDirectory) {
|
|
6712
|
-
commandArgs.push("--cd", args.workingDirectory);
|
|
6713
|
-
}
|
|
6714
|
-
if (args.additionalDirectories?.length) {
|
|
6715
|
-
for (const dir of args.additionalDirectories) {
|
|
6716
|
-
commandArgs.push("--add-dir", dir);
|
|
6717
|
-
}
|
|
6718
|
-
}
|
|
6719
|
-
if (args.skipGitRepoCheck) {
|
|
6720
|
-
commandArgs.push("--skip-git-repo-check");
|
|
6721
|
-
}
|
|
6722
|
-
if (args.outputSchemaFile) {
|
|
6723
|
-
commandArgs.push("--output-schema", args.outputSchemaFile);
|
|
6724
|
-
}
|
|
6725
|
-
if (args.modelReasoningEffort) {
|
|
6726
|
-
commandArgs.push("--config", `model_reasoning_effort="${args.modelReasoningEffort}"`);
|
|
6727
|
-
}
|
|
6728
|
-
if (args.networkAccessEnabled !== void 0) {
|
|
6729
|
-
commandArgs.push(
|
|
6730
|
-
"--config",
|
|
6731
|
-
`sandbox_workspace_write.network_access=${args.networkAccessEnabled}`
|
|
6732
|
-
);
|
|
6733
|
-
}
|
|
6734
|
-
if (args.webSearchMode) {
|
|
6735
|
-
commandArgs.push("--config", `web_search="${args.webSearchMode}"`);
|
|
6736
|
-
} else if (args.webSearchEnabled === true) {
|
|
6737
|
-
commandArgs.push("--config", `web_search="live"`);
|
|
6738
|
-
} else if (args.webSearchEnabled === false) {
|
|
6739
|
-
commandArgs.push("--config", `web_search="disabled"`);
|
|
6740
|
-
}
|
|
6741
|
-
if (args.approvalPolicy) {
|
|
6742
|
-
commandArgs.push("--config", `approval_policy="${args.approvalPolicy}"`);
|
|
6743
|
-
}
|
|
6744
|
-
if (args.threadId) {
|
|
6745
|
-
commandArgs.push("resume", args.threadId);
|
|
6746
|
-
}
|
|
6747
|
-
if (args.images?.length) {
|
|
6748
|
-
for (const image of args.images) {
|
|
6749
|
-
commandArgs.push("--image", image);
|
|
6750
|
-
}
|
|
6751
|
-
}
|
|
6752
|
-
const env = {};
|
|
6753
|
-
if (this.envOverride) {
|
|
6754
|
-
Object.assign(env, this.envOverride);
|
|
6755
|
-
} else {
|
|
6756
|
-
for (const [key, value] of Object.entries(process.env)) {
|
|
6757
|
-
if (value !== void 0) {
|
|
6758
|
-
env[key] = value;
|
|
6759
|
-
}
|
|
6760
|
-
}
|
|
6761
|
-
}
|
|
6762
|
-
if (!env[INTERNAL_ORIGINATOR_ENV]) {
|
|
6763
|
-
env[INTERNAL_ORIGINATOR_ENV] = TYPESCRIPT_SDK_ORIGINATOR;
|
|
6764
|
-
}
|
|
6765
|
-
if (args.apiKey) {
|
|
6766
|
-
env.CODEX_API_KEY = args.apiKey;
|
|
6767
|
-
}
|
|
6768
|
-
if (this.pathDirs.length > 0) {
|
|
6769
|
-
prependPathDirs(env, this.pathDirs);
|
|
6770
|
-
}
|
|
6771
|
-
const child = spawn(this.executablePath, commandArgs, {
|
|
6772
|
-
env,
|
|
6773
|
-
signal: args.signal
|
|
6774
|
-
});
|
|
6775
|
-
let spawnError = null;
|
|
6776
|
-
child.once("error", (err) => spawnError = err);
|
|
6777
|
-
if (!child.stdin) {
|
|
6778
|
-
child.kill();
|
|
6779
|
-
throw new Error("Child process has no stdin");
|
|
6780
|
-
}
|
|
6781
|
-
child.stdin.write(args.input);
|
|
6782
|
-
child.stdin.end();
|
|
6783
|
-
if (!child.stdout) {
|
|
6784
|
-
child.kill();
|
|
6785
|
-
throw new Error("Child process has no stdout");
|
|
6786
|
-
}
|
|
6787
|
-
const stderrChunks = [];
|
|
6788
|
-
if (child.stderr) {
|
|
6789
|
-
child.stderr.on("data", (data) => {
|
|
6790
|
-
stderrChunks.push(data);
|
|
6791
|
-
});
|
|
6792
|
-
}
|
|
6793
|
-
const exitPromise = new Promise(
|
|
6794
|
-
(resolve2) => {
|
|
6795
|
-
child.once("exit", (code, signal) => {
|
|
6796
|
-
resolve2({ code, signal });
|
|
6797
|
-
});
|
|
6798
|
-
}
|
|
6799
|
-
);
|
|
6800
|
-
const rl = readline2.createInterface({
|
|
6801
|
-
input: child.stdout,
|
|
6802
|
-
crlfDelay: Infinity
|
|
6803
|
-
});
|
|
6804
|
-
try {
|
|
6805
|
-
for await (const line of rl) {
|
|
6806
|
-
yield line;
|
|
6807
|
-
}
|
|
6808
|
-
if (spawnError) throw spawnError;
|
|
6809
|
-
const { code, signal } = await exitPromise;
|
|
6810
|
-
if (code !== 0 || signal) {
|
|
6811
|
-
const stderrBuffer = Buffer.concat(stderrChunks);
|
|
6812
|
-
const detail = signal ? `signal ${signal}` : `code ${code ?? 1}`;
|
|
6813
|
-
throw new Error(`Codex Exec exited with ${detail}: ${stderrBuffer.toString("utf8")}`);
|
|
6814
|
-
}
|
|
6815
|
-
} finally {
|
|
6816
|
-
rl.close();
|
|
6817
|
-
child.removeAllListeners();
|
|
6818
|
-
try {
|
|
6819
|
-
if (!child.killed) child.kill();
|
|
6820
|
-
} catch {
|
|
6821
|
-
}
|
|
6822
|
-
}
|
|
6823
|
-
}
|
|
6824
|
-
};
|
|
6825
|
-
function serializeConfigOverrides(configOverrides) {
|
|
6826
|
-
const overrides = [];
|
|
6827
|
-
flattenConfigOverrides(configOverrides, "", overrides);
|
|
6828
|
-
return overrides;
|
|
6829
|
-
}
|
|
6830
|
-
function flattenConfigOverrides(value, prefix, overrides) {
|
|
6831
|
-
if (!isPlainObject(value)) {
|
|
6832
|
-
if (prefix) {
|
|
6833
|
-
overrides.push(`${prefix}=${toTomlValue(value, prefix)}`);
|
|
6834
|
-
return;
|
|
6835
|
-
} else {
|
|
6836
|
-
throw new Error("Codex config overrides must be a plain object");
|
|
6837
|
-
}
|
|
6838
|
-
}
|
|
6839
|
-
const entries = Object.entries(value);
|
|
6840
|
-
if (!prefix && entries.length === 0) {
|
|
6841
|
-
return;
|
|
6842
|
-
}
|
|
6843
|
-
if (prefix && entries.length === 0) {
|
|
6844
|
-
overrides.push(`${prefix}={}`);
|
|
6845
|
-
return;
|
|
6846
|
-
}
|
|
6847
|
-
for (const [key, child] of entries) {
|
|
6848
|
-
if (!key) {
|
|
6849
|
-
throw new Error("Codex config override keys must be non-empty strings");
|
|
6850
|
-
}
|
|
6851
|
-
if (child === void 0) {
|
|
6852
|
-
continue;
|
|
6853
|
-
}
|
|
6854
|
-
const path3 = prefix ? `${prefix}.${key}` : key;
|
|
6855
|
-
if (isPlainObject(child)) {
|
|
6856
|
-
flattenConfigOverrides(child, path3, overrides);
|
|
6857
|
-
} else {
|
|
6858
|
-
overrides.push(`${path3}=${toTomlValue(child, path3)}`);
|
|
6859
|
-
}
|
|
6860
|
-
}
|
|
6861
|
-
}
|
|
6862
|
-
function toTomlValue(value, path3) {
|
|
6863
|
-
if (typeof value === "string") {
|
|
6864
|
-
return JSON.stringify(value);
|
|
6865
|
-
} else if (typeof value === "number") {
|
|
6866
|
-
if (!Number.isFinite(value)) {
|
|
6867
|
-
throw new Error(`Codex config override at ${path3} must be a finite number`);
|
|
6868
|
-
}
|
|
6869
|
-
return `${value}`;
|
|
6870
|
-
} else if (typeof value === "boolean") {
|
|
6871
|
-
return value ? "true" : "false";
|
|
6872
|
-
} else if (Array.isArray(value)) {
|
|
6873
|
-
const rendered = value.map((item, index) => toTomlValue(item, `${path3}[${index}]`));
|
|
6874
|
-
return `[${rendered.join(", ")}]`;
|
|
6875
|
-
} else if (isPlainObject(value)) {
|
|
6876
|
-
const parts = [];
|
|
6877
|
-
for (const [key, child] of Object.entries(value)) {
|
|
6878
|
-
if (!key) {
|
|
6879
|
-
throw new Error("Codex config override keys must be non-empty strings");
|
|
6880
|
-
}
|
|
6881
|
-
if (child === void 0) {
|
|
6882
|
-
continue;
|
|
6883
|
-
}
|
|
6884
|
-
parts.push(`${formatTomlKey(key)} = ${toTomlValue(child, `${path3}.${key}`)}`);
|
|
6885
|
-
}
|
|
6886
|
-
return `{${parts.join(", ")}}`;
|
|
6887
|
-
} else if (value === null) {
|
|
6888
|
-
throw new Error(`Codex config override at ${path3} cannot be null`);
|
|
6889
|
-
} else {
|
|
6890
|
-
const typeName = typeof value;
|
|
6891
|
-
throw new Error(`Unsupported Codex config override value at ${path3}: ${typeName}`);
|
|
6892
|
-
}
|
|
6893
|
-
}
|
|
6894
|
-
var TOML_BARE_KEY = /^[A-Za-z0-9_-]+$/;
|
|
6895
|
-
function formatTomlKey(key) {
|
|
6896
|
-
return TOML_BARE_KEY.test(key) ? key : JSON.stringify(key);
|
|
6897
|
-
}
|
|
6898
|
-
function isPlainObject(value) {
|
|
6899
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
6900
|
-
}
|
|
6901
|
-
function findCodexPath() {
|
|
6902
|
-
const { platform, arch } = process;
|
|
6903
|
-
let targetTriple = null;
|
|
6904
|
-
switch (platform) {
|
|
6905
|
-
case "linux":
|
|
6906
|
-
case "android":
|
|
6907
|
-
switch (arch) {
|
|
6908
|
-
case "x64":
|
|
6909
|
-
targetTriple = "x86_64-unknown-linux-musl";
|
|
6910
|
-
break;
|
|
6911
|
-
case "arm64":
|
|
6912
|
-
targetTriple = "aarch64-unknown-linux-musl";
|
|
6913
|
-
break;
|
|
6914
|
-
default:
|
|
6915
|
-
break;
|
|
6916
|
-
}
|
|
6917
|
-
break;
|
|
6918
|
-
case "darwin":
|
|
6919
|
-
switch (arch) {
|
|
6920
|
-
case "x64":
|
|
6921
|
-
targetTriple = "x86_64-apple-darwin";
|
|
6922
|
-
break;
|
|
6923
|
-
case "arm64":
|
|
6924
|
-
targetTriple = "aarch64-apple-darwin";
|
|
6925
|
-
break;
|
|
6926
|
-
default:
|
|
6927
|
-
break;
|
|
6928
|
-
}
|
|
6929
|
-
break;
|
|
6930
|
-
case "win32":
|
|
6931
|
-
switch (arch) {
|
|
6932
|
-
case "x64":
|
|
6933
|
-
targetTriple = "x86_64-pc-windows-msvc";
|
|
6934
|
-
break;
|
|
6935
|
-
case "arm64":
|
|
6936
|
-
targetTriple = "aarch64-pc-windows-msvc";
|
|
6937
|
-
break;
|
|
6938
|
-
default:
|
|
6939
|
-
break;
|
|
6940
|
-
}
|
|
6941
|
-
break;
|
|
6942
|
-
default:
|
|
6943
|
-
break;
|
|
6944
|
-
}
|
|
6945
|
-
if (!targetTriple) {
|
|
6946
|
-
throw new Error(`Unsupported platform: ${platform} (${arch})`);
|
|
6947
|
-
}
|
|
6948
|
-
const platformPackage = PLATFORM_PACKAGE_BY_TARGET[targetTriple];
|
|
6949
|
-
if (!platformPackage) {
|
|
6950
|
-
throw new Error(`Unsupported target triple: ${targetTriple}`);
|
|
6951
|
-
}
|
|
6952
|
-
let vendorRoot;
|
|
6953
|
-
try {
|
|
6954
|
-
const codexPackageJsonPath = moduleRequire.resolve(`${CODEX_NPM_NAME}/package.json`);
|
|
6955
|
-
const codexRequire = createRequire(codexPackageJsonPath);
|
|
6956
|
-
const platformPackageJsonPath = codexRequire.resolve(`${platformPackage}/package.json`);
|
|
6957
|
-
vendorRoot = path2.join(path2.dirname(platformPackageJsonPath), "vendor");
|
|
6958
|
-
} catch {
|
|
6959
|
-
throw new Error(
|
|
6960
|
-
`Unable to locate Codex CLI binaries. Ensure ${CODEX_NPM_NAME} is installed with optional dependencies.`
|
|
6961
|
-
);
|
|
6962
|
-
}
|
|
6963
|
-
const codexBinaryName = process.platform === "win32" ? "codex.exe" : "codex";
|
|
6964
|
-
const nativePackage = resolveNativePackage(vendorRoot, targetTriple, codexBinaryName);
|
|
6965
|
-
if (!nativePackage) {
|
|
6966
|
-
throw new Error(
|
|
6967
|
-
`Unable to locate Codex CLI binaries for ${targetTriple}. Ensure ${CODEX_NPM_NAME} is installed with optional dependencies.`
|
|
6968
|
-
);
|
|
6969
|
-
}
|
|
6970
|
-
return nativePackage;
|
|
6971
|
-
}
|
|
6972
|
-
function resolveNativePackage(vendorRoot, targetTriple, codexBinaryName) {
|
|
6973
|
-
const packageRoot = path2.join(vendorRoot, targetTriple);
|
|
6974
|
-
const packageBinaryPath = path2.join(packageRoot, "bin", codexBinaryName);
|
|
6975
|
-
if (isFile(packageBinaryPath) && isFile(path2.join(packageRoot, "codex-package.json"))) {
|
|
6976
|
-
return {
|
|
6977
|
-
executablePath: packageBinaryPath,
|
|
6978
|
-
pathDirs: existingDirs(path2.join(packageRoot, "codex-path"))
|
|
6979
|
-
};
|
|
6980
|
-
}
|
|
6981
|
-
const legacyBinaryPath = path2.join(packageRoot, "codex", codexBinaryName);
|
|
6982
|
-
if (isFile(legacyBinaryPath)) {
|
|
6983
|
-
return {
|
|
6984
|
-
executablePath: legacyBinaryPath,
|
|
6985
|
-
pathDirs: existingDirs(path2.join(packageRoot, "path"))
|
|
6986
|
-
};
|
|
6987
|
-
}
|
|
6988
|
-
return null;
|
|
6989
|
-
}
|
|
6990
|
-
function existingDirs(...dirs) {
|
|
6991
|
-
return dirs.filter(isDirectory);
|
|
6992
|
-
}
|
|
6993
|
-
function prependPathDirs(env, pathDirs, platform = process.platform) {
|
|
6994
|
-
const pathKey = pathEnvKey(env, platform);
|
|
6995
|
-
if (platform === "win32") {
|
|
6996
|
-
for (const key of Object.keys(env)) {
|
|
6997
|
-
if (key.toLowerCase() === "path" && key !== pathKey) {
|
|
6998
|
-
delete env[key];
|
|
6999
|
-
}
|
|
7000
|
-
}
|
|
7001
|
-
}
|
|
7002
|
-
const existingEntries = (env[pathKey] ?? "").split(path2.delimiter).filter((entry) => entry.length > 0 && !pathDirs.includes(entry));
|
|
7003
|
-
env[pathKey] = [...pathDirs, ...existingEntries].join(path2.delimiter);
|
|
7004
|
-
}
|
|
7005
|
-
function pathEnvKey(env, platform) {
|
|
7006
|
-
if (platform !== "win32") {
|
|
7007
|
-
return "PATH";
|
|
7008
|
-
}
|
|
7009
|
-
const matchingKeys = Object.keys(env).filter((key) => key.toLowerCase() === "path");
|
|
7010
|
-
return matchingKeys.includes("Path") ? "Path" : matchingKeys.at(-1) ?? "PATH";
|
|
7011
|
-
}
|
|
7012
|
-
function isFile(filePath) {
|
|
7013
|
-
try {
|
|
7014
|
-
return statSync2(filePath).isFile();
|
|
7015
|
-
} catch {
|
|
7016
|
-
return false;
|
|
7017
|
-
}
|
|
7018
|
-
}
|
|
7019
|
-
function isDirectory(filePath) {
|
|
7020
|
-
try {
|
|
7021
|
-
return statSync2(filePath).isDirectory();
|
|
7022
|
-
} catch {
|
|
7023
|
-
return false;
|
|
7024
|
-
}
|
|
7025
|
-
}
|
|
7026
|
-
var Codex = class {
|
|
7027
|
-
exec;
|
|
7028
|
-
options;
|
|
7029
|
-
constructor(options = {}) {
|
|
7030
|
-
const { codexPathOverride, env, config } = options;
|
|
7031
|
-
this.exec = new CodexExec(codexPathOverride, env, config);
|
|
7032
|
-
this.options = options;
|
|
7033
|
-
}
|
|
7034
|
-
/**
|
|
7035
|
-
* Starts a new conversation with an agent.
|
|
7036
|
-
* @returns A new thread instance.
|
|
7037
|
-
*/
|
|
7038
|
-
startThread(options = {}) {
|
|
7039
|
-
return new Thread(this.exec, this.options, options);
|
|
7040
|
-
}
|
|
7041
|
-
/**
|
|
7042
|
-
* Resumes a conversation with an agent based on the thread id.
|
|
7043
|
-
* Threads are persisted in ~/.codex/sessions.
|
|
7044
|
-
*
|
|
7045
|
-
* @param id The id of the thread to resume.
|
|
7046
|
-
* @returns A new thread instance.
|
|
7047
|
-
*/
|
|
7048
|
-
resumeThread(id, options = {}) {
|
|
7049
|
-
return new Thread(this.exec, this.options, options, id);
|
|
7050
|
-
}
|
|
7051
|
-
};
|
|
7052
|
-
|
|
7053
6546
|
// src/session/runner/codex.ts
|
|
6547
|
+
import { Codex } from "@openai/codex-sdk";
|
|
7054
6548
|
var isRecord2 = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
|
|
7055
6549
|
var str = (v) => typeof v === "string" ? v : void 0;
|
|
7056
6550
|
var compactEnv = (env) => {
|
|
@@ -7177,13 +6671,20 @@ async function* startCodexEvents(config, input, worker2, opts) {
|
|
|
7177
6671
|
const codex = new Codex(env ? { env } : void 0);
|
|
7178
6672
|
const resuming = !config.agentSessionId.startsWith("pending:");
|
|
7179
6673
|
const addDirs = additionalDirs();
|
|
6674
|
+
const sandboxMode = codexSandboxMode(opts.planMode ?? false);
|
|
6675
|
+
const approvalPolicy = codexApprovalPolicy();
|
|
6676
|
+
const networkAccessEnabled = codexNetworkAccess();
|
|
6677
|
+
opts.log(
|
|
6678
|
+
`[codex] sandbox=${sandboxMode} approval=${approvalPolicy}${networkAccessEnabled === void 0 ? "" : ` network=${networkAccessEnabled}`}`
|
|
6679
|
+
);
|
|
7180
6680
|
const threadOptions = {
|
|
7181
6681
|
workingDirectory: config.worktreePath,
|
|
7182
6682
|
skipGitRepoCheck: true,
|
|
7183
|
-
sandboxMode
|
|
7184
|
-
approvalPolicy
|
|
6683
|
+
sandboxMode,
|
|
6684
|
+
approvalPolicy,
|
|
7185
6685
|
...opts.model ? { model: opts.model } : {},
|
|
7186
|
-
...addDirs ? { additionalDirectories: addDirs } : {}
|
|
6686
|
+
...addDirs ? { additionalDirectories: addDirs } : {},
|
|
6687
|
+
...networkAccessEnabled === void 0 ? {} : { networkAccessEnabled }
|
|
7187
6688
|
};
|
|
7188
6689
|
const thread = resuming ? codex.resumeThread(config.agentSessionId, threadOptions) : codex.startThread(threadOptions);
|
|
7189
6690
|
const runInput = opts.planMode ? withPlanPrefix(input) : input;
|
|
@@ -7302,12 +6803,12 @@ var startedItemFromToolUse = (block) => {
|
|
|
7302
6803
|
};
|
|
7303
6804
|
}
|
|
7304
6805
|
if (name === "Edit" || name === "Write" || name === "MultiEdit" || name === "Delete") {
|
|
7305
|
-
const
|
|
6806
|
+
const path = pathOf(input);
|
|
7306
6807
|
return {
|
|
7307
6808
|
type: "file_change",
|
|
7308
6809
|
id,
|
|
7309
6810
|
status: "in_progress",
|
|
7310
|
-
changes:
|
|
6811
|
+
changes: path ? [{ path, kind: fileKindOf(name) }] : []
|
|
7311
6812
|
};
|
|
7312
6813
|
}
|
|
7313
6814
|
const mcp = mcpParts(name);
|
|
@@ -8115,7 +7616,7 @@ var createLiveness = (deps) => {
|
|
|
8115
7616
|
};
|
|
8116
7617
|
|
|
8117
7618
|
// src/worker/session-supervisor.ts
|
|
8118
|
-
import { spawn
|
|
7619
|
+
import { spawn } from "node:child_process";
|
|
8119
7620
|
import { randomUUID } from "node:crypto";
|
|
8120
7621
|
import { existsSync as existsSync5 } from "node:fs";
|
|
8121
7622
|
import { dirname as dirname2, join as join7 } from "node:path";
|
|
@@ -8248,12 +7749,12 @@ var ensureExcluded = (repo, pattern) => {
|
|
|
8248
7749
|
});
|
|
8249
7750
|
if (r.status !== 0) return;
|
|
8250
7751
|
const rel = r.stdout.trim();
|
|
8251
|
-
const
|
|
8252
|
-
const current = existsSync4(
|
|
7752
|
+
const path = isAbsolute2(rel) ? rel : resolve(repo, rel);
|
|
7753
|
+
const current = existsSync4(path) ? readFileSync5(path, "utf8") : "";
|
|
8253
7754
|
if (current.split("\n").includes(pattern)) return;
|
|
8254
|
-
mkdirSync3(dirname(
|
|
7755
|
+
mkdirSync3(dirname(path), { recursive: true });
|
|
8255
7756
|
const sep = current === "" || current.endsWith("\n") ? "" : "\n";
|
|
8256
|
-
appendFileSync(
|
|
7757
|
+
appendFileSync(path, `${sep}${pattern}
|
|
8257
7758
|
`, "utf8");
|
|
8258
7759
|
} catch {
|
|
8259
7760
|
}
|
|
@@ -8300,7 +7801,7 @@ var createSessionSupervisor = (deps) => {
|
|
|
8300
7801
|
const children = /* @__PURE__ */ new Map();
|
|
8301
7802
|
const spawnChild = (sessionId, worktreePath) => {
|
|
8302
7803
|
if (children.has(sessionId)) return;
|
|
8303
|
-
const child =
|
|
7804
|
+
const child = spawn(process.execPath, [binPath(), "session", "run", String(sessionId)], {
|
|
8304
7805
|
detached: true,
|
|
8305
7806
|
stdio: "inherit",
|
|
8306
7807
|
env: { ...process.env, BATON_SERVER: cfg.server, BATON_WORKER_TOKEN: cfg.apiToken }
|
|
@@ -8406,7 +7907,7 @@ var createSessionSupervisor = (deps) => {
|
|
|
8406
7907
|
|
|
8407
7908
|
// src/worker/terminal-manager.ts
|
|
8408
7909
|
import { existsSync as existsSync7 } from "node:fs";
|
|
8409
|
-
import { spawn as
|
|
7910
|
+
import { spawn as spawn2 } from "node-pty";
|
|
8410
7911
|
|
|
8411
7912
|
// ../../node_modules/.pnpm/ws@8.21.0/node_modules/ws/wrapper.mjs
|
|
8412
7913
|
var import_stream2 = __toESM(require_stream(), 1);
|
|
@@ -8445,7 +7946,7 @@ var createTerminalManager = (deps) => {
|
|
|
8445
7946
|
return;
|
|
8446
7947
|
}
|
|
8447
7948
|
const claudeBin = process.env.BATON_CLAUDE_BIN ?? "claude";
|
|
8448
|
-
const term =
|
|
7949
|
+
const term = spawn2(claudeBin, ptyArgs(agentSessionId, hasSessionJsonl(agentSessionId)), {
|
|
8449
7950
|
name: "xterm-color",
|
|
8450
7951
|
cols: 80,
|
|
8451
7952
|
rows: 24,
|
|
@@ -8598,14 +8099,14 @@ import { existsSync as existsSync8, mkdirSync as mkdirSync4, readFileSync as rea
|
|
|
8598
8099
|
import { homedir as homedir4 } from "node:os";
|
|
8599
8100
|
import { dirname as dirname3, join as join9 } from "node:path";
|
|
8600
8101
|
var machineIdPath = (env = process.env) => join9(env.XDG_DATA_HOME ?? join9(env.HOME ?? homedir4(), ".local/share"), "baton", "machine-id");
|
|
8601
|
-
var readOrCreateMachineId = (
|
|
8602
|
-
if (existsSync8(
|
|
8603
|
-
const s = readFileSync6(
|
|
8102
|
+
var readOrCreateMachineId = (path = machineIdPath()) => {
|
|
8103
|
+
if (existsSync8(path)) {
|
|
8104
|
+
const s = readFileSync6(path, "utf8").trim();
|
|
8604
8105
|
if (s) return s;
|
|
8605
8106
|
}
|
|
8606
8107
|
const id = randomUUID2();
|
|
8607
|
-
mkdirSync4(dirname3(
|
|
8608
|
-
writeFileSync5(
|
|
8108
|
+
mkdirSync4(dirname3(path), { recursive: true });
|
|
8109
|
+
writeFileSync5(path, `${id}
|
|
8609
8110
|
`, "utf8");
|
|
8610
8111
|
return id;
|
|
8611
8112
|
};
|