opencode-graphiti 0.1.4 → 0.1.6

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 (84) hide show
  1. package/README.md +10 -17
  2. package/esm/deno.d.ts +47 -0
  3. package/esm/deno.d.ts.map +1 -0
  4. package/esm/deno.js +41 -0
  5. package/esm/src/config.d.ts.map +1 -1
  6. package/esm/src/config.js +4 -2
  7. package/esm/src/handlers/chat.d.ts +2 -1
  8. package/esm/src/handlers/chat.d.ts.map +1 -1
  9. package/esm/src/handlers/chat.js +89 -49
  10. package/esm/src/handlers/compacting.d.ts +1 -0
  11. package/esm/src/handlers/compacting.d.ts.map +1 -1
  12. package/esm/src/handlers/compacting.js +2 -1
  13. package/esm/src/handlers/event.d.ts +2 -2
  14. package/esm/src/handlers/event.d.ts.map +1 -1
  15. package/esm/src/handlers/event.js +52 -1
  16. package/esm/src/handlers/system.d.ts +11 -0
  17. package/esm/src/handlers/system.d.ts.map +1 -0
  18. package/esm/src/handlers/system.js +18 -0
  19. package/esm/src/index.d.ts.map +1 -1
  20. package/esm/src/index.js +8 -2
  21. package/esm/src/services/client.d.ts +8 -1
  22. package/esm/src/services/client.d.ts.map +1 -1
  23. package/esm/src/services/client.js +32 -2
  24. package/esm/src/services/compaction.d.ts +10 -0
  25. package/esm/src/services/compaction.d.ts.map +1 -1
  26. package/esm/src/services/compaction.js +106 -18
  27. package/esm/src/services/context-limit.d.ts +2 -8
  28. package/esm/src/services/context-limit.d.ts.map +1 -1
  29. package/esm/src/services/context-limit.js +3 -1
  30. package/esm/src/services/context.d.ts +27 -2
  31. package/esm/src/services/context.d.ts.map +1 -1
  32. package/esm/src/services/context.js +107 -13
  33. package/esm/src/services/logger.d.ts.map +1 -1
  34. package/esm/src/services/logger.js +1 -2
  35. package/esm/src/session.d.ts +6 -25
  36. package/esm/src/session.d.ts.map +1 -1
  37. package/esm/src/session.js +4 -7
  38. package/esm/src/types/index.d.ts +8 -2
  39. package/esm/src/types/index.d.ts.map +1 -1
  40. package/package.json +25 -3
  41. package/script/deno.d.ts +47 -0
  42. package/script/deno.d.ts.map +1 -0
  43. package/script/deno.js +43 -0
  44. package/script/src/config.d.ts.map +1 -1
  45. package/script/src/config.js +4 -2
  46. package/script/src/handlers/chat.d.ts +2 -1
  47. package/script/src/handlers/chat.d.ts.map +1 -1
  48. package/script/src/handlers/chat.js +88 -48
  49. package/script/src/handlers/compacting.d.ts +1 -0
  50. package/script/src/handlers/compacting.d.ts.map +1 -1
  51. package/script/src/handlers/compacting.js +2 -1
  52. package/script/src/handlers/event.d.ts +2 -2
  53. package/script/src/handlers/event.d.ts.map +1 -1
  54. package/script/src/handlers/event.js +52 -1
  55. package/script/src/handlers/system.d.ts +11 -0
  56. package/script/src/handlers/system.d.ts.map +1 -0
  57. package/script/src/handlers/system.js +21 -0
  58. package/script/src/index.d.ts.map +1 -1
  59. package/script/src/index.js +8 -2
  60. package/script/src/services/client.d.ts +8 -1
  61. package/script/src/services/client.d.ts.map +1 -1
  62. package/script/src/services/client.js +35 -2
  63. package/script/src/services/compaction.d.ts +10 -0
  64. package/script/src/services/compaction.d.ts.map +1 -1
  65. package/script/src/services/compaction.js +108 -17
  66. package/script/src/services/context-limit.d.ts +2 -8
  67. package/script/src/services/context-limit.d.ts.map +1 -1
  68. package/script/src/services/context-limit.js +3 -1
  69. package/script/src/services/context.d.ts +27 -2
  70. package/script/src/services/context.d.ts.map +1 -1
  71. package/script/src/services/context.js +118 -14
  72. package/script/src/services/logger.d.ts.map +1 -1
  73. package/script/src/services/logger.js +1 -35
  74. package/script/src/session.d.ts +6 -25
  75. package/script/src/session.d.ts.map +1 -1
  76. package/script/src/session.js +4 -7
  77. package/script/src/types/index.d.ts +8 -2
  78. package/script/src/types/index.d.ts.map +1 -1
  79. package/esm/_dnt.shims.d.ts +0 -6
  80. package/esm/_dnt.shims.d.ts.map +0 -1
  81. package/esm/_dnt.shims.js +0 -61
  82. package/script/_dnt.shims.d.ts +0 -6
  83. package/script/_dnt.shims.d.ts.map +0 -1
  84. package/script/_dnt.shims.js +0 -65
@@ -1,5 +1,6 @@
1
1
  import { Client } from "@modelcontextprotocol/sdk/client/index.js";
2
2
  import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
3
+ import manifest from "../../deno.js";
3
4
  import { logger } from "./logger.js";
4
5
  /**
5
6
  * Graphiti MCP client wrapper for connecting, querying,
@@ -35,12 +36,18 @@ export class GraphitiClient {
35
36
  value: void 0
36
37
  });
37
38
  this.endpoint = endpoint;
38
- this.client = new Client({ name: "opencode-graphiti", version: "0.1.4" });
39
+ this.client = new Client({
40
+ name: manifest.name,
41
+ version: manifest.version,
42
+ });
39
43
  this.transport = new StreamableHTTPClientTransport(new URL(endpoint));
40
44
  }
41
45
  /** Create a fresh MCP Client and Transport pair. */
42
46
  createClientAndTransport() {
43
- this.client = new Client({ name: "opencode-graphiti", version: "0.1.4" });
47
+ this.client = new Client({
48
+ name: manifest.name,
49
+ version: manifest.version,
50
+ });
44
51
  this.transport = new StreamableHTTPClientTransport(new URL(this.endpoint));
45
52
  }
46
53
  /**
@@ -208,6 +215,29 @@ export class GraphitiClient {
208
215
  return [];
209
216
  }
210
217
  }
218
+ /**
219
+ * Retrieve recent episodes for a group.
220
+ */
221
+ async getEpisodes(params) {
222
+ try {
223
+ const result = await this.callTool("get_episodes", {
224
+ group_id: params.groupId,
225
+ last_n: params.lastN,
226
+ });
227
+ if (Array.isArray(result))
228
+ return result;
229
+ if (result &&
230
+ typeof result === "object" &&
231
+ Array.isArray(result.episodes)) {
232
+ return result.episodes;
233
+ }
234
+ return [];
235
+ }
236
+ catch (err) {
237
+ logger.error("getEpisodes error:", err);
238
+ return [];
239
+ }
240
+ }
211
241
  /**
212
242
  * Check whether the Graphiti MCP server is reachable.
213
243
  */
@@ -1,4 +1,13 @@
1
1
  import type { GraphitiFact, GraphitiNode } from "../types/index.js";
2
+ export declare const classifyFacts: (facts: GraphitiFact[], now: Date) => {
3
+ decisions: GraphitiFact[];
4
+ active: GraphitiFact[];
5
+ background: GraphitiFact[];
6
+ };
7
+ export declare const takeFactsWithinBudget: (facts: GraphitiFact[], budget: number, formatOptions: {
8
+ factStaleDays: number;
9
+ now: Date;
10
+ }) => GraphitiFact[];
2
11
  /**
3
12
  * Persist a compaction summary episode when enabled.
4
13
  */
@@ -38,5 +47,6 @@ export declare function getCompactionContext(params: {
38
47
  user?: string;
39
48
  };
40
49
  contextStrings: string[];
50
+ factStaleDays?: number;
41
51
  }): Promise<string[]>;
42
52
  //# sourceMappingURL=compaction.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"compaction.d.ts","sourceRoot":"","sources":["../../../src/src/services/compaction.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAIpE;;GAEG;AACH,wBAAsB,gBAAgB,CAAC,MAAM,EAAE;IAC7C,MAAM,EAAE;QACN,UAAU,EAAE,CAAC,IAAI,EAAE;YACjB,IAAI,EAAE,MAAM,CAAC;YACb,WAAW,EAAE,MAAM,CAAC;YACpB,OAAO,CAAC,EAAE,MAAM,CAAC;YACjB,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;YACrC,iBAAiB,CAAC,EAAE,MAAM,CAAC;SAC5B,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;KACrB,CAAC;IACF,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;CACnB,GAAG,OAAO,CAAC,IAAI,CAAC,CAiBhB;AAED;;GAEG;AACH,wBAAsB,oBAAoB,CAAC,MAAM,EAAE;IACjD,MAAM,EAAE;QACN,WAAW,EAAE,CAAC,IAAI,EAAE;YAClB,KAAK,EAAE,MAAM,CAAC;YACd,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;YACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;SACnB,KAAK,OAAO,CAAC,YAAY,EAAE,CAAC,CAAC;QAC9B,WAAW,EAAE,CAAC,IAAI,EAAE;YAClB,KAAK,EAAE,MAAM,CAAC;YACd,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;YACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;SACnB,KAAK,OAAO,CAAC,YAAY,EAAE,CAAC,CAAC;KAC/B,CAAC;IACF,eAAe,EAAE,MAAM,CAAC;IACxB,QAAQ,EAAE;QACR,OAAO,EAAE,MAAM,CAAC;QAChB,IAAI,CAAC,EAAE,MAAM,CAAC;KACf,CAAC;IACF,cAAc,EAAE,MAAM,EAAE,CAAC;CAC1B,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAgIpB"}
1
+ {"version":3,"file":"compaction.d.ts","sourceRoot":"","sources":["../../../src/src/services/compaction.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AA0BpE,eAAO,MAAM,aAAa,GACxB,OAAO,YAAY,EAAE,EACrB,KAAK,IAAI,KACR;IACD,SAAS,EAAE,YAAY,EAAE,CAAC;IAC1B,MAAM,EAAE,YAAY,EAAE,CAAC;IACvB,UAAU,EAAE,YAAY,EAAE,CAAC;CA4B5B,CAAC;AAEF,eAAO,MAAM,qBAAqB,GAChC,OAAO,YAAY,EAAE,EACrB,QAAQ,MAAM,EACd,eAAe;IAAE,aAAa,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,IAAI,CAAA;CAAE,KAClD,YAAY,EAoBd,CAAC;AAEF;;GAEG;AACH,wBAAsB,gBAAgB,CAAC,MAAM,EAAE;IAC7C,MAAM,EAAE;QACN,UAAU,EAAE,CAAC,IAAI,EAAE;YACjB,IAAI,EAAE,MAAM,CAAC;YACb,WAAW,EAAE,MAAM,CAAC;YACpB,OAAO,CAAC,EAAE,MAAM,CAAC;YACjB,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;YACrC,iBAAiB,CAAC,EAAE,MAAM,CAAC;SAC5B,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;KACrB,CAAC;IACF,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;CACnB,GAAG,OAAO,CAAC,IAAI,CAAC,CAiBhB;AAED;;GAEG;AACH,wBAAsB,oBAAoB,CAAC,MAAM,EAAE;IACjD,MAAM,EAAE;QACN,WAAW,EAAE,CAAC,IAAI,EAAE;YAClB,KAAK,EAAE,MAAM,CAAC;YACd,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;YACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;SACnB,KAAK,OAAO,CAAC,YAAY,EAAE,CAAC,CAAC;QAC9B,WAAW,EAAE,CAAC,IAAI,EAAE;YAClB,KAAK,EAAE,MAAM,CAAC;YACd,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;YACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;SACnB,KAAK,OAAO,CAAC,YAAY,EAAE,CAAC,CAAC;KAC/B,CAAC;IACF,eAAe,EAAE,MAAM,CAAC;IACxB,QAAQ,EAAE;QACR,OAAO,EAAE,MAAM,CAAC;QAChB,IAAI,CAAC,EAAE,MAAM,CAAC;KACf,CAAC;IACF,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CA0KpB"}
@@ -1,5 +1,69 @@
1
- import { formatFactLines, formatNodeLines } from "./context.js";
1
+ import { deduplicateContext, formatFactLines, formatNodeLines, } from "./context.js";
2
2
  import { logger } from "./logger.js";
3
+ const DAY_MS = 24 * 60 * 60 * 1000;
4
+ const DECISION_KEYWORDS = [
5
+ "decided",
6
+ "must",
7
+ "should",
8
+ "prefer",
9
+ "constraint",
10
+ "require",
11
+ "chose",
12
+ "always",
13
+ "never",
14
+ "schema",
15
+ "architecture",
16
+ "agreed",
17
+ "design",
18
+ "selected",
19
+ ];
20
+ export const classifyFacts = (facts, now) => {
21
+ const decisions = [];
22
+ const active = [];
23
+ const background = [];
24
+ const cutoff = now.getTime() - 7 * DAY_MS;
25
+ for (const fact of facts) {
26
+ const text = fact.fact.toLowerCase();
27
+ // Use word boundary regex to match whole words only
28
+ const hasDecisionKeyword = DECISION_KEYWORDS.some((keyword) => {
29
+ const regex = new RegExp(`\\b${keyword}\\b`, "i");
30
+ return regex.test(text);
31
+ });
32
+ if (hasDecisionKeyword) {
33
+ decisions.push(fact);
34
+ continue;
35
+ }
36
+ const validAt = fact.valid_at ? Date.parse(fact.valid_at) : NaN;
37
+ if (!Number.isNaN(validAt) && validAt >= cutoff) {
38
+ active.push(fact);
39
+ continue;
40
+ }
41
+ background.push(fact);
42
+ }
43
+ return { decisions, active, background };
44
+ };
45
+ export const takeFactsWithinBudget = (facts, budget, formatOptions) => {
46
+ if (budget <= 0 || facts.length === 0)
47
+ return [];
48
+ const classified = classifyFacts(facts, formatOptions.now);
49
+ const prioritized = [
50
+ ...classified.decisions,
51
+ ...classified.active,
52
+ ...classified.background,
53
+ ];
54
+ const lines = formatFactLines(prioritized, formatOptions);
55
+ const selected = [];
56
+ let remaining = budget;
57
+ for (let i = 0; i < lines.length; i++) {
58
+ const line = lines[i];
59
+ const length = line.length + 1;
60
+ if (remaining - length < 0)
61
+ continue;
62
+ selected.push(prioritized[i]);
63
+ remaining -= length;
64
+ }
65
+ return selected;
66
+ };
3
67
  /**
4
68
  * Persist a compaction summary episode when enabled.
5
69
  */
@@ -26,6 +90,8 @@ export async function handleCompaction(params) {
26
90
  */
27
91
  export async function getCompactionContext(params) {
28
92
  const { client, characterBudget, groupIds, contextStrings } = params;
93
+ const now = new Date();
94
+ const factStaleDays = params.factStaleDays ?? 30;
29
95
  try {
30
96
  const queryText = contextStrings.slice(0, 3).join(" ").slice(0, 500);
31
97
  if (!queryText.trim())
@@ -66,14 +132,40 @@ export async function getCompactionContext(params) {
66
132
  userFacts.length === 0 && userNodes.length === 0) {
67
133
  return [];
68
134
  }
69
- const buildSection = (header, facts, nodes) => {
135
+ const formatOptions = { factStaleDays, now };
136
+ const projectContext = deduplicateContext({
137
+ facts: projectFacts,
138
+ nodes: projectNodes,
139
+ });
140
+ const userContext = deduplicateContext({
141
+ facts: userFacts,
142
+ nodes: userNodes,
143
+ });
144
+ const buildSection = (header, facts, nodes, budget) => {
70
145
  const lines = [];
71
146
  lines.push(header);
72
147
  lines.push("<instruction>Background context only; do not reference in titles, summaries, or opening responses unless directly relevant.</instruction>");
73
- if (facts.length > 0) {
74
- lines.push("<facts>");
75
- lines.push(...formatFactLines(facts));
76
- lines.push("</facts>");
148
+ const classified = classifyFacts(facts, now);
149
+ const decisionBudget = Math.floor(budget * 0.4);
150
+ const activeBudget = Math.floor(budget * 0.35);
151
+ const backgroundBudget = budget - decisionBudget - activeBudget;
152
+ const selectedDecisions = takeFactsWithinBudget(classified.decisions, decisionBudget, formatOptions);
153
+ const selectedActive = takeFactsWithinBudget(classified.active, activeBudget, formatOptions);
154
+ const selectedBackground = takeFactsWithinBudget(classified.background, backgroundBudget, formatOptions);
155
+ if (selectedDecisions.length > 0) {
156
+ lines.push("<decisions>");
157
+ lines.push(...formatFactLines(selectedDecisions, formatOptions));
158
+ lines.push("</decisions>");
159
+ }
160
+ if (selectedActive.length > 0) {
161
+ lines.push("<active_context>");
162
+ lines.push(...formatFactLines(selectedActive, formatOptions));
163
+ lines.push("</active_context>");
164
+ }
165
+ if (selectedBackground.length > 0) {
166
+ lines.push("<background>");
167
+ lines.push(...formatFactLines(selectedBackground, formatOptions));
168
+ lines.push("</background>");
77
169
  }
78
170
  if (nodes.length > 0) {
79
171
  lines.push("<nodes>");
@@ -82,25 +174,19 @@ export async function getCompactionContext(params) {
82
174
  }
83
175
  return lines.join("\n");
84
176
  };
85
- const projectSection = buildSection('<memory source="project">', projectFacts, projectNodes);
86
- const userSection = buildSection('<memory source="user">', userFacts, userNodes);
87
177
  const headerLines = [
88
178
  "<summary>",
89
- "<current_goal>",
90
- "- ",
91
- "</current_goal>",
92
- "",
93
- "<work_completed>",
179
+ "<decisions>",
94
180
  "- ",
95
- "</work_completed>",
181
+ "</decisions>",
96
182
  "",
97
- "<remaining_tasks>",
183
+ "<active_context>",
98
184
  "- ",
99
- "</remaining_tasks>",
185
+ "</active_context>",
100
186
  "",
101
- "<constraints_decisions>",
187
+ "<background>",
102
188
  "- ",
103
- "</constraints_decisions>",
189
+ "</background>",
104
190
  "",
105
191
  "<persistent_memory>",
106
192
  ];
@@ -109,6 +195,8 @@ export async function getCompactionContext(params) {
109
195
  const remainingBudget = Math.max(characterBudget - base.length, 0);
110
196
  const projectBudget = Math.floor(remainingBudget * 0.7);
111
197
  const userBudget = remainingBudget - projectBudget;
198
+ const projectSection = buildSection('<memory source="project">', projectContext.facts, projectContext.nodes, projectBudget);
199
+ const userSection = buildSection('<memory source="user">', userContext.facts, userContext.nodes, userBudget);
112
200
  const truncatedProject = projectSection.slice(0, projectBudget);
113
201
  const truncatedUser = userSection.slice(0, userBudget);
114
202
  const sections = [header];
@@ -1,11 +1,5 @@
1
- export interface ProviderListClient {
2
- provider: {
3
- list: (options?: {
4
- directory?: string;
5
- }) => Promise<unknown>;
6
- };
7
- }
8
- export declare function resolveContextLimit(providerID: string, modelID: string, client: ProviderListClient, directory: string): Promise<number>;
1
+ import type { OpencodeClient } from "@opencode-ai/sdk";
2
+ export declare function resolveContextLimit(providerID: string, modelID: string, client: OpencodeClient, directory: string): Promise<number>;
9
3
  /**
10
4
  * Calculate the character budget for memory injection
11
5
  * (5% of context limit * 4 chars/token).
@@ -1 +1 @@
1
- {"version":3,"file":"context-limit.d.ts","sourceRoot":"","sources":["../../../src/src/services/context-limit.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE;QACR,IAAI,EAAE,CAAC,OAAO,CAAC,EAAE;YAAE,SAAS,CAAC,EAAE,MAAM,CAAA;SAAE,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;KAC9D,CAAC;CACH;AAID,wBAAsB,mBAAmB,CACvC,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,kBAAkB,EAC1B,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,MAAM,CAAC,CA+BjB;AAED;;;GAGG;AACH,wBAAgB,wBAAwB,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,CAErE"}
1
+ {"version":3,"file":"context-limit.d.ts","sourceRoot":"","sources":["../../../src/src/services/context-limit.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAOvD,wBAAsB,mBAAmB,CACvC,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,cAAc,EACtB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,MAAM,CAAC,CAiCjB;AAED;;;GAGG;AACH,wBAAgB,wBAAwB,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,CAErE"}
@@ -7,7 +7,9 @@ export async function resolveContextLimit(providerID, modelID, client, directory
7
7
  if (cached)
8
8
  return cached;
9
9
  try {
10
- const providers = await client.provider.list({ directory });
10
+ const providers = await client.provider.list({
11
+ query: { directory },
12
+ });
11
13
  const list = providers.providers ?? [];
12
14
  for (const provider of list) {
13
15
  const providerInfo = provider;
@@ -1,8 +1,33 @@
1
1
  import type { GraphitiFact, GraphitiNode } from "../types/index.js";
2
- export declare const formatFactLines: (facts: GraphitiFact[]) => string[];
2
+ export declare const parseDate: (value?: string) => Date | null;
3
+ export declare const isFactInvalid: (fact: GraphitiFact, now: Date) => boolean;
4
+ export declare const annotateStaleFact: (fact: GraphitiFact, now: Date, factStaleDays: number) => GraphitiFact;
5
+ export declare const sortFactsByRecency: (facts: GraphitiFact[]) => GraphitiFact[];
6
+ export declare const filterAndAnnotateFacts: (facts: GraphitiFact[], options?: {
7
+ factStaleDays?: number;
8
+ now?: Date;
9
+ }) => GraphitiFact[];
10
+ export declare const formatFactLine: (fact: GraphitiFact) => string;
11
+ export declare const formatFactLines: (facts: GraphitiFact[], options?: {
12
+ factStaleDays?: number;
13
+ now?: Date;
14
+ }) => string[];
3
15
  export declare const formatNodeLines: (nodes: GraphitiNode[]) => string[];
16
+ export declare const deduplicateFactsByUuid: (facts: GraphitiFact[]) => GraphitiFact[];
17
+ export declare const deduplicateNodesByUuid: (nodes: GraphitiNode[]) => GraphitiNode[];
18
+ export declare const removeNodesReferencedByFacts: (facts: GraphitiFact[], nodes: GraphitiNode[]) => GraphitiNode[];
19
+ export declare const deduplicateContext: (params: {
20
+ facts: GraphitiFact[];
21
+ nodes: GraphitiNode[];
22
+ }) => {
23
+ facts: GraphitiFact[];
24
+ nodes: GraphitiNode[];
25
+ };
4
26
  /**
5
27
  * Format Graphiti facts and nodes into a user-facing context block.
6
28
  */
7
- export declare function formatMemoryContext(facts: GraphitiFact[], nodes: GraphitiNode[]): string;
29
+ export declare function formatMemoryContext(facts: GraphitiFact[], nodes: GraphitiNode[], options?: {
30
+ factStaleDays?: number;
31
+ now?: Date;
32
+ }): string;
8
33
  //# sourceMappingURL=context.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../../src/src/services/context.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEpE,eAAO,MAAM,eAAe,GAAI,OAAO,YAAY,EAAE,KAAG,MAAM,EAO1D,CAAC;AAEL,eAAO,MAAM,eAAe,GAAI,OAAO,YAAY,EAAE,KAAG,MAAM,EAK1D,CAAC;AAEL;;GAEG;AACH,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,YAAY,EAAE,EACrB,KAAK,EAAE,YAAY,EAAE,GACpB,MAAM,CA0BR"}
1
+ {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../../src/src/services/context.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAIpE,eAAO,MAAM,SAAS,GAAI,QAAQ,MAAM,KAAG,IAAI,GAAG,IAKjD,CAAC;AAEF,eAAO,MAAM,aAAa,GAAI,MAAM,YAAY,EAAE,KAAK,IAAI,KAAG,OAQ7D,CAAC;AAEF,eAAO,MAAM,iBAAiB,GAC5B,MAAM,YAAY,EAClB,KAAK,IAAI,EACT,eAAe,MAAM,KACpB,YAUF,CAAC;AAEF,eAAO,MAAM,kBAAkB,GAAI,OAAO,YAAY,EAAE,KAAG,YAAY,EAWtE,CAAC;AAEF,eAAO,MAAM,sBAAsB,GACjC,OAAO,YAAY,EAAE,EACrB,UAAU;IACR,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,GAAG,CAAC,EAAE,IAAI,CAAC;CACZ,KACA,YAAY,EAMd,CAAC;AAEF,eAAO,MAAM,cAAc,GAAI,MAAM,YAAY,KAAG,MAMnD,CAAC;AAEF,eAAO,MAAM,eAAe,GAC1B,OAAO,YAAY,EAAE,EACrB,UAAU;IACR,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,GAAG,CAAC,EAAE,IAAI,CAAC;CACZ,KACA,MAAM,EAGR,CAAC;AAEF,eAAO,MAAM,eAAe,GAAI,OAAO,YAAY,EAAE,KAAG,MAAM,EAK1D,CAAC;AAEL,eAAO,MAAM,sBAAsB,GACjC,OAAO,YAAY,EAAE,KACpB,YAAY,EASd,CAAC;AAEF,eAAO,MAAM,sBAAsB,GACjC,OAAO,YAAY,EAAE,KACpB,YAAY,EASd,CAAC;AAEF,eAAO,MAAM,4BAA4B,GACvC,OAAO,YAAY,EAAE,EACrB,OAAO,YAAY,EAAE,KACpB,YAAY,EAOd,CAAC;AAEF,eAAO,MAAM,kBAAkB,GAAI,QAAQ;IACzC,KAAK,EAAE,YAAY,EAAE,CAAC;IACtB,KAAK,EAAE,YAAY,EAAE,CAAC;CACvB,KAAG;IAAE,KAAK,EAAE,YAAY,EAAE,CAAC;IAAC,KAAK,EAAE,YAAY,EAAE,CAAA;CAQjD,CAAC;AAEF;;GAEG;AACH,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,YAAY,EAAE,EACrB,KAAK,EAAE,YAAY,EAAE,EACrB,OAAO,CAAC,EAAE;IACR,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,GAAG,CAAC,EAAE,IAAI,CAAC;CACZ,GACA,MAAM,CA6BR"}
@@ -1,37 +1,131 @@
1
- export const formatFactLines = (facts) => facts.map((fact) => {
1
+ const DAY_MS = 24 * 60 * 60 * 1000;
2
+ export const parseDate = (value) => {
3
+ if (!value)
4
+ return null;
5
+ const parsed = Date.parse(value);
6
+ if (Number.isNaN(parsed))
7
+ return null;
8
+ return new Date(parsed);
9
+ };
10
+ export const isFactInvalid = (fact, now) => {
11
+ const invalidAt = parseDate(fact.invalid_at);
12
+ if (invalidAt && invalidAt.getTime() < now.getTime())
13
+ return true;
14
+ const validAt = parseDate(fact.valid_at);
15
+ if (validAt && validAt.getTime() > now.getTime())
16
+ return true;
17
+ return false;
18
+ };
19
+ export const annotateStaleFact = (fact, now, factStaleDays) => {
20
+ const validAt = parseDate(fact.valid_at);
21
+ if (!validAt)
22
+ return fact;
23
+ const ageDays = Math.floor((now.getTime() - validAt.getTime()) / DAY_MS);
24
+ if (ageDays < 0)
25
+ return fact;
26
+ if (ageDays < factStaleDays)
27
+ return fact;
28
+ return {
29
+ ...fact,
30
+ fact: `[stale: ${ageDays} days ago] ${fact.fact}`,
31
+ };
32
+ };
33
+ export const sortFactsByRecency = (facts) => {
34
+ const indexed = facts.map((fact, index) => ({
35
+ fact,
36
+ index,
37
+ time: parseDate(fact.valid_at)?.getTime() ?? -Infinity,
38
+ }));
39
+ indexed.sort((a, b) => {
40
+ if (a.time !== b.time)
41
+ return b.time - a.time;
42
+ return a.index - b.index;
43
+ });
44
+ return indexed.map((entry) => entry.fact);
45
+ };
46
+ export const filterAndAnnotateFacts = (facts, options) => {
47
+ const now = options?.now ?? new Date();
48
+ const factStaleDays = options?.factStaleDays ?? 30;
49
+ const filtered = facts.filter((fact) => !isFactInvalid(fact, now));
50
+ const sorted = sortFactsByRecency(filtered);
51
+ return sorted.map((fact) => annotateStaleFact(fact, now, factStaleDays));
52
+ };
53
+ export const formatFactLine = (fact) => {
2
54
  const entities = [];
3
55
  if (fact.source_node?.name)
4
56
  entities.push(fact.source_node.name);
5
57
  if (fact.target_node?.name)
6
58
  entities.push(fact.target_node.name);
7
59
  const entityStr = entities.length > 0 ? ` [${entities.join(" -> ")}]` : "";
8
- return `<fact>${fact.fact}${entityStr}</fact>`;
9
- });
60
+ return `- ${fact.fact}${entityStr}`;
61
+ };
62
+ export const formatFactLines = (facts, options) => {
63
+ const annotated = filterAndAnnotateFacts(facts, options);
64
+ return annotated.map((fact) => formatFactLine(fact));
65
+ };
10
66
  export const formatNodeLines = (nodes) => nodes.map((node) => {
11
67
  const labels = node.labels?.length ? ` (${node.labels.join(", ")})` : "";
12
68
  const summary = node.summary ? `: ${node.summary}` : "";
13
- return `<node>${node.name}${labels}${summary}</node>`;
69
+ return `- **${node.name}**${labels}${summary}`;
14
70
  });
71
+ export const deduplicateFactsByUuid = (facts) => {
72
+ const seen = new Set();
73
+ const deduped = [];
74
+ for (const fact of facts) {
75
+ if (seen.has(fact.uuid))
76
+ continue;
77
+ seen.add(fact.uuid);
78
+ deduped.push(fact);
79
+ }
80
+ return deduped;
81
+ };
82
+ export const deduplicateNodesByUuid = (nodes) => {
83
+ const seen = new Set();
84
+ const deduped = [];
85
+ for (const node of nodes) {
86
+ if (seen.has(node.uuid))
87
+ continue;
88
+ seen.add(node.uuid);
89
+ deduped.push(node);
90
+ }
91
+ return deduped;
92
+ };
93
+ export const removeNodesReferencedByFacts = (facts, nodes) => {
94
+ const factNodeUuids = new Set();
95
+ for (const fact of facts) {
96
+ if (fact.source_node?.uuid)
97
+ factNodeUuids.add(fact.source_node.uuid);
98
+ if (fact.target_node?.uuid)
99
+ factNodeUuids.add(fact.target_node.uuid);
100
+ }
101
+ return nodes.filter((node) => !factNodeUuids.has(node.uuid));
102
+ };
103
+ export const deduplicateContext = (params) => {
104
+ const dedupedFacts = deduplicateFactsByUuid(params.facts);
105
+ const dedupedNodes = deduplicateNodesByUuid(params.nodes);
106
+ const filteredNodes = removeNodesReferencedByFacts(dedupedFacts, dedupedNodes);
107
+ return { facts: dedupedFacts, nodes: filteredNodes };
108
+ };
15
109
  /**
16
110
  * Format Graphiti facts and nodes into a user-facing context block.
17
111
  */
18
- export function formatMemoryContext(facts, nodes) {
112
+ export function formatMemoryContext(facts, nodes, options) {
19
113
  if (facts.length === 0 && nodes.length === 0) {
20
114
  return "";
21
115
  }
22
116
  const sections = [];
23
- sections.push("<memory>");
24
- sections.push("<instruction>Background context only; do not reference in titles, summaries, or opening responses unless directly relevant.</instruction>");
117
+ sections.push("# Persistent Memory (from Graphiti Knowledge Graph)");
118
+ sections.push("The following information was retrieved from your persistent memory.");
119
+ sections.push("Use this context to inform your responses, but do not mention it unless asked.");
25
120
  if (facts.length > 0) {
26
- sections.push("<facts>");
27
- sections.push(...formatFactLines(facts));
28
- sections.push("</facts>");
121
+ sections.push("");
122
+ sections.push("## Known Facts");
123
+ sections.push(...formatFactLines(facts, options));
29
124
  }
30
125
  if (nodes.length > 0) {
31
- sections.push("<nodes>");
126
+ sections.push("");
127
+ sections.push("## Known Entities");
32
128
  sections.push(...formatNodeLines(nodes));
33
- sections.push("</nodes>");
34
129
  }
35
- sections.push("</memory>");
36
130
  return sections.join("\n");
37
131
  }
@@ -1 +1 @@
1
- {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../../src/src/services/logger.ts"],"names":[],"mappings":"AAaA,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":"AAUA,eAAO,MAAM,MAAM;oBACD,OAAO,EAAE;oBAGT,OAAO,EAAE;qBAGR,OAAO,EAAE;qBAGT,OAAO,EAAE;CAG3B,CAAC"}
@@ -1,6 +1,5 @@
1
- import * as dntShim from "../../_dnt.shims.js";
2
1
  import process from "node:process";
3
- const console = dntShim.dntGlobalThis.console;
2
+ const console = globalThis.console;
4
3
  const PREFIX = "[graphiti]";
5
4
  export const logger = {
6
5
  info: (...args) => {
@@ -1,3 +1,4 @@
1
+ import type { OpencodeClient } from "@opencode-ai/sdk";
1
2
  import type { GraphitiClient } from "./services/client.js";
2
3
  /**
3
4
  * Per-session state tracked by the plugin.
@@ -9,8 +10,10 @@ export type SessionState = {
9
10
  userGroupId: string;
10
11
  /** Whether memories have been injected into this session yet. */
11
12
  injectedMemories: boolean;
12
- /** Message count at last memory injection. */
13
- lastInjectionMessageCount: number;
13
+ /** Fact UUIDs included in the last memory injection. */
14
+ lastInjectionFactUuids: Set<string>;
15
+ /** Cached formatted memory context for system prompt injection. */
16
+ cachedMemoryContext?: string;
14
17
  /** Count of messages observed in this session. */
15
18
  messageCount: number;
16
19
  /** Buffered message strings awaiting flush. */
@@ -20,28 +23,6 @@ export type SessionState = {
20
23
  /** True when this session is the primary (non-subagent) session. */
21
24
  isMain: boolean;
22
25
  };
23
- /**
24
- * Minimal SDK client interface needed for session operations.
25
- */
26
- export interface SdkSessionClient {
27
- session: {
28
- /** Retrieve session metadata by ID. */
29
- get: (args: {
30
- path: {
31
- id: string;
32
- };
33
- }) => Promise<unknown>;
34
- /** List recent messages for a session. */
35
- messages: (args: {
36
- sessionID: string;
37
- limit?: number;
38
- }) => Promise<unknown>;
39
- };
40
- }
41
- /**
42
- * Manages session lifecycle, parent ID resolution, message buffering,
43
- * and flushing of pending messages to Graphiti.
44
- */
45
26
  /**
46
27
  * Tracks per-session state, parent resolution, message buffering,
47
28
  * and flushing pending messages to Graphiti.
@@ -55,7 +36,7 @@ export declare class SessionManager {
55
36
  private parentIdCache;
56
37
  private pendingAssistantMessages;
57
38
  private bufferedAssistantMessageIds;
58
- constructor(defaultGroupId: string, defaultUserGroupId: string, sdkClient: SdkSessionClient, graphitiClient: GraphitiClient);
39
+ constructor(defaultGroupId: string, defaultUserGroupId: string, sdkClient: OpencodeClient, graphitiClient: GraphitiClient);
59
40
  /** Get the current session state, if present. */
60
41
  getState(sessionId: string): SessionState | undefined;
61
42
  /** Persist session state for the given session ID. */
@@ -1 +1 @@
1
- {"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../../src/src/session.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../../src/src/session.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,cAAc,EAGf,MAAM,kBAAkB,CAAC;AAC1B,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAI3D;;GAEG;AACH,MAAM,MAAM,YAAY,GAAG;IACzB,0CAA0C;IAC1C,OAAO,EAAE,MAAM,CAAC;IAChB,kDAAkD;IAClD,WAAW,EAAE,MAAM,CAAC;IACpB,iEAAiE;IACjE,gBAAgB,EAAE,OAAO,CAAC;IAC1B,wDAAwD;IACxD,sBAAsB,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IACpC,mEAAmE;IACnE,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,kDAAkD;IAClD,YAAY,EAAE,MAAM,CAAC;IACrB,+CAA+C;IAC/C,eAAe,EAAE,MAAM,EAAE,CAAC;IAC1B,sCAAsC;IACtC,YAAY,EAAE,MAAM,CAAC;IACrB,oEAAoE;IACpE,MAAM,EAAE,OAAO,CAAC;CACjB,CAAC;AAEF;;;GAGG;AACH,qBAAa,cAAc;IAUvB,OAAO,CAAC,QAAQ,CAAC,cAAc;IAC/B,OAAO,CAAC,QAAQ,CAAC,kBAAkB;IACnC,OAAO,CAAC,QAAQ,CAAC,SAAS;IAC1B,OAAO,CAAC,QAAQ,CAAC,cAAc;IAZjC,OAAO,CAAC,QAAQ,CAAmC;IACnD,OAAO,CAAC,aAAa,CAAoC;IACzD,OAAO,CAAC,wBAAwB,CAG5B;IACJ,OAAO,CAAC,2BAA2B,CAAqB;gBAGrC,cAAc,EAAE,MAAM,EACtB,kBAAkB,EAAE,MAAM,EAC1B,SAAS,EAAE,cAAc,EACzB,cAAc,EAAE,cAAc;IAGjD,iDAAiD;IACjD,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,YAAY,GAAG,SAAS;IAIrD,sDAAsD;IACtD,QAAQ,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,YAAY,GAAG,IAAI;IAItD,gDAAgD;IAChD,WAAW,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI;IAI7D,qDAAqD;IAC/C,eAAe,CACnB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IAsBrC,yDAAyD;IACnD,mBAAmB,CACvB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC;QAAE,KAAK,EAAE,YAAY,GAAG,IAAI,CAAC;QAAC,QAAQ,EAAE,OAAO,CAAA;KAAE,CAAC;IA0B7D,yDAAyD;IACnD,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAK5D,6DAA6D;IAC7D,mBAAmB,CACjB,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,MAAM,GACX,IAAI;IAKP,gEAAgE;IAChE,mBAAmB,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO;IAKlE;;OAEG;IACH,wBAAwB,CACtB,KAAK,EAAE,YAAY,EACnB,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,GACb,IAAI;IAwCP,+EAA+E;IACzE,oBAAoB,CACxB,SAAS,EAAE,MAAM,EACjB,iBAAiB,EAAE,MAAM,EACzB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,IAAI,CAAC;IAgFhB,iDAAiD;IACjD,sBAAsB,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI;IAKlE,uCAAuC;IACvC,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI;YAexB,2BAA2B;CAiC1C"}
@@ -1,9 +1,5 @@
1
1
  import { logger } from "./services/logger.js";
2
2
  import { extractTextFromParts } from "./utils.js";
3
- /**
4
- * Manages session lifecycle, parent ID resolution, message buffering,
5
- * and flushing of pending messages to Graphiti.
6
- */
7
3
  /**
8
4
  * Tracks per-session state, parent resolution, message buffering,
9
5
  * and flushing pending messages to Graphiti.
@@ -110,7 +106,8 @@ export class SessionManager {
110
106
  groupId: this.defaultGroupId,
111
107
  userGroupId: this.defaultUserGroupId,
112
108
  injectedMemories: false,
113
- lastInjectionMessageCount: 0,
109
+ lastInjectionFactUuids: new Set(),
110
+ cachedMemoryContext: undefined,
114
111
  messageCount: 0,
115
112
  pendingMessages: [],
116
113
  contextLimit: 200_000,
@@ -271,8 +268,8 @@ export class SessionManager {
271
268
  async fetchLatestAssistantMessage(sessionId) {
272
269
  try {
273
270
  const response = await this.sdkClient.session.messages({
274
- sessionID: sessionId,
275
- limit: 20,
271
+ path: { id: sessionId },
272
+ query: { limit: 20 },
276
273
  });
277
274
  const payload = response && typeof response === "object" &&
278
275
  "data" in response
@@ -4,8 +4,10 @@ export interface GraphitiConfig {
4
4
  endpoint: string;
5
5
  /** Prefix for group IDs to namespace project memories. */
6
6
  groupIdPrefix: string;
7
- /** Number of user messages between reinjections (0 disables). */
8
- injectionInterval: number;
7
+ /** Jaccard similarity threshold below which reinjection occurs. */
8
+ driftThreshold: number;
9
+ /** Number of days after which facts are considered stale. */
10
+ factStaleDays: number;
9
11
  }
10
12
  /** A fact retrieved from the Graphiti knowledge graph. */
11
13
  export interface GraphitiFact {
@@ -59,6 +61,10 @@ export interface GraphitiEpisode {
59
61
  content: string;
60
62
  /** Optional episode source type. */
61
63
  source?: string;
64
+ /** Optional source description for the episode. */
65
+ sourceDescription?: string;
66
+ /** Optional source description (snake_case payload). */
67
+ source_description?: string;
62
68
  /** Optional episode creation timestamp. */
63
69
  created_at?: string;
64
70
  /** Optional labels associated with the episode. */
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/src/types/index.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,MAAM,WAAW,cAAc;IAC7B,+CAA+C;IAC/C,QAAQ,EAAE,MAAM,CAAC;IACjB,0DAA0D;IAC1D,aAAa,EAAE,MAAM,CAAC;IACtB,iEAAiE;IACjE,iBAAiB,EAAE,MAAM,CAAC;CAC3B;AAED,0DAA0D;AAC1D,MAAM,WAAW,YAAY;IAC3B,sCAAsC;IACtC,IAAI,EAAE,MAAM,CAAC;IACb,mCAAmC;IACnC,IAAI,EAAE,MAAM,CAAC;IACb,6CAA6C;IAC7C,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,+CAA+C;IAC/C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,uCAAuC;IACvC,WAAW,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IAC7C,uCAAuC;IACvC,WAAW,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;CAC9C;AAED,kDAAkD;AAClD,MAAM,WAAW,qBAAqB;IACpC,mCAAmC;IACnC,KAAK,EAAE,YAAY,EAAE,CAAC;CACvB;AAED,0DAA0D;AAC1D,MAAM,WAAW,YAAY;IAC3B,sCAAsC;IACtC,IAAI,EAAE,MAAM,CAAC;IACb,gCAAgC;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,4CAA4C;IAC5C,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,gDAAgD;IAChD,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;CACnB;AAED,kDAAkD;AAClD,MAAM,WAAW,qBAAqB;IACpC,mCAAmC;IACnC,KAAK,EAAE,YAAY,EAAE,CAAC;CACvB;AAED,iDAAiD;AACjD,MAAM,WAAW,eAAe;IAC9B,yCAAyC;IACzC,IAAI,EAAE,MAAM,CAAC;IACb,6BAA6B;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,4BAA4B;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,oCAAoC;IACpC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,2CAA2C;IAC3C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,mDAAmD;IACnD,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;CACnB"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/src/types/index.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,MAAM,WAAW,cAAc;IAC7B,+CAA+C;IAC/C,QAAQ,EAAE,MAAM,CAAC;IACjB,0DAA0D;IAC1D,aAAa,EAAE,MAAM,CAAC;IACtB,mEAAmE;IACnE,cAAc,EAAE,MAAM,CAAC;IACvB,6DAA6D;IAC7D,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,0DAA0D;AAC1D,MAAM,WAAW,YAAY;IAC3B,sCAAsC;IACtC,IAAI,EAAE,MAAM,CAAC;IACb,mCAAmC;IACnC,IAAI,EAAE,MAAM,CAAC;IACb,6CAA6C;IAC7C,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,+CAA+C;IAC/C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,uCAAuC;IACvC,WAAW,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IAC7C,uCAAuC;IACvC,WAAW,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;CAC9C;AAED,kDAAkD;AAClD,MAAM,WAAW,qBAAqB;IACpC,mCAAmC;IACnC,KAAK,EAAE,YAAY,EAAE,CAAC;CACvB;AAED,0DAA0D;AAC1D,MAAM,WAAW,YAAY;IAC3B,sCAAsC;IACtC,IAAI,EAAE,MAAM,CAAC;IACb,gCAAgC;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,4CAA4C;IAC5C,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,gDAAgD;IAChD,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;CACnB;AAED,kDAAkD;AAClD,MAAM,WAAW,qBAAqB;IACpC,mCAAmC;IACnC,KAAK,EAAE,YAAY,EAAE,CAAC;CACvB;AAED,iDAAiD;AACjD,MAAM,WAAW,eAAe;IAC9B,yCAAyC;IACzC,IAAI,EAAE,MAAM,CAAC;IACb,6BAA6B;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,4BAA4B;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,oCAAoC;IACpC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,mDAAmD;IACnD,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,wDAAwD;IACxD,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,2CAA2C;IAC3C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,mDAAmD;IACnD,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;CACnB"}