@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.
- package/CHANGELOG.md +55 -0
- package/LICENSE.md +201 -0
- package/README.md +29 -0
- package/dist/agent_config.d.ts +167 -0
- package/dist/agent_config.d.ts.map +1 -0
- package/dist/agent_config.js +544 -0
- package/dist/call_interrupted.d.ts +12 -0
- package/dist/call_interrupted.d.ts.map +1 -0
- package/dist/call_interrupted.js +11 -0
- package/dist/checkpoint_workspace.d.ts +25 -0
- package/dist/checkpoint_workspace.d.ts.map +1 -0
- package/dist/checkpoint_workspace.js +44 -0
- package/dist/context.d.ts +235 -0
- package/dist/context.d.ts.map +1 -0
- package/dist/context.js +322 -0
- package/dist/db_config.d.ts +28 -0
- package/dist/db_config.d.ts.map +1 -0
- package/dist/db_config.js +66 -0
- package/dist/db_naming.d.ts +54 -0
- package/dist/db_naming.d.ts.map +1 -0
- package/dist/db_naming.js +94 -0
- package/dist/error_reporting.d.ts +67 -0
- package/dist/error_reporting.d.ts.map +1 -0
- package/dist/error_reporting.js +311 -0
- package/dist/generated/workflow/v1/activity_pb.d.ts +342 -0
- package/dist/generated/workflow/v1/activity_pb.d.ts.map +1 -0
- package/dist/generated/workflow/v1/activity_pb.js +115 -0
- package/dist/generated/workflow/v1/common_pb.d.ts +184 -0
- package/dist/generated/workflow/v1/common_pb.d.ts.map +1 -0
- package/dist/generated/workflow/v1/common_pb.js +86 -0
- package/dist/generated/workflow/v1/runtime_pb.d.ts +200 -0
- package/dist/generated/workflow/v1/runtime_pb.d.ts.map +1 -0
- package/dist/generated/workflow/v1/runtime_pb.js +40 -0
- package/dist/generated/workflow/v1/state_pb.d.ts +254 -0
- package/dist/generated/workflow/v1/state_pb.d.ts.map +1 -0
- package/dist/generated/workflow/v1/state_pb.js +68 -0
- package/dist/guardrails_evaluator/core.d.ts +23 -0
- package/dist/guardrails_evaluator/core.d.ts.map +1 -0
- package/dist/guardrails_evaluator/core.js +122 -0
- package/dist/guardrails_evaluator/index.d.ts +10 -0
- package/dist/guardrails_evaluator/index.d.ts.map +1 -0
- package/dist/guardrails_evaluator/index.js +11 -0
- package/dist/guardrails_evaluator/regex.d.ts +20 -0
- package/dist/guardrails_evaluator/regex.d.ts.map +1 -0
- package/dist/guardrails_evaluator/regex.js +233 -0
- package/dist/hooks.d.ts +109 -0
- package/dist/hooks.d.ts.map +1 -0
- package/dist/hooks.js +216 -0
- package/dist/http_path.d.ts +18 -0
- package/dist/http_path.d.ts.map +1 -0
- package/dist/http_path.js +53 -0
- package/dist/index.d.ts +35 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +41 -0
- package/dist/launcher.d.ts +130 -0
- package/dist/launcher.d.ts.map +1 -0
- package/dist/launcher.js +325 -0
- package/dist/logger.d.ts +96 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/logger.js +204 -0
- package/dist/mcp_oauth.d.ts +51 -0
- package/dist/mcp_oauth.d.ts.map +1 -0
- package/dist/mcp_oauth.js +389 -0
- package/dist/mcp_oauth_secret.d.ts +21 -0
- package/dist/mcp_oauth_secret.d.ts.map +1 -0
- package/dist/mcp_oauth_secret.js +122 -0
- package/dist/mcp_tools.d.ts +71 -0
- package/dist/mcp_tools.d.ts.map +1 -0
- package/dist/mcp_tools.js +301 -0
- package/dist/memory_appbound.d.ts +42 -0
- package/dist/memory_appbound.d.ts.map +1 -0
- package/dist/memory_appbound.js +159 -0
- package/dist/memory_writer.d.ts +49 -0
- package/dist/memory_writer.d.ts.map +1 -0
- package/dist/memory_writer.js +171 -0
- package/dist/metrics.d.ts +84 -0
- package/dist/metrics.d.ts.map +1 -0
- package/dist/metrics.js +205 -0
- package/dist/models.d.ts +1458 -0
- package/dist/models.d.ts.map +1 -0
- package/dist/models.js +1726 -0
- package/dist/node_logger.d.ts +43 -0
- package/dist/node_logger.d.ts.map +1 -0
- package/dist/node_logger.js +158 -0
- package/dist/owner_callback.d.ts +16 -0
- package/dist/owner_callback.d.ts.map +1 -0
- package/dist/owner_callback.js +40 -0
- package/dist/progress.d.ts +57 -0
- package/dist/progress.d.ts.map +1 -0
- package/dist/progress.js +140 -0
- package/dist/runtime.d.ts +131 -0
- package/dist/runtime.d.ts.map +1 -0
- package/dist/runtime.js +351 -0
- package/dist/secure_llm_proxy.d.ts +115 -0
- package/dist/secure_llm_proxy.d.ts.map +1 -0
- package/dist/secure_llm_proxy.js +922 -0
- package/dist/secure_wrapper.d.ts +332 -0
- package/dist/secure_wrapper.d.ts.map +1 -0
- package/dist/secure_wrapper.js +1249 -0
- package/dist/server/aer.d.ts +61 -0
- package/dist/server/aer.d.ts.map +1 -0
- package/dist/server/aer.js +1124 -0
- package/dist/server/auth.d.ts +56 -0
- package/dist/server/auth.d.ts.map +1 -0
- package/dist/server/auth.js +132 -0
- package/dist/server/base.d.ts +104 -0
- package/dist/server/base.d.ts.map +1 -0
- package/dist/server/base.js +150 -0
- package/dist/server/callInterrupt.d.ts +49 -0
- package/dist/server/callInterrupt.d.ts.map +1 -0
- package/dist/server/callInterrupt.js +68 -0
- package/dist/server/callback_delivery.d.ts +14 -0
- package/dist/server/callback_delivery.d.ts.map +1 -0
- package/dist/server/callback_delivery.js +141 -0
- package/dist/server/chunk_types.d.ts +50 -0
- package/dist/server/chunk_types.d.ts.map +1 -0
- package/dist/server/chunk_types.js +62 -0
- package/dist/server/cors.d.ts +52 -0
- package/dist/server/cors.d.ts.map +1 -0
- package/dist/server/cors.js +107 -0
- package/dist/server/drain.d.ts +169 -0
- package/dist/server/drain.d.ts.map +1 -0
- package/dist/server/drain.js +455 -0
- package/dist/server/function.d.ts +77 -0
- package/dist/server/function.d.ts.map +1 -0
- package/dist/server/function.js +337 -0
- package/dist/server/http_retry.d.ts +37 -0
- package/dist/server/http_retry.d.ts.map +1 -0
- package/dist/server/http_retry.js +157 -0
- package/dist/server/index.d.ts +7 -0
- package/dist/server/index.d.ts.map +1 -0
- package/dist/server/index.js +5 -0
- package/dist/server/metadata.d.ts +50 -0
- package/dist/server/metadata.d.ts.map +1 -0
- package/dist/server/metadata.js +193 -0
- package/dist/server/oe_url.d.ts +36 -0
- package/dist/server/oe_url.d.ts.map +1 -0
- package/dist/server/oe_url.js +50 -0
- package/dist/server/owner_url.d.ts +35 -0
- package/dist/server/owner_url.d.ts.map +1 -0
- package/dist/server/owner_url.js +146 -0
- package/dist/server/query.d.ts +42 -0
- package/dist/server/query.d.ts.map +1 -0
- package/dist/server/query.js +28 -0
- package/dist/server/tool.d.ts +138 -0
- package/dist/server/tool.d.ts.map +1 -0
- package/dist/server/tool.js +1017 -0
- package/dist/span_names.d.ts +21 -0
- package/dist/span_names.d.ts.map +1 -0
- package/dist/span_names.js +31 -0
- package/dist/structured_logging/constants.d.ts +17 -0
- package/dist/structured_logging/constants.d.ts.map +1 -0
- package/dist/structured_logging/constants.js +71 -0
- package/dist/structured_logging/env.d.ts +18 -0
- package/dist/structured_logging/env.d.ts.map +1 -0
- package/dist/structured_logging/env.js +39 -0
- package/dist/structured_logging/install.d.ts +56 -0
- package/dist/structured_logging/install.d.ts.map +1 -0
- package/dist/structured_logging/install.js +107 -0
- package/dist/structured_logging/layout.d.ts +9 -0
- package/dist/structured_logging/layout.d.ts.map +1 -0
- package/dist/structured_logging/layout.js +144 -0
- package/dist/structured_logging/serialize.d.ts +27 -0
- package/dist/structured_logging/serialize.d.ts.map +1 -0
- package/dist/structured_logging/serialize.js +61 -0
- package/dist/structured_logging/stdio_capture.d.ts +59 -0
- package/dist/structured_logging/stdio_capture.d.ts.map +1 -0
- package/dist/structured_logging/stdio_capture.js +164 -0
- package/dist/structured_logging/uncaught.d.ts +14 -0
- package/dist/structured_logging/uncaught.d.ts.map +1 -0
- package/dist/structured_logging/uncaught.js +58 -0
- package/dist/structured_logging.d.ts +48 -0
- package/dist/structured_logging.d.ts.map +1 -0
- package/dist/structured_logging.js +47 -0
- package/dist/tls_client.d.ts +61 -0
- package/dist/tls_client.d.ts.map +1 -0
- package/dist/tls_client.js +298 -0
- package/dist/tool_api_error.d.ts +62 -0
- package/dist/tool_api_error.d.ts.map +1 -0
- package/dist/tool_api_error.js +399 -0
- package/dist/tool_memory_ownership.d.ts +10 -0
- package/dist/tool_memory_ownership.d.ts.map +1 -0
- package/dist/tool_memory_ownership.js +36 -0
- package/dist/toolpod_handlers.d.ts +126 -0
- package/dist/toolpod_handlers.d.ts.map +1 -0
- package/dist/toolpod_handlers.js +1016 -0
- package/dist/tracing/exporters.d.ts +51 -0
- package/dist/tracing/exporters.d.ts.map +1 -0
- package/dist/tracing/exporters.js +327 -0
- package/dist/tracing/index.d.ts +3 -0
- package/dist/tracing/index.d.ts.map +1 -0
- package/dist/tracing/index.js +2 -0
- package/dist/tracing/setup.d.ts +76 -0
- package/dist/tracing/setup.d.ts.map +1 -0
- package/dist/tracing/setup.js +436 -0
- package/dist/utils.d.ts +204 -0
- package/dist/utils.d.ts.map +1 -0
- package/dist/utils.js +867 -0
- package/dist/workflow/activity.d.ts +71 -0
- package/dist/workflow/activity.d.ts.map +1 -0
- package/dist/workflow/activity.js +357 -0
- package/dist/workflow/attempt.d.ts +12 -0
- package/dist/workflow/attempt.d.ts.map +1 -0
- package/dist/workflow/attempt.js +96 -0
- package/dist/workflow/client.d.ts +46 -0
- package/dist/workflow/client.d.ts.map +1 -0
- package/dist/workflow/client.js +299 -0
- package/dist/workflow/context.d.ts +37 -0
- package/dist/workflow/context.d.ts.map +1 -0
- package/dist/workflow/context.js +350 -0
- package/dist/workflow/heartbeat.d.ts +15 -0
- package/dist/workflow/heartbeat.d.ts.map +1 -0
- package/dist/workflow/heartbeat.js +78 -0
- package/dist/workflow/index.d.ts +14 -0
- package/dist/workflow/index.d.ts.map +1 -0
- package/dist/workflow/index.js +10 -0
- package/dist/workflow/memory.d.ts +17 -0
- package/dist/workflow/memory.d.ts.map +1 -0
- package/dist/workflow/memory.js +184 -0
- 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":"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"}
|
package/dist/context.js
ADDED
|
@@ -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
|
+
}
|