678 lines
26 KiB
TypeScript
678 lines
26 KiB
TypeScript
import { z } from 'zod';
|
|
|
|
const telegramSchema = z.object({
|
|
bot_token: z.string().min(1, 'Bot token is required'),
|
|
allowed_chat_ids: z.array(z.number()).min(1, 'At least one chat ID required'),
|
|
require_mention: z.boolean().default(true),
|
|
});
|
|
|
|
const tailscaleSchema = z.object({
|
|
/** Enable Tailscale Serve to expose gateway on tailnet. */
|
|
serve: z.boolean().default(false),
|
|
/** Custom hostname for Tailscale Serve. Defaults to machine hostname. */
|
|
hostname: z.string().optional(),
|
|
/** Tailscale Serve HTTPS port. */
|
|
port: z.number().default(443),
|
|
}).default({});
|
|
|
|
const pairingSchema = z.object({
|
|
/** Enable DM pairing codes for unknown senders. */
|
|
enabled: z.boolean().default(false),
|
|
/** Pairing code time-to-live duration (e.g. '5m', '1h'). */
|
|
code_ttl: z.string().default('5m'),
|
|
/** Length of generated pairing codes. */
|
|
code_length: z.number().default(6),
|
|
}).default({});
|
|
|
|
const wsRateLimitSchema = z.object({
|
|
enabled: z.boolean().default(true),
|
|
capacity: z.number().min(1).max(1000).default(30),
|
|
refill_per_sec: z.number().min(1).max(1000).default(15),
|
|
max_violations: z.number().min(1).max(100).default(8),
|
|
violation_window_ms: z.number().min(1000).max(60000).default(10000),
|
|
}).default({});
|
|
|
|
const serverDiscoverySchema = z.object({
|
|
/** Enable local-network service discovery (mDNS/Bonjour advertisement). */
|
|
enabled: z.boolean().default(false),
|
|
/** Service instance name advertised on LAN. */
|
|
service_name: z.string().min(1).default('flynn-gateway'),
|
|
/** mDNS service type. */
|
|
service_type: z.string().min(1).default('_flynn._tcp'),
|
|
/** Additional TXT metadata advertised with the service record. */
|
|
txt: z.record(z.string(), z.string()).default({}),
|
|
}).default({});
|
|
|
|
const serverSchema = z.object({
|
|
tailscale: tailscaleSchema,
|
|
localhost: z.boolean().default(true),
|
|
port: z.number().default(18800),
|
|
/** Static bearer token for gateway auth. If set, all connections must provide it. */
|
|
token: z.string().optional(),
|
|
/** Trust Tailscale-User-Login header for identity. */
|
|
tailscale_identity: z.boolean().default(false),
|
|
/** Apply token auth to HTTP requests too (not just WebSocket). Default: true when token is set. */
|
|
auth_http: z.boolean().default(true),
|
|
/** Single-client gateway lock. When true, only one WebSocket client can be connected at a time. */
|
|
lock: z.boolean().default(false),
|
|
/** Maximum size (bytes) for inbound HTTP request bodies (webhooks/Gmail push). */
|
|
max_request_body_bytes: z.number().min(1024).max(10 * 1024 * 1024).default(1_048_576),
|
|
/** Per-connection WebSocket ingress rate limit settings. */
|
|
ws_rate_limit: wsRateLimitSchema,
|
|
/** Optional Bonjour/mDNS advertisement settings. */
|
|
discovery: serverDiscoverySchema,
|
|
});
|
|
|
|
/** All supported model provider identifiers. Used by the config schema and TUI autocompletion. */
|
|
export const MODEL_PROVIDERS = ['anthropic', 'openai', 'gemini', 'ollama', 'llamacpp', 'openrouter', 'vercel', 'bedrock', 'github', 'zhipuai', 'xai', 'minimax', 'moonshot', 'synthetic'] as const;
|
|
|
|
export type ModelProvider = (typeof MODEL_PROVIDERS)[number];
|
|
|
|
const modelConfigBaseSchema = z.object({
|
|
provider: z.enum(MODEL_PROVIDERS),
|
|
model: z.string(),
|
|
endpoint: z.string().optional(),
|
|
api_key: z.string().optional(),
|
|
auth_token: z.string().optional(),
|
|
/** Credential selection strategy for this tier (provider-specific). */
|
|
auth_mode: z.enum(['auto', 'api_key', 'oauth']).optional(),
|
|
/** Use OAuth credential flow (provider-specific). */
|
|
use_oauth: z.boolean().optional(),
|
|
for: z.array(z.string()).optional(),
|
|
num_gpu: z.number().optional(),
|
|
context_window: z.number().optional(),
|
|
supports_audio: z.boolean().optional(),
|
|
});
|
|
|
|
const modelConfigSchema = modelConfigBaseSchema.extend({
|
|
fallback: modelConfigBaseSchema.optional(),
|
|
});
|
|
|
|
const thinkingSchema = z.object({
|
|
anthropic: z.object({
|
|
budgetTokens: z.number().default(4096),
|
|
}).default({}),
|
|
openai: z.object({
|
|
reasoningEffort: z.enum(['low', 'medium', 'high']).default('medium'),
|
|
}).default({}),
|
|
gemini: z.object({
|
|
budgetTokens: z.number().default(4096),
|
|
}).default({}),
|
|
}).default({});
|
|
|
|
const modelsSchema = z.object({
|
|
local: modelConfigSchema.optional(),
|
|
fast: modelConfigSchema.optional(),
|
|
default: modelConfigSchema,
|
|
complex: modelConfigSchema.optional(),
|
|
fallback_chain: z.array(z.string()).default(['anthropic']),
|
|
local_providers: z.record(z.string(), modelConfigSchema).optional(),
|
|
thinking: thinkingSchema,
|
|
});
|
|
|
|
const backendsSchema = z.object({
|
|
claude_code: z.object({
|
|
enabled: z.boolean().default(false),
|
|
path: z.string().optional(),
|
|
}).default({ enabled: false }),
|
|
opencode: z.object({
|
|
enabled: z.boolean().default(false),
|
|
path: z.string().optional(),
|
|
}).default({ enabled: false }),
|
|
native: z.object({
|
|
enabled: z.boolean().default(true),
|
|
}).default({ enabled: true }),
|
|
}).default({});
|
|
|
|
const hooksSchema = z.object({
|
|
confirm: z.array(z.string()).default([]),
|
|
log: z.array(z.string()).default([]),
|
|
silent: z.array(z.string()).default([]),
|
|
}).default({});
|
|
|
|
const skillsLoadSchema = z.object({
|
|
/** Enable filesystem watcher for automatic skill reload detection. */
|
|
watch: z.boolean().default(false),
|
|
/** Debounce window for batched watcher events. */
|
|
watch_debounce_ms: z.number().min(10).max(10_000).default(250),
|
|
}).default({});
|
|
|
|
const skillsShellRunnerGovernanceSchema = z.object({
|
|
/** Responsible owner for shell-runner allowlist decisions. */
|
|
owner: z.string().min(1).optional(),
|
|
/** Review cadence for allowlist + rollout status checks. */
|
|
review_cadence_days: z.number().min(1).max(90).default(7),
|
|
/** Minimum success rate required before broader rollout. */
|
|
promotion_min_success_rate: z.number().min(0).max(1).default(0.9),
|
|
}).default({});
|
|
|
|
const skillsSchema = z.object({
|
|
/** Registry catalog source for `flynn skills registry` and install-by-id (file path or HTTPS URL). */
|
|
registry_source: z.string().optional(),
|
|
/** Directory for user-created workspace skills. */
|
|
workspace_dir: z.string().optional(),
|
|
/** Directory for managed (installed) skills. Defaults to ~/.flynn/workspace/skills. */
|
|
managed_dir: z.string().optional(),
|
|
/** Directory for bundled skills shipped with Flynn. */
|
|
bundled_dir: z.string().optional(),
|
|
/** Global policy gate for installer command execution. */
|
|
installation_execution: z.enum(['disabled', 'enabled']).default('disabled'),
|
|
/** Allow use of the shell runner for installer commands. */
|
|
allow_shell_runner: z.boolean().default(false),
|
|
/** Allowlist patterns for shell runner commands (supports '*' wildcard). */
|
|
shell_runner_allowlist: z.array(z.string()).default([]),
|
|
/** Governance controls for shell-runner rollout decisions. */
|
|
shell_runner_governance: skillsShellRunnerGovernanceSchema,
|
|
/** Skills watcher settings. */
|
|
load: skillsLoadSchema,
|
|
}).default({});
|
|
|
|
const mcpServerSchema = z.object({
|
|
name: z.string(),
|
|
command: z.string(),
|
|
args: z.array(z.string()).default([]),
|
|
env: z.record(z.string(), z.string()).optional(),
|
|
cwd: z.string().optional(),
|
|
});
|
|
|
|
const mcpSchema = z.object({
|
|
servers: z.array(mcpServerSchema).default([]),
|
|
}).default({ servers: [] });
|
|
|
|
const modelTierEnum = z.enum(['fast', 'default', 'complex', 'local']);
|
|
|
|
const cronJobSchema = z.object({
|
|
name: z.string().min(1, 'Cron job name is required'),
|
|
schedule: z.string().min(1, 'Cron schedule is required'),
|
|
message: z.string().min(1, 'Cron message is required'),
|
|
output: z.object({
|
|
channel: z.string().min(1),
|
|
peer: z.string().min(1),
|
|
}),
|
|
enabled: z.boolean().default(true),
|
|
timezone: z.string().optional(),
|
|
model_tier: modelTierEnum.optional(),
|
|
});
|
|
|
|
const webhookSchema = z.object({
|
|
name: z.string().min(1, 'Webhook name is required'),
|
|
secret: z.string().optional(),
|
|
message: z.string().default('{{body}}'),
|
|
output: z.object({
|
|
channel: z.string().min(1),
|
|
peer: z.string().min(1),
|
|
}),
|
|
enabled: z.boolean().default(true),
|
|
});
|
|
|
|
const gmailSchema = z.object({
|
|
enabled: z.boolean().default(false),
|
|
credentials_file: z.string().optional(),
|
|
token_file: z.string().default('~/.config/flynn/gmail-token.json'),
|
|
/**
|
|
* Optional Google Cloud Pub/Sub topic for Gmail push notifications.
|
|
* Format: projects/<project-id>/topics/<topic>
|
|
* If omitted, push notifications are disabled and Flynn will use polling.
|
|
*/
|
|
pubsub_topic: z.string().optional(),
|
|
|
|
/**
|
|
* Explicitly disable Gmail push watch registration even if pubsub_topic is set.
|
|
* Useful for environments where Google cannot reach the gateway (e.g. tailnet-only).
|
|
*/
|
|
disable_push: z.boolean().default(false),
|
|
|
|
/**
|
|
* Optional Pub/Sub subscription for pull-based delivery (no inbound webhook required).
|
|
* Format: projects/<project-id>/subscriptions/<subscription>
|
|
*/
|
|
pubsub_subscription_id: z.string().optional(),
|
|
|
|
/** How often to pull messages from pubsub_subscription_id (e.g. '60s'). */
|
|
pubsub_pull_interval: z.string().default('60s'),
|
|
|
|
/** Max messages to pull per cycle (1..100). */
|
|
pubsub_max_messages: z.number().min(1).max(100).default(10),
|
|
watch_labels: z.array(z.string()).default(['INBOX']),
|
|
poll_interval: z.string().default('300s'),
|
|
history_start: z.string().optional(), // ISO date string — only process emails after this date
|
|
output: z.object({
|
|
channel: z.string().min(1),
|
|
peer: z.string().min(1),
|
|
}),
|
|
message: z.string().default('New email from {{from}}: {{subject}}\n\n{{snippet}}'),
|
|
}).optional();
|
|
|
|
const heartbeatCheckSchema = z.enum(['gateway', 'model', 'channels', 'memory', 'disk']);
|
|
|
|
const heartbeatSchema = z.object({
|
|
enabled: z.boolean().default(false),
|
|
interval: z.string().default('5m'),
|
|
checks: z.array(heartbeatCheckSchema).default(['gateway', 'model', 'channels', 'memory', 'disk']),
|
|
notify: z.object({
|
|
channel: z.string().min(1),
|
|
peer: z.string().min(1),
|
|
}).optional(),
|
|
failure_threshold: z.number().min(1).max(10).default(2),
|
|
disk_threshold_mb: z.number().min(10).default(100),
|
|
}).default({});
|
|
|
|
const gcalSchema = z.object({
|
|
enabled: z.boolean().default(false),
|
|
credentials_file: z.string().optional(),
|
|
token_file: z.string().default('~/.config/flynn/gcal-token.json'),
|
|
calendar_ids: z.array(z.string()).default(['primary']),
|
|
}).optional();
|
|
|
|
const gdocsSchema = z.object({
|
|
enabled: z.boolean().default(false),
|
|
credentials_file: z.string().optional(),
|
|
token_file: z.string().default('~/.config/flynn/gdocs-token.json'),
|
|
}).optional();
|
|
|
|
const gdriveSchema = z.object({
|
|
enabled: z.boolean().default(false),
|
|
credentials_file: z.string().optional(),
|
|
token_file: z.string().default('~/.config/flynn/gdrive-token.json'),
|
|
}).optional();
|
|
|
|
const gtasksSchema = z.object({
|
|
enabled: z.boolean().default(false),
|
|
credentials_file: z.string().optional(),
|
|
token_file: z.string().default('~/.config/flynn/gtasks-token.json'),
|
|
}).optional();
|
|
|
|
const automationDeliveryModeSchema = z.enum(['shared_session', 'isolated_job']);
|
|
|
|
const automationSchema = z.object({
|
|
/** Session strategy for automation-triggered runs (cron/webhooks/gmail). */
|
|
delivery_mode: automationDeliveryModeSchema.default('shared_session'),
|
|
cron: z.array(cronJobSchema).default([]),
|
|
webhooks: z.array(webhookSchema).default([]),
|
|
gmail: gmailSchema,
|
|
gcal: gcalSchema,
|
|
gdocs: gdocsSchema,
|
|
gdrive: gdriveSchema,
|
|
gtasks: gtasksSchema,
|
|
heartbeat: heartbeatSchema,
|
|
}).default({});
|
|
|
|
const truthfulnessModeSchema = z.enum(['strict', 'standard', 'relaxed']);
|
|
const autonomyLevelSchema = z.enum(['conservative', 'standard', 'autonomous']);
|
|
|
|
const agentsSchema = z.object({
|
|
primary_tier: z.enum(['fast', 'default', 'complex', 'local']).default('default'),
|
|
delegation: z.object({
|
|
compaction: z.enum(['fast', 'default', 'complex', 'local']).default('fast'),
|
|
memory_extraction: z.enum(['fast', 'default', 'complex', 'local']).default('fast'),
|
|
classification: z.enum(['fast', 'default', 'complex', 'local']).default('fast'),
|
|
tool_summarisation: z.enum(['fast', 'default', 'complex', 'local']).default('fast'),
|
|
complex_reasoning: z.enum(['fast', 'default', 'complex', 'local']).default('complex'),
|
|
}).default({
|
|
compaction: 'fast',
|
|
memory_extraction: 'fast',
|
|
classification: 'fast',
|
|
tool_summarisation: 'fast',
|
|
complex_reasoning: 'complex',
|
|
}),
|
|
auto_escalate: z.boolean().default(false),
|
|
max_delegation_depth: z.number().min(1).max(10).default(3),
|
|
/** Maximum tool-loop iterations before the agent stops. */
|
|
max_iterations: z.number().min(1).max(200).default(200),
|
|
/** Truthfulness enforcement level: strict | standard | relaxed. */
|
|
truthfulness_mode: truthfulnessModeSchema.default('standard'),
|
|
/** Autonomy level for tool execution: conservative | standard | autonomous. */
|
|
autonomy_level: autonomyLevelSchema.default('standard'),
|
|
}).default({});
|
|
|
|
const embeddingProviderSchema = z.enum(['openai', 'gemini', 'ollama', 'llamacpp', 'voyage']);
|
|
|
|
const embeddingSchema = z.object({
|
|
enabled: z.boolean().default(false),
|
|
provider: embeddingProviderSchema.default('openai'),
|
|
model: z.string().default('text-embedding-3-small'),
|
|
endpoint: z.string().optional(),
|
|
api_key: z.string().optional(),
|
|
dimensions: z.number().optional(),
|
|
chunk_size: z.number().min(64).max(8192).default(512),
|
|
chunk_overlap: z.number().min(0).max(1024).default(50),
|
|
top_k: z.number().min(1).max(50).default(5),
|
|
hybrid_weight: z.number().min(0).max(1).default(0.7),
|
|
}).default({});
|
|
|
|
const qmdSchema = z.object({
|
|
/** Enable experimental QMD (query markdown database) memory search backend. */
|
|
enabled: z.boolean().default(false),
|
|
/** Maximum number of QMD results returned by memory.search. */
|
|
top_k: z.number().min(1).max(50).default(8),
|
|
/** Minimum relevance score (0-1) for QMD matches. */
|
|
min_score: z.number().min(0).max(1).default(0.15),
|
|
}).default({});
|
|
|
|
const memorySchema = z.object({
|
|
enabled: z.boolean().default(true),
|
|
dir: z.string().optional(), // Default: ~/.local/share/flynn/memory
|
|
auto_extract: z.boolean().default(true),
|
|
injection_strategy: z.enum(['all', 'recent', 'adaptive']).default('all'),
|
|
max_injection_tokens: z.number().min(100).max(10000).default(2000),
|
|
max_context_tokens: z.number().min(100).max(10000).default(2000),
|
|
embedding: embeddingSchema,
|
|
qmd: qmdSchema,
|
|
}).default({});
|
|
|
|
const compactionSchema = z.object({
|
|
enabled: z.boolean().default(true),
|
|
threshold_pct: z.number().min(10).max(100).default(80),
|
|
keep_turns: z.number().min(1).max(50).default(4),
|
|
summary_max_tokens: z.number().min(128).max(4096).default(1024),
|
|
importance_threshold: z.number().min(0).max(1).default(1),
|
|
}).default({});
|
|
|
|
const discordSchema = z.object({
|
|
bot_token: z.string().min(1, 'Bot token is required'),
|
|
allowed_guild_ids: z.array(z.string()).default([]),
|
|
allowed_channel_ids: z.array(z.string()).default([]),
|
|
require_mention: z.boolean().default(true),
|
|
}).optional();
|
|
|
|
const slackSchema = z.object({
|
|
bot_token: z.string().min(1, 'Bot token is required'),
|
|
app_token: z.string().min(1, 'App token is required'),
|
|
signing_secret: z.string().min(1, 'Signing secret is required'),
|
|
allowed_channel_ids: z.array(z.string()).default([]),
|
|
require_mention: z.boolean().default(false),
|
|
}).optional();
|
|
|
|
const whatsappSchema = z.object({
|
|
allowed_numbers: z.array(z.string()).default([]),
|
|
allowed_group_ids: z.array(z.string()).default([]),
|
|
require_mention: z.boolean().default(true),
|
|
data_dir: z.string().optional(),
|
|
no_sandbox: z.boolean().default(false),
|
|
}).optional();
|
|
|
|
const matrixSchema = z.object({
|
|
homeserver_url: z.string().url('Homeserver URL is required'),
|
|
access_token: z.string().min(1, 'Access token is required'),
|
|
allowed_room_ids: z.array(z.string()).default([]),
|
|
require_mention: z.boolean().default(true),
|
|
sync_timeout_ms: z.number().min(1000).max(120000).default(30000),
|
|
display_name: z.string().optional(),
|
|
}).optional();
|
|
|
|
const signalSchema = z.object({
|
|
account: z.string().min(1, 'Signal account is required'),
|
|
signal_cli_path: z.string().default('signal-cli'),
|
|
allowed_numbers: z.array(z.string()).default([]),
|
|
allowed_group_ids: z.array(z.string()).default([]),
|
|
require_mention: z.boolean().default(true),
|
|
mention_name: z.string().default('flynn'),
|
|
poll_interval_ms: z.number().min(1000).max(60000).default(5000),
|
|
send_timeout_ms: z.number().min(1000).max(60000).default(15000),
|
|
}).optional();
|
|
|
|
const teamsSchema = z.object({
|
|
app_id: z.string().min(1, 'Teams app_id is required'),
|
|
app_password: z.string().min(1, 'Teams app_password is required'),
|
|
allowed_conversation_ids: z.array(z.string()).default([]),
|
|
require_mention: z.boolean().default(true),
|
|
}).optional();
|
|
|
|
const googleChatSchema = z.object({
|
|
service_account_key_file: z.string().optional(),
|
|
service_account_json: z.string().optional(),
|
|
webhook_token: z.string().optional(),
|
|
allowed_space_names: z.array(z.string()).default([]),
|
|
require_mention: z.boolean().default(true),
|
|
}).optional();
|
|
|
|
const browserSchema = z.object({
|
|
enabled: z.boolean().default(false),
|
|
executable_path: z.string().optional(),
|
|
ws_endpoint: z.string().optional(),
|
|
headless: z.boolean().default(true),
|
|
max_pages: z.number().min(1).max(20).default(5),
|
|
default_timeout: z.number().min(1000).max(120000).default(30000),
|
|
}).default({});
|
|
|
|
const processSchema = z.object({
|
|
max_concurrent: z.number().min(1).max(50).default(10),
|
|
max_runtime_minutes: z.number().min(1).max(1440).default(60),
|
|
buffer_size: z.number().min(1024).max(1048576).default(65536),
|
|
}).default({});
|
|
|
|
const retrySchema = z.object({
|
|
enabled: z.boolean().default(true),
|
|
max_retries: z.number().min(0).max(10).default(3),
|
|
initial_delay_ms: z.number().min(100).max(60000).default(1000),
|
|
backoff_multiplier: z.number().min(1).max(5).default(2),
|
|
max_delay_ms: z.number().min(1000).max(120000).default(30000),
|
|
}).default({});
|
|
|
|
const webSearchSchema = z.object({
|
|
provider: z.enum(['brave', 'searxng']).default('brave'),
|
|
api_key: z.string().optional(),
|
|
endpoint: z.string().optional(),
|
|
max_results: z.number().min(1).max(20).default(5),
|
|
}).default({});
|
|
|
|
const audioProviderSchema = z.object({
|
|
type: z.enum(['openai', 'groq', 'ollama', 'llamacpp', 'custom']),
|
|
endpoint: z.string().optional(),
|
|
api_key: z.string().optional(),
|
|
model: z.string().optional(),
|
|
});
|
|
|
|
const audioSchema = z.object({
|
|
enabled: z.boolean().default(false),
|
|
provider: audioProviderSchema.optional(),
|
|
}).default({});
|
|
|
|
// ── Tool policy schemas ──────────────────────────────────────────────
|
|
|
|
const toolProfileEnum = z.enum(['minimal', 'messaging', 'coding', 'full']);
|
|
|
|
const toolOverrideSchema = z.object({
|
|
profile: toolProfileEnum.optional(),
|
|
allow: z.array(z.string()).default([]),
|
|
deny: z.array(z.string()).default([]),
|
|
}).default({});
|
|
|
|
const toolsSchema = z.object({
|
|
profile: toolProfileEnum.default('full'),
|
|
allow: z.array(z.string()).default([]),
|
|
deny: z.array(z.string()).default([]),
|
|
agents: z.record(z.string(), toolOverrideSchema).default({}),
|
|
providers: z.record(z.string(), toolOverrideSchema).default({}),
|
|
}).default({});
|
|
|
|
// ── Sandbox schemas ───────────────────────────────────────────────────
|
|
|
|
const sandboxSchema = z.object({
|
|
enabled: z.boolean().default(false),
|
|
image: z.string().default('node:22-slim'),
|
|
workspace_dir: z.string().default('/workspace'),
|
|
network: z.enum(['none', 'bridge', 'host']).default('none'),
|
|
memory_limit: z.string().default('512m'),
|
|
cpu_limit: z.string().default('1.0'),
|
|
timeout_seconds: z.number().min(10).max(3600).default(300),
|
|
}).default({});
|
|
|
|
// ── Agent config + routing schemas ────────────────────────────────────
|
|
|
|
const agentConfigEntrySchema = z.object({
|
|
system_prompt: z.string().optional(),
|
|
model_tier: modelTierEnum.optional(),
|
|
tool_profile: toolProfileEnum.optional(),
|
|
tool_overrides: toolOverrideSchema.optional(),
|
|
sandbox: z.boolean().default(false),
|
|
});
|
|
|
|
const agentConfigsSchema = z.record(z.string(), agentConfigEntrySchema).default({});
|
|
|
|
const routingSchema = z.object({
|
|
default_agent: z.string().optional(),
|
|
channels: z.record(z.string(), z.string()).default({}),
|
|
senders: z.record(z.string(), z.string()).default({}),
|
|
}).default({});
|
|
|
|
const intentTargetTypeSchema = z.enum(['agent', 'skill']);
|
|
|
|
const intentRuleSchema = z.object({
|
|
name: z.string().min(1),
|
|
patterns: z.array(z.string().min(1)).min(1),
|
|
target: z.object({
|
|
type: intentTargetTypeSchema,
|
|
name: z.string().min(1),
|
|
}),
|
|
priority: z.number().default(0),
|
|
enabled: z.boolean().default(true),
|
|
});
|
|
|
|
const intentsSchema = z.object({
|
|
enabled: z.boolean().default(false),
|
|
match_threshold: z.number().min(0).max(1).default(0.7),
|
|
rules: z.array(intentRuleSchema).default([]),
|
|
}).default({});
|
|
|
|
const routingPolicySchema = z.object({
|
|
enabled: z.boolean().default(false),
|
|
fast_path_threshold: z.number().min(0).max(1).default(0.85),
|
|
llm_threshold: z.number().min(0).max(1).default(0.5),
|
|
default_path: z.enum(['fast', 'llm']).default('llm'),
|
|
}).default({});
|
|
|
|
const contextLevelSchema = z.enum(['minimal', 'normal', 'detailed', 'debug']);
|
|
|
|
const promptSchema = z.object({
|
|
/** Additional directories to search for prompt template files. */
|
|
search_dirs: z.array(z.string()).default([]),
|
|
/** Extra named sections to include in the system prompt. */
|
|
extra_sections: z.array(z.object({
|
|
name: z.string(),
|
|
content: z.string(),
|
|
})).default([]),
|
|
/** Prompt context depth control: minimal | normal | detailed | debug. */
|
|
context_level: contextLevelSchema.default('normal'),
|
|
}).default({});
|
|
|
|
const sessionsSchema = z.object({
|
|
ttl: z.string().default('30d'),
|
|
}).default({});
|
|
|
|
const historyIndexSchema = z.object({
|
|
enabled: z.boolean().default(false),
|
|
max_keywords: z.number().min(1).max(20).default(8),
|
|
search_limit: z.number().min(1).max(100).default(10),
|
|
min_score: z.number().min(0).max(1).default(0.15),
|
|
routing_boost: z.number().min(0).max(0.2).default(0.05),
|
|
}).default({});
|
|
|
|
const logLevelSchema = z.enum(['debug', 'info', 'warn', 'error', 'silent']).default('info');
|
|
|
|
const auditLevelSchema = z.enum(['debug', 'info', 'warn', 'error']).default('debug');
|
|
|
|
const auditSchema = z.object({
|
|
enabled: z.boolean().default(true),
|
|
path: z.string().default('~/.local/share/flynn/audit.log'),
|
|
max_size_mb: z.number().min(1).max(1000).default(10),
|
|
keep_days: z.number().min(1).max(365).default(30),
|
|
levels: z.object({
|
|
tools: auditLevelSchema.default('debug'),
|
|
sessions: auditLevelSchema.default('debug'),
|
|
automation: auditLevelSchema.default('debug'),
|
|
}).default({}),
|
|
}).default({});
|
|
|
|
export const configSchema = z.object({
|
|
log_level: logLevelSchema,
|
|
audit: auditSchema,
|
|
telegram: telegramSchema.optional(),
|
|
discord: discordSchema,
|
|
slack: slackSchema,
|
|
whatsapp: whatsappSchema,
|
|
matrix: matrixSchema,
|
|
signal: signalSchema,
|
|
teams: teamsSchema,
|
|
google_chat: googleChatSchema,
|
|
server: serverSchema.default({}),
|
|
models: modelsSchema,
|
|
backends: backendsSchema.default({}),
|
|
hooks: hooksSchema.default({}),
|
|
skills: skillsSchema.default({}),
|
|
mcp: mcpSchema.default({ servers: [] }),
|
|
automation: automationSchema,
|
|
agents: agentsSchema,
|
|
compaction: compactionSchema,
|
|
memory: memorySchema,
|
|
process: processSchema,
|
|
browser: browserSchema,
|
|
retry: retrySchema,
|
|
web_search: webSearchSchema,
|
|
audio: audioSchema,
|
|
prompt: promptSchema,
|
|
tools: toolsSchema,
|
|
sandbox: sandboxSchema,
|
|
agent_configs: agentConfigsSchema,
|
|
routing: routingSchema,
|
|
intents: intentsSchema,
|
|
routing_policy: routingPolicySchema,
|
|
history_index: historyIndexSchema,
|
|
sessions: sessionsSchema,
|
|
pairing: pairingSchema,
|
|
});
|
|
|
|
export type Config = z.infer<typeof configSchema>;
|
|
export type TelegramConfig = z.infer<typeof telegramSchema>;
|
|
export type ModelConfig = z.infer<typeof modelConfigSchema>;
|
|
export type CronJobConfig = z.infer<typeof cronJobSchema>;
|
|
export type WebhookConfig = z.infer<typeof webhookSchema>;
|
|
export type GmailConfig = z.infer<typeof gmailSchema>;
|
|
export type AgentsConfig = z.infer<typeof agentsSchema>;
|
|
export type CompactionConfig = z.infer<typeof compactionSchema>;
|
|
export type MemoryConfig = z.infer<typeof memorySchema>;
|
|
export type WebSearchConfig = z.infer<typeof webSearchSchema>;
|
|
export type AudioConfig = z.infer<typeof audioSchema>;
|
|
export type ProcessConfig = z.infer<typeof processSchema>;
|
|
export type BrowserConfig = z.infer<typeof browserSchema>;
|
|
export type DiscordConfig = z.infer<typeof discordSchema>;
|
|
export type SlackConfig = z.infer<typeof slackSchema>;
|
|
export type WhatsAppConfig = z.infer<typeof whatsappSchema>;
|
|
export type MatrixConfig = z.infer<typeof matrixSchema>;
|
|
export type SignalConfig = z.infer<typeof signalSchema>;
|
|
export type TeamsConfig = z.infer<typeof teamsSchema>;
|
|
export type GoogleChatConfig = z.infer<typeof googleChatSchema>;
|
|
export type RetryPolicyConfig = z.infer<typeof retrySchema>;
|
|
export type ContextLevel = z.infer<typeof contextLevelSchema>;
|
|
export type PromptConfig = z.infer<typeof promptSchema>;
|
|
export type ToolProfile = z.infer<typeof toolProfileEnum>;
|
|
export type ToolOverrideConfig = z.infer<typeof toolOverrideSchema>;
|
|
export type ToolsConfig = z.infer<typeof toolsSchema>;
|
|
export type SandboxConfig = z.infer<typeof sandboxSchema>;
|
|
export type AgentConfigEntry = z.infer<typeof agentConfigEntrySchema>;
|
|
export type RoutingConfig = z.infer<typeof routingSchema>;
|
|
export type IntentTargetType = z.infer<typeof intentTargetTypeSchema>;
|
|
export type IntentRuleConfig = z.infer<typeof intentRuleSchema>;
|
|
export type IntentsConfig = z.infer<typeof intentsSchema>;
|
|
export type RoutingPolicyConfig = z.infer<typeof routingPolicySchema>;
|
|
export type HistoryIndexConfig = z.infer<typeof historyIndexSchema>;
|
|
export type ServerConfig = z.infer<typeof serverSchema>;
|
|
export type SessionsConfig = z.infer<typeof sessionsSchema>;
|
|
export type ThinkingConfig = z.infer<typeof thinkingSchema>;
|
|
export type HeartbeatConfig = z.infer<typeof heartbeatSchema>;
|
|
export type HeartbeatCheck = z.infer<typeof heartbeatCheckSchema>;
|
|
export type EmbeddingConfig = z.infer<typeof embeddingSchema>;
|
|
export type EmbeddingProvider = z.infer<typeof embeddingProviderSchema>;
|
|
export type QmdConfig = z.infer<typeof qmdSchema>;
|
|
export type GcalConfig = z.infer<typeof gcalSchema>;
|
|
export type GdocsConfig = z.infer<typeof gdocsSchema>;
|
|
export type GdriveConfig = z.infer<typeof gdriveSchema>;
|
|
export type GtasksConfig = z.infer<typeof gtasksSchema>;
|
|
export type AutomationDeliveryMode = z.infer<typeof automationDeliveryModeSchema>;
|
|
export type PairingCodeConfig = z.infer<typeof pairingSchema>;
|
|
export type LogLevel = z.infer<typeof logLevelSchema>;
|
|
export type AuditConfig = z.infer<typeof auditSchema>;
|
|
export type AuditLevel = z.infer<typeof auditLevelSchema>;
|
|
export type TruthfulnessMode = z.infer<typeof truthfulnessModeSchema>;
|
|
export type AutonomyLevel = z.infer<typeof autonomyLevelSchema>;
|