@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
|
@@ -45,13 +45,11 @@ var resolveClientModule = () => {
|
|
|
45
45
|
|
|
46
46
|
// src/server/index.ts
|
|
47
47
|
import http from "http";
|
|
48
|
-
import
|
|
49
|
-
import
|
|
48
|
+
import fs4 from "fs";
|
|
49
|
+
import path6 from "path";
|
|
50
50
|
import os2 from "os";
|
|
51
|
-
import
|
|
52
|
-
import { execSync, execFileSync } from "child_process";
|
|
51
|
+
import crypto2 from "crypto";
|
|
53
52
|
import portfinder from "portfinder";
|
|
54
|
-
import { launchIDE } from "launch-ide";
|
|
55
53
|
import { INSPECTO_API_PATHS } from "@inspecto-dev/types";
|
|
56
54
|
|
|
57
55
|
// src/server/snippet.ts
|
|
@@ -375,9 +373,9 @@ function extractToolOverrides(ide, config) {
|
|
|
375
373
|
function resolveIntents(serverPrompts) {
|
|
376
374
|
const baseMap = /* @__PURE__ */ new Map();
|
|
377
375
|
for (const intent of DEFAULT_INTENTS) {
|
|
378
|
-
|
|
376
|
+
baseMap.set(intent.id, { ...intent });
|
|
379
377
|
}
|
|
380
|
-
const defaults = () =>
|
|
378
|
+
const defaults = () => Array.from(baseMap.values());
|
|
381
379
|
if (!serverPrompts) return defaults();
|
|
382
380
|
const isReplace = !Array.isArray(serverPrompts) && typeof serverPrompts === "object" && serverPrompts.$replace === true;
|
|
383
381
|
const promptsArray = Array.isArray(serverPrompts) ? serverPrompts : isReplace ? serverPrompts.items : [];
|
|
@@ -404,16 +402,18 @@ function resolveIntents(serverPrompts) {
|
|
|
404
402
|
);
|
|
405
403
|
continue;
|
|
406
404
|
}
|
|
407
|
-
if (item.
|
|
405
|
+
if (!item.aiIntent) {
|
|
408
406
|
configLogger.warn(
|
|
409
|
-
`
|
|
407
|
+
`Intent "${item.id}" is missing required "aiIntent".`
|
|
410
408
|
);
|
|
411
409
|
continue;
|
|
412
410
|
}
|
|
413
|
-
result.push(
|
|
411
|
+
result.push(
|
|
412
|
+
baseMap.has(item.id) ? { ...baseMap.get(item.id), ...item } : item
|
|
413
|
+
);
|
|
414
414
|
}
|
|
415
415
|
}
|
|
416
|
-
return
|
|
416
|
+
return result;
|
|
417
417
|
}
|
|
418
418
|
const merged = Array.from(baseMap.values());
|
|
419
419
|
for (const item of promptsArray) {
|
|
@@ -430,9 +430,9 @@ function resolveIntents(serverPrompts) {
|
|
|
430
430
|
configLogger.warn('Intent object missing required "id" field, skipping.');
|
|
431
431
|
continue;
|
|
432
432
|
}
|
|
433
|
-
if (item.
|
|
433
|
+
if (!item.aiIntent) {
|
|
434
434
|
configLogger.warn(
|
|
435
|
-
`
|
|
435
|
+
`Intent "${item.id}" is missing required "aiIntent".`
|
|
436
436
|
);
|
|
437
437
|
continue;
|
|
438
438
|
}
|
|
@@ -450,15 +450,7 @@ function resolveIntents(serverPrompts) {
|
|
|
450
450
|
}
|
|
451
451
|
}
|
|
452
452
|
}
|
|
453
|
-
return
|
|
454
|
-
}
|
|
455
|
-
function ensureOpenInEditorLast(intents) {
|
|
456
|
-
const idx = intents.findIndex((i) => i.id === "open-in-editor");
|
|
457
|
-
if (idx === -1 || idx === intents.length - 1) return intents;
|
|
458
|
-
const result = [...intents];
|
|
459
|
-
const item = result.splice(idx, 1)[0];
|
|
460
|
-
result.push(item);
|
|
461
|
-
return result;
|
|
453
|
+
return merged;
|
|
462
454
|
}
|
|
463
455
|
var watchers = [];
|
|
464
456
|
function watchConfig(onReload, cwd = process.cwd(), gitRoot) {
|
|
@@ -493,7 +485,10 @@ function watchConfig(onReload, cwd = process.cwd(), gitRoot) {
|
|
|
493
485
|
}
|
|
494
486
|
}
|
|
495
487
|
|
|
496
|
-
// src/server/
|
|
488
|
+
// src/server/dispatch-transport.ts
|
|
489
|
+
import crypto from "crypto";
|
|
490
|
+
import { execFileSync } from "child_process";
|
|
491
|
+
import { launchIDE } from "launch-ide";
|
|
497
492
|
var serverLogger = createLogger("inspecto:server", { logLevel: getGlobalLogLevel() });
|
|
498
493
|
var payloadTickets = /* @__PURE__ */ new Map();
|
|
499
494
|
function createTicket(payload) {
|
|
@@ -507,21 +502,363 @@ function createTicket(payload) {
|
|
|
507
502
|
);
|
|
508
503
|
return ticketId;
|
|
509
504
|
}
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
505
|
+
function readTicket(ticketId) {
|
|
506
|
+
return payloadTickets.get(ticketId);
|
|
507
|
+
}
|
|
508
|
+
function launchURI(uri) {
|
|
509
|
+
try {
|
|
510
|
+
if (process.platform === "darwin") {
|
|
511
|
+
execFileSync("open", [uri]);
|
|
512
|
+
} else if (process.platform === "win32") {
|
|
513
|
+
execFileSync("cmd", ["/c", "start", '""', uri]);
|
|
514
|
+
} else {
|
|
515
|
+
execFileSync("xdg-open", [uri]);
|
|
516
|
+
}
|
|
517
|
+
} catch (e) {
|
|
518
|
+
serverLogger.error("Failed to launch URI via execFileSync, falling back to launchIDE:", e);
|
|
519
|
+
launchIDE({ file: uri });
|
|
520
|
+
}
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
// src/server/dispatch-runtime.ts
|
|
524
|
+
function resolvePromptDispatchRuntime(state) {
|
|
525
|
+
const userConfig = loadUserConfigSync(false, state.cwd, state.projectRoot);
|
|
526
|
+
const resolvedTarget = resolveTargetTool(userConfig);
|
|
527
|
+
const finalIde = resolveFinalIde(userConfig.ide, state.ideInfo?.ide, state.ideInfo?.scheme);
|
|
528
|
+
const mode = resolveProviderMode(resolvedTarget, finalIde, userConfig);
|
|
529
|
+
const overrides = extractToolOverrides(finalIde, userConfig)[resolvedTarget] || void 0;
|
|
530
|
+
return {
|
|
531
|
+
resolvedTarget,
|
|
532
|
+
finalIde,
|
|
533
|
+
mode,
|
|
534
|
+
...hasOverrides(overrides) ? { overrides } : {},
|
|
535
|
+
...userConfig["prompt.autoSend"] !== void 0 ? { autoSend: Boolean(userConfig["prompt.autoSend"]) } : {}
|
|
536
|
+
};
|
|
537
|
+
}
|
|
538
|
+
function dispatchPromptThroughIde(runtime, payload) {
|
|
539
|
+
const ticketId = createTicket({
|
|
540
|
+
ide: runtime.finalIde,
|
|
541
|
+
target: runtime.resolvedTarget,
|
|
542
|
+
targetType: runtime.mode,
|
|
543
|
+
prompt: payload.prompt,
|
|
544
|
+
filePath: payload.filePath,
|
|
545
|
+
line: payload.line,
|
|
546
|
+
column: payload.column,
|
|
547
|
+
snippet: payload.snippet,
|
|
548
|
+
...payload.screenshotContext ? { screenshotContext: payload.screenshotContext } : {},
|
|
549
|
+
overrides: runtime.overrides,
|
|
550
|
+
autoSend: runtime.autoSend
|
|
551
|
+
});
|
|
552
|
+
const params = new URLSearchParams();
|
|
553
|
+
params.set("ticket", ticketId);
|
|
554
|
+
params.set("target", runtime.resolvedTarget);
|
|
555
|
+
launchURI(`${runtime.finalIde}://inspecto.inspecto/send?${params.toString()}`);
|
|
556
|
+
return {
|
|
557
|
+
success: true,
|
|
558
|
+
fallbackPayload: {
|
|
559
|
+
prompt: payload.prompt,
|
|
560
|
+
...payload.filePath ? { file: payload.filePath } : {}
|
|
561
|
+
}
|
|
562
|
+
};
|
|
563
|
+
}
|
|
564
|
+
function resolveFinalIde(configuredIde, activeIde, activeIdeScheme) {
|
|
565
|
+
if (configuredIde && activeIdeScheme && !activeIdeScheme.includes(configuredIde)) {
|
|
566
|
+
return configuredIde;
|
|
567
|
+
}
|
|
568
|
+
return configuredIde || activeIdeScheme || activeIde || "vscode";
|
|
569
|
+
}
|
|
570
|
+
function hasOverrides(overrides) {
|
|
571
|
+
return Boolean(overrides && Object.keys(overrides).length > 0);
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
// src/server/path-guards.ts
|
|
575
|
+
import path4 from "path";
|
|
576
|
+
function isWindowsAbsolutePath(file) {
|
|
577
|
+
return /^[a-zA-Z]:[\\/]/.test(file) || /^\\\\[^\\]+\\[^\\]+/.test(file);
|
|
578
|
+
}
|
|
579
|
+
function resolveWorkspacePath(file, cwd) {
|
|
580
|
+
if (isWindowsAbsolutePath(file)) {
|
|
581
|
+
return path4.win32.normalize(file);
|
|
582
|
+
}
|
|
583
|
+
return path4.isAbsolute(file) ? path4.resolve(file) : path4.resolve(cwd, file);
|
|
584
|
+
}
|
|
585
|
+
function assertPathWithinProject(file, projectRoot) {
|
|
586
|
+
const relativeToRoot = isWindowsAbsolutePath(file) || isWindowsAbsolutePath(projectRoot) ? path4.win32.relative(path4.win32.normalize(projectRoot), path4.win32.normalize(file)) : path4.relative(projectRoot, file);
|
|
587
|
+
if (relativeToRoot.startsWith("..") || path4.isAbsolute(relativeToRoot)) {
|
|
588
|
+
throw new Error("Access denied: File is outside of project workspace");
|
|
589
|
+
}
|
|
590
|
+
}
|
|
591
|
+
|
|
592
|
+
// src/server/annotation-dispatch.ts
|
|
593
|
+
var AnnotationDispatchError = class extends Error {
|
|
594
|
+
constructor(message, errorCode) {
|
|
595
|
+
super(message);
|
|
596
|
+
this.name = "AnnotationDispatchError";
|
|
597
|
+
this.errorCode = errorCode;
|
|
598
|
+
}
|
|
516
599
|
};
|
|
517
|
-
|
|
600
|
+
async function dispatchAnnotationsToAi(req, state) {
|
|
601
|
+
try {
|
|
602
|
+
validateAnnotationDispatchRequest(req, state);
|
|
603
|
+
const batch = normalizeAnnotationBatch(req);
|
|
604
|
+
const prompt = buildAnnotationBatchPrompt(batch);
|
|
605
|
+
const representativeTarget = batch.annotations[0]?.targets[0];
|
|
606
|
+
const runtime = resolvePromptDispatchRuntime(state);
|
|
607
|
+
return dispatchPromptThroughIde(runtime, {
|
|
608
|
+
prompt,
|
|
609
|
+
...representativeTarget?.file ? { filePath: representativeTarget.file } : {},
|
|
610
|
+
...representativeTarget?.line ? { line: representativeTarget.line } : {},
|
|
611
|
+
...representativeTarget?.column ? { column: representativeTarget.column } : {},
|
|
612
|
+
...batch.screenshotContext ? { screenshotContext: batch.screenshotContext } : {}
|
|
613
|
+
});
|
|
614
|
+
} catch (error) {
|
|
615
|
+
return {
|
|
616
|
+
success: false,
|
|
617
|
+
error: error instanceof Error ? error.message : String(error),
|
|
618
|
+
errorCode: getAnnotationDispatchErrorCode(error)
|
|
619
|
+
};
|
|
620
|
+
}
|
|
621
|
+
}
|
|
622
|
+
function validateAnnotationDispatchRequest(req, state) {
|
|
623
|
+
if (!req.annotations.length) {
|
|
624
|
+
throw new AnnotationDispatchError("At least one annotation is required.", "INVALID_REQUEST");
|
|
625
|
+
}
|
|
626
|
+
for (const annotation of req.annotations) {
|
|
627
|
+
if (!annotation.targets.length) {
|
|
628
|
+
throw new AnnotationDispatchError(
|
|
629
|
+
"Each annotation must include at least one target.",
|
|
630
|
+
"INVALID_REQUEST"
|
|
631
|
+
);
|
|
632
|
+
}
|
|
633
|
+
for (const target of annotation.targets) {
|
|
634
|
+
const absolutePath = resolveWorkspacePath(target.location.file, state.cwd);
|
|
635
|
+
assertPathWithinProject(absolutePath, state.projectRoot);
|
|
636
|
+
}
|
|
637
|
+
}
|
|
638
|
+
}
|
|
639
|
+
function normalizeAnnotationBatch(req) {
|
|
640
|
+
return {
|
|
641
|
+
instruction: req.instruction?.trim() ?? "",
|
|
642
|
+
responseMode: req.responseMode ?? "unified",
|
|
643
|
+
...req.runtimeContext ? { runtimeContext: req.runtimeContext } : {},
|
|
644
|
+
...req.screenshotContext ? { screenshotContext: req.screenshotContext } : {},
|
|
645
|
+
...req.cssContextPrompt?.trim() ? { cssContextPrompt: req.cssContextPrompt.trim() } : {},
|
|
646
|
+
annotations: req.annotations.map((annotation, index) => ({
|
|
647
|
+
index: index + 1,
|
|
648
|
+
note: annotation.note.trim(),
|
|
649
|
+
intent: annotation.intent,
|
|
650
|
+
targets: annotation.targets.map((target) => ({
|
|
651
|
+
file: target.location.file,
|
|
652
|
+
line: target.location.line,
|
|
653
|
+
column: target.location.column,
|
|
654
|
+
...target.label ? { label: target.label } : {},
|
|
655
|
+
...target.selector ? { selector: target.selector } : {},
|
|
656
|
+
...target.snippet ? { snippet: target.snippet } : {}
|
|
657
|
+
}))
|
|
658
|
+
}))
|
|
659
|
+
};
|
|
660
|
+
}
|
|
661
|
+
function buildAnnotationBatchPrompt(batch) {
|
|
662
|
+
const body = buildSelectedElementsPrompt(batch.annotations);
|
|
663
|
+
const prompt = batch.instruction ? `${batch.instruction}
|
|
664
|
+
|
|
665
|
+
${body}` : body;
|
|
666
|
+
return appendScreenshotContextSection(
|
|
667
|
+
appendCssContextSection(
|
|
668
|
+
appendRuntimeContextSection(prompt, batch.runtimeContext),
|
|
669
|
+
batch.cssContextPrompt
|
|
670
|
+
),
|
|
671
|
+
batch.screenshotContext
|
|
672
|
+
);
|
|
673
|
+
}
|
|
674
|
+
function appendCssContextSection(prompt, cssContextPrompt) {
|
|
675
|
+
if (!cssContextPrompt) return prompt;
|
|
676
|
+
return `${prompt}
|
|
677
|
+
|
|
678
|
+
${cssContextPrompt}`;
|
|
679
|
+
}
|
|
680
|
+
function buildSelectedElementsPrompt(annotations) {
|
|
681
|
+
const lines = ["Selected elements:"];
|
|
682
|
+
for (const annotation of annotations) {
|
|
683
|
+
const trimmedNote = annotation.note.trim();
|
|
684
|
+
for (const target of annotation.targets) {
|
|
685
|
+
const targetLabel = (target.label || "Unknown target").trim() || "Unknown target";
|
|
686
|
+
lines.push(`- ${targetLabel}`);
|
|
687
|
+
lines.push(`file=${target.file}:${target.line}:${target.column}`);
|
|
688
|
+
if (trimmedNote) {
|
|
689
|
+
lines.push(`note=${trimmedNote}`);
|
|
690
|
+
}
|
|
691
|
+
}
|
|
692
|
+
}
|
|
693
|
+
if (lines.length === 1) {
|
|
694
|
+
lines.push("- None");
|
|
695
|
+
}
|
|
696
|
+
return lines.join("\n");
|
|
697
|
+
}
|
|
698
|
+
function appendScreenshotContextSection(prompt, screenshotContext) {
|
|
699
|
+
if (!screenshotContext || !screenshotContext.imageDataUrl && !screenshotContext.imageAssetId) {
|
|
700
|
+
return prompt;
|
|
701
|
+
}
|
|
702
|
+
const lines = [
|
|
703
|
+
"Visual screenshot context attached:",
|
|
704
|
+
`- capturedAt=${screenshotContext.capturedAt}`,
|
|
705
|
+
`- mimeType=${screenshotContext.mimeType}`,
|
|
706
|
+
...screenshotContext.imageAssetId ? [`- imageAssetId=${screenshotContext.imageAssetId}`] : []
|
|
707
|
+
];
|
|
708
|
+
return `${prompt}
|
|
709
|
+
|
|
710
|
+
${lines.join("\n")}`;
|
|
711
|
+
}
|
|
712
|
+
function appendRuntimeContextSection(prompt, runtimeContext) {
|
|
713
|
+
if (!runtimeContext?.records.length) {
|
|
714
|
+
return prompt;
|
|
715
|
+
}
|
|
716
|
+
return `${prompt}
|
|
717
|
+
|
|
718
|
+
${buildRuntimeContextSection(runtimeContext.records)}`;
|
|
719
|
+
}
|
|
720
|
+
function buildRuntimeContextSection(records) {
|
|
721
|
+
return ["Relevant runtime context:", ...records.map(formatRuntimeRecord)].join("\n");
|
|
722
|
+
}
|
|
723
|
+
function formatRuntimeRecord(record) {
|
|
724
|
+
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}`;
|
|
725
|
+
const reasonSummary = record.relevanceReasons.length ? record.relevanceReasons.join("; ") : "timing-based";
|
|
726
|
+
const stackSummary = record.stack ? `
|
|
727
|
+
stack=${record.stack.split("\n").slice(0, 5).join(" | ")}` : "";
|
|
728
|
+
return [
|
|
729
|
+
`- [${record.kind}] ${record.message}`,
|
|
730
|
+
` relevance=${record.relevanceLevel} (${reasonSummary})`,
|
|
731
|
+
` ${requestSummary}`,
|
|
732
|
+
stackSummary
|
|
733
|
+
].filter(Boolean).join("\n");
|
|
734
|
+
}
|
|
735
|
+
function getAnnotationDispatchErrorCode(error) {
|
|
736
|
+
if (error instanceof AnnotationDispatchError) return error.errorCode;
|
|
737
|
+
if (error instanceof Error && error.message.includes("outside of project workspace")) {
|
|
738
|
+
return "FORBIDDEN_PATH";
|
|
739
|
+
}
|
|
740
|
+
return "UNKNOWN";
|
|
741
|
+
}
|
|
742
|
+
|
|
743
|
+
// src/server/client-config.ts
|
|
744
|
+
async function buildClientConfig(serverState2) {
|
|
745
|
+
const userConfig = loadUserConfigSync(false, serverState2.cwd, serverState2.configRoot);
|
|
746
|
+
const promptsConfig = await loadPromptsConfig(false, serverState2.cwd, serverState2.configRoot);
|
|
747
|
+
const effectiveIde = userConfig.ide ?? "vscode";
|
|
748
|
+
let info;
|
|
749
|
+
if (!serverState2.ideInfo) {
|
|
750
|
+
info = { ide: effectiveIde };
|
|
751
|
+
} else {
|
|
752
|
+
const { scheme: _scheme, ...rest } = serverState2.ideInfo;
|
|
753
|
+
info = rest;
|
|
754
|
+
}
|
|
755
|
+
return {
|
|
756
|
+
...info,
|
|
757
|
+
prompts: resolveIntents(promptsConfig),
|
|
758
|
+
hotKeys: userConfig["inspector.hotKey"] ?? "alt",
|
|
759
|
+
theme: userConfig["inspector.theme"] ?? "auto",
|
|
760
|
+
includeSnippet: userConfig["prompt.includeSnippet"] ?? false,
|
|
761
|
+
runtimeContext: {
|
|
762
|
+
enabled: true,
|
|
763
|
+
preview: true,
|
|
764
|
+
maxRuntimeErrors: 3,
|
|
765
|
+
maxFailedRequests: 2
|
|
766
|
+
},
|
|
767
|
+
screenshotContext: {
|
|
768
|
+
enabled: false
|
|
769
|
+
},
|
|
770
|
+
annotationResponseMode: userConfig["prompt.annotationResponseMode"] ?? "unified",
|
|
771
|
+
autoSend: userConfig["prompt.autoSend"] ?? false
|
|
772
|
+
};
|
|
773
|
+
}
|
|
774
|
+
|
|
775
|
+
// src/server/open-file.ts
|
|
776
|
+
import { execFileSync as execFileSync2 } from "child_process";
|
|
777
|
+
import { launchIDE as launchIDE2 } from "launch-ide";
|
|
778
|
+
var serverLogger2 = createLogger("inspecto:server", { logLevel: getGlobalLogLevel() });
|
|
779
|
+
var VSCODE_FAMILY_SCHEMES = [
|
|
780
|
+
"vscode",
|
|
781
|
+
"vscode-insiders",
|
|
782
|
+
"cursor",
|
|
783
|
+
"windsurf",
|
|
784
|
+
"trae",
|
|
785
|
+
"trae-cn",
|
|
786
|
+
"vscodium",
|
|
787
|
+
"codebuddy",
|
|
788
|
+
"codebuddy-cn",
|
|
789
|
+
"antigravity"
|
|
790
|
+
];
|
|
791
|
+
function handleOpenFileRequest(body, serverState2) {
|
|
792
|
+
const absolutePath = resolveWorkspacePath(body.file, serverState2.cwd);
|
|
793
|
+
assertPathWithinProject(absolutePath, serverState2.projectRoot);
|
|
794
|
+
const userConfig = loadUserConfigSync(false, serverState2.cwd, serverState2.configRoot);
|
|
795
|
+
const configuredIde = userConfig.ide;
|
|
796
|
+
const activeIde = serverState2.ideInfo?.ide;
|
|
797
|
+
const activeIdeScheme = serverState2.ideInfo?.scheme;
|
|
798
|
+
const rawEditorHint = configuredIde || activeIde || activeIdeScheme || "code";
|
|
799
|
+
if (configuredIde && activeIdeScheme && !activeIdeScheme.includes(configuredIde)) {
|
|
800
|
+
serverLogger2.warn(
|
|
801
|
+
`Active IDE is ${activeIdeScheme}, but config forces ${configuredIde}. Using configured IDE.`
|
|
802
|
+
);
|
|
803
|
+
}
|
|
804
|
+
let editorHint = rawEditorHint;
|
|
805
|
+
if (rawEditorHint === "vscode") editorHint = "code";
|
|
806
|
+
else if (rawEditorHint === "vscode-insiders") editorHint = "code-insiders";
|
|
807
|
+
else if (rawEditorHint === "vscodium") editorHint = "codium";
|
|
808
|
+
else if (rawEditorHint === "trae-cn" || rawEditorHint === "trae") editorHint = "trae";
|
|
809
|
+
serverLogger2.debug(
|
|
810
|
+
`IDE_OPEN: activeIde=${activeIde}, activeIdeScheme=${activeIdeScheme}, configuredIde=${configuredIde} -> rawEditorHint=${rawEditorHint}, finalEditorHint=${editorHint}`
|
|
811
|
+
);
|
|
812
|
+
if (VSCODE_FAMILY_SCHEMES.includes(rawEditorHint)) {
|
|
813
|
+
let normalizedPath = absolutePath.replace(/\\/g, "/");
|
|
814
|
+
if (!normalizedPath.startsWith("/")) {
|
|
815
|
+
normalizedPath = "/" + normalizedPath;
|
|
816
|
+
}
|
|
817
|
+
const encodedPath = encodeURI(normalizedPath);
|
|
818
|
+
const uri = `${rawEditorHint}://file${encodedPath}:${body.line}:${body.column}`;
|
|
819
|
+
serverLogger2.debug(`IDE_OPEN: Bypassing launchIDE, using URI scheme directly: ${uri}`);
|
|
820
|
+
try {
|
|
821
|
+
if (process.platform === "darwin") {
|
|
822
|
+
execFileSync2("open", [uri]);
|
|
823
|
+
} else if (process.platform === "win32") {
|
|
824
|
+
execFileSync2("cmd", ["/c", "start", '""', uri]);
|
|
825
|
+
} else {
|
|
826
|
+
execFileSync2("xdg-open", [uri]);
|
|
827
|
+
}
|
|
828
|
+
} catch (e) {
|
|
829
|
+
serverLogger2.error(`Failed to launch URI for IDE_OPEN (${uri}):`, e);
|
|
830
|
+
launchIDE2({
|
|
831
|
+
file: absolutePath,
|
|
832
|
+
line: body.line,
|
|
833
|
+
column: body.column,
|
|
834
|
+
editor: editorHint,
|
|
835
|
+
type: process.platform === "darwin" ? "open" : "exec"
|
|
836
|
+
});
|
|
837
|
+
}
|
|
838
|
+
} else {
|
|
839
|
+
launchIDE2({
|
|
840
|
+
file: absolutePath,
|
|
841
|
+
line: body.line,
|
|
842
|
+
column: body.column,
|
|
843
|
+
editor: editorHint,
|
|
844
|
+
type: process.platform === "darwin" ? "open" : "exec"
|
|
845
|
+
});
|
|
846
|
+
}
|
|
847
|
+
return { success: true };
|
|
848
|
+
}
|
|
849
|
+
|
|
850
|
+
// src/server/project-root.ts
|
|
851
|
+
import fs3 from "fs";
|
|
852
|
+
import path5 from "path";
|
|
853
|
+
import { execSync } from "child_process";
|
|
854
|
+
var serverLogger3 = createLogger("inspecto:server", { logLevel: getGlobalLogLevel() });
|
|
518
855
|
function resolveProjectRoot() {
|
|
519
856
|
const cwd = process.cwd();
|
|
520
857
|
let gitRoot;
|
|
521
858
|
try {
|
|
522
859
|
gitRoot = execSync("git rev-parse --show-toplevel", { encoding: "utf-8" }).trim();
|
|
523
860
|
} catch (e) {
|
|
524
|
-
|
|
861
|
+
serverLogger3.warn("Failed to resolve git root via git rev-parse:", e);
|
|
525
862
|
gitRoot = cwd;
|
|
526
863
|
}
|
|
527
864
|
const visited = /* @__PURE__ */ new Set();
|
|
@@ -529,34 +866,31 @@ function resolveProjectRoot() {
|
|
|
529
866
|
let current = start;
|
|
530
867
|
while (!visited.has(current)) {
|
|
531
868
|
visited.add(current);
|
|
532
|
-
if (fs3.existsSync(
|
|
869
|
+
if (fs3.existsSync(path5.join(current, ".inspecto"))) return current;
|
|
533
870
|
if (current === stop) break;
|
|
534
|
-
const parent =
|
|
871
|
+
const parent = path5.dirname(current);
|
|
535
872
|
if (parent === current) break;
|
|
536
873
|
current = parent;
|
|
537
874
|
}
|
|
538
875
|
return null;
|
|
539
876
|
};
|
|
540
|
-
const cwdMatch = search(cwd,
|
|
877
|
+
const cwdMatch = search(cwd, path5.parse(cwd).root);
|
|
541
878
|
if (cwdMatch) return cwdMatch;
|
|
542
|
-
const repoMatch = search(gitRoot,
|
|
879
|
+
const repoMatch = search(gitRoot, path5.parse(gitRoot).root);
|
|
543
880
|
if (repoMatch) return repoMatch;
|
|
544
881
|
return gitRoot;
|
|
545
882
|
}
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
launchIDE({ file: uri });
|
|
558
|
-
}
|
|
559
|
-
}
|
|
883
|
+
|
|
884
|
+
// src/server/index.ts
|
|
885
|
+
var serverLogger4 = createLogger("inspecto:server", { logLevel: getGlobalLogLevel() });
|
|
886
|
+
var serverState = {
|
|
887
|
+
port: null,
|
|
888
|
+
running: false,
|
|
889
|
+
projectRoot: "",
|
|
890
|
+
configRoot: "",
|
|
891
|
+
cwd: process.cwd()
|
|
892
|
+
};
|
|
893
|
+
var serverInstance = null;
|
|
560
894
|
async function startServer() {
|
|
561
895
|
if (serverState.running && serverState.port !== null) {
|
|
562
896
|
return serverState.port;
|
|
@@ -568,7 +902,7 @@ async function startServer() {
|
|
|
568
902
|
const port = await portfinder.getPortPromise();
|
|
569
903
|
watchConfig(
|
|
570
904
|
() => {
|
|
571
|
-
|
|
905
|
+
serverLogger4.info("user config reloaded.");
|
|
572
906
|
},
|
|
573
907
|
serverState.cwd,
|
|
574
908
|
serverState.configRoot
|
|
@@ -584,7 +918,7 @@ async function startServer() {
|
|
|
584
918
|
}
|
|
585
919
|
const url = new URL(req.url ?? "/", `http://localhost:${port}`);
|
|
586
920
|
handleRequest(url, req, res).catch((err) => {
|
|
587
|
-
|
|
921
|
+
serverLogger4.error("server error:", err);
|
|
588
922
|
res.writeHead(500, { "Content-Type": "application/json" });
|
|
589
923
|
res.end(JSON.stringify({ success: false, error: String(err) }));
|
|
590
924
|
});
|
|
@@ -597,41 +931,41 @@ async function startServer() {
|
|
|
597
931
|
serverInstance.once("error", reject);
|
|
598
932
|
});
|
|
599
933
|
serverInstance.on("error", (err) => {
|
|
600
|
-
|
|
934
|
+
serverLogger4.error("persistent server error:", err);
|
|
601
935
|
});
|
|
602
936
|
serverState.port = port;
|
|
603
937
|
serverState.running = true;
|
|
604
|
-
const portFile =
|
|
938
|
+
const portFile = path6.join(os2.tmpdir(), "inspecto.port.json");
|
|
605
939
|
try {
|
|
606
940
|
let portData = {};
|
|
607
|
-
if (
|
|
941
|
+
if (fs4.existsSync(portFile)) {
|
|
608
942
|
try {
|
|
609
|
-
portData = JSON.parse(
|
|
943
|
+
portData = JSON.parse(fs4.readFileSync(portFile, "utf-8"));
|
|
610
944
|
} catch (e) {
|
|
611
945
|
}
|
|
612
946
|
}
|
|
613
|
-
const rootHash =
|
|
947
|
+
const rootHash = crypto2.createHash("md5").update(serverState.projectRoot).digest("hex");
|
|
614
948
|
portData[rootHash] = port;
|
|
615
|
-
|
|
949
|
+
fs4.writeFileSync(portFile, JSON.stringify(portData, null, 2), "utf-8");
|
|
616
950
|
} catch (e) {
|
|
617
|
-
|
|
951
|
+
serverLogger4.warn("Failed to write port file:", e);
|
|
618
952
|
}
|
|
619
953
|
process.once("exit", () => {
|
|
620
954
|
try {
|
|
621
|
-
if (
|
|
622
|
-
const portData = JSON.parse(
|
|
623
|
-
const rootHash =
|
|
955
|
+
if (fs4.existsSync(portFile)) {
|
|
956
|
+
const portData = JSON.parse(fs4.readFileSync(portFile, "utf-8"));
|
|
957
|
+
const rootHash = crypto2.createHash("md5").update(serverState.projectRoot).digest("hex");
|
|
624
958
|
delete portData[rootHash];
|
|
625
959
|
if (Object.keys(portData).length === 0) {
|
|
626
|
-
|
|
960
|
+
fs4.unlinkSync(portFile);
|
|
627
961
|
} else {
|
|
628
|
-
|
|
962
|
+
fs4.writeFileSync(portFile, JSON.stringify(portData, null, 2), "utf-8");
|
|
629
963
|
}
|
|
630
964
|
}
|
|
631
965
|
} catch {
|
|
632
966
|
}
|
|
633
967
|
});
|
|
634
|
-
|
|
968
|
+
serverLogger4.info(`server running at http://127.0.0.1:${port}`);
|
|
635
969
|
return port;
|
|
636
970
|
}
|
|
637
971
|
async function readBody(req) {
|
|
@@ -650,26 +984,7 @@ async function handleRequest(url, req, res) {
|
|
|
650
984
|
return;
|
|
651
985
|
}
|
|
652
986
|
if (pathname === INSPECTO_API_PATHS.CLIENT_CONFIG && req.method === "GET") {
|
|
653
|
-
const
|
|
654
|
-
const promptsConfig = await loadPromptsConfig(false, serverState.cwd, serverState.configRoot);
|
|
655
|
-
const effectiveIde = userConfig.ide ?? "vscode";
|
|
656
|
-
let info;
|
|
657
|
-
if (!serverState.ideInfo) {
|
|
658
|
-
info = {
|
|
659
|
-
ide: effectiveIde
|
|
660
|
-
};
|
|
661
|
-
} else {
|
|
662
|
-
const { scheme: _scheme, ...rest } = serverState.ideInfo;
|
|
663
|
-
info = rest;
|
|
664
|
-
}
|
|
665
|
-
const config = {
|
|
666
|
-
...info,
|
|
667
|
-
prompts: resolveIntents(promptsConfig),
|
|
668
|
-
hotKeys: userConfig["inspector.hotKey"] ?? "alt",
|
|
669
|
-
theme: userConfig["inspector.theme"] ?? "auto",
|
|
670
|
-
includeSnippet: userConfig["prompt.includeSnippet"] ?? false,
|
|
671
|
-
autoSend: userConfig["prompt.autoSend"] ?? false
|
|
672
|
-
};
|
|
987
|
+
const config = await buildClientConfig(serverState);
|
|
673
988
|
delete config.providers;
|
|
674
989
|
res.writeHead(200, { "Content-Type": "application/json" });
|
|
675
990
|
res.end(JSON.stringify(config));
|
|
@@ -680,23 +995,23 @@ async function handleRequest(url, req, res) {
|
|
|
680
995
|
const body = JSON.parse(await readBody(req));
|
|
681
996
|
const ideWorkspace = body.workspaceRoot || "";
|
|
682
997
|
const serverProjectRoot = serverState.projectRoot || "";
|
|
683
|
-
const normalizedIdeRoot = ideWorkspace ?
|
|
684
|
-
const normalizedServerRoot = serverProjectRoot ?
|
|
685
|
-
const isSameProject = !normalizedIdeRoot || !normalizedServerRoot || normalizedIdeRoot === normalizedServerRoot || normalizedServerRoot.startsWith(normalizedIdeRoot +
|
|
998
|
+
const normalizedIdeRoot = ideWorkspace ? path6.resolve(ideWorkspace) : "";
|
|
999
|
+
const normalizedServerRoot = serverProjectRoot ? path6.resolve(serverProjectRoot) : "";
|
|
1000
|
+
const isSameProject = !normalizedIdeRoot || !normalizedServerRoot || normalizedIdeRoot === normalizedServerRoot || normalizedServerRoot.startsWith(normalizedIdeRoot + path6.sep) || normalizedIdeRoot.startsWith(normalizedServerRoot + path6.sep);
|
|
686
1001
|
if (isSameProject) {
|
|
687
1002
|
serverState.ideInfo = body;
|
|
688
|
-
|
|
1003
|
+
serverLogger4.debug(
|
|
689
1004
|
`Accepted IDE info from matched workspace (ide-${body.ide} / schema-${body.scheme})`
|
|
690
1005
|
);
|
|
691
1006
|
} else {
|
|
692
|
-
|
|
1007
|
+
serverLogger4.debug(
|
|
693
1008
|
`Ignored IDE info from unrelated workspace (IDE Workspace: ${ideWorkspace}, Server: ${serverProjectRoot}, Scheme: ${body.scheme}, IDE: ${body.ide})`
|
|
694
1009
|
);
|
|
695
1010
|
}
|
|
696
1011
|
res.writeHead(200, { "Content-Type": "application/json" });
|
|
697
1012
|
res.end(JSON.stringify({ success: true }));
|
|
698
1013
|
} catch (e) {
|
|
699
|
-
|
|
1014
|
+
serverLogger4.error(`Error parsing ${INSPECTO_API_PATHS.IDE_INFO} POST request:`, e);
|
|
700
1015
|
res.writeHead(400, { "Content-Type": "application/json" });
|
|
701
1016
|
res.end(JSON.stringify({ error: "Invalid JSON body" }));
|
|
702
1017
|
}
|
|
@@ -711,79 +1026,14 @@ async function handleRequest(url, req, res) {
|
|
|
711
1026
|
res.end(JSON.stringify({ error: "Invalid JSON body" }));
|
|
712
1027
|
return;
|
|
713
1028
|
}
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
1029
|
+
try {
|
|
1030
|
+
handleOpenFileRequest(body, serverState);
|
|
1031
|
+
} catch {
|
|
1032
|
+
serverLogger4.warn(`Security: Blocked path traversal attempt in IDE_OPEN: ${body.file}`);
|
|
718
1033
|
res.writeHead(403, { "Content-Type": "application/json" });
|
|
719
1034
|
res.end(JSON.stringify({ error: "Access denied: File is outside of project workspace" }));
|
|
720
1035
|
return;
|
|
721
1036
|
}
|
|
722
|
-
const userConfig = loadUserConfigSync(false, serverState.cwd, serverState.configRoot);
|
|
723
|
-
const configuredIde = userConfig.ide;
|
|
724
|
-
const activeIde = serverState.ideInfo?.ide;
|
|
725
|
-
const activeIdeScheme = serverState.ideInfo?.scheme;
|
|
726
|
-
const rawEditorHint = configuredIde || activeIde || activeIdeScheme || "code";
|
|
727
|
-
if (configuredIde && activeIdeScheme && !activeIdeScheme.includes(configuredIde)) {
|
|
728
|
-
serverLogger.warn(
|
|
729
|
-
`Active IDE is ${activeIdeScheme}, but config forces ${configuredIde}. Using configured IDE.`
|
|
730
|
-
);
|
|
731
|
-
}
|
|
732
|
-
let editorHint = rawEditorHint;
|
|
733
|
-
if (rawEditorHint === "vscode") editorHint = "code";
|
|
734
|
-
else if (rawEditorHint === "vscode-insiders") editorHint = "code-insiders";
|
|
735
|
-
else if (rawEditorHint === "vscodium") editorHint = "codium";
|
|
736
|
-
else if (rawEditorHint === "trae-cn" || rawEditorHint === "trae") editorHint = "trae";
|
|
737
|
-
serverLogger.debug(
|
|
738
|
-
`IDE_OPEN: activeIde=${activeIde}, activeIdeScheme=${activeIdeScheme}, configuredIde=${configuredIde} -> rawEditorHint=${rawEditorHint}, finalEditorHint=${editorHint}`
|
|
739
|
-
);
|
|
740
|
-
const VSCODE_FAMILY_SCHEMES = [
|
|
741
|
-
"vscode",
|
|
742
|
-
"vscode-insiders",
|
|
743
|
-
"cursor",
|
|
744
|
-
"windsurf",
|
|
745
|
-
"trae",
|
|
746
|
-
"trae-cn",
|
|
747
|
-
"vscodium",
|
|
748
|
-
"codebuddy",
|
|
749
|
-
"codebuddy-cn",
|
|
750
|
-
"antigravity"
|
|
751
|
-
];
|
|
752
|
-
if (VSCODE_FAMILY_SCHEMES.includes(rawEditorHint)) {
|
|
753
|
-
let normalizedPath = absolutePath.replace(/\\/g, "/");
|
|
754
|
-
if (!normalizedPath.startsWith("/")) {
|
|
755
|
-
normalizedPath = "/" + normalizedPath;
|
|
756
|
-
}
|
|
757
|
-
const encodedPath = encodeURI(normalizedPath);
|
|
758
|
-
const uri = `${rawEditorHint}://file${encodedPath}:${body.line}:${body.column}`;
|
|
759
|
-
serverLogger.debug(`IDE_OPEN: Bypassing launchIDE, using URI scheme directly: ${uri}`);
|
|
760
|
-
try {
|
|
761
|
-
if (process.platform === "darwin") {
|
|
762
|
-
execFileSync("open", [uri]);
|
|
763
|
-
} else if (process.platform === "win32") {
|
|
764
|
-
execFileSync("cmd", ["/c", "start", '""', uri]);
|
|
765
|
-
} else {
|
|
766
|
-
execFileSync("xdg-open", [uri]);
|
|
767
|
-
}
|
|
768
|
-
} catch (e) {
|
|
769
|
-
serverLogger.error(`Failed to launch URI for IDE_OPEN (${uri}):`, e);
|
|
770
|
-
launchIDE({
|
|
771
|
-
file: absolutePath,
|
|
772
|
-
line: body.line,
|
|
773
|
-
column: body.column,
|
|
774
|
-
editor: editorHint,
|
|
775
|
-
type: process.platform === "darwin" ? "open" : "exec"
|
|
776
|
-
});
|
|
777
|
-
}
|
|
778
|
-
} else {
|
|
779
|
-
launchIDE({
|
|
780
|
-
file: absolutePath,
|
|
781
|
-
line: body.line,
|
|
782
|
-
column: body.column,
|
|
783
|
-
editor: editorHint,
|
|
784
|
-
type: process.platform === "darwin" ? "open" : "exec"
|
|
785
|
-
});
|
|
786
|
-
}
|
|
787
1037
|
res.writeHead(200, { "Content-Type": "application/json" });
|
|
788
1038
|
res.end(JSON.stringify({ success: true }));
|
|
789
1039
|
return;
|
|
@@ -794,10 +1044,11 @@ async function handleRequest(url, req, res) {
|
|
|
794
1044
|
const column = parseInt(url.searchParams.get("column") ?? "1", 10);
|
|
795
1045
|
const maxLines = parseInt(url.searchParams.get("maxLines") ?? "100", 10);
|
|
796
1046
|
try {
|
|
797
|
-
const absolutePath =
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
1047
|
+
const absolutePath = resolveWorkspacePath(file, serverState.cwd);
|
|
1048
|
+
try {
|
|
1049
|
+
assertPathWithinProject(absolutePath, serverState.projectRoot);
|
|
1050
|
+
} catch {
|
|
1051
|
+
serverLogger4.warn(`Security: Blocked path traversal attempt in PROJECT_SNIPPET: ${file}`);
|
|
801
1052
|
res.writeHead(403, { "Content-Type": "application/json" });
|
|
802
1053
|
res.end(
|
|
803
1054
|
JSON.stringify({
|
|
@@ -827,7 +1078,23 @@ async function handleRequest(url, req, res) {
|
|
|
827
1078
|
res.writeHead(result.success ? 200 : 500, { "Content-Type": "application/json" });
|
|
828
1079
|
res.end(JSON.stringify(result));
|
|
829
1080
|
} catch (e) {
|
|
830
|
-
|
|
1081
|
+
serverLogger4.error(`Error parsing ${INSPECTO_API_PATHS.AI_DISPATCH} request:`, e);
|
|
1082
|
+
res.writeHead(500, { "Content-Type": "application/json" });
|
|
1083
|
+
res.end(JSON.stringify({ success: false, error: String(e), errorCode: "INTERNAL_ERROR" }));
|
|
1084
|
+
}
|
|
1085
|
+
return;
|
|
1086
|
+
}
|
|
1087
|
+
if (pathname === INSPECTO_API_PATHS.AI_BATCH_DISPATCH && req.method === "POST") {
|
|
1088
|
+
try {
|
|
1089
|
+
const rawBody = await readBody(req);
|
|
1090
|
+
const body = JSON.parse(rawBody);
|
|
1091
|
+
const result = await dispatchAnnotationsToAi(body, serverState);
|
|
1092
|
+
res.writeHead(getBatchDispatchStatusCode(result.errorCode, result.success), {
|
|
1093
|
+
"Content-Type": "application/json"
|
|
1094
|
+
});
|
|
1095
|
+
res.end(JSON.stringify(result));
|
|
1096
|
+
} catch (e) {
|
|
1097
|
+
serverLogger4.error(`Error parsing ${INSPECTO_API_PATHS.AI_BATCH_DISPATCH} request:`, e);
|
|
831
1098
|
res.writeHead(500, { "Content-Type": "application/json" });
|
|
832
1099
|
res.end(JSON.stringify({ success: false, error: String(e), errorCode: "INTERNAL_ERROR" }));
|
|
833
1100
|
}
|
|
@@ -835,7 +1102,7 @@ async function handleRequest(url, req, res) {
|
|
|
835
1102
|
}
|
|
836
1103
|
if (pathname.startsWith(`${INSPECTO_API_PATHS.AI_TICKET}/`) && req.method === "GET") {
|
|
837
1104
|
const ticketId = pathname.substring(INSPECTO_API_PATHS.AI_TICKET.length + 1);
|
|
838
|
-
const payloadStr =
|
|
1105
|
+
const payloadStr = readTicket(ticketId);
|
|
839
1106
|
if (!payloadStr) {
|
|
840
1107
|
res.writeHead(404, { "Content-Type": "application/json" });
|
|
841
1108
|
res.end(JSON.stringify({ success: false, error: "Ticket not found or expired" }));
|
|
@@ -849,58 +1116,32 @@ async function handleRequest(url, req, res) {
|
|
|
849
1116
|
res.end(JSON.stringify({ error: "not found" }));
|
|
850
1117
|
}
|
|
851
1118
|
async function dispatchToAi(req) {
|
|
852
|
-
const { location, snippet, prompt } = req;
|
|
853
|
-
const userConfig = loadUserConfigSync(false, serverState.cwd, serverState.configRoot);
|
|
854
|
-
const resolvedTarget = resolveTargetTool(userConfig);
|
|
1119
|
+
const { location, snippet, prompt, screenshotContext } = req;
|
|
855
1120
|
const formattedPrompt = prompt ?? `Please help me with this code from \`${location.file}\` (line ${location.line}):
|
|
856
1121
|
|
|
857
1122
|
\`\`\`
|
|
858
1123
|
${snippet}
|
|
859
1124
|
\`\`\`
|
|
860
1125
|
`;
|
|
861
|
-
const
|
|
862
|
-
|
|
863
|
-
const activeIde = serverState.ideInfo?.ide;
|
|
864
|
-
const activeIdeScheme = serverState.ideInfo?.scheme;
|
|
865
|
-
const finalIde = configuredIde || activeIdeScheme || activeIde || "vscode";
|
|
866
|
-
if (configuredIde && activeIdeScheme && !activeIdeScheme.includes(configuredIde)) {
|
|
867
|
-
serverLogger.warn(
|
|
868
|
-
`dispatchToAi: Active IDE is ${activeIdeScheme}, but config forces ${configuredIde}. Using configured IDE.`
|
|
869
|
-
);
|
|
870
|
-
}
|
|
871
|
-
const mode = resolveProviderMode(resolvedTarget, finalIde, userConfig);
|
|
872
|
-
const overrides = extractToolOverrides(finalIde, userConfig)[resolvedTarget] || {};
|
|
873
|
-
overrides.type = mode;
|
|
874
|
-
const fullPayload = {
|
|
875
|
-
ide: finalIde,
|
|
876
|
-
target: resolvedTarget,
|
|
877
|
-
targetType: mode,
|
|
1126
|
+
const runtime = resolvePromptDispatchRuntime(serverState);
|
|
1127
|
+
return dispatchPromptThroughIde(runtime, {
|
|
878
1128
|
prompt: formattedPrompt,
|
|
879
1129
|
filePath: location.file,
|
|
880
1130
|
line: location.line,
|
|
881
1131
|
column: location.column,
|
|
882
1132
|
snippet,
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
serverLogger.debug(`dispatchToAi: Generated URI: ${uri}`);
|
|
892
|
-
launchURI(uri);
|
|
893
|
-
return {
|
|
894
|
-
success: true,
|
|
895
|
-
fallbackPayload: {
|
|
896
|
-
prompt: formattedPrompt,
|
|
897
|
-
file: location.file
|
|
898
|
-
}
|
|
899
|
-
};
|
|
1133
|
+
...screenshotContext ? { screenshotContext } : {}
|
|
1134
|
+
});
|
|
1135
|
+
}
|
|
1136
|
+
function getBatchDispatchStatusCode(errorCode, success) {
|
|
1137
|
+
if (success) return 200;
|
|
1138
|
+
if (errorCode === "INVALID_REQUEST") return 400;
|
|
1139
|
+
if (errorCode === "FORBIDDEN_PATH") return 403;
|
|
1140
|
+
return 500;
|
|
900
1141
|
}
|
|
901
1142
|
|
|
902
1143
|
// src/legacy/webpack4/index.ts
|
|
903
|
-
import
|
|
1144
|
+
import path7 from "path";
|
|
904
1145
|
var InspectoWebpack4Plugin = class {
|
|
905
1146
|
constructor(options = {}) {
|
|
906
1147
|
this.options = options;
|
|
@@ -908,7 +1149,7 @@ var InspectoWebpack4Plugin = class {
|
|
|
908
1149
|
apply(compiler) {
|
|
909
1150
|
const clientPath = resolveClientModule();
|
|
910
1151
|
compiler.hooks.afterEnvironment.tap("InspectoWebpack4Plugin", () => {
|
|
911
|
-
const inspectoLoader =
|
|
1152
|
+
const inspectoLoader = path7.resolve(__dirname, "loader.cjs");
|
|
912
1153
|
compiler.options.module.rules.push({
|
|
913
1154
|
test: /\.[jt]sx?$/,
|
|
914
1155
|
enforce: "pre",
|