@bubblebrain-ai/bubble 0.0.34 → 0.0.36
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 +27 -7
- package/dist/agent/abort-errors.d.ts +2 -2
- package/dist/agent/budget-ledger.d.ts +4 -45
- package/dist/agent/budget-ledger.js +5 -75
- package/dist/agent/categories.d.ts +66 -2
- package/dist/agent/categories.js +120 -19
- package/dist/agent/child-runner.d.ts +1 -3
- package/dist/agent/child-runner.js +6 -37
- package/dist/agent/discovery-barrier.js +1 -1
- package/dist/agent/profiles.d.ts +1 -2
- package/dist/agent/profiles.js +25 -14
- package/dist/agent/routing-catalog.d.ts +113 -0
- package/dist/agent/routing-catalog.js +240 -0
- package/dist/agent/subagent-control.d.ts +5 -12
- package/dist/agent/subagent-control.js +0 -2
- package/dist/agent/subagent-store.d.ts +1 -1
- package/dist/agent/subagent-store.js +1 -3
- package/dist/agent/workflow/control.d.ts +21 -0
- package/dist/agent/workflow/control.js +50 -8
- package/dist/agent/workflow/runtime.d.ts +15 -2
- package/dist/agent/workflow/runtime.js +112 -30
- package/dist/agent.d.ts +82 -48
- package/dist/agent.js +360 -232
- package/dist/approval/controller.js +28 -0
- package/dist/approval/tool-helper.js +2 -0
- package/dist/approval/types.d.ts +21 -1
- package/dist/cli.d.ts +1 -1
- package/dist/cli.js +2 -1
- package/dist/config.d.ts +5 -3
- package/dist/config.js +10 -5
- package/dist/context/compact-llm.d.ts +2 -2
- package/dist/external-runtime/grok-acp.d.ts +56 -0
- package/dist/external-runtime/grok-acp.js +386 -0
- package/dist/external-runtime/grok-binary.d.ts +25 -0
- package/dist/external-runtime/grok-binary.js +108 -0
- package/dist/external-runtime/grok-errors.d.ts +7 -0
- package/dist/external-runtime/grok-errors.js +15 -0
- package/dist/external-runtime/grok-input-policy.d.ts +58 -0
- package/dist/external-runtime/grok-input-policy.js +52 -0
- package/dist/external-runtime/grok-ndjson.d.ts +14 -0
- package/dist/external-runtime/grok-ndjson.js +193 -0
- package/dist/external-runtime/grok-network.d.ts +15 -0
- package/dist/external-runtime/grok-network.js +81 -0
- package/dist/external-runtime/grok-preflight.d.ts +28 -0
- package/dist/external-runtime/grok-preflight.js +194 -0
- package/dist/external-runtime/grok-process.d.ts +26 -0
- package/dist/external-runtime/grok-process.js +184 -0
- package/dist/external-runtime/grok-profile.d.ts +32 -0
- package/dist/external-runtime/grok-profile.js +419 -0
- package/dist/external-runtime/grok-provider.d.ts +31 -0
- package/dist/external-runtime/grok-provider.js +41 -0
- package/dist/external-runtime/grok-runtime.d.ts +91 -0
- package/dist/external-runtime/grok-runtime.js +882 -0
- package/dist/external-runtime/index.d.ts +13 -0
- package/dist/external-runtime/index.js +13 -0
- package/dist/external-runtime/session-policy.d.ts +11 -0
- package/dist/external-runtime/session-policy.js +30 -0
- package/dist/external-runtime/types.d.ts +65 -0
- package/dist/external-runtime/types.js +1 -0
- package/dist/feishu/agent-host/approval-card.js +21 -0
- package/dist/feishu/agent-host/run-driver.js +19 -3
- package/dist/feishu/serve.js +1 -0
- package/dist/goal/tools.d.ts +6 -3
- package/dist/goal/tools.js +7 -19
- package/dist/main.js +114 -28
- package/dist/memory/db.d.ts +2 -0
- package/dist/memory/db.js +10 -0
- package/dist/memory/index.d.ts +1 -0
- package/dist/memory/index.js +1 -0
- package/dist/memory/phase1.js +14 -2
- package/dist/memory/phase2.js +21 -2
- package/dist/memory/prompts.js +1 -1
- package/dist/memory/session-policy.d.ts +25 -0
- package/dist/memory/session-policy.js +55 -0
- package/dist/memory/storage.d.ts +1 -0
- package/dist/memory/storage.js +13 -0
- package/dist/model-catalog.d.ts +18 -0
- package/dist/model-catalog.js +92 -52
- package/dist/model-config.d.ts +3 -1
- package/dist/model-config.js +11 -0
- package/dist/oauth/grok.d.ts +25 -0
- package/dist/oauth/grok.js +218 -0
- package/dist/oauth/index.d.ts +1 -0
- package/dist/oauth/index.js +1 -0
- package/dist/oauth/storage.d.ts +9 -0
- package/dist/oauth/storage.js +25 -0
- package/dist/orchestrator/default-hooks.js +23 -7
- package/dist/prompt/compose.d.ts +3 -0
- package/dist/prompt/compose.js +3 -0
- package/dist/prompt/delegation.d.ts +1 -1
- package/dist/prompt/delegation.js +41 -8
- package/dist/prompt/environment.js +0 -4
- package/dist/prompt/reminders.d.ts +0 -1
- package/dist/prompt/reminders.js +1 -11
- package/dist/prompt/routing.d.ts +14 -0
- package/dist/prompt/routing.js +71 -0
- package/dist/prompt/runtime.js +1 -1
- package/dist/prompt/task-reminders.d.ts +20 -0
- package/dist/prompt/task-reminders.js +73 -1
- package/dist/provider-ai-sdk.js +2 -2
- package/dist/provider-grok.d.ts +26 -0
- package/dist/provider-grok.js +59 -0
- package/dist/provider-openai-codex.d.ts +17 -1
- package/dist/provider-openai-codex.js +101 -29
- package/dist/provider-registry.d.ts +72 -0
- package/dist/provider-registry.js +336 -59
- package/dist/provider-transform.d.ts +1 -1
- package/dist/provider-transform.js +35 -17
- package/dist/provider.d.ts +3 -0
- package/dist/provider.js +14 -0
- package/dist/session-types.d.ts +19 -1
- package/dist/session.d.ts +1 -0
- package/dist/session.js +4 -0
- package/dist/slash-commands/commands.js +224 -14
- package/dist/slash-commands/types.d.ts +14 -1
- package/dist/system-prompt.d.ts +2 -0
- package/dist/tools/agent-lifecycle.d.ts +1 -9
- package/dist/tools/agent-lifecycle.js +42 -272
- package/dist/tools/bash.js +1 -1
- package/dist/tools/child-tools.js +2 -0
- package/dist/tools/index.d.ts +2 -2
- package/dist/tools/index.js +7 -5
- package/dist/tools/lsp.js +1 -0
- package/dist/tools/memory.d.ts +7 -2
- package/dist/tools/memory.js +28 -43
- package/dist/tools/server.js +4 -0
- package/dist/tools/tool-search.d.ts +1 -1
- package/dist/tools/tool-search.js +23 -3
- package/dist/tui/model-switch.d.ts +7 -0
- package/dist/tui/model-switch.js +15 -5
- package/dist/tui-ink/app.d.ts +3 -1
- package/dist/tui-ink/app.js +672 -243
- package/dist/tui-ink/approval/approval-dialog.js +37 -1
- package/dist/tui-ink/approval/diff-view.js +4 -4
- package/dist/tui-ink/approval/select.js +2 -2
- package/dist/tui-ink/composer-buffer.d.ts +55 -0
- package/dist/tui-ink/composer-buffer.js +317 -0
- package/dist/tui-ink/feedback-dialog.js +2 -2
- package/dist/tui-ink/feishu-setup-picker.js +3 -3
- package/dist/tui-ink/footer.d.ts +1 -0
- package/dist/tui-ink/footer.js +7 -2
- package/dist/tui-ink/input-box.d.ts +36 -7
- package/dist/tui-ink/input-box.js +229 -157
- package/dist/tui-ink/markdown.js +11 -9
- package/dist/tui-ink/message-list.d.ts +5 -1
- package/dist/tui-ink/message-list.js +15 -2
- package/dist/tui-ink/model-picker.d.ts +61 -4
- package/dist/tui-ink/model-picker.js +464 -128
- package/dist/tui-ink/paste-operation-tracker.d.ts +13 -0
- package/dist/tui-ink/paste-operation-tracker.js +25 -0
- package/dist/tui-ink/plan-confirm.js +1 -1
- package/dist/tui-ink/run.d.ts +3 -0
- package/dist/tui-ink/run.js +1 -1
- package/dist/tui-ink/subagent-view.d.ts +34 -1
- package/dist/tui-ink/subagent-view.js +82 -1
- package/dist/tui-ink/theme.d.ts +19 -2
- package/dist/tui-ink/theme.js +25 -8
- package/dist/tui-ink/welcome.d.ts +3 -2
- package/dist/tui-ink/welcome.js +10 -6
- package/dist/types.d.ts +8 -31
- package/dist/types.js +1 -1
- package/dist/variant/thinking-level.d.ts +2 -2
- package/dist/variant/thinking-level.js +2 -1
- package/dist/variant/variant-resolver.d.ts +22 -0
- package/dist/variant/variant-resolver.js +43 -0
- package/package.json +6 -2
- package/dist/tools/task.d.ts +0 -2
- package/dist/tools/task.js +0 -58
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tracks overlapping paste operations by identity. Finishing an older paste
|
|
3
|
+
* must never clear the pending state of a newer paste.
|
|
4
|
+
*/
|
|
5
|
+
export declare class PasteOperationTracker {
|
|
6
|
+
private nextId;
|
|
7
|
+
private readonly active;
|
|
8
|
+
begin(): number;
|
|
9
|
+
finish(id: number): void;
|
|
10
|
+
invalidateAll(): void;
|
|
11
|
+
get hasPending(): boolean;
|
|
12
|
+
get pendingCount(): number;
|
|
13
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tracks overlapping paste operations by identity. Finishing an older paste
|
|
3
|
+
* must never clear the pending state of a newer paste.
|
|
4
|
+
*/
|
|
5
|
+
export class PasteOperationTracker {
|
|
6
|
+
nextId = 1;
|
|
7
|
+
active = new Set();
|
|
8
|
+
begin() {
|
|
9
|
+
const id = this.nextId++;
|
|
10
|
+
this.active.add(id);
|
|
11
|
+
return id;
|
|
12
|
+
}
|
|
13
|
+
finish(id) {
|
|
14
|
+
this.active.delete(id);
|
|
15
|
+
}
|
|
16
|
+
invalidateAll() {
|
|
17
|
+
this.active.clear();
|
|
18
|
+
}
|
|
19
|
+
get hasPending() {
|
|
20
|
+
return this.active.size > 0;
|
|
21
|
+
}
|
|
22
|
+
get pendingCount() {
|
|
23
|
+
return this.active.size;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
@@ -110,6 +110,6 @@ export function PlanConfirm({ initialPlan, onApprove, onReject }) {
|
|
|
110
110
|
return (_jsx(Text, { children: line || " " }, index));
|
|
111
111
|
}
|
|
112
112
|
const safe = line || " ";
|
|
113
|
-
return (_jsxs(Box, { children: [_jsx(Text, { children: safe.slice(0, cursorCol) }), _jsx(Text, {
|
|
113
|
+
return (_jsxs(Box, { children: [_jsx(Text, { children: safe.slice(0, cursorCol) }), _jsx(Text, { inverse: true, children: safe[cursorCol] || " " }), _jsx(Text, { children: safe.slice(cursorCol + 1) })] }, index));
|
|
114
114
|
}) }), _jsx(Box, { marginTop: 1, children: _jsxs(Text, { color: theme.muted, children: [_jsx(Text, { color: theme.accent, bold: true, children: "\u2303S" }), " save & approve \u00A0\u00A0", _jsx(Text, { color: theme.accent, bold: true, children: "esc" }), " cancel edit"] }) })] }));
|
|
115
115
|
}
|
package/dist/tui-ink/run.d.ts
CHANGED
|
@@ -14,6 +14,7 @@ import type { QuestionController } from "../question/index.js";
|
|
|
14
14
|
import type { MemoryScope } from "../memory/index.js";
|
|
15
15
|
import type { ExternalHookController } from "../hooks/controller.js";
|
|
16
16
|
import type { ResolvedTheme, ThemeMode } from "./theme.js";
|
|
17
|
+
import type { ExternalRuntimeManager } from "../external-runtime/types.js";
|
|
17
18
|
export interface RunTuiOptions {
|
|
18
19
|
sessionManager?: SessionManager;
|
|
19
20
|
createProvider?: (providerId: string, apiKey: string, baseURL: string) => Provider;
|
|
@@ -48,6 +49,8 @@ export interface RunTuiOptions {
|
|
|
48
49
|
updateNoticeRefresh?: Promise<string | null>;
|
|
49
50
|
/** External lifecycle hooks, threaded into slash-command execution. */
|
|
50
51
|
hookController?: ExternalHookController;
|
|
52
|
+
/** Subscription-backed external agent runtime used by the interactive TUI. */
|
|
53
|
+
externalRuntime?: ExternalRuntimeManager;
|
|
51
54
|
}
|
|
52
55
|
export declare function createInkAppElement(agent: Agent, args: CliArgs, options: RunTuiOptions, onExit: (summary: ExitSummary) => void): React.ReactElement;
|
|
53
56
|
export declare function runTui(agent: Agent, args: CliArgs, options?: RunTuiOptions): Promise<ExitSummary | undefined>;
|
package/dist/tui-ink/run.js
CHANGED
|
@@ -3,7 +3,7 @@ import { render } from "ink";
|
|
|
3
3
|
import { App } from "./app.js";
|
|
4
4
|
import { warmHighlighter } from "./code-highlight.js";
|
|
5
5
|
export function createInkAppElement(agent, args, options, onExit) {
|
|
6
|
-
return (_jsx(App, { agent: agent, args: args, sessionManager: options.sessionManager, switchSession: options.switchSession, createProvider: options.createProvider, registry: options.registry, skillRegistry: options.skillRegistry, planHandlerRef: options.planHandlerRef, approvalHandlerRef: options.approvalHandlerRef, questionController: options.questionController, bashAllowlist: options.bashAllowlist, settingsManager: options.settingsManager, lspService: options.lspService, mcpManager: options.mcpManager, goalStore: options.goalStore, themeMode: options.themeMode, themeOverrides: options.themeOverrides, detectedTheme: options.detectedTheme, onThemeModeChange: options.onThemeModeChange, flushMemory: options.flushMemory, runMemoryCompaction: options.runMemoryCompaction, runMemorySummary: options.runMemorySummary, runMemoryRefresh: options.runMemoryRefresh, bypassEnabled: options.bypassEnabled, updateNotice: options.updateNotice, updateNoticeRefresh: options.updateNoticeRefresh, hookController: options.hookController, onExit: onExit }));
|
|
6
|
+
return (_jsx(App, { agent: agent, args: args, sessionManager: options.sessionManager, switchSession: options.switchSession, createProvider: options.createProvider, registry: options.registry, skillRegistry: options.skillRegistry, planHandlerRef: options.planHandlerRef, approvalHandlerRef: options.approvalHandlerRef, questionController: options.questionController, bashAllowlist: options.bashAllowlist, settingsManager: options.settingsManager, lspService: options.lspService, mcpManager: options.mcpManager, goalStore: options.goalStore, themeMode: options.themeMode, themeOverrides: options.themeOverrides, detectedTheme: options.detectedTheme, onThemeModeChange: options.onThemeModeChange, flushMemory: options.flushMemory, runMemoryCompaction: options.runMemoryCompaction, runMemorySummary: options.runMemorySummary, runMemoryRefresh: options.runMemoryRefresh, bypassEnabled: options.bypassEnabled, updateNotice: options.updateNotice, updateNoticeRefresh: options.updateNoticeRefresh, hookController: options.hookController, externalRuntime: options.externalRuntime, onExit: onExit }));
|
|
7
7
|
}
|
|
8
8
|
/**
|
|
9
9
|
* Best-effort terminal restore for abnormal exits. Bubble renders into the
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
import { type SubagentRouteLike } from "../agent/subagent-route-format.js";
|
|
7
7
|
import type { Theme } from "./theme.js";
|
|
8
8
|
import type { DisplayMessage, DisplayToolCall } from "./display-history.js";
|
|
9
|
+
import type { ToolResultMetadata } from "../types.js";
|
|
9
10
|
export interface SubagentDisplay {
|
|
10
11
|
subAgentId?: string;
|
|
11
12
|
agentName?: string;
|
|
@@ -26,13 +27,45 @@ export declare function subagentDescriptor(subagent: SubagentDisplay, includeThi
|
|
|
26
27
|
export declare function subagentStatusColor(status: string | undefined, theme: Theme): string;
|
|
27
28
|
export declare function subagentSummary(subagents: SubagentDisplay[]): string;
|
|
28
29
|
export declare function sortSubagents(subagents: SubagentDisplay[]): SubagentDisplay[];
|
|
29
|
-
/** A spawn_agent (one member)
|
|
30
|
+
/** A spawn_agent (one member) or a run_workflow (a group of members). The
|
|
31
|
+
* "team"/"batch" kinds survive only to render transcripts recorded before
|
|
32
|
+
* those tools were removed (2026-07-06). */
|
|
30
33
|
export interface SubagentGroup {
|
|
31
34
|
id: string;
|
|
32
35
|
kind: "single" | "team" | "batch" | "workflow";
|
|
33
36
|
label: string;
|
|
34
37
|
members: SubagentDisplay[];
|
|
35
38
|
}
|
|
39
|
+
/**
|
|
40
|
+
* Merges subagent tool metadata, deduping member snapshots by subAgentId so a
|
|
41
|
+
* stream of per-child updates accumulates into one member list instead of each
|
|
42
|
+
* update replacing the last.
|
|
43
|
+
*/
|
|
44
|
+
export declare function mergeToolMetadata(current: ToolResultMetadata | undefined, incoming: ToolResultMetadata | undefined): ToolResultMetadata | undefined;
|
|
45
|
+
/**
|
|
46
|
+
* Drops accumulator entries whose every member reached a final status: by then
|
|
47
|
+
* the authoritative snapshot lives in the settled transcript (wait_workflow /
|
|
48
|
+
* wait_agent result), so the entry is dead weight that would otherwise pile up
|
|
49
|
+
* for the life of the process. Entries with running/queued members stay — for
|
|
50
|
+
* a workflow spanning turns they are the only live view. Returns whether the
|
|
51
|
+
* map changed (callers bump their version counter on true).
|
|
52
|
+
*/
|
|
53
|
+
export declare function pruneSettledLiveSubagentTools(map: Map<string, DisplayToolCall>): boolean;
|
|
54
|
+
/**
|
|
55
|
+
* Accumulates a subagent tool_update whose originating tool call has already
|
|
56
|
+
* settled out of the current streaming round. The TUI clears its streaming
|
|
57
|
+
* toolCalls on every turn_start, but background children keep reporting
|
|
58
|
+
* against the launching run_workflow/spawn_agent call id across later rounds
|
|
59
|
+
* (e.g. while a wait_workflow blocks) — without this side-channel those
|
|
60
|
+
* updates are dropped and traces only appear after the whole team finishes.
|
|
61
|
+
* Entries act as synthetic tool calls feeding collectSubagentGroups.
|
|
62
|
+
* Returns true when the update was absorbed.
|
|
63
|
+
*/
|
|
64
|
+
export declare function accumulateLiveSubagentUpdate(map: Map<string, DisplayToolCall>, event: {
|
|
65
|
+
id: string;
|
|
66
|
+
name: string;
|
|
67
|
+
metadata?: ToolResultMetadata;
|
|
68
|
+
}): boolean;
|
|
36
69
|
/**
|
|
37
70
|
* Collects every spawned subagent from the live transcript + streaming tools,
|
|
38
71
|
* grouped by their originating tool call, for the inspector. Pure.
|
|
@@ -75,6 +75,84 @@ function subagentFreshness(member) {
|
|
|
75
75
|
function memberKey(member) {
|
|
76
76
|
return member.subAgentId || `${member.nickname ?? ""}|${member.task ?? ""}`;
|
|
77
77
|
}
|
|
78
|
+
/**
|
|
79
|
+
* Merges subagent tool metadata, deduping member snapshots by subAgentId so a
|
|
80
|
+
* stream of per-child updates accumulates into one member list instead of each
|
|
81
|
+
* update replacing the last.
|
|
82
|
+
*/
|
|
83
|
+
export function mergeToolMetadata(current, incoming) {
|
|
84
|
+
if (!incoming)
|
|
85
|
+
return current;
|
|
86
|
+
if (current?.kind !== "subagent" || incoming.kind !== "subagent") {
|
|
87
|
+
return incoming;
|
|
88
|
+
}
|
|
89
|
+
const currentSubagents = Array.isArray(current.subagents) ? current.subagents : [];
|
|
90
|
+
const incomingSubagents = Array.isArray(incoming.subagents) ? incoming.subagents : [];
|
|
91
|
+
const byId = new Map();
|
|
92
|
+
for (const item of currentSubagents) {
|
|
93
|
+
const subAgentId = typeof item === "object" && item !== null && "subAgentId" in item
|
|
94
|
+
? String(item.subAgentId)
|
|
95
|
+
: "";
|
|
96
|
+
byId.set(subAgentId || `current:${byId.size}`, item);
|
|
97
|
+
}
|
|
98
|
+
for (const item of incomingSubagents) {
|
|
99
|
+
const subAgentId = typeof item === "object" && item !== null && "subAgentId" in item
|
|
100
|
+
? String(item.subAgentId)
|
|
101
|
+
: "";
|
|
102
|
+
byId.set(subAgentId || `incoming:${byId.size}`, item);
|
|
103
|
+
}
|
|
104
|
+
return {
|
|
105
|
+
...current,
|
|
106
|
+
...incoming,
|
|
107
|
+
subagents: [...byId.values()],
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
const FINAL_MEMBER_STATUSES = new Set(["completed", "failed", "blocked", "cancelled", "closed"]);
|
|
111
|
+
/**
|
|
112
|
+
* Drops accumulator entries whose every member reached a final status: by then
|
|
113
|
+
* the authoritative snapshot lives in the settled transcript (wait_workflow /
|
|
114
|
+
* wait_agent result), so the entry is dead weight that would otherwise pile up
|
|
115
|
+
* for the life of the process. Entries with running/queued members stay — for
|
|
116
|
+
* a workflow spanning turns they are the only live view. Returns whether the
|
|
117
|
+
* map changed (callers bump their version counter on true).
|
|
118
|
+
*/
|
|
119
|
+
export function pruneSettledLiveSubagentTools(map) {
|
|
120
|
+
let changed = false;
|
|
121
|
+
for (const [id, tc] of map) {
|
|
122
|
+
const members = Array.isArray(tc.metadata?.subagents) ? tc.metadata.subagents : [];
|
|
123
|
+
const allFinal = members.every((member) => typeof member === "object" && member !== null
|
|
124
|
+
&& FINAL_MEMBER_STATUSES.has(String(member.status)));
|
|
125
|
+
if (allFinal) {
|
|
126
|
+
map.delete(id);
|
|
127
|
+
changed = true;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
return changed;
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Accumulates a subagent tool_update whose originating tool call has already
|
|
134
|
+
* settled out of the current streaming round. The TUI clears its streaming
|
|
135
|
+
* toolCalls on every turn_start, but background children keep reporting
|
|
136
|
+
* against the launching run_workflow/spawn_agent call id across later rounds
|
|
137
|
+
* (e.g. while a wait_workflow blocks) — without this side-channel those
|
|
138
|
+
* updates are dropped and traces only appear after the whole team finishes.
|
|
139
|
+
* Entries act as synthetic tool calls feeding collectSubagentGroups.
|
|
140
|
+
* Returns true when the update was absorbed.
|
|
141
|
+
*/
|
|
142
|
+
export function accumulateLiveSubagentUpdate(map, event) {
|
|
143
|
+
if (event.metadata?.kind !== "subagent")
|
|
144
|
+
return false;
|
|
145
|
+
const prev = map.get(event.id);
|
|
146
|
+
const metadata = mergeToolMetadata(prev?.metadata, event.metadata);
|
|
147
|
+
if (!metadata)
|
|
148
|
+
return false;
|
|
149
|
+
// Per-child updates carry no mode; group them under the launching workflow
|
|
150
|
+
// call rather than falling back to one single-agent group per member.
|
|
151
|
+
if (event.name === "run_workflow" && metadata.mode === undefined)
|
|
152
|
+
metadata.mode = "workflow";
|
|
153
|
+
map.set(event.id, { id: event.id, name: event.name, args: prev?.args ?? {}, metadata });
|
|
154
|
+
return true;
|
|
155
|
+
}
|
|
78
156
|
/**
|
|
79
157
|
* Collects every spawned subagent from the live transcript + streaming tools,
|
|
80
158
|
* grouped by their originating tool call, for the inspector. Pure.
|
|
@@ -159,5 +237,8 @@ export function collectSubagentGroups(messages, streamingTools) {
|
|
|
159
237
|
kind: g.kind,
|
|
160
238
|
label: g.label,
|
|
161
239
|
members: g.memberKeys.map((k) => freshest.get(k)).filter((m) => !!m),
|
|
162
|
-
}))
|
|
240
|
+
}))
|
|
241
|
+
// A group can end up empty when a later echo of the same run (e.g. the
|
|
242
|
+
// wait_workflow result vs the live accumulator) claimed all its members.
|
|
243
|
+
.filter((group) => group.members.length > 0);
|
|
163
244
|
}
|
package/dist/tui-ink/theme.d.ts
CHANGED
|
@@ -15,7 +15,13 @@ export interface Theme {
|
|
|
15
15
|
error: string;
|
|
16
16
|
warning: string;
|
|
17
17
|
success: string;
|
|
18
|
-
|
|
18
|
+
/**
|
|
19
|
+
* Painted canvas color. `undefined` means "do not paint" — the terminal's
|
|
20
|
+
* own background shows through, so the app never fights the user's terminal
|
|
21
|
+
* palette (e.g. forcing pure black inside a soft-dark terminal). Users can
|
|
22
|
+
* still force a painted canvas via `theme.overrides.background` in config.
|
|
23
|
+
*/
|
|
24
|
+
background: string | undefined;
|
|
19
25
|
accent: string;
|
|
20
26
|
/** Welcome banner border. */
|
|
21
27
|
bannerBorder: string;
|
|
@@ -40,7 +46,8 @@ export interface Theme {
|
|
|
40
46
|
toolResult: string;
|
|
41
47
|
toolError: string;
|
|
42
48
|
toolPending: string;
|
|
43
|
-
code
|
|
49
|
+
/** Markdown inline `code` spans. */
|
|
50
|
+
inlineCode: string;
|
|
44
51
|
traceAction: string;
|
|
45
52
|
traceCount: string;
|
|
46
53
|
traceDetail: string;
|
|
@@ -50,8 +57,10 @@ export interface Theme {
|
|
|
50
57
|
userMessageBg: string;
|
|
51
58
|
userMessageText: string;
|
|
52
59
|
userRail: string;
|
|
60
|
+
/** Painted band backgrounds for diff lines inside user-message cards. */
|
|
53
61
|
diffAdd: string;
|
|
54
62
|
diffRemove: string;
|
|
63
|
+
/** Foregrounds for +/- diff lines rendered without a painted background. */
|
|
55
64
|
diffAddFg: string;
|
|
56
65
|
diffRemoveFg: string;
|
|
57
66
|
}
|
|
@@ -62,6 +71,14 @@ export declare const darkTheme: Theme;
|
|
|
62
71
|
* terminal background.
|
|
63
72
|
*/
|
|
64
73
|
export declare const lightTheme: Theme;
|
|
74
|
+
/**
|
|
75
|
+
* Decide whether the canvas needs painting. Auto mode always inherits the
|
|
76
|
+
* terminal's own background, and so does a forced theme that matches the
|
|
77
|
+
* detected terminal. A forced theme that mismatches (e.g. `/theme light`
|
|
78
|
+
* inside a dark terminal) paints its canvas, because its foregrounds are
|
|
79
|
+
* tuned for the opposite background and would otherwise be unreadable.
|
|
80
|
+
*/
|
|
81
|
+
export declare function canvasBackgroundFor(mode: ThemeMode, resolved: ResolvedTheme, terminalTheme: ResolvedTheme): string | undefined;
|
|
65
82
|
export declare const ThemeProvider: import("react").Provider<Theme>;
|
|
66
83
|
export declare function useTheme(): Theme;
|
|
67
84
|
/** Build the active palette given a resolved mode and optional overrides. */
|
package/dist/tui-ink/theme.js
CHANGED
|
@@ -14,7 +14,7 @@ export const darkTheme = {
|
|
|
14
14
|
error: "red",
|
|
15
15
|
warning: "yellow",
|
|
16
16
|
success: "green",
|
|
17
|
-
background:
|
|
17
|
+
background: undefined,
|
|
18
18
|
accent: "cyan",
|
|
19
19
|
bannerBorder: "#38bdf8",
|
|
20
20
|
bannerGradientFrom: "#67e8f9",
|
|
@@ -37,7 +37,7 @@ export const darkTheme = {
|
|
|
37
37
|
toolResult: "gray",
|
|
38
38
|
toolError: "red",
|
|
39
39
|
toolPending: "yellow",
|
|
40
|
-
|
|
40
|
+
inlineCode: "#a78bfa",
|
|
41
41
|
traceAction: "#E89A6B",
|
|
42
42
|
traceCount: "#c9c1bd",
|
|
43
43
|
traceDetail: "gray",
|
|
@@ -49,8 +49,8 @@ export const darkTheme = {
|
|
|
49
49
|
userRail: "#8A7FC6",
|
|
50
50
|
diffAdd: "#1a3d1a",
|
|
51
51
|
diffRemove: "#3d1a1a",
|
|
52
|
-
diffAddFg: "
|
|
53
|
-
diffRemoveFg: "
|
|
52
|
+
diffAddFg: "green",
|
|
53
|
+
diffRemoveFg: "red",
|
|
54
54
|
};
|
|
55
55
|
/**
|
|
56
56
|
* Light palette tuned for paper-neutral surfaces, blue focus/user rails, warm
|
|
@@ -63,7 +63,7 @@ export const lightTheme = {
|
|
|
63
63
|
error: "#B62633",
|
|
64
64
|
warning: "#8B4A00",
|
|
65
65
|
success: "#2F7D4A",
|
|
66
|
-
background:
|
|
66
|
+
background: undefined,
|
|
67
67
|
accent: "#8B4A00",
|
|
68
68
|
bannerBorder: "#356FD2",
|
|
69
69
|
bannerGradientFrom: "#0E7490",
|
|
@@ -86,7 +86,7 @@ export const lightTheme = {
|
|
|
86
86
|
toolResult: "#171717",
|
|
87
87
|
toolError: "#B62633",
|
|
88
88
|
toolPending: "#8B4A00",
|
|
89
|
-
|
|
89
|
+
inlineCode: "#6D28D9",
|
|
90
90
|
traceAction: "#8B4A00",
|
|
91
91
|
traceCount: "#6F7377",
|
|
92
92
|
traceDetail: "#8B9094",
|
|
@@ -98,9 +98,26 @@ export const lightTheme = {
|
|
|
98
98
|
userRail: "#356FD2",
|
|
99
99
|
diffAdd: "#D7E8D8",
|
|
100
100
|
diffRemove: "#F7DADC",
|
|
101
|
-
diffAddFg: "#
|
|
102
|
-
diffRemoveFg: "#
|
|
101
|
+
diffAddFg: "#2F7D4A",
|
|
102
|
+
diffRemoveFg: "#B62633",
|
|
103
103
|
};
|
|
104
|
+
/** Canvas colors painted only when a forced theme mismatches the terminal. */
|
|
105
|
+
const paintedCanvas = {
|
|
106
|
+
dark: "#0A0A0A",
|
|
107
|
+
light: "#FCFCFA",
|
|
108
|
+
};
|
|
109
|
+
/**
|
|
110
|
+
* Decide whether the canvas needs painting. Auto mode always inherits the
|
|
111
|
+
* terminal's own background, and so does a forced theme that matches the
|
|
112
|
+
* detected terminal. A forced theme that mismatches (e.g. `/theme light`
|
|
113
|
+
* inside a dark terminal) paints its canvas, because its foregrounds are
|
|
114
|
+
* tuned for the opposite background and would otherwise be unreadable.
|
|
115
|
+
*/
|
|
116
|
+
export function canvasBackgroundFor(mode, resolved, terminalTheme) {
|
|
117
|
+
if (mode === "auto" || resolved === terminalTheme)
|
|
118
|
+
return undefined;
|
|
119
|
+
return paintedCanvas[resolved];
|
|
120
|
+
}
|
|
104
121
|
const ThemeContext = createContext(darkTheme);
|
|
105
122
|
export const ThemeProvider = ThemeContext.Provider;
|
|
106
123
|
export function useTheme() {
|
|
@@ -9,6 +9,7 @@ interface WelcomeBannerProps {
|
|
|
9
9
|
/** Session identifier (session file basename). */
|
|
10
10
|
sessionLabel?: string;
|
|
11
11
|
providerId?: string;
|
|
12
|
+
modelId?: string;
|
|
12
13
|
modelLabel?: string;
|
|
13
14
|
/** Active thinking level, rendered as part of the model unit (e.g. "xhigh"). */
|
|
14
15
|
thinkingLabel?: string;
|
|
@@ -19,6 +20,6 @@ interface WelcomeVisibilityInput {
|
|
|
19
20
|
}
|
|
20
21
|
export declare function shouldShowWelcomeBanner({ startedWithVisibleHistory, }: WelcomeVisibilityInput): boolean;
|
|
21
22
|
export declare function lerpColor(from: string, to: string, t: number): string;
|
|
22
|
-
export declare function WelcomeBanner({ terminalColumns, tips, updateNotice, cwd, sessionLabel, providerId, modelLabel, thinkingLabel, }: WelcomeBannerProps): import("react/jsx-runtime").JSX.Element;
|
|
23
|
-
export declare function formatModelLine({ providerId, modelLabel, thinkingLabel, tips, }: Pick<WelcomeBannerProps, "providerId" | "modelLabel" | "thinkingLabel" | "tips">): string;
|
|
23
|
+
export declare function WelcomeBanner({ terminalColumns, tips, updateNotice, cwd, sessionLabel, providerId, modelId, modelLabel, thinkingLabel, }: WelcomeBannerProps): import("react/jsx-runtime").JSX.Element;
|
|
24
|
+
export declare function formatModelLine({ providerId, modelId, modelLabel, thinkingLabel, tips, }: Pick<WelcomeBannerProps, "providerId" | "modelId" | "modelLabel" | "thinkingLabel" | "tips">): string;
|
|
24
25
|
export {};
|
package/dist/tui-ink/welcome.js
CHANGED
|
@@ -2,6 +2,7 @@ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-run
|
|
|
2
2
|
import { Box, Text } from "ink";
|
|
3
3
|
import { createRequire } from "node:module";
|
|
4
4
|
import { useTheme } from "./theme.js";
|
|
5
|
+
import { isThinkingOnlyModel, isThinkingToggleModel } from "../provider-transform.js";
|
|
5
6
|
const require = createRequire(import.meta.url);
|
|
6
7
|
const PACKAGE_VERSION = readPackageVersion();
|
|
7
8
|
const COMPACT_LOGO = [
|
|
@@ -28,11 +29,12 @@ function GradientText({ text, from, to }) {
|
|
|
28
29
|
const chars = [...text];
|
|
29
30
|
return (_jsx(_Fragment, { children: chars.map((ch, i) => (_jsx(Text, { bold: true, color: lerpColor(from, to, chars.length <= 1 ? 0 : i / (chars.length - 1)), children: ch }, `ch-${i}`))) }));
|
|
30
31
|
}
|
|
31
|
-
export function WelcomeBanner({ terminalColumns, tips, updateNotice, cwd, sessionLabel, providerId, modelLabel, thinkingLabel, }) {
|
|
32
|
+
export function WelcomeBanner({ terminalColumns, tips, updateNotice, cwd, sessionLabel, providerId, modelId, modelLabel, thinkingLabel, }) {
|
|
32
33
|
const theme = useTheme();
|
|
33
34
|
const effectiveWidth = Math.max(24, Math.min(terminalColumns - 2, 96));
|
|
34
35
|
const modelLine = formatModelLine({
|
|
35
36
|
providerId,
|
|
37
|
+
modelId,
|
|
36
38
|
modelLabel,
|
|
37
39
|
thinkingLabel,
|
|
38
40
|
tips,
|
|
@@ -48,14 +50,16 @@ export function WelcomeBanner({ terminalColumns, tips, updateNotice, cwd, sessio
|
|
|
48
50
|
const labelWidth = Math.max(...infoRows.map((row) => row.label.length)) + 1;
|
|
49
51
|
return (_jsxs(Box, { width: effectiveWidth, flexDirection: "column", marginBottom: 1, borderStyle: "round", borderColor: theme.bannerBorder, paddingX: 2, children: [_jsxs(Box, { flexDirection: "row", children: [_jsx(Box, { flexDirection: "column", marginRight: 2, flexShrink: 0, children: COMPACT_LOGO.map((line, rowIndex) => (_jsx(Text, { bold: true, color: lerpColor(theme.bannerGradientFrom, theme.bannerGradientTo, COMPACT_LOGO.length <= 1 ? 0 : rowIndex / (COMPACT_LOGO.length - 1)), children: line }, `logo-row-${rowIndex}`))) }), _jsxs(Box, { flexDirection: "column", marginTop: 1, flexGrow: 1, flexShrink: 1, children: [_jsx(Box, { children: _jsx(GradientText, { text: "Welcome to Bubble!", from: theme.bannerGradientFrom, to: theme.bannerGradientTo }) }), _jsx(Text, { color: theme.muted, wrap: "wrap", children: "I am a cat and you can send /help for help information." })] })] }), _jsx(Box, { flexDirection: "column", marginTop: 1, children: infoRows.map((row) => (_jsxs(Box, { flexDirection: "row", children: [_jsx(Box, { flexShrink: 0, children: _jsx(Text, { color: theme.dim, children: row.label.padEnd(labelWidth) }) }), _jsx(Box, { flexGrow: 1, flexShrink: 1, children: _jsx(Text, { color: row.color, wrap: "wrap", children: row.value }) })] }, row.label))) }), updateNotice && (_jsx(Box, { marginTop: 1, children: _jsx(Text, { color: theme.accent, children: updateNotice }) }))] }));
|
|
50
52
|
}
|
|
51
|
-
export function formatModelLine({ providerId, modelLabel, thinkingLabel, tips, }) {
|
|
53
|
+
export function formatModelLine({ providerId, modelId, modelLabel, thinkingLabel, tips, }) {
|
|
52
54
|
const parts = [];
|
|
53
|
-
//
|
|
54
|
-
// "thinking mode" rather than "<level> effort"
|
|
55
|
-
//
|
|
55
|
+
// Binary thinking toggles use an internal placeholder level, so label them
|
|
56
|
+
// "thinking mode" rather than "<level> effort". MiniMax provider ids are
|
|
57
|
+
// redundant with the model name, so omit them.
|
|
56
58
|
const isMiniMax = (providerId || "").toLowerCase().includes("minimax");
|
|
59
|
+
const isThinkingToggle = isThinkingToggleModel(providerId, modelId);
|
|
60
|
+
const isThinkingOnly = isThinkingOnlyModel(providerId, modelId);
|
|
57
61
|
if (modelLabel) {
|
|
58
|
-
if (thinkingLabel &&
|
|
62
|
+
if (thinkingLabel && (isThinkingToggle || isThinkingOnly))
|
|
59
63
|
parts.push(modelLabel, "thinking mode");
|
|
60
64
|
else if (thinkingLabel)
|
|
61
65
|
parts.push(`${modelLabel} with ${thinkingLabel} effort`);
|
package/dist/types.d.ts
CHANGED
|
@@ -12,7 +12,8 @@ export interface ImageContent {
|
|
|
12
12
|
};
|
|
13
13
|
}
|
|
14
14
|
export type ContentPart = TextContent | ImageContent;
|
|
15
|
-
export
|
|
15
|
+
export declare const THINKING_LEVELS: readonly ["off", "minimal", "low", "medium", "high", "xhigh", "max", "ultra"];
|
|
16
|
+
export type ThinkingLevel = (typeof THINKING_LEVELS)[number];
|
|
16
17
|
export type ReasoningEffort = ThinkingLevel;
|
|
17
18
|
export type ProviderRawContentBlock = Record<string, unknown> & {
|
|
18
19
|
type: string;
|
|
@@ -169,10 +170,9 @@ export interface ToolContext {
|
|
|
169
170
|
name: string;
|
|
170
171
|
};
|
|
171
172
|
agent?: {
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
}) => Promise<ToolResult>;
|
|
173
|
+
/** Deferred-tool surface; backs tool_search when no controller is wired. */
|
|
174
|
+
listDeferredTools?: () => ToolRegistryEntry[];
|
|
175
|
+
unlockDeferredTools?: (names: string[]) => void;
|
|
176
176
|
runSubAgent?: (input: string | ContentPart[], cwd: string, options: {
|
|
177
177
|
profile: import("./agent/profiles.js").AgentProfile;
|
|
178
178
|
runId: string;
|
|
@@ -210,38 +210,15 @@ export interface ToolContext {
|
|
|
210
210
|
}) => Promise<import("./agent/subagent-control.js").SubagentThreadSnapshot>;
|
|
211
211
|
closeSubAgent?: (agentId: string) => Promise<import("./agent/subagent-control.js").SubagentThreadSnapshot>;
|
|
212
212
|
listSubAgents?: () => import("./agent/subagent-control.js").SubagentThreadSnapshot[];
|
|
213
|
-
runAgentTeam?: (cwd: string, options: {
|
|
214
|
-
profile: import("./agent/profiles.js").AgentProfile;
|
|
215
|
-
category?: string;
|
|
216
|
-
model?: string;
|
|
217
|
-
effort?: ThinkingLevel;
|
|
218
|
-
promptTemplate: string;
|
|
219
|
-
items: string[];
|
|
220
|
-
parentToolCallId: string;
|
|
221
|
-
emitUpdate?: (update: ToolUpdate) => void;
|
|
222
|
-
abortSignal?: AbortSignal;
|
|
223
|
-
approval?: "fail" | "disabled";
|
|
224
|
-
}) => Promise<import("./agent/subagent-control.js").SubagentThreadSnapshot[]>;
|
|
225
|
-
runAgentBatch?: (cwd: string, options: {
|
|
226
|
-
specs: Array<{
|
|
227
|
-
task: string;
|
|
228
|
-
profile: import("./agent/profiles.js").AgentProfile;
|
|
229
|
-
category?: string;
|
|
230
|
-
model?: string;
|
|
231
|
-
effort?: ThinkingLevel;
|
|
232
|
-
outputSchema?: unknown;
|
|
233
|
-
}>;
|
|
234
|
-
parentToolCallId: string;
|
|
235
|
-
emitUpdate?: (update: ToolUpdate) => void;
|
|
236
|
-
abortSignal?: AbortSignal;
|
|
237
|
-
approval?: "fail" | "disabled";
|
|
238
|
-
}) => Promise<import("./agent/subagent-control.js").SubagentThreadSnapshot[]>;
|
|
239
213
|
startWorkflow?: (cwd: string, options: {
|
|
240
214
|
script: string;
|
|
241
215
|
args?: unknown;
|
|
242
216
|
title?: string;
|
|
243
217
|
parentToolCallId: string;
|
|
244
218
|
abortSignal?: AbortSignal;
|
|
219
|
+
ensureProfileTrusted?: (profile: import("./agent/profiles.js").AgentProfile) => Promise<{
|
|
220
|
+
content: string | unknown;
|
|
221
|
+
} | undefined>;
|
|
245
222
|
}) => {
|
|
246
223
|
runId: string;
|
|
247
224
|
title: string;
|
package/dist/types.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type
|
|
2
|
-
export
|
|
1
|
+
import { type ThinkingLevel } from "../types.js";
|
|
2
|
+
export { THINKING_LEVELS } from "../types.js";
|
|
3
3
|
export declare function isThinkingLevel(value: string | undefined): value is ThinkingLevel;
|
|
4
4
|
export declare function clampThinkingLevel(requestedLevel: ThinkingLevel, supportedLevels: readonly ThinkingLevel[]): ThinkingLevel;
|
|
5
5
|
export declare function getNextThinkingLevel(currentLevel: ThinkingLevel, supportedLevels: readonly ThinkingLevel[]): ThinkingLevel;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
|
|
1
|
+
import { THINKING_LEVELS } from "../types.js";
|
|
2
|
+
export { THINKING_LEVELS } from "../types.js";
|
|
2
3
|
export function isThinkingLevel(value) {
|
|
3
4
|
return !!value && THINKING_LEVELS.includes(value);
|
|
4
5
|
}
|
|
@@ -1,4 +1,26 @@
|
|
|
1
1
|
import type { ThinkingLevel } from "../types.js";
|
|
2
2
|
export declare function getAvailableThinkingLevels(providerId: string, modelId: string): ThinkingLevel[];
|
|
3
3
|
export declare function getDefaultThinkingLevel(providerId: string, modelId: string): ThinkingLevel;
|
|
4
|
+
/**
|
|
5
|
+
* A single non-"off" level means the model is always in thinking mode with no
|
|
6
|
+
* user-facing grades (e.g. kimi-k2.7-code) — the level value is an internal
|
|
7
|
+
* placeholder and must not be shown to the user as an effort grade.
|
|
8
|
+
*/
|
|
9
|
+
export declare function isThinkingOnlyLevels(levels: readonly ThinkingLevel[]): boolean;
|
|
10
|
+
export declare function isThinkingOnlyModel(providerId?: string, modelId?: string): boolean;
|
|
11
|
+
/**
|
|
12
|
+
* Some providers expose thinking as a true enabled/disabled switch. We may store
|
|
13
|
+
* the enabled state as "medium" internally for compatibility with ThinkingLevel,
|
|
14
|
+
* but it is not a real user-facing effort grade.
|
|
15
|
+
*/
|
|
16
|
+
export declare function isThinkingToggleModel(providerId?: string, modelId?: string): boolean;
|
|
4
17
|
export declare function normalizeThinkingLevel(level: ThinkingLevel, supportedLevels: readonly ThinkingLevel[]): ThinkingLevel;
|
|
18
|
+
/**
|
|
19
|
+
* Normalizes effort inherited from a previous model or restored session.
|
|
20
|
+
*
|
|
21
|
+
* Unlike an explicit CLI/config choice, an inherited unsupported value does
|
|
22
|
+
* not express a direction the user just chose for the target model. Prefer the
|
|
23
|
+
* target model's declared default in that case, then fall back to the canonical
|
|
24
|
+
* downward clamp for legacy models without an explicit default.
|
|
25
|
+
*/
|
|
26
|
+
export declare function normalizeInheritedThinkingLevel(providerId: string, modelId: string, inheritedLevel: ThinkingLevel): ThinkingLevel;
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { getBuiltinModel, getModelDefaultReasoningLevel } from "../model-catalog.js";
|
|
2
2
|
import { clampThinkingLevel } from "./thinking-level.js";
|
|
3
|
+
const KIMI_TOGGLE_PROVIDER_IDS = new Set(["moonshot-cn", "moonshot-intl", "kimi-for-coding"]);
|
|
4
|
+
const KIMI_THINKING_TOGGLE_MODELS = new Set(["kimi-k2.5", "kimi-k2.6"]);
|
|
3
5
|
export function getAvailableThinkingLevels(providerId, modelId) {
|
|
4
6
|
return getBuiltinModel(providerId, modelId)?.reasoningLevels ?? ["off"];
|
|
5
7
|
}
|
|
@@ -10,6 +12,47 @@ export function getDefaultThinkingLevel(providerId, modelId) {
|
|
|
10
12
|
return explicitDefault;
|
|
11
13
|
return levels.includes("medium") ? "medium" : levels[0] || "off";
|
|
12
14
|
}
|
|
15
|
+
/**
|
|
16
|
+
* A single non-"off" level means the model is always in thinking mode with no
|
|
17
|
+
* user-facing grades (e.g. kimi-k2.7-code) — the level value is an internal
|
|
18
|
+
* placeholder and must not be shown to the user as an effort grade.
|
|
19
|
+
*/
|
|
20
|
+
export function isThinkingOnlyLevels(levels) {
|
|
21
|
+
return levels.length === 1 && levels[0] !== "off";
|
|
22
|
+
}
|
|
23
|
+
export function isThinkingOnlyModel(providerId = "", modelId = "") {
|
|
24
|
+
return isThinkingOnlyLevels(getAvailableThinkingLevels(providerId, modelId));
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Some providers expose thinking as a true enabled/disabled switch. We may store
|
|
28
|
+
* the enabled state as "medium" internally for compatibility with ThinkingLevel,
|
|
29
|
+
* but it is not a real user-facing effort grade.
|
|
30
|
+
*/
|
|
31
|
+
export function isThinkingToggleModel(providerId = "", modelId = "") {
|
|
32
|
+
const normalizedProvider = providerId.toLowerCase();
|
|
33
|
+
const normalizedModel = modelId.toLowerCase();
|
|
34
|
+
if (normalizedProvider.includes("minimax") || normalizedModel.includes("minimax"))
|
|
35
|
+
return true;
|
|
36
|
+
return KIMI_TOGGLE_PROVIDER_IDS.has(normalizedProvider)
|
|
37
|
+
&& KIMI_THINKING_TOGGLE_MODELS.has(normalizedModel);
|
|
38
|
+
}
|
|
13
39
|
export function normalizeThinkingLevel(level, supportedLevels) {
|
|
14
40
|
return clampThinkingLevel(level, supportedLevels);
|
|
15
41
|
}
|
|
42
|
+
/**
|
|
43
|
+
* Normalizes effort inherited from a previous model or restored session.
|
|
44
|
+
*
|
|
45
|
+
* Unlike an explicit CLI/config choice, an inherited unsupported value does
|
|
46
|
+
* not express a direction the user just chose for the target model. Prefer the
|
|
47
|
+
* target model's declared default in that case, then fall back to the canonical
|
|
48
|
+
* downward clamp for legacy models without an explicit default.
|
|
49
|
+
*/
|
|
50
|
+
export function normalizeInheritedThinkingLevel(providerId, modelId, inheritedLevel) {
|
|
51
|
+
const supportedLevels = getAvailableThinkingLevels(providerId, modelId);
|
|
52
|
+
if (supportedLevels.includes(inheritedLevel))
|
|
53
|
+
return inheritedLevel;
|
|
54
|
+
const modelDefault = getModelDefaultReasoningLevel(providerId, modelId);
|
|
55
|
+
if (modelDefault && supportedLevels.includes(modelDefault))
|
|
56
|
+
return modelDefault;
|
|
57
|
+
return clampThinkingLevel(inheritedLevel, supportedLevels);
|
|
58
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bubblebrain-ai/bubble",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.36",
|
|
4
4
|
"description": "A terminal coding agent",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"engines": {
|
|
@@ -24,6 +24,7 @@
|
|
|
24
24
|
"test:watch": "vitest"
|
|
25
25
|
},
|
|
26
26
|
"dependencies": {
|
|
27
|
+
"@agentclientprotocol/sdk": "1.2.1",
|
|
27
28
|
"@ai-sdk/google": "^3.0.88",
|
|
28
29
|
"@ai-sdk/provider": "^3.0.13",
|
|
29
30
|
"@larksuiteoapi/node-sdk": "^1.65.0",
|
|
@@ -59,6 +60,9 @@
|
|
|
59
60
|
"overrides": {
|
|
60
61
|
"axios": "^1.17.0",
|
|
61
62
|
"postcss": "^8.5.15",
|
|
62
|
-
"ws": "^8.21.0"
|
|
63
|
+
"ws": "^8.21.0",
|
|
64
|
+
"openai": {
|
|
65
|
+
"zod": "$zod"
|
|
66
|
+
}
|
|
63
67
|
}
|
|
64
68
|
}
|
package/dist/tools/task.d.ts
DELETED