neatlogs 1.1.19 → 1.1.21
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.
- package/README.md +34 -2
- package/dist/ai-sdk.cjs +186 -11
- package/dist/ai-sdk.cjs.map +1 -1
- package/dist/ai-sdk.d.ts +17 -7
- package/dist/ai-sdk.mjs +189 -12
- package/dist/ai-sdk.mjs.map +1 -1
- package/dist/anthropic.cjs +31 -14
- package/dist/anthropic.cjs.map +1 -1
- package/dist/anthropic.mjs +31 -14
- package/dist/anthropic.mjs.map +1 -1
- package/dist/azure-openai.cjs +31 -14
- package/dist/azure-openai.cjs.map +1 -1
- package/dist/azure-openai.mjs +31 -14
- package/dist/azure-openai.mjs.map +1 -1
- package/dist/bedrock.cjs +31 -14
- package/dist/bedrock.cjs.map +1 -1
- package/dist/bedrock.mjs +31 -14
- package/dist/bedrock.mjs.map +1 -1
- package/dist/browser.cjs +26 -1
- package/dist/browser.cjs.map +1 -1
- package/dist/browser.d.ts +1 -1
- package/dist/browser.mjs +26 -1
- package/dist/browser.mjs.map +1 -1
- package/dist/claude-agent-sdk.cjs +2 -2
- package/dist/claude-agent-sdk.cjs.map +1 -1
- package/dist/claude-agent-sdk.mjs +2 -2
- package/dist/claude-agent-sdk.mjs.map +1 -1
- package/dist/cli.cjs +452 -200
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.mjs +427 -173
- package/dist/cli.mjs.map +1 -1
- package/dist/google-genai.cjs +31 -14
- package/dist/google-genai.cjs.map +1 -1
- package/dist/google-genai.mjs +31 -14
- package/dist/google-genai.mjs.map +1 -1
- package/dist/index.cjs +652 -333
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +15 -6
- package/dist/index.mjs +505 -184
- package/dist/index.mjs.map +1 -1
- package/dist/langchain.cjs +3 -3
- package/dist/langchain.cjs.map +1 -1
- package/dist/langchain.mjs +3 -3
- package/dist/langchain.mjs.map +1 -1
- package/dist/mastra-wrap.cjs +2 -2
- package/dist/mastra-wrap.cjs.map +1 -1
- package/dist/mastra-wrap.mjs +2 -2
- package/dist/mastra-wrap.mjs.map +1 -1
- package/dist/openai-agents.cjs.map +1 -1
- package/dist/openai-agents.mjs.map +1 -1
- package/dist/openai.cjs +31 -14
- package/dist/openai.cjs.map +1 -1
- package/dist/openai.mjs +31 -14
- package/dist/openai.mjs.map +1 -1
- package/dist/opencode-plugin.cjs +1 -1
- package/dist/opencode-plugin.cjs.map +1 -1
- package/dist/opencode-plugin.mjs +1 -1
- package/dist/opencode-plugin.mjs.map +1 -1
- package/dist/openrouter-agent.cjs +31 -14
- package/dist/openrouter-agent.cjs.map +1 -1
- package/dist/openrouter-agent.mjs +31 -14
- package/dist/openrouter-agent.mjs.map +1 -1
- package/dist/pi-agent.cjs.map +1 -1
- package/dist/pi-agent.mjs.map +1 -1
- package/dist/vertex-ai.cjs +31 -14
- package/dist/vertex-ai.cjs.map +1 -1
- package/dist/vertex-ai.mjs +31 -14
- package/dist/vertex-ai.mjs.map +1 -1
- package/package.json +1 -1
package/dist/pi-agent.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/pi-agent.ts","../src/core/provider.ts","../src/core/active-client.ts"],"sourcesContent":["/**\n * Neatlogs Pi Agent integration.\n *\n * Usage:\n * import { init } from 'neatlogs';\n * import { piAgentHooks } from 'neatlogs/pi-agent';\n * import { Agent } from '@earendil-works/pi-agent-core';\n *\n * await init({ apiKey, workflowName });\n * const agent = piAgentHooks(new Agent({ initialState: { systemPrompt, model } }));\n * await agent.prompt('Hello');\n *\n * Pi Agent's `Agent` and `AgentHarness` expose a first-class\n * `subscribe(listener)` API and emit\n * AgentEvents for its run lifecycle (message_*, tool_execution_*, turn_*,\n * agent_*). It does NOT emit its own OpenTelemetry spans — so we LISTEN to those\n * events (no monkey-patching) and translate them into neatlogs OTel spans:\n *\n * AGENT agent run (agent_start → agent_end)\n * ↳ CHAIN turn (turn_start → turn_end)\n * ↳ LLM assistant message (message_start → message_end)\n * ↳ TOOL tool call (tool_execution_start → tool_execution_end)\n *\n * The AGENT span is opened as the active span so the turn/LLM/TOOL children nest\n * under it (and under any user @span / trace() block active when prompt() is\n * called).\n *\n * The LLM span spans the REAL model call: it opens on the assistant\n * `message_start` and closes on `message_end`, so its duration is the provider\n * latency (opening it at message_end only would report ~0ms). Streaming is the\n * default in Pi, so we also record time-to-first-token from the first content\n * delta and carry pi-ai's exact per-call `usage.cost` through instead of letting\n * the backend re-derive it from tokens.\n *\n * For the low-level functional API (`agentLoop`/`agentLoopContinue`/\n * `runAgentLoop`, which have no `subscribe()`), use `tracePiAgentEvents()` to\n * wrap the event sink / iterate the event stream. One layer below that — a bare\n * `streamFn` such as `streamProxy` called outside any loop — use\n * `tracePiStream()`. Both are documented below.\n */\n\nimport {\n trace,\n SpanStatusCode,\n type Span,\n type Context,\n} from '@opentelemetry/api';\nimport { getNeatlogsTracer, getNeatlogsParentContext } from './core/provider.js';\n\nconst TRACER_NAME = 'neatlogs.pi-agent';\nconst PATCH_FLAG = '_neatlogs_patched';\nconst HARNESS_METHOD_FLAG = '_neatlogs_harness_methods_patched';\n\n// Minimal structural types for the Pi Agent event surface (we duck-type — no\n// hard dependency on the pi-agent-core package).\ninterface PiUsage {\n input?: number;\n output?: number;\n cacheRead?: number;\n cacheWrite?: number;\n totalTokens?: number;\n /** pi-ai computes exact per-call cost — carry it through rather than re-deriving. */\n cost?: {\n input?: number;\n output?: number;\n cacheRead?: number;\n cacheWrite?: number;\n total?: number;\n };\n}\ninterface PiToolCall {\n type: 'toolCall';\n id?: string;\n name?: string;\n arguments?: Record<string, unknown>;\n}\ninterface PiAssistantMessage {\n role: 'assistant';\n content?: Array<{ type: string; text?: string; name?: string; arguments?: unknown }>;\n model?: string;\n responseModel?: string;\n provider?: string;\n api?: string;\n usage?: PiUsage;\n stopReason?: string;\n errorMessage?: string;\n /** Epoch ms, stamped by pi when it begins the model-call step. */\n timestamp?: number;\n}\ninterface PiAgentEvent {\n type: string;\n message?: any;\n messages?: any[];\n toolResults?: any[];\n assistantMessageEvent?: { type?: string };\n toolCallId?: string;\n toolName?: string;\n args?: unknown;\n result?: unknown;\n partialResult?: unknown;\n isError?: boolean;\n}\n\n/** An in-flight assistant (LLM) span: opened at message_start, closed at message_end. */\ninterface LlmInFlight {\n span: Span;\n startHr: number;\n /** Epoch ms the span was backdated to (pi's own call-start), when usable. */\n callStartEpochMs?: number;\n /** ms from span start to the first content delta (TTFT). */\n ttftMs?: number;\n /** Input snapshot taken at message_start, before the response mutates state. */\n inputMessages: Array<{ role: string; content: string }>;\n}\n\ninterface PerAgentState {\n agentSpan?: Span;\n agentCtx?: Context;\n /** Current turn (CHAIN) span — turn_start → turn_end. */\n turnSpan?: Span;\n turnCtx?: Context;\n turnIndex: number;\n /** Whether the current turn span already got its input stamped. */\n turnHasInput?: boolean;\n /** When the turn span was opened — a child LLM span may not start before it. */\n turnStartEpochMs?: number;\n /** The assistant LLM span currently streaming, if any. */\n llm?: LlmInFlight;\n toolSpans: Map<string, Span>;\n /** Running conversation (system/user/tool turns) to use as LLM-span input.\n * Pi Agent's assistant message_end carries only the response, not the prompt. */\n inputMessages: Array<{ role: string; content: string }>;\n /** First user message of the CURRENT run, for the AGENT span's input. */\n runInput?: string;\n /** Set when the run ends abnormally (aborted / provider error). */\n runError?: { stopReason: string; message?: string };\n}\n\n/**\n * Subscribe neatlogs tracing to a Pi Agent instance. Returns the same agent\n * (marked so re-subscribing is a no-op). Idempotent per agent.\n */\nexport function piAgentHooks<T extends object>(agent: T): T {\n if (!agent || (agent as any)[PATCH_FLAG]) return agent;\n const a = agent as any;\n if (typeof a.subscribe !== 'function') return agent; // not a Pi Agent — leave alone\n\n const listener = tracePiAgentEvents(() => a.state?.messages);\n a.subscribe((event: PiAgentEvent) => listener(event));\n\n // The maintained Pi package's AgentHarness has two model-producing operations\n // outside the normal AgentEvent loop. Trace those calls explicitly; ordinary\n // prompt/skill/template turns still flow through the subscriber above.\n wrapHarnessModelOperations(a);\n\n markPatched(a);\n return agent;\n}\n\n/**\n * AgentHarness sends ordinary prompts through the same AgentEvent surface as\n * Agent, but `compact()` and summarizing `navigateTree()` call the model outside\n * that loop. Wrap those two public methods so their provider work is visible too.\n */\nfunction wrapHarnessModelOperations(harness: any): void {\n if (harness[HARNESS_METHOD_FLAG]) return;\n const isHarness =\n typeof harness.compact === 'function' &&\n typeof harness.navigateTree === 'function' &&\n typeof harness.getModel === 'function';\n if (!isHarness) return;\n\n patchHarnessMethod(harness, 'compact', (args) => ({ customInstructions: args[0] }));\n patchHarnessMethod(harness, 'navigateTree', (args) => ({ targetId: args[0], options: args[1] }));\n try {\n Object.defineProperty(harness, HARNESS_METHOD_FLAG, { value: true });\n } catch {\n harness[HARNESS_METHOD_FLAG] = true;\n }\n}\n\nfunction patchHarnessMethod(\n harness: any,\n method: 'compact' | 'navigateTree',\n inputOf: (args: any[]) => unknown,\n): void {\n const original = harness[method].bind(harness);\n harness[method] = async (...args: any[]) => {\n const startedAt = Date.now();\n const parent = getNeatlogsParentContext();\n const input = inputOf(args);\n let observedModelCall: boolean | undefined;\n let stopObserving: (() => void) | undefined;\n try {\n stopObserving = harness.subscribe((event: any) => {\n if (method === 'compact' && event?.type === 'session_compact') {\n observedModelCall = !event.fromHook;\n } else if (method === 'navigateTree' && event?.type === 'session_tree') {\n observedModelCall = Boolean(event.summaryEntry) && !event.fromHook;\n }\n });\n } catch {\n // Older compatible harnesses may not allow another listener here.\n }\n let result: any;\n let failure: unknown;\n try {\n result = await original(...args);\n return result;\n } catch (err) {\n failure = err;\n throw err;\n } finally {\n stopObserving?.();\n try {\n emitHarnessOperation(\n method,\n input,\n result,\n failure,\n harness.getModel?.(),\n parent,\n startedAt,\n Date.now(),\n observedModelCall,\n );\n } catch {\n // Observability must not change harness behavior.\n }\n }\n };\n}\n\nfunction emitHarnessOperation(\n method: 'compact' | 'navigateTree',\n input: unknown,\n result: any,\n failure: unknown,\n model: any,\n capturedParent: Context,\n startedAt: number,\n endedAt: number,\n observedModelCall?: boolean,\n): void {\n const tracer = getNeatlogsTracer(TRACER_NAME);\n let parent = capturedParent;\n let root: Span | undefined;\n const inputText = safeStringify(input ?? {});\n const outputText = failure\n ? `[error] ${failure instanceof Error ? failure.message : String(failure)}`\n : harnessOperationOutput(method, result);\n\n if (!trace.getSpan(parent)?.isRecording()) {\n root = tracer.startSpan(\n `pi_agent.harness.${method}`,\n {\n startTime: startedAt,\n attributes: {\n 'neatlogs.span.kind': 'WORKFLOW',\n 'input.value': inputText,\n },\n },\n parent,\n );\n parent = trace.setSpan(parent, root);\n }\n\n const chain = tracer.startSpan(\n `pi_agent.harness.${method}`,\n {\n startTime: startedAt,\n attributes: {\n 'neatlogs.span.kind': 'CHAIN',\n 'neatlogs.pi.operation': method,\n 'input.value': inputText,\n },\n },\n parent,\n );\n const chainCtx = trace.setSpan(parent, chain);\n\n const usage = harnessOperationUsage(method, result);\n const madeModelCall =\n observedModelCall ??\n (failure\n ? isHarnessSummarizationFailure(failure)\n : method === 'compact'\n ? Boolean(result?.usage)\n : Boolean(result?.summaryEntry) && result.summaryEntry.fromHook !== true);\n if (madeModelCall || failure) {\n const llm = openLlmSpan(\n tracer,\n {\n toolSpans: new Map(),\n inputMessages: [{ role: 'user', content: inputText }],\n turnIndex: 0,\n turnCtx: chainCtx,\n turnStartEpochMs: startedAt,\n },\n {\n role: 'assistant',\n model: model?.id ?? model?.model,\n provider: model?.provider,\n timestamp: startedAt,\n },\n );\n if (failure) {\n closeLlmFailure(llm, failure, endedAt);\n } else {\n finishLlmSpan(\n llm,\n {\n role: 'assistant',\n model: model?.id ?? model?.model,\n provider: model?.provider,\n content: outputText ? [{ type: 'text', text: outputText }] : [],\n usage,\n stopReason: 'stop',\n },\n endedAt,\n );\n }\n }\n\n if (outputText) chain.setAttribute('output.value', outputText);\n if (failure) {\n const message = failure instanceof Error ? failure.message : String(failure);\n chain.setAttribute('neatlogs.error.message', message);\n chain.setStatus({ code: SpanStatusCode.ERROR, message });\n } else {\n chain.setStatus({ code: SpanStatusCode.OK });\n }\n chain.end(endedAt);\n\n if (root) {\n if (outputText) root.setAttribute('output.value', outputText);\n if (failure) {\n const message = failure instanceof Error ? failure.message : String(failure);\n root.setAttribute('neatlogs.error.message', message);\n root.setStatus({ code: SpanStatusCode.ERROR, message });\n } else {\n root.setStatus({ code: SpanStatusCode.OK });\n }\n root.end(endedAt);\n }\n}\n\nfunction isHarnessSummarizationFailure(failure: unknown): boolean {\n let current: any = failure;\n const seen = new Set<unknown>();\n while (current && !seen.has(current)) {\n seen.add(current);\n if (current.code === 'summarization_failed') return true;\n current = current.cause;\n }\n return false;\n}\n\nfunction harnessOperationOutput(method: 'compact' | 'navigateTree', result: any): string {\n if (method === 'compact') return typeof result?.summary === 'string' ? result.summary : safeStringify(result ?? {});\n const summary = result?.summaryEntry?.summary;\n return typeof summary === 'string' ? summary : safeStringify(result ?? {});\n}\n\nfunction harnessOperationUsage(method: 'compact' | 'navigateTree', result: any): PiUsage | undefined {\n return method === 'compact' ? result?.usage : result?.summaryEntry?.usage;\n}\n\nfunction closeLlmFailure(llm: LlmInFlight, failure: unknown, endedAt?: number): void {\n const message = failure instanceof Error ? failure.message : String(failure);\n llm.span.setAttribute('output.value', `[error] ${message}`);\n llm.span.setAttribute('neatlogs.error.message', message);\n llm.span.setStatus({ code: SpanStatusCode.ERROR, message });\n llm.span.end(endedAt);\n}\n\n/**\n * Build a standalone Pi AgentEvent listener that emits neatlogs spans.\n *\n * `piAgentHooks()` uses this internally. Reach for it directly when you drive\n * Pi's LOW-LEVEL functional API, which has no `subscribe()` to hook:\n *\n * // runAgentLoop takes an event sink — hand it the tracing listener.\n * const trace = tracePiAgentEvents(() => context.messages);\n * await runAgentLoop(prompts, context, config, async (event) => {\n * trace(event);\n * await myOwnSink?.(event);\n * });\n *\n * // agentLoop / agentLoopContinue return an EventStream — iterate it.\n * const stream = agentLoop(prompts, context, config);\n * const trace = tracePiAgentEvents(() => context.messages);\n * for await (const event of stream) trace(event);\n * const messages = await stream.result();\n *\n * @param getTranscript Optional accessor for the live transcript. Used to\n * recover the run's input when `continue()` (or a continuation loop) starts\n * from a transcript that already holds the user turn, so no new user message\n * is emitted during the run.\n */\nexport function tracePiAgentEvents(\n getTranscript?: () => any[] | undefined,\n): (event: unknown) => void {\n const state: PerAgentState = { toolSpans: new Map(), inputMessages: [], turnIndex: 0 };\n return (event: unknown) => {\n try {\n const tracer = getNeatlogsTracer(TRACER_NAME);\n handleEvent(tracer, state, event as PiAgentEvent, getTranscript);\n } catch {\n // never let tracing break the agent run\n }\n };\n}\n\n/**\n * Wrap a Pi `StreamFn` so every model call it makes gets an LLM span.\n *\n * The event surface above covers the agent loop, but a raw stream function is\n * one layer below it — reach for this when you call pi-ai directly, or when your\n * `streamFn` is NOT the one the loop wraps in agent events, e.g. `streamProxy`\n * used standalone:\n *\n * import { streamProxy } from '@earendil-works/pi-agent-core';\n * const stream = tracePiStream(streamProxy);\n * const result = await stream(model, context, { authToken, proxyUrl }).result();\n *\n * Do not pass it as an `Agent`'s `streamFn`: the loop already emits message\n * events for the same call, so that would double-count. Prefer\n * `piAgentHooks()` there and keep this for the standalone path.\n *\n * Called with no enclosing `span()`/`trace()`, the LLM span would be the trace\n * root — which the backend does not accept as one — so a WORKFLOW root is opened\n * around it. Inside an existing trace no extra root is added.\n */\nexport function tracePiStream<\n F extends (model: any, context: any, options?: any) => any,\n>(streamFn: F): F {\n return ((model: any, context: any, options?: any) => {\n const tracer = getNeatlogsTracer(TRACER_NAME);\n let llm: LlmInFlight | undefined;\n let root: Span | undefined;\n try {\n const state: PerAgentState = { toolSpans: new Map(), inputMessages: [], turnIndex: 0 };\n state.inputMessages = promptMessagesOf(context);\n\n let parent = getNeatlogsParentContext();\n if (!trace.getSpan(parent)?.isRecording()) {\n root = tracer.startSpan(\n 'pi_agent.stream',\n { attributes: { 'neatlogs.span.kind': 'WORKFLOW' } },\n parent,\n );\n parent = trace.setSpan(parent, root);\n const rootInput = state.inputMessages.length\n ? safeStringify({ messages: state.inputMessages })\n : undefined;\n if (rootInput) root.setAttribute('input.value', rootInput);\n }\n state.turnCtx = parent;\n\n llm = openLlmSpan(tracer, state, {\n role: 'assistant',\n model: model?.id ?? model?.model,\n provider: model?.provider,\n });\n } catch {\n /* tracing must never block the call */\n }\n\n let returned: any;\n try {\n returned = streamFn(model, context, options);\n } catch (err) {\n closeStreamFailure(llm, root, err);\n throw err;\n }\n\n // StreamFn explicitly permits EventStream | Promise<EventStream>. Preserve\n // that exact return shape while attaching tracing after an async stream\n // factory resolves. A rejected factory is outside Pi's recommended contract,\n // but still closes both spans rather than leaking them.\n if (isThenable(returned)) {\n return returned.then(\n (stream: any) => attachStreamResult(stream, llm, root),\n (err: unknown) => {\n closeStreamFailure(llm, root, err);\n throw err;\n },\n );\n }\n return attachStreamResult(returned, llm, root);\n }) as F;\n}\n\nfunction attachStreamResult(\n stream: any,\n llm: LlmInFlight | undefined,\n root: Span | undefined,\n): any {\n if (!llm || !stream || typeof stream.result !== 'function') {\n closeStreamRoot(root);\n return stream;\n }\n\n observeStreamDeltas(stream, llm);\n stream.result().then(\n (msg: any) => {\n const message = msg ?? { role: 'assistant' };\n finishLlmSpan(llm, message);\n closeStreamRoot(root, message);\n },\n (err: unknown) => closeStreamFailure(llm, root, err),\n );\n return stream;\n}\n\n/** Observe caller-consumed chunks without consuming or buffering the stream ourselves. */\nfunction observeStreamDeltas(stream: any, llm: LlmInFlight): void {\n const original = stream?.[Symbol.asyncIterator];\n if (typeof original !== 'function' || original.__neatlogsObserved) return;\n const observed = function (this: any): AsyncIterator<any> {\n const iterator = original.call(this) as AsyncIterator<any>;\n return {\n next: async (...args: [] | [undefined]) => {\n const item = await iterator.next(...(args as []));\n if (!item.done && isContentDelta(item.value?.type)) markFirstStreamDelta(llm);\n return item;\n },\n return: iterator.return?.bind(iterator),\n throw: iterator.throw?.bind(iterator),\n };\n };\n Object.defineProperty(observed, '__neatlogsObserved', { value: true });\n try {\n stream[Symbol.asyncIterator] = observed;\n } catch {\n // A frozen stream still gets result-based tracing; only TTFT is unavailable.\n }\n}\n\nfunction markFirstStreamDelta(llm: LlmInFlight): void {\n llm.span.setAttribute('neatlogs.llm.is_streaming', true);\n if (llm.ttftMs !== undefined) return;\n llm.ttftMs =\n llm.callStartEpochMs !== undefined\n ? Date.now() - llm.callStartEpochMs\n : nowMs() - llm.startHr;\n}\n\nfunction closeStreamFailure(\n llm: LlmInFlight | undefined,\n root: Span | undefined,\n err: unknown,\n): void {\n const message = err instanceof Error ? err.message : String(err);\n try {\n llm?.span.setAttribute('output.value', `[error] ${message}`);\n llm?.span.setAttribute('neatlogs.error.message', message);\n llm?.span.setStatus({ code: SpanStatusCode.ERROR, message });\n llm?.span.end();\n } catch {\n /* ignore */\n }\n closeStreamRoot(root, undefined, message);\n}\n\nfunction isThenable(value: any): value is PromiseLike<any> {\n return value != null && typeof value.then === 'function';\n}\n\n/** Close the synthetic WORKFLOW root `tracePiStream` opens when it has no parent. */\nfunction closeStreamRoot(root: Span | undefined, msg?: PiAssistantMessage, error?: string): void {\n if (!root) return;\n try {\n if (msg) {\n const { text, toolCalls } = splitAssistantContent(msg.content);\n const out =\n text ||\n toolCalls.map((tc) => `${tc.name}(${safeStringify(tc.arguments)})`).join('\\n') ||\n terminalSummary(msg);\n if (out) root.setAttribute('output.value', out);\n applyStopReasonStatus(root, msg);\n } else if (error) {\n root.setAttribute('output.value', `[error] ${error}`);\n root.setAttribute('neatlogs.error.message', error);\n root.setStatus({ code: SpanStatusCode.ERROR, message: error });\n }\n root.end();\n } catch {\n /* ignore */\n }\n}\n\n/** Flatten a live transcript into prompt-context rows for LLM-span input. */\nfunction transcriptRows(messages: any[] | undefined): Array<{ role: string; content: string }> {\n if (!Array.isArray(messages)) return [];\n const rows: Array<{ role: string; content: string }> = [];\n for (const m of messages) {\n const content = messageText(m);\n if (!content) continue;\n rows.push({ role: m?.role === 'toolResult' ? 'tool' : String(m?.role ?? 'user'), content });\n }\n return rows;\n}\n\n/** Flatten a pi-ai Context (systemPrompt + messages) into LLM-span input rows. */\nfunction promptMessagesOf(context: any): Array<{ role: string; content: string }> {\n const rows: Array<{ role: string; content: string }> = [];\n if (typeof context?.systemPrompt === 'string' && context.systemPrompt) {\n rows.push({ role: 'system', content: context.systemPrompt });\n }\n if (Array.isArray(context?.messages)) {\n for (const m of context.messages) {\n const content = messageText(m);\n if (content) rows.push({ role: String(m?.role ?? 'user'), content });\n }\n }\n return rows;\n}\n\nfunction handleEvent(\n tracer: ReturnType<typeof trace.getTracer>,\n state: PerAgentState,\n event: PiAgentEvent,\n getTranscript?: () => any[] | undefined,\n): void {\n switch (event.type) {\n case 'agent_start': {\n // Open the AGENT (run) span as the active span so children nest under it.\n const base = getNeatlogsParentContext();\n const span = tracer.startSpan(\n 'pi_agent.run',\n { attributes: { 'neatlogs.span.kind': 'AGENT' } },\n base,\n );\n state.agentSpan = span;\n state.agentCtx = trace.setSpan(base, span);\n // A continuation resumes an existing transcript and emits no user message,\n // so seed the prompt context from it — otherwise the first LLM span of the\n // run would report no input at all.\n state.inputMessages = transcriptRows(getTranscript?.());\n state.turnIndex = 0;\n state.runInput = undefined;\n state.runError = undefined;\n break;\n }\n\n case 'turn_start': {\n // One CHAIN span per turn, so a multi-turn run keeps its turn boundaries\n // instead of flattening every LLM/TOOL child under the run.\n const parent = state.agentCtx ?? getNeatlogsParentContext();\n state.turnIndex += 1;\n // What prompted this turn? If the transcript already ends in a user or tool\n // message it is that message (a tool-result turn, or a continuation). If it\n // ends in an assistant message the prompt has not arrived yet — pi emits\n // turn_start before it — so message_end stamps it instead.\n const pending = state.inputMessages[state.inputMessages.length - 1];\n const priorInput =\n pending && (pending.role === 'user' || pending.role === 'tool') ? pending.content : undefined;\n const span = tracer.startSpan(\n `pi_agent.turn.${state.turnIndex}`,\n {\n attributes: {\n 'neatlogs.span.kind': 'CHAIN',\n 'neatlogs.chain.turn_index': state.turnIndex,\n ...(priorInput ? { 'input.value': priorInput } : {}),\n },\n },\n parent,\n );\n state.turnSpan = span;\n state.turnCtx = trace.setSpan(parent, span);\n state.turnHasInput = !!priorInput;\n state.turnStartEpochMs = Date.now();\n break;\n }\n\n case 'turn_end': {\n if (!state.turnSpan) break;\n const msg = event.message as PiAssistantMessage | undefined;\n const { text, toolCalls } = splitAssistantContent(msg?.content);\n // A tool-use turn produces no assistant text — describe the calls it made\n // rather than leaving the turn's output blank. An aborted turn has neither,\n // so report why it ended.\n const out =\n text ||\n toolCalls.map((tc) => `${tc.name}(${safeStringify(tc.arguments)})`).join('\\n') ||\n terminalSummary(msg);\n if (out) state.turnSpan.setAttribute('output.value', out);\n if (Array.isArray(event.toolResults) && event.toolResults.length) {\n state.turnSpan.setAttribute('neatlogs.chain.tool_result_count', event.toolResults.length);\n }\n applyStopReasonStatus(state.turnSpan, msg);\n state.turnSpan.end();\n state.turnSpan = undefined;\n state.turnCtx = undefined;\n state.turnHasInput = false;\n state.turnStartEpochMs = undefined;\n break;\n }\n\n case 'message_start': {\n const msg = event.message as any;\n if (!msg || msg.role !== 'assistant') break;\n // Open the LLM span HERE so its duration covers the real provider call.\n // (Opening it at message_end would always report ~0ms.)\n state.llm = openLlmSpan(tracer, state, msg);\n break;\n }\n\n case 'message_update': {\n // First content delta = time to first token.\n const llm = state.llm;\n if (!llm) break;\n llm.span.setAttribute('neatlogs.llm.is_streaming', true);\n if (llm.ttftMs === undefined && isContentDelta(event.assistantMessageEvent?.type)) {\n // Measure from the same instant the span starts at, so TTFT stays\n // consistent with the span's own duration.\n llm.ttftMs =\n llm.callStartEpochMs !== undefined\n ? Date.now() - llm.callStartEpochMs\n : nowMs() - llm.startHr;\n }\n break;\n }\n\n case 'message_end': {\n const msg = event.message as any;\n if (!msg) return;\n if (msg.role === 'assistant') {\n // Finish the LLM span opened at message_start. If that event was missed,\n // open one now so the call is still recorded (duration reads ~0ms).\n const llm = state.llm ?? openLlmSpan(tracer, state, msg);\n state.llm = undefined;\n state.runError = finishLlmSpan(llm, msg as PiAssistantMessage) ?? state.runError;\n const { text } = splitAssistantContent(msg.content);\n if (text) state.inputMessages.push({ role: 'assistant', content: text });\n } else {\n // user / toolResult turns — accumulate as input context for later LLM spans.\n const role = msg.role === 'toolResult' ? 'tool' : String(msg.role || 'user');\n const content = messageText(msg);\n if (content) {\n state.inputMessages.push({ role, content });\n if (role === 'user' && state.runInput === undefined) state.runInput = content;\n // turn_start fires before the message that prompts the turn, so the\n // first such message is this turn's input.\n if (state.turnSpan && !state.turnHasInput) {\n state.turnSpan.setAttribute('input.value', content);\n state.turnHasInput = true;\n }\n }\n }\n break;\n }\n\n case 'tool_execution_start': {\n const parent = state.turnCtx ?? state.agentCtx ?? getNeatlogsParentContext();\n const span = tracer.startSpan(\n `pi_agent.tool.${event.toolName ?? 'tool'}`,\n {\n attributes: {\n 'neatlogs.span.kind': 'TOOL',\n ...(event.toolName ? { 'neatlogs.tool.name': String(event.toolName) } : {}),\n ...(event.toolCallId ? { 'neatlogs.tool.call_id': String(event.toolCallId) } : {}),\n ...(event.args !== undefined\n ? { 'input.value': safeStringify(event.args) }\n : {}),\n },\n },\n parent,\n );\n if (event.toolCallId) state.toolSpans.set(event.toolCallId, span);\n break;\n }\n\n case 'tool_execution_update': {\n // Streaming tool progress — record that partials arrived without\n // rewriting output.value (the final result lands at tool_execution_end).\n const span = event.toolCallId ? state.toolSpans.get(event.toolCallId) : undefined;\n if (!span) break;\n span.setAttribute('neatlogs.tool.is_streaming', true);\n break;\n }\n\n case 'tool_execution_end': {\n const span = event.toolCallId ? state.toolSpans.get(event.toolCallId) : undefined;\n if (!span) return;\n if (event.result !== undefined) {\n span.setAttribute('output.value', safeStringify(event.result));\n }\n if (event.isError) {\n span.setStatus({ code: SpanStatusCode.ERROR, message: toolErrorText(event.result) });\n span.setAttribute('neatlogs.tool.is_error', true);\n } else {\n span.setStatus({ code: SpanStatusCode.OK });\n }\n span.end();\n if (event.toolCallId) state.toolSpans.delete(event.toolCallId);\n break;\n }\n\n case 'agent_end': {\n // Close any tool spans that never received an end event, then the LLM span\n // (an abort can end the run mid-stream), the turn span, and the run span.\n for (const ts of state.toolSpans.values()) {\n try {\n ts.setStatus({ code: SpanStatusCode.ERROR, message: 'run ended before tool completed' });\n ts.end();\n } catch {\n /* ignore */\n }\n }\n state.toolSpans.clear();\n\n if (state.llm) {\n try {\n state.llm.span.setAttribute('output.value', '[incomplete] run ended mid-stream');\n state.llm.span.setStatus({ code: SpanStatusCode.ERROR, message: 'run ended mid-stream' });\n state.llm.span.end();\n } catch {\n /* ignore */\n }\n state.llm = undefined;\n }\n\n if (state.turnSpan) {\n try {\n state.turnSpan.end();\n } catch {\n /* ignore */\n }\n state.turnSpan = undefined;\n state.turnCtx = undefined;\n state.turnStartEpochMs = undefined;\n }\n\n if (state.agentSpan) {\n // Agent input = this run's first user message. A continuation\n // (`continue()`, agentLoopContinue) emits NO new user message — the turn\n // is already in the transcript — so fall back to the live transcript.\n const input = state.runInput ?? lastUserTextFrom(event.messages) ?? lastUserTextFrom(getTranscript?.());\n if (input) state.agentSpan.setAttribute('input.value', input);\n\n // Output = final assistant text. On an aborted/errored run there may be\n // none, so fall back to the terminal reason rather than leaving it blank.\n const finalText = lastAssistantText(event.messages);\n const err = state.runError ?? terminalErrorFrom(event.messages);\n if (finalText) {\n state.agentSpan.setAttribute('output.value', finalText);\n } else if (err) {\n state.agentSpan.setAttribute('output.value', `[${err.stopReason}]${err.message ? ` ${err.message}` : ''}`);\n }\n\n if (err) {\n state.agentSpan.setAttribute('neatlogs.agent.stop_reason', err.stopReason);\n if (err.message) state.agentSpan.setAttribute('neatlogs.error.message', err.message);\n state.agentSpan.setStatus({ code: SpanStatusCode.ERROR, message: err.message ?? err.stopReason });\n } else {\n state.agentSpan.setStatus({ code: SpanStatusCode.OK });\n }\n state.agentSpan.end();\n state.agentSpan = undefined;\n state.agentCtx = undefined;\n }\n break;\n }\n\n default:\n break;\n }\n}\n\n/** Start an LLM span for an assistant message, snapshotting the prompt so far. */\nfunction openLlmSpan(\n tracer: ReturnType<typeof trace.getTracer>,\n state: PerAgentState,\n msg: PiAssistantMessage,\n): LlmInFlight {\n const parent = state.turnCtx ?? state.agentCtx ?? getNeatlogsParentContext();\n // Pi emits message_start only once the provider's first stream event lands, so\n // most of the call's latency has already elapsed by now — and an EventStream\n // consumer that lags (`for await` on agentLoop) can receive start/end in one\n // burst, collapsing the span to ~0ms. `msg.timestamp` is stamped when pi begins\n // the model-call step, so prefer it as the start time.\n const startTime = callStartFrom(msg, state.turnStartEpochMs);\n const span = tracer.startSpan(\n `pi_agent.llm.${msg.model || 'model'}`,\n {\n ...(startTime !== undefined ? { startTime } : {}),\n attributes: {\n 'neatlogs.span.kind': 'LLM',\n // Pi streams by default; message_update deltas confirm it per call.\n 'neatlogs.llm.is_streaming': false,\n ...(msg.model ? { 'neatlogs.llm.model_name': String(msg.model) } : {}),\n ...(msg.provider ? { 'neatlogs.llm.provider': String(msg.provider) } : {}),\n },\n },\n parent,\n );\n return {\n span,\n startHr: nowMs(),\n callStartEpochMs: startTime,\n inputMessages: state.inputMessages.slice(),\n };\n}\n\n/**\n * The epoch-ms start of the model call, from pi's own message timestamp.\n *\n * Ignored if it isn't a plausible recent past instant — a clock skew or a\n * replayed transcript would otherwise produce a nonsense duration. Clamped to the\n * enclosing turn so a backdated child can never start before its parent.\n */\nfunction callStartFrom(msg: PiAssistantMessage, turnStart: number | undefined): number | undefined {\n const ts = msg.timestamp;\n if (typeof ts !== 'number' || !Number.isFinite(ts)) return undefined;\n const now = Date.now();\n const age = now - ts;\n if (age < 0 || age > MAX_CALL_AGE_MS) return undefined;\n return turnStart !== undefined ? Math.max(ts, turnStart) : ts;\n}\n\n/** A single model call older than this is a stale/replayed timestamp, not a live call. */\nconst MAX_CALL_AGE_MS = 30 * 60_000;\n\n/** `[aborted] Request was aborted` — output for a message that produced no content. */\nfunction terminalSummary(msg: PiAssistantMessage | undefined): string {\n const reason = msg?.stopReason;\n if (reason !== 'aborted' && reason !== 'error') return '';\n return `[${reason}]${msg?.errorMessage ? ` ${msg.errorMessage}` : ''}`;\n}\n\n/** `aborted` / `error` stop reasons must not report OK. */\nfunction applyStopReasonStatus(span: Span, msg: PiAssistantMessage | undefined): void {\n const reason = msg?.stopReason;\n if (reason === 'aborted' || reason === 'error') {\n span.setStatus({ code: SpanStatusCode.ERROR, message: msg?.errorMessage ?? reason });\n } else {\n span.setStatus({ code: SpanStatusCode.OK });\n }\n}\n\n/** Content deltas that mark the first streamed token. */\nfunction isContentDelta(type: string | undefined): boolean {\n return type === 'text_delta' || type === 'thinking_delta' || type === 'toolcall_delta';\n}\n\nfunction nowMs(): number {\n // performance.now() where available (monotonic), else Date.now().\n const p = (globalThis as any).performance;\n return typeof p?.now === 'function' ? p.now() : Date.now();\n}\n\n/** Pull a readable error message out of a failed tool result. */\nfunction toolErrorText(result: unknown): string {\n if (!result || typeof result !== 'object') return 'tool error';\n const content = (result as any).content;\n if (Array.isArray(content)) {\n const text = content\n .map((b: any) => (typeof b?.text === 'string' ? b.text : ''))\n .filter(Boolean)\n .join(' ')\n .trim();\n if (text) return text;\n }\n return 'tool error';\n}\n\n/** The most recent user message text in a transcript, if any. */\nfunction lastUserTextFrom(messages: any[] | undefined): string | undefined {\n if (!Array.isArray(messages)) return undefined;\n for (let i = messages.length - 1; i >= 0; i--) {\n const m = messages[i];\n if (m && m.role === 'user') {\n const text = messageText(m);\n if (text) return text;\n }\n }\n return undefined;\n}\n\n/** If the run's last assistant turn aborted or errored, describe it. */\nfunction terminalErrorFrom(\n messages: any[] | undefined,\n): { stopReason: string; message?: string } | undefined {\n if (!Array.isArray(messages)) return undefined;\n for (let i = messages.length - 1; i >= 0; i--) {\n const m = messages[i];\n if (m && m.role === 'assistant') {\n if (m.stopReason === 'aborted' || m.stopReason === 'error') {\n return { stopReason: m.stopReason, message: m.errorMessage };\n }\n return undefined;\n }\n }\n return undefined;\n}\n\n/**\n * Close the LLM span opened at `message_start`, stamping the response.\n *\n * The span is already open, so its duration is the real provider latency; here we\n * only attach what the completed message carries: I/O, tokens, pi-ai's exact\n * cost, TTFT, and the terminal status.\n */\nfunction finishLlmSpan(\n llm: LlmInFlight,\n msg: PiAssistantMessage,\n endTime?: number,\n): { stopReason: string; message?: string } | undefined {\n const span = llm.span;\n\n if (msg.model) span.setAttribute('neatlogs.llm.model_name', String(msg.model));\n if (msg.provider) span.setAttribute('neatlogs.llm.provider', String(msg.provider));\n // The provider may answer with a different snapshot than the one requested.\n if (msg.responseModel) span.setAttribute('neatlogs.llm.response_model', String(msg.responseModel));\n if (msg.api) span.setAttribute('neatlogs.llm.api', String(msg.api));\n if (msg.stopReason) span.setAttribute('neatlogs.llm.stop_reason', String(msg.stopReason));\n\n // Input = the conversation as it stood when the call was issued (snapshotted at\n // message_start). Pi Agent's message_end carries only the response, not the prompt.\n const inMsgs = llm.inputMessages;\n if (inMsgs.length) {\n inMsgs.forEach((m, i) => {\n span.setAttribute(`neatlogs.llm.input_messages.${i}.role`, m.role);\n span.setAttribute(`neatlogs.llm.input_messages.${i}.content`, m.content);\n });\n const inBlob = safeStringify({ messages: inMsgs });\n span.setAttribute('neatlogs.llm.input', inBlob);\n span.setAttribute('input.value', inBlob);\n }\n\n const { text, toolCalls } = splitAssistantContent(msg.content);\n // Output: text if present, else a readable tool-call summary so the span isn't\n // blank. A call that was aborted or failed has neither — report why instead.\n const outText =\n text ||\n toolCalls.map((tc) => `${tc.name}(${safeStringify(tc.arguments)})`).join('\\n') ||\n terminalSummary(msg);\n if (outText || toolCalls.length) {\n span.setAttribute('neatlogs.llm.output_messages.0.role', 'assistant');\n span.setAttribute('neatlogs.llm.output_messages.0.content', outText || '');\n const outBlob: Record<string, unknown> = { role: 'assistant', content: outText || '' };\n if (toolCalls.length) {\n outBlob.tool_calls = toolCalls.map((tc) => ({ name: tc.name, arguments: tc.arguments }));\n toolCalls.forEach((tc, j) => {\n if (tc.name) span.setAttribute(`neatlogs.llm.tool_calls.${j}.name`, tc.name);\n if (tc.arguments !== undefined)\n span.setAttribute(`neatlogs.llm.tool_calls.${j}.arguments`, safeStringify(tc.arguments));\n if (tc.id) span.setAttribute(`neatlogs.llm.tool_calls.${j}.id`, String(tc.id));\n });\n }\n span.setAttribute('neatlogs.llm.output', safeStringify(outBlob));\n span.setAttribute('output.value', outText || '');\n }\n\n const usage = msg.usage;\n if (usage) {\n if (usage.input != null) span.setAttribute('neatlogs.llm.token_count.prompt', usage.input);\n if (usage.output != null) span.setAttribute('neatlogs.llm.token_count.completion', usage.output);\n const total = usage.totalTokens ?? ((usage.input ?? 0) + (usage.output ?? 0));\n if (total) span.setAttribute('neatlogs.llm.token_count.total', total);\n if (usage.cacheRead) span.setAttribute('neatlogs.llm.token_count.cache_read', usage.cacheRead);\n if (usage.cacheWrite) span.setAttribute('neatlogs.llm.token_count.cache_write', usage.cacheWrite);\n\n // pi-ai prices the call itself against its model registry — carry that exact\n // figure through rather than letting the backend re-derive it from tokens.\n const cost = usage.cost;\n if (cost) {\n const totalCost =\n cost.total ??\n [cost.input, cost.output, cacheReadOf(cost), cost.cacheWrite].reduce<number>(\n (sum, v) => sum + (typeof v === 'number' ? v : 0),\n 0,\n );\n if (typeof totalCost === 'number' && totalCost > 0) {\n span.setAttribute('neatlogs.llm.cost_usd', totalCost);\n }\n if (typeof cost.input === 'number') span.setAttribute('neatlogs.llm.cost.prompt', cost.input);\n if (typeof cost.output === 'number') span.setAttribute('neatlogs.llm.cost.completion', cost.output);\n }\n }\n\n if (llm.ttftMs !== undefined) {\n span.setAttribute('neatlogs.llm.metrics.ttft_ms', Math.round(llm.ttftMs));\n }\n\n if (msg.errorMessage) span.setAttribute('neatlogs.error.message', String(msg.errorMessage));\n applyStopReasonStatus(span, msg);\n span.end(endTime);\n\n // Report an abnormal terminal state back to the caller: the AGENT span sees\n // only the transcript and would otherwise report a blank, SUCCESSful run.\n return msg.stopReason === 'aborted' || msg.stopReason === 'error'\n ? { stopReason: msg.stopReason, message: msg.errorMessage }\n : undefined;\n}\n\n/** pi-ai has used both `cacheRead` and (older) `cacheReads` for the cost breakdown. */\nfunction cacheReadOf(cost: Record<string, any>): number | undefined {\n return typeof cost.cacheRead === 'number' ? cost.cacheRead : cost.cacheReads;\n}\n\n// ---------------------------------------------------------------------------\n// Content helpers\n// ---------------------------------------------------------------------------\n\nfunction splitAssistantContent(\n content: PiAssistantMessage['content'],\n): { text: string; toolCalls: PiToolCall[] } {\n const texts: string[] = [];\n const toolCalls: PiToolCall[] = [];\n if (Array.isArray(content)) {\n for (const block of content) {\n if (!block || typeof block !== 'object') continue;\n if (block.type === 'text' && typeof block.text === 'string') texts.push(block.text);\n else if (block.type === 'toolCall')\n toolCalls.push(block as unknown as PiToolCall);\n // thinking blocks intentionally omitted from the main output text\n }\n } else if (typeof content === 'string') {\n texts.push(content);\n }\n return { text: texts.join(''), toolCalls };\n}\n\n/** Flatten any message's content (string or block array) to readable text. */\nfunction messageText(msg: any): string {\n if (!msg) return '';\n const c = msg.content;\n if (typeof c === 'string') return c;\n if (!Array.isArray(c)) return '';\n const parts: string[] = [];\n for (const block of c) {\n if (typeof block === 'string') parts.push(block);\n else if (block && typeof block === 'object') {\n if (typeof block.text === 'string') parts.push(block.text);\n else if (block.type === 'toolCall') parts.push(`${block.name ?? 'tool'}(${safeStringify(block.arguments)})`);\n }\n }\n return parts.join('');\n}\n\nfunction lastAssistantText(messages: any[] | undefined): string {\n if (!Array.isArray(messages)) return '';\n for (let i = messages.length - 1; i >= 0; i--) {\n const m = messages[i];\n if (m && m.role === 'assistant') {\n const { text } = splitAssistantContent(m.content);\n if (text) return text;\n }\n }\n return '';\n}\n\nfunction markPatched(e: any): void {\n try {\n Object.defineProperty(e, PATCH_FLAG, { value: true, enumerable: false, configurable: true });\n } catch {\n e[PATCH_FLAG] = true;\n }\n}\n\nfunction safeStringify(value: unknown): string {\n if (typeof value === 'string') return value;\n try {\n return JSON.stringify(value) ?? '';\n } catch {\n return '';\n }\n}\n","/**\n * Neatlogs-owned tracing state.\n *\n * Spans are created by the private Neatlogs provider and their parent is carried\n * in a private context key. The process-global OpenTelemetry span is\n * deliberately left untouched so other observability SDKs cannot export or\n * become parents of Neatlogs spans.\n */\n\nimport { AsyncLocalStorage } from 'node:async_hooks';\nimport {\n ROOT_CONTEXT,\n INVALID_SPAN_CONTEXT,\n createContextKey,\n trace as otelTrace,\n type Context,\n type Span,\n type SpanOptions,\n type Tracer,\n type TracerProvider,\n} from '@opentelemetry/api';\nimport { getActiveClient } from './active-client.js';\n\n// Carries the trace-ROOT span down the private context so descendants can target\n// it (e.g. setTraceOutput). getActiveNeatlogsSpan() returns the innermost span,\n// which is not the root once nested; this key preserves the root reference.\nconst NEATLOGS_ROOT_SPAN_KEY = createContextKey('neatlogs.root_span');\n\n// Entry points are bundled independently (`neatlogs`, `neatlogs/openai`,\n// `neatlogs/ai`, `neatlogs/mastra`, … each in both CJS and ESM), so every piece\n// of shared tracing state — the private span store AND the resolved provider /\n// provider — must live on `globalThis` behind a `Symbol.for` key.\n// Otherwise `init()` (run from the `neatlogs` bundle) sets `_provider` in ITS\n// module copy while a wrapper imported from `neatlogs/openai` reads a different,\n// still-null copy and silently falls back to the foreign global provider.\nconst PRIVATE_SPAN_STORAGE_KEY = Symbol.for(\n 'neatlogs.private_span_async_local_storage',\n);\nconst PRIVATE_PROVIDER_STATE_KEY = Symbol.for(\n 'neatlogs.private_provider_state',\n);\ninterface PrivateProviderState {\n provider: TracerProvider | null;\n}\ntype NeatlogsGlobal = typeof globalThis & {\n [PRIVATE_SPAN_STORAGE_KEY]?: AsyncLocalStorage<Context>;\n [PRIVATE_PROVIDER_STATE_KEY]?: PrivateProviderState;\n};\nconst neatlogsGlobal = globalThis as NeatlogsGlobal;\n// Stores the full Neatlogs Context (parent span PLUS any threaded values such as\n// trace()'s prompt-template keys), not just the span. We never\n// activate the OTel global context, so this private store is the ONLY channel\n// through which those values propagate down to descendant spans.\nconst privateContextStorage =\n neatlogsGlobal[PRIVATE_SPAN_STORAGE_KEY] ??\n (neatlogsGlobal[PRIVATE_SPAN_STORAGE_KEY] = new AsyncLocalStorage<Context>());\nconst providerState: PrivateProviderState =\n neatlogsGlobal[PRIVATE_PROVIDER_STATE_KEY] ??\n (neatlogsGlobal[PRIVATE_PROVIDER_STATE_KEY] = {\n provider: null,\n });\n// Wrappers may be constructed or accidentally invoked before init(). They must\n// never fall back to a foreign process-global provider, so pre-init calls use a\n// local no-op tracer and safely emit no exported spans.\nconst preInitTracer: Tracer = {\n startSpan(): Span {\n return otelTrace.wrapSpanContext(INVALID_SPAN_CONTEXT);\n },\n startActiveSpan<F extends (span: Span) => unknown>(\n _name: string,\n arg2?: SpanOptions | Context | F,\n arg3?: Context | F,\n arg4?: F,\n ): ReturnType<F> {\n const fn =\n typeof arg2 === 'function'\n ? arg2\n : typeof arg3 === 'function'\n ? arg3\n : arg4;\n return fn!(otelTrace.wrapSpanContext(INVALID_SPAN_CONTEXT)) as ReturnType<F>;\n },\n};\n\n/** @internal Configure the provider used by Neatlogs-created spans. */\nexport function _setNeatlogsProvider(provider: TracerProvider | null): void {\n providerState.provider = provider;\n}\n\n/** Resolve a tracer from the private provider when one is configured. */\nexport function getNeatlogsTracer(name: string): Tracer {\n const client = getActiveClient();\n if (client) return client.getTracer(name);\n return providerState.provider?.getTracer(name) ?? preInitTracer;\n}\n\n/** A reusable tracer facade that resolves the active Client on every call. */\nexport function getRoutingNeatlogsTracer(name: string): Tracer {\n return {\n startSpan(spanName: string, options?: SpanOptions, context?: Context): Span {\n return isolateTracer(getNeatlogsTracer(name)).startSpan(\n spanName,\n options,\n context,\n );\n },\n startActiveSpan: ((...args: any[]) =>\n (isolateTracer(getNeatlogsTracer(name)).startActiveSpan as (...inner: any[]) => any)(\n ...args,\n )) as Tracer['startActiveSpan'],\n };\n}\n\n/**\n * @internal The private Neatlogs provider, or null before\n * init(). Used by integrations that must repoint a self-instrumenting library's\n * captured provider onto ours.\n */\nexport function getNeatlogsProvider(): TracerProvider | null {\n const client = getActiveClient();\n if (client) return client.tracerProvider;\n return providerState.provider;\n}\n\n/** Run a Client callback without inheriting another pipeline's private span. */\nexport function runWithFreshNeatlogsContext<T>(fn: () => T): T {\n return privateContextStorage.run(ROOT_CONTEXT, fn);\n}\n\n/**\n * Wrap a tracer so that spans it creates parent from — and, for\n * `startActiveSpan`, activate on — the PRIVATE Neatlogs context instead of the\n * global one.\n *\n * We hand this to libraries that create their own spans off a tracer we give\n * them (the Vercel AI SDK's `experimental_telemetry.tracer`, which calls\n * `tracer.startActiveSpan()` internally). Without the facade the AI SDK's native\n * spans would parent from `context.active()` — the foreign co-tenant's context —\n * and `startActiveSpan` would push them onto the GLOBAL context, so a foreign\n * tracer's next span reads our native span as its parent. Both directions leak.\n *\n */\nexport function isolateTracer(tracer: Tracer): Tracer {\n const facade: Tracer = {\n startSpan(name: string, options?: SpanOptions, context?: Context): Span {\n const parent = context ?? getNeatlogsActiveContext();\n return tracer.startSpan(name, options, parent);\n },\n startActiveSpan<F extends (span: Span) => unknown>(\n name: string,\n arg2?: SpanOptions | Context | F,\n arg3?: Context | F,\n arg4?: F,\n ): ReturnType<F> {\n // Normalize the 2/3/4-arg overloads of startActiveSpan.\n let options: SpanOptions | undefined;\n let context: Context | undefined;\n let fn: F;\n if (typeof arg2 === 'function') {\n fn = arg2 as F;\n } else if (typeof arg3 === 'function') {\n options = arg2 as SpanOptions;\n fn = arg3 as F;\n } else {\n options = arg2 as SpanOptions;\n context = arg3 as Context;\n fn = arg4 as F;\n }\n const parent = context ?? getNeatlogsActiveContext();\n const span = tracer.startSpan(name, options, parent);\n return withNeatlogsSpan(span, () => fn(span), parent) as ReturnType<F>;\n },\n };\n return facade;\n}\n\n/**\n * The base context to build new Neatlogs spans and values on. NEVER contains a\n * foreign provider's span: it reads our private store, or ROOT_CONTEXT when\n * nothing is active.\n */\nexport function getNeatlogsActiveContext(): Context {\n return privateContextStorage.getStore() ?? ROOT_CONTEXT;\n}\n\n/** Return only the active Neatlogs span (never a foreign provider's span). */\nexport function getActiveNeatlogsSpan(): Span | undefined {\n return otelTrace.getSpan(getNeatlogsActiveContext());\n}\n\n/**\n * Return the trace-ROOT Neatlogs span, or undefined when no trace is active.\n *\n * Unlike {@link getActiveNeatlogsSpan} (innermost), this is the outermost span\n * of the current trace — the one the backend derives trace-level output from\n * (`parent_span_id=''`). It is stashed on the private context the first time a\n * span becomes active, so nested calls still resolve to the root.\n */\nexport function getNeatlogsRootSpan(): Span | undefined {\n return getNeatlogsActiveContext().getValue(NEATLOGS_ROOT_SPAN_KEY) as\n | Span\n | undefined;\n}\n\n/**\n * Build a parent context that cannot contain a foreign provider's span.\n *\n * The active Neatlogs context already carries the parent span AND any values\n * the caller threaded in upstream (e.g. `trace()`'s prompt-template values), so\n * those values reach the span processor via `onStart(parentContext)`. An\n * explicit `baseContext` (a caller's own value-carrying context) is honored as-is.\n */\nexport function getNeatlogsParentContext(baseContext?: Context): Context {\n return baseContext ?? getNeatlogsActiveContext();\n}\n\n/**\n * A base context for callers that thread parent linkage themselves\n * (callback/event handlers that keep their own run-id → span map: LangChain,\n * OpenAI-Agents, Claude Agent SDK).\n *\n * This is the ACTIVE Neatlogs context — the private store's\n * context if a Neatlogs `trace()`/`span()` encloses this call, else\n * ROOT_CONTEXT. So a handler's own root/entry span nests under an enclosing\n * Neatlogs trace (preserving its session + end-user id) when one exists, and\n * auto-roots cleanly when one doesn't. A foreign provider's active span can\n * never leak in as an ancestor because the global context is never read.\n */\nexport function getNeatlogsBaseContext(baseContext?: Context): Context {\n return baseContext ?? getNeatlogsActiveContext();\n}\n\n/**\n * Build an execution context for a Neatlogs span while preserving the active\n * foreign context. The span rides our private context store.\n */\nexport function getNeatlogsExecutionContext(\n span: Span,\n baseContext: Context = ROOT_CONTEXT,\n): Context {\n return otelTrace.setSpan(baseContext, span);\n}\n\n/**\n * Run a callback with a Neatlogs span active under the appropriate policy.\n *\n * The stored context is `setSpan(base, span)` — carrying the span PLUS whatever\n * values `base` holds — so threaded values (prompt templates)\n * propagate to descendant spans through our private store instead of the global\n * OTel context we deliberately never touch.\n */\nexport function withNeatlogsSpan<T>(\n span: Span,\n fn: () => T,\n baseContext?: Context,\n): T {\n const base = baseContext ?? getNeatlogsActiveContext();\n let ctx = otelTrace.setSpan(base, span);\n // The first span activated in a context with no root recorded IS the root of\n // this trace; remember it so descendants (setTraceOutput) can target it.\n if (base.getValue(NEATLOGS_ROOT_SPAN_KEY) === undefined) {\n ctx = ctx.setValue(NEATLOGS_ROOT_SPAN_KEY, span);\n }\n return privateContextStorage.run(ctx, fn);\n}\n\n/**\n * @internal Run with a private Neatlogs parent without treating that parent as\n * a locally-recording trace root. This is used for an extracted remote parent:\n * the first local recording span should remain the target for local trace-level\n * output, while still inheriting the remote trace/span IDs.\n */\nexport function withNeatlogsRemoteParent<T>(span: Span, fn: () => T): T {\n return privateContextStorage.run(otelTrace.setSpan(ROOT_CONTEXT, span), fn);\n}\n","import { AsyncLocalStorage } from 'node:async_hooks';\nimport type { Tracer, TracerProvider } from '@opentelemetry/api';\n\nexport interface ActiveNeatlogsClient {\n readonly workflowName: string;\n readonly tracerProvider: TracerProvider;\n getTracer(scope: string): Tracer;\n getLogger(): any | null;\n}\n\nconst ACTIVE_CLIENT_STORAGE_KEY = Symbol.for(\n 'neatlogs.active_client_async_local_storage',\n);\ntype NeatlogsGlobal = typeof globalThis & {\n [ACTIVE_CLIENT_STORAGE_KEY]?: AsyncLocalStorage<ActiveNeatlogsClient>;\n};\nconst neatlogsGlobal = globalThis as NeatlogsGlobal;\nconst storage =\n neatlogsGlobal[ACTIVE_CLIENT_STORAGE_KEY] ??\n (neatlogsGlobal[ACTIVE_CLIENT_STORAGE_KEY] =\n new AsyncLocalStorage<ActiveNeatlogsClient>());\n\nexport function getActiveClient(): ActiveNeatlogsClient | undefined {\n return storage.getStore();\n}\n\nexport function runWithClient<T>(\n client: ActiveNeatlogsClient,\n fn: () => T,\n): T {\n return storage.run(client, fn);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAyCA,IAAAA,cAKO;;;ACrCP,IAAAC,2BAAkC;AAClC,iBAUO;;;ACpBP,8BAAkC;AAUlC,IAAM,4BAA4B,uBAAO;AAAA,EACvC;AACF;AAIA,IAAM,iBAAiB;AACvB,IAAM,UACJ,eAAe,yBAAyB,MACvC,eAAe,yBAAyB,IACvC,IAAI,0CAAwC;AAEzC,SAAS,kBAAoD;AAClE,SAAO,QAAQ,SAAS;AAC1B;;;ADEA,IAAM,6BAAyB,6BAAiB,oBAAoB;AASpE,IAAM,2BAA2B,uBAAO;AAAA,EACtC;AACF;AACA,IAAM,6BAA6B,uBAAO;AAAA,EACxC;AACF;AAQA,IAAMC,kBAAiB;AAKvB,IAAM,wBACJA,gBAAe,wBAAwB,MACtCA,gBAAe,wBAAwB,IAAI,IAAI,2CAA2B;AAC7E,IAAM,gBACJA,gBAAe,0BAA0B,MACxCA,gBAAe,0BAA0B,IAAI;AAAA,EAC5C,UAAU;AACZ;AAIF,IAAM,gBAAwB;AAAA,EAC5B,YAAkB;AAChB,WAAO,WAAAC,MAAU,gBAAgB,+BAAoB;AAAA,EACvD;AAAA,EACA,gBACE,OACA,MACA,MACA,MACe;AACf,UAAM,KACJ,OAAO,SAAS,aACZ,OACA,OAAO,SAAS,aACd,OACA;AACR,WAAO,GAAI,WAAAA,MAAU,gBAAgB,+BAAoB,CAAC;AAAA,EAC5D;AACF;AAQO,SAAS,kBAAkB,MAAsB;AACtD,QAAM,SAAS,gBAAgB;AAC/B,MAAI,OAAQ,QAAO,OAAO,UAAU,IAAI;AACxC,SAAO,cAAc,UAAU,UAAU,IAAI,KAAK;AACpD;AAuFO,SAAS,2BAAoC;AAClD,SAAO,sBAAsB,SAAS,KAAK;AAC7C;AA6BO,SAAS,yBAAyB,aAAgC;AACvE,SAAO,eAAe,yBAAyB;AACjD;;;ADrKA,IAAM,cAAc;AACpB,IAAM,aAAa;AACnB,IAAM,sBAAsB;AA2FrB,SAAS,aAA+B,OAAa;AAC1D,MAAI,CAAC,SAAU,MAAc,UAAU,EAAG,QAAO;AACjD,QAAM,IAAI;AACV,MAAI,OAAO,EAAE,cAAc,WAAY,QAAO;AAE9C,QAAM,WAAW,mBAAmB,MAAM,EAAE,OAAO,QAAQ;AAC3D,IAAE,UAAU,CAAC,UAAwB,SAAS,KAAK,CAAC;AAKpD,6BAA2B,CAAC;AAE5B,cAAY,CAAC;AACb,SAAO;AACT;AAOA,SAAS,2BAA2B,SAAoB;AACtD,MAAI,QAAQ,mBAAmB,EAAG;AAClC,QAAM,YACJ,OAAO,QAAQ,YAAY,cAC3B,OAAO,QAAQ,iBAAiB,cAChC,OAAO,QAAQ,aAAa;AAC9B,MAAI,CAAC,UAAW;AAEhB,qBAAmB,SAAS,WAAW,CAAC,UAAU,EAAE,oBAAoB,KAAK,CAAC,EAAE,EAAE;AAClF,qBAAmB,SAAS,gBAAgB,CAAC,UAAU,EAAE,UAAU,KAAK,CAAC,GAAG,SAAS,KAAK,CAAC,EAAE,EAAE;AAC/F,MAAI;AACF,WAAO,eAAe,SAAS,qBAAqB,EAAE,OAAO,KAAK,CAAC;AAAA,EACrE,QAAQ;AACN,YAAQ,mBAAmB,IAAI;AAAA,EACjC;AACF;AAEA,SAAS,mBACP,SACA,QACA,SACM;AACN,QAAM,WAAW,QAAQ,MAAM,EAAE,KAAK,OAAO;AAC7C,UAAQ,MAAM,IAAI,UAAU,SAAgB;AAC1C,UAAM,YAAY,KAAK,IAAI;AAC3B,UAAM,SAAS,yBAAyB;AACxC,UAAM,QAAQ,QAAQ,IAAI;AAC1B,QAAI;AACJ,QAAI;AACJ,QAAI;AACF,sBAAgB,QAAQ,UAAU,CAAC,UAAe;AAChD,YAAI,WAAW,aAAa,OAAO,SAAS,mBAAmB;AAC7D,8BAAoB,CAAC,MAAM;AAAA,QAC7B,WAAW,WAAW,kBAAkB,OAAO,SAAS,gBAAgB;AACtE,8BAAoB,QAAQ,MAAM,YAAY,KAAK,CAAC,MAAM;AAAA,QAC5D;AAAA,MACF,CAAC;AAAA,IACH,QAAQ;AAAA,IAER;AACA,QAAI;AACJ,QAAI;AACJ,QAAI;AACF,eAAS,MAAM,SAAS,GAAG,IAAI;AAC/B,aAAO;AAAA,IACT,SAAS,KAAK;AACZ,gBAAU;AACV,YAAM;AAAA,IACR,UAAE;AACA,sBAAgB;AAChB,UAAI;AACF;AAAA,UACE;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA,QAAQ,WAAW;AAAA,UACnB;AAAA,UACA;AAAA,UACA,KAAK,IAAI;AAAA,UACT;AAAA,QACF;AAAA,MACF,QAAQ;AAAA,MAER;AAAA,IACF;AAAA,EACF;AACF;AAEA,SAAS,qBACP,QACA,OACA,QACA,SACA,OACA,gBACA,WACA,SACA,mBACM;AACN,QAAM,SAAS,kBAAkB,WAAW;AAC5C,MAAI,SAAS;AACb,MAAI;AACJ,QAAM,YAAY,cAAc,SAAS,CAAC,CAAC;AAC3C,QAAM,aAAa,UACf,WAAW,mBAAmB,QAAQ,QAAQ,UAAU,OAAO,OAAO,CAAC,KACvE,uBAAuB,QAAQ,MAAM;AAEzC,MAAI,CAAC,kBAAM,QAAQ,MAAM,GAAG,YAAY,GAAG;AACzC,WAAO,OAAO;AAAA,MACZ,oBAAoB,MAAM;AAAA,MAC1B;AAAA,QACE,WAAW;AAAA,QACX,YAAY;AAAA,UACV,sBAAsB;AAAA,UACtB,eAAe;AAAA,QACjB;AAAA,MACF;AAAA,MACA;AAAA,IACF;AACA,aAAS,kBAAM,QAAQ,QAAQ,IAAI;AAAA,EACrC;AAEA,QAAM,QAAQ,OAAO;AAAA,IACnB,oBAAoB,MAAM;AAAA,IAC1B;AAAA,MACE,WAAW;AAAA,MACX,YAAY;AAAA,QACV,sBAAsB;AAAA,QACtB,yBAAyB;AAAA,QACzB,eAAe;AAAA,MACjB;AAAA,IACF;AAAA,IACA;AAAA,EACF;AACA,QAAM,WAAW,kBAAM,QAAQ,QAAQ,KAAK;AAE5C,QAAM,QAAQ,sBAAsB,QAAQ,MAAM;AAClD,QAAM,gBACJ,sBACC,UACG,8BAA8B,OAAO,IACrC,WAAW,YACT,QAAQ,QAAQ,KAAK,IACrB,QAAQ,QAAQ,YAAY,KAAK,OAAO,aAAa,aAAa;AAC1E,MAAI,iBAAiB,SAAS;AAC5B,UAAM,MAAM;AAAA,MACV;AAAA,MACA;AAAA,QACE,WAAW,oBAAI,IAAI;AAAA,QACnB,eAAe,CAAC,EAAE,MAAM,QAAQ,SAAS,UAAU,CAAC;AAAA,QACpD,WAAW;AAAA,QACX,SAAS;AAAA,QACT,kBAAkB;AAAA,MACpB;AAAA,MACA;AAAA,QACE,MAAM;AAAA,QACN,OAAO,OAAO,MAAM,OAAO;AAAA,QAC3B,UAAU,OAAO;AAAA,QACjB,WAAW;AAAA,MACb;AAAA,IACF;AACA,QAAI,SAAS;AACX,sBAAgB,KAAK,SAAS,OAAO;AAAA,IACvC,OAAO;AACL;AAAA,QACE;AAAA,QACA;AAAA,UACE,MAAM;AAAA,UACN,OAAO,OAAO,MAAM,OAAO;AAAA,UAC3B,UAAU,OAAO;AAAA,UACjB,SAAS,aAAa,CAAC,EAAE,MAAM,QAAQ,MAAM,WAAW,CAAC,IAAI,CAAC;AAAA,UAC9D;AAAA,UACA,YAAY;AAAA,QACd;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,MAAI,WAAY,OAAM,aAAa,gBAAgB,UAAU;AAC7D,MAAI,SAAS;AACX,UAAM,UAAU,mBAAmB,QAAQ,QAAQ,UAAU,OAAO,OAAO;AAC3E,UAAM,aAAa,0BAA0B,OAAO;AACpD,UAAM,UAAU,EAAE,MAAM,2BAAe,OAAO,QAAQ,CAAC;AAAA,EACzD,OAAO;AACL,UAAM,UAAU,EAAE,MAAM,2BAAe,GAAG,CAAC;AAAA,EAC7C;AACA,QAAM,IAAI,OAAO;AAEjB,MAAI,MAAM;AACR,QAAI,WAAY,MAAK,aAAa,gBAAgB,UAAU;AAC5D,QAAI,SAAS;AACX,YAAM,UAAU,mBAAmB,QAAQ,QAAQ,UAAU,OAAO,OAAO;AAC3E,WAAK,aAAa,0BAA0B,OAAO;AACnD,WAAK,UAAU,EAAE,MAAM,2BAAe,OAAO,QAAQ,CAAC;AAAA,IACxD,OAAO;AACL,WAAK,UAAU,EAAE,MAAM,2BAAe,GAAG,CAAC;AAAA,IAC5C;AACA,SAAK,IAAI,OAAO;AAAA,EAClB;AACF;AAEA,SAAS,8BAA8B,SAA2B;AAChE,MAAI,UAAe;AACnB,QAAM,OAAO,oBAAI,IAAa;AAC9B,SAAO,WAAW,CAAC,KAAK,IAAI,OAAO,GAAG;AACpC,SAAK,IAAI,OAAO;AAChB,QAAI,QAAQ,SAAS,uBAAwB,QAAO;AACpD,cAAU,QAAQ;AAAA,EACpB;AACA,SAAO;AACT;AAEA,SAAS,uBAAuB,QAAoC,QAAqB;AACvF,MAAI,WAAW,UAAW,QAAO,OAAO,QAAQ,YAAY,WAAW,OAAO,UAAU,cAAc,UAAU,CAAC,CAAC;AAClH,QAAM,UAAU,QAAQ,cAAc;AACtC,SAAO,OAAO,YAAY,WAAW,UAAU,cAAc,UAAU,CAAC,CAAC;AAC3E;AAEA,SAAS,sBAAsB,QAAoC,QAAkC;AACnG,SAAO,WAAW,YAAY,QAAQ,QAAQ,QAAQ,cAAc;AACtE;AAEA,SAAS,gBAAgB,KAAkB,SAAkB,SAAwB;AACnF,QAAM,UAAU,mBAAmB,QAAQ,QAAQ,UAAU,OAAO,OAAO;AAC3E,MAAI,KAAK,aAAa,gBAAgB,WAAW,OAAO,EAAE;AAC1D,MAAI,KAAK,aAAa,0BAA0B,OAAO;AACvD,MAAI,KAAK,UAAU,EAAE,MAAM,2BAAe,OAAO,QAAQ,CAAC;AAC1D,MAAI,KAAK,IAAI,OAAO;AACtB;AA0BO,SAAS,mBACd,eAC0B;AAC1B,QAAM,QAAuB,EAAE,WAAW,oBAAI,IAAI,GAAG,eAAe,CAAC,GAAG,WAAW,EAAE;AACrF,SAAO,CAAC,UAAmB;AACzB,QAAI;AACF,YAAM,SAAS,kBAAkB,WAAW;AAC5C,kBAAY,QAAQ,OAAO,OAAuB,aAAa;AAAA,IACjE,QAAQ;AAAA,IAER;AAAA,EACF;AACF;AAsBO,SAAS,cAEd,UAAgB;AAChB,UAAQ,CAAC,OAAY,SAAc,YAAkB;AACnD,UAAM,SAAS,kBAAkB,WAAW;AAC5C,QAAI;AACJ,QAAI;AACJ,QAAI;AACF,YAAM,QAAuB,EAAE,WAAW,oBAAI,IAAI,GAAG,eAAe,CAAC,GAAG,WAAW,EAAE;AACrF,YAAM,gBAAgB,iBAAiB,OAAO;AAE9C,UAAI,SAAS,yBAAyB;AACtC,UAAI,CAAC,kBAAM,QAAQ,MAAM,GAAG,YAAY,GAAG;AACzC,eAAO,OAAO;AAAA,UACZ;AAAA,UACA,EAAE,YAAY,EAAE,sBAAsB,WAAW,EAAE;AAAA,UACnD;AAAA,QACF;AACA,iBAAS,kBAAM,QAAQ,QAAQ,IAAI;AACnC,cAAM,YAAY,MAAM,cAAc,SAClC,cAAc,EAAE,UAAU,MAAM,cAAc,CAAC,IAC/C;AACJ,YAAI,UAAW,MAAK,aAAa,eAAe,SAAS;AAAA,MAC3D;AACA,YAAM,UAAU;AAEhB,YAAM,YAAY,QAAQ,OAAO;AAAA,QAC/B,MAAM;AAAA,QACN,OAAO,OAAO,MAAM,OAAO;AAAA,QAC3B,UAAU,OAAO;AAAA,MACnB,CAAC;AAAA,IACH,QAAQ;AAAA,IAER;AAEA,QAAI;AACJ,QAAI;AACF,iBAAW,SAAS,OAAO,SAAS,OAAO;AAAA,IAC7C,SAAS,KAAK;AACZ,yBAAmB,KAAK,MAAM,GAAG;AACjC,YAAM;AAAA,IACR;AAMA,QAAI,WAAW,QAAQ,GAAG;AACxB,aAAO,SAAS;AAAA,QACd,CAAC,WAAgB,mBAAmB,QAAQ,KAAK,IAAI;AAAA,QACrD,CAAC,QAAiB;AAChB,6BAAmB,KAAK,MAAM,GAAG;AACjC,gBAAM;AAAA,QACR;AAAA,MACF;AAAA,IACF;AACA,WAAO,mBAAmB,UAAU,KAAK,IAAI;AAAA,EAC/C;AACF;AAEA,SAAS,mBACP,QACA,KACA,MACK;AACL,MAAI,CAAC,OAAO,CAAC,UAAU,OAAO,OAAO,WAAW,YAAY;AAC1D,oBAAgB,IAAI;AACpB,WAAO;AAAA,EACT;AAEA,sBAAoB,QAAQ,GAAG;AAC/B,SAAO,OAAO,EAAE;AAAA,IACd,CAAC,QAAa;AACZ,YAAM,UAAU,OAAO,EAAE,MAAM,YAAY;AAC3C,oBAAc,KAAK,OAAO;AAC1B,sBAAgB,MAAM,OAAO;AAAA,IAC/B;AAAA,IACA,CAAC,QAAiB,mBAAmB,KAAK,MAAM,GAAG;AAAA,EACrD;AACA,SAAO;AACT;AAGA,SAAS,oBAAoB,QAAa,KAAwB;AAChE,QAAM,WAAW,SAAS,OAAO,aAAa;AAC9C,MAAI,OAAO,aAAa,cAAc,SAAS,mBAAoB;AACnE,QAAM,WAAW,WAAyC;AACxD,UAAM,WAAW,SAAS,KAAK,IAAI;AACnC,WAAO;AAAA,MACL,MAAM,UAAU,SAA2B;AACzC,cAAM,OAAO,MAAM,SAAS,KAAK,GAAI,IAAW;AAChD,YAAI,CAAC,KAAK,QAAQ,eAAe,KAAK,OAAO,IAAI,EAAG,sBAAqB,GAAG;AAC5E,eAAO;AAAA,MACT;AAAA,MACA,QAAQ,SAAS,QAAQ,KAAK,QAAQ;AAAA,MACtC,OAAO,SAAS,OAAO,KAAK,QAAQ;AAAA,IACtC;AAAA,EACF;AACA,SAAO,eAAe,UAAU,sBAAsB,EAAE,OAAO,KAAK,CAAC;AACrE,MAAI;AACF,WAAO,OAAO,aAAa,IAAI;AAAA,EACjC,QAAQ;AAAA,EAER;AACF;AAEA,SAAS,qBAAqB,KAAwB;AACpD,MAAI,KAAK,aAAa,6BAA6B,IAAI;AACvD,MAAI,IAAI,WAAW,OAAW;AAC9B,MAAI,SACF,IAAI,qBAAqB,SACrB,KAAK,IAAI,IAAI,IAAI,mBACjB,MAAM,IAAI,IAAI;AACtB;AAEA,SAAS,mBACP,KACA,MACA,KACM;AACN,QAAM,UAAU,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAC/D,MAAI;AACF,SAAK,KAAK,aAAa,gBAAgB,WAAW,OAAO,EAAE;AAC3D,SAAK,KAAK,aAAa,0BAA0B,OAAO;AACxD,SAAK,KAAK,UAAU,EAAE,MAAM,2BAAe,OAAO,QAAQ,CAAC;AAC3D,SAAK,KAAK,IAAI;AAAA,EAChB,QAAQ;AAAA,EAER;AACA,kBAAgB,MAAM,QAAW,OAAO;AAC1C;AAEA,SAAS,WAAW,OAAuC;AACzD,SAAO,SAAS,QAAQ,OAAO,MAAM,SAAS;AAChD;AAGA,SAAS,gBAAgB,MAAwB,KAA0B,OAAsB;AAC/F,MAAI,CAAC,KAAM;AACX,MAAI;AACF,QAAI,KAAK;AACP,YAAM,EAAE,MAAM,UAAU,IAAI,sBAAsB,IAAI,OAAO;AAC7D,YAAM,MACJ,QACA,UAAU,IAAI,CAAC,OAAO,GAAG,GAAG,IAAI,IAAI,cAAc,GAAG,SAAS,CAAC,GAAG,EAAE,KAAK,IAAI,KAC7E,gBAAgB,GAAG;AACrB,UAAI,IAAK,MAAK,aAAa,gBAAgB,GAAG;AAC9C,4BAAsB,MAAM,GAAG;AAAA,IACjC,WAAW,OAAO;AAChB,WAAK,aAAa,gBAAgB,WAAW,KAAK,EAAE;AACpD,WAAK,aAAa,0BAA0B,KAAK;AACjD,WAAK,UAAU,EAAE,MAAM,2BAAe,OAAO,SAAS,MAAM,CAAC;AAAA,IAC/D;AACA,SAAK,IAAI;AAAA,EACX,QAAQ;AAAA,EAER;AACF;AAGA,SAAS,eAAe,UAAuE;AAC7F,MAAI,CAAC,MAAM,QAAQ,QAAQ,EAAG,QAAO,CAAC;AACtC,QAAM,OAAiD,CAAC;AACxD,aAAW,KAAK,UAAU;AACxB,UAAM,UAAU,YAAY,CAAC;AAC7B,QAAI,CAAC,QAAS;AACd,SAAK,KAAK,EAAE,MAAM,GAAG,SAAS,eAAe,SAAS,OAAO,GAAG,QAAQ,MAAM,GAAG,QAAQ,CAAC;AAAA,EAC5F;AACA,SAAO;AACT;AAGA,SAAS,iBAAiB,SAAwD;AAChF,QAAM,OAAiD,CAAC;AACxD,MAAI,OAAO,SAAS,iBAAiB,YAAY,QAAQ,cAAc;AACrE,SAAK,KAAK,EAAE,MAAM,UAAU,SAAS,QAAQ,aAAa,CAAC;AAAA,EAC7D;AACA,MAAI,MAAM,QAAQ,SAAS,QAAQ,GAAG;AACpC,eAAW,KAAK,QAAQ,UAAU;AAChC,YAAM,UAAU,YAAY,CAAC;AAC7B,UAAI,QAAS,MAAK,KAAK,EAAE,MAAM,OAAO,GAAG,QAAQ,MAAM,GAAG,QAAQ,CAAC;AAAA,IACrE;AAAA,EACF;AACA,SAAO;AACT;AAEA,SAAS,YACP,QACA,OACA,OACA,eACM;AACN,UAAQ,MAAM,MAAM;AAAA,IAClB,KAAK,eAAe;AAElB,YAAM,OAAO,yBAAyB;AACtC,YAAM,OAAO,OAAO;AAAA,QAClB;AAAA,QACA,EAAE,YAAY,EAAE,sBAAsB,QAAQ,EAAE;AAAA,QAChD;AAAA,MACF;AACA,YAAM,YAAY;AAClB,YAAM,WAAW,kBAAM,QAAQ,MAAM,IAAI;AAIzC,YAAM,gBAAgB,eAAe,gBAAgB,CAAC;AACtD,YAAM,YAAY;AAClB,YAAM,WAAW;AACjB,YAAM,WAAW;AACjB;AAAA,IACF;AAAA,IAEA,KAAK,cAAc;AAGjB,YAAM,SAAS,MAAM,YAAY,yBAAyB;AAC1D,YAAM,aAAa;AAKnB,YAAM,UAAU,MAAM,cAAc,MAAM,cAAc,SAAS,CAAC;AAClE,YAAM,aACJ,YAAY,QAAQ,SAAS,UAAU,QAAQ,SAAS,UAAU,QAAQ,UAAU;AACtF,YAAM,OAAO,OAAO;AAAA,QAClB,iBAAiB,MAAM,SAAS;AAAA,QAChC;AAAA,UACE,YAAY;AAAA,YACV,sBAAsB;AAAA,YACtB,6BAA6B,MAAM;AAAA,YACnC,GAAI,aAAa,EAAE,eAAe,WAAW,IAAI,CAAC;AAAA,UACpD;AAAA,QACF;AAAA,QACA;AAAA,MACF;AACA,YAAM,WAAW;AACjB,YAAM,UAAU,kBAAM,QAAQ,QAAQ,IAAI;AAC1C,YAAM,eAAe,CAAC,CAAC;AACvB,YAAM,mBAAmB,KAAK,IAAI;AAClC;AAAA,IACF;AAAA,IAEA,KAAK,YAAY;AACf,UAAI,CAAC,MAAM,SAAU;AACrB,YAAM,MAAM,MAAM;AAClB,YAAM,EAAE,MAAM,UAAU,IAAI,sBAAsB,KAAK,OAAO;AAI9D,YAAM,MACJ,QACA,UAAU,IAAI,CAAC,OAAO,GAAG,GAAG,IAAI,IAAI,cAAc,GAAG,SAAS,CAAC,GAAG,EAAE,KAAK,IAAI,KAC7E,gBAAgB,GAAG;AACrB,UAAI,IAAK,OAAM,SAAS,aAAa,gBAAgB,GAAG;AACxD,UAAI,MAAM,QAAQ,MAAM,WAAW,KAAK,MAAM,YAAY,QAAQ;AAChE,cAAM,SAAS,aAAa,oCAAoC,MAAM,YAAY,MAAM;AAAA,MAC1F;AACA,4BAAsB,MAAM,UAAU,GAAG;AACzC,YAAM,SAAS,IAAI;AACnB,YAAM,WAAW;AACjB,YAAM,UAAU;AAChB,YAAM,eAAe;AACrB,YAAM,mBAAmB;AACzB;AAAA,IACF;AAAA,IAEA,KAAK,iBAAiB;AACpB,YAAM,MAAM,MAAM;AAClB,UAAI,CAAC,OAAO,IAAI,SAAS,YAAa;AAGtC,YAAM,MAAM,YAAY,QAAQ,OAAO,GAAG;AAC1C;AAAA,IACF;AAAA,IAEA,KAAK,kBAAkB;AAErB,YAAM,MAAM,MAAM;AAClB,UAAI,CAAC,IAAK;AACV,UAAI,KAAK,aAAa,6BAA6B,IAAI;AACvD,UAAI,IAAI,WAAW,UAAa,eAAe,MAAM,uBAAuB,IAAI,GAAG;AAGjF,YAAI,SACF,IAAI,qBAAqB,SACrB,KAAK,IAAI,IAAI,IAAI,mBACjB,MAAM,IAAI,IAAI;AAAA,MACtB;AACA;AAAA,IACF;AAAA,IAEA,KAAK,eAAe;AAClB,YAAM,MAAM,MAAM;AAClB,UAAI,CAAC,IAAK;AACV,UAAI,IAAI,SAAS,aAAa;AAG5B,cAAM,MAAM,MAAM,OAAO,YAAY,QAAQ,OAAO,GAAG;AACvD,cAAM,MAAM;AACZ,cAAM,WAAW,cAAc,KAAK,GAAyB,KAAK,MAAM;AACxE,cAAM,EAAE,KAAK,IAAI,sBAAsB,IAAI,OAAO;AAClD,YAAI,KAAM,OAAM,cAAc,KAAK,EAAE,MAAM,aAAa,SAAS,KAAK,CAAC;AAAA,MACzE,OAAO;AAEL,cAAM,OAAO,IAAI,SAAS,eAAe,SAAS,OAAO,IAAI,QAAQ,MAAM;AAC3E,cAAM,UAAU,YAAY,GAAG;AAC/B,YAAI,SAAS;AACX,gBAAM,cAAc,KAAK,EAAE,MAAM,QAAQ,CAAC;AAC1C,cAAI,SAAS,UAAU,MAAM,aAAa,OAAW,OAAM,WAAW;AAGtE,cAAI,MAAM,YAAY,CAAC,MAAM,cAAc;AACzC,kBAAM,SAAS,aAAa,eAAe,OAAO;AAClD,kBAAM,eAAe;AAAA,UACvB;AAAA,QACF;AAAA,MACF;AACA;AAAA,IACF;AAAA,IAEA,KAAK,wBAAwB;AAC3B,YAAM,SAAS,MAAM,WAAW,MAAM,YAAY,yBAAyB;AAC3E,YAAM,OAAO,OAAO;AAAA,QAClB,iBAAiB,MAAM,YAAY,MAAM;AAAA,QACzC;AAAA,UACE,YAAY;AAAA,YACV,sBAAsB;AAAA,YACtB,GAAI,MAAM,WAAW,EAAE,sBAAsB,OAAO,MAAM,QAAQ,EAAE,IAAI,CAAC;AAAA,YACzE,GAAI,MAAM,aAAa,EAAE,yBAAyB,OAAO,MAAM,UAAU,EAAE,IAAI,CAAC;AAAA,YAChF,GAAI,MAAM,SAAS,SACf,EAAE,eAAe,cAAc,MAAM,IAAI,EAAE,IAC3C,CAAC;AAAA,UACP;AAAA,QACF;AAAA,QACA;AAAA,MACF;AACA,UAAI,MAAM,WAAY,OAAM,UAAU,IAAI,MAAM,YAAY,IAAI;AAChE;AAAA,IACF;AAAA,IAEA,KAAK,yBAAyB;AAG5B,YAAM,OAAO,MAAM,aAAa,MAAM,UAAU,IAAI,MAAM,UAAU,IAAI;AACxE,UAAI,CAAC,KAAM;AACX,WAAK,aAAa,8BAA8B,IAAI;AACpD;AAAA,IACF;AAAA,IAEA,KAAK,sBAAsB;AACzB,YAAM,OAAO,MAAM,aAAa,MAAM,UAAU,IAAI,MAAM,UAAU,IAAI;AACxE,UAAI,CAAC,KAAM;AACX,UAAI,MAAM,WAAW,QAAW;AAC9B,aAAK,aAAa,gBAAgB,cAAc,MAAM,MAAM,CAAC;AAAA,MAC/D;AACA,UAAI,MAAM,SAAS;AACjB,aAAK,UAAU,EAAE,MAAM,2BAAe,OAAO,SAAS,cAAc,MAAM,MAAM,EAAE,CAAC;AACnF,aAAK,aAAa,0BAA0B,IAAI;AAAA,MAClD,OAAO;AACL,aAAK,UAAU,EAAE,MAAM,2BAAe,GAAG,CAAC;AAAA,MAC5C;AACA,WAAK,IAAI;AACT,UAAI,MAAM,WAAY,OAAM,UAAU,OAAO,MAAM,UAAU;AAC7D;AAAA,IACF;AAAA,IAEA,KAAK,aAAa;AAGhB,iBAAW,MAAM,MAAM,UAAU,OAAO,GAAG;AACzC,YAAI;AACF,aAAG,UAAU,EAAE,MAAM,2BAAe,OAAO,SAAS,kCAAkC,CAAC;AACvF,aAAG,IAAI;AAAA,QACT,QAAQ;AAAA,QAER;AAAA,MACF;AACA,YAAM,UAAU,MAAM;AAEtB,UAAI,MAAM,KAAK;AACb,YAAI;AACF,gBAAM,IAAI,KAAK,aAAa,gBAAgB,mCAAmC;AAC/E,gBAAM,IAAI,KAAK,UAAU,EAAE,MAAM,2BAAe,OAAO,SAAS,uBAAuB,CAAC;AACxF,gBAAM,IAAI,KAAK,IAAI;AAAA,QACrB,QAAQ;AAAA,QAER;AACA,cAAM,MAAM;AAAA,MACd;AAEA,UAAI,MAAM,UAAU;AAClB,YAAI;AACF,gBAAM,SAAS,IAAI;AAAA,QACrB,QAAQ;AAAA,QAER;AACA,cAAM,WAAW;AACjB,cAAM,UAAU;AAChB,cAAM,mBAAmB;AAAA,MAC3B;AAEA,UAAI,MAAM,WAAW;AAInB,cAAM,QAAQ,MAAM,YAAY,iBAAiB,MAAM,QAAQ,KAAK,iBAAiB,gBAAgB,CAAC;AACtG,YAAI,MAAO,OAAM,UAAU,aAAa,eAAe,KAAK;AAI5D,cAAM,YAAY,kBAAkB,MAAM,QAAQ;AAClD,cAAM,MAAM,MAAM,YAAY,kBAAkB,MAAM,QAAQ;AAC9D,YAAI,WAAW;AACb,gBAAM,UAAU,aAAa,gBAAgB,SAAS;AAAA,QACxD,WAAW,KAAK;AACd,gBAAM,UAAU,aAAa,gBAAgB,IAAI,IAAI,UAAU,IAAI,IAAI,UAAU,IAAI,IAAI,OAAO,KAAK,EAAE,EAAE;AAAA,QAC3G;AAEA,YAAI,KAAK;AACP,gBAAM,UAAU,aAAa,8BAA8B,IAAI,UAAU;AACzE,cAAI,IAAI,QAAS,OAAM,UAAU,aAAa,0BAA0B,IAAI,OAAO;AACnF,gBAAM,UAAU,UAAU,EAAE,MAAM,2BAAe,OAAO,SAAS,IAAI,WAAW,IAAI,WAAW,CAAC;AAAA,QAClG,OAAO;AACL,gBAAM,UAAU,UAAU,EAAE,MAAM,2BAAe,GAAG,CAAC;AAAA,QACvD;AACA,cAAM,UAAU,IAAI;AACpB,cAAM,YAAY;AAClB,cAAM,WAAW;AAAA,MACnB;AACA;AAAA,IACF;AAAA,IAEA;AACE;AAAA,EACJ;AACF;AAGA,SAAS,YACP,QACA,OACA,KACa;AACb,QAAM,SAAS,MAAM,WAAW,MAAM,YAAY,yBAAyB;AAM3E,QAAM,YAAY,cAAc,KAAK,MAAM,gBAAgB;AAC3D,QAAM,OAAO,OAAO;AAAA,IAClB,gBAAgB,IAAI,SAAS,OAAO;AAAA,IACpC;AAAA,MACE,GAAI,cAAc,SAAY,EAAE,UAAU,IAAI,CAAC;AAAA,MAC/C,YAAY;AAAA,QACV,sBAAsB;AAAA;AAAA,QAEtB,6BAA6B;AAAA,QAC7B,GAAI,IAAI,QAAQ,EAAE,2BAA2B,OAAO,IAAI,KAAK,EAAE,IAAI,CAAC;AAAA,QACpE,GAAI,IAAI,WAAW,EAAE,yBAAyB,OAAO,IAAI,QAAQ,EAAE,IAAI,CAAC;AAAA,MAC1E;AAAA,IACF;AAAA,IACA;AAAA,EACF;AACA,SAAO;AAAA,IACL;AAAA,IACA,SAAS,MAAM;AAAA,IACf,kBAAkB;AAAA,IAClB,eAAe,MAAM,cAAc,MAAM;AAAA,EAC3C;AACF;AASA,SAAS,cAAc,KAAyB,WAAmD;AACjG,QAAM,KAAK,IAAI;AACf,MAAI,OAAO,OAAO,YAAY,CAAC,OAAO,SAAS,EAAE,EAAG,QAAO;AAC3D,QAAM,MAAM,KAAK,IAAI;AACrB,QAAM,MAAM,MAAM;AAClB,MAAI,MAAM,KAAK,MAAM,gBAAiB,QAAO;AAC7C,SAAO,cAAc,SAAY,KAAK,IAAI,IAAI,SAAS,IAAI;AAC7D;AAGA,IAAM,kBAAkB,KAAK;AAG7B,SAAS,gBAAgB,KAA6C;AACpE,QAAM,SAAS,KAAK;AACpB,MAAI,WAAW,aAAa,WAAW,QAAS,QAAO;AACvD,SAAO,IAAI,MAAM,IAAI,KAAK,eAAe,IAAI,IAAI,YAAY,KAAK,EAAE;AACtE;AAGA,SAAS,sBAAsB,MAAY,KAA2C;AACpF,QAAM,SAAS,KAAK;AACpB,MAAI,WAAW,aAAa,WAAW,SAAS;AAC9C,SAAK,UAAU,EAAE,MAAM,2BAAe,OAAO,SAAS,KAAK,gBAAgB,OAAO,CAAC;AAAA,EACrF,OAAO;AACL,SAAK,UAAU,EAAE,MAAM,2BAAe,GAAG,CAAC;AAAA,EAC5C;AACF;AAGA,SAAS,eAAe,MAAmC;AACzD,SAAO,SAAS,gBAAgB,SAAS,oBAAoB,SAAS;AACxE;AAEA,SAAS,QAAgB;AAEvB,QAAM,IAAK,WAAmB;AAC9B,SAAO,OAAO,GAAG,QAAQ,aAAa,EAAE,IAAI,IAAI,KAAK,IAAI;AAC3D;AAGA,SAAS,cAAc,QAAyB;AAC9C,MAAI,CAAC,UAAU,OAAO,WAAW,SAAU,QAAO;AAClD,QAAM,UAAW,OAAe;AAChC,MAAI,MAAM,QAAQ,OAAO,GAAG;AAC1B,UAAM,OAAO,QACV,IAAI,CAAC,MAAY,OAAO,GAAG,SAAS,WAAW,EAAE,OAAO,EAAG,EAC3D,OAAO,OAAO,EACd,KAAK,GAAG,EACR,KAAK;AACR,QAAI,KAAM,QAAO;AAAA,EACnB;AACA,SAAO;AACT;AAGA,SAAS,iBAAiB,UAAiD;AACzE,MAAI,CAAC,MAAM,QAAQ,QAAQ,EAAG,QAAO;AACrC,WAAS,IAAI,SAAS,SAAS,GAAG,KAAK,GAAG,KAAK;AAC7C,UAAM,IAAI,SAAS,CAAC;AACpB,QAAI,KAAK,EAAE,SAAS,QAAQ;AAC1B,YAAM,OAAO,YAAY,CAAC;AAC1B,UAAI,KAAM,QAAO;AAAA,IACnB;AAAA,EACF;AACA,SAAO;AACT;AAGA,SAAS,kBACP,UACsD;AACtD,MAAI,CAAC,MAAM,QAAQ,QAAQ,EAAG,QAAO;AACrC,WAAS,IAAI,SAAS,SAAS,GAAG,KAAK,GAAG,KAAK;AAC7C,UAAM,IAAI,SAAS,CAAC;AACpB,QAAI,KAAK,EAAE,SAAS,aAAa;AAC/B,UAAI,EAAE,eAAe,aAAa,EAAE,eAAe,SAAS;AAC1D,eAAO,EAAE,YAAY,EAAE,YAAY,SAAS,EAAE,aAAa;AAAA,MAC7D;AACA,aAAO;AAAA,IACT;AAAA,EACF;AACA,SAAO;AACT;AASA,SAAS,cACP,KACA,KACA,SACsD;AACtD,QAAM,OAAO,IAAI;AAEjB,MAAI,IAAI,MAAO,MAAK,aAAa,2BAA2B,OAAO,IAAI,KAAK,CAAC;AAC7E,MAAI,IAAI,SAAU,MAAK,aAAa,yBAAyB,OAAO,IAAI,QAAQ,CAAC;AAEjF,MAAI,IAAI,cAAe,MAAK,aAAa,+BAA+B,OAAO,IAAI,aAAa,CAAC;AACjG,MAAI,IAAI,IAAK,MAAK,aAAa,oBAAoB,OAAO,IAAI,GAAG,CAAC;AAClE,MAAI,IAAI,WAAY,MAAK,aAAa,4BAA4B,OAAO,IAAI,UAAU,CAAC;AAIxF,QAAM,SAAS,IAAI;AACnB,MAAI,OAAO,QAAQ;AACjB,WAAO,QAAQ,CAAC,GAAG,MAAM;AACvB,WAAK,aAAa,+BAA+B,CAAC,SAAS,EAAE,IAAI;AACjE,WAAK,aAAa,+BAA+B,CAAC,YAAY,EAAE,OAAO;AAAA,IACzE,CAAC;AACD,UAAM,SAAS,cAAc,EAAE,UAAU,OAAO,CAAC;AACjD,SAAK,aAAa,sBAAsB,MAAM;AAC9C,SAAK,aAAa,eAAe,MAAM;AAAA,EACzC;AAEA,QAAM,EAAE,MAAM,UAAU,IAAI,sBAAsB,IAAI,OAAO;AAG7D,QAAM,UACJ,QACA,UAAU,IAAI,CAAC,OAAO,GAAG,GAAG,IAAI,IAAI,cAAc,GAAG,SAAS,CAAC,GAAG,EAAE,KAAK,IAAI,KAC7E,gBAAgB,GAAG;AACrB,MAAI,WAAW,UAAU,QAAQ;AAC/B,SAAK,aAAa,uCAAuC,WAAW;AACpE,SAAK,aAAa,0CAA0C,WAAW,EAAE;AACzE,UAAM,UAAmC,EAAE,MAAM,aAAa,SAAS,WAAW,GAAG;AACrF,QAAI,UAAU,QAAQ;AACpB,cAAQ,aAAa,UAAU,IAAI,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,WAAW,GAAG,UAAU,EAAE;AACvF,gBAAU,QAAQ,CAAC,IAAI,MAAM;AAC3B,YAAI,GAAG,KAAM,MAAK,aAAa,2BAA2B,CAAC,SAAS,GAAG,IAAI;AAC3E,YAAI,GAAG,cAAc;AACnB,eAAK,aAAa,2BAA2B,CAAC,cAAc,cAAc,GAAG,SAAS,CAAC;AACzF,YAAI,GAAG,GAAI,MAAK,aAAa,2BAA2B,CAAC,OAAO,OAAO,GAAG,EAAE,CAAC;AAAA,MAC/E,CAAC;AAAA,IACH;AACA,SAAK,aAAa,uBAAuB,cAAc,OAAO,CAAC;AAC/D,SAAK,aAAa,gBAAgB,WAAW,EAAE;AAAA,EACjD;AAEA,QAAM,QAAQ,IAAI;AAClB,MAAI,OAAO;AACT,QAAI,MAAM,SAAS,KAAM,MAAK,aAAa,mCAAmC,MAAM,KAAK;AACzF,QAAI,MAAM,UAAU,KAAM,MAAK,aAAa,uCAAuC,MAAM,MAAM;AAC/F,UAAM,QAAQ,MAAM,gBAAiB,MAAM,SAAS,MAAM,MAAM,UAAU;AAC1E,QAAI,MAAO,MAAK,aAAa,kCAAkC,KAAK;AACpE,QAAI,MAAM,UAAW,MAAK,aAAa,uCAAuC,MAAM,SAAS;AAC7F,QAAI,MAAM,WAAY,MAAK,aAAa,wCAAwC,MAAM,UAAU;AAIhG,UAAM,OAAO,MAAM;AACnB,QAAI,MAAM;AACR,YAAM,YACJ,KAAK,SACL,CAAC,KAAK,OAAO,KAAK,QAAQ,YAAY,IAAI,GAAG,KAAK,UAAU,EAAE;AAAA,QAC5D,CAAC,KAAK,MAAM,OAAO,OAAO,MAAM,WAAW,IAAI;AAAA,QAC/C;AAAA,MACF;AACF,UAAI,OAAO,cAAc,YAAY,YAAY,GAAG;AAClD,aAAK,aAAa,yBAAyB,SAAS;AAAA,MACtD;AACA,UAAI,OAAO,KAAK,UAAU,SAAU,MAAK,aAAa,4BAA4B,KAAK,KAAK;AAC5F,UAAI,OAAO,KAAK,WAAW,SAAU,MAAK,aAAa,gCAAgC,KAAK,MAAM;AAAA,IACpG;AAAA,EACF;AAEA,MAAI,IAAI,WAAW,QAAW;AAC5B,SAAK,aAAa,gCAAgC,KAAK,MAAM,IAAI,MAAM,CAAC;AAAA,EAC1E;AAEA,MAAI,IAAI,aAAc,MAAK,aAAa,0BAA0B,OAAO,IAAI,YAAY,CAAC;AAC1F,wBAAsB,MAAM,GAAG;AAC/B,OAAK,IAAI,OAAO;AAIhB,SAAO,IAAI,eAAe,aAAa,IAAI,eAAe,UACtD,EAAE,YAAY,IAAI,YAAY,SAAS,IAAI,aAAa,IACxD;AACN;AAGA,SAAS,YAAY,MAA+C;AAClE,SAAO,OAAO,KAAK,cAAc,WAAW,KAAK,YAAY,KAAK;AACpE;AAMA,SAAS,sBACP,SAC2C;AAC3C,QAAM,QAAkB,CAAC;AACzB,QAAM,YAA0B,CAAC;AACjC,MAAI,MAAM,QAAQ,OAAO,GAAG;AAC1B,eAAW,SAAS,SAAS;AAC3B,UAAI,CAAC,SAAS,OAAO,UAAU,SAAU;AACzC,UAAI,MAAM,SAAS,UAAU,OAAO,MAAM,SAAS,SAAU,OAAM,KAAK,MAAM,IAAI;AAAA,eACzE,MAAM,SAAS;AACtB,kBAAU,KAAK,KAA8B;AAAA,IAEjD;AAAA,EACF,WAAW,OAAO,YAAY,UAAU;AACtC,UAAM,KAAK,OAAO;AAAA,EACpB;AACA,SAAO,EAAE,MAAM,MAAM,KAAK,EAAE,GAAG,UAAU;AAC3C;AAGA,SAAS,YAAY,KAAkB;AACrC,MAAI,CAAC,IAAK,QAAO;AACjB,QAAM,IAAI,IAAI;AACd,MAAI,OAAO,MAAM,SAAU,QAAO;AAClC,MAAI,CAAC,MAAM,QAAQ,CAAC,EAAG,QAAO;AAC9B,QAAM,QAAkB,CAAC;AACzB,aAAW,SAAS,GAAG;AACrB,QAAI,OAAO,UAAU,SAAU,OAAM,KAAK,KAAK;AAAA,aACtC,SAAS,OAAO,UAAU,UAAU;AAC3C,UAAI,OAAO,MAAM,SAAS,SAAU,OAAM,KAAK,MAAM,IAAI;AAAA,eAChD,MAAM,SAAS,WAAY,OAAM,KAAK,GAAG,MAAM,QAAQ,MAAM,IAAI,cAAc,MAAM,SAAS,CAAC,GAAG;AAAA,IAC7G;AAAA,EACF;AACA,SAAO,MAAM,KAAK,EAAE;AACtB;AAEA,SAAS,kBAAkB,UAAqC;AAC9D,MAAI,CAAC,MAAM,QAAQ,QAAQ,EAAG,QAAO;AACrC,WAAS,IAAI,SAAS,SAAS,GAAG,KAAK,GAAG,KAAK;AAC7C,UAAM,IAAI,SAAS,CAAC;AACpB,QAAI,KAAK,EAAE,SAAS,aAAa;AAC/B,YAAM,EAAE,KAAK,IAAI,sBAAsB,EAAE,OAAO;AAChD,UAAI,KAAM,QAAO;AAAA,IACnB;AAAA,EACF;AACA,SAAO;AACT;AAEA,SAAS,YAAY,GAAc;AACjC,MAAI;AACF,WAAO,eAAe,GAAG,YAAY,EAAE,OAAO,MAAM,YAAY,OAAO,cAAc,KAAK,CAAC;AAAA,EAC7F,QAAQ;AACN,MAAE,UAAU,IAAI;AAAA,EAClB;AACF;AAEA,SAAS,cAAc,OAAwB;AAC7C,MAAI,OAAO,UAAU,SAAU,QAAO;AACtC,MAAI;AACF,WAAO,KAAK,UAAU,KAAK,KAAK;AAAA,EAClC,QAAQ;AACN,WAAO;AAAA,EACT;AACF;","names":["import_api","import_node_async_hooks","neatlogsGlobal","otelTrace"]}
|
|
1
|
+
{"version":3,"sources":["../src/pi-agent.ts","../src/core/provider.ts","../src/core/active-client.ts"],"sourcesContent":["/**\n * Neatlogs Pi Agent integration.\n *\n * Usage:\n * import { init } from 'neatlogs';\n * import { piAgentHooks } from 'neatlogs/pi-agent';\n * import { Agent } from '@earendil-works/pi-agent-core';\n *\n * await init({ apiKey, workflowName });\n * const agent = piAgentHooks(new Agent({ initialState: { systemPrompt, model } }));\n * await agent.prompt('Hello');\n *\n * Pi Agent's `Agent` and `AgentHarness` expose a first-class\n * `subscribe(listener)` API and emit\n * AgentEvents for its run lifecycle (message_*, tool_execution_*, turn_*,\n * agent_*). It does NOT emit its own OpenTelemetry spans — so we LISTEN to those\n * events (no monkey-patching) and translate them into neatlogs OTel spans:\n *\n * AGENT agent run (agent_start → agent_end)\n * ↳ CHAIN turn (turn_start → turn_end)\n * ↳ LLM assistant message (message_start → message_end)\n * ↳ TOOL tool call (tool_execution_start → tool_execution_end)\n *\n * The AGENT span is opened as the active span so the turn/LLM/TOOL children nest\n * under it (and under any user @span / trace() block active when prompt() is\n * called).\n *\n * The LLM span spans the REAL model call: it opens on the assistant\n * `message_start` and closes on `message_end`, so its duration is the provider\n * latency (opening it at message_end only would report ~0ms). Streaming is the\n * default in Pi, so we also record time-to-first-token from the first content\n * delta and carry pi-ai's exact per-call `usage.cost` through instead of letting\n * the backend re-derive it from tokens.\n *\n * For the low-level functional API (`agentLoop`/`agentLoopContinue`/\n * `runAgentLoop`, which have no `subscribe()`), use `tracePiAgentEvents()` to\n * wrap the event sink / iterate the event stream. One layer below that — a bare\n * `streamFn` such as `streamProxy` called outside any loop — use\n * `tracePiStream()`. Both are documented below.\n */\n\nimport {\n trace,\n SpanStatusCode,\n type Span,\n type Context,\n} from '@opentelemetry/api';\nimport { getNeatlogsTracer, getNeatlogsParentContext } from './core/provider.js';\n\nconst TRACER_NAME = 'neatlogs.pi-agent';\nconst PATCH_FLAG = '_neatlogs_patched';\nconst HARNESS_METHOD_FLAG = '_neatlogs_harness_methods_patched';\n\n// Minimal structural types for the Pi Agent event surface (we duck-type — no\n// hard dependency on the pi-agent-core package).\ninterface PiUsage {\n input?: number;\n output?: number;\n cacheRead?: number;\n cacheWrite?: number;\n totalTokens?: number;\n /** pi-ai computes exact per-call cost — carry it through rather than re-deriving. */\n cost?: {\n input?: number;\n output?: number;\n cacheRead?: number;\n cacheWrite?: number;\n total?: number;\n };\n}\ninterface PiToolCall {\n type: 'toolCall';\n id?: string;\n name?: string;\n arguments?: Record<string, unknown>;\n}\ninterface PiAssistantMessage {\n role: 'assistant';\n content?: Array<{ type: string; text?: string; name?: string; arguments?: unknown }>;\n model?: string;\n responseModel?: string;\n provider?: string;\n api?: string;\n usage?: PiUsage;\n stopReason?: string;\n errorMessage?: string;\n /** Epoch ms, stamped by pi when it begins the model-call step. */\n timestamp?: number;\n}\ninterface PiAgentEvent {\n type: string;\n message?: any;\n messages?: any[];\n toolResults?: any[];\n assistantMessageEvent?: { type?: string };\n toolCallId?: string;\n toolName?: string;\n args?: unknown;\n result?: unknown;\n partialResult?: unknown;\n isError?: boolean;\n}\n\n/** An in-flight assistant (LLM) span: opened at message_start, closed at message_end. */\ninterface LlmInFlight {\n span: Span;\n startHr: number;\n /** Epoch ms the span was backdated to (pi's own call-start), when usable. */\n callStartEpochMs?: number;\n /** ms from span start to the first content delta (TTFT). */\n ttftMs?: number;\n /** Input snapshot taken at message_start, before the response mutates state. */\n inputMessages: Array<{ role: string; content: string }>;\n}\n\ninterface PerAgentState {\n agentSpan?: Span;\n agentCtx?: Context;\n /** Current turn (CHAIN) span — turn_start → turn_end. */\n turnSpan?: Span;\n turnCtx?: Context;\n turnIndex: number;\n /** Whether the current turn span already got its input stamped. */\n turnHasInput?: boolean;\n /** When the turn span was opened — a child LLM span may not start before it. */\n turnStartEpochMs?: number;\n /** The assistant LLM span currently streaming, if any. */\n llm?: LlmInFlight;\n toolSpans: Map<string, Span>;\n /** Running conversation (system/user/tool turns) to use as LLM-span input.\n * Pi Agent's assistant message_end carries only the response, not the prompt. */\n inputMessages: Array<{ role: string; content: string }>;\n /** First user message of the CURRENT run, for the AGENT span's input. */\n runInput?: string;\n /** Set when the run ends abnormally (aborted / provider error). */\n runError?: { stopReason: string; message?: string };\n}\n\n/**\n * Subscribe neatlogs tracing to a Pi Agent instance. Returns the same agent\n * (marked so re-subscribing is a no-op). Idempotent per agent.\n */\nexport function piAgentHooks<T extends object>(agent: T): T {\n if (!agent || (agent as any)[PATCH_FLAG]) return agent;\n const a = agent as any;\n if (typeof a.subscribe !== 'function') return agent; // not a Pi Agent — leave alone\n\n const listener = tracePiAgentEvents(() => a.state?.messages);\n a.subscribe((event: PiAgentEvent) => listener(event));\n\n // The maintained Pi package's AgentHarness has two model-producing operations\n // outside the normal AgentEvent loop. Trace those calls explicitly; ordinary\n // prompt/skill/template turns still flow through the subscriber above.\n wrapHarnessModelOperations(a);\n\n markPatched(a);\n return agent;\n}\n\n/**\n * AgentHarness sends ordinary prompts through the same AgentEvent surface as\n * Agent, but `compact()` and summarizing `navigateTree()` call the model outside\n * that loop. Wrap those two public methods so their provider work is visible too.\n */\nfunction wrapHarnessModelOperations(harness: any): void {\n if (harness[HARNESS_METHOD_FLAG]) return;\n const isHarness =\n typeof harness.compact === 'function' &&\n typeof harness.navigateTree === 'function' &&\n typeof harness.getModel === 'function';\n if (!isHarness) return;\n\n patchHarnessMethod(harness, 'compact', (args) => ({ customInstructions: args[0] }));\n patchHarnessMethod(harness, 'navigateTree', (args) => ({ targetId: args[0], options: args[1] }));\n try {\n Object.defineProperty(harness, HARNESS_METHOD_FLAG, { value: true });\n } catch {\n harness[HARNESS_METHOD_FLAG] = true;\n }\n}\n\nfunction patchHarnessMethod(\n harness: any,\n method: 'compact' | 'navigateTree',\n inputOf: (args: any[]) => unknown,\n): void {\n const original = harness[method].bind(harness);\n harness[method] = async (...args: any[]) => {\n const startedAt = Date.now();\n const parent = getNeatlogsParentContext();\n const input = inputOf(args);\n let observedModelCall: boolean | undefined;\n let stopObserving: (() => void) | undefined;\n try {\n stopObserving = harness.subscribe((event: any) => {\n if (method === 'compact' && event?.type === 'session_compact') {\n observedModelCall = !event.fromHook;\n } else if (method === 'navigateTree' && event?.type === 'session_tree') {\n observedModelCall = Boolean(event.summaryEntry) && !event.fromHook;\n }\n });\n } catch {\n // Older compatible harnesses may not allow another listener here.\n }\n let result: any;\n let failure: unknown;\n try {\n result = await original(...args);\n return result;\n } catch (err) {\n failure = err;\n throw err;\n } finally {\n stopObserving?.();\n try {\n emitHarnessOperation(\n method,\n input,\n result,\n failure,\n harness.getModel?.(),\n parent,\n startedAt,\n Date.now(),\n observedModelCall,\n );\n } catch {\n // Observability must not change harness behavior.\n }\n }\n };\n}\n\nfunction emitHarnessOperation(\n method: 'compact' | 'navigateTree',\n input: unknown,\n result: any,\n failure: unknown,\n model: any,\n capturedParent: Context,\n startedAt: number,\n endedAt: number,\n observedModelCall?: boolean,\n): void {\n const tracer = getNeatlogsTracer(TRACER_NAME);\n let parent = capturedParent;\n let root: Span | undefined;\n const inputText = safeStringify(input ?? {});\n const outputText = failure\n ? `[error] ${failure instanceof Error ? failure.message : String(failure)}`\n : harnessOperationOutput(method, result);\n\n if (!trace.getSpan(parent)?.isRecording()) {\n root = tracer.startSpan(\n `pi_agent.harness.${method}`,\n {\n startTime: startedAt,\n attributes: {\n 'neatlogs.span.kind': 'WORKFLOW',\n 'input.value': inputText,\n },\n },\n parent,\n );\n parent = trace.setSpan(parent, root);\n }\n\n const chain = tracer.startSpan(\n `pi_agent.harness.${method}`,\n {\n startTime: startedAt,\n attributes: {\n 'neatlogs.span.kind': 'CHAIN',\n 'neatlogs.pi.operation': method,\n 'input.value': inputText,\n },\n },\n parent,\n );\n const chainCtx = trace.setSpan(parent, chain);\n\n const usage = harnessOperationUsage(method, result);\n const madeModelCall =\n observedModelCall ??\n (failure\n ? isHarnessSummarizationFailure(failure)\n : method === 'compact'\n ? Boolean(result?.usage)\n : Boolean(result?.summaryEntry) && result.summaryEntry.fromHook !== true);\n if (madeModelCall || failure) {\n const llm = openLlmSpan(\n tracer,\n {\n toolSpans: new Map(),\n inputMessages: [{ role: 'user', content: inputText }],\n turnIndex: 0,\n turnCtx: chainCtx,\n turnStartEpochMs: startedAt,\n },\n {\n role: 'assistant',\n model: model?.id ?? model?.model,\n provider: model?.provider,\n timestamp: startedAt,\n },\n );\n if (failure) {\n closeLlmFailure(llm, failure, endedAt);\n } else {\n finishLlmSpan(\n llm,\n {\n role: 'assistant',\n model: model?.id ?? model?.model,\n provider: model?.provider,\n content: outputText ? [{ type: 'text', text: outputText }] : [],\n usage,\n stopReason: 'stop',\n },\n endedAt,\n );\n }\n }\n\n if (outputText) chain.setAttribute('output.value', outputText);\n if (failure) {\n const message = failure instanceof Error ? failure.message : String(failure);\n chain.setAttribute('neatlogs.error.message', message);\n chain.setStatus({ code: SpanStatusCode.ERROR, message });\n } else {\n chain.setStatus({ code: SpanStatusCode.OK });\n }\n chain.end(endedAt);\n\n if (root) {\n if (outputText) root.setAttribute('output.value', outputText);\n if (failure) {\n const message = failure instanceof Error ? failure.message : String(failure);\n root.setAttribute('neatlogs.error.message', message);\n root.setStatus({ code: SpanStatusCode.ERROR, message });\n } else {\n root.setStatus({ code: SpanStatusCode.OK });\n }\n root.end(endedAt);\n }\n}\n\nfunction isHarnessSummarizationFailure(failure: unknown): boolean {\n let current: any = failure;\n const seen = new Set<unknown>();\n while (current && !seen.has(current)) {\n seen.add(current);\n if (current.code === 'summarization_failed') return true;\n current = current.cause;\n }\n return false;\n}\n\nfunction harnessOperationOutput(method: 'compact' | 'navigateTree', result: any): string {\n if (method === 'compact') return typeof result?.summary === 'string' ? result.summary : safeStringify(result ?? {});\n const summary = result?.summaryEntry?.summary;\n return typeof summary === 'string' ? summary : safeStringify(result ?? {});\n}\n\nfunction harnessOperationUsage(method: 'compact' | 'navigateTree', result: any): PiUsage | undefined {\n return method === 'compact' ? result?.usage : result?.summaryEntry?.usage;\n}\n\nfunction closeLlmFailure(llm: LlmInFlight, failure: unknown, endedAt?: number): void {\n const message = failure instanceof Error ? failure.message : String(failure);\n llm.span.setAttribute('output.value', `[error] ${message}`);\n llm.span.setAttribute('neatlogs.error.message', message);\n llm.span.setStatus({ code: SpanStatusCode.ERROR, message });\n llm.span.end(endedAt);\n}\n\n/**\n * Build a standalone Pi AgentEvent listener that emits neatlogs spans.\n *\n * `piAgentHooks()` uses this internally. Reach for it directly when you drive\n * Pi's LOW-LEVEL functional API, which has no `subscribe()` to hook:\n *\n * // runAgentLoop takes an event sink — hand it the tracing listener.\n * const trace = tracePiAgentEvents(() => context.messages);\n * await runAgentLoop(prompts, context, config, async (event) => {\n * trace(event);\n * await myOwnSink?.(event);\n * });\n *\n * // agentLoop / agentLoopContinue return an EventStream — iterate it.\n * const stream = agentLoop(prompts, context, config);\n * const trace = tracePiAgentEvents(() => context.messages);\n * for await (const event of stream) trace(event);\n * const messages = await stream.result();\n *\n * @param getTranscript Optional accessor for the live transcript. Used to\n * recover the run's input when `continue()` (or a continuation loop) starts\n * from a transcript that already holds the user turn, so no new user message\n * is emitted during the run.\n */\nexport function tracePiAgentEvents(\n getTranscript?: () => any[] | undefined,\n): (event: unknown) => void {\n const state: PerAgentState = { toolSpans: new Map(), inputMessages: [], turnIndex: 0 };\n return (event: unknown) => {\n try {\n const tracer = getNeatlogsTracer(TRACER_NAME);\n handleEvent(tracer, state, event as PiAgentEvent, getTranscript);\n } catch {\n // never let tracing break the agent run\n }\n };\n}\n\n/**\n * Wrap a Pi `StreamFn` so every model call it makes gets an LLM span.\n *\n * The event surface above covers the agent loop, but a raw stream function is\n * one layer below it — reach for this when you call pi-ai directly, or when your\n * `streamFn` is NOT the one the loop wraps in agent events, e.g. `streamProxy`\n * used standalone:\n *\n * import { streamProxy } from '@earendil-works/pi-agent-core';\n * const stream = tracePiStream(streamProxy);\n * const result = await stream(model, context, { authToken, proxyUrl }).result();\n *\n * Do not pass it as an `Agent`'s `streamFn`: the loop already emits message\n * events for the same call, so that would double-count. Prefer\n * `piAgentHooks()` there and keep this for the standalone path.\n *\n * Called with no enclosing `span()`/`trace()`, the LLM span would be the trace\n * root — which the backend does not accept as one — so a WORKFLOW root is opened\n * around it. Inside an existing trace no extra root is added.\n */\nexport function tracePiStream<\n F extends (model: any, context: any, options?: any) => any,\n>(streamFn: F): F {\n return ((model: any, context: any, options?: any) => {\n const tracer = getNeatlogsTracer(TRACER_NAME);\n let llm: LlmInFlight | undefined;\n let root: Span | undefined;\n try {\n const state: PerAgentState = { toolSpans: new Map(), inputMessages: [], turnIndex: 0 };\n state.inputMessages = promptMessagesOf(context);\n\n let parent = getNeatlogsParentContext();\n if (!trace.getSpan(parent)?.isRecording()) {\n root = tracer.startSpan(\n 'pi_agent.stream',\n { attributes: { 'neatlogs.span.kind': 'WORKFLOW' } },\n parent,\n );\n parent = trace.setSpan(parent, root);\n const rootInput = state.inputMessages.length\n ? safeStringify({ messages: state.inputMessages })\n : undefined;\n if (rootInput) root.setAttribute('input.value', rootInput);\n }\n state.turnCtx = parent;\n\n llm = openLlmSpan(tracer, state, {\n role: 'assistant',\n model: model?.id ?? model?.model,\n provider: model?.provider,\n });\n } catch {\n /* tracing must never block the call */\n }\n\n let returned: any;\n try {\n returned = streamFn(model, context, options);\n } catch (err) {\n closeStreamFailure(llm, root, err);\n throw err;\n }\n\n // StreamFn explicitly permits EventStream | Promise<EventStream>. Preserve\n // that exact return shape while attaching tracing after an async stream\n // factory resolves. A rejected factory is outside Pi's recommended contract,\n // but still closes both spans rather than leaking them.\n if (isThenable(returned)) {\n return returned.then(\n (stream: any) => attachStreamResult(stream, llm, root),\n (err: unknown) => {\n closeStreamFailure(llm, root, err);\n throw err;\n },\n );\n }\n return attachStreamResult(returned, llm, root);\n }) as F;\n}\n\nfunction attachStreamResult(\n stream: any,\n llm: LlmInFlight | undefined,\n root: Span | undefined,\n): any {\n if (!llm || !stream || typeof stream.result !== 'function') {\n closeStreamRoot(root);\n return stream;\n }\n\n observeStreamDeltas(stream, llm);\n stream.result().then(\n (msg: any) => {\n const message = msg ?? { role: 'assistant' };\n finishLlmSpan(llm, message);\n closeStreamRoot(root, message);\n },\n (err: unknown) => closeStreamFailure(llm, root, err),\n );\n return stream;\n}\n\n/** Observe caller-consumed chunks without consuming or buffering the stream ourselves. */\nfunction observeStreamDeltas(stream: any, llm: LlmInFlight): void {\n const original = stream?.[Symbol.asyncIterator];\n if (typeof original !== 'function' || original.__neatlogsObserved) return;\n const observed = function (this: any): AsyncIterator<any> {\n const iterator = original.call(this) as AsyncIterator<any>;\n return {\n next: async (...args: [] | [undefined]) => {\n const item = await iterator.next(...(args as []));\n if (!item.done && isContentDelta(item.value?.type)) markFirstStreamDelta(llm);\n return item;\n },\n return: iterator.return?.bind(iterator),\n throw: iterator.throw?.bind(iterator),\n };\n };\n Object.defineProperty(observed, '__neatlogsObserved', { value: true });\n try {\n stream[Symbol.asyncIterator] = observed;\n } catch {\n // A frozen stream still gets result-based tracing; only TTFT is unavailable.\n }\n}\n\nfunction markFirstStreamDelta(llm: LlmInFlight): void {\n llm.span.setAttribute('neatlogs.llm.is_streaming', true);\n if (llm.ttftMs !== undefined) return;\n llm.ttftMs =\n llm.callStartEpochMs !== undefined\n ? Date.now() - llm.callStartEpochMs\n : nowMs() - llm.startHr;\n}\n\nfunction closeStreamFailure(\n llm: LlmInFlight | undefined,\n root: Span | undefined,\n err: unknown,\n): void {\n const message = err instanceof Error ? err.message : String(err);\n try {\n llm?.span.setAttribute('output.value', `[error] ${message}`);\n llm?.span.setAttribute('neatlogs.error.message', message);\n llm?.span.setStatus({ code: SpanStatusCode.ERROR, message });\n llm?.span.end();\n } catch {\n /* ignore */\n }\n closeStreamRoot(root, undefined, message);\n}\n\nfunction isThenable(value: any): value is PromiseLike<any> {\n return value != null && typeof value.then === 'function';\n}\n\n/** Close the synthetic WORKFLOW root `tracePiStream` opens when it has no parent. */\nfunction closeStreamRoot(root: Span | undefined, msg?: PiAssistantMessage, error?: string): void {\n if (!root) return;\n try {\n if (msg) {\n const { text, toolCalls } = splitAssistantContent(msg.content);\n const out =\n text ||\n toolCalls.map((tc) => `${tc.name}(${safeStringify(tc.arguments)})`).join('\\n') ||\n terminalSummary(msg);\n if (out) root.setAttribute('output.value', out);\n applyStopReasonStatus(root, msg);\n } else if (error) {\n root.setAttribute('output.value', `[error] ${error}`);\n root.setAttribute('neatlogs.error.message', error);\n root.setStatus({ code: SpanStatusCode.ERROR, message: error });\n }\n root.end();\n } catch {\n /* ignore */\n }\n}\n\n/** Flatten a live transcript into prompt-context rows for LLM-span input. */\nfunction transcriptRows(messages: any[] | undefined): Array<{ role: string; content: string }> {\n if (!Array.isArray(messages)) return [];\n const rows: Array<{ role: string; content: string }> = [];\n for (const m of messages) {\n const content = messageText(m);\n if (!content) continue;\n rows.push({ role: m?.role === 'toolResult' ? 'tool' : String(m?.role ?? 'user'), content });\n }\n return rows;\n}\n\n/** Flatten a pi-ai Context (systemPrompt + messages) into LLM-span input rows. */\nfunction promptMessagesOf(context: any): Array<{ role: string; content: string }> {\n const rows: Array<{ role: string; content: string }> = [];\n if (typeof context?.systemPrompt === 'string' && context.systemPrompt) {\n rows.push({ role: 'system', content: context.systemPrompt });\n }\n if (Array.isArray(context?.messages)) {\n for (const m of context.messages) {\n const content = messageText(m);\n if (content) rows.push({ role: String(m?.role ?? 'user'), content });\n }\n }\n return rows;\n}\n\nfunction handleEvent(\n tracer: ReturnType<typeof trace.getTracer>,\n state: PerAgentState,\n event: PiAgentEvent,\n getTranscript?: () => any[] | undefined,\n): void {\n switch (event.type) {\n case 'agent_start': {\n // Open the AGENT (run) span as the active span so children nest under it.\n const base = getNeatlogsParentContext();\n const span = tracer.startSpan(\n 'pi_agent.run',\n { attributes: { 'neatlogs.span.kind': 'AGENT' } },\n base,\n );\n state.agentSpan = span;\n state.agentCtx = trace.setSpan(base, span);\n // A continuation resumes an existing transcript and emits no user message,\n // so seed the prompt context from it — otherwise the first LLM span of the\n // run would report no input at all.\n state.inputMessages = transcriptRows(getTranscript?.());\n state.turnIndex = 0;\n state.runInput = undefined;\n state.runError = undefined;\n break;\n }\n\n case 'turn_start': {\n // One CHAIN span per turn, so a multi-turn run keeps its turn boundaries\n // instead of flattening every LLM/TOOL child under the run.\n const parent = state.agentCtx ?? getNeatlogsParentContext();\n state.turnIndex += 1;\n // What prompted this turn? If the transcript already ends in a user or tool\n // message it is that message (a tool-result turn, or a continuation). If it\n // ends in an assistant message the prompt has not arrived yet — pi emits\n // turn_start before it — so message_end stamps it instead.\n const pending = state.inputMessages[state.inputMessages.length - 1];\n const priorInput =\n pending && (pending.role === 'user' || pending.role === 'tool') ? pending.content : undefined;\n const span = tracer.startSpan(\n `pi_agent.turn.${state.turnIndex}`,\n {\n attributes: {\n 'neatlogs.span.kind': 'CHAIN',\n 'neatlogs.chain.turn_index': state.turnIndex,\n ...(priorInput ? { 'input.value': priorInput } : {}),\n },\n },\n parent,\n );\n state.turnSpan = span;\n state.turnCtx = trace.setSpan(parent, span);\n state.turnHasInput = !!priorInput;\n state.turnStartEpochMs = Date.now();\n break;\n }\n\n case 'turn_end': {\n if (!state.turnSpan) break;\n const msg = event.message as PiAssistantMessage | undefined;\n const { text, toolCalls } = splitAssistantContent(msg?.content);\n // A tool-use turn produces no assistant text — describe the calls it made\n // rather than leaving the turn's output blank. An aborted turn has neither,\n // so report why it ended.\n const out =\n text ||\n toolCalls.map((tc) => `${tc.name}(${safeStringify(tc.arguments)})`).join('\\n') ||\n terminalSummary(msg);\n if (out) state.turnSpan.setAttribute('output.value', out);\n if (Array.isArray(event.toolResults) && event.toolResults.length) {\n state.turnSpan.setAttribute('neatlogs.chain.tool_result_count', event.toolResults.length);\n }\n applyStopReasonStatus(state.turnSpan, msg);\n state.turnSpan.end();\n state.turnSpan = undefined;\n state.turnCtx = undefined;\n state.turnHasInput = false;\n state.turnStartEpochMs = undefined;\n break;\n }\n\n case 'message_start': {\n const msg = event.message as any;\n if (!msg || msg.role !== 'assistant') break;\n // Open the LLM span HERE so its duration covers the real provider call.\n // (Opening it at message_end would always report ~0ms.)\n state.llm = openLlmSpan(tracer, state, msg);\n break;\n }\n\n case 'message_update': {\n // First content delta = time to first token.\n const llm = state.llm;\n if (!llm) break;\n llm.span.setAttribute('neatlogs.llm.is_streaming', true);\n if (llm.ttftMs === undefined && isContentDelta(event.assistantMessageEvent?.type)) {\n // Measure from the same instant the span starts at, so TTFT stays\n // consistent with the span's own duration.\n llm.ttftMs =\n llm.callStartEpochMs !== undefined\n ? Date.now() - llm.callStartEpochMs\n : nowMs() - llm.startHr;\n }\n break;\n }\n\n case 'message_end': {\n const msg = event.message as any;\n if (!msg) return;\n if (msg.role === 'assistant') {\n // Finish the LLM span opened at message_start. If that event was missed,\n // open one now so the call is still recorded (duration reads ~0ms).\n const llm = state.llm ?? openLlmSpan(tracer, state, msg);\n state.llm = undefined;\n state.runError = finishLlmSpan(llm, msg as PiAssistantMessage) ?? state.runError;\n const { text } = splitAssistantContent(msg.content);\n if (text) state.inputMessages.push({ role: 'assistant', content: text });\n } else {\n // user / toolResult turns — accumulate as input context for later LLM spans.\n const role = msg.role === 'toolResult' ? 'tool' : String(msg.role || 'user');\n const content = messageText(msg);\n if (content) {\n state.inputMessages.push({ role, content });\n if (role === 'user' && state.runInput === undefined) state.runInput = content;\n // turn_start fires before the message that prompts the turn, so the\n // first such message is this turn's input.\n if (state.turnSpan && !state.turnHasInput) {\n state.turnSpan.setAttribute('input.value', content);\n state.turnHasInput = true;\n }\n }\n }\n break;\n }\n\n case 'tool_execution_start': {\n const parent = state.turnCtx ?? state.agentCtx ?? getNeatlogsParentContext();\n const span = tracer.startSpan(\n `pi_agent.tool.${event.toolName ?? 'tool'}`,\n {\n attributes: {\n 'neatlogs.span.kind': 'TOOL',\n ...(event.toolName ? { 'neatlogs.tool.name': String(event.toolName) } : {}),\n ...(event.toolCallId ? { 'neatlogs.tool.call_id': String(event.toolCallId) } : {}),\n ...(event.args !== undefined\n ? { 'input.value': safeStringify(event.args) }\n : {}),\n },\n },\n parent,\n );\n if (event.toolCallId) state.toolSpans.set(event.toolCallId, span);\n break;\n }\n\n case 'tool_execution_update': {\n // Streaming tool progress — record that partials arrived without\n // rewriting output.value (the final result lands at tool_execution_end).\n const span = event.toolCallId ? state.toolSpans.get(event.toolCallId) : undefined;\n if (!span) break;\n span.setAttribute('neatlogs.tool.is_streaming', true);\n break;\n }\n\n case 'tool_execution_end': {\n const span = event.toolCallId ? state.toolSpans.get(event.toolCallId) : undefined;\n if (!span) return;\n if (event.result !== undefined) {\n span.setAttribute('output.value', safeStringify(event.result));\n }\n if (event.isError) {\n span.setStatus({ code: SpanStatusCode.ERROR, message: toolErrorText(event.result) });\n span.setAttribute('neatlogs.tool.is_error', true);\n } else {\n span.setStatus({ code: SpanStatusCode.OK });\n }\n span.end();\n if (event.toolCallId) state.toolSpans.delete(event.toolCallId);\n break;\n }\n\n case 'agent_end': {\n // Close any tool spans that never received an end event, then the LLM span\n // (an abort can end the run mid-stream), the turn span, and the run span.\n for (const ts of state.toolSpans.values()) {\n try {\n ts.setStatus({ code: SpanStatusCode.ERROR, message: 'run ended before tool completed' });\n ts.end();\n } catch {\n /* ignore */\n }\n }\n state.toolSpans.clear();\n\n if (state.llm) {\n try {\n state.llm.span.setAttribute('output.value', '[incomplete] run ended mid-stream');\n state.llm.span.setStatus({ code: SpanStatusCode.ERROR, message: 'run ended mid-stream' });\n state.llm.span.end();\n } catch {\n /* ignore */\n }\n state.llm = undefined;\n }\n\n if (state.turnSpan) {\n try {\n state.turnSpan.end();\n } catch {\n /* ignore */\n }\n state.turnSpan = undefined;\n state.turnCtx = undefined;\n state.turnStartEpochMs = undefined;\n }\n\n if (state.agentSpan) {\n // Agent input = this run's first user message. A continuation\n // (`continue()`, agentLoopContinue) emits NO new user message — the turn\n // is already in the transcript — so fall back to the live transcript.\n const input = state.runInput ?? lastUserTextFrom(event.messages) ?? lastUserTextFrom(getTranscript?.());\n if (input) state.agentSpan.setAttribute('input.value', input);\n\n // Output = final assistant text. On an aborted/errored run there may be\n // none, so fall back to the terminal reason rather than leaving it blank.\n const finalText = lastAssistantText(event.messages);\n const err = state.runError ?? terminalErrorFrom(event.messages);\n if (finalText) {\n state.agentSpan.setAttribute('output.value', finalText);\n } else if (err) {\n state.agentSpan.setAttribute('output.value', `[${err.stopReason}]${err.message ? ` ${err.message}` : ''}`);\n }\n\n if (err) {\n state.agentSpan.setAttribute('neatlogs.agent.stop_reason', err.stopReason);\n if (err.message) state.agentSpan.setAttribute('neatlogs.error.message', err.message);\n state.agentSpan.setStatus({ code: SpanStatusCode.ERROR, message: err.message ?? err.stopReason });\n } else {\n state.agentSpan.setStatus({ code: SpanStatusCode.OK });\n }\n state.agentSpan.end();\n state.agentSpan = undefined;\n state.agentCtx = undefined;\n }\n break;\n }\n\n default:\n break;\n }\n}\n\n/** Start an LLM span for an assistant message, snapshotting the prompt so far. */\nfunction openLlmSpan(\n tracer: ReturnType<typeof trace.getTracer>,\n state: PerAgentState,\n msg: PiAssistantMessage,\n): LlmInFlight {\n const parent = state.turnCtx ?? state.agentCtx ?? getNeatlogsParentContext();\n // Pi emits message_start only once the provider's first stream event lands, so\n // most of the call's latency has already elapsed by now — and an EventStream\n // consumer that lags (`for await` on agentLoop) can receive start/end in one\n // burst, collapsing the span to ~0ms. `msg.timestamp` is stamped when pi begins\n // the model-call step, so prefer it as the start time.\n const startTime = callStartFrom(msg, state.turnStartEpochMs);\n const span = tracer.startSpan(\n `pi_agent.llm.${msg.model || 'model'}`,\n {\n ...(startTime !== undefined ? { startTime } : {}),\n attributes: {\n 'neatlogs.span.kind': 'LLM',\n // Pi streams by default; message_update deltas confirm it per call.\n 'neatlogs.llm.is_streaming': false,\n ...(msg.model ? { 'neatlogs.llm.model_name': String(msg.model) } : {}),\n ...(msg.provider ? { 'neatlogs.llm.provider': String(msg.provider) } : {}),\n },\n },\n parent,\n );\n return {\n span,\n startHr: nowMs(),\n callStartEpochMs: startTime,\n inputMessages: state.inputMessages.slice(),\n };\n}\n\n/**\n * The epoch-ms start of the model call, from pi's own message timestamp.\n *\n * Ignored if it isn't a plausible recent past instant — a clock skew or a\n * replayed transcript would otherwise produce a nonsense duration. Clamped to the\n * enclosing turn so a backdated child can never start before its parent.\n */\nfunction callStartFrom(msg: PiAssistantMessage, turnStart: number | undefined): number | undefined {\n const ts = msg.timestamp;\n if (typeof ts !== 'number' || !Number.isFinite(ts)) return undefined;\n const now = Date.now();\n const age = now - ts;\n if (age < 0 || age > MAX_CALL_AGE_MS) return undefined;\n return turnStart !== undefined ? Math.max(ts, turnStart) : ts;\n}\n\n/** A single model call older than this is a stale/replayed timestamp, not a live call. */\nconst MAX_CALL_AGE_MS = 30 * 60_000;\n\n/** `[aborted] Request was aborted` — output for a message that produced no content. */\nfunction terminalSummary(msg: PiAssistantMessage | undefined): string {\n const reason = msg?.stopReason;\n if (reason !== 'aborted' && reason !== 'error') return '';\n return `[${reason}]${msg?.errorMessage ? ` ${msg.errorMessage}` : ''}`;\n}\n\n/** `aborted` / `error` stop reasons must not report OK. */\nfunction applyStopReasonStatus(span: Span, msg: PiAssistantMessage | undefined): void {\n const reason = msg?.stopReason;\n if (reason === 'aborted' || reason === 'error') {\n span.setStatus({ code: SpanStatusCode.ERROR, message: msg?.errorMessage ?? reason });\n } else {\n span.setStatus({ code: SpanStatusCode.OK });\n }\n}\n\n/** Content deltas that mark the first streamed token. */\nfunction isContentDelta(type: string | undefined): boolean {\n return type === 'text_delta' || type === 'thinking_delta' || type === 'toolcall_delta';\n}\n\nfunction nowMs(): number {\n // performance.now() where available (monotonic), else Date.now().\n const p = (globalThis as any).performance;\n return typeof p?.now === 'function' ? p.now() : Date.now();\n}\n\n/** Pull a readable error message out of a failed tool result. */\nfunction toolErrorText(result: unknown): string {\n if (!result || typeof result !== 'object') return 'tool error';\n const content = (result as any).content;\n if (Array.isArray(content)) {\n const text = content\n .map((b: any) => (typeof b?.text === 'string' ? b.text : ''))\n .filter(Boolean)\n .join(' ')\n .trim();\n if (text) return text;\n }\n return 'tool error';\n}\n\n/** The most recent user message text in a transcript, if any. */\nfunction lastUserTextFrom(messages: any[] | undefined): string | undefined {\n if (!Array.isArray(messages)) return undefined;\n for (let i = messages.length - 1; i >= 0; i--) {\n const m = messages[i];\n if (m && m.role === 'user') {\n const text = messageText(m);\n if (text) return text;\n }\n }\n return undefined;\n}\n\n/** If the run's last assistant turn aborted or errored, describe it. */\nfunction terminalErrorFrom(\n messages: any[] | undefined,\n): { stopReason: string; message?: string } | undefined {\n if (!Array.isArray(messages)) return undefined;\n for (let i = messages.length - 1; i >= 0; i--) {\n const m = messages[i];\n if (m && m.role === 'assistant') {\n if (m.stopReason === 'aborted' || m.stopReason === 'error') {\n return { stopReason: m.stopReason, message: m.errorMessage };\n }\n return undefined;\n }\n }\n return undefined;\n}\n\n/**\n * Close the LLM span opened at `message_start`, stamping the response.\n *\n * The span is already open, so its duration is the real provider latency; here we\n * only attach what the completed message carries: I/O, tokens, pi-ai's exact\n * cost, TTFT, and the terminal status.\n */\nfunction finishLlmSpan(\n llm: LlmInFlight,\n msg: PiAssistantMessage,\n endTime?: number,\n): { stopReason: string; message?: string } | undefined {\n const span = llm.span;\n\n if (msg.model) span.setAttribute('neatlogs.llm.model_name', String(msg.model));\n if (msg.provider) span.setAttribute('neatlogs.llm.provider', String(msg.provider));\n // The provider may answer with a different snapshot than the one requested.\n if (msg.responseModel) span.setAttribute('neatlogs.llm.response_model', String(msg.responseModel));\n if (msg.api) span.setAttribute('neatlogs.llm.api', String(msg.api));\n if (msg.stopReason) span.setAttribute('neatlogs.llm.stop_reason', String(msg.stopReason));\n\n // Input = the conversation as it stood when the call was issued (snapshotted at\n // message_start). Pi Agent's message_end carries only the response, not the prompt.\n const inMsgs = llm.inputMessages;\n if (inMsgs.length) {\n inMsgs.forEach((m, i) => {\n span.setAttribute(`neatlogs.llm.input_messages.${i}.role`, m.role);\n span.setAttribute(`neatlogs.llm.input_messages.${i}.content`, m.content);\n });\n const inBlob = safeStringify({ messages: inMsgs });\n span.setAttribute('neatlogs.llm.input', inBlob);\n span.setAttribute('input.value', inBlob);\n }\n\n const { text, toolCalls } = splitAssistantContent(msg.content);\n // Output: text if present, else a readable tool-call summary so the span isn't\n // blank. A call that was aborted or failed has neither — report why instead.\n const outText =\n text ||\n toolCalls.map((tc) => `${tc.name}(${safeStringify(tc.arguments)})`).join('\\n') ||\n terminalSummary(msg);\n if (outText || toolCalls.length) {\n span.setAttribute('neatlogs.llm.output_messages.0.role', 'assistant');\n span.setAttribute('neatlogs.llm.output_messages.0.content', outText || '');\n const outBlob: Record<string, unknown> = { role: 'assistant', content: outText || '' };\n if (toolCalls.length) {\n outBlob.tool_calls = toolCalls.map((tc) => ({ name: tc.name, arguments: tc.arguments }));\n toolCalls.forEach((tc, j) => {\n if (tc.name) span.setAttribute(`neatlogs.llm.tool_calls.${j}.name`, tc.name);\n if (tc.arguments !== undefined)\n span.setAttribute(`neatlogs.llm.tool_calls.${j}.arguments`, safeStringify(tc.arguments));\n if (tc.id) span.setAttribute(`neatlogs.llm.tool_calls.${j}.id`, String(tc.id));\n });\n }\n span.setAttribute('neatlogs.llm.output', safeStringify(outBlob));\n span.setAttribute('output.value', outText || '');\n }\n\n const usage = msg.usage;\n if (usage) {\n if (usage.input != null) span.setAttribute('neatlogs.llm.token_count.prompt', usage.input);\n if (usage.output != null) span.setAttribute('neatlogs.llm.token_count.completion', usage.output);\n const total = usage.totalTokens ?? ((usage.input ?? 0) + (usage.output ?? 0));\n if (total) span.setAttribute('neatlogs.llm.token_count.total', total);\n if (usage.cacheRead) span.setAttribute('neatlogs.llm.token_count.cache_read', usage.cacheRead);\n if (usage.cacheWrite) span.setAttribute('neatlogs.llm.token_count.cache_write', usage.cacheWrite);\n\n // pi-ai prices the call itself against its model registry — carry that exact\n // figure through rather than letting the backend re-derive it from tokens.\n const cost = usage.cost;\n if (cost) {\n const totalCost =\n cost.total ??\n [cost.input, cost.output, cacheReadOf(cost), cost.cacheWrite].reduce<number>(\n (sum, v) => sum + (typeof v === 'number' ? v : 0),\n 0,\n );\n if (typeof totalCost === 'number' && totalCost > 0) {\n span.setAttribute('neatlogs.llm.cost_usd', totalCost);\n }\n if (typeof cost.input === 'number') span.setAttribute('neatlogs.llm.cost.prompt', cost.input);\n if (typeof cost.output === 'number') span.setAttribute('neatlogs.llm.cost.completion', cost.output);\n }\n }\n\n if (llm.ttftMs !== undefined) {\n span.setAttribute('neatlogs.llm.metrics.ttft_ms', Math.round(llm.ttftMs));\n }\n\n if (msg.errorMessage) span.setAttribute('neatlogs.error.message', String(msg.errorMessage));\n applyStopReasonStatus(span, msg);\n span.end(endTime);\n\n // Report an abnormal terminal state back to the caller: the AGENT span sees\n // only the transcript and would otherwise report a blank, SUCCESSful run.\n return msg.stopReason === 'aborted' || msg.stopReason === 'error'\n ? { stopReason: msg.stopReason, message: msg.errorMessage }\n : undefined;\n}\n\n/** pi-ai has used both `cacheRead` and (older) `cacheReads` for the cost breakdown. */\nfunction cacheReadOf(cost: Record<string, any>): number | undefined {\n return typeof cost.cacheRead === 'number' ? cost.cacheRead : cost.cacheReads;\n}\n\n// ---------------------------------------------------------------------------\n// Content helpers\n// ---------------------------------------------------------------------------\n\nfunction splitAssistantContent(\n content: PiAssistantMessage['content'],\n): { text: string; toolCalls: PiToolCall[] } {\n const texts: string[] = [];\n const toolCalls: PiToolCall[] = [];\n if (Array.isArray(content)) {\n for (const block of content) {\n if (!block || typeof block !== 'object') continue;\n if (block.type === 'text' && typeof block.text === 'string') texts.push(block.text);\n else if (block.type === 'toolCall')\n toolCalls.push(block as unknown as PiToolCall);\n // thinking blocks intentionally omitted from the main output text\n }\n } else if (typeof content === 'string') {\n texts.push(content);\n }\n return { text: texts.join(''), toolCalls };\n}\n\n/** Flatten any message's content (string or block array) to readable text. */\nfunction messageText(msg: any): string {\n if (!msg) return '';\n const c = msg.content;\n if (typeof c === 'string') return c;\n if (!Array.isArray(c)) return '';\n const parts: string[] = [];\n for (const block of c) {\n if (typeof block === 'string') parts.push(block);\n else if (block && typeof block === 'object') {\n if (typeof block.text === 'string') parts.push(block.text);\n else if (block.type === 'toolCall') parts.push(`${block.name ?? 'tool'}(${safeStringify(block.arguments)})`);\n }\n }\n return parts.join('');\n}\n\nfunction lastAssistantText(messages: any[] | undefined): string {\n if (!Array.isArray(messages)) return '';\n for (let i = messages.length - 1; i >= 0; i--) {\n const m = messages[i];\n if (m && m.role === 'assistant') {\n const { text } = splitAssistantContent(m.content);\n if (text) return text;\n }\n }\n return '';\n}\n\nfunction markPatched(e: any): void {\n try {\n Object.defineProperty(e, PATCH_FLAG, { value: true, enumerable: false, configurable: true });\n } catch {\n e[PATCH_FLAG] = true;\n }\n}\n\nfunction safeStringify(value: unknown): string {\n if (typeof value === 'string') return value;\n try {\n return JSON.stringify(value) ?? '';\n } catch {\n return '';\n }\n}\n","/**\n * Neatlogs-owned tracing state.\n *\n * Spans are created by the private Neatlogs provider and their parent is carried\n * in a private context key. The process-global OpenTelemetry span is\n * deliberately left untouched so other observability SDKs cannot export or\n * become parents of Neatlogs spans.\n */\n\nimport { AsyncLocalStorage } from 'node:async_hooks';\nimport {\n ROOT_CONTEXT,\n INVALID_SPAN_CONTEXT,\n createContextKey,\n trace as otelTrace,\n type Context,\n type Span,\n type SpanOptions,\n type Tracer,\n type TracerProvider,\n} from '@opentelemetry/api';\nimport { getActiveClient } from './active-client.js';\n\n// Carries the trace-ROOT span down the private context so descendants can target\n// it (e.g. setTraceOutput). getActiveNeatlogsSpan() returns the innermost span,\n// which is not the root once nested; this key preserves the root reference.\nconst NEATLOGS_ROOT_SPAN_KEY = createContextKey('neatlogs.root_span');\n\n// Entry points are bundled independently (`neatlogs`, `neatlogs/openai`,\n// `neatlogs/ai`, `neatlogs/mastra`, … each in both CJS and ESM), so every piece\n// of shared tracing state — the private span store AND the resolved provider /\n// provider — must live on `globalThis` behind a `Symbol.for` key.\n// Otherwise `init()` (run from the `neatlogs` bundle) sets `_provider` in ITS\n// module copy while a wrapper imported from `neatlogs/openai` reads a different,\n// still-null copy and silently falls back to the foreign global provider.\nconst PRIVATE_SPAN_STORAGE_KEY = Symbol.for(\n 'neatlogs.private_span_async_local_storage',\n);\nconst PRIVATE_PROVIDER_STATE_KEY = Symbol.for(\n 'neatlogs.private_provider_state',\n);\ninterface PrivateProviderState {\n provider: TracerProvider | null;\n}\ntype NeatlogsGlobal = typeof globalThis & {\n [PRIVATE_SPAN_STORAGE_KEY]?: AsyncLocalStorage<Context>;\n [PRIVATE_PROVIDER_STATE_KEY]?: PrivateProviderState;\n};\nconst neatlogsGlobal = globalThis as NeatlogsGlobal;\n// Stores the full Neatlogs Context (parent span PLUS any threaded values such as\n// trace()'s prompt-template keys), not just the span. We never\n// activate the OTel global context, so this private store is the ONLY channel\n// through which those values propagate down to descendant spans.\nconst privateContextStorage =\n neatlogsGlobal[PRIVATE_SPAN_STORAGE_KEY] ??\n (neatlogsGlobal[PRIVATE_SPAN_STORAGE_KEY] = new AsyncLocalStorage<Context>());\nconst providerState: PrivateProviderState =\n neatlogsGlobal[PRIVATE_PROVIDER_STATE_KEY] ??\n (neatlogsGlobal[PRIVATE_PROVIDER_STATE_KEY] = {\n provider: null,\n });\n// Wrappers may be constructed or accidentally invoked before init(). They must\n// never fall back to a foreign process-global provider, so pre-init calls use a\n// local no-op tracer and safely emit no exported spans.\nconst preInitTracer: Tracer = {\n startSpan(): Span {\n return otelTrace.wrapSpanContext(INVALID_SPAN_CONTEXT);\n },\n startActiveSpan<F extends (span: Span) => unknown>(\n _name: string,\n arg2?: SpanOptions | Context | F,\n arg3?: Context | F,\n arg4?: F,\n ): ReturnType<F> {\n const fn =\n typeof arg2 === 'function'\n ? arg2\n : typeof arg3 === 'function'\n ? arg3\n : arg4;\n return fn!(otelTrace.wrapSpanContext(INVALID_SPAN_CONTEXT)) as ReturnType<F>;\n },\n};\n\n/** @internal Configure the provider used by Neatlogs-created spans. */\nexport function _setNeatlogsProvider(provider: TracerProvider | null): void {\n providerState.provider = provider;\n}\n\n/** Resolve a tracer from the private provider when one is configured. */\nexport function getNeatlogsTracer(name: string): Tracer {\n const client = getActiveClient();\n if (client) return client.getTracer(name);\n return providerState.provider?.getTracer(name) ?? preInitTracer;\n}\n\n/** A reusable tracer facade that resolves the active Client on every call. */\nexport function getRoutingNeatlogsTracer(name: string): Tracer {\n return {\n startSpan(spanName: string, options?: SpanOptions, context?: Context): Span {\n return isolateTracer(getNeatlogsTracer(name)).startSpan(\n spanName,\n options,\n context,\n );\n },\n startActiveSpan: ((...args: any[]) =>\n (isolateTracer(getNeatlogsTracer(name)).startActiveSpan as (...inner: any[]) => any)(\n ...args,\n )) as Tracer['startActiveSpan'],\n };\n}\n\n/**\n * @internal The private Neatlogs provider, or null before\n * init(). Used by integrations that must repoint a self-instrumenting library's\n * captured provider onto ours.\n */\nexport function getNeatlogsProvider(): TracerProvider | null {\n const client = getActiveClient();\n if (client) return client.tracerProvider;\n return providerState.provider;\n}\n\n/** Run a Client callback without inheriting another pipeline's private span. */\nexport function runWithFreshNeatlogsContext<T>(fn: () => T): T {\n return privateContextStorage.run(ROOT_CONTEXT, fn);\n}\n\n/**\n * Wrap a tracer so that spans it creates parent from — and, for\n * `startActiveSpan`, activate on — the PRIVATE Neatlogs context instead of the\n * global one.\n *\n * We hand this to libraries that create their own spans off a tracer we give\n * them (the Vercel AI SDK's `experimental_telemetry.tracer`, which calls\n * `tracer.startActiveSpan()` internally). Without the facade the AI SDK's native\n * spans would parent from `context.active()` — the foreign co-tenant's context —\n * and `startActiveSpan` would push them onto the GLOBAL context, so a foreign\n * tracer's next span reads our native span as its parent. Both directions leak.\n *\n */\nexport function isolateTracer(tracer: Tracer): Tracer {\n const facade: Tracer = {\n startSpan(name: string, options?: SpanOptions, context?: Context): Span {\n const parent = context ?? getNeatlogsActiveContext();\n return tracer.startSpan(name, options, parent);\n },\n startActiveSpan<F extends (span: Span) => unknown>(\n name: string,\n arg2?: SpanOptions | Context | F,\n arg3?: Context | F,\n arg4?: F,\n ): ReturnType<F> {\n // Normalize the 2/3/4-arg overloads of startActiveSpan.\n let options: SpanOptions | undefined;\n let context: Context | undefined;\n let fn: F;\n if (typeof arg2 === 'function') {\n fn = arg2 as F;\n } else if (typeof arg3 === 'function') {\n options = arg2 as SpanOptions;\n fn = arg3 as F;\n } else {\n options = arg2 as SpanOptions;\n context = arg3 as Context;\n fn = arg4 as F;\n }\n const parent = context ?? getNeatlogsActiveContext();\n const span = tracer.startSpan(name, options, parent);\n return withNeatlogsSpan(span, () => fn(span), parent) as ReturnType<F>;\n },\n };\n return facade;\n}\n\n/**\n * The base context to build new Neatlogs spans and values on. NEVER contains a\n * foreign provider's span: it reads our private store, or ROOT_CONTEXT when\n * nothing is active.\n */\nexport function getNeatlogsActiveContext(): Context {\n return privateContextStorage.getStore() ?? ROOT_CONTEXT;\n}\n\n/** Return only the active Neatlogs span (never a foreign provider's span). */\nexport function getActiveNeatlogsSpan(): Span | undefined {\n return otelTrace.getSpan(getNeatlogsActiveContext());\n}\n\n/**\n * Return the trace-ROOT Neatlogs span, or undefined when no trace is active.\n *\n * Unlike {@link getActiveNeatlogsSpan} (innermost), this is the outermost span\n * of the current trace — the one the backend derives trace-level output from\n * (`parent_span_id=''`). It is stashed on the private context the first time a\n * span becomes active, so nested calls still resolve to the root.\n */\nexport function getNeatlogsRootSpan(): Span | undefined {\n return getNeatlogsActiveContext().getValue(NEATLOGS_ROOT_SPAN_KEY) as\n | Span\n | undefined;\n}\n\n/**\n * Build a parent context that cannot contain a foreign provider's span.\n *\n * The active Neatlogs context already carries the parent span AND any values\n * the caller threaded in upstream (e.g. `trace()`'s prompt-template values), so\n * those values reach the span processor via `onStart(parentContext)`. An\n * explicit `baseContext` (a caller's own value-carrying context) is honored as-is.\n */\nexport function getNeatlogsParentContext(baseContext?: Context): Context {\n return baseContext ?? getNeatlogsActiveContext();\n}\n\n/**\n * A base context for callers that thread parent linkage themselves\n * (callback/event handlers that keep their own run-id → span map: LangChain,\n * OpenAI-Agents, Claude Agent SDK).\n *\n * This is the ACTIVE Neatlogs context — the private store's\n * context if a Neatlogs `trace()`/`span()` encloses this call, else\n * ROOT_CONTEXT. So a handler's own root/entry span nests under an enclosing\n * Neatlogs trace (preserving its session + end-user id) when one exists, and\n * auto-roots cleanly when one doesn't. A foreign provider's active span can\n * never leak in as an ancestor because the global context is never read.\n */\nexport function getNeatlogsBaseContext(baseContext?: Context): Context {\n return baseContext ?? getNeatlogsActiveContext();\n}\n\n/**\n * Build an execution context for a Neatlogs span while preserving the active\n * foreign context. The span rides our private context store.\n */\nexport function getNeatlogsExecutionContext(\n span: Span,\n baseContext: Context = ROOT_CONTEXT,\n): Context {\n return otelTrace.setSpan(baseContext, span);\n}\n\n/**\n * Run a callback with a Neatlogs span active under the appropriate policy.\n *\n * The stored context is `setSpan(base, span)` — carrying the span PLUS whatever\n * values `base` holds — so threaded values (prompt templates)\n * propagate to descendant spans through our private store instead of the global\n * OTel context we deliberately never touch.\n */\nexport function withNeatlogsSpan<T>(\n span: Span,\n fn: () => T,\n baseContext?: Context,\n rootSpan?: Span,\n): T {\n const base = baseContext ?? getNeatlogsActiveContext();\n let ctx = otelTrace.setSpan(base, span);\n // The first span activated in a context with no root recorded IS the root of\n // this trace; remember it so descendants (setTraceOutput) can target it.\n if (base.getValue(NEATLOGS_ROOT_SPAN_KEY) === undefined) {\n ctx = ctx.setValue(NEATLOGS_ROOT_SPAN_KEY, rootSpan ?? span);\n }\n return privateContextStorage.run(ctx, fn);\n}\n\n/**\n * @internal Run with a private Neatlogs parent without treating that parent as\n * a locally-recording trace root. This is used for an extracted remote parent:\n * the first local recording span should remain the target for local trace-level\n * output, while still inheriting the remote trace/span IDs.\n */\nexport function withNeatlogsRemoteParent<T>(span: Span, fn: () => T): T {\n return privateContextStorage.run(otelTrace.setSpan(ROOT_CONTEXT, span), fn);\n}\n","import { AsyncLocalStorage } from 'node:async_hooks';\nimport type { Tracer, TracerProvider } from '@opentelemetry/api';\n\nexport interface ActiveNeatlogsClient {\n readonly workflowName: string;\n readonly tracerProvider: TracerProvider;\n getTracer(scope: string): Tracer;\n getLogger(): any | null;\n}\n\nconst ACTIVE_CLIENT_STORAGE_KEY = Symbol.for(\n 'neatlogs.active_client_async_local_storage',\n);\ntype NeatlogsGlobal = typeof globalThis & {\n [ACTIVE_CLIENT_STORAGE_KEY]?: AsyncLocalStorage<ActiveNeatlogsClient>;\n};\nconst neatlogsGlobal = globalThis as NeatlogsGlobal;\nconst storage =\n neatlogsGlobal[ACTIVE_CLIENT_STORAGE_KEY] ??\n (neatlogsGlobal[ACTIVE_CLIENT_STORAGE_KEY] =\n new AsyncLocalStorage<ActiveNeatlogsClient>());\n\nexport function getActiveClient(): ActiveNeatlogsClient | undefined {\n return storage.getStore();\n}\n\nexport function runWithClient<T>(\n client: ActiveNeatlogsClient,\n fn: () => T,\n): T {\n return storage.run(client, fn);\n}\n"],"mappings":"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","names":["import_api","import_node_async_hooks","neatlogsGlobal","otelTrace"]}
|