@inspecto-dev/plugin 0.3.9 → 0.3.11

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.
@@ -35,18 +35,19 @@ __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.10_typescript@5.9.3_yaml@2.8.3/node_modules/tsup/assets/cjs_shims.js
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.__AI_INSPECTOR_SERVER_URL__ = '${publicServerUrl ?? `http://127.0.0.1:${serverPort}`}';
46
47
  window.addEventListener('load', () => {
47
48
  if (window.InspectoClient) {
48
49
  window.InspectoClient.mountInspector({
49
- serverUrl: 'http://0.0.0.0:' + window.__AI_INSPECTOR_PORT__,
50
+ serverUrl: window.__AI_INSPECTOR_SERVER_URL__,
50
51
  });
51
52
  }
52
53
  });
@@ -77,7 +78,7 @@ var import_node_path4 = __toESM(require("path"), 1);
77
78
  var import_node_os2 = __toESM(require("os"), 1);
78
79
  var import_node_crypto2 = __toESM(require("crypto"), 1);
79
80
  var import_portfinder = __toESM(require("portfinder"), 1);
80
- var import_types2 = require("@inspecto-dev/types");
81
+ var import_types3 = require("@inspecto-dev/types");
81
82
 
82
83
  // src/server/snippet.ts
83
84
  var fs = __toESM(require("fs"), 1);
@@ -425,13 +426,28 @@ function resolveIntents(serverPrompts) {
425
426
  );
426
427
  continue;
427
428
  }
428
- if (!item.aiIntent) {
429
- configLogger.warn(`Intent "${item.id}" is missing required "aiIntent".`);
430
- continue;
429
+ if (item.kind === "workflow") {
430
+ if (!item.prompt) {
431
+ configLogger.warn(`Workflow "${item.id}" missing required "prompt", skipping`);
432
+ continue;
433
+ }
434
+ result.push({
435
+ kind: "workflow",
436
+ id: item.id,
437
+ label: item.label ?? item.id,
438
+ prompt: item.prompt,
439
+ confirm: item.confirm ?? false,
440
+ enabled: item.enabled ?? true
441
+ });
442
+ } else {
443
+ if (!item.aiIntent) {
444
+ configLogger.warn(`Intent "${item.id}" is missing required "aiIntent".`);
445
+ continue;
446
+ }
447
+ result.push(
448
+ baseMap.has(item.id) ? { ...baseMap.get(item.id), ...item } : item
449
+ );
431
450
  }
432
- result.push(
433
- baseMap.has(item.id) ? { ...baseMap.get(item.id), ...item } : item
434
- );
435
451
  }
436
452
  }
437
453
  return result;
@@ -451,26 +467,61 @@ function resolveIntents(serverPrompts) {
451
467
  configLogger.warn('Intent object missing required "id" field, skipping.');
452
468
  continue;
453
469
  }
454
- if (!item.aiIntent) {
455
- configLogger.warn(`Intent "${item.id}" is missing required "aiIntent".`);
456
- continue;
457
- }
458
- const existingIdx = merged.findIndex((i) => i.id === item.id);
459
- if (existingIdx !== -1) {
460
- if (item.enabled === false) {
461
- merged.splice(existingIdx, 1);
470
+ if (item.kind === "workflow") {
471
+ if (!item.prompt) {
472
+ configLogger.warn(`Workflow "${item.id}" missing required "prompt", skipping`);
473
+ continue;
474
+ }
475
+ const wfConfig = {
476
+ kind: "workflow",
477
+ id: item.id,
478
+ label: item.label ?? item.id,
479
+ prompt: item.prompt,
480
+ confirm: item.confirm ?? false,
481
+ enabled: item.enabled ?? true
482
+ };
483
+ const existingIdx = merged.findIndex((i) => i.id === item.id);
484
+ if (existingIdx !== -1) {
485
+ if (item.enabled === false) {
486
+ merged.splice(existingIdx, 1);
487
+ } else {
488
+ merged[existingIdx] = wfConfig;
489
+ }
462
490
  } else {
463
- merged[existingIdx] = { ...merged[existingIdx], ...item };
491
+ if (item.enabled !== false) {
492
+ merged.push(wfConfig);
493
+ }
464
494
  }
465
495
  } else {
466
- if (item.enabled !== false) {
467
- merged.push(item);
496
+ if (!item.aiIntent) {
497
+ configLogger.warn(`Intent "${item.id}" is missing required "aiIntent".`);
498
+ continue;
499
+ }
500
+ const existingIdx = merged.findIndex((i) => i.id === item.id);
501
+ if (existingIdx !== -1) {
502
+ if (item.enabled === false) {
503
+ merged.splice(existingIdx, 1);
504
+ } else {
505
+ merged[existingIdx] = { ...merged[existingIdx], ...item };
506
+ }
507
+ } else {
508
+ if (item.enabled !== false) {
509
+ merged.push(item);
510
+ }
468
511
  }
469
512
  }
470
513
  }
471
514
  }
472
515
  return merged;
473
516
  }
517
+ function resolveWorkflowSlots(intents) {
518
+ return intents.filter(import_types.isWorkflowConfig).filter((w) => w.enabled !== false).map((w) => ({
519
+ id: w.id,
520
+ label: w.label ?? w.id,
521
+ prompt: w.prompt,
522
+ confirm: w.confirm ?? false
523
+ }));
524
+ }
474
525
  var watchers = [];
475
526
  function watchConfig(onReload, cwd = process.cwd(), gitRoot) {
476
527
  if (isWatching) return;
@@ -700,6 +751,10 @@ function assertPathWithinIdeOpenScope(file, projectRoot) {
700
751
  }
701
752
  }
702
753
 
754
+ // src/server/annotation-dispatch.ts
755
+ var import_node_child_process2 = require("child_process");
756
+ var import_node_util = require("util");
757
+
703
758
  // src/server/session-store.ts
704
759
  var DEFAULT_STATUS = "pending";
705
760
  function createAnnotationSessionStore(options = {}) {
@@ -707,8 +762,12 @@ function createAnnotationSessionStore(options = {}) {
707
762
  const listeners = /* @__PURE__ */ new Set();
708
763
  const now = options.now ?? (() => Date.now());
709
764
  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;
765
+ function findNewestMatchingSession(statuses, source) {
766
+ return [...sessions.values()].filter((session) => {
767
+ if (statuses && !statuses.has(session.status)) return false;
768
+ if (source && session.source !== source) return false;
769
+ return true;
770
+ }).sort((left, right) => right.updatedAt - left.updatedAt)[0] ?? null;
712
771
  }
713
772
  function updateSessionStatus(id, status) {
714
773
  const session = sessions.get(id);
@@ -768,7 +827,7 @@ function createAnnotationSessionStore(options = {}) {
768
827
  },
769
828
  async claimNextSession(options2 = {}) {
770
829
  const statuses = normalizeStatuses(DEFAULT_STATUS);
771
- const existingSession = findNewestMatchingSession(statuses);
830
+ const existingSession = findNewestMatchingSession(statuses, options2.source);
772
831
  if (existingSession) {
773
832
  return {
774
833
  session: claimSession(existingSession.id, statuses),
@@ -883,6 +942,7 @@ function cloneValue(value) {
883
942
  }
884
943
 
885
944
  // src/server/annotation-dispatch.ts
945
+ var execAsync = (0, import_node_util.promisify)(import_node_child_process2.exec);
886
946
  var AnnotationDispatchError = class extends Error {
887
947
  constructor(message, errorCode) {
888
948
  super(message);
@@ -894,9 +954,14 @@ async function dispatchAnnotationsToAi(req, state, store = annotationSessionStor
894
954
  try {
895
955
  validateAnnotationDispatchRequest(req, state);
896
956
  const batch = normalizeAnnotationBatch(req);
897
- const prompt = buildAnnotationBatchPrompt(batch);
957
+ let prompt = buildAnnotationBatchPrompt(batch);
958
+ if (req.source === "workflow") {
959
+ prompt = await appendProjectMetadata(prompt, state);
960
+ }
898
961
  const deliveryMode = normalizeDeliveryMode(req.deliveryMode);
899
962
  const session = store.createSession({
963
+ source: req.source || "annotation",
964
+ ...req.workflowId ? { workflowId: req.workflowId } : {},
900
965
  instruction: batch.instruction,
901
966
  annotations: toSessionAnnotations(batch.annotations),
902
967
  deliveryMode,
@@ -922,6 +987,33 @@ async function dispatchAnnotationsToAi(req, state, store = annotationSessionStor
922
987
  };
923
988
  }
924
989
  }
990
+ async function appendProjectMetadata(prompt, state) {
991
+ const lines = ["\n## Project"];
992
+ lines.push(`- Root: ${state.projectRoot}`);
993
+ try {
994
+ const options = {
995
+ cwd: state.projectRoot,
996
+ encoding: "utf-8",
997
+ timeout: 2e3
998
+ };
999
+ const { stdout: branchStdout } = await execAsync("git branch --show-current", options);
1000
+ const branch = branchStdout.trim();
1001
+ lines.push(`- Branch: ${branch}`);
1002
+ const { stdout: statusStdout } = await execAsync("git status --porcelain", options);
1003
+ const statusRaw = statusStdout.trim();
1004
+ const entries = statusRaw ? statusRaw.split("\n") : [];
1005
+ const staged = entries.filter((l) => l[0] !== " " && l[0] !== "?").length;
1006
+ const unstaged = entries.filter((l) => l[1] !== " " && l[1] !== "?").length;
1007
+ const untracked = entries.filter((l) => l[0] === "?").length;
1008
+ lines.push(`- Status: ${staged} staged, ${unstaged} unstaged, ${untracked} untracked`);
1009
+ } catch (err) {
1010
+ console.warn("[inspecto] Failed to get git status for workflow:", err);
1011
+ lines.push("- Git: unavailable or check timeout");
1012
+ }
1013
+ return `${prompt}
1014
+
1015
+ ${lines.join("\n")}`;
1016
+ }
925
1017
  function normalizeDeliveryMode(input) {
926
1018
  return input === "agent" ? "agent" : "ide";
927
1019
  }
@@ -958,7 +1050,7 @@ function toSessionSummary(session) {
958
1050
  };
959
1051
  }
960
1052
  function validateAnnotationDispatchRequest(req, state) {
961
- if (!req.annotations.length) {
1053
+ if (!req.annotations.length && req.source !== "workflow") {
962
1054
  throw new AnnotationDispatchError("At least one annotation is required.", "INVALID_REQUEST");
963
1055
  }
964
1056
  for (const annotation of req.annotations) {
@@ -1060,6 +1152,7 @@ function getAnnotationDispatchErrorCode(error) {
1060
1152
  }
1061
1153
 
1062
1154
  // src/server/client-config.ts
1155
+ var import_types2 = require("@inspecto-dev/types");
1063
1156
  async function buildClientConfig(serverState2) {
1064
1157
  const userConfig = loadUserConfigSync(false, serverState2.cwd, serverState2.configRoot);
1065
1158
  const promptsConfig = await loadPromptsConfig(false, serverState2.cwd, serverState2.configRoot);
@@ -1071,11 +1164,13 @@ async function buildClientConfig(serverState2) {
1071
1164
  const { scheme: _scheme, ...rest } = serverState2.ideInfo;
1072
1165
  info = rest;
1073
1166
  }
1167
+ const allIntents = resolveIntents(promptsConfig);
1074
1168
  return {
1075
1169
  ...info,
1076
- prompts: resolveIntents(promptsConfig),
1170
+ prompts: allIntents.filter(import_types2.isAiIntentConfig),
1171
+ workflows: resolveWorkflowSlots(allIntents),
1077
1172
  hotKeys: userConfig["inspector.hotKey"] ?? "alt",
1078
- annotateDeliveryMode: userConfig["annotate.deliveryMode"] ?? "both",
1173
+ annotateDeliveryMode: userConfig["annotate.deliveryMode"] ?? "agent",
1079
1174
  includeSnippet: userConfig["prompt.includeSnippet"] ?? false,
1080
1175
  runtimeContext: {
1081
1176
  enabled: true,
@@ -1088,7 +1183,7 @@ async function buildClientConfig(serverState2) {
1088
1183
  }
1089
1184
 
1090
1185
  // src/server/open-file.ts
1091
- var import_node_child_process2 = require("child_process");
1186
+ var import_node_child_process3 = require("child_process");
1092
1187
  var import_launch_ide2 = require("launch-ide");
1093
1188
  var serverLogger2 = createLogger("inspecto:server", { logLevel: getGlobalLogLevel() });
1094
1189
  var VSCODE_FAMILY_SCHEMES = [
@@ -1139,11 +1234,11 @@ function handleOpenFileRequest(body, serverState2) {
1139
1234
  serverLogger2.debug(`SOURCE_OPEN: Bypassing launchIDE, using URI scheme directly: ${uri}`);
1140
1235
  try {
1141
1236
  if (process.platform === "darwin") {
1142
- (0, import_node_child_process2.execFileSync)("open", [uri]);
1237
+ (0, import_node_child_process3.execFileSync)("open", [uri]);
1143
1238
  } else if (process.platform === "win32") {
1144
- (0, import_node_child_process2.execFileSync)("cmd", ["/c", "start", '""', uri]);
1239
+ (0, import_node_child_process3.execFileSync)("cmd", ["/c", "start", '""', uri]);
1145
1240
  } else {
1146
- (0, import_node_child_process2.execFileSync)("xdg-open", [uri]);
1241
+ (0, import_node_child_process3.execFileSync)("xdg-open", [uri]);
1147
1242
  }
1148
1243
  } catch (e) {
1149
1244
  serverLogger2.error(`Failed to launch URI for SOURCE_OPEN (${uri}):`, e);
@@ -1170,35 +1265,63 @@ function handleOpenFileRequest(body, serverState2) {
1170
1265
  // src/server/project-root.ts
1171
1266
  var import_node_fs3 = __toESM(require("fs"), 1);
1172
1267
  var import_node_path3 = __toESM(require("path"), 1);
1173
- var import_node_child_process3 = require("child_process");
1268
+ var import_node_child_process4 = require("child_process");
1174
1269
  var serverLogger3 = createLogger("inspecto:server", { logLevel: getGlobalLogLevel() });
1175
- function resolveProjectRoot() {
1176
- const cwd = process.cwd();
1177
- let gitRoot;
1270
+ function resolveGitRoot(_cwd) {
1178
1271
  try {
1179
- gitRoot = (0, import_node_child_process3.execSync)("git rev-parse --show-toplevel", { encoding: "utf-8" }).trim();
1272
+ const output = (0, import_node_child_process4.execSync)("git rev-parse --show-toplevel", { encoding: "utf-8" });
1273
+ return typeof output === "string" ? output.trim() : null;
1180
1274
  } catch (e) {
1181
1275
  serverLogger3.warn("Failed to resolve git root via git rev-parse:", e);
1182
- gitRoot = cwd;
1183
- }
1184
- const visited = /* @__PURE__ */ new Set();
1185
- const search = (start, stop) => {
1186
- let current = start;
1187
- while (!visited.has(current)) {
1188
- visited.add(current);
1189
- if (import_node_fs3.default.existsSync(import_node_path3.default.join(current, ".inspecto"))) return current;
1190
- if (current === stop) break;
1191
- const parent = import_node_path3.default.dirname(current);
1192
- if (parent === current) break;
1193
- current = parent;
1194
- }
1195
1276
  return null;
1196
- };
1197
- const cwdMatch = search(cwd, import_node_path3.default.parse(cwd).root);
1198
- if (cwdMatch) return cwdMatch;
1199
- const repoMatch = search(gitRoot, import_node_path3.default.parse(gitRoot).root);
1200
- if (repoMatch) return repoMatch;
1201
- return gitRoot;
1277
+ }
1278
+ }
1279
+ function findNearestAncestorWith(start, predicate) {
1280
+ let current = start;
1281
+ while (true) {
1282
+ if (predicate(current)) return current;
1283
+ const parent = import_node_path3.default.dirname(current);
1284
+ if (parent === current) break;
1285
+ current = parent;
1286
+ }
1287
+ return null;
1288
+ }
1289
+ function resolveWorkspaceRoot() {
1290
+ const cwd = process.cwd();
1291
+ const inspectoRoot = findNearestAncestorWith(
1292
+ cwd,
1293
+ (dir) => import_node_fs3.default.existsSync(import_node_path3.default.join(dir, ".inspecto"))
1294
+ );
1295
+ if (inspectoRoot) return inspectoRoot;
1296
+ const packageRoot = findNearestAncestorWith(
1297
+ cwd,
1298
+ (dir) => import_node_fs3.default.existsSync(import_node_path3.default.join(dir, "package.json"))
1299
+ );
1300
+ if (packageRoot) return packageRoot;
1301
+ return resolveGitRoot(cwd) ?? cwd;
1302
+ }
1303
+ function resolveProjectRoot() {
1304
+ const cwd = process.cwd();
1305
+ const packageRoot = findNearestAncestorWith(
1306
+ cwd,
1307
+ (dir) => import_node_fs3.default.existsSync(import_node_path3.default.join(dir, "package.json"))
1308
+ );
1309
+ if (packageRoot) return packageRoot;
1310
+ const inspectoRoot = findNearestAncestorWith(
1311
+ cwd,
1312
+ (dir) => import_node_fs3.default.existsSync(import_node_path3.default.join(dir, ".inspecto"))
1313
+ );
1314
+ if (inspectoRoot) return inspectoRoot;
1315
+ return resolveGitRoot(cwd) ?? cwd;
1316
+ }
1317
+
1318
+ // src/server/server-url.ts
1319
+ function resolveServerHost(cwd, configRoot) {
1320
+ if (process.env["VITEST"]) return "127.0.0.1";
1321
+ const userConfig = loadUserConfigSync(false, cwd, configRoot);
1322
+ const configuredHost = userConfig["server.host"]?.trim();
1323
+ if (configuredHost) return configuredHost;
1324
+ return "127.0.0.1";
1202
1325
  }
1203
1326
 
1204
1327
  // src/server/index.ts
@@ -1253,8 +1376,9 @@ async function startServer() {
1253
1376
  return serverState.port;
1254
1377
  }
1255
1378
  serverState.projectRoot = resolveProjectRoot();
1256
- serverState.configRoot = serverState.projectRoot;
1379
+ serverState.configRoot = resolveWorkspaceRoot();
1257
1380
  serverState.cwd = process.cwd();
1381
+ const serverHost = resolveServerHost(serverState.cwd, serverState.configRoot);
1258
1382
  import_portfinder.default.basePort = 5678;
1259
1383
  const port = await import_portfinder.default.getPortPromise();
1260
1384
  watchConfig(
@@ -1281,7 +1405,7 @@ async function startServer() {
1281
1405
  });
1282
1406
  });
1283
1407
  await new Promise((resolve2, reject) => {
1284
- serverInstance.listen(port, "0.0.0.0", () => {
1408
+ serverInstance.listen(port, serverHost, () => {
1285
1409
  serverInstance.unref();
1286
1410
  resolve2();
1287
1411
  });
@@ -1303,7 +1427,7 @@ async function startServer() {
1303
1427
  } catch {
1304
1428
  }
1305
1429
  });
1306
- serverLogger4.info(`server running at http://0.0.0.0:${port}`);
1430
+ serverLogger4.info(`server running at http://${serverHost}:${port}`);
1307
1431
  return port;
1308
1432
  }
1309
1433
  async function readBody(req) {
@@ -1316,19 +1440,19 @@ async function readBody(req) {
1316
1440
  }
1317
1441
  async function handleRequest(url, req, res) {
1318
1442
  const pathname = url.pathname;
1319
- if ((pathname === "/health" || pathname === import_types2.INSPECTO_API_PATHS.HEALTH) && req.method === "GET") {
1443
+ if ((pathname === "/health" || pathname === import_types3.INSPECTO_API_PATHS.HEALTH) && req.method === "GET") {
1320
1444
  res.writeHead(200, { "Content-Type": "application/json" });
1321
1445
  res.end(JSON.stringify({ ok: true, port: serverState.port }));
1322
1446
  return;
1323
1447
  }
1324
- if (pathname === import_types2.INSPECTO_API_PATHS.CLIENT_CONFIG && req.method === "GET") {
1448
+ if (pathname === import_types3.INSPECTO_API_PATHS.CLIENT_CONFIG && req.method === "GET") {
1325
1449
  const config = await buildClientConfig(serverState);
1326
1450
  delete config.providers;
1327
1451
  res.writeHead(200, { "Content-Type": "application/json" });
1328
1452
  res.end(JSON.stringify(config));
1329
1453
  return;
1330
1454
  }
1331
- if (pathname === import_types2.INSPECTO_API_PATHS.IDE_INFO && req.method === "POST") {
1455
+ if (pathname === import_types3.INSPECTO_API_PATHS.IDE_INFO && req.method === "POST") {
1332
1456
  try {
1333
1457
  const body = JSON.parse(await readBody(req));
1334
1458
  const ideWorkspace = body.workspaceRoot || "";
@@ -1349,13 +1473,13 @@ async function handleRequest(url, req, res) {
1349
1473
  res.writeHead(200, { "Content-Type": "application/json" });
1350
1474
  res.end(JSON.stringify({ success: true }));
1351
1475
  } catch (e) {
1352
- serverLogger4.error(`Error parsing ${import_types2.INSPECTO_API_PATHS.IDE_INFO} POST request:`, e);
1476
+ serverLogger4.error(`Error parsing ${import_types3.INSPECTO_API_PATHS.IDE_INFO} POST request:`, e);
1353
1477
  res.writeHead(400, { "Content-Type": "application/json" });
1354
1478
  res.end(JSON.stringify({ error: "Invalid JSON body" }));
1355
1479
  }
1356
1480
  return;
1357
1481
  }
1358
- if ((pathname === import_types2.INSPECTO_API_PATHS.SOURCE_OPEN || pathname === import_types2.INSPECTO_API_PATHS.IDE_OPEN) && req.method === "POST") {
1482
+ if ((pathname === import_types3.INSPECTO_API_PATHS.SOURCE_OPEN || pathname === import_types3.INSPECTO_API_PATHS.IDE_OPEN) && req.method === "POST") {
1359
1483
  let body;
1360
1484
  try {
1361
1485
  body = JSON.parse(await readBody(req));
@@ -1378,7 +1502,7 @@ async function handleRequest(url, req, res) {
1378
1502
  res.end(JSON.stringify({ success: true }));
1379
1503
  return;
1380
1504
  }
1381
- if (pathname === import_types2.INSPECTO_API_PATHS.PROJECT_SNIPPET && req.method === "GET") {
1505
+ if (pathname === import_types3.INSPECTO_API_PATHS.PROJECT_SNIPPET && req.method === "GET") {
1382
1506
  const file = url.searchParams.get("file") ?? "";
1383
1507
  const line = parseInt(url.searchParams.get("line") ?? "1", 10);
1384
1508
  const column = parseInt(url.searchParams.get("column") ?? "1", 10);
@@ -1412,7 +1536,7 @@ async function handleRequest(url, req, res) {
1412
1536
  }
1413
1537
  return;
1414
1538
  }
1415
- if (pathname === import_types2.INSPECTO_API_PATHS.AI_DISPATCH && req.method === "POST") {
1539
+ if (pathname === import_types3.INSPECTO_API_PATHS.AI_DISPATCH && req.method === "POST") {
1416
1540
  try {
1417
1541
  const rawBody = await readBody(req);
1418
1542
  const body = JSON.parse(rawBody);
@@ -1420,13 +1544,13 @@ async function handleRequest(url, req, res) {
1420
1544
  res.writeHead(result.success ? 200 : 500, { "Content-Type": "application/json" });
1421
1545
  res.end(JSON.stringify(result));
1422
1546
  } catch (e) {
1423
- serverLogger4.error(`Error parsing ${import_types2.INSPECTO_API_PATHS.AI_DISPATCH} request:`, e);
1547
+ serverLogger4.error(`Error parsing ${import_types3.INSPECTO_API_PATHS.AI_DISPATCH} request:`, e);
1424
1548
  res.writeHead(500, { "Content-Type": "application/json" });
1425
1549
  res.end(JSON.stringify({ success: false, error: String(e), errorCode: "INTERNAL_ERROR" }));
1426
1550
  }
1427
1551
  return;
1428
1552
  }
1429
- if (pathname === import_types2.INSPECTO_API_PATHS.AI_BATCH_DISPATCH && req.method === "POST") {
1553
+ if (pathname === import_types3.INSPECTO_API_PATHS.AI_BATCH_DISPATCH && req.method === "POST") {
1430
1554
  try {
1431
1555
  const rawBody = await readBody(req);
1432
1556
  const body = JSON.parse(rawBody);
@@ -1436,13 +1560,13 @@ async function handleRequest(url, req, res) {
1436
1560
  });
1437
1561
  res.end(JSON.stringify(result));
1438
1562
  } catch (e) {
1439
- serverLogger4.error(`Error parsing ${import_types2.INSPECTO_API_PATHS.AI_BATCH_DISPATCH} request:`, e);
1563
+ serverLogger4.error(`Error parsing ${import_types3.INSPECTO_API_PATHS.AI_BATCH_DISPATCH} request:`, e);
1440
1564
  res.writeHead(500, { "Content-Type": "application/json" });
1441
1565
  res.end(JSON.stringify({ success: false, error: String(e), errorCode: "INTERNAL_ERROR" }));
1442
1566
  }
1443
1567
  return;
1444
1568
  }
1445
- if (pathname === import_types2.INSPECTO_API_PATHS.SESSION_CLAIM_NEXT && req.method === "POST") {
1569
+ if (pathname === import_types3.INSPECTO_API_PATHS.SESSION_CLAIM_NEXT && req.method === "POST") {
1446
1570
  try {
1447
1571
  const rawBody = await readBody(req);
1448
1572
  const body = rawBody ? JSON.parse(rawBody) : {};
@@ -1469,7 +1593,7 @@ async function handleRequest(url, req, res) {
1469
1593
  }
1470
1594
  return;
1471
1595
  }
1472
- if (pathname === import_types2.INSPECTO_API_PATHS.SESSION_EVENTS && req.method === "GET") {
1596
+ if (pathname === import_types3.INSPECTO_API_PATHS.SESSION_EVENTS && req.method === "GET") {
1473
1597
  const statusParam = url.searchParams.getAll("status");
1474
1598
  const statuses = statusParam.length ? new Set(statusParam) : null;
1475
1599
  const sessionId = url.searchParams.get("sessionId")?.trim() || null;
@@ -1497,7 +1621,7 @@ data: ${JSON.stringify({ ok: true })}
1497
1621
  });
1498
1622
  return;
1499
1623
  }
1500
- if (pathname === import_types2.INSPECTO_API_PATHS.SESSIONS && req.method === "GET") {
1624
+ if (pathname === import_types3.INSPECTO_API_PATHS.SESSIONS && req.method === "GET") {
1501
1625
  const statusParam = url.searchParams.getAll("status");
1502
1626
  const sessions = annotationSessionStore.listSessions(
1503
1627
  statusParam.length ? {
@@ -1508,8 +1632,8 @@ data: ${JSON.stringify({ ok: true })}
1508
1632
  res.end(JSON.stringify({ success: true, sessions }));
1509
1633
  return;
1510
1634
  }
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);
1635
+ if (pathname.startsWith(`${import_types3.INSPECTO_API_PATHS.SESSIONS}/`) && req.method === "GET") {
1636
+ const sessionId = pathname.substring(import_types3.INSPECTO_API_PATHS.SESSIONS.length + 1);
1513
1637
  const session = annotationSessionStore.getSession(sessionId);
1514
1638
  if (!session) {
1515
1639
  res.writeHead(404, { "Content-Type": "application/json" });
@@ -1520,10 +1644,10 @@ data: ${JSON.stringify({ ok: true })}
1520
1644
  res.end(JSON.stringify({ success: true, session }));
1521
1645
  return;
1522
1646
  }
1523
- if (pathname.startsWith(`${import_types2.INSPECTO_API_PATHS.SESSIONS}/`) && pathname.endsWith(import_types2.INSPECTO_API_PATHS.SESSION_REPLY_SUFFIX) && req.method === "POST") {
1647
+ if (pathname.startsWith(`${import_types3.INSPECTO_API_PATHS.SESSIONS}/`) && pathname.endsWith(import_types3.INSPECTO_API_PATHS.SESSION_REPLY_SUFFIX) && req.method === "POST") {
1524
1648
  const sessionId = pathname.slice(
1525
- import_types2.INSPECTO_API_PATHS.SESSIONS.length + 1,
1526
- -import_types2.INSPECTO_API_PATHS.SESSION_REPLY_SUFFIX.length
1649
+ import_types3.INSPECTO_API_PATHS.SESSIONS.length + 1,
1650
+ -import_types3.INSPECTO_API_PATHS.SESSION_REPLY_SUFFIX.length
1527
1651
  );
1528
1652
  try {
1529
1653
  const rawBody = await readBody(req);
@@ -1556,10 +1680,10 @@ data: ${JSON.stringify({ ok: true })}
1556
1680
  }
1557
1681
  return;
1558
1682
  }
1559
- if (pathname.startsWith(`${import_types2.INSPECTO_API_PATHS.SESSIONS}/`) && pathname.endsWith(import_types2.INSPECTO_API_PATHS.SESSION_RESOLVE_SUFFIX) && req.method === "POST") {
1683
+ if (pathname.startsWith(`${import_types3.INSPECTO_API_PATHS.SESSIONS}/`) && pathname.endsWith(import_types3.INSPECTO_API_PATHS.SESSION_RESOLVE_SUFFIX) && req.method === "POST") {
1560
1684
  const sessionId = pathname.slice(
1561
- import_types2.INSPECTO_API_PATHS.SESSIONS.length + 1,
1562
- -import_types2.INSPECTO_API_PATHS.SESSION_RESOLVE_SUFFIX.length
1685
+ import_types3.INSPECTO_API_PATHS.SESSIONS.length + 1,
1686
+ -import_types3.INSPECTO_API_PATHS.SESSION_RESOLVE_SUFFIX.length
1563
1687
  );
1564
1688
  try {
1565
1689
  const rawBody = await readBody(req);
@@ -1607,10 +1731,10 @@ data: ${JSON.stringify({ ok: true })}
1607
1731
  }
1608
1732
  return;
1609
1733
  }
1610
- if (pathname.startsWith(`${import_types2.INSPECTO_API_PATHS.SESSIONS}/`) && pathname.endsWith(import_types2.INSPECTO_API_PATHS.SESSION_DISMISS_SUFFIX) && req.method === "POST") {
1734
+ if (pathname.startsWith(`${import_types3.INSPECTO_API_PATHS.SESSIONS}/`) && pathname.endsWith(import_types3.INSPECTO_API_PATHS.SESSION_DISMISS_SUFFIX) && req.method === "POST") {
1611
1735
  const sessionId = pathname.slice(
1612
- import_types2.INSPECTO_API_PATHS.SESSIONS.length + 1,
1613
- -import_types2.INSPECTO_API_PATHS.SESSION_DISMISS_SUFFIX.length
1736
+ import_types3.INSPECTO_API_PATHS.SESSIONS.length + 1,
1737
+ -import_types3.INSPECTO_API_PATHS.SESSION_DISMISS_SUFFIX.length
1614
1738
  );
1615
1739
  try {
1616
1740
  const rawBody = await readBody(req);
@@ -1648,8 +1772,8 @@ data: ${JSON.stringify({ ok: true })}
1648
1772
  }
1649
1773
  return;
1650
1774
  }
1651
- if (pathname.startsWith(`${import_types2.INSPECTO_API_PATHS.AI_TICKET}/`) && req.method === "GET") {
1652
- const ticketId = pathname.substring(import_types2.INSPECTO_API_PATHS.AI_TICKET.length + 1);
1775
+ if (pathname.startsWith(`${import_types3.INSPECTO_API_PATHS.AI_TICKET}/`) && req.method === "GET") {
1776
+ const ticketId = pathname.substring(import_types3.INSPECTO_API_PATHS.AI_TICKET.length + 1);
1653
1777
  const payloadStr = readTicket(ticketId);
1654
1778
  if (!payloadStr) {
1655
1779
  res.writeHead(404, { "Content-Type": "application/json" });
@@ -1665,10 +1789,23 @@ data: ${JSON.stringify({ ok: true })}
1665
1789
  }
1666
1790
  async function dispatchToAi(req) {
1667
1791
  const { location, snippet, prompt } = req;
1668
- const formattedPrompt = prompt ?? `Please help me with this code from \`${location.file}\` (line ${location.line}):
1792
+ if (prompt?.trim()) {
1793
+ const runtime2 = resolvePromptDispatchRuntime(serverState);
1794
+ return dispatchPromptThroughIde(runtime2, {
1795
+ prompt: prompt.trim()
1796
+ });
1797
+ }
1798
+ if (!location) {
1799
+ return {
1800
+ success: false,
1801
+ error: "Source location is required when prompt is omitted.",
1802
+ errorCode: "INVALID_REQUEST"
1803
+ };
1804
+ }
1805
+ const formattedPrompt = `Please help me with this code from \`${location.file}\` (line ${location.line}):
1669
1806
 
1670
1807
  \`\`\`
1671
- ${snippet}
1808
+ ${snippet ?? ""}
1672
1809
  \`\`\`
1673
1810
  `;
1674
1811
  const runtime = resolvePromptDispatchRuntime(serverState);
@@ -1677,7 +1814,7 @@ ${snippet}
1677
1814
  filePath: location.file,
1678
1815
  line: location.line,
1679
1816
  column: location.column,
1680
- snippet
1817
+ ...snippet !== void 0 ? { snippet } : {}
1681
1818
  });
1682
1819
  }
1683
1820
  function getBatchDispatchStatusCode(errorCode, success) {