@inspecto-dev/plugin 0.3.10 → 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.
@@ -78,7 +78,7 @@ var import_node_path4 = __toESM(require("path"), 1);
78
78
  var import_node_os2 = __toESM(require("os"), 1);
79
79
  var import_node_crypto2 = __toESM(require("crypto"), 1);
80
80
  var import_portfinder = __toESM(require("portfinder"), 1);
81
- var import_types2 = require("@inspecto-dev/types");
81
+ var import_types3 = require("@inspecto-dev/types");
82
82
 
83
83
  // src/server/snippet.ts
84
84
  var fs = __toESM(require("fs"), 1);
@@ -426,13 +426,28 @@ function resolveIntents(serverPrompts) {
426
426
  );
427
427
  continue;
428
428
  }
429
- if (!item.aiIntent) {
430
- configLogger.warn(`Intent "${item.id}" is missing required "aiIntent".`);
431
- 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
+ );
432
450
  }
433
- result.push(
434
- baseMap.has(item.id) ? { ...baseMap.get(item.id), ...item } : item
435
- );
436
451
  }
437
452
  }
438
453
  return result;
@@ -452,26 +467,61 @@ function resolveIntents(serverPrompts) {
452
467
  configLogger.warn('Intent object missing required "id" field, skipping.');
453
468
  continue;
454
469
  }
455
- if (!item.aiIntent) {
456
- configLogger.warn(`Intent "${item.id}" is missing required "aiIntent".`);
457
- continue;
458
- }
459
- const existingIdx = merged.findIndex((i) => i.id === item.id);
460
- if (existingIdx !== -1) {
461
- if (item.enabled === false) {
462
- 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
+ }
463
490
  } else {
464
- merged[existingIdx] = { ...merged[existingIdx], ...item };
491
+ if (item.enabled !== false) {
492
+ merged.push(wfConfig);
493
+ }
465
494
  }
466
495
  } else {
467
- if (item.enabled !== false) {
468
- 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
+ }
469
511
  }
470
512
  }
471
513
  }
472
514
  }
473
515
  return merged;
474
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
+ }
475
525
  var watchers = [];
476
526
  function watchConfig(onReload, cwd = process.cwd(), gitRoot) {
477
527
  if (isWatching) return;
@@ -701,6 +751,10 @@ function assertPathWithinIdeOpenScope(file, projectRoot) {
701
751
  }
702
752
  }
703
753
 
754
+ // src/server/annotation-dispatch.ts
755
+ var import_node_child_process2 = require("child_process");
756
+ var import_node_util = require("util");
757
+
704
758
  // src/server/session-store.ts
705
759
  var DEFAULT_STATUS = "pending";
706
760
  function createAnnotationSessionStore(options = {}) {
@@ -708,8 +762,12 @@ function createAnnotationSessionStore(options = {}) {
708
762
  const listeners = /* @__PURE__ */ new Set();
709
763
  const now = options.now ?? (() => Date.now());
710
764
  const createId = options.createId ?? createRandomId;
711
- function findNewestMatchingSession(statuses) {
712
- return [...sessions.values()].filter((session) => statuses ? statuses.has(session.status) : true).sort((left, right) => right.updatedAt - left.updatedAt)[0] ?? null;
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;
713
771
  }
714
772
  function updateSessionStatus(id, status) {
715
773
  const session = sessions.get(id);
@@ -769,7 +827,7 @@ function createAnnotationSessionStore(options = {}) {
769
827
  },
770
828
  async claimNextSession(options2 = {}) {
771
829
  const statuses = normalizeStatuses(DEFAULT_STATUS);
772
- const existingSession = findNewestMatchingSession(statuses);
830
+ const existingSession = findNewestMatchingSession(statuses, options2.source);
773
831
  if (existingSession) {
774
832
  return {
775
833
  session: claimSession(existingSession.id, statuses),
@@ -884,6 +942,7 @@ function cloneValue(value) {
884
942
  }
885
943
 
886
944
  // src/server/annotation-dispatch.ts
945
+ var execAsync = (0, import_node_util.promisify)(import_node_child_process2.exec);
887
946
  var AnnotationDispatchError = class extends Error {
888
947
  constructor(message, errorCode) {
889
948
  super(message);
@@ -895,9 +954,14 @@ async function dispatchAnnotationsToAi(req, state, store = annotationSessionStor
895
954
  try {
896
955
  validateAnnotationDispatchRequest(req, state);
897
956
  const batch = normalizeAnnotationBatch(req);
898
- const prompt = buildAnnotationBatchPrompt(batch);
957
+ let prompt = buildAnnotationBatchPrompt(batch);
958
+ if (req.source === "workflow") {
959
+ prompt = await appendProjectMetadata(prompt, state);
960
+ }
899
961
  const deliveryMode = normalizeDeliveryMode(req.deliveryMode);
900
962
  const session = store.createSession({
963
+ source: req.source || "annotation",
964
+ ...req.workflowId ? { workflowId: req.workflowId } : {},
901
965
  instruction: batch.instruction,
902
966
  annotations: toSessionAnnotations(batch.annotations),
903
967
  deliveryMode,
@@ -923,6 +987,33 @@ async function dispatchAnnotationsToAi(req, state, store = annotationSessionStor
923
987
  };
924
988
  }
925
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
+ }
926
1017
  function normalizeDeliveryMode(input) {
927
1018
  return input === "agent" ? "agent" : "ide";
928
1019
  }
@@ -959,7 +1050,7 @@ function toSessionSummary(session) {
959
1050
  };
960
1051
  }
961
1052
  function validateAnnotationDispatchRequest(req, state) {
962
- if (!req.annotations.length) {
1053
+ if (!req.annotations.length && req.source !== "workflow") {
963
1054
  throw new AnnotationDispatchError("At least one annotation is required.", "INVALID_REQUEST");
964
1055
  }
965
1056
  for (const annotation of req.annotations) {
@@ -1061,6 +1152,7 @@ function getAnnotationDispatchErrorCode(error) {
1061
1152
  }
1062
1153
 
1063
1154
  // src/server/client-config.ts
1155
+ var import_types2 = require("@inspecto-dev/types");
1064
1156
  async function buildClientConfig(serverState2) {
1065
1157
  const userConfig = loadUserConfigSync(false, serverState2.cwd, serverState2.configRoot);
1066
1158
  const promptsConfig = await loadPromptsConfig(false, serverState2.cwd, serverState2.configRoot);
@@ -1072,11 +1164,13 @@ async function buildClientConfig(serverState2) {
1072
1164
  const { scheme: _scheme, ...rest } = serverState2.ideInfo;
1073
1165
  info = rest;
1074
1166
  }
1167
+ const allIntents = resolveIntents(promptsConfig);
1075
1168
  return {
1076
1169
  ...info,
1077
- prompts: resolveIntents(promptsConfig),
1170
+ prompts: allIntents.filter(import_types2.isAiIntentConfig),
1171
+ workflows: resolveWorkflowSlots(allIntents),
1078
1172
  hotKeys: userConfig["inspector.hotKey"] ?? "alt",
1079
- annotateDeliveryMode: userConfig["annotate.deliveryMode"] ?? "both",
1173
+ annotateDeliveryMode: userConfig["annotate.deliveryMode"] ?? "agent",
1080
1174
  includeSnippet: userConfig["prompt.includeSnippet"] ?? false,
1081
1175
  runtimeContext: {
1082
1176
  enabled: true,
@@ -1089,7 +1183,7 @@ async function buildClientConfig(serverState2) {
1089
1183
  }
1090
1184
 
1091
1185
  // src/server/open-file.ts
1092
- var import_node_child_process2 = require("child_process");
1186
+ var import_node_child_process3 = require("child_process");
1093
1187
  var import_launch_ide2 = require("launch-ide");
1094
1188
  var serverLogger2 = createLogger("inspecto:server", { logLevel: getGlobalLogLevel() });
1095
1189
  var VSCODE_FAMILY_SCHEMES = [
@@ -1140,11 +1234,11 @@ function handleOpenFileRequest(body, serverState2) {
1140
1234
  serverLogger2.debug(`SOURCE_OPEN: Bypassing launchIDE, using URI scheme directly: ${uri}`);
1141
1235
  try {
1142
1236
  if (process.platform === "darwin") {
1143
- (0, import_node_child_process2.execFileSync)("open", [uri]);
1237
+ (0, import_node_child_process3.execFileSync)("open", [uri]);
1144
1238
  } else if (process.platform === "win32") {
1145
- (0, import_node_child_process2.execFileSync)("cmd", ["/c", "start", '""', uri]);
1239
+ (0, import_node_child_process3.execFileSync)("cmd", ["/c", "start", '""', uri]);
1146
1240
  } else {
1147
- (0, import_node_child_process2.execFileSync)("xdg-open", [uri]);
1241
+ (0, import_node_child_process3.execFileSync)("xdg-open", [uri]);
1148
1242
  }
1149
1243
  } catch (e) {
1150
1244
  serverLogger2.error(`Failed to launch URI for SOURCE_OPEN (${uri}):`, e);
@@ -1171,43 +1265,62 @@ function handleOpenFileRequest(body, serverState2) {
1171
1265
  // src/server/project-root.ts
1172
1266
  var import_node_fs3 = __toESM(require("fs"), 1);
1173
1267
  var import_node_path3 = __toESM(require("path"), 1);
1174
- var import_node_child_process3 = require("child_process");
1268
+ var import_node_child_process4 = require("child_process");
1175
1269
  var serverLogger3 = createLogger("inspecto:server", { logLevel: getGlobalLogLevel() });
1176
- function resolveProjectRoot() {
1177
- const cwd = process.cwd();
1178
- let gitRoot;
1270
+ function resolveGitRoot(_cwd) {
1179
1271
  try {
1180
- 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;
1181
1274
  } catch (e) {
1182
1275
  serverLogger3.warn("Failed to resolve git root via git rev-parse:", e);
1183
- gitRoot = cwd;
1184
- }
1185
- const visited = /* @__PURE__ */ new Set();
1186
- const search = (start, stop) => {
1187
- let current = start;
1188
- while (!visited.has(current)) {
1189
- visited.add(current);
1190
- if (import_node_fs3.default.existsSync(import_node_path3.default.join(current, ".inspecto"))) return current;
1191
- if (current === stop) break;
1192
- const parent = import_node_path3.default.dirname(current);
1193
- if (parent === current) break;
1194
- current = parent;
1195
- }
1196
1276
  return null;
1197
- };
1198
- const cwdMatch = search(cwd, import_node_path3.default.parse(cwd).root);
1199
- if (cwdMatch) return cwdMatch;
1200
- const repoMatch = search(gitRoot, import_node_path3.default.parse(gitRoot).root);
1201
- if (repoMatch) return repoMatch;
1202
- 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;
1203
1316
  }
1204
1317
 
1205
1318
  // src/server/server-url.ts
1206
1319
  function resolveServerHost(cwd, configRoot) {
1320
+ if (process.env["VITEST"]) return "127.0.0.1";
1207
1321
  const userConfig = loadUserConfigSync(false, cwd, configRoot);
1208
1322
  const configuredHost = userConfig["server.host"]?.trim();
1209
1323
  if (configuredHost) return configuredHost;
1210
- if (process.env["VITEST"]) return "127.0.0.1";
1211
1324
  return "127.0.0.1";
1212
1325
  }
1213
1326
 
@@ -1263,7 +1376,7 @@ async function startServer() {
1263
1376
  return serverState.port;
1264
1377
  }
1265
1378
  serverState.projectRoot = resolveProjectRoot();
1266
- serverState.configRoot = serverState.projectRoot;
1379
+ serverState.configRoot = resolveWorkspaceRoot();
1267
1380
  serverState.cwd = process.cwd();
1268
1381
  const serverHost = resolveServerHost(serverState.cwd, serverState.configRoot);
1269
1382
  import_portfinder.default.basePort = 5678;
@@ -1327,19 +1440,19 @@ async function readBody(req) {
1327
1440
  }
1328
1441
  async function handleRequest(url, req, res) {
1329
1442
  const pathname = url.pathname;
1330
- 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") {
1331
1444
  res.writeHead(200, { "Content-Type": "application/json" });
1332
1445
  res.end(JSON.stringify({ ok: true, port: serverState.port }));
1333
1446
  return;
1334
1447
  }
1335
- 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") {
1336
1449
  const config = await buildClientConfig(serverState);
1337
1450
  delete config.providers;
1338
1451
  res.writeHead(200, { "Content-Type": "application/json" });
1339
1452
  res.end(JSON.stringify(config));
1340
1453
  return;
1341
1454
  }
1342
- 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") {
1343
1456
  try {
1344
1457
  const body = JSON.parse(await readBody(req));
1345
1458
  const ideWorkspace = body.workspaceRoot || "";
@@ -1360,13 +1473,13 @@ async function handleRequest(url, req, res) {
1360
1473
  res.writeHead(200, { "Content-Type": "application/json" });
1361
1474
  res.end(JSON.stringify({ success: true }));
1362
1475
  } catch (e) {
1363
- 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);
1364
1477
  res.writeHead(400, { "Content-Type": "application/json" });
1365
1478
  res.end(JSON.stringify({ error: "Invalid JSON body" }));
1366
1479
  }
1367
1480
  return;
1368
1481
  }
1369
- 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") {
1370
1483
  let body;
1371
1484
  try {
1372
1485
  body = JSON.parse(await readBody(req));
@@ -1389,7 +1502,7 @@ async function handleRequest(url, req, res) {
1389
1502
  res.end(JSON.stringify({ success: true }));
1390
1503
  return;
1391
1504
  }
1392
- 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") {
1393
1506
  const file = url.searchParams.get("file") ?? "";
1394
1507
  const line = parseInt(url.searchParams.get("line") ?? "1", 10);
1395
1508
  const column = parseInt(url.searchParams.get("column") ?? "1", 10);
@@ -1423,7 +1536,7 @@ async function handleRequest(url, req, res) {
1423
1536
  }
1424
1537
  return;
1425
1538
  }
1426
- 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") {
1427
1540
  try {
1428
1541
  const rawBody = await readBody(req);
1429
1542
  const body = JSON.parse(rawBody);
@@ -1431,13 +1544,13 @@ async function handleRequest(url, req, res) {
1431
1544
  res.writeHead(result.success ? 200 : 500, { "Content-Type": "application/json" });
1432
1545
  res.end(JSON.stringify(result));
1433
1546
  } catch (e) {
1434
- 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);
1435
1548
  res.writeHead(500, { "Content-Type": "application/json" });
1436
1549
  res.end(JSON.stringify({ success: false, error: String(e), errorCode: "INTERNAL_ERROR" }));
1437
1550
  }
1438
1551
  return;
1439
1552
  }
1440
- 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") {
1441
1554
  try {
1442
1555
  const rawBody = await readBody(req);
1443
1556
  const body = JSON.parse(rawBody);
@@ -1447,13 +1560,13 @@ async function handleRequest(url, req, res) {
1447
1560
  });
1448
1561
  res.end(JSON.stringify(result));
1449
1562
  } catch (e) {
1450
- 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);
1451
1564
  res.writeHead(500, { "Content-Type": "application/json" });
1452
1565
  res.end(JSON.stringify({ success: false, error: String(e), errorCode: "INTERNAL_ERROR" }));
1453
1566
  }
1454
1567
  return;
1455
1568
  }
1456
- 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") {
1457
1570
  try {
1458
1571
  const rawBody = await readBody(req);
1459
1572
  const body = rawBody ? JSON.parse(rawBody) : {};
@@ -1480,7 +1593,7 @@ async function handleRequest(url, req, res) {
1480
1593
  }
1481
1594
  return;
1482
1595
  }
1483
- 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") {
1484
1597
  const statusParam = url.searchParams.getAll("status");
1485
1598
  const statuses = statusParam.length ? new Set(statusParam) : null;
1486
1599
  const sessionId = url.searchParams.get("sessionId")?.trim() || null;
@@ -1508,7 +1621,7 @@ data: ${JSON.stringify({ ok: true })}
1508
1621
  });
1509
1622
  return;
1510
1623
  }
1511
- if (pathname === import_types2.INSPECTO_API_PATHS.SESSIONS && req.method === "GET") {
1624
+ if (pathname === import_types3.INSPECTO_API_PATHS.SESSIONS && req.method === "GET") {
1512
1625
  const statusParam = url.searchParams.getAll("status");
1513
1626
  const sessions = annotationSessionStore.listSessions(
1514
1627
  statusParam.length ? {
@@ -1519,8 +1632,8 @@ data: ${JSON.stringify({ ok: true })}
1519
1632
  res.end(JSON.stringify({ success: true, sessions }));
1520
1633
  return;
1521
1634
  }
1522
- if (pathname.startsWith(`${import_types2.INSPECTO_API_PATHS.SESSIONS}/`) && req.method === "GET") {
1523
- const sessionId = pathname.substring(import_types2.INSPECTO_API_PATHS.SESSIONS.length + 1);
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);
1524
1637
  const session = annotationSessionStore.getSession(sessionId);
1525
1638
  if (!session) {
1526
1639
  res.writeHead(404, { "Content-Type": "application/json" });
@@ -1531,10 +1644,10 @@ data: ${JSON.stringify({ ok: true })}
1531
1644
  res.end(JSON.stringify({ success: true, session }));
1532
1645
  return;
1533
1646
  }
1534
- 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") {
1535
1648
  const sessionId = pathname.slice(
1536
- import_types2.INSPECTO_API_PATHS.SESSIONS.length + 1,
1537
- -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
1538
1651
  );
1539
1652
  try {
1540
1653
  const rawBody = await readBody(req);
@@ -1567,10 +1680,10 @@ data: ${JSON.stringify({ ok: true })}
1567
1680
  }
1568
1681
  return;
1569
1682
  }
1570
- 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") {
1571
1684
  const sessionId = pathname.slice(
1572
- import_types2.INSPECTO_API_PATHS.SESSIONS.length + 1,
1573
- -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
1574
1687
  );
1575
1688
  try {
1576
1689
  const rawBody = await readBody(req);
@@ -1618,10 +1731,10 @@ data: ${JSON.stringify({ ok: true })}
1618
1731
  }
1619
1732
  return;
1620
1733
  }
1621
- 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") {
1622
1735
  const sessionId = pathname.slice(
1623
- import_types2.INSPECTO_API_PATHS.SESSIONS.length + 1,
1624
- -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
1625
1738
  );
1626
1739
  try {
1627
1740
  const rawBody = await readBody(req);
@@ -1659,8 +1772,8 @@ data: ${JSON.stringify({ ok: true })}
1659
1772
  }
1660
1773
  return;
1661
1774
  }
1662
- if (pathname.startsWith(`${import_types2.INSPECTO_API_PATHS.AI_TICKET}/`) && req.method === "GET") {
1663
- 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);
1664
1777
  const payloadStr = readTicket(ticketId);
1665
1778
  if (!payloadStr) {
1666
1779
  res.writeHead(404, { "Content-Type": "application/json" });
@@ -1676,10 +1789,23 @@ data: ${JSON.stringify({ ok: true })}
1676
1789
  }
1677
1790
  async function dispatchToAi(req) {
1678
1791
  const { location, snippet, prompt } = req;
1679
- 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}):
1680
1806
 
1681
1807
  \`\`\`
1682
- ${snippet}
1808
+ ${snippet ?? ""}
1683
1809
  \`\`\`
1684
1810
  `;
1685
1811
  const runtime = resolvePromptDispatchRuntime(serverState);
@@ -1688,7 +1814,7 @@ ${snippet}
1688
1814
  filePath: location.file,
1689
1815
  line: location.line,
1690
1816
  column: location.column,
1691
- snippet
1817
+ ...snippet !== void 0 ? { snippet } : {}
1692
1818
  });
1693
1819
  }
1694
1820
  function getBatchDispatchStatusCode(errorCode, success) {