@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
|
@@ -42,13 +42,11 @@ var importMetaUrl = /* @__PURE__ */ getImportMetaUrl();
|
|
|
42
42
|
|
|
43
43
|
// src/server/index.ts
|
|
44
44
|
var import_node_http = __toESM(require("http"), 1);
|
|
45
|
-
var
|
|
46
|
-
var
|
|
45
|
+
var import_node_fs3 = __toESM(require("fs"), 1);
|
|
46
|
+
var import_node_path4 = __toESM(require("path"), 1);
|
|
47
47
|
var import_node_os2 = __toESM(require("os"), 1);
|
|
48
|
-
var
|
|
49
|
-
var import_node_child_process = require("child_process");
|
|
48
|
+
var import_node_crypto2 = __toESM(require("crypto"), 1);
|
|
50
49
|
var import_portfinder = __toESM(require("portfinder"), 1);
|
|
51
|
-
var import_launch_ide = require("launch-ide");
|
|
52
50
|
var import_types2 = require("@inspecto-dev/types");
|
|
53
51
|
|
|
54
52
|
// src/server/snippet.ts
|
|
@@ -368,9 +366,9 @@ function extractToolOverrides(ide, config) {
|
|
|
368
366
|
function resolveIntents(serverPrompts) {
|
|
369
367
|
const baseMap = /* @__PURE__ */ new Map();
|
|
370
368
|
for (const intent of import_types.DEFAULT_INTENTS) {
|
|
371
|
-
|
|
369
|
+
baseMap.set(intent.id, { ...intent });
|
|
372
370
|
}
|
|
373
|
-
const defaults = () =>
|
|
371
|
+
const defaults = () => Array.from(baseMap.values());
|
|
374
372
|
if (!serverPrompts) return defaults();
|
|
375
373
|
const isReplace = !Array.isArray(serverPrompts) && typeof serverPrompts === "object" && serverPrompts.$replace === true;
|
|
376
374
|
const promptsArray = Array.isArray(serverPrompts) ? serverPrompts : isReplace ? serverPrompts.items : [];
|
|
@@ -397,16 +395,18 @@ function resolveIntents(serverPrompts) {
|
|
|
397
395
|
);
|
|
398
396
|
continue;
|
|
399
397
|
}
|
|
400
|
-
if (item.
|
|
398
|
+
if (!item.aiIntent) {
|
|
401
399
|
configLogger.warn(
|
|
402
|
-
`
|
|
400
|
+
`Intent "${item.id}" is missing required "aiIntent".`
|
|
403
401
|
);
|
|
404
402
|
continue;
|
|
405
403
|
}
|
|
406
|
-
result.push(
|
|
404
|
+
result.push(
|
|
405
|
+
baseMap.has(item.id) ? { ...baseMap.get(item.id), ...item } : item
|
|
406
|
+
);
|
|
407
407
|
}
|
|
408
408
|
}
|
|
409
|
-
return
|
|
409
|
+
return result;
|
|
410
410
|
}
|
|
411
411
|
const merged = Array.from(baseMap.values());
|
|
412
412
|
for (const item of promptsArray) {
|
|
@@ -423,9 +423,9 @@ function resolveIntents(serverPrompts) {
|
|
|
423
423
|
configLogger.warn('Intent object missing required "id" field, skipping.');
|
|
424
424
|
continue;
|
|
425
425
|
}
|
|
426
|
-
if (item.
|
|
426
|
+
if (!item.aiIntent) {
|
|
427
427
|
configLogger.warn(
|
|
428
|
-
`
|
|
428
|
+
`Intent "${item.id}" is missing required "aiIntent".`
|
|
429
429
|
);
|
|
430
430
|
continue;
|
|
431
431
|
}
|
|
@@ -443,15 +443,7 @@ function resolveIntents(serverPrompts) {
|
|
|
443
443
|
}
|
|
444
444
|
}
|
|
445
445
|
}
|
|
446
|
-
return
|
|
447
|
-
}
|
|
448
|
-
function ensureOpenInEditorLast(intents) {
|
|
449
|
-
const idx = intents.findIndex((i) => i.id === "open-in-editor");
|
|
450
|
-
if (idx === -1 || idx === intents.length - 1) return intents;
|
|
451
|
-
const result = [...intents];
|
|
452
|
-
const item = result.splice(idx, 1)[0];
|
|
453
|
-
result.push(item);
|
|
454
|
-
return result;
|
|
446
|
+
return merged;
|
|
455
447
|
}
|
|
456
448
|
var watchers = [];
|
|
457
449
|
function watchConfig(onReload, cwd = process.cwd(), gitRoot) {
|
|
@@ -486,7 +478,10 @@ function watchConfig(onReload, cwd = process.cwd(), gitRoot) {
|
|
|
486
478
|
}
|
|
487
479
|
}
|
|
488
480
|
|
|
489
|
-
// src/server/
|
|
481
|
+
// src/server/dispatch-transport.ts
|
|
482
|
+
var import_node_crypto = __toESM(require("crypto"), 1);
|
|
483
|
+
var import_node_child_process = require("child_process");
|
|
484
|
+
var import_launch_ide = require("launch-ide");
|
|
490
485
|
var serverLogger = createLogger("inspecto:server", { logLevel: getGlobalLogLevel() });
|
|
491
486
|
var payloadTickets = /* @__PURE__ */ new Map();
|
|
492
487
|
function createTicket(payload) {
|
|
@@ -500,32 +495,8 @@ function createTicket(payload) {
|
|
|
500
495
|
);
|
|
501
496
|
return ticketId;
|
|
502
497
|
}
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
running: false,
|
|
506
|
-
projectRoot: "",
|
|
507
|
-
configRoot: "",
|
|
508
|
-
cwd: process.cwd()
|
|
509
|
-
};
|
|
510
|
-
var serverInstance = null;
|
|
511
|
-
function resolveProjectRoot() {
|
|
512
|
-
let gitRoot;
|
|
513
|
-
try {
|
|
514
|
-
serverLogger.info("Resolving project root...");
|
|
515
|
-
gitRoot = (0, import_node_child_process.execSync)("git rev-parse --show-toplevel", { encoding: "utf-8" }).trim();
|
|
516
|
-
serverLogger.info("Resolved project root: " + gitRoot);
|
|
517
|
-
} catch (e) {
|
|
518
|
-
serverLogger.error("Failed to resolve project root:", e);
|
|
519
|
-
gitRoot = process.cwd();
|
|
520
|
-
}
|
|
521
|
-
let current = gitRoot;
|
|
522
|
-
while (true) {
|
|
523
|
-
if (import_node_fs2.default.existsSync(import_node_path2.default.join(current, ".inspecto"))) return current;
|
|
524
|
-
const parent = import_node_path2.default.dirname(current);
|
|
525
|
-
if (parent === current) break;
|
|
526
|
-
current = parent;
|
|
527
|
-
}
|
|
528
|
-
return gitRoot;
|
|
498
|
+
function readTicket(ticketId) {
|
|
499
|
+
return payloadTickets.get(ticketId);
|
|
529
500
|
}
|
|
530
501
|
function launchURI(uri) {
|
|
531
502
|
try {
|
|
@@ -541,6 +512,378 @@ function launchURI(uri) {
|
|
|
541
512
|
(0, import_launch_ide.launchIDE)({ file: uri });
|
|
542
513
|
}
|
|
543
514
|
}
|
|
515
|
+
|
|
516
|
+
// src/server/dispatch-runtime.ts
|
|
517
|
+
function resolvePromptDispatchRuntime(state) {
|
|
518
|
+
const userConfig = loadUserConfigSync(false, state.cwd, state.projectRoot);
|
|
519
|
+
const resolvedTarget = resolveTargetTool(userConfig);
|
|
520
|
+
const finalIde = resolveFinalIde(userConfig.ide, state.ideInfo?.ide, state.ideInfo?.scheme);
|
|
521
|
+
const mode = resolveProviderMode(resolvedTarget, finalIde, userConfig);
|
|
522
|
+
const overrides = extractToolOverrides(finalIde, userConfig)[resolvedTarget] || void 0;
|
|
523
|
+
return {
|
|
524
|
+
resolvedTarget,
|
|
525
|
+
finalIde,
|
|
526
|
+
mode,
|
|
527
|
+
...hasOverrides(overrides) ? { overrides } : {},
|
|
528
|
+
...userConfig["prompt.autoSend"] !== void 0 ? { autoSend: Boolean(userConfig["prompt.autoSend"]) } : {}
|
|
529
|
+
};
|
|
530
|
+
}
|
|
531
|
+
function dispatchPromptThroughIde(runtime, payload) {
|
|
532
|
+
const ticketId = createTicket({
|
|
533
|
+
ide: runtime.finalIde,
|
|
534
|
+
target: runtime.resolvedTarget,
|
|
535
|
+
targetType: runtime.mode,
|
|
536
|
+
prompt: payload.prompt,
|
|
537
|
+
filePath: payload.filePath,
|
|
538
|
+
line: payload.line,
|
|
539
|
+
column: payload.column,
|
|
540
|
+
snippet: payload.snippet,
|
|
541
|
+
...payload.screenshotContext ? { screenshotContext: payload.screenshotContext } : {},
|
|
542
|
+
overrides: runtime.overrides,
|
|
543
|
+
autoSend: runtime.autoSend
|
|
544
|
+
});
|
|
545
|
+
const params = new URLSearchParams();
|
|
546
|
+
params.set("ticket", ticketId);
|
|
547
|
+
params.set("target", runtime.resolvedTarget);
|
|
548
|
+
launchURI(`${runtime.finalIde}://inspecto.inspecto/send?${params.toString()}`);
|
|
549
|
+
return {
|
|
550
|
+
success: true,
|
|
551
|
+
fallbackPayload: {
|
|
552
|
+
prompt: payload.prompt,
|
|
553
|
+
...payload.filePath ? { file: payload.filePath } : {}
|
|
554
|
+
}
|
|
555
|
+
};
|
|
556
|
+
}
|
|
557
|
+
function resolveFinalIde(configuredIde, activeIde, activeIdeScheme) {
|
|
558
|
+
if (configuredIde && activeIdeScheme && !activeIdeScheme.includes(configuredIde)) {
|
|
559
|
+
return configuredIde;
|
|
560
|
+
}
|
|
561
|
+
return configuredIde || activeIdeScheme || activeIde || "vscode";
|
|
562
|
+
}
|
|
563
|
+
function hasOverrides(overrides) {
|
|
564
|
+
return Boolean(overrides && Object.keys(overrides).length > 0);
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
// src/server/path-guards.ts
|
|
568
|
+
var import_node_path2 = __toESM(require("path"), 1);
|
|
569
|
+
function isWindowsAbsolutePath(file) {
|
|
570
|
+
return /^[a-zA-Z]:[\\/]/.test(file) || /^\\\\[^\\]+\\[^\\]+/.test(file);
|
|
571
|
+
}
|
|
572
|
+
function resolveWorkspacePath(file, cwd) {
|
|
573
|
+
if (isWindowsAbsolutePath(file)) {
|
|
574
|
+
return import_node_path2.default.win32.normalize(file);
|
|
575
|
+
}
|
|
576
|
+
return import_node_path2.default.isAbsolute(file) ? import_node_path2.default.resolve(file) : import_node_path2.default.resolve(cwd, file);
|
|
577
|
+
}
|
|
578
|
+
function assertPathWithinProject(file, projectRoot) {
|
|
579
|
+
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);
|
|
580
|
+
if (relativeToRoot.startsWith("..") || import_node_path2.default.isAbsolute(relativeToRoot)) {
|
|
581
|
+
throw new Error("Access denied: File is outside of project workspace");
|
|
582
|
+
}
|
|
583
|
+
}
|
|
584
|
+
|
|
585
|
+
// src/server/annotation-dispatch.ts
|
|
586
|
+
var AnnotationDispatchError = class extends Error {
|
|
587
|
+
constructor(message, errorCode) {
|
|
588
|
+
super(message);
|
|
589
|
+
this.name = "AnnotationDispatchError";
|
|
590
|
+
this.errorCode = errorCode;
|
|
591
|
+
}
|
|
592
|
+
};
|
|
593
|
+
async function dispatchAnnotationsToAi(req, state) {
|
|
594
|
+
try {
|
|
595
|
+
validateAnnotationDispatchRequest(req, state);
|
|
596
|
+
const batch = normalizeAnnotationBatch(req);
|
|
597
|
+
const prompt = buildAnnotationBatchPrompt(batch);
|
|
598
|
+
const representativeTarget = batch.annotations[0]?.targets[0];
|
|
599
|
+
const runtime = resolvePromptDispatchRuntime(state);
|
|
600
|
+
return dispatchPromptThroughIde(runtime, {
|
|
601
|
+
prompt,
|
|
602
|
+
...representativeTarget?.file ? { filePath: representativeTarget.file } : {},
|
|
603
|
+
...representativeTarget?.line ? { line: representativeTarget.line } : {},
|
|
604
|
+
...representativeTarget?.column ? { column: representativeTarget.column } : {},
|
|
605
|
+
...batch.screenshotContext ? { screenshotContext: batch.screenshotContext } : {}
|
|
606
|
+
});
|
|
607
|
+
} catch (error) {
|
|
608
|
+
return {
|
|
609
|
+
success: false,
|
|
610
|
+
error: error instanceof Error ? error.message : String(error),
|
|
611
|
+
errorCode: getAnnotationDispatchErrorCode(error)
|
|
612
|
+
};
|
|
613
|
+
}
|
|
614
|
+
}
|
|
615
|
+
function validateAnnotationDispatchRequest(req, state) {
|
|
616
|
+
if (!req.annotations.length) {
|
|
617
|
+
throw new AnnotationDispatchError("At least one annotation is required.", "INVALID_REQUEST");
|
|
618
|
+
}
|
|
619
|
+
for (const annotation of req.annotations) {
|
|
620
|
+
if (!annotation.targets.length) {
|
|
621
|
+
throw new AnnotationDispatchError(
|
|
622
|
+
"Each annotation must include at least one target.",
|
|
623
|
+
"INVALID_REQUEST"
|
|
624
|
+
);
|
|
625
|
+
}
|
|
626
|
+
for (const target of annotation.targets) {
|
|
627
|
+
const absolutePath = resolveWorkspacePath(target.location.file, state.cwd);
|
|
628
|
+
assertPathWithinProject(absolutePath, state.projectRoot);
|
|
629
|
+
}
|
|
630
|
+
}
|
|
631
|
+
}
|
|
632
|
+
function normalizeAnnotationBatch(req) {
|
|
633
|
+
return {
|
|
634
|
+
instruction: req.instruction?.trim() ?? "",
|
|
635
|
+
responseMode: req.responseMode ?? "unified",
|
|
636
|
+
...req.runtimeContext ? { runtimeContext: req.runtimeContext } : {},
|
|
637
|
+
...req.screenshotContext ? { screenshotContext: req.screenshotContext } : {},
|
|
638
|
+
...req.cssContextPrompt?.trim() ? { cssContextPrompt: req.cssContextPrompt.trim() } : {},
|
|
639
|
+
annotations: req.annotations.map((annotation, index) => ({
|
|
640
|
+
index: index + 1,
|
|
641
|
+
note: annotation.note.trim(),
|
|
642
|
+
intent: annotation.intent,
|
|
643
|
+
targets: annotation.targets.map((target) => ({
|
|
644
|
+
file: target.location.file,
|
|
645
|
+
line: target.location.line,
|
|
646
|
+
column: target.location.column,
|
|
647
|
+
...target.label ? { label: target.label } : {},
|
|
648
|
+
...target.selector ? { selector: target.selector } : {},
|
|
649
|
+
...target.snippet ? { snippet: target.snippet } : {}
|
|
650
|
+
}))
|
|
651
|
+
}))
|
|
652
|
+
};
|
|
653
|
+
}
|
|
654
|
+
function buildAnnotationBatchPrompt(batch) {
|
|
655
|
+
const body = buildSelectedElementsPrompt(batch.annotations);
|
|
656
|
+
const prompt = batch.instruction ? `${batch.instruction}
|
|
657
|
+
|
|
658
|
+
${body}` : body;
|
|
659
|
+
return appendScreenshotContextSection(
|
|
660
|
+
appendCssContextSection(
|
|
661
|
+
appendRuntimeContextSection(prompt, batch.runtimeContext),
|
|
662
|
+
batch.cssContextPrompt
|
|
663
|
+
),
|
|
664
|
+
batch.screenshotContext
|
|
665
|
+
);
|
|
666
|
+
}
|
|
667
|
+
function appendCssContextSection(prompt, cssContextPrompt) {
|
|
668
|
+
if (!cssContextPrompt) return prompt;
|
|
669
|
+
return `${prompt}
|
|
670
|
+
|
|
671
|
+
${cssContextPrompt}`;
|
|
672
|
+
}
|
|
673
|
+
function buildSelectedElementsPrompt(annotations) {
|
|
674
|
+
const lines = ["Selected elements:"];
|
|
675
|
+
for (const annotation of annotations) {
|
|
676
|
+
const trimmedNote = annotation.note.trim();
|
|
677
|
+
for (const target of annotation.targets) {
|
|
678
|
+
const targetLabel = (target.label || "Unknown target").trim() || "Unknown target";
|
|
679
|
+
lines.push(`- ${targetLabel}`);
|
|
680
|
+
lines.push(`file=${target.file}:${target.line}:${target.column}`);
|
|
681
|
+
if (trimmedNote) {
|
|
682
|
+
lines.push(`note=${trimmedNote}`);
|
|
683
|
+
}
|
|
684
|
+
}
|
|
685
|
+
}
|
|
686
|
+
if (lines.length === 1) {
|
|
687
|
+
lines.push("- None");
|
|
688
|
+
}
|
|
689
|
+
return lines.join("\n");
|
|
690
|
+
}
|
|
691
|
+
function appendScreenshotContextSection(prompt, screenshotContext) {
|
|
692
|
+
if (!screenshotContext || !screenshotContext.imageDataUrl && !screenshotContext.imageAssetId) {
|
|
693
|
+
return prompt;
|
|
694
|
+
}
|
|
695
|
+
const lines = [
|
|
696
|
+
"Visual screenshot context attached:",
|
|
697
|
+
`- capturedAt=${screenshotContext.capturedAt}`,
|
|
698
|
+
`- mimeType=${screenshotContext.mimeType}`,
|
|
699
|
+
...screenshotContext.imageAssetId ? [`- imageAssetId=${screenshotContext.imageAssetId}`] : []
|
|
700
|
+
];
|
|
701
|
+
return `${prompt}
|
|
702
|
+
|
|
703
|
+
${lines.join("\n")}`;
|
|
704
|
+
}
|
|
705
|
+
function appendRuntimeContextSection(prompt, runtimeContext) {
|
|
706
|
+
if (!runtimeContext?.records.length) {
|
|
707
|
+
return prompt;
|
|
708
|
+
}
|
|
709
|
+
return `${prompt}
|
|
710
|
+
|
|
711
|
+
${buildRuntimeContextSection(runtimeContext.records)}`;
|
|
712
|
+
}
|
|
713
|
+
function buildRuntimeContextSection(records) {
|
|
714
|
+
return ["Relevant runtime context:", ...records.map(formatRuntimeRecord)].join("\n");
|
|
715
|
+
}
|
|
716
|
+
function formatRuntimeRecord(record) {
|
|
717
|
+
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}`;
|
|
718
|
+
const reasonSummary = record.relevanceReasons.length ? record.relevanceReasons.join("; ") : "timing-based";
|
|
719
|
+
const stackSummary = record.stack ? `
|
|
720
|
+
stack=${record.stack.split("\n").slice(0, 5).join(" | ")}` : "";
|
|
721
|
+
return [
|
|
722
|
+
`- [${record.kind}] ${record.message}`,
|
|
723
|
+
` relevance=${record.relevanceLevel} (${reasonSummary})`,
|
|
724
|
+
` ${requestSummary}`,
|
|
725
|
+
stackSummary
|
|
726
|
+
].filter(Boolean).join("\n");
|
|
727
|
+
}
|
|
728
|
+
function getAnnotationDispatchErrorCode(error) {
|
|
729
|
+
if (error instanceof AnnotationDispatchError) return error.errorCode;
|
|
730
|
+
if (error instanceof Error && error.message.includes("outside of project workspace")) {
|
|
731
|
+
return "FORBIDDEN_PATH";
|
|
732
|
+
}
|
|
733
|
+
return "UNKNOWN";
|
|
734
|
+
}
|
|
735
|
+
|
|
736
|
+
// src/server/client-config.ts
|
|
737
|
+
async function buildClientConfig(serverState3) {
|
|
738
|
+
const userConfig = loadUserConfigSync(false, serverState3.cwd, serverState3.configRoot);
|
|
739
|
+
const promptsConfig = await loadPromptsConfig(false, serverState3.cwd, serverState3.configRoot);
|
|
740
|
+
const effectiveIde = userConfig.ide ?? "vscode";
|
|
741
|
+
let info;
|
|
742
|
+
if (!serverState3.ideInfo) {
|
|
743
|
+
info = { ide: effectiveIde };
|
|
744
|
+
} else {
|
|
745
|
+
const { scheme: _scheme, ...rest } = serverState3.ideInfo;
|
|
746
|
+
info = rest;
|
|
747
|
+
}
|
|
748
|
+
return {
|
|
749
|
+
...info,
|
|
750
|
+
prompts: resolveIntents(promptsConfig),
|
|
751
|
+
hotKeys: userConfig["inspector.hotKey"] ?? "alt",
|
|
752
|
+
theme: userConfig["inspector.theme"] ?? "auto",
|
|
753
|
+
includeSnippet: userConfig["prompt.includeSnippet"] ?? false,
|
|
754
|
+
runtimeContext: {
|
|
755
|
+
enabled: true,
|
|
756
|
+
preview: true,
|
|
757
|
+
maxRuntimeErrors: 3,
|
|
758
|
+
maxFailedRequests: 2
|
|
759
|
+
},
|
|
760
|
+
screenshotContext: {
|
|
761
|
+
enabled: false
|
|
762
|
+
},
|
|
763
|
+
annotationResponseMode: userConfig["prompt.annotationResponseMode"] ?? "unified",
|
|
764
|
+
autoSend: userConfig["prompt.autoSend"] ?? false
|
|
765
|
+
};
|
|
766
|
+
}
|
|
767
|
+
|
|
768
|
+
// src/server/open-file.ts
|
|
769
|
+
var import_node_child_process2 = require("child_process");
|
|
770
|
+
var import_launch_ide2 = require("launch-ide");
|
|
771
|
+
var serverLogger2 = createLogger("inspecto:server", { logLevel: getGlobalLogLevel() });
|
|
772
|
+
var VSCODE_FAMILY_SCHEMES = [
|
|
773
|
+
"vscode",
|
|
774
|
+
"vscode-insiders",
|
|
775
|
+
"cursor",
|
|
776
|
+
"windsurf",
|
|
777
|
+
"trae",
|
|
778
|
+
"trae-cn",
|
|
779
|
+
"vscodium",
|
|
780
|
+
"codebuddy",
|
|
781
|
+
"codebuddy-cn",
|
|
782
|
+
"antigravity"
|
|
783
|
+
];
|
|
784
|
+
function handleOpenFileRequest(body, serverState3) {
|
|
785
|
+
const absolutePath = resolveWorkspacePath(body.file, serverState3.cwd);
|
|
786
|
+
assertPathWithinProject(absolutePath, serverState3.projectRoot);
|
|
787
|
+
const userConfig = loadUserConfigSync(false, serverState3.cwd, serverState3.configRoot);
|
|
788
|
+
const configuredIde = userConfig.ide;
|
|
789
|
+
const activeIde = serverState3.ideInfo?.ide;
|
|
790
|
+
const activeIdeScheme = serverState3.ideInfo?.scheme;
|
|
791
|
+
const rawEditorHint = configuredIde || activeIde || activeIdeScheme || "code";
|
|
792
|
+
if (configuredIde && activeIdeScheme && !activeIdeScheme.includes(configuredIde)) {
|
|
793
|
+
serverLogger2.warn(
|
|
794
|
+
`Active IDE is ${activeIdeScheme}, but config forces ${configuredIde}. Using configured IDE.`
|
|
795
|
+
);
|
|
796
|
+
}
|
|
797
|
+
let editorHint = rawEditorHint;
|
|
798
|
+
if (rawEditorHint === "vscode") editorHint = "code";
|
|
799
|
+
else if (rawEditorHint === "vscode-insiders") editorHint = "code-insiders";
|
|
800
|
+
else if (rawEditorHint === "vscodium") editorHint = "codium";
|
|
801
|
+
else if (rawEditorHint === "trae-cn" || rawEditorHint === "trae") editorHint = "trae";
|
|
802
|
+
serverLogger2.debug(
|
|
803
|
+
`IDE_OPEN: activeIde=${activeIde}, activeIdeScheme=${activeIdeScheme}, configuredIde=${configuredIde} -> rawEditorHint=${rawEditorHint}, finalEditorHint=${editorHint}`
|
|
804
|
+
);
|
|
805
|
+
if (VSCODE_FAMILY_SCHEMES.includes(rawEditorHint)) {
|
|
806
|
+
let normalizedPath = absolutePath.replace(/\\/g, "/");
|
|
807
|
+
if (!normalizedPath.startsWith("/")) {
|
|
808
|
+
normalizedPath = "/" + normalizedPath;
|
|
809
|
+
}
|
|
810
|
+
const encodedPath = encodeURI(normalizedPath);
|
|
811
|
+
const uri = `${rawEditorHint}://file${encodedPath}:${body.line}:${body.column}`;
|
|
812
|
+
serverLogger2.debug(`IDE_OPEN: Bypassing launchIDE, using URI scheme directly: ${uri}`);
|
|
813
|
+
try {
|
|
814
|
+
if (process.platform === "darwin") {
|
|
815
|
+
(0, import_node_child_process2.execFileSync)("open", [uri]);
|
|
816
|
+
} else if (process.platform === "win32") {
|
|
817
|
+
(0, import_node_child_process2.execFileSync)("cmd", ["/c", "start", '""', uri]);
|
|
818
|
+
} else {
|
|
819
|
+
(0, import_node_child_process2.execFileSync)("xdg-open", [uri]);
|
|
820
|
+
}
|
|
821
|
+
} catch (e) {
|
|
822
|
+
serverLogger2.error(`Failed to launch URI for IDE_OPEN (${uri}):`, e);
|
|
823
|
+
(0, import_launch_ide2.launchIDE)({
|
|
824
|
+
file: absolutePath,
|
|
825
|
+
line: body.line,
|
|
826
|
+
column: body.column,
|
|
827
|
+
editor: editorHint,
|
|
828
|
+
type: process.platform === "darwin" ? "open" : "exec"
|
|
829
|
+
});
|
|
830
|
+
}
|
|
831
|
+
} else {
|
|
832
|
+
(0, import_launch_ide2.launchIDE)({
|
|
833
|
+
file: absolutePath,
|
|
834
|
+
line: body.line,
|
|
835
|
+
column: body.column,
|
|
836
|
+
editor: editorHint,
|
|
837
|
+
type: process.platform === "darwin" ? "open" : "exec"
|
|
838
|
+
});
|
|
839
|
+
}
|
|
840
|
+
return { success: true };
|
|
841
|
+
}
|
|
842
|
+
|
|
843
|
+
// src/server/project-root.ts
|
|
844
|
+
var import_node_fs2 = __toESM(require("fs"), 1);
|
|
845
|
+
var import_node_path3 = __toESM(require("path"), 1);
|
|
846
|
+
var import_node_child_process3 = require("child_process");
|
|
847
|
+
var serverLogger3 = createLogger("inspecto:server", { logLevel: getGlobalLogLevel() });
|
|
848
|
+
function resolveProjectRoot() {
|
|
849
|
+
const cwd = process.cwd();
|
|
850
|
+
let gitRoot;
|
|
851
|
+
try {
|
|
852
|
+
gitRoot = (0, import_node_child_process3.execSync)("git rev-parse --show-toplevel", { encoding: "utf-8" }).trim();
|
|
853
|
+
} catch (e) {
|
|
854
|
+
serverLogger3.warn("Failed to resolve git root via git rev-parse:", e);
|
|
855
|
+
gitRoot = cwd;
|
|
856
|
+
}
|
|
857
|
+
const visited = /* @__PURE__ */ new Set();
|
|
858
|
+
const search = (start, stop) => {
|
|
859
|
+
let current = start;
|
|
860
|
+
while (!visited.has(current)) {
|
|
861
|
+
visited.add(current);
|
|
862
|
+
if (import_node_fs2.default.existsSync(import_node_path3.default.join(current, ".inspecto"))) return current;
|
|
863
|
+
if (current === stop) break;
|
|
864
|
+
const parent = import_node_path3.default.dirname(current);
|
|
865
|
+
if (parent === current) break;
|
|
866
|
+
current = parent;
|
|
867
|
+
}
|
|
868
|
+
return null;
|
|
869
|
+
};
|
|
870
|
+
const cwdMatch = search(cwd, import_node_path3.default.parse(cwd).root);
|
|
871
|
+
if (cwdMatch) return cwdMatch;
|
|
872
|
+
const repoMatch = search(gitRoot, import_node_path3.default.parse(gitRoot).root);
|
|
873
|
+
if (repoMatch) return repoMatch;
|
|
874
|
+
return gitRoot;
|
|
875
|
+
}
|
|
876
|
+
|
|
877
|
+
// src/server/index.ts
|
|
878
|
+
var serverLogger4 = createLogger("inspecto:server", { logLevel: getGlobalLogLevel() });
|
|
879
|
+
var serverState = {
|
|
880
|
+
port: null,
|
|
881
|
+
running: false,
|
|
882
|
+
projectRoot: "",
|
|
883
|
+
configRoot: "",
|
|
884
|
+
cwd: process.cwd()
|
|
885
|
+
};
|
|
886
|
+
var serverInstance = null;
|
|
544
887
|
async function startServer() {
|
|
545
888
|
if (serverState.running && serverState.port !== null) {
|
|
546
889
|
return serverState.port;
|
|
@@ -552,7 +895,7 @@ async function startServer() {
|
|
|
552
895
|
const port = await import_portfinder.default.getPortPromise();
|
|
553
896
|
watchConfig(
|
|
554
897
|
() => {
|
|
555
|
-
|
|
898
|
+
serverLogger4.info("user config reloaded.");
|
|
556
899
|
},
|
|
557
900
|
serverState.cwd,
|
|
558
901
|
serverState.configRoot
|
|
@@ -568,7 +911,7 @@ async function startServer() {
|
|
|
568
911
|
}
|
|
569
912
|
const url = new URL(req.url ?? "/", `http://localhost:${port}`);
|
|
570
913
|
handleRequest(url, req, res).catch((err) => {
|
|
571
|
-
|
|
914
|
+
serverLogger4.error("server error:", err);
|
|
572
915
|
res.writeHead(500, { "Content-Type": "application/json" });
|
|
573
916
|
res.end(JSON.stringify({ success: false, error: String(err) }));
|
|
574
917
|
});
|
|
@@ -581,41 +924,41 @@ async function startServer() {
|
|
|
581
924
|
serverInstance.once("error", reject);
|
|
582
925
|
});
|
|
583
926
|
serverInstance.on("error", (err) => {
|
|
584
|
-
|
|
927
|
+
serverLogger4.error("persistent server error:", err);
|
|
585
928
|
});
|
|
586
929
|
serverState.port = port;
|
|
587
930
|
serverState.running = true;
|
|
588
|
-
const portFile =
|
|
931
|
+
const portFile = import_node_path4.default.join(import_node_os2.default.tmpdir(), "inspecto.port.json");
|
|
589
932
|
try {
|
|
590
933
|
let portData = {};
|
|
591
|
-
if (
|
|
934
|
+
if (import_node_fs3.default.existsSync(portFile)) {
|
|
592
935
|
try {
|
|
593
|
-
portData = JSON.parse(
|
|
936
|
+
portData = JSON.parse(import_node_fs3.default.readFileSync(portFile, "utf-8"));
|
|
594
937
|
} catch (e) {
|
|
595
938
|
}
|
|
596
939
|
}
|
|
597
|
-
const rootHash =
|
|
940
|
+
const rootHash = import_node_crypto2.default.createHash("md5").update(serverState.projectRoot).digest("hex");
|
|
598
941
|
portData[rootHash] = port;
|
|
599
|
-
|
|
942
|
+
import_node_fs3.default.writeFileSync(portFile, JSON.stringify(portData, null, 2), "utf-8");
|
|
600
943
|
} catch (e) {
|
|
601
|
-
|
|
944
|
+
serverLogger4.warn("Failed to write port file:", e);
|
|
602
945
|
}
|
|
603
946
|
process.once("exit", () => {
|
|
604
947
|
try {
|
|
605
|
-
if (
|
|
606
|
-
const portData = JSON.parse(
|
|
607
|
-
const rootHash =
|
|
948
|
+
if (import_node_fs3.default.existsSync(portFile)) {
|
|
949
|
+
const portData = JSON.parse(import_node_fs3.default.readFileSync(portFile, "utf-8"));
|
|
950
|
+
const rootHash = import_node_crypto2.default.createHash("md5").update(serverState.projectRoot).digest("hex");
|
|
608
951
|
delete portData[rootHash];
|
|
609
952
|
if (Object.keys(portData).length === 0) {
|
|
610
|
-
|
|
953
|
+
import_node_fs3.default.unlinkSync(portFile);
|
|
611
954
|
} else {
|
|
612
|
-
|
|
955
|
+
import_node_fs3.default.writeFileSync(portFile, JSON.stringify(portData, null, 2), "utf-8");
|
|
613
956
|
}
|
|
614
957
|
}
|
|
615
958
|
} catch {
|
|
616
959
|
}
|
|
617
960
|
});
|
|
618
|
-
|
|
961
|
+
serverLogger4.info(`server running at http://127.0.0.1:${port}`);
|
|
619
962
|
return port;
|
|
620
963
|
}
|
|
621
964
|
async function readBody(req) {
|
|
@@ -634,26 +977,7 @@ async function handleRequest(url, req, res) {
|
|
|
634
977
|
return;
|
|
635
978
|
}
|
|
636
979
|
if (pathname === import_types2.INSPECTO_API_PATHS.CLIENT_CONFIG && req.method === "GET") {
|
|
637
|
-
const
|
|
638
|
-
const promptsConfig = await loadPromptsConfig(false, serverState.cwd, serverState.configRoot);
|
|
639
|
-
const effectiveIde = userConfig.ide ?? "vscode";
|
|
640
|
-
let info;
|
|
641
|
-
if (!serverState.ideInfo) {
|
|
642
|
-
info = {
|
|
643
|
-
ide: effectiveIde
|
|
644
|
-
};
|
|
645
|
-
} else {
|
|
646
|
-
const { scheme: _scheme, ...rest } = serverState.ideInfo;
|
|
647
|
-
info = rest;
|
|
648
|
-
}
|
|
649
|
-
const config = {
|
|
650
|
-
...info,
|
|
651
|
-
prompts: resolveIntents(promptsConfig),
|
|
652
|
-
hotKeys: userConfig["inspector.hotKey"] ?? "alt",
|
|
653
|
-
theme: userConfig["inspector.theme"] ?? "auto",
|
|
654
|
-
includeSnippet: userConfig["prompt.includeSnippet"] ?? false,
|
|
655
|
-
autoSend: userConfig["prompt.autoSend"] ?? false
|
|
656
|
-
};
|
|
980
|
+
const config = await buildClientConfig(serverState);
|
|
657
981
|
delete config.providers;
|
|
658
982
|
res.writeHead(200, { "Content-Type": "application/json" });
|
|
659
983
|
res.end(JSON.stringify(config));
|
|
@@ -664,21 +988,23 @@ async function handleRequest(url, req, res) {
|
|
|
664
988
|
const body = JSON.parse(await readBody(req));
|
|
665
989
|
const ideWorkspace = body.workspaceRoot || "";
|
|
666
990
|
const serverProjectRoot = serverState.projectRoot || "";
|
|
667
|
-
const
|
|
991
|
+
const normalizedIdeRoot = ideWorkspace ? import_node_path4.default.resolve(ideWorkspace) : "";
|
|
992
|
+
const normalizedServerRoot = serverProjectRoot ? import_node_path4.default.resolve(serverProjectRoot) : "";
|
|
993
|
+
const isSameProject = !normalizedIdeRoot || !normalizedServerRoot || normalizedIdeRoot === normalizedServerRoot || normalizedServerRoot.startsWith(normalizedIdeRoot + import_node_path4.default.sep) || normalizedIdeRoot.startsWith(normalizedServerRoot + import_node_path4.default.sep);
|
|
668
994
|
if (isSameProject) {
|
|
669
995
|
serverState.ideInfo = body;
|
|
670
|
-
|
|
996
|
+
serverLogger4.debug(
|
|
671
997
|
`Accepted IDE info from matched workspace (ide-${body.ide} / schema-${body.scheme})`
|
|
672
998
|
);
|
|
673
999
|
} else {
|
|
674
|
-
|
|
1000
|
+
serverLogger4.debug(
|
|
675
1001
|
`Ignored IDE info from unrelated workspace (IDE Workspace: ${ideWorkspace}, Server: ${serverProjectRoot}, Scheme: ${body.scheme}, IDE: ${body.ide})`
|
|
676
1002
|
);
|
|
677
1003
|
}
|
|
678
1004
|
res.writeHead(200, { "Content-Type": "application/json" });
|
|
679
1005
|
res.end(JSON.stringify({ success: true }));
|
|
680
1006
|
} catch (e) {
|
|
681
|
-
|
|
1007
|
+
serverLogger4.error(`Error parsing ${import_types2.INSPECTO_API_PATHS.IDE_INFO} POST request:`, e);
|
|
682
1008
|
res.writeHead(400, { "Content-Type": "application/json" });
|
|
683
1009
|
res.end(JSON.stringify({ error: "Invalid JSON body" }));
|
|
684
1010
|
}
|
|
@@ -693,74 +1019,14 @@ async function handleRequest(url, req, res) {
|
|
|
693
1019
|
res.end(JSON.stringify({ error: "Invalid JSON body" }));
|
|
694
1020
|
return;
|
|
695
1021
|
}
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
1022
|
+
try {
|
|
1023
|
+
handleOpenFileRequest(body, serverState);
|
|
1024
|
+
} catch {
|
|
1025
|
+
serverLogger4.warn(`Security: Blocked path traversal attempt in IDE_OPEN: ${body.file}`);
|
|
700
1026
|
res.writeHead(403, { "Content-Type": "application/json" });
|
|
701
1027
|
res.end(JSON.stringify({ error: "Access denied: File is outside of project workspace" }));
|
|
702
1028
|
return;
|
|
703
1029
|
}
|
|
704
|
-
const userConfig = loadUserConfigSync(false, serverState.cwd, serverState.configRoot);
|
|
705
|
-
const configuredIde = userConfig.ide;
|
|
706
|
-
const activeIde = serverState.ideInfo?.ide;
|
|
707
|
-
const activeIdeScheme = serverState.ideInfo?.scheme;
|
|
708
|
-
const rawEditorHint = configuredIde || activeIde || activeIdeScheme || "code";
|
|
709
|
-
if (configuredIde && activeIdeScheme && !activeIdeScheme.includes(configuredIde)) {
|
|
710
|
-
serverLogger.warn(
|
|
711
|
-
`Active IDE is ${activeIdeScheme}, but config forces ${configuredIde}. Using configured IDE.`
|
|
712
|
-
);
|
|
713
|
-
}
|
|
714
|
-
let editorHint = rawEditorHint;
|
|
715
|
-
if (rawEditorHint === "vscode") editorHint = "code";
|
|
716
|
-
else if (rawEditorHint === "vscode-insiders") editorHint = "code-insiders";
|
|
717
|
-
else if (rawEditorHint === "vscodium") editorHint = "codium";
|
|
718
|
-
else if (rawEditorHint === "trae-cn" || rawEditorHint === "trae") editorHint = "trae";
|
|
719
|
-
serverLogger.debug(
|
|
720
|
-
`IDE_OPEN: activeIde=${activeIde}, activeIdeScheme=${activeIdeScheme}, configuredIde=${configuredIde} -> rawEditorHint=${rawEditorHint}, finalEditorHint=${editorHint}`
|
|
721
|
-
);
|
|
722
|
-
const VSCODE_FAMILY_SCHEMES = [
|
|
723
|
-
"vscode",
|
|
724
|
-
"vscode-insiders",
|
|
725
|
-
"cursor",
|
|
726
|
-
"windsurf",
|
|
727
|
-
"trae",
|
|
728
|
-
"trae-cn",
|
|
729
|
-
"vscodium",
|
|
730
|
-
"codebuddy",
|
|
731
|
-
"codebuddy-cn",
|
|
732
|
-
"antigravity"
|
|
733
|
-
];
|
|
734
|
-
if (VSCODE_FAMILY_SCHEMES.includes(rawEditorHint)) {
|
|
735
|
-
const uri = `${rawEditorHint}://file${absolutePath}:${body.line}:${body.column}`;
|
|
736
|
-
serverLogger.debug(`IDE_OPEN: Bypassing launchIDE, using URI scheme directly: ${uri}`);
|
|
737
|
-
try {
|
|
738
|
-
if (process.platform === "darwin") {
|
|
739
|
-
(0, import_node_child_process.execFileSync)("open", [uri]);
|
|
740
|
-
} else if (process.platform === "win32") {
|
|
741
|
-
(0, import_node_child_process.execFileSync)("cmd", ["/c", "start", '""', uri]);
|
|
742
|
-
} else {
|
|
743
|
-
(0, import_node_child_process.execFileSync)("xdg-open", [uri]);
|
|
744
|
-
}
|
|
745
|
-
} catch (e) {
|
|
746
|
-
serverLogger.error(`Failed to launch URI for IDE_OPEN (${uri}):`, e);
|
|
747
|
-
(0, import_launch_ide.launchIDE)({
|
|
748
|
-
file: absolutePath,
|
|
749
|
-
line: body.line,
|
|
750
|
-
column: body.column,
|
|
751
|
-
editor: editorHint,
|
|
752
|
-
type: process.platform === "darwin" ? "open" : "exec"
|
|
753
|
-
});
|
|
754
|
-
}
|
|
755
|
-
} else {
|
|
756
|
-
(0, import_launch_ide.launchIDE)({
|
|
757
|
-
file: absolutePath,
|
|
758
|
-
line: body.line,
|
|
759
|
-
column: body.column,
|
|
760
|
-
editor: editorHint,
|
|
761
|
-
type: process.platform === "darwin" ? "open" : "exec"
|
|
762
|
-
});
|
|
763
|
-
}
|
|
764
1030
|
res.writeHead(200, { "Content-Type": "application/json" });
|
|
765
1031
|
res.end(JSON.stringify({ success: true }));
|
|
766
1032
|
return;
|
|
@@ -771,10 +1037,11 @@ async function handleRequest(url, req, res) {
|
|
|
771
1037
|
const column = parseInt(url.searchParams.get("column") ?? "1", 10);
|
|
772
1038
|
const maxLines = parseInt(url.searchParams.get("maxLines") ?? "100", 10);
|
|
773
1039
|
try {
|
|
774
|
-
const absolutePath =
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
1040
|
+
const absolutePath = resolveWorkspacePath(file, serverState.cwd);
|
|
1041
|
+
try {
|
|
1042
|
+
assertPathWithinProject(absolutePath, serverState.projectRoot);
|
|
1043
|
+
} catch {
|
|
1044
|
+
serverLogger4.warn(`Security: Blocked path traversal attempt in PROJECT_SNIPPET: ${file}`);
|
|
778
1045
|
res.writeHead(403, { "Content-Type": "application/json" });
|
|
779
1046
|
res.end(
|
|
780
1047
|
JSON.stringify({
|
|
@@ -804,7 +1071,23 @@ async function handleRequest(url, req, res) {
|
|
|
804
1071
|
res.writeHead(result.success ? 200 : 500, { "Content-Type": "application/json" });
|
|
805
1072
|
res.end(JSON.stringify(result));
|
|
806
1073
|
} catch (e) {
|
|
807
|
-
|
|
1074
|
+
serverLogger4.error(`Error parsing ${import_types2.INSPECTO_API_PATHS.AI_DISPATCH} request:`, e);
|
|
1075
|
+
res.writeHead(500, { "Content-Type": "application/json" });
|
|
1076
|
+
res.end(JSON.stringify({ success: false, error: String(e), errorCode: "INTERNAL_ERROR" }));
|
|
1077
|
+
}
|
|
1078
|
+
return;
|
|
1079
|
+
}
|
|
1080
|
+
if (pathname === import_types2.INSPECTO_API_PATHS.AI_BATCH_DISPATCH && req.method === "POST") {
|
|
1081
|
+
try {
|
|
1082
|
+
const rawBody = await readBody(req);
|
|
1083
|
+
const body = JSON.parse(rawBody);
|
|
1084
|
+
const result = await dispatchAnnotationsToAi(body, serverState);
|
|
1085
|
+
res.writeHead(getBatchDispatchStatusCode(result.errorCode, result.success), {
|
|
1086
|
+
"Content-Type": "application/json"
|
|
1087
|
+
});
|
|
1088
|
+
res.end(JSON.stringify(result));
|
|
1089
|
+
} catch (e) {
|
|
1090
|
+
serverLogger4.error(`Error parsing ${import_types2.INSPECTO_API_PATHS.AI_BATCH_DISPATCH} request:`, e);
|
|
808
1091
|
res.writeHead(500, { "Content-Type": "application/json" });
|
|
809
1092
|
res.end(JSON.stringify({ success: false, error: String(e), errorCode: "INTERNAL_ERROR" }));
|
|
810
1093
|
}
|
|
@@ -812,7 +1095,7 @@ async function handleRequest(url, req, res) {
|
|
|
812
1095
|
}
|
|
813
1096
|
if (pathname.startsWith(`${import_types2.INSPECTO_API_PATHS.AI_TICKET}/`) && req.method === "GET") {
|
|
814
1097
|
const ticketId = pathname.substring(import_types2.INSPECTO_API_PATHS.AI_TICKET.length + 1);
|
|
815
|
-
const payloadStr =
|
|
1098
|
+
const payloadStr = readTicket(ticketId);
|
|
816
1099
|
if (!payloadStr) {
|
|
817
1100
|
res.writeHead(404, { "Content-Type": "application/json" });
|
|
818
1101
|
res.end(JSON.stringify({ success: false, error: "Ticket not found or expired" }));
|
|
@@ -826,54 +1109,28 @@ async function handleRequest(url, req, res) {
|
|
|
826
1109
|
res.end(JSON.stringify({ error: "not found" }));
|
|
827
1110
|
}
|
|
828
1111
|
async function dispatchToAi(req) {
|
|
829
|
-
const { location, snippet, prompt } = req;
|
|
830
|
-
const userConfig = loadUserConfigSync(false, serverState.cwd, serverState.configRoot);
|
|
831
|
-
const resolvedTarget = resolveTargetTool(userConfig);
|
|
1112
|
+
const { location, snippet, prompt, screenshotContext } = req;
|
|
832
1113
|
const formattedPrompt = prompt ?? `Please help me with this code from \`${location.file}\` (line ${location.line}):
|
|
833
1114
|
|
|
834
1115
|
\`\`\`
|
|
835
1116
|
${snippet}
|
|
836
1117
|
\`\`\`
|
|
837
1118
|
`;
|
|
838
|
-
const
|
|
839
|
-
|
|
840
|
-
const activeIde = serverState.ideInfo?.ide;
|
|
841
|
-
const activeIdeScheme = serverState.ideInfo?.scheme;
|
|
842
|
-
const finalIde = configuredIde || activeIdeScheme || activeIde || "vscode";
|
|
843
|
-
if (configuredIde && activeIdeScheme && !activeIdeScheme.includes(configuredIde)) {
|
|
844
|
-
serverLogger.warn(
|
|
845
|
-
`dispatchToAi: Active IDE is ${activeIdeScheme}, but config forces ${configuredIde}. Using configured IDE.`
|
|
846
|
-
);
|
|
847
|
-
}
|
|
848
|
-
const mode = resolveProviderMode(resolvedTarget, finalIde, userConfig);
|
|
849
|
-
const overrides = extractToolOverrides(finalIde, userConfig)[resolvedTarget] || {};
|
|
850
|
-
overrides.type = mode;
|
|
851
|
-
const fullPayload = {
|
|
852
|
-
ide: finalIde,
|
|
853
|
-
target: resolvedTarget,
|
|
854
|
-
targetType: mode,
|
|
1119
|
+
const runtime = resolvePromptDispatchRuntime(serverState);
|
|
1120
|
+
return dispatchPromptThroughIde(runtime, {
|
|
855
1121
|
prompt: formattedPrompt,
|
|
856
1122
|
filePath: location.file,
|
|
857
1123
|
line: location.line,
|
|
858
1124
|
column: location.column,
|
|
859
1125
|
snippet,
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
serverLogger.debug(`dispatchToAi: Generated URI: ${uri}`);
|
|
869
|
-
launchURI(uri);
|
|
870
|
-
return {
|
|
871
|
-
success: true,
|
|
872
|
-
fallbackPayload: {
|
|
873
|
-
prompt: formattedPrompt,
|
|
874
|
-
file: location.file
|
|
875
|
-
}
|
|
876
|
-
};
|
|
1126
|
+
...screenshotContext ? { screenshotContext } : {}
|
|
1127
|
+
});
|
|
1128
|
+
}
|
|
1129
|
+
function getBatchDispatchStatusCode(errorCode, success) {
|
|
1130
|
+
if (success) return 200;
|
|
1131
|
+
if (errorCode === "INVALID_REQUEST") return 400;
|
|
1132
|
+
if (errorCode === "FORBIDDEN_PATH") return 403;
|
|
1133
|
+
return 500;
|
|
877
1134
|
}
|
|
878
1135
|
|
|
879
1136
|
// src/injectors/utils.ts
|
|
@@ -908,7 +1165,7 @@ window.addEventListener('load', () => {
|
|
|
908
1165
|
}
|
|
909
1166
|
|
|
910
1167
|
// src/legacy/rspack/index.ts
|
|
911
|
-
var
|
|
1168
|
+
var import_node_path5 = __toESM(require("path"), 1);
|
|
912
1169
|
var _dirname = typeof __dirname !== "undefined" ? __dirname : __dirname;
|
|
913
1170
|
var DEFAULT_OPTIONS = {
|
|
914
1171
|
include: [],
|
|
@@ -978,7 +1235,7 @@ var InspectoRspackLegacyPlugin = class {
|
|
|
978
1235
|
);
|
|
979
1236
|
}
|
|
980
1237
|
});
|
|
981
|
-
const loaderPath =
|
|
1238
|
+
const loaderPath = import_node_path5.default.resolve(_dirname, "./loader.cjs");
|
|
982
1239
|
compiler.options.module.rules.push({
|
|
983
1240
|
test: /\.[jt]sx?$/,
|
|
984
1241
|
use: [
|