@hasna/contacts 0.6.35 → 0.6.36

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/dist/cli/index.js CHANGED
@@ -47,7 +47,7 @@ var __export = (target, all) => {
47
47
  var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
48
48
  var __require = import.meta.require;
49
49
 
50
- // node_modules/commander/lib/error.js
50
+ // node_modules/.pnpm/commander@13.1.0/node_modules/commander/lib/error.js
51
51
  var require_error = __commonJS((exports) => {
52
52
  class CommanderError extends Error {
53
53
  constructor(exitCode, code, message) {
@@ -71,7 +71,7 @@ var require_error = __commonJS((exports) => {
71
71
  exports.InvalidArgumentError = InvalidArgumentError;
72
72
  });
73
73
 
74
- // node_modules/commander/lib/argument.js
74
+ // node_modules/.pnpm/commander@13.1.0/node_modules/commander/lib/argument.js
75
75
  var require_argument = __commonJS((exports) => {
76
76
  var { InvalidArgumentError } = require_error();
77
77
 
@@ -150,7 +150,7 @@ var require_argument = __commonJS((exports) => {
150
150
  exports.humanReadableArgName = humanReadableArgName;
151
151
  });
152
152
 
153
- // node_modules/commander/lib/help.js
153
+ // node_modules/.pnpm/commander@13.1.0/node_modules/commander/lib/help.js
154
154
  var require_help = __commonJS((exports) => {
155
155
  var { humanReadableArgName } = require_argument();
156
156
 
@@ -500,7 +500,7 @@ ${itemIndentStr}`);
500
500
  exports.stripColor = stripColor;
501
501
  });
502
502
 
503
- // node_modules/commander/lib/option.js
503
+ // node_modules/.pnpm/commander@13.1.0/node_modules/commander/lib/option.js
504
504
  var require_option = __commonJS((exports) => {
505
505
  var { InvalidArgumentError } = require_error();
506
506
 
@@ -678,7 +678,7 @@ var require_option = __commonJS((exports) => {
678
678
  exports.DualOptions = DualOptions;
679
679
  });
680
680
 
681
- // node_modules/commander/lib/suggestSimilar.js
681
+ // node_modules/.pnpm/commander@13.1.0/node_modules/commander/lib/suggestSimilar.js
682
682
  var require_suggestSimilar = __commonJS((exports) => {
683
683
  var maxDistance = 3;
684
684
  function editDistance(a, b) {
@@ -751,7 +751,7 @@ var require_suggestSimilar = __commonJS((exports) => {
751
751
  exports.suggestSimilar = suggestSimilar;
752
752
  });
753
753
 
754
- // node_modules/commander/lib/command.js
754
+ // node_modules/.pnpm/commander@13.1.0/node_modules/commander/lib/command.js
755
755
  var require_command = __commonJS((exports) => {
756
756
  var EventEmitter = __require("events").EventEmitter;
757
757
  var childProcess = __require("child_process");
@@ -1290,8 +1290,8 @@ Expecting one of '${allowedValues.join("', '")}'`);
1290
1290
  args = args.slice();
1291
1291
  let launchWithNode = false;
1292
1292
  const sourceExt = [".js", ".ts", ".tsx", ".mjs", ".cjs"];
1293
- function findFile(baseDir, baseName) {
1294
- const localBin = path.resolve(baseDir, baseName);
1293
+ function findFile(baseDir2, baseName) {
1294
+ const localBin = path.resolve(baseDir2, baseName);
1295
1295
  if (fs.existsSync(localBin))
1296
1296
  return localBin;
1297
1297
  if (sourceExt.includes(path.extname(baseName)))
@@ -2061,7 +2061,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
2061
2061
  exports.useColor = useColor;
2062
2062
  });
2063
2063
 
2064
- // node_modules/commander/index.js
2064
+ // node_modules/.pnpm/commander@13.1.0/node_modules/commander/index.js
2065
2065
  var require_commander = __commonJS((exports) => {
2066
2066
  var { Argument } = require_argument();
2067
2067
  var { Command } = require_command();
@@ -2121,43 +2121,169 @@ class SqliteAdapter {
2121
2121
  }
2122
2122
  var init_sqlite_adapter = () => {};
2123
2123
 
2124
+ // node_modules/.pnpm/@hasna+paths@0.2.2/node_modules/@hasna/paths/dist/index.js
2125
+ import { homedir as homedir3 } from "os";
2126
+ import { join as join4 } from "path";
2127
+ function assertApp2(app) {
2128
+ if (typeof app !== "string" || app.length === 0) {
2129
+ throw new TypeError("paths: app must be a non-empty string");
2130
+ }
2131
+ if (!APP_SLUG_RE2.test(app)) {
2132
+ throw new TypeError(`paths: invalid app slug "${app}" \u2014 expected lowercase kebab-case ([a-z0-9]+(-[a-z0-9]+)*)`);
2133
+ }
2134
+ }
2135
+ function assertKind(kind) {
2136
+ if (!PATH_KINDS.includes(kind)) {
2137
+ throw new TypeError(`paths: invalid path kind "${kind}" \u2014 expected one of ${PATH_KINDS.join(", ")}`);
2138
+ }
2139
+ }
2140
+ function envOf2(options) {
2141
+ return options.env ?? process.env;
2142
+ }
2143
+ function envValue2(options, kind) {
2144
+ const value = envOf2(options)[KIND_ENV2[kind]];
2145
+ return typeof value === "string" && value.length > 0 ? value : undefined;
2146
+ }
2147
+ function isMacOS2(platform) {
2148
+ return platform === "darwin";
2149
+ }
2150
+ function baseDir2(kind, options) {
2151
+ assertKind(kind);
2152
+ const override = envValue2(options, kind);
2153
+ if (override)
2154
+ return override;
2155
+ const home = options.home ?? homedir3();
2156
+ const platform = options.platform ?? process.platform;
2157
+ if (isMacOS2(platform)) {
2158
+ switch (kind) {
2159
+ case "config":
2160
+ case "data":
2161
+ return join4(home, "Library", "Application Support", "Hasna");
2162
+ case "cache":
2163
+ return join4(home, "Library", "Caches", "Hasna");
2164
+ case "state":
2165
+ return join4(home, "Library", "Logs", "Hasna");
2166
+ }
2167
+ }
2168
+ switch (kind) {
2169
+ case "config":
2170
+ return join4(home, ".config", "hasna");
2171
+ case "data":
2172
+ return join4(home, ".local", "share", "hasna");
2173
+ case "state":
2174
+ return join4(home, ".local", "state", "hasna");
2175
+ case "cache":
2176
+ return join4(home, ".cache", "hasna");
2177
+ }
2178
+ }
2179
+ function resolvePath2(kind, options) {
2180
+ assertKind(kind);
2181
+ assertApp2(options.app);
2182
+ const appSegment = options.internal === true ? join4("internal", options.app) : options.app;
2183
+ return join4(baseDir2(kind, options), appSegment);
2184
+ }
2185
+ function dataDir2(options) {
2186
+ return resolvePath2("data", options);
2187
+ }
2188
+ function stateDir(options) {
2189
+ return resolvePath2("state", options);
2190
+ }
2191
+ var PATH_KINDS, KIND_ENV2, APP_SLUG_RE2;
2192
+ var init_dist = __esm(() => {
2193
+ PATH_KINDS = ["config", "data", "state", "cache"];
2194
+ KIND_ENV2 = {
2195
+ config: "HASNA_CONFIG_HOME",
2196
+ data: "HASNA_DATA_HOME",
2197
+ state: "HASNA_STATE_HOME",
2198
+ cache: "HASNA_CACHE_HOME"
2199
+ };
2200
+ APP_SLUG_RE2 = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
2201
+ });
2202
+
2124
2203
  // src/db/paths.ts
2125
- import { chmodSync, copyFileSync, existsSync as existsSync2, mkdirSync, readdirSync, statSync } from "fs";
2126
- import { join as join2 } from "path";
2204
+ import { chmodSync, copyFileSync, cpSync, existsSync as existsSync3, mkdirSync, readdirSync, statSync } from "fs";
2205
+ import { homedir as homedir5 } from "os";
2206
+ import { join as join6 } from "path";
2127
2207
  function ensurePrivateDir(dir) {
2128
- if (!existsSync2(dir))
2208
+ if (!existsSync3(dir))
2129
2209
  mkdirSync(dir, { recursive: true, mode: 448 });
2130
2210
  chmodSync(dir, 448);
2131
2211
  }
2212
+ function home() {
2213
+ return process.env["HOME"] || process.env["USERPROFILE"] || homedir5();
2214
+ }
2215
+ function hasContent(dir) {
2216
+ if (!existsSync3(dir))
2217
+ return false;
2218
+ try {
2219
+ return readdirSync(dir).length > 0;
2220
+ } catch {
2221
+ return false;
2222
+ }
2223
+ }
2224
+ function adoptLegacy(source, target) {
2225
+ if (!hasContent(source) || hasContent(target))
2226
+ return;
2227
+ ensurePrivateDir(target);
2228
+ for (const entry of readdirSync(source)) {
2229
+ if (entry === ".vault-session")
2230
+ continue;
2231
+ if (entry === "{backups,images,documents}")
2232
+ continue;
2233
+ const oldPath = join6(source, entry);
2234
+ const newPath = join6(target, entry);
2235
+ const st = statSync(oldPath);
2236
+ if (st.isDirectory()) {
2237
+ cpSync(oldPath, newPath, { recursive: true });
2238
+ chmodSync(newPath, 448);
2239
+ } else if (st.isFile()) {
2240
+ copyFileSync(oldPath, newPath);
2241
+ chmodSync(newPath, 384);
2242
+ }
2243
+ }
2244
+ }
2132
2245
  function getDataDir() {
2133
- const home = process.env["HOME"] || process.env["USERPROFILE"] || "~";
2134
- const hasnaDir = join2(home, ".hasna");
2135
- const newDir = join2(home, ".hasna", "contacts");
2136
- const oldDir = join2(home, ".contacts");
2137
- if (existsSync2(oldDir) && !existsSync2(newDir)) {
2138
- ensurePrivateDir(hasnaDir);
2139
- ensurePrivateDir(newDir);
2140
- for (const file of readdirSync(oldDir)) {
2141
- const oldPath = join2(oldDir, file);
2142
- if (statSync(oldPath).isFile()) {
2143
- const newPath = join2(newDir, file);
2144
- copyFileSync(oldPath, newPath);
2145
- chmodSync(newPath, 384);
2146
- }
2147
- }
2148
- }
2149
- ensurePrivateDir(hasnaDir);
2150
- ensurePrivateDir(newDir);
2151
- return newDir;
2246
+ const base = home();
2247
+ const target = dataDir2({ app: "contacts", home: base });
2248
+ if (!checkedDataTargets.has(target)) {
2249
+ adoptLegacy(join6(base, ".hasna", "contacts"), target);
2250
+ adoptLegacy(join6(base, ".contacts"), target);
2251
+ checkedDataTargets.add(target);
2252
+ }
2253
+ ensurePrivateDir(target);
2254
+ return target;
2255
+ }
2256
+ function getStateDir() {
2257
+ const base = home();
2258
+ const target = stateDir({ app: "contacts", home: base });
2259
+ if (!checkedStateTargets.has(target)) {
2260
+ if (!hasContent(target)) {
2261
+ const legacySession = join6(base, ".hasna", "contacts", ".vault-session");
2262
+ if (existsSync3(legacySession)) {
2263
+ ensurePrivateDir(target);
2264
+ const targetSession = join6(target, ".vault-session");
2265
+ copyFileSync(legacySession, targetSession);
2266
+ chmodSync(targetSession, 384);
2267
+ }
2268
+ }
2269
+ checkedStateTargets.add(target);
2270
+ }
2271
+ ensurePrivateDir(target);
2272
+ return target;
2152
2273
  }
2153
2274
  function getDbPath() {
2154
2275
  if (process.env["HASNA_CONTACTS_DB_PATH"])
2155
2276
  return process.env["HASNA_CONTACTS_DB_PATH"];
2156
2277
  if (process.env["CONTACTS_DB_PATH"])
2157
2278
  return process.env["CONTACTS_DB_PATH"];
2158
- return join2(getDataDir(), "contacts.db");
2279
+ return join6(getDataDir(), "contacts.db");
2159
2280
  }
2160
- var init_paths = () => {};
2281
+ var checkedDataTargets, checkedStateTargets;
2282
+ var init_paths = __esm(() => {
2283
+ init_dist();
2284
+ checkedDataTargets = new Set;
2285
+ checkedStateTargets = new Set;
2286
+ });
2161
2287
 
2162
2288
  // src/db/database.ts
2163
2289
  var exports_database = {};
@@ -2165,28 +2291,29 @@ __export(exports_database, {
2165
2291
  uuid: () => uuid,
2166
2292
  resetDatabase: () => resetDatabase,
2167
2293
  now: () => now2,
2294
+ getStateDir: () => getStateDir,
2168
2295
  getDbPath: () => getDbPath,
2169
2296
  getDatabase: () => getDatabase,
2170
2297
  getDataDir: () => getDataDir
2171
2298
  });
2172
- import { chmodSync as chmodSync2, existsSync as existsSync3, mkdirSync as mkdirSync2 } from "fs";
2173
- import { dirname, resolve } from "path";
2299
+ import { chmodSync as chmodSync2, existsSync as existsSync5, mkdirSync as mkdirSync2 } from "fs";
2300
+ import { dirname, resolve as resolve2 } from "path";
2174
2301
  function ensureCreatedPrivateDir(dir) {
2175
- if (!existsSync3(dir))
2302
+ if (!existsSync5(dir))
2176
2303
  mkdirSync2(dir, { recursive: true, mode: 448 });
2177
2304
  }
2178
2305
  function protectDatabaseArtifacts(dbPath) {
2179
2306
  if (dbPath === ":memory:")
2180
2307
  return;
2181
2308
  for (const artifact of [dbPath, `${dbPath}-wal`, `${dbPath}-shm`]) {
2182
- if (existsSync3(artifact))
2309
+ if (existsSync5(artifact))
2183
2310
  chmodSync2(artifact, 384);
2184
2311
  }
2185
2312
  }
2186
2313
  function ensureDir(filePath) {
2187
2314
  if (filePath === ":memory:")
2188
2315
  return;
2189
- const dir = dirname(resolve(filePath));
2316
+ const dir = dirname(resolve2(filePath));
2190
2317
  ensureCreatedPrivateDir(dir);
2191
2318
  }
2192
2319
  function getDatabase(path) {
@@ -5552,9 +5679,24 @@ var init_org_chart = __esm(() => {
5552
5679
  });
5553
5680
 
5554
5681
  // src/lib/vault.ts
5555
- import { existsSync as existsSync4, readFileSync, writeFileSync, mkdirSync as mkdirSync3, unlinkSync } from "fs";
5556
- import { join as join3 } from "path";
5682
+ import { existsSync as existsSync6, readFileSync, writeFileSync, mkdirSync as mkdirSync3, unlinkSync } from "fs";
5683
+ import { join as join7 } from "path";
5557
5684
  import { createCipheriv, createDecipheriv, randomBytes, pbkdf2Sync, createHash as createHash2 } from "crypto";
5685
+ function getVaultDir() {
5686
+ return getDataDir();
5687
+ }
5688
+ function getVaultConfigPath() {
5689
+ return join7(getDataDir(), "vault.json");
5690
+ }
5691
+ function getVaultSessionPath() {
5692
+ return join7(getStateDir(), ".vault-session");
5693
+ }
5694
+ function getDocumentsDir() {
5695
+ const dir = join7(getDataDir(), "documents");
5696
+ if (!existsSync6(dir))
5697
+ mkdirSync3(dir, { recursive: true });
5698
+ return dir;
5699
+ }
5558
5700
  function deriveKey(passphrase, salt) {
5559
5701
  return pbkdf2Sync(passphrase, salt, 1e5, 32, "sha512");
5560
5702
  }
@@ -5563,16 +5705,17 @@ function saveSession(key) {
5563
5705
  key: key.toString("hex"),
5564
5706
  expires_at: new Date(Date.now() + SESSION_TTL_MS).toISOString()
5565
5707
  };
5566
- writeFileSync(VAULT_SESSION, JSON.stringify(session), { mode: 384 });
5708
+ writeFileSync(getVaultSessionPath(), JSON.stringify(session), { mode: 384 });
5567
5709
  }
5568
5710
  function loadSession() {
5569
- if (!existsSync4(VAULT_SESSION))
5711
+ const sessionPath = getVaultSessionPath();
5712
+ if (!existsSync6(sessionPath))
5570
5713
  return null;
5571
5714
  try {
5572
- const session = JSON.parse(readFileSync(VAULT_SESSION, "utf-8"));
5715
+ const session = JSON.parse(readFileSync(sessionPath, "utf-8"));
5573
5716
  if (new Date(session.expires_at).getTime() < Date.now()) {
5574
5717
  try {
5575
- unlinkSync(VAULT_SESSION);
5718
+ unlinkSync(sessionPath);
5576
5719
  } catch {}
5577
5720
  return null;
5578
5721
  }
@@ -5583,30 +5726,30 @@ function loadSession() {
5583
5726
  }
5584
5727
  function clearSession() {
5585
5728
  try {
5586
- if (existsSync4(VAULT_SESSION))
5587
- unlinkSync(VAULT_SESSION);
5729
+ if (existsSync6(getVaultSessionPath()))
5730
+ unlinkSync(getVaultSessionPath());
5588
5731
  } catch {}
5589
5732
  }
5590
5733
  function initVault(passphrase) {
5591
- if (!existsSync4(VAULT_DIR))
5592
- mkdirSync3(VAULT_DIR, { recursive: true });
5593
- if (!existsSync4(DOCUMENTS_DIR))
5594
- mkdirSync3(DOCUMENTS_DIR, { recursive: true });
5734
+ const vaultDir = getVaultDir();
5735
+ if (!existsSync6(vaultDir))
5736
+ mkdirSync3(vaultDir, { recursive: true });
5737
+ mkdirSync3(getDocumentsDir(), { recursive: true });
5595
5738
  const salt = randomBytes(32);
5596
5739
  const key = deriveKey(passphrase, salt);
5597
5740
  const keyHash = createHash2("sha256").update(key).digest("hex");
5598
5741
  const config = { salt: salt.toString("hex"), key_hash: keyHash, created_at: new Date().toISOString() };
5599
- writeFileSync(VAULT_CONFIG, JSON.stringify(config, null, 2));
5742
+ writeFileSync(getVaultConfigPath(), JSON.stringify(config, null, 2));
5600
5743
  _derivedKey = key;
5601
5744
  saveSession(key);
5602
5745
  }
5603
5746
  function isVaultInitialized() {
5604
- return existsSync4(VAULT_CONFIG);
5747
+ return existsSync6(getVaultConfigPath());
5605
5748
  }
5606
5749
  function unlockVault(passphrase) {
5607
- if (!existsSync4(VAULT_CONFIG))
5750
+ if (!existsSync6(getVaultConfigPath()))
5608
5751
  throw new Error("Vault not initialized. Run 'contacts vault init' first.");
5609
- const config = JSON.parse(readFileSync(VAULT_CONFIG, "utf-8"));
5752
+ const config = JSON.parse(readFileSync(getVaultConfigPath(), "utf-8"));
5610
5753
  const salt = Buffer.from(config.salt, "hex");
5611
5754
  const key = deriveKey(passphrase, salt);
5612
5755
  const keyHash = createHash2("sha256").update(key).digest("hex");
@@ -5661,26 +5804,18 @@ function decrypt(ciphertext, iv) {
5661
5804
  return decrypted;
5662
5805
  }
5663
5806
  function storeFile(sourcePath, entityId) {
5664
- if (!existsSync4(DOCUMENTS_DIR))
5665
- mkdirSync3(DOCUMENTS_DIR, { recursive: true });
5807
+ const documentsDir = getDocumentsDir();
5808
+ if (!existsSync6(documentsDir))
5809
+ mkdirSync3(documentsDir, { recursive: true });
5666
5810
  const ext = sourcePath.split(".").pop() || "bin";
5667
- const destPath = join3(DOCUMENTS_DIR, `${entityId}.${ext}`);
5811
+ const destPath = join7(documentsDir, `${entityId}.${ext}`);
5668
5812
  const data = readFileSync(sourcePath);
5669
5813
  writeFileSync(destPath, data);
5670
5814
  return destPath;
5671
5815
  }
5672
- function getDocumentsDir() {
5673
- if (!existsSync4(DOCUMENTS_DIR))
5674
- mkdirSync3(DOCUMENTS_DIR, { recursive: true });
5675
- return DOCUMENTS_DIR;
5676
- }
5677
- var VAULT_DIR, VAULT_CONFIG, VAULT_SESSION, DOCUMENTS_DIR, SESSION_TTL_MS, _derivedKey = null;
5816
+ var SESSION_TTL_MS, _derivedKey = null;
5678
5817
  var init_vault = __esm(() => {
5679
5818
  init_database();
5680
- VAULT_DIR = getDataDir();
5681
- VAULT_CONFIG = join3(VAULT_DIR, "vault.json");
5682
- VAULT_SESSION = join3(VAULT_DIR, ".vault-session");
5683
- DOCUMENTS_DIR = join3(VAULT_DIR, "documents");
5684
5819
  SESSION_TTL_MS = 30 * 60 * 1000;
5685
5820
  });
5686
5821
 
@@ -5693,7 +5828,7 @@ __export(exports_documents, {
5693
5828
  addDocument: () => addDocument,
5694
5829
  DOCUMENT_TYPES: () => DOCUMENT_TYPES
5695
5830
  });
5696
- import { existsSync as existsSync5, unlinkSync as unlinkSync2 } from "fs";
5831
+ import { existsSync as existsSync7, unlinkSync as unlinkSync2 } from "fs";
5697
5832
  function addDocument(input, db) {
5698
5833
  requireVault();
5699
5834
  const _db2 = db || getDatabase();
@@ -5729,7 +5864,7 @@ function listDocuments(contactId, db) {
5729
5864
  function deleteDocument(id, db) {
5730
5865
  const _db2 = db || getDatabase();
5731
5866
  const row = _db2.query(`SELECT encrypted_file_path FROM contact_documents WHERE id = ?`).get(id);
5732
- if (row?.encrypted_file_path && existsSync5(row.encrypted_file_path)) {
5867
+ if (row?.encrypted_file_path && existsSync7(row.encrypted_file_path)) {
5733
5868
  try {
5734
5869
  unlinkSync2(row.encrypted_file_path);
5735
5870
  } catch {}
@@ -6630,10 +6765,10 @@ var init_context = __esm(() => {
6630
6765
  });
6631
6766
 
6632
6767
  // src/lib/images.ts
6633
- import { existsSync as existsSync6, mkdirSync as mkdirSync4, copyFileSync as copyFileSync2, unlinkSync as unlinkSync3, readdirSync as readdirSync2, readFileSync as readFileSync2, writeFileSync as writeFileSync2 } from "fs";
6634
- import { join as join4, extname, basename } from "path";
6768
+ import { existsSync as existsSync8, mkdirSync as mkdirSync4, copyFileSync as copyFileSync2, unlinkSync as unlinkSync3, readdirSync as readdirSync2, readFileSync as readFileSync2, writeFileSync as writeFileSync2 } from "fs";
6769
+ import { join as join8, extname, basename } from "path";
6635
6770
  function ensureImagesDir() {
6636
- if (!existsSync6(IMAGES_DIR))
6771
+ if (!existsSync8(IMAGES_DIR))
6637
6772
  mkdirSync4(IMAGES_DIR, { recursive: true });
6638
6773
  }
6639
6774
  function getImagesDir() {
@@ -6648,17 +6783,17 @@ function saveImage(entityId, source, options) {
6648
6783
  const ext2 = base64Match[1] === "jpeg" ? "jpg" : base64Match[1];
6649
6784
  const data = Buffer.from(base64Match[2], "base64");
6650
6785
  const filename2 = `${entityId}.${ext2}`;
6651
- writeFileSync2(join4(IMAGES_DIR, filename2), data);
6786
+ writeFileSync2(join8(IMAGES_DIR, filename2), data);
6652
6787
  return filename2;
6653
6788
  }
6654
- if (!existsSync6(source) && /^[A-Za-z0-9+/=\n\r]+$/.test(source.trim()) && source.length > 100) {
6789
+ if (!existsSync8(source) && /^[A-Za-z0-9+/=\n\r]+$/.test(source.trim()) && source.length > 100) {
6655
6790
  const ext2 = options?.format || "jpg";
6656
6791
  const data = Buffer.from(source.trim(), "base64");
6657
6792
  const filename2 = `${entityId}.${ext2}`;
6658
- writeFileSync2(join4(IMAGES_DIR, filename2), data);
6793
+ writeFileSync2(join8(IMAGES_DIR, filename2), data);
6659
6794
  return filename2;
6660
6795
  }
6661
- if (!existsSync6(source)) {
6796
+ if (!existsSync8(source)) {
6662
6797
  throw new Error(`Image file not found: ${source}`);
6663
6798
  }
6664
6799
  const ext = extname(source).slice(1).toLowerCase() || "jpg";
@@ -6667,14 +6802,14 @@ function saveImage(entityId, source, options) {
6667
6802
  throw new Error(`Unsupported image format: ${ext}. Supported: ${validExts.join(", ")}`);
6668
6803
  }
6669
6804
  const filename = `${entityId}.${ext === "jpeg" ? "jpg" : ext}`;
6670
- copyFileSync2(source, join4(IMAGES_DIR, filename));
6805
+ copyFileSync2(source, join8(IMAGES_DIR, filename));
6671
6806
  return filename;
6672
6807
  }
6673
6808
  function getImagePath(entityId) {
6674
6809
  ensureImagesDir();
6675
6810
  const files = readdirSync2(IMAGES_DIR);
6676
6811
  const match = files.find((f) => f.startsWith(`${entityId}.`));
6677
- return match ? join4(IMAGES_DIR, match) : null;
6812
+ return match ? join8(IMAGES_DIR, match) : null;
6678
6813
  }
6679
6814
  function getImageAsBase64(entityId) {
6680
6815
  const path = getImagePath(entityId);
@@ -6691,7 +6826,7 @@ function deleteImage(entityId) {
6691
6826
  let deleted = false;
6692
6827
  for (const f of files) {
6693
6828
  if (f.startsWith(`${entityId}.`)) {
6694
- unlinkSync3(join4(IMAGES_DIR, f));
6829
+ unlinkSync3(join8(IMAGES_DIR, f));
6695
6830
  deleted = true;
6696
6831
  }
6697
6832
  }
@@ -6703,13 +6838,13 @@ function listImages() {
6703
6838
  return files.map((f) => ({
6704
6839
  entity_id: basename(f, extname(f)),
6705
6840
  filename: f,
6706
- path: join4(IMAGES_DIR, f)
6841
+ path: join8(IMAGES_DIR, f)
6707
6842
  }));
6708
6843
  }
6709
6844
  var IMAGES_DIR;
6710
6845
  var init_images = __esm(() => {
6711
6846
  init_database();
6712
- IMAGES_DIR = join4(getDataDir(), "images");
6847
+ IMAGES_DIR = join8(getDataDir(), "images");
6713
6848
  });
6714
6849
 
6715
6850
  // src/lib/mailery-sync.ts
@@ -7112,7 +7247,7 @@ function resolveStorageClient(name, env = process.env) {
7112
7247
  const transport = createHttpTransport({ name, baseUrl: resolution.baseUrl, apiKey });
7113
7248
  return { transport: "cloud-http", client: createStorageClient(name, transport), resolution };
7114
7249
  }
7115
- var DEPRECATED_MODE_ALIASES, HasnaHttpError, DEFAULT_RETRY_STATUSES, IDEMPOTENT_METHODS, sleep = (ms) => new Promise((resolve2) => setTimeout(resolve2, ms));
7250
+ var DEPRECATED_MODE_ALIASES, HasnaHttpError, DEFAULT_RETRY_STATUSES, IDEMPOTENT_METHODS, sleep = (ms) => new Promise((resolve3) => setTimeout(resolve3, ms));
7116
7251
  var init_http_storage = __esm(() => {
7117
7252
  DEPRECATED_MODE_ALIASES = new Set(["remote", "hybrid", "self_hosted"]);
7118
7253
  HasnaHttpError = class HasnaHttpError extends Error {
@@ -8929,7 +9064,153 @@ async function exportContacts(format, contacts) {
8929
9064
  }
8930
9065
  }
8931
9066
 
8932
- // node_modules/zod/v4/core/core.js
9067
+ // node_modules/.pnpm/content-type@1.0.5/node_modules/content-type/index.js
9068
+ var require_content_type = __commonJS((exports) => {
9069
+ /*!
9070
+ * content-type
9071
+ * Copyright(c) 2015 Douglas Christopher Wilson
9072
+ * MIT Licensed
9073
+ */
9074
+ var PARAM_REGEXP = /; *([!#$%&'*+.^_`|~0-9A-Za-z-]+) *= *("(?:[\u000b\u0020\u0021\u0023-\u005b\u005d-\u007e\u0080-\u00ff]|\\[\u000b\u0020-\u00ff])*"|[!#$%&'*+.^_`|~0-9A-Za-z-]+) */g;
9075
+ var TEXT_REGEXP = /^[\u000b\u0020-\u007e\u0080-\u00ff]+$/;
9076
+ var TOKEN_REGEXP = /^[!#$%&'*+.^_`|~0-9A-Za-z-]+$/;
9077
+ var QESC_REGEXP = /\\([\u000b\u0020-\u00ff])/g;
9078
+ var QUOTE_REGEXP = /([\\"])/g;
9079
+ var TYPE_REGEXP = /^[!#$%&'*+.^_`|~0-9A-Za-z-]+\/[!#$%&'*+.^_`|~0-9A-Za-z-]+$/;
9080
+ exports.format = format;
9081
+ exports.parse = parse;
9082
+ function format(obj) {
9083
+ if (!obj || typeof obj !== "object") {
9084
+ throw new TypeError("argument obj is required");
9085
+ }
9086
+ var parameters = obj.parameters;
9087
+ var type = obj.type;
9088
+ if (!type || !TYPE_REGEXP.test(type)) {
9089
+ throw new TypeError("invalid type");
9090
+ }
9091
+ var string = type;
9092
+ if (parameters && typeof parameters === "object") {
9093
+ var param;
9094
+ var params = Object.keys(parameters).sort();
9095
+ for (var i = 0;i < params.length; i++) {
9096
+ param = params[i];
9097
+ if (!TOKEN_REGEXP.test(param)) {
9098
+ throw new TypeError("invalid parameter name");
9099
+ }
9100
+ string += "; " + param + "=" + qstring(parameters[param]);
9101
+ }
9102
+ }
9103
+ return string;
9104
+ }
9105
+ function parse(string) {
9106
+ if (!string) {
9107
+ throw new TypeError("argument string is required");
9108
+ }
9109
+ var header = typeof string === "object" ? getcontenttype(string) : string;
9110
+ if (typeof header !== "string") {
9111
+ throw new TypeError("argument string is required to be a string");
9112
+ }
9113
+ var index = header.indexOf(";");
9114
+ var type = index !== -1 ? header.slice(0, index).trim() : header.trim();
9115
+ if (!TYPE_REGEXP.test(type)) {
9116
+ throw new TypeError("invalid media type");
9117
+ }
9118
+ var obj = new ContentType(type.toLowerCase());
9119
+ if (index !== -1) {
9120
+ var key;
9121
+ var match;
9122
+ var value;
9123
+ PARAM_REGEXP.lastIndex = index;
9124
+ while (match = PARAM_REGEXP.exec(header)) {
9125
+ if (match.index !== index) {
9126
+ throw new TypeError("invalid parameter format");
9127
+ }
9128
+ index += match[0].length;
9129
+ key = match[1].toLowerCase();
9130
+ value = match[2];
9131
+ if (value.charCodeAt(0) === 34) {
9132
+ value = value.slice(1, -1);
9133
+ if (value.indexOf("\\") !== -1) {
9134
+ value = value.replace(QESC_REGEXP, "$1");
9135
+ }
9136
+ }
9137
+ obj.parameters[key] = value;
9138
+ }
9139
+ if (index !== header.length) {
9140
+ throw new TypeError("invalid parameter format");
9141
+ }
9142
+ }
9143
+ return obj;
9144
+ }
9145
+ function getcontenttype(obj) {
9146
+ var header;
9147
+ if (typeof obj.getHeader === "function") {
9148
+ header = obj.getHeader("content-type");
9149
+ } else if (typeof obj.headers === "object") {
9150
+ header = obj.headers && obj.headers["content-type"];
9151
+ }
9152
+ if (typeof header !== "string") {
9153
+ throw new TypeError("content-type header is missing from object");
9154
+ }
9155
+ return header;
9156
+ }
9157
+ function qstring(val) {
9158
+ var str = String(val);
9159
+ if (TOKEN_REGEXP.test(str)) {
9160
+ return str;
9161
+ }
9162
+ if (str.length > 0 && !TEXT_REGEXP.test(str)) {
9163
+ throw new TypeError("invalid parameter value");
9164
+ }
9165
+ return '"' + str.replace(QUOTE_REGEXP, "\\$1") + '"';
9166
+ }
9167
+ function ContentType(type) {
9168
+ this.parameters = Object.create(null);
9169
+ this.type = type;
9170
+ }
9171
+ });
9172
+
9173
+ // node_modules/.pnpm/@modelcontextprotocol+sdk@1.30.0_zod@3.25.76/node_modules/@modelcontextprotocol/sdk/dist/esm/shared/mediaType.js
9174
+ function mediaTypeEssence(header) {
9175
+ if (!header) {
9176
+ return;
9177
+ }
9178
+ try {
9179
+ return import_content_type.default.parse(header).type;
9180
+ } catch {
9181
+ const essence = (header.split(";", 1)[0] ?? "").trim().toLowerCase();
9182
+ if (essence === "" || header.slice(essence.length).includes(",")) {
9183
+ return;
9184
+ }
9185
+ return essence;
9186
+ }
9187
+ }
9188
+ function isJsonContentType(header) {
9189
+ if (header === "application/json") {
9190
+ return true;
9191
+ }
9192
+ return mediaTypeEssence(header) === "application/json";
9193
+ }
9194
+ var import_content_type;
9195
+ var init_mediaType = __esm(() => {
9196
+ import_content_type = __toESM(require_content_type(), 1);
9197
+ });
9198
+
9199
+ // node_modules/.pnpm/@modelcontextprotocol+sdk@1.30.0_zod@3.25.76/node_modules/@modelcontextprotocol/sdk/dist/esm/server/sseKeepAlive.js
9200
+ function armSseKeepAlive(intervalMs, onTick) {
9201
+ if (!Number.isFinite(intervalMs) || intervalMs < 1) {
9202
+ return;
9203
+ }
9204
+ const timer = setInterval(onTick, Math.min(intervalMs, MAX_TIMER_DELAY_MS));
9205
+ timer.unref?.();
9206
+ return timer;
9207
+ }
9208
+ var DEFAULT_SSE_KEEP_ALIVE_MS = 15000, MAX_TIMER_DELAY_MS;
9209
+ var init_sseKeepAlive = __esm(() => {
9210
+ MAX_TIMER_DELAY_MS = 2 ** 31 - 1;
9211
+ });
9212
+
9213
+ // node_modules/.pnpm/zod@3.25.76/node_modules/zod/v4/core/core.js
8933
9214
  function $constructor(name, initializer, params) {
8934
9215
  function init(inst, def) {
8935
9216
  var _a;
@@ -8992,7 +9273,7 @@ var init_core = __esm(() => {
8992
9273
  globalConfig = {};
8993
9274
  });
8994
9275
 
8995
- // node_modules/zod/v4/core/util.js
9276
+ // node_modules/.pnpm/zod@3.25.76/node_modules/zod/v4/core/util.js
8996
9277
  var exports_util = {};
8997
9278
  __export(exports_util, {
8998
9279
  unwrapMessage: () => unwrapMessage,
@@ -9508,7 +9789,7 @@ var init_util = __esm(() => {
9508
9789
  };
9509
9790
  });
9510
9791
 
9511
- // node_modules/zod/v4/core/errors.js
9792
+ // node_modules/.pnpm/zod@3.25.76/node_modules/zod/v4/core/errors.js
9512
9793
  function flattenError(error, mapper = (issue2) => issue2.message) {
9513
9794
  const fieldErrors = {};
9514
9795
  const formErrors = [];
@@ -9586,7 +9867,7 @@ var init_errors = __esm(() => {
9586
9867
  $ZodRealError = $constructor("$ZodError", initializer, { Parent: Error });
9587
9868
  });
9588
9869
 
9589
- // node_modules/zod/v4/core/parse.js
9870
+ // node_modules/.pnpm/zod@3.25.76/node_modules/zod/v4/core/parse.js
9590
9871
  var _parse = (_Err) => (schema, value, _ctx, _params) => {
9591
9872
  const ctx = _ctx ? Object.assign(_ctx, { async: false }) : { async: false };
9592
9873
  const result = schema._zod.run({ value, issues: [] }, ctx);
@@ -9640,7 +9921,7 @@ var init_parse = __esm(() => {
9640
9921
  safeParseAsync = /* @__PURE__ */ _safeParseAsync($ZodRealError);
9641
9922
  });
9642
9923
 
9643
- // node_modules/zod/v4/core/regexes.js
9924
+ // node_modules/.pnpm/zod@3.25.76/node_modules/zod/v4/core/regexes.js
9644
9925
  function emoji() {
9645
9926
  return new RegExp(_emoji, "u");
9646
9927
  }
@@ -9697,7 +9978,7 @@ var init_regexes = __esm(() => {
9697
9978
  uppercase = /^[^a-z]*$/;
9698
9979
  });
9699
9980
 
9700
- // node_modules/zod/v4/core/checks.js
9981
+ // node_modules/.pnpm/zod@3.25.76/node_modules/zod/v4/core/checks.js
9701
9982
  var $ZodCheck, numericOriginMap, $ZodCheckLessThan, $ZodCheckGreaterThan, $ZodCheckMultipleOf, $ZodCheckNumberFormat, $ZodCheckMaxLength, $ZodCheckMinLength, $ZodCheckLengthEquals, $ZodCheckStringFormat, $ZodCheckRegex, $ZodCheckLowerCase, $ZodCheckUpperCase, $ZodCheckIncludes, $ZodCheckStartsWith, $ZodCheckEndsWith, $ZodCheckOverwrite;
9702
9983
  var init_checks = __esm(() => {
9703
9984
  init_core();
@@ -10087,7 +10368,7 @@ var init_checks = __esm(() => {
10087
10368
  });
10088
10369
  });
10089
10370
 
10090
- // node_modules/zod/v4/core/doc.js
10371
+ // node_modules/.pnpm/zod@3.25.76/node_modules/zod/v4/core/doc.js
10091
10372
  class Doc {
10092
10373
  constructor(args = []) {
10093
10374
  this.content = [];
@@ -10125,7 +10406,7 @@ class Doc {
10125
10406
  }
10126
10407
  }
10127
10408
 
10128
- // node_modules/zod/v4/core/versions.js
10409
+ // node_modules/.pnpm/zod@3.25.76/node_modules/zod/v4/core/versions.js
10129
10410
  var version;
10130
10411
  var init_versions = __esm(() => {
10131
10412
  version = {
@@ -10135,7 +10416,7 @@ var init_versions = __esm(() => {
10135
10416
  };
10136
10417
  });
10137
10418
 
10138
- // node_modules/zod/v4/core/schemas.js
10419
+ // node_modules/.pnpm/zod@3.25.76/node_modules/zod/v4/core/schemas.js
10139
10420
  function isValidBase64(data) {
10140
10421
  if (data === "")
10141
10422
  return true;
@@ -11377,7 +11658,7 @@ var init_schemas = __esm(() => {
11377
11658
  });
11378
11659
  });
11379
11660
 
11380
- // node_modules/zod/v4/locales/en.js
11661
+ // node_modules/.pnpm/zod@3.25.76/node_modules/zod/v4/locales/en.js
11381
11662
  function en_default() {
11382
11663
  return {
11383
11664
  localeError: error()
@@ -11497,10 +11778,10 @@ var init_en = __esm(() => {
11497
11778
  init_util();
11498
11779
  });
11499
11780
 
11500
- // node_modules/zod/v4/locales/index.js
11781
+ // node_modules/.pnpm/zod@3.25.76/node_modules/zod/v4/locales/index.js
11501
11782
  var init_locales = () => {};
11502
11783
 
11503
- // node_modules/zod/v4/core/registries.js
11784
+ // node_modules/.pnpm/zod@3.25.76/node_modules/zod/v4/core/registries.js
11504
11785
  class $ZodRegistry {
11505
11786
  constructor() {
11506
11787
  this._map = new Map;
@@ -11553,7 +11834,7 @@ var init_registries = __esm(() => {
11553
11834
  globalRegistry = /* @__PURE__ */ registry();
11554
11835
  });
11555
11836
 
11556
- // node_modules/zod/v4/core/api.js
11837
+ // node_modules/.pnpm/zod@3.25.76/node_modules/zod/v4/core/api.js
11557
11838
  function _string(Class2, params) {
11558
11839
  return new Class2({
11559
11840
  type: "string",
@@ -11993,10 +12274,10 @@ var init_api = __esm(() => {
11993
12274
  init_util();
11994
12275
  });
11995
12276
 
11996
- // node_modules/zod/v4/core/function.js
12277
+ // node_modules/.pnpm/zod@3.25.76/node_modules/zod/v4/core/function.js
11997
12278
  var init_function = () => {};
11998
12279
 
11999
- // node_modules/zod/v4/core/to-json-schema.js
12280
+ // node_modules/.pnpm/zod@3.25.76/node_modules/zod/v4/core/to-json-schema.js
12000
12281
  class JSONSchemaGenerator {
12001
12282
  constructor(params) {
12002
12283
  this.counter = 0;
@@ -12753,10 +13034,10 @@ var init_to_json_schema = __esm(() => {
12753
13034
  init_util();
12754
13035
  });
12755
13036
 
12756
- // node_modules/zod/v4/core/json-schema.js
13037
+ // node_modules/.pnpm/zod@3.25.76/node_modules/zod/v4/core/json-schema.js
12757
13038
  var init_json_schema = () => {};
12758
13039
 
12759
- // node_modules/zod/v4/core/index.js
13040
+ // node_modules/.pnpm/zod@3.25.76/node_modules/zod/v4/core/index.js
12760
13041
  var init_core2 = __esm(() => {
12761
13042
  init_util();
12762
13043
  init_regexes();
@@ -12774,12 +13055,12 @@ var init_core2 = __esm(() => {
12774
13055
  init_to_json_schema();
12775
13056
  });
12776
13057
 
12777
- // node_modules/zod/v4/classic/checks.js
13058
+ // node_modules/.pnpm/zod@3.25.76/node_modules/zod/v4/classic/checks.js
12778
13059
  var init_checks2 = __esm(() => {
12779
13060
  init_core2();
12780
13061
  });
12781
13062
 
12782
- // node_modules/zod/v4/classic/iso.js
13063
+ // node_modules/.pnpm/zod@3.25.76/node_modules/zod/v4/classic/iso.js
12783
13064
  var exports_iso = {};
12784
13065
  __export(exports_iso, {
12785
13066
  time: () => time2,
@@ -12825,7 +13106,7 @@ var init_iso = __esm(() => {
12825
13106
  });
12826
13107
  });
12827
13108
 
12828
- // node_modules/zod/v4/classic/errors.js
13109
+ // node_modules/.pnpm/zod@3.25.76/node_modules/zod/v4/classic/errors.js
12829
13110
  var initializer2 = (inst, issues) => {
12830
13111
  $ZodError.init(inst, issues);
12831
13112
  inst.name = "ZodError";
@@ -12858,7 +13139,7 @@ var init_errors2 = __esm(() => {
12858
13139
  });
12859
13140
  });
12860
13141
 
12861
- // node_modules/zod/v4/classic/parse.js
13142
+ // node_modules/.pnpm/zod@3.25.76/node_modules/zod/v4/classic/parse.js
12862
13143
  var parse3, parseAsync2, safeParse2, safeParseAsync2;
12863
13144
  var init_parse2 = __esm(() => {
12864
13145
  init_core2();
@@ -12869,7 +13150,7 @@ var init_parse2 = __esm(() => {
12869
13150
  safeParseAsync2 = /* @__PURE__ */ _safeParseAsync(ZodRealError);
12870
13151
  });
12871
13152
 
12872
- // node_modules/zod/v4/classic/schemas.js
13153
+ // node_modules/.pnpm/zod@3.25.76/node_modules/zod/v4/classic/schemas.js
12873
13154
  function string2(params) {
12874
13155
  return _string(ZodString, params);
12875
13156
  }
@@ -13483,13 +13764,13 @@ var init_schemas2 = __esm(() => {
13483
13764
  });
13484
13765
  });
13485
13766
 
13486
- // node_modules/zod/v4/classic/compat.js
13767
+ // node_modules/.pnpm/zod@3.25.76/node_modules/zod/v4/classic/compat.js
13487
13768
  var init_compat = () => {};
13488
13769
 
13489
- // node_modules/zod/v4/classic/coerce.js
13770
+ // node_modules/.pnpm/zod@3.25.76/node_modules/zod/v4/classic/coerce.js
13490
13771
  var init_coerce = () => {};
13491
13772
 
13492
- // node_modules/zod/v4/classic/external.js
13773
+ // node_modules/.pnpm/zod@3.25.76/node_modules/zod/v4/classic/external.js
13493
13774
  var init_external = __esm(() => {
13494
13775
  init_core2();
13495
13776
  init_core2();
@@ -13505,17 +13786,17 @@ var init_external = __esm(() => {
13505
13786
  config(en_default());
13506
13787
  });
13507
13788
 
13508
- // node_modules/zod/v4/classic/index.js
13789
+ // node_modules/.pnpm/zod@3.25.76/node_modules/zod/v4/classic/index.js
13509
13790
  var init_classic = __esm(() => {
13510
13791
  init_external();
13511
13792
  });
13512
13793
 
13513
- // node_modules/zod/v4/index.js
13794
+ // node_modules/.pnpm/zod@3.25.76/node_modules/zod/v4/index.js
13514
13795
  var init_v4 = __esm(() => {
13515
13796
  init_classic();
13516
13797
  });
13517
13798
 
13518
- // node_modules/@modelcontextprotocol/sdk/dist/esm/types.js
13799
+ // node_modules/.pnpm/@modelcontextprotocol+sdk@1.30.0_zod@3.25.76/node_modules/@modelcontextprotocol/sdk/dist/esm/types.js
13519
13800
  function assertCompleteRequestPrompt(request) {
13520
13801
  if (request.params.ref.type !== "ref/prompt") {
13521
13802
  throw new TypeError(`Expected CompleteRequestPrompt, but got ${request.params.ref.type}`);
@@ -13534,7 +13815,7 @@ var init_types2 = __esm(() => {
13534
13815
  ProgressTokenSchema = union([string2(), number2().int()]);
13535
13816
  CursorSchema = string2();
13536
13817
  TaskCreationParamsSchema = looseObject({
13537
- ttl: union([number2(), _null3()]).optional(),
13818
+ ttl: number2().optional(),
13538
13819
  pollInterval: number2().optional()
13539
13820
  });
13540
13821
  TaskMetadataSchema = object({
@@ -13682,7 +13963,8 @@ var init_types2 = __esm(() => {
13682
13963
  roots: object({
13683
13964
  listChanged: boolean2().optional()
13684
13965
  }).optional(),
13685
- tasks: ClientTasksCapabilitySchema.optional()
13966
+ tasks: ClientTasksCapabilitySchema.optional(),
13967
+ extensions: record(string2(), AssertObjectSchema).optional()
13686
13968
  });
13687
13969
  InitializeRequestParamsSchema = BaseRequestParamsSchema.extend({
13688
13970
  protocolVersion: string2(),
@@ -13707,7 +13989,8 @@ var init_types2 = __esm(() => {
13707
13989
  tools: object({
13708
13990
  listChanged: boolean2().optional()
13709
13991
  }).optional(),
13710
- tasks: ServerTasksCapabilitySchema.optional()
13992
+ tasks: ServerTasksCapabilitySchema.optional(),
13993
+ extensions: record(string2(), AssertObjectSchema).optional()
13711
13994
  });
13712
13995
  InitializeResultSchema = ResultSchema.extend({
13713
13996
  protocolVersion: string2(),
@@ -13822,6 +14105,7 @@ var init_types2 = __esm(() => {
13822
14105
  uri: string2(),
13823
14106
  description: optional(string2()),
13824
14107
  mimeType: optional(string2()),
14108
+ size: optional(number2()),
13825
14109
  annotations: AnnotationsSchema.optional(),
13826
14110
  _meta: optional(looseObject({}))
13827
14111
  });
@@ -14350,17 +14634,19 @@ var init_types2 = __esm(() => {
14350
14634
  };
14351
14635
  });
14352
14636
 
14353
- // node_modules/@modelcontextprotocol/sdk/dist/esm/server/webStandardStreamableHttp.js
14637
+ // node_modules/.pnpm/@modelcontextprotocol+sdk@1.30.0_zod@3.25.76/node_modules/@modelcontextprotocol/sdk/dist/esm/server/webStandardStreamableHttp.js
14354
14638
  class WebStandardStreamableHTTPServerTransport {
14355
14639
  constructor(options = {}) {
14356
14640
  this._started = false;
14357
14641
  this._hasHandledRequest = false;
14358
14642
  this._streamMapping = new Map;
14359
14643
  this._requestToStreamMapping = new Map;
14644
+ this._resumableStreams = new Set;
14360
14645
  this._requestResponseMap = new Map;
14361
14646
  this._initialized = false;
14362
14647
  this._enableJsonResponse = false;
14363
14648
  this._standaloneSseStreamId = "_GET_stream";
14649
+ this._closed = false;
14364
14650
  this.sessionIdGenerator = options.sessionIdGenerator;
14365
14651
  this._enableJsonResponse = options.enableJsonResponse ?? false;
14366
14652
  this._eventStore = options.eventStore;
@@ -14370,6 +14656,22 @@ class WebStandardStreamableHTTPServerTransport {
14370
14656
  this._allowedOrigins = options.allowedOrigins;
14371
14657
  this._enableDnsRebindingProtection = options.enableDnsRebindingProtection ?? false;
14372
14658
  this._retryInterval = options.retryInterval;
14659
+ this._keepAliveMs = options.keepAliveMs ?? DEFAULT_SSE_KEEP_ALIVE_MS;
14660
+ }
14661
+ startKeepAlive(controller, encoder) {
14662
+ if (this._closed)
14663
+ return;
14664
+ const timer = armSseKeepAlive(this._keepAliveMs, () => {
14665
+ try {
14666
+ controller.enqueue(encoder.encode(`: keepalive
14667
+
14668
+ `));
14669
+ } catch {
14670
+ if (timer !== undefined)
14671
+ clearInterval(timer);
14672
+ }
14673
+ });
14674
+ return timer;
14373
14675
  }
14374
14676
  async start() {
14375
14677
  if (this._started) {
@@ -14417,6 +14719,9 @@ class WebStandardStreamableHTTPServerTransport {
14417
14719
  return;
14418
14720
  }
14419
14721
  async handleRequest(req, options) {
14722
+ if (this._closed) {
14723
+ return this.createJsonErrorResponse(404, -32001, "Session not found");
14724
+ }
14420
14725
  if (!this.sessionIdGenerator && this._hasHandledRequest) {
14421
14726
  throw new Error("Stateless transport cannot be reused across requests. Create a new transport per request.");
14422
14727
  }
@@ -14456,6 +14761,7 @@ data:
14456
14761
  `;
14457
14762
  }
14458
14763
  controller.enqueue(encoder.encode(primingEvent));
14764
+ this._resumableStreams.add(streamId);
14459
14765
  }
14460
14766
  async handleGetRequest(req) {
14461
14767
  const acceptHeader = req.headers.get("accept");
@@ -14483,18 +14789,25 @@ data:
14483
14789
  }
14484
14790
  const encoder = new TextEncoder;
14485
14791
  let streamController;
14792
+ let keepAliveTimer = undefined;
14486
14793
  const readable = new ReadableStream({
14487
14794
  start: (controller) => {
14488
14795
  streamController = controller;
14489
14796
  },
14490
14797
  cancel: () => {
14491
- this._streamMapping.delete(this._standaloneSseStreamId);
14798
+ if (keepAliveTimer !== undefined) {
14799
+ clearInterval(keepAliveTimer);
14800
+ }
14801
+ if (this._streamMapping.get(this._standaloneSseStreamId)?.controller === streamController) {
14802
+ this._streamMapping.delete(this._standaloneSseStreamId);
14803
+ }
14492
14804
  }
14493
14805
  });
14494
14806
  const headers = {
14495
14807
  "Content-Type": "text/event-stream",
14496
14808
  "Cache-Control": "no-cache, no-transform",
14497
- Connection: "keep-alive"
14809
+ Connection: "keep-alive",
14810
+ "X-Accel-Buffering": "no"
14498
14811
  };
14499
14812
  if (this.sessionId !== undefined) {
14500
14813
  headers["mcp-session-id"] = this.sessionId;
@@ -14503,12 +14816,16 @@ data:
14503
14816
  controller: streamController,
14504
14817
  encoder,
14505
14818
  cleanup: () => {
14819
+ if (keepAliveTimer !== undefined) {
14820
+ clearInterval(keepAliveTimer);
14821
+ }
14506
14822
  this._streamMapping.delete(this._standaloneSseStreamId);
14507
14823
  try {
14508
14824
  streamController.close();
14509
14825
  } catch {}
14510
14826
  }
14511
14827
  });
14828
+ keepAliveTimer = this.startKeepAlive(streamController, encoder);
14512
14829
  return new Response(readable, { headers });
14513
14830
  }
14514
14831
  async replayEvents(lastEventId) {
@@ -14532,20 +14849,33 @@ data:
14532
14849
  const headers = {
14533
14850
  "Content-Type": "text/event-stream",
14534
14851
  "Cache-Control": "no-cache, no-transform",
14535
- Connection: "keep-alive"
14852
+ Connection: "keep-alive",
14853
+ "X-Accel-Buffering": "no"
14536
14854
  };
14537
14855
  if (this.sessionId !== undefined) {
14538
14856
  headers["mcp-session-id"] = this.sessionId;
14539
14857
  }
14540
14858
  const encoder = new TextEncoder;
14541
14859
  let streamController;
14860
+ let keepAliveTimer = undefined;
14861
+ let replayedStreamId = undefined;
14862
+ let cancelled = false;
14542
14863
  const readable = new ReadableStream({
14543
14864
  start: (controller) => {
14544
14865
  streamController = controller;
14545
14866
  },
14546
- cancel: () => {}
14867
+ cancel: () => {
14868
+ cancelled = true;
14869
+ if (keepAliveTimer !== undefined) {
14870
+ clearInterval(keepAliveTimer);
14871
+ }
14872
+ if (replayedStreamId !== undefined && this._streamMapping.get(replayedStreamId)?.controller === streamController) {
14873
+ this._streamMapping.delete(replayedStreamId);
14874
+ }
14875
+ }
14547
14876
  });
14548
- const replayedStreamId = await this._eventStore.replayEventsAfter(lastEventId, {
14877
+ const replayedEventIds = new Set;
14878
+ replayedStreamId = await this._eventStore.replayEventsAfter(lastEventId, {
14549
14879
  send: async (eventId, message) => {
14550
14880
  const success = this.writeSSEEvent(streamController, encoder, message, eventId);
14551
14881
  if (!success) {
@@ -14553,19 +14883,34 @@ data:
14553
14883
  try {
14554
14884
  streamController.close();
14555
14885
  } catch {}
14886
+ } else {
14887
+ replayedEventIds.add(eventId);
14556
14888
  }
14557
14889
  }
14558
14890
  });
14891
+ if (this._closed || cancelled) {
14892
+ try {
14893
+ streamController.close();
14894
+ } catch {}
14895
+ return this.createJsonErrorResponse(404, -32001, "Session not found");
14896
+ }
14897
+ this._streamMapping.get(replayedStreamId)?.cleanup();
14559
14898
  this._streamMapping.set(replayedStreamId, {
14560
14899
  controller: streamController,
14561
14900
  encoder,
14901
+ replayedEventIds,
14562
14902
  cleanup: () => {
14903
+ if (keepAliveTimer !== undefined) {
14904
+ clearInterval(keepAliveTimer);
14905
+ }
14563
14906
  this._streamMapping.delete(replayedStreamId);
14564
14907
  try {
14565
14908
  streamController.close();
14566
14909
  } catch {}
14567
14910
  }
14568
14911
  });
14912
+ this._resumableStreams.add(replayedStreamId);
14913
+ keepAliveTimer = this.startKeepAlive(streamController, encoder);
14569
14914
  return new Response(readable, { headers });
14570
14915
  } catch (error2) {
14571
14916
  this.onerror?.(error2);
@@ -14615,7 +14960,7 @@ data:
14615
14960
  return this.createJsonErrorResponse(406, -32000, "Not Acceptable: Client must accept both application/json and text/event-stream");
14616
14961
  }
14617
14962
  const ct = req.headers.get("content-type");
14618
- if (!ct || !ct.includes("application/json")) {
14963
+ if (!isJsonContentType(ct)) {
14619
14964
  this.onerror?.(new Error("Unsupported Media Type: Content-Type must be application/json"));
14620
14965
  return this.createJsonErrorResponse(415, -32000, "Unsupported Media Type: Content-Type must be application/json");
14621
14966
  }
@@ -14645,6 +14990,9 @@ data:
14645
14990
  this.onerror?.(new Error("Parse error: Invalid JSON-RPC message"));
14646
14991
  return this.createJsonErrorResponse(400, -32700, "Parse error: Invalid JSON-RPC message");
14647
14992
  }
14993
+ if (this._closed) {
14994
+ return this.createJsonErrorResponse(404, -32001, "Session not found");
14995
+ }
14648
14996
  const isInitializationRequest = messages.some(isInitializeRequest);
14649
14997
  if (isInitializationRequest) {
14650
14998
  if (this._initialized && this.sessionId !== undefined) {
@@ -14671,6 +15019,9 @@ data:
14671
15019
  return protocolError;
14672
15020
  }
14673
15021
  }
15022
+ if (this._closed) {
15023
+ return this.createJsonErrorResponse(404, -32001, "Session not found");
15024
+ }
14674
15025
  const hasRequests = messages.some(isJSONRPCRequest);
14675
15026
  if (!hasRequests) {
14676
15027
  for (const message of messages) {
@@ -14682,9 +15033,9 @@ data:
14682
15033
  const initRequest = messages.find((m) => isInitializeRequest(m));
14683
15034
  const clientProtocolVersion = initRequest ? initRequest.params.protocolVersion : req.headers.get("mcp-protocol-version") ?? DEFAULT_NEGOTIATED_PROTOCOL_VERSION;
14684
15035
  if (this._enableJsonResponse) {
14685
- return new Promise((resolve2) => {
15036
+ return new Promise((resolve3) => {
14686
15037
  this._streamMapping.set(streamId, {
14687
- resolveJson: resolve2,
15038
+ resolveJson: resolve3,
14688
15039
  cleanup: () => {
14689
15040
  this._streamMapping.delete(streamId);
14690
15041
  }
@@ -14701,18 +15052,25 @@ data:
14701
15052
  }
14702
15053
  const encoder = new TextEncoder;
14703
15054
  let streamController;
15055
+ let keepAliveTimer = undefined;
14704
15056
  const readable = new ReadableStream({
14705
15057
  start: (controller) => {
14706
15058
  streamController = controller;
14707
15059
  },
14708
15060
  cancel: () => {
14709
- this._streamMapping.delete(streamId);
15061
+ if (keepAliveTimer !== undefined) {
15062
+ clearInterval(keepAliveTimer);
15063
+ }
15064
+ if (this._streamMapping.get(streamId)?.controller === streamController) {
15065
+ this._streamMapping.delete(streamId);
15066
+ }
14710
15067
  }
14711
15068
  });
14712
15069
  const headers = {
14713
15070
  "Content-Type": "text/event-stream",
14714
- "Cache-Control": "no-cache",
14715
- Connection: "keep-alive"
15071
+ "Cache-Control": "no-cache, no-transform",
15072
+ Connection: "keep-alive",
15073
+ "X-Accel-Buffering": "no"
14716
15074
  };
14717
15075
  if (this.sessionId !== undefined) {
14718
15076
  headers["mcp-session-id"] = this.sessionId;
@@ -14723,6 +15081,9 @@ data:
14723
15081
  controller: streamController,
14724
15082
  encoder,
14725
15083
  cleanup: () => {
15084
+ if (keepAliveTimer !== undefined) {
15085
+ clearInterval(keepAliveTimer);
15086
+ }
14726
15087
  this._streamMapping.delete(streamId);
14727
15088
  try {
14728
15089
  streamController.close();
@@ -14732,19 +15093,33 @@ data:
14732
15093
  this._requestToStreamMapping.set(message.id, streamId);
14733
15094
  }
14734
15095
  }
14735
- await this.writePrimingEvent(streamController, encoder, streamId, clientProtocolVersion);
14736
- for (const message of messages) {
14737
- let closeSSEStream;
14738
- let closeStandaloneSSEStream;
14739
- if (isJSONRPCRequest(message) && this._eventStore && clientProtocolVersion >= "2025-11-25") {
14740
- closeSSEStream = () => {
14741
- this.closeSSEStream(message.id);
14742
- };
14743
- closeStandaloneSSEStream = () => {
14744
- this.closeStandaloneSSEStream();
14745
- };
15096
+ try {
15097
+ await this.writePrimingEvent(streamController, encoder, streamId, clientProtocolVersion);
15098
+ for (const message of messages) {
15099
+ let closeSSEStream;
15100
+ let closeStandaloneSSEStream;
15101
+ if (isJSONRPCRequest(message) && this._eventStore && clientProtocolVersion >= "2025-11-25") {
15102
+ closeSSEStream = () => {
15103
+ this.closeSSEStream(message.id);
15104
+ };
15105
+ closeStandaloneSSEStream = () => {
15106
+ this.closeStandaloneSSEStream();
15107
+ };
15108
+ }
15109
+ this.onmessage?.(message, { authInfo: options?.authInfo, requestInfo, closeSSEStream, closeStandaloneSSEStream });
15110
+ }
15111
+ } catch (error2) {
15112
+ this._streamMapping.get(streamId)?.cleanup();
15113
+ this._resumableStreams.delete(streamId);
15114
+ for (const message of messages) {
15115
+ if (isJSONRPCRequest(message)) {
15116
+ this._requestToStreamMapping.delete(message.id);
15117
+ }
14746
15118
  }
14747
- this.onmessage?.(message, { authInfo: options?.authInfo, requestInfo, closeSSEStream, closeStandaloneSSEStream });
15119
+ throw error2;
15120
+ }
15121
+ if (this._streamMapping.get(streamId)?.controller === streamController) {
15122
+ keepAliveTimer = this.startKeepAlive(streamController, encoder);
14748
15123
  }
14749
15124
  return new Response(readable, { status: 200, headers });
14750
15125
  } catch (error2) {
@@ -14761,9 +15136,12 @@ data:
14761
15136
  if (protocolError) {
14762
15137
  return protocolError;
14763
15138
  }
14764
- await Promise.resolve(this._onsessionclosed?.(this.sessionId));
14765
- await this.close();
14766
- return new Response(null, { status: 200 });
15139
+ try {
15140
+ await Promise.resolve(this._onsessionclosed?.(this.sessionId));
15141
+ return new Response(null, { status: 200 });
15142
+ } finally {
15143
+ await this.close();
15144
+ }
14767
15145
  }
14768
15146
  validateSession(req) {
14769
15147
  if (this.sessionIdGenerator === undefined) {
@@ -14793,11 +15171,16 @@ data:
14793
15171
  return;
14794
15172
  }
14795
15173
  async close() {
15174
+ if (this._closed) {
15175
+ return;
15176
+ }
15177
+ this._closed = true;
14796
15178
  this._streamMapping.forEach(({ cleanup }) => {
14797
15179
  cleanup();
14798
15180
  });
14799
15181
  this._streamMapping.clear();
14800
15182
  this._requestResponseMap.clear();
15183
+ this._resumableStreams.clear();
14801
15184
  this.onclose?.();
14802
15185
  }
14803
15186
  closeSSEStream(requestId) {
@@ -14832,7 +15215,7 @@ data:
14832
15215
  if (standaloneSse === undefined) {
14833
15216
  return;
14834
15217
  }
14835
- if (standaloneSse.controller && standaloneSse.encoder) {
15218
+ if (standaloneSse.controller && standaloneSse.encoder && (eventId === undefined || !standaloneSse.replayedEventIds?.has(eventId))) {
14836
15219
  this.writeSSEEvent(standaloneSse.controller, standaloneSse.encoder, message, eventId);
14837
15220
  }
14838
15221
  return;
@@ -14841,13 +15224,19 @@ data:
14841
15224
  if (!streamId) {
14842
15225
  throw new Error(`No connection established for request ID: ${String(requestId)}`);
14843
15226
  }
14844
- const stream = this._streamMapping.get(streamId);
14845
- if (!this._enableJsonResponse && stream?.controller && stream?.encoder) {
15227
+ let stream = this._streamMapping.get(streamId);
15228
+ if (!this._enableJsonResponse) {
14846
15229
  let eventId;
14847
15230
  if (this._eventStore) {
14848
15231
  eventId = await this._eventStore.storeEvent(streamId, message);
15232
+ stream = this._streamMapping.get(streamId);
15233
+ }
15234
+ if (stream?.controller && stream?.encoder && (eventId === undefined || !stream.replayedEventIds?.has(eventId))) {
15235
+ const written = this.writeSSEEvent(stream.controller, stream.encoder, message, eventId);
15236
+ if (written && eventId !== undefined) {
15237
+ this._resumableStreams.add(streamId);
15238
+ }
14849
15239
  }
14850
- this.writeSSEEvent(stream.controller, stream.encoder, message, eventId);
14851
15240
  }
14852
15241
  if (isJSONRPCResultResponse(message) || isJSONRPCErrorResponse(message)) {
14853
15242
  this._requestResponseMap.set(requestId, message);
@@ -14855,6 +15244,25 @@ data:
14855
15244
  const allResponsesReady = relatedIds.every((id) => this._requestResponseMap.has(id));
14856
15245
  if (allResponsesReady) {
14857
15246
  if (!stream) {
15247
+ if (this._closed) {
15248
+ for (const id of relatedIds) {
15249
+ this._requestResponseMap.delete(id);
15250
+ this._requestToStreamMapping.delete(id);
15251
+ }
15252
+ return;
15253
+ }
15254
+ if (!this._enableJsonResponse && this._eventStore && this._resumableStreams.has(streamId)) {
15255
+ for (const id of relatedIds) {
15256
+ this._requestResponseMap.delete(id);
15257
+ this._requestToStreamMapping.delete(id);
15258
+ }
15259
+ this._resumableStreams.delete(streamId);
15260
+ return;
15261
+ }
15262
+ for (const id of relatedIds) {
15263
+ this._requestResponseMap.delete(id);
15264
+ this._requestToStreamMapping.delete(id);
15265
+ }
14858
15266
  throw new Error(`No connection established for request ID: ${String(requestId)}`);
14859
15267
  }
14860
15268
  if (this._enableJsonResponse && stream.resolveJson) {
@@ -14877,11 +15285,14 @@ data:
14877
15285
  this._requestResponseMap.delete(id);
14878
15286
  this._requestToStreamMapping.delete(id);
14879
15287
  }
15288
+ this._resumableStreams.delete(streamId);
14880
15289
  }
14881
15290
  }
14882
15291
  }
14883
15292
  }
14884
15293
  var init_webStandardStreamableHttp = __esm(() => {
15294
+ init_mediaType();
15295
+ init_sseKeepAlive();
14885
15296
  init_types2();
14886
15297
  });
14887
15298
 
@@ -14934,7 +15345,7 @@ var init_http = __esm(() => {
14934
15345
  init_webStandardStreamableHttp();
14935
15346
  });
14936
15347
 
14937
- // node_modules/zod/v3/helpers/util.js
15348
+ // node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/helpers/util.js
14938
15349
  var util, objectUtil, ZodParsedType, getParsedType2 = (data) => {
14939
15350
  const t = typeof data;
14940
15351
  switch (t) {
@@ -15065,7 +15476,7 @@ var init_util2 = __esm(() => {
15065
15476
  ]);
15066
15477
  });
15067
15478
 
15068
- // node_modules/zod/v3/ZodError.js
15479
+ // node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/ZodError.js
15069
15480
  var ZodIssueCode, quotelessJson = (obj) => {
15070
15481
  const json = JSON.stringify(obj, null, 2);
15071
15482
  return json.replace(/"([^"]+)":/g, "$1:");
@@ -15186,7 +15597,7 @@ var init_ZodError = __esm(() => {
15186
15597
  };
15187
15598
  });
15188
15599
 
15189
- // node_modules/zod/v3/locales/en.js
15600
+ // node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/locales/en.js
15190
15601
  var errorMap = (issue2, _ctx) => {
15191
15602
  let message;
15192
15603
  switch (issue2.code) {
@@ -15293,7 +15704,7 @@ var init_en2 = __esm(() => {
15293
15704
  en_default2 = errorMap;
15294
15705
  });
15295
15706
 
15296
- // node_modules/zod/v3/errors.js
15707
+ // node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/errors.js
15297
15708
  function setErrorMap(map) {
15298
15709
  overrideErrorMap = map;
15299
15710
  }
@@ -15306,7 +15717,7 @@ var init_errors3 = __esm(() => {
15306
15717
  overrideErrorMap = en_default2;
15307
15718
  });
15308
15719
 
15309
- // node_modules/zod/v3/helpers/parseUtil.js
15720
+ // node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/helpers/parseUtil.js
15310
15721
  function addIssueToContext(ctx, issueData) {
15311
15722
  const overrideMap = getErrorMap();
15312
15723
  const issue2 = makeIssue({
@@ -15411,10 +15822,10 @@ var init_parseUtil = __esm(() => {
15411
15822
  });
15412
15823
  });
15413
15824
 
15414
- // node_modules/zod/v3/helpers/typeAliases.js
15825
+ // node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/helpers/typeAliases.js
15415
15826
  var init_typeAliases = () => {};
15416
15827
 
15417
- // node_modules/zod/v3/helpers/errorUtil.js
15828
+ // node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/helpers/errorUtil.js
15418
15829
  var errorUtil;
15419
15830
  var init_errorUtil = __esm(() => {
15420
15831
  (function(errorUtil2) {
@@ -15423,7 +15834,7 @@ var init_errorUtil = __esm(() => {
15423
15834
  })(errorUtil || (errorUtil = {}));
15424
15835
  });
15425
15836
 
15426
- // node_modules/zod/v3/types.js
15837
+ // node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/types.js
15427
15838
  class ParseInputLazyPath {
15428
15839
  constructor(parent, value, path, key) {
15429
15840
  this._cachedPath = [];
@@ -18774,7 +19185,7 @@ var init_types3 = __esm(() => {
18774
19185
  NEVER2 = INVALID;
18775
19186
  });
18776
19187
 
18777
- // node_modules/zod/v3/external.js
19188
+ // node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/external.js
18778
19189
  var exports_external = {};
18779
19190
  __export(exports_external, {
18780
19191
  void: () => voidType,
@@ -18894,17 +19305,17 @@ var init_external2 = __esm(() => {
18894
19305
  init_ZodError();
18895
19306
  });
18896
19307
 
18897
- // node_modules/zod/v3/index.js
19308
+ // node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/index.js
18898
19309
  var init_v3 = __esm(() => {
18899
19310
  init_external2();
18900
19311
  });
18901
19312
 
18902
- // node_modules/zod/v4/mini/parse.js
19313
+ // node_modules/.pnpm/zod@3.25.76/node_modules/zod/v4/mini/parse.js
18903
19314
  var init_parse3 = __esm(() => {
18904
19315
  init_core2();
18905
19316
  });
18906
19317
 
18907
- // node_modules/zod/v4/mini/schemas.js
19318
+ // node_modules/.pnpm/zod@3.25.76/node_modules/zod/v4/mini/schemas.js
18908
19319
  function object2(shape, params) {
18909
19320
  const def = {
18910
19321
  type: "object",
@@ -18953,16 +19364,16 @@ var init_schemas3 = __esm(() => {
18953
19364
  });
18954
19365
  });
18955
19366
 
18956
- // node_modules/zod/v4/mini/checks.js
19367
+ // node_modules/.pnpm/zod@3.25.76/node_modules/zod/v4/mini/checks.js
18957
19368
  var init_checks3 = () => {};
18958
19369
 
18959
- // node_modules/zod/v4/mini/iso.js
19370
+ // node_modules/.pnpm/zod@3.25.76/node_modules/zod/v4/mini/iso.js
18960
19371
  var init_iso2 = () => {};
18961
19372
 
18962
- // node_modules/zod/v4/mini/coerce.js
19373
+ // node_modules/.pnpm/zod@3.25.76/node_modules/zod/v4/mini/coerce.js
18963
19374
  var init_coerce2 = () => {};
18964
19375
 
18965
- // node_modules/zod/v4/mini/external.js
19376
+ // node_modules/.pnpm/zod@3.25.76/node_modules/zod/v4/mini/external.js
18966
19377
  var init_external3 = __esm(() => {
18967
19378
  init_core2();
18968
19379
  init_core2();
@@ -18974,17 +19385,17 @@ var init_external3 = __esm(() => {
18974
19385
  init_checks3();
18975
19386
  });
18976
19387
 
18977
- // node_modules/zod/v4/mini/index.js
19388
+ // node_modules/.pnpm/zod@3.25.76/node_modules/zod/v4/mini/index.js
18978
19389
  var init_mini = __esm(() => {
18979
19390
  init_external3();
18980
19391
  });
18981
19392
 
18982
- // node_modules/zod/v4-mini/index.js
19393
+ // node_modules/.pnpm/zod@3.25.76/node_modules/zod/v4-mini/index.js
18983
19394
  var init_v4_mini = __esm(() => {
18984
19395
  init_mini();
18985
19396
  });
18986
19397
 
18987
- // node_modules/@modelcontextprotocol/sdk/dist/esm/server/zod-compat.js
19398
+ // node_modules/.pnpm/@modelcontextprotocol+sdk@1.30.0_zod@3.25.76/node_modules/@modelcontextprotocol/sdk/dist/esm/server/zod-compat.js
18988
19399
  function isZ4Schema(s) {
18989
19400
  const schema = s;
18990
19401
  return !!schema._zod;
@@ -19068,17 +19479,34 @@ function normalizeObjectSchema(schema) {
19068
19479
  }
19069
19480
  return;
19070
19481
  }
19482
+ function getDotPath(path) {
19483
+ if (path.length === 0) {
19484
+ return "object root";
19485
+ }
19486
+ return path.reduce((acc, seg, index) => {
19487
+ if (index === 0) {
19488
+ return String(seg);
19489
+ }
19490
+ if (typeof seg === "number") {
19491
+ return `${acc}[${seg}]`;
19492
+ }
19493
+ return `${acc}.${seg}`;
19494
+ }, "");
19495
+ }
19071
19496
  function getParseErrorMessage(error2) {
19072
19497
  if (error2 && typeof error2 === "object") {
19498
+ if ("issues" in error2 && Array.isArray(error2.issues) && error2.issues.length > 0) {
19499
+ return error2.issues.map((i) => {
19500
+ if (!i.path?.length) {
19501
+ return i.message;
19502
+ }
19503
+ return `${i.message} at ${getDotPath(i.path)}`;
19504
+ }).join(`
19505
+ `);
19506
+ }
19073
19507
  if ("message" in error2 && typeof error2.message === "string") {
19074
19508
  return error2.message;
19075
19509
  }
19076
- if ("issues" in error2 && Array.isArray(error2.issues) && error2.issues.length > 0) {
19077
- const firstIssue = error2.issues[0];
19078
- if (firstIssue && typeof firstIssue === "object" && "message" in firstIssue) {
19079
- return String(firstIssue.message);
19080
- }
19081
- }
19082
19510
  try {
19083
19511
  return JSON.stringify(error2);
19084
19512
  } catch {
@@ -19132,12 +19560,12 @@ var init_zod_compat = __esm(() => {
19132
19560
  init_v4_mini();
19133
19561
  });
19134
19562
 
19135
- // node_modules/@modelcontextprotocol/sdk/dist/esm/experimental/tasks/interfaces.js
19563
+ // node_modules/.pnpm/@modelcontextprotocol+sdk@1.30.0_zod@3.25.76/node_modules/@modelcontextprotocol/sdk/dist/esm/experimental/tasks/interfaces.js
19136
19564
  function isTerminal(status) {
19137
19565
  return status === "completed" || status === "failed" || status === "cancelled";
19138
19566
  }
19139
19567
 
19140
- // node_modules/zod-to-json-schema/dist/esm/Options.js
19568
+ // node_modules/.pnpm/zod-to-json-schema@3.25.2_zod@3.25.76/node_modules/zod-to-json-schema/dist/esm/Options.js
19141
19569
  var ignoreOverride, defaultOptions, getDefaultOptions = (options) => typeof options === "string" ? {
19142
19570
  ...defaultOptions,
19143
19571
  name: options
@@ -19173,7 +19601,7 @@ var init_Options = __esm(() => {
19173
19601
  };
19174
19602
  });
19175
19603
 
19176
- // node_modules/zod-to-json-schema/dist/esm/Refs.js
19604
+ // node_modules/.pnpm/zod-to-json-schema@3.25.2_zod@3.25.76/node_modules/zod-to-json-schema/dist/esm/Refs.js
19177
19605
  var getRefs = (options) => {
19178
19606
  const _options = getDefaultOptions(options);
19179
19607
  const currentPath = _options.name !== undefined ? [..._options.basePath, _options.definitionPath, _options.name] : _options.basePath;
@@ -19196,7 +19624,7 @@ var init_Refs = __esm(() => {
19196
19624
  init_Options();
19197
19625
  });
19198
19626
 
19199
- // node_modules/zod-to-json-schema/dist/esm/errorMessages.js
19627
+ // node_modules/.pnpm/zod-to-json-schema@3.25.2_zod@3.25.76/node_modules/zod-to-json-schema/dist/esm/errorMessages.js
19200
19628
  function addErrorMessage(res, key, errorMessage, refs) {
19201
19629
  if (!refs?.errorMessages)
19202
19630
  return;
@@ -19212,7 +19640,7 @@ function setResponseValueAndErrors(res, key, value, errorMessage, refs) {
19212
19640
  addErrorMessage(res, key, errorMessage, refs);
19213
19641
  }
19214
19642
 
19215
- // node_modules/zod-to-json-schema/dist/esm/getRelativePath.js
19643
+ // node_modules/.pnpm/zod-to-json-schema@3.25.2_zod@3.25.76/node_modules/zod-to-json-schema/dist/esm/getRelativePath.js
19216
19644
  var getRelativePath = (pathA, pathB) => {
19217
19645
  let i = 0;
19218
19646
  for (;i < pathA.length && i < pathB.length; i++) {
@@ -19222,7 +19650,7 @@ var getRelativePath = (pathA, pathB) => {
19222
19650
  return [(pathA.length - i).toString(), ...pathB.slice(i)].join("/");
19223
19651
  };
19224
19652
 
19225
- // node_modules/zod-to-json-schema/dist/esm/parsers/any.js
19653
+ // node_modules/.pnpm/zod-to-json-schema@3.25.2_zod@3.25.76/node_modules/zod-to-json-schema/dist/esm/parsers/any.js
19226
19654
  function parseAnyDef(refs) {
19227
19655
  if (refs.target !== "openAi") {
19228
19656
  return {};
@@ -19239,7 +19667,7 @@ function parseAnyDef(refs) {
19239
19667
  }
19240
19668
  var init_any = () => {};
19241
19669
 
19242
- // node_modules/zod-to-json-schema/dist/esm/parsers/array.js
19670
+ // node_modules/.pnpm/zod-to-json-schema@3.25.2_zod@3.25.76/node_modules/zod-to-json-schema/dist/esm/parsers/array.js
19243
19671
  function parseArrayDef(def, refs) {
19244
19672
  const res = {
19245
19673
  type: "array"
@@ -19267,7 +19695,7 @@ var init_array = __esm(() => {
19267
19695
  init_parseDef();
19268
19696
  });
19269
19697
 
19270
- // node_modules/zod-to-json-schema/dist/esm/parsers/bigint.js
19698
+ // node_modules/.pnpm/zod-to-json-schema@3.25.2_zod@3.25.76/node_modules/zod-to-json-schema/dist/esm/parsers/bigint.js
19271
19699
  function parseBigintDef(def, refs) {
19272
19700
  const res = {
19273
19701
  type: "integer",
@@ -19314,14 +19742,14 @@ function parseBigintDef(def, refs) {
19314
19742
  }
19315
19743
  var init_bigint = () => {};
19316
19744
 
19317
- // node_modules/zod-to-json-schema/dist/esm/parsers/boolean.js
19745
+ // node_modules/.pnpm/zod-to-json-schema@3.25.2_zod@3.25.76/node_modules/zod-to-json-schema/dist/esm/parsers/boolean.js
19318
19746
  function parseBooleanDef() {
19319
19747
  return {
19320
19748
  type: "boolean"
19321
19749
  };
19322
19750
  }
19323
19751
 
19324
- // node_modules/zod-to-json-schema/dist/esm/parsers/branded.js
19752
+ // node_modules/.pnpm/zod-to-json-schema@3.25.2_zod@3.25.76/node_modules/zod-to-json-schema/dist/esm/parsers/branded.js
19325
19753
  function parseBrandedDef(_def, refs) {
19326
19754
  return parseDef(_def.type._def, refs);
19327
19755
  }
@@ -19329,7 +19757,7 @@ var init_branded = __esm(() => {
19329
19757
  init_parseDef();
19330
19758
  });
19331
19759
 
19332
- // node_modules/zod-to-json-schema/dist/esm/parsers/catch.js
19760
+ // node_modules/.pnpm/zod-to-json-schema@3.25.2_zod@3.25.76/node_modules/zod-to-json-schema/dist/esm/parsers/catch.js
19333
19761
  var parseCatchDef = (def, refs) => {
19334
19762
  return parseDef(def.innerType._def, refs);
19335
19763
  };
@@ -19337,7 +19765,7 @@ var init_catch = __esm(() => {
19337
19765
  init_parseDef();
19338
19766
  });
19339
19767
 
19340
- // node_modules/zod-to-json-schema/dist/esm/parsers/date.js
19768
+ // node_modules/.pnpm/zod-to-json-schema@3.25.2_zod@3.25.76/node_modules/zod-to-json-schema/dist/esm/parsers/date.js
19341
19769
  function parseDateDef(def, refs, overrideDateStrategy) {
19342
19770
  const strategy = overrideDateStrategy ?? refs.dateStrategy;
19343
19771
  if (Array.isArray(strategy)) {
@@ -19383,7 +19811,7 @@ var integerDateParser = (def, refs) => {
19383
19811
  };
19384
19812
  var init_date = () => {};
19385
19813
 
19386
- // node_modules/zod-to-json-schema/dist/esm/parsers/default.js
19814
+ // node_modules/.pnpm/zod-to-json-schema@3.25.2_zod@3.25.76/node_modules/zod-to-json-schema/dist/esm/parsers/default.js
19387
19815
  function parseDefaultDef(_def, refs) {
19388
19816
  return {
19389
19817
  ...parseDef(_def.innerType._def, refs),
@@ -19394,7 +19822,7 @@ var init_default = __esm(() => {
19394
19822
  init_parseDef();
19395
19823
  });
19396
19824
 
19397
- // node_modules/zod-to-json-schema/dist/esm/parsers/effects.js
19825
+ // node_modules/.pnpm/zod-to-json-schema@3.25.2_zod@3.25.76/node_modules/zod-to-json-schema/dist/esm/parsers/effects.js
19398
19826
  function parseEffectsDef(_def, refs) {
19399
19827
  return refs.effectStrategy === "input" ? parseDef(_def.schema._def, refs) : parseAnyDef(refs);
19400
19828
  }
@@ -19403,7 +19831,7 @@ var init_effects = __esm(() => {
19403
19831
  init_any();
19404
19832
  });
19405
19833
 
19406
- // node_modules/zod-to-json-schema/dist/esm/parsers/enum.js
19834
+ // node_modules/.pnpm/zod-to-json-schema@3.25.2_zod@3.25.76/node_modules/zod-to-json-schema/dist/esm/parsers/enum.js
19407
19835
  function parseEnumDef(def) {
19408
19836
  return {
19409
19837
  type: "string",
@@ -19411,7 +19839,7 @@ function parseEnumDef(def) {
19411
19839
  };
19412
19840
  }
19413
19841
 
19414
- // node_modules/zod-to-json-schema/dist/esm/parsers/intersection.js
19842
+ // node_modules/.pnpm/zod-to-json-schema@3.25.2_zod@3.25.76/node_modules/zod-to-json-schema/dist/esm/parsers/intersection.js
19415
19843
  function parseIntersectionDef(def, refs) {
19416
19844
  const allOf = [
19417
19845
  parseDef(def.left._def, {
@@ -19456,7 +19884,7 @@ var init_intersection = __esm(() => {
19456
19884
  init_parseDef();
19457
19885
  });
19458
19886
 
19459
- // node_modules/zod-to-json-schema/dist/esm/parsers/literal.js
19887
+ // node_modules/.pnpm/zod-to-json-schema@3.25.2_zod@3.25.76/node_modules/zod-to-json-schema/dist/esm/parsers/literal.js
19460
19888
  function parseLiteralDef(def, refs) {
19461
19889
  const parsedType2 = typeof def.value;
19462
19890
  if (parsedType2 !== "bigint" && parsedType2 !== "number" && parsedType2 !== "boolean" && parsedType2 !== "string") {
@@ -19476,7 +19904,7 @@ function parseLiteralDef(def, refs) {
19476
19904
  };
19477
19905
  }
19478
19906
 
19479
- // node_modules/zod-to-json-schema/dist/esm/parsers/string.js
19907
+ // node_modules/.pnpm/zod-to-json-schema@3.25.2_zod@3.25.76/node_modules/zod-to-json-schema/dist/esm/parsers/string.js
19480
19908
  function parseStringDef(def, refs) {
19481
19909
  const res = {
19482
19910
  type: "string"
@@ -19775,7 +20203,7 @@ var init_string = __esm(() => {
19775
20203
  ALPHA_NUMERIC = new Set("ABCDEFGHIJKLMNOPQRSTUVXYZabcdefghijklmnopqrstuvxyz0123456789");
19776
20204
  });
19777
20205
 
19778
- // node_modules/zod-to-json-schema/dist/esm/parsers/record.js
20206
+ // node_modules/.pnpm/zod-to-json-schema@3.25.2_zod@3.25.76/node_modules/zod-to-json-schema/dist/esm/parsers/record.js
19779
20207
  function parseRecordDef(def, refs) {
19780
20208
  if (refs.target === "openAi") {
19781
20209
  console.warn("Warning: OpenAI may not support records in schemas! Try an array of key-value pairs instead.");
@@ -19834,7 +20262,7 @@ var init_record = __esm(() => {
19834
20262
  init_any();
19835
20263
  });
19836
20264
 
19837
- // node_modules/zod-to-json-schema/dist/esm/parsers/map.js
20265
+ // node_modules/.pnpm/zod-to-json-schema@3.25.2_zod@3.25.76/node_modules/zod-to-json-schema/dist/esm/parsers/map.js
19838
20266
  function parseMapDef(def, refs) {
19839
20267
  if (refs.mapStrategy === "record") {
19840
20268
  return parseRecordDef(def, refs);
@@ -19864,7 +20292,7 @@ var init_map = __esm(() => {
19864
20292
  init_any();
19865
20293
  });
19866
20294
 
19867
- // node_modules/zod-to-json-schema/dist/esm/parsers/nativeEnum.js
20295
+ // node_modules/.pnpm/zod-to-json-schema@3.25.2_zod@3.25.76/node_modules/zod-to-json-schema/dist/esm/parsers/nativeEnum.js
19868
20296
  function parseNativeEnumDef(def) {
19869
20297
  const object3 = def.values;
19870
20298
  const actualKeys = Object.keys(def.values).filter((key) => {
@@ -19878,7 +20306,7 @@ function parseNativeEnumDef(def) {
19878
20306
  };
19879
20307
  }
19880
20308
 
19881
- // node_modules/zod-to-json-schema/dist/esm/parsers/never.js
20309
+ // node_modules/.pnpm/zod-to-json-schema@3.25.2_zod@3.25.76/node_modules/zod-to-json-schema/dist/esm/parsers/never.js
19882
20310
  function parseNeverDef(refs) {
19883
20311
  return refs.target === "openAi" ? undefined : {
19884
20312
  not: parseAnyDef({
@@ -19891,7 +20319,7 @@ var init_never = __esm(() => {
19891
20319
  init_any();
19892
20320
  });
19893
20321
 
19894
- // node_modules/zod-to-json-schema/dist/esm/parsers/null.js
20322
+ // node_modules/.pnpm/zod-to-json-schema@3.25.2_zod@3.25.76/node_modules/zod-to-json-schema/dist/esm/parsers/null.js
19895
20323
  function parseNullDef(refs) {
19896
20324
  return refs.target === "openApi3" ? {
19897
20325
  enum: ["null"],
@@ -19901,7 +20329,7 @@ function parseNullDef(refs) {
19901
20329
  };
19902
20330
  }
19903
20331
 
19904
- // node_modules/zod-to-json-schema/dist/esm/parsers/union.js
20332
+ // node_modules/.pnpm/zod-to-json-schema@3.25.2_zod@3.25.76/node_modules/zod-to-json-schema/dist/esm/parsers/union.js
19905
20333
  function parseUnionDef(def, refs) {
19906
20334
  if (refs.target === "openApi3")
19907
20335
  return asAnyOf(def, refs);
@@ -19972,7 +20400,7 @@ var init_union = __esm(() => {
19972
20400
  };
19973
20401
  });
19974
20402
 
19975
- // node_modules/zod-to-json-schema/dist/esm/parsers/nullable.js
20403
+ // node_modules/.pnpm/zod-to-json-schema@3.25.2_zod@3.25.76/node_modules/zod-to-json-schema/dist/esm/parsers/nullable.js
19976
20404
  function parseNullableDef(def, refs) {
19977
20405
  if (["ZodString", "ZodNumber", "ZodBigInt", "ZodBoolean", "ZodNull"].includes(def.innerType._def.typeName) && (!def.innerType._def.checks || !def.innerType._def.checks.length)) {
19978
20406
  if (refs.target === "openApi3") {
@@ -20008,7 +20436,7 @@ var init_nullable = __esm(() => {
20008
20436
  init_union();
20009
20437
  });
20010
20438
 
20011
- // node_modules/zod-to-json-schema/dist/esm/parsers/number.js
20439
+ // node_modules/.pnpm/zod-to-json-schema@3.25.2_zod@3.25.76/node_modules/zod-to-json-schema/dist/esm/parsers/number.js
20012
20440
  function parseNumberDef(def, refs) {
20013
20441
  const res = {
20014
20442
  type: "number"
@@ -20058,7 +20486,7 @@ function parseNumberDef(def, refs) {
20058
20486
  }
20059
20487
  var init_number = () => {};
20060
20488
 
20061
- // node_modules/zod-to-json-schema/dist/esm/parsers/object.js
20489
+ // node_modules/.pnpm/zod-to-json-schema@3.25.2_zod@3.25.76/node_modules/zod-to-json-schema/dist/esm/parsers/object.js
20062
20490
  function parseObjectDef(def, refs) {
20063
20491
  const forceOptionalIntoNullable = refs.target === "openAi";
20064
20492
  const result = {
@@ -20131,7 +20559,7 @@ var init_object = __esm(() => {
20131
20559
  init_parseDef();
20132
20560
  });
20133
20561
 
20134
- // node_modules/zod-to-json-schema/dist/esm/parsers/optional.js
20562
+ // node_modules/.pnpm/zod-to-json-schema@3.25.2_zod@3.25.76/node_modules/zod-to-json-schema/dist/esm/parsers/optional.js
20135
20563
  var parseOptionalDef = (def, refs) => {
20136
20564
  if (refs.currentPath.toString() === refs.propertyPath?.toString()) {
20137
20565
  return parseDef(def.innerType._def, refs);
@@ -20154,7 +20582,7 @@ var init_optional = __esm(() => {
20154
20582
  init_any();
20155
20583
  });
20156
20584
 
20157
- // node_modules/zod-to-json-schema/dist/esm/parsers/pipeline.js
20585
+ // node_modules/.pnpm/zod-to-json-schema@3.25.2_zod@3.25.76/node_modules/zod-to-json-schema/dist/esm/parsers/pipeline.js
20158
20586
  var parsePipelineDef = (def, refs) => {
20159
20587
  if (refs.pipeStrategy === "input") {
20160
20588
  return parseDef(def.in._def, refs);
@@ -20177,7 +20605,7 @@ var init_pipeline = __esm(() => {
20177
20605
  init_parseDef();
20178
20606
  });
20179
20607
 
20180
- // node_modules/zod-to-json-schema/dist/esm/parsers/promise.js
20608
+ // node_modules/.pnpm/zod-to-json-schema@3.25.2_zod@3.25.76/node_modules/zod-to-json-schema/dist/esm/parsers/promise.js
20181
20609
  function parsePromiseDef(def, refs) {
20182
20610
  return parseDef(def.type._def, refs);
20183
20611
  }
@@ -20185,7 +20613,7 @@ var init_promise = __esm(() => {
20185
20613
  init_parseDef();
20186
20614
  });
20187
20615
 
20188
- // node_modules/zod-to-json-schema/dist/esm/parsers/set.js
20616
+ // node_modules/.pnpm/zod-to-json-schema@3.25.2_zod@3.25.76/node_modules/zod-to-json-schema/dist/esm/parsers/set.js
20189
20617
  function parseSetDef(def, refs) {
20190
20618
  const items = parseDef(def.valueType._def, {
20191
20619
  ...refs,
@@ -20208,7 +20636,7 @@ var init_set = __esm(() => {
20208
20636
  init_parseDef();
20209
20637
  });
20210
20638
 
20211
- // node_modules/zod-to-json-schema/dist/esm/parsers/tuple.js
20639
+ // node_modules/.pnpm/zod-to-json-schema@3.25.2_zod@3.25.76/node_modules/zod-to-json-schema/dist/esm/parsers/tuple.js
20212
20640
  function parseTupleDef(def, refs) {
20213
20641
  if (def.rest) {
20214
20642
  return {
@@ -20239,7 +20667,7 @@ var init_tuple = __esm(() => {
20239
20667
  init_parseDef();
20240
20668
  });
20241
20669
 
20242
- // node_modules/zod-to-json-schema/dist/esm/parsers/undefined.js
20670
+ // node_modules/.pnpm/zod-to-json-schema@3.25.2_zod@3.25.76/node_modules/zod-to-json-schema/dist/esm/parsers/undefined.js
20243
20671
  function parseUndefinedDef(refs) {
20244
20672
  return {
20245
20673
  not: parseAnyDef(refs)
@@ -20249,7 +20677,7 @@ var init_undefined = __esm(() => {
20249
20677
  init_any();
20250
20678
  });
20251
20679
 
20252
- // node_modules/zod-to-json-schema/dist/esm/parsers/unknown.js
20680
+ // node_modules/.pnpm/zod-to-json-schema@3.25.2_zod@3.25.76/node_modules/zod-to-json-schema/dist/esm/parsers/unknown.js
20253
20681
  function parseUnknownDef(refs) {
20254
20682
  return parseAnyDef(refs);
20255
20683
  }
@@ -20257,7 +20685,7 @@ var init_unknown = __esm(() => {
20257
20685
  init_any();
20258
20686
  });
20259
20687
 
20260
- // node_modules/zod-to-json-schema/dist/esm/parsers/readonly.js
20688
+ // node_modules/.pnpm/zod-to-json-schema@3.25.2_zod@3.25.76/node_modules/zod-to-json-schema/dist/esm/parsers/readonly.js
20261
20689
  var parseReadonlyDef = (def, refs) => {
20262
20690
  return parseDef(def.innerType._def, refs);
20263
20691
  };
@@ -20265,7 +20693,7 @@ var init_readonly = __esm(() => {
20265
20693
  init_parseDef();
20266
20694
  });
20267
20695
 
20268
- // node_modules/zod-to-json-schema/dist/esm/selectParser.js
20696
+ // node_modules/.pnpm/zod-to-json-schema@3.25.2_zod@3.25.76/node_modules/zod-to-json-schema/dist/esm/selectParser.js
20269
20697
  var selectParser = (def, typeName, refs) => {
20270
20698
  switch (typeName) {
20271
20699
  case ZodFirstPartyTypeKind.ZodString:
@@ -20371,7 +20799,7 @@ var init_selectParser = __esm(() => {
20371
20799
  init_readonly();
20372
20800
  });
20373
20801
 
20374
- // node_modules/zod-to-json-schema/dist/esm/parseDef.js
20802
+ // node_modules/.pnpm/zod-to-json-schema@3.25.2_zod@3.25.76/node_modules/zod-to-json-schema/dist/esm/parseDef.js
20375
20803
  function parseDef(def, refs, forceResolution = false) {
20376
20804
  const seenItem = refs.seen.get(def);
20377
20805
  if (refs.override) {
@@ -20431,10 +20859,10 @@ var init_parseDef = __esm(() => {
20431
20859
  init_any();
20432
20860
  });
20433
20861
 
20434
- // node_modules/zod-to-json-schema/dist/esm/parseTypes.js
20862
+ // node_modules/.pnpm/zod-to-json-schema@3.25.2_zod@3.25.76/node_modules/zod-to-json-schema/dist/esm/parseTypes.js
20435
20863
  var init_parseTypes = () => {};
20436
20864
 
20437
- // node_modules/zod-to-json-schema/dist/esm/zodToJsonSchema.js
20865
+ // node_modules/.pnpm/zod-to-json-schema@3.25.2_zod@3.25.76/node_modules/zod-to-json-schema/dist/esm/zodToJsonSchema.js
20438
20866
  var zodToJsonSchema = (schema, options) => {
20439
20867
  const refs = getRefs(options);
20440
20868
  let definitions = typeof options === "object" && options.definitions ? Object.entries(options.definitions).reduce((acc, [name2, schema2]) => ({
@@ -20500,7 +20928,7 @@ var init_zodToJsonSchema = __esm(() => {
20500
20928
  init_any();
20501
20929
  });
20502
20930
 
20503
- // node_modules/zod-to-json-schema/dist/esm/index.js
20931
+ // node_modules/.pnpm/zod-to-json-schema@3.25.2_zod@3.25.76/node_modules/zod-to-json-schema/dist/esm/index.js
20504
20932
  var init_esm = __esm(() => {
20505
20933
  init_zodToJsonSchema();
20506
20934
  init_Options();
@@ -20536,7 +20964,7 @@ var init_esm = __esm(() => {
20536
20964
  init_zodToJsonSchema();
20537
20965
  });
20538
20966
 
20539
- // node_modules/@modelcontextprotocol/sdk/dist/esm/server/zod-json-schema-compat.js
20967
+ // node_modules/.pnpm/@modelcontextprotocol+sdk@1.30.0_zod@3.25.76/node_modules/@modelcontextprotocol/sdk/dist/esm/server/zod-json-schema-compat.js
20540
20968
  function mapMiniTarget(t) {
20541
20969
  if (!t)
20542
20970
  return "draft-7";
@@ -20583,7 +21011,7 @@ var init_zod_json_schema_compat = __esm(() => {
20583
21011
  init_esm();
20584
21012
  });
20585
21013
 
20586
- // node_modules/@modelcontextprotocol/sdk/dist/esm/shared/protocol.js
21014
+ // node_modules/.pnpm/@modelcontextprotocol+sdk@1.30.0_zod@3.25.76/node_modules/@modelcontextprotocol/sdk/dist/esm/shared/protocol.js
20587
21015
  class Protocol {
20588
21016
  constructor(_options) {
20589
21017
  this._options = _options;
@@ -20785,6 +21213,10 @@ class Protocol {
20785
21213
  this._progressHandlers.clear();
20786
21214
  this._taskProgressTokens.clear();
20787
21215
  this._pendingDebouncedNotifications.clear();
21216
+ for (const info of this._timeoutInfo.values()) {
21217
+ clearTimeout(info.timeoutId);
21218
+ }
21219
+ this._timeoutInfo.clear();
20788
21220
  for (const controller of this._requestHandlerAbortControllers.values()) {
20789
21221
  controller.abort();
20790
21222
  }
@@ -20915,7 +21347,9 @@ class Protocol {
20915
21347
  await capturedTransport?.send(errorResponse);
20916
21348
  }
20917
21349
  }).catch((error2) => this._onerror(new Error(`Failed to send response: ${error2}`))).finally(() => {
20918
- this._requestHandlerAbortControllers.delete(request.id);
21350
+ if (this._requestHandlerAbortControllers.get(request.id) === abortController) {
21351
+ this._requestHandlerAbortControllers.delete(request.id);
21352
+ }
20919
21353
  });
20920
21354
  }
20921
21355
  _onprogress(notification) {
@@ -21037,7 +21471,7 @@ class Protocol {
21037
21471
  return;
21038
21472
  }
21039
21473
  const pollInterval = task2.pollInterval ?? this._options?.defaultTaskPollInterval ?? 1000;
21040
- await new Promise((resolve2) => setTimeout(resolve2, pollInterval));
21474
+ await new Promise((resolve3) => setTimeout(resolve3, pollInterval));
21041
21475
  options?.signal?.throwIfAborted();
21042
21476
  }
21043
21477
  } catch (error2) {
@@ -21049,7 +21483,7 @@ class Protocol {
21049
21483
  }
21050
21484
  request(request, resultSchema, options) {
21051
21485
  const { relatedRequestId, resumptionToken, onresumptiontoken, task, relatedTask } = options ?? {};
21052
- return new Promise((resolve2, reject) => {
21486
+ return new Promise((resolve3, reject) => {
21053
21487
  const earlyReject = (error2) => {
21054
21488
  reject(error2);
21055
21489
  };
@@ -21127,7 +21561,7 @@ class Protocol {
21127
21561
  if (!parseResult.success) {
21128
21562
  reject(parseResult.error);
21129
21563
  } else {
21130
- resolve2(parseResult.data);
21564
+ resolve3(parseResult.data);
21131
21565
  }
21132
21566
  } catch (error2) {
21133
21567
  reject(error2);
@@ -21318,12 +21752,12 @@ class Protocol {
21318
21752
  interval = task.pollInterval;
21319
21753
  }
21320
21754
  } catch {}
21321
- return new Promise((resolve2, reject) => {
21755
+ return new Promise((resolve3, reject) => {
21322
21756
  if (signal.aborted) {
21323
21757
  reject(new McpError(ErrorCode.InvalidRequest, "Request cancelled"));
21324
21758
  return;
21325
21759
  }
21326
- const timeoutId = setTimeout(resolve2, interval);
21760
+ const timeoutId = setTimeout(resolve3, interval);
21327
21761
  signal.addEventListener("abort", () => {
21328
21762
  clearTimeout(timeoutId);
21329
21763
  reject(new McpError(ErrorCode.InvalidRequest, "Request cancelled"));
@@ -21422,7 +21856,7 @@ var init_protocol = __esm(() => {
21422
21856
  init_zod_json_schema_compat();
21423
21857
  });
21424
21858
 
21425
- // node_modules/ajv/dist/compile/codegen/code.js
21859
+ // node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/compile/codegen/code.js
21426
21860
  var require_code = __commonJS((exports) => {
21427
21861
  Object.defineProperty(exports, "__esModule", { value: true });
21428
21862
  exports.regexpCode = exports.getEsmExportName = exports.getProperty = exports.safeStringify = exports.stringify = exports.strConcat = exports.addCodeArg = exports.str = exports._ = exports.nil = exports._Code = exports.Name = exports.IDENTIFIER = exports._CodeOrName = undefined;
@@ -21576,7 +22010,7 @@ var require_code = __commonJS((exports) => {
21576
22010
  exports.regexpCode = regexpCode;
21577
22011
  });
21578
22012
 
21579
- // node_modules/ajv/dist/compile/codegen/scope.js
22013
+ // node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/compile/codegen/scope.js
21580
22014
  var require_scope = __commonJS((exports) => {
21581
22015
  Object.defineProperty(exports, "__esModule", { value: true });
21582
22016
  exports.ValueScope = exports.ValueScopeName = exports.Scope = exports.varKinds = exports.UsedValueState = undefined;
@@ -21722,7 +22156,7 @@ var require_scope = __commonJS((exports) => {
21722
22156
  exports.ValueScope = ValueScope;
21723
22157
  });
21724
22158
 
21725
- // node_modules/ajv/dist/compile/codegen/index.js
22159
+ // node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/compile/codegen/index.js
21726
22160
  var require_codegen = __commonJS((exports) => {
21727
22161
  Object.defineProperty(exports, "__esModule", { value: true });
21728
22162
  exports.or = exports.and = exports.not = exports.CodeGen = exports.operators = exports.varKinds = exports.ValueScopeName = exports.ValueScope = exports.Scope = exports.Name = exports.regexpCode = exports.stringify = exports.getProperty = exports.nil = exports.strConcat = exports.str = exports._ = undefined;
@@ -22432,7 +22866,7 @@ var require_codegen = __commonJS((exports) => {
22432
22866
  }
22433
22867
  });
22434
22868
 
22435
- // node_modules/ajv/dist/compile/util.js
22869
+ // node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/compile/util.js
22436
22870
  var require_util = __commonJS((exports) => {
22437
22871
  Object.defineProperty(exports, "__esModule", { value: true });
22438
22872
  exports.checkStrictMode = exports.getErrorPath = exports.Type = exports.useFunc = exports.setEvaluated = exports.evaluatedPropsToName = exports.mergeEvaluated = exports.eachItem = exports.unescapeJsonPointer = exports.escapeJsonPointer = exports.escapeFragment = exports.unescapeFragment = exports.schemaRefOrVal = exports.schemaHasRulesButRef = exports.schemaHasRules = exports.checkUnknownRules = exports.alwaysValidSchema = exports.toHash = undefined;
@@ -22596,7 +23030,7 @@ var require_util = __commonJS((exports) => {
22596
23030
  exports.checkStrictMode = checkStrictMode;
22597
23031
  });
22598
23032
 
22599
- // node_modules/ajv/dist/compile/names.js
23033
+ // node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/compile/names.js
22600
23034
  var require_names = __commonJS((exports) => {
22601
23035
  Object.defineProperty(exports, "__esModule", { value: true });
22602
23036
  var codegen_1 = require_codegen();
@@ -22621,7 +23055,7 @@ var require_names = __commonJS((exports) => {
22621
23055
  exports.default = names;
22622
23056
  });
22623
23057
 
22624
- // node_modules/ajv/dist/compile/errors.js
23058
+ // node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/compile/errors.js
22625
23059
  var require_errors = __commonJS((exports) => {
22626
23060
  Object.defineProperty(exports, "__esModule", { value: true });
22627
23061
  exports.extendErrors = exports.resetErrorsCount = exports.reportExtraError = exports.reportError = exports.keyword$DataError = exports.keywordError = undefined;
@@ -22739,7 +23173,7 @@ var require_errors = __commonJS((exports) => {
22739
23173
  }
22740
23174
  });
22741
23175
 
22742
- // node_modules/ajv/dist/compile/validate/boolSchema.js
23176
+ // node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/compile/validate/boolSchema.js
22743
23177
  var require_boolSchema = __commonJS((exports) => {
22744
23178
  Object.defineProperty(exports, "__esModule", { value: true });
22745
23179
  exports.boolOrEmptySchema = exports.topBoolOrEmptySchema = undefined;
@@ -22787,7 +23221,7 @@ var require_boolSchema = __commonJS((exports) => {
22787
23221
  }
22788
23222
  });
22789
23223
 
22790
- // node_modules/ajv/dist/compile/rules.js
23224
+ // node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/compile/rules.js
22791
23225
  var require_rules = __commonJS((exports) => {
22792
23226
  Object.defineProperty(exports, "__esModule", { value: true });
22793
23227
  exports.getRules = exports.isJSONType = undefined;
@@ -22815,7 +23249,7 @@ var require_rules = __commonJS((exports) => {
22815
23249
  exports.getRules = getRules;
22816
23250
  });
22817
23251
 
22818
- // node_modules/ajv/dist/compile/validate/applicability.js
23252
+ // node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/compile/validate/applicability.js
22819
23253
  var require_applicability = __commonJS((exports) => {
22820
23254
  Object.defineProperty(exports, "__esModule", { value: true });
22821
23255
  exports.shouldUseRule = exports.shouldUseGroup = exports.schemaHasRulesForType = undefined;
@@ -22835,7 +23269,7 @@ var require_applicability = __commonJS((exports) => {
22835
23269
  exports.shouldUseRule = shouldUseRule;
22836
23270
  });
22837
23271
 
22838
- // node_modules/ajv/dist/compile/validate/dataType.js
23272
+ // node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/compile/validate/dataType.js
22839
23273
  var require_dataType = __commonJS((exports) => {
22840
23274
  Object.defineProperty(exports, "__esModule", { value: true });
22841
23275
  exports.reportTypeError = exports.checkDataTypes = exports.checkDataType = exports.coerceAndCheckDataType = exports.getJSONTypes = exports.getSchemaTypes = exports.DataType = undefined;
@@ -23016,7 +23450,7 @@ var require_dataType = __commonJS((exports) => {
23016
23450
  }
23017
23451
  });
23018
23452
 
23019
- // node_modules/ajv/dist/compile/validate/defaults.js
23453
+ // node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/compile/validate/defaults.js
23020
23454
  var require_defaults = __commonJS((exports) => {
23021
23455
  Object.defineProperty(exports, "__esModule", { value: true });
23022
23456
  exports.assignDefaults = undefined;
@@ -23050,7 +23484,7 @@ var require_defaults = __commonJS((exports) => {
23050
23484
  }
23051
23485
  });
23052
23486
 
23053
- // node_modules/ajv/dist/vocabularies/code.js
23487
+ // node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/vocabularies/code.js
23054
23488
  var require_code2 = __commonJS((exports) => {
23055
23489
  Object.defineProperty(exports, "__esModule", { value: true });
23056
23490
  exports.validateUnion = exports.validateArray = exports.usePattern = exports.callValidateCode = exports.schemaProperties = exports.allSchemaProperties = exports.noPropertyInData = exports.propertyInData = exports.isOwnProperty = exports.hasPropFunc = exports.reportMissingProp = exports.checkMissingProp = exports.checkReportMissingProp = undefined;
@@ -23179,7 +23613,7 @@ var require_code2 = __commonJS((exports) => {
23179
23613
  exports.validateUnion = validateUnion;
23180
23614
  });
23181
23615
 
23182
- // node_modules/ajv/dist/compile/validate/keyword.js
23616
+ // node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/compile/validate/keyword.js
23183
23617
  var require_keyword = __commonJS((exports) => {
23184
23618
  Object.defineProperty(exports, "__esModule", { value: true });
23185
23619
  exports.validateKeywordUsage = exports.validSchemaType = exports.funcKeywordCode = exports.macroKeywordCode = undefined;
@@ -23294,7 +23728,7 @@ var require_keyword = __commonJS((exports) => {
23294
23728
  exports.validateKeywordUsage = validateKeywordUsage;
23295
23729
  });
23296
23730
 
23297
- // node_modules/ajv/dist/compile/validate/subschema.js
23731
+ // node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/compile/validate/subschema.js
23298
23732
  var require_subschema = __commonJS((exports) => {
23299
23733
  Object.defineProperty(exports, "__esModule", { value: true });
23300
23734
  exports.extendSubschemaMode = exports.extendSubschemaData = exports.getSubschema = undefined;
@@ -23374,7 +23808,7 @@ var require_subschema = __commonJS((exports) => {
23374
23808
  exports.extendSubschemaMode = extendSubschemaMode;
23375
23809
  });
23376
23810
 
23377
- // node_modules/fast-deep-equal/index.js
23811
+ // node_modules/.pnpm/fast-deep-equal@3.1.3/node_modules/fast-deep-equal/index.js
23378
23812
  var require_fast_deep_equal = __commonJS((exports, module) => {
23379
23813
  module.exports = function equal(a, b) {
23380
23814
  if (a === b)
@@ -23416,7 +23850,7 @@ var require_fast_deep_equal = __commonJS((exports, module) => {
23416
23850
  };
23417
23851
  });
23418
23852
 
23419
- // node_modules/json-schema-traverse/index.js
23853
+ // node_modules/.pnpm/json-schema-traverse@1.0.0/node_modules/json-schema-traverse/index.js
23420
23854
  var require_json_schema_traverse = __commonJS((exports, module) => {
23421
23855
  var traverse = module.exports = function(schema, opts, cb) {
23422
23856
  if (typeof opts == "function") {
@@ -23499,7 +23933,7 @@ var require_json_schema_traverse = __commonJS((exports, module) => {
23499
23933
  }
23500
23934
  });
23501
23935
 
23502
- // node_modules/ajv/dist/compile/resolve.js
23936
+ // node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/compile/resolve.js
23503
23937
  var require_resolve = __commonJS((exports) => {
23504
23938
  Object.defineProperty(exports, "__esModule", { value: true });
23505
23939
  exports.getSchemaRefs = exports.resolveUrl = exports.normalizeId = exports._getFullPath = exports.getFullPath = exports.inlineRef = undefined;
@@ -23652,7 +24086,7 @@ var require_resolve = __commonJS((exports) => {
23652
24086
  exports.getSchemaRefs = getSchemaRefs;
23653
24087
  });
23654
24088
 
23655
- // node_modules/ajv/dist/compile/validate/index.js
24089
+ // node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/compile/validate/index.js
23656
24090
  var require_validate = __commonJS((exports) => {
23657
24091
  Object.defineProperty(exports, "__esModule", { value: true });
23658
24092
  exports.getData = exports.KeywordCxt = exports.validateFunctionCode = undefined;
@@ -24157,7 +24591,7 @@ var require_validate = __commonJS((exports) => {
24157
24591
  exports.getData = getData;
24158
24592
  });
24159
24593
 
24160
- // node_modules/ajv/dist/runtime/validation_error.js
24594
+ // node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/runtime/validation_error.js
24161
24595
  var require_validation_error = __commonJS((exports) => {
24162
24596
  Object.defineProperty(exports, "__esModule", { value: true });
24163
24597
 
@@ -24171,7 +24605,7 @@ var require_validation_error = __commonJS((exports) => {
24171
24605
  exports.default = ValidationError;
24172
24606
  });
24173
24607
 
24174
- // node_modules/ajv/dist/compile/ref_error.js
24608
+ // node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/compile/ref_error.js
24175
24609
  var require_ref_error = __commonJS((exports) => {
24176
24610
  Object.defineProperty(exports, "__esModule", { value: true });
24177
24611
  var resolve_1 = require_resolve();
@@ -24186,7 +24620,7 @@ var require_ref_error = __commonJS((exports) => {
24186
24620
  exports.default = MissingRefError;
24187
24621
  });
24188
24622
 
24189
- // node_modules/ajv/dist/compile/index.js
24623
+ // node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/compile/index.js
24190
24624
  var require_compile = __commonJS((exports) => {
24191
24625
  Object.defineProperty(exports, "__esModule", { value: true });
24192
24626
  exports.resolveSchema = exports.getCompilingSchema = exports.resolveRef = exports.compileSchema = exports.SchemaEnv = undefined;
@@ -24308,7 +24742,7 @@ var require_compile = __commonJS((exports) => {
24308
24742
  const schOrFunc = root.refs[ref];
24309
24743
  if (schOrFunc)
24310
24744
  return schOrFunc;
24311
- let _sch = resolve2.call(this, root, ref);
24745
+ let _sch = resolve3.call(this, root, ref);
24312
24746
  if (_sch === undefined) {
24313
24747
  const schema = (_a = root.localRefs) === null || _a === undefined ? undefined : _a[ref];
24314
24748
  const { schemaId } = this.opts;
@@ -24335,7 +24769,7 @@ var require_compile = __commonJS((exports) => {
24335
24769
  function sameSchemaEnv(s1, s2) {
24336
24770
  return s1.schema === s2.schema && s1.root === s2.root && s1.baseId === s2.baseId;
24337
24771
  }
24338
- function resolve2(root, ref) {
24772
+ function resolve3(root, ref) {
24339
24773
  let sch;
24340
24774
  while (typeof (sch = this.refs[ref]) == "string")
24341
24775
  ref = sch;
@@ -24407,7 +24841,7 @@ var require_compile = __commonJS((exports) => {
24407
24841
  }
24408
24842
  });
24409
24843
 
24410
- // node_modules/ajv/dist/refs/data.json
24844
+ // node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/refs/data.json
24411
24845
  var require_data = __commonJS((exports, module) => {
24412
24846
  module.exports = {
24413
24847
  $id: "https://raw.githubusercontent.com/ajv-validator/ajv/master/lib/refs/data.json#",
@@ -24627,8 +25061,8 @@ var require_utils = __commonJS((exports, module) => {
24627
25061
  var HOST_DELIMS = { "@": "%40", "/": "%2F", "?": "%3F", "#": "%23", ":": "%3A" };
24628
25062
  var HOST_DELIM_RE = /[@/?#:]/g;
24629
25063
  var HOST_DELIM_NO_COLON_RE = /[@/?#]/g;
24630
- function reescapeHostDelimiters(host, isIP) {
24631
- const re = isIP ? HOST_DELIM_NO_COLON_RE : HOST_DELIM_RE;
25064
+ function reescapeHostDelimiters(host, isIP2) {
25065
+ const re = isIP2 ? HOST_DELIM_NO_COLON_RE : HOST_DELIM_RE;
24632
25066
  re.lastIndex = 0;
24633
25067
  return host.replace(re, (ch) => HOST_DELIMS[ch]);
24634
25068
  }
@@ -24921,7 +25355,7 @@ var require_fast_uri = __commonJS((exports, module) => {
24921
25355
  }
24922
25356
  return uri;
24923
25357
  }
24924
- function resolve2(baseURI, relativeURI, options) {
25358
+ function resolve3(baseURI, relativeURI, options) {
24925
25359
  const schemelessOptions = options ? Object.assign({ scheme: "null" }, options) : { scheme: "null" };
24926
25360
  const resolved = resolveComponent(parse6(baseURI, schemelessOptions), parse6(relativeURI, schemelessOptions), schemelessOptions, true);
24927
25361
  schemelessOptions.skipEscape = true;
@@ -25071,7 +25505,7 @@ var require_fast_uri = __commonJS((exports, module) => {
25071
25505
  fragment: undefined
25072
25506
  };
25073
25507
  let malformedAuthorityOrPort = false;
25074
- let isIP = false;
25508
+ let isIP2 = false;
25075
25509
  if (options.reference === "suffix") {
25076
25510
  if (options.scheme) {
25077
25511
  uri = options.scheme + ":" + uri;
@@ -25106,9 +25540,9 @@ var require_fast_uri = __commonJS((exports, module) => {
25106
25540
  if (ipv4result === false) {
25107
25541
  const ipv6result = normalizeIPv6(parsed.host);
25108
25542
  parsed.host = ipv6result.host.toLowerCase();
25109
- isIP = ipv6result.isIPV6;
25543
+ isIP2 = ipv6result.isIPV6;
25110
25544
  } else {
25111
- isIP = true;
25545
+ isIP2 = true;
25112
25546
  }
25113
25547
  }
25114
25548
  if (parsed.scheme === undefined && parsed.userinfo === undefined && parsed.host === undefined && parsed.port === undefined && parsed.query === undefined && !parsed.path) {
@@ -25125,7 +25559,7 @@ var require_fast_uri = __commonJS((exports, module) => {
25125
25559
  }
25126
25560
  const schemeHandler = getSchemeHandler(options.scheme || parsed.scheme);
25127
25561
  if (!options.unicodeSupport && (!schemeHandler || !schemeHandler.unicodeSupport)) {
25128
- if (parsed.host && (options.domainHost || schemeHandler && schemeHandler.domainHost) && isIP === false && nonSimpleDomain(parsed.host)) {
25562
+ if (parsed.host && (options.domainHost || schemeHandler && schemeHandler.domainHost) && isIP2 === false && nonSimpleDomain(parsed.host)) {
25129
25563
  try {
25130
25564
  parsed.host = new URL("http://" + parsed.host).hostname;
25131
25565
  } catch (e) {
@@ -25139,7 +25573,7 @@ var require_fast_uri = __commonJS((exports, module) => {
25139
25573
  parsed.scheme = unescape(parsed.scheme);
25140
25574
  }
25141
25575
  if (parsed.host !== undefined) {
25142
- parsed.host = reescapeHostDelimiters(unescape(parsed.host), isIP);
25576
+ parsed.host = reescapeHostDelimiters(unescape(parsed.host), isIP2);
25143
25577
  }
25144
25578
  }
25145
25579
  if (parsed.path) {
@@ -25186,7 +25620,7 @@ var require_fast_uri = __commonJS((exports, module) => {
25186
25620
  var fastUri = {
25187
25621
  SCHEMES,
25188
25622
  normalize: normalize2,
25189
- resolve: resolve2,
25623
+ resolve: resolve3,
25190
25624
  resolveComponent,
25191
25625
  equal,
25192
25626
  serialize,
@@ -25197,7 +25631,7 @@ var require_fast_uri = __commonJS((exports, module) => {
25197
25631
  module.exports.fastUri = fastUri;
25198
25632
  });
25199
25633
 
25200
- // node_modules/ajv/dist/runtime/uri.js
25634
+ // node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/runtime/uri.js
25201
25635
  var require_uri = __commonJS((exports) => {
25202
25636
  Object.defineProperty(exports, "__esModule", { value: true });
25203
25637
  var uri = require_fast_uri();
@@ -25205,7 +25639,7 @@ var require_uri = __commonJS((exports) => {
25205
25639
  exports.default = uri;
25206
25640
  });
25207
25641
 
25208
- // node_modules/ajv/dist/core.js
25642
+ // node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/core.js
25209
25643
  var require_core = __commonJS((exports) => {
25210
25644
  Object.defineProperty(exports, "__esModule", { value: true });
25211
25645
  exports.CodeGen = exports.Name = exports.nil = exports.stringify = exports.str = exports._ = exports.KeywordCxt = undefined;
@@ -25316,7 +25750,7 @@ var require_core = __commonJS((exports) => {
25316
25750
  constructor(opts = {}) {
25317
25751
  this.schemas = {};
25318
25752
  this.refs = {};
25319
- this.formats = {};
25753
+ this.formats = Object.create(null);
25320
25754
  this._compilations = new Set;
25321
25755
  this._loading = {};
25322
25756
  this._cache = new Map;
@@ -25798,7 +26232,7 @@ var require_core = __commonJS((exports) => {
25798
26232
  }
25799
26233
  });
25800
26234
 
25801
- // node_modules/ajv/dist/vocabularies/core/id.js
26235
+ // node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/vocabularies/core/id.js
25802
26236
  var require_id = __commonJS((exports) => {
25803
26237
  Object.defineProperty(exports, "__esModule", { value: true });
25804
26238
  var def = {
@@ -25810,7 +26244,7 @@ var require_id = __commonJS((exports) => {
25810
26244
  exports.default = def;
25811
26245
  });
25812
26246
 
25813
- // node_modules/ajv/dist/vocabularies/core/ref.js
26247
+ // node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/vocabularies/core/ref.js
25814
26248
  var require_ref = __commonJS((exports) => {
25815
26249
  Object.defineProperty(exports, "__esModule", { value: true });
25816
26250
  exports.callRef = exports.getValidate = undefined;
@@ -25929,7 +26363,7 @@ var require_ref = __commonJS((exports) => {
25929
26363
  exports.default = def;
25930
26364
  });
25931
26365
 
25932
- // node_modules/ajv/dist/vocabularies/core/index.js
26366
+ // node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/vocabularies/core/index.js
25933
26367
  var require_core2 = __commonJS((exports) => {
25934
26368
  Object.defineProperty(exports, "__esModule", { value: true });
25935
26369
  var id_1 = require_id();
@@ -25947,7 +26381,7 @@ var require_core2 = __commonJS((exports) => {
25947
26381
  exports.default = core2;
25948
26382
  });
25949
26383
 
25950
- // node_modules/ajv/dist/vocabularies/validation/limitNumber.js
26384
+ // node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/vocabularies/validation/limitNumber.js
25951
26385
  var require_limitNumber = __commonJS((exports) => {
25952
26386
  Object.defineProperty(exports, "__esModule", { value: true });
25953
26387
  var codegen_1 = require_codegen();
@@ -25976,7 +26410,7 @@ var require_limitNumber = __commonJS((exports) => {
25976
26410
  exports.default = def;
25977
26411
  });
25978
26412
 
25979
- // node_modules/ajv/dist/vocabularies/validation/multipleOf.js
26413
+ // node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/vocabularies/validation/multipleOf.js
25980
26414
  var require_multipleOf = __commonJS((exports) => {
25981
26415
  Object.defineProperty(exports, "__esModule", { value: true });
25982
26416
  var codegen_1 = require_codegen();
@@ -26001,7 +26435,7 @@ var require_multipleOf = __commonJS((exports) => {
26001
26435
  exports.default = def;
26002
26436
  });
26003
26437
 
26004
- // node_modules/ajv/dist/runtime/ucs2length.js
26438
+ // node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/runtime/ucs2length.js
26005
26439
  var require_ucs2length = __commonJS((exports) => {
26006
26440
  Object.defineProperty(exports, "__esModule", { value: true });
26007
26441
  function ucs2length(str) {
@@ -26024,7 +26458,7 @@ var require_ucs2length = __commonJS((exports) => {
26024
26458
  ucs2length.code = 'require("ajv/dist/runtime/ucs2length").default';
26025
26459
  });
26026
26460
 
26027
- // node_modules/ajv/dist/vocabularies/validation/limitLength.js
26461
+ // node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/vocabularies/validation/limitLength.js
26028
26462
  var require_limitLength = __commonJS((exports) => {
26029
26463
  Object.defineProperty(exports, "__esModule", { value: true });
26030
26464
  var codegen_1 = require_codegen();
@@ -26053,7 +26487,7 @@ var require_limitLength = __commonJS((exports) => {
26053
26487
  exports.default = def;
26054
26488
  });
26055
26489
 
26056
- // node_modules/ajv/dist/vocabularies/validation/pattern.js
26490
+ // node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/vocabularies/validation/pattern.js
26057
26491
  var require_pattern = __commonJS((exports) => {
26058
26492
  Object.defineProperty(exports, "__esModule", { value: true });
26059
26493
  var code_1 = require_code2();
@@ -26087,7 +26521,7 @@ var require_pattern = __commonJS((exports) => {
26087
26521
  exports.default = def;
26088
26522
  });
26089
26523
 
26090
- // node_modules/ajv/dist/vocabularies/validation/limitProperties.js
26524
+ // node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/vocabularies/validation/limitProperties.js
26091
26525
  var require_limitProperties = __commonJS((exports) => {
26092
26526
  Object.defineProperty(exports, "__esModule", { value: true });
26093
26527
  var codegen_1 = require_codegen();
@@ -26113,7 +26547,7 @@ var require_limitProperties = __commonJS((exports) => {
26113
26547
  exports.default = def;
26114
26548
  });
26115
26549
 
26116
- // node_modules/ajv/dist/vocabularies/validation/required.js
26550
+ // node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/vocabularies/validation/required.js
26117
26551
  var require_required = __commonJS((exports) => {
26118
26552
  Object.defineProperty(exports, "__esModule", { value: true });
26119
26553
  var code_1 = require_code2();
@@ -26192,7 +26626,7 @@ var require_required = __commonJS((exports) => {
26192
26626
  exports.default = def;
26193
26627
  });
26194
26628
 
26195
- // node_modules/ajv/dist/vocabularies/validation/limitItems.js
26629
+ // node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/vocabularies/validation/limitItems.js
26196
26630
  var require_limitItems = __commonJS((exports) => {
26197
26631
  Object.defineProperty(exports, "__esModule", { value: true });
26198
26632
  var codegen_1 = require_codegen();
@@ -26218,7 +26652,7 @@ var require_limitItems = __commonJS((exports) => {
26218
26652
  exports.default = def;
26219
26653
  });
26220
26654
 
26221
- // node_modules/ajv/dist/runtime/equal.js
26655
+ // node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/runtime/equal.js
26222
26656
  var require_equal = __commonJS((exports) => {
26223
26657
  Object.defineProperty(exports, "__esModule", { value: true });
26224
26658
  var equal = require_fast_deep_equal();
@@ -26226,7 +26660,7 @@ var require_equal = __commonJS((exports) => {
26226
26660
  exports.default = equal;
26227
26661
  });
26228
26662
 
26229
- // node_modules/ajv/dist/vocabularies/validation/uniqueItems.js
26663
+ // node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/vocabularies/validation/uniqueItems.js
26230
26664
  var require_uniqueItems = __commonJS((exports) => {
26231
26665
  Object.defineProperty(exports, "__esModule", { value: true });
26232
26666
  var dataType_1 = require_dataType();
@@ -26290,7 +26724,7 @@ var require_uniqueItems = __commonJS((exports) => {
26290
26724
  exports.default = def;
26291
26725
  });
26292
26726
 
26293
- // node_modules/ajv/dist/vocabularies/validation/const.js
26727
+ // node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/vocabularies/validation/const.js
26294
26728
  var require_const = __commonJS((exports) => {
26295
26729
  Object.defineProperty(exports, "__esModule", { value: true });
26296
26730
  var codegen_1 = require_codegen();
@@ -26316,7 +26750,7 @@ var require_const = __commonJS((exports) => {
26316
26750
  exports.default = def;
26317
26751
  });
26318
26752
 
26319
- // node_modules/ajv/dist/vocabularies/validation/enum.js
26753
+ // node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/vocabularies/validation/enum.js
26320
26754
  var require_enum = __commonJS((exports) => {
26321
26755
  Object.defineProperty(exports, "__esModule", { value: true });
26322
26756
  var codegen_1 = require_codegen();
@@ -26362,7 +26796,7 @@ var require_enum = __commonJS((exports) => {
26362
26796
  exports.default = def;
26363
26797
  });
26364
26798
 
26365
- // node_modules/ajv/dist/vocabularies/validation/index.js
26799
+ // node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/vocabularies/validation/index.js
26366
26800
  var require_validation = __commonJS((exports) => {
26367
26801
  Object.defineProperty(exports, "__esModule", { value: true });
26368
26802
  var limitNumber_1 = require_limitNumber();
@@ -26392,7 +26826,7 @@ var require_validation = __commonJS((exports) => {
26392
26826
  exports.default = validation;
26393
26827
  });
26394
26828
 
26395
- // node_modules/ajv/dist/vocabularies/applicator/additionalItems.js
26829
+ // node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/vocabularies/applicator/additionalItems.js
26396
26830
  var require_additionalItems = __commonJS((exports) => {
26397
26831
  Object.defineProperty(exports, "__esModule", { value: true });
26398
26832
  exports.validateAdditionalItems = undefined;
@@ -26442,7 +26876,7 @@ var require_additionalItems = __commonJS((exports) => {
26442
26876
  exports.default = def;
26443
26877
  });
26444
26878
 
26445
- // node_modules/ajv/dist/vocabularies/applicator/items.js
26879
+ // node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/vocabularies/applicator/items.js
26446
26880
  var require_items = __commonJS((exports) => {
26447
26881
  Object.defineProperty(exports, "__esModule", { value: true });
26448
26882
  exports.validateTuple = undefined;
@@ -26496,7 +26930,7 @@ var require_items = __commonJS((exports) => {
26496
26930
  exports.default = def;
26497
26931
  });
26498
26932
 
26499
- // node_modules/ajv/dist/vocabularies/applicator/prefixItems.js
26933
+ // node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/vocabularies/applicator/prefixItems.js
26500
26934
  var require_prefixItems = __commonJS((exports) => {
26501
26935
  Object.defineProperty(exports, "__esModule", { value: true });
26502
26936
  var items_1 = require_items();
@@ -26510,7 +26944,7 @@ var require_prefixItems = __commonJS((exports) => {
26510
26944
  exports.default = def;
26511
26945
  });
26512
26946
 
26513
- // node_modules/ajv/dist/vocabularies/applicator/items2020.js
26947
+ // node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/vocabularies/applicator/items2020.js
26514
26948
  var require_items2020 = __commonJS((exports) => {
26515
26949
  Object.defineProperty(exports, "__esModule", { value: true });
26516
26950
  var codegen_1 = require_codegen();
@@ -26542,7 +26976,7 @@ var require_items2020 = __commonJS((exports) => {
26542
26976
  exports.default = def;
26543
26977
  });
26544
26978
 
26545
- // node_modules/ajv/dist/vocabularies/applicator/contains.js
26979
+ // node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/vocabularies/applicator/contains.js
26546
26980
  var require_contains = __commonJS((exports) => {
26547
26981
  Object.defineProperty(exports, "__esModule", { value: true });
26548
26982
  var codegen_1 = require_codegen();
@@ -26633,7 +27067,7 @@ var require_contains = __commonJS((exports) => {
26633
27067
  exports.default = def;
26634
27068
  });
26635
27069
 
26636
- // node_modules/ajv/dist/vocabularies/applicator/dependencies.js
27070
+ // node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/vocabularies/applicator/dependencies.js
26637
27071
  var require_dependencies = __commonJS((exports) => {
26638
27072
  Object.defineProperty(exports, "__esModule", { value: true });
26639
27073
  exports.validateSchemaDeps = exports.validatePropertyDeps = exports.error = undefined;
@@ -26718,7 +27152,7 @@ var require_dependencies = __commonJS((exports) => {
26718
27152
  exports.default = def;
26719
27153
  });
26720
27154
 
26721
- // node_modules/ajv/dist/vocabularies/applicator/propertyNames.js
27155
+ // node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/vocabularies/applicator/propertyNames.js
26722
27156
  var require_propertyNames = __commonJS((exports) => {
26723
27157
  Object.defineProperty(exports, "__esModule", { value: true });
26724
27158
  var codegen_1 = require_codegen();
@@ -26758,7 +27192,7 @@ var require_propertyNames = __commonJS((exports) => {
26758
27192
  exports.default = def;
26759
27193
  });
26760
27194
 
26761
- // node_modules/ajv/dist/vocabularies/applicator/additionalProperties.js
27195
+ // node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/vocabularies/applicator/additionalProperties.js
26762
27196
  var require_additionalProperties = __commonJS((exports) => {
26763
27197
  Object.defineProperty(exports, "__esModule", { value: true });
26764
27198
  var code_1 = require_code2();
@@ -26861,7 +27295,7 @@ var require_additionalProperties = __commonJS((exports) => {
26861
27295
  exports.default = def;
26862
27296
  });
26863
27297
 
26864
- // node_modules/ajv/dist/vocabularies/applicator/properties.js
27298
+ // node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/vocabularies/applicator/properties.js
26865
27299
  var require_properties = __commonJS((exports) => {
26866
27300
  Object.defineProperty(exports, "__esModule", { value: true });
26867
27301
  var validate_1 = require_validate();
@@ -26916,7 +27350,7 @@ var require_properties = __commonJS((exports) => {
26916
27350
  exports.default = def;
26917
27351
  });
26918
27352
 
26919
- // node_modules/ajv/dist/vocabularies/applicator/patternProperties.js
27353
+ // node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/vocabularies/applicator/patternProperties.js
26920
27354
  var require_patternProperties = __commonJS((exports) => {
26921
27355
  Object.defineProperty(exports, "__esModule", { value: true });
26922
27356
  var code_1 = require_code2();
@@ -26987,7 +27421,7 @@ var require_patternProperties = __commonJS((exports) => {
26987
27421
  exports.default = def;
26988
27422
  });
26989
27423
 
26990
- // node_modules/ajv/dist/vocabularies/applicator/not.js
27424
+ // node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/vocabularies/applicator/not.js
26991
27425
  var require_not = __commonJS((exports) => {
26992
27426
  Object.defineProperty(exports, "__esModule", { value: true });
26993
27427
  var util_1 = require_util();
@@ -27015,7 +27449,7 @@ var require_not = __commonJS((exports) => {
27015
27449
  exports.default = def;
27016
27450
  });
27017
27451
 
27018
- // node_modules/ajv/dist/vocabularies/applicator/anyOf.js
27452
+ // node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/vocabularies/applicator/anyOf.js
27019
27453
  var require_anyOf = __commonJS((exports) => {
27020
27454
  Object.defineProperty(exports, "__esModule", { value: true });
27021
27455
  var code_1 = require_code2();
@@ -27029,7 +27463,7 @@ var require_anyOf = __commonJS((exports) => {
27029
27463
  exports.default = def;
27030
27464
  });
27031
27465
 
27032
- // node_modules/ajv/dist/vocabularies/applicator/oneOf.js
27466
+ // node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/vocabularies/applicator/oneOf.js
27033
27467
  var require_oneOf = __commonJS((exports) => {
27034
27468
  Object.defineProperty(exports, "__esModule", { value: true });
27035
27469
  var codegen_1 = require_codegen();
@@ -27084,7 +27518,7 @@ var require_oneOf = __commonJS((exports) => {
27084
27518
  exports.default = def;
27085
27519
  });
27086
27520
 
27087
- // node_modules/ajv/dist/vocabularies/applicator/allOf.js
27521
+ // node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/vocabularies/applicator/allOf.js
27088
27522
  var require_allOf = __commonJS((exports) => {
27089
27523
  Object.defineProperty(exports, "__esModule", { value: true });
27090
27524
  var util_1 = require_util();
@@ -27108,7 +27542,7 @@ var require_allOf = __commonJS((exports) => {
27108
27542
  exports.default = def;
27109
27543
  });
27110
27544
 
27111
- // node_modules/ajv/dist/vocabularies/applicator/if.js
27545
+ // node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/vocabularies/applicator/if.js
27112
27546
  var require_if = __commonJS((exports) => {
27113
27547
  Object.defineProperty(exports, "__esModule", { value: true });
27114
27548
  var codegen_1 = require_codegen();
@@ -27174,7 +27608,7 @@ var require_if = __commonJS((exports) => {
27174
27608
  exports.default = def;
27175
27609
  });
27176
27610
 
27177
- // node_modules/ajv/dist/vocabularies/applicator/thenElse.js
27611
+ // node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/vocabularies/applicator/thenElse.js
27178
27612
  var require_thenElse = __commonJS((exports) => {
27179
27613
  Object.defineProperty(exports, "__esModule", { value: true });
27180
27614
  var util_1 = require_util();
@@ -27189,7 +27623,7 @@ var require_thenElse = __commonJS((exports) => {
27189
27623
  exports.default = def;
27190
27624
  });
27191
27625
 
27192
- // node_modules/ajv/dist/vocabularies/applicator/index.js
27626
+ // node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/vocabularies/applicator/index.js
27193
27627
  var require_applicator = __commonJS((exports) => {
27194
27628
  Object.defineProperty(exports, "__esModule", { value: true });
27195
27629
  var additionalItems_1 = require_additionalItems();
@@ -27232,7 +27666,7 @@ var require_applicator = __commonJS((exports) => {
27232
27666
  exports.default = getApplicator;
27233
27667
  });
27234
27668
 
27235
- // node_modules/ajv/dist/vocabularies/format/format.js
27669
+ // node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/vocabularies/format/format.js
27236
27670
  var require_format = __commonJS((exports) => {
27237
27671
  Object.defineProperty(exports, "__esModule", { value: true });
27238
27672
  var codegen_1 = require_codegen();
@@ -27319,7 +27753,7 @@ var require_format = __commonJS((exports) => {
27319
27753
  exports.default = def;
27320
27754
  });
27321
27755
 
27322
- // node_modules/ajv/dist/vocabularies/format/index.js
27756
+ // node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/vocabularies/format/index.js
27323
27757
  var require_format2 = __commonJS((exports) => {
27324
27758
  Object.defineProperty(exports, "__esModule", { value: true });
27325
27759
  var format_1 = require_format();
@@ -27327,7 +27761,7 @@ var require_format2 = __commonJS((exports) => {
27327
27761
  exports.default = format;
27328
27762
  });
27329
27763
 
27330
- // node_modules/ajv/dist/vocabularies/metadata.js
27764
+ // node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/vocabularies/metadata.js
27331
27765
  var require_metadata = __commonJS((exports) => {
27332
27766
  Object.defineProperty(exports, "__esModule", { value: true });
27333
27767
  exports.contentVocabulary = exports.metadataVocabulary = undefined;
@@ -27347,7 +27781,7 @@ var require_metadata = __commonJS((exports) => {
27347
27781
  ];
27348
27782
  });
27349
27783
 
27350
- // node_modules/ajv/dist/vocabularies/draft7.js
27784
+ // node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/vocabularies/draft7.js
27351
27785
  var require_draft7 = __commonJS((exports) => {
27352
27786
  Object.defineProperty(exports, "__esModule", { value: true });
27353
27787
  var core_1 = require_core2();
@@ -27366,7 +27800,7 @@ var require_draft7 = __commonJS((exports) => {
27366
27800
  exports.default = draft7Vocabularies;
27367
27801
  });
27368
27802
 
27369
- // node_modules/ajv/dist/vocabularies/discriminator/types.js
27803
+ // node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/vocabularies/discriminator/types.js
27370
27804
  var require_types = __commonJS((exports) => {
27371
27805
  Object.defineProperty(exports, "__esModule", { value: true });
27372
27806
  exports.DiscrError = undefined;
@@ -27377,7 +27811,7 @@ var require_types = __commonJS((exports) => {
27377
27811
  })(DiscrError || (exports.DiscrError = DiscrError = {}));
27378
27812
  });
27379
27813
 
27380
- // node_modules/ajv/dist/vocabularies/discriminator/index.js
27814
+ // node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/vocabularies/discriminator/index.js
27381
27815
  var require_discriminator = __commonJS((exports) => {
27382
27816
  Object.defineProperty(exports, "__esModule", { value: true });
27383
27817
  var codegen_1 = require_codegen();
@@ -27479,7 +27913,7 @@ var require_discriminator = __commonJS((exports) => {
27479
27913
  exports.default = def;
27480
27914
  });
27481
27915
 
27482
- // node_modules/ajv/dist/refs/json-schema-draft-07.json
27916
+ // node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/refs/json-schema-draft-07.json
27483
27917
  var require_json_schema_draft_07 = __commonJS((exports, module) => {
27484
27918
  module.exports = {
27485
27919
  $schema: "http://json-schema.org/draft-07/schema#",
@@ -27634,7 +28068,7 @@ var require_json_schema_draft_07 = __commonJS((exports, module) => {
27634
28068
  };
27635
28069
  });
27636
28070
 
27637
- // node_modules/ajv/dist/ajv.js
28071
+ // node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/ajv.js
27638
28072
  var require_ajv = __commonJS((exports, module) => {
27639
28073
  Object.defineProperty(exports, "__esModule", { value: true });
27640
28074
  exports.MissingRefError = exports.ValidationError = exports.CodeGen = exports.Name = exports.nil = exports.stringify = exports.str = exports._ = exports.KeywordCxt = exports.Ajv = undefined;
@@ -27702,7 +28136,7 @@ var require_ajv = __commonJS((exports, module) => {
27702
28136
  } });
27703
28137
  });
27704
28138
 
27705
- // node_modules/ajv-formats/dist/formats.js
28139
+ // node_modules/.pnpm/ajv-formats@3.0.1_ajv@8.20.0/node_modules/ajv-formats/dist/formats.js
27706
28140
  var require_formats = __commonJS((exports) => {
27707
28141
  Object.defineProperty(exports, "__esModule", { value: true });
27708
28142
  exports.formatNames = exports.fastFormats = exports.fullFormats = undefined;
@@ -27879,7 +28313,7 @@ var require_formats = __commonJS((exports) => {
27879
28313
  }
27880
28314
  });
27881
28315
 
27882
- // node_modules/ajv-formats/dist/limit.js
28316
+ // node_modules/.pnpm/ajv-formats@3.0.1_ajv@8.20.0/node_modules/ajv-formats/dist/limit.js
27883
28317
  var require_limit = __commonJS((exports) => {
27884
28318
  Object.defineProperty(exports, "__esModule", { value: true });
27885
28319
  exports.formatLimitDefinition = undefined;
@@ -27948,7 +28382,7 @@ var require_limit = __commonJS((exports) => {
27948
28382
  exports.default = formatLimitPlugin;
27949
28383
  });
27950
28384
 
27951
- // node_modules/ajv-formats/dist/index.js
28385
+ // node_modules/.pnpm/ajv-formats@3.0.1_ajv@8.20.0/node_modules/ajv-formats/dist/index.js
27952
28386
  var require_dist = __commonJS((exports, module) => {
27953
28387
  Object.defineProperty(exports, "__esModule", { value: true });
27954
28388
  var formats_1 = require_formats();
@@ -27987,7 +28421,7 @@ var require_dist = __commonJS((exports, module) => {
27987
28421
  exports.default = formatsPlugin;
27988
28422
  });
27989
28423
 
27990
- // node_modules/@modelcontextprotocol/sdk/dist/esm/validation/ajv-provider.js
28424
+ // node_modules/.pnpm/@modelcontextprotocol+sdk@1.30.0_zod@3.25.76/node_modules/@modelcontextprotocol/sdk/dist/esm/validation/ajv-provider.js
27991
28425
  function createDefaultAjvInstance() {
27992
28426
  const ajv = new import_ajv.default({
27993
28427
  strict: false,
@@ -28030,7 +28464,7 @@ var init_ajv_provider = __esm(() => {
28030
28464
  import_ajv_formats = __toESM(require_dist(), 1);
28031
28465
  });
28032
28466
 
28033
- // node_modules/@modelcontextprotocol/sdk/dist/esm/experimental/tasks/server.js
28467
+ // node_modules/.pnpm/@modelcontextprotocol+sdk@1.30.0_zod@3.25.76/node_modules/@modelcontextprotocol/sdk/dist/esm/experimental/tasks/server.js
28034
28468
  class ExperimentalServerTasks {
28035
28469
  constructor(_server) {
28036
28470
  this._server = _server;
@@ -28111,7 +28545,7 @@ var init_server = __esm(() => {
28111
28545
  init_types2();
28112
28546
  });
28113
28547
 
28114
- // node_modules/@modelcontextprotocol/sdk/dist/esm/experimental/tasks/helpers.js
28548
+ // node_modules/.pnpm/@modelcontextprotocol+sdk@1.30.0_zod@3.25.76/node_modules/@modelcontextprotocol/sdk/dist/esm/experimental/tasks/helpers.js
28115
28549
  function assertToolsCallTaskCapability(requests, method, entityName) {
28116
28550
  if (!requests) {
28117
28551
  throw new Error(`${entityName} does not support task creation (required for ${method})`);
@@ -28146,7 +28580,7 @@ function assertClientRequestTaskCapability(requests, method, entityName) {
28146
28580
  }
28147
28581
  }
28148
28582
 
28149
- // node_modules/@modelcontextprotocol/sdk/dist/esm/server/index.js
28583
+ // node_modules/.pnpm/@modelcontextprotocol+sdk@1.30.0_zod@3.25.76/node_modules/@modelcontextprotocol/sdk/dist/esm/server/index.js
28150
28584
  var Server;
28151
28585
  var init_server2 = __esm(() => {
28152
28586
  init_protocol();
@@ -28201,16 +28635,7 @@ var init_server2 = __esm(() => {
28201
28635
  if (!methodSchema) {
28202
28636
  throw new Error("Schema is missing a method literal");
28203
28637
  }
28204
- let methodValue;
28205
- if (isZ4Schema(methodSchema)) {
28206
- const v4Schema = methodSchema;
28207
- const v4Def = v4Schema._zod?.def;
28208
- methodValue = v4Def?.value ?? v4Schema.value;
28209
- } else {
28210
- const v3Schema = methodSchema;
28211
- const legacyDef = v3Schema._def;
28212
- methodValue = legacyDef?.value ?? v3Schema.value;
28213
- }
28638
+ const methodValue = getLiteralValue(methodSchema);
28214
28639
  if (typeof methodValue !== "string") {
28215
28640
  throw new Error("Schema method literal must be a string");
28216
28641
  }
@@ -28487,7 +28912,7 @@ var init_server2 = __esm(() => {
28487
28912
  };
28488
28913
  });
28489
28914
 
28490
- // node_modules/@modelcontextprotocol/sdk/dist/esm/server/completable.js
28915
+ // node_modules/.pnpm/@modelcontextprotocol+sdk@1.30.0_zod@3.25.76/node_modules/@modelcontextprotocol/sdk/dist/esm/server/completable.js
28491
28916
  function isCompletable(schema) {
28492
28917
  return !!schema && typeof schema === "object" && COMPLETABLE_SYMBOL in schema;
28493
28918
  }
@@ -28502,7 +28927,7 @@ var init_completable = __esm(() => {
28502
28927
  McpZodTypeKind2["Completable"] = "McpCompletable";
28503
28928
  })(McpZodTypeKind || (McpZodTypeKind = {}));
28504
28929
  });
28505
- // node_modules/@modelcontextprotocol/sdk/dist/esm/shared/toolNameValidation.js
28930
+ // node_modules/.pnpm/@modelcontextprotocol+sdk@1.30.0_zod@3.25.76/node_modules/@modelcontextprotocol/sdk/dist/esm/shared/toolNameValidation.js
28506
28931
  function validateToolName(name) {
28507
28932
  const warnings = [];
28508
28933
  if (name.length === 0) {
@@ -28563,7 +28988,7 @@ var init_toolNameValidation = __esm(() => {
28563
28988
  TOOL_NAME_REGEX = /^[A-Za-z0-9._-]{1,128}$/;
28564
28989
  });
28565
28990
 
28566
- // node_modules/@modelcontextprotocol/sdk/dist/esm/experimental/tasks/mcp-server.js
28991
+ // node_modules/.pnpm/@modelcontextprotocol+sdk@1.30.0_zod@3.25.76/node_modules/@modelcontextprotocol/sdk/dist/esm/experimental/tasks/mcp-server.js
28567
28992
  class ExperimentalMcpServerTasks {
28568
28993
  constructor(_mcpServer) {
28569
28994
  this._mcpServer = _mcpServer;
@@ -28578,13 +29003,13 @@ class ExperimentalMcpServerTasks {
28578
29003
  }
28579
29004
  }
28580
29005
 
28581
- // node_modules/zod/index.js
29006
+ // node_modules/.pnpm/zod@3.25.76/node_modules/zod/index.js
28582
29007
  var init_zod = __esm(() => {
28583
29008
  init_external2();
28584
29009
  init_external2();
28585
29010
  });
28586
29011
 
28587
- // node_modules/@modelcontextprotocol/sdk/dist/esm/server/mcp.js
29012
+ // node_modules/.pnpm/@modelcontextprotocol+sdk@1.30.0_zod@3.25.76/node_modules/@modelcontextprotocol/sdk/dist/esm/server/mcp.js
28588
29013
  class McpServer {
28589
29014
  constructor(serverInfo, options) {
28590
29015
  this._registeredResources = {};
@@ -28772,7 +29197,7 @@ class McpServer {
28772
29197
  let task = createTaskResult.task;
28773
29198
  const pollInterval = task.pollInterval ?? 5000;
28774
29199
  while (task.status !== "completed" && task.status !== "failed" && task.status !== "cancelled") {
28775
- await new Promise((resolve2) => setTimeout(resolve2, pollInterval));
29200
+ await new Promise((resolve3) => setTimeout(resolve3, pollInterval));
28776
29201
  const updatedTask = await extra.taskStore.getTask(taskId);
28777
29202
  if (!updatedTask) {
28778
29203
  throw new McpError(ErrorCode.InternalError, `Task ${taskId} not found during polling`);
@@ -29168,6 +29593,9 @@ class McpServer {
29168
29593
  annotations = rest.shift();
29169
29594
  }
29170
29595
  } else if (typeof firstArg === "object" && firstArg !== null) {
29596
+ if (Object.values(firstArg).some((v) => typeof v === "object" && v !== null)) {
29597
+ throw new Error(`Tool ${name} expected a Zod schema or ToolAnnotations, but received an unrecognized object`);
29598
+ }
29171
29599
  annotations = rest.shift();
29172
29600
  }
29173
29601
  }
@@ -29256,6 +29684,9 @@ function getZodSchemaObject(schema) {
29256
29684
  if (isZodRawShapeCompat(schema)) {
29257
29685
  return objectFromShape(schema);
29258
29686
  }
29687
+ if (!isZodSchemaInstance(schema)) {
29688
+ throw new Error("inputSchema must be a Zod schema or raw shape, received an unrecognized object");
29689
+ }
29259
29690
  return schema;
29260
29691
  }
29261
29692
  function promptArgumentsFromSchema(schema) {
@@ -29314,9 +29745,17 @@ var init_mcp = __esm(() => {
29314
29745
  };
29315
29746
  });
29316
29747
 
29317
- // node_modules/@modelcontextprotocol/sdk/dist/esm/shared/stdio.js
29748
+ // node_modules/.pnpm/@modelcontextprotocol+sdk@1.30.0_zod@3.25.76/node_modules/@modelcontextprotocol/sdk/dist/esm/shared/stdio.js
29318
29749
  class ReadBuffer {
29750
+ constructor(options) {
29751
+ this._maxBufferSize = options?.maxBufferSize ?? STDIO_DEFAULT_MAX_BUFFER_SIZE;
29752
+ }
29319
29753
  append(chunk) {
29754
+ const newSize = (this._buffer?.length ?? 0) + chunk.length;
29755
+ if (newSize > this._maxBufferSize) {
29756
+ this.clear();
29757
+ throw new Error(`ReadBuffer exceeded maximum size of ${this._maxBufferSize} bytes`);
29758
+ }
29320
29759
  this._buffer = this._buffer ? Buffer.concat([this._buffer, chunk]) : chunk;
29321
29760
  }
29322
29761
  readMessage() {
@@ -29343,26 +29782,33 @@ function serializeMessage(message) {
29343
29782
  return JSON.stringify(message) + `
29344
29783
  `;
29345
29784
  }
29785
+ var STDIO_DEFAULT_MAX_BUFFER_SIZE;
29346
29786
  var init_stdio = __esm(() => {
29347
29787
  init_types2();
29788
+ STDIO_DEFAULT_MAX_BUFFER_SIZE = 10 * 1024 * 1024;
29348
29789
  });
29349
29790
 
29350
- // node_modules/@modelcontextprotocol/sdk/dist/esm/server/stdio.js
29791
+ // node_modules/.pnpm/@modelcontextprotocol+sdk@1.30.0_zod@3.25.76/node_modules/@modelcontextprotocol/sdk/dist/esm/server/stdio.js
29351
29792
  import process2 from "process";
29352
29793
 
29353
29794
  class StdioServerTransport {
29354
- constructor(_stdin = process2.stdin, _stdout = process2.stdout) {
29795
+ constructor(_stdin = process2.stdin, _stdout = process2.stdout, options) {
29355
29796
  this._stdin = _stdin;
29356
29797
  this._stdout = _stdout;
29357
- this._readBuffer = new ReadBuffer;
29358
29798
  this._started = false;
29359
29799
  this._ondata = (chunk) => {
29360
- this._readBuffer.append(chunk);
29361
- this.processReadBuffer();
29800
+ try {
29801
+ this._readBuffer.append(chunk);
29802
+ this.processReadBuffer();
29803
+ } catch (error2) {
29804
+ this.onerror?.(error2);
29805
+ this.close().catch(() => {});
29806
+ }
29362
29807
  };
29363
29808
  this._onerror = (error2) => {
29364
29809
  this.onerror?.(error2);
29365
29810
  };
29811
+ this._readBuffer = new ReadBuffer({ maxBufferSize: options?.maxBufferSize });
29366
29812
  }
29367
29813
  async start() {
29368
29814
  if (this._started) {
@@ -29396,12 +29842,12 @@ class StdioServerTransport {
29396
29842
  this.onclose?.();
29397
29843
  }
29398
29844
  send(message) {
29399
- return new Promise((resolve2) => {
29845
+ return new Promise((resolve3) => {
29400
29846
  const json = serializeMessage(message);
29401
29847
  if (this._stdout.write(json)) {
29402
- resolve2();
29848
+ resolve3();
29403
29849
  } else {
29404
- this._stdout.once("drain", resolve2);
29850
+ this._stdout.once("drain", resolve3);
29405
29851
  }
29406
29852
  });
29407
29853
  }
@@ -29411,9 +29857,9 @@ var init_stdio2 = __esm(() => {
29411
29857
  });
29412
29858
 
29413
29859
  // src/lib/connector.ts
29414
- import { join as join6 } from "path";
29415
- import { existsSync as existsSync8, readFileSync as readFileSync4 } from "fs";
29416
- import { homedir as homedir2 } from "os";
29860
+ import { join as join10 } from "path";
29861
+ import { existsSync as existsSync10, readFileSync as readFileSync4 } from "fs";
29862
+ import { homedir as homedir6 } from "os";
29417
29863
  async function runConnector(name, args, opts = {}) {
29418
29864
  const binary = `connect-${name}`;
29419
29865
  const profile = opts.profile ?? "default";
@@ -29463,12 +29909,12 @@ async function runConnector(name, args, opts = {}) {
29463
29909
  }
29464
29910
  function getConnectorTokenPath(name, profile = "default") {
29465
29911
  const bases = [
29466
- join6(homedir2(), ".connectors", `connect-${name}`, "profiles", profile, "tokens.json"),
29467
- join6(homedir2(), ".connect", `connect-${name}`, "profiles", profile, "tokens.json"),
29468
- join6(homedir2(), ".connect", `connect-${name}`, "tokens.json")
29912
+ join10(homedir6(), ".connectors", `connect-${name}`, "profiles", profile, "tokens.json"),
29913
+ join10(homedir6(), ".connect", `connect-${name}`, "profiles", profile, "tokens.json"),
29914
+ join10(homedir6(), ".connect", `connect-${name}`, "tokens.json")
29469
29915
  ];
29470
29916
  for (const p of bases) {
29471
- if (existsSync8(p))
29917
+ if (existsSync10(p))
29472
29918
  return p;
29473
29919
  }
29474
29920
  return null;
@@ -30793,7 +31239,7 @@ var exports_document_scanner = {};
30793
31239
  __export(exports_document_scanner, {
30794
31240
  scanDocument: () => scanDocument
30795
31241
  });
30796
- import { readFileSync as readFileSync5, existsSync as existsSync9 } from "fs";
31242
+ import { readFileSync as readFileSync5, existsSync as existsSync11 } from "fs";
30797
31243
  import { extname as extname2 } from "path";
30798
31244
  async function scanDocument(imageSource, docType) {
30799
31245
  const apiKey = process.env["OPENAI_API_KEY"];
@@ -30803,7 +31249,7 @@ async function scanDocument(imageSource, docType) {
30803
31249
  let imageData;
30804
31250
  if (imageSource.startsWith("data:image/")) {
30805
31251
  imageData = imageSource;
30806
- } else if (existsSync9(imageSource)) {
31252
+ } else if (existsSync11(imageSource)) {
30807
31253
  const buffer = readFileSync5(imageSource);
30808
31254
  const ext = extname2(imageSource).slice(1).toLowerCase();
30809
31255
  const mime = ext === "jpg" || ext === "jpeg" ? "image/jpeg" : ext === "png" ? "image/png" : ext === "webp" ? "image/webp" : ext === "gif" ? "image/gif" : "image/jpeg";
@@ -30890,12 +31336,14 @@ Only include fields that are actually visible in the document. Return valid JSON
30890
31336
  var init_document_scanner = () => {};
30891
31337
 
30892
31338
  // src/mcp/handlers/advanced.ts
31339
+ import { join as join11 } from "path";
30893
31340
  var json3 = (v) => ({
30894
31341
  content: [{ type: "text", text: JSON.stringify(v, null, 2) }]
30895
31342
  }), _contactsAgents, advancedHandlers;
30896
31343
  var init_advanced = __esm(() => {
30897
31344
  init_store();
30898
31345
  init_document_scanner();
31346
+ init_images();
30899
31347
  _contactsAgents = new Map;
30900
31348
  advancedHandlers = {
30901
31349
  get_field_history: async (a) => json3({ history: await getStore().getFieldHistory(a.contact_id, a.field_name) }),
@@ -31054,8 +31502,9 @@ var init_advanced = __esm(() => {
31054
31502
  const { contact_id, image, format } = a;
31055
31503
  await store.getContact(contact_id);
31056
31504
  const filename = await store.saveImage(contact_id, image, { format });
31057
- await store.updateContact(contact_id, { avatar_url: `~/.hasna/contacts/images/${filename}` });
31058
- return json3({ ok: true, contact_id, filename, avatar_url: `~/.hasna/contacts/images/${filename}` });
31505
+ const avatarUrl = join11(getImagesDir(), filename);
31506
+ await store.updateContact(contact_id, { avatar_url: avatarUrl });
31507
+ return json3({ ok: true, contact_id, filename, avatar_url: avatarUrl });
31059
31508
  },
31060
31509
  get_contact_photo: async (a) => {
31061
31510
  const { contact_id } = a;
@@ -31077,8 +31526,9 @@ var init_advanced = __esm(() => {
31077
31526
  const { company_id, image, format } = a;
31078
31527
  await store.getCompany(company_id);
31079
31528
  const filename = await store.saveImage(company_id, image, { format });
31080
- await store.updateCompany(company_id, { logo_url: `~/.hasna/contacts/images/${filename}` });
31081
- return json3({ ok: true, company_id, filename, logo_url: `~/.hasna/contacts/images/${filename}` });
31529
+ const logoUrl = join11(getImagesDir(), filename);
31530
+ await store.updateCompany(company_id, { logo_url: logoUrl });
31531
+ return json3({ ok: true, company_id, filename, logo_url: logoUrl });
31082
31532
  },
31083
31533
  get_company_logo: async (a) => {
31084
31534
  const { company_id } = a;
@@ -32870,10 +33320,10 @@ var init_tools = __esm(() => {
32870
33320
  { name: "get_deal_team", description: "Get the full buying committee for a deal with contact names and roles.", inputSchema: { type: "object", properties: { deal_id: { type: "string" } }, required: ["deal_id"] } },
32871
33321
  { name: "get_coverage_gaps", description: "Identify coverage gaps in a company account \u2014 missing economic buyer, technical evaluator, or org chart relationships.", inputSchema: { type: "object", properties: { company_id: { type: "string" } }, required: ["company_id"] } },
32872
33322
  { name: "get_recent_contact_events", description: "Polling fallback for change events \u2014 returns recent activity log entries, optionally filtered by event type or date.", inputSchema: { type: "object", properties: { since: { type: "string", description: "ISO 8601 datetime \u2014 only events after this date" }, event_types: { type: "array", items: { type: "string" } } } } },
32873
- { name: "set_contact_photo", description: "Set a contact's profile photo. Provide either a local file path or base64-encoded image data (with or without data URI prefix). Stores image in ~/.hasna/contacts/images/ and updates avatar_url. Supported formats: jpg, png, gif, webp, svg, avif.", inputSchema: { type: "object", properties: { contact_id: { type: "string" }, image: { type: "string", description: "File path (e.g. /tmp/photo.jpg) OR base64 data (e.g. data:image/png;base64,...) OR raw base64 string" }, format: { type: "string", description: "Image format hint when using raw base64 (jpg, png, webp). Not needed for file paths or data URIs." } }, required: ["contact_id", "image"] } },
33323
+ { name: "set_contact_photo", description: "Set a contact's profile photo. Provide either a local file path or base64-encoded image data (with or without data URI prefix). Stores image in the XDG data root images dir and updates avatar_url. Supported formats: jpg, png, gif, webp, svg, avif.", inputSchema: { type: "object", properties: { contact_id: { type: "string" }, image: { type: "string", description: "File path (e.g. /tmp/photo.jpg) OR base64 data (e.g. data:image/png;base64,...) OR raw base64 string" }, format: { type: "string", description: "Image format hint when using raw base64 (jpg, png, webp). Not needed for file paths or data URIs." } }, required: ["contact_id", "image"] } },
32874
33324
  { name: "get_contact_photo", description: "Get a contact's profile photo as base64 data URI. Returns null if no photo is set.", inputSchema: { type: "object", properties: { contact_id: { type: "string" } }, required: ["contact_id"] } },
32875
33325
  { name: "delete_contact_photo", description: "Remove a contact's profile photo.", inputSchema: { type: "object", properties: { contact_id: { type: "string" } }, required: ["contact_id"] } },
32876
- { name: "set_company_logo", description: "Set a company's logo image. Provide either a local file path or base64-encoded image data. Stores image in ~/.hasna/contacts/images/ and updates logo_url.", inputSchema: { type: "object", properties: { company_id: { type: "string" }, image: { type: "string", description: "File path or base64 data" }, format: { type: "string", description: "Image format hint for raw base64" } }, required: ["company_id", "image"] } },
33326
+ { name: "set_company_logo", description: "Set a company's logo image. Provide either a local file path or base64-encoded image data. Stores image in the XDG data root images dir and updates logo_url.", inputSchema: { type: "object", properties: { company_id: { type: "string" }, image: { type: "string", description: "File path or base64 data" }, format: { type: "string", description: "Image format hint for raw base64" } }, required: ["company_id", "image"] } },
32877
33327
  { name: "get_company_logo", description: "Get a company's logo as base64 data URI.", inputSchema: { type: "object", properties: { company_id: { type: "string" } }, required: ["company_id"] } },
32878
33328
  { name: "delete_company_logo", description: "Remove a company's logo image.", inputSchema: { type: "object", properties: { company_id: { type: "string" } }, required: ["company_id"] } },
32879
33329
  { name: "set_sensitivity", description: "Set a contact's sensitivity level (normal, confidential, restricted). Restricted contacts are hidden from list/search unless explicitly requested.", inputSchema: { type: "object", properties: { contact_id: { type: "string" }, sensitivity: { type: "string", enum: ["normal", "confidential", "restricted"] } }, required: ["contact_id", "sensitivity"] } },
@@ -32881,7 +33331,7 @@ var init_tools = __esm(() => {
32881
33331
  { name: "vault_unlock", description: "Unlock the vault for this session with a passphrase.", inputSchema: { type: "object", properties: { passphrase: { type: "string" } }, required: ["passphrase"] } },
32882
33332
  { name: "vault_lock", description: "Lock the vault, clearing the encryption key from memory.", inputSchema: { type: "object", properties: {} } },
32883
33333
  { name: "vault_status", description: "Check vault initialization and lock status.", inputSchema: { type: "object", properties: {} } },
32884
- { name: "add_document", description: "Store a document for a contact (passport, tax_id, medical_record, etc.). Text values are encrypted; file attachments are stored plain so agents can read them. Vault must be unlocked.", inputSchema: { type: "object", properties: { contact_id: { type: "string" }, doc_type: { type: "string", enum: [...DOCUMENT_TYPES] }, label: { type: "string" }, value: { type: "string", description: "Plaintext value (will be encrypted in DB)" }, file_path: { type: "string", description: "File to attach \u2014 stored PLAIN in ~/.hasna/contacts/documents/ for agent access" }, metadata: { type: "object" }, expires_at: { type: "string" } }, required: ["contact_id", "doc_type", "value"] } },
33334
+ { name: "add_document", description: "Store a document for a contact (passport, tax_id, medical_record, etc.). Text values are encrypted; file attachments are stored plain so agents can read them. Vault must be unlocked.", inputSchema: { type: "object", properties: { contact_id: { type: "string" }, doc_type: { type: "string", enum: [...DOCUMENT_TYPES] }, label: { type: "string" }, value: { type: "string", description: "Plaintext value (will be encrypted in DB)" }, file_path: { type: "string", description: "File to attach \u2014 stored PLAIN in the XDG data root documents dir for agent access" }, metadata: { type: "object" }, expires_at: { type: "string" } }, required: ["contact_id", "doc_type", "value"] } },
32885
33335
  { name: "list_documents", description: "List documents for a contact (metadata only \u2014 no decryption needed). Returns file_path for attachments so agents can read them directly.", inputSchema: { type: "object", properties: { contact_id: { type: "string" } }, required: ["contact_id"] } },
32886
33336
  { name: "get_document", description: "Get a document with decrypted value and file_path. Vault must be unlocked for the text value; file is always accessible.", inputSchema: { type: "object", properties: { document_id: { type: "string" } }, required: ["document_id"] } },
32887
33337
  { name: "get_document_file", description: "Get the plain file path for a document attachment. Agents can read this file directly \u2014 it is NOT encrypted. Returns null if no file attached.", inputSchema: { type: "object", properties: { document_id: { type: "string" } }, required: ["document_id"] } },
@@ -33003,10 +33453,10 @@ var init_storage_tools = __esm(() => {
33003
33453
 
33004
33454
  // src/mcp/index.ts
33005
33455
  import { readFileSync as readFileSync6 } from "fs";
33006
- import { join as join7 } from "path";
33456
+ import { join as join12 } from "path";
33007
33457
  function getServerVersion() {
33008
33458
  try {
33009
- const packageJsonPath = join7(import.meta.dir, "..", "..", "package.json");
33459
+ const packageJsonPath = join12(import.meta.dir, "..", "..", "package.json");
33010
33460
  const pkg2 = JSON.parse(readFileSync6(packageJsonPath, "utf8"));
33011
33461
  return pkg2.version ?? "0.0.0";
33012
33462
  } catch {
@@ -37029,8 +37479,8 @@ var init_v1 = __esm(() => {
37029
37479
  });
37030
37480
 
37031
37481
  // src/lib/package-version.ts
37032
- import { existsSync as existsSync10, readFileSync as readFileSync8 } from "fs";
37033
- import { dirname as dirname2, join as join8 } from "path";
37482
+ import { existsSync as existsSync12, readFileSync as readFileSync8 } from "fs";
37483
+ import { dirname as dirname2, join as join13 } from "path";
37034
37484
  import { fileURLToPath } from "url";
37035
37485
  function getPackageVersion() {
37036
37486
  if (cached3)
@@ -37038,8 +37488,8 @@ function getPackageVersion() {
37038
37488
  try {
37039
37489
  let dir = dirname2(fileURLToPath(import.meta.url));
37040
37490
  for (let i = 0;i < 8; i++) {
37041
- const pkgPath = join8(dir, "package.json");
37042
- if (existsSync10(pkgPath)) {
37491
+ const pkgPath = join13(dir, "package.json");
37492
+ if (existsSync12(pkgPath)) {
37043
37493
  const pkg2 = JSON.parse(readFileSync8(pkgPath, "utf8"));
37044
37494
  if (pkg2.name === "@hasna/contacts" && pkg2.version) {
37045
37495
  cached3 = pkg2.version;
@@ -37634,8 +38084,8 @@ __export(exports_serve, {
37634
38084
  startServer: () => startServer,
37635
38085
  createContactsRequestHandler: () => createContactsRequestHandler
37636
38086
  });
37637
- import { existsSync as existsSync11 } from "fs";
37638
- import { join as join9, resolve as resolve2, relative } from "path";
38087
+ import { existsSync as existsSync13 } from "fs";
38088
+ import { join as join14, resolve as resolve3, relative } from "path";
37639
38089
  function json6(data, status = 200) {
37640
38090
  return new Response(JSON.stringify(data), {
37641
38091
  status,
@@ -37667,9 +38117,9 @@ function requireScope(req, scope, options) {
37667
38117
  function isResponse(value) {
37668
38118
  return value instanceof Response;
37669
38119
  }
37670
- function privateFileHeaders(contentType) {
38120
+ function privateFileHeaders(contentType2) {
37671
38121
  return {
37672
- ...contentType ? { "Content-Type": contentType } : {},
38122
+ ...contentType2 ? { "Content-Type": contentType2 } : {},
37673
38123
  "Cache-Control": "private, no-store",
37674
38124
  "X-Content-Type-Options": "nosniff"
37675
38125
  };
@@ -37677,9 +38127,9 @@ function privateFileHeaders(contentType) {
37677
38127
  function isSafeEntityId(id) {
37678
38128
  return /^[A-Za-z0-9][A-Za-z0-9_.:-]{0,127}$/.test(id) && !id.includes("..") && !id.includes("/");
37679
38129
  }
37680
- function isPathInside(baseDir, filePath) {
37681
- const base = resolve2(baseDir);
37682
- const file = resolve2(filePath);
38130
+ function isPathInside(baseDir3, filePath) {
38131
+ const base = resolve3(baseDir3);
38132
+ const file = resolve3(filePath);
37683
38133
  const rel = relative(base, file);
37684
38134
  return rel === "" || !!rel && !rel.startsWith("..") && !rel.startsWith("/") && !rel.includes("..\\");
37685
38135
  }
@@ -37918,7 +38368,7 @@ function handleDocumentFiles(req, segments, options) {
37918
38368
  if (sub === "file") {
37919
38369
  const db = getDatabase();
37920
38370
  const row = db.query(`SELECT encrypted_file_path FROM contact_documents WHERE id = ?`).get(docId);
37921
- if (!row?.encrypted_file_path || !isPathInside(getDocumentsDir(), row.encrypted_file_path) || !existsSync11(row.encrypted_file_path)) {
38371
+ if (!row?.encrypted_file_path || !isPathInside(getDocumentsDir(), row.encrypted_file_path) || !existsSync13(row.encrypted_file_path)) {
37922
38372
  return new Response("No file attachment", { status: 404 });
37923
38373
  }
37924
38374
  auditServerAccess("server.document.file.read", { document_id: docId }, principal);
@@ -37939,7 +38389,7 @@ async function handleImages(req, _url2, segments, options) {
37939
38389
  if (isResponse(principal))
37940
38390
  return principal;
37941
38391
  const imagePath = getImagePath(entityId);
37942
- if (!imagePath || !existsSync11(imagePath)) {
38392
+ if (!imagePath || !existsSync13(imagePath)) {
37943
38393
  return new Response(null, { status: 404, headers: { "Content-Type": "text/plain" } });
37944
38394
  }
37945
38395
  return new Response(Bun.file(imagePath), {
@@ -37950,15 +38400,15 @@ async function handleImages(req, _url2, segments, options) {
37950
38400
  const principal = requireScope(req, "images:write", options);
37951
38401
  if (isResponse(principal))
37952
38402
  return principal;
37953
- const contentType = req.headers.get("content-type") || "";
37954
- if (contentType.includes("multipart/form-data")) {
38403
+ const contentType2 = req.headers.get("content-type") || "";
38404
+ if (contentType2.includes("multipart/form-data")) {
37955
38405
  const formData = await req.formData();
37956
38406
  const file = formData.get("image");
37957
38407
  if (!file)
37958
38408
  return apiError("No image file in form data");
37959
38409
  const ext = file.name?.split(".").pop() || "jpg";
37960
38410
  const buffer = Buffer.from(await file.arrayBuffer());
37961
- const tmpPath = join9(getImagesDir(), `_upload_${entityId}.${ext}`);
38411
+ const tmpPath = join14(getImagesDir(), `_upload_${entityId}.${ext}`);
37962
38412
  const { writeFileSync: wfs } = await import("fs");
37963
38413
  wfs(tmpPath, buffer);
37964
38414
  try {
@@ -37995,7 +38445,7 @@ async function handleImages(req, _url2, segments, options) {
37995
38445
  return apiError("Method not allowed", 405);
37996
38446
  }
37997
38447
  function serveStaticFile(filePath) {
37998
- if (!existsSync11(filePath))
38448
+ if (!existsSync13(filePath))
37999
38449
  return null;
38000
38450
  return new Response(Bun.file(filePath));
38001
38451
  }
@@ -38079,8 +38529,8 @@ function createContactsRequestHandler(options = {}) {
38079
38529
  if (isResponse(principal)) {
38080
38530
  response = principal;
38081
38531
  } else {
38082
- const filePath = join9(DASHBOARD_DIST, url.pathname === "/" ? "index.html" : url.pathname);
38083
- response = serveStaticFile(filePath) ?? serveStaticFile(join9(DASHBOARD_DIST, "index.html")) ?? new Response("Not Found", { status: 404 });
38532
+ const filePath = join14(DASHBOARD_DIST, url.pathname === "/" ? "index.html" : url.pathname);
38533
+ response = serveStaticFile(filePath) ?? serveStaticFile(join14(DASHBOARD_DIST, "index.html")) ?? new Response("Not Found", { status: 404 });
38084
38534
  }
38085
38535
  }
38086
38536
  } catch (err2) {
@@ -38119,23 +38569,33 @@ var init_serve = __esm(() => {
38119
38569
  init_openapi();
38120
38570
  init_cloud();
38121
38571
  init_package_version();
38122
- DASHBOARD_DIST = join9(import.meta.dir, "../../dashboard/dist");
38572
+ DASHBOARD_DIST = join14(import.meta.dir, "../../dashboard/dist");
38123
38573
  });
38124
38574
 
38125
- // node_modules/@hasna/events/dist/commander.js
38575
+ // node_modules/.pnpm/@hasna+events@0.1.17/node_modules/@hasna/events/dist/commander.js
38126
38576
  var exports_commander = {};
38127
38577
  __export(exports_commander, {
38128
- registerWebhookCommands: () => registerWebhookCommands,
38129
38578
  registerEventsCommands: () => registerEventsCommands,
38130
- registerEventCommands: () => registerEventCommands
38579
+ registerEventCommands: () => registerEventCommands,
38580
+ registerChannelCommands: () => registerChannelCommands,
38581
+ DEFAULT_EVENT_LIST_LIMIT: () => DEFAULT_EVENT_LIST_LIMIT
38131
38582
  });
38132
38583
  import { chmod, mkdir, readFile, rename, writeFile } from "fs/promises";
38584
+ import { Buffer as Buffer2 } from "buffer";
38585
+ import { existsSync as existsSync2 } from "fs";
38586
+ import { join as join3 } from "path";
38133
38587
  import { existsSync } from "fs";
38588
+ import { homedir as homedir2 } from "os";
38589
+ import { join as join2, resolve } from "path";
38134
38590
  import { homedir } from "os";
38135
38591
  import { join } from "path";
38136
38592
  import { createHmac, timingSafeEqual } from "crypto";
38593
+ import { lookup as dnsLookup } from "dns/promises";
38594
+ import { isIP } from "net";
38137
38595
  import { randomUUID } from "crypto";
38138
38596
  import { spawn } from "child_process";
38597
+ import { request as nodeHttpRequest } from "http";
38598
+ import { request as nodeHttpsRequest } from "https";
38139
38599
  import { randomUUID as randomUUID2 } from "crypto";
38140
38600
  function getPathValue(input, path) {
38141
38601
  return path.split(".").reduce((value, part) => {
@@ -38145,29 +38605,83 @@ function getPathValue(input, path) {
38145
38605
  return;
38146
38606
  }, input);
38147
38607
  }
38148
- function wildcardToRegExp(pattern) {
38149
- const escaped = pattern.replace(/[|\\{}()[\]^$+?.]/g, "\\$&").replace(/\*/g, ".*");
38150
- return new RegExp(`^${escaped}$`);
38608
+ function getFieldValues(input, path) {
38609
+ const values = [];
38610
+ const push = (value) => {
38611
+ if (!values.some((item) => Object.is(item, value)))
38612
+ values.push(value);
38613
+ };
38614
+ if (path.includes(".") && path in input)
38615
+ push(input[path]);
38616
+ const nestedValue = getPathValue(input, path);
38617
+ if (nestedValue !== undefined || !path.includes("."))
38618
+ push(nestedValue);
38619
+ return values;
38620
+ }
38621
+ function wildcardToRegExp(pattern, options = {}) {
38622
+ let body = "";
38623
+ for (let index = 0;index < pattern.length; index += 1) {
38624
+ const char = pattern[index];
38625
+ if (char === "*") {
38626
+ if (pattern[index + 1] === "*") {
38627
+ body += ".*";
38628
+ index += 1;
38629
+ } else {
38630
+ body += options.segmentSafe ? "[^/]*" : ".*";
38631
+ }
38632
+ } else {
38633
+ body += char.replace(/[|\\{}()[\]^$+?.]/g, "\\$&");
38634
+ }
38635
+ }
38636
+ return new RegExp(`^${body}$`);
38151
38637
  }
38152
- function matchString(value, matcher) {
38638
+ function matchString(value, matcher, options = {}) {
38153
38639
  if (matcher === undefined)
38154
38640
  return true;
38155
38641
  if (value === undefined)
38156
38642
  return false;
38157
38643
  const matchers = Array.isArray(matcher) ? matcher : [matcher];
38158
- return matchers.some((item) => wildcardToRegExp(item).test(value));
38644
+ return matchers.some((item) => wildcardToRegExp(item, options).test(value));
38159
38645
  }
38160
38646
  function matchRecord(input, matcher) {
38161
38647
  if (!matcher)
38162
38648
  return true;
38163
38649
  return Object.entries(matcher).every(([path, expected]) => {
38164
- const actual = getPathValue(input, path);
38165
- if (typeof expected === "string" || Array.isArray(expected)) {
38166
- return matchString(actual === undefined ? undefined : String(actual), expected);
38167
- }
38168
- return actual === expected;
38650
+ const actualValues = getFieldValues(input, path);
38651
+ return matchField(actualValues, expected, path);
38169
38652
  });
38170
38653
  }
38654
+ function matchField(actualValues, expected, path) {
38655
+ if (isNegativeMatcher(expected)) {
38656
+ return !actualValues.some((actual) => matchPositiveField(actual, expected.not, path));
38657
+ }
38658
+ return actualValues.some((actual) => matchPositiveField(actual, expected, path));
38659
+ }
38660
+ function matchPositiveField(actual, expected, path) {
38661
+ if (typeof expected === "string" || Array.isArray(expected)) {
38662
+ return stringCandidates(actual).some((candidate) => matchString(candidate, expected, {
38663
+ segmentSafe: path.endsWith("_path") || path.endsWith(".path")
38664
+ }));
38665
+ }
38666
+ if (Array.isArray(actual)) {
38667
+ return actual.some((item) => item === expected);
38668
+ }
38669
+ return actual === expected;
38670
+ }
38671
+ function stringCandidates(actual) {
38672
+ if (actual === undefined)
38673
+ return [];
38674
+ if (Array.isArray(actual)) {
38675
+ return actual.flatMap((item) => isPrimitiveFieldValue(item) ? [String(item)] : []);
38676
+ }
38677
+ return [String(actual)];
38678
+ }
38679
+ function isPrimitiveFieldValue(value) {
38680
+ return value === null || typeof value === "string" || typeof value === "number" || typeof value === "boolean";
38681
+ }
38682
+ function isNegativeMatcher(value) {
38683
+ return Boolean(value && typeof value === "object" && !Array.isArray(value) && "not" in value);
38684
+ }
38171
38685
  function eventMatchesFilter(event, filter) {
38172
38686
  return matchString(event.source, filter.source) && matchString(event.type, filter.type) && matchString(event.subject, filter.subject) && matchString(event.severity, filter.severity) && matchRecord(event.data, filter.data) && matchRecord(event.metadata, filter.metadata);
38173
38687
  }
@@ -38178,22 +38692,127 @@ function channelMatchesEvent(channel, event) {
38178
38692
  return true;
38179
38693
  return channel.filters.some((filter) => eventMatchesFilter(event, filter));
38180
38694
  }
38695
+ var KIND_ENV = {
38696
+ config: "HASNA_CONFIG_HOME",
38697
+ data: "HASNA_DATA_HOME",
38698
+ state: "HASNA_STATE_HOME",
38699
+ cache: "HASNA_CACHE_HOME"
38700
+ };
38701
+ var APP_SLUG_RE = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
38702
+ function assertApp(app) {
38703
+ if (typeof app !== "string" || app.length === 0) {
38704
+ throw new TypeError("paths: app must be a non-empty string");
38705
+ }
38706
+ if (!APP_SLUG_RE.test(app)) {
38707
+ throw new TypeError(`paths: invalid app slug "${app}" \u2014 expected lowercase kebab-case ([a-z0-9]+(-[a-z0-9]+)*)`);
38708
+ }
38709
+ }
38710
+ function envOf(options) {
38711
+ return options.env ?? process.env;
38712
+ }
38713
+ function envValue(options, kind) {
38714
+ const value = envOf(options)[KIND_ENV[kind]];
38715
+ return typeof value === "string" && value.length > 0 ? value : undefined;
38716
+ }
38717
+ function isMacOS(platform) {
38718
+ return platform === "darwin";
38719
+ }
38720
+ function baseDir(kind, options) {
38721
+ const override = envValue(options, kind);
38722
+ if (override)
38723
+ return override;
38724
+ const home = options.home ?? homedir();
38725
+ const platform = options.platform ?? process.platform;
38726
+ if (isMacOS(platform)) {
38727
+ switch (kind) {
38728
+ case "config":
38729
+ case "data":
38730
+ return join(home, "Library", "Application Support", "Hasna");
38731
+ case "cache":
38732
+ return join(home, "Library", "Caches", "Hasna");
38733
+ case "state":
38734
+ return join(home, "Library", "Logs", "Hasna");
38735
+ }
38736
+ }
38737
+ switch (kind) {
38738
+ case "config":
38739
+ return join(home, ".config", "hasna");
38740
+ case "data":
38741
+ return join(home, ".local", "share", "hasna");
38742
+ case "state":
38743
+ return join(home, ".local", "state", "hasna");
38744
+ case "cache":
38745
+ return join(home, ".cache", "hasna");
38746
+ }
38747
+ }
38748
+ function resolvePath(kind, options) {
38749
+ assertApp(options.app);
38750
+ const appSegment = options.internal === true ? join("internal", options.app) : options.app;
38751
+ return join(baseDir(kind, options), appSegment);
38752
+ }
38753
+ function dataDir(options) {
38754
+ return resolvePath("data", options);
38755
+ }
38181
38756
  var HASNA_EVENTS_DIR_ENV = "HASNA_EVENTS_DIR";
38182
38757
  var HASNA_EVENTS_HOME_ENV = "HASNA_EVENTS_HOME";
38758
+ var EVENTS_STORE_SENTINEL_FILE = "events.json";
38759
+ function effectiveHome() {
38760
+ return process.env["HOME"] || process.env["USERPROFILE"] || homedir2();
38761
+ }
38762
+ function legacyHomeDir() {
38763
+ return join2(effectiveHome(), ".hasna", "events");
38764
+ }
38765
+ function resolverHome() {
38766
+ return dataDir({ app: "events", home: effectiveHome() || undefined });
38767
+ }
38768
+ function adoptResolverHome(resolved, env = process.env) {
38769
+ const dataOverride = env.HASNA_DATA_HOME;
38770
+ if (typeof dataOverride === "string" && dataOverride.trim().length > 0)
38771
+ return true;
38772
+ return existsSync(join2(resolved, EVENTS_STORE_SENTINEL_FILE));
38773
+ }
38774
+ function exactEventsHome() {
38775
+ const dir = process.env[HASNA_EVENTS_DIR_ENV];
38776
+ if (dir && dir.trim())
38777
+ return dir.trim();
38778
+ const home = process.env[HASNA_EVENTS_HOME_ENV];
38779
+ if (home && home.trim())
38780
+ return home.trim();
38781
+ return;
38782
+ }
38783
+ function getEventsHome() {
38784
+ const exact = exactEventsHome();
38785
+ if (exact)
38786
+ return resolve(exact);
38787
+ const resolved = resolverHome();
38788
+ return adoptResolverHome(resolved) ? resolve(resolved) : resolve(legacyHomeDir());
38789
+ }
38790
+ var LOCAL_JSON_EVENT_CURSOR_PREFIX = "local-json-v1:";
38791
+ var DEFAULT_EVENT_PAGE_LIMIT = 100;
38792
+ var MAX_EVENT_PAGE_LIMIT = 1000;
38183
38793
  function getEventsDataDir(override) {
38184
- return override || process.env[HASNA_EVENTS_DIR_ENV] || process.env[HASNA_EVENTS_HOME_ENV] || join(homedir(), ".hasna", "events");
38794
+ return override || getEventsHome();
38795
+ }
38796
+ function getActiveEventsDirEnv() {
38797
+ if (process.env[HASNA_EVENTS_DIR_ENV])
38798
+ return HASNA_EVENTS_DIR_ENV;
38799
+ if (process.env[HASNA_EVENTS_HOME_ENV])
38800
+ return HASNA_EVENTS_HOME_ENV;
38801
+ return null;
38185
38802
  }
38186
38803
 
38187
38804
  class JsonEventsStore {
38188
38805
  dataDir;
38806
+ runtime;
38189
38807
  channelsPath;
38190
38808
  eventsPath;
38191
38809
  deliveriesPath;
38192
- constructor(dataDir = getEventsDataDir()) {
38193
- this.dataDir = dataDir;
38194
- this.channelsPath = join(dataDir, "channels.json");
38195
- this.eventsPath = join(dataDir, "events.json");
38196
- this.deliveriesPath = join(dataDir, "deliveries.json");
38810
+ constructor(dataDir2 = getEventsDataDir()) {
38811
+ this.dataDir = dataDir2;
38812
+ this.runtime = localJsonRuntime(dataDir2);
38813
+ this.channelsPath = join3(dataDir2, "channels.json");
38814
+ this.eventsPath = join3(dataDir2, "events.json");
38815
+ this.deliveriesPath = join3(dataDir2, "deliveries.json");
38197
38816
  }
38198
38817
  async init() {
38199
38818
  await mkdir(this.dataDir, { recursive: true, mode: 448 });
@@ -38238,13 +38857,58 @@ class JsonEventsStore {
38238
38857
  await this.writeJson(this.eventsPath, events);
38239
38858
  return event;
38240
38859
  }
38241
- async listEvents() {
38860
+ async appendEventOnce(event, options = {}) {
38861
+ await this.init();
38862
+ const events = await this.readJson(this.eventsPath, []);
38863
+ const dedupe = options.dedupe !== false;
38864
+ if (dedupe) {
38865
+ const existing = findEventByIdentity(events, { id: event.id, dedupeKey: event.dedupeKey });
38866
+ if (existing) {
38867
+ return {
38868
+ event: existing,
38869
+ stored: false,
38870
+ deduped: true,
38871
+ identity: { id: existing.id, dedupeKey: existing.dedupeKey }
38872
+ };
38873
+ }
38874
+ }
38875
+ events.push(event);
38876
+ await this.writeJson(this.eventsPath, events);
38877
+ return {
38878
+ event,
38879
+ stored: true,
38880
+ deduped: false,
38881
+ identity: { id: event.id, dedupeKey: event.dedupeKey }
38882
+ };
38883
+ }
38884
+ async listEvents(options = {}) {
38242
38885
  await this.init();
38243
- return this.readJson(this.eventsPath, []);
38886
+ const events = await this.readJson(this.eventsPath, []);
38887
+ return queryEvents(events, options);
38888
+ }
38889
+ async listEventsPage(options = {}) {
38890
+ await this.init();
38891
+ const events = await this.readJson(this.eventsPath, []);
38892
+ const queried = queryEvents(events, {
38893
+ eventId: options.eventId,
38894
+ source: options.source,
38895
+ type: options.type
38896
+ });
38897
+ const offset = decodeLocalJsonEventCursor(options.cursor, options);
38898
+ const limit = normalizeEventPageLimit(options.limit);
38899
+ const pageEvents = queried.slice(offset, offset + limit);
38900
+ const nextOffset = offset + pageEvents.length;
38901
+ const hasMore = nextOffset < queried.length;
38902
+ return {
38903
+ events: pageEvents,
38904
+ cursor: options.cursor,
38905
+ nextCursor: hasMore ? encodeLocalJsonEventCursor(nextOffset, options) : undefined,
38906
+ hasMore
38907
+ };
38244
38908
  }
38245
38909
  async findEventByIdentity(identity) {
38246
38910
  const events = await this.listEvents();
38247
- return events.find((event) => identity.id !== undefined && event.id === identity.id || identity.dedupeKey !== undefined && event.dedupeKey === identity.dedupeKey);
38911
+ return findEventByIdentity(events, identity);
38248
38912
  }
38249
38913
  async appendDelivery(result) {
38250
38914
  await this.init();
@@ -38265,7 +38929,7 @@ class JsonEventsStore {
38265
38929
  };
38266
38930
  }
38267
38931
  async ensureArrayFile(path) {
38268
- if (!existsSync(path)) {
38932
+ if (!existsSync2(path)) {
38269
38933
  await writeFile(path, `[]
38270
38934
  `, { encoding: "utf-8", mode: 384 });
38271
38935
  }
@@ -38295,6 +38959,130 @@ class JsonEventsStore {
38295
38959
  });
38296
38960
  }
38297
38961
  }
38962
+ function localJsonRuntime(dataDir2 = getEventsDataDir()) {
38963
+ return {
38964
+ mode: "local-files",
38965
+ name: "json-events-store",
38966
+ remote: false,
38967
+ localFiles: true,
38968
+ localSqlite: false,
38969
+ postgres: false,
38970
+ s3: false,
38971
+ aws: false,
38972
+ durable: true,
38973
+ idempotency: "best-effort-local",
38974
+ replayCursors: true,
38975
+ description: `Local JSON files in ${dataDir2}; no SQLite, Postgres, S3, or AWS runtime is configured by this store.`
38976
+ };
38977
+ }
38978
+ function encodeLocalJsonEventCursor(offset, options = {}) {
38979
+ if (!Number.isInteger(offset) || offset < 0)
38980
+ throw new Error(`Invalid event cursor offset: ${offset}`);
38981
+ const payload = {
38982
+ offset,
38983
+ eventId: options.eventId,
38984
+ source: options.source,
38985
+ type: options.type
38986
+ };
38987
+ return `${LOCAL_JSON_EVENT_CURSOR_PREFIX}${Buffer2.from(JSON.stringify(payload), "utf-8").toString("base64url")}`;
38988
+ }
38989
+ function decodeLocalJsonEventCursor(cursor, options = {}) {
38990
+ if (!cursor)
38991
+ return 0;
38992
+ if (!cursor.startsWith(LOCAL_JSON_EVENT_CURSOR_PREFIX))
38993
+ throw new Error(`Invalid local JSON event cursor: ${cursor}`);
38994
+ const rawPayload = cursor.slice(LOCAL_JSON_EVENT_CURSOR_PREFIX.length);
38995
+ let payload;
38996
+ try {
38997
+ payload = JSON.parse(Buffer2.from(rawPayload, "base64url").toString("utf-8"));
38998
+ } catch {
38999
+ throw new Error(`Invalid local JSON event cursor: ${cursor}`);
39000
+ }
39001
+ const offset = payload.offset;
39002
+ if (!Number.isInteger(offset) || offset < 0)
39003
+ throw new Error(`Invalid local JSON event cursor: ${cursor}`);
39004
+ assertCursorFilter("eventId", payload.eventId, options.eventId);
39005
+ assertCursorFilter("source", payload.source, options.source);
39006
+ assertCursorFilter("type", payload.type, options.type);
39007
+ return offset;
39008
+ }
39009
+ function normalizeEventPageLimit(limit) {
39010
+ if (limit === undefined)
39011
+ return DEFAULT_EVENT_PAGE_LIMIT;
39012
+ if (!Number.isInteger(limit) || limit < 1)
39013
+ throw new Error(`Event page limit must be a positive integer, got ${limit}`);
39014
+ return Math.min(limit, MAX_EVENT_PAGE_LIMIT);
39015
+ }
39016
+ function queryEvents(events, options) {
39017
+ let rows = events;
39018
+ if (options.eventId)
39019
+ rows = rows.filter((event) => event.id === options.eventId);
39020
+ if (options.source)
39021
+ rows = rows.filter((event) => event.source === options.source);
39022
+ if (options.type)
39023
+ rows = rows.filter((event) => event.type === options.type);
39024
+ if (options.cursor) {
39025
+ const offset = decodeLocalJsonEventCursor(options.cursor, options);
39026
+ rows = rows.slice(offset);
39027
+ }
39028
+ if (options.limit !== undefined)
39029
+ rows = rows.slice(0, normalizeEventPageLimit(options.limit));
39030
+ return rows;
39031
+ }
39032
+ function assertCursorFilter(name, cursorValue, optionValue) {
39033
+ if (cursorValue !== optionValue)
39034
+ throw new Error(`Local JSON event cursor ${name} filter mismatch`);
39035
+ }
39036
+ function findEventByIdentity(events, identity) {
39037
+ return events.find((event) => identity.id !== undefined && event.id === identity.id || identity.dedupeKey !== undefined && event.dedupeKey === identity.dedupeKey);
39038
+ }
39039
+ async function getEventsStatus(dataDir2) {
39040
+ const store = new JsonEventsStore(dataDir2);
39041
+ await store.init();
39042
+ const [channels, events, deliveries] = await Promise.all([
39043
+ store.listChannels(),
39044
+ store.listEvents(),
39045
+ store.listDeliveries()
39046
+ ]);
39047
+ const transports = channels.reduce((counts, channel) => {
39048
+ counts[channel.transport] = (counts[channel.transport] ?? 0) + 1;
39049
+ return counts;
39050
+ }, {});
39051
+ return {
39052
+ service: "events",
39053
+ schemaVersion: "1.0",
39054
+ dataDir: store.dataDir,
39055
+ storage: store.runtime,
39056
+ env: {
39057
+ primary: HASNA_EVENTS_DIR_ENV,
39058
+ fallback: HASNA_EVENTS_HOME_ENV,
39059
+ active: getActiveEventsDirEnv()
39060
+ },
39061
+ files: {
39062
+ channels: statusFile(store.dataDir, "channels.json", channels.length),
39063
+ events: statusFile(store.dataDir, "events.json", events.length),
39064
+ deliveries: statusFile(store.dataDir, "deliveries.json", deliveries.length)
39065
+ },
39066
+ counts: {
39067
+ channels: channels.length,
39068
+ enabledChannels: channels.filter((channel) => channel.enabled).length,
39069
+ disabledChannels: channels.filter((channel) => !channel.enabled).length,
39070
+ events: events.length,
39071
+ deliveries: deliveries.length
39072
+ },
39073
+ transports,
39074
+ safety: {
39075
+ includesEventPayloads: false,
39076
+ includesWebhookSecrets: false,
39077
+ listOutputsRedactSecrets: true,
39078
+ statusOutputIsMetadataOnly: true
39079
+ }
39080
+ };
39081
+ }
39082
+ function statusFile(dataDir2, fileName, records) {
39083
+ const path = join3(dataDir2, fileName);
39084
+ return { path, exists: existsSync2(path), records };
39085
+ }
38298
39086
  var DEFAULT_SIGNATURE_TOLERANCE_MS = 5 * 60 * 1000;
38299
39087
  function buildSignatureBase(timestamp, body) {
38300
39088
  return `${timestamp}.${body}`;
@@ -38303,39 +39091,280 @@ function signPayload(secret, timestamp, body) {
38303
39091
  const digest = createHmac("sha256", secret).update(buildSignatureBase(timestamp, body)).digest("hex");
38304
39092
  return `sha256=${digest}`;
38305
39093
  }
39094
+ var DEFAULT_MAX_REDIRECTS = 5;
39095
+ var IPV4_PRIVATE_RANGES = [
39096
+ [0, 16777215],
39097
+ [167772160, 184549375],
39098
+ [1681915904, 1686110207],
39099
+ [2130706432, 2147483647],
39100
+ [2851995648, 2852061183],
39101
+ [2886729728, 2887778303],
39102
+ [3221225472, 3221225727],
39103
+ [3221225984, 3221226239],
39104
+ [3227017984, 3227018239],
39105
+ [3232235520, 3232301055],
39106
+ [3323068416, 3323199487],
39107
+ [3325256704, 3325256959],
39108
+ [3405803776, 3405804031],
39109
+ [3758096384, 4294967295]
39110
+ ];
39111
+ var IPV6_SPECIAL_PREFIXES = [
39112
+ { groups: [0, 0, 0, 0, 0, 0, 0, 0], bits: 128 },
39113
+ { groups: [0, 0, 0, 0, 0, 0, 0, 1], bits: 128 },
39114
+ { groups: [0, 0, 0, 0, 0, 65535, 0, 0], bits: 96 },
39115
+ { groups: [100, 65435, 0, 0, 0, 0, 0, 0], bits: 96 },
39116
+ { groups: [256, 0, 0, 0, 0, 0, 0, 0], bits: 64 },
39117
+ { groups: [8193, 0, 0, 0, 0, 0, 0, 0], bits: 32 },
39118
+ { groups: [8193, 2, 0, 0, 0, 0, 0, 0], bits: 48 },
39119
+ { groups: [8193, 16, 0, 0, 0, 0, 0, 0], bits: 28 },
39120
+ { groups: [8193, 3512, 0, 0, 0, 0, 0, 0], bits: 32 },
39121
+ { groups: [8194, 0, 0, 0, 0, 0, 0, 0], bits: 16 },
39122
+ { groups: [16383, 0, 0, 0, 0, 0, 0, 0], bits: 20 },
39123
+ { groups: [64512, 0, 0, 0, 0, 0, 0, 0], bits: 7 },
39124
+ { groups: [65152, 0, 0, 0, 0, 0, 0, 0], bits: 10 },
39125
+ { groups: [65216, 0, 0, 0, 0, 0, 0, 0], bits: 10 },
39126
+ { groups: [65280, 0, 0, 0, 0, 0, 0, 0], bits: 8 }
39127
+ ];
39128
+ function isPrivateAddress(address) {
39129
+ const normalized = stripZoneId(address);
39130
+ const version = isIP(normalized);
39131
+ if (version === 4) {
39132
+ const integer = ipv4ToInt(normalized);
39133
+ if (integer === undefined)
39134
+ return true;
39135
+ return IPV4_PRIVATE_RANGES.some(([low, high]) => integer >= low && integer <= high);
39136
+ }
39137
+ if (version === 6) {
39138
+ const groups = ipv6Groups(normalized);
39139
+ if (!groups)
39140
+ return true;
39141
+ for (const prefix of IPV6_SPECIAL_PREFIXES) {
39142
+ if (!ipv6MatchesPrefix(groups, prefix.groups, prefix.bits))
39143
+ continue;
39144
+ if (prefix.bits === 96 && groups[5] === 65535) {
39145
+ return isPrivateAddress(ipv4IntToString(groups[6] << 16 | groups[7]));
39146
+ }
39147
+ if (prefix.bits === 16 && groups[0] === 8194) {
39148
+ return isPrivateAddress(ipv4IntToString(groups[1] << 16 | groups[2]));
39149
+ }
39150
+ return true;
39151
+ }
39152
+ return false;
39153
+ }
39154
+ return true;
39155
+ }
39156
+ async function resolveWebhookTarget(url, policy = {}) {
39157
+ const hostname = normalizeHostname(url.hostname);
39158
+ const allowlist = (policy.allowPrivateHosts ?? []).map((entry) => normalizeHostname(entry.toLowerCase()));
39159
+ if (allowlist.includes(hostname)) {
39160
+ const version2 = isIP(hostname);
39161
+ if (version2 === 4 || version2 === 6) {
39162
+ return { hostname, addresses: [hostname] };
39163
+ }
39164
+ const lookup2 = policy.lookup ?? defaultTargetLookup;
39165
+ let resolved2;
39166
+ try {
39167
+ resolved2 = await lookup2(hostname);
39168
+ } catch {
39169
+ throw new Error(`Webhook target ${hostname} could not be resolved`);
39170
+ }
39171
+ if (!Array.isArray(resolved2) || resolved2.length === 0) {
39172
+ throw new Error(`Webhook target ${hostname} resolved to no addresses`);
39173
+ }
39174
+ const addresses = resolved2.map((entry) => normalizeHostname(entry.address));
39175
+ return { hostname, addresses };
39176
+ }
39177
+ const version = isIP(hostname);
39178
+ if (version === 4 || version === 6) {
39179
+ if (isPrivateAddress(hostname)) {
39180
+ throw new Error(`Webhook target ${hostname} is a private or special-use address`);
39181
+ }
39182
+ return { hostname, addresses: [hostname] };
39183
+ }
39184
+ const lookup = policy.lookup ?? defaultTargetLookup;
39185
+ let resolved;
39186
+ try {
39187
+ resolved = await lookup(hostname);
39188
+ } catch {
39189
+ throw new Error(`Webhook target ${hostname} could not be resolved`);
39190
+ }
39191
+ if (!Array.isArray(resolved) || resolved.length === 0) {
39192
+ throw new Error(`Webhook target ${hostname} resolved to no addresses`);
39193
+ }
39194
+ const allowed = [];
39195
+ for (const entry of resolved) {
39196
+ const address = normalizeHostname(entry.address);
39197
+ if (isPrivateAddress(address)) {
39198
+ if (allowlist.includes(address)) {
39199
+ allowed.push(address);
39200
+ continue;
39201
+ }
39202
+ throw new Error(`Webhook target ${hostname} resolves to private or special-use address ${address}`);
39203
+ }
39204
+ allowed.push(address);
39205
+ }
39206
+ if (allowed.length === 0) {
39207
+ throw new Error(`Webhook target ${hostname} resolved to no public addresses`);
39208
+ }
39209
+ return { hostname, addresses: allowed };
39210
+ }
39211
+ function normalizeMaxRedirects(value) {
39212
+ if (value === undefined)
39213
+ return DEFAULT_MAX_REDIRECTS;
39214
+ if (!Number.isInteger(value) || value < 0)
39215
+ throw new Error("webhookTargetPolicy.maxRedirects must be a non-negative integer");
39216
+ return value;
39217
+ }
39218
+ var defaultTargetLookup = async (hostname) => {
39219
+ return dnsLookup(hostname, { all: true, verbatim: false });
39220
+ };
39221
+ function normalizeHostname(hostname) {
39222
+ const lower = hostname.toLowerCase();
39223
+ if (lower.startsWith("[") && lower.endsWith("]"))
39224
+ return lower.slice(1, -1);
39225
+ return lower;
39226
+ }
39227
+ function stripZoneId(address) {
39228
+ const percent = address.indexOf("%");
39229
+ return percent === -1 ? address : address.slice(0, percent);
39230
+ }
39231
+ function ipv4ToInt(address) {
39232
+ const parts = address.split(".");
39233
+ if (parts.length !== 4)
39234
+ return;
39235
+ let value = 0;
39236
+ for (const part of parts) {
39237
+ if (!/^\d{1,3}$/.test(part))
39238
+ return;
39239
+ const octet = Number(part);
39240
+ if (octet > 255)
39241
+ return;
39242
+ value = value << 8 | octet;
39243
+ }
39244
+ return value >>> 0;
39245
+ }
39246
+ function ipv4IntToString(integer) {
39247
+ return [
39248
+ integer >>> 24 & 255,
39249
+ integer >>> 16 & 255,
39250
+ integer >>> 8 & 255,
39251
+ integer & 255
39252
+ ].join(".");
39253
+ }
39254
+ function ipv6Groups(address) {
39255
+ const raw = stripZoneId(address);
39256
+ const doubleColon = raw.indexOf("::");
39257
+ const headText = doubleColon === -1 ? raw : raw.slice(0, doubleColon);
39258
+ const tailText = doubleColon === -1 ? "" : raw.slice(doubleColon + 2);
39259
+ const parseGroups = (text) => {
39260
+ if (text === "")
39261
+ return [];
39262
+ const out = [];
39263
+ for (const part of text.split(":")) {
39264
+ if (part.includes(".")) {
39265
+ const v4 = ipv4ToInt(part);
39266
+ if (v4 === undefined)
39267
+ return;
39268
+ out.push(v4 >>> 16 & 65535, v4 & 65535);
39269
+ } else {
39270
+ if (!/^[0-9a-fA-F]{1,4}$/.test(part))
39271
+ return;
39272
+ out.push(parseInt(part, 16));
39273
+ }
39274
+ }
39275
+ return out;
39276
+ };
39277
+ const head = parseGroups(headText);
39278
+ if (!head)
39279
+ return;
39280
+ const tail = parseGroups(tailText);
39281
+ if (!tail)
39282
+ return;
39283
+ const total = head.length + tail.length;
39284
+ if (doubleColon === -1) {
39285
+ return total === 8 ? head : undefined;
39286
+ }
39287
+ if (total >= 8)
39288
+ return;
39289
+ return [...head, ...new Array(8 - total).fill(0), ...tail];
39290
+ }
39291
+ function ipv6MatchesPrefix(groups, prefixGroups, prefixBits) {
39292
+ let remaining = prefixBits;
39293
+ for (let index = 0;index < prefixGroups.length && remaining > 0; index += 1) {
39294
+ const take = Math.min(16, remaining);
39295
+ const mask = 65535 << 16 - take & 65535;
39296
+ if ((groups[index] & mask) !== (prefixGroups[index] & mask))
39297
+ return false;
39298
+ remaining -= take;
39299
+ }
39300
+ return true;
39301
+ }
38306
39302
  function now() {
38307
39303
  return new Date().toISOString();
38308
39304
  }
38309
39305
  function truncate(value, max = 4096) {
38310
39306
  return value.length > max ? `${value.slice(0, max)}...` : value;
38311
39307
  }
38312
- function buildWebhookRequest(event, channel) {
39308
+ function buildWebhookRequest(event, channel, options = {}) {
38313
39309
  if (!channel.webhook)
38314
39310
  throw new Error(`Channel ${channel.id} has no webhook config`);
39311
+ for (const name of Object.keys(channel.webhook.headers ?? {})) {
39312
+ if (/^x-hasna-/i.test(name)) {
39313
+ throw new Error(`Webhook header ${name} is reserved for signed delivery metadata`);
39314
+ }
39315
+ }
38315
39316
  const body = JSON.stringify(event);
38316
- const timestamp = event.time;
39317
+ const timestamp = options.timestamp ?? new Date().toISOString();
38317
39318
  const headers = {
38318
39319
  "Content-Type": "application/json",
38319
39320
  "User-Agent": "@hasna/events",
38320
39321
  "X-Hasna-Event-Id": event.id,
38321
39322
  "X-Hasna-Event-Type": event.type,
38322
- "X-Hasna-Timestamp": timestamp,
38323
- ...channel.webhook.headers
39323
+ ...channel.webhook.headers,
39324
+ "X-Hasna-Timestamp": timestamp
38324
39325
  };
38325
- if (channel.webhook.secret) {
38326
- headers["X-Hasna-Signature"] = signPayload(channel.webhook.secret, timestamp, body);
39326
+ const secret = options.secret ?? channel.webhook.secret;
39327
+ if (secret) {
39328
+ headers["X-Hasna-Signature"] = signPayload(secret, timestamp, body);
38327
39329
  }
38328
39330
  return { body, headers };
38329
39331
  }
39332
+ function normalizeWebhookUrl(raw) {
39333
+ const url = new URL(raw);
39334
+ if (url.username !== "" || url.password !== "") {
39335
+ url.username = "";
39336
+ url.password = "";
39337
+ }
39338
+ return url.toString();
39339
+ }
38330
39340
  async function dispatchWebhook(event, channel, options = {}) {
38331
39341
  if (!channel.webhook)
38332
39342
  throw new Error(`Channel ${channel.id} has no webhook config`);
39343
+ const webhookUrl = normalizeWebhookUrl(channel.webhook.url);
38333
39344
  const startedAt = now();
38334
- const { body, headers } = buildWebhookRequest(event, channel);
39345
+ let secret = channel.webhook.secret;
39346
+ if (channel.webhook.secretRef) {
39347
+ if (!options.secretResolver) {
39348
+ return failedAttempt(startedAt, "Webhook secret reference has no runtime resolver");
39349
+ }
39350
+ try {
39351
+ secret = await options.secretResolver(channel.webhook.secretRef);
39352
+ } catch {
39353
+ return failedAttempt(startedAt, "Webhook secret reference could not be resolved");
39354
+ }
39355
+ if (!secret)
39356
+ return failedAttempt(startedAt, "Webhook secret reference could not be resolved");
39357
+ }
39358
+ const timestamp = (options.now?.() ?? new Date).toISOString();
39359
+ const { body, headers } = buildWebhookRequest(event, channel, { secret, timestamp });
39360
+ const validateTargets = options.webhookTargetPolicy !== undefined || options.fetchImpl === undefined;
39361
+ if (validateTargets) {
39362
+ return dispatchValidatedWebhook(event, channel, { body, headers, startedAt, options });
39363
+ }
38335
39364
  const controller = new AbortController;
38336
39365
  const timeout = setTimeout(() => controller.abort(), channel.webhook.timeoutMs ?? 15000);
38337
39366
  try {
38338
- const response = await (options.fetchImpl ?? fetch)(channel.webhook.url, {
39367
+ const response = await (options.fetchImpl ?? fetch)(webhookUrl, {
38339
39368
  method: "POST",
38340
39369
  headers,
38341
39370
  body,
@@ -38363,6 +39392,139 @@ async function dispatchWebhook(event, channel, options = {}) {
38363
39392
  clearTimeout(timeout);
38364
39393
  }
38365
39394
  }
39395
+ function isRedirectStatus(status) {
39396
+ return status === 301 || status === 302 || status === 303 || status === 307 || status === 308;
39397
+ }
39398
+ function redirectKeepsBody(status) {
39399
+ return status === 307 || status === 308;
39400
+ }
39401
+ async function pinnedNativeRequest(target, addresses, method, headers, body, signal, tls) {
39402
+ const isHttps = target.protocol === "https:";
39403
+ if (!isHttps && target.protocol !== "http:") {
39404
+ throw new Error(`Webhook target uses unsupported protocol ${target.protocol}`);
39405
+ }
39406
+ const defaultPort = isHttps ? 443 : 80;
39407
+ const port = target.port ? Number(target.port) : defaultPort;
39408
+ const requestOptions = {
39409
+ hostname: target.hostname,
39410
+ port,
39411
+ path: `${target.pathname}${target.search}`,
39412
+ method,
39413
+ headers,
39414
+ ...tls?.ca ? { ca: tls.ca } : {},
39415
+ lookup: (hostname, _options, callback) => {
39416
+ const entries = addresses.map((address) => ({
39417
+ address,
39418
+ family: address.includes(":") ? 6 : 4
39419
+ }));
39420
+ callback(null, entries);
39421
+ }
39422
+ };
39423
+ return new Promise((resolve2, reject) => {
39424
+ const request = isHttps ? nodeHttpsRequest(requestOptions, onResponse) : nodeHttpRequest(requestOptions, onResponse);
39425
+ const onAbort = () => {
39426
+ const error = new Error("The operation was aborted.");
39427
+ error.name = "AbortError";
39428
+ request.destroy(error);
39429
+ };
39430
+ if (signal.aborted)
39431
+ onAbort();
39432
+ else
39433
+ signal.addEventListener("abort", onAbort, { once: true });
39434
+ request.on("error", reject);
39435
+ if (body !== undefined)
39436
+ request.write(body);
39437
+ request.end();
39438
+ function onResponse(response) {
39439
+ const chunks = [];
39440
+ response.on("data", (chunk) => chunks.push(Buffer.from(chunk)));
39441
+ response.on("error", reject);
39442
+ response.on("end", () => {
39443
+ const headersRecord = {};
39444
+ for (const [name, value] of Object.entries(response.headers)) {
39445
+ if (typeof value === "string")
39446
+ headersRecord[name] = value;
39447
+ else if (Array.isArray(value))
39448
+ headersRecord[name] = value.join(", ");
39449
+ }
39450
+ resolve2(new Response(Buffer.concat(chunks), { status: response.statusCode ?? 200, headers: headersRecord }));
39451
+ });
39452
+ }
39453
+ });
39454
+ }
39455
+ async function dispatchValidatedWebhook(event, channel, input) {
39456
+ const { body, headers, startedAt, options } = input;
39457
+ const webhook = channel.webhook;
39458
+ if (!webhook)
39459
+ throw new Error(`Channel ${channel.id} has no webhook config`);
39460
+ const policy = options.webhookTargetPolicy ?? {};
39461
+ const maxRedirects = normalizeMaxRedirects(policy.maxRedirects);
39462
+ const controller = new AbortController;
39463
+ const timeout = setTimeout(() => controller.abort(), webhook.timeoutMs ?? 15000);
39464
+ try {
39465
+ let target = new URL(normalizeWebhookUrl(webhook.url));
39466
+ let requestHeaders = headers;
39467
+ let method = "POST";
39468
+ let requestBody = body;
39469
+ let redirectsFollowed = 0;
39470
+ for (;; ) {
39471
+ const resolved = await resolveWebhookTarget(target, policy).catch((error) => {
39472
+ throw new Error(`Webhook target rejected by SSRF guard: ${error.message}`);
39473
+ });
39474
+ const response = options.fetchImpl ? await options.fetchImpl(target, {
39475
+ method,
39476
+ headers: requestHeaders,
39477
+ body: requestBody,
39478
+ signal: controller.signal,
39479
+ redirect: "manual"
39480
+ }) : await pinnedNativeRequest(target, resolved.addresses, method, requestHeaders, requestBody, controller.signal, options.tls);
39481
+ const location = response.headers.get("location");
39482
+ if (isRedirectStatus(response.status) && location) {
39483
+ if (redirectsFollowed >= maxRedirects) {
39484
+ return failedAttempt(startedAt, `Webhook target exceeded ${maxRedirects} redirects`);
39485
+ }
39486
+ redirectsFollowed += 1;
39487
+ const next = new URL(location, target);
39488
+ target = next;
39489
+ if (!redirectKeepsBody(response.status)) {
39490
+ method = "GET";
39491
+ requestBody = undefined;
39492
+ requestHeaders = Object.fromEntries(Object.entries(requestHeaders).filter(([name]) => name.toLowerCase() !== "content-type" && name.toLowerCase() !== "content-length"));
39493
+ }
39494
+ continue;
39495
+ }
39496
+ const responseBody = truncate(await response.text());
39497
+ return {
39498
+ attempt: 1,
39499
+ status: response.ok ? "success" : "failed",
39500
+ startedAt,
39501
+ completedAt: now(),
39502
+ responseStatus: response.status,
39503
+ responseBody,
39504
+ error: response.ok ? undefined : `Webhook returned HTTP ${response.status}`
39505
+ };
39506
+ }
39507
+ } catch (error) {
39508
+ return {
39509
+ attempt: 1,
39510
+ status: "failed",
39511
+ startedAt,
39512
+ completedAt: now(),
39513
+ error: error instanceof Error ? error.message : String(error)
39514
+ };
39515
+ } finally {
39516
+ clearTimeout(timeout);
39517
+ }
39518
+ }
39519
+ function failedAttempt(startedAt, error) {
39520
+ return {
39521
+ attempt: 1,
39522
+ status: "failed",
39523
+ startedAt,
39524
+ completedAt: now(),
39525
+ error
39526
+ };
39527
+ }
38366
39528
  async function dispatchCommand(event, channel) {
38367
39529
  if (!channel.command)
38368
39530
  throw new Error(`Channel ${channel.id} has no command config`);
@@ -38382,7 +39544,7 @@ async function dispatchCommand(event, channel) {
38382
39544
  HASNA_EVENT_SCHEMA_VERSION: event.schemaVersion,
38383
39545
  HASNA_EVENT_JSON: eventJson
38384
39546
  };
38385
- return new Promise((resolve) => {
39547
+ return new Promise((resolve2) => {
38386
39548
  const child = spawn(channel.command.command, channel.command.args ?? [], {
38387
39549
  cwd: channel.command.cwd,
38388
39550
  env,
@@ -38400,7 +39562,7 @@ async function dispatchCommand(event, channel) {
38400
39562
  });
38401
39563
  child.on("error", (error) => {
38402
39564
  clearTimeout(timeout);
38403
- resolve({
39565
+ resolve2({
38404
39566
  attempt: 1,
38405
39567
  status: "failed",
38406
39568
  startedAt,
@@ -38413,7 +39575,7 @@ async function dispatchCommand(event, channel) {
38413
39575
  child.on("close", (code, signal) => {
38414
39576
  clearTimeout(timeout);
38415
39577
  const success = code === 0;
38416
- resolve({
39578
+ resolve2({
38417
39579
  attempt: 1,
38418
39580
  status: success ? "success" : "failed",
38419
39581
  startedAt,
@@ -38451,6 +39613,90 @@ function createDeliveryResult(event, channel, attempts) {
38451
39613
  completedAt: attempts.at(-1)?.completedAt ?? now()
38452
39614
  };
38453
39615
  }
39616
+
39617
+ class EventValidationError extends Error {
39618
+ eventType;
39619
+ issues;
39620
+ constructor(eventType, issues) {
39621
+ const detail = issues.map((issue) => `${issue.path || "<root>"}: ${issue.message}`).join("; ");
39622
+ super(`Event validation failed for type "${eventType}": ${detail}`);
39623
+ this.name = "EventValidationError";
39624
+ this.eventType = eventType;
39625
+ this.issues = issues;
39626
+ }
39627
+ }
39628
+
39629
+ class EventTypeCatalog {
39630
+ definitions = new Map;
39631
+ register(definition) {
39632
+ this.definitions.set(definition.type, definition);
39633
+ return this;
39634
+ }
39635
+ unregister(type) {
39636
+ return this.definitions.delete(type);
39637
+ }
39638
+ has(type) {
39639
+ return this.definitions.has(type);
39640
+ }
39641
+ get(type) {
39642
+ return this.definitions.get(type);
39643
+ }
39644
+ list() {
39645
+ return [...this.definitions.values()];
39646
+ }
39647
+ validateEvent(event) {
39648
+ const definition = this.definitions.get(event.type);
39649
+ if (!definition)
39650
+ return { ok: true };
39651
+ return definition.validate(event.data, event);
39652
+ }
39653
+ assertEventValid(event) {
39654
+ const result = this.validateEvent(event);
39655
+ if (!result.ok) {
39656
+ throw new EventValidationError(event.type, result.issues);
39657
+ }
39658
+ }
39659
+ }
39660
+ var defaultEventTypeCatalog = new EventTypeCatalog;
39661
+ var APP_EVENT_V1_MAX_DATA_BYTES = 32 * 1024;
39662
+ function redactPaths(event, paths, replacement = "[REDACTED]") {
39663
+ if (paths.length === 0)
39664
+ return event;
39665
+ const copy = structuredClone(event);
39666
+ for (const path of paths) {
39667
+ setPath(copy, path, replacement);
39668
+ }
39669
+ return copy;
39670
+ }
39671
+ function redactSensitiveKeys(event, replacement = "[REDACTED]") {
39672
+ return redactValue(event, replacement);
39673
+ }
39674
+ function shouldRedactKey(key) {
39675
+ return /secret|token|password|api[_-]?key|authorization/i.test(key);
39676
+ }
39677
+ function redactValue(value, replacement) {
39678
+ if (Array.isArray(value))
39679
+ return value.map((item) => redactValue(item, replacement));
39680
+ if (!value || typeof value !== "object")
39681
+ return value;
39682
+ return Object.fromEntries(Object.entries(value).map(([key, item]) => [
39683
+ key,
39684
+ shouldRedactKey(key) ? replacement : redactValue(item, replacement)
39685
+ ]));
39686
+ }
39687
+ function setPath(input, path, replacement) {
39688
+ const parts = path.split(".");
39689
+ let cursor = input;
39690
+ for (const part of parts.slice(0, -1)) {
39691
+ const next = cursor[part];
39692
+ if (!next || typeof next !== "object")
39693
+ return;
39694
+ cursor = next;
39695
+ }
39696
+ const last = parts.at(-1);
39697
+ if (last && last in cursor)
39698
+ cursor[last] = replacement;
39699
+ }
38454
39700
  function createEvent(input) {
38455
39701
  return {
38456
39702
  id: input.id ?? randomUUID2(),
@@ -38471,10 +39717,20 @@ class EventsClient {
38471
39717
  store;
38472
39718
  redactors;
38473
39719
  transportOptions;
39720
+ catalog;
39721
+ validateCatalogTypes;
38474
39722
  constructor(options = {}) {
38475
39723
  this.store = options.store ?? new JsonEventsStore(options.dataDir);
38476
39724
  this.redactors = options.redactors ?? [];
38477
- this.transportOptions = { fetchImpl: options.fetchImpl };
39725
+ this.transportOptions = {
39726
+ fetchImpl: options.fetchImpl,
39727
+ secretResolver: options.secretResolver,
39728
+ now: options.now,
39729
+ tls: options.tls,
39730
+ webhookTargetPolicy: options.webhookTargetPolicy
39731
+ };
39732
+ this.catalog = options.catalog ?? defaultEventTypeCatalog;
39733
+ this.validateCatalogTypes = options.validateCatalogTypes ?? false;
38478
39734
  }
38479
39735
  async addChannel(input) {
38480
39736
  const timestamp = new Date().toISOString();
@@ -38492,18 +39748,40 @@ class EventsClient {
38492
39748
  }
38493
39749
  async emit(input, options = {}) {
38494
39750
  const event = options.redactSensitiveData === false ? createEvent(input) : redactSensitiveKeys(createEvent(input));
38495
- if (options.dedupe !== false) {
38496
- const existing = await this.store.findEventByIdentity({ id: input.id, dedupeKey: event.dedupeKey });
38497
- if (existing) {
38498
- return { event: existing, deliveries: [], deduped: true };
38499
- }
38500
- }
38501
- await this.store.appendEvent(event);
38502
- const deliveries = options.deliver === false ? [] : await this.deliver(event);
38503
- return { event, deliveries, deduped: false };
38504
- }
38505
- async listEvents() {
38506
- return this.store.listEvents();
39751
+ if (options.validate ?? this.validateCatalogTypes) {
39752
+ this.catalog.assertEventValid(event);
39753
+ }
39754
+ const append = await this.appendEvent(event, { dedupe: options.dedupe !== false });
39755
+ if (append.deduped) {
39756
+ return { event: append.event, deliveries: [], deduped: true };
39757
+ }
39758
+ const deliveries = options.deliver === false ? [] : await this.deliver(append.event);
39759
+ return { event: append.event, deliveries, deduped: false };
39760
+ }
39761
+ async listEvents(options = {}) {
39762
+ if (Object.keys(options).length === 0)
39763
+ return this.store.listEvents();
39764
+ return queryClientEvents(await this.store.listEvents(), options);
39765
+ }
39766
+ async listEventsPage(options = {}) {
39767
+ if (this.store.listEventsPage)
39768
+ return this.store.listEventsPage(options);
39769
+ const events = queryClientEvents(await this.store.listEvents(), {
39770
+ eventId: options.eventId,
39771
+ source: options.source,
39772
+ type: options.type
39773
+ });
39774
+ const offset = decodeLocalJsonEventCursor(options.cursor, options);
39775
+ const limit = normalizeEventPageLimit(options.limit);
39776
+ const pageEvents = events.slice(offset, offset + limit);
39777
+ const nextOffset = offset + pageEvents.length;
39778
+ const hasMore = nextOffset < events.length;
39779
+ return {
39780
+ events: pageEvents,
39781
+ cursor: options.cursor,
39782
+ nextCursor: hasMore ? encodeLocalJsonEventCursor(nextOffset, options) : undefined,
39783
+ hasMore
39784
+ };
38507
39785
  }
38508
39786
  async listDeliveries() {
38509
39787
  return this.store.listDeliveries();
@@ -38520,7 +39798,7 @@ class EventsClient {
38520
39798
  }
38521
39799
  return deliveries;
38522
39800
  }
38523
- async testChannel(id, input = {}) {
39801
+ async matchChannel(id, input = {}) {
38524
39802
  const channel = await this.store.getChannel(id);
38525
39803
  if (!channel)
38526
39804
  throw new Error(`Channel not found: ${id}`);
@@ -38537,28 +39815,71 @@ class EventsClient {
38537
39815
  time: input.time,
38538
39816
  id: input.id
38539
39817
  });
39818
+ const matched = channelMatchesEvent(channel, event);
39819
+ return {
39820
+ channelId: channel.id,
39821
+ matched,
39822
+ event,
39823
+ filters: channel.filters,
39824
+ reason: matched ? undefined : channel.enabled ? "event did not match channel filters" : "channel is disabled"
39825
+ };
39826
+ }
39827
+ async testChannel(id, input = {}, options = {}) {
39828
+ const channel = await this.store.getChannel(id);
39829
+ if (!channel)
39830
+ throw new Error(`Channel not found: ${id}`);
39831
+ const match = await this.matchChannel(id, input);
39832
+ const event = match.event;
39833
+ if (options.honorFilters && !match.matched) {
39834
+ const timestamp = new Date().toISOString();
39835
+ const result2 = createDeliveryResult(event, channel, [{
39836
+ attempt: 1,
39837
+ status: "skipped",
39838
+ startedAt: timestamp,
39839
+ completedAt: timestamp,
39840
+ error: match.reason
39841
+ }]);
39842
+ result2.metadata = { reason: "filter_mismatch" };
39843
+ await this.store.appendDelivery(result2);
39844
+ return result2;
39845
+ }
38540
39846
  const eventForChannel = await this.applyRedaction(event, channel);
38541
39847
  const result = await this.deliverWithRetry(eventForChannel, channel);
38542
39848
  await this.store.appendDelivery(result);
38543
39849
  return result;
38544
39850
  }
38545
39851
  async replay(options = {}) {
38546
- const events = (await this.store.listEvents()).filter((event) => {
38547
- if (options.eventId && event.id !== options.eventId)
38548
- return false;
38549
- if (options.source && event.source !== options.source)
38550
- return false;
38551
- if (options.type && event.type !== options.type)
38552
- return false;
38553
- return true;
38554
- });
39852
+ const page = options.cursor || options.limit !== undefined ? await this.listEventsPage(options) : { events: await this.listEvents(options), hasMore: false };
38555
39853
  if (options.dryRun)
38556
- return { events, deliveries: [] };
39854
+ return { events: page.events, deliveries: [], cursor: page.cursor, nextCursor: page.nextCursor, hasMore: page.hasMore };
38557
39855
  const deliveries = [];
38558
- for (const event of events) {
39856
+ for (const event of page.events) {
38559
39857
  deliveries.push(...await this.deliver(event));
38560
39858
  }
38561
- return { events, deliveries };
39859
+ return { events: page.events, deliveries, cursor: page.cursor, nextCursor: page.nextCursor, hasMore: page.hasMore };
39860
+ }
39861
+ async appendEvent(event, options) {
39862
+ if (this.store.appendEventOnce) {
39863
+ return this.store.appendEventOnce(event, { dedupe: options.dedupe });
39864
+ }
39865
+ if (options.dedupe) {
39866
+ const existing = await this.store.findEventByIdentity({ id: event.id, dedupeKey: event.dedupeKey });
39867
+ if (existing) {
39868
+ return {
39869
+ event: existing,
39870
+ stored: false,
39871
+ deduped: true,
39872
+ identity: { id: existing.id, dedupeKey: existing.dedupeKey }
39873
+ };
39874
+ }
39875
+ }
39876
+ const stored = await this.store.appendEvent(event);
39877
+ return {
39878
+ event: stored,
39879
+ stored: true,
39880
+ deduped: false,
39881
+ identity: { id: stored.id, dedupeKey: stored.dedupeKey }
39882
+ };
38562
39883
  }
38563
39884
  async applyRedaction(event, channel) {
38564
39885
  let next = redactPaths(event, channel.redact?.paths ?? [], channel.redact?.replacement ?? "[REDACTED]");
@@ -38585,15 +39906,6 @@ class EventsClient {
38585
39906
  return createDeliveryResult(event, channel, attempts);
38586
39907
  }
38587
39908
  }
38588
- function redactPaths(event, paths, replacement = "[REDACTED]") {
38589
- if (paths.length === 0)
38590
- return event;
38591
- const copy = structuredClone(event);
38592
- for (const path of paths) {
38593
- setPath(copy, path, replacement);
38594
- }
38595
- return copy;
38596
- }
38597
39909
  function sanitizeChannelForOutput(channel) {
38598
39910
  const copy = structuredClone(channel);
38599
39911
  if (copy.webhook?.secret)
@@ -38606,34 +39918,19 @@ function sanitizeChannelForOutput(channel) {
38606
39918
  function sanitizeChannelsForOutput(channels) {
38607
39919
  return channels.map(sanitizeChannelForOutput);
38608
39920
  }
38609
- function redactSensitiveKeys(event, replacement = "[REDACTED]") {
38610
- return redactValue(event, replacement);
38611
- }
38612
- function shouldRedactKey(key) {
38613
- return /secret|token|password|api[_-]?key|authorization/i.test(key);
38614
- }
38615
- function redactValue(value, replacement) {
38616
- if (Array.isArray(value))
38617
- return value.map((item) => redactValue(item, replacement));
38618
- if (!value || typeof value !== "object")
38619
- return value;
38620
- return Object.fromEntries(Object.entries(value).map(([key, item]) => [
38621
- key,
38622
- shouldRedactKey(key) ? replacement : redactValue(item, replacement)
38623
- ]));
38624
- }
38625
- function setPath(input, path, replacement) {
38626
- const parts = path.split(".");
38627
- let cursor = input;
38628
- for (const part of parts.slice(0, -1)) {
38629
- const next = cursor[part];
38630
- if (!next || typeof next !== "object")
38631
- return;
38632
- cursor = next;
38633
- }
38634
- const last = parts.at(-1);
38635
- if (last && last in cursor)
38636
- cursor[last] = replacement;
39921
+ function queryClientEvents(events, options) {
39922
+ let rows = events;
39923
+ if (options.eventId)
39924
+ rows = rows.filter((event) => event.id === options.eventId);
39925
+ if (options.source)
39926
+ rows = rows.filter((event) => event.source === options.source);
39927
+ if (options.type)
39928
+ rows = rows.filter((event) => event.type === options.type);
39929
+ if (options.cursor)
39930
+ rows = rows.slice(decodeLocalJsonEventCursor(options.cursor, options));
39931
+ if (options.limit !== undefined)
39932
+ rows = rows.slice(0, normalizeEventPageLimit(options.limit));
39933
+ return rows;
38637
39934
  }
38638
39935
  function normalizeTime(value) {
38639
39936
  if (!value)
@@ -38647,6 +39944,77 @@ function normalizeRetryPolicy(policy) {
38647
39944
  multiplier: Math.max(1, policy?.multiplier ?? 2)
38648
39945
  };
38649
39946
  }
39947
+ function parseFieldMatchers(values, label, typed = false) {
39948
+ if (!values?.length)
39949
+ return;
39950
+ const result = {};
39951
+ for (const value of values) {
39952
+ const parsed = parseMatcherExpression(value, label);
39953
+ const path = parsed.path;
39954
+ if (path in result)
39955
+ throw new Error(`Duplicate ${label} filter path: ${path}`);
39956
+ const matcherValue = typed ? parseTypedMatcherValue(parsed.rawValue, label) : parsed.rawValue;
39957
+ result[path] = parsed.negated ? { not: matcherValue } : matcherValue;
39958
+ }
39959
+ return result;
39960
+ }
39961
+ function parseFilterOptions(options) {
39962
+ const filter2 = {};
39963
+ if (options.source)
39964
+ filter2.source = options.source;
39965
+ if (options.type)
39966
+ filter2.type = options.type;
39967
+ if (options.subject)
39968
+ filter2.subject = options.subject;
39969
+ if (options.severity)
39970
+ filter2.severity = options.severity;
39971
+ const data = mergeMatchers(parseFieldMatchers(options.data, "data"), parseFieldMatchers(options.dataJson, "data-json", true));
39972
+ const metadata = mergeMatchers(parseFieldMatchers(options.metadata, "metadata"), parseFieldMatchers(options.metadataJson, "metadata-json", true));
39973
+ if (Object.keys(data).length > 0)
39974
+ filter2.data = data;
39975
+ if (Object.keys(metadata).length > 0)
39976
+ filter2.metadata = metadata;
39977
+ return Object.keys(filter2).length > 0 ? [filter2] : undefined;
39978
+ }
39979
+ function mergeMatchers(...records) {
39980
+ const result = {};
39981
+ for (const record of records) {
39982
+ if (!record)
39983
+ continue;
39984
+ for (const [path, value] of Object.entries(record)) {
39985
+ if (path in result)
39986
+ throw new Error(`Duplicate filter path: ${path}`);
39987
+ result[path] = value;
39988
+ }
39989
+ }
39990
+ return result;
39991
+ }
39992
+ function parseTypedMatcherValue(value, label) {
39993
+ const parsed = JSON.parse(value);
39994
+ if (parsed === null || typeof parsed === "string" || typeof parsed === "number" || typeof parsed === "boolean" || Array.isArray(parsed) && parsed.every((item) => typeof item === "string")) {
39995
+ return parsed;
39996
+ }
39997
+ throw new Error(`${label} filter JSON values must be string, string[], number, boolean, or null`);
39998
+ }
39999
+ function parseMatcherExpression(value, label) {
40000
+ const negativeSeparator = value.indexOf("!=");
40001
+ if (negativeSeparator > 0) {
40002
+ return {
40003
+ path: value.slice(0, negativeSeparator),
40004
+ rawValue: value.slice(negativeSeparator + 2),
40005
+ negated: true
40006
+ };
40007
+ }
40008
+ const separator = value.indexOf("=");
40009
+ if (separator <= 0)
40010
+ throw new Error(`Invalid ${label} filter, expected path=value or path!=value: ${value}`);
40011
+ return {
40012
+ path: value.slice(0, separator),
40013
+ rawValue: value.slice(separator + 1),
40014
+ negated: false
40015
+ };
40016
+ }
40017
+ var DEFAULT_EVENT_LIST_LIMIT = 100;
38650
40018
  function parseJsonObject(value, fallback) {
38651
40019
  if (!value)
38652
40020
  return fallback;
@@ -38668,18 +40036,6 @@ function parseHeaders(values) {
38668
40036
  }
38669
40037
  return headers;
38670
40038
  }
38671
- function parseFilter(options) {
38672
- const filter2 = {};
38673
- if (options.source)
38674
- filter2.source = options.source;
38675
- if (options.type)
38676
- filter2.type = options.type;
38677
- if (options.subject)
38678
- filter2.subject = options.subject;
38679
- if (options.severity)
38680
- filter2.severity = options.severity;
38681
- return Object.keys(filter2).length > 0 ? [filter2] : undefined;
38682
- }
38683
40039
  function createClient(options) {
38684
40040
  if (options.createClient)
38685
40041
  return options.createClient();
@@ -38691,22 +40047,30 @@ function print(value, json, text) {
38691
40047
  else
38692
40048
  console.log(text);
38693
40049
  }
40050
+ function fail(error, json) {
40051
+ const message = error instanceof Error ? error.message : String(error);
40052
+ if (json)
40053
+ console.log(JSON.stringify({ error: message }, null, 2));
40054
+ else
40055
+ console.error(message);
40056
+ process.exitCode = 1;
40057
+ }
38694
40058
  function hasJsonOption(options) {
38695
40059
  return Boolean(options?.json || options?.opts?.().json || options?.optsWithGlobals?.().json || options?.parent?.opts?.().json || options?.parent?.optsWithGlobals?.().json);
38696
40060
  }
38697
40061
  function wantsJson(actionOptions, command) {
38698
40062
  return hasJsonOption(actionOptions) || hasJsonOption(command);
38699
40063
  }
38700
- function registerWebhookCommands(program, options) {
38701
- const webhooks = program.command(options.webhooksCommandName ?? "webhooks").description("Manage Hasna event webhook subscriptions");
38702
- webhooks.command("add").description("Add or replace a webhook or command subscription").argument("<target>", "Webhook URL or command binary").requiredOption("--id <id>", "Subscription/channel identifier").option("--transport <kind>", "Transport kind: webhook or command", "webhook").option("--name <name>", "Display name").option("--type <pattern>", "Event type filter, e.g. todos.task.*").option("--source <pattern>", "Event source filter").option("--subject <pattern>", "Event subject filter").option("--severity <pattern>", "Event severity filter").option("--secret <secret>", "Webhook HMAC secret").option("--header <name=value...>", "Webhook header", collectValues, []).option("--arg <arg...>", "Command argument", collectValues, []).option("--timeout-ms <ms>", "Transport timeout in milliseconds", parseNumber).option("--retry-attempts <n>", "Maximum delivery attempts", parseNumber).option("--retry-backoff-ms <ms>", "Initial retry backoff in milliseconds", parseNumber).option("--redact <path...>", "Event field path to redact before delivery", collectValues, []).option("--disabled", "Create channel disabled", false).option("-j, --json", "Print JSON output", false).action(async (target, actionOptions, command) => {
40064
+ function registerChannelCommands(program, options) {
40065
+ const channels = program.command(options.channelsCommandName ?? "channels").description("Manage Hasna event channels");
40066
+ channels.command("add").description("Add or replace a channel").argument("<target>", "Webhook URL or command binary").requiredOption("--id <id>", "Channel identifier").option("--transport <kind>", "Transport kind: webhook or command", "webhook").option("--name <name>", "Display name").option("--type <pattern>", "Event type filter, e.g. todos.task.*").option("--source <pattern>", "Event source filter").option("--subject <pattern>", "Event subject filter").option("--severity <pattern>", "Event severity filter").option("--data <path=value...>", "Event data field filter; string values, path!=value negatives, array-member matching, dot paths, * segment wildcard, ** recursive wildcard", collectValues, []).option("--metadata <path=value...>", "Event metadata field filter; string values, path!=value negatives, array-member matching, dot paths, * segment wildcard, ** recursive wildcard", collectValues, []).option("--data-json <path=json...>", "Event data field filter with typed JSON value; path!=json negatives supported", collectValues, []).option("--metadata-json <path=json...>", "Event metadata field filter with typed JSON value; path!=json negatives supported", collectValues, []).option("--secret <secret>", "Webhook HMAC secret").option("--header <name=value...>", "Webhook header", collectValues, []).option("--arg <arg...>", "Command argument", collectValues, []).option("--timeout-ms <ms>", "Transport timeout in milliseconds", parseNumber).option("--retry-attempts <n>", "Maximum delivery attempts", parseNumber).option("--retry-backoff-ms <ms>", "Initial retry backoff in milliseconds", parseNumber).option("--redact <path...>", "Event field path to redact before delivery", collectValues, []).option("--disabled", "Create channel disabled", false).option("-j, --json", "Print JSON output", false).action(async (target, actionOptions, command) => {
38703
40067
  const timestamp = new Date().toISOString();
38704
40068
  const channel = {
38705
40069
  id: actionOptions.id,
38706
40070
  name: actionOptions.name,
38707
40071
  enabled: !actionOptions.disabled,
38708
40072
  transport: actionOptions.transport,
38709
- filters: parseFilter(actionOptions),
40073
+ filters: parseFilterOptions(actionOptions),
38710
40074
  retry: actionOptions.retryAttempts || actionOptions.retryBackoffMs ? { maxAttempts: actionOptions.retryAttempts, backoffMs: actionOptions.retryBackoffMs } : undefined,
38711
40075
  redact: actionOptions.redact?.length ? { paths: actionOptions.redact } : undefined,
38712
40076
  createdAt: timestamp,
@@ -38722,35 +40086,61 @@ function registerWebhookCommands(program, options) {
38722
40086
  const saved = await createClient(options).addChannel(channel);
38723
40087
  print(sanitizeChannelForOutput(saved), wantsJson(actionOptions, command), `Added ${saved.transport} channel ${saved.id}`);
38724
40088
  });
38725
- webhooks.command("list").description("List configured subscriptions").option("-j, --json", "Print JSON output", false).action(async (actionOptions, command) => {
38726
- const channels = await createClient(options).listChannels();
40089
+ channels.command("list").description("List configured channels").option("-j, --json", "Print JSON output", false).action(async (actionOptions, command) => {
40090
+ const channels2 = await createClient(options).listChannels();
38727
40091
  if (wantsJson(actionOptions, command)) {
38728
- console.log(JSON.stringify(sanitizeChannelsForOutput(channels), null, 2));
40092
+ console.log(JSON.stringify(sanitizeChannelsForOutput(channels2), null, 2));
38729
40093
  return;
38730
40094
  }
38731
- if (!channels.length) {
40095
+ if (!channels2.length) {
38732
40096
  console.log("No channels configured.");
38733
40097
  return;
38734
40098
  }
38735
- for (const channel of channels) {
40099
+ for (const channel of channels2) {
38736
40100
  console.log(`${channel.id} ${channel.enabled ? "enabled" : "disabled"} ${channel.transport} ${channel.webhook?.url ?? channel.command?.command ?? channel.transport}`);
38737
40101
  }
38738
40102
  });
38739
- webhooks.command("remove").description("Remove a subscription").argument("<id>", "Subscription/channel identifier").option("-j, --json", "Print JSON output", false).action(async (id, actionOptions, command) => {
40103
+ channels.command("status").description("Show events channel storage status").option("-j, --json", "Print JSON output", false).action(async (actionOptions, command) => {
40104
+ const status = await getEventsStatus(options.dataDir);
40105
+ print(status, wantsJson(actionOptions, command), `events dataDir: ${status.dataDir}`);
40106
+ });
40107
+ channels.command("remove").description("Remove a channel").argument("<id>", "Channel identifier").option("-j, --json", "Print JSON output", false).action(async (id, actionOptions, command) => {
38740
40108
  const removed = await createClient(options).removeChannel(id);
38741
40109
  print({ removed }, wantsJson(actionOptions, command), removed ? `Removed ${id}` : `Channel not found: ${id}`);
38742
40110
  });
38743
- webhooks.command("test").description("Send a test event to one subscription").argument("<id>", "Subscription/channel identifier").option("--type <type>", "Event type", "events.test").option("--subject <subject>", "Event subject").option("--message <message>", "Event message", "Hasna events test delivery").option("--data <json>", "Event data JSON object").option("-j, --json", "Print JSON output", false).action(async (id, actionOptions, command) => {
38744
- const result = await createClient(options).testChannel(id, {
38745
- source: options.source,
38746
- type: actionOptions.type,
38747
- subject: actionOptions.subject ?? id,
38748
- message: actionOptions.message,
38749
- data: parseJsonObject(actionOptions.data, { test: true })
38750
- });
38751
- print(result, wantsJson(actionOptions, command), `${result.status}: ${result.channelId}`);
40111
+ channels.command("test").description("Send a test event to one channel").argument("<id>", "Channel identifier").option("--source <source>", "Event source override").option("--type <type>", "Event type", "events.test").option("--subject <subject>", "Event subject").option("--message <message>", "Event message", "Hasna events test delivery").option("--data <json>", "Event data JSON object").option("--metadata <json>", "Event metadata JSON object").option("--honor-filters", "Skip delivery when the sample event does not match channel filters", false).option("-j, --json", "Print JSON output", false).action(async (id, actionOptions, command) => {
40112
+ const json = wantsJson(actionOptions, command);
40113
+ try {
40114
+ const result = await createClient(options).testChannel(id, {
40115
+ source: actionOptions.source ?? options.source,
40116
+ type: actionOptions.type,
40117
+ subject: actionOptions.subject ?? id,
40118
+ message: actionOptions.message,
40119
+ data: parseJsonObject(actionOptions.data, { test: true }),
40120
+ metadata: parseJsonObject(actionOptions.metadata, {})
40121
+ }, { honorFilters: actionOptions.honorFilters });
40122
+ print(result, json, `${result.status}: ${result.channelId}`);
40123
+ } catch (error) {
40124
+ fail(error, json);
40125
+ }
38752
40126
  });
38753
- return webhooks;
40127
+ channels.command("match").description("Check whether a sample event matches one channel without delivering").argument("<id>", "Channel identifier").option("--source <source>", "Event source override").option("--type <type>", "Event type", "events.test").option("--subject <subject>", "Event subject").option("--message <message>", "Event message", "Hasna events match preview").option("--data <json>", "Event data JSON object").option("--metadata <json>", "Event metadata JSON object").option("-j, --json", "Print JSON output", false).action(async (id, actionOptions, command) => {
40128
+ const json = wantsJson(actionOptions, command);
40129
+ try {
40130
+ const result = await createClient(options).matchChannel(id, {
40131
+ source: actionOptions.source ?? options.source,
40132
+ type: actionOptions.type,
40133
+ subject: actionOptions.subject ?? id,
40134
+ message: actionOptions.message,
40135
+ data: parseJsonObject(actionOptions.data, { test: true }),
40136
+ metadata: parseJsonObject(actionOptions.metadata, {})
40137
+ });
40138
+ print(result, json, `${result.matched ? "matched" : "skipped"}: ${result.channelId}`);
40139
+ } catch (error) {
40140
+ fail(error, json);
40141
+ }
40142
+ });
40143
+ return channels;
38754
40144
  }
38755
40145
  function registerEventCommands(program, options) {
38756
40146
  const events = program.command(options.eventsCommandName ?? "events").description("Emit, list, and replay Hasna events");
@@ -38767,7 +40157,8 @@ function registerEventCommands(program, options) {
38767
40157
  }, { deliver: actionOptions.deliver, dedupe: actionOptions.dedupe });
38768
40158
  print(result, wantsJson(actionOptions, command), `${result.deduped ? "Deduped" : "Emitted"} ${result.event.id} to ${result.deliveries.length} channel(s)`);
38769
40159
  });
38770
- events.command("list").description("List recorded events").option("--source <source>", "Filter by source").option("--type <type>", "Filter by type").option("--limit <n>", "Limit results", parseNumber).option("-j, --json", "Print JSON output", false).action(async (actionOptions, command) => {
40160
+ const defaultListLimit = options.defaultEventListLimit ?? DEFAULT_EVENT_LIST_LIMIT;
40161
+ events.command("list").description("List recorded events").option("--source <source>", "Filter by source").option("--type <type>", "Filter by type").option("--limit <n>", `Limit to the most recent <n> events (default ${defaultListLimit}; use 0 for all)`, parseNumber, defaultListLimit).option("-j, --json", "Print JSON output", false).action(async (actionOptions, command) => {
38771
40162
  let rows = await createClient(options).listEvents();
38772
40163
  if (actionOptions.source)
38773
40164
  rows = rows.filter((event) => event.source === actionOptions.source);
@@ -38786,19 +40177,21 @@ function registerEventCommands(program, options) {
38786
40177
  for (const event of rows)
38787
40178
  console.log(`${event.time} ${event.id} ${event.source} ${event.type} ${event.severity}`);
38788
40179
  });
38789
- events.command("replay").description("Replay recorded events").option("--id <id>", "Replay one event id").option("--source <source>", "Filter by source").option("--type <type>", "Filter by type").option("--dry-run", "Preview without delivery", false).option("-j, --json", "Print JSON output", false).action(async (actionOptions, command) => {
40180
+ events.command("replay").description("Replay recorded events").option("--id <id>", "Replay one event id").option("--source <source>", "Filter by source").option("--type <type>", "Filter by type").option("--cursor <cursor>", "Opaque replay cursor from a previous page").option("--limit <n>", "Maximum events to replay", parseNumber).option("--dry-run", "Preview without delivery", false).option("-j, --json", "Print JSON output", false).action(async (actionOptions, command) => {
38790
40181
  const result = await createClient(options).replay({
38791
40182
  eventId: actionOptions.id,
38792
40183
  source: actionOptions.source,
38793
40184
  type: actionOptions.type,
40185
+ cursor: actionOptions.cursor,
40186
+ limit: actionOptions.limit,
38794
40187
  dryRun: actionOptions.dryRun
38795
40188
  });
38796
- print(result, wantsJson(actionOptions, command), `Replayed ${result.events.length} event(s), ${result.deliveries.length} delivery result(s)`);
40189
+ print(result, wantsJson(actionOptions, command), replaySummary(result.events.length, result.deliveries.length, result.nextCursor));
38797
40190
  });
38798
40191
  return events;
38799
40192
  }
38800
40193
  function registerEventsCommands(program, options) {
38801
- registerWebhookCommands(program, options);
40194
+ registerChannelCommands(program, options);
38802
40195
  registerEventCommands(program, options);
38803
40196
  }
38804
40197
  function parseNumber(value) {
@@ -38811,8 +40204,12 @@ function collectValues(value, previous) {
38811
40204
  previous.push(value);
38812
40205
  return previous;
38813
40206
  }
40207
+ function replaySummary(events, deliveries, nextCursor) {
40208
+ const suffix = nextCursor ? `, next cursor: ${nextCursor}` : "";
40209
+ return `Replayed ${events} event(s), ${deliveries} delivery result(s)${suffix}`;
40210
+ }
38814
40211
 
38815
- // node_modules/commander/esm.mjs
40212
+ // node_modules/.pnpm/commander@13.1.0/node_modules/commander/esm.mjs
38816
40213
  var import__ = __toESM(require_commander(), 1);
38817
40214
  var {
38818
40215
  program,
@@ -38838,12 +40235,12 @@ import chalk2 from "chalk";
38838
40235
 
38839
40236
  // src/lib/config.ts
38840
40237
  init_database();
38841
- import { existsSync as existsSync7, readFileSync as readFileSync3, writeFileSync as writeFileSync3, mkdirSync as mkdirSync5 } from "fs";
38842
- import { join as join5 } from "path";
40238
+ import { existsSync as existsSync9, readFileSync as readFileSync3, writeFileSync as writeFileSync3, mkdirSync as mkdirSync5 } from "fs";
40239
+ import { join as join9 } from "path";
38843
40240
  var CONFIG_DIR = getDataDir();
38844
- var CONFIG_FILE = join5(CONFIG_DIR, "config.json");
40241
+ var CONFIG_FILE = join9(CONFIG_DIR, "config.json");
38845
40242
  function readConfig() {
38846
- if (!existsSync7(CONFIG_FILE))
40243
+ if (!existsSync9(CONFIG_FILE))
38847
40244
  return {};
38848
40245
  try {
38849
40246
  return JSON.parse(readFileSync3(CONFIG_FILE, "utf-8"));
@@ -38853,8 +40250,8 @@ function readConfig() {
38853
40250
  }
38854
40251
 
38855
40252
  // src/cli/commands/core.tsx
38856
- import { readFileSync as readFileSync9, writeFileSync as writeFileSync4, existsSync as existsSync12, copyFileSync as copyFileSync3, statSync as statSync2, mkdirSync as mkdirSync6, readdirSync as readdirSync3, chmodSync as chmodSync4 } from "fs";
38857
- import { extname as extname3, join as join10 } from "path";
40253
+ import { readFileSync as readFileSync9, writeFileSync as writeFileSync4, existsSync as existsSync14, copyFileSync as copyFileSync3, statSync as statSync2, mkdirSync as mkdirSync6, readdirSync as readdirSync3, chmodSync as chmodSync4 } from "fs";
40254
+ import { extname as extname3, join as join15 } from "path";
38858
40255
 
38859
40256
  // src/cli/utils.tsx
38860
40257
  import chalk from "chalk";
@@ -38949,12 +40346,12 @@ function formatContact(c) {
38949
40346
  }
38950
40347
  async function promptUser(question) {
38951
40348
  process.stdout.write(chalk.cyan("? ") + question + " ");
38952
- return new Promise((resolve2) => {
40349
+ return new Promise((resolve3) => {
38953
40350
  process.stdin.setEncoding("utf8");
38954
40351
  process.stdin.resume();
38955
40352
  process.stdin.once("data", (data) => {
38956
40353
  process.stdin.pause();
38957
- resolve2(data.toString().trim());
40354
+ resolve3(data.toString().trim());
38958
40355
  });
38959
40356
  });
38960
40357
  }
@@ -39325,7 +40722,7 @@ Add New Tag
39325
40722
  });
39326
40723
  program2.command("import <file>").description("Import contacts from CSV, vCard (.vcf), or JSON file").action(async (file) => {
39327
40724
  const store = getStore();
39328
- if (!existsSync12(file)) {
40725
+ if (!existsSync14(file)) {
39329
40726
  console.error(chalk2.red(`
39330
40727
  File not found: ${file}
39331
40728
  `));
@@ -39695,9 +41092,9 @@ ${projectIds.length} project link(s) for ${contactId}
39695
41092
  });
39696
41093
  program2.command("backup").description("Backup the contacts database (local mode only)").option("--output <path>", "Output path").option("--list", "List existing backups").action(async (opts) => {
39697
41094
  const store = getStore();
39698
- const backupDir = join10(getDataDir(), "backups");
41095
+ const backupDir = join15(getDataDir(), "backups");
39699
41096
  if (opts.list) {
39700
- if (!existsSync12(backupDir)) {
41097
+ if (!existsSync14(backupDir)) {
39701
41098
  console.log(chalk2.gray(`
39702
41099
  No backups found.
39703
41100
  `));
@@ -39714,7 +41111,7 @@ No backups found.
39714
41111
  Existing Backups:
39715
41112
  `));
39716
41113
  for (const f of files) {
39717
- const filePath = join10(backupDir, f);
41114
+ const filePath = join15(backupDir, f);
39718
41115
  const size2 = statSync2(filePath).size;
39719
41116
  const mtime = statSync2(filePath).mtime.toISOString().slice(0, 19).replace("T", " ");
39720
41117
  console.log(` ${chalk2.cyan(f)} ${chalk2.gray(`${(size2 / 1024).toFixed(1)} KB ${mtime}`)}`);
@@ -39723,7 +41120,7 @@ Existing Backups:
39723
41120
  return;
39724
41121
  }
39725
41122
  const src = getDbPath();
39726
- if (!existsSync12(src)) {
41123
+ if (!existsSync14(src)) {
39727
41124
  console.error(chalk2.red(`
39728
41125
  Database not found: ${src}
39729
41126
  `));
@@ -39733,7 +41130,7 @@ Database not found: ${src}
39733
41130
  chmodSync4(backupDir, 448);
39734
41131
  await store.flushForBackup();
39735
41132
  const ts = new Date().toISOString().replace(/[:.]/g, "-").slice(0, 19);
39736
- const dest = opts.output || join10(backupDir, `contacts-${ts}.db`);
41133
+ const dest = opts.output || join15(backupDir, `contacts-${ts}.db`);
39737
41134
  copyFileSync3(src, dest);
39738
41135
  chmodSync4(dest, 384);
39739
41136
  const size = statSync2(dest).size;
@@ -40632,7 +42029,9 @@ Searching for: ${contact.display_name}...
40632
42029
 
40633
42030
  // src/cli/commands/advanced.tsx
40634
42031
  init_store();
42032
+ init_images();
40635
42033
  import chalk4 from "chalk";
42034
+ import { join as join16 } from "path";
40636
42035
  function collect3(val, prev) {
40637
42036
  return [...prev, val];
40638
42037
  }
@@ -41124,8 +42523,9 @@ Deal Team: ${dealId}
41124
42523
  return;
41125
42524
  }
41126
42525
  const filename = await store.saveImage(contactId, imagePath);
41127
- await store.updateContact(contactId, { avatar_url: `~/.hasna/contacts/images/${filename}` });
41128
- console.log(chalk4.green(`Photo set for ${contact.display_name}: ~/.hasna/contacts/images/${filename}`));
42526
+ const avatarUrl = join16(getImagesDir(), filename);
42527
+ await store.updateContact(contactId, { avatar_url: avatarUrl });
42528
+ console.log(chalk4.green(`Photo set for ${contact.display_name}: ${avatarUrl}`));
41129
42529
  } catch (e) {
41130
42530
  console.error(chalk4.red(e instanceof Error ? e.message : String(e)));
41131
42531
  }
@@ -41177,8 +42577,9 @@ Deal Team: ${dealId}
41177
42577
  return;
41178
42578
  }
41179
42579
  const filename = await store.saveImage(companyId, imagePath);
41180
- await store.updateCompany(companyId, { logo_url: `~/.hasna/contacts/images/${filename}` });
41181
- console.log(chalk4.green(`Logo set for ${company.name}: ~/.hasna/contacts/images/${filename}`));
42580
+ const logoUrl = join16(getImagesDir(), filename);
42581
+ await store.updateCompany(companyId, { logo_url: logoUrl });
42582
+ console.log(chalk4.green(`Logo set for ${company.name}: ${logoUrl}`));
41182
42583
  } catch (e) {
41183
42584
  console.error(chalk4.red(e instanceof Error ? e.message : String(e)));
41184
42585
  }
@@ -41232,12 +42633,12 @@ Sensitivity set to ${level} for ${contact.display_name}
41232
42633
  const vaultCmd = program2.command("vault").description("Manage the encrypted document vault");
41233
42634
  function promptPassphrase(promptText) {
41234
42635
  const { createInterface } = __require("readline");
41235
- return new Promise((resolve3) => {
42636
+ return new Promise((resolve4) => {
41236
42637
  const rl = createInterface({ input: process.stdin, output: process.stdout });
41237
42638
  process.stdout.write(promptText);
41238
42639
  rl.question("", (answer) => {
41239
42640
  rl.close();
41240
- resolve3(answer);
42641
+ resolve4(answer);
41241
42642
  });
41242
42643
  });
41243
42644
  }
@@ -41493,7 +42894,7 @@ init_store();
41493
42894
  init_audience_contract();
41494
42895
  init_types();
41495
42896
  import chalk5 from "chalk";
41496
- function fail(message) {
42897
+ function fail2(message) {
41497
42898
  console.error(chalk5.red(`
41498
42899
  ${message}
41499
42900
  `));
@@ -41501,7 +42902,7 @@ ${message}
41501
42902
  }
41502
42903
  function parseChannel(value) {
41503
42904
  if (!value || !AUDIENCE_CHANNELS.includes(value)) {
41504
- fail(`--channel must be one of: ${AUDIENCE_CHANNELS.join("|")}`);
42905
+ fail2(`--channel must be one of: ${AUDIENCE_CHANNELS.join("|")}`);
41505
42906
  }
41506
42907
  return value;
41507
42908
  }
@@ -41510,10 +42911,10 @@ function parsePredicates(raw) {
41510
42911
  try {
41511
42912
  parsed = JSON.parse(raw);
41512
42913
  } catch {
41513
- fail(`--predicates must be valid JSON, e.g. '[{"kind":"tag","value":"beta"}]'`);
42914
+ fail2(`--predicates must be valid JSON, e.g. '[{"kind":"tag","value":"beta"}]'`);
41514
42915
  }
41515
42916
  if (!Array.isArray(parsed))
41516
- fail("--predicates must be a JSON array of predicate objects");
42917
+ fail2("--predicates must be a JSON array of predicate objects");
41517
42918
  return parsed;
41518
42919
  }
41519
42920
  function registerAudienceCommands(program2) {
@@ -41521,9 +42922,9 @@ function registerAudienceCommands(program2) {
41521
42922
  audience.command("create <slug>").description("Create an audience segment from predicates over tags/attributes/groups").requiredOption("--name <name>", "Human-readable audience name").requiredOption("--predicates <json>", `JSON array of predicates, e.g. '[{"kind":"tag","value":"beta"}]'`).option("--match <match>", "Predicate combinator: all|any", "all").option("--policy <policy>", `Consent policy: ${CONSENT_POLICIES.join("|")}`, "opt_in").option("--json", "Output JSON").action(async (slug, opts) => {
41522
42923
  const store = getStore();
41523
42924
  if (!["all", "any"].includes(opts.match))
41524
- fail("--match must be all or any");
42925
+ fail2("--match must be all or any");
41525
42926
  if (!CONSENT_POLICIES.includes(opts.policy)) {
41526
- fail(`--policy must be one of: ${CONSENT_POLICIES.join("|")}`);
42927
+ fail2(`--policy must be one of: ${CONSENT_POLICIES.join("|")}`);
41527
42928
  }
41528
42929
  try {
41529
42930
  const created = await store.createAudience({
@@ -41541,7 +42942,7 @@ function registerAudienceCommands(program2) {
41541
42942
  Created audience ${created.audience_id} (${created.id})
41542
42943
  `));
41543
42944
  } catch (err2) {
41544
- fail(err2 instanceof Error ? err2.message : String(err2));
42945
+ fail2(err2 instanceof Error ? err2.message : String(err2));
41545
42946
  }
41546
42947
  });
41547
42948
  audience.command("list").description("List audience segments").option("--json", "Output JSON").action(async (opts) => {
@@ -41575,7 +42976,7 @@ ${audiences.length} audience(s)
41575
42976
  try {
41576
42977
  console.log(JSON.stringify(toAudienceContract(await store.getAudience(id)), null, 2));
41577
42978
  } catch (err2) {
41578
- fail(err2 instanceof Error ? err2.message : String(err2));
42979
+ fail2(err2 instanceof Error ? err2.message : String(err2));
41579
42980
  }
41580
42981
  });
41581
42982
  audience.command("delete <id>").description("Delete an audience segment").action(async (id) => {
@@ -41586,7 +42987,7 @@ ${audiences.length} audience(s)
41586
42987
  Deleted audience ${id}
41587
42988
  `));
41588
42989
  } catch (err2) {
41589
- fail(err2 instanceof Error ? err2.message : String(err2));
42990
+ fail2(err2 instanceof Error ? err2.message : String(err2));
41590
42991
  }
41591
42992
  });
41592
42993
  audience.command("resolve <id>").description("Resolve an audience to recipients for a channel, honoring consent + suppression").requiredOption("--channel <channel>", `Delivery channel: ${AUDIENCE_CHANNELS.join("|")}`).option("--json", "Output JSON").action(async (id, opts) => {
@@ -41613,7 +43014,7 @@ Deleted audience ${id}
41613
43014
  }
41614
43015
  console.log();
41615
43016
  } catch (err2) {
41616
- fail(err2 instanceof Error ? err2.message : String(err2));
43017
+ fail2(err2 instanceof Error ? err2.message : String(err2));
41617
43018
  }
41618
43019
  });
41619
43020
  const consent = program2.command("consent").description("Manage per-channel subscription consent for contacts");
@@ -41621,7 +43022,7 @@ Deleted audience ${id}
41621
43022
  const store = getStore();
41622
43023
  const channel = parseChannel(opts.channel);
41623
43024
  if (!CONSENT_STATUSES.includes(opts.status)) {
41624
- fail(`--status must be one of: ${CONSENT_STATUSES.join("|")}`);
43025
+ fail2(`--status must be one of: ${CONSENT_STATUSES.join("|")}`);
41625
43026
  }
41626
43027
  try {
41627
43028
  const record3 = await store.setContactConsent(contactId, channel, opts.status, opts.source);
@@ -41629,7 +43030,7 @@ Deleted audience ${id}
41629
43030
  Consent for ${contactId} on ${record3.channel}: ${record3.status}
41630
43031
  `));
41631
43032
  } catch (err2) {
41632
- fail(err2 instanceof Error ? err2.message : String(err2));
43033
+ fail2(err2 instanceof Error ? err2.message : String(err2));
41633
43034
  }
41634
43035
  });
41635
43036
  consent.command("show <contactId>").description("Show a contact's consent status per channel").option("--json", "Output JSON").action(async (contactId, opts) => {
@@ -41659,7 +43060,7 @@ No consent records for ${contactId} (all channels: unknown)
41659
43060
  Suppressed ${entry.address} on ${entry.channel}
41660
43061
  `));
41661
43062
  } catch (err2) {
41662
- fail(err2 instanceof Error ? err2.message : String(err2));
43063
+ fail2(err2 instanceof Error ? err2.message : String(err2));
41663
43064
  }
41664
43065
  });
41665
43066
  suppression.command("remove <address>").description("Remove an address from the suppression list").requiredOption("--channel <channel>", `Channel: ${AUDIENCE_CHANNELS.join("|")}`).action(async (address, opts) => {
@@ -41707,7 +43108,7 @@ Pushed ${result.pushed}/${result.pending} suppression(s) via ${result.adapter}`)
41707
43108
  if (result.failed.length)
41708
43109
  process.exit(1);
41709
43110
  } catch (err2) {
41710
- fail(err2 instanceof Error ? err2.message : String(err2));
43111
+ fail2(err2 instanceof Error ? err2.message : String(err2));
41711
43112
  }
41712
43113
  });
41713
43114
  }
@@ -41794,7 +43195,7 @@ function registerStorageCommands(program2) {
41794
43195
  // src/cli/index.tsx
41795
43196
  import { createRequire as createRequire3 } from "module";
41796
43197
  var { registerEventCommands: registerEventCommands2 } = exports_commander;
41797
- var registerWebhookCommands2 = registerWebhookCommands;
43198
+ var registerWebhookCommands2 = undefined;
41798
43199
  var _require = createRequire3(import.meta.url);
41799
43200
  var pkg3 = _require("../../package.json");
41800
43201
  program.name("contacts").description("Open Contacts \u2014 contact management for AI coding agents").version(pkg3.version);