@bubblebrain-ai/bubble 0.0.1

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 (248) hide show
  1. package/README.md +70 -0
  2. package/dist/agent/evidence-tracker.d.ts +15 -0
  3. package/dist/agent/evidence-tracker.js +93 -0
  4. package/dist/agent/execution-governor.d.ts +30 -0
  5. package/dist/agent/execution-governor.js +169 -0
  6. package/dist/agent/subtask-policy.d.ts +14 -0
  7. package/dist/agent/subtask-policy.js +60 -0
  8. package/dist/agent/task-classifier.d.ts +3 -0
  9. package/dist/agent/task-classifier.js +36 -0
  10. package/dist/agent/tool-arbiter.d.ts +7 -0
  11. package/dist/agent/tool-arbiter.js +33 -0
  12. package/dist/agent/tool-intent.d.ts +20 -0
  13. package/dist/agent/tool-intent.js +176 -0
  14. package/dist/agent.d.ts +95 -0
  15. package/dist/agent.js +672 -0
  16. package/dist/approval/controller.d.ts +48 -0
  17. package/dist/approval/controller.js +78 -0
  18. package/dist/approval/danger.d.ts +13 -0
  19. package/dist/approval/danger.js +55 -0
  20. package/dist/approval/diff-hunks.d.ts +12 -0
  21. package/dist/approval/diff-hunks.js +32 -0
  22. package/dist/approval/session-cache.d.ts +35 -0
  23. package/dist/approval/session-cache.js +68 -0
  24. package/dist/approval/tool-helper.d.ts +14 -0
  25. package/dist/approval/tool-helper.js +32 -0
  26. package/dist/approval/types.d.ts +56 -0
  27. package/dist/approval/types.js +8 -0
  28. package/dist/bubble-home.d.ts +8 -0
  29. package/dist/bubble-home.js +19 -0
  30. package/dist/cli.d.ts +19 -0
  31. package/dist/cli.js +82 -0
  32. package/dist/config.d.ts +41 -0
  33. package/dist/config.js +144 -0
  34. package/dist/context/budget.d.ts +21 -0
  35. package/dist/context/budget.js +72 -0
  36. package/dist/context/compact-llm.d.ts +16 -0
  37. package/dist/context/compact-llm.js +132 -0
  38. package/dist/context/compact.d.ts +15 -0
  39. package/dist/context/compact.js +251 -0
  40. package/dist/context/overflow.d.ts +9 -0
  41. package/dist/context/overflow.js +46 -0
  42. package/dist/context/projector.d.ts +26 -0
  43. package/dist/context/projector.js +150 -0
  44. package/dist/context/prune.d.ts +9 -0
  45. package/dist/context/prune.js +111 -0
  46. package/dist/lsp/config.d.ts +18 -0
  47. package/dist/lsp/config.js +58 -0
  48. package/dist/lsp/diagnostics.d.ts +24 -0
  49. package/dist/lsp/diagnostics.js +103 -0
  50. package/dist/lsp/index.d.ts +3 -0
  51. package/dist/lsp/index.js +3 -0
  52. package/dist/lsp/service.d.ts +85 -0
  53. package/dist/lsp/service.js +695 -0
  54. package/dist/main.d.ts +5 -0
  55. package/dist/main.js +352 -0
  56. package/dist/mcp/client.d.ts +68 -0
  57. package/dist/mcp/client.js +163 -0
  58. package/dist/mcp/config.d.ts +26 -0
  59. package/dist/mcp/config.js +127 -0
  60. package/dist/mcp/manager.d.ts +55 -0
  61. package/dist/mcp/manager.js +296 -0
  62. package/dist/mcp/name.d.ts +26 -0
  63. package/dist/mcp/name.js +40 -0
  64. package/dist/mcp/transports.d.ts +53 -0
  65. package/dist/mcp/transports.js +248 -0
  66. package/dist/mcp/types.d.ts +111 -0
  67. package/dist/mcp/types.js +14 -0
  68. package/dist/memory/db.d.ts +62 -0
  69. package/dist/memory/db.js +313 -0
  70. package/dist/memory/index.d.ts +9 -0
  71. package/dist/memory/index.js +9 -0
  72. package/dist/memory/paths.d.ts +18 -0
  73. package/dist/memory/paths.js +38 -0
  74. package/dist/memory/phase1.d.ts +23 -0
  75. package/dist/memory/phase1.js +172 -0
  76. package/dist/memory/phase2.d.ts +19 -0
  77. package/dist/memory/phase2.js +100 -0
  78. package/dist/memory/prompts.d.ts +19 -0
  79. package/dist/memory/prompts.js +99 -0
  80. package/dist/memory/reset.d.ts +1 -0
  81. package/dist/memory/reset.js +13 -0
  82. package/dist/memory/start.d.ts +24 -0
  83. package/dist/memory/start.js +50 -0
  84. package/dist/memory/storage.d.ts +10 -0
  85. package/dist/memory/storage.js +82 -0
  86. package/dist/memory/store.d.ts +43 -0
  87. package/dist/memory/store.js +193 -0
  88. package/dist/memory/usage.d.ts +1 -0
  89. package/dist/memory/usage.js +38 -0
  90. package/dist/model-catalog.d.ts +20 -0
  91. package/dist/model-catalog.js +99 -0
  92. package/dist/model-config.d.ts +32 -0
  93. package/dist/model-config.js +59 -0
  94. package/dist/model-pricing.d.ts +23 -0
  95. package/dist/model-pricing.js +46 -0
  96. package/dist/oauth/index.d.ts +3 -0
  97. package/dist/oauth/index.js +2 -0
  98. package/dist/oauth/openai-codex.d.ts +9 -0
  99. package/dist/oauth/openai-codex.js +173 -0
  100. package/dist/oauth/storage.d.ts +18 -0
  101. package/dist/oauth/storage.js +60 -0
  102. package/dist/oauth/types.d.ts +15 -0
  103. package/dist/oauth/types.js +1 -0
  104. package/dist/orchestrator/default-hooks.d.ts +2 -0
  105. package/dist/orchestrator/default-hooks.js +96 -0
  106. package/dist/orchestrator/hooks.d.ts +78 -0
  107. package/dist/orchestrator/hooks.js +52 -0
  108. package/dist/orchestrator/workflow.d.ts +10 -0
  109. package/dist/orchestrator/workflow.js +22 -0
  110. package/dist/permission/mode.d.ts +23 -0
  111. package/dist/permission/mode.js +20 -0
  112. package/dist/permissions/rule.d.ts +39 -0
  113. package/dist/permissions/rule.js +234 -0
  114. package/dist/permissions/settings.d.ts +71 -0
  115. package/dist/permissions/settings.js +202 -0
  116. package/dist/permissions/types.d.ts +61 -0
  117. package/dist/permissions/types.js +14 -0
  118. package/dist/prompt/compose.d.ts +12 -0
  119. package/dist/prompt/compose.js +67 -0
  120. package/dist/prompt/environment.d.ts +12 -0
  121. package/dist/prompt/environment.js +38 -0
  122. package/dist/prompt/provider-prompts/anthropic.d.ts +1 -0
  123. package/dist/prompt/provider-prompts/anthropic.js +5 -0
  124. package/dist/prompt/provider-prompts/codex.d.ts +1 -0
  125. package/dist/prompt/provider-prompts/codex.js +5 -0
  126. package/dist/prompt/provider-prompts/default.d.ts +1 -0
  127. package/dist/prompt/provider-prompts/default.js +6 -0
  128. package/dist/prompt/provider-prompts/gemini.d.ts +1 -0
  129. package/dist/prompt/provider-prompts/gemini.js +5 -0
  130. package/dist/prompt/provider-prompts/gpt.d.ts +1 -0
  131. package/dist/prompt/provider-prompts/gpt.js +5 -0
  132. package/dist/prompt/reminders.d.ts +30 -0
  133. package/dist/prompt/reminders.js +164 -0
  134. package/dist/prompt/runtime.d.ts +12 -0
  135. package/dist/prompt/runtime.js +31 -0
  136. package/dist/prompt/skills.d.ts +2 -0
  137. package/dist/prompt/skills.js +4 -0
  138. package/dist/provider-openai-codex.d.ts +14 -0
  139. package/dist/provider-openai-codex.js +409 -0
  140. package/dist/provider-registry.d.ts +56 -0
  141. package/dist/provider-registry.js +244 -0
  142. package/dist/provider-transform.d.ts +10 -0
  143. package/dist/provider-transform.js +69 -0
  144. package/dist/provider.d.ts +31 -0
  145. package/dist/provider.js +269 -0
  146. package/dist/question/controller.d.ts +22 -0
  147. package/dist/question/controller.js +97 -0
  148. package/dist/question/index.d.ts +2 -0
  149. package/dist/question/index.js +2 -0
  150. package/dist/question/types.d.ts +42 -0
  151. package/dist/question/types.js +6 -0
  152. package/dist/session-log.d.ts +16 -0
  153. package/dist/session-log.js +267 -0
  154. package/dist/session-types.d.ts +55 -0
  155. package/dist/session-types.js +1 -0
  156. package/dist/session.d.ts +32 -0
  157. package/dist/session.js +135 -0
  158. package/dist/skills/discovery.d.ts +12 -0
  159. package/dist/skills/discovery.js +148 -0
  160. package/dist/skills/format.d.ts +2 -0
  161. package/dist/skills/format.js +47 -0
  162. package/dist/skills/frontmatter.d.ts +5 -0
  163. package/dist/skills/frontmatter.js +60 -0
  164. package/dist/skills/invocation.d.ts +8 -0
  165. package/dist/skills/invocation.js +51 -0
  166. package/dist/skills/registry.d.ts +17 -0
  167. package/dist/skills/registry.js +42 -0
  168. package/dist/skills/types.d.ts +32 -0
  169. package/dist/skills/types.js +1 -0
  170. package/dist/slash-commands/commands.d.ts +7 -0
  171. package/dist/slash-commands/commands.js +779 -0
  172. package/dist/slash-commands/index.d.ts +4 -0
  173. package/dist/slash-commands/index.js +8 -0
  174. package/dist/slash-commands/registry.d.ts +31 -0
  175. package/dist/slash-commands/registry.js +70 -0
  176. package/dist/slash-commands/types.d.ts +44 -0
  177. package/dist/slash-commands/types.js +1 -0
  178. package/dist/slash-commands/unified.d.ts +38 -0
  179. package/dist/slash-commands/unified.js +38 -0
  180. package/dist/system-prompt.d.ts +34 -0
  181. package/dist/system-prompt.js +7 -0
  182. package/dist/tools/bash.d.ts +6 -0
  183. package/dist/tools/bash.js +135 -0
  184. package/dist/tools/edit.d.ts +16 -0
  185. package/dist/tools/edit.js +95 -0
  186. package/dist/tools/exa-mcp.d.ts +3 -0
  187. package/dist/tools/exa-mcp.js +74 -0
  188. package/dist/tools/exit-plan-mode.d.ts +17 -0
  189. package/dist/tools/exit-plan-mode.js +68 -0
  190. package/dist/tools/glob.d.ts +5 -0
  191. package/dist/tools/glob.js +129 -0
  192. package/dist/tools/grep.d.ts +5 -0
  193. package/dist/tools/grep.js +111 -0
  194. package/dist/tools/index.d.ts +36 -0
  195. package/dist/tools/index.js +59 -0
  196. package/dist/tools/lsp.d.ts +4 -0
  197. package/dist/tools/lsp.js +92 -0
  198. package/dist/tools/memory.d.ts +3 -0
  199. package/dist/tools/memory.js +90 -0
  200. package/dist/tools/question.d.ts +3 -0
  201. package/dist/tools/question.js +174 -0
  202. package/dist/tools/read.d.ts +7 -0
  203. package/dist/tools/read.js +83 -0
  204. package/dist/tools/sensitive-paths.d.ts +3 -0
  205. package/dist/tools/sensitive-paths.js +24 -0
  206. package/dist/tools/skill.d.ts +5 -0
  207. package/dist/tools/skill.js +51 -0
  208. package/dist/tools/task.d.ts +2 -0
  209. package/dist/tools/task.js +57 -0
  210. package/dist/tools/todo.d.ts +12 -0
  211. package/dist/tools/todo.js +151 -0
  212. package/dist/tools/tool-search.d.ts +23 -0
  213. package/dist/tools/tool-search.js +124 -0
  214. package/dist/tools/web-fetch.d.ts +6 -0
  215. package/dist/tools/web-fetch.js +75 -0
  216. package/dist/tools/web-search.d.ts +5 -0
  217. package/dist/tools/web-search.js +49 -0
  218. package/dist/tools/write.d.ts +11 -0
  219. package/dist/tools/write.js +77 -0
  220. package/dist/tui/display-history.d.ts +35 -0
  221. package/dist/tui/display-history.js +243 -0
  222. package/dist/tui/file-mentions.d.ts +29 -0
  223. package/dist/tui/file-mentions.js +174 -0
  224. package/dist/tui/image-paste.d.ts +54 -0
  225. package/dist/tui/image-paste.js +288 -0
  226. package/dist/tui/markdown-theme-rules.d.ts +23 -0
  227. package/dist/tui/markdown-theme-rules.js +164 -0
  228. package/dist/tui/markdown-theme.d.ts +5 -0
  229. package/dist/tui/markdown-theme.js +27 -0
  230. package/dist/tui/opencode-spinner.d.ts +21 -0
  231. package/dist/tui/opencode-spinner.js +216 -0
  232. package/dist/tui/prompt-keybindings.d.ts +41 -0
  233. package/dist/tui/prompt-keybindings.js +28 -0
  234. package/dist/tui/recent-activity.d.ts +8 -0
  235. package/dist/tui/recent-activity.js +71 -0
  236. package/dist/tui/run.d.ts +39 -0
  237. package/dist/tui/run.js +5696 -0
  238. package/dist/tui/sidebar-mcp.d.ts +31 -0
  239. package/dist/tui/sidebar-mcp.js +62 -0
  240. package/dist/tui/sidebar-state.d.ts +12 -0
  241. package/dist/tui/sidebar-state.js +69 -0
  242. package/dist/types.d.ts +219 -0
  243. package/dist/types.js +4 -0
  244. package/dist/variant/thinking-level.d.ts +5 -0
  245. package/dist/variant/thinking-level.js +25 -0
  246. package/dist/variant/variant-resolver.d.ts +4 -0
  247. package/dist/variant/variant-resolver.js +12 -0
  248. package/package.json +47 -0
@@ -0,0 +1,38 @@
1
+ import { MemoryDatabase } from "./db.js";
2
+ import { existsSync, readFileSync } from "node:fs";
3
+ const CITATION_BLOCK_RE = /<oai-mem-citation>[\s\S]*?<citation_entries>([\s\S]*?)<\/citation_entries>[\s\S]*?<\/oai-mem-citation>/g;
4
+ const SESSION_RE = /session:\s*([^\n]+)/i;
5
+ export function recordMemoryCitations(cwd, text) {
6
+ const sessionFiles = [];
7
+ for (const match of text.matchAll(CITATION_BLOCK_RE)) {
8
+ const entries = match[1] ?? "";
9
+ for (const line of entries.split("\n")) {
10
+ const session = line.match(SESSION_RE)?.[1]?.trim();
11
+ if (session)
12
+ sessionFiles.push(session);
13
+ const citedPath = parseCitedPath(line);
14
+ if (citedPath && existsSync(citedPath)) {
15
+ const content = readFileSync(citedPath, "utf-8");
16
+ const citedSession = content.match(SESSION_RE)?.[1]?.trim();
17
+ if (citedSession)
18
+ sessionFiles.push(citedSession);
19
+ }
20
+ }
21
+ }
22
+ if (sessionFiles.length === 0)
23
+ return 0;
24
+ const db = new MemoryDatabase(cwd);
25
+ try {
26
+ return db.recordUsage(sessionFiles);
27
+ }
28
+ finally {
29
+ db.close();
30
+ }
31
+ }
32
+ function parseCitedPath(line) {
33
+ const trimmed = line.trim();
34
+ if (!trimmed)
35
+ return undefined;
36
+ const path = trimmed.split("|", 1)[0]?.replace(/:\d+(?:-\d+)?$/, "");
37
+ return path && path.startsWith("/") ? path : undefined;
38
+ }
@@ -0,0 +1,20 @@
1
+ import type { ReasoningEffort } from "./types.js";
2
+ export interface BuiltinProviderDefinition {
3
+ id: string;
4
+ name: string;
5
+ baseURL: string;
6
+ supportsOAuth?: boolean;
7
+ }
8
+ export interface BuiltinModelDefinition {
9
+ id: string;
10
+ name: string;
11
+ providerId: string;
12
+ reasoningLevels: ReasoningEffort[];
13
+ contextWindow?: number;
14
+ }
15
+ export declare const BUILTIN_PROVIDERS: BuiltinProviderDefinition[];
16
+ export declare const BUILTIN_MODELS: BuiltinModelDefinition[];
17
+ export declare function listBuiltinModels(providerId: string): BuiltinModelDefinition[];
18
+ export declare function getBuiltinModel(providerId: string, modelId: string): BuiltinModelDefinition | undefined;
19
+ export declare function getBuiltinProvider(providerId: string): BuiltinProviderDefinition | undefined;
20
+ export declare function getModelContextWindow(providerId: string, modelId: string): number | undefined;
@@ -0,0 +1,99 @@
1
+ export const BUILTIN_PROVIDERS = [
2
+ { id: "openrouter", name: "OpenRouter", baseURL: "https://openrouter.ai/api/v1" },
3
+ { id: "openai", name: "OpenAI", baseURL: "https://api.openai.com/v1", supportsOAuth: true },
4
+ { id: "openai-codex", name: "OpenAI Codex (ChatGPT)", baseURL: "https://chatgpt.com/backend-api" },
5
+ { id: "deepseek", name: "DeepSeek", baseURL: "https://api.deepseek.com" },
6
+ { id: "google", name: "Google", baseURL: "https://generativelanguage.googleapis.com/v1beta/openai" },
7
+ { id: "zhipuai", name: "Zhipu AI", baseURL: "https://open.bigmodel.cn/api/paas/v4" },
8
+ { id: "zhipuai-coding-plan", name: "Zhipu AI Coding Plan", baseURL: "https://open.bigmodel.cn/api/coding/paas/v4" },
9
+ { id: "zai", name: "Z.AI", baseURL: "https://api.z.ai/api/paas/v4" },
10
+ { id: "zai-coding-plan", name: "Z.AI Coding Plan", baseURL: "https://api.z.ai/api/coding/paas/v4" },
11
+ { id: "moonshot-cn", name: "Moonshot (国内 platform.moonshot.cn)", baseURL: "https://api.moonshot.cn/v1" },
12
+ { id: "moonshot-intl", name: "Moonshot (海外 platform.moonshot.ai)", baseURL: "https://api.moonshot.ai/v1" },
13
+ { id: "kimi-for-coding", name: "Kimi for Coding", baseURL: "https://api.kimi.com/coding/v1" },
14
+ { id: "groq", name: "Groq", baseURL: "https://api.groq.com/openai/v1" },
15
+ { id: "together", name: "Together AI", baseURL: "https://api.together.xyz/v1" },
16
+ { id: "fireworks", name: "Fireworks", baseURL: "https://api.fireworks.ai/inference/v1" },
17
+ { id: "local", name: "Local (OpenAI-compatible)", baseURL: "http://localhost:11434/v1" },
18
+ ];
19
+ const ALL_OPENAI_LEVELS = ["off", "minimal", "low", "medium", "high", "xhigh"];
20
+ const GPT51_LEVELS = ["off", "low", "medium", "high"];
21
+ const GPT51_CODEX_MAX_LEVELS = ["off", "low", "medium", "high", "xhigh"];
22
+ const GPT51_CODEX_MINI_LEVELS = ["off", "medium", "high"];
23
+ const OPENAI_CHAT_LEVELS = ["off"];
24
+ const TOGGLE_THINKING_LEVELS = ["off", "medium"];
25
+ const DEEPSEEK_V4_LEVELS = ["high", "max"];
26
+ export const BUILTIN_MODELS = [
27
+ { id: "gpt-5.4", name: "gpt-5.4", providerId: "openai-codex", reasoningLevels: ALL_OPENAI_LEVELS, contextWindow: 272000 },
28
+ { id: "gpt-5.4-mini", name: "gpt-5.4-mini", providerId: "openai-codex", reasoningLevels: ALL_OPENAI_LEVELS, contextWindow: 272000 },
29
+ { id: "gpt-5.3-codex", name: "gpt-5.3-codex", providerId: "openai-codex", reasoningLevels: ALL_OPENAI_LEVELS, contextWindow: 272000 },
30
+ { id: "gpt-5.3-codex-spark", name: "gpt-5.3-codex-spark", providerId: "openai-codex", reasoningLevels: ALL_OPENAI_LEVELS, contextWindow: 272000 },
31
+ { id: "gpt-5.2-codex", name: "gpt-5.2-codex", providerId: "openai-codex", reasoningLevels: ALL_OPENAI_LEVELS, contextWindow: 272000 },
32
+ { id: "gpt-5.2", name: "gpt-5.2", providerId: "openai-codex", reasoningLevels: ALL_OPENAI_LEVELS, contextWindow: 272000 },
33
+ { id: "gpt-5.1-codex-max", name: "gpt-5.1-codex-max", providerId: "openai-codex", reasoningLevels: GPT51_CODEX_MAX_LEVELS, contextWindow: 272000 },
34
+ { id: "gpt-5.1-codex-mini", name: "gpt-5.1-codex-mini", providerId: "openai-codex", reasoningLevels: GPT51_CODEX_MINI_LEVELS, contextWindow: 272000 },
35
+ { id: "gpt-5.1", name: "gpt-5.1", providerId: "openai-codex", reasoningLevels: GPT51_LEVELS, contextWindow: 272000 },
36
+ { id: "gpt-4o", name: "gpt-4o", providerId: "openai", reasoningLevels: OPENAI_CHAT_LEVELS, contextWindow: 128000 },
37
+ { id: "gpt-4o-mini", name: "gpt-4o-mini", providerId: "openai", reasoningLevels: OPENAI_CHAT_LEVELS, contextWindow: 128000 },
38
+ { id: "o1-preview", name: "o1-preview", providerId: "openai", reasoningLevels: ["off", "low", "medium", "high"], contextWindow: 128000 },
39
+ { id: "o1-mini", name: "o1-mini", providerId: "openai", reasoningLevels: ["off", "low", "medium", "high"], contextWindow: 128000 },
40
+ { id: "gpt-4-turbo", name: "gpt-4-turbo", providerId: "openai", reasoningLevels: OPENAI_CHAT_LEVELS, contextWindow: 128000 },
41
+ { id: "deepseek-v4-flash", name: "deepseek-v4-flash", providerId: "deepseek", reasoningLevels: DEEPSEEK_V4_LEVELS, contextWindow: 1048576 },
42
+ { id: "deepseek-v4-pro", name: "deepseek-v4-pro", providerId: "deepseek", reasoningLevels: DEEPSEEK_V4_LEVELS, contextWindow: 1048576 },
43
+ { id: "gemini-2.5-pro-preview-03-25", name: "gemini-2.5-pro-preview-03-25", providerId: "google", reasoningLevels: ["off", "low", "high"], contextWindow: 128000 },
44
+ { id: "gemini-2.0-flash-001", name: "gemini-2.0-flash-001", providerId: "google", reasoningLevels: ["off"], contextWindow: 128000 },
45
+ { id: "gemini-1.5-pro-latest", name: "gemini-1.5-pro-latest", providerId: "google", reasoningLevels: ["off"], contextWindow: 128000 },
46
+ { id: "glm-5.1", name: "GLM-5.1", providerId: "zhipuai", reasoningLevels: TOGGLE_THINKING_LEVELS, contextWindow: 200000 },
47
+ { id: "glm-4.7", name: "GLM-4.7", providerId: "zhipuai", reasoningLevels: TOGGLE_THINKING_LEVELS, contextWindow: 204800 },
48
+ { id: "glm-4.6", name: "GLM-4.6", providerId: "zhipuai", reasoningLevels: TOGGLE_THINKING_LEVELS, contextWindow: 204800 },
49
+ { id: "glm-5.1", name: "GLM-5.1", providerId: "zhipuai-coding-plan", reasoningLevels: TOGGLE_THINKING_LEVELS, contextWindow: 200000 },
50
+ { id: "glm-4.7", name: "GLM-4.7", providerId: "zhipuai-coding-plan", reasoningLevels: TOGGLE_THINKING_LEVELS, contextWindow: 204800 },
51
+ { id: "glm-4.6", name: "GLM-4.6", providerId: "zhipuai-coding-plan", reasoningLevels: TOGGLE_THINKING_LEVELS, contextWindow: 204800 },
52
+ { id: "glm-5.1", name: "GLM-5.1", providerId: "zai", reasoningLevels: TOGGLE_THINKING_LEVELS, contextWindow: 200000 },
53
+ { id: "glm-4.7", name: "GLM-4.7", providerId: "zai", reasoningLevels: TOGGLE_THINKING_LEVELS, contextWindow: 204800 },
54
+ { id: "glm-4.6", name: "GLM-4.6", providerId: "zai", reasoningLevels: TOGGLE_THINKING_LEVELS, contextWindow: 204800 },
55
+ { id: "glm-5-turbo", name: "GLM-5-Turbo", providerId: "zai-coding-plan", reasoningLevels: TOGGLE_THINKING_LEVELS, contextWindow: 200000 },
56
+ { id: "glm-4.7", name: "GLM-4.7", providerId: "zai-coding-plan", reasoningLevels: TOGGLE_THINKING_LEVELS, contextWindow: 204800 },
57
+ { id: "glm-4.6", name: "GLM-4.6", providerId: "zai-coding-plan", reasoningLevels: TOGGLE_THINKING_LEVELS, contextWindow: 200000 },
58
+ { id: "kimi-k2.6", name: "Kimi K2.6", providerId: "moonshot-cn", reasoningLevels: TOGGLE_THINKING_LEVELS, contextWindow: 256000 },
59
+ { id: "k2.6-code-preview", name: "Kimi K2.6 Code Preview", providerId: "moonshot-cn", reasoningLevels: TOGGLE_THINKING_LEVELS, contextWindow: 256000 },
60
+ { id: "kimi-k2.5", name: "Kimi K2.5", providerId: "moonshot-cn", reasoningLevels: TOGGLE_THINKING_LEVELS, contextWindow: 256000 },
61
+ { id: "kimi-k2-turbo-preview", name: "Kimi K2 Turbo", providerId: "moonshot-cn", reasoningLevels: ["off"], contextWindow: 256000 },
62
+ { id: "kimi-k2-0905-preview", name: "Kimi K2 0905", providerId: "moonshot-cn", reasoningLevels: ["off"], contextWindow: 256000 },
63
+ { id: "kimi-k2-thinking", name: "Kimi K2 Thinking", providerId: "moonshot-cn", reasoningLevels: TOGGLE_THINKING_LEVELS, contextWindow: 256000 },
64
+ { id: "kimi-k2.6", name: "Kimi K2.6", providerId: "moonshot-intl", reasoningLevels: TOGGLE_THINKING_LEVELS, contextWindow: 256000 },
65
+ { id: "k2.6-code-preview", name: "Kimi K2.6 Code Preview", providerId: "moonshot-intl", reasoningLevels: TOGGLE_THINKING_LEVELS, contextWindow: 256000 },
66
+ { id: "kimi-k2.5", name: "Kimi K2.5", providerId: "moonshot-intl", reasoningLevels: TOGGLE_THINKING_LEVELS, contextWindow: 256000 },
67
+ { id: "kimi-k2-turbo-preview", name: "Kimi K2 Turbo", providerId: "moonshot-intl", reasoningLevels: ["off"], contextWindow: 256000 },
68
+ { id: "kimi-k2-0905-preview", name: "Kimi K2 0905", providerId: "moonshot-intl", reasoningLevels: ["off"], contextWindow: 256000 },
69
+ { id: "kimi-k2-thinking", name: "Kimi K2 Thinking", providerId: "moonshot-intl", reasoningLevels: TOGGLE_THINKING_LEVELS, contextWindow: 256000 },
70
+ { id: "kimi-k2.6", name: "Kimi K2.6", providerId: "kimi-for-coding", reasoningLevels: TOGGLE_THINKING_LEVELS, contextWindow: 256000 },
71
+ { id: "k2.6-code-preview", name: "Kimi K2.6 Code Preview", providerId: "kimi-for-coding", reasoningLevels: TOGGLE_THINKING_LEVELS, contextWindow: 256000 },
72
+ { id: "kimi-k2-turbo-preview", name: "Kimi K2 Turbo", providerId: "kimi-for-coding", reasoningLevels: ["off"], contextWindow: 256000 },
73
+ { id: "kimi-k2-0905-preview", name: "Kimi K2 0905", providerId: "kimi-for-coding", reasoningLevels: ["off"], contextWindow: 256000 },
74
+ { id: "kimi-k2-thinking", name: "Kimi K2 Thinking", providerId: "kimi-for-coding", reasoningLevels: TOGGLE_THINKING_LEVELS, contextWindow: 256000 },
75
+ { id: "llama-3.3-70b-versatile", name: "llama-3.3-70b-versatile", providerId: "groq", reasoningLevels: ["off"], contextWindow: 32768 },
76
+ { id: "mixtral-8x7b-32768", name: "mixtral-8x7b-32768", providerId: "groq", reasoningLevels: ["off"], contextWindow: 32768 },
77
+ { id: "gemma-2-9b-it", name: "gemma-2-9b-it", providerId: "groq", reasoningLevels: ["off"], contextWindow: 32768 },
78
+ { id: "meta-llama/Llama-3.3-70B-Instruct-Turbo", name: "meta-llama/Llama-3.3-70B-Instruct-Turbo", providerId: "together", reasoningLevels: ["off"], contextWindow: 32768 },
79
+ { id: "Qwen/Qwen2.5-72B-Instruct", name: "Qwen/Qwen2.5-72B-Instruct", providerId: "together", reasoningLevels: ["off"], contextWindow: 32768 },
80
+ { id: "accounts/fireworks/models/kimi-k2p6", name: "Kimi K2.6", providerId: "fireworks", reasoningLevels: ["off"], contextWindow: 256000 },
81
+ { id: "llama3.1", name: "llama3.1", providerId: "local", reasoningLevels: ["off"], contextWindow: 32768 },
82
+ { id: "qwen2.5", name: "qwen2.5", providerId: "local", reasoningLevels: ["off"], contextWindow: 32768 },
83
+ { id: "deepseek-coder-v2", name: "deepseek-coder-v2", providerId: "local", reasoningLevels: ["off"], contextWindow: 32768 },
84
+ ];
85
+ export function listBuiltinModels(providerId) {
86
+ return BUILTIN_MODELS.filter((model) => model.providerId === providerId);
87
+ }
88
+ export function getBuiltinModel(providerId, modelId) {
89
+ return BUILTIN_MODELS.find((model) => model.providerId === providerId && model.id === modelId)
90
+ || (providerId === "openai"
91
+ ? BUILTIN_MODELS.find((model) => model.providerId === "openai-codex" && model.id === modelId)
92
+ : undefined);
93
+ }
94
+ export function getBuiltinProvider(providerId) {
95
+ return BUILTIN_PROVIDERS.find((provider) => provider.id === providerId);
96
+ }
97
+ export function getModelContextWindow(providerId, modelId) {
98
+ return getBuiltinModel(providerId, modelId)?.contextWindow;
99
+ }
@@ -0,0 +1,32 @@
1
+ /**
2
+ * models.json loader.
3
+ *
4
+ * Users can define providers, API keys, base URLs, and custom models
5
+ * in ~/.bubble/models.json.
6
+ */
7
+ import type { ModelInfo } from "./provider-registry.js";
8
+ export interface ProviderModelConfig {
9
+ baseURL?: string;
10
+ apiKey?: string;
11
+ models?: Array<{
12
+ id: string;
13
+ name?: string;
14
+ }>;
15
+ }
16
+ export interface ModelsConfig {
17
+ providers: Record<string, ProviderModelConfig>;
18
+ }
19
+ export declare class ModelConfig {
20
+ private data?;
21
+ private loadError?;
22
+ constructor();
23
+ private load;
24
+ getLoadError(): string | undefined;
25
+ getPath(): string;
26
+ getProviderConfig(providerId: string): ProviderModelConfig | undefined;
27
+ getAllProviders(): Record<string, ProviderModelConfig>;
28
+ hasProvider(providerId: string): boolean;
29
+ getCustomModels(providerId: string): ModelInfo[];
30
+ getApiKey(providerId: string): string | undefined;
31
+ getBaseURL(providerId: string): string | undefined;
32
+ }
@@ -0,0 +1,59 @@
1
+ /**
2
+ * models.json loader.
3
+ *
4
+ * Users can define providers, API keys, base URLs, and custom models
5
+ * in ~/.bubble/models.json.
6
+ */
7
+ import { existsSync, readFileSync } from "node:fs";
8
+ import { join } from "node:path";
9
+ import { homedir } from "node:os";
10
+ const MODELS_PATH = join(homedir(), ".bubble", "models.json");
11
+ export class ModelConfig {
12
+ data;
13
+ loadError;
14
+ constructor() {
15
+ this.load();
16
+ }
17
+ load() {
18
+ if (!existsSync(MODELS_PATH))
19
+ return;
20
+ try {
21
+ const raw = readFileSync(MODELS_PATH, "utf-8");
22
+ this.data = JSON.parse(raw);
23
+ }
24
+ catch (err) {
25
+ this.loadError = err.message;
26
+ }
27
+ }
28
+ getLoadError() {
29
+ return this.loadError;
30
+ }
31
+ getPath() {
32
+ return MODELS_PATH;
33
+ }
34
+ getProviderConfig(providerId) {
35
+ return this.data?.providers?.[providerId];
36
+ }
37
+ getAllProviders() {
38
+ return this.data?.providers ?? {};
39
+ }
40
+ hasProvider(providerId) {
41
+ return !!this.data?.providers?.[providerId];
42
+ }
43
+ getCustomModels(providerId) {
44
+ const cfg = this.data?.providers?.[providerId];
45
+ if (!cfg?.models)
46
+ return [];
47
+ return cfg.models.map((m) => ({
48
+ id: m.id,
49
+ name: m.name || m.id,
50
+ providerId,
51
+ }));
52
+ }
53
+ getApiKey(providerId) {
54
+ return this.data?.providers?.[providerId]?.apiKey;
55
+ }
56
+ getBaseURL(providerId) {
57
+ return this.data?.providers?.[providerId]?.baseURL;
58
+ }
59
+ }
@@ -0,0 +1,23 @@
1
+ import type { TokenUsage } from "./types.js";
2
+ export interface ModelPricing {
3
+ providerId: string;
4
+ modelId: string;
5
+ currency: "USD";
6
+ inputCacheHitPerMillion: number;
7
+ inputCacheMissPerMillion: number;
8
+ outputPerMillion: number;
9
+ effectiveUntil?: string;
10
+ original?: {
11
+ inputCacheHitPerMillion: number;
12
+ inputCacheMissPerMillion: number;
13
+ outputPerMillion: number;
14
+ };
15
+ }
16
+ export interface UsageCost {
17
+ currency: "USD";
18
+ cost: number;
19
+ estimated: boolean;
20
+ }
21
+ export declare const MODEL_PRICING: ModelPricing[];
22
+ export declare function getModelPricing(providerId: string, modelId: string): ModelPricing | undefined;
23
+ export declare function calculateUsageCost(providerId: string, modelId: string, usage: TokenUsage): UsageCost | undefined;
@@ -0,0 +1,46 @@
1
+ export const MODEL_PRICING = [
2
+ {
3
+ providerId: "deepseek",
4
+ modelId: "deepseek-v4-flash",
5
+ currency: "USD",
6
+ inputCacheHitPerMillion: 0.028,
7
+ inputCacheMissPerMillion: 0.14,
8
+ outputPerMillion: 0.28,
9
+ },
10
+ {
11
+ providerId: "deepseek",
12
+ modelId: "deepseek-v4-pro",
13
+ currency: "USD",
14
+ inputCacheHitPerMillion: 0.03625,
15
+ inputCacheMissPerMillion: 0.435,
16
+ outputPerMillion: 0.87,
17
+ effectiveUntil: "2026-05-05T15:59:00Z",
18
+ original: {
19
+ inputCacheHitPerMillion: 0.145,
20
+ inputCacheMissPerMillion: 1.74,
21
+ outputPerMillion: 3.48,
22
+ },
23
+ },
24
+ ];
25
+ export function getModelPricing(providerId, modelId) {
26
+ return MODEL_PRICING.find((item) => item.providerId === providerId && item.modelId === modelId);
27
+ }
28
+ export function calculateUsageCost(providerId, modelId, usage) {
29
+ const pricing = getModelPricing(providerId, modelId);
30
+ if (!pricing)
31
+ return undefined;
32
+ const hasCacheBreakdown = typeof usage.promptCacheHitTokens === "number"
33
+ || typeof usage.promptCacheMissTokens === "number";
34
+ const hit = usage.promptCacheHitTokens ?? 0;
35
+ const miss = hasCacheBreakdown
36
+ ? usage.promptCacheMissTokens ?? Math.max(0, usage.promptTokens - hit)
37
+ : usage.promptTokens;
38
+ const cost = (hit / 1_000_000) * pricing.inputCacheHitPerMillion
39
+ + (miss / 1_000_000) * pricing.inputCacheMissPerMillion
40
+ + (usage.completionTokens / 1_000_000) * pricing.outputPerMillion;
41
+ return {
42
+ currency: pricing.currency,
43
+ cost,
44
+ estimated: !hasCacheBreakdown,
45
+ };
46
+ }
@@ -0,0 +1,3 @@
1
+ export { AuthStorage } from "./storage.js";
2
+ export { loginOpenAICodex, refreshOpenAICodex, type OpenAICodexLoginCallbacks } from "./openai-codex.js";
3
+ export type { OAuthTokens, OAuthCredentials } from "./types.js";
@@ -0,0 +1,2 @@
1
+ export { AuthStorage } from "./storage.js";
2
+ export { loginOpenAICodex, refreshOpenAICodex } from "./openai-codex.js";
@@ -0,0 +1,9 @@
1
+ /**
2
+ * OpenAI Codex OAuth login (PKCE + local callback).
3
+ */
4
+ import type { OAuthTokens } from "./types.js";
5
+ export interface OpenAICodexLoginCallbacks {
6
+ onStatus: (message: string) => void;
7
+ }
8
+ export declare function loginOpenAICodex(callbacks?: OpenAICodexLoginCallbacks): Promise<OAuthTokens>;
9
+ export declare function refreshOpenAICodex(refreshToken: string): Promise<OAuthTokens>;
@@ -0,0 +1,173 @@
1
+ /**
2
+ * OpenAI Codex OAuth login (PKCE + local callback).
3
+ */
4
+ import { createServer } from "node:http";
5
+ import { exec } from "node:child_process";
6
+ import { randomBytes, createHash } from "node:crypto";
7
+ const CLIENT_ID = "app_EMoamEEZ73f0CkXaXp7hrann";
8
+ const AUTH_URL = "https://auth.openai.com/oauth/authorize";
9
+ const TOKEN_URL = "https://auth.openai.com/oauth/token";
10
+ const REDIRECT_URI = "http://localhost:1455/auth/callback";
11
+ const SCOPE = "openid profile email offline_access";
12
+ function generatePKCE() {
13
+ const codeVerifier = randomBytes(32).toString("base64url");
14
+ const codeChallenge = createHash("sha256").update(codeVerifier).digest("base64url");
15
+ return { codeVerifier, codeChallenge };
16
+ }
17
+ function generateState() {
18
+ return randomBytes(16).toString("hex");
19
+ }
20
+ function openBrowser(url) {
21
+ const cmd = process.platform === "darwin" ? "open" : process.platform === "win32" ? "start" : "xdg-open";
22
+ exec(`${cmd} ${JSON.stringify(url)}`, () => {
23
+ // ignore errors; we show manual fallback in UI
24
+ });
25
+ }
26
+ async function startCallbackServer(port, timeoutMs, onStatus) {
27
+ return new Promise((resolve, reject) => {
28
+ let resolved = false;
29
+ const server = createServer((req, res) => {
30
+ try {
31
+ const url = new URL(req.url || "/", `http://127.0.0.1:${port}`);
32
+ onStatus?.(`Received callback request: ${req.url}`);
33
+ if (url.pathname === "/auth/callback") {
34
+ const code = url.searchParams.get("code");
35
+ const state = url.searchParams.get("state");
36
+ const error = url.searchParams.get("error");
37
+ const errorDesc = url.searchParams.get("error_description");
38
+ if (error) {
39
+ res.writeHead(400, { "Content-Type": "text/html" });
40
+ res.end(`<html><body><h1>Authorization failed</h1><p>${errorDesc || error}</p></body></html>`);
41
+ if (!resolved) {
42
+ resolved = true;
43
+ server.close(() => reject(new Error(`OAuth error: ${errorDesc || error}`)));
44
+ }
45
+ return;
46
+ }
47
+ if (code) {
48
+ res.writeHead(200, { "Content-Type": "text/html" });
49
+ res.end(`<html><body><h1>Authorization successful</h1><p>You can close this window and return to the terminal.</p></body></html>`);
50
+ if (!resolved) {
51
+ resolved = true;
52
+ server.close(() => resolve({ code, state: state || "" }));
53
+ }
54
+ return;
55
+ }
56
+ }
57
+ res.writeHead(404);
58
+ res.end("Not found");
59
+ }
60
+ catch {
61
+ res.writeHead(500);
62
+ res.end("Error");
63
+ }
64
+ });
65
+ server.listen(port, "127.0.0.1", () => {
66
+ onStatus?.(`Local server listening on http://127.0.0.1:${port}`);
67
+ });
68
+ setTimeout(() => {
69
+ if (!resolved) {
70
+ resolved = true;
71
+ server.close(() => reject(new Error(`OAuth login timed out after ${timeoutMs / 1000}s`)));
72
+ }
73
+ }, timeoutMs);
74
+ });
75
+ }
76
+ function parseJWT(token) {
77
+ try {
78
+ const parts = token.split(".");
79
+ if (parts.length !== 3)
80
+ return null;
81
+ const payload = Buffer.from(parts[1], "base64url").toString("utf-8");
82
+ return JSON.parse(payload);
83
+ }
84
+ catch {
85
+ return null;
86
+ }
87
+ }
88
+ function extractAccountId(idToken) {
89
+ if (!idToken)
90
+ return undefined;
91
+ const claims = parseJWT(idToken);
92
+ const auth = claims?.["https://api.openai.com/auth"];
93
+ return auth?.chatgpt_account_id || auth?.account_id || claims?.sub;
94
+ }
95
+ export async function loginOpenAICodex(callbacks) {
96
+ callbacks?.onStatus("Starting OpenAI Codex OAuth login...");
97
+ const pkce = generatePKCE();
98
+ const state = generateState();
99
+ const params = new URLSearchParams({
100
+ response_type: "code",
101
+ client_id: CLIENT_ID,
102
+ redirect_uri: REDIRECT_URI,
103
+ scope: SCOPE,
104
+ code_challenge: pkce.codeChallenge,
105
+ code_challenge_method: "S256",
106
+ state,
107
+ id_token_add_organizations: "true",
108
+ codex_cli_simplified_flow: "true",
109
+ });
110
+ const authUrl = `${AUTH_URL}?${params.toString()}`;
111
+ callbacks?.onStatus("Starting local callback server on port 1455...");
112
+ const serverPromise = startCallbackServer(1455, 5 * 60 * 1000, callbacks?.onStatus);
113
+ callbacks?.onStatus("Opening browser for authorization...");
114
+ openBrowser(authUrl);
115
+ callbacks?.onStatus(`If your browser didn't open, copy this URL manually:\n${authUrl}`);
116
+ callbacks?.onStatus("Waiting for authorization (timeout: 5min)...");
117
+ const { code, state: returnedState } = await serverPromise;
118
+ if (returnedState !== state) {
119
+ throw new Error("OAuth state mismatch. Possible CSRF attack.");
120
+ }
121
+ callbacks?.onStatus("Exchanging authorization code for tokens...");
122
+ const response = await fetch(TOKEN_URL, {
123
+ method: "POST",
124
+ headers: { "Content-Type": "application/x-www-form-urlencoded" },
125
+ body: new URLSearchParams({
126
+ grant_type: "authorization_code",
127
+ code,
128
+ redirect_uri: REDIRECT_URI,
129
+ client_id: CLIENT_ID,
130
+ code_verifier: pkce.codeVerifier,
131
+ }),
132
+ });
133
+ if (!response.ok) {
134
+ const text = await response.text().catch(() => "Unknown error");
135
+ throw new Error(`Token exchange failed: ${response.status} ${response.statusText} - ${text}`);
136
+ }
137
+ const data = (await response.json());
138
+ const expiresAt = Date.now() + data.expires_in * 1000;
139
+ const accountId = extractAccountId(data.id_token);
140
+ callbacks?.onStatus("Login successful!");
141
+ return {
142
+ accessToken: data.access_token,
143
+ refreshToken: data.refresh_token,
144
+ expiresAt,
145
+ idToken: data.id_token,
146
+ accountId,
147
+ };
148
+ }
149
+ export async function refreshOpenAICodex(refreshToken) {
150
+ const response = await fetch(TOKEN_URL, {
151
+ method: "POST",
152
+ headers: { "Content-Type": "application/x-www-form-urlencoded" },
153
+ body: new URLSearchParams({
154
+ grant_type: "refresh_token",
155
+ refresh_token: refreshToken,
156
+ client_id: CLIENT_ID,
157
+ }),
158
+ });
159
+ if (!response.ok) {
160
+ const text = await response.text().catch(() => "Unknown error");
161
+ throw new Error(`Token refresh failed: ${response.status} ${response.statusText} - ${text}`);
162
+ }
163
+ const data = (await response.json());
164
+ const expiresAt = Date.now() + data.expires_in * 1000;
165
+ const accountId = extractAccountId(data.id_token);
166
+ return {
167
+ accessToken: data.access_token,
168
+ refreshToken: data.refresh_token || refreshToken,
169
+ expiresAt,
170
+ idToken: data.id_token,
171
+ accountId,
172
+ };
173
+ }
@@ -0,0 +1,18 @@
1
+ /**
2
+ * OAuth credential storage in ~/.bubble/auth.json
3
+ */
4
+ import type { OAuthCredentials } from "./types.js";
5
+ export declare class AuthStorage {
6
+ private data;
7
+ constructor();
8
+ private load;
9
+ private save;
10
+ getPath(): string;
11
+ get(providerId: string): OAuthCredentials | undefined;
12
+ set(providerId: string, creds: OAuthCredentials): void;
13
+ remove(providerId: string): void;
14
+ has(providerId: string): boolean;
15
+ isExpired(providerId: string, graceMs?: number): boolean;
16
+ getAccessToken(providerId: string): string | undefined;
17
+ list(): string[];
18
+ }
@@ -0,0 +1,60 @@
1
+ /**
2
+ * OAuth credential storage in ~/.bubble/auth.json
3
+ */
4
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
5
+ import { dirname, join } from "node:path";
6
+ import { homedir } from "node:os";
7
+ const AUTH_PATH = join(homedir(), ".bubble", "auth.json");
8
+ export class AuthStorage {
9
+ data = {};
10
+ constructor() {
11
+ this.load();
12
+ }
13
+ load() {
14
+ if (!existsSync(AUTH_PATH))
15
+ return;
16
+ try {
17
+ const raw = readFileSync(AUTH_PATH, "utf-8");
18
+ const parsed = JSON.parse(raw);
19
+ this.data = parsed;
20
+ }
21
+ catch {
22
+ this.data = {};
23
+ }
24
+ }
25
+ save() {
26
+ const dir = dirname(AUTH_PATH);
27
+ if (!existsSync(dir))
28
+ mkdirSync(dir, { recursive: true });
29
+ writeFileSync(AUTH_PATH, JSON.stringify(this.data, null, 2) + "\n", { mode: 0o600 });
30
+ }
31
+ getPath() {
32
+ return AUTH_PATH;
33
+ }
34
+ get(providerId) {
35
+ return this.data[providerId];
36
+ }
37
+ set(providerId, creds) {
38
+ this.data[providerId] = creds;
39
+ this.save();
40
+ }
41
+ remove(providerId) {
42
+ delete this.data[providerId];
43
+ this.save();
44
+ }
45
+ has(providerId) {
46
+ return !!this.data[providerId];
47
+ }
48
+ isExpired(providerId, graceMs = 5 * 60 * 1000) {
49
+ const creds = this.data[providerId];
50
+ if (!creds)
51
+ return true;
52
+ return Date.now() >= creds.expiresAt - graceMs;
53
+ }
54
+ getAccessToken(providerId) {
55
+ return this.data[providerId]?.accessToken;
56
+ }
57
+ list() {
58
+ return Object.keys(this.data);
59
+ }
60
+ }
@@ -0,0 +1,15 @@
1
+ export interface OAuthTokens {
2
+ accessToken: string;
3
+ refreshToken: string;
4
+ expiresAt: number;
5
+ idToken?: string;
6
+ accountId?: string;
7
+ }
8
+ export interface OAuthCredentials {
9
+ type: "oauth";
10
+ accessToken: string;
11
+ refreshToken: string;
12
+ expiresAt: number;
13
+ idToken?: string;
14
+ accountId?: string;
15
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,2 @@
1
+ import type { TurnHooks } from "./hooks.js";
2
+ export declare function createDefaultHooks(): TurnHooks[];