mastracode 0.4.0 → 0.5.0

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 (155) hide show
  1. package/CHANGELOG.md +328 -0
  2. package/LICENSE.md +15 -0
  3. package/README.md +68 -29
  4. package/dist/agents/memory.d.ts.map +1 -1
  5. package/dist/agents/model.d.ts +17 -6
  6. package/dist/agents/model.d.ts.map +1 -1
  7. package/dist/agents/prompts/index.d.ts.map +1 -1
  8. package/dist/agents/prompts/tool-guidance.d.ts +2 -0
  9. package/dist/agents/prompts/tool-guidance.d.ts.map +1 -1
  10. package/dist/agents/subagents/audit-tests.d.ts +0 -7
  11. package/dist/agents/subagents/audit-tests.d.ts.map +1 -1
  12. package/dist/agents/subagents/execute.d.ts +0 -7
  13. package/dist/agents/subagents/execute.d.ts.map +1 -1
  14. package/dist/agents/subagents/explore.d.ts +0 -7
  15. package/dist/agents/subagents/explore.d.ts.map +1 -1
  16. package/dist/agents/subagents/index.d.ts.map +1 -1
  17. package/dist/agents/subagents/plan.d.ts +0 -7
  18. package/dist/agents/subagents/plan.d.ts.map +1 -1
  19. package/dist/agents/tools.d.ts +3 -1
  20. package/dist/agents/tools.d.ts.map +1 -1
  21. package/dist/agents/workspace.d.ts +4 -1
  22. package/dist/agents/workspace.d.ts.map +1 -1
  23. package/dist/{chunk-K4WJUBEC.cjs → chunk-AJEYT7X3.cjs} +763 -429
  24. package/dist/chunk-AJEYT7X3.cjs.map +1 -0
  25. package/dist/{chunk-U5A7TFNT.js → chunk-CC2724NI.js} +46 -10
  26. package/dist/chunk-CC2724NI.js.map +1 -0
  27. package/dist/{chunk-REVOTI2T.js → chunk-JI4M5525.js} +740 -412
  28. package/dist/chunk-JI4M5525.js.map +1 -0
  29. package/dist/{chunk-Z4QRXVST.cjs → chunk-MBPGUMYQ.cjs} +325 -251
  30. package/dist/chunk-MBPGUMYQ.cjs.map +1 -0
  31. package/dist/{chunk-MT3YCFCC.cjs → chunk-OEDRHUU5.cjs} +47 -9
  32. package/dist/chunk-OEDRHUU5.cjs.map +1 -0
  33. package/dist/{chunk-M5LKPQB4.js → chunk-WKPHD54B.js} +283 -209
  34. package/dist/chunk-WKPHD54B.js.map +1 -0
  35. package/dist/{chunk-C4X3C2DL.cjs → chunk-XVYUS2EA.cjs} +2213 -1035
  36. package/dist/chunk-XVYUS2EA.cjs.map +1 -0
  37. package/dist/{chunk-X3BGE7CL.js → chunk-YQNZ7DHQ.js} +1788 -613
  38. package/dist/chunk-YQNZ7DHQ.js.map +1 -0
  39. package/dist/cli.cjs +79 -31
  40. package/dist/cli.cjs.map +1 -1
  41. package/dist/cli.js +71 -23
  42. package/dist/cli.js.map +1 -1
  43. package/dist/clipboard/index.d.ts +5 -0
  44. package/dist/clipboard/index.d.ts.map +1 -1
  45. package/dist/error-classification.d.ts +10 -0
  46. package/dist/error-classification.d.ts.map +1 -0
  47. package/dist/index.cjs +2 -2
  48. package/dist/index.d.ts +10 -3
  49. package/dist/index.d.ts.map +1 -1
  50. package/dist/index.js +1 -1
  51. package/dist/mcp/config.d.ts +8 -0
  52. package/dist/mcp/config.d.ts.map +1 -1
  53. package/dist/mcp/index.d.ts +1 -1
  54. package/dist/mcp/index.d.ts.map +1 -1
  55. package/dist/mcp/manager.d.ts +4 -2
  56. package/dist/mcp/manager.d.ts.map +1 -1
  57. package/dist/mcp/types.d.ts +30 -3
  58. package/dist/mcp/types.d.ts.map +1 -1
  59. package/dist/onboarding/onboarding-inline.d.ts +2 -0
  60. package/dist/onboarding/onboarding-inline.d.ts.map +1 -1
  61. package/dist/onboarding/packs.d.ts +1 -0
  62. package/dist/onboarding/packs.d.ts.map +1 -1
  63. package/dist/onboarding/settings.d.ts +37 -2
  64. package/dist/onboarding/settings.d.ts.map +1 -1
  65. package/dist/permissions-S3LGXIDB.js +3 -0
  66. package/dist/{permissions-CVXKYIWR.js.map → permissions-S3LGXIDB.js.map} +1 -1
  67. package/dist/permissions-VGABAVGD.cjs +40 -0
  68. package/dist/{permissions-2HIUSRQN.cjs.map → permissions-VGABAVGD.cjs.map} +1 -1
  69. package/dist/permissions.d.ts.map +1 -1
  70. package/dist/providers/claude-max.d.ts +13 -0
  71. package/dist/providers/claude-max.d.ts.map +1 -1
  72. package/dist/providers/openai-codex.d.ts +1 -0
  73. package/dist/providers/openai-codex.d.ts.map +1 -1
  74. package/dist/tool-names.d.ts +68 -0
  75. package/dist/tool-names.d.ts.map +1 -0
  76. package/dist/tools/ast-smart-edit.d.ts +77 -5
  77. package/dist/tools/ast-smart-edit.d.ts.map +1 -1
  78. package/dist/tools/index.d.ts +2 -2
  79. package/dist/tools/index.d.ts.map +1 -1
  80. package/dist/tools/string-replace-lsp.d.ts +15 -0
  81. package/dist/tools/string-replace-lsp.d.ts.map +1 -1
  82. package/dist/tools/subagent.d.ts.map +1 -1
  83. package/dist/tools/utils.d.ts +4 -2
  84. package/dist/tools/utils.d.ts.map +1 -1
  85. package/dist/tui/command-dispatch.d.ts.map +1 -1
  86. package/dist/tui/commands/clone.d.ts +29 -0
  87. package/dist/tui/commands/clone.d.ts.map +1 -0
  88. package/dist/tui/commands/custom-providers.d.ts +8 -0
  89. package/dist/tui/commands/custom-providers.d.ts.map +1 -0
  90. package/dist/tui/commands/index.d.ts +3 -1
  91. package/dist/tui/commands/index.d.ts.map +1 -1
  92. package/dist/tui/commands/mcp.d.ts.map +1 -1
  93. package/dist/tui/commands/models-pack.d.ts +4 -0
  94. package/dist/tui/commands/models-pack.d.ts.map +1 -1
  95. package/dist/tui/commands/om.d.ts.map +1 -1
  96. package/dist/tui/commands/report-issue.d.ts +3 -0
  97. package/dist/tui/commands/report-issue.d.ts.map +1 -0
  98. package/dist/tui/commands/resource.d.ts.map +1 -1
  99. package/dist/tui/commands/settings.d.ts.map +1 -1
  100. package/dist/tui/commands/threads.d.ts +1 -0
  101. package/dist/tui/commands/threads.d.ts.map +1 -1
  102. package/dist/tui/components/ask-question-inline.d.ts +3 -0
  103. package/dist/tui/components/ask-question-inline.d.ts.map +1 -1
  104. package/dist/tui/components/custom-editor.d.ts +1 -1
  105. package/dist/tui/components/custom-editor.d.ts.map +1 -1
  106. package/dist/tui/components/help-overlay.d.ts.map +1 -1
  107. package/dist/tui/components/plan-approval-inline.d.ts.map +1 -1
  108. package/dist/tui/components/settings.d.ts +2 -0
  109. package/dist/tui/components/settings.d.ts.map +1 -1
  110. package/dist/tui/components/subagent-execution.d.ts +6 -1
  111. package/dist/tui/components/subagent-execution.d.ts.map +1 -1
  112. package/dist/tui/components/thread-selector.d.ts +6 -0
  113. package/dist/tui/components/thread-selector.d.ts.map +1 -1
  114. package/dist/tui/components/tool-execution-enhanced.d.ts +1 -0
  115. package/dist/tui/components/tool-execution-enhanced.d.ts.map +1 -1
  116. package/dist/tui/components/tool-validation-error.d.ts.map +1 -1
  117. package/dist/tui/handlers/message.d.ts.map +1 -1
  118. package/dist/tui/handlers/prompts.d.ts +6 -0
  119. package/dist/tui/handlers/prompts.d.ts.map +1 -1
  120. package/dist/tui/handlers/subagent.d.ts.map +1 -1
  121. package/dist/tui/mastra-tui.d.ts +14 -5
  122. package/dist/tui/mastra-tui.d.ts.map +1 -1
  123. package/dist/tui/render-messages.d.ts.map +1 -1
  124. package/dist/tui/setup.d.ts.map +1 -1
  125. package/dist/tui/state.d.ts +4 -5
  126. package/dist/tui/state.d.ts.map +1 -1
  127. package/dist/tui.cjs +19 -19
  128. package/dist/tui.js +2 -2
  129. package/dist/utils/debug-log.d.ts +12 -0
  130. package/dist/utils/debug-log.d.ts.map +1 -0
  131. package/dist/utils/plans.d.ts +7 -0
  132. package/dist/utils/plans.d.ts.map +1 -0
  133. package/dist/utils/update-check.d.ts +40 -0
  134. package/dist/utils/update-check.d.ts.map +1 -0
  135. package/package.json +8 -8
  136. package/dist/chunk-C4X3C2DL.cjs.map +0 -1
  137. package/dist/chunk-K4WJUBEC.cjs.map +0 -1
  138. package/dist/chunk-M5LKPQB4.js.map +0 -1
  139. package/dist/chunk-MT3YCFCC.cjs.map +0 -1
  140. package/dist/chunk-REVOTI2T.js.map +0 -1
  141. package/dist/chunk-U5A7TFNT.js.map +0 -1
  142. package/dist/chunk-X3BGE7CL.js.map +0 -1
  143. package/dist/chunk-Z4QRXVST.cjs.map +0 -1
  144. package/dist/docs/SKILL.md +0 -30
  145. package/dist/docs/assets/SOURCE_MAP.json +0 -11
  146. package/dist/docs/references/docs-mastra-code-configuration.md +0 -299
  147. package/dist/docs/references/docs-mastra-code-customization.md +0 -228
  148. package/dist/docs/references/docs-mastra-code-modes.md +0 -104
  149. package/dist/docs/references/docs-mastra-code-overview.md +0 -135
  150. package/dist/docs/references/docs-mastra-code-tools.md +0 -229
  151. package/dist/docs/references/reference-mastra-code-createMastraCode.md +0 -108
  152. package/dist/permissions-2HIUSRQN.cjs +0 -40
  153. package/dist/permissions-CVXKYIWR.js +0 -3
  154. package/dist/tui/commands/models.d.ts +0 -3
  155. package/dist/tui/commands/models.d.ts.map +0 -1
@@ -1,10 +1,13 @@
1
1
  import { AuthStorage, getAppDataDir } from './chunk-SM3QCOA7.js';
2
+ import { MC_TOOLS, TOOL_NAME_OVERRIDES } from './chunk-CC2724NI.js';
3
+ import * as fs9 from 'fs';
4
+ import fs9__default, { readFileSync, writeFileSync, promises, existsSync, mkdirSync } from 'fs';
5
+ import * as path2 from 'path';
6
+ import path2__default, { resolve, join, dirname } from 'path';
7
+ import os, { homedir } from 'os';
8
+ import { pathToFileURL, fileURLToPath } from 'url';
9
+ import { Workspace, LocalSandbox, LocalFilesystem } from '@mastra/core/workspace';
2
10
  import { exec, spawn } from 'child_process';
3
- import * as fs8 from 'fs';
4
- import { readFileSync, writeFileSync, promises, existsSync, mkdirSync } from 'fs';
5
- import { homedir } from 'os';
6
- import * as path from 'path';
7
- import path__default, { resolve, join, dirname } from 'path';
8
11
  import { promisify } from 'util';
9
12
  import { createTool } from '@mastra/core/tools';
10
13
  import { z } from 'zod';
@@ -16,7 +19,6 @@ import treeKill from 'tree-kill';
16
19
  import { StreamMessageReader, StreamMessageWriter, createMessageConnection } from 'vscode-jsonrpc/node.js';
17
20
  import { Position, TextDocumentIdentifier } from 'vscode-languageserver-protocol';
18
21
  import { createRequire } from 'module';
19
- import { pathToFileURL } from 'url';
20
22
  import { distance } from 'fastest-levenshtein';
21
23
  import { createAnthropic } from '@ai-sdk/anthropic';
22
24
  import { wrapLanguageModel } from 'ai';
@@ -26,6 +28,410 @@ import { tavily } from '@tavily/core';
26
28
  import { parse, Lang } from '@ast-grep/napi';
27
29
  import chalk from 'chalk';
28
30
 
31
+ var STORAGE_DEFAULTS = {
32
+ backend: "libsql",
33
+ libsql: {},
34
+ pg: {}
35
+ };
36
+ var DEFAULTS = {
37
+ onboarding: {
38
+ completedAt: null,
39
+ skippedAt: null,
40
+ version: 0,
41
+ modePackId: null,
42
+ omPackId: null,
43
+ claudeMaxOAuthWarningAcknowledgedAt: null
44
+ },
45
+ models: {
46
+ activeModelPackId: null,
47
+ modeDefaults: {},
48
+ activeOmPackId: null,
49
+ omModelOverride: null,
50
+ subagentModels: {}
51
+ },
52
+ preferences: {
53
+ yolo: null,
54
+ theme: "auto",
55
+ quietMode: false
56
+ },
57
+ storage: { ...STORAGE_DEFAULTS },
58
+ customModelPacks: [],
59
+ customProviders: [],
60
+ modelUseCounts: {},
61
+ updateDismissedVersion: null,
62
+ lsp: {}
63
+ };
64
+ function getSettingsPath() {
65
+ return join(getAppDataDir(), "settings.json");
66
+ }
67
+ function getCustomProviderId(name) {
68
+ const slug = name.trim().toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
69
+ return slug || "provider";
70
+ }
71
+ function toCustomProviderModelId(providerName, modelName) {
72
+ const providerId = getCustomProviderId(providerName);
73
+ const trimmedModelName = modelName.trim();
74
+ const providerPrefix = `${providerId}/`;
75
+ if (trimmedModelName.startsWith(providerPrefix)) {
76
+ return trimmedModelName;
77
+ }
78
+ return `${providerId}/${trimmedModelName}`;
79
+ }
80
+ function parseCustomProviders(rawProviders) {
81
+ if (!Array.isArray(rawProviders)) return [];
82
+ const parsedProviders = [];
83
+ for (const rawProvider of rawProviders) {
84
+ if (!rawProvider || typeof rawProvider !== "object") continue;
85
+ const candidate = rawProvider;
86
+ const name = typeof candidate.name === "string" ? candidate.name.trim() : "";
87
+ const url = typeof candidate.url === "string" ? candidate.url.trim() : "";
88
+ if (!name || !url) continue;
89
+ const providerId = getCustomProviderId(name);
90
+ const models = Array.isArray(candidate.models) ? [
91
+ ...new Set(
92
+ candidate.models.filter((model) => typeof model === "string").map((model) => model.trim()).map((model) => {
93
+ const providerPrefix = `${providerId}/`;
94
+ if (model.startsWith(providerPrefix)) {
95
+ return model.slice(providerPrefix.length);
96
+ }
97
+ return model;
98
+ })
99
+ )
100
+ ].filter((model) => model.length > 0) : [];
101
+ const apiKey = typeof candidate.apiKey === "string" && candidate.apiKey.trim().length > 0 ? candidate.apiKey.trim() : void 0;
102
+ parsedProviders.push({
103
+ name,
104
+ url,
105
+ ...apiKey ? { apiKey } : {},
106
+ models
107
+ });
108
+ }
109
+ return parsedProviders;
110
+ }
111
+ function migrateFromAuth(settingsPath) {
112
+ const authPath = join(getAppDataDir(), "auth.json");
113
+ if (!existsSync(authPath)) return false;
114
+ let authData;
115
+ try {
116
+ authData = JSON.parse(readFileSync(authPath, "utf-8"));
117
+ } catch {
118
+ return false;
119
+ }
120
+ const modelKeys = Object.keys(authData).filter((k) => k.startsWith("_"));
121
+ if (modelKeys.length === 0) return false;
122
+ let settings;
123
+ if (existsSync(settingsPath)) {
124
+ try {
125
+ const raw = JSON.parse(readFileSync(settingsPath, "utf-8"));
126
+ settings = {
127
+ onboarding: { ...DEFAULTS.onboarding, ...raw.onboarding },
128
+ models: { ...DEFAULTS.models, ...raw.models },
129
+ preferences: { ...DEFAULTS.preferences, ...raw.preferences },
130
+ storage: {
131
+ ...STORAGE_DEFAULTS,
132
+ ...raw.storage,
133
+ libsql: { ...STORAGE_DEFAULTS.libsql, ...raw.storage?.libsql },
134
+ pg: { ...STORAGE_DEFAULTS.pg, ...raw.storage?.pg }
135
+ },
136
+ customModelPacks: Array.isArray(raw.customModelPacks) ? raw.customModelPacks : [],
137
+ customProviders: parseCustomProviders(raw.customProviders),
138
+ modelUseCounts: raw.modelUseCounts && typeof raw.modelUseCounts === "object" ? raw.modelUseCounts : {},
139
+ updateDismissedVersion: typeof raw.updateDismissedVersion === "string" ? raw.updateDismissedVersion : null,
140
+ lsp: raw.lsp && typeof raw.lsp === "object" ? raw.lsp : void 0
141
+ };
142
+ } catch {
143
+ settings = structuredClone(DEFAULTS);
144
+ }
145
+ } else {
146
+ settings = structuredClone(DEFAULTS);
147
+ }
148
+ if (authData._modelRanks && typeof authData._modelRanks === "object") {
149
+ settings.modelUseCounts = { ...authData._modelRanks, ...settings.modelUseCounts };
150
+ }
151
+ for (const key of modelKeys) {
152
+ const modeMatch = key.match(/^_modeModelId_(.+)$/);
153
+ if (modeMatch?.[1] && typeof authData[key] === "string" && !settings.models.modeDefaults[modeMatch[1]]) {
154
+ settings.models.modeDefaults[modeMatch[1]] = authData[key];
155
+ }
156
+ }
157
+ for (const key of modelKeys) {
158
+ if (key === "_subagentModelId" && typeof authData[key] === "string" && !settings.models.subagentModels["default"]) {
159
+ settings.models.subagentModels["default"] = authData[key];
160
+ }
161
+ const saMatch = key.match(/^_subagentModelId_(.+)$/);
162
+ if (saMatch?.[1] && typeof authData[key] === "string" && !settings.models.subagentModels[saMatch[1]]) {
163
+ settings.models.subagentModels[saMatch[1]] = authData[key];
164
+ }
165
+ }
166
+ saveSettings(settings, settingsPath);
167
+ for (const key of modelKeys) {
168
+ delete authData[key];
169
+ }
170
+ try {
171
+ writeFileSync(authPath, JSON.stringify(authData, null, 2), "utf-8");
172
+ } catch {
173
+ }
174
+ return true;
175
+ }
176
+ var LEGACY_VARIED_MODELS = {
177
+ plan: "openai/gpt-5.3-codex",
178
+ build: "anthropic/claude-sonnet-4-5",
179
+ fast: "anthropic/claude-haiku-4-5"
180
+ };
181
+ function migrateLegacyVariedPack(settings) {
182
+ const legacyPackId = "varied";
183
+ const customPackId = "custom:varied";
184
+ const hasLegacyReference = settings.models.activeModelPackId === legacyPackId || settings.onboarding.modePackId === legacyPackId;
185
+ if (!hasLegacyReference) return false;
186
+ const existingIdx = settings.customModelPacks.findIndex((p) => p.name === "varied");
187
+ if (existingIdx >= 0) {
188
+ const existing = settings.customModelPacks[existingIdx];
189
+ const modelsMatch = Object.entries(LEGACY_VARIED_MODELS).every(([k, v]) => existing.models[k] === v);
190
+ if (!modelsMatch) {
191
+ existing.models = { ...LEGACY_VARIED_MODELS };
192
+ }
193
+ } else {
194
+ settings.customModelPacks.push({
195
+ name: "varied",
196
+ models: { ...LEGACY_VARIED_MODELS },
197
+ createdAt: (/* @__PURE__ */ new Date()).toISOString()
198
+ });
199
+ }
200
+ if (settings.models.activeModelPackId === legacyPackId) {
201
+ settings.models.activeModelPackId = customPackId;
202
+ if (Object.keys(settings.models.modeDefaults).length === 0) {
203
+ settings.models.modeDefaults = { ...LEGACY_VARIED_MODELS };
204
+ }
205
+ }
206
+ if (settings.onboarding.modePackId === legacyPackId) {
207
+ settings.onboarding.modePackId = customPackId;
208
+ }
209
+ return true;
210
+ }
211
+ function loadSettings(filePath = getSettingsPath()) {
212
+ migrateFromAuth(filePath);
213
+ if (!existsSync(filePath)) return structuredClone(DEFAULTS);
214
+ try {
215
+ const raw = JSON.parse(readFileSync(filePath, "utf-8"));
216
+ const settings = {
217
+ ...raw,
218
+ onboarding: { ...DEFAULTS.onboarding, ...raw.onboarding },
219
+ models: { ...DEFAULTS.models, ...raw.models },
220
+ preferences: { ...DEFAULTS.preferences, ...raw.preferences },
221
+ storage: {
222
+ ...STORAGE_DEFAULTS,
223
+ ...raw.storage,
224
+ libsql: { ...STORAGE_DEFAULTS.libsql, ...raw.storage?.libsql },
225
+ pg: { ...STORAGE_DEFAULTS.pg, ...raw.storage?.pg }
226
+ },
227
+ customModelPacks: Array.isArray(raw.customModelPacks) ? raw.customModelPacks : [],
228
+ customProviders: parseCustomProviders(raw.customProviders),
229
+ modelUseCounts: raw.modelUseCounts && typeof raw.modelUseCounts === "object" ? raw.modelUseCounts : {},
230
+ updateDismissedVersion: typeof raw.updateDismissedVersion === "string" ? raw.updateDismissedVersion : null,
231
+ lsp: raw.lsp && typeof raw.lsp === "object" ? raw.lsp : void 0
232
+ };
233
+ let settingsChanged = false;
234
+ if (raw.models?.omModelId && !settings.models.omModelOverride) {
235
+ settings.models.omModelOverride = raw.models.omModelId;
236
+ settingsChanged = true;
237
+ }
238
+ if (migrateLegacyVariedPack(settings)) {
239
+ settingsChanged = true;
240
+ }
241
+ if (settingsChanged) {
242
+ saveSettings(settings, filePath);
243
+ }
244
+ return settings;
245
+ } catch {
246
+ return structuredClone(DEFAULTS);
247
+ }
248
+ }
249
+ var THREAD_ACTIVE_MODEL_PACK_ID_KEY = "activeModelPackId";
250
+ function parseThreadSettings(metadata) {
251
+ const modeModelIds = {};
252
+ for (const [key, value] of Object.entries(metadata ?? {})) {
253
+ const modeMatch = key.match(/^modeModelId_(.+)$/);
254
+ if (modeMatch?.[1] && typeof value === "string" && value.length > 0) {
255
+ modeModelIds[modeMatch[1]] = value;
256
+ }
257
+ }
258
+ const rawPackId = metadata?.[THREAD_ACTIVE_MODEL_PACK_ID_KEY];
259
+ const activeModelPackId = typeof rawPackId === "string" && rawPackId.length > 0 ? rawPackId : null;
260
+ return {
261
+ activeModelPackId,
262
+ modeModelIds
263
+ };
264
+ }
265
+ function resolveThreadActiveModelPackId(settings, builtinPacks, metadata) {
266
+ const threadSettings = parseThreadSettings(metadata);
267
+ const isKnownPack = (packId) => {
268
+ if (packId.startsWith("custom:")) {
269
+ const name = packId.slice("custom:".length);
270
+ return settings.customModelPacks.some((p) => p.name === name);
271
+ }
272
+ return builtinPacks.some((p) => p.id === packId);
273
+ };
274
+ if (threadSettings.activeModelPackId && isKnownPack(threadSettings.activeModelPackId)) {
275
+ return threadSettings.activeModelPackId;
276
+ }
277
+ const allPacks = [
278
+ ...builtinPacks,
279
+ ...settings.customModelPacks.map((p) => ({ id: `custom:${p.name}`, models: p.models }))
280
+ ];
281
+ for (const pack of allPacks) {
282
+ const packEntries = Object.entries(pack.models);
283
+ const threadEntries = Object.keys(threadSettings.modeModelIds);
284
+ const matches = packEntries.length === threadEntries.length && packEntries.every(([modeId, modelId]) => threadSettings.modeModelIds[modeId] === modelId);
285
+ if (matches) return pack.id;
286
+ }
287
+ if (settings.models.activeModelPackId && isKnownPack(settings.models.activeModelPackId)) {
288
+ return settings.models.activeModelPackId;
289
+ }
290
+ return null;
291
+ }
292
+ function resolveModelDefaults(settings, builtinPacks) {
293
+ const { activeModelPackId, modeDefaults } = settings.models;
294
+ if (!activeModelPackId) return modeDefaults;
295
+ if (activeModelPackId.startsWith("custom:")) {
296
+ const name = activeModelPackId.slice("custom:".length);
297
+ const pack = settings.customModelPacks.find((p) => p.name === name);
298
+ if (pack) return pack.models;
299
+ return modeDefaults;
300
+ }
301
+ const builtin = builtinPacks.find((p) => p.id === activeModelPackId);
302
+ if (builtin) return builtin.models;
303
+ return modeDefaults;
304
+ }
305
+ function resolveOmModel(settings, builtinOmPacks) {
306
+ const { activeOmPackId, omModelOverride } = settings.models;
307
+ if (!activeOmPackId) return omModelOverride;
308
+ if (activeOmPackId === "custom") return omModelOverride;
309
+ const pack = builtinOmPacks.find((p) => p.id === activeOmPackId);
310
+ if (pack) return pack.modelId;
311
+ return omModelOverride;
312
+ }
313
+ function saveSettings(settings, filePath = getSettingsPath()) {
314
+ const dir = dirname(filePath);
315
+ if (!existsSync(dir)) {
316
+ mkdirSync(dir, { recursive: true });
317
+ }
318
+ writeFileSync(filePath, JSON.stringify(settings, null, 2), "utf-8");
319
+ }
320
+ var mastraCodeLocalSkillsPath = path2__default.join(process.cwd(), ".mastracode", "skills");
321
+ var claudeLocalSkillsPath = path2__default.join(process.cwd(), ".claude", "skills");
322
+ var mastraCodeGlobalSkillsPath = path2__default.join(os.homedir(), ".mastracode", "skills");
323
+ var claudeGlobalSkillsPath = path2__default.join(os.homedir(), ".claude", "skills");
324
+ function collectSkillPaths(skillsDirs) {
325
+ const paths = [];
326
+ const seen = /* @__PURE__ */ new Set();
327
+ for (const skillsDir of skillsDirs) {
328
+ if (!fs9__default.existsSync(skillsDir)) continue;
329
+ const resolved = fs9__default.realpathSync(skillsDir);
330
+ if (!seen.has(resolved)) {
331
+ seen.add(resolved);
332
+ paths.push(skillsDir);
333
+ }
334
+ try {
335
+ const entries = fs9__default.readdirSync(skillsDir, { withFileTypes: true });
336
+ for (const entry of entries) {
337
+ if (entry.isSymbolicLink()) {
338
+ const linkPath = path2__default.join(skillsDir, entry.name);
339
+ const realPath = fs9__default.realpathSync(linkPath);
340
+ const stat = fs9__default.statSync(realPath);
341
+ if (stat.isDirectory()) {
342
+ const realParent = path2__default.dirname(realPath);
343
+ if (!seen.has(realParent)) {
344
+ seen.add(realParent);
345
+ paths.push(realParent);
346
+ }
347
+ }
348
+ }
349
+ }
350
+ } catch {
351
+ }
352
+ }
353
+ return paths;
354
+ }
355
+ var skillPaths = collectSkillPaths([
356
+ mastraCodeLocalSkillsPath,
357
+ claudeLocalSkillsPath,
358
+ mastraCodeGlobalSkillsPath,
359
+ claudeGlobalSkillsPath
360
+ ]);
361
+ var WORKSPACE_ID_PREFIX = "mastra-code-workspace";
362
+ function detectPackageRunner(projectPath) {
363
+ if (existsSync(join(projectPath, "pnpm-lock.yaml"))) return "pnpm dlx";
364
+ if (existsSync(join(projectPath, "bun.lockb")) || existsSync(join(projectPath, "bun.lock"))) return "bunx";
365
+ if (existsSync(join(projectPath, "yarn.lock"))) return "yarn dlx";
366
+ if (existsSync(join(projectPath, "package-lock.json"))) return "npx --yes";
367
+ return "npx --yes";
368
+ }
369
+ function getDynamicWorkspace({ requestContext, mastra: mastra2 }) {
370
+ const ctx = requestContext.get("harness");
371
+ const state = ctx?.getState?.();
372
+ const modeId = ctx?.modeId ?? "build";
373
+ const rawProjectPath = state?.projectPath;
374
+ if (!rawProjectPath) {
375
+ throw new Error("Project path is required");
376
+ }
377
+ const projectPath = path2__default.resolve(rawProjectPath);
378
+ const workspaceId = `${WORKSPACE_ID_PREFIX}-${projectPath}`;
379
+ const sandboxPaths = state?.sandboxAllowedPaths ?? [];
380
+ const allowedPaths = [...skillPaths, ...sandboxPaths.map((p) => path2__default.resolve(p))];
381
+ const isPlanMode = modeId === "plan";
382
+ const planModeTools = {
383
+ mastra_workspace_write_file: { ...TOOL_NAME_OVERRIDES.mastra_workspace_write_file, enabled: false },
384
+ mastra_workspace_edit_file: { ...TOOL_NAME_OVERRIDES.mastra_workspace_edit_file, enabled: false },
385
+ mastra_workspace_ast_edit: { ...TOOL_NAME_OVERRIDES.mastra_workspace_ast_edit, enabled: false }
386
+ };
387
+ let existing;
388
+ try {
389
+ existing = mastra2?.getWorkspaceById(workspaceId);
390
+ } catch {
391
+ }
392
+ if (existing) {
393
+ existing.filesystem.setAllowedPaths(allowedPaths);
394
+ existing.setToolsConfig(isPlanMode ? { ...TOOL_NAME_OVERRIDES, ...planModeTools } : TOOL_NAME_OVERRIDES);
395
+ return existing;
396
+ }
397
+ const userLsp = loadSettings().lsp ?? {};
398
+ const mcModulePath = join(dirname(fileURLToPath(import.meta.url)), "..");
399
+ const lspConfig = {
400
+ ...userLsp,
401
+ packageRunner: userLsp.packageRunner || detectPackageRunner(projectPath),
402
+ // Detected runner is the fallback — user's packageRunner always wins
403
+ searchPaths: [mcModulePath, ...userLsp.searchPaths ?? []]
404
+ };
405
+ return new Workspace({
406
+ id: workspaceId,
407
+ name: "Mastra Code Workspace",
408
+ filesystem: new LocalFilesystem({
409
+ basePath: projectPath,
410
+ allowedPaths
411
+ }),
412
+ sandbox: new LocalSandbox({
413
+ workingDirectory: projectPath,
414
+ env: {
415
+ ...process.env,
416
+ FORCE_COLOR: "1",
417
+ CLICOLOR_FORCE: "1",
418
+ TERM: process.env.TERM || "xterm-256color",
419
+ CI: "true",
420
+ NONINTERACTIVE: "1",
421
+ DEBIAN_FRONTEND: "noninteractive"
422
+ }
423
+ }),
424
+ tools: isPlanMode ? { ...TOOL_NAME_OVERRIDES, ...planModeTools } : TOOL_NAME_OVERRIDES,
425
+ ...skillPaths.length > 0 ? { skills: skillPaths } : {},
426
+ lsp: lspConfig
427
+ });
428
+ }
429
+ if (skillPaths.length > 0) {
430
+ console.info(`Skills loaded from:`);
431
+ for (const p of skillPaths) {
432
+ console.info(` - ${p}`);
433
+ }
434
+ }
29
435
  var enc = new Tiktoken(o200k_base);
30
436
  function sanitizeInput(text) {
31
437
  if (!text) return "";
@@ -49,19 +455,19 @@ var ToolError = class extends Error {
49
455
  // src/tools/utils.ts
50
456
  var fileWriteQueues = /* @__PURE__ */ new Map();
51
457
  async function withWriteLock(filePath, fn) {
52
- const normalizedPath = path.resolve(filePath);
458
+ const normalizedPath = path2.resolve(filePath);
53
459
  const currentQueue = fileWriteQueues.get(normalizedPath) ?? Promise.resolve();
54
- let resolve10;
460
+ let resolve11;
55
461
  let reject;
56
462
  const ourPromise = new Promise((res, rej) => {
57
- resolve10 = res;
463
+ resolve11 = res;
58
464
  reject = rej;
59
465
  });
60
466
  const queuePromise = currentQueue.catch(() => {
61
467
  }).then(async () => {
62
468
  try {
63
469
  const result = await fn();
64
- resolve10(result);
470
+ resolve11(result);
65
471
  } catch (error) {
66
472
  reject(error);
67
473
  }
@@ -85,7 +491,7 @@ async function readFile(filePath) {
85
491
  }
86
492
  async function writeFile(filePath, content) {
87
493
  try {
88
- await promises.mkdir(path.dirname(filePath), { recursive: true });
494
+ await promises.mkdir(path2.dirname(filePath), { recursive: true });
89
495
  await promises.writeFile(filePath, content, "utf8");
90
496
  } catch (e) {
91
497
  const error = e instanceof Error ? e : new Error("Unknown error");
@@ -96,7 +502,7 @@ function makeOutput(fileContent, fileDescriptor, initLine = 1, expandTabs = true
96
502
  if (expandTabs) {
97
503
  fileContent = fileContent.replace(/\t/g, " ");
98
504
  }
99
- const displayPath = path.isAbsolute(fileDescriptor) ? path.relative(process.cwd(), fileDescriptor) : fileDescriptor;
505
+ const displayPath = path2.isAbsolute(fileDescriptor) ? path2.relative(process.cwd(), fileDescriptor) : fileDescriptor;
100
506
  const lines = fileContent.split("\n");
101
507
  const numberedLines = lines.map((line, i) => `${(i + initLine).toString().padStart(6)} ${line}`).join("\n");
102
508
  return `Here's the result of running \`cat -n\` on ${displayPath}:
@@ -104,8 +510,8 @@ ${truncateStringForTokenEstimate(numberedLines, 500, false)}
104
510
  `;
105
511
  }
106
512
  async function validatePath(command, filePath) {
107
- const absolutePath = path.isAbsolute(filePath) ? filePath : path.join(process.cwd(), filePath);
108
- if (!path.isAbsolute(filePath)) {
513
+ const absolutePath = path2.isAbsolute(filePath) ? filePath : path2.join(process.cwd(), filePath);
514
+ if (!path2.isAbsolute(filePath)) {
109
515
  filePath = absolutePath;
110
516
  }
111
517
  try {
@@ -129,23 +535,26 @@ async function validatePath(command, filePath) {
129
535
  }
130
536
  }
131
537
  function isPathAllowed(targetPath, projectRoot, allowedPaths = []) {
132
- const resolved = path.resolve(targetPath);
133
- const roots = [projectRoot, ...allowedPaths].map((p) => path.resolve(p));
134
- return roots.some((root) => resolved === root || resolved.startsWith(root + path.sep));
538
+ const resolved = path2.resolve(targetPath);
539
+ const roots = [projectRoot, ...allowedPaths].map((p) => path2.resolve(p));
540
+ return roots.some((root) => resolved === root || resolved.startsWith(root + path2.sep));
135
541
  }
136
542
  function assertPathAllowed(targetPath, projectRoot, allowedPaths = []) {
137
543
  if (!isPathAllowed(targetPath, projectRoot, allowedPaths)) {
138
- const resolvedTarget = path.resolve(targetPath);
139
- const resolvedRoot = path.resolve(projectRoot);
544
+ const resolvedTarget = path2.resolve(targetPath);
545
+ const resolvedRoot = path2.resolve(projectRoot);
140
546
  throw new ToolError(
141
547
  `Access denied: "${resolvedTarget}" is outside the project root "${resolvedRoot}"` + (allowedPaths.length ? ` and allowed paths [${allowedPaths.join(", ")}]` : "") + `. Use /sandbox to add additional allowed paths.`
142
548
  );
143
549
  }
144
550
  }
145
551
  function getAllowedPathsFromContext(toolContext) {
146
- if (!toolContext?.requestContext) return [];
552
+ if (!toolContext?.requestContext) {
553
+ return [...skillPaths];
554
+ }
147
555
  const harnessCtx = toolContext.requestContext.get("harness");
148
- return harnessCtx?.getState?.()?.sandboxAllowedPaths ?? harnessCtx?.state?.sandboxAllowedPaths ?? [];
556
+ const sandboxPaths = harnessCtx?.getState?.()?.sandboxAllowedPaths ?? harnessCtx?.state?.sandboxAllowedPaths ?? [];
557
+ return [...skillPaths, ...sandboxPaths];
149
558
  }
150
559
 
151
560
  // src/tools/file-view.ts
@@ -194,8 +603,8 @@ async function isDirectory(filePath) {
194
603
  }
195
604
  }
196
605
  async function validatePath2(command, filePath) {
197
- const absolutePath = path.isAbsolute(filePath) ? filePath : path.join(process.cwd(), filePath);
198
- if (!path.isAbsolute(filePath)) {
606
+ const absolutePath = path2.isAbsolute(filePath) ? filePath : path2.join(process.cwd(), filePath);
607
+ if (!path2.isAbsolute(filePath)) {
199
608
  filePath = absolutePath;
200
609
  }
201
610
  try {
@@ -229,7 +638,7 @@ Usage notes:
229
638
  try {
230
639
  const { path: filePath, view_range } = context;
231
640
  const root = projectRoot || process.cwd();
232
- const absolutePath = path.resolve(root, filePath);
641
+ const absolutePath = path2.resolve(root, filePath);
233
642
  const allowedPaths = getAllowedPathsFromContext(toolContext);
234
643
  assertPathAllowed(absolutePath, root, allowedPaths);
235
644
  await validatePath2("view", absolutePath);
@@ -396,7 +805,7 @@ Usage notes:
396
805
  const root = projectRoot || process.cwd();
397
806
  if (context.cwd) {
398
807
  const allowedPaths = getAllowedPathsFromContext(toolContext);
399
- const resolvedCwd = path.resolve(context.cwd);
808
+ const resolvedCwd = path2.resolve(context.cwd);
400
809
  if (!isPathAllowed(resolvedCwd, root, allowedPaths)) {
401
810
  return {
402
811
  content: [
@@ -729,9 +1138,9 @@ ${truncateStringForTokenEstimate(cleanOutput, 1e3)}` : "[User aborted command]"
729
1138
  const pid = subprocess?.pid;
730
1139
  if (pid) {
731
1140
  try {
732
- await new Promise((resolve10) => {
1141
+ await new Promise((resolve11) => {
733
1142
  treeKill(pid, "SIGKILL", (err) => {
734
- resolve10();
1143
+ resolve11();
735
1144
  });
736
1145
  });
737
1146
  } catch {
@@ -999,7 +1408,7 @@ var LSPClient = class {
999
1408
  return currentDiagnostics;
1000
1409
  }
1001
1410
  }
1002
- await new Promise((resolve10) => setTimeout(resolve10, 100));
1411
+ await new Promise((resolve11) => setTimeout(resolve11, 100));
1003
1412
  }
1004
1413
  return waitForChange ? initialDiagnostics || [] : [];
1005
1414
  }
@@ -1107,7 +1516,7 @@ var BUILTIN_SERVERS = {
1107
1516
  languageIds: ["typescript", "typescriptreact", "javascript", "javascriptreact"],
1108
1517
  root: (cwd) => findNearestRoot(cwd, ["tsconfig.json", "package.json"]),
1109
1518
  spawn: async (root) => {
1110
- const requireFromRoot = createRequire(pathToFileURL(path__default.join(root, "package.json")));
1519
+ const requireFromRoot = createRequire(pathToFileURL(path2__default.join(root, "package.json")));
1111
1520
  let tsserver;
1112
1521
  try {
1113
1522
  tsserver = requireFromRoot.resolve("typescript/lib/tsserver.js");
@@ -1305,18 +1714,18 @@ var WORKSPACE_MARKERS = [
1305
1714
  "composer.json"
1306
1715
  ];
1307
1716
  function findWorkspaceRoot(filePath) {
1308
- let currentDir = path.dirname(path.resolve(filePath));
1309
- const root = path.parse(currentDir).root;
1717
+ let currentDir = path2.dirname(path2.resolve(filePath));
1718
+ const root = path2.parse(currentDir).root;
1310
1719
  let closestProjectRoot = null;
1311
1720
  let searchDir = currentDir;
1312
1721
  while (searchDir !== root) {
1313
- const hasTsConfig = fs8.existsSync(path.join(searchDir, "tsconfig.json"));
1314
- const hasPackageJson = fs8.existsSync(path.join(searchDir, "package.json"));
1722
+ const hasTsConfig = fs9.existsSync(path2.join(searchDir, "tsconfig.json"));
1723
+ const hasPackageJson = fs9.existsSync(path2.join(searchDir, "package.json"));
1315
1724
  if (hasTsConfig || hasPackageJson) {
1316
1725
  closestProjectRoot = searchDir;
1317
1726
  break;
1318
1727
  }
1319
- const parentDir = path.dirname(searchDir);
1728
+ const parentDir = path2.dirname(searchDir);
1320
1729
  if (parentDir === searchDir) {
1321
1730
  break;
1322
1731
  }
@@ -1325,21 +1734,21 @@ function findWorkspaceRoot(filePath) {
1325
1734
  if (closestProjectRoot) {
1326
1735
  return closestProjectRoot;
1327
1736
  }
1328
- currentDir = path.dirname(path.resolve(filePath));
1737
+ currentDir = path2.dirname(path2.resolve(filePath));
1329
1738
  while (currentDir !== root) {
1330
1739
  for (const marker of WORKSPACE_MARKERS) {
1331
- const markerPath = path.join(currentDir, marker);
1332
- if (fs8.existsSync(markerPath)) {
1740
+ const markerPath = path2.join(currentDir, marker);
1741
+ if (fs9.existsSync(markerPath)) {
1333
1742
  return currentDir;
1334
1743
  }
1335
1744
  }
1336
- const parentDir = path.dirname(currentDir);
1745
+ const parentDir = path2.dirname(currentDir);
1337
1746
  if (parentDir === currentDir) {
1338
1747
  break;
1339
1748
  }
1340
1749
  currentDir = parentDir;
1341
1750
  }
1342
- return path.dirname(path.resolve(filePath));
1751
+ return path2.dirname(path2.resolve(filePath));
1343
1752
  }
1344
1753
  function removeWhitespace(str) {
1345
1754
  return str.replace(/\t/g, "").replace(/ +/g, "").replace(/^ +| +$/gm, "").replace(/\r?\n/g, "\n").replace(/\s/g, "");
@@ -1679,9 +2088,10 @@ ${divergedMessage ? divergedMessage : ``}Try adjusting your input or the file co
1679
2088
  var sharedFileEditor = new FileEditor();
1680
2089
 
1681
2090
  // src/tools/string-replace-lsp.ts
1682
- var stringReplaceLspTool = createTool({
1683
- id: "string_replace_lsp",
1684
- description: `Edit a file by replacing exact text matches. Returns Language Server Protocol (LSP) diagnostics to show any errors/warnings introduced by your edit.
2091
+ function createStringReplaceLspTool(projectRoot) {
2092
+ return createTool({
2093
+ id: "string_replace_lsp",
2094
+ description: `Edit a file by replacing exact text matches. Returns Language Server Protocol (LSP) diagnostics to show any errors/warnings introduced by your edit.
1685
2095
 
1686
2096
  Usage notes:
1687
2097
  - You MUST use the view tool to read a file before editing it. Never edit blind.
@@ -1691,99 +2101,104 @@ Usage notes:
1691
2101
  - Use start_line to narrow the search to a specific region of the file.
1692
2102
  - After editing, real LSP diagnostics are returned (TypeScript errors, linting warnings, etc).
1693
2103
  - For creating NEW files, use the write_file tool instead.`,
1694
- // requireApproval: true,
1695
- inputSchema: z.object({
1696
- path: z.string(),
1697
- old_str: z.string(),
1698
- new_str: z.string().optional(),
1699
- start_line: z.number().optional()
1700
- }),
1701
- async execute(context, toolContext) {
1702
- const { path: filePath, old_str, new_str, start_line } = context;
1703
- try {
1704
- const absoluteFilePath = path.isAbsolute(filePath) ? filePath : path.join(process.cwd(), filePath);
1705
- const root = process.cwd();
1706
- const allowedPaths = getAllowedPathsFromContext(toolContext);
1707
- assertPathAllowed(absoluteFilePath, root, allowedPaths);
1708
- const result = await sharedFileEditor.strReplace({
1709
- path: filePath,
1710
- old_str,
1711
- new_str: new_str || "",
1712
- start_line
1713
- });
1714
- let diagnosticOutput = "";
2104
+ // requireApproval: true,
2105
+ inputSchema: z.object({
2106
+ path: z.string(),
2107
+ old_str: z.string(),
2108
+ new_str: z.string().optional(),
2109
+ start_line: z.number().optional()
2110
+ }),
2111
+ async execute(context, toolContext) {
2112
+ const { path: filePath, old_str, new_str, start_line } = context;
1715
2113
  try {
1716
- const workspaceRoot = findWorkspaceRoot(absoluteFilePath);
1717
- const client = await lspManager.getClient(absoluteFilePath, workspaceRoot);
1718
- if (client) {
1719
- const contentNew = fs8.readFileSync(absoluteFilePath, "utf-8");
1720
- const languageId = getLanguageId(absoluteFilePath) || path.extname(absoluteFilePath).slice(1);
1721
- client.notifyOpen(absoluteFilePath, contentNew, languageId);
1722
- client.notifyChange(absoluteFilePath, contentNew, 1);
1723
- const diagnostics = await client.waitForDiagnostics(absoluteFilePath, 3e3).catch(() => []);
1724
- if (diagnostics.length > 0) {
1725
- const seen = /* @__PURE__ */ new Set();
1726
- const dedup = diagnostics.filter((d) => {
1727
- const key = `${d.severity}:${d.range.start.line}:${d.range.start.character}:${d.message}`;
1728
- if (seen.has(key)) return false;
1729
- seen.add(key);
1730
- return true;
1731
- });
1732
- const errors = dedup.filter((d) => d.severity === 1);
1733
- const warnings = dedup.filter((d) => d.severity === 2);
1734
- const info = dedup.filter((d) => d.severity === 3);
1735
- const hints = dedup.filter((d) => d.severity === 4);
1736
- const formatDiags = (items) => items.map((d) => ` ${d.range.start.line + 1}:${d.range.start.character + 1} - ${d.message}`).join("\n");
1737
- let diagnosticText = "";
1738
- if (errors.length > 0) {
1739
- diagnosticText += `
2114
+ const root = projectRoot || process.cwd();
2115
+ const absoluteFilePath = path2.resolve(root, filePath);
2116
+ const allowedPaths = getAllowedPathsFromContext(toolContext);
2117
+ assertPathAllowed(absoluteFilePath, root, allowedPaths);
2118
+ const result = await sharedFileEditor.strReplace({
2119
+ path: absoluteFilePath,
2120
+ old_str,
2121
+ new_str: new_str || "",
2122
+ start_line
2123
+ });
2124
+ let diagnosticOutput = "";
2125
+ try {
2126
+ const workspaceRoot = findWorkspaceRoot(absoluteFilePath);
2127
+ const client = await lspManager.getClient(absoluteFilePath, workspaceRoot);
2128
+ if (client) {
2129
+ const contentNew = fs9.readFileSync(absoluteFilePath, "utf-8");
2130
+ const languageId = getLanguageId(absoluteFilePath) || path2.extname(absoluteFilePath).slice(1);
2131
+ client.notifyOpen(absoluteFilePath, contentNew, languageId);
2132
+ client.notifyChange(absoluteFilePath, contentNew, 1);
2133
+ const diagnostics = await client.waitForDiagnostics(absoluteFilePath, 3e3).catch(() => []);
2134
+ if (diagnostics.length > 0) {
2135
+ const seen = /* @__PURE__ */ new Set();
2136
+ const dedup = diagnostics.filter((d) => {
2137
+ const key = `${d.severity}:${d.range.start.line}:${d.range.start.character}:${d.message}`;
2138
+ if (seen.has(key)) return false;
2139
+ seen.add(key);
2140
+ return true;
2141
+ });
2142
+ const errors = dedup.filter((d) => d.severity === 1);
2143
+ const warnings = dedup.filter((d) => d.severity === 2);
2144
+ const info = dedup.filter((d) => d.severity === 3);
2145
+ const hints = dedup.filter((d) => d.severity === 4);
2146
+ const formatDiags = (items) => items.map((d) => ` ${d.range.start.line + 1}:${d.range.start.character + 1} - ${d.message}`).join("\n");
2147
+ let diagnosticText = "";
2148
+ if (errors.length > 0) {
2149
+ diagnosticText += `
1740
2150
  Errors:
1741
2151
  ${formatDiags(errors)}`;
1742
- }
1743
- if (warnings.length > 0) {
1744
- diagnosticText += `
2152
+ }
2153
+ if (warnings.length > 0) {
2154
+ diagnosticText += `
1745
2155
  Warnings:
1746
2156
  ${formatDiags(warnings)}`;
1747
- }
1748
- if (info.length > 0) {
1749
- diagnosticText += `
2157
+ }
2158
+ if (info.length > 0) {
2159
+ diagnosticText += `
1750
2160
  Info:
1751
2161
  ${formatDiags(info)}`;
1752
- }
1753
- if (hints.length > 0) {
1754
- diagnosticText += `
2162
+ }
2163
+ if (hints.length > 0) {
2164
+ diagnosticText += `
1755
2165
  Hints:
1756
2166
  ${formatDiags(hints)}`;
1757
- }
1758
- if (diagnosticText) {
1759
- diagnosticOutput = truncateStringForTokenEstimate(`
2167
+ }
2168
+ if (diagnosticText) {
2169
+ diagnosticOutput = truncateStringForTokenEstimate(`
1760
2170
 
1761
2171
  LSP Diagnostics:${diagnosticText}`, 500, false);
1762
- }
1763
- } else {
1764
- diagnosticOutput = `
2172
+ }
2173
+ } else {
2174
+ diagnosticOutput = `
1765
2175
 
1766
2176
  LSP Diagnostics:
1767
2177
  No errors or warnings`;
2178
+ }
2179
+ }
2180
+ } catch (lspError) {
2181
+ if (process.env.DEBUG === "true") {
2182
+ console.info("string_replace_lsp: failed to retrieve LSP diagnostics", lspError);
1768
2183
  }
1769
2184
  }
1770
- } catch {
2185
+ return {
2186
+ content: [
2187
+ {
2188
+ type: "text",
2189
+ text: result + diagnosticOutput
2190
+ }
2191
+ ]
2192
+ };
2193
+ } catch (e) {
2194
+ return {
2195
+ error: e instanceof Error ? e.message : JSON.stringify(e, null, 2)
2196
+ };
1771
2197
  }
1772
- return {
1773
- content: [
1774
- {
1775
- type: "text",
1776
- text: result + diagnosticOutput
1777
- }
1778
- ]
1779
- };
1780
- } catch (e) {
1781
- return {
1782
- error: e instanceof Error ? e.message : JSON.stringify(e, null, 2)
1783
- };
1784
2198
  }
1785
- }
1786
- });
2199
+ });
2200
+ }
2201
+ createStringReplaceLspTool();
1787
2202
  var MAX_GREP_TOKENS = 2e3;
1788
2203
  var rgAvailable = null;
1789
2204
  async function hasRipgrep() {
@@ -1821,7 +2236,7 @@ Usage notes:
1821
2236
  execute: async (context, toolContext) => {
1822
2237
  try {
1823
2238
  const root = projectRoot || process.cwd();
1824
- const searchPath = context.path ? path.resolve(root, context.path) : root;
2239
+ const searchPath = context.path ? path2.resolve(root, context.path) : root;
1825
2240
  const allowedPaths = getAllowedPathsFromContext(toolContext);
1826
2241
  assertPathAllowed(searchPath, root, allowedPaths);
1827
2242
  const maxResults = context.maxResults ?? 100;
@@ -1936,7 +2351,7 @@ async function matchGlob(pattern, searchPath, root) {
1936
2351
  if (result.exitCode !== 0) {
1937
2352
  return matchGlobWithFind(pattern, searchPath);
1938
2353
  }
1939
- const allFiles = result.stdout.split("\n").filter((f) => f.trim()).map((f) => path.resolve(searchPath, f));
2354
+ const allFiles = result.stdout.split("\n").filter((f) => f.trim()).map((f) => path2.resolve(searchPath, f));
1940
2355
  return filterByGlob(allFiles, pattern, searchPath);
1941
2356
  }
1942
2357
  return matchGlobWithFind(pattern, searchPath);
@@ -1970,7 +2385,7 @@ async function matchGlobWithFind(pattern, searchPath) {
1970
2385
  function filterByGlob(files, pattern, basePath) {
1971
2386
  const regex = globToRegex(pattern);
1972
2387
  return files.filter((file) => {
1973
- const rel = path.relative(basePath, file);
2388
+ const rel = path2.relative(basePath, file);
1974
2389
  return regex.test(rel);
1975
2390
  });
1976
2391
  }
@@ -2026,7 +2441,7 @@ function escapeRegex(s) {
2026
2441
  }
2027
2442
  async function getModTime(filePath) {
2028
2443
  try {
2029
- const stat = await fs8.promises.stat(filePath);
2444
+ const stat = await fs9.promises.stat(filePath);
2030
2445
  return stat.mtimeMs;
2031
2446
  } catch {
2032
2447
  return 0;
@@ -2054,7 +2469,7 @@ Usage notes:
2054
2469
  execute: async (context, toolContext) => {
2055
2470
  try {
2056
2471
  const root = projectRoot || process.cwd();
2057
- const searchPath = context.path ? path.resolve(root, context.path) : root;
2472
+ const searchPath = context.path ? path2.resolve(root, context.path) : root;
2058
2473
  const allowedPaths = getAllowedPathsFromContext(toolContext);
2059
2474
  assertPathAllowed(searchPath, root, allowedPaths);
2060
2475
  const matches = await matchGlob(context.pattern, searchPath, root);
@@ -2071,7 +2486,7 @@ Usage notes:
2071
2486
  }))
2072
2487
  );
2073
2488
  withTimes.sort((a, b) => b.mtime - a.mtime);
2074
- const relativePaths = withTimes.map((f) => path.relative(root, f.path));
2489
+ const relativePaths = withTimes.map((f) => path2.relative(root, f.path));
2075
2490
  const header = `Found ${relativePaths.length} file${relativePaths.length !== 1 ? "s" : ""} matching "${context.pattern}":
2076
2491
 
2077
2492
  `;
@@ -2111,17 +2526,17 @@ Usage notes:
2111
2526
  try {
2112
2527
  const root = projectRoot || process.cwd();
2113
2528
  const filePath = context.path;
2114
- const absolutePath = path.resolve(root, filePath);
2529
+ const absolutePath = path2.resolve(root, filePath);
2115
2530
  const allowedPaths = getAllowedPathsFromContext(toolContext);
2116
2531
  assertPathAllowed(absolutePath, root, allowedPaths);
2117
- const exists = fs8.existsSync(absolutePath);
2118
- const dir = path.dirname(absolutePath);
2119
- if (!fs8.existsSync(dir)) {
2120
- fs8.mkdirSync(dir, { recursive: true });
2532
+ const exists = fs9.existsSync(absolutePath);
2533
+ const dir = path2.dirname(absolutePath);
2534
+ if (!fs9.existsSync(dir)) {
2535
+ fs9.mkdirSync(dir, { recursive: true });
2121
2536
  }
2122
- fs8.writeFileSync(absolutePath, context.content, "utf-8");
2537
+ fs9.writeFileSync(absolutePath, context.content, "utf-8");
2123
2538
  const lineCount = context.content.split("\n").length;
2124
- const relPath = path.relative(root, absolutePath);
2539
+ const relPath = path2.relative(root, absolutePath);
2125
2540
  if (exists) {
2126
2541
  return {
2127
2542
  content: `Overwrote ${relPath} (${lineCount} lines)`,
@@ -2267,6 +2682,13 @@ function setAuthStorage2(storage) {
2267
2682
  var CODEX_INSTRUCTIONS = `You are an interactive CLI tool that helps users with software engineering tasks. Use the instructions below and the tools available to you to assist the user.
2268
2683
 
2269
2684
  IMPORTANT: You should be concise, direct, and helpful. Focus on solving the user's problem efficiently.`;
2685
+ var GPT5_MODEL_RE = /^gpt-5(?:\.|-|$)/;
2686
+ function getEffectiveThinkingLevel(modelId, level) {
2687
+ if (GPT5_MODEL_RE.test(modelId) && level === "off") {
2688
+ return "low";
2689
+ }
2690
+ return level;
2691
+ }
2270
2692
  var THINKING_LEVEL_TO_REASONING_EFFORT = {
2271
2693
  off: void 0,
2272
2694
  low: "low",
@@ -2299,8 +2721,9 @@ function createCodexMiddleware(reasoningEffort) {
2299
2721
  };
2300
2722
  }
2301
2723
  function openaiCodexProvider(modelId = "codex-mini-latest", options) {
2302
- const level = options?.thinkingLevel ?? "medium";
2303
- const reasoningEffort = THINKING_LEVEL_TO_REASONING_EFFORT[level];
2724
+ const requestedLevel = options?.thinkingLevel ?? "medium";
2725
+ const effectiveLevel = getEffectiveThinkingLevel(modelId, requestedLevel);
2726
+ const reasoningEffort = THINKING_LEVEL_TO_REASONING_EFFORT[effectiveLevel];
2304
2727
  const middleware = createCodexMiddleware(reasoningEffort);
2305
2728
  if (process.env.NODE_ENV === "test" || process.env.VITEST) {
2306
2729
  const openai2 = createOpenAI({
@@ -2373,10 +2796,61 @@ function openaiCodexProvider(modelId = "codex-mini-latest", options) {
2373
2796
  });
2374
2797
  }
2375
2798
  var authStorage = new AuthStorage();
2799
+ var OPENAI_PREFIX = "openai/";
2800
+ var CODEX_OPENAI_MODEL_REMAPS = {
2801
+ "gpt-5.3": "gpt-5.3-codex",
2802
+ "gpt-5.2": "gpt-5.2-codex",
2803
+ "gpt-5.1": "gpt-5.1-codex",
2804
+ "gpt-5.1-mini": "gpt-5.1-codex-mini",
2805
+ "gpt-5": "gpt-5-codex"
2806
+ };
2807
+ function remapOpenAIModelForCodexOAuth(modelId) {
2808
+ if (!modelId.startsWith(OPENAI_PREFIX)) {
2809
+ return modelId;
2810
+ }
2811
+ const openaiModelId = modelId.substring(OPENAI_PREFIX.length);
2812
+ if (openaiModelId.includes("-codex")) {
2813
+ return modelId;
2814
+ }
2815
+ const codexModelId = CODEX_OPENAI_MODEL_REMAPS[openaiModelId];
2816
+ if (!codexModelId) {
2817
+ return modelId;
2818
+ }
2819
+ return `${OPENAI_PREFIX}${codexModelId}`;
2820
+ }
2821
+ function getAnthropicApiKey() {
2822
+ if (process.env.ANTHROPIC_API_KEY) {
2823
+ return process.env.ANTHROPIC_API_KEY;
2824
+ }
2825
+ const storedCred = authStorage.get("anthropic");
2826
+ if (storedCred?.type === "api_key") {
2827
+ return storedCred.key;
2828
+ }
2829
+ return void 0;
2830
+ }
2831
+ function anthropicApiKeyProvider(modelId, apiKey) {
2832
+ const anthropic = createAnthropic({ apiKey });
2833
+ return wrapLanguageModel({
2834
+ model: anthropic(modelId),
2835
+ middleware: [promptCacheMiddleware]
2836
+ });
2837
+ }
2376
2838
  function resolveModel(modelId, options) {
2377
2839
  authStorage.reload();
2840
+ const [providerId, modelName] = modelId.split("/", 2);
2841
+ const settings = loadSettings();
2842
+ const customProvider = providerId && modelName ? settings.customProviders.find((provider) => {
2843
+ return providerId === getCustomProviderId(provider.name);
2844
+ }) : void 0;
2845
+ if (customProvider) {
2846
+ return new ModelRouterLanguageModel({
2847
+ id: modelId,
2848
+ url: customProvider.url,
2849
+ apiKey: customProvider.apiKey
2850
+ });
2851
+ }
2378
2852
  const isAnthropicModel = modelId.startsWith("anthropic/");
2379
- const isOpenAIModel = modelId.startsWith("openai/");
2853
+ const isOpenAIModel = modelId.startsWith(OPENAI_PREFIX);
2380
2854
  const isMoonshotModel = modelId.startsWith("moonshotai/");
2381
2855
  if (isMoonshotModel) {
2382
2856
  if (!process.env.MOONSHOT_AI_API_KEY) {
@@ -2388,18 +2862,25 @@ function resolveModel(modelId, options) {
2388
2862
  name: "moonshotai.anthropicv1"
2389
2863
  })(modelId.substring("moonshotai/".length));
2390
2864
  } else if (isAnthropicModel) {
2391
- return opencodeClaudeMaxProvider(modelId.substring(`anthropic/`.length));
2865
+ const bareModelId = modelId.substring("anthropic/".length);
2866
+ if (authStorage.isLoggedIn("anthropic")) {
2867
+ return opencodeClaudeMaxProvider(bareModelId);
2868
+ }
2869
+ const apiKey = getAnthropicApiKey();
2870
+ if (apiKey) {
2871
+ return anthropicApiKeyProvider(bareModelId, apiKey);
2872
+ }
2873
+ return opencodeClaudeMaxProvider(bareModelId);
2392
2874
  } else if (isOpenAIModel && authStorage.isLoggedIn("openai-codex")) {
2393
- return openaiCodexProvider(modelId.substring(`openai/`.length), {
2875
+ const resolvedModelId = options?.remapForCodexOAuth ? remapOpenAIModelForCodexOAuth(modelId) : modelId;
2876
+ return openaiCodexProvider(resolvedModelId.substring(OPENAI_PREFIX.length), {
2394
2877
  thinkingLevel: options?.thinkingLevel
2395
2878
  });
2396
2879
  } else {
2397
2880
  return new ModelRouterLanguageModel(modelId);
2398
2881
  }
2399
2882
  }
2400
- function getDynamicModel({
2401
- requestContext
2402
- }) {
2883
+ function getDynamicModel({ requestContext }) {
2403
2884
  const harnessContext = requestContext.get("harness");
2404
2885
  const modelId = harnessContext?.state?.currentModelId;
2405
2886
  if (!modelId) {
@@ -2448,14 +2929,14 @@ End with a structured summary:
2448
2929
  . **Notes**: Follow-up needed (if any)`,
2449
2930
  allowedTools: [
2450
2931
  // Read tools
2451
- "view",
2452
- "search_content",
2453
- "find_files",
2932
+ MC_TOOLS.VIEW,
2933
+ MC_TOOLS.SEARCH_CONTENT,
2934
+ MC_TOOLS.FIND_FILES,
2454
2935
  // Write tools
2455
- "string_replace_lsp",
2456
- "write_file",
2936
+ MC_TOOLS.STRING_REPLACE_LSP,
2937
+ MC_TOOLS.WRITE_FILE,
2457
2938
  // Execution tool
2458
- "execute_command",
2939
+ MC_TOOLS.EXECUTE_COMMAND,
2459
2940
  // Task tracking (built-in harness tools)
2460
2941
  "task_write",
2461
2942
  "task_check"
@@ -2492,7 +2973,7 @@ End with a structured summary:
2492
2973
  . **Details**: Additional context if needed
2493
2974
 
2494
2975
  Keep your summary under 300 words.`,
2495
- allowedTools: ["view", "search_content", "find_files"]
2976
+ allowedTools: [MC_TOOLS.VIEW, MC_TOOLS.SEARCH_CONTENT, MC_TOOLS.FIND_FILES]
2496
2977
  };
2497
2978
 
2498
2979
  // src/agents/subagents/plan.ts
@@ -2527,7 +3008,7 @@ Structure your plan as:
2527
3008
  . **Risks**: Potential issues or edge cases (if any)
2528
3009
 
2529
3010
  Be specific about code locations (file paths, function names, line numbers). Keep the plan actionable and under 500 words.`,
2530
- allowedTools: ["view", "search_content", "find_files"]
3011
+ allowedTools: [MC_TOOLS.VIEW, MC_TOOLS.SEARCH_CONTENT, MC_TOOLS.FIND_FILES]
2531
3012
  };
2532
3013
  var MAX_WEB_SEARCH_TOKENS = 2e3;
2533
3014
  var MAX_WEB_EXTRACT_TOKENS = 2e3;
@@ -2638,7 +3119,6 @@ function parseSubagentMeta(content) {
2638
3119
  }) : [];
2639
3120
  return { text, modelId, durationMs, toolCalls };
2640
3121
  }
2641
- var getProjectRoot = () => process.cwd();
2642
3122
  var astSmartEditSchema = z.object({
2643
3123
  path: z.string().describe("File path relative to project root"),
2644
3124
  pattern: z.string().optional().describe("AST pattern to search for (supports $VARIABLE placeholders)"),
@@ -2653,9 +3133,10 @@ var astSmartEditSchema = z.object({
2653
3133
  isDefault: z.boolean().optional()
2654
3134
  }).optional().describe("Import specification for add-import transform")
2655
3135
  });
2656
- var astSmartEditTool = createTool({
2657
- id: "ast_smart_edit",
2658
- description: `Edit code using AST-based analysis for intelligent transformations.
3136
+ function createAstSmartEditTool(projectRoot) {
3137
+ return createTool({
3138
+ id: "ast_smart_edit",
3139
+ description: `Edit code using AST-based analysis for intelligent transformations.
2659
3140
 
2660
3141
  Supports various code transformations:
2661
3142
  - Pattern-based search and replace with syntax awareness
@@ -2668,92 +3149,100 @@ Examples:
2668
3149
  - Add import: { transform: 'add-import', importSpec: { module: 'react', names: ['useState'] } }
2669
3150
  - Rename function: { transform: 'rename-function', targetName: 'oldFunc', newName: 'newFunc' }
2670
3151
  - Pattern replace: { pattern: 'console.log($ARG)', replacement: 'logger.debug($ARG)' }`,
2671
- // requireApproval: true,
2672
- inputSchema: astSmartEditSchema,
2673
- execute: async ({ path: path12, pattern, replacement, selector, transform, targetName, newName, importSpec }, toolContext) => {
2674
- try {
2675
- const projectRoot = getProjectRoot();
2676
- const filePath = resolve(projectRoot, path12);
2677
- const allowedPaths = getAllowedPathsFromContext(toolContext);
2678
- assertPathAllowed(filePath, projectRoot, allowedPaths);
2679
- const content = readFileSync(filePath, "utf-8");
2680
- const lang = getLanguageFromPath(path12);
2681
- const ast = parse(lang, content);
2682
- const root = ast.root();
2683
- let modifiedContent = content;
2684
- let changes = [];
2685
- if (transform) {
2686
- switch (transform) {
2687
- case "add-import":
2688
- if (!importSpec) {
2689
- throw new Error("importSpec is required for add-import transform");
2690
- }
2691
- modifiedContent = addImport(content, root, importSpec);
2692
- changes.push(`Added import from '${importSpec.module}'`);
2693
- break;
2694
- case "remove-import":
2695
- if (!targetName) {
2696
- throw new Error("targetName is required for remove-import transform");
2697
- }
2698
- modifiedContent = removeImport(content, root, targetName);
2699
- changes.push(`Removed import '${targetName}'`);
2700
- break;
2701
- case "rename-function":
2702
- if (!targetName || !newName) {
2703
- throw new Error("targetName and newName are required for rename-function transform");
2704
- }
2705
- const funcResult = renameFunction(content, root, targetName, newName);
2706
- modifiedContent = funcResult.content;
2707
- changes.push(`Renamed function '${targetName}' to '${newName}' (${funcResult.count} occurrences)`);
2708
- break;
2709
- case "rename-variable":
2710
- if (!targetName || !newName) {
2711
- throw new Error("targetName and newName are required for rename-variable transform");
2712
- }
2713
- const varResult = renameVariable(content, root, targetName, newName);
2714
- modifiedContent = varResult.content;
2715
- changes.push(`Renamed variable '${targetName}' to '${newName}' (${varResult.count} occurrences)`);
2716
- break;
2717
- default:
2718
- throw new Error(`Unsupported transform: ${transform}`);
3152
+ // requireApproval: true,
3153
+ inputSchema: astSmartEditSchema,
3154
+ execute: async ({ path: path13, pattern, replacement, selector, transform, targetName, newName, importSpec }, toolContext) => {
3155
+ try {
3156
+ const root = process.cwd();
3157
+ const filePath = resolve(root, path13);
3158
+ const allowedPaths = getAllowedPathsFromContext(toolContext);
3159
+ assertPathAllowed(filePath, root, allowedPaths);
3160
+ const content = readFileSync(filePath, "utf-8");
3161
+ const lang = getLanguageFromPath(filePath);
3162
+ const ast = parse(lang, content);
3163
+ const astRoot = ast.root();
3164
+ let modifiedContent = content;
3165
+ const changes = [];
3166
+ if (transform) {
3167
+ switch (transform) {
3168
+ case "add-import":
3169
+ if (!importSpec) {
3170
+ throw new Error("importSpec is required for add-import transform");
3171
+ }
3172
+ modifiedContent = addImport(content, astRoot, importSpec);
3173
+ changes.push(`Added import from '${importSpec.module}'`);
3174
+ break;
3175
+ case "remove-import":
3176
+ if (!targetName) {
3177
+ throw new Error("targetName is required for remove-import transform");
3178
+ }
3179
+ modifiedContent = removeImport(content, astRoot, targetName);
3180
+ changes.push(`Removed import '${targetName}'`);
3181
+ break;
3182
+ case "rename-function":
3183
+ if (!targetName || !newName) {
3184
+ throw new Error("targetName and newName are required for rename-function transform");
3185
+ }
3186
+ const funcResult = renameFunction(content, astRoot, targetName, newName);
3187
+ modifiedContent = funcResult.content;
3188
+ changes.push(`Renamed function '${targetName}' to '${newName}' (${funcResult.count} occurrences)`);
3189
+ break;
3190
+ case "rename-variable":
3191
+ if (!targetName || !newName) {
3192
+ throw new Error("targetName and newName are required for rename-variable transform");
3193
+ }
3194
+ const varResult = renameVariable(content, astRoot, targetName, newName);
3195
+ modifiedContent = varResult.content;
3196
+ changes.push(`Renamed variable '${targetName}' to '${newName}' (${varResult.count} occurrences)`);
3197
+ break;
3198
+ default:
3199
+ throw new Error(`Unsupported transform: ${transform}`);
3200
+ }
3201
+ } else if (pattern && replacement !== void 0) {
3202
+ const result = patternReplace(content, astRoot, pattern, replacement);
3203
+ modifiedContent = result.content;
3204
+ changes.push(`Replaced ${result.count} occurrences of pattern`);
3205
+ } else if (selector) {
3206
+ const matches = astRoot.findAll(selector);
3207
+ const matchInfo = matches.map((match) => ({
3208
+ text: match.text(),
3209
+ range: match.range(),
3210
+ kind: match.kind()
3211
+ }));
3212
+ return {
3213
+ matches: matchInfo.length,
3214
+ details: matchInfo.slice(0, 10)
3215
+ // Limit to first 10 matches
3216
+ };
3217
+ } else {
3218
+ throw new Error("Must provide either transform, pattern/replacement, or selector");
3219
+ }
3220
+ if (modifiedContent !== content) {
3221
+ writeFileSync(filePath, modifiedContent, "utf-8");
2719
3222
  }
2720
- } else if (pattern && replacement !== void 0) {
2721
- const result = patternReplace(content, root, pattern, replacement);
2722
- modifiedContent = result.content;
2723
- changes.push(`Replaced ${result.count} occurrences of pattern`);
2724
- } else if (selector) {
2725
- const matches = root.findAll(selector);
2726
- const matchInfo = matches.map((match) => ({
2727
- text: match.text(),
2728
- range: match.range(),
2729
- kind: match.kind()
2730
- }));
2731
3223
  return {
2732
- matches: matchInfo.length,
2733
- details: matchInfo.slice(0, 10)
2734
- // Limit to first 10 matches
3224
+ success: true,
3225
+ changes,
3226
+ modified: modifiedContent !== content
3227
+ };
3228
+ } catch (error) {
3229
+ const message = error instanceof Error ? error.message : String(error);
3230
+ if (process.env.DEBUG === "true" && error instanceof Error && error.stack) {
3231
+ return {
3232
+ error: message,
3233
+ stack: error.stack
3234
+ };
3235
+ }
3236
+ return {
3237
+ error: message
2735
3238
  };
2736
- } else {
2737
- throw new Error("Must provide either transform, pattern/replacement, or selector");
2738
- }
2739
- if (modifiedContent !== content) {
2740
- writeFileSync(filePath, modifiedContent, "utf-8");
2741
3239
  }
2742
- return {
2743
- success: true,
2744
- changes,
2745
- modified: modifiedContent !== content
2746
- };
2747
- } catch (error) {
2748
- return {
2749
- error: error.message,
2750
- stack: error.stack
2751
- };
2752
3240
  }
2753
- }
2754
- });
2755
- function getLanguageFromPath(path12) {
2756
- const ext = path12.split(".").pop()?.toLowerCase();
3241
+ });
3242
+ }
3243
+ createAstSmartEditTool();
3244
+ function getLanguageFromPath(path13) {
3245
+ const ext = path13.split(".").pop()?.toLowerCase();
2757
3246
  switch (ext) {
2758
3247
  case "ts":
2759
3248
  case "tsx":
@@ -2963,7 +3452,7 @@ var requestSandboxAccessTool = createTool({
2963
3452
  execute: async ({ path: requestedPath, reason }, context) => {
2964
3453
  try {
2965
3454
  const harnessCtx = context?.requestContext?.get("harness");
2966
- const absolutePath = path.isAbsolute(requestedPath) ? requestedPath : path.resolve(process.cwd(), requestedPath);
3455
+ const absolutePath = path2.isAbsolute(requestedPath) ? requestedPath : path2.resolve(process.cwd(), requestedPath);
2967
3456
  const projectRoot = process.cwd();
2968
3457
  const allowedPaths = getAllowedPathsFromContext(context);
2969
3458
  if (isPathAllowed(absolutePath, projectRoot, allowedPaths)) {
@@ -2979,8 +3468,8 @@ var requestSandboxAccessTool = createTool({
2979
3468
  };
2980
3469
  }
2981
3470
  const questionId = `sandbox_${++requestCounter}_${Date.now()}`;
2982
- const answer = await new Promise((resolve10) => {
2983
- harnessCtx.registerQuestion({ questionId, resolve: resolve10 });
3471
+ const answer = await new Promise((resolve11) => {
3472
+ harnessCtx.registerQuestion({ questionId, resolve: resolve11 });
2984
3473
  harnessCtx.emitEvent({
2985
3474
  type: "sandbox_access_request",
2986
3475
  questionId,
@@ -3021,18 +3510,6 @@ function getAvailableModePacks(access, savedCustomPacks = []) {
3021
3510
  const packs = [];
3022
3511
  const openaiCodex = "openai/gpt-5.3-codex";
3023
3512
  const anthropicBuild = access.anthropic === "oauth" ? "anthropic/claude-opus-4-6" : "anthropic/claude-sonnet-4-5";
3024
- if (access.anthropic && access.openai) {
3025
- packs.push({
3026
- id: "varied",
3027
- name: "Varied",
3028
- description: "Models from multiple providers",
3029
- models: {
3030
- build: anthropicBuild,
3031
- plan: openaiCodex,
3032
- fast: access.cerebras ? "cerebras/zai-glm-4.7" : "anthropic/claude-haiku-4-5"
3033
- }
3034
- });
3035
- }
3036
3513
  if (access.anthropic) {
3037
3514
  packs.push({
3038
3515
  id: "anthropic",
@@ -3121,155 +3598,6 @@ function getAvailableOmPacks(access) {
3121
3598
  return packs;
3122
3599
  }
3123
3600
  var ONBOARDING_VERSION = 1;
3124
- var STORAGE_DEFAULTS = {
3125
- backend: "libsql",
3126
- libsql: {},
3127
- pg: {}
3128
- };
3129
- var DEFAULTS = {
3130
- onboarding: {
3131
- completedAt: null,
3132
- skippedAt: null,
3133
- version: 0,
3134
- modePackId: null,
3135
- omPackId: null,
3136
- claudeMaxOAuthWarningAcknowledgedAt: null
3137
- },
3138
- models: {
3139
- activeModelPackId: null,
3140
- modeDefaults: {},
3141
- activeOmPackId: null,
3142
- omModelOverride: null,
3143
- subagentModels: {}
3144
- },
3145
- preferences: {
3146
- yolo: null,
3147
- theme: "auto"
3148
- },
3149
- storage: { ...STORAGE_DEFAULTS },
3150
- customModelPacks: [],
3151
- modelUseCounts: {}
3152
- };
3153
- function getSettingsPath() {
3154
- return join(getAppDataDir(), "settings.json");
3155
- }
3156
- function migrateFromAuth(settingsPath) {
3157
- const authPath = join(getAppDataDir(), "auth.json");
3158
- if (!existsSync(authPath)) return false;
3159
- let authData;
3160
- try {
3161
- authData = JSON.parse(readFileSync(authPath, "utf-8"));
3162
- } catch {
3163
- return false;
3164
- }
3165
- const modelKeys = Object.keys(authData).filter((k) => k.startsWith("_"));
3166
- if (modelKeys.length === 0) return false;
3167
- let settings;
3168
- if (existsSync(settingsPath)) {
3169
- try {
3170
- const raw = JSON.parse(readFileSync(settingsPath, "utf-8"));
3171
- settings = {
3172
- onboarding: { ...DEFAULTS.onboarding, ...raw.onboarding },
3173
- models: { ...DEFAULTS.models, ...raw.models },
3174
- preferences: { ...DEFAULTS.preferences, ...raw.preferences },
3175
- storage: {
3176
- ...STORAGE_DEFAULTS,
3177
- ...raw.storage,
3178
- libsql: { ...STORAGE_DEFAULTS.libsql, ...raw.storage?.libsql },
3179
- pg: { ...STORAGE_DEFAULTS.pg, ...raw.storage?.pg }
3180
- },
3181
- customModelPacks: Array.isArray(raw.customModelPacks) ? raw.customModelPacks : [],
3182
- modelUseCounts: raw.modelUseCounts && typeof raw.modelUseCounts === "object" ? raw.modelUseCounts : {}
3183
- };
3184
- } catch {
3185
- settings = structuredClone(DEFAULTS);
3186
- }
3187
- } else {
3188
- settings = structuredClone(DEFAULTS);
3189
- }
3190
- if (authData._modelRanks && typeof authData._modelRanks === "object") {
3191
- settings.modelUseCounts = { ...authData._modelRanks, ...settings.modelUseCounts };
3192
- }
3193
- for (const key of modelKeys) {
3194
- const modeMatch = key.match(/^_modeModelId_(.+)$/);
3195
- if (modeMatch?.[1] && typeof authData[key] === "string" && !settings.models.modeDefaults[modeMatch[1]]) {
3196
- settings.models.modeDefaults[modeMatch[1]] = authData[key];
3197
- }
3198
- }
3199
- for (const key of modelKeys) {
3200
- if (key === "_subagentModelId" && typeof authData[key] === "string" && !settings.models.subagentModels["default"]) {
3201
- settings.models.subagentModels["default"] = authData[key];
3202
- }
3203
- const saMatch = key.match(/^_subagentModelId_(.+)$/);
3204
- if (saMatch?.[1] && typeof authData[key] === "string" && !settings.models.subagentModels[saMatch[1]]) {
3205
- settings.models.subagentModels[saMatch[1]] = authData[key];
3206
- }
3207
- }
3208
- saveSettings(settings, settingsPath);
3209
- for (const key of modelKeys) {
3210
- delete authData[key];
3211
- }
3212
- try {
3213
- writeFileSync(authPath, JSON.stringify(authData, null, 2), "utf-8");
3214
- } catch {
3215
- }
3216
- return true;
3217
- }
3218
- function loadSettings(filePath = getSettingsPath()) {
3219
- migrateFromAuth(filePath);
3220
- if (!existsSync(filePath)) return structuredClone(DEFAULTS);
3221
- try {
3222
- const raw = JSON.parse(readFileSync(filePath, "utf-8"));
3223
- const settings = {
3224
- onboarding: { ...DEFAULTS.onboarding, ...raw.onboarding },
3225
- models: { ...DEFAULTS.models, ...raw.models },
3226
- preferences: { ...DEFAULTS.preferences, ...raw.preferences },
3227
- storage: {
3228
- ...STORAGE_DEFAULTS,
3229
- ...raw.storage,
3230
- libsql: { ...STORAGE_DEFAULTS.libsql, ...raw.storage?.libsql },
3231
- pg: { ...STORAGE_DEFAULTS.pg, ...raw.storage?.pg }
3232
- },
3233
- customModelPacks: Array.isArray(raw.customModelPacks) ? raw.customModelPacks : [],
3234
- modelUseCounts: raw.modelUseCounts && typeof raw.modelUseCounts === "object" ? raw.modelUseCounts : {}
3235
- };
3236
- if (raw.models?.omModelId && !settings.models.omModelOverride) {
3237
- settings.models.omModelOverride = raw.models.omModelId;
3238
- saveSettings(settings, filePath);
3239
- }
3240
- return settings;
3241
- } catch {
3242
- return structuredClone(DEFAULTS);
3243
- }
3244
- }
3245
- function resolveModelDefaults(settings, builtinPacks) {
3246
- const { activeModelPackId, modeDefaults } = settings.models;
3247
- if (!activeModelPackId) return modeDefaults;
3248
- if (activeModelPackId.startsWith("custom:")) {
3249
- const name = activeModelPackId.slice("custom:".length);
3250
- const pack = settings.customModelPacks.find((p) => p.name === name);
3251
- if (pack) return pack.models;
3252
- return modeDefaults;
3253
- }
3254
- const builtin = builtinPacks.find((p) => p.id === activeModelPackId);
3255
- if (builtin) return builtin.models;
3256
- return modeDefaults;
3257
- }
3258
- function resolveOmModel(settings, builtinOmPacks) {
3259
- const { activeOmPackId, omModelOverride } = settings.models;
3260
- if (!activeOmPackId) return omModelOverride;
3261
- if (activeOmPackId === "custom") return omModelOverride;
3262
- const pack = builtinOmPacks.find((p) => p.id === activeOmPackId);
3263
- if (pack) return pack.modelId;
3264
- return omModelOverride;
3265
- }
3266
- function saveSettings(settings, filePath = getSettingsPath()) {
3267
- const dir = dirname(filePath);
3268
- if (!existsSync(dir)) {
3269
- mkdirSync(dir, { recursive: true });
3270
- }
3271
- writeFileSync(filePath, JSON.stringify(settings, null, 2), "utf-8");
3272
- }
3273
3601
  var currentThemeMode = "dark";
3274
3602
  function getThemeMode() {
3275
3603
  return currentThemeMode;
@@ -3535,15 +3863,15 @@ var ThreadLockError = class extends Error {
3535
3863
  }
3536
3864
  };
3537
3865
  function getLocksDir() {
3538
- const dir = path.join(getAppDataDir(), "locks");
3539
- if (!fs8.existsSync(dir)) {
3540
- fs8.mkdirSync(dir, { recursive: true });
3866
+ const dir = path2.join(getAppDataDir(), "locks");
3867
+ if (!fs9.existsSync(dir)) {
3868
+ fs9.mkdirSync(dir, { recursive: true });
3541
3869
  }
3542
3870
  return dir;
3543
3871
  }
3544
3872
  function getLockPath(threadId) {
3545
3873
  const safeId = threadId.replace(/[^a-zA-Z0-9_-]/g, "_");
3546
- return path.join(getLocksDir(), `${safeId}.lock`);
3874
+ return path2.join(getLocksDir(), `${safeId}.lock`);
3547
3875
  }
3548
3876
  function isProcessAlive(pid) {
3549
3877
  try {
@@ -3556,9 +3884,9 @@ function isProcessAlive(pid) {
3556
3884
  function acquireThreadLock(threadId) {
3557
3885
  const lockPath = getLockPath(threadId);
3558
3886
  const myPid = process.pid;
3559
- if (fs8.existsSync(lockPath)) {
3887
+ if (fs9.existsSync(lockPath)) {
3560
3888
  try {
3561
- const content = fs8.readFileSync(lockPath, "utf-8").trim();
3889
+ const content = fs9.readFileSync(lockPath, "utf-8").trim();
3562
3890
  const ownerPid = parseInt(content, 10);
3563
3891
  if (!isNaN(ownerPid) && ownerPid !== myPid && isProcessAlive(ownerPid)) {
3564
3892
  throw new ThreadLockError(threadId, ownerPid);
@@ -3567,17 +3895,17 @@ function acquireThreadLock(threadId) {
3567
3895
  if (error instanceof ThreadLockError) throw error;
3568
3896
  }
3569
3897
  }
3570
- fs8.writeFileSync(lockPath, String(myPid), { mode: 420 });
3898
+ fs9.writeFileSync(lockPath, String(myPid), { mode: 420 });
3571
3899
  }
3572
3900
  function releaseThreadLock(threadId) {
3573
3901
  const lockPath = getLockPath(threadId);
3574
3902
  const myPid = process.pid;
3575
3903
  try {
3576
- if (!fs8.existsSync(lockPath)) return;
3577
- const content = fs8.readFileSync(lockPath, "utf-8").trim();
3904
+ if (!fs9.existsSync(lockPath)) return;
3905
+ const content = fs9.readFileSync(lockPath, "utf-8").trim();
3578
3906
  const ownerPid = parseInt(content, 10);
3579
3907
  if (ownerPid === myPid) {
3580
- fs8.unlinkSync(lockPath);
3908
+ fs9.unlinkSync(lockPath);
3581
3909
  }
3582
3910
  } catch {
3583
3911
  }
@@ -3585,15 +3913,15 @@ function releaseThreadLock(threadId) {
3585
3913
  function releaseAllThreadLocks() {
3586
3914
  try {
3587
3915
  const locksDir = getLocksDir();
3588
- const files = fs8.readdirSync(locksDir);
3916
+ const files = fs9.readdirSync(locksDir);
3589
3917
  const myPid = String(process.pid);
3590
3918
  for (const file of files) {
3591
3919
  if (!file.endsWith(".lock")) continue;
3592
- const lockPath = path.join(locksDir, file);
3920
+ const lockPath = path2.join(locksDir, file);
3593
3921
  try {
3594
- const content = fs8.readFileSync(lockPath, "utf-8").trim();
3922
+ const content = fs9.readFileSync(lockPath, "utf-8").trim();
3595
3923
  if (content === myPid) {
3596
- fs8.unlinkSync(lockPath);
3924
+ fs9.unlinkSync(lockPath);
3597
3925
  }
3598
3926
  } catch {
3599
3927
  }
@@ -3602,6 +3930,6 @@ function releaseAllThreadLocks() {
3602
3930
  }
3603
3931
  }
3604
3932
 
3605
- export { ONBOARDING_VERSION, ThreadLockError, acquireThreadLock, applyThemeMode, astSmartEditTool, createExecuteCommandTool, createGlobTool, createGrepTool, createViewTool, createWebExtractTool, createWebSearchTool, createWriteFileTool, executeSubagent, exploreSubagent, getAvailableModePacks, getAvailableOmPacks, getDynamicModel, getEditorTheme, getMarkdownTheme, getSelectListTheme, getSettingsListTheme, getThemeMode, hasTavilyKey, loadSettings, mastra, mastraBrand, parseSubagentMeta, planSubagent, releaseAllThreadLocks, releaseThreadLock, requestSandboxAccessTool, resolveModel, resolveModelDefaults, resolveOmModel, saveSettings, setAuthStorage, setAuthStorage2, stringReplaceLspTool, theme, tintHex };
3606
- //# sourceMappingURL=chunk-REVOTI2T.js.map
3607
- //# sourceMappingURL=chunk-REVOTI2T.js.map
3933
+ export { ONBOARDING_VERSION, THREAD_ACTIVE_MODEL_PACK_ID_KEY, ThreadLockError, acquireThreadLock, applyThemeMode, createExecuteCommandTool, createGlobTool, createGrepTool, createStringReplaceLspTool, createViewTool, createWebExtractTool, createWebSearchTool, createWriteFileTool, executeSubagent, exploreSubagent, getAvailableModePacks, getAvailableOmPacks, getCustomProviderId, getDynamicModel, getDynamicWorkspace, getEditorTheme, getMarkdownTheme, getSelectListTheme, getSettingsListTheme, getThemeMode, hasTavilyKey, loadSettings, mastra, mastraBrand, parseSubagentMeta, planSubagent, releaseAllThreadLocks, releaseThreadLock, requestSandboxAccessTool, resolveModel, resolveModelDefaults, resolveOmModel, resolveThreadActiveModelPackId, saveSettings, setAuthStorage, setAuthStorage2, theme, tintHex, toCustomProviderModelId };
3934
+ //# sourceMappingURL=chunk-JI4M5525.js.map
3935
+ //# sourceMappingURL=chunk-JI4M5525.js.map