@khalilgharbaoui/opencode-claude-code-plugin 0.42.1 → 0.42.3
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 +136 -38
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/skills/claude-code-plugin/SKILL.md +13 -4
package/dist/index.js
CHANGED
|
@@ -1723,6 +1723,21 @@ function cliSupportsDontAsk(v) {
|
|
|
1723
1723
|
if (!v) return false;
|
|
1724
1724
|
return gte(v, { major: 2, minor: 1, patch: 263 });
|
|
1725
1725
|
}
|
|
1726
|
+
var INTERACTIVE_MEASURED_CLI = "2.1.288";
|
|
1727
|
+
var INTERACTIVE_MEASURED = { major: 2, minor: 1, patch: 288 };
|
|
1728
|
+
function isUnmeasuredInteractiveCli(v) {
|
|
1729
|
+
if (!v) return false;
|
|
1730
|
+
return gte(v, INTERACTIVE_MEASURED) && !(v.major === INTERACTIVE_MEASURED.major && v.minor === INTERACTIVE_MEASURED.minor && v.patch === INTERACTIVE_MEASURED.patch);
|
|
1731
|
+
}
|
|
1732
|
+
var warnedUnmeasuredInteractive = /* @__PURE__ */ new Set();
|
|
1733
|
+
function reportUnmeasuredInteractiveCli(v) {
|
|
1734
|
+
if (!v || !isUnmeasuredInteractiveCli(v) || warnedUnmeasuredInteractive.has(v.raw)) return;
|
|
1735
|
+
warnedUnmeasuredInteractive.add(v.raw);
|
|
1736
|
+
log.warn(
|
|
1737
|
+
"the interactive transport has not been measured on this Claude Code version; it reads the TUI's screen and transcript, which a new release can change. If a turn hangs or a dialog is not handled, run /claude-code-doctor bundle and report it",
|
|
1738
|
+
{ cliVersion: v.raw, measuredCli: INTERACTIVE_MEASURED_CLI }
|
|
1739
|
+
);
|
|
1740
|
+
}
|
|
1726
1741
|
function cliSupportsSideQuestion(v) {
|
|
1727
1742
|
if (!v) return false;
|
|
1728
1743
|
return gte(v, { major: 2, minor: 1, patch: 258 });
|
|
@@ -5431,6 +5446,7 @@ function snapshotActiveProcesses(now = Date.now()) {
|
|
|
5431
5446
|
ageMs: ap.startedAt === void 0 ? void 0 : Math.max(0, now - ap.startedAt),
|
|
5432
5447
|
effort: ap.effort,
|
|
5433
5448
|
attached: ap.lineEmitter.listenerCount("line") > 0,
|
|
5449
|
+
transport: ap.interactiveControl ? "interactive" : "headless",
|
|
5434
5450
|
proxyUrl: ap.proxyServer?.url,
|
|
5435
5451
|
lastStderr: typeof lastStderr === "string" ? lastStderr : void 0
|
|
5436
5452
|
});
|
|
@@ -5845,6 +5861,8 @@ var PLUGIN_LOG_MESSAGES = /* @__PURE__ */ new Set([
|
|
|
5845
5861
|
"skipping remote MCP server with no url",
|
|
5846
5862
|
"stale scratch directory sweep failed",
|
|
5847
5863
|
"task_batch resolving with child results missing",
|
|
5864
|
+
"the interactive transport has not been measured on this Claude Code version; it reads the TUI's screen and transcript, which a new release can change. If a turn hangs or a dialog is not handled, run /claude-code-doctor bundle and report it",
|
|
5865
|
+
"the interactive turn did not take a forwarded user message",
|
|
5848
5866
|
"this opencode process is running an older plugin build than the one on disk",
|
|
5849
5867
|
"timed out pending proxy call",
|
|
5850
5868
|
"turn abort listener threw",
|
|
@@ -5994,6 +6012,7 @@ var BUNDLE_DATA_ALLOWLIST = {
|
|
|
5994
6012
|
toolNames: "name",
|
|
5995
6013
|
cliFloor: "version",
|
|
5996
6014
|
cliVersion: "version",
|
|
6015
|
+
measuredCli: "version",
|
|
5997
6016
|
// The two halves of the stale-build WARN: what this process loaded and what
|
|
5998
6017
|
// is on disk now. Both are this package's own version strings.
|
|
5999
6018
|
loadedVersion: "version",
|
|
@@ -6453,6 +6472,34 @@ import * as fs4 from "fs";
|
|
|
6453
6472
|
import * as path5 from "path";
|
|
6454
6473
|
import { promisify as promisify2 } from "util";
|
|
6455
6474
|
import { fileURLToPath } from "url";
|
|
6475
|
+
|
|
6476
|
+
// src/transport.ts
|
|
6477
|
+
function requestedTransport(config, env = process.env.CLAUDE_CODE_INTERACTIVE_TRANSPORT) {
|
|
6478
|
+
if (config.transport !== void 0) {
|
|
6479
|
+
if (!["auto", "headless", "interactive"].includes(config.transport)) {
|
|
6480
|
+
throw new Error(`Unknown Claude transport: ${config.transport}`);
|
|
6481
|
+
}
|
|
6482
|
+
return config.transport;
|
|
6483
|
+
}
|
|
6484
|
+
const enabled = config.interactive ?? (env !== void 0 && !["", "0", "false", "no", "off"].includes(env.trim().toLowerCase()));
|
|
6485
|
+
return enabled ? "interactive" : "headless";
|
|
6486
|
+
}
|
|
6487
|
+
function hasInteractiveTransport() {
|
|
6488
|
+
const runtime = globalThis;
|
|
6489
|
+
return typeof runtime.Bun?.Terminal === "function";
|
|
6490
|
+
}
|
|
6491
|
+
async function selectTransport(requested, cliPath, available = hasInteractiveTransport()) {
|
|
6492
|
+
if (requested === "headless") return "headless";
|
|
6493
|
+
if (requested === "interactive") {
|
|
6494
|
+
if (!available) throw new Error("Interactive Claude transport requires Bun.Terminal. Run opencode under a Bun runtime with PTY support.");
|
|
6495
|
+
return "interactive";
|
|
6496
|
+
}
|
|
6497
|
+
if (await detectHeadlessSupport(cliPath) !== "unsupported") return "headless";
|
|
6498
|
+
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.");
|
|
6499
|
+
return "interactive";
|
|
6500
|
+
}
|
|
6501
|
+
|
|
6502
|
+
// src/startup-diagnostics.ts
|
|
6456
6503
|
var cachedPluginVersion;
|
|
6457
6504
|
function pluginVersion() {
|
|
6458
6505
|
if (cachedPluginVersion) return cachedPluginVersion;
|
|
@@ -6535,6 +6582,15 @@ function collectStartupDiagnostics(providers, opencodeVersion) {
|
|
|
6535
6582
|
error: err instanceof Error ? err.message : String(err)
|
|
6536
6583
|
});
|
|
6537
6584
|
}
|
|
6585
|
+
let transport;
|
|
6586
|
+
try {
|
|
6587
|
+
transport = requestedTransport({
|
|
6588
|
+
transport: firstOption(providers, "transport"),
|
|
6589
|
+
interactive: firstOption(providers, "interactive")
|
|
6590
|
+
});
|
|
6591
|
+
} catch {
|
|
6592
|
+
transport = "invalid";
|
|
6593
|
+
}
|
|
6538
6594
|
return {
|
|
6539
6595
|
plugin: pluginVersion(),
|
|
6540
6596
|
opencode: opencodeVersion ?? process.env.OPENCODE_VERSION ?? "unknown",
|
|
@@ -6547,7 +6603,8 @@ function collectStartupDiagnostics(providers, opencodeVersion) {
|
|
|
6547
6603
|
permissionPresets: Object.entries(providers).map(
|
|
6548
6604
|
([name, entry]) => summarizePermissionPreset(name, entry?.options)
|
|
6549
6605
|
),
|
|
6550
|
-
|
|
6606
|
+
transport,
|
|
6607
|
+
interactiveTransport: transport === "interactive",
|
|
6551
6608
|
planModeQuestion: firstOption(providers, "planModeQuestion") === true,
|
|
6552
6609
|
anthropicApiKeyInEnv: Boolean(
|
|
6553
6610
|
process.env.ANTHROPIC_API_KEY || process.env.ANTHROPIC_AUTH_TOKEN
|
|
@@ -6816,7 +6873,14 @@ function formatDoctorReport(report) {
|
|
|
6816
6873
|
lines.push(`| proxyTools | ${list(report.proxyTools)} |`);
|
|
6817
6874
|
lines.push(`| MCP servers (on disk) | ${list(report.mcpServers)} |`);
|
|
6818
6875
|
lines.push(`| permissionPreset | ${describePermissionPresets(report.permissionPresets)} |`);
|
|
6819
|
-
lines.push(
|
|
6876
|
+
lines.push(
|
|
6877
|
+
`| transport | ${report.transport}${report.transport === "auto" ? " (headless until claude refuses `--print`)" : ""}; this conversation: ${report.transportInUse} |`
|
|
6878
|
+
);
|
|
6879
|
+
if (report.interactiveMeasured) {
|
|
6880
|
+
lines.push(
|
|
6881
|
+
`| interactive transport measured on | Claude Code ${report.interactiveMeasured.measured}${report.interactiveMeasured.unmeasured ? ` (this CLI, ${report.claudeCli.version}, is newer and unmeasured: if a turn hangs, send \`/claude-code-doctor bundle\`)` : ""} |`
|
|
6882
|
+
);
|
|
6883
|
+
}
|
|
6820
6884
|
lines.push(`| planModeQuestion | ${report.planModeQuestion} |`);
|
|
6821
6885
|
lines.push(`| turnStats | ${report.turnStats} |`);
|
|
6822
6886
|
lines.push(`| ANTHROPIC_API_KEY in env | ${report.anthropicApiKeyInEnv ? "yes" : "no"} |`);
|
|
@@ -6837,11 +6901,11 @@ function formatDoctorReport(report) {
|
|
|
6837
6901
|
if (report.processes.length === 0) {
|
|
6838
6902
|
lines.push("None. The next message in a Claude Code session spawns one.");
|
|
6839
6903
|
} else {
|
|
6840
|
-
lines.push("| session | model | pid | in flight | age | effort |");
|
|
6841
|
-
lines.push("
|
|
6904
|
+
lines.push("| session | model | transport | pid | in flight | age | effort |");
|
|
6905
|
+
lines.push("|---|---|---|---|---|---|---|");
|
|
6842
6906
|
for (const proc of report.processes) {
|
|
6843
6907
|
lines.push(
|
|
6844
|
-
`| ${proc.session}${proc.compaction ? " (compaction)" : ""} | ${proc.model} | ${proc.pid ?? "unknown"} | ${proc.inFlight ? "yes" : "no"} | ${formatAge(proc.ageMs)} | ${proc.effort ?? "inherited"} |`
|
|
6908
|
+
`| ${proc.session}${proc.compaction ? " (compaction)" : ""} | ${proc.model} | ${proc.transport} | ${proc.pid ?? "unknown"} | ${proc.inFlight ? "yes" : "no"} | ${formatAge(proc.ageMs)} | ${proc.effort ?? "inherited"} |`
|
|
6845
6909
|
);
|
|
6846
6910
|
}
|
|
6847
6911
|
}
|
|
@@ -7061,7 +7125,9 @@ async function gatherDoctorReport(options) {
|
|
|
7061
7125
|
proxyTools: base.proxyTools,
|
|
7062
7126
|
mcpServers: base.mcpServers,
|
|
7063
7127
|
permissionPresets: base.permissionPresets,
|
|
7064
|
-
transport:
|
|
7128
|
+
transport: base.transport,
|
|
7129
|
+
transportInUse: options.interactive ? "interactive" : "headless",
|
|
7130
|
+
interactiveMeasured: base.transport !== "headless" || options.interactive || processes.some((proc) => proc.transport === "interactive") ? { measured: INTERACTIVE_MEASURED_CLI, unmeasured: isUnmeasuredInteractiveCli(cli) } : void 0,
|
|
7065
7131
|
planModeQuestion: base.planModeQuestion,
|
|
7066
7132
|
turnStats: options.turnStats,
|
|
7067
7133
|
anthropicApiKeyInEnv: base.anthropicApiKeyInEnv,
|
|
@@ -8934,6 +9000,9 @@ var ClaudeSession = class {
|
|
|
8934
9000
|
* (the TUI repaints it while it takes the key, measured on 2.1.288) can
|
|
8935
9001
|
* never stand in for the next call's dialog. */
|
|
8936
9002
|
planDialog = null;
|
|
9003
|
+
/** `queue-operation` enqueue records read, which is how `queueInput` knows
|
|
9004
|
+
* the TUI took a message into the running turn. */
|
|
9005
|
+
enqueued = 0;
|
|
8937
9006
|
/** This turn's `ExitPlanMode` calls already answered. */
|
|
8938
9007
|
answeredPlans = /* @__PURE__ */ new Set();
|
|
8939
9008
|
abandonTurn = false;
|
|
@@ -8992,7 +9061,9 @@ var ClaudeSession = class {
|
|
|
8992
9061
|
// The decision arrives after opencode's own question round trip, by
|
|
8993
9062
|
// which time the dialog has long been drawn; this only bounds a TUI
|
|
8994
9063
|
// that never draws it.
|
|
8995
|
-
planDialogWaitMs: opts.planDialogWaitMs ?? 3e4
|
|
9064
|
+
planDialogWaitMs: opts.planDialogWaitMs ?? 3e4,
|
|
9065
|
+
// 100 times the longest silence measured while Claude works (h #g207).
|
|
9066
|
+
idleEndMs: opts.idleEndMs ?? 2e4
|
|
8996
9067
|
};
|
|
8997
9068
|
}
|
|
8998
9069
|
/** The CLI arguments this session spawns with. */
|
|
@@ -9270,7 +9341,8 @@ var ClaudeSession = class {
|
|
|
9270
9341
|
end: null,
|
|
9271
9342
|
sawUserRecord: false,
|
|
9272
9343
|
lastBeat: Date.now(),
|
|
9273
|
-
awaitingOwnPrompt: this.forkPending ? normalizedPrompt(prompt) : null
|
|
9344
|
+
awaitingOwnPrompt: this.forkPending ? normalizedPrompt(prompt) : null,
|
|
9345
|
+
sawReply: false
|
|
9274
9346
|
};
|
|
9275
9347
|
this.forkPending = false;
|
|
9276
9348
|
this.scan = scan;
|
|
@@ -9293,6 +9365,9 @@ var ClaudeSession = class {
|
|
|
9293
9365
|
if (scan.stopReason && Date.now() - scan.stopSeenAt >= this.o.stopSettleMs) {
|
|
9294
9366
|
return { stopReason: scan.stopReason, end: "stop", denied: this.turnDenied };
|
|
9295
9367
|
}
|
|
9368
|
+
if (scan.sawReply && !this.planApprovalToolUseId && Date.now() - this.lastDataAt >= this.o.idleEndMs && Date.now() - scan.stopSeenAt >= this.o.idleEndMs) {
|
|
9369
|
+
return { stopReason: null, end: "ended", denied: this.turnDenied };
|
|
9370
|
+
}
|
|
9296
9371
|
if (this.exited) throw new Error(this.failureMessage("claude exited mid-turn", true));
|
|
9297
9372
|
if (this.abandonTurn) return { stopReason: null, end: "interrupted", denied: this.turnDenied };
|
|
9298
9373
|
const now = Date.now();
|
|
@@ -9342,9 +9417,11 @@ var ClaudeSession = class {
|
|
|
9342
9417
|
scan.awaitingOwnPrompt = null;
|
|
9343
9418
|
}
|
|
9344
9419
|
if (rec) this.notePlanApproval(rec);
|
|
9420
|
+
if (rec?.type === "queue-operation" && rec.operation === "enqueue") this.enqueued++;
|
|
9345
9421
|
scan.onRecord(s, rec);
|
|
9346
9422
|
if (rec) {
|
|
9347
9423
|
if (rec.type === "assistant" && rec.message) {
|
|
9424
|
+
scan.sawReply = true;
|
|
9348
9425
|
const reason = rec.message.stop_reason;
|
|
9349
9426
|
if (typeof reason === "string") {
|
|
9350
9427
|
scan.stopReason = TERMINAL_STOP.has(reason) ? reason : null;
|
|
@@ -9433,6 +9510,29 @@ var ClaudeSession = class {
|
|
|
9433
9510
|
this.write("\r");
|
|
9434
9511
|
return true;
|
|
9435
9512
|
}
|
|
9513
|
+
/**
|
|
9514
|
+
* Type a message into the running turn's own input queue, not as a turn of
|
|
9515
|
+
* its own (h #g206). Measured on 2.1.288: text pasted and submitted while a
|
|
9516
|
+
* tool call runs is recorded as `queue-operation` enqueue and remove plus a
|
|
9517
|
+
* `queued_command` attachment, answered in the same turn, which still ends
|
|
9518
|
+
* once. Resolves true once the enqueue is in the transcript; false with no
|
|
9519
|
+
* turn running, or with a plan approval dialog up, which would take the
|
|
9520
|
+
* keys as its answer.
|
|
9521
|
+
*/
|
|
9522
|
+
async queueInput(text, timeoutMs = 3e3) {
|
|
9523
|
+
if (!this.turn || !this.proc || this.exited || this.pendingPlanApproval) return false;
|
|
9524
|
+
const before = this.enqueued;
|
|
9525
|
+
this.write(this.o.bracketedPaste ? "\x1B[200~" + text + "\x1B[201~" : text);
|
|
9526
|
+
await delay(this.o.submitMinMs);
|
|
9527
|
+
this.write("\r");
|
|
9528
|
+
const deadline = Date.now() + timeoutMs;
|
|
9529
|
+
while (this.enqueued === before) {
|
|
9530
|
+
if (!this.turn || this.exited || Date.now() >= deadline) return false;
|
|
9531
|
+
await delay(this.o.pollMs);
|
|
9532
|
+
this.scanTranscript();
|
|
9533
|
+
}
|
|
9534
|
+
return true;
|
|
9535
|
+
}
|
|
9436
9536
|
/** Wait until the PTY has been quiet for `permissionQuietMs`, at most 3 s. */
|
|
9437
9537
|
async waitForQuiet() {
|
|
9438
9538
|
const until = Date.now() + 3e3;
|
|
@@ -10058,38 +10158,19 @@ function spawnInteractiveProcess(opts) {
|
|
|
10058
10158
|
},
|
|
10059
10159
|
flushTranscript: () => session.flushTranscript(),
|
|
10060
10160
|
planApprovalPending: () => session.pendingPlanApproval !== null,
|
|
10161
|
+
// Text only: an image in a mid-call message is dropped with the
|
|
10162
|
+
// decoder's own warning rather than staged for a turn that is not ours.
|
|
10163
|
+
queueInput: async (content) => {
|
|
10164
|
+
const text = decodeUserEnvelope(JSON.stringify({ type: "user", message: { role: "user", content } })).trim();
|
|
10165
|
+
if (!text) return false;
|
|
10166
|
+
return session.queueInput(text);
|
|
10167
|
+
},
|
|
10061
10168
|
askAside
|
|
10062
10169
|
}
|
|
10063
10170
|
};
|
|
10064
10171
|
return ap;
|
|
10065
10172
|
}
|
|
10066
10173
|
|
|
10067
|
-
// src/transport.ts
|
|
10068
|
-
function requestedTransport(config, env = process.env.CLAUDE_CODE_INTERACTIVE_TRANSPORT) {
|
|
10069
|
-
if (config.transport !== void 0) {
|
|
10070
|
-
if (!["auto", "headless", "interactive"].includes(config.transport)) {
|
|
10071
|
-
throw new Error(`Unknown Claude transport: ${config.transport}`);
|
|
10072
|
-
}
|
|
10073
|
-
return config.transport;
|
|
10074
|
-
}
|
|
10075
|
-
const enabled = config.interactive ?? (env !== void 0 && !["", "0", "false", "no", "off"].includes(env.trim().toLowerCase()));
|
|
10076
|
-
return enabled ? "interactive" : "headless";
|
|
10077
|
-
}
|
|
10078
|
-
function hasInteractiveTransport() {
|
|
10079
|
-
const runtime = globalThis;
|
|
10080
|
-
return typeof runtime.Bun?.Terminal === "function";
|
|
10081
|
-
}
|
|
10082
|
-
async function selectTransport(requested, cliPath, available = hasInteractiveTransport()) {
|
|
10083
|
-
if (requested === "headless") return "headless";
|
|
10084
|
-
if (requested === "interactive") {
|
|
10085
|
-
if (!available) throw new Error("Interactive Claude transport requires Bun.Terminal. Run opencode under a Bun runtime with PTY support.");
|
|
10086
|
-
return "interactive";
|
|
10087
|
-
}
|
|
10088
|
-
if (await detectHeadlessSupport(cliPath) !== "unsupported") return "headless";
|
|
10089
|
-
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.");
|
|
10090
|
-
return "interactive";
|
|
10091
|
-
}
|
|
10092
|
-
|
|
10093
10174
|
// src/prompts.ts
|
|
10094
10175
|
import { readFileSync as readFileSync7, writeFileSync as writeFileSync6 } from "fs";
|
|
10095
10176
|
import { homedir as homedir8 } from "os";
|
|
@@ -13333,6 +13414,7 @@ var ClaudeCodeLanguageModel = class {
|
|
|
13333
13414
|
return abortedBeforeWork("waiting for opencode's MCP status and the CLI version");
|
|
13334
13415
|
}
|
|
13335
13416
|
const [runtimeStatus, cliVersion] = prologue.value;
|
|
13417
|
+
if (useInteractive) reportUnmeasuredInteractiveCli(cliVersion);
|
|
13336
13418
|
const ptyReadOnly = useInteractive && !compactionMode && !doctor && isReadOnlyPermissionMode(this.config.permissionMode);
|
|
13337
13419
|
const ptyReadOnlySupported = cliSupportsRestricted(cliVersion) && cliSupportsDontAsk(cliVersion);
|
|
13338
13420
|
if (ptyReadOnly && !ptyReadOnlySupported) {
|
|
@@ -14292,9 +14374,10 @@ var ClaudeCodeLanguageModel = class {
|
|
|
14292
14374
|
state.proc.on("error", procErrorHandler);
|
|
14293
14375
|
if (hasMatchedPendingResults) {
|
|
14294
14376
|
state.cliAskedForWork = true;
|
|
14295
|
-
const forwardTrailingUserMessages = () => {
|
|
14377
|
+
const forwardTrailingUserMessages = async () => {
|
|
14296
14378
|
if (compactionMode || !state.activeProcess) return 0;
|
|
14297
|
-
|
|
14379
|
+
const control = state.activeProcess.interactiveControl;
|
|
14380
|
+
if (control && (!control.queueInput || !control.turnRunning())) return 0;
|
|
14298
14381
|
const trailing = getTrailingUserMessages(effectivePrompt, {
|
|
14299
14382
|
stripContextReminders: self.stripContextRemindersEnabled()
|
|
14300
14383
|
});
|
|
@@ -14305,6 +14388,21 @@ var ClaudeCodeLanguageModel = class {
|
|
|
14305
14388
|
assistantIndex: trailing.assistantIndex,
|
|
14306
14389
|
count: trailing.messages.length
|
|
14307
14390
|
};
|
|
14391
|
+
if (control) {
|
|
14392
|
+
let queued = 0;
|
|
14393
|
+
for (const content of fresh) if (await control.queueInput(content)) queued++;
|
|
14394
|
+
if (queued < fresh.length) {
|
|
14395
|
+
log.warn("the interactive turn did not take a forwarded user message", {
|
|
14396
|
+
sessionKey: sk,
|
|
14397
|
+
messages: fresh.length - queued
|
|
14398
|
+
});
|
|
14399
|
+
}
|
|
14400
|
+
log.info("forwarded user messages into the interactive turn's input queue", {
|
|
14401
|
+
sessionKey: sk,
|
|
14402
|
+
messages: queued
|
|
14403
|
+
});
|
|
14404
|
+
return queued;
|
|
14405
|
+
}
|
|
14308
14406
|
for (const content of fresh) {
|
|
14309
14407
|
state.proc.stdin?.write(
|
|
14310
14408
|
JSON.stringify({ type: "user", message: { role: "user", content } }) + "\n"
|
|
@@ -14316,7 +14414,7 @@ var ClaudeCodeLanguageModel = class {
|
|
|
14316
14414
|
});
|
|
14317
14415
|
return fresh.length;
|
|
14318
14416
|
};
|
|
14319
|
-
if (!state.unattendedTurnEnded && forwardTrailingUserMessages() > 0) {
|
|
14417
|
+
if (!state.unattendedTurnEnded && await forwardTrailingUserMessages() > 0) {
|
|
14320
14418
|
await new Promise((resolve6) => setTimeout(resolve6, FORWARD_SETTLE_MS));
|
|
14321
14419
|
if (state.controllerClosed) return;
|
|
14322
14420
|
}
|
|
@@ -14351,7 +14449,7 @@ var ClaudeCodeLanguageModel = class {
|
|
|
14351
14449
|
}
|
|
14352
14450
|
if (state.unattendedTurnEnded) {
|
|
14353
14451
|
deliverPendingCompletions(state);
|
|
14354
|
-
forwardTrailingUserMessages();
|
|
14452
|
+
await forwardTrailingUserMessages();
|
|
14355
14453
|
}
|
|
14356
14454
|
const unemitted = getPendingProxyCalls(sk).filter(
|
|
14357
14455
|
(call) => !call.emitted
|