model.js
1 import { cli, Strategy } from '@jackwener/opencli/registry'; 2 import { SelectorError } from '@jackwener/opencli/errors'; 3 export const modelCommand = cli({ 4 site: 'chatwise', 5 name: 'model', 6 description: 'Get or switch the active AI model in ChatWise', 7 domain: 'localhost', 8 strategy: Strategy.UI, 9 browser: true, 10 args: [ 11 { name: 'model-name', required: false, positional: true, help: 'Model to switch to (e.g. gpt-4, claude-3)' }, 12 ], 13 columns: ['Status', 'Model'], 14 func: async (page, kwargs) => { 15 const desiredModel = kwargs['model-name']; 16 if (!desiredModel) { 17 // Read current model 18 const currentModel = await page.evaluate(` 19 (function() { 20 // ChatWise is a multi-LLM client, it typically shows the model name in a dropdown or header 21 const selectors = [ 22 '[class*="model"] span', 23 '[class*="Model"] span', 24 '[data-testid*="model"]', 25 'button[class*="model"]', 26 '[aria-label*="Model"]', 27 '[aria-label*="model"]', 28 ]; 29 30 for (const sel of selectors) { 31 const el = document.querySelector(sel); 32 if (el) { 33 const text = (el.textContent || el.getAttribute('title') || '').trim(); 34 if (text) return text; 35 } 36 } 37 38 return 'Unknown or Not Found'; 39 })() 40 `); 41 return [{ Status: 'Active', Model: currentModel }]; 42 } 43 else { 44 // Try to switch model 45 const opened = await page.evaluate(` 46 (function(target) { 47 const selectors = [ 48 '[class*="model"]', 49 '[class*="Model"]', 50 'button[class*="model"]', 51 ]; 52 53 for (const sel of selectors) { 54 const el = document.querySelector(sel); 55 if (el) { el.click(); return true; } 56 } 57 return false; 58 })(${JSON.stringify(desiredModel)}) 59 `); 60 if (!opened) 61 throw new SelectorError('ChatWise model selector'); 62 await page.wait(0.5); 63 // Find and click the target model in the dropdown 64 const found = await page.evaluate(` 65 (function(target) { 66 const options = document.querySelectorAll('[role="option"], [role="menuitem"], [class*="dropdown-item"], li'); 67 for (const opt of options) { 68 if ((opt.textContent || '').toLowerCase().includes(target.toLowerCase())) { 69 opt.click(); 70 return true; 71 } 72 } 73 return false; 74 })(${JSON.stringify(desiredModel)}) 75 `); 76 return [ 77 { 78 Status: found ? 'Switched' : 'Dropdown opened but model not found', 79 Model: desiredModel, 80 }, 81 ]; 82 } 83 }, 84 });