/** * Smart-default / snapshot RPC handlers for dynamic UI. */ import * as suggestions from '../utils/suggestions.js' import * as validation from '../utils/validation.js' export function registerSuggestionHandlers(session) { session.respond('getHostSnapshot', async () => suggestions.getHostSnapshot()) session.respond('suggestNetworkIPAM', async (args = {}) => { return suggestions.suggestNetworkIPAM(args) }) session.respond('listUsedHostPorts', async () => suggestions.listUsedHostPorts()) session.respond('suggestResourceName', async (args) => { const kind = args.kind || 'container' const base = validation.sanitizeString(args.base || args.name || 'resource', 63) return suggestions.suggestResourceName(kind, base) }) session.respond('suggestFromImage', async (args) => { const image = validation.sanitizeString(args.image || args.id, 255) if (!image) throw new Error('image required') return suggestions.suggestFromImage(image) }) session.respond('suggestDefaults', async (args = {}) => { const kind = args.kind || 'container' if (kind === 'network') { const [ipam, name] = await Promise.all([ suggestions.suggestNetworkIPAM(args), suggestions.suggestResourceName('network', args.base || 'net'), ]) return { success: true, kind: 'network', name: name.name, driver: args.driver || (ipam.driver || 'bridge'), subnet: ipam.subnet, gateway: ipam.gateway, ipam, } } if (kind === 'volume') { const name = await suggestions.suggestResourceName('volume', args.base || 'data') return { success: true, kind: 'volume', name: name.name, driver: 'local' } } if (kind === 'container' && args.image) { return suggestions.suggestFromImage(args.image) } if (kind === 'stack') { const name = await suggestions.suggestResourceName('stack', args.base || 'stack') return { success: true, kind: 'stack', name: name.name } } const snap = await suggestions.getHostSnapshot() return { success: true, kind, snapshot: snap } }) }