@inspecto-dev/plugin 0.3.7 → 0.3.9

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.
Files changed (54) hide show
  1. package/README.md +2 -1
  2. package/dist/astro.cjs +2687 -0
  3. package/dist/astro.cjs.map +1 -0
  4. package/dist/astro.d.cts +17 -0
  5. package/dist/astro.d.ts +17 -0
  6. package/dist/astro.js +2656 -0
  7. package/dist/astro.js.map +1 -0
  8. package/dist/index.cjs +932 -87
  9. package/dist/index.cjs.map +1 -1
  10. package/dist/index.d.cts +22 -1
  11. package/dist/index.d.ts +22 -1
  12. package/dist/index.js +930 -87
  13. package/dist/index.js.map +1 -1
  14. package/dist/legacy/rspack/index.cjs +530 -89
  15. package/dist/legacy/rspack/index.cjs.map +1 -1
  16. package/dist/legacy/rspack/index.js +530 -89
  17. package/dist/legacy/rspack/index.js.map +1 -1
  18. package/dist/legacy/rspack/loader.cjs +407 -3
  19. package/dist/legacy/rspack/loader.cjs.map +1 -1
  20. package/dist/legacy/rspack/loader.js +403 -3
  21. package/dist/legacy/rspack/loader.js.map +1 -1
  22. package/dist/legacy/webpack4/index.cjs +519 -78
  23. package/dist/legacy/webpack4/index.cjs.map +1 -1
  24. package/dist/legacy/webpack4/index.js +519 -78
  25. package/dist/legacy/webpack4/index.js.map +1 -1
  26. package/dist/legacy/webpack4/loader.cjs +407 -3
  27. package/dist/legacy/webpack4/loader.cjs.map +1 -1
  28. package/dist/legacy/webpack4/loader.js +403 -3
  29. package/dist/legacy/webpack4/loader.js.map +1 -1
  30. package/dist/rollup.cjs +932 -87
  31. package/dist/rollup.cjs.map +1 -1
  32. package/dist/rollup.d.cts +1 -1
  33. package/dist/rollup.d.ts +1 -1
  34. package/dist/rollup.js +930 -87
  35. package/dist/rollup.js.map +1 -1
  36. package/dist/rspack.cjs +932 -87
  37. package/dist/rspack.cjs.map +1 -1
  38. package/dist/rspack.d.cts +1 -1
  39. package/dist/rspack.d.ts +1 -1
  40. package/dist/rspack.js +930 -87
  41. package/dist/rspack.js.map +1 -1
  42. package/dist/vite.cjs +932 -87
  43. package/dist/vite.cjs.map +1 -1
  44. package/dist/vite.d.cts +1 -1
  45. package/dist/vite.d.ts +1 -1
  46. package/dist/vite.js +930 -87
  47. package/dist/vite.js.map +1 -1
  48. package/dist/webpack.cjs +932 -87
  49. package/dist/webpack.cjs.map +1 -1
  50. package/dist/webpack.d.cts +1 -1
  51. package/dist/webpack.d.ts +1 -1
  52. package/dist/webpack.js +930 -87
  53. package/dist/webpack.js.map +1 -1
  54. package/package.json +13 -10
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
2
- get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
2
+ get: (a, b2) => (typeof require !== "undefined" ? require : a)[b2]
3
3
  }) : x)(function(x) {
4
4
  if (typeof require !== "undefined") return require.apply(this, arguments);
5
5
  throw Error('Dynamic require of "' + x + '" is not supported');
@@ -80,14 +80,14 @@ function extractTransformFilePath(requestId) {
80
80
  wrapped: filePath !== requestId
81
81
  };
82
82
  }
83
- function shouldTransform(filePath, options) {
83
+ function shouldTransform(filePath, _options) {
84
84
  const resolvedFilePath = extractTransformFilePath(filePath).filePath;
85
85
  if (process.env["NODE_ENV"] === "production") return false;
86
86
  if (resolvedFilePath.includes("node_modules")) return false;
87
87
  if (resolvedFilePath.startsWith("\0")) return false;
88
88
  if (/[/\\](dist|build|\.next|\.nuxt)[/\\]/.test(resolvedFilePath)) return false;
89
89
  const ext = resolvedFilePath.split(".").pop()?.toLowerCase();
90
- if (ext && !["js", "jsx", "ts", "tsx", "mjs", "mts", "vue"].includes(ext)) {
90
+ if (ext && !["js", "jsx", "ts", "tsx", "mjs", "mts", "vue", "svelte", "astro"].includes(ext)) {
91
91
  return false;
92
92
  }
93
93
  return true;
@@ -248,7 +248,7 @@ function transformVue(options) {
248
248
  if (escapeTagsSet.has(tagName)) return;
249
249
  if (tagName === "template" && node === ast.children[0]) return;
250
250
  const alreadyHasAttr = node.props.some(
251
- (p) => p.type === NodeTypes.ATTRIBUTE && p.name === attributeName
251
+ (p2) => p2.type === NodeTypes.ATTRIBUTE && p2.name === attributeName
252
252
  );
253
253
  if (alreadyHasAttr) return;
254
254
  const loc = node.loc;
@@ -285,6 +285,387 @@ function walkElement(node, visitor) {
285
285
  }
286
286
  }
287
287
 
288
+ // src/transform/transform-svelte.ts
289
+ import MagicString3 from "magic-string";
290
+ import { parse as parseSvelte } from "svelte/compiler";
291
+ function walk(node, visitor) {
292
+ if (!node || typeof node !== "object") return;
293
+ visitor.enter(node);
294
+ for (const key in node) {
295
+ if (key === "parent" || key === "prev" || key === "next") continue;
296
+ const value = node[key];
297
+ if (Array.isArray(value)) {
298
+ value.forEach((child) => {
299
+ if (child && typeof child === "object") walk(child, visitor);
300
+ });
301
+ } else if (value && typeof value === "object") {
302
+ walk(value, visitor);
303
+ }
304
+ }
305
+ }
306
+ function transformSvelte(options) {
307
+ const { filePath, source, escapeTags, attributeName = "data-inspecto" } = options;
308
+ const escapeTagsSet = buildEscapeTagsSet(escapeTags);
309
+ let replacedContent = source;
310
+ const scriptRegex = /<script(?:\s+[a-zA-Z-]+(?:\s*=\s*(?:"[^"]*"|'[^']*'|[^>\s]*))?)?>[\s\S]*?<\/script>/gi;
311
+ const styleRegex = /<style(?:\s+[a-zA-Z-]+(?:\s*=\s*(?:"[^"]*"|'[^']*'|[^>\s]*))?)?>[\s\S]*?<\/style>/gi;
312
+ const scriptMatches = source.match(scriptRegex) || [];
313
+ const styleMatches = source.match(styleRegex) || [];
314
+ [...scriptMatches, ...styleMatches].forEach((match) => {
315
+ replacedContent = replacedContent.replace(match, " ".repeat(match.length));
316
+ });
317
+ let ast;
318
+ try {
319
+ ast = parseSvelte(replacedContent);
320
+ } catch {
321
+ return { code: source, map: null, changed: false };
322
+ }
323
+ const s2 = new MagicString3(source);
324
+ let changed = false;
325
+ function countLines(text, position) {
326
+ let lines = 0;
327
+ for (let i2 = 0; i2 < position; i2++) {
328
+ if (text[i2] === "\n") lines++;
329
+ }
330
+ return lines;
331
+ }
332
+ const root = ast.html || ast.fragment || ast;
333
+ walk(root, {
334
+ enter(node) {
335
+ if (node.type === "Element" || node.type === "RegularElement" || node.type === "InlineComponent" || node.type === "Component") {
336
+ const tagName = node.name || "";
337
+ if (tagName && !escapeTagsSet.has(tagName.toLowerCase()) && !node.attributes?.some((attr) => attr.name === attributeName)) {
338
+ const insertPosition = node.start + tagName.length + 1;
339
+ const line = countLines(source, node.start) + 1;
340
+ const lastNewLine = source.lastIndexOf("\n", node.start - 1);
341
+ const column = lastNewLine === -1 ? node.start + 1 : node.start - lastNewLine;
342
+ const attrValue = formatAttrValue(filePath, line, column);
343
+ const addition = ` ${attributeName}="${attrValue}"`;
344
+ s2.appendLeft(insertPosition, addition);
345
+ changed = true;
346
+ }
347
+ }
348
+ }
349
+ });
350
+ return {
351
+ code: s2.toString(),
352
+ map: changed ? s2.generateMap({ source: filePath, includeContent: true }) : null,
353
+ changed
354
+ };
355
+ }
356
+
357
+ // src/transform/transform-astro.ts
358
+ import MagicString4 from "magic-string";
359
+
360
+ // ../../node_modules/.pnpm/@astrojs+compiler@3.0.1/node_modules/@astrojs/compiler/dist/chunk-W5DTLHV4.js
361
+ import g from "crypto";
362
+ import _ from "fs";
363
+ import { TextDecoder as b, TextEncoder as v } from "util";
364
+ globalThis.fs || Object.defineProperty(globalThis, "fs", { value: _ });
365
+ globalThis.process || Object.defineProperties(globalThis, "process", { value: process });
366
+ globalThis.crypto || Object.defineProperty(globalThis, "crypto", { value: g.webcrypto ? g.webcrypto : { getRandomValues(m2) {
367
+ return g.randomFillSync(m2);
368
+ } } });
369
+ globalThis.performance || Object.defineProperty(globalThis, "performance", { value: { now() {
370
+ let [m2, o] = process.hrtime();
371
+ return m2 * 1e3 + o / 1e6;
372
+ } } });
373
+ var y = new v("utf-8");
374
+ var w = new b("utf-8");
375
+ var d = class {
376
+ constructor() {
377
+ this.argv = ["js"], this.env = {}, this.exit = (t) => {
378
+ t !== 0 && console.warn("exit code:", t);
379
+ }, this._exitPromise = new Promise((t) => {
380
+ this._resolveExitPromise = t;
381
+ }), this._pendingEvent = null, this._scheduledTimeouts = /* @__PURE__ */ new Map(), this._nextCallbackTimeoutID = 1;
382
+ let o = (t, e) => {
383
+ this.mem.setUint32(t + 0, e, true), this.mem.setUint32(t + 4, Math.floor(e / 4294967296), true);
384
+ }, n = (t) => {
385
+ let e = this.mem.getUint32(t + 0, true), s2 = this.mem.getInt32(t + 4, true);
386
+ return e + s2 * 4294967296;
387
+ }, r = (t) => {
388
+ let e = this.mem.getFloat64(t, true);
389
+ if (e === 0) return;
390
+ if (!isNaN(e)) return e;
391
+ let s2 = this.mem.getUint32(t, true);
392
+ return this._values[s2];
393
+ }, l = (t, e) => {
394
+ if (typeof e == "number" && e !== 0) {
395
+ if (isNaN(e)) {
396
+ this.mem.setUint32(t + 4, 2146959360, true), this.mem.setUint32(t, 0, true);
397
+ return;
398
+ }
399
+ this.mem.setFloat64(t, e, true);
400
+ return;
401
+ }
402
+ if (e === void 0) {
403
+ this.mem.setFloat64(t, 0, true);
404
+ return;
405
+ }
406
+ let i2 = this._ids.get(e);
407
+ i2 === void 0 && (i2 = this._idPool.pop(), i2 === void 0 && (i2 = this._values.length), this._values[i2] = e, this._goRefCounts[i2] = 0, this._ids.set(e, i2)), this._goRefCounts[i2]++;
408
+ let a = 0;
409
+ switch (typeof e) {
410
+ case "object":
411
+ e !== null && (a = 1);
412
+ break;
413
+ case "string":
414
+ a = 2;
415
+ break;
416
+ case "symbol":
417
+ a = 3;
418
+ break;
419
+ case "function":
420
+ a = 4;
421
+ break;
422
+ }
423
+ this.mem.setUint32(t + 4, 2146959360 | a, true), this.mem.setUint32(t, i2, true);
424
+ }, c = (t) => {
425
+ let e = n(t + 0), s2 = n(t + 8);
426
+ return new Uint8Array(this._inst.exports.mem.buffer, e, s2);
427
+ }, f2 = (t) => {
428
+ let e = n(t + 0), s2 = n(t + 8), i2 = new Array(s2);
429
+ for (let a = 0; a < s2; a++) i2[a] = r(e + a * 8);
430
+ return i2;
431
+ }, u = (t) => {
432
+ let e = n(t + 0), s2 = n(t + 8);
433
+ return w.decode(new DataView(this._inst.exports.mem.buffer, e, s2));
434
+ }, h = Date.now() - performance.now();
435
+ this.importObject = { gojs: { "runtime.wasmExit": (t) => {
436
+ t >>>= 0;
437
+ let e = this.mem.getInt32(t + 8, true);
438
+ this.exited = true, delete this._inst, delete this._values, delete this._goRefCounts, delete this._ids, delete this._idPool, this.exit(e);
439
+ }, "runtime.wasmWrite": (t) => {
440
+ t >>>= 0;
441
+ let e = n(t + 8), s2 = n(t + 16), i2 = this.mem.getInt32(t + 24, true);
442
+ _.writeSync(e, new Uint8Array(this._inst.exports.mem.buffer, s2, i2));
443
+ }, "runtime.resetMemoryDataView": (t) => {
444
+ t >>>= 0, this.mem = new DataView(this._inst.exports.mem.buffer);
445
+ }, "runtime.nanotime1": (t) => {
446
+ t >>>= 0, o(t + 8, (h + performance.now()) * 1e6);
447
+ }, "runtime.walltime": (t) => {
448
+ t >>>= 0;
449
+ let e = (/* @__PURE__ */ new Date()).getTime();
450
+ o(t + 8, e / 1e3), this.mem.setInt32(t + 16, e % 1e3 * 1e6, true);
451
+ }, "runtime.scheduleTimeoutEvent": (t) => {
452
+ t >>>= 0;
453
+ let e = this._nextCallbackTimeoutID;
454
+ this._nextCallbackTimeoutID++, this._scheduledTimeouts.set(e, setTimeout(() => {
455
+ for (this._resume(); this._scheduledTimeouts.has(e); ) console.warn("scheduleTimeoutEvent: missed timeout event"), this._resume();
456
+ }, n(t + 8) + 1)), this.mem.setInt32(t + 16, e, true);
457
+ }, "runtime.clearTimeoutEvent": (t) => {
458
+ t >>>= 0;
459
+ let e = this.mem.getInt32(t + 8, true);
460
+ clearTimeout(this._scheduledTimeouts.get(e)), this._scheduledTimeouts.delete(e);
461
+ }, "runtime.getRandomData": (t) => {
462
+ t >>>= 0, globalThis.crypto.getRandomValues(c(t + 8));
463
+ }, "syscall/js.finalizeRef": (t) => {
464
+ t >>>= 0;
465
+ let e = this.mem.getUint32(t + 8, true);
466
+ if (this._goRefCounts[e]--, this._goRefCounts[e] === 0) {
467
+ let s2 = this._values[e];
468
+ this._values[e] = null, this._ids.delete(s2), this._idPool.push(e);
469
+ }
470
+ }, "syscall/js.stringVal": (t) => {
471
+ t >>>= 0, l(t + 24, u(t + 8));
472
+ }, "syscall/js.valueGet": (t) => {
473
+ t >>>= 0;
474
+ let e = Reflect.get(r(t + 8), u(t + 16));
475
+ t = this._inst.exports.getsp() >>> 0, l(t + 32, e);
476
+ }, "syscall/js.valueSet": (t) => {
477
+ t >>>= 0, Reflect.set(r(t + 8), u(t + 16), r(t + 32));
478
+ }, "syscall/js.valueDelete": (t) => {
479
+ t >>>= 0, Reflect.deleteProperty(r(t + 8), u(t + 16));
480
+ }, "syscall/js.valueIndex": (t) => {
481
+ t >>>= 0, l(t + 24, Reflect.get(r(t + 8), n(t + 16)));
482
+ }, "syscall/js.valueSetIndex": (t) => {
483
+ t >>>= 0, Reflect.set(r(t + 8), n(t + 16), r(t + 24));
484
+ }, "syscall/js.valueCall": (t) => {
485
+ t >>>= 0;
486
+ try {
487
+ let e = r(t + 8), s2 = Reflect.get(e, u(t + 16)), i2 = f2(t + 32), a = Reflect.apply(s2, e, i2);
488
+ t = this._inst.exports.getsp() >>> 0, l(t + 56, a), this.mem.setUint8(t + 64, 1);
489
+ } catch (e) {
490
+ t = this._inst.exports.getsp() >>> 0, l(t + 56, e), this.mem.setUint8(t + 64, 0);
491
+ }
492
+ }, "syscall/js.valueInvoke": (t) => {
493
+ t >>>= 0;
494
+ try {
495
+ let e = r(t + 8), s2 = f2(t + 16), i2 = Reflect.apply(e, void 0, s2);
496
+ t = this._inst.exports.getsp() >>> 0, l(t + 40, i2), this.mem.setUint8(t + 48, 1);
497
+ } catch (e) {
498
+ t = this._inst.exports.getsp() >>> 0, l(t + 40, e), this.mem.setUint8(t + 48, 0);
499
+ }
500
+ }, "syscall/js.valueNew": (t) => {
501
+ t >>>= 0;
502
+ try {
503
+ let e = r(t + 8), s2 = f2(t + 16), i2 = Reflect.construct(e, s2);
504
+ t = this._inst.exports.getsp() >>> 0, l(t + 40, i2), this.mem.setUint8(t + 48, 1);
505
+ } catch (e) {
506
+ t = this._inst.exports.getsp() >>> 0, l(t + 40, e), this.mem.setUint8(t + 48, 0);
507
+ }
508
+ }, "syscall/js.valueLength": (t) => {
509
+ t >>>= 0, o(t + 16, Number.parseInt(r(t + 8).length));
510
+ }, "syscall/js.valuePrepareString": (t) => {
511
+ t >>>= 0;
512
+ let e = y.encode(String(r(t + 8)));
513
+ l(t + 16, e), o(t + 24, e.length);
514
+ }, "syscall/js.valueLoadString": (t) => {
515
+ t >>>= 0;
516
+ let e = r(t + 8);
517
+ c(t + 16).set(e);
518
+ }, "syscall/js.valueInstanceOf": (t) => {
519
+ t >>>= 0, this.mem.setUint8(t + 24, r(t + 8) instanceof r(t + 16) ? 1 : 0);
520
+ }, "syscall/js.copyBytesToGo": (t) => {
521
+ t >>>= 0;
522
+ let e = c(t + 8), s2 = r(t + 32);
523
+ if (!(s2 instanceof Uint8Array || s2 instanceof Uint8ClampedArray)) {
524
+ this.mem.setUint8(t + 48, 0);
525
+ return;
526
+ }
527
+ let i2 = s2.subarray(0, e.length);
528
+ e.set(i2), o(t + 40, i2.length), this.mem.setUint8(t + 48, 1);
529
+ }, "syscall/js.copyBytesToJS": (t) => {
530
+ t >>>= 0;
531
+ let e = r(t + 8), s2 = c(t + 16);
532
+ if (!(e instanceof Uint8Array || e instanceof Uint8ClampedArray)) {
533
+ this.mem.setUint8(t + 48, 0);
534
+ return;
535
+ }
536
+ let i2 = s2.subarray(0, e.length);
537
+ e.set(i2), o(t + 40, i2.length), this.mem.setUint8(t + 48, 1);
538
+ }, debug: (t) => {
539
+ console.log(t);
540
+ } } };
541
+ }
542
+ async run(o) {
543
+ if (!(o instanceof WebAssembly.Instance)) throw new Error("Go.run: WebAssembly.Instance expected");
544
+ this._inst = o, this.mem = new DataView(this._inst.exports.mem.buffer), this._values = [Number.NaN, 0, null, true, false, globalThis, this], this._goRefCounts = new Array(this._values.length).fill(Number.POSITIVE_INFINITY), this._ids = /* @__PURE__ */ new Map([[0, 1], [null, 2], [true, 3], [false, 4], [globalThis, 5], [this, 6]]), this._idPool = [], this.exited = false;
545
+ let n = 4096, r = (h) => {
546
+ let t = n, e = y.encode(`${h}\0`);
547
+ return new Uint8Array(this.mem.buffer, n, e.length).set(e), n += e.length, n % 8 !== 0 && (n += 8 - n % 8), t;
548
+ }, l = this.argv.length, c = [];
549
+ this.argv.forEach((h) => {
550
+ c.push(r(h));
551
+ }), c.push(0), Object.keys(this.env).sort().forEach((h) => {
552
+ c.push(r(`${h}=${this.env[h]}`));
553
+ }), c.push(0);
554
+ let u = n;
555
+ c.forEach((h) => {
556
+ this.mem.setUint32(n, h, true), this.mem.setUint32(n + 4, 0, true), n += 8;
557
+ }), this._inst.exports.run(l, u), this.exited && this._resolveExitPromise(), await this._exitPromise;
558
+ }
559
+ _resume() {
560
+ if (this.exited) throw new Error("Go program has already exited");
561
+ this._inst.exports.resume(), this.exited && this._resolveExitPromise();
562
+ }
563
+ _makeFuncWrapper(o) {
564
+ let n = this;
565
+ return function() {
566
+ let r = { id: o, this: this, args: arguments };
567
+ return n._pendingEvent = r, n._resume(), r.result;
568
+ };
569
+ }
570
+ };
571
+
572
+ // ../../node_modules/.pnpm/@astrojs+compiler@3.0.1/node_modules/@astrojs/compiler/dist/node/sync.js
573
+ import { readFileSync as p } from "fs";
574
+ import { fileURLToPath as m } from "url";
575
+ function i() {
576
+ return s || (s = f()), s;
577
+ }
578
+ var s;
579
+ var w2 = (e, t) => i().parse(e, t);
580
+ function f() {
581
+ let e = new d(), t = v2(m(new URL("../astro.wasm", import.meta.url)), e.importObject);
582
+ e.run(t);
583
+ let o = globalThis["@astrojs/compiler"];
584
+ return { transform: (n, a) => {
585
+ try {
586
+ return o.transform(n, a || {});
587
+ } catch (r) {
588
+ throw s = void 0, r;
589
+ }
590
+ }, parse: (n, a) => {
591
+ try {
592
+ let r = o.parse(n, a || {});
593
+ return { ...r, ast: JSON.parse(r.ast) };
594
+ } catch (r) {
595
+ throw s = void 0, r;
596
+ }
597
+ }, convertToTSX: (n, a) => {
598
+ try {
599
+ let r = o.convertToTSX(n, a || {});
600
+ return { ...r, map: JSON.parse(r.map) };
601
+ } catch (r) {
602
+ throw s = void 0, r;
603
+ }
604
+ } };
605
+ }
606
+ function v2(e, t) {
607
+ let o = p(e);
608
+ return new WebAssembly.Instance(new WebAssembly.Module(o), t);
609
+ }
610
+
611
+ // src/transform/transform-astro.ts
612
+ function walk2(node, visitor) {
613
+ if (!node || typeof node !== "object") return;
614
+ visitor.enter(node);
615
+ if (Array.isArray(node.children)) {
616
+ for (const child of node.children) {
617
+ walk2(child, visitor);
618
+ }
619
+ }
620
+ }
621
+ function transformAstro(options) {
622
+ const { filePath, source, escapeTags, attributeName = "data-inspecto" } = options;
623
+ const escapeTagsSet = buildEscapeTagsSet(escapeTags);
624
+ let ast;
625
+ try {
626
+ ast = w2(source, { position: true }).ast;
627
+ } catch (_err) {
628
+ return { code: source, map: null, changed: false };
629
+ }
630
+ const s2 = new MagicString4(source);
631
+ let changed = false;
632
+ walk2(ast, {
633
+ enter(node) {
634
+ if (node.type === "element" || node.type === "component") {
635
+ const tagName = node.name;
636
+ if (tagName && !escapeTagsSet.has(tagName) && !node.attributes?.some((attr) => attr.name === attributeName)) {
637
+ const startOffset = node.position?.start?.offset ?? -1;
638
+ if (startOffset === -1) return;
639
+ let tagStartIndex = startOffset;
640
+ while (tagStartIndex >= 0 && source[tagStartIndex] !== "<") {
641
+ tagStartIndex--;
642
+ }
643
+ if (tagStartIndex >= 0) {
644
+ const substringAfterTag = source.substring(tagStartIndex);
645
+ const escapedTagName = tagName.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
646
+ const strictRegex = new RegExp(`^<\\s*${escapedTagName}(?=\\s|/|>)`, "i");
647
+ const strictMatch = substringAfterTag.match(strictRegex);
648
+ if (strictMatch) {
649
+ const insertPosition = tagStartIndex + strictMatch[0].length;
650
+ const line = node.position.start.line;
651
+ const column = node.position.start.column;
652
+ const attrValue = formatAttrValue(filePath, line, column);
653
+ const addition = ` ${attributeName}="${attrValue}"`;
654
+ s2.appendLeft(insertPosition, addition);
655
+ changed = true;
656
+ }
657
+ }
658
+ }
659
+ }
660
+ }
661
+ });
662
+ return {
663
+ code: s2.toString(),
664
+ map: changed ? s2.generateMap({ source: filePath, includeContent: true }) : null,
665
+ changed
666
+ };
667
+ }
668
+
288
669
  // src/transform/index.ts
289
670
  function transformRouter(options) {
290
671
  const { filePath, source, projectRoot, pluginOptions } = options;
@@ -309,6 +690,25 @@ function transformRouter(options) {
309
690
  attributeName: pluginOptions.attributeName
310
691
  });
311
692
  }
693
+ if (ext === ".svelte") {
694
+ return transformSvelte({
695
+ filePath,
696
+ source,
697
+ projectRoot,
698
+ escapeTags: pluginOptions.escapeTags,
699
+ pathType: pluginOptions.pathType,
700
+ attributeName: pluginOptions.attributeName
701
+ });
702
+ }
703
+ if (ext === ".astro") {
704
+ return transformAstro({
705
+ filePath,
706
+ source,
707
+ escapeTags: pluginOptions.escapeTags,
708
+ pathType: pluginOptions.pathType,
709
+ attributeName: pluginOptions.attributeName
710
+ });
711
+ }
312
712
  return null;
313
713
  }
314
714
 
@@ -451,7 +851,7 @@ function isDebugEnabled(namespace) {
451
851
  if (typeof process === "undefined" || !process.env) return false;
452
852
  const debugEnv = process.env.DEBUG;
453
853
  if (!debugEnv) return false;
454
- const namespaces = debugEnv.split(",").map((s) => s.trim());
854
+ const namespaces = debugEnv.split(",").map((s2) => s2.trim());
455
855
  for (const ns of namespaces) {
456
856
  if (ns === "*") return true;
457
857
  if (ns.endsWith("*")) {
@@ -607,7 +1007,7 @@ function readJsonSafely(filePath) {
607
1007
  }
608
1008
  return null;
609
1009
  }
610
- function resolveTargetTool(config, ide = "vscode") {
1010
+ function resolveTargetTool(config, _ide = "vscode") {
611
1011
  const defaultProvider = config["provider.default"];
612
1012
  if (defaultProvider) {
613
1013
  const tool = defaultProvider.split(".")[0];
@@ -715,7 +1115,7 @@ function resolveIntents(serverPrompts) {
715
1115
  configLogger.warn(`Intent "${item.id}" is missing required "aiIntent".`);
716
1116
  continue;
717
1117
  }
718
- const existingIdx = merged.findIndex((i) => i.id === item.id);
1118
+ const existingIdx = merged.findIndex((i2) => i2.id === item.id);
719
1119
  if (existingIdx !== -1) {
720
1120
  if (item.enabled === false) {
721
1121
  merged.splice(existingIdx, 1);
@@ -759,7 +1159,7 @@ function watchConfig(onReload, cwd = process.cwd(), gitRoot) {
759
1159
  });
760
1160
  watcher.unref();
761
1161
  watchers.push(watcher);
762
- } catch (e) {
1162
+ } catch (_e) {
763
1163
  }
764
1164
  }
765
1165
  }
@@ -827,7 +1227,6 @@ function dispatchPromptThroughIde(runtime, payload) {
827
1227
  line: payload.line,
828
1228
  column: payload.column,
829
1229
  snippet: payload.snippet,
830
- ...payload.screenshotContext ? { screenshotContext: payload.screenshotContext } : {},
831
1230
  overrides: runtime.overrides,
832
1231
  autoSend: runtime.autoSend
833
1232
  });
@@ -961,6 +1360,188 @@ function assertPathWithinIdeOpenScope(file, projectRoot) {
961
1360
  }
962
1361
  }
963
1362
 
1363
+ // src/server/session-store.ts
1364
+ var DEFAULT_STATUS = "pending";
1365
+ function createAnnotationSessionStore(options = {}) {
1366
+ const sessions = /* @__PURE__ */ new Map();
1367
+ const listeners = /* @__PURE__ */ new Set();
1368
+ const now = options.now ?? (() => Date.now());
1369
+ const createId = options.createId ?? createRandomId;
1370
+ function findNewestMatchingSession(statuses) {
1371
+ return [...sessions.values()].filter((session) => statuses ? statuses.has(session.status) : true).sort((left, right) => right.updatedAt - left.updatedAt)[0] ?? null;
1372
+ }
1373
+ function updateSessionStatus(id, status) {
1374
+ const session = sessions.get(id);
1375
+ if (!session) return null;
1376
+ const timestamp = now();
1377
+ session.status = status;
1378
+ session.updatedAt = timestamp;
1379
+ if (status === "acknowledged") {
1380
+ session.acknowledgedAt = timestamp;
1381
+ }
1382
+ if (status === "resolved") {
1383
+ session.resolvedAt = timestamp;
1384
+ }
1385
+ emit({ type: "session-status-updated", session });
1386
+ return cloneSession(session);
1387
+ }
1388
+ function claimSession(id, statuses) {
1389
+ const session = sessions.get(id);
1390
+ if (!session || statuses && !statuses.has(session.status)) return null;
1391
+ if (session.status === "acknowledged") return cloneSession(session);
1392
+ return updateSessionStatus(id, "acknowledged");
1393
+ }
1394
+ function emit(event) {
1395
+ const snapshot = cloneSession(event.session);
1396
+ for (const listener of listeners) {
1397
+ listener({ type: event.type, session: snapshot });
1398
+ }
1399
+ }
1400
+ const store = {
1401
+ createSession(input) {
1402
+ const timestamp = now();
1403
+ const session = {
1404
+ id: createId(),
1405
+ instruction: input.instruction?.trim() ?? "",
1406
+ annotations: cloneArray(input.annotations),
1407
+ ...input.deliveryMode ? { deliveryMode: input.deliveryMode } : {},
1408
+ status: DEFAULT_STATUS,
1409
+ messages: cloneArray(input.messages ?? []),
1410
+ createdAt: timestamp,
1411
+ updatedAt: timestamp,
1412
+ ...input.runtimeContext ? { runtimeContext: cloneValue(input.runtimeContext) } : {},
1413
+ ...input.cssContextPrompt?.trim() ? { cssContextPrompt: input.cssContextPrompt.trim() } : {},
1414
+ ...input.pageUrl ? { pageUrl: input.pageUrl } : {},
1415
+ ...input.route ? { route: input.route } : {}
1416
+ };
1417
+ sessions.set(session.id, session);
1418
+ emit({ type: "session-created", session });
1419
+ return cloneSession(session);
1420
+ },
1421
+ getSession(id) {
1422
+ const session = sessions.get(id);
1423
+ return session ? cloneSession(session) : null;
1424
+ },
1425
+ listSessions(options2 = {}) {
1426
+ const statuses = normalizeStatuses(options2.status);
1427
+ return [...sessions.values()].filter((session) => statuses ? statuses.has(session.status) : true).sort((left, right) => right.updatedAt - left.updatedAt).map((session) => cloneSession(session));
1428
+ },
1429
+ async claimNextSession(options2 = {}) {
1430
+ const statuses = normalizeStatuses(DEFAULT_STATUS);
1431
+ const existingSession = findNewestMatchingSession(statuses);
1432
+ if (existingSession) {
1433
+ return {
1434
+ session: claimSession(existingSession.id, statuses),
1435
+ timedOut: false,
1436
+ matchedExisting: true
1437
+ };
1438
+ }
1439
+ const timeoutMs = normalizeTimeoutMs(options2.timeoutMs);
1440
+ if (timeoutMs === 0) {
1441
+ return {
1442
+ session: null,
1443
+ timedOut: true,
1444
+ matchedExisting: false
1445
+ };
1446
+ }
1447
+ return await new Promise((resolve2) => {
1448
+ let settled = false;
1449
+ let timeout = null;
1450
+ const finish = (result) => {
1451
+ if (settled) return;
1452
+ settled = true;
1453
+ unsubscribe();
1454
+ if (timeout) {
1455
+ clearTimeout(timeout);
1456
+ }
1457
+ resolve2(result);
1458
+ };
1459
+ const unsubscribe = this.subscribe((event) => {
1460
+ const session = claimSession(event.session.id, statuses);
1461
+ if (!session) return;
1462
+ finish({
1463
+ session,
1464
+ timedOut: false,
1465
+ matchedExisting: false,
1466
+ event: event.type
1467
+ });
1468
+ });
1469
+ if (timeoutMs !== null) {
1470
+ timeout = setTimeout(() => {
1471
+ finish({
1472
+ session: null,
1473
+ timedOut: true,
1474
+ matchedExisting: false
1475
+ });
1476
+ }, timeoutMs);
1477
+ }
1478
+ });
1479
+ },
1480
+ appendMessage(id, input) {
1481
+ const session = sessions.get(id);
1482
+ if (!session) return null;
1483
+ const timestamp = now();
1484
+ session.messages.push({
1485
+ id: createId(),
1486
+ role: input.role,
1487
+ text: input.text,
1488
+ createdAt: timestamp
1489
+ });
1490
+ session.updatedAt = timestamp;
1491
+ if (input.role === "agent" && isPendingLikeStatus(session.status)) {
1492
+ session.status = "in_progress";
1493
+ }
1494
+ emit({ type: "session-message-appended", session });
1495
+ return cloneSession(session);
1496
+ },
1497
+ updateStatus(id, status) {
1498
+ return updateSessionStatus(id, status);
1499
+ },
1500
+ subscribe(listener) {
1501
+ listeners.add(listener);
1502
+ return () => {
1503
+ listeners.delete(listener);
1504
+ };
1505
+ },
1506
+ clear() {
1507
+ sessions.clear();
1508
+ listeners.clear();
1509
+ }
1510
+ };
1511
+ return store;
1512
+ }
1513
+ var annotationSessionStore = createAnnotationSessionStore();
1514
+ function normalizeStatuses(status) {
1515
+ if (!status) return null;
1516
+ return new Set(Array.isArray(status) ? status : [status]);
1517
+ }
1518
+ function normalizeTimeoutMs(value) {
1519
+ if (value === void 0) return null;
1520
+ if (!Number.isFinite(value)) return 0;
1521
+ return Math.max(0, Math.floor(value));
1522
+ }
1523
+ function isPendingLikeStatus(status) {
1524
+ return status === "pending" || status === "acknowledged";
1525
+ }
1526
+ function hasAgentReply(session) {
1527
+ return session.messages.some((message) => message.role === "agent" && Boolean(message.text?.trim()));
1528
+ }
1529
+ function createRandomId() {
1530
+ return `annotation-session-${Math.random().toString(36).slice(2, 10)}`;
1531
+ }
1532
+ function cloneSession(session) {
1533
+ return cloneValue(session);
1534
+ }
1535
+ function cloneArray(value) {
1536
+ return cloneValue(value);
1537
+ }
1538
+ function cloneValue(value) {
1539
+ if (typeof structuredClone === "function") {
1540
+ return structuredClone(value);
1541
+ }
1542
+ return JSON.parse(JSON.stringify(value));
1543
+ }
1544
+
964
1545
  // src/server/annotation-dispatch.ts
965
1546
  var AnnotationDispatchError = class extends Error {
966
1547
  constructor(message, errorCode) {
@@ -969,20 +1550,30 @@ var AnnotationDispatchError = class extends Error {
969
1550
  this.errorCode = errorCode;
970
1551
  }
971
1552
  };
972
- async function dispatchAnnotationsToAi(req, state) {
1553
+ async function dispatchAnnotationsToAi(req, state, store = annotationSessionStore) {
973
1554
  try {
974
1555
  validateAnnotationDispatchRequest(req, state);
975
1556
  const batch = normalizeAnnotationBatch(req);
976
1557
  const prompt = buildAnnotationBatchPrompt(batch);
1558
+ const deliveryMode = normalizeDeliveryMode(req.deliveryMode);
1559
+ const session = store.createSession({
1560
+ instruction: batch.instruction,
1561
+ annotations: toSessionAnnotations(batch.annotations),
1562
+ deliveryMode,
1563
+ ...batch.runtimeContext ? { runtimeContext: batch.runtimeContext } : {},
1564
+ ...batch.cssContextPrompt ? { cssContextPrompt: batch.cssContextPrompt } : {}
1565
+ });
977
1566
  const representativeTarget = batch.annotations[0]?.targets[0];
978
- const runtime = resolvePromptDispatchRuntime(state);
979
- return dispatchPromptThroughIde(runtime, {
1567
+ const dispatchResult = deliveryMode === "ide" ? dispatchPromptThroughIde(resolvePromptDispatchRuntime(state), {
980
1568
  prompt,
981
1569
  ...representativeTarget?.file ? { filePath: representativeTarget.file } : {},
982
1570
  ...representativeTarget?.line ? { line: representativeTarget.line } : {},
983
- ...representativeTarget?.column ? { column: representativeTarget.column } : {},
984
- ...batch.screenshotContext ? { screenshotContext: batch.screenshotContext } : {}
985
- });
1571
+ ...representativeTarget?.column ? { column: representativeTarget.column } : {}
1572
+ }) : { success: true };
1573
+ return {
1574
+ ...dispatchResult,
1575
+ session: toSessionSummary(session)
1576
+ };
986
1577
  } catch (error) {
987
1578
  return {
988
1579
  success: false,
@@ -991,6 +1582,41 @@ async function dispatchAnnotationsToAi(req, state) {
991
1582
  };
992
1583
  }
993
1584
  }
1585
+ function normalizeDeliveryMode(input) {
1586
+ return input === "agent" ? "agent" : "ide";
1587
+ }
1588
+ function toSessionAnnotations(annotations) {
1589
+ return annotations.map((annotation) => ({
1590
+ id: `annotation-${annotation.index}`,
1591
+ note: annotation.note,
1592
+ intent: annotation.intent,
1593
+ targets: annotation.targets.map((target, targetIndex) => ({
1594
+ id: `annotation-${annotation.index}-target-${targetIndex + 1}`,
1595
+ label: target.label ?? "Unknown target",
1596
+ location: {
1597
+ file: target.file,
1598
+ line: target.line,
1599
+ column: target.column
1600
+ },
1601
+ ...target.selector ? { selector: target.selector } : {},
1602
+ ...target.snippet ? { snippet: target.snippet } : {},
1603
+ rect: {
1604
+ x: 0,
1605
+ y: 0,
1606
+ width: 0,
1607
+ height: 0
1608
+ }
1609
+ }))
1610
+ }));
1611
+ }
1612
+ function toSessionSummary(session) {
1613
+ return {
1614
+ id: session.id,
1615
+ status: session.status,
1616
+ createdAt: session.createdAt,
1617
+ updatedAt: session.updatedAt
1618
+ };
1619
+ }
994
1620
  function validateAnnotationDispatchRequest(req, state) {
995
1621
  if (!req.annotations.length) {
996
1622
  throw new AnnotationDispatchError("At least one annotation is required.", "INVALID_REQUEST");
@@ -1011,9 +1637,7 @@ function validateAnnotationDispatchRequest(req, state) {
1011
1637
  function normalizeAnnotationBatch(req) {
1012
1638
  return {
1013
1639
  instruction: req.instruction?.trim() ?? "",
1014
- responseMode: req.responseMode ?? "unified",
1015
1640
  ...req.runtimeContext ? { runtimeContext: req.runtimeContext } : {},
1016
- ...req.screenshotContext ? { screenshotContext: req.screenshotContext } : {},
1017
1641
  ...req.cssContextPrompt?.trim() ? { cssContextPrompt: req.cssContextPrompt.trim() } : {},
1018
1642
  annotations: req.annotations.map((annotation, index) => ({
1019
1643
  index: index + 1,
@@ -1035,12 +1659,9 @@ function buildAnnotationBatchPrompt(batch) {
1035
1659
  const prompt = batch.instruction ? `${batch.instruction}
1036
1660
 
1037
1661
  ${body}` : body;
1038
- return appendScreenshotContextSection(
1039
- appendCssContextSection(
1040
- appendRuntimeContextSection(prompt, batch.runtimeContext),
1041
- batch.cssContextPrompt
1042
- ),
1043
- batch.screenshotContext
1662
+ return appendCssContextSection(
1663
+ appendRuntimeContextSection(prompt, batch.runtimeContext),
1664
+ batch.cssContextPrompt
1044
1665
  );
1045
1666
  }
1046
1667
  function appendCssContextSection(prompt, cssContextPrompt) {
@@ -1067,20 +1688,6 @@ function buildSelectedElementsPrompt(annotations) {
1067
1688
  }
1068
1689
  return lines.join("\n");
1069
1690
  }
1070
- function appendScreenshotContextSection(prompt, screenshotContext) {
1071
- if (!screenshotContext || !screenshotContext.imageDataUrl && !screenshotContext.imageAssetId) {
1072
- return prompt;
1073
- }
1074
- const lines = [
1075
- "Visual screenshot context attached:",
1076
- `- capturedAt=${screenshotContext.capturedAt}`,
1077
- `- mimeType=${screenshotContext.mimeType}`,
1078
- ...screenshotContext.imageAssetId ? [`- imageAssetId=${screenshotContext.imageAssetId}`] : []
1079
- ];
1080
- return `${prompt}
1081
-
1082
- ${lines.join("\n")}`;
1083
- }
1084
1691
  function appendRuntimeContextSection(prompt, runtimeContext) {
1085
1692
  if (!runtimeContext?.records.length) {
1086
1693
  return prompt;
@@ -1128,7 +1735,7 @@ async function buildClientConfig(serverState2) {
1128
1735
  ...info,
1129
1736
  prompts: resolveIntents(promptsConfig),
1130
1737
  hotKeys: userConfig["inspector.hotKey"] ?? "alt",
1131
- theme: userConfig["inspector.theme"] ?? "auto",
1738
+ annotateDeliveryMode: userConfig["annotate.deliveryMode"] ?? "both",
1132
1739
  includeSnippet: userConfig["prompt.includeSnippet"] ?? false,
1133
1740
  runtimeContext: {
1134
1741
  enabled: true,
@@ -1136,10 +1743,6 @@ async function buildClientConfig(serverState2) {
1136
1743
  maxRuntimeErrors: 3,
1137
1744
  maxFailedRequests: 2
1138
1745
  },
1139
- screenshotContext: {
1140
- enabled: false
1141
- },
1142
- annotationResponseMode: userConfig["prompt.annotationResponseMode"] ?? "unified",
1143
1746
  autoSend: userConfig["prompt.autoSend"] ?? false
1144
1747
  };
1145
1748
  }
@@ -1184,7 +1787,7 @@ function handleOpenFileRequest(body, serverState2) {
1184
1787
  else if (rawEditorHint === "vscodium") editorHint = "codium";
1185
1788
  else if (rawEditorHint === "trae-cn" || rawEditorHint === "trae") editorHint = "trae";
1186
1789
  serverLogger2.debug(
1187
- `IDE_OPEN: activeIde=${activeIde}, activeIdeScheme=${activeIdeScheme}, configuredIde=${configuredIde} -> rawEditorHint=${rawEditorHint}, finalEditorHint=${editorHint}`
1790
+ `SOURCE_OPEN: activeIde=${activeIde}, activeIdeScheme=${activeIdeScheme}, configuredIde=${configuredIde} -> rawEditorHint=${rawEditorHint}, finalEditorHint=${editorHint}`
1188
1791
  );
1189
1792
  if (VSCODE_FAMILY_SCHEMES.includes(rawEditorHint)) {
1190
1793
  let normalizedPath = absolutePath.replace(/\\/g, "/");
@@ -1193,7 +1796,7 @@ function handleOpenFileRequest(body, serverState2) {
1193
1796
  }
1194
1797
  const encodedPath = encodeURI(normalizedPath);
1195
1798
  const uri = `${rawEditorHint}://file${encodedPath}:${body.line}:${body.column}`;
1196
- serverLogger2.debug(`IDE_OPEN: Bypassing launchIDE, using URI scheme directly: ${uri}`);
1799
+ serverLogger2.debug(`SOURCE_OPEN: Bypassing launchIDE, using URI scheme directly: ${uri}`);
1197
1800
  try {
1198
1801
  if (process.platform === "darwin") {
1199
1802
  execFileSync2("open", [uri]);
@@ -1203,7 +1806,7 @@ function handleOpenFileRequest(body, serverState2) {
1203
1806
  execFileSync2("xdg-open", [uri]);
1204
1807
  }
1205
1808
  } catch (e) {
1206
- serverLogger2.error(`Failed to launch URI for IDE_OPEN (${uri}):`, e);
1809
+ serverLogger2.error(`Failed to launch URI for SOURCE_OPEN (${uri}):`, e);
1207
1810
  launchIDE2({
1208
1811
  file: absolutePath,
1209
1812
  line: body.line,
@@ -1260,6 +1863,7 @@ function resolveProjectRoot() {
1260
1863
 
1261
1864
  // src/server/index.ts
1262
1865
  var serverLogger4 = createLogger("inspecto:server", { logLevel: getGlobalLogLevel() });
1866
+ var PORT_FILE_NAME = "inspecto.port.json";
1263
1867
  var serverState = {
1264
1868
  port: null,
1265
1869
  running: false,
@@ -1268,6 +1872,42 @@ var serverState = {
1268
1872
  cwd: process.cwd()
1269
1873
  };
1270
1874
  var serverInstance = null;
1875
+ function getPortFilePath() {
1876
+ return path8.join(os2.tmpdir(), PORT_FILE_NAME);
1877
+ }
1878
+ function getProjectRootHash() {
1879
+ if (!serverState.projectRoot) return null;
1880
+ return crypto2.createHash("md5").update(serverState.projectRoot).digest("hex");
1881
+ }
1882
+ function readPortData(portFile) {
1883
+ if (!fs5.existsSync(portFile)) return {};
1884
+ try {
1885
+ return JSON.parse(fs5.readFileSync(portFile, "utf-8"));
1886
+ } catch {
1887
+ return {};
1888
+ }
1889
+ }
1890
+ function writeProjectPort(port) {
1891
+ const rootHash = getProjectRootHash();
1892
+ if (!rootHash) return;
1893
+ const portFile = getPortFilePath();
1894
+ const portData = readPortData(portFile);
1895
+ portData[rootHash] = port;
1896
+ fs5.writeFileSync(portFile, JSON.stringify(portData, null, 2), "utf-8");
1897
+ }
1898
+ function removeProjectPort() {
1899
+ const rootHash = getProjectRootHash();
1900
+ if (!rootHash) return;
1901
+ const portFile = getPortFilePath();
1902
+ if (!fs5.existsSync(portFile)) return;
1903
+ const portData = readPortData(portFile);
1904
+ delete portData[rootHash];
1905
+ if (Object.keys(portData).length === 0) {
1906
+ fs5.unlinkSync(portFile);
1907
+ } else {
1908
+ fs5.writeFileSync(portFile, JSON.stringify(portData, null, 2), "utf-8");
1909
+ }
1910
+ }
1271
1911
  async function startServer() {
1272
1912
  if (serverState.running && serverState.port !== null) {
1273
1913
  return serverState.port;
@@ -1301,7 +1941,7 @@ async function startServer() {
1301
1941
  });
1302
1942
  });
1303
1943
  await new Promise((resolve2, reject) => {
1304
- serverInstance.listen(port, "127.0.0.1", () => {
1944
+ serverInstance.listen(port, "0.0.0.0", () => {
1305
1945
  serverInstance.unref();
1306
1946
  resolve2();
1307
1947
  });
@@ -1312,37 +1952,18 @@ async function startServer() {
1312
1952
  });
1313
1953
  serverState.port = port;
1314
1954
  serverState.running = true;
1315
- const portFile = path8.join(os2.tmpdir(), "inspecto.port.json");
1316
1955
  try {
1317
- let portData = {};
1318
- if (fs5.existsSync(portFile)) {
1319
- try {
1320
- portData = JSON.parse(fs5.readFileSync(portFile, "utf-8"));
1321
- } catch (e) {
1322
- }
1323
- }
1324
- const rootHash = crypto2.createHash("md5").update(serverState.projectRoot).digest("hex");
1325
- portData[rootHash] = port;
1326
- fs5.writeFileSync(portFile, JSON.stringify(portData, null, 2), "utf-8");
1327
- } catch (e) {
1328
- serverLogger4.warn("Failed to write port file:", e);
1956
+ writeProjectPort(port);
1957
+ } catch (_e) {
1958
+ serverLogger4.warn("Failed to write port file:", _e);
1329
1959
  }
1330
1960
  process.once("exit", () => {
1331
1961
  try {
1332
- if (fs5.existsSync(portFile)) {
1333
- const portData = JSON.parse(fs5.readFileSync(portFile, "utf-8"));
1334
- const rootHash = crypto2.createHash("md5").update(serverState.projectRoot).digest("hex");
1335
- delete portData[rootHash];
1336
- if (Object.keys(portData).length === 0) {
1337
- fs5.unlinkSync(portFile);
1338
- } else {
1339
- fs5.writeFileSync(portFile, JSON.stringify(portData, null, 2), "utf-8");
1340
- }
1341
- }
1962
+ removeProjectPort();
1342
1963
  } catch {
1343
1964
  }
1344
1965
  });
1345
- serverLogger4.info(`server running at http://127.0.0.1:${port}`);
1966
+ serverLogger4.info(`server running at http://0.0.0.0:${port}`);
1346
1967
  return port;
1347
1968
  }
1348
1969
  async function readBody(req) {
@@ -1394,11 +2015,11 @@ async function handleRequest(url, req, res) {
1394
2015
  }
1395
2016
  return;
1396
2017
  }
1397
- if (pathname === INSPECTO_API_PATHS.IDE_OPEN && req.method === "POST") {
2018
+ if ((pathname === INSPECTO_API_PATHS.SOURCE_OPEN || pathname === INSPECTO_API_PATHS.IDE_OPEN) && req.method === "POST") {
1398
2019
  let body;
1399
2020
  try {
1400
2021
  body = JSON.parse(await readBody(req));
1401
- } catch (e) {
2022
+ } catch (_e) {
1402
2023
  res.writeHead(400, { "Content-Type": "application/json" });
1403
2024
  res.end(JSON.stringify({ error: "Invalid JSON body" }));
1404
2025
  return;
@@ -1407,7 +2028,7 @@ async function handleRequest(url, req, res) {
1407
2028
  handleOpenFileRequest(body, serverState);
1408
2029
  } catch (err) {
1409
2030
  serverLogger4.warn(
1410
- `Security: Blocked path traversal attempt in IDE_OPEN: ${body.file}. Reason: ${err.message}`
2031
+ `Security: Blocked path traversal attempt in SOURCE_OPEN: ${body.file}. Reason: ${err.message}`
1411
2032
  );
1412
2033
  res.writeHead(403, { "Content-Type": "application/json" });
1413
2034
  res.end(JSON.stringify({ error: "Access denied: File is outside of project workspace" }));
@@ -1481,6 +2102,212 @@ async function handleRequest(url, req, res) {
1481
2102
  }
1482
2103
  return;
1483
2104
  }
2105
+ if (pathname === INSPECTO_API_PATHS.SESSION_CLAIM_NEXT && req.method === "POST") {
2106
+ try {
2107
+ const rawBody = await readBody(req);
2108
+ const body = rawBody ? JSON.parse(rawBody) : {};
2109
+ const timeoutMs = normalizeSessionClaimTimeout(
2110
+ body.timeoutMs === void 0 ? null : String(body.timeoutMs)
2111
+ );
2112
+ const result = await annotationSessionStore.claimNextSession({
2113
+ ...timeoutMs !== void 0 ? { timeoutMs } : {}
2114
+ });
2115
+ res.writeHead(200, { "Content-Type": "application/json" });
2116
+ res.end(
2117
+ JSON.stringify({
2118
+ success: true,
2119
+ timedOut: result.timedOut,
2120
+ matchedExisting: result.matchedExisting,
2121
+ ...result.event ? { event: result.event } : {},
2122
+ ...result.session ? { session: result.session } : {}
2123
+ })
2124
+ );
2125
+ } catch (e) {
2126
+ serverLogger4.error(`Error parsing session claim request:`, e);
2127
+ res.writeHead(400, { "Content-Type": "application/json" });
2128
+ res.end(JSON.stringify({ success: false, error: "Invalid JSON body" }));
2129
+ }
2130
+ return;
2131
+ }
2132
+ if (pathname === INSPECTO_API_PATHS.SESSION_EVENTS && req.method === "GET") {
2133
+ const statusParam = url.searchParams.getAll("status");
2134
+ const statuses = statusParam.length ? new Set(statusParam) : null;
2135
+ const sessionId = url.searchParams.get("sessionId")?.trim() || null;
2136
+ res.writeHead(200, {
2137
+ "Content-Type": "text/event-stream",
2138
+ "Cache-Control": "no-cache",
2139
+ Connection: "keep-alive"
2140
+ });
2141
+ res.write(`event: ready
2142
+ data: ${JSON.stringify({ ok: true })}
2143
+
2144
+ `);
2145
+ const unsubscribe = annotationSessionStore.subscribe((event) => {
2146
+ if (sessionId && event.session.id !== sessionId) {
2147
+ return;
2148
+ }
2149
+ if (statuses && !statuses.has(event.session.status)) {
2150
+ return;
2151
+ }
2152
+ res.write(formatSessionSseEvent(event));
2153
+ });
2154
+ req.on("close", () => {
2155
+ unsubscribe();
2156
+ res.end();
2157
+ });
2158
+ return;
2159
+ }
2160
+ if (pathname === INSPECTO_API_PATHS.SESSIONS && req.method === "GET") {
2161
+ const statusParam = url.searchParams.getAll("status");
2162
+ const sessions = annotationSessionStore.listSessions(
2163
+ statusParam.length ? {
2164
+ status: statusParam
2165
+ } : void 0
2166
+ );
2167
+ res.writeHead(200, { "Content-Type": "application/json" });
2168
+ res.end(JSON.stringify({ success: true, sessions }));
2169
+ return;
2170
+ }
2171
+ if (pathname.startsWith(`${INSPECTO_API_PATHS.SESSIONS}/`) && req.method === "GET") {
2172
+ const sessionId = pathname.substring(INSPECTO_API_PATHS.SESSIONS.length + 1);
2173
+ const session = annotationSessionStore.getSession(sessionId);
2174
+ if (!session) {
2175
+ res.writeHead(404, { "Content-Type": "application/json" });
2176
+ res.end(JSON.stringify({ success: false, error: "Session not found" }));
2177
+ return;
2178
+ }
2179
+ res.writeHead(200, { "Content-Type": "application/json" });
2180
+ res.end(JSON.stringify({ success: true, session }));
2181
+ return;
2182
+ }
2183
+ if (pathname.startsWith(`${INSPECTO_API_PATHS.SESSIONS}/`) && pathname.endsWith(INSPECTO_API_PATHS.SESSION_REPLY_SUFFIX) && req.method === "POST") {
2184
+ const sessionId = pathname.slice(
2185
+ INSPECTO_API_PATHS.SESSIONS.length + 1,
2186
+ -INSPECTO_API_PATHS.SESSION_REPLY_SUFFIX.length
2187
+ );
2188
+ try {
2189
+ const rawBody = await readBody(req);
2190
+ const body = JSON.parse(rawBody);
2191
+ if (!isAnnotationThreadRole(body.role)) {
2192
+ res.writeHead(400, { "Content-Type": "application/json" });
2193
+ res.end(JSON.stringify({ success: false, error: "Reply role is invalid." }));
2194
+ return;
2195
+ }
2196
+ if (!body.text?.trim()) {
2197
+ res.writeHead(400, { "Content-Type": "application/json" });
2198
+ res.end(JSON.stringify({ success: false, error: "Reply text is required." }));
2199
+ return;
2200
+ }
2201
+ const session = annotationSessionStore.appendMessage(sessionId, {
2202
+ role: body.role,
2203
+ text: body.text.trim()
2204
+ });
2205
+ if (!session) {
2206
+ res.writeHead(404, { "Content-Type": "application/json" });
2207
+ res.end(JSON.stringify({ success: false, error: "Session not found" }));
2208
+ return;
2209
+ }
2210
+ res.writeHead(200, { "Content-Type": "application/json" });
2211
+ res.end(JSON.stringify({ success: true, session }));
2212
+ } catch (e) {
2213
+ serverLogger4.error(`Error parsing session reply request:`, e);
2214
+ res.writeHead(400, { "Content-Type": "application/json" });
2215
+ res.end(JSON.stringify({ success: false, error: "Invalid JSON body" }));
2216
+ }
2217
+ return;
2218
+ }
2219
+ if (pathname.startsWith(`${INSPECTO_API_PATHS.SESSIONS}/`) && pathname.endsWith(INSPECTO_API_PATHS.SESSION_RESOLVE_SUFFIX) && req.method === "POST") {
2220
+ const sessionId = pathname.slice(
2221
+ INSPECTO_API_PATHS.SESSIONS.length + 1,
2222
+ -INSPECTO_API_PATHS.SESSION_RESOLVE_SUFFIX.length
2223
+ );
2224
+ try {
2225
+ const rawBody = await readBody(req);
2226
+ const body = rawBody ? JSON.parse(rawBody) : {};
2227
+ const message = body.message?.trim();
2228
+ const existingSession = annotationSessionStore.getSession(sessionId);
2229
+ if (!existingSession) {
2230
+ res.writeHead(404, { "Content-Type": "application/json" });
2231
+ res.end(JSON.stringify({ success: false, error: "Session not found" }));
2232
+ return;
2233
+ }
2234
+ if (!message && !hasAgentReply(existingSession)) {
2235
+ res.writeHead(400, { "Content-Type": "application/json" });
2236
+ res.end(
2237
+ JSON.stringify({
2238
+ success: false,
2239
+ error: "Resolve message is required until an agent reply is recorded."
2240
+ })
2241
+ );
2242
+ return;
2243
+ }
2244
+ if (message) {
2245
+ const repliedSession = annotationSessionStore.appendMessage(sessionId, {
2246
+ role: "agent",
2247
+ text: message
2248
+ });
2249
+ if (!repliedSession) {
2250
+ res.writeHead(404, { "Content-Type": "application/json" });
2251
+ res.end(JSON.stringify({ success: false, error: "Session not found" }));
2252
+ return;
2253
+ }
2254
+ }
2255
+ const session = annotationSessionStore.updateStatus(sessionId, "resolved");
2256
+ if (!session) {
2257
+ res.writeHead(404, { "Content-Type": "application/json" });
2258
+ res.end(JSON.stringify({ success: false, error: "Session not found" }));
2259
+ return;
2260
+ }
2261
+ res.writeHead(200, { "Content-Type": "application/json" });
2262
+ res.end(JSON.stringify({ success: true, session }));
2263
+ } catch (e) {
2264
+ serverLogger4.error(`Error parsing session resolve request:`, e);
2265
+ res.writeHead(400, { "Content-Type": "application/json" });
2266
+ res.end(JSON.stringify({ success: false, error: "Invalid JSON body" }));
2267
+ }
2268
+ return;
2269
+ }
2270
+ if (pathname.startsWith(`${INSPECTO_API_PATHS.SESSIONS}/`) && pathname.endsWith(INSPECTO_API_PATHS.SESSION_DISMISS_SUFFIX) && req.method === "POST") {
2271
+ const sessionId = pathname.slice(
2272
+ INSPECTO_API_PATHS.SESSIONS.length + 1,
2273
+ -INSPECTO_API_PATHS.SESSION_DISMISS_SUFFIX.length
2274
+ );
2275
+ try {
2276
+ const rawBody = await readBody(req);
2277
+ const body = rawBody ? JSON.parse(rawBody) : {};
2278
+ const message = body.message?.trim();
2279
+ const existingSession = annotationSessionStore.getSession(sessionId);
2280
+ if (!existingSession) {
2281
+ res.writeHead(404, { "Content-Type": "application/json" });
2282
+ res.end(JSON.stringify({ success: false, error: "Session not found" }));
2283
+ return;
2284
+ }
2285
+ if (message) {
2286
+ const repliedSession = annotationSessionStore.appendMessage(sessionId, {
2287
+ role: "agent",
2288
+ text: message
2289
+ });
2290
+ if (!repliedSession) {
2291
+ res.writeHead(404, { "Content-Type": "application/json" });
2292
+ res.end(JSON.stringify({ success: false, error: "Session not found" }));
2293
+ return;
2294
+ }
2295
+ }
2296
+ const session = annotationSessionStore.updateStatus(sessionId, "dismissed");
2297
+ if (!session) {
2298
+ res.writeHead(404, { "Content-Type": "application/json" });
2299
+ res.end(JSON.stringify({ success: false, error: "Session not found" }));
2300
+ return;
2301
+ }
2302
+ res.writeHead(200, { "Content-Type": "application/json" });
2303
+ res.end(JSON.stringify({ success: true, session }));
2304
+ } catch (e) {
2305
+ serverLogger4.error(`Error parsing session dismiss request:`, e);
2306
+ res.writeHead(400, { "Content-Type": "application/json" });
2307
+ res.end(JSON.stringify({ success: false, error: "Invalid JSON body" }));
2308
+ }
2309
+ return;
2310
+ }
1484
2311
  if (pathname.startsWith(`${INSPECTO_API_PATHS.AI_TICKET}/`) && req.method === "GET") {
1485
2312
  const ticketId = pathname.substring(INSPECTO_API_PATHS.AI_TICKET.length + 1);
1486
2313
  const payloadStr = readTicket(ticketId);
@@ -1497,7 +2324,7 @@ async function handleRequest(url, req, res) {
1497
2324
  res.end(JSON.stringify({ error: "not found" }));
1498
2325
  }
1499
2326
  async function dispatchToAi(req) {
1500
- const { location, snippet, prompt, screenshotContext } = req;
2327
+ const { location, snippet, prompt } = req;
1501
2328
  const formattedPrompt = prompt ?? `Please help me with this code from \`${location.file}\` (line ${location.line}):
1502
2329
 
1503
2330
  \`\`\`
@@ -1510,8 +2337,7 @@ ${snippet}
1510
2337
  filePath: location.file,
1511
2338
  line: location.line,
1512
2339
  column: location.column,
1513
- snippet,
1514
- ...screenshotContext ? { screenshotContext } : {}
2340
+ snippet
1515
2341
  });
1516
2342
  }
1517
2343
  function getBatchDispatchStatusCode(errorCode, success) {
@@ -1520,6 +2346,21 @@ function getBatchDispatchStatusCode(errorCode, success) {
1520
2346
  if (errorCode === "FORBIDDEN_PATH") return 403;
1521
2347
  return 500;
1522
2348
  }
2349
+ function isAnnotationThreadRole(value) {
2350
+ return value === "user" || value === "agent" || value === "system";
2351
+ }
2352
+ function formatSessionSseEvent(event) {
2353
+ return `event: ${event.type}
2354
+ data: ${JSON.stringify(event)}
2355
+
2356
+ `;
2357
+ }
2358
+ function normalizeSessionClaimTimeout(value) {
2359
+ if (!value?.trim()) return 3e4;
2360
+ const parsed = Number.parseInt(value, 10);
2361
+ if (!Number.isFinite(parsed)) return 3e4;
2362
+ return Math.max(0, Math.min(parsed, 3e5));
2363
+ }
1523
2364
 
1524
2365
  // src/injectors/utils.ts
1525
2366
  import { createRequire } from "module";
@@ -1542,13 +2383,13 @@ var resolveClientModule = () => {
1542
2383
  function getWebpackHtmlScript(serverPort) {
1543
2384
  return `
1544
2385
  window.__AI_INSPECTOR_PORT__ = ${serverPort};
1545
- window.addEventListener('load', () => {
1546
- if (window.InspectoClient) {
1547
- window.InspectoClient.mountInspector({
1548
- serverUrl: 'http://127.0.0.1:' + window.__AI_INSPECTOR_PORT__,
1549
- });
1550
- }
1551
- });
2386
+ window.addEventListener('load', () => {
2387
+ if (window.InspectoClient) {
2388
+ window.InspectoClient.mountInspector({
2389
+ serverUrl: 'http://0.0.0.0:' + window.__AI_INSPECTOR_PORT__,
2390
+ });
2391
+ }
2392
+ });
1552
2393
  `;
1553
2394
  }
1554
2395
  function getWebpackAssetScript(serverPort) {
@@ -1558,7 +2399,7 @@ if (typeof window !== 'undefined') {
1558
2399
  const _initInspecto = () => {
1559
2400
  if (window.InspectoClient) {
1560
2401
  window.InspectoClient.mountInspector({
1561
- serverUrl: 'http://127.0.0.1:' + window.__AI_INSPECTOR_PORT__,
2402
+ serverUrl: 'http://0.0.0.0:' + window.__AI_INSPECTOR_PORT__,
1562
2403
  });
1563
2404
  } else {
1564
2405
  setTimeout(_initInspecto, 100);
@@ -1581,7 +2422,7 @@ function injectWebpack(compiler, serverPortFn, resolveClientModule2) {
1581
2422
  }
1582
2423
  compiler.hooks.compilation.tap("inspecto-overlay", (compilation) => {
1583
2424
  const HtmlWebpackPlugin = compiler.options.plugins.find(
1584
- (p) => p && p.constructor && p.constructor.name === "HtmlWebpackPlugin"
2425
+ (p2) => p2 && p2.constructor && p2.constructor.name === "HtmlWebpackPlugin"
1585
2426
  );
1586
2427
  if (HtmlWebpackPlugin) {
1587
2428
  const hooks = HtmlWebpackPlugin.constructor.getHooks(compilation);
@@ -1625,7 +2466,7 @@ function injectRspack(compiler, serverPortFn, resolveClientModule2) {
1625
2466
  new compiler.webpack.EntryPlugin(compiler.context, inspectoClientPath, {}).apply(compiler);
1626
2467
  compiler.hooks.compilation.tap("inspecto-overlay", (compilation) => {
1627
2468
  const HtmlRspackPlugin = compiler.options.plugins.find(
1628
- (p) => p && p.constructor && p.constructor.name === "HtmlRspackPlugin"
2469
+ (p2) => p2 && p2.constructor && p2.constructor.name === "HtmlRspackPlugin"
1629
2470
  );
1630
2471
  if (HtmlRspackPlugin) {
1631
2472
  const hooks = HtmlRspackPlugin.constructor.getHooks(compilation);
@@ -1649,7 +2490,7 @@ function getViteVirtualModuleScript(serverPort) {
1649
2490
  import { mountInspector } from '@inspecto-dev/core';
1650
2491
  window.__AI_INSPECTOR_PORT__ = ${serverPort};
1651
2492
  mountInspector({
1652
- serverUrl: 'http://127.0.0.1:' + window.__AI_INSPECTOR_PORT__,
2493
+ serverUrl: 'http://0.0.0.0:' + window.__AI_INSPECTOR_PORT__,
1653
2494
  });
1654
2495
  `;
1655
2496
  }
@@ -1783,7 +2624,9 @@ export {
1783
2624
  esbuildPlugin,
1784
2625
  rollupPlugin,
1785
2626
  rspackPlugin,
2627
+ transformAstro,
1786
2628
  transformJsx,
2629
+ transformRouter,
1787
2630
  unplugin,
1788
2631
  vitePlugin,
1789
2632
  webpackPlugin