@inspecto-dev/plugin 0.2.0-alpha.0 → 0.2.0-alpha.2
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 +19 -0
- package/dist/index.cjs +431 -102
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +436 -103
- package/dist/index.js.map +1 -1
- package/dist/legacy/rspack/index.cjs +402 -98
- package/dist/legacy/rspack/index.cjs.map +1 -1
- package/dist/legacy/rspack/index.js +407 -99
- package/dist/legacy/rspack/index.js.map +1 -1
- package/dist/legacy/rspack/loader.cjs +8 -1
- package/dist/legacy/rspack/loader.cjs.map +1 -1
- package/dist/legacy/rspack/loader.js +8 -1
- package/dist/legacy/rspack/loader.js.map +1 -1
- package/dist/legacy/webpack4/index.cjs +977 -0
- package/dist/legacy/webpack4/index.cjs.map +1 -0
- package/dist/legacy/webpack4/index.d.cts +8 -0
- package/dist/legacy/webpack4/index.d.ts +8 -0
- package/dist/legacy/webpack4/index.js +953 -0
- package/dist/legacy/webpack4/index.js.map +1 -0
- package/dist/legacy/webpack4/loader.cjs +347 -0
- package/dist/legacy/webpack4/loader.cjs.map +1 -0
- package/dist/legacy/webpack4/loader.d.cts +3 -0
- package/dist/legacy/webpack4/loader.d.ts +3 -0
- package/dist/legacy/webpack4/loader.js +314 -0
- package/dist/legacy/webpack4/loader.js.map +1 -0
- package/dist/rollup.cjs +431 -102
- package/dist/rollup.cjs.map +1 -1
- package/dist/rollup.js +436 -103
- package/dist/rollup.js.map +1 -1
- package/dist/rspack.cjs +431 -102
- package/dist/rspack.cjs.map +1 -1
- package/dist/rspack.js +436 -103
- package/dist/rspack.js.map +1 -1
- package/dist/vite.cjs +431 -102
- package/dist/vite.cjs.map +1 -1
- package/dist/vite.js +436 -103
- package/dist/vite.js.map +1 -1
- package/dist/webpack.cjs +431 -102
- package/dist/webpack.cjs.map +1 -1
- package/dist/webpack.js +436 -103
- package/dist/webpack.js.map +1 -1
- package/package.json +19 -3
package/dist/rollup.cjs
CHANGED
|
@@ -81,6 +81,10 @@ function shouldTransform(filePath, options) {
|
|
|
81
81
|
if (filePath.includes("node_modules")) return false;
|
|
82
82
|
if (filePath.startsWith("\0")) return false;
|
|
83
83
|
if (/[/\\](dist|build|\.next|\.nuxt)[/\\]/.test(filePath)) return false;
|
|
84
|
+
const ext = filePath.split(".").pop()?.toLowerCase();
|
|
85
|
+
if (ext && !["js", "jsx", "ts", "tsx", "mjs", "mts", "vue"].includes(ext)) {
|
|
86
|
+
return false;
|
|
87
|
+
}
|
|
84
88
|
return true;
|
|
85
89
|
}
|
|
86
90
|
function buildEscapeTagsSet(escapeTags) {
|
|
@@ -245,7 +249,10 @@ function transformVue(options) {
|
|
|
245
249
|
const loc = node.loc;
|
|
246
250
|
if (!loc) return;
|
|
247
251
|
const { line, column } = loc.start;
|
|
248
|
-
const
|
|
252
|
+
const templateStartLoc = descriptor.template.loc.start;
|
|
253
|
+
const absoluteLine = templateStartLoc.line + line - 1;
|
|
254
|
+
const absoluteColumn = line === 1 ? templateStartLoc.column + column - 1 : column;
|
|
255
|
+
const attrValue = formatAttrValue(normalizedPath, absoluteLine, absoluteColumn);
|
|
249
256
|
const tagNameEnd = loc.start.offset + tagName.length + 1;
|
|
250
257
|
const absoluteOffset = templateBlockStart + tagNameEnd;
|
|
251
258
|
ms.appendLeft(absoluteOffset, ` ${attributeName}="${attrValue}"`);
|
|
@@ -305,9 +312,11 @@ var import_node_http = __toESM(require("http"), 1);
|
|
|
305
312
|
var import_node_fs2 = __toESM(require("fs"), 1);
|
|
306
313
|
var import_node_path5 = __toESM(require("path"), 1);
|
|
307
314
|
var import_node_os2 = __toESM(require("os"), 1);
|
|
315
|
+
var import_node_crypto = __toESM(require("crypto"), 1);
|
|
308
316
|
var import_node_child_process = require("child_process");
|
|
309
317
|
var import_portfinder = __toESM(require("portfinder"), 1);
|
|
310
318
|
var import_launch_ide = require("launch-ide");
|
|
319
|
+
var import_types2 = require("@inspecto-dev/types");
|
|
311
320
|
|
|
312
321
|
// src/server/snippet.ts
|
|
313
322
|
var fs = __toESM(require("fs"), 1);
|
|
@@ -423,8 +432,79 @@ var import_node_path4 = __toESM(require("path"), 1);
|
|
|
423
432
|
var import_node_os = __toESM(require("os"), 1);
|
|
424
433
|
var import_defu = require("defu");
|
|
425
434
|
var import_types = require("@inspecto-dev/types");
|
|
435
|
+
|
|
436
|
+
// src/utils/logger.ts
|
|
437
|
+
var LOG_LEVELS = {
|
|
438
|
+
silent: 0,
|
|
439
|
+
error: 1,
|
|
440
|
+
warn: 2,
|
|
441
|
+
info: 3
|
|
442
|
+
};
|
|
443
|
+
function isDebugEnabled(namespace) {
|
|
444
|
+
if (typeof process === "undefined" || !process.env) return false;
|
|
445
|
+
const debugEnv = process.env.DEBUG;
|
|
446
|
+
if (!debugEnv) return false;
|
|
447
|
+
const namespaces = debugEnv.split(",").map((s) => s.trim());
|
|
448
|
+
for (const ns of namespaces) {
|
|
449
|
+
if (ns === "*") return true;
|
|
450
|
+
if (ns.endsWith("*")) {
|
|
451
|
+
const prefix = ns.slice(0, -1);
|
|
452
|
+
if (namespace.startsWith(prefix)) return true;
|
|
453
|
+
} else if (ns === namespace) {
|
|
454
|
+
return true;
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
return false;
|
|
458
|
+
}
|
|
459
|
+
var globalLevel = "warn";
|
|
460
|
+
var registeredLoggers = /* @__PURE__ */ new Set();
|
|
461
|
+
function setLoggerGlobalLevel(level) {
|
|
462
|
+
globalLevel = level;
|
|
463
|
+
for (const logger of registeredLoggers) {
|
|
464
|
+
if (logger.setLevel) {
|
|
465
|
+
logger.setLevel(level);
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
function createLogger(namespace, options) {
|
|
470
|
+
let currentLevel = options?.logLevel ?? globalLevel;
|
|
471
|
+
let numericLevel = LOG_LEVELS[currentLevel] ?? 2;
|
|
472
|
+
const debugEnabled = isDebugEnabled(namespace);
|
|
473
|
+
const logger = {
|
|
474
|
+
setLevel(level) {
|
|
475
|
+
currentLevel = level;
|
|
476
|
+
numericLevel = LOG_LEVELS[level] ?? 2;
|
|
477
|
+
},
|
|
478
|
+
info(msg, ...args) {
|
|
479
|
+
if (numericLevel >= LOG_LEVELS.info) {
|
|
480
|
+
console.log(`\x1B[36m[inspecto]\x1B[0m ${msg}`, ...args);
|
|
481
|
+
}
|
|
482
|
+
},
|
|
483
|
+
warn(msg, ...args) {
|
|
484
|
+
if (numericLevel >= LOG_LEVELS.warn) {
|
|
485
|
+
console.warn(`\x1B[33m[inspecto] WARN:\x1B[0m ${msg}`, ...args);
|
|
486
|
+
}
|
|
487
|
+
},
|
|
488
|
+
error(msg, ...args) {
|
|
489
|
+
if (numericLevel >= LOG_LEVELS.error) {
|
|
490
|
+
console.error(`\x1B[31m[inspecto] ERROR:\x1B[0m ${msg}`, ...args);
|
|
491
|
+
}
|
|
492
|
+
},
|
|
493
|
+
debug(msg, ...args) {
|
|
494
|
+
if (debugEnabled) {
|
|
495
|
+
console.log(`\x1B[90m[${namespace}]\x1B[0m ${msg}`, ...args);
|
|
496
|
+
}
|
|
497
|
+
}
|
|
498
|
+
};
|
|
499
|
+
registeredLoggers.add(logger);
|
|
500
|
+
return logger;
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
// src/config.ts
|
|
504
|
+
var configLogger = createLogger("inspecto:config");
|
|
426
505
|
var loadedConfig = null;
|
|
427
506
|
var loadedPrompts = null;
|
|
507
|
+
var globalLogLevel = "warn";
|
|
428
508
|
var isWatching = false;
|
|
429
509
|
var arrayReplaceMerge = (0, import_defu.createDefu)((obj, key, val) => {
|
|
430
510
|
if (Array.isArray(val)) {
|
|
@@ -432,6 +512,15 @@ var arrayReplaceMerge = (0, import_defu.createDefu)((obj, key, val) => {
|
|
|
432
512
|
return true;
|
|
433
513
|
}
|
|
434
514
|
});
|
|
515
|
+
function setGlobalLogLevel(level) {
|
|
516
|
+
if (level) {
|
|
517
|
+
globalLogLevel = level;
|
|
518
|
+
setLoggerGlobalLevel(level);
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
function getGlobalLogLevel() {
|
|
522
|
+
return globalLogLevel;
|
|
523
|
+
}
|
|
435
524
|
function resolveConfigRoots(cwd, gitRoot) {
|
|
436
525
|
const roots = [];
|
|
437
526
|
let current = cwd;
|
|
@@ -461,7 +550,7 @@ function loadUserConfigSync(force = false, cwd = process.cwd(), gitRoot) {
|
|
|
461
550
|
layers.push(readJsonSafely(import_node_path4.default.join(root, ".inspecto", "settings.json")));
|
|
462
551
|
}
|
|
463
552
|
layers.push(readJsonSafely(import_node_path4.default.join(import_node_os.default.homedir(), ".inspecto", "settings.json")));
|
|
464
|
-
layers.push({
|
|
553
|
+
layers.push({});
|
|
465
554
|
const validLayers = layers.filter((l) => l !== null);
|
|
466
555
|
loadedConfig = arrayReplaceMerge(...validLayers);
|
|
467
556
|
return loadedConfig;
|
|
@@ -504,48 +593,145 @@ function readJsonSafely(filePath) {
|
|
|
504
593
|
}
|
|
505
594
|
} catch (e) {
|
|
506
595
|
if (e instanceof SyntaxError) {
|
|
507
|
-
|
|
596
|
+
configLogger.warn(`Failed to parse config at ${filePath}: Invalid JSON`);
|
|
508
597
|
} else {
|
|
509
|
-
|
|
598
|
+
configLogger.warn(`Failed to read config at ${filePath}:`, e);
|
|
510
599
|
}
|
|
511
600
|
}
|
|
512
601
|
return null;
|
|
513
602
|
}
|
|
514
|
-
function resolveTargetTool(config) {
|
|
515
|
-
|
|
516
|
-
|
|
603
|
+
function resolveTargetTool(config, ide = "vscode") {
|
|
604
|
+
const defaultProvider = config["provider.default"];
|
|
605
|
+
if (defaultProvider) {
|
|
606
|
+
const tool = defaultProvider.split(".")[0];
|
|
607
|
+
return tool;
|
|
517
608
|
}
|
|
518
|
-
|
|
519
|
-
return Object.keys(config.providers)[0];
|
|
520
|
-
}
|
|
521
|
-
return "github-copilot";
|
|
609
|
+
return "copilot";
|
|
522
610
|
}
|
|
523
|
-
function
|
|
611
|
+
function resolveProviderMode(tool, ide, config) {
|
|
524
612
|
let requestedType = void 0;
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
613
|
+
const defaultProvider = config["provider.default"];
|
|
614
|
+
if (defaultProvider && defaultProvider.startsWith(`${tool}.`)) {
|
|
615
|
+
const mode = defaultProvider.split(".")[1];
|
|
616
|
+
if (mode === "extension") requestedType = "extension";
|
|
617
|
+
if (mode === "cli") requestedType = "cli";
|
|
530
618
|
}
|
|
531
|
-
requestedType = requestedType ?? import_types.
|
|
532
|
-
const valid = import_types.VALID_MODES[tool] || [import_types.
|
|
619
|
+
requestedType = requestedType ?? import_types.DEFAULT_PROVIDER_MODE[tool];
|
|
620
|
+
const valid = import_types.VALID_MODES[tool] || [import_types.DEFAULT_PROVIDER_MODE[tool]];
|
|
533
621
|
return requestedType && valid.includes(requestedType) ? requestedType : valid[0];
|
|
534
622
|
}
|
|
535
623
|
function extractToolOverrides(ide, config) {
|
|
536
624
|
const result = {};
|
|
537
|
-
if (!config
|
|
538
|
-
for (const [
|
|
539
|
-
if (!
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
if (
|
|
546
|
-
|
|
547
|
-
|
|
625
|
+
if (!config) return result;
|
|
626
|
+
for (const [key, value] of Object.entries(config)) {
|
|
627
|
+
if (!key.startsWith("provider.")) continue;
|
|
628
|
+
if (key === "provider.default") continue;
|
|
629
|
+
const toolIndex = 1;
|
|
630
|
+
const modeIndex = 2;
|
|
631
|
+
const propIndex = 3;
|
|
632
|
+
const parts = key.split(".");
|
|
633
|
+
if (parts.length >= propIndex + 1) {
|
|
634
|
+
const tool = parts[toolIndex];
|
|
635
|
+
const mode = parts[modeIndex];
|
|
636
|
+
const prop = parts[propIndex];
|
|
637
|
+
if (!result[tool]) {
|
|
638
|
+
result[tool] = { type: mode };
|
|
639
|
+
}
|
|
640
|
+
const overrides = result[tool];
|
|
641
|
+
if (prop === "bin") overrides.binaryPath = value;
|
|
642
|
+
if (prop === "args") overrides.args = value;
|
|
643
|
+
if (prop === "cwd") overrides.cwd = value;
|
|
644
|
+
if (prop === "coldStartDelay") overrides.coldStartDelay = value;
|
|
645
|
+
}
|
|
646
|
+
}
|
|
647
|
+
return result;
|
|
648
|
+
}
|
|
649
|
+
function resolveIntents(serverPrompts) {
|
|
650
|
+
const baseMap = /* @__PURE__ */ new Map();
|
|
651
|
+
for (const intent of import_types.DEFAULT_INTENTS) {
|
|
652
|
+
if (intent.id) baseMap.set(intent.id, { ...intent });
|
|
653
|
+
}
|
|
654
|
+
const defaults = () => ensureOpenInEditorLast(Array.from(baseMap.values()));
|
|
655
|
+
if (!serverPrompts) return defaults();
|
|
656
|
+
const isReplace = !Array.isArray(serverPrompts) && typeof serverPrompts === "object" && serverPrompts.$replace === true;
|
|
657
|
+
const promptsArray = Array.isArray(serverPrompts) ? serverPrompts : isReplace ? serverPrompts.items : [];
|
|
658
|
+
if (!promptsArray || promptsArray.length === 0) return defaults();
|
|
659
|
+
if (isReplace) {
|
|
660
|
+
const result = [];
|
|
661
|
+
for (const item of promptsArray) {
|
|
662
|
+
if (typeof item === "string") {
|
|
663
|
+
if (baseMap.has(item)) {
|
|
664
|
+
result.push(baseMap.get(item));
|
|
665
|
+
} else {
|
|
666
|
+
configLogger.warn(
|
|
667
|
+
`Unknown built-in intent id: "${item}". Available: ${[...baseMap.keys()].join(", ")}`
|
|
668
|
+
);
|
|
669
|
+
}
|
|
670
|
+
} else if (typeof item === "object") {
|
|
671
|
+
if (!item.id) {
|
|
672
|
+
configLogger.warn('Intent object missing required "id" field, skipping.');
|
|
673
|
+
continue;
|
|
674
|
+
}
|
|
675
|
+
if (item.enabled === false) {
|
|
676
|
+
configLogger.warn(
|
|
677
|
+
`Intent "${item.id}" is listed in $replace but has enabled:false \u2014 it will be excluded.`
|
|
678
|
+
);
|
|
679
|
+
continue;
|
|
680
|
+
}
|
|
681
|
+
if (item.isAction && item.id !== "open-in-editor") {
|
|
682
|
+
configLogger.warn(
|
|
683
|
+
`isAction is reserved for built-in actions. Ignoring intent "${item.id}".`
|
|
684
|
+
);
|
|
685
|
+
continue;
|
|
686
|
+
}
|
|
687
|
+
result.push(baseMap.has(item.id) ? { ...baseMap.get(item.id), ...item } : item);
|
|
688
|
+
}
|
|
689
|
+
}
|
|
690
|
+
return ensureOpenInEditorLast(result);
|
|
691
|
+
}
|
|
692
|
+
const merged = Array.from(baseMap.values());
|
|
693
|
+
for (const item of promptsArray) {
|
|
694
|
+
if (typeof item === "string") {
|
|
695
|
+
if (!baseMap.has(item)) {
|
|
696
|
+
configLogger.warn(
|
|
697
|
+
`Unknown built-in intent id: "${item}". In append mode, strings have no effect on ordering \u2014 use $replace to control order.`
|
|
698
|
+
);
|
|
699
|
+
}
|
|
700
|
+
continue;
|
|
701
|
+
}
|
|
702
|
+
if (typeof item === "object") {
|
|
703
|
+
if (!item.id) {
|
|
704
|
+
configLogger.warn('Intent object missing required "id" field, skipping.');
|
|
705
|
+
continue;
|
|
706
|
+
}
|
|
707
|
+
if (item.isAction && item.id !== "open-in-editor") {
|
|
708
|
+
configLogger.warn(
|
|
709
|
+
`isAction is reserved for built-in actions. Ignoring intent "${item.id}".`
|
|
710
|
+
);
|
|
711
|
+
continue;
|
|
712
|
+
}
|
|
713
|
+
const existingIdx = merged.findIndex((i) => i.id === item.id);
|
|
714
|
+
if (existingIdx !== -1) {
|
|
715
|
+
if (item.enabled === false) {
|
|
716
|
+
merged.splice(existingIdx, 1);
|
|
717
|
+
} else {
|
|
718
|
+
merged[existingIdx] = { ...merged[existingIdx], ...item };
|
|
719
|
+
}
|
|
720
|
+
} else {
|
|
721
|
+
if (item.enabled !== false) {
|
|
722
|
+
merged.push(item);
|
|
723
|
+
}
|
|
724
|
+
}
|
|
725
|
+
}
|
|
548
726
|
}
|
|
727
|
+
return ensureOpenInEditorLast(merged);
|
|
728
|
+
}
|
|
729
|
+
function ensureOpenInEditorLast(intents) {
|
|
730
|
+
const idx = intents.findIndex((i) => i.id === "open-in-editor");
|
|
731
|
+
if (idx === -1 || idx === intents.length - 1) return intents;
|
|
732
|
+
const result = [...intents];
|
|
733
|
+
const item = result.splice(idx, 1)[0];
|
|
734
|
+
result.push(item);
|
|
549
735
|
return result;
|
|
550
736
|
}
|
|
551
737
|
var watchers = [];
|
|
@@ -582,6 +768,19 @@ function watchConfig(onReload, cwd = process.cwd(), gitRoot) {
|
|
|
582
768
|
}
|
|
583
769
|
|
|
584
770
|
// src/server/index.ts
|
|
771
|
+
var serverLogger = createLogger("inspecto:server", { logLevel: getGlobalLogLevel() });
|
|
772
|
+
var payloadTickets = /* @__PURE__ */ new Map();
|
|
773
|
+
function createTicket(payload) {
|
|
774
|
+
const ticketId = import_node_crypto.default.randomUUID();
|
|
775
|
+
payloadTickets.set(ticketId, JSON.stringify(payload));
|
|
776
|
+
setTimeout(
|
|
777
|
+
() => {
|
|
778
|
+
payloadTickets.delete(ticketId);
|
|
779
|
+
},
|
|
780
|
+
5 * 60 * 1e3
|
|
781
|
+
);
|
|
782
|
+
return ticketId;
|
|
783
|
+
}
|
|
585
784
|
var serverState = {
|
|
586
785
|
port: null,
|
|
587
786
|
running: false,
|
|
@@ -593,8 +792,11 @@ var serverInstance = null;
|
|
|
593
792
|
function resolveProjectRoot() {
|
|
594
793
|
let gitRoot;
|
|
595
794
|
try {
|
|
795
|
+
serverLogger.info("Resolving project root...");
|
|
596
796
|
gitRoot = (0, import_node_child_process.execSync)("git rev-parse --show-toplevel", { encoding: "utf-8" }).trim();
|
|
597
|
-
|
|
797
|
+
serverLogger.info("Resolved project root: " + gitRoot);
|
|
798
|
+
} catch (e) {
|
|
799
|
+
serverLogger.error("Failed to resolve project root:", e);
|
|
598
800
|
gitRoot = process.cwd();
|
|
599
801
|
}
|
|
600
802
|
let current = gitRoot;
|
|
@@ -616,7 +818,7 @@ function launchURI(uri) {
|
|
|
616
818
|
(0, import_node_child_process.execFileSync)("xdg-open", [uri]);
|
|
617
819
|
}
|
|
618
820
|
} catch (e) {
|
|
619
|
-
|
|
821
|
+
serverLogger.error("Failed to launch URI via execFileSync, falling back to launchIDE:", e);
|
|
620
822
|
(0, import_launch_ide.launchIDE)({ file: uri });
|
|
621
823
|
}
|
|
622
824
|
}
|
|
@@ -631,7 +833,7 @@ async function startServer() {
|
|
|
631
833
|
const port = await import_portfinder.default.getPortPromise();
|
|
632
834
|
watchConfig(
|
|
633
835
|
() => {
|
|
634
|
-
|
|
836
|
+
serverLogger.info("user config reloaded.");
|
|
635
837
|
},
|
|
636
838
|
serverState.cwd,
|
|
637
839
|
serverState.configRoot
|
|
@@ -647,7 +849,7 @@ async function startServer() {
|
|
|
647
849
|
}
|
|
648
850
|
const url = new URL(req.url ?? "/", `http://localhost:${port}`);
|
|
649
851
|
handleRequest(url, req, res).catch((err) => {
|
|
650
|
-
|
|
852
|
+
serverLogger.error("server error:", err);
|
|
651
853
|
res.writeHead(500, { "Content-Type": "application/json" });
|
|
652
854
|
res.end(JSON.stringify({ success: false, error: String(err) }));
|
|
653
855
|
});
|
|
@@ -660,22 +862,41 @@ async function startServer() {
|
|
|
660
862
|
serverInstance.once("error", reject);
|
|
661
863
|
});
|
|
662
864
|
serverInstance.on("error", (err) => {
|
|
663
|
-
|
|
865
|
+
serverLogger.error("persistent server error:", err);
|
|
664
866
|
});
|
|
665
867
|
serverState.port = port;
|
|
666
868
|
serverState.running = true;
|
|
667
|
-
const portFile = import_node_path5.default.join(import_node_os2.default.tmpdir(), "inspecto.port");
|
|
869
|
+
const portFile = import_node_path5.default.join(import_node_os2.default.tmpdir(), "inspecto.port.json");
|
|
668
870
|
try {
|
|
669
|
-
|
|
670
|
-
|
|
871
|
+
let portData = {};
|
|
872
|
+
if (import_node_fs2.default.existsSync(portFile)) {
|
|
873
|
+
try {
|
|
874
|
+
portData = JSON.parse(import_node_fs2.default.readFileSync(portFile, "utf-8"));
|
|
875
|
+
} catch (e) {
|
|
876
|
+
}
|
|
877
|
+
}
|
|
878
|
+
const rootHash = import_node_crypto.default.createHash("md5").update(serverState.projectRoot).digest("hex");
|
|
879
|
+
portData[rootHash] = port;
|
|
880
|
+
import_node_fs2.default.writeFileSync(portFile, JSON.stringify(portData, null, 2), "utf-8");
|
|
881
|
+
} catch (e) {
|
|
882
|
+
serverLogger.warn("Failed to write port file:", e);
|
|
671
883
|
}
|
|
672
884
|
process.once("exit", () => {
|
|
673
885
|
try {
|
|
674
|
-
import_node_fs2.default.
|
|
886
|
+
if (import_node_fs2.default.existsSync(portFile)) {
|
|
887
|
+
const portData = JSON.parse(import_node_fs2.default.readFileSync(portFile, "utf-8"));
|
|
888
|
+
const rootHash = import_node_crypto.default.createHash("md5").update(serverState.projectRoot).digest("hex");
|
|
889
|
+
delete portData[rootHash];
|
|
890
|
+
if (Object.keys(portData).length === 0) {
|
|
891
|
+
import_node_fs2.default.unlinkSync(portFile);
|
|
892
|
+
} else {
|
|
893
|
+
import_node_fs2.default.writeFileSync(portFile, JSON.stringify(portData, null, 2), "utf-8");
|
|
894
|
+
}
|
|
895
|
+
}
|
|
675
896
|
} catch {
|
|
676
897
|
}
|
|
677
898
|
});
|
|
678
|
-
|
|
899
|
+
serverLogger.info(`server running at http://127.0.0.1:${port}`);
|
|
679
900
|
return port;
|
|
680
901
|
}
|
|
681
902
|
async function readBody(req) {
|
|
@@ -688,66 +909,63 @@ async function readBody(req) {
|
|
|
688
909
|
}
|
|
689
910
|
async function handleRequest(url, req, res) {
|
|
690
911
|
const pathname = url.pathname;
|
|
691
|
-
if (pathname === "/health" && req.method === "GET") {
|
|
912
|
+
if ((pathname === "/health" || pathname === import_types2.INSPECTO_API_PATHS.HEALTH) && req.method === "GET") {
|
|
692
913
|
res.writeHead(200, { "Content-Type": "application/json" });
|
|
693
914
|
res.end(JSON.stringify({ ok: true, port: serverState.port }));
|
|
694
915
|
return;
|
|
695
916
|
}
|
|
696
|
-
if (pathname ===
|
|
917
|
+
if (pathname === import_types2.INSPECTO_API_PATHS.CLIENT_CONFIG && req.method === "GET") {
|
|
697
918
|
const userConfig = loadUserConfigSync(false, serverState.cwd, serverState.configRoot);
|
|
698
919
|
const promptsConfig = await loadPromptsConfig(false, serverState.cwd, serverState.configRoot);
|
|
699
920
|
const effectiveIde = userConfig.ide ?? "vscode";
|
|
700
921
|
let info;
|
|
701
922
|
if (!serverState.ideInfo) {
|
|
702
|
-
const fallbackTargets = userConfig.providers ? Object.keys(userConfig.providers) : ["claude-code", "gemini", "coco", "codex"];
|
|
703
923
|
info = {
|
|
704
|
-
ide: effectiveIde
|
|
705
|
-
providers: fallbackTargets.reduce(
|
|
706
|
-
(acc, target) => {
|
|
707
|
-
acc[target] = {
|
|
708
|
-
mode: resolveToolMode(target, effectiveIde, userConfig),
|
|
709
|
-
installed: false
|
|
710
|
-
};
|
|
711
|
-
return acc;
|
|
712
|
-
},
|
|
713
|
-
{}
|
|
714
|
-
)
|
|
924
|
+
ide: effectiveIde
|
|
715
925
|
};
|
|
716
926
|
} else {
|
|
717
927
|
const { scheme: _scheme, ...rest } = serverState.ideInfo;
|
|
718
928
|
info = rest;
|
|
719
929
|
}
|
|
720
|
-
const resolvedProviders = { ...info.providers };
|
|
721
|
-
for (const tool in resolvedProviders) {
|
|
722
|
-
resolvedProviders[tool].mode = resolveToolMode(tool, info.ide, userConfig);
|
|
723
|
-
}
|
|
724
930
|
const config = {
|
|
725
931
|
...info,
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
932
|
+
prompts: resolveIntents(promptsConfig),
|
|
933
|
+
hotKeys: userConfig["inspector.hotKey"] ?? "alt",
|
|
934
|
+
theme: userConfig["inspector.theme"] ?? "auto",
|
|
935
|
+
includeSnippet: userConfig["prompt.includeSnippet"] ?? false,
|
|
936
|
+
autoSend: userConfig["prompt.autoSend"] ?? false
|
|
731
937
|
};
|
|
938
|
+
delete config.providers;
|
|
732
939
|
res.writeHead(200, { "Content-Type": "application/json" });
|
|
733
940
|
res.end(JSON.stringify(config));
|
|
734
941
|
return;
|
|
735
942
|
}
|
|
736
|
-
if (pathname ===
|
|
943
|
+
if (pathname === import_types2.INSPECTO_API_PATHS.IDE_INFO && req.method === "POST") {
|
|
737
944
|
try {
|
|
738
945
|
const body = JSON.parse(await readBody(req));
|
|
739
|
-
|
|
740
|
-
|
|
946
|
+
const ideWorkspace = body.workspaceRoot || "";
|
|
947
|
+
const serverProjectRoot = serverState.projectRoot || "";
|
|
948
|
+
const isSameProject = !ideWorkspace || !serverProjectRoot || ideWorkspace === serverProjectRoot || serverProjectRoot.startsWith(ideWorkspace);
|
|
949
|
+
if (isSameProject) {
|
|
950
|
+
serverState.ideInfo = body;
|
|
951
|
+
serverLogger.debug(
|
|
952
|
+
`Accepted IDE info from matched workspace (ide-${body.ide} / schema-${body.scheme})`
|
|
953
|
+
);
|
|
954
|
+
} else {
|
|
955
|
+
serverLogger.debug(
|
|
956
|
+
`Ignored IDE info from unrelated workspace (IDE Workspace: ${ideWorkspace}, Server: ${serverProjectRoot}, Scheme: ${body.scheme}, IDE: ${body.ide})`
|
|
957
|
+
);
|
|
958
|
+
}
|
|
741
959
|
res.writeHead(200, { "Content-Type": "application/json" });
|
|
742
960
|
res.end(JSON.stringify({ success: true }));
|
|
743
961
|
} catch (e) {
|
|
744
|
-
|
|
962
|
+
serverLogger.error(`Error parsing ${import_types2.INSPECTO_API_PATHS.IDE_INFO} POST request:`, e);
|
|
745
963
|
res.writeHead(400, { "Content-Type": "application/json" });
|
|
746
964
|
res.end(JSON.stringify({ error: "Invalid JSON body" }));
|
|
747
965
|
}
|
|
748
966
|
return;
|
|
749
967
|
}
|
|
750
|
-
if (pathname ===
|
|
968
|
+
if (pathname === import_types2.INSPECTO_API_PATHS.IDE_OPEN && req.method === "POST") {
|
|
751
969
|
let body;
|
|
752
970
|
try {
|
|
753
971
|
body = JSON.parse(await readBody(req));
|
|
@@ -756,28 +974,98 @@ async function handleRequest(url, req, res) {
|
|
|
756
974
|
res.end(JSON.stringify({ error: "Invalid JSON body" }));
|
|
757
975
|
return;
|
|
758
976
|
}
|
|
759
|
-
const absolutePath = import_node_path5.default.isAbsolute(body.file) ? body.file : import_node_path5.default.resolve(serverState.cwd, body.file);
|
|
977
|
+
const absolutePath = import_node_path5.default.isAbsolute(body.file) ? import_node_path5.default.resolve(body.file) : import_node_path5.default.resolve(serverState.cwd, body.file);
|
|
978
|
+
const relativeToRoot = import_node_path5.default.relative(serverState.projectRoot, absolutePath);
|
|
979
|
+
if (relativeToRoot.startsWith("..") || import_node_path5.default.isAbsolute(relativeToRoot)) {
|
|
980
|
+
serverLogger.warn(`Security: Blocked path traversal attempt in IDE_OPEN: ${body.file}`);
|
|
981
|
+
res.writeHead(403, { "Content-Type": "application/json" });
|
|
982
|
+
res.end(JSON.stringify({ error: "Access denied: File is outside of project workspace" }));
|
|
983
|
+
return;
|
|
984
|
+
}
|
|
760
985
|
const userConfig = loadUserConfigSync(false, serverState.cwd, serverState.configRoot);
|
|
761
|
-
const
|
|
762
|
-
const
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
}
|
|
986
|
+
const configuredIde = userConfig.ide;
|
|
987
|
+
const activeIde = serverState.ideInfo?.ide;
|
|
988
|
+
const activeIdeScheme = serverState.ideInfo?.scheme;
|
|
989
|
+
const rawEditorHint = configuredIde || activeIde || activeIdeScheme || "code";
|
|
990
|
+
if (configuredIde && activeIdeScheme && !activeIdeScheme.includes(configuredIde)) {
|
|
991
|
+
serverLogger.warn(
|
|
992
|
+
`Active IDE is ${activeIdeScheme}, but config forces ${configuredIde}. Using configured IDE.`
|
|
993
|
+
);
|
|
994
|
+
}
|
|
995
|
+
let editorHint = rawEditorHint;
|
|
996
|
+
if (rawEditorHint === "vscode") editorHint = "code";
|
|
997
|
+
else if (rawEditorHint === "vscode-insiders") editorHint = "code-insiders";
|
|
998
|
+
else if (rawEditorHint === "vscodium") editorHint = "codium";
|
|
999
|
+
else if (rawEditorHint === "trae-cn" || rawEditorHint === "trae") editorHint = "trae";
|
|
1000
|
+
serverLogger.debug(
|
|
1001
|
+
`IDE_OPEN: activeIde=${activeIde}, activeIdeScheme=${activeIdeScheme}, configuredIde=${configuredIde} -> rawEditorHint=${rawEditorHint}, finalEditorHint=${editorHint}`
|
|
1002
|
+
);
|
|
1003
|
+
const VSCODE_FAMILY_SCHEMES = [
|
|
1004
|
+
"vscode",
|
|
1005
|
+
"vscode-insiders",
|
|
1006
|
+
"cursor",
|
|
1007
|
+
"windsurf",
|
|
1008
|
+
"trae",
|
|
1009
|
+
"trae-cn",
|
|
1010
|
+
"vscodium",
|
|
1011
|
+
"codebuddy",
|
|
1012
|
+
"codebuddy-cn",
|
|
1013
|
+
"antigravity"
|
|
1014
|
+
];
|
|
1015
|
+
if (VSCODE_FAMILY_SCHEMES.includes(rawEditorHint)) {
|
|
1016
|
+
const uri = `${rawEditorHint}://file${absolutePath}:${body.line}:${body.column}`;
|
|
1017
|
+
serverLogger.debug(`IDE_OPEN: Bypassing launchIDE, using URI scheme directly: ${uri}`);
|
|
1018
|
+
try {
|
|
1019
|
+
if (process.platform === "darwin") {
|
|
1020
|
+
(0, import_node_child_process.execFileSync)("open", [uri]);
|
|
1021
|
+
} else if (process.platform === "win32") {
|
|
1022
|
+
(0, import_node_child_process.execFileSync)("cmd", ["/c", "start", '""', uri]);
|
|
1023
|
+
} else {
|
|
1024
|
+
(0, import_node_child_process.execFileSync)("xdg-open", [uri]);
|
|
1025
|
+
}
|
|
1026
|
+
} catch (e) {
|
|
1027
|
+
serverLogger.error(`Failed to launch URI for IDE_OPEN (${uri}):`, e);
|
|
1028
|
+
(0, import_launch_ide.launchIDE)({
|
|
1029
|
+
file: absolutePath,
|
|
1030
|
+
line: body.line,
|
|
1031
|
+
column: body.column,
|
|
1032
|
+
editor: editorHint,
|
|
1033
|
+
type: process.platform === "darwin" ? "open" : "exec"
|
|
1034
|
+
});
|
|
1035
|
+
}
|
|
1036
|
+
} else {
|
|
1037
|
+
(0, import_launch_ide.launchIDE)({
|
|
1038
|
+
file: absolutePath,
|
|
1039
|
+
line: body.line,
|
|
1040
|
+
column: body.column,
|
|
1041
|
+
editor: editorHint,
|
|
1042
|
+
type: process.platform === "darwin" ? "open" : "exec"
|
|
1043
|
+
});
|
|
1044
|
+
}
|
|
770
1045
|
res.writeHead(200, { "Content-Type": "application/json" });
|
|
771
1046
|
res.end(JSON.stringify({ success: true }));
|
|
772
1047
|
return;
|
|
773
1048
|
}
|
|
774
|
-
if (pathname ===
|
|
1049
|
+
if (pathname === import_types2.INSPECTO_API_PATHS.PROJECT_SNIPPET && req.method === "GET") {
|
|
775
1050
|
const file = url.searchParams.get("file") ?? "";
|
|
776
1051
|
const line = parseInt(url.searchParams.get("line") ?? "1", 10);
|
|
777
1052
|
const column = parseInt(url.searchParams.get("column") ?? "1", 10);
|
|
778
1053
|
const maxLines = parseInt(url.searchParams.get("maxLines") ?? "100", 10);
|
|
779
1054
|
try {
|
|
780
|
-
const absolutePath = import_node_path5.default.isAbsolute(file) ? file : import_node_path5.default.resolve(serverState.cwd, file);
|
|
1055
|
+
const absolutePath = import_node_path5.default.isAbsolute(file) ? import_node_path5.default.resolve(file) : import_node_path5.default.resolve(serverState.cwd, file);
|
|
1056
|
+
const relativeToRoot = import_node_path5.default.relative(serverState.projectRoot, absolutePath);
|
|
1057
|
+
if (relativeToRoot.startsWith("..") || import_node_path5.default.isAbsolute(relativeToRoot)) {
|
|
1058
|
+
serverLogger.warn(`Security: Blocked path traversal attempt in PROJECT_SNIPPET: ${file}`);
|
|
1059
|
+
res.writeHead(403, { "Content-Type": "application/json" });
|
|
1060
|
+
res.end(
|
|
1061
|
+
JSON.stringify({
|
|
1062
|
+
success: false,
|
|
1063
|
+
error: "Access denied: File is outside of project workspace",
|
|
1064
|
+
errorCode: "FORBIDDEN"
|
|
1065
|
+
})
|
|
1066
|
+
);
|
|
1067
|
+
return;
|
|
1068
|
+
}
|
|
781
1069
|
const result = await extractSnippet({ file: absolutePath, line, column, maxLines });
|
|
782
1070
|
res.writeHead(200, { "Content-Type": "application/json" });
|
|
783
1071
|
res.end(JSON.stringify(result));
|
|
@@ -789,7 +1077,7 @@ async function handleRequest(url, req, res) {
|
|
|
789
1077
|
}
|
|
790
1078
|
return;
|
|
791
1079
|
}
|
|
792
|
-
if (pathname ===
|
|
1080
|
+
if (pathname === import_types2.INSPECTO_API_PATHS.AI_DISPATCH && req.method === "POST") {
|
|
793
1081
|
try {
|
|
794
1082
|
const rawBody = await readBody(req);
|
|
795
1083
|
const body = JSON.parse(rawBody);
|
|
@@ -797,19 +1085,30 @@ async function handleRequest(url, req, res) {
|
|
|
797
1085
|
res.writeHead(result.success ? 200 : 500, { "Content-Type": "application/json" });
|
|
798
1086
|
res.end(JSON.stringify(result));
|
|
799
1087
|
} catch (e) {
|
|
800
|
-
|
|
1088
|
+
serverLogger.error(`Error parsing ${import_types2.INSPECTO_API_PATHS.AI_DISPATCH} request:`, e);
|
|
801
1089
|
res.writeHead(500, { "Content-Type": "application/json" });
|
|
802
1090
|
res.end(JSON.stringify({ success: false, error: String(e), errorCode: "INTERNAL_ERROR" }));
|
|
803
1091
|
}
|
|
804
1092
|
return;
|
|
805
1093
|
}
|
|
1094
|
+
if (pathname.startsWith(`${import_types2.INSPECTO_API_PATHS.AI_TICKET}/`) && req.method === "GET") {
|
|
1095
|
+
const ticketId = pathname.substring(import_types2.INSPECTO_API_PATHS.AI_TICKET.length + 1);
|
|
1096
|
+
const payloadStr = payloadTickets.get(ticketId);
|
|
1097
|
+
if (!payloadStr) {
|
|
1098
|
+
res.writeHead(404, { "Content-Type": "application/json" });
|
|
1099
|
+
res.end(JSON.stringify({ success: false, error: "Ticket not found or expired" }));
|
|
1100
|
+
return;
|
|
1101
|
+
}
|
|
1102
|
+
res.writeHead(200, { "Content-Type": "application/json" });
|
|
1103
|
+
res.end(payloadStr);
|
|
1104
|
+
return;
|
|
1105
|
+
}
|
|
806
1106
|
res.writeHead(404, { "Content-Type": "application/json" });
|
|
807
1107
|
res.end(JSON.stringify({ error: "not found" }));
|
|
808
1108
|
}
|
|
809
1109
|
async function dispatchToAi(req) {
|
|
810
1110
|
const { location, snippet, prompt } = req;
|
|
811
1111
|
const userConfig = loadUserConfigSync(false, serverState.cwd, serverState.configRoot);
|
|
812
|
-
const ide = userConfig.ide ?? "vscode";
|
|
813
1112
|
const resolvedTarget = resolveTargetTool(userConfig);
|
|
814
1113
|
const formattedPrompt = prompt ?? `Please help me with this code from \`${location.file}\` (line ${location.line}):
|
|
815
1114
|
|
|
@@ -817,22 +1116,45 @@ async function dispatchToAi(req) {
|
|
|
817
1116
|
${snippet}
|
|
818
1117
|
\`\`\`
|
|
819
1118
|
`;
|
|
1119
|
+
const ideReportedMode = serverState.ideInfo?.providers[resolvedTarget]?.mode;
|
|
1120
|
+
const configuredIde = userConfig.ide;
|
|
1121
|
+
const activeIde = serverState.ideInfo?.ide;
|
|
1122
|
+
const activeIdeScheme = serverState.ideInfo?.scheme;
|
|
1123
|
+
const finalIde = configuredIde || activeIdeScheme || activeIde || "vscode";
|
|
1124
|
+
if (configuredIde && activeIdeScheme && !activeIdeScheme.includes(configuredIde)) {
|
|
1125
|
+
serverLogger.warn(
|
|
1126
|
+
`dispatchToAi: Active IDE is ${activeIdeScheme}, but config forces ${configuredIde}. Using configured IDE.`
|
|
1127
|
+
);
|
|
1128
|
+
}
|
|
1129
|
+
const mode = resolveProviderMode(resolvedTarget, finalIde, userConfig);
|
|
1130
|
+
const overrides = extractToolOverrides(finalIde, userConfig)[resolvedTarget] || {};
|
|
1131
|
+
overrides.type = mode;
|
|
1132
|
+
const fullPayload = {
|
|
1133
|
+
ide: finalIde,
|
|
1134
|
+
target: resolvedTarget,
|
|
1135
|
+
targetType: mode,
|
|
1136
|
+
prompt: formattedPrompt,
|
|
1137
|
+
filePath: location.file,
|
|
1138
|
+
line: location.line,
|
|
1139
|
+
column: location.column,
|
|
1140
|
+
snippet,
|
|
1141
|
+
overrides: Object.keys(overrides).length > 0 ? overrides : void 0,
|
|
1142
|
+
autoSend: userConfig["prompt.autoSend"] !== void 0 ? Boolean(userConfig["prompt.autoSend"]) : void 0
|
|
1143
|
+
};
|
|
1144
|
+
const ticketId = createTicket(fullPayload);
|
|
820
1145
|
const params = new URLSearchParams();
|
|
1146
|
+
params.set("ticket", ticketId);
|
|
821
1147
|
params.set("target", resolvedTarget);
|
|
822
|
-
const
|
|
823
|
-
|
|
824
|
-
params.set("overrides", JSON.stringify(overrides));
|
|
825
|
-
}
|
|
826
|
-
params.set("prompt", formattedPrompt);
|
|
827
|
-
params.set("file", location.file);
|
|
828
|
-
params.set("line", String(location.line));
|
|
829
|
-
params.set("col", String(location.column));
|
|
830
|
-
params.set("snippet", snippet);
|
|
831
|
-
const scheme = serverState.ideInfo?.scheme || "vscode";
|
|
832
|
-
const uri = `${scheme}://inspecto.inspecto/send?${params.toString()}`;
|
|
833
|
-
console.log(`[inspecto] dispatchToAi: Generated URI: ${uri}`);
|
|
1148
|
+
const uri = `${finalIde}://inspecto.inspecto/send?${params.toString()}`;
|
|
1149
|
+
serverLogger.debug(`dispatchToAi: Generated URI: ${uri}`);
|
|
834
1150
|
launchURI(uri);
|
|
835
|
-
return {
|
|
1151
|
+
return {
|
|
1152
|
+
success: true,
|
|
1153
|
+
fallbackPayload: {
|
|
1154
|
+
prompt: formattedPrompt,
|
|
1155
|
+
file: location.file
|
|
1156
|
+
}
|
|
1157
|
+
};
|
|
836
1158
|
}
|
|
837
1159
|
|
|
838
1160
|
// src/injectors/utils.ts
|
|
@@ -844,7 +1166,9 @@ var resolveClientModule = () => {
|
|
|
844
1166
|
try {
|
|
845
1167
|
return require.resolve("@inspecto-dev/core");
|
|
846
1168
|
} catch {
|
|
847
|
-
console.warn(
|
|
1169
|
+
console.warn(
|
|
1170
|
+
"[inspecto] Could not resolve @inspecto-dev/core \u2014 falling back to bare specifier"
|
|
1171
|
+
);
|
|
848
1172
|
return "@inspecto-dev/core";
|
|
849
1173
|
}
|
|
850
1174
|
}
|
|
@@ -886,9 +1210,11 @@ if (typeof window !== 'undefined') {
|
|
|
886
1210
|
}
|
|
887
1211
|
function injectWebpack(compiler, serverPortFn, resolveClientModule2) {
|
|
888
1212
|
const inspectoClientPath = resolveClientModule2();
|
|
889
|
-
|
|
890
|
-
compiler
|
|
891
|
-
|
|
1213
|
+
if (compiler.webpack && compiler.webpack.EntryPlugin) {
|
|
1214
|
+
new compiler.webpack.EntryPlugin(compiler.context, inspectoClientPath, {
|
|
1215
|
+
name: void 0
|
|
1216
|
+
}).apply(compiler);
|
|
1217
|
+
}
|
|
892
1218
|
compiler.hooks.compilation.tap("inspecto-overlay", (compilation) => {
|
|
893
1219
|
const HtmlWebpackPlugin = compiler.options.plugins.find(
|
|
894
1220
|
(p) => p && p.constructor && p.constructor.name === "HtmlWebpackPlugin"
|
|
@@ -970,7 +1296,8 @@ var DEFAULT_OPTIONS = {
|
|
|
970
1296
|
exclude: [],
|
|
971
1297
|
escapeTags: [],
|
|
972
1298
|
pathType: "absolute",
|
|
973
|
-
attributeName: "data-inspecto"
|
|
1299
|
+
attributeName: "data-inspecto",
|
|
1300
|
+
logLevel: "warn"
|
|
974
1301
|
};
|
|
975
1302
|
var DEFAULT_PORT = 5678;
|
|
976
1303
|
var getCleanId = (id) => id.split("?")[0];
|
|
@@ -979,6 +1306,8 @@ var InspectoPlugin = (0, import_unplugin.createUnplugin)((userOptions = {}) => {
|
|
|
979
1306
|
...DEFAULT_OPTIONS,
|
|
980
1307
|
...userOptions
|
|
981
1308
|
};
|
|
1309
|
+
setGlobalLogLevel(options.logLevel);
|
|
1310
|
+
const pluginLogger = createLogger("inspecto:plugin", { logLevel: options.logLevel });
|
|
982
1311
|
const isProduction = process.env["NODE_ENV"] === "production";
|
|
983
1312
|
let projectRoot = process.cwd();
|
|
984
1313
|
let serverPort = null;
|
|
@@ -994,7 +1323,7 @@ var InspectoPlugin = (0, import_unplugin.createUnplugin)((userOptions = {}) => {
|
|
|
994
1323
|
buildStart() {
|
|
995
1324
|
if (isProduction) return;
|
|
996
1325
|
projectRoot = serverState.cwd || process.cwd();
|
|
997
|
-
ensureServer().catch(
|
|
1326
|
+
ensureServer().catch((err) => pluginLogger.error("Failed to start server:", err));
|
|
998
1327
|
},
|
|
999
1328
|
buildEnd() {
|
|
1000
1329
|
},
|