@langchain/langgraph-sdk 1.11.2 → 1.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. package/dist/client/base.cjs +7 -0
  2. package/dist/client/base.cjs.map +1 -1
  3. package/dist/client/base.d.cts.map +1 -1
  4. package/dist/client/base.d.ts.map +1 -1
  5. package/dist/client/base.js +7 -0
  6. package/dist/client/base.js.map +1 -1
  7. package/dist/stream/controller.cjs +39 -10
  8. package/dist/stream/controller.cjs.map +1 -1
  9. package/dist/stream/controller.d.cts +7 -6
  10. package/dist/stream/controller.d.cts.map +1 -1
  11. package/dist/stream/controller.d.ts +7 -6
  12. package/dist/stream/controller.d.ts.map +1 -1
  13. package/dist/stream/controller.js +37 -8
  14. package/dist/stream/controller.js.map +1 -1
  15. package/dist/stream/dispatch-config.cjs +23 -0
  16. package/dist/stream/dispatch-config.cjs.map +1 -0
  17. package/dist/stream/dispatch-config.js +23 -0
  18. package/dist/stream/dispatch-config.js.map +1 -0
  19. package/dist/stream/index.d.cts +1 -1
  20. package/dist/stream/index.d.ts +1 -1
  21. package/dist/stream/lifecycle-loading-tracker.cjs +8 -0
  22. package/dist/stream/lifecycle-loading-tracker.cjs.map +1 -1
  23. package/dist/stream/lifecycle-loading-tracker.js +8 -0
  24. package/dist/stream/lifecycle-loading-tracker.js.map +1 -1
  25. package/dist/stream/queue-adapter-agent-server.cjs +204 -0
  26. package/dist/stream/queue-adapter-agent-server.cjs.map +1 -0
  27. package/dist/stream/queue-adapter-agent-server.js +203 -0
  28. package/dist/stream/queue-adapter-agent-server.js.map +1 -0
  29. package/dist/stream/queue-adapter-local.cjs +50 -0
  30. package/dist/stream/queue-adapter-local.cjs.map +1 -0
  31. package/dist/stream/queue-adapter-local.js +49 -0
  32. package/dist/stream/queue-adapter-local.js.map +1 -0
  33. package/dist/stream/queue-adapter.cjs +7 -0
  34. package/dist/stream/queue-adapter.cjs.map +1 -0
  35. package/dist/stream/{submit-coordinator.d.cts → queue-adapter.d.cts} +6 -9
  36. package/dist/stream/queue-adapter.d.cts.map +1 -0
  37. package/dist/stream/queue-adapter.d.ts +24 -0
  38. package/dist/stream/queue-adapter.d.ts.map +1 -0
  39. package/dist/stream/queue-adapter.js +7 -0
  40. package/dist/stream/queue-adapter.js.map +1 -0
  41. package/dist/stream/submit-coordinator.cjs +82 -86
  42. package/dist/stream/submit-coordinator.cjs.map +1 -1
  43. package/dist/stream/submit-coordinator.d.ts +1 -26
  44. package/dist/stream/submit-coordinator.js +82 -85
  45. package/dist/stream/submit-coordinator.js.map +1 -1
  46. package/dist/stream/types.d.cts +25 -4
  47. package/dist/stream/types.d.cts.map +1 -1
  48. package/dist/stream/types.d.ts +25 -4
  49. package/dist/stream/types.d.ts.map +1 -1
  50. package/package.json +1 -1
  51. package/dist/stream/submit-coordinator.d.cts.map +0 -1
  52. package/dist/stream/submit-coordinator.d.ts.map +0 -1
@@ -0,0 +1,203 @@
1
+ import { bindThreadConfig } from "./dispatch-config.js";
2
+ import { EMPTY_QUEUE } from "./queue-adapter.js";
3
+ import { v7 } from "@langchain/core/utils/uuid";
4
+ //#region src/stream/queue-adapter-agent-server.ts
5
+ /**
6
+ * Backs "enqueue" with real, durable runs. An entry is a genuine
7
+ * server-side pending run the instant `enqueue()` resolves.
8
+ *
9
+ * Selected when `queue: "server"` is set (see {@link SubmitCoordinator}'s
10
+ * constructor).
11
+ */
12
+ var AgentServerQueueAdapter = class {
13
+ #runs;
14
+ #assistantId;
15
+ #store;
16
+ #onError;
17
+ #getThread;
18
+ /** One shared subscription for this adapter's lifetime, not one per run. */
19
+ #unsubscribe;
20
+ /** ids canceled while their create() was still in flight. */
21
+ #pendingCancel = /* @__PURE__ */ new Set();
22
+ #threadId;
23
+ /** Guards against a stale hydrate() landing after a rapid thread-switch. */
24
+ #hydrateGeneration = 0;
25
+ /** Aborts in-flight bookkeeping `list()` calls on detach(); replaced (never reused) afterward. */
26
+ #abortController = new AbortController();
27
+ /** Handle for #refreshPending's pending retry, if any; cleared on detach(). */
28
+ #refreshRetryTimer;
29
+ /** Lets enqueue() detect a "started" event during its own create(). */
30
+ #startedEventCount = 0;
31
+ constructor(runs, assistantId, store, onError, getThread) {
32
+ this.#runs = runs;
33
+ this.#assistantId = assistantId;
34
+ this.#store = store;
35
+ this.#onError = onError;
36
+ this.#getThread = getThread;
37
+ }
38
+ async hydrate(threadId) {
39
+ this.#threadId = threadId;
40
+ this.#ensureWatching(threadId);
41
+ const generation = ++this.#hydrateGeneration;
42
+ const knownAtRequestTime = this.#knownRunIds();
43
+ let pending;
44
+ try {
45
+ pending = await this.#runs.list(threadId, {
46
+ status: "pending",
47
+ limit: 1e3,
48
+ select: [
49
+ "run_id",
50
+ "kwargs",
51
+ "created_at",
52
+ "multitask_strategy"
53
+ ],
54
+ signal: this.#abortController.signal
55
+ });
56
+ } catch (error) {
57
+ if (generation === this.#hydrateGeneration) this.#onError(error);
58
+ return;
59
+ }
60
+ if (generation !== this.#hydrateGeneration) return;
61
+ const remoteIds = new Set(pending.map((run) => run.run_id));
62
+ this.#store.setState((current) => {
63
+ const knownRunIds = new Set(current.flatMap((e) => e.runId ? [e.runId] : []));
64
+ const stillValid = current.filter((e) => this.#isStillQueued(e, remoteIds, knownAtRequestTime));
65
+ return [...pending.filter((run) => !knownRunIds.has(run.run_id)).map((run) => this.#toEntry(run)), ...stillValid];
66
+ });
67
+ }
68
+ /**
69
+ * On a self-created thread, this can race the active run's own
70
+ * `run.start` request that creates the thread row: if this
71
+ * `runs.create()` reaches the server first, it may 404. The local
72
+ * adapter has no such race (it never hits the server while queued).
73
+ */
74
+ async enqueue(threadId, values, options) {
75
+ this.#threadId = threadId;
76
+ this.#ensureWatching(threadId);
77
+ const startedEventsBefore = this.#startedEventCount;
78
+ const generationAtEnqueue = this.#hydrateGeneration;
79
+ const id = v7();
80
+ this.#store.setState((current) => [...current, {
81
+ id,
82
+ values,
83
+ options,
84
+ createdAt: /* @__PURE__ */ new Date()
85
+ }]);
86
+ try {
87
+ const run = await this.#runs.create(threadId, this.#assistantId, {
88
+ input: values,
89
+ config: bindThreadConfig(options?.config, threadId),
90
+ metadata: options?.metadata,
91
+ checkpointId: options?.forkFrom,
92
+ multitaskStrategy: "enqueue"
93
+ });
94
+ if (this.#pendingCancel.delete(id)) {
95
+ await this.#runs.cancel(threadId, run.run_id);
96
+ return;
97
+ }
98
+ this.#store.setState((current) => current.map((entry) => entry.id === id ? {
99
+ ...entry,
100
+ runId: run.run_id
101
+ } : entry));
102
+ if (this.#startedEventCount !== startedEventsBefore && this.#hydrateGeneration === generationAtEnqueue) this.#refreshPending(threadId);
103
+ } catch (error) {
104
+ this.#pendingCancel.delete(id);
105
+ this.#store.setState((current) => current.filter((entry) => entry.id !== id));
106
+ this.#onError(error);
107
+ throw error;
108
+ }
109
+ }
110
+ async cancel(id) {
111
+ const entry = this.#store.getSnapshot().find((e) => e.id === id);
112
+ if (!entry) return false;
113
+ this.#store.setState((current) => current.filter((e) => e.id !== id));
114
+ await this.#cancelEntry(entry);
115
+ return true;
116
+ }
117
+ async clear() {
118
+ const entries = this.#store.getSnapshot();
119
+ this.#store.setState(() => EMPTY_QUEUE);
120
+ const failures = (await Promise.allSettled(entries.map((entry) => this.#cancelEntry(entry)))).filter((r) => r.status === "rejected");
121
+ if (failures.length === 1) this.#onError(failures[0].reason);
122
+ else if (failures.length > 1) this.#onError(new AggregateError(failures.map((f) => f.reason), `${failures.length} of ${entries.length} queued runs failed to cancel`));
123
+ }
124
+ detach() {
125
+ this.#hydrateGeneration++;
126
+ this.#unsubscribe?.();
127
+ this.#unsubscribe = void 0;
128
+ this.#threadId = void 0;
129
+ this.#abortController.abort();
130
+ this.#abortController = new AbortController();
131
+ clearTimeout(this.#refreshRetryTimer);
132
+ this.#refreshRetryTimer = void 0;
133
+ }
134
+ async #cancelEntry(entry) {
135
+ if (entry.runId && this.#threadId) await this.#runs.cancel(this.#threadId, entry.runId);
136
+ else this.#pendingCancel.add(entry.id);
137
+ }
138
+ /**
139
+ * Lazily opens ONE subscription for this adapter's lifetime, not one
140
+ * per run. `LifecycleEvent` carries no `run_id`, so a `"running"`
141
+ * event triggers a `runs.list` re-check instead of a direct match.
142
+ */
143
+ #ensureWatching(threadId) {
144
+ if (this.#unsubscribe) return;
145
+ this.#unsubscribe = this.#getThread(threadId).onEvent((event) => {
146
+ if (event.method !== "lifecycle") return;
147
+ if (event.params.data.event !== "running") return;
148
+ this.#startedEventCount++;
149
+ this.#refreshPending(threadId);
150
+ });
151
+ }
152
+ /**
153
+ * Re-lists pending runs and drops any queue entry no longer reported
154
+ * pending: it's running now. Retried once after a network failure
155
+ * before surfacing an error — otherwise a single blip would leave a
156
+ * now-running entry stuck showing "queued" until the next promotion
157
+ * or a manual hydrate.
158
+ */
159
+ async #refreshPending(threadId, attempt = 0) {
160
+ if (this.#store.getSnapshot().length === 0) return;
161
+ const generation = this.#hydrateGeneration;
162
+ const knownAtRequestTime = this.#knownRunIds();
163
+ try {
164
+ const pending = await this.#runs.list(threadId, {
165
+ status: "pending",
166
+ limit: 1e3,
167
+ signal: this.#abortController.signal
168
+ });
169
+ if (generation !== this.#hydrateGeneration) return;
170
+ const stillPendingIds = new Set(pending.map((run) => run.run_id));
171
+ this.#store.setState((current) => current.filter((entry) => this.#isStillQueued(entry, stillPendingIds, knownAtRequestTime)));
172
+ } catch (error) {
173
+ if (generation !== this.#hydrateGeneration) return;
174
+ if (attempt < 1) {
175
+ this.#refreshRetryTimer = setTimeout(() => {
176
+ this.#refreshRetryTimer = void 0;
177
+ this.#refreshPending(threadId, attempt + 1);
178
+ }, 2e3);
179
+ return;
180
+ }
181
+ this.#onError(error);
182
+ }
183
+ }
184
+ #toEntry(run) {
185
+ return {
186
+ id: run.run_id,
187
+ runId: run.run_id,
188
+ values: run.kwargs?.input,
189
+ createdAt: new Date(run.created_at)
190
+ };
191
+ }
192
+ #knownRunIds() {
193
+ return new Set(this.#store.getSnapshot().flatMap((e) => e.runId ? [e.runId] : []));
194
+ }
195
+ /** Shared by hydrate() and #refreshPending(): is a list() response grounds to evict this entry? */
196
+ #isStillQueued(entry, stillPendingIds, knownAtRequestTime) {
197
+ return !entry.runId || stillPendingIds.has(entry.runId) || !knownAtRequestTime.has(entry.runId);
198
+ }
199
+ };
200
+ //#endregion
201
+ export { AgentServerQueueAdapter };
202
+
203
+ //# sourceMappingURL=queue-adapter-agent-server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"queue-adapter-agent-server.js","names":["#runs","#assistantId","#store","#onError","#getThread","#threadId","#ensureWatching","#hydrateGeneration","#knownRunIds","#abortController","#isStillQueued","#toEntry","#startedEventCount","uuidv7","#pendingCancel","#refreshPending","#cancelEntry","#unsubscribe","#refreshRetryTimer"],"sources":["../../src/stream/queue-adapter-agent-server.ts"],"sourcesContent":["import { v7 as uuidv7 } from \"@langchain/core/utils/uuid\";\nimport type { ThreadStream } from \"../client/index.js\";\nimport type { Run } from \"../schema.js\";\nimport { bindThreadConfig } from \"./dispatch-config.js\";\nimport {\n EMPTY_QUEUE,\n type QueueAdapter,\n type ServerQueueCapability,\n type SubmissionQueueEntry,\n type SubmissionQueueSnapshot,\n} from \"./queue-adapter.js\";\nimport { StreamStore } from \"./store.js\";\nimport type { StreamSubmitOptions } from \"./types.js\";\n\n/** `runs.list()`'s `Run` type doesn't declare `kwargs` by default; it's an opt-in `select` field. */\ntype RunWithKwargs = Run & { kwargs?: { input?: unknown } };\n\n/**\n * Backs \"enqueue\" with real, durable runs. An entry is a genuine\n * server-side pending run the instant `enqueue()` resolves.\n *\n * Selected when `queue: \"server\"` is set (see {@link SubmitCoordinator}'s\n * constructor).\n */\nexport class AgentServerQueueAdapter<\n StateType extends object = Record<string, unknown>,\n> implements QueueAdapter<StateType> {\n readonly #runs: ServerQueueCapability;\n readonly #assistantId: string;\n readonly #store: StreamStore<SubmissionQueueSnapshot<StateType>>;\n readonly #onError: (error: unknown) => void;\n readonly #getThread: (threadId: string) => Pick<ThreadStream, \"onEvent\">;\n /** One shared subscription for this adapter's lifetime, not one per run. */\n #unsubscribe: (() => void) | undefined;\n /** ids canceled while their create() was still in flight. */\n #pendingCancel = new Set<string>();\n #threadId: string | undefined;\n /** Guards against a stale hydrate() landing after a rapid thread-switch. */\n #hydrateGeneration = 0;\n /** Aborts in-flight bookkeeping `list()` calls on detach(); replaced (never reused) afterward. */\n #abortController = new AbortController();\n /** Handle for #refreshPending's pending retry, if any; cleared on detach(). */\n #refreshRetryTimer: ReturnType<typeof setTimeout> | undefined;\n /** Lets enqueue() detect a \"started\" event during its own create(). */\n #startedEventCount = 0;\n\n constructor(\n runs: ServerQueueCapability,\n assistantId: string,\n store: StreamStore<SubmissionQueueSnapshot<StateType>>,\n onError: (error: unknown) => void,\n getThread: (threadId: string) => Pick<ThreadStream, \"onEvent\">\n ) {\n this.#runs = runs;\n this.#assistantId = assistantId;\n this.#store = store;\n this.#onError = onError;\n this.#getThread = getThread;\n }\n\n async hydrate(threadId: string): Promise<void> {\n this.#threadId = threadId;\n this.#ensureWatching(threadId);\n const generation = ++this.#hydrateGeneration;\n // Baseline before asking: an entry assigned after this can't be in the response below.\n const knownAtRequestTime = this.#knownRunIds();\n let pending: RunWithKwargs[];\n try {\n pending = (await this.#runs.list(threadId, {\n status: \"pending\",\n // `list()` defaults to 10; a real cap would drop older entries.\n limit: 1000,\n // \"kwargs\" isn't part of the base `Run` shape returned by list();\n // it must be explicitly selected to get the original input back.\n select: [\"run_id\", \"kwargs\", \"created_at\", \"multitask_strategy\"],\n signal: this.#abortController.signal,\n })) as RunWithKwargs[];\n } catch (error) {\n // A generation mismatch means detach() aborted this on purpose.\n if (generation === this.#hydrateGeneration) this.#onError(error);\n return;\n }\n if (generation !== this.#hydrateGeneration) return; // superseded by a later hydrate()/detach()\n\n const remoteIds = new Set(pending.map((run) => run.run_id));\n this.#store.setState((current) => {\n const knownRunIds = new Set(\n current.flatMap((e) => (e.runId ? [e.runId] : []))\n );\n // Local entries are never overwritten by a server reconstruction\n // — a consumer may already be keying UI on their id.\n const stillValid = current.filter((e) =>\n this.#isStillQueued(e, remoteIds, knownAtRequestTime)\n );\n const newFromRemote = pending\n .filter((run) => !knownRunIds.has(run.run_id))\n .map((run) => this.#toEntry(run));\n return [\n ...newFromRemote,\n ...stillValid,\n ] as SubmissionQueueSnapshot<StateType>;\n });\n }\n\n /**\n * On a self-created thread, this can race the active run's own\n * `run.start` request that creates the thread row: if this\n * `runs.create()` reaches the server first, it may 404. The local\n * adapter has no such race (it never hits the server while queued).\n */\n async enqueue(\n threadId: string,\n values: Partial<StateType> | null | undefined,\n options: StreamSubmitOptions<StateType> | undefined\n ): Promise<void> {\n // A brand-new self-created thread may never be hydrated first.\n this.#threadId = threadId;\n this.#ensureWatching(threadId);\n const startedEventsBefore = this.#startedEventCount;\n const generationAtEnqueue = this.#hydrateGeneration;\n const id = uuidv7();\n this.#store.setState((current) => [\n ...current,\n { id, values, options, createdAt: new Date() },\n ]);\n try {\n const run = await this.#runs.create(threadId, this.#assistantId, {\n input: values,\n config: bindThreadConfig(options?.config, threadId),\n metadata: options?.metadata,\n checkpointId: options?.forkFrom,\n multitaskStrategy: \"enqueue\",\n });\n if (this.#pendingCancel.delete(id)) {\n await this.#runs.cancel(threadId, run.run_id); // canceled while creating; don't resurrect it\n return;\n }\n this.#store.setState((current) =>\n current.map((entry) =>\n entry.id === id ? { ...entry, runId: run.run_id } : entry\n )\n );\n // A run may have started before we learned its id; re-check now.\n // Skip if detach()/hydrate() rebound the adapter to another thread\n // in the meantime — `threadId` here is this call's own thread, not\n // necessarily the one the adapter is currently watching.\n if (\n this.#startedEventCount !== startedEventsBefore &&\n this.#hydrateGeneration === generationAtEnqueue\n ) {\n void this.#refreshPending(threadId);\n }\n } catch (error) {\n this.#pendingCancel.delete(id); // avoid leaking a pending-cancel marker nothing will ever consult\n this.#store.setState((current) =>\n current.filter((entry) => entry.id !== id)\n );\n this.#onError(error);\n throw error;\n }\n }\n\n async cancel(id: string): Promise<boolean> {\n const entry = this.#store.getSnapshot().find((e) => e.id === id);\n if (!entry) return false;\n this.#store.setState((current) => current.filter((e) => e.id !== id));\n await this.#cancelEntry(entry);\n return true;\n }\n\n async clear(): Promise<void> {\n const entries = this.#store.getSnapshot();\n this.#store.setState(\n () => EMPTY_QUEUE as SubmissionQueueSnapshot<StateType>\n );\n // `allSettled`, not `all`: one failed cancel must not stop the rest\n // from being attempted, nor reject `clear()` itself.\n const results = await Promise.allSettled(\n entries.map((entry) => this.#cancelEntry(entry))\n );\n const failures = results.filter(\n (r): r is PromiseRejectedResult => r.status === \"rejected\"\n );\n if (failures.length === 1) {\n this.#onError(failures[0].reason);\n } else if (failures.length > 1) {\n this.#onError(\n new AggregateError(\n failures.map((f) => f.reason),\n `${failures.length} of ${entries.length} queued runs failed to cancel`\n )\n );\n }\n }\n\n detach(): void {\n this.#hydrateGeneration++; // invalidate any in-flight hydrate() for this thread\n this.#unsubscribe?.();\n this.#unsubscribe = undefined;\n // #pendingCancel is not cleared: dropping it would silently un-cancel an in-flight create().\n this.#threadId = undefined;\n this.#abortController.abort(); // stop any in-flight hydrate()/#refreshPending() list() call\n this.#abortController = new AbortController(); // an aborted controller can't be reused\n clearTimeout(this.#refreshRetryTimer); // a scheduled retry outliving detach() would target a stale thread\n this.#refreshRetryTimer = undefined;\n }\n\n async #cancelEntry(entry: SubmissionQueueEntry<StateType>): Promise<void> {\n if (entry.runId && this.#threadId) {\n await this.#runs.cancel(this.#threadId, entry.runId); // already real, idempotent\n } else {\n this.#pendingCancel.add(entry.id); // still being created; cancel on arrival\n }\n }\n\n /**\n * Lazily opens ONE subscription for this adapter's lifetime, not one\n * per run. `LifecycleEvent` carries no `run_id`, so a `\"running\"`\n * event triggers a `runs.list` re-check instead of a direct match.\n */\n #ensureWatching(threadId: string): void {\n if (this.#unsubscribe) return;\n this.#unsubscribe = this.#getThread(threadId).onEvent((event) => {\n if (event.method !== \"lifecycle\") return;\n if (event.params.data.event !== \"running\") return;\n this.#startedEventCount++;\n void this.#refreshPending(threadId);\n });\n }\n\n /**\n * Re-lists pending runs and drops any queue entry no longer reported\n * pending: it's running now. Retried once after a network failure\n * before surfacing an error — otherwise a single blip would leave a\n * now-running entry stuck showing \"queued\" until the next promotion\n * or a manual hydrate.\n */\n async #refreshPending(threadId: string, attempt = 0): Promise<void> {\n if (this.#store.getSnapshot().length === 0) return; // nothing left to refresh\n const generation = this.#hydrateGeneration;\n const knownAtRequestTime = this.#knownRunIds(); // same reasoning as hydrate()\n try {\n const pending = await this.#runs.list(threadId, {\n status: \"pending\",\n limit: 1000, // list() defaults to 10; see the matching note in hydrate()\n signal: this.#abortController.signal,\n });\n if (generation !== this.#hydrateGeneration) return; // superseded; thread id is stale\n const stillPendingIds = new Set(pending.map((run) => run.run_id));\n this.#store.setState((current) =>\n current.filter((entry) =>\n this.#isStillQueued(entry, stillPendingIds, knownAtRequestTime)\n )\n );\n } catch (error) {\n if (generation !== this.#hydrateGeneration) return; // detach() aborted this on purpose\n if (attempt < 1) {\n this.#refreshRetryTimer = setTimeout(() => {\n this.#refreshRetryTimer = undefined;\n void this.#refreshPending(threadId, attempt + 1);\n }, 2000);\n return;\n }\n this.#onError(error);\n }\n }\n\n #toEntry(run: RunWithKwargs): SubmissionQueueEntry<StateType> {\n return {\n id: run.run_id,\n runId: run.run_id,\n values: run.kwargs?.input as Partial<StateType> | null | undefined,\n createdAt: new Date(run.created_at),\n };\n }\n\n #knownRunIds(): Set<string> {\n return new Set(\n this.#store.getSnapshot().flatMap((e) => (e.runId ? [e.runId] : []))\n );\n }\n\n /** Shared by hydrate() and #refreshPending(): is a list() response grounds to evict this entry? */\n #isStillQueued(\n entry: SubmissionQueueEntry<StateType>,\n stillPendingIds: Set<string>,\n knownAtRequestTime: Set<string>\n ): boolean {\n return (\n !entry.runId ||\n stillPendingIds.has(entry.runId) ||\n !knownAtRequestTime.has(entry.runId)\n );\n }\n}\n"],"mappings":"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"}
@@ -0,0 +1,50 @@
1
+ require("../_virtual/_rolldown/runtime.cjs");
2
+ const require_queue_adapter = require("./queue-adapter.cjs");
3
+ let _langchain_core_utils_uuid = require("@langchain/core/utils/uuid");
4
+ //#region src/stream/queue-adapter-local.ts
5
+ /**
6
+ * Client-only defer. The default backing for `"enqueue"` — used
7
+ * unless `queue: "server"` is set.
8
+ */
9
+ var LocalQueueAdapter = class {
10
+ #store;
11
+ #onError;
12
+ constructor(store, onError) {
13
+ this.#store = store;
14
+ this.#onError = onError;
15
+ }
16
+ async hydrate() {}
17
+ async enqueue(_threadId, values, options) {
18
+ const entry = {
19
+ id: (0, _langchain_core_utils_uuid.v7)(),
20
+ values,
21
+ options,
22
+ createdAt: /* @__PURE__ */ new Date()
23
+ };
24
+ this.#store.setState((current) => [...current, entry]);
25
+ }
26
+ onIdle(dispatch) {
27
+ const [head, ...rest] = this.#store.getSnapshot();
28
+ if (!head) return;
29
+ this.#store.setState(() => rest);
30
+ dispatch(head.values, {
31
+ ...head.options,
32
+ multitaskStrategy: void 0
33
+ }).catch(this.#onError);
34
+ }
35
+ async cancel(id) {
36
+ const current = this.#store.getSnapshot();
37
+ const next = current.filter((entry) => entry.id !== id);
38
+ if (next.length === current.length) return false;
39
+ this.#store.setState(() => next);
40
+ return true;
41
+ }
42
+ async clear() {
43
+ this.#store.setState(() => require_queue_adapter.EMPTY_QUEUE);
44
+ }
45
+ detach() {}
46
+ };
47
+ //#endregion
48
+ exports.LocalQueueAdapter = LocalQueueAdapter;
49
+
50
+ //# sourceMappingURL=queue-adapter-local.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"queue-adapter-local.cjs","names":["#store","#onError","EMPTY_QUEUE"],"sources":["../../src/stream/queue-adapter-local.ts"],"sourcesContent":["import { v7 as uuidv7 } from \"@langchain/core/utils/uuid\";\nimport {\n EMPTY_QUEUE,\n type QueueAdapter,\n type SubmissionQueueEntry,\n type SubmissionQueueSnapshot,\n} from \"./queue-adapter.js\";\nimport { StreamStore } from \"./store.js\";\nimport type { StreamSubmitOptions } from \"./types.js\";\n\n/**\n * Client-only defer. The default backing for `\"enqueue\"` — used\n * unless `queue: \"server\"` is set.\n */\nexport class LocalQueueAdapter<\n StateType extends object = Record<string, unknown>,\n> implements QueueAdapter<StateType> {\n readonly #store: StreamStore<SubmissionQueueSnapshot<StateType>>;\n readonly #onError: (error: unknown) => void;\n\n constructor(\n store: StreamStore<SubmissionQueueSnapshot<StateType>>,\n onError: (error: unknown) => void\n ) {\n this.#store = store;\n this.#onError = onError;\n }\n\n async hydrate(): Promise<void> {\n // No-op. Nothing to hydrate from. The queue only ever reflects\n // what this session enqueued in memory.\n }\n\n async enqueue(\n _threadId: string,\n values: Partial<StateType> | null | undefined,\n options: StreamSubmitOptions<StateType> | undefined\n ): Promise<void> {\n const entry: SubmissionQueueEntry<StateType> = {\n id: uuidv7(),\n values,\n options,\n createdAt: new Date(),\n };\n this.#store.setState((current) => [...current, entry]);\n }\n\n onIdle(\n dispatch: (\n values: unknown,\n options: StreamSubmitOptions<StateType> | undefined\n ) => Promise<void>\n ): void {\n const [head, ...rest] = this.#store.getSnapshot();\n if (!head) return;\n this.#store.setState(() => rest);\n // Strip the strategy so the drained submission doesn't recursively re-enqueue.\n dispatch(head.values, {\n ...head.options,\n multitaskStrategy: undefined,\n }).catch(this.#onError); // dispatch already routes failures to rootStore.error\n }\n\n async cancel(id: string): Promise<boolean> {\n const current = this.#store.getSnapshot();\n const next = current.filter((entry) => entry.id !== id);\n if (next.length === current.length) return false;\n this.#store.setState(() => next);\n return true;\n }\n\n async clear(): Promise<void> {\n this.#store.setState(\n () => EMPTY_QUEUE as SubmissionQueueSnapshot<StateType>\n );\n }\n\n detach(): void {\n // Nothing to release.\n }\n}\n"],"mappings":";;;;;;;;AAcA,IAAa,oBAAb,MAEqC;CACnC;CACA;CAEA,YACE,OACA,SACA;AACA,QAAA,QAAc;AACd,QAAA,UAAgB;;CAGlB,MAAM,UAAyB;CAK/B,MAAM,QACJ,WACA,QACA,SACe;EACf,MAAM,QAAyC;GAC7C,KAAA,GAAA,2BAAA,KAAY;GACZ;GACA;GACA,2BAAW,IAAI,MAAM;GACtB;AACD,QAAA,MAAY,UAAU,YAAY,CAAC,GAAG,SAAS,MAAM,CAAC;;CAGxD,OACE,UAIM;EACN,MAAM,CAAC,MAAM,GAAG,QAAQ,MAAA,MAAY,aAAa;AACjD,MAAI,CAAC,KAAM;AACX,QAAA,MAAY,eAAe,KAAK;AAEhC,WAAS,KAAK,QAAQ;GACpB,GAAG,KAAK;GACR,mBAAmB,KAAA;GACpB,CAAC,CAAC,MAAM,MAAA,QAAc;;CAGzB,MAAM,OAAO,IAA8B;EACzC,MAAM,UAAU,MAAA,MAAY,aAAa;EACzC,MAAM,OAAO,QAAQ,QAAQ,UAAU,MAAM,OAAO,GAAG;AACvD,MAAI,KAAK,WAAW,QAAQ,OAAQ,QAAO;AAC3C,QAAA,MAAY,eAAe,KAAK;AAChC,SAAO;;CAGT,MAAM,QAAuB;AAC3B,QAAA,MAAY,eACJE,sBAAAA,YACP;;CAGH,SAAe"}
@@ -0,0 +1,49 @@
1
+ import { EMPTY_QUEUE } from "./queue-adapter.js";
2
+ import { v7 } from "@langchain/core/utils/uuid";
3
+ //#region src/stream/queue-adapter-local.ts
4
+ /**
5
+ * Client-only defer. The default backing for `"enqueue"` — used
6
+ * unless `queue: "server"` is set.
7
+ */
8
+ var LocalQueueAdapter = class {
9
+ #store;
10
+ #onError;
11
+ constructor(store, onError) {
12
+ this.#store = store;
13
+ this.#onError = onError;
14
+ }
15
+ async hydrate() {}
16
+ async enqueue(_threadId, values, options) {
17
+ const entry = {
18
+ id: v7(),
19
+ values,
20
+ options,
21
+ createdAt: /* @__PURE__ */ new Date()
22
+ };
23
+ this.#store.setState((current) => [...current, entry]);
24
+ }
25
+ onIdle(dispatch) {
26
+ const [head, ...rest] = this.#store.getSnapshot();
27
+ if (!head) return;
28
+ this.#store.setState(() => rest);
29
+ dispatch(head.values, {
30
+ ...head.options,
31
+ multitaskStrategy: void 0
32
+ }).catch(this.#onError);
33
+ }
34
+ async cancel(id) {
35
+ const current = this.#store.getSnapshot();
36
+ const next = current.filter((entry) => entry.id !== id);
37
+ if (next.length === current.length) return false;
38
+ this.#store.setState(() => next);
39
+ return true;
40
+ }
41
+ async clear() {
42
+ this.#store.setState(() => EMPTY_QUEUE);
43
+ }
44
+ detach() {}
45
+ };
46
+ //#endregion
47
+ export { LocalQueueAdapter };
48
+
49
+ //# sourceMappingURL=queue-adapter-local.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"queue-adapter-local.js","names":["#store","#onError","uuidv7"],"sources":["../../src/stream/queue-adapter-local.ts"],"sourcesContent":["import { v7 as uuidv7 } from \"@langchain/core/utils/uuid\";\nimport {\n EMPTY_QUEUE,\n type QueueAdapter,\n type SubmissionQueueEntry,\n type SubmissionQueueSnapshot,\n} from \"./queue-adapter.js\";\nimport { StreamStore } from \"./store.js\";\nimport type { StreamSubmitOptions } from \"./types.js\";\n\n/**\n * Client-only defer. The default backing for `\"enqueue\"` — used\n * unless `queue: \"server\"` is set.\n */\nexport class LocalQueueAdapter<\n StateType extends object = Record<string, unknown>,\n> implements QueueAdapter<StateType> {\n readonly #store: StreamStore<SubmissionQueueSnapshot<StateType>>;\n readonly #onError: (error: unknown) => void;\n\n constructor(\n store: StreamStore<SubmissionQueueSnapshot<StateType>>,\n onError: (error: unknown) => void\n ) {\n this.#store = store;\n this.#onError = onError;\n }\n\n async hydrate(): Promise<void> {\n // No-op. Nothing to hydrate from. The queue only ever reflects\n // what this session enqueued in memory.\n }\n\n async enqueue(\n _threadId: string,\n values: Partial<StateType> | null | undefined,\n options: StreamSubmitOptions<StateType> | undefined\n ): Promise<void> {\n const entry: SubmissionQueueEntry<StateType> = {\n id: uuidv7(),\n values,\n options,\n createdAt: new Date(),\n };\n this.#store.setState((current) => [...current, entry]);\n }\n\n onIdle(\n dispatch: (\n values: unknown,\n options: StreamSubmitOptions<StateType> | undefined\n ) => Promise<void>\n ): void {\n const [head, ...rest] = this.#store.getSnapshot();\n if (!head) return;\n this.#store.setState(() => rest);\n // Strip the strategy so the drained submission doesn't recursively re-enqueue.\n dispatch(head.values, {\n ...head.options,\n multitaskStrategy: undefined,\n }).catch(this.#onError); // dispatch already routes failures to rootStore.error\n }\n\n async cancel(id: string): Promise<boolean> {\n const current = this.#store.getSnapshot();\n const next = current.filter((entry) => entry.id !== id);\n if (next.length === current.length) return false;\n this.#store.setState(() => next);\n return true;\n }\n\n async clear(): Promise<void> {\n this.#store.setState(\n () => EMPTY_QUEUE as SubmissionQueueSnapshot<StateType>\n );\n }\n\n detach(): void {\n // Nothing to release.\n }\n}\n"],"mappings":";;;;;;;AAcA,IAAa,oBAAb,MAEqC;CACnC;CACA;CAEA,YACE,OACA,SACA;AACA,QAAA,QAAc;AACd,QAAA,UAAgB;;CAGlB,MAAM,UAAyB;CAK/B,MAAM,QACJ,WACA,QACA,SACe;EACf,MAAM,QAAyC;GAC7C,IAAIE,IAAQ;GACZ;GACA;GACA,2BAAW,IAAI,MAAM;GACtB;AACD,QAAA,MAAY,UAAU,YAAY,CAAC,GAAG,SAAS,MAAM,CAAC;;CAGxD,OACE,UAIM;EACN,MAAM,CAAC,MAAM,GAAG,QAAQ,MAAA,MAAY,aAAa;AACjD,MAAI,CAAC,KAAM;AACX,QAAA,MAAY,eAAe,KAAK;AAEhC,WAAS,KAAK,QAAQ;GACpB,GAAG,KAAK;GACR,mBAAmB,KAAA;GACpB,CAAC,CAAC,MAAM,MAAA,QAAc;;CAGzB,MAAM,OAAO,IAA8B;EACzC,MAAM,UAAU,MAAA,MAAY,aAAa;EACzC,MAAM,OAAO,QAAQ,QAAQ,UAAU,MAAM,OAAO,GAAG;AACvD,MAAI,KAAK,WAAW,QAAQ,OAAQ,QAAO;AAC3C,QAAA,MAAY,eAAe,KAAK;AAChC,SAAO;;CAGT,MAAM,QAAuB;AAC3B,QAAA,MAAY,eACJ,YACP;;CAGH,SAAe"}
@@ -0,0 +1,7 @@
1
+ //#region src/stream/queue-adapter.ts
2
+ /** Frozen empty queue, reused for referential stability across resets. */
3
+ const EMPTY_QUEUE = Object.freeze([]);
4
+ //#endregion
5
+ exports.EMPTY_QUEUE = EMPTY_QUEUE;
6
+
7
+ //# sourceMappingURL=queue-adapter.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"queue-adapter.cjs","names":[],"sources":["../../src/stream/queue-adapter.ts"],"sourcesContent":["import type { RunsClient } from \"../client/index.js\";\nimport type { StreamSubmitOptions } from \"./types.js\";\n\n/**\n * What {@link AgentServerQueueAdapter} needs to back `\"enqueue\"` with\n * real, durable server-side runs. Supplied from `client.runs` when\n * `queue: \"server\"` is set; see {@link SubmitCoordinator}.\n */\nexport type ServerQueueCapability = Pick<\n RunsClient,\n \"create\" | \"list\" | \"cancel\"\n>;\n\n/** A single queued submission. */\nexport interface SubmissionQueueEntry<\n StateType extends object = Record<string, unknown>,\n> {\n /** Stable id minted on enqueue (uuidv7) or the server run id for a hydrated entry. */\n readonly id: string;\n /** Server run id, once accepted. Absent while a dispatch is still in flight. */\n readonly runId?: string;\n /** Original submit input, narrowed to the partial state shape. */\n readonly values: Partial<StateType> | null | undefined;\n /** Original submit options, minus the strategy slot which is reset on drain. */\n readonly options?: StreamSubmitOptions<StateType>;\n /** Wall-clock timestamp at enqueue. */\n readonly createdAt: Date;\n}\n\n/**\n * Read-only snapshot of the queue. The queue store hands this out\n * directly; consumers must not mutate the array.\n */\nexport type SubmissionQueueSnapshot<\n StateType extends object = Record<string, unknown>,\n> = ReadonlyArray<SubmissionQueueEntry<StateType>>;\n\n/** Frozen empty queue, reused for referential stability across resets. */\nexport const EMPTY_QUEUE: SubmissionQueueSnapshot<never> = Object.freeze([]);\n\n/**\n * Pluggable backing for `useStream`'s \"enqueue\" multitask strategy. Owns\n * how a deferred submission is tracked while it waits its turn: where\n * it's recorded, how it's hydrated on load, how it learns a run started,\n * and how it's cancelled. {@link SubmitCoordinator} only delegates to\n * this for the `\"enqueue\"` case; see {@link LocalQueueAdapter}\n * (`queue-adapter-local.ts`) and {@link AgentServerQueueAdapter}\n * (`queue-adapter-agent-server.ts`) for the two implementations.\n *\n * Not exported from the package. Which implementation backs a given\n * call is decided by `useStream`'s `queue` option (`\"local\"` by\n * default), never a class a consumer picks between directly.\n */\nexport interface QueueAdapter<\n StateType extends object = Record<string, unknown>,\n> {\n /**\n * Populate the queue store from whatever this adapter considers the\n * source of truth: a real `runs.list` hydrate, or a no-op for the\n * local adapter. Called once, when the controller first binds to a\n * thread.\n */\n hydrate(threadId: string): Promise<void>;\n\n /**\n * Record a deferred submission. Resolves once it's safe to consider\n * *accepted*: for the server-backed adapter, once the server has\n * durably recorded it.\n */\n enqueue(\n threadId: string,\n values: Partial<StateType> | null | undefined,\n options: StreamSubmitOptions<StateType> | undefined\n ): Promise<void>;\n\n /**\n * Cancel one queued entry by its {@link SubmissionQueueEntry.id}.\n * Idempotent: cancelling an entry that's already started running or\n * was already removed resolves `false` rather than throwing.\n */\n cancel(id: string): Promise<boolean>;\n\n /** Cancel and remove every currently-queued entry. */\n clear(): Promise<void>;\n\n /**\n * Release whatever this adapter is watching. Called once, on\n * controller disposal or thread rebind.\n */\n detach(): void;\n\n /**\n * Called whenever the active run settles (nothing currently in\n * flight). Only meaningful for adapters that gate dispatch on\n * client-side timing: {@link LocalQueueAdapter} uses this to drain\n * its next entry via `dispatch`. {@link AgentServerQueueAdapter}\n * omits it entirely: the server's own scheduler decides when the next\n * pending run starts and the adapter only observes it.\n */\n onIdle?(\n dispatch: (\n values: unknown,\n options: StreamSubmitOptions<StateType> | undefined\n ) => Promise<void>\n ): void;\n}\n"],"mappings":";;AAsCA,MAAa,cAA8C,OAAO,OAAO,EAAE,CAAC"}
@@ -1,15 +1,12 @@
1
1
  import { StreamSubmitOptions } from "./types.cjs";
2
2
 
3
- //#region src/stream/submit-coordinator.d.ts
4
- /**
5
- * Queued submission entry mirrored from the server-side run queue.
6
- *
7
- * Surfaces the deferred submission to UI consumers via
8
- * {@link StreamController.queueStore}.
9
- */
3
+ //#region src/stream/queue-adapter.d.ts
4
+ /** A single queued submission. */
10
5
  interface SubmissionQueueEntry<StateType extends object = Record<string, unknown>> {
11
- /** Stable id minted on enqueue (uuidv7 — sortable by creation time). */
6
+ /** Stable id minted on enqueue (uuidv7) or the server run id for a hydrated entry. */
12
7
  readonly id: string;
8
+ /** Server run id, once accepted. Absent while a dispatch is still in flight. */
9
+ readonly runId?: string;
13
10
  /** Original submit input, narrowed to the partial state shape. */
14
11
  readonly values: Partial<StateType> | null | undefined;
15
12
  /** Original submit options, minus the strategy slot which is reset on drain. */
@@ -24,4 +21,4 @@ interface SubmissionQueueEntry<StateType extends object = Record<string, unknown
24
21
  type SubmissionQueueSnapshot<StateType extends object = Record<string, unknown>> = ReadonlyArray<SubmissionQueueEntry<StateType>>;
25
22
  //#endregion
26
23
  export { SubmissionQueueEntry, SubmissionQueueSnapshot };
27
- //# sourceMappingURL=submit-coordinator.d.cts.map
24
+ //# sourceMappingURL=queue-adapter.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"queue-adapter.d.cts","names":[],"sources":["../../src/stream/queue-adapter.ts"],"mappings":";;;;UAciB,oBAAA,4BACY,MAAA;EASR;EAAA,SANV,EAAA;EAQe;EAAA,SANf,KAAA;EALT;EAAA,SAOS,MAAA,EAAQ,OAAA,CAAQ,SAAA;EAJhB;EAAA,SAMA,OAAA,GAAU,mBAAA,CAAoB,SAAA;EAF9B;EAAA,SAIA,SAAA,EAAW,IAAA;AAAA;;;;;KAOV,uBAAA,4BACiB,MAAA,qBACzB,aAAA,CAAc,oBAAA,CAAqB,SAAA"}
@@ -0,0 +1,24 @@
1
+ import { StreamSubmitOptions } from "./types.js";
2
+
3
+ //#region src/stream/queue-adapter.d.ts
4
+ /** A single queued submission. */
5
+ interface SubmissionQueueEntry<StateType extends object = Record<string, unknown>> {
6
+ /** Stable id minted on enqueue (uuidv7) or the server run id for a hydrated entry. */
7
+ readonly id: string;
8
+ /** Server run id, once accepted. Absent while a dispatch is still in flight. */
9
+ readonly runId?: string;
10
+ /** Original submit input, narrowed to the partial state shape. */
11
+ readonly values: Partial<StateType> | null | undefined;
12
+ /** Original submit options, minus the strategy slot which is reset on drain. */
13
+ readonly options?: StreamSubmitOptions<StateType>;
14
+ /** Wall-clock timestamp at enqueue. */
15
+ readonly createdAt: Date;
16
+ }
17
+ /**
18
+ * Read-only snapshot of the queue. The queue store hands this out
19
+ * directly; consumers must not mutate the array.
20
+ */
21
+ type SubmissionQueueSnapshot<StateType extends object = Record<string, unknown>> = ReadonlyArray<SubmissionQueueEntry<StateType>>;
22
+ //#endregion
23
+ export { SubmissionQueueEntry, SubmissionQueueSnapshot };
24
+ //# sourceMappingURL=queue-adapter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"queue-adapter.d.ts","names":[],"sources":["../../src/stream/queue-adapter.ts"],"mappings":";;;;UAciB,oBAAA,4BACY,MAAA;EASY;EAAA,SAN9B,EAAA;EAQW;EAAA,SANX,KAAA;EAMe;EAAA,SAJf,MAAA,EAAQ,OAAA,CAAQ,SAAA;EAPE;EAAA,SASlB,OAAA,GAAU,mBAAA,CAAoB,SAAA;EAJ9B;EAAA,SAMA,SAAA,EAAW,IAAA;AAAA;;;;;KAOV,uBAAA,4BACiB,MAAA,qBACzB,aAAA,CAAc,oBAAA,CAAqB,SAAA"}
@@ -0,0 +1,7 @@
1
+ //#region src/stream/queue-adapter.ts
2
+ /** Frozen empty queue, reused for referential stability across resets. */
3
+ const EMPTY_QUEUE = Object.freeze([]);
4
+ //#endregion
5
+ export { EMPTY_QUEUE };
6
+
7
+ //# sourceMappingURL=queue-adapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"queue-adapter.js","names":[],"sources":["../../src/stream/queue-adapter.ts"],"sourcesContent":["import type { RunsClient } from \"../client/index.js\";\nimport type { StreamSubmitOptions } from \"./types.js\";\n\n/**\n * What {@link AgentServerQueueAdapter} needs to back `\"enqueue\"` with\n * real, durable server-side runs. Supplied from `client.runs` when\n * `queue: \"server\"` is set; see {@link SubmitCoordinator}.\n */\nexport type ServerQueueCapability = Pick<\n RunsClient,\n \"create\" | \"list\" | \"cancel\"\n>;\n\n/** A single queued submission. */\nexport interface SubmissionQueueEntry<\n StateType extends object = Record<string, unknown>,\n> {\n /** Stable id minted on enqueue (uuidv7) or the server run id for a hydrated entry. */\n readonly id: string;\n /** Server run id, once accepted. Absent while a dispatch is still in flight. */\n readonly runId?: string;\n /** Original submit input, narrowed to the partial state shape. */\n readonly values: Partial<StateType> | null | undefined;\n /** Original submit options, minus the strategy slot which is reset on drain. */\n readonly options?: StreamSubmitOptions<StateType>;\n /** Wall-clock timestamp at enqueue. */\n readonly createdAt: Date;\n}\n\n/**\n * Read-only snapshot of the queue. The queue store hands this out\n * directly; consumers must not mutate the array.\n */\nexport type SubmissionQueueSnapshot<\n StateType extends object = Record<string, unknown>,\n> = ReadonlyArray<SubmissionQueueEntry<StateType>>;\n\n/** Frozen empty queue, reused for referential stability across resets. */\nexport const EMPTY_QUEUE: SubmissionQueueSnapshot<never> = Object.freeze([]);\n\n/**\n * Pluggable backing for `useStream`'s \"enqueue\" multitask strategy. Owns\n * how a deferred submission is tracked while it waits its turn: where\n * it's recorded, how it's hydrated on load, how it learns a run started,\n * and how it's cancelled. {@link SubmitCoordinator} only delegates to\n * this for the `\"enqueue\"` case; see {@link LocalQueueAdapter}\n * (`queue-adapter-local.ts`) and {@link AgentServerQueueAdapter}\n * (`queue-adapter-agent-server.ts`) for the two implementations.\n *\n * Not exported from the package. Which implementation backs a given\n * call is decided by `useStream`'s `queue` option (`\"local\"` by\n * default), never a class a consumer picks between directly.\n */\nexport interface QueueAdapter<\n StateType extends object = Record<string, unknown>,\n> {\n /**\n * Populate the queue store from whatever this adapter considers the\n * source of truth: a real `runs.list` hydrate, or a no-op for the\n * local adapter. Called once, when the controller first binds to a\n * thread.\n */\n hydrate(threadId: string): Promise<void>;\n\n /**\n * Record a deferred submission. Resolves once it's safe to consider\n * *accepted*: for the server-backed adapter, once the server has\n * durably recorded it.\n */\n enqueue(\n threadId: string,\n values: Partial<StateType> | null | undefined,\n options: StreamSubmitOptions<StateType> | undefined\n ): Promise<void>;\n\n /**\n * Cancel one queued entry by its {@link SubmissionQueueEntry.id}.\n * Idempotent: cancelling an entry that's already started running or\n * was already removed resolves `false` rather than throwing.\n */\n cancel(id: string): Promise<boolean>;\n\n /** Cancel and remove every currently-queued entry. */\n clear(): Promise<void>;\n\n /**\n * Release whatever this adapter is watching. Called once, on\n * controller disposal or thread rebind.\n */\n detach(): void;\n\n /**\n * Called whenever the active run settles (nothing currently in\n * flight). Only meaningful for adapters that gate dispatch on\n * client-side timing: {@link LocalQueueAdapter} uses this to drain\n * its next entry via `dispatch`. {@link AgentServerQueueAdapter}\n * omits it entirely: the server's own scheduler decides when the next\n * pending run starts and the adapter only observes it.\n */\n onIdle?(\n dispatch: (\n values: unknown,\n options: StreamSubmitOptions<StateType> | undefined\n ) => Promise<void>\n ): void;\n}\n"],"mappings":";;AAsCA,MAAa,cAA8C,OAAO,OAAO,EAAE,CAAC"}