@qvac/sdk 0.17.0 → 0.18.0

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 (154) hide show
  1. package/NOTICE +83 -18
  2. package/README.md +19 -0
  3. package/dist/client/api/audio-gen.d.ts +17 -0
  4. package/dist/client/api/audio-gen.js +17 -0
  5. package/dist/client/api/finetune.d.ts +2 -0
  6. package/dist/client/api/finetune.js +7 -1
  7. package/dist/client/api/index.d.ts +1 -1
  8. package/dist/client/api/index.js +1 -1
  9. package/dist/client/api/load-model.d.ts +8 -0
  10. package/dist/client/api/transcribe.d.ts +19 -2
  11. package/dist/client/api/transcribe.js +66 -27
  12. package/dist/client/api/translate.d.ts +3 -2
  13. package/dist/client/api/translate.js +42 -21
  14. package/dist/client/api/vla.d.ts +42 -1
  15. package/dist/client/api/vla.js +50 -1
  16. package/dist/commands/bundle/entry-gen.d.ts +4 -0
  17. package/dist/commands/bundle/entry-gen.js +6 -0
  18. package/dist/commands/bundle/index.js +19 -12
  19. package/dist/examples/asr/parakeet-indic-conformer-filesystem.d.ts +2 -0
  20. package/dist/examples/asr/parakeet-indic-conformer-filesystem.js +52 -0
  21. package/dist/examples/audiogen/generate-cover.d.ts +2 -0
  22. package/dist/examples/audiogen/generate-cover.js +100 -0
  23. package/dist/examples/llamacpp-fallback.d.ts +2 -0
  24. package/dist/examples/llamacpp-fallback.js +34 -0
  25. package/dist/examples/multi-job-completion.d.ts +28 -0
  26. package/dist/examples/multi-job-completion.js +128 -0
  27. package/dist/examples/profiling/basic.js +32 -1
  28. package/dist/examples/system-resources.d.ts +2 -0
  29. package/dist/examples/system-resources.js +86 -0
  30. package/dist/examples/tts/audio8.d.ts +2 -0
  31. package/dist/examples/tts/audio8.js +54 -0
  32. package/dist/examples/tts/cosyvoice3.d.ts +2 -0
  33. package/dist/examples/tts/cosyvoice3.js +52 -0
  34. package/dist/examples/vla-groot.js +92 -49
  35. package/dist/index.d.ts +2 -2
  36. package/dist/index.js +2 -2
  37. package/dist/models/registry/models.d.ts +782 -6
  38. package/dist/models/registry/models.js +2664 -1859
  39. package/dist/schemas/audio-gen.d.ts +103 -0
  40. package/dist/schemas/audio-gen.js +135 -4
  41. package/dist/schemas/common.d.ts +550 -11
  42. package/dist/schemas/constants-registry.d.ts +18 -4
  43. package/dist/schemas/constants-registry.js +16 -3
  44. package/dist/schemas/index.d.ts +1 -1
  45. package/dist/schemas/index.js +1 -1
  46. package/dist/schemas/llamacpp-config.d.ts +10 -10
  47. package/dist/schemas/llamacpp-config.js +12 -5
  48. package/dist/schemas/load-model.d.ts +3678 -323
  49. package/dist/schemas/load-model.js +21 -3
  50. package/dist/schemas/sdk-config.d.ts +60 -24
  51. package/dist/schemas/sdk-errors-server.d.ts +1 -0
  52. package/dist/schemas/sdk-errors-server.js +5 -0
  53. package/dist/schemas/text-to-speech.d.ts +1086 -110
  54. package/dist/schemas/text-to-speech.js +194 -4
  55. package/dist/schemas/tools.d.ts +0 -16
  56. package/dist/schemas/tools.js +0 -15
  57. package/dist/schemas/transcription-config.d.ts +2 -0
  58. package/dist/schemas/transcription-config.js +10 -4
  59. package/dist/schemas/transcription.d.ts +3 -0
  60. package/dist/schemas/vla.d.ts +83 -0
  61. package/dist/schemas/vla.js +105 -2
  62. package/dist/scripts/link-workspace-inference.d.ts +2 -0
  63. package/dist/scripts/link-workspace-inference.js +31 -0
  64. package/dist/server/bare/ops/cancel.d.ts +1 -1
  65. package/dist/server/bare/ops/cancel.js +1 -1
  66. package/dist/server/bare/ops/kv-cache-retention.js +11 -0
  67. package/dist/server/bare/ops/kv-cache-utils.d.ts +1 -1
  68. package/dist/server/bare/ops/kv-cache-utils.js +40 -12
  69. package/dist/server/bare/ops/transcribe.d.ts +2 -2
  70. package/dist/server/bare/ops/transcribe.js +54 -48
  71. package/dist/server/bare/ops/translate-stats.d.ts +5 -0
  72. package/dist/server/bare/ops/translate-stats.js +11 -0
  73. package/dist/server/bare/ops/translate.js +66 -38
  74. package/dist/server/bare/ops/unload-model.js +30 -24
  75. package/dist/server/bare/plugins/audiogen-ggml/ops/audio-gen-input.d.ts +20 -0
  76. package/dist/server/bare/plugins/audiogen-ggml/ops/audio-gen-input.js +153 -0
  77. package/dist/server/bare/plugins/audiogen-ggml/ops/audio-gen-stream.js +52 -1
  78. package/dist/server/bare/plugins/audiogen-ggml/plugin.d.ts +28 -0
  79. package/dist/server/bare/plugins/ggml-ocr/plugin.js +3 -1
  80. package/dist/server/bare/plugins/ggml-vla/ops/vla-set-embodiment.d.ts +3 -0
  81. package/dist/server/bare/plugins/ggml-vla/ops/vla-set-embodiment.js +9 -0
  82. package/dist/server/bare/plugins/ggml-vla/plugin.d.ts +37 -0
  83. package/dist/server/bare/plugins/ggml-vla/plugin.js +21 -4
  84. package/dist/server/bare/plugins/llamacpp-completion/ops/batch-completion-stream.js +16 -15
  85. package/dist/server/bare/plugins/llamacpp-completion/ops/cache-logger.d.ts +1 -1
  86. package/dist/server/bare/plugins/llamacpp-completion/ops/cache-logger.js +2 -2
  87. package/dist/server/bare/plugins/llamacpp-completion/ops/completion-stats.d.ts +6 -0
  88. package/dist/server/bare/plugins/llamacpp-completion/ops/completion-stats.js +10 -0
  89. package/dist/server/bare/plugins/llamacpp-completion/ops/completion-stream.d.ts +1 -0
  90. package/dist/server/bare/plugins/llamacpp-completion/ops/completion-stream.js +131 -123
  91. package/dist/server/bare/plugins/llamacpp-completion/ops/finetune.js +110 -20
  92. package/dist/server/bare/plugins/llamacpp-completion/ops/kv-cache-session.d.ts +49 -23
  93. package/dist/server/bare/plugins/llamacpp-completion/ops/kv-cache-session.js +308 -143
  94. package/dist/server/bare/plugins/llamacpp-completion/ops/kv-cache-state.d.ts +1 -0
  95. package/dist/server/bare/plugins/llamacpp-completion/ops/kv-cache-state.js +2 -2
  96. package/dist/server/bare/plugins/llamacpp-completion/plugin.d.ts +6 -6
  97. package/dist/server/bare/plugins/llamacpp-completion/plugin.js +55 -36
  98. package/dist/server/bare/plugins/llamacpp-completion/transform.js +1 -7
  99. package/dist/server/bare/plugins/llamacpp-embedding/plugin.js +2 -3
  100. package/dist/server/bare/plugins/nmtcpp-translation/plugin.js +6 -5
  101. package/dist/server/bare/plugins/parakeet-transcription/plugin.js +27 -16
  102. package/dist/server/bare/plugins/tts-ggml/ops/parler-options.js +23 -3
  103. package/dist/server/bare/plugins/tts-ggml/plugin.d.ts +302 -4
  104. package/dist/server/bare/plugins/tts-ggml/plugin.js +131 -0
  105. package/dist/server/bare/plugins/whispercpp-transcription/plugin.js +48 -39
  106. package/dist/server/bare/registry/model-registry.d.ts +1 -0
  107. package/dist/server/bare/runtime/request-registry-singleton.js +29 -15
  108. package/dist/server/bare/runtime/request-registry.d.ts +27 -0
  109. package/dist/server/bare/runtime/request-registry.js +246 -76
  110. package/dist/server/bare/types/addon-responses.d.ts +4 -12
  111. package/dist/server/rpc/handlers/load-model/handler.js +2 -2
  112. package/dist/server/rpc/handlers/load-model/resolve-session.d.ts +1 -1
  113. package/dist/server/rpc/handlers/load-model/resolve-session.js +3 -3
  114. package/dist/server/rpc/handlers/load-model/resolve.d.ts +12 -2
  115. package/dist/server/rpc/handlers/load-model/resolve.js +90 -12
  116. package/dist/server/utils/audio/decoder.d.ts +37 -1
  117. package/dist/server/utils/audio/decoder.js +81 -51
  118. package/dist/server/utils/config-transform.d.ts +3 -0
  119. package/dist/server/utils/config-transform.js +6 -0
  120. package/dist/server/utils/index.d.ts +0 -1
  121. package/dist/server/utils/index.js +0 -1
  122. package/dist/server/utils/shard-utils.d.ts +1 -0
  123. package/dist/server/utils/shard-utils.js +14 -0
  124. package/dist/server/utils/tool-integration.d.ts +3 -10
  125. package/dist/server/utils/tool-integration.js +3 -12
  126. package/dist/utils/errors-server.d.ts +3 -0
  127. package/dist/utils/errors-server.js +5 -0
  128. package/package.json +12 -14
  129. package/dist/examples/llamacpp-dynamic-tools.d.ts +0 -2
  130. package/dist/examples/llamacpp-dynamic-tools.js +0 -152
  131. package/dist/models/update-models/codegen.d.ts +0 -3
  132. package/dist/models/update-models/codegen.js +0 -196
  133. package/dist/models/update-models/companions.d.ts +0 -30
  134. package/dist/models/update-models/companions.js +0 -296
  135. package/dist/models/update-models/history.d.ts +0 -24
  136. package/dist/models/update-models/history.js +0 -107
  137. package/dist/models/update-models/index.d.ts +0 -2
  138. package/dist/models/update-models/index.js +0 -123
  139. package/dist/models/update-models/naming.d.ts +0 -4
  140. package/dist/models/update-models/naming.js +0 -396
  141. package/dist/models/update-models/processing.d.ts +0 -8
  142. package/dist/models/update-models/processing.js +0 -65
  143. package/dist/models/update-models/registry.d.ts +0 -5
  144. package/dist/models/update-models/registry.js +0 -87
  145. package/dist/models/update-models/shards.d.ts +0 -4
  146. package/dist/models/update-models/shards.js +0 -57
  147. package/dist/models/update-models/types.d.ts +0 -88
  148. package/dist/models/update-models/types.js +0 -1
  149. package/dist/models/update-models/utils.d.ts +0 -3
  150. package/dist/models/update-models/utils.js +0 -21
  151. package/dist/server/bare/plugins/llamacpp-completion/ops/batch-cancelled.d.ts +0 -23
  152. package/dist/server/bare/plugins/llamacpp-completion/ops/batch-cancelled.js +0 -30
  153. package/dist/server/utils/expand-gguf-shards.d.ts +0 -3
  154. package/dist/server/utils/expand-gguf-shards.js +0 -22
@@ -1,24 +0,0 @@
1
- import type { CurrentModel, ProcessedModel } from './types.js';
2
- export declare function loadCurrentModels(outputFile: string): CurrentModel[];
3
- export declare function compareModels(remoteModels: ProcessedModel[], currentModels: CurrentModel[]): {
4
- added: ProcessedModel[];
5
- removed: CurrentModel[];
6
- };
7
- export declare function assignNames(models: ProcessedModel[]): (ProcessedModel & {
8
- name: string;
9
- })[];
10
- export declare function separateUpdates(added: (ProcessedModel & {
11
- name: string;
12
- })[], removed: CurrentModel[]): {
13
- added: (ProcessedModel & {
14
- name: string;
15
- })[];
16
- updated: (ProcessedModel & {
17
- name: string;
18
- })[];
19
- removed: CurrentModel[];
20
- };
21
- export declare function createHistoryFile(added: (ProcessedModel & {
22
- name: string;
23
- })[], removed: CurrentModel[], currentModels: CurrentModel[], historyDir: string): string | null;
24
- //# sourceMappingURL=history.d.ts.map
@@ -1,107 +0,0 @@
1
- import fs from 'fs';
2
- import { generateExportName } from './naming.js';
3
- import { getCommitHash } from './utils.js';
4
- export function loadCurrentModels(outputFile) {
5
- try {
6
- if (!fs.existsSync(outputFile)) {
7
- return [];
8
- }
9
- const content = fs.readFileSync(outputFile, 'utf-8');
10
- const modelsMatch = content.match(/export const models = \[([\s\S]*?)\] as const/);
11
- if (!modelsMatch?.[1]) {
12
- return [];
13
- }
14
- const modelsArrayContent = modelsMatch[1];
15
- const currentModels = [];
16
- const modelRegex = /\{[^}]+name:\s*(['"`])([^'"`]+)\1[^}]+(?:registryPath|hyperbeeKey):\s*(['"`])([^'"`]+)\3[^}]+\}/g;
17
- let match;
18
- while ((match = modelRegex.exec(modelsArrayContent)) !== null) {
19
- if (match[2] && match[4]) {
20
- currentModels.push({
21
- name: match[2],
22
- registryPath: match[4]
23
- });
24
- }
25
- }
26
- return currentModels;
27
- }
28
- catch (error) {
29
- const message = error instanceof Error ? error.message : 'Unknown error';
30
- console.warn('⚠️ Could not load current models:', message);
31
- return [];
32
- }
33
- }
34
- export function compareModels(remoteModels, currentModels) {
35
- const currentPaths = new Set(currentModels.map((m) => m.registryPath));
36
- const remotePaths = new Set(remoteModels.map((m) => m.registryPath));
37
- const added = remoteModels.filter((m) => !currentPaths.has(m.registryPath));
38
- const removed = currentModels.filter((m) => !remotePaths.has(m.registryPath));
39
- return { added, removed };
40
- }
41
- export function assignNames(models) {
42
- const usedNames = new Set();
43
- return models.map((m) => ({
44
- ...m,
45
- name: generateExportName({
46
- path: m.registryPath,
47
- engine: m.engine,
48
- name: m.modelName,
49
- quantization: m.quantization,
50
- params: m.params,
51
- tags: m.tags,
52
- usedNames
53
- })
54
- }));
55
- }
56
- export function separateUpdates(added, removed) {
57
- const removedNames = new Set(removed.map((m) => m.name));
58
- const addedNames = new Set(added.map((m) => m.name));
59
- const updatedNames = new Set([...addedNames].filter((name) => removedNames.has(name)));
60
- return {
61
- added: added.filter((m) => !updatedNames.has(m.name)),
62
- updated: added.filter((m) => updatedNames.has(m.name)),
63
- removed: removed.filter((m) => !updatedNames.has(m.name))
64
- };
65
- }
66
- export function createHistoryFile(added, removed, currentModels, historyDir) {
67
- if (added.length === 0 && removed.length === 0) {
68
- return null;
69
- }
70
- const { added: trulyAdded, updated, removed: trulyRemoved } = separateUpdates(added, removed);
71
- if (!fs.existsSync(historyDir)) {
72
- fs.mkdirSync(historyDir, { recursive: true });
73
- }
74
- const shortHash = getCommitHash(true);
75
- const fullHash = getCommitHash(false);
76
- const timestamp = new Date().toISOString();
77
- const filename = `${shortHash}.txt`;
78
- const filepath = `${historyDir}/${filename}`;
79
- let content = `commit=${fullHash}\n`;
80
- content += `timestamp=${timestamp}\n`;
81
- content += `previous_count=${currentModels.length}\n`;
82
- content += `new_count=${currentModels.length + trulyAdded.length - trulyRemoved.length}\n`;
83
- content += `\n`;
84
- if (trulyAdded.length > 0) {
85
- content += `[added]\n`;
86
- trulyAdded.forEach((m) => {
87
- content += `${m.name}\n`;
88
- });
89
- content += `\n`;
90
- }
91
- if (updated.length > 0) {
92
- content += `[updated]\n`;
93
- updated.forEach((m) => {
94
- content += `${m.name}\n`;
95
- });
96
- content += `\n`;
97
- }
98
- if (trulyRemoved.length > 0) {
99
- content += `[removed]\n`;
100
- trulyRemoved.forEach((m) => {
101
- content += `${m.name}\n`;
102
- });
103
- content += `\n`;
104
- }
105
- fs.writeFileSync(filepath, content);
106
- return filepath;
107
- }
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=index.d.ts.map
@@ -1,123 +0,0 @@
1
- import fs from 'fs';
2
- import { fileURLToPath } from 'url';
3
- import { execSync } from 'child_process';
4
- import { generateModelsFileContent } from './codegen.js';
5
- import { assignNames, compareModels, createHistoryFile, loadCurrentModels, separateUpdates } from './history.js';
6
- import { collectModels } from './registry.js';
7
- import { formatSize } from './utils.js';
8
- const OUTPUT_FILE = fileURLToPath(new URL('../registry/models.ts', import.meta.url));
9
- const HISTORY_DIR = fileURLToPath(new URL('../history', import.meta.url));
10
- async function checkOnly(nonBlocking = false, showDuplicates = false) {
11
- const timeoutMs = 30000;
12
- let timedOut = false;
13
- const timeoutPromise = new Promise((resolve) => {
14
- setTimeout(() => {
15
- timedOut = true;
16
- console.log('⏱️ Model check timed out');
17
- console.log(" Run 'bun check-models' manually to retry");
18
- resolve(null);
19
- }, timeoutMs);
20
- });
21
- try {
22
- const result = await Promise.race([
23
- (async () => {
24
- const remoteModels = await collectModels({ showDuplicates });
25
- const currentModels = loadCurrentModels(OUTPUT_FILE);
26
- remoteModels.sort((a, b) => a.addon.localeCompare(b.addon) || a.registryPath.localeCompare(b.registryPath));
27
- return { remoteModels, currentModels };
28
- })(),
29
- timeoutPromise
30
- ]);
31
- if (timedOut || !result) {
32
- process.exit(nonBlocking ? 0 : 1);
33
- }
34
- const { remoteModels, currentModels } = result;
35
- const { added: rawAdded, removed: rawRemoved } = compareModels(remoteModels, currentModels);
36
- if (rawAdded.length === 0 && rawRemoved.length === 0) {
37
- console.log(`✅ Models are up to date (${remoteModels.length} models)`);
38
- process.exit(0);
39
- }
40
- const addedWithNames = assignNames(rawAdded);
41
- const { added, updated, removed } = separateUpdates(addedWithNames, rawRemoved);
42
- console.log('');
43
- console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
44
- if (added.length > 0) {
45
- console.log(`✨ ${added.length} new model${added.length === 1 ? '' : 's'} available:`);
46
- added.slice(0, 10).forEach((m) => {
47
- console.log(` + ${m.name} (${m.addon}, ${formatSize(m.expectedSize)})`);
48
- });
49
- if (added.length > 10) {
50
- console.log(` ... and ${added.length - 10} more`);
51
- }
52
- }
53
- if (updated.length > 0) {
54
- console.log(`\n🔄 ${updated.length} model${updated.length === 1 ? '' : 's'} updated:`);
55
- updated.slice(0, 10).forEach((m) => {
56
- console.log(` ~ ${m.name} (${m.addon}, ${formatSize(m.expectedSize)})`);
57
- });
58
- if (updated.length > 10) {
59
- console.log(` ... and ${updated.length - 10} more`);
60
- }
61
- }
62
- if (removed.length > 0) {
63
- console.log(`\n⚠️ ${removed.length} model${removed.length === 1 ? '' : 's'} removed:`);
64
- removed.slice(0, 5).forEach((m) => {
65
- console.log(` - ${m.name}`);
66
- });
67
- if (removed.length > 5) {
68
- console.log(` ... and ${removed.length - 5} more`);
69
- }
70
- }
71
- console.log('');
72
- console.log(`💡 Run 'bun update-models' to sync changes`);
73
- console.log('');
74
- if (nonBlocking) {
75
- console.log('💡 Commit will proceed - update models when ready');
76
- }
77
- console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
78
- console.log('');
79
- process.exit(nonBlocking ? 0 : 1);
80
- }
81
- catch (error) {
82
- const message = error instanceof Error ? error.message : 'Unknown error';
83
- console.error('❌ Model check failed:', message);
84
- process.exit(nonBlocking ? 0 : 1);
85
- }
86
- }
87
- async function updateModels(showDuplicates = false, noDedup = false) {
88
- console.log('🔄 Fetching models from QVAC Registry...\n');
89
- const currentModels = loadCurrentModels(OUTPUT_FILE);
90
- const models = await collectModels({ showDuplicates, noDedup });
91
- const { added, removed } = compareModels(models, currentModels);
92
- models.sort((a, b) => a.addon.localeCompare(b.addon) || a.registryPath.localeCompare(b.registryPath));
93
- fs.writeFileSync(OUTPUT_FILE, generateModelsFileContent(models));
94
- try {
95
- execSync(`npx prettier --write "${OUTPUT_FILE}"`, { stdio: 'pipe' });
96
- }
97
- catch {
98
- // prettier not available, skip formatting
99
- }
100
- console.log(`✅ Generated ${models.length} models → ${OUTPUT_FILE}`);
101
- const addedWithNames = assignNames(added);
102
- if (added.length > 0 || removed.length > 0) {
103
- const historyFile = createHistoryFile(addedWithNames, removed, currentModels, HISTORY_DIR);
104
- if (historyFile) {
105
- const { added: trulyAdded, updated, removed: trulyRemoved } = separateUpdates(addedWithNames, removed);
106
- console.log(`📜 Created history file → ${historyFile}`);
107
- console.log(` Added: ${trulyAdded.length}, Updated: ${updated.length}, Removed: ${trulyRemoved.length}`);
108
- }
109
- }
110
- }
111
- async function main() {
112
- const CHECK_ONLY = process.argv.includes('--check');
113
- const NON_BLOCKING = process.argv.includes('--non-blocking');
114
- const SHOW_DUPLICATES = process.argv.includes('--show-duplicates');
115
- const NO_DEDUP = process.argv.includes('--no-dedup');
116
- if (CHECK_ONLY) {
117
- await checkOnly(NON_BLOCKING, SHOW_DUPLICATES);
118
- }
119
- else {
120
- await updateModels(SHOW_DUPLICATES, NO_DEDUP);
121
- }
122
- }
123
- main().catch(console.error);
@@ -1,4 +0,0 @@
1
- import type { ExportNameInput } from './types.js';
2
- export declare function cleanPart(p: string): string;
3
- export declare function generateExportName({ path: registryPath, engine, name: modelName, quantization, params, tags, usedNames }: ExportNameInput): string;
4
- //# sourceMappingURL=naming.d.ts.map
@@ -1,396 +0,0 @@
1
- import { getAddonFromEngine } from '../../schemas/engine-addon-map.js';
2
- import { detectShardedModel } from './shards.js';
3
- // Normalizes a name part to a valid JS export name fragment.
4
- // Strips ggml/gguf prefixes, shortens "instruct" to "inst",
5
- // and uppercases with underscore separators.
6
- export function cleanPart(p) {
7
- if (!p)
8
- return '';
9
- return p
10
- .replace(/ggml-?/gi, '')
11
- .replace(/gguf-?/gi, '')
12
- .replace(/instruct/gi, 'inst')
13
- .replace(/^-+|-+$/g, '')
14
- .toUpperCase()
15
- .replace(/[^A-Z0-9]+/g, '_');
16
- }
17
- // Generates a unique export constant name for a model based on its
18
- // registry metadata, engine type, tags, and filename.
19
- export function generateExportName({ path: registryPath, engine, name: modelName, quantization, params, tags, usedNames }) {
20
- let addon = getAddonFromEngine(engine);
21
- // Override addon classification when tags clearly indicate a different type.
22
- // e.g. SmolVLM2 f16 uses translation-llamacpp engine (→nmt) but is actually a multimodal LLM.
23
- if (addon === 'nmt' && tags.some((t) => t === 'generation' || t === 'multimodal')) {
24
- addon = 'llm';
25
- }
26
- let exportName = '';
27
- const filename = decodeURIComponent(registryPath.split('/').pop() || registryPath);
28
- const lowerFilename = filename.toLowerCase();
29
- const lowerPath = registryPath.toLowerCase();
30
- // Extract structured info from tags array.
31
- // Tags typically contain: [function, type, modelName, langPair/other]
32
- const tagType = tags[1] || '';
33
- const tagName = tags[2] || '';
34
- const tagExtra = tags[3] || '';
35
- exportName = generateBaseName({
36
- addon,
37
- engine,
38
- filename,
39
- lowerFilename,
40
- lowerPath,
41
- modelName,
42
- quantization,
43
- params,
44
- tagType,
45
- tagName,
46
- tagExtra,
47
- tags
48
- });
49
- exportName = exportName.replace(/^_+|_+$/g, '').replace(/_+/g, '_');
50
- // Add suffix for metadata files (tensors.txt are shard metadata, not actual models)
51
- if (lowerFilename.endsWith('.tensors.txt')) {
52
- exportName = `${exportName}_TENSORS`;
53
- }
54
- // Add SHARD suffix for sharded models
55
- if (detectShardedModel(filename).isSharded) {
56
- exportName = `${exportName}_SHARD`;
57
- }
58
- return resolveCollision(exportName, quantization, usedNames);
59
- }
60
- // Resolves name collisions by appending quantization or a sequential counter.
61
- function resolveCollision(exportName, quantization, usedNames) {
62
- let finalName = exportName || 'UNKNOWN_MODEL';
63
- if (usedNames.has(finalName) && quantization) {
64
- const cleanedQuant = cleanPart(quantization);
65
- // Only append quantization if it's not already at the end of the name
66
- if (cleanedQuant && !exportName.endsWith(cleanedQuant)) {
67
- const withQuant = `${exportName}_${cleanedQuant}`;
68
- if (!usedNames.has(withQuant)) {
69
- finalName = withQuant;
70
- }
71
- }
72
- }
73
- let counter = 1;
74
- while (usedNames.has(finalName)) {
75
- finalName = `${exportName}_${counter++}`;
76
- }
77
- usedNames.add(finalName);
78
- return finalName;
79
- }
80
- function generateBaseName(input) {
81
- const { addon, lowerFilename } = input;
82
- // Detect VAD Silero before whisper (same engine, different model type)
83
- if (lowerFilename.includes('silero')) {
84
- return generateVadSileroName(input);
85
- }
86
- switch (addon) {
87
- case 'whisper':
88
- return generateWhisperName(input);
89
- case 'bci':
90
- return generateBciName(input);
91
- case 'vad':
92
- return generateVadName(input);
93
- case 'nmt':
94
- return generateNmtName(input);
95
- case 'llm':
96
- return generateLlmName(input);
97
- case 'embeddings':
98
- return generateEmbeddingsName(input);
99
- case 'tts':
100
- return generateTtsName(input);
101
- case 'ocr':
102
- return generateOcrName(input);
103
- case 'parakeet':
104
- return generateParakeetName(input);
105
- case 'diffusion':
106
- return generateDiffusionName(input);
107
- case 'audiogen':
108
- return generateAudioGenName(input);
109
- default:
110
- return cleanPart(input.filename.replace(/\.\w+$/, ''));
111
- }
112
- }
113
- function generateAudioGenName({ filename }) {
114
- const modelName = cleanPart(filename.replace(/\.\w+$/, ''));
115
- return `AUDIOGEN_${modelName}`;
116
- }
117
- function generateVadSileroName({ filename }) {
118
- const versionMatch = filename.match(/v(\d+\.\d+\.\d+)/i);
119
- const version = versionMatch ? versionMatch[1] : '';
120
- const nameParts = ['SILERO', version].filter((p) => p && p !== '');
121
- return `VAD_${nameParts.map(cleanPart).join('_')}`;
122
- }
123
- function generateWhisperName({ filename, lowerFilename, quantization }) {
124
- // Extract language from filename prefix (e.g. "de-tiny-ggml-model-f16.bin")
125
- const langPrefixMatch = filename.match(/^([a-z]{2})-/i);
126
- // Detect English-only models from ".en" or ".en-" in filename
127
- const isEnglishOnly = /\.en[-.]/.test(lowerFilename) || lowerFilename.endsWith('.en.bin');
128
- // Extract size from filename
129
- const sizeMatch = filename.match(/\b(tiny|base|small|medium|large(?:-v[0-9]+)?(?:-turbo)?)\b/i);
130
- const modelSize = sizeMatch ? sizeMatch[1] : '';
131
- // Extract quant from filename (f16, q8_0, etc.)
132
- const quantMatch = filename.match(/[-_](f16|q[0-9]+[_][0-9]+|q8)\b/i);
133
- const fileQuant = quantMatch ? quantMatch[1] : quantization;
134
- const nameParts = [];
135
- if (langPrefixMatch) {
136
- const langCode = langPrefixMatch[1].toLowerCase();
137
- const langMap = {
138
- de: 'GERMAN',
139
- es: 'SPANISH',
140
- fr: 'FRENCH',
141
- it: 'ITALIAN',
142
- ja: 'JAPANESE',
143
- pt: 'PORTUGUESE',
144
- ru: 'RUSSIAN',
145
- nb: 'NORWEGIAN',
146
- en: 'ENGLISH'
147
- };
148
- const langName = langMap[langCode] || langCode.toUpperCase();
149
- nameParts.push(langName);
150
- }
151
- else if (isEnglishOnly) {
152
- nameParts.push('EN');
153
- }
154
- if (modelSize)
155
- nameParts.push(modelSize);
156
- if (fileQuant)
157
- nameParts.push(fileQuant);
158
- return `WHISPER_${nameParts.map(cleanPart).join('_')}`;
159
- }
160
- function generateBciName({ filename, quantization }) {
161
- // Strip the engine/format prefix and a leading "BCI" token so role names
162
- // like "bci-embedder.bin" / "ggml-bci-windowed.bin" become EMBEDDER /
163
- // WINDOWED before we re-prefix with BCI_.
164
- const role = cleanPart(filename.replace(/\.\w+$/, '')).replace(/^BCI_?/, '');
165
- const nameParts = [role, quantization].filter((p) => p && p !== '');
166
- return `BCI_${nameParts.map(cleanPart).join('_')}`;
167
- }
168
- function generateVadName({ filename, tagType, tagName }) {
169
- const versionMatch = filename.match(/v(\d+\.\d+\.\d+)/i);
170
- const version = versionMatch ? versionMatch[1] : '';
171
- const typeName = tagType || tagName || 'SILERO';
172
- const nameParts = [typeName, version].filter((p) => p && p !== '');
173
- return `VAD_${nameParts.map(cleanPart).join('_')}`;
174
- }
175
- function generateNmtName(input) {
176
- const { lowerPath, lowerFilename } = input;
177
- if (lowerPath.includes('salamandra') || lowerFilename.includes('salamandra')) {
178
- return generateNmtSalamandraName(input);
179
- }
180
- if (lowerPath.includes('indictrans') || lowerFilename.includes('indictrans')) {
181
- return generateNmtIndictransName(input);
182
- }
183
- if (lowerPath.includes('bergamot') || lowerFilename.includes('bergamot')) {
184
- return generateNmtBergamotName(input);
185
- }
186
- const nameParts = [input.modelName, input.quantization].filter((p) => p && p !== '');
187
- return `NMT_${nameParts.map(cleanPart).join('_')}`;
188
- }
189
- function generateNmtSalamandraName({ filename }) {
190
- const base = filename.replace(/\.\w+$/, '').replace(/-\d{5}-of-\d{5}/, '');
191
- return cleanPart(base);
192
- }
193
- function generateNmtIndictransName({ filename, quantization }) {
194
- const langMatch = filename.match(/(en-indic|indic-en|indic-indic)/i);
195
- const langDir = langMatch ? langMatch[1] : '';
196
- const langMap = {
197
- 'en-indic': 'EN_HI',
198
- 'indic-en': 'HI_EN',
199
- 'indic-indic': 'HI_HI'
200
- };
201
- const langPair = langMap[langDir.toLowerCase()] || cleanPart(langDir);
202
- const sizeMatch = filename.match(/(\d+[MB])/i);
203
- const size = sizeMatch ? sizeMatch[1] : '';
204
- const nameParts = [langPair, 'INDIC', size, quantization].filter((p) => p && p !== '');
205
- return `MARIAN_${nameParts.map(cleanPart).join('_')}`;
206
- }
207
- function generateNmtBergamotName({ filename }) {
208
- const langMatch = filename.match(/[.]([a-z]{2,4})[.]/i);
209
- let langPair = '';
210
- if (langMatch) {
211
- const code = langMatch[1];
212
- if (code.length === 4) {
213
- langPair = `${code.slice(0, 2).toUpperCase()}_${code.slice(2).toUpperCase()}`;
214
- }
215
- else {
216
- langPair = code.toUpperCase();
217
- }
218
- }
219
- let suffix = '';
220
- if (filename.startsWith('model.')) {
221
- suffix = '';
222
- }
223
- else if (filename.match(/^vocab\./)) {
224
- suffix = '_VOCAB';
225
- }
226
- else if (filename.match(/^srcvocab\./)) {
227
- suffix = '_SRCVOCAB';
228
- }
229
- else if (filename.match(/^trgvocab\./)) {
230
- suffix = '_TRGVOCAB';
231
- }
232
- else if (filename.startsWith('lex.')) {
233
- suffix = '_LEX';
234
- }
235
- else if (filename === 'metadata.json') {
236
- suffix = '_METADATA';
237
- }
238
- return `BERGAMOT_${langPair}${suffix}`;
239
- }
240
- function generateLlmName({ filename, tagType, tagName, modelName, quantization, params }) {
241
- const type = tagType || '';
242
- const name = tagName || modelName || '';
243
- const isMMProj = filename.includes('mmproj');
244
- // Try to extract model family from filename to recover version info
245
- // that tags may omit (e.g., tag "qwen" but filename "Qwen3-1.7B-...")
246
- let familyName = name;
247
- if (params) {
248
- const parseFn = filename
249
- .replace(/^mmproj[-_]/i, '')
250
- .replace(/\.tensors\.txt$/, '')
251
- .replace(/\.\w+$/, '')
252
- .replace(/-\d{5}-of-\d{5}/, '');
253
- const paramsEsc = params.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
254
- const familyMatch = parseFn.match(new RegExp(`^(.+?)[-_]${paramsEsc}`, 'i'));
255
- if (familyMatch?.[1]) {
256
- const candidate = familyMatch[1];
257
- // Use filename family only if it extends the tag name
258
- // Strip common engine/format suffixes from tag before comparing
259
- const tagCore = name.replace(/[-_](ggml|cpp|onnx|llamacpp|metal)$/i, '');
260
- const cleanedCandidate = candidate.replace(/[-_.]/g, '').toLowerCase();
261
- const cleanedTagCore = tagCore.replace(/[-_.]/g, '').toLowerCase();
262
- if (cleanedCandidate.startsWith(cleanedTagCore) &&
263
- cleanedCandidate.length >= cleanedTagCore.length) {
264
- familyName = candidate;
265
- }
266
- }
267
- }
268
- const familyTokens = cleanPart(familyName).split('_');
269
- // Avoid duplicating params when the registry model name already ends with
270
- // the same size (for example, Qwen3-4B + 4B).
271
- const paramsAlreadyIncluded = params !== '' && familyTokens[familyTokens.length - 1] === cleanPart(params);
272
- const nameParts = [familyName, paramsAlreadyIncluded ? '' : params, type, quantization].filter((p) => p && p !== '');
273
- let exportName = nameParts.map(cleanPart).join('_');
274
- if (isMMProj) {
275
- exportName = 'MMPROJ_' + exportName;
276
- }
277
- return exportName;
278
- }
279
- function generateEmbeddingsName({ tagName, modelName, params, quantization }) {
280
- const name = tagName || modelName || '';
281
- const nameParts = [name, params, quantization].filter((p) => p && p !== '');
282
- return nameParts.map(cleanPart).join('_');
283
- }
284
- function generateTtsName({ filename, tagName, modelName, tagExtra, tagType, quantization }) {
285
- const name = tagName || modelName || '';
286
- const language = tagExtra || '';
287
- const type = tagType || '';
288
- const nameParts = [name, language, type, quantization].filter((p) => p && p !== '');
289
- let exportName = `TTS_${nameParts.map(cleanPart).join('_')}`;
290
- if (filename.endsWith('.onnx.json') || filename.includes('config.json')) {
291
- exportName = exportName + '_CONFIG';
292
- }
293
- if (filename.endsWith('.onnx_data')) {
294
- exportName = exportName + '_DATA';
295
- }
296
- return exportName;
297
- }
298
- function generateOcrName({ filename, tagName, modelName, tagExtra }) {
299
- const name = tagName || modelName || '';
300
- const language = tagExtra || '';
301
- let fileType = '';
302
- if (filename.includes('detector')) {
303
- fileType = 'DETECTOR';
304
- }
305
- else if (filename.includes('recognizer')) {
306
- fileType = 'RECOGNIZER';
307
- }
308
- const nameParts = [name, language, fileType].filter((p) => p && p !== '');
309
- return `OCR_${nameParts.map(cleanPart).join('_')}`;
310
- }
311
- function generateDiffusionName({ filename, modelName, quantization, params, tags }) {
312
- // VAE / auxiliary models (tagged "vae" instead of "generation")
313
- if (tags.includes('vae')) {
314
- const name = modelName || 'SD';
315
- return `${cleanPart(name)}_VAE`;
316
- }
317
- // Extract family name from filename
318
- let family = filename
319
- .replace(/\.\w+$/, '')
320
- .replace(/^stable-diffusion-xl/i, 'SDXL')
321
- .replace(/^stable-diffusion/i, 'SD');
322
- // Strip trailing params (e.g. "-4b") and quant (e.g. "-Q8_0") from family
323
- // to avoid duplication since they're appended separately
324
- if (params) {
325
- const paramsEsc = params.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
326
- family = family.replace(new RegExp(`[-_]${paramsEsc}[-_].*$`, 'i'), '');
327
- }
328
- if (quantization) {
329
- const quantEsc = quantization.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
330
- family = family.replace(new RegExp(`[-_]${quantEsc}$`, 'i'), '');
331
- }
332
- const nameParts = [family, params, quantization].filter((p) => p && p !== '');
333
- return nameParts.map(cleanPart).join('_');
334
- }
335
- function generateParakeetName({ filename, lowerPath, quantization }) {
336
- const lower = filename.toLowerCase();
337
- let variant = '';
338
- if (lower.includes('sortformer') || lower.includes('diar_streaming')) {
339
- variant = 'SORTFORMER';
340
- }
341
- else if (lower.includes('ctc') || lowerPath.includes('parakeet-ctc')) {
342
- variant = 'CTC';
343
- }
344
- else if (lower.includes('eou') || lowerPath.includes('parakeet-rs')) {
345
- variant = 'EOU';
346
- }
347
- else if (lower.includes('tdt') || lowerPath.includes('parakeet-tdt')) {
348
- variant = 'TDT';
349
- }
350
- if (lower.endsWith('.gguf')) {
351
- const paramsMatch = filename.match(/(?:^|[-_])(\d+(?:\.\d+)?[mb])(?=[-_.])/i);
352
- const versionMatch = filename.match(/[-_]v(\d+(?:\.\d+)?)/i);
353
- const speakerMatch = filename.match(/(\d+spk)/i);
354
- const paramsHint = paramsMatch ? paramsMatch[1] : '';
355
- const versionHint = versionMatch ? `V${versionMatch[1]}` : '';
356
- const speakerHint = speakerMatch ? speakerMatch[1] : '';
357
- const nameParts = [variant, paramsHint, speakerHint, versionHint, quantization].filter((p) => p && p !== '');
358
- return `PARAKEET_${nameParts.map(cleanPart).join('_')}`;
359
- }
360
- let fileRole = '';
361
- if (lower.includes('encoder') && (lower.endsWith('.data') || lower.endsWith('.onnx.data'))) {
362
- fileRole = 'ENCODER_DATA';
363
- }
364
- else if (lower.includes('encoder')) {
365
- fileRole = 'ENCODER';
366
- }
367
- else if (lower.includes('decoder')) {
368
- fileRole = 'DECODER';
369
- }
370
- else if (lower.includes('vocab')) {
371
- fileRole = 'VOCAB';
372
- }
373
- else if (lower.includes('tokenizer')) {
374
- fileRole = 'TOKENIZER';
375
- }
376
- else if (lower.includes('preprocessor') || lower.includes('nemo')) {
377
- fileRole = 'PREPROCESSOR';
378
- }
379
- else if (lower === 'config.json') {
380
- fileRole = 'CONFIG';
381
- }
382
- else if (lower.endsWith('.onnx.data') || lower.endsWith('.onnx_data')) {
383
- fileRole = 'DATA';
384
- }
385
- else if (lower.includes('sortformer')) {
386
- fileRole = '';
387
- }
388
- else if (lower.endsWith('.onnx') || lower.endsWith('.int8.onnx')) {
389
- fileRole = '';
390
- }
391
- else {
392
- fileRole = cleanPart(filename.replace(/\.\w+$/, ''));
393
- }
394
- const nameParts = [variant, fileRole, quantization].filter((p) => p && p !== '');
395
- return `PARAKEET_${nameParts.map(cleanPart).join('_')}`;
396
- }
@@ -1,8 +0,0 @@
1
- import type { QVACModelEntry } from '@qvac/registry-client';
2
- import type { ProcessedModel } from './types.js';
3
- export declare function toHexString(value: Buffer | string | {
4
- data: number[];
5
- } | undefined): string;
6
- export declare function extractModelName(registryPath: string): string;
7
- export declare function processRegistryModel(model: QVACModelEntry): ProcessedModel | null;
8
- //# sourceMappingURL=processing.d.ts.map