@inspecto-dev/plugin 0.2.0-alpha.4 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/index.cjs +444 -203
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +443 -202
- package/dist/index.js.map +1 -1
- package/dist/legacy/rspack/index.cjs +446 -205
- package/dist/legacy/rspack/index.cjs.map +1 -1
- package/dist/legacy/rspack/index.js +445 -204
- package/dist/legacy/rspack/index.js.map +1 -1
- package/dist/legacy/webpack4/index.cjs +446 -205
- package/dist/legacy/webpack4/index.cjs.map +1 -1
- package/dist/legacy/webpack4/index.js +445 -204
- package/dist/legacy/webpack4/index.js.map +1 -1
- package/dist/rollup.cjs +444 -203
- package/dist/rollup.cjs.map +1 -1
- package/dist/rollup.js +443 -202
- package/dist/rollup.js.map +1 -1
- package/dist/rspack.cjs +444 -203
- package/dist/rspack.cjs.map +1 -1
- package/dist/rspack.js +443 -202
- package/dist/rspack.js.map +1 -1
- package/dist/vite.cjs +444 -203
- package/dist/vite.cjs.map +1 -1
- package/dist/vite.js +443 -202
- package/dist/vite.js.map +1 -1
- package/dist/webpack.cjs +444 -203
- package/dist/webpack.cjs.map +1 -1
- package/dist/webpack.js +443 -202
- 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,21 +525,363 @@ function createTicket(payload) {
|
|
|
530
525
|
);
|
|
531
526
|
return ticketId;
|
|
532
527
|
}
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
528
|
+
function readTicket(ticketId) {
|
|
529
|
+
return payloadTickets.get(ticketId);
|
|
530
|
+
}
|
|
531
|
+
function launchURI(uri) {
|
|
532
|
+
try {
|
|
533
|
+
if (process.platform === "darwin") {
|
|
534
|
+
(0, import_node_child_process.execFileSync)("open", [uri]);
|
|
535
|
+
} else if (process.platform === "win32") {
|
|
536
|
+
(0, import_node_child_process.execFileSync)("cmd", ["/c", "start", '""', uri]);
|
|
537
|
+
} else {
|
|
538
|
+
(0, import_node_child_process.execFileSync)("xdg-open", [uri]);
|
|
539
|
+
}
|
|
540
|
+
} catch (e) {
|
|
541
|
+
serverLogger.error("Failed to launch URI via execFileSync, falling back to launchIDE:", e);
|
|
542
|
+
(0, import_launch_ide.launchIDE)({ file: uri });
|
|
543
|
+
}
|
|
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
|
+
}
|
|
539
622
|
};
|
|
540
|
-
|
|
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() });
|
|
541
878
|
function resolveProjectRoot() {
|
|
542
879
|
const cwd = process.cwd();
|
|
543
880
|
let gitRoot;
|
|
544
881
|
try {
|
|
545
|
-
gitRoot = (0,
|
|
882
|
+
gitRoot = (0, import_node_child_process3.execSync)("git rev-parse --show-toplevel", { encoding: "utf-8" }).trim();
|
|
546
883
|
} catch (e) {
|
|
547
|
-
|
|
884
|
+
serverLogger3.warn("Failed to resolve git root via git rev-parse:", e);
|
|
548
885
|
gitRoot = cwd;
|
|
549
886
|
}
|
|
550
887
|
const visited = /* @__PURE__ */ new Set();
|
|
@@ -552,34 +889,31 @@ function resolveProjectRoot() {
|
|
|
552
889
|
let current = start;
|
|
553
890
|
while (!visited.has(current)) {
|
|
554
891
|
visited.add(current);
|
|
555
|
-
if (import_node_fs2.default.existsSync(
|
|
892
|
+
if (import_node_fs2.default.existsSync(import_node_path3.default.join(current, ".inspecto"))) return current;
|
|
556
893
|
if (current === stop) break;
|
|
557
|
-
const parent =
|
|
894
|
+
const parent = import_node_path3.default.dirname(current);
|
|
558
895
|
if (parent === current) break;
|
|
559
896
|
current = parent;
|
|
560
897
|
}
|
|
561
898
|
return null;
|
|
562
899
|
};
|
|
563
|
-
const cwdMatch = search(cwd,
|
|
900
|
+
const cwdMatch = search(cwd, import_node_path3.default.parse(cwd).root);
|
|
564
901
|
if (cwdMatch) return cwdMatch;
|
|
565
|
-
const repoMatch = search(gitRoot,
|
|
902
|
+
const repoMatch = search(gitRoot, import_node_path3.default.parse(gitRoot).root);
|
|
566
903
|
if (repoMatch) return repoMatch;
|
|
567
904
|
return gitRoot;
|
|
568
905
|
}
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
(0, import_launch_ide.launchIDE)({ file: uri });
|
|
581
|
-
}
|
|
582
|
-
}
|
|
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;
|
|
583
917
|
async function startServer() {
|
|
584
918
|
if (serverState.running && serverState.port !== null) {
|
|
585
919
|
return serverState.port;
|
|
@@ -591,7 +925,7 @@ async function startServer() {
|
|
|
591
925
|
const port = await import_portfinder.default.getPortPromise();
|
|
592
926
|
watchConfig(
|
|
593
927
|
() => {
|
|
594
|
-
|
|
928
|
+
serverLogger4.info("user config reloaded.");
|
|
595
929
|
},
|
|
596
930
|
serverState.cwd,
|
|
597
931
|
serverState.configRoot
|
|
@@ -607,7 +941,7 @@ async function startServer() {
|
|
|
607
941
|
}
|
|
608
942
|
const url = new URL(req.url ?? "/", `http://localhost:${port}`);
|
|
609
943
|
handleRequest(url, req, res).catch((err) => {
|
|
610
|
-
|
|
944
|
+
serverLogger4.error("server error:", err);
|
|
611
945
|
res.writeHead(500, { "Content-Type": "application/json" });
|
|
612
946
|
res.end(JSON.stringify({ success: false, error: String(err) }));
|
|
613
947
|
});
|
|
@@ -620,41 +954,41 @@ async function startServer() {
|
|
|
620
954
|
serverInstance.once("error", reject);
|
|
621
955
|
});
|
|
622
956
|
serverInstance.on("error", (err) => {
|
|
623
|
-
|
|
957
|
+
serverLogger4.error("persistent server error:", err);
|
|
624
958
|
});
|
|
625
959
|
serverState.port = port;
|
|
626
960
|
serverState.running = true;
|
|
627
|
-
const portFile =
|
|
961
|
+
const portFile = import_node_path4.default.join(import_node_os2.default.tmpdir(), "inspecto.port.json");
|
|
628
962
|
try {
|
|
629
963
|
let portData = {};
|
|
630
|
-
if (
|
|
964
|
+
if (import_node_fs3.default.existsSync(portFile)) {
|
|
631
965
|
try {
|
|
632
|
-
portData = JSON.parse(
|
|
966
|
+
portData = JSON.parse(import_node_fs3.default.readFileSync(portFile, "utf-8"));
|
|
633
967
|
} catch (e) {
|
|
634
968
|
}
|
|
635
969
|
}
|
|
636
|
-
const rootHash =
|
|
970
|
+
const rootHash = import_node_crypto2.default.createHash("md5").update(serverState.projectRoot).digest("hex");
|
|
637
971
|
portData[rootHash] = port;
|
|
638
|
-
|
|
972
|
+
import_node_fs3.default.writeFileSync(portFile, JSON.stringify(portData, null, 2), "utf-8");
|
|
639
973
|
} catch (e) {
|
|
640
|
-
|
|
974
|
+
serverLogger4.warn("Failed to write port file:", e);
|
|
641
975
|
}
|
|
642
976
|
process.once("exit", () => {
|
|
643
977
|
try {
|
|
644
|
-
if (
|
|
645
|
-
const portData = JSON.parse(
|
|
646
|
-
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");
|
|
647
981
|
delete portData[rootHash];
|
|
648
982
|
if (Object.keys(portData).length === 0) {
|
|
649
|
-
|
|
983
|
+
import_node_fs3.default.unlinkSync(portFile);
|
|
650
984
|
} else {
|
|
651
|
-
|
|
985
|
+
import_node_fs3.default.writeFileSync(portFile, JSON.stringify(portData, null, 2), "utf-8");
|
|
652
986
|
}
|
|
653
987
|
}
|
|
654
988
|
} catch {
|
|
655
989
|
}
|
|
656
990
|
});
|
|
657
|
-
|
|
991
|
+
serverLogger4.info(`server running at http://127.0.0.1:${port}`);
|
|
658
992
|
return port;
|
|
659
993
|
}
|
|
660
994
|
async function readBody(req) {
|
|
@@ -673,26 +1007,7 @@ async function handleRequest(url, req, res) {
|
|
|
673
1007
|
return;
|
|
674
1008
|
}
|
|
675
1009
|
if (pathname === import_types2.INSPECTO_API_PATHS.CLIENT_CONFIG && req.method === "GET") {
|
|
676
|
-
const
|
|
677
|
-
const promptsConfig = await loadPromptsConfig(false, serverState.cwd, serverState.configRoot);
|
|
678
|
-
const effectiveIde = userConfig.ide ?? "vscode";
|
|
679
|
-
let info;
|
|
680
|
-
if (!serverState.ideInfo) {
|
|
681
|
-
info = {
|
|
682
|
-
ide: effectiveIde
|
|
683
|
-
};
|
|
684
|
-
} else {
|
|
685
|
-
const { scheme: _scheme, ...rest } = serverState.ideInfo;
|
|
686
|
-
info = rest;
|
|
687
|
-
}
|
|
688
|
-
const config = {
|
|
689
|
-
...info,
|
|
690
|
-
prompts: resolveIntents(promptsConfig),
|
|
691
|
-
hotKeys: userConfig["inspector.hotKey"] ?? "alt",
|
|
692
|
-
theme: userConfig["inspector.theme"] ?? "auto",
|
|
693
|
-
includeSnippet: userConfig["prompt.includeSnippet"] ?? false,
|
|
694
|
-
autoSend: userConfig["prompt.autoSend"] ?? false
|
|
695
|
-
};
|
|
1010
|
+
const config = await buildClientConfig(serverState);
|
|
696
1011
|
delete config.providers;
|
|
697
1012
|
res.writeHead(200, { "Content-Type": "application/json" });
|
|
698
1013
|
res.end(JSON.stringify(config));
|
|
@@ -703,23 +1018,23 @@ async function handleRequest(url, req, res) {
|
|
|
703
1018
|
const body = JSON.parse(await readBody(req));
|
|
704
1019
|
const ideWorkspace = body.workspaceRoot || "";
|
|
705
1020
|
const serverProjectRoot = serverState.projectRoot || "";
|
|
706
|
-
const normalizedIdeRoot = ideWorkspace ?
|
|
707
|
-
const normalizedServerRoot = serverProjectRoot ?
|
|
708
|
-
const isSameProject = !normalizedIdeRoot || !normalizedServerRoot || normalizedIdeRoot === normalizedServerRoot || normalizedServerRoot.startsWith(normalizedIdeRoot +
|
|
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);
|
|
709
1024
|
if (isSameProject) {
|
|
710
1025
|
serverState.ideInfo = body;
|
|
711
|
-
|
|
1026
|
+
serverLogger4.debug(
|
|
712
1027
|
`Accepted IDE info from matched workspace (ide-${body.ide} / schema-${body.scheme})`
|
|
713
1028
|
);
|
|
714
1029
|
} else {
|
|
715
|
-
|
|
1030
|
+
serverLogger4.debug(
|
|
716
1031
|
`Ignored IDE info from unrelated workspace (IDE Workspace: ${ideWorkspace}, Server: ${serverProjectRoot}, Scheme: ${body.scheme}, IDE: ${body.ide})`
|
|
717
1032
|
);
|
|
718
1033
|
}
|
|
719
1034
|
res.writeHead(200, { "Content-Type": "application/json" });
|
|
720
1035
|
res.end(JSON.stringify({ success: true }));
|
|
721
1036
|
} catch (e) {
|
|
722
|
-
|
|
1037
|
+
serverLogger4.error(`Error parsing ${import_types2.INSPECTO_API_PATHS.IDE_INFO} POST request:`, e);
|
|
723
1038
|
res.writeHead(400, { "Content-Type": "application/json" });
|
|
724
1039
|
res.end(JSON.stringify({ error: "Invalid JSON body" }));
|
|
725
1040
|
}
|
|
@@ -734,79 +1049,14 @@ async function handleRequest(url, req, res) {
|
|
|
734
1049
|
res.end(JSON.stringify({ error: "Invalid JSON body" }));
|
|
735
1050
|
return;
|
|
736
1051
|
}
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
1052
|
+
try {
|
|
1053
|
+
handleOpenFileRequest(body, serverState);
|
|
1054
|
+
} catch {
|
|
1055
|
+
serverLogger4.warn(`Security: Blocked path traversal attempt in IDE_OPEN: ${body.file}`);
|
|
741
1056
|
res.writeHead(403, { "Content-Type": "application/json" });
|
|
742
1057
|
res.end(JSON.stringify({ error: "Access denied: File is outside of project workspace" }));
|
|
743
1058
|
return;
|
|
744
1059
|
}
|
|
745
|
-
const userConfig = loadUserConfigSync(false, serverState.cwd, serverState.configRoot);
|
|
746
|
-
const configuredIde = userConfig.ide;
|
|
747
|
-
const activeIde = serverState.ideInfo?.ide;
|
|
748
|
-
const activeIdeScheme = serverState.ideInfo?.scheme;
|
|
749
|
-
const rawEditorHint = configuredIde || activeIde || activeIdeScheme || "code";
|
|
750
|
-
if (configuredIde && activeIdeScheme && !activeIdeScheme.includes(configuredIde)) {
|
|
751
|
-
serverLogger.warn(
|
|
752
|
-
`Active IDE is ${activeIdeScheme}, but config forces ${configuredIde}. Using configured IDE.`
|
|
753
|
-
);
|
|
754
|
-
}
|
|
755
|
-
let editorHint = rawEditorHint;
|
|
756
|
-
if (rawEditorHint === "vscode") editorHint = "code";
|
|
757
|
-
else if (rawEditorHint === "vscode-insiders") editorHint = "code-insiders";
|
|
758
|
-
else if (rawEditorHint === "vscodium") editorHint = "codium";
|
|
759
|
-
else if (rawEditorHint === "trae-cn" || rawEditorHint === "trae") editorHint = "trae";
|
|
760
|
-
serverLogger.debug(
|
|
761
|
-
`IDE_OPEN: activeIde=${activeIde}, activeIdeScheme=${activeIdeScheme}, configuredIde=${configuredIde} -> rawEditorHint=${rawEditorHint}, finalEditorHint=${editorHint}`
|
|
762
|
-
);
|
|
763
|
-
const VSCODE_FAMILY_SCHEMES = [
|
|
764
|
-
"vscode",
|
|
765
|
-
"vscode-insiders",
|
|
766
|
-
"cursor",
|
|
767
|
-
"windsurf",
|
|
768
|
-
"trae",
|
|
769
|
-
"trae-cn",
|
|
770
|
-
"vscodium",
|
|
771
|
-
"codebuddy",
|
|
772
|
-
"codebuddy-cn",
|
|
773
|
-
"antigravity"
|
|
774
|
-
];
|
|
775
|
-
if (VSCODE_FAMILY_SCHEMES.includes(rawEditorHint)) {
|
|
776
|
-
let normalizedPath = absolutePath.replace(/\\/g, "/");
|
|
777
|
-
if (!normalizedPath.startsWith("/")) {
|
|
778
|
-
normalizedPath = "/" + normalizedPath;
|
|
779
|
-
}
|
|
780
|
-
const encodedPath = encodeURI(normalizedPath);
|
|
781
|
-
const uri = `${rawEditorHint}://file${encodedPath}:${body.line}:${body.column}`;
|
|
782
|
-
serverLogger.debug(`IDE_OPEN: Bypassing launchIDE, using URI scheme directly: ${uri}`);
|
|
783
|
-
try {
|
|
784
|
-
if (process.platform === "darwin") {
|
|
785
|
-
(0, import_node_child_process.execFileSync)("open", [uri]);
|
|
786
|
-
} else if (process.platform === "win32") {
|
|
787
|
-
(0, import_node_child_process.execFileSync)("cmd", ["/c", "start", '""', uri]);
|
|
788
|
-
} else {
|
|
789
|
-
(0, import_node_child_process.execFileSync)("xdg-open", [uri]);
|
|
790
|
-
}
|
|
791
|
-
} catch (e) {
|
|
792
|
-
serverLogger.error(`Failed to launch URI for IDE_OPEN (${uri}):`, e);
|
|
793
|
-
(0, import_launch_ide.launchIDE)({
|
|
794
|
-
file: absolutePath,
|
|
795
|
-
line: body.line,
|
|
796
|
-
column: body.column,
|
|
797
|
-
editor: editorHint,
|
|
798
|
-
type: process.platform === "darwin" ? "open" : "exec"
|
|
799
|
-
});
|
|
800
|
-
}
|
|
801
|
-
} else {
|
|
802
|
-
(0, import_launch_ide.launchIDE)({
|
|
803
|
-
file: absolutePath,
|
|
804
|
-
line: body.line,
|
|
805
|
-
column: body.column,
|
|
806
|
-
editor: editorHint,
|
|
807
|
-
type: process.platform === "darwin" ? "open" : "exec"
|
|
808
|
-
});
|
|
809
|
-
}
|
|
810
1060
|
res.writeHead(200, { "Content-Type": "application/json" });
|
|
811
1061
|
res.end(JSON.stringify({ success: true }));
|
|
812
1062
|
return;
|
|
@@ -817,10 +1067,11 @@ async function handleRequest(url, req, res) {
|
|
|
817
1067
|
const column = parseInt(url.searchParams.get("column") ?? "1", 10);
|
|
818
1068
|
const maxLines = parseInt(url.searchParams.get("maxLines") ?? "100", 10);
|
|
819
1069
|
try {
|
|
820
|
-
const absolutePath =
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
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}`);
|
|
824
1075
|
res.writeHead(403, { "Content-Type": "application/json" });
|
|
825
1076
|
res.end(
|
|
826
1077
|
JSON.stringify({
|
|
@@ -850,7 +1101,23 @@ async function handleRequest(url, req, res) {
|
|
|
850
1101
|
res.writeHead(result.success ? 200 : 500, { "Content-Type": "application/json" });
|
|
851
1102
|
res.end(JSON.stringify(result));
|
|
852
1103
|
} catch (e) {
|
|
853
|
-
|
|
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);
|
|
854
1121
|
res.writeHead(500, { "Content-Type": "application/json" });
|
|
855
1122
|
res.end(JSON.stringify({ success: false, error: String(e), errorCode: "INTERNAL_ERROR" }));
|
|
856
1123
|
}
|
|
@@ -858,7 +1125,7 @@ async function handleRequest(url, req, res) {
|
|
|
858
1125
|
}
|
|
859
1126
|
if (pathname.startsWith(`${import_types2.INSPECTO_API_PATHS.AI_TICKET}/`) && req.method === "GET") {
|
|
860
1127
|
const ticketId = pathname.substring(import_types2.INSPECTO_API_PATHS.AI_TICKET.length + 1);
|
|
861
|
-
const payloadStr =
|
|
1128
|
+
const payloadStr = readTicket(ticketId);
|
|
862
1129
|
if (!payloadStr) {
|
|
863
1130
|
res.writeHead(404, { "Content-Type": "application/json" });
|
|
864
1131
|
res.end(JSON.stringify({ success: false, error: "Ticket not found or expired" }));
|
|
@@ -872,58 +1139,32 @@ async function handleRequest(url, req, res) {
|
|
|
872
1139
|
res.end(JSON.stringify({ error: "not found" }));
|
|
873
1140
|
}
|
|
874
1141
|
async function dispatchToAi(req) {
|
|
875
|
-
const { location, snippet, prompt } = req;
|
|
876
|
-
const userConfig = loadUserConfigSync(false, serverState.cwd, serverState.configRoot);
|
|
877
|
-
const resolvedTarget = resolveTargetTool(userConfig);
|
|
1142
|
+
const { location, snippet, prompt, screenshotContext } = req;
|
|
878
1143
|
const formattedPrompt = prompt ?? `Please help me with this code from \`${location.file}\` (line ${location.line}):
|
|
879
1144
|
|
|
880
1145
|
\`\`\`
|
|
881
1146
|
${snippet}
|
|
882
1147
|
\`\`\`
|
|
883
1148
|
`;
|
|
884
|
-
const
|
|
885
|
-
|
|
886
|
-
const activeIde = serverState.ideInfo?.ide;
|
|
887
|
-
const activeIdeScheme = serverState.ideInfo?.scheme;
|
|
888
|
-
const finalIde = configuredIde || activeIdeScheme || activeIde || "vscode";
|
|
889
|
-
if (configuredIde && activeIdeScheme && !activeIdeScheme.includes(configuredIde)) {
|
|
890
|
-
serverLogger.warn(
|
|
891
|
-
`dispatchToAi: Active IDE is ${activeIdeScheme}, but config forces ${configuredIde}. Using configured IDE.`
|
|
892
|
-
);
|
|
893
|
-
}
|
|
894
|
-
const mode = resolveProviderMode(resolvedTarget, finalIde, userConfig);
|
|
895
|
-
const overrides = extractToolOverrides(finalIde, userConfig)[resolvedTarget] || {};
|
|
896
|
-
overrides.type = mode;
|
|
897
|
-
const fullPayload = {
|
|
898
|
-
ide: finalIde,
|
|
899
|
-
target: resolvedTarget,
|
|
900
|
-
targetType: mode,
|
|
1149
|
+
const runtime = resolvePromptDispatchRuntime(serverState);
|
|
1150
|
+
return dispatchPromptThroughIde(runtime, {
|
|
901
1151
|
prompt: formattedPrompt,
|
|
902
1152
|
filePath: location.file,
|
|
903
1153
|
line: location.line,
|
|
904
1154
|
column: location.column,
|
|
905
1155
|
snippet,
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
serverLogger.debug(`dispatchToAi: Generated URI: ${uri}`);
|
|
915
|
-
launchURI(uri);
|
|
916
|
-
return {
|
|
917
|
-
success: true,
|
|
918
|
-
fallbackPayload: {
|
|
919
|
-
prompt: formattedPrompt,
|
|
920
|
-
file: location.file
|
|
921
|
-
}
|
|
922
|
-
};
|
|
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;
|
|
923
1164
|
}
|
|
924
1165
|
|
|
925
1166
|
// src/legacy/webpack4/index.ts
|
|
926
|
-
var
|
|
1167
|
+
var import_node_path5 = __toESM(require("path"), 1);
|
|
927
1168
|
var InspectoWebpack4Plugin = class {
|
|
928
1169
|
constructor(options = {}) {
|
|
929
1170
|
this.options = options;
|
|
@@ -931,7 +1172,7 @@ var InspectoWebpack4Plugin = class {
|
|
|
931
1172
|
apply(compiler) {
|
|
932
1173
|
const clientPath = resolveClientModule();
|
|
933
1174
|
compiler.hooks.afterEnvironment.tap("InspectoWebpack4Plugin", () => {
|
|
934
|
-
const inspectoLoader =
|
|
1175
|
+
const inspectoLoader = import_node_path5.default.resolve(__dirname, "loader.cjs");
|
|
935
1176
|
compiler.options.module.rules.push({
|
|
936
1177
|
test: /\.[jt]sx?$/,
|
|
937
1178
|
enforce: "pre",
|