@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.
@@ -47,7 +47,7 @@ var import_node_path4 = __toESM(require("path"), 1);
47
47
  var import_node_os2 = __toESM(require("os"), 1);
48
48
  var import_node_crypto2 = __toESM(require("crypto"), 1);
49
49
  var import_portfinder = __toESM(require("portfinder"), 1);
50
- var import_types2 = require("@inspecto-dev/types");
50
+ var import_types3 = require("@inspecto-dev/types");
51
51
 
52
52
  // src/server/snippet.ts
53
53
  var fs = __toESM(require("fs"), 1);
@@ -395,13 +395,28 @@ function resolveIntents(serverPrompts) {
395
395
  );
396
396
  continue;
397
397
  }
398
- if (!item.aiIntent) {
399
- configLogger.warn(`Intent "${item.id}" is missing required "aiIntent".`);
400
- continue;
398
+ if (item.kind === "workflow") {
399
+ if (!item.prompt) {
400
+ configLogger.warn(`Workflow "${item.id}" missing required "prompt", skipping`);
401
+ continue;
402
+ }
403
+ result.push({
404
+ kind: "workflow",
405
+ id: item.id,
406
+ label: item.label ?? item.id,
407
+ prompt: item.prompt,
408
+ confirm: item.confirm ?? false,
409
+ enabled: item.enabled ?? true
410
+ });
411
+ } else {
412
+ if (!item.aiIntent) {
413
+ configLogger.warn(`Intent "${item.id}" is missing required "aiIntent".`);
414
+ continue;
415
+ }
416
+ result.push(
417
+ baseMap.has(item.id) ? { ...baseMap.get(item.id), ...item } : item
418
+ );
401
419
  }
402
- result.push(
403
- baseMap.has(item.id) ? { ...baseMap.get(item.id), ...item } : item
404
- );
405
420
  }
406
421
  }
407
422
  return result;
@@ -421,26 +436,61 @@ function resolveIntents(serverPrompts) {
421
436
  configLogger.warn('Intent object missing required "id" field, skipping.');
422
437
  continue;
423
438
  }
424
- if (!item.aiIntent) {
425
- configLogger.warn(`Intent "${item.id}" is missing required "aiIntent".`);
426
- continue;
427
- }
428
- const existingIdx = merged.findIndex((i) => i.id === item.id);
429
- if (existingIdx !== -1) {
430
- if (item.enabled === false) {
431
- merged.splice(existingIdx, 1);
439
+ if (item.kind === "workflow") {
440
+ if (!item.prompt) {
441
+ configLogger.warn(`Workflow "${item.id}" missing required "prompt", skipping`);
442
+ continue;
443
+ }
444
+ const wfConfig = {
445
+ kind: "workflow",
446
+ id: item.id,
447
+ label: item.label ?? item.id,
448
+ prompt: item.prompt,
449
+ confirm: item.confirm ?? false,
450
+ enabled: item.enabled ?? true
451
+ };
452
+ const existingIdx = merged.findIndex((i) => i.id === item.id);
453
+ if (existingIdx !== -1) {
454
+ if (item.enabled === false) {
455
+ merged.splice(existingIdx, 1);
456
+ } else {
457
+ merged[existingIdx] = wfConfig;
458
+ }
432
459
  } else {
433
- merged[existingIdx] = { ...merged[existingIdx], ...item };
460
+ if (item.enabled !== false) {
461
+ merged.push(wfConfig);
462
+ }
434
463
  }
435
464
  } else {
436
- if (item.enabled !== false) {
437
- merged.push(item);
465
+ if (!item.aiIntent) {
466
+ configLogger.warn(`Intent "${item.id}" is missing required "aiIntent".`);
467
+ continue;
468
+ }
469
+ const existingIdx = merged.findIndex((i) => i.id === item.id);
470
+ if (existingIdx !== -1) {
471
+ if (item.enabled === false) {
472
+ merged.splice(existingIdx, 1);
473
+ } else {
474
+ merged[existingIdx] = { ...merged[existingIdx], ...item };
475
+ }
476
+ } else {
477
+ if (item.enabled !== false) {
478
+ merged.push(item);
479
+ }
438
480
  }
439
481
  }
440
482
  }
441
483
  }
442
484
  return merged;
443
485
  }
486
+ function resolveWorkflowSlots(intents) {
487
+ return intents.filter(import_types.isWorkflowConfig).filter((w) => w.enabled !== false).map((w) => ({
488
+ id: w.id,
489
+ label: w.label ?? w.id,
490
+ prompt: w.prompt,
491
+ confirm: w.confirm ?? false
492
+ }));
493
+ }
444
494
  var watchers = [];
445
495
  function watchConfig(onReload, cwd = process.cwd(), gitRoot) {
446
496
  if (isWatching) return;
@@ -670,6 +720,10 @@ function assertPathWithinIdeOpenScope(file, projectRoot) {
670
720
  }
671
721
  }
672
722
 
723
+ // src/server/annotation-dispatch.ts
724
+ var import_node_child_process2 = require("child_process");
725
+ var import_node_util = require("util");
726
+
673
727
  // src/server/session-store.ts
674
728
  var DEFAULT_STATUS = "pending";
675
729
  function createAnnotationSessionStore(options = {}) {
@@ -677,8 +731,12 @@ function createAnnotationSessionStore(options = {}) {
677
731
  const listeners = /* @__PURE__ */ new Set();
678
732
  const now = options.now ?? (() => Date.now());
679
733
  const createId = options.createId ?? createRandomId;
680
- function findNewestMatchingSession(statuses) {
681
- return [...sessions.values()].filter((session) => statuses ? statuses.has(session.status) : true).sort((left, right) => right.updatedAt - left.updatedAt)[0] ?? null;
734
+ function findNewestMatchingSession(statuses, source) {
735
+ return [...sessions.values()].filter((session) => {
736
+ if (statuses && !statuses.has(session.status)) return false;
737
+ if (source && session.source !== source) return false;
738
+ return true;
739
+ }).sort((left, right) => right.updatedAt - left.updatedAt)[0] ?? null;
682
740
  }
683
741
  function updateSessionStatus(id, status) {
684
742
  const session = sessions.get(id);
@@ -738,7 +796,7 @@ function createAnnotationSessionStore(options = {}) {
738
796
  },
739
797
  async claimNextSession(options2 = {}) {
740
798
  const statuses = normalizeStatuses(DEFAULT_STATUS);
741
- const existingSession = findNewestMatchingSession(statuses);
799
+ const existingSession = findNewestMatchingSession(statuses, options2.source);
742
800
  if (existingSession) {
743
801
  return {
744
802
  session: claimSession(existingSession.id, statuses),
@@ -853,6 +911,7 @@ function cloneValue(value) {
853
911
  }
854
912
 
855
913
  // src/server/annotation-dispatch.ts
914
+ var execAsync = (0, import_node_util.promisify)(import_node_child_process2.exec);
856
915
  var AnnotationDispatchError = class extends Error {
857
916
  constructor(message, errorCode) {
858
917
  super(message);
@@ -864,9 +923,14 @@ async function dispatchAnnotationsToAi(req, state, store = annotationSessionStor
864
923
  try {
865
924
  validateAnnotationDispatchRequest(req, state);
866
925
  const batch = normalizeAnnotationBatch(req);
867
- const prompt = buildAnnotationBatchPrompt(batch);
926
+ let prompt = buildAnnotationBatchPrompt(batch);
927
+ if (req.source === "workflow") {
928
+ prompt = await appendProjectMetadata(prompt, state);
929
+ }
868
930
  const deliveryMode = normalizeDeliveryMode(req.deliveryMode);
869
931
  const session = store.createSession({
932
+ source: req.source || "annotation",
933
+ ...req.workflowId ? { workflowId: req.workflowId } : {},
870
934
  instruction: batch.instruction,
871
935
  annotations: toSessionAnnotations(batch.annotations),
872
936
  deliveryMode,
@@ -892,6 +956,33 @@ async function dispatchAnnotationsToAi(req, state, store = annotationSessionStor
892
956
  };
893
957
  }
894
958
  }
959
+ async function appendProjectMetadata(prompt, state) {
960
+ const lines = ["\n## Project"];
961
+ lines.push(`- Root: ${state.projectRoot}`);
962
+ try {
963
+ const options = {
964
+ cwd: state.projectRoot,
965
+ encoding: "utf-8",
966
+ timeout: 2e3
967
+ };
968
+ const { stdout: branchStdout } = await execAsync("git branch --show-current", options);
969
+ const branch = branchStdout.trim();
970
+ lines.push(`- Branch: ${branch}`);
971
+ const { stdout: statusStdout } = await execAsync("git status --porcelain", options);
972
+ const statusRaw = statusStdout.trim();
973
+ const entries = statusRaw ? statusRaw.split("\n") : [];
974
+ const staged = entries.filter((l) => l[0] !== " " && l[0] !== "?").length;
975
+ const unstaged = entries.filter((l) => l[1] !== " " && l[1] !== "?").length;
976
+ const untracked = entries.filter((l) => l[0] === "?").length;
977
+ lines.push(`- Status: ${staged} staged, ${unstaged} unstaged, ${untracked} untracked`);
978
+ } catch (err) {
979
+ console.warn("[inspecto] Failed to get git status for workflow:", err);
980
+ lines.push("- Git: unavailable or check timeout");
981
+ }
982
+ return `${prompt}
983
+
984
+ ${lines.join("\n")}`;
985
+ }
895
986
  function normalizeDeliveryMode(input) {
896
987
  return input === "agent" ? "agent" : "ide";
897
988
  }
@@ -928,7 +1019,7 @@ function toSessionSummary(session) {
928
1019
  };
929
1020
  }
930
1021
  function validateAnnotationDispatchRequest(req, state) {
931
- if (!req.annotations.length) {
1022
+ if (!req.annotations.length && req.source !== "workflow") {
932
1023
  throw new AnnotationDispatchError("At least one annotation is required.", "INVALID_REQUEST");
933
1024
  }
934
1025
  for (const annotation of req.annotations) {
@@ -1030,6 +1121,7 @@ function getAnnotationDispatchErrorCode(error) {
1030
1121
  }
1031
1122
 
1032
1123
  // src/server/client-config.ts
1124
+ var import_types2 = require("@inspecto-dev/types");
1033
1125
  async function buildClientConfig(serverState2) {
1034
1126
  const userConfig = loadUserConfigSync(false, serverState2.cwd, serverState2.configRoot);
1035
1127
  const promptsConfig = await loadPromptsConfig(false, serverState2.cwd, serverState2.configRoot);
@@ -1041,11 +1133,13 @@ async function buildClientConfig(serverState2) {
1041
1133
  const { scheme: _scheme, ...rest } = serverState2.ideInfo;
1042
1134
  info = rest;
1043
1135
  }
1136
+ const allIntents = resolveIntents(promptsConfig);
1044
1137
  return {
1045
1138
  ...info,
1046
- prompts: resolveIntents(promptsConfig),
1139
+ prompts: allIntents.filter(import_types2.isAiIntentConfig),
1140
+ workflows: resolveWorkflowSlots(allIntents),
1047
1141
  hotKeys: userConfig["inspector.hotKey"] ?? "alt",
1048
- annotateDeliveryMode: userConfig["annotate.deliveryMode"] ?? "both",
1142
+ annotateDeliveryMode: userConfig["annotate.deliveryMode"] ?? "agent",
1049
1143
  includeSnippet: userConfig["prompt.includeSnippet"] ?? false,
1050
1144
  runtimeContext: {
1051
1145
  enabled: true,
@@ -1058,7 +1152,7 @@ async function buildClientConfig(serverState2) {
1058
1152
  }
1059
1153
 
1060
1154
  // src/server/open-file.ts
1061
- var import_node_child_process2 = require("child_process");
1155
+ var import_node_child_process3 = require("child_process");
1062
1156
  var import_launch_ide2 = require("launch-ide");
1063
1157
  var serverLogger2 = createLogger("inspecto:server", { logLevel: getGlobalLogLevel() });
1064
1158
  var VSCODE_FAMILY_SCHEMES = [
@@ -1109,11 +1203,11 @@ function handleOpenFileRequest(body, serverState2) {
1109
1203
  serverLogger2.debug(`SOURCE_OPEN: Bypassing launchIDE, using URI scheme directly: ${uri}`);
1110
1204
  try {
1111
1205
  if (process.platform === "darwin") {
1112
- (0, import_node_child_process2.execFileSync)("open", [uri]);
1206
+ (0, import_node_child_process3.execFileSync)("open", [uri]);
1113
1207
  } else if (process.platform === "win32") {
1114
- (0, import_node_child_process2.execFileSync)("cmd", ["/c", "start", '""', uri]);
1208
+ (0, import_node_child_process3.execFileSync)("cmd", ["/c", "start", '""', uri]);
1115
1209
  } else {
1116
- (0, import_node_child_process2.execFileSync)("xdg-open", [uri]);
1210
+ (0, import_node_child_process3.execFileSync)("xdg-open", [uri]);
1117
1211
  }
1118
1212
  } catch (e) {
1119
1213
  serverLogger2.error(`Failed to launch URI for SOURCE_OPEN (${uri}):`, e);
@@ -1140,43 +1234,62 @@ function handleOpenFileRequest(body, serverState2) {
1140
1234
  // src/server/project-root.ts
1141
1235
  var import_node_fs3 = __toESM(require("fs"), 1);
1142
1236
  var import_node_path3 = __toESM(require("path"), 1);
1143
- var import_node_child_process3 = require("child_process");
1237
+ var import_node_child_process4 = require("child_process");
1144
1238
  var serverLogger3 = createLogger("inspecto:server", { logLevel: getGlobalLogLevel() });
1145
- function resolveProjectRoot() {
1146
- const cwd = process.cwd();
1147
- let gitRoot;
1239
+ function resolveGitRoot(_cwd) {
1148
1240
  try {
1149
- gitRoot = (0, import_node_child_process3.execSync)("git rev-parse --show-toplevel", { encoding: "utf-8" }).trim();
1241
+ const output = (0, import_node_child_process4.execSync)("git rev-parse --show-toplevel", { encoding: "utf-8" });
1242
+ return typeof output === "string" ? output.trim() : null;
1150
1243
  } catch (e) {
1151
1244
  serverLogger3.warn("Failed to resolve git root via git rev-parse:", e);
1152
- gitRoot = cwd;
1153
- }
1154
- const visited = /* @__PURE__ */ new Set();
1155
- const search = (start, stop) => {
1156
- let current = start;
1157
- while (!visited.has(current)) {
1158
- visited.add(current);
1159
- if (import_node_fs3.default.existsSync(import_node_path3.default.join(current, ".inspecto"))) return current;
1160
- if (current === stop) break;
1161
- const parent = import_node_path3.default.dirname(current);
1162
- if (parent === current) break;
1163
- current = parent;
1164
- }
1165
1245
  return null;
1166
- };
1167
- const cwdMatch = search(cwd, import_node_path3.default.parse(cwd).root);
1168
- if (cwdMatch) return cwdMatch;
1169
- const repoMatch = search(gitRoot, import_node_path3.default.parse(gitRoot).root);
1170
- if (repoMatch) return repoMatch;
1171
- return gitRoot;
1246
+ }
1247
+ }
1248
+ function findNearestAncestorWith(start, predicate) {
1249
+ let current = start;
1250
+ while (true) {
1251
+ if (predicate(current)) return current;
1252
+ const parent = import_node_path3.default.dirname(current);
1253
+ if (parent === current) break;
1254
+ current = parent;
1255
+ }
1256
+ return null;
1257
+ }
1258
+ function resolveWorkspaceRoot() {
1259
+ const cwd = process.cwd();
1260
+ const inspectoRoot = findNearestAncestorWith(
1261
+ cwd,
1262
+ (dir) => import_node_fs3.default.existsSync(import_node_path3.default.join(dir, ".inspecto"))
1263
+ );
1264
+ if (inspectoRoot) return inspectoRoot;
1265
+ const packageRoot = findNearestAncestorWith(
1266
+ cwd,
1267
+ (dir) => import_node_fs3.default.existsSync(import_node_path3.default.join(dir, "package.json"))
1268
+ );
1269
+ if (packageRoot) return packageRoot;
1270
+ return resolveGitRoot(cwd) ?? cwd;
1271
+ }
1272
+ function resolveProjectRoot() {
1273
+ const cwd = process.cwd();
1274
+ const packageRoot = findNearestAncestorWith(
1275
+ cwd,
1276
+ (dir) => import_node_fs3.default.existsSync(import_node_path3.default.join(dir, "package.json"))
1277
+ );
1278
+ if (packageRoot) return packageRoot;
1279
+ const inspectoRoot = findNearestAncestorWith(
1280
+ cwd,
1281
+ (dir) => import_node_fs3.default.existsSync(import_node_path3.default.join(dir, ".inspecto"))
1282
+ );
1283
+ if (inspectoRoot) return inspectoRoot;
1284
+ return resolveGitRoot(cwd) ?? cwd;
1172
1285
  }
1173
1286
 
1174
1287
  // src/server/server-url.ts
1175
1288
  function resolveServerHost(cwd, configRoot) {
1289
+ if (process.env["VITEST"]) return "127.0.0.1";
1176
1290
  const userConfig = loadUserConfigSync(false, cwd, configRoot);
1177
1291
  const configuredHost = userConfig["server.host"]?.trim();
1178
1292
  if (configuredHost) return configuredHost;
1179
- if (process.env["VITEST"]) return "127.0.0.1";
1180
1293
  return "127.0.0.1";
1181
1294
  }
1182
1295
 
@@ -1232,7 +1345,7 @@ async function startServer() {
1232
1345
  return serverState.port;
1233
1346
  }
1234
1347
  serverState.projectRoot = resolveProjectRoot();
1235
- serverState.configRoot = serverState.projectRoot;
1348
+ serverState.configRoot = resolveWorkspaceRoot();
1236
1349
  serverState.cwd = process.cwd();
1237
1350
  const serverHost = resolveServerHost(serverState.cwd, serverState.configRoot);
1238
1351
  import_portfinder.default.basePort = 5678;
@@ -1296,19 +1409,19 @@ async function readBody(req) {
1296
1409
  }
1297
1410
  async function handleRequest(url, req, res) {
1298
1411
  const pathname = url.pathname;
1299
- if ((pathname === "/health" || pathname === import_types2.INSPECTO_API_PATHS.HEALTH) && req.method === "GET") {
1412
+ if ((pathname === "/health" || pathname === import_types3.INSPECTO_API_PATHS.HEALTH) && req.method === "GET") {
1300
1413
  res.writeHead(200, { "Content-Type": "application/json" });
1301
1414
  res.end(JSON.stringify({ ok: true, port: serverState.port }));
1302
1415
  return;
1303
1416
  }
1304
- if (pathname === import_types2.INSPECTO_API_PATHS.CLIENT_CONFIG && req.method === "GET") {
1417
+ if (pathname === import_types3.INSPECTO_API_PATHS.CLIENT_CONFIG && req.method === "GET") {
1305
1418
  const config = await buildClientConfig(serverState);
1306
1419
  delete config.providers;
1307
1420
  res.writeHead(200, { "Content-Type": "application/json" });
1308
1421
  res.end(JSON.stringify(config));
1309
1422
  return;
1310
1423
  }
1311
- if (pathname === import_types2.INSPECTO_API_PATHS.IDE_INFO && req.method === "POST") {
1424
+ if (pathname === import_types3.INSPECTO_API_PATHS.IDE_INFO && req.method === "POST") {
1312
1425
  try {
1313
1426
  const body = JSON.parse(await readBody(req));
1314
1427
  const ideWorkspace = body.workspaceRoot || "";
@@ -1329,13 +1442,13 @@ async function handleRequest(url, req, res) {
1329
1442
  res.writeHead(200, { "Content-Type": "application/json" });
1330
1443
  res.end(JSON.stringify({ success: true }));
1331
1444
  } catch (e) {
1332
- serverLogger4.error(`Error parsing ${import_types2.INSPECTO_API_PATHS.IDE_INFO} POST request:`, e);
1445
+ serverLogger4.error(`Error parsing ${import_types3.INSPECTO_API_PATHS.IDE_INFO} POST request:`, e);
1333
1446
  res.writeHead(400, { "Content-Type": "application/json" });
1334
1447
  res.end(JSON.stringify({ error: "Invalid JSON body" }));
1335
1448
  }
1336
1449
  return;
1337
1450
  }
1338
- if ((pathname === import_types2.INSPECTO_API_PATHS.SOURCE_OPEN || pathname === import_types2.INSPECTO_API_PATHS.IDE_OPEN) && req.method === "POST") {
1451
+ if ((pathname === import_types3.INSPECTO_API_PATHS.SOURCE_OPEN || pathname === import_types3.INSPECTO_API_PATHS.IDE_OPEN) && req.method === "POST") {
1339
1452
  let body;
1340
1453
  try {
1341
1454
  body = JSON.parse(await readBody(req));
@@ -1358,7 +1471,7 @@ async function handleRequest(url, req, res) {
1358
1471
  res.end(JSON.stringify({ success: true }));
1359
1472
  return;
1360
1473
  }
1361
- if (pathname === import_types2.INSPECTO_API_PATHS.PROJECT_SNIPPET && req.method === "GET") {
1474
+ if (pathname === import_types3.INSPECTO_API_PATHS.PROJECT_SNIPPET && req.method === "GET") {
1362
1475
  const file = url.searchParams.get("file") ?? "";
1363
1476
  const line = parseInt(url.searchParams.get("line") ?? "1", 10);
1364
1477
  const column = parseInt(url.searchParams.get("column") ?? "1", 10);
@@ -1392,7 +1505,7 @@ async function handleRequest(url, req, res) {
1392
1505
  }
1393
1506
  return;
1394
1507
  }
1395
- if (pathname === import_types2.INSPECTO_API_PATHS.AI_DISPATCH && req.method === "POST") {
1508
+ if (pathname === import_types3.INSPECTO_API_PATHS.AI_DISPATCH && req.method === "POST") {
1396
1509
  try {
1397
1510
  const rawBody = await readBody(req);
1398
1511
  const body = JSON.parse(rawBody);
@@ -1400,13 +1513,13 @@ async function handleRequest(url, req, res) {
1400
1513
  res.writeHead(result.success ? 200 : 500, { "Content-Type": "application/json" });
1401
1514
  res.end(JSON.stringify(result));
1402
1515
  } catch (e) {
1403
- serverLogger4.error(`Error parsing ${import_types2.INSPECTO_API_PATHS.AI_DISPATCH} request:`, e);
1516
+ serverLogger4.error(`Error parsing ${import_types3.INSPECTO_API_PATHS.AI_DISPATCH} request:`, e);
1404
1517
  res.writeHead(500, { "Content-Type": "application/json" });
1405
1518
  res.end(JSON.stringify({ success: false, error: String(e), errorCode: "INTERNAL_ERROR" }));
1406
1519
  }
1407
1520
  return;
1408
1521
  }
1409
- if (pathname === import_types2.INSPECTO_API_PATHS.AI_BATCH_DISPATCH && req.method === "POST") {
1522
+ if (pathname === import_types3.INSPECTO_API_PATHS.AI_BATCH_DISPATCH && req.method === "POST") {
1410
1523
  try {
1411
1524
  const rawBody = await readBody(req);
1412
1525
  const body = JSON.parse(rawBody);
@@ -1416,13 +1529,13 @@ async function handleRequest(url, req, res) {
1416
1529
  });
1417
1530
  res.end(JSON.stringify(result));
1418
1531
  } catch (e) {
1419
- serverLogger4.error(`Error parsing ${import_types2.INSPECTO_API_PATHS.AI_BATCH_DISPATCH} request:`, e);
1532
+ serverLogger4.error(`Error parsing ${import_types3.INSPECTO_API_PATHS.AI_BATCH_DISPATCH} request:`, e);
1420
1533
  res.writeHead(500, { "Content-Type": "application/json" });
1421
1534
  res.end(JSON.stringify({ success: false, error: String(e), errorCode: "INTERNAL_ERROR" }));
1422
1535
  }
1423
1536
  return;
1424
1537
  }
1425
- if (pathname === import_types2.INSPECTO_API_PATHS.SESSION_CLAIM_NEXT && req.method === "POST") {
1538
+ if (pathname === import_types3.INSPECTO_API_PATHS.SESSION_CLAIM_NEXT && req.method === "POST") {
1426
1539
  try {
1427
1540
  const rawBody = await readBody(req);
1428
1541
  const body = rawBody ? JSON.parse(rawBody) : {};
@@ -1449,7 +1562,7 @@ async function handleRequest(url, req, res) {
1449
1562
  }
1450
1563
  return;
1451
1564
  }
1452
- if (pathname === import_types2.INSPECTO_API_PATHS.SESSION_EVENTS && req.method === "GET") {
1565
+ if (pathname === import_types3.INSPECTO_API_PATHS.SESSION_EVENTS && req.method === "GET") {
1453
1566
  const statusParam = url.searchParams.getAll("status");
1454
1567
  const statuses = statusParam.length ? new Set(statusParam) : null;
1455
1568
  const sessionId = url.searchParams.get("sessionId")?.trim() || null;
@@ -1477,7 +1590,7 @@ data: ${JSON.stringify({ ok: true })}
1477
1590
  });
1478
1591
  return;
1479
1592
  }
1480
- if (pathname === import_types2.INSPECTO_API_PATHS.SESSIONS && req.method === "GET") {
1593
+ if (pathname === import_types3.INSPECTO_API_PATHS.SESSIONS && req.method === "GET") {
1481
1594
  const statusParam = url.searchParams.getAll("status");
1482
1595
  const sessions = annotationSessionStore.listSessions(
1483
1596
  statusParam.length ? {
@@ -1488,8 +1601,8 @@ data: ${JSON.stringify({ ok: true })}
1488
1601
  res.end(JSON.stringify({ success: true, sessions }));
1489
1602
  return;
1490
1603
  }
1491
- if (pathname.startsWith(`${import_types2.INSPECTO_API_PATHS.SESSIONS}/`) && req.method === "GET") {
1492
- const sessionId = pathname.substring(import_types2.INSPECTO_API_PATHS.SESSIONS.length + 1);
1604
+ if (pathname.startsWith(`${import_types3.INSPECTO_API_PATHS.SESSIONS}/`) && req.method === "GET") {
1605
+ const sessionId = pathname.substring(import_types3.INSPECTO_API_PATHS.SESSIONS.length + 1);
1493
1606
  const session = annotationSessionStore.getSession(sessionId);
1494
1607
  if (!session) {
1495
1608
  res.writeHead(404, { "Content-Type": "application/json" });
@@ -1500,10 +1613,10 @@ data: ${JSON.stringify({ ok: true })}
1500
1613
  res.end(JSON.stringify({ success: true, session }));
1501
1614
  return;
1502
1615
  }
1503
- if (pathname.startsWith(`${import_types2.INSPECTO_API_PATHS.SESSIONS}/`) && pathname.endsWith(import_types2.INSPECTO_API_PATHS.SESSION_REPLY_SUFFIX) && req.method === "POST") {
1616
+ if (pathname.startsWith(`${import_types3.INSPECTO_API_PATHS.SESSIONS}/`) && pathname.endsWith(import_types3.INSPECTO_API_PATHS.SESSION_REPLY_SUFFIX) && req.method === "POST") {
1504
1617
  const sessionId = pathname.slice(
1505
- import_types2.INSPECTO_API_PATHS.SESSIONS.length + 1,
1506
- -import_types2.INSPECTO_API_PATHS.SESSION_REPLY_SUFFIX.length
1618
+ import_types3.INSPECTO_API_PATHS.SESSIONS.length + 1,
1619
+ -import_types3.INSPECTO_API_PATHS.SESSION_REPLY_SUFFIX.length
1507
1620
  );
1508
1621
  try {
1509
1622
  const rawBody = await readBody(req);
@@ -1536,10 +1649,10 @@ data: ${JSON.stringify({ ok: true })}
1536
1649
  }
1537
1650
  return;
1538
1651
  }
1539
- if (pathname.startsWith(`${import_types2.INSPECTO_API_PATHS.SESSIONS}/`) && pathname.endsWith(import_types2.INSPECTO_API_PATHS.SESSION_RESOLVE_SUFFIX) && req.method === "POST") {
1652
+ if (pathname.startsWith(`${import_types3.INSPECTO_API_PATHS.SESSIONS}/`) && pathname.endsWith(import_types3.INSPECTO_API_PATHS.SESSION_RESOLVE_SUFFIX) && req.method === "POST") {
1540
1653
  const sessionId = pathname.slice(
1541
- import_types2.INSPECTO_API_PATHS.SESSIONS.length + 1,
1542
- -import_types2.INSPECTO_API_PATHS.SESSION_RESOLVE_SUFFIX.length
1654
+ import_types3.INSPECTO_API_PATHS.SESSIONS.length + 1,
1655
+ -import_types3.INSPECTO_API_PATHS.SESSION_RESOLVE_SUFFIX.length
1543
1656
  );
1544
1657
  try {
1545
1658
  const rawBody = await readBody(req);
@@ -1587,10 +1700,10 @@ data: ${JSON.stringify({ ok: true })}
1587
1700
  }
1588
1701
  return;
1589
1702
  }
1590
- if (pathname.startsWith(`${import_types2.INSPECTO_API_PATHS.SESSIONS}/`) && pathname.endsWith(import_types2.INSPECTO_API_PATHS.SESSION_DISMISS_SUFFIX) && req.method === "POST") {
1703
+ if (pathname.startsWith(`${import_types3.INSPECTO_API_PATHS.SESSIONS}/`) && pathname.endsWith(import_types3.INSPECTO_API_PATHS.SESSION_DISMISS_SUFFIX) && req.method === "POST") {
1591
1704
  const sessionId = pathname.slice(
1592
- import_types2.INSPECTO_API_PATHS.SESSIONS.length + 1,
1593
- -import_types2.INSPECTO_API_PATHS.SESSION_DISMISS_SUFFIX.length
1705
+ import_types3.INSPECTO_API_PATHS.SESSIONS.length + 1,
1706
+ -import_types3.INSPECTO_API_PATHS.SESSION_DISMISS_SUFFIX.length
1594
1707
  );
1595
1708
  try {
1596
1709
  const rawBody = await readBody(req);
@@ -1628,8 +1741,8 @@ data: ${JSON.stringify({ ok: true })}
1628
1741
  }
1629
1742
  return;
1630
1743
  }
1631
- if (pathname.startsWith(`${import_types2.INSPECTO_API_PATHS.AI_TICKET}/`) && req.method === "GET") {
1632
- const ticketId = pathname.substring(import_types2.INSPECTO_API_PATHS.AI_TICKET.length + 1);
1744
+ if (pathname.startsWith(`${import_types3.INSPECTO_API_PATHS.AI_TICKET}/`) && req.method === "GET") {
1745
+ const ticketId = pathname.substring(import_types3.INSPECTO_API_PATHS.AI_TICKET.length + 1);
1633
1746
  const payloadStr = readTicket(ticketId);
1634
1747
  if (!payloadStr) {
1635
1748
  res.writeHead(404, { "Content-Type": "application/json" });
@@ -1645,10 +1758,23 @@ data: ${JSON.stringify({ ok: true })}
1645
1758
  }
1646
1759
  async function dispatchToAi(req) {
1647
1760
  const { location, snippet, prompt } = req;
1648
- const formattedPrompt = prompt ?? `Please help me with this code from \`${location.file}\` (line ${location.line}):
1761
+ if (prompt?.trim()) {
1762
+ const runtime2 = resolvePromptDispatchRuntime(serverState);
1763
+ return dispatchPromptThroughIde(runtime2, {
1764
+ prompt: prompt.trim()
1765
+ });
1766
+ }
1767
+ if (!location) {
1768
+ return {
1769
+ success: false,
1770
+ error: "Source location is required when prompt is omitted.",
1771
+ errorCode: "INVALID_REQUEST"
1772
+ };
1773
+ }
1774
+ const formattedPrompt = `Please help me with this code from \`${location.file}\` (line ${location.line}):
1649
1775
 
1650
1776
  \`\`\`
1651
- ${snippet}
1777
+ ${snippet ?? ""}
1652
1778
  \`\`\`
1653
1779
  `;
1654
1780
  const runtime = resolvePromptDispatchRuntime(serverState);
@@ -1657,7 +1783,7 @@ ${snippet}
1657
1783
  filePath: location.file,
1658
1784
  line: location.line,
1659
1785
  column: location.column,
1660
- snippet
1786
+ ...snippet !== void 0 ? { snippet } : {}
1661
1787
  });
1662
1788
  }
1663
1789
  function getBatchDispatchStatusCode(errorCode, success) {