@agentcash/telemetry 0.3.1 → 0.3.3

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.
@@ -6,6 +6,7 @@ var _chunk2EFPFJCBjs = require('./chunk-2EFPFJCB.js');
6
6
 
7
7
  // src/telemetry.ts
8
8
  var _server = require('next/server');
9
+
9
10
  function withTelemetry(handler) {
10
11
  return async (request) => {
11
12
  const meta = _chunk2EFPFJCBjs.extractRequestMeta.call(void 0, request);
@@ -31,17 +32,25 @@ function withTelemetry(handler) {
31
32
  response = _server.NextResponse.json({ success: false, error: message }, { status: 500 });
32
33
  }
33
34
  }
34
- let responseBodyString = null;
35
- try {
36
- responseBodyString = await response.clone().text();
37
- } catch (e2) {
38
- }
39
35
  if (response.status !== 402) {
40
- _chunk2EFPFJCBjs.recordInvocation.call(void 0, meta, requestBodyString, {
41
- status: response.status,
42
- body: responseBodyString,
43
- headers: JSON.stringify(Object.fromEntries(response.headers.entries())),
44
- contentType: _nullishCoalesce(response.headers.get("content-type"), () => ( null))
36
+ const status = response.status;
37
+ const responseHeaders = JSON.stringify(Object.fromEntries(response.headers.entries()));
38
+ const contentType = _nullishCoalesce(response.headers.get("content-type"), () => ( null));
39
+ let responseBodyString = null;
40
+ try {
41
+ responseBodyString = await response.clone().text();
42
+ } catch (e2) {
43
+ }
44
+ _server.after.call(void 0, () => {
45
+ try {
46
+ _chunk2EFPFJCBjs.recordInvocation.call(void 0, meta, requestBodyString, {
47
+ status,
48
+ body: responseBodyString,
49
+ headers: responseHeaders,
50
+ contentType
51
+ });
52
+ } catch (e3) {
53
+ }
45
54
  });
46
55
  }
47
56
  if (handlerError && !(handlerError instanceof _server.NextResponse)) {
@@ -54,4 +63,4 @@ function withTelemetry(handler) {
54
63
 
55
64
 
56
65
  exports.withTelemetry = withTelemetry;
57
- //# sourceMappingURL=chunk-CIAESB2C.js.map
66
+ //# sourceMappingURL=chunk-FOVQCGAH.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["/home/runner/work/agentcash-telemetry/agentcash-telemetry/dist/chunk-FOVQCGAH.js","../src/telemetry.ts"],"names":[],"mappings":"AAAA;AACE;AACA;AACA;AACF,sDAA4B;AAC5B;AACA;ACAA,qCAA+C;AAC/C;AAkBO,SAAS,aAAA,CAAc,OAAA,EAA2B;AACvD,EAAA,OAAO,MAAA,CAAO,OAAA,EAAA,GAAgD;AAC5D,IAAA,MAAM,KAAA,EAAO,iDAAA,OAA0B,CAAA;AACvC,IAAA,MAAM,IAAA,EAAM,oDAAA,IAA0B,CAAA;AAGtC,IAAA,IAAI,kBAAA,EAAmC,IAAA;AACvC,IAAA,GAAA,CAAI,IAAA,CAAK,OAAA,IAAW,OAAA,GAAU,IAAA,CAAK,OAAA,IAAW,MAAA,GAAS,IAAA,CAAK,OAAA,IAAW,OAAA,EAAS;AAC9E,MAAA,IAAI;AACF,QAAA,MAAM,KAAA,EAAO,MAAM,OAAA,CAAQ,KAAA,CAAM,CAAA,CAAE,IAAA,CAAK,CAAA;AACxC,QAAA,GAAA,CAAI,IAAA,EAAM,kBAAA,EAAoB,IAAA;AAAA,MAChC,EAAA,UAAQ;AAAA,MAER;AAAA,IACF;AAGA,IAAA,IAAI,QAAA;AACJ,IAAA,IAAI,aAAA,EAAwB,IAAA;AAE5B,IAAA,IAAI;AACF,MAAA,SAAA,EAAW,MAAM,OAAA,CAAQ,OAAA,EAAS,GAAG,CAAA;AAAA,IACvC,EAAA,MAAA,CAAS,KAAA,EAAgB;AACvB,MAAA,aAAA,EAAe,KAAA;AACf,MAAA,GAAA,CAAI,MAAA,WAAiB,oBAAA,EAAc;AACjC,QAAA,SAAA,EAAW,KAAA;AAAA,MACb,EAAA,KAAO;AACL,QAAA,MAAM,QAAA,EAAU,MAAA,WAAiB,MAAA,EAAQ,KAAA,CAAM,QAAA,EAAU,uBAAA;AACzD,QAAA,SAAA,EAAW,oBAAA,CAAa,IAAA,CAAK,EAAE,OAAA,EAAS,KAAA,EAAO,KAAA,EAAO,QAAQ,CAAA,EAAG,EAAE,MAAA,EAAQ,IAAI,CAAC,CAAA;AAAA,MAClF;AAAA,IACF;AAGA,IAAA,GAAA,CAAI,QAAA,CAAS,OAAA,IAAW,GAAA,EAAK;AAG3B,MAAA,MAAM,OAAA,EAAS,QAAA,CAAS,MAAA;AACxB,MAAA,MAAM,gBAAA,EAAkB,IAAA,CAAK,SAAA,CAAU,MAAA,CAAO,WAAA,CAAY,QAAA,CAAS,OAAA,CAAQ,OAAA,CAAQ,CAAC,CAAC,CAAA;AACrF,MAAA,MAAM,YAAA,mBAAc,QAAA,CAAS,OAAA,CAAQ,GAAA,CAAI,cAAc,CAAA,UAAK,MAAA;AAC5D,MAAA,IAAI,mBAAA,EAAoC,IAAA;AACxC,MAAA,IAAI;AACF,QAAA,mBAAA,EAAqB,MAAM,QAAA,CAAS,KAAA,CAAM,CAAA,CAAE,IAAA,CAAK,CAAA;AAAA,MACnD,EAAA,WAAQ;AAAA,MAER;AAIA,MAAA,2BAAA,CAAM,EAAA,GAAM;AACV,QAAA,IAAI;AACF,UAAA,+CAAA,IAAiB,EAAM,iBAAA,EAAmB;AAAA,YACxC,MAAA;AAAA,YACA,IAAA,EAAM,kBAAA;AAAA,YACN,OAAA,EAAS,eAAA;AAAA,YACT;AAAA,UACF,CAAC,CAAA;AAAA,QACH,EAAA,WAAQ;AAAA,QAER;AAAA,MACF,CAAC,CAAA;AAAA,IACH;AAGA,IAAA,GAAA,CAAI,aAAA,GAAgB,CAAA,CAAE,aAAA,WAAwB,oBAAA,CAAA,EAAe;AAC3D,MAAA,MAAM,YAAA;AAAA,IACR;AAEA,IAAA,OAAO,QAAA;AAAA,EACT,CAAA;AACF;ADjCA;AACA;AACE;AACF,sCAAC","file":"/home/runner/work/agentcash-telemetry/agentcash-telemetry/dist/chunk-FOVQCGAH.js","sourcesContent":[null,"/**\n * Core telemetry wrapper for Next.js route handlers.\n * Extracts identity headers, logs to ClickHouse, extracts verified wallet.\n * This is a passive observer — it never influences the response.\n */\n\nimport { type NextRequest, NextResponse } from 'next/server';\nimport { after } from 'next/server';\nimport type { TelemetryContext } from './types';\nimport { extractRequestMeta, buildTelemetryContext, recordInvocation } from './telemetry-core';\n\ntype TelemetryHandler = (request: NextRequest, ctx: TelemetryContext) => Promise<NextResponse>;\n\n/**\n * Wrap a Next.js route handler with telemetry.\n * Extracts identity headers, logs the invocation to ClickHouse,\n * and auto-extracts verified wallet from x402 payment headers.\n *\n * Uses Next.js after() to defer the ClickHouse insert until after\n * the response is sent. On Vercel this keeps the Lambda alive until\n * the insert completes, avoiding frozen in-flight promises.\n *\n * The entire telemetry code path is wrapped in try/catch.\n * Telemetry failures never affect the response.\n */\nexport function withTelemetry(handler: TelemetryHandler) {\n return async (request: NextRequest): Promise<NextResponse> => {\n const meta = extractRequestMeta(request);\n const ctx = buildTelemetryContext(meta);\n\n // Capture request body for logging (only for methods with bodies)\n let requestBodyString: string | null = null;\n if (meta.method === 'POST' || meta.method === 'PUT' || meta.method === 'PATCH') {\n try {\n const body = await request.clone().text();\n if (body) requestBodyString = body;\n } catch {\n // Body read failed — that's fine\n }\n }\n\n // Execute the actual handler\n let response: NextResponse;\n let handlerError: unknown = null;\n\n try {\n response = await handler(request, ctx);\n } catch (error: unknown) {\n handlerError = error;\n if (error instanceof NextResponse) {\n response = error;\n } else {\n const message = error instanceof Error ? error.message : 'Internal server error';\n response = NextResponse.json({ success: false, error: message }, { status: 500 });\n }\n }\n\n // 402 is the x402/MPP payment challenge — not a real invocation, skip logging\n if (response.status !== 402) {\n // Capture all response data before returning — response.clone() must happen\n // before Next.js consumes the body to send it to the client.\n const status = response.status;\n const responseHeaders = JSON.stringify(Object.fromEntries(response.headers.entries()));\n const contentType = response.headers.get('content-type') ?? null;\n let responseBodyString: string | null = null;\n try {\n responseBodyString = await response.clone().text();\n } catch {\n // Response body read failed — that's fine\n }\n\n // Defer the ClickHouse insert until after the response is sent.\n // On Vercel, after() keeps the Lambda alive until the insert completes.\n after(() => {\n try {\n recordInvocation(meta, requestBodyString, {\n status,\n body: responseBodyString,\n headers: responseHeaders,\n contentType,\n });\n } catch {\n // Telemetry never affects the response\n }\n });\n }\n\n // Re-throw the original error if it wasn't a NextResponse\n if (handlerError && !(handlerError instanceof NextResponse)) {\n throw handlerError;\n }\n\n return response;\n };\n}\n"]}
@@ -6,6 +6,7 @@ import {
6
6
 
7
7
  // src/telemetry.ts
8
8
  import { NextResponse } from "next/server";
9
+ import { after } from "next/server";
9
10
  function withTelemetry(handler) {
10
11
  return async (request) => {
11
12
  const meta = extractRequestMeta(request);
@@ -31,17 +32,25 @@ function withTelemetry(handler) {
31
32
  response = NextResponse.json({ success: false, error: message }, { status: 500 });
32
33
  }
33
34
  }
34
- let responseBodyString = null;
35
- try {
36
- responseBodyString = await response.clone().text();
37
- } catch {
38
- }
39
35
  if (response.status !== 402) {
40
- recordInvocation(meta, requestBodyString, {
41
- status: response.status,
42
- body: responseBodyString,
43
- headers: JSON.stringify(Object.fromEntries(response.headers.entries())),
44
- contentType: response.headers.get("content-type") ?? null
36
+ const status = response.status;
37
+ const responseHeaders = JSON.stringify(Object.fromEntries(response.headers.entries()));
38
+ const contentType = response.headers.get("content-type") ?? null;
39
+ let responseBodyString = null;
40
+ try {
41
+ responseBodyString = await response.clone().text();
42
+ } catch {
43
+ }
44
+ after(() => {
45
+ try {
46
+ recordInvocation(meta, requestBodyString, {
47
+ status,
48
+ body: responseBodyString,
49
+ headers: responseHeaders,
50
+ contentType
51
+ });
52
+ } catch {
53
+ }
45
54
  });
46
55
  }
47
56
  if (handlerError && !(handlerError instanceof NextResponse)) {
@@ -54,4 +63,4 @@ function withTelemetry(handler) {
54
63
  export {
55
64
  withTelemetry
56
65
  };
57
- //# sourceMappingURL=chunk-YAHKVH4T.mjs.map
66
+ //# sourceMappingURL=chunk-OHOHTH2I.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/telemetry.ts"],"sourcesContent":["/**\n * Core telemetry wrapper for Next.js route handlers.\n * Extracts identity headers, logs to ClickHouse, extracts verified wallet.\n * This is a passive observer — it never influences the response.\n */\n\nimport { type NextRequest, NextResponse } from 'next/server';\nimport { after } from 'next/server';\nimport type { TelemetryContext } from './types';\nimport { extractRequestMeta, buildTelemetryContext, recordInvocation } from './telemetry-core';\n\ntype TelemetryHandler = (request: NextRequest, ctx: TelemetryContext) => Promise<NextResponse>;\n\n/**\n * Wrap a Next.js route handler with telemetry.\n * Extracts identity headers, logs the invocation to ClickHouse,\n * and auto-extracts verified wallet from x402 payment headers.\n *\n * Uses Next.js after() to defer the ClickHouse insert until after\n * the response is sent. On Vercel this keeps the Lambda alive until\n * the insert completes, avoiding frozen in-flight promises.\n *\n * The entire telemetry code path is wrapped in try/catch.\n * Telemetry failures never affect the response.\n */\nexport function withTelemetry(handler: TelemetryHandler) {\n return async (request: NextRequest): Promise<NextResponse> => {\n const meta = extractRequestMeta(request);\n const ctx = buildTelemetryContext(meta);\n\n // Capture request body for logging (only for methods with bodies)\n let requestBodyString: string | null = null;\n if (meta.method === 'POST' || meta.method === 'PUT' || meta.method === 'PATCH') {\n try {\n const body = await request.clone().text();\n if (body) requestBodyString = body;\n } catch {\n // Body read failed — that's fine\n }\n }\n\n // Execute the actual handler\n let response: NextResponse;\n let handlerError: unknown = null;\n\n try {\n response = await handler(request, ctx);\n } catch (error: unknown) {\n handlerError = error;\n if (error instanceof NextResponse) {\n response = error;\n } else {\n const message = error instanceof Error ? error.message : 'Internal server error';\n response = NextResponse.json({ success: false, error: message }, { status: 500 });\n }\n }\n\n // 402 is the x402/MPP payment challenge — not a real invocation, skip logging\n if (response.status !== 402) {\n // Capture all response data before returning — response.clone() must happen\n // before Next.js consumes the body to send it to the client.\n const status = response.status;\n const responseHeaders = JSON.stringify(Object.fromEntries(response.headers.entries()));\n const contentType = response.headers.get('content-type') ?? null;\n let responseBodyString: string | null = null;\n try {\n responseBodyString = await response.clone().text();\n } catch {\n // Response body read failed — that's fine\n }\n\n // Defer the ClickHouse insert until after the response is sent.\n // On Vercel, after() keeps the Lambda alive until the insert completes.\n after(() => {\n try {\n recordInvocation(meta, requestBodyString, {\n status,\n body: responseBodyString,\n headers: responseHeaders,\n contentType,\n });\n } catch {\n // Telemetry never affects the response\n }\n });\n }\n\n // Re-throw the original error if it wasn't a NextResponse\n if (handlerError && !(handlerError instanceof NextResponse)) {\n throw handlerError;\n }\n\n return response;\n };\n}\n"],"mappings":";;;;;;;AAMA,SAA2B,oBAAoB;AAC/C,SAAS,aAAa;AAkBf,SAAS,cAAc,SAA2B;AACvD,SAAO,OAAO,YAAgD;AAC5D,UAAM,OAAO,mBAAmB,OAAO;AACvC,UAAM,MAAM,sBAAsB,IAAI;AAGtC,QAAI,oBAAmC;AACvC,QAAI,KAAK,WAAW,UAAU,KAAK,WAAW,SAAS,KAAK,WAAW,SAAS;AAC9E,UAAI;AACF,cAAM,OAAO,MAAM,QAAQ,MAAM,EAAE,KAAK;AACxC,YAAI,KAAM,qBAAoB;AAAA,MAChC,QAAQ;AAAA,MAER;AAAA,IACF;AAGA,QAAI;AACJ,QAAI,eAAwB;AAE5B,QAAI;AACF,iBAAW,MAAM,QAAQ,SAAS,GAAG;AAAA,IACvC,SAAS,OAAgB;AACvB,qBAAe;AACf,UAAI,iBAAiB,cAAc;AACjC,mBAAW;AAAA,MACb,OAAO;AACL,cAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU;AACzD,mBAAW,aAAa,KAAK,EAAE,SAAS,OAAO,OAAO,QAAQ,GAAG,EAAE,QAAQ,IAAI,CAAC;AAAA,MAClF;AAAA,IACF;AAGA,QAAI,SAAS,WAAW,KAAK;AAG3B,YAAM,SAAS,SAAS;AACxB,YAAM,kBAAkB,KAAK,UAAU,OAAO,YAAY,SAAS,QAAQ,QAAQ,CAAC,CAAC;AACrF,YAAM,cAAc,SAAS,QAAQ,IAAI,cAAc,KAAK;AAC5D,UAAI,qBAAoC;AACxC,UAAI;AACF,6BAAqB,MAAM,SAAS,MAAM,EAAE,KAAK;AAAA,MACnD,QAAQ;AAAA,MAER;AAIA,YAAM,MAAM;AACV,YAAI;AACF,2BAAiB,MAAM,mBAAmB;AAAA,YACxC;AAAA,YACA,MAAM;AAAA,YACN,SAAS;AAAA,YACT;AAAA,UACF,CAAC;AAAA,QACH,QAAQ;AAAA,QAER;AAAA,MACF,CAAC;AAAA,IACH;AAGA,QAAI,gBAAgB,EAAE,wBAAwB,eAAe;AAC3D,YAAM;AAAA,IACR;AAEA,WAAO;AAAA,EACT;AACF;","names":[]}
package/dist/index.d.mts CHANGED
@@ -38,6 +38,10 @@ type TelemetryHandler = (request: NextRequest, ctx: TelemetryContext) => Promise
38
38
  * Extracts identity headers, logs the invocation to ClickHouse,
39
39
  * and auto-extracts verified wallet from x402 payment headers.
40
40
  *
41
+ * Uses Next.js after() to defer the ClickHouse insert until after
42
+ * the response is sent. On Vercel this keeps the Lambda alive until
43
+ * the insert completes, avoiding frozen in-flight promises.
44
+ *
41
45
  * The entire telemetry code path is wrapped in try/catch.
42
46
  * Telemetry failures never affect the response.
43
47
  */
package/dist/index.d.ts CHANGED
@@ -38,6 +38,10 @@ type TelemetryHandler = (request: NextRequest, ctx: TelemetryContext) => Promise
38
38
  * Extracts identity headers, logs the invocation to ClickHouse,
39
39
  * and auto-extracts verified wallet from x402 payment headers.
40
40
  *
41
+ * Uses Next.js after() to defer the ClickHouse insert until after
42
+ * the response is sent. On Vercel this keeps the Lambda alive until
43
+ * the insert completes, avoiding frozen in-flight promises.
44
+ *
41
45
  * The entire telemetry code path is wrapped in try/catch.
42
46
  * Telemetry failures never affect the response.
43
47
  */
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";Object.defineProperty(exports, "__esModule", {value: true});
2
2
 
3
- var _chunkCIAESB2Cjs = require('./chunk-CIAESB2C.js');
3
+ var _chunkFOVQCGAHjs = require('./chunk-FOVQCGAH.js');
4
4
 
5
5
 
6
6
 
@@ -10,5 +10,5 @@ require('./chunk-QEJ7ZGGH.js');
10
10
 
11
11
 
12
12
 
13
- exports.extractVerifiedWallet = _chunk2EFPFJCBjs.extractVerifiedWallet; exports.initTelemetry = _chunk2EFPFJCBjs.initTelemetry; exports.withTelemetry = _chunkCIAESB2Cjs.withTelemetry;
13
+ exports.extractVerifiedWallet = _chunk2EFPFJCBjs.extractVerifiedWallet; exports.initTelemetry = _chunk2EFPFJCBjs.initTelemetry; exports.withTelemetry = _chunkFOVQCGAHjs.withTelemetry;
14
14
  //# sourceMappingURL=index.js.map
package/dist/index.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  withTelemetry
3
- } from "./chunk-YAHKVH4T.mjs";
3
+ } from "./chunk-OHOHTH2I.mjs";
4
4
  import {
5
5
  extractVerifiedWallet,
6
6
  initTelemetry
@@ -63,6 +63,10 @@ interface ResponseMeta {
63
63
  duration: number;
64
64
  contentType: string | null;
65
65
  headers: Record<string, string>;
66
+ /** Parsed request body (when .body() was used). undefined when no body was parsed. */
67
+ requestBody?: unknown;
68
+ /** Handler return value. undefined for raw Response returns (streams) or error paths. */
69
+ responseBody?: unknown;
66
70
  }
67
71
  interface ErrorEvent {
68
72
  status: number;
@@ -63,6 +63,10 @@ interface ResponseMeta {
63
63
  duration: number;
64
64
  contentType: string | null;
65
65
  headers: Record<string, string>;
66
+ /** Parsed request body (when .body() was used). undefined when no body was parsed. */
67
+ requestBody?: unknown;
68
+ /** Handler return value. undefined for raw Response returns (streams) or error paths. */
69
+ responseBody?: unknown;
66
70
  }
67
71
  interface ErrorEvent {
68
72
  status: number;
@@ -63,13 +63,13 @@ function createTelemetryPlugin(config) {
63
63
  referer: meta.referer,
64
64
  request_content_type: meta.contentType,
65
65
  request_headers: JSON.stringify(meta.headers),
66
- request_body: null,
66
+ request_body: response.requestBody !== void 0 ? JSON.stringify(response.requestBody) : null,
67
67
  status_code: response.statusCode,
68
68
  status_text: response.statusText,
69
69
  duration: response.duration,
70
70
  response_content_type: response.contentType,
71
71
  response_headers: JSON.stringify(response.headers),
72
- response_body: null,
72
+ response_body: response.responseBody !== void 0 ? JSON.stringify(response.responseBody) : null,
73
73
  created_at: /* @__PURE__ */ new Date()
74
74
  };
75
75
  _chunkQEJ7ZGGHjs.insertInvocation.call(void 0, row);
@@ -1 +1 @@
1
- {"version":3,"sources":["/home/runner/work/agentcash-telemetry/agentcash-telemetry/dist/router-plugin.js","../src/router-plugin.ts"],"names":[],"mappings":"AAAA;AACE;AACA;AACA;AACF,sDAA4B;AAC5B;AACA;ACmIO,SAAS,qBAAA,CAAsB,MAAA,EAA6C;AAEjF,EAAA,6CAAA,MAAe,CAAO,UAAU,CAAA;AAChC,EAAA,GAAA,CAAI,MAAA,CAAO,MAAA,EAAQ;AACjB,IAAA,6CAAA,CAAe;AAAA,EACjB;AAEA,EAAA,MAAM,IAAA,mBAAM,MAAA,CAAO,OAAA,UAAW,OAAA;AAE9B,EAAA,OAAO;AAAA,IACL,SAAA,CAAU,IAAA,EAAkC;AAC1C,MAAA,MAAM,IAAA,EAA8B;AAAA,QAClC,SAAA,EAAW,IAAA,CAAK,SAAA;AAAA,QAChB,KAAA,EAAO,IAAA,CAAK,KAAA;AAAA,QACZ,aAAA,EAAe,IAAA,CAAK,aAAA;AAAA,QACpB,QAAA,EAAU,IAAA,CAAK,QAAA;AAAA,QACf,SAAA,EAAW,IAAA,CAAK,SAAA;AAAA,QAChB,cAAA,EAAgB,IAAA;AAAA,QAChB,iBAAA,CAAkB,OAAA,EAAiB;AACjC,UAAA,GAAA,CAAI,eAAA,EAAiB,OAAA;AAAA,QACvB,CAAA;AAAA,QACA,KAAA,EAAO;AAAA,MACT,CAAA;AACA,MAAA,OAAO,GAAA;AAAA,IACT,CAAA;AAAA,IAEA,iBAAA,CAAkB,GAAA,EAAoB,OAAA,EAAuB;AAC3D,MAAC,GAAA,CAA+B,SAAA,EAAW,OAAA;AAC3C,MAAA,GAAA,CAAI,GAAA,EAAK;AACP,QAAA,OAAA,CAAQ,GAAA,CAAI,CAAA,qBAAA,EAAwB,OAAA,CAAQ,QAAQ,CAAA,CAAA,EAAI,OAAA,CAAQ,KAAK,CAAA,CAAA,EAAI,OAAA,CAAQ,MAAM,CAAA,CAAA;AACzF,MAAA;AACF,IAAA;AAEkE,IAAA;AAClB,MAAA;AACrC,MAAA;AAC8E,QAAA;AACvF,MAAA;AACF,IAAA;AAEuD,IAAA;AACxC,MAAA;AACK,MAAA;AAET,MAAA;AAC+D,QAAA;AAC9D,QAAA;AACwE,UAAA;AAChF,QAAA;AACF,MAAA;AAGiC,MAAA;AAC/B,QAAA;AACF,MAAA;AAEmC,MAAA;AACxB,QAAA;AAC8C,QAAA;AACrC,QAAA;AACD,QAAA;AAC6C,QAAA;AAEjD,QAAA;AACD,QAAA;AACC,QAAA;AACC,QAAA;AACa,QAAA;AACiB,QAAA;AAC9B,QAAA;AAEQ,QAAA;AACA,QAAA;AACH,QAAA;AACa,QAAA;AACiB,QAAA;AAClC,QAAA;AAEM,QAAA;AACvB,MAAA;AAEoB,MAAA;AACtB,IAAA;AAE+C,IAAA;AACpC,MAAA;AAC4D,QAAA;AACrE,MAAA;AACF,IAAA;AAE+C,IAAA;AACpC,MAAA;AAID,QAAA;AAGN,QAAA;AAC2E,UAAA;AAC3D,2BAAA;AAChB,QAAA;AACF,MAAA;AACF,IAAA;AAE+D,IAAA;AACpD,MAAA;AAKC,QAAA;AAEgF,QAAA;AAC1F,MAAA;AACF,IAAA;AACF,EAAA;AACF;AD5JgG;AACA;AACA","file":"/home/runner/work/agentcash-telemetry/agentcash-telemetry/dist/router-plugin.js","sourcesContent":[null,"/**\n * RouterPlugin adapter for @agentcash/router.\n *\n * Bridges the router's plugin hooks into ClickHouse telemetry.\n * Uses the same mcp_resource_invocations table as the legacy withTelemetry wrapper.\n *\n * Usage:\n * import { createRouter } from '@agentcash/router';\n * import { createTelemetryPlugin } from '@agentcash/telemetry/plugin';\n *\n * const router = createRouter({\n * payeeAddress: '...',\n * plugin: createTelemetryPlugin({\n * clickhouse: {\n * url: process.env.TELEM_CLICKHOUSE_URL ?? 'http://localhost:8123',\n * database: process.env.TELEM_CLICKHOUSE_DATABASE,\n * username: process.env.TELEM_CLICKHOUSE_USERNAME,\n * password: process.env.TELEM_CLICKHOUSE_PASSWORD,\n * },\n * }),\n * });\n */\n\nimport { initClickhouse, pingClickhouse, insertInvocation } from './clickhouse';\nimport type { McpResourceInvocation, TelemetryConfig } from './types';\n\n// ---------------------------------------------------------------------------\n// Minimal RouterPlugin types (inlined to avoid depending on @agentcash/router\n// at runtime — the router passes these shapes, we just consume them)\n// ---------------------------------------------------------------------------\n\ninterface RequestMeta {\n requestId: string;\n method: string;\n route: string;\n origin: string;\n referer: string | null;\n walletAddress: string | null;\n clientId: string | null;\n sessionId: string | null;\n contentType: string | null;\n headers: Record<string, string>;\n startTime: number;\n}\n\ninterface PluginContext {\n readonly requestId: string;\n readonly route: string;\n readonly walletAddress: string | null;\n readonly clientId: string | null;\n readonly sessionId: string | null;\n verifiedWallet: string | null;\n setVerifiedWallet(address: string): void;\n}\n\ninterface PaymentEvent {\n protocol: 'x402' | 'mpp';\n payer: string;\n amount: string;\n network: string;\n}\n\ninterface SettlementEvent {\n protocol: 'x402' | 'mpp';\n payer: string;\n transaction: string;\n network: string;\n}\n\ninterface ResponseMeta {\n statusCode: number;\n statusText: string;\n duration: number;\n contentType: string | null;\n headers: Record<string, string>;\n}\n\ninterface ErrorEvent {\n status: number;\n message: string;\n settled: boolean;\n}\n\ninterface AlertEvent {\n level: string;\n message: string;\n route: string;\n meta?: Record<string, unknown>;\n}\n\ninterface ProviderQuotaEvent {\n provider: string;\n route: string;\n remaining: number | null;\n limit: number | null;\n level: string;\n overage: string;\n message: string;\n}\n\n/** RouterPlugin interface — must match @agentcash/router's RouterPlugin */\ninterface RouterPlugin {\n init?(config: { origin?: string }): void | Promise<void>;\n onRequest?(meta: RequestMeta): PluginContext;\n onPaymentVerified?(ctx: PluginContext, payment: PaymentEvent): void;\n onPaymentSettled?(ctx: PluginContext, settlement: SettlementEvent): void;\n onResponse?(ctx: PluginContext, response: ResponseMeta): void;\n onError?(ctx: PluginContext, error: ErrorEvent): void;\n onAlert?(ctx: PluginContext, alert: AlertEvent): void;\n onProviderQuota?(ctx: PluginContext, event: ProviderQuotaEvent): void;\n}\n\n// ---------------------------------------------------------------------------\n// Extended context — carries request metadata through the lifecycle\n// ---------------------------------------------------------------------------\n\ninterface TelemetryPluginContext extends PluginContext {\n /** Stored from onRequest for use in onResponse */\n _meta: RequestMeta;\n /** Payment info captured between verify and response */\n _payment?: PaymentEvent;\n /** Settlement info captured between settle and response */\n _settlement?: SettlementEvent;\n}\n\n// ---------------------------------------------------------------------------\n// Plugin factory\n// ---------------------------------------------------------------------------\n\nexport interface TelemetryPluginConfig {\n clickhouse: TelemetryConfig['clickhouse'];\n /** If true, pings ClickHouse on init. */\n verify?: boolean;\n /** Console logging for dev. Default: false. */\n console?: boolean;\n}\n\nexport function createTelemetryPlugin(config: TelemetryPluginConfig): RouterPlugin {\n // Initialize ClickHouse synchronously (connection happens on first query)\n initClickhouse(config.clickhouse);\n if (config.verify) {\n pingClickhouse();\n }\n\n const log = config.console ?? false;\n\n return {\n onRequest(meta: RequestMeta): PluginContext {\n const ctx: TelemetryPluginContext = {\n requestId: meta.requestId,\n route: meta.route,\n walletAddress: meta.walletAddress,\n clientId: meta.clientId,\n sessionId: meta.sessionId,\n verifiedWallet: null,\n setVerifiedWallet(address: string) {\n ctx.verifiedWallet = address;\n },\n _meta: meta,\n };\n return ctx as PluginContext;\n },\n\n onPaymentVerified(ctx: PluginContext, payment: PaymentEvent) {\n (ctx as TelemetryPluginContext)._payment = payment;\n if (log) {\n console.log(`[telemetry] VERIFIED ${payment.protocol} ${payment.payer} ${payment.amount}`);\n }\n },\n\n onPaymentSettled(ctx: PluginContext, settlement: SettlementEvent) {\n (ctx as TelemetryPluginContext)._settlement = settlement;\n if (log) {\n console.log(`[telemetry] SETTLED ${settlement.protocol} tx=${settlement.transaction}`);\n }\n },\n\n onResponse(ctx: PluginContext, response: ResponseMeta) {\n const tCtx = ctx as TelemetryPluginContext;\n const meta = tCtx._meta;\n\n if (log) {\n const wallet = ctx.verifiedWallet ? ` wallet=${ctx.verifiedWallet}` : '';\n console.log(\n `[telemetry] ${meta.route} → ${response.statusCode} (${response.duration}ms)${wallet}`,\n );\n }\n\n // 402 is the x402/MPP payment challenge — not a real invocation, skip logging\n if (response.statusCode === 402) {\n return;\n }\n\n const row: McpResourceInvocation = {\n id: meta.requestId,\n x_wallet_address: meta.walletAddress?.toLowerCase() ?? null,\n x_client_id: meta.clientId,\n session_id: meta.sessionId,\n verified_wallet_address: ctx.verifiedWallet?.toLowerCase() ?? null,\n\n method: meta.method,\n route: meta.route,\n origin: meta.origin,\n referer: meta.referer,\n request_content_type: meta.contentType,\n request_headers: JSON.stringify(meta.headers),\n request_body: null,\n\n status_code: response.statusCode,\n status_text: response.statusText,\n duration: response.duration,\n response_content_type: response.contentType,\n response_headers: JSON.stringify(response.headers),\n response_body: null,\n\n created_at: new Date(),\n };\n\n insertInvocation(row);\n },\n\n onError(ctx: PluginContext, error: ErrorEvent) {\n if (log) {\n console.error(`[telemetry] ERROR ${error.status}: ${error.message}`);\n }\n },\n\n onAlert(ctx: PluginContext, alert: AlertEvent) {\n if (log) {\n const logFn =\n alert.level === 'critical' || alert.level === 'error'\n ? console.error\n : alert.level === 'warn'\n ? console.warn\n : console.log;\n logFn(\n `[telemetry] ${alert.level.toUpperCase()} ${alert.route}: ${alert.message}`,\n alert.meta ?? '',\n );\n }\n },\n\n onProviderQuota(ctx: PluginContext, event: ProviderQuotaEvent) {\n if (log) {\n const logFn =\n event.level === 'critical'\n ? console.error\n : event.level === 'warn'\n ? console.warn\n : console.log;\n logFn(`[telemetry] QUOTA ${event.level.toUpperCase()} ${event.provider}: ${event.message}`);\n }\n },\n };\n}\n"]}
1
+ {"version":3,"sources":["/home/runner/work/agentcash-telemetry/agentcash-telemetry/dist/router-plugin.js","../src/router-plugin.ts"],"names":[],"mappings":"AAAA;AACE;AACA;AACA;AACF,sDAA4B;AAC5B;AACA;ACuIO,SAAS,qBAAA,CAAsB,MAAA,EAA6C;AAEjF,EAAA,6CAAA,MAAe,CAAO,UAAU,CAAA;AAChC,EAAA,GAAA,CAAI,MAAA,CAAO,MAAA,EAAQ;AACjB,IAAA,6CAAA,CAAe;AAAA,EACjB;AAEA,EAAA,MAAM,IAAA,mBAAM,MAAA,CAAO,OAAA,UAAW,OAAA;AAE9B,EAAA,OAAO;AAAA,IACL,SAAA,CAAU,IAAA,EAAkC;AAC1C,MAAA,MAAM,IAAA,EAA8B;AAAA,QAClC,SAAA,EAAW,IAAA,CAAK,SAAA;AAAA,QAChB,KAAA,EAAO,IAAA,CAAK,KAAA;AAAA,QACZ,aAAA,EAAe,IAAA,CAAK,aAAA;AAAA,QACpB,QAAA,EAAU,IAAA,CAAK,QAAA;AAAA,QACf,SAAA,EAAW,IAAA,CAAK,SAAA;AAAA,QAChB,cAAA,EAAgB,IAAA;AAAA,QAChB,iBAAA,CAAkB,OAAA,EAAiB;AACjC,UAAA,GAAA,CAAI,eAAA,EAAiB,OAAA;AAAA,QACvB,CAAA;AAAA,QACA,KAAA,EAAO;AAAA,MACT,CAAA;AACA,MAAA,OAAO,GAAA;AAAA,IACT,CAAA;AAAA,IAEA,iBAAA,CAAkB,GAAA,EAAoB,OAAA,EAAuB;AAC3D,MAAC,GAAA,CAA+B,SAAA,EAAW,OAAA;AAC3C,MAAA,GAAA,CAAI,GAAA,EAAK;AACP,QAAA,OAAA,CAAQ,GAAA,CAAI,CAAA,qBAAA,EAAwB,OAAA,CAAQ,QAAQ,CAAA,CAAA,EAAI,OAAA,CAAQ,KAAK,CAAA,CAAA,EAAI,OAAA,CAAQ,MAAM,CAAA,CAAA;AACzF,MAAA;AACF,IAAA;AAEkE,IAAA;AAClB,MAAA;AACrC,MAAA;AAC8E,QAAA;AACvF,MAAA;AACF,IAAA;AAEuD,IAAA;AACxC,MAAA;AACK,MAAA;AAET,MAAA;AAC+D,QAAA;AAC9D,QAAA;AACwE,UAAA;AAChF,QAAA;AACF,MAAA;AAGiC,MAAA;AAC/B,QAAA;AACF,MAAA;AAEmC,MAAA;AACxB,QAAA;AAC8C,QAAA;AACrC,QAAA;AACD,QAAA;AAC6C,QAAA;AAEjD,QAAA;AACD,QAAA;AACC,QAAA;AACC,QAAA;AACa,QAAA;AACiB,QAAA;AAEkC,QAAA;AAExD,QAAA;AACA,QAAA;AACH,QAAA;AACa,QAAA;AACiB,QAAA;AAE2B,QAAA;AAEvD,QAAA;AACvB,MAAA;AAEoB,MAAA;AACtB,IAAA;AAE+C,IAAA;AACpC,MAAA;AAC4D,QAAA;AACrE,MAAA;AACF,IAAA;AAE+C,IAAA;AACpC,MAAA;AAID,QAAA;AAGN,QAAA;AAC2E,UAAA;AAC3D,2BAAA;AAChB,QAAA;AACF,MAAA;AACF,IAAA;AAE+D,IAAA;AACpD,MAAA;AAKC,QAAA;AAEgF,QAAA;AAC1F,MAAA;AACF,IAAA;AACF,EAAA;AACF;ADlKgG;AACA;AACA","file":"/home/runner/work/agentcash-telemetry/agentcash-telemetry/dist/router-plugin.js","sourcesContent":[null,"/**\n * RouterPlugin adapter for @agentcash/router.\n *\n * Bridges the router's plugin hooks into ClickHouse telemetry.\n * Uses the same mcp_resource_invocations table as the legacy withTelemetry wrapper.\n *\n * Usage:\n * import { createRouter } from '@agentcash/router';\n * import { createTelemetryPlugin } from '@agentcash/telemetry/plugin';\n *\n * const router = createRouter({\n * payeeAddress: '...',\n * plugin: createTelemetryPlugin({\n * clickhouse: {\n * url: process.env.TELEM_CLICKHOUSE_URL ?? 'http://localhost:8123',\n * database: process.env.TELEM_CLICKHOUSE_DATABASE,\n * username: process.env.TELEM_CLICKHOUSE_USERNAME,\n * password: process.env.TELEM_CLICKHOUSE_PASSWORD,\n * },\n * }),\n * });\n */\n\nimport { initClickhouse, pingClickhouse, insertInvocation } from './clickhouse';\nimport type { McpResourceInvocation, TelemetryConfig } from './types';\n\n// ---------------------------------------------------------------------------\n// Minimal RouterPlugin types (inlined to avoid depending on @agentcash/router\n// at runtime — the router passes these shapes, we just consume them)\n// ---------------------------------------------------------------------------\n\ninterface RequestMeta {\n requestId: string;\n method: string;\n route: string;\n origin: string;\n referer: string | null;\n walletAddress: string | null;\n clientId: string | null;\n sessionId: string | null;\n contentType: string | null;\n headers: Record<string, string>;\n startTime: number;\n}\n\ninterface PluginContext {\n readonly requestId: string;\n readonly route: string;\n readonly walletAddress: string | null;\n readonly clientId: string | null;\n readonly sessionId: string | null;\n verifiedWallet: string | null;\n setVerifiedWallet(address: string): void;\n}\n\ninterface PaymentEvent {\n protocol: 'x402' | 'mpp';\n payer: string;\n amount: string;\n network: string;\n}\n\ninterface SettlementEvent {\n protocol: 'x402' | 'mpp';\n payer: string;\n transaction: string;\n network: string;\n}\n\ninterface ResponseMeta {\n statusCode: number;\n statusText: string;\n duration: number;\n contentType: string | null;\n headers: Record<string, string>;\n /** Parsed request body (when .body() was used). undefined when no body was parsed. */\n requestBody?: unknown;\n /** Handler return value. undefined for raw Response returns (streams) or error paths. */\n responseBody?: unknown;\n}\n\ninterface ErrorEvent {\n status: number;\n message: string;\n settled: boolean;\n}\n\ninterface AlertEvent {\n level: string;\n message: string;\n route: string;\n meta?: Record<string, unknown>;\n}\n\ninterface ProviderQuotaEvent {\n provider: string;\n route: string;\n remaining: number | null;\n limit: number | null;\n level: string;\n overage: string;\n message: string;\n}\n\n/** RouterPlugin interface — must match @agentcash/router's RouterPlugin */\ninterface RouterPlugin {\n init?(config: { origin?: string }): void | Promise<void>;\n onRequest?(meta: RequestMeta): PluginContext;\n onPaymentVerified?(ctx: PluginContext, payment: PaymentEvent): void;\n onPaymentSettled?(ctx: PluginContext, settlement: SettlementEvent): void;\n onResponse?(ctx: PluginContext, response: ResponseMeta): void;\n onError?(ctx: PluginContext, error: ErrorEvent): void;\n onAlert?(ctx: PluginContext, alert: AlertEvent): void;\n onProviderQuota?(ctx: PluginContext, event: ProviderQuotaEvent): void;\n}\n\n// ---------------------------------------------------------------------------\n// Extended context — carries request metadata through the lifecycle\n// ---------------------------------------------------------------------------\n\ninterface TelemetryPluginContext extends PluginContext {\n /** Stored from onRequest for use in onResponse */\n _meta: RequestMeta;\n /** Payment info captured between verify and response */\n _payment?: PaymentEvent;\n /** Settlement info captured between settle and response */\n _settlement?: SettlementEvent;\n}\n\n// ---------------------------------------------------------------------------\n// Plugin factory\n// ---------------------------------------------------------------------------\n\nexport interface TelemetryPluginConfig {\n clickhouse: TelemetryConfig['clickhouse'];\n /** If true, pings ClickHouse on init. */\n verify?: boolean;\n /** Console logging for dev. Default: false. */\n console?: boolean;\n}\n\nexport function createTelemetryPlugin(config: TelemetryPluginConfig): RouterPlugin {\n // Initialize ClickHouse synchronously (connection happens on first query)\n initClickhouse(config.clickhouse);\n if (config.verify) {\n pingClickhouse();\n }\n\n const log = config.console ?? false;\n\n return {\n onRequest(meta: RequestMeta): PluginContext {\n const ctx: TelemetryPluginContext = {\n requestId: meta.requestId,\n route: meta.route,\n walletAddress: meta.walletAddress,\n clientId: meta.clientId,\n sessionId: meta.sessionId,\n verifiedWallet: null,\n setVerifiedWallet(address: string) {\n ctx.verifiedWallet = address;\n },\n _meta: meta,\n };\n return ctx as PluginContext;\n },\n\n onPaymentVerified(ctx: PluginContext, payment: PaymentEvent) {\n (ctx as TelemetryPluginContext)._payment = payment;\n if (log) {\n console.log(`[telemetry] VERIFIED ${payment.protocol} ${payment.payer} ${payment.amount}`);\n }\n },\n\n onPaymentSettled(ctx: PluginContext, settlement: SettlementEvent) {\n (ctx as TelemetryPluginContext)._settlement = settlement;\n if (log) {\n console.log(`[telemetry] SETTLED ${settlement.protocol} tx=${settlement.transaction}`);\n }\n },\n\n onResponse(ctx: PluginContext, response: ResponseMeta) {\n const tCtx = ctx as TelemetryPluginContext;\n const meta = tCtx._meta;\n\n if (log) {\n const wallet = ctx.verifiedWallet ? ` wallet=${ctx.verifiedWallet}` : '';\n console.log(\n `[telemetry] ${meta.route} → ${response.statusCode} (${response.duration}ms)${wallet}`,\n );\n }\n\n // 402 is the x402/MPP payment challenge — not a real invocation, skip logging\n if (response.statusCode === 402) {\n return;\n }\n\n const row: McpResourceInvocation = {\n id: meta.requestId,\n x_wallet_address: meta.walletAddress?.toLowerCase() ?? null,\n x_client_id: meta.clientId,\n session_id: meta.sessionId,\n verified_wallet_address: ctx.verifiedWallet?.toLowerCase() ?? null,\n\n method: meta.method,\n route: meta.route,\n origin: meta.origin,\n referer: meta.referer,\n request_content_type: meta.contentType,\n request_headers: JSON.stringify(meta.headers),\n request_body:\n response.requestBody !== undefined ? JSON.stringify(response.requestBody) : null,\n\n status_code: response.statusCode,\n status_text: response.statusText,\n duration: response.duration,\n response_content_type: response.contentType,\n response_headers: JSON.stringify(response.headers),\n response_body:\n response.responseBody !== undefined ? JSON.stringify(response.responseBody) : null,\n\n created_at: new Date(),\n };\n\n insertInvocation(row);\n },\n\n onError(ctx: PluginContext, error: ErrorEvent) {\n if (log) {\n console.error(`[telemetry] ERROR ${error.status}: ${error.message}`);\n }\n },\n\n onAlert(ctx: PluginContext, alert: AlertEvent) {\n if (log) {\n const logFn =\n alert.level === 'critical' || alert.level === 'error'\n ? console.error\n : alert.level === 'warn'\n ? console.warn\n : console.log;\n logFn(\n `[telemetry] ${alert.level.toUpperCase()} ${alert.route}: ${alert.message}`,\n alert.meta ?? '',\n );\n }\n },\n\n onProviderQuota(ctx: PluginContext, event: ProviderQuotaEvent) {\n if (log) {\n const logFn =\n event.level === 'critical'\n ? console.error\n : event.level === 'warn'\n ? console.warn\n : console.log;\n logFn(`[telemetry] QUOTA ${event.level.toUpperCase()} ${event.provider}: ${event.message}`);\n }\n },\n };\n}\n"]}
@@ -63,13 +63,13 @@ function createTelemetryPlugin(config) {
63
63
  referer: meta.referer,
64
64
  request_content_type: meta.contentType,
65
65
  request_headers: JSON.stringify(meta.headers),
66
- request_body: null,
66
+ request_body: response.requestBody !== void 0 ? JSON.stringify(response.requestBody) : null,
67
67
  status_code: response.statusCode,
68
68
  status_text: response.statusText,
69
69
  duration: response.duration,
70
70
  response_content_type: response.contentType,
71
71
  response_headers: JSON.stringify(response.headers),
72
- response_body: null,
72
+ response_body: response.responseBody !== void 0 ? JSON.stringify(response.responseBody) : null,
73
73
  created_at: /* @__PURE__ */ new Date()
74
74
  };
75
75
  insertInvocation(row);
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/router-plugin.ts"],"sourcesContent":["/**\n * RouterPlugin adapter for @agentcash/router.\n *\n * Bridges the router's plugin hooks into ClickHouse telemetry.\n * Uses the same mcp_resource_invocations table as the legacy withTelemetry wrapper.\n *\n * Usage:\n * import { createRouter } from '@agentcash/router';\n * import { createTelemetryPlugin } from '@agentcash/telemetry/plugin';\n *\n * const router = createRouter({\n * payeeAddress: '...',\n * plugin: createTelemetryPlugin({\n * clickhouse: {\n * url: process.env.TELEM_CLICKHOUSE_URL ?? 'http://localhost:8123',\n * database: process.env.TELEM_CLICKHOUSE_DATABASE,\n * username: process.env.TELEM_CLICKHOUSE_USERNAME,\n * password: process.env.TELEM_CLICKHOUSE_PASSWORD,\n * },\n * }),\n * });\n */\n\nimport { initClickhouse, pingClickhouse, insertInvocation } from './clickhouse';\nimport type { McpResourceInvocation, TelemetryConfig } from './types';\n\n// ---------------------------------------------------------------------------\n// Minimal RouterPlugin types (inlined to avoid depending on @agentcash/router\n// at runtime — the router passes these shapes, we just consume them)\n// ---------------------------------------------------------------------------\n\ninterface RequestMeta {\n requestId: string;\n method: string;\n route: string;\n origin: string;\n referer: string | null;\n walletAddress: string | null;\n clientId: string | null;\n sessionId: string | null;\n contentType: string | null;\n headers: Record<string, string>;\n startTime: number;\n}\n\ninterface PluginContext {\n readonly requestId: string;\n readonly route: string;\n readonly walletAddress: string | null;\n readonly clientId: string | null;\n readonly sessionId: string | null;\n verifiedWallet: string | null;\n setVerifiedWallet(address: string): void;\n}\n\ninterface PaymentEvent {\n protocol: 'x402' | 'mpp';\n payer: string;\n amount: string;\n network: string;\n}\n\ninterface SettlementEvent {\n protocol: 'x402' | 'mpp';\n payer: string;\n transaction: string;\n network: string;\n}\n\ninterface ResponseMeta {\n statusCode: number;\n statusText: string;\n duration: number;\n contentType: string | null;\n headers: Record<string, string>;\n}\n\ninterface ErrorEvent {\n status: number;\n message: string;\n settled: boolean;\n}\n\ninterface AlertEvent {\n level: string;\n message: string;\n route: string;\n meta?: Record<string, unknown>;\n}\n\ninterface ProviderQuotaEvent {\n provider: string;\n route: string;\n remaining: number | null;\n limit: number | null;\n level: string;\n overage: string;\n message: string;\n}\n\n/** RouterPlugin interface — must match @agentcash/router's RouterPlugin */\ninterface RouterPlugin {\n init?(config: { origin?: string }): void | Promise<void>;\n onRequest?(meta: RequestMeta): PluginContext;\n onPaymentVerified?(ctx: PluginContext, payment: PaymentEvent): void;\n onPaymentSettled?(ctx: PluginContext, settlement: SettlementEvent): void;\n onResponse?(ctx: PluginContext, response: ResponseMeta): void;\n onError?(ctx: PluginContext, error: ErrorEvent): void;\n onAlert?(ctx: PluginContext, alert: AlertEvent): void;\n onProviderQuota?(ctx: PluginContext, event: ProviderQuotaEvent): void;\n}\n\n// ---------------------------------------------------------------------------\n// Extended context — carries request metadata through the lifecycle\n// ---------------------------------------------------------------------------\n\ninterface TelemetryPluginContext extends PluginContext {\n /** Stored from onRequest for use in onResponse */\n _meta: RequestMeta;\n /** Payment info captured between verify and response */\n _payment?: PaymentEvent;\n /** Settlement info captured between settle and response */\n _settlement?: SettlementEvent;\n}\n\n// ---------------------------------------------------------------------------\n// Plugin factory\n// ---------------------------------------------------------------------------\n\nexport interface TelemetryPluginConfig {\n clickhouse: TelemetryConfig['clickhouse'];\n /** If true, pings ClickHouse on init. */\n verify?: boolean;\n /** Console logging for dev. Default: false. */\n console?: boolean;\n}\n\nexport function createTelemetryPlugin(config: TelemetryPluginConfig): RouterPlugin {\n // Initialize ClickHouse synchronously (connection happens on first query)\n initClickhouse(config.clickhouse);\n if (config.verify) {\n pingClickhouse();\n }\n\n const log = config.console ?? false;\n\n return {\n onRequest(meta: RequestMeta): PluginContext {\n const ctx: TelemetryPluginContext = {\n requestId: meta.requestId,\n route: meta.route,\n walletAddress: meta.walletAddress,\n clientId: meta.clientId,\n sessionId: meta.sessionId,\n verifiedWallet: null,\n setVerifiedWallet(address: string) {\n ctx.verifiedWallet = address;\n },\n _meta: meta,\n };\n return ctx as PluginContext;\n },\n\n onPaymentVerified(ctx: PluginContext, payment: PaymentEvent) {\n (ctx as TelemetryPluginContext)._payment = payment;\n if (log) {\n console.log(`[telemetry] VERIFIED ${payment.protocol} ${payment.payer} ${payment.amount}`);\n }\n },\n\n onPaymentSettled(ctx: PluginContext, settlement: SettlementEvent) {\n (ctx as TelemetryPluginContext)._settlement = settlement;\n if (log) {\n console.log(`[telemetry] SETTLED ${settlement.protocol} tx=${settlement.transaction}`);\n }\n },\n\n onResponse(ctx: PluginContext, response: ResponseMeta) {\n const tCtx = ctx as TelemetryPluginContext;\n const meta = tCtx._meta;\n\n if (log) {\n const wallet = ctx.verifiedWallet ? ` wallet=${ctx.verifiedWallet}` : '';\n console.log(\n `[telemetry] ${meta.route} → ${response.statusCode} (${response.duration}ms)${wallet}`,\n );\n }\n\n // 402 is the x402/MPP payment challenge — not a real invocation, skip logging\n if (response.statusCode === 402) {\n return;\n }\n\n const row: McpResourceInvocation = {\n id: meta.requestId,\n x_wallet_address: meta.walletAddress?.toLowerCase() ?? null,\n x_client_id: meta.clientId,\n session_id: meta.sessionId,\n verified_wallet_address: ctx.verifiedWallet?.toLowerCase() ?? null,\n\n method: meta.method,\n route: meta.route,\n origin: meta.origin,\n referer: meta.referer,\n request_content_type: meta.contentType,\n request_headers: JSON.stringify(meta.headers),\n request_body: null,\n\n status_code: response.statusCode,\n status_text: response.statusText,\n duration: response.duration,\n response_content_type: response.contentType,\n response_headers: JSON.stringify(response.headers),\n response_body: null,\n\n created_at: new Date(),\n };\n\n insertInvocation(row);\n },\n\n onError(ctx: PluginContext, error: ErrorEvent) {\n if (log) {\n console.error(`[telemetry] ERROR ${error.status}: ${error.message}`);\n }\n },\n\n onAlert(ctx: PluginContext, alert: AlertEvent) {\n if (log) {\n const logFn =\n alert.level === 'critical' || alert.level === 'error'\n ? console.error\n : alert.level === 'warn'\n ? console.warn\n : console.log;\n logFn(\n `[telemetry] ${alert.level.toUpperCase()} ${alert.route}: ${alert.message}`,\n alert.meta ?? '',\n );\n }\n },\n\n onProviderQuota(ctx: PluginContext, event: ProviderQuotaEvent) {\n if (log) {\n const logFn =\n event.level === 'critical'\n ? console.error\n : event.level === 'warn'\n ? console.warn\n : console.log;\n logFn(`[telemetry] QUOTA ${event.level.toUpperCase()} ${event.provider}: ${event.message}`);\n }\n },\n };\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/router-plugin.ts"],"sourcesContent":["/**\n * RouterPlugin adapter for @agentcash/router.\n *\n * Bridges the router's plugin hooks into ClickHouse telemetry.\n * Uses the same mcp_resource_invocations table as the legacy withTelemetry wrapper.\n *\n * Usage:\n * import { createRouter } from '@agentcash/router';\n * import { createTelemetryPlugin } from '@agentcash/telemetry/plugin';\n *\n * const router = createRouter({\n * payeeAddress: '...',\n * plugin: createTelemetryPlugin({\n * clickhouse: {\n * url: process.env.TELEM_CLICKHOUSE_URL ?? 'http://localhost:8123',\n * database: process.env.TELEM_CLICKHOUSE_DATABASE,\n * username: process.env.TELEM_CLICKHOUSE_USERNAME,\n * password: process.env.TELEM_CLICKHOUSE_PASSWORD,\n * },\n * }),\n * });\n */\n\nimport { initClickhouse, pingClickhouse, insertInvocation } from './clickhouse';\nimport type { McpResourceInvocation, TelemetryConfig } from './types';\n\n// ---------------------------------------------------------------------------\n// Minimal RouterPlugin types (inlined to avoid depending on @agentcash/router\n// at runtime — the router passes these shapes, we just consume them)\n// ---------------------------------------------------------------------------\n\ninterface RequestMeta {\n requestId: string;\n method: string;\n route: string;\n origin: string;\n referer: string | null;\n walletAddress: string | null;\n clientId: string | null;\n sessionId: string | null;\n contentType: string | null;\n headers: Record<string, string>;\n startTime: number;\n}\n\ninterface PluginContext {\n readonly requestId: string;\n readonly route: string;\n readonly walletAddress: string | null;\n readonly clientId: string | null;\n readonly sessionId: string | null;\n verifiedWallet: string | null;\n setVerifiedWallet(address: string): void;\n}\n\ninterface PaymentEvent {\n protocol: 'x402' | 'mpp';\n payer: string;\n amount: string;\n network: string;\n}\n\ninterface SettlementEvent {\n protocol: 'x402' | 'mpp';\n payer: string;\n transaction: string;\n network: string;\n}\n\ninterface ResponseMeta {\n statusCode: number;\n statusText: string;\n duration: number;\n contentType: string | null;\n headers: Record<string, string>;\n /** Parsed request body (when .body() was used). undefined when no body was parsed. */\n requestBody?: unknown;\n /** Handler return value. undefined for raw Response returns (streams) or error paths. */\n responseBody?: unknown;\n}\n\ninterface ErrorEvent {\n status: number;\n message: string;\n settled: boolean;\n}\n\ninterface AlertEvent {\n level: string;\n message: string;\n route: string;\n meta?: Record<string, unknown>;\n}\n\ninterface ProviderQuotaEvent {\n provider: string;\n route: string;\n remaining: number | null;\n limit: number | null;\n level: string;\n overage: string;\n message: string;\n}\n\n/** RouterPlugin interface — must match @agentcash/router's RouterPlugin */\ninterface RouterPlugin {\n init?(config: { origin?: string }): void | Promise<void>;\n onRequest?(meta: RequestMeta): PluginContext;\n onPaymentVerified?(ctx: PluginContext, payment: PaymentEvent): void;\n onPaymentSettled?(ctx: PluginContext, settlement: SettlementEvent): void;\n onResponse?(ctx: PluginContext, response: ResponseMeta): void;\n onError?(ctx: PluginContext, error: ErrorEvent): void;\n onAlert?(ctx: PluginContext, alert: AlertEvent): void;\n onProviderQuota?(ctx: PluginContext, event: ProviderQuotaEvent): void;\n}\n\n// ---------------------------------------------------------------------------\n// Extended context — carries request metadata through the lifecycle\n// ---------------------------------------------------------------------------\n\ninterface TelemetryPluginContext extends PluginContext {\n /** Stored from onRequest for use in onResponse */\n _meta: RequestMeta;\n /** Payment info captured between verify and response */\n _payment?: PaymentEvent;\n /** Settlement info captured between settle and response */\n _settlement?: SettlementEvent;\n}\n\n// ---------------------------------------------------------------------------\n// Plugin factory\n// ---------------------------------------------------------------------------\n\nexport interface TelemetryPluginConfig {\n clickhouse: TelemetryConfig['clickhouse'];\n /** If true, pings ClickHouse on init. */\n verify?: boolean;\n /** Console logging for dev. Default: false. */\n console?: boolean;\n}\n\nexport function createTelemetryPlugin(config: TelemetryPluginConfig): RouterPlugin {\n // Initialize ClickHouse synchronously (connection happens on first query)\n initClickhouse(config.clickhouse);\n if (config.verify) {\n pingClickhouse();\n }\n\n const log = config.console ?? false;\n\n return {\n onRequest(meta: RequestMeta): PluginContext {\n const ctx: TelemetryPluginContext = {\n requestId: meta.requestId,\n route: meta.route,\n walletAddress: meta.walletAddress,\n clientId: meta.clientId,\n sessionId: meta.sessionId,\n verifiedWallet: null,\n setVerifiedWallet(address: string) {\n ctx.verifiedWallet = address;\n },\n _meta: meta,\n };\n return ctx as PluginContext;\n },\n\n onPaymentVerified(ctx: PluginContext, payment: PaymentEvent) {\n (ctx as TelemetryPluginContext)._payment = payment;\n if (log) {\n console.log(`[telemetry] VERIFIED ${payment.protocol} ${payment.payer} ${payment.amount}`);\n }\n },\n\n onPaymentSettled(ctx: PluginContext, settlement: SettlementEvent) {\n (ctx as TelemetryPluginContext)._settlement = settlement;\n if (log) {\n console.log(`[telemetry] SETTLED ${settlement.protocol} tx=${settlement.transaction}`);\n }\n },\n\n onResponse(ctx: PluginContext, response: ResponseMeta) {\n const tCtx = ctx as TelemetryPluginContext;\n const meta = tCtx._meta;\n\n if (log) {\n const wallet = ctx.verifiedWallet ? ` wallet=${ctx.verifiedWallet}` : '';\n console.log(\n `[telemetry] ${meta.route} → ${response.statusCode} (${response.duration}ms)${wallet}`,\n );\n }\n\n // 402 is the x402/MPP payment challenge — not a real invocation, skip logging\n if (response.statusCode === 402) {\n return;\n }\n\n const row: McpResourceInvocation = {\n id: meta.requestId,\n x_wallet_address: meta.walletAddress?.toLowerCase() ?? null,\n x_client_id: meta.clientId,\n session_id: meta.sessionId,\n verified_wallet_address: ctx.verifiedWallet?.toLowerCase() ?? null,\n\n method: meta.method,\n route: meta.route,\n origin: meta.origin,\n referer: meta.referer,\n request_content_type: meta.contentType,\n request_headers: JSON.stringify(meta.headers),\n request_body:\n response.requestBody !== undefined ? JSON.stringify(response.requestBody) : null,\n\n status_code: response.statusCode,\n status_text: response.statusText,\n duration: response.duration,\n response_content_type: response.contentType,\n response_headers: JSON.stringify(response.headers),\n response_body:\n response.responseBody !== undefined ? JSON.stringify(response.responseBody) : null,\n\n created_at: new Date(),\n };\n\n insertInvocation(row);\n },\n\n onError(ctx: PluginContext, error: ErrorEvent) {\n if (log) {\n console.error(`[telemetry] ERROR ${error.status}: ${error.message}`);\n }\n },\n\n onAlert(ctx: PluginContext, alert: AlertEvent) {\n if (log) {\n const logFn =\n alert.level === 'critical' || alert.level === 'error'\n ? console.error\n : alert.level === 'warn'\n ? console.warn\n : console.log;\n logFn(\n `[telemetry] ${alert.level.toUpperCase()} ${alert.route}: ${alert.message}`,\n alert.meta ?? '',\n );\n }\n },\n\n onProviderQuota(ctx: PluginContext, event: ProviderQuotaEvent) {\n if (log) {\n const logFn =\n event.level === 'critical'\n ? console.error\n : event.level === 'warn'\n ? console.warn\n : console.log;\n logFn(`[telemetry] QUOTA ${event.level.toUpperCase()} ${event.provider}: ${event.message}`);\n }\n },\n };\n}\n"],"mappings":"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","names":[]}
package/dist/siwx.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } }
2
2
 
3
- var _chunkCIAESB2Cjs = require('./chunk-CIAESB2C.js');
3
+ var _chunkFOVQCGAHjs = require('./chunk-FOVQCGAH.js');
4
4
  require('./chunk-2EFPFJCB.js');
5
5
  require('./chunk-QEJ7ZGGH.js');
6
6
 
@@ -15,7 +15,7 @@ var _crypto = require('crypto');
15
15
  var _signinwithx = require('@x402/extensions/sign-in-with-x');
16
16
  var _http = require('@x402/core/http');
17
17
  function withSiwxTelemetry(handler) {
18
- return _chunkCIAESB2Cjs.withTelemetry.call(void 0, async (request, ctx) => {
18
+ return _chunkFOVQCGAHjs.withTelemetry.call(void 0, async (request, ctx) => {
19
19
  const header = _nullishCoalesce(request.headers.get("SIGN-IN-WITH-X"), () => ( request.headers.get("sign-in-with-x")));
20
20
  if (!header) {
21
21
  return buildSiwxChallengeResponse(request);
package/dist/siwx.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  withTelemetry
3
- } from "./chunk-YAHKVH4T.mjs";
3
+ } from "./chunk-OHOHTH2I.mjs";
4
4
  import "./chunk-PZWW7EMH.mjs";
5
5
  import "./chunk-V553T6WE.mjs";
6
6
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agentcash/telemetry",
3
- "version": "0.3.1",
3
+ "version": "0.3.3",
4
4
  "description": "ClickHouse telemetry plugin for @agentcash/router. Logs request lifecycle, payments, settlements, and provider quota to ClickHouse.",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",
@@ -1 +0,0 @@
1
- {"version":3,"sources":["/home/runner/work/agentcash-telemetry/agentcash-telemetry/dist/chunk-CIAESB2C.js","../src/telemetry.ts"],"names":[],"mappings":"AAAA;AACE;AACA;AACA;AACF,sDAA4B;AAC5B;AACA;ACAA,qCAA+C;AAcxC,SAAS,aAAA,CAAc,OAAA,EAA2B;AACvD,EAAA,OAAO,MAAA,CAAO,OAAA,EAAA,GAAgD;AAC5D,IAAA,MAAM,KAAA,EAAO,iDAAA,OAA0B,CAAA;AACvC,IAAA,MAAM,IAAA,EAAM,oDAAA,IAA0B,CAAA;AAGtC,IAAA,IAAI,kBAAA,EAAmC,IAAA;AACvC,IAAA,GAAA,CAAI,IAAA,CAAK,OAAA,IAAW,OAAA,GAAU,IAAA,CAAK,OAAA,IAAW,MAAA,GAAS,IAAA,CAAK,OAAA,IAAW,OAAA,EAAS;AAC9E,MAAA,IAAI;AACF,QAAA,MAAM,KAAA,EAAO,MAAM,OAAA,CAAQ,KAAA,CAAM,CAAA,CAAE,IAAA,CAAK,CAAA;AACxC,QAAA,GAAA,CAAI,IAAA,EAAM,kBAAA,EAAoB,IAAA;AAAA,MAChC,EAAA,UAAQ;AAAA,MAER;AAAA,IACF;AAGA,IAAA,IAAI,QAAA;AACJ,IAAA,IAAI,aAAA,EAAwB,IAAA;AAE5B,IAAA,IAAI;AACF,MAAA,SAAA,EAAW,MAAM,OAAA,CAAQ,OAAA,EAAS,GAAG,CAAA;AAAA,IACvC,EAAA,MAAA,CAAS,KAAA,EAAgB;AACvB,MAAA,aAAA,EAAe,KAAA;AACf,MAAA,GAAA,CAAI,MAAA,WAAiB,oBAAA,EAAc;AACjC,QAAA,SAAA,EAAW,KAAA;AAAA,MACb,EAAA,KAAO;AACL,QAAA,MAAM,QAAA,EAAU,MAAA,WAAiB,MAAA,EAAQ,KAAA,CAAM,QAAA,EAAU,uBAAA;AACzD,QAAA,SAAA,EAAW,oBAAA,CAAa,IAAA,CAAK,EAAE,OAAA,EAAS,KAAA,EAAO,KAAA,EAAO,QAAQ,CAAA,EAAG,EAAE,MAAA,EAAQ,IAAI,CAAC,CAAA;AAAA,MAClF;AAAA,IACF;AAGA,IAAA,IAAI,mBAAA,EAAoC,IAAA;AACxC,IAAA,IAAI;AACF,MAAA,mBAAA,EAAqB,MAAM,QAAA,CAAS,KAAA,CAAM,CAAA,CAAE,IAAA,CAAK,CAAA;AAAA,IACnD,EAAA,WAAQ;AAAA,IAER;AAGA,IAAA,GAAA,CAAI,QAAA,CAAS,OAAA,IAAW,GAAA,EAAK;AAC3B,MAAA,+CAAA,IAAiB,EAAM,iBAAA,EAAmB;AAAA,QACxC,MAAA,EAAQ,QAAA,CAAS,MAAA;AAAA,QACjB,IAAA,EAAM,kBAAA;AAAA,QACN,OAAA,EAAS,IAAA,CAAK,SAAA,CAAU,MAAA,CAAO,WAAA,CAAY,QAAA,CAAS,OAAA,CAAQ,OAAA,CAAQ,CAAC,CAAC,CAAA;AAAA,QACtE,WAAA,mBAAa,QAAA,CAAS,OAAA,CAAQ,GAAA,CAAI,cAAc,CAAA,UAAK;AAAA,MACvD,CAAC,CAAA;AAAA,IACH;AAGA,IAAA,GAAA,CAAI,aAAA,GAAgB,CAAA,CAAE,aAAA,WAAwB,oBAAA,CAAA,EAAe;AAC3D,MAAA,MAAM,YAAA;AAAA,IACR;AAEA,IAAA,OAAO,QAAA;AAAA,EACT,CAAA;AACF;ADzBA;AACA;AACE;AACF,sCAAC","file":"/home/runner/work/agentcash-telemetry/agentcash-telemetry/dist/chunk-CIAESB2C.js","sourcesContent":[null,"/**\n * Core telemetry wrapper for Next.js route handlers.\n * Extracts identity headers, logs to ClickHouse, extracts verified wallet.\n * This is a passive observer — it never influences the response.\n */\n\nimport { type NextRequest, NextResponse } from 'next/server';\nimport type { TelemetryContext } from './types';\nimport { extractRequestMeta, buildTelemetryContext, recordInvocation } from './telemetry-core';\n\ntype TelemetryHandler = (request: NextRequest, ctx: TelemetryContext) => Promise<NextResponse>;\n\n/**\n * Wrap a Next.js route handler with telemetry.\n * Extracts identity headers, logs the invocation to ClickHouse,\n * and auto-extracts verified wallet from x402 payment headers.\n *\n * The entire telemetry code path is wrapped in try/catch.\n * Telemetry failures never affect the response.\n */\nexport function withTelemetry(handler: TelemetryHandler) {\n return async (request: NextRequest): Promise<NextResponse> => {\n const meta = extractRequestMeta(request);\n const ctx = buildTelemetryContext(meta);\n\n // Capture request body for logging (only for methods with bodies)\n let requestBodyString: string | null = null;\n if (meta.method === 'POST' || meta.method === 'PUT' || meta.method === 'PATCH') {\n try {\n const body = await request.clone().text();\n if (body) requestBodyString = body;\n } catch {\n // Body read failed — that's fine\n }\n }\n\n // Execute the actual handler\n let response: NextResponse;\n let handlerError: unknown = null;\n\n try {\n response = await handler(request, ctx);\n } catch (error: unknown) {\n handlerError = error;\n if (error instanceof NextResponse) {\n response = error;\n } else {\n const message = error instanceof Error ? error.message : 'Internal server error';\n response = NextResponse.json({ success: false, error: message }, { status: 500 });\n }\n }\n\n // Log to ClickHouse (fire-and-forget)\n let responseBodyString: string | null = null;\n try {\n responseBodyString = await response.clone().text();\n } catch {\n // Response body read failed — that's fine\n }\n\n // 402 is the x402/MPP payment challenge — not a real invocation, skip logging\n if (response.status !== 402) {\n recordInvocation(meta, requestBodyString, {\n status: response.status,\n body: responseBodyString,\n headers: JSON.stringify(Object.fromEntries(response.headers.entries())),\n contentType: response.headers.get('content-type') ?? null,\n });\n }\n\n // Re-throw the original error if it wasn't a NextResponse\n if (handlerError && !(handlerError instanceof NextResponse)) {\n throw handlerError;\n }\n\n return response;\n };\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/telemetry.ts"],"sourcesContent":["/**\n * Core telemetry wrapper for Next.js route handlers.\n * Extracts identity headers, logs to ClickHouse, extracts verified wallet.\n * This is a passive observer — it never influences the response.\n */\n\nimport { type NextRequest, NextResponse } from 'next/server';\nimport type { TelemetryContext } from './types';\nimport { extractRequestMeta, buildTelemetryContext, recordInvocation } from './telemetry-core';\n\ntype TelemetryHandler = (request: NextRequest, ctx: TelemetryContext) => Promise<NextResponse>;\n\n/**\n * Wrap a Next.js route handler with telemetry.\n * Extracts identity headers, logs the invocation to ClickHouse,\n * and auto-extracts verified wallet from x402 payment headers.\n *\n * The entire telemetry code path is wrapped in try/catch.\n * Telemetry failures never affect the response.\n */\nexport function withTelemetry(handler: TelemetryHandler) {\n return async (request: NextRequest): Promise<NextResponse> => {\n const meta = extractRequestMeta(request);\n const ctx = buildTelemetryContext(meta);\n\n // Capture request body for logging (only for methods with bodies)\n let requestBodyString: string | null = null;\n if (meta.method === 'POST' || meta.method === 'PUT' || meta.method === 'PATCH') {\n try {\n const body = await request.clone().text();\n if (body) requestBodyString = body;\n } catch {\n // Body read failed — that's fine\n }\n }\n\n // Execute the actual handler\n let response: NextResponse;\n let handlerError: unknown = null;\n\n try {\n response = await handler(request, ctx);\n } catch (error: unknown) {\n handlerError = error;\n if (error instanceof NextResponse) {\n response = error;\n } else {\n const message = error instanceof Error ? error.message : 'Internal server error';\n response = NextResponse.json({ success: false, error: message }, { status: 500 });\n }\n }\n\n // Log to ClickHouse (fire-and-forget)\n let responseBodyString: string | null = null;\n try {\n responseBodyString = await response.clone().text();\n } catch {\n // Response body read failed — that's fine\n }\n\n // 402 is the x402/MPP payment challenge — not a real invocation, skip logging\n if (response.status !== 402) {\n recordInvocation(meta, requestBodyString, {\n status: response.status,\n body: responseBodyString,\n headers: JSON.stringify(Object.fromEntries(response.headers.entries())),\n contentType: response.headers.get('content-type') ?? null,\n });\n }\n\n // Re-throw the original error if it wasn't a NextResponse\n if (handlerError && !(handlerError instanceof NextResponse)) {\n throw handlerError;\n }\n\n return response;\n };\n}\n"],"mappings":";;;;;;;AAMA,SAA2B,oBAAoB;AAcxC,SAAS,cAAc,SAA2B;AACvD,SAAO,OAAO,YAAgD;AAC5D,UAAM,OAAO,mBAAmB,OAAO;AACvC,UAAM,MAAM,sBAAsB,IAAI;AAGtC,QAAI,oBAAmC;AACvC,QAAI,KAAK,WAAW,UAAU,KAAK,WAAW,SAAS,KAAK,WAAW,SAAS;AAC9E,UAAI;AACF,cAAM,OAAO,MAAM,QAAQ,MAAM,EAAE,KAAK;AACxC,YAAI,KAAM,qBAAoB;AAAA,MAChC,QAAQ;AAAA,MAER;AAAA,IACF;AAGA,QAAI;AACJ,QAAI,eAAwB;AAE5B,QAAI;AACF,iBAAW,MAAM,QAAQ,SAAS,GAAG;AAAA,IACvC,SAAS,OAAgB;AACvB,qBAAe;AACf,UAAI,iBAAiB,cAAc;AACjC,mBAAW;AAAA,MACb,OAAO;AACL,cAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU;AACzD,mBAAW,aAAa,KAAK,EAAE,SAAS,OAAO,OAAO,QAAQ,GAAG,EAAE,QAAQ,IAAI,CAAC;AAAA,MAClF;AAAA,IACF;AAGA,QAAI,qBAAoC;AACxC,QAAI;AACF,2BAAqB,MAAM,SAAS,MAAM,EAAE,KAAK;AAAA,IACnD,QAAQ;AAAA,IAER;AAGA,QAAI,SAAS,WAAW,KAAK;AAC3B,uBAAiB,MAAM,mBAAmB;AAAA,QACxC,QAAQ,SAAS;AAAA,QACjB,MAAM;AAAA,QACN,SAAS,KAAK,UAAU,OAAO,YAAY,SAAS,QAAQ,QAAQ,CAAC,CAAC;AAAA,QACtE,aAAa,SAAS,QAAQ,IAAI,cAAc,KAAK;AAAA,MACvD,CAAC;AAAA,IACH;AAGA,QAAI,gBAAgB,EAAE,wBAAwB,eAAe;AAC3D,YAAM;AAAA,IACR;AAEA,WAAO;AAAA,EACT;AACF;","names":[]}