@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
|
@@ -35,21 +35,22 @@ __export(webpack4_exports, {
|
|
|
35
35
|
});
|
|
36
36
|
module.exports = __toCommonJS(webpack4_exports);
|
|
37
37
|
|
|
38
|
-
// ../../node_modules/.pnpm/tsup@8.5.1_jiti@2.
|
|
38
|
+
// ../../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
|
|
39
39
|
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;
|
|
40
40
|
var importMetaUrl = /* @__PURE__ */ getImportMetaUrl();
|
|
41
41
|
|
|
42
42
|
// src/injectors/webpack.ts
|
|
43
|
-
function getWebpackHtmlScript(serverPort) {
|
|
43
|
+
function getWebpackHtmlScript(serverPort, publicServerUrl) {
|
|
44
44
|
return `
|
|
45
45
|
window.__AI_INSPECTOR_PORT__ = ${serverPort};
|
|
46
|
-
window.
|
|
47
|
-
|
|
48
|
-
window.InspectoClient
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
}
|
|
46
|
+
window.__AI_INSPECTOR_SERVER_URL__ = '${publicServerUrl ?? `http://127.0.0.1:${serverPort}`}';
|
|
47
|
+
window.addEventListener('load', () => {
|
|
48
|
+
if (window.InspectoClient) {
|
|
49
|
+
window.InspectoClient.mountInspector({
|
|
50
|
+
serverUrl: window.__AI_INSPECTOR_SERVER_URL__,
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
});
|
|
53
54
|
`;
|
|
54
55
|
}
|
|
55
56
|
|
|
@@ -567,7 +568,6 @@ function dispatchPromptThroughIde(runtime, payload) {
|
|
|
567
568
|
line: payload.line,
|
|
568
569
|
column: payload.column,
|
|
569
570
|
snippet: payload.snippet,
|
|
570
|
-
...payload.screenshotContext ? { screenshotContext: payload.screenshotContext } : {},
|
|
571
571
|
overrides: runtime.overrides,
|
|
572
572
|
autoSend: runtime.autoSend
|
|
573
573
|
});
|
|
@@ -701,6 +701,188 @@ function assertPathWithinIdeOpenScope(file, projectRoot) {
|
|
|
701
701
|
}
|
|
702
702
|
}
|
|
703
703
|
|
|
704
|
+
// src/server/session-store.ts
|
|
705
|
+
var DEFAULT_STATUS = "pending";
|
|
706
|
+
function createAnnotationSessionStore(options = {}) {
|
|
707
|
+
const sessions = /* @__PURE__ */ new Map();
|
|
708
|
+
const listeners = /* @__PURE__ */ new Set();
|
|
709
|
+
const now = options.now ?? (() => Date.now());
|
|
710
|
+
const createId = options.createId ?? createRandomId;
|
|
711
|
+
function findNewestMatchingSession(statuses) {
|
|
712
|
+
return [...sessions.values()].filter((session) => statuses ? statuses.has(session.status) : true).sort((left, right) => right.updatedAt - left.updatedAt)[0] ?? null;
|
|
713
|
+
}
|
|
714
|
+
function updateSessionStatus(id, status) {
|
|
715
|
+
const session = sessions.get(id);
|
|
716
|
+
if (!session) return null;
|
|
717
|
+
const timestamp = now();
|
|
718
|
+
session.status = status;
|
|
719
|
+
session.updatedAt = timestamp;
|
|
720
|
+
if (status === "acknowledged") {
|
|
721
|
+
session.acknowledgedAt = timestamp;
|
|
722
|
+
}
|
|
723
|
+
if (status === "resolved") {
|
|
724
|
+
session.resolvedAt = timestamp;
|
|
725
|
+
}
|
|
726
|
+
emit({ type: "session-status-updated", session });
|
|
727
|
+
return cloneSession(session);
|
|
728
|
+
}
|
|
729
|
+
function claimSession(id, statuses) {
|
|
730
|
+
const session = sessions.get(id);
|
|
731
|
+
if (!session || statuses && !statuses.has(session.status)) return null;
|
|
732
|
+
if (session.status === "acknowledged") return cloneSession(session);
|
|
733
|
+
return updateSessionStatus(id, "acknowledged");
|
|
734
|
+
}
|
|
735
|
+
function emit(event) {
|
|
736
|
+
const snapshot = cloneSession(event.session);
|
|
737
|
+
for (const listener of listeners) {
|
|
738
|
+
listener({ type: event.type, session: snapshot });
|
|
739
|
+
}
|
|
740
|
+
}
|
|
741
|
+
const store = {
|
|
742
|
+
createSession(input) {
|
|
743
|
+
const timestamp = now();
|
|
744
|
+
const session = {
|
|
745
|
+
id: createId(),
|
|
746
|
+
instruction: input.instruction?.trim() ?? "",
|
|
747
|
+
annotations: cloneArray(input.annotations),
|
|
748
|
+
...input.deliveryMode ? { deliveryMode: input.deliveryMode } : {},
|
|
749
|
+
status: DEFAULT_STATUS,
|
|
750
|
+
messages: cloneArray(input.messages ?? []),
|
|
751
|
+
createdAt: timestamp,
|
|
752
|
+
updatedAt: timestamp,
|
|
753
|
+
...input.runtimeContext ? { runtimeContext: cloneValue(input.runtimeContext) } : {},
|
|
754
|
+
...input.cssContextPrompt?.trim() ? { cssContextPrompt: input.cssContextPrompt.trim() } : {},
|
|
755
|
+
...input.pageUrl ? { pageUrl: input.pageUrl } : {},
|
|
756
|
+
...input.route ? { route: input.route } : {}
|
|
757
|
+
};
|
|
758
|
+
sessions.set(session.id, session);
|
|
759
|
+
emit({ type: "session-created", session });
|
|
760
|
+
return cloneSession(session);
|
|
761
|
+
},
|
|
762
|
+
getSession(id) {
|
|
763
|
+
const session = sessions.get(id);
|
|
764
|
+
return session ? cloneSession(session) : null;
|
|
765
|
+
},
|
|
766
|
+
listSessions(options2 = {}) {
|
|
767
|
+
const statuses = normalizeStatuses(options2.status);
|
|
768
|
+
return [...sessions.values()].filter((session) => statuses ? statuses.has(session.status) : true).sort((left, right) => right.updatedAt - left.updatedAt).map((session) => cloneSession(session));
|
|
769
|
+
},
|
|
770
|
+
async claimNextSession(options2 = {}) {
|
|
771
|
+
const statuses = normalizeStatuses(DEFAULT_STATUS);
|
|
772
|
+
const existingSession = findNewestMatchingSession(statuses);
|
|
773
|
+
if (existingSession) {
|
|
774
|
+
return {
|
|
775
|
+
session: claimSession(existingSession.id, statuses),
|
|
776
|
+
timedOut: false,
|
|
777
|
+
matchedExisting: true
|
|
778
|
+
};
|
|
779
|
+
}
|
|
780
|
+
const timeoutMs = normalizeTimeoutMs(options2.timeoutMs);
|
|
781
|
+
if (timeoutMs === 0) {
|
|
782
|
+
return {
|
|
783
|
+
session: null,
|
|
784
|
+
timedOut: true,
|
|
785
|
+
matchedExisting: false
|
|
786
|
+
};
|
|
787
|
+
}
|
|
788
|
+
return await new Promise((resolve2) => {
|
|
789
|
+
let settled = false;
|
|
790
|
+
let timeout = null;
|
|
791
|
+
const finish = (result) => {
|
|
792
|
+
if (settled) return;
|
|
793
|
+
settled = true;
|
|
794
|
+
unsubscribe();
|
|
795
|
+
if (timeout) {
|
|
796
|
+
clearTimeout(timeout);
|
|
797
|
+
}
|
|
798
|
+
resolve2(result);
|
|
799
|
+
};
|
|
800
|
+
const unsubscribe = this.subscribe((event) => {
|
|
801
|
+
const session = claimSession(event.session.id, statuses);
|
|
802
|
+
if (!session) return;
|
|
803
|
+
finish({
|
|
804
|
+
session,
|
|
805
|
+
timedOut: false,
|
|
806
|
+
matchedExisting: false,
|
|
807
|
+
event: event.type
|
|
808
|
+
});
|
|
809
|
+
});
|
|
810
|
+
if (timeoutMs !== null) {
|
|
811
|
+
timeout = setTimeout(() => {
|
|
812
|
+
finish({
|
|
813
|
+
session: null,
|
|
814
|
+
timedOut: true,
|
|
815
|
+
matchedExisting: false
|
|
816
|
+
});
|
|
817
|
+
}, timeoutMs);
|
|
818
|
+
}
|
|
819
|
+
});
|
|
820
|
+
},
|
|
821
|
+
appendMessage(id, input) {
|
|
822
|
+
const session = sessions.get(id);
|
|
823
|
+
if (!session) return null;
|
|
824
|
+
const timestamp = now();
|
|
825
|
+
session.messages.push({
|
|
826
|
+
id: createId(),
|
|
827
|
+
role: input.role,
|
|
828
|
+
text: input.text,
|
|
829
|
+
createdAt: timestamp
|
|
830
|
+
});
|
|
831
|
+
session.updatedAt = timestamp;
|
|
832
|
+
if (input.role === "agent" && isPendingLikeStatus(session.status)) {
|
|
833
|
+
session.status = "in_progress";
|
|
834
|
+
}
|
|
835
|
+
emit({ type: "session-message-appended", session });
|
|
836
|
+
return cloneSession(session);
|
|
837
|
+
},
|
|
838
|
+
updateStatus(id, status) {
|
|
839
|
+
return updateSessionStatus(id, status);
|
|
840
|
+
},
|
|
841
|
+
subscribe(listener) {
|
|
842
|
+
listeners.add(listener);
|
|
843
|
+
return () => {
|
|
844
|
+
listeners.delete(listener);
|
|
845
|
+
};
|
|
846
|
+
},
|
|
847
|
+
clear() {
|
|
848
|
+
sessions.clear();
|
|
849
|
+
listeners.clear();
|
|
850
|
+
}
|
|
851
|
+
};
|
|
852
|
+
return store;
|
|
853
|
+
}
|
|
854
|
+
var annotationSessionStore = createAnnotationSessionStore();
|
|
855
|
+
function normalizeStatuses(status) {
|
|
856
|
+
if (!status) return null;
|
|
857
|
+
return new Set(Array.isArray(status) ? status : [status]);
|
|
858
|
+
}
|
|
859
|
+
function normalizeTimeoutMs(value) {
|
|
860
|
+
if (value === void 0) return null;
|
|
861
|
+
if (!Number.isFinite(value)) return 0;
|
|
862
|
+
return Math.max(0, Math.floor(value));
|
|
863
|
+
}
|
|
864
|
+
function isPendingLikeStatus(status) {
|
|
865
|
+
return status === "pending" || status === "acknowledged";
|
|
866
|
+
}
|
|
867
|
+
function hasAgentReply(session) {
|
|
868
|
+
return session.messages.some((message) => message.role === "agent" && Boolean(message.text?.trim()));
|
|
869
|
+
}
|
|
870
|
+
function createRandomId() {
|
|
871
|
+
return `annotation-session-${Math.random().toString(36).slice(2, 10)}`;
|
|
872
|
+
}
|
|
873
|
+
function cloneSession(session) {
|
|
874
|
+
return cloneValue(session);
|
|
875
|
+
}
|
|
876
|
+
function cloneArray(value) {
|
|
877
|
+
return cloneValue(value);
|
|
878
|
+
}
|
|
879
|
+
function cloneValue(value) {
|
|
880
|
+
if (typeof structuredClone === "function") {
|
|
881
|
+
return structuredClone(value);
|
|
882
|
+
}
|
|
883
|
+
return JSON.parse(JSON.stringify(value));
|
|
884
|
+
}
|
|
885
|
+
|
|
704
886
|
// src/server/annotation-dispatch.ts
|
|
705
887
|
var AnnotationDispatchError = class extends Error {
|
|
706
888
|
constructor(message, errorCode) {
|
|
@@ -709,20 +891,30 @@ var AnnotationDispatchError = class extends Error {
|
|
|
709
891
|
this.errorCode = errorCode;
|
|
710
892
|
}
|
|
711
893
|
};
|
|
712
|
-
async function dispatchAnnotationsToAi(req, state) {
|
|
894
|
+
async function dispatchAnnotationsToAi(req, state, store = annotationSessionStore) {
|
|
713
895
|
try {
|
|
714
896
|
validateAnnotationDispatchRequest(req, state);
|
|
715
897
|
const batch = normalizeAnnotationBatch(req);
|
|
716
898
|
const prompt = buildAnnotationBatchPrompt(batch);
|
|
899
|
+
const deliveryMode = normalizeDeliveryMode(req.deliveryMode);
|
|
900
|
+
const session = store.createSession({
|
|
901
|
+
instruction: batch.instruction,
|
|
902
|
+
annotations: toSessionAnnotations(batch.annotations),
|
|
903
|
+
deliveryMode,
|
|
904
|
+
...batch.runtimeContext ? { runtimeContext: batch.runtimeContext } : {},
|
|
905
|
+
...batch.cssContextPrompt ? { cssContextPrompt: batch.cssContextPrompt } : {}
|
|
906
|
+
});
|
|
717
907
|
const representativeTarget = batch.annotations[0]?.targets[0];
|
|
718
|
-
const
|
|
719
|
-
return dispatchPromptThroughIde(runtime, {
|
|
908
|
+
const dispatchResult = deliveryMode === "ide" ? dispatchPromptThroughIde(resolvePromptDispatchRuntime(state), {
|
|
720
909
|
prompt,
|
|
721
910
|
...representativeTarget?.file ? { filePath: representativeTarget.file } : {},
|
|
722
911
|
...representativeTarget?.line ? { line: representativeTarget.line } : {},
|
|
723
|
-
...representativeTarget?.column ? { column: representativeTarget.column } : {}
|
|
724
|
-
|
|
725
|
-
|
|
912
|
+
...representativeTarget?.column ? { column: representativeTarget.column } : {}
|
|
913
|
+
}) : { success: true };
|
|
914
|
+
return {
|
|
915
|
+
...dispatchResult,
|
|
916
|
+
session: toSessionSummary(session)
|
|
917
|
+
};
|
|
726
918
|
} catch (error) {
|
|
727
919
|
return {
|
|
728
920
|
success: false,
|
|
@@ -731,6 +923,41 @@ async function dispatchAnnotationsToAi(req, state) {
|
|
|
731
923
|
};
|
|
732
924
|
}
|
|
733
925
|
}
|
|
926
|
+
function normalizeDeliveryMode(input) {
|
|
927
|
+
return input === "agent" ? "agent" : "ide";
|
|
928
|
+
}
|
|
929
|
+
function toSessionAnnotations(annotations) {
|
|
930
|
+
return annotations.map((annotation) => ({
|
|
931
|
+
id: `annotation-${annotation.index}`,
|
|
932
|
+
note: annotation.note,
|
|
933
|
+
intent: annotation.intent,
|
|
934
|
+
targets: annotation.targets.map((target, targetIndex) => ({
|
|
935
|
+
id: `annotation-${annotation.index}-target-${targetIndex + 1}`,
|
|
936
|
+
label: target.label ?? "Unknown target",
|
|
937
|
+
location: {
|
|
938
|
+
file: target.file,
|
|
939
|
+
line: target.line,
|
|
940
|
+
column: target.column
|
|
941
|
+
},
|
|
942
|
+
...target.selector ? { selector: target.selector } : {},
|
|
943
|
+
...target.snippet ? { snippet: target.snippet } : {},
|
|
944
|
+
rect: {
|
|
945
|
+
x: 0,
|
|
946
|
+
y: 0,
|
|
947
|
+
width: 0,
|
|
948
|
+
height: 0
|
|
949
|
+
}
|
|
950
|
+
}))
|
|
951
|
+
}));
|
|
952
|
+
}
|
|
953
|
+
function toSessionSummary(session) {
|
|
954
|
+
return {
|
|
955
|
+
id: session.id,
|
|
956
|
+
status: session.status,
|
|
957
|
+
createdAt: session.createdAt,
|
|
958
|
+
updatedAt: session.updatedAt
|
|
959
|
+
};
|
|
960
|
+
}
|
|
734
961
|
function validateAnnotationDispatchRequest(req, state) {
|
|
735
962
|
if (!req.annotations.length) {
|
|
736
963
|
throw new AnnotationDispatchError("At least one annotation is required.", "INVALID_REQUEST");
|
|
@@ -751,9 +978,7 @@ function validateAnnotationDispatchRequest(req, state) {
|
|
|
751
978
|
function normalizeAnnotationBatch(req) {
|
|
752
979
|
return {
|
|
753
980
|
instruction: req.instruction?.trim() ?? "",
|
|
754
|
-
responseMode: req.responseMode ?? "unified",
|
|
755
981
|
...req.runtimeContext ? { runtimeContext: req.runtimeContext } : {},
|
|
756
|
-
...req.screenshotContext ? { screenshotContext: req.screenshotContext } : {},
|
|
757
982
|
...req.cssContextPrompt?.trim() ? { cssContextPrompt: req.cssContextPrompt.trim() } : {},
|
|
758
983
|
annotations: req.annotations.map((annotation, index) => ({
|
|
759
984
|
index: index + 1,
|
|
@@ -775,12 +1000,9 @@ function buildAnnotationBatchPrompt(batch) {
|
|
|
775
1000
|
const prompt = batch.instruction ? `${batch.instruction}
|
|
776
1001
|
|
|
777
1002
|
${body}` : body;
|
|
778
|
-
return
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
batch.cssContextPrompt
|
|
782
|
-
),
|
|
783
|
-
batch.screenshotContext
|
|
1003
|
+
return appendCssContextSection(
|
|
1004
|
+
appendRuntimeContextSection(prompt, batch.runtimeContext),
|
|
1005
|
+
batch.cssContextPrompt
|
|
784
1006
|
);
|
|
785
1007
|
}
|
|
786
1008
|
function appendCssContextSection(prompt, cssContextPrompt) {
|
|
@@ -807,20 +1029,6 @@ function buildSelectedElementsPrompt(annotations) {
|
|
|
807
1029
|
}
|
|
808
1030
|
return lines.join("\n");
|
|
809
1031
|
}
|
|
810
|
-
function appendScreenshotContextSection(prompt, screenshotContext) {
|
|
811
|
-
if (!screenshotContext || !screenshotContext.imageDataUrl && !screenshotContext.imageAssetId) {
|
|
812
|
-
return prompt;
|
|
813
|
-
}
|
|
814
|
-
const lines = [
|
|
815
|
-
"Visual screenshot context attached:",
|
|
816
|
-
`- capturedAt=${screenshotContext.capturedAt}`,
|
|
817
|
-
`- mimeType=${screenshotContext.mimeType}`,
|
|
818
|
-
...screenshotContext.imageAssetId ? [`- imageAssetId=${screenshotContext.imageAssetId}`] : []
|
|
819
|
-
];
|
|
820
|
-
return `${prompt}
|
|
821
|
-
|
|
822
|
-
${lines.join("\n")}`;
|
|
823
|
-
}
|
|
824
1032
|
function appendRuntimeContextSection(prompt, runtimeContext) {
|
|
825
1033
|
if (!runtimeContext?.records.length) {
|
|
826
1034
|
return prompt;
|
|
@@ -868,7 +1076,7 @@ async function buildClientConfig(serverState2) {
|
|
|
868
1076
|
...info,
|
|
869
1077
|
prompts: resolveIntents(promptsConfig),
|
|
870
1078
|
hotKeys: userConfig["inspector.hotKey"] ?? "alt",
|
|
871
|
-
|
|
1079
|
+
annotateDeliveryMode: userConfig["annotate.deliveryMode"] ?? "both",
|
|
872
1080
|
includeSnippet: userConfig["prompt.includeSnippet"] ?? false,
|
|
873
1081
|
runtimeContext: {
|
|
874
1082
|
enabled: true,
|
|
@@ -876,10 +1084,6 @@ async function buildClientConfig(serverState2) {
|
|
|
876
1084
|
maxRuntimeErrors: 3,
|
|
877
1085
|
maxFailedRequests: 2
|
|
878
1086
|
},
|
|
879
|
-
screenshotContext: {
|
|
880
|
-
enabled: false
|
|
881
|
-
},
|
|
882
|
-
annotationResponseMode: userConfig["prompt.annotationResponseMode"] ?? "unified",
|
|
883
1087
|
autoSend: userConfig["prompt.autoSend"] ?? false
|
|
884
1088
|
};
|
|
885
1089
|
}
|
|
@@ -924,7 +1128,7 @@ function handleOpenFileRequest(body, serverState2) {
|
|
|
924
1128
|
else if (rawEditorHint === "vscodium") editorHint = "codium";
|
|
925
1129
|
else if (rawEditorHint === "trae-cn" || rawEditorHint === "trae") editorHint = "trae";
|
|
926
1130
|
serverLogger2.debug(
|
|
927
|
-
`
|
|
1131
|
+
`SOURCE_OPEN: activeIde=${activeIde}, activeIdeScheme=${activeIdeScheme}, configuredIde=${configuredIde} -> rawEditorHint=${rawEditorHint}, finalEditorHint=${editorHint}`
|
|
928
1132
|
);
|
|
929
1133
|
if (VSCODE_FAMILY_SCHEMES.includes(rawEditorHint)) {
|
|
930
1134
|
let normalizedPath = absolutePath.replace(/\\/g, "/");
|
|
@@ -933,7 +1137,7 @@ function handleOpenFileRequest(body, serverState2) {
|
|
|
933
1137
|
}
|
|
934
1138
|
const encodedPath = encodeURI(normalizedPath);
|
|
935
1139
|
const uri = `${rawEditorHint}://file${encodedPath}:${body.line}:${body.column}`;
|
|
936
|
-
serverLogger2.debug(`
|
|
1140
|
+
serverLogger2.debug(`SOURCE_OPEN: Bypassing launchIDE, using URI scheme directly: ${uri}`);
|
|
937
1141
|
try {
|
|
938
1142
|
if (process.platform === "darwin") {
|
|
939
1143
|
(0, import_node_child_process2.execFileSync)("open", [uri]);
|
|
@@ -943,7 +1147,7 @@ function handleOpenFileRequest(body, serverState2) {
|
|
|
943
1147
|
(0, import_node_child_process2.execFileSync)("xdg-open", [uri]);
|
|
944
1148
|
}
|
|
945
1149
|
} catch (e) {
|
|
946
|
-
serverLogger2.error(`Failed to launch URI for
|
|
1150
|
+
serverLogger2.error(`Failed to launch URI for SOURCE_OPEN (${uri}):`, e);
|
|
947
1151
|
(0, import_launch_ide2.launchIDE)({
|
|
948
1152
|
file: absolutePath,
|
|
949
1153
|
line: body.line,
|
|
@@ -998,8 +1202,18 @@ function resolveProjectRoot() {
|
|
|
998
1202
|
return gitRoot;
|
|
999
1203
|
}
|
|
1000
1204
|
|
|
1205
|
+
// src/server/server-url.ts
|
|
1206
|
+
function resolveServerHost(cwd, configRoot) {
|
|
1207
|
+
const userConfig = loadUserConfigSync(false, cwd, configRoot);
|
|
1208
|
+
const configuredHost = userConfig["server.host"]?.trim();
|
|
1209
|
+
if (configuredHost) return configuredHost;
|
|
1210
|
+
if (process.env["VITEST"]) return "127.0.0.1";
|
|
1211
|
+
return "127.0.0.1";
|
|
1212
|
+
}
|
|
1213
|
+
|
|
1001
1214
|
// src/server/index.ts
|
|
1002
1215
|
var serverLogger4 = createLogger("inspecto:server", { logLevel: getGlobalLogLevel() });
|
|
1216
|
+
var PORT_FILE_NAME = "inspecto.port.json";
|
|
1003
1217
|
var serverState = {
|
|
1004
1218
|
port: null,
|
|
1005
1219
|
running: false,
|
|
@@ -1008,6 +1222,42 @@ var serverState = {
|
|
|
1008
1222
|
cwd: process.cwd()
|
|
1009
1223
|
};
|
|
1010
1224
|
var serverInstance = null;
|
|
1225
|
+
function getPortFilePath() {
|
|
1226
|
+
return import_node_path4.default.join(import_node_os2.default.tmpdir(), PORT_FILE_NAME);
|
|
1227
|
+
}
|
|
1228
|
+
function getProjectRootHash() {
|
|
1229
|
+
if (!serverState.projectRoot) return null;
|
|
1230
|
+
return import_node_crypto2.default.createHash("md5").update(serverState.projectRoot).digest("hex");
|
|
1231
|
+
}
|
|
1232
|
+
function readPortData(portFile) {
|
|
1233
|
+
if (!import_node_fs4.default.existsSync(portFile)) return {};
|
|
1234
|
+
try {
|
|
1235
|
+
return JSON.parse(import_node_fs4.default.readFileSync(portFile, "utf-8"));
|
|
1236
|
+
} catch {
|
|
1237
|
+
return {};
|
|
1238
|
+
}
|
|
1239
|
+
}
|
|
1240
|
+
function writeProjectPort(port) {
|
|
1241
|
+
const rootHash = getProjectRootHash();
|
|
1242
|
+
if (!rootHash) return;
|
|
1243
|
+
const portFile = getPortFilePath();
|
|
1244
|
+
const portData = readPortData(portFile);
|
|
1245
|
+
portData[rootHash] = port;
|
|
1246
|
+
import_node_fs4.default.writeFileSync(portFile, JSON.stringify(portData, null, 2), "utf-8");
|
|
1247
|
+
}
|
|
1248
|
+
function removeProjectPort() {
|
|
1249
|
+
const rootHash = getProjectRootHash();
|
|
1250
|
+
if (!rootHash) return;
|
|
1251
|
+
const portFile = getPortFilePath();
|
|
1252
|
+
if (!import_node_fs4.default.existsSync(portFile)) return;
|
|
1253
|
+
const portData = readPortData(portFile);
|
|
1254
|
+
delete portData[rootHash];
|
|
1255
|
+
if (Object.keys(portData).length === 0) {
|
|
1256
|
+
import_node_fs4.default.unlinkSync(portFile);
|
|
1257
|
+
} else {
|
|
1258
|
+
import_node_fs4.default.writeFileSync(portFile, JSON.stringify(portData, null, 2), "utf-8");
|
|
1259
|
+
}
|
|
1260
|
+
}
|
|
1011
1261
|
async function startServer() {
|
|
1012
1262
|
if (serverState.running && serverState.port !== null) {
|
|
1013
1263
|
return serverState.port;
|
|
@@ -1015,6 +1265,7 @@ async function startServer() {
|
|
|
1015
1265
|
serverState.projectRoot = resolveProjectRoot();
|
|
1016
1266
|
serverState.configRoot = serverState.projectRoot;
|
|
1017
1267
|
serverState.cwd = process.cwd();
|
|
1268
|
+
const serverHost = resolveServerHost(serverState.cwd, serverState.configRoot);
|
|
1018
1269
|
import_portfinder.default.basePort = 5678;
|
|
1019
1270
|
const port = await import_portfinder.default.getPortPromise();
|
|
1020
1271
|
watchConfig(
|
|
@@ -1041,7 +1292,7 @@ async function startServer() {
|
|
|
1041
1292
|
});
|
|
1042
1293
|
});
|
|
1043
1294
|
await new Promise((resolve2, reject) => {
|
|
1044
|
-
serverInstance.listen(port,
|
|
1295
|
+
serverInstance.listen(port, serverHost, () => {
|
|
1045
1296
|
serverInstance.unref();
|
|
1046
1297
|
resolve2();
|
|
1047
1298
|
});
|
|
@@ -1052,37 +1303,18 @@ async function startServer() {
|
|
|
1052
1303
|
});
|
|
1053
1304
|
serverState.port = port;
|
|
1054
1305
|
serverState.running = true;
|
|
1055
|
-
const portFile = import_node_path4.default.join(import_node_os2.default.tmpdir(), "inspecto.port.json");
|
|
1056
1306
|
try {
|
|
1057
|
-
|
|
1058
|
-
if (import_node_fs4.default.existsSync(portFile)) {
|
|
1059
|
-
try {
|
|
1060
|
-
portData = JSON.parse(import_node_fs4.default.readFileSync(portFile, "utf-8"));
|
|
1061
|
-
} catch (_e) {
|
|
1062
|
-
}
|
|
1063
|
-
}
|
|
1064
|
-
const rootHash = import_node_crypto2.default.createHash("md5").update(serverState.projectRoot).digest("hex");
|
|
1065
|
-
portData[rootHash] = port;
|
|
1066
|
-
import_node_fs4.default.writeFileSync(portFile, JSON.stringify(portData, null, 2), "utf-8");
|
|
1307
|
+
writeProjectPort(port);
|
|
1067
1308
|
} catch (_e) {
|
|
1068
1309
|
serverLogger4.warn("Failed to write port file:", _e);
|
|
1069
1310
|
}
|
|
1070
1311
|
process.once("exit", () => {
|
|
1071
1312
|
try {
|
|
1072
|
-
|
|
1073
|
-
const portData = JSON.parse(import_node_fs4.default.readFileSync(portFile, "utf-8"));
|
|
1074
|
-
const rootHash = import_node_crypto2.default.createHash("md5").update(serverState.projectRoot).digest("hex");
|
|
1075
|
-
delete portData[rootHash];
|
|
1076
|
-
if (Object.keys(portData).length === 0) {
|
|
1077
|
-
import_node_fs4.default.unlinkSync(portFile);
|
|
1078
|
-
} else {
|
|
1079
|
-
import_node_fs4.default.writeFileSync(portFile, JSON.stringify(portData, null, 2), "utf-8");
|
|
1080
|
-
}
|
|
1081
|
-
}
|
|
1313
|
+
removeProjectPort();
|
|
1082
1314
|
} catch {
|
|
1083
1315
|
}
|
|
1084
1316
|
});
|
|
1085
|
-
serverLogger4.info(`server running at http
|
|
1317
|
+
serverLogger4.info(`server running at http://${serverHost}:${port}`);
|
|
1086
1318
|
return port;
|
|
1087
1319
|
}
|
|
1088
1320
|
async function readBody(req) {
|
|
@@ -1134,7 +1366,7 @@ async function handleRequest(url, req, res) {
|
|
|
1134
1366
|
}
|
|
1135
1367
|
return;
|
|
1136
1368
|
}
|
|
1137
|
-
if (pathname === import_types2.INSPECTO_API_PATHS.IDE_OPEN && req.method === "POST") {
|
|
1369
|
+
if ((pathname === import_types2.INSPECTO_API_PATHS.SOURCE_OPEN || pathname === import_types2.INSPECTO_API_PATHS.IDE_OPEN) && req.method === "POST") {
|
|
1138
1370
|
let body;
|
|
1139
1371
|
try {
|
|
1140
1372
|
body = JSON.parse(await readBody(req));
|
|
@@ -1147,7 +1379,7 @@ async function handleRequest(url, req, res) {
|
|
|
1147
1379
|
handleOpenFileRequest(body, serverState);
|
|
1148
1380
|
} catch (err) {
|
|
1149
1381
|
serverLogger4.warn(
|
|
1150
|
-
`Security: Blocked path traversal attempt in
|
|
1382
|
+
`Security: Blocked path traversal attempt in SOURCE_OPEN: ${body.file}. Reason: ${err.message}`
|
|
1151
1383
|
);
|
|
1152
1384
|
res.writeHead(403, { "Content-Type": "application/json" });
|
|
1153
1385
|
res.end(JSON.stringify({ error: "Access denied: File is outside of project workspace" }));
|
|
@@ -1221,6 +1453,212 @@ async function handleRequest(url, req, res) {
|
|
|
1221
1453
|
}
|
|
1222
1454
|
return;
|
|
1223
1455
|
}
|
|
1456
|
+
if (pathname === import_types2.INSPECTO_API_PATHS.SESSION_CLAIM_NEXT && req.method === "POST") {
|
|
1457
|
+
try {
|
|
1458
|
+
const rawBody = await readBody(req);
|
|
1459
|
+
const body = rawBody ? JSON.parse(rawBody) : {};
|
|
1460
|
+
const timeoutMs = normalizeSessionClaimTimeout(
|
|
1461
|
+
body.timeoutMs === void 0 ? null : String(body.timeoutMs)
|
|
1462
|
+
);
|
|
1463
|
+
const result = await annotationSessionStore.claimNextSession({
|
|
1464
|
+
...timeoutMs !== void 0 ? { timeoutMs } : {}
|
|
1465
|
+
});
|
|
1466
|
+
res.writeHead(200, { "Content-Type": "application/json" });
|
|
1467
|
+
res.end(
|
|
1468
|
+
JSON.stringify({
|
|
1469
|
+
success: true,
|
|
1470
|
+
timedOut: result.timedOut,
|
|
1471
|
+
matchedExisting: result.matchedExisting,
|
|
1472
|
+
...result.event ? { event: result.event } : {},
|
|
1473
|
+
...result.session ? { session: result.session } : {}
|
|
1474
|
+
})
|
|
1475
|
+
);
|
|
1476
|
+
} catch (e) {
|
|
1477
|
+
serverLogger4.error(`Error parsing session claim request:`, e);
|
|
1478
|
+
res.writeHead(400, { "Content-Type": "application/json" });
|
|
1479
|
+
res.end(JSON.stringify({ success: false, error: "Invalid JSON body" }));
|
|
1480
|
+
}
|
|
1481
|
+
return;
|
|
1482
|
+
}
|
|
1483
|
+
if (pathname === import_types2.INSPECTO_API_PATHS.SESSION_EVENTS && req.method === "GET") {
|
|
1484
|
+
const statusParam = url.searchParams.getAll("status");
|
|
1485
|
+
const statuses = statusParam.length ? new Set(statusParam) : null;
|
|
1486
|
+
const sessionId = url.searchParams.get("sessionId")?.trim() || null;
|
|
1487
|
+
res.writeHead(200, {
|
|
1488
|
+
"Content-Type": "text/event-stream",
|
|
1489
|
+
"Cache-Control": "no-cache",
|
|
1490
|
+
Connection: "keep-alive"
|
|
1491
|
+
});
|
|
1492
|
+
res.write(`event: ready
|
|
1493
|
+
data: ${JSON.stringify({ ok: true })}
|
|
1494
|
+
|
|
1495
|
+
`);
|
|
1496
|
+
const unsubscribe = annotationSessionStore.subscribe((event) => {
|
|
1497
|
+
if (sessionId && event.session.id !== sessionId) {
|
|
1498
|
+
return;
|
|
1499
|
+
}
|
|
1500
|
+
if (statuses && !statuses.has(event.session.status)) {
|
|
1501
|
+
return;
|
|
1502
|
+
}
|
|
1503
|
+
res.write(formatSessionSseEvent(event));
|
|
1504
|
+
});
|
|
1505
|
+
req.on("close", () => {
|
|
1506
|
+
unsubscribe();
|
|
1507
|
+
res.end();
|
|
1508
|
+
});
|
|
1509
|
+
return;
|
|
1510
|
+
}
|
|
1511
|
+
if (pathname === import_types2.INSPECTO_API_PATHS.SESSIONS && req.method === "GET") {
|
|
1512
|
+
const statusParam = url.searchParams.getAll("status");
|
|
1513
|
+
const sessions = annotationSessionStore.listSessions(
|
|
1514
|
+
statusParam.length ? {
|
|
1515
|
+
status: statusParam
|
|
1516
|
+
} : void 0
|
|
1517
|
+
);
|
|
1518
|
+
res.writeHead(200, { "Content-Type": "application/json" });
|
|
1519
|
+
res.end(JSON.stringify({ success: true, sessions }));
|
|
1520
|
+
return;
|
|
1521
|
+
}
|
|
1522
|
+
if (pathname.startsWith(`${import_types2.INSPECTO_API_PATHS.SESSIONS}/`) && req.method === "GET") {
|
|
1523
|
+
const sessionId = pathname.substring(import_types2.INSPECTO_API_PATHS.SESSIONS.length + 1);
|
|
1524
|
+
const session = annotationSessionStore.getSession(sessionId);
|
|
1525
|
+
if (!session) {
|
|
1526
|
+
res.writeHead(404, { "Content-Type": "application/json" });
|
|
1527
|
+
res.end(JSON.stringify({ success: false, error: "Session not found" }));
|
|
1528
|
+
return;
|
|
1529
|
+
}
|
|
1530
|
+
res.writeHead(200, { "Content-Type": "application/json" });
|
|
1531
|
+
res.end(JSON.stringify({ success: true, session }));
|
|
1532
|
+
return;
|
|
1533
|
+
}
|
|
1534
|
+
if (pathname.startsWith(`${import_types2.INSPECTO_API_PATHS.SESSIONS}/`) && pathname.endsWith(import_types2.INSPECTO_API_PATHS.SESSION_REPLY_SUFFIX) && req.method === "POST") {
|
|
1535
|
+
const sessionId = pathname.slice(
|
|
1536
|
+
import_types2.INSPECTO_API_PATHS.SESSIONS.length + 1,
|
|
1537
|
+
-import_types2.INSPECTO_API_PATHS.SESSION_REPLY_SUFFIX.length
|
|
1538
|
+
);
|
|
1539
|
+
try {
|
|
1540
|
+
const rawBody = await readBody(req);
|
|
1541
|
+
const body = JSON.parse(rawBody);
|
|
1542
|
+
if (!isAnnotationThreadRole(body.role)) {
|
|
1543
|
+
res.writeHead(400, { "Content-Type": "application/json" });
|
|
1544
|
+
res.end(JSON.stringify({ success: false, error: "Reply role is invalid." }));
|
|
1545
|
+
return;
|
|
1546
|
+
}
|
|
1547
|
+
if (!body.text?.trim()) {
|
|
1548
|
+
res.writeHead(400, { "Content-Type": "application/json" });
|
|
1549
|
+
res.end(JSON.stringify({ success: false, error: "Reply text is required." }));
|
|
1550
|
+
return;
|
|
1551
|
+
}
|
|
1552
|
+
const session = annotationSessionStore.appendMessage(sessionId, {
|
|
1553
|
+
role: body.role,
|
|
1554
|
+
text: body.text.trim()
|
|
1555
|
+
});
|
|
1556
|
+
if (!session) {
|
|
1557
|
+
res.writeHead(404, { "Content-Type": "application/json" });
|
|
1558
|
+
res.end(JSON.stringify({ success: false, error: "Session not found" }));
|
|
1559
|
+
return;
|
|
1560
|
+
}
|
|
1561
|
+
res.writeHead(200, { "Content-Type": "application/json" });
|
|
1562
|
+
res.end(JSON.stringify({ success: true, session }));
|
|
1563
|
+
} catch (e) {
|
|
1564
|
+
serverLogger4.error(`Error parsing session reply request:`, e);
|
|
1565
|
+
res.writeHead(400, { "Content-Type": "application/json" });
|
|
1566
|
+
res.end(JSON.stringify({ success: false, error: "Invalid JSON body" }));
|
|
1567
|
+
}
|
|
1568
|
+
return;
|
|
1569
|
+
}
|
|
1570
|
+
if (pathname.startsWith(`${import_types2.INSPECTO_API_PATHS.SESSIONS}/`) && pathname.endsWith(import_types2.INSPECTO_API_PATHS.SESSION_RESOLVE_SUFFIX) && req.method === "POST") {
|
|
1571
|
+
const sessionId = pathname.slice(
|
|
1572
|
+
import_types2.INSPECTO_API_PATHS.SESSIONS.length + 1,
|
|
1573
|
+
-import_types2.INSPECTO_API_PATHS.SESSION_RESOLVE_SUFFIX.length
|
|
1574
|
+
);
|
|
1575
|
+
try {
|
|
1576
|
+
const rawBody = await readBody(req);
|
|
1577
|
+
const body = rawBody ? JSON.parse(rawBody) : {};
|
|
1578
|
+
const message = body.message?.trim();
|
|
1579
|
+
const existingSession = annotationSessionStore.getSession(sessionId);
|
|
1580
|
+
if (!existingSession) {
|
|
1581
|
+
res.writeHead(404, { "Content-Type": "application/json" });
|
|
1582
|
+
res.end(JSON.stringify({ success: false, error: "Session not found" }));
|
|
1583
|
+
return;
|
|
1584
|
+
}
|
|
1585
|
+
if (!message && !hasAgentReply(existingSession)) {
|
|
1586
|
+
res.writeHead(400, { "Content-Type": "application/json" });
|
|
1587
|
+
res.end(
|
|
1588
|
+
JSON.stringify({
|
|
1589
|
+
success: false,
|
|
1590
|
+
error: "Resolve message is required until an agent reply is recorded."
|
|
1591
|
+
})
|
|
1592
|
+
);
|
|
1593
|
+
return;
|
|
1594
|
+
}
|
|
1595
|
+
if (message) {
|
|
1596
|
+
const repliedSession = annotationSessionStore.appendMessage(sessionId, {
|
|
1597
|
+
role: "agent",
|
|
1598
|
+
text: message
|
|
1599
|
+
});
|
|
1600
|
+
if (!repliedSession) {
|
|
1601
|
+
res.writeHead(404, { "Content-Type": "application/json" });
|
|
1602
|
+
res.end(JSON.stringify({ success: false, error: "Session not found" }));
|
|
1603
|
+
return;
|
|
1604
|
+
}
|
|
1605
|
+
}
|
|
1606
|
+
const session = annotationSessionStore.updateStatus(sessionId, "resolved");
|
|
1607
|
+
if (!session) {
|
|
1608
|
+
res.writeHead(404, { "Content-Type": "application/json" });
|
|
1609
|
+
res.end(JSON.stringify({ success: false, error: "Session not found" }));
|
|
1610
|
+
return;
|
|
1611
|
+
}
|
|
1612
|
+
res.writeHead(200, { "Content-Type": "application/json" });
|
|
1613
|
+
res.end(JSON.stringify({ success: true, session }));
|
|
1614
|
+
} catch (e) {
|
|
1615
|
+
serverLogger4.error(`Error parsing session resolve request:`, e);
|
|
1616
|
+
res.writeHead(400, { "Content-Type": "application/json" });
|
|
1617
|
+
res.end(JSON.stringify({ success: false, error: "Invalid JSON body" }));
|
|
1618
|
+
}
|
|
1619
|
+
return;
|
|
1620
|
+
}
|
|
1621
|
+
if (pathname.startsWith(`${import_types2.INSPECTO_API_PATHS.SESSIONS}/`) && pathname.endsWith(import_types2.INSPECTO_API_PATHS.SESSION_DISMISS_SUFFIX) && req.method === "POST") {
|
|
1622
|
+
const sessionId = pathname.slice(
|
|
1623
|
+
import_types2.INSPECTO_API_PATHS.SESSIONS.length + 1,
|
|
1624
|
+
-import_types2.INSPECTO_API_PATHS.SESSION_DISMISS_SUFFIX.length
|
|
1625
|
+
);
|
|
1626
|
+
try {
|
|
1627
|
+
const rawBody = await readBody(req);
|
|
1628
|
+
const body = rawBody ? JSON.parse(rawBody) : {};
|
|
1629
|
+
const message = body.message?.trim();
|
|
1630
|
+
const existingSession = annotationSessionStore.getSession(sessionId);
|
|
1631
|
+
if (!existingSession) {
|
|
1632
|
+
res.writeHead(404, { "Content-Type": "application/json" });
|
|
1633
|
+
res.end(JSON.stringify({ success: false, error: "Session not found" }));
|
|
1634
|
+
return;
|
|
1635
|
+
}
|
|
1636
|
+
if (message) {
|
|
1637
|
+
const repliedSession = annotationSessionStore.appendMessage(sessionId, {
|
|
1638
|
+
role: "agent",
|
|
1639
|
+
text: message
|
|
1640
|
+
});
|
|
1641
|
+
if (!repliedSession) {
|
|
1642
|
+
res.writeHead(404, { "Content-Type": "application/json" });
|
|
1643
|
+
res.end(JSON.stringify({ success: false, error: "Session not found" }));
|
|
1644
|
+
return;
|
|
1645
|
+
}
|
|
1646
|
+
}
|
|
1647
|
+
const session = annotationSessionStore.updateStatus(sessionId, "dismissed");
|
|
1648
|
+
if (!session) {
|
|
1649
|
+
res.writeHead(404, { "Content-Type": "application/json" });
|
|
1650
|
+
res.end(JSON.stringify({ success: false, error: "Session not found" }));
|
|
1651
|
+
return;
|
|
1652
|
+
}
|
|
1653
|
+
res.writeHead(200, { "Content-Type": "application/json" });
|
|
1654
|
+
res.end(JSON.stringify({ success: true, session }));
|
|
1655
|
+
} catch (e) {
|
|
1656
|
+
serverLogger4.error(`Error parsing session dismiss request:`, e);
|
|
1657
|
+
res.writeHead(400, { "Content-Type": "application/json" });
|
|
1658
|
+
res.end(JSON.stringify({ success: false, error: "Invalid JSON body" }));
|
|
1659
|
+
}
|
|
1660
|
+
return;
|
|
1661
|
+
}
|
|
1224
1662
|
if (pathname.startsWith(`${import_types2.INSPECTO_API_PATHS.AI_TICKET}/`) && req.method === "GET") {
|
|
1225
1663
|
const ticketId = pathname.substring(import_types2.INSPECTO_API_PATHS.AI_TICKET.length + 1);
|
|
1226
1664
|
const payloadStr = readTicket(ticketId);
|
|
@@ -1237,7 +1675,7 @@ async function handleRequest(url, req, res) {
|
|
|
1237
1675
|
res.end(JSON.stringify({ error: "not found" }));
|
|
1238
1676
|
}
|
|
1239
1677
|
async function dispatchToAi(req) {
|
|
1240
|
-
const { location, snippet, prompt
|
|
1678
|
+
const { location, snippet, prompt } = req;
|
|
1241
1679
|
const formattedPrompt = prompt ?? `Please help me with this code from \`${location.file}\` (line ${location.line}):
|
|
1242
1680
|
|
|
1243
1681
|
\`\`\`
|
|
@@ -1250,8 +1688,7 @@ ${snippet}
|
|
|
1250
1688
|
filePath: location.file,
|
|
1251
1689
|
line: location.line,
|
|
1252
1690
|
column: location.column,
|
|
1253
|
-
snippet
|
|
1254
|
-
...screenshotContext ? { screenshotContext } : {}
|
|
1691
|
+
snippet
|
|
1255
1692
|
});
|
|
1256
1693
|
}
|
|
1257
1694
|
function getBatchDispatchStatusCode(errorCode, success) {
|
|
@@ -1260,6 +1697,21 @@ function getBatchDispatchStatusCode(errorCode, success) {
|
|
|
1260
1697
|
if (errorCode === "FORBIDDEN_PATH") return 403;
|
|
1261
1698
|
return 500;
|
|
1262
1699
|
}
|
|
1700
|
+
function isAnnotationThreadRole(value) {
|
|
1701
|
+
return value === "user" || value === "agent" || value === "system";
|
|
1702
|
+
}
|
|
1703
|
+
function formatSessionSseEvent(event) {
|
|
1704
|
+
return `event: ${event.type}
|
|
1705
|
+
data: ${JSON.stringify(event)}
|
|
1706
|
+
|
|
1707
|
+
`;
|
|
1708
|
+
}
|
|
1709
|
+
function normalizeSessionClaimTimeout(value) {
|
|
1710
|
+
if (!value?.trim()) return 3e4;
|
|
1711
|
+
const parsed = Number.parseInt(value, 10);
|
|
1712
|
+
if (!Number.isFinite(parsed)) return 3e4;
|
|
1713
|
+
return Math.max(0, Math.min(parsed, 3e5));
|
|
1714
|
+
}
|
|
1263
1715
|
|
|
1264
1716
|
// src/legacy/webpack4/index.ts
|
|
1265
1717
|
var import_node_path5 = __toESM(require("path"), 1);
|