1import { errorTag } from "@t3tools/shared/observability";
2
3export function structuralProtocolMethod(value: string): string {
4 return value.length <= 128 && /^[A-Za-z][A-Za-z0-9._:/-]*$/.test(value) ? value : "unknown";
5}
6
7/**
8 * Retain only bounded structural metadata for native protocol diagnostics.
9 * Provider payload values may contain prompts, credentials, or arbitrarily
10 * large tool output and must never be copied into the observability stream.
11 */
12export function summarizeNativeProtocolPayload(
13 payload: unknown,
14): Readonly<Record<string, unknown>> {
15 if (payload === null) return { valueType: "null" };
16 if (typeof payload === "string") {
17 return { valueType: "string", byteLength: new TextEncoder().encode(payload).byteLength };
18 }
19 if (payload instanceof Uint8Array) {
20 return { valueType: "bytes", byteLength: payload.byteLength };
21 }
22 if (Array.isArray(payload)) {
23 return { valueType: "array", itemCount: payload.length };
24 }
25 if (typeof payload !== "object") {
26 return { valueType: typeof payload };
27 }
28
29 try {
30 const record = payload as Record<string, unknown>;
31 return {
32 valueType: "object",
33 fieldCount: Object.keys(record).length,
34 ...(typeof record._tag === "string" ? { messageTag: errorTag(record) } : {}),
35 ...(typeof record.tag === "string" ? { method: structuralProtocolMethod(record.tag) } : {}),
36 };
37 } catch {
38 return { valueType: "object" };
39 }
40}