@botconnector/bccli 0.4.0-beta.2 → 0.4.0-beta.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/{chunk-2JBRLGKD.js → chunk-C5AFWX7H.js} +73 -11
- package/dist/{chunk-L7L4RGKG.js → chunk-GW36UMHZ.js} +1 -1
- package/dist/cli.js +82 -9
- package/dist/{login-KHU7ONSR.js → login-F4G5QXOU.js} +1 -1
- package/dist/{providerCli-G3X7KENO.js → providerCli-MXV6PD6F.js} +1 -1
- package/dist/{ui-A32PTF4F.js → ui-7FXPXXGN.js} +54 -1
- package/package.json +1 -1
|
@@ -12,6 +12,54 @@ import {
|
|
|
12
12
|
saveCredential
|
|
13
13
|
} from "./chunk-RZUJYAQV.js";
|
|
14
14
|
|
|
15
|
+
// src/thinking.ts
|
|
16
|
+
var OPEN = "<think>";
|
|
17
|
+
var CLOSE = "</think>";
|
|
18
|
+
function partialTag(text, tag) {
|
|
19
|
+
for (let n = Math.min(tag.length - 1, text.length); n > 0; n--) if (tag.startsWith(text.slice(-n))) return n;
|
|
20
|
+
return 0;
|
|
21
|
+
}
|
|
22
|
+
var ThinkSplitter = class {
|
|
23
|
+
inside = false;
|
|
24
|
+
held = "";
|
|
25
|
+
push(delta) {
|
|
26
|
+
let rest = this.held + delta;
|
|
27
|
+
this.held = "";
|
|
28
|
+
let text = "";
|
|
29
|
+
let thinking = "";
|
|
30
|
+
while (rest) {
|
|
31
|
+
const tag = this.inside ? CLOSE : OPEN;
|
|
32
|
+
const at = rest.indexOf(tag);
|
|
33
|
+
if (at >= 0) {
|
|
34
|
+
if (this.inside) thinking += rest.slice(0, at);
|
|
35
|
+
else text += rest.slice(0, at);
|
|
36
|
+
rest = rest.slice(at + tag.length);
|
|
37
|
+
this.inside = !this.inside;
|
|
38
|
+
continue;
|
|
39
|
+
}
|
|
40
|
+
const keep = partialTag(rest, tag);
|
|
41
|
+
const out = rest.slice(0, rest.length - keep);
|
|
42
|
+
if (this.inside) thinking += out;
|
|
43
|
+
else text += out;
|
|
44
|
+
this.held = rest.slice(rest.length - keep);
|
|
45
|
+
break;
|
|
46
|
+
}
|
|
47
|
+
return { text, thinking };
|
|
48
|
+
}
|
|
49
|
+
/** Whatever was held back as a possible tag start is plain text after all. */
|
|
50
|
+
flush() {
|
|
51
|
+
const held = this.held;
|
|
52
|
+
this.held = "";
|
|
53
|
+
return this.inside ? { text: "", thinking: held } : { text: held, thinking: "" };
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
function splitThinking(text) {
|
|
57
|
+
const s = new ThinkSplitter();
|
|
58
|
+
const a = s.push(text);
|
|
59
|
+
const b = s.flush();
|
|
60
|
+
return { text: a.text + b.text, thinking: a.thinking + b.thinking };
|
|
61
|
+
}
|
|
62
|
+
|
|
15
63
|
// src/provider.ts
|
|
16
64
|
var ProviderError = class extends Error {
|
|
17
65
|
constructor(message, status) {
|
|
@@ -58,8 +106,21 @@ function errorMessage(body) {
|
|
|
58
106
|
}
|
|
59
107
|
}
|
|
60
108
|
var toUsage = (u) => u ? { inputTokens: u.prompt_tokens ?? 0, outputTokens: u.completion_tokens ?? 0 } : void 0;
|
|
61
|
-
async function readStream(res, onText) {
|
|
109
|
+
async function readStream(res, onText, onThinking) {
|
|
62
110
|
let text = "";
|
|
111
|
+
let thinking = "";
|
|
112
|
+
const splitter = new ThinkSplitter();
|
|
113
|
+
const emit = (part) => {
|
|
114
|
+
if (part.thinking) {
|
|
115
|
+
thinking += part.thinking;
|
|
116
|
+
onThinking?.(part.thinking);
|
|
117
|
+
}
|
|
118
|
+
if (part.text) {
|
|
119
|
+
text += part.text;
|
|
120
|
+
onText?.(part.text);
|
|
121
|
+
if (loopAt < 0) loopAt = detectRepetition(text);
|
|
122
|
+
}
|
|
123
|
+
};
|
|
63
124
|
let usage;
|
|
64
125
|
let finishReason;
|
|
65
126
|
const calls = [];
|
|
@@ -84,11 +145,9 @@ async function readStream(res, onText) {
|
|
|
84
145
|
if (!choice) return;
|
|
85
146
|
if (choice.finish_reason) finishReason = choice.finish_reason;
|
|
86
147
|
const delta = choice.delta ?? {};
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
if (loopAt < 0) loopAt = detectRepetition(text);
|
|
91
|
-
}
|
|
148
|
+
const reasoning = delta.reasoning_content || delta.reasoning;
|
|
149
|
+
if (reasoning) emit({ text: "", thinking: reasoning });
|
|
150
|
+
if (delta.content) emit(splitter.push(delta.content));
|
|
92
151
|
for (const tc of delta.tool_calls ?? []) {
|
|
93
152
|
let target = tc.index !== void 0 ? byIndex.get(tc.index) : current;
|
|
94
153
|
if (!target || tc.index === void 0 && tc.id && target.id && target.id !== tc.id) {
|
|
@@ -110,11 +169,12 @@ async function readStream(res, onText) {
|
|
|
110
169
|
buffer = buffer.slice(newline + 1);
|
|
111
170
|
newline = buffer.indexOf("\n");
|
|
112
171
|
}
|
|
113
|
-
if (loopAt >= 0) return { text: text.slice(0, loopAt), toolCalls: [], usage, finishReason: "repetition" };
|
|
172
|
+
if (loopAt >= 0) return { text: text.slice(0, loopAt), toolCalls: [], thinking: thinking || void 0, usage, finishReason: "repetition" };
|
|
114
173
|
}
|
|
115
174
|
handle(buffer.trim());
|
|
175
|
+
emit(splitter.flush());
|
|
116
176
|
const toolCalls = calls.map((call, index) => ({ ...call, id: call.id || `call_${index}` }));
|
|
117
|
-
return { text, toolCalls, usage, finishReason };
|
|
177
|
+
return { text, toolCalls, thinking: thinking || void 0, usage, finishReason };
|
|
118
178
|
}
|
|
119
179
|
async function readJson(res) {
|
|
120
180
|
const body = await res.json();
|
|
@@ -124,7 +184,9 @@ async function readJson(res) {
|
|
|
124
184
|
name: tc.function?.name ?? "",
|
|
125
185
|
arguments: tc.function?.arguments ?? ""
|
|
126
186
|
}));
|
|
127
|
-
|
|
187
|
+
const split = splitThinking(choice?.message?.content ?? "");
|
|
188
|
+
const thinking = (choice?.message?.reasoning_content || choice?.message?.reasoning || "") + split.thinking;
|
|
189
|
+
return { text: split.text, toolCalls, thinking: thinking || void 0, usage: toUsage(body.usage), finishReason: choice?.finish_reason };
|
|
128
190
|
}
|
|
129
191
|
function createProvider({ baseURL, apiKey, model, fetch: doFetch = fetch, retryDelayMs = 1e3 }) {
|
|
130
192
|
const headers = { "content-type": "application/json" };
|
|
@@ -149,7 +211,7 @@ function createProvider({ baseURL, apiKey, model, fetch: doFetch = fetch, retryD
|
|
|
149
211
|
throw lastError ?? new ProviderError("Permintaan gagal");
|
|
150
212
|
}
|
|
151
213
|
return {
|
|
152
|
-
async chat({ messages, tools, signal, onText }) {
|
|
214
|
+
async chat({ messages, tools, signal, onText, onThinking }) {
|
|
153
215
|
const res = await post(
|
|
154
216
|
"/chat/completions",
|
|
155
217
|
{ model, messages, stream: true, stream_options: { include_usage: true }, ...tools?.length ? { tools } : {} },
|
|
@@ -157,7 +219,7 @@ function createProvider({ baseURL, apiKey, model, fetch: doFetch = fetch, retryD
|
|
|
157
219
|
);
|
|
158
220
|
if ((res.headers.get("content-type") ?? "").includes("application/json")) return readJson(res);
|
|
159
221
|
if (!res.body) throw new ProviderError("Respons provider kosong");
|
|
160
|
-
return readStream(res, onText);
|
|
222
|
+
return readStream(res, onText, onThinking);
|
|
161
223
|
},
|
|
162
224
|
async listModels() {
|
|
163
225
|
const res = await doFetch(`${baseURL}/models`, { headers });
|
|
@@ -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-MXV6PD6F.js");
|
|
39
39
|
const { parseCliArgs } = await import("./args-FCLPQ7TO.js");
|
|
40
40
|
return runProviderCommand(parseCliArgs(["provider", "add", providerId]), {
|
|
41
41
|
env: process.env,
|
package/dist/cli.js
CHANGED
|
@@ -7,10 +7,10 @@ import {
|
|
|
7
7
|
addProviderKey,
|
|
8
8
|
createProvider,
|
|
9
9
|
listAllModels
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-C5AFWX7H.js";
|
|
11
11
|
import {
|
|
12
12
|
runLogin
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-GW36UMHZ.js";
|
|
14
14
|
import {
|
|
15
15
|
BUILTIN_AGENTS,
|
|
16
16
|
buildSystemPrompt,
|
|
@@ -521,6 +521,71 @@ function toolDefinitions(tools) {
|
|
|
521
521
|
});
|
|
522
522
|
}
|
|
523
523
|
|
|
524
|
+
// src/textToolCalls.ts
|
|
525
|
+
var PAIR = /(?:<arg_key>\s*|`)?([A-Za-z_]\w*)(?:\s*<\/arg_key>)?`?\s*(?:=\s*`|<arg_value>)([\s\S]*?)<\/arg_value>/g;
|
|
526
|
+
var CALL_START = /<tool_call>|\n?[^\n]*\bTool call list\b[^\n]*|\n\s*\d+\.\s*Tool:/g;
|
|
527
|
+
function coerce(value, type) {
|
|
528
|
+
const types = Array.isArray(type) ? type : [type];
|
|
529
|
+
const v = value.trim();
|
|
530
|
+
if ((types.includes("integer") || types.includes("number")) && v !== "" && !Number.isNaN(Number(v))) return Number(v);
|
|
531
|
+
if (types.includes("boolean") && /^(true|false)$/i.test(v)) return v.toLowerCase() === "true";
|
|
532
|
+
if ((types.includes("object") || types.includes("array")) && /^[[{]/.test(v)) {
|
|
533
|
+
try {
|
|
534
|
+
return JSON.parse(v);
|
|
535
|
+
} catch {
|
|
536
|
+
}
|
|
537
|
+
}
|
|
538
|
+
return value.replace(/^\n+|\n+$/g, "");
|
|
539
|
+
}
|
|
540
|
+
function pickTool(name, keys, tools) {
|
|
541
|
+
const named = name && tools.find((t) => t.function.name === name);
|
|
542
|
+
if (named) return named;
|
|
543
|
+
let best;
|
|
544
|
+
let bestScore = 0;
|
|
545
|
+
let tie = false;
|
|
546
|
+
for (const t of tools) {
|
|
547
|
+
const params = t.function.parameters;
|
|
548
|
+
const props = Object.keys(params.properties ?? {});
|
|
549
|
+
if (!(params.required ?? []).every((r) => keys.includes(r))) continue;
|
|
550
|
+
const score = keys.filter((k) => props.includes(k)).length;
|
|
551
|
+
if (score > bestScore) [best, bestScore, tie] = [t, score, false];
|
|
552
|
+
else if (score === bestScore && score > 0) tie = true;
|
|
553
|
+
}
|
|
554
|
+
return tie ? void 0 : best;
|
|
555
|
+
}
|
|
556
|
+
function recoverTextToolCalls(text, tools) {
|
|
557
|
+
if (!/<\/arg_value>|<tool_call>/.test(text)) return null;
|
|
558
|
+
const starts = [...text.matchAll(CALL_START)].map((m) => m.index ?? 0);
|
|
559
|
+
const firstPair = text.search(PAIR);
|
|
560
|
+
const cut = Math.min(...[...starts, firstPair].filter((i) => i >= 0));
|
|
561
|
+
const bounds = starts.filter((i) => i >= cut);
|
|
562
|
+
if (!bounds.length || bounds[0] > cut) bounds.unshift(cut);
|
|
563
|
+
const toolCalls = [];
|
|
564
|
+
bounds.forEach((start, n) => {
|
|
565
|
+
const segment = text.slice(start, bounds[n + 1] ?? text.length);
|
|
566
|
+
const name = /<tool_call>\s*([A-Za-z_][\w.-]*)/.exec(segment)?.[1] ?? /Tool:\s*`?([A-Za-z_][\w.-]*)`?/.exec(segment)?.[1];
|
|
567
|
+
let args = [];
|
|
568
|
+
const flush = () => {
|
|
569
|
+
if (!args.length) return;
|
|
570
|
+
const keys = args.map(([k]) => k);
|
|
571
|
+
const tool = pickTool(name, keys, tools);
|
|
572
|
+
if (tool) {
|
|
573
|
+
const props = tool.function.parameters.properties ?? {};
|
|
574
|
+
const input = Object.fromEntries(args.filter(([k]) => k in props).map(([k, v]) => [k, coerce(v, props[k].type)]));
|
|
575
|
+
toolCalls.push({ id: `text_call_${toolCalls.length}`, name: tool.function.name, arguments: JSON.stringify(input) });
|
|
576
|
+
}
|
|
577
|
+
args = [];
|
|
578
|
+
};
|
|
579
|
+
for (const m of segment.matchAll(PAIR)) {
|
|
580
|
+
if (args.some(([k]) => k === m[1])) flush();
|
|
581
|
+
args.push([m[1], m[2]]);
|
|
582
|
+
}
|
|
583
|
+
flush();
|
|
584
|
+
});
|
|
585
|
+
if (!toolCalls.length) return null;
|
|
586
|
+
return { text: text.slice(0, cut).trim(), toolCalls };
|
|
587
|
+
}
|
|
588
|
+
|
|
524
589
|
// src/agent.ts
|
|
525
590
|
var estimateTokens = (text) => Math.ceil(text.length / 4);
|
|
526
591
|
var COMPACT_PROMPT = "Summarize the conversation so far for yourself so you can continue the work with no other context. Include: the user goals, decisions made, files touched and their current state, commands run and results, the task in progress and the next step. Be concise but complete.";
|
|
@@ -615,12 +680,20 @@ ${completion.text}` });
|
|
|
615
680
|
await this.compact(signal);
|
|
616
681
|
this.push({ role: "user", content: `Lanjutkan tugas ini sesuai ringkasan di atas: ${text}` });
|
|
617
682
|
}
|
|
618
|
-
|
|
683
|
+
let completion = await this.provider.chat({
|
|
619
684
|
messages: [{ role: "system", content: this.systemPrompt }, ...this.messages],
|
|
620
685
|
tools: this.turnDefinitions,
|
|
621
686
|
signal,
|
|
622
|
-
onText: (delta) => this.onEvent({ type: "text", delta })
|
|
687
|
+
onText: (delta) => this.onEvent({ type: "text", delta }),
|
|
688
|
+
onThinking: (delta) => this.onEvent({ type: "thinking", delta })
|
|
623
689
|
});
|
|
690
|
+
if (!completion.toolCalls.length && completion.finishReason !== "repetition") {
|
|
691
|
+
const recovered = recoverTextToolCalls(completion.text, this.turnDefinitions);
|
|
692
|
+
if (recovered) {
|
|
693
|
+
completion = { ...completion, ...recovered };
|
|
694
|
+
this.onEvent({ type: "textReplace", text: recovered.text });
|
|
695
|
+
}
|
|
696
|
+
}
|
|
624
697
|
const usage = completion.usage ?? {
|
|
625
698
|
inputTokens: estimateTokens(this.systemPrompt) + estimateTokens(JSON.stringify(this.messages)),
|
|
626
699
|
outputTokens: estimateTokens(completion.text) + (completion.toolCalls.length ? estimateTokens(JSON.stringify(completion.toolCalls)) : 0)
|
|
@@ -1200,7 +1273,7 @@ function createRuntime(opts) {
|
|
|
1200
1273
|
}
|
|
1201
1274
|
|
|
1202
1275
|
// src/version.ts
|
|
1203
|
-
var VERSION = true ? "0.4.0-beta.
|
|
1276
|
+
var VERSION = true ? "0.4.0-beta.4" : "0.0.0-dev";
|
|
1204
1277
|
|
|
1205
1278
|
// src/cli.ts
|
|
1206
1279
|
async function main() {
|
|
@@ -1217,12 +1290,12 @@ async function main() {
|
|
|
1217
1290
|
if (args.command === "login") return runLogin(args.loginProvider ?? "bc-cloud", cwd);
|
|
1218
1291
|
if (args.command === "mcp") {
|
|
1219
1292
|
const { runMcpCommand } = await import("./mcpCli-Q2H63ISP.js");
|
|
1220
|
-
const { readSecret } = await import("./login-
|
|
1293
|
+
const { readSecret } = await import("./login-F4G5QXOU.js");
|
|
1221
1294
|
return runMcpCommand(args, { env: process.env, cwd, out: (s) => console.log(s), err: (s) => console.error(s), readSecret });
|
|
1222
1295
|
}
|
|
1223
1296
|
if (args.command === "provider") {
|
|
1224
|
-
const { runProviderCommand } = await import("./providerCli-
|
|
1225
|
-
const { readSecret } = await import("./login-
|
|
1297
|
+
const { runProviderCommand } = await import("./providerCli-MXV6PD6F.js");
|
|
1298
|
+
const { readSecret } = await import("./login-F4G5QXOU.js");
|
|
1226
1299
|
return runProviderCommand(args, { env: process.env, cwd, out: (s) => console.log(s), err: (s) => console.error(s), readSecret });
|
|
1227
1300
|
}
|
|
1228
1301
|
if (args.command === "models") {
|
|
@@ -1252,7 +1325,7 @@ async function main() {
|
|
|
1252
1325
|
}
|
|
1253
1326
|
}
|
|
1254
1327
|
if (!process.stdin.isTTY) throw new ConfigError('Mode interaktif butuh terminal. Untuk skrip/CI pakai: bccli -p "tugas"');
|
|
1255
|
-
const { startInteractive } = await import("./ui-
|
|
1328
|
+
const { startInteractive } = await import("./ui-7FXPXXGN.js");
|
|
1256
1329
|
return startInteractive(rt, { initialPrompt: args.prompt, resume: args.resume, version: VERSION });
|
|
1257
1330
|
}
|
|
1258
1331
|
main().then(
|
|
@@ -638,6 +638,11 @@ function applyEvent(t, event) {
|
|
|
638
638
|
if (last?.kind === "assistant") return { ...t, live: [...t.live.slice(0, -1), { ...last, text: last.text + event.delta }] };
|
|
639
639
|
return { ...t, live: [...t.live, entry({ kind: "assistant", text: event.delta })] };
|
|
640
640
|
}
|
|
641
|
+
case "thinking": {
|
|
642
|
+
const last = t.live.at(-1);
|
|
643
|
+
if (last?.kind === "thinking") return { ...t, live: [...t.live.slice(0, -1), { ...last, text: last.text + event.delta }] };
|
|
644
|
+
return { ...t, live: [...t.live, entry({ kind: "thinking", text: event.delta })] };
|
|
645
|
+
}
|
|
641
646
|
case "textReplace": {
|
|
642
647
|
const last = t.live.at(-1);
|
|
643
648
|
if (last?.kind !== "assistant") return t;
|
|
@@ -687,6 +692,7 @@ function helpText(runtime) {
|
|
|
687
692
|
"",
|
|
688
693
|
"shift+tab ganti mode izin esc batalkan giliran",
|
|
689
694
|
"ctrl+o output alat terakhir lengkap \\ + enter baris baru",
|
|
695
|
+
"ctrl+t buka/tutup thinking model",
|
|
690
696
|
"@file + tab lengkapi nama file \u2191\u2193 riwayat input"
|
|
691
697
|
].join("\n");
|
|
692
698
|
}
|
|
@@ -713,6 +719,8 @@ function App({ runtime, initialPrompt, version }) {
|
|
|
713
719
|
const [mcpMenu, setMcpMenu] = useState8(null);
|
|
714
720
|
const [listPicker, setListPicker] = useState8(null);
|
|
715
721
|
const [planAsk, setPlanAsk] = useState8(null);
|
|
722
|
+
const [queued, setQueued] = useState8([]);
|
|
723
|
+
const [showThinking, setShowThinking] = useState8(false);
|
|
716
724
|
useEffect2(() => runtime.todos.subscribe(setTodos), [runtime]);
|
|
717
725
|
const extraCommands = [
|
|
718
726
|
...runtime.commands.filter((c) => !SLASH_COMMANDS.some((b) => b.name === c.name.toLowerCase())).map((c) => ({ name: c.name.toLowerCase(), description: c.description ?? "perintah custom" })),
|
|
@@ -1086,6 +1094,19 @@ ARGUMENTS: ${slash.args}`);
|
|
|
1086
1094
|
},
|
|
1087
1095
|
[runSlash, runTurn, runtime, notice]
|
|
1088
1096
|
);
|
|
1097
|
+
const onPrompt = useCallback(
|
|
1098
|
+
(text) => {
|
|
1099
|
+
if (busy) setQueued((q) => [...q, text]);
|
|
1100
|
+
else submit(text);
|
|
1101
|
+
},
|
|
1102
|
+
[busy, submit]
|
|
1103
|
+
);
|
|
1104
|
+
useEffect2(() => {
|
|
1105
|
+
if (busy || pending || planAsk || !queued.length) return;
|
|
1106
|
+
const [next, ...rest] = queued;
|
|
1107
|
+
setQueued(rest);
|
|
1108
|
+
submit(next);
|
|
1109
|
+
}, [busy, pending, planAsk, queued, submit]);
|
|
1089
1110
|
const initialSent = useRef(false);
|
|
1090
1111
|
useEffect2(() => {
|
|
1091
1112
|
if (initialPrompt && !initialSent.current) {
|
|
@@ -1100,6 +1121,25 @@ ARGUMENTS: ${slash.args}`);
|
|
|
1100
1121
|
setMode(next);
|
|
1101
1122
|
} else if (key.escape && busy && !pending) {
|
|
1102
1123
|
controller.current?.abort();
|
|
1124
|
+
if (queued.length) {
|
|
1125
|
+
setQueued([]);
|
|
1126
|
+
notice(`${queued.length} pesan antrian dibatalkan.`, "warn");
|
|
1127
|
+
}
|
|
1128
|
+
} else if (key.ctrl && input === "t") {
|
|
1129
|
+
const next = !showThinking;
|
|
1130
|
+
setShowThinking(next);
|
|
1131
|
+
setTranscript((t) => {
|
|
1132
|
+
const last = [...t.done, ...t.live].findLast((e) => e.kind === "thinking");
|
|
1133
|
+
const reprint = next && last?.kind === "thinking" && t.done.includes(last);
|
|
1134
|
+
return {
|
|
1135
|
+
...t,
|
|
1136
|
+
done: [
|
|
1137
|
+
...t.done,
|
|
1138
|
+
...reprint ? [entry({ kind: "thinking", text: last.text, open: true })] : [],
|
|
1139
|
+
entry({ kind: "notice", text: next ? "Thinking ditampilkan (ctrl+t untuk menutup)." : "Thinking disembunyikan (ctrl+t untuk membuka).", tone: "info" })
|
|
1140
|
+
]
|
|
1141
|
+
};
|
|
1142
|
+
});
|
|
1103
1143
|
} else if (key.ctrl && input === "o" && lastTool.current) {
|
|
1104
1144
|
const t = lastTool.current;
|
|
1105
1145
|
notice(`\u23BF ${t.tool} ${t.target}
|
|
@@ -1180,6 +1220,18 @@ ${t.output}`);
|
|
|
1180
1220
|
/* @__PURE__ */ jsx15(Text15, { color: color(ACCENT), children: "\u25CF " }),
|
|
1181
1221
|
/* @__PURE__ */ jsx15(Markdown, { text: e.text.replace(/^\s+/, "") })
|
|
1182
1222
|
] }, e.id);
|
|
1223
|
+
case "thinking": {
|
|
1224
|
+
const text = e.text.trim();
|
|
1225
|
+
if (!text) return null;
|
|
1226
|
+
if (!(e.open ?? showThinking)) {
|
|
1227
|
+
const lines = text.split("\n").length;
|
|
1228
|
+
return /* @__PURE__ */ jsx15(Box13, { marginTop: 1, children: /* @__PURE__ */ jsx15(Text15, { dimColor: true, children: `\u273B Berpikir \xB7 ${lines} baris \xB7 ctrl+t buka` }) }, e.id);
|
|
1229
|
+
}
|
|
1230
|
+
return /* @__PURE__ */ jsxs10(Box13, { marginTop: 1, flexDirection: "column", children: [
|
|
1231
|
+
/* @__PURE__ */ jsx15(Text15, { dimColor: true, children: "\u273B Berpikir (ctrl+t tutup)" }),
|
|
1232
|
+
/* @__PURE__ */ jsx15(Box13, { paddingLeft: 2, children: /* @__PURE__ */ jsx15(Text15, { dimColor: true, italic: true, children: text }) })
|
|
1233
|
+
] }, e.id);
|
|
1234
|
+
}
|
|
1183
1235
|
case "tool":
|
|
1184
1236
|
return /* @__PURE__ */ jsx15(ToolBlock, { tool: e.tool, target: e.target, output: e.output, display: e.display, isError: e.isError, done: e.done, sub: e.sub }, e.id);
|
|
1185
1237
|
case "notice":
|
|
@@ -1232,7 +1284,8 @@ ${t.output}`);
|
|
|
1232
1284
|
}
|
|
1233
1285
|
) : null,
|
|
1234
1286
|
/* @__PURE__ */ jsx15(TodoList, { items: todos }),
|
|
1235
|
-
/* @__PURE__ */ jsx15(
|
|
1287
|
+
queued.map((q, i) => /* @__PURE__ */ jsx15(Text15, { dimColor: true, children: ` \u23F3 antri: ${q}` }, `${i}-${q}`)),
|
|
1288
|
+
/* @__PURE__ */ jsx15(PromptInput, { disabled: !!pending || !!picker || !!providerMenu || !!prompt || !!planAsk || !!mcpMenu || !!listPicker, history, cwd: runtime.cwd, onSubmit: onPrompt, extraCommands }),
|
|
1236
1289
|
/* @__PURE__ */ jsx15(StatusBar, { mode, tokens, busy, model: modelLabel })
|
|
1237
1290
|
] });
|
|
1238
1291
|
}
|