@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.
Files changed (168) hide show
  1. package/README.md +27 -7
  2. package/dist/agent/abort-errors.d.ts +2 -2
  3. package/dist/agent/budget-ledger.d.ts +4 -45
  4. package/dist/agent/budget-ledger.js +5 -75
  5. package/dist/agent/categories.d.ts +66 -2
  6. package/dist/agent/categories.js +120 -19
  7. package/dist/agent/child-runner.d.ts +1 -3
  8. package/dist/agent/child-runner.js +6 -37
  9. package/dist/agent/discovery-barrier.js +1 -1
  10. package/dist/agent/profiles.d.ts +1 -2
  11. package/dist/agent/profiles.js +25 -14
  12. package/dist/agent/routing-catalog.d.ts +113 -0
  13. package/dist/agent/routing-catalog.js +240 -0
  14. package/dist/agent/subagent-control.d.ts +5 -12
  15. package/dist/agent/subagent-control.js +0 -2
  16. package/dist/agent/subagent-store.d.ts +1 -1
  17. package/dist/agent/subagent-store.js +1 -3
  18. package/dist/agent/workflow/control.d.ts +21 -0
  19. package/dist/agent/workflow/control.js +50 -8
  20. package/dist/agent/workflow/runtime.d.ts +15 -2
  21. package/dist/agent/workflow/runtime.js +112 -30
  22. package/dist/agent.d.ts +82 -48
  23. package/dist/agent.js +360 -232
  24. package/dist/approval/controller.js +28 -0
  25. package/dist/approval/tool-helper.js +2 -0
  26. package/dist/approval/types.d.ts +21 -1
  27. package/dist/cli.d.ts +1 -1
  28. package/dist/cli.js +2 -1
  29. package/dist/config.d.ts +5 -3
  30. package/dist/config.js +10 -5
  31. package/dist/context/compact-llm.d.ts +2 -2
  32. package/dist/external-runtime/grok-acp.d.ts +56 -0
  33. package/dist/external-runtime/grok-acp.js +386 -0
  34. package/dist/external-runtime/grok-binary.d.ts +25 -0
  35. package/dist/external-runtime/grok-binary.js +108 -0
  36. package/dist/external-runtime/grok-errors.d.ts +7 -0
  37. package/dist/external-runtime/grok-errors.js +15 -0
  38. package/dist/external-runtime/grok-input-policy.d.ts +58 -0
  39. package/dist/external-runtime/grok-input-policy.js +52 -0
  40. package/dist/external-runtime/grok-ndjson.d.ts +14 -0
  41. package/dist/external-runtime/grok-ndjson.js +193 -0
  42. package/dist/external-runtime/grok-network.d.ts +15 -0
  43. package/dist/external-runtime/grok-network.js +81 -0
  44. package/dist/external-runtime/grok-preflight.d.ts +28 -0
  45. package/dist/external-runtime/grok-preflight.js +194 -0
  46. package/dist/external-runtime/grok-process.d.ts +26 -0
  47. package/dist/external-runtime/grok-process.js +184 -0
  48. package/dist/external-runtime/grok-profile.d.ts +32 -0
  49. package/dist/external-runtime/grok-profile.js +419 -0
  50. package/dist/external-runtime/grok-provider.d.ts +31 -0
  51. package/dist/external-runtime/grok-provider.js +41 -0
  52. package/dist/external-runtime/grok-runtime.d.ts +91 -0
  53. package/dist/external-runtime/grok-runtime.js +882 -0
  54. package/dist/external-runtime/index.d.ts +13 -0
  55. package/dist/external-runtime/index.js +13 -0
  56. package/dist/external-runtime/session-policy.d.ts +11 -0
  57. package/dist/external-runtime/session-policy.js +30 -0
  58. package/dist/external-runtime/types.d.ts +65 -0
  59. package/dist/external-runtime/types.js +1 -0
  60. package/dist/feishu/agent-host/approval-card.js +21 -0
  61. package/dist/feishu/agent-host/run-driver.js +19 -3
  62. package/dist/feishu/serve.js +1 -0
  63. package/dist/goal/tools.d.ts +6 -3
  64. package/dist/goal/tools.js +7 -19
  65. package/dist/main.js +114 -28
  66. package/dist/memory/db.d.ts +2 -0
  67. package/dist/memory/db.js +10 -0
  68. package/dist/memory/index.d.ts +1 -0
  69. package/dist/memory/index.js +1 -0
  70. package/dist/memory/phase1.js +14 -2
  71. package/dist/memory/phase2.js +21 -2
  72. package/dist/memory/prompts.js +1 -1
  73. package/dist/memory/session-policy.d.ts +25 -0
  74. package/dist/memory/session-policy.js +55 -0
  75. package/dist/memory/storage.d.ts +1 -0
  76. package/dist/memory/storage.js +13 -0
  77. package/dist/model-catalog.d.ts +18 -0
  78. package/dist/model-catalog.js +92 -52
  79. package/dist/model-config.d.ts +3 -1
  80. package/dist/model-config.js +11 -0
  81. package/dist/oauth/grok.d.ts +25 -0
  82. package/dist/oauth/grok.js +218 -0
  83. package/dist/oauth/index.d.ts +1 -0
  84. package/dist/oauth/index.js +1 -0
  85. package/dist/oauth/storage.d.ts +9 -0
  86. package/dist/oauth/storage.js +25 -0
  87. package/dist/orchestrator/default-hooks.js +23 -7
  88. package/dist/prompt/compose.d.ts +3 -0
  89. package/dist/prompt/compose.js +3 -0
  90. package/dist/prompt/delegation.d.ts +1 -1
  91. package/dist/prompt/delegation.js +41 -8
  92. package/dist/prompt/environment.js +0 -4
  93. package/dist/prompt/reminders.d.ts +0 -1
  94. package/dist/prompt/reminders.js +1 -11
  95. package/dist/prompt/routing.d.ts +14 -0
  96. package/dist/prompt/routing.js +71 -0
  97. package/dist/prompt/runtime.js +1 -1
  98. package/dist/prompt/task-reminders.d.ts +20 -0
  99. package/dist/prompt/task-reminders.js +73 -1
  100. package/dist/provider-ai-sdk.js +2 -2
  101. package/dist/provider-grok.d.ts +26 -0
  102. package/dist/provider-grok.js +59 -0
  103. package/dist/provider-openai-codex.d.ts +17 -1
  104. package/dist/provider-openai-codex.js +101 -29
  105. package/dist/provider-registry.d.ts +72 -0
  106. package/dist/provider-registry.js +336 -59
  107. package/dist/provider-transform.d.ts +1 -1
  108. package/dist/provider-transform.js +35 -17
  109. package/dist/provider.d.ts +3 -0
  110. package/dist/provider.js +14 -0
  111. package/dist/session-types.d.ts +19 -1
  112. package/dist/session.d.ts +1 -0
  113. package/dist/session.js +4 -0
  114. package/dist/slash-commands/commands.js +224 -14
  115. package/dist/slash-commands/types.d.ts +14 -1
  116. package/dist/system-prompt.d.ts +2 -0
  117. package/dist/tools/agent-lifecycle.d.ts +1 -9
  118. package/dist/tools/agent-lifecycle.js +42 -272
  119. package/dist/tools/bash.js +1 -1
  120. package/dist/tools/child-tools.js +2 -0
  121. package/dist/tools/index.d.ts +2 -2
  122. package/dist/tools/index.js +7 -5
  123. package/dist/tools/lsp.js +1 -0
  124. package/dist/tools/memory.d.ts +7 -2
  125. package/dist/tools/memory.js +28 -43
  126. package/dist/tools/server.js +4 -0
  127. package/dist/tools/tool-search.d.ts +1 -1
  128. package/dist/tools/tool-search.js +23 -3
  129. package/dist/tui/model-switch.d.ts +7 -0
  130. package/dist/tui/model-switch.js +15 -5
  131. package/dist/tui-ink/app.d.ts +3 -1
  132. package/dist/tui-ink/app.js +672 -243
  133. package/dist/tui-ink/approval/approval-dialog.js +37 -1
  134. package/dist/tui-ink/approval/diff-view.js +4 -4
  135. package/dist/tui-ink/approval/select.js +2 -2
  136. package/dist/tui-ink/composer-buffer.d.ts +55 -0
  137. package/dist/tui-ink/composer-buffer.js +317 -0
  138. package/dist/tui-ink/feedback-dialog.js +2 -2
  139. package/dist/tui-ink/feishu-setup-picker.js +3 -3
  140. package/dist/tui-ink/footer.d.ts +1 -0
  141. package/dist/tui-ink/footer.js +7 -2
  142. package/dist/tui-ink/input-box.d.ts +36 -7
  143. package/dist/tui-ink/input-box.js +229 -157
  144. package/dist/tui-ink/markdown.js +11 -9
  145. package/dist/tui-ink/message-list.d.ts +5 -1
  146. package/dist/tui-ink/message-list.js +15 -2
  147. package/dist/tui-ink/model-picker.d.ts +61 -4
  148. package/dist/tui-ink/model-picker.js +464 -128
  149. package/dist/tui-ink/paste-operation-tracker.d.ts +13 -0
  150. package/dist/tui-ink/paste-operation-tracker.js +25 -0
  151. package/dist/tui-ink/plan-confirm.js +1 -1
  152. package/dist/tui-ink/run.d.ts +3 -0
  153. package/dist/tui-ink/run.js +1 -1
  154. package/dist/tui-ink/subagent-view.d.ts +34 -1
  155. package/dist/tui-ink/subagent-view.js +82 -1
  156. package/dist/tui-ink/theme.d.ts +19 -2
  157. package/dist/tui-ink/theme.js +25 -8
  158. package/dist/tui-ink/welcome.d.ts +3 -2
  159. package/dist/tui-ink/welcome.js +10 -6
  160. package/dist/types.d.ts +8 -31
  161. package/dist/types.js +1 -1
  162. package/dist/variant/thinking-level.d.ts +2 -2
  163. package/dist/variant/thinking-level.js +2 -1
  164. package/dist/variant/variant-resolver.d.ts +22 -0
  165. package/dist/variant/variant-resolver.js +43 -0
  166. package/package.json +6 -2
  167. package/dist/tools/task.d.ts +0 -2
  168. package/dist/tools/task.js +0 -58
@@ -7,6 +7,7 @@ export function createManagedServerTools(cwd, approval) {
7
7
  return [
8
8
  {
9
9
  name: "start_server",
10
+ deferred: true,
10
11
  effect: "unknown",
11
12
  requiresApproval: true,
12
13
  description: "Start a long-running development server as a managed service. Use this instead of bash for npm run dev, next dev, vite, webpack --watch, or similar commands. Pass a foreground server command without a trailing '&'. The tool waits for readiness and then returns a server_id; use server_status, server_logs, and stop_server to manage it.",
@@ -84,6 +85,7 @@ export function createManagedServerTools(cwd, approval) {
84
85
  },
85
86
  {
86
87
  name: "server_status",
88
+ deferred: true,
87
89
  readOnly: true,
88
90
  effect: "read",
89
91
  description: "Show managed development server status. Pass serverId for one server, or omit it to list all managed servers.",
@@ -123,6 +125,7 @@ export function createManagedServerTools(cwd, approval) {
123
125
  },
124
126
  {
125
127
  name: "server_logs",
128
+ deferred: true,
126
129
  readOnly: true,
127
130
  effect: "read",
128
131
  description: "Return recent logs for a managed development server.",
@@ -154,6 +157,7 @@ export function createManagedServerTools(cwd, approval) {
154
157
  },
155
158
  {
156
159
  name: "stop_server",
160
+ deferred: true,
157
161
  effect: "unknown",
158
162
  description: "Stop a managed development server by serverId.",
159
163
  parameters: {
@@ -20,4 +20,4 @@ export interface ToolSearchController {
20
20
  /** Mark a set of deferred tool names as unlocked. */
21
21
  unlock: (names: string[]) => void;
22
22
  }
23
- export declare function createToolSearchTool(controller: ToolSearchController): ToolRegistryEntry;
23
+ export declare function createToolSearchTool(controller?: ToolSearchController): ToolRegistryEntry;
@@ -13,6 +13,22 @@
13
13
  * tools are also unlocked on the agent so subsequent turns include them in
14
14
  * the real tool list.
15
15
  */
16
+ /**
17
+ * Without an injected controller, back the tool with the executing agent from
18
+ * the tool context. This keeps tool_search available in EVERY host — a host
19
+ * that forgets to wire a controller must not strand deferred tools behind an
20
+ * unreachable unlock path (Feishu and the desktop bridge hit exactly that
21
+ * with deferred MCP tools).
22
+ */
23
+ function contextController(ctx) {
24
+ const agent = ctx.agent;
25
+ if (!agent?.listDeferredTools || !agent.unlockDeferredTools)
26
+ return undefined;
27
+ return {
28
+ listDeferred: () => agent.listDeferredTools(),
29
+ unlock: (names) => agent.unlockDeferredTools(names),
30
+ };
31
+ }
16
32
  export function createToolSearchTool(controller) {
17
33
  return {
18
34
  name: "tool_search",
@@ -36,12 +52,16 @@ export function createToolSearchTool(controller) {
36
52
  },
37
53
  required: ["query"],
38
54
  },
39
- async execute(args) {
55
+ async execute(args, ctx) {
56
+ const resolved = controller ?? contextController(ctx);
57
+ if (!resolved) {
58
+ return { content: "Error: tool_search requires an agent runtime.", isError: true };
59
+ }
40
60
  const query = typeof args.query === "string" ? args.query : "";
41
61
  const maxResults = typeof args.max_results === "number" && args.max_results > 0
42
62
  ? Math.min(Math.floor(args.max_results), 25)
43
63
  : 5;
44
- const deferred = controller.listDeferred();
64
+ const deferred = resolved.listDeferred();
45
65
  if (deferred.length === 0) {
46
66
  return { content: "No deferred tools are registered in this session." };
47
67
  }
@@ -70,7 +90,7 @@ export function createToolSearchTool(controller) {
70
90
  };
71
91
  }
72
92
  }
73
- controller.unlock(matches.map((t) => t.name));
93
+ resolved.unlock(matches.map((t) => t.name));
74
94
  const lines = ["<functions>"];
75
95
  for (const tool of matches) {
76
96
  const schema = {
@@ -7,6 +7,11 @@ export interface ModelSwitchAgent {
7
7
  thinking: ThinkingLevel;
8
8
  setProvider(provider: Provider): void;
9
9
  setSystemPrompt(prompt: string): void;
10
+ /** Routing menu for the NEXT parent route (model-routing design §1.5). */
11
+ renderModelRoutingPromptFor?(parent: {
12
+ providerId: string;
13
+ model: string;
14
+ }): string | undefined;
10
15
  }
11
16
  export interface ModelSwitchRegistry {
12
17
  prepareProvider(providerId: string): Promise<void>;
@@ -26,6 +31,8 @@ export interface SwitchAgentModelOptions {
26
31
  agent: ModelSwitchAgent;
27
32
  registry: ModelSwitchRegistry;
28
33
  createProvider: ((providerId: string, apiKey: string, baseURL: string) => Provider) | undefined;
34
+ /** A side-effect-free provider instance prepared before an atomic session transition. */
35
+ preparedProvider?: Provider;
29
36
  workingDir: string;
30
37
  systemPromptOptions: Omit<SystemPromptOptions, "agentName" | "configuredProvider" | "configuredModel" | "configuredModelId" | "thinkingLevel" | "workingDir">;
31
38
  thinkingLevel?: ThinkingLevel;
@@ -1,6 +1,7 @@
1
1
  import { decodeModel, displayModel } from "../provider-registry.js";
2
2
  import { buildSystemPrompt } from "../system-prompt.js";
3
- import { getAvailableThinkingLevels, getDefaultThinkingLevel, normalizeThinkingLevel } from "../provider-transform.js";
3
+ import { getAvailableThinkingLevels, normalizeThinkingLevel } from "../provider-transform.js";
4
+ import { normalizeInheritedThinkingLevel } from "../variant/variant-resolver.js";
4
5
  export function modelSwitchTarget(model, fallbackProviderId) {
5
6
  const decoded = decodeModel(model);
6
7
  return {
@@ -22,13 +23,18 @@ export function formatModelSwitchError(model, error) {
22
23
  }
23
24
  export async function switchAgentModel(options) {
24
25
  const { providerId, modelId } = modelSwitchTarget(options.model, options.agent.providerId || options.registry.getDefault()?.id);
25
- await options.registry.prepareProvider(providerId);
26
+ if (!options.preparedProvider) {
27
+ await options.registry.prepareProvider(providerId);
28
+ }
26
29
  const provider = options.registry.getConfigured().find((item) => item.id === providerId);
27
- if (!provider?.apiKey || !options.createProvider) {
30
+ if (!provider?.apiKey || (!options.createProvider && !options.preparedProvider)) {
28
31
  throw new Error(`Provider ${providerId} is not configured or has no active credentials.`);
29
32
  }
30
- const nextThinkingLevel = normalizeThinkingLevel((options.thinkingLevel ?? options.agent.thinking) || getDefaultThinkingLevel(providerId, modelId), getAvailableThinkingLevels(providerId, modelId));
31
- const nextProvider = options.createProvider(providerId, provider.apiKey, provider.baseURL);
33
+ const nextThinkingLevel = options.thinkingLevel !== undefined
34
+ ? normalizeThinkingLevel(options.thinkingLevel, getAvailableThinkingLevels(providerId, modelId))
35
+ : normalizeInheritedThinkingLevel(providerId, modelId, options.agent.thinking);
36
+ const nextProvider = options.preparedProvider
37
+ ?? options.createProvider(providerId, provider.apiKey, provider.baseURL);
32
38
  const nextSystemPrompt = buildSystemPrompt({
33
39
  agentName: "Bubble",
34
40
  configuredProvider: providerId,
@@ -37,6 +43,10 @@ export async function switchAgentModel(options) {
37
43
  thinkingLevel: nextThinkingLevel,
38
44
  workingDir: options.workingDir,
39
45
  ...options.systemPromptOptions,
46
+ // The spread carries the menu for the OLD parent; re-render for the model
47
+ // being switched to, before any agent state is mutated (design §1.5).
48
+ modelRoutingPrompt: options.agent.renderModelRoutingPromptFor?.({ providerId, model: modelId })
49
+ ?? options.systemPromptOptions.modelRoutingPrompt,
40
50
  });
41
51
  options.agent.model = options.model;
42
52
  options.agent.thinking = nextThinkingLevel;
@@ -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 { GoalStore } from "../goal/store.js";
17
+ import type { ExternalRuntimeManager } from "../external-runtime/types.js";
17
18
  export interface PlanHandlerRef {
18
19
  current?: (plan: string) => Promise<PlanDecision>;
19
20
  }
@@ -53,6 +54,7 @@ interface AppProps {
53
54
  updateNotice?: string;
54
55
  updateNoticeRefresh?: Promise<string | null>;
55
56
  hookController?: ExternalHookController;
57
+ externalRuntime?: ExternalRuntimeManager;
56
58
  onExit?: (summary: ExitSummary) => void;
57
59
  }
58
60
  export interface ExitSummary {
@@ -63,5 +65,5 @@ export declare const INK_LOCAL_SLASH_COMMANDS: readonly [{
63
65
  readonly name: "goal";
64
66
  readonly description: "Set/manage an autonomous goal (/goal <objective>|clear|pause|resume|edit)";
65
67
  }];
66
- export declare function App({ agent, args, sessionManager: initialSessionManager, switchSession, createProvider, registry, skillRegistry, planHandlerRef, approvalHandlerRef, questionController, bashAllowlist, settingsManager, lspService, mcpManager, themeMode: initialThemeMode, themeOverrides, detectedTheme, onThemeModeChange, flushMemory, runMemoryCompaction, runMemorySummary, runMemoryRefresh, goalStore, bypassEnabled, updateNotice, updateNoticeRefresh, hookController, onExit }: AppProps): import("react/jsx-runtime").JSX.Element;
68
+ export declare function App({ agent, args, sessionManager: initialSessionManager, switchSession, createProvider, registry, skillRegistry, planHandlerRef, approvalHandlerRef, questionController, bashAllowlist, settingsManager, lspService, mcpManager, themeMode: initialThemeMode, themeOverrides, detectedTheme, onThemeModeChange, flushMemory, runMemoryCompaction, runMemorySummary, runMemoryRefresh, goalStore, bypassEnabled, updateNotice, updateNoticeRefresh, hookController, externalRuntime, onExit }: AppProps): import("react/jsx-runtime").JSX.Element;
67
69
  export {};