@morsehq-dev/sdk 0.4.1-rc.1 → 0.5.0-rc.1
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/dist/anthropic/index.cjs +12 -10
- package/dist/anthropic/index.js +5 -3
- package/dist/anthropic-agent-sdk/index.cjs +52 -34
- package/dist/anthropic-agent-sdk/index.cjs.map +1 -1
- package/dist/anthropic-agent-sdk/index.js +25 -7
- package/dist/anthropic-agent-sdk/index.js.map +1 -1
- package/dist/browser/anthropic/index.cjs +12 -10
- package/dist/browser/anthropic/index.js +5 -3
- package/dist/browser/anthropic-agent-sdk/index.cjs +52 -34
- package/dist/browser/anthropic-agent-sdk/index.cjs.map +1 -1
- package/dist/browser/anthropic-agent-sdk/index.js +25 -7
- package/dist/browser/anthropic-agent-sdk/index.js.map +1 -1
- package/dist/browser/chunk-32U547L3.js +118 -0
- package/dist/browser/chunk-32U547L3.js.map +1 -0
- package/dist/{chunk-SBGY5NS4.js → browser/chunk-454FDWBM.js} +6 -4
- package/dist/browser/chunk-454FDWBM.js.map +1 -0
- package/dist/browser/{chunk-EFUQVASI.cjs → chunk-5EFKNOO7.cjs} +17 -15
- package/dist/browser/chunk-5EFKNOO7.cjs.map +1 -0
- package/dist/browser/{chunk-DOLWR7LD.js → chunk-5IWGFPKQ.js} +4 -4
- package/dist/browser/{chunk-DOLWR7LD.js.map → chunk-5IWGFPKQ.js.map} +1 -1
- package/dist/browser/{chunk-F3B4UR64.js → chunk-6DOP3MTY.js} +386 -53
- package/dist/browser/chunk-6DOP3MTY.js.map +1 -0
- package/dist/browser/{chunk-GWJYOQNC.js → chunk-A7P3ZBZX.js} +10 -4
- package/dist/browser/chunk-A7P3ZBZX.js.map +1 -0
- package/dist/browser/{chunk-M2GZJ3RS.cjs → chunk-AV35EOER.cjs} +20 -14
- package/dist/browser/chunk-AV35EOER.cjs.map +1 -0
- package/dist/browser/{chunk-AYNX24P5.js → chunk-AZ3SVK3K.js} +3 -3
- package/dist/browser/{chunk-AYNX24P5.js.map → chunk-AZ3SVK3K.js.map} +1 -1
- package/dist/browser/chunk-FNZWJU64.cjs +31 -0
- package/dist/browser/chunk-FNZWJU64.cjs.map +1 -0
- package/dist/browser/chunk-HZZK2EMO.cjs +126 -0
- package/dist/browser/chunk-HZZK2EMO.cjs.map +1 -0
- package/dist/browser/{chunk-QWRQJO57.js → chunk-MLDVXMQD.js} +3 -3
- package/dist/browser/{chunk-QWRQJO57.js.map → chunk-MLDVXMQD.js.map} +1 -1
- package/dist/{chunk-Y7SVGUKY.cjs → browser/chunk-NT37C2TK.cjs} +7 -7
- package/dist/browser/{chunk-YNUZGKUA.cjs.map → chunk-NT37C2TK.cjs.map} +1 -1
- package/dist/browser/{chunk-3643DC7K.cjs → chunk-RBNCTHK3.cjs} +5 -2
- package/dist/browser/{chunk-3643DC7K.cjs.map → chunk-RBNCTHK3.cjs.map} +1 -1
- package/dist/browser/chunk-VFNNU3AX.js +28 -0
- package/dist/browser/chunk-VFNNU3AX.js.map +1 -0
- package/dist/browser/{chunk-HGN7J3EU.cjs → chunk-WY2VLKRR.cjs} +12 -12
- package/dist/browser/{chunk-HGN7J3EU.cjs.map → chunk-WY2VLKRR.cjs.map} +1 -1
- package/dist/browser/{chunk-DXWHT3HK.cjs → chunk-ZGYZZCUK.cjs} +391 -55
- package/dist/browser/chunk-ZGYZZCUK.cjs.map +1 -0
- package/dist/browser/index.cjs +112 -82
- package/dist/browser/index.cjs.map +1 -1
- package/dist/browser/index.js +40 -10
- package/dist/browser/index.js.map +1 -1
- package/dist/browser/integrations/pino.cjs +4 -4
- package/dist/browser/integrations/pino.js +3 -3
- package/dist/browser/langchain/index.cjs +19 -19
- package/dist/browser/langchain/index.js +3 -3
- package/dist/browser/langgraph/index.cjs +34 -26
- package/dist/browser/langgraph/index.cjs.map +1 -1
- package/dist/browser/langgraph/index.js +16 -8
- package/dist/browser/langgraph/index.js.map +1 -1
- package/dist/browser/openai/index.cjs +22 -8
- package/dist/browser/openai/index.cjs.map +1 -1
- package/dist/browser/openai/index.js +17 -3
- package/dist/browser/openai/index.js.map +1 -1
- package/dist/browser/openai-agents/index.cjs +42 -34
- package/dist/browser/openai-agents/index.cjs.map +1 -1
- package/dist/browser/openai-agents/index.js +13 -5
- package/dist/browser/openai-agents/index.js.map +1 -1
- package/dist/browser/vercel-ai/index.cjs +16 -16
- package/dist/browser/vercel-ai/index.js +4 -4
- package/dist/{chunk-4R4SHGOK.js → chunk-4JPZV2VZ.js} +3 -3
- package/dist/{chunk-4R4SHGOK.js.map → chunk-4JPZV2VZ.js.map} +1 -1
- package/dist/{chunk-HNCWTENX.cjs → chunk-5B3IUESN.cjs} +415 -70
- package/dist/chunk-5B3IUESN.cjs.map +1 -0
- package/dist/chunk-5RXSICEJ.js +118 -0
- package/dist/chunk-5RXSICEJ.js.map +1 -0
- package/dist/chunk-7A2EWXZK.cjs +31 -0
- package/dist/chunk-7A2EWXZK.cjs.map +1 -0
- package/dist/{chunk-STK4KJQ6.js → chunk-AAR4FYFO.js} +10 -4
- package/dist/chunk-AAR4FYFO.js.map +1 -0
- package/dist/{chunk-LQI63FHF.cjs → chunk-ADRVMGAW.cjs} +20 -14
- package/dist/chunk-ADRVMGAW.cjs.map +1 -0
- package/dist/{chunk-V5J6J4ZR.js → chunk-CECVNM7R.js} +4 -4
- package/dist/{chunk-V5J6J4ZR.js.map → chunk-CECVNM7R.js.map} +1 -1
- package/dist/{chunk-KJEO52QS.cjs → chunk-HICEJ4LV.cjs} +5 -2
- package/dist/{chunk-KJEO52QS.cjs.map → chunk-HICEJ4LV.cjs.map} +1 -1
- package/dist/{chunk-QXRJUPDP.cjs → chunk-HSY7V4RG.cjs} +12 -12
- package/dist/{chunk-QXRJUPDP.cjs.map → chunk-HSY7V4RG.cjs.map} +1 -1
- package/dist/chunk-LB6ZLJUR.js +28 -0
- package/dist/chunk-LB6ZLJUR.js.map +1 -0
- package/dist/{browser/chunk-F7BGQ26H.js → chunk-O3Q5L2HY.js} +6 -4
- package/dist/chunk-O3Q5L2HY.js.map +1 -0
- package/dist/{chunk-5D6SBSEI.cjs → chunk-RF7NI5VN.cjs} +17 -15
- package/dist/chunk-RF7NI5VN.cjs.map +1 -0
- package/dist/{chunk-AEFUXEKV.js → chunk-TP3N3S2D.js} +3 -3
- package/dist/{chunk-AEFUXEKV.js.map → chunk-TP3N3S2D.js.map} +1 -1
- package/dist/{chunk-LTKGLXAE.js → chunk-UEKQIRRA.js} +410 -68
- package/dist/chunk-UEKQIRRA.js.map +1 -0
- package/dist/{browser/chunk-YNUZGKUA.cjs → chunk-UWQPOWJQ.cjs} +7 -7
- package/dist/{chunk-Y7SVGUKY.cjs.map → chunk-UWQPOWJQ.cjs.map} +1 -1
- package/dist/chunk-VD3KRXSP.cjs +126 -0
- package/dist/chunk-VD3KRXSP.cjs.map +1 -0
- package/dist/index.cjs +119 -89
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +41 -11
- package/dist/index.js.map +1 -1
- package/dist/integrations/pino.cjs +4 -4
- package/dist/integrations/pino.js +3 -3
- package/dist/langchain/index.cjs +19 -19
- package/dist/langchain/index.d.cts +1 -1
- package/dist/langchain/index.d.ts +1 -1
- package/dist/langchain/index.js +3 -3
- package/dist/langgraph/index.cjs +34 -26
- package/dist/langgraph/index.cjs.map +1 -1
- package/dist/langgraph/index.d.cts +1 -1
- package/dist/langgraph/index.d.ts +1 -1
- package/dist/langgraph/index.js +16 -8
- package/dist/langgraph/index.js.map +1 -1
- package/dist/openai/index.cjs +22 -8
- package/dist/openai/index.cjs.map +1 -1
- package/dist/openai/index.js +17 -3
- package/dist/openai/index.js.map +1 -1
- package/dist/openai-agents/index.cjs +42 -34
- package/dist/openai-agents/index.cjs.map +1 -1
- package/dist/openai-agents/index.js +13 -5
- package/dist/openai-agents/index.js.map +1 -1
- package/dist/{tracing-BYAqjT5Q.d.cts → tracing-CNlre8TK.d.cts} +1 -0
- package/dist/{tracing-rz9cWQ8d.d.ts → tracing-J8ZgxVzU.d.ts} +1 -0
- package/dist/vercel-ai/index.cjs +16 -16
- package/dist/vercel-ai/index.js +4 -4
- package/package.json +1 -9
- package/dist/browser/chunk-3BGG7GH3.cjs +0 -183
- package/dist/browser/chunk-3BGG7GH3.cjs.map +0 -1
- package/dist/browser/chunk-DXWHT3HK.cjs.map +0 -1
- package/dist/browser/chunk-EFUQVASI.cjs.map +0 -1
- package/dist/browser/chunk-F3B4UR64.js.map +0 -1
- package/dist/browser/chunk-F7BGQ26H.js.map +0 -1
- package/dist/browser/chunk-GWJYOQNC.js.map +0 -1
- package/dist/browser/chunk-M2GZJ3RS.cjs.map +0 -1
- package/dist/browser/chunk-YHV5GL32.js +0 -178
- package/dist/browser/chunk-YHV5GL32.js.map +0 -1
- package/dist/chunk-5D6SBSEI.cjs.map +0 -1
- package/dist/chunk-HNCWTENX.cjs.map +0 -1
- package/dist/chunk-LQI63FHF.cjs.map +0 -1
- package/dist/chunk-LTKGLXAE.js.map +0 -1
- package/dist/chunk-POCQNSVD.js +0 -178
- package/dist/chunk-POCQNSVD.js.map +0 -1
- package/dist/chunk-SBGY5NS4.js.map +0 -1
- package/dist/chunk-STK4KJQ6.js.map +0 -1
- package/dist/chunk-T2KW3P23.cjs +0 -183
- package/dist/chunk-T2KW3P23.cjs.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/langgraph/callback-handler.ts","../../src/langgraph/llm-and-tool-callbacks.ts","../../src/langgraph/streaming-and-checkpoint.ts","../../src/langgraph/index.ts"],"names":["ADAPTER","MorseCallbackHandler"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * `@morsehq-dev/sdk/langgraph` — `MorseCallbackHandler` (W2-L.1).\n *\n * The handler is registered by LangGraph users via:\n *\n * ```ts\n * import { MorseCallbackHandler } from \"@morsehq-dev/sdk/langgraph\";\n * await app.invoke(input, { callbacks: [new MorseCallbackHandler()] });\n * ```\n *\n * LangGraph type-checks handlers structurally (by method presence on the\n * instance), not via `instanceof BaseCallbackHandler`. We therefore:\n *\n * 1. Always export a duck-typed class implementing `CallbackHandlerSurface`\n * — works without `@langchain/core` installed.\n * 2. Provide `getCallbackHandlerClass()` for users who rely on\n * `instanceof BaseCallbackHandler` — it dynamically loads\n * `@langchain/core/callbacks/base` (optional peer dep) and returns a\n * subclass whose prototype chain includes the real base class.\n *\n * Scope of THIS file (W2-L.1): chain spans only. `handleChainStart` opens\n * an `agent` span (the LangGraph chain IS the agent run); `handleChainEnd`\n * / `handleChainError` closes it. Nested chains nest via the per-runId\n * span map — LangGraph guarantees well-ordered start/end pairs so the\n * tracing-state span stack handles `parent_span_id` linkage for us.\n *\n * `handleLLMStart/End`, `handleToolStart/End`, and streaming callbacks\n * are implemented in W2-L.2 / W2-L.3 as separate methods on the same\n * class (composed in Wave 3-L).\n */\n\nimport { absorbErrorsSync } from \"../_internal/errors\";\nimport type { SpanHandle } from \"../_internal/tracing\";\nimport { emitAgentSpan } from \"../_agent-sdk-common/span-emitter\";\nimport type {\n CallbackHandlerSurface,\n LangChainCoreCallbacksModuleLike,\n SerializedLike,\n} from \"./types\";\n\n/* ------------------------------------------------------------------------ */\n/* Public surface */\n/* ------------------------------------------------------------------------ */\n\nexport interface MorseCallbackHandlerOptions {\n /**\n * Override the agent name on the outer chain span. Falls back, in order,\n * to: `runName` (LangGraph-supplied per-invocation name), `chain.name`\n * (the serialized class name), then `\"langgraph-agent\"`.\n */\n defaultAgentName?: string;\n}\n\nconst ADAPTER = \"langgraph-js\";\nconst HANDLER_NAME = \"morse_callback_handler\";\nconst DEFAULT_AGENT_NAME_FALLBACK = \"langgraph-agent\";\n\n/**\n * Duck-typed LangGraph `BaseCallbackHandler`. Implements `CallbackHandlerSurface`\n * with chain-start / chain-end / chain-error wired to the Morse trace.\n *\n * LangGraph routes callbacks to instance methods by name; it does NOT require\n * an `instanceof` check against the real `BaseCallbackHandler`. Users who\n * need that (rare; `instanceof` checks in custom middleware) should obtain\n * the class via `getCallbackHandlerClass()` instead.\n */\nexport class MorseCallbackHandler implements CallbackHandlerSurface {\n /** Required by LangGraph's `BaseCallbackHandler` interface. */\n public readonly name: string = HANDLER_NAME;\n\n private readonly defaultAgentName: string | undefined;\n\n /** Open chain spans, keyed by LangGraph `runId`. */\n private readonly chainSpans: Map<string, SpanHandle> = new Map();\n\n constructor(options?: MorseCallbackHandlerOptions) {\n this.defaultAgentName = options?.defaultAgentName;\n }\n\n handleChainStart(\n chain: SerializedLike,\n _inputs: Record<string, unknown>,\n runId: string,\n _parentRunId?: string,\n _tags?: string[],\n _metadata?: Record<string, unknown>,\n _runType?: string,\n runName?: string,\n ): void {\n _handleChainStartImpl(this, chain, runId, runName);\n }\n\n handleChainEnd(_outputs: Record<string, unknown>, runId: string, parentRunId?: string): void {\n void parentRunId;\n _handleChainEndImpl(this, runId);\n }\n\n handleChainError(err: unknown, runId: string, parentRunId?: string): void {\n void parentRunId;\n _handleChainErrorImpl(this, err, runId);\n }\n\n /* ------ Internal accessors used by the absorbErrorsSync-wrapped impls ----- */\n\n /** @internal */\n _setSpan(runId: string, handle: SpanHandle): void {\n this.chainSpans.set(runId, handle);\n }\n\n /** @internal */\n _takeSpan(runId: string): SpanHandle | undefined {\n const handle = this.chainSpans.get(runId);\n if (handle) this.chainSpans.delete(runId);\n return handle;\n }\n\n /** @internal */\n _resolveAgentName(chain: SerializedLike | undefined, runName: string | undefined): string {\n if (typeof runName === \"string\" && runName.length > 0) return runName;\n if (chain && typeof chain.name === \"string\" && chain.name.length > 0) return chain.name;\n if (this.defaultAgentName && this.defaultAgentName.length > 0) return this.defaultAgentName;\n return DEFAULT_AGENT_NAME_FALLBACK;\n }\n}\n\n/* ------------------------------------------------------------------------ */\n/* Implementation bodies (wrapped in absorbErrorsSync) */\n/* ------------------------------------------------------------------------ */\n\nconst _handleChainStartImpl: (\n self: MorseCallbackHandler,\n chain: SerializedLike | undefined,\n runId: string,\n runName: string | undefined,\n) => void = absorbErrorsSync(\n (\n self: MorseCallbackHandler,\n chain: SerializedLike | undefined,\n runId: string,\n runName: string | undefined,\n ) => {\n if (typeof runId !== \"string\" || runId.length === 0) return;\n // Defensive: if LangGraph re-fires start for the same runId, leak nothing.\n if (self._takeSpan(runId)) {\n // (we just popped it — drop on the floor; the dangling end will be a no-op)\n }\n const agentName = self._resolveAgentName(chain, runName);\n const handle = emitAgentSpan({ adapter: ADAPTER, agentName });\n if (handle) self._setSpan(runId, handle);\n },\n { fingerprint: \"morse.langgraph.handleChainStart\" },\n) as (\n self: MorseCallbackHandler,\n chain: SerializedLike | undefined,\n runId: string,\n runName: string | undefined,\n) => void;\n\nconst _handleChainEndImpl: (self: MorseCallbackHandler, runId: string) => void = absorbErrorsSync(\n (self: MorseCallbackHandler, runId: string) => {\n const handle = self._takeSpan(runId);\n if (handle) handle.end();\n },\n { fingerprint: \"morse.langgraph.handleChainEnd\" },\n) as (self: MorseCallbackHandler, runId: string) => void;\n\nconst _handleChainErrorImpl: (self: MorseCallbackHandler, err: unknown, runId: string) => void =\n absorbErrorsSync(\n (self: MorseCallbackHandler, err: unknown, runId: string) => {\n const handle = self._takeSpan(runId);\n if (handle) handle.end(err ?? new Error(\"langgraph chain error\"));\n },\n { fingerprint: \"morse.langgraph.handleChainError\" },\n ) as (self: MorseCallbackHandler, err: unknown, runId: string) => void;\n\n/* ------------------------------------------------------------------------ */\n/* Optional peer-dep: real BaseCallbackHandler */\n/* ------------------------------------------------------------------------ */\n\nasync function loadLangChainCoreCallbacks(): Promise<LangChainCoreCallbacksModuleLike | null> {\n try {\n // Function-eval'd dynamic import keeps bundlers from trying to resolve\n // `@langchain/core/callbacks/base` at build time when the dep isn't installed.\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const mod = (await (Function(\"m\", \"return import(m)\") as any)(\n \"@langchain/core/callbacks/base\",\n )) as LangChainCoreCallbacksModuleLike;\n return mod ?? null;\n } catch {\n return null;\n }\n}\n\n/**\n * Best-effort: if `@langchain/core/callbacks/base` is installed at runtime,\n * return an `MorseCallbackHandler`-shaped class whose prototype chain\n * includes the real `BaseCallbackHandler` (for users relying on\n * `instanceof BaseCallbackHandler` checks). Otherwise return the\n * duck-typed `MorseCallbackHandler` defined above.\n */\nexport async function getCallbackHandlerClass(): Promise<typeof MorseCallbackHandler> {\n const mod = await loadLangChainCoreCallbacks();\n const Base = mod?.BaseCallbackHandler;\n if (!Base) return MorseCallbackHandler;\n\n // Build a subclass that mixes the real Base class into the prototype chain\n // while preserving the chain-span behavior. We do this lazily so that\n // simply importing this module does NOT require `@langchain/core`.\n class MorseCallbackHandlerWithBase extends (Base as unknown as {\n new (...args: unknown[]): object;\n }) {\n public readonly name: string = HANDLER_NAME;\n private readonly _av: MorseCallbackHandler;\n constructor(options?: MorseCallbackHandlerOptions) {\n super();\n this._av = new MorseCallbackHandler(options);\n }\n handleChainStart(\n chain: SerializedLike,\n inputs: Record<string, unknown>,\n runId: string,\n parentRunId?: string,\n tags?: string[],\n metadata?: Record<string, unknown>,\n runType?: string,\n runName?: string,\n ): void {\n this._av.handleChainStart(\n chain,\n inputs,\n runId,\n parentRunId,\n tags,\n metadata,\n runType,\n runName,\n );\n }\n handleChainEnd(outputs: Record<string, unknown>, runId: string, parentRunId?: string): void {\n this._av.handleChainEnd(outputs, runId, parentRunId);\n }\n handleChainError(err: unknown, runId: string, parentRunId?: string): void {\n this._av.handleChainError(err, runId, parentRunId);\n }\n }\n return MorseCallbackHandlerWithBase as unknown as typeof MorseCallbackHandler;\n}\n","/**\n * `langgraph/llm-and-tool-callbacks.ts` — W2-L.2.\n *\n * LangGraph JS callback handler fragment that owns the llm + tool surface\n * of `BaseCallbackHandler`. The class shell (constructor + chain methods)\n * is owned by W2-L.1 (`callback-handler.ts`); streaming + checkpoint by\n * W2-L.3 (`streaming-and-checkpoint.ts`). All three are composed together\n * by W3-L (`langgraph/index.ts`).\n *\n * To stay file-disjoint across the three W2-L tasks, each fragment exports\n * a `createX` factory that returns plain method implementations operating\n * on a shared mutable `LangGraphRunState`. The host class threads its\n * `state` reference through each factory in its constructor and copies the\n * methods onto its prototype/instance.\n *\n * Logical span mapping (per design.md §LangGraph JS):\n * handleLLMStart / handleChatModelStart → open `type=llm` span\n * handleLLMEnd / handleLLMError → close active llm span\n * handleToolStart → open `type=tool` span\n * handleToolEnd / handleToolError → close active tool span\n *\n * MHQ-750: `handleChatModelStart` also decomposes the flattened messages\n * (+ any bound `tools`) into `context_segments` via the shared\n * `_agent-sdk-common/context-decomposer`, mirroring the Python adapter's\n * `on_chat_model_start` (`adapters/langgraph.py`), which calls the same\n * `decompose_openai_messages` for the same reason: LangGraph JS messages\n * are `@langchain/core` `BaseMessage`s, which decompose cleanly under the\n * OpenAI-chat-format decomposer's `_getType()`/`.type` duck-typing.\n *\n * All bodies are wrapped in `absorbErrorsSync` so telemetry can never\n * throw at the host LangGraph runtime.\n */\n\nimport { absorbErrorsSync } from \"../_internal/errors\";\nimport { calculateCost } from \"../_internal/pricing\";\nimport type { SpanHandle } from \"../_internal/tracing\";\nimport { emitLlmSpan, emitToolSpan } from \"../_agent-sdk-common/span-emitter\";\nimport { summarizeToolInput, summarizeToolOutput } from \"../_agent-sdk-common/redaction\";\nimport { decomposeOpenAiMessages } from \"../_agent-sdk-common/context-decomposer\";\nimport type {\n BaseMessageLike,\n CallbackHandlerSurface,\n LLMResultLike,\n SerializedLike,\n} from \"./types\";\n\nconst ADAPTER = \"langgraph-js\" as const;\n\n/* ------------------------------------------------------------------------ */\n/* Shared run state */\n/* ------------------------------------------------------------------------ */\n\n/**\n * Shared per-instance state for the composed `MorseCallbackHandler`.\n * Owned/instantiated by W3-L (`langgraph/index.ts`); each W2-L fragment\n * mutates it in place.\n */\nexport interface LangGraphRunState {\n /** Map of runId → SpanHandle for open llm spans. */\n llmSpans: Map<string, SpanHandle>;\n /** Map of runId → SpanHandle for open tool spans. */\n toolSpans: Map<string, SpanHandle>;\n /** Map of runId → SpanHandle for open chain spans (populated by W2-L.1). */\n chainSpans: Map<string, SpanHandle>;\n}\n\nexport interface LlmAndToolHandlerOptions {\n /** Max bytes for tool input summary. Falls through to module default if unset. */\n toolInputMaxBytes?: number;\n /** Max bytes for tool output summary. Falls through to module default if unset. */\n toolOutputMaxBytes?: number;\n}\n\n/** Convenient public type alias for the slice of methods this file owns. */\nexport type LlmAndToolHandlers = Pick<\n CallbackHandlerSurface,\n | \"handleLLMStart\"\n | \"handleChatModelStart\"\n | \"handleLLMEnd\"\n | \"handleLLMError\"\n | \"handleToolStart\"\n | \"handleToolEnd\"\n | \"handleToolError\"\n>;\n\n/* ------------------------------------------------------------------------ */\n/* Helpers */\n/* ------------------------------------------------------------------------ */\n\n/**\n * Extract a provider hint from the `id` path produced by LangChain's\n * `Serializable` machinery. The first segment is usually the package name\n * (`langchain_openai`, `langchain_anthropic`, `langchain_google_vertexai`,\n * etc.). We strip the `langchain_` prefix when present and return the\n * remainder; otherwise we return the first segment verbatim. Returns\n * `undefined` when no identifying segment is available.\n */\nfunction extractProvider(id: string[] | undefined): string | undefined {\n if (!Array.isArray(id) || id.length === 0) return undefined;\n const first = id[0];\n if (typeof first !== \"string\" || first.length === 0) return undefined;\n if (first.startsWith(\"langchain_\")) {\n const tail = first.slice(\"langchain_\".length);\n return tail.length > 0 ? tail : undefined;\n }\n return first;\n}\n\n/**\n * MHQ-788: `llm.name` is LangChain's `Serializable` class name (e.g.\n * `\"ChatOpenAI\"`), never the actual model string — it was always the wrong\n * field, and empty in practice for the real `@langchain/openai` callback\n * invocation this bug was found against. The real model lives in\n * `extraParams.invocation_params.model` (see `chat_models.cjs`'s\n * `invocationParams()` — every provider's chat model puts its model field\n * there before calling `handleChatModelStart`/`handleLLMStart`).\n * `llm.name` is kept only as a last-resort fallback for providers that\n * don't populate `invocation_params.model` for some reason.\n */\nfunction llmModelOf(\n llm: SerializedLike | undefined,\n extraParams?: Record<string, unknown>,\n): string {\n const invocationParams = extraParams?.invocation_params;\n if (invocationParams && typeof invocationParams === \"object\") {\n const model =\n (invocationParams as { model?: unknown; model_name?: unknown }).model ??\n (invocationParams as { model?: unknown; model_name?: unknown }).model_name;\n if (typeof model === \"string\" && model.length > 0) return model;\n }\n if (llm !== undefined && typeof llm.name === \"string\" && llm.name.length > 0) {\n return llm.name;\n }\n return \"unknown\";\n}\n\nfunction toolNameOf(tool: SerializedLike | undefined): string {\n if (tool !== undefined && typeof tool.name === \"string\" && tool.name.length > 0) {\n return tool.name;\n }\n return \"unknown\";\n}\n\n/**\n * LangChain JS passes `handleChatModelStart` a nested `BaseMessage[][]` —\n * one array per \"prompt\" in a batch call. The decomposer expects a flat\n * list of message objects, so flatten one level (mirrors Python's\n * `_flatten_messages` in `adapters/langgraph.py`).\n */\nfunction flattenMessages(messages: BaseMessageLike[][] | undefined): BaseMessageLike[] {\n if (!Array.isArray(messages)) return [];\n const flat: BaseMessageLike[] = [];\n for (const item of messages) {\n if (Array.isArray(item)) {\n flat.push(...item);\n } else if (item !== undefined && item !== null) {\n flat.push(item as unknown as BaseMessageLike);\n }\n }\n return flat;\n}\n\n/** Extract the bound `tools` array from `handleChatModelStart`'s `extra.invocation_params`. */\nfunction toolsFromExtra(extra: Record<string, unknown> | undefined): unknown {\n const invocationParams = extra?.invocation_params as Record<string, unknown> | undefined;\n return invocationParams?.tools;\n}\n\nfunction applyTokenUsage(handle: SpanHandle, output: LLMResultLike | undefined): void {\n const usage = output?.llmOutput?.tokenUsage;\n if (!usage || typeof usage !== \"object\") return;\n const prompt = (usage as Record<string, unknown>).promptTokens;\n const completion = (usage as Record<string, unknown>).completionTokens;\n const total = (usage as Record<string, unknown>).totalTokens;\n if (typeof prompt === \"number\" && Number.isFinite(prompt)) {\n handle.span.input_tokens = prompt;\n }\n if (typeof completion === \"number\" && Number.isFinite(completion)) {\n handle.span.output_tokens = completion;\n }\n if (typeof total === \"number\" && Number.isFinite(total)) {\n handle.span.total_tokens = total;\n } else if (\n typeof handle.span.input_tokens === \"number\" &&\n typeof handle.span.output_tokens === \"number\"\n ) {\n handle.span.total_tokens = handle.span.input_tokens + handle.span.output_tokens;\n }\n if (\n handle.span.cost_usd === undefined &&\n handle.span.model &&\n (typeof handle.span.input_tokens === \"number\" || typeof handle.span.output_tokens === \"number\")\n ) {\n const cost = calculateCost({\n inputTokens: handle.span.input_tokens ?? 0,\n outputTokens: handle.span.output_tokens ?? 0,\n model: handle.span.model,\n });\n if (cost !== undefined) handle.span.cost_usd = cost;\n }\n}\n\nfunction popAndEnd(\n map: Map<string, SpanHandle>,\n runId: string,\n err?: unknown,\n mutate?: (handle: SpanHandle) => void,\n): void {\n const handle = map.get(runId);\n if (handle === undefined) return;\n map.delete(runId);\n if (mutate !== undefined) {\n mutate(handle);\n }\n if (err !== undefined) {\n handle.end(err);\n } else {\n handle.end();\n }\n}\n\n/* ------------------------------------------------------------------------ */\n/* Factory */\n/* ------------------------------------------------------------------------ */\n\n/**\n * Build the llm + tool slice of an `MorseCallbackHandler`. The\n * returned object can be merged onto the host class instance (W3-L); each\n * method mutates `state` in place so all three fragments share the same\n * `runId → SpanHandle` maps.\n *\n * Every method body is wrapped in `absorbErrorsSync` — telemetry never\n * throws into the LangGraph runtime.\n */\nexport function createLlmAndToolHandlers(\n state: LangGraphRunState,\n options: LlmAndToolHandlerOptions = {},\n): LlmAndToolHandlers {\n const toolInputOpts = options.toolInputMaxBytes\n ? { maxBytes: options.toolInputMaxBytes }\n : undefined;\n const toolOutputOpts = options.toolOutputMaxBytes\n ? { maxBytes: options.toolOutputMaxBytes }\n : undefined;\n\n const _handleLLMStart = (\n llm: SerializedLike,\n _prompts: string[],\n runId: string,\n _parentRunId?: string,\n extraParams?: Record<string, unknown>,\n ): void => {\n const handle = emitLlmSpan({\n adapter: ADAPTER,\n model: llmModelOf(llm, extraParams),\n provider: extractProvider(llm?.id),\n });\n if (handle !== null) {\n state.llmSpans.set(runId, handle);\n }\n };\n\n const _handleChatModelStart = (\n llm: SerializedLike,\n messages: BaseMessageLike[][],\n runId: string,\n _parentRunId?: string,\n extraParams?: Record<string, unknown>,\n ): void => {\n // Chat models ARE LLMs — emit a `type=llm` span, same as handleLLMStart.\n // MHQ-750: also decompose the flattened messages (+ bound tools, if\n // any) into context_segments so the dashboard shows context\n // composition for LangGraph JS spans without extra customer config.\n const flatMessages = flattenMessages(messages);\n const contextSegments = decomposeOpenAiMessages(flatMessages, toolsFromExtra(extraParams));\n const handle = emitLlmSpan({\n adapter: ADAPTER,\n model: llmModelOf(llm, extraParams),\n provider: extractProvider(llm?.id),\n contextSegments: contextSegments.length > 0 ? contextSegments : undefined,\n });\n if (handle !== null) {\n state.llmSpans.set(runId, handle);\n }\n };\n\n const _handleLLMEnd = (output: LLMResultLike, runId: string): void => {\n popAndEnd(state.llmSpans, runId, undefined, (handle) => {\n applyTokenUsage(handle, output);\n });\n };\n\n const _handleLLMError = (err: unknown, runId: string): void => {\n popAndEnd(state.llmSpans, runId, err);\n };\n\n const _handleToolStart = (tool: SerializedLike, input: string, runId: string): void => {\n const handle = emitToolSpan({\n adapter: ADAPTER,\n toolName: toolNameOf(tool),\n inputSummary: summarizeToolInput(input, toolInputOpts),\n });\n if (handle !== null) {\n state.toolSpans.set(runId, handle);\n }\n };\n\n const _handleToolEnd = (output: string, runId: string): void => {\n popAndEnd(state.toolSpans, runId, undefined, (handle) => {\n const md = (handle.span.metadata ??= {} as Record<string, unknown>);\n md.tool_output_summary = summarizeToolOutput(output, toolOutputOpts);\n md.success = true;\n });\n };\n\n const _handleToolError = (err: unknown, runId: string): void => {\n popAndEnd(state.toolSpans, runId, err, (handle) => {\n const md = (handle.span.metadata ??= {} as Record<string, unknown>);\n md.success = false;\n });\n };\n\n const fp = \"morse.adapters.langgraph.llm-and-tool\";\n\n return {\n handleLLMStart: absorbErrorsSync(_handleLLMStart, { fingerprint: `${fp}.handleLLMStart` }),\n handleChatModelStart: absorbErrorsSync(_handleChatModelStart, {\n fingerprint: `${fp}.handleChatModelStart`,\n }),\n handleLLMEnd: absorbErrorsSync(_handleLLMEnd, { fingerprint: `${fp}.handleLLMEnd` }),\n handleLLMError: absorbErrorsSync(_handleLLMError, { fingerprint: `${fp}.handleLLMError` }),\n handleToolStart: absorbErrorsSync(_handleToolStart, { fingerprint: `${fp}.handleToolStart` }),\n handleToolEnd: absorbErrorsSync(_handleToolEnd, { fingerprint: `${fp}.handleToolEnd` }),\n handleToolError: absorbErrorsSync(_handleToolError, { fingerprint: `${fp}.handleToolError` }),\n };\n}\n","/**\n * `langgraph/streaming-and-checkpoint.ts` — Phase 13 W2-L.3.\n *\n * Implements streaming-token aggregation for LangGraph JS. Per the design\n * doc, streaming tokens fire `handleLLMNewToken` at very high frequency —\n * we do NOT emit a span per token (would explode volume). Instead we\n * aggregate them onto the parent llm span's `metadata.tokens_streamed`\n * counter so downstream consumers can observe streaming activity without\n * the cardinality blowup.\n *\n * Checkpoint hooks (PostgresSaver / SqliteSaver / MemorySaver) are\n * deferred to v1.5 per the design doc. The surface is left empty here;\n * W3-L composes this module with the others and may add checkpoint\n * instrumentation in a follow-up wave without touching the wiring.\n *\n * All wrappers route through `absorbErrorsSync` — telemetry MUST NOT\n * throw at the caller.\n */\n\nimport { absorbErrorsSync } from \"../_internal/errors\";\nimport type { SpanHandle } from \"../_internal/tracing\";\nimport type { CallbackHandlerSurface } from \"./types\";\n\nconst ADAPTER_FINGERPRINT = \"langgraph.streaming\" as const;\n\n/** State carried across streaming-token events for an in-flight chain run. */\nexport interface StreamingState {\n /** Map of `runId` → SpanHandle (the in-flight llm span W2-L.2 opened). */\n llmSpans: Map<string, SpanHandle>;\n}\n\nexport interface StreamingHandlerOptions {\n /**\n * If true, emit a single `tokens_streamed` metadata count on the parent\n * llm span; default true. If false, the handler is a no-op (useful when\n * the host already tracks streaming elsewhere or wants to minimise\n * mutation under hot streaming loops).\n */\n trackStreamingTokens?: boolean;\n}\n\n/**\n * Returns the streaming-related callback method implementations.\n *\n * Currently exposes only `handleLLMNewToken`. Checkpoint methods\n * (`handleCheckpointStart` / `handleCheckpointEnd`) are not on the\n * `CallbackHandlerSurface` for v1 — they will land in v1.5 when we wire\n * the PostgresSaver/SqliteSaver hooks. Keeping this module in place\n * means W3-L's composition does not change shape when those land.\n */\nexport function createStreamingHandlers(\n state: StreamingState,\n options?: StreamingHandlerOptions,\n): Pick<CallbackHandlerSurface, \"handleLLMNewToken\"> {\n const trackStreamingTokens = options?.trackStreamingTokens ?? true;\n\n const handleLLMNewToken = absorbErrorsSync(\n (_token: string, _idx: { prompt: number; completion: number }, runId: string): void => {\n if (!trackStreamingTokens) return;\n const handle = state.llmSpans.get(runId);\n if (handle === undefined) {\n // No matching llm span — happens when the host fires tokens\n // before `handleLLMStart` or after `handleLLMEnd`, or when the\n // runId is unknown (orphan event). Drop silently.\n return;\n }\n const md = (handle.span.metadata ?? {}) as Record<string, unknown>;\n const prev = typeof md.tokens_streamed === \"number\" ? md.tokens_streamed : 0;\n md.tokens_streamed = prev + 1;\n handle.span.metadata = md;\n },\n { fingerprint: ADAPTER_FINGERPRINT },\n );\n\n return { handleLLMNewToken };\n}\n","/**\n * `@morsehq-dev/sdk/langgraph` — adapter for `@langchain/langgraph` (langgraphjs).\n *\n * W3-L: composes the three W2-L surfaces into a single\n * `MorseCallbackHandler` class exposing the full\n * `BaseCallbackHandler` shape LangGraph requires:\n *\n * - chain start/end/error — from W2-L.1 (`callback-handler.ts`)\n * - llm + tool start/end/error — from W2-L.2 (`llm-and-tool-callbacks.ts`)\n * - llm new-token streaming — from W2-L.3 (`streaming-and-checkpoint.ts`)\n *\n * Users get a single class to register with LangGraph:\n *\n * ```ts\n * import { MorseCallbackHandler } from \"@morsehq-dev/sdk/langgraph\";\n * await app.invoke(input, { callbacks: [new MorseCallbackHandler()] });\n * ```\n *\n * The W2-L.1 base class keeps its own private map of open chain spans\n * (since it predates the shared `LangGraphRunState`). To keep things\n * coherent for advanced consumers reading `state`, the composed class\n * overrides `handleChainStart` / `handleChainEnd` / `handleChainError`\n * to ALSO maintain `state.chainSpans` in addition to calling the\n * super-class method. The base-class behavior is unchanged.\n */\n\nimport type { SpanHandle } from \"../_internal/tracing\";\nimport {\n MorseCallbackHandler as BaseMorseCallbackHandler,\n type MorseCallbackHandlerOptions,\n getCallbackHandlerClass,\n} from \"./callback-handler\";\nimport {\n createLlmAndToolHandlers,\n type LangGraphRunState,\n type LlmAndToolHandlerOptions,\n} from \"./llm-and-tool-callbacks\";\nimport { createStreamingHandlers, type StreamingHandlerOptions } from \"./streaming-and-checkpoint\";\nimport type { CallbackHandlerSurface, SerializedLike } from \"./types\";\n\n/** Combined options for the composed handler. */\nexport type ComposedMorseCallbackHandlerOptions = MorseCallbackHandlerOptions &\n LlmAndToolHandlerOptions &\n StreamingHandlerOptions;\n\n/**\n * Composed `MorseCallbackHandler` — the user-facing class.\n *\n * Inherits chain handlers from `BaseMorseCallbackHandler` (W2-L.1)\n * and attaches the W2-L.2 llm/tool methods and W2-L.3 streaming method\n * onto each instance. All four sources share a single\n * `LangGraphRunState` so future cross-method correlation can read\n * llm/tool/chain maps from one place.\n */\nexport class MorseCallbackHandler\n extends BaseMorseCallbackHandler\n implements CallbackHandlerSurface\n{\n private readonly _state: LangGraphRunState;\n\n // The slotted methods from W2-L.2 / W2-L.3 — `!` because they are\n // assigned in the constructor via `Object.assign`-style copy.\n public handleLLMStart!: NonNullable<CallbackHandlerSurface[\"handleLLMStart\"]>;\n public handleChatModelStart!: NonNullable<CallbackHandlerSurface[\"handleChatModelStart\"]>;\n public handleLLMEnd!: NonNullable<CallbackHandlerSurface[\"handleLLMEnd\"]>;\n public handleLLMError!: NonNullable<CallbackHandlerSurface[\"handleLLMError\"]>;\n public handleToolStart!: NonNullable<CallbackHandlerSurface[\"handleToolStart\"]>;\n public handleToolEnd!: NonNullable<CallbackHandlerSurface[\"handleToolEnd\"]>;\n public handleToolError!: NonNullable<CallbackHandlerSurface[\"handleToolError\"]>;\n public handleLLMNewToken!: NonNullable<CallbackHandlerSurface[\"handleLLMNewToken\"]>;\n\n constructor(options?: ComposedMorseCallbackHandlerOptions) {\n super(options);\n\n this._state = {\n llmSpans: new Map<string, SpanHandle>(),\n toolSpans: new Map<string, SpanHandle>(),\n chainSpans: new Map<string, SpanHandle>(),\n };\n\n const llmAndTool = createLlmAndToolHandlers(this._state, {\n toolInputMaxBytes: options?.toolInputMaxBytes,\n toolOutputMaxBytes: options?.toolOutputMaxBytes,\n });\n const streaming = createStreamingHandlers(this._state, {\n trackStreamingTokens: options?.trackStreamingTokens,\n });\n\n // Copy method implementations onto the instance so LangGraph (which\n // looks up handlers via `typeof handler[method] === \"function\"` on\n // the instance) sees them. Use non-null assertions because the\n // factories always return defined methods.\n this.handleLLMStart = llmAndTool.handleLLMStart!;\n this.handleChatModelStart = llmAndTool.handleChatModelStart!;\n this.handleLLMEnd = llmAndTool.handleLLMEnd!;\n this.handleLLMError = llmAndTool.handleLLMError!;\n this.handleToolStart = llmAndTool.handleToolStart!;\n this.handleToolEnd = llmAndTool.handleToolEnd!;\n this.handleToolError = llmAndTool.handleToolError!;\n this.handleLLMNewToken = streaming.handleLLMNewToken!;\n }\n\n /**\n * The W2-L.1 base maintains its own private chain-span map. We\n * mirror chain handles into the shared `LangGraphRunState` so future\n * cross-fragment logic can correlate by runId. Never throws — the\n * map mutation is in-process and the super method already absorbs\n * errors via `absorbErrorsSync`.\n */\n override handleChainStart(\n chain: SerializedLike,\n inputs: Record<string, unknown>,\n runId: string,\n parentRunId?: string,\n tags?: string[],\n metadata?: Record<string, unknown>,\n runType?: string,\n runName?: string,\n ): void {\n super.handleChainStart(chain, inputs, runId, parentRunId, tags, metadata, runType, runName);\n // Mirror — read the now-open span from the base via the internal\n // accessor used in tests, then re-insert it (the base `_takeSpan`\n // deletes on read, so we'd break the base if we used it here).\n // Instead reach into the base via the public-ish `_setSpan` would\n // double-insert; safer to keep our own shadow keyed off the same\n // runId.\n this._shadowSetChainSpan(runId);\n }\n\n override handleChainEnd(\n outputs: Record<string, unknown>,\n runId: string,\n parentRunId?: string,\n ): void {\n super.handleChainEnd(outputs, runId, parentRunId);\n this._state.chainSpans.delete(runId);\n }\n\n override handleChainError(err: unknown, runId: string, parentRunId?: string): void {\n super.handleChainError(err, runId, parentRunId);\n this._state.chainSpans.delete(runId);\n }\n\n /**\n * Marker insertion for the shared chainSpans map. The W2-L.1 base\n * holds the real `SpanHandle` privately; for the shared map we just\n * need *presence* keyed by runId so downstream fragments can detect\n * an in-flight chain. We stash a sentinel handle whose `end()` is a\n * no-op — the base owns the real lifecycle.\n */\n private _shadowSetChainSpan(runId: string): void {\n if (typeof runId !== \"string\" || runId.length === 0) return;\n const sentinel: SpanHandle = {\n // The base owns the real SpanData — for the shadow we use a\n // minimal stand-in. Downstream readers only check map membership,\n // not field access on this object.\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n span: {} as any,\n end(): void {\n /* no-op */\n },\n };\n this._state.chainSpans.set(runId, sentinel);\n }\n}\n\n/* ------------------------------------------------------------------------ */\n/* Re-exports */\n/* ------------------------------------------------------------------------ */\n\n// Low-level pieces for advanced users who want to compose their own\n// handler shape.\nexport { BaseMorseCallbackHandler };\nexport { getCallbackHandlerClass };\nexport { createLlmAndToolHandlers } from \"./llm-and-tool-callbacks\";\nexport { createStreamingHandlers } from \"./streaming-and-checkpoint\";\n\nexport type {\n MorseCallbackHandlerOptions,\n LangGraphRunState,\n LlmAndToolHandlerOptions,\n StreamingHandlerOptions,\n};\n\nexport type {\n BaseMessageLike,\n CallbackHandlerSurface,\n LangChainCoreCallbacksModuleLike,\n LLMResultLike,\n SerializedLike,\n} from \"./types\";\n"]}
|
|
1
|
+
{"version":3,"sources":["../../src/langgraph/callback-handler.ts","../../src/langgraph/llm-and-tool-callbacks.ts","../../src/langgraph/streaming-and-checkpoint.ts","../../src/langgraph/index.ts"],"names":["ADAPTER","MorseCallbackHandler"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * `@morsehq-dev/sdk/langgraph` — `MorseCallbackHandler` (W2-L.1).\n *\n * The handler is registered by LangGraph users via:\n *\n * ```ts\n * import { MorseCallbackHandler } from \"@morsehq-dev/sdk/langgraph\";\n * await app.invoke(input, { callbacks: [new MorseCallbackHandler()] });\n * ```\n *\n * LangGraph type-checks handlers structurally (by method presence on the\n * instance), not via `instanceof BaseCallbackHandler`. We therefore:\n *\n * 1. Always export a duck-typed class implementing `CallbackHandlerSurface`\n * — works without `@langchain/core` installed.\n * 2. Provide `getCallbackHandlerClass()` for users who rely on\n * `instanceof BaseCallbackHandler` — it dynamically loads\n * `@langchain/core/callbacks/base` (optional peer dep) and returns a\n * subclass whose prototype chain includes the real base class.\n *\n * Scope of THIS file (W2-L.1): chain spans only. `handleChainStart` opens\n * an `agent` span (the LangGraph chain IS the agent run); `handleChainEnd`\n * / `handleChainError` closes it. Nested chains nest via the per-runId\n * span map — LangGraph guarantees well-ordered start/end pairs so the\n * tracing-state span stack handles `parent_span_id` linkage for us.\n *\n * `handleLLMStart/End`, `handleToolStart/End`, and streaming callbacks\n * are implemented in W2-L.2 / W2-L.3 as separate methods on the same\n * class (composed in Wave 3-L).\n */\n\nimport { absorbErrorsSync } from \"../_internal/errors\";\nimport type { SpanHandle } from \"../_internal/tracing\";\nimport { emitAgentSpan } from \"../_agent-sdk-common/span-emitter\";\nimport type {\n CallbackHandlerSurface,\n LangChainCoreCallbacksModuleLike,\n SerializedLike,\n} from \"./types\";\n\n/* ------------------------------------------------------------------------ */\n/* Public surface */\n/* ------------------------------------------------------------------------ */\n\nexport interface MorseCallbackHandlerOptions {\n /**\n * Override the agent name on the outer chain span. Falls back, in order,\n * to: `runName` (LangGraph-supplied per-invocation name), `chain.name`\n * (the serialized class name), then `\"langgraph-agent\"`.\n */\n defaultAgentName?: string;\n}\n\nconst ADAPTER = \"langgraph-js\";\nconst HANDLER_NAME = \"morse_callback_handler\";\nconst DEFAULT_AGENT_NAME_FALLBACK = \"langgraph-agent\";\n\n/**\n * Duck-typed LangGraph `BaseCallbackHandler`. Implements `CallbackHandlerSurface`\n * with chain-start / chain-end / chain-error wired to the Morse trace.\n *\n * LangGraph routes callbacks to instance methods by name; it does NOT require\n * an `instanceof` check against the real `BaseCallbackHandler`. Users who\n * need that (rare; `instanceof` checks in custom middleware) should obtain\n * the class via `getCallbackHandlerClass()` instead.\n */\nexport class MorseCallbackHandler implements CallbackHandlerSurface {\n /** Required by LangGraph's `BaseCallbackHandler` interface. */\n public readonly name: string = HANDLER_NAME;\n\n private readonly defaultAgentName: string | undefined;\n\n /** Open chain spans, keyed by LangGraph `runId`. */\n private readonly chainSpans: Map<string, SpanHandle> = new Map();\n\n constructor(options?: MorseCallbackHandlerOptions) {\n this.defaultAgentName = options?.defaultAgentName;\n }\n\n handleChainStart(\n chain: SerializedLike,\n _inputs: Record<string, unknown>,\n runId: string,\n _parentRunId?: string,\n _tags?: string[],\n _metadata?: Record<string, unknown>,\n _runType?: string,\n runName?: string,\n ): void {\n _handleChainStartImpl(this, chain, runId, runName);\n }\n\n handleChainEnd(_outputs: Record<string, unknown>, runId: string, parentRunId?: string): void {\n void parentRunId;\n _handleChainEndImpl(this, runId);\n }\n\n handleChainError(err: unknown, runId: string, parentRunId?: string): void {\n void parentRunId;\n _handleChainErrorImpl(this, err, runId);\n }\n\n /* ------ Internal accessors used by the absorbErrorsSync-wrapped impls ----- */\n\n /** @internal */\n _setSpan(runId: string, handle: SpanHandle): void {\n this.chainSpans.set(runId, handle);\n }\n\n /** @internal */\n _takeSpan(runId: string): SpanHandle | undefined {\n const handle = this.chainSpans.get(runId);\n if (handle) this.chainSpans.delete(runId);\n return handle;\n }\n\n /** @internal */\n _resolveAgentName(chain: SerializedLike | undefined, runName: string | undefined): string {\n if (typeof runName === \"string\" && runName.length > 0) return runName;\n if (chain && typeof chain.name === \"string\" && chain.name.length > 0) return chain.name;\n if (this.defaultAgentName && this.defaultAgentName.length > 0) return this.defaultAgentName;\n return DEFAULT_AGENT_NAME_FALLBACK;\n }\n}\n\n/* ------------------------------------------------------------------------ */\n/* Implementation bodies (wrapped in absorbErrorsSync) */\n/* ------------------------------------------------------------------------ */\n\nconst _handleChainStartImpl: (\n self: MorseCallbackHandler,\n chain: SerializedLike | undefined,\n runId: string,\n runName: string | undefined,\n) => void = absorbErrorsSync(\n (\n self: MorseCallbackHandler,\n chain: SerializedLike | undefined,\n runId: string,\n runName: string | undefined,\n ) => {\n if (typeof runId !== \"string\" || runId.length === 0) return;\n // Defensive: if LangGraph re-fires start for the same runId, leak nothing.\n if (self._takeSpan(runId)) {\n // (we just popped it — drop on the floor; the dangling end will be a no-op)\n }\n const agentName = self._resolveAgentName(chain, runName);\n const handle = emitAgentSpan({ adapter: ADAPTER, agentName });\n if (handle) self._setSpan(runId, handle);\n },\n { fingerprint: \"morse.langgraph.handleChainStart\" },\n) as (\n self: MorseCallbackHandler,\n chain: SerializedLike | undefined,\n runId: string,\n runName: string | undefined,\n) => void;\n\nconst _handleChainEndImpl: (self: MorseCallbackHandler, runId: string) => void = absorbErrorsSync(\n (self: MorseCallbackHandler, runId: string) => {\n const handle = self._takeSpan(runId);\n if (handle) handle.end();\n },\n { fingerprint: \"morse.langgraph.handleChainEnd\" },\n) as (self: MorseCallbackHandler, runId: string) => void;\n\nconst _handleChainErrorImpl: (self: MorseCallbackHandler, err: unknown, runId: string) => void =\n absorbErrorsSync(\n (self: MorseCallbackHandler, err: unknown, runId: string) => {\n const handle = self._takeSpan(runId);\n if (handle) handle.end(err ?? new Error(\"langgraph chain error\"));\n },\n { fingerprint: \"morse.langgraph.handleChainError\" },\n ) as (self: MorseCallbackHandler, err: unknown, runId: string) => void;\n\n/* ------------------------------------------------------------------------ */\n/* Optional peer-dep: real BaseCallbackHandler */\n/* ------------------------------------------------------------------------ */\n\nasync function loadLangChainCoreCallbacks(): Promise<LangChainCoreCallbacksModuleLike | null> {\n try {\n // Function-eval'd dynamic import keeps bundlers from trying to resolve\n // `@langchain/core/callbacks/base` at build time when the dep isn't installed.\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const mod = (await (Function(\"m\", \"return import(m)\") as any)(\n \"@langchain/core/callbacks/base\",\n )) as LangChainCoreCallbacksModuleLike;\n return mod ?? null;\n } catch {\n return null;\n }\n}\n\n/**\n * Best-effort: if `@langchain/core/callbacks/base` is installed at runtime,\n * return an `MorseCallbackHandler`-shaped class whose prototype chain\n * includes the real `BaseCallbackHandler` (for users relying on\n * `instanceof BaseCallbackHandler` checks). Otherwise return the\n * duck-typed `MorseCallbackHandler` defined above.\n */\nexport async function getCallbackHandlerClass(): Promise<typeof MorseCallbackHandler> {\n const mod = await loadLangChainCoreCallbacks();\n const Base = mod?.BaseCallbackHandler;\n if (!Base) return MorseCallbackHandler;\n\n // Build a subclass that mixes the real Base class into the prototype chain\n // while preserving the chain-span behavior. We do this lazily so that\n // simply importing this module does NOT require `@langchain/core`.\n class MorseCallbackHandlerWithBase extends (Base as unknown as {\n new (...args: unknown[]): object;\n }) {\n public readonly name: string = HANDLER_NAME;\n private readonly _av: MorseCallbackHandler;\n constructor(options?: MorseCallbackHandlerOptions) {\n super();\n this._av = new MorseCallbackHandler(options);\n }\n handleChainStart(\n chain: SerializedLike,\n inputs: Record<string, unknown>,\n runId: string,\n parentRunId?: string,\n tags?: string[],\n metadata?: Record<string, unknown>,\n runType?: string,\n runName?: string,\n ): void {\n this._av.handleChainStart(\n chain,\n inputs,\n runId,\n parentRunId,\n tags,\n metadata,\n runType,\n runName,\n );\n }\n handleChainEnd(outputs: Record<string, unknown>, runId: string, parentRunId?: string): void {\n this._av.handleChainEnd(outputs, runId, parentRunId);\n }\n handleChainError(err: unknown, runId: string, parentRunId?: string): void {\n this._av.handleChainError(err, runId, parentRunId);\n }\n }\n return MorseCallbackHandlerWithBase as unknown as typeof MorseCallbackHandler;\n}\n","/**\n * `langgraph/llm-and-tool-callbacks.ts` — W2-L.2.\n *\n * LangGraph JS callback handler fragment that owns the llm + tool surface\n * of `BaseCallbackHandler`. The class shell (constructor + chain methods)\n * is owned by W2-L.1 (`callback-handler.ts`); streaming + checkpoint by\n * W2-L.3 (`streaming-and-checkpoint.ts`). All three are composed together\n * by W3-L (`langgraph/index.ts`).\n *\n * To stay file-disjoint across the three W2-L tasks, each fragment exports\n * a `createX` factory that returns plain method implementations operating\n * on a shared mutable `LangGraphRunState`. The host class threads its\n * `state` reference through each factory in its constructor and copies the\n * methods onto its prototype/instance.\n *\n * Logical span mapping (per design.md §LangGraph JS):\n * handleLLMStart / handleChatModelStart → open `type=llm` span\n * handleLLMEnd / handleLLMError → close active llm span\n * handleToolStart → open `type=tool` span\n * handleToolEnd / handleToolError → close active tool span\n *\n * MHQ-750: `handleChatModelStart` also decomposes the flattened messages\n * (+ any bound `tools`) into `context_segments` via the shared\n * `_agent-sdk-common/context-decomposer`, mirroring the Python adapter's\n * `on_chat_model_start` (`adapters/langgraph.py`), which calls the same\n * `decompose_openai_messages` for the same reason: LangGraph JS messages\n * are `@langchain/core` `BaseMessage`s, which decompose cleanly under the\n * OpenAI-chat-format decomposer's `_getType()`/`.type` duck-typing.\n *\n * All bodies are wrapped in `absorbErrorsSync` so telemetry can never\n * throw at the host LangGraph runtime.\n */\n\nimport { absorbErrorsSync } from \"../_internal/errors\";\nimport { calculateCost } from \"../_internal/pricing\";\nimport type { SpanHandle } from \"../_internal/tracing\";\nimport { emitLlmSpan, emitToolSpan } from \"../_agent-sdk-common/span-emitter\";\nimport { setActiveFramework } from \"../_internal/active-framework\";\nimport {\n captureLangChainMessages,\n capturePrompts,\n extractLangChainOutputText,\n} from \"../_internal/llm-io\";\nimport { summarizeToolInput, summarizeToolOutput } from \"../_agent-sdk-common/redaction\";\nimport { decomposeOpenAiMessages } from \"../_agent-sdk-common/context-decomposer\";\nimport type {\n BaseMessageLike,\n CallbackHandlerSurface,\n LLMResultLike,\n SerializedLike,\n} from \"./types\";\n\nconst ADAPTER = \"langgraph-js\" as const;\n// MHQ-859: the framework label is cross-language and must match Python's\n// `langgraph.py::_framework_name` exactly — it is what the server groups on,\n// so \"langgraph-js\" here would split one framework into two.\nconst FRAMEWORK = \"langgraph\" as const;\n\n/* ------------------------------------------------------------------------ */\n/* Shared run state */\n/* ------------------------------------------------------------------------ */\n\n/**\n * Shared per-instance state for the composed `MorseCallbackHandler`.\n * Owned/instantiated by W3-L (`langgraph/index.ts`); each W2-L fragment\n * mutates it in place.\n */\nexport interface LangGraphRunState {\n /** Map of runId → SpanHandle for open llm spans. */\n llmSpans: Map<string, SpanHandle>;\n /** Map of runId → SpanHandle for open tool spans. */\n toolSpans: Map<string, SpanHandle>;\n /** Map of runId → SpanHandle for open chain spans (populated by W2-L.1). */\n chainSpans: Map<string, SpanHandle>;\n}\n\nexport interface LlmAndToolHandlerOptions {\n /** Max bytes for tool input summary. Falls through to module default if unset. */\n toolInputMaxBytes?: number;\n /** Max bytes for tool output summary. Falls through to module default if unset. */\n toolOutputMaxBytes?: number;\n}\n\n/** Convenient public type alias for the slice of methods this file owns. */\nexport type LlmAndToolHandlers = Pick<\n CallbackHandlerSurface,\n | \"handleLLMStart\"\n | \"handleChatModelStart\"\n | \"handleLLMEnd\"\n | \"handleLLMError\"\n | \"handleToolStart\"\n | \"handleToolEnd\"\n | \"handleToolError\"\n>;\n\n/* ------------------------------------------------------------------------ */\n/* Helpers */\n/* ------------------------------------------------------------------------ */\n\n/**\n * Extract a provider hint from the `id` path produced by LangChain's\n * `Serializable` machinery. The first segment is usually the package name\n * (`langchain_openai`, `langchain_anthropic`, `langchain_google_vertexai`,\n * etc.). We strip the `langchain_` prefix when present and return the\n * remainder; otherwise we return the first segment verbatim. Returns\n * `undefined` when no identifying segment is available.\n */\nfunction extractProvider(id: string[] | undefined): string | undefined {\n if (!Array.isArray(id) || id.length === 0) return undefined;\n const first = id[0];\n if (typeof first !== \"string\" || first.length === 0) return undefined;\n if (first.startsWith(\"langchain_\")) {\n const tail = first.slice(\"langchain_\".length);\n return tail.length > 0 ? tail : undefined;\n }\n return first;\n}\n\n/**\n * MHQ-788: `llm.name` is LangChain's `Serializable` class name (e.g.\n * `\"ChatOpenAI\"`), never the actual model string — it was always the wrong\n * field, and empty in practice for the real `@langchain/openai` callback\n * invocation this bug was found against. The real model lives in\n * `extraParams.invocation_params.model` (see `chat_models.cjs`'s\n * `invocationParams()` — every provider's chat model puts its model field\n * there before calling `handleChatModelStart`/`handleLLMStart`).\n * `llm.name` is kept only as a last-resort fallback for providers that\n * don't populate `invocation_params.model` for some reason.\n */\nfunction llmModelOf(\n llm: SerializedLike | undefined,\n extraParams?: Record<string, unknown>,\n): string {\n const invocationParams = extraParams?.invocation_params;\n if (invocationParams && typeof invocationParams === \"object\") {\n const model =\n (invocationParams as { model?: unknown; model_name?: unknown }).model ??\n (invocationParams as { model?: unknown; model_name?: unknown }).model_name;\n if (typeof model === \"string\" && model.length > 0) return model;\n }\n if (llm !== undefined && typeof llm.name === \"string\" && llm.name.length > 0) {\n return llm.name;\n }\n return \"unknown\";\n}\n\nfunction toolNameOf(tool: SerializedLike | undefined): string {\n if (tool !== undefined && typeof tool.name === \"string\" && tool.name.length > 0) {\n return tool.name;\n }\n return \"unknown\";\n}\n\n/**\n * LangChain JS passes `handleChatModelStart` a nested `BaseMessage[][]` —\n * one array per \"prompt\" in a batch call. The decomposer expects a flat\n * list of message objects, so flatten one level (mirrors Python's\n * `_flatten_messages` in `adapters/langgraph.py`).\n */\nfunction flattenMessages(messages: BaseMessageLike[][] | undefined): BaseMessageLike[] {\n if (!Array.isArray(messages)) return [];\n const flat: BaseMessageLike[] = [];\n for (const item of messages) {\n if (Array.isArray(item)) {\n flat.push(...item);\n } else if (item !== undefined && item !== null) {\n flat.push(item as unknown as BaseMessageLike);\n }\n }\n return flat;\n}\n\n/** Extract the bound `tools` array from `handleChatModelStart`'s `extra.invocation_params`. */\nfunction toolsFromExtra(extra: Record<string, unknown> | undefined): unknown {\n const invocationParams = extra?.invocation_params as Record<string, unknown> | undefined;\n return invocationParams?.tools;\n}\n\nfunction applyTokenUsage(handle: SpanHandle, output: LLMResultLike | undefined): void {\n const usage = output?.llmOutput?.tokenUsage;\n if (!usage || typeof usage !== \"object\") return;\n const prompt = (usage as Record<string, unknown>).promptTokens;\n const completion = (usage as Record<string, unknown>).completionTokens;\n const total = (usage as Record<string, unknown>).totalTokens;\n if (typeof prompt === \"number\" && Number.isFinite(prompt)) {\n handle.span.input_tokens = prompt;\n }\n if (typeof completion === \"number\" && Number.isFinite(completion)) {\n handle.span.output_tokens = completion;\n }\n if (typeof total === \"number\" && Number.isFinite(total)) {\n handle.span.total_tokens = total;\n } else if (\n typeof handle.span.input_tokens === \"number\" &&\n typeof handle.span.output_tokens === \"number\"\n ) {\n handle.span.total_tokens = handle.span.input_tokens + handle.span.output_tokens;\n }\n if (\n handle.span.cost_usd === undefined &&\n handle.span.model &&\n (typeof handle.span.input_tokens === \"number\" || typeof handle.span.output_tokens === \"number\")\n ) {\n const cost = calculateCost({\n inputTokens: handle.span.input_tokens ?? 0,\n outputTokens: handle.span.output_tokens ?? 0,\n model: handle.span.model,\n });\n if (cost !== undefined) handle.span.cost_usd = cost;\n }\n}\n\nfunction popAndEnd(\n map: Map<string, SpanHandle>,\n runId: string,\n err?: unknown,\n mutate?: (handle: SpanHandle) => void,\n): void {\n const handle = map.get(runId);\n if (handle === undefined) return;\n map.delete(runId);\n if (mutate !== undefined) {\n mutate(handle);\n }\n if (err !== undefined) {\n handle.end(err);\n } else {\n handle.end();\n }\n}\n\n/* ------------------------------------------------------------------------ */\n/* Factory */\n/* ------------------------------------------------------------------------ */\n\n/**\n * Build the llm + tool slice of an `MorseCallbackHandler`. The\n * returned object can be merged onto the host class instance (W3-L); each\n * method mutates `state` in place so all three fragments share the same\n * `runId → SpanHandle` maps.\n *\n * Every method body is wrapped in `absorbErrorsSync` — telemetry never\n * throws into the LangGraph runtime.\n */\nexport function createLlmAndToolHandlers(\n state: LangGraphRunState,\n options: LlmAndToolHandlerOptions = {},\n): LlmAndToolHandlers {\n const toolInputOpts = options.toolInputMaxBytes\n ? { maxBytes: options.toolInputMaxBytes }\n : undefined;\n const toolOutputOpts = options.toolOutputMaxBytes\n ? { maxBytes: options.toolOutputMaxBytes }\n : undefined;\n\n const _handleLLMStart = (\n llm: SerializedLike,\n prompts: string[],\n runId: string,\n _parentRunId?: string,\n extraParams?: Record<string, unknown>,\n ): void => {\n setActiveFramework(FRAMEWORK);\n const handle = emitLlmSpan({\n adapter: ADAPTER,\n model: llmModelOf(llm, extraParams),\n provider: extractProvider(llm?.id),\n inputData: capturePrompts(prompts),\n });\n if (handle !== null) {\n state.llmSpans.set(runId, handle);\n }\n };\n\n const _handleChatModelStart = (\n llm: SerializedLike,\n messages: BaseMessageLike[][],\n runId: string,\n _parentRunId?: string,\n extraParams?: Record<string, unknown>,\n ): void => {\n // Chat models ARE LLMs — emit a `type=llm` span, same as handleLLMStart.\n // MHQ-750: also decompose the flattened messages (+ bound tools, if\n // any) into context_segments so the dashboard shows context\n // composition for LangGraph JS spans without extra customer config.\n const flatMessages = flattenMessages(messages);\n const contextSegments = decomposeOpenAiMessages(flatMessages, toolsFromExtra(extraParams));\n setActiveFramework(FRAMEWORK);\n const handle = emitLlmSpan({\n adapter: ADAPTER,\n model: llmModelOf(llm, extraParams),\n provider: extractProvider(llm?.id),\n contextSegments: contextSegments.length > 0 ? contextSegments : undefined,\n inputData: captureLangChainMessages(flatMessages),\n });\n if (handle !== null) {\n state.llmSpans.set(runId, handle);\n }\n };\n\n const _handleLLMEnd = (output: LLMResultLike, runId: string): void => {\n popAndEnd(state.llmSpans, runId, undefined, (handle) => {\n applyTokenUsage(handle, output);\n // MHQ-858: the response text is only available at end-of-call, so\n // output_data is set here rather than on the emitLlmSpan above.\n const outputText = extractLangChainOutputText(output?.generations);\n if (outputText !== undefined) handle.span.output_data = { content: outputText };\n });\n };\n\n const _handleLLMError = (err: unknown, runId: string): void => {\n popAndEnd(state.llmSpans, runId, err);\n };\n\n const _handleToolStart = (tool: SerializedLike, input: string, runId: string): void => {\n const handle = emitToolSpan({\n adapter: ADAPTER,\n toolName: toolNameOf(tool),\n inputSummary: summarizeToolInput(input, toolInputOpts),\n });\n if (handle !== null) {\n state.toolSpans.set(runId, handle);\n }\n };\n\n const _handleToolEnd = (output: string, runId: string): void => {\n popAndEnd(state.toolSpans, runId, undefined, (handle) => {\n const md = (handle.span.metadata ??= {} as Record<string, unknown>);\n md.tool_output_summary = summarizeToolOutput(output, toolOutputOpts);\n md.success = true;\n });\n };\n\n const _handleToolError = (err: unknown, runId: string): void => {\n popAndEnd(state.toolSpans, runId, err, (handle) => {\n const md = (handle.span.metadata ??= {} as Record<string, unknown>);\n md.success = false;\n });\n };\n\n const fp = \"morse.adapters.langgraph.llm-and-tool\";\n\n return {\n handleLLMStart: absorbErrorsSync(_handleLLMStart, { fingerprint: `${fp}.handleLLMStart` }),\n handleChatModelStart: absorbErrorsSync(_handleChatModelStart, {\n fingerprint: `${fp}.handleChatModelStart`,\n }),\n handleLLMEnd: absorbErrorsSync(_handleLLMEnd, { fingerprint: `${fp}.handleLLMEnd` }),\n handleLLMError: absorbErrorsSync(_handleLLMError, { fingerprint: `${fp}.handleLLMError` }),\n handleToolStart: absorbErrorsSync(_handleToolStart, { fingerprint: `${fp}.handleToolStart` }),\n handleToolEnd: absorbErrorsSync(_handleToolEnd, { fingerprint: `${fp}.handleToolEnd` }),\n handleToolError: absorbErrorsSync(_handleToolError, { fingerprint: `${fp}.handleToolError` }),\n };\n}\n","/**\n * `langgraph/streaming-and-checkpoint.ts` — Phase 13 W2-L.3.\n *\n * Implements streaming-token aggregation for LangGraph JS. Per the design\n * doc, streaming tokens fire `handleLLMNewToken` at very high frequency —\n * we do NOT emit a span per token (would explode volume). Instead we\n * aggregate them onto the parent llm span's `metadata.tokens_streamed`\n * counter so downstream consumers can observe streaming activity without\n * the cardinality blowup.\n *\n * Checkpoint hooks (PostgresSaver / SqliteSaver / MemorySaver) are\n * deferred to v1.5 per the design doc. The surface is left empty here;\n * W3-L composes this module with the others and may add checkpoint\n * instrumentation in a follow-up wave without touching the wiring.\n *\n * All wrappers route through `absorbErrorsSync` — telemetry MUST NOT\n * throw at the caller.\n */\n\nimport { absorbErrorsSync } from \"../_internal/errors\";\nimport type { SpanHandle } from \"../_internal/tracing\";\nimport type { CallbackHandlerSurface } from \"./types\";\n\nconst ADAPTER_FINGERPRINT = \"langgraph.streaming\" as const;\n\n/** State carried across streaming-token events for an in-flight chain run. */\nexport interface StreamingState {\n /** Map of `runId` → SpanHandle (the in-flight llm span W2-L.2 opened). */\n llmSpans: Map<string, SpanHandle>;\n}\n\nexport interface StreamingHandlerOptions {\n /**\n * If true, emit a single `tokens_streamed` metadata count on the parent\n * llm span; default true. If false, the handler is a no-op (useful when\n * the host already tracks streaming elsewhere or wants to minimise\n * mutation under hot streaming loops).\n */\n trackStreamingTokens?: boolean;\n}\n\n/**\n * Returns the streaming-related callback method implementations.\n *\n * Currently exposes only `handleLLMNewToken`. Checkpoint methods\n * (`handleCheckpointStart` / `handleCheckpointEnd`) are not on the\n * `CallbackHandlerSurface` for v1 — they will land in v1.5 when we wire\n * the PostgresSaver/SqliteSaver hooks. Keeping this module in place\n * means W3-L's composition does not change shape when those land.\n */\nexport function createStreamingHandlers(\n state: StreamingState,\n options?: StreamingHandlerOptions,\n): Pick<CallbackHandlerSurface, \"handleLLMNewToken\"> {\n const trackStreamingTokens = options?.trackStreamingTokens ?? true;\n\n const handleLLMNewToken = absorbErrorsSync(\n (_token: string, _idx: { prompt: number; completion: number }, runId: string): void => {\n if (!trackStreamingTokens) return;\n const handle = state.llmSpans.get(runId);\n if (handle === undefined) {\n // No matching llm span — happens when the host fires tokens\n // before `handleLLMStart` or after `handleLLMEnd`, or when the\n // runId is unknown (orphan event). Drop silently.\n return;\n }\n const md = (handle.span.metadata ?? {}) as Record<string, unknown>;\n const prev = typeof md.tokens_streamed === \"number\" ? md.tokens_streamed : 0;\n md.tokens_streamed = prev + 1;\n handle.span.metadata = md;\n },\n { fingerprint: ADAPTER_FINGERPRINT },\n );\n\n return { handleLLMNewToken };\n}\n","/**\n * `@morsehq-dev/sdk/langgraph` — adapter for `@langchain/langgraph` (langgraphjs).\n *\n * W3-L: composes the three W2-L surfaces into a single\n * `MorseCallbackHandler` class exposing the full\n * `BaseCallbackHandler` shape LangGraph requires:\n *\n * - chain start/end/error — from W2-L.1 (`callback-handler.ts`)\n * - llm + tool start/end/error — from W2-L.2 (`llm-and-tool-callbacks.ts`)\n * - llm new-token streaming — from W2-L.3 (`streaming-and-checkpoint.ts`)\n *\n * Users get a single class to register with LangGraph:\n *\n * ```ts\n * import { MorseCallbackHandler } from \"@morsehq-dev/sdk/langgraph\";\n * await app.invoke(input, { callbacks: [new MorseCallbackHandler()] });\n * ```\n *\n * The W2-L.1 base class keeps its own private map of open chain spans\n * (since it predates the shared `LangGraphRunState`). To keep things\n * coherent for advanced consumers reading `state`, the composed class\n * overrides `handleChainStart` / `handleChainEnd` / `handleChainError`\n * to ALSO maintain `state.chainSpans` in addition to calling the\n * super-class method. The base-class behavior is unchanged.\n */\n\nimport type { SpanHandle } from \"../_internal/tracing\";\nimport {\n MorseCallbackHandler as BaseMorseCallbackHandler,\n type MorseCallbackHandlerOptions,\n getCallbackHandlerClass,\n} from \"./callback-handler\";\nimport {\n createLlmAndToolHandlers,\n type LangGraphRunState,\n type LlmAndToolHandlerOptions,\n} from \"./llm-and-tool-callbacks\";\nimport { createStreamingHandlers, type StreamingHandlerOptions } from \"./streaming-and-checkpoint\";\nimport type { CallbackHandlerSurface, SerializedLike } from \"./types\";\n\n/** Combined options for the composed handler. */\nexport type ComposedMorseCallbackHandlerOptions = MorseCallbackHandlerOptions &\n LlmAndToolHandlerOptions &\n StreamingHandlerOptions;\n\n/**\n * Composed `MorseCallbackHandler` — the user-facing class.\n *\n * Inherits chain handlers from `BaseMorseCallbackHandler` (W2-L.1)\n * and attaches the W2-L.2 llm/tool methods and W2-L.3 streaming method\n * onto each instance. All four sources share a single\n * `LangGraphRunState` so future cross-method correlation can read\n * llm/tool/chain maps from one place.\n */\nexport class MorseCallbackHandler\n extends BaseMorseCallbackHandler\n implements CallbackHandlerSurface\n{\n private readonly _state: LangGraphRunState;\n\n // The slotted methods from W2-L.2 / W2-L.3 — `!` because they are\n // assigned in the constructor via `Object.assign`-style copy.\n public handleLLMStart!: NonNullable<CallbackHandlerSurface[\"handleLLMStart\"]>;\n public handleChatModelStart!: NonNullable<CallbackHandlerSurface[\"handleChatModelStart\"]>;\n public handleLLMEnd!: NonNullable<CallbackHandlerSurface[\"handleLLMEnd\"]>;\n public handleLLMError!: NonNullable<CallbackHandlerSurface[\"handleLLMError\"]>;\n public handleToolStart!: NonNullable<CallbackHandlerSurface[\"handleToolStart\"]>;\n public handleToolEnd!: NonNullable<CallbackHandlerSurface[\"handleToolEnd\"]>;\n public handleToolError!: NonNullable<CallbackHandlerSurface[\"handleToolError\"]>;\n public handleLLMNewToken!: NonNullable<CallbackHandlerSurface[\"handleLLMNewToken\"]>;\n\n constructor(options?: ComposedMorseCallbackHandlerOptions) {\n super(options);\n\n this._state = {\n llmSpans: new Map<string, SpanHandle>(),\n toolSpans: new Map<string, SpanHandle>(),\n chainSpans: new Map<string, SpanHandle>(),\n };\n\n const llmAndTool = createLlmAndToolHandlers(this._state, {\n toolInputMaxBytes: options?.toolInputMaxBytes,\n toolOutputMaxBytes: options?.toolOutputMaxBytes,\n });\n const streaming = createStreamingHandlers(this._state, {\n trackStreamingTokens: options?.trackStreamingTokens,\n });\n\n // Copy method implementations onto the instance so LangGraph (which\n // looks up handlers via `typeof handler[method] === \"function\"` on\n // the instance) sees them. Use non-null assertions because the\n // factories always return defined methods.\n this.handleLLMStart = llmAndTool.handleLLMStart!;\n this.handleChatModelStart = llmAndTool.handleChatModelStart!;\n this.handleLLMEnd = llmAndTool.handleLLMEnd!;\n this.handleLLMError = llmAndTool.handleLLMError!;\n this.handleToolStart = llmAndTool.handleToolStart!;\n this.handleToolEnd = llmAndTool.handleToolEnd!;\n this.handleToolError = llmAndTool.handleToolError!;\n this.handleLLMNewToken = streaming.handleLLMNewToken!;\n }\n\n /**\n * The W2-L.1 base maintains its own private chain-span map. We\n * mirror chain handles into the shared `LangGraphRunState` so future\n * cross-fragment logic can correlate by runId. Never throws — the\n * map mutation is in-process and the super method already absorbs\n * errors via `absorbErrorsSync`.\n */\n override handleChainStart(\n chain: SerializedLike,\n inputs: Record<string, unknown>,\n runId: string,\n parentRunId?: string,\n tags?: string[],\n metadata?: Record<string, unknown>,\n runType?: string,\n runName?: string,\n ): void {\n super.handleChainStart(chain, inputs, runId, parentRunId, tags, metadata, runType, runName);\n // Mirror — read the now-open span from the base via the internal\n // accessor used in tests, then re-insert it (the base `_takeSpan`\n // deletes on read, so we'd break the base if we used it here).\n // Instead reach into the base via the public-ish `_setSpan` would\n // double-insert; safer to keep our own shadow keyed off the same\n // runId.\n this._shadowSetChainSpan(runId);\n }\n\n override handleChainEnd(\n outputs: Record<string, unknown>,\n runId: string,\n parentRunId?: string,\n ): void {\n super.handleChainEnd(outputs, runId, parentRunId);\n this._state.chainSpans.delete(runId);\n }\n\n override handleChainError(err: unknown, runId: string, parentRunId?: string): void {\n super.handleChainError(err, runId, parentRunId);\n this._state.chainSpans.delete(runId);\n }\n\n /**\n * Marker insertion for the shared chainSpans map. The W2-L.1 base\n * holds the real `SpanHandle` privately; for the shared map we just\n * need *presence* keyed by runId so downstream fragments can detect\n * an in-flight chain. We stash a sentinel handle whose `end()` is a\n * no-op — the base owns the real lifecycle.\n */\n private _shadowSetChainSpan(runId: string): void {\n if (typeof runId !== \"string\" || runId.length === 0) return;\n const sentinel: SpanHandle = {\n // The base owns the real SpanData — for the shadow we use a\n // minimal stand-in. Downstream readers only check map membership,\n // not field access on this object.\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n span: {} as any,\n end(): void {\n /* no-op */\n },\n };\n this._state.chainSpans.set(runId, sentinel);\n }\n}\n\n/* ------------------------------------------------------------------------ */\n/* Re-exports */\n/* ------------------------------------------------------------------------ */\n\n// Low-level pieces for advanced users who want to compose their own\n// handler shape.\nexport { BaseMorseCallbackHandler };\nexport { getCallbackHandlerClass };\nexport { createLlmAndToolHandlers } from \"./llm-and-tool-callbacks\";\nexport { createStreamingHandlers } from \"./streaming-and-checkpoint\";\n\nexport type {\n MorseCallbackHandlerOptions,\n LangGraphRunState,\n LlmAndToolHandlerOptions,\n StreamingHandlerOptions,\n};\n\nexport type {\n BaseMessageLike,\n CallbackHandlerSurface,\n LangChainCoreCallbacksModuleLike,\n LLMResultLike,\n SerializedLike,\n} from \"./types\";\n"]}
|
package/dist/openai/index.cjs
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
var chunkVD3KRXSP_cjs = require('../chunk-VD3KRXSP.cjs');
|
|
3
4
|
var chunkKBWPNIH4_cjs = require('../chunk-KBWPNIH4.cjs');
|
|
4
|
-
var
|
|
5
|
-
var
|
|
5
|
+
var chunkHICEJ4LV_cjs = require('../chunk-HICEJ4LV.cjs');
|
|
6
|
+
var chunk5B3IUESN_cjs = require('../chunk-5B3IUESN.cjs');
|
|
6
7
|
|
|
7
8
|
// src/openai/index.ts
|
|
8
|
-
|
|
9
|
+
chunk5B3IUESN_cjs.init_tracing();
|
|
10
|
+
chunk5B3IUESN_cjs.init_diagnostics();
|
|
9
11
|
var WRAPPED_CLIENT = /* @__PURE__ */ Symbol.for("morse.openai.wrapped");
|
|
10
12
|
function wrapOpenAI(client, options = {}) {
|
|
11
13
|
if (!client || typeof client !== "object") return client;
|
|
@@ -47,9 +49,10 @@ function isOpenAiWrapped(client) {
|
|
|
47
49
|
function buildPatchedCreate(original, options) {
|
|
48
50
|
const agentName = options.defaultAgentName ?? "openai.chat.completions.create";
|
|
49
51
|
return async function patchedCreate(params, callOptions) {
|
|
50
|
-
const inTrace =
|
|
52
|
+
const inTrace = chunk5B3IUESN_cjs.getActiveTraceState() !== null;
|
|
51
53
|
const work = async () => {
|
|
52
|
-
|
|
54
|
+
chunkVD3KRXSP_cjs.setActiveFramework("openai");
|
|
55
|
+
const handle = chunk5B3IUESN_cjs.startSpan({
|
|
53
56
|
name: "openai.chat.completions.create",
|
|
54
57
|
type: "llm",
|
|
55
58
|
metadata: { model: params?.model }
|
|
@@ -85,8 +88,13 @@ function buildPatchedCreate(original, options) {
|
|
|
85
88
|
if (cost !== void 0) handle.span.cost_usd = cost;
|
|
86
89
|
}
|
|
87
90
|
handle.span.context_segments = segments;
|
|
91
|
+
const inputData = chunkVD3KRXSP_cjs.captureInputMessages(params?.messages);
|
|
92
|
+
if (inputData !== void 0) handle.span.input_data = inputData;
|
|
93
|
+
const outputText = chunkVD3KRXSP_cjs.extractOpenAiOutputText(response?.choices);
|
|
94
|
+
if (outputText !== void 0) handle.span.output_data = { content: outputText };
|
|
88
95
|
}
|
|
89
|
-
} catch {
|
|
96
|
+
} catch (err) {
|
|
97
|
+
reportSwallowed(err, "morse.openai.stream_wrap");
|
|
90
98
|
}
|
|
91
99
|
handle?.end();
|
|
92
100
|
return response;
|
|
@@ -96,7 +104,7 @@ function buildPatchedCreate(original, options) {
|
|
|
96
104
|
}
|
|
97
105
|
let result;
|
|
98
106
|
let thrown;
|
|
99
|
-
await
|
|
107
|
+
await chunk5B3IUESN_cjs.runAsync({ agentName }, async (runHandle) => {
|
|
100
108
|
runHandle.setOutcome(true);
|
|
101
109
|
try {
|
|
102
110
|
result = await work();
|
|
@@ -113,11 +121,17 @@ function buildPatchedCreate(original, options) {
|
|
|
113
121
|
function safeExtractSegments(params) {
|
|
114
122
|
try {
|
|
115
123
|
if (!params || typeof params !== "object") return [];
|
|
116
|
-
return
|
|
124
|
+
return chunkHICEJ4LV_cjs.decomposeOpenAiMessages(params.messages, params.tools);
|
|
117
125
|
} catch {
|
|
118
126
|
return [];
|
|
119
127
|
}
|
|
120
128
|
}
|
|
129
|
+
function reportSwallowed(err, fingerprint) {
|
|
130
|
+
try {
|
|
131
|
+
chunk5B3IUESN_cjs.report(err, { fingerprint });
|
|
132
|
+
} catch {
|
|
133
|
+
}
|
|
134
|
+
}
|
|
121
135
|
|
|
122
136
|
exports.isOpenAiWrapped = isOpenAiWrapped;
|
|
123
137
|
exports.wrapOpenAI = wrapOpenAI;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/openai/index.ts"],"names":["init_tracing","getActiveTraceState","startSpan","calculateCost","runAsync","decomposeOpenAiMessages"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * `@morsehq-dev/sdk/openai` — plain OpenAI SDK instrumentation.\n *\n * Wraps a raw `openai` npm package client (`new OpenAI()` /\n * `new AzureOpenAI()` / any structurally-compatible client) so every\n * `chat.completions.create` call emits an `llm` span carrying model,\n * token counts, `cost_usd`, and pre-segmented `context_segments`.\n *\n * TS port of `apps/sdk/python/src/morse_ai/adapters/openai.py`'s `wrap()`.\n * This module intentionally covers only the `wrap(client)` recommended\n * path (mirrors the Python module's three-layer doc comment, layer 2) —\n * no module-level monkey-patch / `install()` layer, since plain `openai`\n * is not one of the auto-detect targets on either SDK (see\n * `_internal/auto-detect.ts` and Python's `_internal/auto_detect.py`\n * `_adapter_targets()`, which both omit bare `openai`).\n *\n * Distinct from `@morsehq-dev/sdk/openai-agents`, which instruments the\n * `@openai/agents` Agents SDK (a different package with its own Runner /\n * Agent abstractions). This module is for customers calling\n * `openai.chat.completions.create` directly.\n *\n * Context segments are extracted via the shared\n * `_agent-sdk-common/context-decomposer.ts` (`decomposeOpenAiMessages`,\n * MHQ-750) — the request's `messages`/`tools` are already in the native\n * OpenAI wire format the decomposer expects, so no translation layer is\n * needed.\n *\n * Idempotent — wrapping an already-wrapped client instance is a no-op\n * that returns the same wrapper. Recording is best-effort: any failure\n * while building/emitting the span is swallowed so it can never break the\n * customer's OpenAI call. The customer's own API error (thrown by the\n * underlying `create()` call) always propagates unchanged — the span is\n * marked `status: \"failed\"` first, then the error is re-raised.\n *\n * Mirrors `apps/sdk/typescript/src/anthropic/index.ts` in shape.\n */\n\nimport { decomposeOpenAiMessages } from \"../_agent-sdk-common/context-decomposer\";\nimport { calculateCost } from \"../_internal/pricing\";\nimport type { ContextSegment } from \"../_internal/spans\";\nimport { getActiveTraceState, runAsync as _runAsync, startSpan } from \"../_internal/tracing\";\n\n/* ------------------------------------------------------------------------ */\n/* Public types — minimal structural shapes, NOT a hard dep on `openai` */\n/* ------------------------------------------------------------------------ */\n\n/** Subset of the `openai` package's chat message shape we read from. */\nexport interface OpenAiChatMessageParam {\n role: string;\n content?: unknown;\n tool_call_id?: string;\n [key: string]: unknown;\n}\n\n/** Subset of the `openai` package's tool-definition shape we read from. */\nexport interface OpenAiToolParam {\n type?: string;\n function?: { name?: string; [key: string]: unknown };\n [key: string]: unknown;\n}\n\n/**\n * Subset of `openai`'s `ChatCompletionCreateParams` we read from. We\n * deliberately decline to import the real types so the SDK works even when\n * `openai` isn't installed (it's an optional peer dep).\n */\nexport interface OpenAiChatCompletionCreateParams {\n model: string;\n messages: OpenAiChatMessageParam[];\n tools?: OpenAiToolParam[];\n // Allow forward-compat fields without complaint.\n [key: string]: unknown;\n}\n\nexport interface OpenAiCompletionUsageDetails {\n cached_tokens?: number;\n reasoning_tokens?: number;\n [key: string]: unknown;\n}\n\nexport interface OpenAiCompletionUsage {\n prompt_tokens?: number;\n completion_tokens?: number;\n total_tokens?: number;\n prompt_tokens_details?: OpenAiCompletionUsageDetails;\n completion_tokens_details?: OpenAiCompletionUsageDetails;\n [key: string]: unknown;\n}\n\nexport interface OpenAiChatCompletionResponse {\n id?: string;\n model?: string;\n usage?: OpenAiCompletionUsage;\n choices?: Array<{ message?: { content?: unknown; [k: string]: unknown }; [k: string]: unknown }>;\n [key: string]: unknown;\n}\n\n/**\n * Structural shape of the plain OpenAI client we wrap. We only require\n * that `client.chat.completions.create` is a function returning a Promise.\n */\nexport interface OpenAiClientLike {\n chat: {\n completions: {\n create(\n params: OpenAiChatCompletionCreateParams,\n options?: unknown,\n ): Promise<OpenAiChatCompletionResponse>;\n [key: string]: unknown;\n };\n [key: string]: unknown;\n };\n [key: string]: unknown;\n}\n\n/* ------------------------------------------------------------------------ */\n/* Module-level sentinel */\n/* ------------------------------------------------------------------------ */\n\nconst WRAPPED_CLIENT = Symbol.for(\"morse.openai.wrapped\");\n\n/* ------------------------------------------------------------------------ */\n/* Public API */\n/* ------------------------------------------------------------------------ */\n\nexport interface WrapOpenAiOptions {\n /**\n * When provided, used as the parent agent span's name when\n * `chat.completions.create` is called outside an active trace. Defaults\n * to `\"openai.chat.completions.create\"`.\n */\n defaultAgentName?: string;\n}\n\n/**\n * Wrap an OpenAI client so every `chat.completions.create` call records an\n * `llm` span with `model`, token counts, `cost_usd`, and `context_segments`.\n * The wrapper preserves the rest of the client's surface (other resources,\n * helpers, etc.) via a Proxy.\n *\n * Idempotent — a previously wrapped client is returned as-is.\n *\n * @example\n * ```ts\n * import { wrapOpenAI } from \"@morsehq-dev/sdk/openai\";\n * import OpenAI from \"openai\";\n *\n * const client = wrapOpenAI(new OpenAI());\n * const response = await client.chat.completions.create({\n * model: \"gpt-4o-mini\",\n * messages: [{ role: \"user\", content: \"hello\" }],\n * });\n * ```\n */\nexport function wrapOpenAI<C extends OpenAiClientLike>(\n client: C,\n options: WrapOpenAiOptions = {},\n): C {\n if (!client || typeof client !== \"object\") return client;\n // Already wrapped? Pass through.\n if ((client as Record<string | symbol, unknown>)[WRAPPED_CLIENT]) return client;\n\n const originalCreate = client.chat?.completions?.create?.bind(client.chat.completions);\n if (typeof originalCreate !== \"function\") return client;\n\n const patchedCreate = buildPatchedCreate(originalCreate, options);\n\n // Construct a new `completions` object that proxies to the original for\n // any non-`create` access, wrapped in a `chat` proxy, wrapped in a\n // top-level client proxy — mirrors `wrapAnthropic`'s nested-Proxy shape.\n const patchedCompletions = new Proxy(client.chat.completions, {\n get(target, prop, receiver) {\n if (prop === \"create\") return patchedCreate;\n const value = Reflect.get(target, prop, receiver);\n if (typeof value === \"function\") return (value as (...a: unknown[]) => unknown).bind(target);\n return value;\n },\n });\n\n const patchedChat = new Proxy(client.chat, {\n get(target, prop, receiver) {\n if (prop === \"completions\") return patchedCompletions;\n const value = Reflect.get(target, prop, receiver);\n if (typeof value === \"function\") return (value as (...a: unknown[]) => unknown).bind(target);\n return value;\n },\n });\n\n const wrapper = new Proxy(client, {\n get(target, prop, receiver) {\n if (prop === WRAPPED_CLIENT) return true;\n if (prop === \"chat\") return patchedChat;\n const value = Reflect.get(target, prop, receiver);\n if (typeof value === \"function\") return (value as (...a: unknown[]) => unknown).bind(target);\n return value;\n },\n });\n\n return wrapper as C;\n}\n\n/** True when a wrapped OpenAI client is passed in. */\nexport function isOpenAiWrapped(client: unknown): boolean {\n if (!client || typeof client !== \"object\") return false;\n return (client as Record<string | symbol, unknown>)[WRAPPED_CLIENT] === true;\n}\n\n/* ------------------------------------------------------------------------ */\n/* Internals — wrapper that records an `llm` span */\n/* ------------------------------------------------------------------------ */\n\nfunction buildPatchedCreate(\n original: (\n params: OpenAiChatCompletionCreateParams,\n options?: unknown,\n ) => Promise<OpenAiChatCompletionResponse>,\n options: WrapOpenAiOptions,\n): (\n params: OpenAiChatCompletionCreateParams,\n options?: unknown,\n) => Promise<OpenAiChatCompletionResponse> {\n const agentName = options.defaultAgentName ?? \"openai.chat.completions.create\";\n\n return async function patchedCreate(\n this: unknown,\n params: OpenAiChatCompletionCreateParams,\n callOptions?: unknown,\n ): Promise<OpenAiChatCompletionResponse> {\n const inTrace = getActiveTraceState() !== null;\n\n const work = async (): Promise<OpenAiChatCompletionResponse> => {\n const handle = startSpan({\n name: \"openai.chat.completions.create\",\n type: \"llm\",\n metadata: { model: params?.model },\n });\n let response: OpenAiChatCompletionResponse | undefined;\n try {\n response = await original.call(this, params, callOptions);\n } catch (err) {\n // Customer's own API error — mark the span failed, then re-raise\n // unchanged. Never swallow the caller's real error.\n handle?.end(err);\n throw err;\n }\n\n // Recording is best-effort — never let it throw at the caller.\n try {\n if (handle) {\n const segments = safeExtractSegments(params);\n const usage = response?.usage ?? {};\n const inputTokens = usage.prompt_tokens ?? 0;\n const outputTokens = usage.completion_tokens ?? 0;\n const cachedTokens = usage.prompt_tokens_details?.cached_tokens ?? 0;\n const model = response?.model ?? params?.model;\n\n handle.span.model = model;\n if (inputTokens > 0) handle.span.input_tokens = inputTokens;\n if (outputTokens > 0) handle.span.output_tokens = outputTokens;\n if (cachedTokens > 0) handle.span.cached_input_tokens = cachedTokens;\n const totalTokens =\n usage.total_tokens ??\n (inputTokens > 0 || outputTokens > 0 ? inputTokens + outputTokens : 0);\n if (totalTokens > 0) handle.span.total_tokens = totalTokens;\n\n if (model && (inputTokens > 0 || outputTokens > 0)) {\n const cost = calculateCost({\n inputTokens,\n outputTokens,\n model,\n cachedInputTokens: cachedTokens,\n });\n if (cost !== undefined) handle.span.cost_usd = cost;\n }\n handle.span.context_segments = segments;\n }\n } catch {\n // swallow — telemetry must never break the caller\n }\n handle?.end();\n return response;\n };\n\n if (inTrace) {\n return work();\n }\n\n // No active trace — open a fresh agent span around the call so the\n // llm span has a parent. Mirrors `wrapAnthropic`'s pattern: we can't\n // return `work()`'s Promise from inside `_runAsync`'s callback while\n // preserving typing AND having the fresh trace own the lifecycle, so\n // we wrap explicitly.\n let result: OpenAiChatCompletionResponse | undefined;\n let thrown: unknown;\n await _runAsync({ agentName }, async (runHandle) => {\n runHandle.setOutcome(true);\n try {\n result = await work();\n } catch (err) {\n thrown = err;\n throw err;\n }\n return null;\n });\n if (thrown !== undefined) throw thrown;\n return result as OpenAiChatCompletionResponse;\n };\n}\n\nfunction safeExtractSegments(params: OpenAiChatCompletionCreateParams): ContextSegment[] {\n try {\n if (!params || typeof params !== \"object\") return [];\n return decomposeOpenAiMessages(params.messages, params.tools);\n } catch {\n return [];\n }\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../../src/openai/index.ts"],"names":["init_tracing","init_diagnostics","getActiveTraceState","setActiveFramework","startSpan","calculateCost","captureInputMessages","extractOpenAiOutputText","runAsync","decomposeOpenAiMessages","report"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * `@morsehq-dev/sdk/openai` — plain OpenAI SDK instrumentation.\n *\n * Wraps a raw `openai` npm package client (`new OpenAI()` /\n * `new AzureOpenAI()` / any structurally-compatible client) so every\n * `chat.completions.create` call emits an `llm` span carrying model,\n * token counts, `cost_usd`, and pre-segmented `context_segments`.\n *\n * TS port of `apps/sdk/python/src/morse_ai/adapters/openai.py`'s `wrap()`.\n * This module intentionally covers only the `wrap(client)` recommended\n * path (mirrors the Python module's three-layer doc comment, layer 2) —\n * no module-level monkey-patch / `install()` layer, since plain `openai`\n * is not one of the auto-detect targets on either SDK (see\n * `_internal/auto-detect.ts` and Python's `_internal/auto_detect.py`\n * `_adapter_targets()`, which both omit bare `openai`).\n *\n * Distinct from `@morsehq-dev/sdk/openai-agents`, which instruments the\n * `@openai/agents` Agents SDK (a different package with its own Runner /\n * Agent abstractions). This module is for customers calling\n * `openai.chat.completions.create` directly.\n *\n * Context segments are extracted via the shared\n * `_agent-sdk-common/context-decomposer.ts` (`decomposeOpenAiMessages`,\n * MHQ-750) — the request's `messages`/`tools` are already in the native\n * OpenAI wire format the decomposer expects, so no translation layer is\n * needed.\n *\n * Idempotent — wrapping an already-wrapped client instance is a no-op\n * that returns the same wrapper. Recording is best-effort: any failure\n * while building/emitting the span is swallowed so it can never break the\n * customer's OpenAI call. The customer's own API error (thrown by the\n * underlying `create()` call) always propagates unchanged — the span is\n * marked `status: \"failed\"` first, then the error is re-raised.\n *\n * Mirrors `apps/sdk/typescript/src/anthropic/index.ts` in shape.\n */\n\nimport { decomposeOpenAiMessages } from \"../_agent-sdk-common/context-decomposer\";\nimport { setActiveFramework } from \"../_internal/active-framework\";\nimport { captureInputMessages, extractOpenAiOutputText } from \"../_internal/llm-io\";\nimport { calculateCost } from \"../_internal/pricing\";\nimport type { ContextSegment } from \"../_internal/spans\";\nimport { getActiveTraceState, runAsync as _runAsync, startSpan } from \"../_internal/tracing\";\nimport { report } from \"../_internal/diagnostics\";\n\n/* ------------------------------------------------------------------------ */\n/* Public types — minimal structural shapes, NOT a hard dep on `openai` */\n/* ------------------------------------------------------------------------ */\n\n/** Subset of the `openai` package's chat message shape we read from. */\nexport interface OpenAiChatMessageParam {\n role: string;\n content?: unknown;\n tool_call_id?: string;\n [key: string]: unknown;\n}\n\n/** Subset of the `openai` package's tool-definition shape we read from. */\nexport interface OpenAiToolParam {\n type?: string;\n function?: { name?: string; [key: string]: unknown };\n [key: string]: unknown;\n}\n\n/**\n * Subset of `openai`'s `ChatCompletionCreateParams` we read from. We\n * deliberately decline to import the real types so the SDK works even when\n * `openai` isn't installed (it's an optional peer dep).\n */\nexport interface OpenAiChatCompletionCreateParams {\n model: string;\n messages: OpenAiChatMessageParam[];\n tools?: OpenAiToolParam[];\n // Allow forward-compat fields without complaint.\n [key: string]: unknown;\n}\n\nexport interface OpenAiCompletionUsageDetails {\n cached_tokens?: number;\n reasoning_tokens?: number;\n [key: string]: unknown;\n}\n\nexport interface OpenAiCompletionUsage {\n prompt_tokens?: number;\n completion_tokens?: number;\n total_tokens?: number;\n prompt_tokens_details?: OpenAiCompletionUsageDetails;\n completion_tokens_details?: OpenAiCompletionUsageDetails;\n [key: string]: unknown;\n}\n\nexport interface OpenAiChatCompletionResponse {\n id?: string;\n model?: string;\n usage?: OpenAiCompletionUsage;\n choices?: Array<{ message?: { content?: unknown; [k: string]: unknown }; [k: string]: unknown }>;\n [key: string]: unknown;\n}\n\n/**\n * Structural shape of the plain OpenAI client we wrap. We only require\n * that `client.chat.completions.create` is a function returning a Promise.\n */\nexport interface OpenAiClientLike {\n chat: {\n completions: {\n create(\n params: OpenAiChatCompletionCreateParams,\n options?: unknown,\n ): Promise<OpenAiChatCompletionResponse>;\n [key: string]: unknown;\n };\n [key: string]: unknown;\n };\n [key: string]: unknown;\n}\n\n/* ------------------------------------------------------------------------ */\n/* Module-level sentinel */\n/* ------------------------------------------------------------------------ */\n\nconst WRAPPED_CLIENT = Symbol.for(\"morse.openai.wrapped\");\n\n/* ------------------------------------------------------------------------ */\n/* Public API */\n/* ------------------------------------------------------------------------ */\n\nexport interface WrapOpenAiOptions {\n /**\n * When provided, used as the parent agent span's name when\n * `chat.completions.create` is called outside an active trace. Defaults\n * to `\"openai.chat.completions.create\"`.\n */\n defaultAgentName?: string;\n}\n\n/**\n * Wrap an OpenAI client so every `chat.completions.create` call records an\n * `llm` span with `model`, token counts, `cost_usd`, and `context_segments`.\n * The wrapper preserves the rest of the client's surface (other resources,\n * helpers, etc.) via a Proxy.\n *\n * Idempotent — a previously wrapped client is returned as-is.\n *\n * @example\n * ```ts\n * import { wrapOpenAI } from \"@morsehq-dev/sdk/openai\";\n * import OpenAI from \"openai\";\n *\n * const client = wrapOpenAI(new OpenAI());\n * const response = await client.chat.completions.create({\n * model: \"gpt-4o-mini\",\n * messages: [{ role: \"user\", content: \"hello\" }],\n * });\n * ```\n */\nexport function wrapOpenAI<C extends OpenAiClientLike>(\n client: C,\n options: WrapOpenAiOptions = {},\n): C {\n if (!client || typeof client !== \"object\") return client;\n // Already wrapped? Pass through.\n if ((client as Record<string | symbol, unknown>)[WRAPPED_CLIENT]) return client;\n\n const originalCreate = client.chat?.completions?.create?.bind(client.chat.completions);\n if (typeof originalCreate !== \"function\") return client;\n\n const patchedCreate = buildPatchedCreate(originalCreate, options);\n\n // Construct a new `completions` object that proxies to the original for\n // any non-`create` access, wrapped in a `chat` proxy, wrapped in a\n // top-level client proxy — mirrors `wrapAnthropic`'s nested-Proxy shape.\n const patchedCompletions = new Proxy(client.chat.completions, {\n get(target, prop, receiver) {\n if (prop === \"create\") return patchedCreate;\n const value = Reflect.get(target, prop, receiver);\n if (typeof value === \"function\") return (value as (...a: unknown[]) => unknown).bind(target);\n return value;\n },\n });\n\n const patchedChat = new Proxy(client.chat, {\n get(target, prop, receiver) {\n if (prop === \"completions\") return patchedCompletions;\n const value = Reflect.get(target, prop, receiver);\n if (typeof value === \"function\") return (value as (...a: unknown[]) => unknown).bind(target);\n return value;\n },\n });\n\n const wrapper = new Proxy(client, {\n get(target, prop, receiver) {\n if (prop === WRAPPED_CLIENT) return true;\n if (prop === \"chat\") return patchedChat;\n const value = Reflect.get(target, prop, receiver);\n if (typeof value === \"function\") return (value as (...a: unknown[]) => unknown).bind(target);\n return value;\n },\n });\n\n return wrapper as C;\n}\n\n/** True when a wrapped OpenAI client is passed in. */\nexport function isOpenAiWrapped(client: unknown): boolean {\n if (!client || typeof client !== \"object\") return false;\n return (client as Record<string | symbol, unknown>)[WRAPPED_CLIENT] === true;\n}\n\n/* ------------------------------------------------------------------------ */\n/* Internals — wrapper that records an `llm` span */\n/* ------------------------------------------------------------------------ */\n\nfunction buildPatchedCreate(\n original: (\n params: OpenAiChatCompletionCreateParams,\n options?: unknown,\n ) => Promise<OpenAiChatCompletionResponse>,\n options: WrapOpenAiOptions,\n): (\n params: OpenAiChatCompletionCreateParams,\n options?: unknown,\n) => Promise<OpenAiChatCompletionResponse> {\n const agentName = options.defaultAgentName ?? \"openai.chat.completions.create\";\n\n return async function patchedCreate(\n this: unknown,\n params: OpenAiChatCompletionCreateParams,\n callOptions?: unknown,\n ): Promise<OpenAiChatCompletionResponse> {\n const inTrace = getActiveTraceState() !== null;\n\n const work = async (): Promise<OpenAiChatCompletionResponse> => {\n setActiveFramework(\"openai\");\n const handle = startSpan({\n name: \"openai.chat.completions.create\",\n type: \"llm\",\n metadata: { model: params?.model },\n });\n let response: OpenAiChatCompletionResponse | undefined;\n try {\n response = await original.call(this, params, callOptions);\n } catch (err) {\n // Customer's own API error — mark the span failed, then re-raise\n // unchanged. Never swallow the caller's real error.\n handle?.end(err);\n throw err;\n }\n\n // Recording is best-effort — never let it throw at the caller.\n try {\n if (handle) {\n const segments = safeExtractSegments(params);\n const usage = response?.usage ?? {};\n const inputTokens = usage.prompt_tokens ?? 0;\n const outputTokens = usage.completion_tokens ?? 0;\n const cachedTokens = usage.prompt_tokens_details?.cached_tokens ?? 0;\n const model = response?.model ?? params?.model;\n\n handle.span.model = model;\n if (inputTokens > 0) handle.span.input_tokens = inputTokens;\n if (outputTokens > 0) handle.span.output_tokens = outputTokens;\n if (cachedTokens > 0) handle.span.cached_input_tokens = cachedTokens;\n const totalTokens =\n usage.total_tokens ??\n (inputTokens > 0 || outputTokens > 0 ? inputTokens + outputTokens : 0);\n if (totalTokens > 0) handle.span.total_tokens = totalTokens;\n\n if (model && (inputTokens > 0 || outputTokens > 0)) {\n const cost = calculateCost({\n inputTokens,\n outputTokens,\n model,\n cachedInputTokens: cachedTokens,\n });\n if (cost !== undefined) handle.span.cost_usd = cost;\n }\n handle.span.context_segments = segments;\n // MHQ-858: prompt/response capture, parity with the Python\n // adapter's input_data/output_data.\n const inputData = captureInputMessages(params?.messages);\n if (inputData !== undefined) handle.span.input_data = inputData;\n const outputText = extractOpenAiOutputText(response?.choices);\n if (outputText !== undefined) handle.span.output_data = { content: outputText };\n }\n } catch (err) {\n // swallow — telemetry must never break the caller\n reportSwallowed(err, \"morse.openai.stream_wrap\");\n }\n handle?.end();\n return response;\n };\n\n if (inTrace) {\n return work();\n }\n\n // No active trace — open a fresh agent span around the call so the\n // llm span has a parent. Mirrors `wrapAnthropic`'s pattern: we can't\n // return `work()`'s Promise from inside `_runAsync`'s callback while\n // preserving typing AND having the fresh trace own the lifecycle, so\n // we wrap explicitly.\n let result: OpenAiChatCompletionResponse | undefined;\n let thrown: unknown;\n await _runAsync({ agentName }, async (runHandle) => {\n runHandle.setOutcome(true);\n try {\n result = await work();\n } catch (err) {\n thrown = err;\n throw err;\n }\n return null;\n });\n if (thrown !== undefined) throw thrown;\n return result as OpenAiChatCompletionResponse;\n };\n}\n\nfunction safeExtractSegments(params: OpenAiChatCompletionCreateParams): ContextSegment[] {\n try {\n if (!params || typeof params !== \"object\") return [];\n return decomposeOpenAiMessages(params.messages, params.tools);\n } catch {\n return [];\n }\n}\n\n/**\n * Route a swallowed internal error to the diagnostics channel (SDKDIAG-07).\n *\n * Control flow is unchanged — the site still swallows, still returns the same\n * value. It is simply no longer invisible to us.\n */\nfunction reportSwallowed(err: unknown, fingerprint: string): void {\n try {\n report(err, { fingerprint });\n } catch {\n // Reporting must never break the swallow it is reporting on.\n }\n}\n"]}
|
package/dist/openai/index.js
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
|
+
import { setActiveFramework, captureInputMessages, extractOpenAiOutputText } from '../chunk-5RXSICEJ.js';
|
|
1
2
|
import { calculateCost } from '../chunk-XTKMUJWI.js';
|
|
2
|
-
import { decomposeOpenAiMessages } from '../chunk-
|
|
3
|
-
import { init_tracing, getActiveTraceState, runAsync, startSpan } from '../chunk-
|
|
3
|
+
import { decomposeOpenAiMessages } from '../chunk-4JPZV2VZ.js';
|
|
4
|
+
import { init_tracing, init_diagnostics, getActiveTraceState, runAsync, startSpan, report } from '../chunk-UEKQIRRA.js';
|
|
4
5
|
|
|
5
6
|
// src/openai/index.ts
|
|
6
7
|
init_tracing();
|
|
8
|
+
init_diagnostics();
|
|
7
9
|
var WRAPPED_CLIENT = /* @__PURE__ */ Symbol.for("morse.openai.wrapped");
|
|
8
10
|
function wrapOpenAI(client, options = {}) {
|
|
9
11
|
if (!client || typeof client !== "object") return client;
|
|
@@ -47,6 +49,7 @@ function buildPatchedCreate(original, options) {
|
|
|
47
49
|
return async function patchedCreate(params, callOptions) {
|
|
48
50
|
const inTrace = getActiveTraceState() !== null;
|
|
49
51
|
const work = async () => {
|
|
52
|
+
setActiveFramework("openai");
|
|
50
53
|
const handle = startSpan({
|
|
51
54
|
name: "openai.chat.completions.create",
|
|
52
55
|
type: "llm",
|
|
@@ -83,8 +86,13 @@ function buildPatchedCreate(original, options) {
|
|
|
83
86
|
if (cost !== void 0) handle.span.cost_usd = cost;
|
|
84
87
|
}
|
|
85
88
|
handle.span.context_segments = segments;
|
|
89
|
+
const inputData = captureInputMessages(params?.messages);
|
|
90
|
+
if (inputData !== void 0) handle.span.input_data = inputData;
|
|
91
|
+
const outputText = extractOpenAiOutputText(response?.choices);
|
|
92
|
+
if (outputText !== void 0) handle.span.output_data = { content: outputText };
|
|
86
93
|
}
|
|
87
|
-
} catch {
|
|
94
|
+
} catch (err) {
|
|
95
|
+
reportSwallowed(err, "morse.openai.stream_wrap");
|
|
88
96
|
}
|
|
89
97
|
handle?.end();
|
|
90
98
|
return response;
|
|
@@ -116,6 +124,12 @@ function safeExtractSegments(params) {
|
|
|
116
124
|
return [];
|
|
117
125
|
}
|
|
118
126
|
}
|
|
127
|
+
function reportSwallowed(err, fingerprint) {
|
|
128
|
+
try {
|
|
129
|
+
report(err, { fingerprint });
|
|
130
|
+
} catch {
|
|
131
|
+
}
|
|
132
|
+
}
|
|
119
133
|
|
|
120
134
|
export { isOpenAiWrapped, wrapOpenAI };
|
|
121
135
|
//# sourceMappingURL=index.js.map
|
package/dist/openai/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/openai/index.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["/**\n * `@morsehq-dev/sdk/openai` — plain OpenAI SDK instrumentation.\n *\n * Wraps a raw `openai` npm package client (`new OpenAI()` /\n * `new AzureOpenAI()` / any structurally-compatible client) so every\n * `chat.completions.create` call emits an `llm` span carrying model,\n * token counts, `cost_usd`, and pre-segmented `context_segments`.\n *\n * TS port of `apps/sdk/python/src/morse_ai/adapters/openai.py`'s `wrap()`.\n * This module intentionally covers only the `wrap(client)` recommended\n * path (mirrors the Python module's three-layer doc comment, layer 2) —\n * no module-level monkey-patch / `install()` layer, since plain `openai`\n * is not one of the auto-detect targets on either SDK (see\n * `_internal/auto-detect.ts` and Python's `_internal/auto_detect.py`\n * `_adapter_targets()`, which both omit bare `openai`).\n *\n * Distinct from `@morsehq-dev/sdk/openai-agents`, which instruments the\n * `@openai/agents` Agents SDK (a different package with its own Runner /\n * Agent abstractions). This module is for customers calling\n * `openai.chat.completions.create` directly.\n *\n * Context segments are extracted via the shared\n * `_agent-sdk-common/context-decomposer.ts` (`decomposeOpenAiMessages`,\n * MHQ-750) — the request's `messages`/`tools` are already in the native\n * OpenAI wire format the decomposer expects, so no translation layer is\n * needed.\n *\n * Idempotent — wrapping an already-wrapped client instance is a no-op\n * that returns the same wrapper. Recording is best-effort: any failure\n * while building/emitting the span is swallowed so it can never break the\n * customer's OpenAI call. The customer's own API error (thrown by the\n * underlying `create()` call) always propagates unchanged — the span is\n * marked `status: \"failed\"` first, then the error is re-raised.\n *\n * Mirrors `apps/sdk/typescript/src/anthropic/index.ts` in shape.\n */\n\nimport { decomposeOpenAiMessages } from \"../_agent-sdk-common/context-decomposer\";\nimport { calculateCost } from \"../_internal/pricing\";\nimport type { ContextSegment } from \"../_internal/spans\";\nimport { getActiveTraceState, runAsync as _runAsync, startSpan } from \"../_internal/tracing\";\n\n/* ------------------------------------------------------------------------ */\n/* Public types — minimal structural shapes, NOT a hard dep on `openai` */\n/* ------------------------------------------------------------------------ */\n\n/** Subset of the `openai` package's chat message shape we read from. */\nexport interface OpenAiChatMessageParam {\n role: string;\n content?: unknown;\n tool_call_id?: string;\n [key: string]: unknown;\n}\n\n/** Subset of the `openai` package's tool-definition shape we read from. */\nexport interface OpenAiToolParam {\n type?: string;\n function?: { name?: string; [key: string]: unknown };\n [key: string]: unknown;\n}\n\n/**\n * Subset of `openai`'s `ChatCompletionCreateParams` we read from. We\n * deliberately decline to import the real types so the SDK works even when\n * `openai` isn't installed (it's an optional peer dep).\n */\nexport interface OpenAiChatCompletionCreateParams {\n model: string;\n messages: OpenAiChatMessageParam[];\n tools?: OpenAiToolParam[];\n // Allow forward-compat fields without complaint.\n [key: string]: unknown;\n}\n\nexport interface OpenAiCompletionUsageDetails {\n cached_tokens?: number;\n reasoning_tokens?: number;\n [key: string]: unknown;\n}\n\nexport interface OpenAiCompletionUsage {\n prompt_tokens?: number;\n completion_tokens?: number;\n total_tokens?: number;\n prompt_tokens_details?: OpenAiCompletionUsageDetails;\n completion_tokens_details?: OpenAiCompletionUsageDetails;\n [key: string]: unknown;\n}\n\nexport interface OpenAiChatCompletionResponse {\n id?: string;\n model?: string;\n usage?: OpenAiCompletionUsage;\n choices?: Array<{ message?: { content?: unknown; [k: string]: unknown }; [k: string]: unknown }>;\n [key: string]: unknown;\n}\n\n/**\n * Structural shape of the plain OpenAI client we wrap. We only require\n * that `client.chat.completions.create` is a function returning a Promise.\n */\nexport interface OpenAiClientLike {\n chat: {\n completions: {\n create(\n params: OpenAiChatCompletionCreateParams,\n options?: unknown,\n ): Promise<OpenAiChatCompletionResponse>;\n [key: string]: unknown;\n };\n [key: string]: unknown;\n };\n [key: string]: unknown;\n}\n\n/* ------------------------------------------------------------------------ */\n/* Module-level sentinel */\n/* ------------------------------------------------------------------------ */\n\nconst WRAPPED_CLIENT = Symbol.for(\"morse.openai.wrapped\");\n\n/* ------------------------------------------------------------------------ */\n/* Public API */\n/* ------------------------------------------------------------------------ */\n\nexport interface WrapOpenAiOptions {\n /**\n * When provided, used as the parent agent span's name when\n * `chat.completions.create` is called outside an active trace. Defaults\n * to `\"openai.chat.completions.create\"`.\n */\n defaultAgentName?: string;\n}\n\n/**\n * Wrap an OpenAI client so every `chat.completions.create` call records an\n * `llm` span with `model`, token counts, `cost_usd`, and `context_segments`.\n * The wrapper preserves the rest of the client's surface (other resources,\n * helpers, etc.) via a Proxy.\n *\n * Idempotent — a previously wrapped client is returned as-is.\n *\n * @example\n * ```ts\n * import { wrapOpenAI } from \"@morsehq-dev/sdk/openai\";\n * import OpenAI from \"openai\";\n *\n * const client = wrapOpenAI(new OpenAI());\n * const response = await client.chat.completions.create({\n * model: \"gpt-4o-mini\",\n * messages: [{ role: \"user\", content: \"hello\" }],\n * });\n * ```\n */\nexport function wrapOpenAI<C extends OpenAiClientLike>(\n client: C,\n options: WrapOpenAiOptions = {},\n): C {\n if (!client || typeof client !== \"object\") return client;\n // Already wrapped? Pass through.\n if ((client as Record<string | symbol, unknown>)[WRAPPED_CLIENT]) return client;\n\n const originalCreate = client.chat?.completions?.create?.bind(client.chat.completions);\n if (typeof originalCreate !== \"function\") return client;\n\n const patchedCreate = buildPatchedCreate(originalCreate, options);\n\n // Construct a new `completions` object that proxies to the original for\n // any non-`create` access, wrapped in a `chat` proxy, wrapped in a\n // top-level client proxy — mirrors `wrapAnthropic`'s nested-Proxy shape.\n const patchedCompletions = new Proxy(client.chat.completions, {\n get(target, prop, receiver) {\n if (prop === \"create\") return patchedCreate;\n const value = Reflect.get(target, prop, receiver);\n if (typeof value === \"function\") return (value as (...a: unknown[]) => unknown).bind(target);\n return value;\n },\n });\n\n const patchedChat = new Proxy(client.chat, {\n get(target, prop, receiver) {\n if (prop === \"completions\") return patchedCompletions;\n const value = Reflect.get(target, prop, receiver);\n if (typeof value === \"function\") return (value as (...a: unknown[]) => unknown).bind(target);\n return value;\n },\n });\n\n const wrapper = new Proxy(client, {\n get(target, prop, receiver) {\n if (prop === WRAPPED_CLIENT) return true;\n if (prop === \"chat\") return patchedChat;\n const value = Reflect.get(target, prop, receiver);\n if (typeof value === \"function\") return (value as (...a: unknown[]) => unknown).bind(target);\n return value;\n },\n });\n\n return wrapper as C;\n}\n\n/** True when a wrapped OpenAI client is passed in. */\nexport function isOpenAiWrapped(client: unknown): boolean {\n if (!client || typeof client !== \"object\") return false;\n return (client as Record<string | symbol, unknown>)[WRAPPED_CLIENT] === true;\n}\n\n/* ------------------------------------------------------------------------ */\n/* Internals — wrapper that records an `llm` span */\n/* ------------------------------------------------------------------------ */\n\nfunction buildPatchedCreate(\n original: (\n params: OpenAiChatCompletionCreateParams,\n options?: unknown,\n ) => Promise<OpenAiChatCompletionResponse>,\n options: WrapOpenAiOptions,\n): (\n params: OpenAiChatCompletionCreateParams,\n options?: unknown,\n) => Promise<OpenAiChatCompletionResponse> {\n const agentName = options.defaultAgentName ?? \"openai.chat.completions.create\";\n\n return async function patchedCreate(\n this: unknown,\n params: OpenAiChatCompletionCreateParams,\n callOptions?: unknown,\n ): Promise<OpenAiChatCompletionResponse> {\n const inTrace = getActiveTraceState() !== null;\n\n const work = async (): Promise<OpenAiChatCompletionResponse> => {\n const handle = startSpan({\n name: \"openai.chat.completions.create\",\n type: \"llm\",\n metadata: { model: params?.model },\n });\n let response: OpenAiChatCompletionResponse | undefined;\n try {\n response = await original.call(this, params, callOptions);\n } catch (err) {\n // Customer's own API error — mark the span failed, then re-raise\n // unchanged. Never swallow the caller's real error.\n handle?.end(err);\n throw err;\n }\n\n // Recording is best-effort — never let it throw at the caller.\n try {\n if (handle) {\n const segments = safeExtractSegments(params);\n const usage = response?.usage ?? {};\n const inputTokens = usage.prompt_tokens ?? 0;\n const outputTokens = usage.completion_tokens ?? 0;\n const cachedTokens = usage.prompt_tokens_details?.cached_tokens ?? 0;\n const model = response?.model ?? params?.model;\n\n handle.span.model = model;\n if (inputTokens > 0) handle.span.input_tokens = inputTokens;\n if (outputTokens > 0) handle.span.output_tokens = outputTokens;\n if (cachedTokens > 0) handle.span.cached_input_tokens = cachedTokens;\n const totalTokens =\n usage.total_tokens ??\n (inputTokens > 0 || outputTokens > 0 ? inputTokens + outputTokens : 0);\n if (totalTokens > 0) handle.span.total_tokens = totalTokens;\n\n if (model && (inputTokens > 0 || outputTokens > 0)) {\n const cost = calculateCost({\n inputTokens,\n outputTokens,\n model,\n cachedInputTokens: cachedTokens,\n });\n if (cost !== undefined) handle.span.cost_usd = cost;\n }\n handle.span.context_segments = segments;\n }\n } catch {\n // swallow — telemetry must never break the caller\n }\n handle?.end();\n return response;\n };\n\n if (inTrace) {\n return work();\n }\n\n // No active trace — open a fresh agent span around the call so the\n // llm span has a parent. Mirrors `wrapAnthropic`'s pattern: we can't\n // return `work()`'s Promise from inside `_runAsync`'s callback while\n // preserving typing AND having the fresh trace own the lifecycle, so\n // we wrap explicitly.\n let result: OpenAiChatCompletionResponse | undefined;\n let thrown: unknown;\n await _runAsync({ agentName }, async (runHandle) => {\n runHandle.setOutcome(true);\n try {\n result = await work();\n } catch (err) {\n thrown = err;\n throw err;\n }\n return null;\n });\n if (thrown !== undefined) throw thrown;\n return result as OpenAiChatCompletionResponse;\n };\n}\n\nfunction safeExtractSegments(params: OpenAiChatCompletionCreateParams): ContextSegment[] {\n try {\n if (!params || typeof params !== \"object\") return [];\n return decomposeOpenAiMessages(params.messages, params.tools);\n } catch {\n return [];\n }\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../../src/openai/index.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["/**\n * `@morsehq-dev/sdk/openai` — plain OpenAI SDK instrumentation.\n *\n * Wraps a raw `openai` npm package client (`new OpenAI()` /\n * `new AzureOpenAI()` / any structurally-compatible client) so every\n * `chat.completions.create` call emits an `llm` span carrying model,\n * token counts, `cost_usd`, and pre-segmented `context_segments`.\n *\n * TS port of `apps/sdk/python/src/morse_ai/adapters/openai.py`'s `wrap()`.\n * This module intentionally covers only the `wrap(client)` recommended\n * path (mirrors the Python module's three-layer doc comment, layer 2) —\n * no module-level monkey-patch / `install()` layer, since plain `openai`\n * is not one of the auto-detect targets on either SDK (see\n * `_internal/auto-detect.ts` and Python's `_internal/auto_detect.py`\n * `_adapter_targets()`, which both omit bare `openai`).\n *\n * Distinct from `@morsehq-dev/sdk/openai-agents`, which instruments the\n * `@openai/agents` Agents SDK (a different package with its own Runner /\n * Agent abstractions). This module is for customers calling\n * `openai.chat.completions.create` directly.\n *\n * Context segments are extracted via the shared\n * `_agent-sdk-common/context-decomposer.ts` (`decomposeOpenAiMessages`,\n * MHQ-750) — the request's `messages`/`tools` are already in the native\n * OpenAI wire format the decomposer expects, so no translation layer is\n * needed.\n *\n * Idempotent — wrapping an already-wrapped client instance is a no-op\n * that returns the same wrapper. Recording is best-effort: any failure\n * while building/emitting the span is swallowed so it can never break the\n * customer's OpenAI call. The customer's own API error (thrown by the\n * underlying `create()` call) always propagates unchanged — the span is\n * marked `status: \"failed\"` first, then the error is re-raised.\n *\n * Mirrors `apps/sdk/typescript/src/anthropic/index.ts` in shape.\n */\n\nimport { decomposeOpenAiMessages } from \"../_agent-sdk-common/context-decomposer\";\nimport { setActiveFramework } from \"../_internal/active-framework\";\nimport { captureInputMessages, extractOpenAiOutputText } from \"../_internal/llm-io\";\nimport { calculateCost } from \"../_internal/pricing\";\nimport type { ContextSegment } from \"../_internal/spans\";\nimport { getActiveTraceState, runAsync as _runAsync, startSpan } from \"../_internal/tracing\";\nimport { report } from \"../_internal/diagnostics\";\n\n/* ------------------------------------------------------------------------ */\n/* Public types — minimal structural shapes, NOT a hard dep on `openai` */\n/* ------------------------------------------------------------------------ */\n\n/** Subset of the `openai` package's chat message shape we read from. */\nexport interface OpenAiChatMessageParam {\n role: string;\n content?: unknown;\n tool_call_id?: string;\n [key: string]: unknown;\n}\n\n/** Subset of the `openai` package's tool-definition shape we read from. */\nexport interface OpenAiToolParam {\n type?: string;\n function?: { name?: string; [key: string]: unknown };\n [key: string]: unknown;\n}\n\n/**\n * Subset of `openai`'s `ChatCompletionCreateParams` we read from. We\n * deliberately decline to import the real types so the SDK works even when\n * `openai` isn't installed (it's an optional peer dep).\n */\nexport interface OpenAiChatCompletionCreateParams {\n model: string;\n messages: OpenAiChatMessageParam[];\n tools?: OpenAiToolParam[];\n // Allow forward-compat fields without complaint.\n [key: string]: unknown;\n}\n\nexport interface OpenAiCompletionUsageDetails {\n cached_tokens?: number;\n reasoning_tokens?: number;\n [key: string]: unknown;\n}\n\nexport interface OpenAiCompletionUsage {\n prompt_tokens?: number;\n completion_tokens?: number;\n total_tokens?: number;\n prompt_tokens_details?: OpenAiCompletionUsageDetails;\n completion_tokens_details?: OpenAiCompletionUsageDetails;\n [key: string]: unknown;\n}\n\nexport interface OpenAiChatCompletionResponse {\n id?: string;\n model?: string;\n usage?: OpenAiCompletionUsage;\n choices?: Array<{ message?: { content?: unknown; [k: string]: unknown }; [k: string]: unknown }>;\n [key: string]: unknown;\n}\n\n/**\n * Structural shape of the plain OpenAI client we wrap. We only require\n * that `client.chat.completions.create` is a function returning a Promise.\n */\nexport interface OpenAiClientLike {\n chat: {\n completions: {\n create(\n params: OpenAiChatCompletionCreateParams,\n options?: unknown,\n ): Promise<OpenAiChatCompletionResponse>;\n [key: string]: unknown;\n };\n [key: string]: unknown;\n };\n [key: string]: unknown;\n}\n\n/* ------------------------------------------------------------------------ */\n/* Module-level sentinel */\n/* ------------------------------------------------------------------------ */\n\nconst WRAPPED_CLIENT = Symbol.for(\"morse.openai.wrapped\");\n\n/* ------------------------------------------------------------------------ */\n/* Public API */\n/* ------------------------------------------------------------------------ */\n\nexport interface WrapOpenAiOptions {\n /**\n * When provided, used as the parent agent span's name when\n * `chat.completions.create` is called outside an active trace. Defaults\n * to `\"openai.chat.completions.create\"`.\n */\n defaultAgentName?: string;\n}\n\n/**\n * Wrap an OpenAI client so every `chat.completions.create` call records an\n * `llm` span with `model`, token counts, `cost_usd`, and `context_segments`.\n * The wrapper preserves the rest of the client's surface (other resources,\n * helpers, etc.) via a Proxy.\n *\n * Idempotent — a previously wrapped client is returned as-is.\n *\n * @example\n * ```ts\n * import { wrapOpenAI } from \"@morsehq-dev/sdk/openai\";\n * import OpenAI from \"openai\";\n *\n * const client = wrapOpenAI(new OpenAI());\n * const response = await client.chat.completions.create({\n * model: \"gpt-4o-mini\",\n * messages: [{ role: \"user\", content: \"hello\" }],\n * });\n * ```\n */\nexport function wrapOpenAI<C extends OpenAiClientLike>(\n client: C,\n options: WrapOpenAiOptions = {},\n): C {\n if (!client || typeof client !== \"object\") return client;\n // Already wrapped? Pass through.\n if ((client as Record<string | symbol, unknown>)[WRAPPED_CLIENT]) return client;\n\n const originalCreate = client.chat?.completions?.create?.bind(client.chat.completions);\n if (typeof originalCreate !== \"function\") return client;\n\n const patchedCreate = buildPatchedCreate(originalCreate, options);\n\n // Construct a new `completions` object that proxies to the original for\n // any non-`create` access, wrapped in a `chat` proxy, wrapped in a\n // top-level client proxy — mirrors `wrapAnthropic`'s nested-Proxy shape.\n const patchedCompletions = new Proxy(client.chat.completions, {\n get(target, prop, receiver) {\n if (prop === \"create\") return patchedCreate;\n const value = Reflect.get(target, prop, receiver);\n if (typeof value === \"function\") return (value as (...a: unknown[]) => unknown).bind(target);\n return value;\n },\n });\n\n const patchedChat = new Proxy(client.chat, {\n get(target, prop, receiver) {\n if (prop === \"completions\") return patchedCompletions;\n const value = Reflect.get(target, prop, receiver);\n if (typeof value === \"function\") return (value as (...a: unknown[]) => unknown).bind(target);\n return value;\n },\n });\n\n const wrapper = new Proxy(client, {\n get(target, prop, receiver) {\n if (prop === WRAPPED_CLIENT) return true;\n if (prop === \"chat\") return patchedChat;\n const value = Reflect.get(target, prop, receiver);\n if (typeof value === \"function\") return (value as (...a: unknown[]) => unknown).bind(target);\n return value;\n },\n });\n\n return wrapper as C;\n}\n\n/** True when a wrapped OpenAI client is passed in. */\nexport function isOpenAiWrapped(client: unknown): boolean {\n if (!client || typeof client !== \"object\") return false;\n return (client as Record<string | symbol, unknown>)[WRAPPED_CLIENT] === true;\n}\n\n/* ------------------------------------------------------------------------ */\n/* Internals — wrapper that records an `llm` span */\n/* ------------------------------------------------------------------------ */\n\nfunction buildPatchedCreate(\n original: (\n params: OpenAiChatCompletionCreateParams,\n options?: unknown,\n ) => Promise<OpenAiChatCompletionResponse>,\n options: WrapOpenAiOptions,\n): (\n params: OpenAiChatCompletionCreateParams,\n options?: unknown,\n) => Promise<OpenAiChatCompletionResponse> {\n const agentName = options.defaultAgentName ?? \"openai.chat.completions.create\";\n\n return async function patchedCreate(\n this: unknown,\n params: OpenAiChatCompletionCreateParams,\n callOptions?: unknown,\n ): Promise<OpenAiChatCompletionResponse> {\n const inTrace = getActiveTraceState() !== null;\n\n const work = async (): Promise<OpenAiChatCompletionResponse> => {\n setActiveFramework(\"openai\");\n const handle = startSpan({\n name: \"openai.chat.completions.create\",\n type: \"llm\",\n metadata: { model: params?.model },\n });\n let response: OpenAiChatCompletionResponse | undefined;\n try {\n response = await original.call(this, params, callOptions);\n } catch (err) {\n // Customer's own API error — mark the span failed, then re-raise\n // unchanged. Never swallow the caller's real error.\n handle?.end(err);\n throw err;\n }\n\n // Recording is best-effort — never let it throw at the caller.\n try {\n if (handle) {\n const segments = safeExtractSegments(params);\n const usage = response?.usage ?? {};\n const inputTokens = usage.prompt_tokens ?? 0;\n const outputTokens = usage.completion_tokens ?? 0;\n const cachedTokens = usage.prompt_tokens_details?.cached_tokens ?? 0;\n const model = response?.model ?? params?.model;\n\n handle.span.model = model;\n if (inputTokens > 0) handle.span.input_tokens = inputTokens;\n if (outputTokens > 0) handle.span.output_tokens = outputTokens;\n if (cachedTokens > 0) handle.span.cached_input_tokens = cachedTokens;\n const totalTokens =\n usage.total_tokens ??\n (inputTokens > 0 || outputTokens > 0 ? inputTokens + outputTokens : 0);\n if (totalTokens > 0) handle.span.total_tokens = totalTokens;\n\n if (model && (inputTokens > 0 || outputTokens > 0)) {\n const cost = calculateCost({\n inputTokens,\n outputTokens,\n model,\n cachedInputTokens: cachedTokens,\n });\n if (cost !== undefined) handle.span.cost_usd = cost;\n }\n handle.span.context_segments = segments;\n // MHQ-858: prompt/response capture, parity with the Python\n // adapter's input_data/output_data.\n const inputData = captureInputMessages(params?.messages);\n if (inputData !== undefined) handle.span.input_data = inputData;\n const outputText = extractOpenAiOutputText(response?.choices);\n if (outputText !== undefined) handle.span.output_data = { content: outputText };\n }\n } catch (err) {\n // swallow — telemetry must never break the caller\n reportSwallowed(err, \"morse.openai.stream_wrap\");\n }\n handle?.end();\n return response;\n };\n\n if (inTrace) {\n return work();\n }\n\n // No active trace — open a fresh agent span around the call so the\n // llm span has a parent. Mirrors `wrapAnthropic`'s pattern: we can't\n // return `work()`'s Promise from inside `_runAsync`'s callback while\n // preserving typing AND having the fresh trace own the lifecycle, so\n // we wrap explicitly.\n let result: OpenAiChatCompletionResponse | undefined;\n let thrown: unknown;\n await _runAsync({ agentName }, async (runHandle) => {\n runHandle.setOutcome(true);\n try {\n result = await work();\n } catch (err) {\n thrown = err;\n throw err;\n }\n return null;\n });\n if (thrown !== undefined) throw thrown;\n return result as OpenAiChatCompletionResponse;\n };\n}\n\nfunction safeExtractSegments(params: OpenAiChatCompletionCreateParams): ContextSegment[] {\n try {\n if (!params || typeof params !== \"object\") return [];\n return decomposeOpenAiMessages(params.messages, params.tools);\n } catch {\n return [];\n }\n}\n\n/**\n * Route a swallowed internal error to the diagnostics channel (SDKDIAG-07).\n *\n * Control flow is unchanged — the site still swallows, still returns the same\n * value. It is simply no longer invisible to us.\n */\nfunction reportSwallowed(err: unknown, fingerprint: string): void {\n try {\n report(err, { fingerprint });\n } catch {\n // Reporting must never break the swallow it is reporting on.\n }\n}\n"]}
|