import * as plugins from './plugins.js'; export const normalizeFileStem = (valueArg: string) => { return valueArg .trim() .toLowerCase() .replace(/[^a-z0-9]+/g, '-') .replace(/^-+|-+$/g, '') || 'new-item'; }; export const getHelpText = () => `smarthome.exchange CLI Usage: shx help shx init [name] shx open shx agent new shx automation new `; export const runCli = async (argvArg = process.argv.slice(2)) => { const [command, subcommand, nameArg] = argvArg; if (!command || command === 'help' || command === '--help' || command === '-h') { console.log(getHelpText()); return; } if (command === 'init') { await initHome(subcommand || 'birch-lane'); return; } if (command === 'open') { console.log('Open http://localhost:8080 after starting @smarthome.exchange/hub.'); return; } if (command === 'agent' && subcommand === 'new') { await createAgent(nameArg || 'custom-agent'); return; } if (command === 'automation' && subcommand === 'new') { await createAutomation(nameArg || 'new-automation'); return; } throw new Error(`Unknown command: ${argvArg.join(' ')}`); }; export const initHome = async (nameArg: string) => { const homeName = normalizeFileStem(nameArg); await plugins.fs.mkdir('.shx/agents', { recursive: true }); await plugins.fs.mkdir('.shx/automations', { recursive: true }); await plugins.fs.mkdir('.shx/dashboards', { recursive: true }); await plugins.fs.writeFile( '.shx/config.json', `${JSON.stringify({ name: homeName, createdAt: new Date().toISOString() }, null, 2)}\n` ); console.log(`Initialized .shx home: ${homeName}`); }; export const createAgent = async (nameArg: string) => { const fileStem = normalizeFileStem(nameArg); const targetPath = plugins.path.join('.shx', 'agents', `${fileStem}.ts`); await plugins.fs.mkdir(plugins.path.dirname(targetPath), { recursive: true }); await plugins.fs.writeFile( targetPath, `import type { data } from '@smarthome.exchange/interfaces';\n\nexport const agent: data.IAgentDefinition = {\n id: '${fileStem}',\n name: '${nameArg}',\n role: 'Custom household agent',\n glyph: 'custom',\n color: '#60a5fa',\n mode: 'ask',\n model: 'local:small',\n scopes: ['*.read'],\n systemPrompt: 'Describe the agent behavior here.',\n enabled: true,\n};\n` ); console.log(`Created ${targetPath}`); }; export const createAutomation = async (nameArg: string) => { const fileStem = normalizeFileStem(nameArg); const targetPath = plugins.path.join('.shx', 'automations', `${fileStem}.ts`); await plugins.fs.mkdir(plugins.path.dirname(targetPath), { recursive: true }); await plugins.fs.writeFile( targetPath, `import { on, devices } from '@smarthome.exchange/sdk';\n\non({ id: 'manual:${fileStem}', kind: 'manual', expression: '${fileStem}' }, async () => {\n await devices.read('climate.office');\n});\n` ); console.log(`Created ${targetPath}`); }; if (process.argv[1]?.endsWith('/cli.js') || process.argv[1]?.endsWith('\\cli.js')) { runCli().catch((errorArg) => { console.error(errorArg.message); process.exit(1); }); }