opencode-graphiti 0.1.10 → 0.1.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/esm/_dnt.polyfills.d.ts +99 -0
  2. package/esm/_dnt.polyfills.d.ts.map +1 -1
  3. package/esm/_dnt.polyfills.js +127 -1
  4. package/esm/_dnt.shims.d.ts +6 -0
  5. package/esm/_dnt.shims.d.ts.map +1 -0
  6. package/esm/_dnt.shims.js +61 -0
  7. package/esm/src/config.d.ts +14 -7
  8. package/esm/src/config.d.ts.map +1 -1
  9. package/esm/src/config.js +103 -30
  10. package/esm/src/index.d.ts.map +1 -1
  11. package/esm/src/index.js +12 -6
  12. package/esm/src/services/client.d.ts +15 -30
  13. package/esm/src/services/client.d.ts.map +1 -1
  14. package/esm/src/services/client.js +86 -126
  15. package/esm/src/services/connection-manager.d.ts +97 -0
  16. package/esm/src/services/connection-manager.d.ts.map +1 -0
  17. package/esm/src/services/connection-manager.js +535 -0
  18. package/esm/src/services/logger.d.ts +2 -0
  19. package/esm/src/services/logger.d.ts.map +1 -1
  20. package/esm/src/services/logger.js +29 -3
  21. package/esm/src/utils.d.ts.map +1 -1
  22. package/esm/src/utils.js +10 -2
  23. package/package.json +2 -2
  24. package/script/_dnt.polyfills.d.ts +99 -0
  25. package/script/_dnt.polyfills.d.ts.map +1 -1
  26. package/script/_dnt.polyfills.js +128 -0
  27. package/script/_dnt.shims.d.ts +6 -0
  28. package/script/_dnt.shims.d.ts.map +1 -0
  29. package/script/_dnt.shims.js +65 -0
  30. package/script/src/config.d.ts +14 -7
  31. package/script/src/config.d.ts.map +1 -1
  32. package/script/src/config.js +106 -63
  33. package/script/src/index.d.ts.map +1 -1
  34. package/script/src/index.js +12 -6
  35. package/script/src/services/client.d.ts +15 -30
  36. package/script/src/services/client.d.ts.map +1 -1
  37. package/script/src/services/client.js +86 -129
  38. package/script/src/services/connection-manager.d.ts +97 -0
  39. package/script/src/services/connection-manager.d.ts.map +1 -0
  40. package/script/src/services/connection-manager.js +549 -0
  41. package/script/src/services/logger.d.ts +2 -0
  42. package/script/src/services/logger.d.ts.map +1 -1
  43. package/script/src/services/logger.js +65 -7
  44. package/script/src/utils.d.ts.map +1 -1
  45. package/script/src/utils.js +10 -2
@@ -1,132 +1,38 @@
1
- import { Client } from "@modelcontextprotocol/sdk/client/index.js";
2
- import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
3
- import manifest from "../../deno.js";
1
+ import { GraphitiConnectionManager, GraphitiSessionExpiredError, GraphitiTransportError, isGraphitiOfflineError, isGraphitiTimeoutError, } from "./connection-manager.js";
4
2
  import { logger } from "./logger.js";
5
3
  import { normalizeEpisode } from "./sdk-normalize.js";
6
4
  /**
7
- * Graphiti MCP client wrapper for connecting, querying,
8
- * and persisting episodes with basic reconnection handling.
5
+ * Graphiti domain adapter over the connection manager.
9
6
  */
10
7
  export class GraphitiClient {
11
- /**
12
- * Create a Graphiti client bound to the given MCP endpoint URL.
13
- */
14
- constructor(endpoint) {
15
- Object.defineProperty(this, "client", {
16
- enumerable: true,
17
- configurable: true,
18
- writable: true,
19
- value: void 0
20
- });
21
- Object.defineProperty(this, "transport", {
8
+ constructor(endpointOrManager) {
9
+ Object.defineProperty(this, "toolCaller", {
22
10
  enumerable: true,
23
11
  configurable: true,
24
12
  writable: true,
25
13
  value: void 0
26
14
  });
27
- Object.defineProperty(this, "connected", {
28
- enumerable: true,
29
- configurable: true,
30
- writable: true,
31
- value: false
32
- });
33
- Object.defineProperty(this, "endpoint", {
34
- enumerable: true,
35
- configurable: true,
36
- writable: true,
37
- value: void 0
38
- });
39
- this.endpoint = endpoint;
40
- this.client = new Client({
41
- name: manifest.name,
42
- version: manifest.version,
43
- });
44
- this.transport = new StreamableHTTPClientTransport(new URL(endpoint));
45
- }
46
- /** Create a fresh MCP Client and Transport pair. */
47
- createClientAndTransport() {
48
- this.client = new Client({
49
- name: manifest.name,
50
- version: manifest.version,
51
- });
52
- this.transport = new StreamableHTTPClientTransport(new URL(this.endpoint));
53
- }
54
- /**
55
- * Establish a connection to the Graphiti MCP server.
56
- * Creates a fresh Client/Transport if a previous attempt failed.
57
- */
58
- async connect() {
59
- if (this.connected)
60
- return true;
61
- // If a previous connect() tainted the Client's internal state,
62
- // create fresh instances so the retry starts cleanly.
63
- this.createClientAndTransport();
64
- try {
65
- await this.client.connect(this.transport);
66
- this.connected = true;
67
- logger.info("Connected to Graphiti MCP server at", this.endpoint);
68
- return true;
15
+ if (typeof endpointOrManager === "string") {
16
+ this.toolCaller = new GraphitiConnectionManager({
17
+ endpoint: endpointOrManager,
18
+ });
69
19
  }
70
- catch (err) {
71
- logger.error("Failed to connect to Graphiti:", err);
72
- return false;
20
+ else {
21
+ this.toolCaller = endpointOrManager;
73
22
  }
74
23
  }
75
- /**
76
- * Close the underlying MCP client connection.
77
- */
78
- async disconnect() {
79
- if (this.connected) {
80
- await this.client.close();
81
- this.connected = false;
82
- }
24
+ start() {
25
+ this.toolCaller.start();
83
26
  }
84
- async callTool(name, args) {
85
- if (!this.connected) {
86
- const ok = await this.connect();
87
- if (!ok)
88
- throw new Error("Not connected to Graphiti");
89
- }
90
- // Sanitize arguments: omit task_id (and others) if null or undefined
91
- const sanitizedArgs = Object.fromEntries(Object.entries(args).filter(([_, v]) => v !== null && v !== undefined));
92
- try {
93
- const result = await this.client.callTool({
94
- name,
95
- arguments: sanitizedArgs,
96
- });
97
- return this.parseToolResult(result);
98
- }
99
- catch (err) {
100
- if (this.isSessionExpired(err)) {
101
- logger.warn("Graphiti session expired, reconnecting...");
102
- await this.reconnect();
103
- const result = await this.client.callTool({
104
- name,
105
- arguments: sanitizedArgs,
106
- });
107
- return this.parseToolResult(result);
108
- }
109
- throw err;
110
- }
27
+ async stop() {
28
+ await this.toolCaller.stop();
111
29
  }
112
- isSessionExpired(err) {
113
- return !!(err &&
114
- typeof err === "object" &&
115
- "code" in err &&
116
- err.code === 404);
30
+ async connect() {
31
+ this.toolCaller.start();
32
+ return await this.toolCaller.ready();
117
33
  }
118
- async reconnect() {
119
- this.connected = false;
120
- try {
121
- await this.client.close();
122
- }
123
- catch {
124
- // ignore close errors on stale client
125
- }
126
- this.createClientAndTransport();
127
- await this.client.connect(this.transport);
128
- this.connected = true;
129
- logger.info("Reconnected to Graphiti MCP server");
34
+ async ready(timeoutMs) {
35
+ return await this.toolCaller.ready(timeoutMs);
130
36
  }
131
37
  /**
132
38
  * Parse MCP tool results into JSON when possible.
@@ -155,19 +61,6 @@ export class GraphitiClient {
155
61
  return text;
156
62
  }
157
63
  }
158
- /**
159
- * Add an episode to Graphiti memory.
160
- */
161
- async addEpisode(params) {
162
- await this.callTool("add_memory", {
163
- name: params.name,
164
- episode_body: params.episodeBody,
165
- group_id: params.groupId,
166
- source: params.source || "text",
167
- source_description: params.sourceDescription || "",
168
- });
169
- logger.debug("Added episode:", params.name);
170
- }
171
64
  /**
172
65
  * Extract an array from a tool result that may be a bare array or a
173
66
  * wrapped-array response object (`{ [key]: T[] }`).
@@ -184,6 +77,30 @@ export class GraphitiClient {
184
77
  }
185
78
  return null;
186
79
  }
80
+ /**
81
+ * Add an episode to Graphiti memory.
82
+ */
83
+ async addEpisode(params) {
84
+ try {
85
+ await this.callTool("add_memory", {
86
+ name: params.name,
87
+ episode_body: params.episodeBody,
88
+ group_id: params.groupId,
89
+ source: params.source || "text",
90
+ source_description: params.sourceDescription || "",
91
+ });
92
+ logger.debug("Added episode:", params.name);
93
+ }
94
+ catch (err) {
95
+ if (isGraphitiOfflineError(err) ||
96
+ isGraphitiTimeoutError(err) ||
97
+ err instanceof GraphitiTransportError ||
98
+ err instanceof GraphitiSessionExpiredError) {
99
+ logger.warn("addEpisode failed due to Graphiti availability issue", err);
100
+ }
101
+ throw err;
102
+ }
103
+ }
187
104
  /**
188
105
  * Search Graphiti facts matching the provided query.
189
106
  */
@@ -197,6 +114,19 @@ export class GraphitiClient {
197
114
  return this.parseWrappedArray(result, "facts") ?? [];
198
115
  }
199
116
  catch (err) {
117
+ if (isGraphitiTimeoutError(err)) {
118
+ logger.warn("searchFacts request timed out; returning no facts");
119
+ return [];
120
+ }
121
+ if (isGraphitiOfflineError(err)) {
122
+ logger.warn("searchFacts unavailable; returning no facts");
123
+ return [];
124
+ }
125
+ if (err instanceof GraphitiTransportError ||
126
+ err instanceof GraphitiSessionExpiredError) {
127
+ logger.warn("searchFacts unavailable during reconnect; returning no facts");
128
+ return [];
129
+ }
200
130
  logger.error("searchFacts error:", err);
201
131
  return [];
202
132
  }
@@ -214,6 +144,19 @@ export class GraphitiClient {
214
144
  return this.parseWrappedArray(result, "nodes") ?? [];
215
145
  }
216
146
  catch (err) {
147
+ if (isGraphitiTimeoutError(err)) {
148
+ logger.warn("searchNodes request timed out; returning no nodes");
149
+ return [];
150
+ }
151
+ if (isGraphitiOfflineError(err)) {
152
+ logger.warn("searchNodes unavailable; returning no nodes");
153
+ return [];
154
+ }
155
+ if (err instanceof GraphitiTransportError ||
156
+ err instanceof GraphitiSessionExpiredError) {
157
+ logger.warn("searchNodes unavailable during reconnect; returning no nodes");
158
+ return [];
159
+ }
217
160
  logger.error("searchNodes error:", err);
218
161
  return [];
219
162
  }
@@ -232,6 +175,19 @@ export class GraphitiClient {
232
175
  return raw.map(normalizeEpisode);
233
176
  }
234
177
  catch (err) {
178
+ if (isGraphitiTimeoutError(err)) {
179
+ logger.warn("getEpisodes request timed out; returning no episodes");
180
+ return [];
181
+ }
182
+ if (isGraphitiOfflineError(err)) {
183
+ logger.warn("getEpisodes unavailable; returning no episodes");
184
+ return [];
185
+ }
186
+ if (err instanceof GraphitiTransportError ||
187
+ err instanceof GraphitiSessionExpiredError) {
188
+ logger.warn("getEpisodes unavailable during reconnect; returning no episodes");
189
+ return [];
190
+ }
235
191
  logger.error("getEpisodes error:", err);
236
192
  return [];
237
193
  }
@@ -248,4 +204,8 @@ export class GraphitiClient {
248
204
  return false;
249
205
  }
250
206
  }
207
+ async callTool(name, args) {
208
+ const result = await this.toolCaller.callTool(name, args);
209
+ return this.parseToolResult(result);
210
+ }
251
211
  }
@@ -0,0 +1,97 @@
1
+ export type GraphitiConnectionState = "connecting" | "connected" | "offline" | "closing";
2
+ type TimerHandle = ReturnType<typeof setTimeout> | number;
3
+ export declare class GraphitiOfflineError extends Error {
4
+ readonly state: "offline" | "closing";
5
+ readonly kind = "offline";
6
+ constructor(state: "offline" | "closing", message?: string);
7
+ }
8
+ export declare class GraphitiQueueTimeoutError extends Error {
9
+ readonly kind = "queue-timeout";
10
+ constructor(message?: string);
11
+ }
12
+ export declare class GraphitiRequestTimeoutError extends Error {
13
+ readonly kind = "request-timeout";
14
+ constructor(message?: string);
15
+ }
16
+ export declare class GraphitiTransportError extends Error {
17
+ readonly kind = "transport-failure";
18
+ constructor(message?: string);
19
+ }
20
+ export declare class GraphitiSessionExpiredError extends Error {
21
+ readonly kind = "session-expired";
22
+ constructor(message?: string);
23
+ }
24
+ export declare function isGraphitiOfflineError(err: unknown): err is GraphitiOfflineError;
25
+ export declare function isGraphitiTimeoutError(err: unknown): err is GraphitiQueueTimeoutError | GraphitiRequestTimeoutError;
26
+ export type GraphitiToolRequest = {
27
+ name: string;
28
+ arguments?: Record<string, unknown>;
29
+ };
30
+ export interface GraphitiConnection {
31
+ connect(): Promise<void>;
32
+ close(): Promise<void>;
33
+ callTool(request: GraphitiToolRequest): Promise<unknown>;
34
+ }
35
+ export interface GraphitiToolCaller {
36
+ start(): void;
37
+ stop(): Promise<void>;
38
+ ready(timeoutMs?: number): Promise<boolean>;
39
+ callTool(name: string, args: Record<string, unknown>, deadlineMs?: number): Promise<unknown>;
40
+ }
41
+ type ConnectionFactory = (endpoint: string) => GraphitiConnection;
42
+ type GraphitiConnectionManagerOptions = {
43
+ endpoint: string;
44
+ requestDeadlineMs?: number;
45
+ queueCapacity?: number;
46
+ startupTimeoutMs?: number;
47
+ reconnectInitialDelayMs?: number;
48
+ reconnectMaxDelayMs?: number;
49
+ reconnectMultiplier?: number;
50
+ reconnectJitter?: number;
51
+ connectionFactory?: ConnectionFactory;
52
+ random?: () => number;
53
+ setTimer?: (callback: () => void, delayMs: number) => TimerHandle;
54
+ clearTimer?: (timer: TimerHandle) => void;
55
+ };
56
+ export declare class GraphitiConnectionManager implements GraphitiToolCaller {
57
+ private readonly endpoint;
58
+ private readonly requestDeadlineMs;
59
+ private readonly queueCapacity;
60
+ private readonly startupTimeoutMs;
61
+ private readonly reconnectInitialDelayMs;
62
+ private readonly reconnectMaxDelayMs;
63
+ private readonly reconnectMultiplier;
64
+ private readonly reconnectJitter;
65
+ private readonly connectionFactory;
66
+ private readonly random;
67
+ private readonly setTimerImpl;
68
+ private readonly clearTimerImpl;
69
+ private state;
70
+ private connection;
71
+ private connectPromise;
72
+ private reconnectTimer;
73
+ private pendingRequests;
74
+ private readyWaiters;
75
+ private reconnectDelayMs;
76
+ private started;
77
+ private flushingQueue;
78
+ constructor(options: GraphitiConnectionManagerOptions);
79
+ getState(): GraphitiConnectionState;
80
+ start(): void;
81
+ stop(): Promise<void>;
82
+ ready(timeoutMs?: number): Promise<boolean>;
83
+ callTool(name: string, args: Record<string, unknown>, deadlineMs?: number): Promise<unknown>;
84
+ reconnect(): Promise<boolean>;
85
+ private performReconnect;
86
+ private executeConnectedCall;
87
+ private enqueueRequest;
88
+ private flushPendingQueue;
89
+ private removePendingRequest;
90
+ private clearPendingTimer;
91
+ private rejectAllPending;
92
+ private scheduleReconnect;
93
+ private cancelReconnectTimer;
94
+ private resolveReadyWaiters;
95
+ }
96
+ export {};
97
+ //# sourceMappingURL=connection-manager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"connection-manager.d.ts","sourceRoot":"","sources":["../../../src/src/services/connection-manager.ts"],"names":[],"mappings":"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"}