@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
|
@@ -14,13 +14,11 @@ var __dirname = /* @__PURE__ */ getDirname();
|
|
|
14
14
|
|
|
15
15
|
// src/server/index.ts
|
|
16
16
|
import http from "http";
|
|
17
|
-
import
|
|
18
|
-
import
|
|
17
|
+
import fs4 from "fs";
|
|
18
|
+
import path6 from "path";
|
|
19
19
|
import os2 from "os";
|
|
20
|
-
import
|
|
21
|
-
import { execSync, execFileSync } from "child_process";
|
|
20
|
+
import crypto2 from "crypto";
|
|
22
21
|
import portfinder from "portfinder";
|
|
23
|
-
import { launchIDE } from "launch-ide";
|
|
24
22
|
import { INSPECTO_API_PATHS } from "@inspecto-dev/types";
|
|
25
23
|
|
|
26
24
|
// src/server/snippet.ts
|
|
@@ -344,9 +342,9 @@ function extractToolOverrides(ide, config) {
|
|
|
344
342
|
function resolveIntents(serverPrompts) {
|
|
345
343
|
const baseMap = /* @__PURE__ */ new Map();
|
|
346
344
|
for (const intent of DEFAULT_INTENTS) {
|
|
347
|
-
|
|
345
|
+
baseMap.set(intent.id, { ...intent });
|
|
348
346
|
}
|
|
349
|
-
const defaults = () =>
|
|
347
|
+
const defaults = () => Array.from(baseMap.values());
|
|
350
348
|
if (!serverPrompts) return defaults();
|
|
351
349
|
const isReplace = !Array.isArray(serverPrompts) && typeof serverPrompts === "object" && serverPrompts.$replace === true;
|
|
352
350
|
const promptsArray = Array.isArray(serverPrompts) ? serverPrompts : isReplace ? serverPrompts.items : [];
|
|
@@ -373,16 +371,18 @@ function resolveIntents(serverPrompts) {
|
|
|
373
371
|
);
|
|
374
372
|
continue;
|
|
375
373
|
}
|
|
376
|
-
if (item.
|
|
374
|
+
if (!item.aiIntent) {
|
|
377
375
|
configLogger.warn(
|
|
378
|
-
`
|
|
376
|
+
`Intent "${item.id}" is missing required "aiIntent".`
|
|
379
377
|
);
|
|
380
378
|
continue;
|
|
381
379
|
}
|
|
382
|
-
result.push(
|
|
380
|
+
result.push(
|
|
381
|
+
baseMap.has(item.id) ? { ...baseMap.get(item.id), ...item } : item
|
|
382
|
+
);
|
|
383
383
|
}
|
|
384
384
|
}
|
|
385
|
-
return
|
|
385
|
+
return result;
|
|
386
386
|
}
|
|
387
387
|
const merged = Array.from(baseMap.values());
|
|
388
388
|
for (const item of promptsArray) {
|
|
@@ -399,9 +399,9 @@ function resolveIntents(serverPrompts) {
|
|
|
399
399
|
configLogger.warn('Intent object missing required "id" field, skipping.');
|
|
400
400
|
continue;
|
|
401
401
|
}
|
|
402
|
-
if (item.
|
|
402
|
+
if (!item.aiIntent) {
|
|
403
403
|
configLogger.warn(
|
|
404
|
-
`
|
|
404
|
+
`Intent "${item.id}" is missing required "aiIntent".`
|
|
405
405
|
);
|
|
406
406
|
continue;
|
|
407
407
|
}
|
|
@@ -419,15 +419,7 @@ function resolveIntents(serverPrompts) {
|
|
|
419
419
|
}
|
|
420
420
|
}
|
|
421
421
|
}
|
|
422
|
-
return
|
|
423
|
-
}
|
|
424
|
-
function ensureOpenInEditorLast(intents) {
|
|
425
|
-
const idx = intents.findIndex((i) => i.id === "open-in-editor");
|
|
426
|
-
if (idx === -1 || idx === intents.length - 1) return intents;
|
|
427
|
-
const result = [...intents];
|
|
428
|
-
const item = result.splice(idx, 1)[0];
|
|
429
|
-
result.push(item);
|
|
430
|
-
return result;
|
|
422
|
+
return merged;
|
|
431
423
|
}
|
|
432
424
|
var watchers = [];
|
|
433
425
|
function watchConfig(onReload, cwd = process.cwd(), gitRoot) {
|
|
@@ -462,7 +454,10 @@ function watchConfig(onReload, cwd = process.cwd(), gitRoot) {
|
|
|
462
454
|
}
|
|
463
455
|
}
|
|
464
456
|
|
|
465
|
-
// src/server/
|
|
457
|
+
// src/server/dispatch-transport.ts
|
|
458
|
+
import crypto from "crypto";
|
|
459
|
+
import { execFileSync } from "child_process";
|
|
460
|
+
import { launchIDE } from "launch-ide";
|
|
466
461
|
var serverLogger = createLogger("inspecto:server", { logLevel: getGlobalLogLevel() });
|
|
467
462
|
var payloadTickets = /* @__PURE__ */ new Map();
|
|
468
463
|
function createTicket(payload) {
|
|
@@ -476,21 +471,363 @@ function createTicket(payload) {
|
|
|
476
471
|
);
|
|
477
472
|
return ticketId;
|
|
478
473
|
}
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
474
|
+
function readTicket(ticketId) {
|
|
475
|
+
return payloadTickets.get(ticketId);
|
|
476
|
+
}
|
|
477
|
+
function launchURI(uri) {
|
|
478
|
+
try {
|
|
479
|
+
if (process.platform === "darwin") {
|
|
480
|
+
execFileSync("open", [uri]);
|
|
481
|
+
} else if (process.platform === "win32") {
|
|
482
|
+
execFileSync("cmd", ["/c", "start", '""', uri]);
|
|
483
|
+
} else {
|
|
484
|
+
execFileSync("xdg-open", [uri]);
|
|
485
|
+
}
|
|
486
|
+
} catch (e) {
|
|
487
|
+
serverLogger.error("Failed to launch URI via execFileSync, falling back to launchIDE:", e);
|
|
488
|
+
launchIDE({ file: uri });
|
|
489
|
+
}
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
// src/server/dispatch-runtime.ts
|
|
493
|
+
function resolvePromptDispatchRuntime(state) {
|
|
494
|
+
const userConfig = loadUserConfigSync(false, state.cwd, state.projectRoot);
|
|
495
|
+
const resolvedTarget = resolveTargetTool(userConfig);
|
|
496
|
+
const finalIde = resolveFinalIde(userConfig.ide, state.ideInfo?.ide, state.ideInfo?.scheme);
|
|
497
|
+
const mode = resolveProviderMode(resolvedTarget, finalIde, userConfig);
|
|
498
|
+
const overrides = extractToolOverrides(finalIde, userConfig)[resolvedTarget] || void 0;
|
|
499
|
+
return {
|
|
500
|
+
resolvedTarget,
|
|
501
|
+
finalIde,
|
|
502
|
+
mode,
|
|
503
|
+
...hasOverrides(overrides) ? { overrides } : {},
|
|
504
|
+
...userConfig["prompt.autoSend"] !== void 0 ? { autoSend: Boolean(userConfig["prompt.autoSend"]) } : {}
|
|
505
|
+
};
|
|
506
|
+
}
|
|
507
|
+
function dispatchPromptThroughIde(runtime, payload) {
|
|
508
|
+
const ticketId = createTicket({
|
|
509
|
+
ide: runtime.finalIde,
|
|
510
|
+
target: runtime.resolvedTarget,
|
|
511
|
+
targetType: runtime.mode,
|
|
512
|
+
prompt: payload.prompt,
|
|
513
|
+
filePath: payload.filePath,
|
|
514
|
+
line: payload.line,
|
|
515
|
+
column: payload.column,
|
|
516
|
+
snippet: payload.snippet,
|
|
517
|
+
...payload.screenshotContext ? { screenshotContext: payload.screenshotContext } : {},
|
|
518
|
+
overrides: runtime.overrides,
|
|
519
|
+
autoSend: runtime.autoSend
|
|
520
|
+
});
|
|
521
|
+
const params = new URLSearchParams();
|
|
522
|
+
params.set("ticket", ticketId);
|
|
523
|
+
params.set("target", runtime.resolvedTarget);
|
|
524
|
+
launchURI(`${runtime.finalIde}://inspecto.inspecto/send?${params.toString()}`);
|
|
525
|
+
return {
|
|
526
|
+
success: true,
|
|
527
|
+
fallbackPayload: {
|
|
528
|
+
prompt: payload.prompt,
|
|
529
|
+
...payload.filePath ? { file: payload.filePath } : {}
|
|
530
|
+
}
|
|
531
|
+
};
|
|
532
|
+
}
|
|
533
|
+
function resolveFinalIde(configuredIde, activeIde, activeIdeScheme) {
|
|
534
|
+
if (configuredIde && activeIdeScheme && !activeIdeScheme.includes(configuredIde)) {
|
|
535
|
+
return configuredIde;
|
|
536
|
+
}
|
|
537
|
+
return configuredIde || activeIdeScheme || activeIde || "vscode";
|
|
538
|
+
}
|
|
539
|
+
function hasOverrides(overrides) {
|
|
540
|
+
return Boolean(overrides && Object.keys(overrides).length > 0);
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
// src/server/path-guards.ts
|
|
544
|
+
import path4 from "path";
|
|
545
|
+
function isWindowsAbsolutePath(file) {
|
|
546
|
+
return /^[a-zA-Z]:[\\/]/.test(file) || /^\\\\[^\\]+\\[^\\]+/.test(file);
|
|
547
|
+
}
|
|
548
|
+
function resolveWorkspacePath(file, cwd) {
|
|
549
|
+
if (isWindowsAbsolutePath(file)) {
|
|
550
|
+
return path4.win32.normalize(file);
|
|
551
|
+
}
|
|
552
|
+
return path4.isAbsolute(file) ? path4.resolve(file) : path4.resolve(cwd, file);
|
|
553
|
+
}
|
|
554
|
+
function assertPathWithinProject(file, projectRoot) {
|
|
555
|
+
const relativeToRoot = isWindowsAbsolutePath(file) || isWindowsAbsolutePath(projectRoot) ? path4.win32.relative(path4.win32.normalize(projectRoot), path4.win32.normalize(file)) : path4.relative(projectRoot, file);
|
|
556
|
+
if (relativeToRoot.startsWith("..") || path4.isAbsolute(relativeToRoot)) {
|
|
557
|
+
throw new Error("Access denied: File is outside of project workspace");
|
|
558
|
+
}
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
// src/server/annotation-dispatch.ts
|
|
562
|
+
var AnnotationDispatchError = class extends Error {
|
|
563
|
+
constructor(message, errorCode) {
|
|
564
|
+
super(message);
|
|
565
|
+
this.name = "AnnotationDispatchError";
|
|
566
|
+
this.errorCode = errorCode;
|
|
567
|
+
}
|
|
485
568
|
};
|
|
486
|
-
|
|
569
|
+
async function dispatchAnnotationsToAi(req, state) {
|
|
570
|
+
try {
|
|
571
|
+
validateAnnotationDispatchRequest(req, state);
|
|
572
|
+
const batch = normalizeAnnotationBatch(req);
|
|
573
|
+
const prompt = buildAnnotationBatchPrompt(batch);
|
|
574
|
+
const representativeTarget = batch.annotations[0]?.targets[0];
|
|
575
|
+
const runtime = resolvePromptDispatchRuntime(state);
|
|
576
|
+
return dispatchPromptThroughIde(runtime, {
|
|
577
|
+
prompt,
|
|
578
|
+
...representativeTarget?.file ? { filePath: representativeTarget.file } : {},
|
|
579
|
+
...representativeTarget?.line ? { line: representativeTarget.line } : {},
|
|
580
|
+
...representativeTarget?.column ? { column: representativeTarget.column } : {},
|
|
581
|
+
...batch.screenshotContext ? { screenshotContext: batch.screenshotContext } : {}
|
|
582
|
+
});
|
|
583
|
+
} catch (error) {
|
|
584
|
+
return {
|
|
585
|
+
success: false,
|
|
586
|
+
error: error instanceof Error ? error.message : String(error),
|
|
587
|
+
errorCode: getAnnotationDispatchErrorCode(error)
|
|
588
|
+
};
|
|
589
|
+
}
|
|
590
|
+
}
|
|
591
|
+
function validateAnnotationDispatchRequest(req, state) {
|
|
592
|
+
if (!req.annotations.length) {
|
|
593
|
+
throw new AnnotationDispatchError("At least one annotation is required.", "INVALID_REQUEST");
|
|
594
|
+
}
|
|
595
|
+
for (const annotation of req.annotations) {
|
|
596
|
+
if (!annotation.targets.length) {
|
|
597
|
+
throw new AnnotationDispatchError(
|
|
598
|
+
"Each annotation must include at least one target.",
|
|
599
|
+
"INVALID_REQUEST"
|
|
600
|
+
);
|
|
601
|
+
}
|
|
602
|
+
for (const target of annotation.targets) {
|
|
603
|
+
const absolutePath = resolveWorkspacePath(target.location.file, state.cwd);
|
|
604
|
+
assertPathWithinProject(absolutePath, state.projectRoot);
|
|
605
|
+
}
|
|
606
|
+
}
|
|
607
|
+
}
|
|
608
|
+
function normalizeAnnotationBatch(req) {
|
|
609
|
+
return {
|
|
610
|
+
instruction: req.instruction?.trim() ?? "",
|
|
611
|
+
responseMode: req.responseMode ?? "unified",
|
|
612
|
+
...req.runtimeContext ? { runtimeContext: req.runtimeContext } : {},
|
|
613
|
+
...req.screenshotContext ? { screenshotContext: req.screenshotContext } : {},
|
|
614
|
+
...req.cssContextPrompt?.trim() ? { cssContextPrompt: req.cssContextPrompt.trim() } : {},
|
|
615
|
+
annotations: req.annotations.map((annotation, index) => ({
|
|
616
|
+
index: index + 1,
|
|
617
|
+
note: annotation.note.trim(),
|
|
618
|
+
intent: annotation.intent,
|
|
619
|
+
targets: annotation.targets.map((target) => ({
|
|
620
|
+
file: target.location.file,
|
|
621
|
+
line: target.location.line,
|
|
622
|
+
column: target.location.column,
|
|
623
|
+
...target.label ? { label: target.label } : {},
|
|
624
|
+
...target.selector ? { selector: target.selector } : {},
|
|
625
|
+
...target.snippet ? { snippet: target.snippet } : {}
|
|
626
|
+
}))
|
|
627
|
+
}))
|
|
628
|
+
};
|
|
629
|
+
}
|
|
630
|
+
function buildAnnotationBatchPrompt(batch) {
|
|
631
|
+
const body = buildSelectedElementsPrompt(batch.annotations);
|
|
632
|
+
const prompt = batch.instruction ? `${batch.instruction}
|
|
633
|
+
|
|
634
|
+
${body}` : body;
|
|
635
|
+
return appendScreenshotContextSection(
|
|
636
|
+
appendCssContextSection(
|
|
637
|
+
appendRuntimeContextSection(prompt, batch.runtimeContext),
|
|
638
|
+
batch.cssContextPrompt
|
|
639
|
+
),
|
|
640
|
+
batch.screenshotContext
|
|
641
|
+
);
|
|
642
|
+
}
|
|
643
|
+
function appendCssContextSection(prompt, cssContextPrompt) {
|
|
644
|
+
if (!cssContextPrompt) return prompt;
|
|
645
|
+
return `${prompt}
|
|
646
|
+
|
|
647
|
+
${cssContextPrompt}`;
|
|
648
|
+
}
|
|
649
|
+
function buildSelectedElementsPrompt(annotations) {
|
|
650
|
+
const lines = ["Selected elements:"];
|
|
651
|
+
for (const annotation of annotations) {
|
|
652
|
+
const trimmedNote = annotation.note.trim();
|
|
653
|
+
for (const target of annotation.targets) {
|
|
654
|
+
const targetLabel = (target.label || "Unknown target").trim() || "Unknown target";
|
|
655
|
+
lines.push(`- ${targetLabel}`);
|
|
656
|
+
lines.push(`file=${target.file}:${target.line}:${target.column}`);
|
|
657
|
+
if (trimmedNote) {
|
|
658
|
+
lines.push(`note=${trimmedNote}`);
|
|
659
|
+
}
|
|
660
|
+
}
|
|
661
|
+
}
|
|
662
|
+
if (lines.length === 1) {
|
|
663
|
+
lines.push("- None");
|
|
664
|
+
}
|
|
665
|
+
return lines.join("\n");
|
|
666
|
+
}
|
|
667
|
+
function appendScreenshotContextSection(prompt, screenshotContext) {
|
|
668
|
+
if (!screenshotContext || !screenshotContext.imageDataUrl && !screenshotContext.imageAssetId) {
|
|
669
|
+
return prompt;
|
|
670
|
+
}
|
|
671
|
+
const lines = [
|
|
672
|
+
"Visual screenshot context attached:",
|
|
673
|
+
`- capturedAt=${screenshotContext.capturedAt}`,
|
|
674
|
+
`- mimeType=${screenshotContext.mimeType}`,
|
|
675
|
+
...screenshotContext.imageAssetId ? [`- imageAssetId=${screenshotContext.imageAssetId}`] : []
|
|
676
|
+
];
|
|
677
|
+
return `${prompt}
|
|
678
|
+
|
|
679
|
+
${lines.join("\n")}`;
|
|
680
|
+
}
|
|
681
|
+
function appendRuntimeContextSection(prompt, runtimeContext) {
|
|
682
|
+
if (!runtimeContext?.records.length) {
|
|
683
|
+
return prompt;
|
|
684
|
+
}
|
|
685
|
+
return `${prompt}
|
|
686
|
+
|
|
687
|
+
${buildRuntimeContextSection(runtimeContext.records)}`;
|
|
688
|
+
}
|
|
689
|
+
function buildRuntimeContextSection(records) {
|
|
690
|
+
return ["Relevant runtime context:", ...records.map(formatRuntimeRecord)].join("\n");
|
|
691
|
+
}
|
|
692
|
+
function formatRuntimeRecord(record) {
|
|
693
|
+
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}`;
|
|
694
|
+
const reasonSummary = record.relevanceReasons.length ? record.relevanceReasons.join("; ") : "timing-based";
|
|
695
|
+
const stackSummary = record.stack ? `
|
|
696
|
+
stack=${record.stack.split("\n").slice(0, 5).join(" | ")}` : "";
|
|
697
|
+
return [
|
|
698
|
+
`- [${record.kind}] ${record.message}`,
|
|
699
|
+
` relevance=${record.relevanceLevel} (${reasonSummary})`,
|
|
700
|
+
` ${requestSummary}`,
|
|
701
|
+
stackSummary
|
|
702
|
+
].filter(Boolean).join("\n");
|
|
703
|
+
}
|
|
704
|
+
function getAnnotationDispatchErrorCode(error) {
|
|
705
|
+
if (error instanceof AnnotationDispatchError) return error.errorCode;
|
|
706
|
+
if (error instanceof Error && error.message.includes("outside of project workspace")) {
|
|
707
|
+
return "FORBIDDEN_PATH";
|
|
708
|
+
}
|
|
709
|
+
return "UNKNOWN";
|
|
710
|
+
}
|
|
711
|
+
|
|
712
|
+
// src/server/client-config.ts
|
|
713
|
+
async function buildClientConfig(serverState3) {
|
|
714
|
+
const userConfig = loadUserConfigSync(false, serverState3.cwd, serverState3.configRoot);
|
|
715
|
+
const promptsConfig = await loadPromptsConfig(false, serverState3.cwd, serverState3.configRoot);
|
|
716
|
+
const effectiveIde = userConfig.ide ?? "vscode";
|
|
717
|
+
let info;
|
|
718
|
+
if (!serverState3.ideInfo) {
|
|
719
|
+
info = { ide: effectiveIde };
|
|
720
|
+
} else {
|
|
721
|
+
const { scheme: _scheme, ...rest } = serverState3.ideInfo;
|
|
722
|
+
info = rest;
|
|
723
|
+
}
|
|
724
|
+
return {
|
|
725
|
+
...info,
|
|
726
|
+
prompts: resolveIntents(promptsConfig),
|
|
727
|
+
hotKeys: userConfig["inspector.hotKey"] ?? "alt",
|
|
728
|
+
theme: userConfig["inspector.theme"] ?? "auto",
|
|
729
|
+
includeSnippet: userConfig["prompt.includeSnippet"] ?? false,
|
|
730
|
+
runtimeContext: {
|
|
731
|
+
enabled: true,
|
|
732
|
+
preview: true,
|
|
733
|
+
maxRuntimeErrors: 3,
|
|
734
|
+
maxFailedRequests: 2
|
|
735
|
+
},
|
|
736
|
+
screenshotContext: {
|
|
737
|
+
enabled: false
|
|
738
|
+
},
|
|
739
|
+
annotationResponseMode: userConfig["prompt.annotationResponseMode"] ?? "unified",
|
|
740
|
+
autoSend: userConfig["prompt.autoSend"] ?? false
|
|
741
|
+
};
|
|
742
|
+
}
|
|
743
|
+
|
|
744
|
+
// src/server/open-file.ts
|
|
745
|
+
import { execFileSync as execFileSync2 } from "child_process";
|
|
746
|
+
import { launchIDE as launchIDE2 } from "launch-ide";
|
|
747
|
+
var serverLogger2 = createLogger("inspecto:server", { logLevel: getGlobalLogLevel() });
|
|
748
|
+
var VSCODE_FAMILY_SCHEMES = [
|
|
749
|
+
"vscode",
|
|
750
|
+
"vscode-insiders",
|
|
751
|
+
"cursor",
|
|
752
|
+
"windsurf",
|
|
753
|
+
"trae",
|
|
754
|
+
"trae-cn",
|
|
755
|
+
"vscodium",
|
|
756
|
+
"codebuddy",
|
|
757
|
+
"codebuddy-cn",
|
|
758
|
+
"antigravity"
|
|
759
|
+
];
|
|
760
|
+
function handleOpenFileRequest(body, serverState3) {
|
|
761
|
+
const absolutePath = resolveWorkspacePath(body.file, serverState3.cwd);
|
|
762
|
+
assertPathWithinProject(absolutePath, serverState3.projectRoot);
|
|
763
|
+
const userConfig = loadUserConfigSync(false, serverState3.cwd, serverState3.configRoot);
|
|
764
|
+
const configuredIde = userConfig.ide;
|
|
765
|
+
const activeIde = serverState3.ideInfo?.ide;
|
|
766
|
+
const activeIdeScheme = serverState3.ideInfo?.scheme;
|
|
767
|
+
const rawEditorHint = configuredIde || activeIde || activeIdeScheme || "code";
|
|
768
|
+
if (configuredIde && activeIdeScheme && !activeIdeScheme.includes(configuredIde)) {
|
|
769
|
+
serverLogger2.warn(
|
|
770
|
+
`Active IDE is ${activeIdeScheme}, but config forces ${configuredIde}. Using configured IDE.`
|
|
771
|
+
);
|
|
772
|
+
}
|
|
773
|
+
let editorHint = rawEditorHint;
|
|
774
|
+
if (rawEditorHint === "vscode") editorHint = "code";
|
|
775
|
+
else if (rawEditorHint === "vscode-insiders") editorHint = "code-insiders";
|
|
776
|
+
else if (rawEditorHint === "vscodium") editorHint = "codium";
|
|
777
|
+
else if (rawEditorHint === "trae-cn" || rawEditorHint === "trae") editorHint = "trae";
|
|
778
|
+
serverLogger2.debug(
|
|
779
|
+
`IDE_OPEN: activeIde=${activeIde}, activeIdeScheme=${activeIdeScheme}, configuredIde=${configuredIde} -> rawEditorHint=${rawEditorHint}, finalEditorHint=${editorHint}`
|
|
780
|
+
);
|
|
781
|
+
if (VSCODE_FAMILY_SCHEMES.includes(rawEditorHint)) {
|
|
782
|
+
let normalizedPath = absolutePath.replace(/\\/g, "/");
|
|
783
|
+
if (!normalizedPath.startsWith("/")) {
|
|
784
|
+
normalizedPath = "/" + normalizedPath;
|
|
785
|
+
}
|
|
786
|
+
const encodedPath = encodeURI(normalizedPath);
|
|
787
|
+
const uri = `${rawEditorHint}://file${encodedPath}:${body.line}:${body.column}`;
|
|
788
|
+
serverLogger2.debug(`IDE_OPEN: Bypassing launchIDE, using URI scheme directly: ${uri}`);
|
|
789
|
+
try {
|
|
790
|
+
if (process.platform === "darwin") {
|
|
791
|
+
execFileSync2("open", [uri]);
|
|
792
|
+
} else if (process.platform === "win32") {
|
|
793
|
+
execFileSync2("cmd", ["/c", "start", '""', uri]);
|
|
794
|
+
} else {
|
|
795
|
+
execFileSync2("xdg-open", [uri]);
|
|
796
|
+
}
|
|
797
|
+
} catch (e) {
|
|
798
|
+
serverLogger2.error(`Failed to launch URI for IDE_OPEN (${uri}):`, e);
|
|
799
|
+
launchIDE2({
|
|
800
|
+
file: absolutePath,
|
|
801
|
+
line: body.line,
|
|
802
|
+
column: body.column,
|
|
803
|
+
editor: editorHint,
|
|
804
|
+
type: process.platform === "darwin" ? "open" : "exec"
|
|
805
|
+
});
|
|
806
|
+
}
|
|
807
|
+
} else {
|
|
808
|
+
launchIDE2({
|
|
809
|
+
file: absolutePath,
|
|
810
|
+
line: body.line,
|
|
811
|
+
column: body.column,
|
|
812
|
+
editor: editorHint,
|
|
813
|
+
type: process.platform === "darwin" ? "open" : "exec"
|
|
814
|
+
});
|
|
815
|
+
}
|
|
816
|
+
return { success: true };
|
|
817
|
+
}
|
|
818
|
+
|
|
819
|
+
// src/server/project-root.ts
|
|
820
|
+
import fs3 from "fs";
|
|
821
|
+
import path5 from "path";
|
|
822
|
+
import { execSync } from "child_process";
|
|
823
|
+
var serverLogger3 = createLogger("inspecto:server", { logLevel: getGlobalLogLevel() });
|
|
487
824
|
function resolveProjectRoot() {
|
|
488
825
|
const cwd = process.cwd();
|
|
489
826
|
let gitRoot;
|
|
490
827
|
try {
|
|
491
828
|
gitRoot = execSync("git rev-parse --show-toplevel", { encoding: "utf-8" }).trim();
|
|
492
829
|
} catch (e) {
|
|
493
|
-
|
|
830
|
+
serverLogger3.warn("Failed to resolve git root via git rev-parse:", e);
|
|
494
831
|
gitRoot = cwd;
|
|
495
832
|
}
|
|
496
833
|
const visited = /* @__PURE__ */ new Set();
|
|
@@ -498,34 +835,31 @@ function resolveProjectRoot() {
|
|
|
498
835
|
let current = start;
|
|
499
836
|
while (!visited.has(current)) {
|
|
500
837
|
visited.add(current);
|
|
501
|
-
if (fs3.existsSync(
|
|
838
|
+
if (fs3.existsSync(path5.join(current, ".inspecto"))) return current;
|
|
502
839
|
if (current === stop) break;
|
|
503
|
-
const parent =
|
|
840
|
+
const parent = path5.dirname(current);
|
|
504
841
|
if (parent === current) break;
|
|
505
842
|
current = parent;
|
|
506
843
|
}
|
|
507
844
|
return null;
|
|
508
845
|
};
|
|
509
|
-
const cwdMatch = search(cwd,
|
|
846
|
+
const cwdMatch = search(cwd, path5.parse(cwd).root);
|
|
510
847
|
if (cwdMatch) return cwdMatch;
|
|
511
|
-
const repoMatch = search(gitRoot,
|
|
848
|
+
const repoMatch = search(gitRoot, path5.parse(gitRoot).root);
|
|
512
849
|
if (repoMatch) return repoMatch;
|
|
513
850
|
return gitRoot;
|
|
514
851
|
}
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
launchIDE({ file: uri });
|
|
527
|
-
}
|
|
528
|
-
}
|
|
852
|
+
|
|
853
|
+
// src/server/index.ts
|
|
854
|
+
var serverLogger4 = createLogger("inspecto:server", { logLevel: getGlobalLogLevel() });
|
|
855
|
+
var serverState = {
|
|
856
|
+
port: null,
|
|
857
|
+
running: false,
|
|
858
|
+
projectRoot: "",
|
|
859
|
+
configRoot: "",
|
|
860
|
+
cwd: process.cwd()
|
|
861
|
+
};
|
|
862
|
+
var serverInstance = null;
|
|
529
863
|
async function startServer() {
|
|
530
864
|
if (serverState.running && serverState.port !== null) {
|
|
531
865
|
return serverState.port;
|
|
@@ -537,7 +871,7 @@ async function startServer() {
|
|
|
537
871
|
const port = await portfinder.getPortPromise();
|
|
538
872
|
watchConfig(
|
|
539
873
|
() => {
|
|
540
|
-
|
|
874
|
+
serverLogger4.info("user config reloaded.");
|
|
541
875
|
},
|
|
542
876
|
serverState.cwd,
|
|
543
877
|
serverState.configRoot
|
|
@@ -553,7 +887,7 @@ async function startServer() {
|
|
|
553
887
|
}
|
|
554
888
|
const url = new URL(req.url ?? "/", `http://localhost:${port}`);
|
|
555
889
|
handleRequest(url, req, res).catch((err) => {
|
|
556
|
-
|
|
890
|
+
serverLogger4.error("server error:", err);
|
|
557
891
|
res.writeHead(500, { "Content-Type": "application/json" });
|
|
558
892
|
res.end(JSON.stringify({ success: false, error: String(err) }));
|
|
559
893
|
});
|
|
@@ -566,41 +900,41 @@ async function startServer() {
|
|
|
566
900
|
serverInstance.once("error", reject);
|
|
567
901
|
});
|
|
568
902
|
serverInstance.on("error", (err) => {
|
|
569
|
-
|
|
903
|
+
serverLogger4.error("persistent server error:", err);
|
|
570
904
|
});
|
|
571
905
|
serverState.port = port;
|
|
572
906
|
serverState.running = true;
|
|
573
|
-
const portFile =
|
|
907
|
+
const portFile = path6.join(os2.tmpdir(), "inspecto.port.json");
|
|
574
908
|
try {
|
|
575
909
|
let portData = {};
|
|
576
|
-
if (
|
|
910
|
+
if (fs4.existsSync(portFile)) {
|
|
577
911
|
try {
|
|
578
|
-
portData = JSON.parse(
|
|
912
|
+
portData = JSON.parse(fs4.readFileSync(portFile, "utf-8"));
|
|
579
913
|
} catch (e) {
|
|
580
914
|
}
|
|
581
915
|
}
|
|
582
|
-
const rootHash =
|
|
916
|
+
const rootHash = crypto2.createHash("md5").update(serverState.projectRoot).digest("hex");
|
|
583
917
|
portData[rootHash] = port;
|
|
584
|
-
|
|
918
|
+
fs4.writeFileSync(portFile, JSON.stringify(portData, null, 2), "utf-8");
|
|
585
919
|
} catch (e) {
|
|
586
|
-
|
|
920
|
+
serverLogger4.warn("Failed to write port file:", e);
|
|
587
921
|
}
|
|
588
922
|
process.once("exit", () => {
|
|
589
923
|
try {
|
|
590
|
-
if (
|
|
591
|
-
const portData = JSON.parse(
|
|
592
|
-
const rootHash =
|
|
924
|
+
if (fs4.existsSync(portFile)) {
|
|
925
|
+
const portData = JSON.parse(fs4.readFileSync(portFile, "utf-8"));
|
|
926
|
+
const rootHash = crypto2.createHash("md5").update(serverState.projectRoot).digest("hex");
|
|
593
927
|
delete portData[rootHash];
|
|
594
928
|
if (Object.keys(portData).length === 0) {
|
|
595
|
-
|
|
929
|
+
fs4.unlinkSync(portFile);
|
|
596
930
|
} else {
|
|
597
|
-
|
|
931
|
+
fs4.writeFileSync(portFile, JSON.stringify(portData, null, 2), "utf-8");
|
|
598
932
|
}
|
|
599
933
|
}
|
|
600
934
|
} catch {
|
|
601
935
|
}
|
|
602
936
|
});
|
|
603
|
-
|
|
937
|
+
serverLogger4.info(`server running at http://127.0.0.1:${port}`);
|
|
604
938
|
return port;
|
|
605
939
|
}
|
|
606
940
|
async function readBody(req) {
|
|
@@ -619,26 +953,7 @@ async function handleRequest(url, req, res) {
|
|
|
619
953
|
return;
|
|
620
954
|
}
|
|
621
955
|
if (pathname === INSPECTO_API_PATHS.CLIENT_CONFIG && req.method === "GET") {
|
|
622
|
-
const
|
|
623
|
-
const promptsConfig = await loadPromptsConfig(false, serverState.cwd, serverState.configRoot);
|
|
624
|
-
const effectiveIde = userConfig.ide ?? "vscode";
|
|
625
|
-
let info;
|
|
626
|
-
if (!serverState.ideInfo) {
|
|
627
|
-
info = {
|
|
628
|
-
ide: effectiveIde
|
|
629
|
-
};
|
|
630
|
-
} else {
|
|
631
|
-
const { scheme: _scheme, ...rest } = serverState.ideInfo;
|
|
632
|
-
info = rest;
|
|
633
|
-
}
|
|
634
|
-
const config = {
|
|
635
|
-
...info,
|
|
636
|
-
prompts: resolveIntents(promptsConfig),
|
|
637
|
-
hotKeys: userConfig["inspector.hotKey"] ?? "alt",
|
|
638
|
-
theme: userConfig["inspector.theme"] ?? "auto",
|
|
639
|
-
includeSnippet: userConfig["prompt.includeSnippet"] ?? false,
|
|
640
|
-
autoSend: userConfig["prompt.autoSend"] ?? false
|
|
641
|
-
};
|
|
956
|
+
const config = await buildClientConfig(serverState);
|
|
642
957
|
delete config.providers;
|
|
643
958
|
res.writeHead(200, { "Content-Type": "application/json" });
|
|
644
959
|
res.end(JSON.stringify(config));
|
|
@@ -649,23 +964,23 @@ async function handleRequest(url, req, res) {
|
|
|
649
964
|
const body = JSON.parse(await readBody(req));
|
|
650
965
|
const ideWorkspace = body.workspaceRoot || "";
|
|
651
966
|
const serverProjectRoot = serverState.projectRoot || "";
|
|
652
|
-
const normalizedIdeRoot = ideWorkspace ?
|
|
653
|
-
const normalizedServerRoot = serverProjectRoot ?
|
|
654
|
-
const isSameProject = !normalizedIdeRoot || !normalizedServerRoot || normalizedIdeRoot === normalizedServerRoot || normalizedServerRoot.startsWith(normalizedIdeRoot +
|
|
967
|
+
const normalizedIdeRoot = ideWorkspace ? path6.resolve(ideWorkspace) : "";
|
|
968
|
+
const normalizedServerRoot = serverProjectRoot ? path6.resolve(serverProjectRoot) : "";
|
|
969
|
+
const isSameProject = !normalizedIdeRoot || !normalizedServerRoot || normalizedIdeRoot === normalizedServerRoot || normalizedServerRoot.startsWith(normalizedIdeRoot + path6.sep) || normalizedIdeRoot.startsWith(normalizedServerRoot + path6.sep);
|
|
655
970
|
if (isSameProject) {
|
|
656
971
|
serverState.ideInfo = body;
|
|
657
|
-
|
|
972
|
+
serverLogger4.debug(
|
|
658
973
|
`Accepted IDE info from matched workspace (ide-${body.ide} / schema-${body.scheme})`
|
|
659
974
|
);
|
|
660
975
|
} else {
|
|
661
|
-
|
|
976
|
+
serverLogger4.debug(
|
|
662
977
|
`Ignored IDE info from unrelated workspace (IDE Workspace: ${ideWorkspace}, Server: ${serverProjectRoot}, Scheme: ${body.scheme}, IDE: ${body.ide})`
|
|
663
978
|
);
|
|
664
979
|
}
|
|
665
980
|
res.writeHead(200, { "Content-Type": "application/json" });
|
|
666
981
|
res.end(JSON.stringify({ success: true }));
|
|
667
982
|
} catch (e) {
|
|
668
|
-
|
|
983
|
+
serverLogger4.error(`Error parsing ${INSPECTO_API_PATHS.IDE_INFO} POST request:`, e);
|
|
669
984
|
res.writeHead(400, { "Content-Type": "application/json" });
|
|
670
985
|
res.end(JSON.stringify({ error: "Invalid JSON body" }));
|
|
671
986
|
}
|
|
@@ -680,79 +995,14 @@ async function handleRequest(url, req, res) {
|
|
|
680
995
|
res.end(JSON.stringify({ error: "Invalid JSON body" }));
|
|
681
996
|
return;
|
|
682
997
|
}
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
998
|
+
try {
|
|
999
|
+
handleOpenFileRequest(body, serverState);
|
|
1000
|
+
} catch {
|
|
1001
|
+
serverLogger4.warn(`Security: Blocked path traversal attempt in IDE_OPEN: ${body.file}`);
|
|
687
1002
|
res.writeHead(403, { "Content-Type": "application/json" });
|
|
688
1003
|
res.end(JSON.stringify({ error: "Access denied: File is outside of project workspace" }));
|
|
689
1004
|
return;
|
|
690
1005
|
}
|
|
691
|
-
const userConfig = loadUserConfigSync(false, serverState.cwd, serverState.configRoot);
|
|
692
|
-
const configuredIde = userConfig.ide;
|
|
693
|
-
const activeIde = serverState.ideInfo?.ide;
|
|
694
|
-
const activeIdeScheme = serverState.ideInfo?.scheme;
|
|
695
|
-
const rawEditorHint = configuredIde || activeIde || activeIdeScheme || "code";
|
|
696
|
-
if (configuredIde && activeIdeScheme && !activeIdeScheme.includes(configuredIde)) {
|
|
697
|
-
serverLogger.warn(
|
|
698
|
-
`Active IDE is ${activeIdeScheme}, but config forces ${configuredIde}. Using configured IDE.`
|
|
699
|
-
);
|
|
700
|
-
}
|
|
701
|
-
let editorHint = rawEditorHint;
|
|
702
|
-
if (rawEditorHint === "vscode") editorHint = "code";
|
|
703
|
-
else if (rawEditorHint === "vscode-insiders") editorHint = "code-insiders";
|
|
704
|
-
else if (rawEditorHint === "vscodium") editorHint = "codium";
|
|
705
|
-
else if (rawEditorHint === "trae-cn" || rawEditorHint === "trae") editorHint = "trae";
|
|
706
|
-
serverLogger.debug(
|
|
707
|
-
`IDE_OPEN: activeIde=${activeIde}, activeIdeScheme=${activeIdeScheme}, configuredIde=${configuredIde} -> rawEditorHint=${rawEditorHint}, finalEditorHint=${editorHint}`
|
|
708
|
-
);
|
|
709
|
-
const VSCODE_FAMILY_SCHEMES = [
|
|
710
|
-
"vscode",
|
|
711
|
-
"vscode-insiders",
|
|
712
|
-
"cursor",
|
|
713
|
-
"windsurf",
|
|
714
|
-
"trae",
|
|
715
|
-
"trae-cn",
|
|
716
|
-
"vscodium",
|
|
717
|
-
"codebuddy",
|
|
718
|
-
"codebuddy-cn",
|
|
719
|
-
"antigravity"
|
|
720
|
-
];
|
|
721
|
-
if (VSCODE_FAMILY_SCHEMES.includes(rawEditorHint)) {
|
|
722
|
-
let normalizedPath = absolutePath.replace(/\\/g, "/");
|
|
723
|
-
if (!normalizedPath.startsWith("/")) {
|
|
724
|
-
normalizedPath = "/" + normalizedPath;
|
|
725
|
-
}
|
|
726
|
-
const encodedPath = encodeURI(normalizedPath);
|
|
727
|
-
const uri = `${rawEditorHint}://file${encodedPath}:${body.line}:${body.column}`;
|
|
728
|
-
serverLogger.debug(`IDE_OPEN: Bypassing launchIDE, using URI scheme directly: ${uri}`);
|
|
729
|
-
try {
|
|
730
|
-
if (process.platform === "darwin") {
|
|
731
|
-
execFileSync("open", [uri]);
|
|
732
|
-
} else if (process.platform === "win32") {
|
|
733
|
-
execFileSync("cmd", ["/c", "start", '""', uri]);
|
|
734
|
-
} else {
|
|
735
|
-
execFileSync("xdg-open", [uri]);
|
|
736
|
-
}
|
|
737
|
-
} catch (e) {
|
|
738
|
-
serverLogger.error(`Failed to launch URI for IDE_OPEN (${uri}):`, e);
|
|
739
|
-
launchIDE({
|
|
740
|
-
file: absolutePath,
|
|
741
|
-
line: body.line,
|
|
742
|
-
column: body.column,
|
|
743
|
-
editor: editorHint,
|
|
744
|
-
type: process.platform === "darwin" ? "open" : "exec"
|
|
745
|
-
});
|
|
746
|
-
}
|
|
747
|
-
} else {
|
|
748
|
-
launchIDE({
|
|
749
|
-
file: absolutePath,
|
|
750
|
-
line: body.line,
|
|
751
|
-
column: body.column,
|
|
752
|
-
editor: editorHint,
|
|
753
|
-
type: process.platform === "darwin" ? "open" : "exec"
|
|
754
|
-
});
|
|
755
|
-
}
|
|
756
1006
|
res.writeHead(200, { "Content-Type": "application/json" });
|
|
757
1007
|
res.end(JSON.stringify({ success: true }));
|
|
758
1008
|
return;
|
|
@@ -763,10 +1013,11 @@ async function handleRequest(url, req, res) {
|
|
|
763
1013
|
const column = parseInt(url.searchParams.get("column") ?? "1", 10);
|
|
764
1014
|
const maxLines = parseInt(url.searchParams.get("maxLines") ?? "100", 10);
|
|
765
1015
|
try {
|
|
766
|
-
const absolutePath =
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
1016
|
+
const absolutePath = resolveWorkspacePath(file, serverState.cwd);
|
|
1017
|
+
try {
|
|
1018
|
+
assertPathWithinProject(absolutePath, serverState.projectRoot);
|
|
1019
|
+
} catch {
|
|
1020
|
+
serverLogger4.warn(`Security: Blocked path traversal attempt in PROJECT_SNIPPET: ${file}`);
|
|
770
1021
|
res.writeHead(403, { "Content-Type": "application/json" });
|
|
771
1022
|
res.end(
|
|
772
1023
|
JSON.stringify({
|
|
@@ -796,7 +1047,23 @@ async function handleRequest(url, req, res) {
|
|
|
796
1047
|
res.writeHead(result.success ? 200 : 500, { "Content-Type": "application/json" });
|
|
797
1048
|
res.end(JSON.stringify(result));
|
|
798
1049
|
} catch (e) {
|
|
799
|
-
|
|
1050
|
+
serverLogger4.error(`Error parsing ${INSPECTO_API_PATHS.AI_DISPATCH} request:`, e);
|
|
1051
|
+
res.writeHead(500, { "Content-Type": "application/json" });
|
|
1052
|
+
res.end(JSON.stringify({ success: false, error: String(e), errorCode: "INTERNAL_ERROR" }));
|
|
1053
|
+
}
|
|
1054
|
+
return;
|
|
1055
|
+
}
|
|
1056
|
+
if (pathname === INSPECTO_API_PATHS.AI_BATCH_DISPATCH && req.method === "POST") {
|
|
1057
|
+
try {
|
|
1058
|
+
const rawBody = await readBody(req);
|
|
1059
|
+
const body = JSON.parse(rawBody);
|
|
1060
|
+
const result = await dispatchAnnotationsToAi(body, serverState);
|
|
1061
|
+
res.writeHead(getBatchDispatchStatusCode(result.errorCode, result.success), {
|
|
1062
|
+
"Content-Type": "application/json"
|
|
1063
|
+
});
|
|
1064
|
+
res.end(JSON.stringify(result));
|
|
1065
|
+
} catch (e) {
|
|
1066
|
+
serverLogger4.error(`Error parsing ${INSPECTO_API_PATHS.AI_BATCH_DISPATCH} request:`, e);
|
|
800
1067
|
res.writeHead(500, { "Content-Type": "application/json" });
|
|
801
1068
|
res.end(JSON.stringify({ success: false, error: String(e), errorCode: "INTERNAL_ERROR" }));
|
|
802
1069
|
}
|
|
@@ -804,7 +1071,7 @@ async function handleRequest(url, req, res) {
|
|
|
804
1071
|
}
|
|
805
1072
|
if (pathname.startsWith(`${INSPECTO_API_PATHS.AI_TICKET}/`) && req.method === "GET") {
|
|
806
1073
|
const ticketId = pathname.substring(INSPECTO_API_PATHS.AI_TICKET.length + 1);
|
|
807
|
-
const payloadStr =
|
|
1074
|
+
const payloadStr = readTicket(ticketId);
|
|
808
1075
|
if (!payloadStr) {
|
|
809
1076
|
res.writeHead(404, { "Content-Type": "application/json" });
|
|
810
1077
|
res.end(JSON.stringify({ success: false, error: "Ticket not found or expired" }));
|
|
@@ -818,54 +1085,28 @@ async function handleRequest(url, req, res) {
|
|
|
818
1085
|
res.end(JSON.stringify({ error: "not found" }));
|
|
819
1086
|
}
|
|
820
1087
|
async function dispatchToAi(req) {
|
|
821
|
-
const { location, snippet, prompt } = req;
|
|
822
|
-
const userConfig = loadUserConfigSync(false, serverState.cwd, serverState.configRoot);
|
|
823
|
-
const resolvedTarget = resolveTargetTool(userConfig);
|
|
1088
|
+
const { location, snippet, prompt, screenshotContext } = req;
|
|
824
1089
|
const formattedPrompt = prompt ?? `Please help me with this code from \`${location.file}\` (line ${location.line}):
|
|
825
1090
|
|
|
826
1091
|
\`\`\`
|
|
827
1092
|
${snippet}
|
|
828
1093
|
\`\`\`
|
|
829
1094
|
`;
|
|
830
|
-
const
|
|
831
|
-
|
|
832
|
-
const activeIde = serverState.ideInfo?.ide;
|
|
833
|
-
const activeIdeScheme = serverState.ideInfo?.scheme;
|
|
834
|
-
const finalIde = configuredIde || activeIdeScheme || activeIde || "vscode";
|
|
835
|
-
if (configuredIde && activeIdeScheme && !activeIdeScheme.includes(configuredIde)) {
|
|
836
|
-
serverLogger.warn(
|
|
837
|
-
`dispatchToAi: Active IDE is ${activeIdeScheme}, but config forces ${configuredIde}. Using configured IDE.`
|
|
838
|
-
);
|
|
839
|
-
}
|
|
840
|
-
const mode = resolveProviderMode(resolvedTarget, finalIde, userConfig);
|
|
841
|
-
const overrides = extractToolOverrides(finalIde, userConfig)[resolvedTarget] || {};
|
|
842
|
-
overrides.type = mode;
|
|
843
|
-
const fullPayload = {
|
|
844
|
-
ide: finalIde,
|
|
845
|
-
target: resolvedTarget,
|
|
846
|
-
targetType: mode,
|
|
1095
|
+
const runtime = resolvePromptDispatchRuntime(serverState);
|
|
1096
|
+
return dispatchPromptThroughIde(runtime, {
|
|
847
1097
|
prompt: formattedPrompt,
|
|
848
1098
|
filePath: location.file,
|
|
849
1099
|
line: location.line,
|
|
850
1100
|
column: location.column,
|
|
851
1101
|
snippet,
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
serverLogger.debug(`dispatchToAi: Generated URI: ${uri}`);
|
|
861
|
-
launchURI(uri);
|
|
862
|
-
return {
|
|
863
|
-
success: true,
|
|
864
|
-
fallbackPayload: {
|
|
865
|
-
prompt: formattedPrompt,
|
|
866
|
-
file: location.file
|
|
867
|
-
}
|
|
868
|
-
};
|
|
1102
|
+
...screenshotContext ? { screenshotContext } : {}
|
|
1103
|
+
});
|
|
1104
|
+
}
|
|
1105
|
+
function getBatchDispatchStatusCode(errorCode, success) {
|
|
1106
|
+
if (success) return 200;
|
|
1107
|
+
if (errorCode === "INVALID_REQUEST") return 400;
|
|
1108
|
+
if (errorCode === "FORBIDDEN_PATH") return 403;
|
|
1109
|
+
return 500;
|
|
869
1110
|
}
|
|
870
1111
|
|
|
871
1112
|
// src/injectors/utils.ts
|
|
@@ -900,7 +1141,7 @@ window.addEventListener('load', () => {
|
|
|
900
1141
|
}
|
|
901
1142
|
|
|
902
1143
|
// src/legacy/rspack/index.ts
|
|
903
|
-
import
|
|
1144
|
+
import path7 from "path";
|
|
904
1145
|
var _dirname = typeof __dirname !== "undefined" ? __dirname : __dirname;
|
|
905
1146
|
var DEFAULT_OPTIONS = {
|
|
906
1147
|
include: [],
|
|
@@ -970,7 +1211,7 @@ var InspectoRspackLegacyPlugin = class {
|
|
|
970
1211
|
);
|
|
971
1212
|
}
|
|
972
1213
|
});
|
|
973
|
-
const loaderPath =
|
|
1214
|
+
const loaderPath = path7.resolve(_dirname, "./loader.cjs");
|
|
974
1215
|
compiler.options.module.rules.push({
|
|
975
1216
|
test: /\.[jt]sx?$/,
|
|
976
1217
|
use: [
|