| 1 | import { errorTag } from "@t3tools/shared/observability"; |
| 2 | |
| 3 | export 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 | */ |
| 12 | export 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 | } |