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