langsmith 0.7.16 → 0.8.0

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.
@@ -0,0 +1,648 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.wrapManagedAgentSessionEvents = wrapManagedAgentSessionEvents;
4
+ const traceable_js_1 = require("../../traceable.cjs");
5
+ const run_trees_js_1 = require("../../run_trees.cjs");
6
+ const anthropic_js_1 = require("../anthropic.cjs");
7
+ const types_js_1 = require("../../utils/types.cjs");
8
+ function processManagedAgentStreamInputs(inputs) {
9
+ const args = Array.isArray(inputs.args) ? inputs.args : [];
10
+ const [sessionID, params] = args.length > 0 ? args : [inputs.input, undefined];
11
+ return {
12
+ session_id: sessionID,
13
+ ...(params ? { stream_params: params } : {}),
14
+ };
15
+ }
16
+ function getManagedAgentText(content) {
17
+ if (!Array.isArray(content))
18
+ return "";
19
+ return content
20
+ .map((block) => {
21
+ if (typeof block === "object" &&
22
+ block != null &&
23
+ "type" in block &&
24
+ block.type === "text" &&
25
+ "text" in block &&
26
+ typeof block.text === "string") {
27
+ return block.text;
28
+ }
29
+ return "";
30
+ })
31
+ .join("");
32
+ }
33
+ function managedAgentSessionEventsAggregator(chunks) {
34
+ const toolCalls = [];
35
+ const toolResults = [];
36
+ const errors = [];
37
+ const modelRequests = [];
38
+ const previews = new Map();
39
+ let status;
40
+ let stopReason;
41
+ const usage = {
42
+ input_tokens: 0,
43
+ output_tokens: 0,
44
+ cache_creation_input_tokens: 0,
45
+ cache_read_input_tokens: 0,
46
+ };
47
+ for (const event of chunks) {
48
+ switch (event.type) {
49
+ case "agent.message": {
50
+ if (typeof event.id === "string")
51
+ previews.delete(event.id);
52
+ break;
53
+ }
54
+ case "agent.tool_use":
55
+ case "agent.mcp_tool_use":
56
+ case "agent.custom_tool_use": {
57
+ toolCalls.push({ ...event });
58
+ break;
59
+ }
60
+ case "agent.tool_result":
61
+ case "agent.mcp_tool_result":
62
+ case "user.custom_tool_result": {
63
+ toolResults.push({ ...event });
64
+ break;
65
+ }
66
+ case "span.model_request_end": {
67
+ const modelUsage = event.model_usage;
68
+ if (modelUsage) {
69
+ for (const key of Object.keys(usage)) {
70
+ const value = modelUsage[key];
71
+ if (typeof value === "number")
72
+ usage[key] += value;
73
+ }
74
+ modelRequests.push({
75
+ id: event.id,
76
+ is_error: event.is_error,
77
+ model_request_start_id: event.model_request_start_id,
78
+ model_usage: modelUsage,
79
+ processed_at: event.processed_at,
80
+ });
81
+ }
82
+ previews.clear();
83
+ break;
84
+ }
85
+ case "session.error":
86
+ errors.push({ ...event });
87
+ break;
88
+ case "session.status_running":
89
+ case "session.status_idle":
90
+ case "session.status_rescheduled":
91
+ case "session.status_terminated":
92
+ status = event.type;
93
+ if (event.type === "session.status_idle") {
94
+ stopReason = event.stop_reason;
95
+ }
96
+ break;
97
+ }
98
+ }
99
+ const unreconciledPreviews = [...previews.entries()].map(([eventID, byIndex]) => ({
100
+ id: eventID,
101
+ text: [...byIndex.entries()]
102
+ .sort(([left], [right]) => left - right)
103
+ .map(([, text]) => text)
104
+ .join(""),
105
+ }));
106
+ const messageEvents = chunks.filter((event) => event.type === "agent.message");
107
+ const lastMessage = getManagedAgentAssistantOutputMessages(messageEvents).at(-1);
108
+ return {
109
+ content: messageEvents.flatMap((message) => Array.isArray(message.content) ? message.content : []),
110
+ ...(lastMessage ? { messages: [lastMessage] } : {}),
111
+ tool_calls: toolCalls,
112
+ tool_results: toolResults,
113
+ errors,
114
+ model_requests: modelRequests,
115
+ status,
116
+ stop_reason: stopReason,
117
+ events: chunks,
118
+ ...(unreconciledPreviews.length > 0
119
+ ? { unreconciled_previews: unreconciledPreviews }
120
+ : {}),
121
+ };
122
+ }
123
+ function getManagedAgentInputEvents(chunks) {
124
+ return chunks
125
+ .filter((event) => typeof event.type === "string" &&
126
+ (event.type.startsWith("user.") || event.type.startsWith("system.")))
127
+ .map((event) => ({ ...event }));
128
+ }
129
+ function contentBlocksToChatContent(content) {
130
+ if (!Array.isArray(content))
131
+ return content;
132
+ const text = getManagedAgentText(content);
133
+ return text.length > 0 &&
134
+ content.every((block) => {
135
+ return (typeof block === "object" &&
136
+ block != null &&
137
+ "type" in block &&
138
+ block.type === "text");
139
+ })
140
+ ? text
141
+ : content;
142
+ }
143
+ function managedAgentToolUseToContentBlock(event) {
144
+ return {
145
+ type: "tool_use",
146
+ id: event.id,
147
+ name: event.name,
148
+ input: event.input,
149
+ ...(event.type === "agent.mcp_tool_use"
150
+ ? { mcp_server_name: event.mcp_server_name }
151
+ : {}),
152
+ };
153
+ }
154
+ function getManagedAgentChatMessages(events) {
155
+ const messages = [];
156
+ for (const event of events) {
157
+ switch (event.type) {
158
+ case "user.message":
159
+ messages.push({
160
+ role: "user",
161
+ content: contentBlocksToChatContent(event.content),
162
+ });
163
+ break;
164
+ case "agent.message":
165
+ messages.push({
166
+ role: "assistant",
167
+ content: contentBlocksToChatContent(event.content),
168
+ });
169
+ break;
170
+ case "agent.tool_use":
171
+ case "agent.mcp_tool_use":
172
+ case "agent.custom_tool_use":
173
+ messages.push({
174
+ role: "assistant",
175
+ content: [managedAgentToolUseToContentBlock(event)],
176
+ });
177
+ break;
178
+ case "agent.tool_result":
179
+ messages.push({
180
+ role: "tool",
181
+ tool_call_id: event.tool_use_id,
182
+ content: event.content,
183
+ ...(event.is_error != null ? { is_error: event.is_error } : {}),
184
+ });
185
+ break;
186
+ case "agent.mcp_tool_result":
187
+ messages.push({
188
+ role: "tool",
189
+ tool_call_id: event.mcp_tool_use_id,
190
+ content: event.content,
191
+ ...(event.is_error != null ? { is_error: event.is_error } : {}),
192
+ });
193
+ break;
194
+ case "user.custom_tool_result":
195
+ messages.push({
196
+ role: "tool",
197
+ tool_call_id: event.custom_tool_use_id,
198
+ content: event.content,
199
+ ...(event.is_error != null ? { is_error: event.is_error } : {}),
200
+ });
201
+ break;
202
+ case "user.interrupt":
203
+ case "user.define_outcome":
204
+ case "user.tool_result":
205
+ case "user.tool_confirmation":
206
+ break;
207
+ }
208
+ }
209
+ return messages;
210
+ }
211
+ function getManagedAgentAssistantOutputMessages(events) {
212
+ return events.flatMap((event) => {
213
+ if (event.type === "agent.message") {
214
+ return [
215
+ {
216
+ id: event.id,
217
+ role: "assistant",
218
+ content: contentBlocksToChatContent(event.content),
219
+ processed_at: event.processed_at,
220
+ },
221
+ ];
222
+ }
223
+ if (event.type === "agent.tool_use" ||
224
+ event.type === "agent.mcp_tool_use" ||
225
+ event.type === "agent.custom_tool_use") {
226
+ return [
227
+ {
228
+ id: event.id,
229
+ role: "assistant",
230
+ content: [managedAgentToolUseToContentBlock(event)],
231
+ processed_at: event.processed_at,
232
+ },
233
+ ];
234
+ }
235
+ return [];
236
+ });
237
+ }
238
+ function getManagedAgentStreamError(chunks) {
239
+ const errorEvent = chunks.find((event) => event.type === "session.error");
240
+ const error = errorEvent?.error;
241
+ if (typeof error === "object" && error != null && "message" in error) {
242
+ return String(error.message);
243
+ }
244
+ return undefined;
245
+ }
246
+ function isCustomToolRequiresActionIdle(event, chunks) {
247
+ if (event.type !== "session.status_idle" ||
248
+ event.stop_reason.type !== "requires_action") {
249
+ return false;
250
+ }
251
+ return event.stop_reason.event_ids.every((eventID) => chunks.some((candidate) => candidate.type === "agent.custom_tool_use" && candidate.id === eventID));
252
+ }
253
+ function getManagedAgentTurnError(chunks) {
254
+ const idleEvent = [...chunks]
255
+ .reverse()
256
+ .find((event) => event.type === "session.status_idle");
257
+ if (idleEvent?.type === "session.status_idle") {
258
+ if (idleEvent.stop_reason.type === "requires_action") {
259
+ return `Interrupted: requires_action (${idleEvent.stop_reason.event_ids.join(", ")})`;
260
+ }
261
+ if (idleEvent.stop_reason.type === "retries_exhausted") {
262
+ return "Interrupted: retries_exhausted";
263
+ }
264
+ }
265
+ return undefined;
266
+ }
267
+ function stripLangSmithExtraFromRequestOptions(options) {
268
+ if (typeof options === "object" &&
269
+ options != null &&
270
+ "langsmithExtra" in options) {
271
+ const { langsmithExtra: _langsmithExtra, ...rest } = options;
272
+ return rest;
273
+ }
274
+ return options;
275
+ }
276
+ function getProcessedAtMillis(event) {
277
+ if (!event)
278
+ return undefined;
279
+ return typeof event.processed_at === "string"
280
+ ? Date.parse(event.processed_at)
281
+ : undefined;
282
+ }
283
+ function getFirstProcessedAtMillis(events) {
284
+ for (const event of events) {
285
+ const processedAt = getProcessedAtMillis(event);
286
+ if (processedAt !== undefined)
287
+ return processedAt;
288
+ }
289
+ return undefined;
290
+ }
291
+ function getLastProcessedAtMillis(events) {
292
+ for (const event of [...events].reverse()) {
293
+ const processedAt = getProcessedAtMillis(event);
294
+ if (processedAt !== undefined)
295
+ return processedAt;
296
+ }
297
+ return undefined;
298
+ }
299
+ async function createManagedAgentChildRuns(parentRun, chunks, metadata, options) {
300
+ const { modelConfig, systemPrompt, pendingToolUseEvents, completedChildRunIds, } = options;
301
+ const modelName = typeof modelConfig?.id === "string" ? modelConfig.id : undefined;
302
+ const modelRequestStarts = new Map();
303
+ const childSpecs = [];
304
+ const toolUseEvents = new Map();
305
+ const toolResultEvents = new Map();
306
+ // Aggregate tool use and tool results from all events
307
+ // This is necessary because tool results may arrive after the model request ends (eg custom tools)
308
+ for (const event of chunks.all) {
309
+ if ((event.type === "agent.tool_use" ||
310
+ event.type === "agent.mcp_tool_use" ||
311
+ event.type === "agent.custom_tool_use") &&
312
+ typeof event.id === "string") {
313
+ toolUseEvents.set(event.id, event);
314
+ }
315
+ else if (event.type === "agent.tool_result" &&
316
+ typeof event.tool_use_id === "string") {
317
+ toolResultEvents.set(event.tool_use_id, event);
318
+ }
319
+ else if (event.type === "agent.mcp_tool_result" &&
320
+ typeof event.mcp_tool_use_id === "string") {
321
+ toolResultEvents.set(event.mcp_tool_use_id, event);
322
+ }
323
+ else if (event.type === "user.custom_tool_result" &&
324
+ typeof event.custom_tool_use_id === "string") {
325
+ toolResultEvents.set(event.custom_tool_use_id, event);
326
+ }
327
+ }
328
+ // Handle turn specific events (model requests, tool calls)
329
+ for (const event of chunks.turn) {
330
+ if (event.type === "span.model_request_start" &&
331
+ typeof event.id === "string") {
332
+ modelRequestStarts.set(event.id, event);
333
+ }
334
+ else if (event.type === "span.model_request_end") {
335
+ const startID = event.model_request_start_id;
336
+ const startEvent = modelRequestStarts.get(startID);
337
+ const startIndex = startEvent ? chunks.all.indexOf(startEvent) : -1;
338
+ const endIndex = chunks.all.indexOf(event);
339
+ const eventsBeforeRequest = startIndex >= 0 ? chunks.all.slice(0, startIndex) : [];
340
+ const eventsInRequest = startIndex >= 0 && endIndex >= startIndex
341
+ ? chunks.all.slice(startIndex, endIndex + 1)
342
+ : [event];
343
+ const messageEvents = eventsInRequest.filter((candidate) => candidate.type === "agent.message");
344
+ const messages = getManagedAgentAssistantOutputMessages(eventsInRequest);
345
+ const toolCalls = eventsInRequest.filter((candidate) => candidate.type === "agent.tool_use" ||
346
+ candidate.type === "agent.mcp_tool_use" ||
347
+ candidate.type === "agent.custom_tool_use");
348
+ const content = messageEvents.flatMap((message) => Array.isArray(message.content) ? message.content : []);
349
+ const usageMetadata = (0, anthropic_js_1.createUsageMetadata)(event.model_usage);
350
+ const startTime = startEvent
351
+ ? (getProcessedAtMillis(startEvent) ?? Date.now())
352
+ : Date.now();
353
+ childSpecs.push({
354
+ startTime,
355
+ index: startIndex >= 0 ? startIndex : endIndex,
356
+ createAndPost: async () => {
357
+ const childRun = parentRun.createChild({
358
+ name: "ClaudeManagedAgentModelRequest",
359
+ run_type: "llm",
360
+ inputs: {
361
+ events: eventsBeforeRequest,
362
+ system: systemPrompt,
363
+ messages: getManagedAgentChatMessages(eventsBeforeRequest),
364
+ ...(startEvent ? { model_request_start: startEvent } : {}),
365
+ },
366
+ metadata: {
367
+ ...metadata,
368
+ ...(modelName ? { ls_model_name: modelName } : {}),
369
+ ...(modelConfig
370
+ ? {
371
+ ls_invocation_params: {
372
+ ...(metadata.ls_invocation_params ?? {}),
373
+ model_config: modelConfig,
374
+ },
375
+ }
376
+ : {}),
377
+ ...(usageMetadata ? { usage_metadata: usageMetadata } : {}),
378
+ },
379
+ start_time: startTime,
380
+ });
381
+ await childRun.end({
382
+ content,
383
+ messages,
384
+ tool_calls: toolCalls,
385
+ model_request_end: event,
386
+ ...(event.model_usage ? { model_usage: event.model_usage } : {}),
387
+ ...(usageMetadata ? { usage_metadata: usageMetadata } : {}),
388
+ }, event.is_error ? "Model request failed" : undefined, getProcessedAtMillis(event));
389
+ await childRun.postRun();
390
+ },
391
+ });
392
+ }
393
+ }
394
+ for (const [toolUseID, toolUse] of toolUseEvents.entries()) {
395
+ const result = toolResultEvents.get(toolUseID);
396
+ const isCurrentTurnTool = chunks.turn.includes(toolUse) ||
397
+ (result ? chunks.turn.includes(result) : false);
398
+ const pendingToolUse = pendingToolUseEvents.get(toolUseID);
399
+ if (completedChildRunIds.has(toolUseID) &&
400
+ pendingToolUse == null &&
401
+ !isCurrentTurnTool) {
402
+ continue;
403
+ }
404
+ // The model requested a tool but execution is blocked on user confirmation
405
+ // or an external custom-tool result. Do not create a tool child yet; the
406
+ // execution belongs to the later turn that receives the result.
407
+ if (result == null) {
408
+ if (chunks.turn.includes(toolUse) &&
409
+ !completedChildRunIds.has(toolUseID)) {
410
+ pendingToolUseEvents.set(toolUseID, toolUse);
411
+ }
412
+ continue;
413
+ }
414
+ if (!isCurrentTurnTool && pendingToolUse == null) {
415
+ continue;
416
+ }
417
+ const toolUseForRun = pendingToolUse ?? toolUse;
418
+ const toolName = typeof toolUseForRun.name === "string"
419
+ ? toolUseForRun.name
420
+ : "ManagedAgentTool";
421
+ const startTime = pendingToolUse != null
422
+ ? (getProcessedAtMillis(result) ?? Date.now())
423
+ : (getProcessedAtMillis(toolUseForRun) ?? Date.now());
424
+ const index = pendingToolUse != null
425
+ ? chunks.all.indexOf(result)
426
+ : chunks.all.indexOf(toolUseForRun);
427
+ childSpecs.push({
428
+ startTime,
429
+ index,
430
+ createAndPost: async () => {
431
+ const resultArgs = [
432
+ { event: result, content: result.content },
433
+ result.is_error
434
+ ? (getManagedAgentText(result.content) ?? "Tool execution failed")
435
+ : undefined,
436
+ getProcessedAtMillis(result),
437
+ ];
438
+ const childRun = parentRun.createChild({
439
+ name: toolName,
440
+ run_type: "tool",
441
+ inputs: {
442
+ id: toolUseID,
443
+ name: toolUseForRun.name,
444
+ input: toolUseForRun.input,
445
+ event: toolUseForRun,
446
+ },
447
+ metadata,
448
+ start_time: startTime,
449
+ });
450
+ await childRun.end(...resultArgs);
451
+ await childRun.postRun();
452
+ pendingToolUseEvents.delete(toolUseID);
453
+ completedChildRunIds.add(toolUseID);
454
+ },
455
+ });
456
+ }
457
+ childSpecs.sort((left, right) => left.startTime - right.startTime || left.index - right.index);
458
+ for (const childSpec of childSpecs) {
459
+ await childSpec.createAndPost();
460
+ }
461
+ }
462
+ function wrapManagedAgentSessionEvents({ originalBeta, tracedBeta, cleanedOptions, prepopulatedInvocationParams, }) {
463
+ const createManagedAgentStreamRun = (sessionID, params, requestOptions, startTime) => {
464
+ const runtimeConfig = requestOptions?.langsmithExtra ?? {};
465
+ const parentRun = (0, traceable_js_1.getCurrentRunTree)(true);
466
+ const runConfig = {
467
+ ...cleanedOptions,
468
+ ...runtimeConfig,
469
+ name: runtimeConfig.name ?? cleanedOptions.name ?? "ClaudeManagedAgent",
470
+ run_type: "chain",
471
+ inputs: { session_id: sessionID },
472
+ ...(startTime ? { start_time: startTime } : {}),
473
+ tags: [
474
+ ...new Set([
475
+ ...(cleanedOptions.tags ?? []),
476
+ ...(runtimeConfig.tags ?? []),
477
+ ]),
478
+ ],
479
+ metadata: {
480
+ ...cleanedOptions.metadata,
481
+ ...runtimeConfig.metadata,
482
+ ls_provider: "anthropic",
483
+ ls_model_type: "chat",
484
+ thread_id: sessionID,
485
+ ls_invocation_params: {
486
+ ...(typeof prepopulatedInvocationParams === "object" &&
487
+ prepopulatedInvocationParams != null
488
+ ? prepopulatedInvocationParams
489
+ : {}),
490
+ session_id: sessionID,
491
+ ...(params ?? {}),
492
+ },
493
+ },
494
+ };
495
+ return parentRun
496
+ ? parentRun.createChild(runConfig)
497
+ : new run_trees_js_1.RunTree(runConfig);
498
+ };
499
+ // Wrap Claude Managed Agents session event methods if they exist.
500
+ if (originalBeta.sessions?.events) {
501
+ tracedBeta.sessions = Object.create(Object.getPrototypeOf(tracedBeta.sessions));
502
+ Object.assign(tracedBeta.sessions, originalBeta.sessions);
503
+ tracedBeta.sessions.events = Object.create(Object.getPrototypeOf(tracedBeta.sessions.events));
504
+ Object.assign(tracedBeta.sessions.events, originalBeta.sessions.events);
505
+ if (typeof originalBeta.sessions.events.stream === "function") {
506
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
507
+ const streamManagedAgentEvents = async function (...args) {
508
+ const [sessionID, params, requestOptions] = args;
509
+ const sanitizedArgs = [...args];
510
+ sanitizedArgs[2] = stripLangSmithExtraFromRequestOptions(sanitizedArgs[2]);
511
+ while (sanitizedArgs.length > 1 &&
512
+ sanitizedArgs[sanitizedArgs.length - 1] === undefined) {
513
+ sanitizedArgs.pop();
514
+ }
515
+ const sessionPromise = originalBeta.sessions?.retrieve
516
+ ? originalBeta.sessions.retrieve
517
+ .bind(originalBeta.sessions)(sessionID)
518
+ .catch(() => undefined)
519
+ : Promise.resolve(undefined);
520
+ const stream = await originalBeta.sessions?.events?.stream.bind(originalBeta.sessions.events)(...sanitizedArgs);
521
+ const iterator = stream[Symbol.asyncIterator]();
522
+ const allChunks = [];
523
+ const turnChunkLengths = new Set();
524
+ const pendingToolUseEvents = new Map();
525
+ const completedChildRunIds = new Set();
526
+ let flushLength = 0;
527
+ let observedTerminalEvent = false;
528
+ const finalize = async (kind, userError) => {
529
+ const chunks = allChunks.slice(flushLength);
530
+ flushLength = allChunks.length;
531
+ if (chunks.length > 0)
532
+ turnChunkLengths.add(flushLength);
533
+ // Question: should we re-attempt to fetch when finalizing again?
534
+ // ie if the agent's system prompt has changed mid-stream
535
+ const session = await sessionPromise;
536
+ const modelConfig = (0, types_js_1.isRecord)(session?.agent?.model)
537
+ ? session.agent.model
538
+ : undefined;
539
+ const systemPrompt = session?.agent.system ?? undefined;
540
+ if (chunks.length > 0) {
541
+ const turnStartTime = getFirstProcessedAtMillis(chunks) ?? Date.now();
542
+ const rawTurnEndTime = getLastProcessedAtMillis(chunks);
543
+ const turnEndTime = rawTurnEndTime !== undefined && rawTurnEndTime >= turnStartTime
544
+ ? rawTurnEndTime
545
+ : turnStartTime;
546
+ const runTree = createManagedAgentStreamRun(sessionID, params, requestOptions, turnStartTime);
547
+ const inputEvents = getManagedAgentInputEvents(chunks);
548
+ runTree.inputs = {
549
+ ...processManagedAgentStreamInputs({
550
+ args: [sessionID, params, sanitizedArgs[2]],
551
+ }),
552
+ ...(inputEvents.length > 0
553
+ ? {
554
+ events: inputEvents,
555
+ messages: getManagedAgentChatMessages(inputEvents),
556
+ }
557
+ : {}),
558
+ };
559
+ const turnError = userError ??
560
+ getManagedAgentStreamError(chunks) ??
561
+ getManagedAgentTurnError(chunks);
562
+ await runTree.end(managedAgentSessionEventsAggregator(chunks), turnError, turnEndTime);
563
+ await runTree.postRun();
564
+ await createManagedAgentChildRuns(runTree, { turn: chunks, all: allChunks }, runTree.extra.metadata ?? {}, {
565
+ modelConfig,
566
+ systemPrompt,
567
+ pendingToolUseEvents,
568
+ completedChildRunIds,
569
+ });
570
+ }
571
+ if (kind === "done" || kind === "throw") {
572
+ // Pending tool uses without results were never executed, so no tool
573
+ // child run was created. Clear them when the stream ends.
574
+ pendingToolUseEvents.clear();
575
+ }
576
+ };
577
+ stream[Symbol.asyncIterator] = () => ({
578
+ async next() {
579
+ try {
580
+ const result = await iterator.next();
581
+ if (result.done) {
582
+ await finalize("done");
583
+ return result;
584
+ }
585
+ allChunks.push(result.value);
586
+ if (result.value.type === "session.status_idle" ||
587
+ result.value.type === "session.status_terminated" ||
588
+ result.value.type === "session.deleted" ||
589
+ result.value.type === "session.error") {
590
+ if (!isCustomToolRequiresActionIdle(result.value, allChunks)) {
591
+ observedTerminalEvent = true;
592
+ await finalize("flush");
593
+ }
594
+ }
595
+ return result;
596
+ }
597
+ catch (error) {
598
+ await finalize("throw", String(error));
599
+ throw error;
600
+ }
601
+ },
602
+ async return(value) {
603
+ if (allChunks.length) {
604
+ await iterator.return?.(value);
605
+ if (observedTerminalEvent) {
606
+ await finalize("done");
607
+ }
608
+ else {
609
+ await finalize("throw", "Cancelled");
610
+ }
611
+ }
612
+ else {
613
+ await iterator.return?.(value);
614
+ }
615
+ return { done: true, value };
616
+ },
617
+ async throw(error) {
618
+ await finalize("throw", String(error));
619
+ if (iterator.throw)
620
+ return iterator.throw(error);
621
+ throw error;
622
+ },
623
+ });
624
+ return stream;
625
+ };
626
+ Object.defineProperty(streamManagedAgentEvents, "langsmith:traceable", {
627
+ value: { name: "ClaudeManagedAgent", run_type: "chain" },
628
+ });
629
+ tracedBeta.sessions.events.stream = streamManagedAgentEvents;
630
+ }
631
+ if (typeof originalBeta.sessions.events.send === "function") {
632
+ // Do not trace `send` as a separate run. The API returns the submitted
633
+ // user events, which makes the run output look like a duplicate of the
634
+ // input. Instead, annotate the active stream run for the same session.
635
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
636
+ tracedBeta.sessions.events.send = function sendManagedAgentEvents(...args) {
637
+ const sanitizedArgs = [...args];
638
+ if (typeof sanitizedArgs[2] === "object" &&
639
+ sanitizedArgs[2] != null &&
640
+ "langsmithExtra" in sanitizedArgs[2]) {
641
+ const { langsmithExtra: _langsmithExtra, ...rest } = sanitizedArgs[2];
642
+ sanitizedArgs[2] = rest;
643
+ }
644
+ return originalBeta.sessions?.events?.send.bind(originalBeta.sessions.events)(...sanitizedArgs);
645
+ };
646
+ }
647
+ }
648
+ }
@@ -0,0 +1,7 @@
1
+ import type { RunTreeConfig } from "../../index.js";
2
+ export declare function wrapManagedAgentSessionEvents({ originalBeta, tracedBeta, cleanedOptions, prepopulatedInvocationParams, }: {
3
+ originalBeta: any;
4
+ tracedBeta: any;
5
+ cleanedOptions: Partial<RunTreeConfig>;
6
+ prepopulatedInvocationParams: unknown;
7
+ }): void;