From b35ceca2650749ce1887c7fee7d221ef20eaf759 Mon Sep 17 00:00:00 2001 From: Kastrah Date: Mon, 26 Jan 2026 11:33:00 +0100 Subject: [PATCH] feat: Zoho Cliq integration and config updates --- docs/channels/index.md | 1 + pnpm-lock.yaml | 9 ++ src/agents/anthropic-payload-log.ts | 6 +- src/agents/tools/web-search.ts | 121 +++++++++++++++++- src/channels/plugins/zoho-cliq.ts | 98 ++++++++------- src/channels/registry.ts | 1 + src/config/zod-schema.agent-runtime.ts | 14 +-- src/config/zod-schema.core.ts | 161 ++++++------------------ src/config/zod-schema.providers-core.ts | 2 +- src/plugin-sdk/index.ts | 2 +- src/tui/components/custom-editor.ts | 13 +- 11 files changed, 230 insertions(+), 198 deletions(-) diff --git a/docs/channels/index.md b/docs/channels/index.md index f8fd860c3..4ce227bf0 100644 --- a/docs/channels/index.md +++ b/docs/channels/index.md @@ -26,6 +26,7 @@ Text is supported everywhere; media and reactions vary by channel. - [Tlon](/channels/tlon) — Urbit-based messenger (plugin, installed separately). - [Zalo](/channels/zalo) — Zalo Bot API; Vietnam's popular messenger (plugin, installed separately). - [Zalo Personal](/channels/zalouser) — Zalo personal account via QR login (plugin, installed separately). +- [Zoho Cliq](/channels/zoho-cliq) — Zoho Cliq team messaging via OAuth API (plugin, installed separately). - [WebChat](/web/webchat) — Gateway WebChat UI over WebSocket. ## Notes diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 5c186498f..9799721c0 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -434,6 +434,15 @@ importers: specifier: workspace:* version: link:../.. + extensions/zoho-cliq: + devDependencies: + clawdbot: + specifier: workspace:* + version: link:../.. + typescript: + specifier: ^5.0.0 + version: 5.9.3 + ui: dependencies: '@noble/ed25519': diff --git a/src/agents/anthropic-payload-log.ts b/src/agents/anthropic-payload-log.ts index 1023f9f45..162373956 100644 --- a/src/agents/anthropic-payload-log.ts +++ b/src/agents/anthropic-payload-log.ts @@ -172,12 +172,12 @@ export function createAnthropicPayloadLogger(params: { payload, payloadDigest: digest(payload), }); - options?.onPayload?.(payload); + (options as any)?.onPayload?.(payload); }; return streamFn(model, context, { - ...options, + ...(options as any), onPayload: nextOnPayload, - }); + } as any); }; return wrapped; }; diff --git a/src/agents/tools/web-search.ts b/src/agents/tools/web-search.ts index 4bb5c3ea8..431200162 100644 --- a/src/agents/tools/web-search.ts +++ b/src/agents/tools/web-search.ts @@ -17,7 +17,7 @@ import { writeCache, } from "./web-shared.js"; -const SEARCH_PROVIDERS = ["brave", "perplexity"] as const; +const SEARCH_PROVIDERS = ["brave", "perplexity", "valyu"] as const; const DEFAULT_SEARCH_COUNT = 5; const MAX_SEARCH_COUNT = 10; @@ -82,6 +82,14 @@ type PerplexityConfig = { model?: string; }; +type ValyuConfig = { + apiKey?: string; + baseUrl?: string; + maxResults?: number; + searchType?: "all" | "web" | "proprietary"; + deepSearch?: boolean; +}; + type PerplexityApiKeySource = "config" | "perplexity_env" | "openrouter_env" | "none"; type PerplexitySearchResponse = { @@ -130,6 +138,15 @@ function missingSearchKeyPayload(provider: (typeof SEARCH_PROVIDERS)[number]) { }; } +function missingValyuKeyPayload() { + return { + error: "missing_valyu_api_key", + message: + "web_search (valyu) needs an API key. Set VALYU_API_KEY in the Gateway environment, or configure tools.web.search.valyu.apiKey.", + docs: "https://docs.clawd.bot/tools/web", + }; +} + function resolveSearchProvider(search?: WebSearchConfig): (typeof SEARCH_PROVIDERS)[number] { const raw = search && "provider" in search && typeof search.provider === "string" @@ -137,6 +154,7 @@ function resolveSearchProvider(search?: WebSearchConfig): (typeof SEARCH_PROVIDE : ""; if (raw === "perplexity") return "perplexity"; if (raw === "brave") return "brave"; + if (raw === "valyu") return "valyu"; return "brave"; } @@ -213,6 +231,19 @@ function resolvePerplexityModel(perplexity?: PerplexityConfig): string { return fromConfig || DEFAULT_PERPLEXITY_MODEL; } +function resolveValyuConfig(search?: WebSearchConfig): ValyuConfig { + if (!search || typeof search !== "object") return {}; + const valyu = "valyu" in search ? search.valyu : undefined; + if (!valyu || typeof valyu !== "object") return {}; + return valyu as ValyuConfig; +} + +function resolveValyuApiKey(valyu?: ValyuConfig): string | undefined { + const fromConfig = normalizeApiKey(valyu?.apiKey); + const fromEnv = normalizeApiKey(process.env.VALYU_API_KEY); + return fromConfig || fromEnv || undefined; +} + function resolveSearchCount(value: unknown, fallback: number): number { const parsed = typeof value === "number" && Number.isFinite(value) ? value : fallback; const clamped = Math.max(1, Math.min(MAX_SEARCH_COUNT, Math.floor(parsed))); @@ -269,6 +300,61 @@ async function runPerplexitySearch(params: { return { content, citations }; } +async function runValyuSearch(params: { + query: string; + apiKey: string; + baseUrl?: string; + maxResults?: number; + searchType?: string; + deepSearch?: boolean; + timeoutSeconds: number; +}): Promise> { + const baseUrl = params.baseUrl?.replace(/\/$/, "") || "https://api.valyu.ai/v1"; + const endpoint = `${baseUrl}/search`; + + const res = await fetch(endpoint, { + method: "POST", + headers: { + "Content-Type": "application/json", + Authorization: `Bearer ${params.apiKey}`, + }, + body: JSON.stringify({ + query: params.query, + max_num_results: params.maxResults, + search_type: params.searchType || "all", + // Valyu might support a deep search flag in the body or via different endpoint. + // Based on research, it's often a search_type or specialized async API. + // We'll pass it in if supported. + deep_search: params.deepSearch, + }), + signal: withTimeout(undefined, params.timeoutSeconds * 1000), + }); + + if (!res.ok) { + const detail = await readResponseText(res); + throw new Error(`Valyu API error (${res.status}): ${detail || res.statusText}`); + } + + const data = (await res.json()) as any; + // Map Valyu results to common format + const results = Array.isArray(data.results) ? data.results : []; + const mapped = results.map((entry: any) => ({ + title: entry.title || entry.name || "", + url: entry.url || entry.link || "", + description: entry.snippet || entry.description || entry.text || "", + published: entry.published_at || entry.date || undefined, + siteName: entry.source || resolveSiteName(entry.url || ""), + })); + + return { + query: params.query, + provider: "valyu", + count: mapped.length, + results: mapped, + rawResponse: data, // Keep raw for debugging/advanced usage + }; +} + async function runWebSearch(params: { query: string; count: number; @@ -281,6 +367,7 @@ async function runWebSearch(params: { ui_lang?: string; perplexityBaseUrl?: string; perplexityModel?: string; + valyu?: ValyuConfig; }): Promise> { const cacheKey = normalizeCacheKey( `${params.provider}:${params.query}:${params.count}:${params.country || "default"}:${params.search_lang || "default"}:${params.ui_lang || "default"}`, @@ -311,6 +398,24 @@ async function runWebSearch(params: { return payload; } + if (params.provider === "valyu") { + const result = await runValyuSearch({ + query: params.query, + apiKey: params.apiKey, + baseUrl: params.valyu?.baseUrl, + maxResults: params.count, + searchType: params.valyu?.searchType, + deepSearch: params.valyu?.deepSearch, + timeoutSeconds: params.timeoutSeconds, + }); + const payload = { + ...result, + tookMs: Date.now() - start, + }; + writeCache(SEARCH_CACHE, cacheKey, payload, params.cacheTtlMs); + return payload; + } + if (params.provider !== "brave") { throw new Error("Unsupported web search provider."); } @@ -372,11 +477,14 @@ export function createWebSearchTool(options?: { const provider = resolveSearchProvider(search); const perplexityConfig = resolvePerplexityConfig(search); + const valyuConfig = resolveValyuConfig(search); const description = provider === "perplexity" ? "Search the web using Perplexity Sonar (direct or via OpenRouter). Returns AI-synthesized answers with citations from real-time web search." - : "Search the web using Brave Search API. Supports region-specific and localized search via country and language parameters. Returns titles, URLs, and snippets for fast research."; + : provider === "valyu" + ? "Search the web using Valyu API. Supports standard and deep search for high-quality web and proprietary content." + : "Search the web using Brave Search API. Supports region-specific and localized search via country and language parameters. Returns titles, URLs, and snippets for fast research."; return { label: "Web Search", @@ -386,10 +494,16 @@ export function createWebSearchTool(options?: { execute: async (_toolCallId, args) => { const perplexityAuth = provider === "perplexity" ? resolvePerplexityApiKey(perplexityConfig) : undefined; + const valyuApiKey = provider === "valyu" ? resolveValyuApiKey(valyuConfig) : undefined; const apiKey = - provider === "perplexity" ? perplexityAuth?.apiKey : resolveSearchApiKey(search); + provider === "perplexity" + ? perplexityAuth?.apiKey + : provider === "valyu" + ? valyuApiKey + : resolveSearchApiKey(search); if (!apiKey) { + if (provider === "valyu") return jsonResult(missingValyuKeyPayload()); return jsonResult(missingSearchKeyPayload(provider)); } const params = args as Record; @@ -415,6 +529,7 @@ export function createWebSearchTool(options?: { perplexityAuth?.apiKey, ), perplexityModel: resolvePerplexityModel(perplexityConfig), + valyu: valyuConfig, }); return jsonResult(result); }, diff --git a/src/channels/plugins/zoho-cliq.ts b/src/channels/plugins/zoho-cliq.ts index 06a437901..062b367ac 100644 --- a/src/channels/plugins/zoho-cliq.ts +++ b/src/channels/plugins/zoho-cliq.ts @@ -1,7 +1,7 @@ -import { - DEFAULT_ACCOUNT_ID, - normalizeAccountId, -} from "../../routing/session-key.js"; +// Zoho Cliq Channel Plugin - Core Stub +// Full implementation is in extensions/zoho-cliq + +import { DEFAULT_ACCOUNT_ID, normalizeAccountId } from "../../routing/session-key.js"; import type { ChannelMeta } from "./types.js"; import type { ChannelPlugin } from "./types.js"; @@ -11,7 +11,7 @@ const meta: ChannelMeta = { selectionLabel: "Zoho Cliq (OAuth)", docsPath: "/channels/zoho-cliq", docsLabel: "zoho-cliq", - blurb: "supported (OAuth API).", + blurb: "Zoho Cliq team messaging via OAuth API.", }; export type ResolvedZohoCliqAccount = { @@ -24,13 +24,33 @@ export type ResolvedZohoCliqAccount = { refreshToken: string; dc: string; allowFrom?: Array; + config: { + enabled?: boolean; + name?: string; + clientId?: string; + clientSecret?: string; + refreshToken?: string; + dc?: string; + allowFrom?: Array; + dmPolicy?: "open" | "pairing" | "allowlist"; + groupPolicy?: "open" | "allowlist"; + groupAllowFrom?: Array; + }; }; +function parseDataCenter(raw?: string): string { + const upper = (raw ?? "US").toUpperCase(); + if (["US", "EU", "IN", "AU", "JP", "CA", "SA"].includes(upper)) { + return upper; + } + return "US"; +} + export const zohoCliqPlugin: ChannelPlugin = { id: "zoho-cliq", meta, capabilities: { - chatTypes: ["direct", "group"], + chatTypes: ["direct", "group", "channel"], media: true, }, config: { @@ -41,59 +61,40 @@ export const zohoCliqPlugin: ChannelPlugin = { }, resolveAccount: (cfg, accountId) => { const resolvedAccountId = normalizeAccountId(accountId); - const accounts = (cfg as any).channels?.["zoho-cliq"]?.accounts; - if (!accounts) { - return { - accountId: resolvedAccountId, - name: undefined, - enabled: false, - configured: false, - clientId: "", - clientSecret: "", - refreshToken: "", - dc: "", - }; - } - const account = accounts[resolvedAccountId]; - if (!account) { - return { - accountId: resolvedAccountId, - name: undefined, - enabled: false, - configured: false, - clientId: "", - clientSecret: "", - refreshToken: "", - dc: "", - }; - } + const channelCfg = (cfg as any).channels?.["zoho-cliq"]; + const accounts = channelCfg?.accounts; + const accountCfg = + accounts?.[resolvedAccountId] ?? + (resolvedAccountId === DEFAULT_ACCOUNT_ID ? channelCfg : undefined) ?? + {}; + + const clientId = accountCfg.clientId ?? process.env.ZOHO_CLIQ_CLIENT_ID ?? ""; + const clientSecret = accountCfg.clientSecret ?? process.env.ZOHO_CLIQ_CLIENT_SECRET ?? ""; + const refreshToken = accountCfg.refreshToken ?? process.env.ZOHO_CLIQ_REFRESH_TOKEN ?? ""; + const dc = parseDataCenter(accountCfg.dc ?? process.env.ZOHO_CLIQ_DC); + return { accountId: resolvedAccountId, - name: account.name, - enabled: account.enabled ?? true, - configured: !!( - account.clientId && - account.clientSecret && - account.refreshToken - ), - clientId: account.clientId, - clientSecret: account.clientSecret, - refreshToken: account.refreshToken, - dc: account.dc, - allowFrom: account.allowFrom, + name: accountCfg.name, + enabled: accountCfg.enabled ?? true, + configured: Boolean(clientId && clientSecret && refreshToken), + clientId, + clientSecret, + refreshToken, + dc, + allowFrom: accountCfg.allowFrom, + config: accountCfg, }; }, defaultAccountId: (cfg) => { const accounts = (cfg as any).channels?.["zoho-cliq"]?.accounts; if (!accounts) return DEFAULT_ACCOUNT_ID; - const enabled = Object.entries(accounts).filter( - ([_, a]) => (a as any).enabled ?? true, - ); + const enabled = Object.entries(accounts).filter(([_, a]) => (a as any).enabled ?? true); if (enabled.length === 1) return enabled[0][0]; if (Object.hasOwn(accounts, DEFAULT_ACCOUNT_ID)) { return DEFAULT_ACCOUNT_ID; } - return Object.keys(accounts)[0]; + return Object.keys(accounts)[0] ?? DEFAULT_ACCOUNT_ID; }, setAccountEnabled: ({ cfg, accountId, enabled }) => { const resolvedAccountId = accountId ?? DEFAULT_ACCOUNT_ID; @@ -125,6 +126,7 @@ export const zohoCliqPlugin: ChannelPlugin = { name: account.name, enabled: account.enabled, configured: account.configured, + dc: account.dc, }), resolveAllowFrom: ({ cfg, accountId }) => { const resolvedAccountId = accountId ?? DEFAULT_ACCOUNT_ID; diff --git a/src/channels/registry.ts b/src/channels/registry.ts index 86e29967c..b9edfa400 100644 --- a/src/channels/registry.ts +++ b/src/channels/registry.ts @@ -3,6 +3,7 @@ import type { ChannelId } from "./plugins/types.js"; import { requireActivePluginRegistry } from "../plugins/runtime.js"; import { CHAT_CHANNEL_ORDER, type ChatChannelId } from "./order.js"; +export { CHAT_CHANNEL_ORDER, type ChatChannelId }; export const CHANNEL_IDS = [...CHAT_CHANNEL_ORDER] as const; diff --git a/src/config/zod-schema.agent-runtime.ts b/src/config/zod-schema.agent-runtime.ts index 5f82cff77..d51d80fe7 100644 --- a/src/config/zod-schema.agent-runtime.ts +++ b/src/config/zod-schema.agent-runtime.ts @@ -7,6 +7,9 @@ import { IdentitySchema, ToolsMediaSchema, } from "./zod-schema.core.js"; +import { ToolPolicySchema, ValyuConfigSchema } from "./zod-schema.leaf.js"; + +export { ToolPolicySchema }; export const HeartbeatSchema = z .object({ @@ -146,18 +149,10 @@ export const SandboxPruneSchema = z .strict() .optional(); -export const ToolPolicySchema = z - .object({ - allow: z.array(z.string()).optional(), - deny: z.array(z.string()).optional(), - }) - .strict() - .optional(); - export const ToolsWebSearchSchema = z .object({ enabled: z.boolean().optional(), - provider: z.union([z.literal("brave"), z.literal("perplexity")]).optional(), + provider: z.union([z.literal("brave"), z.literal("perplexity"), z.literal("valyu")]).optional(), apiKey: z.string().optional(), maxResults: z.number().int().positive().optional(), timeoutSeconds: z.number().int().positive().optional(), @@ -170,6 +165,7 @@ export const ToolsWebSearchSchema = z }) .strict() .optional(), + valyu: ValyuConfigSchema, }) .strict() .optional(); diff --git a/src/config/zod-schema.core.ts b/src/config/zod-schema.core.ts index 0517df43d..0a3e026f5 100644 --- a/src/config/zod-schema.core.ts +++ b/src/config/zod-schema.core.ts @@ -1,7 +1,44 @@ import { z } from "zod"; - import { isSafeExecutableValue } from "../infra/exec-safety.js"; +import { + BlockStreamingChunkSchema, + BlockStreamingCoalesceSchema, + DmPolicySchema, + ExecutableTokenSchema, + GroupPolicySchema, + HexColorSchema, + MarkdownConfigSchema, + MarkdownTableModeSchema, + MSTeamsReplyStyleSchema, + ProviderCommandsSchema, + ReplyToModeSchema, + RetryConfigSchema, + NativeCommandsSettingSchema, + TtsConfigSchema, + TtsModeSchema, + TtsProviderSchema, +} from "./zod-schema.leaf.js"; + +export { + BlockStreamingChunkSchema, + BlockStreamingCoalesceSchema, + DmPolicySchema, + ExecutableTokenSchema, + GroupPolicySchema, + HexColorSchema, + MarkdownConfigSchema, + MarkdownTableModeSchema, + MSTeamsReplyStyleSchema, + ProviderCommandsSchema, + ReplyToModeSchema, + RetryConfigSchema, + NativeCommandsSettingSchema, + TtsConfigSchema, + TtsModeSchema, + TtsProviderSchema, +}; + export const ModelApiSchema = z.union([ z.literal("openai-completions"), z.literal("openai-responses"), @@ -118,100 +155,6 @@ export const QueueDropSchema = z.union([ z.literal("new"), z.literal("summarize"), ]); -export const ReplyToModeSchema = z.union([z.literal("off"), z.literal("first"), z.literal("all")]); - -// GroupPolicySchema: controls how group messages are handled -// Used with .default("allowlist").optional() pattern: -// - .optional() allows field omission in input config -// - .default("allowlist") ensures runtime always resolves to "allowlist" if not provided -export const GroupPolicySchema = z.enum(["open", "disabled", "allowlist"]); - -export const DmPolicySchema = z.enum(["pairing", "allowlist", "open", "disabled"]); - -export const BlockStreamingCoalesceSchema = z - .object({ - minChars: z.number().int().positive().optional(), - maxChars: z.number().int().positive().optional(), - idleMs: z.number().int().nonnegative().optional(), - }) - .strict(); - -export const BlockStreamingChunkSchema = z - .object({ - minChars: z.number().int().positive().optional(), - maxChars: z.number().int().positive().optional(), - breakPreference: z - .union([z.literal("paragraph"), z.literal("newline"), z.literal("sentence")]) - .optional(), - }) - .strict(); - -export const MarkdownTableModeSchema = z.enum(["off", "bullets", "code"]); - -export const MarkdownConfigSchema = z - .object({ - tables: MarkdownTableModeSchema.optional(), - }) - .strict() - .optional(); - -export const TtsProviderSchema = z.enum(["elevenlabs", "openai"]); -export const TtsModeSchema = z.enum(["final", "all"]); -export const TtsConfigSchema = z - .object({ - enabled: z.boolean().optional(), - mode: TtsModeSchema.optional(), - provider: TtsProviderSchema.optional(), - summaryModel: z.string().optional(), - modelOverrides: z - .object({ - enabled: z.boolean().optional(), - allowText: z.boolean().optional(), - allowProvider: z.boolean().optional(), - allowVoice: z.boolean().optional(), - allowModelId: z.boolean().optional(), - allowVoiceSettings: z.boolean().optional(), - allowNormalization: z.boolean().optional(), - allowSeed: z.boolean().optional(), - }) - .strict() - .optional(), - elevenlabs: z - .object({ - apiKey: z.string().optional(), - baseUrl: z.string().optional(), - voiceId: z.string().optional(), - modelId: z.string().optional(), - seed: z.number().int().min(0).max(4294967295).optional(), - applyTextNormalization: z.enum(["auto", "on", "off"]).optional(), - languageCode: z.string().optional(), - voiceSettings: z - .object({ - stability: z.number().min(0).max(1).optional(), - similarityBoost: z.number().min(0).max(1).optional(), - style: z.number().min(0).max(1).optional(), - useSpeakerBoost: z.boolean().optional(), - speed: z.number().min(0.5).max(2).optional(), - }) - .strict() - .optional(), - }) - .strict() - .optional(), - openai: z - .object({ - apiKey: z.string().optional(), - model: z.string().optional(), - voice: z.string().optional(), - }) - .strict() - .optional(), - prefsPath: z.string().optional(), - maxTextLength: z.number().int().min(1).optional(), - timeoutMs: z.number().int().min(1000).max(120000).optional(), - }) - .strict() - .optional(); export const HumanDelaySchema = z .object({ @@ -271,18 +214,6 @@ export const requireOpenAllowFrom = (params: { }); }; -export const MSTeamsReplyStyleSchema = z.enum(["thread", "top-level"]); - -export const RetryConfigSchema = z - .object({ - attempts: z.number().int().min(1).optional(), - minDelayMs: z.number().int().min(0).optional(), - maxDelayMs: z.number().int().min(0).optional(), - jitter: z.number().min(0).max(1).optional(), - }) - .strict() - .optional(); - export const QueueModeBySurfaceSchema = z .object({ whatsapp: QueueModeSchema.optional(), @@ -339,12 +270,6 @@ export const TranscribeAudioSchema = z .strict() .optional(); -export const HexColorSchema = z.string().regex(/^#?[0-9a-fA-F]{6}$/, "expected hex color (RRGGBB)"); - -export const ExecutableTokenSchema = z - .string() - .refine(isSafeExecutableValue, "expected safe executable name or path"); - export const MediaUnderstandingScopeSchema = z .object({ default: z.union([z.literal("allow"), z.literal("deny")]).optional(), @@ -452,13 +377,3 @@ export const ToolsMediaSchema = z }) .strict() .optional(); - -export const NativeCommandsSettingSchema = z.union([z.boolean(), z.literal("auto")]); - -export const ProviderCommandsSchema = z - .object({ - native: NativeCommandsSettingSchema.optional(), - nativeSkills: NativeCommandsSettingSchema.optional(), - }) - .strict() - .optional(); diff --git a/src/config/zod-schema.providers-core.ts b/src/config/zod-schema.providers-core.ts index d67e9420b..66e7ed206 100644 --- a/src/config/zod-schema.providers-core.ts +++ b/src/config/zod-schema.providers-core.ts @@ -14,7 +14,7 @@ import { RetryConfigSchema, requireOpenAllowFrom, } from "./zod-schema.core.js"; -import { ToolPolicySchema } from "./zod-schema.agent-runtime.js"; +import { ToolPolicySchema } from "./zod-schema.leaf.js"; import { ChannelHeartbeatVisibilitySchema } from "./zod-schema.channels.js"; import { normalizeTelegramCommandDescription, diff --git a/src/plugin-sdk/index.ts b/src/plugin-sdk/index.ts index 61dd1bc0b..d748b4d8f 100644 --- a/src/plugin-sdk/index.ts +++ b/src/plugin-sdk/index.ts @@ -100,7 +100,7 @@ export { normalizeAllowFrom, requireOpenAllowFrom, } from "../config/zod-schema.core.js"; -export { ToolPolicySchema } from "../config/zod-schema.agent-runtime.js"; +export { ToolPolicySchema } from "../config/zod-schema.leaf.js"; export type { RuntimeEnv } from "../runtime.js"; export type { WizardPrompter } from "../wizard/prompts.js"; export { DEFAULT_ACCOUNT_ID, normalizeAccountId } from "../routing/session-key.js"; diff --git a/src/tui/components/custom-editor.ts b/src/tui/components/custom-editor.ts index 0abede6a0..565f02147 100644 --- a/src/tui/components/custom-editor.ts +++ b/src/tui/components/custom-editor.ts @@ -1,11 +1,4 @@ -import { - Editor, - type EditorOptions, - type EditorTheme, - type TUI, - Key, - matchesKey, -} from "@mariozechner/pi-tui"; +import { Editor, type EditorTheme, type TUI, Key, matchesKey } from "@mariozechner/pi-tui"; export class CustomEditor extends Editor { onEscape?: () => void; @@ -19,8 +12,8 @@ export class CustomEditor extends Editor { onShiftTab?: () => void; onAltEnter?: () => void; - constructor(tui: TUI, theme: EditorTheme, options?: EditorOptions) { - super(tui, theme, options); + constructor(tui: TUI, _theme: EditorTheme, _options?: any) { + super(tui, _theme); } handleInput(data: string): void { if (matchesKey(data, Key.alt("enter")) && this.onAltEnter) {