opencode-graphiti 0.1.7 → 0.1.8

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 (36) hide show
  1. package/README.md +14 -10
  2. package/esm/src/handlers/chat.d.ts.map +1 -1
  3. package/esm/src/handlers/chat.js +24 -1
  4. package/esm/src/handlers/event.d.ts.map +1 -1
  5. package/esm/src/handlers/event.js +3 -0
  6. package/esm/src/handlers/messages.d.ts +11 -0
  7. package/esm/src/handlers/messages.d.ts.map +1 -0
  8. package/esm/src/handlers/messages.js +75 -0
  9. package/esm/src/index.js +2 -2
  10. package/esm/src/services/context.d.ts +4 -0
  11. package/esm/src/services/context.d.ts.map +1 -1
  12. package/esm/src/services/context.js +15 -0
  13. package/esm/src/session.d.ts +5 -1
  14. package/esm/src/session.d.ts.map +1 -1
  15. package/esm/src/session.js +2 -0
  16. package/package.json +3 -2
  17. package/script/src/handlers/chat.d.ts.map +1 -1
  18. package/script/src/handlers/chat.js +24 -1
  19. package/script/src/handlers/event.d.ts.map +1 -1
  20. package/script/src/handlers/event.js +3 -0
  21. package/script/src/handlers/messages.d.ts +11 -0
  22. package/script/src/handlers/messages.d.ts.map +1 -0
  23. package/script/src/handlers/messages.js +78 -0
  24. package/script/src/index.js +2 -2
  25. package/script/src/services/context.d.ts +4 -0
  26. package/script/src/services/context.d.ts.map +1 -1
  27. package/script/src/services/context.js +16 -0
  28. package/script/src/session.d.ts +5 -1
  29. package/script/src/session.d.ts.map +1 -1
  30. package/script/src/session.js +2 -0
  31. package/esm/src/handlers/system.d.ts +0 -11
  32. package/esm/src/handlers/system.d.ts.map +0 -1
  33. package/esm/src/handlers/system.js +0 -18
  34. package/script/src/handlers/system.d.ts +0 -11
  35. package/script/src/handlers/system.d.ts.map +0 -1
  36. package/script/src/handlers/system.js +0 -21
package/README.md CHANGED
@@ -23,8 +23,9 @@ reminded of recent project context — regardless of what survived the summary.
23
23
  This plugin connects to a Graphiti MCP server and:
24
24
 
25
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
26
+ - Injects memories into the last user message as a `<memory>` block via
27
+ `experimental.chat.messages.transform`, keeping the system prompt static for
28
+ prefix caching
28
29
  - Detects context drift using Jaccard similarity and re-injects when the
29
30
  conversation topic shifts
30
31
  - Buffers user and assistant messages, flushing them to Graphiti on idle or
@@ -128,8 +129,8 @@ On each user message the plugin searches Graphiti for facts and entities
128
129
  relevant to the message content. Results are split into project and user scopes
129
130
  (70% / 30% budget), deduplicated, filtered for validity, annotated with
130
131
  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.
132
+ formatted context is cached on the session state for the messages transform hook
133
+ to pick up.
133
134
 
134
135
  On the very first message of a session, the plugin also loads the most recent
135
136
  session snapshot episode to prime the conversation with prior context.
@@ -137,13 +138,16 @@ session snapshot episode to prime the conversation with prior context.
137
138
  The injection budget is calculated dynamically: 5% of the model's context limit
138
139
  (resolved from the provider list) multiplied by 4 characters per token.
139
140
 
140
- ### System Prompt Injection (`experimental.chat.system.transform`)
141
+ ### User Message Injection (`experimental.chat.messages.transform`)
141
142
 
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.
143
+ A separate hook reads the cached memory context and prepends it to the last user
144
+ message as a `<memory data-uuids="...">` block. The `data-uuids` attribute lists
145
+ the fact UUIDs included in the injection, which are tracked in
146
+ `visibleFactUuids` so subsequent searches can filter out already-visible facts.
147
+ This approach keeps the system prompt static, enabling provider-side prefix
148
+ caching, and avoids influencing session titles. The cache is cleared after
149
+ injection so stale context is not re-injected on subsequent LLM calls within the
150
+ same turn.
147
151
 
148
152
  ### Drift-Based Re-injection (`chat.message`)
149
153
 
@@ -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,IAiJvC,eAAe,gBAAgB,EAAE,QAAQ,iBAAiB,mBA6EzE"}
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,IAkLvC,eAAe,gBAAgB,EAAE,QAAQ,iBAAiB,mBA6EzE"}
@@ -46,6 +46,28 @@ export function createChatHandler(deps) {
46
46
  facts: userFacts,
47
47
  nodes: userNodes,
48
48
  });
49
+ const visibleSet = new Set(state.visibleFactUuids ?? []);
50
+ const beforeProjectFacts = projectContext.facts.length;
51
+ const beforeUserFacts = userContext.facts.length;
52
+ projectContext.facts = projectContext.facts.filter((fact) => !visibleSet.has(fact.uuid));
53
+ userContext.facts = userContext.facts.filter((fact) => !visibleSet.has(fact.uuid));
54
+ logger.debug("Filtered visible facts from injection", {
55
+ visibleCount: visibleSet.size,
56
+ filteredProjectFacts: beforeProjectFacts - projectContext.facts.length,
57
+ filteredUserFacts: beforeUserFacts - userContext.facts.length,
58
+ remainingProjectFacts: projectContext.facts.length,
59
+ remainingUserFacts: userContext.facts.length,
60
+ });
61
+ if (projectContext.facts.length === 0 &&
62
+ userContext.facts.length === 0 &&
63
+ projectContext.nodes.length === 0 &&
64
+ userContext.nodes.length === 0) {
65
+ logger.debug("All facts filtered; skipping context cache", {
66
+ groupId: state.groupId,
67
+ userGroupId: state.userGroupId,
68
+ });
69
+ return;
70
+ }
49
71
  const projectContextString = formatMemoryContext(projectContext.facts, projectContext.nodes, { factStaleDays });
50
72
  const userContextString = formatMemoryContext(userContext.facts, userContext.nodes, { factStaleDays });
51
73
  if (!projectContextString && !userContextString)
@@ -102,7 +124,8 @@ export function createChatHandler(deps) {
102
124
  ];
103
125
  const factUuids = seedFactUuids ?? Array.from(new Set(allFactUuids));
104
126
  state.cachedMemoryContext = memoryContext;
105
- logger.info(`Cached ${projectFacts.length + userFacts.length} facts and ${projectNodes.length + userNodes.length} nodes for system prompt injection`);
127
+ state.cachedFactUuids = factUuids;
128
+ logger.info(`Cached ${projectFacts.length + userFacts.length} facts and ${projectNodes.length + userNodes.length} nodes for user message injection`);
106
129
  state.lastInjectionFactUuids = factUuids;
107
130
  };
108
131
  const computeJaccardSimilarity = (left, right) => {
@@ -1 +1 @@
1
- {"version":3,"file":"event.d.ts","sourceRoot":"","sources":["../../../src/src/handlers/event.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAC;AACjD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAI5D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAGpD,KAAK,SAAS,GAAG,WAAW,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC;AAC7C,KAAK,UAAU,GAAG,UAAU,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC;AAE3C,0CAA0C;AAC1C,MAAM,WAAW,gBAAgB;IAC/B,cAAc,EAAE,cAAc,CAAC;IAC/B,MAAM,EAAE,cAAc,CAAC;IACvB,cAAc,EAAE,MAAM,CAAC;IACvB,SAAS,EAAE,cAAc,CAAC;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,wCAAwC;AACxC,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,gBAAgB,IAkDzC,WAAW,UAAU,mBAkLpC"}
1
+ {"version":3,"file":"event.d.ts","sourceRoot":"","sources":["../../../src/src/handlers/event.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAC;AACjD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAI5D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAGpD,KAAK,SAAS,GAAG,WAAW,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC;AAC7C,KAAK,UAAU,GAAG,UAAU,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC;AAE3C,0CAA0C;AAC1C,MAAM,WAAW,gBAAgB;IAC/B,cAAc,EAAE,cAAc,CAAC;IAC/B,MAAM,EAAE,cAAc,CAAC;IACvB,cAAc,EAAE,MAAM,CAAC;IACvB,SAAS,EAAE,cAAc,CAAC;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,wCAAwC;AACxC,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,gBAAgB,IAkDzC,WAAW,UAAU,mBAqLpC"}
@@ -60,6 +60,9 @@ export function createEventHandler(deps) {
60
60
  userGroupId: defaultUserGroupId,
61
61
  injectedMemories: false,
62
62
  lastInjectionFactUuids: [],
63
+ cachedMemoryContext: undefined,
64
+ cachedFactUuids: undefined,
65
+ visibleFactUuids: [],
63
66
  messageCount: 0,
64
67
  pendingMessages: [],
65
68
  contextLimit: 200_000,
@@ -0,0 +1,11 @@
1
+ import type { Hooks } from "@opencode-ai/plugin";
2
+ import type { SessionManager } from "../session.js";
3
+ type MessagesTransformHook = NonNullable<Hooks["experimental.chat.messages.transform"]>;
4
+ type MessagesTransformInput = Parameters<MessagesTransformHook>[0];
5
+ type MessagesTransformOutput = Parameters<MessagesTransformHook>[1];
6
+ export interface MessagesHandlerDeps {
7
+ sessionManager: SessionManager;
8
+ }
9
+ export declare function createMessagesHandler(deps: MessagesHandlerDeps): (_input: MessagesTransformInput, output: MessagesTransformOutput) => Promise<void>;
10
+ export {};
11
+ //# sourceMappingURL=messages.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"messages.d.ts","sourceRoot":"","sources":["../../../src/src/handlers/messages.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAC;AAGjD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAEpD,KAAK,qBAAqB,GAAG,WAAW,CACtC,KAAK,CAAC,sCAAsC,CAAC,CAC9C,CAAC;AACF,KAAK,sBAAsB,GAAG,UAAU,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC,CAAC;AACnE,KAAK,uBAAuB,GAAG,UAAU,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC,CAAC;AAEpE,MAAM,WAAW,mBAAmB;IAClC,cAAc,EAAE,cAAc,CAAC;CAChC;AAED,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,mBAAmB,IAK3D,QAAQ,sBAAsB,EAC9B,QAAQ,uBAAuB,mBAkFlC"}
@@ -0,0 +1,75 @@
1
+ import { extractVisibleUuids } from "../services/context.js";
2
+ import { logger } from "../services/logger.js";
3
+ export function createMessagesHandler(deps) {
4
+ const { sessionManager } = deps;
5
+ // deno-lint-ignore require-await
6
+ return async (_input, output) => {
7
+ const lastUserEntry = [...output.messages]
8
+ .reverse()
9
+ .find((message) => message.info.role === "user");
10
+ if (!lastUserEntry)
11
+ return;
12
+ const sessionID = lastUserEntry.info.sessionID;
13
+ const state = sessionManager.getState(sessionID);
14
+ if (!state?.isMain) {
15
+ logger.debug("Skipping memory injection; not main session", {
16
+ sessionID,
17
+ });
18
+ return;
19
+ }
20
+ const allVisibleUuids = [];
21
+ for (const entry of output.messages) {
22
+ for (const part of entry.parts) {
23
+ if (part.type === "text" && "text" in part) {
24
+ const uuids = extractVisibleUuids(part.text);
25
+ if (uuids.length > 0) {
26
+ logger.debug("Found <memory> block UUIDs", {
27
+ sessionID,
28
+ uuids,
29
+ messageID: entry.info.id,
30
+ });
31
+ }
32
+ allVisibleUuids.push(...uuids);
33
+ }
34
+ }
35
+ }
36
+ state.visibleFactUuids = [...new Set(allVisibleUuids)];
37
+ logger.debug("Updated visibleFactUuids from message scan", {
38
+ sessionID,
39
+ visibleCount: state.visibleFactUuids.length,
40
+ });
41
+ if (!state.cachedMemoryContext) {
42
+ logger.debug("Skipping memory injection; no cached context", {
43
+ sessionID,
44
+ });
45
+ return;
46
+ }
47
+ const textPart = lastUserEntry.parts.find((part) => part.type === "text" && "text" in part);
48
+ if (!textPart) {
49
+ logger.debug("Skipping memory injection; no text part", {
50
+ sessionID,
51
+ });
52
+ return;
53
+ }
54
+ if (textPart.text.includes("<memory")) {
55
+ logger.debug("Skipping memory injection; already injected", {
56
+ sessionID,
57
+ });
58
+ state.cachedMemoryContext = undefined;
59
+ state.cachedFactUuids = undefined;
60
+ return;
61
+ }
62
+ const uuids = state.cachedFactUuids ?? [];
63
+ const uuidAttr = uuids.length > 0 ? ` data-uuids="${uuids.join(",")}"` : "";
64
+ const memoryBlock = `<memory${uuidAttr}>\n${state.cachedMemoryContext}\n</memory>`;
65
+ textPart.text = `${memoryBlock}\n\n${textPart.text}`;
66
+ logger.info("Injected memory context into last user message", {
67
+ sessionID,
68
+ factCount: uuids.length,
69
+ blockLength: memoryBlock.length,
70
+ preview: state.cachedMemoryContext.slice(0, 100),
71
+ });
72
+ state.cachedMemoryContext = undefined;
73
+ state.cachedFactUuids = undefined;
74
+ };
75
+ }
package/esm/src/index.js CHANGED
@@ -2,7 +2,7 @@ import { loadConfig } from "./config.js";
2
2
  import { createChatHandler } from "./handlers/chat.js";
3
3
  import { createCompactingHandler } from "./handlers/compacting.js";
4
4
  import { createEventHandler } from "./handlers/event.js";
5
- import { createSystemHandler } from "./handlers/system.js";
5
+ import { createMessagesHandler } from "./handlers/messages.js";
6
6
  import { GraphitiClient } from "./services/client.js";
7
7
  import { logger } from "./services/logger.js";
8
8
  import { SessionManager } from "./session.js";
@@ -44,7 +44,7 @@ export const graphiti = async (input) => {
44
44
  defaultGroupId,
45
45
  factStaleDays: config.factStaleDays,
46
46
  }),
47
- "experimental.chat.system.transform": createSystemHandler({
47
+ "experimental.chat.messages.transform": createMessagesHandler({
48
48
  sessionManager,
49
49
  }),
50
50
  };
@@ -30,4 +30,8 @@ export declare function formatMemoryContext(facts: GraphitiFact[], nodes: Graphi
30
30
  factStaleDays?: number;
31
31
  now?: Date;
32
32
  }): string;
33
+ /**
34
+ * Extract fact UUIDs from all <memory data-uuids="..."> blocks in a text string.
35
+ */
36
+ export declare function extractVisibleUuids(text: string): string[];
33
37
  //# 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;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
+ {"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;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAW1D"}
@@ -129,3 +129,18 @@ export function formatMemoryContext(facts, nodes, options) {
129
129
  }
130
130
  return sections.join("\n");
131
131
  }
132
+ /**
133
+ * Extract fact UUIDs from all <memory data-uuids="..."> blocks in a text string.
134
+ */
135
+ export function extractVisibleUuids(text) {
136
+ const uuids = [];
137
+ const regex = /<memory[^>]*\bdata-uuids="([^"]*)"[^>]*>/g;
138
+ let match;
139
+ while ((match = regex.exec(text)) !== null) {
140
+ const raw = match[1];
141
+ if (raw) {
142
+ uuids.push(...raw.split(",").filter(Boolean));
143
+ }
144
+ }
145
+ return uuids;
146
+ }
@@ -12,8 +12,12 @@ export type SessionState = {
12
12
  injectedMemories: boolean;
13
13
  /** Fact UUIDs included in the last memory injection. */
14
14
  lastInjectionFactUuids: string[];
15
- /** Cached formatted memory context for system prompt injection. */
15
+ /** Cached formatted memory context for user message injection. */
16
16
  cachedMemoryContext?: string;
17
+ /** Fact UUIDs from cached context, for embedding in <memory> tag. */
18
+ cachedFactUuids?: string[];
19
+ /** Fact UUIDs currently visible in <memory> blocks across all messages. */
20
+ visibleFactUuids: string[];
17
21
  /** Count of messages observed in this session. */
18
22
  messageCount: number;
19
23
  /** Buffered message strings awaiting flush. */
@@ -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,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"}
1
+ {"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../../src/src/session.ts"],"names":[],"mappings":"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"}
@@ -108,6 +108,8 @@ export class SessionManager {
108
108
  injectedMemories: false,
109
109
  lastInjectionFactUuids: [],
110
110
  cachedMemoryContext: undefined,
111
+ cachedFactUuids: undefined,
112
+ visibleFactUuids: [],
111
113
  messageCount: 0,
112
114
  pendingMessages: [],
113
115
  contextLimit: 200_000,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opencode-graphiti",
3
- "version": "0.1.7",
3
+ "version": "0.1.8",
4
4
  "description": "OpenCode plugin for persistent memory via Graphiti knowledge graph",
5
5
  "keywords": [
6
6
  "opencode",
@@ -40,7 +40,8 @@
40
40
  "hooks": [
41
41
  "chat.message",
42
42
  "event",
43
- "experimental.session.compacting"
43
+ "experimental.session.compacting",
44
+ "experimental.chat.messages.transform"
44
45
  ]
45
46
  },
46
47
  "dependencies": {
@@ -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,IAiJvC,eAAe,gBAAgB,EAAE,QAAQ,iBAAiB,mBA6EzE"}
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,IAkLvC,eAAe,gBAAgB,EAAE,QAAQ,iBAAiB,mBA6EzE"}
@@ -49,6 +49,28 @@ function createChatHandler(deps) {
49
49
  facts: userFacts,
50
50
  nodes: userNodes,
51
51
  });
52
+ const visibleSet = new Set(state.visibleFactUuids ?? []);
53
+ const beforeProjectFacts = projectContext.facts.length;
54
+ const beforeUserFacts = userContext.facts.length;
55
+ projectContext.facts = projectContext.facts.filter((fact) => !visibleSet.has(fact.uuid));
56
+ userContext.facts = userContext.facts.filter((fact) => !visibleSet.has(fact.uuid));
57
+ logger_js_1.logger.debug("Filtered visible facts from injection", {
58
+ visibleCount: visibleSet.size,
59
+ filteredProjectFacts: beforeProjectFacts - projectContext.facts.length,
60
+ filteredUserFacts: beforeUserFacts - userContext.facts.length,
61
+ remainingProjectFacts: projectContext.facts.length,
62
+ remainingUserFacts: userContext.facts.length,
63
+ });
64
+ if (projectContext.facts.length === 0 &&
65
+ userContext.facts.length === 0 &&
66
+ projectContext.nodes.length === 0 &&
67
+ userContext.nodes.length === 0) {
68
+ logger_js_1.logger.debug("All facts filtered; skipping context cache", {
69
+ groupId: state.groupId,
70
+ userGroupId: state.userGroupId,
71
+ });
72
+ return;
73
+ }
52
74
  const projectContextString = (0, context_js_1.formatMemoryContext)(projectContext.facts, projectContext.nodes, { factStaleDays });
53
75
  const userContextString = (0, context_js_1.formatMemoryContext)(userContext.facts, userContext.nodes, { factStaleDays });
54
76
  if (!projectContextString && !userContextString)
@@ -105,7 +127,8 @@ function createChatHandler(deps) {
105
127
  ];
106
128
  const factUuids = seedFactUuids ?? Array.from(new Set(allFactUuids));
107
129
  state.cachedMemoryContext = memoryContext;
108
- logger_js_1.logger.info(`Cached ${projectFacts.length + userFacts.length} facts and ${projectNodes.length + userNodes.length} nodes for system prompt injection`);
130
+ state.cachedFactUuids = factUuids;
131
+ logger_js_1.logger.info(`Cached ${projectFacts.length + userFacts.length} facts and ${projectNodes.length + userNodes.length} nodes for user message injection`);
109
132
  state.lastInjectionFactUuids = factUuids;
110
133
  };
111
134
  const computeJaccardSimilarity = (left, right) => {
@@ -1 +1 @@
1
- {"version":3,"file":"event.d.ts","sourceRoot":"","sources":["../../../src/src/handlers/event.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAC;AACjD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAI5D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAGpD,KAAK,SAAS,GAAG,WAAW,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC;AAC7C,KAAK,UAAU,GAAG,UAAU,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC;AAE3C,0CAA0C;AAC1C,MAAM,WAAW,gBAAgB;IAC/B,cAAc,EAAE,cAAc,CAAC;IAC/B,MAAM,EAAE,cAAc,CAAC;IACvB,cAAc,EAAE,MAAM,CAAC;IACvB,SAAS,EAAE,cAAc,CAAC;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,wCAAwC;AACxC,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,gBAAgB,IAkDzC,WAAW,UAAU,mBAkLpC"}
1
+ {"version":3,"file":"event.d.ts","sourceRoot":"","sources":["../../../src/src/handlers/event.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAC;AACjD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAI5D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAGpD,KAAK,SAAS,GAAG,WAAW,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC;AAC7C,KAAK,UAAU,GAAG,UAAU,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC;AAE3C,0CAA0C;AAC1C,MAAM,WAAW,gBAAgB;IAC/B,cAAc,EAAE,cAAc,CAAC;IAC/B,MAAM,EAAE,cAAc,CAAC;IACvB,cAAc,EAAE,MAAM,CAAC;IACvB,SAAS,EAAE,cAAc,CAAC;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,wCAAwC;AACxC,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,gBAAgB,IAkDzC,WAAW,UAAU,mBAqLpC"}
@@ -63,6 +63,9 @@ function createEventHandler(deps) {
63
63
  userGroupId: defaultUserGroupId,
64
64
  injectedMemories: false,
65
65
  lastInjectionFactUuids: [],
66
+ cachedMemoryContext: undefined,
67
+ cachedFactUuids: undefined,
68
+ visibleFactUuids: [],
66
69
  messageCount: 0,
67
70
  pendingMessages: [],
68
71
  contextLimit: 200_000,
@@ -0,0 +1,11 @@
1
+ import type { Hooks } from "@opencode-ai/plugin";
2
+ import type { SessionManager } from "../session.js";
3
+ type MessagesTransformHook = NonNullable<Hooks["experimental.chat.messages.transform"]>;
4
+ type MessagesTransformInput = Parameters<MessagesTransformHook>[0];
5
+ type MessagesTransformOutput = Parameters<MessagesTransformHook>[1];
6
+ export interface MessagesHandlerDeps {
7
+ sessionManager: SessionManager;
8
+ }
9
+ export declare function createMessagesHandler(deps: MessagesHandlerDeps): (_input: MessagesTransformInput, output: MessagesTransformOutput) => Promise<void>;
10
+ export {};
11
+ //# sourceMappingURL=messages.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"messages.d.ts","sourceRoot":"","sources":["../../../src/src/handlers/messages.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAC;AAGjD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAEpD,KAAK,qBAAqB,GAAG,WAAW,CACtC,KAAK,CAAC,sCAAsC,CAAC,CAC9C,CAAC;AACF,KAAK,sBAAsB,GAAG,UAAU,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC,CAAC;AACnE,KAAK,uBAAuB,GAAG,UAAU,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC,CAAC;AAEpE,MAAM,WAAW,mBAAmB;IAClC,cAAc,EAAE,cAAc,CAAC;CAChC;AAED,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,mBAAmB,IAK3D,QAAQ,sBAAsB,EAC9B,QAAQ,uBAAuB,mBAkFlC"}
@@ -0,0 +1,78 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createMessagesHandler = createMessagesHandler;
4
+ const context_js_1 = require("../services/context.js");
5
+ const logger_js_1 = require("../services/logger.js");
6
+ function createMessagesHandler(deps) {
7
+ const { sessionManager } = deps;
8
+ // deno-lint-ignore require-await
9
+ return async (_input, output) => {
10
+ const lastUserEntry = [...output.messages]
11
+ .reverse()
12
+ .find((message) => message.info.role === "user");
13
+ if (!lastUserEntry)
14
+ return;
15
+ const sessionID = lastUserEntry.info.sessionID;
16
+ const state = sessionManager.getState(sessionID);
17
+ if (!state?.isMain) {
18
+ logger_js_1.logger.debug("Skipping memory injection; not main session", {
19
+ sessionID,
20
+ });
21
+ return;
22
+ }
23
+ const allVisibleUuids = [];
24
+ for (const entry of output.messages) {
25
+ for (const part of entry.parts) {
26
+ if (part.type === "text" && "text" in part) {
27
+ const uuids = (0, context_js_1.extractVisibleUuids)(part.text);
28
+ if (uuids.length > 0) {
29
+ logger_js_1.logger.debug("Found <memory> block UUIDs", {
30
+ sessionID,
31
+ uuids,
32
+ messageID: entry.info.id,
33
+ });
34
+ }
35
+ allVisibleUuids.push(...uuids);
36
+ }
37
+ }
38
+ }
39
+ state.visibleFactUuids = [...new Set(allVisibleUuids)];
40
+ logger_js_1.logger.debug("Updated visibleFactUuids from message scan", {
41
+ sessionID,
42
+ visibleCount: state.visibleFactUuids.length,
43
+ });
44
+ if (!state.cachedMemoryContext) {
45
+ logger_js_1.logger.debug("Skipping memory injection; no cached context", {
46
+ sessionID,
47
+ });
48
+ return;
49
+ }
50
+ const textPart = lastUserEntry.parts.find((part) => part.type === "text" && "text" in part);
51
+ if (!textPart) {
52
+ logger_js_1.logger.debug("Skipping memory injection; no text part", {
53
+ sessionID,
54
+ });
55
+ return;
56
+ }
57
+ if (textPart.text.includes("<memory")) {
58
+ logger_js_1.logger.debug("Skipping memory injection; already injected", {
59
+ sessionID,
60
+ });
61
+ state.cachedMemoryContext = undefined;
62
+ state.cachedFactUuids = undefined;
63
+ return;
64
+ }
65
+ const uuids = state.cachedFactUuids ?? [];
66
+ const uuidAttr = uuids.length > 0 ? ` data-uuids="${uuids.join(",")}"` : "";
67
+ const memoryBlock = `<memory${uuidAttr}>\n${state.cachedMemoryContext}\n</memory>`;
68
+ textPart.text = `${memoryBlock}\n\n${textPart.text}`;
69
+ logger_js_1.logger.info("Injected memory context into last user message", {
70
+ sessionID,
71
+ factCount: uuids.length,
72
+ blockLength: memoryBlock.length,
73
+ preview: state.cachedMemoryContext.slice(0, 100),
74
+ });
75
+ state.cachedMemoryContext = undefined;
76
+ state.cachedFactUuids = undefined;
77
+ };
78
+ }
@@ -5,7 +5,7 @@ const config_js_1 = require("./config.js");
5
5
  const chat_js_1 = require("./handlers/chat.js");
6
6
  const compacting_js_1 = require("./handlers/compacting.js");
7
7
  const event_js_1 = require("./handlers/event.js");
8
- const system_js_1 = require("./handlers/system.js");
8
+ const messages_js_1 = require("./handlers/messages.js");
9
9
  const client_js_1 = require("./services/client.js");
10
10
  const logger_js_1 = require("./services/logger.js");
11
11
  const session_js_1 = require("./session.js");
@@ -47,7 +47,7 @@ const graphiti = async (input) => {
47
47
  defaultGroupId,
48
48
  factStaleDays: config.factStaleDays,
49
49
  }),
50
- "experimental.chat.system.transform": (0, system_js_1.createSystemHandler)({
50
+ "experimental.chat.messages.transform": (0, messages_js_1.createMessagesHandler)({
51
51
  sessionManager,
52
52
  }),
53
53
  };
@@ -30,4 +30,8 @@ export declare function formatMemoryContext(facts: GraphitiFact[], nodes: Graphi
30
30
  factStaleDays?: number;
31
31
  now?: Date;
32
32
  }): string;
33
+ /**
34
+ * Extract fact UUIDs from all <memory data-uuids="..."> blocks in a text string.
35
+ */
36
+ export declare function extractVisibleUuids(text: string): string[];
33
37
  //# 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;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
+ {"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;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAW1D"}
@@ -2,6 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.deduplicateContext = exports.removeNodesReferencedByFacts = exports.deduplicateNodesByUuid = exports.deduplicateFactsByUuid = exports.formatNodeLines = exports.formatFactLines = exports.formatFactLine = exports.filterAndAnnotateFacts = exports.sortFactsByRecency = exports.annotateStaleFact = exports.isFactInvalid = exports.parseDate = void 0;
4
4
  exports.formatMemoryContext = formatMemoryContext;
5
+ exports.extractVisibleUuids = extractVisibleUuids;
5
6
  const DAY_MS = 24 * 60 * 60 * 1000;
6
7
  const parseDate = (value) => {
7
8
  if (!value)
@@ -145,3 +146,18 @@ function formatMemoryContext(facts, nodes, options) {
145
146
  }
146
147
  return sections.join("\n");
147
148
  }
149
+ /**
150
+ * Extract fact UUIDs from all <memory data-uuids="..."> blocks in a text string.
151
+ */
152
+ function extractVisibleUuids(text) {
153
+ const uuids = [];
154
+ const regex = /<memory[^>]*\bdata-uuids="([^"]*)"[^>]*>/g;
155
+ let match;
156
+ while ((match = regex.exec(text)) !== null) {
157
+ const raw = match[1];
158
+ if (raw) {
159
+ uuids.push(...raw.split(",").filter(Boolean));
160
+ }
161
+ }
162
+ return uuids;
163
+ }
@@ -12,8 +12,12 @@ export type SessionState = {
12
12
  injectedMemories: boolean;
13
13
  /** Fact UUIDs included in the last memory injection. */
14
14
  lastInjectionFactUuids: string[];
15
- /** Cached formatted memory context for system prompt injection. */
15
+ /** Cached formatted memory context for user message injection. */
16
16
  cachedMemoryContext?: string;
17
+ /** Fact UUIDs from cached context, for embedding in <memory> tag. */
18
+ cachedFactUuids?: string[];
19
+ /** Fact UUIDs currently visible in <memory> blocks across all messages. */
20
+ visibleFactUuids: string[];
17
21
  /** Count of messages observed in this session. */
18
22
  messageCount: number;
19
23
  /** Buffered message strings awaiting flush. */
@@ -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,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"}
1
+ {"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../../src/src/session.ts"],"names":[],"mappings":"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"}
@@ -111,6 +111,8 @@ class SessionManager {
111
111
  injectedMemories: false,
112
112
  lastInjectionFactUuids: [],
113
113
  cachedMemoryContext: undefined,
114
+ cachedFactUuids: undefined,
115
+ visibleFactUuids: [],
114
116
  messageCount: 0,
115
117
  pendingMessages: [],
116
118
  contextLimit: 200_000,
@@ -1,11 +0,0 @@
1
- import type { Hooks } from "@opencode-ai/plugin";
2
- import type { SessionManager } from "../session.js";
3
- type SystemTransformHook = NonNullable<Hooks["experimental.chat.system.transform"]>;
4
- type SystemTransformInput = Parameters<SystemTransformHook>[0];
5
- type SystemTransformOutput = Parameters<SystemTransformHook>[1];
6
- export interface SystemHandlerDeps {
7
- sessionManager: SessionManager;
8
- }
9
- export declare function createSystemHandler(deps: SystemHandlerDeps): ({ sessionID }: SystemTransformInput, output: SystemTransformOutput) => Promise<void>;
10
- export {};
11
- //# sourceMappingURL=system.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"system.d.ts","sourceRoot":"","sources":["../../../src/src/handlers/system.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAC;AAEjD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAEpD,KAAK,mBAAmB,GAAG,WAAW,CACpC,KAAK,CAAC,oCAAoC,CAAC,CAC5C,CAAC;AACF,KAAK,oBAAoB,GAAG,UAAU,CAAC,mBAAmB,CAAC,CAAC,CAAC,CAAC,CAAC;AAC/D,KAAK,qBAAqB,GAAG,UAAU,CAAC,mBAAmB,CAAC,CAAC,CAAC,CAAC,CAAC;AAEhE,MAAM,WAAW,iBAAiB;IAChC,cAAc,EAAE,cAAc,CAAC;CAChC;AAED,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,iBAAiB,IAMvD,eAAe,oBAAoB,EACnC,QAAQ,qBAAqB,mBAYhC"}
@@ -1,18 +0,0 @@
1
- import { logger } from "../services/logger.js";
2
- export function createSystemHandler(deps) {
3
- const { sessionManager } = deps;
4
- // Assumes chat.message hook completes before system.transform fires for the same turn.
5
- // deno-lint-ignore require-await
6
- return async ({ sessionID }, output) => {
7
- if (!sessionID)
8
- return;
9
- const state = sessionManager.getState(sessionID);
10
- if (!state?.isMain)
11
- return;
12
- if (!state.cachedMemoryContext)
13
- return;
14
- output.system.push(state.cachedMemoryContext);
15
- state.cachedMemoryContext = undefined;
16
- logger.info("Injected memory context into system prompt");
17
- };
18
- }
@@ -1,11 +0,0 @@
1
- import type { Hooks } from "@opencode-ai/plugin";
2
- import type { SessionManager } from "../session.js";
3
- type SystemTransformHook = NonNullable<Hooks["experimental.chat.system.transform"]>;
4
- type SystemTransformInput = Parameters<SystemTransformHook>[0];
5
- type SystemTransformOutput = Parameters<SystemTransformHook>[1];
6
- export interface SystemHandlerDeps {
7
- sessionManager: SessionManager;
8
- }
9
- export declare function createSystemHandler(deps: SystemHandlerDeps): ({ sessionID }: SystemTransformInput, output: SystemTransformOutput) => Promise<void>;
10
- export {};
11
- //# sourceMappingURL=system.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"system.d.ts","sourceRoot":"","sources":["../../../src/src/handlers/system.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAC;AAEjD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAEpD,KAAK,mBAAmB,GAAG,WAAW,CACpC,KAAK,CAAC,oCAAoC,CAAC,CAC5C,CAAC;AACF,KAAK,oBAAoB,GAAG,UAAU,CAAC,mBAAmB,CAAC,CAAC,CAAC,CAAC,CAAC;AAC/D,KAAK,qBAAqB,GAAG,UAAU,CAAC,mBAAmB,CAAC,CAAC,CAAC,CAAC,CAAC;AAEhE,MAAM,WAAW,iBAAiB;IAChC,cAAc,EAAE,cAAc,CAAC;CAChC;AAED,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,iBAAiB,IAMvD,eAAe,oBAAoB,EACnC,QAAQ,qBAAqB,mBAYhC"}
@@ -1,21 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.createSystemHandler = createSystemHandler;
4
- const logger_js_1 = require("../services/logger.js");
5
- function createSystemHandler(deps) {
6
- const { sessionManager } = deps;
7
- // Assumes chat.message hook completes before system.transform fires for the same turn.
8
- // deno-lint-ignore require-await
9
- return async ({ sessionID }, output) => {
10
- if (!sessionID)
11
- return;
12
- const state = sessionManager.getState(sessionID);
13
- if (!state?.isMain)
14
- return;
15
- if (!state.cachedMemoryContext)
16
- return;
17
- output.system.push(state.cachedMemoryContext);
18
- state.cachedMemoryContext = undefined;
19
- logger_js_1.logger.info("Injected memory context into system prompt");
20
- };
21
- }