@khalilgharbaoui/opencode-claude-code-plugin 0.2.5 → 0.3.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 +1 -0
- package/dist/index.js +79 -12
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -145,7 +145,7 @@ function mapTool(name, input, opts) {
|
|
|
145
145
|
const toolName = parts.slice(1).join("_");
|
|
146
146
|
const openCodeName = `${serverName}_${toolName}`;
|
|
147
147
|
log.debug("mapping MCP tool", { original: name, mapped: openCodeName });
|
|
148
|
-
return { name: openCodeName, input, executed:
|
|
148
|
+
return { name: openCodeName, input, executed: true };
|
|
149
149
|
}
|
|
150
150
|
}
|
|
151
151
|
if (OPENCODE_HANDLED_TOOLS.has(name)) {
|
|
@@ -825,10 +825,12 @@ function buildCliArgs(opts) {
|
|
|
825
825
|
appendSystemPromptFile
|
|
826
826
|
} = opts;
|
|
827
827
|
const args = [
|
|
828
|
+
"--print",
|
|
828
829
|
"--output-format",
|
|
829
830
|
"stream-json",
|
|
830
831
|
"--input-format",
|
|
831
832
|
"stream-json",
|
|
833
|
+
"--include-partial-messages",
|
|
832
834
|
"--verbose"
|
|
833
835
|
];
|
|
834
836
|
if (model) {
|
|
@@ -1267,6 +1269,25 @@ import { unlink as unlink2 } from "fs/promises";
|
|
|
1267
1269
|
import { homedir as homedir2, tmpdir as tmpdir3 } from "os";
|
|
1268
1270
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
1269
1271
|
import { dirname as dirname2, join as join3 } from "path";
|
|
1272
|
+
function hasNewUserContent(prompt) {
|
|
1273
|
+
for (let i = prompt.length - 1; i >= 0; i--) {
|
|
1274
|
+
const msg = prompt[i];
|
|
1275
|
+
if (msg.role === "assistant") return false;
|
|
1276
|
+
if (msg.role !== "user") continue;
|
|
1277
|
+
const content = msg.content;
|
|
1278
|
+
if (typeof content === "string") {
|
|
1279
|
+
if (content.trim()) return true;
|
|
1280
|
+
continue;
|
|
1281
|
+
}
|
|
1282
|
+
if (Array.isArray(content)) {
|
|
1283
|
+
for (const part of content) {
|
|
1284
|
+
if (part.type === "text" && part.text && part.text.trim()) return true;
|
|
1285
|
+
if (part.type === "tool-result") return true;
|
|
1286
|
+
}
|
|
1287
|
+
}
|
|
1288
|
+
}
|
|
1289
|
+
return false;
|
|
1290
|
+
}
|
|
1270
1291
|
function readPromptFileIfPresent(path4) {
|
|
1271
1292
|
try {
|
|
1272
1293
|
const content = readFileSync2(path4, "utf8").trim();
|
|
@@ -1692,6 +1713,24 @@ var ClaudeCodeLanguageModel = class {
|
|
|
1692
1713
|
warnings
|
|
1693
1714
|
};
|
|
1694
1715
|
}
|
|
1716
|
+
if (!hasNewUserContent(options.prompt)) {
|
|
1717
|
+
log.info("doGenerate short-circuit: no new user content");
|
|
1718
|
+
return {
|
|
1719
|
+
content: [],
|
|
1720
|
+
finishReason: this.toFinishReason("stop"),
|
|
1721
|
+
usage: this.toUsage({ input_tokens: 0, output_tokens: 0 }),
|
|
1722
|
+
request: { body: { text: "" } },
|
|
1723
|
+
response: {
|
|
1724
|
+
id: generateId(),
|
|
1725
|
+
timestamp: /* @__PURE__ */ new Date(),
|
|
1726
|
+
modelId: this.modelId
|
|
1727
|
+
},
|
|
1728
|
+
providerMetadata: {
|
|
1729
|
+
"claude-code": { synthetic: true, path: "no-new-user-content" }
|
|
1730
|
+
},
|
|
1731
|
+
warnings
|
|
1732
|
+
};
|
|
1733
|
+
}
|
|
1695
1734
|
const hasPriorConversation = options.prompt.filter((m) => m.role === "user" || m.role === "assistant").length > 1;
|
|
1696
1735
|
if (!hasPriorConversation) {
|
|
1697
1736
|
deleteClaudeSessionId(sk);
|
|
@@ -1743,11 +1782,16 @@ var ClaudeCodeLanguageModel = class {
|
|
|
1743
1782
|
let thinkingText = "";
|
|
1744
1783
|
let resultMeta = {};
|
|
1745
1784
|
const toolCalls = [];
|
|
1785
|
+
let gotPartialEvents = false;
|
|
1746
1786
|
const result = await new Promise((resolve3, reject) => {
|
|
1747
1787
|
rl.on("line", (line) => {
|
|
1748
1788
|
if (!line.trim()) return;
|
|
1749
1789
|
try {
|
|
1750
|
-
const
|
|
1790
|
+
const outer = JSON.parse(line);
|
|
1791
|
+
const msg = outer.type === "stream_event" && outer.event ? { ...outer.event, session_id: outer.session_id } : outer;
|
|
1792
|
+
if (outer.type === "stream_event") {
|
|
1793
|
+
gotPartialEvents = true;
|
|
1794
|
+
}
|
|
1751
1795
|
if (this.handleControlRequest(msg, proc)) {
|
|
1752
1796
|
return;
|
|
1753
1797
|
}
|
|
@@ -1756,7 +1800,7 @@ var ClaudeCodeLanguageModel = class {
|
|
|
1756
1800
|
setClaudeSessionId(sk, msg.session_id);
|
|
1757
1801
|
}
|
|
1758
1802
|
}
|
|
1759
|
-
if (msg.type === "assistant" && msg.message?.content) {
|
|
1803
|
+
if (msg.type === "assistant" && msg.message?.content && !gotPartialEvents) {
|
|
1760
1804
|
for (const block of msg.message.content) {
|
|
1761
1805
|
if (block.type === "text" && block.text) {
|
|
1762
1806
|
responseText += block.text;
|
|
@@ -1975,6 +2019,24 @@ ${plan}
|
|
|
1975
2019
|
request: { body: { text: "" } }
|
|
1976
2020
|
};
|
|
1977
2021
|
}
|
|
2022
|
+
if (!hasNewUserContent(options.prompt)) {
|
|
2023
|
+
log.info("doStream short-circuit: no new user content");
|
|
2024
|
+
const stream2 = new ReadableStream({
|
|
2025
|
+
start(controller) {
|
|
2026
|
+
controller.enqueue({ type: "stream-start", warnings });
|
|
2027
|
+
controller.enqueue({
|
|
2028
|
+
type: "finish",
|
|
2029
|
+
finishReason: toFinishReason("stop"),
|
|
2030
|
+
usage: toUsage({ input_tokens: 0, output_tokens: 0 }),
|
|
2031
|
+
providerMetadata: {
|
|
2032
|
+
"claude-code": { synthetic: true, path: "no-new-user-content" }
|
|
2033
|
+
}
|
|
2034
|
+
});
|
|
2035
|
+
controller.close();
|
|
2036
|
+
}
|
|
2037
|
+
});
|
|
2038
|
+
return { stream: stream2, request: { body: { text: "" } } };
|
|
2039
|
+
}
|
|
1978
2040
|
const hasPriorConversation = options.prompt.filter((m) => m.role === "user" || m.role === "assistant").length > 1;
|
|
1979
2041
|
if (!hasPriorConversation) {
|
|
1980
2042
|
deleteClaudeSessionId(sk);
|
|
@@ -2096,14 +2158,16 @@ ${plan}
|
|
|
2096
2158
|
resultFallbackTimer = null;
|
|
2097
2159
|
}
|
|
2098
2160
|
};
|
|
2099
|
-
const startResultFallback = () => {
|
|
2161
|
+
const startResultFallback = (delayMs = 6e4) => {
|
|
2100
2162
|
clearFallbackTimer();
|
|
2101
2163
|
if (!hasReceivedContent || controllerClosed) return;
|
|
2102
2164
|
resultFallbackTimer = setTimeout(() => {
|
|
2103
2165
|
if (controllerClosed) return;
|
|
2104
|
-
log.warn("result fallback timer fired \u2014 closing stream without result event"
|
|
2166
|
+
log.warn("result fallback timer fired \u2014 closing stream without result event", {
|
|
2167
|
+
delayMs
|
|
2168
|
+
});
|
|
2105
2169
|
closeHandler();
|
|
2106
|
-
},
|
|
2170
|
+
}, delayMs);
|
|
2107
2171
|
};
|
|
2108
2172
|
const toolCallMap = /* @__PURE__ */ new Map();
|
|
2109
2173
|
const skipResultForIds = /* @__PURE__ */ new Set();
|
|
@@ -2139,11 +2203,17 @@ ${plan}
|
|
|
2139
2203
|
} catch {
|
|
2140
2204
|
}
|
|
2141
2205
|
};
|
|
2206
|
+
let gotPartialEvents = false;
|
|
2142
2207
|
const lineHandler = (line) => {
|
|
2143
2208
|
if (!line.trim()) return;
|
|
2144
2209
|
if (controllerClosed) return;
|
|
2210
|
+
startResultFallback();
|
|
2145
2211
|
try {
|
|
2146
|
-
const
|
|
2212
|
+
const outer = JSON.parse(line);
|
|
2213
|
+
const msg = outer.type === "stream_event" && outer.event ? { ...outer.event, session_id: outer.session_id } : outer;
|
|
2214
|
+
if (outer.type === "stream_event") {
|
|
2215
|
+
gotPartialEvents = true;
|
|
2216
|
+
}
|
|
2147
2217
|
if (handleControlRequest(msg, proc)) {
|
|
2148
2218
|
return;
|
|
2149
2219
|
}
|
|
@@ -2172,7 +2242,6 @@ ${plan}
|
|
|
2172
2242
|
reasoningStarted.set(idx, true);
|
|
2173
2243
|
}
|
|
2174
2244
|
if (block.type === "text") {
|
|
2175
|
-
clearFallbackTimer();
|
|
2176
2245
|
textBlockIndices.add(idx);
|
|
2177
2246
|
if (block.text) {
|
|
2178
2247
|
if (!currentTextId) startTextBlock();
|
|
@@ -2185,7 +2254,6 @@ ${plan}
|
|
|
2185
2254
|
}
|
|
2186
2255
|
}
|
|
2187
2256
|
if (block.type === "tool_use" && block.id && block.name) {
|
|
2188
|
-
clearFallbackTimer();
|
|
2189
2257
|
toolCallMap.set(idx, {
|
|
2190
2258
|
id: block.id,
|
|
2191
2259
|
name: block.name,
|
|
@@ -2260,7 +2328,6 @@ ${plan}
|
|
|
2260
2328
|
if (textBlockIndices.has(idx)) {
|
|
2261
2329
|
endTextBlock();
|
|
2262
2330
|
textBlockIndices.delete(idx);
|
|
2263
|
-
startResultFallback();
|
|
2264
2331
|
}
|
|
2265
2332
|
const tc = toolCallMap.get(idx);
|
|
2266
2333
|
if (tc) {
|
|
@@ -2338,7 +2405,7 @@ ${plan}
|
|
|
2338
2405
|
}
|
|
2339
2406
|
}
|
|
2340
2407
|
}
|
|
2341
|
-
if (msg.type === "assistant" && msg.message?.content) {
|
|
2408
|
+
if (msg.type === "assistant" && msg.message?.content && !gotPartialEvents) {
|
|
2342
2409
|
const hasText = msg.message.content.some(
|
|
2343
2410
|
(b) => b.type === "text" && b.text
|
|
2344
2411
|
);
|
|
@@ -2637,7 +2704,7 @@ ${plan}
|
|
|
2637
2704
|
"abort signal received mid-turn, starting grace period",
|
|
2638
2705
|
{ cwd }
|
|
2639
2706
|
);
|
|
2640
|
-
startResultFallback();
|
|
2707
|
+
startResultFallback(5e3);
|
|
2641
2708
|
});
|
|
2642
2709
|
}
|
|
2643
2710
|
if (pendingProxyCall && pendingProxyResult) {
|