@creative-dswork/dscode 0.2.5 → 0.2.7
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/README.md +44 -34
- package/dist/dscode.mjs +946 -401
- package/dist/web/assets/index-BETLH5IB.css +1 -0
- package/dist/web/assets/index-U_3WqyQ1.js +76 -0
- package/dist/web/index.html +2 -2
- package/package.json +4 -4
- package/dist/web/assets/index-CV7uCPct.js +0 -79
- package/dist/web/assets/index-Ccr9Myda.css +0 -1
package/dist/dscode.mjs
CHANGED
|
@@ -115,6 +115,33 @@ var init_qwen = __esm({
|
|
|
115
115
|
}
|
|
116
116
|
});
|
|
117
117
|
|
|
118
|
+
// src/models/kimi.ts
|
|
119
|
+
var KIMI_BASE_URL, KIMI_MODELS;
|
|
120
|
+
var init_kimi = __esm({
|
|
121
|
+
"src/models/kimi.ts"() {
|
|
122
|
+
"use strict";
|
|
123
|
+
KIMI_BASE_URL = "https://api.moonshot.cn/v1";
|
|
124
|
+
KIMI_MODELS = {
|
|
125
|
+
"kimi-k3": {
|
|
126
|
+
api: "openai-completions",
|
|
127
|
+
provider: "kimi",
|
|
128
|
+
baseUrl: KIMI_BASE_URL,
|
|
129
|
+
reasoning: true,
|
|
130
|
+
thinkingLevelMap: { low: null, medium: null, high: null, max: "max" },
|
|
131
|
+
input: ["text", "image"],
|
|
132
|
+
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
|
|
133
|
+
contextWindow: 1048576,
|
|
134
|
+
maxTokens: 131072,
|
|
135
|
+
compat: {
|
|
136
|
+
supportsDeveloperRole: false,
|
|
137
|
+
thinkingFormat: "deepseek",
|
|
138
|
+
deferredToolsMode: "kimi"
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
});
|
|
144
|
+
|
|
118
145
|
// src/models/registry.ts
|
|
119
146
|
import { builtinModels } from "@earendil-works/pi-ai/providers/all";
|
|
120
147
|
import { createProvider, lazyApi, envApiKeyAuth } from "@earendil-works/pi-ai";
|
|
@@ -155,8 +182,13 @@ function resolveModel(provider, modelId) {
|
|
|
155
182
|
function getThinkingLevel(provider, modelId) {
|
|
156
183
|
try {
|
|
157
184
|
const model = resolveModel(provider, modelId);
|
|
158
|
-
if (model.reasoning) return "
|
|
159
|
-
|
|
185
|
+
if (!model.reasoning) return "off";
|
|
186
|
+
if (model.thinkingLevelMap) {
|
|
187
|
+
const supportedLevels = Object.entries(model.thinkingLevelMap).filter(([, v]) => v !== null);
|
|
188
|
+
if (supportedLevels.length === 0) return "off";
|
|
189
|
+
if (supportedLevels.length === 1 && supportedLevels[0][0] === "max") return "max";
|
|
190
|
+
}
|
|
191
|
+
return "high";
|
|
160
192
|
} catch {
|
|
161
193
|
}
|
|
162
194
|
if (modelId.includes("thinking")) return "high";
|
|
@@ -179,11 +211,12 @@ function getEnvApiKey(provider) {
|
|
|
179
211
|
}
|
|
180
212
|
return void 0;
|
|
181
213
|
}
|
|
182
|
-
var providerFactories, customModelDefs, models, qwenProvider, API_KEY_ENV_VARS;
|
|
214
|
+
var providerFactories, customModelDefs, models, qwenProvider, kimiProvider, API_KEY_ENV_VARS;
|
|
183
215
|
var init_registry = __esm({
|
|
184
216
|
"src/models/registry.ts"() {
|
|
185
217
|
"use strict";
|
|
186
218
|
init_qwen();
|
|
219
|
+
init_kimi();
|
|
187
220
|
providerFactories = /* @__PURE__ */ new Map();
|
|
188
221
|
customModelDefs = /* @__PURE__ */ new Map();
|
|
189
222
|
models = builtinModels();
|
|
@@ -195,6 +228,15 @@ var init_registry = __esm({
|
|
|
195
228
|
models: Object.entries(QWEN_MODELS).map(([id, def]) => ({ id, name: `Qwen: ${id}`, ...def })),
|
|
196
229
|
api: lazyApi(() => import("@earendil-works/pi-ai/api/openai-completions"))
|
|
197
230
|
});
|
|
231
|
+
kimiProvider = createProvider({
|
|
232
|
+
id: "kimi",
|
|
233
|
+
name: "Kimi (Moonshot)",
|
|
234
|
+
baseUrl: KIMI_BASE_URL,
|
|
235
|
+
auth: { apiKey: envApiKeyAuth("Kimi API key", ["KIMI_API_KEY", "MOONSHOT_API_KEY"]) },
|
|
236
|
+
models: Object.entries(KIMI_MODELS).map(([id, def]) => ({ id, name: `Kimi ${id}`, ...def })),
|
|
237
|
+
api: lazyApi(() => import("@earendil-works/pi-ai/api/openai-completions"))
|
|
238
|
+
});
|
|
239
|
+
models.setProvider(kimiProvider);
|
|
198
240
|
models.setProvider(qwenProvider);
|
|
199
241
|
API_KEY_ENV_VARS = {
|
|
200
242
|
deepseek: "DEEPSEEK_API_KEY",
|
|
@@ -207,6 +249,7 @@ var init_registry = __esm({
|
|
|
207
249
|
openrouter: "OPENROUTER_API_KEY",
|
|
208
250
|
"vercel-ai-gateway": "AI_GATEWAY_API_KEY",
|
|
209
251
|
zai: "ZAI_API_KEY",
|
|
252
|
+
"kimi": "KIMI_API_KEY",
|
|
210
253
|
"zai-coding-cn": "ZAI_CODING_CN_API_KEY",
|
|
211
254
|
mistral: "MISTRAL_API_KEY",
|
|
212
255
|
minimax: "MINIMAX_API_KEY",
|
|
@@ -453,7 +496,7 @@ function loadConfig(cliCwd) {
|
|
|
453
496
|
const userCommandsDir = join(configDir, "commands");
|
|
454
497
|
const projectCommandsDir = join(projectPath, ".dscode", "commands");
|
|
455
498
|
const defaultThinkingLevel = getThinkingLevel(provider, modelId);
|
|
456
|
-
const validThinkingLevels = /* @__PURE__ */ new Set(["off", "minimal", "low", "medium", "high", "xhigh"]);
|
|
499
|
+
const validThinkingLevels = /* @__PURE__ */ new Set(["off", "minimal", "low", "medium", "high", "xhigh", "max"]);
|
|
457
500
|
const rawThinkingLevel = process.env.AGENT_THINKING_LEVEL ?? userConfig.thinkingLevel ?? merged.thinkingLevel;
|
|
458
501
|
const thinkingLevel = rawThinkingLevel !== void 0 && validThinkingLevels.has(rawThinkingLevel) ? rawThinkingLevel : defaultThinkingLevel;
|
|
459
502
|
const retryFromEnv = {
|
|
@@ -531,6 +574,7 @@ var init_config = __esm({
|
|
|
531
574
|
PROVIDER_ENV_VARS = {
|
|
532
575
|
deepseek: "DEEPSEEK_API_KEY",
|
|
533
576
|
"kimi-coding": "KIMI_API_KEY",
|
|
577
|
+
"kimi": "KIMI_API_KEY",
|
|
534
578
|
openai: "OPENAI_API_KEY",
|
|
535
579
|
anthropic: "ANTHROPIC_API_KEY",
|
|
536
580
|
google: "GEMINI_API_KEY",
|
|
@@ -538,7 +582,8 @@ var init_config = __esm({
|
|
|
538
582
|
groq: "GROQ_API_KEY",
|
|
539
583
|
openrouter: "OPENROUTER_API_KEY",
|
|
540
584
|
mistral: "MISTRAL_API_KEY",
|
|
541
|
-
qwen: "DASHSCOPE_API_KEY"
|
|
585
|
+
qwen: "DASHSCOPE_API_KEY",
|
|
586
|
+
"moonshotai-cn": "MOONSHOT_API_KEY"
|
|
542
587
|
};
|
|
543
588
|
}
|
|
544
589
|
});
|
|
@@ -547,17 +592,17 @@ var init_config = __esm({
|
|
|
547
592
|
import { appendFileSync, mkdirSync as mkdirSync2, existsSync as existsSync2, writeFileSync as writeFileSync2 } from "node:fs";
|
|
548
593
|
import { join as join2 } from "node:path";
|
|
549
594
|
import { homedir as homedir2 } from "node:os";
|
|
550
|
-
function formatLine(level,
|
|
595
|
+
function formatLine(level, agentType, agentId, tag, message) {
|
|
551
596
|
const ts = (/* @__PURE__ */ new Date()).toISOString().replace("T", " ").slice(0, 19);
|
|
552
|
-
return `[${ts}] [${level.toUpperCase()}] [${
|
|
597
|
+
return `[${ts}] [${level.toUpperCase()}] [${agentType}/${agentId}] [${tag}] ${message}`;
|
|
553
598
|
}
|
|
554
599
|
function ensureDir() {
|
|
555
600
|
if (!existsSync2(LOG_DIR)) {
|
|
556
601
|
mkdirSync2(LOG_DIR, { recursive: true });
|
|
557
602
|
}
|
|
558
603
|
}
|
|
559
|
-
function
|
|
560
|
-
return join2(LOG_DIR,
|
|
604
|
+
function filePath() {
|
|
605
|
+
return join2(LOG_DIR, "dscode.log");
|
|
561
606
|
}
|
|
562
607
|
var LEVEL_RANK, Logger, LOG_DIR;
|
|
563
608
|
var init_logger = __esm({
|
|
@@ -579,32 +624,32 @@ var init_logger = __esm({
|
|
|
579
624
|
this.minLevel = LEVEL_RANK[options.level ?? "debug"];
|
|
580
625
|
}
|
|
581
626
|
// ── Public API ──
|
|
582
|
-
debug(
|
|
583
|
-
this.write("debug",
|
|
627
|
+
debug(tag, message) {
|
|
628
|
+
this.write("debug", tag, message);
|
|
584
629
|
}
|
|
585
|
-
info(
|
|
586
|
-
this.write("info",
|
|
630
|
+
info(tag, message) {
|
|
631
|
+
this.write("info", tag, message);
|
|
587
632
|
}
|
|
588
|
-
warn(
|
|
589
|
-
this.write("warn",
|
|
633
|
+
warn(tag, message) {
|
|
634
|
+
this.write("warn", tag, message);
|
|
590
635
|
}
|
|
591
|
-
error(
|
|
592
|
-
this.write("error",
|
|
636
|
+
error(tag, message) {
|
|
637
|
+
this.write("error", tag, message);
|
|
593
638
|
}
|
|
594
|
-
clear(
|
|
639
|
+
clear() {
|
|
595
640
|
try {
|
|
596
641
|
ensureDir();
|
|
597
|
-
writeFileSync2(
|
|
642
|
+
writeFileSync2(filePath(), "", "utf-8");
|
|
598
643
|
} catch {
|
|
599
644
|
}
|
|
600
645
|
}
|
|
601
646
|
// ── Internal ──
|
|
602
|
-
write(level,
|
|
647
|
+
write(level, tag, message) {
|
|
603
648
|
if (LEVEL_RANK[level] < this.minLevel) return;
|
|
604
|
-
const line = formatLine(level,
|
|
649
|
+
const line = formatLine(level, this.type, this.id, tag, message);
|
|
605
650
|
try {
|
|
606
651
|
ensureDir();
|
|
607
|
-
appendFileSync(
|
|
652
|
+
appendFileSync(filePath(), line + "\n", "utf8");
|
|
608
653
|
} catch {
|
|
609
654
|
}
|
|
610
655
|
}
|
|
@@ -626,7 +671,7 @@ async function getSharp() {
|
|
|
626
671
|
return sharpInstance;
|
|
627
672
|
} catch {
|
|
628
673
|
sharpAvailable = false;
|
|
629
|
-
_cacheLogger.warn("
|
|
674
|
+
_cacheLogger.warn("ImageCache", "sharp not available, images will be stored uncompressed");
|
|
630
675
|
return null;
|
|
631
676
|
}
|
|
632
677
|
}
|
|
@@ -685,7 +730,7 @@ var init_cache = __esm({
|
|
|
685
730
|
await pipeline.png().toFile(filepath);
|
|
686
731
|
return { type: "image_ref", hash: filename, mimeType: "image/png" };
|
|
687
732
|
} catch (err) {
|
|
688
|
-
_cacheLogger.warn("
|
|
733
|
+
_cacheLogger.warn("ImageCache", `sharp processing failed, storing original: ${String(err)}`);
|
|
689
734
|
}
|
|
690
735
|
}
|
|
691
736
|
if (!existsSync3(filepath)) {
|
|
@@ -830,20 +875,20 @@ var init_store = __esm({
|
|
|
830
875
|
const projPath = join4(this.projectDir, `${id}.json`);
|
|
831
876
|
const globalPath = join4(this.globalDir, `${id}.json`);
|
|
832
877
|
let raw;
|
|
833
|
-
let
|
|
878
|
+
let filePath2;
|
|
834
879
|
if (existsSync4(projPath)) {
|
|
835
|
-
|
|
880
|
+
filePath2 = projPath;
|
|
836
881
|
} else if (existsSync4(globalPath)) {
|
|
837
|
-
|
|
882
|
+
filePath2 = globalPath;
|
|
838
883
|
} else {
|
|
839
884
|
throw new SessionValidateError(`Session not found: ${id}`);
|
|
840
885
|
}
|
|
841
|
-
const stat4 = existsSync4(
|
|
886
|
+
const stat4 = existsSync4(filePath2);
|
|
842
887
|
if (!stat4) {
|
|
843
888
|
throw new SessionValidateError(`Session not found: ${id}`);
|
|
844
889
|
}
|
|
845
890
|
try {
|
|
846
|
-
raw = JSON.parse(readFileSync3(
|
|
891
|
+
raw = JSON.parse(readFileSync3(filePath2, "utf8"));
|
|
847
892
|
} catch {
|
|
848
893
|
throw new SessionValidateError("Session file is corrupted: invalid JSON");
|
|
849
894
|
}
|
|
@@ -853,16 +898,16 @@ var init_store = __esm({
|
|
|
853
898
|
async loadSessionFile(sessionId) {
|
|
854
899
|
const projPath = join4(this.projectDir, `${sessionId}.json`);
|
|
855
900
|
const globalPath = join4(this.globalDir, `${sessionId}.json`);
|
|
856
|
-
let
|
|
901
|
+
let filePath2;
|
|
857
902
|
if (existsSync4(projPath)) {
|
|
858
|
-
|
|
903
|
+
filePath2 = projPath;
|
|
859
904
|
} else if (existsSync4(globalPath)) {
|
|
860
|
-
|
|
905
|
+
filePath2 = globalPath;
|
|
861
906
|
} else {
|
|
862
907
|
return null;
|
|
863
908
|
}
|
|
864
909
|
try {
|
|
865
|
-
const raw = JSON.parse(readFileSync3(
|
|
910
|
+
const raw = JSON.parse(readFileSync3(filePath2, "utf8"));
|
|
866
911
|
return validateSession(raw, sessionId);
|
|
867
912
|
} catch {
|
|
868
913
|
return null;
|
|
@@ -1228,7 +1273,7 @@ var init_manager = __esm({
|
|
|
1228
1273
|
try {
|
|
1229
1274
|
this.saveSession(agent, pendingPermission);
|
|
1230
1275
|
} catch (err) {
|
|
1231
|
-
this.logger.error("
|
|
1276
|
+
this.logger.error("Save", `trySaveSession failed: ${String(err)}`);
|
|
1232
1277
|
}
|
|
1233
1278
|
}
|
|
1234
1279
|
async loadSession(id, agent) {
|
|
@@ -9124,11 +9169,11 @@ ${lanes.join("\n")}
|
|
|
9124
9169
|
const toCanonicalName = createGetCanonicalFileName(useCaseSensitiveFileNames2);
|
|
9125
9170
|
return nonPollingWatchFile;
|
|
9126
9171
|
function nonPollingWatchFile(fileName, callback, _pollingInterval, fallbackOptions) {
|
|
9127
|
-
const
|
|
9128
|
-
if (fileWatcherCallbacks.add(
|
|
9129
|
-
fileTimestamps.set(
|
|
9172
|
+
const filePath2 = toCanonicalName(fileName);
|
|
9173
|
+
if (fileWatcherCallbacks.add(filePath2, callback).length === 1 && fileTimestamps) {
|
|
9174
|
+
fileTimestamps.set(filePath2, getModifiedTime3(fileName) || missingFileModifiedTime);
|
|
9130
9175
|
}
|
|
9131
|
-
const dirPath = getDirectoryPath(
|
|
9176
|
+
const dirPath = getDirectoryPath(filePath2) || ".";
|
|
9132
9177
|
const watcher = dirWatchers.get(dirPath) || createDirectoryWatcher(getDirectoryPath(fileName) || ".", dirPath, fallbackOptions);
|
|
9133
9178
|
watcher.referenceCount++;
|
|
9134
9179
|
return {
|
|
@@ -9139,7 +9184,7 @@ ${lanes.join("\n")}
|
|
|
9139
9184
|
} else {
|
|
9140
9185
|
watcher.referenceCount--;
|
|
9141
9186
|
}
|
|
9142
|
-
fileWatcherCallbacks.remove(
|
|
9187
|
+
fileWatcherCallbacks.remove(filePath2, callback);
|
|
9143
9188
|
}
|
|
9144
9189
|
};
|
|
9145
9190
|
}
|
|
@@ -9150,19 +9195,19 @@ ${lanes.join("\n")}
|
|
|
9150
9195
|
(eventName, relativeFileName) => {
|
|
9151
9196
|
if (!isString2(relativeFileName)) return;
|
|
9152
9197
|
const fileName = getNormalizedAbsolutePath(relativeFileName, dirName);
|
|
9153
|
-
const
|
|
9154
|
-
const callbacks = fileName && fileWatcherCallbacks.get(
|
|
9198
|
+
const filePath2 = toCanonicalName(fileName);
|
|
9199
|
+
const callbacks = fileName && fileWatcherCallbacks.get(filePath2);
|
|
9155
9200
|
if (callbacks) {
|
|
9156
9201
|
let currentModifiedTime;
|
|
9157
9202
|
let eventKind = 1;
|
|
9158
9203
|
if (fileTimestamps) {
|
|
9159
|
-
const existingTime = fileTimestamps.get(
|
|
9204
|
+
const existingTime = fileTimestamps.get(filePath2);
|
|
9160
9205
|
if (eventName === "change") {
|
|
9161
9206
|
currentModifiedTime = getModifiedTime3(fileName) || missingFileModifiedTime;
|
|
9162
9207
|
if (currentModifiedTime.getTime() === existingTime.getTime()) return;
|
|
9163
9208
|
}
|
|
9164
9209
|
currentModifiedTime || (currentModifiedTime = getModifiedTime3(fileName) || missingFileModifiedTime);
|
|
9165
|
-
fileTimestamps.set(
|
|
9210
|
+
fileTimestamps.set(filePath2, currentModifiedTime);
|
|
9166
9211
|
if (existingTime === missingFileModifiedTime) eventKind = 0;
|
|
9167
9212
|
else if (currentModifiedTime === missingFileModifiedTime) eventKind = 2;
|
|
9168
9213
|
}
|
|
@@ -9981,7 +10026,7 @@ ${lanes.join("\n")}
|
|
|
9981
10026
|
return process.memoryUsage().heapUsed;
|
|
9982
10027
|
},
|
|
9983
10028
|
getFileSize(path) {
|
|
9984
|
-
const stat4 =
|
|
10029
|
+
const stat4 = statSync6(path);
|
|
9985
10030
|
if (stat4 == null ? void 0 : stat4.isFile()) {
|
|
9986
10031
|
return stat4.size;
|
|
9987
10032
|
}
|
|
@@ -10025,7 +10070,7 @@ ${lanes.join("\n")}
|
|
|
10025
10070
|
}
|
|
10026
10071
|
};
|
|
10027
10072
|
return nodeSystem;
|
|
10028
|
-
function
|
|
10073
|
+
function statSync6(path) {
|
|
10029
10074
|
try {
|
|
10030
10075
|
return _fs.statSync(path, statSyncOptions);
|
|
10031
10076
|
} catch {
|
|
@@ -10084,7 +10129,7 @@ ${lanes.join("\n")}
|
|
|
10084
10129
|
activeSession.post("Profiler.stop", (err, { profile }) => {
|
|
10085
10130
|
var _a;
|
|
10086
10131
|
if (!err) {
|
|
10087
|
-
if ((_a =
|
|
10132
|
+
if ((_a = statSync6(profilePath)) == null ? void 0 : _a.isDirectory()) {
|
|
10088
10133
|
profilePath = _path.join(profilePath, `${(/* @__PURE__ */ new Date()).toISOString().replace(/:/g, "-")}+P${process.pid}.cpuprofile`);
|
|
10089
10134
|
}
|
|
10090
10135
|
try {
|
|
@@ -10204,7 +10249,7 @@ ${lanes.join("\n")}
|
|
|
10204
10249
|
let stat4;
|
|
10205
10250
|
if (typeof dirent === "string" || dirent.isSymbolicLink()) {
|
|
10206
10251
|
const name = combinePaths(path, entry);
|
|
10207
|
-
stat4 =
|
|
10252
|
+
stat4 = statSync6(name);
|
|
10208
10253
|
if (!stat4) {
|
|
10209
10254
|
continue;
|
|
10210
10255
|
}
|
|
@@ -10228,7 +10273,7 @@ ${lanes.join("\n")}
|
|
|
10228
10273
|
return matchFiles(path, extensions, excludes, includes, useCaseSensitiveFileNames2, process.cwd(), depth, getAccessibleFileSystemEntries, realpath);
|
|
10229
10274
|
}
|
|
10230
10275
|
function fileSystemEntryExists(path, entryKind) {
|
|
10231
|
-
const stat4 =
|
|
10276
|
+
const stat4 = statSync6(path);
|
|
10232
10277
|
if (!stat4) {
|
|
10233
10278
|
return false;
|
|
10234
10279
|
}
|
|
@@ -10270,7 +10315,7 @@ ${lanes.join("\n")}
|
|
|
10270
10315
|
}
|
|
10271
10316
|
function getModifiedTime3(path) {
|
|
10272
10317
|
var _a;
|
|
10273
|
-
return (_a =
|
|
10318
|
+
return (_a = statSync6(path)) == null ? void 0 : _a.mtime;
|
|
10274
10319
|
}
|
|
10275
10320
|
function setModifiedTime(path, time) {
|
|
10276
10321
|
try {
|
|
@@ -16645,20 +16690,20 @@ ${lanes.join("\n")}
|
|
|
16645
16690
|
function trySetLanguageAndTerritory(language2, territory2, errors2) {
|
|
16646
16691
|
const compilerFilePath = normalizePath2(sys2.getExecutingFilePath());
|
|
16647
16692
|
const containingDirectoryPath = getDirectoryPath(compilerFilePath);
|
|
16648
|
-
let
|
|
16693
|
+
let filePath2 = combinePaths(containingDirectoryPath, language2);
|
|
16649
16694
|
if (territory2) {
|
|
16650
|
-
|
|
16695
|
+
filePath2 = filePath2 + "-" + territory2;
|
|
16651
16696
|
}
|
|
16652
|
-
|
|
16653
|
-
if (!sys2.fileExists(
|
|
16697
|
+
filePath2 = sys2.resolvePath(combinePaths(filePath2, "diagnosticMessages.generated.json"));
|
|
16698
|
+
if (!sys2.fileExists(filePath2)) {
|
|
16654
16699
|
return false;
|
|
16655
16700
|
}
|
|
16656
16701
|
let fileContents = "";
|
|
16657
16702
|
try {
|
|
16658
|
-
fileContents = sys2.readFile(
|
|
16703
|
+
fileContents = sys2.readFile(filePath2);
|
|
16659
16704
|
} catch {
|
|
16660
16705
|
if (errors2) {
|
|
16661
|
-
errors2.push(createCompilerDiagnostic(Diagnostics.Unable_to_open_file_0,
|
|
16706
|
+
errors2.push(createCompilerDiagnostic(Diagnostics.Unable_to_open_file_0, filePath2));
|
|
16662
16707
|
}
|
|
16663
16708
|
return false;
|
|
16664
16709
|
}
|
|
@@ -16666,7 +16711,7 @@ ${lanes.join("\n")}
|
|
|
16666
16711
|
setLocalizedDiagnosticMessages(JSON.parse(fileContents));
|
|
16667
16712
|
} catch {
|
|
16668
16713
|
if (errors2) {
|
|
16669
|
-
errors2.push(createCompilerDiagnostic(Diagnostics.Corrupted_locale_file_0,
|
|
16714
|
+
errors2.push(createCompilerDiagnostic(Diagnostics.Corrupted_locale_file_0, filePath2));
|
|
16670
16715
|
}
|
|
16671
16716
|
return false;
|
|
16672
16717
|
}
|
|
@@ -22118,10 +22163,10 @@ ${lanes.join("\n")}
|
|
|
22118
22163
|
function getExternalModuleNameFromPath(host, fileName, referencePath) {
|
|
22119
22164
|
const getCanonicalFileName = (f) => host.getCanonicalFileName(f);
|
|
22120
22165
|
const dir = toPath(referencePath ? getDirectoryPath(referencePath) : host.getCommonSourceDirectory(), host.getCurrentDirectory(), getCanonicalFileName);
|
|
22121
|
-
const
|
|
22166
|
+
const filePath2 = getNormalizedAbsolutePath(fileName, host.getCurrentDirectory());
|
|
22122
22167
|
const relativePath = getRelativePathToDirectoryOrUrl(
|
|
22123
22168
|
dir,
|
|
22124
|
-
|
|
22169
|
+
filePath2,
|
|
22125
22170
|
dir,
|
|
22126
22171
|
getCanonicalFileName,
|
|
22127
22172
|
/*isAbsolutePathAnUrl*/
|
|
@@ -22196,11 +22241,11 @@ ${lanes.join("\n")}
|
|
|
22196
22241
|
/* Js */
|
|
22197
22242
|
];
|
|
22198
22243
|
}
|
|
22199
|
-
function getPossibleOriginalInputPathWithoutChangingExt(
|
|
22244
|
+
function getPossibleOriginalInputPathWithoutChangingExt(filePath2, ignoreCase, outputDir, getCommonSourceDirectory2) {
|
|
22200
22245
|
return outputDir ? resolvePath2(
|
|
22201
22246
|
getCommonSourceDirectory2(),
|
|
22202
|
-
getRelativePathFromDirectory(outputDir,
|
|
22203
|
-
) :
|
|
22247
|
+
getRelativePathFromDirectory(outputDir, filePath2, ignoreCase)
|
|
22248
|
+
) : filePath2;
|
|
22204
22249
|
}
|
|
22205
22250
|
function getPathsBasePath(options, host) {
|
|
22206
22251
|
var _a;
|
|
@@ -131244,7 +131289,7 @@ ${lanes.join("\n")}
|
|
|
131244
131289
|
const sourceRoot = normalizeSlashes(mapOptions.sourceRoot || "");
|
|
131245
131290
|
return sourceRoot ? ensureTrailingDirectorySeparator(sourceRoot) : sourceRoot;
|
|
131246
131291
|
}
|
|
131247
|
-
function getSourceMapDirectory(mapOptions,
|
|
131292
|
+
function getSourceMapDirectory(mapOptions, filePath2, sourceFile) {
|
|
131248
131293
|
if (mapOptions.sourceRoot) return host.getCommonSourceDirectory();
|
|
131249
131294
|
if (mapOptions.mapRoot) {
|
|
131250
131295
|
let sourceMapDir = normalizeSlashes(mapOptions.mapRoot);
|
|
@@ -131256,9 +131301,9 @@ ${lanes.join("\n")}
|
|
|
131256
131301
|
}
|
|
131257
131302
|
return sourceMapDir;
|
|
131258
131303
|
}
|
|
131259
|
-
return getDirectoryPath(normalizePath2(
|
|
131304
|
+
return getDirectoryPath(normalizePath2(filePath2));
|
|
131260
131305
|
}
|
|
131261
|
-
function getSourceMappingURL(mapOptions, sourceMapGenerator,
|
|
131306
|
+
function getSourceMappingURL(mapOptions, sourceMapGenerator, filePath2, sourceMapFilePath, sourceFile) {
|
|
131262
131307
|
if (mapOptions.inlineSourceMap) {
|
|
131263
131308
|
const sourceMapText = sourceMapGenerator.toString();
|
|
131264
131309
|
const base64SourceMapText = base64encode(sys, sourceMapText);
|
|
@@ -131274,7 +131319,7 @@ ${lanes.join("\n")}
|
|
|
131274
131319
|
sourceMapDir = combinePaths(host.getCommonSourceDirectory(), sourceMapDir);
|
|
131275
131320
|
return encodeURI(
|
|
131276
131321
|
getRelativePathToDirectoryOrUrl(
|
|
131277
|
-
getDirectoryPath(normalizePath2(
|
|
131322
|
+
getDirectoryPath(normalizePath2(filePath2)),
|
|
131278
131323
|
// get the relative sourceMapDir path based on jsFilePath
|
|
131279
131324
|
combinePaths(sourceMapDir, sourceMapFile),
|
|
131280
131325
|
// this is where user expects to see sourceMap
|
|
@@ -136253,11 +136298,11 @@ ${lanes.join("\n")}
|
|
|
136253
136298
|
}
|
|
136254
136299
|
return fsQueryResult;
|
|
136255
136300
|
}
|
|
136256
|
-
function addOrDeleteFile(fileName,
|
|
136301
|
+
function addOrDeleteFile(fileName, filePath2, eventKind) {
|
|
136257
136302
|
if (eventKind === 1) {
|
|
136258
136303
|
return;
|
|
136259
136304
|
}
|
|
136260
|
-
const parentResult = getCachedFileSystemEntriesForBaseDir(
|
|
136305
|
+
const parentResult = getCachedFileSystemEntriesForBaseDir(filePath2);
|
|
136261
136306
|
if (parentResult) {
|
|
136262
136307
|
updateFilesOfFileSystemEntry(
|
|
136263
136308
|
parentResult,
|
|
@@ -136266,7 +136311,7 @@ ${lanes.join("\n")}
|
|
|
136266
136311
|
/* Created */
|
|
136267
136312
|
);
|
|
136268
136313
|
} else {
|
|
136269
|
-
clearFirstAncestorEntry(
|
|
136314
|
+
clearFirstAncestorEntry(filePath2);
|
|
136270
136315
|
}
|
|
136271
136316
|
}
|
|
136272
136317
|
function updateFilesOfFileSystemEntry(parentResult, baseName, fileExists22) {
|
|
@@ -137800,7 +137845,7 @@ ${lanes.join("\n")}
|
|
|
137800
137845
|
function forEachResolution(resolutionCache, callback, file) {
|
|
137801
137846
|
var _a2;
|
|
137802
137847
|
if (file) (_a2 = resolutionCache == null ? void 0 : resolutionCache.get(file.path)) == null ? void 0 : _a2.forEach((resolution, name, mode) => callback(resolution, name, mode, file.path));
|
|
137803
|
-
else resolutionCache == null ? void 0 : resolutionCache.forEach((resolutions,
|
|
137848
|
+
else resolutionCache == null ? void 0 : resolutionCache.forEach((resolutions, filePath2) => resolutions.forEach((resolution, name, mode) => callback(resolution, name, mode, filePath2)));
|
|
137804
137849
|
}
|
|
137805
137850
|
function getPackagesMap() {
|
|
137806
137851
|
if (packageMap) return packageMap;
|
|
@@ -140139,26 +140184,26 @@ ${lanes.join("\n")}
|
|
|
140139
140184
|
if (options.noEmit) {
|
|
140140
140185
|
return false;
|
|
140141
140186
|
}
|
|
140142
|
-
const
|
|
140143
|
-
if (getSourceFileByPath(
|
|
140187
|
+
const filePath2 = toPath3(file);
|
|
140188
|
+
if (getSourceFileByPath(filePath2)) {
|
|
140144
140189
|
return false;
|
|
140145
140190
|
}
|
|
140146
140191
|
const out = options.outFile;
|
|
140147
140192
|
if (out) {
|
|
140148
|
-
return isSameFile(
|
|
140149
|
-
|
|
140193
|
+
return isSameFile(filePath2, out) || isSameFile(
|
|
140194
|
+
filePath2,
|
|
140150
140195
|
removeFileExtension(out) + ".d.ts"
|
|
140151
140196
|
/* Dts */
|
|
140152
140197
|
);
|
|
140153
140198
|
}
|
|
140154
|
-
if (options.declarationDir && containsPath(options.declarationDir,
|
|
140199
|
+
if (options.declarationDir && containsPath(options.declarationDir, filePath2, currentDirectory, !host.useCaseSensitiveFileNames())) {
|
|
140155
140200
|
return true;
|
|
140156
140201
|
}
|
|
140157
140202
|
if (options.outDir) {
|
|
140158
|
-
return containsPath(options.outDir,
|
|
140203
|
+
return containsPath(options.outDir, filePath2, currentDirectory, !host.useCaseSensitiveFileNames());
|
|
140159
140204
|
}
|
|
140160
|
-
if (fileExtensionIsOneOf(
|
|
140161
|
-
const filePathWithoutExtension = removeFileExtension(
|
|
140205
|
+
if (fileExtensionIsOneOf(filePath2, supportedJSExtensionsFlat) || isDeclarationFileName(filePath2)) {
|
|
140206
|
+
const filePathWithoutExtension = removeFileExtension(filePath2);
|
|
140162
140207
|
return !!getSourceFileByPath(
|
|
140163
140208
|
filePathWithoutExtension + ".ts"
|
|
140164
140209
|
/* Ts */
|
|
@@ -141570,9 +141615,9 @@ ${lanes.join("\n")}
|
|
|
141570
141615
|
const newSignature = Debug.checkDefined(state.fileInfos.get(path)).signature;
|
|
141571
141616
|
return newSignature !== oldSignature;
|
|
141572
141617
|
}
|
|
141573
|
-
function handleDtsMayChangeOfGlobalScope(state,
|
|
141618
|
+
function handleDtsMayChangeOfGlobalScope(state, filePath2, invalidateJsFiles, cancellationToken, host) {
|
|
141574
141619
|
var _a;
|
|
141575
|
-
if (!((_a = state.fileInfos.get(
|
|
141620
|
+
if (!((_a = state.fileInfos.get(filePath2)) == null ? void 0 : _a.affectsGlobalScope)) return false;
|
|
141576
141621
|
BuilderState.getAllFilesExcludingDefaultLibraryFile(
|
|
141577
141622
|
state,
|
|
141578
141623
|
state.program,
|
|
@@ -141638,9 +141683,9 @@ ${lanes.join("\n")}
|
|
|
141638
141683
|
(_b = state.referencedMap.getKeys(affectedFile.resolvedPath)) == null ? void 0 : _b.forEach((exportedFromPath) => {
|
|
141639
141684
|
if (handleDtsMayChangeOfGlobalScope(state, exportedFromPath, invalidateJsFiles, cancellationToken, host)) return true;
|
|
141640
141685
|
const references = state.referencedMap.getKeys(exportedFromPath);
|
|
141641
|
-
return references && forEachKey(references, (
|
|
141686
|
+
return references && forEachKey(references, (filePath2) => handleDtsMayChangeOfFileAndExportsOfFile(
|
|
141642
141687
|
state,
|
|
141643
|
-
|
|
141688
|
+
filePath2,
|
|
141644
141689
|
invalidateJsFiles,
|
|
141645
141690
|
seenFileAndExportsOfFile,
|
|
141646
141691
|
cancellationToken,
|
|
@@ -141648,12 +141693,12 @@ ${lanes.join("\n")}
|
|
|
141648
141693
|
));
|
|
141649
141694
|
});
|
|
141650
141695
|
}
|
|
141651
|
-
function handleDtsMayChangeOfFileAndExportsOfFile(state,
|
|
141696
|
+
function handleDtsMayChangeOfFileAndExportsOfFile(state, filePath2, invalidateJsFiles, seenFileAndExportsOfFile, cancellationToken, host) {
|
|
141652
141697
|
var _a;
|
|
141653
|
-
if (!tryAddToSet(seenFileAndExportsOfFile,
|
|
141654
|
-
if (handleDtsMayChangeOfGlobalScope(state,
|
|
141655
|
-
handleDtsMayChangeOf(state,
|
|
141656
|
-
(_a = state.referencedMap.getKeys(
|
|
141698
|
+
if (!tryAddToSet(seenFileAndExportsOfFile, filePath2)) return void 0;
|
|
141699
|
+
if (handleDtsMayChangeOfGlobalScope(state, filePath2, invalidateJsFiles, cancellationToken, host)) return true;
|
|
141700
|
+
handleDtsMayChangeOf(state, filePath2, invalidateJsFiles, cancellationToken, host);
|
|
141701
|
+
(_a = state.referencedMap.getKeys(filePath2)) == null ? void 0 : _a.forEach(
|
|
141657
141702
|
(referencingFilePath) => handleDtsMayChangeOfFileAndExportsOfFile(
|
|
141658
141703
|
state,
|
|
141659
141704
|
referencingFilePath,
|
|
@@ -142297,10 +142342,10 @@ ${lanes.join("\n")}
|
|
|
142297
142342
|
}
|
|
142298
142343
|
}
|
|
142299
142344
|
if (state.compilerOptions.composite) {
|
|
142300
|
-
const
|
|
142301
|
-
emitSignature = handleNewSignature((_c = state.emitSignatures) == null ? void 0 : _c.get(
|
|
142345
|
+
const filePath2 = sourceFiles[0].resolvedPath;
|
|
142346
|
+
emitSignature = handleNewSignature((_c = state.emitSignatures) == null ? void 0 : _c.get(filePath2), emitSignature);
|
|
142302
142347
|
if (!emitSignature) return data.skippedDtsWrite = true;
|
|
142303
|
-
(state.emitSignatures ?? (state.emitSignatures = /* @__PURE__ */ new Map())).set(
|
|
142348
|
+
(state.emitSignatures ?? (state.emitSignatures = /* @__PURE__ */ new Map())).set(filePath2, emitSignature);
|
|
142304
142349
|
}
|
|
142305
142350
|
} else if (state.compilerOptions.composite) {
|
|
142306
142351
|
const newSignature = handleNewSignature(
|
|
@@ -142783,8 +142828,8 @@ ${lanes.join("\n")}
|
|
|
142783
142828
|
function canWatchAffectedPackageJsonOrNodeModulesOfAtTypes(fileOrDirPath) {
|
|
142784
142829
|
return canWatchDirectoryOrFilePath(fileOrDirPath);
|
|
142785
142830
|
}
|
|
142786
|
-
function canWatchAffectingLocation(
|
|
142787
|
-
return canWatchAffectedPackageJsonOrNodeModulesOfAtTypes(
|
|
142831
|
+
function canWatchAffectingLocation(filePath2) {
|
|
142832
|
+
return canWatchAffectedPackageJsonOrNodeModulesOfAtTypes(filePath2);
|
|
142788
142833
|
}
|
|
142789
142834
|
function getDirectoryToWatchFailedLookupLocation(failedLookupLocation, failedLookupLocationPath, rootDir, rootPath, rootPathComponents, isRootWatchable, getCurrentDirectory, preferNonRecursiveWatch) {
|
|
142790
142835
|
const failedLookupPathComponents = getPathComponents(failedLookupLocationPath);
|
|
@@ -143366,8 +143411,8 @@ ${lanes.join("\n")}
|
|
|
143366
143411
|
function isNodeModulesAtTypesDirectory(dirPath) {
|
|
143367
143412
|
return endsWith(dirPath, "/node_modules/@types");
|
|
143368
143413
|
}
|
|
143369
|
-
function watchFailedLookupLocationsOfExternalModuleResolutions(name, resolution,
|
|
143370
|
-
(resolution.files ?? (resolution.files = /* @__PURE__ */ new Set())).add(
|
|
143414
|
+
function watchFailedLookupLocationsOfExternalModuleResolutions(name, resolution, filePath2, getResolutionWithResolvedFileName, deferWatchingNonRelativeResolution) {
|
|
143415
|
+
(resolution.files ?? (resolution.files = /* @__PURE__ */ new Set())).add(filePath2);
|
|
143371
143416
|
if (resolution.files.size !== 1) return;
|
|
143372
143417
|
if (!deferWatchingNonRelativeResolution || isExternalModuleNameRelative(name)) {
|
|
143373
143418
|
watchFailedLookupLocationOfResolution(resolution);
|
|
@@ -143609,8 +143654,8 @@ ${lanes.join("\n")}
|
|
|
143609
143654
|
}
|
|
143610
143655
|
return removeAtRoot;
|
|
143611
143656
|
}
|
|
143612
|
-
function stopWatchFailedLookupLocationOfResolution(resolution,
|
|
143613
|
-
Debug.checkDefined(resolution.files).delete(
|
|
143657
|
+
function stopWatchFailedLookupLocationOfResolution(resolution, filePath2, getResolutionWithResolvedFileName) {
|
|
143658
|
+
Debug.checkDefined(resolution.files).delete(filePath2);
|
|
143614
143659
|
if (resolution.files.size) return;
|
|
143615
143660
|
resolution.files = void 0;
|
|
143616
143661
|
const resolved = getResolutionWithResolvedFileName(resolution);
|
|
@@ -143657,34 +143702,34 @@ ${lanes.join("\n")}
|
|
|
143657
143702
|
/* Recursive */
|
|
143658
143703
|
);
|
|
143659
143704
|
}
|
|
143660
|
-
function removeResolutionsOfFileFromCache(cache,
|
|
143661
|
-
const resolutions = cache.get(
|
|
143705
|
+
function removeResolutionsOfFileFromCache(cache, filePath2, getResolutionWithResolvedFileName) {
|
|
143706
|
+
const resolutions = cache.get(filePath2);
|
|
143662
143707
|
if (resolutions) {
|
|
143663
143708
|
resolutions.forEach(
|
|
143664
143709
|
(resolution) => stopWatchFailedLookupLocationOfResolution(
|
|
143665
143710
|
resolution,
|
|
143666
|
-
|
|
143711
|
+
filePath2,
|
|
143667
143712
|
getResolutionWithResolvedFileName
|
|
143668
143713
|
)
|
|
143669
143714
|
);
|
|
143670
|
-
cache.delete(
|
|
143715
|
+
cache.delete(filePath2);
|
|
143671
143716
|
}
|
|
143672
143717
|
}
|
|
143673
|
-
function removeResolutionsFromProjectReferenceRedirects(
|
|
143718
|
+
function removeResolutionsFromProjectReferenceRedirects(filePath2) {
|
|
143674
143719
|
if (!fileExtensionIs(
|
|
143675
|
-
|
|
143720
|
+
filePath2,
|
|
143676
143721
|
".json"
|
|
143677
143722
|
/* Json */
|
|
143678
143723
|
)) return;
|
|
143679
143724
|
const program = resolutionHost.getCurrentProgram();
|
|
143680
143725
|
if (!program) return;
|
|
143681
|
-
const resolvedProjectReference = program.getResolvedProjectReferenceByPath(
|
|
143726
|
+
const resolvedProjectReference = program.getResolvedProjectReferenceByPath(filePath2);
|
|
143682
143727
|
if (!resolvedProjectReference) return;
|
|
143683
143728
|
resolvedProjectReference.commandLine.fileNames.forEach((f) => removeResolutionsOfFile(resolutionHost.toPath(f)));
|
|
143684
143729
|
}
|
|
143685
|
-
function removeResolutionsOfFile(
|
|
143686
|
-
removeResolutionsOfFileFromCache(resolvedModuleNames,
|
|
143687
|
-
removeResolutionsOfFileFromCache(resolvedTypeReferenceDirectives,
|
|
143730
|
+
function removeResolutionsOfFile(filePath2) {
|
|
143731
|
+
removeResolutionsOfFileFromCache(resolvedModuleNames, filePath2, getResolvedModuleFromResolution);
|
|
143732
|
+
removeResolutionsOfFileFromCache(resolvedTypeReferenceDirectives, filePath2, getResolvedTypeReferenceDirectiveFromResolution);
|
|
143688
143733
|
}
|
|
143689
143734
|
function invalidateResolutions(resolutions, canInvalidate) {
|
|
143690
143735
|
if (!resolutions) return false;
|
|
@@ -143699,10 +143744,10 @@ ${lanes.join("\n")}
|
|
|
143699
143744
|
});
|
|
143700
143745
|
return invalidated;
|
|
143701
143746
|
}
|
|
143702
|
-
function invalidateResolutionOfFile(
|
|
143703
|
-
removeResolutionsOfFile(
|
|
143747
|
+
function invalidateResolutionOfFile(filePath2) {
|
|
143748
|
+
removeResolutionsOfFile(filePath2);
|
|
143704
143749
|
const prevHasChangedAutomaticTypeDirectiveNames = hasChangedAutomaticTypeDirectiveNames;
|
|
143705
|
-
if (invalidateResolutions(resolvedFileToResolution.get(
|
|
143750
|
+
if (invalidateResolutions(resolvedFileToResolution.get(filePath2), returnTrue) && hasChangedAutomaticTypeDirectiveNames && !prevHasChangedAutomaticTypeDirectiveNames) {
|
|
143706
143751
|
resolutionHost.onChangedAutomaticTypeDirectiveNames();
|
|
143707
143752
|
}
|
|
143708
143753
|
}
|
|
@@ -144096,9 +144141,9 @@ ${lanes.join("\n")}
|
|
|
144096
144141
|
var _a;
|
|
144097
144142
|
const configFile = program.getCompilerOptions().configFile;
|
|
144098
144143
|
if (!((_a = configFile == null ? void 0 : configFile.configFileSpecs) == null ? void 0 : _a.validatedFilesSpec)) return void 0;
|
|
144099
|
-
const
|
|
144144
|
+
const filePath2 = program.getCanonicalFileName(fileName);
|
|
144100
144145
|
const basePath = getDirectoryPath(getNormalizedAbsolutePath(configFile.fileName, program.getCurrentDirectory()));
|
|
144101
|
-
const index = findIndex(configFile.configFileSpecs.validatedFilesSpec, (fileSpec) => program.getCanonicalFileName(getNormalizedAbsolutePath(fileSpec, basePath)) ===
|
|
144146
|
+
const index = findIndex(configFile.configFileSpecs.validatedFilesSpec, (fileSpec) => program.getCanonicalFileName(getNormalizedAbsolutePath(fileSpec, basePath)) === filePath2);
|
|
144102
144147
|
return index !== -1 ? configFile.configFileSpecs.validatedFilesSpecBeforeSubstitution[index] : void 0;
|
|
144103
144148
|
}
|
|
144104
144149
|
function getMatchedIncludeSpec(program, fileName) {
|
|
@@ -183289,13 +183334,13 @@ ${newComment.split("\n").map((c2) => ` * ${c2}`).join("\n")}
|
|
|
183289
183334
|
["./*"]
|
|
183290
183335
|
);
|
|
183291
183336
|
if (files) {
|
|
183292
|
-
for (let
|
|
183293
|
-
|
|
183294
|
-
if (exclude && comparePaths(
|
|
183337
|
+
for (let filePath2 of files) {
|
|
183338
|
+
filePath2 = normalizePath2(filePath2);
|
|
183339
|
+
if (exclude && comparePaths(filePath2, exclude, scriptDirectory, ignoreCase) === 0) {
|
|
183295
183340
|
continue;
|
|
183296
183341
|
}
|
|
183297
183342
|
const { name, extension } = getFilenameWithExtensionOption(
|
|
183298
|
-
getBaseFileName(
|
|
183343
|
+
getBaseFileName(filePath2),
|
|
183299
183344
|
program,
|
|
183300
183345
|
extensionOptions,
|
|
183301
183346
|
/*isExportsOrImportsWildcard*/
|
|
@@ -189595,8 +189640,8 @@ ${content}
|
|
|
189595
189640
|
}
|
|
189596
189641
|
return void 0;
|
|
189597
189642
|
}
|
|
189598
|
-
function getPackagePathComponents(
|
|
189599
|
-
const components = getPathComponents(
|
|
189643
|
+
function getPackagePathComponents(filePath2) {
|
|
189644
|
+
const components = getPathComponents(filePath2);
|
|
189600
189645
|
const nodeModulesIdx = components.lastIndexOf("node_modules");
|
|
189601
189646
|
if (nodeModulesIdx === -1) {
|
|
189602
189647
|
return void 0;
|
|
@@ -201069,8 +201114,8 @@ ${options.prefix}` : "\n" : options.prefix
|
|
|
201069
201114
|
this.projectService.delayUpdateProjectGraphAndEnsureProjectStructureForOpenFiles(this);
|
|
201070
201115
|
}
|
|
201071
201116
|
/** @internal */
|
|
201072
|
-
fileIsOpen(
|
|
201073
|
-
return this.projectService.openFiles.has(
|
|
201117
|
+
fileIsOpen(filePath2) {
|
|
201118
|
+
return this.projectService.openFiles.has(filePath2);
|
|
201074
201119
|
}
|
|
201075
201120
|
/** @internal */
|
|
201076
201121
|
writeLog(s) {
|
|
@@ -215423,15 +215468,15 @@ function generateDashboard(result, outputPath) {
|
|
|
215423
215468
|
writeFileSync10(outputPath, html, "utf8");
|
|
215424
215469
|
return outputPath;
|
|
215425
215470
|
}
|
|
215426
|
-
function openDashboard(
|
|
215471
|
+
function openDashboard(filePath2) {
|
|
215427
215472
|
const platform = process.platform;
|
|
215428
215473
|
let cmd;
|
|
215429
215474
|
if (platform === "darwin") {
|
|
215430
|
-
cmd = `open "${
|
|
215475
|
+
cmd = `open "${filePath2}"`;
|
|
215431
215476
|
} else if (platform === "linux") {
|
|
215432
|
-
cmd = `xdg-open "${
|
|
215477
|
+
cmd = `xdg-open "${filePath2}"`;
|
|
215433
215478
|
} else if (platform === "win32") {
|
|
215434
|
-
cmd = `start "" "${
|
|
215479
|
+
cmd = `start "" "${filePath2}"`;
|
|
215435
215480
|
} else {
|
|
215436
215481
|
return;
|
|
215437
215482
|
}
|
|
@@ -215723,11 +215768,11 @@ function safeJsonParse(json, stepName, validator, logger) {
|
|
|
215723
215768
|
parsed = JSON.parse(json);
|
|
215724
215769
|
} catch (err) {
|
|
215725
215770
|
const msg = err instanceof Error ? err.message : String(err);
|
|
215726
|
-
if (logger) logger.warn(
|
|
215771
|
+
if (logger) logger.warn(stepName, `JSON parse: ${msg}`);
|
|
215727
215772
|
}
|
|
215728
215773
|
const result = validator(parsed);
|
|
215729
215774
|
if (!result.ok) {
|
|
215730
|
-
if (logger) logger.warn(
|
|
215775
|
+
if (logger) logger.warn(stepName, `validation: ${result.errors.join("; ")}`);
|
|
215731
215776
|
if (result.partial !== void 0) return result.partial;
|
|
215732
215777
|
return null;
|
|
215733
215778
|
}
|
|
@@ -216742,13 +216787,13 @@ async function attributeWithLLM(data, steps, stats, meta, graphStore, attributio
|
|
|
216742
216787
|
statsSummary,
|
|
216743
216788
|
recoveryArcs
|
|
216744
216789
|
);
|
|
216745
|
-
if (logger) logger.info("
|
|
216790
|
+
if (logger) logger.info("RuleAttribution", `Prompt size: ${prompt.length} chars, graph ${graphSnapshot ? `${graphSnapshot.dataFlows.length} dataFlows, ${graphSnapshot.subtasks.length} subtasks` : "none"}`);
|
|
216746
216791
|
let rawOutput;
|
|
216747
216792
|
let rulesOutput = [];
|
|
216748
216793
|
try {
|
|
216749
216794
|
rawOutput = await callLLM(RULE_ATTRIBUTION_SYSTEM, prompt, harness, 16384);
|
|
216750
216795
|
} catch (err) {
|
|
216751
|
-
if (logger) logger.warn("
|
|
216796
|
+
if (logger) logger.warn("RuleAttribution", `LLM call failed: ${err.message}`);
|
|
216752
216797
|
return [];
|
|
216753
216798
|
}
|
|
216754
216799
|
for (let attempt = 0; attempt < 2; attempt++) {
|
|
@@ -216760,11 +216805,11 @@ async function attributeWithLLM(data, steps, stats, meta, graphStore, attributio
|
|
|
216760
216805
|
rawOutput = await callLLM(RULE_ATTRIBUTION_SYSTEM, retryPrompt, harness, 16384);
|
|
216761
216806
|
continue;
|
|
216762
216807
|
} catch {
|
|
216763
|
-
if (logger) logger.warn("
|
|
216808
|
+
if (logger) logger.warn("RuleAttribution", "Retry LLM call failed");
|
|
216764
216809
|
return [];
|
|
216765
216810
|
}
|
|
216766
216811
|
}
|
|
216767
|
-
if (logger) logger.warn("
|
|
216812
|
+
if (logger) logger.warn("RuleAttribution", "No JSON found in LLM response after retry");
|
|
216768
216813
|
return [];
|
|
216769
216814
|
}
|
|
216770
216815
|
let parsed;
|
|
@@ -216802,7 +216847,7 @@ Output the FULL corrected JSON array.`;
|
|
|
216802
216847
|
rawOutput = await callLLM(RULE_ATTRIBUTION_SYSTEM, retryPrompt, harness, 16384);
|
|
216803
216848
|
continue;
|
|
216804
216849
|
} catch {
|
|
216805
|
-
if (logger) logger.warn("
|
|
216850
|
+
if (logger) logger.warn("RuleAttribution", "Validation retry failed");
|
|
216806
216851
|
break;
|
|
216807
216852
|
}
|
|
216808
216853
|
}
|
|
@@ -216816,11 +216861,11 @@ Output the FULL corrected JSON array.`;
|
|
|
216816
216861
|
rawOutput = await callLLM(RULE_ATTRIBUTION_SYSTEM, retryPrompt, harness, 16384);
|
|
216817
216862
|
continue;
|
|
216818
216863
|
} catch {
|
|
216819
|
-
if (logger) logger.warn("
|
|
216864
|
+
if (logger) logger.warn("RuleAttribution", "Retry LLM call failed");
|
|
216820
216865
|
return [];
|
|
216821
216866
|
}
|
|
216822
216867
|
}
|
|
216823
|
-
if (logger) logger.warn("
|
|
216868
|
+
if (logger) logger.warn("RuleAttribution", "No JSON found in LLM response after retry");
|
|
216824
216869
|
return [];
|
|
216825
216870
|
}
|
|
216826
216871
|
const parsed = safeJsonParse(json, "rule-attribution", validateHarnessRuleOutputs);
|
|
@@ -216836,14 +216881,14 @@ Output the FULL corrected JSON array.`;
|
|
|
216836
216881
|
rawOutput = await callLLM(RULE_ATTRIBUTION_SYSTEM, retryPrompt, harness, 16384);
|
|
216837
216882
|
continue;
|
|
216838
216883
|
} catch {
|
|
216839
|
-
if (logger) logger.warn("
|
|
216884
|
+
if (logger) logger.warn("RuleAttribution", "Validation retry failed");
|
|
216840
216885
|
return [];
|
|
216841
216886
|
}
|
|
216842
216887
|
}
|
|
216843
216888
|
}
|
|
216844
|
-
if (logger) logger.info("
|
|
216889
|
+
if (logger) logger.info("RuleAttribution", `Generated ${rulesOutput.length} rules`);
|
|
216845
216890
|
if (rulesOutput.length === 0) {
|
|
216846
|
-
if (logger) logger.info("
|
|
216891
|
+
if (logger) logger.info("RuleAttribution", `Raw LLM response (first 500): ${rawOutput.slice(0, 500)}`);
|
|
216847
216892
|
}
|
|
216848
216893
|
return rulesOutput.map((r) => ({
|
|
216849
216894
|
id: r.id,
|
|
@@ -218393,9 +218438,9 @@ function writeLibraryMetadata(skeleton, workspacePath) {
|
|
|
218393
218438
|
`| Screenshots Taken | ${stats.screenshotsTaken} |`,
|
|
218394
218439
|
""
|
|
218395
218440
|
].join("\n");
|
|
218396
|
-
const
|
|
218397
|
-
writeFileSync12(
|
|
218398
|
-
return
|
|
218441
|
+
const filePath2 = join24(workspacePath, "library", "meta.md");
|
|
218442
|
+
writeFileSync12(filePath2, content, "utf-8");
|
|
218443
|
+
return filePath2;
|
|
218399
218444
|
}
|
|
218400
218445
|
function writeLibrarySkeleton(skeleton, workspacePath) {
|
|
218401
218446
|
const lines = [];
|
|
@@ -218458,9 +218503,9 @@ function writeLibrarySkeleton(skeleton, workspacePath) {
|
|
|
218458
218503
|
}
|
|
218459
218504
|
lines.push(hints.join("\n"));
|
|
218460
218505
|
lines.push("");
|
|
218461
|
-
const
|
|
218462
|
-
writeFileSync12(
|
|
218463
|
-
return
|
|
218506
|
+
const filePath2 = join24(workspacePath, "library", "skeleton.md");
|
|
218507
|
+
writeFileSync12(filePath2, lines.join("\n"), "utf-8");
|
|
218508
|
+
return filePath2;
|
|
218464
218509
|
}
|
|
218465
218510
|
function writeLibrarySignals(skeleton, workspacePath) {
|
|
218466
218511
|
const typeOrder = [
|
|
@@ -218504,9 +218549,9 @@ function writeLibrarySignals(skeleton, workspacePath) {
|
|
|
218504
218549
|
lines.push("_No signal anchors detected._");
|
|
218505
218550
|
lines.push("");
|
|
218506
218551
|
}
|
|
218507
|
-
const
|
|
218508
|
-
writeFileSync12(
|
|
218509
|
-
return
|
|
218552
|
+
const filePath2 = join24(workspacePath, "library", "signals.md");
|
|
218553
|
+
writeFileSync12(filePath2, lines.join("\n"), "utf-8");
|
|
218554
|
+
return filePath2;
|
|
218510
218555
|
}
|
|
218511
218556
|
function writeLibraryDataItems(skeleton, workspacePath) {
|
|
218512
218557
|
const sorted = [...skeleton.dataItems].sort((a, b) => b.operationCount - a.operationCount);
|
|
@@ -218527,9 +218572,9 @@ function writeLibraryDataItems(skeleton, workspacePath) {
|
|
|
218527
218572
|
lines.push("");
|
|
218528
218573
|
}
|
|
218529
218574
|
}
|
|
218530
|
-
const
|
|
218531
|
-
writeFileSync12(
|
|
218532
|
-
return
|
|
218575
|
+
const filePath2 = join24(workspacePath, "library", "data-items.md");
|
|
218576
|
+
writeFileSync12(filePath2, lines.join("\n"), "utf-8");
|
|
218577
|
+
return filePath2;
|
|
218533
218578
|
}
|
|
218534
218579
|
function writeLibrarySteps(steps, phases, workspacePath) {
|
|
218535
218580
|
const MAX_STEPS_PER_FILE = 150;
|
|
@@ -218570,9 +218615,9 @@ function writeLibrarySteps(steps, phases, workspacePath) {
|
|
|
218570
218615
|
}
|
|
218571
218616
|
lines.push("");
|
|
218572
218617
|
}
|
|
218573
|
-
const
|
|
218574
|
-
writeFileSync12(
|
|
218575
|
-
written.push(
|
|
218618
|
+
const filePath2 = join24(workspacePath, "library", "steps", fileName);
|
|
218619
|
+
writeFileSync12(filePath2, lines.join("\n"), "utf-8");
|
|
218620
|
+
written.push(filePath2);
|
|
218576
218621
|
}
|
|
218577
218622
|
}
|
|
218578
218623
|
return written;
|
|
@@ -218654,9 +218699,9 @@ function writeLibraryReadme(phase, workspacePath) {
|
|
|
218654
218699
|
"- `glob(pattern)` \u2014 list files matching a pattern in library/ or notebook/",
|
|
218655
218700
|
""
|
|
218656
218701
|
].join("\n");
|
|
218657
|
-
const
|
|
218658
|
-
writeFileSync12(
|
|
218659
|
-
return
|
|
218702
|
+
const filePath2 = join24(workspacePath, "library", "README.md");
|
|
218703
|
+
writeFileSync12(filePath2, content, "utf-8");
|
|
218704
|
+
return filePath2;
|
|
218660
218705
|
}
|
|
218661
218706
|
function writeLibrary(skeleton, steps, ruleResult, phase, workspacePath) {
|
|
218662
218707
|
let fileCount = 0;
|
|
@@ -218750,7 +218795,7 @@ var init_progress = __esm({
|
|
|
218750
218795
|
this.logProgressBar();
|
|
218751
218796
|
}
|
|
218752
218797
|
if (this.logger) {
|
|
218753
|
-
this.logger.info("
|
|
218798
|
+
this.logger.info("Progress", label);
|
|
218754
218799
|
}
|
|
218755
218800
|
}
|
|
218756
218801
|
onPhaseProgress(phaseIndex, event, subZoneId) {
|
|
@@ -218789,7 +218834,7 @@ var init_progress = __esm({
|
|
|
218789
218834
|
this.emitWebEvent("phaseDone", { phaseIndex, summary, durationMs });
|
|
218790
218835
|
if (summary) {
|
|
218791
218836
|
if (this.onLog) this.onLog(`\u2713 ${summary}`);
|
|
218792
|
-
if (this.logger) this.logger.info("
|
|
218837
|
+
if (this.logger) this.logger.info("Progress", `Phase ${phaseIndex} done: ${summary}`);
|
|
218793
218838
|
}
|
|
218794
218839
|
this.logProgressBar();
|
|
218795
218840
|
}
|
|
@@ -218814,7 +218859,7 @@ var init_progress = __esm({
|
|
|
218814
218859
|
this.logProgressBar();
|
|
218815
218860
|
}
|
|
218816
218861
|
if (this.logger) {
|
|
218817
|
-
this.logger.info("
|
|
218862
|
+
this.logger.info("Progress", msg);
|
|
218818
218863
|
}
|
|
218819
218864
|
}
|
|
218820
218865
|
dispose() {
|
|
@@ -218916,7 +218961,7 @@ async function runFocusPipeline(data, harness, sessionStats, onLog, logger) {
|
|
|
218916
218961
|
}
|
|
218917
218962
|
const pipelineStart = Date.now();
|
|
218918
218963
|
let totalLLMCalls = 0;
|
|
218919
|
-
if (logger) logger.info("
|
|
218964
|
+
if (logger) logger.info("FocusPipeline", `Start: ${steps.length} steps, session ${sessionId.slice(0, 8)}`);
|
|
218920
218965
|
const progress = new ProgressDisplay({ onLog, logger });
|
|
218921
218966
|
progress.onPhaseStart(0);
|
|
218922
218967
|
await yieldTui();
|
|
@@ -218936,7 +218981,7 @@ async function runFocusPipeline(data, harness, sessionStats, onLog, logger) {
|
|
|
218936
218981
|
const workspacePath = createWorkspace(sessionId);
|
|
218937
218982
|
const { fileCount } = writeLibrary(skeleton, steps, ruleResult, "SCAN", workspacePath);
|
|
218938
218983
|
cleanOldWorkspaces(10);
|
|
218939
|
-
if (logger) logger.info("
|
|
218984
|
+
if (logger) logger.info("Phase0", `Library: ${fileCount} files \u2192 ${workspacePath}`);
|
|
218940
218985
|
progress.onPhaseDone(0, `\u5199\u5165 ${fileCount} \u4E2A\u6587\u4EF6`, Date.now() - pipelineStart);
|
|
218941
218986
|
await yieldTui();
|
|
218942
218987
|
progress.onPhaseStart(1);
|
|
@@ -218944,7 +218989,7 @@ async function runFocusPipeline(data, harness, sessionStats, onLog, logger) {
|
|
|
218944
218989
|
const scanResult = await scanSession(skeleton, harness, workspacePath, sessionId, progress);
|
|
218945
218990
|
totalLLMCalls++;
|
|
218946
218991
|
const scanSummary = scanResult.noIssuesDetected ? "\u672A\u68C0\u6D4B\u5230\u95EE\u9898" : `\u8BC6\u522B\u5230 ${scanResult.zones.length} \u4E2A attention zones: ${scanResult.zones.map((z) => z.id).join(", ")}`;
|
|
218947
|
-
if (logger) logger.info("
|
|
218992
|
+
if (logger) logger.info("SCAN", scanSummary);
|
|
218948
218993
|
progress.onPhaseDone(1, scanSummary, Date.now() - pipelineStart);
|
|
218949
218994
|
await yieldTui();
|
|
218950
218995
|
if (scanResult.noIssuesDetected || scanResult.zones.length === 0) {
|
|
@@ -218961,7 +219006,7 @@ async function runFocusPipeline(data, harness, sessionStats, onLog, logger) {
|
|
|
218961
219006
|
Date.now(),
|
|
218962
219007
|
logger
|
|
218963
219008
|
);
|
|
218964
|
-
if (logger) logger.info("
|
|
219009
|
+
if (logger) logger.info("FocusPipeline", "Early exit: no issues detected");
|
|
218965
219010
|
return { ...sessionStats, phases: [], deviations: [], rootCauses: [], rules: rules2, timeline: [], causalGraph: null, attribution: null, rulesApplied: [] };
|
|
218966
219011
|
}
|
|
218967
219012
|
progress.onPhaseStart(2);
|
|
@@ -218980,7 +219025,7 @@ async function runFocusPipeline(data, harness, sessionStats, onLog, logger) {
|
|
|
218980
219025
|
zoneAnalyses.push({ zoneId: zone.id, subtasks: [], subtaskEdges: [], agentNodes: [], agentEdges: [], stepDataFlows: [], candidates: [], topCandidate: null, zoneGraphComplete: false });
|
|
218981
219026
|
}
|
|
218982
219027
|
}
|
|
218983
|
-
if (logger) logger.info("
|
|
219028
|
+
if (logger) logger.info("ZOOM", `${zoneAnalyses.length} zones, ${zoneAnalyses.filter((z) => z.zoneGraphComplete).length} complete`);
|
|
218984
219029
|
progress.onPhaseDone(2, `${zoneAnalyses.length} zones \u5206\u6790\u5B8C\u6210`, Date.now() - pipelineStart);
|
|
218985
219030
|
await yieldTui();
|
|
218986
219031
|
progress.onPhaseStart(3);
|
|
@@ -218996,7 +219041,7 @@ async function runFocusPipeline(data, harness, sessionStats, onLog, logger) {
|
|
|
218996
219041
|
);
|
|
218997
219042
|
totalLLMCalls++;
|
|
218998
219043
|
const synthSummary = attribution.mistakeStep > 0 ? `\u6839\u56E0: ${attribution.mistakeAgent}@Step ${attribution.mistakeStep}` : "\u5F52\u56E0\u5B8C\u6210";
|
|
218999
|
-
if (logger) logger.info("
|
|
219044
|
+
if (logger) logger.info("SYNTH", synthSummary);
|
|
219000
219045
|
progress.onPhaseDone(3, synthSummary, Date.now() - pipelineStart);
|
|
219001
219046
|
await yieldTui();
|
|
219002
219047
|
progress.onPhaseStart(4);
|
|
@@ -219017,11 +219062,11 @@ async function runFocusPipeline(data, harness, sessionStats, onLog, logger) {
|
|
|
219017
219062
|
sessionStats.metadata.sessionId,
|
|
219018
219063
|
Date.now()
|
|
219019
219064
|
);
|
|
219020
|
-
if (logger) logger.info("
|
|
219065
|
+
if (logger) logger.info("Phase4", `${rules.length} rules extracted`);
|
|
219021
219066
|
progress.onPhaseDone(4, `${rules.length} \u6761\u89C4\u5219`, Date.now() - pipelineStart);
|
|
219022
219067
|
const totalDuration = Date.now() - pipelineStart;
|
|
219023
219068
|
const keyFindings = attribution.mistakeStep > 0 ? `\u6839\u56E0: ${attribution.mistakeAgent}@Step ${attribution.mistakeStep}` : "\u672A\u68C0\u6D4B\u5230\u660E\u786E\u6839\u56E0";
|
|
219024
|
-
if (logger) logger.info("
|
|
219069
|
+
if (logger) logger.info("FocusPipeline", `Done: ${(totalDuration / 1e3).toFixed(1)}s, ${totalLLMCalls} LLM calls, ${keyFindings}`);
|
|
219025
219070
|
progress.showCompletion({ totalDurationMs: totalDuration, totalLLMCalls, keyFindings });
|
|
219026
219071
|
progress.dispose();
|
|
219027
219072
|
const report = { skeleton, scan: scanResult, zoneAnalyses, attribution, totalLLMCalls };
|
|
@@ -219134,11 +219179,11 @@ async function executeStep1(steps, question, harness, logger) {
|
|
|
219134
219179
|
const prev = result[i];
|
|
219135
219180
|
const next = result[i + 1];
|
|
219136
219181
|
if (prev.stepEnd >= next.stepStart) {
|
|
219137
|
-
if (logger) logger.warn("
|
|
219182
|
+
if (logger) logger.warn("Step1", `Fixing overlap: ${prev.id} (${prev.stepStart}-${prev.stepEnd}) overlaps ${next.id} (${next.stepStart}-${next.stepEnd}), truncating ${prev.id}.stepEnd to ${next.stepStart - 1}`);
|
|
219138
219183
|
prev.stepEnd = next.stepStart - 1;
|
|
219139
219184
|
}
|
|
219140
219185
|
if (prev.stepEnd + 1 < next.stepStart) {
|
|
219141
|
-
if (logger) logger.warn("
|
|
219186
|
+
if (logger) logger.warn("Step1", `Filling gap: gap ${prev.stepEnd + 1}-${next.stepStart - 1} between ${prev.id} and ${next.id}, extending ${prev.id}.stepEnd to ${next.stepStart - 1}`);
|
|
219142
219187
|
prev.stepEnd = next.stepStart - 1;
|
|
219143
219188
|
}
|
|
219144
219189
|
}
|
|
@@ -219191,16 +219236,16 @@ async function executeStep3(subtasks, steps, harness, logger) {
|
|
|
219191
219236
|
const prompt = buildStep3SingleSubtaskPrompt(subtask, steps, subtasks);
|
|
219192
219237
|
const flows = await callAndValidate(harness, prompt, validateStepDataFlows, 4096, `Step 3 / ${subtask.id}`);
|
|
219193
219238
|
allFlows.push(...flows);
|
|
219194
|
-
if (logger) logger.info("
|
|
219239
|
+
if (logger) logger.info("Step3", `Subtask ${subtask.id}: ${flows.length} data flows extracted`);
|
|
219195
219240
|
} catch (err) {
|
|
219196
|
-
if (logger) logger.warn("
|
|
219241
|
+
if (logger) logger.warn("Step3", `Subtask ${subtask.id}: ${err instanceof Error ? err.message : String(err)}`);
|
|
219197
219242
|
failedSubtasks++;
|
|
219198
219243
|
}
|
|
219199
219244
|
}
|
|
219200
219245
|
if (failedSubtasks > 0) {
|
|
219201
|
-
if (logger) logger.warn("
|
|
219246
|
+
if (logger) logger.warn("Step3", `${failedSubtasks}/${subtasks.length} subtasks failed to produce data flows`);
|
|
219202
219247
|
}
|
|
219203
|
-
if (logger) logger.info("
|
|
219248
|
+
if (logger) logger.info("Step3", `Subtask summary: ${allFlows.length} total data flows from ${subtasks.length - failedSubtasks}/${subtasks.length} subtasks`);
|
|
219204
219249
|
return { agents, dataFlows: allFlows };
|
|
219205
219250
|
}
|
|
219206
219251
|
async function executeStep4(subtasks, agentNodes, harness) {
|
|
@@ -219407,7 +219452,7 @@ function loadRuleStore(projectPath, logger) {
|
|
|
219407
219452
|
updatedAt: parsed.updatedAt ?? Date.now()
|
|
219408
219453
|
};
|
|
219409
219454
|
} catch (err) {
|
|
219410
|
-
if (logger) logger.warn("
|
|
219455
|
+
if (logger) logger.warn("RuleStore", `Failed to load rules.json, starting fresh: ${err.message}`);
|
|
219411
219456
|
return createEmptyStore(projectPath);
|
|
219412
219457
|
}
|
|
219413
219458
|
}
|
|
@@ -219418,7 +219463,7 @@ function saveRuleStore(store, logger) {
|
|
|
219418
219463
|
store.updatedAt = Date.now();
|
|
219419
219464
|
writeFileSync13(path, JSON.stringify(store, null, 2), "utf8");
|
|
219420
219465
|
} catch (err) {
|
|
219421
|
-
if (logger) logger.error("
|
|
219466
|
+
if (logger) logger.error("RuleStore", `Failed to save rules.json: ${err.message}`);
|
|
219422
219467
|
}
|
|
219423
219468
|
}
|
|
219424
219469
|
function createEmptyStore(projectPath) {
|
|
@@ -219476,7 +219521,7 @@ async function semanticMerge(newRules, existingStore, harness, logger) {
|
|
|
219476
219521
|
rawOutput = await callMergeLLM(RULE_MERGE_SYSTEM, prompt + "\n\n\u26A0 Output PURE JSON array only.", harness);
|
|
219477
219522
|
continue;
|
|
219478
219523
|
}
|
|
219479
|
-
if (logger) logger.warn("
|
|
219524
|
+
if (logger) logger.warn("RuleStore", "No JSON in merge LLM response, adding all as new");
|
|
219480
219525
|
break;
|
|
219481
219526
|
}
|
|
219482
219527
|
const parsed = validateMergeDecisions(JSON.parse(json));
|
|
@@ -219494,10 +219539,10 @@ async function semanticMerge(newRules, existingStore, harness, logger) {
|
|
|
219494
219539
|
);
|
|
219495
219540
|
continue;
|
|
219496
219541
|
}
|
|
219497
|
-
if (logger) logger.warn("
|
|
219542
|
+
if (logger) logger.warn("RuleStore", `Merge validation failed: ${parsed.errors.join("; ")}`);
|
|
219498
219543
|
}
|
|
219499
219544
|
} catch (err) {
|
|
219500
|
-
if (logger) logger.warn("
|
|
219545
|
+
if (logger) logger.warn("RuleStore", `Semantic merge LLM call failed, adding all as new: ${err.message}`);
|
|
219501
219546
|
}
|
|
219502
219547
|
const merged = { ...existingStore.rules };
|
|
219503
219548
|
const decisionMap = new Map(decisions.map((d) => [d.newRuleId, d]));
|
|
@@ -219578,7 +219623,7 @@ async function runEval(sessionId, ctx) {
|
|
|
219578
219623
|
}
|
|
219579
219624
|
}
|
|
219580
219625
|
}
|
|
219581
|
-
evalLogger.clear(
|
|
219626
|
+
evalLogger.clear();
|
|
219582
219627
|
ui.addInfo(`\u6B63\u5728\u5206\u6790 session ${resolvedId.slice(0, 8)}...`);
|
|
219583
219628
|
const onLog = (msg) => {
|
|
219584
219629
|
ui.addInfo(msg);
|
|
@@ -219604,9 +219649,9 @@ async function runEval(sessionId, ctx) {
|
|
|
219604
219649
|
[${analysisLabel}] Messages: ${result.metadata.totalMessages} | Tool calls: ${result.stats.toolCalls} | Error rate: ${result.stats.errorRate}${attributionInfo} | Rules: ${rulesTriggered}`
|
|
219605
219650
|
);
|
|
219606
219651
|
} catch (err) {
|
|
219607
|
-
evalLogger.error("
|
|
219652
|
+
evalLogger.error("Pipeline", `crash: ${err instanceof Error ? err.message : String(err)}`);
|
|
219608
219653
|
if (err instanceof Error && err.stack) {
|
|
219609
|
-
evalLogger.error("
|
|
219654
|
+
evalLogger.error("Pipeline", `stack:
|
|
219610
219655
|
${err.stack}`);
|
|
219611
219656
|
}
|
|
219612
219657
|
ui.addError(`eval: ${err instanceof Error ? err.message : String(err)}`);
|
|
@@ -220624,18 +220669,18 @@ function safeResolveWithin(projectPath, relPath) {
|
|
|
220624
220669
|
}
|
|
220625
220670
|
return resolved;
|
|
220626
220671
|
}
|
|
220627
|
-
function isTextPath(
|
|
220628
|
-
const ext =
|
|
220672
|
+
function isTextPath(filePath2) {
|
|
220673
|
+
const ext = filePath2.slice(filePath2.lastIndexOf(".")).toLowerCase();
|
|
220629
220674
|
if (BINARY_EXTENSIONS.has(ext)) return false;
|
|
220630
220675
|
if (TEXT_EXTENSIONS.has(ext)) return true;
|
|
220631
220676
|
return false;
|
|
220632
220677
|
}
|
|
220633
|
-
function isImagePath(
|
|
220634
|
-
const ext =
|
|
220678
|
+
function isImagePath(filePath2) {
|
|
220679
|
+
const ext = filePath2.slice(filePath2.lastIndexOf(".")).toLowerCase();
|
|
220635
220680
|
return IMAGE_EXTENSIONS.has(ext);
|
|
220636
220681
|
}
|
|
220637
|
-
function imageMimeType(
|
|
220638
|
-
const ext =
|
|
220682
|
+
function imageMimeType(filePath2) {
|
|
220683
|
+
const ext = filePath2.slice(filePath2.lastIndexOf(".")).toLowerCase();
|
|
220639
220684
|
return IMAGE_MIME_MAP[ext] ?? "image/png";
|
|
220640
220685
|
}
|
|
220641
220686
|
function isBinaryContent(buf) {
|
|
@@ -220645,8 +220690,8 @@ function isBinaryContent(buf) {
|
|
|
220645
220690
|
}
|
|
220646
220691
|
return false;
|
|
220647
220692
|
}
|
|
220648
|
-
function inferLanguage(
|
|
220649
|
-
const ext =
|
|
220693
|
+
function inferLanguage(filePath2) {
|
|
220694
|
+
const ext = filePath2.slice(filePath2.lastIndexOf(".")).toLowerCase();
|
|
220650
220695
|
return LANG_MAP[ext] ?? "";
|
|
220651
220696
|
}
|
|
220652
220697
|
function isLikelyFilePath(text) {
|
|
@@ -221308,7 +221353,7 @@ var DEFAULT_MAX_CHARS;
|
|
|
221308
221353
|
var init_tool_result_formatter = __esm({
|
|
221309
221354
|
"src/ui/shared/tool-result-formatter.ts"() {
|
|
221310
221355
|
"use strict";
|
|
221311
|
-
DEFAULT_MAX_CHARS =
|
|
221356
|
+
DEFAULT_MAX_CHARS = 2e3;
|
|
221312
221357
|
}
|
|
221313
221358
|
});
|
|
221314
221359
|
|
|
@@ -221570,8 +221615,8 @@ __export(web_backend_exports, {
|
|
|
221570
221615
|
WebUiBackend: () => WebUiBackend
|
|
221571
221616
|
});
|
|
221572
221617
|
import { createServer, request as httpRequest2 } from "node:http";
|
|
221573
|
-
import { readFileSync as
|
|
221574
|
-
import { join as
|
|
221618
|
+
import { readFileSync as readFileSync22, existsSync as existsSync25, mkdirSync as mkdirSync13, writeFileSync as writeFileSync15, rmSync as rmSync3, readdirSync as readdirSync9, statSync as statSync5 } from "node:fs";
|
|
221619
|
+
import { join as join30, extname as extname2, resolve as resolve10 } from "node:path";
|
|
221575
221620
|
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
221576
221621
|
function extractImagesFromToolResult(result) {
|
|
221577
221622
|
if (!result || typeof result !== "object") return void 0;
|
|
@@ -221630,6 +221675,15 @@ var init_web_backend = __esm({
|
|
|
221630
221675
|
contextWindowThrottlePending = false;
|
|
221631
221676
|
lastArtifactHtml = "";
|
|
221632
221677
|
isAssistantTurn = false;
|
|
221678
|
+
cleanupUploadDir(sessionId) {
|
|
221679
|
+
const uploadDir = join30(this.config.projectPath, ".dscode", "uploads", sessionId);
|
|
221680
|
+
if (existsSync25(uploadDir)) {
|
|
221681
|
+
try {
|
|
221682
|
+
rmSync3(uploadDir, { recursive: true, force: true });
|
|
221683
|
+
} catch {
|
|
221684
|
+
}
|
|
221685
|
+
}
|
|
221686
|
+
}
|
|
221633
221687
|
constructor(options) {
|
|
221634
221688
|
this.port = options.port;
|
|
221635
221689
|
this.harness = options.harness;
|
|
@@ -221803,22 +221857,6 @@ var init_web_backend = __esm({
|
|
|
221803
221857
|
toolStart(name, args) {
|
|
221804
221858
|
this.broadcast({ type: "tool_start", name, args });
|
|
221805
221859
|
}
|
|
221806
|
-
toolEnd(name, result, isError) {
|
|
221807
|
-
const resultStr = typeof result === "string" ? result.slice(0, 5e3) : JSON.stringify(result).slice(0, 5e3);
|
|
221808
|
-
const images = extractImagesFromToolResult(result);
|
|
221809
|
-
if (this.currentAssistant) {
|
|
221810
|
-
this.currentAssistant.tools = this.currentAssistant.tools.filter((t) => t.name !== name || t.result !== "");
|
|
221811
|
-
this.currentAssistant.tools.push({
|
|
221812
|
-
name,
|
|
221813
|
-
args: "",
|
|
221814
|
-
result: resultStr,
|
|
221815
|
-
isError,
|
|
221816
|
-
images
|
|
221817
|
-
});
|
|
221818
|
-
}
|
|
221819
|
-
this.broadcast({ type: "tool_end", name, result: resultStr, isError, images });
|
|
221820
|
-
this.broadcastContextWindow(false);
|
|
221821
|
-
}
|
|
221822
221860
|
finishAssistantMessage() {
|
|
221823
221861
|
this.broadcastSessionTime();
|
|
221824
221862
|
this.stopSessionTimeBroadcast();
|
|
@@ -222024,24 +222062,90 @@ var init_web_backend = __esm({
|
|
|
222024
222062
|
for (const warn of resolved.warnings) {
|
|
222025
222063
|
client.send({ type: "info", display: "toast", text: `@${warn.path ?? ""}: ${warn.type}${warn.detail ? ` \u2014 ${warn.detail}` : ""}` });
|
|
222026
222064
|
}
|
|
222065
|
+
if (cmd.uploadedFiles && cmd.uploadedFiles.length > 0) {
|
|
222066
|
+
const sm = this.harness.sessionManager;
|
|
222067
|
+
const sessionId = sm.getCurrentSessionId?.() ?? "default";
|
|
222068
|
+
const ts = Date.now();
|
|
222069
|
+
const uploadDir = join30(this.config.projectPath, ".dscode", "uploads", sessionId);
|
|
222070
|
+
mkdirSync13(uploadDir, { recursive: true });
|
|
222071
|
+
const tempPaths = [];
|
|
222072
|
+
for (const uf of cmd.uploadedFiles) {
|
|
222073
|
+
const tempName = `${ts}-${uf.name}`;
|
|
222074
|
+
const tempPath = join30(uploadDir, tempName);
|
|
222075
|
+
writeFileSync15(tempPath, Buffer.from(uf.content, "base64"));
|
|
222076
|
+
tempPaths.push(tempPath);
|
|
222077
|
+
}
|
|
222078
|
+
if (tempPaths.length > 0) {
|
|
222079
|
+
const pathLines = tempPaths.map((p) => `- \`${p}\``).join("\n");
|
|
222080
|
+
text = text ? `${text}
|
|
222081
|
+
|
|
222082
|
+
\u{1F4C1} Attached files:
|
|
222083
|
+
${pathLines}` : `\u{1F4C1} Attached files:
|
|
222084
|
+
${pathLines}`;
|
|
222085
|
+
}
|
|
222086
|
+
}
|
|
222027
222087
|
if (cmd.fileRefs && cmd.fileRefs.length > 0) {
|
|
222028
|
-
const
|
|
222029
|
-
|
|
222030
|
-
|
|
222031
|
-
|
|
222088
|
+
const imageRefs = cmd.fileRefs.filter((f) => isImagePath(f));
|
|
222089
|
+
const nonImageRefs = cmd.fileRefs.filter((f) => !isImagePath(f));
|
|
222090
|
+
if (nonImageRefs.length > 0) {
|
|
222091
|
+
const pathLines = nonImageRefs.map((f) => `- \`${f}\``).join("\n");
|
|
222092
|
+
text = text ? `${text}
|
|
222093
|
+
|
|
222094
|
+
\u{1F4C1} Attached files:
|
|
222095
|
+
${pathLines}` : `\u{1F4C1} Attached files:
|
|
222096
|
+
${pathLines}`;
|
|
222097
|
+
}
|
|
222098
|
+
if (imageRefs.length > 0) {
|
|
222099
|
+
const refsResolved = resolveFileRefs(this.config.projectPath, imageRefs, this.config.atFile ?? {});
|
|
222100
|
+
if (!refsResolved.reject) {
|
|
222101
|
+
if (refsResolved.text) {
|
|
222102
|
+
text = text ? `${text}
|
|
222032
222103
|
|
|
222033
222104
|
${refsResolved.text}` : refsResolved.text;
|
|
222105
|
+
}
|
|
222106
|
+
if (refsResolved.images.length > 0) {
|
|
222107
|
+
const refImages = refsResolved.images.map((img) => ({
|
|
222108
|
+
data: img.data,
|
|
222109
|
+
mimeType: img.mimeType
|
|
222110
|
+
}));
|
|
222111
|
+
images = [...images ?? [], ...refImages];
|
|
222112
|
+
}
|
|
222034
222113
|
}
|
|
222035
|
-
|
|
222036
|
-
|
|
222037
|
-
data: img.data,
|
|
222038
|
-
mimeType: img.mimeType
|
|
222039
|
-
}));
|
|
222040
|
-
images = [...images ?? [], ...refImages];
|
|
222114
|
+
for (const warn of refsResolved.warnings) {
|
|
222115
|
+
client.send({ type: "info", display: "toast", text: `${warn.path ?? ""}: ${warn.type}${warn.detail ? ` \u2014 ${warn.detail}` : ""}` });
|
|
222041
222116
|
}
|
|
222042
222117
|
}
|
|
222043
|
-
|
|
222044
|
-
|
|
222118
|
+
}
|
|
222119
|
+
if (cmd.fileRefs && cmd.fileRefs.length > 0) {
|
|
222120
|
+
const imageRefs = cmd.fileRefs.filter((f) => isImagePath(f));
|
|
222121
|
+
const nonImageRefs = cmd.fileRefs.filter((f) => !isImagePath(f));
|
|
222122
|
+
if (nonImageRefs.length > 0) {
|
|
222123
|
+
const pathLines = nonImageRefs.map((f) => `- \`${f}\``).join("\n");
|
|
222124
|
+
text = text ? `${text}
|
|
222125
|
+
|
|
222126
|
+
\u{1F4C1} Attached files:
|
|
222127
|
+
${pathLines}` : `\u{1F4C1} Attached files:
|
|
222128
|
+
${pathLines}`;
|
|
222129
|
+
}
|
|
222130
|
+
if (imageRefs.length > 0) {
|
|
222131
|
+
const refsResolved = resolveFileRefs(this.config.projectPath, imageRefs, this.config.atFile ?? {});
|
|
222132
|
+
if (!refsResolved.reject) {
|
|
222133
|
+
if (refsResolved.text) {
|
|
222134
|
+
text = text ? `${text}
|
|
222135
|
+
|
|
222136
|
+
${refsResolved.text}` : refsResolved.text;
|
|
222137
|
+
}
|
|
222138
|
+
if (refsResolved.images.length > 0) {
|
|
222139
|
+
const refImages = refsResolved.images.map((img) => ({
|
|
222140
|
+
data: img.data,
|
|
222141
|
+
mimeType: img.mimeType
|
|
222142
|
+
}));
|
|
222143
|
+
images = [...images ?? [], ...refImages];
|
|
222144
|
+
}
|
|
222145
|
+
}
|
|
222146
|
+
for (const warn of refsResolved.warnings) {
|
|
222147
|
+
client.send({ type: "info", display: "toast", text: `${warn.path ?? ""}: ${warn.type}${warn.detail ? ` \u2014 ${warn.detail}` : ""}` });
|
|
222148
|
+
}
|
|
222045
222149
|
}
|
|
222046
222150
|
}
|
|
222047
222151
|
client.send({ type: "user_message", text, images: images && images.length > 0 ? images : void 0 });
|
|
@@ -222054,6 +222158,7 @@ ${refsResolved.text}` : refsResolved.text;
|
|
|
222054
222158
|
mimeType: img.mimeType
|
|
222055
222159
|
}));
|
|
222056
222160
|
this.pendingImages = [];
|
|
222161
|
+
this.harness.logger.info("WebBackend", `promptWithImages: textLen=${text.length}, images=${imageContents.length}, img[0].dataLen=${imageContents[0]?.data?.length ?? 0}, mime=${imageContents[0]?.mimeType ?? "?"}`);
|
|
222057
222162
|
await this.harness.promptWithImages(text, imageContents);
|
|
222058
222163
|
} else {
|
|
222059
222164
|
this.pendingImages = [];
|
|
@@ -222082,7 +222187,7 @@ ${refsResolved.text}` : refsResolved.text;
|
|
|
222082
222187
|
fuzzyPattern: fuzzy,
|
|
222083
222188
|
permissionArgs: this.currentPermissionArgs
|
|
222084
222189
|
};
|
|
222085
|
-
this.harness.logger.info("
|
|
222190
|
+
this.harness.logger.info("WebBackend", "saving pendingPermission to metadata, then denying");
|
|
222086
222191
|
sm.saveSession(this.harness.agent, meta.pendingPermission);
|
|
222087
222192
|
}
|
|
222088
222193
|
this.permissionResolve({ decision: "deny" });
|
|
@@ -222201,12 +222306,51 @@ ${refsResolved.text}` : refsResolved.text;
|
|
|
222201
222306
|
await this.handleArtifact(client, cmd);
|
|
222202
222307
|
break;
|
|
222203
222308
|
}
|
|
222309
|
+
case "cache": {
|
|
222310
|
+
this.handleCache(client, cmd);
|
|
222311
|
+
break;
|
|
222312
|
+
}
|
|
222204
222313
|
case "mcp": {
|
|
222205
222314
|
this.handleMcp(client, cmd);
|
|
222206
222315
|
break;
|
|
222207
222316
|
}
|
|
222208
222317
|
}
|
|
222209
222318
|
}
|
|
222319
|
+
handleCache(client, cmd) {
|
|
222320
|
+
const uploadsDir = join30(this.config.projectPath, ".dscode", "uploads");
|
|
222321
|
+
if (cmd.action === "clear") {
|
|
222322
|
+
if (existsSync25(uploadsDir)) {
|
|
222323
|
+
try {
|
|
222324
|
+
rmSync3(uploadsDir, { recursive: true, force: true });
|
|
222325
|
+
} catch {
|
|
222326
|
+
}
|
|
222327
|
+
}
|
|
222328
|
+
client.send({ type: "cache_size", totalBytes: 0, fileCount: 0, sessionCount: 0 });
|
|
222329
|
+
return;
|
|
222330
|
+
}
|
|
222331
|
+
let totalBytes = 0;
|
|
222332
|
+
let fileCount = 0;
|
|
222333
|
+
let sessionCount = 0;
|
|
222334
|
+
if (existsSync25(uploadsDir)) {
|
|
222335
|
+
const sessionDirs = readdirSync9(uploadsDir, { withFileTypes: true }).filter((d) => d.isDirectory());
|
|
222336
|
+
sessionCount = sessionDirs.length;
|
|
222337
|
+
for (const dir of sessionDirs) {
|
|
222338
|
+
const sessionPath = join30(uploadsDir, dir.name);
|
|
222339
|
+
const files = readdirSync9(sessionPath, { withFileTypes: true });
|
|
222340
|
+
for (const f of files) {
|
|
222341
|
+
if (f.isFile()) {
|
|
222342
|
+
try {
|
|
222343
|
+
const st = statSync5(join30(sessionPath, f.name));
|
|
222344
|
+
totalBytes += st.size;
|
|
222345
|
+
fileCount++;
|
|
222346
|
+
} catch {
|
|
222347
|
+
}
|
|
222348
|
+
}
|
|
222349
|
+
}
|
|
222350
|
+
}
|
|
222351
|
+
}
|
|
222352
|
+
client.send({ type: "cache_size", totalBytes, fileCount, sessionCount });
|
|
222353
|
+
}
|
|
222210
222354
|
async handleSlashCommand(client, text) {
|
|
222211
222355
|
try {
|
|
222212
222356
|
const executed = executeSlashCommand(text, { harness: this.harness, ui: this });
|
|
@@ -222531,15 +222675,15 @@ ${matchList}` });
|
|
|
222531
222675
|
const meta = sessionManager.getCurrentMetadata();
|
|
222532
222676
|
if (meta?.pendingPermission) {
|
|
222533
222677
|
pendingPermission = meta.pendingPermission;
|
|
222534
|
-
this.harness.logger.info("
|
|
222678
|
+
this.harness.logger.info("WebBackend", "using pendingPermission from metadata");
|
|
222535
222679
|
}
|
|
222536
222680
|
}
|
|
222537
222681
|
this.harness.abort();
|
|
222538
222682
|
if (pendingPermission) {
|
|
222539
|
-
this.harness.logger.info("
|
|
222683
|
+
this.harness.logger.info("WebBackend", `saving with pendingPermission: ${JSON.stringify(pendingPermission)}`);
|
|
222540
222684
|
sessionManager.saveSession(agent, pendingPermission);
|
|
222541
222685
|
} else {
|
|
222542
|
-
this.harness.logger.info("
|
|
222686
|
+
this.harness.logger.info("WebBackend", "saving without pendingPermission");
|
|
222543
222687
|
this.harness.saveSessionNow();
|
|
222544
222688
|
}
|
|
222545
222689
|
const result = await sessionManager.loadSession(match.id, agent);
|
|
@@ -222598,6 +222742,7 @@ ${matchList}` });
|
|
|
222598
222742
|
if (wasCurrent) {
|
|
222599
222743
|
client.send({ type: "clear_conversation" });
|
|
222600
222744
|
}
|
|
222745
|
+
this.cleanupUploadDir(cmd.id);
|
|
222601
222746
|
client.send({ type: "info", display: "toast", text: "Session deleted." });
|
|
222602
222747
|
const sessions = sessionManager.listSessions();
|
|
222603
222748
|
const currentId = sessionManager.getCurrentSessionId?.() ?? void 0;
|
|
@@ -222781,15 +222926,15 @@ ${matchList}` });
|
|
|
222781
222926
|
req.pipe(proxyReq);
|
|
222782
222927
|
}
|
|
222783
222928
|
serveSpa(req, res) {
|
|
222784
|
-
const projectDist =
|
|
222785
|
-
const moduleDist =
|
|
222786
|
-
const webDist =
|
|
222787
|
-
let
|
|
222788
|
-
const qIdx =
|
|
222789
|
-
if (qIdx >= 0)
|
|
222790
|
-
const hIdx =
|
|
222791
|
-
if (hIdx >= 0)
|
|
222792
|
-
const ext = extname2(
|
|
222929
|
+
const projectDist = join30(resolve10(this.projectRoot), "dist", "web");
|
|
222930
|
+
const moduleDist = join30(fileURLToPath3(new URL(".", import.meta.url)), "web");
|
|
222931
|
+
const webDist = existsSync25(projectDist) ? projectDist : moduleDist;
|
|
222932
|
+
let filePath2 = join30(webDist, req.url === "/" ? "index.html" : req.url);
|
|
222933
|
+
const qIdx = filePath2.indexOf("?");
|
|
222934
|
+
if (qIdx >= 0) filePath2 = filePath2.slice(0, qIdx);
|
|
222935
|
+
const hIdx = filePath2.indexOf("#");
|
|
222936
|
+
if (hIdx >= 0) filePath2 = filePath2.slice(0, hIdx);
|
|
222937
|
+
const ext = extname2(filePath2);
|
|
222793
222938
|
const mimeTypes = {
|
|
222794
222939
|
".html": "text/html",
|
|
222795
222940
|
".js": "application/javascript",
|
|
@@ -222802,12 +222947,12 @@ ${matchList}` });
|
|
|
222802
222947
|
".woff": "font/woff"
|
|
222803
222948
|
};
|
|
222804
222949
|
try {
|
|
222805
|
-
if (
|
|
222806
|
-
const content =
|
|
222950
|
+
if (existsSync25(filePath2) && ext) {
|
|
222951
|
+
const content = readFileSync22(filePath2);
|
|
222807
222952
|
res.writeHead(200, { "Content-Type": mimeTypes[ext] ?? "application/octet-stream" });
|
|
222808
222953
|
res.end(content);
|
|
222809
222954
|
} else {
|
|
222810
|
-
const html =
|
|
222955
|
+
const html = readFileSync22(join30(webDist, "index.html"));
|
|
222811
222956
|
res.writeHead(200, { "Content-Type": "text/html" });
|
|
222812
222957
|
res.end(html);
|
|
222813
222958
|
}
|
|
@@ -222820,9 +222965,9 @@ ${matchList}` });
|
|
|
222820
222965
|
try {
|
|
222821
222966
|
let styleConstraints = "";
|
|
222822
222967
|
try {
|
|
222823
|
-
const skillPath =
|
|
222824
|
-
if (
|
|
222825
|
-
styleConstraints =
|
|
222968
|
+
const skillPath = join30(this.config.projectPath, ".dscode", "html_output_skill");
|
|
222969
|
+
if (existsSync25(skillPath)) {
|
|
222970
|
+
styleConstraints = readFileSync22(skillPath, "utf-8");
|
|
222826
222971
|
}
|
|
222827
222972
|
} catch {
|
|
222828
222973
|
}
|
|
@@ -222907,6 +223052,10 @@ Modify the HTML to fulfill the user's request. Output the complete modified HTML
|
|
|
222907
223052
|
}
|
|
222908
223053
|
}
|
|
222909
223054
|
fullHtml = this.stripArtifactFences(fullHtml);
|
|
223055
|
+
try {
|
|
223056
|
+
writeFileSync15(join30(this.config.projectPath, "_artifact_debug.html"), fullHtml, "utf-8");
|
|
223057
|
+
} catch {
|
|
223058
|
+
}
|
|
222910
223059
|
this.lastArtifactHtml = fullHtml;
|
|
222911
223060
|
client.send({ type: "artifact_end" });
|
|
222912
223061
|
} catch (err) {
|
|
@@ -223040,8 +223189,8 @@ Modify the HTML to fulfill the user's request. Output the complete modified HTML
|
|
|
223040
223189
|
|
|
223041
223190
|
// src/core/main.ts
|
|
223042
223191
|
init_config();
|
|
223043
|
-
import { existsSync as
|
|
223044
|
-
import { dirname as dirname7, join as
|
|
223192
|
+
import { existsSync as existsSync26, readFileSync as readFileSync23 } from "node:fs";
|
|
223193
|
+
import { dirname as dirname7, join as join31, resolve as resolve11 } from "node:path";
|
|
223045
223194
|
import { fileURLToPath as fileURLToPath4 } from "node:url";
|
|
223046
223195
|
import { randomBytes } from "node:crypto";
|
|
223047
223196
|
|
|
@@ -224043,13 +224192,13 @@ var CheckpointManager = class {
|
|
|
224043
224192
|
return this.baseCommit;
|
|
224044
224193
|
}
|
|
224045
224194
|
/** Save a checkpoint of the file before modification. */
|
|
224046
|
-
save(
|
|
224047
|
-
const fileExists4 = existsSync7(
|
|
224048
|
-
const content = fileExists4 ? readFileSync6(
|
|
224049
|
-
this.store.delete(
|
|
224195
|
+
save(filePath2, writerType) {
|
|
224196
|
+
const fileExists4 = existsSync7(filePath2);
|
|
224197
|
+
const content = fileExists4 ? readFileSync6(filePath2) : null;
|
|
224198
|
+
this.store.delete(filePath2);
|
|
224050
224199
|
this.store.save(
|
|
224051
224200
|
{
|
|
224052
|
-
filePath,
|
|
224201
|
+
filePath: filePath2,
|
|
224053
224202
|
baseCommit: this.baseCommit,
|
|
224054
224203
|
writerType,
|
|
224055
224204
|
timestamp: Date.now(),
|
|
@@ -224060,31 +224209,31 @@ var CheckpointManager = class {
|
|
|
224060
224209
|
);
|
|
224061
224210
|
}
|
|
224062
224211
|
/** Restore file from its checkpoint and remove the checkpoint. */
|
|
224063
|
-
rollback(
|
|
224064
|
-
const entry = this.store.load(
|
|
224212
|
+
rollback(filePath2) {
|
|
224213
|
+
const entry = this.store.load(filePath2);
|
|
224065
224214
|
if (!entry) {
|
|
224066
|
-
throw new Error(`No checkpoint found for ${
|
|
224215
|
+
throw new Error(`No checkpoint found for ${filePath2}`);
|
|
224067
224216
|
}
|
|
224068
224217
|
if (entry.content !== null) {
|
|
224069
|
-
const parentDir = dirname(
|
|
224218
|
+
const parentDir = dirname(filePath2);
|
|
224070
224219
|
if (!existsSync7(parentDir)) {
|
|
224071
224220
|
mkdirSync6(parentDir, { recursive: true });
|
|
224072
224221
|
}
|
|
224073
|
-
writeFileSync6(
|
|
224222
|
+
writeFileSync6(filePath2, entry.content);
|
|
224074
224223
|
} else {
|
|
224075
|
-
if (existsSync7(
|
|
224076
|
-
unlinkSync2(
|
|
224224
|
+
if (existsSync7(filePath2)) {
|
|
224225
|
+
unlinkSync2(filePath2);
|
|
224077
224226
|
}
|
|
224078
224227
|
}
|
|
224079
|
-
this.store.delete(
|
|
224228
|
+
this.store.delete(filePath2);
|
|
224080
224229
|
}
|
|
224081
224230
|
/** Commit (remove) the checkpoint after a successful write. */
|
|
224082
|
-
commit(
|
|
224083
|
-
this.store.delete(
|
|
224231
|
+
commit(filePath2) {
|
|
224232
|
+
this.store.delete(filePath2);
|
|
224084
224233
|
}
|
|
224085
224234
|
/** Check if a file has an uncommitted checkpoint. */
|
|
224086
|
-
isDirty(
|
|
224087
|
-
return this.store.load(
|
|
224235
|
+
isDirty(filePath2) {
|
|
224236
|
+
return this.store.load(filePath2) !== null;
|
|
224088
224237
|
}
|
|
224089
224238
|
/** List all file paths with uncommitted checkpoints. */
|
|
224090
224239
|
listDirty() {
|
|
@@ -224099,20 +224248,20 @@ var CheckpointManager = class {
|
|
|
224099
224248
|
// src/checkpoint/write-tracker.ts
|
|
224100
224249
|
var FileWriteTracker = class {
|
|
224101
224250
|
writers = /* @__PURE__ */ new Map();
|
|
224102
|
-
recordWrite(
|
|
224103
|
-
this.writers.set(
|
|
224251
|
+
recordWrite(filePath2, writerType) {
|
|
224252
|
+
this.writers.set(filePath2, writerType);
|
|
224104
224253
|
}
|
|
224105
|
-
getWriter(
|
|
224106
|
-
return this.writers.get(
|
|
224254
|
+
getWriter(filePath2) {
|
|
224255
|
+
return this.writers.get(filePath2) ?? null;
|
|
224107
224256
|
}
|
|
224108
|
-
getContinuity(
|
|
224109
|
-
const prev = this.writers.get(
|
|
224257
|
+
getContinuity(filePath2, currentWriter) {
|
|
224258
|
+
const prev = this.writers.get(filePath2);
|
|
224110
224259
|
if (prev === void 0 || prev === currentWriter) return "clean";
|
|
224111
224260
|
return "mixed";
|
|
224112
224261
|
}
|
|
224113
224262
|
/** Mark a file as having been written by bash (external/black-box writer). */
|
|
224114
|
-
markExternalWrite(
|
|
224115
|
-
this.writers.set(
|
|
224263
|
+
markExternalWrite(filePath2) {
|
|
224264
|
+
this.writers.set(filePath2, "bash");
|
|
224116
224265
|
return { anchorInvalidated: true };
|
|
224117
224266
|
}
|
|
224118
224267
|
};
|
|
@@ -224126,11 +224275,11 @@ var FileSystemCheckpointStore = class {
|
|
|
224126
224275
|
this.baseDir = baseDir;
|
|
224127
224276
|
mkdirSync7(this.baseDir, { recursive: true });
|
|
224128
224277
|
}
|
|
224129
|
-
safeName(
|
|
224130
|
-
return
|
|
224278
|
+
safeName(filePath2) {
|
|
224279
|
+
return filePath2.replace(/[\/\\:]/g, "_").replace(/^_+/, "");
|
|
224131
224280
|
}
|
|
224132
|
-
findCheckpointDir(
|
|
224133
|
-
const prefix = this.safeName(
|
|
224281
|
+
findCheckpointDir(filePath2) {
|
|
224282
|
+
const prefix = this.safeName(filePath2) + "-";
|
|
224134
224283
|
if (!existsSync8(this.baseDir)) return null;
|
|
224135
224284
|
let entries;
|
|
224136
224285
|
try {
|
|
@@ -224158,8 +224307,8 @@ var FileSystemCheckpointStore = class {
|
|
|
224158
224307
|
writeFileSync7(join7(dir, "original"), content);
|
|
224159
224308
|
}
|
|
224160
224309
|
}
|
|
224161
|
-
load(
|
|
224162
|
-
const dir = this.findCheckpointDir(
|
|
224310
|
+
load(filePath2) {
|
|
224311
|
+
const dir = this.findCheckpointDir(filePath2);
|
|
224163
224312
|
if (!dir) return null;
|
|
224164
224313
|
const metaPath = join7(dir, "meta.json");
|
|
224165
224314
|
const originalPath = join7(dir, "original");
|
|
@@ -224167,8 +224316,8 @@ var FileSystemCheckpointStore = class {
|
|
|
224167
224316
|
const content = existsSync8(originalPath) ? readFileSync7(originalPath) : null;
|
|
224168
224317
|
return { meta, content };
|
|
224169
224318
|
}
|
|
224170
|
-
delete(
|
|
224171
|
-
const dir = this.findCheckpointDir(
|
|
224319
|
+
delete(filePath2) {
|
|
224320
|
+
const dir = this.findCheckpointDir(filePath2);
|
|
224172
224321
|
if (dir) {
|
|
224173
224322
|
rmSync(dir, { recursive: true, force: true });
|
|
224174
224323
|
}
|
|
@@ -224221,27 +224370,27 @@ var SnapshotStore = class {
|
|
|
224221
224370
|
* Record a snapshot of a file. Called after read_file returns hashed content
|
|
224222
224371
|
* (so the model receives the file_version and can use it for later edits).
|
|
224223
224372
|
*/
|
|
224224
|
-
record(
|
|
224225
|
-
const key = this.makeKey(
|
|
224373
|
+
record(filePath2, fileVersion, content) {
|
|
224374
|
+
const key = this.makeKey(filePath2, fileVersion);
|
|
224226
224375
|
const existing = this.lruKeys.indexOf(key);
|
|
224227
224376
|
if (existing >= 0) {
|
|
224228
224377
|
this.lruKeys.splice(existing, 1);
|
|
224229
224378
|
this.lruKeys.push(key);
|
|
224230
|
-
const entries2 = this.byFile.get(
|
|
224379
|
+
const entries2 = this.byFile.get(filePath2);
|
|
224231
224380
|
const entry2 = entries2.find((e) => e.fileVersion === fileVersion);
|
|
224232
224381
|
if (entry2) entry2.timestamp = Date.now();
|
|
224233
224382
|
return;
|
|
224234
224383
|
}
|
|
224235
224384
|
const entry = {
|
|
224236
|
-
filePath,
|
|
224385
|
+
filePath: filePath2,
|
|
224237
224386
|
fileVersion,
|
|
224238
224387
|
content,
|
|
224239
224388
|
timestamp: Date.now()
|
|
224240
224389
|
};
|
|
224241
|
-
let entries = this.byFile.get(
|
|
224390
|
+
let entries = this.byFile.get(filePath2);
|
|
224242
224391
|
if (!entries) {
|
|
224243
224392
|
entries = [];
|
|
224244
|
-
this.byFile.set(
|
|
224393
|
+
this.byFile.set(filePath2, entries);
|
|
224245
224394
|
}
|
|
224246
224395
|
entries.unshift(entry);
|
|
224247
224396
|
while (entries.length > this.maxSnapshotsPerFile) {
|
|
@@ -224264,12 +224413,12 @@ var SnapshotStore = class {
|
|
|
224264
224413
|
* Look up a snapshot by file path and version.
|
|
224265
224414
|
* Returns the full file content or null if not found.
|
|
224266
224415
|
*/
|
|
224267
|
-
lookup(
|
|
224268
|
-
const entries = this.byFile.get(
|
|
224416
|
+
lookup(filePath2, fileVersion) {
|
|
224417
|
+
const entries = this.byFile.get(filePath2);
|
|
224269
224418
|
if (!entries) return null;
|
|
224270
224419
|
const entry = entries.find((e) => e.fileVersion === fileVersion);
|
|
224271
224420
|
if (!entry) return null;
|
|
224272
|
-
const key = this.makeKey(
|
|
224421
|
+
const key = this.makeKey(filePath2, fileVersion);
|
|
224273
224422
|
const idx = this.lruKeys.indexOf(key);
|
|
224274
224423
|
if (idx >= 0) {
|
|
224275
224424
|
this.lruKeys.splice(idx, 1);
|
|
@@ -224281,13 +224430,13 @@ var SnapshotStore = class {
|
|
|
224281
224430
|
/**
|
|
224282
224431
|
* Remove all snapshots for a file (called after successful write_file / overwrite_file).
|
|
224283
224432
|
*/
|
|
224284
|
-
invalidate(
|
|
224285
|
-
const entries = this.byFile.get(
|
|
224433
|
+
invalidate(filePath2) {
|
|
224434
|
+
const entries = this.byFile.get(filePath2);
|
|
224286
224435
|
if (!entries) return;
|
|
224287
224436
|
for (const e of entries) {
|
|
224288
224437
|
this.removeFromLru(this.makeKey(e.filePath, e.fileVersion));
|
|
224289
224438
|
}
|
|
224290
|
-
this.byFile.delete(
|
|
224439
|
+
this.byFile.delete(filePath2);
|
|
224291
224440
|
}
|
|
224292
224441
|
/** Remove all snapshots. */
|
|
224293
224442
|
clear() {
|
|
@@ -224299,8 +224448,8 @@ var SnapshotStore = class {
|
|
|
224299
224448
|
return this.lruKeys.length;
|
|
224300
224449
|
}
|
|
224301
224450
|
// --- Private helpers ---
|
|
224302
|
-
makeKey(
|
|
224303
|
-
return `${
|
|
224451
|
+
makeKey(filePath2, fileVersion) {
|
|
224452
|
+
return `${filePath2}::${fileVersion}`;
|
|
224304
224453
|
}
|
|
224305
224454
|
parseKey(key) {
|
|
224306
224455
|
const idx = key.lastIndexOf("::");
|
|
@@ -225406,17 +225555,17 @@ function buildDiffPreview(snapshotLines, expectedLines, currentLines, patch) {
|
|
|
225406
225555
|
|
|
225407
225556
|
// src/drivers/edit/undo-store.ts
|
|
225408
225557
|
var undoSnapshots = /* @__PURE__ */ new Map();
|
|
225409
|
-
function captureUndoSnapshot(
|
|
225410
|
-
undoSnapshots.set(
|
|
225558
|
+
function captureUndoSnapshot(filePath2, content) {
|
|
225559
|
+
undoSnapshots.set(filePath2, content);
|
|
225411
225560
|
}
|
|
225412
|
-
function getUndoSnapshot(
|
|
225413
|
-
return undoSnapshots.get(
|
|
225561
|
+
function getUndoSnapshot(filePath2) {
|
|
225562
|
+
return undoSnapshots.get(filePath2);
|
|
225414
225563
|
}
|
|
225415
|
-
function clearUndoSnapshot(
|
|
225416
|
-
undoSnapshots.delete(
|
|
225564
|
+
function clearUndoSnapshot(filePath2) {
|
|
225565
|
+
undoSnapshots.delete(filePath2);
|
|
225417
225566
|
}
|
|
225418
|
-
function hasUndoSnapshot(
|
|
225419
|
-
return undoSnapshots.has(
|
|
225567
|
+
function hasUndoSnapshot(filePath2) {
|
|
225568
|
+
return undoSnapshots.has(filePath2);
|
|
225420
225569
|
}
|
|
225421
225570
|
|
|
225422
225571
|
// src/drivers/edit/syntax-validate.ts
|
|
@@ -225430,11 +225579,11 @@ var SUPPORTED_EXTENSIONS = /* @__PURE__ */ new Set([
|
|
|
225430
225579
|
".html",
|
|
225431
225580
|
".json"
|
|
225432
225581
|
]);
|
|
225433
|
-
function isSyntaxCheckSupported(
|
|
225434
|
-
return SUPPORTED_EXTENSIONS.has(extname(
|
|
225582
|
+
function isSyntaxCheckSupported(filePath2) {
|
|
225583
|
+
return SUPPORTED_EXTENSIONS.has(extname(filePath2).toLowerCase());
|
|
225435
225584
|
}
|
|
225436
|
-
function getSyntaxTarget(
|
|
225437
|
-
const ext = extname(
|
|
225585
|
+
function getSyntaxTarget(filePath2) {
|
|
225586
|
+
const ext = extname(filePath2).toLowerCase();
|
|
225438
225587
|
switch (ext) {
|
|
225439
225588
|
case ".js":
|
|
225440
225589
|
return { kind: "js" };
|
|
@@ -225465,8 +225614,8 @@ async function getTypeScript() {
|
|
|
225465
225614
|
}
|
|
225466
225615
|
return _tsModule;
|
|
225467
225616
|
}
|
|
225468
|
-
async function validateSyntax(
|
|
225469
|
-
const target = getSyntaxTarget(
|
|
225617
|
+
async function validateSyntax(filePath2, content) {
|
|
225618
|
+
const target = getSyntaxTarget(filePath2);
|
|
225470
225619
|
if (!target) {
|
|
225471
225620
|
return { valid: true };
|
|
225472
225621
|
}
|
|
@@ -225810,7 +225959,7 @@ var editTool = {
|
|
|
225810
225959
|
};
|
|
225811
225960
|
}
|
|
225812
225961
|
if (file_path && !path) {
|
|
225813
|
-
_editLogger.warn("
|
|
225962
|
+
_editLogger.warn("Edit", "file_path is deprecated, use path instead");
|
|
225814
225963
|
}
|
|
225815
225964
|
const resolved = resolve4(effectivePath);
|
|
225816
225965
|
if (!await fileExists3(resolved)) {
|
|
@@ -226738,10 +226887,10 @@ function stripBomAndDecode(buf) {
|
|
|
226738
226887
|
}
|
|
226739
226888
|
return buf.toString("utf8");
|
|
226740
226889
|
}
|
|
226741
|
-
function parseSkillManifest(
|
|
226890
|
+
function parseSkillManifest(filePath2, source) {
|
|
226742
226891
|
let raw;
|
|
226743
226892
|
try {
|
|
226744
|
-
const buf = readFileSync9(
|
|
226893
|
+
const buf = readFileSync9(filePath2);
|
|
226745
226894
|
raw = stripBomAndDecode(buf);
|
|
226746
226895
|
} catch {
|
|
226747
226896
|
return null;
|
|
@@ -226758,7 +226907,7 @@ function parseSkillManifest(filePath, source) {
|
|
|
226758
226907
|
tools: parsed.tools,
|
|
226759
226908
|
instructions: body || void 0,
|
|
226760
226909
|
source,
|
|
226761
|
-
path:
|
|
226910
|
+
path: filePath2
|
|
226762
226911
|
};
|
|
226763
226912
|
}
|
|
226764
226913
|
function parseFrontmatter(text) {
|
|
@@ -227053,10 +227202,10 @@ function stripBomAndDecode2(buf) {
|
|
|
227053
227202
|
function normalizeName(name) {
|
|
227054
227203
|
return name.toLowerCase().replace(/\s+/g, "");
|
|
227055
227204
|
}
|
|
227056
|
-
function parseCommandFile(
|
|
227205
|
+
function parseCommandFile(filePath2, source, derivedName) {
|
|
227057
227206
|
let raw;
|
|
227058
227207
|
try {
|
|
227059
|
-
const buf = readFileSync10(
|
|
227208
|
+
const buf = readFileSync10(filePath2);
|
|
227060
227209
|
raw = stripBomAndDecode2(buf);
|
|
227061
227210
|
} catch {
|
|
227062
227211
|
return null;
|
|
@@ -227070,7 +227219,7 @@ function parseCommandFile(filePath, source, derivedName) {
|
|
|
227070
227219
|
if (!parsed.description) return null;
|
|
227071
227220
|
if (parsed.name !== void 0 && normalizeName(parsed.name) !== normalizeName(derivedName)) {
|
|
227072
227221
|
console.warn(
|
|
227073
|
-
`[commands] Skipping ${
|
|
227222
|
+
`[commands] Skipping ${filePath2}: frontmatter name "${parsed.name}" does not match path-derived name "${derivedName}"`
|
|
227074
227223
|
);
|
|
227075
227224
|
return null;
|
|
227076
227225
|
}
|
|
@@ -227079,7 +227228,7 @@ function parseCommandFile(filePath, source, derivedName) {
|
|
|
227079
227228
|
description: parsed.description,
|
|
227080
227229
|
body,
|
|
227081
227230
|
source,
|
|
227082
|
-
path:
|
|
227231
|
+
path: filePath2
|
|
227083
227232
|
};
|
|
227084
227233
|
}
|
|
227085
227234
|
function parseFrontmatter2(text) {
|
|
@@ -227273,10 +227422,10 @@ var PermissionManager = class {
|
|
|
227273
227422
|
const toolName = context.toolCall.name;
|
|
227274
227423
|
const argsStr = JSON.stringify(context.args);
|
|
227275
227424
|
if ((toolName === "read_file" || toolName === "write_file") && this.denyRegexes.length > 0) {
|
|
227276
|
-
const
|
|
227277
|
-
if (
|
|
227425
|
+
const filePath2 = context.args?.path;
|
|
227426
|
+
if (filePath2) {
|
|
227278
227427
|
for (const { pattern, regex } of this.denyRegexes) {
|
|
227279
|
-
if (regex.test(
|
|
227428
|
+
if (regex.test(filePath2)) {
|
|
227280
227429
|
return { block: true, reason: `Denied by file pattern: ${pattern}` };
|
|
227281
227430
|
}
|
|
227282
227431
|
}
|
|
@@ -227688,6 +227837,7 @@ var MCPClient = class {
|
|
|
227688
227837
|
if (this.closing) return;
|
|
227689
227838
|
if (!this.closed) {
|
|
227690
227839
|
this.closed = true;
|
|
227840
|
+
this.emit({ type: "disconnected", serverName: this.config.name, reason: `MCP server "${this.config.name}" exited with code ${code}` });
|
|
227691
227841
|
setImmediate(() => {
|
|
227692
227842
|
const stderr = stderrBuf.trim().slice(0, 500);
|
|
227693
227843
|
const detail = stderr ? `: ${stderr}` : "";
|
|
@@ -227695,6 +227845,14 @@ var MCPClient = class {
|
|
|
227695
227845
|
});
|
|
227696
227846
|
}
|
|
227697
227847
|
});
|
|
227848
|
+
this.process.on("error", (err) => {
|
|
227849
|
+
if (this.closing) return;
|
|
227850
|
+
if (!this.closed) {
|
|
227851
|
+
this.closed = true;
|
|
227852
|
+
this.emit({ type: "disconnected", serverName: this.config.name, reason: `MCP server "${this.config.name}" error: ${err.message}` });
|
|
227853
|
+
this.rejectAllPending(new Error(`MCP server "${this.config.name}" error: ${err.message}`));
|
|
227854
|
+
}
|
|
227855
|
+
});
|
|
227698
227856
|
this.process.on("error", (err) => {
|
|
227699
227857
|
if (this.closing) return;
|
|
227700
227858
|
if (!this.closed) {
|
|
@@ -227767,11 +227925,18 @@ var MCPClient = class {
|
|
|
227767
227925
|
res.on("end", () => {
|
|
227768
227926
|
if (!this.closed) {
|
|
227769
227927
|
this.closed = true;
|
|
227928
|
+
this.emit({ type: "disconnected", serverName: this.config.name, reason: `MCP server "${this.config.name}" SSE connection closed` });
|
|
227770
227929
|
this.rejectAllPending(new Error(`MCP server "${this.config.name}" SSE connection closed`));
|
|
227771
227930
|
}
|
|
227772
227931
|
});
|
|
227773
227932
|
res.on("error", (err) => {
|
|
227774
|
-
|
|
227933
|
+
if (!this.closed) {
|
|
227934
|
+
this.closed = true;
|
|
227935
|
+
this.emit({ type: "disconnected", serverName: this.config.name, reason: `MCP server "${this.config.name}" SSE error: ${err.message}` });
|
|
227936
|
+
this.rejectAllPending(new Error(`MCP server "${this.config.name}" SSE error: ${err.message}`));
|
|
227937
|
+
} else {
|
|
227938
|
+
reject(new Error(`MCP server "${this.config.name}" SSE error: ${err.message}`));
|
|
227939
|
+
}
|
|
227775
227940
|
});
|
|
227776
227941
|
}
|
|
227777
227942
|
);
|
|
@@ -227999,7 +228164,7 @@ var MCPClient = class {
|
|
|
227999
228164
|
return;
|
|
228000
228165
|
}
|
|
228001
228166
|
if (this.resolvedTransport === "streamable-http") {
|
|
228002
|
-
this.
|
|
228167
|
+
this.sendHttpWithSessionRecovery(this.config.url, { jsonrpc: "2.0", id, method, params: finalParams }, id).then((response) => {
|
|
228003
228168
|
const entry2 = this.pending.get(id);
|
|
228004
228169
|
if (!entry2) return;
|
|
228005
228170
|
if (response.statusCode >= 400) {
|
|
@@ -228185,6 +228350,30 @@ var MCPClient = class {
|
|
|
228185
228350
|
}
|
|
228186
228351
|
return headers;
|
|
228187
228352
|
}
|
|
228353
|
+
async sendHttpWithSessionRecovery(url, payload, id) {
|
|
228354
|
+
const response = await this.sendHttpMessage(url, payload, true, true);
|
|
228355
|
+
const newSessionId = this.getHeader(response.headers, "mcp-session-id");
|
|
228356
|
+
if (newSessionId && newSessionId !== this.sessionId) {
|
|
228357
|
+
this.sessionId = newSessionId;
|
|
228358
|
+
}
|
|
228359
|
+
const isSessionExpired = (response.statusCode === 404 || response.statusCode === 410) && !this.getHeader(response.headers, "mcp-session-id");
|
|
228360
|
+
if (isSessionExpired && !this.closed) {
|
|
228361
|
+
try {
|
|
228362
|
+
await this.connectStreamableHttp();
|
|
228363
|
+
const retryResponse = await this.sendHttpMessage(url, payload, true, true);
|
|
228364
|
+
const retrySessionId = this.getHeader(retryResponse.headers, "mcp-session-id");
|
|
228365
|
+
if (retrySessionId) {
|
|
228366
|
+
this.sessionId = retrySessionId;
|
|
228367
|
+
}
|
|
228368
|
+
return retryResponse;
|
|
228369
|
+
} catch (reinitErr) {
|
|
228370
|
+
this.closed = true;
|
|
228371
|
+
this.emit({ type: "disconnected", serverName: this.config.name, reason: `MCP session recovery failed: ${reinitErr.message}` });
|
|
228372
|
+
throw reinitErr;
|
|
228373
|
+
}
|
|
228374
|
+
}
|
|
228375
|
+
return response;
|
|
228376
|
+
}
|
|
228188
228377
|
async sendHttpMessage(url, payload, isRequest, includeContentType) {
|
|
228189
228378
|
const parsed = new URL(url);
|
|
228190
228379
|
const requester = parsed.protocol === "https:" ? httpsRequest : httpRequest;
|
|
@@ -228362,6 +228551,20 @@ function normalizeHtmlMimeType(mimeType) {
|
|
|
228362
228551
|
if (!mimeType) return "";
|
|
228363
228552
|
return mimeType.split(";").map((part) => part.trim()).sort().join(";");
|
|
228364
228553
|
}
|
|
228554
|
+
function classifyError(err, transport, statusCode) {
|
|
228555
|
+
const msg = err.message ?? "";
|
|
228556
|
+
if (/ECONNREFUSED|ETIMEDOUT/i.test(msg)) return "transient";
|
|
228557
|
+
if (statusCode !== void 0) {
|
|
228558
|
+
if (statusCode === 502 || statusCode === 503 || statusCode === 504) return "transient";
|
|
228559
|
+
if (statusCode === 401 || statusCode === 403) return "permanent";
|
|
228560
|
+
if (statusCode === 404 || statusCode === 410) return "session_expired";
|
|
228561
|
+
}
|
|
228562
|
+
if (/ENOTFOUND/i.test(msg)) return "permanent";
|
|
228563
|
+
if (transport === "stdio" && /exited/i.test(msg)) return "transient";
|
|
228564
|
+
if (transport === "sse" && /connection closed/i.test(msg)) return "transient";
|
|
228565
|
+
if (/invalid|no command|no url/i.test(msg)) return "permanent";
|
|
228566
|
+
return "transient";
|
|
228567
|
+
}
|
|
228365
228568
|
var MCPManager = class {
|
|
228366
228569
|
constructor(configs) {
|
|
228367
228570
|
this.configs = configs;
|
|
@@ -228487,37 +228690,66 @@ var MCPManager = class {
|
|
|
228487
228690
|
if (this.driverRegistry) {
|
|
228488
228691
|
this.driverRegistry.unregister(mcpDriverName(name));
|
|
228489
228692
|
}
|
|
228490
|
-
state.status = "
|
|
228491
|
-
|
|
228492
|
-
|
|
228493
|
-
|
|
228494
|
-
|
|
228495
|
-
|
|
228496
|
-
|
|
228497
|
-
|
|
228498
|
-
|
|
228499
|
-
|
|
228500
|
-
|
|
228501
|
-
|
|
228502
|
-
|
|
228503
|
-
|
|
228504
|
-
|
|
228505
|
-
|
|
228506
|
-
|
|
228507
|
-
|
|
228508
|
-
|
|
228509
|
-
|
|
228510
|
-
|
|
228693
|
+
state.status = "reconnecting";
|
|
228694
|
+
const client = new MCPClient(cfg);
|
|
228695
|
+
client.onEvent((event) => this.handleClientEvent(event));
|
|
228696
|
+
await client.connect();
|
|
228697
|
+
this.clients.set(name, client);
|
|
228698
|
+
const tools = await client.listTools();
|
|
228699
|
+
this.registerDriver(name, tools);
|
|
228700
|
+
state.status = "connected";
|
|
228701
|
+
state.error = void 0;
|
|
228702
|
+
state.toolCount = tools.length;
|
|
228703
|
+
state.negotiatedProtocolVersion = client.getNegotiatedProtocolVersion() ?? void 0;
|
|
228704
|
+
state.resolvedTransport = client.getResolvedTransport();
|
|
228705
|
+
state.compatibilityMode = client.getCompatibilityMode();
|
|
228706
|
+
state.refreshState = "idle";
|
|
228707
|
+
state.refreshError = void 0;
|
|
228708
|
+
state.lastRefreshAt = Date.now();
|
|
228709
|
+
return true;
|
|
228710
|
+
}
|
|
228711
|
+
reconnectTimers = /* @__PURE__ */ new Map();
|
|
228712
|
+
scheduleReconnect(name, attempt) {
|
|
228713
|
+
const state = this.states.get(name);
|
|
228714
|
+
if (!state) return;
|
|
228715
|
+
if (state.status === "disconnected") return;
|
|
228716
|
+
if (attempt >= 10) {
|
|
228717
|
+
state.status = "error";
|
|
228718
|
+
state.error = "Reconnect attempts exhausted";
|
|
228719
|
+
state.refreshState = "error";
|
|
228720
|
+
state.refreshError = "Reconnect attempts exhausted";
|
|
228721
|
+
this.emit({ type: "tools_refresh_failed", serverName: name, error: "Reconnect attempts exhausted" });
|
|
228722
|
+
return;
|
|
228723
|
+
}
|
|
228724
|
+
state.status = "reconnecting";
|
|
228725
|
+
const delay = Math.min(3e4, 1e3 * Math.pow(2, attempt)) + Math.random() * 500;
|
|
228726
|
+
const timer = setTimeout(async () => {
|
|
228727
|
+
this.reconnectTimers.delete(name);
|
|
228728
|
+
try {
|
|
228511
228729
|
await this.reconnectServer(name);
|
|
228512
|
-
|
|
228513
|
-
|
|
228514
|
-
|
|
228515
|
-
|
|
228516
|
-
|
|
228730
|
+
state.refreshState = "idle";
|
|
228731
|
+
state.refreshError = void 0;
|
|
228732
|
+
this.emit({ type: "tools_refreshed", serverName: name, toolCount: state.toolCount });
|
|
228733
|
+
} catch (err) {
|
|
228734
|
+
const cfg = this.configs.find((c2) => c2.name === name);
|
|
228735
|
+
const errorClass = classifyError(err, cfg?.transport ?? "stdio");
|
|
228736
|
+
if (errorClass === "permanent" || errorClass === "session_expired") {
|
|
228737
|
+
if (errorClass === "session_expired") {
|
|
228738
|
+
this.scheduleReconnect(name, 0);
|
|
228739
|
+
return;
|
|
228740
|
+
}
|
|
228741
|
+
state.status = "error";
|
|
228742
|
+
state.error = err.message ?? "Unknown error";
|
|
228743
|
+
state.refreshState = "error";
|
|
228744
|
+
state.refreshError = err.message ?? "Unknown error";
|
|
228745
|
+
state.toolCount = 0;
|
|
228746
|
+
this.emit({ type: "tools_refresh_failed", serverName: name, error: err.message ?? "Unknown error" });
|
|
228747
|
+
return;
|
|
228748
|
+
}
|
|
228749
|
+
this.scheduleReconnect(name, attempt + 1);
|
|
228517
228750
|
}
|
|
228518
|
-
|
|
228519
|
-
|
|
228520
|
-
}
|
|
228751
|
+
}, delay);
|
|
228752
|
+
this.reconnectTimers.set(name, timer);
|
|
228521
228753
|
}
|
|
228522
228754
|
async registerDrivers(registry) {
|
|
228523
228755
|
this.driverRegistry = registry;
|
|
@@ -228533,7 +228765,7 @@ var MCPManager = class {
|
|
|
228533
228765
|
} catch (err) {
|
|
228534
228766
|
const state = this.states.get(name);
|
|
228535
228767
|
if (state.status === "connected" || state.status === "error") {
|
|
228536
|
-
|
|
228768
|
+
this.scheduleReconnect(name, 0);
|
|
228537
228769
|
} else {
|
|
228538
228770
|
state.status = "error";
|
|
228539
228771
|
state.error = err.message ?? "Unknown error";
|
|
@@ -228559,6 +228791,10 @@ var MCPManager = class {
|
|
|
228559
228791
|
})
|
|
228560
228792
|
);
|
|
228561
228793
|
this.clients.clear();
|
|
228794
|
+
for (const timer of this.reconnectTimers.values()) {
|
|
228795
|
+
clearTimeout(timer);
|
|
228796
|
+
}
|
|
228797
|
+
this.reconnectTimers.clear();
|
|
228562
228798
|
}
|
|
228563
228799
|
async connectServer(name) {
|
|
228564
228800
|
const existing = this.clients.get(name);
|
|
@@ -228726,6 +228962,10 @@ var MCPManager = class {
|
|
|
228726
228962
|
if (event.type === "resources_list_changed") {
|
|
228727
228963
|
state.lastRefreshAt = Date.now();
|
|
228728
228964
|
}
|
|
228965
|
+
if (event.type === "disconnected") {
|
|
228966
|
+
state.status = "reconnecting";
|
|
228967
|
+
this.scheduleReconnect(event.serverName, 0);
|
|
228968
|
+
}
|
|
228729
228969
|
}
|
|
228730
228970
|
for (const listener of this.eventListeners) {
|
|
228731
228971
|
listener(event);
|
|
@@ -229492,9 +229732,9 @@ var ConversationView = class {
|
|
|
229492
229732
|
mkdirSync8(cacheDir, { recursive: true });
|
|
229493
229733
|
const ext = displayMimeType.split("/")[1] || "png";
|
|
229494
229734
|
const filename = `${Date.now()}.${ext}`;
|
|
229495
|
-
const
|
|
229496
|
-
writeFileSync9(
|
|
229497
|
-
this.pushText(c.dim(`[image: ${
|
|
229735
|
+
const filePath2 = join16(cacheDir, filename);
|
|
229736
|
+
writeFileSync9(filePath2, Buffer.from(displayData, "base64"));
|
|
229737
|
+
this.pushText(c.dim(`[image: ${filePath2}]`));
|
|
229498
229738
|
if (format !== "webp") {
|
|
229499
229739
|
try {
|
|
229500
229740
|
const img = new Image(displayData, displayMimeType, this.imageTheme, {
|
|
@@ -229913,6 +230153,13 @@ var FileTracker = class {
|
|
|
229913
230153
|
getDisplayPaths() {
|
|
229914
230154
|
return [...this.entries.values()];
|
|
229915
230155
|
}
|
|
230156
|
+
/** Reverse lookup: return the absolute path for a given display path, or undefined. */
|
|
230157
|
+
getAbsPath(displayPath) {
|
|
230158
|
+
for (const [absPath, dp] of this.entries) {
|
|
230159
|
+
if (dp === displayPath) return absPath;
|
|
230160
|
+
}
|
|
230161
|
+
return void 0;
|
|
230162
|
+
}
|
|
229916
230163
|
/** Clear all tracked files. */
|
|
229917
230164
|
clear() {
|
|
229918
230165
|
this.entries.clear();
|
|
@@ -230008,6 +230255,19 @@ function formatCost(total) {
|
|
|
230008
230255
|
if (total >= 0.01) return `$${total.toFixed(4)}`;
|
|
230009
230256
|
return `\xA2${(total * 100).toFixed(2)}`;
|
|
230010
230257
|
}
|
|
230258
|
+
function findFileMarkerAt(text, cursorLine, cursorCol) {
|
|
230259
|
+
const lines = text.split("\n");
|
|
230260
|
+
if (cursorLine < 0 || cursorLine >= lines.length) return void 0;
|
|
230261
|
+
const line = lines[cursorLine];
|
|
230262
|
+
const re = /\[file:([^\]]+)\]/g;
|
|
230263
|
+
let m;
|
|
230264
|
+
while ((m = re.exec(line)) !== null) {
|
|
230265
|
+
if (cursorCol >= m.index && cursorCol <= m.index + m[0].length) {
|
|
230266
|
+
return m[1];
|
|
230267
|
+
}
|
|
230268
|
+
}
|
|
230269
|
+
return void 0;
|
|
230270
|
+
}
|
|
230011
230271
|
var TuiApp = class {
|
|
230012
230272
|
deps;
|
|
230013
230273
|
terminal;
|
|
@@ -230050,6 +230310,10 @@ var TuiApp = class {
|
|
|
230050
230310
|
attachmentScrollOffset = 0;
|
|
230051
230311
|
// Pre-drained images: captured in input listener before Editor's onChange("") clears them
|
|
230052
230312
|
drainedSubmitImages = null;
|
|
230313
|
+
// Pre-drained files: captured in input listener before Editor's onChange("") clears them
|
|
230314
|
+
drainedSubmitFiles = null;
|
|
230315
|
+
// Absolute path shown when cursor is on a [file:xxx] placeholder
|
|
230316
|
+
hoveredFilePath = null;
|
|
230053
230317
|
lastPasteTime = 0;
|
|
230054
230318
|
// ── Kitty protocol multi-chunk buffer ──
|
|
230055
230319
|
// Kitty transmits large images in chunks. Accumulate base64 payloads here
|
|
@@ -230118,6 +230382,14 @@ var TuiApp = class {
|
|
|
230118
230382
|
}
|
|
230119
230383
|
}
|
|
230120
230384
|
}
|
|
230385
|
+
const cursor = this.editor.getCursor();
|
|
230386
|
+
const editorText = this.editor.getText();
|
|
230387
|
+
const hoveredDisplayPath = findFileMarkerAt(editorText, cursor.line, cursor.col);
|
|
230388
|
+
if (hoveredDisplayPath) {
|
|
230389
|
+
this.hoveredFilePath = this.fileTracker.getAbsPath(hoveredDisplayPath) ?? null;
|
|
230390
|
+
} else {
|
|
230391
|
+
this.hoveredFilePath = null;
|
|
230392
|
+
}
|
|
230121
230393
|
this.updateAttachmentBar();
|
|
230122
230394
|
};
|
|
230123
230395
|
this.tui.addInputListener((data) => {
|
|
@@ -230125,8 +230397,13 @@ var TuiApp = class {
|
|
|
230125
230397
|
if (pasteResult) {
|
|
230126
230398
|
return pasteResult;
|
|
230127
230399
|
}
|
|
230128
|
-
if ((matchesKey(data, Key.enter) || matchesKey(data, Key.return) || data === "\r" || data === "\n") &&
|
|
230129
|
-
|
|
230400
|
+
if ((matchesKey(data, Key.enter) || matchesKey(data, Key.return) || data === "\r" || data === "\n") && !this.processing) {
|
|
230401
|
+
if (this.imagePasteHandler.imageCount > 0) {
|
|
230402
|
+
this.drainedSubmitImages = this.imagePasteHandler.drainImages();
|
|
230403
|
+
}
|
|
230404
|
+
if (this.fileTracker.count > 0) {
|
|
230405
|
+
this.drainedSubmitFiles = this.fileTracker.drain();
|
|
230406
|
+
}
|
|
230130
230407
|
}
|
|
230131
230408
|
if (this.handleInput(data)) {
|
|
230132
230409
|
return { consume: true };
|
|
@@ -230458,7 +230735,9 @@ var TuiApp = class {
|
|
|
230458
230735
|
const chipsLine = parts.join(" ");
|
|
230459
230736
|
const scrollHint = this.attachmentScrollOffset > 0 ? ` +${this.attachmentScrollOffset} more` : "";
|
|
230460
230737
|
const hintLine = c.dim(`Ctrl+Shift+\u2190 \u2192 scroll${scrollHint} \xB7 Esc clear all`);
|
|
230461
|
-
this.
|
|
230738
|
+
const hoverLine = this.hoveredFilePath ? c.dim(`
|
|
230739
|
+
Path: ${this.hoveredFilePath}`) : "";
|
|
230740
|
+
this.imageStatus.setText(`${chipsLine}${hoverLine}
|
|
230462
230741
|
${hintLine}`);
|
|
230463
230742
|
this.tui.requestRender(true);
|
|
230464
230743
|
}
|
|
@@ -230921,7 +231200,8 @@ ${hintLine}`);
|
|
|
230921
231200
|
}
|
|
230922
231201
|
const hasText = text.length > 0;
|
|
230923
231202
|
const hasImages = Boolean(images?.length);
|
|
230924
|
-
const fileRefs = this.fileTracker.drain();
|
|
231203
|
+
const fileRefs = this.drainedSubmitFiles ?? this.fileTracker.drain();
|
|
231204
|
+
this.drainedSubmitFiles = null;
|
|
230925
231205
|
const hasFiles = fileRefs.length > 0;
|
|
230926
231206
|
if (!hasText && !hasImages && !hasFiles) {
|
|
230927
231207
|
const now = Date.now();
|
|
@@ -230935,7 +231215,7 @@ ${hintLine}`);
|
|
|
230935
231215
|
});
|
|
230936
231216
|
return;
|
|
230937
231217
|
}
|
|
230938
|
-
if (!hasText && !hasImages) {
|
|
231218
|
+
if (!hasText && !hasImages && !hasFiles) {
|
|
230939
231219
|
const now = Date.now();
|
|
230940
231220
|
if (now - this.lastPasteTime < 100) return;
|
|
230941
231221
|
this.lastPasteTime = now;
|
|
@@ -231022,30 +231302,41 @@ ${hintLine}`);
|
|
|
231022
231302
|
images = [...images ?? [], ...atImages];
|
|
231023
231303
|
}
|
|
231024
231304
|
if (hasFiles) {
|
|
231025
|
-
const
|
|
231026
|
-
|
|
231027
|
-
|
|
231028
|
-
|
|
231029
|
-
|
|
231030
|
-
|
|
231305
|
+
const imageRefs = fileRefs.filter((f) => isImagePath(f));
|
|
231306
|
+
const nonImageRefs = fileRefs.filter((f) => !isImagePath(f));
|
|
231307
|
+
const promptFilePaths = nonImageRefs.length > 0 ? [...nonImageRefs] : [];
|
|
231308
|
+
if (imageRefs.length > 0) {
|
|
231309
|
+
const dedupedImageRefs = imageRefs.filter((f) => !atPathAbsPaths.has(f));
|
|
231310
|
+
if (dedupedImageRefs.length > 0) {
|
|
231311
|
+
promptFilePaths.push(...dedupedImageRefs);
|
|
231312
|
+
const refsResolved = resolveFileRefs(this.deps.config.projectPath, dedupedImageRefs, this.deps.config.atFile ?? {});
|
|
231313
|
+
if (refsResolved.warnings.length > 0) {
|
|
231314
|
+
for (const warn of refsResolved.warnings) {
|
|
231315
|
+
this.conversation.addInfo(c.yellow(`${warn.path ?? ""}: ${warn.type}${warn.detail ? ` \u2014 ${warn.detail}` : ""}`));
|
|
231316
|
+
}
|
|
231317
|
+
}
|
|
231318
|
+
if (refsResolved.images.length > 0) {
|
|
231319
|
+
const refImages = refsResolved.images.map((img) => ({
|
|
231320
|
+
type: "image",
|
|
231321
|
+
data: img.data,
|
|
231322
|
+
mimeType: img.mimeType
|
|
231323
|
+
}));
|
|
231324
|
+
images = [...images ?? [], ...refImages];
|
|
231031
231325
|
}
|
|
231032
231326
|
}
|
|
231327
|
+
}
|
|
231328
|
+
if (promptFilePaths.length > 0) {
|
|
231329
|
+
const pathLines = promptFilePaths.map((f) => `- \`${f}\``).join("\n");
|
|
231033
231330
|
text = text ? `${text}
|
|
231034
|
-
|
|
231035
|
-
|
|
231036
|
-
|
|
231037
|
-
|
|
231038
|
-
data: img.data,
|
|
231039
|
-
mimeType: img.mimeType
|
|
231040
|
-
}));
|
|
231041
|
-
images = [...images ?? [], ...refImages];
|
|
231042
|
-
}
|
|
231331
|
+
|
|
231332
|
+
\u{1F4C1} Attached files:
|
|
231333
|
+
${pathLines}` : `\u{1F4C1} Attached files:
|
|
231334
|
+
${pathLines}`;
|
|
231043
231335
|
}
|
|
231044
231336
|
}
|
|
231045
|
-
|
|
231046
|
-
this.
|
|
231047
|
-
|
|
231048
|
-
);
|
|
231337
|
+
this.conversation.addInfo(
|
|
231338
|
+
c.dim(`${resolveModel(this.deps.config.provider, this.deps.config.modelId).name} does not support image input natively \u2014 using vision model or OCR.`)
|
|
231339
|
+
);
|
|
231049
231340
|
const imageIndicator = images ? c.dim(`[${images.length} image(s) attached]`) : "";
|
|
231050
231341
|
const userMessage = hasText ? imageIndicator ? `${text}
|
|
231051
231342
|
${imageIndicator}` : text : imageIndicator;
|
|
@@ -231262,8 +231553,10 @@ async function ocrImages(images, signal) {
|
|
|
231262
231553
|
}
|
|
231263
231554
|
|
|
231264
231555
|
// src/drivers/vision/client.ts
|
|
231556
|
+
init_logger();
|
|
231265
231557
|
init_models();
|
|
231266
231558
|
init_models();
|
|
231559
|
+
var _clog = new Logger({ type: "harness", id: process.env.DSCODE_RUNTIME_ID ?? "vision-client" });
|
|
231267
231560
|
function resolveVisionModel(visionConfig, fallbackApiKey, onWarning) {
|
|
231268
231561
|
if (!visionConfig?.provider || !visionConfig?.model) return null;
|
|
231269
231562
|
try {
|
|
@@ -231311,6 +231604,8 @@ async function describeImagesViaVisionModel(images, visionModel, apiKey, signal)
|
|
|
231311
231604
|
if (err instanceof DOMException && err.name === "AbortError") {
|
|
231312
231605
|
throw err;
|
|
231313
231606
|
}
|
|
231607
|
+
const errMsg = err instanceof Error ? err.message : String(err);
|
|
231608
|
+
_clog.warn("vision-client", `describeImages FAILED: ${errMsg}. images=${images.length}, totalBase64=${images.reduce((s, i) => s + (i.data?.length ?? 0), 0)}, img[0].mime=${images[0]?.mimeType ?? "?"}`);
|
|
231314
231609
|
throw err;
|
|
231315
231610
|
}
|
|
231316
231611
|
}
|
|
@@ -231344,12 +231639,14 @@ var ImagePipeline = class {
|
|
|
231344
231639
|
onProgress?.({ phase: "compressing", cachedRefs: [] });
|
|
231345
231640
|
const cachedRefs = await Promise.all(normalizedImages.map((img) => ImageCache.put(img)));
|
|
231346
231641
|
onProgress?.({ phase: "compressing", cachedRefs });
|
|
231642
|
+
const compressedRaw = await Promise.all(cachedRefs.map((ref) => ImageCache.get(ref)));
|
|
231643
|
+
const compressedImages = compressedRaw.every((img) => img !== null) ? compressedRaw : normalizedImages;
|
|
231347
231644
|
if (signal?.aborted) throw new DOMException("The operation was aborted", "AbortError");
|
|
231348
231645
|
const vision = resolveVisionModel(this.visionConfig, this.fallbackApiKey, this.onWarning);
|
|
231349
231646
|
if (vision) {
|
|
231350
231647
|
try {
|
|
231351
231648
|
onProgress?.({ phase: "describing", cachedRefs });
|
|
231352
|
-
const description = await describeImagesViaVisionModel(
|
|
231649
|
+
const description = await describeImagesViaVisionModel(compressedImages, vision.model, vision.apiKey, signal);
|
|
231353
231650
|
if (!description || description.trim().length === 0) {
|
|
231354
231651
|
throw new Error("Vision model returned empty description");
|
|
231355
231652
|
}
|
|
@@ -231366,13 +231663,14 @@ ${description}
|
|
|
231366
231663
|
if (err instanceof DOMException && err.name === "AbortError") {
|
|
231367
231664
|
throw err;
|
|
231368
231665
|
}
|
|
231369
|
-
|
|
231666
|
+
const errMsg = err instanceof Error ? err.message : String(err);
|
|
231667
|
+
this.onWarning(`Vision model failed: ${errMsg}. Falling back to OCR.`);
|
|
231370
231668
|
}
|
|
231371
231669
|
}
|
|
231372
231670
|
if (signal?.aborted) throw new DOMException("The operation was aborted", "AbortError");
|
|
231373
231671
|
try {
|
|
231374
231672
|
onProgress?.({ phase: "ocr", cachedRefs });
|
|
231375
|
-
const result = await ocrImages(
|
|
231673
|
+
const result = await ocrImages(compressedImages, signal);
|
|
231376
231674
|
onProgress?.({ phase: "done", cachedRefs });
|
|
231377
231675
|
if (result.hasText) {
|
|
231378
231676
|
const ocrText = text ? `${text}
|
|
@@ -231471,12 +231769,12 @@ var ConfigWatch = class {
|
|
|
231471
231769
|
|
|
231472
231770
|
// src/context/anchor-invalidation.ts
|
|
231473
231771
|
var pendingEvents = [];
|
|
231474
|
-
function recordInvalidation(
|
|
231475
|
-
const existing = pendingEvents.findIndex((e) => e.filePath ===
|
|
231772
|
+
function recordInvalidation(filePath2, lineCount, fileVersion) {
|
|
231773
|
+
const existing = pendingEvents.findIndex((e) => e.filePath === filePath2);
|
|
231476
231774
|
if (existing >= 0) {
|
|
231477
|
-
pendingEvents[existing] = { filePath, lineCount, fileVersion };
|
|
231775
|
+
pendingEvents[existing] = { filePath: filePath2, lineCount, fileVersion };
|
|
231478
231776
|
} else {
|
|
231479
|
-
pendingEvents.push({ filePath, lineCount, fileVersion });
|
|
231777
|
+
pendingEvents.push({ filePath: filePath2, lineCount, fileVersion });
|
|
231480
231778
|
}
|
|
231481
231779
|
}
|
|
231482
231780
|
function consumePendingNotices() {
|
|
@@ -231522,7 +231820,7 @@ var HarnessEventBus = class {
|
|
|
231522
231820
|
try {
|
|
231523
231821
|
handler(event);
|
|
231524
231822
|
} catch (err) {
|
|
231525
|
-
this.logger.error("
|
|
231823
|
+
this.logger.error("EventBus", `handler error for "${event.type}": ${String(err)}`);
|
|
231526
231824
|
}
|
|
231527
231825
|
}
|
|
231528
231826
|
}
|
|
@@ -231559,6 +231857,8 @@ var Harness = class {
|
|
|
231559
231857
|
shuttingDown = false;
|
|
231560
231858
|
turnIndex = 0;
|
|
231561
231859
|
visionAbortController = null;
|
|
231860
|
+
autoSaveTimer;
|
|
231861
|
+
lastSavedMessageCount = 0;
|
|
231562
231862
|
constructor(config, logger, debug) {
|
|
231563
231863
|
this.logger = logger;
|
|
231564
231864
|
this.configStore = new ConfigWatch(config);
|
|
@@ -231647,7 +231947,7 @@ var Harness = class {
|
|
|
231647
231947
|
await self.dumpDebugPrompt();
|
|
231648
231948
|
return self.contextManager.transform(msgs, signal);
|
|
231649
231949
|
} catch (err) {
|
|
231650
|
-
this.logger.error("
|
|
231950
|
+
this.logger.error("TransformContext", String(err));
|
|
231651
231951
|
return msgs;
|
|
231652
231952
|
}
|
|
231653
231953
|
},
|
|
@@ -231670,7 +231970,7 @@ var Harness = class {
|
|
|
231670
231970
|
}
|
|
231671
231971
|
}
|
|
231672
231972
|
} catch (err) {
|
|
231673
|
-
this.logger.error("
|
|
231973
|
+
this.logger.error("AfterToolCall", String(err));
|
|
231674
231974
|
}
|
|
231675
231975
|
if (_signal?.aborted) {
|
|
231676
231976
|
return { terminate: true };
|
|
@@ -231713,6 +232013,7 @@ var Harness = class {
|
|
|
231713
232013
|
const lastAssistantMsg = this.findLastAssistantMessage(msgs);
|
|
231714
232014
|
if (!lastAssistantMsg || lastAssistantMsg.stopReason !== "error") {
|
|
231715
232015
|
this.sessionManager.trySaveSession(this.agent);
|
|
232016
|
+
this.lastSavedMessageCount = this.agent.state.messages.length;
|
|
231716
232017
|
return;
|
|
231717
232018
|
}
|
|
231718
232019
|
const errorMsg = lastAssistantMsg.errorMessage ?? "Unknown model error";
|
|
@@ -231728,6 +232029,7 @@ var Harness = class {
|
|
|
231728
232029
|
this.events.emit({ type: "ui:error", text: `Model error: ${errorMsg}` });
|
|
231729
232030
|
this.events.emit({ type: "turn:error", error: errorMsg, attempt: attempt + 1, maxRetries });
|
|
231730
232031
|
this.sessionManager.trySaveSession(this.agent);
|
|
232032
|
+
this.lastSavedMessageCount = this.agent.state.messages.length;
|
|
231731
232033
|
return;
|
|
231732
232034
|
}
|
|
231733
232035
|
if (attempt >= maxRetries) {
|
|
@@ -231743,6 +232045,7 @@ var Harness = class {
|
|
|
231743
232045
|
this.events.emit({ type: "turn:error", error: errorMsg, attempt: attempt + 1, maxRetries });
|
|
231744
232046
|
this.events.emit({ type: "ui:error", text: "\u2717 All retries exhausted" });
|
|
231745
232047
|
this.sessionManager.trySaveSession(this.agent);
|
|
232048
|
+
this.lastSavedMessageCount = this.agent.state.messages.length;
|
|
231746
232049
|
return;
|
|
231747
232050
|
}
|
|
231748
232051
|
this.events.emit({
|
|
@@ -231761,6 +232064,24 @@ var Harness = class {
|
|
|
231761
232064
|
*/
|
|
231762
232065
|
saveSessionNow() {
|
|
231763
232066
|
this.sessionManager.trySaveSession(this.agent);
|
|
232067
|
+
this.lastSavedMessageCount = this.agent.state.messages.length;
|
|
232068
|
+
}
|
|
232069
|
+
/**
|
|
232070
|
+
* Start periodic auto-save (every 15s) during agent execution.
|
|
232071
|
+
* Only saves when new messages have been added since last save.
|
|
232072
|
+
*/
|
|
232073
|
+
startAutoSave() {
|
|
232074
|
+
this.autoSaveTimer = setInterval(() => {
|
|
232075
|
+
if (this.agent?.state?.messages) {
|
|
232076
|
+
const currentCount = this.agent.state.messages.length;
|
|
232077
|
+
if (currentCount !== this.lastSavedMessageCount) {
|
|
232078
|
+
this.logger.info("AutoSave", `Periodic auto-save (${currentCount} messages, was ${this.lastSavedMessageCount})`);
|
|
232079
|
+
this.sessionManager.trySaveSession(this.agent);
|
|
232080
|
+
this.lastSavedMessageCount = currentCount;
|
|
232081
|
+
}
|
|
232082
|
+
}
|
|
232083
|
+
}, 15e3);
|
|
232084
|
+
this.autoSaveTimer.unref();
|
|
231764
232085
|
}
|
|
231765
232086
|
findLastUserMessageIndex(messages) {
|
|
231766
232087
|
for (let i = messages.length - 1; i >= 0; i--) {
|
|
@@ -231909,6 +232230,7 @@ var Harness = class {
|
|
|
231909
232230
|
}));
|
|
231910
232231
|
}
|
|
231911
232232
|
this.sessionManager.trySaveSession(this.agent);
|
|
232233
|
+
this.lastSavedMessageCount = this.agent.state.messages.length;
|
|
231912
232234
|
const restoredImgs = [];
|
|
231913
232235
|
for (const ref of cachedRefs) {
|
|
231914
232236
|
const cached2 = ImageCache.getSync(ref);
|
|
@@ -231969,6 +232291,7 @@ var Harness = class {
|
|
|
231969
232291
|
this.toolRegistry.initialize(this.makeSkillTool());
|
|
231970
232292
|
this.agent.state.tools = this.toolRegistry.buildToolsForRequest();
|
|
231971
232293
|
}
|
|
232294
|
+
this.startAutoSave();
|
|
231972
232295
|
if (!this.config.apiKey) {
|
|
231973
232296
|
this.events.emit({ type: "ui:info", text: [
|
|
231974
232297
|
"Welcome to DSCode! To get started, configure your API key:",
|
|
@@ -232030,6 +232353,7 @@ var Harness = class {
|
|
|
232030
232353
|
return { success: false, error: `Path does not exist: ${resolvedPath}` };
|
|
232031
232354
|
}
|
|
232032
232355
|
this.sessionManager.trySaveSession(this.agent);
|
|
232356
|
+
this.lastSavedMessageCount = this.agent.state.messages.length;
|
|
232033
232357
|
process.chdir(resolvedPath);
|
|
232034
232358
|
this.configStore.setProjectPath(resolvedPath);
|
|
232035
232359
|
this.sessionManager.updateProjectPath(this.config.dataDir, resolvedPath);
|
|
@@ -232063,7 +232387,7 @@ var Harness = class {
|
|
|
232063
232387
|
this.ui.setMcpManager?.(this.mcpManager);
|
|
232064
232388
|
this.ui.pushMcpState?.();
|
|
232065
232389
|
} catch (err) {
|
|
232066
|
-
this.logger.error("
|
|
232390
|
+
this.logger.error("McpReload", String(err));
|
|
232067
232391
|
}
|
|
232068
232392
|
this.agent.state.tools = this.toolRegistry.buildToolsForRequest();
|
|
232069
232393
|
const memories = this.memoryManager.getRelevantMemories();
|
|
@@ -232073,7 +232397,12 @@ var Harness = class {
|
|
|
232073
232397
|
return { success: true };
|
|
232074
232398
|
}
|
|
232075
232399
|
async shutdown() {
|
|
232400
|
+
if (this.autoSaveTimer) {
|
|
232401
|
+
clearInterval(this.autoSaveTimer);
|
|
232402
|
+
this.autoSaveTimer = void 0;
|
|
232403
|
+
}
|
|
232076
232404
|
this.sessionManager.trySaveSession(this.agent);
|
|
232405
|
+
this.lastSavedMessageCount = this.agent.state.messages.length;
|
|
232077
232406
|
if (this.shuttingDown) return;
|
|
232078
232407
|
this.shuttingDown = true;
|
|
232079
232408
|
this.mcpEventUnsubscribe?.();
|
|
@@ -232086,14 +232415,14 @@ var Harness = class {
|
|
|
232086
232415
|
try {
|
|
232087
232416
|
await this.appHostManager.shutdown();
|
|
232088
232417
|
} catch (err) {
|
|
232089
|
-
this.logger.error("
|
|
232418
|
+
this.logger.error("AppHostShutdown", String(err));
|
|
232090
232419
|
}
|
|
232091
232420
|
}
|
|
232092
232421
|
if (this.mcpManager) {
|
|
232093
232422
|
try {
|
|
232094
232423
|
await this.mcpManager.shutdown();
|
|
232095
232424
|
} catch (err) {
|
|
232096
|
-
this.logger.error("
|
|
232425
|
+
this.logger.error("McpShutdown", String(err));
|
|
232097
232426
|
}
|
|
232098
232427
|
}
|
|
232099
232428
|
}
|
|
@@ -232185,13 +232514,13 @@ You have a \`skill\` tool available. When you decide to use a skill from the lis
|
|
|
232185
232514
|
const hash = String(prompt.length);
|
|
232186
232515
|
if (hash === this.debugPromptLastHash) return;
|
|
232187
232516
|
this.debugPromptLastHash = hash;
|
|
232188
|
-
const { mkdirSync:
|
|
232189
|
-
const { join:
|
|
232190
|
-
const dumpDir =
|
|
232191
|
-
|
|
232192
|
-
const
|
|
232193
|
-
|
|
232194
|
-
process.stderr.write("\n[dscode] --debug: system prompt dumped to " +
|
|
232517
|
+
const { mkdirSync: mkdirSync14, writeFileSync: writeFileSync16 } = await import("node:fs");
|
|
232518
|
+
const { join: join32 } = await import("node:path");
|
|
232519
|
+
const dumpDir = join32(this.config.projectPath, "dump");
|
|
232520
|
+
mkdirSync14(dumpDir, { recursive: true });
|
|
232521
|
+
const filePath2 = join32(dumpDir, "system-prompt.md");
|
|
232522
|
+
writeFileSync16(filePath2, prompt, "utf8");
|
|
232523
|
+
process.stderr.write("\n[dscode] --debug: system prompt dumped to " + filePath2 + " (" + prompt.length + " chars)\n\n");
|
|
232195
232524
|
}
|
|
232196
232525
|
makeSkillTool() {
|
|
232197
232526
|
const skillManager = this.skillManager;
|
|
@@ -232327,6 +232656,14 @@ You have a \`skill\` tool available. When you decide to use a skill from the lis
|
|
|
232327
232656
|
bindEvents() {
|
|
232328
232657
|
this.agent.subscribe((event) => {
|
|
232329
232658
|
switch (event.type) {
|
|
232659
|
+
case "message_end": {
|
|
232660
|
+
if (event.message?.role === "user") {
|
|
232661
|
+
this.logger.info("PreTurnSave", `Saving session pre-turn (${this.agent.state.messages.length} messages)`);
|
|
232662
|
+
this.sessionManager.trySaveSession(this.agent);
|
|
232663
|
+
this.lastSavedMessageCount = this.agent.state.messages.length;
|
|
232664
|
+
}
|
|
232665
|
+
break;
|
|
232666
|
+
}
|
|
232330
232667
|
case "message_update": {
|
|
232331
232668
|
const ev = event.assistantMessageEvent;
|
|
232332
232669
|
if (!ev) break;
|
|
@@ -232368,12 +232705,14 @@ You have a \`skill\` tool available. When you decide to use a skill from the lis
|
|
|
232368
232705
|
if (event.type === "agent_end") {
|
|
232369
232706
|
this.events.emit({ type: "processing:stop" });
|
|
232370
232707
|
this.sessionManager.trySaveSession(this.agent);
|
|
232708
|
+
this.lastSavedMessageCount = this.agent.state.messages.length;
|
|
232371
232709
|
}
|
|
232372
232710
|
if (event.type === "agent_start") {
|
|
232373
232711
|
this.events.emit({ type: "turn:streaming:start" });
|
|
232374
232712
|
}
|
|
232375
232713
|
if (event.type === "turn_end") {
|
|
232376
232714
|
this.sessionManager.trySaveSession(this.agent);
|
|
232715
|
+
this.lastSavedMessageCount = this.agent.state.messages.length;
|
|
232377
232716
|
const turnEndMsg = event.message;
|
|
232378
232717
|
const rawUsage = turnEndMsg?.usage;
|
|
232379
232718
|
this.events.emit({ type: "turn:end", stopReason: turnEndMsg?.stopReason, usage: rawUsage ? { input: rawUsage.input, output: rawUsage.output, cacheRead: rawUsage.cacheRead, cacheWrite: rawUsage.cacheWrite, total: rawUsage.totalTokens, cost: { total: rawUsage.cost.total } } : void 0 });
|
|
@@ -232385,8 +232724,9 @@ You have a \`skill\` tool available. When you decide to use a skill from the lis
|
|
|
232385
232724
|
}
|
|
232386
232725
|
}
|
|
232387
232726
|
} catch (err) {
|
|
232388
|
-
this.logger.error("
|
|
232727
|
+
this.logger.error("AgentEvent", String(err));
|
|
232389
232728
|
this.sessionManager.trySaveSession(this.agent);
|
|
232729
|
+
this.lastSavedMessageCount = this.agent.state.messages.length;
|
|
232390
232730
|
}
|
|
232391
232731
|
});
|
|
232392
232732
|
}
|
|
@@ -232481,6 +232821,132 @@ You have a \`skill\` tool available. When you decide to use a skill from the lis
|
|
|
232481
232821
|
|
|
232482
232822
|
// src/core/main.ts
|
|
232483
232823
|
init_logger();
|
|
232824
|
+
|
|
232825
|
+
// src/core/od-daemon.ts
|
|
232826
|
+
import { spawn as spawn2 } from "node:child_process";
|
|
232827
|
+
import { existsSync as existsSync24, readFileSync as readFileSync21, writeFileSync as writeFileSync14 } from "node:fs";
|
|
232828
|
+
import { homedir as homedir10 } from "node:os";
|
|
232829
|
+
import { join as join29 } from "node:path";
|
|
232830
|
+
function findProjectOd(odDir) {
|
|
232831
|
+
const expandedDir = expandTilde2(odDir);
|
|
232832
|
+
const odPath = join29(expandedDir, "node_modules", ".bin", "od");
|
|
232833
|
+
if (existsSync24(odPath)) return odPath;
|
|
232834
|
+
return null;
|
|
232835
|
+
}
|
|
232836
|
+
function resolveOdCommand(odDir, port) {
|
|
232837
|
+
const expandedDir = expandTilde2(odDir);
|
|
232838
|
+
const odPath = findProjectOd(odDir);
|
|
232839
|
+
if (odPath) {
|
|
232840
|
+
return { cmd: odPath, args: ["--port", String(port), "--no-open"], cwd: expandedDir };
|
|
232841
|
+
}
|
|
232842
|
+
return { cmd: "pnpm", args: ["tools-dev", "run", "web", "--", "--port", String(port), "--no-open"], cwd: expandedDir };
|
|
232843
|
+
}
|
|
232844
|
+
function startOdDaemon(odDir, odPort) {
|
|
232845
|
+
const { cmd, args, cwd } = resolveOdCommand(odDir, odPort);
|
|
232846
|
+
const child = spawn2(cmd, args, {
|
|
232847
|
+
cwd,
|
|
232848
|
+
stdio: "ignore",
|
|
232849
|
+
env: { ...process.env, OD_PORT: String(odPort) }
|
|
232850
|
+
});
|
|
232851
|
+
child.unref();
|
|
232852
|
+
return child;
|
|
232853
|
+
}
|
|
232854
|
+
async function waitForOdDaemon(port, timeoutMs = 3e4) {
|
|
232855
|
+
const start = Date.now();
|
|
232856
|
+
while (Date.now() - start < timeoutMs) {
|
|
232857
|
+
try {
|
|
232858
|
+
const res = await fetch(`http://127.0.0.1:${port}/api/projects`);
|
|
232859
|
+
if (res.status === 200) {
|
|
232860
|
+
console.log(`Open Design daemon ready on port ${port}`);
|
|
232861
|
+
return true;
|
|
232862
|
+
}
|
|
232863
|
+
} catch {
|
|
232864
|
+
}
|
|
232865
|
+
await new Promise((r) => setTimeout(r, 500));
|
|
232866
|
+
}
|
|
232867
|
+
console.warn(`Open Design daemon did not become healthy within ${timeoutMs / 1e3}s`);
|
|
232868
|
+
return false;
|
|
232869
|
+
}
|
|
232870
|
+
var cleanupHandlers = [];
|
|
232871
|
+
function runOdCleanup() {
|
|
232872
|
+
for (const handler of cleanupHandlers) {
|
|
232873
|
+
handler();
|
|
232874
|
+
}
|
|
232875
|
+
cleanupHandlers = [];
|
|
232876
|
+
}
|
|
232877
|
+
var cleanupHooksInstalled = false;
|
|
232878
|
+
function installCleanupHooks() {
|
|
232879
|
+
if (cleanupHooksInstalled) return;
|
|
232880
|
+
cleanupHooksInstalled = true;
|
|
232881
|
+
process.on("exit", runOdCleanup);
|
|
232882
|
+
process.on("SIGINT", runOdCleanup);
|
|
232883
|
+
process.on("SIGTERM", runOdCleanup);
|
|
232884
|
+
}
|
|
232885
|
+
function registerOdCleanup(odChild) {
|
|
232886
|
+
installCleanupHooks();
|
|
232887
|
+
const handler = () => {
|
|
232888
|
+
if (odChild.exitCode !== null || odChild.signalCode !== null) return;
|
|
232889
|
+
odChild.kill("SIGTERM");
|
|
232890
|
+
const forceKill = setTimeout(() => {
|
|
232891
|
+
if (odChild.exitCode === null && odChild.signalCode === null) {
|
|
232892
|
+
odChild.kill("SIGKILL");
|
|
232893
|
+
}
|
|
232894
|
+
}, 3e3);
|
|
232895
|
+
forceKill.unref();
|
|
232896
|
+
};
|
|
232897
|
+
cleanupHandlers.push(handler);
|
|
232898
|
+
}
|
|
232899
|
+
function expandTilde2(filePath2) {
|
|
232900
|
+
if (filePath2.startsWith("~")) {
|
|
232901
|
+
return join29(homedir10(), filePath2.slice(1));
|
|
232902
|
+
}
|
|
232903
|
+
return filePath2;
|
|
232904
|
+
}
|
|
232905
|
+
var MCP_PATH = join29(homedir10(), ".mcp.json");
|
|
232906
|
+
function ensureOdMcpEntry(odDir, odPort) {
|
|
232907
|
+
const expandedDir = expandTilde2(odDir);
|
|
232908
|
+
const daemonCliPath = join29(expandedDir, "apps", "daemon", "src", "cli.ts");
|
|
232909
|
+
const daemonUrl = `http://127.0.0.1:${odPort}`;
|
|
232910
|
+
let mcpConfig;
|
|
232911
|
+
try {
|
|
232912
|
+
if (existsSync24(MCP_PATH)) {
|
|
232913
|
+
const raw = readFileSync21(MCP_PATH, "utf8");
|
|
232914
|
+
mcpConfig = JSON.parse(raw);
|
|
232915
|
+
} else {
|
|
232916
|
+
mcpConfig = {};
|
|
232917
|
+
}
|
|
232918
|
+
} catch (e) {
|
|
232919
|
+
if (existsSync24(MCP_PATH)) {
|
|
232920
|
+
console.warn(
|
|
232921
|
+
`Cannot read ~/.mcp.json: ${e instanceof Error ? e.message : String(e)}`
|
|
232922
|
+
);
|
|
232923
|
+
return false;
|
|
232924
|
+
}
|
|
232925
|
+
mcpConfig = {};
|
|
232926
|
+
}
|
|
232927
|
+
const servers = mcpConfig.mcpServers ?? {};
|
|
232928
|
+
const existing = servers["open-design"];
|
|
232929
|
+
if (existing?.args?.[1] === daemonCliPath && existing?.args?.[4] === daemonUrl) {
|
|
232930
|
+
return true;
|
|
232931
|
+
}
|
|
232932
|
+
servers["open-design"] = {
|
|
232933
|
+
command: "npx",
|
|
232934
|
+
args: ["tsx", daemonCliPath, "mcp", "--daemon-url", daemonUrl]
|
|
232935
|
+
};
|
|
232936
|
+
mcpConfig.mcpServers = servers;
|
|
232937
|
+
try {
|
|
232938
|
+
writeFileSync14(MCP_PATH, JSON.stringify(mcpConfig, null, 2) + "\n");
|
|
232939
|
+
console.log(`~/.mcp.json updated with open-design MCP entry`);
|
|
232940
|
+
return true;
|
|
232941
|
+
} catch (e) {
|
|
232942
|
+
console.warn(
|
|
232943
|
+
`Cannot write ~/.mcp.json: ${e instanceof Error ? e.message : String(e)}`
|
|
232944
|
+
);
|
|
232945
|
+
return false;
|
|
232946
|
+
}
|
|
232947
|
+
}
|
|
232948
|
+
|
|
232949
|
+
// src/core/main.ts
|
|
232484
232950
|
function generateRuntimeId() {
|
|
232485
232951
|
return "rt_" + randomBytes(4).toString("hex");
|
|
232486
232952
|
}
|
|
@@ -232497,12 +232963,12 @@ function emergencySaveSession() {
|
|
|
232497
232963
|
}
|
|
232498
232964
|
}
|
|
232499
232965
|
process.on("unhandledRejection", (reason) => {
|
|
232500
|
-
harnessLogger.error("
|
|
232966
|
+
harnessLogger.error("UnhandledRejection", String(reason));
|
|
232501
232967
|
emergencySaveSession();
|
|
232502
232968
|
});
|
|
232503
232969
|
process.on("uncaughtException", (err) => {
|
|
232504
232970
|
const msg = err instanceof Error ? err.message : String(err);
|
|
232505
|
-
harnessLogger.error("
|
|
232971
|
+
harnessLogger.error("UncaughtException", msg);
|
|
232506
232972
|
emergencySaveSession();
|
|
232507
232973
|
setTimeout(() => {
|
|
232508
232974
|
process.exit(1);
|
|
@@ -232512,28 +232978,28 @@ var sigintCount = 0;
|
|
|
232512
232978
|
process.on("SIGINT", () => {
|
|
232513
232979
|
sigintCount++;
|
|
232514
232980
|
if (sigintCount === 1) {
|
|
232515
|
-
harnessLogger.info("
|
|
232981
|
+
harnessLogger.info("SIGINT", "Shutting down... (press Ctrl+C again to force quit)");
|
|
232516
232982
|
emergencySaveSession();
|
|
232517
232983
|
} else {
|
|
232518
|
-
harnessLogger.info("
|
|
232984
|
+
harnessLogger.info("SIGINT", "Force quitting...");
|
|
232519
232985
|
emergencySaveSession();
|
|
232520
232986
|
process.exit(0);
|
|
232521
232987
|
}
|
|
232522
232988
|
});
|
|
232523
232989
|
process.on("SIGTERM", () => {
|
|
232524
|
-
harnessLogger.info("
|
|
232990
|
+
harnessLogger.info("SIGTERM", "Received SIGTERM, shutting down...");
|
|
232525
232991
|
emergencySaveSession();
|
|
232526
232992
|
process.exit(0);
|
|
232527
232993
|
});
|
|
232528
232994
|
function readCliVersion() {
|
|
232529
232995
|
const currentDir = dirname7(fileURLToPath4(import.meta.url));
|
|
232530
232996
|
const candidates = [
|
|
232531
|
-
|
|
232532
|
-
|
|
232997
|
+
join31(currentDir, "..", "package.json"),
|
|
232998
|
+
join31(currentDir, "..", "..", "package.json")
|
|
232533
232999
|
];
|
|
232534
233000
|
for (const candidate of candidates) {
|
|
232535
|
-
if (!
|
|
232536
|
-
const pkg = JSON.parse(
|
|
233001
|
+
if (!existsSync26(candidate)) continue;
|
|
233002
|
+
const pkg = JSON.parse(readFileSync23(candidate, "utf8"));
|
|
232537
233003
|
if (typeof pkg.version === "string" && pkg.version.trim() !== "") {
|
|
232538
233004
|
return pkg.version;
|
|
232539
233005
|
}
|
|
@@ -232546,11 +233012,14 @@ function parseArgs() {
|
|
|
232546
233012
|
let webPort = 3e3;
|
|
232547
233013
|
let debug = false;
|
|
232548
233014
|
let cwd;
|
|
233015
|
+
let withOd = false;
|
|
232549
233016
|
for (let i = 0; i < args.length; i++) {
|
|
232550
233017
|
if (args[i] === "--web") {
|
|
232551
233018
|
web = true;
|
|
232552
233019
|
} else if (args[i] === "--debug") {
|
|
232553
233020
|
debug = true;
|
|
233021
|
+
} else if (args[i] === "--with-od") {
|
|
233022
|
+
withOd = true;
|
|
232554
233023
|
} else if (args[i] === "--web-port" && i + 1 < args.length) {
|
|
232555
233024
|
webPort = parseInt(args[++i], 10);
|
|
232556
233025
|
if (isNaN(webPort) || webPort < 1 || webPort > 65535) {
|
|
@@ -232560,15 +233029,91 @@ function parseArgs() {
|
|
|
232560
233029
|
cwd = resolve11(args[++i]);
|
|
232561
233030
|
}
|
|
232562
233031
|
}
|
|
232563
|
-
return { web, webPort, debug, cwd };
|
|
233032
|
+
return { web, webPort, debug, cwd, withOd };
|
|
232564
233033
|
}
|
|
232565
233034
|
async function main() {
|
|
232566
233035
|
if (process.argv.slice(2).some((arg) => arg === "--version" || arg === "-v")) {
|
|
232567
233036
|
console.log(readCliVersion());
|
|
232568
233037
|
return;
|
|
232569
233038
|
}
|
|
232570
|
-
const { web, webPort, debug, cwd } = parseArgs();
|
|
233039
|
+
const { web, webPort, debug, cwd, withOd } = parseArgs();
|
|
232571
233040
|
const projectRoot = process.cwd();
|
|
233041
|
+
if (withOd) {
|
|
233042
|
+
const odDir = process.env.OPEN_DESIGN_DIR;
|
|
233043
|
+
const odPort = parseInt(process.env.OD_PORT ?? "7456", 10);
|
|
233044
|
+
if (!odDir) {
|
|
233045
|
+
console.warn("OPEN_DESIGN_DIR is not set. Create a .env file from .env.example");
|
|
233046
|
+
} else {
|
|
233047
|
+
ensureOdMcpEntry(odDir, odPort);
|
|
233048
|
+
const alreadyAlive = await waitForOdDaemon(odPort, 2e3);
|
|
233049
|
+
if (!alreadyAlive) {
|
|
233050
|
+
try {
|
|
233051
|
+
const odChild = startOdDaemon(odDir, odPort);
|
|
233052
|
+
registerOdCleanup(odChild);
|
|
233053
|
+
let odRestartCount = 0;
|
|
233054
|
+
let lastRestartTime = 0;
|
|
233055
|
+
const attachExitHandler = (child) => {
|
|
233056
|
+
child.on("exit", (code, signal) => {
|
|
233057
|
+
if (signal) {
|
|
233058
|
+
harnessLogger.info("ODDaemon", `Open Design daemon killed by signal ${signal}`);
|
|
233059
|
+
} else if (code !== 0 && code !== null) {
|
|
233060
|
+
harnessLogger.info("ODDaemon", `Open Design daemon exited with code ${code}`);
|
|
233061
|
+
}
|
|
233062
|
+
if (code !== 0 && code !== null && withOd) {
|
|
233063
|
+
const now = Date.now();
|
|
233064
|
+
if (now - lastRestartTime < 5e3) {
|
|
233065
|
+
odRestartCount++;
|
|
233066
|
+
} else {
|
|
233067
|
+
odRestartCount = 1;
|
|
233068
|
+
}
|
|
233069
|
+
lastRestartTime = now;
|
|
233070
|
+
if (odRestartCount > 3) {
|
|
233071
|
+
harnessLogger.warn("ODDaemon", "Open Design daemon restart loop detected (3 rapid restarts), giving up");
|
|
233072
|
+
return;
|
|
233073
|
+
}
|
|
233074
|
+
harnessLogger.info("ODDaemon", `Restarting Open Design daemon (attempt ${odRestartCount})...`);
|
|
233075
|
+
try {
|
|
233076
|
+
const newChild = startOdDaemon(odDir, odPort);
|
|
233077
|
+
registerOdCleanup(newChild);
|
|
233078
|
+
attachExitHandler(newChild);
|
|
233079
|
+
void waitForOdDaemon(odPort).then((healthy) => {
|
|
233080
|
+
if (healthy) {
|
|
233081
|
+
harnessLogger.info("ODDaemon", "Open Design daemon restarted successfully");
|
|
233082
|
+
}
|
|
233083
|
+
});
|
|
233084
|
+
} catch (e) {
|
|
233085
|
+
harnessLogger.warn("ODDaemon", `Failed to restart Open Design daemon: ${e instanceof Error ? e.message : String(e)}`);
|
|
233086
|
+
}
|
|
233087
|
+
}
|
|
233088
|
+
});
|
|
233089
|
+
child.on("error", (err) => {
|
|
233090
|
+
if (err.code === "ENOENT") {
|
|
233091
|
+
const expandedDir = expandTilde2(odDir);
|
|
233092
|
+
if (!existsSync26(expandedDir)) {
|
|
233093
|
+
console.warn(
|
|
233094
|
+
`Open Design directory not found: ${expandedDir}. Check OPEN_DESIGN_DIR in .env`
|
|
233095
|
+
);
|
|
233096
|
+
} else {
|
|
233097
|
+
console.warn(
|
|
233098
|
+
`Cannot start Open Design daemon: command not found. Install pnpm (https://pnpm.io/installation) or run \`cd ${expandedDir} && pnpm link --global\` for the global od command.`
|
|
233099
|
+
);
|
|
233100
|
+
}
|
|
233101
|
+
} else {
|
|
233102
|
+
harnessLogger.warn("ODDaemon", `Open Design daemon error: ${err.message}`);
|
|
233103
|
+
}
|
|
233104
|
+
});
|
|
233105
|
+
};
|
|
233106
|
+
attachExitHandler(odChild);
|
|
233107
|
+
await waitForOdDaemon(odPort);
|
|
233108
|
+
} catch (e) {
|
|
233109
|
+
harnessLogger.warn(
|
|
233110
|
+
"ODDaemon",
|
|
233111
|
+
`Failed to start Open Design daemon: ${e instanceof Error ? e.message : String(e)}`
|
|
233112
|
+
);
|
|
233113
|
+
}
|
|
233114
|
+
}
|
|
233115
|
+
}
|
|
233116
|
+
}
|
|
232572
233117
|
const config = loadConfig(cwd);
|
|
232573
233118
|
if (config.apiKey) {
|
|
232574
233119
|
const envVar = PROVIDER_ENV_VARS[config.provider] ?? "DEEPSEEK_API_KEY";
|
|
@@ -232598,7 +233143,7 @@ async function main() {
|
|
|
232598
233143
|
}
|
|
232599
233144
|
}
|
|
232600
233145
|
main().catch((err) => {
|
|
232601
|
-
harnessLogger.error("
|
|
233146
|
+
harnessLogger.error("FatalStartup", err instanceof Error ? err.message : String(err));
|
|
232602
233147
|
emergencySaveSession();
|
|
232603
233148
|
process.exit(1);
|
|
232604
233149
|
});
|