multimodel-dev-os 1.1.0 → 2.0.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 (59) hide show
  1. package/.ai/adapters/custom-adapter.example.yaml +9 -0
  2. package/.ai/adapters/registry.yaml +56 -0
  3. package/.ai/models/README.md +14 -0
  4. package/.ai/models/local-models.yaml +20 -0
  5. package/.ai/models/providers.yaml +29 -0
  6. package/.ai/models/registry.yaml +73 -0
  7. package/.ai/models/routing-presets.yaml +23 -0
  8. package/.ai/skills/custom-skill.example.md +15 -0
  9. package/.ai/templates/custom-template.example.yaml +19 -0
  10. package/.ai/templates/registry.yaml +522 -0
  11. package/README.md +30 -18
  12. package/bin/multimodel-dev-os.js +810 -91
  13. package/docs/.vitepress/config.js +36 -1
  14. package/docs/adapter-authoring.md +46 -0
  15. package/docs/agent-compatibility.md +51 -0
  16. package/docs/cli-roadmap.md +15 -18
  17. package/docs/final-launch.md +5 -4
  18. package/docs/local-models.md +48 -0
  19. package/docs/mobile-android.md +75 -0
  20. package/docs/model-compatibility.md +65 -0
  21. package/docs/model-routing.md +45 -0
  22. package/docs/npm-publishing.md +27 -0
  23. package/docs/package-safety.md +29 -0
  24. package/docs/provider-strategy.md +44 -0
  25. package/docs/public/llms-full.txt +82 -73
  26. package/docs/public/llms.txt +36 -34
  27. package/docs/quickstart.md +7 -6
  28. package/docs/registry-contribution.md +20 -0
  29. package/docs/release-policy.md +26 -0
  30. package/docs/skill-authoring.md +56 -0
  31. package/docs/template-authoring.md +65 -0
  32. package/docs/token-optimization.md +27 -0
  33. package/docs/v2-migration.md +31 -0
  34. package/docs/v2-release-checklist.md +30 -0
  35. package/docs/v2-roadmap.md +95 -0
  36. package/examples/expo-react-native-android/.ai/config.yaml +22 -0
  37. package/examples/expo-react-native-android/.ai/context/architecture.md +18 -0
  38. package/examples/expo-react-native-android/.ai/context/context-budget.md +4 -0
  39. package/examples/expo-react-native-android/.ai/context/model-map.md +6 -0
  40. package/examples/expo-react-native-android/.ai/context/project-brief.md +9 -0
  41. package/examples/expo-react-native-android/.ai/session-logs/.gitkeep +1 -0
  42. package/examples/expo-react-native-android/.ai/skills/expo-android-build.md +11 -0
  43. package/examples/expo-react-native-android/AGENTS.md +20 -0
  44. package/examples/expo-react-native-android/MEMORY.md +13 -0
  45. package/examples/expo-react-native-android/README.md +101 -0
  46. package/examples/expo-react-native-android/RUNBOOK.md +36 -0
  47. package/examples/expo-react-native-android/TASKS.md +14 -0
  48. package/examples/expo-react-native-android/app.config.ts +40 -0
  49. package/examples/expo-react-native-android/app.json +34 -0
  50. package/examples/expo-react-native-android/eas.json +26 -0
  51. package/examples/expo-react-native-android/jest.config.js +11 -0
  52. package/examples/expo-react-native-android/src/app/_layout.tsx +89 -0
  53. package/examples/expo-react-native-android/src/lib/secure-storage.ts +63 -0
  54. package/examples/expo-react-native-android/src/services/api-client.ts +106 -0
  55. package/package.json +3 -2
  56. package/scripts/install.ps1 +230 -230
  57. package/scripts/install.sh +1 -1
  58. package/scripts/prepublish-guard.js +43 -0
  59. package/scripts/verify.js +178 -1
package/scripts/verify.js CHANGED
@@ -6,7 +6,7 @@
6
6
  * Runs on Windows, macOS, and Linux with zero external dependencies.
7
7
  */
8
8
 
9
- import { existsSync, readFileSync, statSync } from 'fs';
9
+ import { existsSync, readFileSync, statSync, readdirSync } from 'fs';
10
10
  import { join, resolve, dirname } from 'path';
11
11
  import { fileURLToPath } from 'url';
12
12
  import { execSync } from 'child_process';
@@ -67,6 +67,7 @@ checkFile('RUNBOOK.md');
67
67
  checkFile('README.md');
68
68
  checkFile('LICENSE');
69
69
  checkFile('CONTRIBUTING.md');
70
+ checkFile('CONTRIBUTORS.md');
70
71
  checkFile('CODE_OF_CONDUCT.md');
71
72
  checkFile('SECURITY.md');
72
73
  checkFile('CHANGELOG.md');
@@ -166,6 +167,15 @@ checkFile('examples/ecommerce-store/AGENTS.md');
166
167
  checkFile('examples/ecommerce-store/MEMORY.md');
167
168
  checkFile('examples/seo-landing-page/AGENTS.md');
168
169
  checkFile('examples/seo-landing-page/MEMORY.md');
170
+ checkFile('examples/expo-react-native-android/AGENTS.md');
171
+ checkFile('examples/expo-react-native-android/MEMORY.md');
172
+ checkFile('examples/expo-react-native-android/app.json');
173
+ checkFile('examples/expo-react-native-android/eas.json');
174
+ checkFile('examples/expo-react-native-android/app.config.ts');
175
+ checkFile('examples/expo-react-native-android/jest.config.js');
176
+ checkFile('examples/expo-react-native-android/src/app/_layout.tsx');
177
+ checkFile('examples/expo-react-native-android/src/lib/secure-storage.ts');
178
+ checkFile('examples/expo-react-native-android/src/services/api-client.ts');
169
179
  checkFile('examples/general-app/AGENTS.md');
170
180
  checkFile('examples/general-app/MEMORY.md');
171
181
 
@@ -175,6 +185,7 @@ checkFile('scripts/install.sh');
175
185
  checkFile('scripts/install.ps1');
176
186
  checkFile('scripts/verify.sh');
177
187
  checkFile('scripts/pack-template.sh');
188
+ checkFile('scripts/prepublish-guard.js');
178
189
  checkFile('bin/multimodel-dev-os.js');
179
190
 
180
191
  // --- GitHub Integration ---
@@ -204,6 +215,34 @@ checkFile('docs/release-policy.md');
204
215
  checkFile('docs/support-policy.md');
205
216
  checkFile('docs/final-launch.md');
206
217
  checkFile('docs/v1-checklist.md');
218
+ checkFile('docs/model-compatibility.md');
219
+ checkFile('docs/model-routing.md');
220
+ checkFile('docs/local-models.md');
221
+ checkFile('docs/provider-strategy.md');
222
+ checkFile('docs/agent-compatibility.md');
223
+ checkFile('docs/adapter-authoring.md');
224
+ checkFile('docs/token-optimization.md');
225
+ checkFile('docs/mobile-android.md');
226
+ checkFile('docs/v2-roadmap.md');
227
+ checkFile('docs/template-authoring.md');
228
+ checkFile('docs/skill-authoring.md');
229
+ checkFile('docs/registry-contribution.md');
230
+ checkFile('docs/v2-migration.md');
231
+ checkFile('docs/v2-release-checklist.md');
232
+ checkFile('docs/package-safety.md');
233
+
234
+ // --- Model & Adapter Registries ---
235
+ console.log('\nModel & Adapter Registries:');
236
+ checkFile('.ai/models/registry.yaml');
237
+ checkFile('.ai/models/providers.yaml');
238
+ checkFile('.ai/models/routing-presets.yaml');
239
+ checkFile('.ai/models/local-models.yaml');
240
+ checkFile('.ai/models/README.md');
241
+ checkFile('.ai/adapters/registry.yaml');
242
+ checkFile('.ai/templates/registry.yaml');
243
+ checkFile('.ai/templates/custom-template.example.yaml');
244
+ checkFile('.ai/adapters/custom-adapter.example.yaml');
245
+ checkFile('.ai/skills/custom-skill.example.md');
207
246
 
208
247
  // --- JSON Schemas ---
209
248
  console.log('\nJSON Schemas:');
@@ -215,7 +254,10 @@ checkFile('.ai/schema/adapter.schema.json');
215
254
  console.log('\nTest Manuals:');
216
255
  checkFile('tests/README.md');
217
256
  checkFile('tests/fixtures/README.md');
257
+ checkFile('tests/fixtures/custom-template-example/README.md');
258
+ checkFile('tests/fixtures/registry-overrides/README.md');
218
259
  checkFile('tests/smoke/README.md');
260
+ checkFile('tests/smoke/cli-smoke.md');
219
261
 
220
262
  // --- Visual & AI Discovery Assets ---
221
263
  console.log('\nVisual & AI Discovery Assets:');
@@ -231,6 +273,111 @@ checkFile('docs/public/assets/social-preview.svg');
231
273
  checkFile('docs/public/assets/terminal-demo.svg');
232
274
  checkFile('docs/public/assets/architecture-preview.svg');
233
275
 
276
+ // --- YAML Parser Helper ---
277
+ function parseYaml(content) {
278
+ try {
279
+ const root = {};
280
+ const stack = [{ obj: root, indent: -1, key: null, isArray: false }];
281
+ const lines = content.split(/\r?\n/);
282
+ for (let line of lines) {
283
+ const commentIdx = line.indexOf('#');
284
+ if (commentIdx !== -1) {
285
+ line = line.substring(0, commentIdx);
286
+ }
287
+ line = line.trimEnd();
288
+ if (!line.trim()) continue;
289
+ const indent = line.match(/^ */)[0].length;
290
+ let trimmed = line.trim();
291
+ while (stack.length > 1 && indent <= stack[stack.length - 1].indent) {
292
+ stack.pop();
293
+ }
294
+ const parent = stack[stack.length - 1];
295
+ if (trimmed.startsWith('-')) {
296
+ trimmed = trimmed.substring(1).trim();
297
+ if (!Array.isArray(parent.obj)) {
298
+ const grandparent = stack[stack.length - 2];
299
+ if (grandparent) {
300
+ grandparent.obj[parent.key] = [];
301
+ parent.obj = grandparent.obj[parent.key];
302
+ }
303
+ }
304
+ const colonIdx = trimmed.indexOf(':');
305
+ if (colonIdx === -1) {
306
+ parent.obj.push(trimmed);
307
+ } else {
308
+ const key = trimmed.substring(0, colonIdx).trim();
309
+ let val = trimmed.substring(colonIdx + 1).trim();
310
+ if ((val.startsWith('"') && val.endsWith('"')) || (val.startsWith("'") && val.endsWith("'"))) {
311
+ val = val.substring(1, val.length - 1);
312
+ }
313
+ if (val === 'true') val = true;
314
+ else if (val === 'false') val = false;
315
+ else if (val === 'null') val = null;
316
+ else if (/^\d+$/.test(val)) val = parseInt(val, 10);
317
+ const newObj = { [key]: val };
318
+ parent.obj.push(newObj);
319
+ stack.push({ obj: newObj, indent: indent, key: key, isArray: false });
320
+ }
321
+ } else {
322
+ const colonIdx = trimmed.indexOf(':');
323
+ if (colonIdx === -1) continue;
324
+ const key = trimmed.substring(0, colonIdx).trim();
325
+ let val = trimmed.substring(colonIdx + 1).trim();
326
+ if ((val.startsWith('"') && val.endsWith('"')) || (val.startsWith("'") && val.endsWith("'"))) {
327
+ val = val.substring(1, val.length - 1);
328
+ }
329
+ if (val === 'true') val = true;
330
+ else if (val === 'false') val = false;
331
+ else if (val === 'null') val = null;
332
+ else if (/^\d+$/.test(val)) val = parseInt(val, 10);
333
+ if (val === '') {
334
+ parent.obj[key] = {};
335
+ stack.push({ obj: parent.obj[key], indent: indent, key: key, isArray: false });
336
+ } else {
337
+ parent.obj[key] = val;
338
+ }
339
+ }
340
+ }
341
+ return root;
342
+ } catch (e) {
343
+ return null;
344
+ }
345
+ }
346
+
347
+ function verifyRegistryParsed(relPath, requiredRootKey) {
348
+ const fullPath = join(projectRoot, relPath);
349
+ if (!existsSync(fullPath)) {
350
+ console.error(` ${RED}✗${NC} ${relPath} (missing for parsing)`);
351
+ fail++;
352
+ return;
353
+ }
354
+ try {
355
+ const data = parseYaml(readFileSync(fullPath, 'utf8'));
356
+ if (!data || typeof data !== 'object') {
357
+ console.error(` ${RED}✗${NC} ${relPath} (YAML parsing returned invalid object)`);
358
+ fail++;
359
+ } else if (requiredRootKey && !data[requiredRootKey]) {
360
+ console.error(` ${RED}✗${NC} ${relPath} (missing root key: "${requiredRootKey}")`);
361
+ fail++;
362
+ } else {
363
+ console.log(` ${GREEN}✓${NC} ${relPath} (parsed successfully, verified root key "${requiredRootKey}")`);
364
+ pass++;
365
+ }
366
+ } catch (e) {
367
+ console.error(` ${RED}✗${NC} ${relPath} (failed parsing: ${e.message})`);
368
+ fail++;
369
+ }
370
+ }
371
+
372
+ // --- Verifying Registry Parsers and Syntax Sanity ---
373
+ console.log('\nVerifying Registry Parsers and Syntax Sanity:');
374
+ verifyRegistryParsed('.ai/models/registry.yaml', 'models');
375
+ verifyRegistryParsed('.ai/models/providers.yaml', 'providers');
376
+ verifyRegistryParsed('.ai/models/routing-presets.yaml', 'presets');
377
+ verifyRegistryParsed('.ai/models/local-models.yaml', 'local_engines');
378
+ verifyRegistryParsed('.ai/adapters/registry.yaml', 'adapters');
379
+ verifyRegistryParsed('.ai/templates/registry.yaml', 'templates');
380
+
234
381
  // --- CLI & Packaging Pre-Flight Tests ---
235
382
  console.log('\nRunning CLI & Packaging Pre-Flight Tests...');
236
383
 
@@ -298,6 +445,36 @@ try {
298
445
  fail++;
299
446
  }
300
447
 
448
+ // --- Package Safety & Hygiene Checks ---
449
+ console.log('\nPackage Safety & Hygiene Checks:');
450
+ if (existsSync(join(projectRoot, '.npmrc'))) {
451
+ console.error(` ${RED}✗ .npmrc file exists in package root (security risk)${NC}`);
452
+ fail++;
453
+ } else {
454
+ console.log(` ${GREEN}✓${NC} No .npmrc file present in package root`);
455
+ pass++;
456
+ }
457
+
458
+ const checkExamplesHygiene = (dir) => {
459
+ if (!existsSync(dir)) return;
460
+ const items = readdirSync(dir);
461
+ for (const item of items) {
462
+ const fullPath = join(dir, item);
463
+ try {
464
+ const stat = statSync(fullPath);
465
+ if (stat.isDirectory()) {
466
+ checkExamplesHygiene(fullPath);
467
+ } else if (stat.isFile()) {
468
+ if (item === '.env' || item.endsWith('.keystore') || item.endsWith('.jks')) {
469
+ console.error(` ${RED}✗ Unsafe file found inside examples: ${fullPath.replace(projectRoot, '')}${NC}`);
470
+ fail++;
471
+ }
472
+ }
473
+ } catch (e) {}
474
+ }
475
+ };
476
+ checkExamplesHygiene(join(projectRoot, 'examples'));
477
+
301
478
  console.log('\n=====================================================');
302
479
  const total = pass + fail + warn;
303
480
  console.log(` Pass: ${GREEN}${pass}${NC} Fail: ${RED}${fail}${NC} Warn: ${YELLOW}${warn}${NC} Total: ${total}`);