@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 +11 -9
- package/dist/cli/pyx-mem.mjs +19 -11
- package/dist/index.d.ts +8 -4
- package/package.json +1 -1
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.
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
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:
|
|
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
|
|
99
|
-
|
|
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
|
|
package/dist/cli/pyx-mem.mjs
CHANGED
|
@@ -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.
|
|
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
|
|
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.
|
|
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
|
|
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.
|
|
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
|
-
|
|
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
|
|
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 &&
|
|
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.
|
|
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
|
-
|
|
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.
|
|
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
|
|
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.
|
|
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
|
|
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;
|