import { t as ChatType } from "./chat-type-CK5stkc4.js"; import { ImageContent } from "@mariozechner/pi-ai"; import { APIEmbed } from "discord-api-types/v10"; import { Embed, RequestClient, TopLevelComponents } from "@buape/carbon"; import { Block, KnownBlock, WebClient } from "@slack/web-api"; import { Bot } from "grammy"; import { AgentTool, AgentToolResult } from "@mariozechner/pi-agent-core"; import { TSchema } from "@sinclair/typebox"; //#region src/channels/plugins/message-action-names.d.ts declare const CHANNEL_MESSAGE_ACTION_NAMES: readonly ["send", "broadcast", "poll", "react", "reactions", "read", "edit", "unsend", "reply", "sendWithEffect", "renameGroup", "setGroupIcon", "addParticipant", "removeParticipant", "leaveGroup", "sendAttachment", "delete", "pin", "unpin", "list-pins", "permissions", "thread-create", "thread-list", "thread-reply", "search", "sticker", "sticker-search", "member-info", "role-info", "emoji-list", "emoji-upload", "sticker-upload", "role-add", "role-remove", "channel-info", "channel-list", "channel-create", "channel-edit", "channel-delete", "channel-move", "category-create", "category-edit", "category-delete", "topic-create", "voice-status", "event-list", "event-create", "timeout", "kick", "ban", "set-presence"]; type ChannelMessageActionName$2 = (typeof CHANNEL_MESSAGE_ACTION_NAMES)[number]; //#endregion //#region src/auto-reply/reply/typing.d.ts type TypingController = { onReplyStart: () => Promise; startTypingLoop: () => Promise; startTypingOnText: (text?: string) => Promise; refreshTypingTtl: () => void; isActive: () => boolean; markRunComplete: () => void; markDispatchIdle: () => void; cleanup: () => void; }; //#endregion //#region src/auto-reply/types.d.ts type BlockReplyContext = { abortSignal?: AbortSignal; timeoutMs?: number; }; /** Context passed to onModelSelected callback with actual model used. */ type ModelSelectedContext = { provider: string; model: string; thinkLevel: string | undefined; }; type TypingPolicy = "auto" | "user_message" | "system_event" | "internal_webchat" | "heartbeat"; type SourceReplyDeliveryMode = "normal" | "message_tool_only"; type GetReplyOptions = { /** Override run id for agent events (defaults to random UUID). */runId?: string; /** Abort signal for the underlying agent run. */ abortSignal?: AbortSignal; /** Optional inbound images (used for webchat attachments). */ images?: ImageContent[]; /** Notifies when an agent run actually starts (useful for webchat command handling). */ onAgentRunStart?: (runId: string) => void; onReplyStart?: () => Promise | void; /** Called when the typing controller cleans up (e.g., run ended with NO_REPLY). */ onTypingCleanup?: () => void; onTypingController?: (typing: TypingController) => void; isHeartbeat?: boolean; /** Policy-level typing control for run classes (user/system/internal/heartbeat). */ typingPolicy?: TypingPolicy; /** Force-disable typing indicators for this run (system/internal/cross-channel routes). */ suppressTyping?: boolean; /** Resolved heartbeat model override (provider/model string from merged per-agent config). */ heartbeatModelOverride?: string; /** If true, suppress tool error warning payloads for this run. */ suppressToolErrorWarnings?: boolean; /** Describes how source replies should be delivered when another channel/tool owns final delivery. */ sourceReplyDeliveryMode?: SourceReplyDeliveryMode; /** Allow progress callbacks even when final/source reply delivery is tool-owned. */ allowProgressCallbacksWhenSourceDeliverySuppressed?: boolean; onPartialReply?: (payload: ReplyPayload) => Promise | void; onReasoningStream?: (payload: ReplyPayload) => Promise | void; /** Called when a thinking/reasoning block ends. */ onReasoningEnd?: () => Promise | void; /** Called when a new assistant message starts (e.g., after tool call or thinking block). */ onAssistantMessageStart?: () => Promise | void; onBlockReply?: (payload: ReplyPayload, context?: BlockReplyContext) => Promise | void; onToolResult?: (payload: ReplyPayload) => Promise | void; /** Called when a tool phase starts/updates, before summary payloads are emitted. */ onToolStart?: (payload: { name?: string; phase?: string; }) => Promise | void; /** Called when the actual model is selected (including after fallback). * Use this to get model/provider/thinkLevel for responsePrefix template interpolation. */ onModelSelected?: (ctx: ModelSelectedContext) => void; disableBlockStreaming?: boolean; /** Timeout for block reply delivery (ms). */ blockReplyTimeoutMs?: number; /** If provided, only load these skills for this session (empty = no skills). */ skillFilter?: string[]; /** Mutable ref to track if a reply was sent (for Slack "first" threading mode). */ hasRepliedRef?: { value: boolean; }; /** Override agent timeout in seconds (0 = no timeout). Threads through to resolveAgentTimeoutMs. */ timeoutOverrideSeconds?: number; }; type ReplyPayload = { text?: string; mediaUrl?: string; mediaUrls?: string[]; replyToId?: string; replyToTag?: boolean; /** True when [[reply_to_current]] was present but not yet mapped to a message id. */ replyToCurrent?: boolean; /** Send audio as voice message (bubble) instead of audio file. Defaults to false. */ audioAsVoice?: boolean; isError?: boolean; /** Marks this payload as a reasoning/thinking block. Channels that do not * have a dedicated reasoning lane (e.g. WhatsApp, web) should suppress it. */ isReasoning?: boolean; /** Channel-specific payload data (per-channel envelope). */ channelData?: Record; }; //#endregion //#region src/infra/exec-safe-bin-policy-profiles.d.ts type SafeBinProfileFixture = { minPositional?: number; maxPositional?: number; allowedValueFlags?: readonly string[]; deniedFlags?: readonly string[]; }; //#endregion //#region src/config/types.base.d.ts type TypingMode = "never" | "instant" | "thinking" | "message"; type SessionScope = "per-sender" | "global"; type DmScope = "main" | "per-peer" | "per-channel-peer" | "per-account-channel-peer"; type ReplyToMode = "off" | "first" | "all"; type GroupPolicy = "open" | "disabled" | "allowlist"; type DmPolicy = "pairing" | "allowlist" | "open" | "disabled"; type OutboundRetryConfig = { /** Max retry attempts for outbound requests (default: 3). */attempts?: number; /** Minimum retry delay in ms (default: 300-500ms depending on provider). */ minDelayMs?: number; /** Maximum retry delay cap in ms (default: 30000). */ maxDelayMs?: number; /** Jitter factor (0-1) applied to delays (default: 0.1). */ jitter?: number; }; type BlockStreamingCoalesceConfig = { minChars?: number; maxChars?: number; idleMs?: number; }; type BlockStreamingChunkConfig = { minChars?: number; maxChars?: number; breakPreference?: "paragraph" | "newline" | "sentence"; }; type MarkdownTableMode = "off" | "bullets" | "code"; type MarkdownConfig = { /** Table rendering mode (off|bullets|code). */tables?: MarkdownTableMode; }; type HumanDelayConfig = { /** Delay style for block replies (off|natural|custom). */mode?: "off" | "natural" | "custom"; /** Minimum delay in milliseconds (default: 800). */ minMs?: number; /** Maximum delay in milliseconds (default: 2500). */ maxMs?: number; }; type SessionSendPolicyAction = "allow" | "deny"; type SessionSendPolicyMatch = { channel?: string; chatType?: ChatType; /** * Session key prefix match. * Note: some consumers match against a normalized key (for example, stripping `agent::`). */ keyPrefix?: string; /** Optional raw session-key prefix match for consumers that normalize session keys. */ rawKeyPrefix?: string; }; type SessionSendPolicyRule = { action: SessionSendPolicyAction; match?: SessionSendPolicyMatch; }; type SessionSendPolicyConfig = { default?: SessionSendPolicyAction; rules?: SessionSendPolicyRule[]; }; type SessionResetMode = "daily" | "idle"; type SessionResetConfig = { mode?: SessionResetMode; /** Local hour (0-23) for the daily reset boundary. */ atHour?: number; /** Sliding idle window (minutes). When set with daily mode, whichever expires first wins. */ idleMinutes?: number; }; type SessionResetByTypeConfig = { direct?: SessionResetConfig; /** @deprecated Use `direct` instead. Kept for backward compatibility. */ dm?: SessionResetConfig; group?: SessionResetConfig; thread?: SessionResetConfig; }; type SessionThreadBindingsConfig = { /** * Master switch for thread-bound session routing features. * Channel/provider keys can override this default. */ enabled?: boolean; /** * Inactivity window for thread-bound sessions (hours). * Session auto-unfocuses after this amount of idle time. Set to 0 to disable. Default: 24. */ idleHours?: number; /** * Optional hard max age for thread-bound sessions (hours). * Session auto-unfocuses once this age is reached even if active. Set to 0 to disable. Default: 0. */ maxAgeHours?: number; }; type SessionConfig = { scope?: SessionScope; /** DM session scoping (default: "main"). */ dmScope?: DmScope; /** Map platform-prefixed identities (e.g. "telegram:123") to canonical DM peers. */ identityLinks?: Record; resetTriggers?: string[]; idleMinutes?: number; reset?: SessionResetConfig; resetByType?: SessionResetByTypeConfig; /** Channel-specific reset overrides (e.g. { discord: { mode: "idle", idleMinutes: 10080 } }). */ resetByChannel?: Record; store?: string; typingIntervalSeconds?: number; typingMode?: TypingMode; /** * Max parent transcript token count allowed for thread/session forking. * If parent totalTokens is above this value, FasedAgent skips parent fork and * starts a fresh thread session instead. Set to 0 to disable this guard. */ parentForkMaxTokens?: number; mainKey?: string; sendPolicy?: SessionSendPolicyConfig; agentToAgent?: { /** Max ping-pong turns between requester/target (0–5). Default: 5. */maxPingPongTurns?: number; }; /** Shared defaults for thread-bound session routing across channels/providers. */ threadBindings?: SessionThreadBindingsConfig; /** Automatic session store maintenance (pruning, capping, file rotation). */ maintenance?: SessionMaintenanceConfig; }; type SessionMaintenanceMode = "enforce" | "warn"; type SessionMaintenanceConfig = { /** Whether to enforce maintenance or warn only. Default: "warn". */mode?: SessionMaintenanceMode; /** Remove session entries older than this duration (e.g. "30d", "12h"). Default: "30d". */ pruneAfter?: string | number; /** Deprecated. Use pruneAfter instead. */ pruneDays?: number; /** Maximum number of session entries to keep. Default: 500. */ maxEntries?: number; /** Rotate sessions.json when it exceeds this size (e.g. "10mb"). Default: 10mb. */ rotateBytes?: number | string; /** * Retention for archived reset transcripts (`*.reset.`). * Set `false` to disable reset-archive cleanup. Default: same as `pruneAfter` (30d). */ resetArchiveRetention?: string | number | false; /** * Optional per-agent sessions-directory disk budget (e.g. "500mb"). * When exceeded, warn (mode=warn) or enforce oldest-first cleanup (mode=enforce). */ maxDiskBytes?: number | string; /** * Target size after disk-budget cleanup (high-water mark), e.g. "400mb". * Default: 80% of maxDiskBytes. */ highWaterBytes?: number | string; }; type LoggingConfig = { level?: "silent" | "fatal" | "error" | "warn" | "info" | "debug" | "trace"; file?: string; /** Maximum size of a single log file in bytes before writes are suppressed. Default: 500 MB. */ maxFileBytes?: number; consoleLevel?: "silent" | "fatal" | "error" | "warn" | "info" | "debug" | "trace"; consoleStyle?: "pretty" | "compact" | "json"; /** Redact sensitive tokens in tool summaries. Default: "tools". */ redactSensitive?: "off" | "tools"; /** Regex patterns used to redact sensitive tokens (defaults apply when unset). */ redactPatterns?: string[]; }; type DiagnosticsOtelConfig = { enabled?: boolean; endpoint?: string; protocol?: "http/protobuf" | "grpc"; headers?: Record; serviceName?: string; traces?: boolean; metrics?: boolean; logs?: boolean; /** Trace sample rate (0.0 - 1.0). */ sampleRate?: number; /** Metric export interval (ms). */ flushIntervalMs?: number; }; type DiagnosticsCacheTraceConfig = { enabled?: boolean; filePath?: string; includeMessages?: boolean; includePrompt?: boolean; includeSystem?: boolean; }; type DiagnosticsPrometheusConfig = { enabled?: boolean; /** HTTP path for Prometheus text exposition. Default: /metrics. */ path?: string; /** * Require normal gateway probe auth for remote clients. Local loopback requests remain allowed. * Default: true. */ requireAuth?: boolean; /** Include lightweight runtime/process gauges. Default: true. */ includeRuntime?: boolean; }; type DiagnosticsConfig = { enabled?: boolean; /** Optional ad-hoc diagnostics flags (e.g. "telegram.http"). */ flags?: string[]; otel?: DiagnosticsOtelConfig; prometheus?: DiagnosticsPrometheusConfig; cacheTrace?: DiagnosticsCacheTraceConfig; }; type WebReconnectConfig = { initialMs?: number; maxMs?: number; factor?: number; jitter?: number; maxAttempts?: number; }; type WebConfig = { /** If false, do not start the WhatsApp web provider. Default: true. */enabled?: boolean; heartbeatSeconds?: number; reconnect?: WebReconnectConfig; }; type AgentElevatedAllowFromConfig = Partial>>; type IdentityConfig = { name?: string; theme?: string; emoji?: string; /** Avatar image: workspace-relative path, http(s) URL, or data URI. */ avatar?: string; }; //#endregion //#region src/config/types.secrets.d.ts type SecretRefSource = "env" | "file" | "exec"; /** * Stable identifier for a secret in a configured source. * Examples: * - env source: provider "default", id "OPENAI_API_KEY" * - file source: provider "mounted-json", id "/providers/openai/apiKey" * - exec source: provider "vault", id "openai/api-key" */ type SecretRef = { source: SecretRefSource; provider: string; id: string; }; type SecretInput = string | SecretRef; type EnvSecretProviderConfig = { source: "env"; /** Optional env var allowlist (exact names). */ allowlist?: string[]; }; type FileSecretProviderMode = "singleValue" | "json"; type FileSecretProviderConfig = { source: "file"; path: string; mode?: FileSecretProviderMode; timeoutMs?: number; maxBytes?: number; }; type ExecSecretProviderConfig = { source: "exec"; command: string; args?: string[]; timeoutMs?: number; noOutputTimeoutMs?: number; maxOutputBytes?: number; jsonOnly?: boolean; env?: Record; passEnv?: string[]; trustedDirs?: string[]; allowInsecurePath?: boolean; allowSymlinkCommand?: boolean; }; type SecretProviderConfig = EnvSecretProviderConfig | FileSecretProviderConfig | ExecSecretProviderConfig; type SecretsConfig = { providers?: Record; defaults?: { env?: string; file?: string; exec?: string; }; resolution?: { maxProviderConcurrency?: number; maxRefsPerProvider?: number; maxBatchBytes?: number; }; }; //#endregion //#region src/config/types.tools.d.ts type MediaUnderstandingScopeMatch = { channel?: string; chatType?: ChatType; keyPrefix?: string; }; type MediaUnderstandingScopeRule = { action: SessionSendPolicyAction; match?: MediaUnderstandingScopeMatch; }; type MediaUnderstandingScopeConfig = { default?: SessionSendPolicyAction; rules?: MediaUnderstandingScopeRule[]; }; type MediaUnderstandingCapability$1 = "image" | "audio" | "video"; type MediaUnderstandingAttachmentsConfig = { /** Select the first matching attachment or process multiple. */mode?: "first" | "all"; /** Max number of attachments to process (default: 1). */ maxAttachments?: number; /** Attachment ordering preference. */ prefer?: "first" | "last" | "path" | "url"; }; type MediaProviderRequestConfig = { /** Optional provider-specific query params (merged into requests). */providerOptions?: Record>; /** @deprecated Use providerOptions.deepgram instead. */ deepgram?: { detectLanguage?: boolean; punctuate?: boolean; smartFormat?: boolean; }; /** Optional base URL override for provider requests. */ baseUrl?: string; /** Optional headers merged into provider requests. */ headers?: Record; }; type MediaUnderstandingModelConfig = MediaProviderRequestConfig & { /** provider API id (e.g. openai, google). */provider?: string; /** Model id for provider-based understanding. */ model?: string; /** Optional capability tags for shared model lists. */ capabilities?: MediaUnderstandingCapability$1[]; /** Use a CLI command instead of provider API. */ type?: "provider" | "cli"; /** CLI binary (required when type=cli). */ command?: string; /** CLI args (template-enabled). */ args?: string[]; /** Optional prompt override for this model entry. */ prompt?: string; /** Optional max output characters for this model entry. */ maxChars?: number; /** Optional max bytes for this model entry. */ maxBytes?: number; /** Optional timeout override (seconds) for this model entry. */ timeoutSeconds?: number; /** Optional language hint for audio transcription. */ language?: string; /** Auth profile id to use for this provider. */ profile?: string; /** Preferred profile id if multiple are available. */ preferredProfile?: string; }; type MediaUnderstandingConfig = MediaProviderRequestConfig & { /** Enable media understanding when models are configured. */enabled?: boolean; /** Optional scope gating for understanding. */ scope?: MediaUnderstandingScopeConfig; /** Default max bytes to send. */ maxBytes?: number; /** Default max output characters. */ maxChars?: number; /** Default prompt. */ prompt?: string; /** Default timeout (seconds). */ timeoutSeconds?: number; /** Default language hint (audio). */ language?: string; /** Attachment selection policy. */ attachments?: MediaUnderstandingAttachmentsConfig; /** Ordered model list (fallbacks in order). */ models?: MediaUnderstandingModelConfig[]; }; type LinkModelConfig = { /** Use a CLI command for link processing. */type?: "cli"; /** CLI binary (required when type=cli). */ command: string; /** CLI args (template-enabled). */ args?: string[]; /** Optional timeout override (seconds) for this model entry. */ timeoutSeconds?: number; }; type LinkToolsConfig = { /** Enable link understanding when models are configured. */enabled?: boolean; /** Optional scope gating for understanding. */ scope?: MediaUnderstandingScopeConfig; /** Max number of links to process per message. */ maxLinks?: number; /** Default timeout (seconds). */ timeoutSeconds?: number; /** Ordered model list (fallbacks in order). */ models?: LinkModelConfig[]; }; type MediaToolsConfig = { /** Shared model list applied across image/audio/video. */models?: MediaUnderstandingModelConfig[]; /** Max concurrent media understanding runs. */ concurrency?: number; image?: MediaUnderstandingConfig; audio?: MediaUnderstandingConfig; video?: MediaUnderstandingConfig; }; type ToolProfileId = "minimal" | "coding" | "messaging" | "full"; type ToolLoopDetectionDetectorConfig = { /** Enable warning/blocking for repeated identical calls to the same tool/params. */genericRepeat?: boolean; /** Enable warning/blocking for known no-progress polling loops. */ knownPollNoProgress?: boolean; /** Enable warning/blocking for no-progress ping-pong alternating patterns. */ pingPong?: boolean; }; type ToolLoopDetectionConfig = { /** Enable tool-loop protection (default: false). */enabled?: boolean; /** Maximum tool call history entries retained for loop detection (default: 30). */ historySize?: number; /** Warning threshold before a warning-only loop classification (default: 10). */ warningThreshold?: number; /** Critical threshold for blocking repetitive loops (default: 20). */ criticalThreshold?: number; /** Global no-progress breaker threshold (default: 30). */ globalCircuitBreakerThreshold?: number; /** Detector toggles. */ detectors?: ToolLoopDetectionDetectorConfig; }; type SessionsToolsVisibility = "self" | "tree" | "agent" | "all"; type ToolPolicyConfig = { allow?: string[]; /** * Additional allowlist entries merged into the effective allowlist. * * Intended for additive configuration (e.g., "also allow shell") without forcing * users to replace/duplicate an existing allowlist or profile. */ alsoAllow?: string[]; deny?: string[]; profile?: ToolProfileId; }; type GroupToolPolicyConfig = { allow?: string[]; /** Additional allowlist entries merged into allow. */ alsoAllow?: string[]; deny?: string[]; }; /** * Per-sender overrides. * * Prefer explicit key prefixes: * - id: * - e164: * - username: * - name: * - * (wildcard) * * Legacy unprefixed keys are supported for backward compatibility and are matched as senderId only. */ type GroupToolPolicyBySenderConfig = Record; type ExecToolConfig = { /** Exec host routing (default: auto). */host?: "auto" | "sandbox" | "gateway" | "node"; /** Exec security mode (default: deny). */ security?: "deny" | "allowlist" | "full"; /** Exec ask mode (default: on-miss). */ ask?: "off" | "on-miss" | "always"; /** Default node binding for exec.host=node (node id/name). */ node?: string; /** Directories to prepend to PATH when running exec (gateway/sandbox). */ pathPrepend?: string[]; /** Safe stdin-only binaries that can run without allowlist entries. */ safeBins?: string[]; /** Extra explicit directories trusted for safeBins path checks (never derived from PATH). */ safeBinTrustedDirs?: string[]; /** Optional custom safe-bin profiles for entries in tools.exec.safeBins. */ safeBinProfiles?: Record; /** Default time (ms) before an exec command auto-backgrounds. */ backgroundMs?: number; /** Default timeout (seconds) before auto-killing exec commands. */ timeoutSec?: number; /** Emit a running notice (ms) when approval-backed exec runs long (default: 10000, 0 = off). */ approvalRunningNoticeMs?: number; /** How long to keep finished sessions in memory (ms). */ cleanupMs?: number; /** Emit a system event and heartbeat when a backgrounded exec exits. */ notifyOnExit?: boolean; /** * Also emit success exit notifications when a backgrounded exec has no output. * Default false to reduce context noise. */ notifyOnExitEmptySuccess?: boolean; /** apply_patch subtool configuration (experimental). */ applyPatch?: { /** Enable apply_patch for OpenAI models (default: false). */enabled?: boolean; /** * Restrict apply_patch paths to the workspace directory. * Default: true (safer; does not affect read/write/edit). */ workspaceOnly?: boolean; /** * Optional allowlist of model ids that can use apply_patch. * Accepts either raw ids (e.g. "gpt-5.2") or full ids (e.g. "openai/gpt-5.2"). */ allowModels?: string[]; }; }; type FsToolsConfig = { /** * Restrict filesystem tools (read/write/edit/apply_patch) to the agent workspace directory. * Default: false (unrestricted, matches legacy behavior). */ workspaceOnly?: boolean; }; type AgentToolsConfig = { /** Base tool profile applied before allow/deny lists. */profile?: ToolProfileId; allow?: string[]; /** Additional allowlist entries merged into allow and/or profile allowlist. */ alsoAllow?: string[]; deny?: string[]; /** Optional tool policy overrides keyed by provider id or "provider/model". */ byProvider?: Record; /** Per-agent elevated exec gate (can only further restrict global tools.elevated). */ elevated?: { /** Enable or disable elevated mode for this agent (default: true). */enabled?: boolean; /** Approved senders for /elevated (per-provider allowlists). */ allowFrom?: AgentElevatedAllowFromConfig; }; /** Exec tool defaults for this agent. */ exec?: ExecToolConfig; /** Filesystem tool path guards. */ fs?: FsToolsConfig; /** Runtime loop detection for repetitive/ stuck tool-call patterns. */ loopDetection?: ToolLoopDetectionConfig; sandbox?: { tools?: { allow?: string[]; deny?: string[]; }; }; }; type MemorySearchConfig = { /** Enable vector memory search (default: true). */enabled?: boolean; /** Sources to index and search (default: ["memory"]). */ sources?: Array<"memory" | "sessions">; /** Extra paths to include in memory search (directories or .md files). */ extraPaths?: string[]; /** Experimental memory search settings. */ experimental?: { /** Enable session transcript indexing (experimental, default: false). */sessionMemory?: boolean; }; /** Embedding provider mode. */ provider?: "openai" | "gemini" | "local" | "voyage" | "mistral" | "ollama" | "auto"; remote?: { baseUrl?: string; apiKey?: string; headers?: Record; /** Explicitly allow sanitized session transcripts to leave the host for embeddings. */ allowSessionContent?: boolean; batch?: { /** Enable batch API for embedding indexing (OpenAI/Gemini; default: true). */enabled?: boolean; /** Wait for batch completion (default: true). */ wait?: boolean; /** Max concurrent batch jobs (default: 2). */ concurrency?: number; /** Poll interval in ms (default: 5000). */ pollIntervalMs?: number; /** Timeout in minutes (default: 60). */ timeoutMinutes?: number; }; }; /** Fallback behavior when embeddings fail. */ fallback?: "openai" | "gemini" | "local" | "voyage" | "mistral" | "none"; /** Embedding model id (remote) or alias (local). */ model?: string; /** Multimodal memory indexing options for providers that support media embeddings. */ multimodal?: { enabled?: boolean; modalities?: Array<"image" | "audio" | "all">; maxFileBytes?: number; }; /** Local embedding settings (node-llama-cpp). */ local?: { /** GGUF model path or hf: URI. */modelPath?: string; /** Optional cache directory for local models. */ modelCacheDir?: string; }; /** Index storage configuration. */ store?: { driver?: "sqlite"; path?: string; vector?: { /** Enable sqlite-vec extension for vector search (default: true). */enabled?: boolean; /** Optional override path to sqlite-vec extension (.dylib/.so/.dll). */ extensionPath?: string; }; cache?: { /** Enable embedding cache (default: true). */enabled?: boolean; /** Optional max cache entries per provider/model. */ maxEntries?: number; }; }; /** Chunking configuration. */ chunking?: { tokens?: number; overlap?: number; }; /** Sync behavior. */ sync?: { onSessionStart?: boolean; onSearch?: boolean; watch?: boolean; watchDebounceMs?: number; intervalMinutes?: number; sessions?: { /** Minimum appended bytes before session transcripts are reindexed. */deltaBytes?: number; /** Minimum appended JSONL lines before session transcripts are reindexed. */ deltaMessages?: number; /** Force reindexing after transcript compaction. */ postCompactionForce?: boolean; }; }; /** Query behavior. */ query?: { maxResults?: number; minScore?: number; hybrid?: { /** Enable hybrid BM25 + vector search (default: true). */enabled?: boolean; /** Weight for vector similarity when merging results (0-1). */ vectorWeight?: number; /** Weight for BM25 text relevance when merging results (0-1). */ textWeight?: number; /** Multiplier for candidate pool size (default: 4). */ candidateMultiplier?: number; /** Optional MMR re-ranking for result diversity. */ mmr?: { /** Enable MMR re-ranking (default: false). */enabled?: boolean; /** Lambda: 0 = max diversity, 1 = max relevance (default: 0.7). */ lambda?: number; }; /** Optional temporal decay to boost recency in hybrid scoring. */ temporalDecay?: { /** Enable temporal decay (default: false). */enabled?: boolean; /** Half-life in days for exponential decay (default: 30). */ halfLifeDays?: number; }; }; }; /** Index cache behavior. */ cache?: { /** Cache chunk embeddings in SQLite (default: true). */enabled?: boolean; /** Optional cap on cached embeddings (best-effort). */ maxEntries?: number; }; }; type ToolsConfig = { /** Base tool profile applied before allow/deny lists. */profile?: ToolProfileId; allow?: string[]; /** Additional allowlist entries merged into allow and/or profile allowlist. */ alsoAllow?: string[]; deny?: string[]; /** Optional tool policy overrides keyed by provider id or "provider/model". */ byProvider?: Record; web?: { search?: { /** Enable web search tool (default: true when API key is present). */enabled?: boolean; /** Search provider id (built-in or plugin-registered). */ provider?: string; /** Brave Search API key or SecretRef (optional; defaults to BRAVE_API_KEY env var). */ apiKey?: SecretInput; /** Default search results count (1-10). */ maxResults?: number; /** Timeout in seconds for search requests. */ timeoutSeconds?: number; /** Cache TTL in minutes for search results. */ cacheTtlMinutes?: number; /** OpenAI-Codex native Responses web_search configuration. */ openaiCodex?: { /** Enable native Codex web_search injection. */enabled?: boolean; /** Use cached or live external web access. */ mode?: "cached" | "live"; /** Optional allowed domains for provider-side web search. */ allowedDomains?: string[]; /** Provider context size hint. */ contextSize?: "low" | "medium" | "high"; /** Optional provider-side user location hint. */ userLocation?: { country?: string; region?: string; city?: string; timezone?: string; }; }; /** DuckDuckGo-specific configuration (keyless fallback provider). */ duckduckgo?: { /** Optional DuckDuckGo region such as "us-en". */region?: string; /** Safe search level. */ safeSearch?: "strict" | "moderate" | "off"; }; /** Exa-specific configuration (used when provider="exa"). */ exa?: { /** Exa API key (defaults to EXA_API_KEY env var). */apiKey?: SecretInput; /** Optional Exa-compatible search endpoint or base URL. */ baseUrl?: string; /** Exa search type. */ type?: "auto" | "neural" | "fast" | "deep" | "deep-reasoning" | "instant"; }; /** Firecrawl search configuration (used when provider="firecrawl"). */ firecrawl?: { /** Firecrawl API key (defaults to FIRECRAWL_API_KEY env var). */apiKey?: SecretInput; /** Firecrawl base URL (default: https://api.firecrawl.dev). */ baseUrl?: string; }; /** Perplexity-specific configuration (used when provider="perplexity"). */ perplexity?: { /** API key for Perplexity or OpenRouter (defaults to PERPLEXITY_API_KEY or OPENROUTER_API_KEY env var). */apiKey?: SecretInput; /** Base URL for API requests (defaults to OpenRouter: https://openrouter.ai/api/v1). */ baseUrl?: string; /** Model to use (defaults to "perplexity/sonar-pro"). */ model?: string; }; /** Grok-specific configuration (used when provider="grok"). */ grok?: { /** API key for xAI (defaults to XAI_API_KEY env var). */apiKey?: SecretInput; /** Model to use (defaults to "grok-4-1-fast"). */ model?: string; /** Include inline citations in response text as markdown links (default: false). */ inlineCitations?: boolean; }; /** Gemini-specific configuration (used when provider="gemini"). */ gemini?: { /** Gemini API key (defaults to GEMINI_API_KEY env var). */apiKey?: SecretInput; /** Model to use for grounded search (defaults to "gemini-3.5-flash"). */ model?: string; }; /** Kimi-specific configuration (used when provider="kimi"). */ kimi?: { /** Moonshot/Kimi API key (defaults to KIMI_API_KEY or MOONSHOT_API_KEY env var). */apiKey?: SecretInput; /** Base URL for API requests (defaults to "https://api.moonshot.ai/v1"). */ baseUrl?: string; /** Model to use (defaults to "moonshot-v1-128k"). */ model?: string; }; /** SearXNG-specific configuration (used when provider="searxng"). */ searxng?: { /** SearXNG instance base URL (defaults to SEARXNG_BASE_URL env var). */baseUrl?: string; /** Optional SearXNG categories, e.g. "general". */ categories?: string; /** Optional SearXNG language. */ language?: string; }; /** Tavily-specific configuration (used when provider="tavily"). */ tavily?: { /** Tavily API key (defaults to TAVILY_API_KEY env var). */apiKey?: SecretInput; /** Tavily base URL (default: https://api.tavily.com). */ baseUrl?: string; /** Include Tavily answer text when available. */ includeAnswer?: boolean; /** Tavily search depth. */ searchDepth?: "basic" | "advanced"; /** Tavily topic filter. */ topic?: string; }; }; fetch?: { /** Enable web fetch tool (default: true). */enabled?: boolean; /** Max characters to return from fetched content. */ maxChars?: number; /** Hard cap for maxChars (tool or config), defaults to 50000. */ maxCharsCap?: number; /** Timeout in seconds for fetch requests. */ timeoutSeconds?: number; /** Cache TTL in minutes for fetched content. */ cacheTtlMinutes?: number; /** Maximum number of redirects to follow (default: 3). */ maxRedirects?: number; /** Override User-Agent header for fetch requests. */ userAgent?: string; /** Use Readability to extract main content (default: true). */ readability?: boolean; firecrawl?: { /** Enable Firecrawl fallback (default: true when apiKey is set). */enabled?: boolean; /** Firecrawl API key (optional; defaults to FIRECRAWL_API_KEY env var). */ apiKey?: SecretInput; /** Firecrawl base URL (default: https://api.firecrawl.dev). */ baseUrl?: string; /** Whether to keep only main content (default: true). */ onlyMainContent?: boolean; /** Max age (ms) for cached Firecrawl content. */ maxAgeMs?: number; /** Timeout in seconds for Firecrawl requests. */ timeoutSeconds?: number; }; }; }; media?: MediaToolsConfig; links?: LinkToolsConfig; /** Message tool configuration. */ message?: { /** * @deprecated Use tools.message.crossContext settings. * Allows cross-context sends across providers. */ allowCrossContextSend?: boolean; crossContext?: { /** Allow sends to other channels within the same provider (default: true). */allowWithinProvider?: boolean; /** Allow sends across different providers (default: false). */ allowAcrossProviders?: boolean; /** Cross-context marker configuration. */ marker?: { /** Enable origin markers for cross-context sends (default: true). */enabled?: boolean; /** Text prefix template, supports {channel}. */ prefix?: string; /** Text suffix template, supports {channel}. */ suffix?: string; }; }; broadcast?: { /** Enable broadcast action (default: true). */enabled?: boolean; }; }; agentToAgent?: { /** Enable agent-to-agent messaging tools. Default: false. */enabled?: boolean; /** Allowlist of agent ids or patterns (implementation-defined). */ allow?: string[]; }; /** * Session tool visibility controls which sessions can be targeted by session tools * (sessions_list, sessions_history, sessions_send). * * Default: "tree" (current session + spawned subagent sessions). */ sessions?: { /** * - "self": only the current session * - "tree": current session + sessions spawned by this session (default) * - "agent": any session belonging to the current agent id (can include other users) * - "all": any session (cross-agent still requires tools.agentToAgent) */ visibility?: SessionsToolsVisibility; }; /** sessions_spawn attachment limits. */ sessions_spawn?: { attachments?: { enabled?: boolean; maxFiles?: number; maxFileBytes?: number; maxTotalBytes?: number; retainOnSessionKeep?: boolean; }; }; /** Elevated exec permissions for the host machine. */ elevated?: { /** Enable or disable elevated mode (default: true). */enabled?: boolean; /** Approved senders for /elevated (per-provider allowlists). */ allowFrom?: AgentElevatedAllowFromConfig; }; /** Exec tool defaults. */ exec?: ExecToolConfig; /** Filesystem tool path guards. */ fs?: FsToolsConfig; /** Runtime loop detection for repetitive/ stuck tool-call patterns. */ loopDetection?: ToolLoopDetectionConfig; /** Sub-agent tool policy defaults (deny wins). */ subagents?: { /** Default model selection for spawned sub-agents (string or {primary,fallbacks}). */model?: string | { primary?: string; fallbacks?: string[]; }; tools?: { allow?: string[]; /** Additional allowlist entries merged into allow and/or default sub-agent denylist. */ alsoAllow?: string[]; deny?: string[]; }; }; /** Sandbox tool policy defaults (deny wins). */ sandbox?: { tools?: { allow?: string[]; deny?: string[]; }; }; }; //#endregion //#region src/infra/retry.d.ts type RetryConfig = { attempts?: number; minDelayMs?: number; maxDelayMs?: number; jitter?: number; }; //#endregion //#region src/discord/send.types.d.ts type DiscordSendResult = { messageId: string; channelId: string; }; //#endregion //#region src/polls.d.ts type PollInput = { question: string; options: string[]; maxSelections?: number; /** * Poll duration in seconds. * Channel-specific limits apply (e.g. Telegram open_period is 5-600s). */ durationSeconds?: number; /** * Poll duration in hours. * Used by channels that model duration in hours (e.g. Discord). */ durationHours?: number; }; //#endregion //#region src/gateway/protocol/client-info.d.ts declare const GATEWAY_CLIENT_IDS: { readonly WEBCHAT_UI: "webchat-ui"; readonly CONTROL_UI: "fased-control-ui"; readonly WEBCHAT: "webchat"; readonly CLI: "cli"; readonly GATEWAY_CLIENT: "gateway-client"; readonly MACOS_APP: "fased-macos"; readonly IOS_APP: "fased-ios"; readonly ANDROID_APP: "fased-android"; readonly NODE_HOST: "node-host"; readonly TEST: "test"; readonly FINGERPRINT: "fingerprint"; readonly PROBE: "fased-probe"; }; type GatewayClientId = (typeof GATEWAY_CLIENT_IDS)[keyof typeof GATEWAY_CLIENT_IDS]; type GatewayClientName = GatewayClientId; declare const GATEWAY_CLIENT_MODES: { readonly WEBCHAT: "webchat"; readonly CLI: "cli"; readonly UI: "ui"; readonly BACKEND: "backend"; readonly NODE: "node"; readonly PROBE: "probe"; readonly TEST: "test"; }; type GatewayClientMode = (typeof GATEWAY_CLIENT_MODES)[keyof typeof GATEWAY_CLIENT_MODES]; //#endregion //#region src/utils/message-channel.d.ts declare const INTERNAL_MESSAGE_CHANNEL: "webchat"; type InternalMessageChannel = typeof INTERNAL_MESSAGE_CHANNEL; type DeliverableMessageChannel = ChannelId; //#endregion //#region src/auto-reply/chunk.d.ts type TextChunkProvider = ChannelId | typeof INTERNAL_MESSAGE_CHANNEL; /** * Chunking mode for outbound messages: * - "length": Split only when exceeding textChunkLimit (default) * - "newline": Prefer breaking on "soft" boundaries. Historically this split on every * newline; now it only breaks on paragraph boundaries (blank lines) unless the text * exceeds the length limit. */ type ChunkMode = "length" | "newline"; declare function resolveTextChunkLimit(cfg: FasedAgentConfig | undefined, provider?: TextChunkProvider, accountId?: string | null, opts?: { fallbackLimit?: number; }): number; declare function resolveChunkMode(cfg: FasedAgentConfig | undefined, provider?: TextChunkProvider, accountId?: string | null): ChunkMode; /** * Split text on newlines, trimming line whitespace. * Blank lines are folded into the next non-empty line as leading "\n" prefixes. * Long lines can be split by length (default) or kept intact via splitLongLines:false. */ declare function chunkByNewline(text: string, maxLineLength: number, opts?: { splitLongLines?: boolean; trimLines?: boolean; isSafeBreak?: (index: number) => boolean; }): string[]; /** * Unified chunking function that dispatches based on mode. */ declare function chunkTextWithMode(text: string, limit: number, mode: ChunkMode): string[]; declare function chunkMarkdownTextWithMode(text: string, limit: number, mode: ChunkMode): string[]; declare function chunkText(text: string, limit: number): string[]; declare function chunkMarkdownText(text: string, limit: number): string[]; //#endregion //#region src/config/types.acp.d.ts type AcpDispatchConfig = { /** Master switch for ACP turn dispatch in the reply pipeline. */enabled?: boolean; }; type AcpStreamConfig = { /** Coalescer idle flush window in milliseconds for ACP streamed text. */coalesceIdleMs?: number; /** Maximum text size per streamed chunk. */ maxChunkChars?: number; }; type AcpRuntimeConfig = { /** Idle runtime TTL in minutes for ACP session workers. */ttlMinutes?: number; /** Optional operator install/setup command shown by `/acp install` and `/acp doctor`. */ installCommand?: string; }; type AcpConfig = { /** Global ACP runtime gate. */enabled?: boolean; dispatch?: AcpDispatchConfig; /** Backend id registered by ACP runtime plugin (for example: acpx). */ backend?: string; defaultAgent?: string; allowedAgents?: string[]; maxConcurrentSessions?: number; stream?: AcpStreamConfig; runtime?: AcpRuntimeConfig; }; //#endregion //#region src/config/types.sandbox.d.ts type SandboxDockerSettings = { /** Docker image to use for sandbox containers. */image?: string; /** Prefix for sandbox container names. */ containerPrefix?: string; /** Container workdir mount path (default: /workspace). */ workdir?: string; /** Run container rootfs read-only. */ readOnlyRoot?: boolean; /** Extra tmpfs mounts for read-only containers. */ tmpfs?: string[]; /** Container network mode (bridge|none|custom). */ network?: string; /** Container user (uid:gid). */ user?: string; /** Drop Linux capabilities. */ capDrop?: string[]; /** Extra environment variables for sandbox exec. */ env?: Record; /** Optional setup command run once after container creation. */ setupCommand?: string; /** Limit container PIDs (0 = Docker default). */ pidsLimit?: number; /** Limit container memory (e.g. 512m, 2g, or bytes as number). */ memory?: string | number; /** Limit container memory swap (same format as memory). */ memorySwap?: string | number; /** Limit container CPU shares (e.g. 0.5, 1, 2). */ cpus?: number; /** * Set ulimit values by name (e.g. nofile, nproc). * Use "soft:hard" string, a number, or { soft, hard }. */ ulimits?: Record; /** Seccomp profile (path or profile name). */ seccompProfile?: string; /** AppArmor profile name. */ apparmorProfile?: string; /** DNS servers (e.g. ["1.1.1.1", "8.8.8.8"]). */ dns?: string[]; /** Extra host mappings (e.g. ["api.local:10.0.0.2"]). */ extraHosts?: string[]; /** Additional bind mounts (host:container:mode format, e.g. ["/host/path:/container/path:rw"]). */ binds?: string[]; /** * Dangerous override: allow bind mounts that target reserved container paths * like /workspace or /agent. */ dangerouslyAllowReservedContainerTargets?: boolean; /** * Dangerous override: allow bind mount sources outside runtime allowlisted roots * (workspace + agent workspace roots). */ dangerouslyAllowExternalBindSources?: boolean; /** * Dangerous override: allow Docker `network: "container:"` namespace joins. * Default behavior blocks container namespace joins to preserve sandbox isolation. */ dangerouslyAllowContainerNamespaceJoin?: boolean; }; type SandboxBrowserSettings = { enabled?: boolean; image?: string; containerPrefix?: string; /** Docker network for sandbox browser containers (default: fased-sandbox-browser). */ network?: string; cdpPort?: number; /** Optional CIDR allowlist for CDP ingress at the container edge (for example: 172.21.0.1/32). */ cdpSourceRange?: string; vncPort?: number; noVncPort?: number; headless?: boolean; enableNoVnc?: boolean; /** * Allow sandboxed sessions to target the host browser control server. * Default: false. */ allowHostControl?: boolean; /** * When true (default), sandboxed browser control will try to start/reattach to * the sandbox browser container when a tool call needs it. */ autoStart?: boolean; /** Max time to wait for CDP to become reachable after auto-start (ms). */ autoStartTimeoutMs?: number; /** Additional bind mounts for the browser container only. When set, replaces docker.binds for the browser container. */ binds?: string[]; }; type SandboxPruneSettings = { /** Prune if idle for more than N hours (0 disables). */idleHours?: number; /** Prune if older than N days (0 disables). */ maxAgeDays?: number; }; //#endregion //#region src/config/types.agents-shared.d.ts type AgentModelConfig = string | { /** Primary model (provider/model). */primary?: string; /** Per-agent fallback model (provider/model), stored as a one-entry list. */ fallbacks?: string[]; }; type AgentTaskModelRolesConfig = { /** Explicit model for planner-created cheap/check task runs (provider/model). */cheapCheck?: string; /** Explicit model for stronger task starts when the planner chooses strong-model. */ strong?: string; /** Explicit follow-up model when a cheap/check task escalates. */ escalation?: string; /** Explicit coding task model for future coding-specialized task runs. */ coding?: string; /** Explicit summarizer model for future summarization and compression task runs. */ summarizer?: string; }; type AgentModelProviderConfig = { /** Auth profile id attached to this Agent for this provider. */profileId?: string; /** Primary model for this Agent/provider pair (provider/model). */ primary?: string; /** Legacy fallback model for this Agent/provider pair (provider/model), stored as a one-entry list. */ fallbacks?: string[]; /** Provider-scoped task model roles for this Agent. */ taskModels?: AgentTaskModelRolesConfig; }; type AgentSandboxConfig = { mode?: "off" | "non-main" | "all"; /** Sandbox backend id. Docker is the default backend. */ backend?: string; /** Agent workspace access inside the sandbox. */ workspaceAccess?: "none" | "ro" | "rw"; /** * Session tools visibility for sandboxed sessions. * - "spawned": only allow session tools to target sessions spawned from this session (default) * - "all": allow session tools to target any session */ sessionToolsVisibility?: "spawned" | "all"; /** Container/workspace scope for sandbox isolation. */ scope?: "session" | "agent" | "shared"; /** Legacy alias for scope ("session" when true, "shared" when false). */ perSession?: boolean; workspaceRoot?: string; /** Docker-specific sandbox settings. */ docker?: SandboxDockerSettings; /** Optional sandboxed browser settings. */ browser?: SandboxBrowserSettings; /** Auto-prune sandbox settings. */ prune?: SandboxPruneSettings; }; //#endregion //#region src/config/types.queue.d.ts type QueueMode = "steer" | "followup" | "collect" | "steer-backlog" | "steer+backlog" | "queue" | "interrupt"; type QueueDropPolicy = "old" | "new" | "summarize"; type QueueModeByProvider = { whatsapp?: QueueMode; telegram?: QueueMode; discord?: QueueMode; irc?: QueueMode; googlechat?: QueueMode; slack?: QueueMode; signal?: QueueMode; imessage?: QueueMode; msteams?: QueueMode; webchat?: QueueMode; }; //#endregion //#region src/config/types.tts.d.ts type TtsProvider = "elevenlabs" | "openai" | "edge"; type TtsMode = "final" | "all"; type TtsAutoMode = "off" | "always" | "inbound" | "tagged"; type TtsModelOverrideConfig = { /** Enable model-provided overrides for TTS. */enabled?: boolean; /** Allow model-provided TTS text blocks. */ allowText?: boolean; /** Allow model-provided provider override (default: false). */ allowProvider?: boolean; /** Allow model-provided voice/voiceId override. */ allowVoice?: boolean; /** Allow model-provided modelId override. */ allowModelId?: boolean; /** Allow model-provided voice settings override. */ allowVoiceSettings?: boolean; /** Allow model-provided normalization or language overrides. */ allowNormalization?: boolean; /** Allow model-provided seed override. */ allowSeed?: boolean; }; type TtsConfig = { /** Auto-TTS mode (preferred). */auto?: TtsAutoMode; /** Legacy: enable auto-TTS when `auto` is not set. */ enabled?: boolean; /** Apply TTS to final replies only or to all replies (tool/block/final). */ mode?: TtsMode; /** Primary TTS provider (fallbacks are automatic). */ provider?: TtsProvider; /** Optional model override for TTS auto-summary (provider/model or alias). */ summaryModel?: string; /** Allow the model to override TTS parameters. */ modelOverrides?: TtsModelOverrideConfig; /** ElevenLabs configuration. */ elevenlabs?: { apiKey?: string; baseUrl?: string; voiceId?: string; modelId?: string; seed?: number; applyTextNormalization?: "auto" | "on" | "off"; languageCode?: string; voiceSettings?: { stability?: number; similarityBoost?: number; style?: number; useSpeakerBoost?: boolean; speed?: number; }; }; /** OpenAI configuration. */ openai?: { apiKey?: string; model?: string; voice?: string; }; /** Microsoft Edge (node-edge-tts) configuration. */ edge?: { /** Explicitly allow Edge TTS usage (no API key required). */enabled?: boolean; voice?: string; lang?: string; outputFormat?: string; pitch?: string; rate?: string; volume?: string; saveSubtitles?: boolean; proxy?: string; timeoutMs?: number; }; /** Optional path for local TTS user preferences JSON. */ prefsPath?: string; /** Hard cap for text sent to TTS (chars). */ maxTextLength?: number; /** API request timeout (ms). */ timeoutMs?: number; }; //#endregion //#region src/config/types.messages.d.ts type GroupChatConfig = { mentionPatterns?: string[]; historyLimit?: number; }; type DmConfig = { historyLimit?: number; }; type QueueConfig = { mode?: QueueMode; byChannel?: QueueModeByProvider; debounceMs?: number; /** Per-channel debounce overrides (ms). */ debounceMsByChannel?: InboundDebounceByProvider; cap?: number; drop?: QueueDropPolicy; }; type InboundDebounceByProvider = Record; type InboundDebounceConfig = { debounceMs?: number; byChannel?: InboundDebounceByProvider; }; type BroadcastStrategy = "parallel" | "sequential"; type BroadcastConfig = { /** Default processing strategy for broadcast peers. */strategy?: BroadcastStrategy; /** * Map peer IDs to arrays of agent IDs that should ALL process messages. * * Note: the index signature includes `undefined` so `strategy?: ...` remains type-safe. */ [peerId: string]: string[] | BroadcastStrategy | undefined; }; type StatusReactionsEmojiConfig = { thinking?: string; tool?: string; coding?: string; web?: string; done?: string; error?: string; stallSoft?: string; stallHard?: string; }; type StatusReactionsTimingConfig = { /** Debounce interval for intermediate states (ms). Default: 700. */debounceMs?: number; /** Soft stall warning timeout (ms). Default: 25000. */ stallSoftMs?: number; /** Hard stall warning timeout (ms). Default: 60000. */ stallHardMs?: number; /** How long to hold done emoji before cleanup (ms). Default: 1500. */ doneHoldMs?: number; /** How long to hold error emoji before cleanup (ms). Default: 2500. */ errorHoldMs?: number; }; type StatusReactionsConfig = { /** Enable lifecycle status reactions (default: false). */enabled?: boolean; /** Override default emojis. */ emojis?: StatusReactionsEmojiConfig; /** Override default timing. */ timing?: StatusReactionsTimingConfig; }; type MessagesConfig = { /** @deprecated Use `whatsapp.messagePrefix` (WhatsApp-only inbound prefix). */messagePrefix?: string; /** * Prefix auto-added to all outbound replies. * * - string: explicit prefix (may include template variables) * - special value: `"auto"` derives `[{agents.list[].identity.name}]` for the routed agent (when set) * * Supported template variables (case-insensitive): * - `{model}` - short model name (e.g., `claude-opus-4-6`, `gpt-4o`) * - `{modelFull}` - full model identifier (e.g., `anthropic/claude-opus-4-6`) * - `{provider}` - provider name (e.g., `anthropic`, `openai`) * - `{thinkingLevel}` or `{think}` - current thinking level (`high`, `low`, `off`) * - `{identity.name}` or `{identityName}` - agent identity name * * Example: `"[{model} | think:{thinkingLevel}]"` → `"[claude-opus-4-6 | think:high]"` * * Unresolved variables remain as literal text (e.g., `{model}` if context unavailable). * * Default: none */ responsePrefix?: string; groupChat?: GroupChatConfig; queue?: QueueConfig; /** Debounce rapid inbound messages per sender (global + per-channel overrides). */ inbound?: InboundDebounceConfig; /** Emoji reaction used to acknowledge inbound messages (empty disables). */ ackReaction?: string; /** When to send ack reactions. Default: "group-mentions". */ ackReactionScope?: "group-mentions" | "group-all" | "direct" | "all"; /** Remove ack reaction after reply is sent (default: false). */ removeAckAfterReply?: boolean; /** Lifecycle status reactions configuration. */ statusReactions?: StatusReactionsConfig; /** When true, suppress ⚠️ tool-error warnings from being shown to the user. Default: false. */ suppressToolErrors?: boolean; /** Text-to-speech settings for outbound replies. */ tts?: TtsConfig; }; type NativeCommandsSetting = boolean | "auto"; type CommandOwnerDisplay = "raw" | "hash"; /** * Per-provider allowlist for command authorization. * Keys are channel IDs (e.g., "discord", "whatsapp") or "*" for global default. * Values are arrays of sender IDs allowed to use commands on that channel. */ type CommandAllowFrom = Record>; type CommandsConfig = { /** Enable native command registration when supported (default: "auto"). */native?: NativeCommandsSetting; /** Enable native skill command registration when supported (default: "auto"). */ nativeSkills?: NativeCommandsSetting; /** Enable text command parsing (default: true). */ text?: boolean; /** Allow bash chat command (`!`; `/bash` alias) (default: false). */ bash?: boolean; /** How long bash waits before backgrounding (default: 2000; 0 backgrounds immediately). */ bashForegroundMs?: number; /** Allow /config command (default: false). */ config?: boolean; /** Allow /debug command (default: false). */ debug?: boolean; /** Allow restart commands/tools (default: true). */ restart?: boolean; /** Enforce access-group allowlists/policies for commands (default: true). */ useAccessGroups?: boolean; /** Explicit owner allowlist for owner-only tools/commands (channel-native IDs). */ ownerAllowFrom?: Array; /** How owner IDs are rendered in system prompts. */ ownerDisplay?: CommandOwnerDisplay; /** Secret used to key owner ID hashes when ownerDisplay is "hash". */ ownerDisplaySecret?: string; /** * Per-provider allowlist restricting who can use slash commands. * If set, overrides the channel's allowFrom for command authorization. * Use "*" key for global default, provider-specific keys override the global. * Example: { "*": ["user1"], discord: ["user:123"] } */ allowFrom?: CommandAllowFrom; }; type ProviderCommandsConfig = { /** Override native command registration for this provider (bool or "auto"). */native?: NativeCommandsSetting; /** Override native skill command registration for this provider (bool or "auto"). */ nativeSkills?: NativeCommandsSetting; }; //#endregion //#region src/config/types.agents.d.ts type AgentConfig = { id: string; default?: boolean; name?: string; workspace?: string; agentDir?: string; /** Legacy migration field for old provider-scoped model settings. */ activeModelProvider?: string; /** Legacy migration field for old provider-scoped model settings. */ modelProviders?: Record; /** Per-agent primary model and one fallback model. Provider is inferred from model refs. */ model?: AgentModelConfig; /** Per-agent task model roles. Provider is inferred from model refs. */ taskModels?: AgentDefaultsConfig["taskModels"]; /** Default thinking level when no /think directive is present. */ thinkingDefault?: AgentDefaultsConfig["thinkingDefault"]; /** Legacy elevated/reasoning default. Prefer thinkingDefault for new configs. */ reasoningDefault?: "off" | "minimal" | "low" | "medium" | "high" | "xhigh" | "max" | "ultra"; /** Default fast-mode preference when no runtime override is present. */ fastModeDefault?: boolean; /** Optional allowlist of skills for this agent (omit = all skills; empty = none). */ skills?: string[]; memorySearch?: MemorySearchConfig; /** Human-like delay between block replies for this agent. */ humanDelay?: HumanDelayConfig; /** Optional per-agent heartbeat overrides. */ heartbeat?: AgentDefaultsConfig["heartbeat"]; identity?: IdentityConfig; groupChat?: GroupChatConfig; subagents?: { /** Allow spawning sub-agents under other agent ids. Use "*" to allow any. */allowAgents?: string[]; /** Require sessions_spawn callers to pass an explicit agentId. */ requireAgentId?: boolean; /** Per-agent default model for spawned sub-agents (string or {primary,fallbacks}). */ model?: AgentModelConfig; }; /** Optional per-agent sandbox overrides. */ sandbox?: AgentSandboxConfig; /** Optional per-agent stream params (e.g. cacheRetention, temperature). */ params?: Record; tools?: AgentToolsConfig; /** Optional per-agent strict-agentic warning policy. */ strictAgentic?: AgentDefaultsConfig["strictAgentic"]; }; type AgentsConfig = { defaults?: AgentDefaultsConfig; list?: AgentConfig[]; }; type AgentBinding = { agentId: string; comment?: string; match: { channel: string; accountId?: string; peer?: { kind: ChatType; id: string; }; guildId?: string; teamId?: string; /** Discord role IDs used for role-based routing. */ roles?: string[]; }; }; //#endregion //#region src/config/types.approvals.d.ts type ExecApprovalForwardingMode = "session" | "targets" | "both"; type ExecApprovalForwardTarget = { /** Channel id (e.g. "discord", "slack", or plugin channel id). */channel: string; /** Destination id (channel id, user id, etc. depending on channel). */ to: string; /** Optional account id for multi-account channels. */ accountId?: string; /** Optional thread id to reply inside a thread. */ threadId?: string | number; }; type ExecApprovalForwardingConfig = { /** Enable forwarding exec approvals to chat channels. Default: false. */enabled?: boolean; /** Delivery mode (session=origin chat, targets=config targets, both=both). Default: session. */ mode?: ExecApprovalForwardingMode; /** Only forward approvals for these agent IDs. Omit = all agents. */ agentFilter?: string[]; /** Only forward approvals matching these session key patterns (substring or regex). */ sessionFilter?: string[]; /** Explicit delivery targets (used when mode includes targets). */ targets?: ExecApprovalForwardTarget[]; }; type ApprovalsConfig = { exec?: ExecApprovalForwardingConfig; }; //#endregion //#region src/config/types.auth.d.ts type AuthProfileConfig = { provider: string; /** * Credential type expected in auth-profiles.json for this profile id. * - api_key: static provider API key * - oauth: refreshable OAuth credentials (access+refresh+expires) * - token: static bearer-style token (optionally expiring; no refresh) */ mode: "api_key" | "oauth" | "token"; email?: string; }; type AuthConfig = { profiles?: Record; order?: Record; cooldowns?: { /** Default billing backoff (hours). Default: 5. */billingBackoffHours?: number; /** Optional per-provider billing backoff (hours). */ billingBackoffHoursByProvider?: Record; /** Legacy-compatible overload cooldown override (ms). New code uses standard profile cooldown windows. */ overloadedBackoffMs?: number; /** Legacy-compatible cap for overload profile rotations. */ overloadedProfileRotations?: number; /** Legacy-compatible cap for rate-limit profile rotations. */ rateLimitedProfileRotations?: number; /** Billing backoff cap (hours). Default: 24. */ billingMaxHours?: number; /** * Failure window for backoff counters (hours). If no failures occur within * this window, counters reset. Default: 24. */ failureWindowHours?: number; }; }; //#endregion //#region src/config/types.browser.d.ts type BrowserProfileConfig = { /** CDP port for this profile. Allocated once at creation, persisted permanently. */cdpPort?: number; /** CDP URL for this profile (use for remote Chrome). */ cdpUrl?: string; /** Profile driver (default: fased). */ driver?: "fased" | "extension"; /** Profile color (hex). Auto-assigned at creation. */ color: string; }; type BrowserSnapshotDefaults = { /** Default snapshot mode (applies when mode is not provided). */mode?: "efficient"; }; type BrowserSsrFPolicyConfig = { /** Legacy alias for private-network access. Prefer dangerouslyAllowPrivateNetwork. */allowPrivateNetwork?: boolean; /** If true, permit browser navigation to private/internal networks. Default: true */ dangerouslyAllowPrivateNetwork?: boolean; /** * Explicitly allowed hostnames (exact-match), including blocked names like localhost. * Example: ["localhost", "metadata.internal"] */ allowedHostnames?: string[]; /** * Hostname allowlist patterns for browser navigation. * Supports exact hosts and "*.example.com" wildcard subdomains. */ hostnameAllowlist?: string[]; }; type BrowserConfig = { enabled?: boolean; /** If false, disable browser act:evaluate (arbitrary JS). Default: true */ evaluateEnabled?: boolean; /** Base URL of the CDP endpoint (for remote browsers). Default: loopback CDP on the derived port. */ cdpUrl?: string; /** Remote CDP HTTP timeout (ms). Default: 1500. */ remoteCdpTimeoutMs?: number; /** Remote CDP WebSocket handshake timeout (ms). Default: max(remoteCdpTimeoutMs * 2, 2000). */ remoteCdpHandshakeTimeoutMs?: number; /** Accent color for the fased browser profile (hex). Default: #FF4500 */ color?: string; /** Override the browser executable path (all platforms). */ executablePath?: string; /** Start Chrome headless (best-effort). Default: false */ headless?: boolean; /** Pass --no-sandbox to Chrome (Linux containers). Default: false */ noSandbox?: boolean; /** If true: never launch; only attach to an existing browser. Default: false */ attachOnly?: boolean; /** Default profile to use when profile param is omitted. Default: "chrome" */ defaultProfile?: string; /** Named browser profiles with explicit CDP ports or URLs. */ profiles?: Record; /** Default snapshot options (applied by the browser tool/CLI when unset). */ snapshotDefaults?: BrowserSnapshotDefaults; /** SSRF policy for browser navigation/open-tab operations. */ ssrfPolicy?: BrowserSsrFPolicyConfig; /** * Additional Chrome launch arguments. * Useful for stealth flags, window size overrides, or custom user-agent strings. * Example: ["--window-size=1920,1080", "--disable-infobars"] */ extraArgs?: string[]; }; //#endregion //#region src/discord/pluralkit.d.ts type DiscordPluralKitConfig = { enabled?: boolean; token?: string; }; //#endregion //#region src/config/types.discord.d.ts type DiscordStreamMode = "off" | "partial" | "block" | "progress"; type DiscordDmConfig = { /** If false, ignore all incoming Discord DMs. Default: true. */enabled?: boolean; /** Direct message access policy (default: pairing). */ policy?: DmPolicy; /** Allowlist for DM senders (ids or names). */ allowFrom?: string[]; /** If true, allow group DMs (default: false). */ groupEnabled?: boolean; /** Optional allowlist for group DM channels (ids or slugs). */ groupChannels?: string[]; }; type DiscordGuildChannelConfig = { allow?: boolean; requireMention?: boolean; /** Optional tool policy overrides for this channel. */ tools?: GroupToolPolicyConfig; toolsBySender?: GroupToolPolicyBySenderConfig; /** If specified, only load these skills for this channel. Omit = all skills; empty = no skills. */ skills?: string[]; /** If false, disable the bot for this channel. */ enabled?: boolean; /** Optional allowlist for channel senders (ids or names). */ users?: string[]; /** Optional allowlist for channel senders by role ID. */ roles?: string[]; /** Optional system prompt snippet for this channel. */ systemPrompt?: string; /** If false, omit thread starter context for this channel (default: true). */ includeThreadStarter?: boolean; }; type DiscordReactionNotificationMode = "off" | "own" | "all" | "allowlist"; type DiscordGuildEntry = { slug?: string; requireMention?: boolean; /** Optional tool policy overrides for this guild (used when channel override is missing). */ tools?: GroupToolPolicyConfig; toolsBySender?: GroupToolPolicyBySenderConfig; /** Reaction notification mode (off|own|all|allowlist). Default: own. */ reactionNotifications?: DiscordReactionNotificationMode; /** Optional allowlist for guild senders (ids or names). */ users?: string[]; /** Optional allowlist for guild senders by role ID. */ roles?: string[]; channels?: Record; }; type DiscordActionConfig = { reactions?: boolean; stickers?: boolean; polls?: boolean; permissions?: boolean; messages?: boolean; threads?: boolean; pins?: boolean; search?: boolean; memberInfo?: boolean; roleInfo?: boolean; roles?: boolean; channelInfo?: boolean; voiceStatus?: boolean; events?: boolean; moderation?: boolean; emojiUploads?: boolean; stickerUploads?: boolean; channels?: boolean; /** Enable bot presence/activity changes (default: false). */ presence?: boolean; }; type DiscordIntentsConfig = { /** Enable Guild Presences privileged intent (requires Portal opt-in). Default: false. */presence?: boolean; /** Enable Guild Members privileged intent (requires Portal opt-in). Default: false. */ guildMembers?: boolean; }; type DiscordVoiceAutoJoinConfig = { /** Guild ID that owns the voice channel. */guildId: string; /** Voice channel ID to join. */ channelId: string; }; type DiscordVoiceConfig = { /** Enable Discord voice channel conversations (default: true). */enabled?: boolean; /** Voice channels to auto-join on startup. */ autoJoin?: DiscordVoiceAutoJoinConfig[]; /** Enable/disable DAVE end-to-end encryption (default: true; Discord may require this). */ daveEncryption?: boolean; /** Consecutive decrypt failures before DAVE session reinitialization (default: 24). */ decryptionFailureTolerance?: number; /** Optional TTS overrides for Discord voice output. */ tts?: TtsConfig; }; type DiscordExecApprovalConfig = { /** Enable exec approval forwarding to Discord DMs. Default: false. */enabled?: boolean; /** Discord user IDs to receive approval prompts. Required if enabled. */ approvers?: string[]; /** Only forward approvals for these agent IDs. Omit = all agents. */ agentFilter?: string[]; /** Only forward approvals matching these session key patterns (substring or regex). */ sessionFilter?: string[]; /** Delete approval DMs after approval, denial, or timeout. Default: false. */ cleanupAfterResolve?: boolean; /** Where to send approval prompts. "dm" sends to approver DMs (default), "channel" sends to the * originating Discord channel, "both" sends to both. When target is "channel" or "both", buttons * are only usable by configured approvers; other users receive an ephemeral denial. */ target?: "dm" | "channel" | "both"; }; type DiscordAgentComponentsConfig = { /** Enable agent-controlled interactive components (buttons, select menus). Default: true. */enabled?: boolean; }; type DiscordUiComponentsConfig = { /** Accent color used by Discord component containers (hex). */accentColor?: string; }; type DiscordUiConfig = { components?: DiscordUiComponentsConfig; }; type DiscordThreadBindingsConfig = { /** * Enable Discord thread binding features (/focus, thread-bound delivery, and * thread-bound subagent session flows). Overrides session.threadBindings.enabled * when set. */ enabled?: boolean; /** * Inactivity window for thread-bound sessions in hours. * Session auto-unfocuses after this amount of idle time. Set to 0 to disable. Default: 24. */ idleHours?: number; /** * Optional hard max age for thread-bound sessions in hours. * Session auto-unfocuses once this age is reached even if active. Set to 0 to disable. Default: 0. */ maxAgeHours?: number; /** * Allow `sessions_spawn({ thread: true })` to auto-create + bind Discord * threads for subagent sessions. Default: false (opt-in). */ spawnSubagentSessions?: boolean; /** * Allow `/acp spawn` to auto-create + bind Discord threads for ACP * sessions. Default: false (opt-in). */ spawnAcpSessions?: boolean; }; type DiscordSlashCommandConfig = { /** Reply ephemerally (default: true). */ephemeral?: boolean; }; type DiscordAccountConfig = { /** Optional display name for this account (used in CLI/UI lists). */name?: string; /** Optional provider capability tags used for agent/runtime guidance. */ capabilities?: string[]; /** Markdown formatting overrides (tables). */ markdown?: MarkdownConfig; /** Override native command registration for Discord (bool or "auto"). */ commands?: ProviderCommandsConfig; /** Allow channel-initiated config writes (default: true). */ configWrites?: boolean; /** If false, do not start this Discord account. Default: true. */ enabled?: boolean; token?: string; /** HTTP(S) proxy URL for Discord gateway WebSocket connections. */ proxy?: string; /** Allow bot-authored messages to trigger replies (default: false). */ allowBots?: boolean; /** * Break-glass override: allow mutable identity matching (names/tags/slugs) in allowlists. * Default behavior is ID-only matching. */ dangerouslyAllowNameMatching?: boolean; /** * Controls how guild channel messages are handled: * - "open": guild channels bypass allowlists; mention-gating applies * - "disabled": block all guild channel messages * - "allowlist": only allow channels present in discord.guilds.*.channels */ groupPolicy?: GroupPolicy; /** Outbound text chunk size (chars). Default: 2000. */ textChunkLimit?: number; /** Chunking mode: "length" (default) splits by size; "newline" splits on every newline. */ chunkMode?: "length" | "newline"; /** Disable block streaming for this account. */ blockStreaming?: boolean; /** * Live stream preview mode: * - "off": disable preview updates * - "partial": edit a single preview message * - "block": stream in chunked preview updates * - "progress": alias that maps to "partial" on Discord * * Legacy boolean values are still accepted and auto-migrated. */ streaming?: DiscordStreamMode | boolean; /** * @deprecated Legacy key; migrated automatically to `streaming`. */ streamMode?: "partial" | "block" | "off"; /** Chunking config for Discord stream previews in `streaming: "block"`. */ draftChunk?: BlockStreamingChunkConfig; /** Merge streamed block replies before sending. */ blockStreamingCoalesce?: BlockStreamingCoalesceConfig; /** * Soft max line count per Discord message. * Discord clients can clip/collapse very tall messages; splitting by lines * keeps replies readable in-channel. Default: 17. */ maxLinesPerMessage?: number; mediaMaxMb?: number; historyLimit?: number; /** Max DM turns to keep as history context. */ dmHistoryLimit?: number; /** Per-DM config overrides keyed by user ID. */ dms?: Record; /** Retry policy for outbound Discord API calls. */ retry?: OutboundRetryConfig; /** Per-action tool gating (default: true for all). */ actions?: DiscordActionConfig; /** Control reply threading when reply tags are present (off|first|all). */ replyToMode?: ReplyToMode; /** * Alias for dm.policy (prefer this so it inherits cleanly via base->account shallow merge). * Legacy key: channels.discord.dm.policy. */ dmPolicy?: DmPolicy; /** * Alias for dm.allowFrom (prefer this so it inherits cleanly via base->account shallow merge). * Legacy key: channels.discord.dm.allowFrom. */ allowFrom?: string[]; /** Default delivery target for CLI --deliver when no explicit --reply-to is provided. */ defaultTo?: string; dm?: DiscordDmConfig; /** New per-guild config keyed by guild id or slug. */ guilds?: Record; /** Heartbeat visibility settings for this channel. */ heartbeat?: ChannelHeartbeatVisibilityConfig; /** Exec approval forwarding configuration. */ execApprovals?: DiscordExecApprovalConfig; /** Agent-controlled interactive components (buttons, select menus). */ agentComponents?: DiscordAgentComponentsConfig; /** Discord UI customization (components, modals, etc.). */ ui?: DiscordUiConfig; /** Slash command configuration. */ slashCommand?: DiscordSlashCommandConfig; /** Thread binding lifecycle settings (focus/subagent thread sessions). */ threadBindings?: DiscordThreadBindingsConfig; /** Privileged Gateway Intents (must also be enabled in Discord Developer Portal). */ intents?: DiscordIntentsConfig; /** Voice channel conversation settings. */ voice?: DiscordVoiceConfig; /** PluralKit identity resolution for proxied messages. */ pluralkit?: DiscordPluralKitConfig; /** Outbound response prefix override for this channel/account. */ responsePrefix?: string; /** * Per-channel ack reaction override. * Discord supports both unicode emoji and custom emoji names. */ ackReaction?: string; /** Bot activity status text (e.g. "Watching X"). */ activity?: string; /** Bot status (online|dnd|idle|invisible). Defaults to online when presence is configured. */ status?: "online" | "dnd" | "idle" | "invisible"; /** Activity type (0=Game, 1=Streaming, 2=Listening, 3=Watching, 4=Custom, 5=Competing). Defaults to 4 (Custom) when activity is set. */ activityType?: 0 | 1 | 2 | 3 | 4 | 5; /** Streaming URL (Twitch/YouTube). Required when activityType=1. */ activityUrl?: string; }; type DiscordConfig = { /** Optional per-account Discord configuration (multi-account). */accounts?: Record; } & DiscordAccountConfig; //#endregion //#region src/config/types.googlechat.d.ts type GoogleChatDmConfig = { /** If false, ignore all incoming Google Chat DMs. Default: true. */enabled?: boolean; /** Direct message access policy (default: pairing). */ policy?: DmPolicy; /** Allowlist for DM senders (user ids or emails). */ allowFrom?: Array; }; type GoogleChatGroupConfig = { /** If false, disable the bot in this space. (Alias for allow: false.) */enabled?: boolean; /** Legacy allow toggle; prefer enabled. */ allow?: boolean; /** Require mentioning the bot to trigger replies. */ requireMention?: boolean; /** Allowlist of users that can invoke the bot in this space. */ users?: Array; /** Optional system prompt for this space. */ systemPrompt?: string; }; type GoogleChatActionConfig = { reactions?: boolean; }; type GoogleChatAccountConfig = { /** Optional display name for this account (used in CLI/UI lists). */name?: string; /** Optional provider capability tags used for agent/runtime guidance. */ capabilities?: string[]; /** Allow channel-initiated config writes (default: true). */ configWrites?: boolean; /** If false, do not start this Google Chat account. Default: true. */ enabled?: boolean; /** Allow bot-authored messages to trigger replies (default: false). */ allowBots?: boolean; /** * Break-glass override: allow mutable principal matching (raw email entries) in allowlists. * Default behavior is ID-only matching. */ dangerouslyAllowNameMatching?: boolean; /** Default mention requirement for space messages (default: true). */ requireMention?: boolean; /** * Controls how space messages are handled: * - "open": spaces bypass allowlists; mention-gating applies * - "disabled": block all space messages * - "allowlist": only allow spaces present in channels.googlechat.groups */ groupPolicy?: GroupPolicy; /** Optional allowlist for space senders (user ids or emails). */ groupAllowFrom?: Array; /** Default delivery target for CLI --deliver when no explicit --reply-to is provided. */ defaultTo?: string; /** Per-space configuration keyed by space id or name. */ groups?: Record; /** Service account JSON (inline string, object, or secret reference). */ serviceAccount?: string | Record | SecretRef; /** Explicit secret reference for service account JSON. */ serviceAccountRef?: SecretRef; /** Service account JSON file path. */ serviceAccountFile?: string; /** Webhook audience type (app-url or project-number). */ audienceType?: "app-url" | "project-number"; /** Audience value (app URL or project number). */ audience?: string; /** Google Chat webhook path (default: /googlechat). */ webhookPath?: string; /** Google Chat webhook URL (used to derive the path). */ webhookUrl?: string; /** Optional bot user resource name (users/...). */ botUser?: string; /** Max space messages to keep as history context (0 disables). */ historyLimit?: number; /** Max DM turns to keep as history context. */ dmHistoryLimit?: number; /** Per-DM config overrides keyed by user id. */ dms?: Record; /** Outbound text chunk size (chars). Default: 4000. */ textChunkLimit?: number; /** Chunking mode: "length" (default) splits by size; "newline" splits on every newline. */ chunkMode?: "length" | "newline"; blockStreaming?: boolean; /** Merge streamed block replies before sending. */ blockStreamingCoalesce?: BlockStreamingCoalesceConfig; mediaMaxMb?: number; /** Control reply threading when reply tags are present (off|first|all). */ replyToMode?: ReplyToMode; /** Per-action tool gating (default: true for all). */ actions?: GoogleChatActionConfig; dm?: GoogleChatDmConfig; /** * Typing indicator mode (default: "message"). * - "none": No indicator * - "message": Send "_ is typing..._" then edit with response * - "reaction": React with 👀 to user message, remove on reply * NOTE: Reaction mode requires user OAuth (not supported with service account auth). * If configured, falls back to message mode with a warning. */ typingIndicator?: "none" | "message" | "reaction"; /** Outbound response prefix override for this channel/account. */ responsePrefix?: string; }; type GoogleChatConfig = { /** Optional per-account Google Chat configuration (multi-account). */accounts?: Record; /** Optional default account id when multiple accounts are configured. */ defaultAccount?: string; } & GoogleChatAccountConfig; //#endregion //#region src/config/types.imessage.d.ts type IMessageAccountConfig = { /** Optional display name for this account (used in CLI/UI lists). */name?: string; /** Optional provider capability tags used for agent/runtime guidance. */ capabilities?: string[]; /** Markdown formatting overrides (tables). */ markdown?: MarkdownConfig; /** Allow channel-initiated config writes (default: true). */ configWrites?: boolean; /** If false, do not start this iMessage account. Default: true. */ enabled?: boolean; /** imsg CLI binary path (default: imsg). */ cliPath?: string; /** Optional Messages db path override. */ dbPath?: string; /** Remote SSH host token for SCP attachment fetches (`host` or `user@host`). */ remoteHost?: string; /** Optional default send service (imessage|sms|auto). */ service?: "imessage" | "sms" | "auto"; /** Optional default region (used when sending SMS). */ region?: string; /** Direct message access policy (default: pairing). */ dmPolicy?: DmPolicy; /** Optional allowlist for inbound handles or chat_id targets. */ allowFrom?: Array; /** Default delivery target for CLI --deliver when no explicit --reply-to is provided. */ defaultTo?: string; /** Optional allowlist for group senders or chat_id targets. */ groupAllowFrom?: Array; /** * Controls how group messages are handled: * - "open": groups bypass allowFrom; mention-gating applies * - "disabled": block all group messages entirely * - "allowlist": only allow group messages from senders in groupAllowFrom/allowFrom */ groupPolicy?: GroupPolicy; /** Max group messages to keep as history context (0 disables). */ historyLimit?: number; /** Max DM turns to keep as history context. */ dmHistoryLimit?: number; /** Per-DM config overrides keyed by user ID. */ dms?: Record; /** Include attachments + reactions in watch payloads. */ includeAttachments?: boolean; /** Allowed local iMessage attachment roots (supports single-segment `*` wildcards). */ attachmentRoots?: string[]; /** Allowed remote iMessage attachment roots for SCP fetches (supports `*`). */ remoteAttachmentRoots?: string[]; /** Max outbound media size in MB. */ mediaMaxMb?: number; /** Timeout for probe/RPC operations in milliseconds (default: 10000). */ probeTimeoutMs?: number; /** Outbound text chunk size (chars). Default: 4000. */ textChunkLimit?: number; /** Chunking mode: "length" (default) splits by size; "newline" splits on every newline. */ chunkMode?: "length" | "newline"; blockStreaming?: boolean; /** Merge streamed block replies before sending. */ blockStreamingCoalesce?: BlockStreamingCoalesceConfig; groups?: Record; /** Heartbeat visibility settings for this channel. */ heartbeat?: ChannelHeartbeatVisibilityConfig; /** Outbound response prefix override for this channel/account. */ responsePrefix?: string; }; type IMessageConfig = { /** Optional per-account iMessage configuration (multi-account). */accounts?: Record; } & IMessageAccountConfig; //#endregion //#region src/config/types.channel-messaging-common.d.ts type CommonChannelMessagingConfig = { /** Optional display name for this account (used in CLI/UI lists). */name?: string; /** Optional provider capability tags used for agent/runtime guidance. */ capabilities?: string[]; /** Markdown formatting overrides (tables). */ markdown?: MarkdownConfig; /** Allow channel-initiated config writes (default: true). */ configWrites?: boolean; /** If false, do not start this account. Default: true. */ enabled?: boolean; /** Direct message access policy (default: pairing). */ dmPolicy?: DmPolicy; /** Optional allowlist for inbound DM senders. */ allowFrom?: Array; /** Default delivery target for CLI --deliver when no explicit --reply-to is provided. */ defaultTo?: string; /** Optional allowlist for group/channel senders. */ groupAllowFrom?: Array; /** Group/channel message handling policy. */ groupPolicy?: GroupPolicy; /** Max group/channel messages to keep as history context (0 disables). */ historyLimit?: number; /** Max DM turns to keep as history context. */ dmHistoryLimit?: number; /** Per-DM config overrides keyed by sender ID. */ dms?: Record; /** Outbound text chunk size (chars). */ textChunkLimit?: number; /** Chunking mode: "length" (default) splits by size; "newline" splits on every newline. */ chunkMode?: "length" | "newline"; blockStreaming?: boolean; /** Merge streamed block replies before sending. */ blockStreamingCoalesce?: BlockStreamingCoalesceConfig; /** Heartbeat visibility settings for this channel. */ heartbeat?: ChannelHeartbeatVisibilityConfig; /** Outbound response prefix override for this channel/account. */ responsePrefix?: string; /** Max outbound media size in MB. */ mediaMaxMb?: number; }; //#endregion //#region src/config/types.irc.d.ts type IrcAccountConfig = CommonChannelMessagingConfig & { /** IRC server hostname (example: irc.libera.chat). */host?: string; /** IRC server port (default: 6697 with TLS, otherwise 6667). */ port?: number; /** Use TLS for IRC connection (default: true). */ tls?: boolean; /** IRC nickname to identify this bot. */ nick?: string; /** IRC USER field username (defaults to nick). */ username?: string; /** IRC USER field realname (default: FasedAgent). */ realname?: string; /** Optional IRC server password (sensitive). */ password?: string; /** Optional file path containing IRC server password. */ passwordFile?: string; /** Optional NickServ identify/register settings. */ nickserv?: { /** Enable NickServ identify/register after connect (default: enabled when password is set). */enabled?: boolean; /** NickServ service nick (default: NickServ). */ service?: string; /** NickServ password (sensitive). */ password?: string; /** Optional file path containing NickServ password. */ passwordFile?: string; /** If true, send NickServ REGISTER on connect. */ register?: boolean; /** Email used with NickServ REGISTER. */ registerEmail?: string; }; /** Auto-join channel list at connect (example: ["#fased"]). */ channels?: string[]; /** Outbound text chunk size (chars). Default: 350. */ textChunkLimit?: number; groups?: Record; skills?: string[]; enabled?: boolean; systemPrompt?: string; }>; /** Optional mention patterns specific to IRC channel messages. */ mentionPatterns?: string[]; }; type IrcConfig = { /** Optional per-account IRC configuration (multi-account). */accounts?: Record; } & IrcAccountConfig; //#endregion //#region src/config/types.msteams.d.ts type MSTeamsWebhookConfig = { /** Port for the webhook server. Default: 3978. */port?: number; /** Path for the messages endpoint. Default: /api/messages. */ path?: string; }; /** Reply style for MS Teams messages. */ type MSTeamsReplyStyle = "thread" | "top-level"; /** Channel-level config for MS Teams. */ type MSTeamsChannelConfig = { /** Require @mention to respond. Default: true. */requireMention?: boolean; /** Optional tool policy overrides for this channel. */ tools?: GroupToolPolicyConfig; toolsBySender?: GroupToolPolicyBySenderConfig; /** Reply style: "thread" replies to the message, "top-level" posts a new message. */ replyStyle?: MSTeamsReplyStyle; }; /** Team-level config for MS Teams. */ type MSTeamsTeamConfig = { /** Default requireMention for channels in this team. */requireMention?: boolean; /** Default tool policy for channels in this team. */ tools?: GroupToolPolicyConfig; toolsBySender?: GroupToolPolicyBySenderConfig; /** Default reply style for channels in this team. */ replyStyle?: MSTeamsReplyStyle; /** Per-channel overrides. Key is conversation ID (e.g., "19:...@thread.tacv2"). */ channels?: Record; }; type MSTeamsConfig = { /** If false, do not start the MS Teams provider. Default: true. */enabled?: boolean; /** Optional provider capability tags used for agent/runtime guidance. */ capabilities?: string[]; /** * Break-glass override: allow mutable identity matching (display names/UPNs) in allowlists. * Default behavior is ID-only matching. */ dangerouslyAllowNameMatching?: boolean; /** Markdown formatting overrides (tables). */ markdown?: MarkdownConfig; /** Allow channel-initiated config writes (default: true). */ configWrites?: boolean; /** Azure Bot App ID (from Azure Bot registration). */ appId?: string; /** Azure Bot App Password / Client Secret. */ appPassword?: string; /** Azure AD Tenant ID (for single-tenant bots). */ tenantId?: string; /** Webhook server configuration. */ webhook?: MSTeamsWebhookConfig; /** Direct message access policy (default: pairing). */ dmPolicy?: DmPolicy; /** Allowlist for DM senders (AAD object IDs or UPNs). */ allowFrom?: Array; /** Default delivery target for CLI --deliver when no explicit --reply-to is provided. */ defaultTo?: string; /** Optional allowlist for group/channel senders (AAD object IDs or UPNs). */ groupAllowFrom?: Array; /** * Controls how group/channel messages are handled: * - "open": groups bypass allowFrom; mention-gating applies * - "disabled": block all group messages * - "allowlist": only allow group messages from senders in groupAllowFrom/allowFrom */ groupPolicy?: GroupPolicy; /** Outbound text chunk size (chars). Default: 4000. */ textChunkLimit?: number; /** Chunking mode: "length" (default) splits by size; "newline" splits on every newline. */ chunkMode?: "length" | "newline"; /** Merge streamed block replies before sending. */ blockStreamingCoalesce?: BlockStreamingCoalesceConfig; /** * Allowed host suffixes for inbound attachment downloads. * Use ["*"] to allow any host (not recommended). */ mediaAllowHosts?: Array; /** * Allowed host suffixes for attaching Authorization headers to inbound media retries. * Use specific hosts only; avoid multi-tenant suffixes. */ mediaAuthAllowHosts?: Array; /** Default: require @mention to respond in channels/groups. */ requireMention?: boolean; /** Max group/channel messages to keep as history context (0 disables). */ historyLimit?: number; /** Max DM turns to keep as history context. */ dmHistoryLimit?: number; /** Per-DM config overrides keyed by user ID. */ dms?: Record; /** Default reply style: "thread" replies to the message, "top-level" posts a new message. */ replyStyle?: MSTeamsReplyStyle; /** Per-team config. Key is team ID (from the /team/ URL path segment). */ teams?: Record; /** Max media size in MB (default: 100MB for OneDrive upload support). */ mediaMaxMb?: number; /** Preserve original inbound attachment filenames when saving Teams media. */ preserveFilenames?: boolean; /** SharePoint site ID for file uploads in group chats/channels (e.g., "contoso.sharepoint.com,guid1,guid2"). */ sharePointSiteId?: string; /** Heartbeat visibility settings for this channel. */ heartbeat?: ChannelHeartbeatVisibilityConfig; /** Outbound response prefix override for this channel/account. */ responsePrefix?: string; }; //#endregion //#region src/config/types.signal.d.ts type SignalReactionNotificationMode = "off" | "own" | "all" | "allowlist"; type SignalReactionLevel = "off" | "ack" | "minimal" | "extensive"; type SignalAccountConfig = CommonChannelMessagingConfig & { /** Optional explicit E.164 account for signal-cli. */account?: string; /** Optional full base URL for signal-cli HTTP daemon. */ httpUrl?: string; /** HTTP host for signal-cli daemon (default 127.0.0.1). */ httpHost?: string; /** HTTP port for signal-cli daemon (default 8080). */ httpPort?: number; /** signal-cli binary path (default: signal-cli). */ cliPath?: string; /** Auto-start signal-cli daemon (default: true if httpUrl not set). */ autoStart?: boolean; /** Max time to wait for signal-cli daemon startup (ms, cap 120000). */ startupTimeoutMs?: number; receiveMode?: "on-start" | "manual"; ignoreAttachments?: boolean; ignoreStories?: boolean; sendReadReceipts?: boolean; /** Outbound text chunk size (chars). Default: 4000. */ textChunkLimit?: number; /** Reaction notification mode (off|own|all|allowlist). Default: own. */ reactionNotifications?: SignalReactionNotificationMode; /** Allowlist for reaction notifications when mode is allowlist. */ reactionAllowlist?: Array; /** Action toggles for message tool capabilities. */ actions?: { /** Enable/disable sending reactions via message tool (default: true). */reactions?: boolean; }; /** * Controls agent reaction behavior: * - "off": No reactions * - "ack": Only automatic ack reactions (👀 when processing) * - "minimal": Agent can react sparingly (default) * - "extensive": Agent can react liberally */ reactionLevel?: SignalReactionLevel; }; type SignalConfig = { /** Optional per-account Signal configuration (multi-account). */accounts?: Record; } & SignalAccountConfig; //#endregion //#region src/config/types.slack.d.ts type SlackDmConfig = { /** If false, ignore all incoming Slack DMs. Default: true. */enabled?: boolean; /** Direct message access policy (default: pairing). */ policy?: DmPolicy; /** Allowlist for DM senders (ids). */ allowFrom?: Array; /** If true, allow group DMs (default: false). */ groupEnabled?: boolean; /** Optional allowlist for group DM channels (ids or slugs). */ groupChannels?: Array; /** @deprecated Prefer channels.slack.replyToModeByChatType.direct. */ replyToMode?: ReplyToMode; }; type SlackChannelConfig = { /** If false, disable the bot in this channel. (Alias for allow: false.) */enabled?: boolean; /** Legacy channel allow toggle; prefer enabled. */ allow?: boolean; /** Require mentioning the bot to trigger replies. */ requireMention?: boolean; /** Optional tool policy overrides for this channel. */ tools?: GroupToolPolicyConfig; toolsBySender?: GroupToolPolicyBySenderConfig; /** Allow bot-authored messages to trigger replies (default: false). */ allowBots?: boolean; /** Allowlist of users that can invoke the bot in this channel. */ users?: Array; /** Optional skill filter for this channel. */ skills?: string[]; /** Optional system prompt for this channel. */ systemPrompt?: string; }; type SlackReactionNotificationMode = "off" | "own" | "all" | "allowlist"; type SlackStreamingMode = "off" | "partial" | "block" | "progress"; type SlackLegacyStreamMode = "replace" | "status_final" | "append"; type SlackActionConfig = { reactions?: boolean; messages?: boolean; pins?: boolean; search?: boolean; permissions?: boolean; memberInfo?: boolean; channelInfo?: boolean; emojiList?: boolean; }; type SlackSlashCommandConfig = { /** Enable handling for the configured slash command (default: false). */enabled?: boolean; /** Slash command name (default: "fased"). */ name?: string; /** Session key prefix for slash commands (default: "slack:slash"). */ sessionPrefix?: string; /** Reply ephemerally (default: true). */ ephemeral?: boolean; }; type SlackThreadConfig = { /** Scope for thread history context (thread|channel). Default: thread. */historyScope?: "thread" | "channel"; /** If true, thread sessions inherit the parent channel transcript. Default: false. */ inheritParent?: boolean; /** Maximum number of thread messages to fetch as context when starting a new thread session (default: 20). Set to 0 to disable thread history fetching. */ initialHistoryLimit?: number; }; type SlackAccountConfig = { /** Optional display name for this account (used in CLI/UI lists). */name?: string; /** Slack connection mode (socket|http). Default: socket. */ mode?: "socket" | "http"; /** Slack signing secret (required for HTTP mode). */ signingSecret?: string; /** Slack Events API webhook path (default: /slack/events). */ webhookPath?: string; /** Optional provider capability tags used for agent/runtime guidance. */ capabilities?: string[]; /** Markdown formatting overrides (tables). */ markdown?: MarkdownConfig; /** Override native command registration for Slack (bool or "auto"). */ commands?: ProviderCommandsConfig; /** Allow channel-initiated config writes (default: true). */ configWrites?: boolean; /** If false, do not start this Slack account. Default: true. */ enabled?: boolean; botToken?: string; appToken?: string; userToken?: string; /** If true, restrict user token to read operations only. Default: true. */ userTokenReadOnly?: boolean; /** Allow bot-authored messages to trigger replies (default: false). */ allowBots?: boolean; /** * Break-glass override: allow mutable identity matching (name/slug) in allowlists. * Default behavior is ID-only matching. */ dangerouslyAllowNameMatching?: boolean; /** Default mention requirement for channel messages (default: true). */ requireMention?: boolean; /** * Controls how channel messages are handled: * - "open": channels bypass allowlists; mention-gating applies * - "disabled": block all channel messages * - "allowlist": only allow channels present in channels.slack.channels */ groupPolicy?: GroupPolicy; /** Max channel messages to keep as history context (0 disables). */ historyLimit?: number; /** Max DM turns to keep as history context. */ dmHistoryLimit?: number; /** Per-DM config overrides keyed by user ID. */ dms?: Record; textChunkLimit?: number; /** Chunking mode: "length" (default) splits by size; "newline" splits on every newline. */ chunkMode?: "length" | "newline"; blockStreaming?: boolean; /** Merge streamed block replies before sending. */ blockStreamingCoalesce?: BlockStreamingCoalesceConfig; /** * Stream preview mode: * - "off": disable live preview streaming * - "partial": replace preview text with the latest partial output (default) * - "block": append chunked preview updates * - "progress": show progress status, then send final text * * Legacy boolean values are still accepted and auto-migrated. */ streaming?: SlackStreamingMode | boolean; /** * Slack native text streaming toggle (`chat.startStream` / `chat.appendStream` / `chat.stopStream`). * Used when `streaming` is `partial`. Default: true. */ nativeStreaming?: boolean; /** @deprecated Legacy preview mode key; migrated automatically to `streaming`. */ streamMode?: SlackLegacyStreamMode; mediaMaxMb?: number; /** Reaction notification mode (off|own|all|allowlist). Default: own. */ reactionNotifications?: SlackReactionNotificationMode; /** Allowlist for reaction notifications when mode is allowlist. */ reactionAllowlist?: Array; /** Control reply threading when reply tags are present (off|first|all). */ replyToMode?: ReplyToMode; /** * Optional per-chat-type reply threading overrides. * Example: { direct: "all", group: "first", channel: "off" }. */ replyToModeByChatType?: Partial>; /** Thread session behavior. */ thread?: SlackThreadConfig; actions?: SlackActionConfig; slashCommand?: SlackSlashCommandConfig; /** * Alias for dm.policy (prefer this so it inherits cleanly via base->account shallow merge). * Legacy key: channels.slack.dm.policy. */ dmPolicy?: DmPolicy; /** * Alias for dm.allowFrom (prefer this so it inherits cleanly via base->account shallow merge). * Legacy key: channels.slack.dm.allowFrom. */ allowFrom?: Array; /** Default delivery target for CLI --deliver when no explicit --reply-to is provided. */ defaultTo?: string; dm?: SlackDmConfig; channels?: Record; /** Heartbeat visibility settings for this channel. */ heartbeat?: ChannelHeartbeatVisibilityConfig; /** Outbound response prefix override for this channel/account. */ responsePrefix?: string; /** * Per-channel ack reaction override. * Slack uses shortcodes (e.g., "eyes") rather than unicode emoji. */ ackReaction?: string; }; type SlackConfig = { /** Optional per-account Slack configuration (multi-account). */accounts?: Record; } & SlackAccountConfig; //#endregion //#region src/config/types.telegram.d.ts type TelegramActionConfig = { reactions?: boolean; sendMessage?: boolean; deleteMessage?: boolean; editMessage?: boolean; /** Enable sticker actions (send and search). */ sticker?: boolean; /** Enable forum topic creation. */ createForumTopic?: boolean; }; type TelegramNetworkConfig = { /** Override Node's autoSelectFamily behavior (true = enable, false = disable). */autoSelectFamily?: boolean; /** * DNS result order for network requests ("ipv4first" | "verbatim"). * Set to "ipv4first" to prioritize IPv4 addresses and work around IPv6 issues. * Default: "ipv4first" on Node 22+ to avoid common fetch failures. */ dnsResultOrder?: "ipv4first" | "verbatim"; }; type TelegramInlineButtonsScope = "off" | "dm" | "group" | "all" | "allowlist"; type TelegramStreamingMode = "off" | "partial" | "block" | "progress"; type TelegramCapabilitiesConfig = string[] | { inlineButtons?: TelegramInlineButtonsScope; }; /** Custom command definition for Telegram bot menu. */ type TelegramCustomCommand = { /** Command name (without leading /). */command: string; /** Description shown in Telegram command menu. */ description: string; }; type TelegramAccountConfig = { /** Optional display name for this account (used in CLI/UI lists). */name?: string; /** Optional provider capability tags used for agent/runtime guidance. */ capabilities?: TelegramCapabilitiesConfig; /** Markdown formatting overrides (tables). */ markdown?: MarkdownConfig; /** Override native command registration for Telegram (bool or "auto"). */ commands?: ProviderCommandsConfig; /** Custom commands to register in Telegram's command menu (merged with native). */ customCommands?: TelegramCustomCommand[]; /** Allow channel-initiated config writes (default: true). */ configWrites?: boolean; /** * Controls how Telegram direct chats (DMs) are handled: * - "pairing" (default): unknown senders get a pairing code; owner must approve * - "allowlist": only allow senders in allowFrom (or paired allow store) * - "open": allow all inbound DMs (requires allowFrom to include "*") * - "disabled": ignore all inbound DMs */ dmPolicy?: DmPolicy; /** If false, do not start this Telegram account. Default: true. */ enabled?: boolean; botToken?: string; /** Path to file containing bot token (for secret managers like agenix). */ tokenFile?: string; /** Control reply threading when reply tags are present (off|first|all). */ replyToMode?: ReplyToMode; groups?: Record; /** DM allowlist (numeric Telegram user IDs). Onboarding can resolve @username to IDs. */ allowFrom?: Array; /** Default delivery target for CLI `--deliver` when no explicit `--reply-to` is provided. */ defaultTo?: string | number; /** Optional allowlist for Telegram group senders (numeric Telegram user IDs). */ groupAllowFrom?: Array; /** * Controls how group messages are handled: * - "open": groups bypass allowFrom, only mention-gating applies * - "disabled": block all group messages entirely * - "allowlist": only allow group messages from senders in groupAllowFrom/allowFrom */ groupPolicy?: GroupPolicy; /** Max group messages to keep as history context (0 disables). */ historyLimit?: number; /** Max DM turns to keep as history context. */ dmHistoryLimit?: number; /** Per-DM config overrides keyed by user ID. */ dms?: Record; /** Outbound text chunk size (chars). Default: 4000. */ textChunkLimit?: number; /** Chunking mode: "length" (default) splits by size; "newline" splits on every newline. */ chunkMode?: "length" | "newline"; /** * Stream preview mode: * - "off": disable preview updates * - "partial": edit a single preview message * - "block": stream in larger chunked updates * - "progress": alias that maps to "partial" on Telegram * * Legacy boolean values are still accepted and auto-migrated. */ streaming?: TelegramStreamingMode | boolean; /** Disable block streaming for this account. */ blockStreaming?: boolean; /** @deprecated Legacy chunking config from `streamMode: "block"`; ignored after migration. */ draftChunk?: BlockStreamingChunkConfig; /** Merge streamed block replies before sending. */ blockStreamingCoalesce?: BlockStreamingCoalesceConfig; /** @deprecated Legacy key; migrated automatically to `streaming`. */ streamMode?: "off" | "partial" | "block"; mediaMaxMb?: number; /** Telegram API client timeout in seconds (grammY ApiClientOptions). */ timeoutSeconds?: number; /** Retry policy for outbound Telegram API calls. */ retry?: OutboundRetryConfig; /** Network transport overrides for Telegram. */ network?: TelegramNetworkConfig; proxy?: string; webhookUrl?: string; webhookSecret?: string; webhookPath?: string; /** Local webhook listener bind host (default: 127.0.0.1). */ webhookHost?: string; /** Local webhook listener bind port (default: 8787). */ webhookPort?: number; /** Per-action tool gating (default: true for all). */ actions?: TelegramActionConfig; /** * Controls which user reactions trigger notifications: * - "off" (default): ignore all reactions * - "own": notify when users react to bot messages * - "all": notify agent of all reactions */ reactionNotifications?: "off" | "own" | "all"; /** * Controls agent's reaction capability: * - "off": agent cannot react * - "ack" (default): bot sends acknowledgment reactions (👀 while processing) * - "minimal": agent can react sparingly (guideline: 1 per 5-10 exchanges) * - "extensive": agent can react liberally when appropriate */ reactionLevel?: "off" | "ack" | "minimal" | "extensive"; /** Heartbeat visibility settings for this channel. */ heartbeat?: ChannelHeartbeatVisibilityConfig; /** Controls whether link previews are shown in outbound messages. Default: true. */ linkPreview?: boolean; /** * Per-channel outbound response prefix override. * * When set, this takes precedence over the global `messages.responsePrefix`. * Use `""` to explicitly disable a global prefix for this channel. * Use `"auto"` to derive `[{identity.name}]` from the routed agent. */ responsePrefix?: string; /** * Per-channel ack reaction override. * Telegram expects unicode emoji (e.g., "👀") rather than shortcodes. */ ackReaction?: string; }; type TelegramTopicConfig = { requireMention?: boolean; /** Per-topic override for group message policy (open|disabled|allowlist). */ groupPolicy?: GroupPolicy; /** If specified, only load these skills for this topic. Omit = all skills; empty = no skills. */ skills?: string[]; /** If false, disable the bot for this topic. */ enabled?: boolean; /** Optional allowlist for topic senders (numeric Telegram user IDs). */ allowFrom?: Array; /** Optional system prompt snippet for this topic. */ systemPrompt?: string; }; type TelegramGroupConfig = { requireMention?: boolean; /** Per-group override for group message policy (open|disabled|allowlist). */ groupPolicy?: GroupPolicy; /** Optional tool policy overrides for this group. */ tools?: GroupToolPolicyConfig; toolsBySender?: GroupToolPolicyBySenderConfig; /** If specified, only load these skills for this group (when no topic). Omit = all skills; empty = no skills. */ skills?: string[]; /** Per-topic configuration (key is message_thread_id as string) */ topics?: Record; /** If false, disable the bot for this group (and its topics). */ enabled?: boolean; /** Optional allowlist for group senders (numeric Telegram user IDs). */ allowFrom?: Array; /** Optional system prompt snippet for this group. */ systemPrompt?: string; }; type TelegramThreadBindingsConfig = { enabled?: boolean; idleHours?: number; maxAgeHours?: number; spawnSubagentSessions?: boolean; spawnAcpSessions?: boolean; }; type TelegramConfig = { /** Optional per-account Telegram configuration (multi-account). */accounts?: Record; threadBindings?: TelegramThreadBindingsConfig; } & TelegramAccountConfig; //#endregion //#region src/config/types.whatsapp.d.ts type WhatsAppActionConfig = { reactions?: boolean; sendMessage?: boolean; polls?: boolean; }; type WhatsAppGroupConfig = { requireMention?: boolean; tools?: GroupToolPolicyConfig; toolsBySender?: GroupToolPolicyBySenderConfig; }; type WhatsAppAckReactionConfig = { /** Emoji to use for acknowledgment (e.g., "👀"). Empty = disabled. */emoji?: string; /** Send reactions in direct chats. Default: true. */ direct?: boolean; /** * Send reactions in group chats: * - "always": react to all group messages * - "mentions": react only when bot is mentioned * - "never": never react in groups * Default: "mentions" */ group?: "always" | "mentions" | "never"; }; type WhatsAppSharedConfig = { /** Whether the WhatsApp channel is enabled. */enabled?: boolean; /** Direct message access policy (default: pairing). */ dmPolicy?: DmPolicy; /** Same-phone setup (bot uses your personal WhatsApp number). */ selfChatMode?: boolean; /** Optional allowlist for WhatsApp direct chats (E.164). */ allowFrom?: string[]; /** Default delivery target for CLI `--deliver` when no explicit `--reply-to` is provided (E.164 or group JID). */ defaultTo?: string; /** Optional allowlist for WhatsApp group senders (E.164). */ groupAllowFrom?: string[]; /** * Controls how group messages are handled: * - "open": groups bypass allowFrom, only mention-gating applies * - "disabled": block all group messages entirely * - "allowlist": only allow group messages from senders in groupAllowFrom/allowFrom */ groupPolicy?: GroupPolicy; /** Max group messages to keep as history context (0 disables). */ historyLimit?: number; /** Max DM turns to keep as history context. */ dmHistoryLimit?: number; /** Per-DM config overrides keyed by user ID. */ dms?: Record; /** Outbound text chunk size (chars). Default: 4000. */ textChunkLimit?: number; /** Chunking mode: "length" (default) splits by size; "newline" splits on every newline. */ chunkMode?: "length" | "newline"; /** Maximum media file size in MB. Default: 50. */ mediaMaxMb?: number; /** Disable block streaming for this account. */ blockStreaming?: boolean; /** Merge streamed block replies before sending. */ blockStreamingCoalesce?: BlockStreamingCoalesceConfig; groups?: Record; /** Acknowledgment reaction sent immediately upon message receipt. */ ackReaction?: WhatsAppAckReactionConfig; /** Debounce window (ms) for batching rapid consecutive messages from the same sender (0 to disable). */ debounceMs?: number; /** Heartbeat visibility settings. */ heartbeat?: ChannelHeartbeatVisibilityConfig; }; type WhatsAppConfigCore = { /** Optional provider capability tags used for agent/runtime guidance. */capabilities?: string[]; /** Markdown formatting overrides (tables). */ markdown?: MarkdownConfig; /** Allow channel-initiated config writes (default: true). */ configWrites?: boolean; /** Send read receipts for incoming messages (default true). */ sendReadReceipts?: boolean; /** Inbound message prefix override (WhatsApp only). */ messagePrefix?: string; /** Outbound response prefix override. */ responsePrefix?: string; }; type WhatsAppConfig = WhatsAppConfigCore & WhatsAppSharedConfig & { /** Optional per-account WhatsApp configuration (multi-account). */accounts?: Record; /** Per-action tool gating (default: true for all). */ actions?: WhatsAppActionConfig; }; type WhatsAppAccountConfig = WhatsAppConfigCore & WhatsAppSharedConfig & { /** Optional display name for this account (used in CLI/UI lists). */name?: string; /** If false, do not start this WhatsApp account provider. Default: true. */ enabled?: boolean; /** Override auth directory (Baileys multi-file auth state). */ authDir?: string; }; //#endregion //#region src/config/types.channels.d.ts type ChannelHeartbeatVisibilityConfig = { /** Show HEARTBEAT_OK acknowledgments in chat (default: false). */showOk?: boolean; /** Show heartbeat alerts with actual content (default: true). */ showAlerts?: boolean; /** Emit indicator events for UI status display (default: true). */ useIndicator?: boolean; }; type ChannelDefaultsConfig = { groupPolicy?: GroupPolicy; /** Default heartbeat visibility for all channels. */ heartbeat?: ChannelHeartbeatVisibilityConfig; }; type ChannelModelByChannelConfig = Record>; type ChannelsConfig = { defaults?: ChannelDefaultsConfig; /** Map provider -> channel id -> model override. */ modelByChannel?: ChannelModelByChannelConfig; whatsapp?: WhatsAppConfig; telegram?: TelegramConfig; discord?: DiscordConfig; irc?: IrcConfig; googlechat?: GoogleChatConfig; slack?: SlackConfig; signal?: SignalConfig; imessage?: IMessageConfig; msteams?: MSTeamsConfig; [key: string]: any; }; //#endregion //#region src/config/types.cron.d.ts type CronConfig = { enabled?: boolean; store?: string; maxConcurrentRuns?: number; /** * Deprecated legacy fallback webhook URL used only for stored jobs with notify=true. * Prefer per-job delivery.mode="webhook" with delivery.to. */ webhook?: string; /** Bearer token for cron webhook POST delivery. */ webhookToken?: string; /** * How long to retain completed cron run sessions before automatic pruning. * Accepts a duration string (e.g. "24h", "7d", "1h30m") or `false` to disable pruning. * Default: "24h". */ sessionRetention?: string | false; /** * Run-log pruning controls for `cron/runs/.jsonl`. * Defaults: `maxBytes=2_000_000`, `keepLines=2000`. */ runLog?: { maxBytes?: number | string; keepLines?: number; }; }; //#endregion //#region src/config/types.wallet.d.ts type WalletChain = "solana"; type WalletRuntimeMode = "managed" | "external"; type WalletRuntimeKind = "external-docker" | "external-custom"; type WalletExternalKind = "docker" | "custom"; type WalletAuthMode = "jwt-bootstrap" | "static-token-compat"; type WalletToolAccessMode = "owner-only" | "allowlist" | "all"; type WalletExecutionMode = "manual" | "autonomous"; type WalletApprovalAuthMode = "none" | "webauthn"; type WalletProviderId = "embedded-keystore" | "local-socket-signer" | "alchemy" | "turnkey" | "wallet-standard" | "privy"; type WalletConfig = { provider?: WalletProviderConfig; execution?: WalletExecutionConfig; approvalAuth?: WalletApprovalAuthConfig; keystore?: WalletKeystoreConfig; runtime?: WalletRuntimeConfig; }; type WalletProviderConfig = { id?: WalletProviderId; }; type WalletExecutionConfig = { mode?: WalletExecutionMode; }; type WalletApprovalAuthConfig = { mode?: WalletApprovalAuthMode; challengeTtlSeconds?: number; grantTtlSeconds?: number; }; type WalletKeystoreConfig = { enabled?: boolean; path?: string; chainSupport?: WalletChain[]; autoLockSeconds?: number; requirePasskeyForUnlock?: boolean; }; type WalletRuntimeConfig = { enabled?: boolean; mode?: WalletRuntimeMode; runtime?: WalletRuntimeKind; external?: WalletExternalConfig; auth?: WalletAuthConfig; source?: WalletSourceConfig; chains?: WalletChain[]; service?: WalletServiceConfig; install?: WalletInstallConfig; policy?: WalletPolicyConfig; toolAccess?: WalletToolAccessConfig; }; type WalletExternalConfig = { kind?: WalletExternalKind; }; type WalletAuthConfig = { mode?: WalletAuthMode; bootstrapUrl?: string; }; type WalletSourceConfig = { ref?: string; }; type WalletServiceConfig = { host?: string; port?: number; }; type WalletInstallConfig = { enabled?: boolean; version?: string; }; type WalletPolicyConfig = { capsEnabled?: boolean; directSigning?: boolean; skillsEnabled?: boolean; solana?: WalletChainPolicy; }; type WalletChainPolicy = { allowPrograms?: string[]; tokenCaps?: Record; maxPerTx?: string; maxDaily?: string; }; type WalletTokenPolicyCap = { maxPerTx?: string; maxDaily?: string; }; type WalletToolAccessConfig = { mode?: WalletToolAccessMode; allowAgents?: string[]; allowSkills?: string[]; denySkills?: string[]; allowSources?: string[]; }; //#endregion //#region src/config/types.federation.d.ts type FederationOfferSource = "builtin" | "manual" | "skill"; type FederationOfferAssetKind = "native" | "spl-token"; type FederationMarketplaceFulfillmentMode = "human" | "agent" | "agent-approval" | "api" | "dataset" | "hybrid"; type FederationMarketplacePriceUnit = "per-job" | "per-hour" | "per-1k-rows" | "per-api-call" | "per-day" | "per-month" | "custom"; type FederationOfferPricingConfig = { currency?: string; model?: string; amount?: number; unit?: FederationMarketplacePriceUnit; unitLabel?: string; }; type FederationOfferPaymentDefaultsConfig = { currency?: string; chain?: WalletChain; assetDecimals?: number; asset?: { kind?: FederationOfferAssetKind; address?: string; }; payee?: { chain?: WalletChain; address?: string; }; }; type FederationMarketplaceReceiptRuleConfig = { kind?: "result" | "artifact" | "invoice" | "receipt" | "tx" | "signature" | "manual"; required?: boolean; description?: string; }; type FederationMarketplaceAutomationPolicyConfig = { allowed?: boolean; humanApprovalRequired?: boolean; allowedSkills?: string[]; allowedPlugins?: string[]; maxRuntimeSeconds?: number; maxSpendAmount?: number; maxSpendCurrency?: string; }; type FederationOfferConfig = { id?: string; source?: FederationOfferSource; enabled?: boolean; title: string; summary?: string; serviceKind: string; inputShape?: string; deliveryShape?: string; capabilities?: string[]; pricing?: FederationOfferPricingConfig; fulfillmentMode?: FederationMarketplaceFulfillmentMode; performer?: FederationMarketplaceFulfillmentMode; receiptRules?: FederationMarketplaceReceiptRuleConfig[]; automation?: FederationMarketplaceAutomationPolicyConfig; paymentRails?: string[]; acceptedAssets?: string[]; paymentDefaults?: FederationOfferPaymentDefaultsConfig; availability?: string; visibility?: string; requiredTrustOrBondTier?: string; createdAt?: string; updatedAt?: string; }; type FederationManualOfferConfig = FederationOfferConfig & { source?: "manual"; }; type FederationSkillOfferConfig = FederationOfferConfig & { source?: "skill"; skillId?: string; }; type FederationOffersConfig = { manual?: FederationManualOfferConfig[]; skill?: FederationSkillOfferConfig[]; }; type FederationMarketplaceRequestStatus = "draft" | "open" | "matched" | "closed"; type FederationMarketplaceOrderStatus = "draft" | "accepted" | "funded" | "running" | "delivered" | "disputed" | "closed" | "cancelled"; type FederationMarketplaceSellerSyncStatus = "not_submitted" | "pending" | "accepted" | "failed"; type FederationMarketplacePaymentIntentStatus = "draft" | "requires_payment" | "submitted" | "verified" | "failed" | "cancelled"; type FederationMarketplaceSettlementMode = "direct" | "escrow"; type FederationMarketplaceSettlementStatus = "not_required" | "requires_payment" | "submitted" | "verified" | "settled" | "held" | "released" | "failed" | "disputed" | "cancelled"; type FederationMarketplaceEscrowStatus = "not_applicable" | "required" | "funded" | "held" | "released" | "refunded" | "cancelled" | "blocked"; type FederationMarketplaceDeliveryStatus = "pending" | "ready" | "running" | "delivered" | "failed" | "blocked"; type FederationMarketplaceReceiptStatus = "pending" | "issued" | "verified" | "rejected"; type FederationMarketplaceBillingPeriod = "one-time" | "per-job" | "per-hour" | "per-1k-rows" | "per-api-call" | "per-day" | "per-week" | "per-month" | "custom"; type FederationMarketplaceSubscriptionStatus = "not_applicable" | "draft" | "active" | "past_due" | "paused" | "expired" | "cancelled" | "blocked"; type FederationMarketplaceRenewalPolicy = "none" | "manual" | "auto-renew" | "auto-renew-with-approval"; type FederationMarketplaceDeliveryStopStatus = "not_required" | "scheduled" | "stopped" | "blocked"; type FederationMarketplaceDeliveryStopConfig = { status?: FederationMarketplaceDeliveryStopStatus; reason?: string; scheduledAt?: string; stoppedAt?: string; updatedAt?: string; }; type FederationMarketplaceSubscriptionConfig = { status?: FederationMarketplaceSubscriptionStatus; billingPeriod?: FederationMarketplaceBillingPeriod; maxBuyers?: number; remainingSlots?: number; startsAt?: string; endsAt?: string; renewalPolicy?: FederationMarketplaceRenewalPolicy; paymentExpiresAt?: string; deliveryStop?: FederationMarketplaceDeliveryStopConfig; createdAt?: string; updatedAt?: string; }; type FederationMarketplaceDeliveryTargetKind = "app-inbox" | "channel" | "webhook" | "websocket" | "federation" | "api" | "artifact"; type FederationMarketplaceDeliveryTargetStatus = "draft" | "ready" | "revoked" | "expired" | "blocked"; type FederationMarketplaceDeliveryTargetScopeConfig = { orderId?: string; subscriptionId?: string; serviceKind?: string; expiresAt?: string; maxDeliveries?: number; }; type FederationMarketplaceDeliveryTargetConfig = { targetId?: string; source?: "order" | "subscription" | "manual"; owner?: "buyer" | "seller"; kind?: FederationMarketplaceDeliveryTargetKind; status?: FederationMarketplaceDeliveryTargetStatus; label?: string; descriptor?: string; maskedTarget?: string; scope?: FederationMarketplaceDeliveryTargetScopeConfig; channel?: { provider?: string; to?: string; accountId?: string; threadId?: string | number; }; webhook?: { url?: string; method?: "POST"; secretRef?: string; }; websocket?: { url?: string; tokenRef?: string; }; federation?: { handle?: string; nodeEndpoint?: string; }; api?: { url?: string; tokenRef?: string; }; artifact?: { artifactRef?: string; }; createdAt?: string; updatedAt?: string; revokedAt?: string; }; type FederationMarketplacePaymentIntentConfig = { intentId?: string; status?: FederationMarketplacePaymentIntentStatus; amount?: number; currency?: string; unit?: FederationMarketplacePriceUnit; method?: string; chain?: WalletChain; assetKind?: FederationOfferAssetKind; assetAddress?: string; assetDecimals?: number; expiresInMinutes?: number; acceptedAssets?: string[]; payerWalletId?: string; payeeHandle?: string; payeeAddress?: string; txRef?: string; createdAt?: string; updatedAt?: string; }; type FederationMarketplaceEscrowConfig = { status?: FederationMarketplaceEscrowStatus; holdPolicy?: "none" | "release_on_delivery" | "manual_release"; releaseRequired?: boolean; vaultWalletId?: string; vaultWalletName?: string; vaultAddress?: string; fundingRequestId?: string; fundingTxRef?: string; fundedAt?: string; releaseRequestId?: string; releaseTxRef?: string; releasedAt?: string; refundRequestId?: string; refundTxRef?: string; refundedAt?: string; cancelledAt?: string; notes?: string; updatedAt?: string; }; type FederationMarketplaceSettlementRecordConfig = { mode?: FederationMarketplaceSettlementMode; status?: FederationMarketplaceSettlementStatus; amount?: number; currency?: string; chain?: WalletChain; assetKind?: FederationOfferAssetKind; assetAddress?: string; assetDecimals?: number; invoiceId?: string; receiptId?: string; txRef?: string; evidenceRef?: string; payerWalletId?: string; payeeAddress?: string; escrow?: FederationMarketplaceEscrowConfig; notes?: string; createdAt?: string; updatedAt?: string; verifiedAt?: string; settledAt?: string; }; type FederationMarketplaceDeliveryRecordConfig = { status?: FederationMarketplaceDeliveryStatus; fulfillmentMode?: FederationMarketplaceFulfillmentMode; inputShape?: string; deliveryShape?: string; targetId?: string; targetKind?: FederationMarketplaceDeliveryTargetKind; targetStatus?: FederationMarketplaceDeliveryTargetStatus; targetLabel?: string; targetMasked?: string; target?: FederationMarketplaceDeliveryTargetConfig; resultRef?: string; artifactRef?: string; notes?: string; deliveredAt?: string; updatedAt?: string; }; type FederationMarketplaceReceiptRecordConfig = { status?: FederationMarketplaceReceiptStatus; invoiceId?: string; receiptId?: string; txRef?: string; resultRef?: string; disputeCaseId?: string; notes?: string; createdAt?: string; updatedAt?: string; }; type FederationMarketplaceRequestConfig = { id?: string; source?: "manual" | "chat"; enabled?: boolean; status?: FederationMarketplaceRequestStatus; title: string; summary?: string; serviceKind: string; inputShape?: string; deliveryShape?: string; capabilities?: string[]; pricing?: FederationOfferPricingConfig; fulfillmentMode?: FederationMarketplaceFulfillmentMode; receiptRules?: FederationMarketplaceReceiptRuleConfig[]; paymentRails?: string[]; acceptedAssets?: string[]; requiredTrustOrBondTier?: string; visibility?: string; expiresAt?: string; createdAt?: string; updatedAt?: string; }; type FederationMarketplaceOrderConfig = { id?: string; source?: "local" | "federation"; status?: FederationMarketplaceOrderStatus; offerId?: string; requestId?: string; buyerHandle?: string; sellerHandle?: string; sellerEndpoint?: string; sellerOrderId?: string; sellerSyncStatus?: FederationMarketplaceSellerSyncStatus; sellerSyncError?: string; sellerSyncedAt?: string; sellerAcceptedAt?: string; /** Directory-bound peer identity that first created this inbound record. */ peerNodeId?: string; /** Exact remote order identifier bound to the peer identity. */ peerRemoteOrderId?: string; /** SHA-256 of the canonical signed order intake body. */ peerRequestDigest?: string; /** SHA-256 of the canonical signed delivery body. */ peerDeliveryDigest?: string; serviceKind?: string; title?: string; pricing?: FederationOfferPricingConfig; fulfillmentMode?: FederationMarketplaceFulfillmentMode; receiptRules?: FederationMarketplaceReceiptRuleConfig[]; paymentIntent?: FederationMarketplacePaymentIntentConfig; settlement?: FederationMarketplaceSettlementRecordConfig; delivery?: FederationMarketplaceDeliveryRecordConfig; subscription?: FederationMarketplaceSubscriptionConfig; receipt?: FederationMarketplaceReceiptRecordConfig; invoiceId?: string; receiptId?: string; txRef?: string; resultRef?: string; disputeCaseId?: string; createdAt?: string; updatedAt?: string; }; type FederationMarketplaceConfig = { requests?: { manual?: FederationMarketplaceRequestConfig[]; }; deliveryTargets?: { local?: FederationMarketplaceDeliveryTargetConfig[]; }; orders?: { local?: FederationMarketplaceOrderConfig[]; }; }; type FederationBondConfig = { walletId?: string; }; type FederationConfig = { offers?: FederationOffersConfig; marketplace?: FederationMarketplaceConfig; bond?: FederationBondConfig; }; //#endregion //#region src/config/types.gateway.d.ts type GatewayBindMode = "auto" | "lan" | "loopback" | "custom" | "tailnet"; type GatewayTlsConfig = { /** Enable TLS for the gateway server. */enabled?: boolean; /** Auto-generate a self-signed cert if cert/key are missing (default: true). */ autoGenerate?: boolean; /** PEM certificate path for the gateway server. */ certPath?: string; /** PEM private key path for the gateway server. */ keyPath?: string; /** Optional PEM CA bundle for TLS clients (mTLS or custom roots). */ caPath?: string; }; type WideAreaDiscoveryConfig = { enabled?: boolean; /** Optional unicast DNS-SD domain (e.g. "fased.internal"). */ domain?: string; }; type MdnsDiscoveryMode = "off" | "minimal" | "full"; type MdnsDiscoveryConfig = { /** * mDNS/Bonjour discovery broadcast mode (default: minimal). * - off: disable mDNS entirely * - minimal: omit cliPath/sshPort from TXT records * - full: include cliPath/sshPort in TXT records */ mode?: MdnsDiscoveryMode; }; type DiscoveryConfig = { wideArea?: WideAreaDiscoveryConfig; mdns?: MdnsDiscoveryConfig; }; type CanvasHostConfig = { enabled?: boolean; /** Directory to serve (default: ~/.fased/workspace/canvas). */ root?: string; /** HTTP port to listen on (default: 18793). */ port?: number; /** Enable live-reload file watching + WS reloads (default: true). */ liveReload?: boolean; }; type TalkProviderConfig = { /** Voice ID for this provider (e.g. ElevenLabs voice id). */voiceId?: string; /** Optional voice name -> ID map. */ voiceAliases?: Record; /** Model ID for this provider. */ modelId?: string; /** Output format (e.g. mp3_44100_128). */ outputFormat?: string; /** API key or local SecretRef for this provider. */ apiKey?: SecretInput | Record; [key: string]: unknown; }; type TalkConfig = { /** Active talk provider ID (e.g. "elevenlabs"). */provider?: string; /** Per-provider configuration. */ providers?: Record; /** Legacy: Default ElevenLabs voice ID for Talk mode. */ voiceId?: string; /** Legacy: Optional voice name -> ElevenLabs voice ID map. */ voiceAliases?: Record; /** Legacy: Default ElevenLabs model ID for Talk mode. */ modelId?: string; /** Legacy: Default ElevenLabs output format (e.g. mp3_44100_128). */ outputFormat?: string; /** Legacy: ElevenLabs API key or local SecretRef. */ apiKey?: SecretInput | Record; /** Stop speaking when user starts talking (default: true). */ interruptOnSpeech?: boolean; }; type GatewayControlUiConfig = { /** If false, the Gateway will not serve the Control UI (default /). */enabled?: boolean; /** Optional base path prefix for the Control UI (e.g. "/fased"). */ basePath?: string; /** Optional filesystem root for Control UI assets (defaults to dist/control-ui). */ root?: string; /** Allowed browser origins for Control UI/WebChat websocket connections. */ allowedOrigins?: string[]; /** Allow token-only auth over insecure HTTP (default: false). */ allowInsecureAuth?: boolean; /** DANGEROUS: Disable device identity checks for the Control UI (default: false). */ dangerouslyDisableDeviceAuth?: boolean; /** DANGEROUS: Allow Host header fallback for browser origin checks (default: false). */ dangerouslyAllowHostHeaderOriginFallback?: boolean; }; type GatewayAuthMode = "none" | "token" | "password" | "trusted-proxy"; /** * Configuration for trusted reverse proxy authentication. * Used when FasedAgent runs behind an identity-aware proxy (Pomerium, Caddy + OAuth, etc.) * that handles authentication and passes user identity via headers. */ type GatewayTrustedProxyConfig = { /** * Header name containing the authenticated user identity (required). * Common values: "x-forwarded-user", "x-remote-user", "x-pomerium-claim-email" */ userHeader: string; /** * Additional headers that MUST be present for the request to be trusted. * Use this to verify the request actually came through the proxy. * Example: ["x-forwarded-proto", "x-forwarded-host"] */ requiredHeaders?: string[]; /** * Optional allowlist of user identities that can access the gateway. * If empty or omitted, all authenticated users from the proxy are allowed. * Example: ["nick@example.com", "admin@company.org"] */ allowUsers?: string[]; }; type GatewayAuthConfig = { /** Authentication mode for Gateway connections. Defaults to token when set. */mode?: GatewayAuthMode; /** Shared token for token mode (stored locally for CLI auth). */ token?: string; /** Shared password for password mode (consider env instead). */ password?: string; /** Allow Tailscale identity headers when serve mode is enabled. */ allowTailscale?: boolean; /** Rate-limit configuration for failed authentication attempts. */ rateLimit?: GatewayAuthRateLimitConfig; /** * Configuration for trusted-proxy auth mode. * Required when mode is "trusted-proxy". */ trustedProxy?: GatewayTrustedProxyConfig; }; type GatewayAuthRateLimitConfig = { /** Maximum failed attempts per IP before blocking. @default 10 */maxAttempts?: number; /** Sliding window duration in milliseconds. @default 60000 (1 min) */ windowMs?: number; /** Lockout duration in milliseconds after the limit is exceeded. @default 300000 (5 min) */ lockoutMs?: number; /** Exempt localhost/loopback addresses from auth rate limiting. @default true */ exemptLoopback?: boolean; }; type GatewayTailscaleMode = "off" | "serve" | "funnel"; type GatewayTailscaleConfig = { /** Tailscale exposure mode for the Gateway control UI. */mode?: GatewayTailscaleMode; /** Reset serve/funnel configuration on shutdown. */ resetOnExit?: boolean; }; type GatewayRemoteConfig = { /** Remote Gateway WebSocket URL (ws:// or wss://). */url?: string; /** Transport for macOS remote connections (ssh tunnel or direct WS). */ transport?: "ssh" | "direct"; /** Token for remote auth (when the gateway requires token auth). */ token?: string; /** Password for remote auth (when the gateway requires password auth). */ password?: string; /** Expected TLS certificate fingerprint (sha256) for remote gateways. */ tlsFingerprint?: string; /** SSH target for tunneling remote Gateway (user@host). */ sshTarget?: string; /** SSH identity file path for tunneling remote Gateway. */ sshIdentity?: string; }; type GatewayReloadMode = "off" | "restart" | "hot" | "hybrid"; type GatewayReloadConfig = { /** Reload strategy for config changes (default: hybrid). */mode?: GatewayReloadMode; /** Debounce window for config reloads (ms). Default: 300. */ debounceMs?: number; }; type GatewayHttpChatCompletionsConfig = { /** * If false, the Gateway will not serve `POST /v1/chat/completions`. * Default: false when absent. */ enabled?: boolean; }; type GatewayHttpResponsesConfig = { /** * If false, the Gateway will not serve `POST /v1/responses` (OpenResponses API). * Default: false when absent. */ enabled?: boolean; /** * Max request body size in bytes for `/v1/responses`. * Default: 20MB. */ maxBodyBytes?: number; /** * Max number of URL-based `input_file` + `input_image` parts per request. * Default: 8. */ maxUrlParts?: number; /** File inputs (input_file). */ files?: GatewayHttpResponsesFilesConfig; /** Image inputs (input_image). */ images?: GatewayHttpResponsesImagesConfig; }; type GatewayHttpResponsesFilesConfig = { /** Allow URL fetches for input_file. Default: true. */allowUrl?: boolean; /** * Optional hostname allowlist for URL fetches. * Supports exact hosts and `*.example.com` wildcards. */ urlAllowlist?: string[]; /** Allowed MIME types (case-insensitive). */ allowedMimes?: string[]; /** Max bytes per file. Default: 5MB. */ maxBytes?: number; /** Max decoded characters per file. Default: 200k. */ maxChars?: number; /** Max redirects when fetching a URL. Default: 3. */ maxRedirects?: number; /** Fetch timeout in ms. Default: 10s. */ timeoutMs?: number; /** PDF handling (application/pdf). */ pdf?: GatewayHttpResponsesPdfConfig; }; type GatewayHttpResponsesPdfConfig = { /** Max pages to parse/render. Default: 4. */maxPages?: number; /** Max pixels per rendered page. Default: 4M. */ maxPixels?: number; /** Minimum extracted text length to skip rasterization. Default: 200 chars. */ minTextChars?: number; }; type GatewayHttpResponsesImagesConfig = { /** Allow URL fetches for input_image. Default: true. */allowUrl?: boolean; /** * Optional hostname allowlist for URL fetches. * Supports exact hosts and `*.example.com` wildcards. */ urlAllowlist?: string[]; /** Allowed MIME types (case-insensitive). */ allowedMimes?: string[]; /** Max bytes per image. Default: 10MB. */ maxBytes?: number; /** Max redirects when fetching a URL. Default: 3. */ maxRedirects?: number; /** Fetch timeout in ms. Default: 10s. */ timeoutMs?: number; }; type GatewayHttpEndpointsConfig = { chatCompletions?: GatewayHttpChatCompletionsConfig; responses?: GatewayHttpResponsesConfig; }; type GatewayHttpConfig = { endpoints?: GatewayHttpEndpointsConfig; securityHeaders?: { strictTransportSecurity?: string | false; }; }; type GatewayNodesConfig = { /** Browser routing policy for node-hosted browser proxies. */browser?: { /** Routing mode (default: auto). */mode?: "auto" | "manual" | "off"; /** Pin to a specific node id/name (optional). */ node?: string; }; /** Additional node.invoke commands to allow on the gateway. */ allowCommands?: string[]; /** Commands to deny even if they appear in the defaults or node claims. */ denyCommands?: string[]; }; type GatewayToolsConfig = { /** Tools to deny via gateway HTTP /tools/invoke (extends defaults). */deny?: string[]; /** Tools to explicitly allow (removes from default deny list). */ allow?: string[]; }; type GatewayConfig = { /** Single multiplexed port for Gateway WS + HTTP (default: 18789). */port?: number; /** * Explicit gateway mode. When set to "remote", local gateway start is disabled. * When set to "local", the CLI may start the gateway locally. */ mode?: "local" | "remote"; /** * Bind address policy for the Gateway WebSocket + Control UI HTTP server. * - auto: Loopback (127.0.0.1) if available, else 0.0.0.0 (fallback to all interfaces) * - lan: 0.0.0.0 (all interfaces, no fallback) * - loopback: 127.0.0.1 (local-only) * - tailnet: Tailnet IPv4 if available (100.64.0.0/10), else loopback * - custom: User-specified IP, fallback to 0.0.0.0 if unavailable (requires customBindHost) * Default: loopback (127.0.0.1). */ bind?: GatewayBindMode; /** Custom IP address for bind="custom" mode. Fallback: 0.0.0.0. */ customBindHost?: string; controlUi?: GatewayControlUiConfig; auth?: GatewayAuthConfig; tailscale?: GatewayTailscaleConfig; remote?: GatewayRemoteConfig; reload?: GatewayReloadConfig; tls?: GatewayTlsConfig; http?: GatewayHttpConfig; nodes?: GatewayNodesConfig; /** * IPs of trusted reverse proxies (e.g. Traefik, nginx). When a connection * arrives from one of these IPs, the Gateway trusts `x-forwarded-for` (or * `x-real-ip`) to determine the client IP for local pairing and HTTP checks. */ trustedProxies?: string[]; /** Tool access restrictions for HTTP /tools/invoke endpoint. */ tools?: GatewayToolsConfig; /** Allow fallback to req.socket.remoteAddress if proxy-aware resolution fails. */ allowRealIpFallback?: boolean; }; //#endregion //#region src/config/types.hooks.d.ts type HookMappingMatch = { path?: string; source?: string; }; type HookMappingTransform = { module: string; export?: string; }; type HookMappingConfig = { id?: string; /** Disabled mappings stay configured but are ignored by webhook runtime. */ enabled?: boolean; match?: HookMappingMatch; action?: "wake" | "agent" | "workflow"; wakeMode?: "now" | "next-heartbeat"; name?: string; /** Route this hook to a specific agent (unknown ids fall back to the default agent). */ agentId?: string; sessionKey?: string; messageTemplate?: string; textTemplate?: string; /** Saved Agent workflow/graph definition to run when action is "workflow". */ workflowDefinitionId?: string; deliver?: boolean; /** DANGEROUS: Disable external content safety wrapping for this hook. */ allowUnsafeExternalContent?: boolean; channel?: "last" | "whatsapp" | "telegram" | "discord" | "irc" | "googlechat" | "slack" | "signal" | "imessage" | "msteams"; to?: string; /** Override model for this hook (provider/model or alias). */ model?: string; thinking?: string; timeoutSeconds?: number; /** Task ledger notification policy for webhook-triggered Agent runs. */ notifyPolicy?: "silent" | "done_only" | "state_changes"; transform?: HookMappingTransform; }; type HooksGmailTailscaleMode = "off" | "serve" | "funnel"; type HooksGmailConfig = { account?: string; project?: string; label?: string; topic?: string; subscription?: string; pushToken?: string; hookUrl?: string; includeBody?: boolean; maxBytes?: number; renewEveryMinutes?: number; /** DANGEROUS: Disable external content safety wrapping for Gmail hooks. */ allowUnsafeExternalContent?: boolean; serve?: { bind?: string; port?: number; path?: string; }; tailscale?: { mode?: HooksGmailTailscaleMode; path?: string; /** Optional tailscale serve/funnel target (port, host:port, or full URL). */ target?: string; }; /** Optional model override for Gmail hook processing (provider/model or alias). */ model?: string; /** Optional thinking level override for Gmail hook processing. */ thinking?: "off" | "minimal" | "low" | "medium" | "high"; }; type InternalHookHandlerConfig = { /** Event key to listen for (e.g., 'command:new', 'session:start') */event: string; /** Path to handler module (workspace-relative) */ module: string; /** Export name from module (default: 'default') */ export?: string; }; type HookConfig = { enabled?: boolean; env?: Record; [key: string]: unknown; }; type HookInstallRecord = { source: "npm" | "archive" | "path"; spec?: string; sourcePath?: string; installPath?: string; version?: string; resolvedName?: string; resolvedVersion?: string; resolvedSpec?: string; integrity?: string; shasum?: string; resolvedAt?: string; installedAt?: string; hooks?: string[]; }; type InternalHooksConfig = { /** Enable hooks system */enabled?: boolean; /** Legacy: List of internal hook handlers to register (still supported) */ handlers?: InternalHookHandlerConfig[]; /** Per-hook configuration overrides */ entries?: Record; /** Load configuration */ load?: { /** Additional hook directories to scan */extraDirs?: string[]; }; /** Install records for hook packs or hooks */ installs?: Record; }; type HooksConfig = { enabled?: boolean; path?: string; token?: string; /** * Default session key used for hook agent runs when no request/mapping session key is used. * If omitted, FasedAgent generates `hook:` per request. */ defaultSessionKey?: string; /** * Allow `sessionKey` from external `/hooks/agent` request payloads. * Default: false. */ allowRequestSessionKey?: boolean; /** * Optional allowlist for explicit session keys (request + mapping). Example: ["hook:"]. * Empty/omitted means no prefix restriction. */ allowedSessionKeyPrefixes?: string[]; /** * Restrict explicit hook `agentId` routing to these agent ids. * Omit or include `*` to allow any agent. Set `[]` to deny all explicit `agentId` routing. */ allowedAgentIds?: string[]; maxBodyBytes?: number; presets?: string[]; transformsDir?: string; mappings?: HookMappingConfig[]; gmail?: HooksGmailConfig; /** Internal agent event hooks */ internal?: InternalHooksConfig; }; //#endregion //#region src/config/types.mcp.d.ts type McpServerConfig = Record; type McpConfig = { /** Owner-managed MCP servers exposed to the native Pi runtime. */servers?: Record; }; //#endregion //#region src/config/types.memory.d.ts type MemoryBackend = "builtin" | "qmd"; type MemoryCitationsMode = "auto" | "on" | "off"; type MemoryQmdSearchMode = "query" | "search" | "vsearch"; type MemoryConfig = { backend?: MemoryBackend; citations?: MemoryCitationsMode; qmd?: MemoryQmdConfig; }; type MemoryQmdConfig = { command?: string; mcporter?: MemoryQmdMcporterConfig; searchMode?: MemoryQmdSearchMode; includeDefaultMemory?: boolean; paths?: MemoryQmdIndexPath[]; sessions?: MemoryQmdSessionConfig; update?: MemoryQmdUpdateConfig; limits?: MemoryQmdLimitsConfig; scope?: SessionSendPolicyConfig; }; type MemoryQmdMcporterConfig = { /** * Route QMD searches through mcporter (MCP runtime) instead of spawning `qmd` per query. * Requires: * - `mcporter` installed and on PATH * - A configured mcporter server that runs `qmd mcp` with `lifecycle: keep-alive` */ enabled?: boolean; /** mcporter server name (defaults to "qmd") */ serverName?: string; /** Start the mcporter daemon automatically (defaults to true when enabled). */ startDaemon?: boolean; }; type MemoryQmdIndexPath = { path: string; name?: string; pattern?: string; }; type MemoryQmdSessionConfig = { enabled?: boolean; exportDir?: string; retentionDays?: number; }; type MemoryQmdUpdateConfig = { interval?: string; debounceMs?: number; onBoot?: boolean; waitForBootSync?: boolean; embedInterval?: string; commandTimeoutMs?: number; updateTimeoutMs?: number; embedTimeoutMs?: number; }; type MemoryQmdLimitsConfig = { maxResults?: number; maxSnippetChars?: number; maxInjectedChars?: number; timeoutMs?: number; }; //#endregion //#region src/shared/model-thinking.d.ts declare const XHIGH_THINKING_LEVELS: readonly ["off", "minimal", "low", "medium", "high", "xhigh"]; declare const MAX_THINKING_LEVELS: readonly ["off", "low", "medium", "high", "xhigh", "max"]; declare const ULTRA_THINKING_LEVELS: readonly ["off", "low", "medium", "high", "xhigh", "max", "ultra"]; type ModelThinkingLevel = (typeof XHIGH_THINKING_LEVELS)[number] | (typeof MAX_THINKING_LEVELS)[number] | (typeof ULTRA_THINKING_LEVELS)[number]; type ModelThinkingMode = "openai-reasoning-effort" | "anthropic-thinking-budget" | "anthropic-adaptive" | "google-thinking-budget" | "xai-reasoning-effort" | "xai-multi-agent-effort" | "mistral-reasoning-effort" | "volcengine-reasoning-effort" | "byteplus-thinking-type" | "zai-binary" | "qwen-thinking" | "moonshot-thinking" | "generic-reasoning"; //#endregion //#region src/config/types.models.d.ts declare const MODEL_APIS: readonly ["openai-completions", "openai-responses", "openai-codex-responses", "anthropic-messages", "google-generative-ai", "github-copilot", "ollama"]; type ModelApi = (typeof MODEL_APIS)[number]; type ModelCompatConfig = { responsesLite?: boolean; supportsStore?: boolean; supportsDeveloperRole?: boolean; supportsReasoningEffort?: boolean; supportsUsageInStreaming?: boolean; supportsTools?: boolean; supportsStrictMode?: boolean; maxTokensField?: "max_completion_tokens" | "max_tokens"; thinkingFormat?: "openai" | "zai" | "qwen"; requiresToolResultName?: boolean; requiresAssistantAfterToolResult?: boolean; requiresThinkingAsText?: boolean; requiresMistralToolIds?: boolean; }; type ModelCapabilityConfig = { tools?: boolean; json?: boolean; audio?: boolean; video?: boolean; speech?: boolean; streaming?: boolean; fixedReasoning?: boolean; thinkingLevels?: ModelThinkingLevel[]; defaultThinkingLevel?: ModelThinkingLevel; thinkingMode?: ModelThinkingMode; reasoningBudgetSupported?: boolean; }; type ModelProviderAuthMode = "api-key" | "oauth" | "token" | "aws-sdk"; type ModelProviderRequestConfig = { allowPrivateNetwork?: boolean; }; type ModelDefinitionConfig = { id: string; name: string; api?: ModelApi; reasoning?: boolean; input?: Array<"text" | "image">; cost: { input: number; output: number; cacheRead: number; cacheWrite: number; }; contextWindow?: number; /** Legacy/runtime alias for usable context after provider-side reservations. */ contextTokens?: number; maxTokens?: number; baseUrl?: string; headers?: Record; compat?: ModelCompatConfig; capabilities?: ModelCapabilityConfig; }; type ModelProviderConfig = { baseUrl?: string; apiKey?: SecretInput; auth?: ModelProviderAuthMode; api?: ModelApi; headers?: Record; authHeader?: boolean; request?: ModelProviderRequestConfig; models: ModelDefinitionConfig[]; }; type ModelsConfig = { mode?: "merge" | "replace"; providers?: Record; }; //#endregion //#region src/config/types.node-host.d.ts type NodeHostBrowserProxyConfig = { /** Enable the browser proxy on the node host (default: true). */enabled?: boolean; /** Optional allowlist of profile names exposed via the proxy. */ allowProfiles?: string[]; }; type NodeHostConfig = { /** Browser proxy settings for node hosts. */browserProxy?: NodeHostBrowserProxyConfig; }; //#endregion //#region src/config/types.installs.d.ts type InstallRecordBase = { source: "npm" | "archive" | "path" | "clawhub"; spec?: string; sourcePath?: string; installPath?: string; version?: string; resolvedName?: string; resolvedVersion?: string; resolvedSpec?: string; integrity?: string; shasum?: string; resolvedAt?: string; installedAt?: string; clawhubUrl?: string; clawhubArtifactUrl?: string; clawhubPackage?: string; clawhubFamily?: "code-plugin" | "bundle-plugin"; clawhubChannel?: "official" | "community" | "private"; artifactKind?: "legacy-zip" | "npm-pack" | "clawpack"; artifactFormat?: "zip" | "tgz"; npmIntegrity?: string; npmShasum?: string; npmTarballName?: string; clawpackSha256?: string; clawpackSpecVersion?: number; clawpackManifestSha256?: string; clawpackSize?: number; securityState?: string; scanState?: string; moderationState?: string; readinessPhase?: string; verificationTier?: string; verificationSourceRepo?: string; verificationSourceCommit?: string; verificationHasProvenance?: boolean; }; //#endregion //#region src/config/types.plugins.d.ts type PluginEntryConfig = { enabled?: boolean; config?: Record; runtime?: PluginEntryRuntimeConfig; }; type PluginEntryRuntimeConfig = { helpers?: { sessions?: { /** Allow future read-only session metadata/status helper access. */read?: boolean; }; }; adminRpcActions?: { /** Explicit per-method admin/write RPC grants. No generic dispatcher is implied. */allow?: Array<{ method?: "chat.inject" | "push.test" | "web.login.start" | "web.login.wait"; /** * Trusted source keys that may use this grant, for example * "origin:bundled" or "source:/opt/fased/plugins/demo". */ sources?: string[]; /** Must remain true for the first plugin-admin RPC access model. */ requireOperatorApproval?: boolean; }>; }; }; type PluginSlotsConfig = { /** Select which plugin owns the memory slot ("none" disables memory plugins). */memory?: string; }; type PluginsLoadConfig = { /** Additional plugin/extension paths to load. */paths?: string[]; }; type PluginInstallRecord = InstallRecordBase; type PluginsConfig = { /** Enable or disable plugin loading. */enabled?: boolean; /** Optional plugin allowlist (plugin ids). */ allow?: string[]; /** Optional plugin denylist (plugin ids). */ deny?: string[]; load?: PluginsLoadConfig; slots?: PluginSlotsConfig; entries?: Record; installs?: Record; }; //#endregion //#region src/config/types.skills.d.ts type SkillConfig = { enabled?: boolean; apiKey?: SecretInput; env?: Record; config?: Record; }; type SkillsLoadConfig = { /** * Additional skill folders to scan (lowest precedence). * Each directory should contain skill subfolders with `SKILL.md`. */ extraDirs?: string[]; /** Watch skill folders for changes and refresh the skills snapshot. */ watch?: boolean; /** Debounce for the skills watcher (ms). */ watchDebounceMs?: number; }; type SkillsInstallConfig = { preferBrew?: boolean; nodeManager?: "npm" | "pnpm" | "yarn" | "bun"; }; type SkillsLimitsConfig = { /** Max number of immediate child directories to consider under a skills root before treating it as suspicious. */maxCandidatesPerRoot?: number; /** Max number of skills to load per skills source (bundled/managed/workspace/extra). */ maxSkillsLoadedPerSource?: number; /** Max number of skills to include in the model-facing skills prompt. */ maxSkillsInPrompt?: number; /** Max characters for the model-facing skills prompt block (approx). */ maxSkillsPromptChars?: number; /** Max size (bytes) allowed for a SKILL.md file to be considered. */ maxSkillFileBytes?: number; }; type SkillsMarketplaceConfig = { /** Registries trusted for installed skills that request wallet actions. Defaults to https://clawhub.com. */allowRegistries?: string[]; }; type SkillsConfig = { /** Optional bundled-skill allowlist (only affects bundled skills). */allowBundled?: string[]; load?: SkillsLoadConfig; install?: SkillsInstallConfig; marketplace?: SkillsMarketplaceConfig; limits?: SkillsLimitsConfig; entries?: Record; }; //#endregion //#region src/config/types.fased.d.ts type FasedAgentConfig = { meta?: { /** Last Fased Agent version that wrote this config. */lastTouchedVersion?: string; /** ISO timestamp when this config was last written. */ lastTouchedAt?: string; }; auth?: AuthConfig; acp?: AcpConfig; env?: { /** Opt-in: import missing secrets from a login shell environment (exec `$SHELL -l -c 'env -0'`). */shellEnv?: { enabled?: boolean; /** Timeout for the login shell exec (ms). Default: 15000. */ timeoutMs?: number; }; /** Inline env vars to apply when not already present in the process env. */ vars?: Record; /** Sugar: allow env vars directly under env (string values only). */ [key: string]: string | Record | { enabled?: boolean; timeoutMs?: number; } | undefined; }; wizard?: { lastRunAt?: string; lastRunVersion?: string; lastRunCommit?: string; lastRunCommand?: string; lastRunMode?: "local" | "remote"; }; diagnostics?: DiagnosticsConfig; logging?: LoggingConfig; update?: { /** Built-in self-update channel for package installs ("stable", "beta", or "dev"). */channel?: "stable" | "beta" | "dev"; /** Check for package self-updates on gateway start. Default: false (opt-in). */ checkOnStart?: boolean; /** Core auto-update policy for package installs. */ auto?: { /** Enable background auto-update checks and apply logic. Default: false. */enabled?: boolean; /** Stable channel minimum delay before auto-apply. Default: 6. */ stableDelayHours?: number; /** Additional stable-channel jitter window. Default: 12. */ stableJitterHours?: number; /** Beta channel check cadence. Default: 1 hour. */ betaCheckIntervalHours?: number; }; }; browser?: BrowserConfig; ui?: { /** Accent color for Fased Agent UI chrome (hex). */seamColor?: string; assistant?: { /** Assistant display name for UI surfaces. */name?: string; /** Assistant avatar (emoji, short text, or image URL/data URI). */ avatar?: string; }; }; secrets?: SecretsConfig; skills?: SkillsConfig; plugins?: PluginsConfig; mcp?: McpConfig; models?: ModelsConfig; nodeHost?: NodeHostConfig; agents?: AgentsConfig; tools?: ToolsConfig; bindings?: AgentBinding[]; broadcast?: BroadcastConfig; messages?: MessagesConfig; commands?: CommandsConfig; approvals?: ApprovalsConfig; session?: SessionConfig; web?: WebConfig; channels?: ChannelsConfig; cron?: CronConfig; hooks?: HooksConfig; discovery?: DiscoveryConfig; federation?: FederationConfig; canvasHost?: CanvasHostConfig; talk?: TalkConfig; gateway?: GatewayConfig; memory?: MemoryConfig; wallet?: WalletConfig; }; //#endregion //#region src/discord/send.shared.d.ts type DiscordSendComponentFactory = (text: string) => TopLevelComponents[]; type DiscordSendComponents = TopLevelComponents[] | DiscordSendComponentFactory; type DiscordSendEmbeds = Array; //#endregion //#region src/discord/send.outbound.d.ts type DiscordSendOpts = { token?: string; accountId?: string; mediaUrl?: string; mediaLocalRoots?: readonly string[]; verbose?: boolean; rest?: RequestClient; replyTo?: string; retry?: RetryConfig; components?: DiscordSendComponents; embeds?: DiscordSendEmbeds; silent?: boolean; }; declare function sendMessageDiscord(to: string, text: string, opts?: DiscordSendOpts): Promise; declare function sendPollDiscord(to: string, poll: PollInput, opts?: DiscordSendOpts & { content?: string; }): Promise; //#endregion //#region src/imessage/accounts.d.ts type ResolvedIMessageAccount = { accountId: string; enabled: boolean; name?: string; config: IMessageAccountConfig; configured: boolean; }; declare const listIMessageAccountIds: (cfg: FasedAgentConfig) => string[]; declare const resolveDefaultIMessageAccountId: (cfg: FasedAgentConfig) => string; declare function resolveIMessageAccount(params: { cfg: FasedAgentConfig; accountId?: string | null; }): ResolvedIMessageAccount; //#endregion //#region src/runtime.d.ts type RuntimeEnv = { log: (...args: unknown[]) => void; error: (...args: unknown[]) => void; exit: (code: number) => void; }; //#endregion //#region src/imessage/client.d.ts type IMessageRpcNotification = { method: string; params?: unknown; }; type IMessageRpcClientOptions = { cliPath?: string; dbPath?: string; runtime?: RuntimeEnv; onNotification?: (msg: IMessageRpcNotification) => void; }; declare class IMessageRpcClient { private readonly cliPath; private readonly dbPath?; private readonly runtime?; private readonly onNotification?; private readonly pending; private readonly closed; private closedResolve; private child; private reader; private nextId; constructor(opts?: IMessageRpcClientOptions); start(): Promise; stop(): Promise; waitForClose(): Promise; request(method: string, params?: Record, opts?: { timeoutMs?: number; }): Promise; private handleLine; private failAll; } //#endregion //#region src/imessage/targets.d.ts type IMessageService = "imessage" | "sms" | "auto"; //#endregion //#region src/imessage/send.d.ts type IMessageSendOpts = { cliPath?: string; dbPath?: string; service?: IMessageService; region?: string; accountId?: string; replyToId?: string; mediaUrl?: string; mediaLocalRoots?: readonly string[]; maxBytes?: number; timeoutMs?: number; chatId?: number; client?: IMessageRpcClient; config?: ReturnType; account?: ResolvedIMessageAccount; resolveAttachmentImpl?: (mediaUrl: string, maxBytes: number, options?: { localRoots?: readonly string[]; }) => Promise<{ path: string; contentType?: string; }>; createClient?: (params: { cliPath: string; dbPath?: string; }) => Promise; }; type IMessageSendResult = { messageId: string; }; declare function sendMessageIMessage(to: string, text: string, opts?: IMessageSendOpts): Promise; //#endregion //#region src/signal/format.d.ts type SignalTextStyle = "BOLD" | "ITALIC" | "STRIKETHROUGH" | "MONOSPACE" | "SPOILER"; type SignalTextStyleRange = { start: number; length: number; style: SignalTextStyle; }; //#endregion //#region src/signal/send.d.ts type SignalSendOpts = { baseUrl?: string; account?: string; accountId?: string; mediaUrl?: string; mediaLocalRoots?: readonly string[]; maxBytes?: number; timeoutMs?: number; textMode?: "markdown" | "plain"; textStyles?: SignalTextStyleRange[]; }; type SignalSendResult = { messageId: string; timestamp?: number; }; declare function sendMessageSignal(to: string, text: string, opts?: SignalSendOpts): Promise; //#endregion //#region src/slack/send.d.ts type SlackSendIdentity = { username?: string; iconUrl?: string; iconEmoji?: string; }; type SlackSendOpts = { token?: string; accountId?: string; mediaUrl?: string; mediaLocalRoots?: readonly string[]; client?: WebClient; threadTs?: string; identity?: SlackSendIdentity; blocks?: (Block | KnownBlock)[]; }; type SlackSendResult = { messageId: string; channelId: string; }; declare function sendMessageSlack(to: string, message: string, opts?: SlackSendOpts): Promise; //#endregion //#region src/telegram/button-types.d.ts type TelegramButtonStyle = "danger" | "success" | "primary"; type TelegramInlineButton = { text: string; callback_data: string; style?: TelegramButtonStyle; }; type TelegramInlineButtons = ReadonlyArray>; //#endregion //#region src/telegram/send.d.ts type TelegramApi = Bot["api"]; type TelegramApiOverride = Partial; type TelegramSendOpts = { token?: string; accountId?: string; verbose?: boolean; mediaUrl?: string; mediaLocalRoots?: readonly string[]; maxBytes?: number; api?: TelegramApiOverride; retry?: RetryConfig; textMode?: "markdown" | "html"; plainText?: string; /** Send audio as voice message (voice bubble) instead of audio file. Defaults to false. */ asVoice?: boolean; /** Send video as video note (voice bubble) instead of regular video. Defaults to false. */ asVideoNote?: boolean; /** Send message silently (no notification). Defaults to false. */ silent?: boolean; /** Message ID to reply to (for threading) */ replyToMessageId?: number; /** Quote text for Telegram reply_parameters. */ quoteText?: string; /** Forum topic thread ID (for forum supergroups) */ messageThreadId?: number; /** Inline keyboard buttons (reply markup). */ buttons?: TelegramInlineButtons; }; type TelegramSendResult = { messageId: string; chatId: string; }; declare function sendMessageTelegram(to: string, text: string, opts?: TelegramSendOpts): Promise; type TelegramPollOpts = { token?: string; accountId?: string; verbose?: boolean; api?: TelegramApiOverride; retry?: RetryConfig; /** Message ID to reply to (for threading) */ replyToMessageId?: number; /** Forum topic thread ID (for forum supergroups) */ messageThreadId?: number; /** Send message silently (no notification). Defaults to false. */ silent?: boolean; /** Whether votes are anonymous. Defaults to true (Telegram default). */ isAnonymous?: boolean; }; /** * Send a poll to a Telegram chat. * @param to - Chat ID or username (e.g., "123456789" or "@username") * @param poll - Poll input with question, options, maxSelections, and optional durationHours * @param opts - Optional configuration */ declare function sendPollTelegram(to: string, poll: PollInput, opts?: TelegramPollOpts): Promise<{ messageId: string; chatId: string; pollId?: string; }>; //#endregion //#region src/web/outbound.d.ts declare function sendMessageWhatsApp(to: string, body: string, options: { verbose: boolean; mediaUrl?: string; mediaLocalRoots?: readonly string[]; gifPlayback?: boolean; accountId?: string; replyToId?: string; }): Promise<{ messageId: string; toJid: string; }>; declare function sendPollWhatsApp(to: string, poll: PollInput, options: { verbose: boolean; accountId?: string; }): Promise<{ messageId: string; toJid: string; }>; //#endregion //#region src/infra/outbound/identity.d.ts type OutboundIdentity = { name?: string; avatarUrl?: string; emoji?: string; }; //#endregion //#region src/media-understanding/types.d.ts type MediaUnderstandingKind = "audio.transcription" | "video.description" | "image.description"; type MediaUnderstandingCapability = "image" | "audio" | "video"; type MediaUnderstandingOutput = { kind: MediaUnderstandingKind; attachmentIndex: number; text: string; provider: string; model?: string; }; type MediaUnderstandingDecisionOutcome = "success" | "skipped" | "disabled" | "no-attachment" | "scope-deny"; type MediaUnderstandingModelDecision = { provider?: string; model?: string; type: "provider" | "cli"; outcome: "success" | "skipped" | "failed"; reason?: string; }; type MediaUnderstandingAttachmentDecision = { attachmentIndex: number; attempts: MediaUnderstandingModelDecision[]; chosen?: MediaUnderstandingModelDecision; }; type MediaUnderstandingDecision = { capability: MediaUnderstandingCapability; outcome: MediaUnderstandingDecisionOutcome; attachments: MediaUnderstandingAttachmentDecision[]; }; //#endregion //#region src/telegram/bot/types.d.ts /** Telegram sticker metadata for context enrichment and caching. */ interface StickerMetadata { /** Emoji associated with the sticker. */ emoji?: string; /** Name of the sticker set the sticker belongs to. */ setName?: string; /** Telegram file_id for sending the sticker back. */ fileId?: string; /** Stable file_unique_id for cache deduplication. */ fileUniqueId?: string; /** Cached description from previous vision processing (skip re-processing if present). */ cachedDescription?: string; } //#endregion //#region src/auto-reply/commands-registry.types.d.ts type CommandArgValue = string | number | boolean | bigint; type CommandArgValues = Record; type CommandArgs = { raw?: string; values?: CommandArgValues; }; type CommandNormalizeOptions = { botUsername?: string; }; type ShouldHandleTextCommandsParams = { cfg: FasedAgentConfig; surface: string; commandSource?: "text" | "native"; }; //#endregion //#region src/auto-reply/templating.d.ts /** Valid message channels for routing. */ type OriginatingChannelType = ChannelId | InternalMessageChannel; type MsgContext = { Body?: string; /** * Agent prompt body (may include envelope/history/context). Prefer this for prompt shaping. * Should use real newlines (`\n`), not escaped `\\n`. */ BodyForAgent?: string; /** * Recent chat history for context (untrusted user content). Prefer passing this * as structured context blocks in the user prompt rather than rendering plaintext envelopes. */ InboundHistory?: Array<{ sender: string; body: string; timestamp?: number; }>; /** * Raw message body without structural context (history, sender labels). * Legacy alias for CommandBody. Falls back to Body if not set. */ RawBody?: string; /** * Prefer for command detection; RawBody is treated as legacy alias. */ CommandBody?: string; /** * Command parsing body. Prefer this over CommandBody/RawBody when set. * Should be the "clean" text (no history/sender context). */ BodyForCommands?: string; CommandArgs?: CommandArgs; From?: string; To?: string; SessionKey?: string; /** Provider account id (multi-account). */ AccountId?: string; ParentSessionKey?: string; MessageSid?: string; /** Provider-specific full message id when MessageSid is a shortened alias. */ MessageSidFull?: string; MessageSids?: string[]; MessageSidFirst?: string; MessageSidLast?: string; ReplyToId?: string; /** Provider-specific full reply-to id when ReplyToId is a shortened alias. */ ReplyToIdFull?: string; ReplyToBody?: string; ReplyToSender?: string; ReplyToIsQuote?: boolean; /** Forward origin from the reply target (when reply_to_message is a forwarded message). */ ReplyToForwardedFrom?: string; ReplyToForwardedFromType?: string; ReplyToForwardedFromId?: string; ReplyToForwardedFromUsername?: string; ReplyToForwardedFromTitle?: string; ReplyToForwardedDate?: number; ForwardedFrom?: string; ForwardedFromType?: string; ForwardedFromId?: string; ForwardedFromUsername?: string; ForwardedFromTitle?: string; ForwardedFromSignature?: string; ForwardedFromChatType?: string; ForwardedFromMessageId?: number; ForwardedDate?: number; ThreadStarterBody?: string; /** Full thread history when starting a new thread session. */ ThreadHistoryBody?: string; IsFirstThreadTurn?: boolean; ThreadLabel?: string; MediaPath?: string; MediaUrl?: string; MediaType?: string; MediaDir?: string; MediaPaths?: string[]; MediaUrls?: string[]; MediaTypes?: string[]; /** Telegram sticker metadata (emoji, set name, file IDs, cached description). */ Sticker?: StickerMetadata; /** True when current-turn sticker media is present in MediaPaths (false for cached-description path). */ StickerMediaIncluded?: boolean; OutputDir?: string; OutputBase?: string; /** Remote host for SCP when media lives on a different machine (e.g., fased@192.168.64.3). */ MediaRemoteHost?: string; Transcript?: string; MediaUnderstanding?: MediaUnderstandingOutput[]; MediaUnderstandingDecisions?: MediaUnderstandingDecision[]; LinkUnderstanding?: string[]; Prompt?: string; MaxChars?: number; ChatType?: string; /** Human label for envelope headers (conversation label, not sender). */ ConversationLabel?: string; GroupSubject?: string; /** Human label for channel-like group conversations (e.g. #general, #support). */ GroupChannel?: string; GroupSpace?: string; GroupMembers?: string; GroupSystemPrompt?: string; /** Untrusted metadata that must not be treated as system instructions. */ UntrustedContext?: string[]; /** Explicit owner allowlist overrides (trusted, configuration-derived). */ OwnerAllowFrom?: Array; SenderName?: string; SenderId?: string; SenderUsername?: string; SenderTag?: string; SenderE164?: string; Timestamp?: number; /** Provider label (e.g. whatsapp, telegram). */ Provider?: string; /** Provider surface label (e.g. discord, slack). Prefer this over `Provider` when available. */ Surface?: string; WasMentioned?: boolean; CommandAuthorized?: boolean; CommandSource?: "text" | "native"; CommandTargetSessionKey?: string; /** Gateway client scopes when the message originates from the gateway. */ GatewayClientScopes?: string[]; /** Thread identifier (Telegram topic id or Matrix thread event id). */ MessageThreadId?: string | number; /** Telegram forum supergroup marker. */ IsForum?: boolean; /** * Originating channel for reply routing. * When set, replies should be routed back to this provider * instead of using lastChannel from the session. */ OriginatingChannel?: OriginatingChannelType; /** * Originating destination for reply routing. * The chat/channel/user ID where the reply should be sent. */ OriginatingTo?: string; /** * Messages from hooks to be included in the response. * Used for hook confirmation messages like "Session context saved to memory". */ HookMessages?: string[]; }; type FinalizedMsgContext = Omit & { /** * Always set by finalizeInboundContext(). * Default-deny: missing/undefined becomes false. */ CommandAuthorized: boolean; }; //#endregion //#region src/infra/outbound/targets.d.ts type OutboundChannel = DeliverableMessageChannel | "none"; //#endregion //#region src/infra/outbound/deliver.d.ts type SendMatrixMessage = (to: string, text: string, opts?: { mediaUrl?: string; replyToId?: string; threadId?: string; timeoutMs?: number; }) => Promise<{ messageId: string; roomId: string; }>; type OutboundSendDeps = { sendWhatsApp?: typeof sendMessageWhatsApp; sendTelegram?: typeof sendMessageTelegram; sendDiscord?: typeof sendMessageDiscord; sendSlack?: typeof sendMessageSlack; sendSignal?: typeof sendMessageSignal; sendIMessage?: typeof sendMessageIMessage; sendMatrix?: SendMatrixMessage; sendMSTeams?: (to: string, text: string, opts?: { mediaUrl?: string; }) => Promise<{ messageId: string; conversationId: string; }>; }; type OutboundDeliveryResult = { channel: Exclude; messageId: string; chatId?: string; channelId?: string; roomId?: string; conversationId?: string; timestamp?: number; toJid?: string; pollId?: string; meta?: Record; }; //#endregion //#region src/channels/ids.d.ts declare const CHAT_CHANNEL_ORDER: readonly ["telegram", "whatsapp", "discord", "irc", "googlechat", "slack", "signal", "imessage"]; type ChatChannelId = (typeof CHAT_CHANNEL_ORDER)[number]; //#endregion //#region src/channels/registry.d.ts type ChatChannelMeta = ChannelMeta; declare function getChatChannelMeta(id: ChatChannelId): ChatChannelMeta; //#endregion //#region src/channels/plugins/types.core.d.ts type ChannelId = ChatChannelId | (string & {}); type ChannelOutboundTargetMode = "explicit" | "implicit" | "heartbeat"; type ChannelAgentTool = AgentTool & { ownerOnly?: boolean; }; type ChannelAgentToolFactory = (params: { cfg?: FasedAgentConfig; }) => ChannelAgentTool[]; type ChannelSetupInput = { name?: string; token?: string; tokenFile?: string; botToken?: string; appToken?: string; signalNumber?: string; cliPath?: string; dbPath?: string; service?: "imessage" | "sms" | "auto"; region?: string; authDir?: string; httpUrl?: string; httpHost?: string; httpPort?: string; webhookPath?: string; webhookUrl?: string; audienceType?: string; audience?: string; useEnv?: boolean; homeserver?: string; userId?: string; accessToken?: string; password?: string; deviceName?: string; initialSyncLimit?: number; ship?: string; url?: string; code?: string; groupChannels?: string[]; dmAllowlist?: string[]; autoDiscoverChannels?: boolean; }; type ChannelStatusIssue = { channel: ChannelId; accountId: string; kind: "intent" | "permissions" | "config" | "auth" | "runtime"; message: string; fix?: string; }; type ChannelAccountState = "linked" | "not linked" | "configured" | "not configured" | "enabled" | "disabled"; type ChannelHeartbeatDeps = { webAuthExists?: () => Promise; hasActiveWebListener?: () => boolean; }; type ChannelMeta = { id: ChannelId; label: string; selectionLabel: string; docsPath: string; docsLabel?: string; blurb: string; order?: number; aliases?: string[]; selectionDocsPrefix?: string; selectionDocsOmitLabel?: boolean; selectionExtras?: string[]; detailLabel?: string; systemImage?: string; showConfigured?: boolean; quickstartAllowFrom?: boolean; forceAccountBinding?: boolean; preferSessionLookupForAnnounceTarget?: boolean; preferOver?: string[]; }; type ChannelAccountSnapshot = { accountId: string; name?: string; enabled?: boolean; configured?: boolean; linked?: boolean; running?: boolean; connected?: boolean; reconnectAttempts?: number; lastConnectedAt?: number | null; lastDisconnect?: string | { at: number; status?: number; error?: string; loggedOut?: boolean; } | null; lastMessageAt?: number | null; lastEventAt?: number | null; lastError?: string | null; lastStartAt?: number | null; lastStopAt?: number | null; lastInboundAt?: number | null; lastOutboundAt?: number | null; mode?: string; dmPolicy?: string; allowFrom?: string[]; tokenSource?: string; botTokenSource?: string; appTokenSource?: string; credentialSource?: string; secretSource?: string; audienceType?: string; audience?: string; webhookPath?: string; webhookUrl?: string; baseUrl?: string; allowUnmentionedGroups?: boolean; cliPath?: string | null; dbPath?: string | null; port?: number | null; probe?: unknown; lastProbeAt?: number | null; audit?: unknown; application?: unknown; bot?: unknown; publicKey?: string | null; profile?: unknown; channelAccessToken?: string; channelSecret?: string; }; type ChannelLogSink = { info: (msg: string) => void; warn: (msg: string) => void; error: (msg: string) => void; debug?: (msg: string) => void; }; type ChannelGroupContext = { cfg: FasedAgentConfig; groupId?: string | null; /** Human label for channel-like group conversations (e.g. #general). */ groupChannel?: string | null; groupSpace?: string | null; accountId?: string | null; senderId?: string | null; senderName?: string | null; senderUsername?: string | null; senderE164?: string | null; }; type ChannelCapabilities = { chatTypes: Array; polls?: boolean; reactions?: boolean; edit?: boolean; unsend?: boolean; reply?: boolean; effects?: boolean; groupManagement?: boolean; threads?: boolean; media?: boolean; nativeCommands?: boolean; blockStreaming?: boolean; }; type ChannelSecurityDmPolicy = { policy: string; allowFrom?: Array | null; policyPath?: string; allowFromPath: string; approveHint: string; normalizeEntry?: (raw: string) => string; }; type ChannelSecurityContext = { cfg: FasedAgentConfig; accountId?: string | null; account: ResolvedAccount; }; type ChannelMentionAdapter = { stripPatterns?: (params: { ctx: MsgContext; cfg: FasedAgentConfig | undefined; agentId?: string; }) => string[]; stripMentions?: (params: { text: string; ctx: MsgContext; cfg: FasedAgentConfig | undefined; agentId?: string; }) => string; }; type ChannelStreamingAdapter = { blockStreamingCoalesceDefaults?: { minChars: number; idleMs: number; }; }; type ChannelThreadingAdapter = { resolveReplyToMode?: (params: { cfg: FasedAgentConfig; accountId?: string | null; chatType?: string | null; }) => "off" | "first" | "all"; /** * When replyToMode is "off", allow explicit reply tags/directives to keep replyToId. * * Default in shared reply flow: true for known providers; per-channel opt-out supported. */ allowExplicitReplyTagsWhenOff?: boolean; /** * Deprecated alias for allowExplicitReplyTagsWhenOff. * Kept for compatibility with older extensions/docks. */ allowTagsWhenOff?: boolean; buildToolContext?: (params: { cfg: FasedAgentConfig; accountId?: string | null; context: ChannelThreadingContext; hasRepliedRef?: { value: boolean; }; }) => ChannelThreadingToolContext | undefined; }; type ChannelThreadingContext = { Channel?: string; From?: string; To?: string; ChatType?: string; CurrentMessageId?: string | number; ReplyToId?: string; ReplyToIdFull?: string; ThreadLabel?: string; MessageThreadId?: string | number; }; type ChannelThreadingToolContext = { currentChannelId?: string; currentChannelProvider?: ChannelId; currentThreadTs?: string; currentMessageId?: string | number; replyToMode?: "off" | "first" | "all"; hasRepliedRef?: { value: boolean; }; /** * When true, skip cross-context decoration (e.g., "[from X]" prefix). * Use this for direct tool invocations where the agent is composing a new message, * not forwarding/relaying a message from another conversation. */ skipCrossContextDecoration?: boolean; }; type ChannelMessagingAdapter = { normalizeTarget?: (raw: string) => string | undefined; targetResolver?: { looksLikeId?: (raw: string, normalized?: string) => boolean; hint?: string; }; formatTargetDisplay?: (params: { target: string; display?: string; kind?: ChannelDirectoryEntryKind; }) => string; }; type ChannelAgentPromptAdapter = { messageToolHints?: (params: { cfg: FasedAgentConfig; accountId?: string | null; }) => string[]; }; type ChannelDirectoryEntryKind = "user" | "group" | "channel"; type ChannelDirectoryEntry = { kind: ChannelDirectoryEntryKind; id: string; name?: string; handle?: string; avatarUrl?: string; rank?: number; raw?: unknown; }; type ChannelMessageActionName$1 = ChannelMessageActionName$2; type ChannelMessageActionContext = { channel: ChannelId; action: ChannelMessageActionName$1; cfg: FasedAgentConfig; params: Record; mediaLocalRoots?: readonly string[]; accountId?: string | null; /** * Trusted sender id from inbound context. This is server-injected and must * never be sourced from tool/model-controlled params. */ requesterSenderId?: string | null; requesterAccountId?: string | null; requesterSenderName?: string | null; requesterSenderUsername?: string | null; requesterSenderE164?: string | null; senderIsOwner?: boolean; sessionId?: string | null; sessionKey?: string | null; agentId?: string | null; gateway?: { url?: string; token?: string; timeoutMs?: number; clientName: GatewayClientName; clientDisplayName?: string; mode: GatewayClientMode; }; toolContext?: ChannelThreadingToolContext; dryRun?: boolean; }; type ChannelToolSend = { to: string; accountId?: string | null; }; type ChannelMessageActionAdapter = { listActions?: (params: { cfg: FasedAgentConfig; }) => ChannelMessageActionName$1[]; supportsAction?: (params: { action: ChannelMessageActionName$1; }) => boolean; supportsButtons?: (params: { cfg: FasedAgentConfig; }) => boolean; supportsCards?: (params: { cfg: FasedAgentConfig; }) => boolean; extractToolSend?: (params: { args: Record; }) => ChannelToolSend | null; handleAction?: (ctx: ChannelMessageActionContext) => Promise>; }; type ChannelPollResult = { messageId: string; toJid?: string; channelId?: string; conversationId?: string; pollId?: string; }; type ChannelPollContext = { cfg: FasedAgentConfig; to: string; poll: PollInput; accountId?: string | null; threadId?: string | null; silent?: boolean; isAnonymous?: boolean; }; /** Minimal base for all channel probe results. Channel-specific probes extend this. */ type BaseProbeResult = { ok: boolean; error?: TError; }; /** Minimal base for token resolution results. */ type BaseTokenResolution = { token: string; source: string; }; //#endregion //#region src/channels/plugins/types.adapters.d.ts type ChannelSetupAdapter = { resolveAccountId?: (params: { cfg: FasedAgentConfig; accountId?: string; input?: ChannelSetupInput; }) => string; resolveBindingAccountId?: (params: { cfg: FasedAgentConfig; agentId: string; accountId?: string; }) => string | undefined; applyAccountName?: (params: { cfg: FasedAgentConfig; accountId: string; name?: string; }) => FasedAgentConfig; applyAccountConfig: (params: { cfg: FasedAgentConfig; accountId: string; input: ChannelSetupInput; }) => FasedAgentConfig; validateInput?: (params: { cfg: FasedAgentConfig; accountId: string; input: ChannelSetupInput; }) => string | null; }; type ChannelConfigAdapter = { listAccountIds: (cfg: FasedAgentConfig) => string[]; resolveAccount: (cfg: FasedAgentConfig, accountId?: string | null) => ResolvedAccount; defaultAccountId?: (cfg: FasedAgentConfig) => string; setAccountEnabled?: (params: { cfg: FasedAgentConfig; accountId: string; enabled: boolean; }) => FasedAgentConfig; deleteAccount?: (params: { cfg: FasedAgentConfig; accountId: string; }) => FasedAgentConfig; isEnabled?: (account: ResolvedAccount, cfg: FasedAgentConfig) => boolean; disabledReason?: (account: ResolvedAccount, cfg: FasedAgentConfig) => string; isConfigured?: (account: ResolvedAccount, cfg: FasedAgentConfig) => boolean | Promise; unconfiguredReason?: (account: ResolvedAccount, cfg: FasedAgentConfig) => string; describeAccount?: (account: ResolvedAccount, cfg: FasedAgentConfig) => ChannelAccountSnapshot; resolveAllowFrom?: (params: { cfg: FasedAgentConfig; accountId?: string | null; }) => Array | undefined; formatAllowFrom?: (params: { cfg: FasedAgentConfig; accountId?: string | null; allowFrom: Array; }) => string[]; resolveDefaultTo?: (params: { cfg: FasedAgentConfig; accountId?: string | null; }) => string | undefined; }; type ChannelGroupAdapter = { resolveRequireMention?: (params: ChannelGroupContext) => boolean | undefined; resolveGroupIntroHint?: (params: ChannelGroupContext) => string | undefined; resolveToolPolicy?: (params: ChannelGroupContext) => GroupToolPolicyConfig | undefined; }; type ChannelOutboundContext = { cfg: FasedAgentConfig; to: string; text: string; mediaUrl?: string; mediaLocalRoots?: readonly string[]; gifPlayback?: boolean; replyToId?: string | null; threadId?: string | number | null; accountId?: string | null; identity?: OutboundIdentity; deps?: OutboundSendDeps; silent?: boolean; }; type ChannelOutboundPayloadContext = ChannelOutboundContext & { payload: ReplyPayload; }; type ChannelOutboundAdapter = { deliveryMode: "direct" | "gateway" | "hybrid"; chunker?: ((text: string, limit: number) => string[]) | null; chunkerMode?: "text" | "markdown"; textChunkLimit?: number; pollMaxOptions?: number; resolveTarget?: (params: { cfg?: FasedAgentConfig; to?: string; allowFrom?: string[]; accountId?: string | null; mode?: ChannelOutboundTargetMode; }) => { ok: true; to: string; } | { ok: false; error: Error; }; sendPayload?: (ctx: ChannelOutboundPayloadContext) => Promise; sendText?: (ctx: ChannelOutboundContext) => Promise; sendMedia?: (ctx: ChannelOutboundContext) => Promise; sendPoll?: (ctx: ChannelPollContext) => Promise; }; type ChannelStatusAdapter = { defaultRuntime?: ChannelAccountSnapshot; buildChannelSummary?: (params: { account: ResolvedAccount; cfg: FasedAgentConfig; defaultAccountId: string; snapshot: ChannelAccountSnapshot; }) => Record | Promise>; probeAccount?: (params: { account: ResolvedAccount; timeoutMs: number; cfg: FasedAgentConfig; }) => Promise; auditAccount?: (params: { account: ResolvedAccount; timeoutMs: number; cfg: FasedAgentConfig; probe?: Probe; }) => Promise; buildAccountSnapshot?: (params: { account: ResolvedAccount; cfg: FasedAgentConfig; runtime?: ChannelAccountSnapshot; probe?: Probe; audit?: Audit; }) => ChannelAccountSnapshot | Promise; logSelfId?: (params: { account: ResolvedAccount; cfg: FasedAgentConfig; runtime: RuntimeEnv; includeChannelPrefix?: boolean; }) => void; resolveAccountState?: (params: { account: ResolvedAccount; cfg: FasedAgentConfig; configured: boolean; enabled: boolean; }) => ChannelAccountState; collectStatusIssues?: (accounts: ChannelAccountSnapshot[]) => ChannelStatusIssue[]; }; type ChannelGatewayContext = { cfg: FasedAgentConfig; accountId: string; account: ResolvedAccount; runtime: RuntimeEnv; abortSignal: AbortSignal; log?: ChannelLogSink; getStatus: () => ChannelAccountSnapshot; setStatus: (next: ChannelAccountSnapshot) => void; }; type ChannelLogoutResult = { cleared: boolean; loggedOut?: boolean; [key: string]: unknown; }; type ChannelLoginWithQrStartResult = { qrDataUrl?: string; message: string; }; type ChannelLoginWithQrWaitResult = { connected: boolean; message: string; }; type ChannelLogoutContext = { cfg: FasedAgentConfig; accountId: string; account: ResolvedAccount; runtime: RuntimeEnv; log?: ChannelLogSink; }; type ChannelPairingAdapter = { idLabel: string; normalizeAllowEntry?: (entry: string) => string; notifyApproval?: (params: { cfg: FasedAgentConfig; id: string; runtime?: RuntimeEnv; }) => Promise; }; type ChannelGatewayAdapter = { startAccount?: (ctx: ChannelGatewayContext) => Promise; stopAccount?: (ctx: ChannelGatewayContext) => Promise; loginWithQrStart?: (params: { accountId?: string; force?: boolean; timeoutMs?: number; verbose?: boolean; }) => Promise; loginWithQrWait?: (params: { accountId?: string; timeoutMs?: number; }) => Promise; logoutAccount?: (ctx: ChannelLogoutContext) => Promise; }; type ChannelAuthAdapter = { login?: (params: { cfg: FasedAgentConfig; accountId?: string | null; runtime: RuntimeEnv; verbose?: boolean; channelInput?: string | null; }) => Promise; }; type ChannelHeartbeatAdapter = { checkReady?: (params: { cfg: FasedAgentConfig; accountId?: string | null; deps?: ChannelHeartbeatDeps; }) => Promise<{ ok: boolean; reason: string; }>; resolveRecipients?: (params: { cfg: FasedAgentConfig; opts?: { to?: string; all?: boolean; }; }) => { recipients: string[]; source: string; }; }; type ChannelDirectorySelfParams = { cfg: FasedAgentConfig; accountId?: string | null; runtime: RuntimeEnv; }; type ChannelDirectoryListParams = { cfg: FasedAgentConfig; accountId?: string | null; query?: string | null; limit?: number | null; runtime: RuntimeEnv; }; type ChannelDirectoryListGroupMembersParams = { cfg: FasedAgentConfig; accountId?: string | null; groupId: string; limit?: number | null; runtime: RuntimeEnv; }; type ChannelDirectoryAdapter = { self?: (params: ChannelDirectorySelfParams) => Promise; listPeers?: (params: ChannelDirectoryListParams) => Promise; listPeersLive?: (params: ChannelDirectoryListParams) => Promise; listGroups?: (params: ChannelDirectoryListParams) => Promise; listGroupsLive?: (params: ChannelDirectoryListParams) => Promise; listGroupMembers?: (params: ChannelDirectoryListGroupMembersParams) => Promise; }; type ChannelResolveKind = "user" | "group"; type ChannelResolveResult = { input: string; resolved: boolean; id?: string; name?: string; note?: string; }; type ChannelResolverAdapter = { resolveTargets: (params: { cfg: FasedAgentConfig; accountId?: string | null; inputs: string[]; kind: ChannelResolveKind; runtime: RuntimeEnv; }) => Promise; }; type ChannelElevatedAdapter = { allowFromFallback?: (params: { cfg: FasedAgentConfig; accountId?: string | null; }) => Array | undefined; }; type ChannelCommandAdapter = { enforceOwnerForCommands?: boolean; skipWhenConfigEmpty?: boolean; }; type ChannelSecurityAdapter = { resolveDmPolicy?: (ctx: ChannelSecurityContext) => ChannelSecurityDmPolicy | null; collectWarnings?: (ctx: ChannelSecurityContext) => Promise | string[]; }; //#endregion //#region src/channels/plugins/types.d.ts type ChannelMessageActionName = ChannelMessageActionName$2; //#endregion //#region src/config/types.agent-defaults.d.ts type AgentModelEntryConfig = { alias?: string; /** Provider-specific API parameters (e.g., GLM-4.7 thinking mode). */ params?: Record; /** Enable streaming for this model (default: true, false for Ollama to avoid SDK issue #1205). */ streaming?: boolean; }; type AgentTaskModelConfig = AgentTaskModelRolesConfig; type AgentContextPruningConfig = { mode?: "off" | "cache-ttl"; /** TTL to consider cache expired (duration string, default unit: minutes). */ ttl?: string; keepLastAssistants?: number; softTrimRatio?: number; hardClearRatio?: number; minPrunableToolChars?: number; tools?: { allow?: string[]; deny?: string[]; }; softTrim?: { maxChars?: number; headChars?: number; tailChars?: number; }; hardClear?: { enabled?: boolean; placeholder?: string; }; }; type CliBackendConfig = { /** CLI command to execute (absolute path or on PATH). */command: string; /** Base args applied to every invocation. */ args?: string[]; /** Output parsing mode (default: json). */ output?: "json" | "text" | "jsonl"; /** Output parsing mode when resuming a CLI session. */ resumeOutput?: "json" | "text" | "jsonl"; /** Prompt input mode (default: arg). */ input?: "arg" | "stdin"; /** Max prompt length for arg mode (if exceeded, stdin is used). */ maxPromptArgChars?: number; /** Extra env vars injected for this CLI. */ env?: Record; /** Env vars to remove before launching this CLI. */ clearEnv?: string[]; /** Flag used to pass model id (e.g. --model). */ modelArg?: string; /** Model aliases mapping (config model id → CLI model id). */ modelAliases?: Record; /** Flag used to pass session id (e.g. --session-id). */ sessionArg?: string; /** Extra args used when resuming a session (use {sessionId} placeholder). */ sessionArgs?: string[]; /** Alternate args to use when resuming a session (use {sessionId} placeholder). */ resumeArgs?: string[]; /** When to pass session ids. */ sessionMode?: "always" | "existing" | "none"; /** JSON fields to read session id from (in order). */ sessionIdFields?: string[]; /** Flag used to pass system prompt. */ systemPromptArg?: string; /** System prompt behavior (append vs replace). */ systemPromptMode?: "append" | "replace"; /** When to send system prompt. */ systemPromptWhen?: "first" | "always" | "never"; /** Flag used to pass image paths. */ imageArg?: string; /** How to pass multiple images. */ imageMode?: "repeat" | "list"; /** Serialize runs for this CLI. */ serialize?: boolean; /** Runtime reliability tuning for this backend's process lifecycle. */ reliability?: { /** No-output watchdog tuning (fresh vs resumed runs). */watchdog?: { /** Fresh/new sessions (non-resume). */fresh?: { /** Fixed watchdog timeout in ms (overrides ratio when set). */noOutputTimeoutMs?: number; /** Fraction of overall timeout used when fixed timeout is not set. */ noOutputTimeoutRatio?: number; /** Lower bound for computed watchdog timeout. */ minMs?: number; /** Upper bound for computed watchdog timeout. */ maxMs?: number; }; /** Resume sessions. */ resume?: { /** Fixed watchdog timeout in ms (overrides ratio when set). */noOutputTimeoutMs?: number; /** Fraction of overall timeout used when fixed timeout is not set. */ noOutputTimeoutRatio?: number; /** Lower bound for computed watchdog timeout. */ minMs?: number; /** Upper bound for computed watchdog timeout. */ maxMs?: number; }; }; }; }; type AgentDefaultsConfig = { /** Primary model and fallbacks (provider/model). Accepts string or {primary,fallbacks}. */model?: AgentModelConfig; /** Explicit task model slots. Tasks never infer provider-specific fallback models. */ taskModels?: AgentTaskModelConfig; /** Optional image-capable model and fallbacks (provider/model). Accepts string or {primary,fallbacks}. */ imageModel?: AgentModelConfig; /** Optional image-generation model and fallbacks (provider/model). Accepts string or {primary,fallbacks}. */ imageGenerationModel?: AgentModelConfig; /** Optional video-generation model and fallbacks (provider/model). Accepts string or {primary,fallbacks}. */ videoGenerationModel?: AgentModelConfig; /** Optional music-generation model and fallbacks (provider/model). Accepts string or {primary,fallbacks}. */ musicGenerationModel?: AgentModelConfig; /** Legacy PDF model override used by PDF-capable tool registration tests. */ pdfModel?: AgentModelConfig; /** Model catalog with optional aliases (full provider/model keys). */ models?: Record; /** Agent working directory (preferred). Used as the default cwd for agent runs. */ workspace?: string; /** Optional repository root for system prompt runtime line (overrides auto-detect). */ repoRoot?: string; /** Skip bootstrap (BOOTSTRAP.md creation, etc.) for pre-configured deployments. */ skipBootstrap?: boolean; /** Max chars for injected bootstrap files before truncation (default: 20000). */ bootstrapMaxChars?: number; /** Max total chars across all injected bootstrap files (default: 150000). */ bootstrapTotalMaxChars?: number; /** Control whether bootstrap truncation warnings are injected into prompts. */ bootstrapPromptTruncationWarning?: "off" | "once" | "always"; /** Optional IANA timezone for the user (used in system prompt; defaults to host timezone). */ userTimezone?: string; /** Time format in system prompt: auto (OS preference), 12-hour, or 24-hour. */ timeFormat?: "auto" | "12" | "24"; /** * Envelope timestamp timezone: "utc" (default), "local", "user", or an IANA timezone string. */ envelopeTimezone?: string; /** * Include absolute timestamps in message envelopes ("on" | "off", default: "on"). */ envelopeTimestamp?: "on" | "off"; /** * Include elapsed time in message envelopes ("on" | "off", default: "on"). */ envelopeElapsed?: "on" | "off"; /** Optional context window cap (used for runtime estimates + status %). */ contextTokens?: number; /** Optional CLI backends for text-only fallback (claude-cli, etc.). */ cliBackends?: Record; /** Opt-in: prune old tool results from the LLM context to reduce token usage. */ contextPruning?: AgentContextPruningConfig; /** Compaction tuning and pre-compaction memory flush behavior. */ compaction?: AgentCompactionConfig; /** Embedded Pi runner hardening and compatibility controls. */ embeddedPi?: { /** * How embedded Pi should trust workspace-local `.pi/config/settings.json`. * - sanitize (default): apply project settings except shellPath/shellCommandPrefix * - ignore: ignore project settings entirely * - trusted: trust project settings as-is */ projectSettingsPolicy?: "trusted" | "sanitize" | "ignore"; }; /** * Strict-agentic completion policy. Warning mode reports runs that planned or * returned empty output without changing delivery/retry behavior. */ strictAgentic?: { /** Default: off. "warn" emits sanitized diagnostics only. */mode?: "off" | "warn"; }; /** Vector memory search configuration (per-agent overrides supported). */ memorySearch?: MemorySearchConfig; /** Optional default allowlist of skills for agents that do not define their own list. */ skills?: string[]; /** Default thinking level when no /think directive is present. */ thinkingDefault?: "off" | "minimal" | "low" | "medium" | "high" | "xhigh" | "max" | "ultra"; /** Legacy elevated/reasoning default. Prefer thinkingDefault for new configs. */ reasoningDefault?: "off" | "minimal" | "low" | "medium" | "high" | "xhigh" | "max" | "ultra"; /** Default fast-mode preference when no runtime override is present. */ fastModeDefault?: boolean; /** Default verbose level when no /verbose directive is present. */ verboseDefault?: "off" | "on" | "full"; /** Default elevated level when no /elevated directive is present. */ elevatedDefault?: "off" | "on" | "ask" | "full"; /** Default block streaming level when no override is present. */ blockStreamingDefault?: "off" | "on"; /** * Block streaming boundary: * - "text_end": end of each assistant text content block (before tool calls) * - "message_end": end of the whole assistant message (may include tool blocks) */ blockStreamingBreak?: "text_end" | "message_end"; /** Soft block chunking for streamed replies (min/max chars, prefer paragraph/newline). */ blockStreamingChunk?: BlockStreamingChunkConfig; /** * Block reply coalescing (merge streamed chunks before send). * idleMs: wait time before flushing when idle. */ blockStreamingCoalesce?: BlockStreamingCoalesceConfig; /** Human-like delay between block replies. */ humanDelay?: HumanDelayConfig; timeoutSeconds?: number; /** Max inbound media size in MB for agent-visible attachments (text note or future image attach). */ mediaMaxMb?: number; /** * Max image side length (pixels) when sanitizing base64 image payloads in transcripts/tool results. * Default: 1200. */ imageMaxDimensionPx?: number; typingIntervalSeconds?: number; /** Typing indicator start mode (never|instant|thinking|message). */ typingMode?: TypingMode; /** Periodic background heartbeat runs. */ heartbeat?: { /** Heartbeat interval (duration string, default unit: minutes; default: 30m). */every?: string; /** Optional active-hours window (local time); heartbeats run only inside this window. */ activeHours?: { /** Start time (24h, HH:MM). Inclusive. */start?: string; /** End time (24h, HH:MM). Exclusive. Use "24:00" for end-of-day. */ end?: string; /** Timezone for the window ("user", "local", or IANA TZ id). Default: "user". */ timezone?: string; }; /** Heartbeat model override (provider/model). */ model?: string; /** Session key for heartbeat runs ("main" or explicit session key). */ session?: string; /** Delivery target ("last", "none", or a channel id). */ target?: "last" | "none" | ChannelId; /** Direct/DM delivery policy. Default: "allow". */ directPolicy?: "allow" | "block"; /** Optional delivery override (E.164 for WhatsApp, chat id for Telegram). Supports :topic:NNN suffix for Telegram topics. */ to?: string; /** Optional account id for multi-account channels. */ accountId?: string; /** Override the heartbeat prompt body (default: "Read HEARTBEAT.md if it exists (workspace context). Follow it strictly. Do not infer or repeat old tasks from prior chats. If nothing needs attention, reply HEARTBEAT_OK."). */ prompt?: string; /** Max chars allowed after HEARTBEAT_OK before delivery (default: 30). */ ackMaxChars?: number; /** Suppress tool error warning payloads during heartbeat runs. */ suppressToolErrorWarnings?: boolean; /** * When enabled, deliver the model's reasoning payload for heartbeat runs (when available) * as a separate message prefixed with `Reasoning:` (same as `/reasoning on`). * * Default: false (only the final heartbeat payload is delivered). */ includeReasoning?: boolean; }; /** Max concurrent agent runs across all conversations. Default: 1 (sequential). */ maxConcurrent?: number; /** Sub-agent defaults (spawned via sessions_spawn). */ subagents?: { /** Max concurrent sub-agent runs (global lane: "subagent"). Default: 1. */maxConcurrent?: number; /** Maximum depth allowed for sessions_spawn chains. Default behavior: 1 (no nested spawns). */ maxSpawnDepth?: number; /** Maximum active children a single requester session may spawn. Default behavior: 5. */ maxChildrenPerAgent?: number; /** Auto-archive sub-agent sessions after N minutes (default: 60). */ archiveAfterMinutes?: number; /** Default model selection for spawned sub-agents (string or {primary,fallbacks}). */ model?: AgentModelConfig; /** Default thinking level for spawned sub-agents (e.g. "off", "low", "medium", "high"). */ thinking?: string; /** Default run timeout in seconds for spawned sub-agents (0 = no timeout). */ runTimeoutSeconds?: number; /** Gateway timeout in ms for sub-agent announce delivery calls (default: 60000). */ announceTimeoutMs?: number; /** Default cross-agent allowlist for sessions_spawn. Agent-level config can override this. */ allowAgents?: string[]; /** Require sessions_spawn callers to pass an explicit agentId. */ requireAgentId?: boolean; }; /** Optional sandbox settings for non-main sessions. */ sandbox?: AgentSandboxConfig; }; type AgentCompactionMode = "default" | "safeguard"; type AgentCompactionIdentifierPolicy = "strict" | "off" | "custom"; type AgentCompactionConfig = { /** Compaction summarization mode. */mode?: AgentCompactionMode; /** Pi reserve tokens target before floor enforcement. */ reserveTokens?: number; /** Pi keepRecentTokens budget used for cut-point selection. */ keepRecentTokens?: number; /** Safety timeout for provider-side compaction calls, in seconds. */ timeoutSeconds?: number; /** Minimum reserve tokens enforced for Pi compaction (0 disables the floor). */ reserveTokensFloor?: number; /** Max share of context window for history during safeguard pruning (0.1–0.9, default 0.5). */ maxHistoryShare?: number; /** Identifier-preservation instruction policy for compaction summaries. */ identifierPolicy?: AgentCompactionIdentifierPolicy; /** Custom identifier-preservation instructions used when identifierPolicy is "custom". */ identifierInstructions?: string; /** Pre-compaction memory flush (agentic turn). Default: enabled. */ memoryFlush?: AgentCompactionMemoryFlushConfig; }; type AgentCompactionMemoryFlushConfig = { /** Enable the pre-compaction memory flush (default: true). */enabled?: boolean; /** Run the memory flush when context is within this many tokens of the compaction threshold. */ softThresholdTokens?: number; /** User prompt used for the memory flush turn (NO_REPLY is enforced if missing). */ prompt?: string; /** System prompt appended for the memory flush turn. */ systemPrompt?: string; }; //#endregion //#region src/config/io.d.ts type ConfigWriteOptions = { /** * Read-time env snapshot used to validate `${VAR}` restoration decisions. * If omitted, write falls back to current process env. */ envSnapshotForRestore?: Record; /** * Optional safety check: only use envSnapshotForRestore when writing the * same config file path that produced the snapshot. */ expectedConfigPath?: string; /** * Paths that must be explicitly removed from the persisted file payload, * even if schema/default normalization reintroduces them. */ unsetPaths?: string[][]; }; declare function loadConfig(): FasedAgentConfig; declare function writeConfigFile(cfg: FasedAgentConfig, options?: ConfigWriteOptions): Promise; //#endregion //#region src/wizard/prompts.d.ts type WizardSelectOption = { value: T; label: string; hint?: string; disabled?: boolean; }; type WizardSelectParams = { message: string; options: Array>; initialValue?: T; }; type WizardMultiSelectParams = { message: string; options: Array>; initialValues?: T[]; searchable?: boolean; }; type WizardTextParams = { message: string; initialValue?: string; placeholder?: string; validate?: (value: string) => string | undefined; }; type WizardConfirmParams = { message: string; initialValue?: boolean; }; type WizardProgress = { update: (message: string) => void; stop: (message?: string) => void; }; type WizardPrompter = { intro: (title: string) => Promise; outro: (message: string) => Promise; note: (message: string, title?: string) => Promise; select: (params: WizardSelectParams) => Promise; multiselect: (params: WizardMultiSelectParams) => Promise; text: (params: WizardTextParams) => Promise; secret?: (params: WizardTextParams) => Promise; confirm: (params: WizardConfirmParams) => Promise; progress: (label: string) => WizardProgress; }; //#endregion //#region src/channels/plugins/onboarding-types.d.ts type SetupChannelsOptions = { allowDisable?: boolean; allowSignalInstall?: boolean; onSelection?: (selection: ChannelId[]) => void; accountIds?: Partial>; onAccountId?: (channel: ChannelId, accountId: string) => void; promptAccountIds?: boolean; whatsappAccountId?: string; promptWhatsAppAccountId?: boolean; onWhatsAppAccountId?: (accountId: string) => void; forceAllowFromChannels?: ChannelId[]; skipStatusNote?: boolean; skipPrimerNote?: boolean; skipDmPolicyPrompt?: boolean; skipConfirm?: boolean; quickstartDefaults?: boolean; initialSelection?: ChannelId[]; }; type PromptAccountIdParams = { cfg: FasedAgentConfig; prompter: WizardPrompter; label: string; currentId?: string; listAccountIds: (cfg: FasedAgentConfig) => string[]; defaultAccountId: string; }; type PromptAccountId = (params: PromptAccountIdParams) => Promise; type ChannelOnboardingStatus = { channel: ChannelId; configured: boolean; statusLines: string[]; selectionHint?: string; quickstartScore?: number; }; type ChannelOnboardingStatusContext = { cfg: FasedAgentConfig; options?: SetupChannelsOptions; accountOverrides: Partial>; }; type ChannelOnboardingConfigureContext = { cfg: FasedAgentConfig; runtime: RuntimeEnv; prompter: WizardPrompter; options?: SetupChannelsOptions; accountOverrides: Partial>; shouldPromptAccountIds: boolean; forceAllowFrom: boolean; }; type ChannelOnboardingResult = { cfg: FasedAgentConfig; accountId?: string; }; type ChannelOnboardingConfiguredResult = ChannelOnboardingResult | "skip"; type ChannelOnboardingInteractiveContext = ChannelOnboardingConfigureContext & { configured: boolean; label: string; }; type ChannelOnboardingDmPolicy = { label: string; channel: ChannelId; policyKey: string; allowFromKey: string; getCurrent: (cfg: FasedAgentConfig) => DmPolicy; setPolicy: (cfg: FasedAgentConfig, policy: DmPolicy) => FasedAgentConfig; promptAllowFrom?: (params: { cfg: FasedAgentConfig; prompter: WizardPrompter; accountId?: string; }) => Promise; }; type ChannelOnboardingUiField = { label: string; path: Array; placeholder?: string; kind?: "text" | "password" | "number" | "list" | "select" | "boolean"; options?: Array<{ label: string; value: string; }>; }; type ChannelOnboardingUiAccess = { kind: "whatsapp-dm"; label?: string; note?: string; } | { kind: "discord-channels"; label?: string; note?: string; placeholder?: string; } | { kind: "slack-channels"; label?: string; note?: string; placeholder?: string; } | { kind: "msteams-channels"; label?: string; note?: string; placeholder?: string; } | { kind: "irc-channels"; label?: string; note?: string; placeholder?: string; } | { kind: "matrix-rooms"; label?: string; note?: string; placeholder?: string; } | { kind: "zalouser-groups"; label?: string; note?: string; placeholder?: string; }; type ChannelOnboardingUiDmPolicy = { label: string; policyKey: string; allowFromKey: string; }; type ChannelOnboardingUiSetup = { title: string; detail: string; notes?: string[]; fields: ChannelOnboardingUiField[]; qrLogin?: { startLabel?: string; waitLabel?: string; alt?: string; }; access?: ChannelOnboardingUiAccess; dmPolicy?: ChannelOnboardingUiDmPolicy; }; type ChannelOnboardingAdapter = { channel: ChannelId; uiSetup?: ChannelOnboardingUiSetup; getStatus: (ctx: ChannelOnboardingStatusContext) => Promise; configure: (ctx: ChannelOnboardingConfigureContext) => Promise; configureInteractive?: (ctx: ChannelOnboardingInteractiveContext) => Promise; configureWhenConfigured?: (ctx: ChannelOnboardingInteractiveContext) => Promise; dmPolicy?: ChannelOnboardingDmPolicy; onAccountRecorded?: (accountId: string, options?: SetupChannelsOptions) => void; disable?: (cfg: FasedAgentConfig) => FasedAgentConfig; }; //#endregion //#region src/channels/plugins/types.plugin.d.ts type ChannelConfigUiHint = { label?: string; help?: string; tags?: string[]; advanced?: boolean; sensitive?: boolean; placeholder?: string; itemTemplate?: unknown; }; type ChannelConfigSchema = { schema: Record; uiHints?: Record; }; type ChannelPlugin = { id: ChannelId; meta: ChannelMeta; capabilities: ChannelCapabilities; defaults?: { queue?: { debounceMs?: number; }; }; reload?: { configPrefixes: string[]; noopPrefixes?: string[]; }; onboarding?: ChannelOnboardingAdapter; config: ChannelConfigAdapter; configSchema?: ChannelConfigSchema; setup?: ChannelSetupAdapter; pairing?: ChannelPairingAdapter; security?: ChannelSecurityAdapter; groups?: ChannelGroupAdapter; mentions?: ChannelMentionAdapter; outbound?: ChannelOutboundAdapter; status?: ChannelStatusAdapter; gatewayMethods?: string[]; gateway?: ChannelGatewayAdapter; auth?: ChannelAuthAdapter; elevated?: ChannelElevatedAdapter; commands?: ChannelCommandAdapter; streaming?: ChannelStreamingAdapter; threading?: ChannelThreadingAdapter; messaging?: ChannelMessagingAdapter; agentPrompt?: ChannelAgentPromptAdapter; directory?: ChannelDirectoryAdapter; resolver?: ChannelResolverAdapter; actions?: ChannelMessageActionAdapter; heartbeat?: ChannelHeartbeatAdapter; agentTools?: ChannelAgentToolFactory | ChannelAgentTool[]; }; //#endregion export { ChannelPollContext as $, MSTeamsReplyStyle as $t, ChannelSecurityAdapter as A, SafeBinProfileFixture as An, FasedAgentConfig as At, ChannelCapabilities as B, WalletProviderId as Bt, ChannelLogoutResult as C, BlockStreamingCoalesceConfig as Cn, RuntimeEnv as Ct, ChannelResolveKind as D, MarkdownConfig as Dn, resolveIMessageAccount as Dt, ChannelPairingAdapter as E, HumanDelayConfig as En, resolveDefaultIMessageAccountId as Et, ChannelAccountSnapshot as F, ModelThinkingLevel as Ft, ChannelId as G, WhatsAppAccountConfig as Gt, ChannelDirectoryEntryKind as H, WalletRuntimeMode as Ht, ChannelAccountState as I, ModelThinkingMode as It, ChannelMessageActionAdapter as J, SlackAccountConfig as Jt, ChannelLogSink as K, TelegramAccountConfig as Kt, ChannelAgentPromptAdapter as L, WalletAuthMode as Lt, ChannelStatusAdapter as M, ReplyPayload as Mn, ModelCompatConfig as Mt, BaseProbeResult as N, CHANNEL_MESSAGE_ACTION_NAMES as Nn, ModelProviderAuthMode as Nt, ChannelResolveResult as O, MarkdownTableMode as On, sendMessageDiscord as Ot, BaseTokenResolution as P, ModelProviderConfig as Pt, ChannelOutboundTargetMode as Q, MSTeamsConfig as Qt, ChannelAgentTool as R, WalletChain as Rt, ChannelLogoutContext as S, SecretRef as Sn, sendMessageIMessage as St, ChannelOutboundContext as T, GroupPolicy as Tn, listIMessageAccountIds as Tt, ChannelGroupContext as U, WalletToolAccessMode as Ut, ChannelDirectoryEntry as V, WalletRuntimeKind as Vt, ChannelHeartbeatDeps as W, CronConfig as Wt, ChannelMessagingAdapter as X, SignalAccountConfig as Xt, ChannelMessageActionContext as Y, SlackSlashCommandConfig as Yt, ChannelMeta as Z, MSTeamsChannelConfig as Zt, ChannelGatewayContext as _, GatewayClientMode as _n, sendPollWhatsApp as _t, PromptAccountId as a, GoogleChatGroupConfig as an, ChannelStreamingAdapter as at, ChannelLoginWithQrStartResult as b, GroupToolPolicyBySenderConfig as bn, sendMessageSlack as bt, writeConfigFile as c, TtsAutoMode as cn, ChannelThreadingToolContext as ct, ChannelAuthAdapter as d, chunkMarkdownText as dn, OutboundDeliveryResult as dt, MSTeamsTeamConfig as en, ChannelPollResult as et, ChannelCommandAdapter as f, chunkMarkdownTextWithMode as fn, FinalizedMsgContext as ft, ChannelGatewayAdapter as g, resolveTextChunkLimit as gn, sendMessageWhatsApp as gt, ChannelElevatedAdapter as h, resolveChunkMode as hn, ShouldHandleTextCommandsParams as ht, ChannelOnboardingDmPolicy as i, GoogleChatDmConfig as in, ChannelStatusIssue as it, ChannelSetupAdapter as j, GetReplyOptions as jn, ModelCapabilityConfig as jt, ChannelResolverAdapter as k, ReplyToMode as kn, sendPollDiscord as kt, AgentDefaultsConfig as l, ChunkMode as ln, ChannelToolSend as lt, ChannelDirectoryAdapter as m, chunkTextWithMode as mn, CommandNormalizeOptions as mt, ChannelPlugin as n, GoogleChatActionConfig as nn, ChannelSecurityDmPolicy as nt, WizardPrompter as o, DiscordAccountConfig as on, ChannelThreadingAdapter as ot, ChannelConfigAdapter as p, chunkText as pn, MsgContext as pt, ChannelMentionAdapter as q, TelegramGroupConfig as qt, ChannelOnboardingAdapter as r, GoogleChatConfig as rn, ChannelSetupInput as rt, loadConfig as s, DmConfig as sn, ChannelThreadingContext as st, ChannelConfigSchema as t, GoogleChatAccountConfig as tn, ChannelSecurityContext as tt, ChannelMessageActionName as u, chunkByNewline as un, getChatChannelMeta as ut, ChannelGroupAdapter as v, GatewayClientName as vn, sendMessageTelegram as vt, ChannelOutboundAdapter as w, DmPolicy as wn, ResolvedIMessageAccount as wt, ChannelLoginWithQrWaitResult as x, GroupToolPolicyConfig as xn, sendMessageSignal as xt, ChannelHeartbeatAdapter as y, PollInput as yn, sendPollTelegram as yt, ChannelAgentToolFactory as z, WalletExecutionMode as zt };