@langchain/angular 1.0.9 → 1.0.11
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/stream-service.cjs +5 -2
- package/dist/stream-service.cjs.map +1 -1
- package/dist/stream-service.d.cts +3 -5
- package/dist/stream-service.d.cts.map +1 -1
- package/dist/stream-service.d.ts +3 -5
- package/dist/stream-service.d.ts.map +1 -1
- package/dist/stream-service.js +5 -2
- package/dist/stream-service.js.map +1 -1
- package/dist/use-stream.cjs +2 -1
- package/dist/use-stream.cjs.map +1 -1
- package/dist/use-stream.d.cts +64 -15
- package/dist/use-stream.d.cts.map +1 -1
- package/dist/use-stream.d.ts +64 -15
- package/dist/use-stream.d.ts.map +1 -1
- package/dist/use-stream.js +2 -1
- package/dist/use-stream.js.map +1 -1
- package/package.json +5 -5
package/dist/stream-service.cjs
CHANGED
|
@@ -64,8 +64,11 @@ let StreamService = class StreamService {
|
|
|
64
64
|
disconnect() {
|
|
65
65
|
return this.stream.disconnect();
|
|
66
66
|
}
|
|
67
|
-
respond(response,
|
|
68
|
-
return this.stream.respond(response,
|
|
67
|
+
respond(response, options) {
|
|
68
|
+
return this.stream.respond(response, options);
|
|
69
|
+
}
|
|
70
|
+
respondAll(responsesById, options) {
|
|
71
|
+
return this.stream.respondAll(responsesById, options);
|
|
69
72
|
}
|
|
70
73
|
getThread() {
|
|
71
74
|
return this.stream.getThread();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stream-service.cjs","names":["EnvironmentInjector","DestroyRef","useStream","STREAM_CONTROLLER"],"sources":["../src/stream-service.ts"],"sourcesContent":["import {\n DestroyRef,\n EnvironmentInjector,\n Injectable,\n inject,\n runInInjectionContext,\n type Signal,\n} from \"@angular/core\";\nimport type { BaseMessage } from \"@langchain/core/messages\";\nimport type { Client, Interrupt } from \"@langchain/langgraph-sdk\";\nimport type {\n AssembledToolCall,\n InferStateType,\n StreamStopOptions,\n StreamSubmitOptions,\n SubgraphDiscoverySnapshot,\n WidenUpdateMessages,\n} from \"@langchain/langgraph-sdk/stream\";\nimport type { ThreadStream } from \"@langchain/langgraph-sdk/client\";\nimport {\n useStream,\n STREAM_CONTROLLER,\n type StreamApi,\n type UseStreamOptions,\n type UseStreamReturn,\n} from \"./use-stream.js\";\n\n/**\n * `@Injectable()` wrapper around {@link useStream}. Extend this class\n * with your own service when you want a DI-scoped, shareable\n * {@link StreamApi}:\n *\n * ```ts\n * @Injectable({ providedIn: \"root\" })\n * export class ChatStream extends StreamService<ChatState> {\n * constructor() {\n * super({\n * transport: new HttpAgentServerAdapter({ apiUrl: \"/api/graph\" }),\n * assistantId: \"chat\",\n * });\n * }\n * }\n * ```\n *\n * The service exposes the same `StreamApi` surface as\n * `injectStream()` — read data via signals (`service.messages()`,\n * `service.isLoading()`) and use the imperative methods\n * (`service.submit(...)`, `service.stop()`).\n *\n * Must be instantiated inside an Angular injection context. Its\n * {@link DestroyRef} owns the controller lifetime, so scoping the\n * service to a component tears down the stream when the component\n * is destroyed.\n */\n@Injectable()\nexport class StreamService<\n T = Record<string, unknown>,\n InterruptType = unknown,\n ConfigurableType extends object = Record<string, unknown>,\n> {\n /** Underlying `StreamApi` returned by {@link useStream}. */\n readonly stream: UseStreamReturn<T, InterruptType, ConfigurableType>;\n\n constructor(options: UseStreamOptions<InferStateType<T>>) {\n const injector = inject(EnvironmentInjector);\n const destroyRef = inject(DestroyRef);\n this.stream = runInInjectionContext(injector, () =>\n useStream<T, InterruptType, ConfigurableType>(options, destroyRef)\n );\n }\n\n // ─── Reactive accessors (pass-through) ────────────────────────────\n\n get values(): UseStreamReturn<T, InterruptType, ConfigurableType>[\"values\"] {\n return this.stream.values;\n }\n\n get messages(): Signal<BaseMessage[]> {\n return this.stream.messages;\n }\n\n get toolCalls(): Signal<AssembledToolCall[]> {\n return this.stream.toolCalls;\n }\n\n get interrupts(): Signal<Interrupt<InterruptType>[]> {\n return this.stream.interrupts;\n }\n\n get interrupt(): Signal<Interrupt<InterruptType> | undefined> {\n return this.stream.interrupt;\n }\n\n get isLoading(): Signal<boolean> {\n return this.stream.isLoading;\n }\n\n get isThreadLoading(): Signal<boolean> {\n return this.stream.isThreadLoading;\n }\n\n get error(): Signal<unknown> {\n return this.stream.error;\n }\n\n get threadId(): Signal<string | null> {\n return this.stream.threadId;\n }\n\n get hydrationPromise(): Signal<Promise<void>> {\n return this.stream.hydrationPromise;\n }\n\n get subagents(): UseStreamReturn<\n T,\n InterruptType,\n ConfigurableType\n >[\"subagents\"] {\n return this.stream.subagents;\n }\n\n get subgraphs(): Signal<ReadonlyMap<string, SubgraphDiscoverySnapshot>> {\n return this.stream.subgraphs;\n }\n\n get subgraphsByNode(): Signal<\n ReadonlyMap<string, readonly SubgraphDiscoverySnapshot[]>\n > {\n return this.stream.subgraphsByNode;\n }\n\n // ─── Identity ─────────────────────────────────────────────────────\n\n get client(): Client {\n return this.stream.client;\n }\n\n get assistantId(): string {\n return this.stream.assistantId;\n }\n\n // ─── Imperatives ──────────────────────────────────────────────────\n\n submit(\n input: WidenUpdateMessages<Partial<InferStateType<T>>> | null | undefined,\n options?: StreamSubmitOptions<InferStateType<T>, ConfigurableType>\n ): Promise<void> {\n return this.stream.submit(\n input as Parameters<this[\"stream\"][\"submit\"]>[0],\n options as Parameters<this[\"stream\"][\"submit\"]>[1]\n );\n }\n\n stop(options?: StreamStopOptions): Promise<void> {\n return this.stream.stop(options);\n }\n\n disconnect(): Promise<void> {\n return this.stream.disconnect();\n }\n\n respond(\n response: unknown,\n
|
|
1
|
+
{"version":3,"file":"stream-service.cjs","names":["EnvironmentInjector","DestroyRef","useStream","STREAM_CONTROLLER"],"sources":["../src/stream-service.ts"],"sourcesContent":["import {\n DestroyRef,\n EnvironmentInjector,\n Injectable,\n inject,\n runInInjectionContext,\n type Signal,\n} from \"@angular/core\";\nimport type { BaseMessage } from \"@langchain/core/messages\";\nimport type { Client, Interrupt } from \"@langchain/langgraph-sdk\";\nimport type {\n AssembledToolCall,\n InferStateType,\n StreamRespondAllOptions,\n StreamRespondOptions,\n StreamStopOptions,\n StreamSubmitOptions,\n SubgraphDiscoverySnapshot,\n WidenUpdateMessages,\n} from \"@langchain/langgraph-sdk/stream\";\nimport type { ThreadStream } from \"@langchain/langgraph-sdk/client\";\nimport {\n useStream,\n STREAM_CONTROLLER,\n type StreamApi,\n type UseStreamOptions,\n type UseStreamReturn,\n} from \"./use-stream.js\";\n\n/**\n * `@Injectable()` wrapper around {@link useStream}. Extend this class\n * with your own service when you want a DI-scoped, shareable\n * {@link StreamApi}:\n *\n * ```ts\n * @Injectable({ providedIn: \"root\" })\n * export class ChatStream extends StreamService<ChatState> {\n * constructor() {\n * super({\n * transport: new HttpAgentServerAdapter({ apiUrl: \"/api/graph\" }),\n * assistantId: \"chat\",\n * });\n * }\n * }\n * ```\n *\n * The service exposes the same `StreamApi` surface as\n * `injectStream()` — read data via signals (`service.messages()`,\n * `service.isLoading()`) and use the imperative methods\n * (`service.submit(...)`, `service.stop()`).\n *\n * Must be instantiated inside an Angular injection context. Its\n * {@link DestroyRef} owns the controller lifetime, so scoping the\n * service to a component tears down the stream when the component\n * is destroyed.\n */\n@Injectable()\nexport class StreamService<\n T = Record<string, unknown>,\n InterruptType = unknown,\n ConfigurableType extends object = Record<string, unknown>,\n> {\n /** Underlying `StreamApi` returned by {@link useStream}. */\n readonly stream: UseStreamReturn<T, InterruptType, ConfigurableType>;\n\n constructor(options: UseStreamOptions<InferStateType<T>>) {\n const injector = inject(EnvironmentInjector);\n const destroyRef = inject(DestroyRef);\n this.stream = runInInjectionContext(injector, () =>\n useStream<T, InterruptType, ConfigurableType>(options, destroyRef)\n );\n }\n\n // ─── Reactive accessors (pass-through) ────────────────────────────\n\n get values(): UseStreamReturn<T, InterruptType, ConfigurableType>[\"values\"] {\n return this.stream.values;\n }\n\n get messages(): Signal<BaseMessage[]> {\n return this.stream.messages;\n }\n\n get toolCalls(): Signal<AssembledToolCall[]> {\n return this.stream.toolCalls;\n }\n\n get interrupts(): Signal<Interrupt<InterruptType>[]> {\n return this.stream.interrupts;\n }\n\n get interrupt(): Signal<Interrupt<InterruptType> | undefined> {\n return this.stream.interrupt;\n }\n\n get isLoading(): Signal<boolean> {\n return this.stream.isLoading;\n }\n\n get isThreadLoading(): Signal<boolean> {\n return this.stream.isThreadLoading;\n }\n\n get error(): Signal<unknown> {\n return this.stream.error;\n }\n\n get threadId(): Signal<string | null> {\n return this.stream.threadId;\n }\n\n get hydrationPromise(): Signal<Promise<void>> {\n return this.stream.hydrationPromise;\n }\n\n get subagents(): UseStreamReturn<\n T,\n InterruptType,\n ConfigurableType\n >[\"subagents\"] {\n return this.stream.subagents;\n }\n\n get subgraphs(): Signal<ReadonlyMap<string, SubgraphDiscoverySnapshot>> {\n return this.stream.subgraphs;\n }\n\n get subgraphsByNode(): Signal<\n ReadonlyMap<string, readonly SubgraphDiscoverySnapshot[]>\n > {\n return this.stream.subgraphsByNode;\n }\n\n // ─── Identity ─────────────────────────────────────────────────────\n\n get client(): Client {\n return this.stream.client;\n }\n\n get assistantId(): string {\n return this.stream.assistantId;\n }\n\n // ─── Imperatives ──────────────────────────────────────────────────\n\n submit(\n input: WidenUpdateMessages<Partial<InferStateType<T>>> | null | undefined,\n options?: StreamSubmitOptions<InferStateType<T>, ConfigurableType>\n ): Promise<void> {\n return this.stream.submit(\n input as Parameters<this[\"stream\"][\"submit\"]>[0],\n options as Parameters<this[\"stream\"][\"submit\"]>[1]\n );\n }\n\n stop(options?: StreamStopOptions): Promise<void> {\n return this.stream.stop(options);\n }\n\n disconnect(): Promise<void> {\n return this.stream.disconnect();\n }\n\n respond(\n response: unknown,\n options?: StreamRespondOptions<ConfigurableType>\n ): Promise<void> {\n return this.stream.respond(response, options);\n }\n\n respondAll(\n responsesById: Record<string, unknown>,\n options?: StreamRespondAllOptions<ConfigurableType>\n ): Promise<void> {\n return this.stream.respondAll(responsesById, options);\n }\n\n getThread(): ThreadStream | undefined {\n return this.stream.getThread();\n }\n\n /** @internal Lets selector primitives resolve the controller. */\n get [STREAM_CONTROLLER](): StreamApi<\n T,\n InterruptType,\n ConfigurableType\n >[typeof STREAM_CONTROLLER] {\n return this.stream[STREAM_CONTROLLER];\n }\n}\n"],"mappings":";;;;AAyDO,IAAA,gBAAA,MAAM,cAIX;;CAEA;CAEA,YAAY,SAA8C;EACxD,MAAM,YAAA,GAAA,cAAA,QAAkBA,cAAAA,oBAAoB;EAC5C,MAAM,cAAA,GAAA,cAAA,QAAoBC,cAAAA,WAAW;AACrC,OAAK,UAAA,GAAA,cAAA,uBAA+B,gBAClCC,mBAAAA,UAA8C,SAAS,WAAW,CACnE;;CAKH,IAAI,SAAwE;AAC1E,SAAO,KAAK,OAAO;;CAGrB,IAAI,WAAkC;AACpC,SAAO,KAAK,OAAO;;CAGrB,IAAI,YAAyC;AAC3C,SAAO,KAAK,OAAO;;CAGrB,IAAI,aAAiD;AACnD,SAAO,KAAK,OAAO;;CAGrB,IAAI,YAA0D;AAC5D,SAAO,KAAK,OAAO;;CAGrB,IAAI,YAA6B;AAC/B,SAAO,KAAK,OAAO;;CAGrB,IAAI,kBAAmC;AACrC,SAAO,KAAK,OAAO;;CAGrB,IAAI,QAAyB;AAC3B,SAAO,KAAK,OAAO;;CAGrB,IAAI,WAAkC;AACpC,SAAO,KAAK,OAAO;;CAGrB,IAAI,mBAA0C;AAC5C,SAAO,KAAK,OAAO;;CAGrB,IAAI,YAIW;AACb,SAAO,KAAK,OAAO;;CAGrB,IAAI,YAAoE;AACtE,SAAO,KAAK,OAAO;;CAGrB,IAAI,kBAEF;AACA,SAAO,KAAK,OAAO;;CAKrB,IAAI,SAAiB;AACnB,SAAO,KAAK,OAAO;;CAGrB,IAAI,cAAsB;AACxB,SAAO,KAAK,OAAO;;CAKrB,OACE,OACA,SACe;AACf,SAAO,KAAK,OAAO,OACjB,OACA,QACD;;CAGH,KAAK,SAA4C;AAC/C,SAAO,KAAK,OAAO,KAAK,QAAQ;;CAGlC,aAA4B;AAC1B,SAAO,KAAK,OAAO,YAAY;;CAGjC,QACE,UACA,SACe;AACf,SAAO,KAAK,OAAO,QAAQ,UAAU,QAAQ;;CAG/C,WACE,eACA,SACe;AACf,SAAO,KAAK,OAAO,WAAW,eAAe,QAAQ;;CAGvD,YAAsC;AACpC,SAAO,KAAK,OAAO,WAAW;;;CAIhC,KAAKC,mBAAAA,qBAIuB;AAC1B,SAAO,KAAK,OAAOA,mBAAAA;;;4EAnIV,CAAA,EAAA,cAAA"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { STREAM_CONTROLLER, StreamApi, UseStreamOptions as UseStreamOptions$1, UseStreamReturn } from "./use-stream.cjs";
|
|
2
|
-
import { AssembledToolCall, InferStateType, StreamStopOptions, StreamSubmitOptions, SubgraphDiscoverySnapshot, WidenUpdateMessages } from "@langchain/langgraph-sdk/stream";
|
|
2
|
+
import { AssembledToolCall, InferStateType, StreamRespondAllOptions, StreamRespondOptions, StreamStopOptions, StreamSubmitOptions, SubgraphDiscoverySnapshot, WidenUpdateMessages } from "@langchain/langgraph-sdk/stream";
|
|
3
3
|
import { Signal } from "@angular/core";
|
|
4
4
|
import { BaseMessage } from "@langchain/core/messages";
|
|
5
5
|
import { Client, Interrupt } from "@langchain/langgraph-sdk";
|
|
@@ -55,10 +55,8 @@ declare class StreamService<T = Record<string, unknown>, InterruptType = unknown
|
|
|
55
55
|
submit(input: WidenUpdateMessages<Partial<InferStateType<T>>> | null | undefined, options?: StreamSubmitOptions<InferStateType<T>, ConfigurableType>): Promise<void>;
|
|
56
56
|
stop(options?: StreamStopOptions): Promise<void>;
|
|
57
57
|
disconnect(): Promise<void>;
|
|
58
|
-
respond(response: unknown,
|
|
59
|
-
|
|
60
|
-
namespace?: string[];
|
|
61
|
-
}): Promise<void>;
|
|
58
|
+
respond(response: unknown, options?: StreamRespondOptions<ConfigurableType>): Promise<void>;
|
|
59
|
+
respondAll(responsesById: Record<string, unknown>, options?: StreamRespondAllOptions<ConfigurableType>): Promise<void>;
|
|
62
60
|
getThread(): ThreadStream | undefined;
|
|
63
61
|
/** @internal Lets selector primitives resolve the controller. */
|
|
64
62
|
get [STREAM_CONTROLLER](): StreamApi<T, InterruptType, ConfigurableType>[typeof STREAM_CONTROLLER];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stream-service.d.cts","names":[],"sources":["../src/stream-service.ts"],"mappings":";;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"stream-service.d.cts","names":[],"sources":["../src/stream-service.ts"],"mappings":";;;;;;;;;;AAwDA;;;;;;;;;;;;;;;;;;;;;;;;;cACa,aAAA,KACP,MAAA,8EAE8B,MAAA;EAmCjB;EAAA,SAhCR,MAAA,EAAQ,eAAA,CAAgB,CAAA,EAAG,aAAA,EAAe,gBAAA;EAEnD,WAAA,CAAY,OAAA,EAAS,kBAAA,CAAiB,cAAA,CAAe,CAAA;EAAA,IAUjD,MAAA,CAAA,GAAU,eAAA,CAAgB,CAAA,EAAG,aAAA,EAAe,gBAAA;EAAA,IAI5C,QAAA,CAAA,GAAY,MAAA,CAAO,WAAA;EAAA,IAInB,SAAA,CAAA,GAAa,MAAA,CAAO,iBAAA;EAAA,IAIpB,UAAA,CAAA,GAAc,MAAA,CAAO,SAAA,CAAU,aAAA;EAAA,IAI/B,SAAA,CAAA,GAAa,MAAA,CAAO,SAAA,CAAU,aAAA;EAAA,IAI9B,SAAA,CAAA,GAAa,MAAA;EAAA,IAIb,eAAA,CAAA,GAAmB,MAAA;EAAA,IAInB,KAAA,CAAA,GAAS,MAAA;EAAA,IAIT,QAAA,CAAA,GAAY,MAAA;EAAA,IAIZ,gBAAA,CAAA,GAAoB,MAAA,CAAO,OAAA;EAAA,IAI3B,SAAA,CAAA,GAAa,eAAA,CACf,CAAA,EACA,aAAA,EACA,gBAAA;EAAA,IAKE,SAAA,CAAA,GAAa,MAAA,CAAO,WAAA,SAAoB,yBAAA;EAAA,IAIxC,eAAA,CAAA,GAAmB,MAAA,CACrB,WAAA,kBAA6B,yBAAA;EAAA,IAO3B,MAAA,CAAA,GAAU,MAAA;EAAA,IAIV,WAAA,CAAA;EAMJ,MAAA,CACE,KAAA,EAAO,mBAAA,CAAoB,OAAA,CAAQ,cAAA,CAAe,CAAA,wBAClD,OAAA,GAAU,mBAAA,CAAoB,cAAA,CAAe,CAAA,GAAI,gBAAA,IAChD,OAAA;EAOH,IAAA,CAAK,OAAA,GAAU,iBAAA,GAAoB,OAAA;EAInC,UAAA,CAAA,GAAc,OAAA;EAId,OAAA,CACE,QAAA,WACA,OAAA,GAAU,oBAAA,CAAqB,gBAAA,IAC9B,OAAA;EAIH,UAAA,CACE,aAAA,EAAe,MAAA,mBACf,OAAA,GAAU,uBAAA,CAAwB,gBAAA,IACjC,OAAA;EAIH,SAAA,CAAA,GAAa,YAAA;EA9BD;EAAA,KAmCP,iBAAA,KAAsB,SAAA,CACzB,CAAA,EACA,aAAA,EACA,gBAAA,SACO,iBAAA;AAAA"}
|
package/dist/stream-service.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ import { STREAM_CONTROLLER, StreamApi, UseStreamOptions as UseStreamOptions$1, U
|
|
|
2
2
|
import { Signal } from "@angular/core";
|
|
3
3
|
import { Client, Interrupt } from "@langchain/langgraph-sdk";
|
|
4
4
|
import { ThreadStream } from "@langchain/langgraph-sdk/client";
|
|
5
|
-
import { AssembledToolCall, InferStateType, StreamStopOptions, StreamSubmitOptions, SubgraphDiscoverySnapshot, WidenUpdateMessages } from "@langchain/langgraph-sdk/stream";
|
|
5
|
+
import { AssembledToolCall, InferStateType, StreamRespondAllOptions, StreamRespondOptions, StreamStopOptions, StreamSubmitOptions, SubgraphDiscoverySnapshot, WidenUpdateMessages } from "@langchain/langgraph-sdk/stream";
|
|
6
6
|
import { BaseMessage } from "@langchain/core/messages";
|
|
7
7
|
|
|
8
8
|
//#region src/stream-service.d.ts
|
|
@@ -55,10 +55,8 @@ declare class StreamService<T = Record<string, unknown>, InterruptType = unknown
|
|
|
55
55
|
submit(input: WidenUpdateMessages<Partial<InferStateType<T>>> | null | undefined, options?: StreamSubmitOptions<InferStateType<T>, ConfigurableType>): Promise<void>;
|
|
56
56
|
stop(options?: StreamStopOptions): Promise<void>;
|
|
57
57
|
disconnect(): Promise<void>;
|
|
58
|
-
respond(response: unknown,
|
|
59
|
-
|
|
60
|
-
namespace?: string[];
|
|
61
|
-
}): Promise<void>;
|
|
58
|
+
respond(response: unknown, options?: StreamRespondOptions<ConfigurableType>): Promise<void>;
|
|
59
|
+
respondAll(responsesById: Record<string, unknown>, options?: StreamRespondAllOptions<ConfigurableType>): Promise<void>;
|
|
62
60
|
getThread(): ThreadStream | undefined;
|
|
63
61
|
/** @internal Lets selector primitives resolve the controller. */
|
|
64
62
|
get [STREAM_CONTROLLER](): StreamApi<T, InterruptType, ConfigurableType>[typeof STREAM_CONTROLLER];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stream-service.d.ts","names":[],"sources":["../src/stream-service.ts"],"mappings":";;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"stream-service.d.ts","names":[],"sources":["../src/stream-service.ts"],"mappings":";;;;;;;;;;AAwDA;;;;;;;;;;;;;;;;;;;;;;;;;cACa,aAAA,KACP,MAAA,8EAE8B,MAAA;EAmCjB;EAAA,SAhCR,MAAA,EAAQ,eAAA,CAAgB,CAAA,EAAG,aAAA,EAAe,gBAAA;EAEnD,WAAA,CAAY,OAAA,EAAS,kBAAA,CAAiB,cAAA,CAAe,CAAA;EAAA,IAUjD,MAAA,CAAA,GAAU,eAAA,CAAgB,CAAA,EAAG,aAAA,EAAe,gBAAA;EAAA,IAI5C,QAAA,CAAA,GAAY,MAAA,CAAO,WAAA;EAAA,IAInB,SAAA,CAAA,GAAa,MAAA,CAAO,iBAAA;EAAA,IAIpB,UAAA,CAAA,GAAc,MAAA,CAAO,SAAA,CAAU,aAAA;EAAA,IAI/B,SAAA,CAAA,GAAa,MAAA,CAAO,SAAA,CAAU,aAAA;EAAA,IAI9B,SAAA,CAAA,GAAa,MAAA;EAAA,IAIb,eAAA,CAAA,GAAmB,MAAA;EAAA,IAInB,KAAA,CAAA,GAAS,MAAA;EAAA,IAIT,QAAA,CAAA,GAAY,MAAA;EAAA,IAIZ,gBAAA,CAAA,GAAoB,MAAA,CAAO,OAAA;EAAA,IAI3B,SAAA,CAAA,GAAa,eAAA,CACf,CAAA,EACA,aAAA,EACA,gBAAA;EAAA,IAKE,SAAA,CAAA,GAAa,MAAA,CAAO,WAAA,SAAoB,yBAAA;EAAA,IAIxC,eAAA,CAAA,GAAmB,MAAA,CACrB,WAAA,kBAA6B,yBAAA;EAAA,IAO3B,MAAA,CAAA,GAAU,MAAA;EAAA,IAIV,WAAA,CAAA;EAMJ,MAAA,CACE,KAAA,EAAO,mBAAA,CAAoB,OAAA,CAAQ,cAAA,CAAe,CAAA,wBAClD,OAAA,GAAU,mBAAA,CAAoB,cAAA,CAAe,CAAA,GAAI,gBAAA,IAChD,OAAA;EAOH,IAAA,CAAK,OAAA,GAAU,iBAAA,GAAoB,OAAA;EAInC,UAAA,CAAA,GAAc,OAAA;EAId,OAAA,CACE,QAAA,WACA,OAAA,GAAU,oBAAA,CAAqB,gBAAA,IAC9B,OAAA;EAIH,UAAA,CACE,aAAA,EAAe,MAAA,mBACf,OAAA,GAAU,uBAAA,CAAwB,gBAAA,IACjC,OAAA;EAIH,SAAA,CAAA,GAAa,YAAA;EA9BD;EAAA,KAmCP,iBAAA,KAAsB,SAAA,CACzB,CAAA,EACA,aAAA,EACA,gBAAA,SACO,iBAAA;AAAA"}
|
package/dist/stream-service.js
CHANGED
|
@@ -64,8 +64,11 @@ let StreamService = class StreamService {
|
|
|
64
64
|
disconnect() {
|
|
65
65
|
return this.stream.disconnect();
|
|
66
66
|
}
|
|
67
|
-
respond(response,
|
|
68
|
-
return this.stream.respond(response,
|
|
67
|
+
respond(response, options) {
|
|
68
|
+
return this.stream.respond(response, options);
|
|
69
|
+
}
|
|
70
|
+
respondAll(responsesById, options) {
|
|
71
|
+
return this.stream.respondAll(responsesById, options);
|
|
69
72
|
}
|
|
70
73
|
getThread() {
|
|
71
74
|
return this.stream.getThread();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stream-service.js","names":[],"sources":["../src/stream-service.ts"],"sourcesContent":["import {\n DestroyRef,\n EnvironmentInjector,\n Injectable,\n inject,\n runInInjectionContext,\n type Signal,\n} from \"@angular/core\";\nimport type { BaseMessage } from \"@langchain/core/messages\";\nimport type { Client, Interrupt } from \"@langchain/langgraph-sdk\";\nimport type {\n AssembledToolCall,\n InferStateType,\n StreamStopOptions,\n StreamSubmitOptions,\n SubgraphDiscoverySnapshot,\n WidenUpdateMessages,\n} from \"@langchain/langgraph-sdk/stream\";\nimport type { ThreadStream } from \"@langchain/langgraph-sdk/client\";\nimport {\n useStream,\n STREAM_CONTROLLER,\n type StreamApi,\n type UseStreamOptions,\n type UseStreamReturn,\n} from \"./use-stream.js\";\n\n/**\n * `@Injectable()` wrapper around {@link useStream}. Extend this class\n * with your own service when you want a DI-scoped, shareable\n * {@link StreamApi}:\n *\n * ```ts\n * @Injectable({ providedIn: \"root\" })\n * export class ChatStream extends StreamService<ChatState> {\n * constructor() {\n * super({\n * transport: new HttpAgentServerAdapter({ apiUrl: \"/api/graph\" }),\n * assistantId: \"chat\",\n * });\n * }\n * }\n * ```\n *\n * The service exposes the same `StreamApi` surface as\n * `injectStream()` — read data via signals (`service.messages()`,\n * `service.isLoading()`) and use the imperative methods\n * (`service.submit(...)`, `service.stop()`).\n *\n * Must be instantiated inside an Angular injection context. Its\n * {@link DestroyRef} owns the controller lifetime, so scoping the\n * service to a component tears down the stream when the component\n * is destroyed.\n */\n@Injectable()\nexport class StreamService<\n T = Record<string, unknown>,\n InterruptType = unknown,\n ConfigurableType extends object = Record<string, unknown>,\n> {\n /** Underlying `StreamApi` returned by {@link useStream}. */\n readonly stream: UseStreamReturn<T, InterruptType, ConfigurableType>;\n\n constructor(options: UseStreamOptions<InferStateType<T>>) {\n const injector = inject(EnvironmentInjector);\n const destroyRef = inject(DestroyRef);\n this.stream = runInInjectionContext(injector, () =>\n useStream<T, InterruptType, ConfigurableType>(options, destroyRef)\n );\n }\n\n // ─── Reactive accessors (pass-through) ────────────────────────────\n\n get values(): UseStreamReturn<T, InterruptType, ConfigurableType>[\"values\"] {\n return this.stream.values;\n }\n\n get messages(): Signal<BaseMessage[]> {\n return this.stream.messages;\n }\n\n get toolCalls(): Signal<AssembledToolCall[]> {\n return this.stream.toolCalls;\n }\n\n get interrupts(): Signal<Interrupt<InterruptType>[]> {\n return this.stream.interrupts;\n }\n\n get interrupt(): Signal<Interrupt<InterruptType> | undefined> {\n return this.stream.interrupt;\n }\n\n get isLoading(): Signal<boolean> {\n return this.stream.isLoading;\n }\n\n get isThreadLoading(): Signal<boolean> {\n return this.stream.isThreadLoading;\n }\n\n get error(): Signal<unknown> {\n return this.stream.error;\n }\n\n get threadId(): Signal<string | null> {\n return this.stream.threadId;\n }\n\n get hydrationPromise(): Signal<Promise<void>> {\n return this.stream.hydrationPromise;\n }\n\n get subagents(): UseStreamReturn<\n T,\n InterruptType,\n ConfigurableType\n >[\"subagents\"] {\n return this.stream.subagents;\n }\n\n get subgraphs(): Signal<ReadonlyMap<string, SubgraphDiscoverySnapshot>> {\n return this.stream.subgraphs;\n }\n\n get subgraphsByNode(): Signal<\n ReadonlyMap<string, readonly SubgraphDiscoverySnapshot[]>\n > {\n return this.stream.subgraphsByNode;\n }\n\n // ─── Identity ─────────────────────────────────────────────────────\n\n get client(): Client {\n return this.stream.client;\n }\n\n get assistantId(): string {\n return this.stream.assistantId;\n }\n\n // ─── Imperatives ──────────────────────────────────────────────────\n\n submit(\n input: WidenUpdateMessages<Partial<InferStateType<T>>> | null | undefined,\n options?: StreamSubmitOptions<InferStateType<T>, ConfigurableType>\n ): Promise<void> {\n return this.stream.submit(\n input as Parameters<this[\"stream\"][\"submit\"]>[0],\n options as Parameters<this[\"stream\"][\"submit\"]>[1]\n );\n }\n\n stop(options?: StreamStopOptions): Promise<void> {\n return this.stream.stop(options);\n }\n\n disconnect(): Promise<void> {\n return this.stream.disconnect();\n }\n\n respond(\n response: unknown,\n
|
|
1
|
+
{"version":3,"file":"stream-service.js","names":[],"sources":["../src/stream-service.ts"],"sourcesContent":["import {\n DestroyRef,\n EnvironmentInjector,\n Injectable,\n inject,\n runInInjectionContext,\n type Signal,\n} from \"@angular/core\";\nimport type { BaseMessage } from \"@langchain/core/messages\";\nimport type { Client, Interrupt } from \"@langchain/langgraph-sdk\";\nimport type {\n AssembledToolCall,\n InferStateType,\n StreamRespondAllOptions,\n StreamRespondOptions,\n StreamStopOptions,\n StreamSubmitOptions,\n SubgraphDiscoverySnapshot,\n WidenUpdateMessages,\n} from \"@langchain/langgraph-sdk/stream\";\nimport type { ThreadStream } from \"@langchain/langgraph-sdk/client\";\nimport {\n useStream,\n STREAM_CONTROLLER,\n type StreamApi,\n type UseStreamOptions,\n type UseStreamReturn,\n} from \"./use-stream.js\";\n\n/**\n * `@Injectable()` wrapper around {@link useStream}. Extend this class\n * with your own service when you want a DI-scoped, shareable\n * {@link StreamApi}:\n *\n * ```ts\n * @Injectable({ providedIn: \"root\" })\n * export class ChatStream extends StreamService<ChatState> {\n * constructor() {\n * super({\n * transport: new HttpAgentServerAdapter({ apiUrl: \"/api/graph\" }),\n * assistantId: \"chat\",\n * });\n * }\n * }\n * ```\n *\n * The service exposes the same `StreamApi` surface as\n * `injectStream()` — read data via signals (`service.messages()`,\n * `service.isLoading()`) and use the imperative methods\n * (`service.submit(...)`, `service.stop()`).\n *\n * Must be instantiated inside an Angular injection context. Its\n * {@link DestroyRef} owns the controller lifetime, so scoping the\n * service to a component tears down the stream when the component\n * is destroyed.\n */\n@Injectable()\nexport class StreamService<\n T = Record<string, unknown>,\n InterruptType = unknown,\n ConfigurableType extends object = Record<string, unknown>,\n> {\n /** Underlying `StreamApi` returned by {@link useStream}. */\n readonly stream: UseStreamReturn<T, InterruptType, ConfigurableType>;\n\n constructor(options: UseStreamOptions<InferStateType<T>>) {\n const injector = inject(EnvironmentInjector);\n const destroyRef = inject(DestroyRef);\n this.stream = runInInjectionContext(injector, () =>\n useStream<T, InterruptType, ConfigurableType>(options, destroyRef)\n );\n }\n\n // ─── Reactive accessors (pass-through) ────────────────────────────\n\n get values(): UseStreamReturn<T, InterruptType, ConfigurableType>[\"values\"] {\n return this.stream.values;\n }\n\n get messages(): Signal<BaseMessage[]> {\n return this.stream.messages;\n }\n\n get toolCalls(): Signal<AssembledToolCall[]> {\n return this.stream.toolCalls;\n }\n\n get interrupts(): Signal<Interrupt<InterruptType>[]> {\n return this.stream.interrupts;\n }\n\n get interrupt(): Signal<Interrupt<InterruptType> | undefined> {\n return this.stream.interrupt;\n }\n\n get isLoading(): Signal<boolean> {\n return this.stream.isLoading;\n }\n\n get isThreadLoading(): Signal<boolean> {\n return this.stream.isThreadLoading;\n }\n\n get error(): Signal<unknown> {\n return this.stream.error;\n }\n\n get threadId(): Signal<string | null> {\n return this.stream.threadId;\n }\n\n get hydrationPromise(): Signal<Promise<void>> {\n return this.stream.hydrationPromise;\n }\n\n get subagents(): UseStreamReturn<\n T,\n InterruptType,\n ConfigurableType\n >[\"subagents\"] {\n return this.stream.subagents;\n }\n\n get subgraphs(): Signal<ReadonlyMap<string, SubgraphDiscoverySnapshot>> {\n return this.stream.subgraphs;\n }\n\n get subgraphsByNode(): Signal<\n ReadonlyMap<string, readonly SubgraphDiscoverySnapshot[]>\n > {\n return this.stream.subgraphsByNode;\n }\n\n // ─── Identity ─────────────────────────────────────────────────────\n\n get client(): Client {\n return this.stream.client;\n }\n\n get assistantId(): string {\n return this.stream.assistantId;\n }\n\n // ─── Imperatives ──────────────────────────────────────────────────\n\n submit(\n input: WidenUpdateMessages<Partial<InferStateType<T>>> | null | undefined,\n options?: StreamSubmitOptions<InferStateType<T>, ConfigurableType>\n ): Promise<void> {\n return this.stream.submit(\n input as Parameters<this[\"stream\"][\"submit\"]>[0],\n options as Parameters<this[\"stream\"][\"submit\"]>[1]\n );\n }\n\n stop(options?: StreamStopOptions): Promise<void> {\n return this.stream.stop(options);\n }\n\n disconnect(): Promise<void> {\n return this.stream.disconnect();\n }\n\n respond(\n response: unknown,\n options?: StreamRespondOptions<ConfigurableType>\n ): Promise<void> {\n return this.stream.respond(response, options);\n }\n\n respondAll(\n responsesById: Record<string, unknown>,\n options?: StreamRespondAllOptions<ConfigurableType>\n ): Promise<void> {\n return this.stream.respondAll(responsesById, options);\n }\n\n getThread(): ThreadStream | undefined {\n return this.stream.getThread();\n }\n\n /** @internal Lets selector primitives resolve the controller. */\n get [STREAM_CONTROLLER](): StreamApi<\n T,\n InterruptType,\n ConfigurableType\n >[typeof STREAM_CONTROLLER] {\n return this.stream[STREAM_CONTROLLER];\n }\n}\n"],"mappings":";;;;AAyDO,IAAA,gBAAA,MAAM,cAIX;;CAEA;CAEA,YAAY,SAA8C;EACxD,MAAM,WAAW,OAAO,oBAAoB;EAC5C,MAAM,aAAa,OAAO,WAAW;AACrC,OAAK,SAAS,sBAAsB,gBAClC,UAA8C,SAAS,WAAW,CACnE;;CAKH,IAAI,SAAwE;AAC1E,SAAO,KAAK,OAAO;;CAGrB,IAAI,WAAkC;AACpC,SAAO,KAAK,OAAO;;CAGrB,IAAI,YAAyC;AAC3C,SAAO,KAAK,OAAO;;CAGrB,IAAI,aAAiD;AACnD,SAAO,KAAK,OAAO;;CAGrB,IAAI,YAA0D;AAC5D,SAAO,KAAK,OAAO;;CAGrB,IAAI,YAA6B;AAC/B,SAAO,KAAK,OAAO;;CAGrB,IAAI,kBAAmC;AACrC,SAAO,KAAK,OAAO;;CAGrB,IAAI,QAAyB;AAC3B,SAAO,KAAK,OAAO;;CAGrB,IAAI,WAAkC;AACpC,SAAO,KAAK,OAAO;;CAGrB,IAAI,mBAA0C;AAC5C,SAAO,KAAK,OAAO;;CAGrB,IAAI,YAIW;AACb,SAAO,KAAK,OAAO;;CAGrB,IAAI,YAAoE;AACtE,SAAO,KAAK,OAAO;;CAGrB,IAAI,kBAEF;AACA,SAAO,KAAK,OAAO;;CAKrB,IAAI,SAAiB;AACnB,SAAO,KAAK,OAAO;;CAGrB,IAAI,cAAsB;AACxB,SAAO,KAAK,OAAO;;CAKrB,OACE,OACA,SACe;AACf,SAAO,KAAK,OAAO,OACjB,OACA,QACD;;CAGH,KAAK,SAA4C;AAC/C,SAAO,KAAK,OAAO,KAAK,QAAQ;;CAGlC,aAA4B;AAC1B,SAAO,KAAK,OAAO,YAAY;;CAGjC,QACE,UACA,SACe;AACf,SAAO,KAAK,OAAO,QAAQ,UAAU,QAAQ;;CAG/C,WACE,eACA,SACe;AACf,SAAO,KAAK,OAAO,WAAW,eAAe,QAAQ;;CAGvD,YAAsC;AACpC,SAAO,KAAK,OAAO,WAAW;;;CAIhC,KAAK,qBAIuB;AAC1B,SAAO,KAAK,OAAO;;;4BAnItB,YAAY,CAAA,EAAA,cAAA"}
|
package/dist/use-stream.cjs
CHANGED
|
@@ -136,7 +136,8 @@ function useStream(options, destroyRef) {
|
|
|
136
136
|
submit: (input, submitOptions) => controller.submit(input, submitOptions),
|
|
137
137
|
stop: (options) => controller.stop(options),
|
|
138
138
|
disconnect: () => controller.disconnect(),
|
|
139
|
-
respond: (response,
|
|
139
|
+
respond: (response, options) => controller.respond(response, options),
|
|
140
|
+
respondAll: (responsesById, options) => controller.respondAll(responsesById, options),
|
|
140
141
|
getThread: () => controller.getThread(),
|
|
141
142
|
client,
|
|
142
143
|
assistantId,
|
package/dist/use-stream.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-stream.cjs","names":["ClientCtor","StreamController","DestroyRef"],"sources":["../src/use-stream.ts"],"sourcesContent":["import {\n DestroyRef,\n computed,\n effect,\n inject,\n isSignal,\n signal,\n untracked,\n type Signal,\n} from \"@angular/core\";\nimport type { BaseMessage } from \"@langchain/core/messages\";\nimport type { Client, Interrupt } from \"@langchain/langgraph-sdk\";\nimport {\n filterOutHeadlessToolInterrupts,\n flushPendingHeadlessToolInterrupts,\n scheduleCoalescedHeadlessToolFlush,\n type AnyHeadlessToolImplementation,\n type OnToolCallback,\n} from \"@langchain/langgraph-sdk\";\nimport {\n Client as ClientCtor,\n type ClientConfig,\n type ThreadStream,\n} from \"@langchain/langgraph-sdk/client\";\nimport {\n StreamController,\n type AgentServerAdapter,\n type AgentServerOptions as StreamAgentServerOptions,\n type ChannelRegistry,\n type CustomAdapterOptions as StreamCustomAdapterOptions,\n type InferStateType,\n type InferToolCalls,\n type InferSubagentStates,\n type RootSnapshot,\n type RunCompletedInfo,\n type RunExecutionInfo,\n type StreamStopOptions,\n type StreamSubmitOptions,\n type SubagentDiscoverySnapshot,\n type SubagentMap,\n type SubgraphByNodeMap,\n type SubgraphDiscoverySnapshot,\n type SubgraphMap,\n type UseStreamOptions as StreamUseStreamOptions,\n type WidenUpdateMessages,\n} from \"@langchain/langgraph-sdk/stream\";\n\ntype AngularThreadId = string | null | Signal<string | null | undefined>;\n\nexport type AgentServerOptions<StateType extends object> =\n StreamAgentServerOptions<StateType, AngularThreadId>;\n\nexport type CustomAdapterOptions<StateType extends object> =\n StreamCustomAdapterOptions<StateType, AngularThreadId, string>;\n\nexport type UseStreamOptions<\n StateType extends object = Record<string, unknown>,\n> = StreamUseStreamOptions<\n StateType,\n AngularThreadId,\n string | undefined,\n string | undefined,\n string\n>;\n\n/**\n * Private field on the handle that carries the\n * {@link StreamController} reference. Selector primitives read this\n * to reach the shared {@link ChannelRegistry}. Use the companion\n * `inject*` selectors (`injectMessages`, `injectToolCalls`,\n * `injectValues`, …) instead of reading this directly.\n */\nexport const STREAM_CONTROLLER: unique symbol = Symbol.for(\n \"@langchain/angular/controller\"\n);\n\n/**\n * Return shape of {@link useStream} — the Angular `StreamApi`.\n *\n * Reactivity primitives follow Angular conventions:\n *\n * - Data projections are `Signal<T>`; call them as functions in\n * templates (`stream.messages()`). They are snapshots — never\n * mutate the returned arrays / maps.\n * - Imperative methods (`submit` / `stop` / `respond`) are plain\n * functions. No `WritableSignal`s are exposed on the root handle.\n * - Identity values captured at construction time (`client`,\n * `assistantId`) are exposed as plain values; remount the\n * component to swap them.\n */\nexport interface UseStreamReturn<\n T = Record<string, unknown>,\n InterruptType = unknown,\n ConfigurableType extends object = Record<string, unknown>,\n StateType extends object = InferStateType<T>,\n SubagentStates = InferSubagentStates<T>,\n> {\n // ----- always-on root projections -----\n /**\n * The most recent `values`-channel snapshot emitted at the root\n * namespace — i.e. the thread-level state as the server sees it\n * after each superstep. Updated on every root `values` event, not\n * on token-level deltas: if you render `stream.values().messages`\n * directly you'll see full turns appear at once instead of\n * streaming token-by-token. Use {@link messages} (or\n * `injectMessages`) for the token-streamed view.\n *\n * Equivalent to calling `injectValues(stream)`.\n */\n readonly values: Signal<StateType>;\n /**\n * The root message projection. Assembled from two sources and\n * merged in real time:\n *\n * 1. `messages`-channel deltas — token-level streaming events\n * (`message-start`, `content-block-delta`, `message-finish`)\n * emitted by the runtime. These drive live, token-by-token\n * updates.\n * 2. `values.messages` snapshots — the authoritative ordering\n * and any messages the agent produces without token streaming\n * (human turns, tool results, echoes from subagents).\n *\n * If the backend only emits `values` events (no `messages`\n * channel), every message will appear fully-formed on each\n * values update rather than streaming. This is a backend/runtime\n * concern — the Angular layer faithfully renders whatever the\n * server sends.\n *\n * Equivalent to calling `injectMessages(stream)` with no target.\n */\n readonly messages: Signal<BaseMessage[]>;\n /**\n * Root-namespace tool calls assembled from the `tools` channel.\n * Each entry is a fully parsed {@link AssembledToolCall} with\n * name, args, and id — suitable for rendering approval UIs or\n * forwarding to headless tool handlers.\n *\n * When the stream is typed with an agent brand or tool list,\n * entries are narrowed via {@link InferToolCalls}. Equivalent to\n * calling `injectToolCalls(stream)` with no target.\n */\n readonly toolCalls: Signal<InferToolCalls<T>[]>;\n /**\n * All unresolved protocol interrupts observed on the root\n * namespace during the active thread. Populated from lifecycle /\n * input events and seeded on hydration from `thread.getState()`.\n * Cleared optimistically when a new run starts or an interrupt is\n * resolved via {@link respond} / `submit({ command: { resume } })`.\n */\n readonly interrupts: Signal<Interrupt<InterruptType>[]>;\n /**\n * Convenience alias for {@link interrupts}[0] — the primary\n * interrupt most UIs should act on when only one is pending.\n * `undefined` when no interrupt is active.\n */\n readonly interrupt: Signal<Interrupt<InterruptType> | undefined>;\n /**\n * `true` while a run is active or being started on the current\n * thread. Driven by root-namespace lifecycle events (`running` →\n * `true`, terminal phases → `false`). Use this to disable submit\n * buttons and show in-flight spinners.\n */\n readonly isLoading: Signal<boolean>;\n /**\n * `true` while the initial `thread.getState()` hydration for the\n * active thread is in flight. Distinct from {@link isLoading} —\n * thread loading covers the one-time fetch that seeds\n * {@link values} / {@link messages} before any user submit.\n */\n readonly isThreadLoading: Signal<boolean>;\n /**\n * The last error observed on the active run or hydration attempt.\n * `undefined` when no error has occurred. Cleared optimistically\n * when a new {@link submit} starts.\n */\n readonly error: Signal<unknown>;\n /**\n * Id of the thread the controller is bound to. `null` until the\n * first {@link submit} creates or selects a thread (or until an\n * explicit `threadId` option is provided and hydrated).\n */\n readonly threadId: Signal<string | null>;\n /**\n * Promise that settles when the active thread's initial hydration\n * completes. Exposed so SSR/render-before-flush pipelines can\n * `await stream.hydrationPromise()` before serialising. A fresh\n * promise is installed on every `threadId` change.\n */\n readonly hydrationPromise: Signal<Promise<void>>;\n\n // ----- always-on discovery -----\n /**\n * Subagents discovered on the root run. For DeepAgent-typed\n * streams the key set is narrowed to the subagent names declared\n * on the agent brand (`keyof InferSubagentStates<T>`).\n */\n readonly subagents: Signal<\n ReadonlyMap<\n keyof SubagentStates & string extends never\n ? string\n : keyof SubagentStates & string,\n SubagentDiscoverySnapshot\n >\n >;\n /**\n * Subgraphs discovered on the root run.\n *\n * A namespace is classified as a subgraph iff at least one\n * strictly-deeper namespace has been observed with it as a prefix.\n * This is inferred from the lifecycle event stream — plain function\n * nodes (`orchestrator`, `writer` in the nested-stategraph example)\n * never appear here even though the server emits namespaced\n * lifecycle events for them. Promotion is monotonic and retroactive;\n * an entry appears as soon as the first descendant event lands.\n */\n readonly subgraphs: Signal<ReadonlyMap<string, SubgraphDiscoverySnapshot>>;\n /**\n * Subgraphs indexed by the graph node that produced them\n * (`addNode(\"visualizer_0\", …)`). Each value is an array because\n * parallel fan-outs and loops can spawn multiple invocations of\n * the same node; arrays preserve insertion order. Updates in\n * lock-step with {@link subgraphs}.\n */\n readonly subgraphsByNode: Signal<\n ReadonlyMap<string, readonly SubgraphDiscoverySnapshot[]>\n >;\n\n // ----- imperatives -----\n /**\n * Dispatch a new run on the bound thread.\n *\n * `input` is typed as `Partial<StateType>` so IDE autocompletion\n * surfaces the state keys declared on the root primitive. Pass\n * `null` (or omit fields) when resuming an interrupt via\n * `options.command.resume` — the server accepts a null payload\n * in that case.\n */\n submit(\n input: WidenUpdateMessages<Partial<StateType>> | null | undefined,\n options?: StreamSubmitOptions<StateType, ConfigurableType>\n ): Promise<void>;\n /**\n * Stop the active run on the current thread. By default cancels the\n * run server-side and disconnects the client; pass `{ cancel: false }`\n * or use {@link disconnect} for join/rejoin. Sets {@link isLoading} to\n * `false` immediately; {@link values} and {@link messages} are preserved.\n */\n stop(options?: StreamStopOptions): Promise<void>;\n /**\n * Disconnect the client without cancelling the run server-side.\n * Alias for `stop({ cancel: false })`.\n */\n disconnect(): Promise<void>;\n /**\n * Resume a pending protocol interrupt by sending a response payload\n * back to the interrupted namespace.\n *\n * When `target` is omitted, responds to the latest unresolved\n * interrupt in {@link interrupts}. Pass an explicit\n * `{ interruptId, namespace? }` when multiple interrupts are\n * pending or the interrupt lives in a subgraph namespace.\n */\n respond(\n response: unknown,\n target?: { interruptId: string; namespace?: string[] }\n ): Promise<void>;\n\n // ----- identity -----\n /** LangGraph SDK client used to construct thread streams. */\n readonly client: Client;\n /** Assistant id the thread is bound to for its lifetime. */\n readonly assistantId: string;\n\n /**\n * Returns the bound {@link ThreadStream}, if one exists (`undefined`\n * until the thread is hydrated or the first submit completes). Prefer\n * the projections and selector primitives for UI work; use this for\n * low-level protocol access (raw subscriptions, state commands, etc.).\n */\n getThread(): ThreadStream | undefined;\n\n /** @internal Used by selector primitives. */\n readonly [STREAM_CONTROLLER]: StreamController<\n StateType,\n InterruptType,\n ConfigurableType\n >;\n}\n\n/**\n * Erased handle useful as a parameter type for helper components that\n * pass a `stream` through to selector primitives without reading\n * `values` directly. Mirrors the React/Vue `AnyStream` alias.\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport type AnyStream = UseStreamReturn<any, any, any>;\n\n/**\n * Convenience alias — the fully-resolved return type of\n * {@link useStream} for a given source type `T`.\n */\nexport type StreamApi<\n T = Record<string, unknown>,\n InterruptType = unknown,\n ConfigurableType extends object = Record<string, unknown>,\n> = UseStreamReturn<T, InterruptType, ConfigurableType>;\n\n/**\n * React-compatible alias for the fully-resolved stream handle type.\n * Angular docs prefer {@link StreamApi}, but shared libraries can use\n * this name across framework bindings.\n */\nexport type UseStreamResult<\n T = Record<string, unknown>,\n InterruptType = unknown,\n ConfigurableType extends object = Record<string, unknown>,\n> = UseStreamReturn<T, InterruptType, ConfigurableType>;\n\n/**\n * Framework-free factory that constructs a {@link StreamController}\n * and wraps its stores in Angular Signals. Callers must supply the\n * {@link DestroyRef} that owns the controller's lifetime — it's\n * already captured by the public `injectStream` helper.\n *\n * Exported for advanced callers (e.g. testing utilities, custom\n * factories) that prefer to manage injection scope themselves.\n */\nexport function useStream<\n T = Record<string, unknown>,\n InterruptType = unknown,\n ConfigurableType extends object = Record<string, unknown>,\n>(\n options: UseStreamOptions<InferStateType<T>>,\n destroyRef?: DestroyRef\n): UseStreamReturn<T, InterruptType, ConfigurableType> {\n type StateType = InferStateType<T>;\n\n interface OptionsBag {\n assistantId?: string;\n threadId?: string | null | Signal<string | null | undefined>;\n client?: Client;\n apiUrl?: string;\n apiKey?: string;\n callerOptions?: ClientConfig[\"callerOptions\"];\n defaultHeaders?: ClientConfig[\"defaultHeaders\"];\n transport?: \"sse\" | \"websocket\" | AgentServerAdapter;\n fetch?: typeof fetch;\n webSocketFactory?: (url: string) => WebSocket;\n onThreadId?: (threadId: string) => void;\n onCreated?: (info: RunExecutionInfo) => void;\n onCompleted?: (info: RunCompletedInfo) => void;\n initialValues?: StateType;\n messagesKey?: string;\n tools?: AnyHeadlessToolImplementation[];\n onTool?: OnToolCallback;\n }\n const asBag = options as OptionsBag;\n\n const hasCustomAdapter =\n asBag.transport != null && typeof asBag.transport !== \"string\";\n const transport = asBag.transport;\n\n const client: Client =\n asBag.client ??\n (new ClientCtor({\n apiUrl: asBag.apiUrl,\n apiKey: asBag.apiKey,\n callerOptions: asBag.callerOptions,\n defaultHeaders: asBag.defaultHeaders,\n }) as unknown as Client);\n\n // Custom adapters may omit `assistantId`; the controller still\n // requires one so it has something to forward to `threads.stream`.\n const sentinel = \"_\";\n const assistantId =\n \"assistantId\" in options ? (options.assistantId ?? sentinel) : sentinel;\n\n // Normalize threadId input to a signal — callers may pass plain\n // values, nulls, or their own signals.\n const threadIdInput: Signal<string | null> = (() => {\n const raw = asBag.threadId;\n if (isSignal(raw)) {\n return computed(\n () => (raw as Signal<string | null | undefined>)() ?? null\n );\n }\n const initial: string | null = (raw as string | null | undefined) ?? null;\n return signal(initial) as unknown as Signal<string | null>;\n })();\n\n const controller = new StreamController<\n StateType,\n InterruptType,\n ConfigurableType\n >({\n assistantId,\n // Cast: the runtime `Client` is state-shape agnostic, but the\n // controller declares `client: Client<StateType>` for its own\n // typings. Same cast is applied in the React/Vue bindings.\n client: client as unknown as Client<StateType>,\n threadId: untracked(() => threadIdInput()),\n transport,\n fetch: hasCustomAdapter ? undefined : asBag.fetch,\n webSocketFactory: hasCustomAdapter ? undefined : asBag.webSocketFactory,\n onThreadId: options.onThreadId,\n onCreated: options.onCreated,\n onCompleted: options.onCompleted,\n initialValues: options.initialValues,\n messagesKey: options.messagesKey,\n });\n\n // Deferred dispose — matches the React `useEffect(() =>\n // controller.activate())` and Vue `onScopeDispose(deactivate)`\n // patterns. HMR / scope-reuse scenarios stay clean because\n // `activate()` cancels the pending dispose if the scope survives.\n const deactivate = controller.activate();\n const ref = destroyRef ?? inject(DestroyRef);\n ref.onDestroy(deactivate);\n\n // ─── Reactivity bridge: StreamStore → Signal ────────────────────────\n function bindStore<S>(\n subscribe: (listener: () => void) => () => void,\n getSnapshot: () => S\n ): Signal<S> {\n const s = signal<S>(getSnapshot());\n const unsubscribe = subscribe(() => {\n s.set(getSnapshot());\n });\n ref.onDestroy(unsubscribe);\n return computed(() => s());\n }\n\n const rootSignal = bindStore<RootSnapshot<StateType, InterruptType>>(\n controller.rootStore.subscribe,\n controller.rootStore.getSnapshot\n );\n const subagentSignal = bindStore<SubagentMap>(\n controller.subagentStore.subscribe,\n controller.subagentStore.getSnapshot\n );\n const subgraphSignal = bindStore<SubgraphMap>(\n controller.subgraphStore.subscribe,\n controller.subgraphStore.getSnapshot\n );\n const subgraphByNodeSignal = bindStore<SubgraphByNodeMap>(\n controller.subgraphByNodeStore.subscribe,\n controller.subgraphByNodeStore.getSnapshot\n );\n\n const values = computed(() => rootSignal().values);\n const messages = computed(() => rootSignal().messages);\n const toolCalls = computed(\n () => rootSignal().toolCalls as InferToolCalls<T>[]\n );\n const interrupts = computed(() =>\n filterOutHeadlessToolInterrupts(rootSignal().interrupts)\n );\n const interrupt = computed(() => interrupts()[0]);\n const isLoading = computed(() => rootSignal().isLoading);\n const isThreadLoading = computed(() => rootSignal().isThreadLoading);\n const error = computed(() => rootSignal().error);\n const threadId = computed(() => rootSignal().threadId);\n\n // `hydrationPromise` is a property on the controller that gets\n // swapped on every `hydrate()` call. Exposing it as a signal lets\n // templates `await stream.hydrationPromise()` reactively; we\n // refresh the reference when the root store settles a new promise.\n const hydrationPromise = computed(() => {\n rootSignal();\n return controller.hydrationPromise;\n });\n\n // ─── threadId reactivity ────────────────────────────────────────────\n //\n // Re-hydrate whenever the caller's threadId input changes after\n // construction. The initial hydrate already fired synchronously in\n // the controller constructor, so we compare against the snapshot\n // captured at construction time rather than blindly skipping the\n // first run — in Angular, `@Input()` bindings apply *between*\n // construction and the first effect tick, so the first read can\n // legitimately be a different (updated) value that needs to\n // hydrate.\n const initialThreadId = untracked(() => threadIdInput()) ?? null;\n let lastAppliedThreadId: string | null = initialThreadId;\n effect(() => {\n const next = threadIdInput() ?? null;\n if (next === lastAppliedThreadId) return;\n lastAppliedThreadId = next;\n untracked(() => {\n void controller.hydrate(next);\n });\n });\n\n // ─── Headless-tool handling ─────────────────────────────────────────\n const tools = options.tools;\n const onTool = options.onTool;\n if (tools?.length) {\n const handledTools = new Set<string>();\n\n // Clear the dedup set whenever the thread id changes.\n effect(() => {\n threadIdInput();\n untracked(() => handledTools.clear());\n });\n\n effect(() => {\n rootSignal();\n untracked(() => {\n scheduleCoalescedHeadlessToolFlush(handledTools, () => {\n const snapshot = rootSignal();\n const bag = snapshot.values as unknown as Record<string, unknown>;\n const protocolInterrupts =\n snapshot.interrupts as unknown as Interrupt[];\n const valuesInterrupts = Array.isArray(bag?.__interrupt__)\n ? (bag.__interrupt__ as Interrupt[])\n : [];\n const headlessInterrupts =\n protocolInterrupts.length > 0\n ? protocolInterrupts\n : valuesInterrupts;\n if (headlessInterrupts.length === 0) return;\n flushPendingHeadlessToolInterrupts(\n { ...bag, __interrupt__: headlessInterrupts },\n tools,\n handledTools,\n {\n onTool,\n defer: (run) => {\n void Promise.resolve().then(run);\n },\n resumeSubmit: (command) =>\n controller.submit(null, {\n command,\n } as StreamSubmitOptions<StateType, ConfigurableType>),\n }\n );\n });\n });\n });\n }\n\n const handle: UseStreamReturn<T, InterruptType, ConfigurableType> = {\n values: values as UseStreamReturn<\n T,\n InterruptType,\n ConfigurableType\n >[\"values\"],\n messages,\n toolCalls,\n interrupts,\n interrupt,\n isLoading,\n isThreadLoading,\n error,\n threadId,\n hydrationPromise,\n subagents: subagentSignal as UseStreamReturn<\n T,\n InterruptType,\n ConfigurableType\n >[\"subagents\"],\n subgraphs: subgraphSignal,\n subgraphsByNode: subgraphByNodeSignal,\n submit: (input, submitOptions) => controller.submit(input, submitOptions),\n stop: (options) => controller.stop(options),\n disconnect: () => controller.disconnect(),\n respond: (response, target) => controller.respond(response, target),\n getThread: () => controller.getThread(),\n client,\n assistantId,\n [STREAM_CONTROLLER]: controller,\n };\n\n return handle;\n}\n\n/**\n * Helper used by the selector primitives to reach the underlying\n * {@link ChannelRegistry} from a stream handle. Kept internal —\n * application code should call `injectMessages`, `injectToolCalls`,\n * etc. instead of reading this directly.\n *\n * @internal\n */\nexport function getRegistry(\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n stream: UseStreamReturn<any, any, any>\n): ChannelRegistry {\n return stream[STREAM_CONTROLLER].registry;\n}\n\nexport type { ThreadStream };\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"use-stream.cjs","names":["ClientCtor","StreamController","DestroyRef"],"sources":["../src/use-stream.ts"],"sourcesContent":["import {\n DestroyRef,\n computed,\n effect,\n inject,\n isSignal,\n signal,\n untracked,\n type Signal,\n} from \"@angular/core\";\nimport type { BaseMessage } from \"@langchain/core/messages\";\nimport type { Client, Interrupt } from \"@langchain/langgraph-sdk\";\nimport {\n filterOutHeadlessToolInterrupts,\n flushPendingHeadlessToolInterrupts,\n scheduleCoalescedHeadlessToolFlush,\n type AnyHeadlessToolImplementation,\n type OnToolCallback,\n} from \"@langchain/langgraph-sdk\";\nimport {\n Client as ClientCtor,\n type ClientConfig,\n type ThreadStream,\n} from \"@langchain/langgraph-sdk/client\";\nimport {\n StreamController,\n type AgentServerAdapter,\n type AgentServerOptions as StreamAgentServerOptions,\n type ChannelRegistry,\n type CustomAdapterOptions as StreamCustomAdapterOptions,\n type InferStateType,\n type InferToolCalls,\n type InferSubagentStates,\n type RootSnapshot,\n type RunCompletedInfo,\n type RunExecutionInfo,\n type StreamRespondAllOptions,\n type StreamRespondOptions,\n type StreamStopOptions,\n type StreamSubmitOptions,\n type SubagentDiscoverySnapshot,\n type SubagentMap,\n type SubgraphByNodeMap,\n type SubgraphDiscoverySnapshot,\n type SubgraphMap,\n type UseStreamOptions as StreamUseStreamOptions,\n type WidenUpdateMessages,\n} from \"@langchain/langgraph-sdk/stream\";\n\ntype AngularThreadId = string | null | Signal<string | null | undefined>;\n\nexport type AgentServerOptions<StateType extends object> =\n StreamAgentServerOptions<StateType, AngularThreadId>;\n\nexport type CustomAdapterOptions<StateType extends object> =\n StreamCustomAdapterOptions<StateType, AngularThreadId, string>;\n\nexport type UseStreamOptions<\n StateType extends object = Record<string, unknown>,\n> = StreamUseStreamOptions<\n StateType,\n AngularThreadId,\n string | undefined,\n string | undefined,\n string\n>;\n\n/**\n * Private field on the handle that carries the\n * {@link StreamController} reference. Selector primitives read this\n * to reach the shared {@link ChannelRegistry}. Use the companion\n * `inject*` selectors (`injectMessages`, `injectToolCalls`,\n * `injectValues`, …) instead of reading this directly.\n */\nexport const STREAM_CONTROLLER: unique symbol = Symbol.for(\n \"@langchain/angular/controller\"\n);\n\n/**\n * Return shape of {@link useStream} — the Angular `StreamApi`.\n *\n * Reactivity primitives follow Angular conventions:\n *\n * - Data projections are `Signal<T>`; call them as functions in\n * templates (`stream.messages()`). They are snapshots — never\n * mutate the returned arrays / maps.\n * - Imperative methods (`submit` / `stop` / `respond`) are plain\n * functions. No `WritableSignal`s are exposed on the root handle.\n * - Identity values captured at construction time (`client`,\n * `assistantId`) are exposed as plain values; remount the\n * component to swap them.\n */\nexport interface UseStreamReturn<\n T = Record<string, unknown>,\n InterruptType = unknown,\n ConfigurableType extends object = Record<string, unknown>,\n StateType extends object = InferStateType<T>,\n SubagentStates = InferSubagentStates<T>,\n> {\n // ----- always-on root projections -----\n /**\n * The most recent `values`-channel snapshot emitted at the root\n * namespace — i.e. the thread-level state as the server sees it\n * after each superstep. Updated on every root `values` event, not\n * on token-level deltas: if you render `stream.values().messages`\n * directly you'll see full turns appear at once instead of\n * streaming token-by-token. Use {@link messages} (or\n * `injectMessages`) for the token-streamed view.\n *\n * Equivalent to calling `injectValues(stream)`.\n */\n readonly values: Signal<StateType>;\n /**\n * The root message projection. Assembled from two sources and\n * merged in real time:\n *\n * 1. `messages`-channel deltas — token-level streaming events\n * (`message-start`, `content-block-delta`, `message-finish`)\n * emitted by the runtime. These drive live, token-by-token\n * updates.\n * 2. `values.messages` snapshots — the authoritative ordering\n * and any messages the agent produces without token streaming\n * (human turns, tool results, echoes from subagents).\n *\n * If the backend only emits `values` events (no `messages`\n * channel), every message will appear fully-formed on each\n * values update rather than streaming. This is a backend/runtime\n * concern — the Angular layer faithfully renders whatever the\n * server sends.\n *\n * Equivalent to calling `injectMessages(stream)` with no target.\n */\n readonly messages: Signal<BaseMessage[]>;\n /**\n * Root-namespace tool calls assembled from the `tools` channel.\n * Each entry is a fully parsed {@link AssembledToolCall} with\n * name, args, and id — suitable for rendering approval UIs or\n * forwarding to headless tool handlers.\n *\n * When the stream is typed with an agent brand or tool list,\n * entries are narrowed via {@link InferToolCalls}. Equivalent to\n * calling `injectToolCalls(stream)` with no target.\n */\n readonly toolCalls: Signal<InferToolCalls<T>[]>;\n /**\n * All unresolved protocol interrupts observed on the root\n * namespace during the active thread. Populated from lifecycle /\n * input events and seeded on hydration from `thread.getState()`.\n * Cleared optimistically when a new run starts or an interrupt is\n * resolved via {@link respond}.\n */\n readonly interrupts: Signal<Interrupt<InterruptType>[]>;\n /**\n * Convenience alias for {@link interrupts}[0] — the primary\n * interrupt most UIs should act on when only one is pending.\n * `undefined` when no interrupt is active.\n */\n readonly interrupt: Signal<Interrupt<InterruptType> | undefined>;\n /**\n * `true` while a run is active or being started on the current\n * thread. Driven by root-namespace lifecycle events (`running` →\n * `true`, terminal phases → `false`). Use this to disable submit\n * buttons and show in-flight spinners.\n */\n readonly isLoading: Signal<boolean>;\n /**\n * `true` while the initial `thread.getState()` hydration for the\n * active thread is in flight. Distinct from {@link isLoading} —\n * thread loading covers the one-time fetch that seeds\n * {@link values} / {@link messages} before any user submit.\n */\n readonly isThreadLoading: Signal<boolean>;\n /**\n * The last error observed on the active run or hydration attempt.\n * `undefined` when no error has occurred. Cleared optimistically\n * when a new {@link submit} starts.\n */\n readonly error: Signal<unknown>;\n /**\n * Id of the thread the controller is bound to. `null` until the\n * first {@link submit} creates or selects a thread (or until an\n * explicit `threadId` option is provided and hydrated).\n */\n readonly threadId: Signal<string | null>;\n /**\n * Promise that settles when the active thread's initial hydration\n * completes. Exposed so SSR/render-before-flush pipelines can\n * `await stream.hydrationPromise()` before serialising. A fresh\n * promise is installed on every `threadId` change.\n */\n readonly hydrationPromise: Signal<Promise<void>>;\n\n // ----- always-on discovery -----\n /**\n * Subagents discovered on the root run. For DeepAgent-typed\n * streams the key set is narrowed to the subagent names declared\n * on the agent brand (`keyof InferSubagentStates<T>`).\n */\n readonly subagents: Signal<\n ReadonlyMap<\n keyof SubagentStates & string extends never\n ? string\n : keyof SubagentStates & string,\n SubagentDiscoverySnapshot\n >\n >;\n /**\n * Subgraphs discovered on the root run.\n *\n * A namespace is classified as a subgraph iff at least one\n * strictly-deeper namespace has been observed with it as a prefix.\n * This is inferred from the lifecycle event stream — plain function\n * nodes (`orchestrator`, `writer` in the nested-stategraph example)\n * never appear here even though the server emits namespaced\n * lifecycle events for them. Promotion is monotonic and retroactive;\n * an entry appears as soon as the first descendant event lands.\n */\n readonly subgraphs: Signal<ReadonlyMap<string, SubgraphDiscoverySnapshot>>;\n /**\n * Subgraphs indexed by the graph node that produced them\n * (`addNode(\"visualizer_0\", …)`). Each value is an array because\n * parallel fan-outs and loops can spawn multiple invocations of\n * the same node; arrays preserve insertion order. Updates in\n * lock-step with {@link subgraphs}.\n */\n readonly subgraphsByNode: Signal<\n ReadonlyMap<string, readonly SubgraphDiscoverySnapshot[]>\n >;\n\n // ----- imperatives -----\n /**\n * Dispatch a new run on the bound thread.\n *\n * `input` is typed as `Partial<StateType>` so IDE autocompletion\n * surfaces the state keys declared on the root primitive.\n */\n submit(\n input: WidenUpdateMessages<Partial<StateType>> | null | undefined,\n options?: StreamSubmitOptions<StateType, ConfigurableType>\n ): Promise<void>;\n /**\n * Stop the active run on the current thread. By default cancels the\n * run server-side and disconnects the client; pass `{ cancel: false }`\n * or use {@link disconnect} for join/rejoin. Sets {@link isLoading} to\n * `false` immediately; {@link values} and {@link messages} are preserved.\n */\n stop(options?: StreamStopOptions): Promise<void>;\n /**\n * Disconnect the client without cancelling the run server-side.\n * Alias for `stop({ cancel: false })`.\n */\n disconnect(): Promise<void>;\n /**\n * Resume a pending protocol interrupt by sending a response payload\n * back to the interrupted namespace.\n *\n * When `options.interruptId` is omitted, walks `getThread()?.interrupts`\n * from newest to oldest and resumes the first not yet resolved by a prior\n * `respond()` call. That may be a root or subgraph interrupt and is\n * **not** necessarily {@link interrupt} (`interrupts()[0]`, root-only).\n * Safe when exactly one interrupt is pending; otherwise pass an explicit\n * `options.interruptId` (and `options.namespace` for subgraph\n * interrupts).\n *\n * The server validates `namespace` against the pending interrupt. Root\n * interrupts use `namespace: []` (default when omitted). For subgraph\n * interrupts, copy `namespace` from `getThread()?.interrupts`.\n *\n * @example\n * ```ts\n * // Single pending interrupt\n * await stream.respond({ approved: true });\n * ```\n *\n * @example\n * ```ts\n * // Multiple root interrupts\n * for (const intr of stream.interrupts()) {\n * await stream.respond(decide(intr.value), { interruptId: intr.id! });\n * }\n * ```\n *\n * @example\n * ```ts\n * // Subgraph interrupt — namespace from `getThread()`\n * const thread = stream.getThread();\n * for (const entry of thread?.interrupts ?? []) {\n * await stream.respond(buildResponse(entry.payload), {\n * interruptId: entry.interruptId,\n * namespace: entry.namespace,\n * });\n * }\n * ```\n *\n * To resume several interrupts pending at the same checkpoint in one\n * command, use {@link respondAll}.\n */\n respond(\n response: unknown,\n options?: StreamRespondOptions<ConfigurableType>\n ): Promise<void>;\n\n /**\n * Resume several pending interrupts at the same checkpoint in a single\n * command — required when a run pauses on multiple interrupts at once\n * (e.g. parallel tool-authorization prompts), which sequential\n * {@link respond} calls cannot handle. `responsesById` maps each pending\n * `interruptId` to its response, so different interrupts can receive\n * different payloads. Pass `options.config` / `options.metadata` to fold\n * run-level config and metadata into the resumed run, mirroring\n * `submit()`.\n *\n * @example\n * ```ts\n * await stream.respondAll({\n * [interruptA.id]: { approved: true },\n * [interruptB.id]: { approved: false },\n * });\n * ```\n */\n respondAll(\n responsesById: Record<string, unknown>,\n options?: StreamRespondAllOptions<ConfigurableType>\n ): Promise<void>;\n\n // ----- identity -----\n /** LangGraph SDK client used to construct thread streams. */\n readonly client: Client;\n /** Assistant id the thread is bound to for its lifetime. */\n readonly assistantId: string;\n\n /**\n * Returns the bound {@link ThreadStream}, if one exists (`undefined`\n * until the thread is hydrated or the first submit completes). Prefer\n * the projections and selector primitives for UI work; use this for\n * low-level protocol access (raw subscriptions, state commands, etc.).\n */\n getThread(): ThreadStream | undefined;\n\n /** @internal Used by selector primitives. */\n readonly [STREAM_CONTROLLER]: StreamController<\n StateType,\n InterruptType,\n ConfigurableType\n >;\n}\n\n/**\n * Erased handle useful as a parameter type for helper components that\n * pass a `stream` through to selector primitives without reading\n * `values` directly. Mirrors the React/Vue `AnyStream` alias.\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport type AnyStream = UseStreamReturn<any, any, any>;\n\n/**\n * Convenience alias — the fully-resolved return type of\n * {@link useStream} for a given source type `T`.\n */\nexport type StreamApi<\n T = Record<string, unknown>,\n InterruptType = unknown,\n ConfigurableType extends object = Record<string, unknown>,\n> = UseStreamReturn<T, InterruptType, ConfigurableType>;\n\n/**\n * React-compatible alias for the fully-resolved stream handle type.\n * Angular docs prefer {@link StreamApi}, but shared libraries can use\n * this name across framework bindings.\n */\nexport type UseStreamResult<\n T = Record<string, unknown>,\n InterruptType = unknown,\n ConfigurableType extends object = Record<string, unknown>,\n> = UseStreamReturn<T, InterruptType, ConfigurableType>;\n\n/**\n * Framework-free factory that constructs a {@link StreamController}\n * and wraps its stores in Angular Signals. Callers must supply the\n * {@link DestroyRef} that owns the controller's lifetime — it's\n * already captured by the public `injectStream` helper.\n *\n * Exported for advanced callers (e.g. testing utilities, custom\n * factories) that prefer to manage injection scope themselves.\n */\nexport function useStream<\n T = Record<string, unknown>,\n InterruptType = unknown,\n ConfigurableType extends object = Record<string, unknown>,\n>(\n options: UseStreamOptions<InferStateType<T>>,\n destroyRef?: DestroyRef\n): UseStreamReturn<T, InterruptType, ConfigurableType> {\n type StateType = InferStateType<T>;\n\n interface OptionsBag {\n assistantId?: string;\n threadId?: string | null | Signal<string | null | undefined>;\n client?: Client;\n apiUrl?: string;\n apiKey?: string;\n callerOptions?: ClientConfig[\"callerOptions\"];\n defaultHeaders?: ClientConfig[\"defaultHeaders\"];\n transport?: \"sse\" | \"websocket\" | AgentServerAdapter;\n fetch?: typeof fetch;\n webSocketFactory?: (url: string) => WebSocket;\n onThreadId?: (threadId: string) => void;\n onCreated?: (info: RunExecutionInfo) => void;\n onCompleted?: (info: RunCompletedInfo) => void;\n initialValues?: StateType;\n messagesKey?: string;\n tools?: AnyHeadlessToolImplementation[];\n onTool?: OnToolCallback;\n }\n const asBag = options as OptionsBag;\n\n const hasCustomAdapter =\n asBag.transport != null && typeof asBag.transport !== \"string\";\n const transport = asBag.transport;\n\n const client: Client =\n asBag.client ??\n (new ClientCtor({\n apiUrl: asBag.apiUrl,\n apiKey: asBag.apiKey,\n callerOptions: asBag.callerOptions,\n defaultHeaders: asBag.defaultHeaders,\n }) as unknown as Client);\n\n // Custom adapters may omit `assistantId`; the controller still\n // requires one so it has something to forward to `threads.stream`.\n const sentinel = \"_\";\n const assistantId =\n \"assistantId\" in options ? (options.assistantId ?? sentinel) : sentinel;\n\n // Normalize threadId input to a signal — callers may pass plain\n // values, nulls, or their own signals.\n const threadIdInput: Signal<string | null> = (() => {\n const raw = asBag.threadId;\n if (isSignal(raw)) {\n return computed(\n () => (raw as Signal<string | null | undefined>)() ?? null\n );\n }\n const initial: string | null = (raw as string | null | undefined) ?? null;\n return signal(initial) as unknown as Signal<string | null>;\n })();\n\n const controller = new StreamController<\n StateType,\n InterruptType,\n ConfigurableType\n >({\n assistantId,\n // Cast: the runtime `Client` is state-shape agnostic, but the\n // controller declares `client: Client<StateType>` for its own\n // typings. Same cast is applied in the React/Vue bindings.\n client: client as unknown as Client<StateType>,\n threadId: untracked(() => threadIdInput()),\n transport,\n fetch: hasCustomAdapter ? undefined : asBag.fetch,\n webSocketFactory: hasCustomAdapter ? undefined : asBag.webSocketFactory,\n onThreadId: options.onThreadId,\n onCreated: options.onCreated,\n onCompleted: options.onCompleted,\n initialValues: options.initialValues,\n messagesKey: options.messagesKey,\n });\n\n // Deferred dispose — matches the React `useEffect(() =>\n // controller.activate())` and Vue `onScopeDispose(deactivate)`\n // patterns. HMR / scope-reuse scenarios stay clean because\n // `activate()` cancels the pending dispose if the scope survives.\n const deactivate = controller.activate();\n const ref = destroyRef ?? inject(DestroyRef);\n ref.onDestroy(deactivate);\n\n // ─── Reactivity bridge: StreamStore → Signal ────────────────────────\n function bindStore<S>(\n subscribe: (listener: () => void) => () => void,\n getSnapshot: () => S\n ): Signal<S> {\n const s = signal<S>(getSnapshot());\n const unsubscribe = subscribe(() => {\n s.set(getSnapshot());\n });\n ref.onDestroy(unsubscribe);\n return computed(() => s());\n }\n\n const rootSignal = bindStore<RootSnapshot<StateType, InterruptType>>(\n controller.rootStore.subscribe,\n controller.rootStore.getSnapshot\n );\n const subagentSignal = bindStore<SubagentMap>(\n controller.subagentStore.subscribe,\n controller.subagentStore.getSnapshot\n );\n const subgraphSignal = bindStore<SubgraphMap>(\n controller.subgraphStore.subscribe,\n controller.subgraphStore.getSnapshot\n );\n const subgraphByNodeSignal = bindStore<SubgraphByNodeMap>(\n controller.subgraphByNodeStore.subscribe,\n controller.subgraphByNodeStore.getSnapshot\n );\n\n const values = computed(() => rootSignal().values);\n const messages = computed(() => rootSignal().messages);\n const toolCalls = computed(\n () => rootSignal().toolCalls as InferToolCalls<T>[]\n );\n const interrupts = computed(() =>\n filterOutHeadlessToolInterrupts(rootSignal().interrupts)\n );\n const interrupt = computed(() => interrupts()[0]);\n const isLoading = computed(() => rootSignal().isLoading);\n const isThreadLoading = computed(() => rootSignal().isThreadLoading);\n const error = computed(() => rootSignal().error);\n const threadId = computed(() => rootSignal().threadId);\n\n // `hydrationPromise` is a property on the controller that gets\n // swapped on every `hydrate()` call. Exposing it as a signal lets\n // templates `await stream.hydrationPromise()` reactively; we\n // refresh the reference when the root store settles a new promise.\n const hydrationPromise = computed(() => {\n rootSignal();\n return controller.hydrationPromise;\n });\n\n // ─── threadId reactivity ────────────────────────────────────────────\n //\n // Re-hydrate whenever the caller's threadId input changes after\n // construction. The initial hydrate already fired synchronously in\n // the controller constructor, so we compare against the snapshot\n // captured at construction time rather than blindly skipping the\n // first run — in Angular, `@Input()` bindings apply *between*\n // construction and the first effect tick, so the first read can\n // legitimately be a different (updated) value that needs to\n // hydrate.\n const initialThreadId = untracked(() => threadIdInput()) ?? null;\n let lastAppliedThreadId: string | null = initialThreadId;\n effect(() => {\n const next = threadIdInput() ?? null;\n if (next === lastAppliedThreadId) return;\n lastAppliedThreadId = next;\n untracked(() => {\n void controller.hydrate(next);\n });\n });\n\n // ─── Headless-tool handling ─────────────────────────────────────────\n const tools = options.tools;\n const onTool = options.onTool;\n if (tools?.length) {\n const handledTools = new Set<string>();\n\n // Clear the dedup set whenever the thread id changes.\n effect(() => {\n threadIdInput();\n untracked(() => handledTools.clear());\n });\n\n effect(() => {\n rootSignal();\n untracked(() => {\n scheduleCoalescedHeadlessToolFlush(handledTools, () => {\n const snapshot = rootSignal();\n const bag = snapshot.values as unknown as Record<string, unknown>;\n const protocolInterrupts =\n snapshot.interrupts as unknown as Interrupt[];\n const valuesInterrupts = Array.isArray(bag?.__interrupt__)\n ? (bag.__interrupt__ as Interrupt[])\n : [];\n const headlessInterrupts =\n protocolInterrupts.length > 0\n ? protocolInterrupts\n : valuesInterrupts;\n if (headlessInterrupts.length === 0) return;\n flushPendingHeadlessToolInterrupts(\n { ...bag, __interrupt__: headlessInterrupts },\n tools,\n handledTools,\n {\n onTool,\n defer: (run) => {\n void Promise.resolve().then(run);\n },\n resumeSubmit: (command) =>\n controller.submit(null, {\n command,\n } as StreamSubmitOptions<StateType, ConfigurableType>),\n }\n );\n });\n });\n });\n }\n\n const handle: UseStreamReturn<T, InterruptType, ConfigurableType> = {\n values: values as UseStreamReturn<\n T,\n InterruptType,\n ConfigurableType\n >[\"values\"],\n messages,\n toolCalls,\n interrupts,\n interrupt,\n isLoading,\n isThreadLoading,\n error,\n threadId,\n hydrationPromise,\n subagents: subagentSignal as UseStreamReturn<\n T,\n InterruptType,\n ConfigurableType\n >[\"subagents\"],\n subgraphs: subgraphSignal,\n subgraphsByNode: subgraphByNodeSignal,\n submit: (input, submitOptions) => controller.submit(input, submitOptions),\n stop: (options) => controller.stop(options),\n disconnect: () => controller.disconnect(),\n respond: (response, options) => controller.respond(response, options),\n respondAll: (responsesById, options) =>\n controller.respondAll(responsesById, options),\n getThread: () => controller.getThread(),\n client,\n assistantId,\n [STREAM_CONTROLLER]: controller,\n };\n\n return handle;\n}\n\n/**\n * Helper used by the selector primitives to reach the underlying\n * {@link ChannelRegistry} from a stream handle. Kept internal —\n * application code should call `injectMessages`, `injectToolCalls`,\n * etc. instead of reading this directly.\n *\n * @internal\n */\nexport function getRegistry(\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n stream: UseStreamReturn<any, any, any>\n): ChannelRegistry {\n return stream[STREAM_CONTROLLER].registry;\n}\n\nexport type { ThreadStream };\n"],"mappings":";;;;;;;;;;;;AA0EA,MAAa,oBAAmC,OAAO,IACrD,gCACD;;;;;;;;;;AAqTD,SAAgB,UAKd,SACA,YACqD;CAsBrD,MAAM,QAAQ;CAEd,MAAM,mBACJ,MAAM,aAAa,QAAQ,OAAO,MAAM,cAAc;CACxD,MAAM,YAAY,MAAM;CAExB,MAAM,SACJ,MAAM,UACL,IAAIA,gCAAAA,OAAW;EACd,QAAQ,MAAM;EACd,QAAQ,MAAM;EACd,eAAe,MAAM;EACrB,gBAAgB,MAAM;EACvB,CAAC;CAIJ,MAAM,WAAW;CACjB,MAAM,cACJ,iBAAiB,UAAW,QAAQ,eAAe,WAAY;CAIjE,MAAM,uBAA8C;EAClD,MAAM,MAAM,MAAM;AAClB,OAAA,GAAA,cAAA,UAAa,IAAI,CACf,SAAA,GAAA,cAAA,gBACS,KAA2C,IAAI,KACvD;AAGH,UAAA,GAAA,cAAA,QADgC,OAAqC,KAC/C;KACpB;CAEJ,MAAM,aAAa,IAAIC,gCAAAA,iBAIrB;EACA;EAIQ;EACR,WAAA,GAAA,cAAA,iBAA0B,eAAe,CAAC;EAC1C;EACA,OAAO,mBAAmB,KAAA,IAAY,MAAM;EAC5C,kBAAkB,mBAAmB,KAAA,IAAY,MAAM;EACvD,YAAY,QAAQ;EACpB,WAAW,QAAQ;EACnB,aAAa,QAAQ;EACrB,eAAe,QAAQ;EACvB,aAAa,QAAQ;EACtB,CAAC;CAMF,MAAM,aAAa,WAAW,UAAU;CACxC,MAAM,MAAM,eAAA,GAAA,cAAA,QAAqBC,cAAAA,WAAW;AAC5C,KAAI,UAAU,WAAW;CAGzB,SAAS,UACP,WACA,aACW;EACX,MAAM,KAAA,GAAA,cAAA,QAAc,aAAa,CAAC;EAClC,MAAM,cAAc,gBAAgB;AAClC,KAAE,IAAI,aAAa,CAAC;IACpB;AACF,MAAI,UAAU,YAAY;AAC1B,UAAA,GAAA,cAAA,gBAAsB,GAAG,CAAC;;CAG5B,MAAM,aAAa,UACjB,WAAW,UAAU,WACrB,WAAW,UAAU,YACtB;CACD,MAAM,iBAAiB,UACrB,WAAW,cAAc,WACzB,WAAW,cAAc,YAC1B;CACD,MAAM,iBAAiB,UACrB,WAAW,cAAc,WACzB,WAAW,cAAc,YAC1B;CACD,MAAM,uBAAuB,UAC3B,WAAW,oBAAoB,WAC/B,WAAW,oBAAoB,YAChC;CAED,MAAM,UAAA,GAAA,cAAA,gBAAwB,YAAY,CAAC,OAAO;CAClD,MAAM,YAAA,GAAA,cAAA,gBAA0B,YAAY,CAAC,SAAS;CACtD,MAAM,aAAA,GAAA,cAAA,gBACE,YAAY,CAAC,UACpB;CACD,MAAM,cAAA,GAAA,cAAA,iBAAA,GAAA,yBAAA,iCAC4B,YAAY,CAAC,WAAW,CACzD;CACD,MAAM,aAAA,GAAA,cAAA,gBAA2B,YAAY,CAAC,GAAG;CACjD,MAAM,aAAA,GAAA,cAAA,gBAA2B,YAAY,CAAC,UAAU;CACxD,MAAM,mBAAA,GAAA,cAAA,gBAAiC,YAAY,CAAC,gBAAgB;CACpE,MAAM,SAAA,GAAA,cAAA,gBAAuB,YAAY,CAAC,MAAM;CAChD,MAAM,YAAA,GAAA,cAAA,gBAA0B,YAAY,CAAC,SAAS;CAMtD,MAAM,oBAAA,GAAA,cAAA,gBAAkC;AACtC,cAAY;AACZ,SAAO,WAAW;GAClB;CAaF,IAAI,uBAAA,GAAA,cAAA,iBADoC,eAAe,CAAC,IAAI;AAE5D,EAAA,GAAA,cAAA,cAAa;EACX,MAAM,OAAO,eAAe,IAAI;AAChC,MAAI,SAAS,oBAAqB;AAClC,wBAAsB;AACtB,GAAA,GAAA,cAAA,iBAAgB;AACT,cAAW,QAAQ,KAAK;IAC7B;GACF;CAGF,MAAM,QAAQ,QAAQ;CACtB,MAAM,SAAS,QAAQ;AACvB,KAAI,OAAO,QAAQ;EACjB,MAAM,+BAAe,IAAI,KAAa;AAGtC,GAAA,GAAA,cAAA,cAAa;AACX,kBAAe;AACf,IAAA,GAAA,cAAA,iBAAgB,aAAa,OAAO,CAAC;IACrC;AAEF,GAAA,GAAA,cAAA,cAAa;AACX,eAAY;AACZ,IAAA,GAAA,cAAA,iBAAgB;AACd,KAAA,GAAA,yBAAA,oCAAmC,oBAAoB;KACrD,MAAM,WAAW,YAAY;KAC7B,MAAM,MAAM,SAAS;KACrB,MAAM,qBACJ,SAAS;KACX,MAAM,mBAAmB,MAAM,QAAQ,KAAK,cAAc,GACrD,IAAI,gBACL,EAAE;KACN,MAAM,qBACJ,mBAAmB,SAAS,IACxB,qBACA;AACN,SAAI,mBAAmB,WAAW,EAAG;AACrC,MAAA,GAAA,yBAAA,oCACE;MAAE,GAAG;MAAK,eAAe;MAAoB,EAC7C,OACA,cACA;MACE;MACA,QAAQ,QAAQ;AACT,eAAQ,SAAS,CAAC,KAAK,IAAI;;MAElC,eAAe,YACb,WAAW,OAAO,MAAM,EACtB,SACD,CAAqD;MACzD,CACF;MACD;KACF;IACF;;AAqCJ,QAlCoE;EAC1D;EAKR;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA,WAAW;EAKX,WAAW;EACX,iBAAiB;EACjB,SAAS,OAAO,kBAAkB,WAAW,OAAO,OAAO,cAAc;EACzE,OAAO,YAAY,WAAW,KAAK,QAAQ;EAC3C,kBAAkB,WAAW,YAAY;EACzC,UAAU,UAAU,YAAY,WAAW,QAAQ,UAAU,QAAQ;EACrE,aAAa,eAAe,YAC1B,WAAW,WAAW,eAAe,QAAQ;EAC/C,iBAAiB,WAAW,WAAW;EACvC;EACA;GACC,oBAAoB;EACtB;;;;;;;;;;AAaH,SAAgB,YAEd,QACiB;AACjB,QAAO,OAAO,mBAAmB"}
|
package/dist/use-stream.d.cts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AgentServerOptions, ChannelRegistry, CustomAdapterOptions, InferStateType, InferSubagentStates, InferToolCalls, StreamController, StreamStopOptions, StreamSubmitOptions, SubagentDiscoverySnapshot, SubgraphDiscoverySnapshot, UseStreamOptions, WidenUpdateMessages } from "@langchain/langgraph-sdk/stream";
|
|
1
|
+
import { AgentServerOptions, ChannelRegistry, CustomAdapterOptions, InferStateType, InferSubagentStates, InferToolCalls, StreamController, StreamRespondAllOptions, StreamRespondOptions, StreamStopOptions, StreamSubmitOptions, SubagentDiscoverySnapshot, SubgraphDiscoverySnapshot, UseStreamOptions, WidenUpdateMessages } from "@langchain/langgraph-sdk/stream";
|
|
2
2
|
import { DestroyRef, Signal } from "@angular/core";
|
|
3
3
|
import { BaseMessage } from "@langchain/core/messages";
|
|
4
4
|
import { Client, Interrupt } from "@langchain/langgraph-sdk";
|
|
@@ -81,7 +81,7 @@ interface UseStreamReturn<T = Record<string, unknown>, InterruptType = unknown,
|
|
|
81
81
|
* namespace during the active thread. Populated from lifecycle /
|
|
82
82
|
* input events and seeded on hydration from `thread.getState()`.
|
|
83
83
|
* Cleared optimistically when a new run starts or an interrupt is
|
|
84
|
-
* resolved via {@link respond}
|
|
84
|
+
* resolved via {@link respond}.
|
|
85
85
|
*/
|
|
86
86
|
readonly interrupts: Signal<Interrupt<InterruptType>[]>;
|
|
87
87
|
/**
|
|
@@ -153,10 +153,7 @@ interface UseStreamReturn<T = Record<string, unknown>, InterruptType = unknown,
|
|
|
153
153
|
* Dispatch a new run on the bound thread.
|
|
154
154
|
*
|
|
155
155
|
* `input` is typed as `Partial<StateType>` so IDE autocompletion
|
|
156
|
-
* surfaces the state keys declared on the root primitive.
|
|
157
|
-
* `null` (or omit fields) when resuming an interrupt via
|
|
158
|
-
* `options.command.resume` — the server accepts a null payload
|
|
159
|
-
* in that case.
|
|
156
|
+
* surfaces the state keys declared on the root primitive.
|
|
160
157
|
*/
|
|
161
158
|
submit(input: WidenUpdateMessages<Partial<StateType>> | null | undefined, options?: StreamSubmitOptions<StateType, ConfigurableType>): Promise<void>;
|
|
162
159
|
/**
|
|
@@ -175,15 +172,67 @@ interface UseStreamReturn<T = Record<string, unknown>, InterruptType = unknown,
|
|
|
175
172
|
* Resume a pending protocol interrupt by sending a response payload
|
|
176
173
|
* back to the interrupted namespace.
|
|
177
174
|
*
|
|
178
|
-
* When `
|
|
179
|
-
*
|
|
180
|
-
* `
|
|
181
|
-
*
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
175
|
+
* When `options.interruptId` is omitted, walks `getThread()?.interrupts`
|
|
176
|
+
* from newest to oldest and resumes the first not yet resolved by a prior
|
|
177
|
+
* `respond()` call. That may be a root or subgraph interrupt and is
|
|
178
|
+
* **not** necessarily {@link interrupt} (`interrupts()[0]`, root-only).
|
|
179
|
+
* Safe when exactly one interrupt is pending; otherwise pass an explicit
|
|
180
|
+
* `options.interruptId` (and `options.namespace` for subgraph
|
|
181
|
+
* interrupts).
|
|
182
|
+
*
|
|
183
|
+
* The server validates `namespace` against the pending interrupt. Root
|
|
184
|
+
* interrupts use `namespace: []` (default when omitted). For subgraph
|
|
185
|
+
* interrupts, copy `namespace` from `getThread()?.interrupts`.
|
|
186
|
+
*
|
|
187
|
+
* @example
|
|
188
|
+
* ```ts
|
|
189
|
+
* // Single pending interrupt
|
|
190
|
+
* await stream.respond({ approved: true });
|
|
191
|
+
* ```
|
|
192
|
+
*
|
|
193
|
+
* @example
|
|
194
|
+
* ```ts
|
|
195
|
+
* // Multiple root interrupts
|
|
196
|
+
* for (const intr of stream.interrupts()) {
|
|
197
|
+
* await stream.respond(decide(intr.value), { interruptId: intr.id! });
|
|
198
|
+
* }
|
|
199
|
+
* ```
|
|
200
|
+
*
|
|
201
|
+
* @example
|
|
202
|
+
* ```ts
|
|
203
|
+
* // Subgraph interrupt — namespace from `getThread()`
|
|
204
|
+
* const thread = stream.getThread();
|
|
205
|
+
* for (const entry of thread?.interrupts ?? []) {
|
|
206
|
+
* await stream.respond(buildResponse(entry.payload), {
|
|
207
|
+
* interruptId: entry.interruptId,
|
|
208
|
+
* namespace: entry.namespace,
|
|
209
|
+
* });
|
|
210
|
+
* }
|
|
211
|
+
* ```
|
|
212
|
+
*
|
|
213
|
+
* To resume several interrupts pending at the same checkpoint in one
|
|
214
|
+
* command, use {@link respondAll}.
|
|
215
|
+
*/
|
|
216
|
+
respond(response: unknown, options?: StreamRespondOptions<ConfigurableType>): Promise<void>;
|
|
217
|
+
/**
|
|
218
|
+
* Resume several pending interrupts at the same checkpoint in a single
|
|
219
|
+
* command — required when a run pauses on multiple interrupts at once
|
|
220
|
+
* (e.g. parallel tool-authorization prompts), which sequential
|
|
221
|
+
* {@link respond} calls cannot handle. `responsesById` maps each pending
|
|
222
|
+
* `interruptId` to its response, so different interrupts can receive
|
|
223
|
+
* different payloads. Pass `options.config` / `options.metadata` to fold
|
|
224
|
+
* run-level config and metadata into the resumed run, mirroring
|
|
225
|
+
* `submit()`.
|
|
226
|
+
*
|
|
227
|
+
* @example
|
|
228
|
+
* ```ts
|
|
229
|
+
* await stream.respondAll({
|
|
230
|
+
* [interruptA.id]: { approved: true },
|
|
231
|
+
* [interruptB.id]: { approved: false },
|
|
232
|
+
* });
|
|
233
|
+
* ```
|
|
234
|
+
*/
|
|
235
|
+
respondAll(responsesById: Record<string, unknown>, options?: StreamRespondAllOptions<ConfigurableType>): Promise<void>;
|
|
187
236
|
/** LangGraph SDK client used to construct thread streams. */
|
|
188
237
|
readonly client: Client;
|
|
189
238
|
/** Assistant id the thread is bound to for its lifetime. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-stream.d.cts","names":[],"sources":["../src/use-stream.ts"],"mappings":";;;;;;;
|
|
1
|
+
{"version":3,"file":"use-stream.d.cts","names":[],"sources":["../src/use-stream.ts"],"mappings":";;;;;;;KAiDK,eAAA,mBAAkC,MAAA;AAAA,KAE3B,oBAAA,6BACV,kBAAA,CAAyB,SAAA,EAAW,eAAA;AAAA,KAE1B,sBAAA,6BACV,oBAAA,CAA2B,SAAA,EAAW,eAAA;AAAA,KAE5B,kBAAA,4BACiB,MAAA,qBACzB,gBAAA,CACF,SAAA,EACA,eAAA;;;;AAVF;;;;cAuBa,iBAAA;;;;;;;;;;AApBb;;;;;UAsCiB,eAAA,KACX,MAAA,8EAE8B,MAAA,8CACP,cAAA,CAAe,CAAA,oBACzB,mBAAA,CAAoB,CAAA;EA1CX;;;;;;;;AAE5B;;;EAF4B,SAwDjB,MAAA,EAAQ,MAAA,CAAO,SAAA;EAnDxB;;;;;;;;;;;;AAcF;;;;;AAkBA;;;EAhCE,SAwES,QAAA,EAAU,MAAA,CAAO,WAAA;EArCQ;;;;;;;;;;EAAA,SAgDzB,SAAA,EAAW,MAAA,CAAO,cAAA,CAAe,CAAA;EAAtB;;;;;;;EAAA,SAQX,UAAA,EAAY,MAAA,CAAO,SAAA,CAAU,aAAA;EAoBZ;;;;;EAAA,SAdjB,SAAA,EAAW,MAAA,CAAO,SAAA,CAAU,aAAA;EA6CvB;;;;;;EAAA,SAtCL,SAAA,EAAW,MAAA;EA8DW;;;;;;EAAA,SAvDtB,eAAA,EAAiB,MAAA;EAmEiB;;;;;EAAA,SA7DlC,KAAA,EAAO,MAAA;EA0HiB;;;;;EAAA,SApHxB,QAAA,EAAU,MAAA;EA4IhB;;;;;;EAAA,SArIM,gBAAA,EAAkB,MAAA,CAAO,OAAA;EAsJxB;;;;;EAAA,SA9ID,SAAA,EAAW,MAAA,CAClB,WAAA,OACQ,cAAA,yCAEI,cAAA,WACV,yBAAA;EA5GJ;;;;;;;;;;;EAAA,SA0HS,SAAA,EAAW,MAAA,CAAO,WAAA,SAAoB,yBAAA;EArF5B;;;;;;;EAAA,SA6FV,eAAA,EAAiB,MAAA,CACxB,WAAA,kBAA6B,yBAAA;EA3EH;;;;;;EAqF5B,MAAA,CACE,KAAA,EAAO,mBAAA,CAAoB,OAAA,CAAQ,SAAA,uBACnC,OAAA,GAAU,mBAAA,CAAoB,SAAA,EAAW,gBAAA,IACxC,OAAA;EA3EiB;;;;;;EAkFpB,IAAA,CAAK,OAAA,GAAU,iBAAA,GAAoB,OAAA;EAxD1B;;;;EA6DT,UAAA,IAAc,OAAA;EApDZ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAkGF,OAAA,CACE,QAAA,WACA,OAAA,GAAU,oBAAA,CAAqB,gBAAA,IAC9B,OAAA;EAwCO;;;;;;;AAaZ;;;;;AAMA;;;;;;EAvCE,UAAA,CACE,aAAA,EAAe,MAAA,mBACf,OAAA,GAAU,uBAAA,CAAwB,gBAAA,IACjC,OAAA;EAwCiC;EAAA,SApC3B,MAAA,EAAQ,MAAA;EAoCA;EAAA,SAlCR,WAAA;EA+BT;;;;;;EAvBA,SAAA,IAAa,cAAA;EA0BQ;EAAA,UAvBX,iBAAA,GAAoB,gBAAA,CAC5B,SAAA,EACA,aAAA,EACA,gBAAA;AAAA;;AA2BJ;;;;KAjBY,SAAA,GAAY,eAAA;;;;;KAMZ,SAAA,KACN,MAAA,8EAE8B,MAAA,qBAChC,eAAA,CAAgB,CAAA,EAAG,aAAA,EAAe,gBAAA;;;;;;KAO1B,eAAA,KACN,MAAA,8EAE8B,MAAA,qBAChC,eAAA,CAAgB,CAAA,EAAG,aAAA,EAAe,gBAAA;;;;;;;AAWtC;;;iBAAgB,SAAA,KACV,MAAA,8EAE8B,MAAA,kBAAA,CAElC,OAAA,EAAS,kBAAA,CAAiB,cAAA,CAAe,CAAA,IACzC,UAAA,GAAa,UAAA,GACZ,eAAA,CAAgB,CAAA,EAAG,aAAA,EAAe,gBAAA"}
|
package/dist/use-stream.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { DestroyRef, Signal } from "@angular/core";
|
|
2
2
|
import { Client, Interrupt } from "@langchain/langgraph-sdk";
|
|
3
3
|
import { ThreadStream as ThreadStream$1 } from "@langchain/langgraph-sdk/client";
|
|
4
|
-
import { AgentServerOptions, ChannelRegistry, CustomAdapterOptions, InferStateType, InferSubagentStates, InferToolCalls, StreamController, StreamStopOptions, StreamSubmitOptions, SubagentDiscoverySnapshot, SubgraphDiscoverySnapshot, UseStreamOptions, WidenUpdateMessages } from "@langchain/langgraph-sdk/stream";
|
|
4
|
+
import { AgentServerOptions, ChannelRegistry, CustomAdapterOptions, InferStateType, InferSubagentStates, InferToolCalls, StreamController, StreamRespondAllOptions, StreamRespondOptions, StreamStopOptions, StreamSubmitOptions, SubagentDiscoverySnapshot, SubgraphDiscoverySnapshot, UseStreamOptions, WidenUpdateMessages } from "@langchain/langgraph-sdk/stream";
|
|
5
5
|
import { BaseMessage } from "@langchain/core/messages";
|
|
6
6
|
|
|
7
7
|
//#region src/use-stream.d.ts
|
|
@@ -81,7 +81,7 @@ interface UseStreamReturn<T = Record<string, unknown>, InterruptType = unknown,
|
|
|
81
81
|
* namespace during the active thread. Populated from lifecycle /
|
|
82
82
|
* input events and seeded on hydration from `thread.getState()`.
|
|
83
83
|
* Cleared optimistically when a new run starts or an interrupt is
|
|
84
|
-
* resolved via {@link respond}
|
|
84
|
+
* resolved via {@link respond}.
|
|
85
85
|
*/
|
|
86
86
|
readonly interrupts: Signal<Interrupt<InterruptType>[]>;
|
|
87
87
|
/**
|
|
@@ -153,10 +153,7 @@ interface UseStreamReturn<T = Record<string, unknown>, InterruptType = unknown,
|
|
|
153
153
|
* Dispatch a new run on the bound thread.
|
|
154
154
|
*
|
|
155
155
|
* `input` is typed as `Partial<StateType>` so IDE autocompletion
|
|
156
|
-
* surfaces the state keys declared on the root primitive.
|
|
157
|
-
* `null` (or omit fields) when resuming an interrupt via
|
|
158
|
-
* `options.command.resume` — the server accepts a null payload
|
|
159
|
-
* in that case.
|
|
156
|
+
* surfaces the state keys declared on the root primitive.
|
|
160
157
|
*/
|
|
161
158
|
submit(input: WidenUpdateMessages<Partial<StateType>> | null | undefined, options?: StreamSubmitOptions<StateType, ConfigurableType>): Promise<void>;
|
|
162
159
|
/**
|
|
@@ -175,15 +172,67 @@ interface UseStreamReturn<T = Record<string, unknown>, InterruptType = unknown,
|
|
|
175
172
|
* Resume a pending protocol interrupt by sending a response payload
|
|
176
173
|
* back to the interrupted namespace.
|
|
177
174
|
*
|
|
178
|
-
* When `
|
|
179
|
-
*
|
|
180
|
-
* `
|
|
181
|
-
*
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
175
|
+
* When `options.interruptId` is omitted, walks `getThread()?.interrupts`
|
|
176
|
+
* from newest to oldest and resumes the first not yet resolved by a prior
|
|
177
|
+
* `respond()` call. That may be a root or subgraph interrupt and is
|
|
178
|
+
* **not** necessarily {@link interrupt} (`interrupts()[0]`, root-only).
|
|
179
|
+
* Safe when exactly one interrupt is pending; otherwise pass an explicit
|
|
180
|
+
* `options.interruptId` (and `options.namespace` for subgraph
|
|
181
|
+
* interrupts).
|
|
182
|
+
*
|
|
183
|
+
* The server validates `namespace` against the pending interrupt. Root
|
|
184
|
+
* interrupts use `namespace: []` (default when omitted). For subgraph
|
|
185
|
+
* interrupts, copy `namespace` from `getThread()?.interrupts`.
|
|
186
|
+
*
|
|
187
|
+
* @example
|
|
188
|
+
* ```ts
|
|
189
|
+
* // Single pending interrupt
|
|
190
|
+
* await stream.respond({ approved: true });
|
|
191
|
+
* ```
|
|
192
|
+
*
|
|
193
|
+
* @example
|
|
194
|
+
* ```ts
|
|
195
|
+
* // Multiple root interrupts
|
|
196
|
+
* for (const intr of stream.interrupts()) {
|
|
197
|
+
* await stream.respond(decide(intr.value), { interruptId: intr.id! });
|
|
198
|
+
* }
|
|
199
|
+
* ```
|
|
200
|
+
*
|
|
201
|
+
* @example
|
|
202
|
+
* ```ts
|
|
203
|
+
* // Subgraph interrupt — namespace from `getThread()`
|
|
204
|
+
* const thread = stream.getThread();
|
|
205
|
+
* for (const entry of thread?.interrupts ?? []) {
|
|
206
|
+
* await stream.respond(buildResponse(entry.payload), {
|
|
207
|
+
* interruptId: entry.interruptId,
|
|
208
|
+
* namespace: entry.namespace,
|
|
209
|
+
* });
|
|
210
|
+
* }
|
|
211
|
+
* ```
|
|
212
|
+
*
|
|
213
|
+
* To resume several interrupts pending at the same checkpoint in one
|
|
214
|
+
* command, use {@link respondAll}.
|
|
215
|
+
*/
|
|
216
|
+
respond(response: unknown, options?: StreamRespondOptions<ConfigurableType>): Promise<void>;
|
|
217
|
+
/**
|
|
218
|
+
* Resume several pending interrupts at the same checkpoint in a single
|
|
219
|
+
* command — required when a run pauses on multiple interrupts at once
|
|
220
|
+
* (e.g. parallel tool-authorization prompts), which sequential
|
|
221
|
+
* {@link respond} calls cannot handle. `responsesById` maps each pending
|
|
222
|
+
* `interruptId` to its response, so different interrupts can receive
|
|
223
|
+
* different payloads. Pass `options.config` / `options.metadata` to fold
|
|
224
|
+
* run-level config and metadata into the resumed run, mirroring
|
|
225
|
+
* `submit()`.
|
|
226
|
+
*
|
|
227
|
+
* @example
|
|
228
|
+
* ```ts
|
|
229
|
+
* await stream.respondAll({
|
|
230
|
+
* [interruptA.id]: { approved: true },
|
|
231
|
+
* [interruptB.id]: { approved: false },
|
|
232
|
+
* });
|
|
233
|
+
* ```
|
|
234
|
+
*/
|
|
235
|
+
respondAll(responsesById: Record<string, unknown>, options?: StreamRespondAllOptions<ConfigurableType>): Promise<void>;
|
|
187
236
|
/** LangGraph SDK client used to construct thread streams. */
|
|
188
237
|
readonly client: Client;
|
|
189
238
|
/** Assistant id the thread is bound to for its lifetime. */
|
package/dist/use-stream.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-stream.d.ts","names":[],"sources":["../src/use-stream.ts"],"mappings":";;;;;;;
|
|
1
|
+
{"version":3,"file":"use-stream.d.ts","names":[],"sources":["../src/use-stream.ts"],"mappings":";;;;;;;KAiDK,eAAA,mBAAkC,MAAA;AAAA,KAE3B,oBAAA,6BACV,kBAAA,CAAyB,SAAA,EAAW,eAAA;AAAA,KAE1B,sBAAA,6BACV,oBAAA,CAA2B,SAAA,EAAW,eAAA;AAAA,KAE5B,kBAAA,4BACiB,MAAA,qBACzB,gBAAA,CACF,SAAA,EACA,eAAA;;;;AAVF;;;;cAuBa,iBAAA;;;;;;;;;;AApBb;;;;;UAsCiB,eAAA,KACX,MAAA,8EAE8B,MAAA,8CACP,cAAA,CAAe,CAAA,oBACzB,mBAAA,CAAoB,CAAA;EA1CX;;;;;;;;AAE5B;;;EAF4B,SAwDjB,MAAA,EAAQ,MAAA,CAAO,SAAA;EAnDxB;;;;;;;;;;;;AAcF;;;;;AAkBA;;;EAhCE,SAwES,QAAA,EAAU,MAAA,CAAO,WAAA;EArCQ;;;;;;;;;;EAAA,SAgDzB,SAAA,EAAW,MAAA,CAAO,cAAA,CAAe,CAAA;EAAtB;;;;;;;EAAA,SAQX,UAAA,EAAY,MAAA,CAAO,SAAA,CAAU,aAAA;EAoBZ;;;;;EAAA,SAdjB,SAAA,EAAW,MAAA,CAAO,SAAA,CAAU,aAAA;EA6CvB;;;;;;EAAA,SAtCL,SAAA,EAAW,MAAA;EA8DW;;;;;;EAAA,SAvDtB,eAAA,EAAiB,MAAA;EAmEiB;;;;;EAAA,SA7DlC,KAAA,EAAO,MAAA;EA0HiB;;;;;EAAA,SApHxB,QAAA,EAAU,MAAA;EA4IhB;;;;;;EAAA,SArIM,gBAAA,EAAkB,MAAA,CAAO,OAAA;EAsJxB;;;;;EAAA,SA9ID,SAAA,EAAW,MAAA,CAClB,WAAA,OACQ,cAAA,yCAEI,cAAA,WACV,yBAAA;EA5GJ;;;;;;;;;;;EAAA,SA0HS,SAAA,EAAW,MAAA,CAAO,WAAA,SAAoB,yBAAA;EArF5B;;;;;;;EAAA,SA6FV,eAAA,EAAiB,MAAA,CACxB,WAAA,kBAA6B,yBAAA;EA3EH;;;;;;EAqF5B,MAAA,CACE,KAAA,EAAO,mBAAA,CAAoB,OAAA,CAAQ,SAAA,uBACnC,OAAA,GAAU,mBAAA,CAAoB,SAAA,EAAW,gBAAA,IACxC,OAAA;EA3EiB;;;;;;EAkFpB,IAAA,CAAK,OAAA,GAAU,iBAAA,GAAoB,OAAA;EAxD1B;;;;EA6DT,UAAA,IAAc,OAAA;EApDZ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAkGF,OAAA,CACE,QAAA,WACA,OAAA,GAAU,oBAAA,CAAqB,gBAAA,IAC9B,OAAA;EAwCO;;;;;;;AAaZ;;;;;AAMA;;;;;;EAvCE,UAAA,CACE,aAAA,EAAe,MAAA,mBACf,OAAA,GAAU,uBAAA,CAAwB,gBAAA,IACjC,OAAA;EAwCiC;EAAA,SApC3B,MAAA,EAAQ,MAAA;EAoCA;EAAA,SAlCR,WAAA;EA+BT;;;;;;EAvBA,SAAA,IAAa,cAAA;EA0BQ;EAAA,UAvBX,iBAAA,GAAoB,gBAAA,CAC5B,SAAA,EACA,aAAA,EACA,gBAAA;AAAA;;AA2BJ;;;;KAjBY,SAAA,GAAY,eAAA;;;;;KAMZ,SAAA,KACN,MAAA,8EAE8B,MAAA,qBAChC,eAAA,CAAgB,CAAA,EAAG,aAAA,EAAe,gBAAA;;;;;;KAO1B,eAAA,KACN,MAAA,8EAE8B,MAAA,qBAChC,eAAA,CAAgB,CAAA,EAAG,aAAA,EAAe,gBAAA;;;;;;;AAWtC;;;iBAAgB,SAAA,KACV,MAAA,8EAE8B,MAAA,kBAAA,CAElC,OAAA,EAAS,kBAAA,CAAiB,cAAA,CAAe,CAAA,IACzC,UAAA,GAAa,UAAA,GACZ,eAAA,CAAgB,CAAA,EAAG,aAAA,EAAe,gBAAA"}
|
package/dist/use-stream.js
CHANGED
|
@@ -136,7 +136,8 @@ function useStream(options, destroyRef) {
|
|
|
136
136
|
submit: (input, submitOptions) => controller.submit(input, submitOptions),
|
|
137
137
|
stop: (options) => controller.stop(options),
|
|
138
138
|
disconnect: () => controller.disconnect(),
|
|
139
|
-
respond: (response,
|
|
139
|
+
respond: (response, options) => controller.respond(response, options),
|
|
140
|
+
respondAll: (responsesById, options) => controller.respondAll(responsesById, options),
|
|
140
141
|
getThread: () => controller.getThread(),
|
|
141
142
|
client,
|
|
142
143
|
assistantId,
|
package/dist/use-stream.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-stream.js","names":["ClientCtor"],"sources":["../src/use-stream.ts"],"sourcesContent":["import {\n DestroyRef,\n computed,\n effect,\n inject,\n isSignal,\n signal,\n untracked,\n type Signal,\n} from \"@angular/core\";\nimport type { BaseMessage } from \"@langchain/core/messages\";\nimport type { Client, Interrupt } from \"@langchain/langgraph-sdk\";\nimport {\n filterOutHeadlessToolInterrupts,\n flushPendingHeadlessToolInterrupts,\n scheduleCoalescedHeadlessToolFlush,\n type AnyHeadlessToolImplementation,\n type OnToolCallback,\n} from \"@langchain/langgraph-sdk\";\nimport {\n Client as ClientCtor,\n type ClientConfig,\n type ThreadStream,\n} from \"@langchain/langgraph-sdk/client\";\nimport {\n StreamController,\n type AgentServerAdapter,\n type AgentServerOptions as StreamAgentServerOptions,\n type ChannelRegistry,\n type CustomAdapterOptions as StreamCustomAdapterOptions,\n type InferStateType,\n type InferToolCalls,\n type InferSubagentStates,\n type RootSnapshot,\n type RunCompletedInfo,\n type RunExecutionInfo,\n type StreamStopOptions,\n type StreamSubmitOptions,\n type SubagentDiscoverySnapshot,\n type SubagentMap,\n type SubgraphByNodeMap,\n type SubgraphDiscoverySnapshot,\n type SubgraphMap,\n type UseStreamOptions as StreamUseStreamOptions,\n type WidenUpdateMessages,\n} from \"@langchain/langgraph-sdk/stream\";\n\ntype AngularThreadId = string | null | Signal<string | null | undefined>;\n\nexport type AgentServerOptions<StateType extends object> =\n StreamAgentServerOptions<StateType, AngularThreadId>;\n\nexport type CustomAdapterOptions<StateType extends object> =\n StreamCustomAdapterOptions<StateType, AngularThreadId, string>;\n\nexport type UseStreamOptions<\n StateType extends object = Record<string, unknown>,\n> = StreamUseStreamOptions<\n StateType,\n AngularThreadId,\n string | undefined,\n string | undefined,\n string\n>;\n\n/**\n * Private field on the handle that carries the\n * {@link StreamController} reference. Selector primitives read this\n * to reach the shared {@link ChannelRegistry}. Use the companion\n * `inject*` selectors (`injectMessages`, `injectToolCalls`,\n * `injectValues`, …) instead of reading this directly.\n */\nexport const STREAM_CONTROLLER: unique symbol = Symbol.for(\n \"@langchain/angular/controller\"\n);\n\n/**\n * Return shape of {@link useStream} — the Angular `StreamApi`.\n *\n * Reactivity primitives follow Angular conventions:\n *\n * - Data projections are `Signal<T>`; call them as functions in\n * templates (`stream.messages()`). They are snapshots — never\n * mutate the returned arrays / maps.\n * - Imperative methods (`submit` / `stop` / `respond`) are plain\n * functions. No `WritableSignal`s are exposed on the root handle.\n * - Identity values captured at construction time (`client`,\n * `assistantId`) are exposed as plain values; remount the\n * component to swap them.\n */\nexport interface UseStreamReturn<\n T = Record<string, unknown>,\n InterruptType = unknown,\n ConfigurableType extends object = Record<string, unknown>,\n StateType extends object = InferStateType<T>,\n SubagentStates = InferSubagentStates<T>,\n> {\n // ----- always-on root projections -----\n /**\n * The most recent `values`-channel snapshot emitted at the root\n * namespace — i.e. the thread-level state as the server sees it\n * after each superstep. Updated on every root `values` event, not\n * on token-level deltas: if you render `stream.values().messages`\n * directly you'll see full turns appear at once instead of\n * streaming token-by-token. Use {@link messages} (or\n * `injectMessages`) for the token-streamed view.\n *\n * Equivalent to calling `injectValues(stream)`.\n */\n readonly values: Signal<StateType>;\n /**\n * The root message projection. Assembled from two sources and\n * merged in real time:\n *\n * 1. `messages`-channel deltas — token-level streaming events\n * (`message-start`, `content-block-delta`, `message-finish`)\n * emitted by the runtime. These drive live, token-by-token\n * updates.\n * 2. `values.messages` snapshots — the authoritative ordering\n * and any messages the agent produces without token streaming\n * (human turns, tool results, echoes from subagents).\n *\n * If the backend only emits `values` events (no `messages`\n * channel), every message will appear fully-formed on each\n * values update rather than streaming. This is a backend/runtime\n * concern — the Angular layer faithfully renders whatever the\n * server sends.\n *\n * Equivalent to calling `injectMessages(stream)` with no target.\n */\n readonly messages: Signal<BaseMessage[]>;\n /**\n * Root-namespace tool calls assembled from the `tools` channel.\n * Each entry is a fully parsed {@link AssembledToolCall} with\n * name, args, and id — suitable for rendering approval UIs or\n * forwarding to headless tool handlers.\n *\n * When the stream is typed with an agent brand or tool list,\n * entries are narrowed via {@link InferToolCalls}. Equivalent to\n * calling `injectToolCalls(stream)` with no target.\n */\n readonly toolCalls: Signal<InferToolCalls<T>[]>;\n /**\n * All unresolved protocol interrupts observed on the root\n * namespace during the active thread. Populated from lifecycle /\n * input events and seeded on hydration from `thread.getState()`.\n * Cleared optimistically when a new run starts or an interrupt is\n * resolved via {@link respond} / `submit({ command: { resume } })`.\n */\n readonly interrupts: Signal<Interrupt<InterruptType>[]>;\n /**\n * Convenience alias for {@link interrupts}[0] — the primary\n * interrupt most UIs should act on when only one is pending.\n * `undefined` when no interrupt is active.\n */\n readonly interrupt: Signal<Interrupt<InterruptType> | undefined>;\n /**\n * `true` while a run is active or being started on the current\n * thread. Driven by root-namespace lifecycle events (`running` →\n * `true`, terminal phases → `false`). Use this to disable submit\n * buttons and show in-flight spinners.\n */\n readonly isLoading: Signal<boolean>;\n /**\n * `true` while the initial `thread.getState()` hydration for the\n * active thread is in flight. Distinct from {@link isLoading} —\n * thread loading covers the one-time fetch that seeds\n * {@link values} / {@link messages} before any user submit.\n */\n readonly isThreadLoading: Signal<boolean>;\n /**\n * The last error observed on the active run or hydration attempt.\n * `undefined` when no error has occurred. Cleared optimistically\n * when a new {@link submit} starts.\n */\n readonly error: Signal<unknown>;\n /**\n * Id of the thread the controller is bound to. `null` until the\n * first {@link submit} creates or selects a thread (or until an\n * explicit `threadId` option is provided and hydrated).\n */\n readonly threadId: Signal<string | null>;\n /**\n * Promise that settles when the active thread's initial hydration\n * completes. Exposed so SSR/render-before-flush pipelines can\n * `await stream.hydrationPromise()` before serialising. A fresh\n * promise is installed on every `threadId` change.\n */\n readonly hydrationPromise: Signal<Promise<void>>;\n\n // ----- always-on discovery -----\n /**\n * Subagents discovered on the root run. For DeepAgent-typed\n * streams the key set is narrowed to the subagent names declared\n * on the agent brand (`keyof InferSubagentStates<T>`).\n */\n readonly subagents: Signal<\n ReadonlyMap<\n keyof SubagentStates & string extends never\n ? string\n : keyof SubagentStates & string,\n SubagentDiscoverySnapshot\n >\n >;\n /**\n * Subgraphs discovered on the root run.\n *\n * A namespace is classified as a subgraph iff at least one\n * strictly-deeper namespace has been observed with it as a prefix.\n * This is inferred from the lifecycle event stream — plain function\n * nodes (`orchestrator`, `writer` in the nested-stategraph example)\n * never appear here even though the server emits namespaced\n * lifecycle events for them. Promotion is monotonic and retroactive;\n * an entry appears as soon as the first descendant event lands.\n */\n readonly subgraphs: Signal<ReadonlyMap<string, SubgraphDiscoverySnapshot>>;\n /**\n * Subgraphs indexed by the graph node that produced them\n * (`addNode(\"visualizer_0\", …)`). Each value is an array because\n * parallel fan-outs and loops can spawn multiple invocations of\n * the same node; arrays preserve insertion order. Updates in\n * lock-step with {@link subgraphs}.\n */\n readonly subgraphsByNode: Signal<\n ReadonlyMap<string, readonly SubgraphDiscoverySnapshot[]>\n >;\n\n // ----- imperatives -----\n /**\n * Dispatch a new run on the bound thread.\n *\n * `input` is typed as `Partial<StateType>` so IDE autocompletion\n * surfaces the state keys declared on the root primitive. Pass\n * `null` (or omit fields) when resuming an interrupt via\n * `options.command.resume` — the server accepts a null payload\n * in that case.\n */\n submit(\n input: WidenUpdateMessages<Partial<StateType>> | null | undefined,\n options?: StreamSubmitOptions<StateType, ConfigurableType>\n ): Promise<void>;\n /**\n * Stop the active run on the current thread. By default cancels the\n * run server-side and disconnects the client; pass `{ cancel: false }`\n * or use {@link disconnect} for join/rejoin. Sets {@link isLoading} to\n * `false` immediately; {@link values} and {@link messages} are preserved.\n */\n stop(options?: StreamStopOptions): Promise<void>;\n /**\n * Disconnect the client without cancelling the run server-side.\n * Alias for `stop({ cancel: false })`.\n */\n disconnect(): Promise<void>;\n /**\n * Resume a pending protocol interrupt by sending a response payload\n * back to the interrupted namespace.\n *\n * When `target` is omitted, responds to the latest unresolved\n * interrupt in {@link interrupts}. Pass an explicit\n * `{ interruptId, namespace? }` when multiple interrupts are\n * pending or the interrupt lives in a subgraph namespace.\n */\n respond(\n response: unknown,\n target?: { interruptId: string; namespace?: string[] }\n ): Promise<void>;\n\n // ----- identity -----\n /** LangGraph SDK client used to construct thread streams. */\n readonly client: Client;\n /** Assistant id the thread is bound to for its lifetime. */\n readonly assistantId: string;\n\n /**\n * Returns the bound {@link ThreadStream}, if one exists (`undefined`\n * until the thread is hydrated or the first submit completes). Prefer\n * the projections and selector primitives for UI work; use this for\n * low-level protocol access (raw subscriptions, state commands, etc.).\n */\n getThread(): ThreadStream | undefined;\n\n /** @internal Used by selector primitives. */\n readonly [STREAM_CONTROLLER]: StreamController<\n StateType,\n InterruptType,\n ConfigurableType\n >;\n}\n\n/**\n * Erased handle useful as a parameter type for helper components that\n * pass a `stream` through to selector primitives without reading\n * `values` directly. Mirrors the React/Vue `AnyStream` alias.\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport type AnyStream = UseStreamReturn<any, any, any>;\n\n/**\n * Convenience alias — the fully-resolved return type of\n * {@link useStream} for a given source type `T`.\n */\nexport type StreamApi<\n T = Record<string, unknown>,\n InterruptType = unknown,\n ConfigurableType extends object = Record<string, unknown>,\n> = UseStreamReturn<T, InterruptType, ConfigurableType>;\n\n/**\n * React-compatible alias for the fully-resolved stream handle type.\n * Angular docs prefer {@link StreamApi}, but shared libraries can use\n * this name across framework bindings.\n */\nexport type UseStreamResult<\n T = Record<string, unknown>,\n InterruptType = unknown,\n ConfigurableType extends object = Record<string, unknown>,\n> = UseStreamReturn<T, InterruptType, ConfigurableType>;\n\n/**\n * Framework-free factory that constructs a {@link StreamController}\n * and wraps its stores in Angular Signals. Callers must supply the\n * {@link DestroyRef} that owns the controller's lifetime — it's\n * already captured by the public `injectStream` helper.\n *\n * Exported for advanced callers (e.g. testing utilities, custom\n * factories) that prefer to manage injection scope themselves.\n */\nexport function useStream<\n T = Record<string, unknown>,\n InterruptType = unknown,\n ConfigurableType extends object = Record<string, unknown>,\n>(\n options: UseStreamOptions<InferStateType<T>>,\n destroyRef?: DestroyRef\n): UseStreamReturn<T, InterruptType, ConfigurableType> {\n type StateType = InferStateType<T>;\n\n interface OptionsBag {\n assistantId?: string;\n threadId?: string | null | Signal<string | null | undefined>;\n client?: Client;\n apiUrl?: string;\n apiKey?: string;\n callerOptions?: ClientConfig[\"callerOptions\"];\n defaultHeaders?: ClientConfig[\"defaultHeaders\"];\n transport?: \"sse\" | \"websocket\" | AgentServerAdapter;\n fetch?: typeof fetch;\n webSocketFactory?: (url: string) => WebSocket;\n onThreadId?: (threadId: string) => void;\n onCreated?: (info: RunExecutionInfo) => void;\n onCompleted?: (info: RunCompletedInfo) => void;\n initialValues?: StateType;\n messagesKey?: string;\n tools?: AnyHeadlessToolImplementation[];\n onTool?: OnToolCallback;\n }\n const asBag = options as OptionsBag;\n\n const hasCustomAdapter =\n asBag.transport != null && typeof asBag.transport !== \"string\";\n const transport = asBag.transport;\n\n const client: Client =\n asBag.client ??\n (new ClientCtor({\n apiUrl: asBag.apiUrl,\n apiKey: asBag.apiKey,\n callerOptions: asBag.callerOptions,\n defaultHeaders: asBag.defaultHeaders,\n }) as unknown as Client);\n\n // Custom adapters may omit `assistantId`; the controller still\n // requires one so it has something to forward to `threads.stream`.\n const sentinel = \"_\";\n const assistantId =\n \"assistantId\" in options ? (options.assistantId ?? sentinel) : sentinel;\n\n // Normalize threadId input to a signal — callers may pass plain\n // values, nulls, or their own signals.\n const threadIdInput: Signal<string | null> = (() => {\n const raw = asBag.threadId;\n if (isSignal(raw)) {\n return computed(\n () => (raw as Signal<string | null | undefined>)() ?? null\n );\n }\n const initial: string | null = (raw as string | null | undefined) ?? null;\n return signal(initial) as unknown as Signal<string | null>;\n })();\n\n const controller = new StreamController<\n StateType,\n InterruptType,\n ConfigurableType\n >({\n assistantId,\n // Cast: the runtime `Client` is state-shape agnostic, but the\n // controller declares `client: Client<StateType>` for its own\n // typings. Same cast is applied in the React/Vue bindings.\n client: client as unknown as Client<StateType>,\n threadId: untracked(() => threadIdInput()),\n transport,\n fetch: hasCustomAdapter ? undefined : asBag.fetch,\n webSocketFactory: hasCustomAdapter ? undefined : asBag.webSocketFactory,\n onThreadId: options.onThreadId,\n onCreated: options.onCreated,\n onCompleted: options.onCompleted,\n initialValues: options.initialValues,\n messagesKey: options.messagesKey,\n });\n\n // Deferred dispose — matches the React `useEffect(() =>\n // controller.activate())` and Vue `onScopeDispose(deactivate)`\n // patterns. HMR / scope-reuse scenarios stay clean because\n // `activate()` cancels the pending dispose if the scope survives.\n const deactivate = controller.activate();\n const ref = destroyRef ?? inject(DestroyRef);\n ref.onDestroy(deactivate);\n\n // ─── Reactivity bridge: StreamStore → Signal ────────────────────────\n function bindStore<S>(\n subscribe: (listener: () => void) => () => void,\n getSnapshot: () => S\n ): Signal<S> {\n const s = signal<S>(getSnapshot());\n const unsubscribe = subscribe(() => {\n s.set(getSnapshot());\n });\n ref.onDestroy(unsubscribe);\n return computed(() => s());\n }\n\n const rootSignal = bindStore<RootSnapshot<StateType, InterruptType>>(\n controller.rootStore.subscribe,\n controller.rootStore.getSnapshot\n );\n const subagentSignal = bindStore<SubagentMap>(\n controller.subagentStore.subscribe,\n controller.subagentStore.getSnapshot\n );\n const subgraphSignal = bindStore<SubgraphMap>(\n controller.subgraphStore.subscribe,\n controller.subgraphStore.getSnapshot\n );\n const subgraphByNodeSignal = bindStore<SubgraphByNodeMap>(\n controller.subgraphByNodeStore.subscribe,\n controller.subgraphByNodeStore.getSnapshot\n );\n\n const values = computed(() => rootSignal().values);\n const messages = computed(() => rootSignal().messages);\n const toolCalls = computed(\n () => rootSignal().toolCalls as InferToolCalls<T>[]\n );\n const interrupts = computed(() =>\n filterOutHeadlessToolInterrupts(rootSignal().interrupts)\n );\n const interrupt = computed(() => interrupts()[0]);\n const isLoading = computed(() => rootSignal().isLoading);\n const isThreadLoading = computed(() => rootSignal().isThreadLoading);\n const error = computed(() => rootSignal().error);\n const threadId = computed(() => rootSignal().threadId);\n\n // `hydrationPromise` is a property on the controller that gets\n // swapped on every `hydrate()` call. Exposing it as a signal lets\n // templates `await stream.hydrationPromise()` reactively; we\n // refresh the reference when the root store settles a new promise.\n const hydrationPromise = computed(() => {\n rootSignal();\n return controller.hydrationPromise;\n });\n\n // ─── threadId reactivity ────────────────────────────────────────────\n //\n // Re-hydrate whenever the caller's threadId input changes after\n // construction. The initial hydrate already fired synchronously in\n // the controller constructor, so we compare against the snapshot\n // captured at construction time rather than blindly skipping the\n // first run — in Angular, `@Input()` bindings apply *between*\n // construction and the first effect tick, so the first read can\n // legitimately be a different (updated) value that needs to\n // hydrate.\n const initialThreadId = untracked(() => threadIdInput()) ?? null;\n let lastAppliedThreadId: string | null = initialThreadId;\n effect(() => {\n const next = threadIdInput() ?? null;\n if (next === lastAppliedThreadId) return;\n lastAppliedThreadId = next;\n untracked(() => {\n void controller.hydrate(next);\n });\n });\n\n // ─── Headless-tool handling ─────────────────────────────────────────\n const tools = options.tools;\n const onTool = options.onTool;\n if (tools?.length) {\n const handledTools = new Set<string>();\n\n // Clear the dedup set whenever the thread id changes.\n effect(() => {\n threadIdInput();\n untracked(() => handledTools.clear());\n });\n\n effect(() => {\n rootSignal();\n untracked(() => {\n scheduleCoalescedHeadlessToolFlush(handledTools, () => {\n const snapshot = rootSignal();\n const bag = snapshot.values as unknown as Record<string, unknown>;\n const protocolInterrupts =\n snapshot.interrupts as unknown as Interrupt[];\n const valuesInterrupts = Array.isArray(bag?.__interrupt__)\n ? (bag.__interrupt__ as Interrupt[])\n : [];\n const headlessInterrupts =\n protocolInterrupts.length > 0\n ? protocolInterrupts\n : valuesInterrupts;\n if (headlessInterrupts.length === 0) return;\n flushPendingHeadlessToolInterrupts(\n { ...bag, __interrupt__: headlessInterrupts },\n tools,\n handledTools,\n {\n onTool,\n defer: (run) => {\n void Promise.resolve().then(run);\n },\n resumeSubmit: (command) =>\n controller.submit(null, {\n command,\n } as StreamSubmitOptions<StateType, ConfigurableType>),\n }\n );\n });\n });\n });\n }\n\n const handle: UseStreamReturn<T, InterruptType, ConfigurableType> = {\n values: values as UseStreamReturn<\n T,\n InterruptType,\n ConfigurableType\n >[\"values\"],\n messages,\n toolCalls,\n interrupts,\n interrupt,\n isLoading,\n isThreadLoading,\n error,\n threadId,\n hydrationPromise,\n subagents: subagentSignal as UseStreamReturn<\n T,\n InterruptType,\n ConfigurableType\n >[\"subagents\"],\n subgraphs: subgraphSignal,\n subgraphsByNode: subgraphByNodeSignal,\n submit: (input, submitOptions) => controller.submit(input, submitOptions),\n stop: (options) => controller.stop(options),\n disconnect: () => controller.disconnect(),\n respond: (response, target) => controller.respond(response, target),\n getThread: () => controller.getThread(),\n client,\n assistantId,\n [STREAM_CONTROLLER]: controller,\n };\n\n return handle;\n}\n\n/**\n * Helper used by the selector primitives to reach the underlying\n * {@link ChannelRegistry} from a stream handle. Kept internal —\n * application code should call `injectMessages`, `injectToolCalls`,\n * etc. instead of reading this directly.\n *\n * @internal\n */\nexport function getRegistry(\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n stream: UseStreamReturn<any, any, any>\n): ChannelRegistry {\n return stream[STREAM_CONTROLLER].registry;\n}\n\nexport type { ThreadStream };\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"use-stream.js","names":["ClientCtor"],"sources":["../src/use-stream.ts"],"sourcesContent":["import {\n DestroyRef,\n computed,\n effect,\n inject,\n isSignal,\n signal,\n untracked,\n type Signal,\n} from \"@angular/core\";\nimport type { BaseMessage } from \"@langchain/core/messages\";\nimport type { Client, Interrupt } from \"@langchain/langgraph-sdk\";\nimport {\n filterOutHeadlessToolInterrupts,\n flushPendingHeadlessToolInterrupts,\n scheduleCoalescedHeadlessToolFlush,\n type AnyHeadlessToolImplementation,\n type OnToolCallback,\n} from \"@langchain/langgraph-sdk\";\nimport {\n Client as ClientCtor,\n type ClientConfig,\n type ThreadStream,\n} from \"@langchain/langgraph-sdk/client\";\nimport {\n StreamController,\n type AgentServerAdapter,\n type AgentServerOptions as StreamAgentServerOptions,\n type ChannelRegistry,\n type CustomAdapterOptions as StreamCustomAdapterOptions,\n type InferStateType,\n type InferToolCalls,\n type InferSubagentStates,\n type RootSnapshot,\n type RunCompletedInfo,\n type RunExecutionInfo,\n type StreamRespondAllOptions,\n type StreamRespondOptions,\n type StreamStopOptions,\n type StreamSubmitOptions,\n type SubagentDiscoverySnapshot,\n type SubagentMap,\n type SubgraphByNodeMap,\n type SubgraphDiscoverySnapshot,\n type SubgraphMap,\n type UseStreamOptions as StreamUseStreamOptions,\n type WidenUpdateMessages,\n} from \"@langchain/langgraph-sdk/stream\";\n\ntype AngularThreadId = string | null | Signal<string | null | undefined>;\n\nexport type AgentServerOptions<StateType extends object> =\n StreamAgentServerOptions<StateType, AngularThreadId>;\n\nexport type CustomAdapterOptions<StateType extends object> =\n StreamCustomAdapterOptions<StateType, AngularThreadId, string>;\n\nexport type UseStreamOptions<\n StateType extends object = Record<string, unknown>,\n> = StreamUseStreamOptions<\n StateType,\n AngularThreadId,\n string | undefined,\n string | undefined,\n string\n>;\n\n/**\n * Private field on the handle that carries the\n * {@link StreamController} reference. Selector primitives read this\n * to reach the shared {@link ChannelRegistry}. Use the companion\n * `inject*` selectors (`injectMessages`, `injectToolCalls`,\n * `injectValues`, …) instead of reading this directly.\n */\nexport const STREAM_CONTROLLER: unique symbol = Symbol.for(\n \"@langchain/angular/controller\"\n);\n\n/**\n * Return shape of {@link useStream} — the Angular `StreamApi`.\n *\n * Reactivity primitives follow Angular conventions:\n *\n * - Data projections are `Signal<T>`; call them as functions in\n * templates (`stream.messages()`). They are snapshots — never\n * mutate the returned arrays / maps.\n * - Imperative methods (`submit` / `stop` / `respond`) are plain\n * functions. No `WritableSignal`s are exposed on the root handle.\n * - Identity values captured at construction time (`client`,\n * `assistantId`) are exposed as plain values; remount the\n * component to swap them.\n */\nexport interface UseStreamReturn<\n T = Record<string, unknown>,\n InterruptType = unknown,\n ConfigurableType extends object = Record<string, unknown>,\n StateType extends object = InferStateType<T>,\n SubagentStates = InferSubagentStates<T>,\n> {\n // ----- always-on root projections -----\n /**\n * The most recent `values`-channel snapshot emitted at the root\n * namespace — i.e. the thread-level state as the server sees it\n * after each superstep. Updated on every root `values` event, not\n * on token-level deltas: if you render `stream.values().messages`\n * directly you'll see full turns appear at once instead of\n * streaming token-by-token. Use {@link messages} (or\n * `injectMessages`) for the token-streamed view.\n *\n * Equivalent to calling `injectValues(stream)`.\n */\n readonly values: Signal<StateType>;\n /**\n * The root message projection. Assembled from two sources and\n * merged in real time:\n *\n * 1. `messages`-channel deltas — token-level streaming events\n * (`message-start`, `content-block-delta`, `message-finish`)\n * emitted by the runtime. These drive live, token-by-token\n * updates.\n * 2. `values.messages` snapshots — the authoritative ordering\n * and any messages the agent produces without token streaming\n * (human turns, tool results, echoes from subagents).\n *\n * If the backend only emits `values` events (no `messages`\n * channel), every message will appear fully-formed on each\n * values update rather than streaming. This is a backend/runtime\n * concern — the Angular layer faithfully renders whatever the\n * server sends.\n *\n * Equivalent to calling `injectMessages(stream)` with no target.\n */\n readonly messages: Signal<BaseMessage[]>;\n /**\n * Root-namespace tool calls assembled from the `tools` channel.\n * Each entry is a fully parsed {@link AssembledToolCall} with\n * name, args, and id — suitable for rendering approval UIs or\n * forwarding to headless tool handlers.\n *\n * When the stream is typed with an agent brand or tool list,\n * entries are narrowed via {@link InferToolCalls}. Equivalent to\n * calling `injectToolCalls(stream)` with no target.\n */\n readonly toolCalls: Signal<InferToolCalls<T>[]>;\n /**\n * All unresolved protocol interrupts observed on the root\n * namespace during the active thread. Populated from lifecycle /\n * input events and seeded on hydration from `thread.getState()`.\n * Cleared optimistically when a new run starts or an interrupt is\n * resolved via {@link respond}.\n */\n readonly interrupts: Signal<Interrupt<InterruptType>[]>;\n /**\n * Convenience alias for {@link interrupts}[0] — the primary\n * interrupt most UIs should act on when only one is pending.\n * `undefined` when no interrupt is active.\n */\n readonly interrupt: Signal<Interrupt<InterruptType> | undefined>;\n /**\n * `true` while a run is active or being started on the current\n * thread. Driven by root-namespace lifecycle events (`running` →\n * `true`, terminal phases → `false`). Use this to disable submit\n * buttons and show in-flight spinners.\n */\n readonly isLoading: Signal<boolean>;\n /**\n * `true` while the initial `thread.getState()` hydration for the\n * active thread is in flight. Distinct from {@link isLoading} —\n * thread loading covers the one-time fetch that seeds\n * {@link values} / {@link messages} before any user submit.\n */\n readonly isThreadLoading: Signal<boolean>;\n /**\n * The last error observed on the active run or hydration attempt.\n * `undefined` when no error has occurred. Cleared optimistically\n * when a new {@link submit} starts.\n */\n readonly error: Signal<unknown>;\n /**\n * Id of the thread the controller is bound to. `null` until the\n * first {@link submit} creates or selects a thread (or until an\n * explicit `threadId` option is provided and hydrated).\n */\n readonly threadId: Signal<string | null>;\n /**\n * Promise that settles when the active thread's initial hydration\n * completes. Exposed so SSR/render-before-flush pipelines can\n * `await stream.hydrationPromise()` before serialising. A fresh\n * promise is installed on every `threadId` change.\n */\n readonly hydrationPromise: Signal<Promise<void>>;\n\n // ----- always-on discovery -----\n /**\n * Subagents discovered on the root run. For DeepAgent-typed\n * streams the key set is narrowed to the subagent names declared\n * on the agent brand (`keyof InferSubagentStates<T>`).\n */\n readonly subagents: Signal<\n ReadonlyMap<\n keyof SubagentStates & string extends never\n ? string\n : keyof SubagentStates & string,\n SubagentDiscoverySnapshot\n >\n >;\n /**\n * Subgraphs discovered on the root run.\n *\n * A namespace is classified as a subgraph iff at least one\n * strictly-deeper namespace has been observed with it as a prefix.\n * This is inferred from the lifecycle event stream — plain function\n * nodes (`orchestrator`, `writer` in the nested-stategraph example)\n * never appear here even though the server emits namespaced\n * lifecycle events for them. Promotion is monotonic and retroactive;\n * an entry appears as soon as the first descendant event lands.\n */\n readonly subgraphs: Signal<ReadonlyMap<string, SubgraphDiscoverySnapshot>>;\n /**\n * Subgraphs indexed by the graph node that produced them\n * (`addNode(\"visualizer_0\", …)`). Each value is an array because\n * parallel fan-outs and loops can spawn multiple invocations of\n * the same node; arrays preserve insertion order. Updates in\n * lock-step with {@link subgraphs}.\n */\n readonly subgraphsByNode: Signal<\n ReadonlyMap<string, readonly SubgraphDiscoverySnapshot[]>\n >;\n\n // ----- imperatives -----\n /**\n * Dispatch a new run on the bound thread.\n *\n * `input` is typed as `Partial<StateType>` so IDE autocompletion\n * surfaces the state keys declared on the root primitive.\n */\n submit(\n input: WidenUpdateMessages<Partial<StateType>> | null | undefined,\n options?: StreamSubmitOptions<StateType, ConfigurableType>\n ): Promise<void>;\n /**\n * Stop the active run on the current thread. By default cancels the\n * run server-side and disconnects the client; pass `{ cancel: false }`\n * or use {@link disconnect} for join/rejoin. Sets {@link isLoading} to\n * `false` immediately; {@link values} and {@link messages} are preserved.\n */\n stop(options?: StreamStopOptions): Promise<void>;\n /**\n * Disconnect the client without cancelling the run server-side.\n * Alias for `stop({ cancel: false })`.\n */\n disconnect(): Promise<void>;\n /**\n * Resume a pending protocol interrupt by sending a response payload\n * back to the interrupted namespace.\n *\n * When `options.interruptId` is omitted, walks `getThread()?.interrupts`\n * from newest to oldest and resumes the first not yet resolved by a prior\n * `respond()` call. That may be a root or subgraph interrupt and is\n * **not** necessarily {@link interrupt} (`interrupts()[0]`, root-only).\n * Safe when exactly one interrupt is pending; otherwise pass an explicit\n * `options.interruptId` (and `options.namespace` for subgraph\n * interrupts).\n *\n * The server validates `namespace` against the pending interrupt. Root\n * interrupts use `namespace: []` (default when omitted). For subgraph\n * interrupts, copy `namespace` from `getThread()?.interrupts`.\n *\n * @example\n * ```ts\n * // Single pending interrupt\n * await stream.respond({ approved: true });\n * ```\n *\n * @example\n * ```ts\n * // Multiple root interrupts\n * for (const intr of stream.interrupts()) {\n * await stream.respond(decide(intr.value), { interruptId: intr.id! });\n * }\n * ```\n *\n * @example\n * ```ts\n * // Subgraph interrupt — namespace from `getThread()`\n * const thread = stream.getThread();\n * for (const entry of thread?.interrupts ?? []) {\n * await stream.respond(buildResponse(entry.payload), {\n * interruptId: entry.interruptId,\n * namespace: entry.namespace,\n * });\n * }\n * ```\n *\n * To resume several interrupts pending at the same checkpoint in one\n * command, use {@link respondAll}.\n */\n respond(\n response: unknown,\n options?: StreamRespondOptions<ConfigurableType>\n ): Promise<void>;\n\n /**\n * Resume several pending interrupts at the same checkpoint in a single\n * command — required when a run pauses on multiple interrupts at once\n * (e.g. parallel tool-authorization prompts), which sequential\n * {@link respond} calls cannot handle. `responsesById` maps each pending\n * `interruptId` to its response, so different interrupts can receive\n * different payloads. Pass `options.config` / `options.metadata` to fold\n * run-level config and metadata into the resumed run, mirroring\n * `submit()`.\n *\n * @example\n * ```ts\n * await stream.respondAll({\n * [interruptA.id]: { approved: true },\n * [interruptB.id]: { approved: false },\n * });\n * ```\n */\n respondAll(\n responsesById: Record<string, unknown>,\n options?: StreamRespondAllOptions<ConfigurableType>\n ): Promise<void>;\n\n // ----- identity -----\n /** LangGraph SDK client used to construct thread streams. */\n readonly client: Client;\n /** Assistant id the thread is bound to for its lifetime. */\n readonly assistantId: string;\n\n /**\n * Returns the bound {@link ThreadStream}, if one exists (`undefined`\n * until the thread is hydrated or the first submit completes). Prefer\n * the projections and selector primitives for UI work; use this for\n * low-level protocol access (raw subscriptions, state commands, etc.).\n */\n getThread(): ThreadStream | undefined;\n\n /** @internal Used by selector primitives. */\n readonly [STREAM_CONTROLLER]: StreamController<\n StateType,\n InterruptType,\n ConfigurableType\n >;\n}\n\n/**\n * Erased handle useful as a parameter type for helper components that\n * pass a `stream` through to selector primitives without reading\n * `values` directly. Mirrors the React/Vue `AnyStream` alias.\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport type AnyStream = UseStreamReturn<any, any, any>;\n\n/**\n * Convenience alias — the fully-resolved return type of\n * {@link useStream} for a given source type `T`.\n */\nexport type StreamApi<\n T = Record<string, unknown>,\n InterruptType = unknown,\n ConfigurableType extends object = Record<string, unknown>,\n> = UseStreamReturn<T, InterruptType, ConfigurableType>;\n\n/**\n * React-compatible alias for the fully-resolved stream handle type.\n * Angular docs prefer {@link StreamApi}, but shared libraries can use\n * this name across framework bindings.\n */\nexport type UseStreamResult<\n T = Record<string, unknown>,\n InterruptType = unknown,\n ConfigurableType extends object = Record<string, unknown>,\n> = UseStreamReturn<T, InterruptType, ConfigurableType>;\n\n/**\n * Framework-free factory that constructs a {@link StreamController}\n * and wraps its stores in Angular Signals. Callers must supply the\n * {@link DestroyRef} that owns the controller's lifetime — it's\n * already captured by the public `injectStream` helper.\n *\n * Exported for advanced callers (e.g. testing utilities, custom\n * factories) that prefer to manage injection scope themselves.\n */\nexport function useStream<\n T = Record<string, unknown>,\n InterruptType = unknown,\n ConfigurableType extends object = Record<string, unknown>,\n>(\n options: UseStreamOptions<InferStateType<T>>,\n destroyRef?: DestroyRef\n): UseStreamReturn<T, InterruptType, ConfigurableType> {\n type StateType = InferStateType<T>;\n\n interface OptionsBag {\n assistantId?: string;\n threadId?: string | null | Signal<string | null | undefined>;\n client?: Client;\n apiUrl?: string;\n apiKey?: string;\n callerOptions?: ClientConfig[\"callerOptions\"];\n defaultHeaders?: ClientConfig[\"defaultHeaders\"];\n transport?: \"sse\" | \"websocket\" | AgentServerAdapter;\n fetch?: typeof fetch;\n webSocketFactory?: (url: string) => WebSocket;\n onThreadId?: (threadId: string) => void;\n onCreated?: (info: RunExecutionInfo) => void;\n onCompleted?: (info: RunCompletedInfo) => void;\n initialValues?: StateType;\n messagesKey?: string;\n tools?: AnyHeadlessToolImplementation[];\n onTool?: OnToolCallback;\n }\n const asBag = options as OptionsBag;\n\n const hasCustomAdapter =\n asBag.transport != null && typeof asBag.transport !== \"string\";\n const transport = asBag.transport;\n\n const client: Client =\n asBag.client ??\n (new ClientCtor({\n apiUrl: asBag.apiUrl,\n apiKey: asBag.apiKey,\n callerOptions: asBag.callerOptions,\n defaultHeaders: asBag.defaultHeaders,\n }) as unknown as Client);\n\n // Custom adapters may omit `assistantId`; the controller still\n // requires one so it has something to forward to `threads.stream`.\n const sentinel = \"_\";\n const assistantId =\n \"assistantId\" in options ? (options.assistantId ?? sentinel) : sentinel;\n\n // Normalize threadId input to a signal — callers may pass plain\n // values, nulls, or their own signals.\n const threadIdInput: Signal<string | null> = (() => {\n const raw = asBag.threadId;\n if (isSignal(raw)) {\n return computed(\n () => (raw as Signal<string | null | undefined>)() ?? null\n );\n }\n const initial: string | null = (raw as string | null | undefined) ?? null;\n return signal(initial) as unknown as Signal<string | null>;\n })();\n\n const controller = new StreamController<\n StateType,\n InterruptType,\n ConfigurableType\n >({\n assistantId,\n // Cast: the runtime `Client` is state-shape agnostic, but the\n // controller declares `client: Client<StateType>` for its own\n // typings. Same cast is applied in the React/Vue bindings.\n client: client as unknown as Client<StateType>,\n threadId: untracked(() => threadIdInput()),\n transport,\n fetch: hasCustomAdapter ? undefined : asBag.fetch,\n webSocketFactory: hasCustomAdapter ? undefined : asBag.webSocketFactory,\n onThreadId: options.onThreadId,\n onCreated: options.onCreated,\n onCompleted: options.onCompleted,\n initialValues: options.initialValues,\n messagesKey: options.messagesKey,\n });\n\n // Deferred dispose — matches the React `useEffect(() =>\n // controller.activate())` and Vue `onScopeDispose(deactivate)`\n // patterns. HMR / scope-reuse scenarios stay clean because\n // `activate()` cancels the pending dispose if the scope survives.\n const deactivate = controller.activate();\n const ref = destroyRef ?? inject(DestroyRef);\n ref.onDestroy(deactivate);\n\n // ─── Reactivity bridge: StreamStore → Signal ────────────────────────\n function bindStore<S>(\n subscribe: (listener: () => void) => () => void,\n getSnapshot: () => S\n ): Signal<S> {\n const s = signal<S>(getSnapshot());\n const unsubscribe = subscribe(() => {\n s.set(getSnapshot());\n });\n ref.onDestroy(unsubscribe);\n return computed(() => s());\n }\n\n const rootSignal = bindStore<RootSnapshot<StateType, InterruptType>>(\n controller.rootStore.subscribe,\n controller.rootStore.getSnapshot\n );\n const subagentSignal = bindStore<SubagentMap>(\n controller.subagentStore.subscribe,\n controller.subagentStore.getSnapshot\n );\n const subgraphSignal = bindStore<SubgraphMap>(\n controller.subgraphStore.subscribe,\n controller.subgraphStore.getSnapshot\n );\n const subgraphByNodeSignal = bindStore<SubgraphByNodeMap>(\n controller.subgraphByNodeStore.subscribe,\n controller.subgraphByNodeStore.getSnapshot\n );\n\n const values = computed(() => rootSignal().values);\n const messages = computed(() => rootSignal().messages);\n const toolCalls = computed(\n () => rootSignal().toolCalls as InferToolCalls<T>[]\n );\n const interrupts = computed(() =>\n filterOutHeadlessToolInterrupts(rootSignal().interrupts)\n );\n const interrupt = computed(() => interrupts()[0]);\n const isLoading = computed(() => rootSignal().isLoading);\n const isThreadLoading = computed(() => rootSignal().isThreadLoading);\n const error = computed(() => rootSignal().error);\n const threadId = computed(() => rootSignal().threadId);\n\n // `hydrationPromise` is a property on the controller that gets\n // swapped on every `hydrate()` call. Exposing it as a signal lets\n // templates `await stream.hydrationPromise()` reactively; we\n // refresh the reference when the root store settles a new promise.\n const hydrationPromise = computed(() => {\n rootSignal();\n return controller.hydrationPromise;\n });\n\n // ─── threadId reactivity ────────────────────────────────────────────\n //\n // Re-hydrate whenever the caller's threadId input changes after\n // construction. The initial hydrate already fired synchronously in\n // the controller constructor, so we compare against the snapshot\n // captured at construction time rather than blindly skipping the\n // first run — in Angular, `@Input()` bindings apply *between*\n // construction and the first effect tick, so the first read can\n // legitimately be a different (updated) value that needs to\n // hydrate.\n const initialThreadId = untracked(() => threadIdInput()) ?? null;\n let lastAppliedThreadId: string | null = initialThreadId;\n effect(() => {\n const next = threadIdInput() ?? null;\n if (next === lastAppliedThreadId) return;\n lastAppliedThreadId = next;\n untracked(() => {\n void controller.hydrate(next);\n });\n });\n\n // ─── Headless-tool handling ─────────────────────────────────────────\n const tools = options.tools;\n const onTool = options.onTool;\n if (tools?.length) {\n const handledTools = new Set<string>();\n\n // Clear the dedup set whenever the thread id changes.\n effect(() => {\n threadIdInput();\n untracked(() => handledTools.clear());\n });\n\n effect(() => {\n rootSignal();\n untracked(() => {\n scheduleCoalescedHeadlessToolFlush(handledTools, () => {\n const snapshot = rootSignal();\n const bag = snapshot.values as unknown as Record<string, unknown>;\n const protocolInterrupts =\n snapshot.interrupts as unknown as Interrupt[];\n const valuesInterrupts = Array.isArray(bag?.__interrupt__)\n ? (bag.__interrupt__ as Interrupt[])\n : [];\n const headlessInterrupts =\n protocolInterrupts.length > 0\n ? protocolInterrupts\n : valuesInterrupts;\n if (headlessInterrupts.length === 0) return;\n flushPendingHeadlessToolInterrupts(\n { ...bag, __interrupt__: headlessInterrupts },\n tools,\n handledTools,\n {\n onTool,\n defer: (run) => {\n void Promise.resolve().then(run);\n },\n resumeSubmit: (command) =>\n controller.submit(null, {\n command,\n } as StreamSubmitOptions<StateType, ConfigurableType>),\n }\n );\n });\n });\n });\n }\n\n const handle: UseStreamReturn<T, InterruptType, ConfigurableType> = {\n values: values as UseStreamReturn<\n T,\n InterruptType,\n ConfigurableType\n >[\"values\"],\n messages,\n toolCalls,\n interrupts,\n interrupt,\n isLoading,\n isThreadLoading,\n error,\n threadId,\n hydrationPromise,\n subagents: subagentSignal as UseStreamReturn<\n T,\n InterruptType,\n ConfigurableType\n >[\"subagents\"],\n subgraphs: subgraphSignal,\n subgraphsByNode: subgraphByNodeSignal,\n submit: (input, submitOptions) => controller.submit(input, submitOptions),\n stop: (options) => controller.stop(options),\n disconnect: () => controller.disconnect(),\n respond: (response, options) => controller.respond(response, options),\n respondAll: (responsesById, options) =>\n controller.respondAll(responsesById, options),\n getThread: () => controller.getThread(),\n client,\n assistantId,\n [STREAM_CONTROLLER]: controller,\n };\n\n return handle;\n}\n\n/**\n * Helper used by the selector primitives to reach the underlying\n * {@link ChannelRegistry} from a stream handle. Kept internal —\n * application code should call `injectMessages`, `injectToolCalls`,\n * etc. instead of reading this directly.\n *\n * @internal\n */\nexport function getRegistry(\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n stream: UseStreamReturn<any, any, any>\n): ChannelRegistry {\n return stream[STREAM_CONTROLLER].registry;\n}\n\nexport type { ThreadStream };\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@langchain/angular",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.11",
|
|
4
4
|
"description": "Angular integration for LangGraph & LangChain",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
"directory": "libs/sdk-angular"
|
|
11
11
|
},
|
|
12
12
|
"dependencies": {
|
|
13
|
-
"@langchain/langgraph-sdk": "1.9.
|
|
13
|
+
"@langchain/langgraph-sdk": "1.9.11"
|
|
14
14
|
},
|
|
15
15
|
"devDependencies": {
|
|
16
16
|
"@analogjs/vite-plugin-angular": "^2.5.0",
|
|
@@ -37,9 +37,9 @@
|
|
|
37
37
|
"vitest-browser-angular": "^0.4.0",
|
|
38
38
|
"webdriverio": "^9.27.0",
|
|
39
39
|
"zod": "^4.3.6",
|
|
40
|
-
"@langchain/langgraph": "^1.3.
|
|
41
|
-
"@langchain/langgraph-api": "^1.2.
|
|
42
|
-
"@langchain/langgraph-checkpoint": "^1.0.
|
|
40
|
+
"@langchain/langgraph": "^1.3.3",
|
|
41
|
+
"@langchain/langgraph-api": "^1.2.4",
|
|
42
|
+
"@langchain/langgraph-checkpoint": "^1.0.4"
|
|
43
43
|
},
|
|
44
44
|
"peerDependencies": {
|
|
45
45
|
"@angular/core": "^18.0.0 || ^19.0.0 || ^20.0.0 || ^21.0.0",
|