@inspecto-dev/plugin 0.3.8 → 0.3.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/astro.cjs +572 -86
- package/dist/astro.cjs.map +1 -1
- package/dist/astro.d.cts +1 -1
- package/dist/astro.d.ts +1 -1
- package/dist/astro.js +571 -85
- package/dist/astro.js.map +1 -1
- package/dist/index.cjs +559 -83
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +558 -82
- package/dist/index.js.map +1 -1
- package/dist/legacy/rspack/index.cjs +526 -74
- package/dist/legacy/rspack/index.cjs.map +1 -1
- package/dist/legacy/rspack/index.js +526 -74
- package/dist/legacy/rspack/index.js.map +1 -1
- package/dist/legacy/rspack/loader.cjs +4 -1
- package/dist/legacy/rspack/loader.cjs.map +1 -1
- package/dist/legacy/rspack/loader.js +3 -0
- package/dist/legacy/rspack/loader.js.map +1 -1
- package/dist/legacy/webpack4/index.cjs +526 -74
- package/dist/legacy/webpack4/index.cjs.map +1 -1
- package/dist/legacy/webpack4/index.js +526 -74
- package/dist/legacy/webpack4/index.js.map +1 -1
- package/dist/legacy/webpack4/loader.cjs +4 -1
- package/dist/legacy/webpack4/loader.cjs.map +1 -1
- package/dist/legacy/webpack4/loader.js +3 -0
- package/dist/legacy/webpack4/loader.js.map +1 -1
- package/dist/rollup.cjs +559 -83
- package/dist/rollup.cjs.map +1 -1
- package/dist/rollup.js +558 -82
- package/dist/rollup.js.map +1 -1
- package/dist/rspack.cjs +559 -83
- package/dist/rspack.cjs.map +1 -1
- package/dist/rspack.js +558 -82
- package/dist/rspack.js.map +1 -1
- package/dist/vite.cjs +559 -83
- package/dist/vite.cjs.map +1 -1
- package/dist/vite.js +558 -82
- package/dist/vite.js.map +1 -1
- package/dist/webpack.cjs +559 -83
- package/dist/webpack.cjs.map +1 -1
- package/dist/webpack.js +558 -82
- package/dist/webpack.js.map +1 -1
- package/package.json +8 -12
package/dist/index.cjs
CHANGED
|
@@ -43,7 +43,7 @@ __export(src_exports, {
|
|
|
43
43
|
});
|
|
44
44
|
module.exports = __toCommonJS(src_exports);
|
|
45
45
|
|
|
46
|
-
// ../../node_modules/.pnpm/tsup@8.5.1_jiti@2.
|
|
46
|
+
// ../../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
|
|
47
47
|
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;
|
|
48
48
|
var importMetaUrl = /* @__PURE__ */ getImportMetaUrl();
|
|
49
49
|
|
|
@@ -736,7 +736,9 @@ function transformRouter(options) {
|
|
|
736
736
|
return transformSvelte({
|
|
737
737
|
filePath,
|
|
738
738
|
source,
|
|
739
|
+
projectRoot,
|
|
739
740
|
escapeTags: pluginOptions.escapeTags,
|
|
741
|
+
pathType: pluginOptions.pathType,
|
|
740
742
|
attributeName: pluginOptions.attributeName
|
|
741
743
|
});
|
|
742
744
|
}
|
|
@@ -745,6 +747,7 @@ function transformRouter(options) {
|
|
|
745
747
|
filePath,
|
|
746
748
|
source,
|
|
747
749
|
escapeTags: pluginOptions.escapeTags,
|
|
750
|
+
pathType: pluginOptions.pathType,
|
|
748
751
|
attributeName: pluginOptions.attributeName
|
|
749
752
|
});
|
|
750
753
|
}
|
|
@@ -1262,7 +1265,6 @@ function dispatchPromptThroughIde(runtime, payload) {
|
|
|
1262
1265
|
line: payload.line,
|
|
1263
1266
|
column: payload.column,
|
|
1264
1267
|
snippet: payload.snippet,
|
|
1265
|
-
...payload.screenshotContext ? { screenshotContext: payload.screenshotContext } : {},
|
|
1266
1268
|
overrides: runtime.overrides,
|
|
1267
1269
|
autoSend: runtime.autoSend
|
|
1268
1270
|
});
|
|
@@ -1396,6 +1398,188 @@ function assertPathWithinIdeOpenScope(file, projectRoot) {
|
|
|
1396
1398
|
}
|
|
1397
1399
|
}
|
|
1398
1400
|
|
|
1401
|
+
// src/server/session-store.ts
|
|
1402
|
+
var DEFAULT_STATUS = "pending";
|
|
1403
|
+
function createAnnotationSessionStore(options = {}) {
|
|
1404
|
+
const sessions = /* @__PURE__ */ new Map();
|
|
1405
|
+
const listeners = /* @__PURE__ */ new Set();
|
|
1406
|
+
const now = options.now ?? (() => Date.now());
|
|
1407
|
+
const createId = options.createId ?? createRandomId;
|
|
1408
|
+
function findNewestMatchingSession(statuses) {
|
|
1409
|
+
return [...sessions.values()].filter((session) => statuses ? statuses.has(session.status) : true).sort((left, right) => right.updatedAt - left.updatedAt)[0] ?? null;
|
|
1410
|
+
}
|
|
1411
|
+
function updateSessionStatus(id, status) {
|
|
1412
|
+
const session = sessions.get(id);
|
|
1413
|
+
if (!session) return null;
|
|
1414
|
+
const timestamp = now();
|
|
1415
|
+
session.status = status;
|
|
1416
|
+
session.updatedAt = timestamp;
|
|
1417
|
+
if (status === "acknowledged") {
|
|
1418
|
+
session.acknowledgedAt = timestamp;
|
|
1419
|
+
}
|
|
1420
|
+
if (status === "resolved") {
|
|
1421
|
+
session.resolvedAt = timestamp;
|
|
1422
|
+
}
|
|
1423
|
+
emit({ type: "session-status-updated", session });
|
|
1424
|
+
return cloneSession(session);
|
|
1425
|
+
}
|
|
1426
|
+
function claimSession(id, statuses) {
|
|
1427
|
+
const session = sessions.get(id);
|
|
1428
|
+
if (!session || statuses && !statuses.has(session.status)) return null;
|
|
1429
|
+
if (session.status === "acknowledged") return cloneSession(session);
|
|
1430
|
+
return updateSessionStatus(id, "acknowledged");
|
|
1431
|
+
}
|
|
1432
|
+
function emit(event) {
|
|
1433
|
+
const snapshot = cloneSession(event.session);
|
|
1434
|
+
for (const listener of listeners) {
|
|
1435
|
+
listener({ type: event.type, session: snapshot });
|
|
1436
|
+
}
|
|
1437
|
+
}
|
|
1438
|
+
const store = {
|
|
1439
|
+
createSession(input) {
|
|
1440
|
+
const timestamp = now();
|
|
1441
|
+
const session = {
|
|
1442
|
+
id: createId(),
|
|
1443
|
+
instruction: input.instruction?.trim() ?? "",
|
|
1444
|
+
annotations: cloneArray(input.annotations),
|
|
1445
|
+
...input.deliveryMode ? { deliveryMode: input.deliveryMode } : {},
|
|
1446
|
+
status: DEFAULT_STATUS,
|
|
1447
|
+
messages: cloneArray(input.messages ?? []),
|
|
1448
|
+
createdAt: timestamp,
|
|
1449
|
+
updatedAt: timestamp,
|
|
1450
|
+
...input.runtimeContext ? { runtimeContext: cloneValue(input.runtimeContext) } : {},
|
|
1451
|
+
...input.cssContextPrompt?.trim() ? { cssContextPrompt: input.cssContextPrompt.trim() } : {},
|
|
1452
|
+
...input.pageUrl ? { pageUrl: input.pageUrl } : {},
|
|
1453
|
+
...input.route ? { route: input.route } : {}
|
|
1454
|
+
};
|
|
1455
|
+
sessions.set(session.id, session);
|
|
1456
|
+
emit({ type: "session-created", session });
|
|
1457
|
+
return cloneSession(session);
|
|
1458
|
+
},
|
|
1459
|
+
getSession(id) {
|
|
1460
|
+
const session = sessions.get(id);
|
|
1461
|
+
return session ? cloneSession(session) : null;
|
|
1462
|
+
},
|
|
1463
|
+
listSessions(options2 = {}) {
|
|
1464
|
+
const statuses = normalizeStatuses(options2.status);
|
|
1465
|
+
return [...sessions.values()].filter((session) => statuses ? statuses.has(session.status) : true).sort((left, right) => right.updatedAt - left.updatedAt).map((session) => cloneSession(session));
|
|
1466
|
+
},
|
|
1467
|
+
async claimNextSession(options2 = {}) {
|
|
1468
|
+
const statuses = normalizeStatuses(DEFAULT_STATUS);
|
|
1469
|
+
const existingSession = findNewestMatchingSession(statuses);
|
|
1470
|
+
if (existingSession) {
|
|
1471
|
+
return {
|
|
1472
|
+
session: claimSession(existingSession.id, statuses),
|
|
1473
|
+
timedOut: false,
|
|
1474
|
+
matchedExisting: true
|
|
1475
|
+
};
|
|
1476
|
+
}
|
|
1477
|
+
const timeoutMs = normalizeTimeoutMs(options2.timeoutMs);
|
|
1478
|
+
if (timeoutMs === 0) {
|
|
1479
|
+
return {
|
|
1480
|
+
session: null,
|
|
1481
|
+
timedOut: true,
|
|
1482
|
+
matchedExisting: false
|
|
1483
|
+
};
|
|
1484
|
+
}
|
|
1485
|
+
return await new Promise((resolve2) => {
|
|
1486
|
+
let settled = false;
|
|
1487
|
+
let timeout = null;
|
|
1488
|
+
const finish = (result) => {
|
|
1489
|
+
if (settled) return;
|
|
1490
|
+
settled = true;
|
|
1491
|
+
unsubscribe();
|
|
1492
|
+
if (timeout) {
|
|
1493
|
+
clearTimeout(timeout);
|
|
1494
|
+
}
|
|
1495
|
+
resolve2(result);
|
|
1496
|
+
};
|
|
1497
|
+
const unsubscribe = this.subscribe((event) => {
|
|
1498
|
+
const session = claimSession(event.session.id, statuses);
|
|
1499
|
+
if (!session) return;
|
|
1500
|
+
finish({
|
|
1501
|
+
session,
|
|
1502
|
+
timedOut: false,
|
|
1503
|
+
matchedExisting: false,
|
|
1504
|
+
event: event.type
|
|
1505
|
+
});
|
|
1506
|
+
});
|
|
1507
|
+
if (timeoutMs !== null) {
|
|
1508
|
+
timeout = setTimeout(() => {
|
|
1509
|
+
finish({
|
|
1510
|
+
session: null,
|
|
1511
|
+
timedOut: true,
|
|
1512
|
+
matchedExisting: false
|
|
1513
|
+
});
|
|
1514
|
+
}, timeoutMs);
|
|
1515
|
+
}
|
|
1516
|
+
});
|
|
1517
|
+
},
|
|
1518
|
+
appendMessage(id, input) {
|
|
1519
|
+
const session = sessions.get(id);
|
|
1520
|
+
if (!session) return null;
|
|
1521
|
+
const timestamp = now();
|
|
1522
|
+
session.messages.push({
|
|
1523
|
+
id: createId(),
|
|
1524
|
+
role: input.role,
|
|
1525
|
+
text: input.text,
|
|
1526
|
+
createdAt: timestamp
|
|
1527
|
+
});
|
|
1528
|
+
session.updatedAt = timestamp;
|
|
1529
|
+
if (input.role === "agent" && isPendingLikeStatus(session.status)) {
|
|
1530
|
+
session.status = "in_progress";
|
|
1531
|
+
}
|
|
1532
|
+
emit({ type: "session-message-appended", session });
|
|
1533
|
+
return cloneSession(session);
|
|
1534
|
+
},
|
|
1535
|
+
updateStatus(id, status) {
|
|
1536
|
+
return updateSessionStatus(id, status);
|
|
1537
|
+
},
|
|
1538
|
+
subscribe(listener) {
|
|
1539
|
+
listeners.add(listener);
|
|
1540
|
+
return () => {
|
|
1541
|
+
listeners.delete(listener);
|
|
1542
|
+
};
|
|
1543
|
+
},
|
|
1544
|
+
clear() {
|
|
1545
|
+
sessions.clear();
|
|
1546
|
+
listeners.clear();
|
|
1547
|
+
}
|
|
1548
|
+
};
|
|
1549
|
+
return store;
|
|
1550
|
+
}
|
|
1551
|
+
var annotationSessionStore = createAnnotationSessionStore();
|
|
1552
|
+
function normalizeStatuses(status) {
|
|
1553
|
+
if (!status) return null;
|
|
1554
|
+
return new Set(Array.isArray(status) ? status : [status]);
|
|
1555
|
+
}
|
|
1556
|
+
function normalizeTimeoutMs(value) {
|
|
1557
|
+
if (value === void 0) return null;
|
|
1558
|
+
if (!Number.isFinite(value)) return 0;
|
|
1559
|
+
return Math.max(0, Math.floor(value));
|
|
1560
|
+
}
|
|
1561
|
+
function isPendingLikeStatus(status) {
|
|
1562
|
+
return status === "pending" || status === "acknowledged";
|
|
1563
|
+
}
|
|
1564
|
+
function hasAgentReply(session) {
|
|
1565
|
+
return session.messages.some((message) => message.role === "agent" && Boolean(message.text?.trim()));
|
|
1566
|
+
}
|
|
1567
|
+
function createRandomId() {
|
|
1568
|
+
return `annotation-session-${Math.random().toString(36).slice(2, 10)}`;
|
|
1569
|
+
}
|
|
1570
|
+
function cloneSession(session) {
|
|
1571
|
+
return cloneValue(session);
|
|
1572
|
+
}
|
|
1573
|
+
function cloneArray(value) {
|
|
1574
|
+
return cloneValue(value);
|
|
1575
|
+
}
|
|
1576
|
+
function cloneValue(value) {
|
|
1577
|
+
if (typeof structuredClone === "function") {
|
|
1578
|
+
return structuredClone(value);
|
|
1579
|
+
}
|
|
1580
|
+
return JSON.parse(JSON.stringify(value));
|
|
1581
|
+
}
|
|
1582
|
+
|
|
1399
1583
|
// src/server/annotation-dispatch.ts
|
|
1400
1584
|
var AnnotationDispatchError = class extends Error {
|
|
1401
1585
|
constructor(message, errorCode) {
|
|
@@ -1404,20 +1588,30 @@ var AnnotationDispatchError = class extends Error {
|
|
|
1404
1588
|
this.errorCode = errorCode;
|
|
1405
1589
|
}
|
|
1406
1590
|
};
|
|
1407
|
-
async function dispatchAnnotationsToAi(req, state) {
|
|
1591
|
+
async function dispatchAnnotationsToAi(req, state, store = annotationSessionStore) {
|
|
1408
1592
|
try {
|
|
1409
1593
|
validateAnnotationDispatchRequest(req, state);
|
|
1410
1594
|
const batch = normalizeAnnotationBatch(req);
|
|
1411
1595
|
const prompt = buildAnnotationBatchPrompt(batch);
|
|
1596
|
+
const deliveryMode = normalizeDeliveryMode(req.deliveryMode);
|
|
1597
|
+
const session = store.createSession({
|
|
1598
|
+
instruction: batch.instruction,
|
|
1599
|
+
annotations: toSessionAnnotations(batch.annotations),
|
|
1600
|
+
deliveryMode,
|
|
1601
|
+
...batch.runtimeContext ? { runtimeContext: batch.runtimeContext } : {},
|
|
1602
|
+
...batch.cssContextPrompt ? { cssContextPrompt: batch.cssContextPrompt } : {}
|
|
1603
|
+
});
|
|
1412
1604
|
const representativeTarget = batch.annotations[0]?.targets[0];
|
|
1413
|
-
const
|
|
1414
|
-
return dispatchPromptThroughIde(runtime, {
|
|
1605
|
+
const dispatchResult = deliveryMode === "ide" ? dispatchPromptThroughIde(resolvePromptDispatchRuntime(state), {
|
|
1415
1606
|
prompt,
|
|
1416
1607
|
...representativeTarget?.file ? { filePath: representativeTarget.file } : {},
|
|
1417
1608
|
...representativeTarget?.line ? { line: representativeTarget.line } : {},
|
|
1418
|
-
...representativeTarget?.column ? { column: representativeTarget.column } : {}
|
|
1419
|
-
|
|
1420
|
-
|
|
1609
|
+
...representativeTarget?.column ? { column: representativeTarget.column } : {}
|
|
1610
|
+
}) : { success: true };
|
|
1611
|
+
return {
|
|
1612
|
+
...dispatchResult,
|
|
1613
|
+
session: toSessionSummary(session)
|
|
1614
|
+
};
|
|
1421
1615
|
} catch (error) {
|
|
1422
1616
|
return {
|
|
1423
1617
|
success: false,
|
|
@@ -1426,6 +1620,41 @@ async function dispatchAnnotationsToAi(req, state) {
|
|
|
1426
1620
|
};
|
|
1427
1621
|
}
|
|
1428
1622
|
}
|
|
1623
|
+
function normalizeDeliveryMode(input) {
|
|
1624
|
+
return input === "agent" ? "agent" : "ide";
|
|
1625
|
+
}
|
|
1626
|
+
function toSessionAnnotations(annotations) {
|
|
1627
|
+
return annotations.map((annotation) => ({
|
|
1628
|
+
id: `annotation-${annotation.index}`,
|
|
1629
|
+
note: annotation.note,
|
|
1630
|
+
intent: annotation.intent,
|
|
1631
|
+
targets: annotation.targets.map((target, targetIndex) => ({
|
|
1632
|
+
id: `annotation-${annotation.index}-target-${targetIndex + 1}`,
|
|
1633
|
+
label: target.label ?? "Unknown target",
|
|
1634
|
+
location: {
|
|
1635
|
+
file: target.file,
|
|
1636
|
+
line: target.line,
|
|
1637
|
+
column: target.column
|
|
1638
|
+
},
|
|
1639
|
+
...target.selector ? { selector: target.selector } : {},
|
|
1640
|
+
...target.snippet ? { snippet: target.snippet } : {},
|
|
1641
|
+
rect: {
|
|
1642
|
+
x: 0,
|
|
1643
|
+
y: 0,
|
|
1644
|
+
width: 0,
|
|
1645
|
+
height: 0
|
|
1646
|
+
}
|
|
1647
|
+
}))
|
|
1648
|
+
}));
|
|
1649
|
+
}
|
|
1650
|
+
function toSessionSummary(session) {
|
|
1651
|
+
return {
|
|
1652
|
+
id: session.id,
|
|
1653
|
+
status: session.status,
|
|
1654
|
+
createdAt: session.createdAt,
|
|
1655
|
+
updatedAt: session.updatedAt
|
|
1656
|
+
};
|
|
1657
|
+
}
|
|
1429
1658
|
function validateAnnotationDispatchRequest(req, state) {
|
|
1430
1659
|
if (!req.annotations.length) {
|
|
1431
1660
|
throw new AnnotationDispatchError("At least one annotation is required.", "INVALID_REQUEST");
|
|
@@ -1446,9 +1675,7 @@ function validateAnnotationDispatchRequest(req, state) {
|
|
|
1446
1675
|
function normalizeAnnotationBatch(req) {
|
|
1447
1676
|
return {
|
|
1448
1677
|
instruction: req.instruction?.trim() ?? "",
|
|
1449
|
-
responseMode: req.responseMode ?? "unified",
|
|
1450
1678
|
...req.runtimeContext ? { runtimeContext: req.runtimeContext } : {},
|
|
1451
|
-
...req.screenshotContext ? { screenshotContext: req.screenshotContext } : {},
|
|
1452
1679
|
...req.cssContextPrompt?.trim() ? { cssContextPrompt: req.cssContextPrompt.trim() } : {},
|
|
1453
1680
|
annotations: req.annotations.map((annotation, index) => ({
|
|
1454
1681
|
index: index + 1,
|
|
@@ -1470,12 +1697,9 @@ function buildAnnotationBatchPrompt(batch) {
|
|
|
1470
1697
|
const prompt = batch.instruction ? `${batch.instruction}
|
|
1471
1698
|
|
|
1472
1699
|
${body}` : body;
|
|
1473
|
-
return
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
batch.cssContextPrompt
|
|
1477
|
-
),
|
|
1478
|
-
batch.screenshotContext
|
|
1700
|
+
return appendCssContextSection(
|
|
1701
|
+
appendRuntimeContextSection(prompt, batch.runtimeContext),
|
|
1702
|
+
batch.cssContextPrompt
|
|
1479
1703
|
);
|
|
1480
1704
|
}
|
|
1481
1705
|
function appendCssContextSection(prompt, cssContextPrompt) {
|
|
@@ -1502,20 +1726,6 @@ function buildSelectedElementsPrompt(annotations) {
|
|
|
1502
1726
|
}
|
|
1503
1727
|
return lines.join("\n");
|
|
1504
1728
|
}
|
|
1505
|
-
function appendScreenshotContextSection(prompt, screenshotContext) {
|
|
1506
|
-
if (!screenshotContext || !screenshotContext.imageDataUrl && !screenshotContext.imageAssetId) {
|
|
1507
|
-
return prompt;
|
|
1508
|
-
}
|
|
1509
|
-
const lines = [
|
|
1510
|
-
"Visual screenshot context attached:",
|
|
1511
|
-
`- capturedAt=${screenshotContext.capturedAt}`,
|
|
1512
|
-
`- mimeType=${screenshotContext.mimeType}`,
|
|
1513
|
-
...screenshotContext.imageAssetId ? [`- imageAssetId=${screenshotContext.imageAssetId}`] : []
|
|
1514
|
-
];
|
|
1515
|
-
return `${prompt}
|
|
1516
|
-
|
|
1517
|
-
${lines.join("\n")}`;
|
|
1518
|
-
}
|
|
1519
1729
|
function appendRuntimeContextSection(prompt, runtimeContext) {
|
|
1520
1730
|
if (!runtimeContext?.records.length) {
|
|
1521
1731
|
return prompt;
|
|
@@ -1563,7 +1773,7 @@ async function buildClientConfig(serverState2) {
|
|
|
1563
1773
|
...info,
|
|
1564
1774
|
prompts: resolveIntents(promptsConfig),
|
|
1565
1775
|
hotKeys: userConfig["inspector.hotKey"] ?? "alt",
|
|
1566
|
-
|
|
1776
|
+
annotateDeliveryMode: userConfig["annotate.deliveryMode"] ?? "both",
|
|
1567
1777
|
includeSnippet: userConfig["prompt.includeSnippet"] ?? false,
|
|
1568
1778
|
runtimeContext: {
|
|
1569
1779
|
enabled: true,
|
|
@@ -1571,10 +1781,6 @@ async function buildClientConfig(serverState2) {
|
|
|
1571
1781
|
maxRuntimeErrors: 3,
|
|
1572
1782
|
maxFailedRequests: 2
|
|
1573
1783
|
},
|
|
1574
|
-
screenshotContext: {
|
|
1575
|
-
enabled: false
|
|
1576
|
-
},
|
|
1577
|
-
annotationResponseMode: userConfig["prompt.annotationResponseMode"] ?? "unified",
|
|
1578
1784
|
autoSend: userConfig["prompt.autoSend"] ?? false
|
|
1579
1785
|
};
|
|
1580
1786
|
}
|
|
@@ -1619,7 +1825,7 @@ function handleOpenFileRequest(body, serverState2) {
|
|
|
1619
1825
|
else if (rawEditorHint === "vscodium") editorHint = "codium";
|
|
1620
1826
|
else if (rawEditorHint === "trae-cn" || rawEditorHint === "trae") editorHint = "trae";
|
|
1621
1827
|
serverLogger2.debug(
|
|
1622
|
-
`
|
|
1828
|
+
`SOURCE_OPEN: activeIde=${activeIde}, activeIdeScheme=${activeIdeScheme}, configuredIde=${configuredIde} -> rawEditorHint=${rawEditorHint}, finalEditorHint=${editorHint}`
|
|
1623
1829
|
);
|
|
1624
1830
|
if (VSCODE_FAMILY_SCHEMES.includes(rawEditorHint)) {
|
|
1625
1831
|
let normalizedPath = absolutePath.replace(/\\/g, "/");
|
|
@@ -1628,7 +1834,7 @@ function handleOpenFileRequest(body, serverState2) {
|
|
|
1628
1834
|
}
|
|
1629
1835
|
const encodedPath = encodeURI(normalizedPath);
|
|
1630
1836
|
const uri = `${rawEditorHint}://file${encodedPath}:${body.line}:${body.column}`;
|
|
1631
|
-
serverLogger2.debug(`
|
|
1837
|
+
serverLogger2.debug(`SOURCE_OPEN: Bypassing launchIDE, using URI scheme directly: ${uri}`);
|
|
1632
1838
|
try {
|
|
1633
1839
|
if (process.platform === "darwin") {
|
|
1634
1840
|
(0, import_node_child_process2.execFileSync)("open", [uri]);
|
|
@@ -1638,7 +1844,7 @@ function handleOpenFileRequest(body, serverState2) {
|
|
|
1638
1844
|
(0, import_node_child_process2.execFileSync)("xdg-open", [uri]);
|
|
1639
1845
|
}
|
|
1640
1846
|
} catch (e) {
|
|
1641
|
-
serverLogger2.error(`Failed to launch URI for
|
|
1847
|
+
serverLogger2.error(`Failed to launch URI for SOURCE_OPEN (${uri}):`, e);
|
|
1642
1848
|
(0, import_launch_ide2.launchIDE)({
|
|
1643
1849
|
file: absolutePath,
|
|
1644
1850
|
line: body.line,
|
|
@@ -1693,8 +1899,27 @@ function resolveProjectRoot() {
|
|
|
1693
1899
|
return gitRoot;
|
|
1694
1900
|
}
|
|
1695
1901
|
|
|
1902
|
+
// src/server/server-url.ts
|
|
1903
|
+
function resolveServerHost(cwd, configRoot) {
|
|
1904
|
+
const userConfig = loadUserConfigSync(false, cwd, configRoot);
|
|
1905
|
+
const configuredHost = userConfig["server.host"]?.trim();
|
|
1906
|
+
if (configuredHost) return configuredHost;
|
|
1907
|
+
if (process.env["VITEST"]) return "127.0.0.1";
|
|
1908
|
+
return "127.0.0.1";
|
|
1909
|
+
}
|
|
1910
|
+
function resolvePublicServerUrl(args) {
|
|
1911
|
+
const userConfig = loadUserConfigSync(false, args.cwd, args.configRoot);
|
|
1912
|
+
const configuredPublicUrl = userConfig["server.publicUrl"]?.trim();
|
|
1913
|
+
if (configuredPublicUrl) {
|
|
1914
|
+
return configuredPublicUrl.replace(/\/$/, "");
|
|
1915
|
+
}
|
|
1916
|
+
const host = resolveServerHost(args.cwd, args.configRoot);
|
|
1917
|
+
return `http://${host}:${args.port}`;
|
|
1918
|
+
}
|
|
1919
|
+
|
|
1696
1920
|
// src/server/index.ts
|
|
1697
1921
|
var serverLogger4 = createLogger("inspecto:server", { logLevel: getGlobalLogLevel() });
|
|
1922
|
+
var PORT_FILE_NAME = "inspecto.port.json";
|
|
1698
1923
|
var serverState = {
|
|
1699
1924
|
port: null,
|
|
1700
1925
|
running: false,
|
|
@@ -1703,6 +1928,42 @@ var serverState = {
|
|
|
1703
1928
|
cwd: process.cwd()
|
|
1704
1929
|
};
|
|
1705
1930
|
var serverInstance = null;
|
|
1931
|
+
function getPortFilePath() {
|
|
1932
|
+
return import_node_path7.default.join(import_node_os2.default.tmpdir(), PORT_FILE_NAME);
|
|
1933
|
+
}
|
|
1934
|
+
function getProjectRootHash() {
|
|
1935
|
+
if (!serverState.projectRoot) return null;
|
|
1936
|
+
return import_node_crypto2.default.createHash("md5").update(serverState.projectRoot).digest("hex");
|
|
1937
|
+
}
|
|
1938
|
+
function readPortData(portFile) {
|
|
1939
|
+
if (!import_node_fs4.default.existsSync(portFile)) return {};
|
|
1940
|
+
try {
|
|
1941
|
+
return JSON.parse(import_node_fs4.default.readFileSync(portFile, "utf-8"));
|
|
1942
|
+
} catch {
|
|
1943
|
+
return {};
|
|
1944
|
+
}
|
|
1945
|
+
}
|
|
1946
|
+
function writeProjectPort(port) {
|
|
1947
|
+
const rootHash = getProjectRootHash();
|
|
1948
|
+
if (!rootHash) return;
|
|
1949
|
+
const portFile = getPortFilePath();
|
|
1950
|
+
const portData = readPortData(portFile);
|
|
1951
|
+
portData[rootHash] = port;
|
|
1952
|
+
import_node_fs4.default.writeFileSync(portFile, JSON.stringify(portData, null, 2), "utf-8");
|
|
1953
|
+
}
|
|
1954
|
+
function removeProjectPort() {
|
|
1955
|
+
const rootHash = getProjectRootHash();
|
|
1956
|
+
if (!rootHash) return;
|
|
1957
|
+
const portFile = getPortFilePath();
|
|
1958
|
+
if (!import_node_fs4.default.existsSync(portFile)) return;
|
|
1959
|
+
const portData = readPortData(portFile);
|
|
1960
|
+
delete portData[rootHash];
|
|
1961
|
+
if (Object.keys(portData).length === 0) {
|
|
1962
|
+
import_node_fs4.default.unlinkSync(portFile);
|
|
1963
|
+
} else {
|
|
1964
|
+
import_node_fs4.default.writeFileSync(portFile, JSON.stringify(portData, null, 2), "utf-8");
|
|
1965
|
+
}
|
|
1966
|
+
}
|
|
1706
1967
|
async function startServer() {
|
|
1707
1968
|
if (serverState.running && serverState.port !== null) {
|
|
1708
1969
|
return serverState.port;
|
|
@@ -1710,6 +1971,7 @@ async function startServer() {
|
|
|
1710
1971
|
serverState.projectRoot = resolveProjectRoot();
|
|
1711
1972
|
serverState.configRoot = serverState.projectRoot;
|
|
1712
1973
|
serverState.cwd = process.cwd();
|
|
1974
|
+
const serverHost = resolveServerHost(serverState.cwd, serverState.configRoot);
|
|
1713
1975
|
import_portfinder.default.basePort = 5678;
|
|
1714
1976
|
const port = await import_portfinder.default.getPortPromise();
|
|
1715
1977
|
watchConfig(
|
|
@@ -1736,7 +1998,7 @@ async function startServer() {
|
|
|
1736
1998
|
});
|
|
1737
1999
|
});
|
|
1738
2000
|
await new Promise((resolve2, reject) => {
|
|
1739
|
-
serverInstance.listen(port,
|
|
2001
|
+
serverInstance.listen(port, serverHost, () => {
|
|
1740
2002
|
serverInstance.unref();
|
|
1741
2003
|
resolve2();
|
|
1742
2004
|
});
|
|
@@ -1747,37 +2009,18 @@ async function startServer() {
|
|
|
1747
2009
|
});
|
|
1748
2010
|
serverState.port = port;
|
|
1749
2011
|
serverState.running = true;
|
|
1750
|
-
const portFile = import_node_path7.default.join(import_node_os2.default.tmpdir(), "inspecto.port.json");
|
|
1751
2012
|
try {
|
|
1752
|
-
|
|
1753
|
-
if (import_node_fs4.default.existsSync(portFile)) {
|
|
1754
|
-
try {
|
|
1755
|
-
portData = JSON.parse(import_node_fs4.default.readFileSync(portFile, "utf-8"));
|
|
1756
|
-
} catch (_e) {
|
|
1757
|
-
}
|
|
1758
|
-
}
|
|
1759
|
-
const rootHash = import_node_crypto2.default.createHash("md5").update(serverState.projectRoot).digest("hex");
|
|
1760
|
-
portData[rootHash] = port;
|
|
1761
|
-
import_node_fs4.default.writeFileSync(portFile, JSON.stringify(portData, null, 2), "utf-8");
|
|
2013
|
+
writeProjectPort(port);
|
|
1762
2014
|
} catch (_e) {
|
|
1763
2015
|
serverLogger4.warn("Failed to write port file:", _e);
|
|
1764
2016
|
}
|
|
1765
2017
|
process.once("exit", () => {
|
|
1766
2018
|
try {
|
|
1767
|
-
|
|
1768
|
-
const portData = JSON.parse(import_node_fs4.default.readFileSync(portFile, "utf-8"));
|
|
1769
|
-
const rootHash = import_node_crypto2.default.createHash("md5").update(serverState.projectRoot).digest("hex");
|
|
1770
|
-
delete portData[rootHash];
|
|
1771
|
-
if (Object.keys(portData).length === 0) {
|
|
1772
|
-
import_node_fs4.default.unlinkSync(portFile);
|
|
1773
|
-
} else {
|
|
1774
|
-
import_node_fs4.default.writeFileSync(portFile, JSON.stringify(portData, null, 2), "utf-8");
|
|
1775
|
-
}
|
|
1776
|
-
}
|
|
2019
|
+
removeProjectPort();
|
|
1777
2020
|
} catch {
|
|
1778
2021
|
}
|
|
1779
2022
|
});
|
|
1780
|
-
serverLogger4.info(`server running at http
|
|
2023
|
+
serverLogger4.info(`server running at http://${serverHost}:${port}`);
|
|
1781
2024
|
return port;
|
|
1782
2025
|
}
|
|
1783
2026
|
async function readBody(req) {
|
|
@@ -1829,7 +2072,7 @@ async function handleRequest(url, req, res) {
|
|
|
1829
2072
|
}
|
|
1830
2073
|
return;
|
|
1831
2074
|
}
|
|
1832
|
-
if (pathname === import_types2.INSPECTO_API_PATHS.IDE_OPEN && req.method === "POST") {
|
|
2075
|
+
if ((pathname === import_types2.INSPECTO_API_PATHS.SOURCE_OPEN || pathname === import_types2.INSPECTO_API_PATHS.IDE_OPEN) && req.method === "POST") {
|
|
1833
2076
|
let body;
|
|
1834
2077
|
try {
|
|
1835
2078
|
body = JSON.parse(await readBody(req));
|
|
@@ -1842,7 +2085,7 @@ async function handleRequest(url, req, res) {
|
|
|
1842
2085
|
handleOpenFileRequest(body, serverState);
|
|
1843
2086
|
} catch (err) {
|
|
1844
2087
|
serverLogger4.warn(
|
|
1845
|
-
`Security: Blocked path traversal attempt in
|
|
2088
|
+
`Security: Blocked path traversal attempt in SOURCE_OPEN: ${body.file}. Reason: ${err.message}`
|
|
1846
2089
|
);
|
|
1847
2090
|
res.writeHead(403, { "Content-Type": "application/json" });
|
|
1848
2091
|
res.end(JSON.stringify({ error: "Access denied: File is outside of project workspace" }));
|
|
@@ -1916,6 +2159,212 @@ async function handleRequest(url, req, res) {
|
|
|
1916
2159
|
}
|
|
1917
2160
|
return;
|
|
1918
2161
|
}
|
|
2162
|
+
if (pathname === import_types2.INSPECTO_API_PATHS.SESSION_CLAIM_NEXT && req.method === "POST") {
|
|
2163
|
+
try {
|
|
2164
|
+
const rawBody = await readBody(req);
|
|
2165
|
+
const body = rawBody ? JSON.parse(rawBody) : {};
|
|
2166
|
+
const timeoutMs = normalizeSessionClaimTimeout(
|
|
2167
|
+
body.timeoutMs === void 0 ? null : String(body.timeoutMs)
|
|
2168
|
+
);
|
|
2169
|
+
const result = await annotationSessionStore.claimNextSession({
|
|
2170
|
+
...timeoutMs !== void 0 ? { timeoutMs } : {}
|
|
2171
|
+
});
|
|
2172
|
+
res.writeHead(200, { "Content-Type": "application/json" });
|
|
2173
|
+
res.end(
|
|
2174
|
+
JSON.stringify({
|
|
2175
|
+
success: true,
|
|
2176
|
+
timedOut: result.timedOut,
|
|
2177
|
+
matchedExisting: result.matchedExisting,
|
|
2178
|
+
...result.event ? { event: result.event } : {},
|
|
2179
|
+
...result.session ? { session: result.session } : {}
|
|
2180
|
+
})
|
|
2181
|
+
);
|
|
2182
|
+
} catch (e) {
|
|
2183
|
+
serverLogger4.error(`Error parsing session claim request:`, e);
|
|
2184
|
+
res.writeHead(400, { "Content-Type": "application/json" });
|
|
2185
|
+
res.end(JSON.stringify({ success: false, error: "Invalid JSON body" }));
|
|
2186
|
+
}
|
|
2187
|
+
return;
|
|
2188
|
+
}
|
|
2189
|
+
if (pathname === import_types2.INSPECTO_API_PATHS.SESSION_EVENTS && req.method === "GET") {
|
|
2190
|
+
const statusParam = url.searchParams.getAll("status");
|
|
2191
|
+
const statuses = statusParam.length ? new Set(statusParam) : null;
|
|
2192
|
+
const sessionId = url.searchParams.get("sessionId")?.trim() || null;
|
|
2193
|
+
res.writeHead(200, {
|
|
2194
|
+
"Content-Type": "text/event-stream",
|
|
2195
|
+
"Cache-Control": "no-cache",
|
|
2196
|
+
Connection: "keep-alive"
|
|
2197
|
+
});
|
|
2198
|
+
res.write(`event: ready
|
|
2199
|
+
data: ${JSON.stringify({ ok: true })}
|
|
2200
|
+
|
|
2201
|
+
`);
|
|
2202
|
+
const unsubscribe = annotationSessionStore.subscribe((event) => {
|
|
2203
|
+
if (sessionId && event.session.id !== sessionId) {
|
|
2204
|
+
return;
|
|
2205
|
+
}
|
|
2206
|
+
if (statuses && !statuses.has(event.session.status)) {
|
|
2207
|
+
return;
|
|
2208
|
+
}
|
|
2209
|
+
res.write(formatSessionSseEvent(event));
|
|
2210
|
+
});
|
|
2211
|
+
req.on("close", () => {
|
|
2212
|
+
unsubscribe();
|
|
2213
|
+
res.end();
|
|
2214
|
+
});
|
|
2215
|
+
return;
|
|
2216
|
+
}
|
|
2217
|
+
if (pathname === import_types2.INSPECTO_API_PATHS.SESSIONS && req.method === "GET") {
|
|
2218
|
+
const statusParam = url.searchParams.getAll("status");
|
|
2219
|
+
const sessions = annotationSessionStore.listSessions(
|
|
2220
|
+
statusParam.length ? {
|
|
2221
|
+
status: statusParam
|
|
2222
|
+
} : void 0
|
|
2223
|
+
);
|
|
2224
|
+
res.writeHead(200, { "Content-Type": "application/json" });
|
|
2225
|
+
res.end(JSON.stringify({ success: true, sessions }));
|
|
2226
|
+
return;
|
|
2227
|
+
}
|
|
2228
|
+
if (pathname.startsWith(`${import_types2.INSPECTO_API_PATHS.SESSIONS}/`) && req.method === "GET") {
|
|
2229
|
+
const sessionId = pathname.substring(import_types2.INSPECTO_API_PATHS.SESSIONS.length + 1);
|
|
2230
|
+
const session = annotationSessionStore.getSession(sessionId);
|
|
2231
|
+
if (!session) {
|
|
2232
|
+
res.writeHead(404, { "Content-Type": "application/json" });
|
|
2233
|
+
res.end(JSON.stringify({ success: false, error: "Session not found" }));
|
|
2234
|
+
return;
|
|
2235
|
+
}
|
|
2236
|
+
res.writeHead(200, { "Content-Type": "application/json" });
|
|
2237
|
+
res.end(JSON.stringify({ success: true, session }));
|
|
2238
|
+
return;
|
|
2239
|
+
}
|
|
2240
|
+
if (pathname.startsWith(`${import_types2.INSPECTO_API_PATHS.SESSIONS}/`) && pathname.endsWith(import_types2.INSPECTO_API_PATHS.SESSION_REPLY_SUFFIX) && req.method === "POST") {
|
|
2241
|
+
const sessionId = pathname.slice(
|
|
2242
|
+
import_types2.INSPECTO_API_PATHS.SESSIONS.length + 1,
|
|
2243
|
+
-import_types2.INSPECTO_API_PATHS.SESSION_REPLY_SUFFIX.length
|
|
2244
|
+
);
|
|
2245
|
+
try {
|
|
2246
|
+
const rawBody = await readBody(req);
|
|
2247
|
+
const body = JSON.parse(rawBody);
|
|
2248
|
+
if (!isAnnotationThreadRole(body.role)) {
|
|
2249
|
+
res.writeHead(400, { "Content-Type": "application/json" });
|
|
2250
|
+
res.end(JSON.stringify({ success: false, error: "Reply role is invalid." }));
|
|
2251
|
+
return;
|
|
2252
|
+
}
|
|
2253
|
+
if (!body.text?.trim()) {
|
|
2254
|
+
res.writeHead(400, { "Content-Type": "application/json" });
|
|
2255
|
+
res.end(JSON.stringify({ success: false, error: "Reply text is required." }));
|
|
2256
|
+
return;
|
|
2257
|
+
}
|
|
2258
|
+
const session = annotationSessionStore.appendMessage(sessionId, {
|
|
2259
|
+
role: body.role,
|
|
2260
|
+
text: body.text.trim()
|
|
2261
|
+
});
|
|
2262
|
+
if (!session) {
|
|
2263
|
+
res.writeHead(404, { "Content-Type": "application/json" });
|
|
2264
|
+
res.end(JSON.stringify({ success: false, error: "Session not found" }));
|
|
2265
|
+
return;
|
|
2266
|
+
}
|
|
2267
|
+
res.writeHead(200, { "Content-Type": "application/json" });
|
|
2268
|
+
res.end(JSON.stringify({ success: true, session }));
|
|
2269
|
+
} catch (e) {
|
|
2270
|
+
serverLogger4.error(`Error parsing session reply request:`, e);
|
|
2271
|
+
res.writeHead(400, { "Content-Type": "application/json" });
|
|
2272
|
+
res.end(JSON.stringify({ success: false, error: "Invalid JSON body" }));
|
|
2273
|
+
}
|
|
2274
|
+
return;
|
|
2275
|
+
}
|
|
2276
|
+
if (pathname.startsWith(`${import_types2.INSPECTO_API_PATHS.SESSIONS}/`) && pathname.endsWith(import_types2.INSPECTO_API_PATHS.SESSION_RESOLVE_SUFFIX) && req.method === "POST") {
|
|
2277
|
+
const sessionId = pathname.slice(
|
|
2278
|
+
import_types2.INSPECTO_API_PATHS.SESSIONS.length + 1,
|
|
2279
|
+
-import_types2.INSPECTO_API_PATHS.SESSION_RESOLVE_SUFFIX.length
|
|
2280
|
+
);
|
|
2281
|
+
try {
|
|
2282
|
+
const rawBody = await readBody(req);
|
|
2283
|
+
const body = rawBody ? JSON.parse(rawBody) : {};
|
|
2284
|
+
const message = body.message?.trim();
|
|
2285
|
+
const existingSession = annotationSessionStore.getSession(sessionId);
|
|
2286
|
+
if (!existingSession) {
|
|
2287
|
+
res.writeHead(404, { "Content-Type": "application/json" });
|
|
2288
|
+
res.end(JSON.stringify({ success: false, error: "Session not found" }));
|
|
2289
|
+
return;
|
|
2290
|
+
}
|
|
2291
|
+
if (!message && !hasAgentReply(existingSession)) {
|
|
2292
|
+
res.writeHead(400, { "Content-Type": "application/json" });
|
|
2293
|
+
res.end(
|
|
2294
|
+
JSON.stringify({
|
|
2295
|
+
success: false,
|
|
2296
|
+
error: "Resolve message is required until an agent reply is recorded."
|
|
2297
|
+
})
|
|
2298
|
+
);
|
|
2299
|
+
return;
|
|
2300
|
+
}
|
|
2301
|
+
if (message) {
|
|
2302
|
+
const repliedSession = annotationSessionStore.appendMessage(sessionId, {
|
|
2303
|
+
role: "agent",
|
|
2304
|
+
text: message
|
|
2305
|
+
});
|
|
2306
|
+
if (!repliedSession) {
|
|
2307
|
+
res.writeHead(404, { "Content-Type": "application/json" });
|
|
2308
|
+
res.end(JSON.stringify({ success: false, error: "Session not found" }));
|
|
2309
|
+
return;
|
|
2310
|
+
}
|
|
2311
|
+
}
|
|
2312
|
+
const session = annotationSessionStore.updateStatus(sessionId, "resolved");
|
|
2313
|
+
if (!session) {
|
|
2314
|
+
res.writeHead(404, { "Content-Type": "application/json" });
|
|
2315
|
+
res.end(JSON.stringify({ success: false, error: "Session not found" }));
|
|
2316
|
+
return;
|
|
2317
|
+
}
|
|
2318
|
+
res.writeHead(200, { "Content-Type": "application/json" });
|
|
2319
|
+
res.end(JSON.stringify({ success: true, session }));
|
|
2320
|
+
} catch (e) {
|
|
2321
|
+
serverLogger4.error(`Error parsing session resolve request:`, e);
|
|
2322
|
+
res.writeHead(400, { "Content-Type": "application/json" });
|
|
2323
|
+
res.end(JSON.stringify({ success: false, error: "Invalid JSON body" }));
|
|
2324
|
+
}
|
|
2325
|
+
return;
|
|
2326
|
+
}
|
|
2327
|
+
if (pathname.startsWith(`${import_types2.INSPECTO_API_PATHS.SESSIONS}/`) && pathname.endsWith(import_types2.INSPECTO_API_PATHS.SESSION_DISMISS_SUFFIX) && req.method === "POST") {
|
|
2328
|
+
const sessionId = pathname.slice(
|
|
2329
|
+
import_types2.INSPECTO_API_PATHS.SESSIONS.length + 1,
|
|
2330
|
+
-import_types2.INSPECTO_API_PATHS.SESSION_DISMISS_SUFFIX.length
|
|
2331
|
+
);
|
|
2332
|
+
try {
|
|
2333
|
+
const rawBody = await readBody(req);
|
|
2334
|
+
const body = rawBody ? JSON.parse(rawBody) : {};
|
|
2335
|
+
const message = body.message?.trim();
|
|
2336
|
+
const existingSession = annotationSessionStore.getSession(sessionId);
|
|
2337
|
+
if (!existingSession) {
|
|
2338
|
+
res.writeHead(404, { "Content-Type": "application/json" });
|
|
2339
|
+
res.end(JSON.stringify({ success: false, error: "Session not found" }));
|
|
2340
|
+
return;
|
|
2341
|
+
}
|
|
2342
|
+
if (message) {
|
|
2343
|
+
const repliedSession = annotationSessionStore.appendMessage(sessionId, {
|
|
2344
|
+
role: "agent",
|
|
2345
|
+
text: message
|
|
2346
|
+
});
|
|
2347
|
+
if (!repliedSession) {
|
|
2348
|
+
res.writeHead(404, { "Content-Type": "application/json" });
|
|
2349
|
+
res.end(JSON.stringify({ success: false, error: "Session not found" }));
|
|
2350
|
+
return;
|
|
2351
|
+
}
|
|
2352
|
+
}
|
|
2353
|
+
const session = annotationSessionStore.updateStatus(sessionId, "dismissed");
|
|
2354
|
+
if (!session) {
|
|
2355
|
+
res.writeHead(404, { "Content-Type": "application/json" });
|
|
2356
|
+
res.end(JSON.stringify({ success: false, error: "Session not found" }));
|
|
2357
|
+
return;
|
|
2358
|
+
}
|
|
2359
|
+
res.writeHead(200, { "Content-Type": "application/json" });
|
|
2360
|
+
res.end(JSON.stringify({ success: true, session }));
|
|
2361
|
+
} catch (e) {
|
|
2362
|
+
serverLogger4.error(`Error parsing session dismiss request:`, e);
|
|
2363
|
+
res.writeHead(400, { "Content-Type": "application/json" });
|
|
2364
|
+
res.end(JSON.stringify({ success: false, error: "Invalid JSON body" }));
|
|
2365
|
+
}
|
|
2366
|
+
return;
|
|
2367
|
+
}
|
|
1919
2368
|
if (pathname.startsWith(`${import_types2.INSPECTO_API_PATHS.AI_TICKET}/`) && req.method === "GET") {
|
|
1920
2369
|
const ticketId = pathname.substring(import_types2.INSPECTO_API_PATHS.AI_TICKET.length + 1);
|
|
1921
2370
|
const payloadStr = readTicket(ticketId);
|
|
@@ -1932,7 +2381,7 @@ async function handleRequest(url, req, res) {
|
|
|
1932
2381
|
res.end(JSON.stringify({ error: "not found" }));
|
|
1933
2382
|
}
|
|
1934
2383
|
async function dispatchToAi(req) {
|
|
1935
|
-
const { location, snippet, prompt
|
|
2384
|
+
const { location, snippet, prompt } = req;
|
|
1936
2385
|
const formattedPrompt = prompt ?? `Please help me with this code from \`${location.file}\` (line ${location.line}):
|
|
1937
2386
|
|
|
1938
2387
|
\`\`\`
|
|
@@ -1945,8 +2394,7 @@ ${snippet}
|
|
|
1945
2394
|
filePath: location.file,
|
|
1946
2395
|
line: location.line,
|
|
1947
2396
|
column: location.column,
|
|
1948
|
-
snippet
|
|
1949
|
-
...screenshotContext ? { screenshotContext } : {}
|
|
2397
|
+
snippet
|
|
1950
2398
|
});
|
|
1951
2399
|
}
|
|
1952
2400
|
function getBatchDispatchStatusCode(errorCode, success) {
|
|
@@ -1955,6 +2403,21 @@ function getBatchDispatchStatusCode(errorCode, success) {
|
|
|
1955
2403
|
if (errorCode === "FORBIDDEN_PATH") return 403;
|
|
1956
2404
|
return 500;
|
|
1957
2405
|
}
|
|
2406
|
+
function isAnnotationThreadRole(value) {
|
|
2407
|
+
return value === "user" || value === "agent" || value === "system";
|
|
2408
|
+
}
|
|
2409
|
+
function formatSessionSseEvent(event) {
|
|
2410
|
+
return `event: ${event.type}
|
|
2411
|
+
data: ${JSON.stringify(event)}
|
|
2412
|
+
|
|
2413
|
+
`;
|
|
2414
|
+
}
|
|
2415
|
+
function normalizeSessionClaimTimeout(value) {
|
|
2416
|
+
if (!value?.trim()) return 3e4;
|
|
2417
|
+
const parsed = Number.parseInt(value, 10);
|
|
2418
|
+
if (!Number.isFinite(parsed)) return 3e4;
|
|
2419
|
+
return Math.max(0, Math.min(parsed, 3e5));
|
|
2420
|
+
}
|
|
1958
2421
|
|
|
1959
2422
|
// src/injectors/utils.ts
|
|
1960
2423
|
var import_node_module = require("module");
|
|
@@ -1974,26 +2437,28 @@ var resolveClientModule = () => {
|
|
|
1974
2437
|
};
|
|
1975
2438
|
|
|
1976
2439
|
// src/injectors/webpack.ts
|
|
1977
|
-
function getWebpackHtmlScript(serverPort) {
|
|
2440
|
+
function getWebpackHtmlScript(serverPort, publicServerUrl) {
|
|
1978
2441
|
return `
|
|
1979
2442
|
window.__AI_INSPECTOR_PORT__ = ${serverPort};
|
|
1980
|
-
window.
|
|
1981
|
-
|
|
1982
|
-
window.InspectoClient
|
|
1983
|
-
|
|
1984
|
-
|
|
1985
|
-
|
|
1986
|
-
}
|
|
2443
|
+
window.__AI_INSPECTOR_SERVER_URL__ = '${publicServerUrl ?? `http://127.0.0.1:${serverPort}`}';
|
|
2444
|
+
window.addEventListener('load', () => {
|
|
2445
|
+
if (window.InspectoClient) {
|
|
2446
|
+
window.InspectoClient.mountInspector({
|
|
2447
|
+
serverUrl: window.__AI_INSPECTOR_SERVER_URL__,
|
|
2448
|
+
});
|
|
2449
|
+
}
|
|
2450
|
+
});
|
|
1987
2451
|
`;
|
|
1988
2452
|
}
|
|
1989
|
-
function getWebpackAssetScript(serverPort) {
|
|
2453
|
+
function getWebpackAssetScript(serverPort, publicServerUrl) {
|
|
1990
2454
|
return `
|
|
1991
2455
|
if (typeof window !== 'undefined') {
|
|
1992
2456
|
window.__AI_INSPECTOR_PORT__ = ${serverPort};
|
|
2457
|
+
window.__AI_INSPECTOR_SERVER_URL__ = '${publicServerUrl ?? `http://127.0.0.1:${serverPort}`}';
|
|
1993
2458
|
const _initInspecto = () => {
|
|
1994
2459
|
if (window.InspectoClient) {
|
|
1995
2460
|
window.InspectoClient.mountInspector({
|
|
1996
|
-
serverUrl:
|
|
2461
|
+
serverUrl: window.__AI_INSPECTOR_SERVER_URL__,
|
|
1997
2462
|
});
|
|
1998
2463
|
} else {
|
|
1999
2464
|
setTimeout(_initInspecto, 100);
|
|
@@ -2007,7 +2472,7 @@ if (typeof window !== 'undefined') {
|
|
|
2007
2472
|
}
|
|
2008
2473
|
`;
|
|
2009
2474
|
}
|
|
2010
|
-
function injectWebpack(compiler, serverPortFn, resolveClientModule2) {
|
|
2475
|
+
function injectWebpack(compiler, serverPortFn, publicServerUrlFn, resolveClientModule2) {
|
|
2011
2476
|
const inspectoClientPath = resolveClientModule2();
|
|
2012
2477
|
if (compiler.webpack && compiler.webpack.EntryPlugin) {
|
|
2013
2478
|
new compiler.webpack.EntryPlugin(compiler.context, inspectoClientPath, {
|
|
@@ -2022,11 +2487,12 @@ function injectWebpack(compiler, serverPortFn, resolveClientModule2) {
|
|
|
2022
2487
|
const hooks = HtmlWebpackPlugin.constructor.getHooks(compilation);
|
|
2023
2488
|
hooks.alterAssetTagGroups.tapPromise("inspecto-overlay", async (data) => {
|
|
2024
2489
|
const port = await serverPortFn();
|
|
2490
|
+
const publicServerUrl = publicServerUrlFn(port);
|
|
2025
2491
|
data.headTags.unshift({
|
|
2026
2492
|
tagName: "script",
|
|
2027
2493
|
voidTag: false,
|
|
2028
2494
|
meta: { plugin: "inspecto-overlay" },
|
|
2029
|
-
innerHTML: getWebpackHtmlScript(port)
|
|
2495
|
+
innerHTML: getWebpackHtmlScript(port, publicServerUrl)
|
|
2030
2496
|
});
|
|
2031
2497
|
return data;
|
|
2032
2498
|
});
|
|
@@ -2039,13 +2505,14 @@ function injectWebpack(compiler, serverPortFn, resolveClientModule2) {
|
|
|
2039
2505
|
},
|
|
2040
2506
|
async (assets) => {
|
|
2041
2507
|
const port = await serverPortFn();
|
|
2508
|
+
const publicServerUrl = publicServerUrlFn(port);
|
|
2042
2509
|
const mainAssetKey = Object.keys(assets).find(
|
|
2043
2510
|
(key) => key.endsWith(".js") && (key.includes("main") || key.includes("app") || key.includes("umi"))
|
|
2044
2511
|
);
|
|
2045
2512
|
if (!mainAssetKey) return;
|
|
2046
2513
|
const originalSource = assets[mainAssetKey].source();
|
|
2047
2514
|
assets[mainAssetKey] = new compiler.webpack.sources.RawSource(
|
|
2048
|
-
getWebpackAssetScript(port) + "\n" + originalSource
|
|
2515
|
+
getWebpackAssetScript(port, publicServerUrl) + "\n" + originalSource
|
|
2049
2516
|
);
|
|
2050
2517
|
}
|
|
2051
2518
|
);
|
|
@@ -2079,12 +2546,13 @@ function injectRspack(compiler, serverPortFn, resolveClientModule2) {
|
|
|
2079
2546
|
}
|
|
2080
2547
|
|
|
2081
2548
|
// src/injectors/vite.ts
|
|
2082
|
-
function getViteVirtualModuleScript(serverPort) {
|
|
2549
|
+
function getViteVirtualModuleScript(serverPort, publicServerUrl) {
|
|
2083
2550
|
return `
|
|
2084
2551
|
import { mountInspector } from '@inspecto-dev/core';
|
|
2085
2552
|
window.__AI_INSPECTOR_PORT__ = ${serverPort};
|
|
2553
|
+
window.__AI_INSPECTOR_SERVER_URL__ = '${publicServerUrl ?? `http://127.0.0.1:${serverPort}`}';
|
|
2086
2554
|
mountInspector({
|
|
2087
|
-
serverUrl:
|
|
2555
|
+
serverUrl: window.__AI_INSPECTOR_SERVER_URL__,
|
|
2088
2556
|
});
|
|
2089
2557
|
`;
|
|
2090
2558
|
}
|
|
@@ -2117,6 +2585,11 @@ var InspectoPlugin = (0, import_unplugin.createUnplugin)((userOptions = {}) => {
|
|
|
2117
2585
|
}
|
|
2118
2586
|
return serverPort;
|
|
2119
2587
|
};
|
|
2588
|
+
const getPublicServerUrl = (port) => resolvePublicServerUrl({
|
|
2589
|
+
cwd: serverState.cwd || process.cwd(),
|
|
2590
|
+
configRoot: serverState.configRoot || projectRoot,
|
|
2591
|
+
port
|
|
2592
|
+
});
|
|
2120
2593
|
return {
|
|
2121
2594
|
name: "inspecto-overlay",
|
|
2122
2595
|
enforce: "pre",
|
|
@@ -2129,7 +2602,7 @@ var InspectoPlugin = (0, import_unplugin.createUnplugin)((userOptions = {}) => {
|
|
|
2129
2602
|
},
|
|
2130
2603
|
webpack: (compiler) => {
|
|
2131
2604
|
if (isProduction) return;
|
|
2132
|
-
injectWebpack(compiler, ensureServer, resolveClientModule);
|
|
2605
|
+
injectWebpack(compiler, ensureServer, getPublicServerUrl, resolveClientModule);
|
|
2133
2606
|
},
|
|
2134
2607
|
rspack: (compiler) => {
|
|
2135
2608
|
if (isProduction) return;
|
|
@@ -2155,7 +2628,10 @@ var InspectoPlugin = (0, import_unplugin.createUnplugin)((userOptions = {}) => {
|
|
|
2155
2628
|
},
|
|
2156
2629
|
load(id) {
|
|
2157
2630
|
if (id === VITE_VIRTUAL_MODULE_ID) {
|
|
2158
|
-
return getViteVirtualModuleScript(
|
|
2631
|
+
return getViteVirtualModuleScript(
|
|
2632
|
+
serverPort ?? DEFAULT_PORT,
|
|
2633
|
+
getPublicServerUrl(serverPort ?? DEFAULT_PORT)
|
|
2634
|
+
);
|
|
2159
2635
|
}
|
|
2160
2636
|
return null;
|
|
2161
2637
|
},
|