@bubblebrain-ai/bubble 0.0.8 → 0.0.10
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/agent/categories.d.ts +34 -0
- package/dist/agent/categories.js +98 -0
- package/dist/agent/profiles.d.ts +4 -0
- package/dist/agent/profiles.js +2 -3
- package/dist/agent/subagent-control.d.ts +5 -0
- package/dist/agent/subagent-control.js +4 -0
- package/dist/agent/subagent-lifecycle-reminder.d.ts +3 -0
- package/dist/agent/subagent-lifecycle-reminder.js +102 -0
- package/dist/agent/subagent-route-format.d.ts +8 -0
- package/dist/agent/subagent-route-format.js +18 -0
- package/dist/agent/subtask-policy.d.ts +0 -1
- package/dist/agent/subtask-policy.js +0 -4
- package/dist/agent.d.ts +12 -0
- package/dist/agent.js +152 -13
- package/dist/config.d.ts +23 -3
- package/dist/config.js +59 -6
- package/dist/context/budget.d.ts +3 -3
- package/dist/context/budget.js +29 -15
- package/dist/context/compact.d.ts +23 -0
- package/dist/context/compact.js +129 -0
- package/dist/context/llm-compactor.d.ts +19 -0
- package/dist/context/llm-compactor.js +200 -0
- package/dist/context/projector.js +28 -12
- package/dist/context/token-estimator.d.ts +14 -0
- package/dist/context/token-estimator.js +106 -0
- package/dist/context/tool-output-truncate.d.ts +8 -0
- package/dist/context/tool-output-truncate.js +59 -0
- package/dist/context/usage.js +9 -9
- package/dist/main.js +43 -6
- package/dist/model-catalog.d.ts +9 -0
- package/dist/model-catalog.js +16 -0
- package/dist/orchestrator/default-hooks.js +18 -0
- package/dist/provider-openai-codex.d.ts +13 -2
- package/dist/provider-openai-codex.js +81 -32
- package/dist/provider-registry.js +20 -4
- package/dist/slash-commands/commands.js +24 -0
- package/dist/slash-commands/types.d.ts +7 -0
- package/dist/tools/agent-lifecycle.js +22 -4
- package/dist/tools/edit.js +2 -2
- package/dist/tools/glob.js +2 -1
- package/dist/tools/grep.js +2 -2
- package/dist/tools/lsp.js +2 -2
- package/dist/tools/path-utils.d.ts +2 -0
- package/dist/tools/path-utils.js +16 -0
- package/dist/tools/read.js +117 -5
- package/dist/tools/write.js +3 -2
- package/dist/tui-ink/app.d.ts +11 -2
- package/dist/tui-ink/app.js +191 -78
- package/dist/tui-ink/approval/approval-dialog.js +4 -1
- package/dist/tui-ink/approval/diff-view.js +2 -1
- package/dist/tui-ink/approval/select.js +2 -1
- package/dist/tui-ink/code-highlight.d.ts +2 -0
- package/dist/tui-ink/code-highlight.js +30 -2
- package/dist/tui-ink/detect-theme.d.ts +19 -0
- package/dist/tui-ink/detect-theme.js +123 -0
- package/dist/tui-ink/footer.js +4 -3
- package/dist/tui-ink/input-box.js +83 -26
- package/dist/tui-ink/input-history.d.ts +16 -0
- package/dist/tui-ink/input-history.js +81 -0
- package/dist/tui-ink/markdown.js +30 -20
- package/dist/tui-ink/message-list.js +112 -16
- package/dist/tui-ink/model-picker.js +6 -1
- package/dist/tui-ink/plan-confirm.js +2 -1
- package/dist/tui-ink/question-dialog.js +2 -1
- package/dist/tui-ink/run.d.ts +5 -1
- package/dist/tui-ink/run.js +30 -2
- package/dist/tui-ink/theme.d.ts +64 -35
- package/dist/tui-ink/theme.js +81 -8
- package/dist/tui-ink/todos.js +5 -3
- package/dist/tui-ink/trace-groups.d.ts +3 -1
- package/dist/tui-ink/trace-groups.js +93 -14
- package/dist/tui-ink/welcome.js +23 -4
- package/dist/types.d.ts +6 -0
- package/package.json +2 -1
package/dist/tui-ink/todos.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { Box, Text } from "ink";
|
|
3
|
-
import {
|
|
3
|
+
import { useTheme } from "./theme.js";
|
|
4
4
|
const MAX_ROWS = 8;
|
|
5
5
|
export function TodosPanel({ todos, terminalColumns }) {
|
|
6
|
+
const theme = useTheme();
|
|
6
7
|
if (todos.length === 0) {
|
|
7
8
|
return null;
|
|
8
9
|
}
|
|
@@ -28,12 +29,13 @@ function selectVisibleRows(todos) {
|
|
|
28
29
|
return todos.slice(start, end);
|
|
29
30
|
}
|
|
30
31
|
function TodoRow({ todo, maxWidth }) {
|
|
31
|
-
const
|
|
32
|
+
const theme = useTheme();
|
|
33
|
+
const { glyph, color, dim, label } = statusStyle(todo, theme);
|
|
32
34
|
const text = label || todo.content;
|
|
33
35
|
const trimmed = text.length > maxWidth - 4 ? text.slice(0, maxWidth - 5) + "…" : text;
|
|
34
36
|
return (_jsx(Box, { height: 1, children: _jsxs(Text, { color: color, dimColor: dim, children: [glyph, " ", trimmed] }) }));
|
|
35
37
|
}
|
|
36
|
-
function statusStyle(todo) {
|
|
38
|
+
function statusStyle(todo, theme) {
|
|
37
39
|
if (todo.status === "completed") {
|
|
38
40
|
return { glyph: "✔", color: theme.muted, dim: true, label: todo.content };
|
|
39
41
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { DisplayToolCall } from "./display-history.js";
|
|
2
|
-
export type TraceGroupKind = "list" | "read" | "search" | "execute" | "edit" | "write" | "other";
|
|
2
|
+
export type TraceGroupKind = "list" | "read" | "search" | "execute" | "edit" | "write" | "subagent" | "other";
|
|
3
3
|
export interface TraceGroup {
|
|
4
4
|
kind: TraceGroupKind;
|
|
5
5
|
title: string;
|
|
@@ -9,9 +9,11 @@ export interface TraceGroup {
|
|
|
9
9
|
command?: string;
|
|
10
10
|
items: string[];
|
|
11
11
|
previewLines: string[];
|
|
12
|
+
errorLines: string[];
|
|
12
13
|
omitted: number;
|
|
13
14
|
pending: boolean;
|
|
14
15
|
hasError: boolean;
|
|
16
|
+
errorCount: number;
|
|
15
17
|
startedAt?: number;
|
|
16
18
|
}
|
|
17
19
|
export interface TraceGroupOptions {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import os from "node:os";
|
|
2
2
|
import { getEditDiffDetails } from "./edit-diff.js";
|
|
3
|
+
import { formatSubagentRoute } from "../agent/subagent-route-format.js";
|
|
3
4
|
const DEFAULT_MAX_ITEMS = 6;
|
|
4
5
|
const DEFAULT_MAX_PREVIEW_LINES = 8;
|
|
5
6
|
export function buildTraceGroups(toolCalls, options = {}) {
|
|
@@ -71,6 +72,9 @@ export function traceGroupLabel(group) {
|
|
|
71
72
|
return group.title;
|
|
72
73
|
}
|
|
73
74
|
function classifyTool(toolCall) {
|
|
75
|
+
if (toolCall.metadata?.kind === "subagent") {
|
|
76
|
+
return { kind: "subagent", title: "Subagents", bucketKey: `subagent:${toolCall.id}`, groupable: false };
|
|
77
|
+
}
|
|
74
78
|
switch (toolCall.name) {
|
|
75
79
|
case "glob": {
|
|
76
80
|
const pattern = String(toolCall.args.pattern ?? "");
|
|
@@ -109,23 +113,26 @@ function buildTraceGroup(classifier, raw, options) {
|
|
|
109
113
|
.filter((value) => typeof value === "number")
|
|
110
114
|
.sort((a, b) => a - b)[0];
|
|
111
115
|
const hasError = raw.some((tool) => !!tool.isError);
|
|
116
|
+
const errorCount = raw.filter((tool) => !!tool.isError).length;
|
|
112
117
|
switch (classifier.kind) {
|
|
113
118
|
case "list":
|
|
114
|
-
return buildListGroup(classifier, raw, options, pending, startedAt, hasError);
|
|
119
|
+
return buildListGroup(classifier, raw, options, pending, startedAt, hasError, errorCount);
|
|
115
120
|
case "read":
|
|
116
|
-
return buildPathGroup(classifier, raw, options, pending, startedAt, hasError, "files");
|
|
121
|
+
return buildPathGroup(classifier, raw, options, pending, startedAt, hasError, errorCount, "files");
|
|
117
122
|
case "search":
|
|
118
|
-
return buildSearchGroup(classifier, raw, options, pending, startedAt, hasError);
|
|
123
|
+
return buildSearchGroup(classifier, raw, options, pending, startedAt, hasError, errorCount);
|
|
119
124
|
case "execute":
|
|
120
|
-
return buildExecuteGroup(classifier, raw[0], options, pending, startedAt, hasError);
|
|
125
|
+
return buildExecuteGroup(classifier, raw[0], options, pending, startedAt, hasError, errorCount);
|
|
121
126
|
case "edit":
|
|
122
127
|
case "write":
|
|
123
|
-
return buildMutationGroup(classifier, raw, options, pending, startedAt, hasError);
|
|
128
|
+
return buildMutationGroup(classifier, raw, options, pending, startedAt, hasError, errorCount);
|
|
129
|
+
case "subagent":
|
|
130
|
+
return buildSubagentGroup(classifier, raw[0], options, pending, startedAt);
|
|
124
131
|
default:
|
|
125
|
-
return buildOtherGroup(classifier, raw, options, pending, startedAt, hasError);
|
|
132
|
+
return buildOtherGroup(classifier, raw, options, pending, startedAt, hasError, errorCount);
|
|
126
133
|
}
|
|
127
134
|
}
|
|
128
|
-
function buildListGroup(classifier, raw, options, pending, startedAt, hasError) {
|
|
135
|
+
function buildListGroup(classifier, raw, options, pending, startedAt, hasError, errorCount) {
|
|
129
136
|
const resultItems = raw.flatMap((tool) => resultLines(tool.result).map((line) => formatTracePath(line, options.homeDir)));
|
|
130
137
|
const fallbackItems = raw
|
|
131
138
|
.map((tool) => String(tool.args.pattern ?? tool.args.path ?? "").trim())
|
|
@@ -143,16 +150,18 @@ function buildListGroup(classifier, raw, options, pending, startedAt, hasError)
|
|
|
143
150
|
noun,
|
|
144
151
|
items: shown,
|
|
145
152
|
previewLines: [],
|
|
153
|
+
errorLines: collectErrorLines(raw, options),
|
|
146
154
|
omitted,
|
|
147
155
|
pending,
|
|
148
156
|
hasError,
|
|
157
|
+
errorCount,
|
|
149
158
|
startedAt,
|
|
150
159
|
};
|
|
151
160
|
}
|
|
152
|
-
function buildPathGroup(classifier, raw, options, pending, startedAt, hasError, nounBase) {
|
|
153
|
-
const items = raw
|
|
161
|
+
function buildPathGroup(classifier, raw, options, pending, startedAt, hasError, errorCount, nounBase) {
|
|
162
|
+
const items = unique(raw
|
|
154
163
|
.map((tool) => formatTracePath(tool.args.path ?? tool.args.file ?? "", options.homeDir))
|
|
155
|
-
.filter(Boolean);
|
|
164
|
+
.filter(Boolean));
|
|
156
165
|
const { shown, omitted } = take(items, options.maxItems);
|
|
157
166
|
const count = items.length || raw.length;
|
|
158
167
|
return {
|
|
@@ -163,13 +172,15 @@ function buildPathGroup(classifier, raw, options, pending, startedAt, hasError,
|
|
|
163
172
|
noun: plural(count, nounBase.slice(0, -1), nounBase),
|
|
164
173
|
items: shown,
|
|
165
174
|
previewLines: [],
|
|
175
|
+
errorLines: collectErrorLines(raw, options),
|
|
166
176
|
omitted,
|
|
167
177
|
pending,
|
|
168
178
|
hasError,
|
|
179
|
+
errorCount,
|
|
169
180
|
startedAt,
|
|
170
181
|
};
|
|
171
182
|
}
|
|
172
|
-
function buildSearchGroup(classifier, raw, options, pending, startedAt, hasError) {
|
|
183
|
+
function buildSearchGroup(classifier, raw, options, pending, startedAt, hasError, errorCount) {
|
|
173
184
|
const items = raw.map((tool) => {
|
|
174
185
|
const pattern = String(tool.args.pattern ?? tool.args.query ?? "").trim();
|
|
175
186
|
const scope = String(tool.args.path ?? tool.args.glob ?? tool.args.include ?? "").trim();
|
|
@@ -186,13 +197,15 @@ function buildSearchGroup(classifier, raw, options, pending, startedAt, hasError
|
|
|
186
197
|
noun: plural(count, "search", "searches"),
|
|
187
198
|
items: shown,
|
|
188
199
|
previewLines: [],
|
|
200
|
+
errorLines: collectErrorLines(raw, options),
|
|
189
201
|
omitted,
|
|
190
202
|
pending,
|
|
191
203
|
hasError,
|
|
204
|
+
errorCount,
|
|
192
205
|
startedAt,
|
|
193
206
|
};
|
|
194
207
|
}
|
|
195
|
-
function buildExecuteGroup(classifier, tool, options, pending, startedAt, hasError) {
|
|
208
|
+
function buildExecuteGroup(classifier, tool, options, pending, startedAt, hasError, errorCount) {
|
|
196
209
|
const lines = resultLines(tool.result).map((line) => formatTracePath(line, options.homeDir));
|
|
197
210
|
const { shown, omitted } = take(lines, options.maxPreviewLines);
|
|
198
211
|
return {
|
|
@@ -202,13 +215,15 @@ function buildExecuteGroup(classifier, tool, options, pending, startedAt, hasErr
|
|
|
202
215
|
command: normalizeCommand(tool.args.command ?? ""),
|
|
203
216
|
items: [],
|
|
204
217
|
previewLines: shown,
|
|
218
|
+
errorLines: [],
|
|
205
219
|
omitted,
|
|
206
220
|
pending,
|
|
207
221
|
hasError,
|
|
222
|
+
errorCount,
|
|
208
223
|
startedAt,
|
|
209
224
|
};
|
|
210
225
|
}
|
|
211
|
-
function buildMutationGroup(classifier, raw, options, pending, startedAt, hasError) {
|
|
226
|
+
function buildMutationGroup(classifier, raw, options, pending, startedAt, hasError, errorCount) {
|
|
212
227
|
const items = raw
|
|
213
228
|
.map((tool) => {
|
|
214
229
|
const path = formatTracePath(tool.args.path ?? "", options.homeDir);
|
|
@@ -233,13 +248,38 @@ function buildMutationGroup(classifier, raw, options, pending, startedAt, hasErr
|
|
|
233
248
|
noun: plural(count, "file", "files"),
|
|
234
249
|
items: shown,
|
|
235
250
|
previewLines: errorPreview,
|
|
251
|
+
errorLines: [],
|
|
236
252
|
omitted,
|
|
237
253
|
pending,
|
|
238
254
|
hasError,
|
|
255
|
+
errorCount,
|
|
239
256
|
startedAt,
|
|
240
257
|
};
|
|
241
258
|
}
|
|
242
|
-
function
|
|
259
|
+
function buildSubagentGroup(classifier, tool, options, pending, startedAt) {
|
|
260
|
+
const subagents = subagentsFromMetadata(tool);
|
|
261
|
+
const rows = subagents.length > 0
|
|
262
|
+
? subagents.map(formatSubagentRow)
|
|
263
|
+
: resultLines(tool.result).map((line) => formatTracePath(line, options.homeDir));
|
|
264
|
+
const { shown, omitted } = take(rows, options.maxPreviewLines);
|
|
265
|
+
const errorCount = subagents.filter(isFailedSubagent).length + (tool.isError ? 1 : 0);
|
|
266
|
+
return {
|
|
267
|
+
kind: "subagent",
|
|
268
|
+
title: classifier.title,
|
|
269
|
+
raw: [tool],
|
|
270
|
+
count: subagents.length || 1,
|
|
271
|
+
noun: plural(subagents.length || 1, "agent", "agents"),
|
|
272
|
+
items: [],
|
|
273
|
+
previewLines: shown,
|
|
274
|
+
errorLines: [],
|
|
275
|
+
omitted,
|
|
276
|
+
pending: pending || subagents.some((subagent) => ["queued", "running"].includes(subagent.status ?? "running")),
|
|
277
|
+
hasError: !!tool.isError || errorCount > 0,
|
|
278
|
+
errorCount,
|
|
279
|
+
startedAt,
|
|
280
|
+
};
|
|
281
|
+
}
|
|
282
|
+
function buildOtherGroup(classifier, raw, options, pending, startedAt, hasError, errorCount) {
|
|
243
283
|
const tool = raw[0];
|
|
244
284
|
const header = toolHeader(tool, options.homeDir);
|
|
245
285
|
const preview = resultLines(tool.result).map((line) => formatTracePath(line, options.homeDir));
|
|
@@ -252,12 +292,36 @@ function buildOtherGroup(classifier, raw, options, pending, startedAt, hasError)
|
|
|
252
292
|
noun: header ? undefined : plural(raw.length, "call", "calls"),
|
|
253
293
|
items: header ? [header] : [],
|
|
254
294
|
previewLines: shown,
|
|
295
|
+
errorLines: [],
|
|
255
296
|
omitted,
|
|
256
297
|
pending,
|
|
257
298
|
hasError,
|
|
299
|
+
errorCount,
|
|
258
300
|
startedAt,
|
|
259
301
|
};
|
|
260
302
|
}
|
|
303
|
+
function subagentsFromMetadata(tool) {
|
|
304
|
+
const raw = tool.metadata?.subagents;
|
|
305
|
+
if (!Array.isArray(raw))
|
|
306
|
+
return [];
|
|
307
|
+
return raw.filter((item) => typeof item === "object" && item !== null);
|
|
308
|
+
}
|
|
309
|
+
function formatSubagentRow(subagent) {
|
|
310
|
+
const label = subagent.nickname || subagent.agentName || subagent.subAgentId || "subagent";
|
|
311
|
+
const role = [subagent.agentName, subagent.category ? `/${subagent.category}` : ""].join("") || "default";
|
|
312
|
+
const route = formatSubagentRoute(subagent.route);
|
|
313
|
+
const descriptor = route ? `${role} @ ${route}` : role;
|
|
314
|
+
const status = subagent.status || "running";
|
|
315
|
+
const note = subagent.error
|
|
316
|
+
|| subagent.toolNotes?.filter(Boolean).at(-1)
|
|
317
|
+
|| subagent.summary
|
|
318
|
+
|| subagent.task
|
|
319
|
+
|| "";
|
|
320
|
+
return [label, `(${descriptor})`, status, note].filter(Boolean).join(" ");
|
|
321
|
+
}
|
|
322
|
+
function isFailedSubagent(subagent) {
|
|
323
|
+
return subagent.status === "failed" || subagent.status === "blocked" || subagent.status === "cancelled";
|
|
324
|
+
}
|
|
261
325
|
function isToolPending(tool) {
|
|
262
326
|
return tool.result === undefined;
|
|
263
327
|
}
|
|
@@ -278,6 +342,21 @@ function take(items, max) {
|
|
|
278
342
|
const shown = items.slice(0, max);
|
|
279
343
|
return { shown, omitted: Math.max(0, items.length - shown.length) };
|
|
280
344
|
}
|
|
345
|
+
function unique(items) {
|
|
346
|
+
return [...new Set(items)];
|
|
347
|
+
}
|
|
348
|
+
function collectErrorLines(raw, options) {
|
|
349
|
+
return raw
|
|
350
|
+
.filter((tool) => tool.isError)
|
|
351
|
+
.flatMap((tool) => resultLines(tool.result).map((line) => formatTraceLine(line, options.homeDir)))
|
|
352
|
+
.slice(0, options.maxPreviewLines);
|
|
353
|
+
}
|
|
354
|
+
function formatTraceLine(value, homeDir) {
|
|
355
|
+
const text = String(value ?? "").trimEnd();
|
|
356
|
+
if (!homeDir)
|
|
357
|
+
return text;
|
|
358
|
+
return text.split(homeDir + "/").join("~/").split(homeDir).join("~");
|
|
359
|
+
}
|
|
281
360
|
function plural(count, singular, pluralValue) {
|
|
282
361
|
return count === 1 ? singular : pluralValue;
|
|
283
362
|
}
|
package/dist/tui-ink/welcome.js
CHANGED
|
@@ -2,7 +2,7 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
|
|
|
2
2
|
import React from "react";
|
|
3
3
|
import { Box, Text } from "ink";
|
|
4
4
|
import { createRequire } from "node:module";
|
|
5
|
-
import {
|
|
5
|
+
import { useTheme } from "./theme.js";
|
|
6
6
|
const require = createRequire(import.meta.url);
|
|
7
7
|
const PACKAGE_VERSION = readPackageVersion();
|
|
8
8
|
const BUBBLE_LOGO_LETTERS = [
|
|
@@ -61,7 +61,20 @@ const BUBBLE_LOGO_LETTERS = [
|
|
|
61
61
|
"███████",
|
|
62
62
|
],
|
|
63
63
|
];
|
|
64
|
-
|
|
64
|
+
/**
|
|
65
|
+
* Derive a 6-step logo gradient from the active theme tokens so the banner
|
|
66
|
+
* stays readable on both dark and light backgrounds.
|
|
67
|
+
*/
|
|
68
|
+
function logoColors(theme) {
|
|
69
|
+
return [
|
|
70
|
+
theme.userMessageText,
|
|
71
|
+
theme.userMessageText,
|
|
72
|
+
theme.inputBorder,
|
|
73
|
+
theme.inputBorder,
|
|
74
|
+
theme.traceCommand,
|
|
75
|
+
theme.traceCommand,
|
|
76
|
+
];
|
|
77
|
+
}
|
|
65
78
|
const COMPACT_LOGO = ["B", "U", "B", "B", "L", "E"];
|
|
66
79
|
const WIDE_LOGO_MIN_WIDTH = 52;
|
|
67
80
|
export function shouldShowWelcomeBanner({ startedWithVisibleHistory, }) {
|
|
@@ -74,6 +87,7 @@ export function shouldShowWelcomeBanner({ startedWithVisibleHistory, }) {
|
|
|
74
87
|
return true;
|
|
75
88
|
}
|
|
76
89
|
export function WelcomeBanner({ terminalColumns, modelLabel, cwd, tips, skillsCount = 0, mcpConnectedCount = 0, mcpTotalCount = 0, hasAgentsFile = false, }) {
|
|
90
|
+
const theme = useTheme();
|
|
77
91
|
const effectiveWidth = Math.max(20, Math.min(terminalColumns - 2, 118));
|
|
78
92
|
const useWideLogo = effectiveWidth >= WIDE_LOGO_MIN_WIDTH;
|
|
79
93
|
const actionableTips = tips
|
|
@@ -88,12 +102,17 @@ export function WelcomeBanner({ terminalColumns, modelLabel, cwd, tips, skillsCo
|
|
|
88
102
|
: _jsx(CompactLogo, {}) }), _jsx(Box, { marginTop: 2, children: _jsx(Text, { bold: true, color: theme.muted, children: PACKAGE_VERSION }) }), _jsxs(Box, { marginTop: 1, children: [_jsx(Text, { bold: true, color: theme.userMessageText, children: "TIP: " }), _jsx(Text, { bold: true, color: theme.userMessageText, children: tip })] }), _jsx(Box, { marginTop: 1, children: _jsx(Text, { color: theme.muted, children: "shift+tab to cycle modes \u00B7 ctrl+r for reasoning \u00B7 ctrl+o for trace" }) }), modelLine && (_jsx(Box, { children: _jsx(Text, { color: theme.muted, children: truncateToWidth(modelLine, effectiveWidth - 4) }) })), _jsxs(Box, { marginTop: 1, children: [_jsx(StatusItem, { label: "Skills", count: skillsCount, ok: skillsCount > 0 }), _jsx(Text, { color: theme.muted, children: " " }), _jsx(StatusItem, { label: "MCPs", count: mcpConnectedCount, total: mcpTotalCount, ok: mcpTotalCount === 0 || mcpConnectedCount === mcpTotalCount }), _jsx(Text, { color: theme.muted, children: " " }), _jsx(StatusItem, { label: "AGENTS.md", ok: hasAgentsFile })] })] }));
|
|
89
103
|
}
|
|
90
104
|
function LogoRow({ rowIndex }) {
|
|
91
|
-
|
|
105
|
+
const theme = useTheme();
|
|
106
|
+
const colors = logoColors(theme);
|
|
107
|
+
return (_jsx(Box, { children: BUBBLE_LOGO_LETTERS.map((letter, index) => (_jsxs(React.Fragment, { children: [_jsx(Text, { bold: true, color: colors[index], children: letter[rowIndex] }), index < BUBBLE_LOGO_LETTERS.length - 1 && _jsx(Text, { children: " " })] }, `${index}-${rowIndex}`))) }));
|
|
92
108
|
}
|
|
93
109
|
function CompactLogo() {
|
|
94
|
-
|
|
110
|
+
const theme = useTheme();
|
|
111
|
+
const colors = logoColors(theme);
|
|
112
|
+
return (_jsx(Box, { children: COMPACT_LOGO.map((letter, index) => (_jsx(Text, { bold: true, color: colors[index], children: letter }, `${letter}-${index}`))) }));
|
|
95
113
|
}
|
|
96
114
|
function StatusItem({ label, count, total, ok, }) {
|
|
115
|
+
const theme = useTheme();
|
|
97
116
|
const countText = count === undefined
|
|
98
117
|
? ""
|
|
99
118
|
: total !== undefined && total > count
|
package/dist/types.d.ts
CHANGED
|
@@ -120,6 +120,8 @@ export interface ToolUpdate {
|
|
|
120
120
|
subAgentId: string;
|
|
121
121
|
agentName: string;
|
|
122
122
|
nickname?: string;
|
|
123
|
+
category?: string;
|
|
124
|
+
route?: import("./agent/categories.js").ResolvedSubagentRoute;
|
|
123
125
|
status: "queued" | "running" | "completed" | "failed" | "blocked" | "cancelled";
|
|
124
126
|
childEvent?: AgentEvent;
|
|
125
127
|
summaryDelta?: string;
|
|
@@ -147,6 +149,8 @@ export interface ToolContext {
|
|
|
147
149
|
runId: string;
|
|
148
150
|
subAgentId: string;
|
|
149
151
|
parentToolCallId: string;
|
|
152
|
+
category?: string;
|
|
153
|
+
route?: import("./agent/categories.js").ResolvedSubagentRoute;
|
|
150
154
|
approval?: "fail" | "disabled";
|
|
151
155
|
emitUpdate?: (update: ToolUpdate) => void;
|
|
152
156
|
description?: string;
|
|
@@ -157,6 +161,8 @@ export interface ToolContext {
|
|
|
157
161
|
spawnSubAgent?: (input: string | ContentPart[], cwd: string, options: {
|
|
158
162
|
profile: import("./agent/profiles.js").AgentProfile;
|
|
159
163
|
parentToolCallId: string;
|
|
164
|
+
category?: string;
|
|
165
|
+
route?: import("./agent/categories.js").ResolvedSubagentRoute;
|
|
160
166
|
approval?: "fail" | "disabled";
|
|
161
167
|
description?: string;
|
|
162
168
|
abortSignal?: AbortSignal;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bubblebrain-ai/bubble",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.10",
|
|
4
4
|
"description": "A terminal coding agent",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"engines": {
|
|
@@ -33,6 +33,7 @@
|
|
|
33
33
|
"chalk": "^5.3.0",
|
|
34
34
|
"diff": "^7.0.0",
|
|
35
35
|
"ink": "^7.0.3",
|
|
36
|
+
"js-tiktoken": "^1.0.21",
|
|
36
37
|
"openai": "^4.77.0",
|
|
37
38
|
"opentui-spinner": "^0.0.6",
|
|
38
39
|
"picomatch": "^4.0.4",
|