@bike4mind/cli 0.2.30 → 0.2.31-b4m-cli-undo-command.19534

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (26) hide show
  1. package/bin/bike4mind-cli.mjs +48 -0
  2. package/dist/{HydrationEngine-WGYKF46H.js → HydrationEngine-YL2HWJ3V.js} +1 -1
  3. package/dist/{artifactExtractor-JQMWU272.js → artifactExtractor-T6NJ7V7P.js} +1 -1
  4. package/dist/{chunk-LBTTUQJM.js → chunk-32PKF3N7.js} +16 -15
  5. package/dist/{chunk-BQAPZP5Y.js → chunk-3SPW5FYJ.js} +236 -18
  6. package/dist/{chunk-U63VANTQ.js → chunk-ERV5G6MX.js} +3 -3
  7. package/dist/{chunk-LLA44SW7.js → chunk-F4PXVLZX.js} +2 -2
  8. package/dist/{chunk-RUI6HNLO.js → chunk-GQGOWACU.js} +8 -4
  9. package/dist/{chunk-WIB75EEX.js → chunk-JWJF6O4L.js} +3 -3
  10. package/dist/{chunk-T4VPCTBM.js → chunk-NI22LIK3.js} +998 -167
  11. package/dist/{chunk-OCYRD7D6.js → chunk-PFBYGCOW.js} +109 -31
  12. package/dist/chunk-WVFOWKNW.js +244 -0
  13. package/dist/commands/doctorCommand.js +87 -0
  14. package/dist/commands/mcpCommand.js +1 -1
  15. package/dist/commands/updateCommand.js +42 -0
  16. package/dist/create-XOEMSBER.js +12 -0
  17. package/dist/index.js +3373 -669
  18. package/dist/{llmMarkdownGenerator-2O24TMGD.js → llmMarkdownGenerator-NPX7ULSW.js} +1 -1
  19. package/dist/{markdownGenerator-6LAK3FQM.js → markdownGenerator-TVJ2RQXC.js} +1 -1
  20. package/dist/{mementoService-NRR7NQ4C.js → mementoService-HGH2XVLM.js} +4 -4
  21. package/dist/{notificationDeduplicator-UTHJHMSZ.js → notificationDeduplicator-HUC53NEW.js} +1 -1
  22. package/dist/{src-VMQ5TKYR.js → src-2BRBILH7.js} +27 -1
  23. package/dist/{src-3FQBHGOM.js → src-JZ6OHGTX.js} +13 -3
  24. package/dist/{subtractCredits-HK72MSDY.js → subtractCredits-4VIHTUR4.js} +4 -4
  25. package/package.json +9 -9
  26. package/dist/create-4WOBQ5JM.js +0 -12
@@ -88,6 +88,8 @@ const argv = await yargs(hideBin(process.argv))
88
88
  })
89
89
  .demandCommand(1, 'You must provide a subcommand (list, add, remove, enable, disable)');
90
90
  })
91
+ .command('update', 'Check for and install CLI updates')
92
+ .command('doctor', 'Run diagnostic checks on CLI installation')
91
93
  .help()
92
94
  .alias('help', 'h')
93
95
  .version()
@@ -149,6 +151,52 @@ if (argv._[0] === 'mcp') {
149
151
  }
150
152
  }
151
153
 
154
+ // Handle update command (external command)
155
+ if (argv._[0] === 'update') {
156
+ try {
157
+ let handleUpdateCommand;
158
+
159
+ if (isDev) {
160
+ const { register } = require('tsx/esm/api');
161
+ register();
162
+ const module = await import('../src/commands/updateCommand.ts');
163
+ handleUpdateCommand = module.handleUpdateCommand;
164
+ } else {
165
+ const module = await import('../dist/commands/updateCommand.js');
166
+ handleUpdateCommand = module.handleUpdateCommand;
167
+ }
168
+
169
+ await handleUpdateCommand();
170
+ process.exit(0);
171
+ } catch (error) {
172
+ console.error('Error:', error.message);
173
+ process.exit(1);
174
+ }
175
+ }
176
+
177
+ // Handle doctor command (external command)
178
+ if (argv._[0] === 'doctor') {
179
+ try {
180
+ let handleDoctorCommand;
181
+
182
+ if (isDev) {
183
+ const { register } = require('tsx/esm/api');
184
+ register();
185
+ const module = await import('../src/commands/doctorCommand.ts');
186
+ handleDoctorCommand = module.handleDoctorCommand;
187
+ } else {
188
+ const module = await import('../dist/commands/doctorCommand.js');
189
+ handleDoctorCommand = module.handleDoctorCommand;
190
+ }
191
+
192
+ await handleDoctorCommand();
193
+ process.exit(0);
194
+ } catch (error) {
195
+ console.error('Error:', error.message);
196
+ process.exit(1);
197
+ }
198
+ }
199
+
152
200
  if (isDev) {
153
201
  // Show dev mode indicator for developers
154
202
  console.log('🔧 Running in development mode (using TypeScript source)\n');
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  HydrationEngine,
4
4
  createHydrationEngine
5
- } from "./chunk-RUI6HNLO.js";
5
+ } from "./chunk-GQGOWACU.js";
6
6
  export {
7
7
  HydrationEngine,
8
8
  createHydrationEngine
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  CurationArtifactType
4
- } from "./chunk-T4VPCTBM.js";
4
+ } from "./chunk-NI22LIK3.js";
5
5
 
6
6
  // ../../b4m-core/packages/services/dist/src/notebookCurationService/artifactExtractor.js
7
7
  var ARTIFACT_TAG_REGEX = /<artifact\s+(.*?)>([\s\S]*?)<\/artifact>/gi;
@@ -269,24 +269,25 @@ var AuthTokensSchema = z.object({
269
269
  userId: z.string()
270
270
  });
271
271
  var ApiConfigSchema = z.object({
272
- customUrl: z.string().url().optional()
272
+ customUrl: z.url().optional()
273
273
  });
274
274
  var McpServerSchema = z.object({
275
275
  name: z.string(),
276
276
  command: z.string().optional(),
277
277
  args: z.array(z.string()).optional(),
278
- env: z.record(z.string()).default({}),
279
- enabled: z.boolean().default(true)
278
+ env: z.record(z.string(), z.string()).prefault({}),
279
+ enabled: z.boolean().prefault(true)
280
280
  });
281
281
  var McpServersSchema = z.union([
282
282
  // Array format (B4M native)
283
283
  z.array(McpServerSchema),
284
284
  // Object format (portable - compatible with Claude Code)
285
285
  z.record(
286
+ z.string(),
286
287
  z.object({
287
288
  command: z.string().optional(),
288
289
  args: z.array(z.string()).optional(),
289
- env: z.record(z.string()).optional(),
290
+ env: z.record(z.string(), z.string()).optional(),
290
291
  enabled: z.boolean().optional()
291
292
  })
292
293
  )
@@ -325,24 +326,24 @@ var CliConfigSchema = z.object({
325
326
  maxTokens: z.number(),
326
327
  temperature: z.number(),
327
328
  autoSave: z.boolean(),
328
- autoCompact: z.boolean().optional().default(true),
329
+ autoCompact: z.boolean().optional().prefault(true),
329
330
  theme: z.enum(["light", "dark"]),
330
331
  exportFormat: z.enum(["markdown", "json"]),
331
- maxIterations: z.number().nullable().default(10),
332
- enableSkillTool: z.boolean().optional().default(true)
332
+ maxIterations: z.number().nullable().prefault(10),
333
+ enableSkillTool: z.boolean().optional().prefault(true)
333
334
  }),
334
335
  tools: z.object({
335
336
  enabled: z.array(z.string()),
336
337
  disabled: z.array(z.string()),
337
- config: z.record(z.any())
338
+ config: z.record(z.string(), z.any())
338
339
  }),
339
- trustedTools: z.array(z.string()).optional().default([])
340
+ trustedTools: z.array(z.string()).optional().prefault([])
340
341
  });
341
342
  var ProjectConfigSchema = z.object({
342
343
  tools: z.object({
343
344
  enabled: z.array(z.string()).optional(),
344
345
  denied: z.array(z.string()).optional(),
345
- config: z.record(z.any()).optional()
346
+ config: z.record(z.string(), z.any()).optional()
346
347
  }).optional(),
347
348
  defaultModel: z.string().optional(),
348
349
  mcpServers: McpServersSchema.optional(),
@@ -432,7 +433,7 @@ async function loadProjectConfig(projectDir) {
432
433
  return null;
433
434
  }
434
435
  if (error instanceof z.ZodError) {
435
- console.error("Project config validation error:", error.errors);
436
+ console.error("Project config validation error:", error.issues);
436
437
  return null;
437
438
  }
438
439
  console.error("Failed to load project config:", error);
@@ -455,7 +456,7 @@ async function loadProjectLocalConfig(projectDir) {
455
456
  return null;
456
457
  }
457
458
  if (error instanceof z.ZodError) {
458
- console.error("Project local config validation error:", error.errors);
459
+ console.error("Project local config validation error:", error.issues);
459
460
  return null;
460
461
  }
461
462
  console.error("Failed to load project local config:", error);
@@ -478,7 +479,7 @@ async function loadMcpJsonConfig(projectDir) {
478
479
  return null;
479
480
  }
480
481
  if (error instanceof z.ZodError) {
481
- console.error(".mcp.json validation error:", error.errors);
482
+ console.error(".mcp.json validation error:", error.issues);
482
483
  return null;
483
484
  }
484
485
  console.error("Failed to load .mcp.json:", error);
@@ -620,7 +621,7 @@ var ConfigStore = class {
620
621
  if (error.code === "ENOENT") {
621
622
  globalConfig = { ...DEFAULT_CONFIG };
622
623
  } else if (error instanceof z.ZodError) {
623
- console.error("Global config validation error:", error.errors);
624
+ console.error("Global config validation error:", error.issues);
624
625
  console.error("Using default configuration");
625
626
  globalConfig = { ...DEFAULT_CONFIG };
626
627
  } else {
@@ -657,7 +658,7 @@ var ConfigStore = class {
657
658
  return this.reset();
658
659
  }
659
660
  if (error instanceof z.ZodError) {
660
- console.error("Config validation error:", error.errors);
661
+ console.error("Config validation error:", error.issues);
661
662
  console.error("Resetting to default configuration");
662
663
  return this.reset();
663
664
  }
@@ -16,10 +16,10 @@ import {
16
16
  dayjsConfig_default,
17
17
  extractSnippetMeta,
18
18
  settingsMap
19
- } from "./chunk-T4VPCTBM.js";
19
+ } from "./chunk-NI22LIK3.js";
20
20
  import {
21
21
  Logger
22
- } from "./chunk-OCYRD7D6.js";
22
+ } from "./chunk-PFBYGCOW.js";
23
23
 
24
24
  // ../../b4m-core/packages/utils/dist/src/storage/S3Storage.js
25
25
  import { S3Client, PutObjectCommand, DeleteObjectCommand, GetObjectCommand, HeadObjectCommand } from "@aws-sdk/client-s3";
@@ -591,6 +591,125 @@ function getSettingsCacheStats() {
591
591
  // ../../b4m-core/packages/utils/dist/src/ingest.js
592
592
  import axios from "axios";
593
593
  import mime2 from "mime-types";
594
+
595
+ // ../../b4m-core/packages/utils/dist/src/ssrfProtection.js
596
+ import dns from "dns";
597
+ import { promisify } from "util";
598
+ var dnsResolve4 = promisify(dns.resolve4);
599
+ var dnsResolve6 = promisify(dns.resolve6);
600
+ function isPrivateIPv4(ip) {
601
+ const ipv4Match = ip.match(/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/);
602
+ if (!ipv4Match)
603
+ return false;
604
+ const [, a, b, c] = ipv4Match.map(Number);
605
+ if (a === 10)
606
+ return true;
607
+ if (a === 172 && b >= 16 && b <= 31)
608
+ return true;
609
+ if (a === 192 && b === 168)
610
+ return true;
611
+ if (a === 127)
612
+ return true;
613
+ if (a === 169 && b === 254)
614
+ return true;
615
+ if (a === 0)
616
+ return true;
617
+ if (a === 100 && b >= 64 && b <= 127)
618
+ return true;
619
+ if (a === 192 && b === 0 && c === 0)
620
+ return true;
621
+ if (a === 192 && b === 0 && c === 2 || a === 198 && b === 51 && c === 100 || a === 203 && b === 0 && c === 113)
622
+ return true;
623
+ if (a >= 224 && a <= 239)
624
+ return true;
625
+ if (a >= 240)
626
+ return true;
627
+ return false;
628
+ }
629
+ function isPrivateIPv6(ip) {
630
+ const normalized = ip.toLowerCase();
631
+ if (normalized === "::1" || normalized === "0:0:0:0:0:0:0:1")
632
+ return true;
633
+ if (normalized === "::" || normalized === "0:0:0:0:0:0:0:0")
634
+ return true;
635
+ if (normalized.startsWith("fe8") || normalized.startsWith("fe9") || normalized.startsWith("fea") || normalized.startsWith("feb"))
636
+ return true;
637
+ if (normalized.startsWith("fc") || normalized.startsWith("fd"))
638
+ return true;
639
+ if (normalized.startsWith("ff"))
640
+ return true;
641
+ const ipv4MappedMatch = normalized.match(/^::ffff:(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})$/);
642
+ if (ipv4MappedMatch) {
643
+ return isPrivateIPv4(ipv4MappedMatch[1]);
644
+ }
645
+ if (normalized.startsWith("2001:db8:") || normalized.startsWith("2001:0db8:"))
646
+ return true;
647
+ if (normalized.startsWith("100::") || normalized.startsWith("0100::"))
648
+ return true;
649
+ if (normalized.startsWith("64:ff9b:") || normalized.startsWith("0064:ff9b:"))
650
+ return true;
651
+ return false;
652
+ }
653
+ function isPrivateIP(ip) {
654
+ if (/^(\d{1,3}\.){3}\d{1,3}$/.test(ip)) {
655
+ return isPrivateIPv4(ip);
656
+ }
657
+ return isPrivateIPv6(ip);
658
+ }
659
+ function isPrivateOrInternalHostname(hostname) {
660
+ const normalized = hostname.toLowerCase();
661
+ if (normalized === "localhost" || normalized === "127.0.0.1" || normalized === "::1" || normalized === "0.0.0.0" || normalized.endsWith(".localhost") || normalized.endsWith(".local")) {
662
+ return true;
663
+ }
664
+ if (normalized === "169.254.169.254" || normalized === "instance-data" || normalized === "metadata.google.internal" || normalized === "metadata.internal") {
665
+ return true;
666
+ }
667
+ if (normalized.endsWith(".cluster.local") || normalized.endsWith(".svc.cluster.local") || normalized.endsWith(".pod.cluster.local")) {
668
+ return true;
669
+ }
670
+ if (/^(\d{1,3}\.){3}\d{1,3}$/.test(normalized)) {
671
+ return isPrivateIPv4(normalized);
672
+ }
673
+ if (normalized.includes(":")) {
674
+ return isPrivateIPv6(normalized);
675
+ }
676
+ return false;
677
+ }
678
+ async function validateUrlForFetch(url) {
679
+ try {
680
+ const parsed = new URL(url);
681
+ if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
682
+ return { valid: false, error: "URL must use HTTP or HTTPS protocol" };
683
+ }
684
+ if (isPrivateOrInternalHostname(parsed.hostname)) {
685
+ return { valid: false, error: "URL points to a private or internal network" };
686
+ }
687
+ const isIPv4Address = /^(\d{1,3}\.){3}\d{1,3}$/.test(parsed.hostname);
688
+ const isIPv6Address = parsed.hostname.includes(":");
689
+ if (!isIPv4Address && !isIPv6Address) {
690
+ try {
691
+ const ipv4Addresses = await dnsResolve4(parsed.hostname).catch(() => []);
692
+ const ipv6Addresses = await dnsResolve6(parsed.hostname).catch(() => []);
693
+ const allAddresses = [...ipv4Addresses, ...ipv6Addresses];
694
+ if (allAddresses.length === 0) {
695
+ return { valid: false, error: "Could not resolve hostname" };
696
+ }
697
+ for (const ip of allAddresses) {
698
+ if (isPrivateIP(ip)) {
699
+ return { valid: false, error: `Hostname resolves to private IP address (${ip})` };
700
+ }
701
+ }
702
+ } catch {
703
+ return { valid: false, error: "Could not resolve hostname" };
704
+ }
705
+ }
706
+ return { valid: true };
707
+ } catch {
708
+ return { valid: false, error: "Invalid URL format" };
709
+ }
710
+ }
711
+
712
+ // ../../b4m-core/packages/utils/dist/src/ingest.js
594
713
  var URL_REGEX = /https?:\/\/(?:[-\w.])+(?:\:[0-9]+)?(?:\/(?:[\w\/_.])*(?:\?(?:[\w&=%.])*)?(?:\#(?:[\w.])*)?)?/gi;
595
714
  function detectURLs(string) {
596
715
  const urlsFound = string.match(URL_REGEX) || [];
@@ -603,15 +722,22 @@ function urlExists(stringWithPossibleUrl) {
603
722
  const cleanString = stringWithPossibleUrl.replace(/\n/g, " ").replace(/,/g, " ");
604
723
  return detectURLs(cleanString);
605
724
  }
725
+ var URL_FETCH_TIMEOUT_MS = 1e4;
606
726
  async function fetchAndParseURL(url, { logger }) {
607
727
  logger.updateMetadata({ failedUrl: null });
608
728
  try {
729
+ const ssrfValidation = await validateUrlForFetch(url);
730
+ if (!ssrfValidation.valid) {
731
+ throw new Error(`URL blocked for security reasons: ${ssrfValidation.error}`);
732
+ }
609
733
  let urlMimeType = "text/plain";
610
734
  if (url.split(".")?.pop()?.startsWith("pdf")) {
611
735
  urlMimeType = "application/pdf";
612
736
  }
613
737
  const response = await axios.get(url, {
614
- responseType: ["application/pdf"].includes(urlMimeType) ? "arraybuffer" : "text"
738
+ responseType: ["application/pdf"].includes(urlMimeType) ? "arraybuffer" : "text",
739
+ timeout: URL_FETCH_TIMEOUT_MS
740
+ // Prevent Lambda timeout exhaustion
615
741
  });
616
742
  const cheerio = await import("cheerio");
617
743
  const htmlContent = response.data;
@@ -619,17 +745,19 @@ async function fetchAndParseURL(url, { logger }) {
619
745
  const title = $("title").text() || url.split("/")?.pop();
620
746
  let urlContent = null;
621
747
  switch (urlMimeType) {
622
- case "application/pdf":
748
+ case "application/pdf": {
623
749
  const pdfbuffer = Buffer.from(response.data);
624
750
  urlContent = pdfbuffer;
625
751
  break;
626
- default:
752
+ }
753
+ default: {
627
754
  let textContent = "";
628
755
  $("body").find("p").each((index, element) => {
629
756
  textContent += $(element).text() + "\n";
630
757
  });
631
758
  urlContent = textContent || htmlContent;
632
759
  break;
760
+ }
633
761
  }
634
762
  logger.log(`Fetched ${title} with mimetype ${urlMimeType} and parsed ${url}`);
635
763
  return { title, textContent: urlContent, mimeType: urlMimeType, ext: mime2.extension(urlMimeType) || null };
@@ -1155,8 +1283,30 @@ function separateUrls(urls) {
1155
1283
  const nonImageUrls = urls.filter((url) => !imageExtensions.some((ext) => url.toLowerCase().endsWith(ext)));
1156
1284
  return { imageUrls, nonImageUrls };
1157
1285
  }
1158
- var urlContentCache = /* @__PURE__ */ new Map();
1159
- var CACHE_TTL_MS = 5 * 60 * 1e3;
1286
+ function sanitizeUrlForLogging(url) {
1287
+ try {
1288
+ const parsed = new URL(url);
1289
+ const sensitiveParams = [
1290
+ "token",
1291
+ "key",
1292
+ "api_key",
1293
+ "apikey",
1294
+ "secret",
1295
+ "password",
1296
+ "session",
1297
+ "auth",
1298
+ "access_token"
1299
+ ];
1300
+ sensitiveParams.forEach((param) => {
1301
+ if (parsed.searchParams.has(param)) {
1302
+ parsed.searchParams.set(param, "[REDACTED]");
1303
+ }
1304
+ });
1305
+ return parsed.toString();
1306
+ } catch {
1307
+ return url.substring(0, 100) + (url.length > 100 ? "..." : "");
1308
+ }
1309
+ }
1160
1310
  async function processUrlsFromPrompt(userPrompt, maxContentBuffer, userId, sendStatusUpdate, logger, options = { verbose: false }) {
1161
1311
  if (!hasURLs(userPrompt)) {
1162
1312
  if (options?.verbose) {
@@ -1164,6 +1314,7 @@ async function processUrlsFromPrompt(userPrompt, maxContentBuffer, userId, sendS
1164
1314
  }
1165
1315
  return { userMessages: [], remainingPrompt: userPrompt };
1166
1316
  }
1317
+ const urlContentCache = /* @__PURE__ */ new Map();
1167
1318
  sendStatusUpdate("Processing URLs from user prompt...");
1168
1319
  const userMessages = [];
1169
1320
  const promptMeta = extractSnippetMeta(userPrompt);
@@ -1191,20 +1342,26 @@ async function processUrlsFromPrompt(userPrompt, maxContentBuffer, userId, sendS
1191
1342
  try {
1192
1343
  const cached = urlContentCache.get(url);
1193
1344
  let textContent;
1194
- if (cached && Date.now() - cached.timestamp < CACHE_TTL_MS) {
1195
- if (options?.verbose) {
1196
- logger.log(`Using cached content for URL: ${url}`);
1197
- }
1198
- textContent = cached.content;
1345
+ if (cached) {
1346
+ logger.info("URL_FETCH", {
1347
+ userId,
1348
+ url: sanitizeUrlForLogging(url),
1349
+ cacheHit: true,
1350
+ source: "same-request-dedup"
1351
+ });
1352
+ textContent = cached;
1199
1353
  } else {
1200
1354
  const result = await fetchAndParseURL(url, { logger });
1201
1355
  if (typeof result.textContent !== "string")
1202
1356
  throw new Error("textContent is not a string");
1203
1357
  textContent = result.textContent;
1204
- urlContentCache.set(url, {
1205
- content: textContent,
1206
- timestamp: Date.now()
1358
+ logger.info("URL_FETCH", {
1359
+ userId,
1360
+ url: sanitizeUrlForLogging(url),
1361
+ cacheHit: false,
1362
+ contentLength: textContent.length
1207
1363
  });
1364
+ urlContentCache.set(url, textContent);
1208
1365
  }
1209
1366
  const message = {
1210
1367
  role: "user",
@@ -7634,7 +7791,7 @@ function secureParameters(params, schema) {
7634
7791
  return schema.parse(params);
7635
7792
  } catch (e) {
7636
7793
  if (isZodError(e)) {
7637
- throw new UnprocessableEntityError(e.errors.map((err) => `${err.path.join(".")}: ${err.message}`).join(", "));
7794
+ throw new UnprocessableEntityError(e.issues.map((err) => `${err.path.join(".")}: ${err.message}`).join(", "));
7638
7795
  }
7639
7796
  throw new InternalServerError();
7640
7797
  }
@@ -11600,6 +11757,9 @@ function findAutomaticFallback(originalModel, availableModels, apiKeyTable, logg
11600
11757
  "gemini-2.5-flash-preview-05-20": ["claude-3-5-haiku-20241022", "gpt-4o-mini", "claude-3-haiku-20240307"],
11601
11758
  "gemini-1.5-pro": ["claude-3-5-sonnet-20241022", "gpt-4o", "claude-3-opus-20240229"],
11602
11759
  "gemini-1.5-flash": ["claude-3-5-haiku-20241022", "gpt-4o-mini", "claude-3-haiku-20240307"],
11760
+ // Claude 4.5/4.6 Opus models fallback to Sonnet 4.5
11761
+ "claude-opus-4-5-20251101": ["claude-sonnet-4-5-20250929", "gpt-5", "claude-haiku-4-5-20251001"],
11762
+ "claude-opus-4-6": ["claude-sonnet-4-5-20250929", "gpt-5", "claude-haiku-4-5-20251001"],
11603
11763
  // Claude models fallback to other Claude models or GPT
11604
11764
  "claude-3-5-sonnet-20241022": ["claude-3-opus-20240229", "gpt-4o", "claude-3-sonnet-20240229"],
11605
11765
  "claude-3-opus-20240229": ["claude-3-5-sonnet-20241022", "gpt-4o", "claude-3-sonnet-20240229"],
@@ -11609,7 +11769,7 @@ function findAutomaticFallback(originalModel, availableModels, apiKeyTable, logg
11609
11769
  };
11610
11770
  const preferences = fallbackPreferences[originalModel.id] || [];
11611
11771
  if (preferences.length === 0) {
11612
- preferences.push("claude-3-5-sonnet-20241022", "gpt-4o", "claude-3-haiku-20240307");
11772
+ preferences.push("claude-sonnet-4-5-20250929", "gpt-5", "claude-haiku-4-5-20251001");
11613
11773
  }
11614
11774
  for (const modelId of preferences) {
11615
11775
  const fallbackModel = availableModels.find((m) => m.id === modelId);
@@ -11998,6 +12158,59 @@ function buildVoiceInstructions(baseInstructions, historyContext) {
11998
12158
  return `${baseInstructions}${historyContext}`;
11999
12159
  }
12000
12160
 
12161
+ // ../../b4m-core/packages/utils/dist/src/lambdaErrorHandler.js
12162
+ var isRegistered = false;
12163
+ function classifyError(error) {
12164
+ if (error instanceof TypeError) {
12165
+ if (error.message === "terminated" || error.message.includes("fetch failed")) {
12166
+ return "network_terminated";
12167
+ }
12168
+ }
12169
+ if (error instanceof Error) {
12170
+ if (error.name === "AbortError") {
12171
+ return "network_timeout";
12172
+ }
12173
+ const connectionErrors = ["ECONNRESET", "ETIMEDOUT", "ECONNREFUSED", "EPIPE", "ENOTFOUND"];
12174
+ if (connectionErrors.some((code) => error.message.includes(code))) {
12175
+ return "network_connection";
12176
+ }
12177
+ }
12178
+ return "unhandled_rejection";
12179
+ }
12180
+ function buildLogEntry(error, category) {
12181
+ return {
12182
+ error: error instanceof Error ? error.message : String(error),
12183
+ stack: error instanceof Error ? error.stack : void 0,
12184
+ category,
12185
+ functionName: process.env.AWS_LAMBDA_FUNCTION_NAME,
12186
+ stage: process.env.SEED_STAGE_NAME,
12187
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
12188
+ };
12189
+ }
12190
+ function registerLambdaErrorHandlers(logger) {
12191
+ if (isRegistered)
12192
+ return;
12193
+ isRegistered = true;
12194
+ const log = logger || console;
12195
+ process.on("unhandledRejection", (reason) => {
12196
+ const category = classifyError(reason);
12197
+ const isNetworkError = category.startsWith("network_");
12198
+ const logEntry = buildLogEntry(reason, category);
12199
+ if (isNetworkError) {
12200
+ log.warn("[Lambda] Network error (unhandled rejection)", logEntry);
12201
+ } else {
12202
+ log.error("[Lambda] Unhandled promise rejection", logEntry);
12203
+ }
12204
+ });
12205
+ process.on("uncaughtException", (error) => {
12206
+ const logEntry = buildLogEntry(error, "uncaught_exception");
12207
+ log.error("[Lambda] Uncaught exception", logEntry);
12208
+ });
12209
+ }
12210
+ function _resetLambdaErrorHandlers() {
12211
+ isRegistered = false;
12212
+ }
12213
+
12001
12214
  export {
12002
12215
  BaseStorage,
12003
12216
  S3Storage,
@@ -12015,6 +12228,9 @@ export {
12015
12228
  warmUpSettingsCache,
12016
12229
  shutdownSettingsCache,
12017
12230
  getSettingsCacheStats,
12231
+ isPrivateIP,
12232
+ isPrivateOrInternalHostname,
12233
+ validateUrlForFetch,
12018
12234
  URL_REGEX,
12019
12235
  detectURLs,
12020
12236
  hasURLs,
@@ -12132,5 +12348,7 @@ export {
12132
12348
  calculateRetryDelay,
12133
12349
  withRetry,
12134
12350
  formatVoiceHistory,
12135
- buildVoiceInstructions
12351
+ buildVoiceInstructions,
12352
+ registerLambdaErrorHandlers,
12353
+ _resetLambdaErrorHandlers
12136
12354
  };
@@ -7,11 +7,11 @@ import {
7
7
  getSettingsMap,
8
8
  getSettingsValue,
9
9
  secureParameters
10
- } from "./chunk-BQAPZP5Y.js";
10
+ } from "./chunk-3SPW5FYJ.js";
11
11
  import {
12
12
  KnowledgeType,
13
13
  SupportedFabFileMimeTypes
14
- } from "./chunk-T4VPCTBM.js";
14
+ } from "./chunk-NI22LIK3.js";
15
15
 
16
16
  // ../../b4m-core/packages/services/dist/src/fabFileService/create.js
17
17
  import { z } from "zod";
@@ -20,7 +20,7 @@ var createFabFileSchema = z.object({
20
20
  fileName: z.string(),
21
21
  mimeType: z.string(),
22
22
  fileSize: z.number(),
23
- type: z.nativeEnum(KnowledgeType),
23
+ type: z.enum(KnowledgeType),
24
24
  content: z.union([z.string(), z.instanceof(Buffer)]).optional(),
25
25
  organizationId: z.string().optional(),
26
26
  /**
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  BadRequestError,
4
4
  secureParameters
5
- } from "./chunk-BQAPZP5Y.js";
5
+ } from "./chunk-3SPW5FYJ.js";
6
6
  import {
7
7
  CompletionApiUsageTransaction,
8
8
  GenericCreditDeductTransaction,
@@ -12,7 +12,7 @@ import {
12
12
  TextGenerationUsageTransaction,
13
13
  TransferCreditTransaction,
14
14
  VideoGenerationUsageTransaction
15
- } from "./chunk-T4VPCTBM.js";
15
+ } from "./chunk-NI22LIK3.js";
16
16
 
17
17
  // ../../b4m-core/packages/services/dist/src/creditService/subtractCredits.js
18
18
  import { z } from "zod";
@@ -595,12 +595,13 @@ var HydrationEngine = class {
595
595
  return numericInputs[0] / numericInputs[1];
596
596
  case "ABS":
597
597
  return numericInputs.length > 0 ? Math.abs(numericInputs[0]) : 0;
598
- case "ROUND":
598
+ case "ROUND": {
599
599
  if (numericInputs.length === 0)
600
600
  return 0;
601
601
  const decimals = numericInputs[1] ?? 0;
602
602
  const factor = Math.pow(10, decimals);
603
603
  return Math.round(numericInputs[0] * factor) / factor;
604
+ }
604
605
  case "FLOOR":
605
606
  return numericInputs.length > 0 ? Math.floor(numericInputs[0]) : 0;
606
607
  case "CEIL":
@@ -624,12 +625,13 @@ var HydrationEngine = class {
624
625
  return numericInputs.length > 0 ? Math.max(...numericInputs) : 0;
625
626
  case "COUNT":
626
627
  return inputs.filter((v) => v !== null).length;
627
- case "MEDIAN":
628
+ case "MEDIAN": {
628
629
  if (numericInputs.length === 0)
629
630
  return 0;
630
631
  const sorted = [...numericInputs].sort((a, b) => a - b);
631
632
  const mid = Math.floor(sorted.length / 2);
632
633
  return sorted.length % 2 === 0 ? (sorted[mid - 1] + sorted[mid]) / 2 : sorted[mid];
634
+ }
633
635
  // Logical
634
636
  case "IF":
635
637
  return inputs[0] ? inputs[1] : inputs[2];
@@ -649,13 +651,14 @@ var HydrationEngine = class {
649
651
  return inputs.length >= 2 && inputs[0] >= inputs[1];
650
652
  case "LESS_THAN_OR_EQUAL":
651
653
  return inputs.length >= 2 && inputs[0] <= inputs[1];
652
- case "BETWEEN":
654
+ case "BETWEEN": {
653
655
  if (inputs.length < 3)
654
656
  return false;
655
657
  const val = inputs[0];
656
658
  const min = inputs[1];
657
659
  const max = inputs[2];
658
660
  return val >= min && val <= max;
661
+ }
659
662
  // Financial
660
663
  case "PERCENT_OF":
661
664
  if (numericInputs.length < 2 || numericInputs[1] === 0)
@@ -714,11 +717,12 @@ var HydrationEngine = class {
714
717
  case "REFERENCE":
715
718
  return inputs[0];
716
719
  // Pass through
717
- case "LOOKUP":
720
+ case "LOOKUP": {
718
721
  if (inputs.length < 2)
719
722
  return null;
720
723
  const index = inputs[0];
721
724
  return inputs[Math.min(index + 1, inputs.length - 1)];
725
+ }
722
726
  default:
723
727
  context.errors.push({
724
728
  type: "INVALID_OPERATION",
@@ -6,17 +6,17 @@ import {
6
6
  getSettingsByNames,
7
7
  obfuscateApiKey,
8
8
  secureParameters
9
- } from "./chunk-BQAPZP5Y.js";
9
+ } from "./chunk-3SPW5FYJ.js";
10
10
  import {
11
11
  ApiKeyType,
12
12
  MementoTier,
13
13
  isSupportedEmbeddingModel
14
- } from "./chunk-T4VPCTBM.js";
14
+ } from "./chunk-NI22LIK3.js";
15
15
 
16
16
  // ../../b4m-core/packages/services/dist/src/apiKeyService/get.js
17
17
  import { z } from "zod";
18
18
  var getApiKeySchema = z.object({
19
- type: z.nativeEnum(ApiKeyType),
19
+ type: z.enum(ApiKeyType),
20
20
  nullIfMissing: z.boolean().optional(),
21
21
  obfuscate: z.boolean().optional(),
22
22
  demoKeyName: z.string().optional()