@mongodb-js/agent-engine-sdk-memory 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 +115 -0
- package/dist/errors.d.ts +65 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +96 -0
- package/dist/http/client_adapter.d.ts +82 -0
- package/dist/http/client_adapter.d.ts.map +1 -0
- package/dist/http/client_adapter.js +452 -0
- package/dist/identity.d.ts +31 -0
- package/dist/identity.d.ts.map +1 -0
- package/dist/identity.js +48 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +9 -0
- package/dist/memory.d.ts +221 -0
- package/dist/memory.d.ts.map +1 -0
- package/dist/memory.js +601 -0
- package/dist/models.d.ts +168 -0
- package/dist/models.d.ts.map +1 -0
- package/dist/models.js +147 -0
- package/dist/tag_syntax.d.ts +22 -0
- package/dist/tag_syntax.d.ts.map +1 -0
- package/dist/tag_syntax.js +110 -0
- package/dist/transport.d.ts +191 -0
- package/dist/transport.d.ts.map +1 -0
- package/dist/transport.js +6 -0
- package/package.json +52 -0
|
@@ -0,0 +1,452 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `MemoryRuntime` + `MemoryCrudClient` implemented over agent-engine-sdk's
|
|
3
|
+
* `MemoryClient`.
|
|
4
|
+
*
|
|
5
|
+
* The facade needs two seams (the workflow runtime and the CRUD conveniences);
|
|
6
|
+
* `MemoryClient` already owns the HTTP mechanics both share — URL building, the
|
|
7
|
+
* transport-extras/dynamic-header hooks, the bounded 5xx/network retry, and the
|
|
8
|
+
* 404→null lookup semantics. Rather than reimplement that stack, this adapter is
|
|
9
|
+
* a thin binding: it fills the empty tenancy the backends stamp (`org_id`/
|
|
10
|
+
* `project_id` come from the trusted OE execution context or the Gateway API
|
|
11
|
+
* key), selects the route convention per backend, and translates
|
|
12
|
+
* `MemoryClient`'s `MemoryHttpError` into the memory package's typed error
|
|
13
|
+
* hierarchy (which is this package's public API).
|
|
14
|
+
*
|
|
15
|
+
* Two `MemoryClient` instances back each adapter: a retrying one for the write
|
|
16
|
+
* turn and all reads (idempotent — turns carry an idempotency key, reads are
|
|
17
|
+
* pure) and a non-retrying one for type-specific creates (no idempotency key, so
|
|
18
|
+
* a retry after the server committed could duplicate the record).
|
|
19
|
+
*/
|
|
20
|
+
import { MemoryClient, MemoryHttpError, } from "@mongodb-js/agent-engine-sdk";
|
|
21
|
+
import { MemoryAuthError, MemoryBadRequestError, MemoryConnectionError, MemoryNotProvisionedError, MemoryNotSupportedError, MemoryRouteNotFoundError, MemoryServerError, } from "../errors.js";
|
|
22
|
+
import { ContextResponseSchema, CreateEpisodicResultSchema, CreateProceduralResultSchema, CreateSemanticResultSchema, CreateTaxonomicResultSchema, CustomMemoryRetrieveResultSchema, CustomMemorySaveResultSchema, MemoryChunkSchema, WriteTurnResultSchema, } from "../models.js";
|
|
23
|
+
/** Error codes the backends use to signal the memory runtime is not yet reachable. */
|
|
24
|
+
const NOT_PROVISIONED_CODES = new Set([
|
|
25
|
+
"AGENT_NOT_DEPLOYED",
|
|
26
|
+
"NO_WORKSPACE_ENDPOINT",
|
|
27
|
+
"PROJECT_RUNTIME_FAILED",
|
|
28
|
+
]);
|
|
29
|
+
const RETRIES = 2; // initial + 2 retries, matching the previous transport
|
|
30
|
+
/** Empty tenancy: the backend stamps the trusted org/project (caller cannot override). */
|
|
31
|
+
const EMPTY_ORG = "";
|
|
32
|
+
const EMPTY_PROJECT = "";
|
|
33
|
+
/** A single `MemoryClient`-backed runtime + CRUD client for the `Memory` facade. */
|
|
34
|
+
export class MemoryClientAdapter {
|
|
35
|
+
retry;
|
|
36
|
+
noRetry;
|
|
37
|
+
projectScoped;
|
|
38
|
+
constructor(opts) {
|
|
39
|
+
this.projectScoped = opts.projectScoped;
|
|
40
|
+
const timeout = opts.timeout ?? 30;
|
|
41
|
+
const make = (maxRetries) => new MemoryClient(opts.baseUrl, timeout, opts.headers ?? {}, opts.apiPrefix, undefined, opts.requestExtras, maxRetries, opts.routeStyle, opts.fetchImpl);
|
|
42
|
+
this.retry = make(RETRIES);
|
|
43
|
+
this.noRetry = make(0);
|
|
44
|
+
}
|
|
45
|
+
// ---------------------------------------------------------------------------
|
|
46
|
+
// Error translation
|
|
47
|
+
// ---------------------------------------------------------------------------
|
|
48
|
+
/** Map a `MemoryClient` failure to this package's typed error hierarchy. */
|
|
49
|
+
mapError(err, coreLoop) {
|
|
50
|
+
if (!(err instanceof MemoryHttpError)) {
|
|
51
|
+
// A JSON-parse (SyntaxError from resp.json()) or schema-validation
|
|
52
|
+
// (ZodError from schema.parse) failure means the backend answered but the
|
|
53
|
+
// success body was unparseable/invalid — a server-side contract violation,
|
|
54
|
+
// not a transport failure. Mirror the Python SDK and surface it as a
|
|
55
|
+
// MemoryServerError rather than a MemoryConnectionError.
|
|
56
|
+
if (err instanceof SyntaxError ||
|
|
57
|
+
(err instanceof Error && err.name === "ZodError")) {
|
|
58
|
+
return new MemoryServerError(String(err), { status: null });
|
|
59
|
+
}
|
|
60
|
+
// fetch/timeout — MemoryClient rethrows the raw error after exhausting retries.
|
|
61
|
+
return new MemoryConnectionError(String(err), { status: null });
|
|
62
|
+
}
|
|
63
|
+
const { status, responseText } = err;
|
|
64
|
+
let code = null;
|
|
65
|
+
let message = responseText;
|
|
66
|
+
try {
|
|
67
|
+
const parsed = JSON.parse(responseText);
|
|
68
|
+
if (parsed !== null &&
|
|
69
|
+
typeof parsed === "object" &&
|
|
70
|
+
!Array.isArray(parsed)) {
|
|
71
|
+
const body = parsed;
|
|
72
|
+
code = body.code || null;
|
|
73
|
+
// `detail` is FastAPI's convention and is what the memory server
|
|
74
|
+
// returns; without it a structured message surfaces as raw JSON. Only
|
|
75
|
+
// strings qualify — FastAPI validation errors put a list there.
|
|
76
|
+
const detail = typeof body.detail === "string" ? body.detail : undefined;
|
|
77
|
+
message =
|
|
78
|
+
body.error ||
|
|
79
|
+
body.message ||
|
|
80
|
+
detail ||
|
|
81
|
+
responseText;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
catch {
|
|
85
|
+
// Non-JSON body: keep the raw text as the message.
|
|
86
|
+
}
|
|
87
|
+
const opts = { status, code, responseText };
|
|
88
|
+
if (status === 401 || status === 403)
|
|
89
|
+
return new MemoryAuthError(message, opts);
|
|
90
|
+
if (code !== null && NOT_PROVISIONED_CODES.has(code))
|
|
91
|
+
return new MemoryNotProvisionedError(message, opts);
|
|
92
|
+
if (status === 404 && coreLoop)
|
|
93
|
+
return this.routeNotFoundError(opts);
|
|
94
|
+
if (status >= 400 && status < 500)
|
|
95
|
+
return new MemoryBadRequestError(message, opts);
|
|
96
|
+
return new MemoryServerError(message, opts);
|
|
97
|
+
}
|
|
98
|
+
routeNotFoundError(opts) {
|
|
99
|
+
const hint = this.projectScoped
|
|
100
|
+
? "projectId is set, so the SDK used a project-scoped memory route; if you " +
|
|
101
|
+
"are targeting a local or direct OE backend, unset projectId (or " +
|
|
102
|
+
"AGENTIC_MEMORY_PROJECT_ID)"
|
|
103
|
+
: "projectId is empty, so the SDK used a flat memory route; if you are " +
|
|
104
|
+
"targeting the hosted Gateway, set projectId (or AGENTIC_MEMORY_PROJECT_ID)";
|
|
105
|
+
return new MemoryRouteNotFoundError("memory route not found (404). This often means the route shape does not " +
|
|
106
|
+
`match the backend: ${hint}. It can also mean baseUrl points at the ` +
|
|
107
|
+
"wrong host.", opts);
|
|
108
|
+
}
|
|
109
|
+
// ---------------------------------------------------------------------------
|
|
110
|
+
// MemoryRuntime
|
|
111
|
+
// ---------------------------------------------------------------------------
|
|
112
|
+
async recordTurn(args) {
|
|
113
|
+
try {
|
|
114
|
+
const r = await this.retry.writeTurn({
|
|
115
|
+
sessionId: args.sessionId,
|
|
116
|
+
role: args.role,
|
|
117
|
+
orgId: EMPTY_ORG,
|
|
118
|
+
userId: args.userId,
|
|
119
|
+
projectId: EMPTY_PROJECT,
|
|
120
|
+
content: args.content,
|
|
121
|
+
modelName: args.modelName,
|
|
122
|
+
toolCalls: args.toolCalls,
|
|
123
|
+
toolCallId: args.toolCallId,
|
|
124
|
+
toolName: args.toolName,
|
|
125
|
+
isError: args.isError,
|
|
126
|
+
idempotencyKey: args.idempotencyKey,
|
|
127
|
+
});
|
|
128
|
+
return WriteTurnResultSchema.parse(r);
|
|
129
|
+
}
|
|
130
|
+
catch (e) {
|
|
131
|
+
throw this.mapError(e, true);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
async buildContext(args) {
|
|
135
|
+
try {
|
|
136
|
+
const r = await this.retry.buildContext({
|
|
137
|
+
query: args.query,
|
|
138
|
+
sessionId: args.sessionId,
|
|
139
|
+
orgId: EMPTY_ORG,
|
|
140
|
+
userId: args.userId,
|
|
141
|
+
projectId: EMPTY_PROJECT,
|
|
142
|
+
visibility: args.visibility,
|
|
143
|
+
metadataFilter: args.metadataFilter,
|
|
144
|
+
// The facade carries enabled sources as a Set; MemoryClient takes a
|
|
145
|
+
// sorted array (deterministic wire order).
|
|
146
|
+
enabledSources: args.enabledSources
|
|
147
|
+
? [...args.enabledSources].sort()
|
|
148
|
+
: null,
|
|
149
|
+
topK: args.topK,
|
|
150
|
+
maxTokens: args.maxTokens,
|
|
151
|
+
});
|
|
152
|
+
return ContextResponseSchema.parse(r);
|
|
153
|
+
}
|
|
154
|
+
catch (e) {
|
|
155
|
+
throw this.mapError(e, true);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
async searchSemantic(args) {
|
|
159
|
+
try {
|
|
160
|
+
const rows = await this.retry.fetchSemanticMemories({
|
|
161
|
+
query: args.query,
|
|
162
|
+
orgId: EMPTY_ORG,
|
|
163
|
+
projectId: EMPTY_PROJECT,
|
|
164
|
+
userId: args.userId,
|
|
165
|
+
visibility: args.visibility,
|
|
166
|
+
topK: args.topK,
|
|
167
|
+
});
|
|
168
|
+
return rows.map((m) => MemoryChunkSchema.parse(m));
|
|
169
|
+
}
|
|
170
|
+
catch (e) {
|
|
171
|
+
throw this.mapError(e, true);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
async searchEpisodes(args) {
|
|
175
|
+
try {
|
|
176
|
+
const rows = await this.retry.fetchEpisodicMemories({
|
|
177
|
+
query: args.query,
|
|
178
|
+
orgId: EMPTY_ORG,
|
|
179
|
+
projectId: EMPTY_PROJECT,
|
|
180
|
+
userId: args.userId,
|
|
181
|
+
visibility: args.visibility,
|
|
182
|
+
sessionId: args.sessionId,
|
|
183
|
+
topK: args.topK,
|
|
184
|
+
});
|
|
185
|
+
return rows.map((m) => MemoryChunkSchema.parse(m));
|
|
186
|
+
}
|
|
187
|
+
catch (e) {
|
|
188
|
+
throw this.mapError(e, true);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
async searchTaxonomic(args) {
|
|
192
|
+
try {
|
|
193
|
+
const rows = await this.retry.fetchTaxonomicMemories({
|
|
194
|
+
query: args.query,
|
|
195
|
+
orgId: EMPTY_ORG,
|
|
196
|
+
projectId: EMPTY_PROJECT,
|
|
197
|
+
domain: args.domain,
|
|
198
|
+
visibility: args.visibility,
|
|
199
|
+
topK: args.topK,
|
|
200
|
+
});
|
|
201
|
+
return rows.map((m) => MemoryChunkSchema.parse(m));
|
|
202
|
+
}
|
|
203
|
+
catch (e) {
|
|
204
|
+
throw this.mapError(e, true);
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
async discoverProcedures(args) {
|
|
208
|
+
try {
|
|
209
|
+
return await this.retry.discoverProcedures({
|
|
210
|
+
query: args.query,
|
|
211
|
+
orgId: EMPTY_ORG,
|
|
212
|
+
projectId: EMPTY_PROJECT,
|
|
213
|
+
userId: args.userId,
|
|
214
|
+
visibility: args.visibility,
|
|
215
|
+
tags: args.tags,
|
|
216
|
+
topK: args.topK,
|
|
217
|
+
similarityThreshold: args.similarityThreshold,
|
|
218
|
+
metadataFilter: args.metadataFilter,
|
|
219
|
+
});
|
|
220
|
+
}
|
|
221
|
+
catch (e) {
|
|
222
|
+
throw this.mapError(e, true);
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
// ---------------------------------------------------------------------------
|
|
226
|
+
// MemoryCrudClient
|
|
227
|
+
// ---------------------------------------------------------------------------
|
|
228
|
+
async createSemantic(args) {
|
|
229
|
+
try {
|
|
230
|
+
const r = await this.noRetry.createSemantic({
|
|
231
|
+
label: args.label,
|
|
232
|
+
text: args.text,
|
|
233
|
+
orgId: EMPTY_ORG,
|
|
234
|
+
userId: args.userId,
|
|
235
|
+
projectId: EMPTY_PROJECT,
|
|
236
|
+
source: args.source,
|
|
237
|
+
visibility: args.visibility,
|
|
238
|
+
agentId: args.agentId,
|
|
239
|
+
metadata: args.metadata,
|
|
240
|
+
upsert: args.upsert,
|
|
241
|
+
});
|
|
242
|
+
return CreateSemanticResultSchema.parse(r);
|
|
243
|
+
}
|
|
244
|
+
catch (e) {
|
|
245
|
+
throw this.mapError(e, false);
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
async getSemantic(args) {
|
|
249
|
+
try {
|
|
250
|
+
return await this.retry.getSemantic({
|
|
251
|
+
orgId: EMPTY_ORG,
|
|
252
|
+
projectId: EMPTY_PROJECT,
|
|
253
|
+
label: args.label,
|
|
254
|
+
userId: args.userId,
|
|
255
|
+
visibility: args.visibility,
|
|
256
|
+
});
|
|
257
|
+
}
|
|
258
|
+
catch (e) {
|
|
259
|
+
throw this.mapError(e, false);
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
async createEpisodic(args) {
|
|
263
|
+
try {
|
|
264
|
+
const r = await this.noRetry.createEpisodic({
|
|
265
|
+
title: args.title,
|
|
266
|
+
content: args.content,
|
|
267
|
+
summaryText: args.summaryText ?? "",
|
|
268
|
+
orgId: EMPTY_ORG,
|
|
269
|
+
userId: args.userId,
|
|
270
|
+
sessionId: args.sessionId,
|
|
271
|
+
projectId: EMPTY_PROJECT,
|
|
272
|
+
visibility: args.visibility,
|
|
273
|
+
agentId: args.agentId,
|
|
274
|
+
participants: args.participants,
|
|
275
|
+
tags: args.tags,
|
|
276
|
+
metadata: args.metadata,
|
|
277
|
+
});
|
|
278
|
+
return CreateEpisodicResultSchema.parse(r);
|
|
279
|
+
}
|
|
280
|
+
catch (e) {
|
|
281
|
+
throw this.mapError(e, false);
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
async listEpisodic(args) {
|
|
285
|
+
try {
|
|
286
|
+
return await this.retry.listEpisodic({
|
|
287
|
+
orgId: EMPTY_ORG,
|
|
288
|
+
projectId: EMPTY_PROJECT,
|
|
289
|
+
userId: args.userId,
|
|
290
|
+
sessionId: args.sessionId,
|
|
291
|
+
visibility: args.visibility,
|
|
292
|
+
limit: args.limit,
|
|
293
|
+
});
|
|
294
|
+
}
|
|
295
|
+
catch (e) {
|
|
296
|
+
throw this.mapError(e, false);
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
async createTaxonomic(args) {
|
|
300
|
+
try {
|
|
301
|
+
const r = await this.noRetry.createTaxonomic({
|
|
302
|
+
domain: args.domain,
|
|
303
|
+
term: args.term,
|
|
304
|
+
definition: args.definition,
|
|
305
|
+
orgId: EMPTY_ORG,
|
|
306
|
+
userId: args.userId,
|
|
307
|
+
projectId: EMPTY_PROJECT,
|
|
308
|
+
relatedTerms: args.relatedTerms,
|
|
309
|
+
visibility: args.visibility,
|
|
310
|
+
});
|
|
311
|
+
return CreateTaxonomicResultSchema.parse(r);
|
|
312
|
+
}
|
|
313
|
+
catch (e) {
|
|
314
|
+
throw this.mapError(e, false);
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
async getTaxonomic(args) {
|
|
318
|
+
try {
|
|
319
|
+
return await this.retry.getTaxonomic({
|
|
320
|
+
orgId: EMPTY_ORG,
|
|
321
|
+
projectId: EMPTY_PROJECT,
|
|
322
|
+
domain: args.domain,
|
|
323
|
+
term: args.term,
|
|
324
|
+
userId: args.userId,
|
|
325
|
+
visibility: args.visibility,
|
|
326
|
+
});
|
|
327
|
+
}
|
|
328
|
+
catch (e) {
|
|
329
|
+
throw this.mapError(e, false);
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
async getDistinctDomains(args) {
|
|
333
|
+
try {
|
|
334
|
+
return await this.retry.getDistinctDomains({
|
|
335
|
+
orgId: EMPTY_ORG,
|
|
336
|
+
projectId: EMPTY_PROJECT,
|
|
337
|
+
visibility: args.visibility,
|
|
338
|
+
});
|
|
339
|
+
}
|
|
340
|
+
catch (e) {
|
|
341
|
+
throw this.mapError(e, false);
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
async createProcedural(args) {
|
|
345
|
+
if (args.updateExisting) {
|
|
346
|
+
// The HTTP backends serve only a create route that always creates;
|
|
347
|
+
// app-bound mode honors updateExisting through its own runtime.
|
|
348
|
+
throw new MemoryNotSupportedError("updateExisting is not supported by the HTTP memory backends; the create " +
|
|
349
|
+
"route always creates a new procedure");
|
|
350
|
+
}
|
|
351
|
+
try {
|
|
352
|
+
const r = await this.noRetry.createProcedural({
|
|
353
|
+
procedure: args.procedure,
|
|
354
|
+
description: args.description,
|
|
355
|
+
content: args.content,
|
|
356
|
+
orgId: EMPTY_ORG,
|
|
357
|
+
userId: args.userId,
|
|
358
|
+
projectId: EMPTY_PROJECT,
|
|
359
|
+
steps: args.steps,
|
|
360
|
+
resources: args.resources,
|
|
361
|
+
allowedTools: args.allowedTools,
|
|
362
|
+
compatibility: args.compatibility,
|
|
363
|
+
license: args.license,
|
|
364
|
+
triggerConditions: args.triggerConditions,
|
|
365
|
+
tags: args.tags,
|
|
366
|
+
visibility: args.visibility,
|
|
367
|
+
agentId: args.agentId,
|
|
368
|
+
extractionSource: args.extractionSource,
|
|
369
|
+
sourceFormat: args.sourceFormat,
|
|
370
|
+
sourcePath: args.sourcePath,
|
|
371
|
+
});
|
|
372
|
+
return CreateProceduralResultSchema.parse(r);
|
|
373
|
+
}
|
|
374
|
+
catch (e) {
|
|
375
|
+
throw this.mapError(e, false);
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
async getProcedural(args) {
|
|
379
|
+
try {
|
|
380
|
+
return await this.retry.getProcedural({
|
|
381
|
+
orgId: EMPTY_ORG,
|
|
382
|
+
projectId: EMPTY_PROJECT,
|
|
383
|
+
procedure: args.procedure,
|
|
384
|
+
userId: args.userId,
|
|
385
|
+
visibility: args.visibility,
|
|
386
|
+
includeDeleted: args.includeDeleted,
|
|
387
|
+
});
|
|
388
|
+
}
|
|
389
|
+
catch (e) {
|
|
390
|
+
throw this.mapError(e, false);
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
/**
|
|
394
|
+
* A bare 404/405 means the platform predates custom-type operations, and a
|
|
395
|
+
* flag-off gateway rejects with a 400 naming the feature; the server's
|
|
396
|
+
* unknown-type 404 names the type in a structured body and must pass
|
|
397
|
+
* through untouched.
|
|
398
|
+
*/
|
|
399
|
+
mapCustomRouteError(e) {
|
|
400
|
+
const mapped = this.mapError(e, false);
|
|
401
|
+
if (mapped instanceof MemoryBadRequestError) {
|
|
402
|
+
const message = String(mapped.message);
|
|
403
|
+
if ((mapped.status === 404 || mapped.status === 405) &&
|
|
404
|
+
!message.includes("unknown custom memory type")) {
|
|
405
|
+
return new MemoryNotSupportedError("this platform version does not support custom memory types; " +
|
|
406
|
+
"save/retrieve requires a platform release with the custom memory " +
|
|
407
|
+
"type operations enabled", { cause: mapped });
|
|
408
|
+
}
|
|
409
|
+
// The gateway's flag-off rejection reuses the generic INVALID_REQUEST
|
|
410
|
+
// code, so this message substring is the only stable discriminator for
|
|
411
|
+
// that 400.
|
|
412
|
+
if (mapped.status === 400 &&
|
|
413
|
+
message.includes("custom_memory_types is not enabled")) {
|
|
414
|
+
return new MemoryNotSupportedError("custom memory types are disabled on this deployment; " +
|
|
415
|
+
"save/retrieve requires the custom_memory_types feature to be " +
|
|
416
|
+
"enabled", { cause: mapped });
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
return mapped;
|
|
420
|
+
}
|
|
421
|
+
async createCustom(args) {
|
|
422
|
+
try {
|
|
423
|
+
const r = await this.noRetry.createCustom({
|
|
424
|
+
memoryType: args.memoryType,
|
|
425
|
+
content: args.content,
|
|
426
|
+
tags: args.tags,
|
|
427
|
+
contextualMetadata: args.contextualMetadata,
|
|
428
|
+
});
|
|
429
|
+
return CustomMemorySaveResultSchema.parse(r);
|
|
430
|
+
}
|
|
431
|
+
catch (e) {
|
|
432
|
+
throw this.mapCustomRouteError(e);
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
async retrieveCustom(args) {
|
|
436
|
+
try {
|
|
437
|
+
const r = await this.retry.retrieveCustom({
|
|
438
|
+
memoryType: args.memoryType,
|
|
439
|
+
query: args.query,
|
|
440
|
+
tags: args.tags,
|
|
441
|
+
topK: args.topK,
|
|
442
|
+
});
|
|
443
|
+
return CustomMemoryRetrieveResultSchema.parse(r);
|
|
444
|
+
}
|
|
445
|
+
catch (e) {
|
|
446
|
+
throw this.mapCustomRouteError(e);
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
close() {
|
|
450
|
+
// MemoryClient holds no client to close (native fetch); present for parity.
|
|
451
|
+
}
|
|
452
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/** Identity-resolution algorithm: call arg > bind context > runtime context. */
|
|
2
|
+
import type { MemoryRequestContext } from "./transport.js";
|
|
3
|
+
declare const FIELDS: readonly ["userId", "agentId", "sessionId"];
|
|
4
|
+
type Field = (typeof FIELDS)[number];
|
|
5
|
+
export type ResolvedIdentity = Record<Field, string | null>;
|
|
6
|
+
/**
|
|
7
|
+
* Resolve identity fields by precedence: call arg > bind ctx > runtime ctx.
|
|
8
|
+
*
|
|
9
|
+
* Blank or whitespace-only values are treated as unset at every tier.
|
|
10
|
+
*
|
|
11
|
+
* Two optional guards drop tiers for one field each:
|
|
12
|
+
*
|
|
13
|
+
* `suppressRuntimeUserId` drops the runtime tier for `userId`. A read asking for
|
|
14
|
+
* a broad visibility must not borrow the ambient principal as its filter. A
|
|
15
|
+
* `userId` set by the caller or by bind is deliberate and still applies.
|
|
16
|
+
*
|
|
17
|
+
* `suppressInheritedSessionId` drops the bind and runtime tiers for `sessionId`,
|
|
18
|
+
* so only an explicit call arg applies. A `sessionId` scopes conversation I/O,
|
|
19
|
+
* not long-term search; episodic search matches it exactly and consolidated
|
|
20
|
+
* episodic memory is stored without one, so an inherited session matches nothing.
|
|
21
|
+
*/
|
|
22
|
+
export declare function resolveIdentity(args: {
|
|
23
|
+
callArgs: Partial<Record<Field, string | null | undefined>>;
|
|
24
|
+
bindCtx?: MemoryRequestContext | null;
|
|
25
|
+
runtimeCtx?: MemoryRequestContext | null;
|
|
26
|
+
required?: readonly Field[];
|
|
27
|
+
suppressRuntimeUserId?: boolean;
|
|
28
|
+
suppressInheritedSessionId?: boolean;
|
|
29
|
+
}): ResolvedIdentity;
|
|
30
|
+
export {};
|
|
31
|
+
//# sourceMappingURL=identity.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"identity.d.ts","sourceRoot":"","sources":["../src/identity.ts"],"names":[],"mappings":"AAAA,gFAAgF;AAGhF,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AAE3D,QAAA,MAAM,MAAM,6CAA8C,CAAC;AAC3D,KAAK,KAAK,GAAG,CAAC,OAAO,MAAM,CAAC,CAAC,MAAM,CAAC,CAAC;AAErC,MAAM,MAAM,gBAAgB,GAAG,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC,CAAC;AAW5D;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE;IACpC,QAAQ,EAAE,OAAO,CAAC,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC,CAAC,CAAC;IAC5D,OAAO,CAAC,EAAE,oBAAoB,GAAG,IAAI,CAAC;IACtC,UAAU,CAAC,EAAE,oBAAoB,GAAG,IAAI,CAAC;IACzC,QAAQ,CAAC,EAAE,SAAS,KAAK,EAAE,CAAC;IAC5B,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC,0BAA0B,CAAC,EAAE,OAAO,CAAC;CACtC,GAAG,gBAAgB,CAgCnB"}
|
package/dist/identity.js
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/** Identity-resolution algorithm: call arg > bind context > runtime context. */
|
|
2
|
+
import { MemoryIdentityError } from "./errors.js";
|
|
3
|
+
const FIELDS = ["userId", "agentId", "sessionId"];
|
|
4
|
+
function normalize(value) {
|
|
5
|
+
// A blank or whitespace-only value carries no identity; treating it as unset
|
|
6
|
+
// keeps it from satisfying `required` or shadowing a bound value.
|
|
7
|
+
if (value === null || value === undefined || value.trim() === "") {
|
|
8
|
+
return null;
|
|
9
|
+
}
|
|
10
|
+
return value;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Resolve identity fields by precedence: call arg > bind ctx > runtime ctx.
|
|
14
|
+
*
|
|
15
|
+
* Blank or whitespace-only values are treated as unset at every tier.
|
|
16
|
+
*
|
|
17
|
+
* Two optional guards drop tiers for one field each:
|
|
18
|
+
*
|
|
19
|
+
* `suppressRuntimeUserId` drops the runtime tier for `userId`. A read asking for
|
|
20
|
+
* a broad visibility must not borrow the ambient principal as its filter. A
|
|
21
|
+
* `userId` set by the caller or by bind is deliberate and still applies.
|
|
22
|
+
*
|
|
23
|
+
* `suppressInheritedSessionId` drops the bind and runtime tiers for `sessionId`,
|
|
24
|
+
* so only an explicit call arg applies. A `sessionId` scopes conversation I/O,
|
|
25
|
+
* not long-term search; episodic search matches it exactly and consolidated
|
|
26
|
+
* episodic memory is stored without one, so an inherited session matches nothing.
|
|
27
|
+
*/
|
|
28
|
+
export function resolveIdentity(args) {
|
|
29
|
+
const { callArgs, bindCtx = null, runtimeCtx = null, required = [], suppressRuntimeUserId = false, suppressInheritedSessionId = false, } = args;
|
|
30
|
+
const resolved = {};
|
|
31
|
+
for (const field of FIELDS) {
|
|
32
|
+
let value = normalize(callArgs[field]);
|
|
33
|
+
const skipInherited = suppressInheritedSessionId && field === "sessionId";
|
|
34
|
+
if (value === null && bindCtx !== null && !skipInherited) {
|
|
35
|
+
value = normalize(bindCtx[field]);
|
|
36
|
+
}
|
|
37
|
+
const skipRuntime = skipInherited || (suppressRuntimeUserId && field === "userId");
|
|
38
|
+
if (value === null && runtimeCtx !== null && !skipRuntime) {
|
|
39
|
+
value = normalize(runtimeCtx[field]);
|
|
40
|
+
}
|
|
41
|
+
resolved[field] = value;
|
|
42
|
+
}
|
|
43
|
+
const missing = required.filter((field) => resolved[field] === null);
|
|
44
|
+
if (missing.length > 0) {
|
|
45
|
+
throw new MemoryIdentityError(`could not resolve required identity field(s): ${missing.join(", ")}`);
|
|
46
|
+
}
|
|
47
|
+
return resolved;
|
|
48
|
+
}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/** @mongodb-js/agent-engine-sdk-memory — unified Memory facade for Atlas Agent Engine. */
|
|
2
|
+
export { Memory, type MemoryOptions } from "./memory.js";
|
|
3
|
+
export { MemorySource, SearchSource, toSearchSource, WriteTurnResultSchema, CreateSemanticResultSchema, CreateEpisodicResultSchema, CreateTaxonomicResultSchema, CreateProceduralResultSchema, CustomMemorySaveResultSchema, RetrievedCustomMemorySchema, CustomMemoryRetrieveResultSchema, MemoryChunkSchema, ContextMetadataSchema, ContextResponseSchema, } from "./models.js";
|
|
4
|
+
export type { JsonValue, WriteTurnResult, CreateSemanticResult, CreateEpisodicResult, CreateTaxonomicResult, CreateProceduralResult, CustomMemorySaveResult, RetrievedCustomMemory, CustomMemoryRetrieveResult, MemoryChunk, ContextMetadata, ContextResponse, } from "./models.js";
|
|
5
|
+
export type { TagScalar, TagMap } from "./tag_syntax.js";
|
|
6
|
+
export type { MemoryRuntime, MemoryCrudClient, MemoryRequestContext, AmbientIdentityRuntime, FetchLike, RequestExtras, } from "./transport.js";
|
|
7
|
+
export { hasAmbientIdentity } from "./transport.js";
|
|
8
|
+
export { resolveIdentity, type ResolvedIdentity } from "./identity.js";
|
|
9
|
+
export { MemoryClientAdapter, type MemoryClientAdapterOptions, } from "./http/client_adapter.js";
|
|
10
|
+
export { MemoryIdentityError, MemoryClientError, MemoryNotSupportedError, MemoryAPIError, MemoryAuthError, MemoryNotProvisionedError, MemoryBadRequestError, MemoryRouteNotFoundError, MemoryServerError, MemoryConnectionError, } from "./errors.js";
|
|
11
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,0FAA0F;AAE1F,OAAO,EAAE,MAAM,EAAE,KAAK,aAAa,EAAE,MAAM,aAAa,CAAC;AAKzD,OAAO,EACL,YAAY,EACZ,YAAY,EACZ,cAAc,EACd,qBAAqB,EACrB,0BAA0B,EAC1B,0BAA0B,EAC1B,2BAA2B,EAC3B,4BAA4B,EAC5B,4BAA4B,EAC5B,2BAA2B,EAC3B,gCAAgC,EAChC,iBAAiB,EACjB,qBAAqB,EACrB,qBAAqB,GACtB,MAAM,aAAa,CAAC;AACrB,YAAY,EACV,SAAS,EACT,eAAe,EACf,oBAAoB,EACpB,oBAAoB,EACpB,qBAAqB,EACrB,sBAAsB,EACtB,sBAAsB,EACtB,qBAAqB,EACrB,0BAA0B,EAC1B,WAAW,EACX,eAAe,EACf,eAAe,GAChB,MAAM,aAAa,CAAC;AAErB,YAAY,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAEzD,YAAY,EACV,aAAa,EACb,gBAAgB,EAChB,oBAAoB,EACpB,sBAAsB,EACtB,SAAS,EACT,aAAa,GACd,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AAEpD,OAAO,EAAE,eAAe,EAAE,KAAK,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAEvE,OAAO,EACL,mBAAmB,EACnB,KAAK,0BAA0B,GAChC,MAAM,0BAA0B,CAAC;AAElC,OAAO,EACL,mBAAmB,EACnB,iBAAiB,EACjB,uBAAuB,EACvB,cAAc,EACd,eAAe,EACf,yBAAyB,EACzB,qBAAqB,EACrB,wBAAwB,EACxB,iBAAiB,EACjB,qBAAqB,GACtB,MAAM,aAAa,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/** @mongodb-js/agent-engine-sdk-memory — unified Memory facade for Atlas Agent Engine. */
|
|
2
|
+
export { Memory } from "./memory.js";
|
|
3
|
+
// Copyright 2026 MongoDB, Inc.
|
|
4
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
export { MemorySource, SearchSource, toSearchSource, WriteTurnResultSchema, CreateSemanticResultSchema, CreateEpisodicResultSchema, CreateTaxonomicResultSchema, CreateProceduralResultSchema, CustomMemorySaveResultSchema, RetrievedCustomMemorySchema, CustomMemoryRetrieveResultSchema, MemoryChunkSchema, ContextMetadataSchema, ContextResponseSchema, } from "./models.js";
|
|
6
|
+
export { hasAmbientIdentity } from "./transport.js";
|
|
7
|
+
export { resolveIdentity } from "./identity.js";
|
|
8
|
+
export { MemoryClientAdapter, } from "./http/client_adapter.js";
|
|
9
|
+
export { MemoryIdentityError, MemoryClientError, MemoryNotSupportedError, MemoryAPIError, MemoryAuthError, MemoryNotProvisionedError, MemoryBadRequestError, MemoryRouteNotFoundError, MemoryServerError, MemoryConnectionError, } from "./errors.js";
|