myagentmemory 0.5.1 → 0.5.2

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/cli.js CHANGED
@@ -617,8 +617,11 @@ async function cmdUserPromptSubmit(_flags) {
617
617
  }
618
618
  // How many Stop events must elapse (per session_id) before the periodic
619
619
  // memory-write nudge fires again. Balances "long sessions get checked
620
- // repeatedly" against "don't block every single turn".
621
- const STOP_NAG_INTERVAL = 12;
620
+ // repeatedly" against "don't block every single turn". Deliberately short —
621
+ // most real sessions are well under a dozen turns, so a wider interval meant
622
+ // the nudge rarely fired in practice (see stop-hook.json in the wild: sessions
623
+ // topping out around 7 turns, zero nags ever recorded).
624
+ const STOP_NAG_INTERVAL = 6;
622
625
  // Bound state/stop-hook.json so it can't grow unboundedly across many sessions.
623
626
  const STOP_HOOK_MAX_SESSIONS = 50;
624
627
  function stopHookStatePath() {
@@ -2691,7 +2694,8 @@ async function cmdServe(flags) {
2691
2694
  }, async () => {
2692
2695
  const memFile = getMemoryFile();
2693
2696
  const scratchFile = getScratchpadFile();
2694
- const memory = redactSecrets(readFileSafe(memFile) ?? "").content || "(empty)";
2697
+ const memory = redactSecrets(readFileSafe(memFile) ?? "").content ||
2698
+ '(empty — this only covers what was explicitly saved. For things said in prior chat sessions, try `agent-memory recall "<query>"` or the `session_recall`/`session_search` MCP tools, if AgentMemory Pro is installed.)';
2695
2699
  const scratchRaw = readFileSafe(scratchFile) ?? "";
2696
2700
  const scratchItems = parseScratchpad(scratchRaw)
2697
2701
  .filter((item) => !item.done)
@@ -2732,7 +2736,7 @@ async function cmdServe(flags) {
2732
2736
  try {
2733
2737
  await runtime.load();
2734
2738
  for (const tool of runtime.getMcpTools()) {
2735
- server.addTool({ name: tool.name, description: tool.description, inputSchema: tool.inputSchema }, (input) => tool.run(input));
2739
+ server.addTool({ name: tool.name, description: tool.description, inputSchema: tool.inputSchema }, (input) => runtime.runMcpTool(tool.name, input));
2736
2740
  }
2737
2741
  server.addStartupHook(() => runtime.runMcpStartup());
2738
2742
  }
@@ -147,6 +147,7 @@ export interface PluginMcpToolInputSchema {
147
147
  export interface PluginMcpToolV1 {
148
148
  name: string;
149
149
  description: string;
150
+ requiredCapability: string;
150
151
  inputSchema: PluginMcpToolInputSchema;
151
152
  run(input: Record<string, unknown>): unknown | Promise<unknown>;
152
153
  }
@@ -34,6 +34,15 @@ export declare class InstalledPluginRuntimeV1 {
34
34
  signal: AbortSignal;
35
35
  }): Promise<PluginContextSectionV1[]>;
36
36
  getMcpTools(): PluginMcpToolV1[];
37
+ /**
38
+ * Invoke a registered MCP tool by name, re-checking entitlement on every
39
+ * call — matching `run()`'s behavior for commands. MCP tools are
40
+ * registered once at `serve --mcp` startup and the server process can
41
+ * live for a long session, so a tool's entitlement must be re-verified
42
+ * per-call rather than trusted from registration time (e.g. a trial
43
+ * expiring mid-session must actually stop the tool from working).
44
+ */
45
+ runMcpTool(name: string, input: Record<string, unknown>): Promise<unknown>;
37
46
  runMcpStartup(): Promise<void>;
38
47
  private createHost;
39
48
  private refreshEntitlement;
@@ -186,6 +186,25 @@ export class InstalledPluginRuntimeV1 {
186
186
  getMcpTools() {
187
187
  return [...this.mcpTools];
188
188
  }
189
+ /**
190
+ * Invoke a registered MCP tool by name, re-checking entitlement on every
191
+ * call — matching `run()`'s behavior for commands. MCP tools are
192
+ * registered once at `serve --mcp` startup and the server process can
193
+ * live for a long session, so a tool's entitlement must be re-verified
194
+ * per-call rather than trusted from registration time (e.g. a trial
195
+ * expiring mid-session must actually stop the tool from working).
196
+ */
197
+ async runMcpTool(name, input) {
198
+ if (!(await this.load()))
199
+ return { error: `Unknown MCP tool: ${name}` };
200
+ const tool = this.mcpTools.find((candidate) => candidate.name === name);
201
+ if (!tool)
202
+ return { error: `Unknown MCP tool: ${name}` };
203
+ const entitlement = await this.refreshEntitlement();
204
+ if (!isPluginCapabilityEnabled(entitlement, tool.requiredCapability))
205
+ return { error: `Capability ${tool.requiredCapability} is not enabled for the ${name} tool` };
206
+ return tool.run(input);
207
+ }
189
208
  async runMcpStartup() {
190
209
  for (const hook of this.mcpStartupHooks)
191
210
  await hook();
@@ -238,6 +257,8 @@ export class InstalledPluginRuntimeV1 {
238
257
  this.contextProviders.push({ provider, pluginId: manifest.id });
239
258
  },
240
259
  registerMcpTool: (tool) => {
260
+ if (!(manifest.capabilities ?? []).includes(tool.requiredCapability))
261
+ throw new PluginBootstrapFailure("plugin_mcp_tool_invalid", `Plugin ${manifest.id} registered an MCP tool with an undeclared capability`);
241
262
  if (!tool.name || this.mcpTools.some((existing) => existing.name === tool.name))
242
263
  throw new PluginBootstrapFailure("plugin_mcp_tool_invalid", `Plugin MCP tool ${tool.name || "(unnamed)"} is invalid or already registered`);
243
264
  this.mcpTools.push(tool);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "myagentmemory",
3
- "version": "0.5.1",
3
+ "version": "0.5.2",
4
4
  "description": "agentmemory (agent-memory) is persistent memory for coding agents (Claude Code, OpenAI Codex, Cursor, Agent) with qmd-powered semantic search across daily logs, long-term memory, and scratchpad",
5
5
  "main": "./dist/core.js",
6
6
  "types": "./dist/core.d.ts",
@@ -176,6 +176,7 @@ export interface PluginMcpToolInputSchema {
176
176
  export interface PluginMcpToolV1 {
177
177
  name: string;
178
178
  description: string;
179
+ requiredCapability: string;
179
180
  inputSchema: PluginMcpToolInputSchema;
180
181
  run(input: Record<string, unknown>): unknown | Promise<unknown>;
181
182
  }