@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.
@@ -36,7 +36,7 @@ __export(rspack_exports, {
36
36
  });
37
37
  module.exports = __toCommonJS(rspack_exports);
38
38
 
39
- // ../../node_modules/.pnpm/tsup@8.5.1_jiti@2.6.1_postcss@8.5.10_typescript@5.9.3_yaml@2.8.3/node_modules/tsup/assets/cjs_shims.js
39
+ // ../../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
40
40
  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;
41
41
  var importMetaUrl = /* @__PURE__ */ getImportMetaUrl();
42
42
 
@@ -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,35 +1234,63 @@ 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;
1285
+ }
1286
+
1287
+ // src/server/server-url.ts
1288
+ function resolveServerHost(cwd, configRoot) {
1289
+ if (process.env["VITEST"]) return "127.0.0.1";
1290
+ const userConfig = loadUserConfigSync(false, cwd, configRoot);
1291
+ const configuredHost = userConfig["server.host"]?.trim();
1292
+ if (configuredHost) return configuredHost;
1293
+ return "127.0.0.1";
1172
1294
  }
1173
1295
 
1174
1296
  // src/server/index.ts
@@ -1223,8 +1345,9 @@ async function startServer() {
1223
1345
  return serverState.port;
1224
1346
  }
1225
1347
  serverState.projectRoot = resolveProjectRoot();
1226
- serverState.configRoot = serverState.projectRoot;
1348
+ serverState.configRoot = resolveWorkspaceRoot();
1227
1349
  serverState.cwd = process.cwd();
1350
+ const serverHost = resolveServerHost(serverState.cwd, serverState.configRoot);
1228
1351
  import_portfinder.default.basePort = 5678;
1229
1352
  const port = await import_portfinder.default.getPortPromise();
1230
1353
  watchConfig(
@@ -1251,7 +1374,7 @@ async function startServer() {
1251
1374
  });
1252
1375
  });
1253
1376
  await new Promise((resolve2, reject) => {
1254
- serverInstance.listen(port, "0.0.0.0", () => {
1377
+ serverInstance.listen(port, serverHost, () => {
1255
1378
  serverInstance.unref();
1256
1379
  resolve2();
1257
1380
  });
@@ -1273,7 +1396,7 @@ async function startServer() {
1273
1396
  } catch {
1274
1397
  }
1275
1398
  });
1276
- serverLogger4.info(`server running at http://0.0.0.0:${port}`);
1399
+ serverLogger4.info(`server running at http://${serverHost}:${port}`);
1277
1400
  return port;
1278
1401
  }
1279
1402
  async function readBody(req) {
@@ -1286,19 +1409,19 @@ async function readBody(req) {
1286
1409
  }
1287
1410
  async function handleRequest(url, req, res) {
1288
1411
  const pathname = url.pathname;
1289
- 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") {
1290
1413
  res.writeHead(200, { "Content-Type": "application/json" });
1291
1414
  res.end(JSON.stringify({ ok: true, port: serverState.port }));
1292
1415
  return;
1293
1416
  }
1294
- 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") {
1295
1418
  const config = await buildClientConfig(serverState);
1296
1419
  delete config.providers;
1297
1420
  res.writeHead(200, { "Content-Type": "application/json" });
1298
1421
  res.end(JSON.stringify(config));
1299
1422
  return;
1300
1423
  }
1301
- 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") {
1302
1425
  try {
1303
1426
  const body = JSON.parse(await readBody(req));
1304
1427
  const ideWorkspace = body.workspaceRoot || "";
@@ -1319,13 +1442,13 @@ async function handleRequest(url, req, res) {
1319
1442
  res.writeHead(200, { "Content-Type": "application/json" });
1320
1443
  res.end(JSON.stringify({ success: true }));
1321
1444
  } catch (e) {
1322
- 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);
1323
1446
  res.writeHead(400, { "Content-Type": "application/json" });
1324
1447
  res.end(JSON.stringify({ error: "Invalid JSON body" }));
1325
1448
  }
1326
1449
  return;
1327
1450
  }
1328
- 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") {
1329
1452
  let body;
1330
1453
  try {
1331
1454
  body = JSON.parse(await readBody(req));
@@ -1348,7 +1471,7 @@ async function handleRequest(url, req, res) {
1348
1471
  res.end(JSON.stringify({ success: true }));
1349
1472
  return;
1350
1473
  }
1351
- 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") {
1352
1475
  const file = url.searchParams.get("file") ?? "";
1353
1476
  const line = parseInt(url.searchParams.get("line") ?? "1", 10);
1354
1477
  const column = parseInt(url.searchParams.get("column") ?? "1", 10);
@@ -1382,7 +1505,7 @@ async function handleRequest(url, req, res) {
1382
1505
  }
1383
1506
  return;
1384
1507
  }
1385
- 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") {
1386
1509
  try {
1387
1510
  const rawBody = await readBody(req);
1388
1511
  const body = JSON.parse(rawBody);
@@ -1390,13 +1513,13 @@ async function handleRequest(url, req, res) {
1390
1513
  res.writeHead(result.success ? 200 : 500, { "Content-Type": "application/json" });
1391
1514
  res.end(JSON.stringify(result));
1392
1515
  } catch (e) {
1393
- 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);
1394
1517
  res.writeHead(500, { "Content-Type": "application/json" });
1395
1518
  res.end(JSON.stringify({ success: false, error: String(e), errorCode: "INTERNAL_ERROR" }));
1396
1519
  }
1397
1520
  return;
1398
1521
  }
1399
- 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") {
1400
1523
  try {
1401
1524
  const rawBody = await readBody(req);
1402
1525
  const body = JSON.parse(rawBody);
@@ -1406,13 +1529,13 @@ async function handleRequest(url, req, res) {
1406
1529
  });
1407
1530
  res.end(JSON.stringify(result));
1408
1531
  } catch (e) {
1409
- 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);
1410
1533
  res.writeHead(500, { "Content-Type": "application/json" });
1411
1534
  res.end(JSON.stringify({ success: false, error: String(e), errorCode: "INTERNAL_ERROR" }));
1412
1535
  }
1413
1536
  return;
1414
1537
  }
1415
- 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") {
1416
1539
  try {
1417
1540
  const rawBody = await readBody(req);
1418
1541
  const body = rawBody ? JSON.parse(rawBody) : {};
@@ -1439,7 +1562,7 @@ async function handleRequest(url, req, res) {
1439
1562
  }
1440
1563
  return;
1441
1564
  }
1442
- 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") {
1443
1566
  const statusParam = url.searchParams.getAll("status");
1444
1567
  const statuses = statusParam.length ? new Set(statusParam) : null;
1445
1568
  const sessionId = url.searchParams.get("sessionId")?.trim() || null;
@@ -1467,7 +1590,7 @@ data: ${JSON.stringify({ ok: true })}
1467
1590
  });
1468
1591
  return;
1469
1592
  }
1470
- if (pathname === import_types2.INSPECTO_API_PATHS.SESSIONS && req.method === "GET") {
1593
+ if (pathname === import_types3.INSPECTO_API_PATHS.SESSIONS && req.method === "GET") {
1471
1594
  const statusParam = url.searchParams.getAll("status");
1472
1595
  const sessions = annotationSessionStore.listSessions(
1473
1596
  statusParam.length ? {
@@ -1478,8 +1601,8 @@ data: ${JSON.stringify({ ok: true })}
1478
1601
  res.end(JSON.stringify({ success: true, sessions }));
1479
1602
  return;
1480
1603
  }
1481
- if (pathname.startsWith(`${import_types2.INSPECTO_API_PATHS.SESSIONS}/`) && req.method === "GET") {
1482
- 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);
1483
1606
  const session = annotationSessionStore.getSession(sessionId);
1484
1607
  if (!session) {
1485
1608
  res.writeHead(404, { "Content-Type": "application/json" });
@@ -1490,10 +1613,10 @@ data: ${JSON.stringify({ ok: true })}
1490
1613
  res.end(JSON.stringify({ success: true, session }));
1491
1614
  return;
1492
1615
  }
1493
- 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") {
1494
1617
  const sessionId = pathname.slice(
1495
- import_types2.INSPECTO_API_PATHS.SESSIONS.length + 1,
1496
- -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
1497
1620
  );
1498
1621
  try {
1499
1622
  const rawBody = await readBody(req);
@@ -1526,10 +1649,10 @@ data: ${JSON.stringify({ ok: true })}
1526
1649
  }
1527
1650
  return;
1528
1651
  }
1529
- 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") {
1530
1653
  const sessionId = pathname.slice(
1531
- import_types2.INSPECTO_API_PATHS.SESSIONS.length + 1,
1532
- -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
1533
1656
  );
1534
1657
  try {
1535
1658
  const rawBody = await readBody(req);
@@ -1577,10 +1700,10 @@ data: ${JSON.stringify({ ok: true })}
1577
1700
  }
1578
1701
  return;
1579
1702
  }
1580
- 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") {
1581
1704
  const sessionId = pathname.slice(
1582
- import_types2.INSPECTO_API_PATHS.SESSIONS.length + 1,
1583
- -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
1584
1707
  );
1585
1708
  try {
1586
1709
  const rawBody = await readBody(req);
@@ -1618,8 +1741,8 @@ data: ${JSON.stringify({ ok: true })}
1618
1741
  }
1619
1742
  return;
1620
1743
  }
1621
- if (pathname.startsWith(`${import_types2.INSPECTO_API_PATHS.AI_TICKET}/`) && req.method === "GET") {
1622
- 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);
1623
1746
  const payloadStr = readTicket(ticketId);
1624
1747
  if (!payloadStr) {
1625
1748
  res.writeHead(404, { "Content-Type": "application/json" });
@@ -1635,10 +1758,23 @@ data: ${JSON.stringify({ ok: true })}
1635
1758
  }
1636
1759
  async function dispatchToAi(req) {
1637
1760
  const { location, snippet, prompt } = req;
1638
- 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}):
1639
1775
 
1640
1776
  \`\`\`
1641
- ${snippet}
1777
+ ${snippet ?? ""}
1642
1778
  \`\`\`
1643
1779
  `;
1644
1780
  const runtime = resolvePromptDispatchRuntime(serverState);
@@ -1647,7 +1783,7 @@ ${snippet}
1647
1783
  filePath: location.file,
1648
1784
  line: location.line,
1649
1785
  column: location.column,
1650
- snippet
1786
+ ...snippet !== void 0 ? { snippet } : {}
1651
1787
  });
1652
1788
  }
1653
1789
  function getBatchDispatchStatusCode(errorCode, success) {
@@ -1690,13 +1826,14 @@ var resolveClientModule = () => {
1690
1826
  };
1691
1827
 
1692
1828
  // src/injectors/webpack.ts
1693
- function getWebpackHtmlScript(serverPort2) {
1829
+ function getWebpackHtmlScript(serverPort2, publicServerUrl) {
1694
1830
  return `
1695
1831
  window.__AI_INSPECTOR_PORT__ = ${serverPort2};
1832
+ window.__AI_INSPECTOR_SERVER_URL__ = '${publicServerUrl ?? `http://127.0.0.1:${serverPort2}`}';
1696
1833
  window.addEventListener('load', () => {
1697
1834
  if (window.InspectoClient) {
1698
1835
  window.InspectoClient.mountInspector({
1699
- serverUrl: 'http://0.0.0.0:' + window.__AI_INSPECTOR_PORT__,
1836
+ serverUrl: window.__AI_INSPECTOR_SERVER_URL__,
1700
1837
  });
1701
1838
  }
1702
1839
  });