agent-memory-graph 0.3.0 → 0.4.1

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.
@@ -5774,6 +5774,63 @@ var entry_default = definePluginEntry({
5774
5774
  name: "Memory Graph",
5775
5775
  description: "Auto-builds a knowledge graph from conversations. Extracts entities/relationships and exposes graph query tools.",
5776
5776
  register(api) {
5777
+ api.on(
5778
+ "before_prompt_build",
5779
+ async (event, ctx) => {
5780
+ const config = ctx?.pluginConfig;
5781
+ if (config?.promptInjection === false) return;
5782
+ try {
5783
+ const graph = await getGraph(config);
5784
+ const stats = graph.stats();
5785
+ if (stats.entities === 0) return;
5786
+ const prompt = event.prompt || "";
5787
+ let contextLines = [];
5788
+ const PRIORITY_TYPES = ["Project", "Person", "Platform", "Organization", "Company", "Event", "System"];
5789
+ const SKIP_TYPES = ["Tool", "Concept", "File", "Award"];
5790
+ if (prompt && prompt.length > 20) {
5791
+ const searchQuery = prompt.slice(0, 100).replace(/[\n\r]+/g, " ").trim();
5792
+ const results = graph.search(searchQuery, 15);
5793
+ if (results.length > 0) {
5794
+ const filtered = results.filter((r) => !SKIP_TYPES.includes(r.entity.type)).sort((a, b) => {
5795
+ const aPriority = PRIORITY_TYPES.indexOf(a.entity.type);
5796
+ const bPriority = PRIORITY_TYPES.indexOf(b.entity.type);
5797
+ const aScore = (aPriority >= 0 ? 100 - aPriority : 50) + (a.relations?.length || 0);
5798
+ const bScore = (bPriority >= 0 ? 100 - bPriority : 50) + (b.relations?.length || 0);
5799
+ return bScore - aScore;
5800
+ }).slice(0, 5);
5801
+ if (filtered.length > 0) {
5802
+ contextLines = filtered.map((r) => {
5803
+ const rels = r.relations?.filter((rel) => !SKIP_TYPES.includes(rel.targetType || "")).slice(0, 3).map((rel) => `${rel.direction === "outgoing" ? "\u2192" : "\u2190"} ${rel.relation} ${rel.target}`).join(", ") || "";
5804
+ return `${r.entity.name} (${r.entity.type})${rels ? ": " + rels : ""}`;
5805
+ });
5806
+ }
5807
+ }
5808
+ }
5809
+ if (contextLines.length === 0) {
5810
+ const allEntities = graph.listEntities({ limit: 30, sortBy: "updated_at" });
5811
+ const prioritized = allEntities.filter((e) => !SKIP_TYPES.includes(e.type)).sort((a, b) => {
5812
+ const aPriority = PRIORITY_TYPES.indexOf(a.type);
5813
+ const bPriority = PRIORITY_TYPES.indexOf(b.type);
5814
+ return (bPriority >= 0 ? bPriority : -1) - (aPriority >= 0 ? aPriority : -1);
5815
+ }).slice(0, 5);
5816
+ if (prioritized.length > 0) {
5817
+ contextLines = prioritized.map((e) => `${e.name} (${e.type})`);
5818
+ }
5819
+ }
5820
+ if (contextLines.length === 0) return;
5821
+ const injection = `## Knowledge Graph Context (auto-injected by memory-graph plugin)
5822
+ Relevant entities from your knowledge graph:
5823
+ ${contextLines.join("\n")}
5824
+
5825
+ Use memory_graph_query or memory_graph_search tools for more details when needed.`;
5826
+ return { appendContext: injection };
5827
+ } catch (err) {
5828
+ console.warn("[memory-graph] Prompt injection failed:", err.message);
5829
+ return;
5830
+ }
5831
+ },
5832
+ { priority: 10 }
5833
+ );
5777
5834
  api.on(
5778
5835
  "message_received",
5779
5836
  async (event) => {
@@ -5827,6 +5884,58 @@ var entry_default = definePluginEntry({
5827
5884
  },
5828
5885
  { priority: 10 }
5829
5886
  );
5887
+ api.on(
5888
+ "agent_end",
5889
+ async (event, ctx) => {
5890
+ const config = ctx?.pluginConfig;
5891
+ const sessionKey = ctx?.sessionKey || "";
5892
+ const messages = event.messages || [];
5893
+ console.log(`[memory-graph] agent_end fired: sessionKey=${sessionKey}, messages=${messages.length}, success=${event.success}`);
5894
+ if (config?.sessionSummary === false) return;
5895
+ if (!sessionKey) return;
5896
+ const textParts = [];
5897
+ for (const msg of messages) {
5898
+ const role = msg.role || "unknown";
5899
+ if (role !== "user" && role !== "assistant") continue;
5900
+ const text = typeof msg.content === "string" ? msg.content : Array.isArray(msg.content) ? msg.content.filter((p) => p.type === "text").map((p) => p.text).join(" ") : "";
5901
+ if (!text || text.length < MIN_MEANINGFUL_LENGTH) continue;
5902
+ textParts.push(`[${role}]: ${text.slice(0, 500)}`);
5903
+ }
5904
+ if (textParts.length < 2) return;
5905
+ const transcript = textParts.join("\n").slice(0, 3e3);
5906
+ try {
5907
+ const graph = await getGraph(config);
5908
+ const { OpenAI } = await import("openai");
5909
+ const client = new OpenAI({
5910
+ apiKey: process.env.OPENAI_API_KEY,
5911
+ baseURL: process.env.OPENAI_BASE_URL
5912
+ });
5913
+ const summaryResponse = await client.chat.completions.create({
5914
+ model: config?.extractionModel || process.env.MEMORY_GRAPH_MODEL || "kr/claude-haiku-4.5",
5915
+ messages: [
5916
+ {
5917
+ role: "system",
5918
+ content: `You are a session summarizer for a knowledge graph. Given a conversation transcript, extract a 2-4 sentence summary of KEY ACTIONS taken (what was built, fixed, published, decided, configured). Focus on concrete outcomes, versions, platforms, and decisions. Skip casual chat and test/debug noise. If nothing meaningful happened, respond with "NO_SUMMARY". Output plain text only.`
5919
+ },
5920
+ { role: "user", content: transcript }
5921
+ ],
5922
+ max_tokens: 300,
5923
+ temperature: 0.3
5924
+ });
5925
+ const summary = summaryResponse.choices?.[0]?.message?.content?.trim();
5926
+ if (summary && summary !== "NO_SUMMARY" && summary.length >= 20) {
5927
+ const today = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
5928
+ await graph.ingest(summary, { source: `session-summary-${today}`, sessionId: sessionKey });
5929
+ console.log(`[memory-graph] Session summary ingested (${textParts.length} msgs \u2192 ${summary.length} chars)`);
5930
+ } else {
5931
+ console.log(`[memory-graph] No meaningful summary for session (${textParts.length} msgs)`);
5932
+ }
5933
+ } catch (err) {
5934
+ console.warn("[memory-graph] Session summary failed:", err.message);
5935
+ }
5936
+ },
5937
+ { priority: 10 }
5938
+ );
5830
5939
  api.on(
5831
5940
  "session_end",
5832
5941
  async (event, ctx) => {
@@ -71,6 +71,11 @@
71
71
  }
72
72
  },
73
73
  "default": []
74
+ },
75
+ "promptInjection": {
76
+ "type": "boolean",
77
+ "description": "Automatically inject relevant graph context into every agent prompt",
78
+ "default": true
74
79
  }
75
80
  },
76
81
  "additionalProperties": false
@@ -79,7 +84,7 @@
79
84
  "openclawVersion": ">=2026.3.24",
80
85
  "entry": "dist/plugin/entry.js"
81
86
  },
82
- "version": "0.1.1",
87
+ "version": "0.4.1",
83
88
  "author": "KLSGG",
84
89
  "repository": "https://github.com/KLSGG/agent-memory-graph",
85
90
  "license": "MIT",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agent-memory-graph",
3
- "version": "0.3.0",
3
+ "version": "0.4.1",
4
4
  "description": "Domain-agnostic knowledge graph memory for AI agents. Zero-config, local-first, SQLite-powered. Works as OpenClaw skill (CLI) or plugin (auto-hook).",
5
5
  "type": "module",
6
6
  "main": "dist/src/index.js",