feat(desktop): integrate SaaS llm_routing, template API, and onboarding template selection
- Add AgentTemplateAvailable/AgentTemplateFull types and fetchAvailableTemplates/fetchTemplateFull API methods to saas-client - Add llm_routing field to SaaSAccountInfo for admin-configured routing priority - Add availableTemplates state and fetchAvailableTemplates action to saasStore with background fetch on login - Add admin llm_routing priority check in connectionStore connect() to force relay or local mode - Add createFromTemplate action to agentStore with SOUL.md persistence - Add Step 0 template selection to AgentOnboardingWizard with grid layout for template browsing
This commit is contained in:
@@ -350,6 +350,70 @@ export const useConnectionStore = create<ConnectionStore>((set, get) => {
|
||||
try {
|
||||
set({ error: null });
|
||||
|
||||
// === Admin Routing Priority ===
|
||||
// Admin-configured llm_routing takes priority over localStorage connectionMode.
|
||||
// This allows admins to force all clients to use relay or local mode.
|
||||
let adminForceLocal = false;
|
||||
try {
|
||||
const storedAccount = JSON.parse(localStorage.getItem('zclaw-saas-account') || '{}');
|
||||
const adminRouting = storedAccount?.account?.llm_routing;
|
||||
|
||||
if (adminRouting === 'relay') {
|
||||
// Force SaaS Relay mode — admin override
|
||||
// Set connection mode to 'saas' so the SaaS relay section below activates
|
||||
localStorage.setItem('zclaw-connection-mode', 'saas');
|
||||
log.debug('Admin llm_routing=relay: forcing SaaS relay mode');
|
||||
} else if (adminRouting === 'local' && isTauriRuntime()) {
|
||||
// Force local Kernel mode — skip SaaS relay entirely
|
||||
adminForceLocal = true;
|
||||
localStorage.setItem('zclaw-connection-mode', 'tauri');
|
||||
log.debug('Admin llm_routing=local: forcing local Kernel mode');
|
||||
}
|
||||
} catch { /* ignore parse errors, fall through to default logic */ }
|
||||
|
||||
// === Internal Kernel Mode: Admin forced local ===
|
||||
// If admin forced local mode, skip directly to Tauri Kernel section
|
||||
if (adminForceLocal) {
|
||||
const kernelClient = getKernelClient();
|
||||
const modelConfig = await getDefaultModelConfigAsync();
|
||||
|
||||
if (!modelConfig) {
|
||||
throw new Error('请先在"模型与 API"设置页面添加自定义模型配置');
|
||||
}
|
||||
|
||||
if (!modelConfig.apiKey) {
|
||||
throw new Error(`模型 ${modelConfig.model} 未配置 API Key,请在"模型与 API"设置页面配置`);
|
||||
}
|
||||
|
||||
kernelClient.setConfig({
|
||||
provider: modelConfig.provider,
|
||||
model: modelConfig.model,
|
||||
apiKey: modelConfig.apiKey,
|
||||
baseUrl: modelConfig.baseUrl,
|
||||
apiProtocol: modelConfig.apiProtocol,
|
||||
});
|
||||
|
||||
kernelClient.onStateChange = (state: ConnectionState) => {
|
||||
set({ connectionState: state });
|
||||
};
|
||||
|
||||
kernelClient.onLog = (level, message) => {
|
||||
set((s) => ({
|
||||
logs: [...s.logs.slice(-99), { timestamp: Date.now(), level, message }],
|
||||
}));
|
||||
};
|
||||
|
||||
set({ client: kernelClient });
|
||||
|
||||
const { initializeStores } = await import('./index');
|
||||
initializeStores();
|
||||
|
||||
await kernelClient.connect();
|
||||
set({ gatewayVersion: '0.1.0-internal' });
|
||||
log.debug('Connected to internal ZCLAW Kernel (admin forced local)');
|
||||
return;
|
||||
}
|
||||
|
||||
// === SaaS Relay Mode ===
|
||||
// Check connection mode from localStorage (set by saasStore).
|
||||
// When SaaS is unreachable, gracefully degrade to local kernel mode
|
||||
|
||||
Reference in New Issue
Block a user