@khalilgharbaoui/opencode-claude-code-plugin 0.39.0 → 0.41.0
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.d.ts +5 -0
- package/dist/index.js +383 -166
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/skills/claude-code-plugin/SKILL.md +51 -8
package/dist/index.js
CHANGED
|
@@ -1728,6 +1728,43 @@ function cliSupportsThinking(v) {
|
|
|
1728
1728
|
return gte(v, { major: 2, minor: 0, patch: 0 });
|
|
1729
1729
|
}
|
|
1730
1730
|
var flagSupport = /* @__PURE__ */ new Map();
|
|
1731
|
+
var headlessSupport = /* @__PURE__ */ new Map();
|
|
1732
|
+
function detectHeadlessSupport(cliPath) {
|
|
1733
|
+
const key = `${cliPath}\0headless`;
|
|
1734
|
+
const cached = headlessSupport.get(key);
|
|
1735
|
+
if (cached) return cached;
|
|
1736
|
+
let deadlineKill = false;
|
|
1737
|
+
const promise = (async () => {
|
|
1738
|
+
try {
|
|
1739
|
+
const execution = execFileAsync(cliPath, [
|
|
1740
|
+
"--print",
|
|
1741
|
+
"--input-format",
|
|
1742
|
+
"stream-json",
|
|
1743
|
+
"--output-format",
|
|
1744
|
+
"stream-json",
|
|
1745
|
+
"--help"
|
|
1746
|
+
], { timeout: probeTimeoutMs, killSignal: "SIGKILL", maxBuffer: 4 * 1024 * 1024 });
|
|
1747
|
+
execution.child.stdin?.end();
|
|
1748
|
+
const { stdout } = await execution;
|
|
1749
|
+
if (!/^\s*Usage:/im.test(stdout) || !/^\s*Options:/im.test(stdout)) return "unknown";
|
|
1750
|
+
const flags = ["--print", "--input-format", "--output-format"];
|
|
1751
|
+
if (!flags.every((flag) => new RegExp(`^\\s+(?:-[A-Za-z],\\s+)?${flag}(?:\\s|,|$)`, "m").test(stdout))) {
|
|
1752
|
+
return "unsupported";
|
|
1753
|
+
}
|
|
1754
|
+
return stdout.includes("stream-json") ? "supported" : "unknown";
|
|
1755
|
+
} catch (error) {
|
|
1756
|
+
deadlineKill = killedByDeadline(error);
|
|
1757
|
+
const stderr = error?.stderr;
|
|
1758
|
+
if (typeof stderr === "string" && /^(?:error: )?(?:unknown|unrecognized|unsupported) option ['"]?--(?:print|input-format|output-format)(?:['"\s]|$)/im.test(stderr)) {
|
|
1759
|
+
return "unsupported";
|
|
1760
|
+
}
|
|
1761
|
+
return "unknown";
|
|
1762
|
+
}
|
|
1763
|
+
})();
|
|
1764
|
+
headlessSupport.set(key, promise);
|
|
1765
|
+
forgetDeadlineKill(headlessSupport, key, promise, () => deadlineKill);
|
|
1766
|
+
return promise;
|
|
1767
|
+
}
|
|
1731
1768
|
function detectCliSupportsFlag(cliPath, flag) {
|
|
1732
1769
|
const key = `${cliPath}\0${flag}`;
|
|
1733
1770
|
const cached = flagSupport.get(key);
|
|
@@ -4887,6 +4924,9 @@ function noteInteractiveProcessExit(sessionKey2, ap, code) {
|
|
|
4887
4924
|
if (activeProcesses.get(sessionKey2) !== ap) return;
|
|
4888
4925
|
cancelIdleProcessEviction(sessionKey2);
|
|
4889
4926
|
activeProcesses.delete(sessionKey2);
|
|
4927
|
+
if (getPendingProxyCalls(sessionKey2).length > 0) {
|
|
4928
|
+
rejectAllPendingProxyCallsForSession(sessionKey2, new Error(CHILD_EXITED_MESSAGE));
|
|
4929
|
+
}
|
|
4890
4930
|
if (code !== 0 && code !== null) {
|
|
4891
4931
|
claudeSessions.delete(sessionKey2);
|
|
4892
4932
|
forgetResumePoint(sessionKey2);
|
|
@@ -6333,6 +6373,10 @@ async function fetchPlanUsage(cliPath, options = {}) {
|
|
|
6333
6373
|
const timeoutMs = options.timeoutMs ?? 2e4;
|
|
6334
6374
|
const run = options.runImpl ?? runCli;
|
|
6335
6375
|
try {
|
|
6376
|
+
const support = options.headlessSupportImpl ?? (options.runImpl ? void 0 : detectHeadlessSupport);
|
|
6377
|
+
if (support && await support(cliPath) === "unsupported") {
|
|
6378
|
+
return { status: "failed", error: "Plan usage is unavailable: this Claude CLI does not support headless output. Check usage in the Claude CLI directly." };
|
|
6379
|
+
}
|
|
6336
6380
|
const env = claudeSpawnEnv({ ignoreAnthropicApiKey: options.ignoreAnthropicApiKey });
|
|
6337
6381
|
const stdout = await run(
|
|
6338
6382
|
cliPath,
|
|
@@ -8052,6 +8096,9 @@ The complete prior conversation appears above. The synthesis instructions follow
|
|
|
8052
8096
|
`
|
|
8053
8097
|
});
|
|
8054
8098
|
}
|
|
8099
|
+
if (opts.compactionInstructions?.trim()) {
|
|
8100
|
+
content.push({ type: "text", text: opts.compactionInstructions });
|
|
8101
|
+
}
|
|
8055
8102
|
} else if (includeHistoryContext) {
|
|
8056
8103
|
const historyContext = compactConversationHistory(prompt);
|
|
8057
8104
|
if (historyContext) {
|
|
@@ -8772,6 +8819,8 @@ var ClaudeSession = class {
|
|
|
8772
8819
|
trustMoves = 0;
|
|
8773
8820
|
trustMovedAt = 0;
|
|
8774
8821
|
turn = null;
|
|
8822
|
+
/** The running turn's read state, shared with `flushTranscript`. */
|
|
8823
|
+
scan = null;
|
|
8775
8824
|
turnDenied = [];
|
|
8776
8825
|
abandonTurn = false;
|
|
8777
8826
|
o;
|
|
@@ -9084,67 +9133,103 @@ var ClaudeSession = class {
|
|
|
9084
9133
|
this.proc.terminal.write(prompt);
|
|
9085
9134
|
}
|
|
9086
9135
|
await this.submitTurn();
|
|
9087
|
-
|
|
9088
|
-
|
|
9089
|
-
|
|
9090
|
-
|
|
9091
|
-
|
|
9136
|
+
const scan = {
|
|
9137
|
+
onRecord,
|
|
9138
|
+
stopReason: null,
|
|
9139
|
+
stopSeenAt: 0,
|
|
9140
|
+
end: null,
|
|
9141
|
+
sawUserRecord: false,
|
|
9142
|
+
lastBeat: Date.now()
|
|
9143
|
+
};
|
|
9144
|
+
this.scan = scan;
|
|
9092
9145
|
const deadline = Date.now() + timeout;
|
|
9093
9146
|
while (Date.now() < deadline) {
|
|
9094
9147
|
await delay(this.o.pollMs);
|
|
9095
9148
|
if (this.aborted) throw new Error("aborted mid-turn");
|
|
9096
9149
|
const fatalNow = this.fatalError();
|
|
9097
9150
|
if (fatalNow) throw fatalNow;
|
|
9098
|
-
|
|
9099
|
-
|
|
9100
|
-
|
|
9101
|
-
|
|
9102
|
-
|
|
9103
|
-
|
|
9104
|
-
|
|
9105
|
-
try {
|
|
9106
|
-
rec = JSON.parse(s);
|
|
9107
|
-
} catch {
|
|
9108
|
-
}
|
|
9109
|
-
onRecord(s, rec);
|
|
9110
|
-
if (!rec) continue;
|
|
9111
|
-
if (rec.type === "assistant" && rec.message) {
|
|
9112
|
-
const reason = rec.message.stop_reason;
|
|
9113
|
-
if (typeof reason === "string") {
|
|
9114
|
-
stopReason = TERMINAL_STOP.has(reason) ? reason : null;
|
|
9115
|
-
}
|
|
9116
|
-
} else if (rec.type === "user") {
|
|
9117
|
-
if (sawUserRecord && isInterruptRecord(rec)) end = "interrupted";
|
|
9118
|
-
sawUserRecord = true;
|
|
9119
|
-
} else if ((sawUserRecord || stopReason) && isTurnDurationRecord(rec)) {
|
|
9120
|
-
end = stopReason ? "stop" : "ended";
|
|
9121
|
-
}
|
|
9122
|
-
this.cursor = i + 1;
|
|
9151
|
+
if (this.scanTranscript() || scan.end) {
|
|
9152
|
+
if (scan.end) {
|
|
9153
|
+
return {
|
|
9154
|
+
stopReason: scan.end === "stop" ? scan.stopReason : null,
|
|
9155
|
+
end: scan.end,
|
|
9156
|
+
denied: this.turnDenied
|
|
9157
|
+
};
|
|
9123
9158
|
}
|
|
9124
|
-
if (!end) this.cursor = lastComplete;
|
|
9125
|
-
lastBeat = Date.now();
|
|
9126
|
-
stopSeenAt = Date.now();
|
|
9127
|
-
if (end) return { stopReason: end === "stop" ? stopReason : null, end, denied: this.turnDenied };
|
|
9128
9159
|
continue;
|
|
9129
9160
|
}
|
|
9130
|
-
if (stopReason && Date.now() - stopSeenAt >= this.o.stopSettleMs) {
|
|
9131
|
-
return { stopReason, end: "stop", denied: this.turnDenied };
|
|
9161
|
+
if (scan.stopReason && Date.now() - scan.stopSeenAt >= this.o.stopSettleMs) {
|
|
9162
|
+
return { stopReason: scan.stopReason, end: "stop", denied: this.turnDenied };
|
|
9132
9163
|
}
|
|
9133
9164
|
if (this.exited) throw new Error(this.failureMessage("claude exited mid-turn", true));
|
|
9134
9165
|
if (this.abandonTurn) return { stopReason: null, end: "interrupted", denied: this.turnDenied };
|
|
9135
9166
|
const now = Date.now();
|
|
9136
|
-
if (onHeartbeat && now - lastBeat >= this.o.heartbeatMs) {
|
|
9137
|
-
lastBeat = now;
|
|
9167
|
+
if (onHeartbeat && now - scan.lastBeat >= this.o.heartbeatMs) {
|
|
9168
|
+
scan.lastBeat = now;
|
|
9138
9169
|
if (now - this.lastDataAt < this.o.heartbeatMs) onHeartbeat();
|
|
9139
9170
|
}
|
|
9140
9171
|
}
|
|
9141
9172
|
return { stopReason: null, end: null, denied: this.turnDenied };
|
|
9142
9173
|
} finally {
|
|
9143
9174
|
this.turn = null;
|
|
9175
|
+
this.scan = null;
|
|
9144
9176
|
this.abandonTurn = false;
|
|
9145
9177
|
settle();
|
|
9146
9178
|
}
|
|
9147
9179
|
}
|
|
9180
|
+
/**
|
|
9181
|
+
* Read every complete transcript record past the cursor into the running
|
|
9182
|
+
* turn. Returns whether anything new was read. The one place a record is
|
|
9183
|
+
* interpreted, shared by the poll loop and `flushTranscript`.
|
|
9184
|
+
*/
|
|
9185
|
+
scanTranscript() {
|
|
9186
|
+
const scan = this.scan;
|
|
9187
|
+
if (!scan || scan.end) return false;
|
|
9188
|
+
const lines = this.readRawLines();
|
|
9189
|
+
const lastComplete = lines.length - 1;
|
|
9190
|
+
if (lastComplete <= this.cursor) return false;
|
|
9191
|
+
for (let i = this.cursor; i < lastComplete && !scan.end; i++) {
|
|
9192
|
+
const s = lines[i];
|
|
9193
|
+
if (!s || !s.trim()) {
|
|
9194
|
+
this.cursor = i + 1;
|
|
9195
|
+
continue;
|
|
9196
|
+
}
|
|
9197
|
+
let rec = null;
|
|
9198
|
+
try {
|
|
9199
|
+
rec = JSON.parse(s);
|
|
9200
|
+
} catch {
|
|
9201
|
+
}
|
|
9202
|
+
scan.onRecord(s, rec);
|
|
9203
|
+
if (rec) {
|
|
9204
|
+
if (rec.type === "assistant" && rec.message) {
|
|
9205
|
+
const reason = rec.message.stop_reason;
|
|
9206
|
+
if (typeof reason === "string") {
|
|
9207
|
+
scan.stopReason = TERMINAL_STOP.has(reason) ? reason : null;
|
|
9208
|
+
}
|
|
9209
|
+
} else if (rec.type === "user") {
|
|
9210
|
+
if (scan.sawUserRecord && isInterruptRecord(rec)) scan.end = "interrupted";
|
|
9211
|
+
scan.sawUserRecord = true;
|
|
9212
|
+
} else if ((scan.sawUserRecord || scan.stopReason) && isTurnDurationRecord(rec)) {
|
|
9213
|
+
scan.end = scan.stopReason ? "stop" : "ended";
|
|
9214
|
+
}
|
|
9215
|
+
}
|
|
9216
|
+
this.cursor = i + 1;
|
|
9217
|
+
}
|
|
9218
|
+
if (!scan.end) this.cursor = lastComplete;
|
|
9219
|
+
scan.lastBeat = Date.now();
|
|
9220
|
+
scan.stopSeenAt = Date.now();
|
|
9221
|
+
return true;
|
|
9222
|
+
}
|
|
9223
|
+
/**
|
|
9224
|
+
* Hand the running turn every record the TUI has already written, now
|
|
9225
|
+
* rather than at the next poll. The TUI writes a reply's records before it
|
|
9226
|
+
* runs the reply's tools, but a proxied tool's MCP call can reach the
|
|
9227
|
+
* plugin inside one poll interval, and the step it ends must not close
|
|
9228
|
+
* before the text that preceded the call was read. No-op between turns.
|
|
9229
|
+
*/
|
|
9230
|
+
flushTranscript() {
|
|
9231
|
+
this.scanTranscript();
|
|
9232
|
+
}
|
|
9148
9233
|
/**
|
|
9149
9234
|
* Stop the running turn the way the TUI's own Esc does, and keep the
|
|
9150
9235
|
* session alive for the next one. Resolves true once the turn ended, false
|
|
@@ -9309,6 +9394,7 @@ ${text}`
|
|
|
9309
9394
|
}
|
|
9310
9395
|
function interactiveExtraArgs(opts) {
|
|
9311
9396
|
const extraArgs = [];
|
|
9397
|
+
if (opts.tools) extraArgs.push("--tools", opts.tools.join(","));
|
|
9312
9398
|
if (opts.mcpConfigPaths && opts.mcpConfigPaths.length > 0) {
|
|
9313
9399
|
extraArgs.push(
|
|
9314
9400
|
"--mcp-config",
|
|
@@ -9316,6 +9402,9 @@ function interactiveExtraArgs(opts) {
|
|
|
9316
9402
|
"--strict-mcp-config"
|
|
9317
9403
|
);
|
|
9318
9404
|
}
|
|
9405
|
+
if (opts.disallowedTools && opts.disallowedTools.length > 0) {
|
|
9406
|
+
extraArgs.push("--disallowedTools", ...opts.disallowedTools);
|
|
9407
|
+
}
|
|
9319
9408
|
for (const dir of opts.pluginDirs ?? []) {
|
|
9320
9409
|
extraArgs.push("--plugin-dir", dir);
|
|
9321
9410
|
}
|
|
@@ -9415,12 +9504,30 @@ function interactiveResultFrame(opts) {
|
|
|
9415
9504
|
duration_ms: 0
|
|
9416
9505
|
});
|
|
9417
9506
|
}
|
|
9507
|
+
function carriesReplyText(line) {
|
|
9508
|
+
try {
|
|
9509
|
+
const rec = JSON.parse(line);
|
|
9510
|
+
if (rec?.type !== "assistant" || !Array.isArray(rec.message?.content)) return false;
|
|
9511
|
+
return rec.message.content.some(
|
|
9512
|
+
(block) => block?.type === "text" && typeof block.text === "string" && block.text.trim()
|
|
9513
|
+
);
|
|
9514
|
+
} catch {
|
|
9515
|
+
return false;
|
|
9516
|
+
}
|
|
9517
|
+
}
|
|
9418
9518
|
function spawnInteractiveProcess(opts) {
|
|
9419
9519
|
const extraArgs = interactiveExtraArgs(opts);
|
|
9420
9520
|
const openCalls = new OpenToolCalls();
|
|
9421
9521
|
let denials = [];
|
|
9422
9522
|
const lineEmitter = new EventEmitter4();
|
|
9423
9523
|
const proc = new EventEmitter4();
|
|
9524
|
+
let ap;
|
|
9525
|
+
let proxyClosed = false;
|
|
9526
|
+
const closeProxyServer = () => {
|
|
9527
|
+
if (proxyClosed || !opts.proxyServer) return;
|
|
9528
|
+
proxyClosed = true;
|
|
9529
|
+
void opts.proxyServer.close();
|
|
9530
|
+
};
|
|
9424
9531
|
const session = new ClaudeSession({
|
|
9425
9532
|
...opts.tuning,
|
|
9426
9533
|
cwd: opts.cwd,
|
|
@@ -9450,6 +9557,7 @@ function spawnInteractiveProcess(opts) {
|
|
|
9450
9557
|
onExit: (code) => {
|
|
9451
9558
|
proc.exitCode = code;
|
|
9452
9559
|
proc.signalCode = code === null ? "SIGTERM" : null;
|
|
9560
|
+
closeProxyServer();
|
|
9453
9561
|
log.info("interactive claude exited", { sessionId: session.sessionId, code });
|
|
9454
9562
|
proc.emit("exit", proc.exitCode, proc.signalCode);
|
|
9455
9563
|
proc.emit("close", proc.exitCode, proc.signalCode);
|
|
@@ -9477,7 +9585,12 @@ function spawnInteractiveProcess(opts) {
|
|
|
9477
9585
|
const runTurn = async (userMsg, turnNumber) => {
|
|
9478
9586
|
const current = () => turnNumber === writes;
|
|
9479
9587
|
const emit2 = (line) => {
|
|
9480
|
-
if (current())
|
|
9588
|
+
if (!current()) return;
|
|
9589
|
+
if (lineEmitter.listenerCount("line") === 0) {
|
|
9590
|
+
if (carriesReplyText(line)) bufferUnattendedLine(ap, line);
|
|
9591
|
+
return;
|
|
9592
|
+
}
|
|
9593
|
+
lineEmitter.emit("line", line);
|
|
9481
9594
|
};
|
|
9482
9595
|
try {
|
|
9483
9596
|
await ensureStarted();
|
|
@@ -9497,7 +9610,13 @@ function spawnInteractiveProcess(opts) {
|
|
|
9497
9610
|
emit2(raw);
|
|
9498
9611
|
},
|
|
9499
9612
|
void 0,
|
|
9500
|
-
|
|
9613
|
+
// Only to a listening turn: it feeds that turn's watchdog, and the
|
|
9614
|
+
// TUI redraws its spinner the whole time it waits on a proxied call.
|
|
9615
|
+
() => {
|
|
9616
|
+
if (lineEmitter.listenerCount("line") > 0) {
|
|
9617
|
+
emit2(heartbeatFrame(session.sessionId, openCalls.newest()));
|
|
9618
|
+
}
|
|
9619
|
+
}
|
|
9501
9620
|
);
|
|
9502
9621
|
log.info("interactive turn ended", {
|
|
9503
9622
|
end,
|
|
@@ -9570,6 +9689,7 @@ function spawnInteractiveProcess(opts) {
|
|
|
9570
9689
|
});
|
|
9571
9690
|
}
|
|
9572
9691
|
}
|
|
9692
|
+
closeProxyServer();
|
|
9573
9693
|
const started = startPromise !== null;
|
|
9574
9694
|
try {
|
|
9575
9695
|
session.dispose();
|
|
@@ -9583,11 +9703,13 @@ function spawnInteractiveProcess(opts) {
|
|
|
9583
9703
|
return true;
|
|
9584
9704
|
}
|
|
9585
9705
|
});
|
|
9586
|
-
|
|
9706
|
+
ap = {
|
|
9587
9707
|
proc,
|
|
9588
9708
|
lineEmitter,
|
|
9589
|
-
proxyServer: null,
|
|
9709
|
+
proxyServer: opts.proxyServer ?? null,
|
|
9590
9710
|
mcpHash: void 0,
|
|
9711
|
+
unattendedLines: [],
|
|
9712
|
+
unattendedDropped: 0,
|
|
9591
9713
|
systemPromptFile: opts.systemPromptFile,
|
|
9592
9714
|
cliPath: opts.cliPath,
|
|
9593
9715
|
interactiveControl: {
|
|
@@ -9597,9 +9719,37 @@ function spawnInteractiveProcess(opts) {
|
|
|
9597
9719
|
interrupt: (timeoutMs) => {
|
|
9598
9720
|
cancelledThrough = writes;
|
|
9599
9721
|
return session.interrupt(timeoutMs);
|
|
9600
|
-
}
|
|
9722
|
+
},
|
|
9723
|
+
flushTranscript: () => session.flushTranscript()
|
|
9601
9724
|
}
|
|
9602
9725
|
};
|
|
9726
|
+
return ap;
|
|
9727
|
+
}
|
|
9728
|
+
|
|
9729
|
+
// src/transport.ts
|
|
9730
|
+
function requestedTransport(config, env = process.env.CLAUDE_CODE_INTERACTIVE_TRANSPORT) {
|
|
9731
|
+
if (config.transport !== void 0) {
|
|
9732
|
+
if (!["auto", "headless", "interactive"].includes(config.transport)) {
|
|
9733
|
+
throw new Error(`Unknown Claude transport: ${config.transport}`);
|
|
9734
|
+
}
|
|
9735
|
+
return config.transport;
|
|
9736
|
+
}
|
|
9737
|
+
const enabled = config.interactive ?? (env !== void 0 && !["", "0", "false", "no", "off"].includes(env.trim().toLowerCase()));
|
|
9738
|
+
return enabled ? "interactive" : "headless";
|
|
9739
|
+
}
|
|
9740
|
+
function hasInteractiveTransport() {
|
|
9741
|
+
const runtime = globalThis;
|
|
9742
|
+
return typeof runtime.Bun?.Terminal === "function";
|
|
9743
|
+
}
|
|
9744
|
+
async function selectTransport(requested, cliPath, available = hasInteractiveTransport()) {
|
|
9745
|
+
if (requested === "headless") return "headless";
|
|
9746
|
+
if (requested === "interactive") {
|
|
9747
|
+
if (!available) throw new Error("Interactive Claude transport requires Bun.Terminal. Run opencode under a Bun runtime with PTY support.");
|
|
9748
|
+
return "interactive";
|
|
9749
|
+
}
|
|
9750
|
+
if (await detectHeadlessSupport(cliPath) !== "unsupported") return "headless";
|
|
9751
|
+
if (!available) throw new Error("Claude no longer supports the headless flags, and Bun.Terminal is unavailable. Run opencode under a Bun runtime with PTY support.");
|
|
9752
|
+
return "interactive";
|
|
9603
9753
|
}
|
|
9604
9754
|
|
|
9605
9755
|
// src/prompts.ts
|
|
@@ -11162,6 +11312,8 @@ function drainNow(state) {
|
|
|
11162
11312
|
}
|
|
11163
11313
|
if (state.drainBuffer.length === 0) return;
|
|
11164
11314
|
if (state.controllerClosed) return;
|
|
11315
|
+
state.activeProcess?.interactiveControl?.flushTranscript();
|
|
11316
|
+
if (state.controllerClosed) return;
|
|
11165
11317
|
const batch = state.drainBuffer.splice(0, state.drainBuffer.length);
|
|
11166
11318
|
log.info("draining pending proxy calls into stream finish", {
|
|
11167
11319
|
sessionKey: state.sessionKey,
|
|
@@ -12468,8 +12620,14 @@ var ClaudeCodeLanguageModel = class {
|
|
|
12468
12620
|
const toFinishReason2 = this.toFinishReason.bind(this);
|
|
12469
12621
|
const handleControlRequest2 = this.handleControlRequest.bind(this);
|
|
12470
12622
|
const flagOn = (v) => v !== void 0 && !["", "0", "false", "no", "off"].includes(v.trim().toLowerCase());
|
|
12471
|
-
const
|
|
12472
|
-
const
|
|
12623
|
+
const transport = requestedTransport(this.config);
|
|
12624
|
+
const doctor = !compactionMode && scope !== "no-tools" ? parseDoctorCommand(options.prompt) : null;
|
|
12625
|
+
const selectedTransport = doctor ? transport === "interactive" ? "interactive" : "headless" : this.config.transport === void 0 && !hasInteractiveTransport() ? "headless" : this.isTitleRequest(scope, options) && !compactionMode ? "headless" : await Promise.race([selectTransport(transport, this.config.cliPath), turnAbort.whenAborted]);
|
|
12626
|
+
if (turnAbort.aborted) return abortedBeforeWork("selecting the transport");
|
|
12627
|
+
const useInteractive = selectedTransport === "interactive";
|
|
12628
|
+
if (useInteractive && !compactionMode && !doctor && (this.config.permissionPreset === "read-only" || this.config.permissionMode === "plan")) {
|
|
12629
|
+
throw new Error("Interactive Claude transport cannot enforce the read-only preset or plan mode. Use the headless transport for this permission posture.");
|
|
12630
|
+
}
|
|
12473
12631
|
const interactiveBypassRequested = this.config.interactiveBypass ?? flagOn(process.env.CLAUDE_CODE_INTERACTIVE_BYPASS);
|
|
12474
12632
|
const modelFallbackArmed = attempt?.armed === true && !compactionMode && !useInteractive;
|
|
12475
12633
|
const sourceAccount = normalizeAccountName(
|
|
@@ -12485,7 +12643,6 @@ var ClaudeCodeLanguageModel = class {
|
|
|
12485
12643
|
let cliPath = failover.cliPath;
|
|
12486
12644
|
if (turnAbort.aborted) return abortedBeforeWork("resolving the spawn cwd and account");
|
|
12487
12645
|
const asideTransportRef = { cliPath, interactive: !!useInteractive };
|
|
12488
|
-
const doctor = !compactionMode && scope !== "no-tools" ? parseDoctorCommand(options.prompt) : null;
|
|
12489
12646
|
if (doctor) {
|
|
12490
12647
|
const doctorOptions = {
|
|
12491
12648
|
cliPath,
|
|
@@ -12605,7 +12762,7 @@ var ClaudeCodeLanguageModel = class {
|
|
|
12605
12762
|
request: { body: { text: "" } }
|
|
12606
12763
|
};
|
|
12607
12764
|
}
|
|
12608
|
-
if (!hasNewUserContent(options.prompt)) {
|
|
12765
|
+
if (!compactionMode && !hasNewUserContent(options.prompt)) {
|
|
12609
12766
|
log.info("doStream short-circuit: no new user content");
|
|
12610
12767
|
const stream2 = new ReadableStream({
|
|
12611
12768
|
start(controller) {
|
|
@@ -12778,6 +12935,7 @@ var ClaudeCodeLanguageModel = class {
|
|
|
12778
12935
|
const effectivePrompt = failoverAnswer?.kind === "switch" ? buildFailoverContinuationPrompt(options.prompt, failoverAnswer.target) : options.prompt;
|
|
12779
12936
|
const userMsg = exitPlanModeQuestionResult ?? getClaudeUserMessage(effectivePrompt, includeHistoryContext, {
|
|
12780
12937
|
compactionMode,
|
|
12938
|
+
compactionInstructions: useInteractive && compactionMode ? extractSystemMessages(effectivePrompt).join("\n\n") : void 0,
|
|
12781
12939
|
cliToolCallIds: new Set(previousPendingProxyCalls.map((c) => c.toolCallId)),
|
|
12782
12940
|
stripContextReminders: this.stripContextRemindersEnabled()
|
|
12783
12941
|
});
|
|
@@ -13015,13 +13173,159 @@ var ClaudeCodeLanguageModel = class {
|
|
|
13015
13173
|
state.proxyServer = null;
|
|
13016
13174
|
}
|
|
13017
13175
|
}
|
|
13018
|
-
|
|
13019
|
-
const
|
|
13176
|
+
const resolveProxyWiring = async () => {
|
|
13177
|
+
const discovery = self.effectiveMcpConfig(
|
|
13178
|
+
cwd,
|
|
13179
|
+
void 0,
|
|
13180
|
+
runtimeStatus
|
|
13181
|
+
);
|
|
13182
|
+
const mcpResolution = self.resolvedProxyMcpTools(
|
|
13183
|
+
discovery.allEnabledServerNames,
|
|
13184
|
+
options.tools,
|
|
13185
|
+
new Set((resolvedProxy ?? []).map((def) => def.name))
|
|
13186
|
+
);
|
|
13187
|
+
const proxyMcpTools = mcpResolution?.defs ?? null;
|
|
13188
|
+
const excludeServers = mcpResolution ? mcpResolution.coveredServers : void 0;
|
|
13189
|
+
const taskProxyEnabled = resolvedProxy?.some((t) => t.name === "task") ?? false;
|
|
13190
|
+
const questionProxyEnabled = resolvedProxy?.some((t) => t.name === "question") ?? false;
|
|
13191
|
+
const opencodeToolsRequested = (self.config.proxyOpencodeTools?.length ?? 0) > 0;
|
|
13192
|
+
log.debug("opencode tool forwarding gate", {
|
|
13193
|
+
requested: self.config.proxyOpencodeTools ?? null,
|
|
13194
|
+
opencodeToolsRequested
|
|
13195
|
+
});
|
|
13196
|
+
const liveToolInfo = taskProxyEnabled || questionProxyEnabled || opencodeToolsRequested ? await loadLiveToolInfo() : {
|
|
13197
|
+
resolved: false,
|
|
13198
|
+
taskDescription: void 0,
|
|
13199
|
+
taskParameters: void 0,
|
|
13200
|
+
questionDescription: void 0,
|
|
13201
|
+
hasQuestion: false
|
|
13202
|
+
};
|
|
13203
|
+
let enrichedProxy = resolvedProxy;
|
|
13204
|
+
let backgroundSubagentsSupported = false;
|
|
13205
|
+
if (enrichedProxy && taskProxyEnabled) {
|
|
13206
|
+
enrichedProxy = overlayTaskProxyDescription(
|
|
13207
|
+
enrichedProxy,
|
|
13208
|
+
liveToolInfo.taskDescription
|
|
13209
|
+
);
|
|
13210
|
+
log.info("task proxy description overlay", {
|
|
13211
|
+
applied: Boolean(liveToolInfo.taskDescription),
|
|
13212
|
+
liveDescriptionLength: liveToolInfo.taskDescription?.length ?? 0,
|
|
13213
|
+
listsAgentTypes: Boolean(
|
|
13214
|
+
liveToolInfo.taskDescription?.includes(
|
|
13215
|
+
"Available agent types"
|
|
13216
|
+
)
|
|
13217
|
+
)
|
|
13218
|
+
});
|
|
13219
|
+
const hostDialect = self.config.hostApi === "v2" ? "v2" : "v1";
|
|
13220
|
+
backgroundSubagentsSupported = liveTaskSupportsBackground(
|
|
13221
|
+
liveToolInfo.taskParameters,
|
|
13222
|
+
hostDialect
|
|
13223
|
+
);
|
|
13224
|
+
enrichedProxy = applyBackgroundSubagentSupport(
|
|
13225
|
+
enrichedProxy,
|
|
13226
|
+
backgroundSubagentsSupported,
|
|
13227
|
+
hostDialect
|
|
13228
|
+
);
|
|
13229
|
+
recordBackgroundSubagentGate({
|
|
13230
|
+
supported: backgroundSubagentsSupported,
|
|
13231
|
+
hostApi: hostDialect,
|
|
13232
|
+
registryResolved: liveToolInfo.resolved
|
|
13233
|
+
});
|
|
13234
|
+
log.info("background subagent gate", {
|
|
13235
|
+
supported: backgroundSubagentsSupported,
|
|
13236
|
+
registryResolved: liveToolInfo.resolved,
|
|
13237
|
+
hostApi: hostDialect,
|
|
13238
|
+
note: backgroundSubagentsSupported ? "task accepts `background`; task_status and task_cancel are registered" : "`background` stripped from the task schema; set OPENCODE_EXPERIMENTAL_BACKGROUND_SUBAGENTS=true in opencode's environment to enable it"
|
|
13239
|
+
});
|
|
13240
|
+
}
|
|
13241
|
+
if (enrichedProxy && questionProxyEnabled) {
|
|
13242
|
+
enrichedProxy = overlayQuestionProxyDescription(
|
|
13243
|
+
enrichedProxy,
|
|
13244
|
+
liveToolInfo.hasQuestion ? liveToolInfo.questionDescription : void 0
|
|
13245
|
+
);
|
|
13246
|
+
enrichedProxy = filterQuestionProxyByOpencodeSupport(
|
|
13247
|
+
enrichedProxy,
|
|
13248
|
+
liveToolInfo.hasQuestion
|
|
13249
|
+
);
|
|
13250
|
+
log.info("question proxy version gate", {
|
|
13251
|
+
opencodeHasQuestion: liveToolInfo.hasQuestion,
|
|
13252
|
+
kept: liveToolInfo.hasQuestion
|
|
13253
|
+
});
|
|
13254
|
+
}
|
|
13255
|
+
const opencodeToolDefs = resolveProxyOpencodeToolDefs({
|
|
13256
|
+
requested: self.config.proxyOpencodeTools,
|
|
13257
|
+
items: liveToolInfo.items,
|
|
13258
|
+
modelTools: self.config.hostApi === "v2" ? options.tools ?? [] : void 0,
|
|
13259
|
+
allowCodeExecution: self.config.permissionPreset !== "read-only",
|
|
13260
|
+
taken: new Set(
|
|
13261
|
+
[...enrichedProxy ?? [], ...proxyMcpTools ?? []].map(
|
|
13262
|
+
(t) => t.name
|
|
13263
|
+
)
|
|
13264
|
+
)
|
|
13265
|
+
});
|
|
13266
|
+
if (opencodeToolDefs.length > 0) {
|
|
13267
|
+
log.info("forwarding opencode tools through the proxy", {
|
|
13268
|
+
tools: opencodeToolDefs.map((t) => t.name)
|
|
13269
|
+
});
|
|
13270
|
+
}
|
|
13271
|
+
const combinedList = [
|
|
13272
|
+
...enrichedProxy ?? [],
|
|
13273
|
+
...proxyMcpTools ?? [],
|
|
13274
|
+
...opencodeToolDefs
|
|
13275
|
+
];
|
|
13276
|
+
const combinedProxyTools = combinedList.length > 0 ? combinedList : null;
|
|
13277
|
+
const pluginCompressEnabled = enrichedProxy?.some((t) => t.name === "compress") ?? false;
|
|
13278
|
+
if (!state.proxyServer && combinedProxyTools) {
|
|
13279
|
+
state.proxyServer = await self.ensureProxyServer(
|
|
13280
|
+
combinedProxyTools,
|
|
13281
|
+
sk,
|
|
13282
|
+
pluginCompressEnabled,
|
|
13283
|
+
affinity
|
|
13284
|
+
);
|
|
13285
|
+
}
|
|
13286
|
+
const questionProxyActive = enrichedProxy?.some((t) => t.name === "question") ?? false;
|
|
13287
|
+
const allDisallowed = resolveDisallowedTools({
|
|
13288
|
+
proxyTools: enrichedProxy,
|
|
13289
|
+
extraDisallowedTools: self.config.extraDisallowedTools,
|
|
13290
|
+
disableWebSearch: self.config.webSearch === "disabled"
|
|
13291
|
+
});
|
|
13292
|
+
return {
|
|
13293
|
+
excludeServers,
|
|
13294
|
+
taskProxyEnabled,
|
|
13295
|
+
backgroundSubagentsSupported,
|
|
13296
|
+
questionProxyActive,
|
|
13297
|
+
opencodeToolDefs,
|
|
13298
|
+
pluginCompressEnabled,
|
|
13299
|
+
allDisallowed
|
|
13300
|
+
};
|
|
13301
|
+
};
|
|
13302
|
+
if (useInteractive && compactionMode) {
|
|
13303
|
+
const ap = spawnInteractiveProcess({
|
|
13304
|
+
cwd,
|
|
13305
|
+
cliPath,
|
|
13306
|
+
configDir: self.config.configDir,
|
|
13307
|
+
model: spawnModelId,
|
|
13308
|
+
fastMode,
|
|
13309
|
+
tools: [],
|
|
13310
|
+
mcpConfigPaths: ['{"mcpServers":{}}'],
|
|
13311
|
+
env: claudeSpawnEnv({ ignoreAnthropicApiKey: self.config.ignoreAnthropicApiKey })
|
|
13312
|
+
});
|
|
13313
|
+
state.proc = ap.proc;
|
|
13314
|
+
state.lineEmitter = ap.lineEmitter;
|
|
13315
|
+
state.activeProcess = ap;
|
|
13316
|
+
} else if (useInteractive) {
|
|
13020
13317
|
if (state.activeProcess) {
|
|
13021
13318
|
state.proc = state.activeProcess.proc;
|
|
13022
13319
|
state.lineEmitter = state.activeProcess.lineEmitter;
|
|
13023
13320
|
log.debug("reusing active interactive session", { sk });
|
|
13024
13321
|
} else {
|
|
13322
|
+
const wiring = await resolveProxyWiring();
|
|
13323
|
+
const mcp = self.effectiveMcpConfig(
|
|
13324
|
+
cwd,
|
|
13325
|
+
state.proxyServer?.configPath(),
|
|
13326
|
+
runtimeStatus,
|
|
13327
|
+
wiring.excludeServers
|
|
13328
|
+
);
|
|
13025
13329
|
const allow = [
|
|
13026
13330
|
...mcp.allEnabledServerNames.map((n) => `mcp__${n}__*`),
|
|
13027
13331
|
"mcp__opencode_proxy__*",
|
|
@@ -13035,12 +13339,27 @@ var ClaudeCodeLanguageModel = class {
|
|
|
13035
13339
|
];
|
|
13036
13340
|
const systemPromptFile = self.config.interactiveSystemPrompt === false ? void 0 : buildAppendedSystemPrompt(
|
|
13037
13341
|
cwd,
|
|
13038
|
-
self.config.multiStepContinuation !== false
|
|
13342
|
+
self.config.multiStepContinuation !== false,
|
|
13039
13343
|
// Do not forward opencode's own system prompt into the
|
|
13040
13344
|
// interactive TUI. Live subscription-account testing
|
|
13041
13345
|
// showed that large forwarded payload can trigger Claude
|
|
13042
13346
|
// Code's third-party-app usage gate, while our static
|
|
13043
|
-
// CLI/AGENTS/continuation prompt remains safe.
|
|
13347
|
+
// CLI/AGENTS/continuation prompt remains safe. The
|
|
13348
|
+
// plugin's own short proxy hints are part of that static
|
|
13349
|
+
// prompt: without them the model narrates a subagent
|
|
13350
|
+
// dispatch instead of calling the proxy (h #g74).
|
|
13351
|
+
[
|
|
13352
|
+
...wiring.taskProxyEnabled ? [SUBAGENT_DISPATCH_HINT] : [],
|
|
13353
|
+
...wiring.backgroundSubagentsSupported ? [BACKGROUND_SUBAGENT_HINT] : [],
|
|
13354
|
+
...wiring.questionProxyActive ? [QUESTION_PROXY_HINT] : []
|
|
13355
|
+
],
|
|
13356
|
+
{
|
|
13357
|
+
compressEnabled: wiring.pluginCompressEnabled,
|
|
13358
|
+
opencodeCompressEnabled: wiring.opencodeToolDefs.some(
|
|
13359
|
+
(t) => t.name === "compress"
|
|
13360
|
+
),
|
|
13361
|
+
compressionSummary: getCompressionSummary(sk)
|
|
13362
|
+
}
|
|
13044
13363
|
);
|
|
13045
13364
|
if (self.config.interactiveSystemPrompt === false) {
|
|
13046
13365
|
log.warn(
|
|
@@ -13069,6 +13388,8 @@ var ClaudeCodeLanguageModel = class {
|
|
|
13069
13388
|
mcpConfigPaths: mcp.paths,
|
|
13070
13389
|
pluginDirs: skillPluginDirs,
|
|
13071
13390
|
permissionsAllow: allow,
|
|
13391
|
+
disallowedTools: wiring.allDisallowed,
|
|
13392
|
+
proxyServer: state.proxyServer,
|
|
13072
13393
|
systemPromptFile,
|
|
13073
13394
|
ignoreAnthropicApiKey: self.config.ignoreAnthropicApiKey,
|
|
13074
13395
|
effort: reasoningEffort,
|
|
@@ -13115,121 +13436,15 @@ var ClaudeCodeLanguageModel = class {
|
|
|
13115
13436
|
cliVersion
|
|
13116
13437
|
});
|
|
13117
13438
|
} else {
|
|
13118
|
-
const
|
|
13119
|
-
|
|
13120
|
-
|
|
13121
|
-
|
|
13122
|
-
|
|
13123
|
-
|
|
13124
|
-
|
|
13125
|
-
|
|
13126
|
-
|
|
13127
|
-
);
|
|
13128
|
-
const proxyMcpTools = mcpResolution?.defs ?? null;
|
|
13129
|
-
const excludeServers = mcpResolution ? mcpResolution.coveredServers : void 0;
|
|
13130
|
-
const taskProxyEnabled = resolvedProxy?.some((t) => t.name === "task") ?? false;
|
|
13131
|
-
const questionProxyEnabled = resolvedProxy?.some((t) => t.name === "question") ?? false;
|
|
13132
|
-
const opencodeToolsRequested = (self.config.proxyOpencodeTools?.length ?? 0) > 0;
|
|
13133
|
-
log.debug("opencode tool forwarding gate", {
|
|
13134
|
-
requested: self.config.proxyOpencodeTools ?? null,
|
|
13135
|
-
opencodeToolsRequested
|
|
13136
|
-
});
|
|
13137
|
-
const liveToolInfo = taskProxyEnabled || questionProxyEnabled || opencodeToolsRequested ? await loadLiveToolInfo() : {
|
|
13138
|
-
resolved: false,
|
|
13139
|
-
taskDescription: void 0,
|
|
13140
|
-
taskParameters: void 0,
|
|
13141
|
-
questionDescription: void 0,
|
|
13142
|
-
hasQuestion: false
|
|
13143
|
-
};
|
|
13144
|
-
let enrichedProxy = resolvedProxy;
|
|
13145
|
-
let backgroundSubagentsSupported = false;
|
|
13146
|
-
if (enrichedProxy && taskProxyEnabled) {
|
|
13147
|
-
enrichedProxy = overlayTaskProxyDescription(
|
|
13148
|
-
enrichedProxy,
|
|
13149
|
-
liveToolInfo.taskDescription
|
|
13150
|
-
);
|
|
13151
|
-
log.info("task proxy description overlay", {
|
|
13152
|
-
applied: Boolean(liveToolInfo.taskDescription),
|
|
13153
|
-
liveDescriptionLength: liveToolInfo.taskDescription?.length ?? 0,
|
|
13154
|
-
listsAgentTypes: Boolean(
|
|
13155
|
-
liveToolInfo.taskDescription?.includes(
|
|
13156
|
-
"Available agent types"
|
|
13157
|
-
)
|
|
13158
|
-
)
|
|
13159
|
-
});
|
|
13160
|
-
const hostDialect = self.config.hostApi === "v2" ? "v2" : "v1";
|
|
13161
|
-
backgroundSubagentsSupported = liveTaskSupportsBackground(
|
|
13162
|
-
liveToolInfo.taskParameters,
|
|
13163
|
-
hostDialect
|
|
13164
|
-
);
|
|
13165
|
-
enrichedProxy = applyBackgroundSubagentSupport(
|
|
13166
|
-
enrichedProxy,
|
|
13167
|
-
backgroundSubagentsSupported,
|
|
13168
|
-
hostDialect
|
|
13169
|
-
);
|
|
13170
|
-
recordBackgroundSubagentGate({
|
|
13171
|
-
supported: backgroundSubagentsSupported,
|
|
13172
|
-
hostApi: hostDialect,
|
|
13173
|
-
registryResolved: liveToolInfo.resolved
|
|
13174
|
-
});
|
|
13175
|
-
log.info("background subagent gate", {
|
|
13176
|
-
supported: backgroundSubagentsSupported,
|
|
13177
|
-
registryResolved: liveToolInfo.resolved,
|
|
13178
|
-
hostApi: hostDialect,
|
|
13179
|
-
note: backgroundSubagentsSupported ? "task accepts `background`; task_status and task_cancel are registered" : "`background` stripped from the task schema; set OPENCODE_EXPERIMENTAL_BACKGROUND_SUBAGENTS=true in opencode's environment to enable it"
|
|
13180
|
-
});
|
|
13181
|
-
}
|
|
13182
|
-
if (enrichedProxy && questionProxyEnabled) {
|
|
13183
|
-
enrichedProxy = overlayQuestionProxyDescription(
|
|
13184
|
-
enrichedProxy,
|
|
13185
|
-
liveToolInfo.hasQuestion ? liveToolInfo.questionDescription : void 0
|
|
13186
|
-
);
|
|
13187
|
-
enrichedProxy = filterQuestionProxyByOpencodeSupport(
|
|
13188
|
-
enrichedProxy,
|
|
13189
|
-
liveToolInfo.hasQuestion
|
|
13190
|
-
);
|
|
13191
|
-
log.info("question proxy version gate", {
|
|
13192
|
-
opencodeHasQuestion: liveToolInfo.hasQuestion,
|
|
13193
|
-
kept: liveToolInfo.hasQuestion
|
|
13194
|
-
});
|
|
13195
|
-
}
|
|
13196
|
-
const opencodeToolDefs = resolveProxyOpencodeToolDefs({
|
|
13197
|
-
requested: self.config.proxyOpencodeTools,
|
|
13198
|
-
items: liveToolInfo.items,
|
|
13199
|
-
modelTools: self.config.hostApi === "v2" ? options.tools ?? [] : void 0,
|
|
13200
|
-
allowCodeExecution: self.config.permissionPreset !== "read-only",
|
|
13201
|
-
taken: new Set(
|
|
13202
|
-
[...enrichedProxy ?? [], ...proxyMcpTools ?? []].map(
|
|
13203
|
-
(t) => t.name
|
|
13204
|
-
)
|
|
13205
|
-
)
|
|
13206
|
-
});
|
|
13207
|
-
if (opencodeToolDefs.length > 0) {
|
|
13208
|
-
log.info("forwarding opencode tools through the proxy", {
|
|
13209
|
-
tools: opencodeToolDefs.map((t) => t.name)
|
|
13210
|
-
});
|
|
13211
|
-
}
|
|
13212
|
-
const combinedList = [
|
|
13213
|
-
...enrichedProxy ?? [],
|
|
13214
|
-
...proxyMcpTools ?? [],
|
|
13215
|
-
...opencodeToolDefs
|
|
13216
|
-
];
|
|
13217
|
-
const combinedProxyTools = combinedList.length > 0 ? combinedList : null;
|
|
13218
|
-
const pluginCompressEnabled = enrichedProxy?.some((t) => t.name === "compress") ?? false;
|
|
13219
|
-
if (!state.proxyServer && combinedProxyTools) {
|
|
13220
|
-
state.proxyServer = await self.ensureProxyServer(
|
|
13221
|
-
combinedProxyTools,
|
|
13222
|
-
sk,
|
|
13223
|
-
pluginCompressEnabled,
|
|
13224
|
-
affinity
|
|
13225
|
-
);
|
|
13226
|
-
}
|
|
13227
|
-
const questionProxyActive = enrichedProxy?.some((t) => t.name === "question") ?? false;
|
|
13228
|
-
const allDisallowed = resolveDisallowedTools({
|
|
13229
|
-
proxyTools: enrichedProxy,
|
|
13230
|
-
extraDisallowedTools: self.config.extraDisallowedTools,
|
|
13231
|
-
disableWebSearch: self.config.webSearch === "disabled"
|
|
13232
|
-
});
|
|
13439
|
+
const {
|
|
13440
|
+
excludeServers,
|
|
13441
|
+
taskProxyEnabled,
|
|
13442
|
+
backgroundSubagentsSupported,
|
|
13443
|
+
questionProxyActive,
|
|
13444
|
+
opencodeToolDefs,
|
|
13445
|
+
pluginCompressEnabled,
|
|
13446
|
+
allDisallowed
|
|
13447
|
+
} = await resolveProxyWiring();
|
|
13233
13448
|
const mcp = self.effectiveMcpConfig(
|
|
13234
13449
|
cwd,
|
|
13235
13450
|
state.proxyServer?.configPath(),
|
|
@@ -13582,6 +13797,7 @@ var ClaudeCodeLanguageModel = class {
|
|
|
13582
13797
|
state.asideSinkUnregister?.();
|
|
13583
13798
|
state.asideSinkUnregister = null;
|
|
13584
13799
|
state.proc.off("error", procErrorHandler);
|
|
13800
|
+
if (compactionMode && useInteractive) state.proc.kill();
|
|
13585
13801
|
};
|
|
13586
13802
|
const procErrorHandler = (err) => {
|
|
13587
13803
|
log.error("process error", { error: err.message });
|
|
@@ -14595,6 +14811,7 @@ function createClaudeCode(settings = {}) {
|
|
|
14595
14811
|
turnStats: settings.turnStats === true,
|
|
14596
14812
|
forkSessions: settings.forkSessions === true,
|
|
14597
14813
|
resumeAfterRestart: settings.resumeAfterRestart !== false,
|
|
14814
|
+
transport: settings.transport,
|
|
14598
14815
|
interactive: settings.interactive,
|
|
14599
14816
|
interactiveBypass: settings.interactiveBypass,
|
|
14600
14817
|
interactiveAllowTools: settings.interactiveAllowTools,
|