@bubblebrain-ai/bubble 0.0.2 → 0.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/main.d.ts +1 -1
- package/dist/main.js +1 -1
- package/dist/tui/run.js +117 -9
- package/package.json +4 -1
package/dist/main.d.ts
CHANGED
package/dist/main.js
CHANGED
package/dist/tui/run.js
CHANGED
|
@@ -387,6 +387,10 @@ function OpenTuiApp(props) {
|
|
|
387
387
|
const sidebarLspRows = [];
|
|
388
388
|
const sidebarLspMarkers = [];
|
|
389
389
|
const sidebarLspLabels = [];
|
|
390
|
+
let sidebarTodoSection;
|
|
391
|
+
const sidebarTodoRows = [];
|
|
392
|
+
const sidebarTodoMarkers = [];
|
|
393
|
+
const sidebarTodoLabels = [];
|
|
390
394
|
const sidebarFileRows = [];
|
|
391
395
|
const sidebarFileLabels = [];
|
|
392
396
|
const sidebarFileAdditions = [];
|
|
@@ -621,6 +625,12 @@ function OpenTuiApp(props) {
|
|
|
621
625
|
setSidebarTick((value) => value + 1);
|
|
622
626
|
syncSidebarContext();
|
|
623
627
|
};
|
|
628
|
+
const syncTodosFromAgent = () => {
|
|
629
|
+
const nextTodos = props.agent.getTodos();
|
|
630
|
+
setTodos(nextTodos);
|
|
631
|
+
syncSidebarTodos(nextTodos);
|
|
632
|
+
bumpSidebar();
|
|
633
|
+
};
|
|
624
634
|
function refreshGitSidebar() {
|
|
625
635
|
setGitState(readGitSidebarState(props.args.cwd));
|
|
626
636
|
syncSidebarFiles();
|
|
@@ -721,6 +731,35 @@ function OpenTuiApp(props) {
|
|
|
721
731
|
}
|
|
722
732
|
sidebarShell?.requestRender();
|
|
723
733
|
}
|
|
734
|
+
function syncSidebarTodos(nextTodos = todos()) {
|
|
735
|
+
const visible = nextTodos.slice(0, 8);
|
|
736
|
+
if (sidebarTodoSection) {
|
|
737
|
+
sidebarTodoSection.visible = visible.length > 0;
|
|
738
|
+
}
|
|
739
|
+
for (let index = 0; index < 8; index++) {
|
|
740
|
+
const row = sidebarTodoRows[index];
|
|
741
|
+
const marker = sidebarTodoMarkers[index];
|
|
742
|
+
const label = sidebarTodoLabels[index];
|
|
743
|
+
const todo = visible[index];
|
|
744
|
+
if (!row || !marker || !label)
|
|
745
|
+
continue;
|
|
746
|
+
row.visible = !!todo;
|
|
747
|
+
if (!todo) {
|
|
748
|
+
safeRequestRender(row);
|
|
749
|
+
continue;
|
|
750
|
+
}
|
|
751
|
+
const completed = todo.status === "completed";
|
|
752
|
+
const inProgress = todo.status === "in_progress";
|
|
753
|
+
const labelText = inProgress ? (todo.activeForm || todo.content) : todo.content;
|
|
754
|
+
marker.content = completed ? "✓" : inProgress ? "◉" : "○";
|
|
755
|
+
marker.fg = completed ? theme.success : inProgress ? theme.warning : theme.textMuted;
|
|
756
|
+
label.content = labelText;
|
|
757
|
+
label.fg = completed ? theme.success : inProgress ? theme.warning : theme.textMuted;
|
|
758
|
+
safeRequestRender(row);
|
|
759
|
+
}
|
|
760
|
+
sidebarShell?.requestRender();
|
|
761
|
+
rootBox?.requestRender();
|
|
762
|
+
}
|
|
724
763
|
function showSidebarLspRows(statuses) {
|
|
725
764
|
for (let index = 0; index < sidebarLspRows.length; index++) {
|
|
726
765
|
const row = sidebarLspRows[index];
|
|
@@ -3016,6 +3055,7 @@ function OpenTuiApp(props) {
|
|
|
3016
3055
|
return true;
|
|
3017
3056
|
if (props.agent.mode !== mode())
|
|
3018
3057
|
setMode(props.agent.mode);
|
|
3058
|
+
syncTodosFromAgent();
|
|
3019
3059
|
syncModelChrome();
|
|
3020
3060
|
syncModeChrome();
|
|
3021
3061
|
if (uiDisposed)
|
|
@@ -3494,6 +3534,7 @@ function OpenTuiApp(props) {
|
|
|
3494
3534
|
}
|
|
3495
3535
|
else if (event.type === "todos_updated") {
|
|
3496
3536
|
setTodos(event.todos);
|
|
3537
|
+
syncSidebarTodos(event.todos);
|
|
3497
3538
|
bumpSidebar();
|
|
3498
3539
|
}
|
|
3499
3540
|
else if (event.type === "mode_changed") {
|
|
@@ -4068,7 +4109,6 @@ function OpenTuiApp(props) {
|
|
|
4068
4109
|
const context = sidebarContextState();
|
|
4069
4110
|
const mcpStates = sidebarMcpStates();
|
|
4070
4111
|
const files = gitState().files;
|
|
4071
|
-
const activeTodos = todos().filter((todo) => todo.status !== "completed");
|
|
4072
4112
|
return h("box", {
|
|
4073
4113
|
ref: (ref) => {
|
|
4074
4114
|
sidebarShell = ref;
|
|
@@ -4154,7 +4194,7 @@ function OpenTuiApp(props) {
|
|
|
4154
4194
|
? renderSidebarSection("Compactions", [
|
|
4155
4195
|
h("text", { fg: theme.info, wrapMode: "word" }, `${currentTranscriptMessages().filter((m) => m.syntheticKind === "ui_compact_card").length} in this session`),
|
|
4156
4196
|
])
|
|
4157
|
-
: null, renderSidebarMcp(mcpStates), renderSidebarLsp(),
|
|
4197
|
+
: null, renderSidebarMcp(mcpStates), renderSidebarLsp(), renderSidebarTodos(todos()), renderSidebarFiles(files))),
|
|
4158
4198
|
renderSidebarFooter(),
|
|
4159
4199
|
]);
|
|
4160
4200
|
}
|
|
@@ -4239,11 +4279,37 @@ function OpenTuiApp(props) {
|
|
|
4239
4279
|
}),
|
|
4240
4280
|
]);
|
|
4241
4281
|
}
|
|
4242
|
-
function renderSidebarTodos(
|
|
4243
|
-
|
|
4244
|
-
|
|
4245
|
-
|
|
4246
|
-
|
|
4282
|
+
function renderSidebarTodos(todos) {
|
|
4283
|
+
const visible = todos.slice(0, 8);
|
|
4284
|
+
return h("box", {
|
|
4285
|
+
flexDirection: "column",
|
|
4286
|
+
flexShrink: 0,
|
|
4287
|
+
visible: visible.length > 0,
|
|
4288
|
+
ref: (ref) => {
|
|
4289
|
+
sidebarTodoSection = ref;
|
|
4290
|
+
syncSidebarTodos();
|
|
4291
|
+
},
|
|
4292
|
+
}, h("text", { fg: theme.text }, "Todo"), ...Array.from({ length: 8 }, (_, index) => {
|
|
4293
|
+
const todo = visible[index];
|
|
4294
|
+
const completed = todo?.status === "completed";
|
|
4295
|
+
const inProgress = todo?.status === "in_progress";
|
|
4296
|
+
const labelText = todo
|
|
4297
|
+
? (inProgress ? (todo.activeForm || todo.content) : todo.content)
|
|
4298
|
+
: "";
|
|
4299
|
+
return h("box", {
|
|
4300
|
+
flexDirection: "row",
|
|
4301
|
+
gap: 1,
|
|
4302
|
+
visible: !!todo,
|
|
4303
|
+
ref: (ref) => { sidebarTodoRows[index] = ref; },
|
|
4304
|
+
}, h("text", {
|
|
4305
|
+
fg: completed ? theme.success : inProgress ? theme.warning : theme.textMuted,
|
|
4306
|
+
flexShrink: 0,
|
|
4307
|
+
ref: (ref) => { sidebarTodoMarkers[index] = ref; },
|
|
4308
|
+
}, completed ? "✓" : inProgress ? "◉" : "○"), h("text", {
|
|
4309
|
+
fg: completed ? theme.success : inProgress ? theme.warning : theme.textMuted,
|
|
4310
|
+
wrapMode: "word",
|
|
4311
|
+
ref: (ref) => { sidebarTodoLabels[index] = ref; },
|
|
4312
|
+
}, labelText));
|
|
4247
4313
|
}));
|
|
4248
4314
|
}
|
|
4249
4315
|
function renderSidebarFiles(files) {
|
|
@@ -5249,10 +5315,50 @@ function createModelSwitchEntry(ctx, model, key, signature) {
|
|
|
5249
5315
|
]);
|
|
5250
5316
|
return { key, signature, node, refs: {} };
|
|
5251
5317
|
}
|
|
5318
|
+
function createTodoWriteRenderable(ctx, tool) {
|
|
5319
|
+
const todos = tool.args.todos || [];
|
|
5320
|
+
const summary = tool.result || "";
|
|
5321
|
+
if (!isToolFinished(tool)) {
|
|
5322
|
+
return createBox(ctx, {
|
|
5323
|
+
paddingLeft: 3,
|
|
5324
|
+
marginTop: 1,
|
|
5325
|
+
flexDirection: "column",
|
|
5326
|
+
flexShrink: 0,
|
|
5327
|
+
}, [
|
|
5328
|
+
createText(ctx, `~ → Planning tasks...`, { fg: toolColor(tool) }),
|
|
5329
|
+
]);
|
|
5330
|
+
}
|
|
5331
|
+
return createBox(ctx, {
|
|
5332
|
+
border: ["left"],
|
|
5333
|
+
borderColor: theme.borderSubtle,
|
|
5334
|
+
backgroundColor: theme.backgroundPanel,
|
|
5335
|
+
marginTop: 1,
|
|
5336
|
+
paddingTop: 1,
|
|
5337
|
+
paddingBottom: 1,
|
|
5338
|
+
paddingLeft: 2,
|
|
5339
|
+
flexDirection: "column",
|
|
5340
|
+
flexShrink: 0,
|
|
5341
|
+
}, [
|
|
5342
|
+
createText(ctx, `# Todo ${summary ? `— ${summary}` : ""}`, { fg: theme.textMuted }),
|
|
5343
|
+
...todos.map((todo, index) => {
|
|
5344
|
+
const completed = todo.status === "completed";
|
|
5345
|
+
const inProgress = todo.status === "in_progress";
|
|
5346
|
+
const marker = completed ? "✓" : inProgress ? "◉" : "○";
|
|
5347
|
+
const fg = completed ? theme.success : inProgress ? theme.warning : theme.textMuted;
|
|
5348
|
+
return createText(ctx, ` ${marker} ${todo.content}`, {
|
|
5349
|
+
fg,
|
|
5350
|
+
marginTop: index === 0 ? 1 : 0,
|
|
5351
|
+
});
|
|
5352
|
+
}),
|
|
5353
|
+
]);
|
|
5354
|
+
}
|
|
5252
5355
|
function createToolRenderable(ctx, tool, syntaxStyle, width = 80) {
|
|
5253
5356
|
if (tool.name === "question") {
|
|
5254
5357
|
return createQuestionToolRenderable(ctx, tool);
|
|
5255
5358
|
}
|
|
5359
|
+
if (tool.name === "todo_write") {
|
|
5360
|
+
return createTodoWriteRenderable(ctx, tool);
|
|
5361
|
+
}
|
|
5256
5362
|
const icon = tool.name === "bash" ? "$" : tool.name === "edit" || tool.name === "write" ? "✎" : "●";
|
|
5257
5363
|
const color = toolColor(tool);
|
|
5258
5364
|
const header = toolHeader(tool);
|
|
@@ -5988,8 +6094,10 @@ function extractToolDiff(tool) {
|
|
|
5988
6094
|
const index = tool.result.indexOf(marker);
|
|
5989
6095
|
if (index === -1)
|
|
5990
6096
|
return undefined;
|
|
5991
|
-
const
|
|
5992
|
-
|
|
6097
|
+
const rawDiff = tool.result.slice(index + marker.length);
|
|
6098
|
+
const diagnosticsIndex = rawDiff.search(/\n\nLSP diagnostics in /);
|
|
6099
|
+
const diff = diagnosticsIndex === -1 ? rawDiff : rawDiff.slice(0, diagnosticsIndex);
|
|
6100
|
+
return diff.trim().length > 0 ? diff : undefined;
|
|
5993
6101
|
}
|
|
5994
6102
|
function diffViewMode(width = 80) {
|
|
5995
6103
|
return width > 120 ? "split" : "unified";
|
package/package.json
CHANGED