@jcyamacho/agent-memory 0.0.2 → 0.0.4

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.
Files changed (3) hide show
  1. package/README.md +36 -28
  2. package/dist/index.js +100 -147
  3. package/package.json +2 -2
package/README.md CHANGED
@@ -13,6 +13,18 @@ decisions across sessions.
13
13
 
14
14
  ## Quick Start
15
15
 
16
+ Claude CLI:
17
+
18
+ ```bash
19
+ claude mcp add --scope user memory -- npx -y @jcyamacho/agent-memory
20
+ ```
21
+
22
+ Codex CLI:
23
+
24
+ ```bash
25
+ codex mcp add memory -- npx -y @jcyamacho/agent-memory
26
+ ```
27
+
16
28
  Example MCP server config:
17
29
 
18
30
  ```json
@@ -51,22 +63,22 @@ With a custom database path:
51
63
  Recommended LLM instructions to pair with this MCP:
52
64
 
53
65
  ```text
54
- Use `memory_recall` at the start of a task, when the user refers to previous
55
- context, or whenever prior preferences, project facts, or decisions may help.
56
-
57
- Use `memory_remember` to save durable context that will matter later, such as
58
- user preferences, project conventions, architecture decisions, constraints, and
59
- stable workflow habits.
60
-
61
- Store concise, self-contained facts or short notes. Include `source`,
62
- `workspace`, and `session` when available so future retrieval is better scoped.
63
-
64
- Do not store secrets, credentials, API keys, tokens, or temporary noise.
65
-
66
- When recalling, use short factual queries and keep `limit` small unless you
67
- need broader recall. Use `preferred_workspace` or `preferred_source` to bias
68
- ranking, and `filter_workspace` or `filter_source` only when exact scoping is
69
- required.
66
+ Use `memory_recall` at task start and whenever prior preferences, project facts,
67
+ or decisions may matter.
68
+
69
+ Use `memory_remember` only for durable, reusable context: preferences,
70
+ conventions, decisions, constraints, and stable workflow habits. Store one
71
+ concise, self-contained fact per memory. Include `workspace` when available. Do
72
+ not store secrets or temporary noise.
73
+
74
+ For `memory_recall`, pass `terms` as 2-5 distinctive strings that describe what
75
+ you are looking for. Prefer names, identifiers, package names, file names, and
76
+ short phrases. Each term is matched independently more terms cast a wider net,
77
+ and results matching multiple terms rank higher. Stemming is applied
78
+ automatically, so exact word forms are not required.
79
+
80
+ Use `workspace` to bias ranking toward the current project. Use `created_*`
81
+ only for exact scoping.
70
82
  ```
71
83
 
72
84
  ## What It Stores
@@ -76,7 +88,7 @@ This MCP is useful for context that should survive across turns and sessions:
76
88
  - User preferences like response style, formatting, and workflow habits
77
89
  - Project facts like paths, architecture choices, and conventions
78
90
  - Important decisions and constraints that should not be rediscovered
79
- - Session-linked notes that still matter later
91
+ - Project-scoped notes that still matter later
80
92
 
81
93
  ## Tools
82
94
 
@@ -87,16 +99,12 @@ Save durable context for later recall.
87
99
  Inputs:
88
100
 
89
101
  - `content` -> fact, preference, decision, or context to store
90
- - `source` -> client, tool, or agent name
91
102
  - `workspace` -> repository or workspace path
92
- - `session` -> conversation or execution session identifier
93
103
 
94
104
  Output:
95
105
 
96
106
  - `id`
97
- - `source`
98
107
  - `workspace`
99
- - `session`
100
108
  - `created_at`
101
109
 
102
110
  ### `recall`
@@ -105,19 +113,16 @@ Retrieve relevant memories for the current task.
105
113
 
106
114
  Inputs:
107
115
 
108
- - `query` -> keywords, names, facts, or phrases to search for
116
+ - `terms` -> 2-5 distinctive terms or short phrases that should appear in the
117
+ memory content; avoid full natural-language questions
109
118
  - `limit` -> maximum results to return
110
- - `preferred_source` -> ranking hint for a source
111
- - `preferred_workspace` -> ranking hint for a workspace
112
- - `filter_source` -> exact source filter
113
- - `filter_workspace` -> exact workspace filter
119
+ - `workspace` -> workspace or repo path; biases ranking toward this workspace
114
120
  - `created_after` -> ISO 8601 lower bound
115
121
  - `created_before` -> ISO 8601 upper bound
116
122
 
117
123
  Output:
118
124
 
119
- - `results[]` with `id`, `content`, `score`, `source`, `workspace`, `session`,
120
- and `created_at`
125
+ - `results[]` with `id`, `content`, `score`, `workspace`, and `created_at`
121
126
 
122
127
  ## Setup
123
128
 
@@ -150,6 +155,9 @@ Set `AGENT_MEMORY_DB_PATH` when you want to:
150
155
  - share a memory DB across multiple clients
151
156
  - store the DB somewhere easier to back up or inspect
152
157
 
158
+ Beta note: schema changes are not migrated. If you are upgrading from an older
159
+ beta, delete the existing memory DB and let the server create a new one.
160
+
153
161
  ## Run from source
154
162
 
155
163
  If you are developing locally instead of using the published package:
package/dist/index.js CHANGED
@@ -12464,7 +12464,7 @@ class StdioServerTransport {
12464
12464
  }
12465
12465
  }
12466
12466
  // package.json
12467
- var version2 = "0.0.2";
12467
+ var version2 = "0.0.4";
12468
12468
 
12469
12469
  // src/config.ts
12470
12470
  import { homedir } from "node:os";
@@ -19881,6 +19881,9 @@ var EMPTY_COMPLETION_RESULT = {
19881
19881
  }
19882
19882
  };
19883
19883
 
19884
+ // src/memory-service.ts
19885
+ import { randomUUID } from "node:crypto";
19886
+
19884
19887
  // src/errors.ts
19885
19888
  class MemoryError extends Error {
19886
19889
  code;
@@ -19905,6 +19908,63 @@ class PersistenceError extends MemoryError {
19905
19908
  }
19906
19909
  }
19907
19910
 
19911
+ // src/memory-service.ts
19912
+ var DEFAULT_LIMIT = 15;
19913
+ var MAX_LIMIT = 50;
19914
+
19915
+ class MemoryService {
19916
+ repository;
19917
+ constructor(repository) {
19918
+ this.repository = repository;
19919
+ }
19920
+ async save(input) {
19921
+ const content = input.content.trim();
19922
+ if (!content) {
19923
+ throw new ValidationError("Memory content is required.");
19924
+ }
19925
+ const now = new Date;
19926
+ const memory = {
19927
+ id: randomUUID(),
19928
+ content,
19929
+ workspace: normalizeOptionalString(input.workspace),
19930
+ createdAt: now,
19931
+ updatedAt: now
19932
+ };
19933
+ return this.repository.save(memory);
19934
+ }
19935
+ async search(input) {
19936
+ const terms = normalizeTerms(input.terms);
19937
+ if (terms.length === 0) {
19938
+ throw new ValidationError("At least one search term is required.");
19939
+ }
19940
+ const normalizedQuery = {
19941
+ terms,
19942
+ limit: normalizeLimit(input.limit),
19943
+ workspace: normalizeOptionalString(input.workspace),
19944
+ createdAfter: input.createdAfter,
19945
+ createdBefore: input.createdBefore
19946
+ };
19947
+ return this.repository.search(normalizedQuery);
19948
+ }
19949
+ }
19950
+ var normalizeLimit = (value) => {
19951
+ if (value === undefined) {
19952
+ return DEFAULT_LIMIT;
19953
+ }
19954
+ if (!Number.isInteger(value) || value < 1 || value > MAX_LIMIT) {
19955
+ throw new ValidationError(`Limit must be an integer between 1 and ${MAX_LIMIT}.`);
19956
+ }
19957
+ return value;
19958
+ };
19959
+ var normalizeOptionalString = (value) => {
19960
+ const trimmed = value?.trim();
19961
+ return trimmed ? trimmed : undefined;
19962
+ };
19963
+ var normalizeTerms = (terms) => {
19964
+ const normalizedTerms = terms.map((term) => term.trim()).filter(Boolean);
19965
+ return [...new Set(normalizedTerms)];
19966
+ };
19967
+
19908
19968
  // src/tools/shared.ts
19909
19969
  var toMcpError = (error2) => {
19910
19970
  if (error2 instanceof McpError) {
@@ -19932,23 +19992,18 @@ var parseOptionalDate = (value, fieldName) => {
19932
19992
 
19933
19993
  // src/tools/recall.ts
19934
19994
  var recallInputSchema = {
19935
- query: string2().describe("What to look for in memory. Use keywords, short phrases, names, decisions, or facts that should match previously remembered context."),
19936
- limit: number2().int().min(1).max(20).optional().describe("Maximum number of memory results to return. Use a small number when you only need the best matches."),
19937
- preferred_source: string2().optional().describe("Preferred source to rank higher when relevant, such as a client, tool, or agent name. This does not exclude other sources."),
19938
- preferred_workspace: string2().optional().describe("Preferred workspace or repository path to rank higher when relevant. This does not exclude other workspaces."),
19939
- filter_source: string2().optional().describe("Only return memories from this exact source."),
19940
- filter_workspace: string2().optional().describe("Only return memories from this exact workspace or repository path."),
19995
+ terms: array(string2()).min(1).describe("Search terms to match against remembered content. Use distinctive keywords, IDs, names, file names, or short phrases as separate items."),
19996
+ limit: number2().int().min(1).max(MAX_LIMIT).optional().describe("Maximum number of memory results to return. Use a small number when you only need the best matches."),
19997
+ workspace: string2().optional().describe("Workspace or repository path. Memories from this workspace rank higher, but other workspaces are not excluded."),
19941
19998
  created_after: string2().optional().describe("Only return memories created at or after this ISO 8601 timestamp."),
19942
19999
  created_before: string2().optional().describe("Only return memories created at or before this ISO 8601 timestamp.")
19943
20000
  };
19944
20001
  var recallOutputSchema = {
19945
20002
  results: array(object({
19946
20003
  id: string2().describe("Stable identifier for the remembered item."),
19947
- content: string2().describe("The remembered content that matched the query."),
20004
+ content: string2().describe("The remembered content that matched the search terms."),
19948
20005
  score: number2().describe("Relevance score for this result. Higher means a better match."),
19949
- source: string2().optional().describe("Source associated with the memory, if available."),
19950
20006
  workspace: string2().optional().describe("Workspace associated with the memory, if available."),
19951
- session: string2().optional().describe("Session associated with the memory, if available."),
19952
20007
  created_at: string2().describe("ISO 8601 timestamp showing when the memory was created.")
19953
20008
  }))
19954
20009
  };
@@ -19957,24 +20012,12 @@ var registerRecallTool = (server, memoryService) => {
19957
20012
  description: "Retrieve previously remembered context that may help with the current task. Use it for user preferences, project facts, prior decisions, constraints, or earlier conversation details.",
19958
20013
  inputSchema: recallInputSchema,
19959
20014
  outputSchema: recallOutputSchema
19960
- }, async ({
19961
- query,
19962
- limit,
19963
- preferred_source,
19964
- preferred_workspace,
19965
- filter_source,
19966
- filter_workspace,
19967
- created_after,
19968
- created_before
19969
- }) => {
20015
+ }, async ({ terms, limit, workspace, created_after, created_before }) => {
19970
20016
  try {
19971
20017
  const results = await memoryService.search({
19972
- query,
20018
+ terms,
19973
20019
  limit,
19974
- preferredSource: preferred_source,
19975
- preferredWorkspace: preferred_workspace,
19976
- filterSource: filter_source,
19977
- filterWorkspace: filter_workspace,
20020
+ workspace,
19978
20021
  createdAfter: parseOptionalDate(created_after, "created_after"),
19979
20022
  createdBefore: parseOptionalDate(created_before, "created_before")
19980
20023
  });
@@ -19983,17 +20026,17 @@ var registerRecallTool = (server, memoryService) => {
19983
20026
  id: result.id,
19984
20027
  content: result.content,
19985
20028
  score: result.score,
19986
- source: result.source,
19987
20029
  workspace: result.workspace,
19988
- session: result.session,
19989
20030
  created_at: result.createdAt.toISOString()
19990
20031
  }))
19991
20032
  };
20033
+ const matchCount = structuredContent.results.length;
20034
+ const summary = matchCount === 1 ? "Found 1 matching memory." : `Found ${matchCount} matching memories.`;
19992
20035
  return {
19993
20036
  content: [
19994
20037
  {
19995
20038
  type: "text",
19996
- text: JSON.stringify(structuredContent, null, 2)
20039
+ text: summary
19997
20040
  }
19998
20041
  ],
19999
20042
  structuredContent
@@ -20007,15 +20050,11 @@ var registerRecallTool = (server, memoryService) => {
20007
20050
  // src/tools/remember.ts
20008
20051
  var rememberInputSchema = {
20009
20052
  content: string2().describe("The exact fact, preference, decision, or context to remember for future retrieval. Use a self-contained sentence or short note."),
20010
- source: string2().optional().describe("Where this memory came from, such as the client, tool, or agent name. Helps with filtering and ranking later."),
20011
- workspace: string2().optional().describe("Repository or workspace path this memory belongs to. Use it to keep memories scoped to a project."),
20012
- session: string2().optional().describe("Conversation or execution session identifier. Useful for tying memories back to one run or thread.")
20053
+ workspace: string2().optional().describe("Repository or workspace path this memory belongs to. Use it to keep memories scoped to a project.")
20013
20054
  };
20014
20055
  var rememberOutputSchema = {
20015
20056
  id: string2().describe("Stable identifier for the saved memory."),
20016
- source: string2().optional().describe("Source stored with the memory, if provided."),
20017
20057
  workspace: string2().optional().describe("Workspace stored with the memory, if provided."),
20018
- session: string2().optional().describe("Session stored with the memory, if provided."),
20019
20058
  created_at: string2().describe("ISO 8601 timestamp showing when the memory was created.")
20020
20059
  };
20021
20060
  var registerRememberTool = (server, memoryService) => {
@@ -20023,26 +20062,22 @@ var registerRememberTool = (server, memoryService) => {
20023
20062
  description: "Save durable context for later recall. Use this for user preferences, project facts, decisions, constraints, or other information worth remembering across turns and tools.",
20024
20063
  inputSchema: rememberInputSchema,
20025
20064
  outputSchema: rememberOutputSchema
20026
- }, async ({ content, source, workspace, session }) => {
20065
+ }, async ({ content, workspace }) => {
20027
20066
  try {
20028
20067
  const memory = await memoryService.save({
20029
20068
  content,
20030
- source,
20031
- workspace,
20032
- session
20069
+ workspace
20033
20070
  });
20034
20071
  const structuredContent = {
20035
20072
  id: memory.id,
20036
- source: memory.source,
20037
20073
  workspace: memory.workspace,
20038
- session: memory.session,
20039
20074
  created_at: memory.createdAt.toISOString()
20040
20075
  };
20041
20076
  return {
20042
20077
  content: [
20043
20078
  {
20044
20079
  type: "text",
20045
- text: JSON.stringify(structuredContent, null, 2)
20080
+ text: "Saved memory."
20046
20081
  }
20047
20082
  ],
20048
20083
  structuredContent
@@ -20064,81 +20099,6 @@ var createMcpServer = (memoryService, version3) => {
20064
20099
  return server;
20065
20100
  };
20066
20101
 
20067
- // src/memory-service.ts
20068
- import { randomUUID } from "node:crypto";
20069
- var DEFAULT_LIMIT = 5;
20070
- var MAX_LIMIT = 20;
20071
- var SOURCE_BIAS = 0.15;
20072
- var WORKSPACE_BIAS = 0.1;
20073
-
20074
- class MemoryService {
20075
- repository;
20076
- constructor(repository) {
20077
- this.repository = repository;
20078
- }
20079
- async save(input) {
20080
- const content = input.content.trim();
20081
- if (!content) {
20082
- throw new ValidationError("Memory content is required.");
20083
- }
20084
- const now = new Date;
20085
- const memory = {
20086
- id: randomUUID(),
20087
- content,
20088
- source: normalizeOptionalString(input.source),
20089
- workspace: normalizeOptionalString(input.workspace),
20090
- session: normalizeOptionalString(input.session),
20091
- createdAt: now,
20092
- updatedAt: now
20093
- };
20094
- return this.repository.save(memory);
20095
- }
20096
- async search(input) {
20097
- const query = input.query.trim();
20098
- if (!query) {
20099
- throw new ValidationError("Search query is required.");
20100
- }
20101
- const normalizedQuery = {
20102
- query,
20103
- limit: normalizeLimit(input.limit),
20104
- preferredSource: normalizeOptionalString(input.preferredSource),
20105
- preferredWorkspace: normalizeOptionalString(input.preferredWorkspace),
20106
- filterSource: normalizeOptionalString(input.filterSource),
20107
- filterWorkspace: normalizeOptionalString(input.filterWorkspace),
20108
- createdAfter: input.createdAfter,
20109
- createdBefore: input.createdBefore
20110
- };
20111
- const results = await this.repository.search(normalizedQuery);
20112
- return results.map((result) => ({
20113
- ...result,
20114
- score: rankResult(result, normalizedQuery)
20115
- })).sort((left, right) => right.score - left.score).slice(0, normalizedQuery.limit);
20116
- }
20117
- }
20118
- var normalizeLimit = (value) => {
20119
- if (value === undefined) {
20120
- return DEFAULT_LIMIT;
20121
- }
20122
- if (!Number.isInteger(value) || value < 1 || value > MAX_LIMIT) {
20123
- throw new ValidationError(`Limit must be an integer between 1 and ${MAX_LIMIT}.`);
20124
- }
20125
- return value;
20126
- };
20127
- var normalizeOptionalString = (value) => {
20128
- const trimmed = value?.trim();
20129
- return trimmed ? trimmed : undefined;
20130
- };
20131
- var rankResult = (result, query) => {
20132
- let score = result.score;
20133
- if (query.preferredSource && result.source === query.preferredSource) {
20134
- score += SOURCE_BIAS;
20135
- }
20136
- if (query.preferredWorkspace && result.workspace === query.preferredWorkspace) {
20137
- score += WORKSPACE_BIAS;
20138
- }
20139
- return Number(score.toFixed(6));
20140
- };
20141
-
20142
20102
  // src/sqlite-db.ts
20143
20103
  import { mkdirSync } from "node:fs";
20144
20104
  import { dirname } from "node:path";
@@ -20147,22 +20107,19 @@ var MEMORY_SCHEMA = `
20147
20107
  CREATE TABLE IF NOT EXISTS memories (
20148
20108
  id TEXT PRIMARY KEY,
20149
20109
  content TEXT NOT NULL,
20150
- source TEXT,
20151
20110
  workspace TEXT,
20152
- session TEXT,
20153
20111
  created_at INTEGER NOT NULL,
20154
20112
  updated_at INTEGER NOT NULL
20155
20113
  );
20156
20114
 
20157
20115
  CREATE INDEX IF NOT EXISTS idx_memories_created_at ON memories(created_at);
20158
- CREATE INDEX IF NOT EXISTS idx_memories_source ON memories(source);
20159
20116
  CREATE INDEX IF NOT EXISTS idx_memories_workspace ON memories(workspace);
20160
20117
 
20161
20118
  CREATE VIRTUAL TABLE IF NOT EXISTS memories_fts USING fts5(
20162
20119
  content,
20163
20120
  content = 'memories',
20164
20121
  content_rowid = 'rowid',
20165
- tokenize = 'unicode61'
20122
+ tokenize = 'porter unicode61'
20166
20123
  );
20167
20124
 
20168
20125
  CREATE TRIGGER IF NOT EXISTS memories_ai AFTER INSERT ON memories BEGIN
@@ -20208,9 +20165,7 @@ var initializeMemoryDatabase = (database) => {
20208
20165
  };
20209
20166
 
20210
20167
  // src/sqlite-repository.ts
20211
- var CANDIDATE_MULTIPLIER = 5;
20212
- var MIN_CANDIDATES = 25;
20213
- var MAX_CANDIDATES = 100;
20168
+ var WORKSPACE_BIAS = 0.1;
20214
20169
 
20215
20170
  class SqliteMemoryRepository {
20216
20171
  database;
@@ -20221,9 +20176,7 @@ class SqliteMemoryRepository {
20221
20176
  INSERT INTO memories (
20222
20177
  id,
20223
20178
  content,
20224
- source,
20225
20179
  workspace,
20226
- session,
20227
20180
  created_at,
20228
20181
  updated_at
20229
20182
  ) VALUES (
@@ -20231,15 +20184,13 @@ class SqliteMemoryRepository {
20231
20184
  ?,
20232
20185
  ?,
20233
20186
  ?,
20234
- ?,
20235
- ?,
20236
20187
  ?
20237
20188
  )
20238
20189
  `);
20239
20190
  }
20240
20191
  async save(memory) {
20241
20192
  try {
20242
- this.insertStatement.run(memory.id, memory.content, memory.source, memory.workspace, memory.session, memory.createdAt.getTime(), memory.updatedAt.getTime());
20193
+ this.insertStatement.run(memory.id, memory.content, memory.workspace, memory.createdAt.getTime(), memory.updatedAt.getTime());
20243
20194
  return memory;
20244
20195
  } catch (error2) {
20245
20196
  throw new PersistenceError("Failed to save memory.", { cause: error2 });
@@ -20247,48 +20198,44 @@ class SqliteMemoryRepository {
20247
20198
  }
20248
20199
  async search(query) {
20249
20200
  try {
20250
- const whereClauses = ["memories_fts MATCH ?"];
20251
- const params = [toFtsQuery(query.query)];
20252
- if (query.filterSource) {
20253
- whereClauses.push("m.source = ?");
20254
- params.push(query.filterSource);
20255
- }
20256
- if (query.filterWorkspace) {
20257
- whereClauses.push("m.workspace = ?");
20258
- params.push(query.filterWorkspace);
20201
+ const selectParams = [];
20202
+ const whereParams = [toFtsQuery(query.terms)];
20203
+ let scoreExpr;
20204
+ if (query.workspace) {
20205
+ scoreExpr = "MAX(0, -bm25(memories_fts) + CASE WHEN m.workspace = ? THEN ? ELSE 0.0 END)";
20206
+ selectParams.push(query.workspace, WORKSPACE_BIAS);
20207
+ } else {
20208
+ scoreExpr = "MAX(0, -bm25(memories_fts))";
20259
20209
  }
20210
+ const whereClauses = ["memories_fts MATCH ?"];
20260
20211
  if (query.createdAfter) {
20261
20212
  whereClauses.push("m.created_at >= ?");
20262
- params.push(query.createdAfter.getTime());
20213
+ whereParams.push(query.createdAfter.getTime());
20263
20214
  }
20264
20215
  if (query.createdBefore) {
20265
20216
  whereClauses.push("m.created_at <= ?");
20266
- params.push(query.createdBefore.getTime());
20217
+ whereParams.push(query.createdBefore.getTime());
20267
20218
  }
20219
+ const params = [...selectParams, ...whereParams, query.limit];
20268
20220
  const statement = this.database.prepare(`
20269
20221
  SELECT
20270
20222
  m.id,
20271
20223
  m.content,
20272
- m.source,
20273
20224
  m.workspace,
20274
- m.session,
20275
20225
  m.created_at,
20276
- MAX(0, -bm25(memories_fts)) AS score
20226
+ ${scoreExpr} AS score
20277
20227
  FROM memories_fts
20278
20228
  INNER JOIN memories AS m ON m.rowid = memories_fts.rowid
20279
20229
  WHERE ${whereClauses.join(" AND ")}
20280
- ORDER BY bm25(memories_fts)
20230
+ ORDER BY score DESC
20281
20231
  LIMIT ?
20282
20232
  `);
20283
- params.push(toCandidateLimit(query.limit));
20284
20233
  const rows = statement.all(...params);
20285
20234
  return rows.map((row) => ({
20286
20235
  id: row.id,
20287
20236
  content: row.content,
20288
20237
  score: row.score,
20289
- source: row.source ?? undefined,
20290
20238
  workspace: row.workspace ?? undefined,
20291
- session: row.session ?? undefined,
20292
20239
  createdAt: new Date(row.created_at)
20293
20240
  }));
20294
20241
  } catch (error2) {
@@ -20298,8 +20245,14 @@ class SqliteMemoryRepository {
20298
20245
  }
20299
20246
  }
20300
20247
  }
20301
- var toCandidateLimit = (limit) => Math.min(Math.max(limit * CANDIDATE_MULTIPLIER, MIN_CANDIDATES), MAX_CANDIDATES);
20302
- var toFtsQuery = (query) => query.trim().split(/\s+/).filter(Boolean).map((term) => `"${term.replaceAll('"', '""')}"`).join(" ");
20248
+ var toFtsQuery = (terms) => terms.map(toFtsTerm).join(" OR ");
20249
+ var toFtsTerm = (term) => {
20250
+ const escaped = term.replaceAll('"', '""');
20251
+ if (term.includes(" ")) {
20252
+ return `"${escaped}"`;
20253
+ }
20254
+ return `"${escaped}"*`;
20255
+ };
20303
20256
 
20304
20257
  // src/index.ts
20305
20258
  var { databasePath } = resolveConfig();
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@jcyamacho/agent-memory",
3
3
  "main": "dist/index.js",
4
- "version": "0.0.2",
4
+ "version": "0.0.4",
5
5
  "bin": {
6
6
  "agent-memory": "dist/index.js"
7
7
  },
@@ -23,7 +23,7 @@
23
23
  "build": "bun build src/index.ts --target=node --external better-sqlite3 --outfile dist/index.js --banner \"#!/usr/bin/env node\"",
24
24
  "start": "node dist/index.js",
25
25
  "test": "bun test",
26
- "lint": "biome check --write",
26
+ "lint": "biome check --write && tsc --noEmit",
27
27
  "release:patch": "npm version patch && git push origin main --follow-tags",
28
28
  "release:minor": "npm version minor && git push origin main --follow-tags",
29
29
  "release:major": "npm version major && git push origin main --follow-tags"