@mem9/mem9 0.4.9 → 0.4.10

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.
@@ -1,82 +0,0 @@
1
- import assert from "node:assert/strict";
2
- import test from "node:test";
3
-
4
- import { ServerBackend } from "./server-backend.js";
5
-
6
- test("register forwards only utm_* params during create-new provision", async () => {
7
- const originalFetch = globalThis.fetch;
8
- let requestedURL = "";
9
-
10
- globalThis.fetch = async (input, init) => {
11
- requestedURL = String(input);
12
- assert.equal(init?.method, "POST");
13
-
14
- return new Response(JSON.stringify({ id: "space-1" }), {
15
- status: 201,
16
- headers: {
17
- "Content-Type": "application/json",
18
- },
19
- });
20
- };
21
-
22
- try {
23
- const backend = new ServerBackend("https://api.mem9.ai", "", "agent-1", {
24
- provisionQueryParams: {
25
- utm_source: "bosn",
26
- foo: "bar",
27
- utm_campaign: "spring",
28
- utm_medium: "",
29
- },
30
- });
31
-
32
- const result = await backend.register();
33
- assert.equal(result.id, "space-1");
34
-
35
- const url = new URL(requestedURL);
36
- assert.equal(url.origin + url.pathname, "https://api.mem9.ai/v1alpha1/mem9s");
37
- assert.equal(url.searchParams.get("utm_source"), "bosn");
38
- assert.equal(url.searchParams.get("utm_campaign"), "spring");
39
- assert.equal(url.searchParams.has("foo"), false);
40
- assert.equal(url.searchParams.has("utm_medium"), false);
41
- } finally {
42
- globalThis.fetch = originalFetch;
43
- }
44
- });
45
-
46
- test("normal memory requests do not append provision query params", async () => {
47
- const originalFetch = globalThis.fetch;
48
- let requestedURL = "";
49
-
50
- globalThis.fetch = async (input) => {
51
- requestedURL = String(input);
52
-
53
- return new Response(
54
- JSON.stringify({
55
- id: "mem-1",
56
- content: "remember this",
57
- created_at: "2026-04-05T00:00:00Z",
58
- updated_at: "2026-04-05T00:00:00Z",
59
- }),
60
- {
61
- status: 200,
62
- headers: {
63
- "Content-Type": "application/json",
64
- },
65
- },
66
- );
67
- };
68
-
69
- try {
70
- const backend = new ServerBackend("https://api.mem9.ai", "space-key", "agent-1", {
71
- provisionQueryParams: {
72
- utm_source: "bosn",
73
- },
74
- });
75
-
76
- await backend.store({ content: "remember this" });
77
-
78
- assert.equal(requestedURL, "https://api.mem9.ai/v1alpha2/mem9s/memories");
79
- } finally {
80
- globalThis.fetch = originalFetch;
81
- }
82
- });
package/server-backend.ts DELETED
@@ -1,194 +0,0 @@
1
- import type { MemoryBackend } from "./backend.js";
2
- import type {
3
- Memory,
4
- StoreResult,
5
- SearchResult,
6
- CreateMemoryInput,
7
- UpdateMemoryInput,
8
- SearchInput,
9
- IngestInput,
10
- IngestResult,
11
- } from "./types.js";
12
-
13
- type ProvisionMem9sResponse = {
14
- id: string;
15
- };
16
-
17
- export const DEFAULT_TIMEOUT_MS = 8_000;
18
- export const DEFAULT_SEARCH_TIMEOUT_MS = 15_000;
19
-
20
- export interface BackendTimeouts {
21
- defaultTimeoutMs?: number;
22
- searchTimeoutMs?: number;
23
- }
24
-
25
- interface ServerBackendOptions {
26
- timeouts?: BackendTimeouts;
27
- provisionQueryParams?: Record<string, string>;
28
- }
29
-
30
- interface RequestOptions {
31
- timeoutMs?: number;
32
- }
33
-
34
- export class ServerBackend implements MemoryBackend {
35
- private baseUrl: string;
36
- private apiKey: string;
37
- private agentName: string;
38
- private provisionQueryParams: Record<string, string>;
39
- private timeouts: Required<BackendTimeouts>;
40
-
41
- constructor(
42
- apiUrl: string,
43
- apiKey: string,
44
- agentName: string,
45
- options: ServerBackendOptions = {},
46
- ) {
47
- this.baseUrl = apiUrl.replace(/\/+$/, "");
48
- this.apiKey = apiKey;
49
- this.agentName = agentName;
50
- this.provisionQueryParams = options.provisionQueryParams ?? {};
51
- this.timeouts = {
52
- defaultTimeoutMs: options.timeouts?.defaultTimeoutMs ?? DEFAULT_TIMEOUT_MS,
53
- searchTimeoutMs: options.timeouts?.searchTimeoutMs ?? DEFAULT_SEARCH_TIMEOUT_MS,
54
- };
55
- }
56
-
57
- async register(): Promise<ProvisionMem9sResponse> {
58
- const query = new URLSearchParams();
59
- for (const [key, value] of Object.entries(this.provisionQueryParams)) {
60
- if (!key.startsWith("utm_") || typeof value !== "string" || value === "") {
61
- continue;
62
- }
63
-
64
- query.set(key, value);
65
- }
66
-
67
- const qs = query.toString();
68
- const resp = await fetch(this.baseUrl + "/v1alpha1/mem9s" + (qs ? `?${qs}` : ""), {
69
- method: "POST",
70
- signal: AbortSignal.timeout(this.timeouts.defaultTimeoutMs),
71
- });
72
-
73
- if (!resp.ok) {
74
- const body = await resp.text();
75
- throw new Error(`mem9s provision failed (${resp.status}): ${body}`);
76
- }
77
-
78
- const data = (await resp.json()) as ProvisionMem9sResponse;
79
- if (!data?.id) {
80
- throw new Error("mem9s provision did not return API key");
81
- }
82
-
83
- this.apiKey = data.id;
84
- return data;
85
- }
86
-
87
- private memoryPath(path: string): string {
88
- if (!this.apiKey) {
89
- throw new Error("API key is not configured");
90
- }
91
- return `/v1alpha2/mem9s${path}`;
92
- }
93
-
94
- async store(input: CreateMemoryInput): Promise<StoreResult> {
95
- return this.request<StoreResult>("POST", this.memoryPath("/memories"), input);
96
- }
97
-
98
- async search(input: SearchInput): Promise<SearchResult> {
99
- const params = new URLSearchParams();
100
- if (input.q) params.set("q", input.q);
101
- if (input.tags) params.set("tags", input.tags);
102
- if (input.source) params.set("source", input.source);
103
- if (input.limit != null) params.set("limit", String(input.limit));
104
- if (input.offset != null) params.set("offset", String(input.offset));
105
- if (input.memory_type) params.set("memory_type", input.memory_type);
106
-
107
- const qs = params.toString();
108
- const raw = await this.request<{
109
- memories: Memory[];
110
- total: number;
111
- limit: number;
112
- offset: number;
113
- }>(
114
- "GET",
115
- `${this.memoryPath("/memories")}${qs ? "?" + qs : ""}`,
116
- undefined,
117
- { timeoutMs: this.timeouts.searchTimeoutMs },
118
- );
119
- return {
120
- data: raw.memories ?? [],
121
- total: raw.total,
122
- limit: raw.limit,
123
- offset: raw.offset,
124
- };
125
- }
126
-
127
- async get(id: string): Promise<Memory | null> {
128
- try {
129
- return await this.request<Memory>("GET", this.memoryPath(`/memories/${id}`));
130
- } catch {
131
- return null;
132
- }
133
- }
134
-
135
- async update(id: string, input: UpdateMemoryInput): Promise<Memory | null> {
136
- try {
137
- return await this.request<Memory>("PUT", this.memoryPath(`/memories/${id}`), input);
138
- } catch {
139
- return null;
140
- }
141
- }
142
-
143
- async remove(id: string): Promise<boolean> {
144
- try {
145
- await this.request("DELETE", this.memoryPath(`/memories/${id}`));
146
- return true;
147
- } catch {
148
- return false;
149
- }
150
- }
151
-
152
- async ingest(input: IngestInput): Promise<IngestResult> {
153
- return this.request<IngestResult>("POST", this.memoryPath("/memories"), input);
154
- }
155
-
156
- private async requestRaw(
157
- method: string,
158
- path: string,
159
- body?: unknown,
160
- options?: RequestOptions,
161
- ): Promise<Response> {
162
- const url = this.baseUrl + path;
163
- const headers: Record<string, string> = {
164
- "Content-Type": "application/json",
165
- "X-Mnemo-Agent-Id": this.agentName,
166
- "X-API-Key": this.apiKey,
167
- };
168
- return fetch(url, {
169
- method,
170
- headers,
171
- body: body != null ? JSON.stringify(body) : undefined,
172
- signal: AbortSignal.timeout(options?.timeoutMs ?? this.timeouts.defaultTimeoutMs),
173
- });
174
- }
175
-
176
- private async request<T>(
177
- method: string,
178
- path: string,
179
- body?: unknown,
180
- options?: RequestOptions,
181
- ): Promise<T> {
182
- const resp = await this.requestRaw(method, path, body, options);
183
-
184
- if (resp.status === 204) {
185
- return undefined as T;
186
- }
187
-
188
- const data = await resp.json();
189
- if (!resp.ok) {
190
- throw new Error((data as { error?: string }).error || `HTTP ${resp.status}`);
191
- }
192
- return data as T;
193
- }
194
- }
package/types.ts DELETED
@@ -1,96 +0,0 @@
1
- export interface PluginConfig {
2
- // Server mode (apiUrl present → server)
3
- apiUrl?: string;
4
- apiKey?: string;
5
- provisionToken?: string;
6
- provisionQueryParams?: Record<string, string>;
7
- tenantID?: string;
8
- defaultTimeoutMs?: number;
9
- searchTimeoutMs?: number;
10
- debug?: boolean;
11
- // Deprecated: use debug
12
- debugRecall?: boolean;
13
-
14
- tenantName?: string;
15
-
16
- // Agent identity for server mode.
17
- // Defaults to "agent" if not set. Overridden by ctx.agentId at runtime.
18
- agentName?: string;
19
-
20
- // Ingest: size-aware message selection for smart pipeline
21
- maxIngestBytes?: number;
22
- }
23
-
24
- export interface Memory {
25
- id: string;
26
- content: string;
27
- source?: string | null;
28
- tags?: string[] | null;
29
- metadata?: Record<string, unknown> | null;
30
- version?: number;
31
- updated_by?: string | null;
32
- created_at: string;
33
- updated_at: string;
34
- score?: number;
35
- confidence?: number;
36
-
37
- // Smart memory pipeline (server mode)
38
- memory_type?: string;
39
- state?: string;
40
- agent_id?: string;
41
- session_id?: string;
42
-
43
- relative_age?: string;
44
- }
45
-
46
- export interface SearchResult {
47
- data: Memory[];
48
- total: number;
49
- limit: number;
50
- offset: number;
51
- }
52
-
53
- export interface CreateMemoryInput {
54
- content: string;
55
- source?: string;
56
- tags?: string[];
57
- metadata?: Record<string, unknown>;
58
- }
59
-
60
- export interface UpdateMemoryInput {
61
- content?: string;
62
- source?: string;
63
- tags?: string[];
64
- metadata?: Record<string, unknown>;
65
- }
66
-
67
- export interface SearchInput {
68
- q?: string;
69
- tags?: string;
70
- source?: string;
71
- limit?: number;
72
- offset?: number;
73
- memory_type?: string;
74
- }
75
-
76
- export interface IngestMessage {
77
- role: string;
78
- content: string;
79
- }
80
-
81
- export interface IngestInput {
82
- messages: IngestMessage[];
83
- session_id: string;
84
- agent_id: string;
85
- mode?: "smart" | "raw";
86
- }
87
-
88
- export interface IngestResult {
89
- status: "accepted" | "complete" | "partial" | "failed";
90
- memories_changed?: number;
91
- insight_ids?: string[];
92
- warnings?: number;
93
- error?: string;
94
- }
95
-
96
- export type StoreResult = Memory | IngestResult;