@botconnector/bccli 0.4.0-beta.21 → 0.4.0-beta.23
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/{chunk-34STZH4U.js → chunk-TUSJXGMP.js} +148 -35
- package/dist/{chunk-VNIUYPVN.js → chunk-XUJKRRPO.js} +1 -1
- package/dist/cli.js +86 -35
- package/dist/{login-TG5LQP3I.js → login-KHHIC6QQ.js} +1 -1
- package/dist/{providerCli-6FXMBKQL.js → providerCli-Q3FWHOKL.js} +1 -1
- package/package.json +1 -1
|
@@ -19,6 +19,7 @@ import {
|
|
|
19
19
|
// src/provider.ts
|
|
20
20
|
import OpenAI from "openai";
|
|
21
21
|
import { ResponsesWS } from "openai/resources/responses/ws";
|
|
22
|
+
import { toResponseInputItems } from "openai/lib/responses/ResponseInputItems";
|
|
22
23
|
|
|
23
24
|
// src/thinking.ts
|
|
24
25
|
var OPEN = "<think>";
|
|
@@ -207,29 +208,77 @@ function responseInputFromMessages(messages) {
|
|
|
207
208
|
continue;
|
|
208
209
|
}
|
|
209
210
|
if (message.role === "assistant") {
|
|
211
|
+
if (message.responses_output_items?.length) {
|
|
212
|
+
input.push(...toResponseInputItems(message.responses_output_items));
|
|
213
|
+
continue;
|
|
214
|
+
}
|
|
210
215
|
if (message.content) input.push({ role: "assistant", content: message.content });
|
|
211
216
|
for (const call of message.tool_calls ?? []) {
|
|
212
217
|
input.push({
|
|
213
218
|
type: "function_call",
|
|
214
219
|
call_id: call.id,
|
|
215
220
|
name: call.function.name,
|
|
216
|
-
arguments: call.function.arguments || "{}"
|
|
221
|
+
arguments: call.function.arguments || "{}",
|
|
222
|
+
...call.caller ? { caller: call.caller } : {}
|
|
217
223
|
});
|
|
218
224
|
}
|
|
219
225
|
continue;
|
|
220
226
|
}
|
|
221
|
-
input.push({
|
|
227
|
+
input.push({
|
|
228
|
+
type: "function_call_output",
|
|
229
|
+
call_id: message.tool_call_id,
|
|
230
|
+
output: message.content,
|
|
231
|
+
...message.responses_caller ? { caller: message.responses_caller } : {}
|
|
232
|
+
});
|
|
222
233
|
}
|
|
223
234
|
return input;
|
|
224
235
|
}
|
|
225
|
-
|
|
226
|
-
|
|
236
|
+
var LUNA_TOOL_SEARCH_MIN_MCP_TOOLS = 20;
|
|
237
|
+
var LUNA_TOOL_SEARCH_MIN_MCP_SCHEMA_CHARS = 32e3;
|
|
238
|
+
var LUNA_PTC_SAFE_FUNCTIONS = /* @__PURE__ */ new Set(["read", "grep", "glob"]);
|
|
239
|
+
function lunaToolPlan(tools, enableProgrammaticToolCalling = false) {
|
|
240
|
+
const native = (tools ?? []).map((tool) => ({
|
|
227
241
|
type: "function",
|
|
228
242
|
name: tool.function.name,
|
|
229
243
|
description: tool.function.description,
|
|
230
244
|
parameters: tool.function.parameters,
|
|
231
245
|
strict: false
|
|
232
246
|
}));
|
|
247
|
+
const mcpIndexes = native.map((tool, index) => String(tool.name).startsWith("mcp__") ? index : -1).filter((index) => index >= 0);
|
|
248
|
+
const deferredSchemaChars = mcpIndexes.reduce((sum, index) => sum + JSON.stringify(native[index]).length, 0);
|
|
249
|
+
const useToolSearch = mcpIndexes.length >= LUNA_TOOL_SEARCH_MIN_MCP_TOOLS || deferredSchemaChars >= LUNA_TOOL_SEARCH_MIN_MCP_SCHEMA_CHARS;
|
|
250
|
+
if (enableProgrammaticToolCalling) {
|
|
251
|
+
for (let index = 0; index < native.length; index++) {
|
|
252
|
+
if (LUNA_PTC_SAFE_FUNCTIONS.has(String(native[index].name))) {
|
|
253
|
+
native[index] = { ...native[index], allowed_callers: ["direct", "programmatic"] };
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
native.push({ type: "programmatic_tool_calling" });
|
|
257
|
+
}
|
|
258
|
+
if (!useToolSearch) {
|
|
259
|
+
return {
|
|
260
|
+
tools: native,
|
|
261
|
+
useToolSearch: false,
|
|
262
|
+
useProgrammaticToolCalling: enableProgrammaticToolCalling,
|
|
263
|
+
deferredToolCount: 0,
|
|
264
|
+
deferredSchemaChars
|
|
265
|
+
};
|
|
266
|
+
}
|
|
267
|
+
for (const index of mcpIndexes) native[index] = { ...native[index], defer_loading: true };
|
|
268
|
+
native.push({
|
|
269
|
+
type: "tool_search",
|
|
270
|
+
execution: "server"
|
|
271
|
+
});
|
|
272
|
+
return {
|
|
273
|
+
tools: native,
|
|
274
|
+
useToolSearch: true,
|
|
275
|
+
useProgrammaticToolCalling: enableProgrammaticToolCalling,
|
|
276
|
+
deferredToolCount: mcpIndexes.length,
|
|
277
|
+
deferredSchemaChars
|
|
278
|
+
};
|
|
279
|
+
}
|
|
280
|
+
function responseTools(tools, enableProgrammaticToolCalling = false) {
|
|
281
|
+
return lunaToolPlan(tools, enableProgrammaticToolCalling).tools;
|
|
233
282
|
}
|
|
234
283
|
function responseReasoning(level) {
|
|
235
284
|
if (level === "auto") return {};
|
|
@@ -238,12 +287,36 @@ function responseReasoning(level) {
|
|
|
238
287
|
function toResponsesUsage(usage) {
|
|
239
288
|
return usage ? { inputTokens: usage.input_tokens ?? 0, outputTokens: usage.output_tokens ?? 0 } : void 0;
|
|
240
289
|
}
|
|
290
|
+
function programCaller(item) {
|
|
291
|
+
const caller = item?.caller;
|
|
292
|
+
return caller?.type === "program" && typeof caller.caller_id === "string" ? { type: "program", caller_id: caller.caller_id } : void 0;
|
|
293
|
+
}
|
|
294
|
+
function responsesFinishReason(items, toolCallCount, incompleteReason) {
|
|
295
|
+
if (incompleteReason) return incompleteReason;
|
|
296
|
+
if (toolCallCount) return "tool_calls";
|
|
297
|
+
const hasMessage = items?.some((item) => item.type === "message") ?? false;
|
|
298
|
+
const hasProgramState = items?.some((item) => item.type === "program" || item.type === "program_output") ?? false;
|
|
299
|
+
return !hasMessage && hasProgramState ? "continue" : "stop";
|
|
300
|
+
}
|
|
301
|
+
function hasPendingProgrammaticReplay(messages) {
|
|
302
|
+
let pending = false;
|
|
303
|
+
for (const message of messages) {
|
|
304
|
+
if (message.role !== "assistant") continue;
|
|
305
|
+
for (const item of message.responses_output_items ?? []) {
|
|
306
|
+
if (item.type === "program") pending = true;
|
|
307
|
+
else if (item.type === "message" && pending) pending = false;
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
return pending;
|
|
311
|
+
}
|
|
241
312
|
async function readResponsesStream(res, onText) {
|
|
242
313
|
let text = "";
|
|
243
314
|
let usage;
|
|
244
315
|
let finishReason;
|
|
245
316
|
let loopAt = -1;
|
|
246
317
|
const calls = /* @__PURE__ */ new Map();
|
|
318
|
+
const outputItems = /* @__PURE__ */ new Map();
|
|
319
|
+
let responsesOutputItems;
|
|
247
320
|
const decoder = new TextDecoder();
|
|
248
321
|
let buffer = "";
|
|
249
322
|
const emitText = (delta) => {
|
|
@@ -276,7 +349,8 @@ async function readResponsesStream(res, onText) {
|
|
|
276
349
|
calls.set(Number(event.output_index ?? calls.size), {
|
|
277
350
|
id: String(event.item.call_id || event.item.id || `call_${calls.size}`),
|
|
278
351
|
name: String(event.item.name || ""),
|
|
279
|
-
arguments: String(event.item.arguments || "")
|
|
352
|
+
arguments: String(event.item.arguments || ""),
|
|
353
|
+
...programCaller(event.item) ? { caller: programCaller(event.item) } : {}
|
|
280
354
|
});
|
|
281
355
|
return;
|
|
282
356
|
}
|
|
@@ -286,24 +360,34 @@ async function readResponsesStream(res, onText) {
|
|
|
286
360
|
if (call) call.arguments += String(event.delta || "");
|
|
287
361
|
return;
|
|
288
362
|
}
|
|
289
|
-
if (event.type === "response.output_item.done" && event.item
|
|
290
|
-
const index = Number(event.output_index ??
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
363
|
+
if (event.type === "response.output_item.done" && event.item) {
|
|
364
|
+
const index = Number(event.output_index ?? outputItems.size);
|
|
365
|
+
outputItems.set(index, event.item);
|
|
366
|
+
if (event.item.type === "function_call") {
|
|
367
|
+
const current = calls.get(index);
|
|
368
|
+
calls.set(index, {
|
|
369
|
+
id: String(event.item.call_id || current?.id || event.item.id || `call_${index}`),
|
|
370
|
+
name: String(event.item.name || current?.name || ""),
|
|
371
|
+
arguments: String(event.item.arguments ?? current?.arguments ?? ""),
|
|
372
|
+
...programCaller(event.item) ?? current?.caller ? { caller: programCaller(event.item) ?? current?.caller } : {}
|
|
373
|
+
});
|
|
374
|
+
}
|
|
297
375
|
return;
|
|
298
376
|
}
|
|
299
377
|
if (event.type === "response.completed") {
|
|
300
378
|
usage = toResponsesUsage(event.response?.usage);
|
|
301
|
-
|
|
379
|
+
responsesOutputItems = event.response?.output ?? [...outputItems.entries()].sort(([a], [b]) => a - b).map(([, item]) => item);
|
|
380
|
+
finishReason = responsesFinishReason(responsesOutputItems, calls.size);
|
|
302
381
|
return;
|
|
303
382
|
}
|
|
304
383
|
if (event.type === "response.incomplete") {
|
|
305
384
|
usage = toResponsesUsage(event.response?.usage);
|
|
306
|
-
|
|
385
|
+
responsesOutputItems = event.response?.output ?? [...outputItems.entries()].sort(([a], [b]) => a - b).map(([, item]) => item);
|
|
386
|
+
finishReason = responsesFinishReason(
|
|
387
|
+
responsesOutputItems,
|
|
388
|
+
calls.size,
|
|
389
|
+
String(event.response?.incomplete_details?.reason || "incomplete")
|
|
390
|
+
);
|
|
307
391
|
}
|
|
308
392
|
};
|
|
309
393
|
for await (const chunk of res.body) {
|
|
@@ -323,7 +407,8 @@ async function readResponsesStream(res, onText) {
|
|
|
323
407
|
text,
|
|
324
408
|
toolCalls: [...calls.entries()].sort(([a], [b]) => a - b).map(([, call]) => call),
|
|
325
409
|
usage,
|
|
326
|
-
finishReason
|
|
410
|
+
finishReason,
|
|
411
|
+
responsesOutputItems
|
|
327
412
|
};
|
|
328
413
|
}
|
|
329
414
|
async function readResponsesJson(res) {
|
|
@@ -340,7 +425,8 @@ async function readResponsesJson(res) {
|
|
|
340
425
|
toolCalls.push({
|
|
341
426
|
id: String(item.call_id || item.id || `call_${toolCalls.length}`),
|
|
342
427
|
name: String(item.name || ""),
|
|
343
|
-
arguments: String(item.arguments || "{}")
|
|
428
|
+
arguments: String(item.arguments || "{}"),
|
|
429
|
+
...programCaller(item) ? { caller: programCaller(item) } : {}
|
|
344
430
|
});
|
|
345
431
|
}
|
|
346
432
|
}
|
|
@@ -348,7 +434,12 @@ async function readResponsesJson(res) {
|
|
|
348
434
|
text,
|
|
349
435
|
toolCalls,
|
|
350
436
|
usage: toResponsesUsage(body.usage),
|
|
351
|
-
|
|
437
|
+
responsesOutputItems: body.output,
|
|
438
|
+
finishReason: responsesFinishReason(
|
|
439
|
+
body.output,
|
|
440
|
+
toolCalls.length,
|
|
441
|
+
body.status === "incomplete" ? String(body.incomplete_details?.reason || "incomplete") : void 0
|
|
442
|
+
)
|
|
352
443
|
};
|
|
353
444
|
}
|
|
354
445
|
function cloneMessages(messages) {
|
|
@@ -365,9 +456,11 @@ function completionAssistantMessage(completion) {
|
|
|
365
456
|
tool_calls: completion.toolCalls.map((call) => ({
|
|
366
457
|
id: call.id,
|
|
367
458
|
type: "function",
|
|
368
|
-
function: { name: call.name, arguments: call.arguments }
|
|
459
|
+
function: { name: call.name, arguments: call.arguments },
|
|
460
|
+
...call.caller ? { caller: call.caller } : {}
|
|
369
461
|
}))
|
|
370
|
-
} : {}
|
|
462
|
+
} : {},
|
|
463
|
+
...completion.responsesOutputItems?.length ? { responses_output_items: completion.responsesOutputItems } : {}
|
|
371
464
|
};
|
|
372
465
|
}
|
|
373
466
|
function responseContinuationInput(messages, continuation) {
|
|
@@ -385,7 +478,12 @@ function responseContinuationInput(messages, continuation) {
|
|
|
385
478
|
return { input: responseInputFromMessages(messages), incremental: false };
|
|
386
479
|
}
|
|
387
480
|
const delta = messages.slice(continuation.requestMessages.length + 1);
|
|
388
|
-
if (!delta.length)
|
|
481
|
+
if (!delta.length) {
|
|
482
|
+
if (continuation.completion.finishReason === "continue") {
|
|
483
|
+
return { input: [], previousResponseId: continuation.responseId, incremental: true };
|
|
484
|
+
}
|
|
485
|
+
return { input: responseInputFromMessages(messages), incremental: false };
|
|
486
|
+
}
|
|
389
487
|
return {
|
|
390
488
|
input: responseInputFromMessages(delta),
|
|
391
489
|
previousResponseId: continuation.responseId,
|
|
@@ -399,6 +497,7 @@ async function readResponsesWebSocketTurn(events, ws, onText, signal) {
|
|
|
399
497
|
let finishReason;
|
|
400
498
|
let loopAt = -1;
|
|
401
499
|
const calls = /* @__PURE__ */ new Map();
|
|
500
|
+
const outputItems = /* @__PURE__ */ new Map();
|
|
402
501
|
const emitText = (delta) => {
|
|
403
502
|
if (!delta) return;
|
|
404
503
|
text += delta;
|
|
@@ -456,7 +555,8 @@ async function readResponsesWebSocketTurn(events, ws, onText, signal) {
|
|
|
456
555
|
calls.set(index, {
|
|
457
556
|
id: String(event.item.call_id || event.item.id || `call_${index}`),
|
|
458
557
|
name: String(event.item.name || ""),
|
|
459
|
-
arguments: String(event.item.arguments || "")
|
|
558
|
+
arguments: String(event.item.arguments || ""),
|
|
559
|
+
...programCaller(event.item) ? { caller: programCaller(event.item) } : {}
|
|
460
560
|
});
|
|
461
561
|
continue;
|
|
462
562
|
}
|
|
@@ -466,14 +566,18 @@ async function readResponsesWebSocketTurn(events, ws, onText, signal) {
|
|
|
466
566
|
if (call) call.arguments += String(event.delta || "");
|
|
467
567
|
continue;
|
|
468
568
|
}
|
|
469
|
-
if (event.type === "response.output_item.done" && event.item
|
|
470
|
-
const index = Number(event.output_index ??
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
569
|
+
if (event.type === "response.output_item.done" && event.item) {
|
|
570
|
+
const index = Number(event.output_index ?? outputItems.size);
|
|
571
|
+
outputItems.set(index, event.item);
|
|
572
|
+
if (event.item.type === "function_call") {
|
|
573
|
+
const current = calls.get(index);
|
|
574
|
+
calls.set(index, {
|
|
575
|
+
id: String(event.item.call_id || current?.id || event.item.id || `call_${index}`),
|
|
576
|
+
name: String(event.item.name || current?.name || ""),
|
|
577
|
+
arguments: String(event.item.arguments ?? current?.arguments ?? ""),
|
|
578
|
+
...programCaller(event.item) ?? current?.caller ? { caller: programCaller(event.item) ?? current?.caller } : {}
|
|
579
|
+
});
|
|
580
|
+
}
|
|
477
581
|
continue;
|
|
478
582
|
}
|
|
479
583
|
if (event.type === "response.failed") {
|
|
@@ -484,14 +588,20 @@ async function readResponsesWebSocketTurn(events, ws, onText, signal) {
|
|
|
484
588
|
if (event.type === "response.completed" || event.type === "response.incomplete") {
|
|
485
589
|
responseId = String(event.response?.id || responseId);
|
|
486
590
|
usage = toResponsesUsage(event.response?.usage);
|
|
487
|
-
|
|
591
|
+
const responsesOutputItems = event.response?.output ?? [...outputItems.entries()].sort(([a], [b]) => a - b).map(([, item]) => item);
|
|
592
|
+
finishReason = responsesFinishReason(
|
|
593
|
+
responsesOutputItems,
|
|
594
|
+
calls.size,
|
|
595
|
+
event.type === "response.incomplete" ? String(event.response?.incomplete_details?.reason || "incomplete") : void 0
|
|
596
|
+
);
|
|
488
597
|
return {
|
|
489
598
|
responseId,
|
|
490
599
|
completion: {
|
|
491
600
|
text,
|
|
492
601
|
toolCalls: [...calls.entries()].sort(([a], [b]) => a - b).map(([, call]) => call),
|
|
493
602
|
usage,
|
|
494
|
-
finishReason
|
|
603
|
+
finishReason,
|
|
604
|
+
responsesOutputItems
|
|
495
605
|
}
|
|
496
606
|
};
|
|
497
607
|
}
|
|
@@ -508,7 +618,8 @@ function createProvider(options) {
|
|
|
508
618
|
providerId,
|
|
509
619
|
fetch: fetchOverride,
|
|
510
620
|
retryDelayMs = 1e3,
|
|
511
|
-
responsesWebSocketFactory
|
|
621
|
+
responsesWebSocketFactory,
|
|
622
|
+
enableProgrammaticToolCalling = false
|
|
512
623
|
} = options;
|
|
513
624
|
const doFetch = fetchOverride ?? fetch;
|
|
514
625
|
const headers = { "content-type": "application/json" };
|
|
@@ -561,7 +672,7 @@ function createProvider(options) {
|
|
|
561
672
|
lunaWsIdleTimer.unref?.();
|
|
562
673
|
};
|
|
563
674
|
async function chatLunaWebSocket(messages, tools, reasoning, signal, onText) {
|
|
564
|
-
const nativeTools = responseTools(tools);
|
|
675
|
+
const nativeTools = responseTools(tools, enableProgrammaticToolCalling);
|
|
565
676
|
const initialPlan = responseContinuationInput(messages, lunaContinuation);
|
|
566
677
|
for (let attempt = 0; attempt < 2; attempt++) {
|
|
567
678
|
if (signal?.aborted) throw signal.reason ?? new Error("Request aborted");
|
|
@@ -653,7 +764,7 @@ function createProvider(options) {
|
|
|
653
764
|
}
|
|
654
765
|
}
|
|
655
766
|
if (useNativeResponses) {
|
|
656
|
-
const nativeTools = responseTools(tools);
|
|
767
|
+
const nativeTools = responseTools(tools, enableProgrammaticToolCalling);
|
|
657
768
|
const res2 = await post(
|
|
658
769
|
"/responses",
|
|
659
770
|
{
|
|
@@ -780,6 +891,8 @@ async function runProviderCommand(args, deps) {
|
|
|
780
891
|
}
|
|
781
892
|
|
|
782
893
|
export {
|
|
894
|
+
hasPendingProgrammaticReplay,
|
|
895
|
+
completionAssistantMessage,
|
|
783
896
|
createProvider,
|
|
784
897
|
listAllModels,
|
|
785
898
|
addProviderKey,
|
|
@@ -35,7 +35,7 @@ function readSecret(prompt) {
|
|
|
35
35
|
});
|
|
36
36
|
}
|
|
37
37
|
async function runLogin(providerId, cwd) {
|
|
38
|
-
const { runProviderCommand } = await import("./providerCli-
|
|
38
|
+
const { runProviderCommand } = await import("./providerCli-Q3FWHOKL.js");
|
|
39
39
|
const { parseCliArgs } = await import("./args-XQYEBOKB.js");
|
|
40
40
|
return runProviderCommand(parseCliArgs(["provider", "add", providerId]), {
|
|
41
41
|
env: process.env,
|
package/dist/cli.js
CHANGED
|
@@ -18,9 +18,11 @@ import {
|
|
|
18
18
|
} from "./chunk-ELML4KVQ.js";
|
|
19
19
|
import {
|
|
20
20
|
addProviderKey,
|
|
21
|
+
completionAssistantMessage,
|
|
21
22
|
createProvider,
|
|
23
|
+
hasPendingProgrammaticReplay,
|
|
22
24
|
listAllModels
|
|
23
|
-
} from "./chunk-
|
|
25
|
+
} from "./chunk-TUSJXGMP.js";
|
|
24
26
|
import {
|
|
25
27
|
providerName,
|
|
26
28
|
readGlobalConfigFile
|
|
@@ -28,7 +30,7 @@ import {
|
|
|
28
30
|
import "./chunk-SN3ODJZN.js";
|
|
29
31
|
import {
|
|
30
32
|
runLogin
|
|
31
|
-
} from "./chunk-
|
|
33
|
+
} from "./chunk-XUJKRRPO.js";
|
|
32
34
|
import {
|
|
33
35
|
Session,
|
|
34
36
|
pruneSessions
|
|
@@ -570,6 +572,7 @@ var fetchTool = createFetchTool();
|
|
|
570
572
|
// src/tools/glob.ts
|
|
571
573
|
import fg from "fast-glob";
|
|
572
574
|
import { z as z4 } from "zod";
|
|
575
|
+
var MAX_OUTPUT_CHARS = 24e3;
|
|
573
576
|
var globTool = defineTool({
|
|
574
577
|
name: "glob",
|
|
575
578
|
description: 'Find files by glob pattern, e.g. "src/**/*.ts". Respects .gitignore. Max 500 results.',
|
|
@@ -583,9 +586,19 @@ var globTool = defineTool({
|
|
|
583
586
|
const root = resolvePath(ctx.cwd, input.path ?? ".");
|
|
584
587
|
const files = (await fg(input.pattern, { cwd: root, ignore: ignorePatterns(root), onlyFiles: true, dot: true })).sort();
|
|
585
588
|
if (!files.length) return { output: "No matching files." };
|
|
586
|
-
const
|
|
587
|
-
const
|
|
588
|
-
|
|
589
|
+
const first = files.slice(0, 500);
|
|
590
|
+
const shown = [];
|
|
591
|
+
let size = 0;
|
|
592
|
+
for (const file of first) {
|
|
593
|
+
const extra = file.length + (shown.length ? 1 : 0);
|
|
594
|
+
if (shown.length && size + extra > MAX_OUTPUT_CHARS) break;
|
|
595
|
+
shown.push(file);
|
|
596
|
+
size += extra;
|
|
597
|
+
if (size >= MAX_OUTPUT_CHARS) break;
|
|
598
|
+
}
|
|
599
|
+
const omitted = files.length - shown.length;
|
|
600
|
+
const more = omitted > 0 ? `
|
|
601
|
+
\u2026 ${omitted} more files omitted (narrow pattern/path)` : "";
|
|
589
602
|
return { output: shown.join("\n") + more, display: `${files.length} file` };
|
|
590
603
|
}
|
|
591
604
|
});
|
|
@@ -596,6 +609,7 @@ import { readFile as readFile2 } from "fs/promises";
|
|
|
596
609
|
import fg2 from "fast-glob";
|
|
597
610
|
import { z as z5 } from "zod";
|
|
598
611
|
var MAX_MATCHES = 200;
|
|
612
|
+
var MAX_OUTPUT_CHARS2 = 24e3;
|
|
599
613
|
async function grepJs(pattern, opts) {
|
|
600
614
|
const regex = new RegExp(pattern, opts.ignoreCase ? "i" : "");
|
|
601
615
|
const files = await fg2(opts.glob ?? "**/*", { cwd: opts.root, ignore: ignorePatterns(opts.root), onlyFiles: true, dot: true });
|
|
@@ -651,7 +665,19 @@ var grepTool = defineTool({
|
|
|
651
665
|
}
|
|
652
666
|
const matches = await grepRg(input.pattern, opts) ?? await grepJs(input.pattern, opts);
|
|
653
667
|
if (!matches.length) return { output: "No matches." };
|
|
654
|
-
|
|
668
|
+
const shown = [];
|
|
669
|
+
let size = 0;
|
|
670
|
+
for (const match of matches) {
|
|
671
|
+
const extra = match.length + (shown.length ? 1 : 0);
|
|
672
|
+
if (shown.length && size + extra > MAX_OUTPUT_CHARS2) break;
|
|
673
|
+
shown.push(match);
|
|
674
|
+
size += extra;
|
|
675
|
+
if (size >= MAX_OUTPUT_CHARS2) break;
|
|
676
|
+
}
|
|
677
|
+
const omitted = matches.length - shown.length;
|
|
678
|
+
const suffix = omitted > 0 ? `
|
|
679
|
+
\u2026 ${omitted} more matches omitted (narrow pattern/path/glob)` : "";
|
|
680
|
+
return { output: shown.join("\n") + suffix, display: t("{n} results", { n: matches.length }) };
|
|
655
681
|
}
|
|
656
682
|
});
|
|
657
683
|
|
|
@@ -659,6 +685,7 @@ var grepTool = defineTool({
|
|
|
659
685
|
import { readFile as readFile3 } from "fs/promises";
|
|
660
686
|
import { z as z6 } from "zod";
|
|
661
687
|
var MAX_LINE = 2e3;
|
|
688
|
+
var MAX_OUTPUT_CHARS3 = 4e4;
|
|
662
689
|
var readTool = defineTool({
|
|
663
690
|
name: "read",
|
|
664
691
|
description: "Read a text file. Returns numbered lines (default first 2000). Use offset/limit for large files. Always read a file before editing it.",
|
|
@@ -683,17 +710,29 @@ var readTool = defineTool({
|
|
|
683
710
|
const lines = buffer.toString("utf8").split(/\r?\n/);
|
|
684
711
|
const start = (input.offset ?? 1) - 1;
|
|
685
712
|
const limit = input.limit ?? 2e3;
|
|
686
|
-
const
|
|
687
|
-
const
|
|
713
|
+
const requested = lines.slice(start, start + limit);
|
|
714
|
+
const shown = [];
|
|
715
|
+
let size = 0;
|
|
716
|
+
for (let i = 0; i < requested.length; i++) {
|
|
717
|
+
const line = requested[i];
|
|
688
718
|
const text = line.length > MAX_LINE ? `${line.slice(0, MAX_LINE)}\u2026 [line truncated]` : line;
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
719
|
+
const rendered = `${String(start + i + 1).padStart(6)} ${text}`;
|
|
720
|
+
const extra = rendered.length + (shown.length ? 1 : 0);
|
|
721
|
+
if (shown.length && size + extra > MAX_OUTPUT_CHARS3) break;
|
|
722
|
+
shown.push(rendered);
|
|
723
|
+
size += extra;
|
|
724
|
+
if (size >= MAX_OUTPUT_CHARS3) break;
|
|
725
|
+
}
|
|
726
|
+
const body = shown.join("\n");
|
|
727
|
+
const remaining = lines.length - start - shown.length;
|
|
728
|
+
const tokenBudgetHit = shown.length < requested.length;
|
|
729
|
+
const nextOffset = start + shown.length + 1;
|
|
692
730
|
ctx.readFiles.add(abs);
|
|
693
731
|
return {
|
|
694
|
-
output: remaining > 0 ? `${body}
|
|
732
|
+
output: remaining > 0 ? tokenBudgetHit ? `${body}
|
|
733
|
+
\u2026 ${remaining} more lines (token budget reached; continue with offset=${nextOffset})` : `${body}
|
|
695
734
|
\u2026 ${remaining} more lines (use offset)` : body,
|
|
696
|
-
display: t("{n} lines", { n:
|
|
735
|
+
display: t("{n} lines", { n: shown.length })
|
|
697
736
|
};
|
|
698
737
|
}
|
|
699
738
|
});
|
|
@@ -916,10 +955,10 @@ ${completion.text}` });
|
|
|
916
955
|
this.opts.onTurnStart?.();
|
|
917
956
|
this.webBudget.startTurn();
|
|
918
957
|
try {
|
|
919
|
-
if (this.lastInputTokens > this.contextWindow * 0.8) await this.compact(signal);
|
|
958
|
+
if (this.lastInputTokens > this.contextWindow * 0.8 && !hasPendingProgrammaticReplay(this.messages)) await this.compact(signal);
|
|
920
959
|
this.push({ role: "user", content: text });
|
|
921
960
|
for (let step = 0; step < this.maxSteps; step++) {
|
|
922
|
-
if (step > 0 && this.lastInputTokens > this.contextWindow * 0.8) {
|
|
961
|
+
if (step > 0 && this.lastInputTokens > this.contextWindow * 0.8 && !hasPendingProgrammaticReplay(this.messages)) {
|
|
923
962
|
await this.compact(signal);
|
|
924
963
|
this.push({ role: "user", content: `Continue this task using the summary above: ${text}` });
|
|
925
964
|
}
|
|
@@ -947,17 +986,7 @@ ${completion.text}` });
|
|
|
947
986
|
this.totalUsage.outputTokens += usage.outputTokens;
|
|
948
987
|
this.lastInputTokens = usage.inputTokens;
|
|
949
988
|
this.onEvent({ type: "usage", ...this.totalUsage });
|
|
950
|
-
this.push(
|
|
951
|
-
role: "assistant",
|
|
952
|
-
content: completion.text || null,
|
|
953
|
-
...completion.toolCalls.length ? {
|
|
954
|
-
tool_calls: completion.toolCalls.map((c) => ({
|
|
955
|
-
id: c.id,
|
|
956
|
-
type: "function",
|
|
957
|
-
function: { name: c.name, arguments: c.arguments }
|
|
958
|
-
}))
|
|
959
|
-
} : {}
|
|
960
|
-
});
|
|
989
|
+
this.push(completionAssistantMessage(completion));
|
|
961
990
|
if (completion.finishReason === "repetition") {
|
|
962
991
|
this.onEvent({ type: "textReplace", text: completion.text });
|
|
963
992
|
this.onEvent({
|
|
@@ -967,6 +996,7 @@ ${completion.text}` });
|
|
|
967
996
|
return;
|
|
968
997
|
}
|
|
969
998
|
if (!completion.toolCalls.length) {
|
|
999
|
+
if (completion.finishReason === "continue") continue;
|
|
970
1000
|
this.onEvent({ type: "done" });
|
|
971
1001
|
return;
|
|
972
1002
|
}
|
|
@@ -974,7 +1004,13 @@ ${completion.text}` });
|
|
|
974
1004
|
let i = 0;
|
|
975
1005
|
while (i < calls.length) {
|
|
976
1006
|
if (signal.aborted) {
|
|
977
|
-
for (const pending of calls.slice(i))
|
|
1007
|
+
for (const pending of calls.slice(i))
|
|
1008
|
+
this.push({
|
|
1009
|
+
role: "tool",
|
|
1010
|
+
tool_call_id: pending.id,
|
|
1011
|
+
content: "Cancelled by the user.",
|
|
1012
|
+
...pending.caller ? { responses_caller: pending.caller } : {}
|
|
1013
|
+
});
|
|
978
1014
|
this.onEvent({ type: "aborted" });
|
|
979
1015
|
return;
|
|
980
1016
|
}
|
|
@@ -983,7 +1019,12 @@ ${completion.text}` });
|
|
|
983
1019
|
const batch = calls.slice(i, j);
|
|
984
1020
|
const results = await Promise.all(batch.map((c) => this.runTool(c, signal)));
|
|
985
1021
|
batch.forEach((c, k) => {
|
|
986
|
-
this.push({
|
|
1022
|
+
this.push({
|
|
1023
|
+
role: "tool",
|
|
1024
|
+
tool_call_id: c.id,
|
|
1025
|
+
content: results[k],
|
|
1026
|
+
...c.caller ? { responses_caller: c.caller } : {}
|
|
1027
|
+
});
|
|
987
1028
|
});
|
|
988
1029
|
i = j;
|
|
989
1030
|
}
|
|
@@ -1140,6 +1181,7 @@ import { Client } from "@modelcontextprotocol/sdk/client/index.js";
|
|
|
1140
1181
|
import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
|
|
1141
1182
|
import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
|
|
1142
1183
|
import { z as z9 } from "zod";
|
|
1184
|
+
var MCP_OUTPUT_MAX_CHARS = 32e3;
|
|
1143
1185
|
function mcpToolName(server, tool, taken) {
|
|
1144
1186
|
const clean2 = (s) => s.replace(/[^A-Za-z0-9_-]+/g, "_");
|
|
1145
1187
|
const base = `mcp__${clean2(server)}__${clean2(tool)}`.slice(0, 64);
|
|
@@ -1213,8 +1255,11 @@ var McpManager = class {
|
|
|
1213
1255
|
try {
|
|
1214
1256
|
const result = await client.callTool({ name: tool.name, arguments: input }, void 0, { signal: ctx.signal });
|
|
1215
1257
|
const output = (result.content ?? []).map((c) => c.type === "text" ? c.text ?? "" : `[${c.type}]`).join("\n") || "(empty)";
|
|
1216
|
-
return {
|
|
1217
|
-
|
|
1258
|
+
return {
|
|
1259
|
+
output: output.length > MCP_OUTPUT_MAX_CHARS ? `${output.slice(0, MCP_OUTPUT_MAX_CHARS)}
|
|
1260
|
+
\u2026 [truncated at ${MCP_OUTPUT_MAX_CHARS} characters; narrow the MCP request if possible]` : output,
|
|
1261
|
+
isError: !!result.isError
|
|
1262
|
+
};
|
|
1218
1263
|
} catch (error) {
|
|
1219
1264
|
return { output: `Server MCP ${server} error: ${error.message}`, isError: true };
|
|
1220
1265
|
}
|
|
@@ -1468,7 +1513,13 @@ function createRuntime(opts) {
|
|
|
1468
1513
|
let reasoning = opts.args.reasoning ?? config.reasoning;
|
|
1469
1514
|
const makeProvider = (ref) => {
|
|
1470
1515
|
const resolved = resolveModel(config, ref, env);
|
|
1471
|
-
return opts.provider ?? createProvider({
|
|
1516
|
+
return opts.provider ?? createProvider({
|
|
1517
|
+
baseURL: resolved.baseURL,
|
|
1518
|
+
apiKey: resolved.apiKey,
|
|
1519
|
+
model: resolved.model,
|
|
1520
|
+
providerId: resolved.providerId,
|
|
1521
|
+
enableProgrammaticToolCalling: env.BCCLI_LUNA_PTC === "1"
|
|
1522
|
+
});
|
|
1472
1523
|
};
|
|
1473
1524
|
const provider = makeProvider(modelRef);
|
|
1474
1525
|
const mode = opts.args.allowAll ? "allowAll" : opts.args.permissionMode ?? config.permissionMode;
|
|
@@ -1604,7 +1655,7 @@ function createRuntime(opts) {
|
|
|
1604
1655
|
}
|
|
1605
1656
|
|
|
1606
1657
|
// src/version.ts
|
|
1607
|
-
var VERSION = true ? "0.4.0-beta.
|
|
1658
|
+
var VERSION = true ? "0.4.0-beta.23" : "0.0.0-dev";
|
|
1608
1659
|
|
|
1609
1660
|
// src/cli.ts
|
|
1610
1661
|
function chooseLanguage(argv) {
|
|
@@ -1630,12 +1681,12 @@ async function main() {
|
|
|
1630
1681
|
if (args.command === "login") return runLogin(args.loginProvider ?? "bc-cloud", cwd);
|
|
1631
1682
|
if (args.command === "mcp") {
|
|
1632
1683
|
const { runMcpCommand } = await import("./mcpCli-J43FHF2H.js");
|
|
1633
|
-
const { readSecret } = await import("./login-
|
|
1684
|
+
const { readSecret } = await import("./login-KHHIC6QQ.js");
|
|
1634
1685
|
return runMcpCommand(args, { env: process.env, cwd, out: (s) => console.log(s), err: (s) => console.error(s), readSecret });
|
|
1635
1686
|
}
|
|
1636
1687
|
if (args.command === "provider") {
|
|
1637
|
-
const { runProviderCommand } = await import("./providerCli-
|
|
1638
|
-
const { readSecret } = await import("./login-
|
|
1688
|
+
const { runProviderCommand } = await import("./providerCli-Q3FWHOKL.js");
|
|
1689
|
+
const { readSecret } = await import("./login-KHHIC6QQ.js");
|
|
1639
1690
|
return runProviderCommand(args, { env: process.env, cwd, out: (s) => console.log(s), err: (s) => console.error(s), readSecret });
|
|
1640
1691
|
}
|
|
1641
1692
|
if (args.command === "connect" || args.command === "disconnect" || args.command === "integrations") {
|