mastracode 0.2.0 → 0.3.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 (166) hide show
  1. package/CHANGELOG.md +144 -0
  2. package/README.md +9 -1
  3. package/dist/agents/instructions.d.ts.map +1 -1
  4. package/dist/agents/prompts/base.d.ts +2 -0
  5. package/dist/agents/prompts/base.d.ts.map +1 -1
  6. package/dist/agents/prompts/build.d.ts +1 -1
  7. package/dist/agents/prompts/build.d.ts.map +1 -1
  8. package/dist/agents/prompts/index.d.ts +1 -2
  9. package/dist/agents/prompts/index.d.ts.map +1 -1
  10. package/dist/agents/prompts/plan.d.ts +1 -1
  11. package/dist/agents/prompts/plan.d.ts.map +1 -1
  12. package/dist/agents/prompts/tool-guidance.d.ts +11 -0
  13. package/dist/agents/prompts/tool-guidance.d.ts.map +1 -0
  14. package/dist/agents/workspace.d.ts.map +1 -1
  15. package/dist/auth/storage.d.ts +0 -48
  16. package/dist/auth/storage.d.ts.map +1 -1
  17. package/dist/{chunk-LVGWM7ZS.cjs → chunk-7K5VFY2N.cjs} +768 -1373
  18. package/dist/chunk-7K5VFY2N.cjs.map +1 -0
  19. package/dist/chunk-7TFV3VBB.cjs +8823 -0
  20. package/dist/chunk-7TFV3VBB.cjs.map +1 -0
  21. package/dist/chunk-C6XKRHRK.cjs +853 -0
  22. package/dist/chunk-C6XKRHRK.cjs.map +1 -0
  23. package/dist/{chunk-7V6U7OKQ.js → chunk-HHX6BKLR.js} +234 -121
  24. package/dist/chunk-HHX6BKLR.js.map +1 -0
  25. package/dist/{chunk-FYTZFUHD.js → chunk-LYETHS2L.js} +6389 -5481
  26. package/dist/chunk-LYETHS2L.js.map +1 -0
  27. package/dist/{chunk-BYMDWH2E.js → chunk-V4HZ2AVV.js} +729 -1332
  28. package/dist/chunk-V4HZ2AVV.js.map +1 -0
  29. package/dist/chunk-VRZZSUQE.js +835 -0
  30. package/dist/chunk-VRZZSUQE.js.map +1 -0
  31. package/dist/{chunk-QDLLGD43.cjs → chunk-VZFPT5N7.cjs} +274 -161
  32. package/dist/chunk-VZFPT5N7.cjs.map +1 -0
  33. package/dist/cli.cjs +64 -21
  34. package/dist/cli.cjs.map +1 -1
  35. package/dist/cli.js +61 -18
  36. package/dist/cli.js.map +1 -1
  37. package/dist/index.cjs +2 -2
  38. package/dist/index.d.ts +6 -7
  39. package/dist/index.d.ts.map +1 -1
  40. package/dist/index.js +1 -1
  41. package/dist/onboarding/index.d.ts +7 -0
  42. package/dist/onboarding/index.d.ts.map +1 -0
  43. package/dist/onboarding/onboarding-inline.d.ts +95 -0
  44. package/dist/onboarding/onboarding-inline.d.ts.map +1 -0
  45. package/dist/onboarding/packs.d.ts +46 -0
  46. package/dist/onboarding/packs.d.ts.map +1 -0
  47. package/dist/onboarding/settings.d.ts +110 -0
  48. package/dist/onboarding/settings.d.ts.map +1 -0
  49. package/dist/storage-52Y5MKTG.js +3 -0
  50. package/dist/storage-52Y5MKTG.js.map +1 -0
  51. package/dist/storage-JFFX7LJJ.cjs +24 -0
  52. package/dist/storage-JFFX7LJJ.cjs.map +1 -0
  53. package/dist/tools/string-replace-lsp.d.ts.map +1 -1
  54. package/dist/tui/command-dispatch.d.ts +8 -0
  55. package/dist/tui/command-dispatch.d.ts.map +1 -0
  56. package/dist/tui/commands/cost.d.ts +3 -0
  57. package/dist/tui/commands/cost.d.ts.map +1 -0
  58. package/dist/tui/commands/diff.d.ts +3 -0
  59. package/dist/tui/commands/diff.d.ts.map +1 -0
  60. package/dist/tui/commands/exit.d.ts +3 -0
  61. package/dist/tui/commands/exit.d.ts.map +1 -0
  62. package/dist/tui/commands/help.d.ts +3 -0
  63. package/dist/tui/commands/help.d.ts.map +1 -0
  64. package/dist/tui/commands/hooks.d.ts +3 -0
  65. package/dist/tui/commands/hooks.d.ts.map +1 -0
  66. package/dist/tui/commands/index.d.ts +27 -0
  67. package/dist/tui/commands/index.d.ts.map +1 -0
  68. package/dist/tui/commands/login.d.ts +3 -0
  69. package/dist/tui/commands/login.d.ts.map +1 -0
  70. package/dist/tui/commands/mcp.d.ts +3 -0
  71. package/dist/tui/commands/mcp.d.ts.map +1 -0
  72. package/dist/tui/commands/mode.d.ts +3 -0
  73. package/dist/tui/commands/mode.d.ts.map +1 -0
  74. package/dist/tui/commands/models-pack.d.ts +3 -0
  75. package/dist/tui/commands/models-pack.d.ts.map +1 -0
  76. package/dist/tui/commands/models.d.ts +3 -0
  77. package/dist/tui/commands/models.d.ts.map +1 -0
  78. package/dist/tui/commands/name.d.ts +3 -0
  79. package/dist/tui/commands/name.d.ts.map +1 -0
  80. package/dist/tui/commands/new.d.ts +3 -0
  81. package/dist/tui/commands/new.d.ts.map +1 -0
  82. package/dist/tui/commands/om.d.ts +3 -0
  83. package/dist/tui/commands/om.d.ts.map +1 -0
  84. package/dist/tui/commands/permissions.d.ts +3 -0
  85. package/dist/tui/commands/permissions.d.ts.map +1 -0
  86. package/dist/tui/commands/resource.d.ts +3 -0
  87. package/dist/tui/commands/resource.d.ts.map +1 -0
  88. package/dist/tui/commands/review.d.ts +3 -0
  89. package/dist/tui/commands/review.d.ts.map +1 -0
  90. package/dist/tui/commands/sandbox.d.ts +3 -0
  91. package/dist/tui/commands/sandbox.d.ts.map +1 -0
  92. package/dist/tui/commands/settings.d.ts +3 -0
  93. package/dist/tui/commands/settings.d.ts.map +1 -0
  94. package/dist/tui/commands/setup.d.ts +3 -0
  95. package/dist/tui/commands/setup.d.ts.map +1 -0
  96. package/dist/tui/commands/skills.d.ts +3 -0
  97. package/dist/tui/commands/skills.d.ts.map +1 -0
  98. package/dist/tui/commands/subagents.d.ts +3 -0
  99. package/dist/tui/commands/subagents.d.ts.map +1 -0
  100. package/dist/tui/commands/think.d.ts +3 -0
  101. package/dist/tui/commands/think.d.ts.map +1 -0
  102. package/dist/tui/commands/thread-tag-dir.d.ts +3 -0
  103. package/dist/tui/commands/thread-tag-dir.d.ts.map +1 -0
  104. package/dist/tui/commands/threads.d.ts +3 -0
  105. package/dist/tui/commands/threads.d.ts.map +1 -0
  106. package/dist/tui/commands/types.d.ts +28 -0
  107. package/dist/tui/commands/types.d.ts.map +1 -0
  108. package/dist/tui/commands/yolo.d.ts +3 -0
  109. package/dist/tui/commands/yolo.d.ts.map +1 -0
  110. package/dist/tui/components/banner.d.ts +9 -0
  111. package/dist/tui/components/banner.d.ts.map +1 -0
  112. package/dist/tui/components/help-overlay.d.ts +15 -0
  113. package/dist/tui/components/help-overlay.d.ts.map +1 -0
  114. package/dist/tui/components/model-selector.d.ts +3 -0
  115. package/dist/tui/components/model-selector.d.ts.map +1 -1
  116. package/dist/tui/components/om-progress.d.ts +4 -30
  117. package/dist/tui/components/om-progress.d.ts.map +1 -1
  118. package/dist/tui/components/settings.d.ts +5 -0
  119. package/dist/tui/components/settings.d.ts.map +1 -1
  120. package/dist/tui/components/tool-execution-enhanced.d.ts.map +1 -1
  121. package/dist/tui/display.d.ts +12 -0
  122. package/dist/tui/display.d.ts.map +1 -0
  123. package/dist/tui/event-dispatch.d.ts +11 -0
  124. package/dist/tui/event-dispatch.d.ts.map +1 -0
  125. package/dist/tui/handlers/agent-lifecycle.d.ts +6 -0
  126. package/dist/tui/handlers/agent-lifecycle.d.ts.map +1 -0
  127. package/dist/tui/handlers/index.d.ts +8 -0
  128. package/dist/tui/handlers/index.d.ts.map +1 -0
  129. package/dist/tui/handlers/message.d.ts +6 -0
  130. package/dist/tui/handlers/message.d.ts.map +1 -0
  131. package/dist/tui/handlers/om.d.ts +11 -0
  132. package/dist/tui/handlers/om.d.ts.map +1 -0
  133. package/dist/tui/handlers/prompts.d.ts +20 -0
  134. package/dist/tui/handlers/prompts.d.ts.map +1 -0
  135. package/dist/tui/handlers/subagent.d.ts +6 -0
  136. package/dist/tui/handlers/subagent.d.ts.map +1 -0
  137. package/dist/tui/handlers/tool.d.ts +30 -0
  138. package/dist/tui/handlers/tool.d.ts.map +1 -0
  139. package/dist/tui/handlers/types.d.ts +33 -0
  140. package/dist/tui/handlers/types.d.ts.map +1 -0
  141. package/dist/tui/mastra-tui.d.ts +9 -221
  142. package/dist/tui/mastra-tui.d.ts.map +1 -1
  143. package/dist/tui/render-messages.d.ts +22 -0
  144. package/dist/tui/render-messages.d.ts.map +1 -0
  145. package/dist/tui/setup.d.ts +17 -0
  146. package/dist/tui/setup.d.ts.map +1 -0
  147. package/dist/tui/shell.d.ts +3 -0
  148. package/dist/tui/shell.d.ts.map +1 -0
  149. package/dist/tui/state.d.ts +4 -24
  150. package/dist/tui/state.d.ts.map +1 -1
  151. package/dist/tui/status-line.d.ts +7 -0
  152. package/dist/tui/status-line.d.ts.map +1 -0
  153. package/dist/tui.cjs +17 -17
  154. package/dist/tui.js +2 -2
  155. package/dist/utils/project.d.ts +37 -9
  156. package/dist/utils/project.d.ts.map +1 -1
  157. package/dist/utils/storage-factory.d.ts +21 -0
  158. package/dist/utils/storage-factory.d.ts.map +1 -0
  159. package/package.json +7 -6
  160. package/dist/chunk-7V6U7OKQ.js.map +0 -1
  161. package/dist/chunk-BQ4ZKTYN.cjs +0 -7915
  162. package/dist/chunk-BQ4ZKTYN.cjs.map +0 -1
  163. package/dist/chunk-BYMDWH2E.js.map +0 -1
  164. package/dist/chunk-FYTZFUHD.js.map +0 -1
  165. package/dist/chunk-LVGWM7ZS.cjs.map +0 -1
  166. package/dist/chunk-QDLLGD43.cjs.map +0 -1
@@ -1,1281 +1,58 @@
1
1
  'use strict';
2
2
 
3
+ var chunkC6XKRHRK_cjs = require('./chunk-C6XKRHRK.cjs');
3
4
  var child_process = require('child_process');
4
- var crypto$1 = require('crypto');
5
- var fs9 = require('fs');
5
+ var fs8 = require('fs');
6
6
  var os = require('os');
7
7
  var path = require('path');
8
- var anthropic = require('@ai-sdk/anthropic');
9
- var ai = require('ai');
10
- var openai = require('@ai-sdk/openai');
11
- var llm = require('@mastra/core/llm');
12
- var util = require('util');
13
- var tools = require('@mastra/core/tools');
14
- var zod = require('zod');
15
- var lite = require('js-tiktoken/lite');
16
- var o200k_base = require('js-tiktoken/ranks/o200k_base');
17
- var execa = require('execa');
18
- var stripAnsi = require('strip-ansi');
19
- var treeKill = require('tree-kill');
20
- var node_js = require('vscode-jsonrpc/node.js');
21
- var vscodeLanguageserverProtocol = require('vscode-languageserver-protocol');
22
- var module$1 = require('module');
23
- var url = require('url');
24
- var fastestLevenshtein = require('fastest-levenshtein');
25
- var core = require('@tavily/core');
26
- var napi = require('@ast-grep/napi');
27
- var chalk = require('chalk');
28
-
29
- function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
30
-
31
- function _interopNamespace(e) {
32
- if (e && e.__esModule) return e;
33
- var n = Object.create(null);
34
- if (e) {
35
- Object.keys(e).forEach(function (k) {
36
- if (k !== 'default') {
37
- var d = Object.getOwnPropertyDescriptor(e, k);
38
- Object.defineProperty(n, k, d.get ? d : {
39
- enumerable: true,
40
- get: function () { return e[k]; }
41
- });
42
- }
43
- });
44
- }
45
- n.default = e;
46
- return Object.freeze(n);
47
- }
48
-
49
- var fs9__namespace = /*#__PURE__*/_interopNamespace(fs9);
50
- var os__default = /*#__PURE__*/_interopDefault(os);
51
- var path__namespace = /*#__PURE__*/_interopNamespace(path);
52
- var o200k_base__default = /*#__PURE__*/_interopDefault(o200k_base);
53
- var stripAnsi__default = /*#__PURE__*/_interopDefault(stripAnsi);
54
- var treeKill__default = /*#__PURE__*/_interopDefault(treeKill);
55
- var chalk__default = /*#__PURE__*/_interopDefault(chalk);
56
-
57
- // src/utils/project.ts
58
- function git(args, cwd) {
59
- try {
60
- return child_process.execSync(`git ${args}`, {
61
- cwd,
62
- encoding: "utf-8",
63
- stdio: ["pipe", "pipe", "pipe"]
64
- }).trim();
65
- } catch {
66
- return void 0;
67
- }
68
- }
69
- function slugify(str) {
70
- return str.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "");
71
- }
72
- function shortHash(str) {
73
- return crypto$1.createHash("sha256").update(str).digest("hex").slice(0, 12);
74
- }
75
- function normalizeGitUrl(url) {
76
- return url.replace(/\.git$/, "").replace(/^git@([^:]+):/, "https://$1/").replace(/^ssh:\/\/git@/, "https://").toLowerCase();
77
- }
78
- function detectProject(projectPath) {
79
- const absolutePath = path__namespace.default.resolve(projectPath);
80
- const gitDir = git("rev-parse --git-dir", absolutePath);
81
- const isGitRepo = gitDir !== void 0;
82
- let rootPath = absolutePath;
83
- let gitUrl;
84
- let gitBranch;
85
- let isWorktree = false;
86
- let mainRepoPath;
87
- if (isGitRepo) {
88
- rootPath = git("rev-parse --show-toplevel", absolutePath) || absolutePath;
89
- const commonDir = git("rev-parse --git-common-dir", absolutePath);
90
- if (commonDir && commonDir !== ".git" && commonDir !== gitDir) {
91
- isWorktree = true;
92
- mainRepoPath = path__namespace.default.dirname(path__namespace.default.resolve(rootPath, commonDir));
93
- }
94
- gitUrl = git("remote get-url origin", absolutePath);
95
- if (!gitUrl) {
96
- const remotes = git("remote", absolutePath);
97
- if (remotes) {
98
- const firstRemote = remotes.split("\n")[0];
99
- if (firstRemote) {
100
- gitUrl = git(`remote get-url ${firstRemote}`, absolutePath);
101
- }
102
- }
103
- }
104
- gitBranch = git("rev-parse --abbrev-ref HEAD", absolutePath);
105
- }
106
- let resourceIdSource;
107
- if (gitUrl) {
108
- resourceIdSource = normalizeGitUrl(gitUrl);
109
- } else if (mainRepoPath) {
110
- resourceIdSource = mainRepoPath;
111
- } else {
112
- resourceIdSource = rootPath;
113
- }
114
- const baseName = gitUrl ? gitUrl.split("/").pop()?.replace(/\.git$/, "") || "project" : path__namespace.default.basename(rootPath);
115
- const resourceId = `${slugify(baseName)}-${shortHash(resourceIdSource)}`;
116
- return {
117
- resourceId,
118
- name: baseName,
119
- rootPath,
120
- gitUrl,
121
- gitBranch,
122
- isWorktree,
123
- mainRepoPath
124
- };
125
- }
126
- function getAppDataDir() {
127
- const platform = os__default.default.platform();
128
- let baseDir;
129
- if (platform === "darwin") {
130
- baseDir = path__namespace.default.join(os__default.default.homedir(), "Library", "Application Support");
131
- } else if (platform === "win32") {
132
- baseDir = process.env.APPDATA || path__namespace.default.join(os__default.default.homedir(), "AppData", "Roaming");
133
- } else {
134
- baseDir = process.env.XDG_DATA_HOME || path__namespace.default.join(os__default.default.homedir(), ".local", "share");
135
- }
136
- const appDir = path__namespace.default.join(baseDir, "mastracode");
137
- if (!fs9__namespace.default.existsSync(appDir)) {
138
- fs9__namespace.default.mkdirSync(appDir, { recursive: true });
139
- }
140
- return appDir;
141
- }
142
- function getDatabasePath() {
143
- if (process.env.MASTRA_DB_PATH) {
144
- return process.env.MASTRA_DB_PATH;
145
- }
146
- return path__namespace.default.join(getAppDataDir(), "mastra.db");
147
- }
148
- function getStorageConfig(projectDir) {
149
- if (process.env.MASTRA_DB_URL) {
150
- return {
151
- url: process.env.MASTRA_DB_URL,
152
- authToken: process.env.MASTRA_DB_AUTH_TOKEN,
153
- isRemote: !process.env.MASTRA_DB_URL.startsWith("file:")
154
- };
155
- }
156
- if (projectDir) {
157
- const projectConfig = loadDatabaseConfig(path__namespace.default.join(projectDir, ".mastracode", "database.json"));
158
- if (projectConfig) return projectConfig;
159
- }
160
- const globalConfig = loadDatabaseConfig(path__namespace.default.join(os__default.default.homedir(), ".mastracode", "database.json"));
161
- if (globalConfig) return globalConfig;
162
- return {
163
- url: `file:${getDatabasePath()}`,
164
- isRemote: false
165
- };
166
- }
167
- function loadDatabaseConfig(filePath) {
168
- try {
169
- if (!fs9__namespace.default.existsSync(filePath)) return null;
170
- const raw = fs9__namespace.default.readFileSync(filePath, "utf-8");
171
- const parsed = JSON.parse(raw);
172
- if (typeof parsed?.url === "string" && parsed.url) {
173
- return {
174
- url: parsed.url,
175
- authToken: typeof parsed.authToken === "string" ? parsed.authToken : void 0,
176
- isRemote: !parsed.url.startsWith("file:")
177
- };
178
- }
179
- return null;
180
- } catch {
181
- return null;
182
- }
183
- }
184
- function getUserId(projectDir) {
185
- if (process.env.MASTRA_USER_ID) {
186
- return process.env.MASTRA_USER_ID;
187
- }
188
- const cwd = projectDir || process.cwd();
189
- const email = git("config user.email", cwd);
190
- if (email) {
191
- return email;
192
- }
193
- return os__default.default.userInfo().username || "unknown";
194
- }
195
- function getOmScope(projectDir) {
196
- const envScope = process.env.MASTRA_OM_SCOPE;
197
- if (envScope === "thread" || envScope === "resource") {
198
- return envScope;
199
- }
200
- if (projectDir) {
201
- const scope2 = loadOmScopeFromConfig(path__namespace.default.join(projectDir, ".mastracode", "database.json"));
202
- if (scope2) return scope2;
203
- }
204
- const scope = loadOmScopeFromConfig(path__namespace.default.join(os__default.default.homedir(), ".mastracode", "database.json"));
205
- if (scope) return scope;
206
- return "thread";
207
- }
208
- function loadOmScopeFromConfig(filePath) {
209
- try {
210
- if (!fs9__namespace.default.existsSync(filePath)) return null;
211
- const raw = fs9__namespace.default.readFileSync(filePath, "utf-8");
212
- const parsed = JSON.parse(raw);
213
- if (parsed?.omScope === "thread" || parsed?.omScope === "resource") {
214
- return parsed.omScope;
215
- }
216
- return null;
217
- } catch {
218
- return null;
219
- }
220
- }
221
- function getResourceIdOverride(projectDir) {
222
- if (process.env.MASTRA_RESOURCE_ID) {
223
- return process.env.MASTRA_RESOURCE_ID;
224
- }
225
- if (projectDir) {
226
- const rid2 = loadStringField(path__namespace.default.join(projectDir, ".mastracode", "database.json"), "resourceId");
227
- if (rid2) return rid2;
228
- }
229
- const rid = loadStringField(path__namespace.default.join(os__default.default.homedir(), ".mastracode", "database.json"), "resourceId");
230
- if (rid) return rid;
231
- return null;
232
- }
233
- function loadStringField(filePath, field) {
234
- try {
235
- if (!fs9__namespace.default.existsSync(filePath)) return null;
236
- const raw = fs9__namespace.default.readFileSync(filePath, "utf-8");
237
- const parsed = JSON.parse(raw);
238
- const value = parsed?.[field];
239
- if (typeof value === "string" && value) {
240
- return value;
241
- }
242
- return null;
243
- } catch {
244
- return null;
245
- }
246
- }
247
-
248
- // src/auth/pkce.ts
249
- function base64urlEncode(bytes) {
250
- let binary = "";
251
- for (const byte of bytes) {
252
- binary += String.fromCharCode(byte);
253
- }
254
- return btoa(binary).replace(/\+/g, "-").replace(/\//g, "_").replace(/=/g, "");
255
- }
256
- async function generatePKCE() {
257
- const verifierBytes = new Uint8Array(32);
258
- crypto.getRandomValues(verifierBytes);
259
- const verifier = base64urlEncode(verifierBytes);
260
- const encoder = new TextEncoder();
261
- const data = encoder.encode(verifier);
262
- const hashBuffer = await crypto.subtle.digest("SHA-256", data);
263
- const challenge = base64urlEncode(new Uint8Array(hashBuffer));
264
- return { verifier, challenge };
265
- }
266
-
267
- // src/auth/providers/anthropic.ts
268
- var decode = (s) => atob(s);
269
- var CLIENT_ID = decode("OWQxYzI1MGEtZTYxYi00NGQ5LTg4ZWQtNTk0NGQxOTYyZjVl");
270
- var AUTHORIZE_URL = "https://claude.ai/oauth/authorize";
271
- var TOKEN_URL = "https://console.anthropic.com/v1/oauth/token";
272
- var REDIRECT_URI = "https://console.anthropic.com/oauth/code/callback";
273
- var SCOPES = "org:create_api_key user:profile user:inference";
274
- async function loginAnthropic(onAuthUrl, onPromptCode) {
275
- const { verifier, challenge } = await generatePKCE();
276
- const authParams = new URLSearchParams({
277
- code: "true",
278
- client_id: CLIENT_ID,
279
- response_type: "code",
280
- redirect_uri: REDIRECT_URI,
281
- scope: SCOPES,
282
- code_challenge: challenge,
283
- code_challenge_method: "S256",
284
- state: verifier
285
- });
286
- const authUrl = `${AUTHORIZE_URL}?${authParams.toString()}`;
287
- onAuthUrl(authUrl);
288
- const authCode = await onPromptCode();
289
- const splits = authCode.split("#");
290
- const code = splits[0];
291
- const state = splits[1];
292
- const tokenResponse = await fetch(TOKEN_URL, {
293
- method: "POST",
294
- headers: {
295
- "Content-Type": "application/json"
296
- },
297
- body: JSON.stringify({
298
- grant_type: "authorization_code",
299
- client_id: CLIENT_ID,
300
- code,
301
- state,
302
- redirect_uri: REDIRECT_URI,
303
- code_verifier: verifier
304
- })
305
- });
306
- if (!tokenResponse.ok) {
307
- const error = await tokenResponse.text();
308
- throw new Error(`Token exchange failed: ${error}`);
309
- }
310
- const tokenData = await tokenResponse.json();
311
- const expiresAt = Date.now() + tokenData.expires_in * 1e3 - 5 * 60 * 1e3;
312
- return {
313
- refresh: tokenData.refresh_token,
314
- access: tokenData.access_token,
315
- expires: expiresAt
316
- };
317
- }
318
- async function refreshAnthropicToken(refreshToken) {
319
- const response = await fetch(TOKEN_URL, {
320
- method: "POST",
321
- headers: { "Content-Type": "application/json" },
322
- body: JSON.stringify({
323
- grant_type: "refresh_token",
324
- client_id: CLIENT_ID,
325
- refresh_token: refreshToken
326
- })
327
- });
328
- if (!response.ok) {
329
- const error = await response.text();
330
- throw new Error(`Anthropic token refresh failed: ${error}`);
331
- }
332
- const data = await response.json();
333
- return {
334
- refresh: data.refresh_token,
335
- access: data.access_token,
336
- expires: Date.now() + data.expires_in * 1e3 - 5 * 60 * 1e3
337
- };
338
- }
339
- var anthropicOAuthProvider = {
340
- id: "anthropic",
341
- name: "Anthropic (Claude Pro/Max)",
342
- async login(callbacks) {
343
- return loginAnthropic(
344
- (url) => callbacks.onAuth({ url }),
345
- () => callbacks.onPrompt({ message: "Paste the authorization code:" })
346
- );
347
- },
348
- async refreshToken(credentials) {
349
- return refreshAnthropicToken(credentials.refresh);
350
- },
351
- getApiKey(credentials) {
352
- return credentials.access;
353
- }
354
- };
355
-
356
- // src/auth/providers/openai-codex.ts
357
- var _randomBytes = null;
358
- var _http = null;
359
- if (typeof process !== "undefined" && (process.versions?.node || process.versions?.bun)) {
360
- import('crypto').then((m) => {
361
- _randomBytes = m.randomBytes;
362
- });
363
- import('http').then((m) => {
364
- _http = m;
365
- });
366
- }
367
- var CLIENT_ID2 = "app_EMoamEEZ73f0CkXaXp7hrann";
368
- var AUTHORIZE_URL2 = "https://auth.openai.com/oauth/authorize";
369
- var TOKEN_URL2 = "https://auth.openai.com/oauth/token";
370
- var REDIRECT_URI2 = "http://localhost:1455/auth/callback";
371
- var SCOPE = "openid profile email offline_access";
372
- var JWT_CLAIM_PATH = "https://api.openai.com/auth";
373
- var SUCCESS_HTML = `<!doctype html>
374
- <html lang="en">
375
- <head>
376
- <meta charset="utf-8" />
377
- <meta name="viewport" content="width=device-width, initial-scale=1" />
378
- <title>Authentication successful</title>
379
- </head>
380
- <body>
381
- <p>Authentication successful. Return to your terminal to continue.</p>
382
- </body>
383
- </html>`;
384
- function createState() {
385
- if (!_randomBytes) {
386
- throw new Error("OpenAI Codex OAuth is only available in Node.js environments");
387
- }
388
- return _randomBytes(16).toString("hex");
389
- }
390
- function parseAuthorizationInput(input) {
391
- const value = input.trim();
392
- if (!value) return {};
393
- try {
394
- const url = new URL(value);
395
- return {
396
- code: url.searchParams.get("code") ?? void 0,
397
- state: url.searchParams.get("state") ?? void 0
398
- };
399
- } catch {
400
- }
401
- if (value.includes("#")) {
402
- const [code, state] = value.split("#", 2);
403
- return { code, state };
404
- }
405
- if (value.includes("code=")) {
406
- const params = new URLSearchParams(value);
407
- return {
408
- code: params.get("code") ?? void 0,
409
- state: params.get("state") ?? void 0
410
- };
411
- }
412
- return { code: value };
413
- }
414
- function decodeJwt(token) {
415
- try {
416
- const parts = token.split(".");
417
- if (parts.length !== 3) return null;
418
- const payload = parts[1] ?? "";
419
- const decoded = atob(payload);
420
- return JSON.parse(decoded);
421
- } catch {
422
- return null;
423
- }
424
- }
425
- async function exchangeAuthorizationCode(code, verifier, redirectUri = REDIRECT_URI2) {
426
- const response = await fetch(TOKEN_URL2, {
427
- method: "POST",
428
- headers: { "Content-Type": "application/x-www-form-urlencoded" },
429
- body: new URLSearchParams({
430
- grant_type: "authorization_code",
431
- client_id: CLIENT_ID2,
432
- code,
433
- code_verifier: verifier,
434
- redirect_uri: redirectUri
435
- })
436
- });
437
- if (!response.ok) {
438
- const text = await response.text().catch(() => "");
439
- console.error("[openai-codex] code->token failed:", response.status, text);
440
- return { type: "failed" };
441
- }
442
- const json = await response.json();
443
- if (!json.access_token || !json.refresh_token || typeof json.expires_in !== "number") {
444
- console.error("[openai-codex] token response missing fields:", json);
445
- return { type: "failed" };
446
- }
447
- return {
448
- type: "success",
449
- access: json.access_token,
450
- refresh: json.refresh_token,
451
- expires: Date.now() + json.expires_in * 1e3
452
- };
453
- }
454
- async function refreshAccessToken(refreshToken) {
455
- try {
456
- const response = await fetch(TOKEN_URL2, {
457
- method: "POST",
458
- headers: { "Content-Type": "application/x-www-form-urlencoded" },
459
- body: new URLSearchParams({
460
- grant_type: "refresh_token",
461
- refresh_token: refreshToken,
462
- client_id: CLIENT_ID2
463
- })
464
- });
465
- if (!response.ok) {
466
- const text = await response.text().catch(() => "");
467
- console.error("[openai-codex] Token refresh failed:", response.status, text);
468
- return { type: "failed" };
469
- }
470
- const json = await response.json();
471
- if (!json.access_token || !json.refresh_token || typeof json.expires_in !== "number") {
472
- console.error("[openai-codex] Token refresh response missing fields:", json);
473
- return { type: "failed" };
474
- }
475
- return {
476
- type: "success",
477
- access: json.access_token,
478
- refresh: json.refresh_token,
479
- expires: Date.now() + json.expires_in * 1e3
480
- };
481
- } catch (error) {
482
- console.error("[openai-codex] Token refresh error:", error);
483
- return { type: "failed" };
484
- }
485
- }
486
- async function createAuthorizationFlow(originator = "pi") {
487
- const { verifier, challenge } = await generatePKCE();
488
- const state = createState();
489
- const url = new URL(AUTHORIZE_URL2);
490
- url.searchParams.set("response_type", "code");
491
- url.searchParams.set("client_id", CLIENT_ID2);
492
- url.searchParams.set("redirect_uri", REDIRECT_URI2);
493
- url.searchParams.set("scope", SCOPE);
494
- url.searchParams.set("code_challenge", challenge);
495
- url.searchParams.set("code_challenge_method", "S256");
496
- url.searchParams.set("state", state);
497
- url.searchParams.set("id_token_add_organizations", "true");
498
- url.searchParams.set("codex_cli_simplified_flow", "true");
499
- url.searchParams.set("originator", originator);
500
- return { verifier, state, url: url.toString() };
501
- }
502
- function startLocalOAuthServer(state) {
503
- if (!_http) {
504
- throw new Error("OpenAI Codex OAuth is only available in Node.js environments");
505
- }
506
- let lastCode = null;
507
- let cancelled = false;
508
- const server = _http.createServer((req, res) => {
509
- try {
510
- const url = new URL(req.url || "", "http://localhost");
511
- if (url.pathname !== "/auth/callback") {
512
- res.statusCode = 404;
513
- res.end("Not found");
514
- return;
515
- }
516
- if (url.searchParams.get("state") !== state) {
517
- res.statusCode = 400;
518
- res.end("State mismatch");
519
- return;
520
- }
521
- const code = url.searchParams.get("code");
522
- if (!code) {
523
- res.statusCode = 400;
524
- res.end("Missing authorization code");
525
- return;
526
- }
527
- res.statusCode = 200;
528
- res.setHeader("Content-Type", "text/html; charset=utf-8");
529
- res.end(SUCCESS_HTML);
530
- lastCode = code;
531
- } catch {
532
- res.statusCode = 500;
533
- res.end("Internal error");
534
- }
535
- });
536
- return new Promise((resolve10) => {
537
- server.listen(1455, "127.0.0.1", () => {
538
- resolve10({
539
- close: () => server.close(),
540
- cancelWait: () => {
541
- cancelled = true;
542
- },
543
- waitForCode: async () => {
544
- const sleep = () => new Promise((r) => setTimeout(r, 100));
545
- for (let i = 0; i < 600; i += 1) {
546
- if (lastCode) return { code: lastCode };
547
- if (cancelled) return null;
548
- await sleep();
549
- }
550
- return null;
551
- }
552
- });
553
- }).on("error", (err) => {
554
- console.error(
555
- "[openai-codex] Failed to bind http://127.0.0.1:1455 (",
556
- err.code,
557
- ") Falling back to manual paste."
558
- );
559
- resolve10({
560
- close: () => {
561
- try {
562
- server.close();
563
- } catch {
564
- }
565
- },
566
- cancelWait: () => {
567
- },
568
- waitForCode: async () => null
569
- });
570
- });
571
- });
572
- }
573
- function getAccountId(accessToken) {
574
- const payload = decodeJwt(accessToken);
575
- const auth = payload?.[JWT_CLAIM_PATH];
576
- const accountId = auth?.chatgpt_account_id;
577
- return typeof accountId === "string" && accountId.length > 0 ? accountId : null;
578
- }
579
- async function loginOpenAICodex(options) {
580
- const { verifier, state, url } = await createAuthorizationFlow(options.originator);
581
- const server = await startLocalOAuthServer(state);
582
- options.onAuth({
583
- url,
584
- instructions: "A browser window should open. Complete login to finish."
585
- });
586
- let code;
587
- try {
588
- if (options.onManualCodeInput) {
589
- let manualCode;
590
- let manualError;
591
- const manualPromise = options.onManualCodeInput().then((input) => {
592
- manualCode = input;
593
- server.cancelWait();
594
- }).catch((err) => {
595
- manualError = err instanceof Error ? err : new Error(String(err));
596
- server.cancelWait();
597
- });
598
- const result = await server.waitForCode();
599
- if (manualError) {
600
- throw manualError;
601
- }
602
- if (result?.code) {
603
- code = result.code;
604
- } else if (manualCode) {
605
- const parsed = parseAuthorizationInput(manualCode);
606
- if (parsed.state && parsed.state !== state) {
607
- throw new Error("State mismatch");
608
- }
609
- code = parsed.code;
610
- }
611
- if (!code) {
612
- await manualPromise;
613
- if (manualError) {
614
- throw manualError;
615
- }
616
- if (manualCode) {
617
- const parsed = parseAuthorizationInput(manualCode);
618
- if (parsed.state && parsed.state !== state) {
619
- throw new Error("State mismatch");
620
- }
621
- code = parsed.code;
622
- }
623
- }
624
- } else {
625
- const result = await server.waitForCode();
626
- if (result?.code) {
627
- code = result.code;
628
- }
629
- }
630
- if (!code) {
631
- const input = await options.onPrompt({
632
- message: "Paste the authorization code (or full redirect URL):"
633
- });
634
- const parsed = parseAuthorizationInput(input);
635
- if (parsed.state && parsed.state !== state) {
636
- throw new Error("State mismatch");
637
- }
638
- code = parsed.code;
639
- }
640
- if (!code) {
641
- throw new Error("Missing authorization code");
642
- }
643
- const tokenResult = await exchangeAuthorizationCode(code, verifier);
644
- if (tokenResult.type !== "success") {
645
- throw new Error("Token exchange failed");
646
- }
647
- const accountId = getAccountId(tokenResult.access);
648
- if (!accountId) {
649
- throw new Error("Failed to extract accountId from token");
650
- }
651
- return {
652
- access: tokenResult.access,
653
- refresh: tokenResult.refresh,
654
- expires: tokenResult.expires,
655
- accountId
656
- };
657
- } finally {
658
- server.close();
659
- }
660
- }
661
- async function refreshOpenAICodexToken(refreshToken) {
662
- const result = await refreshAccessToken(refreshToken);
663
- if (result.type !== "success") {
664
- throw new Error("Failed to refresh OpenAI Codex token");
665
- }
666
- const accountId = getAccountId(result.access);
667
- if (!accountId) {
668
- throw new Error("Failed to extract accountId from token");
669
- }
670
- return {
671
- access: result.access,
672
- refresh: result.refresh,
673
- expires: result.expires,
674
- accountId
675
- };
676
- }
677
- var openaiCodexOAuthProvider = {
678
- id: "openai-codex",
679
- name: "ChatGPT Plus/Pro (Codex Subscription)",
680
- usesCallbackServer: true,
681
- async login(callbacks) {
682
- return loginOpenAICodex({
683
- onAuth: callbacks.onAuth,
684
- onPrompt: callbacks.onPrompt,
685
- onProgress: callbacks.onProgress,
686
- onManualCodeInput: callbacks.onManualCodeInput
687
- });
688
- },
689
- async refreshToken(credentials) {
690
- return refreshOpenAICodexToken(credentials.refresh);
691
- },
692
- getApiKey(credentials) {
693
- return credentials.access;
694
- }
695
- };
696
-
697
- // src/auth/storage.ts
698
- var PROVIDER_DEFAULT_MODELS = {
699
- anthropic: "anthropic/claude-opus-4-6",
700
- "openai-codex": "openai/gpt-5.3-codex"
701
- };
702
- var oauthProviderRegistry = /* @__PURE__ */ new Map([
703
- [anthropicOAuthProvider.id, anthropicOAuthProvider],
704
- [openaiCodexOAuthProvider.id, openaiCodexOAuthProvider]
705
- ]);
706
- function getOAuthProvider(id) {
707
- return oauthProviderRegistry.get(id);
708
- }
709
- function getOAuthProviders() {
710
- return Array.from(oauthProviderRegistry.values());
711
- }
712
- var AuthStorage = class {
713
- constructor(authPath = path.join(getAppDataDir(), "auth.json")) {
714
- this.authPath = authPath;
715
- this.reload();
716
- }
717
- data = {};
718
- /**
719
- * Reload credentials from disk.
720
- */
721
- reload() {
722
- if (!fs9.existsSync(this.authPath)) {
723
- this.data = {};
724
- return;
725
- }
726
- try {
727
- this.data = JSON.parse(fs9.readFileSync(this.authPath, "utf-8"));
728
- } catch {
729
- this.data = {};
730
- }
731
- }
732
- /**
733
- * Save credentials to disk.
734
- */
735
- save() {
736
- const dir = path.dirname(this.authPath);
737
- if (!fs9.existsSync(dir)) {
738
- fs9.mkdirSync(dir, { recursive: true, mode: 448 });
739
- }
740
- fs9.writeFileSync(this.authPath, JSON.stringify(this.data, null, 2), "utf-8");
741
- fs9.chmodSync(this.authPath, 384);
742
- }
743
- /**
744
- * Get credential for a provider.
745
- */
746
- get(provider) {
747
- return this.data[provider] ?? void 0;
748
- }
749
- /**
750
- * Set credential for a provider.
751
- */
752
- set(provider, credential) {
753
- this.data[provider] = credential;
754
- this.save();
755
- }
756
- /**
757
- * Remove credential for a provider.
758
- */
759
- remove(provider) {
760
- delete this.data[provider];
761
- this.save();
762
- }
763
- /**
764
- * List all providers with credentials.
765
- */
766
- list() {
767
- return Object.keys(this.data);
768
- }
769
- /**
770
- * Check if credentials exist for a provider.
771
- */
772
- has(provider) {
773
- return provider in this.data;
774
- }
775
- /**
776
- * Check if logged in via OAuth for a provider.
777
- */
778
- isLoggedIn(provider) {
779
- const cred = this.data[provider];
780
- return cred?.type === "oauth";
781
- }
782
- /**
783
- * Login to an OAuth provider.
784
- */
785
- async login(providerId, callbacks) {
786
- const provider = getOAuthProvider(providerId);
787
- if (!provider) {
788
- throw new Error(`Unknown OAuth provider: ${providerId}`);
789
- }
790
- const credentials = await provider.login(callbacks);
791
- this.set(providerId, { type: "oauth", ...credentials });
792
- }
793
- /**
794
- * Logout from a provider.
795
- */
796
- logout(provider) {
797
- this.remove(provider);
798
- }
799
- /**
800
- * Get API key for a provider, auto-refreshing OAuth tokens if needed.
801
- */
802
- async getApiKey(providerId) {
803
- const cred = this.data[providerId];
804
- if (cred?.type === "api_key") {
805
- return cred.key;
806
- }
807
- if (cred?.type === "oauth") {
808
- const provider = getOAuthProvider(providerId);
809
- if (!provider) {
810
- return void 0;
811
- }
812
- if (Date.now() >= cred.expires) {
813
- try {
814
- const newCreds = await provider.refreshToken(cred);
815
- this.set(providerId, { type: "oauth", ...newCreds });
816
- return provider.getApiKey(newCreds);
817
- } catch {
818
- return void 0;
819
- }
820
- }
821
- return provider.getApiKey(cred);
822
- }
823
- return void 0;
824
- }
825
- /**
826
- * Get the last used model ID (global preference).
827
- */
828
- getLastModelId() {
829
- return this.data._lastModelId;
830
- }
831
- /**
832
- * Set the last used model ID (global preference).
833
- */
834
- setLastModelId(modelId) {
835
- this.data._lastModelId = modelId;
836
- this.save();
837
- }
838
- /**
839
- * Get the global model ID for a specific mode.
840
- * @param modeId Mode ID (e.g., "build", "plan", "explore")
841
- */
842
- getModeModelId(modeId) {
843
- return this.data[`_modeModelId_${modeId}`];
844
- }
845
- /**
846
- * Set the global model ID for a specific mode.
847
- * @param modeId Mode ID (e.g., "build", "plan", "explore")
848
- * @param modelId Full model ID
849
- */
850
- setModeModelId(modeId, modelId) {
851
- this.data[`_modeModelId_${modeId}`] = modelId;
852
- this.save();
853
- }
854
- /**
855
- * Get the global subagent model ID for an agent type.
856
- * @param agentType Optional agent type (explore, plan, execute)
857
- */
858
- getSubagentModelId(agentType) {
859
- if (agentType) {
860
- return this.data[`_subagentModelId_${agentType}`];
861
- }
862
- return this.data._subagentModelId;
863
- }
864
- /**
865
- * Set the global subagent model ID for an agent type.
866
- * @param modelId Full model ID
867
- * @param agentType Optional agent type (explore, plan, execute)
868
- */
869
- setSubagentModelId(modelId, agentType) {
870
- if (agentType) {
871
- this.data[`_subagentModelId_${agentType}`] = modelId;
872
- } else {
873
- this.data._subagentModelId = modelId;
874
- }
875
- this.save();
876
- }
877
- /**
878
- * Get the default model for a provider after login.
879
- */
880
- getDefaultModelForProvider(providerId) {
881
- return PROVIDER_DEFAULT_MODELS[providerId];
882
- }
883
- // ===========================================================================
884
- // Model Usage Ranking
885
- // ===========================================================================
886
- getModelRanks() {
887
- return this.data._modelRanks ?? {};
888
- }
889
- /**
890
- * Get the use count for a model (0 if never used).
891
- */
892
- getModelUseCount(modelId) {
893
- return this.getModelRanks()[modelId] ?? 0;
894
- }
895
- /**
896
- * Get all model use counts.
897
- */
898
- getAllModelUseCounts() {
899
- return { ...this.getModelRanks() };
900
- }
901
- /**
902
- * Increment the use count for a model and persist.
903
- */
904
- incrementModelUseCount(modelId) {
905
- const ranks = this.getModelRanks();
906
- ranks[modelId] = (ranks[modelId] ?? 0) + 1;
907
- this.data._modelRanks = ranks;
908
- this.save();
909
- }
910
- };
911
- var claudeCodeIdentity = "You are Claude Code, Anthropic's official CLI for Claude.";
912
- var authStorageInstance = null;
913
- function getAuthStorage() {
914
- if (!authStorageInstance) {
915
- authStorageInstance = new AuthStorage();
916
- }
917
- return authStorageInstance;
918
- }
919
- function setAuthStorage(storage) {
920
- authStorageInstance = storage;
921
- }
922
- var claudeCodeMiddleware = {
923
- specificationVersion: "v3",
924
- transformParams: async ({ params }) => {
925
- const systemMessage = {
926
- role: "system",
927
- content: claudeCodeIdentity
928
- };
929
- if (params.temperature) {
930
- delete params.topP;
931
- }
932
- return {
933
- ...params,
934
- prompt: [systemMessage, ...params.prompt]
935
- };
936
- }
937
- };
938
- var promptCacheMiddleware = {
939
- specificationVersion: "v3",
940
- transformParams: async ({ params }) => {
941
- const prompt = [...params.prompt];
942
- const cacheControl = { type: "ephemeral", ttl: "5m" };
943
- const addCacheToMessage = (msg) => {
944
- if (typeof msg.content === "string") {
945
- return {
946
- ...msg,
947
- providerOptions: {
948
- ...msg.providerOptions,
949
- anthropic: { ...msg.providerOptions?.anthropic, cacheControl }
950
- }
951
- };
952
- }
953
- if (Array.isArray(msg.content) && msg.content.length > 0) {
954
- const content = [...msg.content];
955
- const lastPart = content[content.length - 1];
956
- content[content.length - 1] = {
957
- ...lastPart,
958
- providerOptions: {
959
- ...lastPart.providerOptions,
960
- anthropic: { ...lastPart.providerOptions?.anthropic, cacheControl }
961
- }
962
- };
963
- return { ...msg, content };
964
- }
965
- return msg;
966
- };
967
- let lastSystemIdx = -1;
968
- for (let i = prompt.length - 1; i >= 0; i--) {
969
- if (prompt[i].role === "system") {
970
- lastSystemIdx = i;
971
- break;
972
- }
973
- }
974
- if (lastSystemIdx >= 0) {
975
- prompt[lastSystemIdx] = addCacheToMessage(prompt[lastSystemIdx]);
976
- }
977
- const lastIdx = prompt.length - 1;
978
- if (lastIdx >= 0 && lastIdx !== lastSystemIdx) {
979
- prompt[lastIdx] = addCacheToMessage(prompt[lastIdx]);
980
- }
981
- return { ...params, prompt };
982
- }
983
- };
984
- function opencodeClaudeMaxProvider(modelId = "claude-sonnet-4-20250514") {
985
- if (process.env.NODE_ENV === "test" || process.env.VITEST) {
986
- const anthropic2 = anthropic.createAnthropic({
987
- apiKey: process.env.ANTHROPIC_API_KEY || "test-api-key"
988
- });
989
- return ai.wrapLanguageModel({
990
- model: anthropic2(modelId),
991
- middleware: [claudeCodeMiddleware, promptCacheMiddleware]
992
- });
993
- }
994
- const oauthFetch = async (url, init) => {
995
- const authStorage2 = getAuthStorage();
996
- authStorage2.reload();
997
- const accessToken = await authStorage2.getApiKey("anthropic");
998
- if (!accessToken) {
999
- throw new Error("Not logged in to Anthropic. Run /login first.");
1000
- }
1001
- return fetch(url, {
1002
- ...init,
1003
- headers: {
1004
- Authorization: `Bearer ${accessToken}`,
1005
- "anthropic-beta": "oauth-2025-04-20,claude-code-20250219,interleaved-thinking-2025-05-14,fine-grained-tool-streaming-2025-05-14",
1006
- "anthropic-version": "2023-06-01"
1007
- }
1008
- });
1009
- };
1010
- const anthropic$1 = anthropic.createAnthropic({
1011
- // Provide a dummy API key - the actual auth is handled via OAuth in oauthFetch
1012
- // This prevents the SDK from throwing "API key is missing" at model creation time
1013
- apiKey: "oauth-placeholder",
1014
- fetch: oauthFetch
1015
- });
1016
- return ai.wrapLanguageModel({
1017
- model: anthropic$1(modelId),
1018
- middleware: [claudeCodeMiddleware, promptCacheMiddleware]
1019
- });
1020
- }
1021
- var CODEX_API_ENDPOINT = "https://chatgpt.com/backend-api/codex/responses";
1022
- var authStorageInstance2 = null;
1023
- function getAuthStorage2() {
1024
- if (!authStorageInstance2) {
1025
- authStorageInstance2 = new AuthStorage();
1026
- }
1027
- return authStorageInstance2;
1028
- }
1029
- function setAuthStorage2(storage) {
1030
- authStorageInstance2 = storage;
1031
- }
1032
- 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.
1033
-
1034
- IMPORTANT: You should be concise, direct, and helpful. Focus on solving the user's problem efficiently.`;
1035
- var openaiCodexMiddleware = {
1036
- specificationVersion: "v3",
1037
- transformParams: async ({ params }) => {
1038
- if (params.temperature) {
1039
- delete params.topP;
1040
- }
1041
- params.providerOptions = {
1042
- ...params.providerOptions,
1043
- openai: {
1044
- ...params.providerOptions?.openai ?? {},
1045
- // Codex API requires instructions
1046
- instructions: CODEX_INSTRUCTIONS,
1047
- // Codex API requires store to be false
1048
- store: false
1049
- }
1050
- };
1051
- return params;
1052
- }
1053
- };
1054
- function openaiCodexProvider(modelId = "codex-mini-latest") {
1055
- if (process.env.NODE_ENV === "test" || process.env.VITEST) {
1056
- const openai2 = openai.createOpenAI({
1057
- apiKey: process.env.OPENAI_API_KEY || "test-api-key"
1058
- });
1059
- return ai.wrapLanguageModel({
1060
- model: openai2.responses(modelId),
1061
- middleware: [openaiCodexMiddleware]
1062
- });
1063
- }
1064
- const oauthFetch = async (url, init) => {
1065
- const authStorage2 = getAuthStorage2();
1066
- authStorage2.reload();
1067
- const cred = authStorage2.get("openai-codex");
1068
- if (!cred || cred.type !== "oauth") {
1069
- throw new Error("Not logged in to OpenAI Codex. Run /login first.");
1070
- }
1071
- let accessToken = cred.access;
1072
- if (Date.now() >= cred.expires) {
1073
- const refreshedToken = await authStorage2.getApiKey("openai-codex");
1074
- if (!refreshedToken) {
1075
- throw new Error("Failed to refresh OpenAI Codex token. Please /login again.");
1076
- }
1077
- accessToken = refreshedToken;
1078
- authStorage2.reload();
1079
- }
1080
- const accountId = cred.accountId;
1081
- const headers = new Headers();
1082
- if (init?.headers) {
1083
- if (init.headers instanceof Headers) {
1084
- init.headers.forEach((value, key) => {
1085
- if (key.toLowerCase() !== "authorization") {
1086
- headers.set(key, value);
1087
- }
8
+ var util = require('util');
9
+ var tools = require('@mastra/core/tools');
10
+ var zod = require('zod');
11
+ var lite = require('js-tiktoken/lite');
12
+ var o200k_base = require('js-tiktoken/ranks/o200k_base');
13
+ var execa = require('execa');
14
+ var stripAnsi = require('strip-ansi');
15
+ var treeKill = require('tree-kill');
16
+ var node_js = require('vscode-jsonrpc/node.js');
17
+ var vscodeLanguageserverProtocol = require('vscode-languageserver-protocol');
18
+ var module$1 = require('module');
19
+ var url = require('url');
20
+ var fastestLevenshtein = require('fastest-levenshtein');
21
+ var anthropic = require('@ai-sdk/anthropic');
22
+ var ai = require('ai');
23
+ var openai = require('@ai-sdk/openai');
24
+ var llm = require('@mastra/core/llm');
25
+ var core = require('@tavily/core');
26
+ var napi = require('@ast-grep/napi');
27
+ var chalk = require('chalk');
28
+
29
+ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
30
+
31
+ function _interopNamespace(e) {
32
+ if (e && e.__esModule) return e;
33
+ var n = Object.create(null);
34
+ if (e) {
35
+ Object.keys(e).forEach(function (k) {
36
+ if (k !== 'default') {
37
+ var d = Object.getOwnPropertyDescriptor(e, k);
38
+ Object.defineProperty(n, k, d.get ? d : {
39
+ enumerable: true,
40
+ get: function () { return e[k]; }
1088
41
  });
1089
- } else if (Array.isArray(init.headers)) {
1090
- for (const [key, value] of init.headers) {
1091
- if (key.toLowerCase() !== "authorization" && value !== void 0) {
1092
- headers.set(key, String(value));
1093
- }
1094
- }
1095
- } else {
1096
- for (const [key, value] of Object.entries(init.headers)) {
1097
- if (key.toLowerCase() !== "authorization" && value !== void 0) {
1098
- headers.set(key, String(value));
1099
- }
1100
- }
1101
42
  }
1102
- }
1103
- headers.set("Authorization", `Bearer ${accessToken}`);
1104
- if (accountId) {
1105
- headers.set("ChatGPT-Account-Id", accountId);
1106
- }
1107
- const parsed = url instanceof URL ? url : new URL(typeof url === "string" ? url : url.url);
1108
- const shouldRewrite = parsed.pathname.includes("/v1/responses") || parsed.pathname.includes("/chat/completions");
1109
- const finalUrl = shouldRewrite ? new URL(CODEX_API_ENDPOINT) : parsed;
1110
- return fetch(finalUrl, {
1111
- ...init,
1112
- headers
1113
43
  });
1114
- };
1115
- const openai$1 = openai.createOpenAI({
1116
- // Use a dummy API key since we're using OAuth
1117
- apiKey: "oauth-dummy-key",
1118
- fetch: oauthFetch
1119
- });
1120
- return ai.wrapLanguageModel({
1121
- model: openai$1.responses(modelId),
1122
- middleware: [openaiCodexMiddleware]
1123
- });
1124
- }
1125
- var authStorage = new AuthStorage();
1126
- function resolveModel(modelId) {
1127
- authStorage.reload();
1128
- const isAnthropicModel = modelId.startsWith("anthropic/");
1129
- const isOpenAIModel = modelId.startsWith("openai/");
1130
- const isMoonshotModel = modelId.startsWith("moonshotai/");
1131
- if (isMoonshotModel) {
1132
- if (!process.env.MOONSHOT_AI_API_KEY) {
1133
- throw new Error(`Need MOONSHOT_AI_API_KEY`);
1134
- }
1135
- return anthropic.createAnthropic({
1136
- apiKey: process.env.MOONSHOT_AI_API_KEY,
1137
- baseURL: "https://api.moonshot.ai/anthropic/v1",
1138
- name: "moonshotai.anthropicv1"
1139
- })(modelId.substring("moonshotai/".length));
1140
- } else if (isAnthropicModel) {
1141
- return opencodeClaudeMaxProvider(modelId.substring(`anthropic/`.length));
1142
- } else if (isOpenAIModel && authStorage.isLoggedIn("openai-codex")) {
1143
- return openaiCodexProvider(modelId.substring(`openai/`.length));
1144
- } else {
1145
- return new llm.ModelRouterLanguageModel(modelId);
1146
- }
1147
- }
1148
- function getDynamicModel({
1149
- requestContext
1150
- }) {
1151
- const harnessContext = requestContext.get("harness");
1152
- const modelId = harnessContext?.state?.currentModelId;
1153
- if (!modelId) {
1154
- throw new Error("No model selected. Use /models to select a model first.");
1155
44
  }
1156
- return resolveModel(modelId);
45
+ n.default = e;
46
+ return Object.freeze(n);
1157
47
  }
1158
48
 
1159
- // src/agents/subagents/execute.ts
1160
- var executeSubagent = {
1161
- id: "execute",
1162
- name: "Execute",
1163
- instructions: `You are a focused execution agent. Your job is to complete a specific, well-defined task by making the necessary changes to the codebase.
1164
-
1165
- ## Rules
1166
- - You have FULL ACCESS to read, write, and execute within your task scope.
1167
- - Stay focused on the specific task given. Do not make unrelated changes.
1168
- - Read files before modifying them \u2014 use view first, then string_replace_lsp or write_file.
1169
- - Verify your changes work by running relevant tests or checking for errors.
1170
-
1171
- ## Tool Strategy
1172
- - **Read first**: Always view a file before editing it
1173
- - **Edit precisely**: Use string_replace_lsp with enough context to match uniquely
1174
- - **Use specialized tools**: Prefer view/search_content/find_files over shell commands for reading
1175
- - **Parallelize**: Make independent tool calls together (e.g., view multiple files at once)
1176
-
1177
- ## Workflow
1178
- . Understand the task and explore relevant code
1179
- . For complex tasks (3+ steps): use task_write to track progress
1180
- . Make changes incrementally \u2014 verify each change before moving on
1181
- . Run tests or type-check to verify
1182
- . If you created tasks: ALWAYS call task_check before finishing
1183
-
1184
- ## Efficiency
1185
- Your output returns to the parent agent. Be concise:
1186
- - Don't repeat file contents in your response
1187
- - Summarize what changed, don't narrate each step
1188
- - Keep your final summary under 300 words
1189
-
1190
- ## Output Format
1191
- End with a structured summary:
1192
- . **Completed**: What you implemented (1-2 sentences)
1193
- . **Changes**: Files modified/created
1194
- . **Verification**: How you verified it works
1195
- . **Notes**: Follow-up needed (if any)`,
1196
- allowedTools: [
1197
- // Read tools
1198
- "view",
1199
- "search_content",
1200
- "find_files",
1201
- // Write tools
1202
- "string_replace_lsp",
1203
- "write_file",
1204
- // Execution tool
1205
- "execute_command",
1206
- // Task tracking (built-in harness tools)
1207
- "task_write",
1208
- "task_check"
1209
- ]
1210
- };
1211
-
1212
- // src/agents/subagents/explore.ts
1213
- var exploreSubagent = {
1214
- id: "explore",
1215
- name: "Explore",
1216
- instructions: `You are an expert code explorer. Your job is to investigate a codebase and answer a specific question or gather specific information.
1217
-
1218
- ## Rules
1219
- - You have READ-ONLY access. You cannot modify files or run commands.
1220
- - Be thorough \u2014 search broadly first, then drill into relevant files.
1221
- - After gathering enough information, produce a clear, concise summary of your findings.
1222
-
1223
- ## Tool Strategy
1224
- - **Start broad**: Use find_files (glob) to understand project structure
1225
- - **Search smart**: Use search_content (grep) with specific patterns \u2014 avoid overly broad searches
1226
- - **Read efficiently**: Use view with view_range for large files \u2014 don't read entire files if you only need a section
1227
- - **Parallelize**: Make multiple independent tool calls in one round when exploring different areas
1228
-
1229
- ## Efficiency
1230
- Your output returns to the parent agent. Be concise:
1231
- - Don't include raw file contents in your response \u2014 summarize what you found
1232
- - Reference files by path and line number, not by copying code
1233
- - If a search returns many results, report the count and key examples, not every match
1234
-
1235
- ## Output Format
1236
- End with a structured summary:
1237
- . **Answer**: Direct answer to the question (1-2 sentences)
1238
- . **Key Files**: Most relevant files with line numbers
1239
- . **Details**: Additional context if needed
1240
-
1241
- Keep your summary under 300 words.`,
1242
- allowedTools: ["view", "search_content", "find_files"]
1243
- };
1244
-
1245
- // src/agents/subagents/plan.ts
1246
- var planSubagent = {
1247
- id: "plan",
1248
- name: "Plan",
1249
- instructions: `You are an expert software architect and planner. Your job is to analyze a codebase and produce a detailed implementation plan for a given task.
1250
-
1251
- ## Rules
1252
- - You have READ-ONLY access. You cannot modify files or run commands.
1253
- - First, explore the codebase to understand existing patterns, architecture, and conventions.
1254
- - Produce a concrete, actionable plan \u2014 not vague suggestions.
1255
-
1256
- ## Tool Strategy
1257
- - **Discover structure**: Use find_files (glob) to understand project layout and find relevant files
1258
- - **Find patterns**: Use search_content (grep) to locate existing implementations, imports, and conventions
1259
- - **Understand deeply**: Use view with view_range to read specific sections of key files
1260
- - **Parallelize**: Make multiple independent tool calls when exploring different areas
1261
-
1262
- ## Efficiency
1263
- Your output returns to the parent agent. Be concise:
1264
- - Don't include raw file contents \u2014 reference by path and line number
1265
- - Focus on actionable details, not general observations
1266
- - If you find many similar patterns, describe the pattern once with examples
1267
-
1268
- ## Output Format
1269
- Structure your plan as:
1270
-
1271
- . **Summary**: One-paragraph overview (2-3 sentences)
1272
- . **Files to Change**: List each file with specific changes needed
1273
- . **Implementation Order**: Numbered steps in dependency order
1274
- . **Risks**: Potential issues or edge cases (if any)
49
+ var fs8__namespace = /*#__PURE__*/_interopNamespace(fs8);
50
+ var path__namespace = /*#__PURE__*/_interopNamespace(path);
51
+ var o200k_base__default = /*#__PURE__*/_interopDefault(o200k_base);
52
+ var stripAnsi__default = /*#__PURE__*/_interopDefault(stripAnsi);
53
+ var treeKill__default = /*#__PURE__*/_interopDefault(treeKill);
54
+ var chalk__default = /*#__PURE__*/_interopDefault(chalk);
1275
55
 
1276
- Be specific about code locations (file paths, function names, line numbers). Keep the plan actionable and under 500 words.`,
1277
- allowedTools: ["view", "search_content", "find_files"]
1278
- };
1279
56
  var enc = new lite.Tiktoken(o200k_base__default.default);
1280
57
  function sanitizeInput(text) {
1281
58
  if (!text) return "";
@@ -1327,7 +104,7 @@ async function withWriteLock(filePath, fn) {
1327
104
  var SNIPPET_LINES = 4;
1328
105
  async function readFile(filePath) {
1329
106
  try {
1330
- return await fs9.promises.readFile(filePath, "utf8");
107
+ return await fs8.promises.readFile(filePath, "utf8");
1331
108
  } catch (e) {
1332
109
  const error = e instanceof Error ? e : new Error("Unknown error");
1333
110
  throw new Error(`Failed to read ${filePath}: ${error.message}`);
@@ -1335,8 +112,8 @@ async function readFile(filePath) {
1335
112
  }
1336
113
  async function writeFile(filePath, content) {
1337
114
  try {
1338
- await fs9.promises.mkdir(path__namespace.dirname(filePath), { recursive: true });
1339
- await fs9.promises.writeFile(filePath, content, "utf8");
115
+ await fs8.promises.mkdir(path__namespace.dirname(filePath), { recursive: true });
116
+ await fs8.promises.writeFile(filePath, content, "utf8");
1340
117
  } catch (e) {
1341
118
  const error = e instanceof Error ? e : new Error("Unknown error");
1342
119
  throw new Error(`Failed to write to ${filePath}: ${error.message}`);
@@ -1359,7 +136,7 @@ async function validatePath(command, filePath) {
1359
136
  filePath = absolutePath;
1360
137
  }
1361
138
  try {
1362
- const stats = await fs9.promises.stat(filePath);
139
+ const stats = await fs8.promises.stat(filePath);
1363
140
  if (stats.isDirectory() && command !== "view") {
1364
141
  throw new ToolError(
1365
142
  `The path ${filePath} is a directory and only the \`view\` command can be used on directories`
@@ -1429,7 +206,7 @@ ${numberedLines}
1429
206
  }
1430
207
  async function readFile2(filePath) {
1431
208
  try {
1432
- return await fs9.promises.readFile(filePath, "utf8");
209
+ return await fs8.promises.readFile(filePath, "utf8");
1433
210
  } catch (e) {
1434
211
  const error = e instanceof Error ? e : new Error("Unknown error");
1435
212
  throw new Error(`Failed to read ${filePath}: ${error.message}`);
@@ -1437,7 +214,7 @@ async function readFile2(filePath) {
1437
214
  }
1438
215
  async function isDirectory(filePath) {
1439
216
  try {
1440
- const stats = await fs9.promises.stat(filePath);
217
+ const stats = await fs8.promises.stat(filePath);
1441
218
  return stats.isDirectory();
1442
219
  } catch {
1443
220
  return false;
@@ -1449,7 +226,7 @@ async function validatePath2(command, filePath) {
1449
226
  filePath = absolutePath;
1450
227
  }
1451
228
  try {
1452
- const stats = await fs9.promises.stat(filePath);
229
+ const stats = await fs8.promises.stat(filePath);
1453
230
  if (stats.isDirectory() && command !== "view") ;
1454
231
  } catch (e) {
1455
232
  const error = e instanceof Error ? e : new Error("Unknown error");
@@ -1484,7 +261,7 @@ Usage notes:
1484
261
  assertPathAllowed(absolutePath, root, allowedPaths);
1485
262
  await validatePath2("view", absolutePath);
1486
263
  if (await isDirectory(absolutePath)) {
1487
- const { stdout, stderr } = await execAsync(`find "${absolutePath}" -maxdepth 2 -not -path '*/\\\\.*'`);
264
+ const { stdout, stderr } = await execAsync(`find "${absolutePath}" -maxdepth 2 -not -path '*/.*'`);
1488
265
  if (stderr) {
1489
266
  throw new Error(stderr);
1490
267
  }
@@ -1992,7 +769,52 @@ ${truncateStringForTokenEstimate(cleanOutput, 1e3)}` : "[User aborted command]"
1992
769
  }
1993
770
  });
1994
771
  }
1995
- createExecuteCommandTool();
772
+ createExecuteCommandTool();
773
+
774
+ // src/lsp/language.ts
775
+ var LANGUAGE_EXTENSIONS = {
776
+ // TypeScript/JavaScript
777
+ ".ts": "typescript",
778
+ ".tsx": "typescriptreact",
779
+ ".js": "javascript",
780
+ ".jsx": "javascriptreact",
781
+ ".mjs": "javascript",
782
+ ".cjs": "javascript",
783
+ // Python
784
+ ".py": "python",
785
+ ".pyi": "python",
786
+ // Go
787
+ ".go": "go",
788
+ // Rust
789
+ ".rs": "rust",
790
+ // C/C++
791
+ ".c": "c",
792
+ ".cpp": "cpp",
793
+ ".cc": "cpp",
794
+ ".cxx": "cpp",
795
+ ".h": "c",
796
+ ".hpp": "cpp",
797
+ // Java
798
+ ".java": "java",
799
+ // JSON
800
+ ".json": "json",
801
+ ".jsonc": "jsonc",
802
+ // YAML
803
+ ".yaml": "yaml",
804
+ ".yml": "yaml",
805
+ // Markdown
806
+ ".md": "markdown",
807
+ // HTML/CSS
808
+ ".html": "html",
809
+ ".css": "css",
810
+ ".scss": "scss",
811
+ ".sass": "sass",
812
+ ".less": "less"
813
+ };
814
+ function getLanguageId(filePath) {
815
+ const ext = filePath.substring(filePath.lastIndexOf("."));
816
+ return LANGUAGE_EXTENSIONS[ext];
817
+ }
1996
818
  var LSPClient = class {
1997
819
  connection = null;
1998
820
  process = null;
@@ -2291,58 +1113,11 @@ var LSPClient = class {
2291
1113
  this.diagnostics = /* @__PURE__ */ new Map();
2292
1114
  }
2293
1115
  };
2294
-
2295
- // src/lsp/language.ts
2296
- var LANGUAGE_EXTENSIONS = {
2297
- // TypeScript/JavaScript
2298
- ".ts": "typescript",
2299
- ".tsx": "typescriptreact",
2300
- ".js": "javascript",
2301
- ".jsx": "javascriptreact",
2302
- ".mjs": "javascript",
2303
- ".cjs": "javascript",
2304
- // Python
2305
- ".py": "python",
2306
- ".pyi": "python",
2307
- // Go
2308
- ".go": "go",
2309
- // Rust
2310
- ".rs": "rust",
2311
- // C/C++
2312
- ".c": "c",
2313
- ".cpp": "cpp",
2314
- ".cc": "cpp",
2315
- ".cxx": "cpp",
2316
- ".h": "c",
2317
- ".hpp": "cpp",
2318
- // Java
2319
- ".java": "java",
2320
- // JSON
2321
- ".json": "json",
2322
- ".jsonc": "jsonc",
2323
- // YAML
2324
- ".yaml": "yaml",
2325
- ".yml": "yaml",
2326
- // Markdown
2327
- ".md": "markdown",
2328
- // HTML/CSS
2329
- ".html": "html",
2330
- ".css": "css",
2331
- ".scss": "scss",
2332
- ".sass": "sass",
2333
- ".less": "less"
2334
- };
2335
- function getLanguageId(filePath) {
2336
- const ext = filePath.substring(filePath.lastIndexOf("."));
2337
- return LANGUAGE_EXTENSIONS[ext];
2338
- }
2339
-
2340
- // src/lsp/server.ts
2341
1116
  function findNearestRoot(cwd, markers) {
2342
1117
  let current = cwd;
2343
1118
  while (current !== "/") {
2344
1119
  for (const marker of markers) {
2345
- if (fs9.existsSync(path.join(current, marker))) {
1120
+ if (fs8.existsSync(path.join(current, marker))) {
2346
1121
  return current;
2347
1122
  }
2348
1123
  }
@@ -2372,9 +1147,9 @@ var BUILTIN_SERVERS = {
2372
1147
  const localBin = path.join(root, "node_modules", ".bin", "typescript-language-server");
2373
1148
  const cwdBin = path.join(process.cwd(), "node_modules", ".bin", "typescript-language-server");
2374
1149
  let tslsBinary;
2375
- if (fs9.existsSync(localBin)) {
1150
+ if (fs8.existsSync(localBin)) {
2376
1151
  tslsBinary = localBin;
2377
- } else if (fs9.existsSync(cwdBin)) {
1152
+ } else if (fs8.existsSync(cwdBin)) {
2378
1153
  tslsBinary = cwdBin;
2379
1154
  } else {
2380
1155
  tslsBinary = "npx";
@@ -2415,7 +1190,7 @@ var BUILTIN_SERVERS = {
2415
1190
  root: (cwd) => findNearestRoot(cwd, ["pyproject.toml", "setup.py", "requirements.txt", ".git"]),
2416
1191
  spawn: (root) => {
2417
1192
  const localPath = path.join(process.cwd(), "node_modules", ".bin", "pyright-langserver");
2418
- const binaryPath = fs9.existsSync(localPath) ? localPath : "pyright-langserver";
1193
+ const binaryPath = fs8.existsSync(localPath) ? localPath : "pyright-langserver";
2419
1194
  return child_process.spawn(binaryPath, ["--stdio"], {
2420
1195
  cwd: root,
2421
1196
  stdio: ["pipe", "pipe", "pipe"]
@@ -2562,8 +1337,8 @@ function findWorkspaceRoot(filePath) {
2562
1337
  let closestProjectRoot = null;
2563
1338
  let searchDir = currentDir;
2564
1339
  while (searchDir !== root) {
2565
- const hasTsConfig = fs9__namespace.existsSync(path__namespace.join(searchDir, "tsconfig.json"));
2566
- const hasPackageJson = fs9__namespace.existsSync(path__namespace.join(searchDir, "package.json"));
1340
+ const hasTsConfig = fs8__namespace.existsSync(path__namespace.join(searchDir, "tsconfig.json"));
1341
+ const hasPackageJson = fs8__namespace.existsSync(path__namespace.join(searchDir, "package.json"));
2567
1342
  if (hasTsConfig || hasPackageJson) {
2568
1343
  closestProjectRoot = searchDir;
2569
1344
  break;
@@ -2581,7 +1356,7 @@ function findWorkspaceRoot(filePath) {
2581
1356
  while (currentDir !== root) {
2582
1357
  for (const marker of WORKSPACE_MARKERS) {
2583
1358
  const markerPath = path__namespace.join(currentDir, marker);
2584
- if (fs9__namespace.existsSync(markerPath)) {
1359
+ if (fs8__namespace.existsSync(markerPath)) {
2585
1360
  return currentDir;
2586
1361
  }
2587
1362
  }
@@ -2609,7 +1384,7 @@ var FileEditor = class {
2609
1384
  async view(args) {
2610
1385
  await validatePath("view", args.path);
2611
1386
  if (await this.isDirectory(args.path)) {
2612
- const { stdout, stderr } = await this.execAsync(`find "${args.path}" -maxdepth 2 -not -path '*/\\\\.*'`);
1387
+ const { stdout, stderr } = await this.execAsync(`find "${args.path}" -maxdepth 2 -not -path '*/.*'`);
2613
1388
  if (stderr) return stderr;
2614
1389
  return `Here's the files and directories up to 2 levels deep in ${args.path}, excluding hidden items:
2615
1390
  ${stdout}
@@ -2921,7 +1696,7 @@ ${divergedMessage ? divergedMessage : ``}Try adjusting your input or the file co
2921
1696
  }
2922
1697
  async isDirectory(filePath) {
2923
1698
  try {
2924
- const stats = await fs9.promises.stat(filePath);
1699
+ const stats = await fs8.promises.stat(filePath);
2925
1700
  return stats.isDirectory();
2926
1701
  } catch {
2927
1702
  return false;
@@ -2968,8 +1743,8 @@ Usage notes:
2968
1743
  const workspaceRoot = findWorkspaceRoot(absoluteFilePath);
2969
1744
  const client = await lspManager.getClient(absoluteFilePath, workspaceRoot);
2970
1745
  if (client) {
2971
- const contentNew = fs9__namespace.readFileSync(absoluteFilePath, "utf-8");
2972
- const languageId = path__namespace.extname(absoluteFilePath).slice(1);
1746
+ const contentNew = fs8__namespace.readFileSync(absoluteFilePath, "utf-8");
1747
+ const languageId = getLanguageId(absoluteFilePath) || path__namespace.extname(absoluteFilePath).slice(1);
2973
1748
  client.notifyOpen(absoluteFilePath, contentNew, languageId);
2974
1749
  client.notifyChange(absoluteFilePath, contentNew, 1);
2975
1750
  const diagnostics = await client.waitForDiagnostics(absoluteFilePath, 3e3).catch(() => []);
@@ -3278,7 +2053,7 @@ function escapeRegex(s) {
3278
2053
  }
3279
2054
  async function getModTime(filePath) {
3280
2055
  try {
3281
- const stat = await fs9__namespace.promises.stat(filePath);
2056
+ const stat = await fs8__namespace.promises.stat(filePath);
3282
2057
  return stat.mtimeMs;
3283
2058
  } catch {
3284
2059
  return 0;
@@ -3366,12 +2141,12 @@ Usage notes:
3366
2141
  const absolutePath = path__namespace.resolve(root, filePath);
3367
2142
  const allowedPaths = getAllowedPathsFromContext(toolContext);
3368
2143
  assertPathAllowed(absolutePath, root, allowedPaths);
3369
- const exists = fs9__namespace.existsSync(absolutePath);
2144
+ const exists = fs8__namespace.existsSync(absolutePath);
3370
2145
  const dir = path__namespace.dirname(absolutePath);
3371
- if (!fs9__namespace.existsSync(dir)) {
3372
- fs9__namespace.mkdirSync(dir, { recursive: true });
2146
+ if (!fs8__namespace.existsSync(dir)) {
2147
+ fs8__namespace.mkdirSync(dir, { recursive: true });
3373
2148
  }
3374
- fs9__namespace.writeFileSync(absolutePath, context.content, "utf-8");
2149
+ fs8__namespace.writeFileSync(absolutePath, context.content, "utf-8");
3375
2150
  const lineCount = context.content.split("\n").length;
3376
2151
  const relPath = path__namespace.relative(root, absolutePath);
3377
2152
  if (exists) {
@@ -3385,16 +2160,384 @@ Usage notes:
3385
2160
  isError: false
3386
2161
  };
3387
2162
  }
3388
- } catch (error) {
3389
- const msg = error instanceof Error ? error.message : "Unknown error";
3390
- return {
3391
- content: `write_file failed: ${msg}`,
3392
- isError: true
3393
- };
2163
+ } catch (error) {
2164
+ const msg = error instanceof Error ? error.message : "Unknown error";
2165
+ return {
2166
+ content: `write_file failed: ${msg}`,
2167
+ isError: true
2168
+ };
2169
+ }
2170
+ }
2171
+ });
2172
+ }
2173
+ var claudeCodeIdentity = "You are Claude Code, Anthropic's official CLI for Claude.";
2174
+ var authStorageInstance = null;
2175
+ function getAuthStorage() {
2176
+ if (!authStorageInstance) {
2177
+ authStorageInstance = new chunkC6XKRHRK_cjs.AuthStorage();
2178
+ }
2179
+ return authStorageInstance;
2180
+ }
2181
+ function setAuthStorage(storage) {
2182
+ authStorageInstance = storage;
2183
+ }
2184
+ var claudeCodeMiddleware = {
2185
+ specificationVersion: "v3",
2186
+ transformParams: async ({ params }) => {
2187
+ const systemMessage = {
2188
+ role: "system",
2189
+ content: claudeCodeIdentity
2190
+ };
2191
+ if (params.temperature) {
2192
+ delete params.topP;
2193
+ }
2194
+ return {
2195
+ ...params,
2196
+ prompt: [systemMessage, ...params.prompt]
2197
+ };
2198
+ }
2199
+ };
2200
+ var promptCacheMiddleware = {
2201
+ specificationVersion: "v3",
2202
+ transformParams: async ({ params }) => {
2203
+ const prompt = [...params.prompt];
2204
+ const cacheControl = { type: "ephemeral", ttl: "5m" };
2205
+ const addCacheToMessage = (msg) => {
2206
+ if (typeof msg.content === "string") {
2207
+ return {
2208
+ ...msg,
2209
+ providerOptions: {
2210
+ ...msg.providerOptions,
2211
+ anthropic: { ...msg.providerOptions?.anthropic, cacheControl }
2212
+ }
2213
+ };
2214
+ }
2215
+ if (Array.isArray(msg.content) && msg.content.length > 0) {
2216
+ const content = [...msg.content];
2217
+ const lastPart = content[content.length - 1];
2218
+ content[content.length - 1] = {
2219
+ ...lastPart,
2220
+ providerOptions: {
2221
+ ...lastPart.providerOptions,
2222
+ anthropic: { ...lastPart.providerOptions?.anthropic, cacheControl }
2223
+ }
2224
+ };
2225
+ return { ...msg, content };
2226
+ }
2227
+ return msg;
2228
+ };
2229
+ let lastSystemIdx = -1;
2230
+ for (let i = prompt.length - 1; i >= 0; i--) {
2231
+ if (prompt[i].role === "system") {
2232
+ lastSystemIdx = i;
2233
+ break;
2234
+ }
2235
+ }
2236
+ if (lastSystemIdx >= 0) {
2237
+ prompt[lastSystemIdx] = addCacheToMessage(prompt[lastSystemIdx]);
2238
+ }
2239
+ const lastIdx = prompt.length - 1;
2240
+ if (lastIdx >= 0 && lastIdx !== lastSystemIdx) {
2241
+ prompt[lastIdx] = addCacheToMessage(prompt[lastIdx]);
2242
+ }
2243
+ return { ...params, prompt };
2244
+ }
2245
+ };
2246
+ function opencodeClaudeMaxProvider(modelId = "claude-sonnet-4-20250514") {
2247
+ if (process.env.NODE_ENV === "test" || process.env.VITEST) {
2248
+ const anthropic2 = anthropic.createAnthropic({
2249
+ apiKey: process.env.ANTHROPIC_API_KEY || "test-api-key"
2250
+ });
2251
+ return ai.wrapLanguageModel({
2252
+ model: anthropic2(modelId),
2253
+ middleware: [claudeCodeMiddleware, promptCacheMiddleware]
2254
+ });
2255
+ }
2256
+ const oauthFetch = async (url, init) => {
2257
+ const authStorage2 = getAuthStorage();
2258
+ authStorage2.reload();
2259
+ const accessToken = await authStorage2.getApiKey("anthropic");
2260
+ if (!accessToken) {
2261
+ throw new Error("Not logged in to Anthropic. Run /login first.");
2262
+ }
2263
+ return fetch(url, {
2264
+ ...init,
2265
+ headers: {
2266
+ Authorization: `Bearer ${accessToken}`,
2267
+ "anthropic-beta": "oauth-2025-04-20,claude-code-20250219,interleaved-thinking-2025-05-14,fine-grained-tool-streaming-2025-05-14",
2268
+ "anthropic-version": "2023-06-01"
2269
+ }
2270
+ });
2271
+ };
2272
+ const anthropic$1 = anthropic.createAnthropic({
2273
+ // Provide a dummy API key - the actual auth is handled via OAuth in oauthFetch
2274
+ // This prevents the SDK from throwing "API key is missing" at model creation time
2275
+ apiKey: "oauth-placeholder",
2276
+ fetch: oauthFetch
2277
+ });
2278
+ return ai.wrapLanguageModel({
2279
+ model: anthropic$1(modelId),
2280
+ middleware: [claudeCodeMiddleware, promptCacheMiddleware]
2281
+ });
2282
+ }
2283
+ var CODEX_API_ENDPOINT = "https://chatgpt.com/backend-api/codex/responses";
2284
+ var authStorageInstance2 = null;
2285
+ function getAuthStorage2() {
2286
+ if (!authStorageInstance2) {
2287
+ authStorageInstance2 = new chunkC6XKRHRK_cjs.AuthStorage();
2288
+ }
2289
+ return authStorageInstance2;
2290
+ }
2291
+ function setAuthStorage2(storage) {
2292
+ authStorageInstance2 = storage;
2293
+ }
2294
+ 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.
2295
+
2296
+ IMPORTANT: You should be concise, direct, and helpful. Focus on solving the user's problem efficiently.`;
2297
+ var openaiCodexMiddleware = {
2298
+ specificationVersion: "v3",
2299
+ transformParams: async ({ params }) => {
2300
+ if (params.temperature) {
2301
+ delete params.topP;
2302
+ }
2303
+ params.providerOptions = {
2304
+ ...params.providerOptions,
2305
+ openai: {
2306
+ ...params.providerOptions?.openai ?? {},
2307
+ // Codex API requires instructions
2308
+ instructions: CODEX_INSTRUCTIONS,
2309
+ // Codex API requires store to be false
2310
+ store: false
2311
+ }
2312
+ };
2313
+ return params;
2314
+ }
2315
+ };
2316
+ function openaiCodexProvider(modelId = "codex-mini-latest") {
2317
+ if (process.env.NODE_ENV === "test" || process.env.VITEST) {
2318
+ const openai2 = openai.createOpenAI({
2319
+ apiKey: process.env.OPENAI_API_KEY || "test-api-key"
2320
+ });
2321
+ return ai.wrapLanguageModel({
2322
+ model: openai2.responses(modelId),
2323
+ middleware: [openaiCodexMiddleware]
2324
+ });
2325
+ }
2326
+ const oauthFetch = async (url, init) => {
2327
+ const authStorage2 = getAuthStorage2();
2328
+ authStorage2.reload();
2329
+ const cred = authStorage2.get("openai-codex");
2330
+ if (!cred || cred.type !== "oauth") {
2331
+ throw new Error("Not logged in to OpenAI Codex. Run /login first.");
2332
+ }
2333
+ let accessToken = cred.access;
2334
+ if (Date.now() >= cred.expires) {
2335
+ const refreshedToken = await authStorage2.getApiKey("openai-codex");
2336
+ if (!refreshedToken) {
2337
+ throw new Error("Failed to refresh OpenAI Codex token. Please /login again.");
2338
+ }
2339
+ accessToken = refreshedToken;
2340
+ authStorage2.reload();
2341
+ }
2342
+ const accountId = cred.accountId;
2343
+ const headers = new Headers();
2344
+ if (init?.headers) {
2345
+ if (init.headers instanceof Headers) {
2346
+ init.headers.forEach((value, key) => {
2347
+ if (key.toLowerCase() !== "authorization") {
2348
+ headers.set(key, value);
2349
+ }
2350
+ });
2351
+ } else if (Array.isArray(init.headers)) {
2352
+ for (const [key, value] of init.headers) {
2353
+ if (key.toLowerCase() !== "authorization" && value !== void 0) {
2354
+ headers.set(key, String(value));
2355
+ }
2356
+ }
2357
+ } else {
2358
+ for (const [key, value] of Object.entries(init.headers)) {
2359
+ if (key.toLowerCase() !== "authorization" && value !== void 0) {
2360
+ headers.set(key, String(value));
2361
+ }
2362
+ }
3394
2363
  }
3395
2364
  }
2365
+ headers.set("Authorization", `Bearer ${accessToken}`);
2366
+ if (accountId) {
2367
+ headers.set("ChatGPT-Account-Id", accountId);
2368
+ }
2369
+ const parsed = url instanceof URL ? url : new URL(typeof url === "string" ? url : url.url);
2370
+ const shouldRewrite = parsed.pathname.includes("/v1/responses") || parsed.pathname.includes("/chat/completions");
2371
+ const finalUrl = shouldRewrite ? new URL(CODEX_API_ENDPOINT) : parsed;
2372
+ return fetch(finalUrl, {
2373
+ ...init,
2374
+ headers
2375
+ });
2376
+ };
2377
+ const openai$1 = openai.createOpenAI({
2378
+ // Use a dummy API key since we're using OAuth
2379
+ apiKey: "oauth-dummy-key",
2380
+ fetch: oauthFetch
2381
+ });
2382
+ return ai.wrapLanguageModel({
2383
+ model: openai$1.responses(modelId),
2384
+ middleware: [openaiCodexMiddleware]
3396
2385
  });
3397
2386
  }
2387
+ var authStorage = new chunkC6XKRHRK_cjs.AuthStorage();
2388
+ function resolveModel(modelId) {
2389
+ authStorage.reload();
2390
+ const isAnthropicModel = modelId.startsWith("anthropic/");
2391
+ const isOpenAIModel = modelId.startsWith("openai/");
2392
+ const isMoonshotModel = modelId.startsWith("moonshotai/");
2393
+ if (isMoonshotModel) {
2394
+ if (!process.env.MOONSHOT_AI_API_KEY) {
2395
+ throw new Error(`Need MOONSHOT_AI_API_KEY`);
2396
+ }
2397
+ return anthropic.createAnthropic({
2398
+ apiKey: process.env.MOONSHOT_AI_API_KEY,
2399
+ baseURL: "https://api.moonshot.ai/anthropic/v1",
2400
+ name: "moonshotai.anthropicv1"
2401
+ })(modelId.substring("moonshotai/".length));
2402
+ } else if (isAnthropicModel) {
2403
+ return opencodeClaudeMaxProvider(modelId.substring(`anthropic/`.length));
2404
+ } else if (isOpenAIModel && authStorage.isLoggedIn("openai-codex")) {
2405
+ return openaiCodexProvider(modelId.substring(`openai/`.length));
2406
+ } else {
2407
+ return new llm.ModelRouterLanguageModel(modelId);
2408
+ }
2409
+ }
2410
+ function getDynamicModel({
2411
+ requestContext
2412
+ }) {
2413
+ const harnessContext = requestContext.get("harness");
2414
+ const modelId = harnessContext?.state?.currentModelId;
2415
+ if (!modelId) {
2416
+ throw new Error("No model selected. Use /models to select a model first.");
2417
+ }
2418
+ return resolveModel(modelId);
2419
+ }
2420
+
2421
+ // src/agents/subagents/execute.ts
2422
+ var executeSubagent = {
2423
+ id: "execute",
2424
+ name: "Execute",
2425
+ instructions: `You are a focused execution agent. Your job is to complete a specific, well-defined task by making the necessary changes to the codebase.
2426
+
2427
+ ## Rules
2428
+ - You have FULL ACCESS to read, write, and execute within your task scope.
2429
+ - Stay focused on the specific task given. Do not make unrelated changes.
2430
+ - Read files before modifying them \u2014 use view first, then string_replace_lsp or write_file.
2431
+ - Verify your changes work by running relevant tests or checking for errors.
2432
+
2433
+ ## Tool Strategy
2434
+ - **Read first**: Always view a file before editing it
2435
+ - **Edit precisely**: Use string_replace_lsp with enough context to match uniquely
2436
+ - **Use specialized tools**: Prefer view/search_content/find_files over shell commands for reading
2437
+ - **Parallelize**: Make independent tool calls together (e.g., view multiple files at once)
2438
+
2439
+ ## Workflow
2440
+ . Understand the task and explore relevant code
2441
+ . For complex tasks (3+ steps): use task_write to track progress
2442
+ . Make changes incrementally \u2014 verify each change before moving on
2443
+ . Run tests or type-check to verify
2444
+ . If you created tasks: ALWAYS call task_check before finishing
2445
+
2446
+ ## Efficiency
2447
+ Your output returns to the parent agent. Be concise:
2448
+ - Don't repeat file contents in your response
2449
+ - Summarize what changed, don't narrate each step
2450
+ - Keep your final summary under 300 words
2451
+
2452
+ ## Output Format
2453
+ End with a structured summary:
2454
+ . **Completed**: What you implemented (1-2 sentences)
2455
+ . **Changes**: Files modified/created
2456
+ . **Verification**: How you verified it works
2457
+ . **Notes**: Follow-up needed (if any)`,
2458
+ allowedTools: [
2459
+ // Read tools
2460
+ "view",
2461
+ "search_content",
2462
+ "find_files",
2463
+ // Write tools
2464
+ "string_replace_lsp",
2465
+ "write_file",
2466
+ // Execution tool
2467
+ "execute_command",
2468
+ // Task tracking (built-in harness tools)
2469
+ "task_write",
2470
+ "task_check"
2471
+ ]
2472
+ };
2473
+
2474
+ // src/agents/subagents/explore.ts
2475
+ var exploreSubagent = {
2476
+ id: "explore",
2477
+ name: "Explore",
2478
+ instructions: `You are an expert code explorer. Your job is to investigate a codebase and answer a specific question or gather specific information.
2479
+
2480
+ ## Rules
2481
+ - You have READ-ONLY access. You cannot modify files or run commands.
2482
+ - Be thorough \u2014 search broadly first, then drill into relevant files.
2483
+ - After gathering enough information, produce a clear, concise summary of your findings.
2484
+
2485
+ ## Tool Strategy
2486
+ - **Start broad**: Use find_files (glob) to understand project structure
2487
+ - **Search smart**: Use search_content (grep) with specific patterns \u2014 avoid overly broad searches
2488
+ - **Read efficiently**: Use view with view_range for large files \u2014 don't read entire files if you only need a section
2489
+ - **Parallelize**: Make multiple independent tool calls in one round when exploring different areas
2490
+
2491
+ ## Efficiency
2492
+ Your output returns to the parent agent. Be concise:
2493
+ - Don't include raw file contents in your response \u2014 summarize what you found
2494
+ - Reference files by path and line number, not by copying code
2495
+ - If a search returns many results, report the count and key examples, not every match
2496
+
2497
+ ## Output Format
2498
+ End with a structured summary:
2499
+ . **Answer**: Direct answer to the question (1-2 sentences)
2500
+ . **Key Files**: Most relevant files with line numbers
2501
+ . **Details**: Additional context if needed
2502
+
2503
+ Keep your summary under 300 words.`,
2504
+ allowedTools: ["view", "search_content", "find_files"]
2505
+ };
2506
+
2507
+ // src/agents/subagents/plan.ts
2508
+ var planSubagent = {
2509
+ id: "plan",
2510
+ name: "Plan",
2511
+ instructions: `You are an expert software architect and planner. Your job is to analyze a codebase and produce a detailed implementation plan for a given task.
2512
+
2513
+ ## Rules
2514
+ - You have READ-ONLY access. You cannot modify files or run commands.
2515
+ - First, explore the codebase to understand existing patterns, architecture, and conventions.
2516
+ - Produce a concrete, actionable plan \u2014 not vague suggestions.
2517
+
2518
+ ## Tool Strategy
2519
+ - **Discover structure**: Use find_files (glob) to understand project layout and find relevant files
2520
+ - **Find patterns**: Use search_content (grep) to locate existing implementations, imports, and conventions
2521
+ - **Understand deeply**: Use view with view_range to read specific sections of key files
2522
+ - **Parallelize**: Make multiple independent tool calls when exploring different areas
2523
+
2524
+ ## Efficiency
2525
+ Your output returns to the parent agent. Be concise:
2526
+ - Don't include raw file contents \u2014 reference by path and line number
2527
+ - Focus on actionable details, not general observations
2528
+ - If you find many similar patterns, describe the pattern once with examples
2529
+
2530
+ ## Output Format
2531
+ Structure your plan as:
2532
+
2533
+ . **Summary**: One-paragraph overview (2-3 sentences)
2534
+ . **Files to Change**: List each file with specific changes needed
2535
+ . **Implementation Order**: Numbered steps in dependency order
2536
+ . **Risks**: Potential issues or edge cases (if any)
2537
+
2538
+ Be specific about code locations (file paths, function names, line numbers). Keep the plan actionable and under 500 words.`,
2539
+ allowedTools: ["view", "search_content", "find_files"]
2540
+ };
3398
2541
  var MAX_WEB_SEARCH_TOKENS = 2e3;
3399
2542
  var MAX_WEB_EXTRACT_TOKENS = 2e3;
3400
2543
  var MIN_RELEVANCE_SCORE = 0.25;
@@ -3536,14 +2679,14 @@ Examples:
3536
2679
  - Pattern replace: { pattern: 'console.log($ARG)', replacement: 'logger.debug($ARG)' }`,
3537
2680
  // requireApproval: true,
3538
2681
  inputSchema: astSmartEditSchema,
3539
- execute: async ({ path: path13, pattern, replacement, selector, transform, targetName, newName, importSpec }, toolContext) => {
2682
+ execute: async ({ path: path12, pattern, replacement, selector, transform, targetName, newName, importSpec }, toolContext) => {
3540
2683
  try {
3541
2684
  const projectRoot = getProjectRoot();
3542
- const filePath = path.resolve(projectRoot, path13);
2685
+ const filePath = path.resolve(projectRoot, path12);
3543
2686
  const allowedPaths = getAllowedPathsFromContext(toolContext);
3544
2687
  assertPathAllowed(filePath, projectRoot, allowedPaths);
3545
- const content = fs9.readFileSync(filePath, "utf-8");
3546
- const lang = getLanguageFromPath(path13);
2688
+ const content = fs8.readFileSync(filePath, "utf-8");
2689
+ const lang = getLanguageFromPath(path12);
3547
2690
  const ast = napi.parse(lang, content);
3548
2691
  const root = ast.root();
3549
2692
  let modifiedContent = content;
@@ -3603,7 +2746,7 @@ Examples:
3603
2746
  throw new Error("Must provide either transform, pattern/replacement, or selector");
3604
2747
  }
3605
2748
  if (modifiedContent !== content) {
3606
- fs9.writeFileSync(filePath, modifiedContent, "utf-8");
2749
+ fs8.writeFileSync(filePath, modifiedContent, "utf-8");
3607
2750
  }
3608
2751
  return {
3609
2752
  success: true,
@@ -3618,8 +2761,8 @@ Examples:
3618
2761
  }
3619
2762
  }
3620
2763
  });
3621
- function getLanguageFromPath(path13) {
3622
- const ext = path13.split(".").pop()?.toLowerCase();
2764
+ function getLanguageFromPath(path12) {
2765
+ const ext = path12.split(".").pop()?.toLowerCase();
3623
2766
  switch (ext) {
3624
2767
  case "ts":
3625
2768
  case "tsx":
@@ -3881,6 +3024,259 @@ var requestSandboxAccessTool = tools.createTool({
3881
3024
  }
3882
3025
  }
3883
3026
  });
3027
+
3028
+ // src/onboarding/packs.ts
3029
+ function getAvailableModePacks(access, savedCustomPacks = []) {
3030
+ const packs = [];
3031
+ const openaiCodex = "openai/gpt-5.2-codex";
3032
+ const anthropicBuild = access.anthropic === "oauth" ? "anthropic/claude-opus-4-6" : "anthropic/claude-sonnet-4-5";
3033
+ if (access.anthropic && access.openai) {
3034
+ packs.push({
3035
+ id: "varied",
3036
+ name: "Varied",
3037
+ description: "Models from multiple providers",
3038
+ models: {
3039
+ build: anthropicBuild,
3040
+ plan: openaiCodex,
3041
+ fast: access.cerebras ? "cerebras/zai-glm-4.7" : "anthropic/claude-haiku-4-5"
3042
+ }
3043
+ });
3044
+ }
3045
+ if (access.anthropic) {
3046
+ packs.push({
3047
+ id: "anthropic",
3048
+ name: "Anthropic",
3049
+ description: access.anthropic === "oauth" ? "All Anthropic models via Max subscription" : "All Anthropic models via API key",
3050
+ models: {
3051
+ build: anthropicBuild,
3052
+ plan: anthropicBuild,
3053
+ fast: "anthropic/claude-haiku-4-5"
3054
+ }
3055
+ });
3056
+ }
3057
+ if (access.openai) {
3058
+ packs.push({
3059
+ id: "openai",
3060
+ name: "OpenAI",
3061
+ description: access.openai === "oauth" ? "All OpenAI models via Codex subscription" : "All OpenAI models via API key",
3062
+ models: {
3063
+ build: openaiCodex,
3064
+ plan: openaiCodex,
3065
+ fast: "openai/gpt-5.1-codex-mini"
3066
+ }
3067
+ });
3068
+ }
3069
+ for (const cp of savedCustomPacks) {
3070
+ packs.push({
3071
+ id: `custom:${cp.name}`,
3072
+ name: cp.name,
3073
+ description: "Saved custom pack",
3074
+ models: {
3075
+ build: cp.models.build ?? "",
3076
+ plan: cp.models.plan ?? "",
3077
+ fast: cp.models.fast ?? ""
3078
+ }
3079
+ });
3080
+ }
3081
+ const hasCustom = savedCustomPacks.length > 0;
3082
+ packs.push({
3083
+ id: "custom",
3084
+ name: hasCustom ? "New Custom" : "Custom",
3085
+ description: "Choose a model for each mode",
3086
+ models: { build: "", plan: "", fast: "" }
3087
+ });
3088
+ return packs;
3089
+ }
3090
+ function getAvailableOmPacks(access) {
3091
+ const packs = [];
3092
+ if (access.google) {
3093
+ packs.push({
3094
+ id: "gemini",
3095
+ name: "Gemini Flash",
3096
+ description: access.google === "oauth" ? "Via Google OAuth" : "Via Google API key",
3097
+ modelId: "google/gemini-2.5-flash"
3098
+ });
3099
+ }
3100
+ if (access.anthropic) {
3101
+ packs.push({
3102
+ id: "anthropic",
3103
+ name: "Claude Haiku",
3104
+ description: access.anthropic === "oauth" ? "Via Max subscription" : "Via Anthropic API key",
3105
+ modelId: "anthropic/claude-haiku-4-5"
3106
+ });
3107
+ }
3108
+ if (access.openai) {
3109
+ packs.push({
3110
+ id: "openai",
3111
+ name: "Codex Mini",
3112
+ description: access.openai === "oauth" ? "Via Codex subscription" : "Via OpenAI API key",
3113
+ modelId: "openai/gpt-5.1-codex-mini"
3114
+ });
3115
+ }
3116
+ if (access.deepseek) {
3117
+ packs.push({
3118
+ id: "deepseek",
3119
+ name: "DeepSeek",
3120
+ description: "Via DeepSeek API key",
3121
+ modelId: "deepseek/deepseek-chat"
3122
+ });
3123
+ }
3124
+ packs.push({
3125
+ id: "custom",
3126
+ name: "Custom",
3127
+ description: "Choose any available model",
3128
+ modelId: ""
3129
+ });
3130
+ return packs;
3131
+ }
3132
+ var ONBOARDING_VERSION = 1;
3133
+ var STORAGE_DEFAULTS = {
3134
+ backend: "libsql",
3135
+ libsql: {},
3136
+ pg: {}
3137
+ };
3138
+ var DEFAULTS = {
3139
+ onboarding: {
3140
+ completedAt: null,
3141
+ skippedAt: null,
3142
+ version: 0,
3143
+ modePackId: null,
3144
+ omPackId: null
3145
+ },
3146
+ models: {
3147
+ activeModelPackId: null,
3148
+ modeDefaults: {},
3149
+ activeOmPackId: null,
3150
+ omModelOverride: null,
3151
+ subagentModels: {}
3152
+ },
3153
+ preferences: {
3154
+ yolo: null
3155
+ },
3156
+ storage: { ...STORAGE_DEFAULTS },
3157
+ customModelPacks: [],
3158
+ modelUseCounts: {}
3159
+ };
3160
+ function getSettingsPath() {
3161
+ return path.join(chunkC6XKRHRK_cjs.getAppDataDir(), "settings.json");
3162
+ }
3163
+ function migrateFromAuth(settingsPath) {
3164
+ const authPath = path.join(chunkC6XKRHRK_cjs.getAppDataDir(), "auth.json");
3165
+ if (!fs8.existsSync(authPath)) return false;
3166
+ let authData;
3167
+ try {
3168
+ authData = JSON.parse(fs8.readFileSync(authPath, "utf-8"));
3169
+ } catch {
3170
+ return false;
3171
+ }
3172
+ const modelKeys = Object.keys(authData).filter((k) => k.startsWith("_"));
3173
+ if (modelKeys.length === 0) return false;
3174
+ let settings;
3175
+ if (fs8.existsSync(settingsPath)) {
3176
+ try {
3177
+ const raw = JSON.parse(fs8.readFileSync(settingsPath, "utf-8"));
3178
+ settings = {
3179
+ onboarding: { ...DEFAULTS.onboarding, ...raw.onboarding },
3180
+ models: { ...DEFAULTS.models, ...raw.models },
3181
+ preferences: { ...DEFAULTS.preferences, ...raw.preferences },
3182
+ storage: {
3183
+ ...STORAGE_DEFAULTS,
3184
+ ...raw.storage,
3185
+ libsql: { ...STORAGE_DEFAULTS.libsql, ...raw.storage?.libsql },
3186
+ pg: { ...STORAGE_DEFAULTS.pg, ...raw.storage?.pg }
3187
+ },
3188
+ customModelPacks: Array.isArray(raw.customModelPacks) ? raw.customModelPacks : [],
3189
+ modelUseCounts: raw.modelUseCounts && typeof raw.modelUseCounts === "object" ? raw.modelUseCounts : {}
3190
+ };
3191
+ } catch {
3192
+ settings = structuredClone(DEFAULTS);
3193
+ }
3194
+ } else {
3195
+ settings = structuredClone(DEFAULTS);
3196
+ }
3197
+ if (authData._modelRanks && typeof authData._modelRanks === "object") {
3198
+ settings.modelUseCounts = { ...authData._modelRanks, ...settings.modelUseCounts };
3199
+ }
3200
+ for (const key of modelKeys) {
3201
+ const modeMatch = key.match(/^_modeModelId_(.+)$/);
3202
+ if (modeMatch?.[1] && typeof authData[key] === "string" && !settings.models.modeDefaults[modeMatch[1]]) {
3203
+ settings.models.modeDefaults[modeMatch[1]] = authData[key];
3204
+ }
3205
+ }
3206
+ for (const key of modelKeys) {
3207
+ if (key === "_subagentModelId" && typeof authData[key] === "string" && !settings.models.subagentModels["default"]) {
3208
+ settings.models.subagentModels["default"] = authData[key];
3209
+ }
3210
+ const saMatch = key.match(/^_subagentModelId_(.+)$/);
3211
+ if (saMatch?.[1] && typeof authData[key] === "string" && !settings.models.subagentModels[saMatch[1]]) {
3212
+ settings.models.subagentModels[saMatch[1]] = authData[key];
3213
+ }
3214
+ }
3215
+ saveSettings(settings, settingsPath);
3216
+ for (const key of modelKeys) {
3217
+ delete authData[key];
3218
+ }
3219
+ try {
3220
+ fs8.writeFileSync(authPath, JSON.stringify(authData, null, 2), "utf-8");
3221
+ } catch {
3222
+ }
3223
+ return true;
3224
+ }
3225
+ function loadSettings(filePath = getSettingsPath()) {
3226
+ migrateFromAuth(filePath);
3227
+ if (!fs8.existsSync(filePath)) return structuredClone(DEFAULTS);
3228
+ try {
3229
+ const raw = JSON.parse(fs8.readFileSync(filePath, "utf-8"));
3230
+ const settings = {
3231
+ onboarding: { ...DEFAULTS.onboarding, ...raw.onboarding },
3232
+ models: { ...DEFAULTS.models, ...raw.models },
3233
+ preferences: { ...DEFAULTS.preferences, ...raw.preferences },
3234
+ storage: {
3235
+ ...STORAGE_DEFAULTS,
3236
+ ...raw.storage,
3237
+ libsql: { ...STORAGE_DEFAULTS.libsql, ...raw.storage?.libsql },
3238
+ pg: { ...STORAGE_DEFAULTS.pg, ...raw.storage?.pg }
3239
+ },
3240
+ customModelPacks: Array.isArray(raw.customModelPacks) ? raw.customModelPacks : [],
3241
+ modelUseCounts: raw.modelUseCounts && typeof raw.modelUseCounts === "object" ? raw.modelUseCounts : {}
3242
+ };
3243
+ if (raw.models?.omModelId && !settings.models.omModelOverride) {
3244
+ settings.models.omModelOverride = raw.models.omModelId;
3245
+ saveSettings(settings, filePath);
3246
+ }
3247
+ return settings;
3248
+ } catch {
3249
+ return structuredClone(DEFAULTS);
3250
+ }
3251
+ }
3252
+ function resolveModelDefaults(settings, builtinPacks) {
3253
+ const { activeModelPackId, modeDefaults } = settings.models;
3254
+ if (!activeModelPackId) return modeDefaults;
3255
+ if (activeModelPackId.startsWith("custom:")) {
3256
+ const name = activeModelPackId.slice("custom:".length);
3257
+ const pack = settings.customModelPacks.find((p) => p.name === name);
3258
+ if (pack) return pack.models;
3259
+ return modeDefaults;
3260
+ }
3261
+ const builtin = builtinPacks.find((p) => p.id === activeModelPackId);
3262
+ if (builtin) return builtin.models;
3263
+ return modeDefaults;
3264
+ }
3265
+ function resolveOmModel(settings, builtinOmPacks) {
3266
+ const { activeOmPackId, omModelOverride } = settings.models;
3267
+ if (!activeOmPackId) return omModelOverride;
3268
+ if (activeOmPackId === "custom") return omModelOverride;
3269
+ const pack = builtinOmPacks.find((p) => p.id === activeOmPackId);
3270
+ if (pack) return pack.modelId;
3271
+ return omModelOverride;
3272
+ }
3273
+ function saveSettings(settings, filePath = getSettingsPath()) {
3274
+ const dir = path.dirname(filePath);
3275
+ if (!fs8.existsSync(dir)) {
3276
+ fs8.mkdirSync(dir, { recursive: true });
3277
+ }
3278
+ fs8.writeFileSync(filePath, JSON.stringify(settings, null, 2), "utf-8");
3279
+ }
3884
3280
  var mastra = {
3885
3281
  purple: "#7f45e0",
3886
3282
  // #b588fe brand is too washed out for terminal
@@ -4061,9 +3457,9 @@ var ThreadLockError = class extends Error {
4061
3457
  }
4062
3458
  };
4063
3459
  function getLocksDir() {
4064
- const dir = path__namespace.join(getAppDataDir(), "locks");
4065
- if (!fs9__namespace.existsSync(dir)) {
4066
- fs9__namespace.mkdirSync(dir, { recursive: true });
3460
+ const dir = path__namespace.join(chunkC6XKRHRK_cjs.getAppDataDir(), "locks");
3461
+ if (!fs8__namespace.existsSync(dir)) {
3462
+ fs8__namespace.mkdirSync(dir, { recursive: true });
4067
3463
  }
4068
3464
  return dir;
4069
3465
  }
@@ -4082,9 +3478,9 @@ function isProcessAlive(pid) {
4082
3478
  function acquireThreadLock(threadId) {
4083
3479
  const lockPath = getLockPath(threadId);
4084
3480
  const myPid = process.pid;
4085
- if (fs9__namespace.existsSync(lockPath)) {
3481
+ if (fs8__namespace.existsSync(lockPath)) {
4086
3482
  try {
4087
- const content = fs9__namespace.readFileSync(lockPath, "utf-8").trim();
3483
+ const content = fs8__namespace.readFileSync(lockPath, "utf-8").trim();
4088
3484
  const ownerPid = parseInt(content, 10);
4089
3485
  if (!isNaN(ownerPid) && ownerPid !== myPid && isProcessAlive(ownerPid)) {
4090
3486
  throw new ThreadLockError(threadId, ownerPid);
@@ -4093,17 +3489,17 @@ function acquireThreadLock(threadId) {
4093
3489
  if (error instanceof ThreadLockError) throw error;
4094
3490
  }
4095
3491
  }
4096
- fs9__namespace.writeFileSync(lockPath, String(myPid), { mode: 420 });
3492
+ fs8__namespace.writeFileSync(lockPath, String(myPid), { mode: 420 });
4097
3493
  }
4098
3494
  function releaseThreadLock(threadId) {
4099
3495
  const lockPath = getLockPath(threadId);
4100
3496
  const myPid = process.pid;
4101
3497
  try {
4102
- if (!fs9__namespace.existsSync(lockPath)) return;
4103
- const content = fs9__namespace.readFileSync(lockPath, "utf-8").trim();
3498
+ if (!fs8__namespace.existsSync(lockPath)) return;
3499
+ const content = fs8__namespace.readFileSync(lockPath, "utf-8").trim();
4104
3500
  const ownerPid = parseInt(content, 10);
4105
3501
  if (ownerPid === myPid) {
4106
- fs9__namespace.unlinkSync(lockPath);
3502
+ fs8__namespace.unlinkSync(lockPath);
4107
3503
  }
4108
3504
  } catch {
4109
3505
  }
@@ -4111,15 +3507,15 @@ function releaseThreadLock(threadId) {
4111
3507
  function releaseAllThreadLocks() {
4112
3508
  try {
4113
3509
  const locksDir = getLocksDir();
4114
- const files = fs9__namespace.readdirSync(locksDir);
3510
+ const files = fs8__namespace.readdirSync(locksDir);
4115
3511
  const myPid = String(process.pid);
4116
3512
  for (const file of files) {
4117
3513
  if (!file.endsWith(".lock")) continue;
4118
3514
  const lockPath = path__namespace.join(locksDir, file);
4119
3515
  try {
4120
- const content = fs9__namespace.readFileSync(lockPath, "utf-8").trim();
3516
+ const content = fs8__namespace.readFileSync(lockPath, "utf-8").trim();
4121
3517
  if (content === myPid) {
4122
- fs9__namespace.unlinkSync(lockPath);
3518
+ fs8__namespace.unlinkSync(lockPath);
4123
3519
  }
4124
3520
  } catch {
4125
3521
  }
@@ -4128,7 +3524,7 @@ function releaseAllThreadLocks() {
4128
3524
  }
4129
3525
  }
4130
3526
 
4131
- exports.AuthStorage = AuthStorage;
3527
+ exports.ONBOARDING_VERSION = ONBOARDING_VERSION;
4132
3528
  exports.ThreadLockError = ThreadLockError;
4133
3529
  exports.acquireThreadLock = acquireThreadLock;
4134
3530
  exports.astSmartEditTool = astSmartEditTool;
@@ -4141,23 +3537,19 @@ exports.createViewTool = createViewTool;
4141
3537
  exports.createWebExtractTool = createWebExtractTool;
4142
3538
  exports.createWebSearchTool = createWebSearchTool;
4143
3539
  exports.createWriteFileTool = createWriteFileTool;
4144
- exports.detectProject = detectProject;
4145
3540
  exports.executeSubagent = executeSubagent;
4146
3541
  exports.exploreSubagent = exploreSubagent;
4147
3542
  exports.fg = fg;
4148
- exports.getAppDataDir = getAppDataDir;
3543
+ exports.getAvailableModePacks = getAvailableModePacks;
3544
+ exports.getAvailableOmPacks = getAvailableOmPacks;
4149
3545
  exports.getDynamicModel = getDynamicModel;
4150
3546
  exports.getEditorTheme = getEditorTheme;
4151
3547
  exports.getMarkdownTheme = getMarkdownTheme;
4152
- exports.getOAuthProviders = getOAuthProviders;
4153
- exports.getOmScope = getOmScope;
4154
- exports.getResourceIdOverride = getResourceIdOverride;
4155
3548
  exports.getSelectListTheme = getSelectListTheme;
4156
3549
  exports.getSettingsListTheme = getSettingsListTheme;
4157
- exports.getStorageConfig = getStorageConfig;
4158
3550
  exports.getTheme = getTheme;
4159
- exports.getUserId = getUserId;
4160
3551
  exports.hasTavilyKey = hasTavilyKey;
3552
+ exports.loadSettings = loadSettings;
4161
3553
  exports.mastra = mastra;
4162
3554
  exports.parseSubagentMeta = parseSubagentMeta;
4163
3555
  exports.planSubagent = planSubagent;
@@ -4165,11 +3557,14 @@ exports.releaseAllThreadLocks = releaseAllThreadLocks;
4165
3557
  exports.releaseThreadLock = releaseThreadLock;
4166
3558
  exports.requestSandboxAccessTool = requestSandboxAccessTool;
4167
3559
  exports.resolveModel = resolveModel;
3560
+ exports.resolveModelDefaults = resolveModelDefaults;
3561
+ exports.resolveOmModel = resolveOmModel;
3562
+ exports.saveSettings = saveSettings;
4168
3563
  exports.setAuthStorage = setAuthStorage;
4169
3564
  exports.setAuthStorage2 = setAuthStorage2;
4170
3565
  exports.setTheme = setTheme;
4171
3566
  exports.stringReplaceLspTool = stringReplaceLspTool;
4172
3567
  exports.theme = theme;
4173
3568
  exports.tintHex = tintHex;
4174
- //# sourceMappingURL=chunk-LVGWM7ZS.cjs.map
4175
- //# sourceMappingURL=chunk-LVGWM7ZS.cjs.map
3569
+ //# sourceMappingURL=chunk-7K5VFY2N.cjs.map
3570
+ //# sourceMappingURL=chunk-7K5VFY2N.cjs.map