@character-foundry/character-foundry 0.1.9 → 0.4.0-dev.1765937896

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 (71) hide show
  1. package/dist/app-framework.cjs +291 -95
  2. package/dist/app-framework.cjs.map +1 -1
  3. package/dist/app-framework.d.cts +1 -1
  4. package/dist/app-framework.d.ts +1 -1
  5. package/dist/app-framework.js +292 -96
  6. package/dist/app-framework.js.map +1 -1
  7. package/dist/charx.cjs +44 -23
  8. package/dist/charx.cjs.map +1 -1
  9. package/dist/charx.d.cts +368 -207
  10. package/dist/charx.d.ts +368 -207
  11. package/dist/charx.js +44 -23
  12. package/dist/charx.js.map +1 -1
  13. package/dist/exporter.cjs +27 -22
  14. package/dist/exporter.cjs.map +1 -1
  15. package/dist/exporter.d.cts +368 -207
  16. package/dist/exporter.d.ts +368 -207
  17. package/dist/exporter.js +27 -22
  18. package/dist/exporter.js.map +1 -1
  19. package/dist/federation.cjs +16 -4
  20. package/dist/federation.cjs.map +1 -1
  21. package/dist/federation.d.cts +368 -207
  22. package/dist/federation.d.ts +368 -207
  23. package/dist/federation.js +16 -4
  24. package/dist/federation.js.map +1 -1
  25. package/dist/image-utils.cjs.map +1 -1
  26. package/dist/image-utils.d.cts +12 -0
  27. package/dist/image-utils.d.ts +12 -0
  28. package/dist/image-utils.js.map +1 -1
  29. package/dist/index.cjs +106 -56
  30. package/dist/index.cjs.map +1 -1
  31. package/dist/index.d.cts +708 -423
  32. package/dist/index.d.ts +708 -423
  33. package/dist/index.js +106 -56
  34. package/dist/index.js.map +1 -1
  35. package/dist/loader.cjs +106 -56
  36. package/dist/loader.cjs.map +1 -1
  37. package/dist/loader.d.cts +564 -318
  38. package/dist/loader.d.ts +564 -318
  39. package/dist/loader.js +106 -56
  40. package/dist/loader.js.map +1 -1
  41. package/dist/lorebook.cjs +5 -5
  42. package/dist/lorebook.cjs.map +1 -1
  43. package/dist/lorebook.d.cts +674 -381
  44. package/dist/lorebook.d.ts +674 -381
  45. package/dist/lorebook.js +5 -5
  46. package/dist/lorebook.js.map +1 -1
  47. package/dist/normalizer.cjs +33 -23
  48. package/dist/normalizer.cjs.map +1 -1
  49. package/dist/normalizer.d.cts +896 -560
  50. package/dist/normalizer.d.ts +896 -560
  51. package/dist/normalizer.js +33 -23
  52. package/dist/normalizer.js.map +1 -1
  53. package/dist/png.cjs +27 -22
  54. package/dist/png.cjs.map +1 -1
  55. package/dist/png.d.cts +512 -312
  56. package/dist/png.d.ts +512 -312
  57. package/dist/png.js +27 -22
  58. package/dist/png.js.map +1 -1
  59. package/dist/schemas.cjs +41 -26
  60. package/dist/schemas.cjs.map +1 -1
  61. package/dist/schemas.d.cts +1444 -896
  62. package/dist/schemas.d.ts +1444 -896
  63. package/dist/schemas.js +41 -26
  64. package/dist/schemas.js.map +1 -1
  65. package/dist/voxta.cjs +48 -25
  66. package/dist/voxta.cjs.map +1 -1
  67. package/dist/voxta.d.cts +564 -318
  68. package/dist/voxta.d.ts +564 -318
  69. package/dist/voxta.js +48 -25
  70. package/dist/voxta.js.map +1 -1
  71. package/package.json +6 -6
package/dist/index.js CHANGED
@@ -104,7 +104,23 @@ function streamingUnzipSync(data, limits = DEFAULT_ZIP_LIMITS) {
104
104
  if (unsafePathHandling === "warn" && limits.onUnsafePath) {
105
105
  limits.onUnsafePath(file.name, reason);
106
106
  }
107
- file.ondata = () => {
107
+ file.ondata = (err, chunk, _final) => {
108
+ if (error) return;
109
+ if (err) {
110
+ error = err;
111
+ return;
112
+ }
113
+ if (chunk && chunk.length > 0) {
114
+ totalBytes += chunk.length;
115
+ if (totalBytes > limits.maxTotalSize) {
116
+ error = new ZipPreflightError(
117
+ `Total actual size ${totalBytes} exceeds limit ${limits.maxTotalSize}`,
118
+ totalBytes,
119
+ limits.maxTotalSize
120
+ );
121
+ file.terminate();
122
+ }
123
+ }
108
124
  };
109
125
  file.start();
110
126
  return;
@@ -564,22 +580,24 @@ var ExtractedAssetSchema = z.object({
564
580
  mimeType: z.string()
565
581
  });
566
582
  var CCv2LorebookEntrySchema = z2.object({
567
- keys: z2.array(z2.string()),
583
+ keys: z2.array(z2.string()).optional(),
584
+ // Some tools use 'key' instead
568
585
  content: z2.string(),
569
- enabled: z2.boolean(),
570
- insertion_order: z2.number().int(),
571
- // Optional fields
586
+ enabled: z2.boolean().default(true),
587
+ // Default to enabled if missing
588
+ insertion_order: z2.number().int().default(0),
589
+ // Optional fields - be lenient with nulls since wild data has them
572
590
  extensions: z2.record(z2.unknown()).optional(),
573
- case_sensitive: z2.boolean().optional(),
591
+ case_sensitive: z2.boolean().nullable().optional(),
574
592
  name: z2.string().optional(),
575
593
  priority: z2.number().int().optional(),
576
594
  id: z2.number().int().optional(),
577
595
  comment: z2.string().optional(),
578
- selective: z2.boolean().optional(),
596
+ selective: z2.boolean().nullable().optional(),
579
597
  secondary_keys: z2.array(z2.string()).optional(),
580
- constant: z2.boolean().optional(),
581
- position: z2.enum(["before_char", "after_char"]).optional()
582
- });
598
+ constant: z2.boolean().nullable().optional(),
599
+ position: z2.union([z2.enum(["before_char", "after_char"]), z2.number().int()]).nullable().optional()
600
+ }).passthrough();
583
601
  var CCv2CharacterBookSchema = z2.object({
584
602
  name: z2.string().optional(),
585
603
  description: z2.string().optional(),
@@ -627,31 +645,34 @@ function getV2Data(card) {
627
645
  return card;
628
646
  }
629
647
  var CCv3LorebookEntrySchema = z3.object({
630
- keys: z3.array(z3.string()),
648
+ keys: z3.array(z3.string()).optional(),
649
+ // Some tools use 'key' instead
631
650
  content: z3.string(),
632
- enabled: z3.boolean(),
633
- insertion_order: z3.number().int(),
634
- // Optional fields
635
- case_sensitive: z3.boolean().optional(),
651
+ enabled: z3.boolean().default(true),
652
+ // Default to enabled if missing
653
+ insertion_order: z3.number().int().default(0),
654
+ // Optional fields - be lenient with nulls since wild data has them
655
+ case_sensitive: z3.boolean().nullable().optional(),
636
656
  name: z3.string().optional(),
637
657
  priority: z3.number().int().optional(),
638
658
  id: z3.number().int().optional(),
639
659
  comment: z3.string().optional(),
640
- selective: z3.boolean().optional(),
660
+ selective: z3.boolean().nullable().optional(),
641
661
  secondary_keys: z3.array(z3.string()).optional(),
642
- constant: z3.boolean().optional(),
643
- position: z3.enum(["before_char", "after_char"]).optional(),
662
+ constant: z3.boolean().nullable().optional(),
663
+ position: z3.union([z3.enum(["before_char", "after_char"]), z3.number().int()]).nullable().optional(),
644
664
  extensions: z3.record(z3.unknown()).optional(),
645
- // v3 specific
665
+ // v3 specific - also lenient with types since SillyTavern uses numbers for enums
646
666
  automation_id: z3.string().optional(),
647
- role: z3.enum(["system", "user", "assistant"]).optional(),
667
+ role: z3.union([z3.enum(["system", "user", "assistant"]), z3.number().int()]).nullable().optional(),
648
668
  group: z3.string().optional(),
649
669
  scan_frequency: z3.number().int().nonnegative().optional(),
650
- probability: z3.number().min(0).max(1).optional(),
670
+ probability: z3.number().min(0).max(100).optional(),
671
+ // Some tools use 0-100 instead of 0-1
651
672
  use_regex: z3.boolean().optional(),
652
673
  depth: z3.number().int().nonnegative().optional(),
653
- selective_logic: z3.enum(["AND", "NOT"]).optional()
654
- });
674
+ selective_logic: z3.union([z3.enum(["AND", "NOT"]), z3.number().int()]).optional()
675
+ }).passthrough();
655
676
  var CCv3CharacterBookSchema = z3.object({
656
677
  name: z3.string().optional(),
657
678
  description: z3.string().optional(),
@@ -8087,8 +8108,10 @@ function voxtaToCCv3(character, books) {
8087
8108
  };
8088
8109
  }
8089
8110
  }
8090
- const creationDate = character.DateCreated ? Math.floor(new Date(character.DateCreated).getTime() / 1e3) : void 0;
8091
- const modificationDate = character.DateModified ? Math.floor(new Date(character.DateModified).getTime() / 1e3) : void 0;
8111
+ const rawCreationDate = character.DateCreated ? Math.floor(new Date(character.DateCreated).getTime() / 1e3) : void 0;
8112
+ const rawModificationDate = character.DateModified ? Math.floor(new Date(character.DateModified).getTime() / 1e3) : void 0;
8113
+ const creationDate = rawCreationDate !== void 0 && rawCreationDate >= 0 ? rawCreationDate : void 0;
8114
+ const modificationDate = rawModificationDate !== void 0 && rawModificationDate >= 0 ? rawModificationDate : void 0;
8092
8115
  const card = {
8093
8116
  spec: "chara_card_v3",
8094
8117
  spec_version: "3.0",
@@ -8329,6 +8352,11 @@ var DELTA_MAX_TOTAL_SIZE = 500 * 1024 * 1024;
8329
8352
  var DELTA_MAX_FILE_SIZE = 50 * 1024 * 1024;
8330
8353
 
8331
8354
  // ../normalizer/dist/index.js
8355
+ function normalizePosition(position) {
8356
+ if (position === void 0 || position === null) return "before_char";
8357
+ if (typeof position === "string") return position;
8358
+ return position;
8359
+ }
8332
8360
  function convertLorebookEntry(entry, index) {
8333
8361
  return {
8334
8362
  keys: entry.keys || [],
@@ -8344,7 +8372,7 @@ function convertLorebookEntry(entry, index) {
8344
8372
  selective: entry.selective ?? false,
8345
8373
  secondary_keys: entry.secondary_keys || [],
8346
8374
  constant: entry.constant ?? false,
8347
- position: entry.position || "before_char"
8375
+ position: normalizePosition(entry.position)
8348
8376
  };
8349
8377
  }
8350
8378
  function convertCharacterBook(book) {
@@ -8507,6 +8535,43 @@ var DEFAULT_OPTIONS3 = {
8507
8535
  maxTotalSize: 500 * 1024 * 1024,
8508
8536
  extractAssets: true
8509
8537
  };
8538
+ var ASSET_PREFIX_VARIANTS = [
8539
+ { prefix: "__asset:", format: "CCv3 (SillyTavern)" },
8540
+ { prefix: "asset:", format: "CCv2/CCv3 common" },
8541
+ { prefix: "pngchunk:", format: "Explicit PNG chunk" },
8542
+ { prefix: "chara-ext-asset_:", format: "RisuAI (with colon)" },
8543
+ { prefix: "chara-ext-asset_", format: "RisuAI" },
8544
+ { prefix: "__asset_", format: "Legacy underscore variant" }
8545
+ ];
8546
+ function isChunkReference(uri) {
8547
+ return ASSET_PREFIX_VARIANTS.some(({ prefix }) => uri.startsWith(prefix)) || !uri.includes(":");
8548
+ }
8549
+ function stripAssetPrefix(uri) {
8550
+ for (const { prefix } of ASSET_PREFIX_VARIANTS) {
8551
+ if (uri.startsWith(prefix)) {
8552
+ return uri.substring(prefix.length);
8553
+ }
8554
+ }
8555
+ return uri;
8556
+ }
8557
+ function generateChunkKeyCandidates(assetId, originalUri) {
8558
+ return [
8559
+ assetId,
8560
+ // Plain ID: "0"
8561
+ originalUri,
8562
+ // Original URI: "__asset:0"
8563
+ `asset:${assetId}`,
8564
+ // Common format
8565
+ `__asset:${assetId}`,
8566
+ // CCv3 format
8567
+ `__asset_${assetId}`,
8568
+ // Legacy underscore variant
8569
+ `chara-ext-asset_${assetId}`,
8570
+ // RisuAI format
8571
+ `chara-ext-asset_:${assetId}`
8572
+ // RisuAI format with colon
8573
+ ];
8574
+ }
8510
8575
  function estimateBase64DecodedSize(base64Length) {
8511
8576
  return Math.ceil(base64Length * 0.75);
8512
8577
  }
@@ -8574,39 +8639,22 @@ function parsePng(data, options) {
8574
8639
  if (extracted.extraChunks && options.extractAssets && card.data.assets) {
8575
8640
  const usedChunks = /* @__PURE__ */ new Set();
8576
8641
  const chunkMap = /* @__PURE__ */ new Map();
8642
+ const risuIndexPrefixes = ASSET_PREFIX_VARIANTS.filter((v) => v.prefix.startsWith("chara-ext-asset_"));
8577
8643
  for (const chunk of extracted.extraChunks) {
8578
8644
  chunkMap.set(chunk.keyword, chunk);
8579
- if (chunk.keyword.startsWith("chara-ext-asset_")) {
8580
- const suffix = chunk.keyword.replace("chara-ext-asset_", "");
8581
- chunkMap.set(suffix, chunk);
8582
- if (suffix.startsWith(":")) {
8583
- chunkMap.set(suffix.substring(1), chunk);
8645
+ for (const { prefix } of risuIndexPrefixes) {
8646
+ if (chunk.keyword.startsWith(prefix)) {
8647
+ const suffix = chunk.keyword.substring(prefix.length);
8648
+ chunkMap.set(suffix, chunk);
8649
+ break;
8584
8650
  }
8585
8651
  }
8586
8652
  }
8587
8653
  for (const descriptor of card.data.assets) {
8588
8654
  if (!descriptor.uri) continue;
8589
- if (descriptor.uri.startsWith("__asset:") || descriptor.uri.startsWith("asset:") || descriptor.uri.startsWith("pngchunk:") || !descriptor.uri.includes(":")) {
8590
- let assetId = descriptor.uri;
8591
- if (assetId.startsWith("__asset:")) assetId = assetId.substring(8);
8592
- else if (assetId.startsWith("asset:")) assetId = assetId.substring(6);
8593
- else if (assetId.startsWith("pngchunk:")) assetId = assetId.substring(9);
8594
- const candidates = [
8595
- assetId,
8596
- // "0"
8597
- descriptor.uri,
8598
- // "__asset:0"
8599
- `asset:${assetId}`,
8600
- // "asset:0"
8601
- `__asset:${assetId}`,
8602
- // "__asset:0"
8603
- `__asset_${assetId}`,
8604
- // "__asset_0"
8605
- `chara-ext-asset_${assetId}`,
8606
- // "chara-ext-asset_0"
8607
- `chara-ext-asset_:${assetId}`
8608
- // "chara-ext-asset_:0"
8609
- ];
8655
+ if (isChunkReference(descriptor.uri)) {
8656
+ const assetId = stripAssetPrefix(descriptor.uri);
8657
+ const candidates = generateChunkKeyCandidates(assetId, descriptor.uri);
8610
8658
  let chunk;
8611
8659
  for (const candidate of candidates) {
8612
8660
  chunk = chunkMap.get(candidate);
@@ -8653,13 +8701,15 @@ function parsePng(data, options) {
8653
8701
  }
8654
8702
  }
8655
8703
  }
8704
+ const risuPrefixes = ASSET_PREFIX_VARIANTS.filter((v) => v.prefix.startsWith("chara-ext-asset_"));
8656
8705
  for (const chunk of extracted.extraChunks) {
8657
8706
  if (!usedChunks.has(chunk.keyword)) {
8658
8707
  let assetId = null;
8659
- if (chunk.keyword.startsWith("chara-ext-asset_:")) {
8660
- assetId = chunk.keyword.substring("chara-ext-asset_:".length);
8661
- } else if (chunk.keyword.startsWith("chara-ext-asset_")) {
8662
- assetId = chunk.keyword.substring("chara-ext-asset_".length);
8708
+ for (const { prefix } of risuPrefixes) {
8709
+ if (chunk.keyword.startsWith(prefix)) {
8710
+ assetId = chunk.keyword.substring(prefix.length);
8711
+ break;
8712
+ }
8663
8713
  }
8664
8714
  if (assetId) {
8665
8715
  try {