@bubblebrain-ai/bubble 0.0.58 → 0.0.60

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 (177) hide show
  1. package/README.md +56 -6
  2. package/dist/agent/child-runner.js +5 -1
  3. package/dist/agent/internal-reminder-sanitizer.d.ts +1 -1
  4. package/dist/agent/internal-reminder-sanitizer.js +7 -1
  5. package/dist/agent/profiles.js +4 -4
  6. package/dist/agent/routing-catalog.d.ts +19 -1
  7. package/dist/agent/routing-catalog.js +32 -13
  8. package/dist/agent/subagent/runtime.d.ts +28 -0
  9. package/dist/agent/subagent/runtime.js +34 -30
  10. package/dist/agent/subagent-control.d.ts +7 -0
  11. package/dist/agent/subagent-control.js +2 -0
  12. package/dist/agent/subagent-lifecycle-reminder.js +2 -1
  13. package/dist/agent/subagent-wait-guidance.d.ts +2 -0
  14. package/dist/agent/subagent-wait-guidance.js +8 -0
  15. package/dist/agent/subtask-policy.js +4 -4
  16. package/dist/agent.d.ts +20 -11
  17. package/dist/agent.js +200 -117
  18. package/dist/anthropic-thinking.d.ts +4 -0
  19. package/dist/anthropic-thinking.js +11 -0
  20. package/dist/approval/controller.d.ts +20 -6
  21. package/dist/approval/controller.js +67 -8
  22. package/dist/approval/protected-paths.d.ts +1 -0
  23. package/dist/approval/protected-paths.js +35 -0
  24. package/dist/approval/session-cache.d.ts +12 -26
  25. package/dist/approval/session-cache.js +20 -50
  26. package/dist/approval/types.d.ts +27 -1
  27. package/dist/cli.d.ts +5 -0
  28. package/dist/cli.js +25 -2
  29. package/dist/config.d.ts +3 -0
  30. package/dist/config.js +7 -0
  31. package/dist/context/checkpoint.d.ts +18 -0
  32. package/dist/context/checkpoint.js +117 -0
  33. package/dist/context/compact-llm.js +7 -0
  34. package/dist/context/compact.d.ts +8 -0
  35. package/dist/context/compact.js +40 -7
  36. package/dist/context/llm-compactor.d.ts +36 -2
  37. package/dist/context/llm-compactor.js +227 -44
  38. package/dist/context/session-write-lock.d.ts +20 -0
  39. package/dist/context/session-write-lock.js +162 -0
  40. package/dist/context/tool-images.d.ts +3 -0
  41. package/dist/context/tool-images.js +35 -0
  42. package/dist/context/usage.js +22 -5
  43. package/dist/feishu/agent-host/run-driver.js +56 -9
  44. package/dist/lsp/service.d.ts +13 -1
  45. package/dist/lsp/service.js +163 -43
  46. package/dist/main.js +82 -16
  47. package/dist/mcp/config.d.ts +4 -0
  48. package/dist/mcp/config.js +17 -0
  49. package/dist/mcp/manager.d.ts +13 -1
  50. package/dist/mcp/manager.js +32 -1
  51. package/dist/mcp/transports.js +11 -0
  52. package/dist/memory/db.d.ts +1 -0
  53. package/dist/memory/db.js +20 -4
  54. package/dist/memory/phase1.js +122 -16
  55. package/dist/memory/prompts.js +3 -0
  56. package/dist/model-catalog.js +19 -3
  57. package/dist/model-config.d.ts +1 -0
  58. package/dist/model-config.js +5 -5
  59. package/dist/model-pricing.js +26 -9
  60. package/dist/network/provider-transport-log.d.ts +12 -0
  61. package/dist/network/provider-transport-log.js +32 -0
  62. package/dist/network/provider-transport.js +6 -1
  63. package/dist/network/retry.d.ts +1 -1
  64. package/dist/network/retry.js +1 -1
  65. package/dist/oauth/grok.d.ts +1 -0
  66. package/dist/oauth/grok.js +20 -16
  67. package/dist/oauth/openai-codex.d.ts +1 -0
  68. package/dist/oauth/openai-codex.js +29 -25
  69. package/dist/oauth/refresh-control.d.ts +12 -0
  70. package/dist/oauth/refresh-control.js +42 -0
  71. package/dist/oauth/storage.d.ts +55 -1
  72. package/dist/oauth/storage.js +281 -16
  73. package/dist/permissions/rule.d.ts +6 -3
  74. package/dist/permissions/rule.js +71 -12
  75. package/dist/permissions/settings.d.ts +28 -1
  76. package/dist/permissions/settings.js +93 -3
  77. package/dist/permissions/shell-command.d.ts +36 -0
  78. package/dist/permissions/shell-command.js +226 -0
  79. package/dist/permissions/trust-prompt.d.ts +10 -0
  80. package/dist/permissions/trust-prompt.js +34 -0
  81. package/dist/permissions/trust.d.ts +26 -0
  82. package/dist/permissions/trust.js +113 -0
  83. package/dist/prompt/compose.d.ts +3 -0
  84. package/dist/prompt/compose.js +24 -7
  85. package/dist/prompt/environment.js +2 -2
  86. package/dist/prompt/reminders.js +1 -1
  87. package/dist/prompt/runtime.js +1 -1
  88. package/dist/provider-anthropic.d.ts +6 -2
  89. package/dist/provider-anthropic.js +98 -18
  90. package/dist/provider-error-record.d.ts +9 -0
  91. package/dist/provider-error-record.js +42 -14
  92. package/dist/provider-grok.js +5 -1
  93. package/dist/provider-openai-codex.d.ts +8 -0
  94. package/dist/provider-openai-codex.js +107 -24
  95. package/dist/provider-registry.d.ts +45 -2
  96. package/dist/provider-registry.js +300 -88
  97. package/dist/provider-transform.js +8 -0
  98. package/dist/provider-zen-errors.d.ts +9 -0
  99. package/dist/provider-zen-errors.js +36 -0
  100. package/dist/provider.js +36 -5
  101. package/dist/sdk/index.d.ts +69 -8
  102. package/dist/sdk/index.js +252 -39
  103. package/dist/sdk/replay-event-log.d.ts +7 -0
  104. package/dist/sdk/replay-event-log.js +66 -16
  105. package/dist/session-context-fence.d.ts +16 -0
  106. package/dist/session-context-fence.js +26 -0
  107. package/dist/session-log.d.ts +11 -2
  108. package/dist/session-log.js +187 -39
  109. package/dist/session-types.d.ts +5 -1
  110. package/dist/session.d.ts +39 -7
  111. package/dist/session.js +341 -93
  112. package/dist/skills/format.d.ts +31 -1
  113. package/dist/skills/format.js +45 -24
  114. package/dist/slash-commands/commands.d.ts +3 -0
  115. package/dist/slash-commands/commands.js +29 -14
  116. package/dist/system-prompt.d.ts +3 -1
  117. package/dist/tasks/manager.d.ts +7 -0
  118. package/dist/tasks/manager.js +97 -18
  119. package/dist/tools/agent-lifecycle.js +11 -7
  120. package/dist/tools/child-tools.d.ts +1 -1
  121. package/dist/tools/child-tools.js +4 -4
  122. package/dist/tools/edit-apply.d.ts +0 -3
  123. package/dist/tools/edit-apply.js +45 -249
  124. package/dist/tools/edit.js +3 -3
  125. package/dist/tools/exit-plan-mode.d.ts +5 -0
  126. package/dist/tools/exit-plan-mode.js +3 -2
  127. package/dist/tools/file-state.d.ts +4 -0
  128. package/dist/tools/file-state.js +12 -3
  129. package/dist/tools/grep.js +20 -1
  130. package/dist/tools/index.d.ts +1 -1
  131. package/dist/tools/index.js +3 -3
  132. package/dist/tools/ls.d.ts +3 -0
  133. package/dist/tools/ls.js +85 -0
  134. package/dist/tools/path-utils.d.ts +6 -0
  135. package/dist/tools/path-utils.js +38 -1
  136. package/dist/tools/sensitive-paths.d.ts +8 -0
  137. package/dist/tools/sensitive-paths.js +85 -3
  138. package/dist/tools/skill.d.ts +2 -0
  139. package/dist/tools/skill.js +34 -2
  140. package/dist/tools/task-tools.js +11 -7
  141. package/dist/tui/app.js +22 -12
  142. package/dist/tui/components/approval-dialog.d.ts +5 -5
  143. package/dist/tui/components/approval-dialog.js +16 -51
  144. package/dist/tui/components/skills-panel.d.ts +4 -0
  145. package/dist/tui/components/skills-panel.js +15 -1
  146. package/dist/tui/components/streaming-message.js +7 -2
  147. package/dist/tui/components/tasks-pane.d.ts +38 -0
  148. package/dist/tui/components/tasks-pane.js +182 -32
  149. package/dist/tui/components/transcript.d.ts +11 -4
  150. package/dist/tui/components/transcript.js +158 -71
  151. package/dist/tui/composer-autocomplete.d.ts +17 -2
  152. package/dist/tui/composer-autocomplete.js +79 -2
  153. package/dist/tui/controller/controller.d.ts +9 -4
  154. package/dist/tui/controller/controller.js +87 -95
  155. package/dist/tui/controller/goal-runtime-controller.js +1 -1
  156. package/dist/tui/controller/session-transition.js +1 -1
  157. package/dist/tui/model/subagent-view.d.ts +11 -19
  158. package/dist/tui/model/subagent-view.js +56 -85
  159. package/dist/tui/model/task-lifecycle.d.ts +57 -0
  160. package/dist/tui/model/task-lifecycle.js +124 -0
  161. package/dist/tui/model/trace-groups.js +10 -9
  162. package/dist/tui/trace-groups.js +10 -9
  163. package/dist/types.d.ts +20 -0
  164. package/dist/variant/variant-resolver.js +2 -0
  165. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/tui-alt-screen.d.ts +1 -0
  166. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/tui-alt-screen.d.ts.map +1 -1
  167. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/tui-alt-screen.js +6 -0
  168. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/tui-alt-screen.js.map +1 -1
  169. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/tui.d.ts +2 -0
  170. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/tui.d.ts.map +1 -1
  171. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/tui.js +8 -4
  172. package/node_modules/@bubblebrain-ai/pi-tui/dist/src/tui.js.map +1 -1
  173. package/package.json +11 -3
  174. package/dist/prompt/skills.d.ts +0 -2
  175. package/dist/prompt/skills.js +0 -4
  176. package/dist/tools/glob.d.ts +0 -5
  177. package/dist/tools/glob.js +0 -199
@@ -0,0 +1,36 @@
1
+ import { ProviderStreamInterruptedError } from "./network/retry.js";
2
+ /** Only Zen's opaque upstream rejection is recoverable, not arbitrary 422s. */
3
+ export function isSpaceBunnyUpstreamRejection(providerId, model, error) {
4
+ if (providerId !== "opencode-zen" || model !== "space-bunny-free")
5
+ return false;
6
+ const e = error;
7
+ return e?.status === 422 && typeof e.message === "string"
8
+ && /Upstream request failed:\s*\[invalid_request_error\]\s*unprocessable entity/i.test(e.message);
9
+ }
10
+ export function recoverableSpaceBunnyError(error) {
11
+ return new ProviderStreamInterruptedError("Space Bunny upstream rejected the request (422); retrying the model request.", {
12
+ cause: error, maxRetries: 2,
13
+ });
14
+ }
15
+ /** Counts only: never persist prompts, tool arguments, URLs or API headers. */
16
+ export function chatRequestShape(body) {
17
+ const messages = body.messages ?? [];
18
+ const shape = { messages: messages.length, tools: body.tools?.length ?? 0, assistant: 0,
19
+ emptyAssistant: 0, reasoning: 0, toolCalls: 0, toolResults: 0, contentChars: 0 };
20
+ for (const m of messages) {
21
+ if (typeof m.content === "string")
22
+ shape.contentChars += m.content.length;
23
+ if (m.role === "assistant") {
24
+ shape.assistant++;
25
+ const calls = Array.isArray(m.tool_calls) ? m.tool_calls.length : 0;
26
+ shape.toolCalls += calls;
27
+ if (!m.content && !calls)
28
+ shape.emptyAssistant++;
29
+ if (m.reasoning_content)
30
+ shape.reasoning++;
31
+ }
32
+ if (m.role === "tool")
33
+ shape.toolResults++;
34
+ }
35
+ return shape;
36
+ }
package/dist/provider.js CHANGED
@@ -11,11 +11,13 @@ import { createAiSdkProvider } from "./provider-ai-sdk.js";
11
11
  import { createOpenAICodexProvider, isOpenAICodexBaseUrl } from "./provider-openai-codex.js";
12
12
  import { buildGrokSubscriptionHeaders, createGrokSubscriptionFetch, isGrokSubscriptionBaseUrl, } from "./provider-grok.js";
13
13
  import { getChatGptFetch } from "./network/chatgpt-transport.js";
14
+ import { createProviderFetch } from "./network/provider-transport.js";
15
+ import { chatRequestShape, isSpaceBunnyUpstreamRejection, recoverableSpaceBunnyError } from "./provider-zen-errors.js";
14
16
  import { createProviderProtocolArtifactFilter } from "./provider-artifacts.js";
15
17
  import { resolveProviderRequestConfig } from "./provider-transform.js";
16
18
  import { debugReasoningStream, summarizeDebugText } from "./reasoning-debug.js";
17
19
  import { isProviderResponseError, ProviderResponseError, RateLimitError, } from "./network/errors.js";
18
- import { isRetryableHttpStatus, ProviderStreamInterruptedError } from "./network/retry.js";
20
+ import { computeRetryDelayMs, isRetryableHttpStatus, ProviderStreamInterruptedError, sleepBeforeRetry } from "./network/retry.js";
19
21
  import { assertProviderModelAllowed } from "./provider-model-policy.js";
20
22
  // Diagnostic logger for tool-args byte-loss investigation. Activate with
21
23
  // BUBBLE_DEBUG_TOOL_ARGS=/path/to/log.jsonl (any writable path)
@@ -90,6 +92,18 @@ export function createProviderInstance(options) {
90
92
  return createArkResponsesProvider(options);
91
93
  }
92
94
  if (protocol === "openai-responses") {
95
+ if (options.providerId === "opencode-zen") {
96
+ // Existing Zen profiles explicitly store Responses for Muse. Dispatch
97
+ // by model at send time: Space Bunny rejects /responses with 400
98
+ // ModelProtocolUnsupported and uses /chat/completions instead.
99
+ const responses = createOpenAIResponsesProvider(options);
100
+ const chat = createProviderInstance({ ...options, protocol: "openai-chat" });
101
+ const forModel = (model) => model === "space-bunny-free" ? chat : responses;
102
+ return {
103
+ streamChat: (messages, chatOptions) => forModel(chatOptions.model).streamChat(messages, chatOptions),
104
+ complete: (messages, chatOptions) => forModel(chatOptions?.model).complete(messages, chatOptions),
105
+ };
106
+ }
93
107
  return createOpenAIResponsesProvider(options);
94
108
  }
95
109
  if (protocol === "ai-sdk") {
@@ -117,6 +131,9 @@ export function createProviderInstance(options) {
117
131
  baseURL: options.baseURL,
118
132
  timeout: resolveRequestTimeoutMs(process.env.BUBBLE_PROVIDER_REQUEST_TIMEOUT_MS),
119
133
  ...(Object.keys(defaultHeaders).length > 0 ? { defaultHeaders } : {}),
134
+ ...(options.providerId === "opencode-zen" ? {
135
+ fetch: createProviderFetch({ providerName: "OpenCode Zen" }),
136
+ } : {}),
120
137
  ...(grokSubscription
121
138
  ? {
122
139
  fetch: (options.grokAuth
@@ -175,6 +192,9 @@ export function createProviderInstance(options) {
175
192
  });
176
193
  }
177
194
  catch (error) {
195
+ if (!chatOptions.abortSignal?.aborted && isSpaceBunnyUpstreamRejection(options.providerId, chatOptions.model, error)) {
196
+ throw Object.assign(recoverableSpaceBunnyError(error), { requestShape: chatRequestShape(requestBody) });
197
+ }
178
198
  if (error?.status === 429) {
179
199
  const retryAfterHeader = error?.headers?.["retry-after"];
180
200
  const retryAfterSeconds = Number(retryAfterHeader);
@@ -216,6 +236,9 @@ export function createProviderInstance(options) {
216
236
  catch (error) {
217
237
  if (chatOptions.abortSignal?.aborted)
218
238
  throw error;
239
+ if (isSpaceBunnyUpstreamRejection(options.providerId, chatOptions.model, error)) {
240
+ throw Object.assign(recoverableSpaceBunnyError(error), { requestShape: chatRequestShape(body) });
241
+ }
219
242
  if (isProviderResponseError(error)) {
220
243
  const rateLimited = error.status === 429 || error.errorType === "rate_limit_exceeded";
221
244
  if (rateLimited && chatOptions.rateLimitPolicy === "defer") {
@@ -264,10 +287,17 @@ export function createProviderInstance(options) {
264
287
  if (requestConfig.reasoningEffort && requestConfig.reasoningEffort !== "off") {
265
288
  body.reasoning = { enabled: true };
266
289
  }
267
- const response = await client.chat.completions.create(body, {
268
- signal: chatOptions?.abortSignal,
269
- });
270
- return response.choices[0]?.message?.content ?? "";
290
+ for (let attempt = 0;; attempt++) {
291
+ try {
292
+ const response = await client.chat.completions.create(body, { signal: chatOptions?.abortSignal });
293
+ return response.choices[0]?.message?.content ?? "";
294
+ }
295
+ catch (error) {
296
+ if (chatOptions?.abortSignal?.aborted || attempt >= 2 || !isSpaceBunnyUpstreamRejection(options.providerId, body.model, error))
297
+ throw error;
298
+ await sleepBeforeRetry(computeRetryDelayMs(attempt + 1), chatOptions?.abortSignal);
299
+ }
300
+ }
271
301
  }
272
302
  return { streamChat, complete };
273
303
  }
@@ -301,6 +331,7 @@ function isMiniMaxOpenAICompatible(options) {
301
331
  function shouldRequestStreamUsage(options) {
302
332
  const providerId = (options.providerId || "").toLowerCase();
303
333
  return providerId === "openai"
334
+ || providerId === "opencode-zen"
304
335
  || providerId === "deepseek"
305
336
  || providerId === "moonshot-cn"
306
337
  || providerId === "moonshot-intl"
@@ -14,6 +14,7 @@
14
14
  * Runs under plain Node (>=20); nothing here touches the TUI layer.
15
15
  */
16
16
  import { type SessionSummary } from "../session.js";
17
+ import { type RepoCapabilities } from "../permissions/trust.js";
17
18
  import type { ApprovalDecision, ApprovalRequest } from "../approval/types.js";
18
19
  import { UserConfig } from "../config.js";
19
20
  import { ProviderRegistry } from "../provider-registry.js";
@@ -21,8 +22,13 @@ import type { ResolvedSubagentRoute } from "../agent/categories.js";
21
22
  import { type QuestionAnswer, type QuestionRequest } from "../question/controller.js";
22
23
  import { SkillRegistry } from "../skills/registry.js";
23
24
  import type { SkillSummary } from "../skills/types.js";
24
- import type { AgentEvent, AgentRunInput, ContentPart, Message, PermissionMode, Provider, ThinkingLevel } from "../types.js";
25
+ import type { AgentEvent, AgentRunInput, ContentPart, Message, PermissionMode, Provider, ThinkingLevel, ToolRegistryEntry } from "../types.js";
25
26
  export interface BubbleSdkOptions {
27
+ /** Optional process-local replay window. Active readers never lose unread
28
+ * events. Older cursors fail explicitly; restore durable session history.
29
+ * Omit for unlimited replay (the public SDK compatibility default). The
30
+ * first opener sets the shared process-local window for that session. */
31
+ sessionEventRetention?: number;
26
32
  /** Fallback working directory for sessions created without an explicit cwd. */
27
33
  defaultCwd?: string;
28
34
  /**
@@ -52,15 +58,46 @@ export interface TurnHandlers {
52
58
  onQuestion?: (req: QuestionRequest) => Promise<QuestionAnswer[] | null>;
53
59
  /** Plan-mode proposal. Return true to approve executing the plan. */
54
60
  onPlanApproval?: (planMarkdown: string) => Promise<boolean>;
61
+ /**
62
+ * Folder trust (Kimi Code style): the session folder's `.bubble` settings
63
+ * would enable allow rules, MCP servers or LSP servers the user has not
64
+ * trusted. Return true to trust them. Asked at most once per folder per SDK
65
+ * instance; without a handler, or on false, they stay off.
66
+ */
67
+ onProjectTrust?: (request: {
68
+ cwd: string;
69
+ pending: RepoCapabilities;
70
+ }) => Promise<boolean>;
55
71
  /** Fired once per turn after provider/model/tools are resolved, before the first event. */
56
72
  onStart?: (info: TurnStartInfo) => void;
57
73
  }
58
74
  export interface RunTurnOptions extends TurnHandlers {
75
+ /**
76
+ * Turn-scoped host capabilities. Never cached globally or given to subagents;
77
+ * follow-up turns the SDK starts for this turn (queued input, pending steers)
78
+ * reuse this turn's options, these included.
79
+ */
80
+ hostTools?: ToolRegistryEntry[];
81
+ /**
82
+ * Extra skill directories for this turn, e.g. skills a host app ships with.
83
+ * Searched after the user's own roots, so a user skill of the same name wins.
84
+ * Like hostTools, follow-up turns the SDK starts for this turn reuse them.
85
+ */
86
+ skillPaths?: string[];
59
87
  /** Plain text, or content parts (text + base64 images) for attachments. */
60
88
  prompt: string | ContentPart[];
89
+ /** Preserve an admitted input if cancelled before initialization records it. */
90
+ preserveInterruptedInput?: boolean;
61
91
  /** "provider:model" or bare model id (resolved against the default provider). */
62
92
  model?: string;
63
93
  mode?: PermissionMode;
94
+ /**
95
+ * Mode the turn switches to when the user approves a plan (only relevant
96
+ * when `mode` is "plan"). Hosts pass the mode the user had selected before
97
+ * entering plan mode, so approving a plan does not silently downgrade
98
+ * bypassPermissions to default. Defaults to "default".
99
+ */
100
+ planExitMode?: Exclude<PermissionMode, "plan">;
64
101
  thinkingLevel?: ThinkingLevel;
65
102
  /**
66
103
  * Extra text appended to the built system prompt. Lets hosts (and the eval
@@ -113,21 +150,24 @@ export interface SdkSessionEvent {
113
150
  turnId: string;
114
151
  event: AgentEvent;
115
152
  /**
116
- * Present only on the synthesized record that ends a turn abnormally.
117
- * Replay subscribers use it to tell "turn failed" from "turn still running";
118
- * the per-turn runTurn() iterator instead surfaces the thrown error.
153
+ * Marks a settled turn after cleanup and admission of any fallback steer.
154
+ * Successful turns mark agent_end; failures synthesize a turn_end record.
119
155
  */
120
156
  terminal?: SdkSessionTerminal;
121
157
  }
122
- export interface SdkSessionTerminal {
158
+ export type SdkSessionTerminal = {
159
+ kind: "completed";
160
+ } | {
123
161
  kind: "failed" | "cancelled";
124
162
  message: string;
125
- }
163
+ };
126
164
  export interface SdkStopOptions {
127
165
  /** Match Claude-style interruption: queued messages survive by default. */
128
166
  cancelQueued?: boolean;
129
167
  }
130
168
  export interface SdkSessionHandle extends SdkSessionRef {
169
+ /** Current replay cursor; snapshot before send to observe only new work. */
170
+ readonly latestSequence: number;
131
171
  /** Events from every turn in this session. Opening another handle reconnects from sequence 1. */
132
172
  readonly events: AsyncIterable<SdkSessionEvent>;
133
173
  /** Reconnect after the last sequence the host durably processed. */
@@ -142,12 +182,17 @@ export declare class BubbleSdk {
142
182
  readonly registry: ProviderRegistry;
143
183
  private readonly defaultCwd;
144
184
  private readonly mcpEnabled;
185
+ private readonly sessionEventRetention;
145
186
  private readonly cwdBySession;
146
187
  private readonly bashAllowlists;
188
+ private readonly sessionGrants;
147
189
  private readonly turnCoordinator;
148
190
  private readonly turnRuntimes;
149
191
  private readonly lastTurnOptions;
150
192
  private readonly mcpToolsByCwd;
193
+ private readonly mcpManagersByCwd;
194
+ /** Folders whose trust question was already put to the host. */
195
+ private readonly projectTrustAsked;
151
196
  private readonly inputIdNonce;
152
197
  private nextTurnInputPrefix;
153
198
  private nextDetachedInputId;
@@ -161,9 +206,14 @@ export declare class BubbleSdk {
161
206
  }): SdkSessionRef;
162
207
  openSession(sessionId: string): SdkSessionHandle;
163
208
  getHistory(sessionId: string): Message[];
209
+ /** Preserve an accepted desktop input cancelled before runTurn was admitted. */
210
+ recordInterruptedInput(sessionId: string, prompt: string | ContentPart[]): void;
211
+ private persistInterruptedInput;
164
212
  deleteSession(sessionId: string): Promise<void>;
165
213
  /** Interrupt the active turn. Queued turns survive unless cancelQueued is true. */
166
214
  stop(sessionId: string, options?: SdkStopOptions): number;
215
+ /** Stop and wait for persistence, cleanup, and terminal event publication. */
216
+ stopAndWait(sessionId: string, options?: SdkStopOptions): Promise<number>;
167
217
  /** Cancel queued turns without interrupting the turn that owns the session slot. */
168
218
  clearQueue(sessionId: string): number;
169
219
  getSessionRunState(sessionId: string): SdkSessionRunState;
@@ -174,7 +224,13 @@ export declare class BubbleSdk {
174
224
  steer(sessionId: string, content: string): SdkSteerResult;
175
225
  enqueueTurn(sessionId: string, options: RunTurnOptions): AsyncGenerator<AgentEvent>;
176
226
  queueTurn(sessionId: string, options: RunTurnOptions): AsyncGenerator<AgentEvent>;
177
- listSkills(cwd?: string): SkillSummary[];
227
+ listSkills(cwd?: string, skillPaths?: string[]): SkillSummary[];
228
+ /**
229
+ * Ask the host once per folder (onProjectTrust) before this turn loads the
230
+ * repository's allow rules, MCP servers and LSP servers. Trusting restarts
231
+ * the folder's MCP servers so newly trusted ones are available right away.
232
+ */
233
+ private resolveProjectTrust;
178
234
  /** Configured providers + default model, for a host's model picker. */
179
235
  getModelConfig(): {
180
236
  defaultProviderId: string;
@@ -205,13 +261,17 @@ export declare class BubbleSdk {
205
261
  private publishSessionEvent;
206
262
  private ownerForSession;
207
263
  private bashAllowlistFor;
264
+ private sessionGrantsFor;
208
265
  /**
209
266
  * Default cross-provider subagent factory over this SDK instance's own
210
267
  * registry — the same semantics as the TUI's createProviderForRoute. The
211
268
  * registry is reloaded first so a key added after construction works.
212
269
  */
213
270
  private defaultProviderFactory;
214
- /** MCP servers are started lazily, once per cwd (McpManager has no stop). */
271
+ /**
272
+ * MCP servers are started lazily, once per cwd, and restarted only when the
273
+ * repository's settings get trusted (resolveProjectTrust).
274
+ */
215
275
  private mcpToolsFor;
216
276
  private resolveSession;
217
277
  private resolveProvider;
@@ -236,6 +296,7 @@ export { SessionManager, getSessionsDir, type SessionSummary, type UserTurn, typ
236
296
  export { PermissionAwareApprovalController } from "../approval/controller.js";
237
297
  export { BashAllowlist } from "../approval/session-cache.js";
238
298
  export type { ApprovalController, ApprovalDecision, ApprovalRequest } from "../approval/types.js";
299
+ export type { RepoCapabilities } from "../permissions/trust.js";
239
300
  export { createAllTools, buildToolPromptOptions, type PlanController } from "../tools/index.js";
240
301
  export { buildSystemPrompt } from "../system-prompt.js";
241
302
  export { FileStateTracker } from "../tools/file-state.js";