@inspecto-dev/plugin 0.3.8 → 0.3.10
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/dist/astro.cjs +572 -86
- package/dist/astro.cjs.map +1 -1
- package/dist/astro.d.cts +1 -1
- package/dist/astro.d.ts +1 -1
- package/dist/astro.js +571 -85
- package/dist/astro.js.map +1 -1
- package/dist/index.cjs +559 -83
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +558 -82
- package/dist/index.js.map +1 -1
- package/dist/legacy/rspack/index.cjs +526 -74
- package/dist/legacy/rspack/index.cjs.map +1 -1
- package/dist/legacy/rspack/index.js +526 -74
- package/dist/legacy/rspack/index.js.map +1 -1
- package/dist/legacy/rspack/loader.cjs +4 -1
- package/dist/legacy/rspack/loader.cjs.map +1 -1
- package/dist/legacy/rspack/loader.js +3 -0
- package/dist/legacy/rspack/loader.js.map +1 -1
- package/dist/legacy/webpack4/index.cjs +526 -74
- package/dist/legacy/webpack4/index.cjs.map +1 -1
- package/dist/legacy/webpack4/index.js +526 -74
- package/dist/legacy/webpack4/index.js.map +1 -1
- package/dist/legacy/webpack4/loader.cjs +4 -1
- package/dist/legacy/webpack4/loader.cjs.map +1 -1
- package/dist/legacy/webpack4/loader.js +3 -0
- package/dist/legacy/webpack4/loader.js.map +1 -1
- package/dist/rollup.cjs +559 -83
- package/dist/rollup.cjs.map +1 -1
- package/dist/rollup.js +558 -82
- package/dist/rollup.js.map +1 -1
- package/dist/rspack.cjs +559 -83
- package/dist/rspack.cjs.map +1 -1
- package/dist/rspack.js +558 -82
- package/dist/rspack.js.map +1 -1
- package/dist/vite.cjs +559 -83
- package/dist/vite.cjs.map +1 -1
- package/dist/vite.js +558 -82
- package/dist/vite.js.map +1 -1
- package/dist/webpack.cjs +559 -83
- package/dist/webpack.cjs.map +1 -1
- package/dist/webpack.js +558 -82
- package/dist/webpack.js.map +1 -1
- package/package.json +8 -12
package/dist/astro.cjs
CHANGED
|
@@ -36,7 +36,7 @@ __export(astro_exports, {
|
|
|
36
36
|
});
|
|
37
37
|
module.exports = __toCommonJS(astro_exports);
|
|
38
38
|
|
|
39
|
-
// ../../node_modules/.pnpm/tsup@8.5.1_jiti@2.
|
|
39
|
+
// ../../node_modules/.pnpm/tsup@8.5.1_jiti@2.7.0_postcss@8.5.14_typescript@5.9.3_yaml@2.8.4/node_modules/tsup/assets/cjs_shims.js
|
|
40
40
|
var getImportMetaUrl = () => typeof document === "undefined" ? new URL(`file:${__filename}`).href : document.currentScript && document.currentScript.tagName.toUpperCase() === "SCRIPT" ? document.currentScript.src : new URL("main.js", document.baseURI).href;
|
|
41
41
|
var importMetaUrl = /* @__PURE__ */ getImportMetaUrl();
|
|
42
42
|
|
|
@@ -551,7 +551,6 @@ function dispatchPromptThroughIde(runtime, payload) {
|
|
|
551
551
|
line: payload.line,
|
|
552
552
|
column: payload.column,
|
|
553
553
|
snippet: payload.snippet,
|
|
554
|
-
...payload.screenshotContext ? { screenshotContext: payload.screenshotContext } : {},
|
|
555
554
|
overrides: runtime.overrides,
|
|
556
555
|
autoSend: runtime.autoSend
|
|
557
556
|
});
|
|
@@ -685,6 +684,188 @@ function assertPathWithinIdeOpenScope(file, projectRoot) {
|
|
|
685
684
|
}
|
|
686
685
|
}
|
|
687
686
|
|
|
687
|
+
// src/server/session-store.ts
|
|
688
|
+
var DEFAULT_STATUS = "pending";
|
|
689
|
+
function createAnnotationSessionStore(options = {}) {
|
|
690
|
+
const sessions = /* @__PURE__ */ new Map();
|
|
691
|
+
const listeners = /* @__PURE__ */ new Set();
|
|
692
|
+
const now = options.now ?? (() => Date.now());
|
|
693
|
+
const createId = options.createId ?? createRandomId;
|
|
694
|
+
function findNewestMatchingSession(statuses) {
|
|
695
|
+
return [...sessions.values()].filter((session) => statuses ? statuses.has(session.status) : true).sort((left, right) => right.updatedAt - left.updatedAt)[0] ?? null;
|
|
696
|
+
}
|
|
697
|
+
function updateSessionStatus(id, status) {
|
|
698
|
+
const session = sessions.get(id);
|
|
699
|
+
if (!session) return null;
|
|
700
|
+
const timestamp = now();
|
|
701
|
+
session.status = status;
|
|
702
|
+
session.updatedAt = timestamp;
|
|
703
|
+
if (status === "acknowledged") {
|
|
704
|
+
session.acknowledgedAt = timestamp;
|
|
705
|
+
}
|
|
706
|
+
if (status === "resolved") {
|
|
707
|
+
session.resolvedAt = timestamp;
|
|
708
|
+
}
|
|
709
|
+
emit({ type: "session-status-updated", session });
|
|
710
|
+
return cloneSession(session);
|
|
711
|
+
}
|
|
712
|
+
function claimSession(id, statuses) {
|
|
713
|
+
const session = sessions.get(id);
|
|
714
|
+
if (!session || statuses && !statuses.has(session.status)) return null;
|
|
715
|
+
if (session.status === "acknowledged") return cloneSession(session);
|
|
716
|
+
return updateSessionStatus(id, "acknowledged");
|
|
717
|
+
}
|
|
718
|
+
function emit(event) {
|
|
719
|
+
const snapshot = cloneSession(event.session);
|
|
720
|
+
for (const listener of listeners) {
|
|
721
|
+
listener({ type: event.type, session: snapshot });
|
|
722
|
+
}
|
|
723
|
+
}
|
|
724
|
+
const store = {
|
|
725
|
+
createSession(input) {
|
|
726
|
+
const timestamp = now();
|
|
727
|
+
const session = {
|
|
728
|
+
id: createId(),
|
|
729
|
+
instruction: input.instruction?.trim() ?? "",
|
|
730
|
+
annotations: cloneArray(input.annotations),
|
|
731
|
+
...input.deliveryMode ? { deliveryMode: input.deliveryMode } : {},
|
|
732
|
+
status: DEFAULT_STATUS,
|
|
733
|
+
messages: cloneArray(input.messages ?? []),
|
|
734
|
+
createdAt: timestamp,
|
|
735
|
+
updatedAt: timestamp,
|
|
736
|
+
...input.runtimeContext ? { runtimeContext: cloneValue(input.runtimeContext) } : {},
|
|
737
|
+
...input.cssContextPrompt?.trim() ? { cssContextPrompt: input.cssContextPrompt.trim() } : {},
|
|
738
|
+
...input.pageUrl ? { pageUrl: input.pageUrl } : {},
|
|
739
|
+
...input.route ? { route: input.route } : {}
|
|
740
|
+
};
|
|
741
|
+
sessions.set(session.id, session);
|
|
742
|
+
emit({ type: "session-created", session });
|
|
743
|
+
return cloneSession(session);
|
|
744
|
+
},
|
|
745
|
+
getSession(id) {
|
|
746
|
+
const session = sessions.get(id);
|
|
747
|
+
return session ? cloneSession(session) : null;
|
|
748
|
+
},
|
|
749
|
+
listSessions(options2 = {}) {
|
|
750
|
+
const statuses = normalizeStatuses(options2.status);
|
|
751
|
+
return [...sessions.values()].filter((session) => statuses ? statuses.has(session.status) : true).sort((left, right) => right.updatedAt - left.updatedAt).map((session) => cloneSession(session));
|
|
752
|
+
},
|
|
753
|
+
async claimNextSession(options2 = {}) {
|
|
754
|
+
const statuses = normalizeStatuses(DEFAULT_STATUS);
|
|
755
|
+
const existingSession = findNewestMatchingSession(statuses);
|
|
756
|
+
if (existingSession) {
|
|
757
|
+
return {
|
|
758
|
+
session: claimSession(existingSession.id, statuses),
|
|
759
|
+
timedOut: false,
|
|
760
|
+
matchedExisting: true
|
|
761
|
+
};
|
|
762
|
+
}
|
|
763
|
+
const timeoutMs = normalizeTimeoutMs(options2.timeoutMs);
|
|
764
|
+
if (timeoutMs === 0) {
|
|
765
|
+
return {
|
|
766
|
+
session: null,
|
|
767
|
+
timedOut: true,
|
|
768
|
+
matchedExisting: false
|
|
769
|
+
};
|
|
770
|
+
}
|
|
771
|
+
return await new Promise((resolve2) => {
|
|
772
|
+
let settled = false;
|
|
773
|
+
let timeout = null;
|
|
774
|
+
const finish = (result) => {
|
|
775
|
+
if (settled) return;
|
|
776
|
+
settled = true;
|
|
777
|
+
unsubscribe();
|
|
778
|
+
if (timeout) {
|
|
779
|
+
clearTimeout(timeout);
|
|
780
|
+
}
|
|
781
|
+
resolve2(result);
|
|
782
|
+
};
|
|
783
|
+
const unsubscribe = this.subscribe((event) => {
|
|
784
|
+
const session = claimSession(event.session.id, statuses);
|
|
785
|
+
if (!session) return;
|
|
786
|
+
finish({
|
|
787
|
+
session,
|
|
788
|
+
timedOut: false,
|
|
789
|
+
matchedExisting: false,
|
|
790
|
+
event: event.type
|
|
791
|
+
});
|
|
792
|
+
});
|
|
793
|
+
if (timeoutMs !== null) {
|
|
794
|
+
timeout = setTimeout(() => {
|
|
795
|
+
finish({
|
|
796
|
+
session: null,
|
|
797
|
+
timedOut: true,
|
|
798
|
+
matchedExisting: false
|
|
799
|
+
});
|
|
800
|
+
}, timeoutMs);
|
|
801
|
+
}
|
|
802
|
+
});
|
|
803
|
+
},
|
|
804
|
+
appendMessage(id, input) {
|
|
805
|
+
const session = sessions.get(id);
|
|
806
|
+
if (!session) return null;
|
|
807
|
+
const timestamp = now();
|
|
808
|
+
session.messages.push({
|
|
809
|
+
id: createId(),
|
|
810
|
+
role: input.role,
|
|
811
|
+
text: input.text,
|
|
812
|
+
createdAt: timestamp
|
|
813
|
+
});
|
|
814
|
+
session.updatedAt = timestamp;
|
|
815
|
+
if (input.role === "agent" && isPendingLikeStatus(session.status)) {
|
|
816
|
+
session.status = "in_progress";
|
|
817
|
+
}
|
|
818
|
+
emit({ type: "session-message-appended", session });
|
|
819
|
+
return cloneSession(session);
|
|
820
|
+
},
|
|
821
|
+
updateStatus(id, status) {
|
|
822
|
+
return updateSessionStatus(id, status);
|
|
823
|
+
},
|
|
824
|
+
subscribe(listener) {
|
|
825
|
+
listeners.add(listener);
|
|
826
|
+
return () => {
|
|
827
|
+
listeners.delete(listener);
|
|
828
|
+
};
|
|
829
|
+
},
|
|
830
|
+
clear() {
|
|
831
|
+
sessions.clear();
|
|
832
|
+
listeners.clear();
|
|
833
|
+
}
|
|
834
|
+
};
|
|
835
|
+
return store;
|
|
836
|
+
}
|
|
837
|
+
var annotationSessionStore = createAnnotationSessionStore();
|
|
838
|
+
function normalizeStatuses(status) {
|
|
839
|
+
if (!status) return null;
|
|
840
|
+
return new Set(Array.isArray(status) ? status : [status]);
|
|
841
|
+
}
|
|
842
|
+
function normalizeTimeoutMs(value) {
|
|
843
|
+
if (value === void 0) return null;
|
|
844
|
+
if (!Number.isFinite(value)) return 0;
|
|
845
|
+
return Math.max(0, Math.floor(value));
|
|
846
|
+
}
|
|
847
|
+
function isPendingLikeStatus(status) {
|
|
848
|
+
return status === "pending" || status === "acknowledged";
|
|
849
|
+
}
|
|
850
|
+
function hasAgentReply(session) {
|
|
851
|
+
return session.messages.some((message) => message.role === "agent" && Boolean(message.text?.trim()));
|
|
852
|
+
}
|
|
853
|
+
function createRandomId() {
|
|
854
|
+
return `annotation-session-${Math.random().toString(36).slice(2, 10)}`;
|
|
855
|
+
}
|
|
856
|
+
function cloneSession(session) {
|
|
857
|
+
return cloneValue(session);
|
|
858
|
+
}
|
|
859
|
+
function cloneArray(value) {
|
|
860
|
+
return cloneValue(value);
|
|
861
|
+
}
|
|
862
|
+
function cloneValue(value) {
|
|
863
|
+
if (typeof structuredClone === "function") {
|
|
864
|
+
return structuredClone(value);
|
|
865
|
+
}
|
|
866
|
+
return JSON.parse(JSON.stringify(value));
|
|
867
|
+
}
|
|
868
|
+
|
|
688
869
|
// src/server/annotation-dispatch.ts
|
|
689
870
|
var AnnotationDispatchError = class extends Error {
|
|
690
871
|
constructor(message, errorCode) {
|
|
@@ -693,20 +874,30 @@ var AnnotationDispatchError = class extends Error {
|
|
|
693
874
|
this.errorCode = errorCode;
|
|
694
875
|
}
|
|
695
876
|
};
|
|
696
|
-
async function dispatchAnnotationsToAi(req, state) {
|
|
877
|
+
async function dispatchAnnotationsToAi(req, state, store = annotationSessionStore) {
|
|
697
878
|
try {
|
|
698
879
|
validateAnnotationDispatchRequest(req, state);
|
|
699
880
|
const batch = normalizeAnnotationBatch(req);
|
|
700
881
|
const prompt = buildAnnotationBatchPrompt(batch);
|
|
882
|
+
const deliveryMode = normalizeDeliveryMode(req.deliveryMode);
|
|
883
|
+
const session = store.createSession({
|
|
884
|
+
instruction: batch.instruction,
|
|
885
|
+
annotations: toSessionAnnotations(batch.annotations),
|
|
886
|
+
deliveryMode,
|
|
887
|
+
...batch.runtimeContext ? { runtimeContext: batch.runtimeContext } : {},
|
|
888
|
+
...batch.cssContextPrompt ? { cssContextPrompt: batch.cssContextPrompt } : {}
|
|
889
|
+
});
|
|
701
890
|
const representativeTarget = batch.annotations[0]?.targets[0];
|
|
702
|
-
const
|
|
703
|
-
return dispatchPromptThroughIde(runtime, {
|
|
891
|
+
const dispatchResult = deliveryMode === "ide" ? dispatchPromptThroughIde(resolvePromptDispatchRuntime(state), {
|
|
704
892
|
prompt,
|
|
705
893
|
...representativeTarget?.file ? { filePath: representativeTarget.file } : {},
|
|
706
894
|
...representativeTarget?.line ? { line: representativeTarget.line } : {},
|
|
707
|
-
...representativeTarget?.column ? { column: representativeTarget.column } : {}
|
|
708
|
-
|
|
709
|
-
|
|
895
|
+
...representativeTarget?.column ? { column: representativeTarget.column } : {}
|
|
896
|
+
}) : { success: true };
|
|
897
|
+
return {
|
|
898
|
+
...dispatchResult,
|
|
899
|
+
session: toSessionSummary(session)
|
|
900
|
+
};
|
|
710
901
|
} catch (error) {
|
|
711
902
|
return {
|
|
712
903
|
success: false,
|
|
@@ -715,6 +906,41 @@ async function dispatchAnnotationsToAi(req, state) {
|
|
|
715
906
|
};
|
|
716
907
|
}
|
|
717
908
|
}
|
|
909
|
+
function normalizeDeliveryMode(input) {
|
|
910
|
+
return input === "agent" ? "agent" : "ide";
|
|
911
|
+
}
|
|
912
|
+
function toSessionAnnotations(annotations) {
|
|
913
|
+
return annotations.map((annotation) => ({
|
|
914
|
+
id: `annotation-${annotation.index}`,
|
|
915
|
+
note: annotation.note,
|
|
916
|
+
intent: annotation.intent,
|
|
917
|
+
targets: annotation.targets.map((target, targetIndex) => ({
|
|
918
|
+
id: `annotation-${annotation.index}-target-${targetIndex + 1}`,
|
|
919
|
+
label: target.label ?? "Unknown target",
|
|
920
|
+
location: {
|
|
921
|
+
file: target.file,
|
|
922
|
+
line: target.line,
|
|
923
|
+
column: target.column
|
|
924
|
+
},
|
|
925
|
+
...target.selector ? { selector: target.selector } : {},
|
|
926
|
+
...target.snippet ? { snippet: target.snippet } : {},
|
|
927
|
+
rect: {
|
|
928
|
+
x: 0,
|
|
929
|
+
y: 0,
|
|
930
|
+
width: 0,
|
|
931
|
+
height: 0
|
|
932
|
+
}
|
|
933
|
+
}))
|
|
934
|
+
}));
|
|
935
|
+
}
|
|
936
|
+
function toSessionSummary(session) {
|
|
937
|
+
return {
|
|
938
|
+
id: session.id,
|
|
939
|
+
status: session.status,
|
|
940
|
+
createdAt: session.createdAt,
|
|
941
|
+
updatedAt: session.updatedAt
|
|
942
|
+
};
|
|
943
|
+
}
|
|
718
944
|
function validateAnnotationDispatchRequest(req, state) {
|
|
719
945
|
if (!req.annotations.length) {
|
|
720
946
|
throw new AnnotationDispatchError("At least one annotation is required.", "INVALID_REQUEST");
|
|
@@ -735,9 +961,7 @@ function validateAnnotationDispatchRequest(req, state) {
|
|
|
735
961
|
function normalizeAnnotationBatch(req) {
|
|
736
962
|
return {
|
|
737
963
|
instruction: req.instruction?.trim() ?? "",
|
|
738
|
-
responseMode: req.responseMode ?? "unified",
|
|
739
964
|
...req.runtimeContext ? { runtimeContext: req.runtimeContext } : {},
|
|
740
|
-
...req.screenshotContext ? { screenshotContext: req.screenshotContext } : {},
|
|
741
965
|
...req.cssContextPrompt?.trim() ? { cssContextPrompt: req.cssContextPrompt.trim() } : {},
|
|
742
966
|
annotations: req.annotations.map((annotation, index) => ({
|
|
743
967
|
index: index + 1,
|
|
@@ -759,12 +983,9 @@ function buildAnnotationBatchPrompt(batch) {
|
|
|
759
983
|
const prompt = batch.instruction ? `${batch.instruction}
|
|
760
984
|
|
|
761
985
|
${body}` : body;
|
|
762
|
-
return
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
batch.cssContextPrompt
|
|
766
|
-
),
|
|
767
|
-
batch.screenshotContext
|
|
986
|
+
return appendCssContextSection(
|
|
987
|
+
appendRuntimeContextSection(prompt, batch.runtimeContext),
|
|
988
|
+
batch.cssContextPrompt
|
|
768
989
|
);
|
|
769
990
|
}
|
|
770
991
|
function appendCssContextSection(prompt, cssContextPrompt) {
|
|
@@ -791,20 +1012,6 @@ function buildSelectedElementsPrompt(annotations) {
|
|
|
791
1012
|
}
|
|
792
1013
|
return lines.join("\n");
|
|
793
1014
|
}
|
|
794
|
-
function appendScreenshotContextSection(prompt, screenshotContext) {
|
|
795
|
-
if (!screenshotContext || !screenshotContext.imageDataUrl && !screenshotContext.imageAssetId) {
|
|
796
|
-
return prompt;
|
|
797
|
-
}
|
|
798
|
-
const lines = [
|
|
799
|
-
"Visual screenshot context attached:",
|
|
800
|
-
`- capturedAt=${screenshotContext.capturedAt}`,
|
|
801
|
-
`- mimeType=${screenshotContext.mimeType}`,
|
|
802
|
-
...screenshotContext.imageAssetId ? [`- imageAssetId=${screenshotContext.imageAssetId}`] : []
|
|
803
|
-
];
|
|
804
|
-
return `${prompt}
|
|
805
|
-
|
|
806
|
-
${lines.join("\n")}`;
|
|
807
|
-
}
|
|
808
1015
|
function appendRuntimeContextSection(prompt, runtimeContext) {
|
|
809
1016
|
if (!runtimeContext?.records.length) {
|
|
810
1017
|
return prompt;
|
|
@@ -852,7 +1059,7 @@ async function buildClientConfig(serverState2) {
|
|
|
852
1059
|
...info,
|
|
853
1060
|
prompts: resolveIntents(promptsConfig),
|
|
854
1061
|
hotKeys: userConfig["inspector.hotKey"] ?? "alt",
|
|
855
|
-
|
|
1062
|
+
annotateDeliveryMode: userConfig["annotate.deliveryMode"] ?? "both",
|
|
856
1063
|
includeSnippet: userConfig["prompt.includeSnippet"] ?? false,
|
|
857
1064
|
runtimeContext: {
|
|
858
1065
|
enabled: true,
|
|
@@ -860,10 +1067,6 @@ async function buildClientConfig(serverState2) {
|
|
|
860
1067
|
maxRuntimeErrors: 3,
|
|
861
1068
|
maxFailedRequests: 2
|
|
862
1069
|
},
|
|
863
|
-
screenshotContext: {
|
|
864
|
-
enabled: false
|
|
865
|
-
},
|
|
866
|
-
annotationResponseMode: userConfig["prompt.annotationResponseMode"] ?? "unified",
|
|
867
1070
|
autoSend: userConfig["prompt.autoSend"] ?? false
|
|
868
1071
|
};
|
|
869
1072
|
}
|
|
@@ -908,7 +1111,7 @@ function handleOpenFileRequest(body, serverState2) {
|
|
|
908
1111
|
else if (rawEditorHint === "vscodium") editorHint = "codium";
|
|
909
1112
|
else if (rawEditorHint === "trae-cn" || rawEditorHint === "trae") editorHint = "trae";
|
|
910
1113
|
serverLogger2.debug(
|
|
911
|
-
`
|
|
1114
|
+
`SOURCE_OPEN: activeIde=${activeIde}, activeIdeScheme=${activeIdeScheme}, configuredIde=${configuredIde} -> rawEditorHint=${rawEditorHint}, finalEditorHint=${editorHint}`
|
|
912
1115
|
);
|
|
913
1116
|
if (VSCODE_FAMILY_SCHEMES.includes(rawEditorHint)) {
|
|
914
1117
|
let normalizedPath = absolutePath.replace(/\\/g, "/");
|
|
@@ -917,7 +1120,7 @@ function handleOpenFileRequest(body, serverState2) {
|
|
|
917
1120
|
}
|
|
918
1121
|
const encodedPath = encodeURI(normalizedPath);
|
|
919
1122
|
const uri = `${rawEditorHint}://file${encodedPath}:${body.line}:${body.column}`;
|
|
920
|
-
serverLogger2.debug(`
|
|
1123
|
+
serverLogger2.debug(`SOURCE_OPEN: Bypassing launchIDE, using URI scheme directly: ${uri}`);
|
|
921
1124
|
try {
|
|
922
1125
|
if (process.platform === "darwin") {
|
|
923
1126
|
(0, import_node_child_process2.execFileSync)("open", [uri]);
|
|
@@ -927,7 +1130,7 @@ function handleOpenFileRequest(body, serverState2) {
|
|
|
927
1130
|
(0, import_node_child_process2.execFileSync)("xdg-open", [uri]);
|
|
928
1131
|
}
|
|
929
1132
|
} catch (e) {
|
|
930
|
-
serverLogger2.error(`Failed to launch URI for
|
|
1133
|
+
serverLogger2.error(`Failed to launch URI for SOURCE_OPEN (${uri}):`, e);
|
|
931
1134
|
(0, import_launch_ide2.launchIDE)({
|
|
932
1135
|
file: absolutePath,
|
|
933
1136
|
line: body.line,
|
|
@@ -982,8 +1185,27 @@ function resolveProjectRoot() {
|
|
|
982
1185
|
return gitRoot;
|
|
983
1186
|
}
|
|
984
1187
|
|
|
1188
|
+
// src/server/server-url.ts
|
|
1189
|
+
function resolveServerHost(cwd, configRoot) {
|
|
1190
|
+
const userConfig = loadUserConfigSync(false, cwd, configRoot);
|
|
1191
|
+
const configuredHost = userConfig["server.host"]?.trim();
|
|
1192
|
+
if (configuredHost) return configuredHost;
|
|
1193
|
+
if (process.env["VITEST"]) return "127.0.0.1";
|
|
1194
|
+
return "127.0.0.1";
|
|
1195
|
+
}
|
|
1196
|
+
function resolvePublicServerUrl(args) {
|
|
1197
|
+
const userConfig = loadUserConfigSync(false, args.cwd, args.configRoot);
|
|
1198
|
+
const configuredPublicUrl = userConfig["server.publicUrl"]?.trim();
|
|
1199
|
+
if (configuredPublicUrl) {
|
|
1200
|
+
return configuredPublicUrl.replace(/\/$/, "");
|
|
1201
|
+
}
|
|
1202
|
+
const host = resolveServerHost(args.cwd, args.configRoot);
|
|
1203
|
+
return `http://${host}:${args.port}`;
|
|
1204
|
+
}
|
|
1205
|
+
|
|
985
1206
|
// src/server/index.ts
|
|
986
1207
|
var serverLogger4 = createLogger("inspecto:server", { logLevel: getGlobalLogLevel() });
|
|
1208
|
+
var PORT_FILE_NAME = "inspecto.port.json";
|
|
987
1209
|
var serverState = {
|
|
988
1210
|
port: null,
|
|
989
1211
|
running: false,
|
|
@@ -992,6 +1214,42 @@ var serverState = {
|
|
|
992
1214
|
cwd: process.cwd()
|
|
993
1215
|
};
|
|
994
1216
|
var serverInstance = null;
|
|
1217
|
+
function getPortFilePath() {
|
|
1218
|
+
return import_node_path4.default.join(import_node_os2.default.tmpdir(), PORT_FILE_NAME);
|
|
1219
|
+
}
|
|
1220
|
+
function getProjectRootHash() {
|
|
1221
|
+
if (!serverState.projectRoot) return null;
|
|
1222
|
+
return import_node_crypto2.default.createHash("md5").update(serverState.projectRoot).digest("hex");
|
|
1223
|
+
}
|
|
1224
|
+
function readPortData(portFile) {
|
|
1225
|
+
if (!import_node_fs4.default.existsSync(portFile)) return {};
|
|
1226
|
+
try {
|
|
1227
|
+
return JSON.parse(import_node_fs4.default.readFileSync(portFile, "utf-8"));
|
|
1228
|
+
} catch {
|
|
1229
|
+
return {};
|
|
1230
|
+
}
|
|
1231
|
+
}
|
|
1232
|
+
function writeProjectPort(port) {
|
|
1233
|
+
const rootHash = getProjectRootHash();
|
|
1234
|
+
if (!rootHash) return;
|
|
1235
|
+
const portFile = getPortFilePath();
|
|
1236
|
+
const portData = readPortData(portFile);
|
|
1237
|
+
portData[rootHash] = port;
|
|
1238
|
+
import_node_fs4.default.writeFileSync(portFile, JSON.stringify(portData, null, 2), "utf-8");
|
|
1239
|
+
}
|
|
1240
|
+
function removeProjectPort() {
|
|
1241
|
+
const rootHash = getProjectRootHash();
|
|
1242
|
+
if (!rootHash) return;
|
|
1243
|
+
const portFile = getPortFilePath();
|
|
1244
|
+
if (!import_node_fs4.default.existsSync(portFile)) return;
|
|
1245
|
+
const portData = readPortData(portFile);
|
|
1246
|
+
delete portData[rootHash];
|
|
1247
|
+
if (Object.keys(portData).length === 0) {
|
|
1248
|
+
import_node_fs4.default.unlinkSync(portFile);
|
|
1249
|
+
} else {
|
|
1250
|
+
import_node_fs4.default.writeFileSync(portFile, JSON.stringify(portData, null, 2), "utf-8");
|
|
1251
|
+
}
|
|
1252
|
+
}
|
|
995
1253
|
async function startServer() {
|
|
996
1254
|
if (serverState.running && serverState.port !== null) {
|
|
997
1255
|
return serverState.port;
|
|
@@ -999,6 +1257,7 @@ async function startServer() {
|
|
|
999
1257
|
serverState.projectRoot = resolveProjectRoot();
|
|
1000
1258
|
serverState.configRoot = serverState.projectRoot;
|
|
1001
1259
|
serverState.cwd = process.cwd();
|
|
1260
|
+
const serverHost = resolveServerHost(serverState.cwd, serverState.configRoot);
|
|
1002
1261
|
import_portfinder.default.basePort = 5678;
|
|
1003
1262
|
const port = await import_portfinder.default.getPortPromise();
|
|
1004
1263
|
watchConfig(
|
|
@@ -1025,7 +1284,7 @@ async function startServer() {
|
|
|
1025
1284
|
});
|
|
1026
1285
|
});
|
|
1027
1286
|
await new Promise((resolve2, reject) => {
|
|
1028
|
-
serverInstance.listen(port,
|
|
1287
|
+
serverInstance.listen(port, serverHost, () => {
|
|
1029
1288
|
serverInstance.unref();
|
|
1030
1289
|
resolve2();
|
|
1031
1290
|
});
|
|
@@ -1036,37 +1295,18 @@ async function startServer() {
|
|
|
1036
1295
|
});
|
|
1037
1296
|
serverState.port = port;
|
|
1038
1297
|
serverState.running = true;
|
|
1039
|
-
const portFile = import_node_path4.default.join(import_node_os2.default.tmpdir(), "inspecto.port.json");
|
|
1040
1298
|
try {
|
|
1041
|
-
|
|
1042
|
-
if (import_node_fs4.default.existsSync(portFile)) {
|
|
1043
|
-
try {
|
|
1044
|
-
portData = JSON.parse(import_node_fs4.default.readFileSync(portFile, "utf-8"));
|
|
1045
|
-
} catch (_e) {
|
|
1046
|
-
}
|
|
1047
|
-
}
|
|
1048
|
-
const rootHash = import_node_crypto2.default.createHash("md5").update(serverState.projectRoot).digest("hex");
|
|
1049
|
-
portData[rootHash] = port;
|
|
1050
|
-
import_node_fs4.default.writeFileSync(portFile, JSON.stringify(portData, null, 2), "utf-8");
|
|
1299
|
+
writeProjectPort(port);
|
|
1051
1300
|
} catch (_e) {
|
|
1052
1301
|
serverLogger4.warn("Failed to write port file:", _e);
|
|
1053
1302
|
}
|
|
1054
1303
|
process.once("exit", () => {
|
|
1055
1304
|
try {
|
|
1056
|
-
|
|
1057
|
-
const portData = JSON.parse(import_node_fs4.default.readFileSync(portFile, "utf-8"));
|
|
1058
|
-
const rootHash = import_node_crypto2.default.createHash("md5").update(serverState.projectRoot).digest("hex");
|
|
1059
|
-
delete portData[rootHash];
|
|
1060
|
-
if (Object.keys(portData).length === 0) {
|
|
1061
|
-
import_node_fs4.default.unlinkSync(portFile);
|
|
1062
|
-
} else {
|
|
1063
|
-
import_node_fs4.default.writeFileSync(portFile, JSON.stringify(portData, null, 2), "utf-8");
|
|
1064
|
-
}
|
|
1065
|
-
}
|
|
1305
|
+
removeProjectPort();
|
|
1066
1306
|
} catch {
|
|
1067
1307
|
}
|
|
1068
1308
|
});
|
|
1069
|
-
serverLogger4.info(`server running at http
|
|
1309
|
+
serverLogger4.info(`server running at http://${serverHost}:${port}`);
|
|
1070
1310
|
return port;
|
|
1071
1311
|
}
|
|
1072
1312
|
async function readBody(req) {
|
|
@@ -1118,7 +1358,7 @@ async function handleRequest(url, req, res) {
|
|
|
1118
1358
|
}
|
|
1119
1359
|
return;
|
|
1120
1360
|
}
|
|
1121
|
-
if (pathname === import_types2.INSPECTO_API_PATHS.IDE_OPEN && req.method === "POST") {
|
|
1361
|
+
if ((pathname === import_types2.INSPECTO_API_PATHS.SOURCE_OPEN || pathname === import_types2.INSPECTO_API_PATHS.IDE_OPEN) && req.method === "POST") {
|
|
1122
1362
|
let body;
|
|
1123
1363
|
try {
|
|
1124
1364
|
body = JSON.parse(await readBody(req));
|
|
@@ -1131,7 +1371,7 @@ async function handleRequest(url, req, res) {
|
|
|
1131
1371
|
handleOpenFileRequest(body, serverState);
|
|
1132
1372
|
} catch (err) {
|
|
1133
1373
|
serverLogger4.warn(
|
|
1134
|
-
`Security: Blocked path traversal attempt in
|
|
1374
|
+
`Security: Blocked path traversal attempt in SOURCE_OPEN: ${body.file}. Reason: ${err.message}`
|
|
1135
1375
|
);
|
|
1136
1376
|
res.writeHead(403, { "Content-Type": "application/json" });
|
|
1137
1377
|
res.end(JSON.stringify({ error: "Access denied: File is outside of project workspace" }));
|
|
@@ -1205,6 +1445,212 @@ async function handleRequest(url, req, res) {
|
|
|
1205
1445
|
}
|
|
1206
1446
|
return;
|
|
1207
1447
|
}
|
|
1448
|
+
if (pathname === import_types2.INSPECTO_API_PATHS.SESSION_CLAIM_NEXT && req.method === "POST") {
|
|
1449
|
+
try {
|
|
1450
|
+
const rawBody = await readBody(req);
|
|
1451
|
+
const body = rawBody ? JSON.parse(rawBody) : {};
|
|
1452
|
+
const timeoutMs = normalizeSessionClaimTimeout(
|
|
1453
|
+
body.timeoutMs === void 0 ? null : String(body.timeoutMs)
|
|
1454
|
+
);
|
|
1455
|
+
const result = await annotationSessionStore.claimNextSession({
|
|
1456
|
+
...timeoutMs !== void 0 ? { timeoutMs } : {}
|
|
1457
|
+
});
|
|
1458
|
+
res.writeHead(200, { "Content-Type": "application/json" });
|
|
1459
|
+
res.end(
|
|
1460
|
+
JSON.stringify({
|
|
1461
|
+
success: true,
|
|
1462
|
+
timedOut: result.timedOut,
|
|
1463
|
+
matchedExisting: result.matchedExisting,
|
|
1464
|
+
...result.event ? { event: result.event } : {},
|
|
1465
|
+
...result.session ? { session: result.session } : {}
|
|
1466
|
+
})
|
|
1467
|
+
);
|
|
1468
|
+
} catch (e) {
|
|
1469
|
+
serverLogger4.error(`Error parsing session claim request:`, e);
|
|
1470
|
+
res.writeHead(400, { "Content-Type": "application/json" });
|
|
1471
|
+
res.end(JSON.stringify({ success: false, error: "Invalid JSON body" }));
|
|
1472
|
+
}
|
|
1473
|
+
return;
|
|
1474
|
+
}
|
|
1475
|
+
if (pathname === import_types2.INSPECTO_API_PATHS.SESSION_EVENTS && req.method === "GET") {
|
|
1476
|
+
const statusParam = url.searchParams.getAll("status");
|
|
1477
|
+
const statuses = statusParam.length ? new Set(statusParam) : null;
|
|
1478
|
+
const sessionId = url.searchParams.get("sessionId")?.trim() || null;
|
|
1479
|
+
res.writeHead(200, {
|
|
1480
|
+
"Content-Type": "text/event-stream",
|
|
1481
|
+
"Cache-Control": "no-cache",
|
|
1482
|
+
Connection: "keep-alive"
|
|
1483
|
+
});
|
|
1484
|
+
res.write(`event: ready
|
|
1485
|
+
data: ${JSON.stringify({ ok: true })}
|
|
1486
|
+
|
|
1487
|
+
`);
|
|
1488
|
+
const unsubscribe = annotationSessionStore.subscribe((event) => {
|
|
1489
|
+
if (sessionId && event.session.id !== sessionId) {
|
|
1490
|
+
return;
|
|
1491
|
+
}
|
|
1492
|
+
if (statuses && !statuses.has(event.session.status)) {
|
|
1493
|
+
return;
|
|
1494
|
+
}
|
|
1495
|
+
res.write(formatSessionSseEvent(event));
|
|
1496
|
+
});
|
|
1497
|
+
req.on("close", () => {
|
|
1498
|
+
unsubscribe();
|
|
1499
|
+
res.end();
|
|
1500
|
+
});
|
|
1501
|
+
return;
|
|
1502
|
+
}
|
|
1503
|
+
if (pathname === import_types2.INSPECTO_API_PATHS.SESSIONS && req.method === "GET") {
|
|
1504
|
+
const statusParam = url.searchParams.getAll("status");
|
|
1505
|
+
const sessions = annotationSessionStore.listSessions(
|
|
1506
|
+
statusParam.length ? {
|
|
1507
|
+
status: statusParam
|
|
1508
|
+
} : void 0
|
|
1509
|
+
);
|
|
1510
|
+
res.writeHead(200, { "Content-Type": "application/json" });
|
|
1511
|
+
res.end(JSON.stringify({ success: true, sessions }));
|
|
1512
|
+
return;
|
|
1513
|
+
}
|
|
1514
|
+
if (pathname.startsWith(`${import_types2.INSPECTO_API_PATHS.SESSIONS}/`) && req.method === "GET") {
|
|
1515
|
+
const sessionId = pathname.substring(import_types2.INSPECTO_API_PATHS.SESSIONS.length + 1);
|
|
1516
|
+
const session = annotationSessionStore.getSession(sessionId);
|
|
1517
|
+
if (!session) {
|
|
1518
|
+
res.writeHead(404, { "Content-Type": "application/json" });
|
|
1519
|
+
res.end(JSON.stringify({ success: false, error: "Session not found" }));
|
|
1520
|
+
return;
|
|
1521
|
+
}
|
|
1522
|
+
res.writeHead(200, { "Content-Type": "application/json" });
|
|
1523
|
+
res.end(JSON.stringify({ success: true, session }));
|
|
1524
|
+
return;
|
|
1525
|
+
}
|
|
1526
|
+
if (pathname.startsWith(`${import_types2.INSPECTO_API_PATHS.SESSIONS}/`) && pathname.endsWith(import_types2.INSPECTO_API_PATHS.SESSION_REPLY_SUFFIX) && req.method === "POST") {
|
|
1527
|
+
const sessionId = pathname.slice(
|
|
1528
|
+
import_types2.INSPECTO_API_PATHS.SESSIONS.length + 1,
|
|
1529
|
+
-import_types2.INSPECTO_API_PATHS.SESSION_REPLY_SUFFIX.length
|
|
1530
|
+
);
|
|
1531
|
+
try {
|
|
1532
|
+
const rawBody = await readBody(req);
|
|
1533
|
+
const body = JSON.parse(rawBody);
|
|
1534
|
+
if (!isAnnotationThreadRole(body.role)) {
|
|
1535
|
+
res.writeHead(400, { "Content-Type": "application/json" });
|
|
1536
|
+
res.end(JSON.stringify({ success: false, error: "Reply role is invalid." }));
|
|
1537
|
+
return;
|
|
1538
|
+
}
|
|
1539
|
+
if (!body.text?.trim()) {
|
|
1540
|
+
res.writeHead(400, { "Content-Type": "application/json" });
|
|
1541
|
+
res.end(JSON.stringify({ success: false, error: "Reply text is required." }));
|
|
1542
|
+
return;
|
|
1543
|
+
}
|
|
1544
|
+
const session = annotationSessionStore.appendMessage(sessionId, {
|
|
1545
|
+
role: body.role,
|
|
1546
|
+
text: body.text.trim()
|
|
1547
|
+
});
|
|
1548
|
+
if (!session) {
|
|
1549
|
+
res.writeHead(404, { "Content-Type": "application/json" });
|
|
1550
|
+
res.end(JSON.stringify({ success: false, error: "Session not found" }));
|
|
1551
|
+
return;
|
|
1552
|
+
}
|
|
1553
|
+
res.writeHead(200, { "Content-Type": "application/json" });
|
|
1554
|
+
res.end(JSON.stringify({ success: true, session }));
|
|
1555
|
+
} catch (e) {
|
|
1556
|
+
serverLogger4.error(`Error parsing session reply request:`, e);
|
|
1557
|
+
res.writeHead(400, { "Content-Type": "application/json" });
|
|
1558
|
+
res.end(JSON.stringify({ success: false, error: "Invalid JSON body" }));
|
|
1559
|
+
}
|
|
1560
|
+
return;
|
|
1561
|
+
}
|
|
1562
|
+
if (pathname.startsWith(`${import_types2.INSPECTO_API_PATHS.SESSIONS}/`) && pathname.endsWith(import_types2.INSPECTO_API_PATHS.SESSION_RESOLVE_SUFFIX) && req.method === "POST") {
|
|
1563
|
+
const sessionId = pathname.slice(
|
|
1564
|
+
import_types2.INSPECTO_API_PATHS.SESSIONS.length + 1,
|
|
1565
|
+
-import_types2.INSPECTO_API_PATHS.SESSION_RESOLVE_SUFFIX.length
|
|
1566
|
+
);
|
|
1567
|
+
try {
|
|
1568
|
+
const rawBody = await readBody(req);
|
|
1569
|
+
const body = rawBody ? JSON.parse(rawBody) : {};
|
|
1570
|
+
const message = body.message?.trim();
|
|
1571
|
+
const existingSession = annotationSessionStore.getSession(sessionId);
|
|
1572
|
+
if (!existingSession) {
|
|
1573
|
+
res.writeHead(404, { "Content-Type": "application/json" });
|
|
1574
|
+
res.end(JSON.stringify({ success: false, error: "Session not found" }));
|
|
1575
|
+
return;
|
|
1576
|
+
}
|
|
1577
|
+
if (!message && !hasAgentReply(existingSession)) {
|
|
1578
|
+
res.writeHead(400, { "Content-Type": "application/json" });
|
|
1579
|
+
res.end(
|
|
1580
|
+
JSON.stringify({
|
|
1581
|
+
success: false,
|
|
1582
|
+
error: "Resolve message is required until an agent reply is recorded."
|
|
1583
|
+
})
|
|
1584
|
+
);
|
|
1585
|
+
return;
|
|
1586
|
+
}
|
|
1587
|
+
if (message) {
|
|
1588
|
+
const repliedSession = annotationSessionStore.appendMessage(sessionId, {
|
|
1589
|
+
role: "agent",
|
|
1590
|
+
text: message
|
|
1591
|
+
});
|
|
1592
|
+
if (!repliedSession) {
|
|
1593
|
+
res.writeHead(404, { "Content-Type": "application/json" });
|
|
1594
|
+
res.end(JSON.stringify({ success: false, error: "Session not found" }));
|
|
1595
|
+
return;
|
|
1596
|
+
}
|
|
1597
|
+
}
|
|
1598
|
+
const session = annotationSessionStore.updateStatus(sessionId, "resolved");
|
|
1599
|
+
if (!session) {
|
|
1600
|
+
res.writeHead(404, { "Content-Type": "application/json" });
|
|
1601
|
+
res.end(JSON.stringify({ success: false, error: "Session not found" }));
|
|
1602
|
+
return;
|
|
1603
|
+
}
|
|
1604
|
+
res.writeHead(200, { "Content-Type": "application/json" });
|
|
1605
|
+
res.end(JSON.stringify({ success: true, session }));
|
|
1606
|
+
} catch (e) {
|
|
1607
|
+
serverLogger4.error(`Error parsing session resolve request:`, e);
|
|
1608
|
+
res.writeHead(400, { "Content-Type": "application/json" });
|
|
1609
|
+
res.end(JSON.stringify({ success: false, error: "Invalid JSON body" }));
|
|
1610
|
+
}
|
|
1611
|
+
return;
|
|
1612
|
+
}
|
|
1613
|
+
if (pathname.startsWith(`${import_types2.INSPECTO_API_PATHS.SESSIONS}/`) && pathname.endsWith(import_types2.INSPECTO_API_PATHS.SESSION_DISMISS_SUFFIX) && req.method === "POST") {
|
|
1614
|
+
const sessionId = pathname.slice(
|
|
1615
|
+
import_types2.INSPECTO_API_PATHS.SESSIONS.length + 1,
|
|
1616
|
+
-import_types2.INSPECTO_API_PATHS.SESSION_DISMISS_SUFFIX.length
|
|
1617
|
+
);
|
|
1618
|
+
try {
|
|
1619
|
+
const rawBody = await readBody(req);
|
|
1620
|
+
const body = rawBody ? JSON.parse(rawBody) : {};
|
|
1621
|
+
const message = body.message?.trim();
|
|
1622
|
+
const existingSession = annotationSessionStore.getSession(sessionId);
|
|
1623
|
+
if (!existingSession) {
|
|
1624
|
+
res.writeHead(404, { "Content-Type": "application/json" });
|
|
1625
|
+
res.end(JSON.stringify({ success: false, error: "Session not found" }));
|
|
1626
|
+
return;
|
|
1627
|
+
}
|
|
1628
|
+
if (message) {
|
|
1629
|
+
const repliedSession = annotationSessionStore.appendMessage(sessionId, {
|
|
1630
|
+
role: "agent",
|
|
1631
|
+
text: message
|
|
1632
|
+
});
|
|
1633
|
+
if (!repliedSession) {
|
|
1634
|
+
res.writeHead(404, { "Content-Type": "application/json" });
|
|
1635
|
+
res.end(JSON.stringify({ success: false, error: "Session not found" }));
|
|
1636
|
+
return;
|
|
1637
|
+
}
|
|
1638
|
+
}
|
|
1639
|
+
const session = annotationSessionStore.updateStatus(sessionId, "dismissed");
|
|
1640
|
+
if (!session) {
|
|
1641
|
+
res.writeHead(404, { "Content-Type": "application/json" });
|
|
1642
|
+
res.end(JSON.stringify({ success: false, error: "Session not found" }));
|
|
1643
|
+
return;
|
|
1644
|
+
}
|
|
1645
|
+
res.writeHead(200, { "Content-Type": "application/json" });
|
|
1646
|
+
res.end(JSON.stringify({ success: true, session }));
|
|
1647
|
+
} catch (e) {
|
|
1648
|
+
serverLogger4.error(`Error parsing session dismiss request:`, e);
|
|
1649
|
+
res.writeHead(400, { "Content-Type": "application/json" });
|
|
1650
|
+
res.end(JSON.stringify({ success: false, error: "Invalid JSON body" }));
|
|
1651
|
+
}
|
|
1652
|
+
return;
|
|
1653
|
+
}
|
|
1208
1654
|
if (pathname.startsWith(`${import_types2.INSPECTO_API_PATHS.AI_TICKET}/`) && req.method === "GET") {
|
|
1209
1655
|
const ticketId = pathname.substring(import_types2.INSPECTO_API_PATHS.AI_TICKET.length + 1);
|
|
1210
1656
|
const payloadStr = readTicket(ticketId);
|
|
@@ -1221,7 +1667,7 @@ async function handleRequest(url, req, res) {
|
|
|
1221
1667
|
res.end(JSON.stringify({ error: "not found" }));
|
|
1222
1668
|
}
|
|
1223
1669
|
async function dispatchToAi(req) {
|
|
1224
|
-
const { location, snippet, prompt
|
|
1670
|
+
const { location, snippet, prompt } = req;
|
|
1225
1671
|
const formattedPrompt = prompt ?? `Please help me with this code from \`${location.file}\` (line ${location.line}):
|
|
1226
1672
|
|
|
1227
1673
|
\`\`\`
|
|
@@ -1234,8 +1680,7 @@ ${snippet}
|
|
|
1234
1680
|
filePath: location.file,
|
|
1235
1681
|
line: location.line,
|
|
1236
1682
|
column: location.column,
|
|
1237
|
-
snippet
|
|
1238
|
-
...screenshotContext ? { screenshotContext } : {}
|
|
1683
|
+
snippet
|
|
1239
1684
|
});
|
|
1240
1685
|
}
|
|
1241
1686
|
function getBatchDispatchStatusCode(errorCode, success) {
|
|
@@ -1244,6 +1689,21 @@ function getBatchDispatchStatusCode(errorCode, success) {
|
|
|
1244
1689
|
if (errorCode === "FORBIDDEN_PATH") return 403;
|
|
1245
1690
|
return 500;
|
|
1246
1691
|
}
|
|
1692
|
+
function isAnnotationThreadRole(value) {
|
|
1693
|
+
return value === "user" || value === "agent" || value === "system";
|
|
1694
|
+
}
|
|
1695
|
+
function formatSessionSseEvent(event) {
|
|
1696
|
+
return `event: ${event.type}
|
|
1697
|
+
data: ${JSON.stringify(event)}
|
|
1698
|
+
|
|
1699
|
+
`;
|
|
1700
|
+
}
|
|
1701
|
+
function normalizeSessionClaimTimeout(value) {
|
|
1702
|
+
if (!value?.trim()) return 3e4;
|
|
1703
|
+
const parsed = Number.parseInt(value, 10);
|
|
1704
|
+
if (!Number.isFinite(parsed)) return 3e4;
|
|
1705
|
+
return Math.max(0, Math.min(parsed, 3e5));
|
|
1706
|
+
}
|
|
1247
1707
|
|
|
1248
1708
|
// src/index.ts
|
|
1249
1709
|
var import_unplugin = require("unplugin");
|
|
@@ -1934,7 +2394,9 @@ function transformRouter(options) {
|
|
|
1934
2394
|
return transformSvelte({
|
|
1935
2395
|
filePath,
|
|
1936
2396
|
source,
|
|
2397
|
+
projectRoot,
|
|
1937
2398
|
escapeTags: pluginOptions.escapeTags,
|
|
2399
|
+
pathType: pluginOptions.pathType,
|
|
1938
2400
|
attributeName: pluginOptions.attributeName
|
|
1939
2401
|
});
|
|
1940
2402
|
}
|
|
@@ -1943,6 +2405,7 @@ function transformRouter(options) {
|
|
|
1943
2405
|
filePath,
|
|
1944
2406
|
source,
|
|
1945
2407
|
escapeTags: pluginOptions.escapeTags,
|
|
2408
|
+
pathType: pluginOptions.pathType,
|
|
1946
2409
|
attributeName: pluginOptions.attributeName
|
|
1947
2410
|
});
|
|
1948
2411
|
}
|
|
@@ -1967,26 +2430,28 @@ var resolveClientModule = () => {
|
|
|
1967
2430
|
};
|
|
1968
2431
|
|
|
1969
2432
|
// src/injectors/webpack.ts
|
|
1970
|
-
function getWebpackHtmlScript(serverPort) {
|
|
2433
|
+
function getWebpackHtmlScript(serverPort, publicServerUrl) {
|
|
1971
2434
|
return `
|
|
1972
2435
|
window.__AI_INSPECTOR_PORT__ = ${serverPort};
|
|
1973
|
-
window.
|
|
1974
|
-
|
|
1975
|
-
window.InspectoClient
|
|
1976
|
-
|
|
1977
|
-
|
|
1978
|
-
|
|
1979
|
-
}
|
|
2436
|
+
window.__AI_INSPECTOR_SERVER_URL__ = '${publicServerUrl ?? `http://127.0.0.1:${serverPort}`}';
|
|
2437
|
+
window.addEventListener('load', () => {
|
|
2438
|
+
if (window.InspectoClient) {
|
|
2439
|
+
window.InspectoClient.mountInspector({
|
|
2440
|
+
serverUrl: window.__AI_INSPECTOR_SERVER_URL__,
|
|
2441
|
+
});
|
|
2442
|
+
}
|
|
2443
|
+
});
|
|
1980
2444
|
`;
|
|
1981
2445
|
}
|
|
1982
|
-
function getWebpackAssetScript(serverPort) {
|
|
2446
|
+
function getWebpackAssetScript(serverPort, publicServerUrl) {
|
|
1983
2447
|
return `
|
|
1984
2448
|
if (typeof window !== 'undefined') {
|
|
1985
2449
|
window.__AI_INSPECTOR_PORT__ = ${serverPort};
|
|
2450
|
+
window.__AI_INSPECTOR_SERVER_URL__ = '${publicServerUrl ?? `http://127.0.0.1:${serverPort}`}';
|
|
1986
2451
|
const _initInspecto = () => {
|
|
1987
2452
|
if (window.InspectoClient) {
|
|
1988
2453
|
window.InspectoClient.mountInspector({
|
|
1989
|
-
serverUrl:
|
|
2454
|
+
serverUrl: window.__AI_INSPECTOR_SERVER_URL__,
|
|
1990
2455
|
});
|
|
1991
2456
|
} else {
|
|
1992
2457
|
setTimeout(_initInspecto, 100);
|
|
@@ -2000,7 +2465,7 @@ if (typeof window !== 'undefined') {
|
|
|
2000
2465
|
}
|
|
2001
2466
|
`;
|
|
2002
2467
|
}
|
|
2003
|
-
function injectWebpack(compiler, serverPortFn, resolveClientModule2) {
|
|
2468
|
+
function injectWebpack(compiler, serverPortFn, publicServerUrlFn, resolveClientModule2) {
|
|
2004
2469
|
const inspectoClientPath = resolveClientModule2();
|
|
2005
2470
|
if (compiler.webpack && compiler.webpack.EntryPlugin) {
|
|
2006
2471
|
new compiler.webpack.EntryPlugin(compiler.context, inspectoClientPath, {
|
|
@@ -2015,11 +2480,12 @@ function injectWebpack(compiler, serverPortFn, resolveClientModule2) {
|
|
|
2015
2480
|
const hooks = HtmlWebpackPlugin.constructor.getHooks(compilation);
|
|
2016
2481
|
hooks.alterAssetTagGroups.tapPromise("inspecto-overlay", async (data) => {
|
|
2017
2482
|
const port = await serverPortFn();
|
|
2483
|
+
const publicServerUrl = publicServerUrlFn(port);
|
|
2018
2484
|
data.headTags.unshift({
|
|
2019
2485
|
tagName: "script",
|
|
2020
2486
|
voidTag: false,
|
|
2021
2487
|
meta: { plugin: "inspecto-overlay" },
|
|
2022
|
-
innerHTML: getWebpackHtmlScript(port)
|
|
2488
|
+
innerHTML: getWebpackHtmlScript(port, publicServerUrl)
|
|
2023
2489
|
});
|
|
2024
2490
|
return data;
|
|
2025
2491
|
});
|
|
@@ -2032,13 +2498,14 @@ function injectWebpack(compiler, serverPortFn, resolveClientModule2) {
|
|
|
2032
2498
|
},
|
|
2033
2499
|
async (assets) => {
|
|
2034
2500
|
const port = await serverPortFn();
|
|
2501
|
+
const publicServerUrl = publicServerUrlFn(port);
|
|
2035
2502
|
const mainAssetKey = Object.keys(assets).find(
|
|
2036
2503
|
(key) => key.endsWith(".js") && (key.includes("main") || key.includes("app") || key.includes("umi"))
|
|
2037
2504
|
);
|
|
2038
2505
|
if (!mainAssetKey) return;
|
|
2039
2506
|
const originalSource = assets[mainAssetKey].source();
|
|
2040
2507
|
assets[mainAssetKey] = new compiler.webpack.sources.RawSource(
|
|
2041
|
-
getWebpackAssetScript(port) + "\n" + originalSource
|
|
2508
|
+
getWebpackAssetScript(port, publicServerUrl) + "\n" + originalSource
|
|
2042
2509
|
);
|
|
2043
2510
|
}
|
|
2044
2511
|
);
|
|
@@ -2072,12 +2539,13 @@ function injectRspack(compiler, serverPortFn, resolveClientModule2) {
|
|
|
2072
2539
|
}
|
|
2073
2540
|
|
|
2074
2541
|
// src/injectors/vite.ts
|
|
2075
|
-
function getViteVirtualModuleScript(serverPort) {
|
|
2542
|
+
function getViteVirtualModuleScript(serverPort, publicServerUrl) {
|
|
2076
2543
|
return `
|
|
2077
2544
|
import { mountInspector } from '@inspecto-dev/core';
|
|
2078
2545
|
window.__AI_INSPECTOR_PORT__ = ${serverPort};
|
|
2546
|
+
window.__AI_INSPECTOR_SERVER_URL__ = '${publicServerUrl ?? `http://127.0.0.1:${serverPort}`}';
|
|
2079
2547
|
mountInspector({
|
|
2080
|
-
serverUrl:
|
|
2548
|
+
serverUrl: window.__AI_INSPECTOR_SERVER_URL__,
|
|
2081
2549
|
});
|
|
2082
2550
|
`;
|
|
2083
2551
|
}
|
|
@@ -2110,6 +2578,11 @@ var InspectoPlugin = (0, import_unplugin.createUnplugin)((userOptions = {}) => {
|
|
|
2110
2578
|
}
|
|
2111
2579
|
return serverPort;
|
|
2112
2580
|
};
|
|
2581
|
+
const getPublicServerUrl = (port) => resolvePublicServerUrl({
|
|
2582
|
+
cwd: serverState.cwd || process.cwd(),
|
|
2583
|
+
configRoot: serverState.configRoot || projectRoot,
|
|
2584
|
+
port
|
|
2585
|
+
});
|
|
2113
2586
|
return {
|
|
2114
2587
|
name: "inspecto-overlay",
|
|
2115
2588
|
enforce: "pre",
|
|
@@ -2122,7 +2595,7 @@ var InspectoPlugin = (0, import_unplugin.createUnplugin)((userOptions = {}) => {
|
|
|
2122
2595
|
},
|
|
2123
2596
|
webpack: (compiler) => {
|
|
2124
2597
|
if (isProduction) return;
|
|
2125
|
-
injectWebpack(compiler, ensureServer, resolveClientModule);
|
|
2598
|
+
injectWebpack(compiler, ensureServer, getPublicServerUrl, resolveClientModule);
|
|
2126
2599
|
},
|
|
2127
2600
|
rspack: (compiler) => {
|
|
2128
2601
|
if (isProduction) return;
|
|
@@ -2148,7 +2621,10 @@ var InspectoPlugin = (0, import_unplugin.createUnplugin)((userOptions = {}) => {
|
|
|
2148
2621
|
},
|
|
2149
2622
|
load(id) {
|
|
2150
2623
|
if (id === VITE_VIRTUAL_MODULE_ID) {
|
|
2151
|
-
return getViteVirtualModuleScript(
|
|
2624
|
+
return getViteVirtualModuleScript(
|
|
2625
|
+
serverPort ?? DEFAULT_PORT,
|
|
2626
|
+
getPublicServerUrl(serverPort ?? DEFAULT_PORT)
|
|
2627
|
+
);
|
|
2152
2628
|
}
|
|
2153
2629
|
return null;
|
|
2154
2630
|
},
|
|
@@ -2206,10 +2682,10 @@ var rollupPlugin = InspectoPlugin.rollup;
|
|
|
2206
2682
|
var esbuildPlugin = InspectoPlugin.esbuild;
|
|
2207
2683
|
|
|
2208
2684
|
// src/astro.ts
|
|
2209
|
-
function getAstroInjectedScript(serverPort) {
|
|
2685
|
+
function getAstroInjectedScript(serverPort, publicServerUrl) {
|
|
2210
2686
|
return `
|
|
2211
2687
|
import { mountInspector } from '@inspecto-dev/core';
|
|
2212
|
-
window.__AI_INSPECTOR_SERVER_URL__ = 'http://127.0.0.1:${serverPort}';
|
|
2688
|
+
window.__AI_INSPECTOR_SERVER_URL__ = '${publicServerUrl ?? `http://127.0.0.1:${serverPort}`}';
|
|
2213
2689
|
mountInspector({
|
|
2214
2690
|
serverUrl: window.__AI_INSPECTOR_SERVER_URL__,
|
|
2215
2691
|
});
|
|
@@ -2229,7 +2705,17 @@ function astroIntegration(options) {
|
|
|
2229
2705
|
return;
|
|
2230
2706
|
}
|
|
2231
2707
|
const serverPort = await startServer();
|
|
2232
|
-
injectScript(
|
|
2708
|
+
injectScript(
|
|
2709
|
+
"page",
|
|
2710
|
+
getAstroInjectedScript(
|
|
2711
|
+
serverPort,
|
|
2712
|
+
resolvePublicServerUrl({
|
|
2713
|
+
cwd: serverState.cwd || process.cwd(),
|
|
2714
|
+
configRoot: serverState.configRoot || process.cwd(),
|
|
2715
|
+
port: serverPort
|
|
2716
|
+
})
|
|
2717
|
+
)
|
|
2718
|
+
);
|
|
2233
2719
|
}
|
|
2234
2720
|
}
|
|
2235
2721
|
};
|