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