@pyxmate/memory 0.26.4 → 0.27.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -36,12 +36,12 @@ Restart Claude Code. The 7 memory tools (`search_memories`, `store_memory`,
36
36
  `get_memory`, `list_memories`, `delete_memory`, `ingest_memory_file`,
37
37
  `summarize_memory_entity`) are auto-discovered via MCP Tool Search.
38
38
 
39
- **That's the whole setup** — no extra LLM API keys. When the agent calls
40
- `store_memory` without supplying `entities`/`relationships`, the MCP tool
41
- auto-extracts a graph topology by asking the agent's own LLM via MCP sampling
42
- (same pattern as image-description / `extractEntitiesV2` for file ingest).
43
- Your LLM, your credentials. Pass `extractEntities: false` on a per-call basis
44
- to opt out of auto-extraction. See
39
+ **That's the whole setup** — no extra server-side LLM API keys. Graph is a
40
+ relational retrieval dimension, not a search-score boost. When content names
41
+ people, organizations, tools, places, events, or key concepts, the caller LLM
42
+ must pass both `entities` and `relationships`; edges matter as much as nodes because traversal
43
+ needs them to connect related memories. The server does not auto-extract graph
44
+ data and there is no regex fallback. See
45
45
  [`graph-auto-entity-extraction-v2`](https://github.com/pyx-corp/pyx-memory-v1/blob/main/docs/specs/graph-auto-entity-extraction-v2/spec.md)
46
46
  for the full contract.
47
47
 
@@ -68,7 +68,7 @@ await memory.store({
68
68
  const results = await memory.search({ query: 'deadline', limit: 5 });
69
69
  ```
70
70
 
71
- ### Optional: client-side auto-extraction
71
+ ### Optional: caller-side extraction helper
72
72
 
73
73
  `MemoryClient.store(entry, options)` accepts an `enrichment.extractEntities`
74
74
  callback. The SDK invokes your callback (running against **your own** LLM
@@ -94,9 +94,11 @@ await memory.store(
94
94
  );
95
95
  ```
96
96
 
97
+ Entity-free memories are valid. Store responses include `graphEntitiesWritten`
98
+ and `graphRelationshipsWritten`, with zero making an omitted graph write visible.
97
99
  Per-call `entry.extractEntities: false` skips the callback entirely;
98
- `entry.extractEntities: true` with no callback throws a loud error (no silent
99
- no-op). The server never sees an LLM API key — it just persists what you send.
100
+ `entry.extractEntities: true` with no callback throws a loud error. The server
101
+ never sees an LLM API key or runs regex extraction — it persists what you send.
100
102
 
101
103
  ## Entry Points
102
104
 
@@ -516,7 +516,7 @@ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
516
516
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
517
517
 
518
518
  // src/mcp/instructions.ts
519
- var PYX_MEMORY_INSTRUCTIONS = `Use pyx-memory to search durable project/user memory before assuming prior decisions, and to store concise facts after corrections, bug fixes, design decisions, integration discoveries, gotchas, explicit preferences, or "remember this" requests. Store decisions, not deliberation. Include topic and project. Add entities/relationships for named people, tools, organizations, locations, or events. Use file ingest for documents/images worth persisting; images require a description.`;
519
+ var PYX_MEMORY_INSTRUCTIONS = `Use pyx-memory to search durable project/user memory before assuming prior decisions, and to store concise facts after corrections, bug fixes, design decisions, integration discoveries, gotchas, explicit preferences, or "remember this" requests. Store decisions, not deliberation. Include topic and project. When content names people, organizations, tools, places, events, or key concepts, you (the caller) must extract and pass both entities and relationships \u2014 the server does not auto-extract them. Edges matter as much as nodes: without relationships the graph cannot connect related memories. Use file ingest for documents/images worth persisting; images require a description.`;
520
520
 
521
521
  // src/mcp/sampling.ts
522
522
  function createSamplingClient(server) {
@@ -15524,11 +15524,15 @@ var relationshipTypes = [
15524
15524
  "WORKS_AT",
15525
15525
  "LOCATED_IN"
15526
15526
  ];
15527
+ var storeTargets = ["sqlite", "vector", "graph"];
15527
15528
  var inputShape7 = {
15528
15529
  content: external_exports.string().min(1).describe("Concise factual statement to persist; decision, not deliberation."),
15529
15530
  topic: external_exports.string().min(1).describe("Required metadata.topic for retrieval grouping."),
15530
15531
  project: external_exports.string().min(1).describe("Required metadata.project namespace."),
15531
15532
  type: external_exports.enum(["short-term", "long-term", "working", "episodic", "summary"]).optional().describe("Memory type. Default long-term."),
15533
+ targets: external_exports.array(external_exports.enum(storeTargets)).optional().describe(
15534
+ "Storage targets. Include 'graph' when you provide entities/relationships or want zero graph write counts reported."
15535
+ ),
15532
15536
  importance: external_exports.number().int().min(1).max(10).optional().describe("Importance 1\u201310."),
15533
15537
  eventTime: external_exports.string().optional().describe("ISO-8601 timestamp of when the event happened (bi-temporal)."),
15534
15538
  source: external_exports.string().optional().describe("Free-form origin (filename, URL, conversation id)."),
@@ -15541,7 +15545,7 @@ var inputShape7 = {
15541
15545
  type: external_exports.enum(entityTypes).describe("Entity type.")
15542
15546
  })
15543
15547
  ).optional().describe(
15544
- "Named entities mentioned by the content; required when relationships are present. When omitted, the MCP tool may auto-extract via the connected client's LLM (MCP sampling) before sending to the server; set `extractEntities:false` to skip."
15548
+ "Named entities mentioned by the content. The caller LLM must extract and pass these when the content names people, organizations, tools, places, events, or key concepts; the server does not auto-extract them."
15545
15549
  ),
15546
15550
  relationships: external_exports.array(
15547
15551
  external_exports.object({
@@ -15550,10 +15554,10 @@ var inputShape7 = {
15550
15554
  type: external_exports.enum(relationshipTypes).describe("Relationship type.")
15551
15555
  })
15552
15556
  ).optional().describe(
15553
- "Edges between entities; source and target must be entity names from this request. When omitted, the MCP tool may auto-extract via the connected client's LLM (MCP sampling) before sending to the server; set `extractEntities:false` to skip."
15557
+ "Edges between entities; source and target must be entity names from this request. Relationships matter as much as entities because graph traversal needs edges to connect related memories."
15554
15558
  ),
15555
15559
  extractEntities: external_exports.boolean().optional().describe(
15556
- "Override client-side auto-extraction (MCP sampling): false to skip, true to require (errors if the connected client does not support sampling)."
15560
+ "Override extraction: false skips caller-side extraction; true requires caller entities or MCP sampling and errors loudly if neither is available."
15557
15561
  ),
15558
15562
  ...scopeShape
15559
15563
  };
@@ -15561,7 +15565,7 @@ var storeMemoryTool = {
15561
15565
  name: "store_memory",
15562
15566
  config: {
15563
15567
  title: "Store pyx-memory entry",
15564
- description: "Store one concise factual memory with required topic and project metadata. Provide entities/relationships explicitly when you want exact graph topology; when omitted, the MCP tool may auto-extract using your own LLM via MCP sampling before sending to the server.",
15568
+ description: "Store one concise factual memory with required topic and project metadata. When content names people, organizations, tools, places, events, or key concepts, the caller LLM must extract and pass entities and relationships; the server does not auto-extract them. Relationships (edges) matter as much as entities because graph traversal needs edges to connect related memories. Entity-free memories are valid; omit graph data or set extractEntities:false when there are no graph facts.",
15565
15569
  inputSchema: inputShape7,
15566
15570
  annotations: { readOnlyHint: false, idempotentHint: false, openWorldHint: true }
15567
15571
  },
@@ -15575,12 +15579,14 @@ var storeMemoryTool = {
15575
15579
  const samplingAvailable = deps.samplingClient?.isAvailable() ?? false;
15576
15580
  const optedOut = args.extractEntities === false;
15577
15581
  const forced = args.extractEntities === true;
15578
- if (forced && !samplingAvailable) {
15582
+ const graphTargeted = args.targets?.includes("graph") ?? true;
15583
+ const hasCallerEntities = (entities?.length ?? 0) > 0;
15584
+ if (forced && graphTargeted && !samplingAvailable && !hasCallerEntities) {
15579
15585
  throw new Error(
15580
- "extractEntities=true requested but the connected MCP client did not advertise the `sampling` capability. Pass entities/relationships explicitly, set extractEntities:false, or connect a sampling-capable client."
15586
+ "extractEntities=true requested but the connected MCP client did not advertise the sampling capability. Pass entities/relationships explicitly, set extractEntities:false, or connect a sampling-capable client."
15581
15587
  );
15582
15588
  }
15583
- if (deps.samplingClient && samplingAvailable && !optedOut && (entities?.length ?? 0) === 0) {
15589
+ if (graphTargeted && deps.samplingClient && samplingAvailable && !optedOut && !hasCallerEntities) {
15584
15590
  const prompt = buildExtractionPrompt(args.content);
15585
15591
  const completion = await deps.samplingClient.complete(
15586
15592
  prompt,
@@ -15594,6 +15600,7 @@ var storeMemoryTool = {
15594
15600
  const body = {
15595
15601
  content: args.content,
15596
15602
  type: args.type ?? "long-term",
15603
+ targets: args.targets,
15597
15604
  metadata: {
15598
15605
  source: "agent",
15599
15606
  topic: args.topic,
@@ -15605,7 +15612,8 @@ var storeMemoryTool = {
15605
15612
  sessionId: args.sessionId,
15606
15613
  parentId: args.parentId,
15607
15614
  entities,
15608
- relationships
15615
+ relationships,
15616
+ ...args.extractEntities === false ? { extractEntities: false } : {}
15609
15617
  };
15610
15618
  const res = await http.requestJson({
15611
15619
  method: "POST",
@@ -15678,7 +15686,7 @@ var ALL_TOOL_NAMES = ALL_TOOLS.map((t) => t.name);
15678
15686
  // src/mcp/server.ts
15679
15687
  async function runMcpServer(opts) {
15680
15688
  const fetchImpl = opts.fetchImpl ?? fetch;
15681
- const version2 = opts.version ?? (true ? "0.26.4" : "0.0.0-dev");
15689
+ const version2 = opts.version ?? (true ? "0.27.0" : "0.0.0-dev");
15682
15690
  const server = new McpServer(
15683
15691
  { name: "pyx-memory", version: version2 },
15684
15692
  { instructions: PYX_MEMORY_INSTRUCTIONS, capabilities: { tools: {} } }
@@ -15865,7 +15873,7 @@ function mcpInstallClaudeCodeCommand(opts = {}) {
15865
15873
  process.stdout.write(
15866
15874
  `Installed pyx-memory MCP server in Claude Code (scope: ${scope}).
15867
15875
  Restart Claude Code to make the tools available. No API key was written to .mcp.json \u2014 credentials live in the OS credential store.
15868
- Graph entities/relationships auto-extract via your client's own LLM (MCP sampling) when you call store_memory without entities \u2014 no extra LLM keys to configure.
15876
+ To populate the knowledge graph, pass entities and relationships when you call store_memory \u2014 the server does not auto-extract them. Sampling-capable MCP clients can fill them from your own LLM; Claude Code does not advertise sampling, so extract and pass them yourself.
15869
15877
  `
15870
15878
  );
15871
15879
  return EXIT.OK;
package/dist/index.d.ts CHANGED
@@ -482,6 +482,10 @@ interface MemoryEntry {
482
482
  sensitivity?: SensitivityLevel;
483
483
  /** Whether the content field is encrypted at rest. */
484
484
  encrypted?: boolean;
485
+ /** Number of graph entities written by this store call. Present on store responses. */
486
+ graphEntitiesWritten?: number;
487
+ /** Number of graph relationships written by this store call. Present on store responses. */
488
+ graphRelationshipsWritten?: number;
485
489
  /** Tenant ID for multi-tenant isolation. */
486
490
  tenantId?: string;
487
491
  /** User ID within the tenant. */
@@ -620,11 +624,11 @@ type StoreInput = Omit<MemoryEntry, 'id' | 'createdAt'> & {
620
624
  createdAt?: string;
621
625
  /** Storage targets. Default: ["sqlite", "vector"]. */
622
626
  targets?: StoreTarget[];
623
- /** Agent-provided entities for graph storage. Required when targets includes "graph". */
627
+ /** Agent-provided entities for graph storage. */
624
628
  entities?: IngestEntity[];
625
629
  /** Agent-provided relationships for graph storage. */
626
630
  relationships?: IngestRelationship[];
627
- /** Override server-side auto-extraction for this store call. */
631
+ /** Override graph entity extraction for this store call. */
628
632
  extractEntities?: boolean;
629
633
  /** Graph-failure handling. Default: "throw" (loud) — see GraphFailureMode. */
630
634
  graphFailureMode?: GraphFailureMode;
@@ -637,11 +641,11 @@ interface MemoryIngestRequest {
637
641
  sessionId?: string;
638
642
  /** Storage targets. Default: ["sqlite", "vector"]. */
639
643
  targets?: StoreTarget[];
640
- /** Agent-provided entities for graph storage. Required when targets includes "graph". */
644
+ /** Agent-provided entities for graph storage. */
641
645
  entities?: IngestEntity[];
642
646
  /** Agent-provided relationships for graph storage. */
643
647
  relationships?: IngestRelationship[];
644
- /** Override server-side auto-extraction for this ingest request. */
648
+ /** Override graph entity extraction for this ingest request. */
645
649
  extractEntities?: boolean;
646
650
  /** Graph-failure handling. Default: "throw" (loud) — see GraphFailureMode. */
647
651
  graphFailureMode?: GraphFailureMode;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pyxmate/memory",
3
- "version": "0.26.4",
3
+ "version": "0.27.0",
4
4
  "type": "module",
5
5
  "description": "SDK for pyx-memory — Memory as a Service for AI agents",
6
6
  "license": "MIT",