indelible-mcp 4.9.0 → 4.9.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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/src/index.js +123 -99
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "indelible-mcp",
3
- "version": "4.9.0",
3
+ "version": "4.9.2",
4
4
  "description": "Blockchain-backed memory and code storage for Claude Code. Save AI conversations and source code permanently on BSV.",
5
5
  "type": "module",
6
6
  "main": "src/index.js",
package/src/index.js CHANGED
@@ -14,7 +14,7 @@ var __export = (target, all) => {
14
14
  __defProp(target, name, { get: all[name], enumerable: true });
15
15
  };
16
16
 
17
- // mcp-server/lib/crypto.js
17
+ // lib/crypto.js
18
18
  import { createCipheriv, createDecipheriv, createHash, randomBytes, pbkdf2Sync } from "crypto";
19
19
  function deriveKey(wif) {
20
20
  return createHash("sha256").update(wif).digest();
@@ -69,11 +69,11 @@ function decryptWif(encryptedObj, pin) {
69
69
  return decrypted;
70
70
  }
71
71
  var init_crypto = __esm({
72
- "mcp-server/lib/crypto.js"() {
72
+ "lib/crypto.js"() {
73
73
  }
74
74
  });
75
75
 
76
- // mcp-server/lib/config.customer.js
76
+ // lib/config.customer.js
77
77
  import { readFileSync, writeFileSync, existsSync, mkdirSync } from "node:fs";
78
78
  import { homedir } from "node:os";
79
79
  import { join } from "node:path";
@@ -124,7 +124,7 @@ async function getWif() {
124
124
  }
125
125
  var CONFIG_DIR, CONFIG_FILE, _cachedWif;
126
126
  var init_config_customer = __esm({
127
- "mcp-server/lib/config.customer.js"() {
127
+ "lib/config.customer.js"() {
128
128
  init_crypto();
129
129
  CONFIG_DIR = join(homedir(), ".indelible");
130
130
  CONFIG_FILE = join(CONFIG_DIR, "config.json");
@@ -132,7 +132,7 @@ var init_config_customer = __esm({
132
132
  }
133
133
  });
134
134
 
135
- // mcp-server/lib/spv.js
135
+ // lib/spv.js
136
136
  import { Transaction, P2PKH, PrivateKey, SatoshisPerKilobyte, LockingScript, OP } from "@bsv/sdk";
137
137
  import { Transaction as Transaction2, P2PKH as P2PKH2, PrivateKey as PrivateKey2, SatoshisPerKilobyte as SatoshisPerKilobyte2, LockingScript as LockingScript2, OP as OP2 } from "@bsv/sdk";
138
138
  async function getBridges() {
@@ -545,7 +545,7 @@ async function buildPaymentTx(wif, utxos, payToAddress, satoshis) {
545
545
  }
546
546
  var SEED_BRIDGES, OLD_BRIDGE_IPS, bridgeHealth, HEALTH_CHECK_INTERVAL, MAX_FAILURES, migrationDone, _stickyBridge, STICKY_WINDOW_MS;
547
547
  var init_spv = __esm({
548
- "mcp-server/lib/spv.js"() {
548
+ "lib/spv.js"() {
549
549
  init_config_customer();
550
550
  SEED_BRIDGES = [
551
551
  { url: "http://144.202.48.217:9333", name: "bridge-alpha" },
@@ -573,7 +573,7 @@ var init_spv = __esm({
573
573
  }
574
574
  });
575
575
 
576
- // mcp-server/lib/utxo-cache.js
576
+ // lib/utxo-cache.js
577
577
  import { readFileSync as readFileSync2, writeFileSync as writeFileSync2, existsSync as existsSync2, mkdirSync as mkdirSync2 } from "fs";
578
578
  import { join as join2 } from "path";
579
579
  import { homedir as homedir2 } from "os";
@@ -624,13 +624,13 @@ function invalidate(address) {
624
624
  }
625
625
  var DIR, CACHE_PATH;
626
626
  var init_utxo_cache = __esm({
627
- "mcp-server/lib/utxo-cache.js"() {
627
+ "lib/utxo-cache.js"() {
628
628
  DIR = join2(homedir2(), ".indelible");
629
629
  CACHE_PATH = process.env.INDELIBLE_UTXO_CACHE || join2(DIR, "utxo-cache.json");
630
630
  }
631
631
  });
632
632
 
633
- // mcp-server/lib/summary.js
633
+ // lib/summary.js
634
634
  import { createCipheriv as createCipheriv2, createDecipheriv as createDecipheriv2, randomBytes as randomBytes2 } from "crypto";
635
635
  function encryptSummary(plaintext, wif, txId) {
636
636
  if (!txId || typeof txId !== "string" || !TXID_REGEX.test(txId)) {
@@ -679,7 +679,7 @@ function decryptSummaryOrLock(summary_enc, wif, expectedTxId) {
679
679
  }
680
680
  var TXID_REGEX, LOCK_PLACEHOLDER;
681
681
  var init_summary = __esm({
682
- "mcp-server/lib/summary.js"() {
682
+ "lib/summary.js"() {
683
683
  init_crypto();
684
684
  TXID_REGEX = /^[0-9a-f]{64}$/i;
685
685
  LOCK_PLACEHOLDER = {
@@ -692,7 +692,7 @@ var init_summary = __esm({
692
692
  }
693
693
  });
694
694
 
695
- // mcp-server/lib/wallet-brc100.js
695
+ // lib/wallet-brc100.js
696
696
  import { PrivateKey as PrivateKey3, CompletedProtoWallet, AuthFetch } from "@bsv/sdk";
697
697
  function createAuthClient(wif) {
698
698
  if (!wif) throw new Error("createAuthClient: wif required");
@@ -712,13 +712,13 @@ function createAuthClient(wif) {
712
712
  }
713
713
  var cached, cachedWif;
714
714
  var init_wallet_brc100 = __esm({
715
- "mcp-server/lib/wallet-brc100.js"() {
715
+ "lib/wallet-brc100.js"() {
716
716
  cached = null;
717
717
  cachedWif = null;
718
718
  }
719
719
  });
720
720
 
721
- // mcp-server/lib/api-client.js
721
+ // lib/api-client.js
722
722
  var api_client_exports = {};
723
723
  __export(api_client_exports, {
724
724
  buildReceipt: () => buildReceipt,
@@ -1100,7 +1100,7 @@ async function checkConnection() {
1100
1100
  }
1101
1101
  var DEFAULT_API_URL, TIER2_CACHE_TTL_MS, TIER2_BACKOFF_TTL_MS, TIER2_BACKOFF_THRESHOLD, tier2Cache, tier2TransientFailures;
1102
1102
  var init_api_client = __esm({
1103
- "mcp-server/lib/api-client.js"() {
1103
+ "lib/api-client.js"() {
1104
1104
  init_config_customer();
1105
1105
  init_spv();
1106
1106
  init_utxo_cache();
@@ -1115,7 +1115,7 @@ var init_api_client = __esm({
1115
1115
  }
1116
1116
  });
1117
1117
 
1118
- // mcp-server/lib/share.js
1118
+ // lib/share.js
1119
1119
  import { createCipheriv as createCipheriv3, createDecipheriv as createDecipheriv3, createHash as createHash2, randomBytes as randomBytes3, hkdfSync } from "node:crypto";
1120
1120
  import { PrivateKey as PrivateKey5, PublicKey, Signature, ProtoWallet } from "@bsv/sdk";
1121
1121
  function isValidP2PKH(addr) {
@@ -1415,7 +1415,7 @@ async function unwrapRecoveryV3(wrapHex, wallet, keyID, ownerPubkeyHex) {
1415
1415
  }
1416
1416
  var HKDF_INFO, TXID_REGEX2, P2PKH_REGEX, CANONICAL_FIELDS, SELF_WRAP_TXID, ENCRYPT_PROTOCOL_ID_V2;
1417
1417
  var init_share = __esm({
1418
- "mcp-server/lib/share.js"() {
1418
+ "lib/share.js"() {
1419
1419
  HKDF_INFO = "indelible-share-v1";
1420
1420
  TXID_REGEX2 = /^[0-9a-f]{64}$/i;
1421
1421
  P2PKH_REGEX = /^1[1-9A-HJ-NP-Za-km-z]{25,34}$/;
@@ -1433,7 +1433,7 @@ var init_share = __esm({
1433
1433
  }
1434
1434
  });
1435
1435
 
1436
- // mcp-server/lib/save-log.js
1436
+ // lib/save-log.js
1437
1437
  import { appendFileSync, readFileSync as readFileSync3, writeFileSync as writeFileSync3, existsSync as existsSync3, mkdirSync as mkdirSync3 } from "fs";
1438
1438
  import { join as join3 } from "path";
1439
1439
  import { homedir as homedir3 } from "os";
@@ -1470,13 +1470,13 @@ function appendReceipt(receipt, meta = {}) {
1470
1470
  }
1471
1471
  var DIR2, LOG;
1472
1472
  var init_save_log = __esm({
1473
- "mcp-server/lib/save-log.js"() {
1473
+ "lib/save-log.js"() {
1474
1474
  DIR2 = join3(homedir3(), ".indelible");
1475
1475
  LOG = join3(DIR2, "save-log.jsonl");
1476
1476
  }
1477
1477
  });
1478
1478
 
1479
- // mcp-server/lib/advisory/index.customer.js
1479
+ // lib/advisory/index.customer.js
1480
1480
  function extractAnchors() {
1481
1481
  return null;
1482
1482
  }
@@ -1521,11 +1521,11 @@ async function pollInfraEmotions() {
1521
1521
  return null;
1522
1522
  }
1523
1523
  var init_index_customer = __esm({
1524
- "mcp-server/lib/advisory/index.customer.js"() {
1524
+ "lib/advisory/index.customer.js"() {
1525
1525
  }
1526
1526
  });
1527
1527
 
1528
- // mcp-server/build/wall-stub.js
1528
+ // build/wall-stub.js
1529
1529
  var wall_stub_exports = {};
1530
1530
  __export(wall_stub_exports, {
1531
1531
  adversarialReview: () => adversarialReview,
@@ -1546,7 +1546,7 @@ __export(wall_stub_exports, {
1546
1546
  });
1547
1547
  var asyncEmpty, calibrate, adversarialReview, bookkeeperAudit, quartermasterBrief, treasuryStatus, checkAsRyan, auditChainGoalState2, buildAndWriteFederationChat, readRecentEvents, dispatchCloneCheck, cloneCheck2, logAgentVerdict2, escalateVerdict, announce, wall_stub_default;
1548
1548
  var init_wall_stub = __esm({
1549
- "mcp-server/build/wall-stub.js"() {
1549
+ "build/wall-stub.js"() {
1550
1550
  asyncEmpty = async () => ({});
1551
1551
  calibrate = asyncEmpty;
1552
1552
  adversarialReview = asyncEmpty;
@@ -1569,7 +1569,7 @@ var init_wall_stub = __esm({
1569
1569
  }
1570
1570
  });
1571
1571
 
1572
- // mcp-server/tools/save_style.js
1572
+ // tools/save_style.js
1573
1573
  import { readFile as readFile3 } from "fs/promises";
1574
1574
  import { existsSync as existsSync6 } from "fs";
1575
1575
  function stripCoreRules(rulesText) {
@@ -1665,7 +1665,7 @@ async function saveStyleFromFile(filePath, styleName, description) {
1665
1665
  }
1666
1666
  var CORE_RULES_MARKER, CORE_RULES;
1667
1667
  var init_save_style = __esm({
1668
- "mcp-server/tools/save_style.js"() {
1668
+ "tools/save_style.js"() {
1669
1669
  init_config_customer();
1670
1670
  init_crypto();
1671
1671
  init_spv();
@@ -1729,7 +1729,7 @@ Handbooks live in the project root \u2014 check MEMORY.md for paths.
1729
1729
  }
1730
1730
  });
1731
1731
 
1732
- // mcp-server/tools/load_style.js
1732
+ // tools/load_style.js
1733
1733
  import { Transaction as Transaction4 } from "@bsv/sdk";
1734
1734
  import { writeFileSync as writeFileSync4 } from "fs";
1735
1735
  import { join as join6 } from "path";
@@ -1836,7 +1836,7 @@ async function loadStyle(txId) {
1836
1836
  }
1837
1837
  var SYNCABLE_FIELDS, API_TIMEOUT_MS;
1838
1838
  var init_load_style = __esm({
1839
- "mcp-server/tools/load_style.js"() {
1839
+ "tools/load_style.js"() {
1840
1840
  init_config_customer();
1841
1841
  init_crypto();
1842
1842
  init_spv();
@@ -1846,7 +1846,7 @@ var init_load_style = __esm({
1846
1846
  }
1847
1847
  });
1848
1848
 
1849
- // scripts/lib/claim-status.mjs
1849
+ // ../scripts/lib/claim-status.mjs
1850
1850
  import { hostname } from "os";
1851
1851
  function pidAlive(pid) {
1852
1852
  try {
@@ -1885,12 +1885,12 @@ function claimStatus(g) {
1885
1885
  }
1886
1886
  var CLAIM_STALE_MS;
1887
1887
  var init_claim_status = __esm({
1888
- "scripts/lib/claim-status.mjs"() {
1888
+ "../scripts/lib/claim-status.mjs"() {
1889
1889
  CLAIM_STALE_MS = 30 * 60 * 1e3;
1890
1890
  }
1891
1891
  });
1892
1892
 
1893
- // mcp-server/lib/tenant-paths.js
1893
+ // lib/tenant-paths.js
1894
1894
  import { homedir as homedir7 } from "os";
1895
1895
  import { join as join7 } from "path";
1896
1896
  function base(tenantId) {
@@ -1907,14 +1907,14 @@ function base(tenantId) {
1907
1907
  }
1908
1908
  var goalsDir, goalsPath, innerStatePath;
1909
1909
  var init_tenant_paths = __esm({
1910
- "mcp-server/lib/tenant-paths.js"() {
1910
+ "lib/tenant-paths.js"() {
1911
1911
  goalsDir = (t) => base(t);
1912
1912
  goalsPath = (t) => join7(base(t), "goals.json");
1913
1913
  innerStatePath = (t) => join7(base(t), "inner-state.json");
1914
1914
  }
1915
1915
  });
1916
1916
 
1917
- // mcp-server/tools/goals.js
1917
+ // tools/goals.js
1918
1918
  import { readFileSync as readFileSync5, writeFileSync as writeFileSync5, existsSync as existsSync7, mkdirSync as mkdirSync4, unlinkSync, openSync, closeSync, renameSync } from "fs";
1919
1919
  import { join as join8 } from "path";
1920
1920
  import { homedir as homedir8, hostname as hostname2 } from "os";
@@ -2352,7 +2352,7 @@ async function _manageGoal({ action, goal_id, title, intent, priority, owner, ne
2352
2352
  }
2353
2353
  var GOALS_DIR, GOALS_PATH, CURRENT_FOCUS_PATH, GOALS_LOCK, LOCK_STALE_MS, LOCK_POLL_MS, LOCK_MAX_TRIES, LEAKED_TAG_RE, LEAK_BOUNDARY_RE;
2354
2354
  var init_goals = __esm({
2355
- "mcp-server/tools/goals.js"() {
2355
+ "tools/goals.js"() {
2356
2356
  init_index_customer();
2357
2357
  init_claim_status();
2358
2358
  init_tenant_paths();
@@ -2368,7 +2368,7 @@ var init_goals = __esm({
2368
2368
  }
2369
2369
  });
2370
2370
 
2371
- // mcp-server/tools/inner_state.js
2371
+ // tools/inner_state.js
2372
2372
  import { readFileSync as readFileSync6, writeFileSync as writeFileSync6, existsSync as existsSync8, mkdirSync as mkdirSync5 } from "fs";
2373
2373
  function ensureDir3() {
2374
2374
  const dir = base("");
@@ -2671,7 +2671,7 @@ async function updateInnerState({ observed, source, preoccupations, open_loops,
2671
2671
  }
2672
2672
  var STATE_PATH, BASELINE, MAX_DELTA, SMOOTHING, BASELINE_PULL;
2673
2673
  var init_inner_state = __esm({
2674
- "mcp-server/tools/inner_state.js"() {
2674
+ "tools/inner_state.js"() {
2675
2675
  init_index_customer();
2676
2676
  init_tenant_paths();
2677
2677
  STATE_PATH = innerStatePath("");
@@ -2689,7 +2689,7 @@ var init_inner_state = __esm({
2689
2689
  }
2690
2690
  });
2691
2691
 
2692
- // mcp-server/tools/load_context.js
2692
+ // tools/load_context.js
2693
2693
  import { gunzipSync } from "zlib";
2694
2694
  import { existsSync as existsSync9, createReadStream as createReadStream2 } from "fs";
2695
2695
  import { createInterface as createInterface2 } from "readline";
@@ -3255,7 +3255,7 @@ async function loadContext(numSessions = 5, pagination = null, opts = {}) {
3255
3255
  }
3256
3256
  var RECENT_MESSAGES_FULL, OLDER_MESSAGES_SUMMARIZED;
3257
3257
  var init_load_context = __esm({
3258
- "mcp-server/tools/load_context.js"() {
3258
+ "tools/load_context.js"() {
3259
3259
  init_config_customer();
3260
3260
  init_crypto();
3261
3261
  init_summary();
@@ -3271,7 +3271,7 @@ var init_load_context = __esm({
3271
3271
  }
3272
3272
  });
3273
3273
 
3274
- // mcp-server/lib/file-lock.js
3274
+ // lib/file-lock.js
3275
3275
  import { openSync as openSync2, writeFileSync as writeFileSync7, closeSync as closeSync2, readFileSync as readFileSync8, unlinkSync as unlinkSync2, renameSync as renameSync2 } from "fs";
3276
3276
  function pidAlive2(pid) {
3277
3277
  if (!Number.isInteger(pid)) return false;
@@ -3318,11 +3318,11 @@ async function withFileLock(lockPath, fn, { staleMs = 5e3, pollMs = 50, maxTries
3318
3318
  }
3319
3319
  }
3320
3320
  var init_file_lock = __esm({
3321
- "mcp-server/lib/file-lock.js"() {
3321
+ "lib/file-lock.js"() {
3322
3322
  }
3323
3323
  });
3324
3324
 
3325
- // mcp-server/lib/semantic/manifest.js
3325
+ // lib/semantic/manifest.js
3326
3326
  var manifest_exports = {};
3327
3327
  __export(manifest_exports, {
3328
3328
  DIM: () => DIM,
@@ -3354,7 +3354,7 @@ function packPresent(profile = PROFILE) {
3354
3354
  }
3355
3355
  var MODEL_VER, DIM, QUERY_PREFIX, MAX_TOKENS, PROFILE, PACK_FILES;
3356
3356
  var init_manifest = __esm({
3357
- "mcp-server/lib/semantic/manifest.js"() {
3357
+ "lib/semantic/manifest.js"() {
3358
3358
  MODEL_VER = "bge-small-en-v1.5-int8@6c9c6101";
3359
3359
  DIM = 384;
3360
3360
  QUERY_PREFIX = "Represent this sentence for searching relevant passages: ";
@@ -3399,7 +3399,7 @@ var init_manifest = __esm({
3399
3399
  }
3400
3400
  });
3401
3401
 
3402
- // mcp-server/lib/semantic/tokenizer.js
3402
+ // lib/semantic/tokenizer.js
3403
3403
  import { readFileSync as readFileSync9 } from "fs";
3404
3404
  import { join as join13 } from "path";
3405
3405
  function isPunct(cp, ch) {
@@ -3420,7 +3420,7 @@ function getTokenizer(profileDir = packDir()) {
3420
3420
  }
3421
3421
  var WordPieceTokenizer, _singleton;
3422
3422
  var init_tokenizer = __esm({
3423
- "mcp-server/lib/semantic/tokenizer.js"() {
3423
+ "lib/semantic/tokenizer.js"() {
3424
3424
  init_manifest();
3425
3425
  WordPieceTokenizer = class {
3426
3426
  /** @param {string} tokenizerJsonPath absolute path to the pack's tokenizer.json */
@@ -3522,7 +3522,7 @@ var init_tokenizer = __esm({
3522
3522
  }
3523
3523
  });
3524
3524
 
3525
- // mcp-server/lib/semantic/embedder.js
3525
+ // lib/semantic/embedder.js
3526
3526
  var embedder_exports = {};
3527
3527
  __export(embedder_exports, {
3528
3528
  DIM: () => DIM,
@@ -3610,7 +3610,7 @@ async function embedPassages(texts) {
3610
3610
  }
3611
3611
  var _loading, _engine;
3612
3612
  var init_embedder = __esm({
3613
- "mcp-server/lib/semantic/embedder.js"() {
3613
+ "lib/semantic/embedder.js"() {
3614
3614
  init_manifest();
3615
3615
  init_tokenizer();
3616
3616
  _loading = null;
@@ -3618,7 +3618,7 @@ var init_embedder = __esm({
3618
3618
  }
3619
3619
  });
3620
3620
 
3621
- // mcp-server/lib/semantic/vec-store.js
3621
+ // lib/semantic/vec-store.js
3622
3622
  var vec_store_exports = {};
3623
3623
  __export(vec_store_exports, {
3624
3624
  CHUNK_CHARS: () => CHUNK_CHARS,
@@ -3744,19 +3744,19 @@ async function rebuildVectorSidecar(address, { maxEmbed = 300, onProgress = null
3744
3744
  const { embedPassages: embedPassages2 } = await Promise.resolve().then(() => (init_embedder(), embedder_exports));
3745
3745
  const index = readIndex2(address);
3746
3746
  const covered = coveredTxIds(address);
3747
- const missing = [...index.values()].filter((r) => r?.txId && !covered.has(r.txId));
3747
+ const work = [];
3748
+ for (const r of index.values()) {
3749
+ if (!r?.txId || covered.has(r.txId)) continue;
3750
+ const chunks = chunkRecord(r);
3751
+ if (chunks.length) work.push({ rec: r, chunks });
3752
+ }
3748
3753
  let embedded = 0;
3749
3754
  const batchRows = [];
3750
- for (const rec of missing.slice(0, maxEmbed)) {
3751
- const chunks = chunkRecord(rec);
3752
- if (!chunks.length) {
3753
- covered.add(rec.txId);
3754
- continue;
3755
- }
3755
+ for (const { rec, chunks } of work.slice(0, maxEmbed)) {
3756
3756
  const vecs = await embedPassages2(chunks.map((c) => c.text));
3757
3757
  for (let i = 0; i < chunks.length; i++) batchRows.push({ txId: rec.txId, chunk: chunks[i].chunk, vec: vecs[i] });
3758
3758
  embedded++;
3759
- if (onProgress && embedded % 25 === 0) onProgress({ embedded, total: Math.min(missing.length, maxEmbed) });
3759
+ if (onProgress && embedded % 25 === 0) onProgress({ embedded, total: Math.min(work.length, maxEmbed) });
3760
3760
  if (batchRows.length >= 200) {
3761
3761
  await appendEmbeds(address, batchRows.splice(0));
3762
3762
  }
@@ -3764,13 +3764,14 @@ async function rebuildVectorSidecar(address, { maxEmbed = 300, onProgress = null
3764
3764
  await appendEmbeds(address, batchRows);
3765
3765
  return {
3766
3766
  embedded,
3767
- remaining: Math.max(0, missing.length - embedded),
3767
+ remaining: Math.max(0, work.length - embedded),
3768
+ // embeddable-only → reaches 0, loop terminates
3768
3769
  coverage: { vecs: coveredTxIds(address).size, indexed: index.size }
3769
3770
  };
3770
3771
  }
3771
3772
  var INDEX_DIR, embedsPath, embedsLock, CHUNK_CHARS, MAX_CHUNKS, _cache;
3772
3773
  var init_vec_store = __esm({
3773
- "mcp-server/lib/semantic/vec-store.js"() {
3774
+ "lib/semantic/vec-store.js"() {
3774
3775
  init_file_lock();
3775
3776
  init_manifest();
3776
3777
  INDEX_DIR = join15(homedir12(), ".indelible", "recall-index");
@@ -3782,7 +3783,7 @@ var init_vec_store = __esm({
3782
3783
  }
3783
3784
  });
3784
3785
 
3785
- // mcp-server/lib/recall-index.js
3786
+ // lib/recall-index.js
3786
3787
  var recall_index_exports = {};
3787
3788
  __export(recall_index_exports, {
3788
3789
  buildIndexWindow: () => buildIndexWindow,
@@ -3824,7 +3825,8 @@ function deriveTitleSearch(session) {
3824
3825
  };
3825
3826
  const first = msgs.find(isUser) || msgs[0];
3826
3827
  const summary = (session?.summary || "").trim();
3827
- const title = summary || (first ? contentText(first).replace(/\s+/g, " ").trim().slice(0, 90) : "");
3828
+ const firstText = first ? contentText(first).replace(/\s+/g, " ").trim().slice(0, 90) : "";
3829
+ const title = summary && !isGenericSummary(summary) ? summary : firstText || summary;
3828
3830
  const searchText = msgs.map((m) => `${m.role || m.type || ""}: ${contentText(m)}`).join(" \n ").toLowerCase().slice(0, 2e4);
3829
3831
  return { title, searchText, message_count: msgs.length };
3830
3832
  }
@@ -4006,7 +4008,15 @@ async function searchIndexSemantic(address, { fromDate = null, toDate = null, qu
4006
4008
  const qv = await embedQuery2(query);
4007
4009
  const cand = new Set(recs.map((r) => r.txId));
4008
4010
  const scores = semanticScores2(address, qv, cand);
4009
- if (scores.size) semRanked = [...scores.entries()].sort((a, b) => b[1] - a[1]).slice(0, K).map(([txId]) => txId);
4011
+ if (scores.size) {
4012
+ const recById = new Map(recs.map((r) => [r.txId, r]));
4013
+ const qWeight = (r) => {
4014
+ const len = (r?.searchText || "").length;
4015
+ if (len < MIN_SEMANTIC_CHARS) return 0;
4016
+ return Math.min(1, len / SUBSTANTIAL_CHARS);
4017
+ };
4018
+ semRanked = [...scores.entries()].map(([txId, s]) => [txId, s * qWeight(recById.get(txId))]).filter(([, s]) => s > 0).sort((a, b) => b[1] - a[1]).slice(0, K).map(([txId]) => txId);
4019
+ }
4010
4020
  semInfo.available = true;
4011
4021
  semInfo.model = MODEL_VER2;
4012
4022
  semInfo.coverage = { vecs: coveredTxIds2(address).size, indexed: readIndex(address).size };
@@ -4029,8 +4039,17 @@ async function searchIndexSemantic(address, { fromDate = null, toDate = null, qu
4029
4039
  ordered = [...score.entries()].sort((a, b) => b[1] - a[1]).map(([id]) => byId.get(id)).filter(Boolean);
4030
4040
  ranking_used = "blend";
4031
4041
  }
4042
+ const deduped = [];
4043
+ const seenSig = /* @__PURE__ */ new Set();
4044
+ for (const r of ordered) {
4045
+ const st = r?.searchText || "";
4046
+ const sig = st.length >= 80 ? st.slice(0, 240) : `id:${r.txId}`;
4047
+ if (seenSig.has(sig)) continue;
4048
+ seenSig.add(sig);
4049
+ deduped.push(r);
4050
+ }
4032
4051
  return {
4033
- results: ordered.slice(0, limit).map((r) => ({
4052
+ results: deduped.slice(0, limit).map((r) => ({
4034
4053
  txId: r.txId,
4035
4054
  date: r.date,
4036
4055
  title: r.title,
@@ -4053,9 +4072,9 @@ function indexStatus(address) {
4053
4072
  index_file: indexPath(address)
4054
4073
  };
4055
4074
  }
4056
- var ROOT, INDEX_DIR2, GAPS_DIR, indexPath, indexLock, gapsPath, gapsLock, withTimeout;
4075
+ var ROOT, INDEX_DIR2, GAPS_DIR, indexPath, indexLock, gapsPath, gapsLock, withTimeout, isGenericSummary, MIN_SEMANTIC_CHARS, SUBSTANTIAL_CHARS;
4057
4076
  var init_recall_index = __esm({
4058
- "mcp-server/lib/recall-index.js"() {
4077
+ "lib/recall-index.js"() {
4059
4078
  init_file_lock();
4060
4079
  init_spv();
4061
4080
  init_load_context();
@@ -4067,10 +4086,13 @@ var init_recall_index = __esm({
4067
4086
  gapsPath = (a) => join16(GAPS_DIR, `${a}.jsonl`);
4068
4087
  gapsLock = (a) => join16(GAPS_DIR, `${a}.lock`);
4069
4088
  withTimeout = (p, ms) => Promise.race([p, new Promise((_, rej) => setTimeout(() => rej(new Error("fetch timeout")), ms))]);
4089
+ isGenericSummary = (s) => /^(auto[-\s]?save|auto[-\s]?compaction|checkpoint|save[-_\s]?all|delta[-\s]?save)\b/i.test(s || "");
4090
+ MIN_SEMANTIC_CHARS = 140;
4091
+ SUBSTANTIAL_CHARS = 1200;
4070
4092
  }
4071
4093
  });
4072
4094
 
4073
- // mcp-server/lib/semantic/fetch-pack.js
4095
+ // lib/semantic/fetch-pack.js
4074
4096
  var fetch_pack_exports = {};
4075
4097
  __export(fetch_pack_exports, {
4076
4098
  fetchPack: () => fetchPack
@@ -4134,7 +4156,7 @@ async function fetchPack({ profile = PROFILE, timeoutMs = 3e5, onProgress = null
4134
4156
  }
4135
4157
  var PackError;
4136
4158
  var init_fetch_pack = __esm({
4137
- "mcp-server/lib/semantic/fetch-pack.js"() {
4159
+ "lib/semantic/fetch-pack.js"() {
4138
4160
  init_manifest();
4139
4161
  PackError = class extends Error {
4140
4162
  constructor(code, message) {
@@ -4145,7 +4167,7 @@ var init_fetch_pack = __esm({
4145
4167
  }
4146
4168
  });
4147
4169
 
4148
- // cli-sandbox/src/index.js
4170
+ // ../cli-sandbox/src/index.js
4149
4171
  init_config_customer();
4150
4172
  import { createInterface as createInterface3 } from "node:readline";
4151
4173
  import { execSync as execSync2 } from "node:child_process";
@@ -4154,7 +4176,7 @@ import { join as join19, dirname as dirname5, resolve as resolve2 } from "node:p
4154
4176
  import { fileURLToPath as fileURLToPath2 } from "node:url";
4155
4177
  import { readFileSync as readFileSync15, writeFileSync as writeFileSync8, existsSync as existsSync19, mkdirSync as mkdirSync9, readdirSync, statSync as statSync4 } from "node:fs";
4156
4178
 
4157
- // mcp-server/lib/guardrails-run.js
4179
+ // lib/guardrails-run.js
4158
4180
  function contextFromInput(input) {
4159
4181
  const tool = input?.tool_name;
4160
4182
  const ti = input?.tool_input || {};
@@ -4180,7 +4202,7 @@ function runRules(input, rules) {
4180
4202
  return null;
4181
4203
  }
4182
4204
 
4183
- // mcp-server/lib/guardrails.customer.js
4205
+ // lib/guardrails.customer.js
4184
4206
  var RULES = [
4185
4207
  {
4186
4208
  // Reading a private key or seed into the chat sends it to the model and into
@@ -4222,7 +4244,7 @@ function evaluate(input) {
4222
4244
  return runRules(input, RULES);
4223
4245
  }
4224
4246
 
4225
- // mcp-server/tools/setup_wallet.js
4247
+ // tools/setup_wallet.js
4226
4248
  init_config_customer();
4227
4249
  init_crypto();
4228
4250
  init_api_client();
@@ -4318,7 +4340,7 @@ async function setupWallet(apiUrl = DEFAULT_API_URL2, importWif, pin) {
4318
4340
  };
4319
4341
  }
4320
4342
 
4321
- // mcp-server/tools/save_session.js
4343
+ // tools/save_session.js
4322
4344
  init_config_customer();
4323
4345
  init_crypto();
4324
4346
  init_share();
@@ -4333,10 +4355,10 @@ import { dirname, join as join5 } from "path";
4333
4355
  import { homedir as homedir5 } from "os";
4334
4356
  import { PrivateKey as PrivateKey6 } from "@bsv/sdk";
4335
4357
 
4336
- // mcp-server/lib/witness.js
4358
+ // lib/witness.js
4337
4359
  init_index_customer();
4338
4360
 
4339
- // mcp-server/lib/redact.js
4361
+ // lib/redact.js
4340
4362
  import { createHash as createHash3 } from "node:crypto";
4341
4363
  var B58_ALPHABET = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
4342
4364
  function base58Decode(str) {
@@ -4467,7 +4489,7 @@ function redactSession(session) {
4467
4489
  return changed;
4468
4490
  }
4469
4491
 
4470
- // mcp-server/lib/witness.js
4492
+ // lib/witness.js
4471
4493
  var MAX_SESSION_BYTES = 9 * 1024 * 1024;
4472
4494
  var MAX_FILE_BYTES = 100 * 1024 * 1024;
4473
4495
  var WARN_FILE_BYTES = 10 * 1024 * 1024;
@@ -4750,10 +4772,10 @@ function isBypassed(opts = {}) {
4750
4772
  return false;
4751
4773
  }
4752
4774
 
4753
- // mcp-server/tools/save_session.js
4775
+ // tools/save_session.js
4754
4776
  init_index_customer();
4755
4777
 
4756
- // mcp-server/tools/save_file.js
4778
+ // tools/save_file.js
4757
4779
  init_config_customer();
4758
4780
  init_crypto();
4759
4781
  init_api_client();
@@ -5021,13 +5043,13 @@ ${formatSaveReceipt(receipt)}`
5021
5043
  }
5022
5044
  }
5023
5045
 
5024
- // mcp-server/lib/transcript-path.js
5046
+ // lib/transcript-path.js
5025
5047
  import { resolve } from "path";
5026
5048
  function canonicalTranscriptKey(p) {
5027
5049
  return p && typeof p === "string" ? resolve(p) : p;
5028
5050
  }
5029
5051
 
5030
- // mcp-server/tools/save_session.js
5052
+ // tools/save_session.js
5031
5053
  init_index_customer();
5032
5054
  init_index_customer();
5033
5055
  var PLANS_DIR = join5(homedir5(), ".claude", "plans");
@@ -6021,10 +6043,10 @@ ${formatSaveReceipt(result.receipt)}`
6021
6043
  }
6022
6044
  }
6023
6045
 
6024
- // cli-sandbox/src/index.js
6046
+ // ../cli-sandbox/src/index.js
6025
6047
  init_load_context();
6026
6048
 
6027
- // mcp-server/tools/save_project.js
6049
+ // tools/save_project.js
6028
6050
  init_config_customer();
6029
6051
  init_crypto();
6030
6052
  init_spv();
@@ -6193,7 +6215,7 @@ ${formatSaveReceipt(receipt)}`
6193
6215
  }
6194
6216
  }
6195
6217
 
6196
- // mcp-server/tools/load_file.js
6218
+ // tools/load_file.js
6197
6219
  init_config_customer();
6198
6220
  init_crypto();
6199
6221
  init_share();
@@ -6383,7 +6405,7 @@ async function loadFile(txId, options = {}) {
6383
6405
  };
6384
6406
  }
6385
6407
 
6386
- // mcp-server/tools/load_project.js
6408
+ // tools/load_project.js
6387
6409
  init_config_customer();
6388
6410
  init_crypto();
6389
6411
  init_share();
@@ -6562,11 +6584,11 @@ async function loadProject(txId, options = {}) {
6562
6584
  };
6563
6585
  }
6564
6586
 
6565
- // cli-sandbox/src/index.js
6587
+ // ../cli-sandbox/src/index.js
6566
6588
  init_save_style();
6567
6589
  init_load_style();
6568
6590
 
6569
- // mcp-server/tools/update_vault_index.js
6591
+ // tools/update_vault_index.js
6570
6592
  init_config_customer();
6571
6593
  init_crypto();
6572
6594
  init_spv();
@@ -6636,7 +6658,7 @@ ${formatSaveReceipt(receipt)}`
6636
6658
  }
6637
6659
  }
6638
6660
 
6639
- // mcp-server/tools/diary_connect.js
6661
+ // tools/diary_connect.js
6640
6662
  init_config_customer();
6641
6663
  init_api_client();
6642
6664
  async function diaryConnect({ apiKey, model, name }) {
@@ -6684,11 +6706,11 @@ async function diaryConnect({ apiKey, model, name }) {
6684
6706
  };
6685
6707
  }
6686
6708
 
6687
- // mcp-server/tools/diary_chat.js
6709
+ // tools/diary_chat.js
6688
6710
  init_config_customer();
6689
6711
  init_api_client();
6690
6712
 
6691
- // mcp-server/tools/diary_save.js
6713
+ // tools/diary_save.js
6692
6714
  init_config_customer();
6693
6715
  init_crypto();
6694
6716
  init_api_client();
@@ -6790,7 +6812,7 @@ async function diarySave({ messages, summary }) {
6790
6812
  return saveCompanionExchange({ messages, summary, type: "diary", trigger: "interactive" });
6791
6813
  }
6792
6814
 
6793
- // mcp-server/tools/diary_recall.js
6815
+ // tools/diary_recall.js
6794
6816
  init_config_customer();
6795
6817
  init_recall_index();
6796
6818
  init_load_context();
@@ -6854,7 +6876,7 @@ async function diaryRecall({ from_date = null, to_date = null, query = null, dep
6854
6876
  };
6855
6877
  }
6856
6878
 
6857
- // mcp-server/tools/diary_chat.js
6879
+ // tools/diary_chat.js
6858
6880
  async function diaryChat({ message, context, systemPrompt }) {
6859
6881
  if (!message) {
6860
6882
  return {
@@ -7005,7 +7027,7 @@ ${context}` });
7005
7027
  }
7006
7028
  }
7007
7029
 
7008
- // mcp-server/tools/x402_fetch.js
7030
+ // tools/x402_fetch.js
7009
7031
  init_config_customer();
7010
7032
  init_spv();
7011
7033
  init_utxo_cache();
@@ -7140,7 +7162,7 @@ async function x402Fetch({ url, method = "GET", headers = {}, body, maxSats }) {
7140
7162
  };
7141
7163
  }
7142
7164
 
7143
- // cli-sandbox/src/index.js
7165
+ // ../cli-sandbox/src/index.js
7144
7166
  init_goals();
7145
7167
  init_inner_state();
7146
7168
  init_wall_stub();
@@ -7150,7 +7172,7 @@ init_wall_stub();
7150
7172
  init_wall_stub();
7151
7173
  init_wall_stub();
7152
7174
 
7153
- // mcp-server/tools/save_goals_to_chain.js
7175
+ // tools/save_goals_to_chain.js
7154
7176
  import { readFileSync as readFileSync13, existsSync as existsSync16 } from "fs";
7155
7177
  init_spv();
7156
7178
  init_utxo_cache();
@@ -7252,7 +7274,7 @@ Web Goals tab should reflect these on next refresh (chain scan).`
7252
7274
  };
7253
7275
  }
7254
7276
 
7255
- // mcp-server/tools/recall_context.js
7277
+ // tools/recall_context.js
7256
7278
  init_config_customer();
7257
7279
  init_recall_index();
7258
7280
  init_load_context();
@@ -7320,7 +7342,7 @@ async function recallContext({ from_date = null, to_date = null, query = null, d
7320
7342
  };
7321
7343
  }
7322
7344
 
7323
- // mcp-server/tools/report_bug.js
7345
+ // tools/report_bug.js
7324
7346
  import { readFileSync as readFileSync14, existsSync as existsSync17 } from "fs";
7325
7347
  import { join as join17, dirname as dirname4 } from "path";
7326
7348
  import { homedir as homedir14 } from "os";
@@ -7430,7 +7452,7 @@ async function reportBug(args2 = {}, mcpVersion) {
7430
7452
  }
7431
7453
  }
7432
7454
 
7433
- // mcp-server/tools/share_session.js
7455
+ // tools/share_session.js
7434
7456
  init_config_customer();
7435
7457
  init_spv();
7436
7458
  init_api_client();
@@ -7650,7 +7672,7 @@ function pushDataChunk2(data) {
7650
7672
  return { op, data };
7651
7673
  }
7652
7674
 
7653
- // mcp-server/tools/load_shared.js
7675
+ // tools/load_shared.js
7654
7676
  async function loadShared(opts = {}) {
7655
7677
  globalThis.__pathACallCount = (globalThis.__pathACallCount || 0) + 1;
7656
7678
  return {
@@ -7659,7 +7681,7 @@ async function loadShared(opts = {}) {
7659
7681
  };
7660
7682
  }
7661
7683
 
7662
- // cli-sandbox/src/index.js
7684
+ // ../cli-sandbox/src/index.js
7663
7685
  init_wall_stub();
7664
7686
  init_wall_stub();
7665
7687
  init_wall_stub();
@@ -7953,7 +7975,7 @@ Commands:
7953
7975
  const r = await rebuildVectorSidecar2(cfg.address, { maxEmbed: 100 });
7954
7976
  total += r.embedded;
7955
7977
  console.log(` embedded ${total} sessions; remaining ${r.remaining}; coverage ${r.coverage.vecs}/${r.coverage.indexed}`);
7956
- if (r.remaining === 0) break;
7978
+ if (r.remaining === 0 || r.embedded === 0) break;
7957
7979
  }
7958
7980
  console.log(JSON.stringify({ success: true, message: "Semantic recall enabled \u2014 meaning-based search is live in recall_context.", embedded: total }));
7959
7981
  } catch (e) {
@@ -7967,7 +7989,7 @@ Commands:
7967
7989
  }
7968
7990
  function printHelp() {
7969
7991
  console.log(`
7970
- Indelible MCP \u2014 Blockchain memory for Claude Code (v4.9.0)
7992
+ Indelible MCP \u2014 Blockchain memory for Claude Code (v4.9.2)
7971
7993
 
7972
7994
  Setup:
7973
7995
  indelible-mcp setup --wif=KEY --pin=PIN Import and encrypt your private key
@@ -8187,7 +8209,7 @@ function readStdin() {
8187
8209
  }
8188
8210
  var SERVER_INFO = {
8189
8211
  name: "indelible",
8190
- version: "4.9.0",
8212
+ version: "4.9.2",
8191
8213
  description: "Blockchain-backed memory and code storage for Claude Code"
8192
8214
  };
8193
8215
  var TOOLS = [
@@ -8484,7 +8506,8 @@ var TOOLS = [
8484
8506
  depth: { type: "string", enum: ["list", "full"], description: '"list" (default) = Tier-1 search; "full" = decrypt given txids.' },
8485
8507
  limit: { type: "number", description: 'Max results for depth:"list" (default 25).' },
8486
8508
  txids: { type: "array", items: { type: "string" }, description: 'For depth:"full": session txids to decrypt (max 20).' },
8487
- max_index: { type: "number", description: "Max sessions to decrypt-and-index this call (default 150)." }
8509
+ max_index: { type: "number", description: "Max sessions to decrypt-and-index this call (default 150)." },
8510
+ ranking: { type: "string", enum: ["blend", "keyword", "semantic"], description: "Result ranking: 'blend' (default) fuses keyword + meaning-based ranking; 'keyword' = exact-term only; 'semantic' = meaning only. Meaning ranking needs the local model pack (indelible-mcp semantic-fetch); absent = keyword with a notice. Nothing ever leaves your machine." }
8488
8511
  },
8489
8512
  required: []
8490
8513
  }
@@ -8641,7 +8664,8 @@ async function handleMcpRequest(request) {
8641
8664
  depth: args2?.depth || "list",
8642
8665
  limit: args2?.limit || 25,
8643
8666
  txids: args2?.txids || null,
8644
- max_index: args2?.max_index || 150
8667
+ max_index: args2?.max_index || 150,
8668
+ ranking: args2?.ranking || "blend"
8645
8669
  });
8646
8670
  break;
8647
8671
  case "report_bug":