opencode-graphiti 0.1.0
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 +21 -0
- package/README.md +176 -0
- package/esm/_dnt.shims.d.ts +6 -0
- package/esm/_dnt.shims.d.ts.map +1 -0
- package/esm/_dnt.shims.js +61 -0
- package/esm/mod.d.ts +2 -0
- package/esm/mod.d.ts.map +1 -0
- package/esm/mod.js +1 -0
- package/esm/package.json +3 -0
- package/esm/src/config.d.ts +3 -0
- package/esm/src/config.d.ts.map +1 -0
- package/esm/src/config.js +43 -0
- package/esm/src/index.d.ts +4 -0
- package/esm/src/index.d.ts.map +1 -0
- package/esm/src/index.js +436 -0
- package/esm/src/services/client.d.ts +37 -0
- package/esm/src/services/client.d.ts.map +1 -0
- package/esm/src/services/client.js +201 -0
- package/esm/src/services/compaction.d.ts +93 -0
- package/esm/src/services/compaction.d.ts.map +1 -0
- package/esm/src/services/compaction.js +144 -0
- package/esm/src/services/context.d.ts +3 -0
- package/esm/src/services/context.d.ts.map +1 -0
- package/esm/src/services/context.js +36 -0
- package/esm/src/services/logger.d.ts +7 -0
- package/esm/src/services/logger.d.ts.map +1 -0
- package/esm/src/services/logger.js +22 -0
- package/esm/src/types/index.d.ts +48 -0
- package/esm/src/types/index.d.ts.map +1 -0
- package/esm/src/types/index.js +1 -0
- package/package.json +34 -0
- package/script/_dnt.shims.d.ts +6 -0
- package/script/_dnt.shims.d.ts.map +1 -0
- package/script/_dnt.shims.js +65 -0
- package/script/mod.d.ts +2 -0
- package/script/mod.d.ts.map +1 -0
- package/script/mod.js +17 -0
- package/script/package.json +3 -0
- package/script/src/config.d.ts +3 -0
- package/script/src/config.d.ts.map +1 -0
- package/script/src/config.js +79 -0
- package/script/src/index.d.ts +4 -0
- package/script/src/index.d.ts.map +1 -0
- package/script/src/index.js +441 -0
- package/script/src/services/client.d.ts +37 -0
- package/script/src/services/client.d.ts.map +1 -0
- package/script/src/services/client.js +238 -0
- package/script/src/services/compaction.d.ts +93 -0
- package/script/src/services/compaction.d.ts.map +1 -0
- package/script/src/services/compaction.js +149 -0
- package/script/src/services/context.d.ts +3 -0
- package/script/src/services/context.d.ts.map +1 -0
- package/script/src/services/context.js +39 -0
- package/script/src/services/logger.d.ts +7 -0
- package/script/src/services/logger.d.ts.map +1 -0
- package/script/src/services/logger.js +61 -0
- package/script/src/types/index.d.ts +48 -0
- package/script/src/types/index.d.ts.map +1 -0
- package/script/src/types/index.js +2 -0
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.GraphitiClient = void 0;
|
|
37
|
+
const dntShim = __importStar(require("../../_dnt.shims.js"));
|
|
38
|
+
const index_js_1 = require("@modelcontextprotocol/sdk/client/index.js");
|
|
39
|
+
const streamableHttp_js_1 = require("@modelcontextprotocol/sdk/client/streamableHttp.js");
|
|
40
|
+
const logger_js_1 = require("./logger.js");
|
|
41
|
+
class GraphitiClient {
|
|
42
|
+
constructor(endpoint) {
|
|
43
|
+
Object.defineProperty(this, "client", {
|
|
44
|
+
enumerable: true,
|
|
45
|
+
configurable: true,
|
|
46
|
+
writable: true,
|
|
47
|
+
value: void 0
|
|
48
|
+
});
|
|
49
|
+
Object.defineProperty(this, "transport", {
|
|
50
|
+
enumerable: true,
|
|
51
|
+
configurable: true,
|
|
52
|
+
writable: true,
|
|
53
|
+
value: void 0
|
|
54
|
+
});
|
|
55
|
+
Object.defineProperty(this, "connected", {
|
|
56
|
+
enumerable: true,
|
|
57
|
+
configurable: true,
|
|
58
|
+
writable: true,
|
|
59
|
+
value: false
|
|
60
|
+
});
|
|
61
|
+
Object.defineProperty(this, "endpoint", {
|
|
62
|
+
enumerable: true,
|
|
63
|
+
configurable: true,
|
|
64
|
+
writable: true,
|
|
65
|
+
value: void 0
|
|
66
|
+
});
|
|
67
|
+
this.endpoint = endpoint;
|
|
68
|
+
this.client = new index_js_1.Client({ name: "opencode-graphiti", version: "0.1.0" });
|
|
69
|
+
const url = new dntShim.dntGlobalThis.URL(endpoint);
|
|
70
|
+
this.transport = new streamableHttp_js_1.StreamableHTTPClientTransport(url);
|
|
71
|
+
}
|
|
72
|
+
async connect() {
|
|
73
|
+
if (this.connected)
|
|
74
|
+
return true;
|
|
75
|
+
try {
|
|
76
|
+
await this.client.connect(this.transport);
|
|
77
|
+
this.connected = true;
|
|
78
|
+
logger_js_1.logger.info("Connected to Graphiti MCP server at", this.endpoint);
|
|
79
|
+
return true;
|
|
80
|
+
}
|
|
81
|
+
catch (err) {
|
|
82
|
+
logger_js_1.logger.error("Failed to connect to Graphiti:", err);
|
|
83
|
+
return false;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
async disconnect() {
|
|
87
|
+
if (this.connected) {
|
|
88
|
+
await this.client.close();
|
|
89
|
+
this.connected = false;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
async callTool(name, args) {
|
|
93
|
+
if (!this.connected) {
|
|
94
|
+
const ok = await this.connect();
|
|
95
|
+
if (!ok)
|
|
96
|
+
throw new Error("Not connected to Graphiti");
|
|
97
|
+
}
|
|
98
|
+
// Sanitize arguments: omit task_id (and others) if null or undefined
|
|
99
|
+
const sanitizedArgs = Object.fromEntries(Object.entries(args).filter(([_, v]) => v !== null && v !== undefined));
|
|
100
|
+
try {
|
|
101
|
+
const result = await this.client.callTool({
|
|
102
|
+
name,
|
|
103
|
+
arguments: sanitizedArgs,
|
|
104
|
+
});
|
|
105
|
+
return this.parseToolResult(result);
|
|
106
|
+
}
|
|
107
|
+
catch (err) {
|
|
108
|
+
if (this.isSessionExpired(err)) {
|
|
109
|
+
logger_js_1.logger.warn("Graphiti session expired, reconnecting...");
|
|
110
|
+
await this.reconnect();
|
|
111
|
+
const result = await this.client.callTool({
|
|
112
|
+
name,
|
|
113
|
+
arguments: sanitizedArgs,
|
|
114
|
+
});
|
|
115
|
+
return this.parseToolResult(result);
|
|
116
|
+
}
|
|
117
|
+
throw err;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
isSessionExpired(err) {
|
|
121
|
+
return !!(err &&
|
|
122
|
+
typeof err === "object" &&
|
|
123
|
+
"code" in err &&
|
|
124
|
+
err.code === 404);
|
|
125
|
+
}
|
|
126
|
+
async reconnect() {
|
|
127
|
+
this.connected = false;
|
|
128
|
+
try {
|
|
129
|
+
await this.transport.close();
|
|
130
|
+
}
|
|
131
|
+
catch {
|
|
132
|
+
// ignore transport close errors
|
|
133
|
+
}
|
|
134
|
+
this.transport = new streamableHttp_js_1.StreamableHTTPClientTransport(new URL(this.endpoint));
|
|
135
|
+
await this.client.connect(this.transport);
|
|
136
|
+
this.connected = true;
|
|
137
|
+
logger_js_1.logger.info("Reconnected to Graphiti MCP server");
|
|
138
|
+
}
|
|
139
|
+
// Public for testing
|
|
140
|
+
parseToolResult(result) {
|
|
141
|
+
const typedResult = result;
|
|
142
|
+
const content = typedResult.content;
|
|
143
|
+
if (!Array.isArray(content) || content.length === 0)
|
|
144
|
+
return result;
|
|
145
|
+
const text = content.find((item) => item?.type === "text")?.text;
|
|
146
|
+
if (text === undefined)
|
|
147
|
+
return result;
|
|
148
|
+
if (typeof text !== "string") {
|
|
149
|
+
try {
|
|
150
|
+
return JSON.parse(String(text));
|
|
151
|
+
}
|
|
152
|
+
catch {
|
|
153
|
+
return text;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
try {
|
|
157
|
+
return JSON.parse(text);
|
|
158
|
+
}
|
|
159
|
+
catch {
|
|
160
|
+
return text;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
async addEpisode(params) {
|
|
164
|
+
await this.callTool("add_memory", {
|
|
165
|
+
name: params.name,
|
|
166
|
+
episode_body: params.episodeBody,
|
|
167
|
+
group_id: params.groupId,
|
|
168
|
+
source: params.source || "text",
|
|
169
|
+
source_description: params.sourceDescription || "",
|
|
170
|
+
});
|
|
171
|
+
logger_js_1.logger.debug("Added episode:", params.name);
|
|
172
|
+
}
|
|
173
|
+
async searchFacts(params) {
|
|
174
|
+
try {
|
|
175
|
+
const result = await this.callTool("search_memory_facts", {
|
|
176
|
+
query: params.query,
|
|
177
|
+
group_ids: params.groupIds,
|
|
178
|
+
max_facts: params.maxFacts || 10,
|
|
179
|
+
});
|
|
180
|
+
if (Array.isArray(result))
|
|
181
|
+
return result;
|
|
182
|
+
if (result &&
|
|
183
|
+
typeof result === "object" &&
|
|
184
|
+
Array.isArray(result.facts)) {
|
|
185
|
+
return result.facts;
|
|
186
|
+
}
|
|
187
|
+
return [];
|
|
188
|
+
}
|
|
189
|
+
catch (err) {
|
|
190
|
+
logger_js_1.logger.error("searchFacts error:", err);
|
|
191
|
+
return [];
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
async searchNodes(params) {
|
|
195
|
+
try {
|
|
196
|
+
const result = await this.callTool("search_nodes", {
|
|
197
|
+
query: params.query,
|
|
198
|
+
group_ids: params.groupIds,
|
|
199
|
+
max_nodes: params.maxNodes || 10,
|
|
200
|
+
});
|
|
201
|
+
if (Array.isArray(result))
|
|
202
|
+
return result;
|
|
203
|
+
if (result &&
|
|
204
|
+
typeof result === "object" &&
|
|
205
|
+
Array.isArray(result.nodes)) {
|
|
206
|
+
return result.nodes;
|
|
207
|
+
}
|
|
208
|
+
return [];
|
|
209
|
+
}
|
|
210
|
+
catch (err) {
|
|
211
|
+
logger_js_1.logger.error("searchNodes error:", err);
|
|
212
|
+
return [];
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
async getEpisodes(params) {
|
|
216
|
+
try {
|
|
217
|
+
const result = await this.callTool("get_episodes", {
|
|
218
|
+
group_ids: params.groupIds,
|
|
219
|
+
max_episodes: params.maxEpisodes || 10,
|
|
220
|
+
});
|
|
221
|
+
return result || [];
|
|
222
|
+
}
|
|
223
|
+
catch (err) {
|
|
224
|
+
logger_js_1.logger.error("getEpisodes error:", err);
|
|
225
|
+
return [];
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
async getStatus() {
|
|
229
|
+
try {
|
|
230
|
+
await this.callTool("get_status", {});
|
|
231
|
+
return true;
|
|
232
|
+
}
|
|
233
|
+
catch {
|
|
234
|
+
return false;
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
exports.GraphitiClient = GraphitiClient;
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import type { GraphitiConfig } from "../types/index.js";
|
|
2
|
+
export interface CompactionDependencies {
|
|
3
|
+
sdkClient: {
|
|
4
|
+
session: {
|
|
5
|
+
summarize: (options: {
|
|
6
|
+
path: {
|
|
7
|
+
id: string;
|
|
8
|
+
};
|
|
9
|
+
body?: {
|
|
10
|
+
providerID: string;
|
|
11
|
+
modelID: string;
|
|
12
|
+
};
|
|
13
|
+
query?: {
|
|
14
|
+
directory?: string;
|
|
15
|
+
};
|
|
16
|
+
}) => Promise<unknown>;
|
|
17
|
+
promptAsync: (options: {
|
|
18
|
+
path: {
|
|
19
|
+
id: string;
|
|
20
|
+
};
|
|
21
|
+
body?: {
|
|
22
|
+
parts: Array<{
|
|
23
|
+
type: "text";
|
|
24
|
+
text: string;
|
|
25
|
+
}>;
|
|
26
|
+
};
|
|
27
|
+
query?: {
|
|
28
|
+
directory?: string;
|
|
29
|
+
};
|
|
30
|
+
}) => Promise<unknown>;
|
|
31
|
+
};
|
|
32
|
+
tui: {
|
|
33
|
+
showToast: (options?: {
|
|
34
|
+
body?: {
|
|
35
|
+
title?: string;
|
|
36
|
+
message: string;
|
|
37
|
+
variant: "info" | "success" | "warning" | "error";
|
|
38
|
+
duration?: number;
|
|
39
|
+
};
|
|
40
|
+
query?: {
|
|
41
|
+
directory?: string;
|
|
42
|
+
};
|
|
43
|
+
}) => Promise<unknown>;
|
|
44
|
+
};
|
|
45
|
+
provider: {
|
|
46
|
+
list: (options?: {
|
|
47
|
+
directory?: string;
|
|
48
|
+
}) => Promise<unknown>;
|
|
49
|
+
};
|
|
50
|
+
};
|
|
51
|
+
directory: string;
|
|
52
|
+
}
|
|
53
|
+
export declare function createPreemptiveCompactionHandler(config: Pick<GraphitiConfig, "compactionThreshold" | "minTokensForCompaction" | "compactionCooldownMs" | "autoResumeAfterCompaction">, deps: CompactionDependencies): {
|
|
54
|
+
checkAndTriggerCompaction(sessionId: string, tokens: {
|
|
55
|
+
input: number;
|
|
56
|
+
output: number;
|
|
57
|
+
reasoning: number;
|
|
58
|
+
cache: {
|
|
59
|
+
read: number;
|
|
60
|
+
write: number;
|
|
61
|
+
};
|
|
62
|
+
}, providerID: string, modelID: string): Promise<void>;
|
|
63
|
+
};
|
|
64
|
+
export declare function handleCompaction(params: {
|
|
65
|
+
client: {
|
|
66
|
+
addEpisode: (args: {
|
|
67
|
+
name: string;
|
|
68
|
+
episodeBody: string;
|
|
69
|
+
groupId?: string;
|
|
70
|
+
source?: "text" | "json" | "message";
|
|
71
|
+
sourceDescription?: string;
|
|
72
|
+
}) => Promise<void>;
|
|
73
|
+
};
|
|
74
|
+
config: GraphitiConfig;
|
|
75
|
+
groupId: string;
|
|
76
|
+
summary: string;
|
|
77
|
+
sessionId: string;
|
|
78
|
+
}): Promise<void>;
|
|
79
|
+
export declare function getCompactionContext(params: {
|
|
80
|
+
client: {
|
|
81
|
+
searchFacts: (args: {
|
|
82
|
+
query: string;
|
|
83
|
+
groupIds?: string[];
|
|
84
|
+
maxFacts?: number;
|
|
85
|
+
}) => Promise<Array<{
|
|
86
|
+
fact: string;
|
|
87
|
+
}>>;
|
|
88
|
+
};
|
|
89
|
+
config: GraphitiConfig;
|
|
90
|
+
groupId: string;
|
|
91
|
+
contextStrings: string[];
|
|
92
|
+
}): Promise<string[]>;
|
|
93
|
+
//# sourceMappingURL=compaction.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compaction.d.ts","sourceRoot":"","sources":["../../../src/src/services/compaction.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAGxD,MAAM,WAAW,sBAAsB;IACrC,SAAS,EAAE;QACT,OAAO,EAAE;YACP,SAAS,EAAE,CAAC,OAAO,EAAE;gBACnB,IAAI,EAAE;oBAAE,EAAE,EAAE,MAAM,CAAA;iBAAE,CAAC;gBACrB,IAAI,CAAC,EAAE;oBAAE,UAAU,EAAE,MAAM,CAAC;oBAAC,OAAO,EAAE,MAAM,CAAA;iBAAE,CAAC;gBAC/C,KAAK,CAAC,EAAE;oBAAE,SAAS,CAAC,EAAE,MAAM,CAAA;iBAAE,CAAC;aAChC,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;YACvB,WAAW,EAAE,CAAC,OAAO,EAAE;gBACrB,IAAI,EAAE;oBAAE,EAAE,EAAE,MAAM,CAAA;iBAAE,CAAC;gBACrB,IAAI,CAAC,EAAE;oBAAE,KAAK,EAAE,KAAK,CAAC;wBAAE,IAAI,EAAE,MAAM,CAAC;wBAAC,IAAI,EAAE,MAAM,CAAA;qBAAE,CAAC,CAAA;iBAAE,CAAC;gBACxD,KAAK,CAAC,EAAE;oBAAE,SAAS,CAAC,EAAE,MAAM,CAAA;iBAAE,CAAC;aAChC,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;SACxB,CAAC;QACF,GAAG,EAAE;YACH,SAAS,EAAE,CAAC,OAAO,CAAC,EAAE;gBACpB,IAAI,CAAC,EAAE;oBACL,KAAK,CAAC,EAAE,MAAM,CAAC;oBACf,OAAO,EAAE,MAAM,CAAC;oBAChB,OAAO,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS,GAAG,OAAO,CAAC;oBAClD,QAAQ,CAAC,EAAE,MAAM,CAAC;iBACnB,CAAC;gBACF,KAAK,CAAC,EAAE;oBAAE,SAAS,CAAC,EAAE,MAAM,CAAA;iBAAE,CAAC;aAChC,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;SACxB,CAAC;QACF,QAAQ,EAAE;YACR,IAAI,EAAE,CAAC,OAAO,CAAC,EAAE;gBAAE,SAAS,CAAC,EAAE,MAAM,CAAA;aAAE,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;SAC9D,CAAC;KACH,CAAC;IACF,SAAS,EAAE,MAAM,CAAC;CACnB;AAwDD,wBAAgB,iCAAiC,CAC/C,MAAM,EAAE,IAAI,CACV,cAAc,EACZ,qBAAqB,GACrB,wBAAwB,GACxB,sBAAsB,GACtB,2BAA2B,CAC9B,EACD,IAAI,EAAE,sBAAsB,GAC3B;IACD,yBAAyB,CACvB,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE;QACN,KAAK,EAAE,MAAM,CAAC;QACd,MAAM,EAAE,MAAM,CAAC;QACf,SAAS,EAAE,MAAM,CAAC;QAClB,KAAK,EAAE;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,KAAK,EAAE,MAAM,CAAA;SAAE,CAAC;KACxC,EACD,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,IAAI,CAAC,CAAC;CAClB,CAiFA;AAED,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,MAAM,EAAE,cAAc,CAAC;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;CACnB,GAAG,OAAO,CAAC,IAAI,CAAC,CAiBhB;AAED,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,KAAK,CAAC;YAAE,IAAI,EAAE,MAAM,CAAA;SAAE,CAAC,CAAC,CAAC;KACxC,CAAC;IACF,MAAM,EAAE,cAAc,CAAC;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,cAAc,EAAE,MAAM,EAAE,CAAC;CAC1B,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAyBpB"}
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createPreemptiveCompactionHandler = createPreemptiveCompactionHandler;
|
|
4
|
+
exports.handleCompaction = handleCompaction;
|
|
5
|
+
exports.getCompactionContext = getCompactionContext;
|
|
6
|
+
const logger_js_1 = require("./logger.js");
|
|
7
|
+
const DEFAULT_CONTEXT_LIMIT = 200_000;
|
|
8
|
+
const RESUME_DELAY_MS = 500;
|
|
9
|
+
const delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
10
|
+
const buildModelKey = (providerID, modelID) => `${providerID}/${modelID}`;
|
|
11
|
+
const resolveContextLimit = async (providerID, modelID, deps, state) => {
|
|
12
|
+
const modelKey = buildModelKey(providerID, modelID);
|
|
13
|
+
const cached = state.contextLimitCache.get(modelKey);
|
|
14
|
+
if (cached)
|
|
15
|
+
return cached;
|
|
16
|
+
try {
|
|
17
|
+
const providers = await deps.sdkClient.provider.list({
|
|
18
|
+
directory: deps.directory,
|
|
19
|
+
});
|
|
20
|
+
const list = providers.providers ?? [];
|
|
21
|
+
for (const provider of list) {
|
|
22
|
+
const providerInfo = provider;
|
|
23
|
+
if (providerInfo.id !== providerID)
|
|
24
|
+
continue;
|
|
25
|
+
const models = providerInfo.models ?? [];
|
|
26
|
+
for (const model of models) {
|
|
27
|
+
const modelInfo = model;
|
|
28
|
+
if (modelInfo.id !== modelID)
|
|
29
|
+
continue;
|
|
30
|
+
const contextLimit = modelInfo.limit?.context;
|
|
31
|
+
if (typeof contextLimit === "number" && contextLimit > 0) {
|
|
32
|
+
state.contextLimitCache.set(modelKey, contextLimit);
|
|
33
|
+
return contextLimit;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
catch (err) {
|
|
39
|
+
logger_js_1.logger.warn("Failed to fetch provider context limit", err);
|
|
40
|
+
}
|
|
41
|
+
state.contextLimitCache.set(modelKey, DEFAULT_CONTEXT_LIMIT);
|
|
42
|
+
return DEFAULT_CONTEXT_LIMIT;
|
|
43
|
+
};
|
|
44
|
+
function createPreemptiveCompactionHandler(config, deps) {
|
|
45
|
+
const state = {
|
|
46
|
+
lastCompactionTime: new Map(),
|
|
47
|
+
compactionInProgress: new Set(),
|
|
48
|
+
contextLimitCache: new Map(),
|
|
49
|
+
};
|
|
50
|
+
const checkAndTriggerCompaction = async (sessionId, tokens, providerID, modelID) => {
|
|
51
|
+
const totalTokens = tokens.input + tokens.cache.read + tokens.output +
|
|
52
|
+
tokens.reasoning;
|
|
53
|
+
if (totalTokens < (config.minTokensForCompaction ?? 0))
|
|
54
|
+
return;
|
|
55
|
+
if (state.compactionInProgress.has(sessionId))
|
|
56
|
+
return;
|
|
57
|
+
const lastCompaction = state.lastCompactionTime.get(sessionId) ?? 0;
|
|
58
|
+
if (Date.now() - lastCompaction < (config.compactionCooldownMs ?? 0)) {
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
const contextLimit = await resolveContextLimit(providerID, modelID, deps, state);
|
|
62
|
+
const usageRatio = totalTokens / contextLimit;
|
|
63
|
+
if (usageRatio < (config.compactionThreshold ?? 1))
|
|
64
|
+
return;
|
|
65
|
+
state.compactionInProgress.add(sessionId);
|
|
66
|
+
try {
|
|
67
|
+
await deps.sdkClient.tui.showToast({
|
|
68
|
+
body: {
|
|
69
|
+
title: "Graphiti",
|
|
70
|
+
message: "Compacting session to preserve context...",
|
|
71
|
+
variant: "info",
|
|
72
|
+
duration: 3000,
|
|
73
|
+
},
|
|
74
|
+
query: { directory: deps.directory },
|
|
75
|
+
});
|
|
76
|
+
await deps.sdkClient.session.summarize({
|
|
77
|
+
path: { id: sessionId },
|
|
78
|
+
body: { providerID, modelID },
|
|
79
|
+
query: { directory: deps.directory },
|
|
80
|
+
});
|
|
81
|
+
state.lastCompactionTime.set(sessionId, Date.now());
|
|
82
|
+
if (config.autoResumeAfterCompaction) {
|
|
83
|
+
await delay(RESUME_DELAY_MS);
|
|
84
|
+
await deps.sdkClient.session.promptAsync({
|
|
85
|
+
path: { id: sessionId },
|
|
86
|
+
body: { parts: [{ type: "text", text: "Continue" }] },
|
|
87
|
+
query: { directory: deps.directory },
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
logger_js_1.logger.info("Preemptive compaction triggered", {
|
|
91
|
+
sessionId,
|
|
92
|
+
providerID,
|
|
93
|
+
modelID,
|
|
94
|
+
usageRatio,
|
|
95
|
+
totalTokens,
|
|
96
|
+
contextLimit,
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
catch (err) {
|
|
100
|
+
logger_js_1.logger.error("Preemptive compaction failed", err);
|
|
101
|
+
}
|
|
102
|
+
finally {
|
|
103
|
+
state.compactionInProgress.delete(sessionId);
|
|
104
|
+
}
|
|
105
|
+
};
|
|
106
|
+
return { checkAndTriggerCompaction };
|
|
107
|
+
}
|
|
108
|
+
async function handleCompaction(params) {
|
|
109
|
+
const { client, config, groupId, summary, sessionId } = params;
|
|
110
|
+
if (!config.enableCompactionSave || !summary)
|
|
111
|
+
return;
|
|
112
|
+
try {
|
|
113
|
+
await client.addEpisode({
|
|
114
|
+
name: `Session compaction: ${sessionId}`,
|
|
115
|
+
episodeBody: summary,
|
|
116
|
+
groupId,
|
|
117
|
+
source: "text",
|
|
118
|
+
sourceDescription: "OpenCode session compaction summary",
|
|
119
|
+
});
|
|
120
|
+
logger_js_1.logger.info("Saved compaction summary to Graphiti for session", sessionId);
|
|
121
|
+
}
|
|
122
|
+
catch (err) {
|
|
123
|
+
logger_js_1.logger.error("Failed to save compaction summary:", err);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
async function getCompactionContext(params) {
|
|
127
|
+
const { client, config, groupId, contextStrings } = params;
|
|
128
|
+
try {
|
|
129
|
+
const queryText = contextStrings.slice(0, 3).join(" ").slice(0, 500);
|
|
130
|
+
if (!queryText.trim())
|
|
131
|
+
return [];
|
|
132
|
+
const facts = await client.searchFacts({
|
|
133
|
+
query: queryText,
|
|
134
|
+
groupIds: [groupId],
|
|
135
|
+
maxFacts: config.maxFacts,
|
|
136
|
+
});
|
|
137
|
+
if (facts.length === 0)
|
|
138
|
+
return [];
|
|
139
|
+
const lines = [
|
|
140
|
+
"## Persistent Knowledge (preserve these facts during compaction):",
|
|
141
|
+
...facts.map((fact) => `- ${fact.fact}`),
|
|
142
|
+
];
|
|
143
|
+
return [lines.join("\n")];
|
|
144
|
+
}
|
|
145
|
+
catch (err) {
|
|
146
|
+
logger_js_1.logger.error("Failed to get compaction context:", err);
|
|
147
|
+
return [];
|
|
148
|
+
}
|
|
149
|
+
}
|
|
@@ -0,0 +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,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,YAAY,EAAE,EACrB,KAAK,EAAE,YAAY,EAAE,GACpB,MAAM,CA0CR"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.formatMemoryContext = formatMemoryContext;
|
|
4
|
+
function formatMemoryContext(facts, nodes) {
|
|
5
|
+
const sections = [];
|
|
6
|
+
sections.push("# Persistent Memory (from Graphiti Knowledge Graph)");
|
|
7
|
+
sections.push("");
|
|
8
|
+
sections.push("The following information was retrieved from your persistent memory.");
|
|
9
|
+
sections.push("Use this context to inform your responses, but do not mention it unless asked.");
|
|
10
|
+
sections.push("");
|
|
11
|
+
if (facts.length > 0) {
|
|
12
|
+
sections.push("## Known Facts");
|
|
13
|
+
for (const fact of facts) {
|
|
14
|
+
const entities = [];
|
|
15
|
+
if (fact.source_node?.name)
|
|
16
|
+
entities.push(fact.source_node.name);
|
|
17
|
+
if (fact.target_node?.name)
|
|
18
|
+
entities.push(fact.target_node.name);
|
|
19
|
+
const entityStr = entities.length > 0
|
|
20
|
+
? ` [${entities.join(" -> ")}]`
|
|
21
|
+
: "";
|
|
22
|
+
sections.push(`- ${fact.fact}${entityStr}`);
|
|
23
|
+
}
|
|
24
|
+
sections.push("");
|
|
25
|
+
}
|
|
26
|
+
if (nodes.length > 0) {
|
|
27
|
+
sections.push("## Known Entities");
|
|
28
|
+
for (const node of nodes) {
|
|
29
|
+
const labels = node.labels?.length ? ` (${node.labels.join(", ")})` : "";
|
|
30
|
+
const summary = node.summary ? `: ${node.summary}` : "";
|
|
31
|
+
sections.push(`- **${node.name}**${labels}${summary}`);
|
|
32
|
+
}
|
|
33
|
+
sections.push("");
|
|
34
|
+
}
|
|
35
|
+
if (facts.length === 0 && nodes.length === 0) {
|
|
36
|
+
return "";
|
|
37
|
+
}
|
|
38
|
+
return sections.join("\n");
|
|
39
|
+
}
|
|
@@ -0,0 +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"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
+
};
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.logger = void 0;
|
|
40
|
+
const dntShim = __importStar(require("../../_dnt.shims.js"));
|
|
41
|
+
const node_process_1 = __importDefault(require("node:process"));
|
|
42
|
+
const console = dntShim.dntGlobalThis.console;
|
|
43
|
+
const PREFIX = "[graphiti]";
|
|
44
|
+
exports.logger = {
|
|
45
|
+
info: (...args) => {
|
|
46
|
+
if (node_process_1.default.env.GRAPHITI_DEBUG)
|
|
47
|
+
console.log(PREFIX, ...args);
|
|
48
|
+
},
|
|
49
|
+
warn: (...args) => {
|
|
50
|
+
if (node_process_1.default.env.GRAPHITI_DEBUG)
|
|
51
|
+
console.warn(PREFIX, ...args);
|
|
52
|
+
},
|
|
53
|
+
error: (...args) => {
|
|
54
|
+
if (node_process_1.default.env.GRAPHITI_DEBUG)
|
|
55
|
+
console.error(PREFIX, ...args);
|
|
56
|
+
},
|
|
57
|
+
debug: (...args) => {
|
|
58
|
+
if (node_process_1.default.env.GRAPHITI_DEBUG)
|
|
59
|
+
console.debug(PREFIX, ...args);
|
|
60
|
+
},
|
|
61
|
+
};
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
export interface GraphitiConfig {
|
|
2
|
+
endpoint: string;
|
|
3
|
+
groupIdPrefix: string;
|
|
4
|
+
maxFacts: number;
|
|
5
|
+
maxNodes: number;
|
|
6
|
+
maxEpisodes: number;
|
|
7
|
+
injectOnFirstMessage: boolean;
|
|
8
|
+
enableCompactionSave: boolean;
|
|
9
|
+
compactionThreshold?: number;
|
|
10
|
+
minTokensForCompaction?: number;
|
|
11
|
+
compactionCooldownMs?: number;
|
|
12
|
+
autoResumeAfterCompaction?: boolean;
|
|
13
|
+
}
|
|
14
|
+
export interface GraphitiFact {
|
|
15
|
+
uuid: string;
|
|
16
|
+
fact: string;
|
|
17
|
+
valid_at?: string;
|
|
18
|
+
invalid_at?: string;
|
|
19
|
+
source_node?: {
|
|
20
|
+
name: string;
|
|
21
|
+
uuid: string;
|
|
22
|
+
};
|
|
23
|
+
target_node?: {
|
|
24
|
+
name: string;
|
|
25
|
+
uuid: string;
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
export interface GraphitiFactsResponse {
|
|
29
|
+
facts: GraphitiFact[];
|
|
30
|
+
}
|
|
31
|
+
export interface GraphitiNode {
|
|
32
|
+
uuid: string;
|
|
33
|
+
name: string;
|
|
34
|
+
summary?: string;
|
|
35
|
+
labels?: string[];
|
|
36
|
+
}
|
|
37
|
+
export interface GraphitiNodesResponse {
|
|
38
|
+
nodes: GraphitiNode[];
|
|
39
|
+
}
|
|
40
|
+
export interface GraphitiEpisode {
|
|
41
|
+
uuid: string;
|
|
42
|
+
name: string;
|
|
43
|
+
content: string;
|
|
44
|
+
source?: string;
|
|
45
|
+
created_at?: string;
|
|
46
|
+
labels?: string[];
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/src/types/index.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,oBAAoB,EAAE,OAAO,CAAC;IAC9B,oBAAoB,EAAE,OAAO,CAAC;IAE9B,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,yBAAyB,CAAC,EAAE,OAAO,CAAC;CACrC;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IAC7C,WAAW,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;CAC9C;AAED,MAAM,WAAW,qBAAqB;IACpC,KAAK,EAAE,YAAY,EAAE,CAAC;CACvB;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;CACnB;AAED,MAAM,WAAW,qBAAqB;IACpC,KAAK,EAAE,YAAY,EAAE,CAAC;CACvB;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;CACnB"}
|