@pyxmate/memory 1.22.3 → 1.23.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/dist/agent-contract.d.ts +3 -2
- package/dist/agent-contract.mjs +3 -1
- package/dist/{chunk-QWLTZIIK.mjs → chunk-7YHCNO3N.mjs} +1 -1
- package/dist/{chunk-BUKDWHTY.mjs → chunk-C46EE5BH.mjs} +5 -0
- package/dist/{chunk-EZERG25I.mjs → chunk-QD7G23CN.mjs} +12 -7
- package/dist/{chunk-HVJZDJGH.mjs → chunk-SGL73IY5.mjs} +1 -1
- package/dist/cli/pyx-mem.mjs +90 -30
- package/dist/dashboard.mjs +3 -3
- package/dist/{data-plane-contract-webbeMs5.d.ts → data-plane-contract-C5VqxrpF.d.ts} +5 -0
- package/dist/data-plane-contract.d.ts +1 -1
- package/dist/data-plane-contract.mjs +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.mjs +2 -2
- package/dist/react.mjs +3 -3
- package/package.json +1 -1
package/dist/agent-contract.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
declare const PYX_MEMORY_INSTRUCTIONS = "Use pyx-memory for durable memory across sessions, proactively \u2014 do not wait to be told. SEARCH before assuming: at the start of a task, and before proposing an approach or re-deriving a past decision, search memory for the project and topic; resolve relative times (\"last year\", \"\uB450 \uB2EC \uC804\") to an absolute ISO-8601 anchorTime
|
|
1
|
+
declare const PYX_MEMORY_INSTRUCTIONS = "Use pyx-memory for durable memory across sessions, proactively \u2014 do not wait to be told. It is the memory of record: a host's built-in memory (e.g. MEMORY.md) never replaces it. At the start of each conversation, load the tools (even if deferred) and call get_memory_rules; its rules are current and supersede any older pasted copy. SEARCH before assuming: at the start of a task, and before proposing an approach or re-deriving a past decision, search memory for the project and topic; resolve relative times (\"last year\", \"\uB450 \uB2EC \uC804\") to an absolute ISO-8601 anchorTime. STORE when durable state settles \u2014 usually before your final response or handoff; if nothing durable changed, store nothing. Otherwise capture a fact (correction, bug fix + root cause, design decision + reasoning, integration/API detail, gotcha, preference, \"remember this\"), a reusable process once stable, a milestone snapshot (type episodic, not a running log), or a changed decision (store the new state with eventTime, never a silent overwrite, so lineage traces it) \u2014 concise facts not deliberation, each with topic and project. Pass eventTime (ISO-8601, when the fact took effect) for anything that can change or go stale; recency ordering, \"as of\" queries, and stale-vs-current resolution all key off it. After a memory informs your work, call reinforce so it stays in the quick/medium tiers. When the user corrects you, call record_correction; before a task, call fetch_applicable_corrections. When content names people, organizations, tools, places, events, or key concepts, pass entities and relationships \u2014 you build the graph, the server does not extract it; a multi-entity store with no connecting edge is refused. Match search effort to need: quick (default, strongest) for routine recall, deep for full/archived history; use lineage to trace how a fact changed. userId/teamId/agentId and callerAccessLevel are attribution filters, not a security isolation boundary.";
|
|
2
2
|
declare const PYX_MEMORY_COMPANION_CORE_INSTRUCTIONS = "Use pyx-memory for durable memory across sessions, proactively \u2014 do not wait to be told. SEARCH (search_memories) before assuming: at the start of a task, and before re-deriving a past decision, search memory for the project and topic; resolve relative times (\"last year\", \"\uB450 \uB2EC \uC804\") to an absolute ISO-8601 anchorTime so results rank by proximity to that time. Match search effort to need: quick (default, strongest) for routine recall, deep for full/archived history. STORE (store_memory) when durable state settles \u2014 usually before your final response; if nothing durable changed, store nothing. Capture concise facts, not deliberation \u2014 a correction, bug fix + root cause, decision + reasoning, integration detail, gotcha, preference, or an explicit \"remember this\" \u2014 each with topic and project. Pass eventTime (ISO-8601, when the fact took effect) for anything that can change or go stale; recency ordering and stale-vs-current resolution key off it. When content names people, organizations, tools, places, events, or key concepts, pass entities and relationships \u2014 you build the graph; a multi-entity store with no connecting edge is refused. Recalled memories reflect what was true when written \u2014 verify named files, flags, and versions before acting.";
|
|
3
3
|
declare const PERSISTENT_MEMORY_SECTION: string;
|
|
4
|
+
declare const PASTE_MEMORY_RULES: string;
|
|
4
5
|
declare function buildDesignGuide({ appName }: {
|
|
5
6
|
appName: string;
|
|
6
7
|
}): string;
|
|
@@ -38,4 +39,4 @@ declare const STRUCTURE_GRAPH_PROMPT_DESC = "Returns a prompt that extracts the
|
|
|
38
39
|
declare function buildGraphStructuringPrompt(content: string): string;
|
|
39
40
|
declare function buildAgentSnippet(): string;
|
|
40
41
|
|
|
41
|
-
export { AGENT_TARGETS, PERSISTENT_MEMORY_SECTION, PYX_MEMORY_COMPANION_CORE_INSTRUCTIONS, PYX_MEMORY_INSTRUCTIONS, SEARCH_ENUMERATION_CONCEPT_DESC, SEARCH_LIMIT_DESC, STORE_ENTITIES_DESC, STORE_EVENT_TIME_DESC, STORE_RELATIONSHIPS_DESC, STORE_TOOL_DESC, STORE_TRIPLES_DESC, STRUCTURE_GRAPH_PROMPT_DESC, buildAgentSnippet, buildDesignGuide, buildGraphStructuringPrompt };
|
|
42
|
+
export { AGENT_TARGETS, PASTE_MEMORY_RULES, PERSISTENT_MEMORY_SECTION, PYX_MEMORY_COMPANION_CORE_INSTRUCTIONS, PYX_MEMORY_INSTRUCTIONS, SEARCH_ENUMERATION_CONCEPT_DESC, SEARCH_LIMIT_DESC, STORE_ENTITIES_DESC, STORE_EVENT_TIME_DESC, STORE_RELATIONSHIPS_DESC, STORE_TOOL_DESC, STORE_TRIPLES_DESC, STRUCTURE_GRAPH_PROMPT_DESC, buildAgentSnippet, buildDesignGuide, buildGraphStructuringPrompt };
|
package/dist/agent-contract.mjs
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
AGENT_TARGETS,
|
|
3
|
+
PASTE_MEMORY_RULES,
|
|
3
4
|
PERSISTENT_MEMORY_SECTION,
|
|
4
5
|
PYX_MEMORY_COMPANION_CORE_INSTRUCTIONS,
|
|
5
6
|
PYX_MEMORY_INSTRUCTIONS,
|
|
@@ -14,9 +15,10 @@ import {
|
|
|
14
15
|
buildAgentSnippet,
|
|
15
16
|
buildDesignGuide,
|
|
16
17
|
buildGraphStructuringPrompt
|
|
17
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-QD7G23CN.mjs";
|
|
18
19
|
export {
|
|
19
20
|
AGENT_TARGETS,
|
|
21
|
+
PASTE_MEMORY_RULES,
|
|
20
22
|
PERSISTENT_MEMORY_SECTION,
|
|
21
23
|
PYX_MEMORY_COMPANION_CORE_INSTRUCTIONS,
|
|
22
24
|
PYX_MEMORY_INSTRUCTIONS,
|
|
@@ -256,6 +256,11 @@ var DATA_PLANE_OPERATION_COVERAGE = {
|
|
|
256
256
|
reasonCode: "nonchargeable_operation",
|
|
257
257
|
reason: "status is nonchargeable and must bypass data-plane reservation"
|
|
258
258
|
},
|
|
259
|
+
"mcp:get_memory_rules": {
|
|
260
|
+
support: "not_execution_ready",
|
|
261
|
+
reasonCode: "nonchargeable_operation",
|
|
262
|
+
reason: "the rules text is nonchargeable and must bypass data-plane reservation"
|
|
263
|
+
},
|
|
259
264
|
"mcp:get_user_profile": { support: "sqlite_atomic_one_step" },
|
|
260
265
|
"mcp:upsert_user_profile": { support: "sqlite_atomic_one_step" },
|
|
261
266
|
"mcp:record_correction": { support: "sqlite_atomic_one_step" },
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
// src/contract/index.ts
|
|
2
|
-
var PYX_MEMORY_INSTRUCTIONS = `Use pyx-memory for durable memory across sessions, proactively \u2014 do not wait to be told. SEARCH before assuming: at the start of a task, and before proposing an approach or re-deriving a past decision, search memory for the project and topic; resolve relative times ("last year", "\uB450 \uB2EC \uC804") to an absolute ISO-8601 anchorTime
|
|
2
|
+
var PYX_MEMORY_INSTRUCTIONS = `Use pyx-memory for durable memory across sessions, proactively \u2014 do not wait to be told. It is the memory of record: a host's built-in memory (e.g. MEMORY.md) never replaces it. At the start of each conversation, load the tools (even if deferred) and call get_memory_rules; its rules are current and supersede any older pasted copy. SEARCH before assuming: at the start of a task, and before proposing an approach or re-deriving a past decision, search memory for the project and topic; resolve relative times ("last year", "\uB450 \uB2EC \uC804") to an absolute ISO-8601 anchorTime. STORE when durable state settles \u2014 usually before your final response or handoff; if nothing durable changed, store nothing. Otherwise capture a fact (correction, bug fix + root cause, design decision + reasoning, integration/API detail, gotcha, preference, "remember this"), a reusable process once stable, a milestone snapshot (type episodic, not a running log), or a changed decision (store the new state with eventTime, never a silent overwrite, so lineage traces it) \u2014 concise facts not deliberation, each with topic and project. Pass eventTime (ISO-8601, when the fact took effect) for anything that can change or go stale; recency ordering, "as of" queries, and stale-vs-current resolution all key off it. After a memory informs your work, call reinforce so it stays in the quick/medium tiers. When the user corrects you, call record_correction; before a task, call fetch_applicable_corrections. When content names people, organizations, tools, places, events, or key concepts, pass entities and relationships \u2014 you build the graph, the server does not extract it; a multi-entity store with no connecting edge is refused. Match search effort to need: quick (default, strongest) for routine recall, deep for full/archived history; use lineage to trace how a fact changed. userId/teamId/agentId and callerAccessLevel are attribution filters, not a security isolation boundary.`;
|
|
3
3
|
var PYX_MEMORY_COMPANION_CORE_INSTRUCTIONS = `Use pyx-memory for durable memory across sessions, proactively \u2014 do not wait to be told. SEARCH (search_memories) before assuming: at the start of a task, and before re-deriving a past decision, search memory for the project and topic; resolve relative times ("last year", "\uB450 \uB2EC \uC804") to an absolute ISO-8601 anchorTime so results rank by proximity to that time. Match search effort to need: quick (default, strongest) for routine recall, deep for full/archived history. STORE (store_memory) when durable state settles \u2014 usually before your final response; if nothing durable changed, store nothing. Capture concise facts, not deliberation \u2014 a correction, bug fix + root cause, decision + reasoning, integration detail, gotcha, preference, or an explicit "remember this" \u2014 each with topic and project. Pass eventTime (ISO-8601, when the fact took effect) for anything that can change or go stale; recency ordering and stale-vs-current resolution key off it. When content names people, organizations, tools, places, events, or key concepts, pass entities and relationships \u2014 you build the graph; a multi-entity store with no connecting edge is refused. Recalled memories reflect what was true when written \u2014 verify named files, flags, and versions before acting.`;
|
|
4
4
|
var PERSISTENT_MEMORY_SECTION = [
|
|
5
5
|
"## Persistent Memory",
|
|
6
6
|
"",
|
|
7
|
-
"Use the configured `pyx-memory` MCP tools
|
|
7
|
+
"Use the configured `pyx-memory` MCP tools as your memory of record across conversations; a host's built-in memory (e.g. `MEMORY.md`) never replaces them. Load them first if deferred.",
|
|
8
8
|
"",
|
|
9
9
|
"Search before assuming:",
|
|
10
10
|
"",
|
|
@@ -28,7 +28,7 @@ var PERSISTENT_MEMORY_SECTION = [
|
|
|
28
28
|
"Store when durable state settles, usually before a final response/handoff; if nothing durable changed, store nothing. Capture:",
|
|
29
29
|
"",
|
|
30
30
|
'- Facts (default) \u2014 one correction/preference, root-cause fix, reasoned design decision, integration detail, gotcha, or explicit "remember this" request per memory.',
|
|
31
|
-
"- Process (`type: long-term`) \u2014 a reusable workflow, convention, or playbook a fresh session should follow
|
|
31
|
+
"- Process (`type: long-term`) \u2014 a reusable workflow, convention, or playbook a fresh session should follow, once stabilized or adopted.",
|
|
32
32
|
"- Trajectory (`type: episodic`) \u2014 only at a real milestone, handoff, or user-requested checkpoint: one dated snapshot of what changed, where it stands, and the open frontier. Not a running log.",
|
|
33
33
|
"- Ordinary conversational facts omit `id` and evolve through new entries with `eventTime`. Only application-owned canonical mirrors may reuse an app-supplied stable `id` with `metadata.dbRef.revision`. Revisions are opaque; retry with the same stable `id`, opaque revision, and byte-exact identical payload. Never invent, randomize, or timestamp-suffix IDs; replay stale snapshots or manifests; or use store-new plus delete-old. On `revision_reuse_conflict`, reread the authoritative source; do not mint a new ID or revision.",
|
|
34
34
|
"",
|
|
@@ -36,15 +36,19 @@ var PERSISTENT_MEMORY_SECTION = [
|
|
|
36
36
|
"",
|
|
37
37
|
"- Always include `topic` and `project`.",
|
|
38
38
|
"- Store concise facts and decisions, not deliberation.",
|
|
39
|
-
"- Keep one memory per concept; do not bundle unrelated facts.",
|
|
40
39
|
"- Do not store ephemeral files, raw logs, or progress. Aggregate high-frequency streams into a dated fact/summary with `eventTime`; never one memory or graph node per sample.",
|
|
41
40
|
"- Pass `eventTime` (ISO-8601, when a changeable/stale fact happened/took effect); recency/as-of/stale-vs-current key off it.",
|
|
42
41
|
"- Graph is for retrieval. For named people, organizations, tools, places, events, or concepts, pass `entities` + `relationships` (caller-wins); connect multi-entity stores with a relationship or `triples`. Relationships matter as much as entities. Entity-free memories are valid.",
|
|
43
42
|
'- Use specific durable entities, never catch-all hubs ("me", "health"); bounded `IS_A` categories are the exception.',
|
|
44
43
|
'- For countable categories the user may later enumerate, add a canonical category `CONCEPT` node and an `IS_A` edge from each member to it (`"yoga"` IS_A `"fitness classes"`).',
|
|
45
44
|
"- Taxonomy: when a store response reports unnamed clusters, call get_taxonomy_state and name each via name_cluster (short, domain-true, user's language); rename only when composition clearly changed.",
|
|
46
|
-
"- Ingest documents/images only when
|
|
47
|
-
"- Before ingesting docx/xlsx/pptx,
|
|
45
|
+
"- Ingest documents/images only when worth persisting; images need a short description to be searchable.",
|
|
46
|
+
"- Before ingesting docx/xlsx/pptx, pre-extract to `.md`; headings keep section context."
|
|
47
|
+
].join("\n");
|
|
48
|
+
var PASTE_MEMORY_RULES = [
|
|
49
|
+
"## Persistent Memory",
|
|
50
|
+
"",
|
|
51
|
+
"Use the configured `pyx-memory` MCP tools as your memory of record across conversations; a host's built-in memory never replaces them. At the start of every conversation, load them (even if deferred), call `get_memory_rules`, and follow the rules it returns \u2014 they are always current."
|
|
48
52
|
].join("\n");
|
|
49
53
|
function buildDesignGuide({ appName }) {
|
|
50
54
|
const name = appName.trim() || "your app";
|
|
@@ -154,7 +158,7 @@ function buildAgentSnippet() {
|
|
|
154
158
|
"",
|
|
155
159
|
"Install only the section below, verbatim. After writing, tell the user which file you updated.",
|
|
156
160
|
"",
|
|
157
|
-
|
|
161
|
+
PASTE_MEMORY_RULES
|
|
158
162
|
].join("\n");
|
|
159
163
|
}
|
|
160
164
|
|
|
@@ -162,6 +166,7 @@ export {
|
|
|
162
166
|
PYX_MEMORY_INSTRUCTIONS,
|
|
163
167
|
PYX_MEMORY_COMPANION_CORE_INSTRUCTIONS,
|
|
164
168
|
PERSISTENT_MEMORY_SECTION,
|
|
169
|
+
PASTE_MEMORY_RULES,
|
|
165
170
|
buildDesignGuide,
|
|
166
171
|
AGENT_TARGETS,
|
|
167
172
|
STORE_ENTITIES_DESC,
|
package/dist/cli/pyx-mem.mjs
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import {
|
|
3
3
|
PERSISTENT_MEMORY_SECTION,
|
|
4
4
|
buildDesignGuide
|
|
5
|
-
} from "../chunk-
|
|
5
|
+
} from "../chunk-QD7G23CN.mjs";
|
|
6
6
|
import {
|
|
7
7
|
MEMORY_PROJECT_LABEL_MAX_CHARS,
|
|
8
8
|
TAXONOMY_MAX_CATEGORIES,
|
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
TAXONOMY_MAX_SAMPLE_TOPICS,
|
|
11
11
|
TAXONOMY_MAX_TOP_ENTITIES
|
|
12
12
|
} from "../chunk-KZKGRND2.mjs";
|
|
13
|
-
import "../chunk-
|
|
13
|
+
import "../chunk-C46EE5BH.mjs";
|
|
14
14
|
|
|
15
15
|
// src/cli/exit-codes.ts
|
|
16
16
|
var EXIT = {
|
|
@@ -2223,7 +2223,7 @@ function createProxyServer(client, version, uploadLocalFile) {
|
|
|
2223
2223
|
return server;
|
|
2224
2224
|
}
|
|
2225
2225
|
async function runMcpProxyServer(opts) {
|
|
2226
|
-
const version = opts.version ?? (true ? "1.
|
|
2226
|
+
const version = opts.version ?? (true ? "1.23.0" : "0.0.0-dev");
|
|
2227
2227
|
const read = await opts.readCredentials();
|
|
2228
2228
|
if (!read.ok) {
|
|
2229
2229
|
throw new Error(
|
|
@@ -2257,7 +2257,9 @@ async function runMcpProxyServer(opts) {
|
|
|
2257
2257
|
const closed = new Promise((resolve3) => {
|
|
2258
2258
|
transport.onclose = () => resolve3();
|
|
2259
2259
|
});
|
|
2260
|
+
process.stdin.once("end", () => void transport.close());
|
|
2260
2261
|
await server.connect(transport);
|
|
2262
|
+
void opts.onConnected?.(client);
|
|
2261
2263
|
await closed;
|
|
2262
2264
|
} finally {
|
|
2263
2265
|
await client.close().catch(() => {
|
|
@@ -2591,17 +2593,26 @@ function mcpInstallCodexCommand(opts = {}) {
|
|
|
2591
2593
|
const remote = opts.remote ?? false;
|
|
2592
2594
|
const spawnSync = opts._spawnSync ?? nodeSpawnSync;
|
|
2593
2595
|
const home = opts._homeDir ?? homedir2();
|
|
2596
|
+
const codexHome = (opts._env ?? process.env).CODEX_HOME;
|
|
2594
2597
|
const probe = spawnSync("codex", ["--version"], { stdio: "pipe" });
|
|
2595
2598
|
if (probe.error || probe.status !== 0) {
|
|
2596
|
-
printCodexManualInstructions(home, remote);
|
|
2599
|
+
printCodexManualInstructions(home, remote, codexHome);
|
|
2597
2600
|
return EXIT.OK;
|
|
2598
2601
|
}
|
|
2599
|
-
const cmd = [
|
|
2602
|
+
const cmd = [
|
|
2603
|
+
"mcp",
|
|
2604
|
+
"add",
|
|
2605
|
+
SERVER_NAME,
|
|
2606
|
+
...codexHome ? ["--env", `CODEX_HOME=${codexHome}`] : [],
|
|
2607
|
+
"--",
|
|
2608
|
+
"pyx-mem",
|
|
2609
|
+
...pyxMemArgs(remote)
|
|
2610
|
+
];
|
|
2600
2611
|
const res = spawnSync("codex", cmd, { stdio: "inherit" });
|
|
2601
2612
|
if (res.status !== 0) {
|
|
2602
2613
|
process.stderr.write(`\`codex ${cmd.join(" ")}\` exited with code ${res.status ?? "null"}.
|
|
2603
2614
|
`);
|
|
2604
|
-
printCodexManualInstructions(home, remote);
|
|
2615
|
+
printCodexManualInstructions(home, remote, codexHome);
|
|
2605
2616
|
return EXIT.USAGE;
|
|
2606
2617
|
}
|
|
2607
2618
|
process.stdout.write(
|
|
@@ -2611,20 +2622,21 @@ Restart Codex CLI to make the tools available. No API key was written to config.
|
|
|
2611
2622
|
);
|
|
2612
2623
|
return EXIT.OK;
|
|
2613
2624
|
}
|
|
2614
|
-
function printCodexManualInstructions(home, remote) {
|
|
2615
|
-
const configPath = join2(home, ".codex", "config.toml");
|
|
2625
|
+
function printCodexManualInstructions(home, remote, codexHome) {
|
|
2626
|
+
const configPath = join2(codexHome ?? join2(home, ".codex"), "config.toml");
|
|
2616
2627
|
process.stdout.write(
|
|
2617
2628
|
[
|
|
2618
2629
|
"The `codex` CLI is not on PATH, or the install command failed.",
|
|
2619
2630
|
"",
|
|
2620
2631
|
"Run this once Codex CLI is installed:",
|
|
2621
|
-
` codex mcp add ${SERVER_NAME} -- pyx-mem ${pyxMemArgs(remote).join(" ")}`,
|
|
2632
|
+
` codex mcp add ${SERVER_NAME}${codexHome ? ` --env ${JSON.stringify(`CODEX_HOME=${codexHome}`)}` : ""} -- pyx-mem ${pyxMemArgs(remote).join(" ")}`,
|
|
2622
2633
|
"",
|
|
2623
2634
|
`Or add this section manually to ${configPath}:`,
|
|
2624
2635
|
"",
|
|
2625
2636
|
`[mcp_servers.${SERVER_NAME}]`,
|
|
2626
2637
|
`command = "pyx-mem"`,
|
|
2627
2638
|
`args = ${JSON.stringify(pyxMemArgs(remote))}`,
|
|
2639
|
+
...codexHome ? [`env = { CODEX_HOME = ${JSON.stringify(codexHome)} }`] : [],
|
|
2628
2640
|
"",
|
|
2629
2641
|
"Do NOT add your pyx-memory API key here. Run `pyx-mem login` to store it in the OS credential store.",
|
|
2630
2642
|
""
|
|
@@ -2841,35 +2853,49 @@ function printHermesManualInstructions(remote) {
|
|
|
2841
2853
|
);
|
|
2842
2854
|
}
|
|
2843
2855
|
var RULES_FILE_TARGETS = {
|
|
2844
|
-
"claude-code": [".claude", "CLAUDE.md"
|
|
2845
|
-
codex: [".codex", "AGENTS.md"
|
|
2846
|
-
"gemini-cli": [".gemini", "GEMINI.md"
|
|
2847
|
-
"oh-my-pi": [".omp", "agent", "RULES.md"
|
|
2856
|
+
"claude-code": { envDir: "CLAUDE_CONFIG_DIR", dir: [".claude"], file: "CLAUDE.md" },
|
|
2857
|
+
codex: { envDir: "CODEX_HOME", dir: [".codex"], file: "AGENTS.md" },
|
|
2858
|
+
"gemini-cli": { dir: [".gemini"], file: "GEMINI.md" },
|
|
2859
|
+
"oh-my-pi": { dir: [".omp", "agent"], file: "RULES.md" }
|
|
2848
2860
|
};
|
|
2861
|
+
function rulesFilePath(target, opts) {
|
|
2862
|
+
if (!Object.hasOwn(RULES_FILE_TARGETS, target)) return void 0;
|
|
2863
|
+
const spec = RULES_FILE_TARGETS[target];
|
|
2864
|
+
const env = opts._env ?? (opts._homeDir === void 0 ? process.env : {});
|
|
2865
|
+
const configDir = spec.envDir ? env[spec.envDir] : void 0;
|
|
2866
|
+
return configDir ? join2(configDir, spec.file) : join2(opts._homeDir ?? homedir2(), ...spec.dir, spec.file);
|
|
2867
|
+
}
|
|
2849
2868
|
function installMemoryRules(opts) {
|
|
2850
|
-
const
|
|
2851
|
-
if (!
|
|
2869
|
+
const filePath = rulesFilePath(opts.target, opts);
|
|
2870
|
+
if (!filePath) return;
|
|
2852
2871
|
if (opts.noRules) {
|
|
2853
2872
|
process.stdout.write(
|
|
2854
2873
|
'Skipped writing the memory rules (--no-rules). The tools are installed, but the agent will reach for memory only when you ask; add the "## Persistent Memory" rules yourself to change that.\n'
|
|
2855
2874
|
);
|
|
2856
2875
|
return;
|
|
2857
2876
|
}
|
|
2858
|
-
const
|
|
2859
|
-
const result = writeMemoryRulesFile({
|
|
2860
|
-
filePath: join2(home, ...segs),
|
|
2861
|
-
section: PERSISTENT_MEMORY_SECTION
|
|
2862
|
-
});
|
|
2877
|
+
const result = writeMemoryRulesFile({ filePath, section: PERSISTENT_MEMORY_SECTION });
|
|
2863
2878
|
process.stdout.write(result.message);
|
|
2864
2879
|
}
|
|
2880
|
+
function installMemoryRulesOnly(target, opts = {}) {
|
|
2881
|
+
if (target === void 0 || !rulesFilePath(target, opts)) {
|
|
2882
|
+
process.stderr.write(
|
|
2883
|
+
`Error: \`pyx-mem mcp rules\` needs a host with a known rules file: ${Object.keys(RULES_FILE_TARGETS).join(", ")}.
|
|
2884
|
+
`
|
|
2885
|
+
);
|
|
2886
|
+
return EXIT.USAGE;
|
|
2887
|
+
}
|
|
2888
|
+
installMemoryRules({ ...opts, target, noRules: false });
|
|
2889
|
+
return EXIT.OK;
|
|
2890
|
+
}
|
|
2865
2891
|
function reconcileMemoryRules(opts = {}) {
|
|
2866
|
-
const
|
|
2867
|
-
for (const
|
|
2868
|
-
const filePath =
|
|
2892
|
+
const section = opts.section ?? PERSISTENT_MEMORY_SECTION;
|
|
2893
|
+
for (const target of Object.keys(RULES_FILE_TARGETS)) {
|
|
2894
|
+
const filePath = rulesFilePath(target, opts);
|
|
2869
2895
|
try {
|
|
2870
2896
|
if (!existsSync3(filePath)) continue;
|
|
2871
2897
|
if (!hasPyxMemoryRules(readFileSync3(filePath, "utf8"))) continue;
|
|
2872
|
-
const result = writeMemoryRulesFile({ filePath, section
|
|
2898
|
+
const result = writeMemoryRulesFile({ filePath, section });
|
|
2873
2899
|
if (result.action !== "unchanged") {
|
|
2874
2900
|
process.stderr.write(
|
|
2875
2901
|
`pyx-memory: refreshed the "## Persistent Memory" rules in ${filePath}
|
|
@@ -2880,6 +2906,31 @@ function reconcileMemoryRules(opts = {}) {
|
|
|
2880
2906
|
}
|
|
2881
2907
|
}
|
|
2882
2908
|
}
|
|
2909
|
+
var MAX_SERVER_RULES_BYTES = 16 * 1024;
|
|
2910
|
+
async function syncMemoryRulesFromServer(client, opts = {}) {
|
|
2911
|
+
try {
|
|
2912
|
+
const { tools } = await client.listTools();
|
|
2913
|
+
if (!tools.some((tool) => tool.name === "get_memory_rules")) {
|
|
2914
|
+
reconcileMemoryRules(opts);
|
|
2915
|
+
return;
|
|
2916
|
+
}
|
|
2917
|
+
const result = await client.callTool({ name: "get_memory_rules", arguments: {} });
|
|
2918
|
+
const [first] = result.content ?? [];
|
|
2919
|
+
const section = first?.type === "text" ? first.text : void 0;
|
|
2920
|
+
if (result.isError || !section || !isRulesSection(section)) {
|
|
2921
|
+
throw new Error('the server returned no valid "## Persistent Memory" section');
|
|
2922
|
+
}
|
|
2923
|
+
reconcileMemoryRules({ ...opts, section });
|
|
2924
|
+
} catch (err) {
|
|
2925
|
+
process.stderr.write(
|
|
2926
|
+
`pyx-memory: left the installed memory rules unchanged \u2014 could not fetch current rules (${err instanceof Error ? err.message : String(err)}).
|
|
2927
|
+
`
|
|
2928
|
+
);
|
|
2929
|
+
}
|
|
2930
|
+
}
|
|
2931
|
+
function isRulesSection(text) {
|
|
2932
|
+
return text.startsWith("## Persistent Memory\n") && Buffer.byteLength(text, "utf8") <= MAX_SERVER_RULES_BYTES && !text.includes("<!-- pyx-memory:") && !/^\s*(```|~~~)/m.test(text);
|
|
2933
|
+
}
|
|
2883
2934
|
function validateScope(scope) {
|
|
2884
2935
|
if (VALID_SCOPES.has(scope)) return true;
|
|
2885
2936
|
process.stderr.write(`Error: invalid --scope \`${scope}\`. Expected: local | user | project.
|
|
@@ -2909,14 +2960,12 @@ function writeJsonAndReport(filePath, agentLabel, entry, opts = {}) {
|
|
|
2909
2960
|
|
|
2910
2961
|
// src/cli/commands/mcp.ts
|
|
2911
2962
|
async function mcpCommand() {
|
|
2912
|
-
reconcileMemoryRules();
|
|
2913
2963
|
const readCredentials = createReadCredentials(() => getDefaultKeychain());
|
|
2914
|
-
const onStdinEnd = new Promise((resolve3) => {
|
|
2915
|
-
process.stdin.once("end", resolve3);
|
|
2916
|
-
process.stdin.once("close", resolve3);
|
|
2917
|
-
});
|
|
2918
2964
|
try {
|
|
2919
|
-
await
|
|
2965
|
+
await runMcpProxyServer({
|
|
2966
|
+
readCredentials,
|
|
2967
|
+
onConnected: (client) => syncMemoryRulesFromServer(client)
|
|
2968
|
+
});
|
|
2920
2969
|
return EXIT.OK;
|
|
2921
2970
|
} catch (err) {
|
|
2922
2971
|
process.stderr.write(`Internal error: ${err instanceof Error ? err.message : String(err)}
|
|
@@ -3370,6 +3419,10 @@ Commands:
|
|
|
3370
3419
|
your other content is preserved) so memory fires by
|
|
3371
3420
|
default. Pass --no-rules to skip that write.
|
|
3372
3421
|
Targets: claude-code, codex, cursor, cline, continue, windsurf, gemini-cli, pi, oh-my-pi, openclaw, hermes.
|
|
3422
|
+
mcp rules <target> Write or refresh only the always-on rules for
|
|
3423
|
+
claude-code, codex, gemini-cli, or oh-my-pi (no MCP
|
|
3424
|
+
registration). Honors CLAUDE_CONFIG_DIR / CODEX_HOME;
|
|
3425
|
+
'pyx-mem mcp' keeps them current from the server.
|
|
3373
3426
|
|
|
3374
3427
|
Notes:
|
|
3375
3428
|
- Credentials are stored only in the OS credential store (Keychain / libsecret / Credential Manager).
|
|
@@ -3473,6 +3526,13 @@ function runMcpCommand(parsed) {
|
|
|
3473
3526
|
parsed.flags["no-rules"] === true
|
|
3474
3527
|
);
|
|
3475
3528
|
}
|
|
3529
|
+
if (parsed.subcommand === "rules") {
|
|
3530
|
+
if (Object.keys(parsed.flags).length > 0) {
|
|
3531
|
+
process.stderr.write("Error: `pyx-mem mcp rules <host>` takes no flags.\n");
|
|
3532
|
+
return EXIT.USAGE;
|
|
3533
|
+
}
|
|
3534
|
+
return installMemoryRulesOnly(parsed.positional[0]);
|
|
3535
|
+
}
|
|
3476
3536
|
process.stderr.write(
|
|
3477
3537
|
`Error: unknown subcommand \`mcp ${parsed.subcommand}\`. Run \`pyx-mem --help\`.
|
|
3478
3538
|
`
|
package/dist/dashboard.mjs
CHANGED
|
@@ -11,10 +11,10 @@ import {
|
|
|
11
11
|
toGraphologyFormat,
|
|
12
12
|
transformGraphData,
|
|
13
13
|
unreachableHealth
|
|
14
|
-
} from "./chunk-
|
|
15
|
-
import "./chunk-
|
|
14
|
+
} from "./chunk-7YHCNO3N.mjs";
|
|
15
|
+
import "./chunk-SGL73IY5.mjs";
|
|
16
16
|
import "./chunk-KZKGRND2.mjs";
|
|
17
|
-
import "./chunk-
|
|
17
|
+
import "./chunk-C46EE5BH.mjs";
|
|
18
18
|
export {
|
|
19
19
|
DashboardClient,
|
|
20
20
|
Poller,
|
|
@@ -186,6 +186,11 @@ declare const DATA_PLANE_OPERATION_COVERAGE: {
|
|
|
186
186
|
readonly reasonCode: "nonchargeable_operation";
|
|
187
187
|
readonly reason: "status is nonchargeable and must bypass data-plane reservation";
|
|
188
188
|
};
|
|
189
|
+
readonly 'mcp:get_memory_rules': {
|
|
190
|
+
readonly support: "not_execution_ready";
|
|
191
|
+
readonly reasonCode: "nonchargeable_operation";
|
|
192
|
+
readonly reason: "the rules text is nonchargeable and must bypass data-plane reservation";
|
|
193
|
+
};
|
|
189
194
|
readonly 'mcp:get_user_profile': {
|
|
190
195
|
readonly support: "sqlite_atomic_one_step";
|
|
191
196
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export { C as CanonicalDataPlaneObject, a as CanonicalDataPlaneValue, b as CompileContext, c as CompileDataPlaneRequest, d as CompileDataPlaneResult, f as CompiledDataPlaneExecutionPlan, D as DATA_PLANE_CATALOG_VERSION, g as DATA_PLANE_COMPILER_LIMITS, h as DATA_PLANE_CONTRACT_VERSION, i as DATA_PLANE_HTTP_RESPONSE_FRAME, j as DATA_PLANE_MANIFEST_FRAME, k as DATA_PLANE_MANIFEST_VERSION, l as DATA_PLANE_OPERATION_COVERAGE, m as DATA_PLANE_SEARCH_EMBEDDING_CONTRACT, n as DATA_PLANE_STEP_INPUT_FRAME, o as DataPlaneCatalogOperation, q as DataPlaneUnsupportedReasonCode, S as SupportedDataPlaneCatalogOperation, r as canonicalDataPlaneJson, s as compileDataPlaneRequest, t as hashDataPlaneHttpResponseV1, u as hashDataPlaneManifestV1, v as hashDataPlaneStepInputV1 } from './data-plane-contract-
|
|
1
|
+
export { C as CanonicalDataPlaneObject, a as CanonicalDataPlaneValue, b as CompileContext, c as CompileDataPlaneRequest, d as CompileDataPlaneResult, f as CompiledDataPlaneExecutionPlan, D as DATA_PLANE_CATALOG_VERSION, g as DATA_PLANE_COMPILER_LIMITS, h as DATA_PLANE_CONTRACT_VERSION, i as DATA_PLANE_HTTP_RESPONSE_FRAME, j as DATA_PLANE_MANIFEST_FRAME, k as DATA_PLANE_MANIFEST_VERSION, l as DATA_PLANE_OPERATION_COVERAGE, m as DATA_PLANE_SEARCH_EMBEDDING_CONTRACT, n as DATA_PLANE_STEP_INPUT_FRAME, o as DataPlaneCatalogOperation, q as DataPlaneUnsupportedReasonCode, S as SupportedDataPlaneCatalogOperation, r as canonicalDataPlaneJson, s as compileDataPlaneRequest, t as hashDataPlaneHttpResponseV1, u as hashDataPlaneManifestV1, v as hashDataPlaneStepInputV1 } from './data-plane-contract-C5VqxrpF.js';
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { StoreInput as StoreInput$1, MemoryEntry as MemoryEntry$1, MemorySearchParams as MemorySearchParams$1, MemorySearchResult as MemorySearchResult$1, MemoryType as MemoryType$1, PrincipalContext as PrincipalContext$1, SensitivityLevel as SensitivityLevel$1, MemoryStats as MemoryStats$1, MemoryInsights as MemoryInsights$1, LineageParams as LineageParams$1, LineageResult as LineageResult$1, ReinforceParams as ReinforceParams$1, ReinforceResult as ReinforceResult$1, WikiLintReport as WikiLintReport$1, GraphRepairResult as GraphRepairResult$1, ExtractedImageMeta as ExtractedImageMeta$1, IngestEntity as IngestEntity$1, IngestRelationship as IngestRelationship$1, EntityExtractionResult as EntityExtractionResult$1, Topology as Topology$1, IngestEvent as IngestEvent$1, GraphEnrichEvent as GraphEnrichEvent$1, GraphNode as GraphNode$1, GraphTraversalResult as GraphTraversalResult$1, CorrectionRecord as CorrectionRecord$1 } from '@pyx-memory/shared';
|
|
2
2
|
export { documentContentSource, documentGraphSource, documentImageSource } from '@pyx-memory/shared';
|
|
3
|
-
export { e as encodeListCursorToken, p as parseListCursorToken } from './data-plane-contract-
|
|
3
|
+
export { e as encodeListCursorToken, p as parseListCursorToken } from './data-plane-contract-C5VqxrpF.js';
|
|
4
4
|
|
|
5
5
|
/** ISO 8601 timestamp string */
|
|
6
6
|
type Timestamp = string;
|
package/dist/index.mjs
CHANGED
|
@@ -2,7 +2,7 @@ import {
|
|
|
2
2
|
DisabledMemory,
|
|
3
3
|
MemoryClient,
|
|
4
4
|
MemoryServerError
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-SGL73IY5.mjs";
|
|
6
6
|
import {
|
|
7
7
|
DEFAULTS,
|
|
8
8
|
MEMORY_PROJECT_LABEL_MAX_CHARS,
|
|
@@ -37,7 +37,7 @@ import {
|
|
|
37
37
|
normalizeGraphLabel,
|
|
38
38
|
normalizeNameKey,
|
|
39
39
|
parseListCursorToken
|
|
40
|
-
} from "./chunk-
|
|
40
|
+
} from "./chunk-C46EE5BH.mjs";
|
|
41
41
|
|
|
42
42
|
// src/preset.ts
|
|
43
43
|
var DEFAULT_MEMORY_URL = `http://localhost:${DEFAULTS.MEMORY_SERVER_PORT}`;
|
package/dist/react.mjs
CHANGED
|
@@ -11,10 +11,10 @@ import {
|
|
|
11
11
|
toGraphologyFormat,
|
|
12
12
|
transformGraphData,
|
|
13
13
|
unreachableHealth
|
|
14
|
-
} from "./chunk-
|
|
15
|
-
import "./chunk-
|
|
14
|
+
} from "./chunk-7YHCNO3N.mjs";
|
|
15
|
+
import "./chunk-SGL73IY5.mjs";
|
|
16
16
|
import "./chunk-KZKGRND2.mjs";
|
|
17
|
-
import "./chunk-
|
|
17
|
+
import "./chunk-C46EE5BH.mjs";
|
|
18
18
|
|
|
19
19
|
// ../dashboard/src/hooks/use-consolidation-log.ts
|
|
20
20
|
import { useCallback as useCallback2, useMemo } from "react";
|