@mongodb-js/agent-engine-sdk 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/LICENSE.md +201 -0
- package/README.md +20 -0
- package/dist/api/events.d.ts +39 -0
- package/dist/api/events.d.ts.map +1 -0
- package/dist/api/events.js +9 -0
- package/dist/api/v1/memory.d.ts +257 -0
- package/dist/api/v1/memory.d.ts.map +1 -0
- package/dist/api/v1/memory.js +219 -0
- package/dist/app.d.ts +27 -0
- package/dist/app.d.ts.map +1 -0
- package/dist/app.js +19 -0
- package/dist/clients/events.d.ts +11 -0
- package/dist/clients/events.d.ts.map +1 -0
- package/dist/clients/events.js +67 -0
- package/dist/clients/memory.d.ts +358 -0
- package/dist/clients/memory.d.ts.map +1 -0
- package/dist/clients/memory.js +658 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +8 -0
- package/dist/interfaces.d.ts +111 -0
- package/dist/interfaces.d.ts.map +1 -0
- package/dist/interfaces.js +22 -0
- package/dist/models.d.ts +593 -0
- package/dist/models.d.ts.map +1 -0
- package/dist/models.js +588 -0
- package/package.json +50 -0
|
@@ -0,0 +1,658 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HTTP client for the Memory Server API.
|
|
3
|
+
*
|
|
4
|
+
* Makes HTTP calls to the memory server, allowing transparent replacement
|
|
5
|
+
* of direct mongomem_core usage.
|
|
6
|
+
*/
|
|
7
|
+
import { z } from "zod";
|
|
8
|
+
import { ContextResponseSchema, CreateEpisodicResultSchema, CreateProceduralResultSchema, CreateSemanticResultSchema, CreateTaxonomicResultSchema, CustomMemoryRetrieveResultSchema, CustomMemorySaveResultSchema, DeleteResultSchema, MemoryChunkSchema, WriteTurnResultSchema, } from "../api/v1/memory.js";
|
|
9
|
+
/**
|
|
10
|
+
* Trim a session id, returning `null` when it is absent or blank. The memory
|
|
11
|
+
* server accepts a null `session_id` (sessionless context/turns); callers that
|
|
12
|
+
* require one enforce it above this layer.
|
|
13
|
+
*/
|
|
14
|
+
function normalizeSessionId(sessionId) {
|
|
15
|
+
if (!sessionId || !sessionId.trim())
|
|
16
|
+
return null;
|
|
17
|
+
return sessionId.trim();
|
|
18
|
+
}
|
|
19
|
+
/** Reject non-finite / non-integer / non-positive maxTokens before serialization. */
|
|
20
|
+
function requirePositiveMaxTokens(maxTokens) {
|
|
21
|
+
if (maxTokens === undefined) {
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
if (!Number.isInteger(maxTokens) || maxTokens <= 0) {
|
|
25
|
+
throw new RangeError("maxTokens must be a positive integer");
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Percent-encode an id for use as a single URL path segment, refusing bare
|
|
30
|
+
* dot segments: encodeURIComponent leaves '.'/'..' untouched, and the URL
|
|
31
|
+
* parser would collapse them into a parent-path rewrite of this authenticated
|
|
32
|
+
* request.
|
|
33
|
+
*/
|
|
34
|
+
function encodeIdSegment(id) {
|
|
35
|
+
if (id === "." || id === "..") {
|
|
36
|
+
throw new Error(`Invalid memory id: bare dot segment ${JSON.stringify(id)}`);
|
|
37
|
+
}
|
|
38
|
+
return encodeURIComponent(id);
|
|
39
|
+
}
|
|
40
|
+
function requireSessionId(sessionId) {
|
|
41
|
+
if (!sessionId || !sessionId.trim()) {
|
|
42
|
+
throw new Error("session_id is required for memory server requests");
|
|
43
|
+
}
|
|
44
|
+
return sessionId.trim();
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Thrown for non-OK memory-server responses. Carries the HTTP status and body
|
|
48
|
+
* so callers can branch on failure mode (e.g. map 401/403/404/5xx to typed
|
|
49
|
+
* errors) instead of parsing a message string. Extends `Error`, so existing
|
|
50
|
+
* `catch (e) { ... }` consumers are unaffected.
|
|
51
|
+
*/
|
|
52
|
+
export class MemoryHttpError extends Error {
|
|
53
|
+
status;
|
|
54
|
+
responseText;
|
|
55
|
+
constructor(status, responseText) {
|
|
56
|
+
super(`HTTP ${status}: ${responseText}`);
|
|
57
|
+
this.status = status;
|
|
58
|
+
this.responseText = responseText;
|
|
59
|
+
this.name = "MemoryHttpError";
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
/** 5xx statuses worth retrying — transient gateway/proxy failures. */
|
|
63
|
+
const RETRYABLE_STATUS = new Set([502, 503, 504]);
|
|
64
|
+
const RETRY_BASE_DELAY_MS = 200;
|
|
65
|
+
function sleep(ms) {
|
|
66
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* HTTP client for the Memory Server.
|
|
70
|
+
*
|
|
71
|
+
* ```ts
|
|
72
|
+
* const client = new MemoryClient('http://127.0.0.1:8081')
|
|
73
|
+
*
|
|
74
|
+
* // Write conversation turn
|
|
75
|
+
* await client.writeTurn({ sessionId: 'thread_123', role: 'user', content: 'Hello', orgId: 'org_1', userId: 'user_1', projectId: 'proj_1' })
|
|
76
|
+
*
|
|
77
|
+
* // Build context
|
|
78
|
+
* const context = await client.buildContext({ query: 'What did we discuss?', sessionId: 'thread_123', orgId: 'org_1', userId: 'user_1', projectId: 'proj_1' })
|
|
79
|
+
* ```
|
|
80
|
+
*/
|
|
81
|
+
export class MemoryClient {
|
|
82
|
+
baseUrl;
|
|
83
|
+
timeout;
|
|
84
|
+
staticHeaders;
|
|
85
|
+
dynamicHeaders;
|
|
86
|
+
apiPrefix;
|
|
87
|
+
requestExtras;
|
|
88
|
+
maxRetries;
|
|
89
|
+
routeStyle;
|
|
90
|
+
fetchImpl;
|
|
91
|
+
/**
|
|
92
|
+
* @param baseUrl Memory server base URL (e.g. "http://127.0.0.1:8081")
|
|
93
|
+
* @param timeout Request timeout in seconds (default: 30)
|
|
94
|
+
* @param staticHeaders Pod-level identity headers set at construction time
|
|
95
|
+
* (e.g. `X-Agent-Engine-Agent-Id` from APP_ID). Defensively copied so caller
|
|
96
|
+
* mutations after construction have no effect.
|
|
97
|
+
* @param apiPrefix URL path prefix for memory endpoints. Defaults to
|
|
98
|
+
* "/api/v1/memory" (the OE proxy route, which strips `/memory/` before
|
|
99
|
+
* forwarding to the memory server). Use "/api/v1" when connecting
|
|
100
|
+
* directly to the memory server.
|
|
101
|
+
* @param dynamicHeaders Called on every request; result is merged over
|
|
102
|
+
* `staticHeaders`. Used by agent-engine-runner-shared to inject execution-scoped
|
|
103
|
+
* `X-Agent-Engine-Execution-Id` from AsyncLocalStorage.
|
|
104
|
+
* @param requestExtras Called on every request; the returned `RequestInit` is
|
|
105
|
+
* spread into `fetch` init before method/headers/signal. Used to inject a
|
|
106
|
+
* custom transport (e.g. an undici mTLS `dispatcher`) for app-bound calls.
|
|
107
|
+
* @param maxRetries Number of retries on transient 5xx (502/503/504) and
|
|
108
|
+
* network errors, with exponential backoff. Default 0 (no retry).
|
|
109
|
+
* @param routeStyle Memory route convention (see {@link MemoryRouteStyle}).
|
|
110
|
+
* Defaults to "native" — the memory server / OE proxy routes. Use "aliased"
|
|
111
|
+
* for the API Gateway's project-scoped routes (`/turns`, `/context`,
|
|
112
|
+
* single `/search` with a `type` body field).
|
|
113
|
+
*/
|
|
114
|
+
constructor(baseUrl, timeout = 30, staticHeaders = {}, apiPrefix = "/api/v1/memory", dynamicHeaders, requestExtras, maxRetries = 0, routeStyle = "native", fetchImpl) {
|
|
115
|
+
this.baseUrl = baseUrl.replace(/\/$/, "");
|
|
116
|
+
this.timeout = timeout;
|
|
117
|
+
this.staticHeaders = { ...staticHeaders };
|
|
118
|
+
this.apiPrefix = "/" + apiPrefix.replace(/^\/+|\/+$/g, "");
|
|
119
|
+
this.dynamicHeaders = dynamicHeaders;
|
|
120
|
+
this.requestExtras = requestExtras;
|
|
121
|
+
this.maxRetries = Math.max(0, maxRetries);
|
|
122
|
+
this.routeStyle = routeStyle;
|
|
123
|
+
// Bind so a passed method keeps its receiver; default to the global fetch.
|
|
124
|
+
this.fetchImpl = fetchImpl ?? fetch;
|
|
125
|
+
}
|
|
126
|
+
/** Route + body for a ranked-search request, per the active route style. */
|
|
127
|
+
searchRoute(type, body) {
|
|
128
|
+
return this.routeStyle === "aliased"
|
|
129
|
+
? { path: "/search", body: { type, ...body } }
|
|
130
|
+
: { path: `/retrieval/${type}`, body };
|
|
131
|
+
}
|
|
132
|
+
/** Path for the write-turn route, per the active route style. */
|
|
133
|
+
get turnsPath() {
|
|
134
|
+
return this.routeStyle === "aliased" ? "/turns" : "/stm/turns";
|
|
135
|
+
}
|
|
136
|
+
/** Path for the build-context route, per the active route style. */
|
|
137
|
+
get contextPath() {
|
|
138
|
+
return this.routeStyle === "aliased" ? "/context" : "/retrieval/context";
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* `fetch` with the configured transport extras and retry on transient 5xx /
|
|
142
|
+
* network errors. All memory-server routes are safe to retry: writes are
|
|
143
|
+
* idempotent (server upserts by label/session) and reads are pure.
|
|
144
|
+
*/
|
|
145
|
+
async fetchWithRetry(url, init) {
|
|
146
|
+
for (let attempt = 0;; attempt++) {
|
|
147
|
+
try {
|
|
148
|
+
const resp = await this.fetchImpl(url, init);
|
|
149
|
+
if (RETRYABLE_STATUS.has(resp.status) && attempt < this.maxRetries) {
|
|
150
|
+
// Drain the discarded body so the connection can be reused.
|
|
151
|
+
await resp.body?.cancel().catch(() => { });
|
|
152
|
+
await sleep(RETRY_BASE_DELAY_MS * 2 ** attempt);
|
|
153
|
+
continue;
|
|
154
|
+
}
|
|
155
|
+
return resp;
|
|
156
|
+
}
|
|
157
|
+
catch (err) {
|
|
158
|
+
if (attempt >= this.maxRetries)
|
|
159
|
+
throw err;
|
|
160
|
+
await sleep(RETRY_BASE_DELAY_MS * 2 ** attempt);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
composeSignal(caller) {
|
|
165
|
+
const timeout = AbortSignal.timeout(this.timeout * 1000);
|
|
166
|
+
return caller ? AbortSignal.any([caller, timeout]) : timeout;
|
|
167
|
+
}
|
|
168
|
+
requestHeaders() {
|
|
169
|
+
return this.dynamicHeaders
|
|
170
|
+
? { ...this.staticHeaders, ...this.dynamicHeaders() }
|
|
171
|
+
: { ...this.staticHeaders };
|
|
172
|
+
}
|
|
173
|
+
buildUrl(path, params) {
|
|
174
|
+
const url = new URL(`${this.baseUrl}${this.apiPrefix}${path}`);
|
|
175
|
+
if (params !== undefined) {
|
|
176
|
+
for (const [k, v] of Object.entries(params)) {
|
|
177
|
+
if (v !== undefined && v !== null)
|
|
178
|
+
url.searchParams.set(k, String(v));
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
return url.toString();
|
|
182
|
+
}
|
|
183
|
+
buildInit(method, body, signal) {
|
|
184
|
+
const extras = this.requestExtras?.() ?? {};
|
|
185
|
+
const init = {
|
|
186
|
+
...extras,
|
|
187
|
+
method,
|
|
188
|
+
headers: {
|
|
189
|
+
...(extras.headers ?? {}),
|
|
190
|
+
...this.requestHeaders(),
|
|
191
|
+
},
|
|
192
|
+
signal: this.composeSignal(signal),
|
|
193
|
+
};
|
|
194
|
+
if (body !== undefined) {
|
|
195
|
+
init.headers["Content-Type"] =
|
|
196
|
+
"application/json";
|
|
197
|
+
init.body = JSON.stringify(body);
|
|
198
|
+
}
|
|
199
|
+
return init;
|
|
200
|
+
}
|
|
201
|
+
async request(method, path, schema, body, params, signal) {
|
|
202
|
+
const resp = await this.fetchWithRetry(this.buildUrl(path, params), this.buildInit(method, body, signal));
|
|
203
|
+
if (!resp.ok)
|
|
204
|
+
throw new MemoryHttpError(resp.status, await resp.text());
|
|
205
|
+
return schema.parse(await resp.json());
|
|
206
|
+
}
|
|
207
|
+
/**
|
|
208
|
+
* Like `request`, but returns `null` on a 404 instead of throwing. Mirrors
|
|
209
|
+
* Python's `if resp.status_code == 404: return None` on the list/lookup GETs
|
|
210
|
+
* (`get_semantic`, `get_taxonomic`, `get_procedural`), so a not-found lookup
|
|
211
|
+
* resolves to `null` rather than surfacing as an HTTP error.
|
|
212
|
+
*/
|
|
213
|
+
async requestOrNull(method, path, schema, body, params, signal) {
|
|
214
|
+
const resp = await this.fetchWithRetry(this.buildUrl(path, params), this.buildInit(method, body, signal));
|
|
215
|
+
if (resp.status === 404)
|
|
216
|
+
return null;
|
|
217
|
+
if (!resp.ok)
|
|
218
|
+
throw new MemoryHttpError(resp.status, await resp.text());
|
|
219
|
+
return schema.parse(await resp.json());
|
|
220
|
+
}
|
|
221
|
+
// ===========================================================================
|
|
222
|
+
// Short-Term Memory (STM)
|
|
223
|
+
// ===========================================================================
|
|
224
|
+
async writeTurn(params) {
|
|
225
|
+
const body = {
|
|
226
|
+
session_id: normalizeSessionId(params.sessionId),
|
|
227
|
+
role: params.role,
|
|
228
|
+
org_id: params.orgId,
|
|
229
|
+
user_id: params.userId ?? null,
|
|
230
|
+
project_id: params.projectId,
|
|
231
|
+
content: params.content,
|
|
232
|
+
tokens: params.tokens,
|
|
233
|
+
stop_reason: params.stopReason,
|
|
234
|
+
model_name: params.modelName,
|
|
235
|
+
tool_calls: params.toolCalls,
|
|
236
|
+
tool_call_id: params.toolCallId,
|
|
237
|
+
tool_name: params.toolName,
|
|
238
|
+
// Default to false so the field is always present on the wire, matching
|
|
239
|
+
// Python's `is_error: bool = False` (TS would otherwise drop an
|
|
240
|
+
// `undefined` key via JSON.stringify).
|
|
241
|
+
is_error: params.isError ?? false,
|
|
242
|
+
};
|
|
243
|
+
if (params.idempotencyKey != null)
|
|
244
|
+
body.idempotency_key = params.idempotencyKey;
|
|
245
|
+
return this.request("POST", this.turnsPath, WriteTurnResultSchema, body, undefined, params.signal);
|
|
246
|
+
}
|
|
247
|
+
// ===========================================================================
|
|
248
|
+
// Context Building
|
|
249
|
+
// ===========================================================================
|
|
250
|
+
/**
|
|
251
|
+
* Build unified memory context.
|
|
252
|
+
* Omitted `enabledSources` defaults to episodic and semantic; include
|
|
253
|
+
* "stm" for recent turns.
|
|
254
|
+
*/
|
|
255
|
+
async buildContext(params) {
|
|
256
|
+
requirePositiveMaxTokens(params.maxTokens);
|
|
257
|
+
const body = {
|
|
258
|
+
query: params.query,
|
|
259
|
+
session_id: normalizeSessionId(params.sessionId),
|
|
260
|
+
org_id: params.orgId,
|
|
261
|
+
user_id: params.userId ?? null,
|
|
262
|
+
visibility: params.visibility,
|
|
263
|
+
project_id: params.projectId,
|
|
264
|
+
enabled_sources: params.enabledSources,
|
|
265
|
+
format_style: params.formatStyle,
|
|
266
|
+
top_k: params.topK ?? 50,
|
|
267
|
+
};
|
|
268
|
+
// Match Python's `if metadata_filter:` (truthy) — an empty object is not
|
|
269
|
+
// sent, so the server applies its default unfiltered behaviour.
|
|
270
|
+
if (params.metadataFilter != null &&
|
|
271
|
+
Object.keys(params.metadataFilter).length > 0)
|
|
272
|
+
body["metadata_filter"] = params.metadataFilter;
|
|
273
|
+
if (params.maxTokens !== undefined)
|
|
274
|
+
body["max_tokens"] = params.maxTokens;
|
|
275
|
+
return this.request("POST", this.contextPath, ContextResponseSchema, body, undefined, params.signal);
|
|
276
|
+
}
|
|
277
|
+
// ===========================================================================
|
|
278
|
+
// Semantic Memory
|
|
279
|
+
// ===========================================================================
|
|
280
|
+
async createSemantic(params) {
|
|
281
|
+
const body = {
|
|
282
|
+
label: params.label,
|
|
283
|
+
text: params.text,
|
|
284
|
+
org_id: params.orgId,
|
|
285
|
+
user_id: params.userId,
|
|
286
|
+
source: params.source ?? "agent",
|
|
287
|
+
visibility: params.visibility ?? "private",
|
|
288
|
+
project_id: params.projectId,
|
|
289
|
+
agent_id: params.agentId,
|
|
290
|
+
embedding: params.embedding,
|
|
291
|
+
metadata: params.metadata,
|
|
292
|
+
// Server-side upsert flag (Python `create_semantic(..., upsert=...)`,
|
|
293
|
+
// default False at the client layer). When true, the server updates an
|
|
294
|
+
// existing memory with the same label instead of erroring on duplicate.
|
|
295
|
+
upsert: params.upsert ?? false,
|
|
296
|
+
};
|
|
297
|
+
return this.request("POST", "/semantic", CreateSemanticResultSchema, body, undefined, params.signal);
|
|
298
|
+
}
|
|
299
|
+
async fetchSemanticMemories(params) {
|
|
300
|
+
const route = this.searchRoute("semantic", {
|
|
301
|
+
query: params.query,
|
|
302
|
+
org_id: params.orgId,
|
|
303
|
+
project_id: params.projectId,
|
|
304
|
+
user_id: params.userId,
|
|
305
|
+
visibility: params.visibility,
|
|
306
|
+
top_k: params.topK ?? 50,
|
|
307
|
+
});
|
|
308
|
+
const data = await this.request("POST", route.path, z.object({ memories: z.array(MemoryChunkSchema) }), route.body, undefined, params.signal);
|
|
309
|
+
return data.memories;
|
|
310
|
+
}
|
|
311
|
+
async getSemantic(params) {
|
|
312
|
+
if (params.id != null) {
|
|
313
|
+
let idUrl = `${this.baseUrl}${this.apiPrefix}/semantic/${encodeIdSegment(String(params.id))}` +
|
|
314
|
+
`?org_id=${encodeURIComponent(params.orgId)}&project_id=${encodeURIComponent(params.projectId)}`;
|
|
315
|
+
if (params.userId != null)
|
|
316
|
+
idUrl += `&user_id=${encodeURIComponent(params.userId)}`;
|
|
317
|
+
if (params.visibility != null)
|
|
318
|
+
idUrl += `&visibility=${encodeURIComponent(params.visibility)}`;
|
|
319
|
+
const resp = await this.fetchWithRetry(idUrl, this.buildInit("GET", undefined, params.signal));
|
|
320
|
+
if (resp.status === 404)
|
|
321
|
+
return null;
|
|
322
|
+
if (!resp.ok)
|
|
323
|
+
throw new MemoryHttpError(resp.status, await resp.text());
|
|
324
|
+
return (await resp.json());
|
|
325
|
+
}
|
|
326
|
+
const urlParams = {
|
|
327
|
+
org_id: params.orgId,
|
|
328
|
+
project_id: params.projectId,
|
|
329
|
+
};
|
|
330
|
+
if (params.userId != null)
|
|
331
|
+
urlParams["user_id"] = params.userId;
|
|
332
|
+
if (params.visibility != null)
|
|
333
|
+
urlParams["visibility"] = params.visibility;
|
|
334
|
+
if (params.label != null)
|
|
335
|
+
urlParams["label"] = params.label;
|
|
336
|
+
const data = await this.requestOrNull("GET", "/semantic", z.object({ entries: z.array(z.unknown()) }), undefined, urlParams, params.signal);
|
|
337
|
+
if (data == null)
|
|
338
|
+
return null;
|
|
339
|
+
return data.entries.length > 0 ? data.entries[0] : null;
|
|
340
|
+
}
|
|
341
|
+
async updateSemantic(params) {
|
|
342
|
+
const existing = await this.getSemantic({
|
|
343
|
+
orgId: params.orgId,
|
|
344
|
+
projectId: params.projectId,
|
|
345
|
+
label: params.label,
|
|
346
|
+
signal: params.signal,
|
|
347
|
+
});
|
|
348
|
+
if (existing == null)
|
|
349
|
+
throw new Error(`Semantic memory not found: ${params.label}`);
|
|
350
|
+
const memoryId = existing["id"] ??
|
|
351
|
+
existing["_id"];
|
|
352
|
+
if (memoryId == null)
|
|
353
|
+
throw new Error(`Semantic memory has no id field: ${params.label}`);
|
|
354
|
+
const body = {
|
|
355
|
+
org_id: params.orgId,
|
|
356
|
+
project_id: params.projectId,
|
|
357
|
+
text: params.text,
|
|
358
|
+
source: params.source,
|
|
359
|
+
visibility: params.visibility,
|
|
360
|
+
};
|
|
361
|
+
return this.request("PATCH", `/semantic/${encodeIdSegment(String(memoryId))}`, z.unknown(), body, undefined, params.signal);
|
|
362
|
+
}
|
|
363
|
+
// ===========================================================================
|
|
364
|
+
// Episodic Memory
|
|
365
|
+
// ===========================================================================
|
|
366
|
+
async createEpisodic(params) {
|
|
367
|
+
const body = {
|
|
368
|
+
title: params.title,
|
|
369
|
+
content: params.content,
|
|
370
|
+
summary_text: params.summaryText,
|
|
371
|
+
org_id: params.orgId,
|
|
372
|
+
user_id: params.userId,
|
|
373
|
+
session_id: requireSessionId(params.sessionId),
|
|
374
|
+
visibility: params.visibility ?? "private",
|
|
375
|
+
project_id: params.projectId,
|
|
376
|
+
agent_id: params.agentId,
|
|
377
|
+
};
|
|
378
|
+
if (params.metadata != null)
|
|
379
|
+
body["metadata"] = params.metadata;
|
|
380
|
+
if (params.snapshotRefId != null)
|
|
381
|
+
body["snapshot_ref_id"] = params.snapshotRefId;
|
|
382
|
+
if (params.summaryType != null)
|
|
383
|
+
body["summary_type"] = params.summaryType;
|
|
384
|
+
if (params.sourceAgent != null)
|
|
385
|
+
body["source_agent"] = params.sourceAgent;
|
|
386
|
+
if (params.participants != null)
|
|
387
|
+
body["participants"] = params.participants;
|
|
388
|
+
if (params.tags != null)
|
|
389
|
+
body["tags"] = params.tags;
|
|
390
|
+
if (params.extractionSource != null)
|
|
391
|
+
body["extraction_source"] = params.extractionSource;
|
|
392
|
+
if (params.embedding != null)
|
|
393
|
+
body["embedding"] = params.embedding;
|
|
394
|
+
if (params.skipEmbedding != null)
|
|
395
|
+
body["skip_embedding"] = params.skipEmbedding;
|
|
396
|
+
return this.request("POST", "/episodic", CreateEpisodicResultSchema, body, undefined, params.signal);
|
|
397
|
+
}
|
|
398
|
+
async fetchEpisodicMemories(params) {
|
|
399
|
+
const route = this.searchRoute("episodic", {
|
|
400
|
+
query: params.query,
|
|
401
|
+
org_id: params.orgId,
|
|
402
|
+
project_id: params.projectId,
|
|
403
|
+
user_id: params.userId,
|
|
404
|
+
visibility: params.visibility,
|
|
405
|
+
session_id: params.sessionId,
|
|
406
|
+
top_k: params.topK ?? 50,
|
|
407
|
+
});
|
|
408
|
+
const data = await this.request("POST", route.path, z.object({ memories: z.array(MemoryChunkSchema) }), route.body, undefined, params.signal);
|
|
409
|
+
return data.memories;
|
|
410
|
+
}
|
|
411
|
+
async listEpisodic(params) {
|
|
412
|
+
const data = await this.request("GET", "/episodic", z.object({ entries: z.array(z.unknown()) }), undefined, {
|
|
413
|
+
org_id: params.orgId,
|
|
414
|
+
project_id: params.projectId,
|
|
415
|
+
user_id: params.userId ?? undefined,
|
|
416
|
+
session_id: params.sessionId ?? undefined,
|
|
417
|
+
visibility: params.visibility ?? undefined,
|
|
418
|
+
limit: params.limit ?? 20,
|
|
419
|
+
}, params.signal);
|
|
420
|
+
return data.entries;
|
|
421
|
+
}
|
|
422
|
+
// ===========================================================================
|
|
423
|
+
// Taxonomic Memory
|
|
424
|
+
// ===========================================================================
|
|
425
|
+
async createTaxonomic(params) {
|
|
426
|
+
const body = {
|
|
427
|
+
domain: params.domain,
|
|
428
|
+
term: params.term,
|
|
429
|
+
definition: params.definition,
|
|
430
|
+
org_id: params.orgId,
|
|
431
|
+
user_id: params.userId,
|
|
432
|
+
project_id: params.projectId,
|
|
433
|
+
related_terms: params.relatedTerms,
|
|
434
|
+
query_expansion: params.queryExpansion ?? true,
|
|
435
|
+
visibility: params.visibility ?? "org",
|
|
436
|
+
};
|
|
437
|
+
return this.request("POST", "/taxonomic", CreateTaxonomicResultSchema, body, undefined, params.signal);
|
|
438
|
+
}
|
|
439
|
+
async fetchTaxonomicMemories(params) {
|
|
440
|
+
// user_id is deliberately omitted from the body (see param doc above).
|
|
441
|
+
const route = this.searchRoute("taxonomic", {
|
|
442
|
+
query: params.query,
|
|
443
|
+
org_id: params.orgId,
|
|
444
|
+
project_id: params.projectId,
|
|
445
|
+
domain: params.domain,
|
|
446
|
+
visibility: params.visibility,
|
|
447
|
+
top_k: params.topK ?? 50,
|
|
448
|
+
});
|
|
449
|
+
const data = await this.request("POST", route.path, z.object({ memories: z.array(MemoryChunkSchema) }), route.body, undefined, params.signal);
|
|
450
|
+
return data.memories;
|
|
451
|
+
}
|
|
452
|
+
async getTaxonomic(params) {
|
|
453
|
+
const data = await this.requestOrNull("GET", "/taxonomic", z.object({ entries: z.array(z.unknown()) }), undefined, {
|
|
454
|
+
org_id: params.orgId,
|
|
455
|
+
project_id: params.projectId,
|
|
456
|
+
domain: params.domain ?? undefined,
|
|
457
|
+
user_id: params.userId ?? undefined,
|
|
458
|
+
visibility: params.visibility ?? undefined,
|
|
459
|
+
}, params.signal);
|
|
460
|
+
if (data == null)
|
|
461
|
+
return null;
|
|
462
|
+
if (params.term != null) {
|
|
463
|
+
return (data.entries.find((e) => e["term"] === params.term) ?? null);
|
|
464
|
+
}
|
|
465
|
+
return data.entries.length > 0 ? data.entries[0] : null;
|
|
466
|
+
}
|
|
467
|
+
async getDistinctDomains(params) {
|
|
468
|
+
const data = await this.request("GET", "/taxonomic/domains", z.object({ domains: z.array(z.string()) }), undefined, {
|
|
469
|
+
org_id: params.orgId,
|
|
470
|
+
project_id: params.projectId,
|
|
471
|
+
visibility: params.visibility ?? undefined,
|
|
472
|
+
}, params.signal);
|
|
473
|
+
return data.domains;
|
|
474
|
+
}
|
|
475
|
+
// ===========================================================================
|
|
476
|
+
// Procedural Memory
|
|
477
|
+
// ===========================================================================
|
|
478
|
+
async createProcedural(params) {
|
|
479
|
+
const body = {
|
|
480
|
+
procedure: params.procedure,
|
|
481
|
+
description: params.description,
|
|
482
|
+
content: params.content,
|
|
483
|
+
org_id: params.orgId,
|
|
484
|
+
user_id: params.userId,
|
|
485
|
+
steps: params.steps,
|
|
486
|
+
resources: params.resources,
|
|
487
|
+
allowed_tools: params.allowedTools,
|
|
488
|
+
compatibility: params.compatibility,
|
|
489
|
+
license: params.license,
|
|
490
|
+
trigger_conditions: params.triggerConditions,
|
|
491
|
+
tags: params.tags,
|
|
492
|
+
visibility: params.visibility ?? "private",
|
|
493
|
+
project_id: params.projectId,
|
|
494
|
+
agent_id: params.agentId,
|
|
495
|
+
extraction_source: params.extractionSource,
|
|
496
|
+
source_format: params.sourceFormat,
|
|
497
|
+
source_path: params.sourcePath,
|
|
498
|
+
};
|
|
499
|
+
return this.request("POST", "/procedural", CreateProceduralResultSchema, body, undefined, params.signal);
|
|
500
|
+
}
|
|
501
|
+
async getProcedural(params) {
|
|
502
|
+
if (params.id != null) {
|
|
503
|
+
let idUrl = `${this.baseUrl}${this.apiPrefix}/procedural/${encodeIdSegment(String(params.id))}` +
|
|
504
|
+
`?org_id=${encodeURIComponent(params.orgId)}&project_id=${encodeURIComponent(params.projectId)}` +
|
|
505
|
+
`&include_deleted=${params.includeDeleted ?? false}`;
|
|
506
|
+
if (params.userId != null)
|
|
507
|
+
idUrl += `&user_id=${encodeURIComponent(params.userId)}`;
|
|
508
|
+
if (params.visibility != null)
|
|
509
|
+
idUrl += `&visibility=${encodeURIComponent(params.visibility)}`;
|
|
510
|
+
const resp = await this.fetchWithRetry(idUrl, this.buildInit("GET", undefined, params.signal));
|
|
511
|
+
if (resp.status === 404)
|
|
512
|
+
return null;
|
|
513
|
+
if (!resp.ok)
|
|
514
|
+
throw new MemoryHttpError(resp.status, await resp.text());
|
|
515
|
+
return (await resp.json());
|
|
516
|
+
}
|
|
517
|
+
const urlParams = {
|
|
518
|
+
org_id: params.orgId,
|
|
519
|
+
project_id: params.projectId,
|
|
520
|
+
include_deleted: params.includeDeleted ?? false,
|
|
521
|
+
};
|
|
522
|
+
if (params.userId != null)
|
|
523
|
+
urlParams["user_id"] = params.userId;
|
|
524
|
+
if (params.visibility != null)
|
|
525
|
+
urlParams["visibility"] = params.visibility;
|
|
526
|
+
if (params.procedure != null)
|
|
527
|
+
urlParams["procedure"] = params.procedure;
|
|
528
|
+
const data = await this.requestOrNull("GET", "/procedural", z.object({ entries: z.array(z.unknown()) }), undefined, urlParams, params.signal);
|
|
529
|
+
if (data == null)
|
|
530
|
+
return null;
|
|
531
|
+
if (params.procedure != null) {
|
|
532
|
+
return (data.entries.find((e) => e["procedure"] === params.procedure) ?? null);
|
|
533
|
+
}
|
|
534
|
+
return data.entries.length > 0 ? data.entries[0] : null;
|
|
535
|
+
}
|
|
536
|
+
async updateProcedural(params) {
|
|
537
|
+
let memoryId = params.id;
|
|
538
|
+
if (memoryId == null && params.procedure != null) {
|
|
539
|
+
const existing = await this.getProcedural({
|
|
540
|
+
orgId: params.orgId,
|
|
541
|
+
projectId: params.projectId,
|
|
542
|
+
procedure: params.procedure,
|
|
543
|
+
signal: params.signal,
|
|
544
|
+
});
|
|
545
|
+
if (existing == null)
|
|
546
|
+
throw new Error(`Procedural memory not found: ${params.procedure}`);
|
|
547
|
+
const rawId = existing["id"] ??
|
|
548
|
+
existing["_id"];
|
|
549
|
+
if (rawId == null)
|
|
550
|
+
throw new Error(`Procedural memory has no id field: ${params.procedure}`);
|
|
551
|
+
memoryId = String(rawId);
|
|
552
|
+
}
|
|
553
|
+
if (memoryId == null)
|
|
554
|
+
throw new Error("id or procedure is required to update a procedural memory");
|
|
555
|
+
const body = {
|
|
556
|
+
org_id: params.orgId,
|
|
557
|
+
description: params.description,
|
|
558
|
+
content: params.content,
|
|
559
|
+
steps: params.steps,
|
|
560
|
+
resources: params.resources,
|
|
561
|
+
allowed_tools: params.allowedTools,
|
|
562
|
+
trigger_conditions: params.triggerConditions,
|
|
563
|
+
tags: params.tags,
|
|
564
|
+
visibility: params.visibility,
|
|
565
|
+
project_id: params.projectId,
|
|
566
|
+
};
|
|
567
|
+
return this.request("PATCH", `/procedural/${encodeIdSegment(String(memoryId))}`, z.unknown(), body, undefined, params.signal);
|
|
568
|
+
}
|
|
569
|
+
async deleteProcedural(params) {
|
|
570
|
+
let memoryId = params.id;
|
|
571
|
+
if (memoryId == null && params.procedure != null) {
|
|
572
|
+
const existing = await this.getProcedural({
|
|
573
|
+
orgId: params.orgId,
|
|
574
|
+
projectId: params.projectId,
|
|
575
|
+
procedure: params.procedure,
|
|
576
|
+
signal: params.signal,
|
|
577
|
+
});
|
|
578
|
+
if (existing == null)
|
|
579
|
+
throw new Error(`Procedural memory not found: ${params.procedure}`);
|
|
580
|
+
const rawId = existing["id"] ??
|
|
581
|
+
existing["_id"];
|
|
582
|
+
if (rawId == null)
|
|
583
|
+
throw new Error(`Procedural memory has no id field: ${params.procedure}`);
|
|
584
|
+
memoryId = String(rawId);
|
|
585
|
+
}
|
|
586
|
+
if (memoryId == null)
|
|
587
|
+
throw new Error("id or procedure is required to delete a procedural memory");
|
|
588
|
+
return this.request("DELETE", `/procedural/${encodeIdSegment(String(memoryId))}`, DeleteResultSchema, undefined, {
|
|
589
|
+
org_id: params.orgId,
|
|
590
|
+
project_id: params.projectId,
|
|
591
|
+
soft: params.soft ?? true,
|
|
592
|
+
}, params.signal);
|
|
593
|
+
}
|
|
594
|
+
async discoverProcedures(params) {
|
|
595
|
+
const body = {
|
|
596
|
+
query: params.query,
|
|
597
|
+
org_id: params.orgId,
|
|
598
|
+
user_id: params.userId,
|
|
599
|
+
visibility: params.visibility,
|
|
600
|
+
project_id: params.projectId,
|
|
601
|
+
tags: params.tags,
|
|
602
|
+
top_k: params.topK ?? 10,
|
|
603
|
+
similarity_threshold: params.similarityThreshold ?? 0.0,
|
|
604
|
+
};
|
|
605
|
+
// Match Python's `if metadata_filter:` (truthy) — skip an empty object.
|
|
606
|
+
if (params.metadataFilter != null &&
|
|
607
|
+
Object.keys(params.metadataFilter).length > 0)
|
|
608
|
+
body["metadata_filter"] = params.metadataFilter;
|
|
609
|
+
const route = this.searchRoute("procedural", body);
|
|
610
|
+
const data = await this.request("POST", route.path, z.object({ memories: z.array(z.record(z.string(), z.unknown())) }), route.body, undefined, params.signal);
|
|
611
|
+
return data.memories.map((m) => ({
|
|
612
|
+
procedure: m["metadata"]?.["procedure"] ?? "",
|
|
613
|
+
content: m["content"] ?? "",
|
|
614
|
+
score: m["similarity_score"] ?? 0.0,
|
|
615
|
+
...m["metadata"],
|
|
616
|
+
}));
|
|
617
|
+
}
|
|
618
|
+
async fetchProceduralMemories(params) {
|
|
619
|
+
const route = this.searchRoute("procedural", {
|
|
620
|
+
query: params.query,
|
|
621
|
+
org_id: params.orgId,
|
|
622
|
+
user_id: params.userId,
|
|
623
|
+
visibility: params.visibility,
|
|
624
|
+
project_id: params.projectId,
|
|
625
|
+
tags: params.tags,
|
|
626
|
+
top_k: params.topK ?? 50,
|
|
627
|
+
});
|
|
628
|
+
const data = await this.request("POST", route.path, z.object({ memories: z.array(MemoryChunkSchema) }), route.body, undefined, params.signal);
|
|
629
|
+
return data.memories;
|
|
630
|
+
}
|
|
631
|
+
// ===========================================================================
|
|
632
|
+
// Custom Memory Types
|
|
633
|
+
// ===========================================================================
|
|
634
|
+
async createCustom(params) {
|
|
635
|
+
const body = { content: params.content };
|
|
636
|
+
if (params.tags != null)
|
|
637
|
+
body.tags = params.tags;
|
|
638
|
+
if (params.contextualMetadata != null) {
|
|
639
|
+
body.contextual_metadata = params.contextualMetadata;
|
|
640
|
+
}
|
|
641
|
+
return this.request("POST", `/types/${encodeIdSegment(params.memoryType)}`, CustomMemorySaveResultSchema, body, undefined, params.signal);
|
|
642
|
+
}
|
|
643
|
+
async retrieveCustom(params) {
|
|
644
|
+
const body = {
|
|
645
|
+
query: params.query,
|
|
646
|
+
top_k: params.topK ?? 10,
|
|
647
|
+
};
|
|
648
|
+
if (params.tags != null)
|
|
649
|
+
body.tags = params.tags;
|
|
650
|
+
return this.request("POST", `/types/${encodeIdSegment(params.memoryType)}/retrieve`, CustomMemoryRetrieveResultSchema, body, undefined, params.signal);
|
|
651
|
+
}
|
|
652
|
+
// ===========================================================================
|
|
653
|
+
// Bootstrap
|
|
654
|
+
// ===========================================================================
|
|
655
|
+
bootstrap() {
|
|
656
|
+
// No-op for HTTP client — server handles bootstrap.
|
|
657
|
+
}
|
|
658
|
+
}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/** @mongodb-js/agent-engine-sdk — Core TypeScript protocols and models for MongoDB Agent Engine. */
|
|
2
|
+
export type { JsonValue, Role, AnyContentBlock, TextBlock, ImageBlock, DocumentBlock, ToolDefinition, ToolDefinitionInput, LLMStreamChunk, ToolCallChunk, Message, AgentInput, AgentOutput, StreamEvent, RequestContext, BranchRef, Event, SessionSummary, SessionsSummaryResponse, SessionMessage, SessionMessagesResponse, } from "./models.js";
|
|
3
|
+
export { TextBlockSchema, ImageBlockSchema, DocumentBlockSchema, AnyContentBlockSchema, ToolDefinitionSchema, createToolDefinition, JsonValueSchema, LLMTokenUsage, LLMTokenUsageSchema, LLMToolCall, LLMToolCallSchema, LLMToolSchema, LLMToolSchemaValidator, LLMInvocationOptions, LLMInvocationOptionsSchema, LLMResponse, LLMResponseSchema, MessageSchema, serializeMessage, ToolCallChunkSchema, AgentInputSchema, AgentOutputSchema, StreamEventSchema, BranchRefSchema, EventSchema, DateFromStringSchema, SessionSummarySchema, SessionsSummaryResponseSchema, SessionMessageSchema, SessionMessagesResponseSchema, } from "./models.js";
|
|
4
|
+
export type { ExecutionResult, BaseAgent, BaseLLM, BaseExecutionCallback, } from "./interfaces.js";
|
|
5
|
+
export { NullExecutionCallback } from "./interfaces.js";
|
|
6
|
+
export { BaseApp } from "./app.js";
|
|
7
|
+
export type { EventResponse, EventsResponse } from "./api/events.js";
|
|
8
|
+
export { EventResponseSchema, EventsResponseSchema } from "./api/events.js";
|
|
9
|
+
export type { WriteTurnResult, CreateSemanticResult, BulkCreateSemanticResult, CreateEpisodicResult, CreateTaxonomicResult, CreateProceduralResult, CreateUserContextResult, CreateSnapshotResult, PromoteSnapshotResult, DeleteResult, InternalStateResult, ISGenerationResult, MemoryChunk, ContextConfig, ContextMetadata, ContextResponse, TagScalar, CustomMemorySaveResult, RetrievedCustomMemory, CustomMemoryRetrieveResult, } from "./api/v1/memory.js";
|
|
10
|
+
export { MemorySource, MemorySourceSchema, FormatStyle, FormatStyleSchema, ModelType, ModelTypeSchema, WriteTurnResultSchema, CreateSemanticResultSchema, BulkCreateSemanticResultSchema, CreateEpisodicResultSchema, CreateTaxonomicResultSchema, CreateProceduralResultSchema, CreateUserContextResultSchema, CreateSnapshotResultSchema, PromoteSnapshotResultSchema, DeleteResultSchema, InternalStateResultSchema, ISGenerationResultSchema, MemoryChunkSchema, ContextConfigSchema, ContextMetadataSchema, ContextResponseSchema, TagScalarSchema, CustomMemorySaveResultSchema, RetrievedCustomMemorySchema, CustomMemoryRetrieveResultSchema, } from "./api/v1/memory.js";
|
|
11
|
+
export { EventClient } from "./clients/events.js";
|
|
12
|
+
export { MemoryClient, MemoryHttpError } from "./clients/memory.js";
|
|
13
|
+
export type { MemoryRouteStyle } from "./clients/memory.js";
|
|
14
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,oGAAoG;AAEpG,YAAY,EACV,SAAS,EACT,IAAI,EACJ,eAAe,EACf,SAAS,EACT,UAAU,EACV,aAAa,EACb,cAAc,EACd,mBAAmB,EACnB,cAAc,EACd,aAAa,EACb,OAAO,EACP,UAAU,EACV,WAAW,EACX,WAAW,EACX,cAAc,EACd,SAAS,EACT,KAAK,EACL,cAAc,EACd,uBAAuB,EACvB,cAAc,EACd,uBAAuB,GACxB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,eAAe,EACf,gBAAgB,EAChB,mBAAmB,EACnB,qBAAqB,EACrB,oBAAoB,EACpB,oBAAoB,EACpB,eAAe,EACf,aAAa,EACb,mBAAmB,EACnB,WAAW,EACX,iBAAiB,EACjB,aAAa,EACb,sBAAsB,EACtB,oBAAoB,EACpB,0BAA0B,EAC1B,WAAW,EACX,iBAAiB,EACjB,aAAa,EACb,gBAAgB,EAChB,mBAAmB,EACnB,gBAAgB,EAChB,iBAAiB,EACjB,iBAAiB,EACjB,eAAe,EACf,WAAW,EACX,oBAAoB,EACpB,oBAAoB,EACpB,6BAA6B,EAC7B,oBAAoB,EACpB,6BAA6B,GAC9B,MAAM,aAAa,CAAC;AAErB,YAAY,EACV,eAAe,EACf,SAAS,EACT,OAAO,EACP,qBAAqB,GACtB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;AAExD,OAAO,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AAEnC,YAAY,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACrE,OAAO,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AAE5E,YAAY,EACV,eAAe,EACf,oBAAoB,EACpB,wBAAwB,EACxB,oBAAoB,EACpB,qBAAqB,EACrB,sBAAsB,EACtB,uBAAuB,EACvB,oBAAoB,EACpB,qBAAqB,EACrB,YAAY,EACZ,mBAAmB,EACnB,kBAAkB,EAClB,WAAW,EACX,aAAa,EACb,eAAe,EACf,eAAe,EACf,SAAS,EACT,sBAAsB,EACtB,qBAAqB,EACrB,0BAA0B,GAC3B,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACL,YAAY,EACZ,kBAAkB,EAClB,WAAW,EACX,iBAAiB,EACjB,SAAS,EACT,eAAe,EACf,qBAAqB,EACrB,0BAA0B,EAC1B,8BAA8B,EAC9B,0BAA0B,EAC1B,2BAA2B,EAC3B,4BAA4B,EAC5B,6BAA6B,EAC7B,0BAA0B,EAC1B,2BAA2B,EAC3B,kBAAkB,EAClB,yBAAyB,EACzB,wBAAwB,EACxB,iBAAiB,EACjB,mBAAmB,EACnB,qBAAqB,EACrB,qBAAqB,EACrB,eAAe,EACf,4BAA4B,EAC5B,2BAA2B,EAC3B,gCAAgC,GACjC,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAClD,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AACpE,YAAY,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC"}
|