@hasna/mementos 0.14.71 → 0.14.73

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
 
@@ -1 +1 @@
1
- {"version":3,"file":"memory-cmd-crud.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/memory-cmd-crud.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA+BzC,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAka3D"}
1
+ {"version":3,"file":"memory-cmd-crud.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/memory-cmd-crud.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA+BzC,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAwf3D"}
@@ -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) {
@@ -59822,7 +59827,13 @@ function registerCrudCommands(program2) {
59822
59827
  let resolvedAgentId;
59823
59828
  if (globalOpts.agent) {
59824
59829
  const ag = getAgent(globalOpts.agent);
59825
- resolvedAgentId = ag?.id;
59830
+ if (!ag) {
59831
+ throw new Error(`Unknown agent "${globalOpts.agent}": no registered agent matches that name or id.
59832
+ ` + `Refusing to save. Dropping the flag would write this memory to the unowned ` + `(no-agent) row for key "${key}", overwriting whatever is there under an owner ` + `you did not name.
59833
+ ` + `Register the agent first: mementos register-agent ${globalOpts.agent}
59834
+ ` + `Or omit --agent to write to the unowned row deliberately.`);
59835
+ }
59836
+ resolvedAgentId = ag.id;
59826
59837
  }
59827
59838
  const input = {
59828
59839
  key,
@@ -59838,9 +59849,18 @@ function registerCrudCommands(program2) {
59838
59849
  session_id: globalOpts.session
59839
59850
  };
59840
59851
  if (globalOpts.project) {
59841
- const project = getProject(resolve3(globalOpts.project));
59842
- if (project)
59843
- input.project_id = project.id;
59852
+ const projectPath = resolve3(globalOpts.project);
59853
+ const project = getProject(projectPath);
59854
+ if (!project) {
59855
+ throw new Error(`Unknown project "${projectPath}": no registered project matches that path.
59856
+ ` + `Refusing to save. Dropping the flag would write this memory to the no-project ` + `row for key "${key}", overwriting whatever is there in a scope you did not name.
59857
+ ` + `Register it first: mementos projects --add --path ${projectPath} --name <name>
59858
+ ` + `Or omit --project to write outside any project deliberately.`);
59859
+ }
59860
+ input.project_id = project.id;
59861
+ }
59862
+ if (typeof input.session_id === "string" && MEMORY_SCOPES.includes(input.session_id)) {
59863
+ console.error(chalk2.yellow(`Warning: --session "${input.session_id}" looks like a scope, not a session id. ` + `Note that -s is the global --session, not --scope; this save is writing ` + `session_id="${input.session_id}" and leaving scope at "${input.scope ?? "private"}". ` + `If you meant the scope, pass --scope ${input.session_id} (long form only).`));
59844
59864
  }
59845
59865
  const bucket = (m) => [m.scope ?? "private", m.agent_id ?? "", m.project_id ?? "", m.session_id ?? ""].join("\x1F");
59846
59866
  const targetBucket = bucket({
@@ -59859,9 +59879,9 @@ function registerCrudCommands(program2) {
59859
59879
  if (!match && sameKey.length > 0) {
59860
59880
  const rows = sameKey.map((m) => ` ${m.id.slice(0, 8)} scope=${m.scope} project=${m.project_id ?? "none"} session=${m.session_id ?? "none"} agent=${m.agent_id ?? "none"}`).join(`
59861
59881
  `);
59862
- throw new Error(`Refusing to fork key "${key}": ${sameKey.length} active memor${sameKey.length === 1 ? "y" : "ies"} ` + `already ${sameKey.length === 1 ? "uses" : "use"} it, ` + `but none matches the scope/project/session this save targets ` + `(scope=${input.scope ?? "private"}, project=${input.project_id ?? "none"}, session=${input.session_id ?? "none"}).
59882
+ throw new Error(`Refusing to fork key "${key}": ${sameKey.length} active memor${sameKey.length === 1 ? "y" : "ies"} ` + `already ${sameKey.length === 1 ? "uses" : "use"} it, ` + `but none matches the scope/project/session/agent this save targets ` + `(scope=${input.scope ?? "private"}, project=${input.project_id ?? "none"}, session=${input.session_id ?? "none"}, agent=${input.agent_id ?? "none"}).
59863
59883
  ` + `${rows}
59864
- ` + `Saving would create a second active row under the same key. Either target the existing row ` + `(match its scope/project/session flags, or use \`mementos update <id>\`), or pass \`--dedupe create\` ` + `to fork deliberately.`);
59884
+ ` + `Saving would create a second active row under the same key. Either target the existing row ` + `(match its scope/project/session/agent flags, or use \`mementos update <id>\`), or pass \`--dedupe create\` ` + `to fork deliberately.`);
59865
59885
  }
59866
59886
  }
59867
59887
  const memory = forkRequested ? createMemory(input, dedupe) : createMemory(input);
@@ -60574,9 +60594,15 @@ init_search();
60574
60594
  init_helpers();
60575
60595
  import chalk11 from "chalk";
60576
60596
  import { resolve as resolve6 } from "path";
60597
+
60598
+ // src/cli/commands/memory-cmd-recall-exit.ts
60599
+ var RECALL_EXIT_NOT_FOUND = 1;
60600
+ var RECALL_EXIT_FUZZY = 2;
60601
+
60602
+ // src/cli/commands/memory-cmd-recall.ts
60577
60603
  function registerRecallCommand(program2) {
60578
60604
  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) => {
60605
+ 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
60606
  try {
60581
60607
  const globalOpts = program2.opts();
60582
60608
  const agentId = opts.agent || globalOpts.agent;
@@ -60588,7 +60614,7 @@ function registerRecallCommand(program2) {
60588
60614
  projectId = project.id;
60589
60615
  }
60590
60616
  const memory = getMemoryByKey(key, opts.scope, agentId, projectId);
60591
- if (memory) {
60617
+ if (memory && memory.key === key) {
60592
60618
  touchMemory(memory.id);
60593
60619
  if (globalOpts.json) {
60594
60620
  outputJson(memory);
@@ -60597,29 +60623,39 @@ function registerRecallCommand(program2) {
60597
60623
  }
60598
60624
  return;
60599
60625
  }
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));
60626
+ if (opts.fuzzy) {
60627
+ const results = searchMemories(key, {
60628
+ scope: opts.scope,
60629
+ agent_id: agentId,
60630
+ project_id: projectId,
60631
+ limit: 1
60632
+ });
60633
+ if (results.length > 0) {
60634
+ const best = results[0];
60635
+ touchMemory(best.memory.id);
60636
+ if (globalOpts.json) {
60637
+ outputJson({
60638
+ fuzzy_match: true,
60639
+ requested_key: key,
60640
+ returned_key: best.memory.key,
60641
+ score: best.score,
60642
+ match_type: best.match_type,
60643
+ memory: best.memory
60644
+ });
60645
+ } else {
60646
+ 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.`));
60647
+ console.log(formatMemoryDetail(best.memory));
60648
+ }
60649
+ process.exit(RECALL_EXIT_FUZZY);
60614
60650
  }
60615
- return;
60616
60651
  }
60652
+ 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
60653
  if (globalOpts.json) {
60618
- outputJson({ error: `No memory found for key: ${key}` });
60654
+ outputJson({ error: message, requested_key: key });
60619
60655
  } else {
60620
- console.error(chalk11.yellow(`No memory found for key: ${key}`));
60656
+ console.error(chalk11.yellow(message));
60621
60657
  }
60622
- process.exit(1);
60658
+ process.exit(RECALL_EXIT_NOT_FOUND);
60623
60659
  } catch (e) {
60624
60660
  handleError(e);
60625
60661
  }
@@ -61489,6 +61525,21 @@ function readGlobalConfig() {
61489
61525
  return {};
61490
61526
  }
61491
61527
  }
61528
+ function readGlobalConfigForWrite() {
61529
+ const p = globalConfigPath();
61530
+ if (!existsSync4(p))
61531
+ return {};
61532
+ try {
61533
+ const data = JSON.parse(readFileSync4(p, "utf-8"));
61534
+ if (data === null || typeof data !== "object" || Array.isArray(data)) {
61535
+ throw new Error("expected a JSON object");
61536
+ }
61537
+ return data;
61538
+ } catch (error) {
61539
+ const detail = error instanceof Error ? error.message : String(error);
61540
+ throw new Error(`Cannot update global config at ${p}: ${detail}`);
61541
+ }
61542
+ }
61492
61543
  function writeGlobalConfig(data) {
61493
61544
  const p = globalConfigPath();
61494
61545
  ensureDir2(dirname3(p));
@@ -61502,7 +61553,7 @@ function getActiveProfile() {
61502
61553
  return cfg["active_profile"] || null;
61503
61554
  }
61504
61555
  function setActiveProfile(name) {
61505
- const cfg = readGlobalConfig();
61556
+ const cfg = readGlobalConfigForWrite();
61506
61557
  if (name === null) {
61507
61558
  delete cfg["active_profile"];
61508
61559
  } 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"}
@@ -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.71",
3
+ "version": "0.14.73",
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",