@librechat/agents 3.4.1 → 3.4.2

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 (128) hide show
  1. package/dist/cjs/agents/AgentContext.cjs.map +1 -1
  2. package/dist/cjs/graphs/Graph.cjs +57 -33
  3. package/dist/cjs/graphs/Graph.cjs.map +1 -1
  4. package/dist/cjs/graphs/MultiAgentGraph.cjs +81 -33
  5. package/dist/cjs/graphs/MultiAgentGraph.cjs.map +1 -1
  6. package/dist/cjs/graphs/applyGraphRuntimeConfig.cjs +14 -0
  7. package/dist/cjs/graphs/applyGraphRuntimeConfig.cjs.map +1 -0
  8. package/dist/cjs/graphs/createGraph.cjs +15 -0
  9. package/dist/cjs/graphs/createGraph.cjs.map +1 -0
  10. package/dist/cjs/graphs/index.cjs +1 -0
  11. package/dist/cjs/hooks/createWorkspacePolicyHook.cjs +1 -1
  12. package/dist/cjs/main.cjs +20 -11
  13. package/dist/cjs/run.cjs +48 -38
  14. package/dist/cjs/run.cjs.map +1 -1
  15. package/dist/cjs/session/JsonlSessionStore.cjs +2 -2
  16. package/dist/cjs/tools/SubagentTool.cjs +4 -4
  17. package/dist/cjs/tools/SubagentTool.cjs.map +1 -1
  18. package/dist/cjs/tools/ToolNode.cjs +13 -9
  19. package/dist/cjs/tools/ToolNode.cjs.map +1 -1
  20. package/dist/cjs/tools/eagerEventExecution.cjs +1 -0
  21. package/dist/cjs/tools/local/LocalExecutionEngine.cjs +3 -3
  22. package/dist/cjs/tools/local/LocalProgrammaticToolCalling.cjs +2 -2
  23. package/dist/cjs/tools/search/rerankers.cjs +154 -1
  24. package/dist/cjs/tools/search/rerankers.cjs.map +1 -1
  25. package/dist/cjs/tools/search/tool.cjs +4 -1
  26. package/dist/cjs/tools/search/tool.cjs.map +1 -1
  27. package/dist/cjs/tools/subagent/SubagentExecutionRegistry.cjs +601 -0
  28. package/dist/cjs/tools/subagent/SubagentExecutionRegistry.cjs.map +1 -0
  29. package/dist/cjs/tools/subagent/SubagentExecutor.cjs +672 -343
  30. package/dist/cjs/tools/subagent/SubagentExecutor.cjs.map +1 -1
  31. package/dist/cjs/tools/subagent/SubagentReplay.cjs +3 -1
  32. package/dist/cjs/tools/subagent/SubagentReplay.cjs.map +1 -1
  33. package/dist/cjs/tools/subagent/childGraphConfig.cjs +278 -0
  34. package/dist/cjs/tools/subagent/childGraphConfig.cjs.map +1 -0
  35. package/dist/cjs/tools/subagent/index.cjs +1 -0
  36. package/dist/cjs/tools/subagent/runtimeLimits.cjs +5 -0
  37. package/dist/cjs/tools/subagent/runtimeLimits.cjs.map +1 -0
  38. package/dist/esm/agents/AgentContext.mjs.map +1 -1
  39. package/dist/esm/graphs/Graph.mjs +57 -33
  40. package/dist/esm/graphs/Graph.mjs.map +1 -1
  41. package/dist/esm/graphs/MultiAgentGraph.mjs +81 -33
  42. package/dist/esm/graphs/MultiAgentGraph.mjs.map +1 -1
  43. package/dist/esm/graphs/applyGraphRuntimeConfig.mjs +14 -0
  44. package/dist/esm/graphs/applyGraphRuntimeConfig.mjs.map +1 -0
  45. package/dist/esm/graphs/createGraph.mjs +15 -0
  46. package/dist/esm/graphs/createGraph.mjs.map +1 -0
  47. package/dist/esm/graphs/index.mjs +1 -0
  48. package/dist/esm/hooks/createWorkspacePolicyHook.mjs +1 -1
  49. package/dist/esm/main.mjs +12 -10
  50. package/dist/esm/run.mjs +48 -38
  51. package/dist/esm/run.mjs.map +1 -1
  52. package/dist/esm/session/JsonlSessionStore.mjs +2 -2
  53. package/dist/esm/tools/SubagentTool.mjs +4 -4
  54. package/dist/esm/tools/SubagentTool.mjs.map +1 -1
  55. package/dist/esm/tools/ToolNode.mjs +13 -9
  56. package/dist/esm/tools/ToolNode.mjs.map +1 -1
  57. package/dist/esm/tools/eagerEventExecution.mjs +1 -1
  58. package/dist/esm/tools/local/LocalExecutionEngine.mjs +3 -3
  59. package/dist/esm/tools/local/LocalProgrammaticToolCalling.mjs +2 -2
  60. package/dist/esm/tools/search/rerankers.mjs +154 -1
  61. package/dist/esm/tools/search/rerankers.mjs.map +1 -1
  62. package/dist/esm/tools/search/tool.mjs +4 -1
  63. package/dist/esm/tools/search/tool.mjs.map +1 -1
  64. package/dist/esm/tools/subagent/SubagentExecutionRegistry.mjs +597 -0
  65. package/dist/esm/tools/subagent/SubagentExecutionRegistry.mjs.map +1 -0
  66. package/dist/esm/tools/subagent/SubagentExecutor.mjs +672 -343
  67. package/dist/esm/tools/subagent/SubagentExecutor.mjs.map +1 -1
  68. package/dist/esm/tools/subagent/SubagentReplay.mjs +3 -1
  69. package/dist/esm/tools/subagent/SubagentReplay.mjs.map +1 -1
  70. package/dist/esm/tools/subagent/childGraphConfig.mjs +272 -0
  71. package/dist/esm/tools/subagent/childGraphConfig.mjs.map +1 -0
  72. package/dist/esm/tools/subagent/index.mjs +1 -0
  73. package/dist/esm/tools/subagent/runtimeLimits.mjs +5 -0
  74. package/dist/esm/tools/subagent/runtimeLimits.mjs.map +1 -0
  75. package/dist/types/agents/AgentContext.d.ts +1 -1
  76. package/dist/types/graphs/Graph.d.ts +7 -2
  77. package/dist/types/graphs/MultiAgentGraph.d.ts +7 -1
  78. package/dist/types/graphs/applyGraphRuntimeConfig.d.ts +3 -0
  79. package/dist/types/graphs/createGraph.d.ts +13 -0
  80. package/dist/types/graphs/graphFactory.d.ts +13 -0
  81. package/dist/types/graphs/index.d.ts +2 -0
  82. package/dist/types/run.d.ts +2 -2
  83. package/dist/types/tools/SubagentTool.d.ts +1 -1
  84. package/dist/types/tools/search/rerankers.d.ts +28 -0
  85. package/dist/types/tools/search/types.d.ts +38 -1
  86. package/dist/types/tools/subagent/SubagentExecutionRegistry.d.ts +171 -0
  87. package/dist/types/tools/subagent/SubagentExecutor.d.ts +32 -37
  88. package/dist/types/tools/subagent/SubagentReplay.d.ts +5 -1
  89. package/dist/types/tools/subagent/childGraphConfig.d.ts +37 -0
  90. package/dist/types/tools/subagent/index.d.ts +1 -1
  91. package/dist/types/tools/subagent/runtimeLimits.d.ts +4 -0
  92. package/dist/types/types/graph.d.ts +184 -19
  93. package/package.json +3 -1
  94. package/src/agents/AgentContext.ts +1 -1
  95. package/src/graphs/Graph.ts +111 -60
  96. package/src/graphs/MultiAgentGraph.ts +149 -47
  97. package/src/graphs/__tests__/MultiAgentGraph.test.ts +86 -0
  98. package/src/graphs/__tests__/composition.smoke.test.ts +152 -0
  99. package/src/graphs/__tests__/createGraph.test.ts +206 -0
  100. package/src/graphs/applyGraphRuntimeConfig.ts +25 -0
  101. package/src/graphs/createGraph.ts +32 -0
  102. package/src/graphs/graphFactory.ts +12 -0
  103. package/src/graphs/index.ts +2 -0
  104. package/src/run.ts +50 -38
  105. package/src/specs/graph-subagent.live.test.ts +242 -0
  106. package/src/specs/graph-subagent.test.ts +322 -0
  107. package/src/specs/langfuse-routing.integration.test.ts +120 -1
  108. package/src/specs/subagent.test.ts +130 -4
  109. package/src/tools/SubagentTool.ts +4 -4
  110. package/src/tools/ToolNode.ts +22 -10
  111. package/src/tools/__tests__/SubagentExecutor.test.ts +198 -9
  112. package/src/tools/__tests__/SubagentReplay.test.ts +29 -0
  113. package/src/tools/__tests__/directToolHITLResumeScope.test.ts +28 -2
  114. package/src/tools/__tests__/subagentHooks.test.ts +90 -3
  115. package/src/tools/search/rag-api-reranker.test.ts +891 -0
  116. package/src/tools/search/rerankers.ts +260 -0
  117. package/src/tools/search/tool.ts +6 -0
  118. package/src/tools/search/types.ts +45 -1
  119. package/src/tools/subagent/SubagentExecutionRegistry.ts +1159 -0
  120. package/src/tools/subagent/SubagentExecutor.ts +1245 -563
  121. package/src/tools/subagent/SubagentReplay.ts +10 -1
  122. package/src/tools/subagent/__tests__/SubagentExecutionRegistry.test.ts +637 -0
  123. package/src/tools/subagent/__tests__/SubagentExecutor.lazy.test.ts +3054 -0
  124. package/src/tools/subagent/__tests__/childGraphConfig.test.ts +521 -0
  125. package/src/tools/subagent/childGraphConfig.ts +694 -0
  126. package/src/tools/subagent/index.ts +6 -0
  127. package/src/tools/subagent/runtimeLimits.ts +7 -0
  128. package/src/types/graph.ts +217 -19
@@ -0,0 +1,597 @@
1
+ import { SUBAGENT_RESUME_ATTEMPT_CONFIG_KEY, getSubagentResumeManifest } from "./SubagentReplay.mjs";
2
+ //#region src/tools/subagent/SubagentExecutionRegistry.ts
3
+ const SUBAGENT_THREAD_ID_PREFIX = "subagent:";
4
+ const SUBAGENT_EXECUTION_INVALIDATED_MESSAGE = "Subagent execution was invalidated.";
5
+ function getPreparationResourceKey(kind, identity) {
6
+ return JSON.stringify([kind, identity]);
7
+ }
8
+ function attachRollbackError(cause, rollbackError) {
9
+ if (!(cause instanceof Error)) return;
10
+ try {
11
+ Object.defineProperty(cause, "rollbackError", {
12
+ configurable: true,
13
+ value: rollbackError
14
+ });
15
+ } catch {
16
+ return;
17
+ }
18
+ }
19
+ var PreparationLease = class {
20
+ owners;
21
+ token;
22
+ checkpointKey;
23
+ approvalKey;
24
+ constructor(owners, token, checkpointKey, approvalKey) {
25
+ this.owners = owners;
26
+ this.token = token;
27
+ this.checkpointKey = checkpointKey;
28
+ this.approvalKey = approvalKey;
29
+ }
30
+ get ownsCheckpoint() {
31
+ return this.owns(this.checkpointKey);
32
+ }
33
+ get ownsCreatedCheckpoint() {
34
+ return this.isCreated(this.checkpointKey);
35
+ }
36
+ get ownsApprovalScope() {
37
+ return this.owns(this.approvalKey);
38
+ }
39
+ get ownsCreatedApprovalScope() {
40
+ return this.isCreated(this.approvalKey);
41
+ }
42
+ assertOwned() {
43
+ if (!this.owns(this.checkpointKey) || !this.owns(this.approvalKey)) throw new SubagentExecutionInvalidatedError();
44
+ }
45
+ markCheckpointCreated(cleanup) {
46
+ this.markCreated(this.checkpointKey, cleanup);
47
+ }
48
+ markApprovalScopeCreated(cleanup) {
49
+ this.markCreated(this.approvalKey, cleanup);
50
+ }
51
+ release() {
52
+ this.releaseResource(this.checkpointKey);
53
+ this.releaseResource(this.approvalKey);
54
+ }
55
+ async rollback(cause, cleanup) {
56
+ let rollbackError;
57
+ let rollbackFailed = false;
58
+ try {
59
+ await cleanup?.(this);
60
+ } catch (error) {
61
+ rollbackError = error;
62
+ rollbackFailed = true;
63
+ }
64
+ const resourceRollback = await this.rollbackOwnedResources();
65
+ if (!rollbackFailed && resourceRollback.failed) {
66
+ rollbackError = resourceRollback.error;
67
+ rollbackFailed = true;
68
+ }
69
+ try {
70
+ if (rollbackFailed) attachRollbackError(cause, rollbackError);
71
+ } finally {
72
+ this.release();
73
+ }
74
+ throw cause;
75
+ }
76
+ owns(key) {
77
+ const owner = this.owners.get(key);
78
+ return owner?.status === "owned" && owner.token === this.token;
79
+ }
80
+ isCreated(key) {
81
+ const owner = this.owners.get(key);
82
+ return owner?.status === "owned" && owner.token === this.token && owner.created;
83
+ }
84
+ markCreated(key, cleanup) {
85
+ const owner = this.owners.get(key);
86
+ if (owner?.status !== "owned" || owner.token !== this.token) throw new SubagentExecutionInvalidatedError();
87
+ owner.created = true;
88
+ owner.cleanup = cleanup;
89
+ }
90
+ async rollbackOwnedResources() {
91
+ const cleanups = [];
92
+ for (const key of [this.checkpointKey, this.approvalKey]) {
93
+ const owner = this.owners.get(key);
94
+ if (owner?.status !== "owned" || owner.token !== this.token) continue;
95
+ if (!owner.created || owner.cleanup == null) {
96
+ this.owners.delete(key);
97
+ continue;
98
+ }
99
+ const state = {
100
+ status: "cleaning",
101
+ token: this.token
102
+ };
103
+ this.owners.set(key, state);
104
+ cleanups.push({
105
+ key,
106
+ state,
107
+ cleanup: owner.cleanup
108
+ });
109
+ }
110
+ return (await Promise.all(cleanups.map(({ key, state, cleanup }) => this.cleanResource(key, state, cleanup)))).find((result) => result.failed) ?? { failed: false };
111
+ }
112
+ async cleanResource(key, state, cleanup) {
113
+ try {
114
+ await cleanup();
115
+ return { failed: false };
116
+ } catch (error) {
117
+ return {
118
+ failed: true,
119
+ error
120
+ };
121
+ } finally {
122
+ if (this.owners.get(key) === state) this.owners.delete(key);
123
+ }
124
+ }
125
+ releaseResource(key) {
126
+ const owner = this.owners.get(key);
127
+ if (owner?.status === "owned" && owner.token === this.token) this.owners.delete(key);
128
+ }
129
+ };
130
+ function getConfigurable(config) {
131
+ return config?.configurable;
132
+ }
133
+ function getConfigurableString(configurable, key) {
134
+ const value = configurable?.[key];
135
+ return typeof value === "string" && value.length > 0 ? value : void 0;
136
+ }
137
+ function encodeThreadIdentity(identity) {
138
+ return `${SUBAGENT_THREAD_ID_PREFIX}${Buffer.from(JSON.stringify(identity)).toString("base64url")}`;
139
+ }
140
+ function assertSameIdentity(current, next) {
141
+ if (current.childRunId === next.childRunId && current.childThreadId === next.childThreadId && current.approvalExecutionScope === next.approvalExecutionScope) return;
142
+ throw new Error("Subagent execution identity cannot change after binding.");
143
+ }
144
+ function assertCompatibleResumeExecution(current, next) {
145
+ if (current.parentToolCallId === next.parentToolCallId && current.childRunId === next.childRunId && current.subagentType === next.subagentType && current.configId === next.configId) return;
146
+ throw new Error("Subagent resume source cannot change after binding.");
147
+ }
148
+ function assertSameInvocation(current, next) {
149
+ if (current.description === next.description && current.subagentType === next.subagentType && current.configId === next.configId) return;
150
+ throw new SubagentInvocationBindingError();
151
+ }
152
+ function assertSameSettlement(current, next) {
153
+ if (current.definitionAuthority === next.definitionAuthority && current.fingerprint === next.fingerprint && current.subagentType === next.subagentType && current.configId === next.configId) return;
154
+ throw new SubagentSettlementBindingError();
155
+ }
156
+ function getAbortReason(signal) {
157
+ return signal.reason ?? /* @__PURE__ */ new Error("Subagent execution aborted.");
158
+ }
159
+ function getSubagentApprovalExecutionScope(childRunId, resumeAttemptId) {
160
+ return `subagent-approval:${Buffer.from(JSON.stringify([childRunId, resumeAttemptId])).toString("base64url")}`;
161
+ }
162
+ var SubagentExecutionInvalidatedError = class extends Error {
163
+ constructor() {
164
+ super(SUBAGENT_EXECUTION_INVALIDATED_MESSAGE);
165
+ this.name = "SubagentExecutionInvalidatedError";
166
+ }
167
+ };
168
+ var SubagentDefinitionBindingError = class extends Error {
169
+ constructor() {
170
+ super("Subagent effective definition binding cannot change.");
171
+ this.name = "SubagentDefinitionBindingError";
172
+ }
173
+ };
174
+ var SubagentInvocationBindingError = class extends Error {
175
+ constructor() {
176
+ super("Subagent invocation binding cannot change.");
177
+ this.name = "SubagentInvocationBindingError";
178
+ }
179
+ };
180
+ var SubagentSettlementBindingError = class extends Error {
181
+ constructor() {
182
+ super("Subagent settlement binding cannot change.");
183
+ this.name = "SubagentSettlementBindingError";
184
+ }
185
+ };
186
+ /** In-process source of truth for one Durable Subagent Execution. */
187
+ var SubagentExecutionRecord = class {
188
+ address;
189
+ identityValue;
190
+ bindingValue;
191
+ bindingAuthority;
192
+ invocationValue;
193
+ settlementValue;
194
+ settledOutputValue;
195
+ resumeExecutionValue;
196
+ activeRunValue;
197
+ completedResultValue;
198
+ resolvedConfigValue;
199
+ pendingIdentityResolution;
200
+ pendingConfigResolution;
201
+ pendingExecution;
202
+ pendingSettlement;
203
+ phaseValue = "registered";
204
+ startedValue = false;
205
+ completedValue = false;
206
+ settledValue = false;
207
+ constructor(address, resumeExecution) {
208
+ this.address = address;
209
+ this.resumeExecutionValue = resumeExecution;
210
+ }
211
+ get snapshot() {
212
+ return {
213
+ address: this.address,
214
+ phase: this.phaseValue,
215
+ ...this.identityValue == null ? {} : { identity: this.identityValue },
216
+ ...this.bindingValue == null ? {} : { binding: this.bindingValue },
217
+ ...this.invocationValue == null ? {} : { invocation: this.invocationValue },
218
+ ...this.settlementValue == null ? {} : { settlement: this.settlementValue },
219
+ ...this.resumeExecutionValue == null ? {} : { resumeExecution: this.resumeExecutionValue },
220
+ ...this.activeRunValue == null ? {} : { activeRun: this.activeRunValue },
221
+ ...this.completedResultValue == null ? {} : { completedResult: this.completedResultValue },
222
+ ...this.resolvedConfigValue == null ? {} : { resolvedConfig: this.resolvedConfigValue },
223
+ started: this.startedValue,
224
+ completed: this.completedValue,
225
+ resolvingIdentity: this.pendingIdentityResolution != null,
226
+ resolving: this.pendingConfigResolution != null,
227
+ executing: this.pendingExecution != null,
228
+ settling: this.pendingSettlement != null,
229
+ settled: this.settledValue
230
+ };
231
+ }
232
+ get identity() {
233
+ return this.identityValue;
234
+ }
235
+ get binding() {
236
+ return this.bindingValue;
237
+ }
238
+ get resumeExecution() {
239
+ return this.resumeExecutionValue;
240
+ }
241
+ get invocation() {
242
+ return this.invocationValue;
243
+ }
244
+ get activeRun() {
245
+ return this.activeRunValue;
246
+ }
247
+ get settlement() {
248
+ return this.settlementValue;
249
+ }
250
+ get settledOutput() {
251
+ return this.settledOutputValue;
252
+ }
253
+ get completedResult() {
254
+ return this.completedResultValue;
255
+ }
256
+ get resolvedConfig() {
257
+ return this.resolvedConfigValue;
258
+ }
259
+ get started() {
260
+ return this.startedValue;
261
+ }
262
+ get completed() {
263
+ return this.completedValue;
264
+ }
265
+ assertUsable(signal) {
266
+ if (signal?.aborted === true) throw getAbortReason(signal);
267
+ if (this.phaseValue === "invalidated") throw new SubagentExecutionInvalidatedError();
268
+ }
269
+ attachResumeExecution(resumeExecution) {
270
+ if (resumeExecution == null) return;
271
+ if (this.resumeExecutionValue != null) {
272
+ assertCompatibleResumeExecution(this.resumeExecutionValue, resumeExecution);
273
+ return;
274
+ }
275
+ this.resumeExecutionValue = resumeExecution;
276
+ }
277
+ bindIdentity(identity) {
278
+ this.assertUsable();
279
+ if (this.identityValue != null) {
280
+ assertSameIdentity(this.identityValue, identity);
281
+ return;
282
+ }
283
+ this.identityValue = Object.freeze({ ...identity });
284
+ }
285
+ resolveIdentity(resolve) {
286
+ this.assertUsable();
287
+ if (this.identityValue != null) return Promise.resolve(this.identityValue);
288
+ if (this.pendingIdentityResolution != null) return this.pendingIdentityResolution;
289
+ const pending = Promise.resolve().then(() => {
290
+ this.assertCurrentIdentityResolution(pending);
291
+ return resolve();
292
+ }).then(async (resolution) => {
293
+ try {
294
+ this.assertCurrentIdentityResolution(pending);
295
+ resolution.lease.assertOwned();
296
+ resolution.commit?.(resolution.lease);
297
+ this.assertCurrentIdentityResolution(pending);
298
+ resolution.lease.assertOwned();
299
+ this.bindIdentity(resolution.identity);
300
+ const boundIdentity = this.identityValue;
301
+ if (boundIdentity == null) throw new SubagentExecutionInvalidatedError();
302
+ resolution.lease.release();
303
+ return boundIdentity;
304
+ } catch (error) {
305
+ return resolution.lease.rollback(error, async (lease) => {
306
+ await resolution.rollback?.(lease);
307
+ });
308
+ }
309
+ }).finally(() => {
310
+ if (this.pendingIdentityResolution === pending) this.pendingIdentityResolution = void 0;
311
+ });
312
+ this.pendingIdentityResolution = pending;
313
+ return pending;
314
+ }
315
+ bindDefinition(binding, authority) {
316
+ this.assertUsable();
317
+ if (this.bindingAuthority === "effective") {
318
+ if (authority === "provisional") return;
319
+ if (this.bindingValue?.subagentType !== binding.subagentType || this.bindingValue?.configId !== binding.configId) throw new SubagentDefinitionBindingError();
320
+ return;
321
+ }
322
+ if (authority === "provisional" && this.bindingValue != null) return;
323
+ this.bindingValue = Object.freeze({ ...binding });
324
+ this.bindingAuthority = authority;
325
+ }
326
+ resolveConfig(resolve, signal) {
327
+ this.assertUsable(signal);
328
+ if (this.resolvedConfigValue != null) return Promise.resolve(this.resolvedConfigValue);
329
+ if (this.pendingConfigResolution != null) return this.pendingConfigResolution;
330
+ const pending = Promise.resolve().then(resolve).then((resolvedConfig) => {
331
+ this.assertUsable(signal);
332
+ if (this.pendingConfigResolution !== pending) throw new SubagentExecutionInvalidatedError();
333
+ this.resolvedConfigValue = resolvedConfig;
334
+ return resolvedConfig;
335
+ }).finally(() => {
336
+ if (this.pendingConfigResolution === pending) this.pendingConfigResolution = void 0;
337
+ });
338
+ this.pendingConfigResolution = pending;
339
+ return pending;
340
+ }
341
+ execute(invocation, execute) {
342
+ this.bindDefinition({
343
+ subagentType: invocation.subagentType,
344
+ ...invocation.configId == null ? {} : { configId: invocation.configId }
345
+ }, "effective");
346
+ this.bindInvocation(invocation);
347
+ if (this.pendingExecution != null) return this.pendingExecution;
348
+ const pending = Promise.resolve().then(execute).finally(() => {
349
+ if (this.pendingExecution === pending) this.pendingExecution = void 0;
350
+ });
351
+ this.pendingExecution = pending;
352
+ return pending;
353
+ }
354
+ settle(settlement, settledOutput, persist) {
355
+ this.bindDefinition({
356
+ ...settlement.subagentType == null ? {} : { subagentType: settlement.subagentType },
357
+ ...settlement.configId == null ? {} : { configId: settlement.configId }
358
+ }, settlement.definitionAuthority);
359
+ this.bindInvocation(settlement.invocation);
360
+ if (this.settlementValue != null) assertSameSettlement(this.settlementValue, settlement);
361
+ else this.settlementValue = Object.freeze({
362
+ ...settlement,
363
+ invocation: Object.freeze({ ...settlement.invocation })
364
+ });
365
+ if (this.settledValue) return Promise.resolve();
366
+ if (this.pendingSettlement != null) return this.pendingSettlement;
367
+ const pending = Promise.resolve().then(persist).then(() => {
368
+ this.assertUsable();
369
+ if (this.pendingSettlement !== pending) throw new SubagentExecutionInvalidatedError();
370
+ this.settledValue = true;
371
+ this.settledOutputValue = settledOutput;
372
+ this.activeRunValue = void 0;
373
+ this.completedResultValue = void 0;
374
+ this.resolvedConfigValue = void 0;
375
+ }).finally(() => {
376
+ if (this.pendingSettlement === pending) this.pendingSettlement = void 0;
377
+ });
378
+ this.pendingSettlement = pending;
379
+ return pending;
380
+ }
381
+ activate(activeRun) {
382
+ this.transitionTo("active", [
383
+ "registered",
384
+ "active",
385
+ "interrupted",
386
+ "failed"
387
+ ]);
388
+ if (this.activeRunValue != null) return this.activeRunValue;
389
+ this.activeRunValue = activeRun;
390
+ return activeRun;
391
+ }
392
+ markStarted() {
393
+ this.assertUsable();
394
+ if (this.phaseValue === "completed") throw new Error("Completed subagent execution cannot start again.");
395
+ this.startedValue = true;
396
+ }
397
+ markInterrupted() {
398
+ this.transitionTo("interrupted", ["active", "interrupted"]);
399
+ }
400
+ markFailed() {
401
+ this.transitionTo("failed", [
402
+ "registered",
403
+ "active",
404
+ "interrupted",
405
+ "failed"
406
+ ]);
407
+ this.activeRunValue = void 0;
408
+ this.resolvedConfigValue = void 0;
409
+ }
410
+ markCompleted(result) {
411
+ this.transitionTo("completed", ["active"]);
412
+ this.completedValue = true;
413
+ this.completedResultValue = result;
414
+ this.resolvedConfigValue = void 0;
415
+ }
416
+ releaseActiveRun() {
417
+ const activeRun = this.activeRunValue;
418
+ this.activeRunValue = void 0;
419
+ return activeRun;
420
+ }
421
+ releaseResolvedConfig() {
422
+ this.resolvedConfigValue = void 0;
423
+ }
424
+ invalidate() {
425
+ this.phaseValue = "invalidated";
426
+ this.identityValue = void 0;
427
+ this.bindingValue = void 0;
428
+ this.bindingAuthority = void 0;
429
+ this.invocationValue = void 0;
430
+ this.settlementValue = void 0;
431
+ this.settledOutputValue = void 0;
432
+ this.resumeExecutionValue = void 0;
433
+ this.activeRunValue = void 0;
434
+ this.completedResultValue = void 0;
435
+ this.resolvedConfigValue = void 0;
436
+ this.pendingIdentityResolution = void 0;
437
+ this.pendingConfigResolution = void 0;
438
+ this.pendingExecution = void 0;
439
+ this.pendingSettlement = void 0;
440
+ this.startedValue = false;
441
+ this.completedValue = false;
442
+ this.settledValue = false;
443
+ }
444
+ bindInvocation(invocation) {
445
+ if (this.invocationValue != null) {
446
+ assertSameInvocation(this.invocationValue, invocation);
447
+ return;
448
+ }
449
+ this.invocationValue = Object.freeze({ ...invocation });
450
+ }
451
+ assertCurrentIdentityResolution(pending) {
452
+ this.assertUsable();
453
+ if (this.pendingIdentityResolution !== pending) throw new SubagentExecutionInvalidatedError();
454
+ }
455
+ transitionTo(next, allowed) {
456
+ this.assertUsable();
457
+ if (!allowed.includes(this.phaseValue)) throw new Error(`Cannot transition subagent execution from ${this.phaseValue} to ${next}.`);
458
+ this.phaseValue = next;
459
+ }
460
+ };
461
+ /** Owns canonical addressing, record selection, and invalidation. */
462
+ var SubagentExecutionRegistry = class {
463
+ options;
464
+ recordsByAddress = /* @__PURE__ */ new Map();
465
+ checkpointThreadIds = /* @__PURE__ */ new Set();
466
+ preparationResourceOwners = /* @__PURE__ */ new Map();
467
+ nextPreparationToken = 0;
468
+ constructor(options) {
469
+ this.options = options;
470
+ }
471
+ open(input) {
472
+ const address = this.createAddress(input);
473
+ const resumeExecution = getSubagentResumeManifest(input.parentConfigurable)?.executions.find((execution) => execution.parentToolCallId === input.parentToolCallId);
474
+ const current = this.recordsByAddress.get(address.key);
475
+ if (current != null) {
476
+ current.attachResumeExecution(resumeExecution);
477
+ return current;
478
+ }
479
+ const record = new SubagentExecutionRecord(address, resumeExecution);
480
+ this.recordsByAddress.set(address.key, record);
481
+ return record;
482
+ }
483
+ remove(record) {
484
+ if (this.recordsByAddress.get(record.address.key) !== record) return;
485
+ this.recordsByAddress.delete(record.address.key);
486
+ record.invalidate();
487
+ }
488
+ beginIdentityPreparation(record, identity) {
489
+ record.assertUsable();
490
+ if (this.recordsByAddress.get(record.address.key) !== record) throw new SubagentExecutionInvalidatedError();
491
+ const checkpointKey = getPreparationResourceKey("checkpoint", identity.childThreadId);
492
+ const approvalKey = getPreparationResourceKey("approval", identity.approvalExecutionScope);
493
+ const resourceKeys = [checkpointKey, approvalKey];
494
+ if (resourceKeys.map((key) => this.preparationResourceOwners.get(key)).some((resource) => resource != null)) throw new SubagentExecutionInvalidatedError();
495
+ this.nextPreparationToken += 1;
496
+ const token = this.nextPreparationToken;
497
+ for (let i = 0; i < resourceKeys.length; i++) {
498
+ const key = resourceKeys[i];
499
+ this.preparationResourceOwners.set(key, {
500
+ status: "owned",
501
+ token,
502
+ created: false
503
+ });
504
+ }
505
+ return new PreparationLease(this.preparationResourceOwners, token, checkpointKey, approvalKey);
506
+ }
507
+ selectForResume(selection = {}) {
508
+ if (selection.config != null) return this.selectScopedRecords(selection);
509
+ const counts = /* @__PURE__ */ new Map();
510
+ const candidates = [];
511
+ for (const record of this.recordsByAddress.values()) {
512
+ if (record.identity == null) continue;
513
+ const parentToolCallId = record.address.parentToolCallId;
514
+ if (selection.parentToolCallIds != null && !selection.parentToolCallIds.has(parentToolCallId)) continue;
515
+ candidates.push(record);
516
+ counts.set(parentToolCallId, (counts.get(parentToolCallId) ?? 0) + 1);
517
+ }
518
+ return candidates.filter((record) => counts.get(record.address.parentToolCallId) === 1);
519
+ }
520
+ rememberCheckpointThread(...threadIds) {
521
+ for (const threadId of threadIds) this.checkpointThreadIds.add(threadId);
522
+ }
523
+ getCheckpointThreadIds(getNestedThreadIds) {
524
+ const threadIds = new Set(this.checkpointThreadIds);
525
+ if (getNestedThreadIds == null) return [...threadIds];
526
+ for (const record of this.recordsByAddress.values()) {
527
+ if (record.activeRun == null) continue;
528
+ for (const threadId of getNestedThreadIds(record.activeRun)) threadIds.add(threadId);
529
+ }
530
+ return [...threadIds];
531
+ }
532
+ resetCheckpointThreadIds() {
533
+ this.checkpointThreadIds.clear();
534
+ }
535
+ retireResumeSources(current, sourceThreadIds, retire) {
536
+ for (const record of this.recordsByAddress.values()) {
537
+ if (record === current || record.identity == null || !sourceThreadIds.has(record.identity.childThreadId)) continue;
538
+ try {
539
+ retire(record);
540
+ } finally {
541
+ this.remove(record);
542
+ }
543
+ }
544
+ }
545
+ clear(dispose) {
546
+ for (const record of this.recordsByAddress.values()) {
547
+ dispose?.(record);
548
+ record.invalidate();
549
+ }
550
+ this.recordsByAddress.clear();
551
+ }
552
+ selectScopedRecords(selection) {
553
+ const parentConfigurable = getConfigurable(selection.config);
554
+ const threadId = getConfigurableString(parentConfigurable, "thread_id");
555
+ const parentToolCallIds = selection.parentToolCallIds ?? new Set([...this.recordsByAddress.values()].map((record) => record.address.parentToolCallId));
556
+ const records = [];
557
+ for (const parentToolCallId of parentToolCallIds) {
558
+ const address = this.createAddress({
559
+ threadId,
560
+ parentToolCallId,
561
+ parentConfigurable
562
+ });
563
+ const record = this.recordsByAddress.get(address.key);
564
+ if (record?.identity != null) records.push(record);
565
+ }
566
+ return records;
567
+ }
568
+ createAddress(input) {
569
+ const durableParentId = input.threadId ?? this.options.parentRunId;
570
+ const parentFork = getConfigurableString(input.parentConfigurable, "checkpoint_id") ?? "root";
571
+ const parentBatch = getConfigurableString(input.parentConfigurable, "__librechat_subagent_parent_batch") ?? "batch";
572
+ const configuredResumeAttemptId = getConfigurableString(input.parentConfigurable, SUBAGENT_RESUME_ATTEMPT_CONFIG_KEY);
573
+ const resumeAttemptId = configuredResumeAttemptId ?? this.options.parentRunId;
574
+ const identity = [
575
+ durableParentId,
576
+ parentFork,
577
+ this.options.parentAgentId ?? "agent",
578
+ input.parentToolCallId,
579
+ parentBatch
580
+ ];
581
+ const baseChildThreadId = encodeThreadIdentity(identity);
582
+ const branchChildThreadId = this.options.durable ? encodeThreadIdentity([...identity, resumeAttemptId]) : baseChildThreadId;
583
+ return Object.freeze({
584
+ key: branchChildThreadId,
585
+ baseChildThreadId,
586
+ branchChildThreadId,
587
+ currentChildRunId: `${this.options.parentRunId}_sub_${baseChildThreadId.slice(9)}`,
588
+ explicitResumeAttempt: configuredResumeAttemptId != null,
589
+ parentToolCallId: input.parentToolCallId,
590
+ resumeAttemptId
591
+ });
592
+ }
593
+ };
594
+ //#endregion
595
+ export { SubagentDefinitionBindingError, SubagentExecutionRegistry, SubagentInvocationBindingError, SubagentSettlementBindingError, getSubagentApprovalExecutionScope };
596
+
597
+ //# sourceMappingURL=SubagentExecutionRegistry.mjs.map