@mastra/code-sdk 1.0.3-alpha.1 → 1.1.0-alpha.2

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 (258) hide show
  1. package/CHANGELOG.md +38 -0
  2. package/dist/acp/agent.js +155 -167
  3. package/dist/acp/agent.js.map +1 -1
  4. package/dist/acp/event-mapper.js +193 -168
  5. package/dist/acp/event-mapper.js.map +1 -1
  6. package/dist/acp/index.js +60 -49
  7. package/dist/acp/index.js.map +1 -1
  8. package/dist/acp/server.js +31 -30
  9. package/dist/acp/server.js.map +1 -1
  10. package/dist/acp.js +1 -4
  11. package/dist/agents/credential-resolver.js +40 -29
  12. package/dist/agents/credential-resolver.js.map +1 -1
  13. package/dist/agents/custom-provider-source.js +16 -9
  14. package/dist/agents/custom-provider-source.js.map +1 -1
  15. package/dist/agents/instructions.js +27 -36
  16. package/dist/agents/instructions.js.map +1 -1
  17. package/dist/agents/mastracode-gateway.js +355 -428
  18. package/dist/agents/mastracode-gateway.js.map +1 -1
  19. package/dist/agents/memory.js +87 -78
  20. package/dist/agents/memory.js.map +1 -1
  21. package/dist/agents/model.js +114 -119
  22. package/dist/agents/model.js.map +1 -1
  23. package/dist/agents/modes/build.js +12 -13
  24. package/dist/agents/modes/build.js.map +1 -1
  25. package/dist/agents/modes/explore.js +14 -13
  26. package/dist/agents/modes/explore.js.map +1 -1
  27. package/dist/agents/modes/plan.js +14 -15
  28. package/dist/agents/modes/plan.js.map +1 -1
  29. package/dist/agents/prompts/agent-instructions.js +78 -69
  30. package/dist/agents/prompts/agent-instructions.js.map +1 -1
  31. package/dist/agents/prompts/build.js +19 -16
  32. package/dist/agents/prompts/build.js.map +1 -1
  33. package/dist/agents/prompts/fast.js +8 -4
  34. package/dist/agents/prompts/fast.js.map +1 -1
  35. package/dist/agents/prompts/index.js +48 -47
  36. package/dist/agents/prompts/index.js.map +1 -1
  37. package/dist/agents/prompts/model.js +6 -5
  38. package/dist/agents/prompts/model.js.map +1 -1
  39. package/dist/agents/prompts/plan.js +20 -16
  40. package/dist/agents/prompts/plan.js.map +1 -1
  41. package/dist/agents/prompts/tool-guidance.js +77 -109
  42. package/dist/agents/prompts/tool-guidance.js.map +1 -1
  43. package/dist/agents/sandbox-filesystem.js +245 -259
  44. package/dist/agents/sandbox-filesystem.js.map +1 -1
  45. package/dist/agents/sandbox-reattach.js +9 -11
  46. package/dist/agents/sandbox-reattach.js.map +1 -1
  47. package/dist/agents/thread-caveman-state.js +92 -81
  48. package/dist/agents/thread-caveman-state.js.map +1 -1
  49. package/dist/agents/tool-availability.js +62 -80
  50. package/dist/agents/tool-availability.js.map +1 -1
  51. package/dist/agents/tools.js +99 -139
  52. package/dist/agents/tools.js.map +1 -1
  53. package/dist/agents/workspace.js +232 -225
  54. package/dist/agents/workspace.js.map +1 -1
  55. package/dist/analytics.js +139 -128
  56. package/dist/analytics.js.map +1 -1
  57. package/dist/auth/authorization-input.js +39 -25
  58. package/dist/auth/authorization-input.js.map +1 -1
  59. package/dist/auth/device-code.js +112 -80
  60. package/dist/auth/device-code.js.map +1 -1
  61. package/dist/auth/index.js +2 -9
  62. package/dist/auth/pkce.js +27 -16
  63. package/dist/auth/pkce.js.map +1 -1
  64. package/dist/auth/providers/anthropic.js +107 -93
  65. package/dist/auth/providers/anthropic.js.map +1 -1
  66. package/dist/auth/providers/github-copilot.js +304 -293
  67. package/dist/auth/providers/github-copilot.js.map +1 -1
  68. package/dist/auth/providers/openai-codex.js +442 -460
  69. package/dist/auth/providers/openai-codex.js.map +1 -1
  70. package/dist/auth/providers/xai.js +179 -145
  71. package/dist/auth/providers/xai.js.map +1 -1
  72. package/dist/auth/storage.js +182 -175
  73. package/dist/auth/storage.js.map +1 -1
  74. package/dist/auth/types.js +1 -1
  75. package/dist/clipboard/index.js +206 -172
  76. package/dist/clipboard/index.js.map +1 -1
  77. package/dist/constants.js +11 -16
  78. package/dist/constants.js.map +1 -1
  79. package/dist/error-classification.js +19 -11
  80. package/dist/error-classification.js.map +1 -1
  81. package/dist/evals/context-builder.js +145 -104
  82. package/dist/evals/context-builder.js.map +1 -1
  83. package/dist/evals/index.js +4 -7
  84. package/dist/evals/scorers/classify-command.js +62 -41
  85. package/dist/evals/scorers/classify-command.js.map +1 -1
  86. package/dist/evals/scorers/efficiency.js +239 -181
  87. package/dist/evals/scorers/efficiency.js.map +1 -1
  88. package/dist/evals/scorers/extract-tools.js +51 -47
  89. package/dist/evals/scorers/extract-tools.js.map +1 -1
  90. package/dist/evals/scorers/index.js +1 -5
  91. package/dist/evals/scorers/outcome.js +321 -212
  92. package/dist/evals/scorers/outcome.js.map +1 -1
  93. package/dist/goal-manager.js +266 -261
  94. package/dist/goal-manager.js.map +1 -1
  95. package/dist/goal-signal.js +14 -13
  96. package/dist/goal-signal.js.map +1 -1
  97. package/dist/headless/cli.js +153 -154
  98. package/dist/headless/cli.js.map +1 -1
  99. package/dist/headless/flags.js +180 -178
  100. package/dist/headless/flags.js.map +1 -1
  101. package/dist/headless/format.js +72 -71
  102. package/dist/headless/format.js.map +1 -1
  103. package/dist/headless/index.js +5 -31
  104. package/dist/headless/policy.js +35 -31
  105. package/dist/headless/policy.js.map +1 -1
  106. package/dist/headless/run-mc.js +332 -334
  107. package/dist/headless/run-mc.js.map +1 -1
  108. package/dist/headless/types.js +16 -7
  109. package/dist/headless/types.js.map +1 -1
  110. package/dist/hooks/config.js +56 -61
  111. package/dist/hooks/config.js.map +1 -1
  112. package/dist/hooks/executor.js +118 -116
  113. package/dist/hooks/executor.js.map +1 -1
  114. package/dist/hooks/index.js +4 -15
  115. package/dist/hooks/manager.js +221 -280
  116. package/dist/hooks/manager.js.map +1 -1
  117. package/dist/hooks/types.js +5 -4
  118. package/dist/hooks/types.js.map +1 -1
  119. package/dist/index.d.ts.map +1 -1
  120. package/dist/index.js +632 -712
  121. package/dist/index.js.map +1 -1
  122. package/dist/ipc/ipc-reporter.js +19 -22
  123. package/dist/ipc/ipc-reporter.js.map +1 -1
  124. package/dist/lsp/client.js +248 -306
  125. package/dist/lsp/client.js.map +1 -1
  126. package/dist/lsp/index.js +1 -6
  127. package/dist/lsp/language.js +39 -43
  128. package/dist/lsp/language.js.map +1 -1
  129. package/dist/lsp/manager.js +78 -93
  130. package/dist/lsp/manager.js.map +1 -1
  131. package/dist/lsp/server.js +151 -120
  132. package/dist/lsp/server.js.map +1 -1
  133. package/dist/lsp/workspace.js +50 -47
  134. package/dist/lsp/workspace.js.map +1 -1
  135. package/dist/mcp/config.js +210 -199
  136. package/dist/mcp/config.js.map +1 -1
  137. package/dist/mcp/index.js +2 -9
  138. package/dist/mcp/manager.js +482 -475
  139. package/dist/mcp/manager.js.map +1 -1
  140. package/dist/mcp/types.js +1 -1
  141. package/dist/onboarding/custom-packs.js +14 -17
  142. package/dist/onboarding/custom-packs.js.map +1 -1
  143. package/dist/onboarding/custom-providers.js +22 -20
  144. package/dist/onboarding/custom-providers.js.map +1 -1
  145. package/dist/onboarding/index.d.ts +1 -1
  146. package/dist/onboarding/index.d.ts.map +1 -1
  147. package/dist/onboarding/index.js +3 -21
  148. package/dist/onboarding/om-settings.d.ts +5 -0
  149. package/dist/onboarding/om-settings.d.ts.map +1 -1
  150. package/dist/onboarding/om-settings.js +41 -20
  151. package/dist/onboarding/om-settings.js.map +1 -1
  152. package/dist/onboarding/packs.d.ts +4 -6
  153. package/dist/onboarding/packs.d.ts.map +1 -1
  154. package/dist/onboarding/packs.js +154 -105
  155. package/dist/onboarding/packs.js.map +1 -1
  156. package/dist/onboarding/settings.js +575 -517
  157. package/dist/onboarding/settings.js.map +1 -1
  158. package/dist/permissions.js +112 -99
  159. package/dist/permissions.js.map +1 -1
  160. package/dist/plugin.js +21 -23
  161. package/dist/plugin.js.map +1 -1
  162. package/dist/plugins/dependencies.js +64 -87
  163. package/dist/plugins/dependencies.js.map +1 -1
  164. package/dist/plugins/install.js +159 -169
  165. package/dist/plugins/install.js.map +1 -1
  166. package/dist/plugins/loader.js +170 -185
  167. package/dist/plugins/loader.js.map +1 -1
  168. package/dist/plugins/manager.js +374 -380
  169. package/dist/plugins/manager.js.map +1 -1
  170. package/dist/plugins/manifest.js +38 -63
  171. package/dist/plugins/manifest.js.map +1 -1
  172. package/dist/plugins/package-link.js +48 -64
  173. package/dist/plugins/package-link.js.map +1 -1
  174. package/dist/plugins/paths.js +18 -19
  175. package/dist/plugins/paths.js.map +1 -1
  176. package/dist/plugins/registry.js +97 -81
  177. package/dist/plugins/registry.js.map +1 -1
  178. package/dist/plugins/scaffold.js +62 -98
  179. package/dist/plugins/scaffold.js.map +1 -1
  180. package/dist/plugins/types.js +1 -1
  181. package/dist/processors/plan-rejection-abort.js +45 -44
  182. package/dist/processors/plan-rejection-abort.js.map +1 -1
  183. package/dist/providers/amazon-bedrock-gateway.js +134 -125
  184. package/dist/providers/amazon-bedrock-gateway.js.map +1 -1
  185. package/dist/providers/amazon-bedrock.js +68 -47
  186. package/dist/providers/amazon-bedrock.js.map +1 -1
  187. package/dist/providers/claude-max.js +153 -133
  188. package/dist/providers/claude-max.js.map +1 -1
  189. package/dist/providers/github-copilot.js +232 -230
  190. package/dist/providers/github-copilot.js.map +1 -1
  191. package/dist/providers/openai-codex.js +271 -260
  192. package/dist/providers/openai-codex.js.map +1 -1
  193. package/dist/providers/xai.js +57 -50
  194. package/dist/providers/xai.js.map +1 -1
  195. package/dist/schema.js +91 -89
  196. package/dist/schema.js.map +1 -1
  197. package/dist/theme-palette.js +18 -14
  198. package/dist/theme-palette.js.map +1 -1
  199. package/dist/tool-names.js +46 -37
  200. package/dist/tool-names.js.map +1 -1
  201. package/dist/tools/index.js +2 -8
  202. package/dist/tools/request-sandbox-access.js +71 -80
  203. package/dist/tools/request-sandbox-access.js.map +1 -1
  204. package/dist/tools/utils.js +26 -16
  205. package/dist/tools/utils.js.map +1 -1
  206. package/dist/tools/web-search.js +51 -55
  207. package/dist/tools/web-search.js.map +1 -1
  208. package/dist/utils/binaries.js +65 -61
  209. package/dist/utils/binaries.js.map +1 -1
  210. package/dist/utils/debug-log.js +51 -47
  211. package/dist/utils/debug-log.js.map +1 -1
  212. package/dist/utils/errors.js +157 -192
  213. package/dist/utils/errors.js.map +1 -1
  214. package/dist/utils/gateway-sync.js +49 -37
  215. package/dist/utils/gateway-sync.js.map +1 -1
  216. package/dist/utils/path-security.js +7 -6
  217. package/dist/utils/path-security.js.map +1 -1
  218. package/dist/utils/plan-diff.js +58 -39
  219. package/dist/utils/plan-diff.js.map +1 -1
  220. package/dist/utils/plans.js +92 -74
  221. package/dist/utils/plans.js.map +1 -1
  222. package/dist/utils/project.js +318 -256
  223. package/dist/utils/project.js.map +1 -1
  224. package/dist/utils/signals-pubsub.js +117 -99
  225. package/dist/utils/signals-pubsub.js.map +1 -1
  226. package/dist/utils/slash-command-loader.js +118 -154
  227. package/dist/utils/slash-command-loader.js.map +1 -1
  228. package/dist/utils/slash-command-processor.js +92 -83
  229. package/dist/utils/slash-command-processor.js.map +1 -1
  230. package/dist/utils/stdin-pipe.js +87 -63
  231. package/dist/utils/stdin-pipe.js.map +1 -1
  232. package/dist/utils/storage-factory.js +104 -84
  233. package/dist/utils/storage-factory.js.map +1 -1
  234. package/dist/utils/storage-maintenance.js +249 -211
  235. package/dist/utils/storage-maintenance.js.map +1 -1
  236. package/dist/utils/thread-lock.js +96 -92
  237. package/dist/utils/thread-lock.js.map +1 -1
  238. package/dist/utils/token-estimator.js +12 -12
  239. package/dist/utils/token-estimator.js.map +1 -1
  240. package/dist/utils/update-check.d.ts +1 -1
  241. package/dist/utils/update-check.js +341 -259
  242. package/dist/utils/update-check.js.map +1 -1
  243. package/dist/voice/stt-registry.js +131 -113
  244. package/dist/voice/stt-registry.js.map +1 -1
  245. package/package.json +12 -12
  246. package/dist/acp.js.map +0 -1
  247. package/dist/auth/index.js.map +0 -1
  248. package/dist/auth/types.js.map +0 -1
  249. package/dist/evals/index.js.map +0 -1
  250. package/dist/evals/scorers/index.js.map +0 -1
  251. package/dist/headless/index.js.map +0 -1
  252. package/dist/hooks/index.js.map +0 -1
  253. package/dist/lsp/index.js.map +0 -1
  254. package/dist/mcp/index.js.map +0 -1
  255. package/dist/mcp/types.js.map +0 -1
  256. package/dist/onboarding/index.js.map +0 -1
  257. package/dist/plugins/types.js.map +0 -1
  258. package/dist/tools/index.js.map +0 -1
@@ -1,598 +1,656 @@
1
- import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
2
- import { dirname, join } from "node:path";
1
+ import { getAppDataDir } from "../utils/project.js";
3
2
  import { AuthStorage } from "../auth/storage.js";
4
3
  import { buildCodexStagehandFetch, createCodexMiddleware } from "../providers/openai-codex.js";
5
- import { getAppDataDir } from "../utils/project.js";
6
4
  import { DEFAULT_STT_PROVIDER, resolveSTTModel } from "../voice/stt-registry.js";
5
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
6
+ import { dirname, join } from "path";
7
+ //#region src/onboarding/settings.ts
8
+ /**
9
+ * Persistent global settings stored in the app data directory as settings.json.
10
+ * This file persists onboarding state AND user preferences (model choices, yolo, etc.)
11
+ * so they carry across threads and restarts.
12
+ */
13
+ /** Gateway provider key used in AuthStorage. */
7
14
  const MASTRA_GATEWAY_PROVIDER = "mastra-gateway";
15
+ /** Default gateway URL. */
8
16
  const MASTRA_GATEWAY_DEFAULT_URL = "https://gateway-api.mastra.ai";
17
+ /** @deprecated Renamed to {@link MASTRA_GATEWAY_PROVIDER}. */
9
18
  const MEMORY_GATEWAY_PROVIDER = MASTRA_GATEWAY_PROVIDER;
19
+ /** @deprecated Renamed to {@link MASTRA_GATEWAY_DEFAULT_URL}. */
10
20
  const MEMORY_GATEWAY_DEFAULT_URL = MASTRA_GATEWAY_DEFAULT_URL;
21
+ /** Auth key prefix for observability tokens stored per-resource in auth.json */
11
22
  const OBSERVABILITY_AUTH_PREFIX = "observability:";
12
23
  const STORAGE_DEFAULTS = {
13
- backend: "libsql",
14
- libsql: {},
15
- pg: {}
24
+ backend: "libsql",
25
+ libsql: {},
26
+ pg: {}
16
27
  };
28
+ /** Default STT engine: on-device macOS recognizer where available, else cloud. */
17
29
  function defaultVoiceEngine() {
18
- return process.platform === "darwin" ? "macos-native" : "cloud";
30
+ return process.platform === "darwin" ? "macos-native" : "cloud";
19
31
  }
20
32
  const DEFAULTS = {
21
- onboarding: {
22
- completedAt: null,
23
- skippedAt: null,
24
- version: 0,
25
- modePackId: null,
26
- omPackId: null,
27
- quietModePreferenceSelected: true
28
- },
29
- models: {
30
- activeModelPackId: null,
31
- modeDefaults: {},
32
- activeOmPackId: null,
33
- omModelOverride: null,
34
- observerModelOverride: null,
35
- reflectorModelOverride: null,
36
- omObservationThreshold: null,
37
- omReflectionThreshold: null,
38
- omCavemanObservations: null,
39
- omObserveAttachments: null,
40
- subagentModels: {},
41
- goalJudgeModel: null,
42
- goalMaxTurns: null
43
- },
44
- preferences: {
45
- yolo: null,
46
- theme: "auto",
47
- thinkingLevel: "off",
48
- quietMode: false,
49
- quietModeMaxToolPreviewLines: 2
50
- },
51
- storage: { ...STORAGE_DEFAULTS },
52
- customModelPacks: [],
53
- customProviders: [],
54
- modelUseCounts: {},
55
- updateDismissedVersion: null,
56
- memoryGateway: {},
57
- lsp: {},
58
- browser: {
59
- enabled: false,
60
- provider: "stagehand",
61
- headless: false,
62
- viewport: { width: 1280, height: 720 },
63
- stagehand: { env: "LOCAL" }
64
- },
65
- shellPassthrough: { mode: "default" },
66
- voice: { enabled: false, engine: defaultVoiceEngine(), provider: DEFAULT_STT_PROVIDER },
67
- signals: { unixSocketPubSub: false, experimentalGithubSignals: false },
68
- observability: { resources: {}, localTracing: false }
33
+ onboarding: {
34
+ completedAt: null,
35
+ skippedAt: null,
36
+ version: 0,
37
+ modePackId: null,
38
+ omPackId: null,
39
+ quietModePreferenceSelected: true
40
+ },
41
+ models: {
42
+ activeModelPackId: null,
43
+ modeDefaults: {},
44
+ activeOmPackId: null,
45
+ omModelOverride: null,
46
+ observerModelOverride: null,
47
+ reflectorModelOverride: null,
48
+ omObservationThreshold: null,
49
+ omReflectionThreshold: null,
50
+ omCavemanObservations: null,
51
+ omObserveAttachments: null,
52
+ subagentModels: {},
53
+ goalJudgeModel: null,
54
+ goalMaxTurns: null
55
+ },
56
+ preferences: {
57
+ yolo: null,
58
+ theme: "auto",
59
+ thinkingLevel: "off",
60
+ quietMode: false,
61
+ quietModeMaxToolPreviewLines: 2
62
+ },
63
+ storage: { ...STORAGE_DEFAULTS },
64
+ customModelPacks: [],
65
+ customProviders: [],
66
+ modelUseCounts: {},
67
+ updateDismissedVersion: null,
68
+ memoryGateway: {},
69
+ lsp: {},
70
+ browser: {
71
+ enabled: false,
72
+ provider: "stagehand",
73
+ headless: false,
74
+ viewport: {
75
+ width: 1280,
76
+ height: 720
77
+ },
78
+ stagehand: { env: "LOCAL" }
79
+ },
80
+ shellPassthrough: { mode: "default" },
81
+ voice: {
82
+ enabled: false,
83
+ engine: defaultVoiceEngine(),
84
+ provider: DEFAULT_STT_PROVIDER
85
+ },
86
+ signals: {
87
+ unixSocketPubSub: false,
88
+ experimentalGithubSignals: false
89
+ },
90
+ observability: {
91
+ resources: {},
92
+ localTracing: false
93
+ }
69
94
  };
70
- const THINKING_LEVEL_VALUES = ["off", "low", "medium", "high", "xhigh"];
95
+ const THINKING_LEVEL_VALUES = [
96
+ "off",
97
+ "low",
98
+ "medium",
99
+ "high",
100
+ "xhigh"
101
+ ];
71
102
  const QUIET_MODE_MAX_TOOL_PREVIEW_LINES_MAX = 8;
72
103
  const loadedSignalSettings = /* @__PURE__ */ new WeakMap();
73
104
  function cloneSignalSettings(signals) {
74
- return { ...signals };
105
+ return { ...signals };
75
106
  }
76
107
  function rememberLoadedSettings(settings) {
77
- loadedSignalSettings.set(settings, cloneSignalSettings(settings.signals));
78
- return settings;
108
+ loadedSignalSettings.set(settings, cloneSignalSettings(settings.signals));
109
+ return settings;
79
110
  }
80
111
  function signalSettingsEqual(left, right) {
81
- return left.unixSocketPubSub === right.unixSocketPubSub && left.experimentalGithubSignals === right.experimentalGithubSignals;
112
+ return left.unixSocketPubSub === right.unixSocketPubSub && left.experimentalGithubSignals === right.experimentalGithubSignals;
82
113
  }
83
114
  function parseThinkingLevel(value) {
84
- return typeof value === "string" && THINKING_LEVEL_VALUES.includes(value) ? value : DEFAULTS.preferences.thinkingLevel;
115
+ return typeof value === "string" && THINKING_LEVEL_VALUES.includes(value) ? value : DEFAULTS.preferences.thinkingLevel;
85
116
  }
86
117
  function parseQuietModeMaxToolPreviewLines(value) {
87
- const rawValue = typeof value === "number" && Number.isFinite(value) ? value : DEFAULTS.preferences.quietModeMaxToolPreviewLines;
88
- return Math.min(QUIET_MODE_MAX_TOOL_PREVIEW_LINES_MAX, Math.max(0, Math.floor(rawValue)));
118
+ const rawValue = typeof value === "number" && Number.isFinite(value) ? value : DEFAULTS.preferences.quietModeMaxToolPreviewLines;
119
+ return Math.min(QUIET_MODE_MAX_TOOL_PREVIEW_LINES_MAX, Math.max(0, Math.floor(rawValue)));
89
120
  }
90
121
  function parsePreferences(rawPreferences) {
91
- const raw = rawPreferences && typeof rawPreferences === "object" ? rawPreferences : {};
92
- return {
93
- ...DEFAULTS.preferences,
94
- ...raw,
95
- thinkingLevel: parseThinkingLevel(raw.thinkingLevel),
96
- quietModeMaxToolPreviewLines: parseQuietModeMaxToolPreviewLines(raw.quietModeMaxToolPreviewLines)
97
- };
122
+ const raw = rawPreferences && typeof rawPreferences === "object" ? rawPreferences : {};
123
+ return {
124
+ ...DEFAULTS.preferences,
125
+ ...raw,
126
+ thinkingLevel: parseThinkingLevel(raw.thinkingLevel),
127
+ quietModeMaxToolPreviewLines: parseQuietModeMaxToolPreviewLines(raw.quietModeMaxToolPreviewLines)
128
+ };
98
129
  }
99
130
  function parseSignalSettings(rawSignals) {
100
- const raw = rawSignals && typeof rawSignals === "object" ? rawSignals : {};
101
- return {
102
- unixSocketPubSub: typeof raw.unixSocketPubSub === "boolean" ? raw.unixSocketPubSub : DEFAULTS.signals.unixSocketPubSub,
103
- experimentalGithubSignals: typeof raw.experimentalGithubSignals === "boolean" ? raw.experimentalGithubSignals : DEFAULTS.signals.experimentalGithubSignals
104
- };
131
+ const raw = rawSignals && typeof rawSignals === "object" ? rawSignals : {};
132
+ return {
133
+ unixSocketPubSub: typeof raw.unixSocketPubSub === "boolean" ? raw.unixSocketPubSub : DEFAULTS.signals.unixSocketPubSub,
134
+ experimentalGithubSignals: typeof raw.experimentalGithubSignals === "boolean" ? raw.experimentalGithubSignals : DEFAULTS.signals.experimentalGithubSignals
135
+ };
105
136
  }
106
137
  function hasQuietModePreferenceSelected(rawOnboarding) {
107
- return Boolean(
108
- rawOnboarding && typeof rawOnboarding === "object" && Object.prototype.hasOwnProperty.call(rawOnboarding, "quietModePreferenceSelected")
109
- );
138
+ return Boolean(rawOnboarding && typeof rawOnboarding === "object" && Object.prototype.hasOwnProperty.call(rawOnboarding, "quietModePreferenceSelected"));
110
139
  }
111
140
  function applyQuietModePreferenceRollout(settings, rawOnboarding) {
112
- if (hasQuietModePreferenceSelected(rawOnboarding)) return;
113
- settings.onboarding.quietModePreferenceSelected = settings.preferences.quietMode === true;
141
+ if (hasQuietModePreferenceSelected(rawOnboarding)) return;
142
+ settings.onboarding.quietModePreferenceSelected = settings.preferences.quietMode === true;
114
143
  }
115
144
  function getNewInstallDefaults() {
116
- const settings = structuredClone(DEFAULTS);
117
- settings.preferences.quietMode = true;
118
- settings.onboarding.quietModePreferenceSelected = true;
119
- return settings;
145
+ const settings = structuredClone(DEFAULTS);
146
+ settings.preferences.quietMode = true;
147
+ settings.onboarding.quietModePreferenceSelected = true;
148
+ return settings;
120
149
  }
121
150
  function getSettingsPath() {
122
- return join(getAppDataDir(), "settings.json");
151
+ return join(getAppDataDir(), "settings.json");
123
152
  }
124
153
  function getCustomProviderId(name) {
125
- const slug = name.trim().toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
126
- return slug || "provider";
154
+ return name.trim().toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "") || "provider";
127
155
  }
128
156
  function toCustomProviderModelId(providerName, modelName) {
129
- const providerId = getCustomProviderId(providerName);
130
- const trimmedModelName = modelName.trim();
131
- const providerPrefix = `${providerId}/`;
132
- if (trimmedModelName.startsWith(providerPrefix)) {
133
- return trimmedModelName;
134
- }
135
- return `${providerId}/${trimmedModelName}`;
157
+ const providerId = getCustomProviderId(providerName);
158
+ const trimmedModelName = modelName.trim();
159
+ const providerPrefix = `${providerId}/`;
160
+ if (trimmedModelName.startsWith(providerPrefix)) return trimmedModelName;
161
+ return `${providerId}/${trimmedModelName}`;
136
162
  }
137
163
  function parseCustomProviders(rawProviders) {
138
- if (!Array.isArray(rawProviders)) return [];
139
- const parsedProviders = [];
140
- for (const rawProvider of rawProviders) {
141
- if (!rawProvider || typeof rawProvider !== "object") continue;
142
- const candidate = rawProvider;
143
- const name = typeof candidate.name === "string" ? candidate.name.trim() : "";
144
- const url = typeof candidate.url === "string" ? candidate.url.trim() : "";
145
- if (!name || !url) continue;
146
- const providerId = getCustomProviderId(name);
147
- const models = Array.isArray(candidate.models) ? [
148
- ...new Set(
149
- candidate.models.filter((model) => typeof model === "string").map((model) => model.trim()).map((model) => {
150
- const providerPrefix = `${providerId}/`;
151
- if (model.startsWith(providerPrefix)) {
152
- return model.slice(providerPrefix.length);
153
- }
154
- return model;
155
- })
156
- )
157
- ].filter((model) => model.length > 0) : [];
158
- const apiKey = typeof candidate.apiKey === "string" && candidate.apiKey.trim().length > 0 ? candidate.apiKey.trim() : void 0;
159
- parsedProviders.push({
160
- name,
161
- url,
162
- ...apiKey ? { apiKey } : {},
163
- models
164
- });
165
- }
166
- return parsedProviders;
164
+ if (!Array.isArray(rawProviders)) return [];
165
+ const parsedProviders = [];
166
+ for (const rawProvider of rawProviders) {
167
+ if (!rawProvider || typeof rawProvider !== "object") continue;
168
+ const candidate = rawProvider;
169
+ const name = typeof candidate.name === "string" ? candidate.name.trim() : "";
170
+ const url = typeof candidate.url === "string" ? candidate.url.trim() : "";
171
+ if (!name || !url) continue;
172
+ const providerId = getCustomProviderId(name);
173
+ const models = Array.isArray(candidate.models) ? [...new Set(candidate.models.filter((model) => typeof model === "string").map((model) => model.trim()).map((model) => {
174
+ const providerPrefix = `${providerId}/`;
175
+ if (model.startsWith(providerPrefix)) return model.slice(providerPrefix.length);
176
+ return model;
177
+ }))].filter((model) => model.length > 0) : [];
178
+ const apiKey = typeof candidate.apiKey === "string" && candidate.apiKey.trim().length > 0 ? candidate.apiKey.trim() : void 0;
179
+ parsedProviders.push({
180
+ name,
181
+ url,
182
+ ...apiKey ? { apiKey } : {},
183
+ models
184
+ });
185
+ }
186
+ return parsedProviders;
167
187
  }
168
188
  const BROWSER_PROVIDERS = /* @__PURE__ */ new Set(["stagehand", "agent-browser"]);
169
189
  const STAGEHAND_ENVS = /* @__PURE__ */ new Set(["LOCAL", "BROWSERBASE"]);
190
+ /**
191
+ * Deep-merge and validate browser settings from JSON.
192
+ * Explicitly validates types to handle malformed settings.json gracefully.
193
+ */
170
194
  function parseBrowserSettings(rawBrowser) {
171
- const raw = rawBrowser && typeof rawBrowser === "object" ? rawBrowser : {};
172
- const rawViewport = raw.viewport && typeof raw.viewport === "object" ? raw.viewport : {};
173
- const rawStagehand = raw.stagehand && typeof raw.stagehand === "object" ? raw.stagehand : {};
174
- const rawAgentBrowser = raw.agentBrowser && typeof raw.agentBrowser === "object" ? raw.agentBrowser : {};
175
- return {
176
- enabled: typeof raw.enabled === "boolean" ? raw.enabled : DEFAULTS.browser.enabled,
177
- provider: typeof raw.provider === "string" && BROWSER_PROVIDERS.has(raw.provider) ? raw.provider : DEFAULTS.browser.provider,
178
- headless: typeof raw.headless === "boolean" ? raw.headless : DEFAULTS.browser.headless,
179
- cdpUrl: typeof raw.cdpUrl === "string" && raw.cdpUrl.trim() ? raw.cdpUrl.trim() : void 0,
180
- profile: typeof raw.profile === "string" && raw.profile.trim() ? raw.profile.trim() : void 0,
181
- executablePath: typeof raw.executablePath === "string" && raw.executablePath.trim() ? raw.executablePath.trim() : void 0,
182
- viewport: {
183
- width: typeof rawViewport.width === "number" ? rawViewport.width : DEFAULTS.browser.viewport.width,
184
- height: typeof rawViewport.height === "number" ? rawViewport.height : DEFAULTS.browser.viewport.height
185
- },
186
- scope: typeof raw.scope === "string" && (raw.scope === "shared" || raw.scope === "thread") ? raw.scope : void 0,
187
- stagehand: {
188
- env: typeof rawStagehand.env === "string" && STAGEHAND_ENVS.has(rawStagehand.env) ? rawStagehand.env : DEFAULTS.browser.stagehand.env,
189
- ...typeof rawStagehand.apiKey === "string" && rawStagehand.apiKey.trim() ? { apiKey: rawStagehand.apiKey.trim() } : {},
190
- ...typeof rawStagehand.projectId === "string" && rawStagehand.projectId.trim() ? { projectId: rawStagehand.projectId.trim() } : {},
191
- ...typeof rawStagehand.preserveUserDataDir === "boolean" ? { preserveUserDataDir: rawStagehand.preserveUserDataDir } : {}
192
- },
193
- agentBrowser: typeof rawAgentBrowser.storageState === "string" && rawAgentBrowser.storageState.trim() ? { storageState: rawAgentBrowser.storageState.trim() } : void 0
194
- };
195
+ const raw = rawBrowser && typeof rawBrowser === "object" ? rawBrowser : {};
196
+ const rawViewport = raw.viewport && typeof raw.viewport === "object" ? raw.viewport : {};
197
+ const rawStagehand = raw.stagehand && typeof raw.stagehand === "object" ? raw.stagehand : {};
198
+ const rawAgentBrowser = raw.agentBrowser && typeof raw.agentBrowser === "object" ? raw.agentBrowser : {};
199
+ return {
200
+ enabled: typeof raw.enabled === "boolean" ? raw.enabled : DEFAULTS.browser.enabled,
201
+ provider: typeof raw.provider === "string" && BROWSER_PROVIDERS.has(raw.provider) ? raw.provider : DEFAULTS.browser.provider,
202
+ headless: typeof raw.headless === "boolean" ? raw.headless : DEFAULTS.browser.headless,
203
+ cdpUrl: typeof raw.cdpUrl === "string" && raw.cdpUrl.trim() ? raw.cdpUrl.trim() : void 0,
204
+ profile: typeof raw.profile === "string" && raw.profile.trim() ? raw.profile.trim() : void 0,
205
+ executablePath: typeof raw.executablePath === "string" && raw.executablePath.trim() ? raw.executablePath.trim() : void 0,
206
+ viewport: {
207
+ width: typeof rawViewport.width === "number" ? rawViewport.width : DEFAULTS.browser.viewport.width,
208
+ height: typeof rawViewport.height === "number" ? rawViewport.height : DEFAULTS.browser.viewport.height
209
+ },
210
+ scope: typeof raw.scope === "string" && (raw.scope === "shared" || raw.scope === "thread") ? raw.scope : void 0,
211
+ stagehand: {
212
+ env: typeof rawStagehand.env === "string" && STAGEHAND_ENVS.has(rawStagehand.env) ? rawStagehand.env : DEFAULTS.browser.stagehand.env,
213
+ ...typeof rawStagehand.apiKey === "string" && rawStagehand.apiKey.trim() ? { apiKey: rawStagehand.apiKey.trim() } : {},
214
+ ...typeof rawStagehand.projectId === "string" && rawStagehand.projectId.trim() ? { projectId: rawStagehand.projectId.trim() } : {},
215
+ ...typeof rawStagehand.preserveUserDataDir === "boolean" ? { preserveUserDataDir: rawStagehand.preserveUserDataDir } : {}
216
+ },
217
+ agentBrowser: typeof rawAgentBrowser.storageState === "string" && rawAgentBrowser.storageState.trim() ? { storageState: rawAgentBrowser.storageState.trim() } : void 0
218
+ };
195
219
  }
196
220
  function parseShellPassthroughSettings(rawShellPassthrough) {
197
- const raw = rawShellPassthrough && typeof rawShellPassthrough === "object" ? rawShellPassthrough : {};
198
- const executable = typeof raw.executable === "string" && raw.executable.trim() ? raw.executable.trim() : void 0;
199
- const family = typeof raw.family === "string" && raw.family.trim() ? raw.family.trim() : void 0;
200
- const mode = typeof raw.mode === "string" && raw.mode.trim() ? raw.mode.trim() : void 0;
201
- const defaultMode = executable ? void 0 : DEFAULTS.shellPassthrough.mode;
202
- return {
203
- ...mode ?? defaultMode ? { mode: mode ?? defaultMode } : {},
204
- ...executable ? { executable } : {},
205
- ...family ? { family } : {}
206
- };
221
+ const raw = rawShellPassthrough && typeof rawShellPassthrough === "object" ? rawShellPassthrough : {};
222
+ const executable = typeof raw.executable === "string" && raw.executable.trim() ? raw.executable.trim() : void 0;
223
+ const family = typeof raw.family === "string" && raw.family.trim() ? raw.family.trim() : void 0;
224
+ const mode = typeof raw.mode === "string" && raw.mode.trim() ? raw.mode.trim() : void 0;
225
+ const defaultMode = executable ? void 0 : DEFAULTS.shellPassthrough.mode;
226
+ return {
227
+ ...mode ?? defaultMode ? { mode: mode ?? defaultMode } : {},
228
+ ...executable ? { executable } : {},
229
+ ...family ? { family } : {}
230
+ };
207
231
  }
208
232
  function parseVoiceSettings(rawVoice) {
209
- const raw = rawVoice && typeof rawVoice === "object" ? rawVoice : {};
210
- const enabled = typeof raw.enabled === "boolean" ? raw.enabled : DEFAULTS.voice.enabled;
211
- const engine = raw.engine === "macos-native" || raw.engine === "cloud" ? raw.engine : defaultVoiceEngine();
212
- const provider = typeof raw.provider === "string" ? raw.provider : DEFAULTS.voice.provider;
213
- const model = typeof raw.model === "string" ? raw.model : void 0;
214
- const resolved = resolveSTTModel(provider, model);
215
- return {
216
- enabled,
217
- engine,
218
- provider: resolved.provider,
219
- model: resolved.model
220
- };
233
+ const raw = rawVoice && typeof rawVoice === "object" ? rawVoice : {};
234
+ const enabled = typeof raw.enabled === "boolean" ? raw.enabled : DEFAULTS.voice.enabled;
235
+ const engine = raw.engine === "macos-native" || raw.engine === "cloud" ? raw.engine : defaultVoiceEngine();
236
+ const resolved = resolveSTTModel(typeof raw.provider === "string" ? raw.provider : DEFAULTS.voice.provider, typeof raw.model === "string" ? raw.model : void 0);
237
+ return {
238
+ enabled,
239
+ engine,
240
+ provider: resolved.provider,
241
+ model: resolved.model
242
+ };
221
243
  }
222
244
  const VALID_PROJECT_ID = /^[a-zA-Z0-9_-]+$/;
223
245
  function parseObservabilitySettings(raw) {
224
- if (!raw || typeof raw !== "object") return { resources: {}, localTracing: false };
225
- const obj = raw;
226
- const localTracing = obj.localTracing === true;
227
- const rawResources = obj.resources;
228
- if (!rawResources || typeof rawResources !== "object") return { resources: {}, localTracing };
229
- const resources = {};
230
- for (const [key, val] of Object.entries(rawResources)) {
231
- if (val && typeof val === "object") {
232
- const v = val;
233
- if (typeof v.projectId === "string" && VALID_PROJECT_ID.test(v.projectId)) {
234
- resources[key] = {
235
- projectId: v.projectId,
236
- configuredAt: typeof v.configuredAt === "string" ? v.configuredAt : (/* @__PURE__ */ new Date()).toISOString()
237
- };
238
- }
239
- }
240
- }
241
- return { resources, localTracing };
242
- }
246
+ if (!raw || typeof raw !== "object") return {
247
+ resources: {},
248
+ localTracing: false
249
+ };
250
+ const obj = raw;
251
+ const localTracing = obj.localTracing === true;
252
+ const rawResources = obj.resources;
253
+ if (!rawResources || typeof rawResources !== "object") return {
254
+ resources: {},
255
+ localTracing
256
+ };
257
+ const resources = {};
258
+ for (const [key, val] of Object.entries(rawResources)) if (val && typeof val === "object") {
259
+ const v = val;
260
+ if (typeof v.projectId === "string" && VALID_PROJECT_ID.test(v.projectId)) resources[key] = {
261
+ projectId: v.projectId,
262
+ configuredAt: typeof v.configuredAt === "string" ? v.configuredAt : (/* @__PURE__ */ new Date()).toISOString()
263
+ };
264
+ }
265
+ return {
266
+ resources,
267
+ localTracing
268
+ };
269
+ }
270
+ /**
271
+ * One-time migration: move model-related data from auth.json to settings.json.
272
+ * Reads `_modelRanks`, `_modeModelId_*`, `_subagentModelId*` from auth.json,
273
+ * merges them into settings, removes them from auth.json, and writes both files.
274
+ * No-ops if auth.json has no _ prefixed model data.
275
+ */
243
276
  function migrateFromAuth(settingsPath) {
244
- const authPath = join(getAppDataDir(), "auth.json");
245
- if (!existsSync(authPath)) return false;
246
- let authData;
247
- try {
248
- authData = JSON.parse(readFileSync(authPath, "utf-8"));
249
- } catch {
250
- return false;
251
- }
252
- const modelKeys = Object.keys(authData).filter((k) => k.startsWith("_"));
253
- if (modelKeys.length === 0) return false;
254
- let settings;
255
- if (existsSync(settingsPath)) {
256
- try {
257
- const raw = JSON.parse(readFileSync(settingsPath, "utf-8"));
258
- settings = {
259
- onboarding: { ...DEFAULTS.onboarding, ...raw.onboarding },
260
- models: { ...DEFAULTS.models, ...raw.models },
261
- preferences: parsePreferences(raw.preferences),
262
- storage: {
263
- ...STORAGE_DEFAULTS,
264
- ...raw.storage,
265
- libsql: { ...STORAGE_DEFAULTS.libsql, ...raw.storage?.libsql },
266
- pg: { ...STORAGE_DEFAULTS.pg, ...raw.storage?.pg }
267
- },
268
- customModelPacks: Array.isArray(raw.customModelPacks) ? raw.customModelPacks : [],
269
- customProviders: parseCustomProviders(raw.customProviders),
270
- modelUseCounts: raw.modelUseCounts && typeof raw.modelUseCounts === "object" ? raw.modelUseCounts : {},
271
- updateDismissedVersion: typeof raw.updateDismissedVersion === "string" ? raw.updateDismissedVersion : null,
272
- memoryGateway: raw.memoryGateway && typeof raw.memoryGateway === "object" ? raw.memoryGateway : {},
273
- lsp: raw.lsp && typeof raw.lsp === "object" ? raw.lsp : void 0,
274
- browser: parseBrowserSettings(raw.browser),
275
- shellPassthrough: parseShellPassthroughSettings(raw.shellPassthrough),
276
- voice: parseVoiceSettings(raw.voice),
277
- signals: parseSignalSettings(raw.signals),
278
- observability: parseObservabilitySettings(raw.observability)
279
- };
280
- applyQuietModePreferenceRollout(settings, raw.onboarding);
281
- } catch {
282
- settings = structuredClone(DEFAULTS);
283
- }
284
- } else {
285
- settings = structuredClone(DEFAULTS);
286
- }
287
- if (authData._modelRanks && typeof authData._modelRanks === "object") {
288
- settings.modelUseCounts = { ...authData._modelRanks, ...settings.modelUseCounts };
289
- }
290
- for (const key of modelKeys) {
291
- const modeMatch = key.match(/^_modeModelId_(.+)$/);
292
- if (modeMatch?.[1] && typeof authData[key] === "string" && !settings.models.modeDefaults[modeMatch[1]]) {
293
- settings.models.modeDefaults[modeMatch[1]] = authData[key];
294
- }
295
- }
296
- for (const key of modelKeys) {
297
- if (key === "_subagentModelId" && typeof authData[key] === "string" && !settings.models.subagentModels["default"]) {
298
- settings.models.subagentModels["default"] = authData[key];
299
- }
300
- const saMatch = key.match(/^_subagentModelId_(.+)$/);
301
- if (saMatch?.[1] && typeof authData[key] === "string" && !settings.models.subagentModels[saMatch[1]]) {
302
- settings.models.subagentModels[saMatch[1]] = authData[key];
303
- }
304
- }
305
- saveSettings(settings, settingsPath);
306
- for (const key of modelKeys) {
307
- delete authData[key];
308
- }
309
- try {
310
- writeFileSync(authPath, JSON.stringify(authData, null, 2), "utf-8");
311
- } catch {
312
- }
313
- return true;
277
+ const authPath = join(getAppDataDir(), "auth.json");
278
+ if (!existsSync(authPath)) return false;
279
+ let authData;
280
+ try {
281
+ authData = JSON.parse(readFileSync(authPath, "utf-8"));
282
+ } catch {
283
+ return false;
284
+ }
285
+ const modelKeys = Object.keys(authData).filter((k) => k.startsWith("_"));
286
+ if (modelKeys.length === 0) return false;
287
+ let settings;
288
+ if (existsSync(settingsPath)) try {
289
+ const raw = JSON.parse(readFileSync(settingsPath, "utf-8"));
290
+ settings = {
291
+ onboarding: {
292
+ ...DEFAULTS.onboarding,
293
+ ...raw.onboarding
294
+ },
295
+ models: {
296
+ ...DEFAULTS.models,
297
+ ...raw.models
298
+ },
299
+ preferences: parsePreferences(raw.preferences),
300
+ storage: {
301
+ ...STORAGE_DEFAULTS,
302
+ ...raw.storage,
303
+ libsql: {
304
+ ...STORAGE_DEFAULTS.libsql,
305
+ ...raw.storage?.libsql
306
+ },
307
+ pg: {
308
+ ...STORAGE_DEFAULTS.pg,
309
+ ...raw.storage?.pg
310
+ }
311
+ },
312
+ customModelPacks: Array.isArray(raw.customModelPacks) ? raw.customModelPacks : [],
313
+ customProviders: parseCustomProviders(raw.customProviders),
314
+ modelUseCounts: raw.modelUseCounts && typeof raw.modelUseCounts === "object" ? raw.modelUseCounts : {},
315
+ updateDismissedVersion: typeof raw.updateDismissedVersion === "string" ? raw.updateDismissedVersion : null,
316
+ memoryGateway: raw.memoryGateway && typeof raw.memoryGateway === "object" ? raw.memoryGateway : {},
317
+ lsp: raw.lsp && typeof raw.lsp === "object" ? raw.lsp : void 0,
318
+ browser: parseBrowserSettings(raw.browser),
319
+ shellPassthrough: parseShellPassthroughSettings(raw.shellPassthrough),
320
+ voice: parseVoiceSettings(raw.voice),
321
+ signals: parseSignalSettings(raw.signals),
322
+ observability: parseObservabilitySettings(raw.observability)
323
+ };
324
+ applyQuietModePreferenceRollout(settings, raw.onboarding);
325
+ } catch {
326
+ settings = structuredClone(DEFAULTS);
327
+ }
328
+ else settings = structuredClone(DEFAULTS);
329
+ if (authData._modelRanks && typeof authData._modelRanks === "object") settings.modelUseCounts = {
330
+ ...authData._modelRanks,
331
+ ...settings.modelUseCounts
332
+ };
333
+ for (const key of modelKeys) {
334
+ const modeMatch = key.match(/^_modeModelId_(.+)$/);
335
+ if (modeMatch?.[1] && typeof authData[key] === "string" && !settings.models.modeDefaults[modeMatch[1]]) settings.models.modeDefaults[modeMatch[1]] = authData[key];
336
+ }
337
+ for (const key of modelKeys) {
338
+ if (key === "_subagentModelId" && typeof authData[key] === "string" && !settings.models.subagentModels["default"]) settings.models.subagentModels["default"] = authData[key];
339
+ const saMatch = key.match(/^_subagentModelId_(.+)$/);
340
+ if (saMatch?.[1] && typeof authData[key] === "string" && !settings.models.subagentModels[saMatch[1]]) settings.models.subagentModels[saMatch[1]] = authData[key];
341
+ }
342
+ saveSettings(settings, settingsPath);
343
+ for (const key of modelKeys) delete authData[key];
344
+ try {
345
+ writeFileSync(authPath, JSON.stringify(authData, null, 2), "utf-8");
346
+ } catch {}
347
+ return true;
314
348
  }
315
349
  const LEGACY_VARIED_MODELS = {
316
- plan: "openai/gpt-5.4",
317
- build: "anthropic/claude-sonnet-4-5",
318
- fast: "anthropic/claude-haiku-4-5"
350
+ plan: "openai/gpt-5.4",
351
+ build: "anthropic/claude-sonnet-4-5",
352
+ fast: "anthropic/claude-haiku-4-5"
319
353
  };
320
354
  function migrateLegacyVariedPack(settings) {
321
- const legacyPackId = "varied";
322
- const customPackId = "custom:varied";
323
- const hasLegacyReference = settings.models.activeModelPackId === legacyPackId || settings.onboarding.modePackId === legacyPackId;
324
- if (!hasLegacyReference) return false;
325
- const existingIdx = settings.customModelPacks.findIndex((p) => p.name === "varied");
326
- if (existingIdx >= 0) {
327
- const existing = settings.customModelPacks[existingIdx];
328
- const modelsMatch = Object.entries(LEGACY_VARIED_MODELS).every(([k, v]) => existing.models[k] === v);
329
- if (!modelsMatch) {
330
- existing.models = { ...LEGACY_VARIED_MODELS };
331
- }
332
- } else {
333
- settings.customModelPacks.push({
334
- name: "varied",
335
- models: { ...LEGACY_VARIED_MODELS },
336
- createdAt: (/* @__PURE__ */ new Date()).toISOString()
337
- });
338
- }
339
- if (settings.models.activeModelPackId === legacyPackId) {
340
- settings.models.activeModelPackId = customPackId;
341
- if (Object.keys(settings.models.modeDefaults).length === 0) {
342
- settings.models.modeDefaults = { ...LEGACY_VARIED_MODELS };
343
- }
344
- }
345
- if (settings.onboarding.modePackId === legacyPackId) {
346
- settings.onboarding.modePackId = customPackId;
347
- }
348
- return true;
355
+ const legacyPackId = "varied";
356
+ const customPackId = "custom:varied";
357
+ if (!(settings.models.activeModelPackId === legacyPackId || settings.onboarding.modePackId === legacyPackId)) return false;
358
+ const existingIdx = settings.customModelPacks.findIndex((p) => p.name === "varied");
359
+ if (existingIdx >= 0) {
360
+ const existing = settings.customModelPacks[existingIdx];
361
+ if (!Object.entries(LEGACY_VARIED_MODELS).every(([k, v]) => existing.models[k] === v)) existing.models = { ...LEGACY_VARIED_MODELS };
362
+ } else settings.customModelPacks.push({
363
+ name: "varied",
364
+ models: { ...LEGACY_VARIED_MODELS },
365
+ createdAt: (/* @__PURE__ */ new Date()).toISOString()
366
+ });
367
+ if (settings.models.activeModelPackId === legacyPackId) {
368
+ settings.models.activeModelPackId = customPackId;
369
+ if (Object.keys(settings.models.modeDefaults).length === 0) settings.models.modeDefaults = { ...LEGACY_VARIED_MODELS };
370
+ }
371
+ if (settings.onboarding.modePackId === legacyPackId) settings.onboarding.modePackId = customPackId;
372
+ return true;
349
373
  }
350
374
  function loadSettings(filePath = getSettingsPath()) {
351
- migrateFromAuth(filePath);
352
- if (!existsSync(filePath)) return rememberLoadedSettings(getNewInstallDefaults());
353
- try {
354
- const raw = JSON.parse(readFileSync(filePath, "utf-8"));
355
- const settings = {
356
- ...raw,
357
- onboarding: { ...DEFAULTS.onboarding, ...raw.onboarding },
358
- models: { ...DEFAULTS.models, ...raw.models },
359
- preferences: parsePreferences(raw.preferences),
360
- storage: {
361
- ...STORAGE_DEFAULTS,
362
- ...raw.storage,
363
- libsql: { ...STORAGE_DEFAULTS.libsql, ...raw.storage?.libsql },
364
- pg: { ...STORAGE_DEFAULTS.pg, ...raw.storage?.pg }
365
- },
366
- customModelPacks: Array.isArray(raw.customModelPacks) ? raw.customModelPacks : [],
367
- customProviders: parseCustomProviders(raw.customProviders),
368
- modelUseCounts: raw.modelUseCounts && typeof raw.modelUseCounts === "object" ? raw.modelUseCounts : {},
369
- updateDismissedVersion: typeof raw.updateDismissedVersion === "string" ? raw.updateDismissedVersion : null,
370
- memoryGateway: raw.memoryGateway && typeof raw.memoryGateway === "object" ? raw.memoryGateway : {},
371
- lsp: raw.lsp && typeof raw.lsp === "object" ? raw.lsp : void 0,
372
- browser: parseBrowserSettings(raw.browser),
373
- shellPassthrough: parseShellPassthroughSettings(raw.shellPassthrough),
374
- voice: parseVoiceSettings(raw.voice),
375
- signals: parseSignalSettings(raw.signals),
376
- observability: parseObservabilitySettings(raw.observability)
377
- };
378
- let settingsChanged = false;
379
- if (!hasQuietModePreferenceSelected(raw.onboarding)) {
380
- applyQuietModePreferenceRollout(settings, raw.onboarding);
381
- settingsChanged = true;
382
- }
383
- if (raw.models?.omModelId && !settings.models.omModelOverride) {
384
- settings.models.omModelOverride = raw.models.omModelId;
385
- settingsChanged = true;
386
- }
387
- if (migrateLegacyVariedPack(settings)) {
388
- settingsChanged = true;
389
- }
390
- if (settingsChanged) {
391
- saveSettings(settings, filePath);
392
- }
393
- return rememberLoadedSettings(settings);
394
- } catch {
395
- return rememberLoadedSettings(structuredClone(DEFAULTS));
396
- }
375
+ migrateFromAuth(filePath);
376
+ if (!existsSync(filePath)) return rememberLoadedSettings(getNewInstallDefaults());
377
+ try {
378
+ const raw = JSON.parse(readFileSync(filePath, "utf-8"));
379
+ const settings = {
380
+ ...raw,
381
+ onboarding: {
382
+ ...DEFAULTS.onboarding,
383
+ ...raw.onboarding
384
+ },
385
+ models: {
386
+ ...DEFAULTS.models,
387
+ ...raw.models
388
+ },
389
+ preferences: parsePreferences(raw.preferences),
390
+ storage: {
391
+ ...STORAGE_DEFAULTS,
392
+ ...raw.storage,
393
+ libsql: {
394
+ ...STORAGE_DEFAULTS.libsql,
395
+ ...raw.storage?.libsql
396
+ },
397
+ pg: {
398
+ ...STORAGE_DEFAULTS.pg,
399
+ ...raw.storage?.pg
400
+ }
401
+ },
402
+ customModelPacks: Array.isArray(raw.customModelPacks) ? raw.customModelPacks : [],
403
+ customProviders: parseCustomProviders(raw.customProviders),
404
+ modelUseCounts: raw.modelUseCounts && typeof raw.modelUseCounts === "object" ? raw.modelUseCounts : {},
405
+ updateDismissedVersion: typeof raw.updateDismissedVersion === "string" ? raw.updateDismissedVersion : null,
406
+ memoryGateway: raw.memoryGateway && typeof raw.memoryGateway === "object" ? raw.memoryGateway : {},
407
+ lsp: raw.lsp && typeof raw.lsp === "object" ? raw.lsp : void 0,
408
+ browser: parseBrowserSettings(raw.browser),
409
+ shellPassthrough: parseShellPassthroughSettings(raw.shellPassthrough),
410
+ voice: parseVoiceSettings(raw.voice),
411
+ signals: parseSignalSettings(raw.signals),
412
+ observability: parseObservabilitySettings(raw.observability)
413
+ };
414
+ let settingsChanged = false;
415
+ if (!hasQuietModePreferenceSelected(raw.onboarding)) {
416
+ applyQuietModePreferenceRollout(settings, raw.onboarding);
417
+ settingsChanged = true;
418
+ }
419
+ if (raw.models?.omModelId && !settings.models.omModelOverride) {
420
+ settings.models.omModelOverride = raw.models.omModelId;
421
+ settingsChanged = true;
422
+ }
423
+ if (migrateLegacyVariedPack(settings)) settingsChanged = true;
424
+ if (settingsChanged) saveSettings(settings, filePath);
425
+ return rememberLoadedSettings(settings);
426
+ } catch {
427
+ return rememberLoadedSettings(structuredClone(DEFAULTS));
428
+ }
397
429
  }
398
430
  const THREAD_ACTIVE_MODEL_PACK_ID_KEY = "activeModelPackId";
399
431
  function parseThreadSettings(metadata) {
400
- const modeModelIds = {};
401
- for (const [key, value] of Object.entries(metadata ?? {})) {
402
- const modeMatch = key.match(/^modeModelId_(.+)$/);
403
- if (modeMatch?.[1] && typeof value === "string" && value.length > 0) {
404
- modeModelIds[modeMatch[1]] = value;
405
- }
406
- }
407
- const rawPackId = metadata?.[THREAD_ACTIVE_MODEL_PACK_ID_KEY];
408
- const activeModelPackId = typeof rawPackId === "string" && rawPackId.length > 0 ? rawPackId : null;
409
- return {
410
- activeModelPackId,
411
- modeModelIds
412
- };
413
- }
432
+ const modeModelIds = {};
433
+ for (const [key, value] of Object.entries(metadata ?? {})) {
434
+ const modeMatch = key.match(/^modeModelId_(.+)$/);
435
+ if (modeMatch?.[1] && typeof value === "string" && value.length > 0) modeModelIds[modeMatch[1]] = value;
436
+ }
437
+ const rawPackId = metadata?.[THREAD_ACTIVE_MODEL_PACK_ID_KEY];
438
+ return {
439
+ activeModelPackId: typeof rawPackId === "string" && rawPackId.length > 0 ? rawPackId : null,
440
+ modeModelIds
441
+ };
442
+ }
443
+ /**
444
+ * Resolve active model pack id for the current thread.
445
+ *
446
+ * Priority:
447
+ * 1) explicit thread metadata activeModelPackId
448
+ * 2) inferred from thread modeModelId_* values
449
+ * 3) global settings.models.activeModelPackId
450
+ */
414
451
  function resolveThreadActiveModelPackId(settings, builtinPacks, metadata) {
415
- const threadSettings = parseThreadSettings(metadata);
416
- const isKnownPack = (packId) => {
417
- if (packId.startsWith("custom:")) {
418
- const name = packId.slice("custom:".length);
419
- return settings.customModelPacks.some((p) => p.name === name);
420
- }
421
- return builtinPacks.some((p) => p.id === packId);
422
- };
423
- if (threadSettings.activeModelPackId && isKnownPack(threadSettings.activeModelPackId)) {
424
- return threadSettings.activeModelPackId;
425
- }
426
- const allPacks = [
427
- ...builtinPacks,
428
- ...settings.customModelPacks.map((p) => ({ id: `custom:${p.name}`, models: p.models }))
429
- ];
430
- for (const pack of allPacks) {
431
- const packEntries = Object.entries(pack.models);
432
- const threadEntries = Object.keys(threadSettings.modeModelIds);
433
- const matches = packEntries.length === threadEntries.length && packEntries.every(([modeId, modelId]) => threadSettings.modeModelIds[modeId] === modelId);
434
- if (matches) return pack.id;
435
- }
436
- if (settings.models.activeModelPackId && isKnownPack(settings.models.activeModelPackId)) {
437
- return settings.models.activeModelPackId;
438
- }
439
- return null;
440
- }
452
+ const threadSettings = parseThreadSettings(metadata);
453
+ const isKnownPack = (packId) => {
454
+ if (packId.startsWith("custom:")) {
455
+ const name = packId.slice(7);
456
+ return settings.customModelPacks.some((p) => p.name === name);
457
+ }
458
+ return builtinPacks.some((p) => p.id === packId);
459
+ };
460
+ if (threadSettings.activeModelPackId && isKnownPack(threadSettings.activeModelPackId)) return threadSettings.activeModelPackId;
461
+ const allPacks = [...builtinPacks, ...settings.customModelPacks.map((p) => ({
462
+ id: `custom:${p.name}`,
463
+ models: p.models
464
+ }))];
465
+ for (const pack of allPacks) {
466
+ const packEntries = Object.entries(pack.models);
467
+ const threadEntries = Object.keys(threadSettings.modeModelIds);
468
+ if (packEntries.length === threadEntries.length && packEntries.every(([modeId, modelId]) => threadSettings.modeModelIds[modeId] === modelId)) return pack.id;
469
+ }
470
+ if (settings.models.activeModelPackId && isKnownPack(settings.models.activeModelPackId)) return settings.models.activeModelPackId;
471
+ return null;
472
+ }
473
+ /**
474
+ * Resolve effective per-mode model defaults.
475
+ *
476
+ * If `activeModelPackId` is set, looks up the pack (built-in or custom) and
477
+ * returns its models. Falls back to the explicit `modeDefaults` map.
478
+ *
479
+ * @param settings The loaded global settings.
480
+ * @param builtinPacks Built-in packs for the current provider access
481
+ * (from `getAvailableModePacks`). Pass `[]` if unavailable.
482
+ */
441
483
  function resolveModelDefaults(settings, builtinPacks) {
442
- const { activeModelPackId, modeDefaults } = settings.models;
443
- if (!activeModelPackId) return modeDefaults;
444
- if (activeModelPackId.startsWith("custom:")) {
445
- const name = activeModelPackId.slice("custom:".length);
446
- const pack = settings.customModelPacks.find((p) => p.name === name);
447
- if (pack) return pack.models;
448
- return modeDefaults;
449
- }
450
- const builtin = builtinPacks.find((p) => p.id === activeModelPackId);
451
- if (builtin) return builtin.models;
452
- return modeDefaults;
453
- }
484
+ const { activeModelPackId, modeDefaults } = settings.models;
485
+ if (!activeModelPackId) return modeDefaults;
486
+ if (activeModelPackId.startsWith("custom:")) {
487
+ const name = activeModelPackId.slice(7);
488
+ const pack = settings.customModelPacks.find((p) => p.name === name);
489
+ if (pack) return pack.models;
490
+ return modeDefaults;
491
+ }
492
+ const builtin = builtinPacks.find((p) => p.id === activeModelPackId);
493
+ if (builtin) return builtin.models;
494
+ return modeDefaults;
495
+ }
496
+ /**
497
+ * Resolve the effective model ID for one of the two OM roles.
498
+ *
499
+ * Lookup order:
500
+ * 1. The role-specific override (`observerModelOverride` /
501
+ * `reflectorModelOverride`) if set.
502
+ * 2. If `activeOmPackId` points at a built-in pack, that pack's model.
503
+ * 3. The shared `omModelOverride` fallback.
504
+ *
505
+ * @param settings The loaded global settings.
506
+ * @param role Which OM role to resolve (`'observer'` or `'reflector'`).
507
+ * @param builtinOmPacks Built-in OM packs for the current provider access
508
+ * (from `getAvailableOmPacks`). Pass `[]` if unavailable.
509
+ */
454
510
  function resolveOmRoleModel(settings, role, builtinOmPacks) {
455
- const { activeOmPackId, omModelOverride, observerModelOverride, reflectorModelOverride } = settings.models;
456
- const roleOverride = role === "observer" ? observerModelOverride : reflectorModelOverride;
457
- if (roleOverride) return roleOverride;
458
- if (!activeOmPackId) return omModelOverride;
459
- if (activeOmPackId === "custom") return omModelOverride;
460
- const pack = builtinOmPacks.find((p) => p.id === activeOmPackId);
461
- if (pack) return pack.modelId;
462
- return omModelOverride;
463
- }
511
+ const { activeOmPackId, omModelOverride, observerModelOverride, reflectorModelOverride } = settings.models;
512
+ const roleOverride = role === "observer" ? observerModelOverride : reflectorModelOverride;
513
+ if (roleOverride) return roleOverride;
514
+ if (!activeOmPackId) return omModelOverride;
515
+ if (activeOmPackId === "custom") return omModelOverride;
516
+ const pack = builtinOmPacks.find((p) => p.id === activeOmPackId);
517
+ if (pack) return pack.modelId;
518
+ return omModelOverride;
519
+ }
520
+ /**
521
+ * @deprecated Use `resolveOmRoleModel(settings, 'observer' | 'reflector', ...)`.
522
+ * Equivalent to resolving the observer role (existing callers set both observer
523
+ * and reflector to the same value).
524
+ */
464
525
  function resolveOmModel(settings, builtinOmPacks) {
465
- return resolveOmRoleModel(settings, "observer", builtinOmPacks);
526
+ return resolveOmRoleModel(settings, "observer", builtinOmPacks);
466
527
  }
467
528
  function getSignalSettingsForSave(settings, filePath) {
468
- const loadedSignals = loadedSignalSettings.get(settings);
469
- if (!loadedSignals || !signalSettingsEqual(settings.signals, loadedSignals) || !existsSync(filePath)) {
470
- return settings.signals;
471
- }
472
- try {
473
- const currentRaw = JSON.parse(readFileSync(filePath, "utf-8"));
474
- const currentSignals = parseSignalSettings(currentRaw.signals);
475
- if (!signalSettingsEqual(currentSignals, loadedSignals)) {
476
- return currentSignals;
477
- }
478
- } catch {
479
- }
480
- return settings.signals;
529
+ const loadedSignals = loadedSignalSettings.get(settings);
530
+ if (!loadedSignals || !signalSettingsEqual(settings.signals, loadedSignals) || !existsSync(filePath)) return settings.signals;
531
+ try {
532
+ const currentSignals = parseSignalSettings(JSON.parse(readFileSync(filePath, "utf-8")).signals);
533
+ if (!signalSettingsEqual(currentSignals, loadedSignals)) return currentSignals;
534
+ } catch {}
535
+ return settings.signals;
481
536
  }
482
537
  function saveSettings(settings, filePath = getSettingsPath()) {
483
- const dir = dirname(filePath);
484
- if (!existsSync(dir)) {
485
- mkdirSync(dir, { recursive: true });
486
- }
487
- const signals = getSignalSettingsForSave(settings, filePath);
488
- settings.signals = signals;
489
- loadedSignalSettings.set(settings, cloneSignalSettings(signals));
490
- writeFileSync(filePath, JSON.stringify(settings, null, 2), "utf-8");
491
- }
538
+ const dir = dirname(filePath);
539
+ if (!existsSync(dir)) mkdirSync(dir, { recursive: true });
540
+ const signals = getSignalSettingsForSave(settings, filePath);
541
+ settings.signals = signals;
542
+ loadedSignalSettings.set(settings, cloneSignalSettings(signals));
543
+ writeFileSync(filePath, JSON.stringify(settings, null, 2), "utf-8");
544
+ }
545
+ /** Marker file name to track which provider last used a profile. */
492
546
  const PROFILE_PROVIDER_MARKER = ".mastra-provider";
547
+ /**
548
+ * Check which provider last used a profile directory.
549
+ * Returns the provider name if the marker exists, undefined otherwise.
550
+ */
493
551
  function getProfileProvider(profilePath) {
494
- const markerPath = join(profilePath, PROFILE_PROVIDER_MARKER);
495
- if (!existsSync(markerPath)) {
496
- return void 0;
497
- }
498
- try {
499
- const content = readFileSync(markerPath, "utf-8").trim();
500
- if (content === "stagehand" || content === "agent-browser") {
501
- return content;
502
- }
503
- return void 0;
504
- } catch {
505
- return void 0;
506
- }
507
- }
552
+ const markerPath = join(profilePath, PROFILE_PROVIDER_MARKER);
553
+ if (!existsSync(markerPath)) return;
554
+ try {
555
+ const content = readFileSync(markerPath, "utf-8").trim();
556
+ if (content === "stagehand" || content === "agent-browser") return content;
557
+ return;
558
+ } catch {
559
+ return;
560
+ }
561
+ }
562
+ /**
563
+ * Write the provider marker to a profile directory.
564
+ * Creates the directory if it doesn't exist.
565
+ */
508
566
  function setProfileProvider(profilePath, provider) {
509
- const markerPath = join(profilePath, PROFILE_PROVIDER_MARKER);
510
- if (!existsSync(profilePath)) {
511
- mkdirSync(profilePath, { recursive: true });
512
- }
513
- writeFileSync(markerPath, provider, "utf-8");
514
- }
567
+ const markerPath = join(profilePath, PROFILE_PROVIDER_MARKER);
568
+ if (!existsSync(profilePath)) mkdirSync(profilePath, { recursive: true });
569
+ writeFileSync(markerPath, provider, "utf-8");
570
+ }
571
+ /**
572
+ * Check if a profile has a provider mismatch.
573
+ * Returns the existing provider if there's a mismatch, undefined otherwise.
574
+ */
515
575
  function checkProfileProviderMismatch(profilePath, targetProvider) {
516
- if (!profilePath) {
517
- return void 0;
518
- }
519
- const existingProvider = getProfileProvider(profilePath);
520
- if (existingProvider && existingProvider !== targetProvider) {
521
- return existingProvider;
522
- }
523
- return void 0;
576
+ if (!profilePath) return;
577
+ const existingProvider = getProfileProvider(profilePath);
578
+ if (existingProvider && existingProvider !== targetProvider) return existingProvider;
524
579
  }
525
580
  function browserRecordingOptions() {
526
- return { outputDir: join(getAppDataDir(), "browser-recordings") };
581
+ return { outputDir: join(getAppDataDir(), "browser-recordings") };
527
582
  }
583
+ /**
584
+ * Create a browser instance from settings.
585
+ * Shared by startup (main.ts) and live reconfiguration (/browser command).
586
+ * Returns undefined if browser is disabled.
587
+ */
528
588
  async function createBrowserFromSettings(settings) {
529
- if (!settings.enabled) {
530
- return void 0;
531
- }
532
- const { provider, headless, viewport, cdpUrl, profile, executablePath, stagehand, agentBrowser } = settings;
533
- const scope = profile ? "shared" : settings.scope;
534
- const launchConfig = { headless, viewport, profile, executablePath, scope };
535
- if (provider === "stagehand") {
536
- const { StagehandBrowser } = await import("@mastra/stagehand");
537
- const stagehandOpts = {
538
- env: stagehand?.env ?? "LOCAL",
539
- apiKey: stagehand?.apiKey ?? process.env.BROWSERBASE_API_KEY,
540
- projectId: stagehand?.projectId ?? process.env.BROWSERBASE_PROJECT_ID,
541
- preserveUserDataDir: stagehand?.preserveUserDataDir,
542
- recording: browserRecordingOptions()
543
- };
544
- const authStorage = new AuthStorage();
545
- const cred = authStorage.get("openai-codex");
546
- if (cred?.type === "oauth") {
547
- const accountId = cred.accountId;
548
- stagehandOpts.model = {
549
- modelName: "openai/gpt-5.4-mini",
550
- apiKey: "codex-oauth",
551
- baseURL: "https://chatgpt.com/backend-api/codex",
552
- headers: {
553
- originator: "mastracode",
554
- "User-Agent": "mastracode",
555
- ...accountId ? { "ChatGPT-Account-ID": accountId } : {}
556
- },
557
- fetch: buildCodexStagehandFetch(authStorage),
558
- middleware: createCodexMiddleware()
559
- };
560
- }
561
- return cdpUrl ? new StagehandBrowser({ ...launchConfig, cdpUrl, scope: "shared", ...stagehandOpts }) : new StagehandBrowser({ ...launchConfig, ...stagehandOpts });
562
- } else if (provider === "agent-browser") {
563
- const { AgentBrowser } = await import("@mastra/agent-browser");
564
- const agentBrowserOpts = {
565
- storageState: agentBrowser?.storageState,
566
- recording: browserRecordingOptions()
567
- };
568
- return cdpUrl ? new AgentBrowser({ ...launchConfig, cdpUrl, scope: "shared", ...agentBrowserOpts }) : new AgentBrowser({ ...launchConfig, ...agentBrowserOpts, scope });
569
- }
570
- throw new Error(`Unsupported browser provider: ${provider}`);
571
- }
572
- export {
573
- MASTRA_GATEWAY_DEFAULT_URL,
574
- MASTRA_GATEWAY_PROVIDER,
575
- MEMORY_GATEWAY_DEFAULT_URL,
576
- MEMORY_GATEWAY_PROVIDER,
577
- OBSERVABILITY_AUTH_PREFIX,
578
- STORAGE_DEFAULTS,
579
- THREAD_ACTIVE_MODEL_PACK_ID_KEY,
580
- checkProfileProviderMismatch,
581
- createBrowserFromSettings,
582
- defaultVoiceEngine,
583
- getCustomProviderId,
584
- getProfileProvider,
585
- getSettingsPath,
586
- loadSettings,
587
- migrateLegacyVariedPack,
588
- parseCustomProviders,
589
- parseThreadSettings,
590
- resolveModelDefaults,
591
- resolveOmModel,
592
- resolveOmRoleModel,
593
- resolveThreadActiveModelPackId,
594
- saveSettings,
595
- setProfileProvider,
596
- toCustomProviderModelId
597
- };
589
+ if (!settings.enabled) return;
590
+ const { provider, headless, viewport, cdpUrl, profile, executablePath, stagehand, agentBrowser } = settings;
591
+ const scope = profile ? "shared" : settings.scope;
592
+ const launchConfig = {
593
+ headless,
594
+ viewport,
595
+ profile,
596
+ executablePath,
597
+ scope
598
+ };
599
+ if (provider === "stagehand") {
600
+ const { StagehandBrowser } = await import("@mastra/stagehand");
601
+ const stagehandOpts = {
602
+ env: stagehand?.env ?? "LOCAL",
603
+ apiKey: stagehand?.apiKey ?? process.env.BROWSERBASE_API_KEY,
604
+ projectId: stagehand?.projectId ?? process.env.BROWSERBASE_PROJECT_ID,
605
+ preserveUserDataDir: stagehand?.preserveUserDataDir,
606
+ recording: browserRecordingOptions()
607
+ };
608
+ const authStorage = new AuthStorage();
609
+ const cred = authStorage.get("openai-codex");
610
+ if (cred?.type === "oauth") {
611
+ const accountId = cred.accountId;
612
+ stagehandOpts.model = {
613
+ modelName: "openai/gpt-5.4-mini",
614
+ apiKey: "codex-oauth",
615
+ baseURL: "https://chatgpt.com/backend-api/codex",
616
+ headers: {
617
+ originator: "mastracode",
618
+ "User-Agent": "mastracode",
619
+ ...accountId ? { "ChatGPT-Account-ID": accountId } : {}
620
+ },
621
+ fetch: buildCodexStagehandFetch(authStorage),
622
+ middleware: createCodexMiddleware()
623
+ };
624
+ }
625
+ return cdpUrl ? new StagehandBrowser({
626
+ ...launchConfig,
627
+ cdpUrl,
628
+ scope: "shared",
629
+ ...stagehandOpts
630
+ }) : new StagehandBrowser({
631
+ ...launchConfig,
632
+ ...stagehandOpts
633
+ });
634
+ } else if (provider === "agent-browser") {
635
+ const { AgentBrowser } = await import("@mastra/agent-browser");
636
+ const agentBrowserOpts = {
637
+ storageState: agentBrowser?.storageState,
638
+ recording: browserRecordingOptions()
639
+ };
640
+ return cdpUrl ? new AgentBrowser({
641
+ ...launchConfig,
642
+ cdpUrl,
643
+ scope: "shared",
644
+ ...agentBrowserOpts
645
+ }) : new AgentBrowser({
646
+ ...launchConfig,
647
+ ...agentBrowserOpts,
648
+ scope
649
+ });
650
+ }
651
+ throw new Error(`Unsupported browser provider: ${provider}`);
652
+ }
653
+ //#endregion
654
+ export { MASTRA_GATEWAY_DEFAULT_URL, MASTRA_GATEWAY_PROVIDER, MEMORY_GATEWAY_DEFAULT_URL, MEMORY_GATEWAY_PROVIDER, OBSERVABILITY_AUTH_PREFIX, STORAGE_DEFAULTS, THREAD_ACTIVE_MODEL_PACK_ID_KEY, checkProfileProviderMismatch, createBrowserFromSettings, defaultVoiceEngine, getCustomProviderId, getProfileProvider, getSettingsPath, loadSettings, migrateLegacyVariedPack, parseCustomProviders, parseThreadSettings, resolveModelDefaults, resolveOmModel, resolveOmRoleModel, resolveThreadActiveModelPackId, saveSettings, setProfileProvider, toCustomProviderModelId };
655
+
598
656
  //# sourceMappingURL=settings.js.map