@nomad-e/bluma-cli 0.1.30 → 0.1.32
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/README.md +435 -49
- package/dist/config/native_tools.json +12 -8
- package/dist/main.js +1459 -664
- package/package.json +2 -1
package/dist/main.js
CHANGED
|
@@ -328,33 +328,71 @@ var init_async_command = __esm({
|
|
|
328
328
|
});
|
|
329
329
|
|
|
330
330
|
// src/main.ts
|
|
331
|
-
import
|
|
331
|
+
import React12 from "react";
|
|
332
332
|
import { render } from "ink";
|
|
333
|
-
import { EventEmitter as
|
|
333
|
+
import { EventEmitter as EventEmitter3 } from "events";
|
|
334
334
|
import fs15 from "fs";
|
|
335
335
|
import { v4 as uuidv46 } from "uuid";
|
|
336
336
|
|
|
337
337
|
// src/app/ui/App.tsx
|
|
338
|
-
import { useState as
|
|
339
|
-
import { Box as
|
|
338
|
+
import { useState as useState6, useEffect as useEffect7, useRef as useRef5, useCallback as useCallback2, memo as memo12 } from "react";
|
|
339
|
+
import { Box as Box20, Text as Text19, Static } from "ink";
|
|
340
340
|
|
|
341
341
|
// src/app/ui/layout.tsx
|
|
342
342
|
import { Box, Text } from "ink";
|
|
343
343
|
import { memo } from "react";
|
|
344
|
-
|
|
344
|
+
|
|
345
|
+
// src/app/ui/theme/blumaTerminal.ts
|
|
346
|
+
var BLUMA_TERMINAL = {
|
|
347
|
+
brandBlue: "blue",
|
|
348
|
+
brandMagenta: "magenta",
|
|
349
|
+
text: "white",
|
|
350
|
+
muted: "gray",
|
|
351
|
+
dim: "gray",
|
|
352
|
+
code: "gray",
|
|
353
|
+
codeLabel: "blue",
|
|
354
|
+
link: "blue",
|
|
355
|
+
linkUnderline: true,
|
|
356
|
+
success: "green",
|
|
357
|
+
warn: "yellow",
|
|
358
|
+
err: "red",
|
|
359
|
+
panelBorder: "blue",
|
|
360
|
+
toolLabel: "magenta",
|
|
361
|
+
toolMeta: "gray",
|
|
362
|
+
heading1: "blue",
|
|
363
|
+
heading2: "blue",
|
|
364
|
+
headingDeep: "magenta",
|
|
365
|
+
listBullet: "magenta",
|
|
366
|
+
listBulletSub: "blue",
|
|
367
|
+
rule: "gray",
|
|
368
|
+
/** M3 CLI — superfícies e hierarquia */
|
|
369
|
+
m3Outline: "blue",
|
|
370
|
+
m3TonalOutline: "magenta",
|
|
371
|
+
m3Rail: "blue",
|
|
372
|
+
m3Label: "gray",
|
|
373
|
+
m3OnSurface: "white"
|
|
374
|
+
};
|
|
375
|
+
|
|
376
|
+
// src/app/ui/layout.tsx
|
|
377
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
345
378
|
var HeaderComponent = ({
|
|
346
379
|
sessionId,
|
|
347
380
|
workdir
|
|
348
381
|
}) => {
|
|
349
382
|
const dirName = workdir.split("/").pop() || workdir;
|
|
350
383
|
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginBottom: 1, children: [
|
|
351
|
-
/* @__PURE__ */
|
|
352
|
-
|
|
384
|
+
/* @__PURE__ */ jsxs(Box, { flexDirection: "row", flexWrap: "wrap", children: [
|
|
385
|
+
/* @__PURE__ */ jsx(Text, { color: BLUMA_TERMINAL.brandBlue, bold: true, children: "BluMa" }),
|
|
386
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: " \u2014 " }),
|
|
387
|
+
/* @__PURE__ */ jsx(Text, { children: "Base Language Unit" }),
|
|
388
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: " \xB7 " }),
|
|
389
|
+
/* @__PURE__ */ jsx(Text, { color: BLUMA_TERMINAL.brandMagenta, bold: true, children: "Model Agent" })
|
|
390
|
+
] }),
|
|
391
|
+
/* @__PURE__ */ jsxs(Box, { flexDirection: "row", flexWrap: "wrap", children: [
|
|
353
392
|
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "cwd " }),
|
|
354
|
-
/* @__PURE__ */ jsx(Text, { color:
|
|
355
|
-
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "
|
|
356
|
-
/* @__PURE__ */ jsx(Text, { dimColor: true, children:
|
|
357
|
-
/* @__PURE__ */ jsx(Text, { color: "gray", children: sessionId.slice(0, 8) })
|
|
393
|
+
/* @__PURE__ */ jsx(Text, { color: BLUMA_TERMINAL.brandBlue, children: dirName }),
|
|
394
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: " \u2502 session " }),
|
|
395
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: sessionId.slice(0, 8) })
|
|
358
396
|
] })
|
|
359
397
|
] });
|
|
360
398
|
};
|
|
@@ -366,12 +404,12 @@ var SessionInfoComponent = ({
|
|
|
366
404
|
mcpStatus
|
|
367
405
|
}) => /* @__PURE__ */ jsxs(Box, { paddingX: 1, children: [
|
|
368
406
|
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "mcp " }),
|
|
369
|
-
/* @__PURE__ */ jsx(Text, { color: mcpStatus === "connected" ?
|
|
370
|
-
toolsCount !== null
|
|
407
|
+
/* @__PURE__ */ jsx(Text, { color: mcpStatus === "connected" ? BLUMA_TERMINAL.success : BLUMA_TERMINAL.warn, children: mcpStatus === "connected" ? "on" : "\u2026" }),
|
|
408
|
+
toolsCount !== null ? /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
371
409
|
" ",
|
|
372
410
|
toolsCount,
|
|
373
411
|
" tools"
|
|
374
|
-
] })
|
|
412
|
+
] }) : null
|
|
375
413
|
] });
|
|
376
414
|
var SessionInfo = memo(SessionInfoComponent);
|
|
377
415
|
var TaskStatusBarComponent = ({
|
|
@@ -380,9 +418,9 @@ var TaskStatusBarComponent = ({
|
|
|
380
418
|
status
|
|
381
419
|
}) => {
|
|
382
420
|
const modeColors = {
|
|
383
|
-
PLANNING:
|
|
384
|
-
EXECUTION:
|
|
385
|
-
VERIFICATION:
|
|
421
|
+
PLANNING: BLUMA_TERMINAL.brandBlue,
|
|
422
|
+
EXECUTION: BLUMA_TERMINAL.brandBlue,
|
|
423
|
+
VERIFICATION: BLUMA_TERMINAL.brandMagenta
|
|
386
424
|
};
|
|
387
425
|
return /* @__PURE__ */ jsxs(Box, { paddingX: 1, children: [
|
|
388
426
|
/* @__PURE__ */ jsxs(Text, { color: modeColors[mode], bold: true, children: [
|
|
@@ -394,10 +432,10 @@ var TaskStatusBarComponent = ({
|
|
|
394
432
|
" ",
|
|
395
433
|
taskName
|
|
396
434
|
] }),
|
|
397
|
-
status
|
|
398
|
-
"
|
|
435
|
+
status ? /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
436
|
+
" \u2014 ",
|
|
399
437
|
status
|
|
400
|
-
] })
|
|
438
|
+
] }) : null
|
|
401
439
|
] });
|
|
402
440
|
};
|
|
403
441
|
var TaskStatusBar = memo(TaskStatusBarComponent);
|
|
@@ -408,6 +446,12 @@ import { Box as Box2, Text as Text2, useStdout, useInput as useInput2 } from "in
|
|
|
408
446
|
// src/app/ui/utils/useSimpleInputBuffer.ts
|
|
409
447
|
import { useReducer, useRef, useCallback, useEffect } from "react";
|
|
410
448
|
import { useInput } from "ink";
|
|
449
|
+
|
|
450
|
+
// src/app/ui/utils/expandPreviewHotkey.ts
|
|
451
|
+
import { EventEmitter } from "events";
|
|
452
|
+
var expandPreviewHotkeyBus = new EventEmitter();
|
|
453
|
+
|
|
454
|
+
// src/app/ui/utils/useSimpleInputBuffer.ts
|
|
411
455
|
function getLineStart(text, cursorPos) {
|
|
412
456
|
let pos = cursorPos - 1;
|
|
413
457
|
while (pos >= 0 && text[pos] !== "\n") {
|
|
@@ -546,7 +590,12 @@ function inputReducer(state, action, viewWidth) {
|
|
|
546
590
|
return state;
|
|
547
591
|
}
|
|
548
592
|
}
|
|
549
|
-
var useCustomInput = ({
|
|
593
|
+
var useCustomInput = ({
|
|
594
|
+
onSubmit,
|
|
595
|
+
viewWidth,
|
|
596
|
+
isReadOnly,
|
|
597
|
+
onInterrupt
|
|
598
|
+
}) => {
|
|
550
599
|
const [state, dispatch] = useReducer(
|
|
551
600
|
(s, a) => inputReducer(s, a, viewWidth),
|
|
552
601
|
{ text: "", cursorPosition: 0, viewStart: 0 }
|
|
@@ -597,6 +646,10 @@ var useCustomInput = ({ onSubmit, viewWidth, isReadOnly, onInterrupt }) => {
|
|
|
597
646
|
if (inputBuffer.current.length > 0 && (key.ctrl || key.meta || key.escape || key.return || key.leftArrow || key.rightArrow || key.upArrow || key.downArrow || key.tab || key.shift)) {
|
|
598
647
|
flushInputBuffer();
|
|
599
648
|
}
|
|
649
|
+
if (key.ctrl && input === "o") {
|
|
650
|
+
expandPreviewHotkeyBus.emit("expand");
|
|
651
|
+
return;
|
|
652
|
+
}
|
|
600
653
|
if (key.escape) {
|
|
601
654
|
onInterrupt();
|
|
602
655
|
return;
|
|
@@ -685,7 +738,7 @@ var useCustomInput = ({ onSubmit, viewWidth, isReadOnly, onInterrupt }) => {
|
|
|
685
738
|
|
|
686
739
|
// src/app/ui/components/InputPrompt.tsx
|
|
687
740
|
import { useEffect as useEffect3, useMemo, useState as useState2, memo as memo2 } from "react";
|
|
688
|
-
import { EventEmitter } from "events";
|
|
741
|
+
import { EventEmitter as EventEmitter2 } from "events";
|
|
689
742
|
|
|
690
743
|
// src/app/ui/utils/slashRegistry.ts
|
|
691
744
|
var getSlashCommands = () => [
|
|
@@ -884,9 +937,14 @@ function useAtCompletion({
|
|
|
884
937
|
return { open, suggestions, selected, setSelected, insertAtSelection, close, update };
|
|
885
938
|
}
|
|
886
939
|
|
|
940
|
+
// src/app/ui/constants/toolUiPreview.ts
|
|
941
|
+
var TOOL_PREVIEW_MAX_LINES = 8;
|
|
942
|
+
var EXPAND_OVERLAY_MAX_LINES = 60;
|
|
943
|
+
var TERMINAL_RULE_CHAR = "\u2500";
|
|
944
|
+
|
|
887
945
|
// src/app/ui/components/InputPrompt.tsx
|
|
888
|
-
import { Fragment
|
|
889
|
-
var uiEventBus = global.__bluma_ui_eventbus__ || new
|
|
946
|
+
import { Fragment, jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
947
|
+
var uiEventBus = global.__bluma_ui_eventbus__ || new EventEmitter2();
|
|
890
948
|
global.__bluma_ui_eventbus__ = uiEventBus;
|
|
891
949
|
var TextLine = memo2(({
|
|
892
950
|
line,
|
|
@@ -931,8 +989,8 @@ var PathSuggestions = memo2(({
|
|
|
931
989
|
const realIdx = start + idx;
|
|
932
990
|
const isSelected = realIdx === selected;
|
|
933
991
|
return /* @__PURE__ */ jsxs2(Box2, { paddingLeft: 1, paddingY: 0, children: [
|
|
934
|
-
/* @__PURE__ */ jsx2(Text2, { color: isSelected ?
|
|
935
|
-
/* @__PURE__ */ jsx2(Text2, { color: isSelected ?
|
|
992
|
+
/* @__PURE__ */ jsx2(Text2, { color: isSelected ? BLUMA_TERMINAL.brandMagenta : BLUMA_TERMINAL.muted, children: isSelected ? "> " : " " }),
|
|
993
|
+
/* @__PURE__ */ jsx2(Text2, { color: isSelected ? BLUMA_TERMINAL.brandBlue : void 0, bold: isSelected, dimColor: !isSelected, children: s.label })
|
|
936
994
|
] }, s.fullPath);
|
|
937
995
|
}) });
|
|
938
996
|
});
|
|
@@ -943,11 +1001,11 @@ var SlashSuggestions = memo2(({
|
|
|
943
1001
|
}) => /* @__PURE__ */ jsx2(Box2, { flexDirection: "column", marginTop: 1, children: suggestions.map((s, idx) => {
|
|
944
1002
|
const isSelected = idx === selectedIndex;
|
|
945
1003
|
return /* @__PURE__ */ jsxs2(Box2, { paddingLeft: 1, paddingY: 0, children: [
|
|
946
|
-
/* @__PURE__ */ jsx2(Text2, { color: isSelected ?
|
|
947
|
-
/* @__PURE__ */ jsxs2(Text2, { color: isSelected ?
|
|
1004
|
+
/* @__PURE__ */ jsx2(Text2, { color: isSelected ? BLUMA_TERMINAL.brandMagenta : BLUMA_TERMINAL.muted, children: isSelected ? "> " : " " }),
|
|
1005
|
+
/* @__PURE__ */ jsxs2(Text2, { color: isSelected ? BLUMA_TERMINAL.brandBlue : void 0, bold: isSelected, dimColor: !isSelected, children: [
|
|
948
1006
|
s.name,
|
|
949
1007
|
" ",
|
|
950
|
-
/* @__PURE__ */ jsxs2(Text2, {
|
|
1008
|
+
/* @__PURE__ */ jsxs2(Text2, { dimColor: true, children: [
|
|
951
1009
|
"- ",
|
|
952
1010
|
s.description
|
|
953
1011
|
] })
|
|
@@ -955,7 +1013,14 @@ var SlashSuggestions = memo2(({
|
|
|
955
1013
|
] }, s.name);
|
|
956
1014
|
}) }));
|
|
957
1015
|
SlashSuggestions.displayName = "SlashSuggestions";
|
|
958
|
-
var
|
|
1016
|
+
var InputRuleLine = memo2(() => {
|
|
1017
|
+
const { stdout } = useStdout();
|
|
1018
|
+
const cols = stdout?.columns ?? 80;
|
|
1019
|
+
const n = Math.max(8, cols);
|
|
1020
|
+
return /* @__PURE__ */ jsx2(Text2, { color: "white", children: TERMINAL_RULE_CHAR.repeat(n) });
|
|
1021
|
+
});
|
|
1022
|
+
InputRuleLine.displayName = "InputRuleLine";
|
|
1023
|
+
var Footer = memo2(({ isReadOnly }) => /* @__PURE__ */ jsx2(Box2, { justifyContent: "center", children: /* @__PURE__ */ jsx2(Text2, { dimColor: true, children: isReadOnly ? "ctrl+c to exit | Enter to send message | Shift+Enter for new line | esc interrupt | Ctrl+O expand last clip" : "ctrl+c to exit | Enter to submit | Shift+Enter for new line | /help commands | esc interrupt | Ctrl+O expand last clip" }) }));
|
|
959
1024
|
Footer.displayName = "Footer";
|
|
960
1025
|
var TextLinesRenderer = memo2(({
|
|
961
1026
|
lines,
|
|
@@ -965,17 +1030,14 @@ var TextLinesRenderer = memo2(({
|
|
|
965
1030
|
showPlaceholder,
|
|
966
1031
|
placeholder
|
|
967
1032
|
}) => {
|
|
968
|
-
return /* @__PURE__ */ jsx2(
|
|
1033
|
+
return /* @__PURE__ */ jsx2(Fragment, { children: lines.map((line, idx) => {
|
|
969
1034
|
const isFirstLine = idx === 0;
|
|
970
|
-
return /* @__PURE__ */ jsxs2(Box2, { flexDirection: "row",
|
|
971
|
-
isFirstLine && /* @__PURE__ */ jsxs2(Text2, { color: "white", children: [
|
|
1035
|
+
return /* @__PURE__ */ jsxs2(Box2, { flexDirection: "row", children: [
|
|
1036
|
+
isFirstLine && /* @__PURE__ */ jsxs2(Text2, { color: "white", bold: true, children: [
|
|
972
1037
|
">",
|
|
973
1038
|
" "
|
|
974
1039
|
] }),
|
|
975
|
-
!isFirstLine && /* @__PURE__ */
|
|
976
|
-
"\u2502",
|
|
977
|
-
" "
|
|
978
|
-
] }),
|
|
1040
|
+
!isFirstLine && /* @__PURE__ */ jsx2(Text2, { color: BLUMA_TERMINAL.brandMagenta, children: "\u2502 " }),
|
|
979
1041
|
showPlaceholder && isFirstLine && line.length === 0 ? /* @__PURE__ */ jsx2(Text2, { dimColor: true, children: placeholder }) : /* @__PURE__ */ jsx2(
|
|
980
1042
|
TextLine,
|
|
981
1043
|
{
|
|
@@ -1116,14 +1178,15 @@ var InputPrompt = memo2(({
|
|
|
1116
1178
|
return;
|
|
1117
1179
|
}
|
|
1118
1180
|
}, { isActive: true });
|
|
1119
|
-
return /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", children: [
|
|
1120
|
-
|
|
1121
|
-
|
|
1181
|
+
return /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", marginTop: 1, children: [
|
|
1182
|
+
/* @__PURE__ */ jsx2(InputRuleLine, {}),
|
|
1183
|
+
/* @__PURE__ */ jsx2(Box2, { flexDirection: "column", marginY: 0, children: disableWhileProcessing ? /* @__PURE__ */ jsxs2(Box2, { flexDirection: "row", flexWrap: "nowrap", children: [
|
|
1184
|
+
/* @__PURE__ */ jsxs2(Text2, { color: "white", bold: true, children: [
|
|
1122
1185
|
">",
|
|
1123
1186
|
" "
|
|
1124
1187
|
] }),
|
|
1125
1188
|
/* @__PURE__ */ jsx2(Text2, { dimColor: true, children: "ctrl+c to exit" })
|
|
1126
|
-
] })
|
|
1189
|
+
] }) : /* @__PURE__ */ jsxs2(Fragment, { children: [
|
|
1127
1190
|
/* @__PURE__ */ jsx2(Box2, { flexDirection: "column", children: /* @__PURE__ */ jsx2(
|
|
1128
1191
|
TextLinesRenderer,
|
|
1129
1192
|
{
|
|
@@ -1142,14 +1205,9 @@ var InputPrompt = memo2(({
|
|
|
1142
1205
|
selected: pathAutocomplete.selected
|
|
1143
1206
|
}
|
|
1144
1207
|
),
|
|
1145
|
-
slashOpen && slashSuggestions.length > 0 && /* @__PURE__ */ jsx2(
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
suggestions: slashSuggestions,
|
|
1149
|
-
selectedIndex: slashIndex
|
|
1150
|
-
}
|
|
1151
|
-
)
|
|
1152
|
-
] }),
|
|
1208
|
+
slashOpen && slashSuggestions.length > 0 && /* @__PURE__ */ jsx2(SlashSuggestions, { suggestions: slashSuggestions, selectedIndex: slashIndex })
|
|
1209
|
+
] }) }),
|
|
1210
|
+
/* @__PURE__ */ jsx2(InputRuleLine, {}),
|
|
1153
1211
|
/* @__PURE__ */ jsx2(Footer, { isReadOnly })
|
|
1154
1212
|
] });
|
|
1155
1213
|
});
|
|
@@ -1157,7 +1215,7 @@ InputPrompt.displayName = "InputPrompt";
|
|
|
1157
1215
|
|
|
1158
1216
|
// src/app/ui/ConfirmationPrompt.tsx
|
|
1159
1217
|
import { memo as memo4 } from "react";
|
|
1160
|
-
import { Box as
|
|
1218
|
+
import { Box as Box7, Text as Text7 } from "ink";
|
|
1161
1219
|
|
|
1162
1220
|
// src/app/ui/InteractiveMenu.tsx
|
|
1163
1221
|
import { useState as useState3, memo as memo3 } from "react";
|
|
@@ -1165,9 +1223,9 @@ import { Box as Box3, Text as Text3, useInput as useInput3 } from "ink";
|
|
|
1165
1223
|
import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
1166
1224
|
var InteractiveMenuComponent = ({ onDecision }) => {
|
|
1167
1225
|
const options = [
|
|
1168
|
-
{ key: "y", label: "yes", value: "accept"
|
|
1169
|
-
{ key: "n", label: "no", value: "decline"
|
|
1170
|
-
{ key: "a", label: "always", value: "accept_always"
|
|
1226
|
+
{ key: "y", label: "yes", value: "accept" },
|
|
1227
|
+
{ key: "n", label: "no", value: "decline" },
|
|
1228
|
+
{ key: "a", label: "always", value: "accept_always" }
|
|
1171
1229
|
];
|
|
1172
1230
|
const [selected, setSelected] = useState3(0);
|
|
1173
1231
|
useInput3((input, key) => {
|
|
@@ -1188,12 +1246,12 @@ var InteractiveMenuComponent = ({ onDecision }) => {
|
|
|
1188
1246
|
onDecision(opt.value);
|
|
1189
1247
|
}
|
|
1190
1248
|
});
|
|
1191
|
-
return /* @__PURE__ */ jsxs3(Box3, { flexDirection: "column",
|
|
1192
|
-
/* @__PURE__ */ jsxs3(Box3, { children: [
|
|
1193
|
-
/* @__PURE__ */ jsx3(Text3, { dimColor: true, children: "approve
|
|
1249
|
+
return /* @__PURE__ */ jsxs3(Box3, { flexDirection: "column", marginTop: 1, children: [
|
|
1250
|
+
/* @__PURE__ */ jsxs3(Box3, { flexDirection: "row", flexWrap: "wrap", children: [
|
|
1251
|
+
/* @__PURE__ */ jsx3(Text3, { dimColor: true, children: "approve \xB7 " }),
|
|
1194
1252
|
options.map((opt, idx) => {
|
|
1195
1253
|
const isSelected = idx === selected;
|
|
1196
|
-
return /* @__PURE__ */ jsx3(Box3, { marginRight: 1, children: /* @__PURE__ */ jsxs3(Text3, { color: isSelected ?
|
|
1254
|
+
return /* @__PURE__ */ jsx3(Box3, { marginRight: 1, children: /* @__PURE__ */ jsxs3(Text3, { color: isSelected ? BLUMA_TERMINAL.brandMagenta : BLUMA_TERMINAL.muted, bold: isSelected, children: [
|
|
1197
1255
|
"[",
|
|
1198
1256
|
opt.key,
|
|
1199
1257
|
"]",
|
|
@@ -1201,7 +1259,7 @@ var InteractiveMenuComponent = ({ onDecision }) => {
|
|
|
1201
1259
|
] }) }, opt.value);
|
|
1202
1260
|
})
|
|
1203
1261
|
] }),
|
|
1204
|
-
/* @__PURE__ */ jsx3(Box3, { children: /* @__PURE__ */ jsx3(Text3, { dimColor: true, children: "arrows
|
|
1262
|
+
/* @__PURE__ */ jsx3(Box3, { marginTop: 0, children: /* @__PURE__ */ jsx3(Text3, { dimColor: true, children: "arrows \xB7 enter \xB7 esc cancel" }) })
|
|
1205
1263
|
] });
|
|
1206
1264
|
};
|
|
1207
1265
|
var InteractiveMenu = memo3(InteractiveMenuComponent);
|
|
@@ -1354,7 +1412,7 @@ var renderEditTool = ({ toolCall, preview }) => {
|
|
|
1354
1412
|
var renderGeneric = ({ toolCall }) => {
|
|
1355
1413
|
const toolName = toolCall.function.name;
|
|
1356
1414
|
const rawArguments = toolCall.function.arguments;
|
|
1357
|
-
const
|
|
1415
|
+
const MAX_LINES = 5;
|
|
1358
1416
|
let formattedArgsString;
|
|
1359
1417
|
if (!rawArguments) {
|
|
1360
1418
|
formattedArgsString = "";
|
|
@@ -1369,9 +1427,9 @@ var renderGeneric = ({ toolCall }) => {
|
|
|
1369
1427
|
formattedArgsString = JSON.stringify(rawArguments, null, 2);
|
|
1370
1428
|
}
|
|
1371
1429
|
const lines = formattedArgsString.split("\n");
|
|
1372
|
-
const isTruncated = lines.length >
|
|
1373
|
-
const visibleLines = isTruncated ? lines.slice(0,
|
|
1374
|
-
const remainingCount = lines.length -
|
|
1430
|
+
const isTruncated = lines.length > MAX_LINES;
|
|
1431
|
+
const visibleLines = isTruncated ? lines.slice(0, MAX_LINES) : lines;
|
|
1432
|
+
const remainingCount = lines.length - MAX_LINES;
|
|
1375
1433
|
return /* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", paddingX: 1, marginBottom: 1, children: [
|
|
1376
1434
|
/* @__PURE__ */ jsxs5(Box5, { children: [
|
|
1377
1435
|
/* @__PURE__ */ jsx5(Text5, { color: "blue", children: "\u25B8" }),
|
|
@@ -1411,12 +1469,12 @@ var renderTodoTool = ({ toolCall }) => {
|
|
|
1411
1469
|
/* @__PURE__ */ jsx5(Text5, { dimColor: true, children: " todo" })
|
|
1412
1470
|
] }),
|
|
1413
1471
|
/* @__PURE__ */ jsxs5(Box5, { paddingLeft: 2, flexDirection: "column", children: [
|
|
1414
|
-
/* @__PURE__ */ jsxs5(Text5, { color: "
|
|
1415
|
-
"
|
|
1472
|
+
/* @__PURE__ */ jsxs5(Text5, { color: "blue", children: [
|
|
1473
|
+
"todo ",
|
|
1416
1474
|
pending,
|
|
1417
|
-
"
|
|
1475
|
+
" open \xB7 ",
|
|
1418
1476
|
completed,
|
|
1419
|
-
"
|
|
1477
|
+
" done"
|
|
1420
1478
|
] }),
|
|
1421
1479
|
tasks.length > 0 && tasks.length <= 10 && /* @__PURE__ */ jsx5(Box5, { paddingLeft: 2, flexDirection: "column", marginTop: 1, children: tasks.map((task, idx) => {
|
|
1422
1480
|
const isComplete = task.isComplete === true;
|
|
@@ -1466,19 +1524,60 @@ var promptRenderers = {
|
|
|
1466
1524
|
// <--- ADICIONE ESTA LINHA
|
|
1467
1525
|
};
|
|
1468
1526
|
|
|
1469
|
-
// src/app/ui/
|
|
1527
|
+
// src/app/ui/theme/m3Layout.tsx
|
|
1528
|
+
import { Box as Box6, Text as Text6 } from "ink";
|
|
1470
1529
|
import { jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
1530
|
+
function ChatBlock({
|
|
1531
|
+
children,
|
|
1532
|
+
marginBottom = 1
|
|
1533
|
+
}) {
|
|
1534
|
+
return /* @__PURE__ */ jsx6(Box6, { flexDirection: "column", marginBottom, children });
|
|
1535
|
+
}
|
|
1536
|
+
function ChatUserMessage({ children }) {
|
|
1537
|
+
return /* @__PURE__ */ jsxs6(Box6, { flexDirection: "row", marginBottom: 1, flexWrap: "wrap", alignItems: "flex-start", children: [
|
|
1538
|
+
/* @__PURE__ */ jsxs6(Text6, { color: "white", bold: true, children: [
|
|
1539
|
+
">",
|
|
1540
|
+
" "
|
|
1541
|
+
] }),
|
|
1542
|
+
/* @__PURE__ */ jsx6(Box6, { flexDirection: "column", flexGrow: 1, children })
|
|
1543
|
+
] });
|
|
1544
|
+
}
|
|
1545
|
+
function ChatMeta({ children }) {
|
|
1546
|
+
return /* @__PURE__ */ jsx6(Box6, { marginBottom: 1, children: /* @__PURE__ */ jsx6(Text6, { dimColor: true, children }) });
|
|
1547
|
+
}
|
|
1548
|
+
function ChatStatusRow({ children }) {
|
|
1549
|
+
return /* @__PURE__ */ jsxs6(Box6, { flexDirection: "row", marginBottom: 1, flexWrap: "wrap", children: [
|
|
1550
|
+
/* @__PURE__ */ jsxs6(Text6, { color: BLUMA_TERMINAL.brandMagenta, bold: true, children: [
|
|
1551
|
+
"*",
|
|
1552
|
+
" "
|
|
1553
|
+
] }),
|
|
1554
|
+
children
|
|
1555
|
+
] });
|
|
1556
|
+
}
|
|
1557
|
+
function ChatTurnDuration({ secondsFormatted }) {
|
|
1558
|
+
return /* @__PURE__ */ jsx6(Box6, { marginBottom: 1, children: /* @__PURE__ */ jsxs6(Text6, { dimColor: true, children: [
|
|
1559
|
+
/* @__PURE__ */ jsx6(Text6, { color: BLUMA_TERMINAL.brandBlue, children: "\xB7 " }),
|
|
1560
|
+
/* @__PURE__ */ jsxs6(Text6, { color: BLUMA_TERMINAL.brandMagenta, children: [
|
|
1561
|
+
secondsFormatted,
|
|
1562
|
+
"s"
|
|
1563
|
+
] })
|
|
1564
|
+
] }) });
|
|
1565
|
+
}
|
|
1566
|
+
var M3StatusStrip = ChatStatusRow;
|
|
1567
|
+
|
|
1568
|
+
// src/app/ui/ConfirmationPrompt.tsx
|
|
1569
|
+
import { jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
1471
1570
|
var ConfirmationPromptComponent = ({ toolCalls, preview, onDecision }) => {
|
|
1472
|
-
const toolCall = toolCalls && toolCalls.length > 0 ? toolCalls[0] : null;
|
|
1473
|
-
if (!toolCall) {
|
|
1474
|
-
return /* @__PURE__ */
|
|
1571
|
+
const toolCall = toolCalls && Array.isArray(toolCalls) && toolCalls.length > 0 ? toolCalls[0] : null;
|
|
1572
|
+
if (!toolCall?.function) {
|
|
1573
|
+
return /* @__PURE__ */ jsx7(Box7, { paddingX: 1, children: /* @__PURE__ */ jsx7(Text7, { dimColor: true, children: "waiting\u2026" }) });
|
|
1475
1574
|
}
|
|
1476
|
-
const toolName = toolCall.function.name;
|
|
1575
|
+
const toolName = toolCall.function.name || "tool";
|
|
1477
1576
|
const renderFunction = promptRenderers[toolName] || renderGeneric;
|
|
1478
|
-
return /* @__PURE__ */
|
|
1577
|
+
return /* @__PURE__ */ jsx7(ChatBlock, { marginBottom: 1, children: /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", paddingLeft: 1, children: [
|
|
1479
1578
|
renderFunction({ toolCall, preview }),
|
|
1480
|
-
/* @__PURE__ */
|
|
1481
|
-
] });
|
|
1579
|
+
/* @__PURE__ */ jsx7(InteractiveMenu, { onDecision })
|
|
1580
|
+
] }) });
|
|
1482
1581
|
};
|
|
1483
1582
|
var ConfirmationPrompt = memo4(ConfirmationPromptComponent);
|
|
1484
1583
|
|
|
@@ -3605,14 +3704,84 @@ function searchNotes(args) {
|
|
|
3605
3704
|
matched: matches
|
|
3606
3705
|
};
|
|
3607
3706
|
}
|
|
3608
|
-
function
|
|
3707
|
+
function removeNote(args) {
|
|
3609
3708
|
loadMemoryFromFile();
|
|
3610
|
-
|
|
3611
|
-
|
|
3709
|
+
const id = args.id;
|
|
3710
|
+
if (id == null || typeof id !== "number" || !Number.isFinite(id)) {
|
|
3711
|
+
return {
|
|
3712
|
+
success: false,
|
|
3713
|
+
message: "id is required for action=remove (use list or search to get ids)",
|
|
3714
|
+
entries: memoryStore
|
|
3715
|
+
};
|
|
3716
|
+
}
|
|
3717
|
+
const idx = memoryStore.findIndex((e) => e.id === id);
|
|
3718
|
+
if (idx === -1) {
|
|
3719
|
+
return {
|
|
3720
|
+
success: false,
|
|
3721
|
+
message: `No coding memory entry with id=${id}`,
|
|
3722
|
+
entries: memoryStore
|
|
3723
|
+
};
|
|
3724
|
+
}
|
|
3725
|
+
memoryStore.splice(idx, 1);
|
|
3726
|
+
saveMemoryToFile();
|
|
3727
|
+
return {
|
|
3728
|
+
success: true,
|
|
3729
|
+
message: `Removed coding memory entry id=${id}`,
|
|
3730
|
+
entries: memoryStore
|
|
3731
|
+
};
|
|
3732
|
+
}
|
|
3733
|
+
function updateNote(args) {
|
|
3734
|
+
loadMemoryFromFile();
|
|
3735
|
+
const id = args.id;
|
|
3736
|
+
if (id == null || typeof id !== "number" || !Number.isFinite(id)) {
|
|
3737
|
+
return {
|
|
3738
|
+
success: false,
|
|
3739
|
+
message: "id is required for action=update",
|
|
3740
|
+
entries: memoryStore
|
|
3741
|
+
};
|
|
3742
|
+
}
|
|
3743
|
+
const entry = memoryStore.find((e) => e.id === id);
|
|
3744
|
+
if (!entry) {
|
|
3745
|
+
return {
|
|
3746
|
+
success: false,
|
|
3747
|
+
message: `No coding memory entry with id=${id}`,
|
|
3748
|
+
entries: memoryStore
|
|
3749
|
+
};
|
|
3750
|
+
}
|
|
3751
|
+
const hasNote = typeof args.note === "string";
|
|
3752
|
+
const hasTags = args.tags !== void 0;
|
|
3753
|
+
if (!hasNote && !hasTags) {
|
|
3754
|
+
return {
|
|
3755
|
+
success: false,
|
|
3756
|
+
message: "update requires `note` and/or `tags` (omit fields you do not want to change)",
|
|
3757
|
+
entries: memoryStore
|
|
3758
|
+
};
|
|
3759
|
+
}
|
|
3760
|
+
if (hasNote) {
|
|
3761
|
+
const newNote = args.note.trim();
|
|
3762
|
+
if (!newNote) {
|
|
3763
|
+
return {
|
|
3764
|
+
success: false,
|
|
3765
|
+
message: "note cannot be empty; omit `note` to keep the existing text",
|
|
3766
|
+
entries: memoryStore
|
|
3767
|
+
};
|
|
3768
|
+
}
|
|
3769
|
+
if (newNote.length > 4e3) {
|
|
3770
|
+
return {
|
|
3771
|
+
success: false,
|
|
3772
|
+
message: "note too long (max 4000 chars)",
|
|
3773
|
+
entries: memoryStore
|
|
3774
|
+
};
|
|
3775
|
+
}
|
|
3776
|
+
entry.note = newNote;
|
|
3777
|
+
}
|
|
3778
|
+
if (hasTags) {
|
|
3779
|
+
entry.tags = normalizeTags(args.tags);
|
|
3780
|
+
}
|
|
3612
3781
|
saveMemoryToFile();
|
|
3613
3782
|
return {
|
|
3614
3783
|
success: true,
|
|
3615
|
-
message:
|
|
3784
|
+
message: `Updated coding memory id=${id}`,
|
|
3616
3785
|
entries: memoryStore
|
|
3617
3786
|
};
|
|
3618
3787
|
}
|
|
@@ -3625,8 +3794,10 @@ async function coding_memory(args) {
|
|
|
3625
3794
|
return listNotes();
|
|
3626
3795
|
case "search":
|
|
3627
3796
|
return searchNotes(args);
|
|
3628
|
-
case "
|
|
3629
|
-
return
|
|
3797
|
+
case "remove":
|
|
3798
|
+
return removeNote(args);
|
|
3799
|
+
case "update":
|
|
3800
|
+
return updateNote(args);
|
|
3630
3801
|
default:
|
|
3631
3802
|
return {
|
|
3632
3803
|
success: false,
|
|
@@ -3939,20 +4110,21 @@ async function withFileLock(file, fn) {
|
|
|
3939
4110
|
}
|
|
3940
4111
|
var pendingSaves = /* @__PURE__ */ new Map();
|
|
3941
4112
|
var DEBOUNCE_DELAY_MS = 100;
|
|
3942
|
-
function debouncedSave(sessionFile, history) {
|
|
4113
|
+
function debouncedSave(sessionFile, history, memory) {
|
|
3943
4114
|
const existing = pendingSaves.get(sessionFile);
|
|
3944
4115
|
if (existing) {
|
|
3945
4116
|
clearTimeout(existing.timer);
|
|
3946
4117
|
}
|
|
4118
|
+
const resolvedMemory = memory !== void 0 ? memory : existing?.memory;
|
|
3947
4119
|
const timer = setTimeout(async () => {
|
|
3948
4120
|
pendingSaves.delete(sessionFile);
|
|
3949
4121
|
try {
|
|
3950
|
-
await doSaveSessionHistory(sessionFile, history);
|
|
4122
|
+
await doSaveSessionHistory(sessionFile, history, resolvedMemory);
|
|
3951
4123
|
} catch (e) {
|
|
3952
4124
|
console.warn(`Debounced save failed for ${sessionFile}: ${e.message}`);
|
|
3953
4125
|
}
|
|
3954
4126
|
}, DEBOUNCE_DELAY_MS);
|
|
3955
|
-
pendingSaves.set(sessionFile, { history: [...history], timer });
|
|
4127
|
+
pendingSaves.set(sessionFile, { history: [...history], memory: resolvedMemory, timer });
|
|
3956
4128
|
}
|
|
3957
4129
|
function expandHome(p) {
|
|
3958
4130
|
if (!p) return p;
|
|
@@ -4017,7 +4189,11 @@ async function loadOrcreateSession(sessionId) {
|
|
|
4017
4189
|
await fs11.access(sessionFile);
|
|
4018
4190
|
const fileContent = await fs11.readFile(sessionFile, "utf-8");
|
|
4019
4191
|
const sessionData = JSON.parse(fileContent);
|
|
4020
|
-
|
|
4192
|
+
const memory = {
|
|
4193
|
+
historyAnchor: sessionData.history_anchor ?? null,
|
|
4194
|
+
compressedTurnSliceCount: sessionData.compressed_turn_slice_count ?? 0
|
|
4195
|
+
};
|
|
4196
|
+
return [sessionFile, sessionData.conversation_history || [], memory];
|
|
4021
4197
|
} catch (error) {
|
|
4022
4198
|
const newSessionData = {
|
|
4023
4199
|
session_id: sessionId,
|
|
@@ -4025,10 +4201,14 @@ async function loadOrcreateSession(sessionId) {
|
|
|
4025
4201
|
conversation_history: []
|
|
4026
4202
|
};
|
|
4027
4203
|
await fs11.writeFile(sessionFile, JSON.stringify(newSessionData, null, 2), "utf-8");
|
|
4028
|
-
|
|
4204
|
+
const emptyMemory = {
|
|
4205
|
+
historyAnchor: null,
|
|
4206
|
+
compressedTurnSliceCount: 0
|
|
4207
|
+
};
|
|
4208
|
+
return [sessionFile, [], emptyMemory];
|
|
4029
4209
|
}
|
|
4030
4210
|
}
|
|
4031
|
-
async function doSaveSessionHistory(sessionFile, history) {
|
|
4211
|
+
async function doSaveSessionHistory(sessionFile, history, memory) {
|
|
4032
4212
|
await withFileLock(sessionFile, async () => {
|
|
4033
4213
|
let sessionData;
|
|
4034
4214
|
try {
|
|
@@ -4061,6 +4241,14 @@ async function doSaveSessionHistory(sessionFile, history) {
|
|
|
4061
4241
|
}
|
|
4062
4242
|
sessionData.conversation_history = history;
|
|
4063
4243
|
sessionData.last_updated = (/* @__PURE__ */ new Date()).toISOString();
|
|
4244
|
+
if (memory) {
|
|
4245
|
+
if (memory.historyAnchor) {
|
|
4246
|
+
sessionData.history_anchor = memory.historyAnchor;
|
|
4247
|
+
} else {
|
|
4248
|
+
delete sessionData.history_anchor;
|
|
4249
|
+
}
|
|
4250
|
+
sessionData.compressed_turn_slice_count = memory.compressedTurnSliceCount;
|
|
4251
|
+
}
|
|
4064
4252
|
const tempSessionFile = `${sessionFile}.${Date.now()}.tmp`;
|
|
4065
4253
|
try {
|
|
4066
4254
|
await fs11.writeFile(tempSessionFile, JSON.stringify(sessionData, null, 2), "utf-8");
|
|
@@ -4078,14 +4266,14 @@ async function doSaveSessionHistory(sessionFile, history) {
|
|
|
4078
4266
|
}
|
|
4079
4267
|
});
|
|
4080
4268
|
}
|
|
4081
|
-
async function saveSessionHistory(sessionFile, history) {
|
|
4269
|
+
async function saveSessionHistory(sessionFile, history, memory) {
|
|
4082
4270
|
const cleanHistory = history.filter((msg) => {
|
|
4083
4271
|
if (msg.role === "user" && typeof msg.content === "string") {
|
|
4084
4272
|
return !msg.content.startsWith("[SKILL:");
|
|
4085
4273
|
}
|
|
4086
4274
|
return true;
|
|
4087
4275
|
});
|
|
4088
|
-
debouncedSave(sessionFile, cleanHistory);
|
|
4276
|
+
debouncedSave(sessionFile, cleanHistory, memory);
|
|
4089
4277
|
}
|
|
4090
4278
|
|
|
4091
4279
|
// src/app/agent/core/prompt/prompt_builder.ts
|
|
@@ -4098,7 +4286,6 @@ import { execSync } from "child_process";
|
|
|
4098
4286
|
import fs12 from "fs";
|
|
4099
4287
|
import path14 from "path";
|
|
4100
4288
|
import os7 from "os";
|
|
4101
|
-
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
4102
4289
|
var SkillLoader = class _SkillLoader {
|
|
4103
4290
|
bundledSkillsDir;
|
|
4104
4291
|
projectSkillsDir;
|
|
@@ -4115,19 +4302,35 @@ var SkillLoader = class _SkillLoader {
|
|
|
4115
4302
|
* Funciona tanto em ESM como quando executado a partir de dist/.
|
|
4116
4303
|
*/
|
|
4117
4304
|
static resolveBundledDir() {
|
|
4118
|
-
if (process.env.
|
|
4119
|
-
if (typeof __dirname !== "undefined") {
|
|
4120
|
-
return path14.join(__dirname, "config", "skills");
|
|
4121
|
-
}
|
|
4305
|
+
if (process.env.JEST_WORKER_ID !== void 0 || process.env.NODE_ENV === "test") {
|
|
4122
4306
|
return path14.join(process.cwd(), "dist", "config", "skills");
|
|
4123
4307
|
}
|
|
4124
|
-
|
|
4125
|
-
|
|
4126
|
-
|
|
4127
|
-
|
|
4128
|
-
|
|
4129
|
-
|
|
4308
|
+
const candidates = [];
|
|
4309
|
+
const argv1 = process.argv[1];
|
|
4310
|
+
if (argv1 && !argv1.startsWith("-")) {
|
|
4311
|
+
try {
|
|
4312
|
+
const scriptDir = path14.dirname(path14.resolve(argv1));
|
|
4313
|
+
candidates.push(path14.join(scriptDir, "config", "skills"));
|
|
4314
|
+
} catch {
|
|
4315
|
+
}
|
|
4130
4316
|
}
|
|
4317
|
+
candidates.push(
|
|
4318
|
+
path14.join(process.cwd(), "dist", "config", "skills"),
|
|
4319
|
+
path14.join(process.cwd(), "node_modules", "@nomad-e", "bluma-cli", "dist", "config", "skills")
|
|
4320
|
+
);
|
|
4321
|
+
if (typeof __dirname !== "undefined") {
|
|
4322
|
+
candidates.push(
|
|
4323
|
+
path14.join(__dirname, "config", "skills"),
|
|
4324
|
+
path14.join(__dirname, "..", "..", "..", "config", "skills")
|
|
4325
|
+
);
|
|
4326
|
+
}
|
|
4327
|
+
for (const c of candidates) {
|
|
4328
|
+
const abs = path14.resolve(c);
|
|
4329
|
+
if (fs12.existsSync(abs)) {
|
|
4330
|
+
return abs;
|
|
4331
|
+
}
|
|
4332
|
+
}
|
|
4333
|
+
return path14.join(process.cwd(), "dist", "config", "skills");
|
|
4131
4334
|
}
|
|
4132
4335
|
/**
|
|
4133
4336
|
* Lista skills disponíveis de todas as fontes.
|
|
@@ -4501,6 +4704,10 @@ var SYSTEM_PROMPT = `
|
|
|
4501
4704
|
- NEVER try to \`load_skill\` with a name that isn't in \`<available_skills>\`
|
|
4502
4705
|
- Your base knowledge (testing, git, docker...) is NOT a skill - it's just knowledge you have
|
|
4503
4706
|
|
|
4707
|
+
**Git / commits (when \`git-commit\` is listed in \`<available_skills>\`):**
|
|
4708
|
+
- For "commit", "push", "commit message", or "conventional commit": call \`load_skill({ skill_name: "git-commit" })\` **before** \`git commit\`, then follow the skill body (scopes, types, optional validator script).
|
|
4709
|
+
- The bundled skill name is exactly \`git-commit\`. Do **not** use \`git-conventional\` or other invented names.
|
|
4710
|
+
|
|
4504
4711
|
**Progressive Disclosure (Skills with references and scripts):**
|
|
4505
4712
|
|
|
4506
4713
|
Skills may include additional assets beyond the SKILL.md body:
|
|
@@ -4553,19 +4760,35 @@ You MUST adapt all commands to this environment. Use the correct package manager
|
|
|
4553
4760
|
<coding_memory>
|
|
4554
4761
|
## Persistent coding memory (tool: \`coding_memory\`)
|
|
4555
4762
|
|
|
4556
|
-
|
|
4763
|
+
This is your **long-term scratchpad** (usually \`~/.bluma/coding_memory.json\`). It is **not** the chat log: it persists across sessions so you can behave like a coding agent that **actually recalls** stable project facts\u2014**but only if you use the tool**.
|
|
4764
|
+
|
|
4765
|
+
### Ground rules
|
|
4766
|
+
- **Never invent** what is stored: if you are not sure, run \`action: "search"\` (or \`list\`) before stating a remembered fact.
|
|
4767
|
+
- The **<coding_memory_snapshot>** below is a **one-time snapshot at session start**. After any \`add\`, \`remove\`, or \`update\` in this session, treat the snapshot as **possibly stale** and **search** or **list** before relying on it.
|
|
4768
|
+
- Do **not** ask the user for permission to search memory when it reduces risk (e.g. they mention a prior decision, branch name, or "as we agreed").
|
|
4769
|
+
- **There is no "clear all"**: you can only **remove** entries **one id at a time** (\`action: "remove"\`, \`id\`). To fix bad data, \`update\` or \`remove\` specific ids.
|
|
4770
|
+
|
|
4771
|
+
### When to search first
|
|
4772
|
+
- User: "lembra-te / remember / last time / o que combin\xE1mos / qual era o comando".
|
|
4773
|
+
- You are about to edit, run tests, or refactor using **assumptions** that came from earlier in this project (stack, scripts, env vars, URLs).
|
|
4774
|
+
- You return to a task after many unrelated turns\u2014the chat may have been compressed; **memory on disk still holds** the durable notes if you saved them.
|
|
4557
4775
|
|
|
4558
|
-
###
|
|
4559
|
-
-
|
|
4560
|
-
-
|
|
4776
|
+
### When to add
|
|
4777
|
+
- **Stable** facts: architecture, naming conventions, test commands, ports, API bases, repo layout, user preferences that repeat.
|
|
4778
|
+
- **Pointers**, not novels: one short \`note\` + \`tags\` (e.g. \`auth\`, \`deploy\`, \`bluma\`). Put long specs in the repo; here only **reminders**.
|
|
4561
4779
|
|
|
4562
|
-
###
|
|
4563
|
-
-
|
|
4564
|
-
-
|
|
4780
|
+
### CRUD (tool actions)
|
|
4781
|
+
- **Create:** \`add\` + \`note\` (+ optional \`tags\`).
|
|
4782
|
+
- **Read:** \`list\` (all ids) or \`search\` + \`query\`.
|
|
4783
|
+
- **Update:** \`update\` + \`id\` + new \`note\` and/or \`tags\` (omit fields you leave unchanged).
|
|
4784
|
+
- **Delete:** \`remove\` + \`id\` only \u2014 **never** bulk-wipe; the product intentionally forbids it.
|
|
4785
|
+
|
|
4786
|
+
### When something changes
|
|
4787
|
+
- Prefer \`update\` on the same \`id\` when correcting a note; add a **new** note if the old one should remain as history; \`remove\` obsolete ids.
|
|
4565
4788
|
|
|
4566
4789
|
### Habits (continuity)
|
|
4567
|
-
- Prefer **search** or **list** over guessing
|
|
4568
|
-
-
|
|
4790
|
+
- Prefer **search** or **list** over guessing whenever "memory" matters.
|
|
4791
|
+
- After important milestones (feature done, bug fixed, migration applied), consider a **brief add** so future-you in a new session is not blind.
|
|
4569
4792
|
</coding_memory>
|
|
4570
4793
|
|
|
4571
4794
|
---
|
|
@@ -4601,6 +4824,7 @@ Run tests when modifying code. If a testing skill is listed in available_skills,
|
|
|
4601
4824
|
- **ALWAYS read a file before editing** - Use read_file_lines or ls_tool first
|
|
4602
4825
|
- **Use absolute paths** when possible to avoid ambiguity
|
|
4603
4826
|
- **For edit_tool**: Provide exact content with correct whitespace (read first!)
|
|
4827
|
+
- **Truncated CLI preview** (user may press Ctrl+O for more lines): still not a substitute for \`read_file_lines\` \u2014 use the tool for authoritative content before editing
|
|
4604
4828
|
- **Check file exists** before attempting edits
|
|
4605
4829
|
|
|
4606
4830
|
### Safe Auto-Approved Tools (no confirmation needed):
|
|
@@ -5007,7 +5231,7 @@ tools:
|
|
|
5007
5231
|
|
|
5008
5232
|
2. READ FRONTMATTER FIRST
|
|
5009
5233
|
- name: npm-publish
|
|
5010
|
-
- depends_on: [git-
|
|
5234
|
+
- depends_on: [git-commit]
|
|
5011
5235
|
- tools.required: [shell_command, command_status]
|
|
5012
5236
|
- tools.recommended: [read_file_lines, message]
|
|
5013
5237
|
|
|
@@ -5044,17 +5268,17 @@ User: "Publish the package"
|
|
|
5044
5268
|
2. load_skill({ skill_name: "npm-publish" })
|
|
5045
5269
|
|
|
5046
5270
|
3. Read frontmatter:
|
|
5047
|
-
- depends_on: [git-
|
|
5271
|
+
- depends_on: [git-commit]
|
|
5048
5272
|
- tools.required: [shell_command, command_status]
|
|
5049
5273
|
|
|
5050
5274
|
4. Read body -> Workflow says:
|
|
5051
|
-
"Step 1: If uncommitted changes, delegate to git-
|
|
5275
|
+
"Step 1: If uncommitted changes, delegate to git-commit"
|
|
5052
5276
|
|
|
5053
5277
|
5. Check git status with shell_command (required tool)
|
|
5054
5278
|
Found changes
|
|
5055
5279
|
|
|
5056
|
-
6. Delegate: load_skill({ skill_name: "git-
|
|
5057
|
-
- Read git-
|
|
5280
|
+
6. Delegate: load_skill({ skill_name: "git-commit" })
|
|
5281
|
+
- Read git-commit frontmatter
|
|
5058
5282
|
- Follow its workflow for commit
|
|
5059
5283
|
- Commit done
|
|
5060
5284
|
|
|
@@ -5080,7 +5304,7 @@ User: "Publish the package"
|
|
|
5080
5304
|
<coding_memory_snapshot>
|
|
5081
5305
|
## Persistent notes (loaded at session start from disk)
|
|
5082
5306
|
|
|
5083
|
-
${memorySnapshot.trim().length > 0 ? memorySnapshot : "(No entries yet. Use coding_memory
|
|
5307
|
+
${memorySnapshot.trim().length > 0 ? memorySnapshot : "(No entries yet. Use coding_memory: add, list, search \u2014 remove/update by id when needed.)"}
|
|
5084
5308
|
</coding_memory_snapshot>
|
|
5085
5309
|
`;
|
|
5086
5310
|
return prompt;
|
|
@@ -5094,6 +5318,161 @@ function isGitRepo(dir) {
|
|
|
5094
5318
|
}
|
|
5095
5319
|
}
|
|
5096
5320
|
|
|
5321
|
+
// src/app/agent/core/context-api/token_counter.ts
|
|
5322
|
+
import { getEncoding } from "js-tiktoken";
|
|
5323
|
+
var MESSAGE_OVERHEAD_TOKENS = 4;
|
|
5324
|
+
var CONVERSATION_BASE_OVERHEAD = 3;
|
|
5325
|
+
var cachedEncoding = null;
|
|
5326
|
+
function getO200kEncoding() {
|
|
5327
|
+
if (!cachedEncoding) {
|
|
5328
|
+
cachedEncoding = getEncoding("o200k_base");
|
|
5329
|
+
}
|
|
5330
|
+
return cachedEncoding;
|
|
5331
|
+
}
|
|
5332
|
+
function messageBodyForTokens(msg) {
|
|
5333
|
+
const c = msg.content;
|
|
5334
|
+
if (c == null) {
|
|
5335
|
+
return "";
|
|
5336
|
+
}
|
|
5337
|
+
if (typeof c === "string") {
|
|
5338
|
+
return c;
|
|
5339
|
+
}
|
|
5340
|
+
return JSON.stringify(c);
|
|
5341
|
+
}
|
|
5342
|
+
function messageExtraForTokens(msg) {
|
|
5343
|
+
const m = msg;
|
|
5344
|
+
const parts = [String(m.role ?? "")];
|
|
5345
|
+
if (Array.isArray(m.tool_calls)) {
|
|
5346
|
+
parts.push(JSON.stringify(m.tool_calls));
|
|
5347
|
+
}
|
|
5348
|
+
if (typeof m.tool_call_id === "string") {
|
|
5349
|
+
parts.push(m.tool_call_id);
|
|
5350
|
+
}
|
|
5351
|
+
if (typeof m.name === "string") {
|
|
5352
|
+
parts.push(m.name);
|
|
5353
|
+
}
|
|
5354
|
+
return parts.join("\0");
|
|
5355
|
+
}
|
|
5356
|
+
function countTokens(messages) {
|
|
5357
|
+
if (messages.length === 0) {
|
|
5358
|
+
return CONVERSATION_BASE_OVERHEAD;
|
|
5359
|
+
}
|
|
5360
|
+
const enc = getO200kEncoding();
|
|
5361
|
+
let total = CONVERSATION_BASE_OVERHEAD;
|
|
5362
|
+
for (const msg of messages) {
|
|
5363
|
+
const body = messageBodyForTokens(msg);
|
|
5364
|
+
const extra = messageExtraForTokens(msg);
|
|
5365
|
+
const nBody = body ? enc.encode(body).length : 0;
|
|
5366
|
+
const nExtra = extra ? enc.encode(extra).length : 0;
|
|
5367
|
+
total += nBody + nExtra + MESSAGE_OVERHEAD_TOKENS;
|
|
5368
|
+
}
|
|
5369
|
+
return total;
|
|
5370
|
+
}
|
|
5371
|
+
|
|
5372
|
+
// src/app/agent/core/context-api/history_anchor.ts
|
|
5373
|
+
function stripJsonFence(text) {
|
|
5374
|
+
let s = text.trim();
|
|
5375
|
+
const fence = /^```(?:json)?\s*([\s\S]*?)```\s*$/im.exec(s);
|
|
5376
|
+
if (fence) {
|
|
5377
|
+
s = fence[1].trim();
|
|
5378
|
+
}
|
|
5379
|
+
return s;
|
|
5380
|
+
}
|
|
5381
|
+
function parseAnchorJson(raw) {
|
|
5382
|
+
const cleaned = stripJsonFence(raw);
|
|
5383
|
+
const start = cleaned.indexOf("{");
|
|
5384
|
+
const end = cleaned.lastIndexOf("}");
|
|
5385
|
+
if (start === -1 || end === -1 || end <= start) {
|
|
5386
|
+
throw new Error("compressToAnchor: resposta sem JSON object");
|
|
5387
|
+
}
|
|
5388
|
+
const parsed = JSON.parse(cleaned.slice(start, end + 1));
|
|
5389
|
+
return {
|
|
5390
|
+
intent: String(parsed.intent ?? ""),
|
|
5391
|
+
filesModified: Array.isArray(parsed.filesModified) ? parsed.filesModified.map(String) : [],
|
|
5392
|
+
decisionsMade: Array.isArray(parsed.decisionsMade) ? parsed.decisionsMade.map(String) : [],
|
|
5393
|
+
errorsEncountered: Array.isArray(parsed.errorsEncountered) ? parsed.errorsEncountered.map(String) : [],
|
|
5394
|
+
currentState: String(parsed.currentState ?? ""),
|
|
5395
|
+
nextSteps: String(parsed.nextSteps ?? ""),
|
|
5396
|
+
compressedAt: typeof parsed.compressedAt === "number" ? parsed.compressedAt : Date.now(),
|
|
5397
|
+
turnsCompressed: typeof parsed.turnsCompressed === "number" ? parsed.turnsCompressed : 0
|
|
5398
|
+
};
|
|
5399
|
+
}
|
|
5400
|
+
function formatMessagesForPrompt(msgs) {
|
|
5401
|
+
return msgs.map((m, i) => {
|
|
5402
|
+
const role = m.role ?? "?";
|
|
5403
|
+
const content = m.content;
|
|
5404
|
+
const text = typeof content === "string" ? content : content == null ? "" : JSON.stringify(content);
|
|
5405
|
+
const toolCalls = m.tool_calls;
|
|
5406
|
+
const tail = toolCalls ? `
|
|
5407
|
+
[tool_calls]: ${JSON.stringify(toolCalls)}` : "";
|
|
5408
|
+
return `--- msg ${i + 1} (${role}) ---
|
|
5409
|
+
${text.slice(0, 12e4)}${tail}`;
|
|
5410
|
+
}).join("\n\n");
|
|
5411
|
+
}
|
|
5412
|
+
async function compressToAnchor(spansToCompress, existingAnchor, llmService, userContext, turnSlicesInBatch) {
|
|
5413
|
+
const messagesBlock = formatMessagesForPrompt(spansToCompress);
|
|
5414
|
+
const existingBlock = existingAnchor ? `ANCHOR EXISTENTE (estende este, n\xE3o substitui \u2014 merge sem perder informa\xE7\xE3o):
|
|
5415
|
+
${JSON.stringify(existingAnchor, null, 2)}` : "N\xE3o existe anchor anterior.";
|
|
5416
|
+
const userPrompt = `Tu \xE9s um compressor de hist\xF3rico para um agente de c\xF3digo CLI.
|
|
5417
|
+
|
|
5418
|
+
${existingBlock}
|
|
5419
|
+
|
|
5420
|
+
MENSAGENS A COMPRIMIR (turnos antigos da conversa):
|
|
5421
|
+
${messagesBlock}
|
|
5422
|
+
|
|
5423
|
+
Produz um JSON com esta estrutura exata:
|
|
5424
|
+
{
|
|
5425
|
+
"intent": "objetivo principal da sess\xE3o",
|
|
5426
|
+
"filesModified": ["path1", "path2"],
|
|
5427
|
+
"decisionsMade": ["decis\xE3o 1", "decis\xE3o 2"],
|
|
5428
|
+
"errorsEncountered": ["erro X \u2192 resolvido com Y"],
|
|
5429
|
+
"currentState": "onde estamos agora em 2-3 frases",
|
|
5430
|
+
"nextSteps": "o que est\xE1 pendente",
|
|
5431
|
+
"compressedAt": ${Date.now()},
|
|
5432
|
+
"turnsCompressed": 0
|
|
5433
|
+
}
|
|
5434
|
+
|
|
5435
|
+
Regras:
|
|
5436
|
+
- Responde APENAS com JSON v\xE1lido, sem markdown, sem texto extra
|
|
5437
|
+
- filesModified: inclui TODOS os paths de ficheiros mencionados
|
|
5438
|
+
- decisionsMade: preserva decis\xF5es de arquitetura, abordagem, estrutura
|
|
5439
|
+
- errorsEncountered: formato "erro \u2192 solu\xE7\xE3o"
|
|
5440
|
+
- Se j\xE1 existe anchor, faz merge \u2014 n\xE3o percas informa\xE7\xE3o anterior
|
|
5441
|
+
- O campo turnsCompressed na resposta ser\xE1 ignorado; usa 0.`;
|
|
5442
|
+
const resp = await llmService.chatCompletion({
|
|
5443
|
+
messages: [
|
|
5444
|
+
{
|
|
5445
|
+
role: "system",
|
|
5446
|
+
content: "\xC9s um extrator factual. Sa\xEDda: apenas um objeto JSON v\xE1lido, sem markdown."
|
|
5447
|
+
},
|
|
5448
|
+
{ role: "user", content: userPrompt }
|
|
5449
|
+
],
|
|
5450
|
+
temperature: 0,
|
|
5451
|
+
max_tokens: 4096,
|
|
5452
|
+
userContext
|
|
5453
|
+
});
|
|
5454
|
+
const text = resp.choices[0]?.message?.content;
|
|
5455
|
+
if (typeof text !== "string" || !text.trim()) {
|
|
5456
|
+
throw new Error("compressToAnchor: modelo n\xE3o devolveu conte\xFAdo textual");
|
|
5457
|
+
}
|
|
5458
|
+
const anchor = parseAnchorJson(text);
|
|
5459
|
+
const prevTurns = existingAnchor?.turnsCompressed ?? 0;
|
|
5460
|
+
anchor.turnsCompressed = prevTurns + Math.max(0, turnSlicesInBatch);
|
|
5461
|
+
anchor.compressedAt = Date.now();
|
|
5462
|
+
return anchor;
|
|
5463
|
+
}
|
|
5464
|
+
function anchorToSystemMessage(anchor) {
|
|
5465
|
+
const date = new Date(anchor.compressedAt).toISOString();
|
|
5466
|
+
const content = `[MEM\xD3RIA DE SESS\xC3O \u2014 ${anchor.turnsCompressed} turnos comprimidos em ${date}]
|
|
5467
|
+
Objetivo: ${anchor.intent}
|
|
5468
|
+
Ficheiros modificados: ${anchor.filesModified.join(", ") || "(nenhum)"}
|
|
5469
|
+
Decis\xF5es tomadas: ${anchor.decisionsMade.join(" | ") || "(nenhuma)"}
|
|
5470
|
+
Erros resolvidos: ${anchor.errorsEncountered.join(" | ") || "(nenhum)"}
|
|
5471
|
+
Estado atual: ${anchor.currentState}
|
|
5472
|
+
Pr\xF3ximos passos: ${anchor.nextSteps}`;
|
|
5473
|
+
return { role: "system", content };
|
|
5474
|
+
}
|
|
5475
|
+
|
|
5097
5476
|
// src/app/agent/core/context-api/context_manager.ts
|
|
5098
5477
|
function isEndTurnToolCall(tc) {
|
|
5099
5478
|
if (tc.function.name === "agent_end_turn") {
|
|
@@ -5109,40 +5488,26 @@ function isEndTurnToolCall(tc) {
|
|
|
5109
5488
|
}
|
|
5110
5489
|
return false;
|
|
5111
5490
|
}
|
|
5112
|
-
function
|
|
5113
|
-
if (!fullHistory.length) {
|
|
5114
|
-
return [];
|
|
5115
|
-
}
|
|
5116
|
-
if (maxTurns === null || maxTurns === void 0) {
|
|
5117
|
-
return [...fullHistory];
|
|
5118
|
-
}
|
|
5119
|
-
const systemMessages = [];
|
|
5120
|
-
let historyStartIndex = 0;
|
|
5121
|
-
while (historyStartIndex < fullHistory.length && fullHistory[historyStartIndex].role === "system") {
|
|
5122
|
-
systemMessages.push(fullHistory[historyStartIndex]);
|
|
5123
|
-
historyStartIndex++;
|
|
5124
|
-
}
|
|
5125
|
-
const conversationHistory = fullHistory.slice(historyStartIndex);
|
|
5491
|
+
function partitionConversationIntoTurnSlices(conversationHistory) {
|
|
5126
5492
|
const turns = [];
|
|
5127
5493
|
let currentTurn = [];
|
|
5128
|
-
let turnsFound = 0;
|
|
5129
5494
|
const isDevOverlay = (m) => m?.role === "user" && m?.name === "user_overlay";
|
|
5130
5495
|
for (let i = conversationHistory.length - 1; i >= 0; i--) {
|
|
5131
5496
|
const msg = conversationHistory[i];
|
|
5132
5497
|
currentTurn.unshift(msg);
|
|
5133
|
-
const endsWithAgentEnd = msg.role === "assistant" && msg.tool_calls?.some(
|
|
5498
|
+
const endsWithAgentEnd = msg.role === "assistant" && msg.tool_calls?.some(
|
|
5499
|
+
(tc) => isEndTurnToolCall(tc)
|
|
5500
|
+
);
|
|
5134
5501
|
if (endsWithAgentEnd) {
|
|
5135
5502
|
turns.unshift([...currentTurn]);
|
|
5136
5503
|
currentTurn = [];
|
|
5137
|
-
turnsFound++;
|
|
5138
|
-
if (turnsFound >= maxTurns) {
|
|
5139
|
-
break;
|
|
5140
|
-
}
|
|
5141
5504
|
continue;
|
|
5142
5505
|
}
|
|
5143
5506
|
const prev = conversationHistory[i - 1];
|
|
5144
5507
|
if (msg.role === "user" && !isDevOverlay(msg)) {
|
|
5145
|
-
if (prev && prev.role === "assistant" && !prev.tool_calls?.some(
|
|
5508
|
+
if (prev && prev.role === "assistant" && !prev.tool_calls?.some(
|
|
5509
|
+
(tc) => isEndTurnToolCall(tc)
|
|
5510
|
+
)) {
|
|
5146
5511
|
const hasNonOverlay = currentTurn.some((m) => m.role !== "user" || !isDevOverlay(m));
|
|
5147
5512
|
if (hasNonOverlay) {
|
|
5148
5513
|
turns.unshift([...currentTurn]);
|
|
@@ -5154,8 +5519,76 @@ function createApiContextWindow(fullHistory, maxTurns) {
|
|
|
5154
5519
|
if (currentTurn.length > 0) {
|
|
5155
5520
|
turns.unshift(currentTurn);
|
|
5156
5521
|
}
|
|
5157
|
-
|
|
5158
|
-
|
|
5522
|
+
return turns;
|
|
5523
|
+
}
|
|
5524
|
+
var DEFAULT_TOKEN_BUDGET = 6e4;
|
|
5525
|
+
var DEFAULT_COMPRESS_THRESHOLD = 0.7;
|
|
5526
|
+
var DEFAULT_KEEP_RECENT_TURNS = 8;
|
|
5527
|
+
function readContextOptionInt(envKey, fallback) {
|
|
5528
|
+
const raw = (process.env[envKey] ?? "").trim();
|
|
5529
|
+
if (!raw) return fallback;
|
|
5530
|
+
const n = Number(raw);
|
|
5531
|
+
return Number.isFinite(n) && n > 0 ? Math.floor(n) : fallback;
|
|
5532
|
+
}
|
|
5533
|
+
function readContextOptionFloat(envKey, fallback) {
|
|
5534
|
+
const raw = (process.env[envKey] ?? "").trim();
|
|
5535
|
+
if (!raw) return fallback;
|
|
5536
|
+
const n = Number(raw);
|
|
5537
|
+
return Number.isFinite(n) && n > 0 && n <= 1 ? n : fallback;
|
|
5538
|
+
}
|
|
5539
|
+
function buildContextMessages(systemMessages, anchor, pendingRaw, recentFlat) {
|
|
5540
|
+
const anchorMsg = anchor ? [anchorToSystemMessage(anchor)] : [];
|
|
5541
|
+
return [...systemMessages, ...anchorMsg, ...pendingRaw, ...recentFlat];
|
|
5542
|
+
}
|
|
5543
|
+
async function createApiContextWindow(fullHistory, currentAnchor, compressedTurnSliceCount, llmService, userContext, options) {
|
|
5544
|
+
if (!fullHistory.length) {
|
|
5545
|
+
return {
|
|
5546
|
+
messages: [],
|
|
5547
|
+
newAnchor: currentAnchor,
|
|
5548
|
+
newCompressedTurnSliceCount: compressedTurnSliceCount
|
|
5549
|
+
};
|
|
5550
|
+
}
|
|
5551
|
+
const tokenBudget = options?.tokenBudget ?? readContextOptionInt("BLUMA_CONTEXT_TOKEN_BUDGET", DEFAULT_TOKEN_BUDGET);
|
|
5552
|
+
const compressThreshold = options?.compressThreshold ?? readContextOptionFloat("BLUMA_COMPRESS_THRESHOLD", DEFAULT_COMPRESS_THRESHOLD);
|
|
5553
|
+
const keepRecentTurns = options?.keepRecentTurns ?? readContextOptionInt("BLUMA_KEEP_RECENT_TURNS", DEFAULT_KEEP_RECENT_TURNS);
|
|
5554
|
+
const systemMessages = [];
|
|
5555
|
+
let historyStartIndex = 0;
|
|
5556
|
+
while (historyStartIndex < fullHistory.length && fullHistory[historyStartIndex].role === "system") {
|
|
5557
|
+
systemMessages.push(fullHistory[historyStartIndex]);
|
|
5558
|
+
historyStartIndex++;
|
|
5559
|
+
}
|
|
5560
|
+
const conversationHistory = fullHistory.slice(historyStartIndex);
|
|
5561
|
+
const turnSlices = partitionConversationIntoTurnSlices(conversationHistory);
|
|
5562
|
+
const n = turnSlices.length;
|
|
5563
|
+
const recentStart = Math.max(0, n - keepRecentTurns);
|
|
5564
|
+
let sliceCount = Math.min(Math.max(0, compressedTurnSliceCount), recentStart);
|
|
5565
|
+
let anchor = currentAnchor;
|
|
5566
|
+
const recentSlices = turnSlices.slice(recentStart);
|
|
5567
|
+
const recentFlat = recentSlices.flat();
|
|
5568
|
+
const thresholdTokens = tokenBudget * compressThreshold;
|
|
5569
|
+
let pendingSlices = turnSlices.slice(sliceCount, recentStart);
|
|
5570
|
+
let pendingFlat = pendingSlices.flat();
|
|
5571
|
+
let messages = buildContextMessages(systemMessages, anchor, pendingFlat, recentFlat);
|
|
5572
|
+
let tokens = countTokens(messages);
|
|
5573
|
+
while (tokens >= thresholdTokens && pendingSlices.length > 0) {
|
|
5574
|
+
anchor = await compressToAnchor(
|
|
5575
|
+
pendingFlat,
|
|
5576
|
+
anchor,
|
|
5577
|
+
llmService,
|
|
5578
|
+
userContext,
|
|
5579
|
+
pendingSlices.length
|
|
5580
|
+
);
|
|
5581
|
+
sliceCount = recentStart;
|
|
5582
|
+
pendingSlices = [];
|
|
5583
|
+
pendingFlat = [];
|
|
5584
|
+
messages = buildContextMessages(systemMessages, anchor, pendingFlat, recentFlat);
|
|
5585
|
+
tokens = countTokens(messages);
|
|
5586
|
+
}
|
|
5587
|
+
return {
|
|
5588
|
+
messages,
|
|
5589
|
+
newAnchor: anchor,
|
|
5590
|
+
newCompressedTurnSliceCount: sliceCount
|
|
5591
|
+
};
|
|
5159
5592
|
}
|
|
5160
5593
|
|
|
5161
5594
|
// src/app/agent/core/llm/llm.ts
|
|
@@ -5538,7 +5971,9 @@ var BluMaAgent = class {
|
|
|
5538
5971
|
mcpClient;
|
|
5539
5972
|
feedbackSystem;
|
|
5540
5973
|
skillLoader;
|
|
5541
|
-
|
|
5974
|
+
/** Memória comprimida persistida (turnos antigos) + cursor de fatias já absorvidas. */
|
|
5975
|
+
sessionAnchor = null;
|
|
5976
|
+
compressedTurnSliceCount = 0;
|
|
5542
5977
|
isInterrupted = false;
|
|
5543
5978
|
/** Mesmo turnId durante processTurn + todo o loop de tool_calls (FactorRouter). */
|
|
5544
5979
|
activeTurnContext = null;
|
|
@@ -5562,50 +5997,74 @@ var BluMaAgent = class {
|
|
|
5562
5997
|
this.eventBus.emit("backend_message", { type: "user_overlay", payload: clean, ts: data.ts || Date.now() });
|
|
5563
5998
|
try {
|
|
5564
5999
|
if (this.sessionFile) {
|
|
5565
|
-
|
|
6000
|
+
this.persistSession();
|
|
5566
6001
|
} else {
|
|
5567
|
-
const [sessionFile,
|
|
6002
|
+
const [sessionFile, , mem] = await loadOrcreateSession(this.sessionId);
|
|
5568
6003
|
this.sessionFile = sessionFile;
|
|
5569
|
-
|
|
6004
|
+
this.sessionAnchor = mem.historyAnchor;
|
|
6005
|
+
this.compressedTurnSliceCount = mem.compressedTurnSliceCount;
|
|
6006
|
+
this.persistSession();
|
|
5570
6007
|
}
|
|
5571
6008
|
} catch (e) {
|
|
5572
6009
|
this.eventBus.emit("backend_message", { type: "error", message: `Falha ao salvar hist\xF3rico ap\xF3s user_overlay: ${e.message}` });
|
|
5573
6010
|
}
|
|
5574
6011
|
});
|
|
5575
6012
|
}
|
|
6013
|
+
getMemorySnapshot() {
|
|
6014
|
+
return {
|
|
6015
|
+
historyAnchor: this.sessionAnchor,
|
|
6016
|
+
compressedTurnSliceCount: this.compressedTurnSliceCount
|
|
6017
|
+
};
|
|
6018
|
+
}
|
|
6019
|
+
/** Debounced: grava histórico + estado de compressão no mesmo ficheiro de sessão. */
|
|
6020
|
+
persistSession() {
|
|
6021
|
+
if (!this.sessionFile) return;
|
|
6022
|
+
void saveSessionHistory(this.sessionFile, this.history, this.getMemorySnapshot());
|
|
6023
|
+
}
|
|
5576
6024
|
async initialize() {
|
|
5577
6025
|
await this.mcpClient.nativeToolInvoker.initialize();
|
|
5578
6026
|
await this.mcpClient.initialize();
|
|
5579
|
-
const [sessionFile, history] = await loadOrcreateSession(this.sessionId);
|
|
6027
|
+
const [sessionFile, history, mem] = await loadOrcreateSession(this.sessionId);
|
|
5580
6028
|
this.sessionFile = sessionFile;
|
|
5581
6029
|
this.history = history;
|
|
6030
|
+
this.sessionAnchor = mem.historyAnchor;
|
|
6031
|
+
this.compressedTurnSliceCount = mem.compressedTurnSliceCount;
|
|
5582
6032
|
initializeSkillContext({
|
|
5583
6033
|
history: this.history,
|
|
5584
6034
|
skillLoader: this.skillLoader
|
|
5585
6035
|
});
|
|
5586
|
-
|
|
5587
|
-
|
|
5588
|
-
|
|
5589
|
-
|
|
5590
|
-
|
|
5591
|
-
|
|
5592
|
-
|
|
5593
|
-
|
|
5594
|
-
|
|
5595
|
-
|
|
5596
|
-
|
|
5597
|
-
|
|
5598
|
-
|
|
5599
|
-
|
|
5600
|
-
|
|
5601
|
-
|
|
5602
|
-
});
|
|
5603
|
-
}
|
|
6036
|
+
const dirs = this.skillLoader.getSkillsDirs();
|
|
6037
|
+
this.eventBus.emit("backend_message", {
|
|
6038
|
+
type: "info",
|
|
6039
|
+
message: `Skills dirs \u2014 bundled: ${dirs.bundled} | project: ${dirs.project} | global: ${dirs.global}`
|
|
6040
|
+
});
|
|
6041
|
+
const availableSkills = this.skillLoader.listAvailable();
|
|
6042
|
+
this.eventBus.emit("backend_message", {
|
|
6043
|
+
type: "info",
|
|
6044
|
+
message: `Skills loaded: ${availableSkills.length} \u2014 ${availableSkills.map((s) => `${s.name} (${s.source})`).join(", ") || "none"}`
|
|
6045
|
+
});
|
|
6046
|
+
if (this.skillLoader.hasConflicts()) {
|
|
6047
|
+
for (const warning of this.skillLoader.formatConflictWarnings()) {
|
|
6048
|
+
this.eventBus.emit("backend_message", {
|
|
6049
|
+
type: "warning",
|
|
6050
|
+
message: warning
|
|
6051
|
+
});
|
|
5604
6052
|
}
|
|
5605
|
-
|
|
6053
|
+
}
|
|
6054
|
+
const systemPrompt = getUnifiedSystemPrompt(availableSkills);
|
|
6055
|
+
if (this.history.length === 0) {
|
|
5606
6056
|
this.history.push({ role: "system", content: systemPrompt });
|
|
5607
|
-
|
|
6057
|
+
} else {
|
|
6058
|
+
const sysIdx = this.history.findIndex(
|
|
6059
|
+
(m) => m.role === "system" && typeof m.content === "string" && String(m.content).includes("<identity>")
|
|
6060
|
+
);
|
|
6061
|
+
if (sysIdx >= 0) {
|
|
6062
|
+
this.history[sysIdx] = { ...this.history[sysIdx], content: systemPrompt };
|
|
6063
|
+
} else {
|
|
6064
|
+
this.history.unshift({ role: "system", content: systemPrompt });
|
|
6065
|
+
}
|
|
5608
6066
|
}
|
|
6067
|
+
this.persistSession();
|
|
5609
6068
|
}
|
|
5610
6069
|
getAvailableTools() {
|
|
5611
6070
|
return this.mcpClient.getAvailableTools();
|
|
@@ -5634,11 +6093,13 @@ var BluMaAgent = class {
|
|
|
5634
6093
|
let toolResultContent;
|
|
5635
6094
|
let shouldContinueConversation = true;
|
|
5636
6095
|
if (!this.sessionFile) {
|
|
5637
|
-
const [sessionFile, history] = await loadOrcreateSession(this.sessionId);
|
|
6096
|
+
const [sessionFile, history, mem] = await loadOrcreateSession(this.sessionId);
|
|
5638
6097
|
this.sessionFile = sessionFile;
|
|
5639
6098
|
if (this.history.length === 0 && history.length > 0) {
|
|
5640
6099
|
this.history = history;
|
|
5641
6100
|
}
|
|
6101
|
+
this.sessionAnchor = mem.historyAnchor;
|
|
6102
|
+
this.compressedTurnSliceCount = mem.compressedTurnSliceCount;
|
|
5642
6103
|
}
|
|
5643
6104
|
if (decisionData.type === "user_decision_execute") {
|
|
5644
6105
|
const toolName = toolCall.function.name;
|
|
@@ -5660,7 +6121,7 @@ var BluMaAgent = class {
|
|
|
5660
6121
|
raw_arguments: toolCall.function.arguments
|
|
5661
6122
|
});
|
|
5662
6123
|
this.history.push({ role: "tool", tool_call_id: toolCall.id, content: toolResultContent });
|
|
5663
|
-
|
|
6124
|
+
this.persistSession();
|
|
5664
6125
|
await this._continueConversation();
|
|
5665
6126
|
return;
|
|
5666
6127
|
}
|
|
@@ -5672,7 +6133,7 @@ var BluMaAgent = class {
|
|
|
5672
6133
|
received: toolArgs
|
|
5673
6134
|
});
|
|
5674
6135
|
this.history.push({ role: "tool", tool_call_id: toolCall.id, content: toolResultContent });
|
|
5675
|
-
|
|
6136
|
+
this.persistSession();
|
|
5676
6137
|
await this._continueConversation();
|
|
5677
6138
|
return;
|
|
5678
6139
|
}
|
|
@@ -5683,7 +6144,7 @@ var BluMaAgent = class {
|
|
|
5683
6144
|
received: toolArgs
|
|
5684
6145
|
});
|
|
5685
6146
|
this.history.push({ role: "tool", tool_call_id: toolCall.id, content: toolResultContent });
|
|
5686
|
-
|
|
6147
|
+
this.persistSession();
|
|
5687
6148
|
await this._continueConversation();
|
|
5688
6149
|
return;
|
|
5689
6150
|
}
|
|
@@ -5753,7 +6214,7 @@ var BluMaAgent = class {
|
|
|
5753
6214
|
toolResultContent = "The system rejected this action. Verify that the command you are executing contributes to the tasks intent and try again.";
|
|
5754
6215
|
}
|
|
5755
6216
|
this.history.push({ role: "tool", tool_call_id: toolCall.id, content: toolResultContent });
|
|
5756
|
-
|
|
6217
|
+
this.persistSession();
|
|
5757
6218
|
if (shouldContinueConversation && !this.isInterrupted) {
|
|
5758
6219
|
await this._continueConversation();
|
|
5759
6220
|
}
|
|
@@ -5803,7 +6264,16 @@ ${editData.error.display}`;
|
|
|
5803
6264
|
this.eventBus.emit("backend_message", { type: "info", message: "Task Canceled." });
|
|
5804
6265
|
return;
|
|
5805
6266
|
}
|
|
5806
|
-
const contextWindow = createApiContextWindow(
|
|
6267
|
+
const { messages: contextWindow, newAnchor, newCompressedTurnSliceCount } = await createApiContextWindow(
|
|
6268
|
+
this.history,
|
|
6269
|
+
this.sessionAnchor,
|
|
6270
|
+
this.compressedTurnSliceCount,
|
|
6271
|
+
this.llm,
|
|
6272
|
+
this.getLlmUserContext()
|
|
6273
|
+
);
|
|
6274
|
+
this.sessionAnchor = newAnchor;
|
|
6275
|
+
this.compressedTurnSliceCount = newCompressedTurnSliceCount;
|
|
6276
|
+
this.persistSession();
|
|
5807
6277
|
const llmService = this.llm;
|
|
5808
6278
|
if (typeof llmService.chatCompletionStream === "function") {
|
|
5809
6279
|
await this._handleStreamingResponse(contextWindow);
|
|
@@ -5814,7 +6284,7 @@ ${editData.error.display}`;
|
|
|
5814
6284
|
const errorMessage = error instanceof Error ? error.message : "An unknown API error occurred.";
|
|
5815
6285
|
this.eventBus.emit("backend_message", { type: "error", message: errorMessage });
|
|
5816
6286
|
} finally {
|
|
5817
|
-
|
|
6287
|
+
this.persistSession();
|
|
5818
6288
|
}
|
|
5819
6289
|
}
|
|
5820
6290
|
async _handleStreamingResponse(contextWindow) {
|
|
@@ -6623,18 +7093,15 @@ var Agent = class {
|
|
|
6623
7093
|
|
|
6624
7094
|
// src/app/ui/WorkingTimer.tsx
|
|
6625
7095
|
import { useState as useState4, useEffect as useEffect4, memo as memo5 } from "react";
|
|
6626
|
-
import { Box as
|
|
6627
|
-
import { jsx as
|
|
7096
|
+
import { Box as Box8, Text as Text8 } from "ink";
|
|
7097
|
+
import { jsx as jsx8, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
6628
7098
|
var WorkingTimerComponent = ({ eventBus, taskName, taskStatus }) => {
|
|
6629
|
-
const [currentAction, setCurrentAction] = useState4("
|
|
7099
|
+
const [currentAction, setCurrentAction] = useState4("working");
|
|
6630
7100
|
const [shinePosition, setShinePosition] = useState4(0);
|
|
6631
|
-
const [dots, setDots] = useState4("");
|
|
6632
7101
|
useEffect4(() => {
|
|
6633
7102
|
if (!eventBus) return;
|
|
6634
7103
|
const handleActionStatus = (data) => {
|
|
6635
|
-
if (data.action)
|
|
6636
|
-
setCurrentAction(data.action);
|
|
6637
|
-
}
|
|
7104
|
+
if (data.action) setCurrentAction(data.action);
|
|
6638
7105
|
};
|
|
6639
7106
|
eventBus.on("action_status", handleActionStatus);
|
|
6640
7107
|
return () => {
|
|
@@ -6647,12 +7114,6 @@ var WorkingTimerComponent = ({ eventBus, taskName, taskStatus }) => {
|
|
|
6647
7114
|
}, 120);
|
|
6648
7115
|
return () => clearInterval(shineTimer);
|
|
6649
7116
|
}, []);
|
|
6650
|
-
useEffect4(() => {
|
|
6651
|
-
const dotsTimer = setInterval(() => {
|
|
6652
|
-
setDots((prev) => prev.length >= 3 ? "" : prev + ".");
|
|
6653
|
-
}, 500);
|
|
6654
|
-
return () => clearInterval(dotsTimer);
|
|
6655
|
-
}, []);
|
|
6656
7117
|
const displayAction = taskStatus || currentAction;
|
|
6657
7118
|
const renderShineText = (text) => {
|
|
6658
7119
|
const chars = text.split("");
|
|
@@ -6661,29 +7122,28 @@ var WorkingTimerComponent = ({ eventBus, taskName, taskStatus }) => {
|
|
|
6661
7122
|
return chars.map((char, i) => {
|
|
6662
7123
|
const distance = Math.abs(i - shineIdx);
|
|
6663
7124
|
if (distance <= 1) {
|
|
6664
|
-
return /* @__PURE__ */
|
|
6665
|
-
} else {
|
|
6666
|
-
return /* @__PURE__ */ jsx7(Text7, { color: "gray", dimColor: true, children: char }, i);
|
|
7125
|
+
return /* @__PURE__ */ jsx8(Text8, { color: BLUMA_TERMINAL.brandMagenta, children: char }, i);
|
|
6667
7126
|
}
|
|
7127
|
+
return /* @__PURE__ */ jsx8(Text8, { dimColor: true, children: char }, i);
|
|
6668
7128
|
});
|
|
6669
7129
|
};
|
|
6670
|
-
return /* @__PURE__ */
|
|
6671
|
-
/* @__PURE__ */
|
|
6672
|
-
taskName
|
|
6673
|
-
"\
|
|
7130
|
+
return /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", marginBottom: 1, children: [
|
|
7131
|
+
/* @__PURE__ */ jsx8(M3StatusStrip, { children: renderShineText(displayAction) }),
|
|
7132
|
+
taskName ? /* @__PURE__ */ jsx8(Box8, { paddingLeft: 2, children: /* @__PURE__ */ jsxs8(Text8, { dimColor: true, children: [
|
|
7133
|
+
/* @__PURE__ */ jsx8(Text8, { color: BLUMA_TERMINAL.brandBlue, children: "\u2514 " }),
|
|
6674
7134
|
taskName
|
|
6675
|
-
] }) })
|
|
7135
|
+
] }) }) : null
|
|
6676
7136
|
] });
|
|
6677
7137
|
};
|
|
6678
7138
|
var WorkingTimer = memo5(WorkingTimerComponent);
|
|
6679
7139
|
|
|
6680
7140
|
// src/app/ui/components/ToolCallDisplay.tsx
|
|
6681
7141
|
import { memo as memo6 } from "react";
|
|
6682
|
-
import { Box as
|
|
7142
|
+
import { Box as Box10 } from "ink";
|
|
6683
7143
|
|
|
6684
7144
|
// src/app/ui/components/toolCallRenderers.tsx
|
|
6685
|
-
import { Box as
|
|
6686
|
-
import { jsx as
|
|
7145
|
+
import { Box as Box9, Text as Text9 } from "ink";
|
|
7146
|
+
import { jsx as jsx9, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
6687
7147
|
var parseArgs = (args) => {
|
|
6688
7148
|
if (typeof args === "string") {
|
|
6689
7149
|
try {
|
|
@@ -6705,9 +7165,9 @@ var getBasename = (filepath) => {
|
|
|
6705
7165
|
var renderShellCommand2 = ({ args }) => {
|
|
6706
7166
|
const parsed = parseArgs(args);
|
|
6707
7167
|
const command = parsed.command || "[no command]";
|
|
6708
|
-
return /* @__PURE__ */
|
|
6709
|
-
/* @__PURE__ */
|
|
6710
|
-
/* @__PURE__ */
|
|
7168
|
+
return /* @__PURE__ */ jsxs9(Box9, { children: [
|
|
7169
|
+
/* @__PURE__ */ jsx9(Text9, { color: BLUMA_TERMINAL.brandBlue, bold: true, children: "$" }),
|
|
7170
|
+
/* @__PURE__ */ jsxs9(Text9, { children: [
|
|
6711
7171
|
" ",
|
|
6712
7172
|
truncate(command, 70)
|
|
6713
7173
|
] })
|
|
@@ -6716,9 +7176,9 @@ var renderShellCommand2 = ({ args }) => {
|
|
|
6716
7176
|
var renderLsTool2 = ({ args }) => {
|
|
6717
7177
|
const parsed = parseArgs(args);
|
|
6718
7178
|
const path19 = parsed.directory_path || ".";
|
|
6719
|
-
return /* @__PURE__ */
|
|
6720
|
-
/* @__PURE__ */
|
|
6721
|
-
/* @__PURE__ */
|
|
7179
|
+
return /* @__PURE__ */ jsxs9(Box9, { children: [
|
|
7180
|
+
/* @__PURE__ */ jsx9(Text9, { color: BLUMA_TERMINAL.brandBlue, bold: true, children: "ls" }),
|
|
7181
|
+
/* @__PURE__ */ jsxs9(Text9, { dimColor: true, children: [
|
|
6722
7182
|
" ",
|
|
6723
7183
|
path19
|
|
6724
7184
|
] })
|
|
@@ -6727,9 +7187,9 @@ var renderLsTool2 = ({ args }) => {
|
|
|
6727
7187
|
var renderCountFilesLines = ({ args }) => {
|
|
6728
7188
|
const parsed = parseArgs(args);
|
|
6729
7189
|
const filepath = parsed.filepath || "[no file]";
|
|
6730
|
-
return /* @__PURE__ */
|
|
6731
|
-
/* @__PURE__ */
|
|
6732
|
-
/* @__PURE__ */
|
|
7190
|
+
return /* @__PURE__ */ jsxs9(Box9, { children: [
|
|
7191
|
+
/* @__PURE__ */ jsx9(Text9, { color: BLUMA_TERMINAL.brandBlue, bold: true, children: "wc -l" }),
|
|
7192
|
+
/* @__PURE__ */ jsxs9(Text9, { dimColor: true, children: [
|
|
6733
7193
|
" ",
|
|
6734
7194
|
getBasename(filepath)
|
|
6735
7195
|
] })
|
|
@@ -6740,14 +7200,15 @@ var renderReadFileLines2 = ({ args }) => {
|
|
|
6740
7200
|
const filepath = parsed.filepath || "[no file]";
|
|
6741
7201
|
const start = parsed.start_line || 1;
|
|
6742
7202
|
const end = parsed.end_line || start;
|
|
6743
|
-
return /* @__PURE__ */
|
|
6744
|
-
/* @__PURE__ */
|
|
6745
|
-
/* @__PURE__ */
|
|
7203
|
+
return /* @__PURE__ */ jsxs9(Box9, { children: [
|
|
7204
|
+
/* @__PURE__ */ jsx9(Text9, { color: BLUMA_TERMINAL.brandBlue, bold: true, children: "cat" }),
|
|
7205
|
+
/* @__PURE__ */ jsxs9(Text9, { dimColor: true, children: [
|
|
6746
7206
|
" ",
|
|
6747
7207
|
getBasename(filepath)
|
|
6748
7208
|
] }),
|
|
6749
|
-
/* @__PURE__ */
|
|
6750
|
-
"
|
|
7209
|
+
/* @__PURE__ */ jsxs9(Text9, { color: BLUMA_TERMINAL.brandMagenta, children: [
|
|
7210
|
+
" ",
|
|
7211
|
+
":",
|
|
6751
7212
|
start,
|
|
6752
7213
|
"-",
|
|
6753
7214
|
end
|
|
@@ -6758,9 +7219,9 @@ var renderBlumaNotebook = ({ args }) => {
|
|
|
6758
7219
|
const parsed = parseArgs(args);
|
|
6759
7220
|
const thought = parsed.thought || parsed.content?.thought || "[thinking...]";
|
|
6760
7221
|
const truncated = truncate(thought, 100);
|
|
6761
|
-
return /* @__PURE__ */
|
|
6762
|
-
/* @__PURE__ */
|
|
6763
|
-
/* @__PURE__ */
|
|
7222
|
+
return /* @__PURE__ */ jsxs9(Box9, { flexDirection: "column", children: [
|
|
7223
|
+
/* @__PURE__ */ jsx9(Box9, { children: /* @__PURE__ */ jsx9(Text9, { color: BLUMA_TERMINAL.brandMagenta, bold: true, children: "thinking" }) }),
|
|
7224
|
+
/* @__PURE__ */ jsx9(Box9, { paddingLeft: 2, children: /* @__PURE__ */ jsx9(Text9, { dimColor: true, italic: true, children: truncated }) })
|
|
6764
7225
|
] });
|
|
6765
7226
|
};
|
|
6766
7227
|
var renderEditToolCall = ({ args, preview }) => {
|
|
@@ -6768,20 +7229,20 @@ var renderEditToolCall = ({ args, preview }) => {
|
|
|
6768
7229
|
const filepath = parsed.file_path || "[no file]";
|
|
6769
7230
|
const oldStr = parsed.old_string || "";
|
|
6770
7231
|
const newStr = parsed.new_string || "";
|
|
6771
|
-
return /* @__PURE__ */
|
|
6772
|
-
/* @__PURE__ */
|
|
6773
|
-
/* @__PURE__ */
|
|
6774
|
-
/* @__PURE__ */
|
|
7232
|
+
return /* @__PURE__ */ jsxs9(Box9, { flexDirection: "column", children: [
|
|
7233
|
+
/* @__PURE__ */ jsxs9(Box9, { children: [
|
|
7234
|
+
/* @__PURE__ */ jsx9(Text9, { color: BLUMA_TERMINAL.brandMagenta, bold: true, children: "edit" }),
|
|
7235
|
+
/* @__PURE__ */ jsxs9(Text9, { dimColor: true, children: [
|
|
6775
7236
|
" ",
|
|
6776
7237
|
getBasename(filepath)
|
|
6777
7238
|
] })
|
|
6778
7239
|
] }),
|
|
6779
|
-
preview ? /* @__PURE__ */
|
|
6780
|
-
/* @__PURE__ */
|
|
7240
|
+
preview ? /* @__PURE__ */ jsx9(Box9, { marginTop: 1, children: /* @__PURE__ */ jsx9(SimpleDiff, { text: preview, maxHeight: 8 }) }) : /* @__PURE__ */ jsxs9(Box9, { paddingLeft: 2, flexDirection: "column", children: [
|
|
7241
|
+
/* @__PURE__ */ jsxs9(Text9, { color: "red", dimColor: true, children: [
|
|
6781
7242
|
"- ",
|
|
6782
7243
|
truncate(oldStr, 50)
|
|
6783
7244
|
] }),
|
|
6784
|
-
/* @__PURE__ */
|
|
7245
|
+
/* @__PURE__ */ jsxs9(Text9, { color: "green", bold: true, children: [
|
|
6785
7246
|
"+ ",
|
|
6786
7247
|
truncate(newStr, 50)
|
|
6787
7248
|
] })
|
|
@@ -6797,36 +7258,40 @@ var renderTodoTool2 = ({ args }) => {
|
|
|
6797
7258
|
const barWidth = 10;
|
|
6798
7259
|
const filled = Math.round(progress / 100 * barWidth);
|
|
6799
7260
|
const bar = "=".repeat(filled) + " ".repeat(barWidth - filled);
|
|
6800
|
-
return /* @__PURE__ */
|
|
6801
|
-
/* @__PURE__ */
|
|
6802
|
-
/* @__PURE__ */
|
|
6803
|
-
/* @__PURE__ */
|
|
6804
|
-
|
|
7261
|
+
return /* @__PURE__ */ jsxs9(Box9, { flexDirection: "column", children: [
|
|
7262
|
+
/* @__PURE__ */ jsxs9(Box9, { flexDirection: "row", flexWrap: "wrap", children: [
|
|
7263
|
+
/* @__PURE__ */ jsx9(Text9, { color: BLUMA_TERMINAL.brandBlue, bold: true, children: pending }),
|
|
7264
|
+
/* @__PURE__ */ jsx9(Text9, { dimColor: true, children: " open \xB7 " }),
|
|
7265
|
+
/* @__PURE__ */ jsx9(Text9, { color: BLUMA_TERMINAL.brandMagenta, bold: true, children: completed }),
|
|
7266
|
+
/* @__PURE__ */ jsx9(Text9, { dimColor: true, children: " done \xB7 " }),
|
|
7267
|
+
/* @__PURE__ */ jsxs9(Text9, { dimColor: true, children: [
|
|
7268
|
+
"[",
|
|
6805
7269
|
bar,
|
|
6806
7270
|
"] ",
|
|
6807
7271
|
progress,
|
|
6808
7272
|
"%"
|
|
6809
7273
|
] })
|
|
6810
7274
|
] }),
|
|
6811
|
-
tasks.length > 0 && /* @__PURE__ */
|
|
6812
|
-
tasks.slice(0, 15).map((task, i) =>
|
|
6813
|
-
|
|
6814
|
-
{
|
|
6815
|
-
color:
|
|
6816
|
-
|
|
6817
|
-
|
|
6818
|
-
|
|
6819
|
-
|
|
6820
|
-
|
|
6821
|
-
|
|
6822
|
-
|
|
6823
|
-
|
|
6824
|
-
|
|
6825
|
-
|
|
6826
|
-
|
|
6827
|
-
|
|
7275
|
+
tasks.length > 0 && /* @__PURE__ */ jsxs9(Box9, { flexDirection: "column", marginTop: 1, paddingLeft: 1, children: [
|
|
7276
|
+
tasks.slice(0, 15).map((task, i) => {
|
|
7277
|
+
const done = task.isComplete === true;
|
|
7278
|
+
return /* @__PURE__ */ jsxs9(Box9, { flexDirection: "row", children: [
|
|
7279
|
+
/* @__PURE__ */ jsx9(Text9, { color: done ? BLUMA_TERMINAL.brandBlue : BLUMA_TERMINAL.brandMagenta, children: done ? "\u25A0 " : "\u25A1 " }),
|
|
7280
|
+
/* @__PURE__ */ jsx9(
|
|
7281
|
+
Text9,
|
|
7282
|
+
{
|
|
7283
|
+
dimColor: done,
|
|
7284
|
+
strikethrough: done,
|
|
7285
|
+
color: done ? BLUMA_TERMINAL.muted : void 0,
|
|
7286
|
+
children: task.description
|
|
7287
|
+
}
|
|
7288
|
+
)
|
|
7289
|
+
] }, i);
|
|
7290
|
+
}),
|
|
7291
|
+
tasks.length > 15 && /* @__PURE__ */ jsxs9(Text9, { dimColor: true, children: [
|
|
7292
|
+
"\u2026 +",
|
|
6828
7293
|
tasks.length - 15,
|
|
6829
|
-
"
|
|
7294
|
+
" tasks"
|
|
6830
7295
|
] })
|
|
6831
7296
|
] })
|
|
6832
7297
|
] });
|
|
@@ -6835,14 +7300,14 @@ var renderFindByName = ({ args }) => {
|
|
|
6835
7300
|
const parsed = parseArgs(args);
|
|
6836
7301
|
const pattern = parsed.pattern || "*";
|
|
6837
7302
|
const dir = parsed.directory || ".";
|
|
6838
|
-
return /* @__PURE__ */
|
|
6839
|
-
/* @__PURE__ */
|
|
6840
|
-
/* @__PURE__ */
|
|
7303
|
+
return /* @__PURE__ */ jsxs9(Box9, { children: [
|
|
7304
|
+
/* @__PURE__ */ jsx9(Text9, { color: BLUMA_TERMINAL.brandBlue, bold: true, children: "find" }),
|
|
7305
|
+
/* @__PURE__ */ jsxs9(Text9, { color: BLUMA_TERMINAL.brandMagenta, children: [
|
|
6841
7306
|
' "',
|
|
6842
7307
|
pattern,
|
|
6843
7308
|
'"'
|
|
6844
7309
|
] }),
|
|
6845
|
-
/* @__PURE__ */
|
|
7310
|
+
/* @__PURE__ */ jsxs9(Text9, { dimColor: true, children: [
|
|
6846
7311
|
" in ",
|
|
6847
7312
|
dir
|
|
6848
7313
|
] })
|
|
@@ -6852,14 +7317,14 @@ var renderGrepSearch = ({ args }) => {
|
|
|
6852
7317
|
const parsed = parseArgs(args);
|
|
6853
7318
|
const query = parsed.query || "";
|
|
6854
7319
|
const path19 = parsed.path || ".";
|
|
6855
|
-
return /* @__PURE__ */
|
|
6856
|
-
/* @__PURE__ */
|
|
6857
|
-
/* @__PURE__ */
|
|
7320
|
+
return /* @__PURE__ */ jsxs9(Box9, { children: [
|
|
7321
|
+
/* @__PURE__ */ jsx9(Text9, { color: BLUMA_TERMINAL.brandBlue, bold: true, children: "grep" }),
|
|
7322
|
+
/* @__PURE__ */ jsxs9(Text9, { color: BLUMA_TERMINAL.brandMagenta, children: [
|
|
6858
7323
|
' "',
|
|
6859
7324
|
truncate(query, 30),
|
|
6860
7325
|
'"'
|
|
6861
7326
|
] }),
|
|
6862
|
-
/* @__PURE__ */
|
|
7327
|
+
/* @__PURE__ */ jsxs9(Text9, { dimColor: true, children: [
|
|
6863
7328
|
" ",
|
|
6864
7329
|
path19
|
|
6865
7330
|
] })
|
|
@@ -6868,9 +7333,9 @@ var renderGrepSearch = ({ args }) => {
|
|
|
6868
7333
|
var renderViewFileOutline = ({ args }) => {
|
|
6869
7334
|
const parsed = parseArgs(args);
|
|
6870
7335
|
const filepath = parsed.file_path || "[no file]";
|
|
6871
|
-
return /* @__PURE__ */
|
|
6872
|
-
/* @__PURE__ */
|
|
6873
|
-
/* @__PURE__ */
|
|
7336
|
+
return /* @__PURE__ */ jsxs9(Box9, { children: [
|
|
7337
|
+
/* @__PURE__ */ jsx9(Text9, { color: BLUMA_TERMINAL.brandBlue, bold: true, children: "outline" }),
|
|
7338
|
+
/* @__PURE__ */ jsxs9(Text9, { dimColor: true, children: [
|
|
6874
7339
|
" ",
|
|
6875
7340
|
getBasename(filepath)
|
|
6876
7341
|
] })
|
|
@@ -6879,9 +7344,9 @@ var renderViewFileOutline = ({ args }) => {
|
|
|
6879
7344
|
var renderCommandStatus = ({ args }) => {
|
|
6880
7345
|
const parsed = parseArgs(args);
|
|
6881
7346
|
const id = parsed.command_id || "[no id]";
|
|
6882
|
-
return /* @__PURE__ */
|
|
6883
|
-
/* @__PURE__ */
|
|
6884
|
-
/* @__PURE__ */
|
|
7347
|
+
return /* @__PURE__ */ jsxs9(Box9, { children: [
|
|
7348
|
+
/* @__PURE__ */ jsx9(Text9, { color: BLUMA_TERMINAL.brandBlue, bold: true, children: "status" }),
|
|
7349
|
+
/* @__PURE__ */ jsxs9(Text9, { color: BLUMA_TERMINAL.brandMagenta, children: [
|
|
6885
7350
|
" #",
|
|
6886
7351
|
id
|
|
6887
7352
|
] })
|
|
@@ -6893,36 +7358,36 @@ var renderTaskBoundary = ({ args }) => {
|
|
|
6893
7358
|
const mode = parsed.mode || "EXECUTION";
|
|
6894
7359
|
const status = parsed.task_status || "";
|
|
6895
7360
|
const modeColors = {
|
|
6896
|
-
PLANNING:
|
|
6897
|
-
EXECUTION:
|
|
6898
|
-
VERIFICATION:
|
|
7361
|
+
PLANNING: BLUMA_TERMINAL.brandBlue,
|
|
7362
|
+
EXECUTION: BLUMA_TERMINAL.brandBlue,
|
|
7363
|
+
VERIFICATION: BLUMA_TERMINAL.brandMagenta
|
|
6899
7364
|
};
|
|
6900
7365
|
const modeSymbols = {
|
|
6901
7366
|
PLANNING: "P",
|
|
6902
7367
|
EXECUTION: "E",
|
|
6903
7368
|
VERIFICATION: "V"
|
|
6904
7369
|
};
|
|
6905
|
-
return /* @__PURE__ */
|
|
6906
|
-
/* @__PURE__ */
|
|
6907
|
-
/* @__PURE__ */
|
|
7370
|
+
return /* @__PURE__ */ jsxs9(Box9, { flexDirection: "column", children: [
|
|
7371
|
+
/* @__PURE__ */ jsxs9(Box9, { children: [
|
|
7372
|
+
/* @__PURE__ */ jsxs9(Text9, { color: modeColors[mode] || BLUMA_TERMINAL.muted, bold: true, children: [
|
|
6908
7373
|
"[",
|
|
6909
7374
|
modeSymbols[mode] || "?",
|
|
6910
7375
|
"]"
|
|
6911
7376
|
] }),
|
|
6912
|
-
/* @__PURE__ */
|
|
7377
|
+
/* @__PURE__ */ jsxs9(Text9, { children: [
|
|
6913
7378
|
" ",
|
|
6914
7379
|
name
|
|
6915
7380
|
] })
|
|
6916
7381
|
] }),
|
|
6917
|
-
status && /* @__PURE__ */
|
|
7382
|
+
status && /* @__PURE__ */ jsx9(Box9, { paddingLeft: 4, children: /* @__PURE__ */ jsx9(Text9, { dimColor: true, children: truncate(status, 60) }) })
|
|
6918
7383
|
] });
|
|
6919
7384
|
};
|
|
6920
7385
|
var renderSearchWeb = ({ args }) => {
|
|
6921
7386
|
const parsed = parseArgs(args);
|
|
6922
7387
|
const query = parsed.query || "[no query]";
|
|
6923
|
-
return /* @__PURE__ */
|
|
6924
|
-
/* @__PURE__ */
|
|
6925
|
-
/* @__PURE__ */
|
|
7388
|
+
return /* @__PURE__ */ jsxs9(Box9, { children: [
|
|
7389
|
+
/* @__PURE__ */ jsx9(Text9, { color: BLUMA_TERMINAL.brandBlue, bold: true, children: "search" }),
|
|
7390
|
+
/* @__PURE__ */ jsxs9(Text9, { color: BLUMA_TERMINAL.brandMagenta, children: [
|
|
6926
7391
|
' "',
|
|
6927
7392
|
truncate(query, 40),
|
|
6928
7393
|
'"'
|
|
@@ -6932,9 +7397,9 @@ var renderSearchWeb = ({ args }) => {
|
|
|
6932
7397
|
var renderLoadSkill = ({ args }) => {
|
|
6933
7398
|
const parsed = parseArgs(args);
|
|
6934
7399
|
const skillName = parsed.skill_name || "[no skill]";
|
|
6935
|
-
return /* @__PURE__ */
|
|
6936
|
-
/* @__PURE__ */
|
|
6937
|
-
/* @__PURE__ */
|
|
7400
|
+
return /* @__PURE__ */ jsxs9(Box9, { children: [
|
|
7401
|
+
/* @__PURE__ */ jsx9(Text9, { color: BLUMA_TERMINAL.brandBlue, bold: true, children: "load skill" }),
|
|
7402
|
+
/* @__PURE__ */ jsxs9(Text9, { color: BLUMA_TERMINAL.brandMagenta, children: [
|
|
6938
7403
|
" ",
|
|
6939
7404
|
skillName
|
|
6940
7405
|
] })
|
|
@@ -6943,13 +7408,7 @@ var renderLoadSkill = ({ args }) => {
|
|
|
6943
7408
|
var renderGeneric2 = ({ toolName, args }) => {
|
|
6944
7409
|
const parsed = parseArgs(args);
|
|
6945
7410
|
const keys = Object.keys(parsed).slice(0, 2);
|
|
6946
|
-
return /* @__PURE__ */
|
|
6947
|
-
/* @__PURE__ */ jsx8(Text8, { color: "white", bold: true, children: toolName }),
|
|
6948
|
-
keys.length > 0 && /* @__PURE__ */ jsxs8(Text8, { children: [
|
|
6949
|
-
" ",
|
|
6950
|
-
keys.map((k) => `${k}:${truncate(String(parsed[k]), 20)}`).join(" ")
|
|
6951
|
-
] })
|
|
6952
|
-
] });
|
|
7411
|
+
return /* @__PURE__ */ jsx9(Box9, { children: keys.length > 0 ? /* @__PURE__ */ jsx9(Text9, { dimColor: true, children: keys.map((k) => `${k}:${truncate(String(parsed[k]), 20)}`).join(" ") }) : /* @__PURE__ */ jsx9(Text9, { dimColor: true, children: "\u2014" }) });
|
|
6953
7412
|
};
|
|
6954
7413
|
var ToolRenderDisplay = {
|
|
6955
7414
|
shell_command: renderShellCommand2,
|
|
@@ -6969,76 +7428,230 @@ var ToolRenderDisplay = {
|
|
|
6969
7428
|
};
|
|
6970
7429
|
|
|
6971
7430
|
// src/app/ui/components/ToolCallDisplay.tsx
|
|
6972
|
-
import { jsx as
|
|
7431
|
+
import { jsx as jsx10 } from "react/jsx-runtime";
|
|
6973
7432
|
var ToolCallDisplayComponent = ({ toolName, args, preview }) => {
|
|
6974
|
-
if (toolName.includes("message")) {
|
|
7433
|
+
if (toolName.includes("message") || toolName.includes("task_boundary") || toolName === "todo") {
|
|
6975
7434
|
return null;
|
|
6976
7435
|
}
|
|
6977
7436
|
const Renderer = ToolRenderDisplay[toolName] || ((props) => renderGeneric2({ ...props, toolName }));
|
|
6978
|
-
return /* @__PURE__ */
|
|
7437
|
+
return /* @__PURE__ */ jsx10(ChatBlock, { marginBottom: 1, children: /* @__PURE__ */ jsx10(Box10, { flexDirection: "column", paddingLeft: 1, children: /* @__PURE__ */ jsx10(Renderer, { toolName, args, preview }) }) });
|
|
6979
7438
|
};
|
|
6980
7439
|
var ToolCallDisplay = memo6(ToolCallDisplayComponent);
|
|
6981
7440
|
|
|
6982
7441
|
// src/app/ui/components/ToolResultDisplay.tsx
|
|
6983
|
-
import { memo as memo8 } from "react";
|
|
6984
|
-
import { Box as
|
|
7442
|
+
import { memo as memo8, useEffect as useEffect5 } from "react";
|
|
7443
|
+
import { Box as Box12, Text as Text11 } from "ink";
|
|
6985
7444
|
|
|
6986
7445
|
// src/app/ui/components/MarkdownRenderer.tsx
|
|
6987
|
-
import { memo as memo7 } from "react";
|
|
6988
|
-
import { Box as
|
|
7446
|
+
import { cloneElement, isValidElement, memo as memo7 } from "react";
|
|
7447
|
+
import { Box as Box11, Text as Text10 } from "ink";
|
|
6989
7448
|
import { marked } from "marked";
|
|
6990
7449
|
import { highlight } from "cli-highlight";
|
|
6991
|
-
import {
|
|
6992
|
-
|
|
6993
|
-
|
|
6994
|
-
|
|
6995
|
-
|
|
6996
|
-
|
|
6997
|
-
|
|
6998
|
-
}
|
|
6999
|
-
|
|
7450
|
+
import { jsx as jsx11, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
7451
|
+
marked.setOptions({ gfm: true });
|
|
7452
|
+
function styleInlineNodes(nodes, keyPrefix, style) {
|
|
7453
|
+
return nodes.map(
|
|
7454
|
+
(n, j) => isValidElement(n) ? cloneElement(n, {
|
|
7455
|
+
key: `${keyPrefix}-${j}`,
|
|
7456
|
+
...style
|
|
7457
|
+
}) : n
|
|
7458
|
+
);
|
|
7459
|
+
}
|
|
7460
|
+
function headingColor(depth) {
|
|
7461
|
+
if (depth <= 1) return BLUMA_TERMINAL.heading1;
|
|
7462
|
+
if (depth === 2) return BLUMA_TERMINAL.heading2;
|
|
7463
|
+
return BLUMA_TERMINAL.headingDeep;
|
|
7464
|
+
}
|
|
7465
|
+
function bulletGlyph(ordered, index, start, task, checked, depth) {
|
|
7466
|
+
if (task) return checked ? "[x]" : "[ ]";
|
|
7467
|
+
if (ordered) {
|
|
7468
|
+
const n = typeof start === "number" ? start + index : index + 1;
|
|
7469
|
+
return `${n}.`;
|
|
7470
|
+
}
|
|
7471
|
+
return depth === 0 ? "\xB7" : "\u2514";
|
|
7472
|
+
}
|
|
7473
|
+
function walkInline(tokens, keyBase, opts = {}) {
|
|
7474
|
+
if (!tokens?.length) return [];
|
|
7475
|
+
const out = [];
|
|
7476
|
+
tokens.forEach((t, i) => {
|
|
7477
|
+
const k = `${keyBase}-i${i}`;
|
|
7478
|
+
switch (t.type) {
|
|
7479
|
+
case "text":
|
|
7480
|
+
out.push(
|
|
7481
|
+
/* @__PURE__ */ jsx11(
|
|
7482
|
+
Text10,
|
|
7483
|
+
{
|
|
7484
|
+
bold: opts.bold,
|
|
7485
|
+
italic: opts.italic,
|
|
7486
|
+
strikethrough: opts.strike,
|
|
7487
|
+
underline: opts.link,
|
|
7488
|
+
color: opts.link ? BLUMA_TERMINAL.link : opts.bold ? BLUMA_TERMINAL.brandBlue : void 0,
|
|
7489
|
+
children: t.text
|
|
7490
|
+
},
|
|
7491
|
+
k
|
|
7492
|
+
)
|
|
7493
|
+
);
|
|
7494
|
+
break;
|
|
7495
|
+
case "strong":
|
|
7496
|
+
out.push(...walkInline(t.tokens, k, { ...opts, bold: true }));
|
|
7497
|
+
break;
|
|
7498
|
+
case "em":
|
|
7499
|
+
out.push(...walkInline(t.tokens, k, { ...opts, italic: true }));
|
|
7500
|
+
break;
|
|
7501
|
+
case "codespan":
|
|
7502
|
+
out.push(
|
|
7503
|
+
/* @__PURE__ */ jsx11(
|
|
7504
|
+
Text10,
|
|
7505
|
+
{
|
|
7506
|
+
color: opts.link ? BLUMA_TERMINAL.link : BLUMA_TERMINAL.code,
|
|
7507
|
+
backgroundColor: opts.link ? void 0 : "black",
|
|
7508
|
+
underline: opts.link,
|
|
7509
|
+
children: opts.link ? t.text : `\xA0${t.text}\xA0`
|
|
7510
|
+
},
|
|
7511
|
+
k
|
|
7512
|
+
)
|
|
7513
|
+
);
|
|
7514
|
+
break;
|
|
7515
|
+
case "link": {
|
|
7516
|
+
const L = t;
|
|
7517
|
+
const inner = walkInline(L.tokens, k + "l", { ...opts, link: true });
|
|
7518
|
+
out.push(
|
|
7519
|
+
/* @__PURE__ */ jsx11(Box11, { flexDirection: "row", flexWrap: "wrap", children: inner.length > 0 ? inner : /* @__PURE__ */ jsx11(Text10, { color: BLUMA_TERMINAL.link, underline: true, children: L.text }) }, k)
|
|
7520
|
+
);
|
|
7521
|
+
break;
|
|
7522
|
+
}
|
|
7523
|
+
case "br":
|
|
7524
|
+
out.push(
|
|
7525
|
+
/* @__PURE__ */ jsx11(Text10, { dimColor: true, children: "\n" }, k)
|
|
7526
|
+
);
|
|
7527
|
+
break;
|
|
7528
|
+
case "escape":
|
|
7529
|
+
out.push(
|
|
7530
|
+
/* @__PURE__ */ jsx11(
|
|
7531
|
+
Text10,
|
|
7532
|
+
{
|
|
7533
|
+
bold: opts.bold,
|
|
7534
|
+
italic: opts.italic,
|
|
7535
|
+
underline: opts.link,
|
|
7536
|
+
color: opts.link ? BLUMA_TERMINAL.link : void 0,
|
|
7537
|
+
children: t.text
|
|
7538
|
+
},
|
|
7539
|
+
k
|
|
7540
|
+
)
|
|
7541
|
+
);
|
|
7542
|
+
break;
|
|
7543
|
+
case "del":
|
|
7544
|
+
out.push(...walkInline(t.tokens, k, { ...opts, strike: true }));
|
|
7545
|
+
break;
|
|
7546
|
+
case "image": {
|
|
7547
|
+
const Im = t;
|
|
7548
|
+
out.push(
|
|
7549
|
+
/* @__PURE__ */ jsxs10(Text10, { dimColor: true, italic: true, children: [
|
|
7550
|
+
"[",
|
|
7551
|
+
Im.text || "img",
|
|
7552
|
+
"]"
|
|
7553
|
+
] }, k)
|
|
7554
|
+
);
|
|
7555
|
+
break;
|
|
7556
|
+
}
|
|
7557
|
+
default:
|
|
7558
|
+
if ("text" in t && typeof t.text === "string") {
|
|
7559
|
+
out.push(
|
|
7560
|
+
/* @__PURE__ */ jsx11(Text10, { bold: opts.bold, italic: opts.italic, children: t.text }, k)
|
|
7561
|
+
);
|
|
7562
|
+
}
|
|
7563
|
+
}
|
|
7564
|
+
});
|
|
7565
|
+
return out;
|
|
7566
|
+
}
|
|
7567
|
+
function renderParagraph(p, key) {
|
|
7568
|
+
const nodes = walkInline(p.tokens, key);
|
|
7569
|
+
return /* @__PURE__ */ jsx11(Box11, { marginBottom: 1, flexDirection: "row", flexWrap: "wrap", children: nodes.length > 0 ? nodes : /* @__PURE__ */ jsx11(Text10, { dimColor: true, children: p.text }) }, key);
|
|
7570
|
+
}
|
|
7571
|
+
function renderListItemBlocks(item, depth, keyBase) {
|
|
7572
|
+
if (!item.tokens?.length) {
|
|
7573
|
+
const nodes = walkInline(
|
|
7574
|
+
[{ type: "text", raw: item.text, text: item.text }],
|
|
7575
|
+
keyBase
|
|
7576
|
+
);
|
|
7577
|
+
return nodes.length ? [/* @__PURE__ */ jsx11(Box11, { flexDirection: "row", flexWrap: "wrap", children: nodes }, keyBase)] : [];
|
|
7578
|
+
}
|
|
7579
|
+
const blocks = [];
|
|
7580
|
+
item.tokens.forEach((sub, si) => {
|
|
7581
|
+
const sk = `${keyBase}-b${si}`;
|
|
7582
|
+
if (sub.type === "paragraph") {
|
|
7583
|
+
blocks.push(renderParagraph(sub, sk));
|
|
7584
|
+
} else if (sub.type === "list") {
|
|
7585
|
+
blocks.push(renderListBlock(sub, depth + 1, sk));
|
|
7586
|
+
} else if (sub.type === "text") {
|
|
7587
|
+
const n = walkInline([sub], sk);
|
|
7588
|
+
if (n.length) blocks.push(/* @__PURE__ */ jsx11(Box11, { flexDirection: "row", flexWrap: "wrap", children: n }, sk));
|
|
7589
|
+
}
|
|
7590
|
+
});
|
|
7591
|
+
return blocks;
|
|
7592
|
+
}
|
|
7593
|
+
function renderListBlock(list, depth, keyBase) {
|
|
7594
|
+
return /* @__PURE__ */ jsx11(Box11, { flexDirection: "column", marginBottom: 1, paddingLeft: depth > 0 ? 2 : 0, children: list.items.map((item, idx) => {
|
|
7595
|
+
const glyph = bulletGlyph(
|
|
7596
|
+
list.ordered,
|
|
7597
|
+
idx,
|
|
7598
|
+
list.start,
|
|
7599
|
+
item.task,
|
|
7600
|
+
item.checked,
|
|
7601
|
+
depth
|
|
7602
|
+
);
|
|
7603
|
+
const gColor = depth === 0 ? BLUMA_TERMINAL.listBullet : BLUMA_TERMINAL.listBulletSub;
|
|
7604
|
+
const body = renderListItemBlocks(item, depth, `${keyBase}-it${idx}`);
|
|
7605
|
+
return /* @__PURE__ */ jsxs10(Box11, { flexDirection: "row", alignItems: "flex-start", marginBottom: 0, children: [
|
|
7606
|
+
/* @__PURE__ */ jsx11(Text10, { color: gColor, children: (item.task ? glyph : `${glyph} `).padEnd(item.task ? 4 : 3, " ") }),
|
|
7607
|
+
/* @__PURE__ */ jsx11(Box11, { flexDirection: "column", flexGrow: 1, children: body.length > 0 ? body : /* @__PURE__ */ jsx11(Text10, { dimColor: true, children: item.text }) })
|
|
7608
|
+
] }, `${keyBase}-row-${idx}`);
|
|
7609
|
+
}) }, keyBase);
|
|
7610
|
+
}
|
|
7611
|
+
function renderBlockquote(q, key) {
|
|
7612
|
+
const inner = q.tokens && q.tokens.length > 0 ? renderBlockTokens(q.tokens, `${key}-inner`) : /* @__PURE__ */ jsx11(Text10, { dimColor: true, italic: true, children: q.text });
|
|
7613
|
+
return /* @__PURE__ */ jsxs10(
|
|
7614
|
+
Box11,
|
|
7615
|
+
{
|
|
7616
|
+
flexDirection: "row",
|
|
7617
|
+
marginBottom: 1,
|
|
7618
|
+
borderStyle: "single",
|
|
7619
|
+
borderColor: BLUMA_TERMINAL.brandMagenta,
|
|
7620
|
+
paddingLeft: 1,
|
|
7621
|
+
paddingY: 0,
|
|
7622
|
+
children: [
|
|
7623
|
+
/* @__PURE__ */ jsx11(Text10, { color: BLUMA_TERMINAL.brandMagenta, children: "\u2502 " }),
|
|
7624
|
+
/* @__PURE__ */ jsx11(Box11, { flexDirection: "column", flexGrow: 1, children: inner })
|
|
7625
|
+
]
|
|
7626
|
+
},
|
|
7627
|
+
key
|
|
7628
|
+
);
|
|
7629
|
+
}
|
|
7630
|
+
function renderBlockTokens(tokens, keyRoot) {
|
|
7000
7631
|
const elements = [];
|
|
7001
7632
|
for (let i = 0; i < tokens.length; i++) {
|
|
7002
7633
|
const token = tokens[i];
|
|
7003
|
-
const key =
|
|
7634
|
+
const key = `${keyRoot}-${i}`;
|
|
7004
7635
|
switch (token.type) {
|
|
7005
7636
|
case "heading": {
|
|
7006
|
-
const
|
|
7007
|
-
const
|
|
7637
|
+
const h = token;
|
|
7638
|
+
const color = headingColor(h.depth);
|
|
7639
|
+
const prefix = h.depth <= 2 ? `${"#".repeat(h.depth)} ` : "";
|
|
7640
|
+
const inner = walkInline(h.tokens, `${key}-h`);
|
|
7008
7641
|
elements.push(
|
|
7009
|
-
/* @__PURE__ */
|
|
7010
|
-
prefix,
|
|
7011
|
-
|
|
7012
|
-
|
|
7013
|
-
] }) }, key)
|
|
7642
|
+
/* @__PURE__ */ jsxs10(Box11, { marginBottom: 1, flexDirection: "row", flexWrap: "wrap", alignItems: "flex-start", children: [
|
|
7643
|
+
/* @__PURE__ */ jsx11(Text10, { color, bold: true, children: prefix }),
|
|
7644
|
+
inner.length > 0 ? inner : /* @__PURE__ */ jsx11(Text10, { color, bold: true, children: h.text })
|
|
7645
|
+
] }, key)
|
|
7014
7646
|
);
|
|
7015
7647
|
break;
|
|
7016
7648
|
}
|
|
7017
|
-
case "paragraph":
|
|
7018
|
-
|
|
7019
|
-
elements.push(
|
|
7020
|
-
/* @__PURE__ */ jsx10(Box10, { marginBottom: 1, children: renderInline(para.text) }, key)
|
|
7021
|
-
);
|
|
7649
|
+
case "paragraph":
|
|
7650
|
+
elements.push(renderParagraph(token, key));
|
|
7022
7651
|
break;
|
|
7023
|
-
|
|
7024
|
-
|
|
7025
|
-
const list = token;
|
|
7026
|
-
list.items.forEach((item, idx) => {
|
|
7027
|
-
const bullet = list.ordered ? `${idx + 1}.` : "\u2022";
|
|
7028
|
-
const text = item.tokens?.filter((t) => t.type === "text").map((t) => t.text).join("") || item.text;
|
|
7029
|
-
elements.push(
|
|
7030
|
-
/* @__PURE__ */ jsxs9(Box10, { paddingLeft: 1, children: [
|
|
7031
|
-
/* @__PURE__ */ jsx10(Text9, { color: COLORS.listBullet, children: bullet }),
|
|
7032
|
-
/* @__PURE__ */ jsxs9(Text9, { children: [
|
|
7033
|
-
" ",
|
|
7034
|
-
renderInline(text)
|
|
7035
|
-
] })
|
|
7036
|
-
] }, `${key}-item-${idx}`)
|
|
7037
|
-
);
|
|
7038
|
-
});
|
|
7039
|
-
elements.push(/* @__PURE__ */ jsx10(Box10, { marginBottom: 1 }, `${key}-spacer`));
|
|
7652
|
+
case "list":
|
|
7653
|
+
elements.push(renderListBlock(token, 0, key));
|
|
7040
7654
|
break;
|
|
7041
|
-
}
|
|
7042
7655
|
case "code": {
|
|
7043
7656
|
const code = token;
|
|
7044
7657
|
let highlighted;
|
|
@@ -7051,110 +7664,144 @@ function renderTokens(tokens) {
|
|
|
7051
7664
|
highlighted = code.text;
|
|
7052
7665
|
}
|
|
7053
7666
|
elements.push(
|
|
7054
|
-
/* @__PURE__ */
|
|
7055
|
-
|
|
7056
|
-
|
|
7057
|
-
|
|
7667
|
+
/* @__PURE__ */ jsxs10(
|
|
7668
|
+
Box11,
|
|
7669
|
+
{
|
|
7670
|
+
flexDirection: "column",
|
|
7671
|
+
marginBottom: 1,
|
|
7672
|
+
borderStyle: "single",
|
|
7673
|
+
borderColor: BLUMA_TERMINAL.panelBorder,
|
|
7674
|
+
paddingX: 1,
|
|
7675
|
+
children: [
|
|
7676
|
+
code.lang ? /* @__PURE__ */ jsx11(Text10, { color: BLUMA_TERMINAL.codeLabel, dimColor: true, children: code.lang }) : null,
|
|
7677
|
+
/* @__PURE__ */ jsx11(Text10, { dimColor: true, children: highlighted })
|
|
7678
|
+
]
|
|
7679
|
+
},
|
|
7680
|
+
key
|
|
7681
|
+
)
|
|
7058
7682
|
);
|
|
7059
7683
|
break;
|
|
7060
7684
|
}
|
|
7061
|
-
case "blockquote":
|
|
7062
|
-
|
|
7063
|
-
elements.push(
|
|
7064
|
-
/* @__PURE__ */ jsxs9(Box10, { marginBottom: 1, children: [
|
|
7065
|
-
/* @__PURE__ */ jsx10(Text9, { color: COLORS.quote, children: "\u2502 " }),
|
|
7066
|
-
/* @__PURE__ */ jsx10(Text9, { dimColor: true, italic: true, children: quote.text })
|
|
7067
|
-
] }, key)
|
|
7068
|
-
);
|
|
7685
|
+
case "blockquote":
|
|
7686
|
+
elements.push(renderBlockquote(token, key));
|
|
7069
7687
|
break;
|
|
7070
|
-
}
|
|
7071
7688
|
case "table": {
|
|
7072
7689
|
const table = token;
|
|
7073
7690
|
elements.push(
|
|
7074
|
-
/* @__PURE__ */
|
|
7691
|
+
/* @__PURE__ */ jsxs10(Box11, { flexDirection: "column", marginBottom: 1, children: [
|
|
7692
|
+
/* @__PURE__ */ jsx11(Box11, { flexDirection: "row", children: table.header.map((cell, idx) => {
|
|
7693
|
+
const headerNodes = walkInline(cell.tokens, `${key}-h${idx}`);
|
|
7694
|
+
const styled = headerNodes.length > 0 ? styleInlineNodes(headerNodes, `${key}-h${idx}`, { bold: true, color: BLUMA_TERMINAL.brandBlue }) : [/* @__PURE__ */ jsx11(Text10, { bold: true, color: BLUMA_TERMINAL.brandBlue, children: cell.text }, `${key}-h${idx}-t`)];
|
|
7695
|
+
return /* @__PURE__ */ jsx11(Box11, { paddingRight: 2, flexDirection: "row", flexWrap: "wrap", children: styled }, idx);
|
|
7696
|
+
}) }),
|
|
7697
|
+
table.rows.map((row, rowIdx) => /* @__PURE__ */ jsx11(Box11, { flexDirection: "row", children: row.map((cell, cellIdx) => {
|
|
7698
|
+
const cellNodes = walkInline(cell.tokens, `${key}-c${rowIdx}-${cellIdx}`);
|
|
7699
|
+
const styled = cellNodes.length > 0 ? styleInlineNodes(cellNodes, `${key}-c${rowIdx}-${cellIdx}`, { dimColor: true }) : [/* @__PURE__ */ jsx11(Text10, { dimColor: true, children: cell.text }, `${key}-c${rowIdx}-${cellIdx}-t`)];
|
|
7700
|
+
return /* @__PURE__ */ jsx11(Box11, { paddingRight: 2, flexDirection: "row", flexWrap: "wrap", children: styled }, cellIdx);
|
|
7701
|
+
}) }, `${key}-r${rowIdx}`))
|
|
7702
|
+
] }, key)
|
|
7075
7703
|
);
|
|
7076
|
-
table.rows.forEach((row, rowIdx) => {
|
|
7077
|
-
elements.push(
|
|
7078
|
-
/* @__PURE__ */ jsx10(Box10, { flexDirection: "row", children: row.map((cell, cellIdx) => /* @__PURE__ */ jsx10(Box10, { paddingRight: 2, children: /* @__PURE__ */ jsx10(Text9, { children: cell.text }) }, cellIdx)) }, `${key}-row-${rowIdx}`)
|
|
7079
|
-
);
|
|
7080
|
-
});
|
|
7081
|
-
elements.push(/* @__PURE__ */ jsx10(Box10, { marginBottom: 1 }, `${key}-spacer`));
|
|
7082
7704
|
break;
|
|
7083
7705
|
}
|
|
7084
|
-
case "hr":
|
|
7706
|
+
case "hr":
|
|
7085
7707
|
elements.push(
|
|
7086
|
-
/* @__PURE__ */
|
|
7708
|
+
/* @__PURE__ */ jsx11(Box11, { marginY: 1, children: /* @__PURE__ */ jsx11(Text10, { dimColor: true, children: "\u2500".repeat(42) }) }, key)
|
|
7087
7709
|
);
|
|
7088
7710
|
break;
|
|
7089
|
-
|
|
7090
|
-
case "space": {
|
|
7711
|
+
case "space":
|
|
7091
7712
|
break;
|
|
7092
|
-
|
|
7093
|
-
default: {
|
|
7713
|
+
default:
|
|
7094
7714
|
if ("text" in token && typeof token.text === "string") {
|
|
7095
|
-
elements.push(
|
|
7715
|
+
elements.push(
|
|
7716
|
+
/* @__PURE__ */ jsx11(Text10, { dimColor: true, children: token.text }, key)
|
|
7717
|
+
);
|
|
7096
7718
|
}
|
|
7097
|
-
}
|
|
7098
7719
|
}
|
|
7099
7720
|
}
|
|
7100
7721
|
return elements;
|
|
7101
7722
|
}
|
|
7102
|
-
function renderInline(text) {
|
|
7103
|
-
const parts = [];
|
|
7104
|
-
let remaining = text;
|
|
7105
|
-
let partIndex = 0;
|
|
7106
|
-
const inlineRegex = /(\*\*(.+?)\*\*|\*(.+?)\*|`(.+?)`|\[(.+?)\]\((.+?)\))/;
|
|
7107
|
-
while (remaining.length > 0) {
|
|
7108
|
-
const match = remaining.match(inlineRegex);
|
|
7109
|
-
if (!match) {
|
|
7110
|
-
parts.push(/* @__PURE__ */ jsx10(Text9, { children: remaining }, `inline-${partIndex++}`));
|
|
7111
|
-
break;
|
|
7112
|
-
}
|
|
7113
|
-
const matchIndex = match.index ?? 0;
|
|
7114
|
-
if (matchIndex > 0) {
|
|
7115
|
-
parts.push(
|
|
7116
|
-
/* @__PURE__ */ jsx10(Text9, { children: remaining.slice(0, matchIndex) }, `inline-${partIndex++}`)
|
|
7117
|
-
);
|
|
7118
|
-
}
|
|
7119
|
-
const fullMatch = match[0];
|
|
7120
|
-
if (fullMatch.startsWith("**")) {
|
|
7121
|
-
parts.push(
|
|
7122
|
-
/* @__PURE__ */ jsx10(Text9, { bold: true, children: match[2] }, `inline-${partIndex++}`)
|
|
7123
|
-
);
|
|
7124
|
-
} else if (fullMatch.startsWith("*")) {
|
|
7125
|
-
parts.push(
|
|
7126
|
-
/* @__PURE__ */ jsx10(Text9, { italic: true, children: match[3] }, `inline-${partIndex++}`)
|
|
7127
|
-
);
|
|
7128
|
-
} else if (fullMatch.startsWith("`")) {
|
|
7129
|
-
parts.push(
|
|
7130
|
-
/* @__PURE__ */ jsxs9(Text9, { color: COLORS.code, children: [
|
|
7131
|
-
"`",
|
|
7132
|
-
match[4],
|
|
7133
|
-
"`"
|
|
7134
|
-
] }, `inline-${partIndex++}`)
|
|
7135
|
-
);
|
|
7136
|
-
} else if (fullMatch.startsWith("[")) {
|
|
7137
|
-
parts.push(
|
|
7138
|
-
/* @__PURE__ */ jsx10(Text9, { color: COLORS.link, underline: true, children: match[5] }, `inline-${partIndex++}`)
|
|
7139
|
-
);
|
|
7140
|
-
}
|
|
7141
|
-
remaining = remaining.slice(matchIndex + fullMatch.length);
|
|
7142
|
-
}
|
|
7143
|
-
return parts.length === 1 ? parts[0] : /* @__PURE__ */ jsx10(Fragment3, { children: parts });
|
|
7144
|
-
}
|
|
7145
7723
|
var MarkdownRendererComponent = ({ markdown }) => {
|
|
7146
7724
|
if (!markdown || markdown.trim() === "") {
|
|
7147
7725
|
return null;
|
|
7148
7726
|
}
|
|
7149
7727
|
const tokens = marked.lexer(markdown);
|
|
7150
|
-
return /* @__PURE__ */
|
|
7728
|
+
return /* @__PURE__ */ jsx11(Box11, { flexDirection: "column", paddingRight: 1, children: renderBlockTokens(tokens, "md") });
|
|
7151
7729
|
};
|
|
7152
7730
|
var MarkdownRenderer = memo7(MarkdownRendererComponent);
|
|
7153
7731
|
|
|
7732
|
+
// src/app/ui/utils/expandablePreviewStore.ts
|
|
7733
|
+
var latest = null;
|
|
7734
|
+
function parseResult(result) {
|
|
7735
|
+
try {
|
|
7736
|
+
return JSON.parse(result);
|
|
7737
|
+
} catch {
|
|
7738
|
+
return null;
|
|
7739
|
+
}
|
|
7740
|
+
}
|
|
7741
|
+
function truncatedLineCount(text, maxVisible) {
|
|
7742
|
+
const allLines = text.split("\n").filter((l) => l.trim());
|
|
7743
|
+
if (allLines.length <= maxVisible) {
|
|
7744
|
+
return { truncated: 0, totalKept: allLines.length };
|
|
7745
|
+
}
|
|
7746
|
+
return { truncated: allLines.length - maxVisible, totalKept: maxVisible };
|
|
7747
|
+
}
|
|
7748
|
+
function refreshExpandableFromToolResult(toolName, result) {
|
|
7749
|
+
if (toolName.includes("task_boundary")) {
|
|
7750
|
+
return;
|
|
7751
|
+
}
|
|
7752
|
+
const parsed = parseResult(result);
|
|
7753
|
+
if (toolName.includes("read_file") && parsed && typeof parsed.content === "string") {
|
|
7754
|
+
const { truncated } = truncatedLineCount(parsed.content, TOOL_PREVIEW_MAX_LINES);
|
|
7755
|
+
if (truncated > 0) {
|
|
7756
|
+
const fp = typeof parsed.filepath === "string" ? parsed.filepath : "file";
|
|
7757
|
+
const sl = parsed.start_line;
|
|
7758
|
+
const el = parsed.end_line;
|
|
7759
|
+
const range = typeof sl === "number" && typeof el === "number" ? ` :${sl}-${el}` : "";
|
|
7760
|
+
latest = {
|
|
7761
|
+
fullText: parsed.content,
|
|
7762
|
+
title: `${fp}${range}`,
|
|
7763
|
+
toolName,
|
|
7764
|
+
linesHidden: truncated
|
|
7765
|
+
};
|
|
7766
|
+
} else {
|
|
7767
|
+
latest = null;
|
|
7768
|
+
}
|
|
7769
|
+
return;
|
|
7770
|
+
}
|
|
7771
|
+
if ((toolName.includes("shell_command") || toolName.includes("run_command") || toolName.includes("command_status")) && parsed) {
|
|
7772
|
+
const output = String(parsed.stdout || parsed.output || "");
|
|
7773
|
+
const stderr = String(parsed.stderr || "");
|
|
7774
|
+
const status = String(parsed.status || "");
|
|
7775
|
+
if (parsed.command_id && !output && !stderr && !status) {
|
|
7776
|
+
return;
|
|
7777
|
+
}
|
|
7778
|
+
if (status === "running") {
|
|
7779
|
+
return;
|
|
7780
|
+
}
|
|
7781
|
+
const blob = output || stderr;
|
|
7782
|
+
if (!blob) {
|
|
7783
|
+
return;
|
|
7784
|
+
}
|
|
7785
|
+
const { truncated } = truncatedLineCount(blob, TOOL_PREVIEW_MAX_LINES);
|
|
7786
|
+
if (truncated > 0) {
|
|
7787
|
+
latest = {
|
|
7788
|
+
fullText: blob,
|
|
7789
|
+
title: "shell output",
|
|
7790
|
+
toolName,
|
|
7791
|
+
linesHidden: truncated
|
|
7792
|
+
};
|
|
7793
|
+
} else {
|
|
7794
|
+
latest = null;
|
|
7795
|
+
}
|
|
7796
|
+
}
|
|
7797
|
+
}
|
|
7798
|
+
function peekLatestExpandable() {
|
|
7799
|
+
return latest;
|
|
7800
|
+
}
|
|
7801
|
+
|
|
7154
7802
|
// src/app/ui/components/ToolResultDisplay.tsx
|
|
7155
|
-
import { jsx as
|
|
7156
|
-
var
|
|
7157
|
-
var parseResult = (result) => {
|
|
7803
|
+
import { jsx as jsx12, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
7804
|
+
var parseResult2 = (result) => {
|
|
7158
7805
|
try {
|
|
7159
7806
|
return JSON.parse(result);
|
|
7160
7807
|
} catch {
|
|
@@ -7171,153 +7818,222 @@ var truncateLines = (text, max) => {
|
|
|
7171
7818
|
truncated: allLines.length - max
|
|
7172
7819
|
};
|
|
7173
7820
|
};
|
|
7821
|
+
function TodoTaskLine({
|
|
7822
|
+
done,
|
|
7823
|
+
label
|
|
7824
|
+
}) {
|
|
7825
|
+
return /* @__PURE__ */ jsxs11(Box12, { flexDirection: "row", children: [
|
|
7826
|
+
/* @__PURE__ */ jsx12(Text11, { color: done ? BLUMA_TERMINAL.brandBlue : BLUMA_TERMINAL.brandMagenta, children: done ? "\u25A0 " : "\u25A1 " }),
|
|
7827
|
+
/* @__PURE__ */ jsx12(Text11, { dimColor: done, strikethrough: done, color: done ? BLUMA_TERMINAL.muted : void 0, children: label })
|
|
7828
|
+
] });
|
|
7829
|
+
}
|
|
7174
7830
|
var ToolResultDisplayComponent = ({ toolName, result }) => {
|
|
7831
|
+
useEffect5(() => {
|
|
7832
|
+
refreshExpandableFromToolResult(toolName, result);
|
|
7833
|
+
}, [toolName, result]);
|
|
7175
7834
|
if (toolName.includes("task_boundary")) {
|
|
7176
7835
|
return null;
|
|
7177
7836
|
}
|
|
7178
|
-
const parsed =
|
|
7837
|
+
const parsed = parseResult2(result);
|
|
7179
7838
|
if (toolName.includes("message")) {
|
|
7180
|
-
const body = parsed?.content?.body
|
|
7839
|
+
const body = parsed?.content?.body ?? parsed?.body ?? parsed?.message;
|
|
7181
7840
|
if (!body) return null;
|
|
7182
|
-
return /* @__PURE__ */
|
|
7183
|
-
}
|
|
7184
|
-
if (toolName.includes("read_file") && parsed
|
|
7185
|
-
const { lines, truncated } = truncateLines(parsed.content,
|
|
7186
|
-
return /* @__PURE__ */
|
|
7187
|
-
lines.map((line, i) => /* @__PURE__ */
|
|
7188
|
-
truncated > 0
|
|
7189
|
-
"
|
|
7841
|
+
return /* @__PURE__ */ jsx12(ChatBlock, { marginBottom: 1, children: /* @__PURE__ */ jsx12(Box12, { paddingLeft: 2, flexDirection: "column", children: /* @__PURE__ */ jsx12(MarkdownRenderer, { markdown: String(body) }) }) });
|
|
7842
|
+
}
|
|
7843
|
+
if (toolName.includes("read_file") && parsed && typeof parsed.content === "string") {
|
|
7844
|
+
const { lines, truncated } = truncateLines(parsed.content, TOOL_PREVIEW_MAX_LINES);
|
|
7845
|
+
return /* @__PURE__ */ jsx12(ChatBlock, { marginBottom: 1, children: /* @__PURE__ */ jsxs11(Box12, { flexDirection: "column", paddingLeft: 2, children: [
|
|
7846
|
+
lines.map((line, i) => /* @__PURE__ */ jsx12(Text11, { dimColor: true, children: line.slice(0, 120) }, i)),
|
|
7847
|
+
truncated > 0 ? /* @__PURE__ */ jsxs11(Text11, { dimColor: true, children: [
|
|
7848
|
+
"\u2026 +",
|
|
7190
7849
|
truncated,
|
|
7191
|
-
" lines"
|
|
7192
|
-
] })
|
|
7193
|
-
] });
|
|
7850
|
+
" lines \xB7 Ctrl+O expand"
|
|
7851
|
+
] }) : null
|
|
7852
|
+
] }) });
|
|
7194
7853
|
}
|
|
7195
7854
|
if ((toolName.includes("shell_command") || toolName.includes("run_command") || toolName.includes("command_status")) && parsed) {
|
|
7196
|
-
const output = parsed.stdout || parsed.output || "";
|
|
7197
|
-
const stderr = parsed.stderr || "";
|
|
7855
|
+
const output = String(parsed.stdout || parsed.output || "");
|
|
7856
|
+
const stderr = String(parsed.stderr || "");
|
|
7198
7857
|
const exitCode = parsed.exit_code ?? parsed.exitCode ?? 0;
|
|
7199
|
-
const status = parsed.status || "";
|
|
7858
|
+
const status = String(parsed.status || "");
|
|
7200
7859
|
if (parsed.command_id && !output && !stderr && !status) {
|
|
7201
|
-
return /* @__PURE__ */
|
|
7860
|
+
return /* @__PURE__ */ jsx12(ChatBlock, { marginBottom: 1, children: /* @__PURE__ */ jsx12(Box12, { paddingLeft: 2, children: /* @__PURE__ */ jsxs11(Text11, { dimColor: true, children: [
|
|
7202
7861
|
"started #",
|
|
7203
|
-
parsed.command_id.slice(0, 8)
|
|
7204
|
-
] }) });
|
|
7862
|
+
String(parsed.command_id).slice(0, 8)
|
|
7863
|
+
] }) }) });
|
|
7205
7864
|
}
|
|
7206
7865
|
if (status === "running") {
|
|
7207
|
-
return /* @__PURE__ */
|
|
7866
|
+
return /* @__PURE__ */ jsx12(ChatBlock, { marginBottom: 1, children: /* @__PURE__ */ jsx12(Box12, { paddingLeft: 2, children: /* @__PURE__ */ jsx12(Text11, { color: BLUMA_TERMINAL.warn, dimColor: true, children: "still running\u2026" }) }) });
|
|
7208
7867
|
}
|
|
7209
7868
|
if (!output && !stderr) return null;
|
|
7210
|
-
const { lines, truncated } = truncateLines(output || stderr,
|
|
7869
|
+
const { lines, truncated } = truncateLines(output || stderr, TOOL_PREVIEW_MAX_LINES);
|
|
7211
7870
|
const isError = exitCode !== 0;
|
|
7212
7871
|
const isSuccess = exitCode === 0 && status !== "running";
|
|
7213
|
-
const
|
|
7214
|
-
return /* @__PURE__ */
|
|
7215
|
-
lines.map((line, i) => /* @__PURE__ */
|
|
7216
|
-
truncated > 0
|
|
7217
|
-
"
|
|
7872
|
+
const lineColor = isError ? BLUMA_TERMINAL.err : isSuccess ? BLUMA_TERMINAL.success : BLUMA_TERMINAL.muted;
|
|
7873
|
+
return /* @__PURE__ */ jsx12(ChatBlock, { marginBottom: 1, children: /* @__PURE__ */ jsxs11(Box12, { flexDirection: "column", paddingLeft: 2, children: [
|
|
7874
|
+
lines.map((line, i) => /* @__PURE__ */ jsx12(Text11, { dimColor: true, color: lineColor, children: line.slice(0, 120) }, i)),
|
|
7875
|
+
truncated > 0 ? /* @__PURE__ */ jsxs11(Text11, { dimColor: true, children: [
|
|
7876
|
+
"\u2026 +",
|
|
7218
7877
|
truncated,
|
|
7219
|
-
" lines"
|
|
7220
|
-
] }),
|
|
7221
|
-
exitCode !== 0
|
|
7222
|
-
"exit
|
|
7878
|
+
" lines \xB7 Ctrl+O expand"
|
|
7879
|
+
] }) : null,
|
|
7880
|
+
exitCode !== 0 ? /* @__PURE__ */ jsxs11(Text11, { dimColor: true, color: BLUMA_TERMINAL.err, children: [
|
|
7881
|
+
"exit ",
|
|
7223
7882
|
exitCode
|
|
7224
|
-
] })
|
|
7225
|
-
] });
|
|
7883
|
+
] }) : null
|
|
7884
|
+
] }) });
|
|
7226
7885
|
}
|
|
7227
7886
|
if ((toolName.includes("grep") || toolName.includes("find_by_name")) && parsed) {
|
|
7228
7887
|
const matches = parsed.matches || parsed.results || parsed.files || [];
|
|
7229
7888
|
if (matches.length === 0) {
|
|
7230
|
-
return /* @__PURE__ */
|
|
7889
|
+
return /* @__PURE__ */ jsx12(ChatBlock, { marginBottom: 1, children: /* @__PURE__ */ jsx12(Box12, { paddingLeft: 2, children: /* @__PURE__ */ jsx12(Text11, { dimColor: true, children: "no matches" }) }) });
|
|
7231
7890
|
}
|
|
7232
|
-
return /* @__PURE__ */
|
|
7233
|
-
/* @__PURE__ */
|
|
7891
|
+
return /* @__PURE__ */ jsx12(ChatBlock, { marginBottom: 1, children: /* @__PURE__ */ jsxs11(Box12, { flexDirection: "column", paddingLeft: 2, children: [
|
|
7892
|
+
/* @__PURE__ */ jsxs11(Text11, { dimColor: true, children: [
|
|
7234
7893
|
matches.length,
|
|
7235
7894
|
" matches"
|
|
7236
7895
|
] }),
|
|
7237
|
-
matches.slice(0, 5).map((m, i) =>
|
|
7238
|
-
|
|
7239
|
-
|
|
7240
|
-
|
|
7241
|
-
|
|
7242
|
-
|
|
7243
|
-
|
|
7244
|
-
|
|
7245
|
-
|
|
7246
|
-
|
|
7896
|
+
matches.slice(0, 5).map((m, i) => {
|
|
7897
|
+
const row = m;
|
|
7898
|
+
const path19 = row.file || row.path || row.name || m;
|
|
7899
|
+
const line = row.line;
|
|
7900
|
+
return /* @__PURE__ */ jsxs11(Text11, { dimColor: true, children: [
|
|
7901
|
+
String(path19),
|
|
7902
|
+
line != null ? `:${line}` : ""
|
|
7903
|
+
] }, i);
|
|
7904
|
+
}),
|
|
7905
|
+
matches.length > 5 ? /* @__PURE__ */ jsxs11(Text11, { dimColor: true, children: [
|
|
7906
|
+
"\u2026 +",
|
|
7907
|
+
matches.length - 5
|
|
7908
|
+
] }) : null
|
|
7909
|
+
] }) });
|
|
7247
7910
|
}
|
|
7248
7911
|
if (toolName.includes("ls_tool") && parsed) {
|
|
7249
7912
|
const entries = parsed.entries || parsed.files || [];
|
|
7250
7913
|
if (entries.length === 0) return null;
|
|
7251
|
-
return /* @__PURE__ */
|
|
7252
|
-
entries.slice(0, 6).map((e, i) =>
|
|
7253
|
-
|
|
7254
|
-
|
|
7255
|
-
|
|
7256
|
-
|
|
7257
|
-
|
|
7258
|
-
|
|
7259
|
-
|
|
7260
|
-
|
|
7261
|
-
|
|
7262
|
-
|
|
7914
|
+
return /* @__PURE__ */ jsx12(ChatBlock, { marginBottom: 1, children: /* @__PURE__ */ jsxs11(Box12, { flexDirection: "column", paddingLeft: 2, children: [
|
|
7915
|
+
entries.slice(0, 6).map((e, i) => {
|
|
7916
|
+
const row = e;
|
|
7917
|
+
const name = row.name ?? e;
|
|
7918
|
+
const isDir = Boolean(row.isDirectory);
|
|
7919
|
+
return /* @__PURE__ */ jsxs11(Text11, { dimColor: true, color: isDir ? BLUMA_TERMINAL.brandBlue : BLUMA_TERMINAL.muted, children: [
|
|
7920
|
+
isDir ? "d " : "f ",
|
|
7921
|
+
String(name)
|
|
7922
|
+
] }, i);
|
|
7923
|
+
}),
|
|
7924
|
+
entries.length > 6 ? /* @__PURE__ */ jsxs11(Text11, { dimColor: true, children: [
|
|
7925
|
+
"\u2026 +",
|
|
7926
|
+
entries.length - 6
|
|
7927
|
+
] }) : null
|
|
7928
|
+
] }) });
|
|
7263
7929
|
}
|
|
7264
7930
|
if (toolName.includes("load_skill") && parsed) {
|
|
7265
7931
|
if (!parsed.success) {
|
|
7266
|
-
return /* @__PURE__ */
|
|
7267
|
-
"
|
|
7268
|
-
parsed.message
|
|
7269
|
-
] }) });
|
|
7270
|
-
}
|
|
7271
|
-
|
|
7272
|
-
|
|
7273
|
-
/* @__PURE__ */
|
|
7274
|
-
/* @__PURE__ */
|
|
7275
|
-
"
|
|
7276
|
-
|
|
7277
|
-
|
|
7932
|
+
return /* @__PURE__ */ jsx12(ChatBlock, { marginBottom: 1, children: /* @__PURE__ */ jsx12(Box12, { paddingLeft: 2, children: /* @__PURE__ */ jsxs11(Text11, { dimColor: true, color: BLUMA_TERMINAL.err, children: [
|
|
7933
|
+
"Not found: ",
|
|
7934
|
+
String(parsed.message || "")
|
|
7935
|
+
] }) }) });
|
|
7936
|
+
}
|
|
7937
|
+
const desc = parsed.description ? String(parsed.description) : "";
|
|
7938
|
+
return /* @__PURE__ */ jsx12(ChatBlock, { marginBottom: 1, children: /* @__PURE__ */ jsxs11(Box12, { paddingLeft: 2, flexDirection: "row", flexWrap: "wrap", children: [
|
|
7939
|
+
/* @__PURE__ */ jsx12(Text11, { color: BLUMA_TERMINAL.brandMagenta, bold: true, children: String(parsed.skill_name || "") }),
|
|
7940
|
+
/* @__PURE__ */ jsxs11(Text11, { dimColor: true, children: [
|
|
7941
|
+
" ",
|
|
7942
|
+
"\u2014 ",
|
|
7943
|
+
desc.slice(0, 80),
|
|
7944
|
+
desc.length > 80 ? "\u2026" : ""
|
|
7278
7945
|
] })
|
|
7279
|
-
] });
|
|
7946
|
+
] }) });
|
|
7280
7947
|
}
|
|
7281
7948
|
if (toolName.includes("todo")) {
|
|
7282
|
-
|
|
7949
|
+
if (parsed && Array.isArray(parsed.tasks)) {
|
|
7950
|
+
const tasks = parsed.tasks;
|
|
7951
|
+
const stats = parsed.stats;
|
|
7952
|
+
const msg = typeof parsed.message === "string" ? parsed.message : "";
|
|
7953
|
+
return /* @__PURE__ */ jsx12(ChatBlock, { marginBottom: 1, children: /* @__PURE__ */ jsxs11(Box12, { flexDirection: "column", paddingLeft: 2, children: [
|
|
7954
|
+
msg ? /* @__PURE__ */ jsx12(Box12, { marginBottom: 1, children: /* @__PURE__ */ jsx12(Text11, { dimColor: true, children: msg }) }) : null,
|
|
7955
|
+
stats && typeof stats.progress === "number" ? /* @__PURE__ */ jsxs11(Text11, { dimColor: true, children: [
|
|
7956
|
+
stats.completed ?? 0,
|
|
7957
|
+
"/",
|
|
7958
|
+
stats.total ?? tasks.length,
|
|
7959
|
+
" done \xB7 ",
|
|
7960
|
+
stats.progress,
|
|
7961
|
+
"%"
|
|
7962
|
+
] }) : null,
|
|
7963
|
+
/* @__PURE__ */ jsxs11(Box12, { flexDirection: "column", marginTop: 1, children: [
|
|
7964
|
+
tasks.slice(0, 12).map((t, i) => {
|
|
7965
|
+
const done = t.status === "completed" || t.isComplete === true;
|
|
7966
|
+
const line = `#${t.id ?? i + 1} ${t.description ?? ""}`;
|
|
7967
|
+
return /* @__PURE__ */ jsx12(TodoTaskLine, { done, label: line }, i);
|
|
7968
|
+
}),
|
|
7969
|
+
tasks.length > 12 ? /* @__PURE__ */ jsxs11(Text11, { dimColor: true, children: [
|
|
7970
|
+
"\u2026 +",
|
|
7971
|
+
tasks.length - 12,
|
|
7972
|
+
" tasks"
|
|
7973
|
+
] }) : null
|
|
7974
|
+
] })
|
|
7975
|
+
] }) });
|
|
7976
|
+
}
|
|
7977
|
+
const lines = result.split("\n").filter(Boolean);
|
|
7978
|
+
if (lines.length === 0) return null;
|
|
7979
|
+
return /* @__PURE__ */ jsx12(ChatBlock, { marginBottom: 1, children: /* @__PURE__ */ jsx12(Box12, { flexDirection: "column", paddingLeft: 2, children: lines.slice(0, 14).map((line, i) => /* @__PURE__ */ jsx12(Text11, { dimColor: true, children: line.slice(0, 100) }, i)) }) });
|
|
7283
7980
|
}
|
|
7284
7981
|
if (toolName.includes("view_file_outline") && parsed) {
|
|
7285
7982
|
const symbols = parsed.symbols || parsed.outline || [];
|
|
7286
7983
|
if (symbols.length === 0) return null;
|
|
7287
|
-
return /* @__PURE__ */
|
|
7288
|
-
symbols.slice(0, 5).map((s, i) =>
|
|
7289
|
-
|
|
7290
|
-
|
|
7291
|
-
|
|
7292
|
-
|
|
7293
|
-
|
|
7294
|
-
|
|
7295
|
-
|
|
7296
|
-
|
|
7297
|
-
|
|
7298
|
-
|
|
7984
|
+
return /* @__PURE__ */ jsx12(ChatBlock, { marginBottom: 1, children: /* @__PURE__ */ jsxs11(Box12, { flexDirection: "column", paddingLeft: 2, children: [
|
|
7985
|
+
symbols.slice(0, 5).map((s, i) => {
|
|
7986
|
+
const row = s;
|
|
7987
|
+
return /* @__PURE__ */ jsxs11(Text11, { dimColor: true, children: [
|
|
7988
|
+
String(row.kind || "sym"),
|
|
7989
|
+
" ",
|
|
7990
|
+
String(row.name || "")
|
|
7991
|
+
] }, i);
|
|
7992
|
+
}),
|
|
7993
|
+
symbols.length > 5 ? /* @__PURE__ */ jsxs11(Text11, { dimColor: true, children: [
|
|
7994
|
+
"\u2026 +",
|
|
7995
|
+
symbols.length - 5
|
|
7996
|
+
] }) : null
|
|
7997
|
+
] }) });
|
|
7299
7998
|
}
|
|
7300
7999
|
return null;
|
|
7301
8000
|
};
|
|
7302
8001
|
var ToolResultDisplay = memo8(ToolResultDisplayComponent);
|
|
7303
8002
|
|
|
8003
|
+
// src/app/ui/SessionInfoConnectingMCP.tsx
|
|
8004
|
+
import { Box as Box13, Text as Text12 } from "ink";
|
|
8005
|
+
import Spinner from "ink-spinner";
|
|
8006
|
+
import { jsx as jsx13, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
8007
|
+
var SessionInfoConnectingMCP = ({
|
|
8008
|
+
sessionId,
|
|
8009
|
+
workdir,
|
|
8010
|
+
statusMessage
|
|
8011
|
+
}) => /* @__PURE__ */ jsx13(ChatBlock, { marginBottom: 1, children: /* @__PURE__ */ jsxs12(Box13, { flexDirection: "column", paddingLeft: 1, children: [
|
|
8012
|
+
/* @__PURE__ */ jsxs12(Text12, { children: [
|
|
8013
|
+
/* @__PURE__ */ jsx13(Text12, { bold: true, color: BLUMA_TERMINAL.brandBlue, children: "session" }),
|
|
8014
|
+
/* @__PURE__ */ jsx13(Text12, { dimColor: true, children: " \xB7 " }),
|
|
8015
|
+
/* @__PURE__ */ jsx13(Text12, { color: BLUMA_TERMINAL.brandMagenta, children: sessionId.slice(0, 12) })
|
|
8016
|
+
] }),
|
|
8017
|
+
/* @__PURE__ */ jsxs12(Text12, { dimColor: true, children: [
|
|
8018
|
+
/* @__PURE__ */ jsx13(Text12, { color: BLUMA_TERMINAL.brandMagenta, children: "\u2514 " }),
|
|
8019
|
+
workdir
|
|
8020
|
+
] }),
|
|
8021
|
+
/* @__PURE__ */ jsxs12(Box13, { marginTop: 1, flexDirection: "row", flexWrap: "wrap", children: [
|
|
8022
|
+
/* @__PURE__ */ jsxs12(Text12, { color: BLUMA_TERMINAL.warn, children: [
|
|
8023
|
+
/* @__PURE__ */ jsx13(Spinner, { type: "dots" }),
|
|
8024
|
+
" "
|
|
8025
|
+
] }),
|
|
8026
|
+
/* @__PURE__ */ jsx13(Text12, { dimColor: true, children: statusMessage || "Establishing MCP\u2026" })
|
|
8027
|
+
] })
|
|
8028
|
+
] }) });
|
|
8029
|
+
var SessionInfoConnectingMCP_default = SessionInfoConnectingMCP;
|
|
8030
|
+
|
|
7304
8031
|
// src/app/ui/components/SlashCommands.tsx
|
|
7305
|
-
import { Box as
|
|
7306
|
-
import { Fragment as
|
|
8032
|
+
import { Box as Box14, Text as Text13 } from "ink";
|
|
8033
|
+
import { Fragment as Fragment2, jsx as jsx14, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
7307
8034
|
var SlashCommands = ({ input, setHistory, agentRef }) => {
|
|
7308
8035
|
const [cmd, ...args] = input.slice(1).trim().split(/\s+/);
|
|
7309
|
-
const outBox = (children) => /* @__PURE__ */
|
|
7310
|
-
Box12,
|
|
7311
|
-
{
|
|
7312
|
-
borderStyle: "single",
|
|
7313
|
-
borderColor: "gray",
|
|
7314
|
-
paddingX: 2,
|
|
7315
|
-
paddingY: 0,
|
|
7316
|
-
marginBottom: 1,
|
|
7317
|
-
flexDirection: "column",
|
|
7318
|
-
children
|
|
7319
|
-
}
|
|
7320
|
-
);
|
|
8036
|
+
const outBox = (children) => /* @__PURE__ */ jsx14(ChatBlock, { marginBottom: 1, children: /* @__PURE__ */ jsx14(Box14, { paddingLeft: 1, flexDirection: "column", children }) });
|
|
7321
8037
|
const render2 = () => {
|
|
7322
8038
|
if (!cmd) {
|
|
7323
8039
|
return null;
|
|
@@ -7325,11 +8041,11 @@ var SlashCommands = ({ input, setHistory, agentRef }) => {
|
|
|
7325
8041
|
if (cmd === "help") {
|
|
7326
8042
|
const cmds = getSlashCommands();
|
|
7327
8043
|
return outBox(
|
|
7328
|
-
/* @__PURE__ */
|
|
7329
|
-
/* @__PURE__ */
|
|
7330
|
-
/* @__PURE__ */
|
|
7331
|
-
/* @__PURE__ */
|
|
7332
|
-
/* @__PURE__ */
|
|
8044
|
+
/* @__PURE__ */ jsxs13(Fragment2, { children: [
|
|
8045
|
+
/* @__PURE__ */ jsx14(Box14, { marginBottom: 1, children: /* @__PURE__ */ jsx14(Text13, { bold: true, color: BLUMA_TERMINAL.brandMagenta, children: "Available Commands" }) }),
|
|
8046
|
+
/* @__PURE__ */ jsx14(Box14, { flexDirection: "column", children: cmds.map((c, i) => /* @__PURE__ */ jsxs13(Box14, { children: [
|
|
8047
|
+
/* @__PURE__ */ jsx14(Text13, { color: BLUMA_TERMINAL.brandBlue, children: c.name.padEnd(12) }),
|
|
8048
|
+
/* @__PURE__ */ jsx14(Text13, { dimColor: true, children: c.description })
|
|
7333
8049
|
] }, i)) })
|
|
7334
8050
|
] })
|
|
7335
8051
|
);
|
|
@@ -7337,9 +8053,9 @@ var SlashCommands = ({ input, setHistory, agentRef }) => {
|
|
|
7337
8053
|
if (cmd === "clear") {
|
|
7338
8054
|
setHistory((prev) => prev.filter((item) => item.id === 0 || item.id === 1));
|
|
7339
8055
|
return outBox(
|
|
7340
|
-
/* @__PURE__ */
|
|
7341
|
-
/* @__PURE__ */
|
|
7342
|
-
/* @__PURE__ */
|
|
8056
|
+
/* @__PURE__ */ jsxs13(Box14, { children: [
|
|
8057
|
+
/* @__PURE__ */ jsx14(Text13, { color: "green", children: "[ok]" }),
|
|
8058
|
+
/* @__PURE__ */ jsx14(Text13, { dimColor: true, children: " History cleared" })
|
|
7343
8059
|
] })
|
|
7344
8060
|
);
|
|
7345
8061
|
}
|
|
@@ -7351,8 +8067,8 @@ var SlashCommands = ({ input, setHistory, agentRef }) => {
|
|
|
7351
8067
|
setHistory((prev) => prev.concat({
|
|
7352
8068
|
id: Date.now(),
|
|
7353
8069
|
component: outBox(
|
|
7354
|
-
/* @__PURE__ */
|
|
7355
|
-
"
|
|
8070
|
+
/* @__PURE__ */ jsx14(Box14, { children: /* @__PURE__ */ jsxs13(Text13, { color: "red", children: [
|
|
8071
|
+
"Failed to execute /init: ",
|
|
7356
8072
|
e?.message || String(e)
|
|
7357
8073
|
] }) })
|
|
7358
8074
|
)
|
|
@@ -7372,41 +8088,41 @@ var SlashCommands = ({ input, setHistory, agentRef }) => {
|
|
|
7372
8088
|
const colType = 10;
|
|
7373
8089
|
const colSource = 18;
|
|
7374
8090
|
return outBox(
|
|
7375
|
-
/* @__PURE__ */
|
|
7376
|
-
/* @__PURE__ */
|
|
7377
|
-
/* @__PURE__ */
|
|
7378
|
-
/* @__PURE__ */
|
|
7379
|
-
/* @__PURE__ */
|
|
8091
|
+
/* @__PURE__ */ jsxs13(Fragment2, { children: [
|
|
8092
|
+
/* @__PURE__ */ jsxs13(Box14, { marginBottom: 1, children: [
|
|
8093
|
+
/* @__PURE__ */ jsx14(Text13, { bold: true, color: BLUMA_TERMINAL.brandMagenta, children: "MCP Tools" }),
|
|
8094
|
+
/* @__PURE__ */ jsx14(Text13, { dimColor: true, children: " \u2022 " }),
|
|
8095
|
+
/* @__PURE__ */ jsxs13(Text13, { dimColor: true, children: [
|
|
7380
8096
|
tools.length,
|
|
7381
8097
|
" total"
|
|
7382
8098
|
] }),
|
|
7383
|
-
term && /* @__PURE__ */
|
|
7384
|
-
/* @__PURE__ */
|
|
7385
|
-
/* @__PURE__ */
|
|
8099
|
+
term && /* @__PURE__ */ jsxs13(Fragment2, { children: [
|
|
8100
|
+
/* @__PURE__ */ jsx14(Text13, { dimColor: true, children: " \u2022 filter: " }),
|
|
8101
|
+
/* @__PURE__ */ jsxs13(Text13, { color: BLUMA_TERMINAL.brandBlue, children: [
|
|
7386
8102
|
'"',
|
|
7387
8103
|
term,
|
|
7388
8104
|
'"'
|
|
7389
8105
|
] }),
|
|
7390
|
-
/* @__PURE__ */
|
|
8106
|
+
/* @__PURE__ */ jsxs13(Text13, { dimColor: true, children: [
|
|
7391
8107
|
" \u2022 showing: ",
|
|
7392
8108
|
filtered.length
|
|
7393
8109
|
] })
|
|
7394
8110
|
] })
|
|
7395
8111
|
] }),
|
|
7396
|
-
filtered.length === 0 ? /* @__PURE__ */
|
|
7397
|
-
/* @__PURE__ */
|
|
8112
|
+
filtered.length === 0 ? /* @__PURE__ */ jsx14(Text13, { color: "yellow", children: "No MCP tools found" }) : /* @__PURE__ */ jsxs13(Box14, { flexDirection: "column", children: [
|
|
8113
|
+
/* @__PURE__ */ jsx14(Box14, { children: /* @__PURE__ */ jsxs13(Text13, { color: "gray", children: [
|
|
7398
8114
|
pad("Name", colName),
|
|
7399
8115
|
" \u2502 ",
|
|
7400
8116
|
pad("Type", colType),
|
|
7401
8117
|
" \u2502 ",
|
|
7402
8118
|
pad("Source", colSource)
|
|
7403
8119
|
] }) }),
|
|
7404
|
-
/* @__PURE__ */
|
|
8120
|
+
/* @__PURE__ */ jsx14(Text13, { color: "gray", children: "\u2500".repeat(colName + colType + colSource + 6) }),
|
|
7405
8121
|
filtered.map((t, i) => {
|
|
7406
8122
|
const name = t.function?.name || t.name || "tool";
|
|
7407
8123
|
const type = t.function?.name ? "fn" : t.type || "tool";
|
|
7408
8124
|
const source = t.source || t.provider || "mcp";
|
|
7409
|
-
return /* @__PURE__ */
|
|
8125
|
+
return /* @__PURE__ */ jsxs13(Text13, { color: "white", children: [
|
|
7410
8126
|
pad(name, colName),
|
|
7411
8127
|
" \u2502 ",
|
|
7412
8128
|
pad(String(type), colType),
|
|
@@ -7429,22 +8145,22 @@ var SlashCommands = ({ input, setHistory, agentRef }) => {
|
|
|
7429
8145
|
const colType = 10;
|
|
7430
8146
|
const colSource = 18;
|
|
7431
8147
|
return outBox(
|
|
7432
|
-
/* @__PURE__ */
|
|
7433
|
-
/* @__PURE__ */
|
|
7434
|
-
/* @__PURE__ */
|
|
8148
|
+
/* @__PURE__ */ jsxs13(Fragment2, { children: [
|
|
8149
|
+
/* @__PURE__ */ jsx14(Text13, { color: BLUMA_TERMINAL.brandMagenta, bold: true, children: "Native Tools" }),
|
|
8150
|
+
/* @__PURE__ */ jsxs13(Text13, { color: "gray", children: [
|
|
7435
8151
|
"Total Native: ",
|
|
7436
8152
|
tools.length,
|
|
7437
8153
|
term ? ` | Filter: "${term}" | Showing: ${filtered.length}` : ""
|
|
7438
8154
|
] }),
|
|
7439
|
-
filtered.length === 0 ? /* @__PURE__ */
|
|
7440
|
-
/* @__PURE__ */
|
|
8155
|
+
filtered.length === 0 ? /* @__PURE__ */ jsx14(Text13, { color: "yellow", children: "No native tools to display." }) : /* @__PURE__ */ jsxs13(Box14, { flexDirection: "column", children: [
|
|
8156
|
+
/* @__PURE__ */ jsxs13(Text13, { color: "gray", children: [
|
|
7441
8157
|
pad("Name", colName),
|
|
7442
8158
|
" | ",
|
|
7443
8159
|
pad("Type", colType),
|
|
7444
8160
|
" | ",
|
|
7445
8161
|
pad("Source", colSource)
|
|
7446
8162
|
] }),
|
|
7447
|
-
/* @__PURE__ */
|
|
8163
|
+
/* @__PURE__ */ jsxs13(Text13, { color: "gray", children: [
|
|
7448
8164
|
"".padEnd(colName, "-"),
|
|
7449
8165
|
"---",
|
|
7450
8166
|
"".padEnd(colType, "-"),
|
|
@@ -7455,7 +8171,7 @@ var SlashCommands = ({ input, setHistory, agentRef }) => {
|
|
|
7455
8171
|
const name = t.function?.name || t.name || "tool";
|
|
7456
8172
|
const type = t.function?.name ? "fn" : t.type || "tool";
|
|
7457
8173
|
const source = t.source || "native";
|
|
7458
|
-
return /* @__PURE__ */
|
|
8174
|
+
return /* @__PURE__ */ jsxs13(Text13, { color: "white", children: [
|
|
7459
8175
|
pad(name, colName),
|
|
7460
8176
|
" | ",
|
|
7461
8177
|
pad(String(type), colType),
|
|
@@ -7467,18 +8183,18 @@ var SlashCommands = ({ input, setHistory, agentRef }) => {
|
|
|
7467
8183
|
] })
|
|
7468
8184
|
);
|
|
7469
8185
|
}
|
|
7470
|
-
return outBox(/* @__PURE__ */
|
|
8186
|
+
return outBox(/* @__PURE__ */ jsxs13(Text13, { color: "red", children: [
|
|
7471
8187
|
"Command not recognized: /",
|
|
7472
8188
|
cmd
|
|
7473
8189
|
] }));
|
|
7474
8190
|
};
|
|
7475
|
-
return /* @__PURE__ */
|
|
8191
|
+
return /* @__PURE__ */ jsx14(Fragment2, { children: render2() });
|
|
7476
8192
|
};
|
|
7477
8193
|
var SlashCommands_default = SlashCommands;
|
|
7478
8194
|
|
|
7479
8195
|
// src/app/agent/utils/update_check.ts
|
|
7480
8196
|
import updateNotifier from "update-notifier";
|
|
7481
|
-
import { fileURLToPath as
|
|
8197
|
+
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
7482
8198
|
import path18 from "path";
|
|
7483
8199
|
import fs14 from "fs";
|
|
7484
8200
|
var BLUMA_PACKAGE_NAME = "@nomad-e/bluma-cli";
|
|
@@ -7513,7 +8229,7 @@ async function checkForUpdates() {
|
|
|
7513
8229
|
pkg = findBlumaPackageJson(path18.dirname(binPath));
|
|
7514
8230
|
}
|
|
7515
8231
|
if (!pkg) {
|
|
7516
|
-
const __filename =
|
|
8232
|
+
const __filename = fileURLToPath3(import.meta.url);
|
|
7517
8233
|
const __dirname2 = path18.dirname(__filename);
|
|
7518
8234
|
pkg = findBlumaPackageJson(__dirname2);
|
|
7519
8235
|
}
|
|
@@ -7542,86 +8258,88 @@ Run: npm i -g ${BLUMA_PACKAGE_NAME} to update.`;
|
|
|
7542
8258
|
}
|
|
7543
8259
|
|
|
7544
8260
|
// src/app/ui/components/UpdateNotice.tsx
|
|
7545
|
-
import { Box as
|
|
7546
|
-
import { jsx as
|
|
8261
|
+
import { Box as Box15, Text as Text14 } from "ink";
|
|
8262
|
+
import { jsx as jsx15, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
7547
8263
|
function parseUpdateMessage(msg) {
|
|
7548
8264
|
const lines = msg.split(/\r?\n/).map((l) => l.trim());
|
|
7549
8265
|
const first = lines[0] || "";
|
|
7550
8266
|
const hintLine = lines.slice(1).join(" ") || "";
|
|
7551
8267
|
const nameMatch = first.match(/Update available for\s+([^!]+)!/i);
|
|
7552
8268
|
const versionMatch = first.match(/!\s*([^\s]+)\s*→\s*([^\s]+)/);
|
|
7553
|
-
const name = nameMatch?.[1]?.trim();
|
|
7554
|
-
const current = versionMatch?.[1]?.trim();
|
|
7555
|
-
const latest = versionMatch?.[2]?.trim();
|
|
7556
8269
|
return {
|
|
7557
|
-
name,
|
|
7558
|
-
current,
|
|
7559
|
-
latest,
|
|
8270
|
+
name: nameMatch?.[1]?.trim(),
|
|
8271
|
+
current: versionMatch?.[1]?.trim(),
|
|
8272
|
+
latest: versionMatch?.[2]?.trim(),
|
|
7560
8273
|
hint: hintLine || void 0
|
|
7561
8274
|
};
|
|
7562
8275
|
}
|
|
7563
8276
|
var UpdateNotice = ({ message: message2 }) => {
|
|
7564
|
-
const { name, current, latest, hint } = parseUpdateMessage(message2);
|
|
7565
|
-
return /* @__PURE__ */
|
|
7566
|
-
/* @__PURE__ */
|
|
7567
|
-
name && current &&
|
|
7568
|
-
|
|
7569
|
-
|
|
8277
|
+
const { name, current, latest: latest2, hint } = parseUpdateMessage(message2);
|
|
8278
|
+
return /* @__PURE__ */ jsx15(ChatBlock, { marginBottom: 1, children: /* @__PURE__ */ jsxs14(Box15, { flexDirection: "column", paddingLeft: 2, children: [
|
|
8279
|
+
name && current && latest2 ? /* @__PURE__ */ jsx15(Text14, { color: BLUMA_TERMINAL.brandMagenta, bold: true, children: name }) : null,
|
|
8280
|
+
name && current && latest2 ? /* @__PURE__ */ jsxs14(Text14, { dimColor: true, children: [
|
|
8281
|
+
current,
|
|
8282
|
+
" \u2192 ",
|
|
8283
|
+
latest2
|
|
8284
|
+
] }) : /* @__PURE__ */ jsx15(Text14, { dimColor: true, children: message2 }),
|
|
8285
|
+
hint ? /* @__PURE__ */ jsx15(Box15, { marginTop: 1, children: /* @__PURE__ */ jsx15(Text14, { dimColor: true, children: hint }) }) : null
|
|
8286
|
+
] }) });
|
|
7570
8287
|
};
|
|
7571
8288
|
var UpdateNotice_default = UpdateNotice;
|
|
7572
8289
|
|
|
7573
8290
|
// src/app/ui/components/ErrorMessage.tsx
|
|
7574
|
-
import { Box as
|
|
7575
|
-
import { jsx as
|
|
7576
|
-
var ErrorMessage = ({ message: message2, details, hint }) => {
|
|
7577
|
-
|
|
7578
|
-
|
|
7579
|
-
|
|
7580
|
-
|
|
7581
|
-
|
|
7582
|
-
|
|
7583
|
-
|
|
7584
|
-
hint && /* @__PURE__ */ jsx14(Box14, { paddingLeft: 2, children: /* @__PURE__ */ jsxs13(Text13, { color: "gray", children: [
|
|
7585
|
-
"hint: ",
|
|
7586
|
-
hint
|
|
7587
|
-
] }) })
|
|
7588
|
-
] });
|
|
7589
|
-
};
|
|
8291
|
+
import { Box as Box16, Text as Text15 } from "ink";
|
|
8292
|
+
import { jsx as jsx16, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
8293
|
+
var ErrorMessage = ({ message: message2, details, hint }) => /* @__PURE__ */ jsx16(ChatBlock, { marginBottom: 1, children: /* @__PURE__ */ jsxs15(Box16, { flexDirection: "column", paddingLeft: 2, children: [
|
|
8294
|
+
/* @__PURE__ */ jsx16(Text15, { color: BLUMA_TERMINAL.err, children: message2 }),
|
|
8295
|
+
details ? /* @__PURE__ */ jsx16(Box16, { marginTop: 1, children: /* @__PURE__ */ jsx16(Text15, { dimColor: true, children: details }) }) : null,
|
|
8296
|
+
hint ? /* @__PURE__ */ jsx16(Box16, { marginTop: 1, children: /* @__PURE__ */ jsxs15(Text15, { dimColor: true, children: [
|
|
8297
|
+
"hint: ",
|
|
8298
|
+
hint
|
|
8299
|
+
] }) }) : null
|
|
8300
|
+
] }) });
|
|
7590
8301
|
var ErrorMessage_default = ErrorMessage;
|
|
7591
8302
|
|
|
7592
8303
|
// src/app/ui/components/ReasoningDisplay.tsx
|
|
7593
|
-
import { memo as memo9
|
|
7594
|
-
import { Box as
|
|
7595
|
-
import { jsx as
|
|
8304
|
+
import { memo as memo9 } from "react";
|
|
8305
|
+
import { Box as Box17, Text as Text16 } from "ink";
|
|
8306
|
+
import { jsx as jsx17, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
7596
8307
|
var ReasoningDisplayComponent = ({
|
|
7597
8308
|
reasoning,
|
|
7598
8309
|
collapsed = false
|
|
7599
8310
|
}) => {
|
|
7600
|
-
const [isExpanded, setIsExpanded] = useState5(!collapsed);
|
|
7601
8311
|
if (!reasoning || reasoning.trim() === "") {
|
|
7602
8312
|
return null;
|
|
7603
8313
|
}
|
|
7604
|
-
const maxLines =
|
|
8314
|
+
const maxLines = collapsed ? 6 : 200;
|
|
7605
8315
|
const lines = reasoning.split("\n");
|
|
7606
|
-
const
|
|
7607
|
-
|
|
7608
|
-
|
|
7609
|
-
|
|
7610
|
-
|
|
8316
|
+
const displayLines = lines.slice(0, maxLines);
|
|
8317
|
+
const truncated = lines.length > maxLines;
|
|
8318
|
+
return /* @__PURE__ */ jsx17(ChatBlock, { marginBottom: 1, children: /* @__PURE__ */ jsxs16(Box17, { flexDirection: "column", paddingLeft: 2, children: [
|
|
8319
|
+
displayLines.map((line, i) => /* @__PURE__ */ jsx17(Text16, { dimColor: true, children: line }, i)),
|
|
8320
|
+
truncated ? /* @__PURE__ */ jsxs16(Text16, { dimColor: true, children: [
|
|
8321
|
+
"\u2026 +",
|
|
8322
|
+
lines.length - maxLines,
|
|
8323
|
+
" lines"
|
|
8324
|
+
] }) : null
|
|
8325
|
+
] }) });
|
|
7611
8326
|
};
|
|
7612
8327
|
var ReasoningDisplay = memo9(ReasoningDisplayComponent);
|
|
7613
8328
|
|
|
7614
8329
|
// src/app/ui/components/StreamingText.tsx
|
|
7615
|
-
import { useState as
|
|
7616
|
-
import { Box as
|
|
7617
|
-
import { jsx as
|
|
7618
|
-
var StreamingTextComponent = ({
|
|
7619
|
-
|
|
7620
|
-
|
|
8330
|
+
import { useState as useState5, useEffect as useEffect6, useRef as useRef4, memo as memo10 } from "react";
|
|
8331
|
+
import { Box as Box18, Text as Text17 } from "ink";
|
|
8332
|
+
import { jsx as jsx18, jsxs as jsxs17 } from "react/jsx-runtime";
|
|
8333
|
+
var StreamingTextComponent = ({
|
|
8334
|
+
eventBus,
|
|
8335
|
+
onReasoningComplete
|
|
8336
|
+
}) => {
|
|
8337
|
+
const [reasoning, setReasoning] = useState5("");
|
|
8338
|
+
const [isStreaming, setIsStreaming] = useState5(false);
|
|
7621
8339
|
const reasoningRef = useRef4("");
|
|
7622
8340
|
const lastUpdateRef = useRef4(0);
|
|
7623
8341
|
const pendingUpdateRef = useRef4(null);
|
|
7624
|
-
|
|
8342
|
+
useEffect6(() => {
|
|
7625
8343
|
const handleStart = () => {
|
|
7626
8344
|
setReasoning("");
|
|
7627
8345
|
reasoningRef.current = "";
|
|
@@ -7677,19 +8395,56 @@ var StreamingTextComponent = ({ eventBus, onReasoningComplete }) => {
|
|
|
7677
8395
|
truncatedCount = lines.length - MAX_VISIBLE_LINES;
|
|
7678
8396
|
displayLines = lines.slice(-MAX_VISIBLE_LINES);
|
|
7679
8397
|
}
|
|
7680
|
-
return /* @__PURE__ */
|
|
7681
|
-
truncatedCount > 0
|
|
7682
|
-
"
|
|
8398
|
+
return /* @__PURE__ */ jsx18(ChatBlock, { marginBottom: 1, children: /* @__PURE__ */ jsxs17(Box18, { flexDirection: "column", paddingLeft: 2, children: [
|
|
8399
|
+
truncatedCount > 0 ? /* @__PURE__ */ jsxs17(Text17, { dimColor: true, children: [
|
|
8400
|
+
"\u2026 ",
|
|
7683
8401
|
truncatedCount,
|
|
7684
|
-
"
|
|
7685
|
-
] }),
|
|
7686
|
-
|
|
7687
|
-
] });
|
|
8402
|
+
" lines above hidden"
|
|
8403
|
+
] }) : null,
|
|
8404
|
+
displayLines.map((line, i) => /* @__PURE__ */ jsx18(Text17, { dimColor: true, children: line }, i))
|
|
8405
|
+
] }) });
|
|
7688
8406
|
};
|
|
7689
8407
|
var StreamingText = memo10(StreamingTextComponent);
|
|
7690
8408
|
|
|
8409
|
+
// src/app/ui/components/ExpandedPreviewBlock.tsx
|
|
8410
|
+
import { memo as memo11 } from "react";
|
|
8411
|
+
import { Box as Box19, Text as Text18 } from "ink";
|
|
8412
|
+
import { jsx as jsx19, jsxs as jsxs18 } from "react/jsx-runtime";
|
|
8413
|
+
function ExpandedPreviewBlockComponent({ data }) {
|
|
8414
|
+
const cols = typeof process.stdout?.columns === "number" ? process.stdout.columns : 80;
|
|
8415
|
+
const rule = TERMINAL_RULE_CHAR.repeat(Math.max(8, cols));
|
|
8416
|
+
const lines = data.fullText.split("\n");
|
|
8417
|
+
const cap = EXPAND_OVERLAY_MAX_LINES;
|
|
8418
|
+
const shown = lines.slice(0, cap);
|
|
8419
|
+
const rest = lines.length - cap;
|
|
8420
|
+
return /* @__PURE__ */ jsxs18(ChatBlock, { marginBottom: 1, children: [
|
|
8421
|
+
/* @__PURE__ */ jsx19(Text18, { color: "white", children: rule }),
|
|
8422
|
+
/* @__PURE__ */ jsxs18(Box19, { flexDirection: "column", paddingLeft: 1, children: [
|
|
8423
|
+
/* @__PURE__ */ jsx19(Text18, { color: BLUMA_TERMINAL.brandMagenta, bold: true, children: "expand (Ctrl+O)" }),
|
|
8424
|
+
/* @__PURE__ */ jsx19(Text18, { dimColor: true, children: data.title }),
|
|
8425
|
+
/* @__PURE__ */ jsxs18(Text18, { dimColor: true, children: [
|
|
8426
|
+
"+",
|
|
8427
|
+
data.linesHidden,
|
|
8428
|
+
" lines were clipped in chat \xB7 below: up to ",
|
|
8429
|
+
cap,
|
|
8430
|
+
" lines \xB7 use read_file_lines before edit_tool"
|
|
8431
|
+
] }),
|
|
8432
|
+
/* @__PURE__ */ jsxs18(Box19, { flexDirection: "column", marginTop: 1, children: [
|
|
8433
|
+
shown.map((line, i) => /* @__PURE__ */ jsx19(Text18, { dimColor: true, children: line.slice(0, 200) }, i)),
|
|
8434
|
+
rest > 0 ? /* @__PURE__ */ jsxs18(Text18, { dimColor: true, children: [
|
|
8435
|
+
"\u2026 +",
|
|
8436
|
+
rest,
|
|
8437
|
+
" more lines in this chunk"
|
|
8438
|
+
] }) : null
|
|
8439
|
+
] })
|
|
8440
|
+
] }),
|
|
8441
|
+
/* @__PURE__ */ jsx19(Text18, { color: "white", children: rule })
|
|
8442
|
+
] });
|
|
8443
|
+
}
|
|
8444
|
+
var ExpandedPreviewBlock = memo11(ExpandedPreviewBlockComponent);
|
|
8445
|
+
|
|
7691
8446
|
// src/app/ui/App.tsx
|
|
7692
|
-
import { jsx as
|
|
8447
|
+
import { jsx as jsx20, jsxs as jsxs19 } from "react/jsx-runtime";
|
|
7693
8448
|
var SAFE_AUTO_APPROVE_TOOLS = [
|
|
7694
8449
|
// Comunicação/UI
|
|
7695
8450
|
"message",
|
|
@@ -7707,36 +8462,64 @@ var SAFE_AUTO_APPROVE_TOOLS = [
|
|
|
7707
8462
|
];
|
|
7708
8463
|
var AppComponent = ({ eventBus, sessionId }) => {
|
|
7709
8464
|
const agentInstance = useRef5(null);
|
|
7710
|
-
const [history, setHistory] =
|
|
7711
|
-
const [statusMessage, setStatusMessage] =
|
|
8465
|
+
const [history, setHistory] = useState6([]);
|
|
8466
|
+
const [statusMessage, setStatusMessage] = useState6(
|
|
7712
8467
|
"Initializing agent..."
|
|
7713
8468
|
);
|
|
7714
|
-
const [toolsCount, setToolsCount] =
|
|
7715
|
-
const [mcpStatus, setMcpStatus] =
|
|
8469
|
+
const [toolsCount, setToolsCount] = useState6(null);
|
|
8470
|
+
const [mcpStatus, setMcpStatus] = useState6(
|
|
7716
8471
|
"connecting"
|
|
7717
8472
|
);
|
|
7718
|
-
const [isProcessing, setIsProcessing] =
|
|
7719
|
-
const [pendingConfirmation, setPendingConfirmation] =
|
|
8473
|
+
const [isProcessing, setIsProcessing] = useState6(true);
|
|
8474
|
+
const [pendingConfirmation, setPendingConfirmation] = useState6(
|
|
7720
8475
|
null
|
|
7721
8476
|
);
|
|
7722
|
-
const [confirmationPreview, setConfirmationPreview] =
|
|
8477
|
+
const [confirmationPreview, setConfirmationPreview] = useState6(
|
|
7723
8478
|
null
|
|
7724
8479
|
);
|
|
7725
|
-
const [isInitAgentActive, setIsInitAgentActive] =
|
|
8480
|
+
const [isInitAgentActive, setIsInitAgentActive] = useState6(false);
|
|
7726
8481
|
const alwaysAcceptList = useRef5([]);
|
|
7727
8482
|
const workdir = process.cwd();
|
|
7728
8483
|
const updateCheckRan = useRef5(false);
|
|
7729
|
-
const
|
|
7730
|
-
const
|
|
8484
|
+
const turnStartedAtRef = useRef5(null);
|
|
8485
|
+
const appendExpandPreviewToHistory = useCallback2(() => {
|
|
8486
|
+
const p = peekLatestExpandable();
|
|
8487
|
+
setHistory((prev) => {
|
|
8488
|
+
const id = prev.length;
|
|
8489
|
+
if (!p) {
|
|
8490
|
+
return [
|
|
8491
|
+
...prev,
|
|
8492
|
+
{
|
|
8493
|
+
id,
|
|
8494
|
+
component: /* @__PURE__ */ jsx20(ChatMeta, { children: "Ctrl+O: no truncated preview to expand" }, id)
|
|
8495
|
+
}
|
|
8496
|
+
];
|
|
8497
|
+
}
|
|
8498
|
+
return [
|
|
8499
|
+
...prev,
|
|
8500
|
+
{
|
|
8501
|
+
id,
|
|
8502
|
+
component: /* @__PURE__ */ jsx20(ExpandedPreviewBlock, { data: p }, id)
|
|
8503
|
+
}
|
|
8504
|
+
];
|
|
8505
|
+
});
|
|
8506
|
+
}, []);
|
|
8507
|
+
useEffect7(() => {
|
|
8508
|
+
expandPreviewHotkeyBus.on("expand", appendExpandPreviewToHistory);
|
|
8509
|
+
return () => {
|
|
8510
|
+
expandPreviewHotkeyBus.off("expand", appendExpandPreviewToHistory);
|
|
8511
|
+
};
|
|
8512
|
+
}, [appendExpandPreviewToHistory]);
|
|
7731
8513
|
const handleInterrupt = useCallback2(() => {
|
|
7732
8514
|
if (!isProcessing) return;
|
|
7733
8515
|
eventBus.emit("user_interrupt");
|
|
8516
|
+
turnStartedAtRef.current = null;
|
|
7734
8517
|
setIsProcessing(false);
|
|
7735
8518
|
setHistory((prev) => [
|
|
7736
8519
|
...prev,
|
|
7737
8520
|
{
|
|
7738
8521
|
id: prev.length,
|
|
7739
|
-
component: /* @__PURE__ */
|
|
8522
|
+
component: /* @__PURE__ */ jsx20(ChatMeta, { children: "cancelled (Esc)" })
|
|
7740
8523
|
}
|
|
7741
8524
|
]);
|
|
7742
8525
|
}, [isProcessing, eventBus]);
|
|
@@ -7752,6 +8535,7 @@ var AppComponent = ({ eventBus, sessionId }) => {
|
|
|
7752
8535
|
if (cmd === "init") {
|
|
7753
8536
|
setIsInitAgentActive(true);
|
|
7754
8537
|
setIsProcessing(true);
|
|
8538
|
+
turnStartedAtRef.current = Date.now();
|
|
7755
8539
|
} else {
|
|
7756
8540
|
setIsProcessing(false);
|
|
7757
8541
|
setIsInitAgentActive(false);
|
|
@@ -7760,11 +8544,11 @@ var AppComponent = ({ eventBus, sessionId }) => {
|
|
|
7760
8544
|
...prev,
|
|
7761
8545
|
{
|
|
7762
8546
|
id: prev.length,
|
|
7763
|
-
component: /* @__PURE__ */
|
|
8547
|
+
component: /* @__PURE__ */ jsx20(ChatUserMessage, { children: /* @__PURE__ */ jsx20(Text19, { dimColor: true, children: text }) })
|
|
7764
8548
|
},
|
|
7765
8549
|
{
|
|
7766
8550
|
id: prev.length + 1,
|
|
7767
|
-
component: /* @__PURE__ */
|
|
8551
|
+
component: /* @__PURE__ */ jsx20(
|
|
7768
8552
|
SlashCommands_default,
|
|
7769
8553
|
{
|
|
7770
8554
|
input: text,
|
|
@@ -7783,17 +8567,15 @@ var AppComponent = ({ eventBus, sessionId }) => {
|
|
|
7783
8567
|
return;
|
|
7784
8568
|
}
|
|
7785
8569
|
setIsProcessing(true);
|
|
8570
|
+
turnStartedAtRef.current = Date.now();
|
|
7786
8571
|
setHistory((prev) => [
|
|
7787
8572
|
...prev,
|
|
7788
8573
|
{
|
|
7789
8574
|
id: prev.length,
|
|
7790
|
-
component: /* @__PURE__ */
|
|
7791
|
-
|
|
7792
|
-
|
|
7793
|
-
|
|
7794
|
-
command
|
|
7795
|
-
] })
|
|
7796
|
-
] })
|
|
8575
|
+
component: /* @__PURE__ */ jsx20(ChatUserMessage, { children: /* @__PURE__ */ jsxs19(Text19, { bold: true, color: "white", children: [
|
|
8576
|
+
"$ !",
|
|
8577
|
+
command
|
|
8578
|
+
] }) })
|
|
7797
8579
|
}
|
|
7798
8580
|
]);
|
|
7799
8581
|
Promise.resolve().then(() => (init_async_command(), async_command_exports)).then(async ({ runCommandAsync: runCommandAsync2 }) => {
|
|
@@ -7807,11 +8589,12 @@ Command ID: ${result.command_id}
|
|
|
7807
8589
|
Please use command_status to check the result and report back to the user.`;
|
|
7808
8590
|
agentInstance.current?.processTurn({ content: contextMessage });
|
|
7809
8591
|
} else {
|
|
8592
|
+
turnStartedAtRef.current = null;
|
|
7810
8593
|
setHistory((prev) => [
|
|
7811
8594
|
...prev,
|
|
7812
8595
|
{
|
|
7813
8596
|
id: prev.length,
|
|
7814
|
-
component: /* @__PURE__ */
|
|
8597
|
+
component: /* @__PURE__ */ jsxs19(Text19, { color: "red", children: [
|
|
7815
8598
|
"Failed to execute: ",
|
|
7816
8599
|
result.error || result.message
|
|
7817
8600
|
] })
|
|
@@ -7820,11 +8603,12 @@ Please use command_status to check the result and report back to the user.`;
|
|
|
7820
8603
|
setIsProcessing(false);
|
|
7821
8604
|
}
|
|
7822
8605
|
} catch (err) {
|
|
8606
|
+
turnStartedAtRef.current = null;
|
|
7823
8607
|
setHistory((prev) => [
|
|
7824
8608
|
...prev,
|
|
7825
8609
|
{
|
|
7826
8610
|
id: prev.length,
|
|
7827
|
-
component: /* @__PURE__ */
|
|
8611
|
+
component: /* @__PURE__ */ jsxs19(Text19, { color: "red", children: [
|
|
7828
8612
|
"Error: ",
|
|
7829
8613
|
err.message
|
|
7830
8614
|
] })
|
|
@@ -7836,21 +8620,13 @@ Please use command_status to check the result and report back to the user.`;
|
|
|
7836
8620
|
return;
|
|
7837
8621
|
}
|
|
7838
8622
|
setIsProcessing(true);
|
|
8623
|
+
turnStartedAtRef.current = Date.now();
|
|
7839
8624
|
const displayText = text.length > 1e4 ? text.substring(0, 1e4) + "..." : text;
|
|
7840
8625
|
setHistory((prev) => [
|
|
7841
8626
|
...prev,
|
|
7842
8627
|
{
|
|
7843
8628
|
id: prev.length,
|
|
7844
|
-
component: (
|
|
7845
|
-
// Uma única Box para o espaçamento
|
|
7846
|
-
/* @__PURE__ */ jsx17(Box17, { marginBottom: 1, children: /* @__PURE__ */ jsxs16(Text16, { color: "white", dimColor: true, children: [
|
|
7847
|
-
/* @__PURE__ */ jsxs16(Text16, { color: "white", children: [
|
|
7848
|
-
">",
|
|
7849
|
-
" "
|
|
7850
|
-
] }),
|
|
7851
|
-
displayText
|
|
7852
|
-
] }) })
|
|
7853
|
-
)
|
|
8629
|
+
component: /* @__PURE__ */ jsx20(ChatUserMessage, { children: /* @__PURE__ */ jsx20(Text19, { children: displayText }) })
|
|
7854
8630
|
}
|
|
7855
8631
|
]);
|
|
7856
8632
|
agentInstance.current.processTurn({ content: text });
|
|
@@ -7878,8 +8654,8 @@ Please use command_status to check the result and report back to the user.`;
|
|
|
7878
8654
|
},
|
|
7879
8655
|
[]
|
|
7880
8656
|
);
|
|
7881
|
-
|
|
7882
|
-
setHistory([{ id: 0, component: /* @__PURE__ */
|
|
8657
|
+
useEffect7(() => {
|
|
8658
|
+
setHistory([{ id: 0, component: /* @__PURE__ */ jsx20(Header, { sessionId, workdir }) }]);
|
|
7883
8659
|
const initializeAgent = async () => {
|
|
7884
8660
|
try {
|
|
7885
8661
|
agentInstance.current = new Agent(sessionId, eventBus);
|
|
@@ -7899,6 +8675,20 @@ Please use command_status to check the result and report back to the user.`;
|
|
|
7899
8675
|
};
|
|
7900
8676
|
const handleBackendMessage = (parsed) => {
|
|
7901
8677
|
try {
|
|
8678
|
+
const appendTurnDurationIfAny = () => {
|
|
8679
|
+
const t = turnStartedAtRef.current;
|
|
8680
|
+
if (t == null) return;
|
|
8681
|
+
turnStartedAtRef.current = null;
|
|
8682
|
+
const ms = Date.now() - t;
|
|
8683
|
+
const sec = ms < 1e4 ? (ms / 1e3).toFixed(1) : String(Math.round(ms / 1e3));
|
|
8684
|
+
setHistory((prev) => [
|
|
8685
|
+
...prev,
|
|
8686
|
+
{
|
|
8687
|
+
id: prev.length,
|
|
8688
|
+
component: /* @__PURE__ */ jsx20(ChatTurnDuration, { secondsFormatted: sec })
|
|
8689
|
+
}
|
|
8690
|
+
]);
|
|
8691
|
+
};
|
|
7902
8692
|
if (parsed.type === "done" || parsed.type === "error") {
|
|
7903
8693
|
setIsInitAgentActive(false);
|
|
7904
8694
|
}
|
|
@@ -7924,6 +8714,7 @@ Please use command_status to check the result and report back to the user.`;
|
|
|
7924
8714
|
if (parsed.type === "done") {
|
|
7925
8715
|
if (parsed.status !== "awaiting_confirmation") {
|
|
7926
8716
|
setStatusMessage(null);
|
|
8717
|
+
appendTurnDurationIfAny();
|
|
7927
8718
|
}
|
|
7928
8719
|
setIsProcessing(false);
|
|
7929
8720
|
return;
|
|
@@ -7945,7 +8736,7 @@ Please use command_status to check the result and report back to the user.`;
|
|
|
7945
8736
|
...prev,
|
|
7946
8737
|
{
|
|
7947
8738
|
id: prev.length,
|
|
7948
|
-
component: /* @__PURE__ */
|
|
8739
|
+
component: /* @__PURE__ */ jsx20(UpdateNotice_default, { message: msg })
|
|
7949
8740
|
}
|
|
7950
8741
|
]);
|
|
7951
8742
|
}
|
|
@@ -7959,25 +8750,14 @@ Please use command_status to check the result and report back to the user.`;
|
|
|
7959
8750
|
}
|
|
7960
8751
|
let newComponent = null;
|
|
7961
8752
|
if (parsed.type === "debug") {
|
|
7962
|
-
newComponent = /* @__PURE__ */
|
|
8753
|
+
newComponent = /* @__PURE__ */ jsx20(ChatMeta, { children: parsed.message });
|
|
7963
8754
|
} else if (parsed.type === "protocol_violation") {
|
|
7964
|
-
newComponent = /* @__PURE__ */
|
|
7965
|
-
|
|
7966
|
-
{
|
|
7967
|
-
|
|
7968
|
-
borderColor: "yellow",
|
|
7969
|
-
flexDirection: "column",
|
|
7970
|
-
marginBottom: 1,
|
|
7971
|
-
paddingX: 1,
|
|
7972
|
-
children: [
|
|
7973
|
-
/* @__PURE__ */ jsx17(Text16, { color: "yellow", bold: true, children: "Protocol Violation" }),
|
|
7974
|
-
/* @__PURE__ */ jsx17(Text16, { color: "gray", children: parsed.content }),
|
|
7975
|
-
/* @__PURE__ */ jsx17(Text16, { color: "yellow", children: parsed.message })
|
|
7976
|
-
]
|
|
7977
|
-
}
|
|
7978
|
-
);
|
|
8755
|
+
newComponent = /* @__PURE__ */ jsx20(ChatBlock, { marginBottom: 1, children: /* @__PURE__ */ jsxs19(Box20, { flexDirection: "column", paddingLeft: 2, children: [
|
|
8756
|
+
/* @__PURE__ */ jsx20(Text19, { dimColor: true, children: parsed.content }),
|
|
8757
|
+
/* @__PURE__ */ jsx20(Text19, { dimColor: true, children: parsed.message })
|
|
8758
|
+
] }) });
|
|
7979
8759
|
} else if (parsed.type === "error") {
|
|
7980
|
-
newComponent = /* @__PURE__ */
|
|
8760
|
+
newComponent = /* @__PURE__ */ jsx20(
|
|
7981
8761
|
ErrorMessage_default,
|
|
7982
8762
|
{
|
|
7983
8763
|
message: parsed.message,
|
|
@@ -7987,7 +8767,7 @@ Please use command_status to check the result and report back to the user.`;
|
|
|
7987
8767
|
);
|
|
7988
8768
|
} else if (parsed.type === "tool_call") {
|
|
7989
8769
|
const nextId3 = history.length;
|
|
7990
|
-
newComponent = /* @__PURE__ */
|
|
8770
|
+
newComponent = /* @__PURE__ */ jsx20(
|
|
7991
8771
|
ToolCallDisplay,
|
|
7992
8772
|
{
|
|
7993
8773
|
toolName: parsed.tool_name,
|
|
@@ -7996,7 +8776,7 @@ Please use command_status to check the result and report back to the user.`;
|
|
|
7996
8776
|
}
|
|
7997
8777
|
);
|
|
7998
8778
|
} else if (parsed.type === "tool_result") {
|
|
7999
|
-
newComponent = /* @__PURE__ */
|
|
8779
|
+
newComponent = /* @__PURE__ */ jsx20(
|
|
8000
8780
|
ToolResultDisplay,
|
|
8001
8781
|
{
|
|
8002
8782
|
toolName: parsed.tool_name,
|
|
@@ -8004,18 +8784,11 @@ Please use command_status to check the result and report back to the user.`;
|
|
|
8004
8784
|
}
|
|
8005
8785
|
);
|
|
8006
8786
|
} else if (parsed.type === "user_overlay") {
|
|
8007
|
-
newComponent = /* @__PURE__ */
|
|
8008
|
-
/* @__PURE__ */ jsxs16(Text16, { color: "magenta", children: [
|
|
8009
|
-
">",
|
|
8010
|
-
" "
|
|
8011
|
-
] }),
|
|
8012
|
-
parsed.payload
|
|
8013
|
-
] }) });
|
|
8787
|
+
newComponent = /* @__PURE__ */ jsx20(ChatUserMessage, { children: /* @__PURE__ */ jsx20(Text19, { dimColor: true, children: parsed.payload }) });
|
|
8014
8788
|
} else if (parsed.type === "reasoning") {
|
|
8015
|
-
newComponent = /* @__PURE__ */
|
|
8789
|
+
newComponent = /* @__PURE__ */ jsx20(ReasoningDisplay, { reasoning: parsed.content });
|
|
8016
8790
|
} else if (parsed.type === "log") {
|
|
8017
|
-
newComponent = /* @__PURE__ */
|
|
8018
|
-
"\u2139\uFE0F ",
|
|
8791
|
+
newComponent = /* @__PURE__ */ jsxs19(ChatMeta, { children: [
|
|
8019
8792
|
parsed.message,
|
|
8020
8793
|
parsed.payload ? `: ${parsed.payload}` : ""
|
|
8021
8794
|
] });
|
|
@@ -8023,10 +8796,25 @@ Please use command_status to check the result and report back to the user.`;
|
|
|
8023
8796
|
newComponent = null;
|
|
8024
8797
|
}
|
|
8025
8798
|
if (newComponent) {
|
|
8026
|
-
setHistory((prev) =>
|
|
8027
|
-
|
|
8028
|
-
|
|
8029
|
-
|
|
8799
|
+
setHistory((prev) => {
|
|
8800
|
+
const next = [
|
|
8801
|
+
...prev,
|
|
8802
|
+
{ id: prev.length, component: newComponent }
|
|
8803
|
+
];
|
|
8804
|
+
if (parsed.type === "error") {
|
|
8805
|
+
const t = turnStartedAtRef.current;
|
|
8806
|
+
if (t != null) {
|
|
8807
|
+
turnStartedAtRef.current = null;
|
|
8808
|
+
const ms = Date.now() - t;
|
|
8809
|
+
const sec = ms < 1e4 ? (ms / 1e3).toFixed(1) : String(Math.round(ms / 1e3));
|
|
8810
|
+
next.push({
|
|
8811
|
+
id: next.length,
|
|
8812
|
+
component: /* @__PURE__ */ jsx20(ChatTurnDuration, { secondsFormatted: sec })
|
|
8813
|
+
});
|
|
8814
|
+
}
|
|
8815
|
+
}
|
|
8816
|
+
return next;
|
|
8817
|
+
});
|
|
8030
8818
|
}
|
|
8031
8819
|
} catch (error) {
|
|
8032
8820
|
}
|
|
@@ -8044,10 +8832,17 @@ Please use command_status to check the result and report back to the user.`;
|
|
|
8044
8832
|
}, [eventBus, sessionId, handleConfirmation]);
|
|
8045
8833
|
const renderInteractiveComponent = () => {
|
|
8046
8834
|
if (mcpStatus !== "connected") {
|
|
8047
|
-
return
|
|
8835
|
+
return /* @__PURE__ */ jsx20(
|
|
8836
|
+
SessionInfoConnectingMCP_default,
|
|
8837
|
+
{
|
|
8838
|
+
sessionId,
|
|
8839
|
+
workdir,
|
|
8840
|
+
statusMessage
|
|
8841
|
+
}
|
|
8842
|
+
);
|
|
8048
8843
|
}
|
|
8049
8844
|
if (pendingConfirmation) {
|
|
8050
|
-
return /* @__PURE__ */
|
|
8845
|
+
return /* @__PURE__ */ jsx20(
|
|
8051
8846
|
ConfirmationPrompt,
|
|
8052
8847
|
{
|
|
8053
8848
|
toolCalls: pendingConfirmation,
|
|
@@ -8059,9 +8854,9 @@ Please use command_status to check the result and report back to the user.`;
|
|
|
8059
8854
|
}
|
|
8060
8855
|
);
|
|
8061
8856
|
}
|
|
8062
|
-
return /* @__PURE__ */
|
|
8063
|
-
isProcessing && !pendingConfirmation && /* @__PURE__ */
|
|
8064
|
-
/* @__PURE__ */
|
|
8857
|
+
return /* @__PURE__ */ jsxs19(Box20, { flexDirection: "column", children: [
|
|
8858
|
+
isProcessing && !pendingConfirmation && /* @__PURE__ */ jsx20(WorkingTimer, { eventBus }),
|
|
8859
|
+
/* @__PURE__ */ jsx20(
|
|
8065
8860
|
InputPrompt,
|
|
8066
8861
|
{
|
|
8067
8862
|
onSubmit: handleSubmit,
|
|
@@ -8072,9 +8867,9 @@ Please use command_status to check the result and report back to the user.`;
|
|
|
8072
8867
|
)
|
|
8073
8868
|
] });
|
|
8074
8869
|
};
|
|
8075
|
-
return /* @__PURE__ */
|
|
8076
|
-
/* @__PURE__ */
|
|
8077
|
-
/* @__PURE__ */
|
|
8870
|
+
return /* @__PURE__ */ jsxs19(Box20, { flexDirection: "column", children: [
|
|
8871
|
+
/* @__PURE__ */ jsx20(Static, { items: history, children: (item) => /* @__PURE__ */ jsx20(Box20, { children: item.component }, item.id) }),
|
|
8872
|
+
/* @__PURE__ */ jsx20(
|
|
8078
8873
|
StreamingText,
|
|
8079
8874
|
{
|
|
8080
8875
|
eventBus,
|
|
@@ -8084,7 +8879,7 @@ Please use command_status to check the result and report back to the user.`;
|
|
|
8084
8879
|
...prev,
|
|
8085
8880
|
{
|
|
8086
8881
|
id: prev.length,
|
|
8087
|
-
component: /* @__PURE__ */
|
|
8882
|
+
component: /* @__PURE__ */ jsx20(ReasoningDisplay, { reasoning })
|
|
8088
8883
|
}
|
|
8089
8884
|
]);
|
|
8090
8885
|
}
|
|
@@ -8094,7 +8889,7 @@ Please use command_status to check the result and report back to the user.`;
|
|
|
8094
8889
|
renderInteractiveComponent()
|
|
8095
8890
|
] });
|
|
8096
8891
|
};
|
|
8097
|
-
var App =
|
|
8892
|
+
var App = memo12(AppComponent);
|
|
8098
8893
|
var App_default = App;
|
|
8099
8894
|
|
|
8100
8895
|
// src/app/ui/utils/terminalTitle.ts
|
|
@@ -8218,7 +9013,7 @@ async function runAgentMode() {
|
|
|
8218
9013
|
process.env.BLUMA_SANDBOX_NAME = String(envelope.metadata.sandbox_name);
|
|
8219
9014
|
}
|
|
8220
9015
|
}
|
|
8221
|
-
const eventBus = new
|
|
9016
|
+
const eventBus = new EventEmitter3();
|
|
8222
9017
|
const sessionId = envelope.session_id || envelope.message_id || uuidv46();
|
|
8223
9018
|
const uc = envelope.user_context;
|
|
8224
9019
|
const userContextInput = {
|
|
@@ -8350,13 +9145,13 @@ async function runAgentMode() {
|
|
|
8350
9145
|
function runCliMode() {
|
|
8351
9146
|
const BLUMA_TITLE = process.env.BLUMA_TITLE || "BluMa - NomadEngenuity";
|
|
8352
9147
|
startTitleKeeper(BLUMA_TITLE);
|
|
8353
|
-
const eventBus = new
|
|
9148
|
+
const eventBus = new EventEmitter3();
|
|
8354
9149
|
const sessionId = uuidv46();
|
|
8355
9150
|
const props = {
|
|
8356
9151
|
eventBus,
|
|
8357
9152
|
sessionId
|
|
8358
9153
|
};
|
|
8359
|
-
render(
|
|
9154
|
+
render(React12.createElement(App_default, props));
|
|
8360
9155
|
}
|
|
8361
9156
|
var argv = process.argv.slice(2);
|
|
8362
9157
|
if (argv[0] === "agent") {
|