@mongodb-js/agent-engine-runner-shared 0.11.3

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 (220) hide show
  1. package/CHANGELOG.md +55 -0
  2. package/LICENSE.md +201 -0
  3. package/README.md +29 -0
  4. package/dist/agent_config.d.ts +167 -0
  5. package/dist/agent_config.d.ts.map +1 -0
  6. package/dist/agent_config.js +544 -0
  7. package/dist/call_interrupted.d.ts +12 -0
  8. package/dist/call_interrupted.d.ts.map +1 -0
  9. package/dist/call_interrupted.js +11 -0
  10. package/dist/checkpoint_workspace.d.ts +25 -0
  11. package/dist/checkpoint_workspace.d.ts.map +1 -0
  12. package/dist/checkpoint_workspace.js +44 -0
  13. package/dist/context.d.ts +235 -0
  14. package/dist/context.d.ts.map +1 -0
  15. package/dist/context.js +322 -0
  16. package/dist/db_config.d.ts +28 -0
  17. package/dist/db_config.d.ts.map +1 -0
  18. package/dist/db_config.js +66 -0
  19. package/dist/db_naming.d.ts +54 -0
  20. package/dist/db_naming.d.ts.map +1 -0
  21. package/dist/db_naming.js +94 -0
  22. package/dist/error_reporting.d.ts +67 -0
  23. package/dist/error_reporting.d.ts.map +1 -0
  24. package/dist/error_reporting.js +311 -0
  25. package/dist/generated/workflow/v1/activity_pb.d.ts +342 -0
  26. package/dist/generated/workflow/v1/activity_pb.d.ts.map +1 -0
  27. package/dist/generated/workflow/v1/activity_pb.js +115 -0
  28. package/dist/generated/workflow/v1/common_pb.d.ts +184 -0
  29. package/dist/generated/workflow/v1/common_pb.d.ts.map +1 -0
  30. package/dist/generated/workflow/v1/common_pb.js +86 -0
  31. package/dist/generated/workflow/v1/runtime_pb.d.ts +200 -0
  32. package/dist/generated/workflow/v1/runtime_pb.d.ts.map +1 -0
  33. package/dist/generated/workflow/v1/runtime_pb.js +40 -0
  34. package/dist/generated/workflow/v1/state_pb.d.ts +254 -0
  35. package/dist/generated/workflow/v1/state_pb.d.ts.map +1 -0
  36. package/dist/generated/workflow/v1/state_pb.js +68 -0
  37. package/dist/guardrails_evaluator/core.d.ts +23 -0
  38. package/dist/guardrails_evaluator/core.d.ts.map +1 -0
  39. package/dist/guardrails_evaluator/core.js +122 -0
  40. package/dist/guardrails_evaluator/index.d.ts +10 -0
  41. package/dist/guardrails_evaluator/index.d.ts.map +1 -0
  42. package/dist/guardrails_evaluator/index.js +11 -0
  43. package/dist/guardrails_evaluator/regex.d.ts +20 -0
  44. package/dist/guardrails_evaluator/regex.d.ts.map +1 -0
  45. package/dist/guardrails_evaluator/regex.js +233 -0
  46. package/dist/hooks.d.ts +109 -0
  47. package/dist/hooks.d.ts.map +1 -0
  48. package/dist/hooks.js +216 -0
  49. package/dist/http_path.d.ts +18 -0
  50. package/dist/http_path.d.ts.map +1 -0
  51. package/dist/http_path.js +53 -0
  52. package/dist/index.d.ts +35 -0
  53. package/dist/index.d.ts.map +1 -0
  54. package/dist/index.js +41 -0
  55. package/dist/launcher.d.ts +130 -0
  56. package/dist/launcher.d.ts.map +1 -0
  57. package/dist/launcher.js +325 -0
  58. package/dist/logger.d.ts +96 -0
  59. package/dist/logger.d.ts.map +1 -0
  60. package/dist/logger.js +204 -0
  61. package/dist/mcp_oauth.d.ts +51 -0
  62. package/dist/mcp_oauth.d.ts.map +1 -0
  63. package/dist/mcp_oauth.js +389 -0
  64. package/dist/mcp_oauth_secret.d.ts +21 -0
  65. package/dist/mcp_oauth_secret.d.ts.map +1 -0
  66. package/dist/mcp_oauth_secret.js +122 -0
  67. package/dist/mcp_tools.d.ts +71 -0
  68. package/dist/mcp_tools.d.ts.map +1 -0
  69. package/dist/mcp_tools.js +301 -0
  70. package/dist/memory_appbound.d.ts +42 -0
  71. package/dist/memory_appbound.d.ts.map +1 -0
  72. package/dist/memory_appbound.js +159 -0
  73. package/dist/memory_writer.d.ts +49 -0
  74. package/dist/memory_writer.d.ts.map +1 -0
  75. package/dist/memory_writer.js +171 -0
  76. package/dist/metrics.d.ts +84 -0
  77. package/dist/metrics.d.ts.map +1 -0
  78. package/dist/metrics.js +205 -0
  79. package/dist/models.d.ts +1458 -0
  80. package/dist/models.d.ts.map +1 -0
  81. package/dist/models.js +1726 -0
  82. package/dist/node_logger.d.ts +43 -0
  83. package/dist/node_logger.d.ts.map +1 -0
  84. package/dist/node_logger.js +158 -0
  85. package/dist/owner_callback.d.ts +16 -0
  86. package/dist/owner_callback.d.ts.map +1 -0
  87. package/dist/owner_callback.js +40 -0
  88. package/dist/progress.d.ts +57 -0
  89. package/dist/progress.d.ts.map +1 -0
  90. package/dist/progress.js +140 -0
  91. package/dist/runtime.d.ts +131 -0
  92. package/dist/runtime.d.ts.map +1 -0
  93. package/dist/runtime.js +351 -0
  94. package/dist/secure_llm_proxy.d.ts +115 -0
  95. package/dist/secure_llm_proxy.d.ts.map +1 -0
  96. package/dist/secure_llm_proxy.js +922 -0
  97. package/dist/secure_wrapper.d.ts +332 -0
  98. package/dist/secure_wrapper.d.ts.map +1 -0
  99. package/dist/secure_wrapper.js +1249 -0
  100. package/dist/server/aer.d.ts +61 -0
  101. package/dist/server/aer.d.ts.map +1 -0
  102. package/dist/server/aer.js +1124 -0
  103. package/dist/server/auth.d.ts +56 -0
  104. package/dist/server/auth.d.ts.map +1 -0
  105. package/dist/server/auth.js +132 -0
  106. package/dist/server/base.d.ts +104 -0
  107. package/dist/server/base.d.ts.map +1 -0
  108. package/dist/server/base.js +150 -0
  109. package/dist/server/callInterrupt.d.ts +49 -0
  110. package/dist/server/callInterrupt.d.ts.map +1 -0
  111. package/dist/server/callInterrupt.js +68 -0
  112. package/dist/server/callback_delivery.d.ts +14 -0
  113. package/dist/server/callback_delivery.d.ts.map +1 -0
  114. package/dist/server/callback_delivery.js +141 -0
  115. package/dist/server/chunk_types.d.ts +50 -0
  116. package/dist/server/chunk_types.d.ts.map +1 -0
  117. package/dist/server/chunk_types.js +62 -0
  118. package/dist/server/cors.d.ts +52 -0
  119. package/dist/server/cors.d.ts.map +1 -0
  120. package/dist/server/cors.js +107 -0
  121. package/dist/server/drain.d.ts +169 -0
  122. package/dist/server/drain.d.ts.map +1 -0
  123. package/dist/server/drain.js +455 -0
  124. package/dist/server/function.d.ts +77 -0
  125. package/dist/server/function.d.ts.map +1 -0
  126. package/dist/server/function.js +337 -0
  127. package/dist/server/http_retry.d.ts +37 -0
  128. package/dist/server/http_retry.d.ts.map +1 -0
  129. package/dist/server/http_retry.js +157 -0
  130. package/dist/server/index.d.ts +7 -0
  131. package/dist/server/index.d.ts.map +1 -0
  132. package/dist/server/index.js +5 -0
  133. package/dist/server/metadata.d.ts +50 -0
  134. package/dist/server/metadata.d.ts.map +1 -0
  135. package/dist/server/metadata.js +193 -0
  136. package/dist/server/oe_url.d.ts +36 -0
  137. package/dist/server/oe_url.d.ts.map +1 -0
  138. package/dist/server/oe_url.js +50 -0
  139. package/dist/server/owner_url.d.ts +35 -0
  140. package/dist/server/owner_url.d.ts.map +1 -0
  141. package/dist/server/owner_url.js +146 -0
  142. package/dist/server/query.d.ts +42 -0
  143. package/dist/server/query.d.ts.map +1 -0
  144. package/dist/server/query.js +28 -0
  145. package/dist/server/tool.d.ts +138 -0
  146. package/dist/server/tool.d.ts.map +1 -0
  147. package/dist/server/tool.js +1017 -0
  148. package/dist/span_names.d.ts +21 -0
  149. package/dist/span_names.d.ts.map +1 -0
  150. package/dist/span_names.js +31 -0
  151. package/dist/structured_logging/constants.d.ts +17 -0
  152. package/dist/structured_logging/constants.d.ts.map +1 -0
  153. package/dist/structured_logging/constants.js +71 -0
  154. package/dist/structured_logging/env.d.ts +18 -0
  155. package/dist/structured_logging/env.d.ts.map +1 -0
  156. package/dist/structured_logging/env.js +39 -0
  157. package/dist/structured_logging/install.d.ts +56 -0
  158. package/dist/structured_logging/install.d.ts.map +1 -0
  159. package/dist/structured_logging/install.js +107 -0
  160. package/dist/structured_logging/layout.d.ts +9 -0
  161. package/dist/structured_logging/layout.d.ts.map +1 -0
  162. package/dist/structured_logging/layout.js +144 -0
  163. package/dist/structured_logging/serialize.d.ts +27 -0
  164. package/dist/structured_logging/serialize.d.ts.map +1 -0
  165. package/dist/structured_logging/serialize.js +61 -0
  166. package/dist/structured_logging/stdio_capture.d.ts +59 -0
  167. package/dist/structured_logging/stdio_capture.d.ts.map +1 -0
  168. package/dist/structured_logging/stdio_capture.js +164 -0
  169. package/dist/structured_logging/uncaught.d.ts +14 -0
  170. package/dist/structured_logging/uncaught.d.ts.map +1 -0
  171. package/dist/structured_logging/uncaught.js +58 -0
  172. package/dist/structured_logging.d.ts +48 -0
  173. package/dist/structured_logging.d.ts.map +1 -0
  174. package/dist/structured_logging.js +47 -0
  175. package/dist/tls_client.d.ts +61 -0
  176. package/dist/tls_client.d.ts.map +1 -0
  177. package/dist/tls_client.js +298 -0
  178. package/dist/tool_api_error.d.ts +62 -0
  179. package/dist/tool_api_error.d.ts.map +1 -0
  180. package/dist/tool_api_error.js +399 -0
  181. package/dist/tool_memory_ownership.d.ts +10 -0
  182. package/dist/tool_memory_ownership.d.ts.map +1 -0
  183. package/dist/tool_memory_ownership.js +36 -0
  184. package/dist/toolpod_handlers.d.ts +126 -0
  185. package/dist/toolpod_handlers.d.ts.map +1 -0
  186. package/dist/toolpod_handlers.js +1016 -0
  187. package/dist/tracing/exporters.d.ts +51 -0
  188. package/dist/tracing/exporters.d.ts.map +1 -0
  189. package/dist/tracing/exporters.js +327 -0
  190. package/dist/tracing/index.d.ts +3 -0
  191. package/dist/tracing/index.d.ts.map +1 -0
  192. package/dist/tracing/index.js +2 -0
  193. package/dist/tracing/setup.d.ts +76 -0
  194. package/dist/tracing/setup.d.ts.map +1 -0
  195. package/dist/tracing/setup.js +436 -0
  196. package/dist/utils.d.ts +204 -0
  197. package/dist/utils.d.ts.map +1 -0
  198. package/dist/utils.js +867 -0
  199. package/dist/workflow/activity.d.ts +71 -0
  200. package/dist/workflow/activity.d.ts.map +1 -0
  201. package/dist/workflow/activity.js +357 -0
  202. package/dist/workflow/attempt.d.ts +12 -0
  203. package/dist/workflow/attempt.d.ts.map +1 -0
  204. package/dist/workflow/attempt.js +96 -0
  205. package/dist/workflow/client.d.ts +46 -0
  206. package/dist/workflow/client.d.ts.map +1 -0
  207. package/dist/workflow/client.js +299 -0
  208. package/dist/workflow/context.d.ts +37 -0
  209. package/dist/workflow/context.d.ts.map +1 -0
  210. package/dist/workflow/context.js +350 -0
  211. package/dist/workflow/heartbeat.d.ts +15 -0
  212. package/dist/workflow/heartbeat.d.ts.map +1 -0
  213. package/dist/workflow/heartbeat.js +78 -0
  214. package/dist/workflow/index.d.ts +14 -0
  215. package/dist/workflow/index.d.ts.map +1 -0
  216. package/dist/workflow/index.js +10 -0
  217. package/dist/workflow/memory.d.ts +17 -0
  218. package/dist/workflow/memory.d.ts.map +1 -0
  219. package/dist/workflow/memory.js +184 -0
  220. package/package.json +73 -0
@@ -0,0 +1,235 @@
1
+ /**
2
+ * Per-execution context management using AsyncLocalStorage.
3
+ *
4
+ * Mirrors Python `agent_engine_runner_shared/context.py` which uses `contextvars.ContextVar`.
5
+ * Each concurrent execution gets its own isolated context frame, preventing
6
+ * cross-execution contamination of execution_id, wrapper, and OE URL.
7
+ *
8
+ * The single entry point is `runWithExecutionContext(store, fn)`, which runs
9
+ * `fn` inside an isolated frame via `AsyncLocalStorage#run`. The frame is a
10
+ * child that never mutates the parent and is torn down automatically when `fn`
11
+ * settles — even if `fn` throws or spawns async work via setTimeout/Promise.
12
+ *
13
+ * Node's `AsyncLocalStorage#enterWith` (a set/clear-token style) is deliberately
14
+ * avoided: it rebinds the current async frame in place, so the store leaks into
15
+ * the surrounding context and cannot be reliably restored. The Python
16
+ * `set_execution_context` / `clear_execution_context` token pair is collapsed
17
+ * into this callback form, which is the equivalent of Python's
18
+ * `set_execution_context(...)` + `try/finally clear_execution_context(...)`.
19
+ */
20
+ import type { ToolAuthorization } from "./models.js";
21
+ export interface ExecutionStore {
22
+ executionId: string | null;
23
+ wrapper: unknown | null;
24
+ oeUrl: string | null;
25
+ /**
26
+ * Validated replica-specific OE owner callback URL, or null when
27
+ * the request carried none / it failed validation. Owner-preferring
28
+ * transports (e.g. {@link module:progress}) send here first and fall back to
29
+ * `oeUrl` on any owner failure. Already validated against `oeUrl` by the
30
+ * caller (see `server/owner_url.ts`), so consumers trust it as-is.
31
+ */
32
+ oeOwnerUrl: string | null;
33
+ /**
34
+ * One-way owner-failure latch: once an owner pre-attempt fails, later
35
+ * owner-preferring posts in this execution skip the owner URL entirely
36
+ * instead of re-paying the pre-attempt timeout on every emit. A nested
37
+ * object for the same reason as `sessionFinish`: the reference survives
38
+ * store spreads (e.g. {@link runWithSuspendRequestContext}), a reassigned
39
+ * field would not. Mirrors the AER stream path's `onOwnerFailure` discard.
40
+ */
41
+ ownerUrlFailure: {
42
+ failed: boolean;
43
+ };
44
+ requestId: string | null;
45
+ /** Platform trace ID for log correlation. */
46
+ traceId: string | null;
47
+ userId: string | null;
48
+ sessionId: string | null;
49
+ workspaceId: string | null;
50
+ customHeaders: Record<string, string> | null;
51
+ executionMetadata: Record<string, unknown> | null;
52
+ /** Delegated credential injected by OE for tool execution. */
53
+ authorization: ToolAuthorization | null;
54
+ /** Opaque caller-provided invocation payload (the request body beyond `message`). */
55
+ payload: Record<string, unknown> | null;
56
+ /**
57
+ * Execution-wide abort signal (fires on the AER execution timeout). Combined
58
+ * into in-flight OE/LLM fetches via {@link withExecutionSignal} so a timeout
59
+ * cancels active network I/O instead of leaving it to run. Null outside an
60
+ * AER execution (e.g. a single Tool Pod call).
61
+ */
62
+ signal: AbortSignal | null;
63
+ /**
64
+ * Holder for a pending session-finish request. A nested object
65
+ * rather than a bare boolean: the AER reads it from the frame that started
66
+ * the run, while agent code deep in the call chain mutates it in place —
67
+ * the object reference is shared across that chain, a reassigned boolean
68
+ * field on the store would not be.
69
+ */
70
+ sessionFinish: {
71
+ requested: boolean;
72
+ closed: boolean;
73
+ };
74
+ /**
75
+ * Out-of-band suspend signal. Only the author-facing
76
+ * `suspendPayloadToJson` writes it, so untrusted tool-result content — which
77
+ * cannot reach this process-local frame — can never forge a HITL suspend. A
78
+ * nested holder for the same reason as `sessionFinish`: a tool offloaded to a
79
+ * worker thread mutates the shared object, not a reassigned store field.
80
+ */
81
+ suspendRequest: {
82
+ payload: Record<string, unknown> | null;
83
+ };
84
+ }
85
+ export interface OwnerUrlFailureState {
86
+ failed: boolean;
87
+ }
88
+ export type SessionFinishStatus = "requested" | "already_requested" | "unavailable";
89
+ export interface SetExecutionContextArgs {
90
+ executionId: string;
91
+ wrapper: unknown;
92
+ oeUrl: string;
93
+ /** Validated replica-specific OE owner callback URL. */
94
+ oeOwnerUrl?: string | null;
95
+ ownerUrlFailure?: OwnerUrlFailureState;
96
+ requestId?: string | null;
97
+ traceId?: string | null;
98
+ userId?: string | null;
99
+ sessionId?: string | null;
100
+ workspaceId?: string | null;
101
+ customHeaders?: Record<string, string> | null;
102
+ authorization?: ToolAuthorization | null;
103
+ payload?: Record<string, unknown> | null;
104
+ signal?: AbortSignal | null;
105
+ }
106
+ /**
107
+ * Run `fn` with an isolated execution context frame.
108
+ *
109
+ * `storage.run` creates a child frame that never mutates the parent, so cleanup
110
+ * is automatic even if `fn` throws or spawns work via setTimeout/Promise. This
111
+ * is the equivalent of Python's `set_execution_context(...)` followed by a
112
+ * try/finally `clear_execution_context(...)`.
113
+ *
114
+ * @example
115
+ * await runWithExecutionContext({ executionId, wrapper, oeUrl, userId }, async () => {
116
+ * await runAgentLogic() // getCurrentUserId() works anywhere in this call chain
117
+ * })
118
+ */
119
+ export declare function runWithExecutionContext<T>(args: SetExecutionContextArgs, fn: () => T): T;
120
+ export declare function getCurrentExecutionId(): string | null;
121
+ export declare function getCurrentWrapper(): unknown | null;
122
+ export declare function getCurrentOeUrl(): string | null;
123
+ /**
124
+ * Validated replica-specific OE owner callback URL for the current execution,
125
+ * or null when none was forwarded or a previous owner pre-attempt already
126
+ * failed (see {@link reportOeOwnerUrlFailure}). Owner-preferring transports
127
+ * send here first and fall back to {@link getCurrentOeUrl} on any owner
128
+ * failure.
129
+ */
130
+ export declare function getCurrentOeOwnerUrl(): string | null;
131
+ /**
132
+ * Mark the current execution's owner URL unusable. One-way: after this,
133
+ * {@link getCurrentOeOwnerUrl} returns null for the rest of the execution so
134
+ * repeated emits stop re-paying the pre-attempt timeout against a dead owner.
135
+ * Reads `storage.getStore()` directly (like {@link recordSuspendRequest}) so a
136
+ * call outside a run is a no-op instead of mutating the frozen fallback.
137
+ */
138
+ export declare function reportOeOwnerUrlFailure(): void;
139
+ export declare function getCurrentRequestId(): string | null;
140
+ export declare function getCurrentTraceId(): string | null;
141
+ export declare function getCurrentUserId(): string | null;
142
+ export declare function getCurrentSessionId(): string | null;
143
+ export declare function getCurrentWorkspaceId(): string | null;
144
+ /** Delegated authorization for the current execution, if OE injected one. */
145
+ export declare function getCurrentAuthorization(): ToolAuthorization | null;
146
+ /**
147
+ * The opaque caller-provided invocation payload for the current execution
148
+ * (the request body beyond `message`), or null if none was forwarded.
149
+ */
150
+ export declare function getCurrentPayload(): Record<string, unknown> | null;
151
+ /**
152
+ * Caller-provided custom headers, with platform-internal `a2a-` entries
153
+ * stripped — agent code should never see A2A tokens or routing metadata.
154
+ * Internal platform code that needs the full set (e.g. the A2A client) should
155
+ * call {@link getAllCustomHeaders} instead.
156
+ */
157
+ export declare function getCurrentCustomHeaders(): Record<string, string>;
158
+ /** All custom headers including platform-internal `a2a-` entries. */
159
+ export declare function getAllCustomHeaders(): Record<string, string>;
160
+ export declare function getCurrentExecutionMetadata(): Record<string, unknown>;
161
+ /**
162
+ * Combine a per-call `AbortSignal` (e.g. a request/read timeout) with the
163
+ * current execution's abort signal, if one is set. The returned signal aborts
164
+ * when *either* fires, so an execution-wide timeout cancels the in-flight OE/LLM
165
+ * fetch instead of leaving it to run until its own deadline. Returns
166
+ * `callSignal` unchanged when there is no execution signal (e.g. a Tool Pod
167
+ * call outside an AER execution). Mirrors the effect of Python's
168
+ * `asyncio.wait_for` cancelling in-flight I/O on timeout.
169
+ */
170
+ export declare function withExecutionSignal(callSignal: AbortSignal): AbortSignal;
171
+ export interface RecordMemoryMetadataArgs {
172
+ action: string;
173
+ memoryType: string;
174
+ content?: string;
175
+ relevanceScore?: number;
176
+ query?: string;
177
+ }
178
+ /**
179
+ * Attach explicit memory metadata to the current execution step, if one exists.
180
+ * Mutates the metadata object in-place (matching the Python behaviour).
181
+ */
182
+ export declare function recordCurrentMemoryMetadata(args: RecordMemoryMetadataArgs): void;
183
+ /**
184
+ * Record that the agent considers this session finished. Reads directly off
185
+ * `storage.getStore()` (not `current()`) so a call outside a run reports
186
+ * "unavailable" without ever touching the frozen `EMPTY_STORE` fallback.
187
+ * `wrapper` is null for Tool Pod / Function contexts (see server/tool.ts,
188
+ * server/function.ts) — only the AER holds the finish latch, so those
189
+ * contexts must also report "unavailable" rather than a misleading success.
190
+ */
191
+ export declare function requestSessionFinish(): SessionFinishStatus;
192
+ /**
193
+ * Close the current execution's session-finish latch.
194
+ *
195
+ * Called from the AER's `finally` once the execute frame ends (covers
196
+ * success, error, policy-denied, and suspend paths alike). After this,
197
+ * requestSessionFinish() reports "unavailable" instead of promising a
198
+ * release nothing will act on — e.g. a setTimeout or floating promise
199
+ * scheduled during the turn but resolving after it.
200
+ */
201
+ export declare function closeSessionFinish(): void;
202
+ export declare function isSessionFinishRequested(): boolean;
203
+ /**
204
+ * Record an author-intended HITL suspend for the current tool call. Called
205
+ * only by `suspendPayloadToJson`, so the signal's provenance is the tool
206
+ * author's code, not tool-result data. Reads `storage.getStore()` directly so
207
+ * a call outside a run is a no-op instead of mutating the frozen fallback.
208
+ */
209
+ export declare function recordSuspendRequest(payload: Record<string, unknown>): void;
210
+ /**
211
+ * The suspend payload the current tool call requested via
212
+ * `suspendPayloadToJson`, or null if it did not. The Tool Pod reads this after
213
+ * the tool returns to decide whether to report `status: "suspend"`.
214
+ */
215
+ export declare function getRequestedSuspend(): Record<string, unknown> | null;
216
+ /** Run one in-process tool call with an isolated suspend marker. */
217
+ export declare function runWithSuspendRequestContext<T>(fn: () => T): T;
218
+ /** `"customer"` inside a customer-code boundary, else null. */
219
+ export declare function getCurrentLogOrigin(): string | null;
220
+ /**
221
+ * Mark the dynamic extent of customer agent/tool code for log attribution.
222
+ * Nested scopes are a no-op. Missing origin is unclassified, not proven
223
+ * platform-authored.
224
+ */
225
+ export declare function runWithCustomerOrigin<T>(fn: () => T): T;
226
+ /**
227
+ * The per-call stop signal for the in-flight callback-routed tool call.
228
+ * Defined only inside a tool body that declared call-interrupt support; a
229
+ * cooperative body checks it (or forwards it to `fetch` etc.) to stop at its
230
+ * next checkpoint. Undefined everywhere else.
231
+ */
232
+ export declare function getCallAbortSignal(): AbortSignal | undefined;
233
+ /** Run one callback-routed tool body with its per-call abort signal attached. */
234
+ export declare function runWithCallAbortSignal<T>(signal: AbortSignal, fn: () => T): T;
235
+ //# sourceMappingURL=context.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAKH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAErD,MAAM,WAAW,cAAc;IAC7B,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,OAAO,EAAE,OAAO,GAAG,IAAI,CAAC;IACxB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB;;;;;;OAMG;IACH,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B;;;;;;;OAOG;IACH,eAAe,EAAE;QAAE,MAAM,EAAE,OAAO,CAAA;KAAE,CAAC;IACrC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,6CAA6C;IAC7C,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI,CAAC;IAC7C,iBAAiB,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IAClD,8DAA8D;IAC9D,aAAa,EAAE,iBAAiB,GAAG,IAAI,CAAC;IACxC,qFAAqF;IACrF,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IACxC;;;;;OAKG;IACH,MAAM,EAAE,WAAW,GAAG,IAAI,CAAC;IAC3B;;;;;;OAMG;IACH,aAAa,EAAE;QAAE,SAAS,EAAE,OAAO,CAAC;QAAC,MAAM,EAAE,OAAO,CAAA;KAAE,CAAC;IACvD;;;;;;OAMG;IACH,cAAc,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAA;KAAE,CAAC;CAC7D;AAED,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,MAAM,mBAAmB,GAC3B,WAAW,GACX,mBAAmB,GACnB,aAAa,CAAC;AA8BlB,MAAM,WAAW,uBAAuB;IACtC,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,wDAAwD;IACxD,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,eAAe,CAAC,EAAE,oBAAoB,CAAC;IACvC,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI,CAAC;IAC9C,aAAa,CAAC,EAAE,iBAAiB,GAAG,IAAI,CAAC;IACzC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IACzC,MAAM,CAAC,EAAE,WAAW,GAAG,IAAI,CAAC;CAC7B;AA8BD;;;;;;;;;;;;GAYG;AACH,wBAAgB,uBAAuB,CAAC,CAAC,EACvC,IAAI,EAAE,uBAAuB,EAC7B,EAAE,EAAE,MAAM,CAAC,GACV,CAAC,CAEH;AAMD,wBAAgB,qBAAqB,IAAI,MAAM,GAAG,IAAI,CAErD;AAED,wBAAgB,iBAAiB,IAAI,OAAO,GAAG,IAAI,CAElD;AAED,wBAAgB,eAAe,IAAI,MAAM,GAAG,IAAI,CAE/C;AAED;;;;;;GAMG;AACH,wBAAgB,oBAAoB,IAAI,MAAM,GAAG,IAAI,CAGpD;AAED;;;;;;GAMG;AACH,wBAAgB,uBAAuB,IAAI,IAAI,CAK9C;AAED,wBAAgB,mBAAmB,IAAI,MAAM,GAAG,IAAI,CAEnD;AAED,wBAAgB,iBAAiB,IAAI,MAAM,GAAG,IAAI,CAEjD;AAED,wBAAgB,gBAAgB,IAAI,MAAM,GAAG,IAAI,CAEhD;AAED,wBAAgB,mBAAmB,IAAI,MAAM,GAAG,IAAI,CAEnD;AAED,wBAAgB,qBAAqB,IAAI,MAAM,GAAG,IAAI,CAErD;AAED,6EAA6E;AAC7E,wBAAgB,uBAAuB,IAAI,iBAAiB,GAAG,IAAI,CAElE;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAElE;AAED;;;;;GAKG;AACH,wBAAgB,uBAAuB,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAKhE;AAED,qEAAqE;AACrE,wBAAgB,mBAAmB,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAE5D;AAED,wBAAgB,2BAA2B,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAErE;AAED;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CAAC,UAAU,EAAE,WAAW,GAAG,WAAW,CAGxE;AAMD,MAAM,WAAW,wBAAwB;IACvC,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;GAGG;AACH,wBAAgB,2BAA2B,CACzC,IAAI,EAAE,wBAAwB,GAC7B,IAAI,CA6BN;AAMD;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,IAAI,mBAAmB,CAkB1D;AAED;;;;;;;;GAQG;AACH,wBAAgB,kBAAkB,IAAI,IAAI,CAKzC;AAED,wBAAgB,wBAAwB,IAAI,OAAO,CAElD;AAMD;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAK3E;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAEpE;AAED,oEAAoE;AACpE,wBAAgB,4BAA4B,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,GAAG,CAAC,CAM9D;AAKD,+DAA+D;AAC/D,wBAAgB,mBAAmB,IAAI,MAAM,GAAG,IAAI,CAEnD;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,GAAG,CAAC,CAKvD;AAID;;;;;GAKG;AACH,wBAAgB,kBAAkB,IAAI,WAAW,GAAG,SAAS,CAE5D;AAED,iFAAiF;AACjF,wBAAgB,sBAAsB,CAAC,CAAC,EAAE,MAAM,EAAE,WAAW,EAAE,EAAE,EAAE,MAAM,CAAC,GAAG,CAAC,CAE7E"}
@@ -0,0 +1,322 @@
1
+ /**
2
+ * Per-execution context management using AsyncLocalStorage.
3
+ *
4
+ * Mirrors Python `agent_engine_runner_shared/context.py` which uses `contextvars.ContextVar`.
5
+ * Each concurrent execution gets its own isolated context frame, preventing
6
+ * cross-execution contamination of execution_id, wrapper, and OE URL.
7
+ *
8
+ * The single entry point is `runWithExecutionContext(store, fn)`, which runs
9
+ * `fn` inside an isolated frame via `AsyncLocalStorage#run`. The frame is a
10
+ * child that never mutates the parent and is torn down automatically when `fn`
11
+ * settles — even if `fn` throws or spawns async work via setTimeout/Promise.
12
+ *
13
+ * Node's `AsyncLocalStorage#enterWith` (a set/clear-token style) is deliberately
14
+ * avoided: it rebinds the current async frame in place, so the store leaks into
15
+ * the surrounding context and cannot be reliably restored. The Python
16
+ * `set_execution_context` / `clear_execution_context` token pair is collapsed
17
+ * into this callback form, which is the equivalent of Python's
18
+ * `set_execution_context(...)` + `try/finally clear_execution_context(...)`.
19
+ */
20
+ import { AsyncLocalStorage } from "node:async_hooks";
21
+ import { randomUUID } from "node:crypto";
22
+ import { redactText } from "./error_reporting.js";
23
+ // Frozen so accidental mutations to the fallback don't bleed into real stores.
24
+ const EMPTY_STORE = Object.freeze({
25
+ executionId: null,
26
+ wrapper: null,
27
+ oeUrl: null,
28
+ oeOwnerUrl: null,
29
+ ownerUrlFailure: Object.freeze({ failed: false }),
30
+ requestId: null,
31
+ traceId: null,
32
+ userId: null,
33
+ sessionId: null,
34
+ workspaceId: null,
35
+ customHeaders: null,
36
+ executionMetadata: null,
37
+ authorization: null,
38
+ payload: null,
39
+ signal: null,
40
+ // closed: true — nothing outside a run can finish.
41
+ sessionFinish: Object.freeze({ requested: false, closed: true }),
42
+ suspendRequest: Object.freeze({ payload: null }),
43
+ });
44
+ const storage = new AsyncLocalStorage();
45
+ function current() {
46
+ return storage.getStore() ?? EMPTY_STORE;
47
+ }
48
+ function buildStore(args) {
49
+ const parent = storage.getStore();
50
+ return {
51
+ executionId: args.executionId,
52
+ wrapper: args.wrapper,
53
+ oeUrl: args.oeUrl,
54
+ oeOwnerUrl: args.oeOwnerUrl ?? null,
55
+ ownerUrlFailure: args.ownerUrlFailure ??
56
+ (parent?.executionId === args.executionId
57
+ ? parent.ownerUrlFailure
58
+ : { failed: false }),
59
+ traceId: args.traceId ?? null,
60
+ requestId: args.requestId || `req-${randomUUID().replace(/-/g, "").slice(0, 12)}`,
61
+ userId: args.userId ?? null,
62
+ sessionId: args.sessionId ?? null,
63
+ workspaceId: args.workspaceId ?? null,
64
+ customHeaders: args.customHeaders ?? null,
65
+ executionMetadata: {},
66
+ authorization: args.authorization ?? null,
67
+ payload: args.payload ?? null,
68
+ signal: args.signal ?? null,
69
+ sessionFinish: { requested: false, closed: false },
70
+ suspendRequest: { payload: null },
71
+ };
72
+ }
73
+ /**
74
+ * Run `fn` with an isolated execution context frame.
75
+ *
76
+ * `storage.run` creates a child frame that never mutates the parent, so cleanup
77
+ * is automatic even if `fn` throws or spawns work via setTimeout/Promise. This
78
+ * is the equivalent of Python's `set_execution_context(...)` followed by a
79
+ * try/finally `clear_execution_context(...)`.
80
+ *
81
+ * @example
82
+ * await runWithExecutionContext({ executionId, wrapper, oeUrl, userId }, async () => {
83
+ * await runAgentLogic() // getCurrentUserId() works anywhere in this call chain
84
+ * })
85
+ */
86
+ export function runWithExecutionContext(args, fn) {
87
+ return storage.run(buildStore(args), fn);
88
+ }
89
+ // =========================================================================
90
+ // Accessors — read-only views of the current store
91
+ // =========================================================================
92
+ export function getCurrentExecutionId() {
93
+ return current().executionId;
94
+ }
95
+ export function getCurrentWrapper() {
96
+ return current().wrapper;
97
+ }
98
+ export function getCurrentOeUrl() {
99
+ return current().oeUrl;
100
+ }
101
+ /**
102
+ * Validated replica-specific OE owner callback URL for the current execution,
103
+ * or null when none was forwarded or a previous owner pre-attempt already
104
+ * failed (see {@link reportOeOwnerUrlFailure}). Owner-preferring transports
105
+ * send here first and fall back to {@link getCurrentOeUrl} on any owner
106
+ * failure.
107
+ */
108
+ export function getCurrentOeOwnerUrl() {
109
+ const store = current();
110
+ return store.ownerUrlFailure.failed ? null : store.oeOwnerUrl;
111
+ }
112
+ /**
113
+ * Mark the current execution's owner URL unusable. One-way: after this,
114
+ * {@link getCurrentOeOwnerUrl} returns null for the rest of the execution so
115
+ * repeated emits stop re-paying the pre-attempt timeout against a dead owner.
116
+ * Reads `storage.getStore()` directly (like {@link recordSuspendRequest}) so a
117
+ * call outside a run is a no-op instead of mutating the frozen fallback.
118
+ */
119
+ export function reportOeOwnerUrlFailure() {
120
+ const store = storage.getStore();
121
+ if (store !== undefined) {
122
+ store.ownerUrlFailure.failed = true;
123
+ }
124
+ }
125
+ export function getCurrentRequestId() {
126
+ return current().requestId;
127
+ }
128
+ export function getCurrentTraceId() {
129
+ return current().traceId;
130
+ }
131
+ export function getCurrentUserId() {
132
+ return current().userId;
133
+ }
134
+ export function getCurrentSessionId() {
135
+ return current().sessionId;
136
+ }
137
+ export function getCurrentWorkspaceId() {
138
+ return current().workspaceId;
139
+ }
140
+ /** Delegated authorization for the current execution, if OE injected one. */
141
+ export function getCurrentAuthorization() {
142
+ return current().authorization;
143
+ }
144
+ /**
145
+ * The opaque caller-provided invocation payload for the current execution
146
+ * (the request body beyond `message`), or null if none was forwarded.
147
+ */
148
+ export function getCurrentPayload() {
149
+ return current().payload;
150
+ }
151
+ /**
152
+ * Caller-provided custom headers, with platform-internal `a2a-` entries
153
+ * stripped — agent code should never see A2A tokens or routing metadata.
154
+ * Internal platform code that needs the full set (e.g. the A2A client) should
155
+ * call {@link getAllCustomHeaders} instead.
156
+ */
157
+ export function getCurrentCustomHeaders() {
158
+ const headers = current().customHeaders ?? {};
159
+ return Object.fromEntries(Object.entries(headers).filter(([key]) => !key.startsWith("a2a-")));
160
+ }
161
+ /** All custom headers including platform-internal `a2a-` entries. */
162
+ export function getAllCustomHeaders() {
163
+ return current().customHeaders ?? {};
164
+ }
165
+ export function getCurrentExecutionMetadata() {
166
+ return current().executionMetadata ?? {};
167
+ }
168
+ /**
169
+ * Combine a per-call `AbortSignal` (e.g. a request/read timeout) with the
170
+ * current execution's abort signal, if one is set. The returned signal aborts
171
+ * when *either* fires, so an execution-wide timeout cancels the in-flight OE/LLM
172
+ * fetch instead of leaving it to run until its own deadline. Returns
173
+ * `callSignal` unchanged when there is no execution signal (e.g. a Tool Pod
174
+ * call outside an AER execution). Mirrors the effect of Python's
175
+ * `asyncio.wait_for` cancelling in-flight I/O on timeout.
176
+ */
177
+ export function withExecutionSignal(callSignal) {
178
+ const execSignal = current().signal;
179
+ return execSignal ? AbortSignal.any([callSignal, execSignal]) : callSignal;
180
+ }
181
+ /**
182
+ * Attach explicit memory metadata to the current execution step, if one exists.
183
+ * Mutates the metadata object in-place (matching the Python behaviour).
184
+ */
185
+ export function recordCurrentMemoryMetadata(args) {
186
+ const metadata = storage.getStore()?.executionMetadata;
187
+ if (metadata === null || metadata === undefined) {
188
+ return;
189
+ }
190
+ const memory = {
191
+ action: args.action,
192
+ type: args.memoryType,
193
+ };
194
+ if (args.content) {
195
+ // Content and query are user/LLM-derived and this metadata is returned
196
+ // to the UI — scrub credential-shaped fragments before persisting.
197
+ memory["content"] = redactText(args.content);
198
+ }
199
+ if (args.relevanceScore !== undefined) {
200
+ memory["relevance_score"] = args.relevanceScore;
201
+ }
202
+ if (args.query) {
203
+ memory["query"] = redactText(args.query);
204
+ }
205
+ let memoryEvents = metadata["memory_events"];
206
+ if (!Array.isArray(memoryEvents)) {
207
+ memoryEvents = [];
208
+ metadata["memory_events"] = memoryEvents;
209
+ }
210
+ memoryEvents.push(memory);
211
+ metadata["memory"] = memory;
212
+ }
213
+ // =========================================================================
214
+ // Session finish request
215
+ // =========================================================================
216
+ /**
217
+ * Record that the agent considers this session finished. Reads directly off
218
+ * `storage.getStore()` (not `current()`) so a call outside a run reports
219
+ * "unavailable" without ever touching the frozen `EMPTY_STORE` fallback.
220
+ * `wrapper` is null for Tool Pod / Function contexts (see server/tool.ts,
221
+ * server/function.ts) — only the AER holds the finish latch, so those
222
+ * contexts must also report "unavailable" rather than a misleading success.
223
+ */
224
+ export function requestSessionFinish() {
225
+ const store = storage.getStore();
226
+ if (store === undefined || store.wrapper === null) {
227
+ return "unavailable";
228
+ }
229
+ // No lock: this function is synchronous and non-async, so it cannot be
230
+ // preempted mid-call by another callback on the same event loop turn.
231
+ // Only cross-turn ordering (this call vs. closeSessionFinish() from a
232
+ // *different* turn) matters, and that's a plain sequential read/write on
233
+ // this store's own object — never shared with another turn's store.
234
+ if (store.sessionFinish.closed) {
235
+ return "unavailable";
236
+ }
237
+ if (store.sessionFinish.requested) {
238
+ return "already_requested";
239
+ }
240
+ store.sessionFinish.requested = true;
241
+ return "requested";
242
+ }
243
+ /**
244
+ * Close the current execution's session-finish latch.
245
+ *
246
+ * Called from the AER's `finally` once the execute frame ends (covers
247
+ * success, error, policy-denied, and suspend paths alike). After this,
248
+ * requestSessionFinish() reports "unavailable" instead of promising a
249
+ * release nothing will act on — e.g. a setTimeout or floating promise
250
+ * scheduled during the turn but resolving after it.
251
+ */
252
+ export function closeSessionFinish() {
253
+ const store = storage.getStore();
254
+ if (store !== undefined) {
255
+ store.sessionFinish.closed = true;
256
+ }
257
+ }
258
+ export function isSessionFinishRequested() {
259
+ return current().sessionFinish.requested;
260
+ }
261
+ // =========================================================================
262
+ // Suspend request signal
263
+ // =========================================================================
264
+ /**
265
+ * Record an author-intended HITL suspend for the current tool call. Called
266
+ * only by `suspendPayloadToJson`, so the signal's provenance is the tool
267
+ * author's code, not tool-result data. Reads `storage.getStore()` directly so
268
+ * a call outside a run is a no-op instead of mutating the frozen fallback.
269
+ */
270
+ export function recordSuspendRequest(payload) {
271
+ const store = storage.getStore();
272
+ if (store !== undefined) {
273
+ store.suspendRequest.payload = payload;
274
+ }
275
+ }
276
+ /**
277
+ * The suspend payload the current tool call requested via
278
+ * `suspendPayloadToJson`, or null if it did not. The Tool Pod reads this after
279
+ * the tool returns to decide whether to report `status: "suspend"`.
280
+ */
281
+ export function getRequestedSuspend() {
282
+ return current().suspendRequest.payload;
283
+ }
284
+ /** Run one in-process tool call with an isolated suspend marker. */
285
+ export function runWithSuspendRequestContext(fn) {
286
+ const store = storage.getStore();
287
+ if (store === undefined) {
288
+ return fn();
289
+ }
290
+ return storage.run({ ...store, suspendRequest: { payload: null } }, fn);
291
+ }
292
+ const CUSTOMER_ORIGIN = "customer";
293
+ const customerOriginStorage = new AsyncLocalStorage();
294
+ /** `"customer"` inside a customer-code boundary, else null. */
295
+ export function getCurrentLogOrigin() {
296
+ return customerOriginStorage.getStore() === true ? CUSTOMER_ORIGIN : null;
297
+ }
298
+ /**
299
+ * Mark the dynamic extent of customer agent/tool code for log attribution.
300
+ * Nested scopes are a no-op. Missing origin is unclassified, not proven
301
+ * platform-authored.
302
+ */
303
+ export function runWithCustomerOrigin(fn) {
304
+ if (customerOriginStorage.getStore() === true) {
305
+ return fn();
306
+ }
307
+ return customerOriginStorage.run(true, fn);
308
+ }
309
+ const callAbortStorage = new AsyncLocalStorage();
310
+ /**
311
+ * The per-call stop signal for the in-flight callback-routed tool call.
312
+ * Defined only inside a tool body that declared call-interrupt support; a
313
+ * cooperative body checks it (or forwards it to `fetch` etc.) to stop at its
314
+ * next checkpoint. Undefined everywhere else.
315
+ */
316
+ export function getCallAbortSignal() {
317
+ return callAbortStorage.getStore();
318
+ }
319
+ /** Run one callback-routed tool body with its per-call abort signal attached. */
320
+ export function runWithCallAbortSignal(signal, fn) {
321
+ return callAbortStorage.run(signal, fn);
322
+ }
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Single source of truth for the consolidated data-plane database name.
3
+ *
4
+ * All platform-owned stores (execution logs, checkpoints, memory, traces)
5
+ * live in one database. Override via the `MDB_AGENTIC_STORE_DB` environment
6
+ * variable; the default is `mdb_store`.
7
+ */
8
+ import type { MongoClient } from "mongodb";
9
+ /**
10
+ * Return the base (unscoped) consolidated data-plane database name.
11
+ *
12
+ * Reads `MDB_AGENTIC_STORE_DB` from the environment on every call so that
13
+ * late configuration (e.g. loading a .env file after import) is respected. For
14
+ * the per-project-scoped name use {@link resolveStoreDbName}.
15
+ */
16
+ export declare function getStoreDbName(): string;
17
+ /**
18
+ * Return the per-project-scoped store DB name, resolved once and cached.
19
+ *
20
+ * Applies the same resolution the OE uses ({@link resolveEffectiveDb}) against
21
+ * the live cluster, so the AER/SDK writers converge on the same database the OE
22
+ * reads. `base` defaults to {@link getStoreDbName}. Explicit values are
23
+ * returned exactly and skip discovery.
24
+ */
25
+ export declare function resolveStoreDbName(client: MongoClient, base?: string): Promise<string>;
26
+ /** Clear the memoized resolved store DB names (test seam). */
27
+ export declare function resetStoreDbCache(): void;
28
+ //# sourceMappingURL=db_config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"db_config.d.ts","sourceRoot":"","sources":["../src/db_config.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAKH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAM3C;;;;;;GAMG;AACH,wBAAgB,cAAc,IAAI,MAAM,CAGvC;AASD;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,WAAW,EACnB,IAAI,CAAC,EAAE,MAAM,GACZ,OAAO,CAAC,MAAM,CAAC,CA2BjB;AAED,8DAA8D;AAC9D,wBAAgB,iBAAiB,IAAI,IAAI,CAExC"}
@@ -0,0 +1,66 @@
1
+ /**
2
+ * Single source of truth for the consolidated data-plane database name.
3
+ *
4
+ * All platform-owned stores (execution logs, checkpoints, memory, traces)
5
+ * live in one database. Override via the `MDB_AGENTIC_STORE_DB` environment
6
+ * variable; the default is `mdb_store`.
7
+ */
8
+ import { resolveEffectiveDb } from "./db_naming.js";
9
+ const DEFAULT_DB_NAME = "mdb_store";
10
+ const LEGACY_DEFAULT_DB_NAMES = ["mdb_agentic_store"];
11
+ const ENV_VAR = "MDB_AGENTIC_STORE_DB";
12
+ /**
13
+ * Return the base (unscoped) consolidated data-plane database name.
14
+ *
15
+ * Reads `MDB_AGENTIC_STORE_DB` from the environment on every call so that
16
+ * late configuration (e.g. loading a .env file after import) is respected. For
17
+ * the per-project-scoped name use {@link resolveStoreDbName}.
18
+ */
19
+ export function getStoreDbName() {
20
+ const value = process.env[ENV_VAR]?.trim();
21
+ return value || DEFAULT_DB_NAME;
22
+ }
23
+ // Memoized per-project-resolved store DB names, keyed by base. Resolution needs
24
+ // a connected MongoClient (to list databases), which is not available when
25
+ // getStoreDbName runs during construction, so it is deferred to the first
26
+ // consumer that has a client and cached process-wide. The cached value is a
27
+ // Promise so concurrent callers share one listDatabases round trip per base.
28
+ const resolvedStoreDb = {};
29
+ /**
30
+ * Return the per-project-scoped store DB name, resolved once and cached.
31
+ *
32
+ * Applies the same resolution the OE uses ({@link resolveEffectiveDb}) against
33
+ * the live cluster, so the AER/SDK writers converge on the same database the OE
34
+ * reads. `base` defaults to {@link getStoreDbName}. Explicit values are
35
+ * returned exactly and skip discovery.
36
+ */
37
+ export function resolveStoreDbName(client, base) {
38
+ if (base !== undefined && base !== "")
39
+ return Promise.resolve(base);
40
+ const configured = (process.env[ENV_VAR] ?? "").trim();
41
+ if (configured)
42
+ return Promise.resolve(configured);
43
+ const b = DEFAULT_DB_NAME;
44
+ if (!(b in resolvedStoreDb)) {
45
+ const lister = {
46
+ listDatabaseNames: async () => {
47
+ const res = await client.db().admin().listDatabases({ nameOnly: true });
48
+ return res.databases.map((d) => d.name);
49
+ },
50
+ };
51
+ resolvedStoreDb[b] = resolveEffectiveDb(lister, b, (process.env["PROJECT_ID"] ?? "").trim(), {
52
+ label: "agent store database",
53
+ legacyBases: LEGACY_DEFAULT_DB_NAMES,
54
+ }).catch((err) => {
55
+ // Don't cache a rejection — allow a later retry.
56
+ delete resolvedStoreDb[b];
57
+ throw err;
58
+ });
59
+ }
60
+ return resolvedStoreDb[b];
61
+ }
62
+ /** Clear the memoized resolved store DB names (test seam). */
63
+ export function resetStoreDbCache() {
64
+ for (const key of Object.keys(resolvedStoreDb))
65
+ delete resolvedStoreDb[key];
66
+ }