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.
- package/CHANGELOG.md +144 -0
- package/README.md +9 -1
- package/dist/agents/instructions.d.ts.map +1 -1
- package/dist/agents/prompts/base.d.ts +2 -0
- package/dist/agents/prompts/base.d.ts.map +1 -1
- package/dist/agents/prompts/build.d.ts +1 -1
- package/dist/agents/prompts/build.d.ts.map +1 -1
- package/dist/agents/prompts/index.d.ts +1 -2
- package/dist/agents/prompts/index.d.ts.map +1 -1
- package/dist/agents/prompts/plan.d.ts +1 -1
- package/dist/agents/prompts/plan.d.ts.map +1 -1
- package/dist/agents/prompts/tool-guidance.d.ts +11 -0
- package/dist/agents/prompts/tool-guidance.d.ts.map +1 -0
- package/dist/agents/workspace.d.ts.map +1 -1
- package/dist/auth/storage.d.ts +0 -48
- package/dist/auth/storage.d.ts.map +1 -1
- package/dist/{chunk-LVGWM7ZS.cjs → chunk-7K5VFY2N.cjs} +768 -1373
- package/dist/chunk-7K5VFY2N.cjs.map +1 -0
- package/dist/chunk-7TFV3VBB.cjs +8823 -0
- package/dist/chunk-7TFV3VBB.cjs.map +1 -0
- package/dist/chunk-C6XKRHRK.cjs +853 -0
- package/dist/chunk-C6XKRHRK.cjs.map +1 -0
- package/dist/{chunk-7V6U7OKQ.js → chunk-HHX6BKLR.js} +234 -121
- package/dist/chunk-HHX6BKLR.js.map +1 -0
- package/dist/{chunk-FYTZFUHD.js → chunk-LYETHS2L.js} +6389 -5481
- package/dist/chunk-LYETHS2L.js.map +1 -0
- package/dist/{chunk-BYMDWH2E.js → chunk-V4HZ2AVV.js} +729 -1332
- package/dist/chunk-V4HZ2AVV.js.map +1 -0
- package/dist/chunk-VRZZSUQE.js +835 -0
- package/dist/chunk-VRZZSUQE.js.map +1 -0
- package/dist/{chunk-QDLLGD43.cjs → chunk-VZFPT5N7.cjs} +274 -161
- package/dist/chunk-VZFPT5N7.cjs.map +1 -0
- package/dist/cli.cjs +64 -21
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +61 -18
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +2 -2
- package/dist/index.d.ts +6 -7
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/onboarding/index.d.ts +7 -0
- package/dist/onboarding/index.d.ts.map +1 -0
- package/dist/onboarding/onboarding-inline.d.ts +95 -0
- package/dist/onboarding/onboarding-inline.d.ts.map +1 -0
- package/dist/onboarding/packs.d.ts +46 -0
- package/dist/onboarding/packs.d.ts.map +1 -0
- package/dist/onboarding/settings.d.ts +110 -0
- package/dist/onboarding/settings.d.ts.map +1 -0
- package/dist/storage-52Y5MKTG.js +3 -0
- package/dist/storage-52Y5MKTG.js.map +1 -0
- package/dist/storage-JFFX7LJJ.cjs +24 -0
- package/dist/storage-JFFX7LJJ.cjs.map +1 -0
- package/dist/tools/string-replace-lsp.d.ts.map +1 -1
- package/dist/tui/command-dispatch.d.ts +8 -0
- package/dist/tui/command-dispatch.d.ts.map +1 -0
- package/dist/tui/commands/cost.d.ts +3 -0
- package/dist/tui/commands/cost.d.ts.map +1 -0
- package/dist/tui/commands/diff.d.ts +3 -0
- package/dist/tui/commands/diff.d.ts.map +1 -0
- package/dist/tui/commands/exit.d.ts +3 -0
- package/dist/tui/commands/exit.d.ts.map +1 -0
- package/dist/tui/commands/help.d.ts +3 -0
- package/dist/tui/commands/help.d.ts.map +1 -0
- package/dist/tui/commands/hooks.d.ts +3 -0
- package/dist/tui/commands/hooks.d.ts.map +1 -0
- package/dist/tui/commands/index.d.ts +27 -0
- package/dist/tui/commands/index.d.ts.map +1 -0
- package/dist/tui/commands/login.d.ts +3 -0
- package/dist/tui/commands/login.d.ts.map +1 -0
- package/dist/tui/commands/mcp.d.ts +3 -0
- package/dist/tui/commands/mcp.d.ts.map +1 -0
- package/dist/tui/commands/mode.d.ts +3 -0
- package/dist/tui/commands/mode.d.ts.map +1 -0
- package/dist/tui/commands/models-pack.d.ts +3 -0
- package/dist/tui/commands/models-pack.d.ts.map +1 -0
- package/dist/tui/commands/models.d.ts +3 -0
- package/dist/tui/commands/models.d.ts.map +1 -0
- package/dist/tui/commands/name.d.ts +3 -0
- package/dist/tui/commands/name.d.ts.map +1 -0
- package/dist/tui/commands/new.d.ts +3 -0
- package/dist/tui/commands/new.d.ts.map +1 -0
- package/dist/tui/commands/om.d.ts +3 -0
- package/dist/tui/commands/om.d.ts.map +1 -0
- package/dist/tui/commands/permissions.d.ts +3 -0
- package/dist/tui/commands/permissions.d.ts.map +1 -0
- package/dist/tui/commands/resource.d.ts +3 -0
- package/dist/tui/commands/resource.d.ts.map +1 -0
- package/dist/tui/commands/review.d.ts +3 -0
- package/dist/tui/commands/review.d.ts.map +1 -0
- package/dist/tui/commands/sandbox.d.ts +3 -0
- package/dist/tui/commands/sandbox.d.ts.map +1 -0
- package/dist/tui/commands/settings.d.ts +3 -0
- package/dist/tui/commands/settings.d.ts.map +1 -0
- package/dist/tui/commands/setup.d.ts +3 -0
- package/dist/tui/commands/setup.d.ts.map +1 -0
- package/dist/tui/commands/skills.d.ts +3 -0
- package/dist/tui/commands/skills.d.ts.map +1 -0
- package/dist/tui/commands/subagents.d.ts +3 -0
- package/dist/tui/commands/subagents.d.ts.map +1 -0
- package/dist/tui/commands/think.d.ts +3 -0
- package/dist/tui/commands/think.d.ts.map +1 -0
- package/dist/tui/commands/thread-tag-dir.d.ts +3 -0
- package/dist/tui/commands/thread-tag-dir.d.ts.map +1 -0
- package/dist/tui/commands/threads.d.ts +3 -0
- package/dist/tui/commands/threads.d.ts.map +1 -0
- package/dist/tui/commands/types.d.ts +28 -0
- package/dist/tui/commands/types.d.ts.map +1 -0
- package/dist/tui/commands/yolo.d.ts +3 -0
- package/dist/tui/commands/yolo.d.ts.map +1 -0
- package/dist/tui/components/banner.d.ts +9 -0
- package/dist/tui/components/banner.d.ts.map +1 -0
- package/dist/tui/components/help-overlay.d.ts +15 -0
- package/dist/tui/components/help-overlay.d.ts.map +1 -0
- package/dist/tui/components/model-selector.d.ts +3 -0
- package/dist/tui/components/model-selector.d.ts.map +1 -1
- package/dist/tui/components/om-progress.d.ts +4 -30
- package/dist/tui/components/om-progress.d.ts.map +1 -1
- package/dist/tui/components/settings.d.ts +5 -0
- package/dist/tui/components/settings.d.ts.map +1 -1
- package/dist/tui/components/tool-execution-enhanced.d.ts.map +1 -1
- package/dist/tui/display.d.ts +12 -0
- package/dist/tui/display.d.ts.map +1 -0
- package/dist/tui/event-dispatch.d.ts +11 -0
- package/dist/tui/event-dispatch.d.ts.map +1 -0
- package/dist/tui/handlers/agent-lifecycle.d.ts +6 -0
- package/dist/tui/handlers/agent-lifecycle.d.ts.map +1 -0
- package/dist/tui/handlers/index.d.ts +8 -0
- package/dist/tui/handlers/index.d.ts.map +1 -0
- package/dist/tui/handlers/message.d.ts +6 -0
- package/dist/tui/handlers/message.d.ts.map +1 -0
- package/dist/tui/handlers/om.d.ts +11 -0
- package/dist/tui/handlers/om.d.ts.map +1 -0
- package/dist/tui/handlers/prompts.d.ts +20 -0
- package/dist/tui/handlers/prompts.d.ts.map +1 -0
- package/dist/tui/handlers/subagent.d.ts +6 -0
- package/dist/tui/handlers/subagent.d.ts.map +1 -0
- package/dist/tui/handlers/tool.d.ts +30 -0
- package/dist/tui/handlers/tool.d.ts.map +1 -0
- package/dist/tui/handlers/types.d.ts +33 -0
- package/dist/tui/handlers/types.d.ts.map +1 -0
- package/dist/tui/mastra-tui.d.ts +9 -221
- package/dist/tui/mastra-tui.d.ts.map +1 -1
- package/dist/tui/render-messages.d.ts +22 -0
- package/dist/tui/render-messages.d.ts.map +1 -0
- package/dist/tui/setup.d.ts +17 -0
- package/dist/tui/setup.d.ts.map +1 -0
- package/dist/tui/shell.d.ts +3 -0
- package/dist/tui/shell.d.ts.map +1 -0
- package/dist/tui/state.d.ts +4 -24
- package/dist/tui/state.d.ts.map +1 -1
- package/dist/tui/status-line.d.ts +7 -0
- package/dist/tui/status-line.d.ts.map +1 -0
- package/dist/tui.cjs +17 -17
- package/dist/tui.js +2 -2
- package/dist/utils/project.d.ts +37 -9
- package/dist/utils/project.d.ts.map +1 -1
- package/dist/utils/storage-factory.d.ts +21 -0
- package/dist/utils/storage-factory.d.ts.map +1 -0
- package/package.json +7 -6
- package/dist/chunk-7V6U7OKQ.js.map +0 -1
- package/dist/chunk-BQ4ZKTYN.cjs +0 -7915
- package/dist/chunk-BQ4ZKTYN.cjs.map +0 -1
- package/dist/chunk-BYMDWH2E.js.map +0 -1
- package/dist/chunk-FYTZFUHD.js.map +0 -1
- package/dist/chunk-LVGWM7ZS.cjs.map +0 -1
- 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
|
|
5
|
-
var fs9 = require('fs');
|
|
5
|
+
var fs8 = require('fs');
|
|
6
6
|
var os = require('os');
|
|
7
7
|
var path = require('path');
|
|
8
|
-
var
|
|
9
|
-
var
|
|
10
|
-
var
|
|
11
|
-
var
|
|
12
|
-
var
|
|
13
|
-
var
|
|
14
|
-
var
|
|
15
|
-
var
|
|
16
|
-
var
|
|
17
|
-
var
|
|
18
|
-
var
|
|
19
|
-
var
|
|
20
|
-
var
|
|
21
|
-
var
|
|
22
|
-
var
|
|
23
|
-
var
|
|
24
|
-
var
|
|
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
|
-
|
|
45
|
+
n.default = e;
|
|
46
|
+
return Object.freeze(n);
|
|
1157
47
|
}
|
|
1158
48
|
|
|
1159
|
-
|
|
1160
|
-
var
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
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
|
|
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
|
|
1339
|
-
await
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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 (
|
|
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 (
|
|
1150
|
+
if (fs8.existsSync(localBin)) {
|
|
2376
1151
|
tslsBinary = localBin;
|
|
2377
|
-
} else if (
|
|
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 =
|
|
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 =
|
|
2566
|
-
const hasPackageJson =
|
|
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 (
|
|
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
|
|
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 =
|
|
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
|
|
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 =
|
|
2144
|
+
const exists = fs8__namespace.existsSync(absolutePath);
|
|
3370
2145
|
const dir = path__namespace.dirname(absolutePath);
|
|
3371
|
-
if (!
|
|
3372
|
-
|
|
2146
|
+
if (!fs8__namespace.existsSync(dir)) {
|
|
2147
|
+
fs8__namespace.mkdirSync(dir, { recursive: true });
|
|
3373
2148
|
}
|
|
3374
|
-
|
|
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:
|
|
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,
|
|
2685
|
+
const filePath = path.resolve(projectRoot, path12);
|
|
3543
2686
|
const allowedPaths = getAllowedPathsFromContext(toolContext);
|
|
3544
2687
|
assertPathAllowed(filePath, projectRoot, allowedPaths);
|
|
3545
|
-
const content =
|
|
3546
|
-
const lang = getLanguageFromPath(
|
|
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
|
-
|
|
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(
|
|
3622
|
-
const ext =
|
|
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 (!
|
|
4066
|
-
|
|
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 (
|
|
3481
|
+
if (fs8__namespace.existsSync(lockPath)) {
|
|
4086
3482
|
try {
|
|
4087
|
-
const content =
|
|
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
|
-
|
|
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 (!
|
|
4103
|
-
const content =
|
|
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
|
-
|
|
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 =
|
|
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 =
|
|
3516
|
+
const content = fs8__namespace.readFileSync(lockPath, "utf-8").trim();
|
|
4121
3517
|
if (content === myPid) {
|
|
4122
|
-
|
|
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.
|
|
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.
|
|
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-
|
|
4175
|
-
//# sourceMappingURL=chunk-
|
|
3569
|
+
//# sourceMappingURL=chunk-7K5VFY2N.cjs.map
|
|
3570
|
+
//# sourceMappingURL=chunk-7K5VFY2N.cjs.map
|