@botconnector/bccli 0.4.2 → 0.4.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/{acp-UYC6APR5.js → acp-NU4HZHQO.js} +1 -1
- package/dist/{chunk-ZEPTUKNW.js → chunk-4W5SKQDC.js} +33 -0
- package/dist/{chunk-SVD4LHJC.js → chunk-6AUROP2E.js} +1 -1
- package/dist/{chunk-IYR5PYA3.js → chunk-7I2ZGPUS.js} +1 -1
- package/dist/{chunk-266SY3MC.js → chunk-FUJGHCWN.js} +1 -1
- package/dist/{chunk-H7XJDKJY.js → chunk-GWVLPN4B.js} +1 -1
- package/dist/{chunk-R72OV7RF.js → chunk-QNUJHKEL.js} +255 -71
- package/dist/{chunk-C64KM37J.js → chunk-WDX62DFH.js} +5 -1
- package/dist/{chunk-5YJ3ZQVR.js → chunk-XTOATEI6.js} +2 -2
- package/dist/{chunk-TIMSYZIR.js → chunk-Z5NI5FIK.js} +1 -1
- package/dist/cli.js +20 -20
- package/dist/{ghBotCli-TSLRORJJ.js → ghBotCli-GCIUUMKQ.js} +6 -6
- package/dist/{login-RYESFZG6.js → login-YXSSB2HQ.js} +1 -1
- package/dist/lsp.d.ts +23 -0
- package/dist/{modelsCli-OP7CDZC7.js → modelsCli-656AKYZD.js} +2 -2
- package/dist/{providerCli-5OZI2GQQ.js → providerCli-V2576JXE.js} +3 -3
- package/dist/sdk.js +284 -68
- package/dist/{serve-4J7HA4JO.js → serve-XPAGXIGS.js} +7 -7
- package/dist/{session-YQXCCKXI.js → session-V2VCAF7E.js} +2 -2
- package/dist/{setup-S4AJT6XE.js → setup-HVVHOIL4.js} +6 -6
- package/dist/tools/diagnostics.d.ts +8 -0
- package/dist/tools/sandbox.d.ts +3 -0
- package/dist/{transferCli-R2KEIWQR.js → transferCli-C6XS6QYH.js} +2 -2
- package/dist/{ui-36ZEK65V.js → ui-43C6Y57K.js} +27 -5
- package/dist/{update-FSS7X5WV.js → update-AVZO4XID.js} +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -3,36 +3,36 @@ import {
|
|
|
3
3
|
resolvePrintPrompt,
|
|
4
4
|
resolveWorktree,
|
|
5
5
|
runPrint
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-WDX62DFH.js";
|
|
7
7
|
import {
|
|
8
8
|
createRuntime
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-QNUJHKEL.js";
|
|
10
10
|
import "./chunk-OK2USAXX.js";
|
|
11
|
-
import "./chunk-
|
|
11
|
+
import "./chunk-4W5SKQDC.js";
|
|
12
12
|
import "./chunk-JXM6REER.js";
|
|
13
13
|
import "./chunk-PSO7R5AD.js";
|
|
14
14
|
import {
|
|
15
15
|
VERSION
|
|
16
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-FUJGHCWN.js";
|
|
17
17
|
import {
|
|
18
18
|
helpText,
|
|
19
19
|
parseCliArgs
|
|
20
20
|
} from "./chunk-6UO5GX55.js";
|
|
21
21
|
import "./chunk-WFZKJY3R.js";
|
|
22
|
-
import "./chunk-
|
|
23
|
-
import "./chunk-
|
|
22
|
+
import "./chunk-GWVLPN4B.js";
|
|
23
|
+
import "./chunk-7I2ZGPUS.js";
|
|
24
24
|
import {
|
|
25
25
|
readGlobalConfigFile
|
|
26
26
|
} from "./chunk-HQW4BROS.js";
|
|
27
27
|
import {
|
|
28
28
|
defaultLoginDeps,
|
|
29
29
|
runLogin
|
|
30
|
-
} from "./chunk-
|
|
30
|
+
} from "./chunk-Z5NI5FIK.js";
|
|
31
31
|
import "./chunk-3I5BW3ZT.js";
|
|
32
32
|
import {
|
|
33
33
|
pruneSessions
|
|
34
|
-
} from "./chunk-
|
|
35
|
-
import "./chunk-
|
|
34
|
+
} from "./chunk-6AUROP2E.js";
|
|
35
|
+
import "./chunk-XTOATEI6.js";
|
|
36
36
|
import "./chunk-KPTML72Q.js";
|
|
37
37
|
import "./chunk-6M55UPES.js";
|
|
38
38
|
import {
|
|
@@ -86,12 +86,12 @@ async function main() {
|
|
|
86
86
|
if (args.command === "login") return runLogin(args.loginProvider ?? "bc-cloud", cwd, args, defaultLoginDeps());
|
|
87
87
|
if (args.command === "mcp") {
|
|
88
88
|
const { runMcpCommand } = await import("./mcpCli-SETTCL3K.js");
|
|
89
|
-
const { readSecret } = await import("./login-
|
|
89
|
+
const { readSecret } = await import("./login-YXSSB2HQ.js");
|
|
90
90
|
return runMcpCommand(args, { env: process.env, cwd, out: (s) => console.log(s), err: (s) => console.error(s), readSecret });
|
|
91
91
|
}
|
|
92
92
|
if (args.command === "provider") {
|
|
93
|
-
const { runProviderCommand } = await import("./providerCli-
|
|
94
|
-
const { readSecret } = await import("./login-
|
|
93
|
+
const { runProviderCommand } = await import("./providerCli-V2576JXE.js");
|
|
94
|
+
const { readSecret } = await import("./login-YXSSB2HQ.js");
|
|
95
95
|
return runProviderCommand(args, { env: process.env, cwd, out: (s) => console.log(s), err: (s) => console.error(s), readSecret });
|
|
96
96
|
}
|
|
97
97
|
if (args.command === "connect" || args.command === "disconnect" || args.command === "integrations") {
|
|
@@ -105,20 +105,20 @@ async function main() {
|
|
|
105
105
|
});
|
|
106
106
|
}
|
|
107
107
|
if (args.command === "models") {
|
|
108
|
-
const { runModelsCommand } = await import("./modelsCli-
|
|
108
|
+
const { runModelsCommand } = await import("./modelsCli-656AKYZD.js");
|
|
109
109
|
return runModelsCommand(args, { env: process.env, cwd, out: (s) => console.log(s), err: (s) => console.error(s), fetch: globalThis.fetch });
|
|
110
110
|
}
|
|
111
111
|
if (args.command === "update") {
|
|
112
|
-
const { runUpdateCommand } = await import("./update-
|
|
112
|
+
const { runUpdateCommand } = await import("./update-AVZO4XID.js");
|
|
113
113
|
return runUpdateCommand({ env: process.env });
|
|
114
114
|
}
|
|
115
115
|
if (args.command === "acp") {
|
|
116
|
-
const { runtimeAgent, runAcp } = await import("./acp-
|
|
116
|
+
const { runtimeAgent, runAcp } = await import("./acp-NU4HZHQO.js");
|
|
117
117
|
await runAcp(process.stdin, process.stdout, { cwd, newAgent: (c) => runtimeAgent(c, args.allowAll) });
|
|
118
118
|
return 0;
|
|
119
119
|
}
|
|
120
120
|
if (args.command === "serve") {
|
|
121
|
-
const { serveBanner, startServe } = await import("./serve-
|
|
121
|
+
const { serveBanner, startServe } = await import("./serve-XPAGXIGS.js");
|
|
122
122
|
const handle = await startServe({ port: args.port, host: args.host, token: args.token, cwd, env: process.env });
|
|
123
123
|
process.stderr.write(serveBanner(handle, { token: args.token }));
|
|
124
124
|
await new Promise((resolve) => {
|
|
@@ -146,7 +146,7 @@ async function main() {
|
|
|
146
146
|
});
|
|
147
147
|
}
|
|
148
148
|
if (args.command === "gh-bot") {
|
|
149
|
-
const { runGhBotCommand } = await import("./ghBotCli-
|
|
149
|
+
const { runGhBotCommand } = await import("./ghBotCli-GCIUUMKQ.js");
|
|
150
150
|
return runGhBotCommand(args, { env: process.env, cwd, out: (s) => console.log(s), err: (s) => console.error(s) });
|
|
151
151
|
}
|
|
152
152
|
if (args.command === "completion") {
|
|
@@ -162,7 +162,7 @@ async function main() {
|
|
|
162
162
|
);
|
|
163
163
|
}
|
|
164
164
|
if (args.command === "export" || args.command === "import") {
|
|
165
|
-
const { runExportCommand, runImportCommand } = await import("./transferCli-
|
|
165
|
+
const { runExportCommand, runImportCommand } = await import("./transferCli-C6XS6QYH.js");
|
|
166
166
|
const { bccliHome } = await import("./config-LAINORU5.js");
|
|
167
167
|
const deps = { subArgs: args.subArgs, home: bccliHome(process.env), cwd };
|
|
168
168
|
const io = { out: (s) => console.log(s), err: (s) => console.error(s) };
|
|
@@ -215,13 +215,13 @@ async function main() {
|
|
|
215
215
|
let updateMessage;
|
|
216
216
|
if (rt.config.updateCheck !== "off" && !process.env.BCCLI_NO_UPDATE_CHECK) {
|
|
217
217
|
try {
|
|
218
|
-
const { checkForUpdate } = await import("./update-
|
|
218
|
+
const { checkForUpdate } = await import("./update-AVZO4XID.js");
|
|
219
219
|
const update = await checkForUpdate({ home: rt.home, fetch: globalThis.fetch, now: /* @__PURE__ */ new Date() });
|
|
220
220
|
updateMessage = update;
|
|
221
221
|
} catch {
|
|
222
222
|
}
|
|
223
223
|
}
|
|
224
|
-
const { startInteractive } = await import("./ui-
|
|
224
|
+
const { startInteractive } = await import("./ui-43C6Y57K.js");
|
|
225
225
|
return startInteractive(rt, { initialPrompt: args.prompt, resume: args.resume, version: VERSION, updateMessage });
|
|
226
226
|
}
|
|
227
227
|
main().then(
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
createRuntime
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-QNUJHKEL.js";
|
|
5
5
|
import "./chunk-OK2USAXX.js";
|
|
6
|
-
import "./chunk-
|
|
6
|
+
import "./chunk-4W5SKQDC.js";
|
|
7
7
|
import "./chunk-JXM6REER.js";
|
|
8
8
|
import "./chunk-PSO7R5AD.js";
|
|
9
9
|
import {
|
|
@@ -11,12 +11,12 @@ import {
|
|
|
11
11
|
parseCliArgs
|
|
12
12
|
} from "./chunk-6UO5GX55.js";
|
|
13
13
|
import "./chunk-WFZKJY3R.js";
|
|
14
|
-
import "./chunk-
|
|
15
|
-
import "./chunk-
|
|
14
|
+
import "./chunk-GWVLPN4B.js";
|
|
15
|
+
import "./chunk-7I2ZGPUS.js";
|
|
16
16
|
import "./chunk-HQW4BROS.js";
|
|
17
17
|
import "./chunk-3I5BW3ZT.js";
|
|
18
|
-
import "./chunk-
|
|
19
|
-
import "./chunk-
|
|
18
|
+
import "./chunk-6AUROP2E.js";
|
|
19
|
+
import "./chunk-XTOATEI6.js";
|
|
20
20
|
import "./chunk-KPTML72Q.js";
|
|
21
21
|
import "./chunk-6M55UPES.js";
|
|
22
22
|
import {
|
package/dist/lsp.d.ts
CHANGED
|
@@ -11,6 +11,19 @@ export interface LspDiagnostic {
|
|
|
11
11
|
severity: number;
|
|
12
12
|
message: string;
|
|
13
13
|
}
|
|
14
|
+
export interface LspLocation {
|
|
15
|
+
uri: string;
|
|
16
|
+
path: string;
|
|
17
|
+
line: number;
|
|
18
|
+
character: number;
|
|
19
|
+
}
|
|
20
|
+
export interface WarmLspClient {
|
|
21
|
+
diagnostics(file: string, timeoutMs?: number): Promise<LspDiagnostic[]>;
|
|
22
|
+
hover(file: string, line: number, character: number, timeoutMs?: number): Promise<string>;
|
|
23
|
+
definition(file: string, line: number, character: number, timeoutMs?: number): Promise<LspLocation[]>;
|
|
24
|
+
references(file: string, line: number, character: number, timeoutMs?: number): Promise<LspLocation[]>;
|
|
25
|
+
close(): Promise<void>;
|
|
26
|
+
}
|
|
14
27
|
interface LspRawDiagnostic {
|
|
15
28
|
range?: {
|
|
16
29
|
start?: {
|
|
@@ -47,4 +60,14 @@ export declare function getDiagnostics(opts: {
|
|
|
47
60
|
timeoutMs?: number;
|
|
48
61
|
signal?: AbortSignal;
|
|
49
62
|
}): Promise<LspDiagnostic[]>;
|
|
63
|
+
/**
|
|
64
|
+
* Persistent warm LSP client: spawns the language server once, sends `didOpen` on first
|
|
65
|
+
* touch of a file and `didChange` on subsequent touches, and serves `diagnostics`,
|
|
66
|
+
* `hover`, `definition`, and `references` over the same warm process.
|
|
67
|
+
*/
|
|
68
|
+
export declare function createWarmLspClient(opts: {
|
|
69
|
+
server: LspServer;
|
|
70
|
+
cwd: string;
|
|
71
|
+
timeoutMs?: number;
|
|
72
|
+
}): WarmLspClient;
|
|
50
73
|
export {};
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
listAllModels
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-7I2ZGPUS.js";
|
|
5
5
|
import "./chunk-HQW4BROS.js";
|
|
6
|
-
import "./chunk-
|
|
6
|
+
import "./chunk-XTOATEI6.js";
|
|
7
7
|
import "./chunk-KPTML72Q.js";
|
|
8
8
|
import {
|
|
9
9
|
loadConfig,
|
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
import {
|
|
3
3
|
addProviderKey,
|
|
4
4
|
runProviderCommand
|
|
5
|
-
} from "./chunk-
|
|
6
|
-
import "./chunk-
|
|
5
|
+
} from "./chunk-GWVLPN4B.js";
|
|
6
|
+
import "./chunk-7I2ZGPUS.js";
|
|
7
7
|
import "./chunk-HQW4BROS.js";
|
|
8
|
-
import "./chunk-
|
|
8
|
+
import "./chunk-XTOATEI6.js";
|
|
9
9
|
import "./chunk-KPTML72Q.js";
|
|
10
10
|
import "./chunk-RX4UQX43.js";
|
|
11
11
|
import "./chunk-3WHI4LN3.js";
|
package/dist/sdk.js
CHANGED
|
@@ -1829,7 +1829,7 @@ function createProvider(options) {
|
|
|
1829
1829
|
const isBotConnectorCloud = /^https:\/\/api\.botconnector\.id\/v1\/?$/.test(baseURL) && apiKey?.startsWith("bc_live_");
|
|
1830
1830
|
if (isBotConnectorCloud) {
|
|
1831
1831
|
headers["x-botconnector-client"] = "bccli";
|
|
1832
|
-
headers["x-botconnector-client-version"] = "0.4.
|
|
1832
|
+
headers["x-botconnector-client-version"] = "0.4.3";
|
|
1833
1833
|
}
|
|
1834
1834
|
const useNativeResponses = isBotConnectorCloud && providerId === "bc-cloud" && model === "gpt-6-luna";
|
|
1835
1835
|
const useResponsesWebSocket = useNativeResponses && Boolean(apiKey) && (fetchOverride === void 0 || responsesWebSocketFactory !== void 0);
|
|
@@ -1860,7 +1860,7 @@ function createProvider(options) {
|
|
|
1860
1860
|
baseURL: baseURL.replace(/\/+$/, ""),
|
|
1861
1861
|
defaultHeaders: {
|
|
1862
1862
|
"x-botconnector-client": "bccli",
|
|
1863
|
-
"x-botconnector-client-version": "0.4.
|
|
1863
|
+
"x-botconnector-client-version": "0.4.3"
|
|
1864
1864
|
}
|
|
1865
1865
|
});
|
|
1866
1866
|
lunaWs = responsesWebSocketFactory ? responsesWebSocketFactory(client) : new ResponsesWS(client, { reconnect: null });
|
|
@@ -2268,6 +2268,11 @@ import { join as join2 } from "path";
|
|
|
2268
2268
|
import { z } from "zod";
|
|
2269
2269
|
|
|
2270
2270
|
// src/tools/sandbox.ts
|
|
2271
|
+
function winPathToWsl(winPath) {
|
|
2272
|
+
const normalized = winPath.replace(/\\/g, "/");
|
|
2273
|
+
const m = /^([A-Za-z]):\/(.*)$/.exec(normalized);
|
|
2274
|
+
return m ? `/mnt/${m[1].toLowerCase()}/${m[2]}` : normalized;
|
|
2275
|
+
}
|
|
2271
2276
|
function darwinProfile(cwd, network) {
|
|
2272
2277
|
const writable = [cwd, "/tmp", "/private/tmp", "/dev", "/var/folders"].map((p) => `(subpath "${p}")`).join(" ");
|
|
2273
2278
|
return [
|
|
@@ -2311,6 +2316,33 @@ function sandboxArgv(command, opts) {
|
|
|
2311
2316
|
command
|
|
2312
2317
|
];
|
|
2313
2318
|
}
|
|
2319
|
+
if (opts.platform === "win32" && (opts.wslBwrap || process.env.BCCLI_WIN32_WSL_SANDBOX === "1")) {
|
|
2320
|
+
const wslCwd = winPathToWsl(opts.cwd);
|
|
2321
|
+
return [
|
|
2322
|
+
"wsl.exe",
|
|
2323
|
+
"--",
|
|
2324
|
+
"bwrap",
|
|
2325
|
+
"--ro-bind",
|
|
2326
|
+
"/",
|
|
2327
|
+
"/",
|
|
2328
|
+
"--dev-bind",
|
|
2329
|
+
"/dev",
|
|
2330
|
+
"/dev",
|
|
2331
|
+
"--proc",
|
|
2332
|
+
"/proc",
|
|
2333
|
+
"--bind",
|
|
2334
|
+
wslCwd,
|
|
2335
|
+
wslCwd,
|
|
2336
|
+
"--tmpfs",
|
|
2337
|
+
"/tmp",
|
|
2338
|
+
"--die-with-parent",
|
|
2339
|
+
...opts.network ? [] : ["--unshare-net"],
|
|
2340
|
+
"--",
|
|
2341
|
+
"/bin/bash",
|
|
2342
|
+
"-c",
|
|
2343
|
+
command
|
|
2344
|
+
];
|
|
2345
|
+
}
|
|
2314
2346
|
return void 0;
|
|
2315
2347
|
}
|
|
2316
2348
|
|
|
@@ -5476,14 +5508,14 @@ function createRepoMapTool() {
|
|
|
5476
5508
|
}
|
|
5477
5509
|
|
|
5478
5510
|
// src/tools/diagnostics.ts
|
|
5479
|
-
import { extname as extname3 } from "path";
|
|
5511
|
+
import { extname as extname3, relative as relative3 } from "path";
|
|
5480
5512
|
import { z as z17 } from "zod";
|
|
5481
5513
|
|
|
5482
5514
|
// src/lsp.ts
|
|
5483
5515
|
import { spawn as spawn4 } from "child_process";
|
|
5484
5516
|
import { readFileSync as readFileSync12 } from "fs";
|
|
5485
5517
|
import { extname as extname2 } from "path";
|
|
5486
|
-
import { pathToFileURL } from "url";
|
|
5518
|
+
import { fileURLToPath, pathToFileURL } from "url";
|
|
5487
5519
|
var LANGUAGE_IDS = {
|
|
5488
5520
|
".ts": "typescript",
|
|
5489
5521
|
".tsx": "typescriptreact",
|
|
@@ -5551,86 +5583,253 @@ function createLspParser(onMessage) {
|
|
|
5551
5583
|
}
|
|
5552
5584
|
};
|
|
5553
5585
|
}
|
|
5554
|
-
function
|
|
5555
|
-
|
|
5556
|
-
|
|
5557
|
-
|
|
5558
|
-
|
|
5559
|
-
|
|
5586
|
+
function extractHoverText(contents) {
|
|
5587
|
+
if (!contents) return "";
|
|
5588
|
+
if (typeof contents === "string") return contents.trim();
|
|
5589
|
+
if (Array.isArray(contents)) return contents.map(extractHoverText).filter(Boolean).join("\n\n");
|
|
5590
|
+
if (typeof contents === "object" && "value" in contents && typeof contents.value === "string") {
|
|
5591
|
+
return contents.value.trim();
|
|
5592
|
+
}
|
|
5593
|
+
return "";
|
|
5594
|
+
}
|
|
5595
|
+
function normalizeLocations(raw) {
|
|
5596
|
+
const items = Array.isArray(raw) ? raw : raw ? [raw] : [];
|
|
5597
|
+
const out = [];
|
|
5598
|
+
for (const item of items) {
|
|
5599
|
+
if (!item || typeof item !== "object") continue;
|
|
5600
|
+
const rec = item;
|
|
5601
|
+
const uri = rec.uri ?? rec.targetUri;
|
|
5602
|
+
const start = rec.range?.start ?? rec.targetSelectionRange?.start ?? rec.targetRange?.start;
|
|
5603
|
+
if (!uri) continue;
|
|
5604
|
+
let path = uri;
|
|
5605
|
+
try {
|
|
5606
|
+
if (uri.startsWith("file:")) path = fileURLToPath(uri);
|
|
5607
|
+
} catch {
|
|
5608
|
+
}
|
|
5609
|
+
out.push({
|
|
5610
|
+
uri,
|
|
5611
|
+
path,
|
|
5612
|
+
line: start?.line ?? 0,
|
|
5613
|
+
character: start?.character ?? 0
|
|
5560
5614
|
});
|
|
5561
|
-
|
|
5562
|
-
|
|
5563
|
-
|
|
5564
|
-
|
|
5565
|
-
|
|
5566
|
-
|
|
5567
|
-
|
|
5568
|
-
|
|
5569
|
-
|
|
5570
|
-
|
|
5571
|
-
|
|
5572
|
-
|
|
5573
|
-
|
|
5574
|
-
|
|
5575
|
-
|
|
5576
|
-
|
|
5577
|
-
|
|
5578
|
-
|
|
5579
|
-
|
|
5580
|
-
|
|
5615
|
+
}
|
|
5616
|
+
return out;
|
|
5617
|
+
}
|
|
5618
|
+
function createWarmLspClient(opts) {
|
|
5619
|
+
let child;
|
|
5620
|
+
let initPromise;
|
|
5621
|
+
let nextId = 2;
|
|
5622
|
+
const opened = /* @__PURE__ */ new Map();
|
|
5623
|
+
const pendingRpc = /* @__PURE__ */ new Map();
|
|
5624
|
+
const diagWaiters = /* @__PURE__ */ new Map();
|
|
5625
|
+
const send = (msg) => {
|
|
5626
|
+
try {
|
|
5627
|
+
child?.stdin?.write(encodeLsp(msg));
|
|
5628
|
+
} catch {
|
|
5629
|
+
}
|
|
5630
|
+
};
|
|
5631
|
+
const resetState = () => {
|
|
5632
|
+
child = void 0;
|
|
5633
|
+
initPromise = void 0;
|
|
5634
|
+
opened.clear();
|
|
5635
|
+
for (const [, resolve5] of pendingRpc) resolve5(void 0);
|
|
5636
|
+
pendingRpc.clear();
|
|
5637
|
+
for (const [, waiters] of diagWaiters) {
|
|
5638
|
+
for (const w of waiters) w([]);
|
|
5639
|
+
}
|
|
5640
|
+
diagWaiters.clear();
|
|
5641
|
+
};
|
|
5642
|
+
const ensureStarted = () => {
|
|
5643
|
+
if (initPromise && child && !child.killed) return initPromise;
|
|
5644
|
+
opened.clear();
|
|
5645
|
+
initPromise = new Promise((resolveInit) => {
|
|
5646
|
+
const proc = spawn4(opts.server.command, opts.server.args ?? [], {
|
|
5647
|
+
cwd: opts.cwd,
|
|
5648
|
+
stdio: ["pipe", "pipe", "ignore"],
|
|
5649
|
+
shell: useShellForLsp(opts.server.command)
|
|
5650
|
+
});
|
|
5651
|
+
child = proc;
|
|
5652
|
+
let initSettled = false;
|
|
5653
|
+
const settleInit = () => {
|
|
5654
|
+
if (!initSettled) {
|
|
5655
|
+
initSettled = true;
|
|
5656
|
+
resolveInit();
|
|
5581
5657
|
}
|
|
5582
|
-
}
|
|
5583
|
-
|
|
5584
|
-
|
|
5585
|
-
|
|
5586
|
-
|
|
5587
|
-
|
|
5588
|
-
opts.signal?.addEventListener("abort", onAbort, { once: true });
|
|
5589
|
-
const timer = setTimeout(() => finish([]), opts.timeoutMs ?? 8e3);
|
|
5590
|
-
const parser = createLspParser((msg) => {
|
|
5591
|
-
if (msg.id === 1 && msg.result) {
|
|
5592
|
-
send({ jsonrpc: "2.0", method: "initialized", params: {} });
|
|
5593
|
-
let text = "";
|
|
5594
|
-
try {
|
|
5595
|
-
text = readFileSync12(opts.file, "utf8");
|
|
5596
|
-
} catch {
|
|
5658
|
+
};
|
|
5659
|
+
const parser = createLspParser((msg) => {
|
|
5660
|
+
if (msg.id === 1 && msg.result !== void 0) {
|
|
5661
|
+
send({ jsonrpc: "2.0", method: "initialized", params: {} });
|
|
5662
|
+
settleInit();
|
|
5663
|
+
return;
|
|
5597
5664
|
}
|
|
5598
|
-
|
|
5599
|
-
|
|
5600
|
-
|
|
5601
|
-
|
|
5602
|
-
|
|
5603
|
-
|
|
5604
|
-
|
|
5605
|
-
|
|
5606
|
-
(msg.params.diagnostics ?? []).map((d) => ({
|
|
5665
|
+
if (msg.id !== void 0 && pendingRpc.has(msg.id)) {
|
|
5666
|
+
const fn = pendingRpc.get(msg.id);
|
|
5667
|
+
pendingRpc.delete(msg.id);
|
|
5668
|
+
fn?.(msg.result);
|
|
5669
|
+
return;
|
|
5670
|
+
}
|
|
5671
|
+
if (msg.method === "textDocument/publishDiagnostics" && msg.params?.uri) {
|
|
5672
|
+
const uri = msg.params.uri;
|
|
5673
|
+
const diags = (msg.params.diagnostics ?? []).map((d) => ({
|
|
5607
5674
|
line: d.range?.start?.line ?? 0,
|
|
5608
5675
|
character: d.range?.start?.character ?? 0,
|
|
5609
5676
|
severity: d.severity ?? 1,
|
|
5610
5677
|
message: String(d.message ?? "")
|
|
5611
|
-
}))
|
|
5612
|
-
|
|
5613
|
-
|
|
5678
|
+
}));
|
|
5679
|
+
const list2 = diagWaiters.get(uri);
|
|
5680
|
+
if (list2?.length) {
|
|
5681
|
+
diagWaiters.delete(uri);
|
|
5682
|
+
for (const w of list2) w(diags);
|
|
5683
|
+
}
|
|
5684
|
+
}
|
|
5685
|
+
});
|
|
5686
|
+
proc.stdout?.on("data", (c) => parser.push(c));
|
|
5687
|
+
proc.on("error", () => {
|
|
5688
|
+
resetState();
|
|
5689
|
+
settleInit();
|
|
5690
|
+
});
|
|
5691
|
+
proc.on("close", () => {
|
|
5692
|
+
resetState();
|
|
5693
|
+
settleInit();
|
|
5694
|
+
});
|
|
5695
|
+
send({
|
|
5696
|
+
jsonrpc: "2.0",
|
|
5697
|
+
id: 1,
|
|
5698
|
+
method: "initialize",
|
|
5699
|
+
params: { processId: process.pid, capabilities: {}, rootUri: pathToFileURL(opts.cwd).href }
|
|
5700
|
+
});
|
|
5614
5701
|
});
|
|
5615
|
-
|
|
5616
|
-
|
|
5617
|
-
|
|
5618
|
-
|
|
5619
|
-
|
|
5620
|
-
|
|
5621
|
-
|
|
5622
|
-
|
|
5702
|
+
return initPromise;
|
|
5703
|
+
};
|
|
5704
|
+
const syncDocument = (file) => {
|
|
5705
|
+
const uri = pathToFileURL(file).href;
|
|
5706
|
+
let text = "";
|
|
5707
|
+
try {
|
|
5708
|
+
text = readFileSync12(file, "utf8");
|
|
5709
|
+
} catch {
|
|
5710
|
+
}
|
|
5711
|
+
const prevVersion = opened.get(uri);
|
|
5712
|
+
if (prevVersion === void 0) {
|
|
5713
|
+
opened.set(uri, 1);
|
|
5714
|
+
send({
|
|
5715
|
+
jsonrpc: "2.0",
|
|
5716
|
+
method: "textDocument/didOpen",
|
|
5717
|
+
params: { textDocument: { uri, languageId: languageIdFor(file), version: 1, text } }
|
|
5718
|
+
});
|
|
5719
|
+
} else {
|
|
5720
|
+
const version = prevVersion + 1;
|
|
5721
|
+
opened.set(uri, version);
|
|
5722
|
+
send({
|
|
5723
|
+
jsonrpc: "2.0",
|
|
5724
|
+
method: "textDocument/didChange",
|
|
5725
|
+
params: {
|
|
5726
|
+
textDocument: { uri, version },
|
|
5727
|
+
contentChanges: [{ text }]
|
|
5728
|
+
}
|
|
5729
|
+
});
|
|
5730
|
+
}
|
|
5731
|
+
return uri;
|
|
5732
|
+
};
|
|
5733
|
+
const request = (method, params, timeoutMs = opts.timeoutMs ?? 8e3) => new Promise((resolve5) => {
|
|
5734
|
+
const id = nextId++;
|
|
5735
|
+
const timer = setTimeout(() => {
|
|
5736
|
+
pendingRpc.delete(id);
|
|
5737
|
+
resolve5(void 0);
|
|
5738
|
+
}, timeoutMs);
|
|
5739
|
+
pendingRpc.set(id, (res) => {
|
|
5740
|
+
clearTimeout(timer);
|
|
5741
|
+
resolve5(res);
|
|
5623
5742
|
});
|
|
5743
|
+
send({ jsonrpc: "2.0", id, method, params });
|
|
5624
5744
|
});
|
|
5745
|
+
return {
|
|
5746
|
+
async diagnostics(file, timeoutMs = opts.timeoutMs ?? 8e3) {
|
|
5747
|
+
await ensureStarted();
|
|
5748
|
+
if (!child) return [];
|
|
5749
|
+
const uri = pathToFileURL(file).href;
|
|
5750
|
+
return new Promise((resolve5) => {
|
|
5751
|
+
const timer = setTimeout(() => {
|
|
5752
|
+
const list3 = diagWaiters.get(uri) ?? [];
|
|
5753
|
+
diagWaiters.set(
|
|
5754
|
+
uri,
|
|
5755
|
+
list3.filter((w) => w !== onDiag)
|
|
5756
|
+
);
|
|
5757
|
+
resolve5([]);
|
|
5758
|
+
}, timeoutMs);
|
|
5759
|
+
const onDiag = (diags) => {
|
|
5760
|
+
clearTimeout(timer);
|
|
5761
|
+
resolve5(diags);
|
|
5762
|
+
};
|
|
5763
|
+
const list2 = diagWaiters.get(uri) ?? [];
|
|
5764
|
+
list2.push(onDiag);
|
|
5765
|
+
diagWaiters.set(uri, list2);
|
|
5766
|
+
syncDocument(file);
|
|
5767
|
+
});
|
|
5768
|
+
},
|
|
5769
|
+
async hover(file, line, character, timeoutMs) {
|
|
5770
|
+
await ensureStarted();
|
|
5771
|
+
if (!child) return "";
|
|
5772
|
+
const uri = syncDocument(file);
|
|
5773
|
+
const res = await request("textDocument/hover", { textDocument: { uri }, position: { line, character } }, timeoutMs);
|
|
5774
|
+
return extractHoverText(res?.contents);
|
|
5775
|
+
},
|
|
5776
|
+
async definition(file, line, character, timeoutMs) {
|
|
5777
|
+
await ensureStarted();
|
|
5778
|
+
if (!child) return [];
|
|
5779
|
+
const uri = syncDocument(file);
|
|
5780
|
+
const res = await request("textDocument/definition", { textDocument: { uri }, position: { line, character } }, timeoutMs);
|
|
5781
|
+
return normalizeLocations(res);
|
|
5782
|
+
},
|
|
5783
|
+
async references(file, line, character, timeoutMs) {
|
|
5784
|
+
await ensureStarted();
|
|
5785
|
+
if (!child) return [];
|
|
5786
|
+
const uri = syncDocument(file);
|
|
5787
|
+
const res = await request(
|
|
5788
|
+
"textDocument/references",
|
|
5789
|
+
{ textDocument: { uri }, position: { line, character }, context: { includeDeclaration: true } },
|
|
5790
|
+
timeoutMs
|
|
5791
|
+
);
|
|
5792
|
+
return normalizeLocations(res);
|
|
5793
|
+
},
|
|
5794
|
+
async close() {
|
|
5795
|
+
if (!child) return;
|
|
5796
|
+
const proc = child;
|
|
5797
|
+
send({ jsonrpc: "2.0", id: nextId++, method: "shutdown" });
|
|
5798
|
+
send({ jsonrpc: "2.0", method: "exit" });
|
|
5799
|
+
resetState();
|
|
5800
|
+
const killer = setTimeout(() => {
|
|
5801
|
+
try {
|
|
5802
|
+
proc.kill();
|
|
5803
|
+
} catch {
|
|
5804
|
+
}
|
|
5805
|
+
}, 200);
|
|
5806
|
+
killer.unref?.();
|
|
5807
|
+
}
|
|
5808
|
+
};
|
|
5625
5809
|
}
|
|
5626
5810
|
|
|
5627
5811
|
// src/tools/diagnostics.ts
|
|
5628
5812
|
var SEVERITY = { 1: "error", 2: "warning", 3: "info", 4: "hint" };
|
|
5629
|
-
var SCHEMA = z17.object({
|
|
5813
|
+
var SCHEMA = z17.object({
|
|
5814
|
+
path: z17.string().describe("File to check (absolute or relative to the working directory)"),
|
|
5815
|
+
action: z17.enum(["diagnostics", "hover", "definition", "references"]).optional().describe("LSP query action, default diagnostics"),
|
|
5816
|
+
line: z17.number().int().min(1).optional().describe("1-based line number for hover, definition, or references"),
|
|
5817
|
+
character: z17.number().int().min(1).optional().describe("1-based column number for hover, definition, or references")
|
|
5818
|
+
});
|
|
5630
5819
|
function createDiagnosticsTool(servers) {
|
|
5820
|
+
const warmPool = /* @__PURE__ */ new Map();
|
|
5821
|
+
const clientFor = (server, cwd) => {
|
|
5822
|
+
const key = `${cwd}::${server.command}::${(server.args ?? []).join("\0")}`;
|
|
5823
|
+
let client = warmPool.get(key);
|
|
5824
|
+
if (!client) {
|
|
5825
|
+
client = createWarmLspClient({ server, cwd, timeoutMs: 15e3 });
|
|
5826
|
+
warmPool.set(key, client);
|
|
5827
|
+
}
|
|
5828
|
+
return client;
|
|
5829
|
+
};
|
|
5631
5830
|
return defineTool({
|
|
5632
5831
|
name: "diagnostics",
|
|
5633
|
-
description: '
|
|
5832
|
+
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"] }.',
|
|
5634
5833
|
schema: SCHEMA,
|
|
5635
5834
|
kind: "read",
|
|
5636
5835
|
target: (input) => input.path,
|
|
@@ -5641,7 +5840,24 @@ function createDiagnosticsTool(servers) {
|
|
|
5641
5840
|
if (!server) {
|
|
5642
5841
|
return { output: t("No LSP server is configured for {ext} files.", { ext: ext || "(none)" }), isError: true };
|
|
5643
5842
|
}
|
|
5644
|
-
const
|
|
5843
|
+
const client = clientFor(server, ctx.cwd);
|
|
5844
|
+
const action = input.action ?? "diagnostics";
|
|
5845
|
+
const line0 = Math.max(0, (input.line ?? 1) - 1);
|
|
5846
|
+
const char0 = Math.max(0, (input.character ?? 1) - 1);
|
|
5847
|
+
if (action === "hover") {
|
|
5848
|
+
const text = await client.hover(file, line0, char0, 15e3);
|
|
5849
|
+
return { output: text || "No hover information." };
|
|
5850
|
+
}
|
|
5851
|
+
if (action === "definition" || action === "references") {
|
|
5852
|
+
const locs = action === "definition" ? await client.definition(file, line0, char0, 15e3) : await client.references(file, line0, char0, 15e3);
|
|
5853
|
+
if (!locs.length) return { output: `No ${action} found.` };
|
|
5854
|
+
const formatted = locs.map((l) => {
|
|
5855
|
+
const rel = relative3(ctx.cwd, l.path).replace(/\\/g, "/") || input.path;
|
|
5856
|
+
return `${rel}:${l.line + 1}:${l.character + 1}`;
|
|
5857
|
+
});
|
|
5858
|
+
return { output: formatted.join("\n") };
|
|
5859
|
+
}
|
|
5860
|
+
const diags = await client.diagnostics(file, 15e3);
|
|
5645
5861
|
if (!diags.length) return { output: "No diagnostics." };
|
|
5646
5862
|
const lines = diags.map((d) => `${input.path}:${d.line + 1}:${d.character + 1} ${SEVERITY[d.severity] ?? "error"} ${d.message}`);
|
|
5647
5863
|
return { output: lines.join("\n"), isError: diags.some((d) => d.severity === 1) };
|