@inspecto-dev/plugin 0.2.0-alpha.3 → 0.3.0-alpha.1
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 +1 -1
- package/dist/index.cjs +452 -195
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +452 -195
- package/dist/index.js.map +1 -1
- package/dist/legacy/rspack/index.cjs +454 -197
- package/dist/legacy/rspack/index.cjs.map +1 -1
- package/dist/legacy/rspack/index.js +454 -197
- package/dist/legacy/rspack/index.js.map +1 -1
- package/dist/legacy/webpack4/index.cjs +454 -197
- package/dist/legacy/webpack4/index.cjs.map +1 -1
- package/dist/legacy/webpack4/index.js +454 -197
- package/dist/legacy/webpack4/index.js.map +1 -1
- package/dist/rollup.cjs +452 -195
- package/dist/rollup.cjs.map +1 -1
- package/dist/rollup.js +452 -195
- package/dist/rollup.js.map +1 -1
- package/dist/rspack.cjs +452 -195
- package/dist/rspack.cjs.map +1 -1
- package/dist/rspack.js +452 -195
- package/dist/rspack.js.map +1 -1
- package/dist/vite.cjs +452 -195
- package/dist/vite.cjs.map +1 -1
- package/dist/vite.js +452 -195
- package/dist/vite.js.map +1 -1
- package/dist/webpack.cjs +452 -195
- package/dist/webpack.cjs.map +1 -1
- package/dist/webpack.js +452 -195
- package/dist/webpack.js.map +1 -1
- package/package.json +2 -2
|
@@ -72,13 +72,11 @@ var resolveClientModule = () => {
|
|
|
72
72
|
|
|
73
73
|
// src/server/index.ts
|
|
74
74
|
var import_node_http = __toESM(require("http"), 1);
|
|
75
|
-
var
|
|
76
|
-
var
|
|
75
|
+
var import_node_fs3 = __toESM(require("fs"), 1);
|
|
76
|
+
var import_node_path4 = __toESM(require("path"), 1);
|
|
77
77
|
var import_node_os2 = __toESM(require("os"), 1);
|
|
78
|
-
var
|
|
79
|
-
var import_node_child_process = require("child_process");
|
|
78
|
+
var import_node_crypto2 = __toESM(require("crypto"), 1);
|
|
80
79
|
var import_portfinder = __toESM(require("portfinder"), 1);
|
|
81
|
-
var import_launch_ide = require("launch-ide");
|
|
82
80
|
var import_types2 = require("@inspecto-dev/types");
|
|
83
81
|
|
|
84
82
|
// src/server/snippet.ts
|
|
@@ -398,9 +396,9 @@ function extractToolOverrides(ide, config) {
|
|
|
398
396
|
function resolveIntents(serverPrompts) {
|
|
399
397
|
const baseMap = /* @__PURE__ */ new Map();
|
|
400
398
|
for (const intent of import_types.DEFAULT_INTENTS) {
|
|
401
|
-
|
|
399
|
+
baseMap.set(intent.id, { ...intent });
|
|
402
400
|
}
|
|
403
|
-
const defaults = () =>
|
|
401
|
+
const defaults = () => Array.from(baseMap.values());
|
|
404
402
|
if (!serverPrompts) return defaults();
|
|
405
403
|
const isReplace = !Array.isArray(serverPrompts) && typeof serverPrompts === "object" && serverPrompts.$replace === true;
|
|
406
404
|
const promptsArray = Array.isArray(serverPrompts) ? serverPrompts : isReplace ? serverPrompts.items : [];
|
|
@@ -427,16 +425,18 @@ function resolveIntents(serverPrompts) {
|
|
|
427
425
|
);
|
|
428
426
|
continue;
|
|
429
427
|
}
|
|
430
|
-
if (item.
|
|
428
|
+
if (!item.aiIntent) {
|
|
431
429
|
configLogger.warn(
|
|
432
|
-
`
|
|
430
|
+
`Intent "${item.id}" is missing required "aiIntent".`
|
|
433
431
|
);
|
|
434
432
|
continue;
|
|
435
433
|
}
|
|
436
|
-
result.push(
|
|
434
|
+
result.push(
|
|
435
|
+
baseMap.has(item.id) ? { ...baseMap.get(item.id), ...item } : item
|
|
436
|
+
);
|
|
437
437
|
}
|
|
438
438
|
}
|
|
439
|
-
return
|
|
439
|
+
return result;
|
|
440
440
|
}
|
|
441
441
|
const merged = Array.from(baseMap.values());
|
|
442
442
|
for (const item of promptsArray) {
|
|
@@ -453,9 +453,9 @@ function resolveIntents(serverPrompts) {
|
|
|
453
453
|
configLogger.warn('Intent object missing required "id" field, skipping.');
|
|
454
454
|
continue;
|
|
455
455
|
}
|
|
456
|
-
if (item.
|
|
456
|
+
if (!item.aiIntent) {
|
|
457
457
|
configLogger.warn(
|
|
458
|
-
`
|
|
458
|
+
`Intent "${item.id}" is missing required "aiIntent".`
|
|
459
459
|
);
|
|
460
460
|
continue;
|
|
461
461
|
}
|
|
@@ -473,15 +473,7 @@ function resolveIntents(serverPrompts) {
|
|
|
473
473
|
}
|
|
474
474
|
}
|
|
475
475
|
}
|
|
476
|
-
return
|
|
477
|
-
}
|
|
478
|
-
function ensureOpenInEditorLast(intents) {
|
|
479
|
-
const idx = intents.findIndex((i) => i.id === "open-in-editor");
|
|
480
|
-
if (idx === -1 || idx === intents.length - 1) return intents;
|
|
481
|
-
const result = [...intents];
|
|
482
|
-
const item = result.splice(idx, 1)[0];
|
|
483
|
-
result.push(item);
|
|
484
|
-
return result;
|
|
476
|
+
return merged;
|
|
485
477
|
}
|
|
486
478
|
var watchers = [];
|
|
487
479
|
function watchConfig(onReload, cwd = process.cwd(), gitRoot) {
|
|
@@ -516,7 +508,10 @@ function watchConfig(onReload, cwd = process.cwd(), gitRoot) {
|
|
|
516
508
|
}
|
|
517
509
|
}
|
|
518
510
|
|
|
519
|
-
// src/server/
|
|
511
|
+
// src/server/dispatch-transport.ts
|
|
512
|
+
var import_node_crypto = __toESM(require("crypto"), 1);
|
|
513
|
+
var import_node_child_process = require("child_process");
|
|
514
|
+
var import_launch_ide = require("launch-ide");
|
|
520
515
|
var serverLogger = createLogger("inspecto:server", { logLevel: getGlobalLogLevel() });
|
|
521
516
|
var payloadTickets = /* @__PURE__ */ new Map();
|
|
522
517
|
function createTicket(payload) {
|
|
@@ -530,32 +525,8 @@ function createTicket(payload) {
|
|
|
530
525
|
);
|
|
531
526
|
return ticketId;
|
|
532
527
|
}
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
running: false,
|
|
536
|
-
projectRoot: "",
|
|
537
|
-
configRoot: "",
|
|
538
|
-
cwd: process.cwd()
|
|
539
|
-
};
|
|
540
|
-
var serverInstance = null;
|
|
541
|
-
function resolveProjectRoot() {
|
|
542
|
-
let gitRoot;
|
|
543
|
-
try {
|
|
544
|
-
serverLogger.info("Resolving project root...");
|
|
545
|
-
gitRoot = (0, import_node_child_process.execSync)("git rev-parse --show-toplevel", { encoding: "utf-8" }).trim();
|
|
546
|
-
serverLogger.info("Resolved project root: " + gitRoot);
|
|
547
|
-
} catch (e) {
|
|
548
|
-
serverLogger.error("Failed to resolve project root:", e);
|
|
549
|
-
gitRoot = process.cwd();
|
|
550
|
-
}
|
|
551
|
-
let current = gitRoot;
|
|
552
|
-
while (true) {
|
|
553
|
-
if (import_node_fs2.default.existsSync(import_node_path2.default.join(current, ".inspecto"))) return current;
|
|
554
|
-
const parent = import_node_path2.default.dirname(current);
|
|
555
|
-
if (parent === current) break;
|
|
556
|
-
current = parent;
|
|
557
|
-
}
|
|
558
|
-
return gitRoot;
|
|
528
|
+
function readTicket(ticketId) {
|
|
529
|
+
return payloadTickets.get(ticketId);
|
|
559
530
|
}
|
|
560
531
|
function launchURI(uri) {
|
|
561
532
|
try {
|
|
@@ -571,6 +542,378 @@ function launchURI(uri) {
|
|
|
571
542
|
(0, import_launch_ide.launchIDE)({ file: uri });
|
|
572
543
|
}
|
|
573
544
|
}
|
|
545
|
+
|
|
546
|
+
// src/server/dispatch-runtime.ts
|
|
547
|
+
function resolvePromptDispatchRuntime(state) {
|
|
548
|
+
const userConfig = loadUserConfigSync(false, state.cwd, state.projectRoot);
|
|
549
|
+
const resolvedTarget = resolveTargetTool(userConfig);
|
|
550
|
+
const finalIde = resolveFinalIde(userConfig.ide, state.ideInfo?.ide, state.ideInfo?.scheme);
|
|
551
|
+
const mode = resolveProviderMode(resolvedTarget, finalIde, userConfig);
|
|
552
|
+
const overrides = extractToolOverrides(finalIde, userConfig)[resolvedTarget] || void 0;
|
|
553
|
+
return {
|
|
554
|
+
resolvedTarget,
|
|
555
|
+
finalIde,
|
|
556
|
+
mode,
|
|
557
|
+
...hasOverrides(overrides) ? { overrides } : {},
|
|
558
|
+
...userConfig["prompt.autoSend"] !== void 0 ? { autoSend: Boolean(userConfig["prompt.autoSend"]) } : {}
|
|
559
|
+
};
|
|
560
|
+
}
|
|
561
|
+
function dispatchPromptThroughIde(runtime, payload) {
|
|
562
|
+
const ticketId = createTicket({
|
|
563
|
+
ide: runtime.finalIde,
|
|
564
|
+
target: runtime.resolvedTarget,
|
|
565
|
+
targetType: runtime.mode,
|
|
566
|
+
prompt: payload.prompt,
|
|
567
|
+
filePath: payload.filePath,
|
|
568
|
+
line: payload.line,
|
|
569
|
+
column: payload.column,
|
|
570
|
+
snippet: payload.snippet,
|
|
571
|
+
...payload.screenshotContext ? { screenshotContext: payload.screenshotContext } : {},
|
|
572
|
+
overrides: runtime.overrides,
|
|
573
|
+
autoSend: runtime.autoSend
|
|
574
|
+
});
|
|
575
|
+
const params = new URLSearchParams();
|
|
576
|
+
params.set("ticket", ticketId);
|
|
577
|
+
params.set("target", runtime.resolvedTarget);
|
|
578
|
+
launchURI(`${runtime.finalIde}://inspecto.inspecto/send?${params.toString()}`);
|
|
579
|
+
return {
|
|
580
|
+
success: true,
|
|
581
|
+
fallbackPayload: {
|
|
582
|
+
prompt: payload.prompt,
|
|
583
|
+
...payload.filePath ? { file: payload.filePath } : {}
|
|
584
|
+
}
|
|
585
|
+
};
|
|
586
|
+
}
|
|
587
|
+
function resolveFinalIde(configuredIde, activeIde, activeIdeScheme) {
|
|
588
|
+
if (configuredIde && activeIdeScheme && !activeIdeScheme.includes(configuredIde)) {
|
|
589
|
+
return configuredIde;
|
|
590
|
+
}
|
|
591
|
+
return configuredIde || activeIdeScheme || activeIde || "vscode";
|
|
592
|
+
}
|
|
593
|
+
function hasOverrides(overrides) {
|
|
594
|
+
return Boolean(overrides && Object.keys(overrides).length > 0);
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
// src/server/path-guards.ts
|
|
598
|
+
var import_node_path2 = __toESM(require("path"), 1);
|
|
599
|
+
function isWindowsAbsolutePath(file) {
|
|
600
|
+
return /^[a-zA-Z]:[\\/]/.test(file) || /^\\\\[^\\]+\\[^\\]+/.test(file);
|
|
601
|
+
}
|
|
602
|
+
function resolveWorkspacePath(file, cwd) {
|
|
603
|
+
if (isWindowsAbsolutePath(file)) {
|
|
604
|
+
return import_node_path2.default.win32.normalize(file);
|
|
605
|
+
}
|
|
606
|
+
return import_node_path2.default.isAbsolute(file) ? import_node_path2.default.resolve(file) : import_node_path2.default.resolve(cwd, file);
|
|
607
|
+
}
|
|
608
|
+
function assertPathWithinProject(file, projectRoot) {
|
|
609
|
+
const relativeToRoot = isWindowsAbsolutePath(file) || isWindowsAbsolutePath(projectRoot) ? import_node_path2.default.win32.relative(import_node_path2.default.win32.normalize(projectRoot), import_node_path2.default.win32.normalize(file)) : import_node_path2.default.relative(projectRoot, file);
|
|
610
|
+
if (relativeToRoot.startsWith("..") || import_node_path2.default.isAbsolute(relativeToRoot)) {
|
|
611
|
+
throw new Error("Access denied: File is outside of project workspace");
|
|
612
|
+
}
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
// src/server/annotation-dispatch.ts
|
|
616
|
+
var AnnotationDispatchError = class extends Error {
|
|
617
|
+
constructor(message, errorCode) {
|
|
618
|
+
super(message);
|
|
619
|
+
this.name = "AnnotationDispatchError";
|
|
620
|
+
this.errorCode = errorCode;
|
|
621
|
+
}
|
|
622
|
+
};
|
|
623
|
+
async function dispatchAnnotationsToAi(req, state) {
|
|
624
|
+
try {
|
|
625
|
+
validateAnnotationDispatchRequest(req, state);
|
|
626
|
+
const batch = normalizeAnnotationBatch(req);
|
|
627
|
+
const prompt = buildAnnotationBatchPrompt(batch);
|
|
628
|
+
const representativeTarget = batch.annotations[0]?.targets[0];
|
|
629
|
+
const runtime = resolvePromptDispatchRuntime(state);
|
|
630
|
+
return dispatchPromptThroughIde(runtime, {
|
|
631
|
+
prompt,
|
|
632
|
+
...representativeTarget?.file ? { filePath: representativeTarget.file } : {},
|
|
633
|
+
...representativeTarget?.line ? { line: representativeTarget.line } : {},
|
|
634
|
+
...representativeTarget?.column ? { column: representativeTarget.column } : {},
|
|
635
|
+
...batch.screenshotContext ? { screenshotContext: batch.screenshotContext } : {}
|
|
636
|
+
});
|
|
637
|
+
} catch (error) {
|
|
638
|
+
return {
|
|
639
|
+
success: false,
|
|
640
|
+
error: error instanceof Error ? error.message : String(error),
|
|
641
|
+
errorCode: getAnnotationDispatchErrorCode(error)
|
|
642
|
+
};
|
|
643
|
+
}
|
|
644
|
+
}
|
|
645
|
+
function validateAnnotationDispatchRequest(req, state) {
|
|
646
|
+
if (!req.annotations.length) {
|
|
647
|
+
throw new AnnotationDispatchError("At least one annotation is required.", "INVALID_REQUEST");
|
|
648
|
+
}
|
|
649
|
+
for (const annotation of req.annotations) {
|
|
650
|
+
if (!annotation.targets.length) {
|
|
651
|
+
throw new AnnotationDispatchError(
|
|
652
|
+
"Each annotation must include at least one target.",
|
|
653
|
+
"INVALID_REQUEST"
|
|
654
|
+
);
|
|
655
|
+
}
|
|
656
|
+
for (const target of annotation.targets) {
|
|
657
|
+
const absolutePath = resolveWorkspacePath(target.location.file, state.cwd);
|
|
658
|
+
assertPathWithinProject(absolutePath, state.projectRoot);
|
|
659
|
+
}
|
|
660
|
+
}
|
|
661
|
+
}
|
|
662
|
+
function normalizeAnnotationBatch(req) {
|
|
663
|
+
return {
|
|
664
|
+
instruction: req.instruction?.trim() ?? "",
|
|
665
|
+
responseMode: req.responseMode ?? "unified",
|
|
666
|
+
...req.runtimeContext ? { runtimeContext: req.runtimeContext } : {},
|
|
667
|
+
...req.screenshotContext ? { screenshotContext: req.screenshotContext } : {},
|
|
668
|
+
...req.cssContextPrompt?.trim() ? { cssContextPrompt: req.cssContextPrompt.trim() } : {},
|
|
669
|
+
annotations: req.annotations.map((annotation, index) => ({
|
|
670
|
+
index: index + 1,
|
|
671
|
+
note: annotation.note.trim(),
|
|
672
|
+
intent: annotation.intent,
|
|
673
|
+
targets: annotation.targets.map((target) => ({
|
|
674
|
+
file: target.location.file,
|
|
675
|
+
line: target.location.line,
|
|
676
|
+
column: target.location.column,
|
|
677
|
+
...target.label ? { label: target.label } : {},
|
|
678
|
+
...target.selector ? { selector: target.selector } : {},
|
|
679
|
+
...target.snippet ? { snippet: target.snippet } : {}
|
|
680
|
+
}))
|
|
681
|
+
}))
|
|
682
|
+
};
|
|
683
|
+
}
|
|
684
|
+
function buildAnnotationBatchPrompt(batch) {
|
|
685
|
+
const body = buildSelectedElementsPrompt(batch.annotations);
|
|
686
|
+
const prompt = batch.instruction ? `${batch.instruction}
|
|
687
|
+
|
|
688
|
+
${body}` : body;
|
|
689
|
+
return appendScreenshotContextSection(
|
|
690
|
+
appendCssContextSection(
|
|
691
|
+
appendRuntimeContextSection(prompt, batch.runtimeContext),
|
|
692
|
+
batch.cssContextPrompt
|
|
693
|
+
),
|
|
694
|
+
batch.screenshotContext
|
|
695
|
+
);
|
|
696
|
+
}
|
|
697
|
+
function appendCssContextSection(prompt, cssContextPrompt) {
|
|
698
|
+
if (!cssContextPrompt) return prompt;
|
|
699
|
+
return `${prompt}
|
|
700
|
+
|
|
701
|
+
${cssContextPrompt}`;
|
|
702
|
+
}
|
|
703
|
+
function buildSelectedElementsPrompt(annotations) {
|
|
704
|
+
const lines = ["Selected elements:"];
|
|
705
|
+
for (const annotation of annotations) {
|
|
706
|
+
const trimmedNote = annotation.note.trim();
|
|
707
|
+
for (const target of annotation.targets) {
|
|
708
|
+
const targetLabel = (target.label || "Unknown target").trim() || "Unknown target";
|
|
709
|
+
lines.push(`- ${targetLabel}`);
|
|
710
|
+
lines.push(`file=${target.file}:${target.line}:${target.column}`);
|
|
711
|
+
if (trimmedNote) {
|
|
712
|
+
lines.push(`note=${trimmedNote}`);
|
|
713
|
+
}
|
|
714
|
+
}
|
|
715
|
+
}
|
|
716
|
+
if (lines.length === 1) {
|
|
717
|
+
lines.push("- None");
|
|
718
|
+
}
|
|
719
|
+
return lines.join("\n");
|
|
720
|
+
}
|
|
721
|
+
function appendScreenshotContextSection(prompt, screenshotContext) {
|
|
722
|
+
if (!screenshotContext || !screenshotContext.imageDataUrl && !screenshotContext.imageAssetId) {
|
|
723
|
+
return prompt;
|
|
724
|
+
}
|
|
725
|
+
const lines = [
|
|
726
|
+
"Visual screenshot context attached:",
|
|
727
|
+
`- capturedAt=${screenshotContext.capturedAt}`,
|
|
728
|
+
`- mimeType=${screenshotContext.mimeType}`,
|
|
729
|
+
...screenshotContext.imageAssetId ? [`- imageAssetId=${screenshotContext.imageAssetId}`] : []
|
|
730
|
+
];
|
|
731
|
+
return `${prompt}
|
|
732
|
+
|
|
733
|
+
${lines.join("\n")}`;
|
|
734
|
+
}
|
|
735
|
+
function appendRuntimeContextSection(prompt, runtimeContext) {
|
|
736
|
+
if (!runtimeContext?.records.length) {
|
|
737
|
+
return prompt;
|
|
738
|
+
}
|
|
739
|
+
return `${prompt}
|
|
740
|
+
|
|
741
|
+
${buildRuntimeContextSection(runtimeContext.records)}`;
|
|
742
|
+
}
|
|
743
|
+
function buildRuntimeContextSection(records) {
|
|
744
|
+
return ["Relevant runtime context:", ...records.map(formatRuntimeRecord)].join("\n");
|
|
745
|
+
}
|
|
746
|
+
function formatRuntimeRecord(record) {
|
|
747
|
+
const requestSummary = record.kind === "failed-request" ? `request=${record.request?.method ?? "GET"} ${record.request?.pathname ?? record.request?.url ?? "unknown"} status=${record.request?.status ?? "unknown"}` : `occurrences=${record.occurrenceCount}`;
|
|
748
|
+
const reasonSummary = record.relevanceReasons.length ? record.relevanceReasons.join("; ") : "timing-based";
|
|
749
|
+
const stackSummary = record.stack ? `
|
|
750
|
+
stack=${record.stack.split("\n").slice(0, 5).join(" | ")}` : "";
|
|
751
|
+
return [
|
|
752
|
+
`- [${record.kind}] ${record.message}`,
|
|
753
|
+
` relevance=${record.relevanceLevel} (${reasonSummary})`,
|
|
754
|
+
` ${requestSummary}`,
|
|
755
|
+
stackSummary
|
|
756
|
+
].filter(Boolean).join("\n");
|
|
757
|
+
}
|
|
758
|
+
function getAnnotationDispatchErrorCode(error) {
|
|
759
|
+
if (error instanceof AnnotationDispatchError) return error.errorCode;
|
|
760
|
+
if (error instanceof Error && error.message.includes("outside of project workspace")) {
|
|
761
|
+
return "FORBIDDEN_PATH";
|
|
762
|
+
}
|
|
763
|
+
return "UNKNOWN";
|
|
764
|
+
}
|
|
765
|
+
|
|
766
|
+
// src/server/client-config.ts
|
|
767
|
+
async function buildClientConfig(serverState2) {
|
|
768
|
+
const userConfig = loadUserConfigSync(false, serverState2.cwd, serverState2.configRoot);
|
|
769
|
+
const promptsConfig = await loadPromptsConfig(false, serverState2.cwd, serverState2.configRoot);
|
|
770
|
+
const effectiveIde = userConfig.ide ?? "vscode";
|
|
771
|
+
let info;
|
|
772
|
+
if (!serverState2.ideInfo) {
|
|
773
|
+
info = { ide: effectiveIde };
|
|
774
|
+
} else {
|
|
775
|
+
const { scheme: _scheme, ...rest } = serverState2.ideInfo;
|
|
776
|
+
info = rest;
|
|
777
|
+
}
|
|
778
|
+
return {
|
|
779
|
+
...info,
|
|
780
|
+
prompts: resolveIntents(promptsConfig),
|
|
781
|
+
hotKeys: userConfig["inspector.hotKey"] ?? "alt",
|
|
782
|
+
theme: userConfig["inspector.theme"] ?? "auto",
|
|
783
|
+
includeSnippet: userConfig["prompt.includeSnippet"] ?? false,
|
|
784
|
+
runtimeContext: {
|
|
785
|
+
enabled: true,
|
|
786
|
+
preview: true,
|
|
787
|
+
maxRuntimeErrors: 3,
|
|
788
|
+
maxFailedRequests: 2
|
|
789
|
+
},
|
|
790
|
+
screenshotContext: {
|
|
791
|
+
enabled: false
|
|
792
|
+
},
|
|
793
|
+
annotationResponseMode: userConfig["prompt.annotationResponseMode"] ?? "unified",
|
|
794
|
+
autoSend: userConfig["prompt.autoSend"] ?? false
|
|
795
|
+
};
|
|
796
|
+
}
|
|
797
|
+
|
|
798
|
+
// src/server/open-file.ts
|
|
799
|
+
var import_node_child_process2 = require("child_process");
|
|
800
|
+
var import_launch_ide2 = require("launch-ide");
|
|
801
|
+
var serverLogger2 = createLogger("inspecto:server", { logLevel: getGlobalLogLevel() });
|
|
802
|
+
var VSCODE_FAMILY_SCHEMES = [
|
|
803
|
+
"vscode",
|
|
804
|
+
"vscode-insiders",
|
|
805
|
+
"cursor",
|
|
806
|
+
"windsurf",
|
|
807
|
+
"trae",
|
|
808
|
+
"trae-cn",
|
|
809
|
+
"vscodium",
|
|
810
|
+
"codebuddy",
|
|
811
|
+
"codebuddy-cn",
|
|
812
|
+
"antigravity"
|
|
813
|
+
];
|
|
814
|
+
function handleOpenFileRequest(body, serverState2) {
|
|
815
|
+
const absolutePath = resolveWorkspacePath(body.file, serverState2.cwd);
|
|
816
|
+
assertPathWithinProject(absolutePath, serverState2.projectRoot);
|
|
817
|
+
const userConfig = loadUserConfigSync(false, serverState2.cwd, serverState2.configRoot);
|
|
818
|
+
const configuredIde = userConfig.ide;
|
|
819
|
+
const activeIde = serverState2.ideInfo?.ide;
|
|
820
|
+
const activeIdeScheme = serverState2.ideInfo?.scheme;
|
|
821
|
+
const rawEditorHint = configuredIde || activeIde || activeIdeScheme || "code";
|
|
822
|
+
if (configuredIde && activeIdeScheme && !activeIdeScheme.includes(configuredIde)) {
|
|
823
|
+
serverLogger2.warn(
|
|
824
|
+
`Active IDE is ${activeIdeScheme}, but config forces ${configuredIde}. Using configured IDE.`
|
|
825
|
+
);
|
|
826
|
+
}
|
|
827
|
+
let editorHint = rawEditorHint;
|
|
828
|
+
if (rawEditorHint === "vscode") editorHint = "code";
|
|
829
|
+
else if (rawEditorHint === "vscode-insiders") editorHint = "code-insiders";
|
|
830
|
+
else if (rawEditorHint === "vscodium") editorHint = "codium";
|
|
831
|
+
else if (rawEditorHint === "trae-cn" || rawEditorHint === "trae") editorHint = "trae";
|
|
832
|
+
serverLogger2.debug(
|
|
833
|
+
`IDE_OPEN: activeIde=${activeIde}, activeIdeScheme=${activeIdeScheme}, configuredIde=${configuredIde} -> rawEditorHint=${rawEditorHint}, finalEditorHint=${editorHint}`
|
|
834
|
+
);
|
|
835
|
+
if (VSCODE_FAMILY_SCHEMES.includes(rawEditorHint)) {
|
|
836
|
+
let normalizedPath = absolutePath.replace(/\\/g, "/");
|
|
837
|
+
if (!normalizedPath.startsWith("/")) {
|
|
838
|
+
normalizedPath = "/" + normalizedPath;
|
|
839
|
+
}
|
|
840
|
+
const encodedPath = encodeURI(normalizedPath);
|
|
841
|
+
const uri = `${rawEditorHint}://file${encodedPath}:${body.line}:${body.column}`;
|
|
842
|
+
serverLogger2.debug(`IDE_OPEN: Bypassing launchIDE, using URI scheme directly: ${uri}`);
|
|
843
|
+
try {
|
|
844
|
+
if (process.platform === "darwin") {
|
|
845
|
+
(0, import_node_child_process2.execFileSync)("open", [uri]);
|
|
846
|
+
} else if (process.platform === "win32") {
|
|
847
|
+
(0, import_node_child_process2.execFileSync)("cmd", ["/c", "start", '""', uri]);
|
|
848
|
+
} else {
|
|
849
|
+
(0, import_node_child_process2.execFileSync)("xdg-open", [uri]);
|
|
850
|
+
}
|
|
851
|
+
} catch (e) {
|
|
852
|
+
serverLogger2.error(`Failed to launch URI for IDE_OPEN (${uri}):`, e);
|
|
853
|
+
(0, import_launch_ide2.launchIDE)({
|
|
854
|
+
file: absolutePath,
|
|
855
|
+
line: body.line,
|
|
856
|
+
column: body.column,
|
|
857
|
+
editor: editorHint,
|
|
858
|
+
type: process.platform === "darwin" ? "open" : "exec"
|
|
859
|
+
});
|
|
860
|
+
}
|
|
861
|
+
} else {
|
|
862
|
+
(0, import_launch_ide2.launchIDE)({
|
|
863
|
+
file: absolutePath,
|
|
864
|
+
line: body.line,
|
|
865
|
+
column: body.column,
|
|
866
|
+
editor: editorHint,
|
|
867
|
+
type: process.platform === "darwin" ? "open" : "exec"
|
|
868
|
+
});
|
|
869
|
+
}
|
|
870
|
+
return { success: true };
|
|
871
|
+
}
|
|
872
|
+
|
|
873
|
+
// src/server/project-root.ts
|
|
874
|
+
var import_node_fs2 = __toESM(require("fs"), 1);
|
|
875
|
+
var import_node_path3 = __toESM(require("path"), 1);
|
|
876
|
+
var import_node_child_process3 = require("child_process");
|
|
877
|
+
var serverLogger3 = createLogger("inspecto:server", { logLevel: getGlobalLogLevel() });
|
|
878
|
+
function resolveProjectRoot() {
|
|
879
|
+
const cwd = process.cwd();
|
|
880
|
+
let gitRoot;
|
|
881
|
+
try {
|
|
882
|
+
gitRoot = (0, import_node_child_process3.execSync)("git rev-parse --show-toplevel", { encoding: "utf-8" }).trim();
|
|
883
|
+
} catch (e) {
|
|
884
|
+
serverLogger3.warn("Failed to resolve git root via git rev-parse:", e);
|
|
885
|
+
gitRoot = cwd;
|
|
886
|
+
}
|
|
887
|
+
const visited = /* @__PURE__ */ new Set();
|
|
888
|
+
const search = (start, stop) => {
|
|
889
|
+
let current = start;
|
|
890
|
+
while (!visited.has(current)) {
|
|
891
|
+
visited.add(current);
|
|
892
|
+
if (import_node_fs2.default.existsSync(import_node_path3.default.join(current, ".inspecto"))) return current;
|
|
893
|
+
if (current === stop) break;
|
|
894
|
+
const parent = import_node_path3.default.dirname(current);
|
|
895
|
+
if (parent === current) break;
|
|
896
|
+
current = parent;
|
|
897
|
+
}
|
|
898
|
+
return null;
|
|
899
|
+
};
|
|
900
|
+
const cwdMatch = search(cwd, import_node_path3.default.parse(cwd).root);
|
|
901
|
+
if (cwdMatch) return cwdMatch;
|
|
902
|
+
const repoMatch = search(gitRoot, import_node_path3.default.parse(gitRoot).root);
|
|
903
|
+
if (repoMatch) return repoMatch;
|
|
904
|
+
return gitRoot;
|
|
905
|
+
}
|
|
906
|
+
|
|
907
|
+
// src/server/index.ts
|
|
908
|
+
var serverLogger4 = createLogger("inspecto:server", { logLevel: getGlobalLogLevel() });
|
|
909
|
+
var serverState = {
|
|
910
|
+
port: null,
|
|
911
|
+
running: false,
|
|
912
|
+
projectRoot: "",
|
|
913
|
+
configRoot: "",
|
|
914
|
+
cwd: process.cwd()
|
|
915
|
+
};
|
|
916
|
+
var serverInstance = null;
|
|
574
917
|
async function startServer() {
|
|
575
918
|
if (serverState.running && serverState.port !== null) {
|
|
576
919
|
return serverState.port;
|
|
@@ -582,7 +925,7 @@ async function startServer() {
|
|
|
582
925
|
const port = await import_portfinder.default.getPortPromise();
|
|
583
926
|
watchConfig(
|
|
584
927
|
() => {
|
|
585
|
-
|
|
928
|
+
serverLogger4.info("user config reloaded.");
|
|
586
929
|
},
|
|
587
930
|
serverState.cwd,
|
|
588
931
|
serverState.configRoot
|
|
@@ -598,7 +941,7 @@ async function startServer() {
|
|
|
598
941
|
}
|
|
599
942
|
const url = new URL(req.url ?? "/", `http://localhost:${port}`);
|
|
600
943
|
handleRequest(url, req, res).catch((err) => {
|
|
601
|
-
|
|
944
|
+
serverLogger4.error("server error:", err);
|
|
602
945
|
res.writeHead(500, { "Content-Type": "application/json" });
|
|
603
946
|
res.end(JSON.stringify({ success: false, error: String(err) }));
|
|
604
947
|
});
|
|
@@ -611,41 +954,41 @@ async function startServer() {
|
|
|
611
954
|
serverInstance.once("error", reject);
|
|
612
955
|
});
|
|
613
956
|
serverInstance.on("error", (err) => {
|
|
614
|
-
|
|
957
|
+
serverLogger4.error("persistent server error:", err);
|
|
615
958
|
});
|
|
616
959
|
serverState.port = port;
|
|
617
960
|
serverState.running = true;
|
|
618
|
-
const portFile =
|
|
961
|
+
const portFile = import_node_path4.default.join(import_node_os2.default.tmpdir(), "inspecto.port.json");
|
|
619
962
|
try {
|
|
620
963
|
let portData = {};
|
|
621
|
-
if (
|
|
964
|
+
if (import_node_fs3.default.existsSync(portFile)) {
|
|
622
965
|
try {
|
|
623
|
-
portData = JSON.parse(
|
|
966
|
+
portData = JSON.parse(import_node_fs3.default.readFileSync(portFile, "utf-8"));
|
|
624
967
|
} catch (e) {
|
|
625
968
|
}
|
|
626
969
|
}
|
|
627
|
-
const rootHash =
|
|
970
|
+
const rootHash = import_node_crypto2.default.createHash("md5").update(serverState.projectRoot).digest("hex");
|
|
628
971
|
portData[rootHash] = port;
|
|
629
|
-
|
|
972
|
+
import_node_fs3.default.writeFileSync(portFile, JSON.stringify(portData, null, 2), "utf-8");
|
|
630
973
|
} catch (e) {
|
|
631
|
-
|
|
974
|
+
serverLogger4.warn("Failed to write port file:", e);
|
|
632
975
|
}
|
|
633
976
|
process.once("exit", () => {
|
|
634
977
|
try {
|
|
635
|
-
if (
|
|
636
|
-
const portData = JSON.parse(
|
|
637
|
-
const rootHash =
|
|
978
|
+
if (import_node_fs3.default.existsSync(portFile)) {
|
|
979
|
+
const portData = JSON.parse(import_node_fs3.default.readFileSync(portFile, "utf-8"));
|
|
980
|
+
const rootHash = import_node_crypto2.default.createHash("md5").update(serverState.projectRoot).digest("hex");
|
|
638
981
|
delete portData[rootHash];
|
|
639
982
|
if (Object.keys(portData).length === 0) {
|
|
640
|
-
|
|
983
|
+
import_node_fs3.default.unlinkSync(portFile);
|
|
641
984
|
} else {
|
|
642
|
-
|
|
985
|
+
import_node_fs3.default.writeFileSync(portFile, JSON.stringify(portData, null, 2), "utf-8");
|
|
643
986
|
}
|
|
644
987
|
}
|
|
645
988
|
} catch {
|
|
646
989
|
}
|
|
647
990
|
});
|
|
648
|
-
|
|
991
|
+
serverLogger4.info(`server running at http://127.0.0.1:${port}`);
|
|
649
992
|
return port;
|
|
650
993
|
}
|
|
651
994
|
async function readBody(req) {
|
|
@@ -664,26 +1007,7 @@ async function handleRequest(url, req, res) {
|
|
|
664
1007
|
return;
|
|
665
1008
|
}
|
|
666
1009
|
if (pathname === import_types2.INSPECTO_API_PATHS.CLIENT_CONFIG && req.method === "GET") {
|
|
667
|
-
const
|
|
668
|
-
const promptsConfig = await loadPromptsConfig(false, serverState.cwd, serverState.configRoot);
|
|
669
|
-
const effectiveIde = userConfig.ide ?? "vscode";
|
|
670
|
-
let info;
|
|
671
|
-
if (!serverState.ideInfo) {
|
|
672
|
-
info = {
|
|
673
|
-
ide: effectiveIde
|
|
674
|
-
};
|
|
675
|
-
} else {
|
|
676
|
-
const { scheme: _scheme, ...rest } = serverState.ideInfo;
|
|
677
|
-
info = rest;
|
|
678
|
-
}
|
|
679
|
-
const config = {
|
|
680
|
-
...info,
|
|
681
|
-
prompts: resolveIntents(promptsConfig),
|
|
682
|
-
hotKeys: userConfig["inspector.hotKey"] ?? "alt",
|
|
683
|
-
theme: userConfig["inspector.theme"] ?? "auto",
|
|
684
|
-
includeSnippet: userConfig["prompt.includeSnippet"] ?? false,
|
|
685
|
-
autoSend: userConfig["prompt.autoSend"] ?? false
|
|
686
|
-
};
|
|
1010
|
+
const config = await buildClientConfig(serverState);
|
|
687
1011
|
delete config.providers;
|
|
688
1012
|
res.writeHead(200, { "Content-Type": "application/json" });
|
|
689
1013
|
res.end(JSON.stringify(config));
|
|
@@ -694,21 +1018,23 @@ async function handleRequest(url, req, res) {
|
|
|
694
1018
|
const body = JSON.parse(await readBody(req));
|
|
695
1019
|
const ideWorkspace = body.workspaceRoot || "";
|
|
696
1020
|
const serverProjectRoot = serverState.projectRoot || "";
|
|
697
|
-
const
|
|
1021
|
+
const normalizedIdeRoot = ideWorkspace ? import_node_path4.default.resolve(ideWorkspace) : "";
|
|
1022
|
+
const normalizedServerRoot = serverProjectRoot ? import_node_path4.default.resolve(serverProjectRoot) : "";
|
|
1023
|
+
const isSameProject = !normalizedIdeRoot || !normalizedServerRoot || normalizedIdeRoot === normalizedServerRoot || normalizedServerRoot.startsWith(normalizedIdeRoot + import_node_path4.default.sep) || normalizedIdeRoot.startsWith(normalizedServerRoot + import_node_path4.default.sep);
|
|
698
1024
|
if (isSameProject) {
|
|
699
1025
|
serverState.ideInfo = body;
|
|
700
|
-
|
|
1026
|
+
serverLogger4.debug(
|
|
701
1027
|
`Accepted IDE info from matched workspace (ide-${body.ide} / schema-${body.scheme})`
|
|
702
1028
|
);
|
|
703
1029
|
} else {
|
|
704
|
-
|
|
1030
|
+
serverLogger4.debug(
|
|
705
1031
|
`Ignored IDE info from unrelated workspace (IDE Workspace: ${ideWorkspace}, Server: ${serverProjectRoot}, Scheme: ${body.scheme}, IDE: ${body.ide})`
|
|
706
1032
|
);
|
|
707
1033
|
}
|
|
708
1034
|
res.writeHead(200, { "Content-Type": "application/json" });
|
|
709
1035
|
res.end(JSON.stringify({ success: true }));
|
|
710
1036
|
} catch (e) {
|
|
711
|
-
|
|
1037
|
+
serverLogger4.error(`Error parsing ${import_types2.INSPECTO_API_PATHS.IDE_INFO} POST request:`, e);
|
|
712
1038
|
res.writeHead(400, { "Content-Type": "application/json" });
|
|
713
1039
|
res.end(JSON.stringify({ error: "Invalid JSON body" }));
|
|
714
1040
|
}
|
|
@@ -723,74 +1049,14 @@ async function handleRequest(url, req, res) {
|
|
|
723
1049
|
res.end(JSON.stringify({ error: "Invalid JSON body" }));
|
|
724
1050
|
return;
|
|
725
1051
|
}
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
1052
|
+
try {
|
|
1053
|
+
handleOpenFileRequest(body, serverState);
|
|
1054
|
+
} catch {
|
|
1055
|
+
serverLogger4.warn(`Security: Blocked path traversal attempt in IDE_OPEN: ${body.file}`);
|
|
730
1056
|
res.writeHead(403, { "Content-Type": "application/json" });
|
|
731
1057
|
res.end(JSON.stringify({ error: "Access denied: File is outside of project workspace" }));
|
|
732
1058
|
return;
|
|
733
1059
|
}
|
|
734
|
-
const userConfig = loadUserConfigSync(false, serverState.cwd, serverState.configRoot);
|
|
735
|
-
const configuredIde = userConfig.ide;
|
|
736
|
-
const activeIde = serverState.ideInfo?.ide;
|
|
737
|
-
const activeIdeScheme = serverState.ideInfo?.scheme;
|
|
738
|
-
const rawEditorHint = configuredIde || activeIde || activeIdeScheme || "code";
|
|
739
|
-
if (configuredIde && activeIdeScheme && !activeIdeScheme.includes(configuredIde)) {
|
|
740
|
-
serverLogger.warn(
|
|
741
|
-
`Active IDE is ${activeIdeScheme}, but config forces ${configuredIde}. Using configured IDE.`
|
|
742
|
-
);
|
|
743
|
-
}
|
|
744
|
-
let editorHint = rawEditorHint;
|
|
745
|
-
if (rawEditorHint === "vscode") editorHint = "code";
|
|
746
|
-
else if (rawEditorHint === "vscode-insiders") editorHint = "code-insiders";
|
|
747
|
-
else if (rawEditorHint === "vscodium") editorHint = "codium";
|
|
748
|
-
else if (rawEditorHint === "trae-cn" || rawEditorHint === "trae") editorHint = "trae";
|
|
749
|
-
serverLogger.debug(
|
|
750
|
-
`IDE_OPEN: activeIde=${activeIde}, activeIdeScheme=${activeIdeScheme}, configuredIde=${configuredIde} -> rawEditorHint=${rawEditorHint}, finalEditorHint=${editorHint}`
|
|
751
|
-
);
|
|
752
|
-
const VSCODE_FAMILY_SCHEMES = [
|
|
753
|
-
"vscode",
|
|
754
|
-
"vscode-insiders",
|
|
755
|
-
"cursor",
|
|
756
|
-
"windsurf",
|
|
757
|
-
"trae",
|
|
758
|
-
"trae-cn",
|
|
759
|
-
"vscodium",
|
|
760
|
-
"codebuddy",
|
|
761
|
-
"codebuddy-cn",
|
|
762
|
-
"antigravity"
|
|
763
|
-
];
|
|
764
|
-
if (VSCODE_FAMILY_SCHEMES.includes(rawEditorHint)) {
|
|
765
|
-
const uri = `${rawEditorHint}://file${absolutePath}:${body.line}:${body.column}`;
|
|
766
|
-
serverLogger.debug(`IDE_OPEN: Bypassing launchIDE, using URI scheme directly: ${uri}`);
|
|
767
|
-
try {
|
|
768
|
-
if (process.platform === "darwin") {
|
|
769
|
-
(0, import_node_child_process.execFileSync)("open", [uri]);
|
|
770
|
-
} else if (process.platform === "win32") {
|
|
771
|
-
(0, import_node_child_process.execFileSync)("cmd", ["/c", "start", '""', uri]);
|
|
772
|
-
} else {
|
|
773
|
-
(0, import_node_child_process.execFileSync)("xdg-open", [uri]);
|
|
774
|
-
}
|
|
775
|
-
} catch (e) {
|
|
776
|
-
serverLogger.error(`Failed to launch URI for IDE_OPEN (${uri}):`, e);
|
|
777
|
-
(0, import_launch_ide.launchIDE)({
|
|
778
|
-
file: absolutePath,
|
|
779
|
-
line: body.line,
|
|
780
|
-
column: body.column,
|
|
781
|
-
editor: editorHint,
|
|
782
|
-
type: process.platform === "darwin" ? "open" : "exec"
|
|
783
|
-
});
|
|
784
|
-
}
|
|
785
|
-
} else {
|
|
786
|
-
(0, import_launch_ide.launchIDE)({
|
|
787
|
-
file: absolutePath,
|
|
788
|
-
line: body.line,
|
|
789
|
-
column: body.column,
|
|
790
|
-
editor: editorHint,
|
|
791
|
-
type: process.platform === "darwin" ? "open" : "exec"
|
|
792
|
-
});
|
|
793
|
-
}
|
|
794
1060
|
res.writeHead(200, { "Content-Type": "application/json" });
|
|
795
1061
|
res.end(JSON.stringify({ success: true }));
|
|
796
1062
|
return;
|
|
@@ -801,10 +1067,11 @@ async function handleRequest(url, req, res) {
|
|
|
801
1067
|
const column = parseInt(url.searchParams.get("column") ?? "1", 10);
|
|
802
1068
|
const maxLines = parseInt(url.searchParams.get("maxLines") ?? "100", 10);
|
|
803
1069
|
try {
|
|
804
|
-
const absolutePath =
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
1070
|
+
const absolutePath = resolveWorkspacePath(file, serverState.cwd);
|
|
1071
|
+
try {
|
|
1072
|
+
assertPathWithinProject(absolutePath, serverState.projectRoot);
|
|
1073
|
+
} catch {
|
|
1074
|
+
serverLogger4.warn(`Security: Blocked path traversal attempt in PROJECT_SNIPPET: ${file}`);
|
|
808
1075
|
res.writeHead(403, { "Content-Type": "application/json" });
|
|
809
1076
|
res.end(
|
|
810
1077
|
JSON.stringify({
|
|
@@ -834,7 +1101,23 @@ async function handleRequest(url, req, res) {
|
|
|
834
1101
|
res.writeHead(result.success ? 200 : 500, { "Content-Type": "application/json" });
|
|
835
1102
|
res.end(JSON.stringify(result));
|
|
836
1103
|
} catch (e) {
|
|
837
|
-
|
|
1104
|
+
serverLogger4.error(`Error parsing ${import_types2.INSPECTO_API_PATHS.AI_DISPATCH} request:`, e);
|
|
1105
|
+
res.writeHead(500, { "Content-Type": "application/json" });
|
|
1106
|
+
res.end(JSON.stringify({ success: false, error: String(e), errorCode: "INTERNAL_ERROR" }));
|
|
1107
|
+
}
|
|
1108
|
+
return;
|
|
1109
|
+
}
|
|
1110
|
+
if (pathname === import_types2.INSPECTO_API_PATHS.AI_BATCH_DISPATCH && req.method === "POST") {
|
|
1111
|
+
try {
|
|
1112
|
+
const rawBody = await readBody(req);
|
|
1113
|
+
const body = JSON.parse(rawBody);
|
|
1114
|
+
const result = await dispatchAnnotationsToAi(body, serverState);
|
|
1115
|
+
res.writeHead(getBatchDispatchStatusCode(result.errorCode, result.success), {
|
|
1116
|
+
"Content-Type": "application/json"
|
|
1117
|
+
});
|
|
1118
|
+
res.end(JSON.stringify(result));
|
|
1119
|
+
} catch (e) {
|
|
1120
|
+
serverLogger4.error(`Error parsing ${import_types2.INSPECTO_API_PATHS.AI_BATCH_DISPATCH} request:`, e);
|
|
838
1121
|
res.writeHead(500, { "Content-Type": "application/json" });
|
|
839
1122
|
res.end(JSON.stringify({ success: false, error: String(e), errorCode: "INTERNAL_ERROR" }));
|
|
840
1123
|
}
|
|
@@ -842,7 +1125,7 @@ async function handleRequest(url, req, res) {
|
|
|
842
1125
|
}
|
|
843
1126
|
if (pathname.startsWith(`${import_types2.INSPECTO_API_PATHS.AI_TICKET}/`) && req.method === "GET") {
|
|
844
1127
|
const ticketId = pathname.substring(import_types2.INSPECTO_API_PATHS.AI_TICKET.length + 1);
|
|
845
|
-
const payloadStr =
|
|
1128
|
+
const payloadStr = readTicket(ticketId);
|
|
846
1129
|
if (!payloadStr) {
|
|
847
1130
|
res.writeHead(404, { "Content-Type": "application/json" });
|
|
848
1131
|
res.end(JSON.stringify({ success: false, error: "Ticket not found or expired" }));
|
|
@@ -856,58 +1139,32 @@ async function handleRequest(url, req, res) {
|
|
|
856
1139
|
res.end(JSON.stringify({ error: "not found" }));
|
|
857
1140
|
}
|
|
858
1141
|
async function dispatchToAi(req) {
|
|
859
|
-
const { location, snippet, prompt } = req;
|
|
860
|
-
const userConfig = loadUserConfigSync(false, serverState.cwd, serverState.configRoot);
|
|
861
|
-
const resolvedTarget = resolveTargetTool(userConfig);
|
|
1142
|
+
const { location, snippet, prompt, screenshotContext } = req;
|
|
862
1143
|
const formattedPrompt = prompt ?? `Please help me with this code from \`${location.file}\` (line ${location.line}):
|
|
863
1144
|
|
|
864
1145
|
\`\`\`
|
|
865
1146
|
${snippet}
|
|
866
1147
|
\`\`\`
|
|
867
1148
|
`;
|
|
868
|
-
const
|
|
869
|
-
|
|
870
|
-
const activeIde = serverState.ideInfo?.ide;
|
|
871
|
-
const activeIdeScheme = serverState.ideInfo?.scheme;
|
|
872
|
-
const finalIde = configuredIde || activeIdeScheme || activeIde || "vscode";
|
|
873
|
-
if (configuredIde && activeIdeScheme && !activeIdeScheme.includes(configuredIde)) {
|
|
874
|
-
serverLogger.warn(
|
|
875
|
-
`dispatchToAi: Active IDE is ${activeIdeScheme}, but config forces ${configuredIde}. Using configured IDE.`
|
|
876
|
-
);
|
|
877
|
-
}
|
|
878
|
-
const mode = resolveProviderMode(resolvedTarget, finalIde, userConfig);
|
|
879
|
-
const overrides = extractToolOverrides(finalIde, userConfig)[resolvedTarget] || {};
|
|
880
|
-
overrides.type = mode;
|
|
881
|
-
const fullPayload = {
|
|
882
|
-
ide: finalIde,
|
|
883
|
-
target: resolvedTarget,
|
|
884
|
-
targetType: mode,
|
|
1149
|
+
const runtime = resolvePromptDispatchRuntime(serverState);
|
|
1150
|
+
return dispatchPromptThroughIde(runtime, {
|
|
885
1151
|
prompt: formattedPrompt,
|
|
886
1152
|
filePath: location.file,
|
|
887
1153
|
line: location.line,
|
|
888
1154
|
column: location.column,
|
|
889
1155
|
snippet,
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
serverLogger.debug(`dispatchToAi: Generated URI: ${uri}`);
|
|
899
|
-
launchURI(uri);
|
|
900
|
-
return {
|
|
901
|
-
success: true,
|
|
902
|
-
fallbackPayload: {
|
|
903
|
-
prompt: formattedPrompt,
|
|
904
|
-
file: location.file
|
|
905
|
-
}
|
|
906
|
-
};
|
|
1156
|
+
...screenshotContext ? { screenshotContext } : {}
|
|
1157
|
+
});
|
|
1158
|
+
}
|
|
1159
|
+
function getBatchDispatchStatusCode(errorCode, success) {
|
|
1160
|
+
if (success) return 200;
|
|
1161
|
+
if (errorCode === "INVALID_REQUEST") return 400;
|
|
1162
|
+
if (errorCode === "FORBIDDEN_PATH") return 403;
|
|
1163
|
+
return 500;
|
|
907
1164
|
}
|
|
908
1165
|
|
|
909
1166
|
// src/legacy/webpack4/index.ts
|
|
910
|
-
var
|
|
1167
|
+
var import_node_path5 = __toESM(require("path"), 1);
|
|
911
1168
|
var InspectoWebpack4Plugin = class {
|
|
912
1169
|
constructor(options = {}) {
|
|
913
1170
|
this.options = options;
|
|
@@ -915,7 +1172,7 @@ var InspectoWebpack4Plugin = class {
|
|
|
915
1172
|
apply(compiler) {
|
|
916
1173
|
const clientPath = resolveClientModule();
|
|
917
1174
|
compiler.hooks.afterEnvironment.tap("InspectoWebpack4Plugin", () => {
|
|
918
|
-
const inspectoLoader =
|
|
1175
|
+
const inspectoLoader = import_node_path5.default.resolve(__dirname, "loader.cjs");
|
|
919
1176
|
compiler.options.module.rules.push({
|
|
920
1177
|
test: /\.[jt]sx?$/,
|
|
921
1178
|
enforce: "pre",
|