@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
|
@@ -5,7 +5,7 @@ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require
|
|
|
5
5
|
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
6
6
|
});
|
|
7
7
|
|
|
8
|
-
// ../../node_modules/.pnpm/tsup@8.5.1_jiti@2.
|
|
8
|
+
// ../../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/esm_shims.js
|
|
9
9
|
import path from "path";
|
|
10
10
|
import { fileURLToPath } from "url";
|
|
11
11
|
var getFilename = () => fileURLToPath(import.meta.url);
|
|
@@ -13,16 +13,17 @@ var getDirname = () => path.dirname(getFilename());
|
|
|
13
13
|
var __dirname = /* @__PURE__ */ getDirname();
|
|
14
14
|
|
|
15
15
|
// src/injectors/webpack.ts
|
|
16
|
-
function getWebpackHtmlScript(serverPort) {
|
|
16
|
+
function getWebpackHtmlScript(serverPort, publicServerUrl) {
|
|
17
17
|
return `
|
|
18
18
|
window.__AI_INSPECTOR_PORT__ = ${serverPort};
|
|
19
|
-
window.
|
|
20
|
-
|
|
21
|
-
window.InspectoClient
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
}
|
|
19
|
+
window.__AI_INSPECTOR_SERVER_URL__ = '${publicServerUrl ?? `http://127.0.0.1:${serverPort}`}';
|
|
20
|
+
window.addEventListener('load', () => {
|
|
21
|
+
if (window.InspectoClient) {
|
|
22
|
+
window.InspectoClient.mountInspector({
|
|
23
|
+
serverUrl: window.__AI_INSPECTOR_SERVER_URL__,
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
});
|
|
26
27
|
`;
|
|
27
28
|
}
|
|
28
29
|
|
|
@@ -544,7 +545,6 @@ function dispatchPromptThroughIde(runtime, payload) {
|
|
|
544
545
|
line: payload.line,
|
|
545
546
|
column: payload.column,
|
|
546
547
|
snippet: payload.snippet,
|
|
547
|
-
...payload.screenshotContext ? { screenshotContext: payload.screenshotContext } : {},
|
|
548
548
|
overrides: runtime.overrides,
|
|
549
549
|
autoSend: runtime.autoSend
|
|
550
550
|
});
|
|
@@ -678,6 +678,188 @@ function assertPathWithinIdeOpenScope(file, projectRoot) {
|
|
|
678
678
|
}
|
|
679
679
|
}
|
|
680
680
|
|
|
681
|
+
// src/server/session-store.ts
|
|
682
|
+
var DEFAULT_STATUS = "pending";
|
|
683
|
+
function createAnnotationSessionStore(options = {}) {
|
|
684
|
+
const sessions = /* @__PURE__ */ new Map();
|
|
685
|
+
const listeners = /* @__PURE__ */ new Set();
|
|
686
|
+
const now = options.now ?? (() => Date.now());
|
|
687
|
+
const createId = options.createId ?? createRandomId;
|
|
688
|
+
function findNewestMatchingSession(statuses) {
|
|
689
|
+
return [...sessions.values()].filter((session) => statuses ? statuses.has(session.status) : true).sort((left, right) => right.updatedAt - left.updatedAt)[0] ?? null;
|
|
690
|
+
}
|
|
691
|
+
function updateSessionStatus(id, status) {
|
|
692
|
+
const session = sessions.get(id);
|
|
693
|
+
if (!session) return null;
|
|
694
|
+
const timestamp = now();
|
|
695
|
+
session.status = status;
|
|
696
|
+
session.updatedAt = timestamp;
|
|
697
|
+
if (status === "acknowledged") {
|
|
698
|
+
session.acknowledgedAt = timestamp;
|
|
699
|
+
}
|
|
700
|
+
if (status === "resolved") {
|
|
701
|
+
session.resolvedAt = timestamp;
|
|
702
|
+
}
|
|
703
|
+
emit({ type: "session-status-updated", session });
|
|
704
|
+
return cloneSession(session);
|
|
705
|
+
}
|
|
706
|
+
function claimSession(id, statuses) {
|
|
707
|
+
const session = sessions.get(id);
|
|
708
|
+
if (!session || statuses && !statuses.has(session.status)) return null;
|
|
709
|
+
if (session.status === "acknowledged") return cloneSession(session);
|
|
710
|
+
return updateSessionStatus(id, "acknowledged");
|
|
711
|
+
}
|
|
712
|
+
function emit(event) {
|
|
713
|
+
const snapshot = cloneSession(event.session);
|
|
714
|
+
for (const listener of listeners) {
|
|
715
|
+
listener({ type: event.type, session: snapshot });
|
|
716
|
+
}
|
|
717
|
+
}
|
|
718
|
+
const store = {
|
|
719
|
+
createSession(input) {
|
|
720
|
+
const timestamp = now();
|
|
721
|
+
const session = {
|
|
722
|
+
id: createId(),
|
|
723
|
+
instruction: input.instruction?.trim() ?? "",
|
|
724
|
+
annotations: cloneArray(input.annotations),
|
|
725
|
+
...input.deliveryMode ? { deliveryMode: input.deliveryMode } : {},
|
|
726
|
+
status: DEFAULT_STATUS,
|
|
727
|
+
messages: cloneArray(input.messages ?? []),
|
|
728
|
+
createdAt: timestamp,
|
|
729
|
+
updatedAt: timestamp,
|
|
730
|
+
...input.runtimeContext ? { runtimeContext: cloneValue(input.runtimeContext) } : {},
|
|
731
|
+
...input.cssContextPrompt?.trim() ? { cssContextPrompt: input.cssContextPrompt.trim() } : {},
|
|
732
|
+
...input.pageUrl ? { pageUrl: input.pageUrl } : {},
|
|
733
|
+
...input.route ? { route: input.route } : {}
|
|
734
|
+
};
|
|
735
|
+
sessions.set(session.id, session);
|
|
736
|
+
emit({ type: "session-created", session });
|
|
737
|
+
return cloneSession(session);
|
|
738
|
+
},
|
|
739
|
+
getSession(id) {
|
|
740
|
+
const session = sessions.get(id);
|
|
741
|
+
return session ? cloneSession(session) : null;
|
|
742
|
+
},
|
|
743
|
+
listSessions(options2 = {}) {
|
|
744
|
+
const statuses = normalizeStatuses(options2.status);
|
|
745
|
+
return [...sessions.values()].filter((session) => statuses ? statuses.has(session.status) : true).sort((left, right) => right.updatedAt - left.updatedAt).map((session) => cloneSession(session));
|
|
746
|
+
},
|
|
747
|
+
async claimNextSession(options2 = {}) {
|
|
748
|
+
const statuses = normalizeStatuses(DEFAULT_STATUS);
|
|
749
|
+
const existingSession = findNewestMatchingSession(statuses);
|
|
750
|
+
if (existingSession) {
|
|
751
|
+
return {
|
|
752
|
+
session: claimSession(existingSession.id, statuses),
|
|
753
|
+
timedOut: false,
|
|
754
|
+
matchedExisting: true
|
|
755
|
+
};
|
|
756
|
+
}
|
|
757
|
+
const timeoutMs = normalizeTimeoutMs(options2.timeoutMs);
|
|
758
|
+
if (timeoutMs === 0) {
|
|
759
|
+
return {
|
|
760
|
+
session: null,
|
|
761
|
+
timedOut: true,
|
|
762
|
+
matchedExisting: false
|
|
763
|
+
};
|
|
764
|
+
}
|
|
765
|
+
return await new Promise((resolve2) => {
|
|
766
|
+
let settled = false;
|
|
767
|
+
let timeout = null;
|
|
768
|
+
const finish = (result) => {
|
|
769
|
+
if (settled) return;
|
|
770
|
+
settled = true;
|
|
771
|
+
unsubscribe();
|
|
772
|
+
if (timeout) {
|
|
773
|
+
clearTimeout(timeout);
|
|
774
|
+
}
|
|
775
|
+
resolve2(result);
|
|
776
|
+
};
|
|
777
|
+
const unsubscribe = this.subscribe((event) => {
|
|
778
|
+
const session = claimSession(event.session.id, statuses);
|
|
779
|
+
if (!session) return;
|
|
780
|
+
finish({
|
|
781
|
+
session,
|
|
782
|
+
timedOut: false,
|
|
783
|
+
matchedExisting: false,
|
|
784
|
+
event: event.type
|
|
785
|
+
});
|
|
786
|
+
});
|
|
787
|
+
if (timeoutMs !== null) {
|
|
788
|
+
timeout = setTimeout(() => {
|
|
789
|
+
finish({
|
|
790
|
+
session: null,
|
|
791
|
+
timedOut: true,
|
|
792
|
+
matchedExisting: false
|
|
793
|
+
});
|
|
794
|
+
}, timeoutMs);
|
|
795
|
+
}
|
|
796
|
+
});
|
|
797
|
+
},
|
|
798
|
+
appendMessage(id, input) {
|
|
799
|
+
const session = sessions.get(id);
|
|
800
|
+
if (!session) return null;
|
|
801
|
+
const timestamp = now();
|
|
802
|
+
session.messages.push({
|
|
803
|
+
id: createId(),
|
|
804
|
+
role: input.role,
|
|
805
|
+
text: input.text,
|
|
806
|
+
createdAt: timestamp
|
|
807
|
+
});
|
|
808
|
+
session.updatedAt = timestamp;
|
|
809
|
+
if (input.role === "agent" && isPendingLikeStatus(session.status)) {
|
|
810
|
+
session.status = "in_progress";
|
|
811
|
+
}
|
|
812
|
+
emit({ type: "session-message-appended", session });
|
|
813
|
+
return cloneSession(session);
|
|
814
|
+
},
|
|
815
|
+
updateStatus(id, status) {
|
|
816
|
+
return updateSessionStatus(id, status);
|
|
817
|
+
},
|
|
818
|
+
subscribe(listener) {
|
|
819
|
+
listeners.add(listener);
|
|
820
|
+
return () => {
|
|
821
|
+
listeners.delete(listener);
|
|
822
|
+
};
|
|
823
|
+
},
|
|
824
|
+
clear() {
|
|
825
|
+
sessions.clear();
|
|
826
|
+
listeners.clear();
|
|
827
|
+
}
|
|
828
|
+
};
|
|
829
|
+
return store;
|
|
830
|
+
}
|
|
831
|
+
var annotationSessionStore = createAnnotationSessionStore();
|
|
832
|
+
function normalizeStatuses(status) {
|
|
833
|
+
if (!status) return null;
|
|
834
|
+
return new Set(Array.isArray(status) ? status : [status]);
|
|
835
|
+
}
|
|
836
|
+
function normalizeTimeoutMs(value) {
|
|
837
|
+
if (value === void 0) return null;
|
|
838
|
+
if (!Number.isFinite(value)) return 0;
|
|
839
|
+
return Math.max(0, Math.floor(value));
|
|
840
|
+
}
|
|
841
|
+
function isPendingLikeStatus(status) {
|
|
842
|
+
return status === "pending" || status === "acknowledged";
|
|
843
|
+
}
|
|
844
|
+
function hasAgentReply(session) {
|
|
845
|
+
return session.messages.some((message) => message.role === "agent" && Boolean(message.text?.trim()));
|
|
846
|
+
}
|
|
847
|
+
function createRandomId() {
|
|
848
|
+
return `annotation-session-${Math.random().toString(36).slice(2, 10)}`;
|
|
849
|
+
}
|
|
850
|
+
function cloneSession(session) {
|
|
851
|
+
return cloneValue(session);
|
|
852
|
+
}
|
|
853
|
+
function cloneArray(value) {
|
|
854
|
+
return cloneValue(value);
|
|
855
|
+
}
|
|
856
|
+
function cloneValue(value) {
|
|
857
|
+
if (typeof structuredClone === "function") {
|
|
858
|
+
return structuredClone(value);
|
|
859
|
+
}
|
|
860
|
+
return JSON.parse(JSON.stringify(value));
|
|
861
|
+
}
|
|
862
|
+
|
|
681
863
|
// src/server/annotation-dispatch.ts
|
|
682
864
|
var AnnotationDispatchError = class extends Error {
|
|
683
865
|
constructor(message, errorCode) {
|
|
@@ -686,20 +868,30 @@ var AnnotationDispatchError = class extends Error {
|
|
|
686
868
|
this.errorCode = errorCode;
|
|
687
869
|
}
|
|
688
870
|
};
|
|
689
|
-
async function dispatchAnnotationsToAi(req, state) {
|
|
871
|
+
async function dispatchAnnotationsToAi(req, state, store = annotationSessionStore) {
|
|
690
872
|
try {
|
|
691
873
|
validateAnnotationDispatchRequest(req, state);
|
|
692
874
|
const batch = normalizeAnnotationBatch(req);
|
|
693
875
|
const prompt = buildAnnotationBatchPrompt(batch);
|
|
876
|
+
const deliveryMode = normalizeDeliveryMode(req.deliveryMode);
|
|
877
|
+
const session = store.createSession({
|
|
878
|
+
instruction: batch.instruction,
|
|
879
|
+
annotations: toSessionAnnotations(batch.annotations),
|
|
880
|
+
deliveryMode,
|
|
881
|
+
...batch.runtimeContext ? { runtimeContext: batch.runtimeContext } : {},
|
|
882
|
+
...batch.cssContextPrompt ? { cssContextPrompt: batch.cssContextPrompt } : {}
|
|
883
|
+
});
|
|
694
884
|
const representativeTarget = batch.annotations[0]?.targets[0];
|
|
695
|
-
const
|
|
696
|
-
return dispatchPromptThroughIde(runtime, {
|
|
885
|
+
const dispatchResult = deliveryMode === "ide" ? dispatchPromptThroughIde(resolvePromptDispatchRuntime(state), {
|
|
697
886
|
prompt,
|
|
698
887
|
...representativeTarget?.file ? { filePath: representativeTarget.file } : {},
|
|
699
888
|
...representativeTarget?.line ? { line: representativeTarget.line } : {},
|
|
700
|
-
...representativeTarget?.column ? { column: representativeTarget.column } : {}
|
|
701
|
-
|
|
702
|
-
|
|
889
|
+
...representativeTarget?.column ? { column: representativeTarget.column } : {}
|
|
890
|
+
}) : { success: true };
|
|
891
|
+
return {
|
|
892
|
+
...dispatchResult,
|
|
893
|
+
session: toSessionSummary(session)
|
|
894
|
+
};
|
|
703
895
|
} catch (error) {
|
|
704
896
|
return {
|
|
705
897
|
success: false,
|
|
@@ -708,6 +900,41 @@ async function dispatchAnnotationsToAi(req, state) {
|
|
|
708
900
|
};
|
|
709
901
|
}
|
|
710
902
|
}
|
|
903
|
+
function normalizeDeliveryMode(input) {
|
|
904
|
+
return input === "agent" ? "agent" : "ide";
|
|
905
|
+
}
|
|
906
|
+
function toSessionAnnotations(annotations) {
|
|
907
|
+
return annotations.map((annotation) => ({
|
|
908
|
+
id: `annotation-${annotation.index}`,
|
|
909
|
+
note: annotation.note,
|
|
910
|
+
intent: annotation.intent,
|
|
911
|
+
targets: annotation.targets.map((target, targetIndex) => ({
|
|
912
|
+
id: `annotation-${annotation.index}-target-${targetIndex + 1}`,
|
|
913
|
+
label: target.label ?? "Unknown target",
|
|
914
|
+
location: {
|
|
915
|
+
file: target.file,
|
|
916
|
+
line: target.line,
|
|
917
|
+
column: target.column
|
|
918
|
+
},
|
|
919
|
+
...target.selector ? { selector: target.selector } : {},
|
|
920
|
+
...target.snippet ? { snippet: target.snippet } : {},
|
|
921
|
+
rect: {
|
|
922
|
+
x: 0,
|
|
923
|
+
y: 0,
|
|
924
|
+
width: 0,
|
|
925
|
+
height: 0
|
|
926
|
+
}
|
|
927
|
+
}))
|
|
928
|
+
}));
|
|
929
|
+
}
|
|
930
|
+
function toSessionSummary(session) {
|
|
931
|
+
return {
|
|
932
|
+
id: session.id,
|
|
933
|
+
status: session.status,
|
|
934
|
+
createdAt: session.createdAt,
|
|
935
|
+
updatedAt: session.updatedAt
|
|
936
|
+
};
|
|
937
|
+
}
|
|
711
938
|
function validateAnnotationDispatchRequest(req, state) {
|
|
712
939
|
if (!req.annotations.length) {
|
|
713
940
|
throw new AnnotationDispatchError("At least one annotation is required.", "INVALID_REQUEST");
|
|
@@ -728,9 +955,7 @@ function validateAnnotationDispatchRequest(req, state) {
|
|
|
728
955
|
function normalizeAnnotationBatch(req) {
|
|
729
956
|
return {
|
|
730
957
|
instruction: req.instruction?.trim() ?? "",
|
|
731
|
-
responseMode: req.responseMode ?? "unified",
|
|
732
958
|
...req.runtimeContext ? { runtimeContext: req.runtimeContext } : {},
|
|
733
|
-
...req.screenshotContext ? { screenshotContext: req.screenshotContext } : {},
|
|
734
959
|
...req.cssContextPrompt?.trim() ? { cssContextPrompt: req.cssContextPrompt.trim() } : {},
|
|
735
960
|
annotations: req.annotations.map((annotation, index) => ({
|
|
736
961
|
index: index + 1,
|
|
@@ -752,12 +977,9 @@ function buildAnnotationBatchPrompt(batch) {
|
|
|
752
977
|
const prompt = batch.instruction ? `${batch.instruction}
|
|
753
978
|
|
|
754
979
|
${body}` : body;
|
|
755
|
-
return
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
batch.cssContextPrompt
|
|
759
|
-
),
|
|
760
|
-
batch.screenshotContext
|
|
980
|
+
return appendCssContextSection(
|
|
981
|
+
appendRuntimeContextSection(prompt, batch.runtimeContext),
|
|
982
|
+
batch.cssContextPrompt
|
|
761
983
|
);
|
|
762
984
|
}
|
|
763
985
|
function appendCssContextSection(prompt, cssContextPrompt) {
|
|
@@ -784,20 +1006,6 @@ function buildSelectedElementsPrompt(annotations) {
|
|
|
784
1006
|
}
|
|
785
1007
|
return lines.join("\n");
|
|
786
1008
|
}
|
|
787
|
-
function appendScreenshotContextSection(prompt, screenshotContext) {
|
|
788
|
-
if (!screenshotContext || !screenshotContext.imageDataUrl && !screenshotContext.imageAssetId) {
|
|
789
|
-
return prompt;
|
|
790
|
-
}
|
|
791
|
-
const lines = [
|
|
792
|
-
"Visual screenshot context attached:",
|
|
793
|
-
`- capturedAt=${screenshotContext.capturedAt}`,
|
|
794
|
-
`- mimeType=${screenshotContext.mimeType}`,
|
|
795
|
-
...screenshotContext.imageAssetId ? [`- imageAssetId=${screenshotContext.imageAssetId}`] : []
|
|
796
|
-
];
|
|
797
|
-
return `${prompt}
|
|
798
|
-
|
|
799
|
-
${lines.join("\n")}`;
|
|
800
|
-
}
|
|
801
1009
|
function appendRuntimeContextSection(prompt, runtimeContext) {
|
|
802
1010
|
if (!runtimeContext?.records.length) {
|
|
803
1011
|
return prompt;
|
|
@@ -845,7 +1053,7 @@ async function buildClientConfig(serverState2) {
|
|
|
845
1053
|
...info,
|
|
846
1054
|
prompts: resolveIntents(promptsConfig),
|
|
847
1055
|
hotKeys: userConfig["inspector.hotKey"] ?? "alt",
|
|
848
|
-
|
|
1056
|
+
annotateDeliveryMode: userConfig["annotate.deliveryMode"] ?? "both",
|
|
849
1057
|
includeSnippet: userConfig["prompt.includeSnippet"] ?? false,
|
|
850
1058
|
runtimeContext: {
|
|
851
1059
|
enabled: true,
|
|
@@ -853,10 +1061,6 @@ async function buildClientConfig(serverState2) {
|
|
|
853
1061
|
maxRuntimeErrors: 3,
|
|
854
1062
|
maxFailedRequests: 2
|
|
855
1063
|
},
|
|
856
|
-
screenshotContext: {
|
|
857
|
-
enabled: false
|
|
858
|
-
},
|
|
859
|
-
annotationResponseMode: userConfig["prompt.annotationResponseMode"] ?? "unified",
|
|
860
1064
|
autoSend: userConfig["prompt.autoSend"] ?? false
|
|
861
1065
|
};
|
|
862
1066
|
}
|
|
@@ -901,7 +1105,7 @@ function handleOpenFileRequest(body, serverState2) {
|
|
|
901
1105
|
else if (rawEditorHint === "vscodium") editorHint = "codium";
|
|
902
1106
|
else if (rawEditorHint === "trae-cn" || rawEditorHint === "trae") editorHint = "trae";
|
|
903
1107
|
serverLogger2.debug(
|
|
904
|
-
`
|
|
1108
|
+
`SOURCE_OPEN: activeIde=${activeIde}, activeIdeScheme=${activeIdeScheme}, configuredIde=${configuredIde} -> rawEditorHint=${rawEditorHint}, finalEditorHint=${editorHint}`
|
|
905
1109
|
);
|
|
906
1110
|
if (VSCODE_FAMILY_SCHEMES.includes(rawEditorHint)) {
|
|
907
1111
|
let normalizedPath = absolutePath.replace(/\\/g, "/");
|
|
@@ -910,7 +1114,7 @@ function handleOpenFileRequest(body, serverState2) {
|
|
|
910
1114
|
}
|
|
911
1115
|
const encodedPath = encodeURI(normalizedPath);
|
|
912
1116
|
const uri = `${rawEditorHint}://file${encodedPath}:${body.line}:${body.column}`;
|
|
913
|
-
serverLogger2.debug(`
|
|
1117
|
+
serverLogger2.debug(`SOURCE_OPEN: Bypassing launchIDE, using URI scheme directly: ${uri}`);
|
|
914
1118
|
try {
|
|
915
1119
|
if (process.platform === "darwin") {
|
|
916
1120
|
execFileSync2("open", [uri]);
|
|
@@ -920,7 +1124,7 @@ function handleOpenFileRequest(body, serverState2) {
|
|
|
920
1124
|
execFileSync2("xdg-open", [uri]);
|
|
921
1125
|
}
|
|
922
1126
|
} catch (e) {
|
|
923
|
-
serverLogger2.error(`Failed to launch URI for
|
|
1127
|
+
serverLogger2.error(`Failed to launch URI for SOURCE_OPEN (${uri}):`, e);
|
|
924
1128
|
launchIDE2({
|
|
925
1129
|
file: absolutePath,
|
|
926
1130
|
line: body.line,
|
|
@@ -975,8 +1179,18 @@ function resolveProjectRoot() {
|
|
|
975
1179
|
return gitRoot;
|
|
976
1180
|
}
|
|
977
1181
|
|
|
1182
|
+
// src/server/server-url.ts
|
|
1183
|
+
function resolveServerHost(cwd, configRoot) {
|
|
1184
|
+
const userConfig = loadUserConfigSync(false, cwd, configRoot);
|
|
1185
|
+
const configuredHost = userConfig["server.host"]?.trim();
|
|
1186
|
+
if (configuredHost) return configuredHost;
|
|
1187
|
+
if (process.env["VITEST"]) return "127.0.0.1";
|
|
1188
|
+
return "127.0.0.1";
|
|
1189
|
+
}
|
|
1190
|
+
|
|
978
1191
|
// src/server/index.ts
|
|
979
1192
|
var serverLogger4 = createLogger("inspecto:server", { logLevel: getGlobalLogLevel() });
|
|
1193
|
+
var PORT_FILE_NAME = "inspecto.port.json";
|
|
980
1194
|
var serverState = {
|
|
981
1195
|
port: null,
|
|
982
1196
|
running: false,
|
|
@@ -985,6 +1199,42 @@ var serverState = {
|
|
|
985
1199
|
cwd: process.cwd()
|
|
986
1200
|
};
|
|
987
1201
|
var serverInstance = null;
|
|
1202
|
+
function getPortFilePath() {
|
|
1203
|
+
return path6.join(os2.tmpdir(), PORT_FILE_NAME);
|
|
1204
|
+
}
|
|
1205
|
+
function getProjectRootHash() {
|
|
1206
|
+
if (!serverState.projectRoot) return null;
|
|
1207
|
+
return crypto2.createHash("md5").update(serverState.projectRoot).digest("hex");
|
|
1208
|
+
}
|
|
1209
|
+
function readPortData(portFile) {
|
|
1210
|
+
if (!fs5.existsSync(portFile)) return {};
|
|
1211
|
+
try {
|
|
1212
|
+
return JSON.parse(fs5.readFileSync(portFile, "utf-8"));
|
|
1213
|
+
} catch {
|
|
1214
|
+
return {};
|
|
1215
|
+
}
|
|
1216
|
+
}
|
|
1217
|
+
function writeProjectPort(port) {
|
|
1218
|
+
const rootHash = getProjectRootHash();
|
|
1219
|
+
if (!rootHash) return;
|
|
1220
|
+
const portFile = getPortFilePath();
|
|
1221
|
+
const portData = readPortData(portFile);
|
|
1222
|
+
portData[rootHash] = port;
|
|
1223
|
+
fs5.writeFileSync(portFile, JSON.stringify(portData, null, 2), "utf-8");
|
|
1224
|
+
}
|
|
1225
|
+
function removeProjectPort() {
|
|
1226
|
+
const rootHash = getProjectRootHash();
|
|
1227
|
+
if (!rootHash) return;
|
|
1228
|
+
const portFile = getPortFilePath();
|
|
1229
|
+
if (!fs5.existsSync(portFile)) return;
|
|
1230
|
+
const portData = readPortData(portFile);
|
|
1231
|
+
delete portData[rootHash];
|
|
1232
|
+
if (Object.keys(portData).length === 0) {
|
|
1233
|
+
fs5.unlinkSync(portFile);
|
|
1234
|
+
} else {
|
|
1235
|
+
fs5.writeFileSync(portFile, JSON.stringify(portData, null, 2), "utf-8");
|
|
1236
|
+
}
|
|
1237
|
+
}
|
|
988
1238
|
async function startServer() {
|
|
989
1239
|
if (serverState.running && serverState.port !== null) {
|
|
990
1240
|
return serverState.port;
|
|
@@ -992,6 +1242,7 @@ async function startServer() {
|
|
|
992
1242
|
serverState.projectRoot = resolveProjectRoot();
|
|
993
1243
|
serverState.configRoot = serverState.projectRoot;
|
|
994
1244
|
serverState.cwd = process.cwd();
|
|
1245
|
+
const serverHost = resolveServerHost(serverState.cwd, serverState.configRoot);
|
|
995
1246
|
portfinder.basePort = 5678;
|
|
996
1247
|
const port = await portfinder.getPortPromise();
|
|
997
1248
|
watchConfig(
|
|
@@ -1018,7 +1269,7 @@ async function startServer() {
|
|
|
1018
1269
|
});
|
|
1019
1270
|
});
|
|
1020
1271
|
await new Promise((resolve2, reject) => {
|
|
1021
|
-
serverInstance.listen(port,
|
|
1272
|
+
serverInstance.listen(port, serverHost, () => {
|
|
1022
1273
|
serverInstance.unref();
|
|
1023
1274
|
resolve2();
|
|
1024
1275
|
});
|
|
@@ -1029,37 +1280,18 @@ async function startServer() {
|
|
|
1029
1280
|
});
|
|
1030
1281
|
serverState.port = port;
|
|
1031
1282
|
serverState.running = true;
|
|
1032
|
-
const portFile = path6.join(os2.tmpdir(), "inspecto.port.json");
|
|
1033
1283
|
try {
|
|
1034
|
-
|
|
1035
|
-
if (fs5.existsSync(portFile)) {
|
|
1036
|
-
try {
|
|
1037
|
-
portData = JSON.parse(fs5.readFileSync(portFile, "utf-8"));
|
|
1038
|
-
} catch (_e) {
|
|
1039
|
-
}
|
|
1040
|
-
}
|
|
1041
|
-
const rootHash = crypto2.createHash("md5").update(serverState.projectRoot).digest("hex");
|
|
1042
|
-
portData[rootHash] = port;
|
|
1043
|
-
fs5.writeFileSync(portFile, JSON.stringify(portData, null, 2), "utf-8");
|
|
1284
|
+
writeProjectPort(port);
|
|
1044
1285
|
} catch (_e) {
|
|
1045
1286
|
serverLogger4.warn("Failed to write port file:", _e);
|
|
1046
1287
|
}
|
|
1047
1288
|
process.once("exit", () => {
|
|
1048
1289
|
try {
|
|
1049
|
-
|
|
1050
|
-
const portData = JSON.parse(fs5.readFileSync(portFile, "utf-8"));
|
|
1051
|
-
const rootHash = crypto2.createHash("md5").update(serverState.projectRoot).digest("hex");
|
|
1052
|
-
delete portData[rootHash];
|
|
1053
|
-
if (Object.keys(portData).length === 0) {
|
|
1054
|
-
fs5.unlinkSync(portFile);
|
|
1055
|
-
} else {
|
|
1056
|
-
fs5.writeFileSync(portFile, JSON.stringify(portData, null, 2), "utf-8");
|
|
1057
|
-
}
|
|
1058
|
-
}
|
|
1290
|
+
removeProjectPort();
|
|
1059
1291
|
} catch {
|
|
1060
1292
|
}
|
|
1061
1293
|
});
|
|
1062
|
-
serverLogger4.info(`server running at http
|
|
1294
|
+
serverLogger4.info(`server running at http://${serverHost}:${port}`);
|
|
1063
1295
|
return port;
|
|
1064
1296
|
}
|
|
1065
1297
|
async function readBody(req) {
|
|
@@ -1111,7 +1343,7 @@ async function handleRequest(url, req, res) {
|
|
|
1111
1343
|
}
|
|
1112
1344
|
return;
|
|
1113
1345
|
}
|
|
1114
|
-
if (pathname === INSPECTO_API_PATHS.IDE_OPEN && req.method === "POST") {
|
|
1346
|
+
if ((pathname === INSPECTO_API_PATHS.SOURCE_OPEN || pathname === INSPECTO_API_PATHS.IDE_OPEN) && req.method === "POST") {
|
|
1115
1347
|
let body;
|
|
1116
1348
|
try {
|
|
1117
1349
|
body = JSON.parse(await readBody(req));
|
|
@@ -1124,7 +1356,7 @@ async function handleRequest(url, req, res) {
|
|
|
1124
1356
|
handleOpenFileRequest(body, serverState);
|
|
1125
1357
|
} catch (err) {
|
|
1126
1358
|
serverLogger4.warn(
|
|
1127
|
-
`Security: Blocked path traversal attempt in
|
|
1359
|
+
`Security: Blocked path traversal attempt in SOURCE_OPEN: ${body.file}. Reason: ${err.message}`
|
|
1128
1360
|
);
|
|
1129
1361
|
res.writeHead(403, { "Content-Type": "application/json" });
|
|
1130
1362
|
res.end(JSON.stringify({ error: "Access denied: File is outside of project workspace" }));
|
|
@@ -1198,6 +1430,212 @@ async function handleRequest(url, req, res) {
|
|
|
1198
1430
|
}
|
|
1199
1431
|
return;
|
|
1200
1432
|
}
|
|
1433
|
+
if (pathname === INSPECTO_API_PATHS.SESSION_CLAIM_NEXT && req.method === "POST") {
|
|
1434
|
+
try {
|
|
1435
|
+
const rawBody = await readBody(req);
|
|
1436
|
+
const body = rawBody ? JSON.parse(rawBody) : {};
|
|
1437
|
+
const timeoutMs = normalizeSessionClaimTimeout(
|
|
1438
|
+
body.timeoutMs === void 0 ? null : String(body.timeoutMs)
|
|
1439
|
+
);
|
|
1440
|
+
const result = await annotationSessionStore.claimNextSession({
|
|
1441
|
+
...timeoutMs !== void 0 ? { timeoutMs } : {}
|
|
1442
|
+
});
|
|
1443
|
+
res.writeHead(200, { "Content-Type": "application/json" });
|
|
1444
|
+
res.end(
|
|
1445
|
+
JSON.stringify({
|
|
1446
|
+
success: true,
|
|
1447
|
+
timedOut: result.timedOut,
|
|
1448
|
+
matchedExisting: result.matchedExisting,
|
|
1449
|
+
...result.event ? { event: result.event } : {},
|
|
1450
|
+
...result.session ? { session: result.session } : {}
|
|
1451
|
+
})
|
|
1452
|
+
);
|
|
1453
|
+
} catch (e) {
|
|
1454
|
+
serverLogger4.error(`Error parsing session claim request:`, e);
|
|
1455
|
+
res.writeHead(400, { "Content-Type": "application/json" });
|
|
1456
|
+
res.end(JSON.stringify({ success: false, error: "Invalid JSON body" }));
|
|
1457
|
+
}
|
|
1458
|
+
return;
|
|
1459
|
+
}
|
|
1460
|
+
if (pathname === INSPECTO_API_PATHS.SESSION_EVENTS && req.method === "GET") {
|
|
1461
|
+
const statusParam = url.searchParams.getAll("status");
|
|
1462
|
+
const statuses = statusParam.length ? new Set(statusParam) : null;
|
|
1463
|
+
const sessionId = url.searchParams.get("sessionId")?.trim() || null;
|
|
1464
|
+
res.writeHead(200, {
|
|
1465
|
+
"Content-Type": "text/event-stream",
|
|
1466
|
+
"Cache-Control": "no-cache",
|
|
1467
|
+
Connection: "keep-alive"
|
|
1468
|
+
});
|
|
1469
|
+
res.write(`event: ready
|
|
1470
|
+
data: ${JSON.stringify({ ok: true })}
|
|
1471
|
+
|
|
1472
|
+
`);
|
|
1473
|
+
const unsubscribe = annotationSessionStore.subscribe((event) => {
|
|
1474
|
+
if (sessionId && event.session.id !== sessionId) {
|
|
1475
|
+
return;
|
|
1476
|
+
}
|
|
1477
|
+
if (statuses && !statuses.has(event.session.status)) {
|
|
1478
|
+
return;
|
|
1479
|
+
}
|
|
1480
|
+
res.write(formatSessionSseEvent(event));
|
|
1481
|
+
});
|
|
1482
|
+
req.on("close", () => {
|
|
1483
|
+
unsubscribe();
|
|
1484
|
+
res.end();
|
|
1485
|
+
});
|
|
1486
|
+
return;
|
|
1487
|
+
}
|
|
1488
|
+
if (pathname === INSPECTO_API_PATHS.SESSIONS && req.method === "GET") {
|
|
1489
|
+
const statusParam = url.searchParams.getAll("status");
|
|
1490
|
+
const sessions = annotationSessionStore.listSessions(
|
|
1491
|
+
statusParam.length ? {
|
|
1492
|
+
status: statusParam
|
|
1493
|
+
} : void 0
|
|
1494
|
+
);
|
|
1495
|
+
res.writeHead(200, { "Content-Type": "application/json" });
|
|
1496
|
+
res.end(JSON.stringify({ success: true, sessions }));
|
|
1497
|
+
return;
|
|
1498
|
+
}
|
|
1499
|
+
if (pathname.startsWith(`${INSPECTO_API_PATHS.SESSIONS}/`) && req.method === "GET") {
|
|
1500
|
+
const sessionId = pathname.substring(INSPECTO_API_PATHS.SESSIONS.length + 1);
|
|
1501
|
+
const session = annotationSessionStore.getSession(sessionId);
|
|
1502
|
+
if (!session) {
|
|
1503
|
+
res.writeHead(404, { "Content-Type": "application/json" });
|
|
1504
|
+
res.end(JSON.stringify({ success: false, error: "Session not found" }));
|
|
1505
|
+
return;
|
|
1506
|
+
}
|
|
1507
|
+
res.writeHead(200, { "Content-Type": "application/json" });
|
|
1508
|
+
res.end(JSON.stringify({ success: true, session }));
|
|
1509
|
+
return;
|
|
1510
|
+
}
|
|
1511
|
+
if (pathname.startsWith(`${INSPECTO_API_PATHS.SESSIONS}/`) && pathname.endsWith(INSPECTO_API_PATHS.SESSION_REPLY_SUFFIX) && req.method === "POST") {
|
|
1512
|
+
const sessionId = pathname.slice(
|
|
1513
|
+
INSPECTO_API_PATHS.SESSIONS.length + 1,
|
|
1514
|
+
-INSPECTO_API_PATHS.SESSION_REPLY_SUFFIX.length
|
|
1515
|
+
);
|
|
1516
|
+
try {
|
|
1517
|
+
const rawBody = await readBody(req);
|
|
1518
|
+
const body = JSON.parse(rawBody);
|
|
1519
|
+
if (!isAnnotationThreadRole(body.role)) {
|
|
1520
|
+
res.writeHead(400, { "Content-Type": "application/json" });
|
|
1521
|
+
res.end(JSON.stringify({ success: false, error: "Reply role is invalid." }));
|
|
1522
|
+
return;
|
|
1523
|
+
}
|
|
1524
|
+
if (!body.text?.trim()) {
|
|
1525
|
+
res.writeHead(400, { "Content-Type": "application/json" });
|
|
1526
|
+
res.end(JSON.stringify({ success: false, error: "Reply text is required." }));
|
|
1527
|
+
return;
|
|
1528
|
+
}
|
|
1529
|
+
const session = annotationSessionStore.appendMessage(sessionId, {
|
|
1530
|
+
role: body.role,
|
|
1531
|
+
text: body.text.trim()
|
|
1532
|
+
});
|
|
1533
|
+
if (!session) {
|
|
1534
|
+
res.writeHead(404, { "Content-Type": "application/json" });
|
|
1535
|
+
res.end(JSON.stringify({ success: false, error: "Session not found" }));
|
|
1536
|
+
return;
|
|
1537
|
+
}
|
|
1538
|
+
res.writeHead(200, { "Content-Type": "application/json" });
|
|
1539
|
+
res.end(JSON.stringify({ success: true, session }));
|
|
1540
|
+
} catch (e) {
|
|
1541
|
+
serverLogger4.error(`Error parsing session reply request:`, e);
|
|
1542
|
+
res.writeHead(400, { "Content-Type": "application/json" });
|
|
1543
|
+
res.end(JSON.stringify({ success: false, error: "Invalid JSON body" }));
|
|
1544
|
+
}
|
|
1545
|
+
return;
|
|
1546
|
+
}
|
|
1547
|
+
if (pathname.startsWith(`${INSPECTO_API_PATHS.SESSIONS}/`) && pathname.endsWith(INSPECTO_API_PATHS.SESSION_RESOLVE_SUFFIX) && req.method === "POST") {
|
|
1548
|
+
const sessionId = pathname.slice(
|
|
1549
|
+
INSPECTO_API_PATHS.SESSIONS.length + 1,
|
|
1550
|
+
-INSPECTO_API_PATHS.SESSION_RESOLVE_SUFFIX.length
|
|
1551
|
+
);
|
|
1552
|
+
try {
|
|
1553
|
+
const rawBody = await readBody(req);
|
|
1554
|
+
const body = rawBody ? JSON.parse(rawBody) : {};
|
|
1555
|
+
const message = body.message?.trim();
|
|
1556
|
+
const existingSession = annotationSessionStore.getSession(sessionId);
|
|
1557
|
+
if (!existingSession) {
|
|
1558
|
+
res.writeHead(404, { "Content-Type": "application/json" });
|
|
1559
|
+
res.end(JSON.stringify({ success: false, error: "Session not found" }));
|
|
1560
|
+
return;
|
|
1561
|
+
}
|
|
1562
|
+
if (!message && !hasAgentReply(existingSession)) {
|
|
1563
|
+
res.writeHead(400, { "Content-Type": "application/json" });
|
|
1564
|
+
res.end(
|
|
1565
|
+
JSON.stringify({
|
|
1566
|
+
success: false,
|
|
1567
|
+
error: "Resolve message is required until an agent reply is recorded."
|
|
1568
|
+
})
|
|
1569
|
+
);
|
|
1570
|
+
return;
|
|
1571
|
+
}
|
|
1572
|
+
if (message) {
|
|
1573
|
+
const repliedSession = annotationSessionStore.appendMessage(sessionId, {
|
|
1574
|
+
role: "agent",
|
|
1575
|
+
text: message
|
|
1576
|
+
});
|
|
1577
|
+
if (!repliedSession) {
|
|
1578
|
+
res.writeHead(404, { "Content-Type": "application/json" });
|
|
1579
|
+
res.end(JSON.stringify({ success: false, error: "Session not found" }));
|
|
1580
|
+
return;
|
|
1581
|
+
}
|
|
1582
|
+
}
|
|
1583
|
+
const session = annotationSessionStore.updateStatus(sessionId, "resolved");
|
|
1584
|
+
if (!session) {
|
|
1585
|
+
res.writeHead(404, { "Content-Type": "application/json" });
|
|
1586
|
+
res.end(JSON.stringify({ success: false, error: "Session not found" }));
|
|
1587
|
+
return;
|
|
1588
|
+
}
|
|
1589
|
+
res.writeHead(200, { "Content-Type": "application/json" });
|
|
1590
|
+
res.end(JSON.stringify({ success: true, session }));
|
|
1591
|
+
} catch (e) {
|
|
1592
|
+
serverLogger4.error(`Error parsing session resolve request:`, e);
|
|
1593
|
+
res.writeHead(400, { "Content-Type": "application/json" });
|
|
1594
|
+
res.end(JSON.stringify({ success: false, error: "Invalid JSON body" }));
|
|
1595
|
+
}
|
|
1596
|
+
return;
|
|
1597
|
+
}
|
|
1598
|
+
if (pathname.startsWith(`${INSPECTO_API_PATHS.SESSIONS}/`) && pathname.endsWith(INSPECTO_API_PATHS.SESSION_DISMISS_SUFFIX) && req.method === "POST") {
|
|
1599
|
+
const sessionId = pathname.slice(
|
|
1600
|
+
INSPECTO_API_PATHS.SESSIONS.length + 1,
|
|
1601
|
+
-INSPECTO_API_PATHS.SESSION_DISMISS_SUFFIX.length
|
|
1602
|
+
);
|
|
1603
|
+
try {
|
|
1604
|
+
const rawBody = await readBody(req);
|
|
1605
|
+
const body = rawBody ? JSON.parse(rawBody) : {};
|
|
1606
|
+
const message = body.message?.trim();
|
|
1607
|
+
const existingSession = annotationSessionStore.getSession(sessionId);
|
|
1608
|
+
if (!existingSession) {
|
|
1609
|
+
res.writeHead(404, { "Content-Type": "application/json" });
|
|
1610
|
+
res.end(JSON.stringify({ success: false, error: "Session not found" }));
|
|
1611
|
+
return;
|
|
1612
|
+
}
|
|
1613
|
+
if (message) {
|
|
1614
|
+
const repliedSession = annotationSessionStore.appendMessage(sessionId, {
|
|
1615
|
+
role: "agent",
|
|
1616
|
+
text: message
|
|
1617
|
+
});
|
|
1618
|
+
if (!repliedSession) {
|
|
1619
|
+
res.writeHead(404, { "Content-Type": "application/json" });
|
|
1620
|
+
res.end(JSON.stringify({ success: false, error: "Session not found" }));
|
|
1621
|
+
return;
|
|
1622
|
+
}
|
|
1623
|
+
}
|
|
1624
|
+
const session = annotationSessionStore.updateStatus(sessionId, "dismissed");
|
|
1625
|
+
if (!session) {
|
|
1626
|
+
res.writeHead(404, { "Content-Type": "application/json" });
|
|
1627
|
+
res.end(JSON.stringify({ success: false, error: "Session not found" }));
|
|
1628
|
+
return;
|
|
1629
|
+
}
|
|
1630
|
+
res.writeHead(200, { "Content-Type": "application/json" });
|
|
1631
|
+
res.end(JSON.stringify({ success: true, session }));
|
|
1632
|
+
} catch (e) {
|
|
1633
|
+
serverLogger4.error(`Error parsing session dismiss request:`, e);
|
|
1634
|
+
res.writeHead(400, { "Content-Type": "application/json" });
|
|
1635
|
+
res.end(JSON.stringify({ success: false, error: "Invalid JSON body" }));
|
|
1636
|
+
}
|
|
1637
|
+
return;
|
|
1638
|
+
}
|
|
1201
1639
|
if (pathname.startsWith(`${INSPECTO_API_PATHS.AI_TICKET}/`) && req.method === "GET") {
|
|
1202
1640
|
const ticketId = pathname.substring(INSPECTO_API_PATHS.AI_TICKET.length + 1);
|
|
1203
1641
|
const payloadStr = readTicket(ticketId);
|
|
@@ -1214,7 +1652,7 @@ async function handleRequest(url, req, res) {
|
|
|
1214
1652
|
res.end(JSON.stringify({ error: "not found" }));
|
|
1215
1653
|
}
|
|
1216
1654
|
async function dispatchToAi(req) {
|
|
1217
|
-
const { location, snippet, prompt
|
|
1655
|
+
const { location, snippet, prompt } = req;
|
|
1218
1656
|
const formattedPrompt = prompt ?? `Please help me with this code from \`${location.file}\` (line ${location.line}):
|
|
1219
1657
|
|
|
1220
1658
|
\`\`\`
|
|
@@ -1227,8 +1665,7 @@ ${snippet}
|
|
|
1227
1665
|
filePath: location.file,
|
|
1228
1666
|
line: location.line,
|
|
1229
1667
|
column: location.column,
|
|
1230
|
-
snippet
|
|
1231
|
-
...screenshotContext ? { screenshotContext } : {}
|
|
1668
|
+
snippet
|
|
1232
1669
|
});
|
|
1233
1670
|
}
|
|
1234
1671
|
function getBatchDispatchStatusCode(errorCode, success) {
|
|
@@ -1237,6 +1674,21 @@ function getBatchDispatchStatusCode(errorCode, success) {
|
|
|
1237
1674
|
if (errorCode === "FORBIDDEN_PATH") return 403;
|
|
1238
1675
|
return 500;
|
|
1239
1676
|
}
|
|
1677
|
+
function isAnnotationThreadRole(value) {
|
|
1678
|
+
return value === "user" || value === "agent" || value === "system";
|
|
1679
|
+
}
|
|
1680
|
+
function formatSessionSseEvent(event) {
|
|
1681
|
+
return `event: ${event.type}
|
|
1682
|
+
data: ${JSON.stringify(event)}
|
|
1683
|
+
|
|
1684
|
+
`;
|
|
1685
|
+
}
|
|
1686
|
+
function normalizeSessionClaimTimeout(value) {
|
|
1687
|
+
if (!value?.trim()) return 3e4;
|
|
1688
|
+
const parsed = Number.parseInt(value, 10);
|
|
1689
|
+
if (!Number.isFinite(parsed)) return 3e4;
|
|
1690
|
+
return Math.max(0, Math.min(parsed, 3e5));
|
|
1691
|
+
}
|
|
1240
1692
|
|
|
1241
1693
|
// src/legacy/webpack4/index.ts
|
|
1242
1694
|
import path7 from "path";
|