opencode-graphiti 0.1.6 → 0.1.7
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/README.md +35 -18
- package/esm/src/handlers/chat.d.ts.map +1 -1
- package/esm/src/handlers/chat.js +31 -20
- package/esm/src/handlers/event.js +1 -1
- package/esm/src/session.d.ts +1 -1
- package/esm/src/session.d.ts.map +1 -1
- package/esm/src/session.js +1 -1
- package/package.json +1 -1
- package/script/src/handlers/chat.d.ts.map +1 -1
- package/script/src/handlers/chat.js +31 -20
- package/script/src/handlers/event.js +1 -1
- package/script/src/session.d.ts +1 -1
- package/script/src/session.d.ts.map +1 -1
- package/script/src/session.js +1 -1
package/README.md
CHANGED
|
@@ -22,12 +22,16 @@ reminded of recent project context — regardless of what survived the summary.
|
|
|
22
22
|
|
|
23
23
|
This plugin connects to a Graphiti MCP server and:
|
|
24
24
|
|
|
25
|
-
-
|
|
26
|
-
-
|
|
25
|
+
- Searches Graphiti for relevant facts and entities on each user message
|
|
26
|
+
- Injects memories into the system prompt via
|
|
27
|
+
`experimental.chat.system.transform`, keeping session titles clean
|
|
28
|
+
- Detects context drift using Jaccard similarity and re-injects when the
|
|
29
|
+
conversation topic shifts
|
|
27
30
|
- Buffers user and assistant messages, flushing them to Graphiti on idle or
|
|
28
31
|
before compaction
|
|
29
32
|
- Preserves key facts during context compaction
|
|
30
33
|
- Saves compaction summaries as episodes so knowledge survives across boundaries
|
|
34
|
+
- Annotates stale facts and filters expired ones automatically
|
|
31
35
|
- Scopes memories per project (and per user) using directory-based group IDs
|
|
32
36
|
|
|
33
37
|
## Prerequisites
|
|
@@ -104,8 +108,12 @@ Create a config file at `~/.config/opencode/graphiti.jsonc`:
|
|
|
104
108
|
// Prefix for project group IDs (e.g. "opencode-my-project")
|
|
105
109
|
"groupIdPrefix": "opencode",
|
|
106
110
|
|
|
107
|
-
//
|
|
108
|
-
|
|
111
|
+
// Jaccard similarity threshold (0–1) below which memory is re-injected
|
|
112
|
+
// Lower values mean the topic must drift further before re-injection
|
|
113
|
+
"driftThreshold": 0.5,
|
|
114
|
+
|
|
115
|
+
// Number of days after which facts are annotated as stale
|
|
116
|
+
"factStaleDays": 30
|
|
109
117
|
}
|
|
110
118
|
```
|
|
111
119
|
|
|
@@ -114,27 +122,36 @@ values.
|
|
|
114
122
|
|
|
115
123
|
## How It Works
|
|
116
124
|
|
|
117
|
-
### Memory
|
|
125
|
+
### Memory Search and Caching (`chat.message`)
|
|
118
126
|
|
|
119
|
-
On
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
127
|
+
On each user message the plugin searches Graphiti for facts and entities
|
|
128
|
+
relevant to the message content. Results are split into project and user scopes
|
|
129
|
+
(70% / 30% budget), deduplicated, filtered for validity, annotated with
|
|
130
|
+
staleness if older than `factStaleDays`, and formatted as Markdown. The
|
|
131
|
+
formatted context is cached on the session state for the system prompt hook to
|
|
132
|
+
pick up.
|
|
123
133
|
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
field is unavailable, the plugin falls back to prepending synthetic parts.
|
|
134
|
+
On the very first message of a session, the plugin also loads the most recent
|
|
135
|
+
session snapshot episode to prime the conversation with prior context.
|
|
127
136
|
|
|
128
137
|
The injection budget is calculated dynamically: 5% of the model's context limit
|
|
129
138
|
(resolved from the provider list) multiplied by 4 characters per token.
|
|
130
139
|
|
|
131
|
-
###
|
|
140
|
+
### System Prompt Injection (`experimental.chat.system.transform`)
|
|
141
|
+
|
|
142
|
+
A separate hook reads the cached memory context and appends it to the system
|
|
143
|
+
prompt array. This approach keeps memory out of user message parts, which
|
|
144
|
+
prevents it from influencing session titles or being treated as user
|
|
145
|
+
instructions. The cache is cleared after injection so stale context is not
|
|
146
|
+
re-injected on subsequent LLM calls within the same turn.
|
|
147
|
+
|
|
148
|
+
### Drift-Based Re-injection (`chat.message`)
|
|
132
149
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
project
|
|
150
|
+
After the first injection, the plugin monitors for context drift on every user
|
|
151
|
+
message. It searches Graphiti for the current message and compares the returned
|
|
152
|
+
fact UUIDs against the previously injected set using Jaccard similarity. When
|
|
153
|
+
similarity drops below `driftThreshold` (default 0.5), the memory cache is
|
|
154
|
+
refreshed with project-scoped results only (no user scope).
|
|
138
155
|
|
|
139
156
|
### Message Buffering (`event`)
|
|
140
157
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chat.d.ts","sourceRoot":"","sources":["../../../src/src/handlers/chat.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAC;AACjD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAO5D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAGpD,KAAK,eAAe,GAAG,WAAW,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC,CAAC;AAC1D,KAAK,gBAAgB,GAAG,UAAU,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,CAAC;AACvD,KAAK,iBAAiB,GAAG,UAAU,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,CAAC;AAExD,iDAAiD;AACjD,MAAM,WAAW,eAAe;IAC9B,cAAc,EAAE,cAAc,CAAC;IAC/B,cAAc,EAAE,MAAM,CAAC;IACvB,aAAa,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,cAAc,CAAC;CACxB;AAED,+CAA+C;AAC/C,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,eAAe,
|
|
1
|
+
{"version":3,"file":"chat.d.ts","sourceRoot":"","sources":["../../../src/src/handlers/chat.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAC;AACjD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAO5D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAGpD,KAAK,eAAe,GAAG,WAAW,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC,CAAC;AAC1D,KAAK,gBAAgB,GAAG,UAAU,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,CAAC;AACvD,KAAK,iBAAiB,GAAG,UAAU,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,CAAC;AAExD,iDAAiD;AACjD,MAAM,WAAW,eAAe;IAC9B,cAAc,EAAE,cAAc,CAAC;IAC/B,cAAc,EAAE,MAAM,CAAC;IACvB,aAAa,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,cAAc,CAAC;CACxB;AAED,+CAA+C;AAC/C,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,eAAe,IAiJvC,eAAe,gBAAgB,EAAE,QAAQ,iBAAiB,mBA6EzE"}
|
package/esm/src/handlers/chat.js
CHANGED
|
@@ -96,24 +96,26 @@ export function createChatHandler(deps) {
|
|
|
96
96
|
.slice(0, characterBudget);
|
|
97
97
|
if (!memoryContext)
|
|
98
98
|
return;
|
|
99
|
-
const
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
99
|
+
const allFactUuids = [
|
|
100
|
+
...projectContext.facts.map((fact) => fact.uuid),
|
|
101
|
+
...userContext.facts.map((fact) => fact.uuid),
|
|
102
|
+
];
|
|
103
|
+
const factUuids = seedFactUuids ?? Array.from(new Set(allFactUuids));
|
|
104
104
|
state.cachedMemoryContext = memoryContext;
|
|
105
105
|
logger.info(`Cached ${projectFacts.length + userFacts.length} facts and ${projectNodes.length + userNodes.length} nodes for system prompt injection`);
|
|
106
106
|
state.lastInjectionFactUuids = factUuids;
|
|
107
107
|
};
|
|
108
108
|
const computeJaccardSimilarity = (left, right) => {
|
|
109
|
-
if (left.
|
|
109
|
+
if (left.length === 0 && right.length === 0)
|
|
110
110
|
return 1;
|
|
111
|
+
const leftSet = new Set(left);
|
|
112
|
+
const rightSet = new Set(right);
|
|
111
113
|
let intersection = 0;
|
|
112
|
-
for (const value of
|
|
113
|
-
if (
|
|
114
|
+
for (const value of leftSet) {
|
|
115
|
+
if (rightSet.has(value))
|
|
114
116
|
intersection += 1;
|
|
115
117
|
}
|
|
116
|
-
const union =
|
|
118
|
+
const union = leftSet.size + rightSet.size - intersection;
|
|
117
119
|
return union === 0 ? 1 : intersection / union;
|
|
118
120
|
};
|
|
119
121
|
return async ({ sessionID }, output) => {
|
|
@@ -144,18 +146,27 @@ export function createChatHandler(deps) {
|
|
|
144
146
|
let shouldReinject = false;
|
|
145
147
|
let currentFactUuids = null;
|
|
146
148
|
if (!shouldInjectOnFirst) {
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
149
|
+
try {
|
|
150
|
+
const driftFacts = await client.searchFacts({
|
|
151
|
+
query: messageText,
|
|
152
|
+
groupIds: [state.groupId],
|
|
153
|
+
maxFacts: 20,
|
|
154
|
+
});
|
|
155
|
+
currentFactUuids = driftFacts.map((fact) => fact.uuid);
|
|
156
|
+
const similarity = computeJaccardSimilarity(currentFactUuids, state.lastInjectionFactUuids);
|
|
157
|
+
shouldReinject = similarity < driftThreshold;
|
|
158
|
+
if (!shouldReinject) {
|
|
159
|
+
logger.debug("Skipping reinjection; similarity above threshold", {
|
|
160
|
+
sessionID,
|
|
161
|
+
similarity,
|
|
162
|
+
});
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
catch (err) {
|
|
167
|
+
logger.error("Failed to check topic drift, skipping reinjection", {
|
|
157
168
|
sessionID,
|
|
158
|
-
|
|
169
|
+
err,
|
|
159
170
|
});
|
|
160
171
|
return;
|
|
161
172
|
}
|
|
@@ -59,7 +59,7 @@ export function createEventHandler(deps) {
|
|
|
59
59
|
groupId: defaultGroupId,
|
|
60
60
|
userGroupId: defaultUserGroupId,
|
|
61
61
|
injectedMemories: false,
|
|
62
|
-
lastInjectionFactUuids:
|
|
62
|
+
lastInjectionFactUuids: [],
|
|
63
63
|
messageCount: 0,
|
|
64
64
|
pendingMessages: [],
|
|
65
65
|
contextLimit: 200_000,
|
package/esm/src/session.d.ts
CHANGED
|
@@ -11,7 +11,7 @@ export type SessionState = {
|
|
|
11
11
|
/** Whether memories have been injected into this session yet. */
|
|
12
12
|
injectedMemories: boolean;
|
|
13
13
|
/** Fact UUIDs included in the last memory injection. */
|
|
14
|
-
lastInjectionFactUuids:
|
|
14
|
+
lastInjectionFactUuids: string[];
|
|
15
15
|
/** Cached formatted memory context for system prompt injection. */
|
|
16
16
|
cachedMemoryContext?: string;
|
|
17
17
|
/** Count of messages observed in this session. */
|
package/esm/src/session.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
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,
|
|
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,MAAM,EAAE,CAAC;IACjC,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"}
|
package/esm/src/session.js
CHANGED
|
@@ -106,7 +106,7 @@ export class SessionManager {
|
|
|
106
106
|
groupId: this.defaultGroupId,
|
|
107
107
|
userGroupId: this.defaultUserGroupId,
|
|
108
108
|
injectedMemories: false,
|
|
109
|
-
lastInjectionFactUuids:
|
|
109
|
+
lastInjectionFactUuids: [],
|
|
110
110
|
cachedMemoryContext: undefined,
|
|
111
111
|
messageCount: 0,
|
|
112
112
|
pendingMessages: [],
|
package/package.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chat.d.ts","sourceRoot":"","sources":["../../../src/src/handlers/chat.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAC;AACjD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAO5D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAGpD,KAAK,eAAe,GAAG,WAAW,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC,CAAC;AAC1D,KAAK,gBAAgB,GAAG,UAAU,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,CAAC;AACvD,KAAK,iBAAiB,GAAG,UAAU,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,CAAC;AAExD,iDAAiD;AACjD,MAAM,WAAW,eAAe;IAC9B,cAAc,EAAE,cAAc,CAAC;IAC/B,cAAc,EAAE,MAAM,CAAC;IACvB,aAAa,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,cAAc,CAAC;CACxB;AAED,+CAA+C;AAC/C,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,eAAe,
|
|
1
|
+
{"version":3,"file":"chat.d.ts","sourceRoot":"","sources":["../../../src/src/handlers/chat.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAC;AACjD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAO5D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAGpD,KAAK,eAAe,GAAG,WAAW,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC,CAAC;AAC1D,KAAK,gBAAgB,GAAG,UAAU,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,CAAC;AACvD,KAAK,iBAAiB,GAAG,UAAU,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,CAAC;AAExD,iDAAiD;AACjD,MAAM,WAAW,eAAe;IAC9B,cAAc,EAAE,cAAc,CAAC;IAC/B,cAAc,EAAE,MAAM,CAAC;IACvB,aAAa,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,cAAc,CAAC;CACxB;AAED,+CAA+C;AAC/C,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,eAAe,IAiJvC,eAAe,gBAAgB,EAAE,QAAQ,iBAAiB,mBA6EzE"}
|
|
@@ -99,24 +99,26 @@ function createChatHandler(deps) {
|
|
|
99
99
|
.slice(0, characterBudget);
|
|
100
100
|
if (!memoryContext)
|
|
101
101
|
return;
|
|
102
|
-
const
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
102
|
+
const allFactUuids = [
|
|
103
|
+
...projectContext.facts.map((fact) => fact.uuid),
|
|
104
|
+
...userContext.facts.map((fact) => fact.uuid),
|
|
105
|
+
];
|
|
106
|
+
const factUuids = seedFactUuids ?? Array.from(new Set(allFactUuids));
|
|
107
107
|
state.cachedMemoryContext = memoryContext;
|
|
108
108
|
logger_js_1.logger.info(`Cached ${projectFacts.length + userFacts.length} facts and ${projectNodes.length + userNodes.length} nodes for system prompt injection`);
|
|
109
109
|
state.lastInjectionFactUuids = factUuids;
|
|
110
110
|
};
|
|
111
111
|
const computeJaccardSimilarity = (left, right) => {
|
|
112
|
-
if (left.
|
|
112
|
+
if (left.length === 0 && right.length === 0)
|
|
113
113
|
return 1;
|
|
114
|
+
const leftSet = new Set(left);
|
|
115
|
+
const rightSet = new Set(right);
|
|
114
116
|
let intersection = 0;
|
|
115
|
-
for (const value of
|
|
116
|
-
if (
|
|
117
|
+
for (const value of leftSet) {
|
|
118
|
+
if (rightSet.has(value))
|
|
117
119
|
intersection += 1;
|
|
118
120
|
}
|
|
119
|
-
const union =
|
|
121
|
+
const union = leftSet.size + rightSet.size - intersection;
|
|
120
122
|
return union === 0 ? 1 : intersection / union;
|
|
121
123
|
};
|
|
122
124
|
return async ({ sessionID }, output) => {
|
|
@@ -147,18 +149,27 @@ function createChatHandler(deps) {
|
|
|
147
149
|
let shouldReinject = false;
|
|
148
150
|
let currentFactUuids = null;
|
|
149
151
|
if (!shouldInjectOnFirst) {
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
152
|
+
try {
|
|
153
|
+
const driftFacts = await client.searchFacts({
|
|
154
|
+
query: messageText,
|
|
155
|
+
groupIds: [state.groupId],
|
|
156
|
+
maxFacts: 20,
|
|
157
|
+
});
|
|
158
|
+
currentFactUuids = driftFacts.map((fact) => fact.uuid);
|
|
159
|
+
const similarity = computeJaccardSimilarity(currentFactUuids, state.lastInjectionFactUuids);
|
|
160
|
+
shouldReinject = similarity < driftThreshold;
|
|
161
|
+
if (!shouldReinject) {
|
|
162
|
+
logger_js_1.logger.debug("Skipping reinjection; similarity above threshold", {
|
|
163
|
+
sessionID,
|
|
164
|
+
similarity,
|
|
165
|
+
});
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
catch (err) {
|
|
170
|
+
logger_js_1.logger.error("Failed to check topic drift, skipping reinjection", {
|
|
160
171
|
sessionID,
|
|
161
|
-
|
|
172
|
+
err,
|
|
162
173
|
});
|
|
163
174
|
return;
|
|
164
175
|
}
|
|
@@ -62,7 +62,7 @@ function createEventHandler(deps) {
|
|
|
62
62
|
groupId: defaultGroupId,
|
|
63
63
|
userGroupId: defaultUserGroupId,
|
|
64
64
|
injectedMemories: false,
|
|
65
|
-
lastInjectionFactUuids:
|
|
65
|
+
lastInjectionFactUuids: [],
|
|
66
66
|
messageCount: 0,
|
|
67
67
|
pendingMessages: [],
|
|
68
68
|
contextLimit: 200_000,
|
package/script/src/session.d.ts
CHANGED
|
@@ -11,7 +11,7 @@ export type SessionState = {
|
|
|
11
11
|
/** Whether memories have been injected into this session yet. */
|
|
12
12
|
injectedMemories: boolean;
|
|
13
13
|
/** Fact UUIDs included in the last memory injection. */
|
|
14
|
-
lastInjectionFactUuids:
|
|
14
|
+
lastInjectionFactUuids: string[];
|
|
15
15
|
/** Cached formatted memory context for system prompt injection. */
|
|
16
16
|
cachedMemoryContext?: string;
|
|
17
17
|
/** Count of messages observed in this session. */
|
|
@@ -1 +1 @@
|
|
|
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,
|
|
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,MAAM,EAAE,CAAC;IACjC,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"}
|
package/script/src/session.js
CHANGED
|
@@ -109,7 +109,7 @@ class SessionManager {
|
|
|
109
109
|
groupId: this.defaultGroupId,
|
|
110
110
|
userGroupId: this.defaultUserGroupId,
|
|
111
111
|
injectedMemories: false,
|
|
112
|
-
lastInjectionFactUuids:
|
|
112
|
+
lastInjectionFactUuids: [],
|
|
113
113
|
cachedMemoryContext: undefined,
|
|
114
114
|
messageCount: 0,
|
|
115
115
|
pendingMessages: [],
|