opencode-graphiti 0.1.3 → 0.1.4

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.
@@ -1,6 +1,9 @@
1
- import type { Part } from "@opencode-ai/sdk";
1
+ import type { Hooks } from "@opencode-ai/plugin";
2
2
  import type { GraphitiClient } from "../services/client.js";
3
3
  import type { SessionManager } from "../session.js";
4
+ type ChatMessageHook = NonNullable<Hooks["chat.message"]>;
5
+ type ChatMessageInput = Parameters<ChatMessageHook>[0];
6
+ type ChatMessageOutput = Parameters<ChatMessageHook>[1];
4
7
  /** Dependencies for the chat message handler. */
5
8
  export interface ChatHandlerDeps {
6
9
  sessionManager: SessionManager;
@@ -8,14 +11,6 @@ export interface ChatHandlerDeps {
8
11
  client: GraphitiClient;
9
12
  }
10
13
  /** Creates the `chat.message` hook handler. */
11
- export declare function createChatHandler(deps: ChatHandlerDeps): ({ sessionID }: {
12
- sessionID: string;
13
- }, output: {
14
- allow_buffering?: boolean;
15
- parts: Part[];
16
- message: {
17
- sessionID: string;
18
- id: string;
19
- };
20
- }) => Promise<void>;
14
+ export declare function createChatHandler(deps: ChatHandlerDeps): ({ sessionID }: ChatMessageInput, output: ChatMessageOutput) => Promise<void>;
15
+ export {};
21
16
  //# sourceMappingURL=chat.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"chat.d.ts","sourceRoot":"","sources":["../../../src/src/handlers/chat.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAI5D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAGpD,iDAAiD;AACjD,MAAM,WAAW,eAAe;IAC9B,cAAc,EAAE,cAAc,CAAC;IAC/B,iBAAiB,EAAE,MAAM,CAAC;IAC1B,MAAM,EAAE,cAAc,CAAC;CACxB;AAED,+CAA+C;AAC/C,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,eAAe,IA6FnD,eAAe;IAAE,SAAS,EAAE,MAAM,CAAA;CAAE,EACpC,QAAQ;IACN,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,KAAK,EAAE,IAAI,EAAE,CAAC;IACd,OAAO,EAAE;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC;CAC5C,mBA4DJ"}
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;AAEjD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAI5D,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,iBAAiB,EAAE,MAAM,CAAC;IAC1B,MAAM,EAAE,cAAc,CAAC;CACxB;AAED,+CAA+C;AAC/C,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,eAAe,IAyGvC,eAAe,gBAAgB,EAAE,QAAQ,iBAAiB,mBAuDzE"}
@@ -1,24 +1,20 @@
1
- import { formatMemoryContext } from "../services/context.js";
2
1
  import { calculateInjectionBudget } from "../services/context-limit.js";
2
+ import { formatMemoryContext } from "../services/context.js";
3
3
  import { logger } from "../services/logger.js";
4
4
  import { extractTextFromParts } from "../utils.js";
5
5
  /** Creates the `chat.message` hook handler. */
6
6
  export function createChatHandler(deps) {
7
7
  const { sessionManager, injectionInterval, client } = deps;
8
8
  const removeSyntheticMemoryParts = (parts) => parts.filter((part) => {
9
- const synthetic = part.synthetic;
10
- const id = typeof part.id === "string"
11
- ? String(part.id)
12
- : "";
13
- if (!synthetic)
9
+ if (part.type !== "text")
14
10
  return true;
15
- if (id.startsWith("graphiti-memory-"))
11
+ if (part.id?.startsWith("graphiti-memory-"))
16
12
  return false;
17
- if (id.startsWith("graphiti-refresh-"))
13
+ if (part.id?.startsWith("graphiti-refresh-"))
18
14
  return false;
19
15
  return true;
20
16
  });
21
- const injectMemoryContext = async (state, messageText, output, prefix, useUserScope, characterBudget) => {
17
+ const injectMemoryContext = async (state, messageText, output, prefix, useUserScope, characterBudget, shouldReinject) => {
22
18
  const userGroupId = state.userGroupId;
23
19
  const projectFactsPromise = client.searchFacts({
24
20
  query: messageText,
@@ -67,14 +63,28 @@ export function createChatHandler(deps) {
67
63
  .slice(0, characterBudget);
68
64
  if (!memoryContext)
69
65
  return;
70
- output.parts.unshift({
71
- type: "text",
72
- text: memoryContext,
73
- id: `${prefix}${Date.now()}`,
74
- sessionID: output.message.sessionID,
75
- messageID: output.message.id,
76
- synthetic: true,
77
- });
66
+ if ("system" in output.message) {
67
+ try {
68
+ output.message.system = memoryContext;
69
+ return;
70
+ }
71
+ catch (_err) {
72
+ // Fall through to synthetic injection.
73
+ }
74
+ }
75
+ if (shouldReinject) {
76
+ output.parts = removeSyntheticMemoryParts(output.parts);
77
+ }
78
+ {
79
+ output.parts.unshift({
80
+ type: "text",
81
+ text: memoryContext,
82
+ id: `${prefix}${Date.now()}`,
83
+ sessionID: output.message.sessionID,
84
+ messageID: output.message.id,
85
+ synthetic: true,
86
+ });
87
+ }
78
88
  logger.info(`Injected ${projectFacts.length + userFacts.length} facts and ${projectNodes.length + userNodes.length} nodes`);
79
89
  };
80
90
  return async ({ sessionID }, output) => {
@@ -84,7 +94,6 @@ export function createChatHandler(deps) {
84
94
  }
85
95
  const { state, resolved } = await sessionManager.resolveSessionState(sessionID);
86
96
  if (!resolved) {
87
- output.allow_buffering = true;
88
97
  logger.debug("Unable to resolve session for message:", { sessionID });
89
98
  return;
90
99
  }
@@ -109,14 +118,11 @@ export function createChatHandler(deps) {
109
118
  injectionInterval;
110
119
  if (!shouldInjectOnFirst && !shouldReinject)
111
120
  return;
112
- if (shouldReinject) {
113
- output.parts = removeSyntheticMemoryParts(output.parts);
114
- }
115
121
  try {
116
122
  const prefix = shouldReinject ? "graphiti-refresh-" : "graphiti-memory-";
117
123
  const useUserScope = shouldInjectOnFirst;
118
124
  const characterBudget = calculateInjectionBudget(state.contextLimit);
119
- await injectMemoryContext(state, messageText, output, prefix, useUserScope, characterBudget);
125
+ await injectMemoryContext(state, messageText, output, prefix, useUserScope, characterBudget, shouldReinject);
120
126
  state.injectedMemories = true;
121
127
  state.lastInjectionMessageCount = state.messageCount;
122
128
  }
@@ -1,5 +1,9 @@
1
+ import type { Hooks } from "@opencode-ai/plugin";
1
2
  import type { GraphitiClient } from "../services/client.js";
2
3
  import type { SessionManager } from "../session.js";
4
+ type CompactingHook = NonNullable<Hooks["experimental.session.compacting"]>;
5
+ type CompactingInput = Parameters<CompactingHook>[0];
6
+ type CompactingOutput = Parameters<CompactingHook>[1];
3
7
  /** Dependencies for the compacting handler. */
4
8
  export interface CompactingHandlerDeps {
5
9
  sessionManager: SessionManager;
@@ -7,9 +11,6 @@ export interface CompactingHandlerDeps {
7
11
  defaultGroupId: string;
8
12
  }
9
13
  /** Creates the `experimental.session.compacting` hook handler. */
10
- export declare function createCompactingHandler(deps: CompactingHandlerDeps): ({ sessionID }: {
11
- sessionID: string;
12
- }, output: {
13
- context: string[];
14
- }) => Promise<void>;
14
+ export declare function createCompactingHandler(deps: CompactingHandlerDeps): ({ sessionID }: CompactingInput, output: CompactingOutput) => Promise<void>;
15
+ export {};
15
16
  //# sourceMappingURL=compacting.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"compacting.d.ts","sourceRoot":"","sources":["../../../src/src/handlers/compacting.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAI5D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAEpD,+CAA+C;AAC/C,MAAM,WAAW,qBAAqB;IACpC,cAAc,EAAE,cAAc,CAAC;IAC/B,MAAM,EAAE,cAAc,CAAC;IACvB,cAAc,EAAE,MAAM,CAAC;CACxB;AAED,kEAAkE;AAClE,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,qBAAqB,IAI/D,eAAe;IAAE,SAAS,EAAE,MAAM,CAAA;CAAE,EACpC,QAAQ;IAAE,OAAO,EAAE,MAAM,EAAE,CAAA;CAAE,mBAyBhC"}
1
+ {"version":3,"file":"compacting.d.ts","sourceRoot":"","sources":["../../../src/src/handlers/compacting.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAC;AACjD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAI5D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAEpD,KAAK,cAAc,GAAG,WAAW,CAAC,KAAK,CAAC,iCAAiC,CAAC,CAAC,CAAC;AAC5E,KAAK,eAAe,GAAG,UAAU,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,CAAC;AACrD,KAAK,gBAAgB,GAAG,UAAU,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,CAAC;AAEtD,+CAA+C;AAC/C,MAAM,WAAW,qBAAqB;IACpC,cAAc,EAAE,cAAc,CAAC;IAC/B,MAAM,EAAE,cAAc,CAAC;IACvB,cAAc,EAAE,MAAM,CAAC;CACxB;AAED,kEAAkE;AAClE,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,qBAAqB,IAI/D,eAAe,eAAe,EAC9B,QAAQ,gBAAgB,mBAyB3B"}
@@ -1,7 +1,9 @@
1
- import type { Event } from "@opencode-ai/sdk";
1
+ import type { Hooks } from "@opencode-ai/plugin";
2
2
  import type { GraphitiClient } from "../services/client.js";
3
3
  import type { ProviderListClient } from "../services/context-limit.js";
4
4
  import type { SessionManager } from "../session.js";
5
+ type EventHook = NonNullable<Hooks["event"]>;
6
+ type EventInput = Parameters<EventHook>[0];
5
7
  /** Dependencies for the event handler. */
6
8
  export interface EventHandlerDeps {
7
9
  sessionManager: SessionManager;
@@ -12,7 +14,6 @@ export interface EventHandlerDeps {
12
14
  groupIdPrefix: string;
13
15
  }
14
16
  /** Creates the `event` hook handler. */
15
- export declare function createEventHandler(deps: EventHandlerDeps): ({ event }: {
16
- event: Event;
17
- }) => Promise<void>;
17
+ export declare function createEventHandler(deps: EventHandlerDeps): ({ event }: EventInput) => Promise<void>;
18
+ export {};
18
19
  //# sourceMappingURL=event.d.ts.map
@@ -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,kBAAkB,CAAC;AAC9C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAE5D,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,8BAA8B,CAAC;AAGvE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAGpD,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,kBAAkB,CAAC;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,wCAAwC;AACxC,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,gBAAgB,IAWzC,WAAW;IAAE,KAAK,EAAE,KAAK,CAAA;CAAE,mBA+J1C"}
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,uBAAuB,CAAC;AAE5D,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,8BAA8B,CAAC;AAGvE,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,kBAAkB,CAAC;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,wCAAwC;AACxC,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,gBAAgB,IAWzC,WAAW,UAAU,mBA+JpC"}
@@ -35,12 +35,12 @@ export class GraphitiClient {
35
35
  value: void 0
36
36
  });
37
37
  this.endpoint = endpoint;
38
- this.client = new Client({ name: "opencode-graphiti", version: "0.1.0" });
38
+ this.client = new Client({ name: "opencode-graphiti", version: "0.1.4" });
39
39
  this.transport = new StreamableHTTPClientTransport(new URL(endpoint));
40
40
  }
41
41
  /** Create a fresh MCP Client and Transport pair. */
42
42
  createClientAndTransport() {
43
- this.client = new Client({ name: "opencode-graphiti", version: "0.1.0" });
43
+ this.client = new Client({ name: "opencode-graphiti", version: "0.1.4" });
44
44
  this.transport = new StreamableHTTPClientTransport(new URL(this.endpoint));
45
45
  }
46
46
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"compaction.d.ts","sourceRoot":"","sources":["../../../src/src/services/compaction.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAIpE;;GAEG;AACH,wBAAsB,gBAAgB,CAAC,MAAM,EAAE;IAC7C,MAAM,EAAE;QACN,UAAU,EAAE,CAAC,IAAI,EAAE;YACjB,IAAI,EAAE,MAAM,CAAC;YACb,WAAW,EAAE,MAAM,CAAC;YACpB,OAAO,CAAC,EAAE,MAAM,CAAC;YACjB,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;YACrC,iBAAiB,CAAC,EAAE,MAAM,CAAC;SAC5B,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;KACrB,CAAC;IACF,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;CACnB,GAAG,OAAO,CAAC,IAAI,CAAC,CAiBhB;AAED;;GAEG;AACH,wBAAsB,oBAAoB,CAAC,MAAM,EAAE;IACjD,MAAM,EAAE;QACN,WAAW,EAAE,CAAC,IAAI,EAAE;YAClB,KAAK,EAAE,MAAM,CAAC;YACd,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;YACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;SACnB,KAAK,OAAO,CAAC,YAAY,EAAE,CAAC,CAAC;QAC9B,WAAW,EAAE,CAAC,IAAI,EAAE;YAClB,KAAK,EAAE,MAAM,CAAC;YACd,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;YACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;SACnB,KAAK,OAAO,CAAC,YAAY,EAAE,CAAC,CAAC;KAC/B,CAAC;IACF,eAAe,EAAE,MAAM,CAAC;IACxB,QAAQ,EAAE;QACR,OAAO,EAAE,MAAM,CAAC;QAChB,IAAI,CAAC,EAAE,MAAM,CAAC;KACf,CAAC;IACF,cAAc,EAAE,MAAM,EAAE,CAAC;CAC1B,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CA8GpB"}
1
+ {"version":3,"file":"compaction.d.ts","sourceRoot":"","sources":["../../../src/src/services/compaction.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAIpE;;GAEG;AACH,wBAAsB,gBAAgB,CAAC,MAAM,EAAE;IAC7C,MAAM,EAAE;QACN,UAAU,EAAE,CAAC,IAAI,EAAE;YACjB,IAAI,EAAE,MAAM,CAAC;YACb,WAAW,EAAE,MAAM,CAAC;YACpB,OAAO,CAAC,EAAE,MAAM,CAAC;YACjB,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;YACrC,iBAAiB,CAAC,EAAE,MAAM,CAAC;SAC5B,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;KACrB,CAAC;IACF,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;CACnB,GAAG,OAAO,CAAC,IAAI,CAAC,CAiBhB;AAED;;GAEG;AACH,wBAAsB,oBAAoB,CAAC,MAAM,EAAE;IACjD,MAAM,EAAE;QACN,WAAW,EAAE,CAAC,IAAI,EAAE;YAClB,KAAK,EAAE,MAAM,CAAC;YACd,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;YACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;SACnB,KAAK,OAAO,CAAC,YAAY,EAAE,CAAC,CAAC;QAC9B,WAAW,EAAE,CAAC,IAAI,EAAE;YAClB,KAAK,EAAE,MAAM,CAAC;YACd,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;YACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;SACnB,KAAK,OAAO,CAAC,YAAY,EAAE,CAAC,CAAC;KAC/B,CAAC;IACF,eAAe,EAAE,MAAM,CAAC;IACxB,QAAQ,EAAE;QACR,OAAO,EAAE,MAAM,CAAC;QAChB,IAAI,CAAC,EAAE,MAAM,CAAC;KACf,CAAC;IACF,cAAc,EAAE,MAAM,EAAE,CAAC;CAC1B,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAgIpB"}
@@ -69,32 +69,40 @@ export async function getCompactionContext(params) {
69
69
  const buildSection = (header, facts, nodes) => {
70
70
  const lines = [];
71
71
  lines.push(header);
72
+ lines.push("<instruction>Background context only; do not reference in titles, summaries, or opening responses unless directly relevant.</instruction>");
72
73
  if (facts.length > 0) {
73
- lines.push("### Facts");
74
+ lines.push("<facts>");
74
75
  lines.push(...formatFactLines(facts));
76
+ lines.push("</facts>");
75
77
  }
76
78
  if (nodes.length > 0) {
77
- lines.push("### Nodes");
79
+ lines.push("<nodes>");
78
80
  lines.push(...formatNodeLines(nodes));
81
+ lines.push("</nodes>");
79
82
  }
80
83
  return lines.join("\n");
81
84
  };
82
- const projectSection = buildSection("## Persistent Knowledge (Project)", projectFacts, projectNodes);
83
- const userSection = buildSection("## Persistent Knowledge (User)", userFacts, userNodes);
85
+ const projectSection = buildSection('<memory source="project">', projectFacts, projectNodes);
86
+ const userSection = buildSection('<memory source="user">', userFacts, userNodes);
84
87
  const headerLines = [
85
- "## Current Goal",
88
+ "<summary>",
89
+ "<current_goal>",
86
90
  "- ",
91
+ "</current_goal>",
87
92
  "",
88
- "## Work Completed",
93
+ "<work_completed>",
89
94
  "- ",
95
+ "</work_completed>",
90
96
  "",
91
- "## Remaining Tasks",
97
+ "<remaining_tasks>",
92
98
  "- ",
99
+ "</remaining_tasks>",
93
100
  "",
94
- "## Constraints & Decisions",
101
+ "<constraints_decisions>",
95
102
  "- ",
103
+ "</constraints_decisions>",
96
104
  "",
97
- "## Persistent Knowledge",
105
+ "<persistent_memory>",
98
106
  ];
99
107
  const header = headerLines.join("\n");
100
108
  const base = `${header}\n`;
@@ -104,10 +112,16 @@ export async function getCompactionContext(params) {
104
112
  const truncatedProject = projectSection.slice(0, projectBudget);
105
113
  const truncatedUser = userSection.slice(0, userBudget);
106
114
  const sections = [header];
107
- if (truncatedProject.trim())
115
+ if (truncatedProject.trim()) {
108
116
  sections.push(truncatedProject);
109
- if (truncatedUser.trim())
117
+ sections.push("</memory>");
118
+ }
119
+ if (truncatedUser.trim()) {
110
120
  sections.push(truncatedUser);
121
+ sections.push("</memory>");
122
+ }
123
+ sections.push("</persistent_memory>");
124
+ sections.push("</summary>");
111
125
  const content = sections.join("\n").slice(0, characterBudget);
112
126
  return [content];
113
127
  }
@@ -1 +1 @@
1
- {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../../src/src/services/context.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEpE,eAAO,MAAM,eAAe,GAAI,OAAO,YAAY,EAAE,KAAG,MAAM,EAO1D,CAAC;AAEL,eAAO,MAAM,eAAe,GAAI,OAAO,YAAY,EAAE,KAAG,MAAM,EAK1D,CAAC;AAEL;;GAEG;AACH,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,YAAY,EAAE,EACrB,KAAK,EAAE,YAAY,EAAE,GACpB,MAAM,CA8BR"}
1
+ {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../../src/src/services/context.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEpE,eAAO,MAAM,eAAe,GAAI,OAAO,YAAY,EAAE,KAAG,MAAM,EAO1D,CAAC;AAEL,eAAO,MAAM,eAAe,GAAI,OAAO,YAAY,EAAE,KAAG,MAAM,EAK1D,CAAC;AAEL;;GAEG;AACH,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,YAAY,EAAE,EACrB,KAAK,EAAE,YAAY,EAAE,GACpB,MAAM,CA0BR"}
@@ -5,35 +5,33 @@ export const formatFactLines = (facts) => facts.map((fact) => {
5
5
  if (fact.target_node?.name)
6
6
  entities.push(fact.target_node.name);
7
7
  const entityStr = entities.length > 0 ? ` [${entities.join(" -> ")}]` : "";
8
- return `- ${fact.fact}${entityStr}`;
8
+ return `<fact>${fact.fact}${entityStr}</fact>`;
9
9
  });
10
10
  export const formatNodeLines = (nodes) => nodes.map((node) => {
11
11
  const labels = node.labels?.length ? ` (${node.labels.join(", ")})` : "";
12
12
  const summary = node.summary ? `: ${node.summary}` : "";
13
- return `- **${node.name}**${labels}${summary}`;
13
+ return `<node>${node.name}${labels}${summary}</node>`;
14
14
  });
15
15
  /**
16
16
  * Format Graphiti facts and nodes into a user-facing context block.
17
17
  */
18
18
  export function formatMemoryContext(facts, nodes) {
19
+ if (facts.length === 0 && nodes.length === 0) {
20
+ return "";
21
+ }
19
22
  const sections = [];
20
- sections.push("# Persistent Memory (from Graphiti Knowledge Graph)");
21
- sections.push("");
22
- sections.push("The following information was retrieved from your persistent memory.");
23
- sections.push("Use this context to inform your responses, but do not mention it unless asked.");
24
- sections.push("");
23
+ sections.push("<memory>");
24
+ sections.push("<instruction>Background context only; do not reference in titles, summaries, or opening responses unless directly relevant.</instruction>");
25
25
  if (facts.length > 0) {
26
- sections.push("## Known Facts");
26
+ sections.push("<facts>");
27
27
  sections.push(...formatFactLines(facts));
28
- sections.push("");
28
+ sections.push("</facts>");
29
29
  }
30
30
  if (nodes.length > 0) {
31
- sections.push("## Known Entities");
31
+ sections.push("<nodes>");
32
32
  sections.push(...formatNodeLines(nodes));
33
- sections.push("");
34
- }
35
- if (facts.length === 0 && nodes.length === 0) {
36
- return "";
33
+ sections.push("</nodes>");
37
34
  }
35
+ sections.push("</memory>");
38
36
  return sections.join("\n");
39
37
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opencode-graphiti",
3
- "version": "0.1.3",
3
+ "version": "0.1.4",
4
4
  "description": "OpenCode plugin for persistent memory via Graphiti knowledge graph",
5
5
  "license": "MIT",
6
6
  "main": "./esm/mod.js",
@@ -1,6 +1,9 @@
1
- import type { Part } from "@opencode-ai/sdk";
1
+ import type { Hooks } from "@opencode-ai/plugin";
2
2
  import type { GraphitiClient } from "../services/client.js";
3
3
  import type { SessionManager } from "../session.js";
4
+ type ChatMessageHook = NonNullable<Hooks["chat.message"]>;
5
+ type ChatMessageInput = Parameters<ChatMessageHook>[0];
6
+ type ChatMessageOutput = Parameters<ChatMessageHook>[1];
4
7
  /** Dependencies for the chat message handler. */
5
8
  export interface ChatHandlerDeps {
6
9
  sessionManager: SessionManager;
@@ -8,14 +11,6 @@ export interface ChatHandlerDeps {
8
11
  client: GraphitiClient;
9
12
  }
10
13
  /** Creates the `chat.message` hook handler. */
11
- export declare function createChatHandler(deps: ChatHandlerDeps): ({ sessionID }: {
12
- sessionID: string;
13
- }, output: {
14
- allow_buffering?: boolean;
15
- parts: Part[];
16
- message: {
17
- sessionID: string;
18
- id: string;
19
- };
20
- }) => Promise<void>;
14
+ export declare function createChatHandler(deps: ChatHandlerDeps): ({ sessionID }: ChatMessageInput, output: ChatMessageOutput) => Promise<void>;
15
+ export {};
21
16
  //# sourceMappingURL=chat.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"chat.d.ts","sourceRoot":"","sources":["../../../src/src/handlers/chat.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAI5D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAGpD,iDAAiD;AACjD,MAAM,WAAW,eAAe;IAC9B,cAAc,EAAE,cAAc,CAAC;IAC/B,iBAAiB,EAAE,MAAM,CAAC;IAC1B,MAAM,EAAE,cAAc,CAAC;CACxB;AAED,+CAA+C;AAC/C,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,eAAe,IA6FnD,eAAe;IAAE,SAAS,EAAE,MAAM,CAAA;CAAE,EACpC,QAAQ;IACN,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,KAAK,EAAE,IAAI,EAAE,CAAC;IACd,OAAO,EAAE;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC;CAC5C,mBA4DJ"}
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;AAEjD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAI5D,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,iBAAiB,EAAE,MAAM,CAAC;IAC1B,MAAM,EAAE,cAAc,CAAC;CACxB;AAED,+CAA+C;AAC/C,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,eAAe,IAyGvC,eAAe,gBAAgB,EAAE,QAAQ,iBAAiB,mBAuDzE"}
@@ -1,27 +1,23 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.createChatHandler = createChatHandler;
4
- const context_js_1 = require("../services/context.js");
5
4
  const context_limit_js_1 = require("../services/context-limit.js");
5
+ const context_js_1 = require("../services/context.js");
6
6
  const logger_js_1 = require("../services/logger.js");
7
7
  const utils_js_1 = require("../utils.js");
8
8
  /** Creates the `chat.message` hook handler. */
9
9
  function createChatHandler(deps) {
10
10
  const { sessionManager, injectionInterval, client } = deps;
11
11
  const removeSyntheticMemoryParts = (parts) => parts.filter((part) => {
12
- const synthetic = part.synthetic;
13
- const id = typeof part.id === "string"
14
- ? String(part.id)
15
- : "";
16
- if (!synthetic)
12
+ if (part.type !== "text")
17
13
  return true;
18
- if (id.startsWith("graphiti-memory-"))
14
+ if (part.id?.startsWith("graphiti-memory-"))
19
15
  return false;
20
- if (id.startsWith("graphiti-refresh-"))
16
+ if (part.id?.startsWith("graphiti-refresh-"))
21
17
  return false;
22
18
  return true;
23
19
  });
24
- const injectMemoryContext = async (state, messageText, output, prefix, useUserScope, characterBudget) => {
20
+ const injectMemoryContext = async (state, messageText, output, prefix, useUserScope, characterBudget, shouldReinject) => {
25
21
  const userGroupId = state.userGroupId;
26
22
  const projectFactsPromise = client.searchFacts({
27
23
  query: messageText,
@@ -70,14 +66,28 @@ function createChatHandler(deps) {
70
66
  .slice(0, characterBudget);
71
67
  if (!memoryContext)
72
68
  return;
73
- output.parts.unshift({
74
- type: "text",
75
- text: memoryContext,
76
- id: `${prefix}${Date.now()}`,
77
- sessionID: output.message.sessionID,
78
- messageID: output.message.id,
79
- synthetic: true,
80
- });
69
+ if ("system" in output.message) {
70
+ try {
71
+ output.message.system = memoryContext;
72
+ return;
73
+ }
74
+ catch (_err) {
75
+ // Fall through to synthetic injection.
76
+ }
77
+ }
78
+ if (shouldReinject) {
79
+ output.parts = removeSyntheticMemoryParts(output.parts);
80
+ }
81
+ {
82
+ output.parts.unshift({
83
+ type: "text",
84
+ text: memoryContext,
85
+ id: `${prefix}${Date.now()}`,
86
+ sessionID: output.message.sessionID,
87
+ messageID: output.message.id,
88
+ synthetic: true,
89
+ });
90
+ }
81
91
  logger_js_1.logger.info(`Injected ${projectFacts.length + userFacts.length} facts and ${projectNodes.length + userNodes.length} nodes`);
82
92
  };
83
93
  return async ({ sessionID }, output) => {
@@ -87,7 +97,6 @@ function createChatHandler(deps) {
87
97
  }
88
98
  const { state, resolved } = await sessionManager.resolveSessionState(sessionID);
89
99
  if (!resolved) {
90
- output.allow_buffering = true;
91
100
  logger_js_1.logger.debug("Unable to resolve session for message:", { sessionID });
92
101
  return;
93
102
  }
@@ -112,14 +121,11 @@ function createChatHandler(deps) {
112
121
  injectionInterval;
113
122
  if (!shouldInjectOnFirst && !shouldReinject)
114
123
  return;
115
- if (shouldReinject) {
116
- output.parts = removeSyntheticMemoryParts(output.parts);
117
- }
118
124
  try {
119
125
  const prefix = shouldReinject ? "graphiti-refresh-" : "graphiti-memory-";
120
126
  const useUserScope = shouldInjectOnFirst;
121
127
  const characterBudget = (0, context_limit_js_1.calculateInjectionBudget)(state.contextLimit);
122
- await injectMemoryContext(state, messageText, output, prefix, useUserScope, characterBudget);
128
+ await injectMemoryContext(state, messageText, output, prefix, useUserScope, characterBudget, shouldReinject);
123
129
  state.injectedMemories = true;
124
130
  state.lastInjectionMessageCount = state.messageCount;
125
131
  }
@@ -1,5 +1,9 @@
1
+ import type { Hooks } from "@opencode-ai/plugin";
1
2
  import type { GraphitiClient } from "../services/client.js";
2
3
  import type { SessionManager } from "../session.js";
4
+ type CompactingHook = NonNullable<Hooks["experimental.session.compacting"]>;
5
+ type CompactingInput = Parameters<CompactingHook>[0];
6
+ type CompactingOutput = Parameters<CompactingHook>[1];
3
7
  /** Dependencies for the compacting handler. */
4
8
  export interface CompactingHandlerDeps {
5
9
  sessionManager: SessionManager;
@@ -7,9 +11,6 @@ export interface CompactingHandlerDeps {
7
11
  defaultGroupId: string;
8
12
  }
9
13
  /** Creates the `experimental.session.compacting` hook handler. */
10
- export declare function createCompactingHandler(deps: CompactingHandlerDeps): ({ sessionID }: {
11
- sessionID: string;
12
- }, output: {
13
- context: string[];
14
- }) => Promise<void>;
14
+ export declare function createCompactingHandler(deps: CompactingHandlerDeps): ({ sessionID }: CompactingInput, output: CompactingOutput) => Promise<void>;
15
+ export {};
15
16
  //# sourceMappingURL=compacting.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"compacting.d.ts","sourceRoot":"","sources":["../../../src/src/handlers/compacting.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAI5D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAEpD,+CAA+C;AAC/C,MAAM,WAAW,qBAAqB;IACpC,cAAc,EAAE,cAAc,CAAC;IAC/B,MAAM,EAAE,cAAc,CAAC;IACvB,cAAc,EAAE,MAAM,CAAC;CACxB;AAED,kEAAkE;AAClE,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,qBAAqB,IAI/D,eAAe;IAAE,SAAS,EAAE,MAAM,CAAA;CAAE,EACpC,QAAQ;IAAE,OAAO,EAAE,MAAM,EAAE,CAAA;CAAE,mBAyBhC"}
1
+ {"version":3,"file":"compacting.d.ts","sourceRoot":"","sources":["../../../src/src/handlers/compacting.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAC;AACjD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAI5D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAEpD,KAAK,cAAc,GAAG,WAAW,CAAC,KAAK,CAAC,iCAAiC,CAAC,CAAC,CAAC;AAC5E,KAAK,eAAe,GAAG,UAAU,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,CAAC;AACrD,KAAK,gBAAgB,GAAG,UAAU,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,CAAC;AAEtD,+CAA+C;AAC/C,MAAM,WAAW,qBAAqB;IACpC,cAAc,EAAE,cAAc,CAAC;IAC/B,MAAM,EAAE,cAAc,CAAC;IACvB,cAAc,EAAE,MAAM,CAAC;CACxB;AAED,kEAAkE;AAClE,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,qBAAqB,IAI/D,eAAe,eAAe,EAC9B,QAAQ,gBAAgB,mBAyB3B"}
@@ -1,7 +1,9 @@
1
- import type { Event } from "@opencode-ai/sdk";
1
+ import type { Hooks } from "@opencode-ai/plugin";
2
2
  import type { GraphitiClient } from "../services/client.js";
3
3
  import type { ProviderListClient } from "../services/context-limit.js";
4
4
  import type { SessionManager } from "../session.js";
5
+ type EventHook = NonNullable<Hooks["event"]>;
6
+ type EventInput = Parameters<EventHook>[0];
5
7
  /** Dependencies for the event handler. */
6
8
  export interface EventHandlerDeps {
7
9
  sessionManager: SessionManager;
@@ -12,7 +14,6 @@ export interface EventHandlerDeps {
12
14
  groupIdPrefix: string;
13
15
  }
14
16
  /** Creates the `event` hook handler. */
15
- export declare function createEventHandler(deps: EventHandlerDeps): ({ event }: {
16
- event: Event;
17
- }) => Promise<void>;
17
+ export declare function createEventHandler(deps: EventHandlerDeps): ({ event }: EventInput) => Promise<void>;
18
+ export {};
18
19
  //# sourceMappingURL=event.d.ts.map
@@ -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,kBAAkB,CAAC;AAC9C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAE5D,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,8BAA8B,CAAC;AAGvE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAGpD,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,kBAAkB,CAAC;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,wCAAwC;AACxC,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,gBAAgB,IAWzC,WAAW;IAAE,KAAK,EAAE,KAAK,CAAA;CAAE,mBA+J1C"}
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,uBAAuB,CAAC;AAE5D,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,8BAA8B,CAAC;AAGvE,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,kBAAkB,CAAC;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,wCAAwC;AACxC,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,gBAAgB,IAWzC,WAAW,UAAU,mBA+JpC"}
@@ -38,12 +38,12 @@ class GraphitiClient {
38
38
  value: void 0
39
39
  });
40
40
  this.endpoint = endpoint;
41
- this.client = new index_js_1.Client({ name: "opencode-graphiti", version: "0.1.0" });
41
+ this.client = new index_js_1.Client({ name: "opencode-graphiti", version: "0.1.4" });
42
42
  this.transport = new streamableHttp_js_1.StreamableHTTPClientTransport(new URL(endpoint));
43
43
  }
44
44
  /** Create a fresh MCP Client and Transport pair. */
45
45
  createClientAndTransport() {
46
- this.client = new index_js_1.Client({ name: "opencode-graphiti", version: "0.1.0" });
46
+ this.client = new index_js_1.Client({ name: "opencode-graphiti", version: "0.1.4" });
47
47
  this.transport = new streamableHttp_js_1.StreamableHTTPClientTransport(new URL(this.endpoint));
48
48
  }
49
49
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"compaction.d.ts","sourceRoot":"","sources":["../../../src/src/services/compaction.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAIpE;;GAEG;AACH,wBAAsB,gBAAgB,CAAC,MAAM,EAAE;IAC7C,MAAM,EAAE;QACN,UAAU,EAAE,CAAC,IAAI,EAAE;YACjB,IAAI,EAAE,MAAM,CAAC;YACb,WAAW,EAAE,MAAM,CAAC;YACpB,OAAO,CAAC,EAAE,MAAM,CAAC;YACjB,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;YACrC,iBAAiB,CAAC,EAAE,MAAM,CAAC;SAC5B,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;KACrB,CAAC;IACF,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;CACnB,GAAG,OAAO,CAAC,IAAI,CAAC,CAiBhB;AAED;;GAEG;AACH,wBAAsB,oBAAoB,CAAC,MAAM,EAAE;IACjD,MAAM,EAAE;QACN,WAAW,EAAE,CAAC,IAAI,EAAE;YAClB,KAAK,EAAE,MAAM,CAAC;YACd,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;YACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;SACnB,KAAK,OAAO,CAAC,YAAY,EAAE,CAAC,CAAC;QAC9B,WAAW,EAAE,CAAC,IAAI,EAAE;YAClB,KAAK,EAAE,MAAM,CAAC;YACd,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;YACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;SACnB,KAAK,OAAO,CAAC,YAAY,EAAE,CAAC,CAAC;KAC/B,CAAC;IACF,eAAe,EAAE,MAAM,CAAC;IACxB,QAAQ,EAAE;QACR,OAAO,EAAE,MAAM,CAAC;QAChB,IAAI,CAAC,EAAE,MAAM,CAAC;KACf,CAAC;IACF,cAAc,EAAE,MAAM,EAAE,CAAC;CAC1B,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CA8GpB"}
1
+ {"version":3,"file":"compaction.d.ts","sourceRoot":"","sources":["../../../src/src/services/compaction.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAIpE;;GAEG;AACH,wBAAsB,gBAAgB,CAAC,MAAM,EAAE;IAC7C,MAAM,EAAE;QACN,UAAU,EAAE,CAAC,IAAI,EAAE;YACjB,IAAI,EAAE,MAAM,CAAC;YACb,WAAW,EAAE,MAAM,CAAC;YACpB,OAAO,CAAC,EAAE,MAAM,CAAC;YACjB,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;YACrC,iBAAiB,CAAC,EAAE,MAAM,CAAC;SAC5B,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;KACrB,CAAC;IACF,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;CACnB,GAAG,OAAO,CAAC,IAAI,CAAC,CAiBhB;AAED;;GAEG;AACH,wBAAsB,oBAAoB,CAAC,MAAM,EAAE;IACjD,MAAM,EAAE;QACN,WAAW,EAAE,CAAC,IAAI,EAAE;YAClB,KAAK,EAAE,MAAM,CAAC;YACd,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;YACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;SACnB,KAAK,OAAO,CAAC,YAAY,EAAE,CAAC,CAAC;QAC9B,WAAW,EAAE,CAAC,IAAI,EAAE;YAClB,KAAK,EAAE,MAAM,CAAC;YACd,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;YACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;SACnB,KAAK,OAAO,CAAC,YAAY,EAAE,CAAC,CAAC;KAC/B,CAAC;IACF,eAAe,EAAE,MAAM,CAAC;IACxB,QAAQ,EAAE;QACR,OAAO,EAAE,MAAM,CAAC;QAChB,IAAI,CAAC,EAAE,MAAM,CAAC;KACf,CAAC;IACF,cAAc,EAAE,MAAM,EAAE,CAAC;CAC1B,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAgIpB"}
@@ -73,32 +73,40 @@ async function getCompactionContext(params) {
73
73
  const buildSection = (header, facts, nodes) => {
74
74
  const lines = [];
75
75
  lines.push(header);
76
+ lines.push("<instruction>Background context only; do not reference in titles, summaries, or opening responses unless directly relevant.</instruction>");
76
77
  if (facts.length > 0) {
77
- lines.push("### Facts");
78
+ lines.push("<facts>");
78
79
  lines.push(...(0, context_js_1.formatFactLines)(facts));
80
+ lines.push("</facts>");
79
81
  }
80
82
  if (nodes.length > 0) {
81
- lines.push("### Nodes");
83
+ lines.push("<nodes>");
82
84
  lines.push(...(0, context_js_1.formatNodeLines)(nodes));
85
+ lines.push("</nodes>");
83
86
  }
84
87
  return lines.join("\n");
85
88
  };
86
- const projectSection = buildSection("## Persistent Knowledge (Project)", projectFacts, projectNodes);
87
- const userSection = buildSection("## Persistent Knowledge (User)", userFacts, userNodes);
89
+ const projectSection = buildSection('<memory source="project">', projectFacts, projectNodes);
90
+ const userSection = buildSection('<memory source="user">', userFacts, userNodes);
88
91
  const headerLines = [
89
- "## Current Goal",
92
+ "<summary>",
93
+ "<current_goal>",
90
94
  "- ",
95
+ "</current_goal>",
91
96
  "",
92
- "## Work Completed",
97
+ "<work_completed>",
93
98
  "- ",
99
+ "</work_completed>",
94
100
  "",
95
- "## Remaining Tasks",
101
+ "<remaining_tasks>",
96
102
  "- ",
103
+ "</remaining_tasks>",
97
104
  "",
98
- "## Constraints & Decisions",
105
+ "<constraints_decisions>",
99
106
  "- ",
107
+ "</constraints_decisions>",
100
108
  "",
101
- "## Persistent Knowledge",
109
+ "<persistent_memory>",
102
110
  ];
103
111
  const header = headerLines.join("\n");
104
112
  const base = `${header}\n`;
@@ -108,10 +116,16 @@ async function getCompactionContext(params) {
108
116
  const truncatedProject = projectSection.slice(0, projectBudget);
109
117
  const truncatedUser = userSection.slice(0, userBudget);
110
118
  const sections = [header];
111
- if (truncatedProject.trim())
119
+ if (truncatedProject.trim()) {
112
120
  sections.push(truncatedProject);
113
- if (truncatedUser.trim())
121
+ sections.push("</memory>");
122
+ }
123
+ if (truncatedUser.trim()) {
114
124
  sections.push(truncatedUser);
125
+ sections.push("</memory>");
126
+ }
127
+ sections.push("</persistent_memory>");
128
+ sections.push("</summary>");
115
129
  const content = sections.join("\n").slice(0, characterBudget);
116
130
  return [content];
117
131
  }
@@ -1 +1 @@
1
- {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../../src/src/services/context.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEpE,eAAO,MAAM,eAAe,GAAI,OAAO,YAAY,EAAE,KAAG,MAAM,EAO1D,CAAC;AAEL,eAAO,MAAM,eAAe,GAAI,OAAO,YAAY,EAAE,KAAG,MAAM,EAK1D,CAAC;AAEL;;GAEG;AACH,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,YAAY,EAAE,EACrB,KAAK,EAAE,YAAY,EAAE,GACpB,MAAM,CA8BR"}
1
+ {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../../src/src/services/context.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEpE,eAAO,MAAM,eAAe,GAAI,OAAO,YAAY,EAAE,KAAG,MAAM,EAO1D,CAAC;AAEL,eAAO,MAAM,eAAe,GAAI,OAAO,YAAY,EAAE,KAAG,MAAM,EAK1D,CAAC;AAEL;;GAEG;AACH,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,YAAY,EAAE,EACrB,KAAK,EAAE,YAAY,EAAE,GACpB,MAAM,CA0BR"}
@@ -9,37 +9,35 @@ const formatFactLines = (facts) => facts.map((fact) => {
9
9
  if (fact.target_node?.name)
10
10
  entities.push(fact.target_node.name);
11
11
  const entityStr = entities.length > 0 ? ` [${entities.join(" -> ")}]` : "";
12
- return `- ${fact.fact}${entityStr}`;
12
+ return `<fact>${fact.fact}${entityStr}</fact>`;
13
13
  });
14
14
  exports.formatFactLines = formatFactLines;
15
15
  const formatNodeLines = (nodes) => nodes.map((node) => {
16
16
  const labels = node.labels?.length ? ` (${node.labels.join(", ")})` : "";
17
17
  const summary = node.summary ? `: ${node.summary}` : "";
18
- return `- **${node.name}**${labels}${summary}`;
18
+ return `<node>${node.name}${labels}${summary}</node>`;
19
19
  });
20
20
  exports.formatNodeLines = formatNodeLines;
21
21
  /**
22
22
  * Format Graphiti facts and nodes into a user-facing context block.
23
23
  */
24
24
  function formatMemoryContext(facts, nodes) {
25
+ if (facts.length === 0 && nodes.length === 0) {
26
+ return "";
27
+ }
25
28
  const sections = [];
26
- sections.push("# Persistent Memory (from Graphiti Knowledge Graph)");
27
- sections.push("");
28
- sections.push("The following information was retrieved from your persistent memory.");
29
- sections.push("Use this context to inform your responses, but do not mention it unless asked.");
30
- sections.push("");
29
+ sections.push("<memory>");
30
+ sections.push("<instruction>Background context only; do not reference in titles, summaries, or opening responses unless directly relevant.</instruction>");
31
31
  if (facts.length > 0) {
32
- sections.push("## Known Facts");
32
+ sections.push("<facts>");
33
33
  sections.push(...(0, exports.formatFactLines)(facts));
34
- sections.push("");
34
+ sections.push("</facts>");
35
35
  }
36
36
  if (nodes.length > 0) {
37
- sections.push("## Known Entities");
37
+ sections.push("<nodes>");
38
38
  sections.push(...(0, exports.formatNodeLines)(nodes));
39
- sections.push("");
40
- }
41
- if (facts.length === 0 && nodes.length === 0) {
42
- return "";
39
+ sections.push("</nodes>");
43
40
  }
41
+ sections.push("</memory>");
44
42
  return sections.join("\n");
45
43
  }