pi-automem-bridge 0.2.2 → 0.2.3

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
@@ -10,7 +10,7 @@
10
10
  pi install npm:pi-automem-bridge
11
11
  ```
12
12
 
13
- [![npm version](https://badge.fury.io/js/pi-automem-bridge.svg)](https://badge.fury.io/js/pi-automem-bridge)
13
+ [![npm version](https://img.shields.io/npm/v/pi-automem-bridge)](https://www.npmjs.com/package/pi-automem-bridge)
14
14
  [![npm downloads](https://img.shields.io/npm/dw/pi-automem-bridge)](https://www.npmjs.com/package/pi-automem-bridge)
15
15
 
16
16
  [![ko-fi](https://ko-fi.com/img/githubbutton_sm.svg)](https://ko-fi.com/L2J320X82M)
@@ -135,6 +135,8 @@ You don't type these — pi does, in plain conversation. Tell it *"remember that
135
135
  | `automem_link_memories` | Create a typed relationship between two existing memories. |
136
136
  | `automem_correct_memory` | Store a correction and link old → new with a provenance relationship (EVOLVED_INTO or CONTRADICTS). |
137
137
 
138
+ Policy blocks, missing approval in non-interactive contexts, and invalid update requests surface as pi tool errors. User-cancelled confirmations and duplicate detection are normal control-flow results, so the agent can stop or choose the next write path deliberately.
139
+
138
140
  ---
139
141
 
140
142
  ## Write policy
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-automem-bridge",
3
- "version": "0.2.2",
3
+ "version": "0.2.3",
4
4
  "description": "Automatic long-term memory recall and policy-gated writes for pi agents via AutoMem MCP",
5
5
  "keywords": [
6
6
  "pi-package",
@@ -68,11 +68,10 @@ export function registerMemoryTools(pi: ExtensionAPI) {
68
68
  config,
69
69
  ).catch(() => ({ text: "Similar recall failed.", matches: [] }));
70
70
 
71
- return {
72
- content: [{ type: "text" as const, text: formatProposal(decision.action, decision.reasons, decision.normalized, similarText, similarMatches) }],
73
- details: { action: decision.action, reasons: decision.reasons, findings: decision.findings, candidate: decision.normalized, similarMatches },
74
- isError: decision.action === "block",
75
- };
71
+ return {
72
+ content: [{ type: "text" as const, text: formatProposal(decision.action, decision.reasons, decision.normalized, similarText, similarMatches) }],
73
+ details: { action: decision.action, reasons: decision.reasons, findings: decision.findings, candidate: decision.normalized, similarMatches },
74
+ };
76
75
  },
77
76
  });
78
77
 
@@ -87,15 +86,11 @@ export function registerMemoryTools(pi: ExtensionAPI) {
87
86
  const config = loadConfig();
88
87
  setAutoMemMcpServerName(config.mcpServerName);
89
88
  const candidate = toCandidate(params);
90
- const decision = evaluateWritePolicy(candidate, config);
91
-
92
- if (decision.action === "block") {
93
- return {
94
- content: [{ type: "text" as const, text: "Blocked by AutoMem write policy.\n" + decision.reasons.map((r: string) => "- " + r).join("\n") }],
95
- details: { action: decision.action, reasons: decision.reasons, findings: decision.findings },
96
- isError: true,
97
- };
98
- }
89
+ const decision = evaluateWritePolicy(candidate, config);
90
+
91
+ if (decision.action === "block") {
92
+ throw new Error("Blocked by AutoMem write policy.\n" + decision.reasons.map((r: string) => "- " + r).join("\n"));
93
+ }
99
94
 
100
95
  const needsConfirmation = decision.action !== "auto";
101
96
  if (needsConfirmation && !params.approvedByUser) {
@@ -104,14 +99,10 @@ export function registerMemoryTools(pi: ExtensionAPI) {
104
99
  if (!ok) {
105
100
  return { content: [{ type: "text" as const, text: "AutoMem memory write cancelled." }], details: { cancelled: true } };
106
101
  }
107
- } else {
108
- return {
109
- content: [{ type: "text" as const, text: "Confirmation required before storing this memory. Re-run with approvedByUser=true only after explicit user approval." }],
110
- details: { action: decision.action, reasons: decision.reasons, candidate: decision.normalized },
111
- isError: true,
112
- };
113
- }
114
- }
102
+ } else {
103
+ throw new Error("Confirmation required before storing this memory. Re-run with approvedByUser=true only after explicit user approval.");
104
+ }
105
+ }
115
106
 
116
107
  // ── UPDATE path ──────────────────────────────────────────────────────
117
108
  if (params.updateMemoryId) {
@@ -158,11 +149,10 @@ export function registerMemoryTools(pi: ExtensionAPI) {
158
149
  " 2. Store anyway (new memory): call automem_commit_memory with dedupeQuery=\"\" to skip dedupe",
159
150
  " 3. Cancel: do nothing if this is not worth storing separately",
160
151
  ].join("\n"),
161
- }],
162
- details: { duplicateDetected: true, existingMemoryId: top.id, existingContent: top.content, candidate: decision.normalized, allSimilar: similarMatches },
163
- isError: false,
164
- };
165
- }
152
+ }],
153
+ details: { duplicateDetected: true, existingMemoryId: top.id, existingContent: top.content, candidate: decision.normalized, allSimilar: similarMatches },
154
+ };
155
+ }
166
156
 
167
157
  // ── STORE path ───────────────────────────────────────────────────────
168
158
  const result = await automemStore(
@@ -193,12 +183,9 @@ export function registerMemoryTools(pi: ExtensionAPI) {
193
183
  promptSnippet: "Use after automem_commit_memory returns DUPLICATE_DETECTED, or when correcting a known memory. Requires the existing memory ID.",
194
184
  parameters: UpdateParams,
195
185
  async execute(_toolCallId, params, _signal, _onUpdate, ctx: any) {
196
- if (!params.memoryId) {
197
- return {
198
- content: [{ type: "text" as const, text: "memoryId is required for automem_update_memory." }],
199
- isError: true,
200
- };
201
- }
186
+ if (!params.memoryId) {
187
+ throw new Error("memoryId is required for automem_update_memory.");
188
+ }
202
189
 
203
190
  if (!params.approvedByUser) {
204
191
  if (ctx && ctx.ui && typeof ctx.ui.confirm === "function") {
@@ -212,13 +199,10 @@ export function registerMemoryTools(pi: ExtensionAPI) {
212
199
  if (!ok) {
213
200
  return { content: [{ type: "text" as const, text: "AutoMem memory update cancelled." }], details: { cancelled: true } };
214
201
  }
215
- } else {
216
- return {
217
- content: [{ type: "text" as const, text: "Confirmation required before updating this memory. Re-run with approvedByUser=true only after explicit user approval." }],
218
- isError: true,
219
- };
220
- }
221
- }
202
+ } else {
203
+ throw new Error("Confirmation required before updating this memory. Re-run with approvedByUser=true only after explicit user approval.");
204
+ }
205
+ }
222
206
 
223
207
  const result = await automemUpdate(params.memoryId, {
224
208
  content: params.content,
@@ -31,14 +31,11 @@ export function registerRelationshipTools(pi: ExtensionAPI) {
31
31
  parameters: LinkParams,
32
32
  async execute(_toolCallId: string, params: any) {
33
33
  const config = loadConfig();
34
- setAutoMemMcpServerName(config.mcpServerName);
35
-
36
- if (!params.approvedByUser) {
37
- return {
38
- content: [{ type: "text" as const, text: "Confirmation required before linking memories. Re-run with approvedByUser=true only after explicit user approval.\n\nWould link:\n " + params.memoryId1 + " → " + params.relationship + " → " + params.memoryId2 }],
39
- isError: true,
40
- };
41
- }
34
+ setAutoMemMcpServerName(config.mcpServerName);
35
+
36
+ if (!params.approvedByUser) {
37
+ throw new Error("Confirmation required before linking memories. Re-run with approvedByUser=true only after explicit user approval.\n\nWould link:\n " + params.memoryId1 + " -> " + params.relationship + " -> " + params.memoryId2);
38
+ }
42
39
 
43
40
  const strength = typeof params.strength === "number" ? params.strength : 0.5;
44
41
  const result = await automemAssociate(params.memoryId1, params.memoryId2, params.relationship, strength);
@@ -66,21 +63,14 @@ export function registerRelationshipTools(pi: ExtensionAPI) {
66
63
  tags: Array.isArray(params.tags) ? params.tags : [],
67
64
  importance: params.importance,
68
65
  };
69
- const decision = evaluateWritePolicy(candidate, config);
70
- if (decision.action === "block") {
71
- return {
72
- content: [{ type: "text" as const, text: "Blocked by AutoMem write policy.\n" + decision.reasons.map((r: string) => "- " + r).join("\n") }],
73
- details: { action: decision.action, reasons: decision.reasons, findings: decision.findings },
74
- isError: true,
75
- };
76
- }
77
-
78
- if (!params.approvedByUser) {
79
- return {
80
- content: [{ type: "text" as const, text: "Confirmation required before correcting memory. Re-run with approvedByUser=true only after explicit user approval.\n\nWould correct memory " + params.memoryId + " with:\n " + params.correction }],
81
- isError: true,
82
- };
83
- }
66
+ const decision = evaluateWritePolicy(candidate, config);
67
+ if (decision.action === "block") {
68
+ throw new Error("Blocked by AutoMem write policy.\n" + decision.reasons.map((r: string) => "- " + r).join("\n"));
69
+ }
70
+
71
+ if (!params.approvedByUser) {
72
+ throw new Error("Confirmation required before correcting memory. Re-run with approvedByUser=true only after explicit user approval.\n\nWould correct memory " + params.memoryId + " with:\n " + params.correction);
73
+ }
84
74
 
85
75
  const rel = params.relationship === "CONTRADICTS" ? "CONTRADICTS" : "EVOLVED_INTO";
86
76
  // Store the normalized candidate so corrections get the same alwaysTag,