@hasna/mementos 0.1.0 → 0.1.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.
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,YAAY,EACV,MAAM,EACN,mBAAmB,EACnB,WAAW,EACX,cAAc,EACd,YAAY,EACZ,YAAY,EACZ,YAAY,EACZ,kBAAkB,EAClB,WAAW,EACX,iBAAiB,EACjB,iBAAiB,EACjB,UAAU,EACV,KAAK,EACL,OAAO,EACP,cAAc,EACd,aAAa,EACb,WAAW,EACX,UAAU,EACV,kBAAkB,GACnB,MAAM,kBAAkB,CAAC;AAG1B,OAAO,EACL,mBAAmB,EACnB,oBAAoB,EACpB,kBAAkB,EAClB,iBAAiB,EACjB,oBAAoB,GACrB,MAAM,kBAAkB,CAAC;AAG1B,OAAO,EACL,WAAW,EACX,aAAa,EACb,aAAa,EACb,SAAS,EACT,gBAAgB,EAChB,GAAG,EACH,IAAI,EACJ,SAAS,GACV,MAAM,kBAAkB,CAAC;AAG1B,OAAO,EACL,YAAY,EACZ,SAAS,EACT,cAAc,EACd,YAAY,EACZ,YAAY,EACZ,YAAY,EACZ,kBAAkB,EAClB,WAAW,EACX,oBAAoB,GACrB,MAAM,kBAAkB,CAAC;AAG1B,OAAO,EACL,aAAa,EACb,QAAQ,EACR,UAAU,GACX,MAAM,gBAAgB,CAAC;AAGxB,OAAO,EACL,eAAe,EACf,UAAU,EACV,YAAY,GACb,MAAM,kBAAkB,CAAC;AAG1B,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAGjD,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAG7D,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACnD,YAAY,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAG1D,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAG7E,OAAO,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,YAAY,EACV,MAAM,EACN,mBAAmB,EACnB,WAAW,EACX,cAAc,EACd,YAAY,EACZ,YAAY,EACZ,YAAY,EACZ,kBAAkB,EAClB,WAAW,EACX,iBAAiB,EACjB,iBAAiB,EACjB,UAAU,EACV,KAAK,EACL,OAAO,EACP,cAAc,EACd,aAAa,EACb,WAAW,EACX,UAAU,EACV,kBAAkB,GACnB,MAAM,kBAAkB,CAAC;AAG1B,OAAO,EACL,mBAAmB,EACnB,oBAAoB,EACpB,kBAAkB,EAClB,iBAAiB,EACjB,oBAAoB,GACrB,MAAM,kBAAkB,CAAC;AAG1B,OAAO,EACL,WAAW,EACX,aAAa,EACb,aAAa,EACb,SAAS,EACT,gBAAgB,EAChB,GAAG,EACH,IAAI,EACJ,SAAS,GACV,MAAM,kBAAkB,CAAC;AAG1B,OAAO,EACL,YAAY,EACZ,SAAS,EACT,cAAc,EACd,YAAY,EACZ,YAAY,EACZ,YAAY,EACZ,kBAAkB,EAClB,WAAW,EACX,oBAAoB,GACrB,MAAM,kBAAkB,CAAC;AAG1B,OAAO,EACL,aAAa,EACb,QAAQ,EACR,UAAU,EACV,WAAW,GACZ,MAAM,gBAAgB,CAAC;AAGxB,OAAO,EACL,eAAe,EACf,UAAU,EACV,YAAY,GACb,MAAM,kBAAkB,CAAC;AAG1B,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAGjD,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAG7D,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACnD,YAAY,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAG1D,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAG7E,OAAO,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC"}
package/dist/index.js CHANGED
@@ -602,6 +602,31 @@ function listAgents(db) {
602
602
  const rows = d.query("SELECT * FROM agents ORDER BY last_seen_at DESC").all();
603
603
  return rows.map(parseAgentRow);
604
604
  }
605
+ function updateAgent(id, updates, db) {
606
+ const d = db || getDatabase();
607
+ const agent = getAgent(id, d);
608
+ if (!agent)
609
+ return null;
610
+ const timestamp = now();
611
+ if (updates.name && updates.name !== agent.name) {
612
+ const existing = d.query("SELECT id FROM agents WHERE name = ? AND id != ?").get(updates.name, agent.id);
613
+ if (existing) {
614
+ throw new Error(`Agent name already taken: ${updates.name}`);
615
+ }
616
+ d.run("UPDATE agents SET name = ? WHERE id = ?", [updates.name, agent.id]);
617
+ }
618
+ if (updates.description !== undefined) {
619
+ d.run("UPDATE agents SET description = ? WHERE id = ?", [updates.description, agent.id]);
620
+ }
621
+ if (updates.role !== undefined) {
622
+ d.run("UPDATE agents SET role = ? WHERE id = ?", [updates.role, agent.id]);
623
+ }
624
+ if (updates.metadata !== undefined) {
625
+ d.run("UPDATE agents SET metadata = ? WHERE id = ?", [JSON.stringify(updates.metadata), agent.id]);
626
+ }
627
+ d.run("UPDATE agents SET last_seen_at = ? WHERE id = ?", [timestamp, agent.id]);
628
+ return getAgent(agent.id, d);
629
+ }
605
630
  // src/db/projects.ts
606
631
  function parseProjectRow(row) {
607
632
  return {
@@ -1136,6 +1161,7 @@ var defaultSyncAgents = ["claude", "codex", "gemini"];
1136
1161
  export {
1137
1162
  uuid,
1138
1163
  updateMemory,
1164
+ updateAgent,
1139
1165
  touchMemory,
1140
1166
  syncMemories,
1141
1167
  shortUuid,
@@ -0,0 +1,17 @@
1
+ import type { Database } from "bun:sqlite";
2
+ import type { Memory, MemoryScope, MemoryCategory } from "../types/index.js";
3
+ export interface PollOptions {
4
+ interval_ms?: number;
5
+ scope?: MemoryScope;
6
+ category?: MemoryCategory;
7
+ agent_id?: string;
8
+ project_id?: string;
9
+ on_memories: (memories: Memory[]) => void;
10
+ on_error?: (error: Error) => void;
11
+ db?: Database;
12
+ }
13
+ export interface PollHandle {
14
+ stop: () => void;
15
+ }
16
+ export declare function startPolling(opts: PollOptions): PollHandle;
17
+ //# sourceMappingURL=poll.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"poll.d.ts","sourceRoot":"","sources":["../../src/lib/poll.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAC3C,OAAO,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAQ7E,MAAM,WAAW,WAAW;IAC1B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,QAAQ,CAAC,EAAE,cAAc,CAAC;IAC1B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;IAC1C,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IAClC,EAAE,CAAC,EAAE,QAAQ,CAAC;CACf;AAED,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,IAAI,CAAC;CAClB;AAMD,wBAAgB,YAAY,CAAC,IAAI,EAAE,WAAW,GAAG,UAAU,CA0F1D"}
package/dist/mcp/index.js CHANGED
@@ -4577,6 +4577,31 @@ function listAgents(db) {
4577
4577
  const rows = d.query("SELECT * FROM agents ORDER BY last_seen_at DESC").all();
4578
4578
  return rows.map(parseAgentRow);
4579
4579
  }
4580
+ function updateAgent(id, updates, db) {
4581
+ const d = db || getDatabase();
4582
+ const agent = getAgent(id, d);
4583
+ if (!agent)
4584
+ return null;
4585
+ const timestamp = now();
4586
+ if (updates.name && updates.name !== agent.name) {
4587
+ const existing = d.query("SELECT id FROM agents WHERE name = ? AND id != ?").get(updates.name, agent.id);
4588
+ if (existing) {
4589
+ throw new Error(`Agent name already taken: ${updates.name}`);
4590
+ }
4591
+ d.run("UPDATE agents SET name = ? WHERE id = ?", [updates.name, agent.id]);
4592
+ }
4593
+ if (updates.description !== undefined) {
4594
+ d.run("UPDATE agents SET description = ? WHERE id = ?", [updates.description, agent.id]);
4595
+ }
4596
+ if (updates.role !== undefined) {
4597
+ d.run("UPDATE agents SET role = ? WHERE id = ?", [updates.role, agent.id]);
4598
+ }
4599
+ if (updates.metadata !== undefined) {
4600
+ d.run("UPDATE agents SET metadata = ? WHERE id = ?", [JSON.stringify(updates.metadata), agent.id]);
4601
+ }
4602
+ d.run("UPDATE agents SET last_seen_at = ? WHERE id = ?", [timestamp, agent.id]);
4603
+ return getAgent(agent.id, d);
4604
+ }
4580
4605
 
4581
4606
  // src/db/projects.ts
4582
4607
  function parseProjectRow(row) {
@@ -5059,6 +5084,35 @@ Last seen: ${agent.last_seen_at}`
5059
5084
  return { content: [{ type: "text", text: formatError(e) }], isError: true };
5060
5085
  }
5061
5086
  });
5087
+ server.tool("update_agent", "Update an agent's name, description, role, or metadata. Agents can update themselves.", {
5088
+ id: exports_external.string().describe("Agent ID or name"),
5089
+ name: exports_external.string().optional().describe("New agent name"),
5090
+ description: exports_external.string().optional().describe("New description"),
5091
+ role: exports_external.string().optional().describe("New role"),
5092
+ metadata: exports_external.record(exports_external.unknown()).optional().describe("Updated metadata")
5093
+ }, async (args) => {
5094
+ try {
5095
+ const { id, ...updates } = args;
5096
+ const agent = updateAgent(id, updates);
5097
+ if (!agent) {
5098
+ return { content: [{ type: "text", text: `Agent not found: ${id}` }] };
5099
+ }
5100
+ return {
5101
+ content: [{
5102
+ type: "text",
5103
+ text: `Agent updated:
5104
+ ID: ${agent.id}
5105
+ Name: ${agent.name}
5106
+ Description: ${agent.description || "-"}
5107
+ Role: ${agent.role || "agent"}
5108
+ Metadata: ${JSON.stringify(agent.metadata)}
5109
+ Last seen: ${agent.last_seen_at}`
5110
+ }]
5111
+ };
5112
+ } catch (e) {
5113
+ return { content: [{ type: "text", text: formatError(e) }], isError: true };
5114
+ }
5115
+ });
5062
5116
  server.tool("register_project", "Register a project for memory scoping", {
5063
5117
  name: exports_external.string().describe("Project name"),
5064
5118
  path: exports_external.string().describe("Absolute path to project"),
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":";AACA;;;GAGG;AAwiBH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAmC9C"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":";AACA;;;GAGG;AAslBH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAkD9C"}
@@ -1,6 +1,11 @@
1
1
  #!/usr/bin/env bun
2
2
  // @bun
3
3
 
4
+ // src/server/index.ts
5
+ import { existsSync as existsSync2 } from "fs";
6
+ import { dirname as dirname2, extname, join as join2 } from "path";
7
+ import { fileURLToPath } from "url";
8
+
4
9
  // src/types/index.ts
5
10
  class MemoryNotFoundError extends Error {
6
11
  constructor(id) {
@@ -755,6 +760,44 @@ function parsePort() {
755
760
  }
756
761
  return DEFAULT_PORT;
757
762
  }
763
+ function resolveDashboardDir() {
764
+ const candidates = [];
765
+ try {
766
+ const scriptDir = dirname2(fileURLToPath(import.meta.url));
767
+ candidates.push(join2(scriptDir, "..", "dashboard", "dist"));
768
+ candidates.push(join2(scriptDir, "..", "..", "dashboard", "dist"));
769
+ } catch {}
770
+ if (process.argv[1]) {
771
+ const mainDir = dirname2(process.argv[1]);
772
+ candidates.push(join2(mainDir, "..", "dashboard", "dist"));
773
+ candidates.push(join2(mainDir, "..", "..", "dashboard", "dist"));
774
+ }
775
+ candidates.push(join2(process.cwd(), "dashboard", "dist"));
776
+ for (const c of candidates) {
777
+ if (existsSync2(c))
778
+ return c;
779
+ }
780
+ return join2(process.cwd(), "dashboard", "dist");
781
+ }
782
+ var MIME_TYPES = {
783
+ ".html": "text/html; charset=utf-8",
784
+ ".js": "application/javascript",
785
+ ".css": "text/css",
786
+ ".json": "application/json",
787
+ ".svg": "image/svg+xml",
788
+ ".png": "image/png",
789
+ ".ico": "image/x-icon",
790
+ ".woff": "font/woff",
791
+ ".woff2": "font/woff2"
792
+ };
793
+ function serveStaticFile(filePath) {
794
+ if (!existsSync2(filePath))
795
+ return null;
796
+ const ct = MIME_TYPES[extname(filePath)] || "application/octet-stream";
797
+ return new Response(Bun.file(filePath), {
798
+ headers: { "Content-Type": ct }
799
+ });
800
+ }
758
801
  var CORS_HEADERS = {
759
802
  "Access-Control-Allow-Origin": "*",
760
803
  "Access-Control-Allow-Methods": "GET, POST, PATCH, DELETE, OPTIONS",
@@ -1117,6 +1160,20 @@ function startServer(port) {
1117
1160
  }
1118
1161
  const matched = matchRoute(req.method, pathname);
1119
1162
  if (!matched) {
1163
+ if (pathname.startsWith("/api/")) {
1164
+ return errorResponse("Not found", 404);
1165
+ }
1166
+ const dashDir = resolveDashboardDir();
1167
+ if (existsSync2(dashDir) && (req.method === "GET" || req.method === "HEAD")) {
1168
+ if (pathname !== "/") {
1169
+ const staticRes = serveStaticFile(join2(dashDir, pathname));
1170
+ if (staticRes)
1171
+ return staticRes;
1172
+ }
1173
+ const indexRes = serveStaticFile(join2(dashDir, "index.html"));
1174
+ if (indexRes)
1175
+ return indexRes;
1176
+ }
1120
1177
  return errorResponse("Not found", 404);
1121
1178
  }
1122
1179
  try {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hasna/mementos",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "description": "Universal memory system for AI agents - CLI + MCP server + library API",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",