@hasna/mementos 0.14.70 → 0.14.72

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/bun.lock CHANGED
@@ -8,7 +8,7 @@
8
8
  "@ai-sdk/anthropic": "^3.0.82",
9
9
  "@ai-sdk/openai": "^3.0.69",
10
10
  "@ai-sdk/openai-compatible": "^2.0.48",
11
- "@hasna/contracts": "0.4.2",
11
+ "@hasna/contracts": "0.8.5",
12
12
  "@hasna/events": "^0.1.6",
13
13
  "@modelcontextprotocol/sdk": "^1.12.1",
14
14
  "ai": "^6.0.199",
@@ -44,7 +44,7 @@
44
44
 
45
45
  "@alcalzone/ansi-tokenize": ["@alcalzone/ansi-tokenize@0.1.3", "", { "dependencies": { "ansi-styles": "^6.2.1", "is-fullwidth-code-point": "^4.0.0" } }, "sha512-3yWxPTq3UQ/FY9p1ErPxIyfT64elWaMvM9lIHnaqpyft63tkxodF5aUElYHrdisWve5cETkh1+KBw1yJuW0aRw=="],
46
46
 
47
- "@hasna/contracts": ["@hasna/contracts@0.4.2", "", { "dependencies": { "commander": "^13.1.0", "zod": "^3.25.76" }, "bin": { "contracts": "dist/cli/index.js", "contracts-cli": "dist/cli/index.js" } }, "sha512-xD7ZWQXR+AjYAJVpaMsQ+8V0SABiJSKVeI0B1WbPByYeGz6daDtgyZ6c3q0c2S6uzIEtUxlGHPundr675636ew=="],
47
+ "@hasna/contracts": ["@hasna/contracts@0.8.5", "", { "dependencies": { "commander": "^13.1.0", "zod": "^3.25.76" }, "bin": { "contracts": "dist/cli/index.js", "contracts-cli": "dist/cli/contracts-cli.js" } }, "sha512-Iyk5srD6J3R7ci2g0gkyt+MCa6Da/lghPosGtgWBRgtJeGYCIAAnHF1yweoXnnqGAWZajFuDgJEWDVH11qpUhA=="],
48
48
 
49
49
  "@hasna/events": ["@hasna/events@0.1.6", "", { "dependencies": { "commander": "^13.1.0" }, "bin": { "events": "dist/cli/index.js", "hasna-events": "dist/cli/index.js" } }, "sha512-rKLxjBIat45UxciUwh9hKM63l/mcurJXAhgVkYHvrsGnOK9HwExrwgOlylNzDBDb+huiQw9DWdLb31q5oWDfIw=="],
50
50
 
@@ -0,0 +1,3 @@
1
+ export declare const RECALL_EXIT_NOT_FOUND = 1;
2
+ export declare const RECALL_EXIT_FUZZY = 2;
3
+ //# sourceMappingURL=memory-cmd-recall-exit.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"memory-cmd-recall-exit.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/memory-cmd-recall-exit.ts"],"names":[],"mappings":"AAeA,eAAO,MAAM,qBAAqB,IAAI,CAAC;AACvC,eAAO,MAAM,iBAAiB,IAAI,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"memory-cmd-recall.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/memory-cmd-recall.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AASzC,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CA6D5D"}
1
+ {"version":3,"file":"memory-cmd-recall.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/memory-cmd-recall.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAUzC,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAwF5D"}
@@ -1 +1 @@
1
- {"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../src/cli/helpers.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../src/cli/helpers.ts"],"names":[],"mappings":"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"}
package/dist/cli/index.js CHANGED
@@ -6536,9 +6536,14 @@ function readFileConfig() {
6536
6536
  if (!existsSync4(configPath))
6537
6537
  return {};
6538
6538
  try {
6539
- return JSON.parse(readFileSync2(configPath, "utf-8"));
6540
- } catch {
6541
- return {};
6539
+ const data = JSON.parse(readFileSync2(configPath, "utf-8"));
6540
+ if (data === null || typeof data !== "object" || Array.isArray(data)) {
6541
+ throw new Error("expected a JSON object");
6542
+ }
6543
+ return data;
6544
+ } catch (error) {
6545
+ const detail = error instanceof Error ? error.message : String(error);
6546
+ throw new Error(`Cannot update global config at ${configPath}: ${detail}`);
6542
6547
  }
6543
6548
  }
6544
6549
  function writeFileConfig(data) {
@@ -60574,9 +60579,15 @@ init_search();
60574
60579
  init_helpers();
60575
60580
  import chalk11 from "chalk";
60576
60581
  import { resolve as resolve6 } from "path";
60582
+
60583
+ // src/cli/commands/memory-cmd-recall-exit.ts
60584
+ var RECALL_EXIT_NOT_FOUND = 1;
60585
+ var RECALL_EXIT_FUZZY = 2;
60586
+
60587
+ // src/cli/commands/memory-cmd-recall.ts
60577
60588
  function registerRecallCommand(program2) {
60578
60589
  const handleError = makeHandleError(program2);
60579
- program2.command("recall <key>").description("Recall a memory by key").option("--scope <scope>", "Scope filter").option("--agent <name>", "Agent filter").option("--project <path>", "Project filter").action((key, opts) => {
60590
+ program2.command("recall <key>").alias("get").description("Recall a memory by exact key (use --fuzzy to fall back to the nearest match)").option("--scope <scope>", "Scope filter").option("--agent <name>", "Agent filter").option("--project <path>", "Project filter").option("--fuzzy", "If the exact key is absent, return the nearest match instead (exits 2)").action((key, opts) => {
60580
60591
  try {
60581
60592
  const globalOpts = program2.opts();
60582
60593
  const agentId = opts.agent || globalOpts.agent;
@@ -60588,7 +60599,7 @@ function registerRecallCommand(program2) {
60588
60599
  projectId = project.id;
60589
60600
  }
60590
60601
  const memory = getMemoryByKey(key, opts.scope, agentId, projectId);
60591
- if (memory) {
60602
+ if (memory && memory.key === key) {
60592
60603
  touchMemory(memory.id);
60593
60604
  if (globalOpts.json) {
60594
60605
  outputJson(memory);
@@ -60597,29 +60608,39 @@ function registerRecallCommand(program2) {
60597
60608
  }
60598
60609
  return;
60599
60610
  }
60600
- const results = searchMemories(key, {
60601
- scope: opts.scope,
60602
- agent_id: agentId,
60603
- project_id: projectId,
60604
- limit: 1
60605
- });
60606
- if (results.length > 0) {
60607
- const best = results[0];
60608
- touchMemory(best.memory.id);
60609
- if (globalOpts.json) {
60610
- outputJson({ fuzzy_match: true, score: best.score, match_type: best.match_type, memory: best.memory });
60611
- } else {
60612
- console.log(chalk11.yellow(`No exact match, showing best result (score: ${best.score.toFixed(2)}, match: ${best.match_type}):`));
60613
- console.log(formatMemoryDetail(best.memory));
60611
+ if (opts.fuzzy) {
60612
+ const results = searchMemories(key, {
60613
+ scope: opts.scope,
60614
+ agent_id: agentId,
60615
+ project_id: projectId,
60616
+ limit: 1
60617
+ });
60618
+ if (results.length > 0) {
60619
+ const best = results[0];
60620
+ touchMemory(best.memory.id);
60621
+ if (globalOpts.json) {
60622
+ outputJson({
60623
+ fuzzy_match: true,
60624
+ requested_key: key,
60625
+ returned_key: best.memory.key,
60626
+ score: best.score,
60627
+ match_type: best.match_type,
60628
+ memory: best.memory
60629
+ });
60630
+ } else {
60631
+ console.error(chalk11.yellow(`No memory with key "${key}". Showing the nearest match "${best.memory.key}" ` + `(score: ${best.score.toFixed(2)}, match: ${best.match_type}) \u2014 this is a DIFFERENT record.`));
60632
+ console.log(formatMemoryDetail(best.memory));
60633
+ }
60634
+ process.exit(RECALL_EXIT_FUZZY);
60614
60635
  }
60615
- return;
60616
60636
  }
60637
+ const message = opts.fuzzy ? `No memory found for key: ${key}` : `No memory found for key: ${key} (exact match; pass --fuzzy to return the nearest record instead)`;
60617
60638
  if (globalOpts.json) {
60618
- outputJson({ error: `No memory found for key: ${key}` });
60639
+ outputJson({ error: message, requested_key: key });
60619
60640
  } else {
60620
- console.error(chalk11.yellow(`No memory found for key: ${key}`));
60641
+ console.error(chalk11.yellow(message));
60621
60642
  }
60622
- process.exit(1);
60643
+ process.exit(RECALL_EXIT_NOT_FOUND);
60623
60644
  } catch (e) {
60624
60645
  handleError(e);
60625
60646
  }
@@ -61489,6 +61510,21 @@ function readGlobalConfig() {
61489
61510
  return {};
61490
61511
  }
61491
61512
  }
61513
+ function readGlobalConfigForWrite() {
61514
+ const p = globalConfigPath();
61515
+ if (!existsSync4(p))
61516
+ return {};
61517
+ try {
61518
+ const data = JSON.parse(readFileSync4(p, "utf-8"));
61519
+ if (data === null || typeof data !== "object" || Array.isArray(data)) {
61520
+ throw new Error("expected a JSON object");
61521
+ }
61522
+ return data;
61523
+ } catch (error) {
61524
+ const detail = error instanceof Error ? error.message : String(error);
61525
+ throw new Error(`Cannot update global config at ${p}: ${detail}`);
61526
+ }
61527
+ }
61492
61528
  function writeGlobalConfig(data) {
61493
61529
  const p = globalConfigPath();
61494
61530
  ensureDir2(dirname3(p));
@@ -61502,7 +61538,7 @@ function getActiveProfile() {
61502
61538
  return cfg["active_profile"] || null;
61503
61539
  }
61504
61540
  function setActiveProfile(name) {
61505
- const cfg = readGlobalConfig();
61541
+ const cfg = readGlobalConfigForWrite();
61506
61542
  if (name === null) {
61507
61543
  delete cfg["active_profile"];
61508
61544
  } else {
package/dist/index.js CHANGED
@@ -51717,6 +51717,21 @@ function readGlobalConfig() {
51717
51717
  return {};
51718
51718
  }
51719
51719
  }
51720
+ function readGlobalConfigForWrite() {
51721
+ const p = globalConfigPath();
51722
+ if (!existsSync3(p))
51723
+ return {};
51724
+ try {
51725
+ const data = JSON.parse(readFileSync2(p, "utf-8"));
51726
+ if (data === null || typeof data !== "object" || Array.isArray(data)) {
51727
+ throw new Error("expected a JSON object");
51728
+ }
51729
+ return data;
51730
+ } catch (error) {
51731
+ const detail = error instanceof Error ? error.message : String(error);
51732
+ throw new Error(`Cannot update global config at ${p}: ${detail}`);
51733
+ }
51734
+ }
51720
51735
  function writeGlobalConfig(data) {
51721
51736
  const p = globalConfigPath();
51722
51737
  ensureDir2(dirname2(p));
@@ -51730,7 +51745,7 @@ function getActiveProfile() {
51730
51745
  return cfg["active_profile"] || null;
51731
51746
  }
51732
51747
  function setActiveProfile(name) {
51733
- const cfg = readGlobalConfig();
51748
+ const cfg = readGlobalConfigForWrite();
51734
51749
  if (name === null) {
51735
51750
  delete cfg["active_profile"];
51736
51751
  } else {
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/lib/config.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,cAAc,EAA+B,MAAM,UAAU,CAAC;AAc5E,eAAO,MAAM,cAAc,EAAE,cA4B5B,CAAC;AA4DF,wBAAgB,UAAU,IAAI,cAAc,CAwC3C;AA4ED,wBAAgB,gBAAgB,IAAI,MAAM,GAAG,IAAI,CAMhD;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,CAQ1D;AAED,wBAAgB,YAAY,IAAI,MAAM,EAAE,CAOvC;AAED,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAOnD;AAED,wBAAgB,SAAS,IAAI,MAAM,CAmDlC"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/lib/config.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,cAAc,EAA+B,MAAM,UAAU,CAAC;AAc5E,eAAO,MAAM,cAAc,EAAE,cA4B5B,CAAC;AA4DF,wBAAgB,UAAU,IAAI,cAAc,CAwC3C;AA2FD,wBAAgB,gBAAgB,IAAI,MAAM,GAAG,IAAI,CAMhD;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,CAQ1D;AAED,wBAAgB,YAAY,IAAI,MAAM,EAAE,CAOvC;AAED,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAOnD;AAED,wBAAgB,SAAS,IAAI,MAAM,CAmDlC"}
@@ -12,9 +12,24 @@ export interface GdprErasureResult {
12
12
  }
13
13
  /**
14
14
  * Erase all memories containing the given PII identifier.
15
- * Replaces value, summary, and key with "[REDACTED]".
16
- * Clears tags and metadata that might contain PII.
15
+ *
16
+ * Replaces `value` with "[REDACTED]", clears `summary`, `tags` and `metadata`,
17
+ * and rewrites `key` to `[REDACTED]:<random token>` — per-row, for the reason
18
+ * given at the UPDATE below. Nothing derived from the original key or imported
19
+ * row id is retained.
20
+ *
21
+ * The erase runs in ONE TRANSACTION and is therefore all-or-nothing: a caller
22
+ * never observes a partially-erased subject, and a failed attempt leaves the
23
+ * store fully intact so a retry starts from a clean, still-fully-matching set.
24
+ *
17
25
  * Preserves the audit trail (audit_log entries have hashes, not content).
26
+ *
27
+ * NOTE: an erased memory is no longer reachable by its original key, so a later
28
+ * `save` under that key creates a NEW record rather than merging into the
29
+ * tombstone. That is deliberate: silently resurrecting an erased row and
30
+ * re-associating it with the data subject is precisely what erasure must
31
+ * prevent. Every foreign key into `memories` references `memories(id)` — no
32
+ * relational integrity depends on `key`, which is a human lookup handle only.
18
33
  */
19
34
  export declare function gdprErase(identifier: string, options?: {
20
35
  project_id?: string;
@@ -1 +1 @@
1
- {"version":3,"file":"gdpr.d.ts","sourceRoot":"","sources":["../../src/lib/gdpr.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,aAAa,IAAI,QAAQ,EAAE,MAAM,eAAe,CAAC;AAG1D,MAAM,WAAW,iBAAiB;IAChC,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;;;;GAKG;AACH,wBAAgB,SAAS,CACvB,UAAU,EAAE,MAAM,EAClB,OAAO,GAAE;IACP,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,OAAO,CAAC;CACd,EACN,EAAE,CAAC,EAAE,QAAQ,GACZ,iBAAiB,CA+FnB"}
1
+ {"version":3,"file":"gdpr.d.ts","sourceRoot":"","sources":["../../src/lib/gdpr.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,aAAa,IAAI,QAAQ,EAAE,MAAM,eAAe,CAAC;AAG1D,MAAM,WAAW,iBAAiB;IAChC,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,SAAS,CACvB,UAAU,EAAE,MAAM,EAClB,OAAO,GAAE;IACP,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,OAAO,CAAC;CACd,EACN,EAAE,CAAC,EAAE,QAAQ,GACZ,iBAAiB,CA8JnB"}
package/dist/mcp/index.js CHANGED
@@ -12074,18 +12074,23 @@ function gdprErase(identifier, options = {}, db) {
12074
12074
  timestamp
12075
12075
  };
12076
12076
  }
12077
- const memoryIds = [];
12078
- for (const row of rows) {
12079
- d.run(`UPDATE memories SET
12077
+ const memoryIds = d.transaction(() => {
12078
+ const ids = [];
12079
+ for (const row of rows) {
12080
+ const redactedKey = `[REDACTED]:${crypto.randomUUID()}`;
12081
+ d.run(`UPDATE memories SET
12082
+ key = ?,
12080
12083
  value = '[REDACTED]',
12081
12084
  summary = NULL,
12082
12085
  tags = '[]',
12083
12086
  metadata = '{}',
12084
12087
  updated_at = ?
12085
- WHERE id = ?`, [timestamp, row.id]);
12086
- d.run("DELETE FROM memory_tags WHERE memory_id = ?", [row.id]);
12087
- memoryIds.push(row.id);
12088
- }
12088
+ WHERE id = ?`, [redactedKey, timestamp, row.id]);
12089
+ d.run("DELETE FROM memory_tags WHERE memory_id = ?", [row.id]);
12090
+ ids.push(row.id);
12091
+ }
12092
+ return ids;
12093
+ });
12089
12094
  return {
12090
12095
  erased_count: memoryIds.length,
12091
12096
  memory_ids: memoryIds,
@@ -2,15 +2,73 @@
2
2
  "$schema": "./node_modules/@hasna/contracts/dist/hasna.contract.schema.json",
3
3
  "schema": "hasna.service_contract.v1",
4
4
  "name": "mementos",
5
- "class": "service",
5
+ "class": "cli-with-store",
6
6
  "contractVersion": "v1",
7
- "kitVersion": "0.4.1",
8
- "description": "Universal memory system for AI agents — CLI + MCP server + REST serve API + typed SDK. self_hosted service backed by pure-remote Postgres (Amendment A1).",
9
- "bins": ["mementos", "mementos-mcp", "mementos-serve"],
7
+ "kitVersion": "0.8.5",
8
+ "description": "Universal memory system for AI agents — CLI, MCP server, REST API, and TypeScript SDK over one SQLite or PostgreSQL store.",
9
+ "bins": [
10
+ "mementos",
11
+ "mementos-mcp",
12
+ "mementos-serve"
13
+ ],
14
+ "hosting": [
15
+ "user-hosted"
16
+ ],
17
+ "serviceSurfaces": [
18
+ {
19
+ "name": "http-api",
20
+ "kind": "api",
21
+ "status": "supported",
22
+ "bin": "mementos-serve",
23
+ "authMode": "api-key",
24
+ "health": { "method": "GET", "path": "/health", "public": true },
25
+ "readiness": { "method": "GET", "path": "/ready", "public": true },
26
+ "version": { "method": "GET", "path": "/version", "public": true },
27
+ "apiBasePath": "/v1",
28
+ "openApiPath": "/v1/openapi.json"
29
+ },
30
+ {
31
+ "name": "typescript-sdk",
32
+ "kind": "sdk",
33
+ "status": "supported",
34
+ "authMode": "api-key",
35
+ "exportSubpath": "./sdk",
36
+ "clientClassName": "MementosClient"
37
+ },
38
+ {
39
+ "name": "mcp",
40
+ "kind": "mcp",
41
+ "status": "supported",
42
+ "mcpBin": "mementos-mcp",
43
+ "authMode": "local-only"
44
+ },
45
+ {
46
+ "name": "cli",
47
+ "kind": "cli",
48
+ "status": "supported",
49
+ "bin": "mementos",
50
+ "authMode": "local-only"
51
+ }
52
+ ],
10
53
  "storage": {
11
- "mode": "cloud",
54
+ "mode": "sqlite",
55
+ "engines": [
56
+ "sqlite",
57
+ "postgres"
58
+ ],
12
59
  "envPrefix": "HASNA_MEMENTOS_",
13
60
  "aliasEnvPrefix": "MEMENTOS_",
14
- "databaseUrlSecretRef": "hasna/oss/mementos/database-url"
61
+ "sqlitePath": "~/.hasna/mementos/mementos.db",
62
+ "pgTestGate": {
63
+ "envVar": "MEMENTOS_TEST_DATABASE_URL",
64
+ "command": "bun run test:pg"
65
+ }
66
+ },
67
+ "metadata": {
68
+ "release": {
69
+ "artifactScan": {
70
+ "script": "scan-artifact"
71
+ }
72
+ }
15
73
  }
16
74
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hasna/mementos",
3
- "version": "0.14.70",
3
+ "version": "0.14.72",
4
4
  "description": "Universal memory system for AI agents - CLI + MCP server + library API",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -38,9 +38,14 @@
38
38
  "clean": "rm -rf dist",
39
39
  "build": "bun run clean && bun build src/cli/index.tsx --outdir dist/cli --target bun --external ink --external react --external chalk --external @modelcontextprotocol/sdk --external @hasna/contracts --external @hasna/contracts/schemas --external @hasna/contracts/auth --external pg && bun build src/mcp/index.ts --outdir dist/mcp --target bun --external @modelcontextprotocol/sdk --external @hasna/contracts --external @hasna/contracts/schemas --external @hasna/contracts/auth --external pg && bun build src/server/index.ts --outdir dist/server --target bun --external @hasna/contracts --external @hasna/contracts/schemas --external @hasna/contracts/auth --external pg && bun build src/index.ts src/storage.ts src/pg-sync-worker.ts --outdir dist --target bun --external @hasna/contracts --external @hasna/contracts/schemas --external @hasna/contracts/auth --external pg && bun build src/sdk/index.ts --outdir dist/sdk --target bun && tsc --emitDeclarationOnly --outDir dist",
40
40
  "prepare": "bun run build",
41
- "prepublishOnly": "bun run typecheck && bun run test",
41
+ "prepack": "bun run build && bun run scan-artifact",
42
+ "prepublishOnly": "bun run typecheck && bun run test && bun run contracts:conformance && contracts no-cloud-scan .",
43
+ "scan-artifact": "bun scripts/scan-artifact.ts",
44
+ "contract:check": "bun run build && contracts repo-conformance .",
45
+ "contracts:conformance": "contracts conformance fixtures",
42
46
  "typecheck": "tsc --noEmit",
43
47
  "test": "bun test --isolate --timeout=10000",
48
+ "test:pg": "bun scripts/pg-test-gate.ts",
44
49
  "dev:cli": "bun run src/cli/index.tsx",
45
50
  "dev:mcp": "bun run src/mcp/index.ts",
46
51
  "dev:serve": "bun run src/server/index.ts",
@@ -79,7 +84,7 @@
79
84
  "@ai-sdk/anthropic": "^3.0.82",
80
85
  "@ai-sdk/openai": "^3.0.69",
81
86
  "@ai-sdk/openai-compatible": "^2.0.48",
82
- "@hasna/contracts": "0.4.2",
87
+ "@hasna/contracts": "0.8.5",
83
88
  "@hasna/events": "^0.1.6",
84
89
  "@modelcontextprotocol/sdk": "^1.12.1",
85
90
  "ai": "^6.0.199",