@aiden-ade/sandbox-agent 0.1.7 → 0.1.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.cjs +208 -6
- package/package.json +13 -11
package/dist/index.cjs
CHANGED
|
@@ -5160,6 +5160,7 @@ function createGenericCliBackend(options) {
|
|
|
5160
5160
|
runtimeSessionId: state.runtimeSessionId
|
|
5161
5161
|
});
|
|
5162
5162
|
}
|
|
5163
|
+
await options.afterExit?.(context, state);
|
|
5163
5164
|
const hasRenderableTurn = state.summary.trim().length > 0 || state.iterations > 0;
|
|
5164
5165
|
if (hasRenderableTurn) {
|
|
5165
5166
|
await presenter.onTurnComplete([]);
|
|
@@ -5551,6 +5552,110 @@ function parseCodexStructuredLine(line, context, state) {
|
|
|
5551
5552
|
break;
|
|
5552
5553
|
}
|
|
5553
5554
|
}
|
|
5555
|
+
function parseJsonObject(value2) {
|
|
5556
|
+
try {
|
|
5557
|
+
const parsed = JSON.parse(value2);
|
|
5558
|
+
return typeof parsed === "object" && parsed !== null ? parsed : null;
|
|
5559
|
+
} catch {
|
|
5560
|
+
return null;
|
|
5561
|
+
}
|
|
5562
|
+
}
|
|
5563
|
+
function parseMaybeJson(value2) {
|
|
5564
|
+
if (typeof value2 !== "string") return value2;
|
|
5565
|
+
return parseJsonObject(value2) ?? value2;
|
|
5566
|
+
}
|
|
5567
|
+
function normalizeCodexMcpToolResult(output) {
|
|
5568
|
+
if (typeof output !== "string") return JSON.stringify(output ?? {}, null, 2);
|
|
5569
|
+
const outputMarker = "\nOutput:\n";
|
|
5570
|
+
const raw = output.includes(outputMarker) ? output.slice(output.indexOf(outputMarker) + outputMarker.length).trim() : output.trim();
|
|
5571
|
+
let parsed;
|
|
5572
|
+
try {
|
|
5573
|
+
parsed = JSON.parse(raw);
|
|
5574
|
+
} catch {
|
|
5575
|
+
return raw;
|
|
5576
|
+
}
|
|
5577
|
+
if (Array.isArray(parsed)) {
|
|
5578
|
+
const textBlocks = parsed.filter(
|
|
5579
|
+
(entry) => typeof entry === "object" && entry !== null && "text" in entry
|
|
5580
|
+
).map((entry) => typeof entry.text === "string" ? entry.text : "").filter(Boolean);
|
|
5581
|
+
if (textBlocks.length > 0) return textBlocks.join("\n");
|
|
5582
|
+
}
|
|
5583
|
+
return raw;
|
|
5584
|
+
}
|
|
5585
|
+
function findCodexSessionLog(runtimeSessionId, codexHome) {
|
|
5586
|
+
if (!runtimeSessionId || !(0, import_fs.existsSync)(codexHome)) return null;
|
|
5587
|
+
const root = (0, import_path.join)(codexHome, "sessions");
|
|
5588
|
+
if (!(0, import_fs.existsSync)(root)) return null;
|
|
5589
|
+
const matches = [];
|
|
5590
|
+
const stack = [root];
|
|
5591
|
+
while (stack.length > 0) {
|
|
5592
|
+
const dir = stack.pop();
|
|
5593
|
+
let entries;
|
|
5594
|
+
try {
|
|
5595
|
+
entries = (0, import_fs.readdirSync)(dir, { withFileTypes: true });
|
|
5596
|
+
} catch {
|
|
5597
|
+
continue;
|
|
5598
|
+
}
|
|
5599
|
+
for (const entry of entries) {
|
|
5600
|
+
const path = (0, import_path.join)(dir, entry.name);
|
|
5601
|
+
if (entry.isDirectory()) {
|
|
5602
|
+
stack.push(path);
|
|
5603
|
+
} else if (entry.isFile() && entry.name.includes(runtimeSessionId) && entry.name.endsWith(".jsonl")) {
|
|
5604
|
+
try {
|
|
5605
|
+
matches.push({ path, mtimeMs: (0, import_fs.statSync)(path).mtimeMs });
|
|
5606
|
+
} catch {
|
|
5607
|
+
matches.push({ path, mtimeMs: 0 });
|
|
5608
|
+
}
|
|
5609
|
+
}
|
|
5610
|
+
}
|
|
5611
|
+
}
|
|
5612
|
+
matches.sort((a, b) => b.mtimeMs - a.mtimeMs);
|
|
5613
|
+
return matches[0]?.path ?? null;
|
|
5614
|
+
}
|
|
5615
|
+
async function replayCodexMcpToolEventsFromSessionLog(context, state) {
|
|
5616
|
+
const runtimeSessionId = state.runtimeSessionId;
|
|
5617
|
+
if (!runtimeSessionId) return;
|
|
5618
|
+
const codexHome = context.env.CODEX_HOME || process.env.CODEX_HOME || (0, import_path.join)((0, import_os.homedir)(), ".codex");
|
|
5619
|
+
const logPath = findCodexSessionLog(runtimeSessionId, codexHome);
|
|
5620
|
+
if (!logPath) return;
|
|
5621
|
+
const emittedToolIds = /* @__PURE__ */ new Set();
|
|
5622
|
+
const lines = (0, import_fs.readFileSync)(logPath, "utf8").split(/\r?\n/).filter(Boolean);
|
|
5623
|
+
for (const line of lines) {
|
|
5624
|
+
const entry = parseJsonObject(line);
|
|
5625
|
+
const payload = entry && typeof entry.payload === "object" && entry.payload !== null ? entry.payload : null;
|
|
5626
|
+
if (!payload) continue;
|
|
5627
|
+
if (payload.type === "function_call") {
|
|
5628
|
+
const callId = typeof payload.call_id === "string" ? payload.call_id : "";
|
|
5629
|
+
const name = typeof payload.name === "string" ? payload.name : "";
|
|
5630
|
+
const namespace = typeof payload.namespace === "string" ? payload.namespace : "";
|
|
5631
|
+
if (!callId || !name || !namespace.startsWith("mcp__")) continue;
|
|
5632
|
+
const toolName = `${namespace}${name}`;
|
|
5633
|
+
context.presenter.onToolUse(toolName, parseMaybeJson(payload.arguments), callId);
|
|
5634
|
+
emittedToolIds.add(callId);
|
|
5635
|
+
continue;
|
|
5636
|
+
}
|
|
5637
|
+
if (payload.type === "tool_search_call") {
|
|
5638
|
+
const callId = typeof payload.call_id === "string" ? payload.call_id : "";
|
|
5639
|
+
if (!callId) continue;
|
|
5640
|
+
context.presenter.onToolUse("tool_search", payload.arguments ?? {}, callId);
|
|
5641
|
+
emittedToolIds.add(callId);
|
|
5642
|
+
}
|
|
5643
|
+
}
|
|
5644
|
+
if (emittedToolIds.size === 0) return;
|
|
5645
|
+
for (const line of lines) {
|
|
5646
|
+
const entry = parseJsonObject(line);
|
|
5647
|
+
const payload = entry && typeof entry.payload === "object" && entry.payload !== null ? entry.payload : null;
|
|
5648
|
+
if (!payload || payload.type !== "function_call_output" && payload.type !== "tool_search_output") continue;
|
|
5649
|
+
const callId = typeof payload.call_id === "string" ? payload.call_id : "";
|
|
5650
|
+
if (!emittedToolIds.has(callId)) continue;
|
|
5651
|
+
try {
|
|
5652
|
+
const result = payload.type === "tool_search_output" ? JSON.stringify(payload.tools ?? [], null, 2) : normalizeCodexMcpToolResult(payload.output);
|
|
5653
|
+
context.presenter.onToolResult?.(callId, result);
|
|
5654
|
+
} catch {
|
|
5655
|
+
context.presenter.onToolResult?.(callId, String(payload.output ?? ""));
|
|
5656
|
+
}
|
|
5657
|
+
}
|
|
5658
|
+
}
|
|
5554
5659
|
function extractCursorToolEntry(toolCall) {
|
|
5555
5660
|
const [rawName, rawPayload] = Object.entries(toolCall)[0] ?? [];
|
|
5556
5661
|
if (!rawName || typeof rawPayload !== "object" || rawPayload === null) return null;
|
|
@@ -5892,10 +5997,13 @@ function kimiSessionId(cwd) {
|
|
|
5892
5997
|
}
|
|
5893
5998
|
return (0, import_crypto.createHash)("md5").update(resolved).digest("hex");
|
|
5894
5999
|
}
|
|
6000
|
+
function shouldEnableKimiCliThinking(model2) {
|
|
6001
|
+
return model2?.trim() === "kimi-k2.6-thinking";
|
|
6002
|
+
}
|
|
5895
6003
|
function resolveKimiCliModelArg(model2) {
|
|
5896
6004
|
const trimmed = model2?.trim();
|
|
5897
6005
|
if (!trimmed) return void 0;
|
|
5898
|
-
if (trimmed === "kimi-latest" || trimmed === "kimi-k2.5" || trimmed === "kimi-k2.6") {
|
|
6006
|
+
if (trimmed === "kimi-latest" || trimmed === "kimi-k2.5" || trimmed === "kimi-k2.6" || shouldEnableKimiCliThinking(trimmed)) {
|
|
5899
6007
|
return void 0;
|
|
5900
6008
|
}
|
|
5901
6009
|
if (trimmed.startsWith("claude-")) return void 0;
|
|
@@ -5921,6 +6029,11 @@ function parseKimiStructuredLine(line, context, state) {
|
|
|
5921
6029
|
const contentBlocks = Array.isArray(parsed.content) ? parsed.content : [];
|
|
5922
6030
|
const toolCalls = Array.isArray(parsed.tool_calls) ? parsed.tool_calls : [];
|
|
5923
6031
|
if (role === "assistant") {
|
|
6032
|
+
const thinking = contentBlocks.filter((b) => b.type === "think" && typeof b.think === "string").map((b) => b.think).join("");
|
|
6033
|
+
if (thinking) {
|
|
6034
|
+
state.iterations = Math.max(state.iterations, 1);
|
|
6035
|
+
void presenter.onThinking(thinking);
|
|
6036
|
+
}
|
|
5924
6037
|
if (toolCalls.length > 0) {
|
|
5925
6038
|
state.iterations = Math.max(state.iterations, 1);
|
|
5926
6039
|
for (const tc of toolCalls) {
|
|
@@ -5972,6 +6085,9 @@ function createKimiCliBackend(command = "kimi", defaultArgs = []) {
|
|
|
5972
6085
|
];
|
|
5973
6086
|
const resumeId = context.config.runtimeSessionId?.trim() || context.config.providerSessionId?.trim();
|
|
5974
6087
|
if (resumeId) args.push("--session", resumeId);
|
|
6088
|
+
if (shouldEnableKimiCliThinking(context.config.selectedModel)) {
|
|
6089
|
+
args.push("--thinking");
|
|
6090
|
+
}
|
|
5975
6091
|
const model2 = resolveKimiCliModelArg(context.config.selectedModel);
|
|
5976
6092
|
if (model2) args.push("--model", model2);
|
|
5977
6093
|
return [...args, ...defaultArgs, "--prompt", prompt];
|
|
@@ -6308,7 +6424,8 @@ function createCodexRuntimeBackend(command = "codex", defaultArgs = []) {
|
|
|
6308
6424
|
const basePrompt = buildPromptWithSystem(ctx.config, ctx.promptText);
|
|
6309
6425
|
return ctx.config.mode === "plan" ? buildPlanModePrefix(basePrompt) : basePrompt;
|
|
6310
6426
|
},
|
|
6311
|
-
parseStructuredLine: parseCodexStructuredLine
|
|
6427
|
+
parseStructuredLine: parseCodexStructuredLine,
|
|
6428
|
+
afterExit: replayCodexMcpToolEventsFromSessionLog
|
|
6312
6429
|
}).run(context);
|
|
6313
6430
|
} finally {
|
|
6314
6431
|
cleanup();
|
|
@@ -6316,12 +6433,37 @@ function createCodexRuntimeBackend(command = "codex", defaultArgs = []) {
|
|
|
6316
6433
|
}
|
|
6317
6434
|
};
|
|
6318
6435
|
}
|
|
6436
|
+
function createCopilotCliBackend(command = "copilot", defaultArgs = []) {
|
|
6437
|
+
return createGenericCliBackend({
|
|
6438
|
+
kind: "copilot_cli",
|
|
6439
|
+
supportTier: "text",
|
|
6440
|
+
command,
|
|
6441
|
+
args: [],
|
|
6442
|
+
buildArgs: (context, prompt) => {
|
|
6443
|
+
const args = [
|
|
6444
|
+
"--autopilot",
|
|
6445
|
+
"--yolo",
|
|
6446
|
+
"--max-autopilot-continues",
|
|
6447
|
+
"20",
|
|
6448
|
+
"-s",
|
|
6449
|
+
"-p",
|
|
6450
|
+
prompt
|
|
6451
|
+
];
|
|
6452
|
+
if (context.config.selectedModel?.trim()) {
|
|
6453
|
+
args.push("--model", context.config.selectedModel.trim());
|
|
6454
|
+
}
|
|
6455
|
+
return [...args, ...defaultArgs];
|
|
6456
|
+
}
|
|
6457
|
+
});
|
|
6458
|
+
}
|
|
6319
6459
|
var DEFAULT_MODEL = "claude-sonnet-4-6";
|
|
6320
6460
|
var DROID_DEFAULT_MODEL = "claude-opus-4-7";
|
|
6321
6461
|
function defaultSelectedModelForBackend(backendKind2) {
|
|
6322
6462
|
switch (backendKind2) {
|
|
6323
6463
|
case "droid_cli":
|
|
6324
6464
|
return DROID_DEFAULT_MODEL;
|
|
6465
|
+
case "copilot_cli":
|
|
6466
|
+
return "claude-sonnet-4.5";
|
|
6325
6467
|
case "kimi_cli":
|
|
6326
6468
|
return void 0;
|
|
6327
6469
|
default:
|
|
@@ -6424,6 +6566,7 @@ var BaseMachineAgent = class _BaseMachineAgent {
|
|
|
6424
6566
|
case "gemini_cli":
|
|
6425
6567
|
case "opencode_cli":
|
|
6426
6568
|
return "structured";
|
|
6569
|
+
case "copilot_cli":
|
|
6427
6570
|
case "generic_cli":
|
|
6428
6571
|
default:
|
|
6429
6572
|
return "text";
|
|
@@ -6469,7 +6612,7 @@ Prefer relative paths and keep your work scoped to this project.`
|
|
|
6469
6612
|
const promptText = this.buildPromptText(runtimeConfig);
|
|
6470
6613
|
const runtimeCommand = runtimeConfig.runtimeCommand || this.runtime.runtimeCommand;
|
|
6471
6614
|
const runtimeArgs = runtimeConfig.runtimeArgs || this.runtime.runtimeArgs || [];
|
|
6472
|
-
const backend = backendKind2 === "claude_cli" ? createClaudeCliBackend(runtimeCommand || "claude", runtimeArgs) : backendKind2 === "codex_app_server" ? createCodexRuntimeBackend(runtimeCommand || "codex", runtimeArgs) : backendKind2 === "cursor_agent_cli" ? createCursorAgentCliBackend(runtimeCommand || "cursor-agent", runtimeArgs) : backendKind2 === "gemini_cli" ? createGeminiCliBackend(runtimeCommand || "gemini", runtimeArgs) : backendKind2 === "droid_cli" ? createDroidCliBackend(runtimeCommand || "droid", runtimeArgs) : backendKind2 === "opencode_cli" ? createOpencodeCliBackend(runtimeCommand || "opencode", runtimeArgs) : backendKind2 === "kimi_cli" ? createKimiCliBackend(runtimeCommand || "kimi", runtimeArgs) : createGenericCliPassthroughBackend(runtimeCommand || "generic-cli", runtimeArgs);
|
|
6615
|
+
const backend = backendKind2 === "claude_cli" ? createClaudeCliBackend(runtimeCommand || "claude", runtimeArgs) : backendKind2 === "codex_app_server" ? createCodexRuntimeBackend(runtimeCommand || "codex", runtimeArgs) : backendKind2 === "copilot_cli" ? createCopilotCliBackend(runtimeCommand || "copilot", runtimeArgs) : backendKind2 === "cursor_agent_cli" ? createCursorAgentCliBackend(runtimeCommand || "cursor-agent", runtimeArgs) : backendKind2 === "gemini_cli" ? createGeminiCliBackend(runtimeCommand || "gemini", runtimeArgs) : backendKind2 === "droid_cli" ? createDroidCliBackend(runtimeCommand || "droid", runtimeArgs) : backendKind2 === "opencode_cli" ? createOpencodeCliBackend(runtimeCommand || "opencode", runtimeArgs) : backendKind2 === "kimi_cli" ? createKimiCliBackend(runtimeCommand || "kimi", runtimeArgs) : createGenericCliPassthroughBackend(runtimeCommand || "generic-cli", runtimeArgs);
|
|
6473
6616
|
let lastResult = null;
|
|
6474
6617
|
for (let attempt = 0; attempt <= _BaseMachineAgent.MAX_RETRIES; attempt++) {
|
|
6475
6618
|
if (this.abortController?.signal.aborted) break;
|
|
@@ -6607,11 +6750,61 @@ Prefer relative paths and keep your work scoped to this project.`
|
|
|
6607
6750
|
};
|
|
6608
6751
|
|
|
6609
6752
|
// src/core-agent.ts
|
|
6610
|
-
var CoreAgent = class extends BaseMachineAgent {
|
|
6753
|
+
var CoreAgent = class _CoreAgent extends BaseMachineAgent {
|
|
6611
6754
|
childProcess = null;
|
|
6755
|
+
_aborted = false;
|
|
6756
|
+
/** How long to wait after SIGTERM before escalating to SIGKILL. */
|
|
6757
|
+
static SIGKILL_DELAY_MS = 3e3;
|
|
6612
6758
|
constructor(presenter, runtime) {
|
|
6613
6759
|
super(presenter, runtime);
|
|
6614
6760
|
}
|
|
6761
|
+
abort() {
|
|
6762
|
+
this._aborted = true;
|
|
6763
|
+
super.abort();
|
|
6764
|
+
}
|
|
6765
|
+
kill() {
|
|
6766
|
+
this._aborted = true;
|
|
6767
|
+
super.abort();
|
|
6768
|
+
const child = this.childProcess;
|
|
6769
|
+
if (!child || child.killed || child.exitCode !== null) return false;
|
|
6770
|
+
return this.killChildProcess(child);
|
|
6771
|
+
}
|
|
6772
|
+
killChildProcess(child) {
|
|
6773
|
+
const pid = child.pid;
|
|
6774
|
+
if (!pid) return false;
|
|
6775
|
+
console.info("[CoreAgent] Killing agent process", { pid });
|
|
6776
|
+
try {
|
|
6777
|
+
if (process.platform === "win32") {
|
|
6778
|
+
child.kill("SIGTERM");
|
|
6779
|
+
} else {
|
|
6780
|
+
process.kill(-pid, "SIGTERM");
|
|
6781
|
+
}
|
|
6782
|
+
} catch (err) {
|
|
6783
|
+
if (err.code !== "ESRCH") {
|
|
6784
|
+
console.warn("[CoreAgent] SIGTERM failed", { pid, err });
|
|
6785
|
+
}
|
|
6786
|
+
try {
|
|
6787
|
+
child.kill("SIGTERM");
|
|
6788
|
+
} catch {
|
|
6789
|
+
}
|
|
6790
|
+
}
|
|
6791
|
+
setTimeout(() => {
|
|
6792
|
+
if (child.killed || child.exitCode !== null) return;
|
|
6793
|
+
console.warn("[CoreAgent] Escalating to SIGKILL", { pid });
|
|
6794
|
+
try {
|
|
6795
|
+
if (process.platform === "win32") {
|
|
6796
|
+
child.kill("SIGKILL");
|
|
6797
|
+
} else {
|
|
6798
|
+
process.kill(-pid, "SIGKILL");
|
|
6799
|
+
}
|
|
6800
|
+
} catch (err) {
|
|
6801
|
+
if (err.code !== "ESRCH") {
|
|
6802
|
+
console.warn("[CoreAgent] SIGKILL failed", { pid, err });
|
|
6803
|
+
}
|
|
6804
|
+
}
|
|
6805
|
+
}, _CoreAgent.SIGKILL_DELAY_MS);
|
|
6806
|
+
return true;
|
|
6807
|
+
}
|
|
6615
6808
|
// ── Interactive tool response (WS relay → stdin) ───────────────────────
|
|
6616
6809
|
/**
|
|
6617
6810
|
* Send a tool_result to the CLI's stdin (stream-json format).
|
|
@@ -6652,6 +6845,12 @@ var CoreAgent = class extends BaseMachineAgent {
|
|
|
6652
6845
|
child.on("exit", () => {
|
|
6653
6846
|
this.childProcess = null;
|
|
6654
6847
|
});
|
|
6848
|
+
child.on("error", () => {
|
|
6849
|
+
this.childProcess = null;
|
|
6850
|
+
});
|
|
6851
|
+
if (this._aborted) {
|
|
6852
|
+
this.killChildProcess(child);
|
|
6853
|
+
}
|
|
6655
6854
|
};
|
|
6656
6855
|
}
|
|
6657
6856
|
async buildCliEnvironment() {
|
|
@@ -10447,7 +10646,7 @@ var WSClient = class {
|
|
|
10447
10646
|
};
|
|
10448
10647
|
|
|
10449
10648
|
// src/version.ts
|
|
10450
|
-
var AGENT_VERSION = "0.1.
|
|
10649
|
+
var AGENT_VERSION = "0.1.8";
|
|
10451
10650
|
|
|
10452
10651
|
// src/sandbox.ts
|
|
10453
10652
|
async function runSandbox(config) {
|
|
@@ -10479,7 +10678,10 @@ async function runSandbox(config) {
|
|
|
10479
10678
|
},
|
|
10480
10679
|
onStop: () => {
|
|
10481
10680
|
console.info("[sandbox] Stop signal received");
|
|
10482
|
-
if (currentAgent)
|
|
10681
|
+
if (currentAgent) {
|
|
10682
|
+
const killed = currentAgent.kill();
|
|
10683
|
+
if (!killed) currentAgent.abort();
|
|
10684
|
+
}
|
|
10483
10685
|
},
|
|
10484
10686
|
onToolResponse: (toolId, response) => {
|
|
10485
10687
|
if (currentAgent) {
|
package/package.json
CHANGED
|
@@ -1,27 +1,29 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aiden-ade/sandbox-agent",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.8",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"bin": {
|
|
6
6
|
"aiden-agent": "./dist/index.cjs"
|
|
7
7
|
},
|
|
8
|
-
"files": [
|
|
8
|
+
"files": [
|
|
9
|
+
"dist/"
|
|
10
|
+
],
|
|
9
11
|
"publishConfig": {
|
|
10
12
|
"access": "public"
|
|
11
13
|
},
|
|
12
|
-
"scripts": {
|
|
13
|
-
"build": "tsup",
|
|
14
|
-
"dev": "tsx src/index.ts",
|
|
15
|
-
"type-check": "tsc --noEmit"
|
|
16
|
-
},
|
|
17
14
|
"dependencies": {},
|
|
18
15
|
"devDependencies": {
|
|
19
|
-
"@aiden/agent-core": "workspace:*",
|
|
20
|
-
"@aiden/shared": "workspace:*",
|
|
21
16
|
"socket.io-client": "^4.8.0",
|
|
22
17
|
"@types/node": "^22.0.0",
|
|
23
18
|
"tsup": "^8.5.1",
|
|
24
19
|
"tsx": "^4.19.0",
|
|
25
|
-
"typescript": "~5.9.3"
|
|
20
|
+
"typescript": "~5.9.3",
|
|
21
|
+
"@aiden/agent-core": "0.1.0",
|
|
22
|
+
"@aiden/shared": "0.1.0"
|
|
23
|
+
},
|
|
24
|
+
"scripts": {
|
|
25
|
+
"build": "tsup",
|
|
26
|
+
"dev": "tsx src/index.ts",
|
|
27
|
+
"type-check": "tsc --noEmit"
|
|
26
28
|
}
|
|
27
|
-
}
|
|
29
|
+
}
|