botversion-sdk 2.3.3 → 2.3.4

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 (2) hide show
  1. package/package.json +1 -1
  2. package/undo/lib/tagger.js +113 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "botversion-sdk",
3
- "version": "2.3.3",
3
+ "version": "2.3.4",
4
4
  "description": "BotVersion SDK: auto-detect and register your API endpoints, with undo for AI actions",
5
5
  "main": "index.js",
6
6
  "bin": {
@@ -32,6 +32,7 @@ const dbg = (...a) => {
32
32
  };
33
33
  const seenEvents = new Set(); // distinct server event names seen (capped)
34
34
  let seenRequests = 0;
35
+ const listenerSeen = new WeakSet(); // DEBUG: responses the server-event listener saw
35
36
 
36
37
  function setApiKey(key) {
37
38
  try {
@@ -303,6 +304,10 @@ function wrapEmit(proto) {
303
304
  if (event === "request") {
304
305
  // DEBUG: shows whether requests reach this listener at all (first 3 requests, plus every botversion request)
305
306
  let bvSeen = false;
307
+ try {
308
+ if (global._botVersionDebug && res && typeof res === "object")
309
+ listenerSeen.add(res); // DEBUG: marks "the listener saw this request"
310
+ } catch (_) {}
306
311
  try {
307
312
  if (global._botVersionDebug) {
308
313
  seenRequests++;
@@ -359,9 +364,117 @@ function wrapEmit(proto) {
359
364
  return true;
360
365
  }
361
366
 
367
+ // DEBUG PROBE: watches every response Node finishes, whatever way the host received the request.
368
+ // Compares it with what the server-event listener saw. Prints only when debug is on.
369
+ globalThis.__bvTaggerLoads = (globalThis.__bvTaggerLoads || 0) + 1;
370
+ const PROBE = Symbol.for("botversion.undoExp.probe");
371
+ const probeCount = { all: 0, bv: 0 };
372
+ const probed = new WeakSet();
373
+
374
+ function installResponseProbe() {
375
+ try {
376
+ if (!global._botVersionDebug) return;
377
+ const http = require("http");
378
+
379
+ // Startup facts: which process, which module copy, which Next.js
380
+ let nextVersion = null;
381
+ try {
382
+ nextVersion = require(
383
+ require.resolve("next/package.json", { paths: [process.cwd()] }),
384
+ ).version;
385
+ } catch (_) {}
386
+ dbg("probe installed", {
387
+ pid: process.pid,
388
+ uptimeSec: Math.round(process.uptime()),
389
+ taggerCopiesLoaded: globalThis.__bvTaggerLoads,
390
+ script: String(process.argv[1] || "").slice(-60),
391
+ cwd: process.cwd(),
392
+ node: process.version,
393
+ next: nextVersion,
394
+ nextRuntime: process.env.NEXT_RUNTIME || null,
395
+ vercelEnv: process.env.VERCEL_ENV || null,
396
+ region: process.env.VERCEL_REGION || null,
397
+ lambda: !!process.env.AWS_LAMBDA_FUNCTION_NAME,
398
+ emitPatched: !!(
399
+ http.Server &&
400
+ http.Server.prototype.emit &&
401
+ http.Server.prototype.emit[PATCHED]
402
+ ),
403
+ });
404
+
405
+ // Does this process ever start a real Node server?
406
+ const SP = http.Server && http.Server.prototype;
407
+ if (SP && typeof SP.listen === "function" && !SP.listen[PROBE]) {
408
+ const origListen = SP.listen;
409
+ const wl = function listen() {
410
+ try {
411
+ dbg("a Node server started listening in this process", {
412
+ pid: process.pid,
413
+ args: Array.prototype.slice
414
+ .call(arguments)
415
+ .filter((a) => typeof a === "number" || typeof a === "string")
416
+ .slice(0, 2),
417
+ });
418
+ } catch (_) {}
419
+ return origListen.apply(this, arguments);
420
+ };
421
+ Object.defineProperty(wl, PROBE, { value: true });
422
+ SP.listen = wl;
423
+ }
424
+
425
+ // Watches every finished response.
426
+ const RP = http.ServerResponse && http.ServerResponse.prototype;
427
+ if (!RP || typeof RP.end !== "function") {
428
+ dbg("probe: ServerResponse.end not found, cannot watch responses");
429
+ return;
430
+ }
431
+ if (RP.end[PROBE]) return;
432
+ const origEnd = RP.end;
433
+ const wrapped = function end() {
434
+ try {
435
+ if (!probed.has(this)) {
436
+ probed.add(this);
437
+ const req = this.req;
438
+ const h = (req && req.headers) || {};
439
+ const bvHeaders = Object.keys(h).filter(
440
+ (k) => k.indexOf("x-botversion-") === 0,
441
+ );
442
+ const p = String((req && req.url) || "")
443
+ .split("?")[0]
444
+ .slice(0, 120);
445
+ const isBv = bvHeaders.length > 0 || p.indexOf("botversion") !== -1;
446
+ const log =
447
+ (probeCount.all < 5 && ++probeCount.all) ||
448
+ (isBv && probeCount.bv < 40 && ++probeCount.bv);
449
+ if (log)
450
+ dbg("response finished", {
451
+ pid: process.pid,
452
+ uptimeSec: Math.round(process.uptime()),
453
+ method: req && req.method,
454
+ path: p,
455
+ status: this.statusCode,
456
+ botversionHeaders: bvHeaders,
457
+ listenerSawIt: listenerSeen.has(this),
458
+ insideAiRequest: !!getCurrent(),
459
+ hasSigningKey: !!signingKey,
460
+ undoStartedHere: !!global._botVersionUndoStarted,
461
+ taggerCopiesLoaded: globalThis.__bvTaggerLoads,
462
+ });
463
+ }
464
+ } catch (_) {}
465
+ return origEnd.apply(this, arguments);
466
+ };
467
+ Object.defineProperty(wrapped, PROBE, { value: true });
468
+ RP.end = wrapped;
469
+ } catch (e) {
470
+ dbg("probe could not be installed:", e && e.message);
471
+ }
472
+ }
473
+
362
474
  // Wraps every built-in server type that exists in this Node version.
363
475
  function install() {
364
476
  const wrapped = [];
477
+ installResponseProbe(); // DEBUG probe, does nothing unless debug is on
365
478
  const targets = [
366
479
  ["http", (m) => m.Server && m.Server.prototype],
367
480
  ["https", (m) => m.Server && m.Server.prototype],