Skip to content

Commit b6485cc

Browse files
don't ship middleware transformer
1 parent 69f40c6 commit b6485cc

7 files changed

Lines changed: 8 additions & 320 deletions

File tree

libs/langchain-core/src/language_models/chat_models.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -353,7 +353,7 @@ export abstract class BaseChatModel<
353353
*
354354
* @example
355355
* ```ts
356-
* const stream = model.streamV2([{ role: "user", content: "Hello" }]);
356+
* const stream = model.streamEvents([{ role: "user", content: "Hello" }]);
357357
*
358358
* // Stream text
359359
* for await (const token of stream.text) {
@@ -364,7 +364,7 @@ export abstract class BaseChatModel<
364364
* const message = await stream;
365365
* ```
366366
*/
367-
streamV2(
367+
streamEvents(
368368
input: BaseLanguageModelInput,
369369
options?: Partial<CallOptions>
370370
): ChatModelStream {

libs/langchain/src/agents/ReactAgent.ts

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,6 @@ import {
5454
} from "./nodes/utils.js";
5555
import {
5656
createToolCallTransformer,
57-
createMiddlewareTransformer,
5857
type AgentRunStream,
5958
type InferStreamExtensions,
6059
} from "./stream.js";
@@ -674,7 +673,6 @@ export class ReactAgent<
674673
*/
675674
const compileTransformers = [
676675
createToolCallTransformer([]),
677-
createMiddlewareTransformer([]),
678676
/* user-defined stream transformers */
679677
...(this.options.streamTransformers ?? []),
680678
];
@@ -1376,7 +1374,6 @@ export class ReactAgent<
13761374
AgentRunStream<
13771375
MergedAgentState<Types>,
13781376
Types["Tools"],
1379-
Types["Middleware"],
13801377
InferStreamExtensions<Types["StreamTransformers"]>
13811378
>
13821379
>;
@@ -1446,7 +1443,6 @@ export class ReactAgent<
14461443
AgentRunStream<
14471444
MergedAgentState<Types>,
14481445
Types["Tools"],
1449-
Types["Middleware"],
14501446
InferStreamExtensions<Types["StreamTransformers"]>
14511447
>
14521448
>
@@ -1508,7 +1504,6 @@ export class ReactAgent<
15081504
})) as unknown as AgentRunStream<
15091505
FullState,
15101506
Types["Tools"],
1511-
Types["Middleware"],
15121507
InferStreamExtensions<Types["StreamTransformers"]>
15131508
>;
15141509
})();

libs/langchain/src/agents/index.ts

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -716,14 +716,5 @@ export { MIDDLEWARE_BRAND } from "./middleware/types.js";
716716
export type * from "./middleware/types.js";
717717
export { FakeToolCallingModel } from "./tests/utils.js";
718718
export type { ReactAgent } from "./ReactAgent.js";
719-
export {
720-
createToolCallTransformer,
721-
createMiddlewareTransformer,
722-
} from "./stream.js";
723-
export type {
724-
AgentRunStream,
725-
MiddlewarePhase,
726-
MiddlewareEvent,
727-
MiddlewareEventUnion,
728-
ToolCallStreamUnion,
729-
} from "./stream.js";
719+
export { createToolCallTransformer } from "./stream.js";
720+
export type { AgentRunStream, ToolCallStreamUnion } from "./stream.js";

libs/langchain/src/agents/stream.ts

Lines changed: 0 additions & 111 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ import {
2222
type ToolCallStream,
2323
type ToolCallStatus,
2424
type ToolsEventData,
25-
type UpdatesEventData,
2625
type Namespace,
2726
} from "@langchain/langgraph";
2827
import type {
@@ -31,10 +30,6 @@ import type {
3130
DynamicStructuredTool,
3231
StructuredToolInterface,
3332
} from "@langchain/core/tools";
34-
import type {
35-
AgentMiddleware,
36-
InferMiddlewareState,
37-
} from "./middleware/types.js";
3833

3934
/**
4035
* Infers the merged extensions shape from a tuple of stream transformer
@@ -92,46 +87,6 @@ export type ToolCallStreamUnion<
9287
>;
9388
}[number];
9489

95-
/**
96-
* Lifecycle phase that a middleware hook occupies within an agent turn.
97-
*/
98-
export type MiddlewarePhase =
99-
| "before_agent"
100-
| "before_model"
101-
| "after_model"
102-
| "after_agent";
103-
104-
/**
105-
* Represents a single middleware lifecycle event observed during an
106-
* agent run. Emitted by the middleware transformer.
107-
*
108-
* @typeParam TStateDelta - Shape of the state delta produced by this
109-
* middleware. Defaults to `Record<string, unknown>` when the
110-
* middleware tuple is not typed.
111-
*/
112-
export interface MiddlewareEvent<TStateDelta = Record<string, unknown>> {
113-
phase: MiddlewarePhase;
114-
name: string;
115-
stateDelta: TStateDelta;
116-
timestamp: number;
117-
}
118-
119-
/**
120-
* Discriminated union of {@link MiddlewareEvent} variants, one per
121-
* middleware in `TMiddleware`. When the middleware array is typed,
122-
* `event.stateDelta` narrows to the middleware's inferred state type.
123-
*
124-
* Falls back to `MiddlewareEvent` (untyped) when the middleware array
125-
* is a plain `AgentMiddleware[]`.
126-
*/
127-
export type MiddlewareEventUnion<
128-
TMiddleware extends readonly AgentMiddleware[],
129-
> = {
130-
[K in keyof TMiddleware]: TMiddleware[K] extends AgentMiddleware
131-
? MiddlewareEvent<InferMiddlewareState<TMiddleware[K]>>
132-
: MiddlewareEvent;
133-
}[number];
134-
13590
/**
13691
* A {@link GraphRunStream} with native agent-level projections assigned
13792
* directly on the instance by `createGraphRunStream` (via `__native`
@@ -156,13 +111,10 @@ export type AgentRunStream<
156111
| ClientTool
157112
| ServerTool
158113
)[],
159-
TMiddleware extends readonly AgentMiddleware[] = readonly AgentMiddleware[],
160114
TExtensions extends Record<string, unknown> = Record<string, unknown>,
161115
> = GraphRunStream<TValues, TExtensions> & {
162116
/** Tool call streams from the native ToolCallTransformer. */
163117
toolCalls: AsyncIterable<ToolCallStreamUnion<TTools>>;
164-
/** Middleware lifecycle events from the native MiddlewareTransformer. */
165-
middleware: AsyncIterable<MiddlewareEventUnion<TMiddleware>>;
166118
};
167119

168120
interface ToolCallProjection {
@@ -371,66 +323,3 @@ export function createToolCallTransformer(
371323
};
372324
};
373325
}
374-
375-
interface MiddlewareProjection {
376-
middleware: AsyncIterable<MiddlewareEvent>;
377-
}
378-
379-
const MIDDLEWARE_NODE_PATTERN =
380-
/^(.+)\.(before_agent|before_model|after_model|after_agent)$/;
381-
382-
/**
383-
* Creates a native transformer that watches `updates` events from
384-
* middleware nodes and surfaces them as typed {@link MiddlewareEvent}
385-
* objects.
386-
*
387-
* Marked `__native: true` — projection key lands directly on the
388-
* `GraphRunStream` instance as `run.middleware`.
389-
*/
390-
export function createMiddlewareTransformer(
391-
path: Namespace
392-
): () => NativeStreamTransformer<MiddlewareProjection> {
393-
return () => {
394-
const middlewareLog = StreamChannel.local<MiddlewareEvent>();
395-
396-
return {
397-
__native: true as const,
398-
399-
init: () => ({
400-
middleware: middlewareLog,
401-
}),
402-
403-
process(event: ProtocolEvent): boolean {
404-
if (event.method !== "updates") return true;
405-
if (!isOwnEvent(event.params.namespace, path)) return true;
406-
407-
const data = event.params.data as UpdatesEventData;
408-
const nodeName = data.node ?? event.params.node;
409-
if (!nodeName) return true;
410-
411-
const match = MIDDLEWARE_NODE_PATTERN.exec(nodeName);
412-
if (!match) return true;
413-
414-
const name = match[1];
415-
const phase = match[2] as MiddlewarePhase;
416-
417-
middlewareLog.push({
418-
phase,
419-
name,
420-
stateDelta: data.values ?? {},
421-
timestamp: event.params.timestamp,
422-
});
423-
424-
return true;
425-
},
426-
427-
finalize(): void {
428-
middlewareLog.close();
429-
},
430-
431-
fail(err: unknown): void {
432-
middlewareLog.fail(err);
433-
},
434-
};
435-
};
436-
}

libs/langchain/src/agents/tests/stream.int.test.ts

Lines changed: 2 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import { tool } from "@langchain/core/tools";
1414
import { AIMessage } from "@langchain/core/messages";
1515
import { Client } from "@langchain/langgraph-sdk";
1616

17-
import { createMiddleware, createAgent } from "../index.js";
17+
import { createAgent } from "../index.js";
1818

1919
const threads: ThreadSaver = (() => {
2020
const THREADS: Record<
@@ -55,24 +55,6 @@ const minusTool = tool(
5555
schema: z.object({ a: z.number(), b: z.number() }),
5656
}
5757
);
58-
const middlewareA = createMiddleware({
59-
name: "trackerA",
60-
stateSchema: z.object({
61-
trackerState: z.string().default("init"),
62-
}),
63-
beforeModel: () => ({ trackerState: "before", before: true }),
64-
afterModel: () => ({ trackerState: "after", after: true }),
65-
});
66-
67-
const middlewareB = createMiddleware({
68-
name: "trackerB",
69-
stateSchema: z.object({
70-
trackerState: z.string().default("init"),
71-
}),
72-
wrapModelCall: async (request, handler) => {
73-
return await handler(request);
74-
},
75-
});
7658

7759
const model = fakeModel()
7860
.respondWithTools([
@@ -84,7 +66,6 @@ const model = fakeModel()
8466
const agent = createAgent({
8567
model,
8668
tools: [addTool, minusTool],
87-
middleware: [middlewareA, middlewareB],
8869
// oxlint-disable-next-line typescript/no-explicit-any
8970
}) as unknown as Pregel<any, any, any, any, any>;
9071

@@ -151,7 +132,7 @@ async function collectAllEvents(
151132
beforeAll(setup);
152133

153134
describe("streamEvents", () => {
154-
it("should emit stream evebts for each tool and middleware invocation", async () => {
135+
it("should emit stream events for each tool invocation", async () => {
155136
console.log("url", url);
156137
const client = new Client({ apiUrl: url! });
157138

@@ -234,14 +215,10 @@ describe("streamEvents", () => {
234215
expect(updates.length).toBe(8);
235216
const updateNodes = updates.map(nodeOf);
236217
expect(updateNodes).toEqual([
237-
"trackerA.before_model",
238218
"model_request",
239-
"trackerA.after_model",
240219
"tools",
241220
"tools",
242-
"trackerA.before_model",
243221
"model_request",
244-
"trackerA.after_model",
245222
]);
246223

247224
// first model_request produced tool calls
@@ -269,10 +246,6 @@ describe("streamEvents", () => {
269246
tool_call_id: "call_2",
270247
});
271248

272-
// middleware state transitions are reflected
273-
expect(dataOf(updates[0]).trackerState).toBe("before");
274-
expect(dataOf(updates[2]).trackerState).toBe("after");
275-
276249
// --- values: 8 state snapshots ---
277250
const values = eventsByChannel.get("values") ?? [];
278251
expect(values.length).toBe(8);

libs/langchain/src/agents/tests/stream.test-d.ts

Lines changed: 1 addition & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { tool } from "@langchain/core/tools";
55
import { fakeModel } from "@langchain/core/testing";
66
import { StreamChannel, type StreamTransformer } from "@langchain/langgraph";
77

8-
import { createAgent, createMiddleware } from "../index.js";
8+
import { createAgent } from "../index.js";
99

1010
describe("streamEvents types", () => {
1111
it("should type tool calls as a discriminated union", async () => {
@@ -58,42 +58,6 @@ describe("streamEvents types", () => {
5858
}
5959
});
6060

61-
it("should type middleware events with inferred state delta", async () => {
62-
const model = fakeModel().respond(new AIMessage("ok"));
63-
64-
const tracker = createMiddleware({
65-
name: "tracker",
66-
stateSchema: z.object({
67-
trackerState: z.string().default("init"),
68-
}),
69-
beforeModel: () => ({ trackerState: "before" }),
70-
});
71-
72-
const agent = createAgent({
73-
model,
74-
tools: [],
75-
middleware: [tracker],
76-
});
77-
78-
const run = await agent.streamEvents(
79-
{
80-
messages: [new HumanMessage("hi")],
81-
},
82-
{ version: "v3" }
83-
);
84-
85-
for await (const event of run.middleware) {
86-
expectTypeOf(event.phase).toEqualTypeOf<
87-
"before_model" | "after_model" | "before_agent" | "after_agent"
88-
>();
89-
expectTypeOf(event.name).toEqualTypeOf<string>();
90-
expectTypeOf(event.stateDelta).toEqualTypeOf<{
91-
trackerState: string;
92-
}>();
93-
expectTypeOf(event.timestamp).toEqualTypeOf<number>();
94-
}
95-
});
96-
9761
it("should type run.extensions from streamTransformers registered at creation time", async () => {
9862
const model = fakeModel().respond(new AIMessage("ok"));
9963

0 commit comments

Comments
 (0)