@morsehq-dev/sdk 0.4.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.
Files changed (161) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +294 -0
  3. package/dist/anthropic/index.cjs +39 -0
  4. package/dist/anthropic/index.cjs.map +1 -0
  5. package/dist/anthropic/index.d.cts +213 -0
  6. package/dist/anthropic/index.d.ts +213 -0
  7. package/dist/anthropic/index.js +6 -0
  8. package/dist/anthropic/index.js.map +1 -0
  9. package/dist/anthropic-agent-sdk/index.cjs +744 -0
  10. package/dist/anthropic-agent-sdk/index.cjs.map +1 -0
  11. package/dist/anthropic-agent-sdk/index.d.cts +371 -0
  12. package/dist/anthropic-agent-sdk/index.d.ts +371 -0
  13. package/dist/anthropic-agent-sdk/index.js +735 -0
  14. package/dist/anthropic-agent-sdk/index.js.map +1 -0
  15. package/dist/browser/anthropic/index.cjs +39 -0
  16. package/dist/browser/anthropic/index.cjs.map +1 -0
  17. package/dist/browser/anthropic/index.js +6 -0
  18. package/dist/browser/anthropic/index.js.map +1 -0
  19. package/dist/browser/anthropic-agent-sdk/index.cjs +744 -0
  20. package/dist/browser/anthropic-agent-sdk/index.cjs.map +1 -0
  21. package/dist/browser/anthropic-agent-sdk/index.js +735 -0
  22. package/dist/browser/anthropic-agent-sdk/index.js.map +1 -0
  23. package/dist/browser/chunk-3643DC7K.cjs +365 -0
  24. package/dist/browser/chunk-3643DC7K.cjs.map +1 -0
  25. package/dist/browser/chunk-4FALQMOZ.js +232 -0
  26. package/dist/browser/chunk-4FALQMOZ.js.map +1 -0
  27. package/dist/browser/chunk-5J2QBK75.js +884 -0
  28. package/dist/browser/chunk-5J2QBK75.js.map +1 -0
  29. package/dist/browser/chunk-7MSXWGAH.js +53 -0
  30. package/dist/browser/chunk-7MSXWGAH.js.map +1 -0
  31. package/dist/browser/chunk-A24L5N5N.js +596 -0
  32. package/dist/browser/chunk-A24L5N5N.js.map +1 -0
  33. package/dist/browser/chunk-B7DEUDP6.cjs +177 -0
  34. package/dist/browser/chunk-B7DEUDP6.cjs.map +1 -0
  35. package/dist/browser/chunk-F6CJACNH.cjs +604 -0
  36. package/dist/browser/chunk-F6CJACNH.cjs.map +1 -0
  37. package/dist/browser/chunk-JBOYFQSB.js +412 -0
  38. package/dist/browser/chunk-JBOYFQSB.js.map +1 -0
  39. package/dist/browser/chunk-KRBADE6R.cjs +183 -0
  40. package/dist/browser/chunk-KRBADE6R.cjs.map +1 -0
  41. package/dist/browser/chunk-MCJYZH6W.cjs +415 -0
  42. package/dist/browser/chunk-MCJYZH6W.cjs.map +1 -0
  43. package/dist/browser/chunk-NQG2IAQS.js +178 -0
  44. package/dist/browser/chunk-NQG2IAQS.js.map +1 -0
  45. package/dist/browser/chunk-O4HG3OSK.cjs +929 -0
  46. package/dist/browser/chunk-O4HG3OSK.cjs.map +1 -0
  47. package/dist/browser/chunk-QWRQJO57.js +363 -0
  48. package/dist/browser/chunk-QWRQJO57.js.map +1 -0
  49. package/dist/browser/chunk-SWQOPFE4.cjs +234 -0
  50. package/dist/browser/chunk-SWQOPFE4.cjs.map +1 -0
  51. package/dist/browser/chunk-TYDG747E.js +171 -0
  52. package/dist/browser/chunk-TYDG747E.js.map +1 -0
  53. package/dist/browser/chunk-TZRSDDFP.cjs +56 -0
  54. package/dist/browser/chunk-TZRSDDFP.cjs.map +1 -0
  55. package/dist/browser/index.cjs +587 -0
  56. package/dist/browser/index.cjs.map +1 -0
  57. package/dist/browser/index.js +522 -0
  58. package/dist/browser/index.js.map +1 -0
  59. package/dist/browser/integrations/pino.cjs +89 -0
  60. package/dist/browser/integrations/pino.cjs.map +1 -0
  61. package/dist/browser/integrations/pino.js +86 -0
  62. package/dist/browser/integrations/pino.js.map +1 -0
  63. package/dist/browser/langchain/index.cjs +535 -0
  64. package/dist/browser/langchain/index.cjs.map +1 -0
  65. package/dist/browser/langchain/index.js +528 -0
  66. package/dist/browser/langchain/index.js.map +1 -0
  67. package/dist/browser/langgraph/index.cjs +377 -0
  68. package/dist/browser/langgraph/index.cjs.map +1 -0
  69. package/dist/browser/langgraph/index.js +371 -0
  70. package/dist/browser/langgraph/index.js.map +1 -0
  71. package/dist/browser/openai/index.cjs +125 -0
  72. package/dist/browser/openai/index.cjs.map +1 -0
  73. package/dist/browser/openai/index.js +122 -0
  74. package/dist/browser/openai/index.js.map +1 -0
  75. package/dist/browser/openai-agents/index.cjs +689 -0
  76. package/dist/browser/openai-agents/index.cjs.map +1 -0
  77. package/dist/browser/openai-agents/index.js +678 -0
  78. package/dist/browser/openai-agents/index.js.map +1 -0
  79. package/dist/browser/vercel-ai/index.cjs +233 -0
  80. package/dist/browser/vercel-ai/index.cjs.map +1 -0
  81. package/dist/browser/vercel-ai/index.js +231 -0
  82. package/dist/browser/vercel-ai/index.js.map +1 -0
  83. package/dist/chunk-4R4SHGOK.js +363 -0
  84. package/dist/chunk-4R4SHGOK.js.map +1 -0
  85. package/dist/chunk-7EO7MQBA.cjs +183 -0
  86. package/dist/chunk-7EO7MQBA.cjs.map +1 -0
  87. package/dist/chunk-7YCENA54.cjs +604 -0
  88. package/dist/chunk-7YCENA54.cjs.map +1 -0
  89. package/dist/chunk-CKFOGDUF.js +596 -0
  90. package/dist/chunk-CKFOGDUF.js.map +1 -0
  91. package/dist/chunk-FJUNILZT.cjs +1324 -0
  92. package/dist/chunk-FJUNILZT.cjs.map +1 -0
  93. package/dist/chunk-HDAFUKQ3.js +171 -0
  94. package/dist/chunk-HDAFUKQ3.js.map +1 -0
  95. package/dist/chunk-KBWPNIH4.cjs +234 -0
  96. package/dist/chunk-KBWPNIH4.cjs.map +1 -0
  97. package/dist/chunk-KJEO52QS.cjs +365 -0
  98. package/dist/chunk-KJEO52QS.cjs.map +1 -0
  99. package/dist/chunk-KZBCOZIQ.cjs +177 -0
  100. package/dist/chunk-KZBCOZIQ.cjs.map +1 -0
  101. package/dist/chunk-ME5JALGT.js +53 -0
  102. package/dist/chunk-ME5JALGT.js.map +1 -0
  103. package/dist/chunk-PVHDEPRE.cjs +56 -0
  104. package/dist/chunk-PVHDEPRE.cjs.map +1 -0
  105. package/dist/chunk-RTL23YOQ.js +178 -0
  106. package/dist/chunk-RTL23YOQ.js.map +1 -0
  107. package/dist/chunk-TQWI4UYO.js +1277 -0
  108. package/dist/chunk-TQWI4UYO.js.map +1 -0
  109. package/dist/chunk-VXDBDPDR.cjs +415 -0
  110. package/dist/chunk-VXDBDPDR.cjs.map +1 -0
  111. package/dist/chunk-XTKMUJWI.js +232 -0
  112. package/dist/chunk-XTKMUJWI.js.map +1 -0
  113. package/dist/chunk-ZKUGOWER.js +412 -0
  114. package/dist/chunk-ZKUGOWER.js.map +1 -0
  115. package/dist/index.cjs +843 -0
  116. package/dist/index.cjs.map +1 -0
  117. package/dist/index.d.cts +464 -0
  118. package/dist/index.d.ts +464 -0
  119. package/dist/index.js +778 -0
  120. package/dist/index.js.map +1 -0
  121. package/dist/integrations/pino.cjs +89 -0
  122. package/dist/integrations/pino.cjs.map +1 -0
  123. package/dist/integrations/pino.d.cts +65 -0
  124. package/dist/integrations/pino.d.ts +65 -0
  125. package/dist/integrations/pino.js +86 -0
  126. package/dist/integrations/pino.js.map +1 -0
  127. package/dist/langchain/index.cjs +535 -0
  128. package/dist/langchain/index.cjs.map +1 -0
  129. package/dist/langchain/index.d.cts +265 -0
  130. package/dist/langchain/index.d.ts +265 -0
  131. package/dist/langchain/index.js +528 -0
  132. package/dist/langchain/index.js.map +1 -0
  133. package/dist/langgraph/index.cjs +377 -0
  134. package/dist/langgraph/index.cjs.map +1 -0
  135. package/dist/langgraph/index.d.cts +324 -0
  136. package/dist/langgraph/index.d.ts +324 -0
  137. package/dist/langgraph/index.js +371 -0
  138. package/dist/langgraph/index.js.map +1 -0
  139. package/dist/openai/index.cjs +125 -0
  140. package/dist/openai/index.cjs.map +1 -0
  141. package/dist/openai/index.d.cts +136 -0
  142. package/dist/openai/index.d.ts +136 -0
  143. package/dist/openai/index.js +122 -0
  144. package/dist/openai/index.js.map +1 -0
  145. package/dist/openai-agents/index.cjs +689 -0
  146. package/dist/openai-agents/index.cjs.map +1 -0
  147. package/dist/openai-agents/index.d.cts +502 -0
  148. package/dist/openai-agents/index.d.ts +502 -0
  149. package/dist/openai-agents/index.js +678 -0
  150. package/dist/openai-agents/index.js.map +1 -0
  151. package/dist/spans-DZtMuBvc.d.cts +73 -0
  152. package/dist/spans-DZtMuBvc.d.ts +73 -0
  153. package/dist/tracing-BYAqjT5Q.d.cts +114 -0
  154. package/dist/tracing-rz9cWQ8d.d.ts +114 -0
  155. package/dist/vercel-ai/index.cjs +233 -0
  156. package/dist/vercel-ai/index.cjs.map +1 -0
  157. package/dist/vercel-ai/index.d.cts +93 -0
  158. package/dist/vercel-ai/index.d.ts +93 -0
  159. package/dist/vercel-ai/index.js +231 -0
  160. package/dist/vercel-ai/index.js.map +1 -0
  161. package/package.json +182 -0
@@ -0,0 +1,265 @@
1
+ import { S as SpanHandle } from '../tracing-BYAqjT5Q.cjs';
2
+ import '../spans-DZtMuBvc.cjs';
3
+
4
+ /**
5
+ * Structural types for `@langchain/core` (plain LangChain — chains, LLMs,
6
+ * tools, retrievers) callback handlers.
7
+ *
8
+ * MHQ-482: port of `apps/sdk/python/src/morse_ai/adapters/langchain.py`.
9
+ *
10
+ * No hard import — `@langchain/core` is an optional peer dep. We mirror the
11
+ * `BaseCallbackHandler` method surface our `MorseCallbackHandler` needs to
12
+ * implement (or duck-type when the base class isn't installed). Verified
13
+ * against `@langchain/core/dist/callbacks/base.d.ts` — method names and
14
+ * argument order match exactly (this is the SAME base class LangGraph JS's
15
+ * `MorseCallbackHandler` in `../langgraph/` implements; the two adapters
16
+ * are structurally siblings, not a subclass relationship, because
17
+ * `@langchain/core`'s `BaseCallbackHandler` surface is identical whether a
18
+ * handler is registered on a plain chain or a LangGraph graph).
19
+ */
20
+ /** Subset of `Serialized` from `@langchain/core/load/serializable`. */
21
+ interface SerializedLike {
22
+ id?: string[];
23
+ name?: string;
24
+ kwargs?: Record<string, unknown>;
25
+ [k: string]: unknown;
26
+ }
27
+ /** Subset of `BaseMessage` shape passed on `LLMResult.generations[].message`. */
28
+ interface BaseMessageLike {
29
+ content?: string | unknown[];
30
+ /** LC v0.3 standard usage shape — snake_case, matches the Python SDK. */
31
+ usage_metadata?: {
32
+ input_tokens?: number;
33
+ output_tokens?: number;
34
+ total_tokens?: number;
35
+ input_token_details?: {
36
+ cache_read?: number;
37
+ cache_creation?: number;
38
+ [k: string]: unknown;
39
+ };
40
+ [k: string]: unknown;
41
+ };
42
+ response_metadata?: {
43
+ model_name?: string;
44
+ model?: string;
45
+ token_usage?: {
46
+ prompt_tokens?: number;
47
+ completion_tokens?: number;
48
+ total_tokens?: number;
49
+ input_tokens?: number;
50
+ output_tokens?: number;
51
+ [k: string]: unknown;
52
+ };
53
+ [k: string]: unknown;
54
+ };
55
+ [k: string]: unknown;
56
+ }
57
+ /** Subset of `Generation` / `ChatGeneration` from `@langchain/core/outputs`. */
58
+ interface GenerationLike {
59
+ text?: string;
60
+ message?: BaseMessageLike;
61
+ [k: string]: unknown;
62
+ }
63
+ /** Subset of `LLMResult` from `@langchain/core/outputs`. */
64
+ interface LLMResultLike {
65
+ generations?: GenerationLike[][];
66
+ llmOutput?: {
67
+ tokenUsage?: Record<string, unknown>;
68
+ token_usage?: Record<string, unknown>;
69
+ usage?: Record<string, unknown>;
70
+ model_name?: string;
71
+ model?: string;
72
+ [k: string]: unknown;
73
+ };
74
+ [k: string]: unknown;
75
+ }
76
+ /** Subset of `DocumentInterface` from `@langchain/core/documents`. */
77
+ interface DocumentLike {
78
+ pageContent?: string;
79
+ metadata?: {
80
+ source?: string;
81
+ score?: number;
82
+ relevance_score?: number;
83
+ [k: string]: unknown;
84
+ };
85
+ [k: string]: unknown;
86
+ }
87
+ /**
88
+ * The methods we implement from `BaseCallbackHandler`. Loose signatures
89
+ * because the real base class is conditionally imported; argument order
90
+ * mirrors `@langchain/core/dist/callbacks/base.d.ts` exactly.
91
+ */
92
+ interface CallbackHandlerSurface {
93
+ handleChainStart?(chain: SerializedLike, inputs: Record<string, unknown>, runId: string, parentRunId?: string, tags?: string[], metadata?: Record<string, unknown>, runType?: string, runName?: string): void | Promise<void>;
94
+ handleChainEnd?(outputs: Record<string, unknown>, runId: string, parentRunId?: string, tags?: string[], kwargs?: Record<string, unknown>): void | Promise<void>;
95
+ handleChainError?(err: unknown, runId: string, parentRunId?: string, tags?: string[], kwargs?: Record<string, unknown>): void | Promise<void>;
96
+ handleLLMStart?(llm: SerializedLike, prompts: string[], runId: string, parentRunId?: string, extraParams?: Record<string, unknown>, tags?: string[], metadata?: Record<string, unknown>, runName?: string): void | Promise<void>;
97
+ handleChatModelStart?(llm: SerializedLike, messages: BaseMessageLike[][], runId: string, parentRunId?: string, extraParams?: Record<string, unknown>, tags?: string[], metadata?: Record<string, unknown>, runName?: string): void | Promise<void>;
98
+ handleLLMEnd?(output: LLMResultLike, runId: string, parentRunId?: string, tags?: string[], extraParams?: Record<string, unknown>): void | Promise<void>;
99
+ handleLLMError?(err: unknown, runId: string, parentRunId?: string, tags?: string[], extraParams?: Record<string, unknown>): void | Promise<void>;
100
+ handleToolStart?(tool: SerializedLike, input: string, runId: string, parentRunId?: string, tags?: string[], metadata?: Record<string, unknown>, runName?: string): void | Promise<void>;
101
+ handleToolEnd?(output: unknown, runId: string, parentRunId?: string, tags?: string[]): void | Promise<void>;
102
+ handleToolError?(err: unknown, runId: string, parentRunId?: string, tags?: string[]): void | Promise<void>;
103
+ handleRetrieverStart?(retriever: SerializedLike, query: string, runId: string, parentRunId?: string, tags?: string[], metadata?: Record<string, unknown>, name?: string): void | Promise<void>;
104
+ handleRetrieverEnd?(documents: DocumentLike[], runId: string, parentRunId?: string, tags?: string[]): void | Promise<void>;
105
+ handleRetrieverError?(err: unknown, runId: string, parentRunId?: string, tags?: string[]): void | Promise<void>;
106
+ }
107
+ /** Module-shape probe for `@langchain/core/callbacks/base`. */
108
+ interface LangChainCoreCallbacksModuleLike {
109
+ BaseCallbackHandler?: {
110
+ new (...args: unknown[]): CallbackHandlerSurface & {
111
+ name: string;
112
+ };
113
+ prototype: CallbackHandlerSurface;
114
+ };
115
+ [k: string]: unknown;
116
+ }
117
+
118
+ /**
119
+ * `@morsehq-dev/sdk/langchain` — `MorseCallbackHandler` for plain LangChain
120
+ * (chains, LLMs, tools, retrievers). Port of
121
+ * `apps/sdk/python/src/morse_ai/adapters/langchain.py` (MHQ-482).
122
+ *
123
+ * Usage:
124
+ *
125
+ * ```ts
126
+ * import { MorseCallbackHandler } from "@morsehq-dev/sdk/langchain";
127
+ * import { runAsync } from "@morsehq-dev/sdk"; // or morse.run()
128
+ *
129
+ * const handler = new MorseCallbackHandler({ agentName: "my-agent" });
130
+ * await runAsync({ agentName: "my-agent" }, async () => {
131
+ * await chain.invoke(input, { callbacks: [handler] });
132
+ * });
133
+ * ```
134
+ *
135
+ * Span mapping (mirrors the Python adapter):
136
+ * - handleChainStart / handleChainEnd / handleChainError → `type=agent`
137
+ * - handleLLMStart / handleChatModelStart / handleLLMEnd / handleLLMError → `type=llm`
138
+ * - handleToolStart / handleToolEnd / handleToolError → `type=tool`
139
+ * - handleRetrieverStart / handleRetrieverEnd / handleRetrieverError (@beta)
140
+ * → `type=retriever`
141
+ *
142
+ * ## Deviations from the Python adapter (see PR report for full rationale)
143
+ *
144
+ * 1. **No auto-trace creation.** Python's `MorseCallbackHandler` calls
145
+ * `morse_ai.tracing.run(...)` itself when no trace is active (contextvars
146
+ * support manually entering/exiting a context across independent callback
147
+ * invocations). The TS SDK's trace context is `AsyncLocalStorage`-based
148
+ * (`_internal/tracing.ts`), which only supports the `als.run(store, fn)`
149
+ * callback shape — there is no way to open a trace and leave it open
150
+ * across separate, unwrapped callback calls. Callers MUST wrap the
151
+ * LangChain invocation in `morse.run()` / `runAsync()`. This mirrors the
152
+ * constraint the existing `../langgraph/` adapter already operates under
153
+ * (see its file-header comments) — every span helper silently no-ops
154
+ * (returns `null`) when there is no active trace, exactly like this file.
155
+ * 2. **No structural subclass relationship with `../langgraph/`.** The task
156
+ * brief notes that Python's `langgraph.py::LangGraphCallbackHandler`
157
+ * subclasses `langchain.py::MorseCallbackHandler`. `@langchain/core`'s
158
+ * `BaseCallbackHandler` surface is identical for plain chains and for
159
+ * LangGraph graphs (LangGraph JS is built on `@langchain/core`
160
+ * callbacks), so structurally the two TS adapters COULD share a base.
161
+ * But the existing `../langgraph/` files are off-limits for this task
162
+ * (a separate, already-shipped gap) and refactoring them to extract a
163
+ * shared base is out of scope / higher risk than the value it buys right
164
+ * now. This adapter is therefore a structural sibling, not a subclass —
165
+ * same conventions (span-emission via `startSpan`, `absorbErrorsSync`
166
+ * everywhere, `metadata.adapter` tagging), independently implemented.
167
+ * 3. **No cost computation.** Python's `on_llm_end` calls
168
+ * `morse_ai.pricing.calculate_cost` and `merge_provider_reported_cost`.
169
+ * Neither has a TS port yet (owned by a separate parallel MHQ-482 gap).
170
+ * Token counts/model are still captured; `cost_usd` is left unset until
171
+ * the pricing gap lands.
172
+ * 4. **`type=retriever` uses a real, added `SpanType` variant** (see
173
+ * `_internal/spans.ts`) rather than the `type=tool` +
174
+ * `metadata.tool_kind` fallback pattern used for `hook`/`subagent` — the
175
+ * backend already accepts `"retriever"` (Python's `SpanType.RETRIEVER`
176
+ * has shipped since the Python adapter), so no fallback is needed.
177
+ *
178
+ * All public methods absorb internal errors (never throw into the LangChain
179
+ * runtime) — mirrors Python's `try/except Exception: logger.debug(...)`
180
+ * wrapping on every callback.
181
+ */
182
+
183
+ interface MorseCallbackHandlerOptions {
184
+ /** Falls back to `"langchain-agent"` when unset. Only used for documentation
185
+ * purposes on this handler instance — the actual trace's agent name is set
186
+ * by whatever `morse.run()` / `runAsync()` call wraps the invocation. */
187
+ agentName?: string;
188
+ }
189
+ /**
190
+ * Coerce arbitrary LangChain chain/tool/retriever input or output into a
191
+ * dict payload the wire schema requires (`SpanData.input_data` /
192
+ * `output_data`). Port of Python's `MorseCallbackHandler._ensure_dict`:
193
+ *
194
+ * - `null` / `undefined` → `undefined` (legitimately absent)
195
+ * - plain object → unchanged
196
+ * - object with a callable `toJSON()` returning a plain object → that result
197
+ * (JS analogue of Python's Pydantic `model_dump()` / `dict()` duck typing)
198
+ * - other (string / number / array / class instance) → `{ value: String(x) }`
199
+ *
200
+ * Oversized payloads (JSON > `MAX_STATE_PAYLOAD_BYTES`) are replaced with a
201
+ * truncation marker so the transport queue stays bounded but the dashboard
202
+ * still shows a usable preview — never silently dropped to `undefined`.
203
+ */
204
+ declare function coerceStateValue(data: unknown): Record<string, unknown> | undefined;
205
+ interface TokenUsage {
206
+ inputTokens?: number;
207
+ outputTokens?: number;
208
+ totalTokens?: number;
209
+ cachedInputTokens?: number;
210
+ }
211
+ /**
212
+ * Returns token usage across the provider shapes LangChain JS integrations
213
+ * use in practice. Field names below are snake_case because — unlike most
214
+ * of the JS ecosystem — `@langchain/core`'s `usage_metadata` /
215
+ * `response_metadata` fields ARE snake_case (verified against
216
+ * `@langchain/core/dist/messages/ai.d.ts`), matching the Python SDK 1:1.
217
+ * `llmOutput` is a free-form provider bag; we also check the camelCase
218
+ * `tokenUsage` key the existing `../langgraph/` adapter established.
219
+ */
220
+ declare function extractTokenUsage(response: LLMResultLike | null | undefined): TokenUsage;
221
+ /** Best-effort model-name extraction from an `LLMResult`. */
222
+ declare function extractModel(response: LLMResultLike | null | undefined): string | undefined;
223
+ /** Best-effort output-text extraction from an `LLMResult`, for `output_data.text`. */
224
+ declare function extractOutputText(response: LLMResultLike | null | undefined): string;
225
+ declare class MorseCallbackHandler implements CallbackHandlerSurface {
226
+ /** Required by LangChain's `BaseCallbackHandler` interface. */
227
+ readonly name: string;
228
+ readonly agentName: string;
229
+ /** Map of `runId` → open `SpanHandle`, spanning chain/llm/tool/retriever
230
+ * spans together (mirrors Python's single `_span_stack` dict). */
231
+ private readonly spanStack;
232
+ constructor(options?: MorseCallbackHandlerOptions);
233
+ private openSpan;
234
+ private closeSpan;
235
+ handleChainStart(chain: SerializedLike, inputs: Record<string, unknown>, runId: string): void;
236
+ handleChainEnd(outputs: Record<string, unknown>, runId: string): void;
237
+ handleChainError(err: unknown, runId: string): void;
238
+ handleLLMStart(llm: SerializedLike, prompts: string[], runId: string, _parentRunId?: string, extraParams?: Record<string, unknown>): void;
239
+ handleChatModelStart(llm: SerializedLike, messages: BaseMessageLike[][], runId: string, _parentRunId?: string, extraParams?: Record<string, unknown>): void;
240
+ handleLLMEnd(output: LLMResultLike, runId: string): void;
241
+ handleLLMError(err: unknown, runId: string): void;
242
+ handleToolStart(tool: SerializedLike, input: string, runId: string): void;
243
+ handleToolEnd(output: unknown, runId: string): void;
244
+ handleToolError(err: unknown, runId: string): void;
245
+ handleRetrieverStart(retriever: SerializedLike, query: string, runId: string): void;
246
+ handleRetrieverEnd(documents: DocumentLike[], runId: string): void;
247
+ handleRetrieverError(err: unknown, runId: string): void;
248
+ /** @internal */
249
+ _openSpan(runId: string, name: string, type: "agent" | "llm" | "tool" | "retriever", inputData?: unknown, extraMetadata?: Record<string, unknown>): SpanHandle | null;
250
+ /** @internal */
251
+ _closeSpan(runId: string, outputData?: unknown, error?: unknown): void;
252
+ /** @internal */
253
+ _getSpan(runId: string): SpanHandle | undefined;
254
+ }
255
+ /**
256
+ * Best-effort: if `@langchain/core/callbacks/base` is installed at runtime,
257
+ * return a `MorseCallbackHandler`-shaped class whose prototype chain
258
+ * includes the real `BaseCallbackHandler` (for users relying on
259
+ * `instanceof BaseCallbackHandler` checks). Otherwise return the duck-typed
260
+ * `MorseCallbackHandler` defined above. Mirrors `../langgraph/callback-handler.ts`'s
261
+ * `getCallbackHandlerClass()`.
262
+ */
263
+ declare function getCallbackHandlerClass(): Promise<typeof MorseCallbackHandler>;
264
+
265
+ export { type BaseMessageLike, type CallbackHandlerSurface, type DocumentLike, type GenerationLike, type LLMResultLike, type LangChainCoreCallbacksModuleLike, MorseCallbackHandler, type MorseCallbackHandlerOptions, type SerializedLike, type TokenUsage, coerceStateValue, extractModel, extractOutputText, extractTokenUsage, getCallbackHandlerClass };
@@ -0,0 +1,265 @@
1
+ import { S as SpanHandle } from '../tracing-rz9cWQ8d.js';
2
+ import '../spans-DZtMuBvc.js';
3
+
4
+ /**
5
+ * Structural types for `@langchain/core` (plain LangChain — chains, LLMs,
6
+ * tools, retrievers) callback handlers.
7
+ *
8
+ * MHQ-482: port of `apps/sdk/python/src/morse_ai/adapters/langchain.py`.
9
+ *
10
+ * No hard import — `@langchain/core` is an optional peer dep. We mirror the
11
+ * `BaseCallbackHandler` method surface our `MorseCallbackHandler` needs to
12
+ * implement (or duck-type when the base class isn't installed). Verified
13
+ * against `@langchain/core/dist/callbacks/base.d.ts` — method names and
14
+ * argument order match exactly (this is the SAME base class LangGraph JS's
15
+ * `MorseCallbackHandler` in `../langgraph/` implements; the two adapters
16
+ * are structurally siblings, not a subclass relationship, because
17
+ * `@langchain/core`'s `BaseCallbackHandler` surface is identical whether a
18
+ * handler is registered on a plain chain or a LangGraph graph).
19
+ */
20
+ /** Subset of `Serialized` from `@langchain/core/load/serializable`. */
21
+ interface SerializedLike {
22
+ id?: string[];
23
+ name?: string;
24
+ kwargs?: Record<string, unknown>;
25
+ [k: string]: unknown;
26
+ }
27
+ /** Subset of `BaseMessage` shape passed on `LLMResult.generations[].message`. */
28
+ interface BaseMessageLike {
29
+ content?: string | unknown[];
30
+ /** LC v0.3 standard usage shape — snake_case, matches the Python SDK. */
31
+ usage_metadata?: {
32
+ input_tokens?: number;
33
+ output_tokens?: number;
34
+ total_tokens?: number;
35
+ input_token_details?: {
36
+ cache_read?: number;
37
+ cache_creation?: number;
38
+ [k: string]: unknown;
39
+ };
40
+ [k: string]: unknown;
41
+ };
42
+ response_metadata?: {
43
+ model_name?: string;
44
+ model?: string;
45
+ token_usage?: {
46
+ prompt_tokens?: number;
47
+ completion_tokens?: number;
48
+ total_tokens?: number;
49
+ input_tokens?: number;
50
+ output_tokens?: number;
51
+ [k: string]: unknown;
52
+ };
53
+ [k: string]: unknown;
54
+ };
55
+ [k: string]: unknown;
56
+ }
57
+ /** Subset of `Generation` / `ChatGeneration` from `@langchain/core/outputs`. */
58
+ interface GenerationLike {
59
+ text?: string;
60
+ message?: BaseMessageLike;
61
+ [k: string]: unknown;
62
+ }
63
+ /** Subset of `LLMResult` from `@langchain/core/outputs`. */
64
+ interface LLMResultLike {
65
+ generations?: GenerationLike[][];
66
+ llmOutput?: {
67
+ tokenUsage?: Record<string, unknown>;
68
+ token_usage?: Record<string, unknown>;
69
+ usage?: Record<string, unknown>;
70
+ model_name?: string;
71
+ model?: string;
72
+ [k: string]: unknown;
73
+ };
74
+ [k: string]: unknown;
75
+ }
76
+ /** Subset of `DocumentInterface` from `@langchain/core/documents`. */
77
+ interface DocumentLike {
78
+ pageContent?: string;
79
+ metadata?: {
80
+ source?: string;
81
+ score?: number;
82
+ relevance_score?: number;
83
+ [k: string]: unknown;
84
+ };
85
+ [k: string]: unknown;
86
+ }
87
+ /**
88
+ * The methods we implement from `BaseCallbackHandler`. Loose signatures
89
+ * because the real base class is conditionally imported; argument order
90
+ * mirrors `@langchain/core/dist/callbacks/base.d.ts` exactly.
91
+ */
92
+ interface CallbackHandlerSurface {
93
+ handleChainStart?(chain: SerializedLike, inputs: Record<string, unknown>, runId: string, parentRunId?: string, tags?: string[], metadata?: Record<string, unknown>, runType?: string, runName?: string): void | Promise<void>;
94
+ handleChainEnd?(outputs: Record<string, unknown>, runId: string, parentRunId?: string, tags?: string[], kwargs?: Record<string, unknown>): void | Promise<void>;
95
+ handleChainError?(err: unknown, runId: string, parentRunId?: string, tags?: string[], kwargs?: Record<string, unknown>): void | Promise<void>;
96
+ handleLLMStart?(llm: SerializedLike, prompts: string[], runId: string, parentRunId?: string, extraParams?: Record<string, unknown>, tags?: string[], metadata?: Record<string, unknown>, runName?: string): void | Promise<void>;
97
+ handleChatModelStart?(llm: SerializedLike, messages: BaseMessageLike[][], runId: string, parentRunId?: string, extraParams?: Record<string, unknown>, tags?: string[], metadata?: Record<string, unknown>, runName?: string): void | Promise<void>;
98
+ handleLLMEnd?(output: LLMResultLike, runId: string, parentRunId?: string, tags?: string[], extraParams?: Record<string, unknown>): void | Promise<void>;
99
+ handleLLMError?(err: unknown, runId: string, parentRunId?: string, tags?: string[], extraParams?: Record<string, unknown>): void | Promise<void>;
100
+ handleToolStart?(tool: SerializedLike, input: string, runId: string, parentRunId?: string, tags?: string[], metadata?: Record<string, unknown>, runName?: string): void | Promise<void>;
101
+ handleToolEnd?(output: unknown, runId: string, parentRunId?: string, tags?: string[]): void | Promise<void>;
102
+ handleToolError?(err: unknown, runId: string, parentRunId?: string, tags?: string[]): void | Promise<void>;
103
+ handleRetrieverStart?(retriever: SerializedLike, query: string, runId: string, parentRunId?: string, tags?: string[], metadata?: Record<string, unknown>, name?: string): void | Promise<void>;
104
+ handleRetrieverEnd?(documents: DocumentLike[], runId: string, parentRunId?: string, tags?: string[]): void | Promise<void>;
105
+ handleRetrieverError?(err: unknown, runId: string, parentRunId?: string, tags?: string[]): void | Promise<void>;
106
+ }
107
+ /** Module-shape probe for `@langchain/core/callbacks/base`. */
108
+ interface LangChainCoreCallbacksModuleLike {
109
+ BaseCallbackHandler?: {
110
+ new (...args: unknown[]): CallbackHandlerSurface & {
111
+ name: string;
112
+ };
113
+ prototype: CallbackHandlerSurface;
114
+ };
115
+ [k: string]: unknown;
116
+ }
117
+
118
+ /**
119
+ * `@morsehq-dev/sdk/langchain` — `MorseCallbackHandler` for plain LangChain
120
+ * (chains, LLMs, tools, retrievers). Port of
121
+ * `apps/sdk/python/src/morse_ai/adapters/langchain.py` (MHQ-482).
122
+ *
123
+ * Usage:
124
+ *
125
+ * ```ts
126
+ * import { MorseCallbackHandler } from "@morsehq-dev/sdk/langchain";
127
+ * import { runAsync } from "@morsehq-dev/sdk"; // or morse.run()
128
+ *
129
+ * const handler = new MorseCallbackHandler({ agentName: "my-agent" });
130
+ * await runAsync({ agentName: "my-agent" }, async () => {
131
+ * await chain.invoke(input, { callbacks: [handler] });
132
+ * });
133
+ * ```
134
+ *
135
+ * Span mapping (mirrors the Python adapter):
136
+ * - handleChainStart / handleChainEnd / handleChainError → `type=agent`
137
+ * - handleLLMStart / handleChatModelStart / handleLLMEnd / handleLLMError → `type=llm`
138
+ * - handleToolStart / handleToolEnd / handleToolError → `type=tool`
139
+ * - handleRetrieverStart / handleRetrieverEnd / handleRetrieverError (@beta)
140
+ * → `type=retriever`
141
+ *
142
+ * ## Deviations from the Python adapter (see PR report for full rationale)
143
+ *
144
+ * 1. **No auto-trace creation.** Python's `MorseCallbackHandler` calls
145
+ * `morse_ai.tracing.run(...)` itself when no trace is active (contextvars
146
+ * support manually entering/exiting a context across independent callback
147
+ * invocations). The TS SDK's trace context is `AsyncLocalStorage`-based
148
+ * (`_internal/tracing.ts`), which only supports the `als.run(store, fn)`
149
+ * callback shape — there is no way to open a trace and leave it open
150
+ * across separate, unwrapped callback calls. Callers MUST wrap the
151
+ * LangChain invocation in `morse.run()` / `runAsync()`. This mirrors the
152
+ * constraint the existing `../langgraph/` adapter already operates under
153
+ * (see its file-header comments) — every span helper silently no-ops
154
+ * (returns `null`) when there is no active trace, exactly like this file.
155
+ * 2. **No structural subclass relationship with `../langgraph/`.** The task
156
+ * brief notes that Python's `langgraph.py::LangGraphCallbackHandler`
157
+ * subclasses `langchain.py::MorseCallbackHandler`. `@langchain/core`'s
158
+ * `BaseCallbackHandler` surface is identical for plain chains and for
159
+ * LangGraph graphs (LangGraph JS is built on `@langchain/core`
160
+ * callbacks), so structurally the two TS adapters COULD share a base.
161
+ * But the existing `../langgraph/` files are off-limits for this task
162
+ * (a separate, already-shipped gap) and refactoring them to extract a
163
+ * shared base is out of scope / higher risk than the value it buys right
164
+ * now. This adapter is therefore a structural sibling, not a subclass —
165
+ * same conventions (span-emission via `startSpan`, `absorbErrorsSync`
166
+ * everywhere, `metadata.adapter` tagging), independently implemented.
167
+ * 3. **No cost computation.** Python's `on_llm_end` calls
168
+ * `morse_ai.pricing.calculate_cost` and `merge_provider_reported_cost`.
169
+ * Neither has a TS port yet (owned by a separate parallel MHQ-482 gap).
170
+ * Token counts/model are still captured; `cost_usd` is left unset until
171
+ * the pricing gap lands.
172
+ * 4. **`type=retriever` uses a real, added `SpanType` variant** (see
173
+ * `_internal/spans.ts`) rather than the `type=tool` +
174
+ * `metadata.tool_kind` fallback pattern used for `hook`/`subagent` — the
175
+ * backend already accepts `"retriever"` (Python's `SpanType.RETRIEVER`
176
+ * has shipped since the Python adapter), so no fallback is needed.
177
+ *
178
+ * All public methods absorb internal errors (never throw into the LangChain
179
+ * runtime) — mirrors Python's `try/except Exception: logger.debug(...)`
180
+ * wrapping on every callback.
181
+ */
182
+
183
+ interface MorseCallbackHandlerOptions {
184
+ /** Falls back to `"langchain-agent"` when unset. Only used for documentation
185
+ * purposes on this handler instance — the actual trace's agent name is set
186
+ * by whatever `morse.run()` / `runAsync()` call wraps the invocation. */
187
+ agentName?: string;
188
+ }
189
+ /**
190
+ * Coerce arbitrary LangChain chain/tool/retriever input or output into a
191
+ * dict payload the wire schema requires (`SpanData.input_data` /
192
+ * `output_data`). Port of Python's `MorseCallbackHandler._ensure_dict`:
193
+ *
194
+ * - `null` / `undefined` → `undefined` (legitimately absent)
195
+ * - plain object → unchanged
196
+ * - object with a callable `toJSON()` returning a plain object → that result
197
+ * (JS analogue of Python's Pydantic `model_dump()` / `dict()` duck typing)
198
+ * - other (string / number / array / class instance) → `{ value: String(x) }`
199
+ *
200
+ * Oversized payloads (JSON > `MAX_STATE_PAYLOAD_BYTES`) are replaced with a
201
+ * truncation marker so the transport queue stays bounded but the dashboard
202
+ * still shows a usable preview — never silently dropped to `undefined`.
203
+ */
204
+ declare function coerceStateValue(data: unknown): Record<string, unknown> | undefined;
205
+ interface TokenUsage {
206
+ inputTokens?: number;
207
+ outputTokens?: number;
208
+ totalTokens?: number;
209
+ cachedInputTokens?: number;
210
+ }
211
+ /**
212
+ * Returns token usage across the provider shapes LangChain JS integrations
213
+ * use in practice. Field names below are snake_case because — unlike most
214
+ * of the JS ecosystem — `@langchain/core`'s `usage_metadata` /
215
+ * `response_metadata` fields ARE snake_case (verified against
216
+ * `@langchain/core/dist/messages/ai.d.ts`), matching the Python SDK 1:1.
217
+ * `llmOutput` is a free-form provider bag; we also check the camelCase
218
+ * `tokenUsage` key the existing `../langgraph/` adapter established.
219
+ */
220
+ declare function extractTokenUsage(response: LLMResultLike | null | undefined): TokenUsage;
221
+ /** Best-effort model-name extraction from an `LLMResult`. */
222
+ declare function extractModel(response: LLMResultLike | null | undefined): string | undefined;
223
+ /** Best-effort output-text extraction from an `LLMResult`, for `output_data.text`. */
224
+ declare function extractOutputText(response: LLMResultLike | null | undefined): string;
225
+ declare class MorseCallbackHandler implements CallbackHandlerSurface {
226
+ /** Required by LangChain's `BaseCallbackHandler` interface. */
227
+ readonly name: string;
228
+ readonly agentName: string;
229
+ /** Map of `runId` → open `SpanHandle`, spanning chain/llm/tool/retriever
230
+ * spans together (mirrors Python's single `_span_stack` dict). */
231
+ private readonly spanStack;
232
+ constructor(options?: MorseCallbackHandlerOptions);
233
+ private openSpan;
234
+ private closeSpan;
235
+ handleChainStart(chain: SerializedLike, inputs: Record<string, unknown>, runId: string): void;
236
+ handleChainEnd(outputs: Record<string, unknown>, runId: string): void;
237
+ handleChainError(err: unknown, runId: string): void;
238
+ handleLLMStart(llm: SerializedLike, prompts: string[], runId: string, _parentRunId?: string, extraParams?: Record<string, unknown>): void;
239
+ handleChatModelStart(llm: SerializedLike, messages: BaseMessageLike[][], runId: string, _parentRunId?: string, extraParams?: Record<string, unknown>): void;
240
+ handleLLMEnd(output: LLMResultLike, runId: string): void;
241
+ handleLLMError(err: unknown, runId: string): void;
242
+ handleToolStart(tool: SerializedLike, input: string, runId: string): void;
243
+ handleToolEnd(output: unknown, runId: string): void;
244
+ handleToolError(err: unknown, runId: string): void;
245
+ handleRetrieverStart(retriever: SerializedLike, query: string, runId: string): void;
246
+ handleRetrieverEnd(documents: DocumentLike[], runId: string): void;
247
+ handleRetrieverError(err: unknown, runId: string): void;
248
+ /** @internal */
249
+ _openSpan(runId: string, name: string, type: "agent" | "llm" | "tool" | "retriever", inputData?: unknown, extraMetadata?: Record<string, unknown>): SpanHandle | null;
250
+ /** @internal */
251
+ _closeSpan(runId: string, outputData?: unknown, error?: unknown): void;
252
+ /** @internal */
253
+ _getSpan(runId: string): SpanHandle | undefined;
254
+ }
255
+ /**
256
+ * Best-effort: if `@langchain/core/callbacks/base` is installed at runtime,
257
+ * return a `MorseCallbackHandler`-shaped class whose prototype chain
258
+ * includes the real `BaseCallbackHandler` (for users relying on
259
+ * `instanceof BaseCallbackHandler` checks). Otherwise return the duck-typed
260
+ * `MorseCallbackHandler` defined above. Mirrors `../langgraph/callback-handler.ts`'s
261
+ * `getCallbackHandlerClass()`.
262
+ */
263
+ declare function getCallbackHandlerClass(): Promise<typeof MorseCallbackHandler>;
264
+
265
+ export { type BaseMessageLike, type CallbackHandlerSurface, type DocumentLike, type GenerationLike, type LLMResultLike, type LangChainCoreCallbacksModuleLike, MorseCallbackHandler, type MorseCallbackHandlerOptions, type SerializedLike, type TokenUsage, coerceStateValue, extractModel, extractOutputText, extractTokenUsage, getCallbackHandlerClass };