@botconnector/bccli 0.4.2 → 0.4.4
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/{acp-UYC6APR5.js → acp-SWBX4TT6.js} +2 -2
- package/dist/{args-NRTZWWEV.js → args-UCLW7NID.js} +2 -2
- package/dist/{chunk-TIMSYZIR.js → chunk-5BVC3Y6B.js} +2 -2
- package/dist/{chunk-266SY3MC.js → chunk-CGBSE55G.js} +1 -1
- package/dist/{chunk-R72OV7RF.js → chunk-FI7RUJRX.js} +255 -71
- package/dist/{chunk-ZEPTUKNW.js → chunk-HBQ6OLQT.js} +76 -20
- package/dist/{chunk-5YJ3ZQVR.js → chunk-MSDK4IIJ.js} +9 -7
- package/dist/{chunk-IYR5PYA3.js → chunk-OZ5GHMTN.js} +1 -1
- package/dist/{chunk-KPTML72Q.js → chunk-QQJ2VVIW.js} +8 -0
- package/dist/{chunk-H7XJDKJY.js → chunk-RZF6A43N.js} +1 -1
- package/dist/{chunk-SVD4LHJC.js → chunk-SMTBYDNO.js} +1 -1
- package/dist/{chunk-6UO5GX55.js → chunk-TGGKACSE.js} +1 -1
- package/dist/{chunk-C64KM37J.js → chunk-YCHCHOMK.js} +5 -1
- package/dist/cli.js +22 -22
- package/dist/{ghBotCli-TSLRORJJ.js → ghBotCli-ZVWU7EMG.js} +8 -8
- package/dist/{login-RYESFZG6.js → login-QPUWIC76.js} +1 -1
- package/dist/lsp.d.ts +23 -0
- package/dist/{modelsCli-OP7CDZC7.js → modelsCli-SZK4E2BY.js} +3 -3
- package/dist/{providerCli-5OZI2GQQ.js → providerCli-PKI7B2SC.js} +4 -4
- package/dist/sdk.js +341 -92
- package/dist/{serve-4J7HA4JO.js → serve-L3SAIAAI.js} +9 -9
- package/dist/{session-YQXCCKXI.js → session-ASXO6GXR.js} +3 -3
- package/dist/{setup-S4AJT6XE.js → setup-F7FZ66OS.js} +7 -7
- package/dist/tools/diagnostics.d.ts +8 -0
- package/dist/tools/sandbox.d.ts +3 -0
- package/dist/{transferCli-R2KEIWQR.js → transferCli-HKGAWZ3Q.js} +3 -3
- package/dist/{ui-36ZEK65V.js → ui-NPA52YJH.js} +45 -9
- package/dist/{update-FSS7X5WV.js → update-AFIM34US.js} +1 -1
- package/package.json +1 -1
|
@@ -180,8 +180,8 @@ function runtimeAgent(cwd, allowAll = false) {
|
|
|
180
180
|
return {
|
|
181
181
|
async run(text, onChunk, signal, io) {
|
|
182
182
|
if (!rt) {
|
|
183
|
-
const { parseCliArgs } = await import("./args-
|
|
184
|
-
const { createRuntime } = await import("./setup-
|
|
183
|
+
const { parseCliArgs } = await import("./args-UCLW7NID.js");
|
|
184
|
+
const { createRuntime } = await import("./setup-F7FZ66OS.js");
|
|
185
185
|
rt = createRuntime({ cwd, args: { ...parseCliArgs([]), allowAll } });
|
|
186
186
|
}
|
|
187
187
|
if (io && !allowAll) rt.agent.askPermission = (req) => io.askPermission(req);
|
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
import {
|
|
3
3
|
helpText,
|
|
4
4
|
parseCliArgs
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-TGGKACSE.js";
|
|
6
6
|
import "./chunk-WFZKJY3R.js";
|
|
7
|
-
import "./chunk-
|
|
7
|
+
import "./chunk-QQJ2VVIW.js";
|
|
8
8
|
import "./chunk-RX4UQX43.js";
|
|
9
9
|
import "./chunk-3WHI4LN3.js";
|
|
10
10
|
export {
|
|
@@ -91,8 +91,8 @@ function defaultLoginDeps() {
|
|
|
91
91
|
fetch: globalThis.fetch,
|
|
92
92
|
// Wiring NYATA jalur lama: persis runLogin lama (provider add + prompt key).
|
|
93
93
|
legacyAdd: async (providerId, targetCwd) => {
|
|
94
|
-
const { runProviderCommand } = await import("./providerCli-
|
|
95
|
-
const { parseCliArgs: parse } = await import("./args-
|
|
94
|
+
const { runProviderCommand } = await import("./providerCli-PKI7B2SC.js");
|
|
95
|
+
const { parseCliArgs: parse } = await import("./args-UCLW7NID.js");
|
|
96
96
|
return runProviderCommand(parse(["provider", "add", providerId]), {
|
|
97
97
|
env: process.env,
|
|
98
98
|
cwd: targetCwd,
|
|
@@ -24,7 +24,7 @@ import {
|
|
|
24
24
|
resolvePath,
|
|
25
25
|
runHooks,
|
|
26
26
|
validateGlobPattern
|
|
27
|
-
} from "./chunk-
|
|
27
|
+
} from "./chunk-HBQ6OLQT.js";
|
|
28
28
|
import {
|
|
29
29
|
createWebSearchTool,
|
|
30
30
|
fetchTool
|
|
@@ -37,10 +37,10 @@ import {
|
|
|
37
37
|
} from "./chunk-WFZKJY3R.js";
|
|
38
38
|
import {
|
|
39
39
|
addProviderKey
|
|
40
|
-
} from "./chunk-
|
|
40
|
+
} from "./chunk-RZF6A43N.js";
|
|
41
41
|
import {
|
|
42
42
|
listAllModels
|
|
43
|
-
} from "./chunk-
|
|
43
|
+
} from "./chunk-OZ5GHMTN.js";
|
|
44
44
|
import {
|
|
45
45
|
providerName
|
|
46
46
|
} from "./chunk-HQW4BROS.js";
|
|
@@ -50,14 +50,14 @@ import {
|
|
|
50
50
|
} from "./chunk-3I5BW3ZT.js";
|
|
51
51
|
import {
|
|
52
52
|
Session
|
|
53
|
-
} from "./chunk-
|
|
53
|
+
} from "./chunk-SMTBYDNO.js";
|
|
54
54
|
import {
|
|
55
55
|
completionAssistantMessage,
|
|
56
56
|
createProvider,
|
|
57
57
|
hasPendingProgrammaticReplay,
|
|
58
58
|
imageUserMessage,
|
|
59
59
|
withFallbackProvider
|
|
60
|
-
} from "./chunk-
|
|
60
|
+
} from "./chunk-MSDK4IIJ.js";
|
|
61
61
|
import {
|
|
62
62
|
expandEnvVars
|
|
63
63
|
} from "./chunk-6M55UPES.js";
|
|
@@ -1914,14 +1914,14 @@ function createRepoMapTool() {
|
|
|
1914
1914
|
}
|
|
1915
1915
|
|
|
1916
1916
|
// src/tools/diagnostics.ts
|
|
1917
|
-
import { extname as extname3 } from "path";
|
|
1917
|
+
import { extname as extname3, relative as relative2 } from "path";
|
|
1918
1918
|
import { z as z14 } from "zod";
|
|
1919
1919
|
|
|
1920
1920
|
// src/lsp.ts
|
|
1921
1921
|
import { spawn } from "child_process";
|
|
1922
1922
|
import { readFileSync as readFileSync4 } from "fs";
|
|
1923
1923
|
import { extname as extname2 } from "path";
|
|
1924
|
-
import { pathToFileURL } from "url";
|
|
1924
|
+
import { fileURLToPath, pathToFileURL } from "url";
|
|
1925
1925
|
var LANGUAGE_IDS = {
|
|
1926
1926
|
".ts": "typescript",
|
|
1927
1927
|
".tsx": "typescriptreact",
|
|
@@ -1989,86 +1989,253 @@ function createLspParser(onMessage) {
|
|
|
1989
1989
|
}
|
|
1990
1990
|
};
|
|
1991
1991
|
}
|
|
1992
|
-
function
|
|
1993
|
-
|
|
1994
|
-
|
|
1995
|
-
|
|
1996
|
-
|
|
1997
|
-
|
|
1992
|
+
function extractHoverText(contents) {
|
|
1993
|
+
if (!contents) return "";
|
|
1994
|
+
if (typeof contents === "string") return contents.trim();
|
|
1995
|
+
if (Array.isArray(contents)) return contents.map(extractHoverText).filter(Boolean).join("\n\n");
|
|
1996
|
+
if (typeof contents === "object" && "value" in contents && typeof contents.value === "string") {
|
|
1997
|
+
return contents.value.trim();
|
|
1998
|
+
}
|
|
1999
|
+
return "";
|
|
2000
|
+
}
|
|
2001
|
+
function normalizeLocations(raw) {
|
|
2002
|
+
const items = Array.isArray(raw) ? raw : raw ? [raw] : [];
|
|
2003
|
+
const out = [];
|
|
2004
|
+
for (const item of items) {
|
|
2005
|
+
if (!item || typeof item !== "object") continue;
|
|
2006
|
+
const rec = item;
|
|
2007
|
+
const uri = rec.uri ?? rec.targetUri;
|
|
2008
|
+
const start = rec.range?.start ?? rec.targetSelectionRange?.start ?? rec.targetRange?.start;
|
|
2009
|
+
if (!uri) continue;
|
|
2010
|
+
let path = uri;
|
|
2011
|
+
try {
|
|
2012
|
+
if (uri.startsWith("file:")) path = fileURLToPath(uri);
|
|
2013
|
+
} catch {
|
|
2014
|
+
}
|
|
2015
|
+
out.push({
|
|
2016
|
+
uri,
|
|
2017
|
+
path,
|
|
2018
|
+
line: start?.line ?? 0,
|
|
2019
|
+
character: start?.character ?? 0
|
|
1998
2020
|
});
|
|
1999
|
-
|
|
2000
|
-
|
|
2001
|
-
|
|
2002
|
-
|
|
2003
|
-
|
|
2004
|
-
|
|
2005
|
-
|
|
2006
|
-
|
|
2007
|
-
|
|
2008
|
-
|
|
2009
|
-
|
|
2010
|
-
|
|
2011
|
-
|
|
2012
|
-
|
|
2013
|
-
|
|
2014
|
-
|
|
2015
|
-
|
|
2016
|
-
|
|
2017
|
-
|
|
2018
|
-
|
|
2021
|
+
}
|
|
2022
|
+
return out;
|
|
2023
|
+
}
|
|
2024
|
+
function createWarmLspClient(opts) {
|
|
2025
|
+
let child;
|
|
2026
|
+
let initPromise;
|
|
2027
|
+
let nextId = 2;
|
|
2028
|
+
const opened = /* @__PURE__ */ new Map();
|
|
2029
|
+
const pendingRpc = /* @__PURE__ */ new Map();
|
|
2030
|
+
const diagWaiters = /* @__PURE__ */ new Map();
|
|
2031
|
+
const send = (msg) => {
|
|
2032
|
+
try {
|
|
2033
|
+
child?.stdin?.write(encodeLsp(msg));
|
|
2034
|
+
} catch {
|
|
2035
|
+
}
|
|
2036
|
+
};
|
|
2037
|
+
const resetState = () => {
|
|
2038
|
+
child = void 0;
|
|
2039
|
+
initPromise = void 0;
|
|
2040
|
+
opened.clear();
|
|
2041
|
+
for (const [, resolve] of pendingRpc) resolve(void 0);
|
|
2042
|
+
pendingRpc.clear();
|
|
2043
|
+
for (const [, waiters] of diagWaiters) {
|
|
2044
|
+
for (const w of waiters) w([]);
|
|
2045
|
+
}
|
|
2046
|
+
diagWaiters.clear();
|
|
2047
|
+
};
|
|
2048
|
+
const ensureStarted = () => {
|
|
2049
|
+
if (initPromise && child && !child.killed) return initPromise;
|
|
2050
|
+
opened.clear();
|
|
2051
|
+
initPromise = new Promise((resolveInit) => {
|
|
2052
|
+
const proc = spawn(opts.server.command, opts.server.args ?? [], {
|
|
2053
|
+
cwd: opts.cwd,
|
|
2054
|
+
stdio: ["pipe", "pipe", "ignore"],
|
|
2055
|
+
shell: useShellForLsp(opts.server.command)
|
|
2056
|
+
});
|
|
2057
|
+
child = proc;
|
|
2058
|
+
let initSettled = false;
|
|
2059
|
+
const settleInit = () => {
|
|
2060
|
+
if (!initSettled) {
|
|
2061
|
+
initSettled = true;
|
|
2062
|
+
resolveInit();
|
|
2019
2063
|
}
|
|
2020
|
-
}
|
|
2021
|
-
|
|
2022
|
-
|
|
2023
|
-
|
|
2024
|
-
|
|
2025
|
-
|
|
2026
|
-
opts.signal?.addEventListener("abort", onAbort, { once: true });
|
|
2027
|
-
const timer = setTimeout(() => finish([]), opts.timeoutMs ?? 8e3);
|
|
2028
|
-
const parser = createLspParser((msg) => {
|
|
2029
|
-
if (msg.id === 1 && msg.result) {
|
|
2030
|
-
send({ jsonrpc: "2.0", method: "initialized", params: {} });
|
|
2031
|
-
let text = "";
|
|
2032
|
-
try {
|
|
2033
|
-
text = readFileSync4(opts.file, "utf8");
|
|
2034
|
-
} catch {
|
|
2064
|
+
};
|
|
2065
|
+
const parser = createLspParser((msg) => {
|
|
2066
|
+
if (msg.id === 1 && msg.result !== void 0) {
|
|
2067
|
+
send({ jsonrpc: "2.0", method: "initialized", params: {} });
|
|
2068
|
+
settleInit();
|
|
2069
|
+
return;
|
|
2035
2070
|
}
|
|
2036
|
-
|
|
2037
|
-
|
|
2038
|
-
|
|
2039
|
-
|
|
2040
|
-
|
|
2041
|
-
|
|
2042
|
-
|
|
2043
|
-
|
|
2044
|
-
(msg.params.diagnostics ?? []).map((d) => ({
|
|
2071
|
+
if (msg.id !== void 0 && pendingRpc.has(msg.id)) {
|
|
2072
|
+
const fn = pendingRpc.get(msg.id);
|
|
2073
|
+
pendingRpc.delete(msg.id);
|
|
2074
|
+
fn?.(msg.result);
|
|
2075
|
+
return;
|
|
2076
|
+
}
|
|
2077
|
+
if (msg.method === "textDocument/publishDiagnostics" && msg.params?.uri) {
|
|
2078
|
+
const uri = msg.params.uri;
|
|
2079
|
+
const diags = (msg.params.diagnostics ?? []).map((d) => ({
|
|
2045
2080
|
line: d.range?.start?.line ?? 0,
|
|
2046
2081
|
character: d.range?.start?.character ?? 0,
|
|
2047
2082
|
severity: d.severity ?? 1,
|
|
2048
2083
|
message: String(d.message ?? "")
|
|
2049
|
-
}))
|
|
2050
|
-
|
|
2051
|
-
|
|
2084
|
+
}));
|
|
2085
|
+
const list = diagWaiters.get(uri);
|
|
2086
|
+
if (list?.length) {
|
|
2087
|
+
diagWaiters.delete(uri);
|
|
2088
|
+
for (const w of list) w(diags);
|
|
2089
|
+
}
|
|
2090
|
+
}
|
|
2091
|
+
});
|
|
2092
|
+
proc.stdout?.on("data", (c) => parser.push(c));
|
|
2093
|
+
proc.on("error", () => {
|
|
2094
|
+
resetState();
|
|
2095
|
+
settleInit();
|
|
2096
|
+
});
|
|
2097
|
+
proc.on("close", () => {
|
|
2098
|
+
resetState();
|
|
2099
|
+
settleInit();
|
|
2100
|
+
});
|
|
2101
|
+
send({
|
|
2102
|
+
jsonrpc: "2.0",
|
|
2103
|
+
id: 1,
|
|
2104
|
+
method: "initialize",
|
|
2105
|
+
params: { processId: process.pid, capabilities: {}, rootUri: pathToFileURL(opts.cwd).href }
|
|
2106
|
+
});
|
|
2052
2107
|
});
|
|
2053
|
-
|
|
2054
|
-
|
|
2055
|
-
|
|
2056
|
-
|
|
2057
|
-
|
|
2058
|
-
|
|
2059
|
-
|
|
2060
|
-
|
|
2108
|
+
return initPromise;
|
|
2109
|
+
};
|
|
2110
|
+
const syncDocument = (file) => {
|
|
2111
|
+
const uri = pathToFileURL(file).href;
|
|
2112
|
+
let text = "";
|
|
2113
|
+
try {
|
|
2114
|
+
text = readFileSync4(file, "utf8");
|
|
2115
|
+
} catch {
|
|
2116
|
+
}
|
|
2117
|
+
const prevVersion = opened.get(uri);
|
|
2118
|
+
if (prevVersion === void 0) {
|
|
2119
|
+
opened.set(uri, 1);
|
|
2120
|
+
send({
|
|
2121
|
+
jsonrpc: "2.0",
|
|
2122
|
+
method: "textDocument/didOpen",
|
|
2123
|
+
params: { textDocument: { uri, languageId: languageIdFor(file), version: 1, text } }
|
|
2124
|
+
});
|
|
2125
|
+
} else {
|
|
2126
|
+
const version = prevVersion + 1;
|
|
2127
|
+
opened.set(uri, version);
|
|
2128
|
+
send({
|
|
2129
|
+
jsonrpc: "2.0",
|
|
2130
|
+
method: "textDocument/didChange",
|
|
2131
|
+
params: {
|
|
2132
|
+
textDocument: { uri, version },
|
|
2133
|
+
contentChanges: [{ text }]
|
|
2134
|
+
}
|
|
2135
|
+
});
|
|
2136
|
+
}
|
|
2137
|
+
return uri;
|
|
2138
|
+
};
|
|
2139
|
+
const request = (method, params, timeoutMs = opts.timeoutMs ?? 8e3) => new Promise((resolve) => {
|
|
2140
|
+
const id = nextId++;
|
|
2141
|
+
const timer = setTimeout(() => {
|
|
2142
|
+
pendingRpc.delete(id);
|
|
2143
|
+
resolve(void 0);
|
|
2144
|
+
}, timeoutMs);
|
|
2145
|
+
pendingRpc.set(id, (res) => {
|
|
2146
|
+
clearTimeout(timer);
|
|
2147
|
+
resolve(res);
|
|
2061
2148
|
});
|
|
2149
|
+
send({ jsonrpc: "2.0", id, method, params });
|
|
2062
2150
|
});
|
|
2151
|
+
return {
|
|
2152
|
+
async diagnostics(file, timeoutMs = opts.timeoutMs ?? 8e3) {
|
|
2153
|
+
await ensureStarted();
|
|
2154
|
+
if (!child) return [];
|
|
2155
|
+
const uri = pathToFileURL(file).href;
|
|
2156
|
+
return new Promise((resolve) => {
|
|
2157
|
+
const timer = setTimeout(() => {
|
|
2158
|
+
const list2 = diagWaiters.get(uri) ?? [];
|
|
2159
|
+
diagWaiters.set(
|
|
2160
|
+
uri,
|
|
2161
|
+
list2.filter((w) => w !== onDiag)
|
|
2162
|
+
);
|
|
2163
|
+
resolve([]);
|
|
2164
|
+
}, timeoutMs);
|
|
2165
|
+
const onDiag = (diags) => {
|
|
2166
|
+
clearTimeout(timer);
|
|
2167
|
+
resolve(diags);
|
|
2168
|
+
};
|
|
2169
|
+
const list = diagWaiters.get(uri) ?? [];
|
|
2170
|
+
list.push(onDiag);
|
|
2171
|
+
diagWaiters.set(uri, list);
|
|
2172
|
+
syncDocument(file);
|
|
2173
|
+
});
|
|
2174
|
+
},
|
|
2175
|
+
async hover(file, line, character, timeoutMs) {
|
|
2176
|
+
await ensureStarted();
|
|
2177
|
+
if (!child) return "";
|
|
2178
|
+
const uri = syncDocument(file);
|
|
2179
|
+
const res = await request("textDocument/hover", { textDocument: { uri }, position: { line, character } }, timeoutMs);
|
|
2180
|
+
return extractHoverText(res?.contents);
|
|
2181
|
+
},
|
|
2182
|
+
async definition(file, line, character, timeoutMs) {
|
|
2183
|
+
await ensureStarted();
|
|
2184
|
+
if (!child) return [];
|
|
2185
|
+
const uri = syncDocument(file);
|
|
2186
|
+
const res = await request("textDocument/definition", { textDocument: { uri }, position: { line, character } }, timeoutMs);
|
|
2187
|
+
return normalizeLocations(res);
|
|
2188
|
+
},
|
|
2189
|
+
async references(file, line, character, timeoutMs) {
|
|
2190
|
+
await ensureStarted();
|
|
2191
|
+
if (!child) return [];
|
|
2192
|
+
const uri = syncDocument(file);
|
|
2193
|
+
const res = await request(
|
|
2194
|
+
"textDocument/references",
|
|
2195
|
+
{ textDocument: { uri }, position: { line, character }, context: { includeDeclaration: true } },
|
|
2196
|
+
timeoutMs
|
|
2197
|
+
);
|
|
2198
|
+
return normalizeLocations(res);
|
|
2199
|
+
},
|
|
2200
|
+
async close() {
|
|
2201
|
+
if (!child) return;
|
|
2202
|
+
const proc = child;
|
|
2203
|
+
send({ jsonrpc: "2.0", id: nextId++, method: "shutdown" });
|
|
2204
|
+
send({ jsonrpc: "2.0", method: "exit" });
|
|
2205
|
+
resetState();
|
|
2206
|
+
const killer = setTimeout(() => {
|
|
2207
|
+
try {
|
|
2208
|
+
proc.kill();
|
|
2209
|
+
} catch {
|
|
2210
|
+
}
|
|
2211
|
+
}, 200);
|
|
2212
|
+
killer.unref?.();
|
|
2213
|
+
}
|
|
2214
|
+
};
|
|
2063
2215
|
}
|
|
2064
2216
|
|
|
2065
2217
|
// src/tools/diagnostics.ts
|
|
2066
2218
|
var SEVERITY = { 1: "error", 2: "warning", 3: "info", 4: "hint" };
|
|
2067
|
-
var SCHEMA = z14.object({
|
|
2219
|
+
var SCHEMA = z14.object({
|
|
2220
|
+
path: z14.string().describe("File to check (absolute or relative to the working directory)"),
|
|
2221
|
+
action: z14.enum(["diagnostics", "hover", "definition", "references"]).optional().describe("LSP query action, default diagnostics"),
|
|
2222
|
+
line: z14.number().int().min(1).optional().describe("1-based line number for hover, definition, or references"),
|
|
2223
|
+
character: z14.number().int().min(1).optional().describe("1-based column number for hover, definition, or references")
|
|
2224
|
+
});
|
|
2068
2225
|
function createDiagnosticsTool(servers) {
|
|
2226
|
+
const warmPool = /* @__PURE__ */ new Map();
|
|
2227
|
+
const clientFor = (server, cwd) => {
|
|
2228
|
+
const key = `${cwd}::${server.command}::${(server.args ?? []).join("\0")}`;
|
|
2229
|
+
let client = warmPool.get(key);
|
|
2230
|
+
if (!client) {
|
|
2231
|
+
client = createWarmLspClient({ server, cwd, timeoutMs: 15e3 });
|
|
2232
|
+
warmPool.set(key, client);
|
|
2233
|
+
}
|
|
2234
|
+
return client;
|
|
2235
|
+
};
|
|
2069
2236
|
return defineTool({
|
|
2070
2237
|
name: "diagnostics",
|
|
2071
|
-
description: '
|
|
2238
|
+
description: 'Query the configured LSP server(s) on a file for diagnostics (errors/warnings), hover docs, definition, or references. Configure servers under "lsp.servers" in ~/.bccli/config.json, e.g. { "extensions": [".ts"], "command": "typescript-language-server", "args": ["--stdio"] }.',
|
|
2072
2239
|
schema: SCHEMA,
|
|
2073
2240
|
kind: "read",
|
|
2074
2241
|
target: (input) => input.path,
|
|
@@ -2079,7 +2246,24 @@ function createDiagnosticsTool(servers) {
|
|
|
2079
2246
|
if (!server) {
|
|
2080
2247
|
return { output: t("No LSP server is configured for {ext} files.", { ext: ext || "(none)" }), isError: true };
|
|
2081
2248
|
}
|
|
2082
|
-
const
|
|
2249
|
+
const client = clientFor(server, ctx.cwd);
|
|
2250
|
+
const action = input.action ?? "diagnostics";
|
|
2251
|
+
const line0 = Math.max(0, (input.line ?? 1) - 1);
|
|
2252
|
+
const char0 = Math.max(0, (input.character ?? 1) - 1);
|
|
2253
|
+
if (action === "hover") {
|
|
2254
|
+
const text = await client.hover(file, line0, char0, 15e3);
|
|
2255
|
+
return { output: text || "No hover information." };
|
|
2256
|
+
}
|
|
2257
|
+
if (action === "definition" || action === "references") {
|
|
2258
|
+
const locs = action === "definition" ? await client.definition(file, line0, char0, 15e3) : await client.references(file, line0, char0, 15e3);
|
|
2259
|
+
if (!locs.length) return { output: `No ${action} found.` };
|
|
2260
|
+
const formatted = locs.map((l) => {
|
|
2261
|
+
const rel = relative2(ctx.cwd, l.path).replace(/\\/g, "/") || input.path;
|
|
2262
|
+
return `${rel}:${l.line + 1}:${l.character + 1}`;
|
|
2263
|
+
});
|
|
2264
|
+
return { output: formatted.join("\n") };
|
|
2265
|
+
}
|
|
2266
|
+
const diags = await client.diagnostics(file, 15e3);
|
|
2083
2267
|
if (!diags.length) return { output: "No diagnostics." };
|
|
2084
2268
|
const lines = diags.map((d) => `${input.path}:${d.line + 1}:${d.character + 1} ${SEVERITY[d.severity] ?? "error"} ${d.message}`);
|
|
2085
2269
|
return { output: lines.join("\n"), isError: diags.some((d) => d.severity === 1) };
|
|
@@ -14,6 +14,11 @@ import { join } from "path";
|
|
|
14
14
|
import { z } from "zod";
|
|
15
15
|
|
|
16
16
|
// src/tools/sandbox.ts
|
|
17
|
+
function winPathToWsl(winPath) {
|
|
18
|
+
const normalized = winPath.replace(/\\/g, "/");
|
|
19
|
+
const m = /^([A-Za-z]):\/(.*)$/.exec(normalized);
|
|
20
|
+
return m ? `/mnt/${m[1].toLowerCase()}/${m[2]}` : normalized;
|
|
21
|
+
}
|
|
17
22
|
function darwinProfile(cwd, network) {
|
|
18
23
|
const writable = [cwd, "/tmp", "/private/tmp", "/dev", "/var/folders"].map((p) => `(subpath "${p}")`).join(" ");
|
|
19
24
|
return [
|
|
@@ -57,6 +62,33 @@ function sandboxArgv(command, opts) {
|
|
|
57
62
|
command
|
|
58
63
|
];
|
|
59
64
|
}
|
|
65
|
+
if (opts.platform === "win32" && (opts.wslBwrap || process.env.BCCLI_WIN32_WSL_SANDBOX === "1")) {
|
|
66
|
+
const wslCwd = winPathToWsl(opts.cwd);
|
|
67
|
+
return [
|
|
68
|
+
"wsl.exe",
|
|
69
|
+
"--",
|
|
70
|
+
"bwrap",
|
|
71
|
+
"--ro-bind",
|
|
72
|
+
"/",
|
|
73
|
+
"/",
|
|
74
|
+
"--dev-bind",
|
|
75
|
+
"/dev",
|
|
76
|
+
"/dev",
|
|
77
|
+
"--proc",
|
|
78
|
+
"/proc",
|
|
79
|
+
"--bind",
|
|
80
|
+
wslCwd,
|
|
81
|
+
wslCwd,
|
|
82
|
+
"--tmpfs",
|
|
83
|
+
"/tmp",
|
|
84
|
+
"--die-with-parent",
|
|
85
|
+
...opts.network ? [] : ["--unshare-net"],
|
|
86
|
+
"--",
|
|
87
|
+
"/bin/bash",
|
|
88
|
+
"-c",
|
|
89
|
+
command
|
|
90
|
+
];
|
|
91
|
+
}
|
|
60
92
|
return void 0;
|
|
61
93
|
}
|
|
62
94
|
|
|
@@ -168,10 +200,14 @@ function startBackground(command, cwd, env, shell) {
|
|
|
168
200
|
task.status = "exited";
|
|
169
201
|
task.head += `${task.head ? "\n" : ""}${error.message}`;
|
|
170
202
|
});
|
|
171
|
-
child.on("
|
|
203
|
+
child.on("exit", (code) => {
|
|
172
204
|
task.status = "exited";
|
|
173
205
|
task.exitCode = code;
|
|
174
206
|
});
|
|
207
|
+
child.on("close", (code) => {
|
|
208
|
+
task.status = "exited";
|
|
209
|
+
if (task.exitCode === null) task.exitCode = code;
|
|
210
|
+
});
|
|
175
211
|
return task;
|
|
176
212
|
}
|
|
177
213
|
function backgroundStatus(task) {
|
|
@@ -275,8 +311,40 @@ function runCommand(command, opts) {
|
|
|
275
311
|
};
|
|
276
312
|
child.stdout.on("data", onData);
|
|
277
313
|
child.stderr.on("data", onData);
|
|
314
|
+
let settled = false;
|
|
315
|
+
let exitDrainTimer;
|
|
316
|
+
let killDrainTimer;
|
|
317
|
+
const finish = (exitCode, extra = "") => {
|
|
318
|
+
if (settled) return;
|
|
319
|
+
settled = true;
|
|
320
|
+
active.delete(killAsAborted);
|
|
321
|
+
clearTimeout(timer);
|
|
322
|
+
if (exitDrainTimer) clearTimeout(exitDrainTimer);
|
|
323
|
+
if (killDrainTimer) clearTimeout(killDrainTimer);
|
|
324
|
+
opts.signal.removeEventListener("abort", onAbort);
|
|
325
|
+
child.stdout.removeListener("data", onData);
|
|
326
|
+
child.stderr.removeListener("data", onData);
|
|
327
|
+
child.stdout.destroy();
|
|
328
|
+
child.stderr.destroy();
|
|
329
|
+
let spillNote = "";
|
|
330
|
+
if (dropped && fullChunks.length) {
|
|
331
|
+
try {
|
|
332
|
+
const spillPath = join(tmpdir(), `bccli-bash-${Date.now()}-${Math.random().toString(36).slice(2, 8)}.log`);
|
|
333
|
+
writeFileSync(spillPath, fullChunks.join(""), "utf8");
|
|
334
|
+
spillNote = `; full output saved to ${spillPath}`;
|
|
335
|
+
} catch {
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
const output = dropped ? `${head}
|
|
339
|
+
\u2026 [${dropped} characters truncated${spillNote}] \u2026
|
|
340
|
+
${tail}` : head + tail;
|
|
341
|
+
resolve3({ output: output + extra, exitCode, timedOut, aborted });
|
|
342
|
+
};
|
|
278
343
|
const kill = () => {
|
|
279
344
|
if (child.pid !== void 0) killProcessTree(child.pid);
|
|
345
|
+
if (!killDrainTimer) {
|
|
346
|
+
killDrainTimer = setTimeout(() => finish(child.exitCode), 500);
|
|
347
|
+
}
|
|
280
348
|
};
|
|
281
349
|
const killAsAborted = () => {
|
|
282
350
|
aborted = true;
|
|
@@ -293,29 +361,16 @@ function runCommand(command, opts) {
|
|
|
293
361
|
};
|
|
294
362
|
if (opts.signal.aborted) onAbort();
|
|
295
363
|
opts.signal.addEventListener("abort", onAbort, { once: true });
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
opts.signal.removeEventListener("abort", onAbort);
|
|
300
|
-
let spillNote = "";
|
|
301
|
-
if (dropped && fullChunks.length) {
|
|
302
|
-
try {
|
|
303
|
-
const spillPath = join(tmpdir(), `bccli-bash-${Date.now()}-${Math.random().toString(36).slice(2, 8)}.log`);
|
|
304
|
-
writeFileSync(spillPath, fullChunks.join(""), "utf8");
|
|
305
|
-
spillNote = `; full output saved to ${spillPath}`;
|
|
306
|
-
} catch {
|
|
307
|
-
}
|
|
364
|
+
child.on("exit", (code) => {
|
|
365
|
+
if (!exitDrainTimer) {
|
|
366
|
+
exitDrainTimer = setTimeout(() => finish(code), 200);
|
|
308
367
|
}
|
|
309
|
-
|
|
310
|
-
\u2026 [${dropped} characters truncated${spillNote}] \u2026
|
|
311
|
-
${tail}` : head + tail;
|
|
312
|
-
resolve3({ output: output + extra, exitCode, timedOut, aborted });
|
|
313
|
-
};
|
|
368
|
+
});
|
|
314
369
|
child.on("error", (error) => finish(null, error.message));
|
|
315
|
-
child.on("close", (code) => finish(code));
|
|
370
|
+
child.on("close", (code) => finish(code ?? child.exitCode));
|
|
316
371
|
});
|
|
317
372
|
}
|
|
318
|
-
var BASH_DESCRIPTION = "Run a shell command in the project directory. No interactive input. Default timeout 2 minutes (max 10). Use for tests, builds, git, and other CLI tasks. Set background: true for long-running jobs, then poll with task_id (stop with kill: true) or use the /tasks command.";
|
|
373
|
+
var BASH_DESCRIPTION = "Run a shell command in the project directory. No interactive input. Default timeout 2 minutes (max 10). Use for tests, builds, git, and other CLI tasks. Set background: true for long-running jobs, then poll with task_id (stop with kill: true) or use the /tasks command. Do not pipe commands that start background daemons (such as agent-browser) through | head or | tail.";
|
|
319
374
|
var BASH_SCHEMA = z.object({
|
|
320
375
|
command: z.string().optional().describe("The shell command to run (required unless task_id is set)"),
|
|
321
376
|
timeout_ms: z.number().int().min(1e3).max(6e5).optional().describe("Timeout in milliseconds"),
|
|
@@ -797,6 +852,7 @@ function normalizeGlobPath(path) {
|
|
|
797
852
|
}
|
|
798
853
|
|
|
799
854
|
export {
|
|
855
|
+
resolveShell,
|
|
800
856
|
runHooks,
|
|
801
857
|
renderBackgroundTasks,
|
|
802
858
|
runCommand,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
reasoningPayload
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-QQJ2VVIW.js";
|
|
5
5
|
import {
|
|
6
6
|
t
|
|
7
7
|
} from "./chunk-3WHI4LN3.js";
|
|
@@ -159,7 +159,7 @@ async function readStream(res, onText, onThinking) {
|
|
|
159
159
|
if (!choice) return;
|
|
160
160
|
if (choice.finish_reason) finishReason = choice.finish_reason;
|
|
161
161
|
const delta = choice.delta ?? {};
|
|
162
|
-
const reasoning = delta.reasoning_content || delta.reasoning;
|
|
162
|
+
const reasoning = delta.reasoning_content || delta.reasoning || delta.thinking;
|
|
163
163
|
if (reasoning) emit({ text: "", thinking: reasoning });
|
|
164
164
|
if (delta.content) emit(splitter.push(delta.content));
|
|
165
165
|
for (const tc of delta.tool_calls ?? []) {
|
|
@@ -190,7 +190,7 @@ async function readStream(res, onText, onThinking) {
|
|
|
190
190
|
const toolCalls = calls.map((call, index) => ({ ...call, id: call.id || `call_${index}` }));
|
|
191
191
|
return { text, toolCalls, thinking: thinking || void 0, usage, finishReason };
|
|
192
192
|
}
|
|
193
|
-
async function readJson(res) {
|
|
193
|
+
async function readJson(res, onText, onThinking) {
|
|
194
194
|
const body = await res.json();
|
|
195
195
|
const choice = body.choices?.[0];
|
|
196
196
|
const toolCalls = (choice?.message?.tool_calls ?? []).map((tc, i) => ({
|
|
@@ -199,7 +199,9 @@ async function readJson(res) {
|
|
|
199
199
|
arguments: tc.function?.arguments ?? ""
|
|
200
200
|
}));
|
|
201
201
|
const split = splitThinking(choice?.message?.content ?? "");
|
|
202
|
-
const thinking = (choice?.message?.reasoning_content || choice?.message?.reasoning || "") + split.thinking;
|
|
202
|
+
const thinking = (choice?.message?.reasoning_content || choice?.message?.reasoning || choice?.message?.thinking || "") + split.thinking;
|
|
203
|
+
if (thinking) onThinking?.(thinking);
|
|
204
|
+
if (split.text) onText?.(split.text);
|
|
203
205
|
return { text: split.text, toolCalls, thinking: thinking || void 0, usage: toUsage(body.usage), finishReason: choice?.finish_reason };
|
|
204
206
|
}
|
|
205
207
|
function contentText(content) {
|
|
@@ -758,7 +760,7 @@ function createProvider(options) {
|
|
|
758
760
|
const isBotConnectorCloud = /^https:\/\/api\.botconnector\.id\/v1\/?$/.test(baseURL) && apiKey?.startsWith("bc_live_");
|
|
759
761
|
if (isBotConnectorCloud) {
|
|
760
762
|
headers["x-botconnector-client"] = "bccli";
|
|
761
|
-
headers["x-botconnector-client-version"] = "0.4.
|
|
763
|
+
headers["x-botconnector-client-version"] = "0.4.4";
|
|
762
764
|
}
|
|
763
765
|
const useNativeResponses = isBotConnectorCloud && providerId === "bc-cloud" && model === "gpt-6-luna";
|
|
764
766
|
const useResponsesWebSocket = useNativeResponses && Boolean(apiKey) && (fetchOverride === void 0 || responsesWebSocketFactory !== void 0);
|
|
@@ -789,7 +791,7 @@ function createProvider(options) {
|
|
|
789
791
|
baseURL: baseURL.replace(/\/+$/, ""),
|
|
790
792
|
defaultHeaders: {
|
|
791
793
|
"x-botconnector-client": "bccli",
|
|
792
|
-
"x-botconnector-client-version": "0.4.
|
|
794
|
+
"x-botconnector-client-version": "0.4.4"
|
|
793
795
|
}
|
|
794
796
|
});
|
|
795
797
|
lunaWs = responsesWebSocketFactory ? responsesWebSocketFactory(client) : new ResponsesWS(client, { reconnect: null });
|
|
@@ -942,7 +944,7 @@ function createProvider(options) {
|
|
|
942
944
|
{ model, messages, stream: true, stream_options: { include_usage: true }, ...tools?.length ? { tools } : {}, ...reasoningOverride },
|
|
943
945
|
signal
|
|
944
946
|
);
|
|
945
|
-
if ((res.headers.get("content-type") ?? "").includes("application/json")) return readJson(res);
|
|
947
|
+
if ((res.headers.get("content-type") ?? "").includes("application/json")) return readJson(res, onText, onThinking);
|
|
946
948
|
if (!res.body) throw new ProviderError(t("Empty response from the provider"));
|
|
947
949
|
return readStream(res, onText, onThinking);
|
|
948
950
|
},
|