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:
iven
2026-03-31 03:15:45 +08:00
parent 9fb9c3204c
commit c9b9c5231b
6 changed files with 927 additions and 1025 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,462 @@
/**
* SaaS Type Definitions
*
* All type/interface definitions for the ZCLAW SaaS client.
* Extracted from saas-client.ts for modularity.
*/
// === Account & Auth Types ===
/** Public account info returned by the SaaS backend */
export interface SaaSAccountInfo {
id: string;
username: string;
email: string;
display_name: string;
role: 'super_admin' | 'admin' | 'user';
status: 'active' | 'disabled' | 'suspended';
totp_enabled: boolean;
created_at: string;
llm_routing?: 'relay' | 'local';
}
/** Lightweight template info for listing available templates */
export interface AgentTemplateAvailable {
id: string;
name: string;
category: string;
emoji?: string;
description?: string;
source_id?: string;
}
/** Full template details for creating an agent from template */
export interface AgentTemplateFull {
id: string;
name: string;
description?: string;
category: string;
emoji?: string;
personality?: string;
system_prompt?: string;
soul_content?: string;
scenarios: string[];
welcome_message?: string;
quick_commands: Array<{ label: string; command: string }>;
communication_style?: string;
model?: string;
tools: string[];
temperature?: number;
max_tokens?: number;
source_id?: string;
}
/** A model available for relay through the SaaS backend */
export interface SaaSModelInfo {
id: string;
provider_id: string;
alias: string;
context_window: number;
max_output_tokens: number;
supports_streaming: boolean;
supports_vision: boolean;
}
/** Config item from the SaaS backend */
export interface SaaSConfigItem {
id: string;
category: string;
key_path: string;
value_type: string;
current_value: string | null;
default_value: string | null;
source: string;
description: string | null;
requires_restart: boolean;
created_at: string;
updated_at: string;
}
/** SaaS API error shape */
export interface SaaSErrorResponse {
error: string;
message: string;
}
/** Login response from POST /api/v1/auth/login */
export interface SaaSLoginResponse {
token: string;
refresh_token: string;
account: SaaSAccountInfo;
}
/** Refresh response from POST /api/v1/auth/refresh */
export interface SaaSRefreshResponse {
token: string;
}
/** TOTP setup response from POST /api/v1/auth/totp/setup */
export interface TotpSetupResponse {
otpauth_uri: string;
secret: string;
issuer: string;
}
/** TOTP verify/disable response */
export interface TotpResultResponse {
ok: boolean;
totp_enabled: boolean;
message: string;
}
/** Device info stored on the SaaS backend */
export interface DeviceInfo {
id: string;
device_id: string;
device_name: string | null;
platform: string | null;
app_version: string | null;
last_seen_at: string;
created_at: string;
}
// === Relay & Config Types ===
/** Relay task info from GET /api/v1/relay/tasks */
export interface RelayTaskInfo {
id: string;
account_id: string;
provider_id: string;
model_id: string;
status: string;
priority: number;
attempt_count: number;
max_attempts: number;
input_tokens: number;
output_tokens: number;
error_message: string | null;
queued_at: string;
started_at: string | null;
completed_at: string | null;
created_at: string;
}
/** Config diff request for POST /api/v1/config/diff and /sync */
export interface SyncConfigRequest {
client_fingerprint: string;
action: 'push' | 'merge';
config_keys: string[];
client_values: Record<string, unknown>;
}
/** A single config diff entry */
export interface ConfigDiffItem {
key_path: string;
client_value: string | null;
saas_value: string | null;
conflict: boolean;
}
/** Config diff response */
export interface ConfigDiffResponse {
items: ConfigDiffItem[];
total_keys: number;
conflicts: number;
}
/** Config sync result */
export interface ConfigSyncResult {
updated: number;
created: number;
skipped: number;
}
/** Paginated response wrapper */
export interface PaginatedResponse<T> {
items: T[];
total: number;
page: number;
page_size: number;
}
// === Prompt OTA Types ===
/** Prompt template info */
export interface PromptTemplateInfo {
id: string;
name: string;
category: string;
description: string | null;
source: string;
current_version: number;
status: string;
created_at: string;
updated_at: string;
}
/** Prompt version info */
export interface PromptVersionInfo {
id: string;
template_id: string;
version: number;
system_prompt: string;
user_prompt_template: string | null;
variables: PromptVariable[];
changelog: string | null;
min_app_version: string | null;
created_at: string;
}
/** Prompt variable definition */
export interface PromptVariable {
name: string;
type: string;
default_value?: string;
description?: string;
required?: boolean;
}
/** OTA update check result */
export interface PromptCheckResult {
updates: PromptUpdatePayload[];
server_time: string;
}
/** Single OTA update payload */
export interface PromptUpdatePayload {
name: string;
version: number;
system_prompt: string;
user_prompt_template: string | null;
variables: PromptVariable[];
source: string;
min_app_version: string | null;
changelog: string | null;
}
// === Admin Types: Providers ===
/** Provider info from GET /api/v1/providers */
export interface ProviderInfo {
id: string;
name: string;
display_name: string;
base_url: string;
api_protocol: string;
enabled: boolean;
rate_limit_rpm: number | null;
rate_limit_tpm: number | null;
created_at: string;
updated_at: string;
}
/** Create provider request */
export interface CreateProviderRequest {
name: string;
display_name: string;
base_url: string;
api_protocol?: string;
api_key?: string;
rate_limit_rpm?: number;
rate_limit_tpm?: number;
}
/** Update provider request */
export interface UpdateProviderRequest {
display_name?: string;
base_url?: string;
api_key?: string;
rate_limit_rpm?: number;
rate_limit_tpm?: number;
enabled?: boolean;
}
// === Admin Types: Models ===
/** Model info from GET /api/v1/models */
export interface ModelInfo {
id: string;
provider_id: string;
model_id: string;
alias: string;
context_window: number;
max_output_tokens: number;
supports_streaming: boolean;
supports_vision: boolean;
enabled: boolean;
pricing_input: number;
pricing_output: number;
created_at: string;
updated_at: string;
}
/** Create model request */
export interface CreateModelRequest {
provider_id: string;
model_id: string;
alias: string;
context_window?: number;
max_output_tokens?: number;
supports_streaming?: boolean;
supports_vision?: boolean;
pricing_input?: number;
pricing_output?: number;
}
/** Update model request */
export interface UpdateModelRequest {
alias?: string;
context_window?: number;
max_output_tokens?: number;
supports_streaming?: boolean;
supports_vision?: boolean;
enabled?: boolean;
pricing_input?: number;
pricing_output?: number;
}
// === Admin Types: API Keys ===
/** Account API key info */
export interface AccountApiKeyInfo {
id: string;
provider_id: string;
key_label: string | null;
permissions: string[];
enabled: boolean;
last_used_at: string | null;
created_at: string;
updated_at: string;
}
/** Create API key request */
export interface CreateApiKeyRequest {
provider_id: string;
key_value: string;
key_label?: string;
permissions?: string[];
}
// === Admin Types: Usage & Accounts ===
/** Usage statistics */
export interface UsageStats {
total_input_tokens: number;
total_output_tokens: number;
total_requests: number;
by_provider: Record<string, { input_tokens: number; output_tokens: number; requests: number }>;
by_model: Record<string, { input_tokens: number; output_tokens: number; requests: number }>;
daily: Array<{ date: string; input_tokens: number; output_tokens: number; requests: number }>;
}
/** Account public info (extended) */
export interface AccountPublic {
id: string;
username: string;
email: string;
display_name: string;
role: 'super_admin' | 'admin' | 'user';
status: 'active' | 'disabled' | 'suspended';
totp_enabled: boolean;
last_login_at: string | null;
created_at: string;
}
/** Update account request */
export interface UpdateAccountRequest {
display_name?: string;
email?: string;
role?: string;
avatar_url?: string;
}
// === Admin Types: Tokens ===
/** Token info */
export interface TokenInfo {
id: string;
name: string;
token_prefix: string;
permissions: string[];
last_used_at: string | null;
expires_at: string | null;
created_at: string;
token?: string;
}
/** Create token request */
export interface CreateTokenRequest {
name: string;
permissions: string[];
expires_days?: number;
}
// === Admin Types: Logs & Dashboard ===
/** Operation log info */
export interface OperationLogInfo {
id: number;
account_id: string | null;
action: string;
target_type: string | null;
target_id: string | null;
details: Record<string, unknown> | null;
ip_address: string | null;
created_at: string;
}
/** Dashboard statistics */
export interface DashboardStats {
total_accounts: number;
active_accounts: number;
tasks_today: number;
active_providers: number;
active_models: number;
tokens_today_input: number;
tokens_today_output: number;
}
// === Admin Types: Roles & Permissions ===
/** Role info */
export interface RoleInfo {
id: string;
name: string;
description: string | null;
permissions: string[];
is_system: boolean;
created_at: string;
updated_at: string;
}
/** Create role request */
export interface CreateRoleRequest {
id: string;
name: string;
description?: string;
permissions: string[];
}
/** Update role request */
export interface UpdateRoleRequest {
name?: string;
description?: string;
permissions?: string[];
}
/** Permission template */
export interface PermissionTemplate {
id: string;
name: string;
description: string | null;
permissions: string[];
created_at: string;
updated_at: string;
}
/** Create template request */
export interface CreateTemplateRequest {
name: string;
description?: string;
permissions: string[];
}