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
@@ -0,0 +1,535 @@
1
+ import { Client } from "@modelcontextprotocol/sdk/client/index.js";
2
+ import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
3
+ import manifest from "../../deno.js";
4
+ import { logger } from "./logger.js";
5
+ export class GraphitiOfflineError extends Error {
6
+ constructor(state, message) {
7
+ super(message ??
8
+ (state === "closing"
9
+ ? "Graphiti connection manager is closing"
10
+ : "Graphiti connection manager is offline"));
11
+ Object.defineProperty(this, "state", {
12
+ enumerable: true,
13
+ configurable: true,
14
+ writable: true,
15
+ value: state
16
+ });
17
+ Object.defineProperty(this, "kind", {
18
+ enumerable: true,
19
+ configurable: true,
20
+ writable: true,
21
+ value: "offline"
22
+ });
23
+ this.name = "GraphitiOfflineError";
24
+ }
25
+ }
26
+ export class GraphitiQueueTimeoutError extends Error {
27
+ constructor(message = "Graphiti request timed out while waiting for connection") {
28
+ super(message);
29
+ Object.defineProperty(this, "kind", {
30
+ enumerable: true,
31
+ configurable: true,
32
+ writable: true,
33
+ value: "queue-timeout"
34
+ });
35
+ this.name = "GraphitiQueueTimeoutError";
36
+ }
37
+ }
38
+ export class GraphitiRequestTimeoutError extends Error {
39
+ constructor(message = "Graphiti request timed out") {
40
+ super(message);
41
+ Object.defineProperty(this, "kind", {
42
+ enumerable: true,
43
+ configurable: true,
44
+ writable: true,
45
+ value: "request-timeout"
46
+ });
47
+ this.name = "GraphitiRequestTimeoutError";
48
+ }
49
+ }
50
+ export class GraphitiTransportError extends Error {
51
+ constructor(message = "Graphiti transport failure") {
52
+ super(message);
53
+ Object.defineProperty(this, "kind", {
54
+ enumerable: true,
55
+ configurable: true,
56
+ writable: true,
57
+ value: "transport-failure"
58
+ });
59
+ this.name = "GraphitiTransportError";
60
+ }
61
+ }
62
+ export class GraphitiSessionExpiredError extends Error {
63
+ constructor(message = "Graphiti session expired") {
64
+ super(message);
65
+ Object.defineProperty(this, "kind", {
66
+ enumerable: true,
67
+ configurable: true,
68
+ writable: true,
69
+ value: "session-expired"
70
+ });
71
+ this.name = "GraphitiSessionExpiredError";
72
+ }
73
+ }
74
+ export function isGraphitiOfflineError(err) {
75
+ return err instanceof GraphitiOfflineError;
76
+ }
77
+ export function isGraphitiTimeoutError(err) {
78
+ return err instanceof GraphitiQueueTimeoutError ||
79
+ err instanceof GraphitiRequestTimeoutError;
80
+ }
81
+ function createMcpConnection(endpoint) {
82
+ const client = new Client({
83
+ name: manifest.name,
84
+ version: manifest.version,
85
+ });
86
+ const transport = new StreamableHTTPClientTransport(new URL(endpoint));
87
+ return {
88
+ connect: () => client.connect(transport),
89
+ close: () => client.close(),
90
+ callTool: (request) => client.callTool(request),
91
+ };
92
+ }
93
+ function getErrorMessage(err) {
94
+ if (typeof err === "string")
95
+ return err;
96
+ if (!err || typeof err !== "object")
97
+ return "";
98
+ const { message, cause } = err;
99
+ if (typeof message === "string")
100
+ return message;
101
+ if (cause)
102
+ return getErrorMessage(cause);
103
+ return "";
104
+ }
105
+ function isRequestTimeout(err) {
106
+ if (!err || typeof err !== "object") {
107
+ return typeof err === "string" && /request timed out/i.test(err);
108
+ }
109
+ const { code } = err;
110
+ return code === -32001 || /request timed out/i.test(getErrorMessage(err));
111
+ }
112
+ function isSessionExpired(err) {
113
+ return !!(err &&
114
+ typeof err === "object" &&
115
+ "code" in err &&
116
+ err.code === 404);
117
+ }
118
+ function isTransportFailure(err) {
119
+ if (!err)
120
+ return false;
121
+ if (isRequestTimeout(err) || isSessionExpired(err))
122
+ return false;
123
+ const message = getErrorMessage(err);
124
+ if (/(socket hang up|fetch failed|network|connection reset|connection refused|econnrefused|terminated|broken pipe|stream closed|unexpected end|transport)/i
125
+ .test(message)) {
126
+ return true;
127
+ }
128
+ if (typeof err === "object") {
129
+ const { name } = err;
130
+ return name === "TypeError" && message.length > 0;
131
+ }
132
+ return false;
133
+ }
134
+ export class GraphitiConnectionManager {
135
+ constructor(options) {
136
+ Object.defineProperty(this, "endpoint", {
137
+ enumerable: true,
138
+ configurable: true,
139
+ writable: true,
140
+ value: void 0
141
+ });
142
+ Object.defineProperty(this, "requestDeadlineMs", {
143
+ enumerable: true,
144
+ configurable: true,
145
+ writable: true,
146
+ value: void 0
147
+ });
148
+ Object.defineProperty(this, "queueCapacity", {
149
+ enumerable: true,
150
+ configurable: true,
151
+ writable: true,
152
+ value: void 0
153
+ });
154
+ Object.defineProperty(this, "startupTimeoutMs", {
155
+ enumerable: true,
156
+ configurable: true,
157
+ writable: true,
158
+ value: void 0
159
+ });
160
+ Object.defineProperty(this, "reconnectInitialDelayMs", {
161
+ enumerable: true,
162
+ configurable: true,
163
+ writable: true,
164
+ value: void 0
165
+ });
166
+ Object.defineProperty(this, "reconnectMaxDelayMs", {
167
+ enumerable: true,
168
+ configurable: true,
169
+ writable: true,
170
+ value: void 0
171
+ });
172
+ Object.defineProperty(this, "reconnectMultiplier", {
173
+ enumerable: true,
174
+ configurable: true,
175
+ writable: true,
176
+ value: void 0
177
+ });
178
+ Object.defineProperty(this, "reconnectJitter", {
179
+ enumerable: true,
180
+ configurable: true,
181
+ writable: true,
182
+ value: void 0
183
+ });
184
+ Object.defineProperty(this, "connectionFactory", {
185
+ enumerable: true,
186
+ configurable: true,
187
+ writable: true,
188
+ value: void 0
189
+ });
190
+ Object.defineProperty(this, "random", {
191
+ enumerable: true,
192
+ configurable: true,
193
+ writable: true,
194
+ value: void 0
195
+ });
196
+ Object.defineProperty(this, "setTimerImpl", {
197
+ enumerable: true,
198
+ configurable: true,
199
+ writable: true,
200
+ value: void 0
201
+ });
202
+ Object.defineProperty(this, "clearTimerImpl", {
203
+ enumerable: true,
204
+ configurable: true,
205
+ writable: true,
206
+ value: void 0
207
+ });
208
+ Object.defineProperty(this, "state", {
209
+ enumerable: true,
210
+ configurable: true,
211
+ writable: true,
212
+ value: "offline"
213
+ });
214
+ Object.defineProperty(this, "connection", {
215
+ enumerable: true,
216
+ configurable: true,
217
+ writable: true,
218
+ value: null
219
+ });
220
+ Object.defineProperty(this, "connectPromise", {
221
+ enumerable: true,
222
+ configurable: true,
223
+ writable: true,
224
+ value: null
225
+ });
226
+ Object.defineProperty(this, "reconnectTimer", {
227
+ enumerable: true,
228
+ configurable: true,
229
+ writable: true,
230
+ value: null
231
+ });
232
+ Object.defineProperty(this, "pendingRequests", {
233
+ enumerable: true,
234
+ configurable: true,
235
+ writable: true,
236
+ value: []
237
+ });
238
+ Object.defineProperty(this, "readyWaiters", {
239
+ enumerable: true,
240
+ configurable: true,
241
+ writable: true,
242
+ value: new Set()
243
+ });
244
+ Object.defineProperty(this, "reconnectDelayMs", {
245
+ enumerable: true,
246
+ configurable: true,
247
+ writable: true,
248
+ value: void 0
249
+ });
250
+ Object.defineProperty(this, "started", {
251
+ enumerable: true,
252
+ configurable: true,
253
+ writable: true,
254
+ value: false
255
+ });
256
+ Object.defineProperty(this, "flushingQueue", {
257
+ enumerable: true,
258
+ configurable: true,
259
+ writable: true,
260
+ value: false
261
+ });
262
+ this.endpoint = options.endpoint;
263
+ this.requestDeadlineMs = options.requestDeadlineMs ?? 15_000;
264
+ this.queueCapacity = options.queueCapacity ?? 32;
265
+ this.startupTimeoutMs = options.startupTimeoutMs ?? this.requestDeadlineMs;
266
+ this.reconnectInitialDelayMs = options.reconnectInitialDelayMs ?? 1_000;
267
+ this.reconnectMaxDelayMs = options.reconnectMaxDelayMs ?? 60_000;
268
+ this.reconnectMultiplier = options.reconnectMultiplier ?? 2;
269
+ this.reconnectJitter = options.reconnectJitter ?? 0.25;
270
+ this.connectionFactory = options.connectionFactory ?? createMcpConnection;
271
+ this.random = options.random ?? Math.random;
272
+ this.setTimerImpl = options.setTimer ??
273
+ ((callback, delayMs) => setTimeout(callback, delayMs));
274
+ this.clearTimerImpl = options.clearTimer ??
275
+ ((timer) => clearTimeout(timer));
276
+ this.reconnectDelayMs = this.reconnectInitialDelayMs;
277
+ }
278
+ getState() {
279
+ return this.state;
280
+ }
281
+ start() {
282
+ if (this.started || this.state === "closing")
283
+ return;
284
+ this.started = true;
285
+ void this.reconnect();
286
+ }
287
+ async stop() {
288
+ if (this.state === "closing")
289
+ return;
290
+ this.started = false;
291
+ this.state = "closing";
292
+ this.cancelReconnectTimer();
293
+ this.rejectAllPending(new GraphitiOfflineError("closing", "Graphiti connection manager stopped"));
294
+ this.resolveReadyWaiters(false);
295
+ const connection = this.connection;
296
+ this.connection = null;
297
+ if (connection) {
298
+ try {
299
+ await connection.close();
300
+ }
301
+ catch {
302
+ // Ignore close errors while shutting down.
303
+ }
304
+ }
305
+ }
306
+ async ready(timeoutMs = this.startupTimeoutMs) {
307
+ if (this.state === "connected")
308
+ return true;
309
+ if (this.state === "closing")
310
+ return false;
311
+ return await new Promise((resolve) => {
312
+ let settled = false;
313
+ let timer = null;
314
+ const finish = (value) => {
315
+ if (settled)
316
+ return;
317
+ settled = true;
318
+ if (timer !== null)
319
+ this.clearTimerImpl(timer);
320
+ this.readyWaiters.delete(finish);
321
+ resolve(value);
322
+ };
323
+ this.readyWaiters.add(finish);
324
+ if (timeoutMs >= 0) {
325
+ timer = this.setTimerImpl(() => finish(false), timeoutMs);
326
+ }
327
+ });
328
+ }
329
+ async callTool(name, args, deadlineMs = this.requestDeadlineMs) {
330
+ const sanitizedArgs = Object.fromEntries(Object.entries(args).filter(([_, value]) => value !== null && value !== undefined));
331
+ if (this.state === "closing") {
332
+ throw new GraphitiOfflineError("closing");
333
+ }
334
+ if (this.state === "offline") {
335
+ throw new GraphitiOfflineError("offline");
336
+ }
337
+ if (this.state === "connecting") {
338
+ return await this.enqueueRequest(name, sanitizedArgs, deadlineMs);
339
+ }
340
+ return await this.executeConnectedCall(name, sanitizedArgs);
341
+ }
342
+ async reconnect() {
343
+ if (this.state === "closing")
344
+ return false;
345
+ if (this.connectPromise)
346
+ return await this.connectPromise;
347
+ this.cancelReconnectTimer();
348
+ this.state = "connecting";
349
+ const attempt = this.performReconnect();
350
+ this.connectPromise = attempt.finally(() => {
351
+ this.connectPromise = null;
352
+ });
353
+ return await this.connectPromise;
354
+ }
355
+ async performReconnect() {
356
+ const previousConnection = this.connection;
357
+ this.connection = null;
358
+ if (previousConnection) {
359
+ try {
360
+ await previousConnection.close();
361
+ }
362
+ catch {
363
+ // Ignore stale close failures during reconnect.
364
+ }
365
+ }
366
+ const nextConnection = this.connectionFactory(this.endpoint);
367
+ try {
368
+ await nextConnection.connect();
369
+ if (this.state === "closing") {
370
+ try {
371
+ await nextConnection.close();
372
+ }
373
+ catch {
374
+ // Ignore close failures while shutting down.
375
+ }
376
+ return false;
377
+ }
378
+ this.connection = nextConnection;
379
+ this.state = "connected";
380
+ this.reconnectDelayMs = this.reconnectInitialDelayMs;
381
+ this.resolveReadyWaiters(true);
382
+ logger.info("Connected to Graphiti MCP server at", this.endpoint);
383
+ void this.flushPendingQueue();
384
+ return true;
385
+ }
386
+ catch (err) {
387
+ try {
388
+ await nextConnection.close();
389
+ }
390
+ catch {
391
+ // Ignore close failures for failed connects.
392
+ }
393
+ if (this.state !== "closing") {
394
+ this.state = "offline";
395
+ this.rejectAllPending(new GraphitiOfflineError("offline"));
396
+ this.scheduleReconnect();
397
+ logger.warn("Failed to connect to Graphiti MCP server", err);
398
+ }
399
+ return false;
400
+ }
401
+ }
402
+ async executeConnectedCall(name, args, attempt = 0) {
403
+ if (this.state !== "connected" || !this.connection) {
404
+ throw new GraphitiOfflineError("offline");
405
+ }
406
+ try {
407
+ return await this.connection.callTool({ name, arguments: args });
408
+ }
409
+ catch (err) {
410
+ if (isRequestTimeout(err)) {
411
+ throw new GraphitiRequestTimeoutError(getErrorMessage(err) || undefined);
412
+ }
413
+ if (isSessionExpired(err)) {
414
+ const typedError = new GraphitiSessionExpiredError(getErrorMessage(err) || undefined);
415
+ if (attempt >= 1) {
416
+ void this.reconnect();
417
+ throw typedError;
418
+ }
419
+ const connected = await this.reconnect();
420
+ if (!connected)
421
+ throw typedError;
422
+ return await this.executeConnectedCall(name, args, attempt + 1);
423
+ }
424
+ if (isTransportFailure(err)) {
425
+ const typedError = new GraphitiTransportError(getErrorMessage(err) || undefined);
426
+ if (attempt >= 1) {
427
+ void this.reconnect();
428
+ throw typedError;
429
+ }
430
+ const connected = await this.reconnect();
431
+ if (!connected)
432
+ throw typedError;
433
+ return await this.executeConnectedCall(name, args, attempt + 1);
434
+ }
435
+ throw err;
436
+ }
437
+ }
438
+ enqueueRequest(name, args, deadlineMs) {
439
+ if (deadlineMs <= 0) {
440
+ return Promise.reject(new GraphitiQueueTimeoutError());
441
+ }
442
+ return new Promise((resolve, reject) => {
443
+ const pending = {
444
+ name,
445
+ args,
446
+ resolve,
447
+ reject,
448
+ timer: null,
449
+ };
450
+ pending.timer = this.setTimerImpl(() => {
451
+ this.removePendingRequest(pending);
452
+ reject(new GraphitiQueueTimeoutError());
453
+ }, deadlineMs);
454
+ if (this.pendingRequests.length >= this.queueCapacity) {
455
+ const dropped = this.pendingRequests.shift();
456
+ if (dropped) {
457
+ this.clearPendingTimer(dropped);
458
+ dropped.reject(new GraphitiQueueTimeoutError("Graphiti request dropped because the connecting queue is full"));
459
+ }
460
+ }
461
+ this.pendingRequests.push(pending);
462
+ });
463
+ }
464
+ async flushPendingQueue() {
465
+ if (this.flushingQueue || this.state !== "connected")
466
+ return;
467
+ this.flushingQueue = true;
468
+ try {
469
+ while (this.state === "connected" && this.pendingRequests.length > 0) {
470
+ const next = this.pendingRequests.shift();
471
+ if (!next)
472
+ continue;
473
+ this.clearPendingTimer(next);
474
+ try {
475
+ const result = await this.executeConnectedCall(next.name, next.args);
476
+ next.resolve(result);
477
+ }
478
+ catch (err) {
479
+ next.reject(err);
480
+ }
481
+ }
482
+ }
483
+ finally {
484
+ this.flushingQueue = false;
485
+ }
486
+ }
487
+ removePendingRequest(target) {
488
+ const index = this.pendingRequests.indexOf(target);
489
+ if (index >= 0) {
490
+ this.pendingRequests.splice(index, 1);
491
+ }
492
+ this.clearPendingTimer(target);
493
+ }
494
+ clearPendingTimer(request) {
495
+ if (request.timer !== null) {
496
+ this.clearTimerImpl(request.timer);
497
+ request.timer = null;
498
+ }
499
+ }
500
+ rejectAllPending(error) {
501
+ const pending = [...this.pendingRequests];
502
+ this.pendingRequests = [];
503
+ for (const request of pending) {
504
+ this.clearPendingTimer(request);
505
+ request.reject(error);
506
+ }
507
+ }
508
+ scheduleReconnect() {
509
+ if (!this.started || this.state === "closing" || this.reconnectTimer !== null) {
510
+ return;
511
+ }
512
+ const jitterFactor = 1 + ((this.random() * 2) - 1) * this.reconnectJitter;
513
+ const delayMs = Math.max(0, Math.round(this.reconnectDelayMs * jitterFactor));
514
+ this.reconnectTimer = this.setTimerImpl(() => {
515
+ this.reconnectTimer = null;
516
+ if (this.state === "closing")
517
+ return;
518
+ void this.reconnect();
519
+ }, delayMs);
520
+ this.reconnectDelayMs = Math.min(this.reconnectMaxDelayMs, Math.max(this.reconnectInitialDelayMs, Math.round(this.reconnectDelayMs * this.reconnectMultiplier)));
521
+ }
522
+ cancelReconnectTimer() {
523
+ if (this.reconnectTimer !== null) {
524
+ this.clearTimerImpl(this.reconnectTimer);
525
+ this.reconnectTimer = null;
526
+ }
527
+ }
528
+ resolveReadyWaiters(value) {
529
+ const waiters = [...this.readyWaiters];
530
+ this.readyWaiters.clear();
531
+ for (const waiter of waiters) {
532
+ waiter(value);
533
+ }
534
+ }
535
+ }
@@ -1,3 +1,5 @@
1
+ export declare const setLoggerDebugOverride: (value: boolean | undefined) => void;
2
+ export declare const setLoggerSilentOverride: (value: boolean) => void;
1
3
  export declare const logger: {
2
4
  info: (...args: unknown[]) => void;
3
5
  warn: (...args: unknown[]) => void;
@@ -1 +1 @@
1
- {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../../src/src/services/logger.ts"],"names":[],"mappings":"AAUA,eAAO,MAAM,MAAM;oBACD,OAAO,EAAE;oBAGT,OAAO,EAAE;qBAGR,OAAO,EAAE;qBAGT,OAAO,EAAE;CAG3B,CAAC"}
1
+ {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../../src/src/services/logger.ts"],"names":[],"mappings":"AAqBA,eAAO,MAAM,sBAAsB,GAAI,OAAO,OAAO,GAAG,SAAS,KAAG,IAEnE,CAAC;AAEF,eAAO,MAAM,uBAAuB,GAAI,OAAO,OAAO,KAAG,IAExD,CAAC;AAEF,eAAO,MAAM,MAAM;oBACD,OAAO,EAAE;oBAIT,OAAO,EAAE;qBAIR,OAAO,EAAE;qBAIT,OAAO,EAAE;CAI3B,CAAC"}
@@ -1,19 +1,45 @@
1
- import process from "node:process";
1
+ import * as dntShim from "../../_dnt.shims.js";
2
2
  const console = globalThis.console;
3
3
  const PREFIX = "[graphiti]";
4
+ let debugOverride;
5
+ let silentOverride = false;
6
+ const isDebugEnabled = () => {
7
+ if (debugOverride !== undefined)
8
+ return debugOverride;
9
+ try {
10
+ return !!dntShim.Deno.env.get("GRAPHITI_DEBUG");
11
+ }
12
+ catch {
13
+ return false;
14
+ }
15
+ };
16
+ export const setLoggerDebugOverride = (value) => {
17
+ debugOverride = value;
18
+ };
19
+ export const setLoggerSilentOverride = (value) => {
20
+ silentOverride = value;
21
+ };
4
22
  export const logger = {
5
23
  info: (...args) => {
6
- if (process.env.GRAPHITI_DEBUG)
24
+ if (silentOverride)
25
+ return;
26
+ if (isDebugEnabled())
7
27
  console.log(PREFIX, ...args);
8
28
  },
9
29
  warn: (...args) => {
30
+ if (silentOverride)
31
+ return;
10
32
  console.warn(PREFIX, ...args);
11
33
  },
12
34
  error: (...args) => {
35
+ if (silentOverride)
36
+ return;
13
37
  console.error(PREFIX, ...args);
14
38
  },
15
39
  debug: (...args) => {
16
- if (process.env.GRAPHITI_DEBUG)
40
+ if (silentOverride)
41
+ return;
42
+ if (isDebugEnabled())
17
43
  console.debug(PREFIX, ...args);
18
44
  },
19
45
  };
@@ -1 +1 @@
1
- {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/src/utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAW7C;;GAEG;AACH,eAAO,MAAM,WAAW,GACtB,SAAS,MAAM,EACf,kBAAyB,KACxB,MAKF,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,eAAe,GAC1B,SAAS,MAAM,EACf,kBAAyB,KACxB,MAMF,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,UAAU,GAAI,OAAO,OAAO,KAAG,KAAK,IAAI,IAAI,GAAG;IAC1D,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CAMd,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,oBAAoB,GAAI,OAAO,IAAI,EAAE,KAAG,MACe,CAAC;AAErE;;;;GAIG;AACH,eAAO,MAAM,sBAAsB,GACjC,MAAM,MAAM,EACZ,QAAQ,MAAM,KACb,MAKF,CAAC"}
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/src/utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAkB7C;;GAEG;AACH,eAAO,MAAM,WAAW,GACtB,SAAS,MAAM,EACf,kBAAyB,KACxB,MAKF,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,eAAe,GAC1B,SAAS,MAAM,EACf,kBAAyB,KACxB,MAMF,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,UAAU,GAAI,OAAO,OAAO,KAAG,KAAK,IAAI,IAAI,GAAG;IAC1D,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CAMd,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,oBAAoB,GAAI,OAAO,IAAI,EAAE,KAAG,MACe,CAAC;AAErE;;;;GAIG;AACH,eAAO,MAAM,sBAAsB,GACjC,MAAM,MAAM,EACZ,QAAQ,MAAM,KACb,MAKF,CAAC"}
package/esm/src/utils.js CHANGED
@@ -1,7 +1,15 @@
1
1
  import os from "node:os";
2
2
  import process from "node:process";
3
3
  const getProjectName = (directory) => directory.split("/").filter(Boolean).at(-1)?.trim() || "default";
4
- const getUserName = (home = os.homedir().split("/").filter(Boolean).at(-1)) => home?.trim() || undefined;
4
+ const getHomeDirectory = () => {
5
+ try {
6
+ return os.homedir();
7
+ }
8
+ catch {
9
+ return undefined;
10
+ }
11
+ };
12
+ const getUserName = () => getHomeDirectory()?.split("/").filter(Boolean).at(-1)?.trim() || undefined;
5
13
  /**
6
14
  * Build a sanitized Graphiti group ID from a prefix and project directory.
7
15
  */
@@ -16,7 +24,7 @@ export const makeGroupId = (prefix, directory = process.cwd()) => {
16
24
  */
17
25
  export const makeUserGroupId = (prefix, directory = process.cwd()) => {
18
26
  const projectName = getProjectName(directory);
19
- const userName = getUserName();
27
+ const userName = getUserName() ?? "unknown";
20
28
  const prefixPart = prefix ? `${prefix}-` : "";
21
29
  const rawGroupId = `${prefixPart}${projectName}__user-${userName}`;
22
30
  return rawGroupId.replace(/[^A-Za-z0-9_-]/g, "_");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opencode-graphiti",
3
- "version": "0.1.10",
3
+ "version": "0.1.12",
4
4
  "description": "OpenCode plugin for persistent memory via Graphiti knowledge graph",
5
5
  "keywords": [
6
6
  "opencode",
@@ -49,7 +49,7 @@
49
49
  "@opencode-ai/plugin": "^1.1.53",
50
50
  "@opencode-ai/sdk": "^1.1.53",
51
51
  "cosmiconfig": "9.0.0",
52
- "zod": "4.3.6"
52
+ "@deno/shim-deno": "~0.18.0"
53
53
  },
54
54
  "devDependencies": {
55
55
  "@types/node": "^20.9.0"