@hasna/mementos 0.10.3 → 0.10.5

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/index.js CHANGED
@@ -6920,6 +6920,13 @@ function listAgents(db) {
6920
6920
  const rows = d.query("SELECT * FROM agents ORDER BY last_seen_at DESC").all();
6921
6921
  return rows.map(parseAgentRow);
6922
6922
  }
6923
+ function touchAgent(idOrName, db) {
6924
+ const d = db || getDatabase();
6925
+ const agent = getAgent(idOrName, d);
6926
+ if (!agent)
6927
+ return;
6928
+ d.run("UPDATE agents SET last_seen_at = ? WHERE id = ?", [now(), agent.id]);
6929
+ }
6923
6930
  function updateAgent(id, updates, db) {
6924
6931
  const d = db || getDatabase();
6925
6932
  const agent = getAgent(id, d);
@@ -6960,6 +6967,40 @@ function updateAgent(id, updates, db) {
6960
6967
  return getAgent(agent.id, d);
6961
6968
  }
6962
6969
 
6970
+ // src/lib/focus.ts
6971
+ init_hooks();
6972
+ var sessionFocus = new Map;
6973
+ function setFocus(agentId, projectId) {
6974
+ const previous = getFocusCached(agentId);
6975
+ sessionFocus.set(agentId, projectId);
6976
+ updateAgent(agentId, { active_project_id: projectId });
6977
+ if (projectId && projectId !== previous) {
6978
+ hookRegistry.runHooks("OnSessionStart", {
6979
+ agentId,
6980
+ projectId,
6981
+ timestamp: Date.now()
6982
+ });
6983
+ } else if (!projectId && previous) {
6984
+ hookRegistry.runHooks("OnSessionEnd", {
6985
+ agentId,
6986
+ projectId: previous,
6987
+ timestamp: Date.now()
6988
+ });
6989
+ }
6990
+ }
6991
+ function getFocusCached(agentId) {
6992
+ return sessionFocus.get(agentId) ?? null;
6993
+ }
6994
+ function getFocus(agentId) {
6995
+ if (sessionFocus.has(agentId)) {
6996
+ return sessionFocus.get(agentId) ?? null;
6997
+ }
6998
+ const agent = getAgent(agentId);
6999
+ const projectId = agent?.active_project_id ?? null;
7000
+ sessionFocus.set(agentId, projectId);
7001
+ return projectId;
7002
+ }
7003
+
6963
7004
  // src/db/projects.ts
6964
7005
  init_database();
6965
7006
  function parseProjectRow(row) {
@@ -10832,4 +10873,77 @@ session_end = "bun ${script}"`));
10832
10873
  console.log("Usage: mementos session setup-hook --claude | --codex");
10833
10874
  }
10834
10875
  });
10876
+ program2.command("heartbeat [agent-id]").description("Update last_seen_at to signal this agent is active").action((agentId) => {
10877
+ const globalOpts = program2.opts();
10878
+ const id = agentId || globalOpts.agent;
10879
+ if (!id) {
10880
+ process.stderr.write(`Agent ID required. Use --agent or pass as argument.
10881
+ `);
10882
+ process.exit(1);
10883
+ }
10884
+ const agent = getAgent(id);
10885
+ if (!agent) {
10886
+ process.stderr.write(`Agent not found: ${id}
10887
+ `);
10888
+ process.exit(1);
10889
+ }
10890
+ touchAgent(agent.id);
10891
+ if (globalOpts.json)
10892
+ console.log(JSON.stringify({ agent_id: agent.id, name: agent.name, last_seen_at: new Date().toISOString() }));
10893
+ else
10894
+ console.log(chalk.green(`\u2665 ${agent.name} (${agent.id}) \u2014 heartbeat sent`));
10895
+ });
10896
+ program2.command("set-focus [project]").description("Focus this agent on a project (or clear focus if no project given)").option("--agent <id>", "Agent ID").action((project, opts) => {
10897
+ const globalOpts = program2.opts();
10898
+ const agentId = opts?.agent || globalOpts.agent;
10899
+ if (!agentId) {
10900
+ process.stderr.write(`Agent ID required. Use --agent.
10901
+ `);
10902
+ process.exit(1);
10903
+ }
10904
+ setFocus(agentId, project ?? null);
10905
+ if (project)
10906
+ console.log(chalk.green(`Focused: ${agentId} \u2192 project ${project}`));
10907
+ else
10908
+ console.log(chalk.dim(`Focus cleared for ${agentId}`));
10909
+ });
10910
+ program2.command("get-focus").description("Show the current project focus for an agent").option("--agent <id>", "Agent ID").action((opts) => {
10911
+ const globalOpts = program2.opts();
10912
+ const agentId = opts?.agent || globalOpts.agent;
10913
+ if (!agentId) {
10914
+ process.stderr.write(`Agent ID required. Use --agent.
10915
+ `);
10916
+ process.exit(1);
10917
+ }
10918
+ const focus = getFocus(agentId);
10919
+ if (focus)
10920
+ console.log(chalk.cyan(`Focus: ${focus}`));
10921
+ else
10922
+ console.log(chalk.dim("No focus set."));
10923
+ });
10924
+ program2.command("remove <nameOrId>").description("Remove/delete a memory by name or ID (alias for memory delete)").option("--agent <id>", "Agent ID").action((nameOrId, opts) => {
10925
+ const globalOpts = program2.opts();
10926
+ const agentId = opts.agent || globalOpts.agent;
10927
+ const { deleteMemory: deleteMemory2, getMemoryByKey: getMemoryByKey2, resolvePartialMemoryId } = (init_memories(), __toCommonJS(exports_memories));
10928
+ let id = null;
10929
+ try {
10930
+ id = resolvePartialMemoryId?.(nameOrId) || null;
10931
+ } catch {}
10932
+ if (!id) {
10933
+ const mem = getMemoryByKey2?.(nameOrId, agentId);
10934
+ if (mem)
10935
+ id = mem.id;
10936
+ }
10937
+ if (!id) {
10938
+ console.error(chalk.red(`Memory not found: ${nameOrId}`));
10939
+ process.exit(1);
10940
+ }
10941
+ const deleted = deleteMemory2(id);
10942
+ if (deleted)
10943
+ console.log(chalk.green(`\u2713 Memory ${id.slice(0, 8)} removed`));
10944
+ else {
10945
+ console.error(chalk.red(`Memory not found: ${nameOrId}`));
10946
+ process.exit(1);
10947
+ }
10948
+ });
10835
10949
  program2.parse(process.argv);
package/dist/mcp/index.js CHANGED
@@ -11165,6 +11165,17 @@ server.tool("set_focus", "Set focus for an agent on a project. Memory ops will a
11165
11165
  return { content: [{ type: "text", text: formatError(e) }], isError: true };
11166
11166
  }
11167
11167
  });
11168
+ server.tool("heartbeat", "Update agent last_seen_at to signal active session. Call periodically during long tasks to prevent being marked stale.", { agent_id: exports_external.string().describe("Agent ID or name") }, async (args) => {
11169
+ try {
11170
+ const agent = getAgent(args.agent_id);
11171
+ if (!agent)
11172
+ return { content: [{ type: "text", text: `Agent not found: ${args.agent_id}` }], isError: true };
11173
+ touchAgent(agent.id);
11174
+ return { content: [{ type: "text", text: `\u2665 ${agent.name} (${agent.id}) \u2014 last_seen_at updated` }] };
11175
+ } catch (e) {
11176
+ return { content: [{ type: "text", text: formatError(e) }], isError: true };
11177
+ }
11178
+ });
11168
11179
  server.tool("get_focus", "Get the current focus project for an agent.", { agent_id: exports_external.string() }, async (args) => {
11169
11180
  try {
11170
11181
  const projectId = getFocus(args.agent_id);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hasna/mementos",
3
- "version": "0.10.3",
3
+ "version": "0.10.5",
4
4
  "description": "Universal memory system for AI agents - CLI + MCP server + library API",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",