diff --git a/package.json b/package.json index 6496a3abe66..78e5705e112 100644 --- a/package.json +++ b/package.json @@ -646,17 +646,17 @@ "canon:check:json": "node scripts/canon.mjs check --json", "canon:enforce": "node scripts/canon.mjs enforce --json", "canvas:a2ui:bundle": "bash scripts/bundle-a2ui.sh", - "check": "pnpm check:no-conflict-markers && pnpm check:host-env-policy:swift && pnpm check:bundled-channel-config-metadata && pnpm check:base-config-schema && pnpm check:bundled-plugin-metadata && pnpm check:bundled-provider-auth-env-vars && pnpm format:check && pnpm tsgo && pnpm plugin-sdk:check-exports && pnpm lint && pnpm lint:tmp:no-random-messaging && pnpm lint:tmp:channel-agnostic-boundaries && pnpm lint:tmp:no-raw-channel-fetch && pnpm lint:agent:ingress-owner && pnpm lint:plugins:no-register-http-handler && pnpm lint:plugins:no-monolithic-plugin-sdk-entry-imports && pnpm lint:plugins:no-extension-src-imports && pnpm lint:plugins:no-extension-test-core-imports && pnpm lint:plugins:no-extension-imports && pnpm lint:plugins:plugin-sdk-subpaths-exported && pnpm lint:extensions:no-src-outside-plugin-sdk && pnpm lint:extensions:no-plugin-sdk-internal && pnpm lint:extensions:no-relative-outside-package && pnpm lint:web-search-provider-boundaries && pnpm lint:webhook:no-low-level-body-read && pnpm lint:auth:no-pairing-store-group && pnpm lint:auth:pairing-account-scope", + "check": "pnpm check:no-conflict-markers && pnpm check:host-env-policy:swift && pnpm check:base-config-schema && pnpm check:bundled-plugin-metadata && pnpm check:bundled-provider-auth-env-vars && pnpm format:check && pnpm tsgo && pnpm plugin-sdk:check-exports && pnpm lint && pnpm lint:tmp:no-random-messaging && pnpm lint:tmp:channel-agnostic-boundaries && pnpm lint:tmp:no-raw-channel-fetch && pnpm lint:agent:ingress-owner && pnpm lint:plugins:no-register-http-handler && pnpm lint:plugins:no-monolithic-plugin-sdk-entry-imports && pnpm lint:plugins:no-extension-src-imports && pnpm lint:plugins:no-extension-test-core-imports && pnpm lint:plugins:no-extension-imports && pnpm lint:plugins:plugin-sdk-subpaths-exported && pnpm lint:extensions:no-src-outside-plugin-sdk && pnpm lint:extensions:no-plugin-sdk-internal && pnpm lint:extensions:no-relative-outside-package && pnpm lint:web-search-provider-boundaries && pnpm lint:webhook:no-low-level-body-read && pnpm lint:auth:no-pairing-store-group && pnpm lint:auth:pairing-account-scope", "check:base-config-schema": "node --import tsx scripts/generate-base-config-schema.ts --check", - "check:bundled-channel-config-metadata": "node --import tsx scripts/generate-bundled-channel-config-metadata.ts --check", + "check:bundled-channel-config-metadata": "node scripts/generate-bundled-plugin-metadata.mjs --check", "check:bundled-plugin-metadata": "node scripts/generate-bundled-plugin-metadata.mjs --check", "check:bundled-provider-auth-env-vars": "node scripts/generate-bundled-provider-auth-env-vars.mjs --check", "check:docs": "pnpm format:docs:check && pnpm lint:docs && pnpm docs:check-i18n-glossary && pnpm docs:check-links", "check:host-env-policy:swift": "node scripts/generate-host-env-security-policy-swift.mjs --check", "check:loc": "node --import tsx scripts/check-ts-max-loc.ts --max 500", "check:no-conflict-markers": "node scripts/check-no-conflict-markers.mjs", - "config:channels:check": "node --import tsx scripts/generate-bundled-channel-config-metadata.ts --check", - "config:channels:gen": "node --import tsx scripts/generate-bundled-channel-config-metadata.ts --write", + "config:channels:check": "node scripts/generate-bundled-plugin-metadata.mjs --check", + "config:channels:gen": "node scripts/generate-bundled-plugin-metadata.mjs", "config:docs:check": "node --import tsx scripts/generate-config-doc-baseline.ts --check", "config:docs:gen": "node --import tsx scripts/generate-config-doc-baseline.ts --write", "config:schema:check": "node --import tsx scripts/generate-base-config-schema.ts --check", diff --git a/scripts/generate-bundled-channel-config-metadata.ts b/scripts/generate-bundled-channel-config-metadata.ts deleted file mode 100644 index 2d009748dfc..00000000000 --- a/scripts/generate-bundled-channel-config-metadata.ts +++ /dev/null @@ -1,212 +0,0 @@ -#!/usr/bin/env node -import fs from "node:fs"; -import path from "node:path"; -import { loadChannelConfigSurfaceModule } from "./load-channel-config-surface.ts"; - -const GENERATED_BY = "scripts/generate-bundled-channel-config-metadata.ts"; -const DEFAULT_OUTPUT_PATH = "src/config/bundled-channel-config-metadata.generated.ts"; - -type BundledPluginSource = { - dirName: string; - pluginDir: string; - manifestPath: string; - manifest: { - id: string; - channels?: unknown; - name?: string; - description?: string; - } & Record; - packageJson?: Record; -}; - -const { collectBundledPluginSources } = (await import( - new URL("./lib/bundled-plugin-source-utils.mjs", import.meta.url).href -)) as { - collectBundledPluginSources: (params?: { - repoRoot?: string; - requirePackageJson?: boolean; - }) => BundledPluginSource[]; -}; - -const { formatGeneratedModule } = (await import( - new URL("./lib/format-generated-module.mjs", import.meta.url).href -)) as { - formatGeneratedModule: ( - source: string, - options: { - repoRoot: string; - outputPath: string; - errorLabel: string; - }, - ) => string; -}; - -const { writeGeneratedOutput } = (await import( - new URL("./lib/generated-output-utils.mjs", import.meta.url).href -)) as { - writeGeneratedOutput: (params: { - repoRoot: string; - outputPath: string; - next: string; - check?: boolean; - }) => { - changed: boolean; - wrote: boolean; - outputPath: string; - }; -}; - -type BundledChannelConfigMetadata = { - pluginId: string; - channelId: string; - label?: string; - description?: string; - schema: Record; - uiHints?: Record; -}; - -function resolveChannelConfigSchemaModulePath(rootDir: string): string | null { - const candidates = [ - path.join(rootDir, "src", "config-schema.ts"), - path.join(rootDir, "src", "config-schema.js"), - path.join(rootDir, "src", "config-schema.mts"), - path.join(rootDir, "src", "config-schema.mjs"), - ]; - for (const candidate of candidates) { - if (fs.existsSync(candidate)) { - return candidate; - } - } - return null; -} - -function resolvePackageChannelMeta(source: BundledPluginSource) { - const openclawMeta = - source.packageJson && - typeof source.packageJson === "object" && - !Array.isArray(source.packageJson) && - "openclaw" in source.packageJson - ? (source.packageJson.openclaw as Record | undefined) - : undefined; - const channelMeta = - openclawMeta && - typeof openclawMeta.channel === "object" && - openclawMeta.channel && - !Array.isArray(openclawMeta.channel) - ? (openclawMeta.channel as Record) - : undefined; - return channelMeta; -} - -function resolveRootLabel(source: BundledPluginSource, channelId: string): string | undefined { - const channelMeta = resolvePackageChannelMeta(source); - if (channelMeta?.id === channelId && typeof channelMeta.label === "string") { - return channelMeta.label.trim(); - } - if (typeof source.manifest?.name === "string" && source.manifest.name.trim()) { - return source.manifest.name.trim(); - } - return undefined; -} - -function resolveRootDescription( - source: BundledPluginSource, - channelId: string, -): string | undefined { - const channelMeta = resolvePackageChannelMeta(source); - if (channelMeta?.id === channelId && typeof channelMeta.blurb === "string") { - return channelMeta.blurb.trim(); - } - if (typeof source.manifest?.description === "string" && source.manifest.description.trim()) { - return source.manifest.description.trim(); - } - return undefined; -} - -function formatTypeScriptModule(source: string, outputPath: string, repoRoot: string): string { - return formatGeneratedModule(source, { - repoRoot, - outputPath, - errorLabel: "bundled channel config metadata", - }); -} - -export async function collectBundledChannelConfigMetadata(params?: { repoRoot?: string }) { - const repoRoot = path.resolve(params?.repoRoot ?? process.cwd()); - const sources = collectBundledPluginSources({ repoRoot, requirePackageJson: true }); - const entries: BundledChannelConfigMetadata[] = []; - - for (const source of sources) { - const channelIds = Array.isArray(source.manifest?.channels) - ? source.manifest.channels.filter( - (entry: unknown): entry is string => typeof entry === "string" && entry.trim().length > 0, - ) - : []; - if (channelIds.length === 0) { - continue; - } - const modulePath = resolveChannelConfigSchemaModulePath(source.pluginDir); - if (!modulePath) { - continue; - } - const surface = await loadChannelConfigSurfaceModule(modulePath, { repoRoot }); - if (!surface?.schema) { - continue; - } - for (const channelId of channelIds) { - const label = resolveRootLabel(source, channelId); - const description = resolveRootDescription(source, channelId); - entries.push({ - pluginId: String(source.manifest.id), - channelId, - ...(label ? { label } : {}), - ...(description ? { description } : {}), - schema: surface.schema, - ...(Object.keys(surface.uiHints ?? {}).length > 0 ? { uiHints: surface.uiHints } : {}), - }); - } - } - - return entries.toSorted((left, right) => left.channelId.localeCompare(right.channelId)); -} - -export async function writeBundledChannelConfigMetadataModule(params?: { - repoRoot?: string; - outputPath?: string; - check?: boolean; -}) { - const repoRoot = path.resolve(params?.repoRoot ?? process.cwd()); - const outputPath = params?.outputPath ?? DEFAULT_OUTPUT_PATH; - const entries = await collectBundledChannelConfigMetadata({ repoRoot }); - const next = formatTypeScriptModule( - `// Auto-generated by ${GENERATED_BY}. Do not edit directly. - -export const GENERATED_BUNDLED_CHANNEL_CONFIG_METADATA = ${JSON.stringify(entries, null, 2)} as const; -`, - outputPath, - repoRoot, - ); - return writeGeneratedOutput({ - repoRoot, - outputPath, - next, - check: params?.check, - }); -} - -if (import.meta.url === new URL(process.argv[1] ?? "", "file://").href) { - const check = process.argv.includes("--check"); - const result = await writeBundledChannelConfigMetadataModule({ check }); - if (!result.changed) { - process.exitCode = 0; - } else if (check) { - console.error( - `[bundled-channel-config-metadata] stale generated output at ${path.relative(process.cwd(), result.outputPath)}`, - ); - process.exitCode = 1; - } else { - console.log( - `[bundled-channel-config-metadata] wrote ${path.relative(process.cwd(), result.outputPath)}`, - ); - } -} diff --git a/scripts/generate-bundled-plugin-metadata.d.mts b/scripts/generate-bundled-plugin-metadata.d.mts index ba40cebf8ec..b4fbfd4a232 100644 --- a/scripts/generate-bundled-plugin-metadata.d.mts +++ b/scripts/generate-bundled-plugin-metadata.d.mts @@ -17,16 +17,17 @@ export type BundledPluginMetadataEntry = { export function collectBundledPluginMetadata(params?: { repoRoot?: string; -}): BundledPluginMetadataEntry[]; +}): Promise; export function renderBundledPluginMetadataModule(entries: BundledPluginMetadataEntry[]): string; export function writeBundledPluginMetadataModule(params?: { repoRoot?: string; outputPath?: string; + entriesOutputPath?: string; check?: boolean; -}): { +}): Promise<{ changed: boolean; wrote: boolean; - outputPath: string; -}; + outputPaths: string[]; +}>; diff --git a/scripts/generate-bundled-plugin-metadata.mjs b/scripts/generate-bundled-plugin-metadata.mjs index bdea88ab87b..557549d7e0e 100644 --- a/scripts/generate-bundled-plugin-metadata.mjs +++ b/scripts/generate-bundled-plugin-metadata.mjs @@ -1,3 +1,5 @@ +import { execFileSync } from "node:child_process"; +import fs from "node:fs"; import path from "node:path"; import { collectBundledPluginSources } from "./lib/bundled-plugin-source-utils.mjs"; import { formatGeneratedModule } from "./lib/format-generated-module.mjs"; @@ -134,12 +136,131 @@ function normalizePluginManifest(raw) { ...(typeof raw.description === "string" ? { description: raw.description.trim() } : {}), ...(typeof raw.version === "string" ? { version: raw.version.trim() } : {}), ...(normalizeObject(raw.uiHints) ? { uiHints: raw.uiHints } : {}), + ...(normalizeObject(raw.channelConfigs) ? { channelConfigs: raw.channelConfigs } : {}), ...(normalizeManifestContracts(raw.contracts) ? { contracts: normalizeManifestContracts(raw.contracts) } : {}), }; } +function resolvePackageChannelMeta(packageJson) { + const openclawMeta = + packageJson && + typeof packageJson === "object" && + !Array.isArray(packageJson) && + "openclaw" in packageJson + ? packageJson.openclaw + : undefined; + if (!openclawMeta || typeof openclawMeta !== "object" || Array.isArray(openclawMeta)) { + return undefined; + } + const channelMeta = openclawMeta.channel; + if (!channelMeta || typeof channelMeta !== "object" || Array.isArray(channelMeta)) { + return undefined; + } + return channelMeta; +} + +function resolveChannelConfigSchemaModulePath(rootDir) { + const candidates = [ + path.join(rootDir, "src", "config-schema.ts"), + path.join(rootDir, "src", "config-schema.js"), + path.join(rootDir, "src", "config-schema.mts"), + path.join(rootDir, "src", "config-schema.mjs"), + ]; + for (const candidate of candidates) { + if (fs.existsSync(candidate)) { + return candidate; + } + } + return null; +} + +function resolveRootLabel(source, channelId) { + const channelMeta = resolvePackageChannelMeta(source.packageJson); + if (channelMeta?.id === channelId && typeof channelMeta.label === "string") { + return channelMeta.label.trim(); + } + if (typeof source.manifest?.name === "string" && source.manifest.name.trim()) { + return source.manifest.name.trim(); + } + return undefined; +} + +function resolveRootDescription(source, channelId) { + const channelMeta = resolvePackageChannelMeta(source.packageJson); + if (channelMeta?.id === channelId && typeof channelMeta.blurb === "string") { + return channelMeta.blurb.trim(); + } + if (typeof source.manifest?.description === "string" && source.manifest.description.trim()) { + return source.manifest.description.trim(); + } + return undefined; +} + +async function collectBundledChannelConfigsForSource({ source, manifest }) { + const channelIds = Array.isArray(manifest.channels) + ? manifest.channels.filter((entry) => typeof entry === "string" && entry.trim()) + : []; + const existingChannelConfigs = normalizeObject(manifest.channelConfigs) + ? { ...manifest.channelConfigs } + : {}; + if (channelIds.length === 0) { + return Object.keys(existingChannelConfigs).length > 0 ? existingChannelConfigs : undefined; + } + + const modulePath = resolveChannelConfigSchemaModulePath(source.pluginDir); + if (!modulePath || !fs.existsSync(modulePath)) { + return Object.keys(existingChannelConfigs).length > 0 ? existingChannelConfigs : undefined; + } + + const surfaceJson = execFileSync( + process.execPath, + ["--import", "tsx", "scripts/load-channel-config-surface.ts", modulePath], + { + // Run from the host repo so the generator always resolves its own loader/tooling, + // even when inspecting a temporary or alternate repo root. + cwd: FORMATTER_CWD, + encoding: "utf8", + }, + ); + const surface = JSON.parse(surfaceJson); + if (!surface?.schema) { + return Object.keys(existingChannelConfigs).length > 0 ? existingChannelConfigs : undefined; + } + + for (const channelId of channelIds) { + const existing = + existingChannelConfigs[channelId] && + typeof existingChannelConfigs[channelId] === "object" && + !Array.isArray(existingChannelConfigs[channelId]) + ? existingChannelConfigs[channelId] + : undefined; + const label = existing?.label ?? resolveRootLabel(source, channelId); + const description = existing?.description ?? resolveRootDescription(source, channelId); + const uiHints = + surface.uiHints || existing?.uiHints + ? { + ...(surface.uiHints && Object.keys(surface.uiHints).length > 0 + ? { ...surface.uiHints } + : {}), + ...(existing?.uiHints && Object.keys(existing.uiHints).length > 0 + ? { ...existing.uiHints } + : {}), + } + : undefined; + + existingChannelConfigs[channelId] = { + schema: surface.schema, + ...(uiHints && Object.keys(uiHints).length > 0 ? { uiHints } : {}), + ...(label ? { label } : {}), + ...(description ? { description } : {}), + }; + } + + return Object.keys(existingChannelConfigs).length > 0 ? existingChannelConfigs : undefined; +} + function formatTypeScriptModule(source, { outputPath }) { return formatGeneratedModule(source, { repoRoot: FORMATTER_CWD, @@ -161,7 +282,7 @@ function normalizeGeneratedImportPath(dirName, builtPath) { return `../../extensions/${dirName}/${String(builtPath).replace(/^\.\//u, "")}`; } -export function collectBundledPluginMetadata(params = {}) { +export async function collectBundledPluginMetadata(params = {}) { const repoRoot = path.resolve(params.repoRoot ?? process.cwd()); const entries = []; for (const source of collectBundledPluginSources({ repoRoot, requirePackageJson: true })) { @@ -192,6 +313,10 @@ export function collectBundledPluginMetadata(params = {}) { built: rewriteEntryToBuiltPath(packageManifest.setupEntry.trim()), } : undefined; + const channelConfigs = await collectBundledChannelConfigsForSource({ source, manifest }); + if (channelConfigs) { + manifest.channelConfigs = channelConfigs; + } entries.push({ dirName: source.dirName, @@ -264,9 +389,9 @@ ${imports} `; } -export function writeBundledPluginMetadataModule(params = {}) { +export async function writeBundledPluginMetadataModule(params = {}) { const repoRoot = path.resolve(params.repoRoot ?? process.cwd()); - const entries = collectBundledPluginMetadata({ repoRoot }); + const entries = await collectBundledPluginMetadata({ repoRoot }); const outputPath = path.resolve(repoRoot, params.outputPath ?? DEFAULT_OUTPUT_PATH); const entriesOutputPath = path.resolve( repoRoot, @@ -299,7 +424,7 @@ export function writeBundledPluginMetadataModule(params = {}) { if (import.meta.url === new URL(process.argv[1] ?? "", "file:").href) { const check = process.argv.includes("--check"); - const result = writeBundledPluginMetadataModule({ check }); + const result = await writeBundledPluginMetadataModule({ check }); if (!result.changed) { process.exitCode = 0; } else if (check) { diff --git a/scripts/load-channel-config-surface.ts b/scripts/load-channel-config-surface.ts index b2d061b2e0b..3852711851b 100644 --- a/scripts/load-channel-config-surface.ts +++ b/scripts/load-channel-config-surface.ts @@ -1,18 +1,11 @@ import fs from "node:fs"; import path from "node:path"; import { fileURLToPath, pathToFileURL } from "node:url"; +import { buildChannelConfigSchema } from "../src/channels/plugins/config-schema.js"; -type BuiltChannelConfigSurface = { - schema: Record; - uiHints?: Record; -}; - -type JsonSchemaCapableSurface = { - toJSONSchema?: (params?: Record) => unknown; - uiHints?: Record; -}; - -function isBuiltChannelConfigSchema(value: unknown): value is BuiltChannelConfigSurface { +function isBuiltChannelConfigSchema( + value: unknown, +): value is { schema: Record; uiHints?: Record } { if (!value || typeof value !== "object") { return false; } @@ -20,32 +13,9 @@ function isBuiltChannelConfigSchema(value: unknown): value is BuiltChannelConfig return Boolean(candidate.schema && typeof candidate.schema === "object"); } -function buildSchemaSurface(value: unknown): BuiltChannelConfigSurface | null { - if (!value || typeof value !== "object") { - return null; - } - const candidate = value as JsonSchemaCapableSurface; - if (typeof candidate.toJSONSchema === "function") { - return { - schema: candidate.toJSONSchema({ - target: "draft-07", - unrepresentable: "any", - }) as Record, - ...(candidate.uiHints ? { uiHints: candidate.uiHints } : {}), - }; - } - return { - schema: { - type: "object", - additionalProperties: true, - }, - ...(candidate.uiHints ? { uiHints: candidate.uiHints } : {}), - }; -} - -function resolveChannelConfigSurfaceExport( +function resolveConfigSchemaExport( imported: Record, -): BuiltChannelConfigSurface | null { +): { schema: Record; uiHints?: Record } | null { for (const [name, value] of Object.entries(imported)) { if (name.endsWith("ChannelConfigSchema") && isBuiltChannelConfigSchema(value)) { return value; @@ -59,9 +29,8 @@ function resolveChannelConfigSurfaceExport( if (isBuiltChannelConfigSchema(value)) { return value; } - const wrapped = buildSchemaSurface(value); - if (wrapped) { - return wrapped; + if (value && typeof value === "object") { + return buildChannelConfigSchema(value as never); } } @@ -97,7 +66,8 @@ function shouldRetryViaIsolatedCopy(error: unknown): boolean { return false; } const code = "code" in error ? error.code : undefined; - return code === "ERR_MODULE_NOT_FOUND"; + const message = "message" in error && typeof error.message === "string" ? error.message : ""; + return code === "ERR_MODULE_NOT_FOUND" && message.includes(`${path.sep}node_modules${path.sep}`); } const SOURCE_FILE_EXTENSIONS = [".ts", ".tsx", ".mts", ".cts", ".js", ".jsx", ".mjs", ".cjs"]; @@ -215,7 +185,7 @@ export async function loadChannelConfigSurfaceModule( try { const imported = (await import(pathToFileURL(modulePath).href)) as Record; - return resolveChannelConfigSurfaceExport(imported); + return resolveConfigSchemaExport(imported); } catch (error) { if (!shouldRetryViaIsolatedCopy(error)) { throw error; @@ -226,7 +196,7 @@ export async function loadChannelConfigSurfaceModule( const imported = (await import( `${pathToFileURL(isolatedCopy.copiedModulePath).href}?isolated=${Date.now()}` )) as Record; - return resolveChannelConfigSurfaceExport(imported); + return resolveConfigSchemaExport(imported); } finally { isolatedCopy.cleanup(); } diff --git a/src/config/bundled-channel-config-metadata.generated.ts b/src/config/bundled-channel-config-metadata.generated.ts deleted file mode 100644 index 4e4f57737b0..00000000000 --- a/src/config/bundled-channel-config-metadata.generated.ts +++ /dev/null @@ -1,14727 +0,0 @@ -// Auto-generated by scripts/generate-bundled-channel-config-metadata.ts. Do not edit directly. - -export const GENERATED_BUNDLED_CHANNEL_CONFIG_METADATA = [ - { - pluginId: "bluebubbles", - channelId: "bluebubbles", - label: "BlueBubbles", - description: "iMessage via the BlueBubbles mac app + REST API.", - schema: { - $schema: "http://json-schema.org/draft-07/schema#", - type: "object", - properties: { - name: { - type: "string", - }, - enabled: { - type: "boolean", - }, - markdown: { - type: "object", - properties: { - tables: { - type: "string", - enum: ["off", "bullets", "code"], - }, - }, - additionalProperties: false, - }, - serverUrl: { - type: "string", - }, - password: { - anyOf: [ - { - type: "string", - }, - { - oneOf: [ - { - type: "object", - properties: { - source: { - type: "string", - const: "env", - }, - provider: { - type: "string", - pattern: "^[a-z][a-z0-9_-]{0,63}$", - }, - id: { - type: "string", - pattern: "^[A-Z][A-Z0-9_]{0,127}$", - }, - }, - required: ["source", "provider", "id"], - additionalProperties: false, - }, - { - type: "object", - properties: { - source: { - type: "string", - const: "file", - }, - provider: { - type: "string", - pattern: "^[a-z][a-z0-9_-]{0,63}$", - }, - id: { - type: "string", - }, - }, - required: ["source", "provider", "id"], - additionalProperties: false, - }, - { - type: "object", - properties: { - source: { - type: "string", - const: "exec", - }, - provider: { - type: "string", - pattern: "^[a-z][a-z0-9_-]{0,63}$", - }, - id: { - type: "string", - }, - }, - required: ["source", "provider", "id"], - additionalProperties: false, - }, - ], - }, - ], - }, - webhookPath: { - type: "string", - }, - dmPolicy: { - type: "string", - enum: ["pairing", "allowlist", "open", "disabled"], - }, - allowFrom: { - type: "array", - items: { - anyOf: [ - { - type: "string", - }, - { - type: "number", - }, - ], - }, - }, - groupAllowFrom: { - type: "array", - items: { - anyOf: [ - { - type: "string", - }, - { - type: "number", - }, - ], - }, - }, - groupPolicy: { - type: "string", - enum: ["open", "disabled", "allowlist"], - }, - enrichGroupParticipantsFromContacts: { - default: true, - type: "boolean", - }, - historyLimit: { - type: "integer", - minimum: 0, - maximum: 9007199254740991, - }, - dmHistoryLimit: { - type: "integer", - minimum: 0, - maximum: 9007199254740991, - }, - textChunkLimit: { - type: "integer", - exclusiveMinimum: 0, - maximum: 9007199254740991, - }, - chunkMode: { - type: "string", - enum: ["length", "newline"], - }, - mediaMaxMb: { - type: "integer", - exclusiveMinimum: 0, - maximum: 9007199254740991, - }, - mediaLocalRoots: { - type: "array", - items: { - type: "string", - }, - }, - sendReadReceipts: { - type: "boolean", - }, - allowPrivateNetwork: { - type: "boolean", - }, - blockStreaming: { - type: "boolean", - }, - groups: { - type: "object", - properties: {}, - additionalProperties: { - type: "object", - properties: { - requireMention: { - type: "boolean", - }, - tools: { - type: "object", - properties: { - allow: { - type: "array", - items: { - type: "string", - }, - }, - alsoAllow: { - type: "array", - items: { - type: "string", - }, - }, - deny: { - type: "array", - items: { - type: "string", - }, - }, - }, - additionalProperties: false, - }, - }, - additionalProperties: false, - }, - }, - accounts: { - type: "object", - properties: {}, - additionalProperties: { - type: "object", - properties: { - name: { - type: "string", - }, - enabled: { - type: "boolean", - }, - markdown: { - type: "object", - properties: { - tables: { - type: "string", - enum: ["off", "bullets", "code"], - }, - }, - additionalProperties: false, - }, - serverUrl: { - type: "string", - }, - password: { - anyOf: [ - { - type: "string", - }, - { - oneOf: [ - { - type: "object", - properties: { - source: { - type: "string", - const: "env", - }, - provider: { - type: "string", - pattern: "^[a-z][a-z0-9_-]{0,63}$", - }, - id: { - type: "string", - pattern: "^[A-Z][A-Z0-9_]{0,127}$", - }, - }, - required: ["source", "provider", "id"], - additionalProperties: false, - }, - { - type: "object", - properties: { - source: { - type: "string", - const: "file", - }, - provider: { - type: "string", - pattern: "^[a-z][a-z0-9_-]{0,63}$", - }, - id: { - type: "string", - }, - }, - required: ["source", "provider", "id"], - additionalProperties: false, - }, - { - type: "object", - properties: { - source: { - type: "string", - const: "exec", - }, - provider: { - type: "string", - pattern: "^[a-z][a-z0-9_-]{0,63}$", - }, - id: { - type: "string", - }, - }, - required: ["source", "provider", "id"], - additionalProperties: false, - }, - ], - }, - ], - }, - webhookPath: { - type: "string", - }, - dmPolicy: { - type: "string", - enum: ["pairing", "allowlist", "open", "disabled"], - }, - allowFrom: { - type: "array", - items: { - anyOf: [ - { - type: "string", - }, - { - type: "number", - }, - ], - }, - }, - groupAllowFrom: { - type: "array", - items: { - anyOf: [ - { - type: "string", - }, - { - type: "number", - }, - ], - }, - }, - groupPolicy: { - type: "string", - enum: ["open", "disabled", "allowlist"], - }, - enrichGroupParticipantsFromContacts: { - default: true, - type: "boolean", - }, - historyLimit: { - type: "integer", - minimum: 0, - maximum: 9007199254740991, - }, - dmHistoryLimit: { - type: "integer", - minimum: 0, - maximum: 9007199254740991, - }, - textChunkLimit: { - type: "integer", - exclusiveMinimum: 0, - maximum: 9007199254740991, - }, - chunkMode: { - type: "string", - enum: ["length", "newline"], - }, - mediaMaxMb: { - type: "integer", - exclusiveMinimum: 0, - maximum: 9007199254740991, - }, - mediaLocalRoots: { - type: "array", - items: { - type: "string", - }, - }, - sendReadReceipts: { - type: "boolean", - }, - allowPrivateNetwork: { - type: "boolean", - }, - blockStreaming: { - type: "boolean", - }, - groups: { - type: "object", - properties: {}, - additionalProperties: { - type: "object", - properties: { - requireMention: { - type: "boolean", - }, - tools: { - type: "object", - properties: { - allow: { - type: "array", - items: { - type: "string", - }, - }, - alsoAllow: { - type: "array", - items: { - type: "string", - }, - }, - deny: { - type: "array", - items: { - type: "string", - }, - }, - }, - additionalProperties: false, - }, - }, - additionalProperties: false, - }, - }, - }, - required: ["enrichGroupParticipantsFromContacts"], - additionalProperties: false, - }, - }, - defaultAccount: { - type: "string", - }, - actions: { - type: "object", - properties: { - reactions: { - default: true, - type: "boolean", - }, - edit: { - default: true, - type: "boolean", - }, - unsend: { - default: true, - type: "boolean", - }, - reply: { - default: true, - type: "boolean", - }, - sendWithEffect: { - default: true, - type: "boolean", - }, - renameGroup: { - default: true, - type: "boolean", - }, - setGroupIcon: { - default: true, - type: "boolean", - }, - addParticipant: { - default: true, - type: "boolean", - }, - removeParticipant: { - default: true, - type: "boolean", - }, - leaveGroup: { - default: true, - type: "boolean", - }, - sendAttachment: { - default: true, - type: "boolean", - }, - }, - required: [ - "reactions", - "edit", - "unsend", - "reply", - "sendWithEffect", - "renameGroup", - "setGroupIcon", - "addParticipant", - "removeParticipant", - "leaveGroup", - "sendAttachment", - ], - additionalProperties: false, - }, - }, - required: ["enrichGroupParticipantsFromContacts"], - additionalProperties: false, - }, - uiHints: { - "": { - label: "BlueBubbles", - help: "BlueBubbles channel provider configuration used for Apple messaging bridge integrations. Keep DM policy aligned with your trusted sender model in shared deployments.", - }, - dmPolicy: { - label: "BlueBubbles DM Policy", - help: 'Direct message access control ("pairing" recommended). "open" requires channels.bluebubbles.allowFrom=["*"].', - }, - }, - }, - { - pluginId: "discord", - channelId: "discord", - label: "Discord", - description: "very well supported right now.", - schema: { - $schema: "http://json-schema.org/draft-07/schema#", - type: "object", - properties: { - name: { - type: "string", - }, - capabilities: { - type: "array", - items: { - type: "string", - }, - }, - markdown: { - type: "object", - properties: { - tables: { - type: "string", - enum: ["off", "bullets", "code"], - }, - }, - additionalProperties: false, - }, - enabled: { - type: "boolean", - }, - commands: { - type: "object", - properties: { - native: { - anyOf: [ - { - type: "boolean", - }, - { - type: "string", - const: "auto", - }, - ], - }, - nativeSkills: { - anyOf: [ - { - type: "boolean", - }, - { - type: "string", - const: "auto", - }, - ], - }, - }, - additionalProperties: false, - }, - configWrites: { - type: "boolean", - }, - token: { - anyOf: [ - { - type: "string", - }, - { - oneOf: [ - { - type: "object", - properties: { - source: { - type: "string", - const: "env", - }, - provider: { - type: "string", - pattern: "^[a-z][a-z0-9_-]{0,63}$", - }, - id: { - type: "string", - pattern: "^[A-Z][A-Z0-9_]{0,127}$", - }, - }, - required: ["source", "provider", "id"], - additionalProperties: false, - }, - { - type: "object", - properties: { - source: { - type: "string", - const: "file", - }, - provider: { - type: "string", - pattern: "^[a-z][a-z0-9_-]{0,63}$", - }, - id: { - type: "string", - }, - }, - required: ["source", "provider", "id"], - additionalProperties: false, - }, - { - type: "object", - properties: { - source: { - type: "string", - const: "exec", - }, - provider: { - type: "string", - pattern: "^[a-z][a-z0-9_-]{0,63}$", - }, - id: { - type: "string", - }, - }, - required: ["source", "provider", "id"], - additionalProperties: false, - }, - ], - }, - ], - }, - proxy: { - type: "string", - }, - allowBots: { - anyOf: [ - { - type: "boolean", - }, - { - type: "string", - const: "mentions", - }, - ], - }, - dangerouslyAllowNameMatching: { - type: "boolean", - }, - groupPolicy: { - default: "allowlist", - type: "string", - enum: ["open", "disabled", "allowlist"], - }, - historyLimit: { - type: "integer", - minimum: 0, - maximum: 9007199254740991, - }, - dmHistoryLimit: { - type: "integer", - minimum: 0, - maximum: 9007199254740991, - }, - dms: { - type: "object", - propertyNames: { - type: "string", - }, - additionalProperties: { - type: "object", - properties: { - historyLimit: { - type: "integer", - minimum: 0, - maximum: 9007199254740991, - }, - }, - additionalProperties: false, - }, - }, - textChunkLimit: { - type: "integer", - exclusiveMinimum: 0, - maximum: 9007199254740991, - }, - chunkMode: { - type: "string", - enum: ["length", "newline"], - }, - blockStreaming: { - type: "boolean", - }, - blockStreamingCoalesce: { - type: "object", - properties: { - minChars: { - type: "integer", - exclusiveMinimum: 0, - maximum: 9007199254740991, - }, - maxChars: { - type: "integer", - exclusiveMinimum: 0, - maximum: 9007199254740991, - }, - idleMs: { - type: "integer", - minimum: 0, - maximum: 9007199254740991, - }, - }, - additionalProperties: false, - }, - streaming: { - anyOf: [ - { - type: "boolean", - }, - { - type: "string", - enum: ["off", "partial", "block", "progress"], - }, - ], - }, - streamMode: { - type: "string", - enum: ["partial", "block", "off"], - }, - draftChunk: { - type: "object", - properties: { - minChars: { - type: "integer", - exclusiveMinimum: 0, - maximum: 9007199254740991, - }, - maxChars: { - type: "integer", - exclusiveMinimum: 0, - maximum: 9007199254740991, - }, - breakPreference: { - anyOf: [ - { - type: "string", - const: "paragraph", - }, - { - type: "string", - const: "newline", - }, - { - type: "string", - const: "sentence", - }, - ], - }, - }, - additionalProperties: false, - }, - maxLinesPerMessage: { - type: "integer", - exclusiveMinimum: 0, - maximum: 9007199254740991, - }, - mediaMaxMb: { - type: "number", - exclusiveMinimum: 0, - }, - retry: { - type: "object", - properties: { - attempts: { - type: "integer", - minimum: 1, - maximum: 9007199254740991, - }, - minDelayMs: { - type: "integer", - minimum: 0, - maximum: 9007199254740991, - }, - maxDelayMs: { - type: "integer", - minimum: 0, - maximum: 9007199254740991, - }, - jitter: { - type: "number", - minimum: 0, - maximum: 1, - }, - }, - additionalProperties: false, - }, - actions: { - type: "object", - properties: { - reactions: { - type: "boolean", - }, - stickers: { - type: "boolean", - }, - emojiUploads: { - type: "boolean", - }, - stickerUploads: { - type: "boolean", - }, - polls: { - type: "boolean", - }, - permissions: { - type: "boolean", - }, - messages: { - type: "boolean", - }, - threads: { - type: "boolean", - }, - pins: { - type: "boolean", - }, - search: { - type: "boolean", - }, - memberInfo: { - type: "boolean", - }, - roleInfo: { - type: "boolean", - }, - roles: { - type: "boolean", - }, - channelInfo: { - type: "boolean", - }, - voiceStatus: { - type: "boolean", - }, - events: { - type: "boolean", - }, - moderation: { - type: "boolean", - }, - channels: { - type: "boolean", - }, - presence: { - type: "boolean", - }, - }, - additionalProperties: false, - }, - replyToMode: { - anyOf: [ - { - type: "string", - const: "off", - }, - { - type: "string", - const: "first", - }, - { - type: "string", - const: "all", - }, - ], - }, - dmPolicy: { - type: "string", - enum: ["pairing", "allowlist", "open", "disabled"], - }, - allowFrom: { - type: "array", - items: { - anyOf: [ - { - type: "string", - }, - { - type: "number", - }, - ], - }, - }, - defaultTo: { - type: "string", - }, - dm: { - type: "object", - properties: { - enabled: { - type: "boolean", - }, - policy: { - type: "string", - enum: ["pairing", "allowlist", "open", "disabled"], - }, - allowFrom: { - type: "array", - items: { - anyOf: [ - { - type: "string", - }, - { - type: "number", - }, - ], - }, - }, - groupEnabled: { - type: "boolean", - }, - groupChannels: { - type: "array", - items: { - anyOf: [ - { - type: "string", - }, - { - type: "number", - }, - ], - }, - }, - }, - additionalProperties: false, - }, - guilds: { - type: "object", - propertyNames: { - type: "string", - }, - additionalProperties: { - type: "object", - properties: { - slug: { - type: "string", - }, - requireMention: { - type: "boolean", - }, - ignoreOtherMentions: { - type: "boolean", - }, - tools: { - type: "object", - properties: { - allow: { - type: "array", - items: { - type: "string", - }, - }, - alsoAllow: { - type: "array", - items: { - type: "string", - }, - }, - deny: { - type: "array", - items: { - type: "string", - }, - }, - }, - additionalProperties: false, - }, - toolsBySender: { - type: "object", - propertyNames: { - type: "string", - }, - additionalProperties: { - type: "object", - properties: { - allow: { - type: "array", - items: { - type: "string", - }, - }, - alsoAllow: { - type: "array", - items: { - type: "string", - }, - }, - deny: { - type: "array", - items: { - type: "string", - }, - }, - }, - additionalProperties: false, - }, - }, - reactionNotifications: { - type: "string", - enum: ["off", "own", "all", "allowlist"], - }, - users: { - type: "array", - items: { - anyOf: [ - { - type: "string", - }, - { - type: "number", - }, - ], - }, - }, - roles: { - type: "array", - items: { - anyOf: [ - { - type: "string", - }, - { - type: "number", - }, - ], - }, - }, - channels: { - type: "object", - propertyNames: { - type: "string", - }, - additionalProperties: { - type: "object", - properties: { - allow: { - type: "boolean", - }, - requireMention: { - type: "boolean", - }, - ignoreOtherMentions: { - type: "boolean", - }, - tools: { - type: "object", - properties: { - allow: { - type: "array", - items: { - type: "string", - }, - }, - alsoAllow: { - type: "array", - items: { - type: "string", - }, - }, - deny: { - type: "array", - items: { - type: "string", - }, - }, - }, - additionalProperties: false, - }, - toolsBySender: { - type: "object", - propertyNames: { - type: "string", - }, - additionalProperties: { - type: "object", - properties: { - allow: { - type: "array", - items: { - type: "string", - }, - }, - alsoAllow: { - type: "array", - items: { - type: "string", - }, - }, - deny: { - type: "array", - items: { - type: "string", - }, - }, - }, - additionalProperties: false, - }, - }, - skills: { - type: "array", - items: { - type: "string", - }, - }, - enabled: { - type: "boolean", - }, - users: { - type: "array", - items: { - anyOf: [ - { - type: "string", - }, - { - type: "number", - }, - ], - }, - }, - roles: { - type: "array", - items: { - anyOf: [ - { - type: "string", - }, - { - type: "number", - }, - ], - }, - }, - systemPrompt: { - type: "string", - }, - includeThreadStarter: { - type: "boolean", - }, - autoThread: { - type: "boolean", - }, - autoThreadName: { - type: "string", - enum: ["message", "generated"], - }, - autoArchiveDuration: { - anyOf: [ - { - type: "string", - enum: ["60", "1440", "4320", "10080"], - }, - { - type: "number", - const: 60, - }, - { - type: "number", - const: 1440, - }, - { - type: "number", - const: 4320, - }, - { - type: "number", - const: 10080, - }, - ], - }, - }, - additionalProperties: false, - }, - }, - }, - additionalProperties: false, - }, - }, - heartbeat: { - type: "object", - properties: { - showOk: { - type: "boolean", - }, - showAlerts: { - type: "boolean", - }, - useIndicator: { - type: "boolean", - }, - }, - additionalProperties: false, - }, - healthMonitor: { - type: "object", - properties: { - enabled: { - type: "boolean", - }, - }, - additionalProperties: false, - }, - execApprovals: { - type: "object", - properties: { - enabled: { - type: "boolean", - }, - approvers: { - type: "array", - items: { - anyOf: [ - { - type: "string", - }, - { - type: "number", - }, - ], - }, - }, - agentFilter: { - type: "array", - items: { - type: "string", - }, - }, - sessionFilter: { - type: "array", - items: { - type: "string", - }, - }, - cleanupAfterResolve: { - type: "boolean", - }, - target: { - type: "string", - enum: ["dm", "channel", "both"], - }, - }, - additionalProperties: false, - }, - agentComponents: { - type: "object", - properties: { - enabled: { - type: "boolean", - }, - }, - additionalProperties: false, - }, - ui: { - type: "object", - properties: { - components: { - type: "object", - properties: { - accentColor: { - type: "string", - pattern: "^#?[0-9a-fA-F]{6}$", - }, - }, - additionalProperties: false, - }, - }, - additionalProperties: false, - }, - slashCommand: { - type: "object", - properties: { - ephemeral: { - type: "boolean", - }, - }, - additionalProperties: false, - }, - threadBindings: { - type: "object", - properties: { - enabled: { - type: "boolean", - }, - idleHours: { - type: "number", - minimum: 0, - }, - maxAgeHours: { - type: "number", - minimum: 0, - }, - spawnSubagentSessions: { - type: "boolean", - }, - spawnAcpSessions: { - type: "boolean", - }, - }, - additionalProperties: false, - }, - intents: { - type: "object", - properties: { - presence: { - type: "boolean", - }, - guildMembers: { - type: "boolean", - }, - }, - additionalProperties: false, - }, - voice: { - type: "object", - properties: { - enabled: { - type: "boolean", - }, - autoJoin: { - type: "array", - items: { - type: "object", - properties: { - guildId: { - type: "string", - minLength: 1, - }, - channelId: { - type: "string", - minLength: 1, - }, - }, - required: ["guildId", "channelId"], - additionalProperties: false, - }, - }, - daveEncryption: { - type: "boolean", - }, - decryptionFailureTolerance: { - type: "integer", - minimum: 0, - maximum: 9007199254740991, - }, - tts: { - type: "object", - properties: { - auto: { - type: "string", - enum: ["off", "always", "inbound", "tagged"], - }, - enabled: { - type: "boolean", - }, - mode: { - type: "string", - enum: ["final", "all"], - }, - provider: { - type: "string", - minLength: 1, - }, - summaryModel: { - type: "string", - }, - modelOverrides: { - type: "object", - properties: { - enabled: { - type: "boolean", - }, - allowText: { - type: "boolean", - }, - allowProvider: { - type: "boolean", - }, - allowVoice: { - type: "boolean", - }, - allowModelId: { - type: "boolean", - }, - allowVoiceSettings: { - type: "boolean", - }, - allowNormalization: { - type: "boolean", - }, - allowSeed: { - type: "boolean", - }, - }, - additionalProperties: false, - }, - providers: { - type: "object", - propertyNames: { - type: "string", - }, - additionalProperties: { - type: "object", - properties: { - apiKey: { - anyOf: [ - { - type: "string", - }, - { - oneOf: [ - { - type: "object", - properties: { - source: { - type: "string", - const: "env", - }, - provider: { - type: "string", - pattern: "^[a-z][a-z0-9_-]{0,63}$", - }, - id: { - type: "string", - pattern: "^[A-Z][A-Z0-9_]{0,127}$", - }, - }, - required: ["source", "provider", "id"], - additionalProperties: false, - }, - { - type: "object", - properties: { - source: { - type: "string", - const: "file", - }, - provider: { - type: "string", - pattern: "^[a-z][a-z0-9_-]{0,63}$", - }, - id: { - type: "string", - }, - }, - required: ["source", "provider", "id"], - additionalProperties: false, - }, - { - type: "object", - properties: { - source: { - type: "string", - const: "exec", - }, - provider: { - type: "string", - pattern: "^[a-z][a-z0-9_-]{0,63}$", - }, - id: { - type: "string", - }, - }, - required: ["source", "provider", "id"], - additionalProperties: false, - }, - ], - }, - ], - }, - }, - additionalProperties: { - anyOf: [ - { - type: "string", - }, - { - type: "number", - }, - { - type: "boolean", - }, - { - type: "null", - }, - { - type: "array", - items: {}, - }, - { - type: "object", - propertyNames: { - type: "string", - }, - additionalProperties: {}, - }, - ], - }, - }, - }, - prefsPath: { - type: "string", - }, - maxTextLength: { - type: "integer", - minimum: 1, - maximum: 9007199254740991, - }, - timeoutMs: { - type: "integer", - minimum: 1000, - maximum: 120000, - }, - }, - additionalProperties: false, - }, - }, - additionalProperties: false, - }, - pluralkit: { - type: "object", - properties: { - enabled: { - type: "boolean", - }, - token: { - anyOf: [ - { - type: "string", - }, - { - oneOf: [ - { - type: "object", - properties: { - source: { - type: "string", - const: "env", - }, - provider: { - type: "string", - pattern: "^[a-z][a-z0-9_-]{0,63}$", - }, - id: { - type: "string", - pattern: "^[A-Z][A-Z0-9_]{0,127}$", - }, - }, - required: ["source", "provider", "id"], - additionalProperties: false, - }, - { - type: "object", - properties: { - source: { - type: "string", - const: "file", - }, - provider: { - type: "string", - pattern: "^[a-z][a-z0-9_-]{0,63}$", - }, - id: { - type: "string", - }, - }, - required: ["source", "provider", "id"], - additionalProperties: false, - }, - { - type: "object", - properties: { - source: { - type: "string", - const: "exec", - }, - provider: { - type: "string", - pattern: "^[a-z][a-z0-9_-]{0,63}$", - }, - id: { - type: "string", - }, - }, - required: ["source", "provider", "id"], - additionalProperties: false, - }, - ], - }, - ], - }, - }, - additionalProperties: false, - }, - responsePrefix: { - type: "string", - }, - ackReaction: { - type: "string", - }, - ackReactionScope: { - type: "string", - enum: ["group-mentions", "group-all", "direct", "all", "off", "none"], - }, - activity: { - type: "string", - }, - status: { - type: "string", - enum: ["online", "dnd", "idle", "invisible"], - }, - autoPresence: { - type: "object", - properties: { - enabled: { - type: "boolean", - }, - intervalMs: { - type: "integer", - exclusiveMinimum: 0, - maximum: 9007199254740991, - }, - minUpdateIntervalMs: { - type: "integer", - exclusiveMinimum: 0, - maximum: 9007199254740991, - }, - healthyText: { - type: "string", - }, - degradedText: { - type: "string", - }, - exhaustedText: { - type: "string", - }, - }, - additionalProperties: false, - }, - activityType: { - anyOf: [ - { - type: "number", - const: 0, - }, - { - type: "number", - const: 1, - }, - { - type: "number", - const: 2, - }, - { - type: "number", - const: 3, - }, - { - type: "number", - const: 4, - }, - { - type: "number", - const: 5, - }, - ], - }, - activityUrl: { - type: "string", - format: "uri", - }, - inboundWorker: { - type: "object", - properties: { - runTimeoutMs: { - type: "integer", - minimum: 0, - maximum: 9007199254740991, - }, - }, - additionalProperties: false, - }, - eventQueue: { - type: "object", - properties: { - listenerTimeout: { - type: "integer", - exclusiveMinimum: 0, - maximum: 9007199254740991, - }, - maxQueueSize: { - type: "integer", - exclusiveMinimum: 0, - maximum: 9007199254740991, - }, - maxConcurrency: { - type: "integer", - exclusiveMinimum: 0, - maximum: 9007199254740991, - }, - }, - additionalProperties: false, - }, - accounts: { - type: "object", - propertyNames: { - type: "string", - }, - additionalProperties: { - type: "object", - properties: { - name: { - type: "string", - }, - capabilities: { - type: "array", - items: { - type: "string", - }, - }, - markdown: { - type: "object", - properties: { - tables: { - type: "string", - enum: ["off", "bullets", "code"], - }, - }, - additionalProperties: false, - }, - enabled: { - type: "boolean", - }, - commands: { - type: "object", - properties: { - native: { - anyOf: [ - { - type: "boolean", - }, - { - type: "string", - const: "auto", - }, - ], - }, - nativeSkills: { - anyOf: [ - { - type: "boolean", - }, - { - type: "string", - const: "auto", - }, - ], - }, - }, - additionalProperties: false, - }, - configWrites: { - type: "boolean", - }, - token: { - anyOf: [ - { - type: "string", - }, - { - oneOf: [ - { - type: "object", - properties: { - source: { - type: "string", - const: "env", - }, - provider: { - type: "string", - pattern: "^[a-z][a-z0-9_-]{0,63}$", - }, - id: { - type: "string", - pattern: "^[A-Z][A-Z0-9_]{0,127}$", - }, - }, - required: ["source", "provider", "id"], - additionalProperties: false, - }, - { - type: "object", - properties: { - source: { - type: "string", - const: "file", - }, - provider: { - type: "string", - pattern: "^[a-z][a-z0-9_-]{0,63}$", - }, - id: { - type: "string", - }, - }, - required: ["source", "provider", "id"], - additionalProperties: false, - }, - { - type: "object", - properties: { - source: { - type: "string", - const: "exec", - }, - provider: { - type: "string", - pattern: "^[a-z][a-z0-9_-]{0,63}$", - }, - id: { - type: "string", - }, - }, - required: ["source", "provider", "id"], - additionalProperties: false, - }, - ], - }, - ], - }, - proxy: { - type: "string", - }, - allowBots: { - anyOf: [ - { - type: "boolean", - }, - { - type: "string", - const: "mentions", - }, - ], - }, - dangerouslyAllowNameMatching: { - type: "boolean", - }, - groupPolicy: { - default: "allowlist", - type: "string", - enum: ["open", "disabled", "allowlist"], - }, - historyLimit: { - type: "integer", - minimum: 0, - maximum: 9007199254740991, - }, - dmHistoryLimit: { - type: "integer", - minimum: 0, - maximum: 9007199254740991, - }, - dms: { - type: "object", - propertyNames: { - type: "string", - }, - additionalProperties: { - type: "object", - properties: { - historyLimit: { - type: "integer", - minimum: 0, - maximum: 9007199254740991, - }, - }, - additionalProperties: false, - }, - }, - textChunkLimit: { - type: "integer", - exclusiveMinimum: 0, - maximum: 9007199254740991, - }, - chunkMode: { - type: "string", - enum: ["length", "newline"], - }, - blockStreaming: { - type: "boolean", - }, - blockStreamingCoalesce: { - type: "object", - properties: { - minChars: { - type: "integer", - exclusiveMinimum: 0, - maximum: 9007199254740991, - }, - maxChars: { - type: "integer", - exclusiveMinimum: 0, - maximum: 9007199254740991, - }, - idleMs: { - type: "integer", - minimum: 0, - maximum: 9007199254740991, - }, - }, - additionalProperties: false, - }, - streaming: { - anyOf: [ - { - type: "boolean", - }, - { - type: "string", - enum: ["off", "partial", "block", "progress"], - }, - ], - }, - streamMode: { - type: "string", - enum: ["partial", "block", "off"], - }, - draftChunk: { - type: "object", - properties: { - minChars: { - type: "integer", - exclusiveMinimum: 0, - maximum: 9007199254740991, - }, - maxChars: { - type: "integer", - exclusiveMinimum: 0, - maximum: 9007199254740991, - }, - breakPreference: { - anyOf: [ - { - type: "string", - const: "paragraph", - }, - { - type: "string", - const: "newline", - }, - { - type: "string", - const: "sentence", - }, - ], - }, - }, - additionalProperties: false, - }, - maxLinesPerMessage: { - type: "integer", - exclusiveMinimum: 0, - maximum: 9007199254740991, - }, - mediaMaxMb: { - type: "number", - exclusiveMinimum: 0, - }, - retry: { - type: "object", - properties: { - attempts: { - type: "integer", - minimum: 1, - maximum: 9007199254740991, - }, - minDelayMs: { - type: "integer", - minimum: 0, - maximum: 9007199254740991, - }, - maxDelayMs: { - type: "integer", - minimum: 0, - maximum: 9007199254740991, - }, - jitter: { - type: "number", - minimum: 0, - maximum: 1, - }, - }, - additionalProperties: false, - }, - actions: { - type: "object", - properties: { - reactions: { - type: "boolean", - }, - stickers: { - type: "boolean", - }, - emojiUploads: { - type: "boolean", - }, - stickerUploads: { - type: "boolean", - }, - polls: { - type: "boolean", - }, - permissions: { - type: "boolean", - }, - messages: { - type: "boolean", - }, - threads: { - type: "boolean", - }, - pins: { - type: "boolean", - }, - search: { - type: "boolean", - }, - memberInfo: { - type: "boolean", - }, - roleInfo: { - type: "boolean", - }, - roles: { - type: "boolean", - }, - channelInfo: { - type: "boolean", - }, - voiceStatus: { - type: "boolean", - }, - events: { - type: "boolean", - }, - moderation: { - type: "boolean", - }, - channels: { - type: "boolean", - }, - presence: { - type: "boolean", - }, - }, - additionalProperties: false, - }, - replyToMode: { - anyOf: [ - { - type: "string", - const: "off", - }, - { - type: "string", - const: "first", - }, - { - type: "string", - const: "all", - }, - ], - }, - dmPolicy: { - type: "string", - enum: ["pairing", "allowlist", "open", "disabled"], - }, - allowFrom: { - type: "array", - items: { - anyOf: [ - { - type: "string", - }, - { - type: "number", - }, - ], - }, - }, - defaultTo: { - type: "string", - }, - dm: { - type: "object", - properties: { - enabled: { - type: "boolean", - }, - policy: { - type: "string", - enum: ["pairing", "allowlist", "open", "disabled"], - }, - allowFrom: { - type: "array", - items: { - anyOf: [ - { - type: "string", - }, - { - type: "number", - }, - ], - }, - }, - groupEnabled: { - type: "boolean", - }, - groupChannels: { - type: "array", - items: { - anyOf: [ - { - type: "string", - }, - { - type: "number", - }, - ], - }, - }, - }, - additionalProperties: false, - }, - guilds: { - type: "object", - propertyNames: { - type: "string", - }, - additionalProperties: { - type: "object", - properties: { - slug: { - type: "string", - }, - requireMention: { - type: "boolean", - }, - ignoreOtherMentions: { - type: "boolean", - }, - tools: { - type: "object", - properties: { - allow: { - type: "array", - items: { - type: "string", - }, - }, - alsoAllow: { - type: "array", - items: { - type: "string", - }, - }, - deny: { - type: "array", - items: { - type: "string", - }, - }, - }, - additionalProperties: false, - }, - toolsBySender: { - type: "object", - propertyNames: { - type: "string", - }, - additionalProperties: { - type: "object", - properties: { - allow: { - type: "array", - items: { - type: "string", - }, - }, - alsoAllow: { - type: "array", - items: { - type: "string", - }, - }, - deny: { - type: "array", - items: { - type: "string", - }, - }, - }, - additionalProperties: false, - }, - }, - reactionNotifications: { - type: "string", - enum: ["off", "own", "all", "allowlist"], - }, - users: { - type: "array", - items: { - anyOf: [ - { - type: "string", - }, - { - type: "number", - }, - ], - }, - }, - roles: { - type: "array", - items: { - anyOf: [ - { - type: "string", - }, - { - type: "number", - }, - ], - }, - }, - channels: { - type: "object", - propertyNames: { - type: "string", - }, - additionalProperties: { - type: "object", - properties: { - allow: { - type: "boolean", - }, - requireMention: { - type: "boolean", - }, - ignoreOtherMentions: { - type: "boolean", - }, - tools: { - type: "object", - properties: { - allow: { - type: "array", - items: { - type: "string", - }, - }, - alsoAllow: { - type: "array", - items: { - type: "string", - }, - }, - deny: { - type: "array", - items: { - type: "string", - }, - }, - }, - additionalProperties: false, - }, - toolsBySender: { - type: "object", - propertyNames: { - type: "string", - }, - additionalProperties: { - type: "object", - properties: { - allow: { - type: "array", - items: { - type: "string", - }, - }, - alsoAllow: { - type: "array", - items: { - type: "string", - }, - }, - deny: { - type: "array", - items: { - type: "string", - }, - }, - }, - additionalProperties: false, - }, - }, - skills: { - type: "array", - items: { - type: "string", - }, - }, - enabled: { - type: "boolean", - }, - users: { - type: "array", - items: { - anyOf: [ - { - type: "string", - }, - { - type: "number", - }, - ], - }, - }, - roles: { - type: "array", - items: { - anyOf: [ - { - type: "string", - }, - { - type: "number", - }, - ], - }, - }, - systemPrompt: { - type: "string", - }, - includeThreadStarter: { - type: "boolean", - }, - autoThread: { - type: "boolean", - }, - autoThreadName: { - type: "string", - enum: ["message", "generated"], - }, - autoArchiveDuration: { - anyOf: [ - { - type: "string", - enum: ["60", "1440", "4320", "10080"], - }, - { - type: "number", - const: 60, - }, - { - type: "number", - const: 1440, - }, - { - type: "number", - const: 4320, - }, - { - type: "number", - const: 10080, - }, - ], - }, - }, - additionalProperties: false, - }, - }, - }, - additionalProperties: false, - }, - }, - heartbeat: { - type: "object", - properties: { - showOk: { - type: "boolean", - }, - showAlerts: { - type: "boolean", - }, - useIndicator: { - type: "boolean", - }, - }, - additionalProperties: false, - }, - healthMonitor: { - type: "object", - properties: { - enabled: { - type: "boolean", - }, - }, - additionalProperties: false, - }, - execApprovals: { - type: "object", - properties: { - enabled: { - type: "boolean", - }, - approvers: { - type: "array", - items: { - anyOf: [ - { - type: "string", - }, - { - type: "number", - }, - ], - }, - }, - agentFilter: { - type: "array", - items: { - type: "string", - }, - }, - sessionFilter: { - type: "array", - items: { - type: "string", - }, - }, - cleanupAfterResolve: { - type: "boolean", - }, - target: { - type: "string", - enum: ["dm", "channel", "both"], - }, - }, - additionalProperties: false, - }, - agentComponents: { - type: "object", - properties: { - enabled: { - type: "boolean", - }, - }, - additionalProperties: false, - }, - ui: { - type: "object", - properties: { - components: { - type: "object", - properties: { - accentColor: { - type: "string", - pattern: "^#?[0-9a-fA-F]{6}$", - }, - }, - additionalProperties: false, - }, - }, - additionalProperties: false, - }, - slashCommand: { - type: "object", - properties: { - ephemeral: { - type: "boolean", - }, - }, - additionalProperties: false, - }, - threadBindings: { - type: "object", - properties: { - enabled: { - type: "boolean", - }, - idleHours: { - type: "number", - minimum: 0, - }, - maxAgeHours: { - type: "number", - minimum: 0, - }, - spawnSubagentSessions: { - type: "boolean", - }, - spawnAcpSessions: { - type: "boolean", - }, - }, - additionalProperties: false, - }, - intents: { - type: "object", - properties: { - presence: { - type: "boolean", - }, - guildMembers: { - type: "boolean", - }, - }, - additionalProperties: false, - }, - voice: { - type: "object", - properties: { - enabled: { - type: "boolean", - }, - autoJoin: { - type: "array", - items: { - type: "object", - properties: { - guildId: { - type: "string", - minLength: 1, - }, - channelId: { - type: "string", - minLength: 1, - }, - }, - required: ["guildId", "channelId"], - additionalProperties: false, - }, - }, - daveEncryption: { - type: "boolean", - }, - decryptionFailureTolerance: { - type: "integer", - minimum: 0, - maximum: 9007199254740991, - }, - tts: { - type: "object", - properties: { - auto: { - type: "string", - enum: ["off", "always", "inbound", "tagged"], - }, - enabled: { - type: "boolean", - }, - mode: { - type: "string", - enum: ["final", "all"], - }, - provider: { - type: "string", - minLength: 1, - }, - summaryModel: { - type: "string", - }, - modelOverrides: { - type: "object", - properties: { - enabled: { - type: "boolean", - }, - allowText: { - type: "boolean", - }, - allowProvider: { - type: "boolean", - }, - allowVoice: { - type: "boolean", - }, - allowModelId: { - type: "boolean", - }, - allowVoiceSettings: { - type: "boolean", - }, - allowNormalization: { - type: "boolean", - }, - allowSeed: { - type: "boolean", - }, - }, - additionalProperties: false, - }, - providers: { - type: "object", - propertyNames: { - type: "string", - }, - additionalProperties: { - type: "object", - properties: { - apiKey: { - anyOf: [ - { - type: "string", - }, - { - oneOf: [ - { - type: "object", - properties: { - source: { - type: "string", - const: "env", - }, - provider: { - type: "string", - pattern: "^[a-z][a-z0-9_-]{0,63}$", - }, - id: { - type: "string", - pattern: "^[A-Z][A-Z0-9_]{0,127}$", - }, - }, - required: ["source", "provider", "id"], - additionalProperties: false, - }, - { - type: "object", - properties: { - source: { - type: "string", - const: "file", - }, - provider: { - type: "string", - pattern: "^[a-z][a-z0-9_-]{0,63}$", - }, - id: { - type: "string", - }, - }, - required: ["source", "provider", "id"], - additionalProperties: false, - }, - { - type: "object", - properties: { - source: { - type: "string", - const: "exec", - }, - provider: { - type: "string", - pattern: "^[a-z][a-z0-9_-]{0,63}$", - }, - id: { - type: "string", - }, - }, - required: ["source", "provider", "id"], - additionalProperties: false, - }, - ], - }, - ], - }, - }, - additionalProperties: { - anyOf: [ - { - type: "string", - }, - { - type: "number", - }, - { - type: "boolean", - }, - { - type: "null", - }, - { - type: "array", - items: {}, - }, - { - type: "object", - propertyNames: { - type: "string", - }, - additionalProperties: {}, - }, - ], - }, - }, - }, - prefsPath: { - type: "string", - }, - maxTextLength: { - type: "integer", - minimum: 1, - maximum: 9007199254740991, - }, - timeoutMs: { - type: "integer", - minimum: 1000, - maximum: 120000, - }, - }, - additionalProperties: false, - }, - }, - additionalProperties: false, - }, - pluralkit: { - type: "object", - properties: { - enabled: { - type: "boolean", - }, - token: { - anyOf: [ - { - type: "string", - }, - { - oneOf: [ - { - type: "object", - properties: { - source: { - type: "string", - const: "env", - }, - provider: { - type: "string", - pattern: "^[a-z][a-z0-9_-]{0,63}$", - }, - id: { - type: "string", - pattern: "^[A-Z][A-Z0-9_]{0,127}$", - }, - }, - required: ["source", "provider", "id"], - additionalProperties: false, - }, - { - type: "object", - properties: { - source: { - type: "string", - const: "file", - }, - provider: { - type: "string", - pattern: "^[a-z][a-z0-9_-]{0,63}$", - }, - id: { - type: "string", - }, - }, - required: ["source", "provider", "id"], - additionalProperties: false, - }, - { - type: "object", - properties: { - source: { - type: "string", - const: "exec", - }, - provider: { - type: "string", - pattern: "^[a-z][a-z0-9_-]{0,63}$", - }, - id: { - type: "string", - }, - }, - required: ["source", "provider", "id"], - additionalProperties: false, - }, - ], - }, - ], - }, - }, - additionalProperties: false, - }, - responsePrefix: { - type: "string", - }, - ackReaction: { - type: "string", - }, - ackReactionScope: { - type: "string", - enum: ["group-mentions", "group-all", "direct", "all", "off", "none"], - }, - activity: { - type: "string", - }, - status: { - type: "string", - enum: ["online", "dnd", "idle", "invisible"], - }, - autoPresence: { - type: "object", - properties: { - enabled: { - type: "boolean", - }, - intervalMs: { - type: "integer", - exclusiveMinimum: 0, - maximum: 9007199254740991, - }, - minUpdateIntervalMs: { - type: "integer", - exclusiveMinimum: 0, - maximum: 9007199254740991, - }, - healthyText: { - type: "string", - }, - degradedText: { - type: "string", - }, - exhaustedText: { - type: "string", - }, - }, - additionalProperties: false, - }, - activityType: { - anyOf: [ - { - type: "number", - const: 0, - }, - { - type: "number", - const: 1, - }, - { - type: "number", - const: 2, - }, - { - type: "number", - const: 3, - }, - { - type: "number", - const: 4, - }, - { - type: "number", - const: 5, - }, - ], - }, - activityUrl: { - type: "string", - format: "uri", - }, - inboundWorker: { - type: "object", - properties: { - runTimeoutMs: { - type: "integer", - minimum: 0, - maximum: 9007199254740991, - }, - }, - additionalProperties: false, - }, - eventQueue: { - type: "object", - properties: { - listenerTimeout: { - type: "integer", - exclusiveMinimum: 0, - maximum: 9007199254740991, - }, - maxQueueSize: { - type: "integer", - exclusiveMinimum: 0, - maximum: 9007199254740991, - }, - maxConcurrency: { - type: "integer", - exclusiveMinimum: 0, - maximum: 9007199254740991, - }, - }, - additionalProperties: false, - }, - }, - required: ["groupPolicy"], - additionalProperties: false, - }, - }, - defaultAccount: { - type: "string", - }, - }, - required: ["groupPolicy"], - additionalProperties: false, - }, - uiHints: { - "": { - label: "Discord", - help: "Discord channel provider configuration for bot auth, retry policy, streaming, thread bindings, and optional voice capabilities. Keep privileged intents and advanced features disabled unless needed.", - }, - dmPolicy: { - label: "Discord DM Policy", - help: 'Direct message access control ("pairing" recommended). "open" requires channels.discord.allowFrom=["*"].', - }, - "dm.policy": { - label: "Discord DM Policy", - help: 'Direct message access control ("pairing" recommended). "open" requires channels.discord.allowFrom=["*"] (legacy: channels.discord.dm.allowFrom).', - }, - configWrites: { - label: "Discord Config Writes", - help: "Allow Discord to write config in response to channel events/commands (default: true).", - }, - proxy: { - label: "Discord Proxy URL", - help: "Proxy URL for Discord gateway + API requests (app-id lookup and allowlist resolution). Set per account via channels.discord.accounts..proxy.", - }, - "commands.native": { - label: "Discord Native Commands", - help: 'Override native commands for Discord (bool or "auto").', - }, - "commands.nativeSkills": { - label: "Discord Native Skill Commands", - help: 'Override native skill commands for Discord (bool or "auto").', - }, - streaming: { - label: "Discord Streaming Mode", - help: 'Unified Discord stream preview mode: "off" | "partial" | "block" | "progress". "progress" maps to "partial" on Discord. Legacy boolean/streamMode keys are auto-mapped.', - }, - streamMode: { - label: "Discord Stream Mode (Legacy)", - help: "Legacy Discord preview mode alias (off | partial | block); auto-migrated to channels.discord.streaming.", - }, - "draftChunk.minChars": { - label: "Discord Draft Chunk Min Chars", - help: 'Minimum chars before emitting a Discord stream preview update when channels.discord.streaming="block" (default: 200).', - }, - "draftChunk.maxChars": { - label: "Discord Draft Chunk Max Chars", - help: 'Target max size for a Discord stream preview chunk when channels.discord.streaming="block" (default: 800; clamped to channels.discord.textChunkLimit).', - }, - "draftChunk.breakPreference": { - label: "Discord Draft Chunk Break Preference", - help: "Preferred breakpoints for Discord draft chunks (paragraph | newline | sentence). Default: paragraph.", - }, - "retry.attempts": { - label: "Discord Retry Attempts", - help: "Max retry attempts for outbound Discord API calls (default: 3).", - }, - "retry.minDelayMs": { - label: "Discord Retry Min Delay (ms)", - help: "Minimum retry delay in ms for Discord outbound calls.", - }, - "retry.maxDelayMs": { - label: "Discord Retry Max Delay (ms)", - help: "Maximum retry delay cap in ms for Discord outbound calls.", - }, - "retry.jitter": { - label: "Discord Retry Jitter", - help: "Jitter factor (0-1) applied to Discord retry delays.", - }, - maxLinesPerMessage: { - label: "Discord Max Lines Per Message", - help: "Soft max line count per Discord message (default: 17).", - }, - "inboundWorker.runTimeoutMs": { - label: "Discord Inbound Worker Timeout (ms)", - help: "Optional queued Discord inbound worker timeout in ms. This is separate from Carbon listener timeouts; defaults to 1800000 and can be disabled with 0. Set per account via channels.discord.accounts..inboundWorker.runTimeoutMs.", - }, - "eventQueue.listenerTimeout": { - label: "Discord EventQueue Listener Timeout (ms)", - help: "Canonical Discord listener timeout control in ms for gateway normalization/enqueue handlers. Default is 120000 in OpenClaw; set per account via channels.discord.accounts..eventQueue.listenerTimeout.", - }, - "eventQueue.maxQueueSize": { - label: "Discord EventQueue Max Queue Size", - help: "Optional Discord EventQueue capacity override (max queued events before backpressure). Set per account via channels.discord.accounts..eventQueue.maxQueueSize.", - }, - "eventQueue.maxConcurrency": { - label: "Discord EventQueue Max Concurrency", - help: "Optional Discord EventQueue concurrency override (max concurrent handler executions). Set per account via channels.discord.accounts..eventQueue.maxConcurrency.", - }, - "threadBindings.enabled": { - label: "Discord Thread Binding Enabled", - help: "Enable Discord thread binding features (/focus, bound-thread routing/delivery, and thread-bound subagent sessions). Overrides session.threadBindings.enabled when set.", - }, - "threadBindings.idleHours": { - label: "Discord Thread Binding Idle Timeout (hours)", - help: "Inactivity window in hours for Discord thread-bound sessions (/focus and spawned thread sessions). Set 0 to disable idle auto-unfocus (default: 24). Overrides session.threadBindings.idleHours when set.", - }, - "threadBindings.maxAgeHours": { - label: "Discord Thread Binding Max Age (hours)", - help: "Optional hard max age in hours for Discord thread-bound sessions. Set 0 to disable hard cap (default: 0). Overrides session.threadBindings.maxAgeHours when set.", - }, - "threadBindings.spawnSubagentSessions": { - label: "Discord Thread-Bound Subagent Spawn", - help: "Allow subagent spawns with thread=true to auto-create and bind Discord threads (default: false; opt-in). Set true to enable thread-bound subagent spawns for this account/channel.", - }, - "threadBindings.spawnAcpSessions": { - label: "Discord Thread-Bound ACP Spawn", - help: "Allow /acp spawn to auto-create and bind Discord threads for ACP sessions (default: false; opt-in). Set true to enable thread-bound ACP spawns for this account/channel.", - }, - "ui.components.accentColor": { - label: "Discord Component Accent Color", - help: "Accent color for Discord component containers (hex). Set per account via channels.discord.accounts..ui.components.accentColor.", - }, - "intents.presence": { - label: "Discord Presence Intent", - help: "Enable the Guild Presences privileged intent. Must also be enabled in the Discord Developer Portal. Allows tracking user activities (e.g. Spotify). Default: false.", - }, - "intents.guildMembers": { - label: "Discord Guild Members Intent", - help: "Enable the Guild Members privileged intent. Must also be enabled in the Discord Developer Portal. Default: false.", - }, - "voice.enabled": { - label: "Discord Voice Enabled", - help: "Enable Discord voice channel conversations (default: true). Omit channels.discord.voice to keep voice support disabled for the account.", - }, - "voice.autoJoin": { - label: "Discord Voice Auto-Join", - help: "Voice channels to auto-join on startup (list of guildId/channelId entries).", - }, - "voice.daveEncryption": { - label: "Discord Voice DAVE Encryption", - help: "Toggle DAVE end-to-end encryption for Discord voice joins (default: true in @discordjs/voice; Discord may require this).", - }, - "voice.decryptionFailureTolerance": { - label: "Discord Voice Decrypt Failure Tolerance", - help: "Consecutive decrypt failures before DAVE attempts session recovery (passed to @discordjs/voice; default: 24).", - }, - "voice.tts": { - label: "Discord Voice Text-to-Speech", - help: "Optional TTS overrides for Discord voice playback (merged with messages.tts).", - }, - "pluralkit.enabled": { - label: "Discord PluralKit Enabled", - help: "Resolve PluralKit proxied messages and treat system members as distinct senders.", - }, - "pluralkit.token": { - label: "Discord PluralKit Token", - help: "Optional PluralKit token for resolving private systems or members.", - }, - activity: { - label: "Discord Presence Activity", - help: "Discord presence activity text (defaults to custom status).", - }, - status: { - label: "Discord Presence Status", - help: "Discord presence status (online, dnd, idle, invisible).", - }, - "autoPresence.enabled": { - label: "Discord Auto Presence Enabled", - help: "Enable automatic Discord bot presence updates based on runtime/model availability signals. When enabled: healthy=>online, degraded/unknown=>idle, exhausted/unavailable=>dnd.", - }, - "autoPresence.intervalMs": { - label: "Discord Auto Presence Check Interval (ms)", - help: "How often to evaluate Discord auto-presence state in milliseconds (default: 30000).", - }, - "autoPresence.minUpdateIntervalMs": { - label: "Discord Auto Presence Min Update Interval (ms)", - help: "Minimum time between actual Discord presence update calls in milliseconds (default: 15000). Prevents status spam on noisy state changes.", - }, - "autoPresence.healthyText": { - label: "Discord Auto Presence Healthy Text", - help: "Optional custom status text while runtime is healthy (online). If omitted, falls back to static channels.discord.activity when set.", - }, - "autoPresence.degradedText": { - label: "Discord Auto Presence Degraded Text", - help: "Optional custom status text while runtime/model availability is degraded or unknown (idle).", - }, - "autoPresence.exhaustedText": { - label: "Discord Auto Presence Exhausted Text", - help: "Optional custom status text while runtime detects exhausted/unavailable model quota (dnd). Supports {reason} template placeholder.", - }, - activityType: { - label: "Discord Presence Activity Type", - help: "Discord presence activity type (0=Playing,1=Streaming,2=Listening,3=Watching,4=Custom,5=Competing).", - }, - activityUrl: { - label: "Discord Presence Activity URL", - help: "Discord presence streaming URL (required for activityType=1).", - }, - allowBots: { - label: "Discord Allow Bot Messages", - help: 'Allow bot-authored messages to trigger Discord replies (default: false). Set "mentions" to only accept bot messages that mention the bot.', - }, - token: { - label: "Discord Bot Token", - help: "Discord bot token used for gateway and REST API authentication for this provider account. Keep this secret out of committed config and rotate immediately after any leak.", - }, - }, - }, - { - pluginId: "feishu", - channelId: "feishu", - label: "Feishu", - description: "飞书/Lark enterprise messaging with doc/wiki/drive tools.", - schema: { - $schema: "http://json-schema.org/draft-07/schema#", - type: "object", - properties: { - enabled: { - type: "boolean", - }, - defaultAccount: { - type: "string", - }, - appId: { - type: "string", - }, - appSecret: { - anyOf: [ - { - type: "string", - }, - { - oneOf: [ - { - type: "object", - properties: { - source: { - type: "string", - const: "env", - }, - provider: { - type: "string", - pattern: "^[a-z][a-z0-9_-]{0,63}$", - }, - id: { - type: "string", - pattern: "^[A-Z][A-Z0-9_]{0,127}$", - }, - }, - required: ["source", "provider", "id"], - additionalProperties: false, - }, - { - type: "object", - properties: { - source: { - type: "string", - const: "file", - }, - provider: { - type: "string", - pattern: "^[a-z][a-z0-9_-]{0,63}$", - }, - id: { - type: "string", - }, - }, - required: ["source", "provider", "id"], - additionalProperties: false, - }, - { - type: "object", - properties: { - source: { - type: "string", - const: "exec", - }, - provider: { - type: "string", - pattern: "^[a-z][a-z0-9_-]{0,63}$", - }, - id: { - type: "string", - }, - }, - required: ["source", "provider", "id"], - additionalProperties: false, - }, - ], - }, - ], - }, - encryptKey: { - anyOf: [ - { - type: "string", - }, - { - oneOf: [ - { - type: "object", - properties: { - source: { - type: "string", - const: "env", - }, - provider: { - type: "string", - pattern: "^[a-z][a-z0-9_-]{0,63}$", - }, - id: { - type: "string", - pattern: "^[A-Z][A-Z0-9_]{0,127}$", - }, - }, - required: ["source", "provider", "id"], - additionalProperties: false, - }, - { - type: "object", - properties: { - source: { - type: "string", - const: "file", - }, - provider: { - type: "string", - pattern: "^[a-z][a-z0-9_-]{0,63}$", - }, - id: { - type: "string", - }, - }, - required: ["source", "provider", "id"], - additionalProperties: false, - }, - { - type: "object", - properties: { - source: { - type: "string", - const: "exec", - }, - provider: { - type: "string", - pattern: "^[a-z][a-z0-9_-]{0,63}$", - }, - id: { - type: "string", - }, - }, - required: ["source", "provider", "id"], - additionalProperties: false, - }, - ], - }, - ], - }, - verificationToken: { - anyOf: [ - { - type: "string", - }, - { - oneOf: [ - { - type: "object", - properties: { - source: { - type: "string", - const: "env", - }, - provider: { - type: "string", - pattern: "^[a-z][a-z0-9_-]{0,63}$", - }, - id: { - type: "string", - pattern: "^[A-Z][A-Z0-9_]{0,127}$", - }, - }, - required: ["source", "provider", "id"], - additionalProperties: false, - }, - { - type: "object", - properties: { - source: { - type: "string", - const: "file", - }, - provider: { - type: "string", - pattern: "^[a-z][a-z0-9_-]{0,63}$", - }, - id: { - type: "string", - }, - }, - required: ["source", "provider", "id"], - additionalProperties: false, - }, - { - type: "object", - properties: { - source: { - type: "string", - const: "exec", - }, - provider: { - type: "string", - pattern: "^[a-z][a-z0-9_-]{0,63}$", - }, - id: { - type: "string", - }, - }, - required: ["source", "provider", "id"], - additionalProperties: false, - }, - ], - }, - ], - }, - domain: { - default: "feishu", - anyOf: [ - { - type: "string", - enum: ["feishu", "lark"], - }, - { - type: "string", - format: "uri", - pattern: "^https:\\/\\/.*", - }, - ], - }, - connectionMode: { - default: "websocket", - type: "string", - enum: ["websocket", "webhook"], - }, - webhookPath: { - default: "/feishu/events", - type: "string", - }, - webhookHost: { - type: "string", - }, - webhookPort: { - type: "integer", - exclusiveMinimum: 0, - maximum: 9007199254740991, - }, - capabilities: { - type: "array", - items: { - type: "string", - }, - }, - markdown: { - type: "object", - properties: { - mode: { - type: "string", - enum: ["native", "escape", "strip"], - }, - tableMode: { - type: "string", - enum: ["native", "ascii", "simple"], - }, - }, - additionalProperties: false, - }, - configWrites: { - type: "boolean", - }, - dmPolicy: { - default: "pairing", - type: "string", - enum: ["open", "pairing", "allowlist"], - }, - allowFrom: { - type: "array", - items: { - anyOf: [ - { - type: "string", - }, - { - type: "number", - }, - ], - }, - }, - groupPolicy: { - default: "allowlist", - anyOf: [ - { - type: "string", - enum: ["open", "allowlist", "disabled"], - }, - {}, - ], - }, - groupAllowFrom: { - type: "array", - items: { - anyOf: [ - { - type: "string", - }, - { - type: "number", - }, - ], - }, - }, - groupSenderAllowFrom: { - type: "array", - items: { - anyOf: [ - { - type: "string", - }, - { - type: "number", - }, - ], - }, - }, - requireMention: { - type: "boolean", - }, - groups: { - type: "object", - propertyNames: { - type: "string", - }, - additionalProperties: { - type: "object", - properties: { - requireMention: { - type: "boolean", - }, - tools: { - type: "object", - properties: { - allow: { - type: "array", - items: { - type: "string", - }, - }, - deny: { - type: "array", - items: { - type: "string", - }, - }, - }, - additionalProperties: false, - }, - skills: { - type: "array", - items: { - type: "string", - }, - }, - enabled: { - type: "boolean", - }, - allowFrom: { - type: "array", - items: { - anyOf: [ - { - type: "string", - }, - { - type: "number", - }, - ], - }, - }, - systemPrompt: { - type: "string", - }, - groupSessionScope: { - type: "string", - enum: ["group", "group_sender", "group_topic", "group_topic_sender"], - }, - topicSessionMode: { - type: "string", - enum: ["disabled", "enabled"], - }, - replyInThread: { - type: "string", - enum: ["disabled", "enabled"], - }, - }, - additionalProperties: false, - }, - }, - historyLimit: { - type: "integer", - minimum: 0, - maximum: 9007199254740991, - }, - dmHistoryLimit: { - type: "integer", - minimum: 0, - maximum: 9007199254740991, - }, - dms: { - type: "object", - propertyNames: { - type: "string", - }, - additionalProperties: { - type: "object", - properties: { - enabled: { - type: "boolean", - }, - systemPrompt: { - type: "string", - }, - }, - additionalProperties: false, - }, - }, - textChunkLimit: { - type: "integer", - exclusiveMinimum: 0, - maximum: 9007199254740991, - }, - chunkMode: { - type: "string", - enum: ["length", "newline"], - }, - blockStreamingCoalesce: { - type: "object", - properties: { - enabled: { - type: "boolean", - }, - minDelayMs: { - type: "integer", - exclusiveMinimum: 0, - maximum: 9007199254740991, - }, - maxDelayMs: { - type: "integer", - exclusiveMinimum: 0, - maximum: 9007199254740991, - }, - }, - additionalProperties: false, - }, - mediaMaxMb: { - type: "number", - exclusiveMinimum: 0, - }, - httpTimeoutMs: { - type: "integer", - exclusiveMinimum: 0, - maximum: 300000, - }, - heartbeat: { - type: "object", - properties: { - visibility: { - type: "string", - enum: ["visible", "hidden"], - }, - intervalMs: { - type: "integer", - exclusiveMinimum: 0, - maximum: 9007199254740991, - }, - }, - additionalProperties: false, - }, - renderMode: { - type: "string", - enum: ["auto", "raw", "card"], - }, - streaming: { - type: "boolean", - }, - tools: { - type: "object", - properties: { - doc: { - type: "boolean", - }, - chat: { - type: "boolean", - }, - wiki: { - type: "boolean", - }, - drive: { - type: "boolean", - }, - perm: { - type: "boolean", - }, - scopes: { - type: "boolean", - }, - }, - additionalProperties: false, - }, - actions: { - type: "object", - properties: { - reactions: { - type: "boolean", - }, - }, - additionalProperties: false, - }, - replyInThread: { - type: "string", - enum: ["disabled", "enabled"], - }, - reactionNotifications: { - default: "own", - type: "string", - enum: ["off", "own", "all"], - }, - typingIndicator: { - default: true, - type: "boolean", - }, - resolveSenderNames: { - default: true, - type: "boolean", - }, - groupSessionScope: { - type: "string", - enum: ["group", "group_sender", "group_topic", "group_topic_sender"], - }, - topicSessionMode: { - type: "string", - enum: ["disabled", "enabled"], - }, - dynamicAgentCreation: { - type: "object", - properties: { - enabled: { - type: "boolean", - }, - workspaceTemplate: { - type: "string", - }, - agentDirTemplate: { - type: "string", - }, - maxAgents: { - type: "integer", - exclusiveMinimum: 0, - maximum: 9007199254740991, - }, - }, - additionalProperties: false, - }, - accounts: { - type: "object", - propertyNames: { - type: "string", - }, - additionalProperties: { - type: "object", - properties: { - enabled: { - type: "boolean", - }, - name: { - type: "string", - }, - appId: { - type: "string", - }, - appSecret: { - anyOf: [ - { - type: "string", - }, - { - oneOf: [ - { - type: "object", - properties: { - source: { - type: "string", - const: "env", - }, - provider: { - type: "string", - pattern: "^[a-z][a-z0-9_-]{0,63}$", - }, - id: { - type: "string", - pattern: "^[A-Z][A-Z0-9_]{0,127}$", - }, - }, - required: ["source", "provider", "id"], - additionalProperties: false, - }, - { - type: "object", - properties: { - source: { - type: "string", - const: "file", - }, - provider: { - type: "string", - pattern: "^[a-z][a-z0-9_-]{0,63}$", - }, - id: { - type: "string", - }, - }, - required: ["source", "provider", "id"], - additionalProperties: false, - }, - { - type: "object", - properties: { - source: { - type: "string", - const: "exec", - }, - provider: { - type: "string", - pattern: "^[a-z][a-z0-9_-]{0,63}$", - }, - id: { - type: "string", - }, - }, - required: ["source", "provider", "id"], - additionalProperties: false, - }, - ], - }, - ], - }, - encryptKey: { - anyOf: [ - { - type: "string", - }, - { - oneOf: [ - { - type: "object", - properties: { - source: { - type: "string", - const: "env", - }, - provider: { - type: "string", - pattern: "^[a-z][a-z0-9_-]{0,63}$", - }, - id: { - type: "string", - pattern: "^[A-Z][A-Z0-9_]{0,127}$", - }, - }, - required: ["source", "provider", "id"], - additionalProperties: false, - }, - { - type: "object", - properties: { - source: { - type: "string", - const: "file", - }, - provider: { - type: "string", - pattern: "^[a-z][a-z0-9_-]{0,63}$", - }, - id: { - type: "string", - }, - }, - required: ["source", "provider", "id"], - additionalProperties: false, - }, - { - type: "object", - properties: { - source: { - type: "string", - const: "exec", - }, - provider: { - type: "string", - pattern: "^[a-z][a-z0-9_-]{0,63}$", - }, - id: { - type: "string", - }, - }, - required: ["source", "provider", "id"], - additionalProperties: false, - }, - ], - }, - ], - }, - verificationToken: { - anyOf: [ - { - type: "string", - }, - { - oneOf: [ - { - type: "object", - properties: { - source: { - type: "string", - const: "env", - }, - provider: { - type: "string", - pattern: "^[a-z][a-z0-9_-]{0,63}$", - }, - id: { - type: "string", - pattern: "^[A-Z][A-Z0-9_]{0,127}$", - }, - }, - required: ["source", "provider", "id"], - additionalProperties: false, - }, - { - type: "object", - properties: { - source: { - type: "string", - const: "file", - }, - provider: { - type: "string", - pattern: "^[a-z][a-z0-9_-]{0,63}$", - }, - id: { - type: "string", - }, - }, - required: ["source", "provider", "id"], - additionalProperties: false, - }, - { - type: "object", - properties: { - source: { - type: "string", - const: "exec", - }, - provider: { - type: "string", - pattern: "^[a-z][a-z0-9_-]{0,63}$", - }, - id: { - type: "string", - }, - }, - required: ["source", "provider", "id"], - additionalProperties: false, - }, - ], - }, - ], - }, - domain: { - anyOf: [ - { - type: "string", - enum: ["feishu", "lark"], - }, - { - type: "string", - format: "uri", - pattern: "^https:\\/\\/.*", - }, - ], - }, - connectionMode: { - type: "string", - enum: ["websocket", "webhook"], - }, - webhookPath: { - type: "string", - }, - webhookHost: { - type: "string", - }, - webhookPort: { - type: "integer", - exclusiveMinimum: 0, - maximum: 9007199254740991, - }, - capabilities: { - type: "array", - items: { - type: "string", - }, - }, - markdown: { - type: "object", - properties: { - mode: { - type: "string", - enum: ["native", "escape", "strip"], - }, - tableMode: { - type: "string", - enum: ["native", "ascii", "simple"], - }, - }, - additionalProperties: false, - }, - configWrites: { - type: "boolean", - }, - dmPolicy: { - type: "string", - enum: ["open", "pairing", "allowlist"], - }, - allowFrom: { - type: "array", - items: { - anyOf: [ - { - type: "string", - }, - { - type: "number", - }, - ], - }, - }, - groupPolicy: { - anyOf: [ - { - type: "string", - enum: ["open", "allowlist", "disabled"], - }, - {}, - ], - }, - groupAllowFrom: { - type: "array", - items: { - anyOf: [ - { - type: "string", - }, - { - type: "number", - }, - ], - }, - }, - groupSenderAllowFrom: { - type: "array", - items: { - anyOf: [ - { - type: "string", - }, - { - type: "number", - }, - ], - }, - }, - requireMention: { - type: "boolean", - }, - groups: { - type: "object", - propertyNames: { - type: "string", - }, - additionalProperties: { - type: "object", - properties: { - requireMention: { - type: "boolean", - }, - tools: { - type: "object", - properties: { - allow: { - type: "array", - items: { - type: "string", - }, - }, - deny: { - type: "array", - items: { - type: "string", - }, - }, - }, - additionalProperties: false, - }, - skills: { - type: "array", - items: { - type: "string", - }, - }, - enabled: { - type: "boolean", - }, - allowFrom: { - type: "array", - items: { - anyOf: [ - { - type: "string", - }, - { - type: "number", - }, - ], - }, - }, - systemPrompt: { - type: "string", - }, - groupSessionScope: { - type: "string", - enum: ["group", "group_sender", "group_topic", "group_topic_sender"], - }, - topicSessionMode: { - type: "string", - enum: ["disabled", "enabled"], - }, - replyInThread: { - type: "string", - enum: ["disabled", "enabled"], - }, - }, - additionalProperties: false, - }, - }, - historyLimit: { - type: "integer", - minimum: 0, - maximum: 9007199254740991, - }, - dmHistoryLimit: { - type: "integer", - minimum: 0, - maximum: 9007199254740991, - }, - dms: { - type: "object", - propertyNames: { - type: "string", - }, - additionalProperties: { - type: "object", - properties: { - enabled: { - type: "boolean", - }, - systemPrompt: { - type: "string", - }, - }, - additionalProperties: false, - }, - }, - textChunkLimit: { - type: "integer", - exclusiveMinimum: 0, - maximum: 9007199254740991, - }, - chunkMode: { - type: "string", - enum: ["length", "newline"], - }, - blockStreamingCoalesce: { - type: "object", - properties: { - enabled: { - type: "boolean", - }, - minDelayMs: { - type: "integer", - exclusiveMinimum: 0, - maximum: 9007199254740991, - }, - maxDelayMs: { - type: "integer", - exclusiveMinimum: 0, - maximum: 9007199254740991, - }, - }, - additionalProperties: false, - }, - mediaMaxMb: { - type: "number", - exclusiveMinimum: 0, - }, - httpTimeoutMs: { - type: "integer", - exclusiveMinimum: 0, - maximum: 300000, - }, - heartbeat: { - type: "object", - properties: { - visibility: { - type: "string", - enum: ["visible", "hidden"], - }, - intervalMs: { - type: "integer", - exclusiveMinimum: 0, - maximum: 9007199254740991, - }, - }, - additionalProperties: false, - }, - renderMode: { - type: "string", - enum: ["auto", "raw", "card"], - }, - streaming: { - type: "boolean", - }, - tools: { - type: "object", - properties: { - doc: { - type: "boolean", - }, - chat: { - type: "boolean", - }, - wiki: { - type: "boolean", - }, - drive: { - type: "boolean", - }, - perm: { - type: "boolean", - }, - scopes: { - type: "boolean", - }, - }, - additionalProperties: false, - }, - actions: { - type: "object", - properties: { - reactions: { - type: "boolean", - }, - }, - additionalProperties: false, - }, - replyInThread: { - type: "string", - enum: ["disabled", "enabled"], - }, - reactionNotifications: { - type: "string", - enum: ["off", "own", "all"], - }, - typingIndicator: { - type: "boolean", - }, - resolveSenderNames: { - type: "boolean", - }, - groupSessionScope: { - type: "string", - enum: ["group", "group_sender", "group_topic", "group_topic_sender"], - }, - topicSessionMode: { - type: "string", - enum: ["disabled", "enabled"], - }, - }, - additionalProperties: false, - }, - }, - }, - required: [ - "domain", - "connectionMode", - "webhookPath", - "dmPolicy", - "groupPolicy", - "reactionNotifications", - "typingIndicator", - "resolveSenderNames", - ], - additionalProperties: false, - }, - }, - { - pluginId: "googlechat", - channelId: "googlechat", - label: "Google Chat", - description: "Google Workspace Chat app via HTTP webhooks.", - schema: { - $schema: "http://json-schema.org/draft-07/schema#", - type: "object", - properties: { - name: { - type: "string", - }, - capabilities: { - type: "array", - items: { - type: "string", - }, - }, - enabled: { - type: "boolean", - }, - configWrites: { - type: "boolean", - }, - allowBots: { - type: "boolean", - }, - dangerouslyAllowNameMatching: { - type: "boolean", - }, - requireMention: { - type: "boolean", - }, - groupPolicy: { - default: "allowlist", - type: "string", - enum: ["open", "disabled", "allowlist"], - }, - groupAllowFrom: { - type: "array", - items: { - anyOf: [ - { - type: "string", - }, - { - type: "number", - }, - ], - }, - }, - groups: { - type: "object", - propertyNames: { - type: "string", - }, - additionalProperties: { - type: "object", - properties: { - enabled: { - type: "boolean", - }, - allow: { - type: "boolean", - }, - requireMention: { - type: "boolean", - }, - users: { - type: "array", - items: { - anyOf: [ - { - type: "string", - }, - { - type: "number", - }, - ], - }, - }, - systemPrompt: { - type: "string", - }, - }, - additionalProperties: false, - }, - }, - defaultTo: { - type: "string", - }, - serviceAccount: { - anyOf: [ - { - type: "string", - }, - { - type: "object", - propertyNames: { - type: "string", - }, - additionalProperties: {}, - }, - { - oneOf: [ - { - type: "object", - properties: { - source: { - type: "string", - const: "env", - }, - provider: { - type: "string", - pattern: "^[a-z][a-z0-9_-]{0,63}$", - }, - id: { - type: "string", - pattern: "^[A-Z][A-Z0-9_]{0,127}$", - }, - }, - required: ["source", "provider", "id"], - additionalProperties: false, - }, - { - type: "object", - properties: { - source: { - type: "string", - const: "file", - }, - provider: { - type: "string", - pattern: "^[a-z][a-z0-9_-]{0,63}$", - }, - id: { - type: "string", - }, - }, - required: ["source", "provider", "id"], - additionalProperties: false, - }, - { - type: "object", - properties: { - source: { - type: "string", - const: "exec", - }, - provider: { - type: "string", - pattern: "^[a-z][a-z0-9_-]{0,63}$", - }, - id: { - type: "string", - }, - }, - required: ["source", "provider", "id"], - additionalProperties: false, - }, - ], - }, - ], - }, - serviceAccountRef: { - oneOf: [ - { - type: "object", - properties: { - source: { - type: "string", - const: "env", - }, - provider: { - type: "string", - pattern: "^[a-z][a-z0-9_-]{0,63}$", - }, - id: { - type: "string", - pattern: "^[A-Z][A-Z0-9_]{0,127}$", - }, - }, - required: ["source", "provider", "id"], - additionalProperties: false, - }, - { - type: "object", - properties: { - source: { - type: "string", - const: "file", - }, - provider: { - type: "string", - pattern: "^[a-z][a-z0-9_-]{0,63}$", - }, - id: { - type: "string", - }, - }, - required: ["source", "provider", "id"], - additionalProperties: false, - }, - { - type: "object", - properties: { - source: { - type: "string", - const: "exec", - }, - provider: { - type: "string", - pattern: "^[a-z][a-z0-9_-]{0,63}$", - }, - id: { - type: "string", - }, - }, - required: ["source", "provider", "id"], - additionalProperties: false, - }, - ], - }, - serviceAccountFile: { - type: "string", - }, - audienceType: { - type: "string", - enum: ["app-url", "project-number"], - }, - audience: { - type: "string", - }, - appPrincipal: { - type: "string", - }, - webhookPath: { - type: "string", - }, - webhookUrl: { - type: "string", - }, - botUser: { - type: "string", - }, - historyLimit: { - type: "integer", - minimum: 0, - maximum: 9007199254740991, - }, - dmHistoryLimit: { - type: "integer", - minimum: 0, - maximum: 9007199254740991, - }, - dms: { - type: "object", - propertyNames: { - type: "string", - }, - additionalProperties: { - type: "object", - properties: { - historyLimit: { - type: "integer", - minimum: 0, - maximum: 9007199254740991, - }, - }, - additionalProperties: false, - }, - }, - textChunkLimit: { - type: "integer", - exclusiveMinimum: 0, - maximum: 9007199254740991, - }, - chunkMode: { - type: "string", - enum: ["length", "newline"], - }, - blockStreaming: { - type: "boolean", - }, - blockStreamingCoalesce: { - type: "object", - properties: { - minChars: { - type: "integer", - exclusiveMinimum: 0, - maximum: 9007199254740991, - }, - maxChars: { - type: "integer", - exclusiveMinimum: 0, - maximum: 9007199254740991, - }, - idleMs: { - type: "integer", - minimum: 0, - maximum: 9007199254740991, - }, - }, - additionalProperties: false, - }, - streamMode: { - default: "replace", - type: "string", - enum: ["replace", "status_final", "append"], - }, - mediaMaxMb: { - type: "number", - exclusiveMinimum: 0, - }, - replyToMode: { - anyOf: [ - { - type: "string", - const: "off", - }, - { - type: "string", - const: "first", - }, - { - type: "string", - const: "all", - }, - ], - }, - actions: { - type: "object", - properties: { - reactions: { - type: "boolean", - }, - }, - additionalProperties: false, - }, - dm: { - type: "object", - properties: { - enabled: { - type: "boolean", - }, - policy: { - default: "pairing", - type: "string", - enum: ["pairing", "allowlist", "open", "disabled"], - }, - allowFrom: { - type: "array", - items: { - anyOf: [ - { - type: "string", - }, - { - type: "number", - }, - ], - }, - }, - }, - required: ["policy"], - additionalProperties: false, - }, - healthMonitor: { - type: "object", - properties: { - enabled: { - type: "boolean", - }, - }, - additionalProperties: false, - }, - typingIndicator: { - type: "string", - enum: ["none", "message", "reaction"], - }, - responsePrefix: { - type: "string", - }, - accounts: { - type: "object", - propertyNames: { - type: "string", - }, - additionalProperties: { - type: "object", - properties: { - name: { - type: "string", - }, - capabilities: { - type: "array", - items: { - type: "string", - }, - }, - enabled: { - type: "boolean", - }, - configWrites: { - type: "boolean", - }, - allowBots: { - type: "boolean", - }, - dangerouslyAllowNameMatching: { - type: "boolean", - }, - requireMention: { - type: "boolean", - }, - groupPolicy: { - default: "allowlist", - type: "string", - enum: ["open", "disabled", "allowlist"], - }, - groupAllowFrom: { - type: "array", - items: { - anyOf: [ - { - type: "string", - }, - { - type: "number", - }, - ], - }, - }, - groups: { - type: "object", - propertyNames: { - type: "string", - }, - additionalProperties: { - type: "object", - properties: { - enabled: { - type: "boolean", - }, - allow: { - type: "boolean", - }, - requireMention: { - type: "boolean", - }, - users: { - type: "array", - items: { - anyOf: [ - { - type: "string", - }, - { - type: "number", - }, - ], - }, - }, - systemPrompt: { - type: "string", - }, - }, - additionalProperties: false, - }, - }, - defaultTo: { - type: "string", - }, - serviceAccount: { - anyOf: [ - { - type: "string", - }, - { - type: "object", - propertyNames: { - type: "string", - }, - additionalProperties: {}, - }, - { - oneOf: [ - { - type: "object", - properties: { - source: { - type: "string", - const: "env", - }, - provider: { - type: "string", - pattern: "^[a-z][a-z0-9_-]{0,63}$", - }, - id: { - type: "string", - pattern: "^[A-Z][A-Z0-9_]{0,127}$", - }, - }, - required: ["source", "provider", "id"], - additionalProperties: false, - }, - { - type: "object", - properties: { - source: { - type: "string", - const: "file", - }, - provider: { - type: "string", - pattern: "^[a-z][a-z0-9_-]{0,63}$", - }, - id: { - type: "string", - }, - }, - required: ["source", "provider", "id"], - additionalProperties: false, - }, - { - type: "object", - properties: { - source: { - type: "string", - const: "exec", - }, - provider: { - type: "string", - pattern: "^[a-z][a-z0-9_-]{0,63}$", - }, - id: { - type: "string", - }, - }, - required: ["source", "provider", "id"], - additionalProperties: false, - }, - ], - }, - ], - }, - serviceAccountRef: { - oneOf: [ - { - type: "object", - properties: { - source: { - type: "string", - const: "env", - }, - provider: { - type: "string", - pattern: "^[a-z][a-z0-9_-]{0,63}$", - }, - id: { - type: "string", - pattern: "^[A-Z][A-Z0-9_]{0,127}$", - }, - }, - required: ["source", "provider", "id"], - additionalProperties: false, - }, - { - type: "object", - properties: { - source: { - type: "string", - const: "file", - }, - provider: { - type: "string", - pattern: "^[a-z][a-z0-9_-]{0,63}$", - }, - id: { - type: "string", - }, - }, - required: ["source", "provider", "id"], - additionalProperties: false, - }, - { - type: "object", - properties: { - source: { - type: "string", - const: "exec", - }, - provider: { - type: "string", - pattern: "^[a-z][a-z0-9_-]{0,63}$", - }, - id: { - type: "string", - }, - }, - required: ["source", "provider", "id"], - additionalProperties: false, - }, - ], - }, - serviceAccountFile: { - type: "string", - }, - audienceType: { - type: "string", - enum: ["app-url", "project-number"], - }, - audience: { - type: "string", - }, - appPrincipal: { - type: "string", - }, - webhookPath: { - type: "string", - }, - webhookUrl: { - type: "string", - }, - botUser: { - type: "string", - }, - historyLimit: { - type: "integer", - minimum: 0, - maximum: 9007199254740991, - }, - dmHistoryLimit: { - type: "integer", - minimum: 0, - maximum: 9007199254740991, - }, - dms: { - type: "object", - propertyNames: { - type: "string", - }, - additionalProperties: { - type: "object", - properties: { - historyLimit: { - type: "integer", - minimum: 0, - maximum: 9007199254740991, - }, - }, - additionalProperties: false, - }, - }, - textChunkLimit: { - type: "integer", - exclusiveMinimum: 0, - maximum: 9007199254740991, - }, - chunkMode: { - type: "string", - enum: ["length", "newline"], - }, - blockStreaming: { - type: "boolean", - }, - blockStreamingCoalesce: { - type: "object", - properties: { - minChars: { - type: "integer", - exclusiveMinimum: 0, - maximum: 9007199254740991, - }, - maxChars: { - type: "integer", - exclusiveMinimum: 0, - maximum: 9007199254740991, - }, - idleMs: { - type: "integer", - minimum: 0, - maximum: 9007199254740991, - }, - }, - additionalProperties: false, - }, - streamMode: { - default: "replace", - type: "string", - enum: ["replace", "status_final", "append"], - }, - mediaMaxMb: { - type: "number", - exclusiveMinimum: 0, - }, - replyToMode: { - anyOf: [ - { - type: "string", - const: "off", - }, - { - type: "string", - const: "first", - }, - { - type: "string", - const: "all", - }, - ], - }, - actions: { - type: "object", - properties: { - reactions: { - type: "boolean", - }, - }, - additionalProperties: false, - }, - dm: { - type: "object", - properties: { - enabled: { - type: "boolean", - }, - policy: { - default: "pairing", - type: "string", - enum: ["pairing", "allowlist", "open", "disabled"], - }, - allowFrom: { - type: "array", - items: { - anyOf: [ - { - type: "string", - }, - { - type: "number", - }, - ], - }, - }, - }, - required: ["policy"], - additionalProperties: false, - }, - healthMonitor: { - type: "object", - properties: { - enabled: { - type: "boolean", - }, - }, - additionalProperties: false, - }, - typingIndicator: { - type: "string", - enum: ["none", "message", "reaction"], - }, - responsePrefix: { - type: "string", - }, - }, - required: ["groupPolicy", "streamMode"], - additionalProperties: false, - }, - }, - defaultAccount: { - type: "string", - }, - }, - required: ["groupPolicy", "streamMode"], - additionalProperties: false, - }, - }, - { - pluginId: "imessage", - channelId: "imessage", - label: "iMessage", - description: "this is still a work in progress.", - schema: { - $schema: "http://json-schema.org/draft-07/schema#", - type: "object", - properties: { - name: { - type: "string", - }, - capabilities: { - type: "array", - items: { - type: "string", - }, - }, - markdown: { - type: "object", - properties: { - tables: { - type: "string", - enum: ["off", "bullets", "code"], - }, - }, - additionalProperties: false, - }, - enabled: { - type: "boolean", - }, - configWrites: { - type: "boolean", - }, - cliPath: { - type: "string", - }, - dbPath: { - type: "string", - }, - remoteHost: { - type: "string", - }, - service: { - anyOf: [ - { - type: "string", - const: "imessage", - }, - { - type: "string", - const: "sms", - }, - { - type: "string", - const: "auto", - }, - ], - }, - region: { - type: "string", - }, - dmPolicy: { - default: "pairing", - type: "string", - enum: ["pairing", "allowlist", "open", "disabled"], - }, - allowFrom: { - type: "array", - items: { - anyOf: [ - { - type: "string", - }, - { - type: "number", - }, - ], - }, - }, - defaultTo: { - type: "string", - }, - groupAllowFrom: { - type: "array", - items: { - anyOf: [ - { - type: "string", - }, - { - type: "number", - }, - ], - }, - }, - groupPolicy: { - default: "allowlist", - type: "string", - enum: ["open", "disabled", "allowlist"], - }, - historyLimit: { - type: "integer", - minimum: 0, - maximum: 9007199254740991, - }, - dmHistoryLimit: { - type: "integer", - minimum: 0, - maximum: 9007199254740991, - }, - dms: { - type: "object", - propertyNames: { - type: "string", - }, - additionalProperties: { - type: "object", - properties: { - historyLimit: { - type: "integer", - minimum: 0, - maximum: 9007199254740991, - }, - }, - additionalProperties: false, - }, - }, - includeAttachments: { - type: "boolean", - }, - attachmentRoots: { - type: "array", - items: { - type: "string", - }, - }, - remoteAttachmentRoots: { - type: "array", - items: { - type: "string", - }, - }, - mediaMaxMb: { - type: "integer", - exclusiveMinimum: 0, - maximum: 9007199254740991, - }, - textChunkLimit: { - type: "integer", - exclusiveMinimum: 0, - maximum: 9007199254740991, - }, - chunkMode: { - type: "string", - enum: ["length", "newline"], - }, - blockStreaming: { - type: "boolean", - }, - blockStreamingCoalesce: { - type: "object", - properties: { - minChars: { - type: "integer", - exclusiveMinimum: 0, - maximum: 9007199254740991, - }, - maxChars: { - type: "integer", - exclusiveMinimum: 0, - maximum: 9007199254740991, - }, - idleMs: { - type: "integer", - minimum: 0, - maximum: 9007199254740991, - }, - }, - additionalProperties: false, - }, - groups: { - type: "object", - propertyNames: { - type: "string", - }, - additionalProperties: { - type: "object", - properties: { - requireMention: { - type: "boolean", - }, - tools: { - type: "object", - properties: { - allow: { - type: "array", - items: { - type: "string", - }, - }, - alsoAllow: { - type: "array", - items: { - type: "string", - }, - }, - deny: { - type: "array", - items: { - type: "string", - }, - }, - }, - additionalProperties: false, - }, - toolsBySender: { - type: "object", - propertyNames: { - type: "string", - }, - additionalProperties: { - type: "object", - properties: { - allow: { - type: "array", - items: { - type: "string", - }, - }, - alsoAllow: { - type: "array", - items: { - type: "string", - }, - }, - deny: { - type: "array", - items: { - type: "string", - }, - }, - }, - additionalProperties: false, - }, - }, - }, - additionalProperties: false, - }, - }, - heartbeat: { - type: "object", - properties: { - showOk: { - type: "boolean", - }, - showAlerts: { - type: "boolean", - }, - useIndicator: { - type: "boolean", - }, - }, - additionalProperties: false, - }, - healthMonitor: { - type: "object", - properties: { - enabled: { - type: "boolean", - }, - }, - additionalProperties: false, - }, - responsePrefix: { - type: "string", - }, - accounts: { - type: "object", - propertyNames: { - type: "string", - }, - additionalProperties: { - type: "object", - properties: { - name: { - type: "string", - }, - capabilities: { - type: "array", - items: { - type: "string", - }, - }, - markdown: { - type: "object", - properties: { - tables: { - type: "string", - enum: ["off", "bullets", "code"], - }, - }, - additionalProperties: false, - }, - enabled: { - type: "boolean", - }, - configWrites: { - type: "boolean", - }, - cliPath: { - type: "string", - }, - dbPath: { - type: "string", - }, - remoteHost: { - type: "string", - }, - service: { - anyOf: [ - { - type: "string", - const: "imessage", - }, - { - type: "string", - const: "sms", - }, - { - type: "string", - const: "auto", - }, - ], - }, - region: { - type: "string", - }, - dmPolicy: { - default: "pairing", - type: "string", - enum: ["pairing", "allowlist", "open", "disabled"], - }, - allowFrom: { - type: "array", - items: { - anyOf: [ - { - type: "string", - }, - { - type: "number", - }, - ], - }, - }, - defaultTo: { - type: "string", - }, - groupAllowFrom: { - type: "array", - items: { - anyOf: [ - { - type: "string", - }, - { - type: "number", - }, - ], - }, - }, - groupPolicy: { - default: "allowlist", - type: "string", - enum: ["open", "disabled", "allowlist"], - }, - historyLimit: { - type: "integer", - minimum: 0, - maximum: 9007199254740991, - }, - dmHistoryLimit: { - type: "integer", - minimum: 0, - maximum: 9007199254740991, - }, - dms: { - type: "object", - propertyNames: { - type: "string", - }, - additionalProperties: { - type: "object", - properties: { - historyLimit: { - type: "integer", - minimum: 0, - maximum: 9007199254740991, - }, - }, - additionalProperties: false, - }, - }, - includeAttachments: { - type: "boolean", - }, - attachmentRoots: { - type: "array", - items: { - type: "string", - }, - }, - remoteAttachmentRoots: { - type: "array", - items: { - type: "string", - }, - }, - mediaMaxMb: { - type: "integer", - exclusiveMinimum: 0, - maximum: 9007199254740991, - }, - textChunkLimit: { - type: "integer", - exclusiveMinimum: 0, - maximum: 9007199254740991, - }, - chunkMode: { - type: "string", - enum: ["length", "newline"], - }, - blockStreaming: { - type: "boolean", - }, - blockStreamingCoalesce: { - type: "object", - properties: { - minChars: { - type: "integer", - exclusiveMinimum: 0, - maximum: 9007199254740991, - }, - maxChars: { - type: "integer", - exclusiveMinimum: 0, - maximum: 9007199254740991, - }, - idleMs: { - type: "integer", - minimum: 0, - maximum: 9007199254740991, - }, - }, - additionalProperties: false, - }, - groups: { - type: "object", - propertyNames: { - type: "string", - }, - additionalProperties: { - type: "object", - properties: { - requireMention: { - type: "boolean", - }, - tools: { - type: "object", - properties: { - allow: { - type: "array", - items: { - type: "string", - }, - }, - alsoAllow: { - type: "array", - items: { - type: "string", - }, - }, - deny: { - type: "array", - items: { - type: "string", - }, - }, - }, - additionalProperties: false, - }, - toolsBySender: { - type: "object", - propertyNames: { - type: "string", - }, - additionalProperties: { - type: "object", - properties: { - allow: { - type: "array", - items: { - type: "string", - }, - }, - alsoAllow: { - type: "array", - items: { - type: "string", - }, - }, - deny: { - type: "array", - items: { - type: "string", - }, - }, - }, - additionalProperties: false, - }, - }, - }, - additionalProperties: false, - }, - }, - heartbeat: { - type: "object", - properties: { - showOk: { - type: "boolean", - }, - showAlerts: { - type: "boolean", - }, - useIndicator: { - type: "boolean", - }, - }, - additionalProperties: false, - }, - healthMonitor: { - type: "object", - properties: { - enabled: { - type: "boolean", - }, - }, - additionalProperties: false, - }, - responsePrefix: { - type: "string", - }, - }, - required: ["dmPolicy", "groupPolicy"], - additionalProperties: false, - }, - }, - defaultAccount: { - type: "string", - }, - }, - required: ["dmPolicy", "groupPolicy"], - additionalProperties: false, - }, - uiHints: { - "": { - label: "iMessage", - help: "iMessage channel provider configuration for CLI integration and DM access policy handling. Use explicit CLI paths when runtime environments have non-standard binary locations.", - }, - dmPolicy: { - label: "iMessage DM Policy", - help: 'Direct message access control ("pairing" recommended). "open" requires channels.imessage.allowFrom=["*"].', - }, - configWrites: { - label: "iMessage Config Writes", - help: "Allow iMessage to write config in response to channel events/commands (default: true).", - }, - cliPath: { - label: "iMessage CLI Path", - help: "Filesystem path to the iMessage bridge CLI binary used for send/receive operations. Set explicitly when the binary is not on PATH in service runtime environments.", - }, - }, - }, - { - pluginId: "irc", - channelId: "irc", - label: "IRC", - description: "classic IRC networks with DM/channel routing and pairing controls.", - schema: { - $schema: "http://json-schema.org/draft-07/schema#", - type: "object", - properties: { - name: { - type: "string", - }, - enabled: { - type: "boolean", - }, - dangerouslyAllowNameMatching: { - type: "boolean", - }, - host: { - type: "string", - }, - port: { - type: "integer", - minimum: 1, - maximum: 65535, - }, - tls: { - type: "boolean", - }, - nick: { - type: "string", - }, - username: { - type: "string", - }, - realname: { - type: "string", - }, - password: { - type: "string", - }, - passwordFile: { - type: "string", - }, - nickserv: { - type: "object", - properties: { - enabled: { - type: "boolean", - }, - service: { - type: "string", - }, - password: { - type: "string", - }, - passwordFile: { - type: "string", - }, - register: { - type: "boolean", - }, - registerEmail: { - type: "string", - }, - }, - additionalProperties: false, - }, - dmPolicy: { - default: "pairing", - type: "string", - enum: ["pairing", "allowlist", "open", "disabled"], - }, - allowFrom: { - type: "array", - items: { - anyOf: [ - { - type: "string", - }, - { - type: "number", - }, - ], - }, - }, - groupPolicy: { - default: "allowlist", - type: "string", - enum: ["open", "disabled", "allowlist"], - }, - groupAllowFrom: { - type: "array", - items: { - anyOf: [ - { - type: "string", - }, - { - type: "number", - }, - ], - }, - }, - groups: { - type: "object", - propertyNames: { - type: "string", - }, - additionalProperties: { - type: "object", - properties: { - requireMention: { - type: "boolean", - }, - tools: { - type: "object", - properties: { - allow: { - type: "array", - items: { - type: "string", - }, - }, - alsoAllow: { - type: "array", - items: { - type: "string", - }, - }, - deny: { - type: "array", - items: { - type: "string", - }, - }, - }, - additionalProperties: false, - }, - toolsBySender: { - type: "object", - propertyNames: { - type: "string", - }, - additionalProperties: { - type: "object", - properties: { - allow: { - type: "array", - items: { - type: "string", - }, - }, - alsoAllow: { - type: "array", - items: { - type: "string", - }, - }, - deny: { - type: "array", - items: { - type: "string", - }, - }, - }, - additionalProperties: false, - }, - }, - skills: { - type: "array", - items: { - type: "string", - }, - }, - enabled: { - type: "boolean", - }, - allowFrom: { - type: "array", - items: { - anyOf: [ - { - type: "string", - }, - { - type: "number", - }, - ], - }, - }, - systemPrompt: { - type: "string", - }, - }, - additionalProperties: false, - }, - }, - channels: { - type: "array", - items: { - type: "string", - }, - }, - mentionPatterns: { - type: "array", - items: { - type: "string", - }, - }, - markdown: { - type: "object", - properties: { - tables: { - type: "string", - enum: ["off", "bullets", "code"], - }, - }, - additionalProperties: false, - }, - historyLimit: { - type: "integer", - minimum: 0, - maximum: 9007199254740991, - }, - dmHistoryLimit: { - type: "integer", - minimum: 0, - maximum: 9007199254740991, - }, - dms: { - type: "object", - propertyNames: { - type: "string", - }, - additionalProperties: { - type: "object", - properties: { - historyLimit: { - type: "integer", - minimum: 0, - maximum: 9007199254740991, - }, - }, - additionalProperties: false, - }, - }, - textChunkLimit: { - type: "integer", - exclusiveMinimum: 0, - maximum: 9007199254740991, - }, - chunkMode: { - type: "string", - enum: ["length", "newline"], - }, - blockStreaming: { - type: "boolean", - }, - blockStreamingCoalesce: { - type: "object", - properties: { - minChars: { - type: "integer", - exclusiveMinimum: 0, - maximum: 9007199254740991, - }, - maxChars: { - type: "integer", - exclusiveMinimum: 0, - maximum: 9007199254740991, - }, - idleMs: { - type: "integer", - minimum: 0, - maximum: 9007199254740991, - }, - }, - additionalProperties: false, - }, - responsePrefix: { - type: "string", - }, - mediaMaxMb: { - type: "number", - exclusiveMinimum: 0, - }, - accounts: { - type: "object", - propertyNames: { - type: "string", - }, - additionalProperties: { - type: "object", - properties: { - name: { - type: "string", - }, - enabled: { - type: "boolean", - }, - dangerouslyAllowNameMatching: { - type: "boolean", - }, - host: { - type: "string", - }, - port: { - type: "integer", - minimum: 1, - maximum: 65535, - }, - tls: { - type: "boolean", - }, - nick: { - type: "string", - }, - username: { - type: "string", - }, - realname: { - type: "string", - }, - password: { - type: "string", - }, - passwordFile: { - type: "string", - }, - nickserv: { - type: "object", - properties: { - enabled: { - type: "boolean", - }, - service: { - type: "string", - }, - password: { - type: "string", - }, - passwordFile: { - type: "string", - }, - register: { - type: "boolean", - }, - registerEmail: { - type: "string", - }, - }, - additionalProperties: false, - }, - dmPolicy: { - default: "pairing", - type: "string", - enum: ["pairing", "allowlist", "open", "disabled"], - }, - allowFrom: { - type: "array", - items: { - anyOf: [ - { - type: "string", - }, - { - type: "number", - }, - ], - }, - }, - groupPolicy: { - default: "allowlist", - type: "string", - enum: ["open", "disabled", "allowlist"], - }, - groupAllowFrom: { - type: "array", - items: { - anyOf: [ - { - type: "string", - }, - { - type: "number", - }, - ], - }, - }, - groups: { - type: "object", - propertyNames: { - type: "string", - }, - additionalProperties: { - type: "object", - properties: { - requireMention: { - type: "boolean", - }, - tools: { - type: "object", - properties: { - allow: { - type: "array", - items: { - type: "string", - }, - }, - alsoAllow: { - type: "array", - items: { - type: "string", - }, - }, - deny: { - type: "array", - items: { - type: "string", - }, - }, - }, - additionalProperties: false, - }, - toolsBySender: { - type: "object", - propertyNames: { - type: "string", - }, - additionalProperties: { - type: "object", - properties: { - allow: { - type: "array", - items: { - type: "string", - }, - }, - alsoAllow: { - type: "array", - items: { - type: "string", - }, - }, - deny: { - type: "array", - items: { - type: "string", - }, - }, - }, - additionalProperties: false, - }, - }, - skills: { - type: "array", - items: { - type: "string", - }, - }, - enabled: { - type: "boolean", - }, - allowFrom: { - type: "array", - items: { - anyOf: [ - { - type: "string", - }, - { - type: "number", - }, - ], - }, - }, - systemPrompt: { - type: "string", - }, - }, - additionalProperties: false, - }, - }, - channels: { - type: "array", - items: { - type: "string", - }, - }, - mentionPatterns: { - type: "array", - items: { - type: "string", - }, - }, - markdown: { - type: "object", - properties: { - tables: { - type: "string", - enum: ["off", "bullets", "code"], - }, - }, - additionalProperties: false, - }, - historyLimit: { - type: "integer", - minimum: 0, - maximum: 9007199254740991, - }, - dmHistoryLimit: { - type: "integer", - minimum: 0, - maximum: 9007199254740991, - }, - dms: { - type: "object", - propertyNames: { - type: "string", - }, - additionalProperties: { - type: "object", - properties: { - historyLimit: { - type: "integer", - minimum: 0, - maximum: 9007199254740991, - }, - }, - additionalProperties: false, - }, - }, - textChunkLimit: { - type: "integer", - exclusiveMinimum: 0, - maximum: 9007199254740991, - }, - chunkMode: { - type: "string", - enum: ["length", "newline"], - }, - blockStreaming: { - type: "boolean", - }, - blockStreamingCoalesce: { - type: "object", - properties: { - minChars: { - type: "integer", - exclusiveMinimum: 0, - maximum: 9007199254740991, - }, - maxChars: { - type: "integer", - exclusiveMinimum: 0, - maximum: 9007199254740991, - }, - idleMs: { - type: "integer", - minimum: 0, - maximum: 9007199254740991, - }, - }, - additionalProperties: false, - }, - responsePrefix: { - type: "string", - }, - mediaMaxMb: { - type: "number", - exclusiveMinimum: 0, - }, - }, - required: ["dmPolicy", "groupPolicy"], - additionalProperties: false, - }, - }, - defaultAccount: { - type: "string", - }, - }, - required: ["dmPolicy", "groupPolicy"], - additionalProperties: false, - }, - uiHints: { - "": { - label: "IRC", - help: "IRC channel provider configuration and compatibility settings for classic IRC transport workflows. Use this section when bridging legacy chat infrastructure into OpenClaw.", - }, - dmPolicy: { - label: "IRC DM Policy", - help: 'Direct message access control ("pairing" recommended). "open" requires channels.irc.allowFrom=["*"].', - }, - "nickserv.enabled": { - label: "IRC NickServ Enabled", - help: "Enable NickServ identify/register after connect (defaults to enabled when password is configured).", - }, - "nickserv.service": { - label: "IRC NickServ Service", - help: "NickServ service nick (default: NickServ).", - }, - "nickserv.password": { - label: "IRC NickServ Password", - help: "NickServ password used for IDENTIFY/REGISTER (sensitive).", - }, - "nickserv.passwordFile": { - label: "IRC NickServ Password File", - help: "Optional file path containing NickServ password.", - }, - "nickserv.register": { - label: "IRC NickServ Register", - help: "If true, send NickServ REGISTER on every connect. Use once for initial registration, then disable.", - }, - "nickserv.registerEmail": { - label: "IRC NickServ Register Email", - help: "Email used with NickServ REGISTER (required when register=true).", - }, - configWrites: { - label: "IRC Config Writes", - help: "Allow IRC to write config in response to channel events/commands (default: true).", - }, - }, - }, - { - pluginId: "line", - channelId: "line", - label: "LINE", - description: "LINE Messaging API bot for Japan/Taiwan/Thailand markets.", - schema: { - $schema: "http://json-schema.org/draft-07/schema#", - type: "object", - properties: { - enabled: { - type: "boolean", - }, - channelAccessToken: { - type: "string", - }, - channelSecret: { - type: "string", - }, - tokenFile: { - type: "string", - }, - secretFile: { - type: "string", - }, - name: { - type: "string", - }, - allowFrom: { - type: "array", - items: { - anyOf: [ - { - type: "string", - }, - { - type: "number", - }, - ], - }, - }, - groupAllowFrom: { - type: "array", - items: { - anyOf: [ - { - type: "string", - }, - { - type: "number", - }, - ], - }, - }, - dmPolicy: { - default: "pairing", - type: "string", - enum: ["open", "allowlist", "pairing", "disabled"], - }, - groupPolicy: { - default: "allowlist", - type: "string", - enum: ["open", "allowlist", "disabled"], - }, - responsePrefix: { - type: "string", - }, - mediaMaxMb: { - type: "number", - }, - webhookPath: { - type: "string", - }, - accounts: { - type: "object", - propertyNames: { - type: "string", - }, - additionalProperties: { - type: "object", - properties: { - enabled: { - type: "boolean", - }, - channelAccessToken: { - type: "string", - }, - channelSecret: { - type: "string", - }, - tokenFile: { - type: "string", - }, - secretFile: { - type: "string", - }, - name: { - type: "string", - }, - allowFrom: { - type: "array", - items: { - anyOf: [ - { - type: "string", - }, - { - type: "number", - }, - ], - }, - }, - groupAllowFrom: { - type: "array", - items: { - anyOf: [ - { - type: "string", - }, - { - type: "number", - }, - ], - }, - }, - dmPolicy: { - default: "pairing", - type: "string", - enum: ["open", "allowlist", "pairing", "disabled"], - }, - groupPolicy: { - default: "allowlist", - type: "string", - enum: ["open", "allowlist", "disabled"], - }, - responsePrefix: { - type: "string", - }, - mediaMaxMb: { - type: "number", - }, - webhookPath: { - type: "string", - }, - groups: { - type: "object", - propertyNames: { - type: "string", - }, - additionalProperties: { - type: "object", - properties: { - enabled: { - type: "boolean", - }, - allowFrom: { - type: "array", - items: { - anyOf: [ - { - type: "string", - }, - { - type: "number", - }, - ], - }, - }, - requireMention: { - type: "boolean", - }, - systemPrompt: { - type: "string", - }, - skills: { - type: "array", - items: { - type: "string", - }, - }, - }, - additionalProperties: false, - }, - }, - }, - required: ["dmPolicy", "groupPolicy"], - additionalProperties: false, - }, - }, - defaultAccount: { - type: "string", - }, - groups: { - type: "object", - propertyNames: { - type: "string", - }, - additionalProperties: { - type: "object", - properties: { - enabled: { - type: "boolean", - }, - allowFrom: { - type: "array", - items: { - anyOf: [ - { - type: "string", - }, - { - type: "number", - }, - ], - }, - }, - requireMention: { - type: "boolean", - }, - systemPrompt: { - type: "string", - }, - skills: { - type: "array", - items: { - type: "string", - }, - }, - }, - additionalProperties: false, - }, - }, - }, - required: ["dmPolicy", "groupPolicy"], - additionalProperties: false, - }, - }, - { - pluginId: "matrix", - channelId: "matrix", - label: "Matrix", - description: "open protocol; install the plugin to enable.", - schema: { - $schema: "http://json-schema.org/draft-07/schema#", - type: "object", - properties: { - name: { - type: "string", - }, - enabled: { - type: "boolean", - }, - defaultAccount: { - type: "string", - }, - accounts: { - type: "object", - propertyNames: { - type: "string", - }, - additionalProperties: {}, - }, - markdown: { - type: "object", - properties: { - tables: { - type: "string", - enum: ["off", "bullets", "code"], - }, - }, - additionalProperties: false, - }, - homeserver: { - type: "string", - }, - allowPrivateNetwork: { - type: "boolean", - }, - userId: { - type: "string", - }, - accessToken: { - type: "string", - }, - password: { - anyOf: [ - { - type: "string", - }, - { - oneOf: [ - { - type: "object", - properties: { - source: { - type: "string", - const: "env", - }, - provider: { - type: "string", - pattern: "^[a-z][a-z0-9_-]{0,63}$", - }, - id: { - type: "string", - pattern: "^[A-Z][A-Z0-9_]{0,127}$", - }, - }, - required: ["source", "provider", "id"], - additionalProperties: false, - }, - { - type: "object", - properties: { - source: { - type: "string", - const: "file", - }, - provider: { - type: "string", - pattern: "^[a-z][a-z0-9_-]{0,63}$", - }, - id: { - type: "string", - }, - }, - required: ["source", "provider", "id"], - additionalProperties: false, - }, - { - type: "object", - properties: { - source: { - type: "string", - const: "exec", - }, - provider: { - type: "string", - pattern: "^[a-z][a-z0-9_-]{0,63}$", - }, - id: { - type: "string", - }, - }, - required: ["source", "provider", "id"], - additionalProperties: false, - }, - ], - }, - ], - }, - deviceId: { - type: "string", - }, - deviceName: { - type: "string", - }, - avatarUrl: { - type: "string", - }, - initialSyncLimit: { - type: "number", - }, - encryption: { - type: "boolean", - }, - allowlistOnly: { - type: "boolean", - }, - allowBots: { - anyOf: [ - { - type: "boolean", - }, - { - type: "string", - const: "mentions", - }, - ], - }, - groupPolicy: { - type: "string", - enum: ["open", "disabled", "allowlist"], - }, - replyToMode: { - type: "string", - enum: ["off", "first", "all"], - }, - threadReplies: { - type: "string", - enum: ["off", "inbound", "always"], - }, - textChunkLimit: { - type: "number", - }, - chunkMode: { - type: "string", - enum: ["length", "newline"], - }, - responsePrefix: { - type: "string", - }, - ackReaction: { - type: "string", - }, - ackReactionScope: { - type: "string", - enum: ["group-mentions", "group-all", "direct", "all", "none", "off"], - }, - reactionNotifications: { - type: "string", - enum: ["off", "own"], - }, - threadBindings: { - type: "object", - properties: { - enabled: { - type: "boolean", - }, - idleHours: { - type: "number", - minimum: 0, - }, - maxAgeHours: { - type: "number", - minimum: 0, - }, - spawnSubagentSessions: { - type: "boolean", - }, - spawnAcpSessions: { - type: "boolean", - }, - }, - additionalProperties: false, - }, - startupVerification: { - type: "string", - enum: ["off", "if-unverified"], - }, - startupVerificationCooldownHours: { - type: "number", - }, - mediaMaxMb: { - type: "number", - }, - autoJoin: { - type: "string", - enum: ["always", "allowlist", "off"], - }, - autoJoinAllowlist: { - type: "array", - items: { - anyOf: [ - { - type: "string", - }, - { - type: "number", - }, - ], - }, - }, - groupAllowFrom: { - type: "array", - items: { - anyOf: [ - { - type: "string", - }, - { - type: "number", - }, - ], - }, - }, - dm: { - type: "object", - properties: { - enabled: { - type: "boolean", - }, - policy: { - type: "string", - enum: ["pairing", "allowlist", "open", "disabled"], - }, - allowFrom: { - type: "array", - items: { - anyOf: [ - { - type: "string", - }, - { - type: "number", - }, - ], - }, - }, - }, - additionalProperties: false, - }, - groups: { - type: "object", - properties: {}, - additionalProperties: { - type: "object", - properties: { - enabled: { - type: "boolean", - }, - allow: { - type: "boolean", - }, - requireMention: { - type: "boolean", - }, - allowBots: { - anyOf: [ - { - type: "boolean", - }, - { - type: "string", - const: "mentions", - }, - ], - }, - tools: { - type: "object", - properties: { - allow: { - type: "array", - items: { - type: "string", - }, - }, - alsoAllow: { - type: "array", - items: { - type: "string", - }, - }, - deny: { - type: "array", - items: { - type: "string", - }, - }, - }, - additionalProperties: false, - }, - autoReply: { - type: "boolean", - }, - users: { - type: "array", - items: { - anyOf: [ - { - type: "string", - }, - { - type: "number", - }, - ], - }, - }, - skills: { - type: "array", - items: { - type: "string", - }, - }, - systemPrompt: { - type: "string", - }, - }, - additionalProperties: false, - }, - }, - rooms: { - type: "object", - properties: {}, - additionalProperties: { - type: "object", - properties: { - enabled: { - type: "boolean", - }, - allow: { - type: "boolean", - }, - requireMention: { - type: "boolean", - }, - allowBots: { - anyOf: [ - { - type: "boolean", - }, - { - type: "string", - const: "mentions", - }, - ], - }, - tools: { - type: "object", - properties: { - allow: { - type: "array", - items: { - type: "string", - }, - }, - alsoAllow: { - type: "array", - items: { - type: "string", - }, - }, - deny: { - type: "array", - items: { - type: "string", - }, - }, - }, - additionalProperties: false, - }, - autoReply: { - type: "boolean", - }, - users: { - type: "array", - items: { - anyOf: [ - { - type: "string", - }, - { - type: "number", - }, - ], - }, - }, - skills: { - type: "array", - items: { - type: "string", - }, - }, - systemPrompt: { - type: "string", - }, - }, - additionalProperties: false, - }, - }, - actions: { - type: "object", - properties: { - reactions: { - type: "boolean", - }, - messages: { - type: "boolean", - }, - pins: { - type: "boolean", - }, - profile: { - type: "boolean", - }, - memberInfo: { - type: "boolean", - }, - channelInfo: { - type: "boolean", - }, - verification: { - type: "boolean", - }, - }, - additionalProperties: false, - }, - }, - additionalProperties: false, - }, - }, - { - pluginId: "mattermost", - channelId: "mattermost", - label: "Mattermost", - description: "self-hosted Slack-style chat; install the plugin to enable.", - schema: { - $schema: "http://json-schema.org/draft-07/schema#", - type: "object", - properties: { - name: { - type: "string", - }, - capabilities: { - type: "array", - items: { - type: "string", - }, - }, - dangerouslyAllowNameMatching: { - type: "boolean", - }, - markdown: { - type: "object", - properties: { - tables: { - type: "string", - enum: ["off", "bullets", "code"], - }, - }, - additionalProperties: false, - }, - enabled: { - type: "boolean", - }, - configWrites: { - type: "boolean", - }, - botToken: { - anyOf: [ - { - type: "string", - }, - { - oneOf: [ - { - type: "object", - properties: { - source: { - type: "string", - const: "env", - }, - provider: { - type: "string", - pattern: "^[a-z][a-z0-9_-]{0,63}$", - }, - id: { - type: "string", - pattern: "^[A-Z][A-Z0-9_]{0,127}$", - }, - }, - required: ["source", "provider", "id"], - additionalProperties: false, - }, - { - type: "object", - properties: { - source: { - type: "string", - const: "file", - }, - provider: { - type: "string", - pattern: "^[a-z][a-z0-9_-]{0,63}$", - }, - id: { - type: "string", - }, - }, - required: ["source", "provider", "id"], - additionalProperties: false, - }, - { - type: "object", - properties: { - source: { - type: "string", - const: "exec", - }, - provider: { - type: "string", - pattern: "^[a-z][a-z0-9_-]{0,63}$", - }, - id: { - type: "string", - }, - }, - required: ["source", "provider", "id"], - additionalProperties: false, - }, - ], - }, - ], - }, - baseUrl: { - type: "string", - }, - chatmode: { - type: "string", - enum: ["oncall", "onmessage", "onchar"], - }, - oncharPrefixes: { - type: "array", - items: { - type: "string", - }, - }, - requireMention: { - type: "boolean", - }, - dmPolicy: { - default: "pairing", - type: "string", - enum: ["pairing", "allowlist", "open", "disabled"], - }, - allowFrom: { - type: "array", - items: { - anyOf: [ - { - type: "string", - }, - { - type: "number", - }, - ], - }, - }, - groupAllowFrom: { - type: "array", - items: { - anyOf: [ - { - type: "string", - }, - { - type: "number", - }, - ], - }, - }, - groupPolicy: { - default: "allowlist", - type: "string", - enum: ["open", "disabled", "allowlist"], - }, - textChunkLimit: { - type: "integer", - exclusiveMinimum: 0, - maximum: 9007199254740991, - }, - chunkMode: { - type: "string", - enum: ["length", "newline"], - }, - blockStreaming: { - type: "boolean", - }, - blockStreamingCoalesce: { - type: "object", - properties: { - minChars: { - type: "integer", - exclusiveMinimum: 0, - maximum: 9007199254740991, - }, - maxChars: { - type: "integer", - exclusiveMinimum: 0, - maximum: 9007199254740991, - }, - idleMs: { - type: "integer", - minimum: 0, - maximum: 9007199254740991, - }, - }, - additionalProperties: false, - }, - replyToMode: { - type: "string", - enum: ["off", "first", "all"], - }, - responsePrefix: { - type: "string", - }, - actions: { - type: "object", - properties: { - reactions: { - type: "boolean", - }, - }, - additionalProperties: false, - }, - commands: { - type: "object", - properties: { - native: { - anyOf: [ - { - type: "boolean", - }, - { - type: "string", - const: "auto", - }, - ], - }, - nativeSkills: { - anyOf: [ - { - type: "boolean", - }, - { - type: "string", - const: "auto", - }, - ], - }, - callbackPath: { - type: "string", - }, - callbackUrl: { - type: "string", - }, - }, - additionalProperties: false, - }, - interactions: { - type: "object", - properties: { - callbackBaseUrl: { - type: "string", - }, - allowedSourceIps: { - type: "array", - items: { - type: "string", - }, - }, - }, - additionalProperties: false, - }, - allowPrivateNetwork: { - type: "boolean", - }, - dmChannelRetry: { - type: "object", - properties: { - maxRetries: { - type: "integer", - minimum: 0, - maximum: 10, - }, - initialDelayMs: { - type: "integer", - minimum: 100, - maximum: 60000, - }, - maxDelayMs: { - type: "integer", - minimum: 1000, - maximum: 60000, - }, - timeoutMs: { - type: "integer", - minimum: 5000, - maximum: 120000, - }, - }, - additionalProperties: false, - }, - accounts: { - type: "object", - propertyNames: { - type: "string", - }, - additionalProperties: { - type: "object", - properties: { - name: { - type: "string", - }, - capabilities: { - type: "array", - items: { - type: "string", - }, - }, - dangerouslyAllowNameMatching: { - type: "boolean", - }, - markdown: { - type: "object", - properties: { - tables: { - type: "string", - enum: ["off", "bullets", "code"], - }, - }, - additionalProperties: false, - }, - enabled: { - type: "boolean", - }, - configWrites: { - type: "boolean", - }, - botToken: { - anyOf: [ - { - type: "string", - }, - { - oneOf: [ - { - type: "object", - properties: { - source: { - type: "string", - const: "env", - }, - provider: { - type: "string", - pattern: "^[a-z][a-z0-9_-]{0,63}$", - }, - id: { - type: "string", - pattern: "^[A-Z][A-Z0-9_]{0,127}$", - }, - }, - required: ["source", "provider", "id"], - additionalProperties: false, - }, - { - type: "object", - properties: { - source: { - type: "string", - const: "file", - }, - provider: { - type: "string", - pattern: "^[a-z][a-z0-9_-]{0,63}$", - }, - id: { - type: "string", - }, - }, - required: ["source", "provider", "id"], - additionalProperties: false, - }, - { - type: "object", - properties: { - source: { - type: "string", - const: "exec", - }, - provider: { - type: "string", - pattern: "^[a-z][a-z0-9_-]{0,63}$", - }, - id: { - type: "string", - }, - }, - required: ["source", "provider", "id"], - additionalProperties: false, - }, - ], - }, - ], - }, - baseUrl: { - type: "string", - }, - chatmode: { - type: "string", - enum: ["oncall", "onmessage", "onchar"], - }, - oncharPrefixes: { - type: "array", - items: { - type: "string", - }, - }, - requireMention: { - type: "boolean", - }, - dmPolicy: { - default: "pairing", - type: "string", - enum: ["pairing", "allowlist", "open", "disabled"], - }, - allowFrom: { - type: "array", - items: { - anyOf: [ - { - type: "string", - }, - { - type: "number", - }, - ], - }, - }, - groupAllowFrom: { - type: "array", - items: { - anyOf: [ - { - type: "string", - }, - { - type: "number", - }, - ], - }, - }, - groupPolicy: { - default: "allowlist", - type: "string", - enum: ["open", "disabled", "allowlist"], - }, - textChunkLimit: { - type: "integer", - exclusiveMinimum: 0, - maximum: 9007199254740991, - }, - chunkMode: { - type: "string", - enum: ["length", "newline"], - }, - blockStreaming: { - type: "boolean", - }, - blockStreamingCoalesce: { - type: "object", - properties: { - minChars: { - type: "integer", - exclusiveMinimum: 0, - maximum: 9007199254740991, - }, - maxChars: { - type: "integer", - exclusiveMinimum: 0, - maximum: 9007199254740991, - }, - idleMs: { - type: "integer", - minimum: 0, - maximum: 9007199254740991, - }, - }, - additionalProperties: false, - }, - replyToMode: { - type: "string", - enum: ["off", "first", "all"], - }, - responsePrefix: { - type: "string", - }, - actions: { - type: "object", - properties: { - reactions: { - type: "boolean", - }, - }, - additionalProperties: false, - }, - commands: { - type: "object", - properties: { - native: { - anyOf: [ - { - type: "boolean", - }, - { - type: "string", - const: "auto", - }, - ], - }, - nativeSkills: { - anyOf: [ - { - type: "boolean", - }, - { - type: "string", - const: "auto", - }, - ], - }, - callbackPath: { - type: "string", - }, - callbackUrl: { - type: "string", - }, - }, - additionalProperties: false, - }, - interactions: { - type: "object", - properties: { - callbackBaseUrl: { - type: "string", - }, - allowedSourceIps: { - type: "array", - items: { - type: "string", - }, - }, - }, - additionalProperties: false, - }, - allowPrivateNetwork: { - type: "boolean", - }, - dmChannelRetry: { - type: "object", - properties: { - maxRetries: { - type: "integer", - minimum: 0, - maximum: 10, - }, - initialDelayMs: { - type: "integer", - minimum: 100, - maximum: 60000, - }, - maxDelayMs: { - type: "integer", - minimum: 1000, - maximum: 60000, - }, - timeoutMs: { - type: "integer", - minimum: 5000, - maximum: 120000, - }, - }, - additionalProperties: false, - }, - }, - required: ["dmPolicy", "groupPolicy"], - additionalProperties: false, - }, - }, - defaultAccount: { - type: "string", - }, - }, - required: ["dmPolicy", "groupPolicy"], - additionalProperties: false, - }, - }, - { - pluginId: "msteams", - channelId: "msteams", - label: "Microsoft Teams", - description: "Teams SDK; enterprise support.", - schema: { - $schema: "http://json-schema.org/draft-07/schema#", - type: "object", - properties: { - enabled: { - type: "boolean", - }, - capabilities: { - type: "array", - items: { - type: "string", - }, - }, - dangerouslyAllowNameMatching: { - type: "boolean", - }, - markdown: { - type: "object", - properties: { - tables: { - type: "string", - enum: ["off", "bullets", "code"], - }, - }, - additionalProperties: false, - }, - configWrites: { - type: "boolean", - }, - appId: { - type: "string", - }, - appPassword: { - anyOf: [ - { - type: "string", - }, - { - oneOf: [ - { - type: "object", - properties: { - source: { - type: "string", - const: "env", - }, - provider: { - type: "string", - pattern: "^[a-z][a-z0-9_-]{0,63}$", - }, - id: { - type: "string", - pattern: "^[A-Z][A-Z0-9_]{0,127}$", - }, - }, - required: ["source", "provider", "id"], - additionalProperties: false, - }, - { - type: "object", - properties: { - source: { - type: "string", - const: "file", - }, - provider: { - type: "string", - pattern: "^[a-z][a-z0-9_-]{0,63}$", - }, - id: { - type: "string", - }, - }, - required: ["source", "provider", "id"], - additionalProperties: false, - }, - { - type: "object", - properties: { - source: { - type: "string", - const: "exec", - }, - provider: { - type: "string", - pattern: "^[a-z][a-z0-9_-]{0,63}$", - }, - id: { - type: "string", - }, - }, - required: ["source", "provider", "id"], - additionalProperties: false, - }, - ], - }, - ], - }, - tenantId: { - type: "string", - }, - webhook: { - type: "object", - properties: { - port: { - type: "integer", - exclusiveMinimum: 0, - maximum: 9007199254740991, - }, - path: { - type: "string", - }, - }, - additionalProperties: false, - }, - dmPolicy: { - default: "pairing", - type: "string", - enum: ["pairing", "allowlist", "open", "disabled"], - }, - allowFrom: { - type: "array", - items: { - type: "string", - }, - }, - defaultTo: { - type: "string", - }, - groupAllowFrom: { - type: "array", - items: { - type: "string", - }, - }, - groupPolicy: { - default: "allowlist", - type: "string", - enum: ["open", "disabled", "allowlist"], - }, - textChunkLimit: { - type: "integer", - exclusiveMinimum: 0, - maximum: 9007199254740991, - }, - chunkMode: { - type: "string", - enum: ["length", "newline"], - }, - blockStreamingCoalesce: { - type: "object", - properties: { - minChars: { - type: "integer", - exclusiveMinimum: 0, - maximum: 9007199254740991, - }, - maxChars: { - type: "integer", - exclusiveMinimum: 0, - maximum: 9007199254740991, - }, - idleMs: { - type: "integer", - minimum: 0, - maximum: 9007199254740991, - }, - }, - additionalProperties: false, - }, - mediaAllowHosts: { - type: "array", - items: { - type: "string", - }, - }, - mediaAuthAllowHosts: { - type: "array", - items: { - type: "string", - }, - }, - requireMention: { - type: "boolean", - }, - historyLimit: { - type: "integer", - minimum: 0, - maximum: 9007199254740991, - }, - dmHistoryLimit: { - type: "integer", - minimum: 0, - maximum: 9007199254740991, - }, - dms: { - type: "object", - propertyNames: { - type: "string", - }, - additionalProperties: { - type: "object", - properties: { - historyLimit: { - type: "integer", - minimum: 0, - maximum: 9007199254740991, - }, - }, - additionalProperties: false, - }, - }, - replyStyle: { - type: "string", - enum: ["thread", "top-level"], - }, - teams: { - type: "object", - propertyNames: { - type: "string", - }, - additionalProperties: { - type: "object", - properties: { - requireMention: { - type: "boolean", - }, - tools: { - type: "object", - properties: { - allow: { - type: "array", - items: { - type: "string", - }, - }, - alsoAllow: { - type: "array", - items: { - type: "string", - }, - }, - deny: { - type: "array", - items: { - type: "string", - }, - }, - }, - additionalProperties: false, - }, - toolsBySender: { - type: "object", - propertyNames: { - type: "string", - }, - additionalProperties: { - type: "object", - properties: { - allow: { - type: "array", - items: { - type: "string", - }, - }, - alsoAllow: { - type: "array", - items: { - type: "string", - }, - }, - deny: { - type: "array", - items: { - type: "string", - }, - }, - }, - additionalProperties: false, - }, - }, - replyStyle: { - type: "string", - enum: ["thread", "top-level"], - }, - channels: { - type: "object", - propertyNames: { - type: "string", - }, - additionalProperties: { - type: "object", - properties: { - requireMention: { - type: "boolean", - }, - tools: { - type: "object", - properties: { - allow: { - type: "array", - items: { - type: "string", - }, - }, - alsoAllow: { - type: "array", - items: { - type: "string", - }, - }, - deny: { - type: "array", - items: { - type: "string", - }, - }, - }, - additionalProperties: false, - }, - toolsBySender: { - type: "object", - propertyNames: { - type: "string", - }, - additionalProperties: { - type: "object", - properties: { - allow: { - type: "array", - items: { - type: "string", - }, - }, - alsoAllow: { - type: "array", - items: { - type: "string", - }, - }, - deny: { - type: "array", - items: { - type: "string", - }, - }, - }, - additionalProperties: false, - }, - }, - replyStyle: { - type: "string", - enum: ["thread", "top-level"], - }, - }, - additionalProperties: false, - }, - }, - }, - additionalProperties: false, - }, - }, - mediaMaxMb: { - type: "number", - exclusiveMinimum: 0, - }, - sharePointSiteId: { - type: "string", - }, - heartbeat: { - type: "object", - properties: { - showOk: { - type: "boolean", - }, - showAlerts: { - type: "boolean", - }, - useIndicator: { - type: "boolean", - }, - }, - additionalProperties: false, - }, - healthMonitor: { - type: "object", - properties: { - enabled: { - type: "boolean", - }, - }, - additionalProperties: false, - }, - responsePrefix: { - type: "string", - }, - welcomeCard: { - type: "boolean", - }, - promptStarters: { - type: "array", - items: { - type: "string", - }, - }, - groupWelcomeCard: { - type: "boolean", - }, - feedbackEnabled: { - type: "boolean", - }, - feedbackReflection: { - type: "boolean", - }, - feedbackReflectionCooldownMs: { - type: "integer", - minimum: 0, - maximum: 9007199254740991, - }, - }, - required: ["dmPolicy", "groupPolicy"], - additionalProperties: false, - }, - uiHints: { - "": { - label: "MS Teams", - help: "Microsoft Teams channel provider configuration and provider-specific policy toggles. Use this section to isolate Teams behavior from other enterprise chat providers.", - }, - configWrites: { - label: "MS Teams Config Writes", - help: "Allow Microsoft Teams to write config in response to channel events/commands (default: true).", - }, - }, - }, - { - pluginId: "nextcloud-talk", - channelId: "nextcloud-talk", - label: "Nextcloud Talk", - description: "Self-hosted chat via Nextcloud Talk webhook bots.", - schema: { - $schema: "http://json-schema.org/draft-07/schema#", - type: "object", - properties: { - name: { - type: "string", - }, - enabled: { - type: "boolean", - }, - markdown: { - type: "object", - properties: { - tables: { - type: "string", - enum: ["off", "bullets", "code"], - }, - }, - additionalProperties: false, - }, - baseUrl: { - type: "string", - }, - botSecret: { - anyOf: [ - { - type: "string", - }, - { - oneOf: [ - { - type: "object", - properties: { - source: { - type: "string", - const: "env", - }, - provider: { - type: "string", - pattern: "^[a-z][a-z0-9_-]{0,63}$", - }, - id: { - type: "string", - pattern: "^[A-Z][A-Z0-9_]{0,127}$", - }, - }, - required: ["source", "provider", "id"], - additionalProperties: false, - }, - { - type: "object", - properties: { - source: { - type: "string", - const: "file", - }, - provider: { - type: "string", - pattern: "^[a-z][a-z0-9_-]{0,63}$", - }, - id: { - type: "string", - }, - }, - required: ["source", "provider", "id"], - additionalProperties: false, - }, - { - type: "object", - properties: { - source: { - type: "string", - const: "exec", - }, - provider: { - type: "string", - pattern: "^[a-z][a-z0-9_-]{0,63}$", - }, - id: { - type: "string", - }, - }, - required: ["source", "provider", "id"], - additionalProperties: false, - }, - ], - }, - ], - }, - botSecretFile: { - type: "string", - }, - apiUser: { - type: "string", - }, - apiPassword: { - anyOf: [ - { - type: "string", - }, - { - oneOf: [ - { - type: "object", - properties: { - source: { - type: "string", - const: "env", - }, - provider: { - type: "string", - pattern: "^[a-z][a-z0-9_-]{0,63}$", - }, - id: { - type: "string", - pattern: "^[A-Z][A-Z0-9_]{0,127}$", - }, - }, - required: ["source", "provider", "id"], - additionalProperties: false, - }, - { - type: "object", - properties: { - source: { - type: "string", - const: "file", - }, - provider: { - type: "string", - pattern: "^[a-z][a-z0-9_-]{0,63}$", - }, - id: { - type: "string", - }, - }, - required: ["source", "provider", "id"], - additionalProperties: false, - }, - { - type: "object", - properties: { - source: { - type: "string", - const: "exec", - }, - provider: { - type: "string", - pattern: "^[a-z][a-z0-9_-]{0,63}$", - }, - id: { - type: "string", - }, - }, - required: ["source", "provider", "id"], - additionalProperties: false, - }, - ], - }, - ], - }, - apiPasswordFile: { - type: "string", - }, - dmPolicy: { - default: "pairing", - type: "string", - enum: ["pairing", "allowlist", "open", "disabled"], - }, - webhookPort: { - type: "integer", - exclusiveMinimum: 0, - maximum: 9007199254740991, - }, - webhookHost: { - type: "string", - }, - webhookPath: { - type: "string", - }, - webhookPublicUrl: { - type: "string", - }, - allowFrom: { - type: "array", - items: { - type: "string", - }, - }, - groupAllowFrom: { - type: "array", - items: { - type: "string", - }, - }, - groupPolicy: { - default: "allowlist", - type: "string", - enum: ["open", "disabled", "allowlist"], - }, - rooms: { - type: "object", - propertyNames: { - type: "string", - }, - additionalProperties: { - type: "object", - properties: { - requireMention: { - type: "boolean", - }, - tools: { - type: "object", - properties: { - allow: { - type: "array", - items: { - type: "string", - }, - }, - alsoAllow: { - type: "array", - items: { - type: "string", - }, - }, - deny: { - type: "array", - items: { - type: "string", - }, - }, - }, - additionalProperties: false, - }, - skills: { - type: "array", - items: { - type: "string", - }, - }, - enabled: { - type: "boolean", - }, - allowFrom: { - type: "array", - items: { - type: "string", - }, - }, - systemPrompt: { - type: "string", - }, - }, - additionalProperties: false, - }, - }, - allowPrivateNetwork: { - type: "boolean", - }, - historyLimit: { - type: "integer", - minimum: 0, - maximum: 9007199254740991, - }, - dmHistoryLimit: { - type: "integer", - minimum: 0, - maximum: 9007199254740991, - }, - dms: { - type: "object", - propertyNames: { - type: "string", - }, - additionalProperties: { - type: "object", - properties: { - historyLimit: { - type: "integer", - minimum: 0, - maximum: 9007199254740991, - }, - }, - additionalProperties: false, - }, - }, - textChunkLimit: { - type: "integer", - exclusiveMinimum: 0, - maximum: 9007199254740991, - }, - chunkMode: { - type: "string", - enum: ["length", "newline"], - }, - blockStreaming: { - type: "boolean", - }, - blockStreamingCoalesce: { - type: "object", - properties: { - minChars: { - type: "integer", - exclusiveMinimum: 0, - maximum: 9007199254740991, - }, - maxChars: { - type: "integer", - exclusiveMinimum: 0, - maximum: 9007199254740991, - }, - idleMs: { - type: "integer", - minimum: 0, - maximum: 9007199254740991, - }, - }, - additionalProperties: false, - }, - responsePrefix: { - type: "string", - }, - mediaMaxMb: { - type: "number", - exclusiveMinimum: 0, - }, - accounts: { - type: "object", - propertyNames: { - type: "string", - }, - additionalProperties: { - type: "object", - properties: { - name: { - type: "string", - }, - enabled: { - type: "boolean", - }, - markdown: { - type: "object", - properties: { - tables: { - type: "string", - enum: ["off", "bullets", "code"], - }, - }, - additionalProperties: false, - }, - baseUrl: { - type: "string", - }, - botSecret: { - anyOf: [ - { - type: "string", - }, - { - oneOf: [ - { - type: "object", - properties: { - source: { - type: "string", - const: "env", - }, - provider: { - type: "string", - pattern: "^[a-z][a-z0-9_-]{0,63}$", - }, - id: { - type: "string", - pattern: "^[A-Z][A-Z0-9_]{0,127}$", - }, - }, - required: ["source", "provider", "id"], - additionalProperties: false, - }, - { - type: "object", - properties: { - source: { - type: "string", - const: "file", - }, - provider: { - type: "string", - pattern: "^[a-z][a-z0-9_-]{0,63}$", - }, - id: { - type: "string", - }, - }, - required: ["source", "provider", "id"], - additionalProperties: false, - }, - { - type: "object", - properties: { - source: { - type: "string", - const: "exec", - }, - provider: { - type: "string", - pattern: "^[a-z][a-z0-9_-]{0,63}$", - }, - id: { - type: "string", - }, - }, - required: ["source", "provider", "id"], - additionalProperties: false, - }, - ], - }, - ], - }, - botSecretFile: { - type: "string", - }, - apiUser: { - type: "string", - }, - apiPassword: { - anyOf: [ - { - type: "string", - }, - { - oneOf: [ - { - type: "object", - properties: { - source: { - type: "string", - const: "env", - }, - provider: { - type: "string", - pattern: "^[a-z][a-z0-9_-]{0,63}$", - }, - id: { - type: "string", - pattern: "^[A-Z][A-Z0-9_]{0,127}$", - }, - }, - required: ["source", "provider", "id"], - additionalProperties: false, - }, - { - type: "object", - properties: { - source: { - type: "string", - const: "file", - }, - provider: { - type: "string", - pattern: "^[a-z][a-z0-9_-]{0,63}$", - }, - id: { - type: "string", - }, - }, - required: ["source", "provider", "id"], - additionalProperties: false, - }, - { - type: "object", - properties: { - source: { - type: "string", - const: "exec", - }, - provider: { - type: "string", - pattern: "^[a-z][a-z0-9_-]{0,63}$", - }, - id: { - type: "string", - }, - }, - required: ["source", "provider", "id"], - additionalProperties: false, - }, - ], - }, - ], - }, - apiPasswordFile: { - type: "string", - }, - dmPolicy: { - default: "pairing", - type: "string", - enum: ["pairing", "allowlist", "open", "disabled"], - }, - webhookPort: { - type: "integer", - exclusiveMinimum: 0, - maximum: 9007199254740991, - }, - webhookHost: { - type: "string", - }, - webhookPath: { - type: "string", - }, - webhookPublicUrl: { - type: "string", - }, - allowFrom: { - type: "array", - items: { - type: "string", - }, - }, - groupAllowFrom: { - type: "array", - items: { - type: "string", - }, - }, - groupPolicy: { - default: "allowlist", - type: "string", - enum: ["open", "disabled", "allowlist"], - }, - rooms: { - type: "object", - propertyNames: { - type: "string", - }, - additionalProperties: { - type: "object", - properties: { - requireMention: { - type: "boolean", - }, - tools: { - type: "object", - properties: { - allow: { - type: "array", - items: { - type: "string", - }, - }, - alsoAllow: { - type: "array", - items: { - type: "string", - }, - }, - deny: { - type: "array", - items: { - type: "string", - }, - }, - }, - additionalProperties: false, - }, - skills: { - type: "array", - items: { - type: "string", - }, - }, - enabled: { - type: "boolean", - }, - allowFrom: { - type: "array", - items: { - type: "string", - }, - }, - systemPrompt: { - type: "string", - }, - }, - additionalProperties: false, - }, - }, - allowPrivateNetwork: { - type: "boolean", - }, - historyLimit: { - type: "integer", - minimum: 0, - maximum: 9007199254740991, - }, - dmHistoryLimit: { - type: "integer", - minimum: 0, - maximum: 9007199254740991, - }, - dms: { - type: "object", - propertyNames: { - type: "string", - }, - additionalProperties: { - type: "object", - properties: { - historyLimit: { - type: "integer", - minimum: 0, - maximum: 9007199254740991, - }, - }, - additionalProperties: false, - }, - }, - textChunkLimit: { - type: "integer", - exclusiveMinimum: 0, - maximum: 9007199254740991, - }, - chunkMode: { - type: "string", - enum: ["length", "newline"], - }, - blockStreaming: { - type: "boolean", - }, - blockStreamingCoalesce: { - type: "object", - properties: { - minChars: { - type: "integer", - exclusiveMinimum: 0, - maximum: 9007199254740991, - }, - maxChars: { - type: "integer", - exclusiveMinimum: 0, - maximum: 9007199254740991, - }, - idleMs: { - type: "integer", - minimum: 0, - maximum: 9007199254740991, - }, - }, - additionalProperties: false, - }, - responsePrefix: { - type: "string", - }, - mediaMaxMb: { - type: "number", - exclusiveMinimum: 0, - }, - }, - required: ["dmPolicy", "groupPolicy"], - additionalProperties: false, - }, - }, - defaultAccount: { - type: "string", - }, - }, - required: ["dmPolicy", "groupPolicy"], - additionalProperties: false, - }, - }, - { - pluginId: "nostr", - channelId: "nostr", - label: "Nostr", - description: "Decentralized protocol; encrypted DMs via NIP-04.", - schema: { - $schema: "http://json-schema.org/draft-07/schema#", - type: "object", - properties: { - name: { - type: "string", - }, - defaultAccount: { - type: "string", - }, - enabled: { - type: "boolean", - }, - markdown: { - type: "object", - properties: { - tables: { - type: "string", - enum: ["off", "bullets", "code"], - }, - }, - additionalProperties: false, - }, - privateKey: { - type: "string", - }, - relays: { - type: "array", - items: { - type: "string", - }, - }, - dmPolicy: { - type: "string", - enum: ["pairing", "allowlist", "open", "disabled"], - }, - allowFrom: { - type: "array", - items: { - anyOf: [ - { - type: "string", - }, - { - type: "number", - }, - ], - }, - }, - profile: { - type: "object", - properties: { - name: { - type: "string", - maxLength: 256, - }, - displayName: { - type: "string", - maxLength: 256, - }, - about: { - type: "string", - maxLength: 2000, - }, - picture: { - type: "string", - format: "uri", - }, - banner: { - type: "string", - format: "uri", - }, - website: { - type: "string", - format: "uri", - }, - nip05: { - type: "string", - }, - lud16: { - type: "string", - }, - }, - additionalProperties: false, - }, - }, - additionalProperties: false, - }, - }, - { - pluginId: "signal", - channelId: "signal", - label: "Signal", - description: 'signal-cli linked device; more setup (David Reagans: "Hop on Discord.").', - schema: { - $schema: "http://json-schema.org/draft-07/schema#", - type: "object", - properties: { - name: { - type: "string", - }, - capabilities: { - type: "array", - items: { - type: "string", - }, - }, - markdown: { - type: "object", - properties: { - tables: { - type: "string", - enum: ["off", "bullets", "code"], - }, - }, - additionalProperties: false, - }, - enabled: { - type: "boolean", - }, - configWrites: { - type: "boolean", - }, - account: { - type: "string", - }, - accountUuid: { - type: "string", - }, - httpUrl: { - type: "string", - }, - httpHost: { - type: "string", - }, - httpPort: { - type: "integer", - exclusiveMinimum: 0, - maximum: 9007199254740991, - }, - cliPath: { - type: "string", - }, - autoStart: { - type: "boolean", - }, - startupTimeoutMs: { - type: "integer", - minimum: 1000, - maximum: 120000, - }, - receiveMode: { - anyOf: [ - { - type: "string", - const: "on-start", - }, - { - type: "string", - const: "manual", - }, - ], - }, - ignoreAttachments: { - type: "boolean", - }, - ignoreStories: { - type: "boolean", - }, - sendReadReceipts: { - type: "boolean", - }, - dmPolicy: { - default: "pairing", - type: "string", - enum: ["pairing", "allowlist", "open", "disabled"], - }, - allowFrom: { - type: "array", - items: { - anyOf: [ - { - type: "string", - }, - { - type: "number", - }, - ], - }, - }, - defaultTo: { - type: "string", - }, - groupAllowFrom: { - type: "array", - items: { - anyOf: [ - { - type: "string", - }, - { - type: "number", - }, - ], - }, - }, - groupPolicy: { - default: "allowlist", - type: "string", - enum: ["open", "disabled", "allowlist"], - }, - groups: { - type: "object", - propertyNames: { - type: "string", - }, - additionalProperties: { - type: "object", - properties: { - requireMention: { - type: "boolean", - }, - tools: { - type: "object", - properties: { - allow: { - type: "array", - items: { - type: "string", - }, - }, - alsoAllow: { - type: "array", - items: { - type: "string", - }, - }, - deny: { - type: "array", - items: { - type: "string", - }, - }, - }, - additionalProperties: false, - }, - toolsBySender: { - type: "object", - propertyNames: { - type: "string", - }, - additionalProperties: { - type: "object", - properties: { - allow: { - type: "array", - items: { - type: "string", - }, - }, - alsoAllow: { - type: "array", - items: { - type: "string", - }, - }, - deny: { - type: "array", - items: { - type: "string", - }, - }, - }, - additionalProperties: false, - }, - }, - }, - additionalProperties: false, - }, - }, - historyLimit: { - type: "integer", - minimum: 0, - maximum: 9007199254740991, - }, - dmHistoryLimit: { - type: "integer", - minimum: 0, - maximum: 9007199254740991, - }, - dms: { - type: "object", - propertyNames: { - type: "string", - }, - additionalProperties: { - type: "object", - properties: { - historyLimit: { - type: "integer", - minimum: 0, - maximum: 9007199254740991, - }, - }, - additionalProperties: false, - }, - }, - textChunkLimit: { - type: "integer", - exclusiveMinimum: 0, - maximum: 9007199254740991, - }, - chunkMode: { - type: "string", - enum: ["length", "newline"], - }, - blockStreaming: { - type: "boolean", - }, - blockStreamingCoalesce: { - type: "object", - properties: { - minChars: { - type: "integer", - exclusiveMinimum: 0, - maximum: 9007199254740991, - }, - maxChars: { - type: "integer", - exclusiveMinimum: 0, - maximum: 9007199254740991, - }, - idleMs: { - type: "integer", - minimum: 0, - maximum: 9007199254740991, - }, - }, - additionalProperties: false, - }, - mediaMaxMb: { - type: "integer", - exclusiveMinimum: 0, - maximum: 9007199254740991, - }, - reactionNotifications: { - type: "string", - enum: ["off", "own", "all", "allowlist"], - }, - reactionAllowlist: { - type: "array", - items: { - anyOf: [ - { - type: "string", - }, - { - type: "number", - }, - ], - }, - }, - actions: { - type: "object", - properties: { - reactions: { - type: "boolean", - }, - }, - additionalProperties: false, - }, - reactionLevel: { - type: "string", - enum: ["off", "ack", "minimal", "extensive"], - }, - heartbeat: { - type: "object", - properties: { - showOk: { - type: "boolean", - }, - showAlerts: { - type: "boolean", - }, - useIndicator: { - type: "boolean", - }, - }, - additionalProperties: false, - }, - healthMonitor: { - type: "object", - properties: { - enabled: { - type: "boolean", - }, - }, - additionalProperties: false, - }, - responsePrefix: { - type: "string", - }, - accounts: { - type: "object", - propertyNames: { - type: "string", - }, - additionalProperties: { - type: "object", - properties: { - name: { - type: "string", - }, - capabilities: { - type: "array", - items: { - type: "string", - }, - }, - markdown: { - type: "object", - properties: { - tables: { - type: "string", - enum: ["off", "bullets", "code"], - }, - }, - additionalProperties: false, - }, - enabled: { - type: "boolean", - }, - configWrites: { - type: "boolean", - }, - account: { - type: "string", - }, - accountUuid: { - type: "string", - }, - httpUrl: { - type: "string", - }, - httpHost: { - type: "string", - }, - httpPort: { - type: "integer", - exclusiveMinimum: 0, - maximum: 9007199254740991, - }, - cliPath: { - type: "string", - }, - autoStart: { - type: "boolean", - }, - startupTimeoutMs: { - type: "integer", - minimum: 1000, - maximum: 120000, - }, - receiveMode: { - anyOf: [ - { - type: "string", - const: "on-start", - }, - { - type: "string", - const: "manual", - }, - ], - }, - ignoreAttachments: { - type: "boolean", - }, - ignoreStories: { - type: "boolean", - }, - sendReadReceipts: { - type: "boolean", - }, - dmPolicy: { - default: "pairing", - type: "string", - enum: ["pairing", "allowlist", "open", "disabled"], - }, - allowFrom: { - type: "array", - items: { - anyOf: [ - { - type: "string", - }, - { - type: "number", - }, - ], - }, - }, - defaultTo: { - type: "string", - }, - groupAllowFrom: { - type: "array", - items: { - anyOf: [ - { - type: "string", - }, - { - type: "number", - }, - ], - }, - }, - groupPolicy: { - default: "allowlist", - type: "string", - enum: ["open", "disabled", "allowlist"], - }, - groups: { - type: "object", - propertyNames: { - type: "string", - }, - additionalProperties: { - type: "object", - properties: { - requireMention: { - type: "boolean", - }, - tools: { - type: "object", - properties: { - allow: { - type: "array", - items: { - type: "string", - }, - }, - alsoAllow: { - type: "array", - items: { - type: "string", - }, - }, - deny: { - type: "array", - items: { - type: "string", - }, - }, - }, - additionalProperties: false, - }, - toolsBySender: { - type: "object", - propertyNames: { - type: "string", - }, - additionalProperties: { - type: "object", - properties: { - allow: { - type: "array", - items: { - type: "string", - }, - }, - alsoAllow: { - type: "array", - items: { - type: "string", - }, - }, - deny: { - type: "array", - items: { - type: "string", - }, - }, - }, - additionalProperties: false, - }, - }, - }, - additionalProperties: false, - }, - }, - historyLimit: { - type: "integer", - minimum: 0, - maximum: 9007199254740991, - }, - dmHistoryLimit: { - type: "integer", - minimum: 0, - maximum: 9007199254740991, - }, - dms: { - type: "object", - propertyNames: { - type: "string", - }, - additionalProperties: { - type: "object", - properties: { - historyLimit: { - type: "integer", - minimum: 0, - maximum: 9007199254740991, - }, - }, - additionalProperties: false, - }, - }, - textChunkLimit: { - type: "integer", - exclusiveMinimum: 0, - maximum: 9007199254740991, - }, - chunkMode: { - type: "string", - enum: ["length", "newline"], - }, - blockStreaming: { - type: "boolean", - }, - blockStreamingCoalesce: { - type: "object", - properties: { - minChars: { - type: "integer", - exclusiveMinimum: 0, - maximum: 9007199254740991, - }, - maxChars: { - type: "integer", - exclusiveMinimum: 0, - maximum: 9007199254740991, - }, - idleMs: { - type: "integer", - minimum: 0, - maximum: 9007199254740991, - }, - }, - additionalProperties: false, - }, - mediaMaxMb: { - type: "integer", - exclusiveMinimum: 0, - maximum: 9007199254740991, - }, - reactionNotifications: { - type: "string", - enum: ["off", "own", "all", "allowlist"], - }, - reactionAllowlist: { - type: "array", - items: { - anyOf: [ - { - type: "string", - }, - { - type: "number", - }, - ], - }, - }, - actions: { - type: "object", - properties: { - reactions: { - type: "boolean", - }, - }, - additionalProperties: false, - }, - reactionLevel: { - type: "string", - enum: ["off", "ack", "minimal", "extensive"], - }, - heartbeat: { - type: "object", - properties: { - showOk: { - type: "boolean", - }, - showAlerts: { - type: "boolean", - }, - useIndicator: { - type: "boolean", - }, - }, - additionalProperties: false, - }, - healthMonitor: { - type: "object", - properties: { - enabled: { - type: "boolean", - }, - }, - additionalProperties: false, - }, - responsePrefix: { - type: "string", - }, - }, - required: ["dmPolicy", "groupPolicy"], - additionalProperties: false, - }, - }, - defaultAccount: { - type: "string", - }, - }, - required: ["dmPolicy", "groupPolicy"], - additionalProperties: false, - }, - uiHints: { - "": { - label: "Signal", - help: "Signal channel provider configuration including account identity and DM policy behavior. Keep account mapping explicit so routing remains stable across multi-device setups.", - }, - dmPolicy: { - label: "Signal DM Policy", - help: 'Direct message access control ("pairing" recommended). "open" requires channels.signal.allowFrom=["*"].', - }, - configWrites: { - label: "Signal Config Writes", - help: "Allow Signal to write config in response to channel events/commands (default: true).", - }, - account: { - label: "Signal Account", - help: "Signal account identifier (phone/number handle) used to bind this channel config to a specific Signal identity. Keep this aligned with your linked device/session state.", - }, - }, - }, - { - pluginId: "slack", - channelId: "slack", - label: "Slack", - description: "supported (Socket Mode).", - schema: { - $schema: "http://json-schema.org/draft-07/schema#", - type: "object", - properties: { - name: { - type: "string", - }, - mode: { - default: "socket", - type: "string", - enum: ["socket", "http"], - }, - signingSecret: { - anyOf: [ - { - type: "string", - }, - { - oneOf: [ - { - type: "object", - properties: { - source: { - type: "string", - const: "env", - }, - provider: { - type: "string", - pattern: "^[a-z][a-z0-9_-]{0,63}$", - }, - id: { - type: "string", - pattern: "^[A-Z][A-Z0-9_]{0,127}$", - }, - }, - required: ["source", "provider", "id"], - additionalProperties: false, - }, - { - type: "object", - properties: { - source: { - type: "string", - const: "file", - }, - provider: { - type: "string", - pattern: "^[a-z][a-z0-9_-]{0,63}$", - }, - id: { - type: "string", - }, - }, - required: ["source", "provider", "id"], - additionalProperties: false, - }, - { - type: "object", - properties: { - source: { - type: "string", - const: "exec", - }, - provider: { - type: "string", - pattern: "^[a-z][a-z0-9_-]{0,63}$", - }, - id: { - type: "string", - }, - }, - required: ["source", "provider", "id"], - additionalProperties: false, - }, - ], - }, - ], - }, - webhookPath: { - default: "/slack/events", - type: "string", - }, - capabilities: { - anyOf: [ - { - type: "array", - items: { - type: "string", - }, - }, - { - type: "object", - properties: { - interactiveReplies: { - type: "boolean", - }, - }, - additionalProperties: false, - }, - ], - }, - markdown: { - type: "object", - properties: { - tables: { - type: "string", - enum: ["off", "bullets", "code"], - }, - }, - additionalProperties: false, - }, - enabled: { - type: "boolean", - }, - commands: { - type: "object", - properties: { - native: { - anyOf: [ - { - type: "boolean", - }, - { - type: "string", - const: "auto", - }, - ], - }, - nativeSkills: { - anyOf: [ - { - type: "boolean", - }, - { - type: "string", - const: "auto", - }, - ], - }, - }, - additionalProperties: false, - }, - configWrites: { - type: "boolean", - }, - botToken: { - anyOf: [ - { - type: "string", - }, - { - oneOf: [ - { - type: "object", - properties: { - source: { - type: "string", - const: "env", - }, - provider: { - type: "string", - pattern: "^[a-z][a-z0-9_-]{0,63}$", - }, - id: { - type: "string", - pattern: "^[A-Z][A-Z0-9_]{0,127}$", - }, - }, - required: ["source", "provider", "id"], - additionalProperties: false, - }, - { - type: "object", - properties: { - source: { - type: "string", - const: "file", - }, - provider: { - type: "string", - pattern: "^[a-z][a-z0-9_-]{0,63}$", - }, - id: { - type: "string", - }, - }, - required: ["source", "provider", "id"], - additionalProperties: false, - }, - { - type: "object", - properties: { - source: { - type: "string", - const: "exec", - }, - provider: { - type: "string", - pattern: "^[a-z][a-z0-9_-]{0,63}$", - }, - id: { - type: "string", - }, - }, - required: ["source", "provider", "id"], - additionalProperties: false, - }, - ], - }, - ], - }, - appToken: { - anyOf: [ - { - type: "string", - }, - { - oneOf: [ - { - type: "object", - properties: { - source: { - type: "string", - const: "env", - }, - provider: { - type: "string", - pattern: "^[a-z][a-z0-9_-]{0,63}$", - }, - id: { - type: "string", - pattern: "^[A-Z][A-Z0-9_]{0,127}$", - }, - }, - required: ["source", "provider", "id"], - additionalProperties: false, - }, - { - type: "object", - properties: { - source: { - type: "string", - const: "file", - }, - provider: { - type: "string", - pattern: "^[a-z][a-z0-9_-]{0,63}$", - }, - id: { - type: "string", - }, - }, - required: ["source", "provider", "id"], - additionalProperties: false, - }, - { - type: "object", - properties: { - source: { - type: "string", - const: "exec", - }, - provider: { - type: "string", - pattern: "^[a-z][a-z0-9_-]{0,63}$", - }, - id: { - type: "string", - }, - }, - required: ["source", "provider", "id"], - additionalProperties: false, - }, - ], - }, - ], - }, - userToken: { - anyOf: [ - { - type: "string", - }, - { - oneOf: [ - { - type: "object", - properties: { - source: { - type: "string", - const: "env", - }, - provider: { - type: "string", - pattern: "^[a-z][a-z0-9_-]{0,63}$", - }, - id: { - type: "string", - pattern: "^[A-Z][A-Z0-9_]{0,127}$", - }, - }, - required: ["source", "provider", "id"], - additionalProperties: false, - }, - { - type: "object", - properties: { - source: { - type: "string", - const: "file", - }, - provider: { - type: "string", - pattern: "^[a-z][a-z0-9_-]{0,63}$", - }, - id: { - type: "string", - }, - }, - required: ["source", "provider", "id"], - additionalProperties: false, - }, - { - type: "object", - properties: { - source: { - type: "string", - const: "exec", - }, - provider: { - type: "string", - pattern: "^[a-z][a-z0-9_-]{0,63}$", - }, - id: { - type: "string", - }, - }, - required: ["source", "provider", "id"], - additionalProperties: false, - }, - ], - }, - ], - }, - userTokenReadOnly: { - default: true, - type: "boolean", - }, - allowBots: { - type: "boolean", - }, - dangerouslyAllowNameMatching: { - type: "boolean", - }, - requireMention: { - type: "boolean", - }, - groupPolicy: { - default: "allowlist", - type: "string", - enum: ["open", "disabled", "allowlist"], - }, - historyLimit: { - type: "integer", - minimum: 0, - maximum: 9007199254740991, - }, - dmHistoryLimit: { - type: "integer", - minimum: 0, - maximum: 9007199254740991, - }, - dms: { - type: "object", - propertyNames: { - type: "string", - }, - additionalProperties: { - type: "object", - properties: { - historyLimit: { - type: "integer", - minimum: 0, - maximum: 9007199254740991, - }, - }, - additionalProperties: false, - }, - }, - textChunkLimit: { - type: "integer", - exclusiveMinimum: 0, - maximum: 9007199254740991, - }, - chunkMode: { - type: "string", - enum: ["length", "newline"], - }, - blockStreaming: { - type: "boolean", - }, - blockStreamingCoalesce: { - type: "object", - properties: { - minChars: { - type: "integer", - exclusiveMinimum: 0, - maximum: 9007199254740991, - }, - maxChars: { - type: "integer", - exclusiveMinimum: 0, - maximum: 9007199254740991, - }, - idleMs: { - type: "integer", - minimum: 0, - maximum: 9007199254740991, - }, - }, - additionalProperties: false, - }, - streaming: { - anyOf: [ - { - type: "boolean", - }, - { - type: "string", - enum: ["off", "partial", "block", "progress"], - }, - ], - }, - nativeStreaming: { - type: "boolean", - }, - streamMode: { - type: "string", - enum: ["replace", "status_final", "append"], - }, - mediaMaxMb: { - type: "number", - exclusiveMinimum: 0, - }, - reactionNotifications: { - type: "string", - enum: ["off", "own", "all", "allowlist"], - }, - reactionAllowlist: { - type: "array", - items: { - anyOf: [ - { - type: "string", - }, - { - type: "number", - }, - ], - }, - }, - replyToMode: { - anyOf: [ - { - type: "string", - const: "off", - }, - { - type: "string", - const: "first", - }, - { - type: "string", - const: "all", - }, - ], - }, - replyToModeByChatType: { - type: "object", - properties: { - direct: { - anyOf: [ - { - type: "string", - const: "off", - }, - { - type: "string", - const: "first", - }, - { - type: "string", - const: "all", - }, - ], - }, - group: { - anyOf: [ - { - type: "string", - const: "off", - }, - { - type: "string", - const: "first", - }, - { - type: "string", - const: "all", - }, - ], - }, - channel: { - anyOf: [ - { - type: "string", - const: "off", - }, - { - type: "string", - const: "first", - }, - { - type: "string", - const: "all", - }, - ], - }, - }, - additionalProperties: false, - }, - thread: { - type: "object", - properties: { - historyScope: { - type: "string", - enum: ["thread", "channel"], - }, - inheritParent: { - type: "boolean", - }, - initialHistoryLimit: { - type: "integer", - minimum: 0, - maximum: 9007199254740991, - }, - }, - additionalProperties: false, - }, - actions: { - type: "object", - properties: { - reactions: { - type: "boolean", - }, - messages: { - type: "boolean", - }, - pins: { - type: "boolean", - }, - search: { - type: "boolean", - }, - permissions: { - type: "boolean", - }, - memberInfo: { - type: "boolean", - }, - channelInfo: { - type: "boolean", - }, - emojiList: { - type: "boolean", - }, - }, - additionalProperties: false, - }, - slashCommand: { - type: "object", - properties: { - enabled: { - type: "boolean", - }, - name: { - type: "string", - }, - sessionPrefix: { - type: "string", - }, - ephemeral: { - type: "boolean", - }, - }, - additionalProperties: false, - }, - dmPolicy: { - type: "string", - enum: ["pairing", "allowlist", "open", "disabled"], - }, - allowFrom: { - type: "array", - items: { - anyOf: [ - { - type: "string", - }, - { - type: "number", - }, - ], - }, - }, - defaultTo: { - type: "string", - }, - dm: { - type: "object", - properties: { - enabled: { - type: "boolean", - }, - policy: { - type: "string", - enum: ["pairing", "allowlist", "open", "disabled"], - }, - allowFrom: { - type: "array", - items: { - anyOf: [ - { - type: "string", - }, - { - type: "number", - }, - ], - }, - }, - groupEnabled: { - type: "boolean", - }, - groupChannels: { - type: "array", - items: { - anyOf: [ - { - type: "string", - }, - { - type: "number", - }, - ], - }, - }, - replyToMode: { - anyOf: [ - { - type: "string", - const: "off", - }, - { - type: "string", - const: "first", - }, - { - type: "string", - const: "all", - }, - ], - }, - }, - additionalProperties: false, - }, - channels: { - type: "object", - propertyNames: { - type: "string", - }, - additionalProperties: { - type: "object", - properties: { - enabled: { - type: "boolean", - }, - allow: { - type: "boolean", - }, - requireMention: { - type: "boolean", - }, - tools: { - type: "object", - properties: { - allow: { - type: "array", - items: { - type: "string", - }, - }, - alsoAllow: { - type: "array", - items: { - type: "string", - }, - }, - deny: { - type: "array", - items: { - type: "string", - }, - }, - }, - additionalProperties: false, - }, - toolsBySender: { - type: "object", - propertyNames: { - type: "string", - }, - additionalProperties: { - type: "object", - properties: { - allow: { - type: "array", - items: { - type: "string", - }, - }, - alsoAllow: { - type: "array", - items: { - type: "string", - }, - }, - deny: { - type: "array", - items: { - type: "string", - }, - }, - }, - additionalProperties: false, - }, - }, - allowBots: { - type: "boolean", - }, - users: { - type: "array", - items: { - anyOf: [ - { - type: "string", - }, - { - type: "number", - }, - ], - }, - }, - skills: { - type: "array", - items: { - type: "string", - }, - }, - systemPrompt: { - type: "string", - }, - }, - additionalProperties: false, - }, - }, - heartbeat: { - type: "object", - properties: { - showOk: { - type: "boolean", - }, - showAlerts: { - type: "boolean", - }, - useIndicator: { - type: "boolean", - }, - }, - additionalProperties: false, - }, - healthMonitor: { - type: "object", - properties: { - enabled: { - type: "boolean", - }, - }, - additionalProperties: false, - }, - responsePrefix: { - type: "string", - }, - ackReaction: { - type: "string", - }, - typingReaction: { - type: "string", - }, - accounts: { - type: "object", - propertyNames: { - type: "string", - }, - additionalProperties: { - type: "object", - properties: { - name: { - type: "string", - }, - mode: { - type: "string", - enum: ["socket", "http"], - }, - signingSecret: { - anyOf: [ - { - type: "string", - }, - { - oneOf: [ - { - type: "object", - properties: { - source: { - type: "string", - const: "env", - }, - provider: { - type: "string", - pattern: "^[a-z][a-z0-9_-]{0,63}$", - }, - id: { - type: "string", - pattern: "^[A-Z][A-Z0-9_]{0,127}$", - }, - }, - required: ["source", "provider", "id"], - additionalProperties: false, - }, - { - type: "object", - properties: { - source: { - type: "string", - const: "file", - }, - provider: { - type: "string", - pattern: "^[a-z][a-z0-9_-]{0,63}$", - }, - id: { - type: "string", - }, - }, - required: ["source", "provider", "id"], - additionalProperties: false, - }, - { - type: "object", - properties: { - source: { - type: "string", - const: "exec", - }, - provider: { - type: "string", - pattern: "^[a-z][a-z0-9_-]{0,63}$", - }, - id: { - type: "string", - }, - }, - required: ["source", "provider", "id"], - additionalProperties: false, - }, - ], - }, - ], - }, - webhookPath: { - type: "string", - }, - capabilities: { - anyOf: [ - { - type: "array", - items: { - type: "string", - }, - }, - { - type: "object", - properties: { - interactiveReplies: { - type: "boolean", - }, - }, - additionalProperties: false, - }, - ], - }, - markdown: { - type: "object", - properties: { - tables: { - type: "string", - enum: ["off", "bullets", "code"], - }, - }, - additionalProperties: false, - }, - enabled: { - type: "boolean", - }, - commands: { - type: "object", - properties: { - native: { - anyOf: [ - { - type: "boolean", - }, - { - type: "string", - const: "auto", - }, - ], - }, - nativeSkills: { - anyOf: [ - { - type: "boolean", - }, - { - type: "string", - const: "auto", - }, - ], - }, - }, - additionalProperties: false, - }, - configWrites: { - type: "boolean", - }, - botToken: { - anyOf: [ - { - type: "string", - }, - { - oneOf: [ - { - type: "object", - properties: { - source: { - type: "string", - const: "env", - }, - provider: { - type: "string", - pattern: "^[a-z][a-z0-9_-]{0,63}$", - }, - id: { - type: "string", - pattern: "^[A-Z][A-Z0-9_]{0,127}$", - }, - }, - required: ["source", "provider", "id"], - additionalProperties: false, - }, - { - type: "object", - properties: { - source: { - type: "string", - const: "file", - }, - provider: { - type: "string", - pattern: "^[a-z][a-z0-9_-]{0,63}$", - }, - id: { - type: "string", - }, - }, - required: ["source", "provider", "id"], - additionalProperties: false, - }, - { - type: "object", - properties: { - source: { - type: "string", - const: "exec", - }, - provider: { - type: "string", - pattern: "^[a-z][a-z0-9_-]{0,63}$", - }, - id: { - type: "string", - }, - }, - required: ["source", "provider", "id"], - additionalProperties: false, - }, - ], - }, - ], - }, - appToken: { - anyOf: [ - { - type: "string", - }, - { - oneOf: [ - { - type: "object", - properties: { - source: { - type: "string", - const: "env", - }, - provider: { - type: "string", - pattern: "^[a-z][a-z0-9_-]{0,63}$", - }, - id: { - type: "string", - pattern: "^[A-Z][A-Z0-9_]{0,127}$", - }, - }, - required: ["source", "provider", "id"], - additionalProperties: false, - }, - { - type: "object", - properties: { - source: { - type: "string", - const: "file", - }, - provider: { - type: "string", - pattern: "^[a-z][a-z0-9_-]{0,63}$", - }, - id: { - type: "string", - }, - }, - required: ["source", "provider", "id"], - additionalProperties: false, - }, - { - type: "object", - properties: { - source: { - type: "string", - const: "exec", - }, - provider: { - type: "string", - pattern: "^[a-z][a-z0-9_-]{0,63}$", - }, - id: { - type: "string", - }, - }, - required: ["source", "provider", "id"], - additionalProperties: false, - }, - ], - }, - ], - }, - userToken: { - anyOf: [ - { - type: "string", - }, - { - oneOf: [ - { - type: "object", - properties: { - source: { - type: "string", - const: "env", - }, - provider: { - type: "string", - pattern: "^[a-z][a-z0-9_-]{0,63}$", - }, - id: { - type: "string", - pattern: "^[A-Z][A-Z0-9_]{0,127}$", - }, - }, - required: ["source", "provider", "id"], - additionalProperties: false, - }, - { - type: "object", - properties: { - source: { - type: "string", - const: "file", - }, - provider: { - type: "string", - pattern: "^[a-z][a-z0-9_-]{0,63}$", - }, - id: { - type: "string", - }, - }, - required: ["source", "provider", "id"], - additionalProperties: false, - }, - { - type: "object", - properties: { - source: { - type: "string", - const: "exec", - }, - provider: { - type: "string", - pattern: "^[a-z][a-z0-9_-]{0,63}$", - }, - id: { - type: "string", - }, - }, - required: ["source", "provider", "id"], - additionalProperties: false, - }, - ], - }, - ], - }, - userTokenReadOnly: { - default: true, - type: "boolean", - }, - allowBots: { - type: "boolean", - }, - dangerouslyAllowNameMatching: { - type: "boolean", - }, - requireMention: { - type: "boolean", - }, - groupPolicy: { - type: "string", - enum: ["open", "disabled", "allowlist"], - }, - historyLimit: { - type: "integer", - minimum: 0, - maximum: 9007199254740991, - }, - dmHistoryLimit: { - type: "integer", - minimum: 0, - maximum: 9007199254740991, - }, - dms: { - type: "object", - propertyNames: { - type: "string", - }, - additionalProperties: { - type: "object", - properties: { - historyLimit: { - type: "integer", - minimum: 0, - maximum: 9007199254740991, - }, - }, - additionalProperties: false, - }, - }, - textChunkLimit: { - type: "integer", - exclusiveMinimum: 0, - maximum: 9007199254740991, - }, - chunkMode: { - type: "string", - enum: ["length", "newline"], - }, - blockStreaming: { - type: "boolean", - }, - blockStreamingCoalesce: { - type: "object", - properties: { - minChars: { - type: "integer", - exclusiveMinimum: 0, - maximum: 9007199254740991, - }, - maxChars: { - type: "integer", - exclusiveMinimum: 0, - maximum: 9007199254740991, - }, - idleMs: { - type: "integer", - minimum: 0, - maximum: 9007199254740991, - }, - }, - additionalProperties: false, - }, - streaming: { - anyOf: [ - { - type: "boolean", - }, - { - type: "string", - enum: ["off", "partial", "block", "progress"], - }, - ], - }, - nativeStreaming: { - type: "boolean", - }, - streamMode: { - type: "string", - enum: ["replace", "status_final", "append"], - }, - mediaMaxMb: { - type: "number", - exclusiveMinimum: 0, - }, - reactionNotifications: { - type: "string", - enum: ["off", "own", "all", "allowlist"], - }, - reactionAllowlist: { - type: "array", - items: { - anyOf: [ - { - type: "string", - }, - { - type: "number", - }, - ], - }, - }, - replyToMode: { - anyOf: [ - { - type: "string", - const: "off", - }, - { - type: "string", - const: "first", - }, - { - type: "string", - const: "all", - }, - ], - }, - replyToModeByChatType: { - type: "object", - properties: { - direct: { - anyOf: [ - { - type: "string", - const: "off", - }, - { - type: "string", - const: "first", - }, - { - type: "string", - const: "all", - }, - ], - }, - group: { - anyOf: [ - { - type: "string", - const: "off", - }, - { - type: "string", - const: "first", - }, - { - type: "string", - const: "all", - }, - ], - }, - channel: { - anyOf: [ - { - type: "string", - const: "off", - }, - { - type: "string", - const: "first", - }, - { - type: "string", - const: "all", - }, - ], - }, - }, - additionalProperties: false, - }, - thread: { - type: "object", - properties: { - historyScope: { - type: "string", - enum: ["thread", "channel"], - }, - inheritParent: { - type: "boolean", - }, - initialHistoryLimit: { - type: "integer", - minimum: 0, - maximum: 9007199254740991, - }, - }, - additionalProperties: false, - }, - actions: { - type: "object", - properties: { - reactions: { - type: "boolean", - }, - messages: { - type: "boolean", - }, - pins: { - type: "boolean", - }, - search: { - type: "boolean", - }, - permissions: { - type: "boolean", - }, - memberInfo: { - type: "boolean", - }, - channelInfo: { - type: "boolean", - }, - emojiList: { - type: "boolean", - }, - }, - additionalProperties: false, - }, - slashCommand: { - type: "object", - properties: { - enabled: { - type: "boolean", - }, - name: { - type: "string", - }, - sessionPrefix: { - type: "string", - }, - ephemeral: { - type: "boolean", - }, - }, - additionalProperties: false, - }, - dmPolicy: { - type: "string", - enum: ["pairing", "allowlist", "open", "disabled"], - }, - allowFrom: { - type: "array", - items: { - anyOf: [ - { - type: "string", - }, - { - type: "number", - }, - ], - }, - }, - defaultTo: { - type: "string", - }, - dm: { - type: "object", - properties: { - enabled: { - type: "boolean", - }, - policy: { - type: "string", - enum: ["pairing", "allowlist", "open", "disabled"], - }, - allowFrom: { - type: "array", - items: { - anyOf: [ - { - type: "string", - }, - { - type: "number", - }, - ], - }, - }, - groupEnabled: { - type: "boolean", - }, - groupChannels: { - type: "array", - items: { - anyOf: [ - { - type: "string", - }, - { - type: "number", - }, - ], - }, - }, - replyToMode: { - anyOf: [ - { - type: "string", - const: "off", - }, - { - type: "string", - const: "first", - }, - { - type: "string", - const: "all", - }, - ], - }, - }, - additionalProperties: false, - }, - channels: { - type: "object", - propertyNames: { - type: "string", - }, - additionalProperties: { - type: "object", - properties: { - enabled: { - type: "boolean", - }, - allow: { - type: "boolean", - }, - requireMention: { - type: "boolean", - }, - tools: { - type: "object", - properties: { - allow: { - type: "array", - items: { - type: "string", - }, - }, - alsoAllow: { - type: "array", - items: { - type: "string", - }, - }, - deny: { - type: "array", - items: { - type: "string", - }, - }, - }, - additionalProperties: false, - }, - toolsBySender: { - type: "object", - propertyNames: { - type: "string", - }, - additionalProperties: { - type: "object", - properties: { - allow: { - type: "array", - items: { - type: "string", - }, - }, - alsoAllow: { - type: "array", - items: { - type: "string", - }, - }, - deny: { - type: "array", - items: { - type: "string", - }, - }, - }, - additionalProperties: false, - }, - }, - allowBots: { - type: "boolean", - }, - users: { - type: "array", - items: { - anyOf: [ - { - type: "string", - }, - { - type: "number", - }, - ], - }, - }, - skills: { - type: "array", - items: { - type: "string", - }, - }, - systemPrompt: { - type: "string", - }, - }, - additionalProperties: false, - }, - }, - heartbeat: { - type: "object", - properties: { - showOk: { - type: "boolean", - }, - showAlerts: { - type: "boolean", - }, - useIndicator: { - type: "boolean", - }, - }, - additionalProperties: false, - }, - healthMonitor: { - type: "object", - properties: { - enabled: { - type: "boolean", - }, - }, - additionalProperties: false, - }, - responsePrefix: { - type: "string", - }, - ackReaction: { - type: "string", - }, - typingReaction: { - type: "string", - }, - }, - required: ["userTokenReadOnly"], - additionalProperties: false, - }, - }, - defaultAccount: { - type: "string", - }, - }, - required: ["mode", "webhookPath", "userTokenReadOnly", "groupPolicy"], - additionalProperties: false, - }, - uiHints: { - "": { - label: "Slack", - help: "Slack channel provider configuration for bot/app tokens, streaming behavior, and DM policy controls. Keep token handling and thread behavior explicit to avoid noisy workspace interactions.", - }, - "dm.policy": { - label: "Slack DM Policy", - help: 'Direct message access control ("pairing" recommended). "open" requires channels.slack.allowFrom=["*"] (legacy: channels.slack.dm.allowFrom).', - }, - dmPolicy: { - label: "Slack DM Policy", - help: 'Direct message access control ("pairing" recommended). "open" requires channels.slack.allowFrom=["*"].', - }, - configWrites: { - label: "Slack Config Writes", - help: "Allow Slack to write config in response to channel events/commands (default: true).", - }, - "commands.native": { - label: "Slack Native Commands", - help: 'Override native commands for Slack (bool or "auto").', - }, - "commands.nativeSkills": { - label: "Slack Native Skill Commands", - help: 'Override native skill commands for Slack (bool or "auto").', - }, - allowBots: { - label: "Slack Allow Bot Messages", - help: "Allow bot-authored messages to trigger Slack replies (default: false).", - }, - botToken: { - label: "Slack Bot Token", - help: "Slack bot token used for standard chat actions in the configured workspace. Keep this credential scoped and rotate if workspace app permissions change.", - }, - appToken: { - label: "Slack App Token", - help: "Slack app-level token used for Socket Mode connections and event transport when enabled. Use least-privilege app scopes and store this token as a secret.", - }, - userToken: { - label: "Slack User Token", - help: "Optional Slack user token for workflows requiring user-context API access beyond bot permissions. Use sparingly and audit scopes because this token can carry broader authority.", - }, - userTokenReadOnly: { - label: "Slack User Token Read Only", - help: "When true, treat configured Slack user token usage as read-only helper behavior where possible. Keep enabled if you only need supplemental reads without user-context writes.", - }, - "capabilities.interactiveReplies": { - label: "Slack Interactive Replies", - help: "Enable agent-authored Slack interactive reply directives (`[[slack_buttons: ...]]`, `[[slack_select: ...]]`). Default: false.", - }, - streaming: { - label: "Slack Streaming Mode", - help: 'Unified Slack stream preview mode: "off" | "partial" | "block" | "progress". Legacy boolean/streamMode keys are auto-mapped.', - }, - nativeStreaming: { - label: "Slack Native Streaming", - help: "Enable native Slack text streaming (chat.startStream/chat.appendStream/chat.stopStream) when channels.slack.streaming is partial (default: true).", - }, - streamMode: { - label: "Slack Stream Mode (Legacy)", - help: "Legacy Slack preview mode alias (replace | status_final | append); auto-migrated to channels.slack.streaming.", - }, - "thread.historyScope": { - label: "Slack Thread History Scope", - help: 'Scope for Slack thread history context ("thread" isolates per thread; "channel" reuses channel history).', - }, - "thread.inheritParent": { - label: "Slack Thread Parent Inheritance", - help: "If true, Slack thread sessions inherit the parent channel transcript (default: false).", - }, - "thread.initialHistoryLimit": { - label: "Slack Thread Initial History Limit", - help: "Maximum number of existing Slack thread messages to fetch when starting a new thread session (default: 20, set to 0 to disable).", - }, - }, - }, - { - pluginId: "synology-chat", - channelId: "synology-chat", - label: "Synology Chat", - description: "Connect your Synology NAS Chat to OpenClaw with full agent capabilities.", - schema: { - $schema: "http://json-schema.org/draft-07/schema#", - type: "object", - properties: { - dangerouslyAllowNameMatching: { - type: "boolean", - }, - dangerouslyAllowInheritedWebhookPath: { - type: "boolean", - }, - }, - additionalProperties: {}, - }, - }, - { - pluginId: "telegram", - channelId: "telegram", - label: "Telegram", - description: "simplest way to get started — register a bot with @BotFather and get going.", - schema: { - $schema: "http://json-schema.org/draft-07/schema#", - type: "object", - properties: { - name: { - type: "string", - }, - capabilities: { - anyOf: [ - { - type: "array", - items: { - type: "string", - }, - }, - { - type: "object", - properties: { - inlineButtons: { - type: "string", - enum: ["off", "dm", "group", "all", "allowlist"], - }, - }, - additionalProperties: false, - }, - ], - }, - execApprovals: { - type: "object", - properties: { - enabled: { - type: "boolean", - }, - approvers: { - type: "array", - items: { - anyOf: [ - { - type: "string", - }, - { - type: "number", - }, - ], - }, - }, - agentFilter: { - type: "array", - items: { - type: "string", - }, - }, - sessionFilter: { - type: "array", - items: { - type: "string", - }, - }, - target: { - type: "string", - enum: ["dm", "channel", "both"], - }, - }, - additionalProperties: false, - }, - markdown: { - type: "object", - properties: { - tables: { - type: "string", - enum: ["off", "bullets", "code"], - }, - }, - additionalProperties: false, - }, - enabled: { - type: "boolean", - }, - commands: { - type: "object", - properties: { - native: { - anyOf: [ - { - type: "boolean", - }, - { - type: "string", - const: "auto", - }, - ], - }, - nativeSkills: { - anyOf: [ - { - type: "boolean", - }, - { - type: "string", - const: "auto", - }, - ], - }, - }, - additionalProperties: false, - }, - customCommands: { - type: "array", - items: { - type: "object", - properties: { - command: { - type: "string", - }, - description: { - type: "string", - }, - }, - required: ["command", "description"], - additionalProperties: false, - }, - }, - configWrites: { - type: "boolean", - }, - dmPolicy: { - default: "pairing", - type: "string", - enum: ["pairing", "allowlist", "open", "disabled"], - }, - botToken: { - anyOf: [ - { - type: "string", - }, - { - oneOf: [ - { - type: "object", - properties: { - source: { - type: "string", - const: "env", - }, - provider: { - type: "string", - pattern: "^[a-z][a-z0-9_-]{0,63}$", - }, - id: { - type: "string", - pattern: "^[A-Z][A-Z0-9_]{0,127}$", - }, - }, - required: ["source", "provider", "id"], - additionalProperties: false, - }, - { - type: "object", - properties: { - source: { - type: "string", - const: "file", - }, - provider: { - type: "string", - pattern: "^[a-z][a-z0-9_-]{0,63}$", - }, - id: { - type: "string", - }, - }, - required: ["source", "provider", "id"], - additionalProperties: false, - }, - { - type: "object", - properties: { - source: { - type: "string", - const: "exec", - }, - provider: { - type: "string", - pattern: "^[a-z][a-z0-9_-]{0,63}$", - }, - id: { - type: "string", - }, - }, - required: ["source", "provider", "id"], - additionalProperties: false, - }, - ], - }, - ], - }, - tokenFile: { - type: "string", - }, - replyToMode: { - anyOf: [ - { - type: "string", - const: "off", - }, - { - type: "string", - const: "first", - }, - { - type: "string", - const: "all", - }, - ], - }, - groups: { - type: "object", - propertyNames: { - type: "string", - }, - additionalProperties: { - type: "object", - properties: { - requireMention: { - type: "boolean", - }, - disableAudioPreflight: { - type: "boolean", - }, - groupPolicy: { - type: "string", - enum: ["open", "disabled", "allowlist"], - }, - tools: { - type: "object", - properties: { - allow: { - type: "array", - items: { - type: "string", - }, - }, - alsoAllow: { - type: "array", - items: { - type: "string", - }, - }, - deny: { - type: "array", - items: { - type: "string", - }, - }, - }, - additionalProperties: false, - }, - toolsBySender: { - type: "object", - propertyNames: { - type: "string", - }, - additionalProperties: { - type: "object", - properties: { - allow: { - type: "array", - items: { - type: "string", - }, - }, - alsoAllow: { - type: "array", - items: { - type: "string", - }, - }, - deny: { - type: "array", - items: { - type: "string", - }, - }, - }, - additionalProperties: false, - }, - }, - skills: { - type: "array", - items: { - type: "string", - }, - }, - enabled: { - type: "boolean", - }, - allowFrom: { - type: "array", - items: { - anyOf: [ - { - type: "string", - }, - { - type: "number", - }, - ], - }, - }, - systemPrompt: { - type: "string", - }, - topics: { - type: "object", - propertyNames: { - type: "string", - }, - additionalProperties: { - type: "object", - properties: { - requireMention: { - type: "boolean", - }, - disableAudioPreflight: { - type: "boolean", - }, - groupPolicy: { - type: "string", - enum: ["open", "disabled", "allowlist"], - }, - skills: { - type: "array", - items: { - type: "string", - }, - }, - enabled: { - type: "boolean", - }, - allowFrom: { - type: "array", - items: { - anyOf: [ - { - type: "string", - }, - { - type: "number", - }, - ], - }, - }, - systemPrompt: { - type: "string", - }, - agentId: { - type: "string", - }, - }, - additionalProperties: false, - }, - }, - }, - additionalProperties: false, - }, - }, - allowFrom: { - type: "array", - items: { - anyOf: [ - { - type: "string", - }, - { - type: "number", - }, - ], - }, - }, - defaultTo: { - anyOf: [ - { - type: "string", - }, - { - type: "number", - }, - ], - }, - groupAllowFrom: { - type: "array", - items: { - anyOf: [ - { - type: "string", - }, - { - type: "number", - }, - ], - }, - }, - groupPolicy: { - default: "allowlist", - type: "string", - enum: ["open", "disabled", "allowlist"], - }, - historyLimit: { - type: "integer", - minimum: 0, - maximum: 9007199254740991, - }, - dmHistoryLimit: { - type: "integer", - minimum: 0, - maximum: 9007199254740991, - }, - dms: { - type: "object", - propertyNames: { - type: "string", - }, - additionalProperties: { - type: "object", - properties: { - historyLimit: { - type: "integer", - minimum: 0, - maximum: 9007199254740991, - }, - }, - additionalProperties: false, - }, - }, - direct: { - type: "object", - propertyNames: { - type: "string", - }, - additionalProperties: { - type: "object", - properties: { - dmPolicy: { - type: "string", - enum: ["pairing", "allowlist", "open", "disabled"], - }, - tools: { - type: "object", - properties: { - allow: { - type: "array", - items: { - type: "string", - }, - }, - alsoAllow: { - type: "array", - items: { - type: "string", - }, - }, - deny: { - type: "array", - items: { - type: "string", - }, - }, - }, - additionalProperties: false, - }, - toolsBySender: { - type: "object", - propertyNames: { - type: "string", - }, - additionalProperties: { - type: "object", - properties: { - allow: { - type: "array", - items: { - type: "string", - }, - }, - alsoAllow: { - type: "array", - items: { - type: "string", - }, - }, - deny: { - type: "array", - items: { - type: "string", - }, - }, - }, - additionalProperties: false, - }, - }, - skills: { - type: "array", - items: { - type: "string", - }, - }, - enabled: { - type: "boolean", - }, - allowFrom: { - type: "array", - items: { - anyOf: [ - { - type: "string", - }, - { - type: "number", - }, - ], - }, - }, - systemPrompt: { - type: "string", - }, - topics: { - type: "object", - propertyNames: { - type: "string", - }, - additionalProperties: { - type: "object", - properties: { - requireMention: { - type: "boolean", - }, - disableAudioPreflight: { - type: "boolean", - }, - groupPolicy: { - type: "string", - enum: ["open", "disabled", "allowlist"], - }, - skills: { - type: "array", - items: { - type: "string", - }, - }, - enabled: { - type: "boolean", - }, - allowFrom: { - type: "array", - items: { - anyOf: [ - { - type: "string", - }, - { - type: "number", - }, - ], - }, - }, - systemPrompt: { - type: "string", - }, - agentId: { - type: "string", - }, - }, - additionalProperties: false, - }, - }, - requireTopic: { - type: "boolean", - }, - autoTopicLabel: { - anyOf: [ - { - type: "boolean", - }, - { - type: "object", - properties: { - enabled: { - type: "boolean", - }, - prompt: { - type: "string", - }, - }, - additionalProperties: false, - }, - ], - }, - }, - additionalProperties: false, - }, - }, - textChunkLimit: { - type: "integer", - exclusiveMinimum: 0, - maximum: 9007199254740991, - }, - chunkMode: { - type: "string", - enum: ["length", "newline"], - }, - streaming: { - anyOf: [ - { - type: "boolean", - }, - { - type: "string", - enum: ["off", "partial", "block", "progress"], - }, - ], - }, - blockStreaming: { - type: "boolean", - }, - draftChunk: { - type: "object", - properties: { - minChars: { - type: "integer", - exclusiveMinimum: 0, - maximum: 9007199254740991, - }, - maxChars: { - type: "integer", - exclusiveMinimum: 0, - maximum: 9007199254740991, - }, - breakPreference: { - anyOf: [ - { - type: "string", - const: "paragraph", - }, - { - type: "string", - const: "newline", - }, - { - type: "string", - const: "sentence", - }, - ], - }, - }, - additionalProperties: false, - }, - blockStreamingCoalesce: { - type: "object", - properties: { - minChars: { - type: "integer", - exclusiveMinimum: 0, - maximum: 9007199254740991, - }, - maxChars: { - type: "integer", - exclusiveMinimum: 0, - maximum: 9007199254740991, - }, - idleMs: { - type: "integer", - minimum: 0, - maximum: 9007199254740991, - }, - }, - additionalProperties: false, - }, - streamMode: { - type: "string", - enum: ["off", "partial", "block"], - }, - mediaMaxMb: { - type: "number", - exclusiveMinimum: 0, - }, - timeoutSeconds: { - type: "integer", - exclusiveMinimum: 0, - maximum: 9007199254740991, - }, - retry: { - type: "object", - properties: { - attempts: { - type: "integer", - minimum: 1, - maximum: 9007199254740991, - }, - minDelayMs: { - type: "integer", - minimum: 0, - maximum: 9007199254740991, - }, - maxDelayMs: { - type: "integer", - minimum: 0, - maximum: 9007199254740991, - }, - jitter: { - type: "number", - minimum: 0, - maximum: 1, - }, - }, - additionalProperties: false, - }, - network: { - type: "object", - properties: { - autoSelectFamily: { - type: "boolean", - }, - dnsResultOrder: { - type: "string", - enum: ["ipv4first", "verbatim"], - }, - }, - additionalProperties: false, - }, - proxy: { - type: "string", - }, - webhookUrl: { - description: - "Public HTTPS webhook URL registered with Telegram for inbound updates. This must be internet-reachable and requires channels.telegram.webhookSecret.", - type: "string", - }, - webhookSecret: { - description: - "Secret token sent to Telegram during webhook registration and verified on inbound webhook requests. Telegram returns this value for verification; this is not the gateway auth token and not the bot token.", - anyOf: [ - { - type: "string", - }, - { - oneOf: [ - { - type: "object", - properties: { - source: { - type: "string", - const: "env", - }, - provider: { - type: "string", - pattern: "^[a-z][a-z0-9_-]{0,63}$", - }, - id: { - type: "string", - pattern: "^[A-Z][A-Z0-9_]{0,127}$", - }, - }, - required: ["source", "provider", "id"], - additionalProperties: false, - }, - { - type: "object", - properties: { - source: { - type: "string", - const: "file", - }, - provider: { - type: "string", - pattern: "^[a-z][a-z0-9_-]{0,63}$", - }, - id: { - type: "string", - }, - }, - required: ["source", "provider", "id"], - additionalProperties: false, - }, - { - type: "object", - properties: { - source: { - type: "string", - const: "exec", - }, - provider: { - type: "string", - pattern: "^[a-z][a-z0-9_-]{0,63}$", - }, - id: { - type: "string", - }, - }, - required: ["source", "provider", "id"], - additionalProperties: false, - }, - ], - }, - ], - }, - webhookPath: { - description: - "Local webhook route path served by the gateway listener. Defaults to /telegram-webhook.", - type: "string", - }, - webhookHost: { - description: - "Local bind host for the webhook listener. Defaults to 127.0.0.1; keep loopback unless you intentionally expose direct ingress.", - type: "string", - }, - webhookPort: { - description: - "Local bind port for the webhook listener. Defaults to 8787; set to 0 to let the OS assign an ephemeral port.", - type: "integer", - minimum: 0, - maximum: 9007199254740991, - }, - webhookCertPath: { - description: - "Path to the self-signed certificate (PEM) to upload to Telegram during webhook registration. Required for self-signed certs (direct IP or no domain).", - type: "string", - }, - actions: { - type: "object", - properties: { - reactions: { - type: "boolean", - }, - sendMessage: { - type: "boolean", - }, - poll: { - type: "boolean", - }, - deleteMessage: { - type: "boolean", - }, - editMessage: { - type: "boolean", - }, - sticker: { - type: "boolean", - }, - createForumTopic: { - type: "boolean", - }, - editForumTopic: { - type: "boolean", - }, - }, - additionalProperties: false, - }, - threadBindings: { - type: "object", - properties: { - enabled: { - type: "boolean", - }, - idleHours: { - type: "number", - minimum: 0, - }, - maxAgeHours: { - type: "number", - minimum: 0, - }, - spawnSubagentSessions: { - type: "boolean", - }, - spawnAcpSessions: { - type: "boolean", - }, - }, - additionalProperties: false, - }, - reactionNotifications: { - type: "string", - enum: ["off", "own", "all"], - }, - reactionLevel: { - type: "string", - enum: ["off", "ack", "minimal", "extensive"], - }, - heartbeat: { - type: "object", - properties: { - showOk: { - type: "boolean", - }, - showAlerts: { - type: "boolean", - }, - useIndicator: { - type: "boolean", - }, - }, - additionalProperties: false, - }, - healthMonitor: { - type: "object", - properties: { - enabled: { - type: "boolean", - }, - }, - additionalProperties: false, - }, - linkPreview: { - type: "boolean", - }, - silentErrorReplies: { - type: "boolean", - }, - responsePrefix: { - type: "string", - }, - ackReaction: { - type: "string", - }, - apiRoot: { - type: "string", - format: "uri", - }, - autoTopicLabel: { - anyOf: [ - { - type: "boolean", - }, - { - type: "object", - properties: { - enabled: { - type: "boolean", - }, - prompt: { - type: "string", - }, - }, - additionalProperties: false, - }, - ], - }, - accounts: { - type: "object", - propertyNames: { - type: "string", - }, - additionalProperties: { - type: "object", - properties: { - name: { - type: "string", - }, - capabilities: { - anyOf: [ - { - type: "array", - items: { - type: "string", - }, - }, - { - type: "object", - properties: { - inlineButtons: { - type: "string", - enum: ["off", "dm", "group", "all", "allowlist"], - }, - }, - additionalProperties: false, - }, - ], - }, - execApprovals: { - type: "object", - properties: { - enabled: { - type: "boolean", - }, - approvers: { - type: "array", - items: { - anyOf: [ - { - type: "string", - }, - { - type: "number", - }, - ], - }, - }, - agentFilter: { - type: "array", - items: { - type: "string", - }, - }, - sessionFilter: { - type: "array", - items: { - type: "string", - }, - }, - target: { - type: "string", - enum: ["dm", "channel", "both"], - }, - }, - additionalProperties: false, - }, - markdown: { - type: "object", - properties: { - tables: { - type: "string", - enum: ["off", "bullets", "code"], - }, - }, - additionalProperties: false, - }, - enabled: { - type: "boolean", - }, - commands: { - type: "object", - properties: { - native: { - anyOf: [ - { - type: "boolean", - }, - { - type: "string", - const: "auto", - }, - ], - }, - nativeSkills: { - anyOf: [ - { - type: "boolean", - }, - { - type: "string", - const: "auto", - }, - ], - }, - }, - additionalProperties: false, - }, - customCommands: { - type: "array", - items: { - type: "object", - properties: { - command: { - type: "string", - }, - description: { - type: "string", - }, - }, - required: ["command", "description"], - additionalProperties: false, - }, - }, - configWrites: { - type: "boolean", - }, - dmPolicy: { - default: "pairing", - type: "string", - enum: ["pairing", "allowlist", "open", "disabled"], - }, - botToken: { - anyOf: [ - { - type: "string", - }, - { - oneOf: [ - { - type: "object", - properties: { - source: { - type: "string", - const: "env", - }, - provider: { - type: "string", - pattern: "^[a-z][a-z0-9_-]{0,63}$", - }, - id: { - type: "string", - pattern: "^[A-Z][A-Z0-9_]{0,127}$", - }, - }, - required: ["source", "provider", "id"], - additionalProperties: false, - }, - { - type: "object", - properties: { - source: { - type: "string", - const: "file", - }, - provider: { - type: "string", - pattern: "^[a-z][a-z0-9_-]{0,63}$", - }, - id: { - type: "string", - }, - }, - required: ["source", "provider", "id"], - additionalProperties: false, - }, - { - type: "object", - properties: { - source: { - type: "string", - const: "exec", - }, - provider: { - type: "string", - pattern: "^[a-z][a-z0-9_-]{0,63}$", - }, - id: { - type: "string", - }, - }, - required: ["source", "provider", "id"], - additionalProperties: false, - }, - ], - }, - ], - }, - tokenFile: { - type: "string", - }, - replyToMode: { - anyOf: [ - { - type: "string", - const: "off", - }, - { - type: "string", - const: "first", - }, - { - type: "string", - const: "all", - }, - ], - }, - groups: { - type: "object", - propertyNames: { - type: "string", - }, - additionalProperties: { - type: "object", - properties: { - requireMention: { - type: "boolean", - }, - disableAudioPreflight: { - type: "boolean", - }, - groupPolicy: { - type: "string", - enum: ["open", "disabled", "allowlist"], - }, - tools: { - type: "object", - properties: { - allow: { - type: "array", - items: { - type: "string", - }, - }, - alsoAllow: { - type: "array", - items: { - type: "string", - }, - }, - deny: { - type: "array", - items: { - type: "string", - }, - }, - }, - additionalProperties: false, - }, - toolsBySender: { - type: "object", - propertyNames: { - type: "string", - }, - additionalProperties: { - type: "object", - properties: { - allow: { - type: "array", - items: { - type: "string", - }, - }, - alsoAllow: { - type: "array", - items: { - type: "string", - }, - }, - deny: { - type: "array", - items: { - type: "string", - }, - }, - }, - additionalProperties: false, - }, - }, - skills: { - type: "array", - items: { - type: "string", - }, - }, - enabled: { - type: "boolean", - }, - allowFrom: { - type: "array", - items: { - anyOf: [ - { - type: "string", - }, - { - type: "number", - }, - ], - }, - }, - systemPrompt: { - type: "string", - }, - topics: { - type: "object", - propertyNames: { - type: "string", - }, - additionalProperties: { - type: "object", - properties: { - requireMention: { - type: "boolean", - }, - disableAudioPreflight: { - type: "boolean", - }, - groupPolicy: { - type: "string", - enum: ["open", "disabled", "allowlist"], - }, - skills: { - type: "array", - items: { - type: "string", - }, - }, - enabled: { - type: "boolean", - }, - allowFrom: { - type: "array", - items: { - anyOf: [ - { - type: "string", - }, - { - type: "number", - }, - ], - }, - }, - systemPrompt: { - type: "string", - }, - agentId: { - type: "string", - }, - }, - additionalProperties: false, - }, - }, - }, - additionalProperties: false, - }, - }, - allowFrom: { - type: "array", - items: { - anyOf: [ - { - type: "string", - }, - { - type: "number", - }, - ], - }, - }, - defaultTo: { - anyOf: [ - { - type: "string", - }, - { - type: "number", - }, - ], - }, - groupAllowFrom: { - type: "array", - items: { - anyOf: [ - { - type: "string", - }, - { - type: "number", - }, - ], - }, - }, - groupPolicy: { - default: "allowlist", - type: "string", - enum: ["open", "disabled", "allowlist"], - }, - historyLimit: { - type: "integer", - minimum: 0, - maximum: 9007199254740991, - }, - dmHistoryLimit: { - type: "integer", - minimum: 0, - maximum: 9007199254740991, - }, - dms: { - type: "object", - propertyNames: { - type: "string", - }, - additionalProperties: { - type: "object", - properties: { - historyLimit: { - type: "integer", - minimum: 0, - maximum: 9007199254740991, - }, - }, - additionalProperties: false, - }, - }, - direct: { - type: "object", - propertyNames: { - type: "string", - }, - additionalProperties: { - type: "object", - properties: { - dmPolicy: { - type: "string", - enum: ["pairing", "allowlist", "open", "disabled"], - }, - tools: { - type: "object", - properties: { - allow: { - type: "array", - items: { - type: "string", - }, - }, - alsoAllow: { - type: "array", - items: { - type: "string", - }, - }, - deny: { - type: "array", - items: { - type: "string", - }, - }, - }, - additionalProperties: false, - }, - toolsBySender: { - type: "object", - propertyNames: { - type: "string", - }, - additionalProperties: { - type: "object", - properties: { - allow: { - type: "array", - items: { - type: "string", - }, - }, - alsoAllow: { - type: "array", - items: { - type: "string", - }, - }, - deny: { - type: "array", - items: { - type: "string", - }, - }, - }, - additionalProperties: false, - }, - }, - skills: { - type: "array", - items: { - type: "string", - }, - }, - enabled: { - type: "boolean", - }, - allowFrom: { - type: "array", - items: { - anyOf: [ - { - type: "string", - }, - { - type: "number", - }, - ], - }, - }, - systemPrompt: { - type: "string", - }, - topics: { - type: "object", - propertyNames: { - type: "string", - }, - additionalProperties: { - type: "object", - properties: { - requireMention: { - type: "boolean", - }, - disableAudioPreflight: { - type: "boolean", - }, - groupPolicy: { - type: "string", - enum: ["open", "disabled", "allowlist"], - }, - skills: { - type: "array", - items: { - type: "string", - }, - }, - enabled: { - type: "boolean", - }, - allowFrom: { - type: "array", - items: { - anyOf: [ - { - type: "string", - }, - { - type: "number", - }, - ], - }, - }, - systemPrompt: { - type: "string", - }, - agentId: { - type: "string", - }, - }, - additionalProperties: false, - }, - }, - requireTopic: { - type: "boolean", - }, - autoTopicLabel: { - anyOf: [ - { - type: "boolean", - }, - { - type: "object", - properties: { - enabled: { - type: "boolean", - }, - prompt: { - type: "string", - }, - }, - additionalProperties: false, - }, - ], - }, - }, - additionalProperties: false, - }, - }, - textChunkLimit: { - type: "integer", - exclusiveMinimum: 0, - maximum: 9007199254740991, - }, - chunkMode: { - type: "string", - enum: ["length", "newline"], - }, - streaming: { - anyOf: [ - { - type: "boolean", - }, - { - type: "string", - enum: ["off", "partial", "block", "progress"], - }, - ], - }, - blockStreaming: { - type: "boolean", - }, - draftChunk: { - type: "object", - properties: { - minChars: { - type: "integer", - exclusiveMinimum: 0, - maximum: 9007199254740991, - }, - maxChars: { - type: "integer", - exclusiveMinimum: 0, - maximum: 9007199254740991, - }, - breakPreference: { - anyOf: [ - { - type: "string", - const: "paragraph", - }, - { - type: "string", - const: "newline", - }, - { - type: "string", - const: "sentence", - }, - ], - }, - }, - additionalProperties: false, - }, - blockStreamingCoalesce: { - type: "object", - properties: { - minChars: { - type: "integer", - exclusiveMinimum: 0, - maximum: 9007199254740991, - }, - maxChars: { - type: "integer", - exclusiveMinimum: 0, - maximum: 9007199254740991, - }, - idleMs: { - type: "integer", - minimum: 0, - maximum: 9007199254740991, - }, - }, - additionalProperties: false, - }, - streamMode: { - type: "string", - enum: ["off", "partial", "block"], - }, - mediaMaxMb: { - type: "number", - exclusiveMinimum: 0, - }, - timeoutSeconds: { - type: "integer", - exclusiveMinimum: 0, - maximum: 9007199254740991, - }, - retry: { - type: "object", - properties: { - attempts: { - type: "integer", - minimum: 1, - maximum: 9007199254740991, - }, - minDelayMs: { - type: "integer", - minimum: 0, - maximum: 9007199254740991, - }, - maxDelayMs: { - type: "integer", - minimum: 0, - maximum: 9007199254740991, - }, - jitter: { - type: "number", - minimum: 0, - maximum: 1, - }, - }, - additionalProperties: false, - }, - network: { - type: "object", - properties: { - autoSelectFamily: { - type: "boolean", - }, - dnsResultOrder: { - type: "string", - enum: ["ipv4first", "verbatim"], - }, - }, - additionalProperties: false, - }, - proxy: { - type: "string", - }, - webhookUrl: { - description: - "Public HTTPS webhook URL registered with Telegram for inbound updates. This must be internet-reachable and requires channels.telegram.webhookSecret.", - type: "string", - }, - webhookSecret: { - description: - "Secret token sent to Telegram during webhook registration and verified on inbound webhook requests. Telegram returns this value for verification; this is not the gateway auth token and not the bot token.", - anyOf: [ - { - type: "string", - }, - { - oneOf: [ - { - type: "object", - properties: { - source: { - type: "string", - const: "env", - }, - provider: { - type: "string", - pattern: "^[a-z][a-z0-9_-]{0,63}$", - }, - id: { - type: "string", - pattern: "^[A-Z][A-Z0-9_]{0,127}$", - }, - }, - required: ["source", "provider", "id"], - additionalProperties: false, - }, - { - type: "object", - properties: { - source: { - type: "string", - const: "file", - }, - provider: { - type: "string", - pattern: "^[a-z][a-z0-9_-]{0,63}$", - }, - id: { - type: "string", - }, - }, - required: ["source", "provider", "id"], - additionalProperties: false, - }, - { - type: "object", - properties: { - source: { - type: "string", - const: "exec", - }, - provider: { - type: "string", - pattern: "^[a-z][a-z0-9_-]{0,63}$", - }, - id: { - type: "string", - }, - }, - required: ["source", "provider", "id"], - additionalProperties: false, - }, - ], - }, - ], - }, - webhookPath: { - description: - "Local webhook route path served by the gateway listener. Defaults to /telegram-webhook.", - type: "string", - }, - webhookHost: { - description: - "Local bind host for the webhook listener. Defaults to 127.0.0.1; keep loopback unless you intentionally expose direct ingress.", - type: "string", - }, - webhookPort: { - description: - "Local bind port for the webhook listener. Defaults to 8787; set to 0 to let the OS assign an ephemeral port.", - type: "integer", - minimum: 0, - maximum: 9007199254740991, - }, - webhookCertPath: { - description: - "Path to the self-signed certificate (PEM) to upload to Telegram during webhook registration. Required for self-signed certs (direct IP or no domain).", - type: "string", - }, - actions: { - type: "object", - properties: { - reactions: { - type: "boolean", - }, - sendMessage: { - type: "boolean", - }, - poll: { - type: "boolean", - }, - deleteMessage: { - type: "boolean", - }, - editMessage: { - type: "boolean", - }, - sticker: { - type: "boolean", - }, - createForumTopic: { - type: "boolean", - }, - editForumTopic: { - type: "boolean", - }, - }, - additionalProperties: false, - }, - threadBindings: { - type: "object", - properties: { - enabled: { - type: "boolean", - }, - idleHours: { - type: "number", - minimum: 0, - }, - maxAgeHours: { - type: "number", - minimum: 0, - }, - spawnSubagentSessions: { - type: "boolean", - }, - spawnAcpSessions: { - type: "boolean", - }, - }, - additionalProperties: false, - }, - reactionNotifications: { - type: "string", - enum: ["off", "own", "all"], - }, - reactionLevel: { - type: "string", - enum: ["off", "ack", "minimal", "extensive"], - }, - heartbeat: { - type: "object", - properties: { - showOk: { - type: "boolean", - }, - showAlerts: { - type: "boolean", - }, - useIndicator: { - type: "boolean", - }, - }, - additionalProperties: false, - }, - healthMonitor: { - type: "object", - properties: { - enabled: { - type: "boolean", - }, - }, - additionalProperties: false, - }, - linkPreview: { - type: "boolean", - }, - silentErrorReplies: { - type: "boolean", - }, - responsePrefix: { - type: "string", - }, - ackReaction: { - type: "string", - }, - apiRoot: { - type: "string", - format: "uri", - }, - autoTopicLabel: { - anyOf: [ - { - type: "boolean", - }, - { - type: "object", - properties: { - enabled: { - type: "boolean", - }, - prompt: { - type: "string", - }, - }, - additionalProperties: false, - }, - ], - }, - }, - required: ["dmPolicy", "groupPolicy"], - additionalProperties: false, - }, - }, - defaultAccount: { - type: "string", - }, - }, - required: ["dmPolicy", "groupPolicy"], - additionalProperties: false, - }, - uiHints: { - "": { - label: "Telegram", - help: "Telegram channel provider configuration including auth tokens, retry behavior, and message rendering controls. Use this section to tune bot behavior for Telegram-specific API semantics.", - }, - customCommands: { - label: "Telegram Custom Commands", - help: "Additional Telegram bot menu commands (merged with native; conflicts ignored).", - }, - botToken: { - label: "Telegram Bot Token", - help: "Telegram bot token used to authenticate Bot API requests for this account/provider config. Use secret/env substitution and rotate tokens if exposure is suspected.", - }, - dmPolicy: { - label: "Telegram DM Policy", - help: 'Direct message access control ("pairing" recommended). "open" requires channels.telegram.allowFrom=["*"].', - }, - configWrites: { - label: "Telegram Config Writes", - help: "Allow Telegram to write config in response to channel events/commands (default: true).", - }, - "commands.native": { - label: "Telegram Native Commands", - help: 'Override native commands for Telegram (bool or "auto").', - }, - "commands.nativeSkills": { - label: "Telegram Native Skill Commands", - help: 'Override native skill commands for Telegram (bool or "auto").', - }, - streaming: { - label: "Telegram Streaming Mode", - help: 'Unified Telegram stream preview mode: "off" | "partial" | "block" | "progress" (default: "partial"). "progress" maps to "partial" on Telegram. Legacy boolean/streamMode keys are auto-mapped.', - }, - "retry.attempts": { - label: "Telegram Retry Attempts", - help: "Max retry attempts for outbound Telegram API calls (default: 3).", - }, - "retry.minDelayMs": { - label: "Telegram Retry Min Delay (ms)", - help: "Minimum retry delay in ms for Telegram outbound calls.", - }, - "retry.maxDelayMs": { - label: "Telegram Retry Max Delay (ms)", - help: "Maximum retry delay cap in ms for Telegram outbound calls.", - }, - "retry.jitter": { - label: "Telegram Retry Jitter", - help: "Jitter factor (0-1) applied to Telegram retry delays.", - }, - "network.autoSelectFamily": { - label: "Telegram autoSelectFamily", - help: "Override Node autoSelectFamily for Telegram (true=enable, false=disable).", - }, - timeoutSeconds: { - label: "Telegram API Timeout (seconds)", - help: "Max seconds before Telegram API requests are aborted (default: 500 per grammY).", - }, - silentErrorReplies: { - label: "Telegram Silent Error Replies", - help: "When true, Telegram bot replies marked as errors are sent silently (no notification sound). Default: false.", - }, - apiRoot: { - label: "Telegram API Root URL", - help: "Custom Telegram Bot API root URL. Use for self-hosted Bot API servers (https://github.com/tdlib/telegram-bot-api) or reverse proxies in regions where api.telegram.org is blocked.", - }, - autoTopicLabel: { - label: "Telegram Auto Topic Label", - help: "Auto-rename DM forum topics on first message using LLM. Default: true. Set to false to disable, or use object form { enabled: true, prompt: '...' } for custom prompt.", - }, - "autoTopicLabel.enabled": { - label: "Telegram Auto Topic Label Enabled", - help: "Whether auto topic labeling is enabled. Default: true.", - }, - "autoTopicLabel.prompt": { - label: "Telegram Auto Topic Label Prompt", - help: "Custom prompt for LLM-based topic naming. The user message is appended after the prompt.", - }, - "capabilities.inlineButtons": { - label: "Telegram Inline Buttons", - help: "Enable Telegram inline button components for supported command and interaction surfaces. Disable if your deployment needs plain-text-only compatibility behavior.", - }, - execApprovals: { - label: "Telegram Exec Approvals", - help: "Telegram-native exec approval routing and approver authorization. Enable this only when Telegram should act as an explicit exec-approval client for the selected bot account.", - }, - "execApprovals.enabled": { - label: "Telegram Exec Approvals Enabled", - help: "Enable Telegram exec approvals for this account. When false or unset, Telegram messages/buttons cannot approve exec requests.", - }, - "execApprovals.approvers": { - label: "Telegram Exec Approval Approvers", - help: "Telegram user IDs allowed to approve exec requests for this bot account. Use numeric Telegram user IDs; prompts are only delivered to these approvers when target includes dm.", - }, - "execApprovals.agentFilter": { - label: "Telegram Exec Approval Agent Filter", - help: 'Optional allowlist of agent IDs eligible for Telegram exec approvals, for example `["main", "ops-agent"]`. Use this to keep approval prompts scoped to the agents you actually operate from Telegram.', - }, - "execApprovals.sessionFilter": { - label: "Telegram Exec Approval Session Filter", - help: "Optional session-key filters matched as substring or regex-style patterns before Telegram approval routing is used. Use narrow patterns so Telegram approvals only appear for intended sessions.", - }, - "execApprovals.target": { - label: "Telegram Exec Approval Target", - help: 'Controls where Telegram approval prompts are sent: "dm" sends to approver DMs (default), "channel" sends to the originating Telegram chat/topic, and "both" sends to both. Channel delivery exposes the command text to the chat, so only use it in trusted groups/topics.', - }, - "threadBindings.enabled": { - label: "Telegram Thread Binding Enabled", - help: "Enable Telegram conversation binding features (/focus, /unfocus, /agents, and /session idle|max-age). Overrides session.threadBindings.enabled when set.", - }, - "threadBindings.idleHours": { - label: "Telegram Thread Binding Idle Timeout (hours)", - help: "Inactivity window in hours for Telegram bound sessions. Set 0 to disable idle auto-unfocus (default: 24). Overrides session.threadBindings.idleHours when set.", - }, - "threadBindings.maxAgeHours": { - label: "Telegram Thread Binding Max Age (hours)", - help: "Optional hard max age in hours for Telegram bound sessions. Set 0 to disable hard cap (default: 0). Overrides session.threadBindings.maxAgeHours when set.", - }, - "threadBindings.spawnSubagentSessions": { - label: "Telegram Thread-Bound Subagent Spawn", - help: "Allow subagent spawns with thread=true to auto-bind Telegram current conversations when supported.", - }, - "threadBindings.spawnAcpSessions": { - label: "Telegram Thread-Bound ACP Spawn", - help: "Allow ACP spawns with thread=true to auto-bind Telegram current conversations when supported.", - }, - }, - }, - { - pluginId: "tlon", - channelId: "tlon", - label: "Tlon", - description: "decentralized messaging on Urbit; install the plugin to enable.", - schema: { - $schema: "http://json-schema.org/draft-07/schema#", - type: "object", - properties: { - name: { - type: "string", - }, - enabled: { - type: "boolean", - }, - ship: { - type: "string", - minLength: 1, - }, - url: { - type: "string", - }, - code: { - type: "string", - }, - allowPrivateNetwork: { - type: "boolean", - }, - groupChannels: { - type: "array", - items: { - type: "string", - minLength: 1, - }, - }, - dmAllowlist: { - type: "array", - items: { - type: "string", - minLength: 1, - }, - }, - autoDiscoverChannels: { - type: "boolean", - }, - showModelSignature: { - type: "boolean", - }, - responsePrefix: { - type: "string", - }, - autoAcceptDmInvites: { - type: "boolean", - }, - autoAcceptGroupInvites: { - type: "boolean", - }, - ownerShip: { - type: "string", - minLength: 1, - }, - authorization: { - type: "object", - properties: { - channelRules: { - type: "object", - propertyNames: { - type: "string", - }, - additionalProperties: { - type: "object", - properties: { - mode: { - type: "string", - enum: ["restricted", "open"], - }, - allowedShips: { - type: "array", - items: { - type: "string", - minLength: 1, - }, - }, - }, - additionalProperties: false, - }, - }, - }, - additionalProperties: false, - }, - defaultAuthorizedShips: { - type: "array", - items: { - type: "string", - minLength: 1, - }, - }, - accounts: { - type: "object", - propertyNames: { - type: "string", - }, - additionalProperties: { - type: "object", - properties: { - name: { - type: "string", - }, - enabled: { - type: "boolean", - }, - ship: { - type: "string", - minLength: 1, - }, - url: { - type: "string", - }, - code: { - type: "string", - }, - allowPrivateNetwork: { - type: "boolean", - }, - groupChannels: { - type: "array", - items: { - type: "string", - minLength: 1, - }, - }, - dmAllowlist: { - type: "array", - items: { - type: "string", - minLength: 1, - }, - }, - autoDiscoverChannels: { - type: "boolean", - }, - showModelSignature: { - type: "boolean", - }, - responsePrefix: { - type: "string", - }, - autoAcceptDmInvites: { - type: "boolean", - }, - autoAcceptGroupInvites: { - type: "boolean", - }, - ownerShip: { - type: "string", - minLength: 1, - }, - }, - additionalProperties: false, - }, - }, - }, - additionalProperties: false, - }, - }, - { - pluginId: "twitch", - channelId: "twitch", - label: "Twitch", - description: "Twitch chat integration", - schema: { - $schema: "http://json-schema.org/draft-07/schema#", - anyOf: [ - { - allOf: [ - { - type: "object", - properties: { - name: { - type: "string", - }, - enabled: { - type: "boolean", - }, - markdown: { - type: "object", - properties: { - tables: { - type: "string", - enum: ["off", "bullets", "code"], - }, - }, - additionalProperties: false, - }, - }, - additionalProperties: false, - }, - { - type: "object", - properties: { - username: { - type: "string", - }, - accessToken: { - type: "string", - }, - clientId: { - type: "string", - }, - channel: { - type: "string", - minLength: 1, - }, - enabled: { - type: "boolean", - }, - allowFrom: { - type: "array", - items: { - type: "string", - }, - }, - allowedRoles: { - type: "array", - items: { - type: "string", - enum: ["moderator", "owner", "vip", "subscriber", "all"], - }, - }, - requireMention: { - type: "boolean", - }, - responsePrefix: { - type: "string", - }, - clientSecret: { - type: "string", - }, - refreshToken: { - type: "string", - }, - expiresIn: { - anyOf: [ - { - type: "number", - }, - { - type: "null", - }, - ], - }, - obtainmentTimestamp: { - type: "number", - }, - }, - required: ["username", "accessToken", "channel"], - additionalProperties: false, - }, - ], - }, - { - allOf: [ - { - type: "object", - properties: { - name: { - type: "string", - }, - enabled: { - type: "boolean", - }, - markdown: { - type: "object", - properties: { - tables: { - type: "string", - enum: ["off", "bullets", "code"], - }, - }, - additionalProperties: false, - }, - }, - additionalProperties: false, - }, - { - type: "object", - properties: { - accounts: { - type: "object", - propertyNames: { - type: "string", - }, - additionalProperties: { - type: "object", - properties: { - username: { - type: "string", - }, - accessToken: { - type: "string", - }, - clientId: { - type: "string", - }, - channel: { - type: "string", - minLength: 1, - }, - enabled: { - type: "boolean", - }, - allowFrom: { - type: "array", - items: { - type: "string", - }, - }, - allowedRoles: { - type: "array", - items: { - type: "string", - enum: ["moderator", "owner", "vip", "subscriber", "all"], - }, - }, - requireMention: { - type: "boolean", - }, - responsePrefix: { - type: "string", - }, - clientSecret: { - type: "string", - }, - refreshToken: { - type: "string", - }, - expiresIn: { - anyOf: [ - { - type: "number", - }, - { - type: "null", - }, - ], - }, - obtainmentTimestamp: { - type: "number", - }, - }, - required: ["username", "accessToken", "channel"], - additionalProperties: false, - }, - }, - }, - required: ["accounts"], - additionalProperties: false, - }, - ], - }, - ], - }, - }, - { - pluginId: "whatsapp", - channelId: "whatsapp", - label: "WhatsApp", - description: "works with your own number; recommend a separate phone + eSIM.", - schema: { - $schema: "http://json-schema.org/draft-07/schema#", - type: "object", - properties: { - enabled: { - type: "boolean", - }, - capabilities: { - type: "array", - items: { - type: "string", - }, - }, - markdown: { - type: "object", - properties: { - tables: { - type: "string", - enum: ["off", "bullets", "code"], - }, - }, - additionalProperties: false, - }, - configWrites: { - type: "boolean", - }, - sendReadReceipts: { - type: "boolean", - }, - messagePrefix: { - type: "string", - }, - responsePrefix: { - type: "string", - }, - dmPolicy: { - default: "pairing", - type: "string", - enum: ["pairing", "allowlist", "open", "disabled"], - }, - selfChatMode: { - type: "boolean", - }, - allowFrom: { - type: "array", - items: { - type: "string", - }, - }, - defaultTo: { - type: "string", - }, - groupAllowFrom: { - type: "array", - items: { - type: "string", - }, - }, - groupPolicy: { - default: "allowlist", - type: "string", - enum: ["open", "disabled", "allowlist"], - }, - historyLimit: { - type: "integer", - minimum: 0, - maximum: 9007199254740991, - }, - dmHistoryLimit: { - type: "integer", - minimum: 0, - maximum: 9007199254740991, - }, - dms: { - type: "object", - propertyNames: { - type: "string", - }, - additionalProperties: { - type: "object", - properties: { - historyLimit: { - type: "integer", - minimum: 0, - maximum: 9007199254740991, - }, - }, - additionalProperties: false, - }, - }, - textChunkLimit: { - type: "integer", - exclusiveMinimum: 0, - maximum: 9007199254740991, - }, - chunkMode: { - type: "string", - enum: ["length", "newline"], - }, - blockStreaming: { - type: "boolean", - }, - blockStreamingCoalesce: { - type: "object", - properties: { - minChars: { - type: "integer", - exclusiveMinimum: 0, - maximum: 9007199254740991, - }, - maxChars: { - type: "integer", - exclusiveMinimum: 0, - maximum: 9007199254740991, - }, - idleMs: { - type: "integer", - minimum: 0, - maximum: 9007199254740991, - }, - }, - additionalProperties: false, - }, - groups: { - type: "object", - propertyNames: { - type: "string", - }, - additionalProperties: { - type: "object", - properties: { - requireMention: { - type: "boolean", - }, - tools: { - type: "object", - properties: { - allow: { - type: "array", - items: { - type: "string", - }, - }, - alsoAllow: { - type: "array", - items: { - type: "string", - }, - }, - deny: { - type: "array", - items: { - type: "string", - }, - }, - }, - additionalProperties: false, - }, - toolsBySender: { - type: "object", - propertyNames: { - type: "string", - }, - additionalProperties: { - type: "object", - properties: { - allow: { - type: "array", - items: { - type: "string", - }, - }, - alsoAllow: { - type: "array", - items: { - type: "string", - }, - }, - deny: { - type: "array", - items: { - type: "string", - }, - }, - }, - additionalProperties: false, - }, - }, - }, - additionalProperties: false, - }, - }, - ackReaction: { - type: "object", - properties: { - emoji: { - type: "string", - }, - direct: { - default: true, - type: "boolean", - }, - group: { - default: "mentions", - type: "string", - enum: ["always", "mentions", "never"], - }, - }, - required: ["direct", "group"], - additionalProperties: false, - }, - debounceMs: { - default: 0, - type: "integer", - minimum: 0, - maximum: 9007199254740991, - }, - heartbeat: { - type: "object", - properties: { - showOk: { - type: "boolean", - }, - showAlerts: { - type: "boolean", - }, - useIndicator: { - type: "boolean", - }, - }, - additionalProperties: false, - }, - healthMonitor: { - type: "object", - properties: { - enabled: { - type: "boolean", - }, - }, - additionalProperties: false, - }, - accounts: { - type: "object", - propertyNames: { - type: "string", - }, - additionalProperties: { - type: "object", - properties: { - enabled: { - type: "boolean", - }, - capabilities: { - type: "array", - items: { - type: "string", - }, - }, - markdown: { - type: "object", - properties: { - tables: { - type: "string", - enum: ["off", "bullets", "code"], - }, - }, - additionalProperties: false, - }, - configWrites: { - type: "boolean", - }, - sendReadReceipts: { - type: "boolean", - }, - messagePrefix: { - type: "string", - }, - responsePrefix: { - type: "string", - }, - dmPolicy: { - default: "pairing", - type: "string", - enum: ["pairing", "allowlist", "open", "disabled"], - }, - selfChatMode: { - type: "boolean", - }, - allowFrom: { - type: "array", - items: { - type: "string", - }, - }, - defaultTo: { - type: "string", - }, - groupAllowFrom: { - type: "array", - items: { - type: "string", - }, - }, - groupPolicy: { - default: "allowlist", - type: "string", - enum: ["open", "disabled", "allowlist"], - }, - historyLimit: { - type: "integer", - minimum: 0, - maximum: 9007199254740991, - }, - dmHistoryLimit: { - type: "integer", - minimum: 0, - maximum: 9007199254740991, - }, - dms: { - type: "object", - propertyNames: { - type: "string", - }, - additionalProperties: { - type: "object", - properties: { - historyLimit: { - type: "integer", - minimum: 0, - maximum: 9007199254740991, - }, - }, - additionalProperties: false, - }, - }, - textChunkLimit: { - type: "integer", - exclusiveMinimum: 0, - maximum: 9007199254740991, - }, - chunkMode: { - type: "string", - enum: ["length", "newline"], - }, - blockStreaming: { - type: "boolean", - }, - blockStreamingCoalesce: { - type: "object", - properties: { - minChars: { - type: "integer", - exclusiveMinimum: 0, - maximum: 9007199254740991, - }, - maxChars: { - type: "integer", - exclusiveMinimum: 0, - maximum: 9007199254740991, - }, - idleMs: { - type: "integer", - minimum: 0, - maximum: 9007199254740991, - }, - }, - additionalProperties: false, - }, - groups: { - type: "object", - propertyNames: { - type: "string", - }, - additionalProperties: { - type: "object", - properties: { - requireMention: { - type: "boolean", - }, - tools: { - type: "object", - properties: { - allow: { - type: "array", - items: { - type: "string", - }, - }, - alsoAllow: { - type: "array", - items: { - type: "string", - }, - }, - deny: { - type: "array", - items: { - type: "string", - }, - }, - }, - additionalProperties: false, - }, - toolsBySender: { - type: "object", - propertyNames: { - type: "string", - }, - additionalProperties: { - type: "object", - properties: { - allow: { - type: "array", - items: { - type: "string", - }, - }, - alsoAllow: { - type: "array", - items: { - type: "string", - }, - }, - deny: { - type: "array", - items: { - type: "string", - }, - }, - }, - additionalProperties: false, - }, - }, - }, - additionalProperties: false, - }, - }, - ackReaction: { - type: "object", - properties: { - emoji: { - type: "string", - }, - direct: { - default: true, - type: "boolean", - }, - group: { - default: "mentions", - type: "string", - enum: ["always", "mentions", "never"], - }, - }, - required: ["direct", "group"], - additionalProperties: false, - }, - debounceMs: { - default: 0, - type: "integer", - minimum: 0, - maximum: 9007199254740991, - }, - heartbeat: { - type: "object", - properties: { - showOk: { - type: "boolean", - }, - showAlerts: { - type: "boolean", - }, - useIndicator: { - type: "boolean", - }, - }, - additionalProperties: false, - }, - healthMonitor: { - type: "object", - properties: { - enabled: { - type: "boolean", - }, - }, - additionalProperties: false, - }, - name: { - type: "string", - }, - authDir: { - type: "string", - }, - mediaMaxMb: { - type: "integer", - exclusiveMinimum: 0, - maximum: 9007199254740991, - }, - }, - required: ["dmPolicy", "groupPolicy", "debounceMs"], - additionalProperties: false, - }, - }, - defaultAccount: { - type: "string", - }, - mediaMaxMb: { - default: 50, - type: "integer", - exclusiveMinimum: 0, - maximum: 9007199254740991, - }, - actions: { - type: "object", - properties: { - reactions: { - type: "boolean", - }, - sendMessage: { - type: "boolean", - }, - polls: { - type: "boolean", - }, - }, - additionalProperties: false, - }, - }, - required: ["dmPolicy", "groupPolicy", "debounceMs", "mediaMaxMb"], - additionalProperties: false, - }, - uiHints: { - "": { - label: "WhatsApp", - help: "WhatsApp channel provider configuration for access policy and message batching behavior. Use this section to tune responsiveness and direct-message routing safety for WhatsApp chats.", - }, - dmPolicy: { - label: "WhatsApp DM Policy", - help: 'Direct message access control ("pairing" recommended). "open" requires channels.whatsapp.allowFrom=["*"].', - }, - selfChatMode: { - label: "WhatsApp Self-Phone Mode", - help: "Same-phone setup (bot uses your personal WhatsApp number).", - }, - debounceMs: { - label: "WhatsApp Message Debounce (ms)", - help: "Debounce window (ms) for batching rapid consecutive messages from the same sender (0 to disable).", - }, - configWrites: { - label: "WhatsApp Config Writes", - help: "Allow WhatsApp to write config in response to channel events/commands (default: true).", - }, - }, - }, - { - pluginId: "zalo", - channelId: "zalo", - label: "Zalo", - description: "Vietnam-focused messaging platform with Bot API.", - schema: { - $schema: "http://json-schema.org/draft-07/schema#", - type: "object", - properties: { - name: { - type: "string", - }, - enabled: { - type: "boolean", - }, - markdown: { - type: "object", - properties: { - tables: { - type: "string", - enum: ["off", "bullets", "code"], - }, - }, - additionalProperties: false, - }, - botToken: { - anyOf: [ - { - type: "string", - }, - { - oneOf: [ - { - type: "object", - properties: { - source: { - type: "string", - const: "env", - }, - provider: { - type: "string", - pattern: "^[a-z][a-z0-9_-]{0,63}$", - }, - id: { - type: "string", - pattern: "^[A-Z][A-Z0-9_]{0,127}$", - }, - }, - required: ["source", "provider", "id"], - additionalProperties: false, - }, - { - type: "object", - properties: { - source: { - type: "string", - const: "file", - }, - provider: { - type: "string", - pattern: "^[a-z][a-z0-9_-]{0,63}$", - }, - id: { - type: "string", - }, - }, - required: ["source", "provider", "id"], - additionalProperties: false, - }, - { - type: "object", - properties: { - source: { - type: "string", - const: "exec", - }, - provider: { - type: "string", - pattern: "^[a-z][a-z0-9_-]{0,63}$", - }, - id: { - type: "string", - }, - }, - required: ["source", "provider", "id"], - additionalProperties: false, - }, - ], - }, - ], - }, - tokenFile: { - type: "string", - }, - webhookUrl: { - type: "string", - }, - webhookSecret: { - anyOf: [ - { - type: "string", - }, - { - oneOf: [ - { - type: "object", - properties: { - source: { - type: "string", - const: "env", - }, - provider: { - type: "string", - pattern: "^[a-z][a-z0-9_-]{0,63}$", - }, - id: { - type: "string", - pattern: "^[A-Z][A-Z0-9_]{0,127}$", - }, - }, - required: ["source", "provider", "id"], - additionalProperties: false, - }, - { - type: "object", - properties: { - source: { - type: "string", - const: "file", - }, - provider: { - type: "string", - pattern: "^[a-z][a-z0-9_-]{0,63}$", - }, - id: { - type: "string", - }, - }, - required: ["source", "provider", "id"], - additionalProperties: false, - }, - { - type: "object", - properties: { - source: { - type: "string", - const: "exec", - }, - provider: { - type: "string", - pattern: "^[a-z][a-z0-9_-]{0,63}$", - }, - id: { - type: "string", - }, - }, - required: ["source", "provider", "id"], - additionalProperties: false, - }, - ], - }, - ], - }, - webhookPath: { - type: "string", - }, - dmPolicy: { - type: "string", - enum: ["pairing", "allowlist", "open", "disabled"], - }, - allowFrom: { - type: "array", - items: { - anyOf: [ - { - type: "string", - }, - { - type: "number", - }, - ], - }, - }, - groupPolicy: { - type: "string", - enum: ["open", "disabled", "allowlist"], - }, - groupAllowFrom: { - type: "array", - items: { - anyOf: [ - { - type: "string", - }, - { - type: "number", - }, - ], - }, - }, - mediaMaxMb: { - type: "number", - }, - proxy: { - type: "string", - }, - responsePrefix: { - type: "string", - }, - accounts: { - type: "object", - properties: {}, - additionalProperties: { - type: "object", - properties: { - name: { - type: "string", - }, - enabled: { - type: "boolean", - }, - markdown: { - type: "object", - properties: { - tables: { - type: "string", - enum: ["off", "bullets", "code"], - }, - }, - additionalProperties: false, - }, - botToken: { - anyOf: [ - { - type: "string", - }, - { - oneOf: [ - { - type: "object", - properties: { - source: { - type: "string", - const: "env", - }, - provider: { - type: "string", - pattern: "^[a-z][a-z0-9_-]{0,63}$", - }, - id: { - type: "string", - pattern: "^[A-Z][A-Z0-9_]{0,127}$", - }, - }, - required: ["source", "provider", "id"], - additionalProperties: false, - }, - { - type: "object", - properties: { - source: { - type: "string", - const: "file", - }, - provider: { - type: "string", - pattern: "^[a-z][a-z0-9_-]{0,63}$", - }, - id: { - type: "string", - }, - }, - required: ["source", "provider", "id"], - additionalProperties: false, - }, - { - type: "object", - properties: { - source: { - type: "string", - const: "exec", - }, - provider: { - type: "string", - pattern: "^[a-z][a-z0-9_-]{0,63}$", - }, - id: { - type: "string", - }, - }, - required: ["source", "provider", "id"], - additionalProperties: false, - }, - ], - }, - ], - }, - tokenFile: { - type: "string", - }, - webhookUrl: { - type: "string", - }, - webhookSecret: { - anyOf: [ - { - type: "string", - }, - { - oneOf: [ - { - type: "object", - properties: { - source: { - type: "string", - const: "env", - }, - provider: { - type: "string", - pattern: "^[a-z][a-z0-9_-]{0,63}$", - }, - id: { - type: "string", - pattern: "^[A-Z][A-Z0-9_]{0,127}$", - }, - }, - required: ["source", "provider", "id"], - additionalProperties: false, - }, - { - type: "object", - properties: { - source: { - type: "string", - const: "file", - }, - provider: { - type: "string", - pattern: "^[a-z][a-z0-9_-]{0,63}$", - }, - id: { - type: "string", - }, - }, - required: ["source", "provider", "id"], - additionalProperties: false, - }, - { - type: "object", - properties: { - source: { - type: "string", - const: "exec", - }, - provider: { - type: "string", - pattern: "^[a-z][a-z0-9_-]{0,63}$", - }, - id: { - type: "string", - }, - }, - required: ["source", "provider", "id"], - additionalProperties: false, - }, - ], - }, - ], - }, - webhookPath: { - type: "string", - }, - dmPolicy: { - type: "string", - enum: ["pairing", "allowlist", "open", "disabled"], - }, - allowFrom: { - type: "array", - items: { - anyOf: [ - { - type: "string", - }, - { - type: "number", - }, - ], - }, - }, - groupPolicy: { - type: "string", - enum: ["open", "disabled", "allowlist"], - }, - groupAllowFrom: { - type: "array", - items: { - anyOf: [ - { - type: "string", - }, - { - type: "number", - }, - ], - }, - }, - mediaMaxMb: { - type: "number", - }, - proxy: { - type: "string", - }, - responsePrefix: { - type: "string", - }, - }, - additionalProperties: false, - }, - }, - defaultAccount: { - type: "string", - }, - }, - additionalProperties: false, - }, - }, - { - pluginId: "zalouser", - channelId: "zalouser", - label: "Zalo Personal", - description: "Zalo personal account via QR code login.", - schema: { - $schema: "http://json-schema.org/draft-07/schema#", - type: "object", - properties: { - name: { - type: "string", - }, - enabled: { - type: "boolean", - }, - markdown: { - type: "object", - properties: { - tables: { - type: "string", - enum: ["off", "bullets", "code"], - }, - }, - additionalProperties: false, - }, - profile: { - type: "string", - }, - dangerouslyAllowNameMatching: { - type: "boolean", - }, - dmPolicy: { - type: "string", - enum: ["pairing", "allowlist", "open", "disabled"], - }, - allowFrom: { - type: "array", - items: { - anyOf: [ - { - type: "string", - }, - { - type: "number", - }, - ], - }, - }, - historyLimit: { - type: "integer", - minimum: 0, - maximum: 9007199254740991, - }, - groupAllowFrom: { - type: "array", - items: { - anyOf: [ - { - type: "string", - }, - { - type: "number", - }, - ], - }, - }, - groupPolicy: { - default: "allowlist", - type: "string", - enum: ["open", "disabled", "allowlist"], - }, - groups: { - type: "object", - properties: {}, - additionalProperties: { - type: "object", - properties: { - allow: { - type: "boolean", - }, - enabled: { - type: "boolean", - }, - requireMention: { - type: "boolean", - }, - tools: { - type: "object", - properties: { - allow: { - type: "array", - items: { - type: "string", - }, - }, - alsoAllow: { - type: "array", - items: { - type: "string", - }, - }, - deny: { - type: "array", - items: { - type: "string", - }, - }, - }, - additionalProperties: false, - }, - }, - additionalProperties: false, - }, - }, - messagePrefix: { - type: "string", - }, - responsePrefix: { - type: "string", - }, - accounts: { - type: "object", - properties: {}, - additionalProperties: { - type: "object", - properties: { - name: { - type: "string", - }, - enabled: { - type: "boolean", - }, - markdown: { - type: "object", - properties: { - tables: { - type: "string", - enum: ["off", "bullets", "code"], - }, - }, - additionalProperties: false, - }, - profile: { - type: "string", - }, - dangerouslyAllowNameMatching: { - type: "boolean", - }, - dmPolicy: { - type: "string", - enum: ["pairing", "allowlist", "open", "disabled"], - }, - allowFrom: { - type: "array", - items: { - anyOf: [ - { - type: "string", - }, - { - type: "number", - }, - ], - }, - }, - historyLimit: { - type: "integer", - minimum: 0, - maximum: 9007199254740991, - }, - groupAllowFrom: { - type: "array", - items: { - anyOf: [ - { - type: "string", - }, - { - type: "number", - }, - ], - }, - }, - groupPolicy: { - default: "allowlist", - type: "string", - enum: ["open", "disabled", "allowlist"], - }, - groups: { - type: "object", - properties: {}, - additionalProperties: { - type: "object", - properties: { - allow: { - type: "boolean", - }, - enabled: { - type: "boolean", - }, - requireMention: { - type: "boolean", - }, - tools: { - type: "object", - properties: { - allow: { - type: "array", - items: { - type: "string", - }, - }, - alsoAllow: { - type: "array", - items: { - type: "string", - }, - }, - deny: { - type: "array", - items: { - type: "string", - }, - }, - }, - additionalProperties: false, - }, - }, - additionalProperties: false, - }, - }, - messagePrefix: { - type: "string", - }, - responsePrefix: { - type: "string", - }, - }, - required: ["groupPolicy"], - additionalProperties: false, - }, - }, - defaultAccount: { - type: "string", - }, - }, - required: ["groupPolicy"], - additionalProperties: false, - }, - }, -] as const; diff --git a/src/config/bundled-channel-config-metadata.test.ts b/src/config/bundled-channel-config-metadata.test.ts deleted file mode 100644 index 8478369cbb0..00000000000 --- a/src/config/bundled-channel-config-metadata.test.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { describe, expect, it } from "vitest"; -import { collectBundledChannelConfigMetadata } from "../../scripts/generate-bundled-channel-config-metadata.ts"; -import { BUNDLED_CHANNEL_CONFIG_METADATA } from "./bundled-channel-config-metadata.js"; - -describe("bundled channel config metadata", () => { - it("matches the generated metadata snapshot", async () => { - expect(BUNDLED_CHANNEL_CONFIG_METADATA).toEqual( - await collectBundledChannelConfigMetadata({ repoRoot: process.cwd() }), - ); - }); -}); diff --git a/src/config/bundled-channel-config-metadata.ts b/src/config/bundled-channel-config-metadata.ts deleted file mode 100644 index 105f165e07f..00000000000 --- a/src/config/bundled-channel-config-metadata.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { GENERATED_BUNDLED_CHANNEL_CONFIG_METADATA } from "./bundled-channel-config-metadata.generated.js"; -import type { ConfigUiHint } from "./schema.hints.js"; - -export type BundledChannelConfigMetadata = { - pluginId: string; - channelId: string; - label?: string; - description?: string; - schema: Record; - uiHints?: Record; -}; - -export const BUNDLED_CHANNEL_CONFIG_METADATA = - GENERATED_BUNDLED_CHANNEL_CONFIG_METADATA as unknown as readonly BundledChannelConfigMetadata[]; diff --git a/src/config/schema.base.generated.ts b/src/config/schema.base.generated.ts index 895f4bec74c..5827d7ac5a3 100644 --- a/src/config/schema.base.generated.ts +++ b/src/config/schema.base.generated.ts @@ -11790,7 +11790,7 @@ export const GENERATED_BASE_CONFIG_SCHEMA = { }, "agents.list[].runtime.acp.agent": { label: "Agent ACP Harness Agent", - help: "Optional ACP harness agent id to use for this OpenClaw agent (for example codex, claude).", + help: "Optional ACP harness agent id to use for this OpenClaw agent (for example codex, claude, cursor, gemini, openclaw).", tags: ["advanced"], }, "agents.list[].runtime.acp.backend": { diff --git a/src/config/types.channels.ts b/src/config/types.channels.ts index 96d8efddac6..650a22736ff 100644 --- a/src/config/types.channels.ts +++ b/src/config/types.channels.ts @@ -1,13 +1,4 @@ import type { GroupPolicy } from "./types.base.js"; -import type { DiscordConfig } from "./types.discord.js"; -import type { GoogleChatConfig } from "./types.googlechat.js"; -import type { IMessageConfig } from "./types.imessage.js"; -import type { IrcConfig } from "./types.irc.js"; -import type { MSTeamsConfig } from "./types.msteams.js"; -import type { SignalConfig } from "./types.signal.js"; -import type { SlackConfig } from "./types.slack.js"; -import type { TelegramConfig } from "./types.telegram.js"; -import type { WhatsAppConfig } from "./types.whatsapp.js"; export type ChannelHeartbeatVisibilityConfig = { /** Show HEARTBEAT_OK acknowledgments in chat (default: false). */ @@ -52,20 +43,11 @@ export type ExtensionChannelConfig = { [key: string]: unknown; }; -export type ChannelsConfig = { +export interface 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; - // Extension channels use dynamic keys - use ExtensionChannelConfig in extensions + /** Channel sections are plugin-owned; concrete channel files augment this interface. */ // eslint-disable-next-line @typescript-eslint/no-explicit-any [key: string]: any; -}; +} diff --git a/src/config/types.discord.ts b/src/config/types.discord.ts index b015a055981..d8ffa046662 100644 --- a/src/config/types.discord.ts +++ b/src/config/types.discord.ts @@ -377,3 +377,9 @@ export type DiscordConfig = { /** Optional default account id when multiple accounts are configured. */ defaultAccount?: string; } & DiscordAccountConfig; + +declare module "./types.channels.js" { + interface ChannelsConfig { + discord?: DiscordConfig; + } +} diff --git a/src/config/types.googlechat.ts b/src/config/types.googlechat.ts index 1951e51db10..928372ed7f4 100644 --- a/src/config/types.googlechat.ts +++ b/src/config/types.googlechat.ts @@ -123,3 +123,9 @@ export type GoogleChatConfig = { /** Optional default account id when multiple accounts are configured. */ defaultAccount?: string; } & GoogleChatAccountConfig; + +declare module "./types.channels.js" { + interface ChannelsConfig { + googlechat?: GoogleChatConfig; + } +} diff --git a/src/config/types.imessage.ts b/src/config/types.imessage.ts index 4d63965586b..89215f8057c 100644 --- a/src/config/types.imessage.ts +++ b/src/config/types.imessage.ts @@ -92,3 +92,9 @@ export type IMessageConfig = { /** Optional default account id when multiple accounts are configured. */ defaultAccount?: string; } & IMessageAccountConfig; + +declare module "./types.channels.js" { + interface ChannelsConfig { + imessage?: IMessageConfig; + } +} diff --git a/src/config/types.irc.ts b/src/config/types.irc.ts index c316c5f213b..3379650bac4 100644 --- a/src/config/types.irc.ts +++ b/src/config/types.irc.ts @@ -59,3 +59,9 @@ export type IrcConfig = { /** Optional default account id when multiple accounts are configured. */ defaultAccount?: string; } & IrcAccountConfig; + +declare module "./types.channels.js" { + interface ChannelsConfig { + irc?: IrcConfig; + } +} diff --git a/src/config/types.msteams.ts b/src/config/types.msteams.ts index 4d9211d64d6..3252b16807c 100644 --- a/src/config/types.msteams.ts +++ b/src/config/types.msteams.ts @@ -134,3 +134,9 @@ export type MSTeamsConfig = { /** Minimum interval (ms) between reflections per session. Default: 300000 (5 min). */ feedbackReflectionCooldownMs?: number; }; + +declare module "./types.channels.js" { + interface ChannelsConfig { + msteams?: MSTeamsConfig; + } +} diff --git a/src/config/types.signal.ts b/src/config/types.signal.ts index bd33a64cf51..d5337a81ec8 100644 --- a/src/config/types.signal.ts +++ b/src/config/types.signal.ts @@ -60,3 +60,9 @@ export type SignalConfig = { /** Optional default account id when multiple accounts are configured. */ defaultAccount?: string; } & SignalAccountConfig; + +declare module "./types.channels.js" { + interface ChannelsConfig { + signal?: SignalConfig; + } +} diff --git a/src/config/types.slack.ts b/src/config/types.slack.ts index c62e3b03e64..e99db54c1ad 100644 --- a/src/config/types.slack.ts +++ b/src/config/types.slack.ts @@ -207,3 +207,9 @@ export type SlackConfig = { /** Optional default account id when multiple accounts are configured. */ defaultAccount?: string; } & SlackAccountConfig; + +declare module "./types.channels.js" { + interface ChannelsConfig { + slack?: SlackConfig; + } +} diff --git a/src/config/types.telegram.ts b/src/config/types.telegram.ts index 5e58ad556a3..2fb5bc91435 100644 --- a/src/config/types.telegram.ts +++ b/src/config/types.telegram.ts @@ -298,3 +298,9 @@ export type TelegramConfig = { /** Optional default account id when multiple accounts are configured. */ defaultAccount?: string; } & TelegramAccountConfig; + +declare module "./types.channels.js" { + interface ChannelsConfig { + telegram?: TelegramConfig; + } +} diff --git a/src/config/types.whatsapp.ts b/src/config/types.whatsapp.ts index 29ae866956a..0bb3146af0c 100644 --- a/src/config/types.whatsapp.ts +++ b/src/config/types.whatsapp.ts @@ -119,3 +119,9 @@ export type WhatsAppAccountConfig = WhatsAppConfigCore & /** Override auth directory (Baileys multi-file auth state). */ authDir?: string; }; + +declare module "./types.channels.js" { + interface ChannelsConfig { + whatsapp?: WhatsAppConfig; + } +} diff --git a/src/plugins/bundled-plugin-metadata.generated.ts b/src/plugins/bundled-plugin-metadata.generated.ts index 56a2a10d343..aa753d5d6b9 100644 --- a/src/plugins/bundled-plugin-metadata.generated.ts +++ b/src/plugins/bundled-plugin-metadata.generated.ts @@ -258,6 +258,511 @@ export const GENERATED_BUNDLED_PLUGIN_METADATA = [ properties: {}, }, channels: ["bluebubbles"], + channelConfigs: { + bluebubbles: { + schema: { + $schema: "http://json-schema.org/draft-07/schema#", + type: "object", + properties: { + name: { + type: "string", + }, + enabled: { + type: "boolean", + }, + markdown: { + type: "object", + properties: { + tables: { + type: "string", + enum: ["off", "bullets", "code"], + }, + }, + additionalProperties: false, + }, + serverUrl: { + type: "string", + }, + password: { + anyOf: [ + { + type: "string", + }, + { + oneOf: [ + { + type: "object", + properties: { + source: { + type: "string", + const: "env", + }, + provider: { + type: "string", + pattern: "^[a-z][a-z0-9_-]{0,63}$", + }, + id: { + type: "string", + pattern: "^[A-Z][A-Z0-9_]{0,127}$", + }, + }, + required: ["source", "provider", "id"], + additionalProperties: false, + }, + { + type: "object", + properties: { + source: { + type: "string", + const: "file", + }, + provider: { + type: "string", + pattern: "^[a-z][a-z0-9_-]{0,63}$", + }, + id: { + type: "string", + }, + }, + required: ["source", "provider", "id"], + additionalProperties: false, + }, + { + type: "object", + properties: { + source: { + type: "string", + const: "exec", + }, + provider: { + type: "string", + pattern: "^[a-z][a-z0-9_-]{0,63}$", + }, + id: { + type: "string", + }, + }, + required: ["source", "provider", "id"], + additionalProperties: false, + }, + ], + }, + ], + }, + webhookPath: { + type: "string", + }, + dmPolicy: { + type: "string", + enum: ["pairing", "allowlist", "open", "disabled"], + }, + allowFrom: { + type: "array", + items: { + anyOf: [ + { + type: "string", + }, + { + type: "number", + }, + ], + }, + }, + groupAllowFrom: { + type: "array", + items: { + anyOf: [ + { + type: "string", + }, + { + type: "number", + }, + ], + }, + }, + groupPolicy: { + type: "string", + enum: ["open", "disabled", "allowlist"], + }, + enrichGroupParticipantsFromContacts: { + default: true, + type: "boolean", + }, + historyLimit: { + type: "integer", + minimum: 0, + maximum: 9007199254740991, + }, + dmHistoryLimit: { + type: "integer", + minimum: 0, + maximum: 9007199254740991, + }, + textChunkLimit: { + type: "integer", + exclusiveMinimum: 0, + maximum: 9007199254740991, + }, + chunkMode: { + type: "string", + enum: ["length", "newline"], + }, + mediaMaxMb: { + type: "integer", + exclusiveMinimum: 0, + maximum: 9007199254740991, + }, + mediaLocalRoots: { + type: "array", + items: { + type: "string", + }, + }, + sendReadReceipts: { + type: "boolean", + }, + allowPrivateNetwork: { + type: "boolean", + }, + blockStreaming: { + type: "boolean", + }, + groups: { + type: "object", + properties: {}, + additionalProperties: { + type: "object", + properties: { + requireMention: { + type: "boolean", + }, + tools: { + type: "object", + properties: { + allow: { + type: "array", + items: { + type: "string", + }, + }, + alsoAllow: { + type: "array", + items: { + type: "string", + }, + }, + deny: { + type: "array", + items: { + type: "string", + }, + }, + }, + additionalProperties: false, + }, + }, + additionalProperties: false, + }, + }, + accounts: { + type: "object", + properties: {}, + additionalProperties: { + type: "object", + properties: { + name: { + type: "string", + }, + enabled: { + type: "boolean", + }, + markdown: { + type: "object", + properties: { + tables: { + type: "string", + enum: ["off", "bullets", "code"], + }, + }, + additionalProperties: false, + }, + serverUrl: { + type: "string", + }, + password: { + anyOf: [ + { + type: "string", + }, + { + oneOf: [ + { + type: "object", + properties: { + source: { + type: "string", + const: "env", + }, + provider: { + type: "string", + pattern: "^[a-z][a-z0-9_-]{0,63}$", + }, + id: { + type: "string", + pattern: "^[A-Z][A-Z0-9_]{0,127}$", + }, + }, + required: ["source", "provider", "id"], + additionalProperties: false, + }, + { + type: "object", + properties: { + source: { + type: "string", + const: "file", + }, + provider: { + type: "string", + pattern: "^[a-z][a-z0-9_-]{0,63}$", + }, + id: { + type: "string", + }, + }, + required: ["source", "provider", "id"], + additionalProperties: false, + }, + { + type: "object", + properties: { + source: { + type: "string", + const: "exec", + }, + provider: { + type: "string", + pattern: "^[a-z][a-z0-9_-]{0,63}$", + }, + id: { + type: "string", + }, + }, + required: ["source", "provider", "id"], + additionalProperties: false, + }, + ], + }, + ], + }, + webhookPath: { + type: "string", + }, + dmPolicy: { + type: "string", + enum: ["pairing", "allowlist", "open", "disabled"], + }, + allowFrom: { + type: "array", + items: { + anyOf: [ + { + type: "string", + }, + { + type: "number", + }, + ], + }, + }, + groupAllowFrom: { + type: "array", + items: { + anyOf: [ + { + type: "string", + }, + { + type: "number", + }, + ], + }, + }, + groupPolicy: { + type: "string", + enum: ["open", "disabled", "allowlist"], + }, + enrichGroupParticipantsFromContacts: { + default: true, + type: "boolean", + }, + historyLimit: { + type: "integer", + minimum: 0, + maximum: 9007199254740991, + }, + dmHistoryLimit: { + type: "integer", + minimum: 0, + maximum: 9007199254740991, + }, + textChunkLimit: { + type: "integer", + exclusiveMinimum: 0, + maximum: 9007199254740991, + }, + chunkMode: { + type: "string", + enum: ["length", "newline"], + }, + mediaMaxMb: { + type: "integer", + exclusiveMinimum: 0, + maximum: 9007199254740991, + }, + mediaLocalRoots: { + type: "array", + items: { + type: "string", + }, + }, + sendReadReceipts: { + type: "boolean", + }, + allowPrivateNetwork: { + type: "boolean", + }, + blockStreaming: { + type: "boolean", + }, + groups: { + type: "object", + properties: {}, + additionalProperties: { + type: "object", + properties: { + requireMention: { + type: "boolean", + }, + tools: { + type: "object", + properties: { + allow: { + type: "array", + items: { + type: "string", + }, + }, + alsoAllow: { + type: "array", + items: { + type: "string", + }, + }, + deny: { + type: "array", + items: { + type: "string", + }, + }, + }, + additionalProperties: false, + }, + }, + additionalProperties: false, + }, + }, + }, + required: ["enrichGroupParticipantsFromContacts"], + additionalProperties: false, + }, + }, + defaultAccount: { + type: "string", + }, + actions: { + type: "object", + properties: { + reactions: { + default: true, + type: "boolean", + }, + edit: { + default: true, + type: "boolean", + }, + unsend: { + default: true, + type: "boolean", + }, + reply: { + default: true, + type: "boolean", + }, + sendWithEffect: { + default: true, + type: "boolean", + }, + renameGroup: { + default: true, + type: "boolean", + }, + setGroupIcon: { + default: true, + type: "boolean", + }, + addParticipant: { + default: true, + type: "boolean", + }, + removeParticipant: { + default: true, + type: "boolean", + }, + leaveGroup: { + default: true, + type: "boolean", + }, + sendAttachment: { + default: true, + type: "boolean", + }, + }, + required: [ + "reactions", + "edit", + "unsend", + "reply", + "sendWithEffect", + "renameGroup", + "setGroupIcon", + "addParticipant", + "removeParticipant", + "leaveGroup", + "sendAttachment", + ], + additionalProperties: false, + }, + }, + required: ["enrichGroupParticipantsFromContacts"], + additionalProperties: false, + }, + uiHints: { + "": { + label: "BlueBubbles", + help: "BlueBubbles channel provider configuration used for Apple messaging bridge integrations. Keep DM policy aligned with your trusted sender model in shared deployments.", + }, + dmPolicy: { + label: "BlueBubbles DM Policy", + help: 'Direct message access control ("pairing" recommended). "open" requires channels.bluebubbles.allowFrom=["*"].', + }, + }, + label: "BlueBubbles", + description: "iMessage via the BlueBubbles mac app + REST API.", + }, + }, }, }, { @@ -834,6 +1339,2630 @@ export const GENERATED_BUNDLED_PLUGIN_METADATA = [ properties: {}, }, channels: ["discord"], + channelConfigs: { + discord: { + schema: { + $schema: "http://json-schema.org/draft-07/schema#", + type: "object", + properties: { + name: { + type: "string", + }, + capabilities: { + type: "array", + items: { + type: "string", + }, + }, + markdown: { + type: "object", + properties: { + tables: { + type: "string", + enum: ["off", "bullets", "code"], + }, + }, + additionalProperties: false, + }, + enabled: { + type: "boolean", + }, + commands: { + type: "object", + properties: { + native: { + anyOf: [ + { + type: "boolean", + }, + { + type: "string", + const: "auto", + }, + ], + }, + nativeSkills: { + anyOf: [ + { + type: "boolean", + }, + { + type: "string", + const: "auto", + }, + ], + }, + }, + additionalProperties: false, + }, + configWrites: { + type: "boolean", + }, + token: { + anyOf: [ + { + type: "string", + }, + { + oneOf: [ + { + type: "object", + properties: { + source: { + type: "string", + const: "env", + }, + provider: { + type: "string", + pattern: "^[a-z][a-z0-9_-]{0,63}$", + }, + id: { + type: "string", + pattern: "^[A-Z][A-Z0-9_]{0,127}$", + }, + }, + required: ["source", "provider", "id"], + additionalProperties: false, + }, + { + type: "object", + properties: { + source: { + type: "string", + const: "file", + }, + provider: { + type: "string", + pattern: "^[a-z][a-z0-9_-]{0,63}$", + }, + id: { + type: "string", + }, + }, + required: ["source", "provider", "id"], + additionalProperties: false, + }, + { + type: "object", + properties: { + source: { + type: "string", + const: "exec", + }, + provider: { + type: "string", + pattern: "^[a-z][a-z0-9_-]{0,63}$", + }, + id: { + type: "string", + }, + }, + required: ["source", "provider", "id"], + additionalProperties: false, + }, + ], + }, + ], + }, + proxy: { + type: "string", + }, + allowBots: { + anyOf: [ + { + type: "boolean", + }, + { + type: "string", + const: "mentions", + }, + ], + }, + dangerouslyAllowNameMatching: { + type: "boolean", + }, + groupPolicy: { + default: "allowlist", + type: "string", + enum: ["open", "disabled", "allowlist"], + }, + historyLimit: { + type: "integer", + minimum: 0, + maximum: 9007199254740991, + }, + dmHistoryLimit: { + type: "integer", + minimum: 0, + maximum: 9007199254740991, + }, + dms: { + type: "object", + propertyNames: { + type: "string", + }, + additionalProperties: { + type: "object", + properties: { + historyLimit: { + type: "integer", + minimum: 0, + maximum: 9007199254740991, + }, + }, + additionalProperties: false, + }, + }, + textChunkLimit: { + type: "integer", + exclusiveMinimum: 0, + maximum: 9007199254740991, + }, + chunkMode: { + type: "string", + enum: ["length", "newline"], + }, + blockStreaming: { + type: "boolean", + }, + blockStreamingCoalesce: { + type: "object", + properties: { + minChars: { + type: "integer", + exclusiveMinimum: 0, + maximum: 9007199254740991, + }, + maxChars: { + type: "integer", + exclusiveMinimum: 0, + maximum: 9007199254740991, + }, + idleMs: { + type: "integer", + minimum: 0, + maximum: 9007199254740991, + }, + }, + additionalProperties: false, + }, + streaming: { + anyOf: [ + { + type: "boolean", + }, + { + type: "string", + enum: ["off", "partial", "block", "progress"], + }, + ], + }, + streamMode: { + type: "string", + enum: ["partial", "block", "off"], + }, + draftChunk: { + type: "object", + properties: { + minChars: { + type: "integer", + exclusiveMinimum: 0, + maximum: 9007199254740991, + }, + maxChars: { + type: "integer", + exclusiveMinimum: 0, + maximum: 9007199254740991, + }, + breakPreference: { + anyOf: [ + { + type: "string", + const: "paragraph", + }, + { + type: "string", + const: "newline", + }, + { + type: "string", + const: "sentence", + }, + ], + }, + }, + additionalProperties: false, + }, + maxLinesPerMessage: { + type: "integer", + exclusiveMinimum: 0, + maximum: 9007199254740991, + }, + mediaMaxMb: { + type: "number", + exclusiveMinimum: 0, + }, + retry: { + type: "object", + properties: { + attempts: { + type: "integer", + minimum: 1, + maximum: 9007199254740991, + }, + minDelayMs: { + type: "integer", + minimum: 0, + maximum: 9007199254740991, + }, + maxDelayMs: { + type: "integer", + minimum: 0, + maximum: 9007199254740991, + }, + jitter: { + type: "number", + minimum: 0, + maximum: 1, + }, + }, + additionalProperties: false, + }, + actions: { + type: "object", + properties: { + reactions: { + type: "boolean", + }, + stickers: { + type: "boolean", + }, + emojiUploads: { + type: "boolean", + }, + stickerUploads: { + type: "boolean", + }, + polls: { + type: "boolean", + }, + permissions: { + type: "boolean", + }, + messages: { + type: "boolean", + }, + threads: { + type: "boolean", + }, + pins: { + type: "boolean", + }, + search: { + type: "boolean", + }, + memberInfo: { + type: "boolean", + }, + roleInfo: { + type: "boolean", + }, + roles: { + type: "boolean", + }, + channelInfo: { + type: "boolean", + }, + voiceStatus: { + type: "boolean", + }, + events: { + type: "boolean", + }, + moderation: { + type: "boolean", + }, + channels: { + type: "boolean", + }, + presence: { + type: "boolean", + }, + }, + additionalProperties: false, + }, + replyToMode: { + anyOf: [ + { + type: "string", + const: "off", + }, + { + type: "string", + const: "first", + }, + { + type: "string", + const: "all", + }, + ], + }, + dmPolicy: { + type: "string", + enum: ["pairing", "allowlist", "open", "disabled"], + }, + allowFrom: { + type: "array", + items: { + anyOf: [ + { + type: "string", + }, + { + type: "number", + }, + ], + }, + }, + defaultTo: { + type: "string", + }, + dm: { + type: "object", + properties: { + enabled: { + type: "boolean", + }, + policy: { + type: "string", + enum: ["pairing", "allowlist", "open", "disabled"], + }, + allowFrom: { + type: "array", + items: { + anyOf: [ + { + type: "string", + }, + { + type: "number", + }, + ], + }, + }, + groupEnabled: { + type: "boolean", + }, + groupChannels: { + type: "array", + items: { + anyOf: [ + { + type: "string", + }, + { + type: "number", + }, + ], + }, + }, + }, + additionalProperties: false, + }, + guilds: { + type: "object", + propertyNames: { + type: "string", + }, + additionalProperties: { + type: "object", + properties: { + slug: { + type: "string", + }, + requireMention: { + type: "boolean", + }, + ignoreOtherMentions: { + type: "boolean", + }, + tools: { + type: "object", + properties: { + allow: { + type: "array", + items: { + type: "string", + }, + }, + alsoAllow: { + type: "array", + items: { + type: "string", + }, + }, + deny: { + type: "array", + items: { + type: "string", + }, + }, + }, + additionalProperties: false, + }, + toolsBySender: { + type: "object", + propertyNames: { + type: "string", + }, + additionalProperties: { + type: "object", + properties: { + allow: { + type: "array", + items: { + type: "string", + }, + }, + alsoAllow: { + type: "array", + items: { + type: "string", + }, + }, + deny: { + type: "array", + items: { + type: "string", + }, + }, + }, + additionalProperties: false, + }, + }, + reactionNotifications: { + type: "string", + enum: ["off", "own", "all", "allowlist"], + }, + users: { + type: "array", + items: { + anyOf: [ + { + type: "string", + }, + { + type: "number", + }, + ], + }, + }, + roles: { + type: "array", + items: { + anyOf: [ + { + type: "string", + }, + { + type: "number", + }, + ], + }, + }, + channels: { + type: "object", + propertyNames: { + type: "string", + }, + additionalProperties: { + type: "object", + properties: { + allow: { + type: "boolean", + }, + requireMention: { + type: "boolean", + }, + ignoreOtherMentions: { + type: "boolean", + }, + tools: { + type: "object", + properties: { + allow: { + type: "array", + items: { + type: "string", + }, + }, + alsoAllow: { + type: "array", + items: { + type: "string", + }, + }, + deny: { + type: "array", + items: { + type: "string", + }, + }, + }, + additionalProperties: false, + }, + toolsBySender: { + type: "object", + propertyNames: { + type: "string", + }, + additionalProperties: { + type: "object", + properties: { + allow: { + type: "array", + items: { + type: "string", + }, + }, + alsoAllow: { + type: "array", + items: { + type: "string", + }, + }, + deny: { + type: "array", + items: { + type: "string", + }, + }, + }, + additionalProperties: false, + }, + }, + skills: { + type: "array", + items: { + type: "string", + }, + }, + enabled: { + type: "boolean", + }, + users: { + type: "array", + items: { + anyOf: [ + { + type: "string", + }, + { + type: "number", + }, + ], + }, + }, + roles: { + type: "array", + items: { + anyOf: [ + { + type: "string", + }, + { + type: "number", + }, + ], + }, + }, + systemPrompt: { + type: "string", + }, + includeThreadStarter: { + type: "boolean", + }, + autoThread: { + type: "boolean", + }, + autoThreadName: { + type: "string", + enum: ["message", "generated"], + }, + autoArchiveDuration: { + anyOf: [ + { + type: "string", + enum: ["60", "1440", "4320", "10080"], + }, + { + type: "number", + const: 60, + }, + { + type: "number", + const: 1440, + }, + { + type: "number", + const: 4320, + }, + { + type: "number", + const: 10080, + }, + ], + }, + }, + additionalProperties: false, + }, + }, + }, + additionalProperties: false, + }, + }, + heartbeat: { + type: "object", + properties: { + showOk: { + type: "boolean", + }, + showAlerts: { + type: "boolean", + }, + useIndicator: { + type: "boolean", + }, + }, + additionalProperties: false, + }, + healthMonitor: { + type: "object", + properties: { + enabled: { + type: "boolean", + }, + }, + additionalProperties: false, + }, + execApprovals: { + type: "object", + properties: { + enabled: { + type: "boolean", + }, + approvers: { + type: "array", + items: { + anyOf: [ + { + type: "string", + }, + { + type: "number", + }, + ], + }, + }, + agentFilter: { + type: "array", + items: { + type: "string", + }, + }, + sessionFilter: { + type: "array", + items: { + type: "string", + }, + }, + cleanupAfterResolve: { + type: "boolean", + }, + target: { + type: "string", + enum: ["dm", "channel", "both"], + }, + }, + additionalProperties: false, + }, + agentComponents: { + type: "object", + properties: { + enabled: { + type: "boolean", + }, + }, + additionalProperties: false, + }, + ui: { + type: "object", + properties: { + components: { + type: "object", + properties: { + accentColor: { + type: "string", + pattern: "^#?[0-9a-fA-F]{6}$", + }, + }, + additionalProperties: false, + }, + }, + additionalProperties: false, + }, + slashCommand: { + type: "object", + properties: { + ephemeral: { + type: "boolean", + }, + }, + additionalProperties: false, + }, + threadBindings: { + type: "object", + properties: { + enabled: { + type: "boolean", + }, + idleHours: { + type: "number", + minimum: 0, + }, + maxAgeHours: { + type: "number", + minimum: 0, + }, + spawnSubagentSessions: { + type: "boolean", + }, + spawnAcpSessions: { + type: "boolean", + }, + }, + additionalProperties: false, + }, + intents: { + type: "object", + properties: { + presence: { + type: "boolean", + }, + guildMembers: { + type: "boolean", + }, + }, + additionalProperties: false, + }, + voice: { + type: "object", + properties: { + enabled: { + type: "boolean", + }, + autoJoin: { + type: "array", + items: { + type: "object", + properties: { + guildId: { + type: "string", + minLength: 1, + }, + channelId: { + type: "string", + minLength: 1, + }, + }, + required: ["guildId", "channelId"], + additionalProperties: false, + }, + }, + daveEncryption: { + type: "boolean", + }, + decryptionFailureTolerance: { + type: "integer", + minimum: 0, + maximum: 9007199254740991, + }, + tts: { + type: "object", + properties: { + auto: { + type: "string", + enum: ["off", "always", "inbound", "tagged"], + }, + enabled: { + type: "boolean", + }, + mode: { + type: "string", + enum: ["final", "all"], + }, + provider: { + type: "string", + minLength: 1, + }, + summaryModel: { + type: "string", + }, + modelOverrides: { + type: "object", + properties: { + enabled: { + type: "boolean", + }, + allowText: { + type: "boolean", + }, + allowProvider: { + type: "boolean", + }, + allowVoice: { + type: "boolean", + }, + allowModelId: { + type: "boolean", + }, + allowVoiceSettings: { + type: "boolean", + }, + allowNormalization: { + type: "boolean", + }, + allowSeed: { + type: "boolean", + }, + }, + additionalProperties: false, + }, + providers: { + type: "object", + propertyNames: { + type: "string", + }, + additionalProperties: { + type: "object", + properties: { + apiKey: { + anyOf: [ + { + type: "string", + }, + { + oneOf: [ + { + type: "object", + properties: { + source: { + type: "string", + const: "env", + }, + provider: { + type: "string", + pattern: "^[a-z][a-z0-9_-]{0,63}$", + }, + id: { + type: "string", + pattern: "^[A-Z][A-Z0-9_]{0,127}$", + }, + }, + required: ["source", "provider", "id"], + additionalProperties: false, + }, + { + type: "object", + properties: { + source: { + type: "string", + const: "file", + }, + provider: { + type: "string", + pattern: "^[a-z][a-z0-9_-]{0,63}$", + }, + id: { + type: "string", + }, + }, + required: ["source", "provider", "id"], + additionalProperties: false, + }, + { + type: "object", + properties: { + source: { + type: "string", + const: "exec", + }, + provider: { + type: "string", + pattern: "^[a-z][a-z0-9_-]{0,63}$", + }, + id: { + type: "string", + }, + }, + required: ["source", "provider", "id"], + additionalProperties: false, + }, + ], + }, + ], + }, + }, + additionalProperties: { + anyOf: [ + { + type: "string", + }, + { + type: "number", + }, + { + type: "boolean", + }, + { + type: "null", + }, + { + type: "array", + items: {}, + }, + { + type: "object", + propertyNames: { + type: "string", + }, + additionalProperties: {}, + }, + ], + }, + }, + }, + prefsPath: { + type: "string", + }, + maxTextLength: { + type: "integer", + minimum: 1, + maximum: 9007199254740991, + }, + timeoutMs: { + type: "integer", + minimum: 1000, + maximum: 120000, + }, + }, + additionalProperties: false, + }, + }, + additionalProperties: false, + }, + pluralkit: { + type: "object", + properties: { + enabled: { + type: "boolean", + }, + token: { + anyOf: [ + { + type: "string", + }, + { + oneOf: [ + { + type: "object", + properties: { + source: { + type: "string", + const: "env", + }, + provider: { + type: "string", + pattern: "^[a-z][a-z0-9_-]{0,63}$", + }, + id: { + type: "string", + pattern: "^[A-Z][A-Z0-9_]{0,127}$", + }, + }, + required: ["source", "provider", "id"], + additionalProperties: false, + }, + { + type: "object", + properties: { + source: { + type: "string", + const: "file", + }, + provider: { + type: "string", + pattern: "^[a-z][a-z0-9_-]{0,63}$", + }, + id: { + type: "string", + }, + }, + required: ["source", "provider", "id"], + additionalProperties: false, + }, + { + type: "object", + properties: { + source: { + type: "string", + const: "exec", + }, + provider: { + type: "string", + pattern: "^[a-z][a-z0-9_-]{0,63}$", + }, + id: { + type: "string", + }, + }, + required: ["source", "provider", "id"], + additionalProperties: false, + }, + ], + }, + ], + }, + }, + additionalProperties: false, + }, + responsePrefix: { + type: "string", + }, + ackReaction: { + type: "string", + }, + ackReactionScope: { + type: "string", + enum: ["group-mentions", "group-all", "direct", "all", "off", "none"], + }, + activity: { + type: "string", + }, + status: { + type: "string", + enum: ["online", "dnd", "idle", "invisible"], + }, + autoPresence: { + type: "object", + properties: { + enabled: { + type: "boolean", + }, + intervalMs: { + type: "integer", + exclusiveMinimum: 0, + maximum: 9007199254740991, + }, + minUpdateIntervalMs: { + type: "integer", + exclusiveMinimum: 0, + maximum: 9007199254740991, + }, + healthyText: { + type: "string", + }, + degradedText: { + type: "string", + }, + exhaustedText: { + type: "string", + }, + }, + additionalProperties: false, + }, + activityType: { + anyOf: [ + { + type: "number", + const: 0, + }, + { + type: "number", + const: 1, + }, + { + type: "number", + const: 2, + }, + { + type: "number", + const: 3, + }, + { + type: "number", + const: 4, + }, + { + type: "number", + const: 5, + }, + ], + }, + activityUrl: { + type: "string", + format: "uri", + }, + inboundWorker: { + type: "object", + properties: { + runTimeoutMs: { + type: "integer", + minimum: 0, + maximum: 9007199254740991, + }, + }, + additionalProperties: false, + }, + eventQueue: { + type: "object", + properties: { + listenerTimeout: { + type: "integer", + exclusiveMinimum: 0, + maximum: 9007199254740991, + }, + maxQueueSize: { + type: "integer", + exclusiveMinimum: 0, + maximum: 9007199254740991, + }, + maxConcurrency: { + type: "integer", + exclusiveMinimum: 0, + maximum: 9007199254740991, + }, + }, + additionalProperties: false, + }, + accounts: { + type: "object", + propertyNames: { + type: "string", + }, + additionalProperties: { + type: "object", + properties: { + name: { + type: "string", + }, + capabilities: { + type: "array", + items: { + type: "string", + }, + }, + markdown: { + type: "object", + properties: { + tables: { + type: "string", + enum: ["off", "bullets", "code"], + }, + }, + additionalProperties: false, + }, + enabled: { + type: "boolean", + }, + commands: { + type: "object", + properties: { + native: { + anyOf: [ + { + type: "boolean", + }, + { + type: "string", + const: "auto", + }, + ], + }, + nativeSkills: { + anyOf: [ + { + type: "boolean", + }, + { + type: "string", + const: "auto", + }, + ], + }, + }, + additionalProperties: false, + }, + configWrites: { + type: "boolean", + }, + token: { + anyOf: [ + { + type: "string", + }, + { + oneOf: [ + { + type: "object", + properties: { + source: { + type: "string", + const: "env", + }, + provider: { + type: "string", + pattern: "^[a-z][a-z0-9_-]{0,63}$", + }, + id: { + type: "string", + pattern: "^[A-Z][A-Z0-9_]{0,127}$", + }, + }, + required: ["source", "provider", "id"], + additionalProperties: false, + }, + { + type: "object", + properties: { + source: { + type: "string", + const: "file", + }, + provider: { + type: "string", + pattern: "^[a-z][a-z0-9_-]{0,63}$", + }, + id: { + type: "string", + }, + }, + required: ["source", "provider", "id"], + additionalProperties: false, + }, + { + type: "object", + properties: { + source: { + type: "string", + const: "exec", + }, + provider: { + type: "string", + pattern: "^[a-z][a-z0-9_-]{0,63}$", + }, + id: { + type: "string", + }, + }, + required: ["source", "provider", "id"], + additionalProperties: false, + }, + ], + }, + ], + }, + proxy: { + type: "string", + }, + allowBots: { + anyOf: [ + { + type: "boolean", + }, + { + type: "string", + const: "mentions", + }, + ], + }, + dangerouslyAllowNameMatching: { + type: "boolean", + }, + groupPolicy: { + default: "allowlist", + type: "string", + enum: ["open", "disabled", "allowlist"], + }, + historyLimit: { + type: "integer", + minimum: 0, + maximum: 9007199254740991, + }, + dmHistoryLimit: { + type: "integer", + minimum: 0, + maximum: 9007199254740991, + }, + dms: { + type: "object", + propertyNames: { + type: "string", + }, + additionalProperties: { + type: "object", + properties: { + historyLimit: { + type: "integer", + minimum: 0, + maximum: 9007199254740991, + }, + }, + additionalProperties: false, + }, + }, + textChunkLimit: { + type: "integer", + exclusiveMinimum: 0, + maximum: 9007199254740991, + }, + chunkMode: { + type: "string", + enum: ["length", "newline"], + }, + blockStreaming: { + type: "boolean", + }, + blockStreamingCoalesce: { + type: "object", + properties: { + minChars: { + type: "integer", + exclusiveMinimum: 0, + maximum: 9007199254740991, + }, + maxChars: { + type: "integer", + exclusiveMinimum: 0, + maximum: 9007199254740991, + }, + idleMs: { + type: "integer", + minimum: 0, + maximum: 9007199254740991, + }, + }, + additionalProperties: false, + }, + streaming: { + anyOf: [ + { + type: "boolean", + }, + { + type: "string", + enum: ["off", "partial", "block", "progress"], + }, + ], + }, + streamMode: { + type: "string", + enum: ["partial", "block", "off"], + }, + draftChunk: { + type: "object", + properties: { + minChars: { + type: "integer", + exclusiveMinimum: 0, + maximum: 9007199254740991, + }, + maxChars: { + type: "integer", + exclusiveMinimum: 0, + maximum: 9007199254740991, + }, + breakPreference: { + anyOf: [ + { + type: "string", + const: "paragraph", + }, + { + type: "string", + const: "newline", + }, + { + type: "string", + const: "sentence", + }, + ], + }, + }, + additionalProperties: false, + }, + maxLinesPerMessage: { + type: "integer", + exclusiveMinimum: 0, + maximum: 9007199254740991, + }, + mediaMaxMb: { + type: "number", + exclusiveMinimum: 0, + }, + retry: { + type: "object", + properties: { + attempts: { + type: "integer", + minimum: 1, + maximum: 9007199254740991, + }, + minDelayMs: { + type: "integer", + minimum: 0, + maximum: 9007199254740991, + }, + maxDelayMs: { + type: "integer", + minimum: 0, + maximum: 9007199254740991, + }, + jitter: { + type: "number", + minimum: 0, + maximum: 1, + }, + }, + additionalProperties: false, + }, + actions: { + type: "object", + properties: { + reactions: { + type: "boolean", + }, + stickers: { + type: "boolean", + }, + emojiUploads: { + type: "boolean", + }, + stickerUploads: { + type: "boolean", + }, + polls: { + type: "boolean", + }, + permissions: { + type: "boolean", + }, + messages: { + type: "boolean", + }, + threads: { + type: "boolean", + }, + pins: { + type: "boolean", + }, + search: { + type: "boolean", + }, + memberInfo: { + type: "boolean", + }, + roleInfo: { + type: "boolean", + }, + roles: { + type: "boolean", + }, + channelInfo: { + type: "boolean", + }, + voiceStatus: { + type: "boolean", + }, + events: { + type: "boolean", + }, + moderation: { + type: "boolean", + }, + channels: { + type: "boolean", + }, + presence: { + type: "boolean", + }, + }, + additionalProperties: false, + }, + replyToMode: { + anyOf: [ + { + type: "string", + const: "off", + }, + { + type: "string", + const: "first", + }, + { + type: "string", + const: "all", + }, + ], + }, + dmPolicy: { + type: "string", + enum: ["pairing", "allowlist", "open", "disabled"], + }, + allowFrom: { + type: "array", + items: { + anyOf: [ + { + type: "string", + }, + { + type: "number", + }, + ], + }, + }, + defaultTo: { + type: "string", + }, + dm: { + type: "object", + properties: { + enabled: { + type: "boolean", + }, + policy: { + type: "string", + enum: ["pairing", "allowlist", "open", "disabled"], + }, + allowFrom: { + type: "array", + items: { + anyOf: [ + { + type: "string", + }, + { + type: "number", + }, + ], + }, + }, + groupEnabled: { + type: "boolean", + }, + groupChannels: { + type: "array", + items: { + anyOf: [ + { + type: "string", + }, + { + type: "number", + }, + ], + }, + }, + }, + additionalProperties: false, + }, + guilds: { + type: "object", + propertyNames: { + type: "string", + }, + additionalProperties: { + type: "object", + properties: { + slug: { + type: "string", + }, + requireMention: { + type: "boolean", + }, + ignoreOtherMentions: { + type: "boolean", + }, + tools: { + type: "object", + properties: { + allow: { + type: "array", + items: { + type: "string", + }, + }, + alsoAllow: { + type: "array", + items: { + type: "string", + }, + }, + deny: { + type: "array", + items: { + type: "string", + }, + }, + }, + additionalProperties: false, + }, + toolsBySender: { + type: "object", + propertyNames: { + type: "string", + }, + additionalProperties: { + type: "object", + properties: { + allow: { + type: "array", + items: { + type: "string", + }, + }, + alsoAllow: { + type: "array", + items: { + type: "string", + }, + }, + deny: { + type: "array", + items: { + type: "string", + }, + }, + }, + additionalProperties: false, + }, + }, + reactionNotifications: { + type: "string", + enum: ["off", "own", "all", "allowlist"], + }, + users: { + type: "array", + items: { + anyOf: [ + { + type: "string", + }, + { + type: "number", + }, + ], + }, + }, + roles: { + type: "array", + items: { + anyOf: [ + { + type: "string", + }, + { + type: "number", + }, + ], + }, + }, + channels: { + type: "object", + propertyNames: { + type: "string", + }, + additionalProperties: { + type: "object", + properties: { + allow: { + type: "boolean", + }, + requireMention: { + type: "boolean", + }, + ignoreOtherMentions: { + type: "boolean", + }, + tools: { + type: "object", + properties: { + allow: { + type: "array", + items: { + type: "string", + }, + }, + alsoAllow: { + type: "array", + items: { + type: "string", + }, + }, + deny: { + type: "array", + items: { + type: "string", + }, + }, + }, + additionalProperties: false, + }, + toolsBySender: { + type: "object", + propertyNames: { + type: "string", + }, + additionalProperties: { + type: "object", + properties: { + allow: { + type: "array", + items: { + type: "string", + }, + }, + alsoAllow: { + type: "array", + items: { + type: "string", + }, + }, + deny: { + type: "array", + items: { + type: "string", + }, + }, + }, + additionalProperties: false, + }, + }, + skills: { + type: "array", + items: { + type: "string", + }, + }, + enabled: { + type: "boolean", + }, + users: { + type: "array", + items: { + anyOf: [ + { + type: "string", + }, + { + type: "number", + }, + ], + }, + }, + roles: { + type: "array", + items: { + anyOf: [ + { + type: "string", + }, + { + type: "number", + }, + ], + }, + }, + systemPrompt: { + type: "string", + }, + includeThreadStarter: { + type: "boolean", + }, + autoThread: { + type: "boolean", + }, + autoThreadName: { + type: "string", + enum: ["message", "generated"], + }, + autoArchiveDuration: { + anyOf: [ + { + type: "string", + enum: ["60", "1440", "4320", "10080"], + }, + { + type: "number", + const: 60, + }, + { + type: "number", + const: 1440, + }, + { + type: "number", + const: 4320, + }, + { + type: "number", + const: 10080, + }, + ], + }, + }, + additionalProperties: false, + }, + }, + }, + additionalProperties: false, + }, + }, + heartbeat: { + type: "object", + properties: { + showOk: { + type: "boolean", + }, + showAlerts: { + type: "boolean", + }, + useIndicator: { + type: "boolean", + }, + }, + additionalProperties: false, + }, + healthMonitor: { + type: "object", + properties: { + enabled: { + type: "boolean", + }, + }, + additionalProperties: false, + }, + execApprovals: { + type: "object", + properties: { + enabled: { + type: "boolean", + }, + approvers: { + type: "array", + items: { + anyOf: [ + { + type: "string", + }, + { + type: "number", + }, + ], + }, + }, + agentFilter: { + type: "array", + items: { + type: "string", + }, + }, + sessionFilter: { + type: "array", + items: { + type: "string", + }, + }, + cleanupAfterResolve: { + type: "boolean", + }, + target: { + type: "string", + enum: ["dm", "channel", "both"], + }, + }, + additionalProperties: false, + }, + agentComponents: { + type: "object", + properties: { + enabled: { + type: "boolean", + }, + }, + additionalProperties: false, + }, + ui: { + type: "object", + properties: { + components: { + type: "object", + properties: { + accentColor: { + type: "string", + pattern: "^#?[0-9a-fA-F]{6}$", + }, + }, + additionalProperties: false, + }, + }, + additionalProperties: false, + }, + slashCommand: { + type: "object", + properties: { + ephemeral: { + type: "boolean", + }, + }, + additionalProperties: false, + }, + threadBindings: { + type: "object", + properties: { + enabled: { + type: "boolean", + }, + idleHours: { + type: "number", + minimum: 0, + }, + maxAgeHours: { + type: "number", + minimum: 0, + }, + spawnSubagentSessions: { + type: "boolean", + }, + spawnAcpSessions: { + type: "boolean", + }, + }, + additionalProperties: false, + }, + intents: { + type: "object", + properties: { + presence: { + type: "boolean", + }, + guildMembers: { + type: "boolean", + }, + }, + additionalProperties: false, + }, + voice: { + type: "object", + properties: { + enabled: { + type: "boolean", + }, + autoJoin: { + type: "array", + items: { + type: "object", + properties: { + guildId: { + type: "string", + minLength: 1, + }, + channelId: { + type: "string", + minLength: 1, + }, + }, + required: ["guildId", "channelId"], + additionalProperties: false, + }, + }, + daveEncryption: { + type: "boolean", + }, + decryptionFailureTolerance: { + type: "integer", + minimum: 0, + maximum: 9007199254740991, + }, + tts: { + type: "object", + properties: { + auto: { + type: "string", + enum: ["off", "always", "inbound", "tagged"], + }, + enabled: { + type: "boolean", + }, + mode: { + type: "string", + enum: ["final", "all"], + }, + provider: { + type: "string", + minLength: 1, + }, + summaryModel: { + type: "string", + }, + modelOverrides: { + type: "object", + properties: { + enabled: { + type: "boolean", + }, + allowText: { + type: "boolean", + }, + allowProvider: { + type: "boolean", + }, + allowVoice: { + type: "boolean", + }, + allowModelId: { + type: "boolean", + }, + allowVoiceSettings: { + type: "boolean", + }, + allowNormalization: { + type: "boolean", + }, + allowSeed: { + type: "boolean", + }, + }, + additionalProperties: false, + }, + providers: { + type: "object", + propertyNames: { + type: "string", + }, + additionalProperties: { + type: "object", + properties: { + apiKey: { + anyOf: [ + { + type: "string", + }, + { + oneOf: [ + { + type: "object", + properties: { + source: { + type: "string", + const: "env", + }, + provider: { + type: "string", + pattern: "^[a-z][a-z0-9_-]{0,63}$", + }, + id: { + type: "string", + pattern: "^[A-Z][A-Z0-9_]{0,127}$", + }, + }, + required: ["source", "provider", "id"], + additionalProperties: false, + }, + { + type: "object", + properties: { + source: { + type: "string", + const: "file", + }, + provider: { + type: "string", + pattern: "^[a-z][a-z0-9_-]{0,63}$", + }, + id: { + type: "string", + }, + }, + required: ["source", "provider", "id"], + additionalProperties: false, + }, + { + type: "object", + properties: { + source: { + type: "string", + const: "exec", + }, + provider: { + type: "string", + pattern: "^[a-z][a-z0-9_-]{0,63}$", + }, + id: { + type: "string", + }, + }, + required: ["source", "provider", "id"], + additionalProperties: false, + }, + ], + }, + ], + }, + }, + additionalProperties: { + anyOf: [ + { + type: "string", + }, + { + type: "number", + }, + { + type: "boolean", + }, + { + type: "null", + }, + { + type: "array", + items: {}, + }, + { + type: "object", + propertyNames: { + type: "string", + }, + additionalProperties: {}, + }, + ], + }, + }, + }, + prefsPath: { + type: "string", + }, + maxTextLength: { + type: "integer", + minimum: 1, + maximum: 9007199254740991, + }, + timeoutMs: { + type: "integer", + minimum: 1000, + maximum: 120000, + }, + }, + additionalProperties: false, + }, + }, + additionalProperties: false, + }, + pluralkit: { + type: "object", + properties: { + enabled: { + type: "boolean", + }, + token: { + anyOf: [ + { + type: "string", + }, + { + oneOf: [ + { + type: "object", + properties: { + source: { + type: "string", + const: "env", + }, + provider: { + type: "string", + pattern: "^[a-z][a-z0-9_-]{0,63}$", + }, + id: { + type: "string", + pattern: "^[A-Z][A-Z0-9_]{0,127}$", + }, + }, + required: ["source", "provider", "id"], + additionalProperties: false, + }, + { + type: "object", + properties: { + source: { + type: "string", + const: "file", + }, + provider: { + type: "string", + pattern: "^[a-z][a-z0-9_-]{0,63}$", + }, + id: { + type: "string", + }, + }, + required: ["source", "provider", "id"], + additionalProperties: false, + }, + { + type: "object", + properties: { + source: { + type: "string", + const: "exec", + }, + provider: { + type: "string", + pattern: "^[a-z][a-z0-9_-]{0,63}$", + }, + id: { + type: "string", + }, + }, + required: ["source", "provider", "id"], + additionalProperties: false, + }, + ], + }, + ], + }, + }, + additionalProperties: false, + }, + responsePrefix: { + type: "string", + }, + ackReaction: { + type: "string", + }, + ackReactionScope: { + type: "string", + enum: ["group-mentions", "group-all", "direct", "all", "off", "none"], + }, + activity: { + type: "string", + }, + status: { + type: "string", + enum: ["online", "dnd", "idle", "invisible"], + }, + autoPresence: { + type: "object", + properties: { + enabled: { + type: "boolean", + }, + intervalMs: { + type: "integer", + exclusiveMinimum: 0, + maximum: 9007199254740991, + }, + minUpdateIntervalMs: { + type: "integer", + exclusiveMinimum: 0, + maximum: 9007199254740991, + }, + healthyText: { + type: "string", + }, + degradedText: { + type: "string", + }, + exhaustedText: { + type: "string", + }, + }, + additionalProperties: false, + }, + activityType: { + anyOf: [ + { + type: "number", + const: 0, + }, + { + type: "number", + const: 1, + }, + { + type: "number", + const: 2, + }, + { + type: "number", + const: 3, + }, + { + type: "number", + const: 4, + }, + { + type: "number", + const: 5, + }, + ], + }, + activityUrl: { + type: "string", + format: "uri", + }, + inboundWorker: { + type: "object", + properties: { + runTimeoutMs: { + type: "integer", + minimum: 0, + maximum: 9007199254740991, + }, + }, + additionalProperties: false, + }, + eventQueue: { + type: "object", + properties: { + listenerTimeout: { + type: "integer", + exclusiveMinimum: 0, + maximum: 9007199254740991, + }, + maxQueueSize: { + type: "integer", + exclusiveMinimum: 0, + maximum: 9007199254740991, + }, + maxConcurrency: { + type: "integer", + exclusiveMinimum: 0, + maximum: 9007199254740991, + }, + }, + additionalProperties: false, + }, + }, + required: ["groupPolicy"], + additionalProperties: false, + }, + }, + defaultAccount: { + type: "string", + }, + }, + required: ["groupPolicy"], + additionalProperties: false, + }, + uiHints: { + "": { + label: "Discord", + help: "Discord channel provider configuration for bot auth, retry policy, streaming, thread bindings, and optional voice capabilities. Keep privileged intents and advanced features disabled unless needed.", + }, + dmPolicy: { + label: "Discord DM Policy", + help: 'Direct message access control ("pairing" recommended). "open" requires channels.discord.allowFrom=["*"].', + }, + "dm.policy": { + label: "Discord DM Policy", + help: 'Direct message access control ("pairing" recommended). "open" requires channels.discord.allowFrom=["*"] (legacy: channels.discord.dm.allowFrom).', + }, + configWrites: { + label: "Discord Config Writes", + help: "Allow Discord to write config in response to channel events/commands (default: true).", + }, + proxy: { + label: "Discord Proxy URL", + help: "Proxy URL for Discord gateway + API requests (app-id lookup and allowlist resolution). Set per account via channels.discord.accounts..proxy.", + }, + "commands.native": { + label: "Discord Native Commands", + help: 'Override native commands for Discord (bool or "auto").', + }, + "commands.nativeSkills": { + label: "Discord Native Skill Commands", + help: 'Override native skill commands for Discord (bool or "auto").', + }, + streaming: { + label: "Discord Streaming Mode", + help: 'Unified Discord stream preview mode: "off" | "partial" | "block" | "progress". "progress" maps to "partial" on Discord. Legacy boolean/streamMode keys are auto-mapped.', + }, + streamMode: { + label: "Discord Stream Mode (Legacy)", + help: "Legacy Discord preview mode alias (off | partial | block); auto-migrated to channels.discord.streaming.", + }, + "draftChunk.minChars": { + label: "Discord Draft Chunk Min Chars", + help: 'Minimum chars before emitting a Discord stream preview update when channels.discord.streaming="block" (default: 200).', + }, + "draftChunk.maxChars": { + label: "Discord Draft Chunk Max Chars", + help: 'Target max size for a Discord stream preview chunk when channels.discord.streaming="block" (default: 800; clamped to channels.discord.textChunkLimit).', + }, + "draftChunk.breakPreference": { + label: "Discord Draft Chunk Break Preference", + help: "Preferred breakpoints for Discord draft chunks (paragraph | newline | sentence). Default: paragraph.", + }, + "retry.attempts": { + label: "Discord Retry Attempts", + help: "Max retry attempts for outbound Discord API calls (default: 3).", + }, + "retry.minDelayMs": { + label: "Discord Retry Min Delay (ms)", + help: "Minimum retry delay in ms for Discord outbound calls.", + }, + "retry.maxDelayMs": { + label: "Discord Retry Max Delay (ms)", + help: "Maximum retry delay cap in ms for Discord outbound calls.", + }, + "retry.jitter": { + label: "Discord Retry Jitter", + help: "Jitter factor (0-1) applied to Discord retry delays.", + }, + maxLinesPerMessage: { + label: "Discord Max Lines Per Message", + help: "Soft max line count per Discord message (default: 17).", + }, + "inboundWorker.runTimeoutMs": { + label: "Discord Inbound Worker Timeout (ms)", + help: "Optional queued Discord inbound worker timeout in ms. This is separate from Carbon listener timeouts; defaults to 1800000 and can be disabled with 0. Set per account via channels.discord.accounts..inboundWorker.runTimeoutMs.", + }, + "eventQueue.listenerTimeout": { + label: "Discord EventQueue Listener Timeout (ms)", + help: "Canonical Discord listener timeout control in ms for gateway normalization/enqueue handlers. Default is 120000 in OpenClaw; set per account via channels.discord.accounts..eventQueue.listenerTimeout.", + }, + "eventQueue.maxQueueSize": { + label: "Discord EventQueue Max Queue Size", + help: "Optional Discord EventQueue capacity override (max queued events before backpressure). Set per account via channels.discord.accounts..eventQueue.maxQueueSize.", + }, + "eventQueue.maxConcurrency": { + label: "Discord EventQueue Max Concurrency", + help: "Optional Discord EventQueue concurrency override (max concurrent handler executions). Set per account via channels.discord.accounts..eventQueue.maxConcurrency.", + }, + "threadBindings.enabled": { + label: "Discord Thread Binding Enabled", + help: "Enable Discord thread binding features (/focus, bound-thread routing/delivery, and thread-bound subagent sessions). Overrides session.threadBindings.enabled when set.", + }, + "threadBindings.idleHours": { + label: "Discord Thread Binding Idle Timeout (hours)", + help: "Inactivity window in hours for Discord thread-bound sessions (/focus and spawned thread sessions). Set 0 to disable idle auto-unfocus (default: 24). Overrides session.threadBindings.idleHours when set.", + }, + "threadBindings.maxAgeHours": { + label: "Discord Thread Binding Max Age (hours)", + help: "Optional hard max age in hours for Discord thread-bound sessions. Set 0 to disable hard cap (default: 0). Overrides session.threadBindings.maxAgeHours when set.", + }, + "threadBindings.spawnSubagentSessions": { + label: "Discord Thread-Bound Subagent Spawn", + help: "Allow subagent spawns with thread=true to auto-create and bind Discord threads (default: false; opt-in). Set true to enable thread-bound subagent spawns for this account/channel.", + }, + "threadBindings.spawnAcpSessions": { + label: "Discord Thread-Bound ACP Spawn", + help: "Allow /acp spawn to auto-create and bind Discord threads for ACP sessions (default: false; opt-in). Set true to enable thread-bound ACP spawns for this account/channel.", + }, + "ui.components.accentColor": { + label: "Discord Component Accent Color", + help: "Accent color for Discord component containers (hex). Set per account via channels.discord.accounts..ui.components.accentColor.", + }, + "intents.presence": { + label: "Discord Presence Intent", + help: "Enable the Guild Presences privileged intent. Must also be enabled in the Discord Developer Portal. Allows tracking user activities (e.g. Spotify). Default: false.", + }, + "intents.guildMembers": { + label: "Discord Guild Members Intent", + help: "Enable the Guild Members privileged intent. Must also be enabled in the Discord Developer Portal. Default: false.", + }, + "voice.enabled": { + label: "Discord Voice Enabled", + help: "Enable Discord voice channel conversations (default: true). Omit channels.discord.voice to keep voice support disabled for the account.", + }, + "voice.autoJoin": { + label: "Discord Voice Auto-Join", + help: "Voice channels to auto-join on startup (list of guildId/channelId entries).", + }, + "voice.daveEncryption": { + label: "Discord Voice DAVE Encryption", + help: "Toggle DAVE end-to-end encryption for Discord voice joins (default: true in @discordjs/voice; Discord may require this).", + }, + "voice.decryptionFailureTolerance": { + label: "Discord Voice Decrypt Failure Tolerance", + help: "Consecutive decrypt failures before DAVE attempts session recovery (passed to @discordjs/voice; default: 24).", + }, + "voice.tts": { + label: "Discord Voice Text-to-Speech", + help: "Optional TTS overrides for Discord voice playback (merged with messages.tts).", + }, + "pluralkit.enabled": { + label: "Discord PluralKit Enabled", + help: "Resolve PluralKit proxied messages and treat system members as distinct senders.", + }, + "pluralkit.token": { + label: "Discord PluralKit Token", + help: "Optional PluralKit token for resolving private systems or members.", + }, + activity: { + label: "Discord Presence Activity", + help: "Discord presence activity text (defaults to custom status).", + }, + status: { + label: "Discord Presence Status", + help: "Discord presence status (online, dnd, idle, invisible).", + }, + "autoPresence.enabled": { + label: "Discord Auto Presence Enabled", + help: "Enable automatic Discord bot presence updates based on runtime/model availability signals. When enabled: healthy=>online, degraded/unknown=>idle, exhausted/unavailable=>dnd.", + }, + "autoPresence.intervalMs": { + label: "Discord Auto Presence Check Interval (ms)", + help: "How often to evaluate Discord auto-presence state in milliseconds (default: 30000).", + }, + "autoPresence.minUpdateIntervalMs": { + label: "Discord Auto Presence Min Update Interval (ms)", + help: "Minimum time between actual Discord presence update calls in milliseconds (default: 15000). Prevents status spam on noisy state changes.", + }, + "autoPresence.healthyText": { + label: "Discord Auto Presence Healthy Text", + help: "Optional custom status text while runtime is healthy (online). If omitted, falls back to static channels.discord.activity when set.", + }, + "autoPresence.degradedText": { + label: "Discord Auto Presence Degraded Text", + help: "Optional custom status text while runtime/model availability is degraded or unknown (idle).", + }, + "autoPresence.exhaustedText": { + label: "Discord Auto Presence Exhausted Text", + help: "Optional custom status text while runtime detects exhausted/unavailable model quota (dnd). Supports {reason} template placeholder.", + }, + activityType: { + label: "Discord Presence Activity Type", + help: "Discord presence activity type (0=Playing,1=Streaming,2=Listening,3=Watching,4=Custom,5=Competing).", + }, + activityUrl: { + label: "Discord Presence Activity URL", + help: "Discord presence streaming URL (required for activityType=1).", + }, + allowBots: { + label: "Discord Allow Bot Messages", + help: 'Allow bot-authored messages to trigger Discord replies (default: false). Set "mentions" to only accept bot messages that mention the bot.', + }, + token: { + label: "Discord Bot Token", + help: "Discord bot token used for gateway and REST API authentication for this provider account. Keep this secret out of committed config and rotate immediately after any leak.", + }, + }, + label: "Discord", + description: "very well supported right now.", + }, + }, }, }, { @@ -1045,6 +4174,1119 @@ export const GENERATED_BUNDLED_PLUGIN_METADATA = [ }, channels: ["feishu"], skills: ["./skills"], + channelConfigs: { + feishu: { + schema: { + $schema: "http://json-schema.org/draft-07/schema#", + type: "object", + properties: { + enabled: { + type: "boolean", + }, + defaultAccount: { + type: "string", + }, + appId: { + type: "string", + }, + appSecret: { + anyOf: [ + { + type: "string", + }, + { + oneOf: [ + { + type: "object", + properties: { + source: { + type: "string", + const: "env", + }, + provider: { + type: "string", + pattern: "^[a-z][a-z0-9_-]{0,63}$", + }, + id: { + type: "string", + pattern: "^[A-Z][A-Z0-9_]{0,127}$", + }, + }, + required: ["source", "provider", "id"], + additionalProperties: false, + }, + { + type: "object", + properties: { + source: { + type: "string", + const: "file", + }, + provider: { + type: "string", + pattern: "^[a-z][a-z0-9_-]{0,63}$", + }, + id: { + type: "string", + }, + }, + required: ["source", "provider", "id"], + additionalProperties: false, + }, + { + type: "object", + properties: { + source: { + type: "string", + const: "exec", + }, + provider: { + type: "string", + pattern: "^[a-z][a-z0-9_-]{0,63}$", + }, + id: { + type: "string", + }, + }, + required: ["source", "provider", "id"], + additionalProperties: false, + }, + ], + }, + ], + }, + encryptKey: { + anyOf: [ + { + type: "string", + }, + { + oneOf: [ + { + type: "object", + properties: { + source: { + type: "string", + const: "env", + }, + provider: { + type: "string", + pattern: "^[a-z][a-z0-9_-]{0,63}$", + }, + id: { + type: "string", + pattern: "^[A-Z][A-Z0-9_]{0,127}$", + }, + }, + required: ["source", "provider", "id"], + additionalProperties: false, + }, + { + type: "object", + properties: { + source: { + type: "string", + const: "file", + }, + provider: { + type: "string", + pattern: "^[a-z][a-z0-9_-]{0,63}$", + }, + id: { + type: "string", + }, + }, + required: ["source", "provider", "id"], + additionalProperties: false, + }, + { + type: "object", + properties: { + source: { + type: "string", + const: "exec", + }, + provider: { + type: "string", + pattern: "^[a-z][a-z0-9_-]{0,63}$", + }, + id: { + type: "string", + }, + }, + required: ["source", "provider", "id"], + additionalProperties: false, + }, + ], + }, + ], + }, + verificationToken: { + anyOf: [ + { + type: "string", + }, + { + oneOf: [ + { + type: "object", + properties: { + source: { + type: "string", + const: "env", + }, + provider: { + type: "string", + pattern: "^[a-z][a-z0-9_-]{0,63}$", + }, + id: { + type: "string", + pattern: "^[A-Z][A-Z0-9_]{0,127}$", + }, + }, + required: ["source", "provider", "id"], + additionalProperties: false, + }, + { + type: "object", + properties: { + source: { + type: "string", + const: "file", + }, + provider: { + type: "string", + pattern: "^[a-z][a-z0-9_-]{0,63}$", + }, + id: { + type: "string", + }, + }, + required: ["source", "provider", "id"], + additionalProperties: false, + }, + { + type: "object", + properties: { + source: { + type: "string", + const: "exec", + }, + provider: { + type: "string", + pattern: "^[a-z][a-z0-9_-]{0,63}$", + }, + id: { + type: "string", + }, + }, + required: ["source", "provider", "id"], + additionalProperties: false, + }, + ], + }, + ], + }, + domain: { + default: "feishu", + anyOf: [ + { + type: "string", + enum: ["feishu", "lark"], + }, + { + type: "string", + format: "uri", + pattern: "^https:\\/\\/.*", + }, + ], + }, + connectionMode: { + default: "websocket", + type: "string", + enum: ["websocket", "webhook"], + }, + webhookPath: { + default: "/feishu/events", + type: "string", + }, + webhookHost: { + type: "string", + }, + webhookPort: { + type: "integer", + exclusiveMinimum: 0, + maximum: 9007199254740991, + }, + capabilities: { + type: "array", + items: { + type: "string", + }, + }, + markdown: { + type: "object", + properties: { + mode: { + type: "string", + enum: ["native", "escape", "strip"], + }, + tableMode: { + type: "string", + enum: ["native", "ascii", "simple"], + }, + }, + additionalProperties: false, + }, + configWrites: { + type: "boolean", + }, + dmPolicy: { + default: "pairing", + type: "string", + enum: ["open", "pairing", "allowlist"], + }, + allowFrom: { + type: "array", + items: { + anyOf: [ + { + type: "string", + }, + { + type: "number", + }, + ], + }, + }, + groupPolicy: { + default: "allowlist", + anyOf: [ + { + type: "string", + enum: ["open", "allowlist", "disabled"], + }, + {}, + ], + }, + groupAllowFrom: { + type: "array", + items: { + anyOf: [ + { + type: "string", + }, + { + type: "number", + }, + ], + }, + }, + groupSenderAllowFrom: { + type: "array", + items: { + anyOf: [ + { + type: "string", + }, + { + type: "number", + }, + ], + }, + }, + requireMention: { + type: "boolean", + }, + groups: { + type: "object", + propertyNames: { + type: "string", + }, + additionalProperties: { + type: "object", + properties: { + requireMention: { + type: "boolean", + }, + tools: { + type: "object", + properties: { + allow: { + type: "array", + items: { + type: "string", + }, + }, + deny: { + type: "array", + items: { + type: "string", + }, + }, + }, + additionalProperties: false, + }, + skills: { + type: "array", + items: { + type: "string", + }, + }, + enabled: { + type: "boolean", + }, + allowFrom: { + type: "array", + items: { + anyOf: [ + { + type: "string", + }, + { + type: "number", + }, + ], + }, + }, + systemPrompt: { + type: "string", + }, + groupSessionScope: { + type: "string", + enum: ["group", "group_sender", "group_topic", "group_topic_sender"], + }, + topicSessionMode: { + type: "string", + enum: ["disabled", "enabled"], + }, + replyInThread: { + type: "string", + enum: ["disabled", "enabled"], + }, + }, + additionalProperties: false, + }, + }, + historyLimit: { + type: "integer", + minimum: 0, + maximum: 9007199254740991, + }, + dmHistoryLimit: { + type: "integer", + minimum: 0, + maximum: 9007199254740991, + }, + dms: { + type: "object", + propertyNames: { + type: "string", + }, + additionalProperties: { + type: "object", + properties: { + enabled: { + type: "boolean", + }, + systemPrompt: { + type: "string", + }, + }, + additionalProperties: false, + }, + }, + textChunkLimit: { + type: "integer", + exclusiveMinimum: 0, + maximum: 9007199254740991, + }, + chunkMode: { + type: "string", + enum: ["length", "newline"], + }, + blockStreamingCoalesce: { + type: "object", + properties: { + enabled: { + type: "boolean", + }, + minDelayMs: { + type: "integer", + exclusiveMinimum: 0, + maximum: 9007199254740991, + }, + maxDelayMs: { + type: "integer", + exclusiveMinimum: 0, + maximum: 9007199254740991, + }, + }, + additionalProperties: false, + }, + mediaMaxMb: { + type: "number", + exclusiveMinimum: 0, + }, + httpTimeoutMs: { + type: "integer", + exclusiveMinimum: 0, + maximum: 300000, + }, + heartbeat: { + type: "object", + properties: { + visibility: { + type: "string", + enum: ["visible", "hidden"], + }, + intervalMs: { + type: "integer", + exclusiveMinimum: 0, + maximum: 9007199254740991, + }, + }, + additionalProperties: false, + }, + renderMode: { + type: "string", + enum: ["auto", "raw", "card"], + }, + streaming: { + type: "boolean", + }, + tools: { + type: "object", + properties: { + doc: { + type: "boolean", + }, + chat: { + type: "boolean", + }, + wiki: { + type: "boolean", + }, + drive: { + type: "boolean", + }, + perm: { + type: "boolean", + }, + scopes: { + type: "boolean", + }, + }, + additionalProperties: false, + }, + actions: { + type: "object", + properties: { + reactions: { + type: "boolean", + }, + }, + additionalProperties: false, + }, + replyInThread: { + type: "string", + enum: ["disabled", "enabled"], + }, + reactionNotifications: { + default: "own", + type: "string", + enum: ["off", "own", "all"], + }, + typingIndicator: { + default: true, + type: "boolean", + }, + resolveSenderNames: { + default: true, + type: "boolean", + }, + groupSessionScope: { + type: "string", + enum: ["group", "group_sender", "group_topic", "group_topic_sender"], + }, + topicSessionMode: { + type: "string", + enum: ["disabled", "enabled"], + }, + dynamicAgentCreation: { + type: "object", + properties: { + enabled: { + type: "boolean", + }, + workspaceTemplate: { + type: "string", + }, + agentDirTemplate: { + type: "string", + }, + maxAgents: { + type: "integer", + exclusiveMinimum: 0, + maximum: 9007199254740991, + }, + }, + additionalProperties: false, + }, + accounts: { + type: "object", + propertyNames: { + type: "string", + }, + additionalProperties: { + type: "object", + properties: { + enabled: { + type: "boolean", + }, + name: { + type: "string", + }, + appId: { + type: "string", + }, + appSecret: { + anyOf: [ + { + type: "string", + }, + { + oneOf: [ + { + type: "object", + properties: { + source: { + type: "string", + const: "env", + }, + provider: { + type: "string", + pattern: "^[a-z][a-z0-9_-]{0,63}$", + }, + id: { + type: "string", + pattern: "^[A-Z][A-Z0-9_]{0,127}$", + }, + }, + required: ["source", "provider", "id"], + additionalProperties: false, + }, + { + type: "object", + properties: { + source: { + type: "string", + const: "file", + }, + provider: { + type: "string", + pattern: "^[a-z][a-z0-9_-]{0,63}$", + }, + id: { + type: "string", + }, + }, + required: ["source", "provider", "id"], + additionalProperties: false, + }, + { + type: "object", + properties: { + source: { + type: "string", + const: "exec", + }, + provider: { + type: "string", + pattern: "^[a-z][a-z0-9_-]{0,63}$", + }, + id: { + type: "string", + }, + }, + required: ["source", "provider", "id"], + additionalProperties: false, + }, + ], + }, + ], + }, + encryptKey: { + anyOf: [ + { + type: "string", + }, + { + oneOf: [ + { + type: "object", + properties: { + source: { + type: "string", + const: "env", + }, + provider: { + type: "string", + pattern: "^[a-z][a-z0-9_-]{0,63}$", + }, + id: { + type: "string", + pattern: "^[A-Z][A-Z0-9_]{0,127}$", + }, + }, + required: ["source", "provider", "id"], + additionalProperties: false, + }, + { + type: "object", + properties: { + source: { + type: "string", + const: "file", + }, + provider: { + type: "string", + pattern: "^[a-z][a-z0-9_-]{0,63}$", + }, + id: { + type: "string", + }, + }, + required: ["source", "provider", "id"], + additionalProperties: false, + }, + { + type: "object", + properties: { + source: { + type: "string", + const: "exec", + }, + provider: { + type: "string", + pattern: "^[a-z][a-z0-9_-]{0,63}$", + }, + id: { + type: "string", + }, + }, + required: ["source", "provider", "id"], + additionalProperties: false, + }, + ], + }, + ], + }, + verificationToken: { + anyOf: [ + { + type: "string", + }, + { + oneOf: [ + { + type: "object", + properties: { + source: { + type: "string", + const: "env", + }, + provider: { + type: "string", + pattern: "^[a-z][a-z0-9_-]{0,63}$", + }, + id: { + type: "string", + pattern: "^[A-Z][A-Z0-9_]{0,127}$", + }, + }, + required: ["source", "provider", "id"], + additionalProperties: false, + }, + { + type: "object", + properties: { + source: { + type: "string", + const: "file", + }, + provider: { + type: "string", + pattern: "^[a-z][a-z0-9_-]{0,63}$", + }, + id: { + type: "string", + }, + }, + required: ["source", "provider", "id"], + additionalProperties: false, + }, + { + type: "object", + properties: { + source: { + type: "string", + const: "exec", + }, + provider: { + type: "string", + pattern: "^[a-z][a-z0-9_-]{0,63}$", + }, + id: { + type: "string", + }, + }, + required: ["source", "provider", "id"], + additionalProperties: false, + }, + ], + }, + ], + }, + domain: { + anyOf: [ + { + type: "string", + enum: ["feishu", "lark"], + }, + { + type: "string", + format: "uri", + pattern: "^https:\\/\\/.*", + }, + ], + }, + connectionMode: { + type: "string", + enum: ["websocket", "webhook"], + }, + webhookPath: { + type: "string", + }, + webhookHost: { + type: "string", + }, + webhookPort: { + type: "integer", + exclusiveMinimum: 0, + maximum: 9007199254740991, + }, + capabilities: { + type: "array", + items: { + type: "string", + }, + }, + markdown: { + type: "object", + properties: { + mode: { + type: "string", + enum: ["native", "escape", "strip"], + }, + tableMode: { + type: "string", + enum: ["native", "ascii", "simple"], + }, + }, + additionalProperties: false, + }, + configWrites: { + type: "boolean", + }, + dmPolicy: { + type: "string", + enum: ["open", "pairing", "allowlist"], + }, + allowFrom: { + type: "array", + items: { + anyOf: [ + { + type: "string", + }, + { + type: "number", + }, + ], + }, + }, + groupPolicy: { + anyOf: [ + { + type: "string", + enum: ["open", "allowlist", "disabled"], + }, + {}, + ], + }, + groupAllowFrom: { + type: "array", + items: { + anyOf: [ + { + type: "string", + }, + { + type: "number", + }, + ], + }, + }, + groupSenderAllowFrom: { + type: "array", + items: { + anyOf: [ + { + type: "string", + }, + { + type: "number", + }, + ], + }, + }, + requireMention: { + type: "boolean", + }, + groups: { + type: "object", + propertyNames: { + type: "string", + }, + additionalProperties: { + type: "object", + properties: { + requireMention: { + type: "boolean", + }, + tools: { + type: "object", + properties: { + allow: { + type: "array", + items: { + type: "string", + }, + }, + deny: { + type: "array", + items: { + type: "string", + }, + }, + }, + additionalProperties: false, + }, + skills: { + type: "array", + items: { + type: "string", + }, + }, + enabled: { + type: "boolean", + }, + allowFrom: { + type: "array", + items: { + anyOf: [ + { + type: "string", + }, + { + type: "number", + }, + ], + }, + }, + systemPrompt: { + type: "string", + }, + groupSessionScope: { + type: "string", + enum: ["group", "group_sender", "group_topic", "group_topic_sender"], + }, + topicSessionMode: { + type: "string", + enum: ["disabled", "enabled"], + }, + replyInThread: { + type: "string", + enum: ["disabled", "enabled"], + }, + }, + additionalProperties: false, + }, + }, + historyLimit: { + type: "integer", + minimum: 0, + maximum: 9007199254740991, + }, + dmHistoryLimit: { + type: "integer", + minimum: 0, + maximum: 9007199254740991, + }, + dms: { + type: "object", + propertyNames: { + type: "string", + }, + additionalProperties: { + type: "object", + properties: { + enabled: { + type: "boolean", + }, + systemPrompt: { + type: "string", + }, + }, + additionalProperties: false, + }, + }, + textChunkLimit: { + type: "integer", + exclusiveMinimum: 0, + maximum: 9007199254740991, + }, + chunkMode: { + type: "string", + enum: ["length", "newline"], + }, + blockStreamingCoalesce: { + type: "object", + properties: { + enabled: { + type: "boolean", + }, + minDelayMs: { + type: "integer", + exclusiveMinimum: 0, + maximum: 9007199254740991, + }, + maxDelayMs: { + type: "integer", + exclusiveMinimum: 0, + maximum: 9007199254740991, + }, + }, + additionalProperties: false, + }, + mediaMaxMb: { + type: "number", + exclusiveMinimum: 0, + }, + httpTimeoutMs: { + type: "integer", + exclusiveMinimum: 0, + maximum: 300000, + }, + heartbeat: { + type: "object", + properties: { + visibility: { + type: "string", + enum: ["visible", "hidden"], + }, + intervalMs: { + type: "integer", + exclusiveMinimum: 0, + maximum: 9007199254740991, + }, + }, + additionalProperties: false, + }, + renderMode: { + type: "string", + enum: ["auto", "raw", "card"], + }, + streaming: { + type: "boolean", + }, + tools: { + type: "object", + properties: { + doc: { + type: "boolean", + }, + chat: { + type: "boolean", + }, + wiki: { + type: "boolean", + }, + drive: { + type: "boolean", + }, + perm: { + type: "boolean", + }, + scopes: { + type: "boolean", + }, + }, + additionalProperties: false, + }, + actions: { + type: "object", + properties: { + reactions: { + type: "boolean", + }, + }, + additionalProperties: false, + }, + replyInThread: { + type: "string", + enum: ["disabled", "enabled"], + }, + reactionNotifications: { + type: "string", + enum: ["off", "own", "all"], + }, + typingIndicator: { + type: "boolean", + }, + resolveSenderNames: { + type: "boolean", + }, + groupSessionScope: { + type: "string", + enum: ["group", "group_sender", "group_topic", "group_topic_sender"], + }, + topicSessionMode: { + type: "string", + enum: ["disabled", "enabled"], + }, + }, + additionalProperties: false, + }, + }, + }, + required: [ + "domain", + "connectionMode", + "webhookPath", + "dmPolicy", + "groupPolicy", + "reactionNotifications", + "typingIndicator", + "resolveSenderNames", + ], + additionalProperties: false, + }, + label: "Feishu", + description: "飞书/Lark enterprise messaging with doc/wiki/drive tools.", + }, + }, }, }, { @@ -1264,6 +5506,784 @@ export const GENERATED_BUNDLED_PLUGIN_METADATA = [ properties: {}, }, channels: ["googlechat"], + channelConfigs: { + googlechat: { + schema: { + $schema: "http://json-schema.org/draft-07/schema#", + type: "object", + properties: { + name: { + type: "string", + }, + capabilities: { + type: "array", + items: { + type: "string", + }, + }, + enabled: { + type: "boolean", + }, + configWrites: { + type: "boolean", + }, + allowBots: { + type: "boolean", + }, + dangerouslyAllowNameMatching: { + type: "boolean", + }, + requireMention: { + type: "boolean", + }, + groupPolicy: { + default: "allowlist", + type: "string", + enum: ["open", "disabled", "allowlist"], + }, + groupAllowFrom: { + type: "array", + items: { + anyOf: [ + { + type: "string", + }, + { + type: "number", + }, + ], + }, + }, + groups: { + type: "object", + propertyNames: { + type: "string", + }, + additionalProperties: { + type: "object", + properties: { + enabled: { + type: "boolean", + }, + allow: { + type: "boolean", + }, + requireMention: { + type: "boolean", + }, + users: { + type: "array", + items: { + anyOf: [ + { + type: "string", + }, + { + type: "number", + }, + ], + }, + }, + systemPrompt: { + type: "string", + }, + }, + additionalProperties: false, + }, + }, + defaultTo: { + type: "string", + }, + serviceAccount: { + anyOf: [ + { + type: "string", + }, + { + type: "object", + propertyNames: { + type: "string", + }, + additionalProperties: {}, + }, + { + oneOf: [ + { + type: "object", + properties: { + source: { + type: "string", + const: "env", + }, + provider: { + type: "string", + pattern: "^[a-z][a-z0-9_-]{0,63}$", + }, + id: { + type: "string", + pattern: "^[A-Z][A-Z0-9_]{0,127}$", + }, + }, + required: ["source", "provider", "id"], + additionalProperties: false, + }, + { + type: "object", + properties: { + source: { + type: "string", + const: "file", + }, + provider: { + type: "string", + pattern: "^[a-z][a-z0-9_-]{0,63}$", + }, + id: { + type: "string", + }, + }, + required: ["source", "provider", "id"], + additionalProperties: false, + }, + { + type: "object", + properties: { + source: { + type: "string", + const: "exec", + }, + provider: { + type: "string", + pattern: "^[a-z][a-z0-9_-]{0,63}$", + }, + id: { + type: "string", + }, + }, + required: ["source", "provider", "id"], + additionalProperties: false, + }, + ], + }, + ], + }, + serviceAccountRef: { + oneOf: [ + { + type: "object", + properties: { + source: { + type: "string", + const: "env", + }, + provider: { + type: "string", + pattern: "^[a-z][a-z0-9_-]{0,63}$", + }, + id: { + type: "string", + pattern: "^[A-Z][A-Z0-9_]{0,127}$", + }, + }, + required: ["source", "provider", "id"], + additionalProperties: false, + }, + { + type: "object", + properties: { + source: { + type: "string", + const: "file", + }, + provider: { + type: "string", + pattern: "^[a-z][a-z0-9_-]{0,63}$", + }, + id: { + type: "string", + }, + }, + required: ["source", "provider", "id"], + additionalProperties: false, + }, + { + type: "object", + properties: { + source: { + type: "string", + const: "exec", + }, + provider: { + type: "string", + pattern: "^[a-z][a-z0-9_-]{0,63}$", + }, + id: { + type: "string", + }, + }, + required: ["source", "provider", "id"], + additionalProperties: false, + }, + ], + }, + serviceAccountFile: { + type: "string", + }, + audienceType: { + type: "string", + enum: ["app-url", "project-number"], + }, + audience: { + type: "string", + }, + appPrincipal: { + type: "string", + }, + webhookPath: { + type: "string", + }, + webhookUrl: { + type: "string", + }, + botUser: { + type: "string", + }, + historyLimit: { + type: "integer", + minimum: 0, + maximum: 9007199254740991, + }, + dmHistoryLimit: { + type: "integer", + minimum: 0, + maximum: 9007199254740991, + }, + dms: { + type: "object", + propertyNames: { + type: "string", + }, + additionalProperties: { + type: "object", + properties: { + historyLimit: { + type: "integer", + minimum: 0, + maximum: 9007199254740991, + }, + }, + additionalProperties: false, + }, + }, + textChunkLimit: { + type: "integer", + exclusiveMinimum: 0, + maximum: 9007199254740991, + }, + chunkMode: { + type: "string", + enum: ["length", "newline"], + }, + blockStreaming: { + type: "boolean", + }, + blockStreamingCoalesce: { + type: "object", + properties: { + minChars: { + type: "integer", + exclusiveMinimum: 0, + maximum: 9007199254740991, + }, + maxChars: { + type: "integer", + exclusiveMinimum: 0, + maximum: 9007199254740991, + }, + idleMs: { + type: "integer", + minimum: 0, + maximum: 9007199254740991, + }, + }, + additionalProperties: false, + }, + streamMode: { + default: "replace", + type: "string", + enum: ["replace", "status_final", "append"], + }, + mediaMaxMb: { + type: "number", + exclusiveMinimum: 0, + }, + replyToMode: { + anyOf: [ + { + type: "string", + const: "off", + }, + { + type: "string", + const: "first", + }, + { + type: "string", + const: "all", + }, + ], + }, + actions: { + type: "object", + properties: { + reactions: { + type: "boolean", + }, + }, + additionalProperties: false, + }, + dm: { + type: "object", + properties: { + enabled: { + type: "boolean", + }, + policy: { + default: "pairing", + type: "string", + enum: ["pairing", "allowlist", "open", "disabled"], + }, + allowFrom: { + type: "array", + items: { + anyOf: [ + { + type: "string", + }, + { + type: "number", + }, + ], + }, + }, + }, + required: ["policy"], + additionalProperties: false, + }, + healthMonitor: { + type: "object", + properties: { + enabled: { + type: "boolean", + }, + }, + additionalProperties: false, + }, + typingIndicator: { + type: "string", + enum: ["none", "message", "reaction"], + }, + responsePrefix: { + type: "string", + }, + accounts: { + type: "object", + propertyNames: { + type: "string", + }, + additionalProperties: { + type: "object", + properties: { + name: { + type: "string", + }, + capabilities: { + type: "array", + items: { + type: "string", + }, + }, + enabled: { + type: "boolean", + }, + configWrites: { + type: "boolean", + }, + allowBots: { + type: "boolean", + }, + dangerouslyAllowNameMatching: { + type: "boolean", + }, + requireMention: { + type: "boolean", + }, + groupPolicy: { + default: "allowlist", + type: "string", + enum: ["open", "disabled", "allowlist"], + }, + groupAllowFrom: { + type: "array", + items: { + anyOf: [ + { + type: "string", + }, + { + type: "number", + }, + ], + }, + }, + groups: { + type: "object", + propertyNames: { + type: "string", + }, + additionalProperties: { + type: "object", + properties: { + enabled: { + type: "boolean", + }, + allow: { + type: "boolean", + }, + requireMention: { + type: "boolean", + }, + users: { + type: "array", + items: { + anyOf: [ + { + type: "string", + }, + { + type: "number", + }, + ], + }, + }, + systemPrompt: { + type: "string", + }, + }, + additionalProperties: false, + }, + }, + defaultTo: { + type: "string", + }, + serviceAccount: { + anyOf: [ + { + type: "string", + }, + { + type: "object", + propertyNames: { + type: "string", + }, + additionalProperties: {}, + }, + { + oneOf: [ + { + type: "object", + properties: { + source: { + type: "string", + const: "env", + }, + provider: { + type: "string", + pattern: "^[a-z][a-z0-9_-]{0,63}$", + }, + id: { + type: "string", + pattern: "^[A-Z][A-Z0-9_]{0,127}$", + }, + }, + required: ["source", "provider", "id"], + additionalProperties: false, + }, + { + type: "object", + properties: { + source: { + type: "string", + const: "file", + }, + provider: { + type: "string", + pattern: "^[a-z][a-z0-9_-]{0,63}$", + }, + id: { + type: "string", + }, + }, + required: ["source", "provider", "id"], + additionalProperties: false, + }, + { + type: "object", + properties: { + source: { + type: "string", + const: "exec", + }, + provider: { + type: "string", + pattern: "^[a-z][a-z0-9_-]{0,63}$", + }, + id: { + type: "string", + }, + }, + required: ["source", "provider", "id"], + additionalProperties: false, + }, + ], + }, + ], + }, + serviceAccountRef: { + oneOf: [ + { + type: "object", + properties: { + source: { + type: "string", + const: "env", + }, + provider: { + type: "string", + pattern: "^[a-z][a-z0-9_-]{0,63}$", + }, + id: { + type: "string", + pattern: "^[A-Z][A-Z0-9_]{0,127}$", + }, + }, + required: ["source", "provider", "id"], + additionalProperties: false, + }, + { + type: "object", + properties: { + source: { + type: "string", + const: "file", + }, + provider: { + type: "string", + pattern: "^[a-z][a-z0-9_-]{0,63}$", + }, + id: { + type: "string", + }, + }, + required: ["source", "provider", "id"], + additionalProperties: false, + }, + { + type: "object", + properties: { + source: { + type: "string", + const: "exec", + }, + provider: { + type: "string", + pattern: "^[a-z][a-z0-9_-]{0,63}$", + }, + id: { + type: "string", + }, + }, + required: ["source", "provider", "id"], + additionalProperties: false, + }, + ], + }, + serviceAccountFile: { + type: "string", + }, + audienceType: { + type: "string", + enum: ["app-url", "project-number"], + }, + audience: { + type: "string", + }, + appPrincipal: { + type: "string", + }, + webhookPath: { + type: "string", + }, + webhookUrl: { + type: "string", + }, + botUser: { + type: "string", + }, + historyLimit: { + type: "integer", + minimum: 0, + maximum: 9007199254740991, + }, + dmHistoryLimit: { + type: "integer", + minimum: 0, + maximum: 9007199254740991, + }, + dms: { + type: "object", + propertyNames: { + type: "string", + }, + additionalProperties: { + type: "object", + properties: { + historyLimit: { + type: "integer", + minimum: 0, + maximum: 9007199254740991, + }, + }, + additionalProperties: false, + }, + }, + textChunkLimit: { + type: "integer", + exclusiveMinimum: 0, + maximum: 9007199254740991, + }, + chunkMode: { + type: "string", + enum: ["length", "newline"], + }, + blockStreaming: { + type: "boolean", + }, + blockStreamingCoalesce: { + type: "object", + properties: { + minChars: { + type: "integer", + exclusiveMinimum: 0, + maximum: 9007199254740991, + }, + maxChars: { + type: "integer", + exclusiveMinimum: 0, + maximum: 9007199254740991, + }, + idleMs: { + type: "integer", + minimum: 0, + maximum: 9007199254740991, + }, + }, + additionalProperties: false, + }, + streamMode: { + default: "replace", + type: "string", + enum: ["replace", "status_final", "append"], + }, + mediaMaxMb: { + type: "number", + exclusiveMinimum: 0, + }, + replyToMode: { + anyOf: [ + { + type: "string", + const: "off", + }, + { + type: "string", + const: "first", + }, + { + type: "string", + const: "all", + }, + ], + }, + actions: { + type: "object", + properties: { + reactions: { + type: "boolean", + }, + }, + additionalProperties: false, + }, + dm: { + type: "object", + properties: { + enabled: { + type: "boolean", + }, + policy: { + default: "pairing", + type: "string", + enum: ["pairing", "allowlist", "open", "disabled"], + }, + allowFrom: { + type: "array", + items: { + anyOf: [ + { + type: "string", + }, + { + type: "number", + }, + ], + }, + }, + }, + required: ["policy"], + additionalProperties: false, + }, + healthMonitor: { + type: "object", + properties: { + enabled: { + type: "boolean", + }, + }, + additionalProperties: false, + }, + typingIndicator: { + type: "string", + enum: ["none", "message", "reaction"], + }, + responsePrefix: { + type: "string", + }, + }, + required: ["groupPolicy", "streamMode"], + additionalProperties: false, + }, + }, + defaultAccount: { + type: "string", + }, + }, + required: ["groupPolicy", "streamMode"], + additionalProperties: false, + }, + label: "Google Chat", + description: "Google Workspace Chat app via HTTP webhooks.", + }, + }, }, }, { @@ -1370,6 +6390,590 @@ export const GENERATED_BUNDLED_PLUGIN_METADATA = [ properties: {}, }, channels: ["imessage"], + channelConfigs: { + imessage: { + schema: { + $schema: "http://json-schema.org/draft-07/schema#", + type: "object", + properties: { + name: { + type: "string", + }, + capabilities: { + type: "array", + items: { + type: "string", + }, + }, + markdown: { + type: "object", + properties: { + tables: { + type: "string", + enum: ["off", "bullets", "code"], + }, + }, + additionalProperties: false, + }, + enabled: { + type: "boolean", + }, + configWrites: { + type: "boolean", + }, + cliPath: { + type: "string", + }, + dbPath: { + type: "string", + }, + remoteHost: { + type: "string", + }, + service: { + anyOf: [ + { + type: "string", + const: "imessage", + }, + { + type: "string", + const: "sms", + }, + { + type: "string", + const: "auto", + }, + ], + }, + region: { + type: "string", + }, + dmPolicy: { + default: "pairing", + type: "string", + enum: ["pairing", "allowlist", "open", "disabled"], + }, + allowFrom: { + type: "array", + items: { + anyOf: [ + { + type: "string", + }, + { + type: "number", + }, + ], + }, + }, + defaultTo: { + type: "string", + }, + groupAllowFrom: { + type: "array", + items: { + anyOf: [ + { + type: "string", + }, + { + type: "number", + }, + ], + }, + }, + groupPolicy: { + default: "allowlist", + type: "string", + enum: ["open", "disabled", "allowlist"], + }, + historyLimit: { + type: "integer", + minimum: 0, + maximum: 9007199254740991, + }, + dmHistoryLimit: { + type: "integer", + minimum: 0, + maximum: 9007199254740991, + }, + dms: { + type: "object", + propertyNames: { + type: "string", + }, + additionalProperties: { + type: "object", + properties: { + historyLimit: { + type: "integer", + minimum: 0, + maximum: 9007199254740991, + }, + }, + additionalProperties: false, + }, + }, + includeAttachments: { + type: "boolean", + }, + attachmentRoots: { + type: "array", + items: { + type: "string", + }, + }, + remoteAttachmentRoots: { + type: "array", + items: { + type: "string", + }, + }, + mediaMaxMb: { + type: "integer", + exclusiveMinimum: 0, + maximum: 9007199254740991, + }, + textChunkLimit: { + type: "integer", + exclusiveMinimum: 0, + maximum: 9007199254740991, + }, + chunkMode: { + type: "string", + enum: ["length", "newline"], + }, + blockStreaming: { + type: "boolean", + }, + blockStreamingCoalesce: { + type: "object", + properties: { + minChars: { + type: "integer", + exclusiveMinimum: 0, + maximum: 9007199254740991, + }, + maxChars: { + type: "integer", + exclusiveMinimum: 0, + maximum: 9007199254740991, + }, + idleMs: { + type: "integer", + minimum: 0, + maximum: 9007199254740991, + }, + }, + additionalProperties: false, + }, + groups: { + type: "object", + propertyNames: { + type: "string", + }, + additionalProperties: { + type: "object", + properties: { + requireMention: { + type: "boolean", + }, + tools: { + type: "object", + properties: { + allow: { + type: "array", + items: { + type: "string", + }, + }, + alsoAllow: { + type: "array", + items: { + type: "string", + }, + }, + deny: { + type: "array", + items: { + type: "string", + }, + }, + }, + additionalProperties: false, + }, + toolsBySender: { + type: "object", + propertyNames: { + type: "string", + }, + additionalProperties: { + type: "object", + properties: { + allow: { + type: "array", + items: { + type: "string", + }, + }, + alsoAllow: { + type: "array", + items: { + type: "string", + }, + }, + deny: { + type: "array", + items: { + type: "string", + }, + }, + }, + additionalProperties: false, + }, + }, + }, + additionalProperties: false, + }, + }, + heartbeat: { + type: "object", + properties: { + showOk: { + type: "boolean", + }, + showAlerts: { + type: "boolean", + }, + useIndicator: { + type: "boolean", + }, + }, + additionalProperties: false, + }, + healthMonitor: { + type: "object", + properties: { + enabled: { + type: "boolean", + }, + }, + additionalProperties: false, + }, + responsePrefix: { + type: "string", + }, + accounts: { + type: "object", + propertyNames: { + type: "string", + }, + additionalProperties: { + type: "object", + properties: { + name: { + type: "string", + }, + capabilities: { + type: "array", + items: { + type: "string", + }, + }, + markdown: { + type: "object", + properties: { + tables: { + type: "string", + enum: ["off", "bullets", "code"], + }, + }, + additionalProperties: false, + }, + enabled: { + type: "boolean", + }, + configWrites: { + type: "boolean", + }, + cliPath: { + type: "string", + }, + dbPath: { + type: "string", + }, + remoteHost: { + type: "string", + }, + service: { + anyOf: [ + { + type: "string", + const: "imessage", + }, + { + type: "string", + const: "sms", + }, + { + type: "string", + const: "auto", + }, + ], + }, + region: { + type: "string", + }, + dmPolicy: { + default: "pairing", + type: "string", + enum: ["pairing", "allowlist", "open", "disabled"], + }, + allowFrom: { + type: "array", + items: { + anyOf: [ + { + type: "string", + }, + { + type: "number", + }, + ], + }, + }, + defaultTo: { + type: "string", + }, + groupAllowFrom: { + type: "array", + items: { + anyOf: [ + { + type: "string", + }, + { + type: "number", + }, + ], + }, + }, + groupPolicy: { + default: "allowlist", + type: "string", + enum: ["open", "disabled", "allowlist"], + }, + historyLimit: { + type: "integer", + minimum: 0, + maximum: 9007199254740991, + }, + dmHistoryLimit: { + type: "integer", + minimum: 0, + maximum: 9007199254740991, + }, + dms: { + type: "object", + propertyNames: { + type: "string", + }, + additionalProperties: { + type: "object", + properties: { + historyLimit: { + type: "integer", + minimum: 0, + maximum: 9007199254740991, + }, + }, + additionalProperties: false, + }, + }, + includeAttachments: { + type: "boolean", + }, + attachmentRoots: { + type: "array", + items: { + type: "string", + }, + }, + remoteAttachmentRoots: { + type: "array", + items: { + type: "string", + }, + }, + mediaMaxMb: { + type: "integer", + exclusiveMinimum: 0, + maximum: 9007199254740991, + }, + textChunkLimit: { + type: "integer", + exclusiveMinimum: 0, + maximum: 9007199254740991, + }, + chunkMode: { + type: "string", + enum: ["length", "newline"], + }, + blockStreaming: { + type: "boolean", + }, + blockStreamingCoalesce: { + type: "object", + properties: { + minChars: { + type: "integer", + exclusiveMinimum: 0, + maximum: 9007199254740991, + }, + maxChars: { + type: "integer", + exclusiveMinimum: 0, + maximum: 9007199254740991, + }, + idleMs: { + type: "integer", + minimum: 0, + maximum: 9007199254740991, + }, + }, + additionalProperties: false, + }, + groups: { + type: "object", + propertyNames: { + type: "string", + }, + additionalProperties: { + type: "object", + properties: { + requireMention: { + type: "boolean", + }, + tools: { + type: "object", + properties: { + allow: { + type: "array", + items: { + type: "string", + }, + }, + alsoAllow: { + type: "array", + items: { + type: "string", + }, + }, + deny: { + type: "array", + items: { + type: "string", + }, + }, + }, + additionalProperties: false, + }, + toolsBySender: { + type: "object", + propertyNames: { + type: "string", + }, + additionalProperties: { + type: "object", + properties: { + allow: { + type: "array", + items: { + type: "string", + }, + }, + alsoAllow: { + type: "array", + items: { + type: "string", + }, + }, + deny: { + type: "array", + items: { + type: "string", + }, + }, + }, + additionalProperties: false, + }, + }, + }, + additionalProperties: false, + }, + }, + heartbeat: { + type: "object", + properties: { + showOk: { + type: "boolean", + }, + showAlerts: { + type: "boolean", + }, + useIndicator: { + type: "boolean", + }, + }, + additionalProperties: false, + }, + healthMonitor: { + type: "object", + properties: { + enabled: { + type: "boolean", + }, + }, + additionalProperties: false, + }, + responsePrefix: { + type: "string", + }, + }, + required: ["dmPolicy", "groupPolicy"], + additionalProperties: false, + }, + }, + defaultAccount: { + type: "string", + }, + }, + required: ["dmPolicy", "groupPolicy"], + additionalProperties: false, + }, + uiHints: { + "": { + label: "iMessage", + help: "iMessage channel provider configuration for CLI integration and DM access policy handling. Use explicit CLI paths when runtime environments have non-standard binary locations.", + }, + dmPolicy: { + label: "iMessage DM Policy", + help: 'Direct message access control ("pairing" recommended). "open" requires channels.imessage.allowFrom=["*"].', + }, + configWrites: { + label: "iMessage Config Writes", + help: "Allow iMessage to write config in response to channel events/commands (default: true).", + }, + cliPath: { + label: "iMessage CLI Path", + help: "Filesystem path to the iMessage bridge CLI binary used for send/receive operations. Set explicitly when the binary is not on PATH in service runtime environments.", + }, + }, + label: "iMessage", + description: "this is still a work in progress.", + }, + }, }, }, { @@ -1411,6 +7015,630 @@ export const GENERATED_BUNDLED_PLUGIN_METADATA = [ properties: {}, }, channels: ["irc"], + channelConfigs: { + irc: { + schema: { + $schema: "http://json-schema.org/draft-07/schema#", + type: "object", + properties: { + name: { + type: "string", + }, + enabled: { + type: "boolean", + }, + dangerouslyAllowNameMatching: { + type: "boolean", + }, + host: { + type: "string", + }, + port: { + type: "integer", + minimum: 1, + maximum: 65535, + }, + tls: { + type: "boolean", + }, + nick: { + type: "string", + }, + username: { + type: "string", + }, + realname: { + type: "string", + }, + password: { + type: "string", + }, + passwordFile: { + type: "string", + }, + nickserv: { + type: "object", + properties: { + enabled: { + type: "boolean", + }, + service: { + type: "string", + }, + password: { + type: "string", + }, + passwordFile: { + type: "string", + }, + register: { + type: "boolean", + }, + registerEmail: { + type: "string", + }, + }, + additionalProperties: false, + }, + dmPolicy: { + default: "pairing", + type: "string", + enum: ["pairing", "allowlist", "open", "disabled"], + }, + allowFrom: { + type: "array", + items: { + anyOf: [ + { + type: "string", + }, + { + type: "number", + }, + ], + }, + }, + groupPolicy: { + default: "allowlist", + type: "string", + enum: ["open", "disabled", "allowlist"], + }, + groupAllowFrom: { + type: "array", + items: { + anyOf: [ + { + type: "string", + }, + { + type: "number", + }, + ], + }, + }, + groups: { + type: "object", + propertyNames: { + type: "string", + }, + additionalProperties: { + type: "object", + properties: { + requireMention: { + type: "boolean", + }, + tools: { + type: "object", + properties: { + allow: { + type: "array", + items: { + type: "string", + }, + }, + alsoAllow: { + type: "array", + items: { + type: "string", + }, + }, + deny: { + type: "array", + items: { + type: "string", + }, + }, + }, + additionalProperties: false, + }, + toolsBySender: { + type: "object", + propertyNames: { + type: "string", + }, + additionalProperties: { + type: "object", + properties: { + allow: { + type: "array", + items: { + type: "string", + }, + }, + alsoAllow: { + type: "array", + items: { + type: "string", + }, + }, + deny: { + type: "array", + items: { + type: "string", + }, + }, + }, + additionalProperties: false, + }, + }, + skills: { + type: "array", + items: { + type: "string", + }, + }, + enabled: { + type: "boolean", + }, + allowFrom: { + type: "array", + items: { + anyOf: [ + { + type: "string", + }, + { + type: "number", + }, + ], + }, + }, + systemPrompt: { + type: "string", + }, + }, + additionalProperties: false, + }, + }, + channels: { + type: "array", + items: { + type: "string", + }, + }, + mentionPatterns: { + type: "array", + items: { + type: "string", + }, + }, + markdown: { + type: "object", + properties: { + tables: { + type: "string", + enum: ["off", "bullets", "code"], + }, + }, + additionalProperties: false, + }, + historyLimit: { + type: "integer", + minimum: 0, + maximum: 9007199254740991, + }, + dmHistoryLimit: { + type: "integer", + minimum: 0, + maximum: 9007199254740991, + }, + dms: { + type: "object", + propertyNames: { + type: "string", + }, + additionalProperties: { + type: "object", + properties: { + historyLimit: { + type: "integer", + minimum: 0, + maximum: 9007199254740991, + }, + }, + additionalProperties: false, + }, + }, + textChunkLimit: { + type: "integer", + exclusiveMinimum: 0, + maximum: 9007199254740991, + }, + chunkMode: { + type: "string", + enum: ["length", "newline"], + }, + blockStreaming: { + type: "boolean", + }, + blockStreamingCoalesce: { + type: "object", + properties: { + minChars: { + type: "integer", + exclusiveMinimum: 0, + maximum: 9007199254740991, + }, + maxChars: { + type: "integer", + exclusiveMinimum: 0, + maximum: 9007199254740991, + }, + idleMs: { + type: "integer", + minimum: 0, + maximum: 9007199254740991, + }, + }, + additionalProperties: false, + }, + responsePrefix: { + type: "string", + }, + mediaMaxMb: { + type: "number", + exclusiveMinimum: 0, + }, + accounts: { + type: "object", + propertyNames: { + type: "string", + }, + additionalProperties: { + type: "object", + properties: { + name: { + type: "string", + }, + enabled: { + type: "boolean", + }, + dangerouslyAllowNameMatching: { + type: "boolean", + }, + host: { + type: "string", + }, + port: { + type: "integer", + minimum: 1, + maximum: 65535, + }, + tls: { + type: "boolean", + }, + nick: { + type: "string", + }, + username: { + type: "string", + }, + realname: { + type: "string", + }, + password: { + type: "string", + }, + passwordFile: { + type: "string", + }, + nickserv: { + type: "object", + properties: { + enabled: { + type: "boolean", + }, + service: { + type: "string", + }, + password: { + type: "string", + }, + passwordFile: { + type: "string", + }, + register: { + type: "boolean", + }, + registerEmail: { + type: "string", + }, + }, + additionalProperties: false, + }, + dmPolicy: { + default: "pairing", + type: "string", + enum: ["pairing", "allowlist", "open", "disabled"], + }, + allowFrom: { + type: "array", + items: { + anyOf: [ + { + type: "string", + }, + { + type: "number", + }, + ], + }, + }, + groupPolicy: { + default: "allowlist", + type: "string", + enum: ["open", "disabled", "allowlist"], + }, + groupAllowFrom: { + type: "array", + items: { + anyOf: [ + { + type: "string", + }, + { + type: "number", + }, + ], + }, + }, + groups: { + type: "object", + propertyNames: { + type: "string", + }, + additionalProperties: { + type: "object", + properties: { + requireMention: { + type: "boolean", + }, + tools: { + type: "object", + properties: { + allow: { + type: "array", + items: { + type: "string", + }, + }, + alsoAllow: { + type: "array", + items: { + type: "string", + }, + }, + deny: { + type: "array", + items: { + type: "string", + }, + }, + }, + additionalProperties: false, + }, + toolsBySender: { + type: "object", + propertyNames: { + type: "string", + }, + additionalProperties: { + type: "object", + properties: { + allow: { + type: "array", + items: { + type: "string", + }, + }, + alsoAllow: { + type: "array", + items: { + type: "string", + }, + }, + deny: { + type: "array", + items: { + type: "string", + }, + }, + }, + additionalProperties: false, + }, + }, + skills: { + type: "array", + items: { + type: "string", + }, + }, + enabled: { + type: "boolean", + }, + allowFrom: { + type: "array", + items: { + anyOf: [ + { + type: "string", + }, + { + type: "number", + }, + ], + }, + }, + systemPrompt: { + type: "string", + }, + }, + additionalProperties: false, + }, + }, + channels: { + type: "array", + items: { + type: "string", + }, + }, + mentionPatterns: { + type: "array", + items: { + type: "string", + }, + }, + markdown: { + type: "object", + properties: { + tables: { + type: "string", + enum: ["off", "bullets", "code"], + }, + }, + additionalProperties: false, + }, + historyLimit: { + type: "integer", + minimum: 0, + maximum: 9007199254740991, + }, + dmHistoryLimit: { + type: "integer", + minimum: 0, + maximum: 9007199254740991, + }, + dms: { + type: "object", + propertyNames: { + type: "string", + }, + additionalProperties: { + type: "object", + properties: { + historyLimit: { + type: "integer", + minimum: 0, + maximum: 9007199254740991, + }, + }, + additionalProperties: false, + }, + }, + textChunkLimit: { + type: "integer", + exclusiveMinimum: 0, + maximum: 9007199254740991, + }, + chunkMode: { + type: "string", + enum: ["length", "newline"], + }, + blockStreaming: { + type: "boolean", + }, + blockStreamingCoalesce: { + type: "object", + properties: { + minChars: { + type: "integer", + exclusiveMinimum: 0, + maximum: 9007199254740991, + }, + maxChars: { + type: "integer", + exclusiveMinimum: 0, + maximum: 9007199254740991, + }, + idleMs: { + type: "integer", + minimum: 0, + maximum: 9007199254740991, + }, + }, + additionalProperties: false, + }, + responsePrefix: { + type: "string", + }, + mediaMaxMb: { + type: "number", + exclusiveMinimum: 0, + }, + }, + required: ["dmPolicy", "groupPolicy"], + additionalProperties: false, + }, + }, + defaultAccount: { + type: "string", + }, + }, + required: ["dmPolicy", "groupPolicy"], + additionalProperties: false, + }, + uiHints: { + "": { + label: "IRC", + help: "IRC channel provider configuration and compatibility settings for classic IRC transport workflows. Use this section when bridging legacy chat infrastructure into OpenClaw.", + }, + dmPolicy: { + label: "IRC DM Policy", + help: 'Direct message access control ("pairing" recommended). "open" requires channels.irc.allowFrom=["*"].', + }, + "nickserv.enabled": { + label: "IRC NickServ Enabled", + help: "Enable NickServ identify/register after connect (defaults to enabled when password is configured).", + }, + "nickserv.service": { + label: "IRC NickServ Service", + help: "NickServ service nick (default: NickServ).", + }, + "nickserv.password": { + label: "IRC NickServ Password", + help: "NickServ password used for IDENTIFY/REGISTER (sensitive).", + }, + "nickserv.passwordFile": { + label: "IRC NickServ Password File", + help: "Optional file path containing NickServ password.", + }, + "nickserv.register": { + label: "IRC NickServ Register", + help: "If true, send NickServ REGISTER on every connect. Use once for initial registration, then disable.", + }, + "nickserv.registerEmail": { + label: "IRC NickServ Register Email", + help: "Email used with NickServ REGISTER (required when register=true).", + }, + configWrites: { + label: "IRC Config Writes", + help: "Allow IRC to write config in response to channel events/commands (default: true).", + }, + }, + label: "IRC", + description: "classic IRC networks with DM/channel routing and pairing controls.", + }, + }, }, }, { @@ -1539,6 +7767,242 @@ export const GENERATED_BUNDLED_PLUGIN_METADATA = [ properties: {}, }, channels: ["line"], + channelConfigs: { + line: { + schema: { + $schema: "http://json-schema.org/draft-07/schema#", + type: "object", + properties: { + enabled: { + type: "boolean", + }, + channelAccessToken: { + type: "string", + }, + channelSecret: { + type: "string", + }, + tokenFile: { + type: "string", + }, + secretFile: { + type: "string", + }, + name: { + type: "string", + }, + allowFrom: { + type: "array", + items: { + anyOf: [ + { + type: "string", + }, + { + type: "number", + }, + ], + }, + }, + groupAllowFrom: { + type: "array", + items: { + anyOf: [ + { + type: "string", + }, + { + type: "number", + }, + ], + }, + }, + dmPolicy: { + default: "pairing", + type: "string", + enum: ["open", "allowlist", "pairing", "disabled"], + }, + groupPolicy: { + default: "allowlist", + type: "string", + enum: ["open", "allowlist", "disabled"], + }, + responsePrefix: { + type: "string", + }, + mediaMaxMb: { + type: "number", + }, + webhookPath: { + type: "string", + }, + accounts: { + type: "object", + propertyNames: { + type: "string", + }, + additionalProperties: { + type: "object", + properties: { + enabled: { + type: "boolean", + }, + channelAccessToken: { + type: "string", + }, + channelSecret: { + type: "string", + }, + tokenFile: { + type: "string", + }, + secretFile: { + type: "string", + }, + name: { + type: "string", + }, + allowFrom: { + type: "array", + items: { + anyOf: [ + { + type: "string", + }, + { + type: "number", + }, + ], + }, + }, + groupAllowFrom: { + type: "array", + items: { + anyOf: [ + { + type: "string", + }, + { + type: "number", + }, + ], + }, + }, + dmPolicy: { + default: "pairing", + type: "string", + enum: ["open", "allowlist", "pairing", "disabled"], + }, + groupPolicy: { + default: "allowlist", + type: "string", + enum: ["open", "allowlist", "disabled"], + }, + responsePrefix: { + type: "string", + }, + mediaMaxMb: { + type: "number", + }, + webhookPath: { + type: "string", + }, + groups: { + type: "object", + propertyNames: { + type: "string", + }, + additionalProperties: { + type: "object", + properties: { + enabled: { + type: "boolean", + }, + allowFrom: { + type: "array", + items: { + anyOf: [ + { + type: "string", + }, + { + type: "number", + }, + ], + }, + }, + requireMention: { + type: "boolean", + }, + systemPrompt: { + type: "string", + }, + skills: { + type: "array", + items: { + type: "string", + }, + }, + }, + additionalProperties: false, + }, + }, + }, + required: ["dmPolicy", "groupPolicy"], + additionalProperties: false, + }, + }, + defaultAccount: { + type: "string", + }, + groups: { + type: "object", + propertyNames: { + type: "string", + }, + additionalProperties: { + type: "object", + properties: { + enabled: { + type: "boolean", + }, + allowFrom: { + type: "array", + items: { + anyOf: [ + { + type: "string", + }, + { + type: "number", + }, + ], + }, + }, + requireMention: { + type: "boolean", + }, + systemPrompt: { + type: "string", + }, + skills: { + type: "array", + items: { + type: "string", + }, + }, + }, + additionalProperties: false, + }, + }, + }, + required: ["dmPolicy", "groupPolicy"], + additionalProperties: false, + }, + label: "LINE", + description: "LINE Messaging API bot for Japan/Taiwan/Thailand markets.", + }, + }, }, }, { @@ -1654,6 +8118,459 @@ export const GENERATED_BUNDLED_PLUGIN_METADATA = [ properties: {}, }, channels: ["matrix"], + channelConfigs: { + matrix: { + schema: { + $schema: "http://json-schema.org/draft-07/schema#", + type: "object", + properties: { + name: { + type: "string", + }, + enabled: { + type: "boolean", + }, + defaultAccount: { + type: "string", + }, + accounts: { + type: "object", + propertyNames: { + type: "string", + }, + additionalProperties: {}, + }, + markdown: { + type: "object", + properties: { + tables: { + type: "string", + enum: ["off", "bullets", "code"], + }, + }, + additionalProperties: false, + }, + homeserver: { + type: "string", + }, + allowPrivateNetwork: { + type: "boolean", + }, + userId: { + type: "string", + }, + accessToken: { + type: "string", + }, + password: { + anyOf: [ + { + type: "string", + }, + { + oneOf: [ + { + type: "object", + properties: { + source: { + type: "string", + const: "env", + }, + provider: { + type: "string", + pattern: "^[a-z][a-z0-9_-]{0,63}$", + }, + id: { + type: "string", + pattern: "^[A-Z][A-Z0-9_]{0,127}$", + }, + }, + required: ["source", "provider", "id"], + additionalProperties: false, + }, + { + type: "object", + properties: { + source: { + type: "string", + const: "file", + }, + provider: { + type: "string", + pattern: "^[a-z][a-z0-9_-]{0,63}$", + }, + id: { + type: "string", + }, + }, + required: ["source", "provider", "id"], + additionalProperties: false, + }, + { + type: "object", + properties: { + source: { + type: "string", + const: "exec", + }, + provider: { + type: "string", + pattern: "^[a-z][a-z0-9_-]{0,63}$", + }, + id: { + type: "string", + }, + }, + required: ["source", "provider", "id"], + additionalProperties: false, + }, + ], + }, + ], + }, + deviceId: { + type: "string", + }, + deviceName: { + type: "string", + }, + avatarUrl: { + type: "string", + }, + initialSyncLimit: { + type: "number", + }, + encryption: { + type: "boolean", + }, + allowlistOnly: { + type: "boolean", + }, + allowBots: { + anyOf: [ + { + type: "boolean", + }, + { + type: "string", + const: "mentions", + }, + ], + }, + groupPolicy: { + type: "string", + enum: ["open", "disabled", "allowlist"], + }, + replyToMode: { + type: "string", + enum: ["off", "first", "all"], + }, + threadReplies: { + type: "string", + enum: ["off", "inbound", "always"], + }, + textChunkLimit: { + type: "number", + }, + chunkMode: { + type: "string", + enum: ["length", "newline"], + }, + responsePrefix: { + type: "string", + }, + ackReaction: { + type: "string", + }, + ackReactionScope: { + type: "string", + enum: ["group-mentions", "group-all", "direct", "all", "none", "off"], + }, + reactionNotifications: { + type: "string", + enum: ["off", "own"], + }, + threadBindings: { + type: "object", + properties: { + enabled: { + type: "boolean", + }, + idleHours: { + type: "number", + minimum: 0, + }, + maxAgeHours: { + type: "number", + minimum: 0, + }, + spawnSubagentSessions: { + type: "boolean", + }, + spawnAcpSessions: { + type: "boolean", + }, + }, + additionalProperties: false, + }, + startupVerification: { + type: "string", + enum: ["off", "if-unverified"], + }, + startupVerificationCooldownHours: { + type: "number", + }, + mediaMaxMb: { + type: "number", + }, + autoJoin: { + type: "string", + enum: ["always", "allowlist", "off"], + }, + autoJoinAllowlist: { + type: "array", + items: { + anyOf: [ + { + type: "string", + }, + { + type: "number", + }, + ], + }, + }, + groupAllowFrom: { + type: "array", + items: { + anyOf: [ + { + type: "string", + }, + { + type: "number", + }, + ], + }, + }, + dm: { + type: "object", + properties: { + enabled: { + type: "boolean", + }, + policy: { + type: "string", + enum: ["pairing", "allowlist", "open", "disabled"], + }, + allowFrom: { + type: "array", + items: { + anyOf: [ + { + type: "string", + }, + { + type: "number", + }, + ], + }, + }, + }, + additionalProperties: false, + }, + groups: { + type: "object", + properties: {}, + additionalProperties: { + type: "object", + properties: { + enabled: { + type: "boolean", + }, + allow: { + type: "boolean", + }, + requireMention: { + type: "boolean", + }, + allowBots: { + anyOf: [ + { + type: "boolean", + }, + { + type: "string", + const: "mentions", + }, + ], + }, + tools: { + type: "object", + properties: { + allow: { + type: "array", + items: { + type: "string", + }, + }, + alsoAllow: { + type: "array", + items: { + type: "string", + }, + }, + deny: { + type: "array", + items: { + type: "string", + }, + }, + }, + additionalProperties: false, + }, + autoReply: { + type: "boolean", + }, + users: { + type: "array", + items: { + anyOf: [ + { + type: "string", + }, + { + type: "number", + }, + ], + }, + }, + skills: { + type: "array", + items: { + type: "string", + }, + }, + systemPrompt: { + type: "string", + }, + }, + additionalProperties: false, + }, + }, + rooms: { + type: "object", + properties: {}, + additionalProperties: { + type: "object", + properties: { + enabled: { + type: "boolean", + }, + allow: { + type: "boolean", + }, + requireMention: { + type: "boolean", + }, + allowBots: { + anyOf: [ + { + type: "boolean", + }, + { + type: "string", + const: "mentions", + }, + ], + }, + tools: { + type: "object", + properties: { + allow: { + type: "array", + items: { + type: "string", + }, + }, + alsoAllow: { + type: "array", + items: { + type: "string", + }, + }, + deny: { + type: "array", + items: { + type: "string", + }, + }, + }, + additionalProperties: false, + }, + autoReply: { + type: "boolean", + }, + users: { + type: "array", + items: { + anyOf: [ + { + type: "string", + }, + { + type: "number", + }, + ], + }, + }, + skills: { + type: "array", + items: { + type: "string", + }, + }, + systemPrompt: { + type: "string", + }, + }, + additionalProperties: false, + }, + }, + actions: { + type: "object", + properties: { + reactions: { + type: "boolean", + }, + messages: { + type: "boolean", + }, + pins: { + type: "boolean", + }, + profile: { + type: "boolean", + }, + memberInfo: { + type: "boolean", + }, + channelInfo: { + type: "boolean", + }, + verification: { + type: "boolean", + }, + }, + additionalProperties: false, + }, + }, + additionalProperties: false, + }, + label: "Matrix", + description: "open protocol; install the plugin to enable.", + }, + }, }, }, { @@ -1697,6 +8614,582 @@ export const GENERATED_BUNDLED_PLUGIN_METADATA = [ properties: {}, }, channels: ["mattermost"], + channelConfigs: { + mattermost: { + schema: { + $schema: "http://json-schema.org/draft-07/schema#", + type: "object", + properties: { + name: { + type: "string", + }, + capabilities: { + type: "array", + items: { + type: "string", + }, + }, + dangerouslyAllowNameMatching: { + type: "boolean", + }, + markdown: { + type: "object", + properties: { + tables: { + type: "string", + enum: ["off", "bullets", "code"], + }, + }, + additionalProperties: false, + }, + enabled: { + type: "boolean", + }, + configWrites: { + type: "boolean", + }, + botToken: { + anyOf: [ + { + type: "string", + }, + { + oneOf: [ + { + type: "object", + properties: { + source: { + type: "string", + const: "env", + }, + provider: { + type: "string", + pattern: "^[a-z][a-z0-9_-]{0,63}$", + }, + id: { + type: "string", + pattern: "^[A-Z][A-Z0-9_]{0,127}$", + }, + }, + required: ["source", "provider", "id"], + additionalProperties: false, + }, + { + type: "object", + properties: { + source: { + type: "string", + const: "file", + }, + provider: { + type: "string", + pattern: "^[a-z][a-z0-9_-]{0,63}$", + }, + id: { + type: "string", + }, + }, + required: ["source", "provider", "id"], + additionalProperties: false, + }, + { + type: "object", + properties: { + source: { + type: "string", + const: "exec", + }, + provider: { + type: "string", + pattern: "^[a-z][a-z0-9_-]{0,63}$", + }, + id: { + type: "string", + }, + }, + required: ["source", "provider", "id"], + additionalProperties: false, + }, + ], + }, + ], + }, + baseUrl: { + type: "string", + }, + chatmode: { + type: "string", + enum: ["oncall", "onmessage", "onchar"], + }, + oncharPrefixes: { + type: "array", + items: { + type: "string", + }, + }, + requireMention: { + type: "boolean", + }, + dmPolicy: { + default: "pairing", + type: "string", + enum: ["pairing", "allowlist", "open", "disabled"], + }, + allowFrom: { + type: "array", + items: { + anyOf: [ + { + type: "string", + }, + { + type: "number", + }, + ], + }, + }, + groupAllowFrom: { + type: "array", + items: { + anyOf: [ + { + type: "string", + }, + { + type: "number", + }, + ], + }, + }, + groupPolicy: { + default: "allowlist", + type: "string", + enum: ["open", "disabled", "allowlist"], + }, + textChunkLimit: { + type: "integer", + exclusiveMinimum: 0, + maximum: 9007199254740991, + }, + chunkMode: { + type: "string", + enum: ["length", "newline"], + }, + blockStreaming: { + type: "boolean", + }, + blockStreamingCoalesce: { + type: "object", + properties: { + minChars: { + type: "integer", + exclusiveMinimum: 0, + maximum: 9007199254740991, + }, + maxChars: { + type: "integer", + exclusiveMinimum: 0, + maximum: 9007199254740991, + }, + idleMs: { + type: "integer", + minimum: 0, + maximum: 9007199254740991, + }, + }, + additionalProperties: false, + }, + replyToMode: { + type: "string", + enum: ["off", "first", "all"], + }, + responsePrefix: { + type: "string", + }, + actions: { + type: "object", + properties: { + reactions: { + type: "boolean", + }, + }, + additionalProperties: false, + }, + commands: { + type: "object", + properties: { + native: { + anyOf: [ + { + type: "boolean", + }, + { + type: "string", + const: "auto", + }, + ], + }, + nativeSkills: { + anyOf: [ + { + type: "boolean", + }, + { + type: "string", + const: "auto", + }, + ], + }, + callbackPath: { + type: "string", + }, + callbackUrl: { + type: "string", + }, + }, + additionalProperties: false, + }, + interactions: { + type: "object", + properties: { + callbackBaseUrl: { + type: "string", + }, + allowedSourceIps: { + type: "array", + items: { + type: "string", + }, + }, + }, + additionalProperties: false, + }, + allowPrivateNetwork: { + type: "boolean", + }, + dmChannelRetry: { + type: "object", + properties: { + maxRetries: { + type: "integer", + minimum: 0, + maximum: 10, + }, + initialDelayMs: { + type: "integer", + minimum: 100, + maximum: 60000, + }, + maxDelayMs: { + type: "integer", + minimum: 1000, + maximum: 60000, + }, + timeoutMs: { + type: "integer", + minimum: 5000, + maximum: 120000, + }, + }, + additionalProperties: false, + }, + accounts: { + type: "object", + propertyNames: { + type: "string", + }, + additionalProperties: { + type: "object", + properties: { + name: { + type: "string", + }, + capabilities: { + type: "array", + items: { + type: "string", + }, + }, + dangerouslyAllowNameMatching: { + type: "boolean", + }, + markdown: { + type: "object", + properties: { + tables: { + type: "string", + enum: ["off", "bullets", "code"], + }, + }, + additionalProperties: false, + }, + enabled: { + type: "boolean", + }, + configWrites: { + type: "boolean", + }, + botToken: { + anyOf: [ + { + type: "string", + }, + { + oneOf: [ + { + type: "object", + properties: { + source: { + type: "string", + const: "env", + }, + provider: { + type: "string", + pattern: "^[a-z][a-z0-9_-]{0,63}$", + }, + id: { + type: "string", + pattern: "^[A-Z][A-Z0-9_]{0,127}$", + }, + }, + required: ["source", "provider", "id"], + additionalProperties: false, + }, + { + type: "object", + properties: { + source: { + type: "string", + const: "file", + }, + provider: { + type: "string", + pattern: "^[a-z][a-z0-9_-]{0,63}$", + }, + id: { + type: "string", + }, + }, + required: ["source", "provider", "id"], + additionalProperties: false, + }, + { + type: "object", + properties: { + source: { + type: "string", + const: "exec", + }, + provider: { + type: "string", + pattern: "^[a-z][a-z0-9_-]{0,63}$", + }, + id: { + type: "string", + }, + }, + required: ["source", "provider", "id"], + additionalProperties: false, + }, + ], + }, + ], + }, + baseUrl: { + type: "string", + }, + chatmode: { + type: "string", + enum: ["oncall", "onmessage", "onchar"], + }, + oncharPrefixes: { + type: "array", + items: { + type: "string", + }, + }, + requireMention: { + type: "boolean", + }, + dmPolicy: { + default: "pairing", + type: "string", + enum: ["pairing", "allowlist", "open", "disabled"], + }, + allowFrom: { + type: "array", + items: { + anyOf: [ + { + type: "string", + }, + { + type: "number", + }, + ], + }, + }, + groupAllowFrom: { + type: "array", + items: { + anyOf: [ + { + type: "string", + }, + { + type: "number", + }, + ], + }, + }, + groupPolicy: { + default: "allowlist", + type: "string", + enum: ["open", "disabled", "allowlist"], + }, + textChunkLimit: { + type: "integer", + exclusiveMinimum: 0, + maximum: 9007199254740991, + }, + chunkMode: { + type: "string", + enum: ["length", "newline"], + }, + blockStreaming: { + type: "boolean", + }, + blockStreamingCoalesce: { + type: "object", + properties: { + minChars: { + type: "integer", + exclusiveMinimum: 0, + maximum: 9007199254740991, + }, + maxChars: { + type: "integer", + exclusiveMinimum: 0, + maximum: 9007199254740991, + }, + idleMs: { + type: "integer", + minimum: 0, + maximum: 9007199254740991, + }, + }, + additionalProperties: false, + }, + replyToMode: { + type: "string", + enum: ["off", "first", "all"], + }, + responsePrefix: { + type: "string", + }, + actions: { + type: "object", + properties: { + reactions: { + type: "boolean", + }, + }, + additionalProperties: false, + }, + commands: { + type: "object", + properties: { + native: { + anyOf: [ + { + type: "boolean", + }, + { + type: "string", + const: "auto", + }, + ], + }, + nativeSkills: { + anyOf: [ + { + type: "boolean", + }, + { + type: "string", + const: "auto", + }, + ], + }, + callbackPath: { + type: "string", + }, + callbackUrl: { + type: "string", + }, + }, + additionalProperties: false, + }, + interactions: { + type: "object", + properties: { + callbackBaseUrl: { + type: "string", + }, + allowedSourceIps: { + type: "array", + items: { + type: "string", + }, + }, + }, + additionalProperties: false, + }, + allowPrivateNetwork: { + type: "boolean", + }, + dmChannelRetry: { + type: "object", + properties: { + maxRetries: { + type: "integer", + minimum: 0, + maximum: 10, + }, + initialDelayMs: { + type: "integer", + minimum: 100, + maximum: 60000, + }, + maxDelayMs: { + type: "integer", + minimum: 1000, + maximum: 60000, + }, + timeoutMs: { + type: "integer", + minimum: 5000, + maximum: 120000, + }, + }, + additionalProperties: false, + }, + }, + required: ["dmPolicy", "groupPolicy"], + additionalProperties: false, + }, + }, + defaultAccount: { + type: "string", + }, + }, + required: ["dmPolicy", "groupPolicy"], + additionalProperties: false, + }, + label: "Mattermost", + description: "self-hosted Slack-style chat; install the plugin to enable.", + }, + }, }, }, { @@ -2244,6 +9737,445 @@ export const GENERATED_BUNDLED_PLUGIN_METADATA = [ properties: {}, }, channels: ["msteams"], + channelConfigs: { + msteams: { + schema: { + $schema: "http://json-schema.org/draft-07/schema#", + type: "object", + properties: { + enabled: { + type: "boolean", + }, + capabilities: { + type: "array", + items: { + type: "string", + }, + }, + dangerouslyAllowNameMatching: { + type: "boolean", + }, + markdown: { + type: "object", + properties: { + tables: { + type: "string", + enum: ["off", "bullets", "code"], + }, + }, + additionalProperties: false, + }, + configWrites: { + type: "boolean", + }, + appId: { + type: "string", + }, + appPassword: { + anyOf: [ + { + type: "string", + }, + { + oneOf: [ + { + type: "object", + properties: { + source: { + type: "string", + const: "env", + }, + provider: { + type: "string", + pattern: "^[a-z][a-z0-9_-]{0,63}$", + }, + id: { + type: "string", + pattern: "^[A-Z][A-Z0-9_]{0,127}$", + }, + }, + required: ["source", "provider", "id"], + additionalProperties: false, + }, + { + type: "object", + properties: { + source: { + type: "string", + const: "file", + }, + provider: { + type: "string", + pattern: "^[a-z][a-z0-9_-]{0,63}$", + }, + id: { + type: "string", + }, + }, + required: ["source", "provider", "id"], + additionalProperties: false, + }, + { + type: "object", + properties: { + source: { + type: "string", + const: "exec", + }, + provider: { + type: "string", + pattern: "^[a-z][a-z0-9_-]{0,63}$", + }, + id: { + type: "string", + }, + }, + required: ["source", "provider", "id"], + additionalProperties: false, + }, + ], + }, + ], + }, + tenantId: { + type: "string", + }, + webhook: { + type: "object", + properties: { + port: { + type: "integer", + exclusiveMinimum: 0, + maximum: 9007199254740991, + }, + path: { + type: "string", + }, + }, + additionalProperties: false, + }, + dmPolicy: { + default: "pairing", + type: "string", + enum: ["pairing", "allowlist", "open", "disabled"], + }, + allowFrom: { + type: "array", + items: { + type: "string", + }, + }, + defaultTo: { + type: "string", + }, + groupAllowFrom: { + type: "array", + items: { + type: "string", + }, + }, + groupPolicy: { + default: "allowlist", + type: "string", + enum: ["open", "disabled", "allowlist"], + }, + textChunkLimit: { + type: "integer", + exclusiveMinimum: 0, + maximum: 9007199254740991, + }, + chunkMode: { + type: "string", + enum: ["length", "newline"], + }, + blockStreamingCoalesce: { + type: "object", + properties: { + minChars: { + type: "integer", + exclusiveMinimum: 0, + maximum: 9007199254740991, + }, + maxChars: { + type: "integer", + exclusiveMinimum: 0, + maximum: 9007199254740991, + }, + idleMs: { + type: "integer", + minimum: 0, + maximum: 9007199254740991, + }, + }, + additionalProperties: false, + }, + mediaAllowHosts: { + type: "array", + items: { + type: "string", + }, + }, + mediaAuthAllowHosts: { + type: "array", + items: { + type: "string", + }, + }, + requireMention: { + type: "boolean", + }, + historyLimit: { + type: "integer", + minimum: 0, + maximum: 9007199254740991, + }, + dmHistoryLimit: { + type: "integer", + minimum: 0, + maximum: 9007199254740991, + }, + dms: { + type: "object", + propertyNames: { + type: "string", + }, + additionalProperties: { + type: "object", + properties: { + historyLimit: { + type: "integer", + minimum: 0, + maximum: 9007199254740991, + }, + }, + additionalProperties: false, + }, + }, + replyStyle: { + type: "string", + enum: ["thread", "top-level"], + }, + teams: { + type: "object", + propertyNames: { + type: "string", + }, + additionalProperties: { + type: "object", + properties: { + requireMention: { + type: "boolean", + }, + tools: { + type: "object", + properties: { + allow: { + type: "array", + items: { + type: "string", + }, + }, + alsoAllow: { + type: "array", + items: { + type: "string", + }, + }, + deny: { + type: "array", + items: { + type: "string", + }, + }, + }, + additionalProperties: false, + }, + toolsBySender: { + type: "object", + propertyNames: { + type: "string", + }, + additionalProperties: { + type: "object", + properties: { + allow: { + type: "array", + items: { + type: "string", + }, + }, + alsoAllow: { + type: "array", + items: { + type: "string", + }, + }, + deny: { + type: "array", + items: { + type: "string", + }, + }, + }, + additionalProperties: false, + }, + }, + replyStyle: { + type: "string", + enum: ["thread", "top-level"], + }, + channels: { + type: "object", + propertyNames: { + type: "string", + }, + additionalProperties: { + type: "object", + properties: { + requireMention: { + type: "boolean", + }, + tools: { + type: "object", + properties: { + allow: { + type: "array", + items: { + type: "string", + }, + }, + alsoAllow: { + type: "array", + items: { + type: "string", + }, + }, + deny: { + type: "array", + items: { + type: "string", + }, + }, + }, + additionalProperties: false, + }, + toolsBySender: { + type: "object", + propertyNames: { + type: "string", + }, + additionalProperties: { + type: "object", + properties: { + allow: { + type: "array", + items: { + type: "string", + }, + }, + alsoAllow: { + type: "array", + items: { + type: "string", + }, + }, + deny: { + type: "array", + items: { + type: "string", + }, + }, + }, + additionalProperties: false, + }, + }, + replyStyle: { + type: "string", + enum: ["thread", "top-level"], + }, + }, + additionalProperties: false, + }, + }, + }, + additionalProperties: false, + }, + }, + mediaMaxMb: { + type: "number", + exclusiveMinimum: 0, + }, + sharePointSiteId: { + type: "string", + }, + heartbeat: { + type: "object", + properties: { + showOk: { + type: "boolean", + }, + showAlerts: { + type: "boolean", + }, + useIndicator: { + type: "boolean", + }, + }, + additionalProperties: false, + }, + healthMonitor: { + type: "object", + properties: { + enabled: { + type: "boolean", + }, + }, + additionalProperties: false, + }, + responsePrefix: { + type: "string", + }, + welcomeCard: { + type: "boolean", + }, + promptStarters: { + type: "array", + items: { + type: "string", + }, + }, + groupWelcomeCard: { + type: "boolean", + }, + feedbackEnabled: { + type: "boolean", + }, + feedbackReflection: { + type: "boolean", + }, + feedbackReflectionCooldownMs: { + type: "integer", + minimum: 0, + maximum: 9007199254740991, + }, + }, + required: ["dmPolicy", "groupPolicy"], + additionalProperties: false, + }, + uiHints: { + "": { + label: "MS Teams", + help: "Microsoft Teams channel provider configuration and provider-specific policy toggles. Use this section to isolate Teams behavior from other enterprise chat providers.", + }, + configWrites: { + label: "MS Teams Config Writes", + help: "Allow Microsoft Teams to write config in response to channel events/commands (default: true).", + }, + }, + label: "Microsoft Teams", + description: "Teams SDK; enterprise support.", + }, + }, }, }, { @@ -2289,6 +10221,682 @@ export const GENERATED_BUNDLED_PLUGIN_METADATA = [ properties: {}, }, channels: ["nextcloud-talk"], + channelConfigs: { + "nextcloud-talk": { + schema: { + $schema: "http://json-schema.org/draft-07/schema#", + type: "object", + properties: { + name: { + type: "string", + }, + enabled: { + type: "boolean", + }, + markdown: { + type: "object", + properties: { + tables: { + type: "string", + enum: ["off", "bullets", "code"], + }, + }, + additionalProperties: false, + }, + baseUrl: { + type: "string", + }, + botSecret: { + anyOf: [ + { + type: "string", + }, + { + oneOf: [ + { + type: "object", + properties: { + source: { + type: "string", + const: "env", + }, + provider: { + type: "string", + pattern: "^[a-z][a-z0-9_-]{0,63}$", + }, + id: { + type: "string", + pattern: "^[A-Z][A-Z0-9_]{0,127}$", + }, + }, + required: ["source", "provider", "id"], + additionalProperties: false, + }, + { + type: "object", + properties: { + source: { + type: "string", + const: "file", + }, + provider: { + type: "string", + pattern: "^[a-z][a-z0-9_-]{0,63}$", + }, + id: { + type: "string", + }, + }, + required: ["source", "provider", "id"], + additionalProperties: false, + }, + { + type: "object", + properties: { + source: { + type: "string", + const: "exec", + }, + provider: { + type: "string", + pattern: "^[a-z][a-z0-9_-]{0,63}$", + }, + id: { + type: "string", + }, + }, + required: ["source", "provider", "id"], + additionalProperties: false, + }, + ], + }, + ], + }, + botSecretFile: { + type: "string", + }, + apiUser: { + type: "string", + }, + apiPassword: { + anyOf: [ + { + type: "string", + }, + { + oneOf: [ + { + type: "object", + properties: { + source: { + type: "string", + const: "env", + }, + provider: { + type: "string", + pattern: "^[a-z][a-z0-9_-]{0,63}$", + }, + id: { + type: "string", + pattern: "^[A-Z][A-Z0-9_]{0,127}$", + }, + }, + required: ["source", "provider", "id"], + additionalProperties: false, + }, + { + type: "object", + properties: { + source: { + type: "string", + const: "file", + }, + provider: { + type: "string", + pattern: "^[a-z][a-z0-9_-]{0,63}$", + }, + id: { + type: "string", + }, + }, + required: ["source", "provider", "id"], + additionalProperties: false, + }, + { + type: "object", + properties: { + source: { + type: "string", + const: "exec", + }, + provider: { + type: "string", + pattern: "^[a-z][a-z0-9_-]{0,63}$", + }, + id: { + type: "string", + }, + }, + required: ["source", "provider", "id"], + additionalProperties: false, + }, + ], + }, + ], + }, + apiPasswordFile: { + type: "string", + }, + dmPolicy: { + default: "pairing", + type: "string", + enum: ["pairing", "allowlist", "open", "disabled"], + }, + webhookPort: { + type: "integer", + exclusiveMinimum: 0, + maximum: 9007199254740991, + }, + webhookHost: { + type: "string", + }, + webhookPath: { + type: "string", + }, + webhookPublicUrl: { + type: "string", + }, + allowFrom: { + type: "array", + items: { + type: "string", + }, + }, + groupAllowFrom: { + type: "array", + items: { + type: "string", + }, + }, + groupPolicy: { + default: "allowlist", + type: "string", + enum: ["open", "disabled", "allowlist"], + }, + rooms: { + type: "object", + propertyNames: { + type: "string", + }, + additionalProperties: { + type: "object", + properties: { + requireMention: { + type: "boolean", + }, + tools: { + type: "object", + properties: { + allow: { + type: "array", + items: { + type: "string", + }, + }, + alsoAllow: { + type: "array", + items: { + type: "string", + }, + }, + deny: { + type: "array", + items: { + type: "string", + }, + }, + }, + additionalProperties: false, + }, + skills: { + type: "array", + items: { + type: "string", + }, + }, + enabled: { + type: "boolean", + }, + allowFrom: { + type: "array", + items: { + type: "string", + }, + }, + systemPrompt: { + type: "string", + }, + }, + additionalProperties: false, + }, + }, + allowPrivateNetwork: { + type: "boolean", + }, + historyLimit: { + type: "integer", + minimum: 0, + maximum: 9007199254740991, + }, + dmHistoryLimit: { + type: "integer", + minimum: 0, + maximum: 9007199254740991, + }, + dms: { + type: "object", + propertyNames: { + type: "string", + }, + additionalProperties: { + type: "object", + properties: { + historyLimit: { + type: "integer", + minimum: 0, + maximum: 9007199254740991, + }, + }, + additionalProperties: false, + }, + }, + textChunkLimit: { + type: "integer", + exclusiveMinimum: 0, + maximum: 9007199254740991, + }, + chunkMode: { + type: "string", + enum: ["length", "newline"], + }, + blockStreaming: { + type: "boolean", + }, + blockStreamingCoalesce: { + type: "object", + properties: { + minChars: { + type: "integer", + exclusiveMinimum: 0, + maximum: 9007199254740991, + }, + maxChars: { + type: "integer", + exclusiveMinimum: 0, + maximum: 9007199254740991, + }, + idleMs: { + type: "integer", + minimum: 0, + maximum: 9007199254740991, + }, + }, + additionalProperties: false, + }, + responsePrefix: { + type: "string", + }, + mediaMaxMb: { + type: "number", + exclusiveMinimum: 0, + }, + accounts: { + type: "object", + propertyNames: { + type: "string", + }, + additionalProperties: { + type: "object", + properties: { + name: { + type: "string", + }, + enabled: { + type: "boolean", + }, + markdown: { + type: "object", + properties: { + tables: { + type: "string", + enum: ["off", "bullets", "code"], + }, + }, + additionalProperties: false, + }, + baseUrl: { + type: "string", + }, + botSecret: { + anyOf: [ + { + type: "string", + }, + { + oneOf: [ + { + type: "object", + properties: { + source: { + type: "string", + const: "env", + }, + provider: { + type: "string", + pattern: "^[a-z][a-z0-9_-]{0,63}$", + }, + id: { + type: "string", + pattern: "^[A-Z][A-Z0-9_]{0,127}$", + }, + }, + required: ["source", "provider", "id"], + additionalProperties: false, + }, + { + type: "object", + properties: { + source: { + type: "string", + const: "file", + }, + provider: { + type: "string", + pattern: "^[a-z][a-z0-9_-]{0,63}$", + }, + id: { + type: "string", + }, + }, + required: ["source", "provider", "id"], + additionalProperties: false, + }, + { + type: "object", + properties: { + source: { + type: "string", + const: "exec", + }, + provider: { + type: "string", + pattern: "^[a-z][a-z0-9_-]{0,63}$", + }, + id: { + type: "string", + }, + }, + required: ["source", "provider", "id"], + additionalProperties: false, + }, + ], + }, + ], + }, + botSecretFile: { + type: "string", + }, + apiUser: { + type: "string", + }, + apiPassword: { + anyOf: [ + { + type: "string", + }, + { + oneOf: [ + { + type: "object", + properties: { + source: { + type: "string", + const: "env", + }, + provider: { + type: "string", + pattern: "^[a-z][a-z0-9_-]{0,63}$", + }, + id: { + type: "string", + pattern: "^[A-Z][A-Z0-9_]{0,127}$", + }, + }, + required: ["source", "provider", "id"], + additionalProperties: false, + }, + { + type: "object", + properties: { + source: { + type: "string", + const: "file", + }, + provider: { + type: "string", + pattern: "^[a-z][a-z0-9_-]{0,63}$", + }, + id: { + type: "string", + }, + }, + required: ["source", "provider", "id"], + additionalProperties: false, + }, + { + type: "object", + properties: { + source: { + type: "string", + const: "exec", + }, + provider: { + type: "string", + pattern: "^[a-z][a-z0-9_-]{0,63}$", + }, + id: { + type: "string", + }, + }, + required: ["source", "provider", "id"], + additionalProperties: false, + }, + ], + }, + ], + }, + apiPasswordFile: { + type: "string", + }, + dmPolicy: { + default: "pairing", + type: "string", + enum: ["pairing", "allowlist", "open", "disabled"], + }, + webhookPort: { + type: "integer", + exclusiveMinimum: 0, + maximum: 9007199254740991, + }, + webhookHost: { + type: "string", + }, + webhookPath: { + type: "string", + }, + webhookPublicUrl: { + type: "string", + }, + allowFrom: { + type: "array", + items: { + type: "string", + }, + }, + groupAllowFrom: { + type: "array", + items: { + type: "string", + }, + }, + groupPolicy: { + default: "allowlist", + type: "string", + enum: ["open", "disabled", "allowlist"], + }, + rooms: { + type: "object", + propertyNames: { + type: "string", + }, + additionalProperties: { + type: "object", + properties: { + requireMention: { + type: "boolean", + }, + tools: { + type: "object", + properties: { + allow: { + type: "array", + items: { + type: "string", + }, + }, + alsoAllow: { + type: "array", + items: { + type: "string", + }, + }, + deny: { + type: "array", + items: { + type: "string", + }, + }, + }, + additionalProperties: false, + }, + skills: { + type: "array", + items: { + type: "string", + }, + }, + enabled: { + type: "boolean", + }, + allowFrom: { + type: "array", + items: { + type: "string", + }, + }, + systemPrompt: { + type: "string", + }, + }, + additionalProperties: false, + }, + }, + allowPrivateNetwork: { + type: "boolean", + }, + historyLimit: { + type: "integer", + minimum: 0, + maximum: 9007199254740991, + }, + dmHistoryLimit: { + type: "integer", + minimum: 0, + maximum: 9007199254740991, + }, + dms: { + type: "object", + propertyNames: { + type: "string", + }, + additionalProperties: { + type: "object", + properties: { + historyLimit: { + type: "integer", + minimum: 0, + maximum: 9007199254740991, + }, + }, + additionalProperties: false, + }, + }, + textChunkLimit: { + type: "integer", + exclusiveMinimum: 0, + maximum: 9007199254740991, + }, + chunkMode: { + type: "string", + enum: ["length", "newline"], + }, + blockStreaming: { + type: "boolean", + }, + blockStreamingCoalesce: { + type: "object", + properties: { + minChars: { + type: "integer", + exclusiveMinimum: 0, + maximum: 9007199254740991, + }, + maxChars: { + type: "integer", + exclusiveMinimum: 0, + maximum: 9007199254740991, + }, + idleMs: { + type: "integer", + minimum: 0, + maximum: 9007199254740991, + }, + }, + additionalProperties: false, + }, + responsePrefix: { + type: "string", + }, + mediaMaxMb: { + type: "number", + exclusiveMinimum: 0, + }, + }, + required: ["dmPolicy", "groupPolicy"], + additionalProperties: false, + }, + }, + defaultAccount: { + type: "string", + }, + }, + required: ["dmPolicy", "groupPolicy"], + additionalProperties: false, + }, + label: "Nextcloud Talk", + description: "Self-hosted chat via Nextcloud Talk webhook bots.", + }, + }, }, }, { @@ -2333,6 +10941,100 @@ export const GENERATED_BUNDLED_PLUGIN_METADATA = [ properties: {}, }, channels: ["nostr"], + channelConfigs: { + nostr: { + schema: { + $schema: "http://json-schema.org/draft-07/schema#", + type: "object", + properties: { + name: { + type: "string", + }, + defaultAccount: { + type: "string", + }, + enabled: { + type: "boolean", + }, + markdown: { + type: "object", + properties: { + tables: { + type: "string", + enum: ["off", "bullets", "code"], + }, + }, + additionalProperties: false, + }, + privateKey: { + type: "string", + }, + relays: { + type: "array", + items: { + type: "string", + }, + }, + dmPolicy: { + type: "string", + enum: ["pairing", "allowlist", "open", "disabled"], + }, + allowFrom: { + type: "array", + items: { + anyOf: [ + { + type: "string", + }, + { + type: "number", + }, + ], + }, + }, + profile: { + type: "object", + properties: { + name: { + type: "string", + maxLength: 256, + }, + displayName: { + type: "string", + maxLength: 256, + }, + about: { + type: "string", + maxLength: 2000, + }, + picture: { + type: "string", + format: "uri", + }, + banner: { + type: "string", + format: "uri", + }, + website: { + type: "string", + format: "uri", + }, + nip05: { + type: "string", + }, + lud16: { + type: "string", + }, + }, + additionalProperties: false, + }, + }, + additionalProperties: false, + }, + label: "Nostr", + description: "Decentralized protocol; encrypted DMs via NIP-04.", + }, + }, }, }, { @@ -2893,6 +11595,662 @@ export const GENERATED_BUNDLED_PLUGIN_METADATA = [ properties: {}, }, channels: ["signal"], + channelConfigs: { + signal: { + schema: { + $schema: "http://json-schema.org/draft-07/schema#", + type: "object", + properties: { + name: { + type: "string", + }, + capabilities: { + type: "array", + items: { + type: "string", + }, + }, + markdown: { + type: "object", + properties: { + tables: { + type: "string", + enum: ["off", "bullets", "code"], + }, + }, + additionalProperties: false, + }, + enabled: { + type: "boolean", + }, + configWrites: { + type: "boolean", + }, + account: { + type: "string", + }, + accountUuid: { + type: "string", + }, + httpUrl: { + type: "string", + }, + httpHost: { + type: "string", + }, + httpPort: { + type: "integer", + exclusiveMinimum: 0, + maximum: 9007199254740991, + }, + cliPath: { + type: "string", + }, + autoStart: { + type: "boolean", + }, + startupTimeoutMs: { + type: "integer", + minimum: 1000, + maximum: 120000, + }, + receiveMode: { + anyOf: [ + { + type: "string", + const: "on-start", + }, + { + type: "string", + const: "manual", + }, + ], + }, + ignoreAttachments: { + type: "boolean", + }, + ignoreStories: { + type: "boolean", + }, + sendReadReceipts: { + type: "boolean", + }, + dmPolicy: { + default: "pairing", + type: "string", + enum: ["pairing", "allowlist", "open", "disabled"], + }, + allowFrom: { + type: "array", + items: { + anyOf: [ + { + type: "string", + }, + { + type: "number", + }, + ], + }, + }, + defaultTo: { + type: "string", + }, + groupAllowFrom: { + type: "array", + items: { + anyOf: [ + { + type: "string", + }, + { + type: "number", + }, + ], + }, + }, + groupPolicy: { + default: "allowlist", + type: "string", + enum: ["open", "disabled", "allowlist"], + }, + groups: { + type: "object", + propertyNames: { + type: "string", + }, + additionalProperties: { + type: "object", + properties: { + requireMention: { + type: "boolean", + }, + tools: { + type: "object", + properties: { + allow: { + type: "array", + items: { + type: "string", + }, + }, + alsoAllow: { + type: "array", + items: { + type: "string", + }, + }, + deny: { + type: "array", + items: { + type: "string", + }, + }, + }, + additionalProperties: false, + }, + toolsBySender: { + type: "object", + propertyNames: { + type: "string", + }, + additionalProperties: { + type: "object", + properties: { + allow: { + type: "array", + items: { + type: "string", + }, + }, + alsoAllow: { + type: "array", + items: { + type: "string", + }, + }, + deny: { + type: "array", + items: { + type: "string", + }, + }, + }, + additionalProperties: false, + }, + }, + }, + additionalProperties: false, + }, + }, + historyLimit: { + type: "integer", + minimum: 0, + maximum: 9007199254740991, + }, + dmHistoryLimit: { + type: "integer", + minimum: 0, + maximum: 9007199254740991, + }, + dms: { + type: "object", + propertyNames: { + type: "string", + }, + additionalProperties: { + type: "object", + properties: { + historyLimit: { + type: "integer", + minimum: 0, + maximum: 9007199254740991, + }, + }, + additionalProperties: false, + }, + }, + textChunkLimit: { + type: "integer", + exclusiveMinimum: 0, + maximum: 9007199254740991, + }, + chunkMode: { + type: "string", + enum: ["length", "newline"], + }, + blockStreaming: { + type: "boolean", + }, + blockStreamingCoalesce: { + type: "object", + properties: { + minChars: { + type: "integer", + exclusiveMinimum: 0, + maximum: 9007199254740991, + }, + maxChars: { + type: "integer", + exclusiveMinimum: 0, + maximum: 9007199254740991, + }, + idleMs: { + type: "integer", + minimum: 0, + maximum: 9007199254740991, + }, + }, + additionalProperties: false, + }, + mediaMaxMb: { + type: "integer", + exclusiveMinimum: 0, + maximum: 9007199254740991, + }, + reactionNotifications: { + type: "string", + enum: ["off", "own", "all", "allowlist"], + }, + reactionAllowlist: { + type: "array", + items: { + anyOf: [ + { + type: "string", + }, + { + type: "number", + }, + ], + }, + }, + actions: { + type: "object", + properties: { + reactions: { + type: "boolean", + }, + }, + additionalProperties: false, + }, + reactionLevel: { + type: "string", + enum: ["off", "ack", "minimal", "extensive"], + }, + heartbeat: { + type: "object", + properties: { + showOk: { + type: "boolean", + }, + showAlerts: { + type: "boolean", + }, + useIndicator: { + type: "boolean", + }, + }, + additionalProperties: false, + }, + healthMonitor: { + type: "object", + properties: { + enabled: { + type: "boolean", + }, + }, + additionalProperties: false, + }, + responsePrefix: { + type: "string", + }, + accounts: { + type: "object", + propertyNames: { + type: "string", + }, + additionalProperties: { + type: "object", + properties: { + name: { + type: "string", + }, + capabilities: { + type: "array", + items: { + type: "string", + }, + }, + markdown: { + type: "object", + properties: { + tables: { + type: "string", + enum: ["off", "bullets", "code"], + }, + }, + additionalProperties: false, + }, + enabled: { + type: "boolean", + }, + configWrites: { + type: "boolean", + }, + account: { + type: "string", + }, + accountUuid: { + type: "string", + }, + httpUrl: { + type: "string", + }, + httpHost: { + type: "string", + }, + httpPort: { + type: "integer", + exclusiveMinimum: 0, + maximum: 9007199254740991, + }, + cliPath: { + type: "string", + }, + autoStart: { + type: "boolean", + }, + startupTimeoutMs: { + type: "integer", + minimum: 1000, + maximum: 120000, + }, + receiveMode: { + anyOf: [ + { + type: "string", + const: "on-start", + }, + { + type: "string", + const: "manual", + }, + ], + }, + ignoreAttachments: { + type: "boolean", + }, + ignoreStories: { + type: "boolean", + }, + sendReadReceipts: { + type: "boolean", + }, + dmPolicy: { + default: "pairing", + type: "string", + enum: ["pairing", "allowlist", "open", "disabled"], + }, + allowFrom: { + type: "array", + items: { + anyOf: [ + { + type: "string", + }, + { + type: "number", + }, + ], + }, + }, + defaultTo: { + type: "string", + }, + groupAllowFrom: { + type: "array", + items: { + anyOf: [ + { + type: "string", + }, + { + type: "number", + }, + ], + }, + }, + groupPolicy: { + default: "allowlist", + type: "string", + enum: ["open", "disabled", "allowlist"], + }, + groups: { + type: "object", + propertyNames: { + type: "string", + }, + additionalProperties: { + type: "object", + properties: { + requireMention: { + type: "boolean", + }, + tools: { + type: "object", + properties: { + allow: { + type: "array", + items: { + type: "string", + }, + }, + alsoAllow: { + type: "array", + items: { + type: "string", + }, + }, + deny: { + type: "array", + items: { + type: "string", + }, + }, + }, + additionalProperties: false, + }, + toolsBySender: { + type: "object", + propertyNames: { + type: "string", + }, + additionalProperties: { + type: "object", + properties: { + allow: { + type: "array", + items: { + type: "string", + }, + }, + alsoAllow: { + type: "array", + items: { + type: "string", + }, + }, + deny: { + type: "array", + items: { + type: "string", + }, + }, + }, + additionalProperties: false, + }, + }, + }, + additionalProperties: false, + }, + }, + historyLimit: { + type: "integer", + minimum: 0, + maximum: 9007199254740991, + }, + dmHistoryLimit: { + type: "integer", + minimum: 0, + maximum: 9007199254740991, + }, + dms: { + type: "object", + propertyNames: { + type: "string", + }, + additionalProperties: { + type: "object", + properties: { + historyLimit: { + type: "integer", + minimum: 0, + maximum: 9007199254740991, + }, + }, + additionalProperties: false, + }, + }, + textChunkLimit: { + type: "integer", + exclusiveMinimum: 0, + maximum: 9007199254740991, + }, + chunkMode: { + type: "string", + enum: ["length", "newline"], + }, + blockStreaming: { + type: "boolean", + }, + blockStreamingCoalesce: { + type: "object", + properties: { + minChars: { + type: "integer", + exclusiveMinimum: 0, + maximum: 9007199254740991, + }, + maxChars: { + type: "integer", + exclusiveMinimum: 0, + maximum: 9007199254740991, + }, + idleMs: { + type: "integer", + minimum: 0, + maximum: 9007199254740991, + }, + }, + additionalProperties: false, + }, + mediaMaxMb: { + type: "integer", + exclusiveMinimum: 0, + maximum: 9007199254740991, + }, + reactionNotifications: { + type: "string", + enum: ["off", "own", "all", "allowlist"], + }, + reactionAllowlist: { + type: "array", + items: { + anyOf: [ + { + type: "string", + }, + { + type: "number", + }, + ], + }, + }, + actions: { + type: "object", + properties: { + reactions: { + type: "boolean", + }, + }, + additionalProperties: false, + }, + reactionLevel: { + type: "string", + enum: ["off", "ack", "minimal", "extensive"], + }, + heartbeat: { + type: "object", + properties: { + showOk: { + type: "boolean", + }, + showAlerts: { + type: "boolean", + }, + useIndicator: { + type: "boolean", + }, + }, + additionalProperties: false, + }, + healthMonitor: { + type: "object", + properties: { + enabled: { + type: "boolean", + }, + }, + additionalProperties: false, + }, + responsePrefix: { + type: "string", + }, + }, + required: ["dmPolicy", "groupPolicy"], + additionalProperties: false, + }, + }, + defaultAccount: { + type: "string", + }, + }, + required: ["dmPolicy", "groupPolicy"], + additionalProperties: false, + }, + uiHints: { + "": { + label: "Signal", + help: "Signal channel provider configuration including account identity and DM policy behavior. Keep account mapping explicit so routing remains stable across multi-device setups.", + }, + dmPolicy: { + label: "Signal DM Policy", + help: 'Direct message access control ("pairing" recommended). "open" requires channels.signal.allowFrom=["*"].', + }, + configWrites: { + label: "Signal Config Writes", + help: "Allow Signal to write config in response to channel events/commands (default: true).", + }, + account: { + label: "Signal Account", + help: "Signal account identifier (phone/number handle) used to bind this channel config to a specific Signal identity. Keep this aligned with your linked device/session state.", + }, + }, + label: "Signal", + description: 'signal-cli linked device; more setup (David Reagans: "Hop on Discord.").', + }, + }, }, }, { @@ -2931,6 +12289,1713 @@ export const GENERATED_BUNDLED_PLUGIN_METADATA = [ properties: {}, }, channels: ["slack"], + channelConfigs: { + slack: { + schema: { + $schema: "http://json-schema.org/draft-07/schema#", + type: "object", + properties: { + name: { + type: "string", + }, + mode: { + default: "socket", + type: "string", + enum: ["socket", "http"], + }, + signingSecret: { + anyOf: [ + { + type: "string", + }, + { + oneOf: [ + { + type: "object", + properties: { + source: { + type: "string", + const: "env", + }, + provider: { + type: "string", + pattern: "^[a-z][a-z0-9_-]{0,63}$", + }, + id: { + type: "string", + pattern: "^[A-Z][A-Z0-9_]{0,127}$", + }, + }, + required: ["source", "provider", "id"], + additionalProperties: false, + }, + { + type: "object", + properties: { + source: { + type: "string", + const: "file", + }, + provider: { + type: "string", + pattern: "^[a-z][a-z0-9_-]{0,63}$", + }, + id: { + type: "string", + }, + }, + required: ["source", "provider", "id"], + additionalProperties: false, + }, + { + type: "object", + properties: { + source: { + type: "string", + const: "exec", + }, + provider: { + type: "string", + pattern: "^[a-z][a-z0-9_-]{0,63}$", + }, + id: { + type: "string", + }, + }, + required: ["source", "provider", "id"], + additionalProperties: false, + }, + ], + }, + ], + }, + webhookPath: { + default: "/slack/events", + type: "string", + }, + capabilities: { + anyOf: [ + { + type: "array", + items: { + type: "string", + }, + }, + { + type: "object", + properties: { + interactiveReplies: { + type: "boolean", + }, + }, + additionalProperties: false, + }, + ], + }, + markdown: { + type: "object", + properties: { + tables: { + type: "string", + enum: ["off", "bullets", "code"], + }, + }, + additionalProperties: false, + }, + enabled: { + type: "boolean", + }, + commands: { + type: "object", + properties: { + native: { + anyOf: [ + { + type: "boolean", + }, + { + type: "string", + const: "auto", + }, + ], + }, + nativeSkills: { + anyOf: [ + { + type: "boolean", + }, + { + type: "string", + const: "auto", + }, + ], + }, + }, + additionalProperties: false, + }, + configWrites: { + type: "boolean", + }, + botToken: { + anyOf: [ + { + type: "string", + }, + { + oneOf: [ + { + type: "object", + properties: { + source: { + type: "string", + const: "env", + }, + provider: { + type: "string", + pattern: "^[a-z][a-z0-9_-]{0,63}$", + }, + id: { + type: "string", + pattern: "^[A-Z][A-Z0-9_]{0,127}$", + }, + }, + required: ["source", "provider", "id"], + additionalProperties: false, + }, + { + type: "object", + properties: { + source: { + type: "string", + const: "file", + }, + provider: { + type: "string", + pattern: "^[a-z][a-z0-9_-]{0,63}$", + }, + id: { + type: "string", + }, + }, + required: ["source", "provider", "id"], + additionalProperties: false, + }, + { + type: "object", + properties: { + source: { + type: "string", + const: "exec", + }, + provider: { + type: "string", + pattern: "^[a-z][a-z0-9_-]{0,63}$", + }, + id: { + type: "string", + }, + }, + required: ["source", "provider", "id"], + additionalProperties: false, + }, + ], + }, + ], + }, + appToken: { + anyOf: [ + { + type: "string", + }, + { + oneOf: [ + { + type: "object", + properties: { + source: { + type: "string", + const: "env", + }, + provider: { + type: "string", + pattern: "^[a-z][a-z0-9_-]{0,63}$", + }, + id: { + type: "string", + pattern: "^[A-Z][A-Z0-9_]{0,127}$", + }, + }, + required: ["source", "provider", "id"], + additionalProperties: false, + }, + { + type: "object", + properties: { + source: { + type: "string", + const: "file", + }, + provider: { + type: "string", + pattern: "^[a-z][a-z0-9_-]{0,63}$", + }, + id: { + type: "string", + }, + }, + required: ["source", "provider", "id"], + additionalProperties: false, + }, + { + type: "object", + properties: { + source: { + type: "string", + const: "exec", + }, + provider: { + type: "string", + pattern: "^[a-z][a-z0-9_-]{0,63}$", + }, + id: { + type: "string", + }, + }, + required: ["source", "provider", "id"], + additionalProperties: false, + }, + ], + }, + ], + }, + userToken: { + anyOf: [ + { + type: "string", + }, + { + oneOf: [ + { + type: "object", + properties: { + source: { + type: "string", + const: "env", + }, + provider: { + type: "string", + pattern: "^[a-z][a-z0-9_-]{0,63}$", + }, + id: { + type: "string", + pattern: "^[A-Z][A-Z0-9_]{0,127}$", + }, + }, + required: ["source", "provider", "id"], + additionalProperties: false, + }, + { + type: "object", + properties: { + source: { + type: "string", + const: "file", + }, + provider: { + type: "string", + pattern: "^[a-z][a-z0-9_-]{0,63}$", + }, + id: { + type: "string", + }, + }, + required: ["source", "provider", "id"], + additionalProperties: false, + }, + { + type: "object", + properties: { + source: { + type: "string", + const: "exec", + }, + provider: { + type: "string", + pattern: "^[a-z][a-z0-9_-]{0,63}$", + }, + id: { + type: "string", + }, + }, + required: ["source", "provider", "id"], + additionalProperties: false, + }, + ], + }, + ], + }, + userTokenReadOnly: { + default: true, + type: "boolean", + }, + allowBots: { + type: "boolean", + }, + dangerouslyAllowNameMatching: { + type: "boolean", + }, + requireMention: { + type: "boolean", + }, + groupPolicy: { + default: "allowlist", + type: "string", + enum: ["open", "disabled", "allowlist"], + }, + historyLimit: { + type: "integer", + minimum: 0, + maximum: 9007199254740991, + }, + dmHistoryLimit: { + type: "integer", + minimum: 0, + maximum: 9007199254740991, + }, + dms: { + type: "object", + propertyNames: { + type: "string", + }, + additionalProperties: { + type: "object", + properties: { + historyLimit: { + type: "integer", + minimum: 0, + maximum: 9007199254740991, + }, + }, + additionalProperties: false, + }, + }, + textChunkLimit: { + type: "integer", + exclusiveMinimum: 0, + maximum: 9007199254740991, + }, + chunkMode: { + type: "string", + enum: ["length", "newline"], + }, + blockStreaming: { + type: "boolean", + }, + blockStreamingCoalesce: { + type: "object", + properties: { + minChars: { + type: "integer", + exclusiveMinimum: 0, + maximum: 9007199254740991, + }, + maxChars: { + type: "integer", + exclusiveMinimum: 0, + maximum: 9007199254740991, + }, + idleMs: { + type: "integer", + minimum: 0, + maximum: 9007199254740991, + }, + }, + additionalProperties: false, + }, + streaming: { + anyOf: [ + { + type: "boolean", + }, + { + type: "string", + enum: ["off", "partial", "block", "progress"], + }, + ], + }, + nativeStreaming: { + type: "boolean", + }, + streamMode: { + type: "string", + enum: ["replace", "status_final", "append"], + }, + mediaMaxMb: { + type: "number", + exclusiveMinimum: 0, + }, + reactionNotifications: { + type: "string", + enum: ["off", "own", "all", "allowlist"], + }, + reactionAllowlist: { + type: "array", + items: { + anyOf: [ + { + type: "string", + }, + { + type: "number", + }, + ], + }, + }, + replyToMode: { + anyOf: [ + { + type: "string", + const: "off", + }, + { + type: "string", + const: "first", + }, + { + type: "string", + const: "all", + }, + ], + }, + replyToModeByChatType: { + type: "object", + properties: { + direct: { + anyOf: [ + { + type: "string", + const: "off", + }, + { + type: "string", + const: "first", + }, + { + type: "string", + const: "all", + }, + ], + }, + group: { + anyOf: [ + { + type: "string", + const: "off", + }, + { + type: "string", + const: "first", + }, + { + type: "string", + const: "all", + }, + ], + }, + channel: { + anyOf: [ + { + type: "string", + const: "off", + }, + { + type: "string", + const: "first", + }, + { + type: "string", + const: "all", + }, + ], + }, + }, + additionalProperties: false, + }, + thread: { + type: "object", + properties: { + historyScope: { + type: "string", + enum: ["thread", "channel"], + }, + inheritParent: { + type: "boolean", + }, + initialHistoryLimit: { + type: "integer", + minimum: 0, + maximum: 9007199254740991, + }, + }, + additionalProperties: false, + }, + actions: { + type: "object", + properties: { + reactions: { + type: "boolean", + }, + messages: { + type: "boolean", + }, + pins: { + type: "boolean", + }, + search: { + type: "boolean", + }, + permissions: { + type: "boolean", + }, + memberInfo: { + type: "boolean", + }, + channelInfo: { + type: "boolean", + }, + emojiList: { + type: "boolean", + }, + }, + additionalProperties: false, + }, + slashCommand: { + type: "object", + properties: { + enabled: { + type: "boolean", + }, + name: { + type: "string", + }, + sessionPrefix: { + type: "string", + }, + ephemeral: { + type: "boolean", + }, + }, + additionalProperties: false, + }, + dmPolicy: { + type: "string", + enum: ["pairing", "allowlist", "open", "disabled"], + }, + allowFrom: { + type: "array", + items: { + anyOf: [ + { + type: "string", + }, + { + type: "number", + }, + ], + }, + }, + defaultTo: { + type: "string", + }, + dm: { + type: "object", + properties: { + enabled: { + type: "boolean", + }, + policy: { + type: "string", + enum: ["pairing", "allowlist", "open", "disabled"], + }, + allowFrom: { + type: "array", + items: { + anyOf: [ + { + type: "string", + }, + { + type: "number", + }, + ], + }, + }, + groupEnabled: { + type: "boolean", + }, + groupChannels: { + type: "array", + items: { + anyOf: [ + { + type: "string", + }, + { + type: "number", + }, + ], + }, + }, + replyToMode: { + anyOf: [ + { + type: "string", + const: "off", + }, + { + type: "string", + const: "first", + }, + { + type: "string", + const: "all", + }, + ], + }, + }, + additionalProperties: false, + }, + channels: { + type: "object", + propertyNames: { + type: "string", + }, + additionalProperties: { + type: "object", + properties: { + enabled: { + type: "boolean", + }, + allow: { + type: "boolean", + }, + requireMention: { + type: "boolean", + }, + tools: { + type: "object", + properties: { + allow: { + type: "array", + items: { + type: "string", + }, + }, + alsoAllow: { + type: "array", + items: { + type: "string", + }, + }, + deny: { + type: "array", + items: { + type: "string", + }, + }, + }, + additionalProperties: false, + }, + toolsBySender: { + type: "object", + propertyNames: { + type: "string", + }, + additionalProperties: { + type: "object", + properties: { + allow: { + type: "array", + items: { + type: "string", + }, + }, + alsoAllow: { + type: "array", + items: { + type: "string", + }, + }, + deny: { + type: "array", + items: { + type: "string", + }, + }, + }, + additionalProperties: false, + }, + }, + allowBots: { + type: "boolean", + }, + users: { + type: "array", + items: { + anyOf: [ + { + type: "string", + }, + { + type: "number", + }, + ], + }, + }, + skills: { + type: "array", + items: { + type: "string", + }, + }, + systemPrompt: { + type: "string", + }, + }, + additionalProperties: false, + }, + }, + heartbeat: { + type: "object", + properties: { + showOk: { + type: "boolean", + }, + showAlerts: { + type: "boolean", + }, + useIndicator: { + type: "boolean", + }, + }, + additionalProperties: false, + }, + healthMonitor: { + type: "object", + properties: { + enabled: { + type: "boolean", + }, + }, + additionalProperties: false, + }, + responsePrefix: { + type: "string", + }, + ackReaction: { + type: "string", + }, + typingReaction: { + type: "string", + }, + accounts: { + type: "object", + propertyNames: { + type: "string", + }, + additionalProperties: { + type: "object", + properties: { + name: { + type: "string", + }, + mode: { + type: "string", + enum: ["socket", "http"], + }, + signingSecret: { + anyOf: [ + { + type: "string", + }, + { + oneOf: [ + { + type: "object", + properties: { + source: { + type: "string", + const: "env", + }, + provider: { + type: "string", + pattern: "^[a-z][a-z0-9_-]{0,63}$", + }, + id: { + type: "string", + pattern: "^[A-Z][A-Z0-9_]{0,127}$", + }, + }, + required: ["source", "provider", "id"], + additionalProperties: false, + }, + { + type: "object", + properties: { + source: { + type: "string", + const: "file", + }, + provider: { + type: "string", + pattern: "^[a-z][a-z0-9_-]{0,63}$", + }, + id: { + type: "string", + }, + }, + required: ["source", "provider", "id"], + additionalProperties: false, + }, + { + type: "object", + properties: { + source: { + type: "string", + const: "exec", + }, + provider: { + type: "string", + pattern: "^[a-z][a-z0-9_-]{0,63}$", + }, + id: { + type: "string", + }, + }, + required: ["source", "provider", "id"], + additionalProperties: false, + }, + ], + }, + ], + }, + webhookPath: { + type: "string", + }, + capabilities: { + anyOf: [ + { + type: "array", + items: { + type: "string", + }, + }, + { + type: "object", + properties: { + interactiveReplies: { + type: "boolean", + }, + }, + additionalProperties: false, + }, + ], + }, + markdown: { + type: "object", + properties: { + tables: { + type: "string", + enum: ["off", "bullets", "code"], + }, + }, + additionalProperties: false, + }, + enabled: { + type: "boolean", + }, + commands: { + type: "object", + properties: { + native: { + anyOf: [ + { + type: "boolean", + }, + { + type: "string", + const: "auto", + }, + ], + }, + nativeSkills: { + anyOf: [ + { + type: "boolean", + }, + { + type: "string", + const: "auto", + }, + ], + }, + }, + additionalProperties: false, + }, + configWrites: { + type: "boolean", + }, + botToken: { + anyOf: [ + { + type: "string", + }, + { + oneOf: [ + { + type: "object", + properties: { + source: { + type: "string", + const: "env", + }, + provider: { + type: "string", + pattern: "^[a-z][a-z0-9_-]{0,63}$", + }, + id: { + type: "string", + pattern: "^[A-Z][A-Z0-9_]{0,127}$", + }, + }, + required: ["source", "provider", "id"], + additionalProperties: false, + }, + { + type: "object", + properties: { + source: { + type: "string", + const: "file", + }, + provider: { + type: "string", + pattern: "^[a-z][a-z0-9_-]{0,63}$", + }, + id: { + type: "string", + }, + }, + required: ["source", "provider", "id"], + additionalProperties: false, + }, + { + type: "object", + properties: { + source: { + type: "string", + const: "exec", + }, + provider: { + type: "string", + pattern: "^[a-z][a-z0-9_-]{0,63}$", + }, + id: { + type: "string", + }, + }, + required: ["source", "provider", "id"], + additionalProperties: false, + }, + ], + }, + ], + }, + appToken: { + anyOf: [ + { + type: "string", + }, + { + oneOf: [ + { + type: "object", + properties: { + source: { + type: "string", + const: "env", + }, + provider: { + type: "string", + pattern: "^[a-z][a-z0-9_-]{0,63}$", + }, + id: { + type: "string", + pattern: "^[A-Z][A-Z0-9_]{0,127}$", + }, + }, + required: ["source", "provider", "id"], + additionalProperties: false, + }, + { + type: "object", + properties: { + source: { + type: "string", + const: "file", + }, + provider: { + type: "string", + pattern: "^[a-z][a-z0-9_-]{0,63}$", + }, + id: { + type: "string", + }, + }, + required: ["source", "provider", "id"], + additionalProperties: false, + }, + { + type: "object", + properties: { + source: { + type: "string", + const: "exec", + }, + provider: { + type: "string", + pattern: "^[a-z][a-z0-9_-]{0,63}$", + }, + id: { + type: "string", + }, + }, + required: ["source", "provider", "id"], + additionalProperties: false, + }, + ], + }, + ], + }, + userToken: { + anyOf: [ + { + type: "string", + }, + { + oneOf: [ + { + type: "object", + properties: { + source: { + type: "string", + const: "env", + }, + provider: { + type: "string", + pattern: "^[a-z][a-z0-9_-]{0,63}$", + }, + id: { + type: "string", + pattern: "^[A-Z][A-Z0-9_]{0,127}$", + }, + }, + required: ["source", "provider", "id"], + additionalProperties: false, + }, + { + type: "object", + properties: { + source: { + type: "string", + const: "file", + }, + provider: { + type: "string", + pattern: "^[a-z][a-z0-9_-]{0,63}$", + }, + id: { + type: "string", + }, + }, + required: ["source", "provider", "id"], + additionalProperties: false, + }, + { + type: "object", + properties: { + source: { + type: "string", + const: "exec", + }, + provider: { + type: "string", + pattern: "^[a-z][a-z0-9_-]{0,63}$", + }, + id: { + type: "string", + }, + }, + required: ["source", "provider", "id"], + additionalProperties: false, + }, + ], + }, + ], + }, + userTokenReadOnly: { + default: true, + type: "boolean", + }, + allowBots: { + type: "boolean", + }, + dangerouslyAllowNameMatching: { + type: "boolean", + }, + requireMention: { + type: "boolean", + }, + groupPolicy: { + type: "string", + enum: ["open", "disabled", "allowlist"], + }, + historyLimit: { + type: "integer", + minimum: 0, + maximum: 9007199254740991, + }, + dmHistoryLimit: { + type: "integer", + minimum: 0, + maximum: 9007199254740991, + }, + dms: { + type: "object", + propertyNames: { + type: "string", + }, + additionalProperties: { + type: "object", + properties: { + historyLimit: { + type: "integer", + minimum: 0, + maximum: 9007199254740991, + }, + }, + additionalProperties: false, + }, + }, + textChunkLimit: { + type: "integer", + exclusiveMinimum: 0, + maximum: 9007199254740991, + }, + chunkMode: { + type: "string", + enum: ["length", "newline"], + }, + blockStreaming: { + type: "boolean", + }, + blockStreamingCoalesce: { + type: "object", + properties: { + minChars: { + type: "integer", + exclusiveMinimum: 0, + maximum: 9007199254740991, + }, + maxChars: { + type: "integer", + exclusiveMinimum: 0, + maximum: 9007199254740991, + }, + idleMs: { + type: "integer", + minimum: 0, + maximum: 9007199254740991, + }, + }, + additionalProperties: false, + }, + streaming: { + anyOf: [ + { + type: "boolean", + }, + { + type: "string", + enum: ["off", "partial", "block", "progress"], + }, + ], + }, + nativeStreaming: { + type: "boolean", + }, + streamMode: { + type: "string", + enum: ["replace", "status_final", "append"], + }, + mediaMaxMb: { + type: "number", + exclusiveMinimum: 0, + }, + reactionNotifications: { + type: "string", + enum: ["off", "own", "all", "allowlist"], + }, + reactionAllowlist: { + type: "array", + items: { + anyOf: [ + { + type: "string", + }, + { + type: "number", + }, + ], + }, + }, + replyToMode: { + anyOf: [ + { + type: "string", + const: "off", + }, + { + type: "string", + const: "first", + }, + { + type: "string", + const: "all", + }, + ], + }, + replyToModeByChatType: { + type: "object", + properties: { + direct: { + anyOf: [ + { + type: "string", + const: "off", + }, + { + type: "string", + const: "first", + }, + { + type: "string", + const: "all", + }, + ], + }, + group: { + anyOf: [ + { + type: "string", + const: "off", + }, + { + type: "string", + const: "first", + }, + { + type: "string", + const: "all", + }, + ], + }, + channel: { + anyOf: [ + { + type: "string", + const: "off", + }, + { + type: "string", + const: "first", + }, + { + type: "string", + const: "all", + }, + ], + }, + }, + additionalProperties: false, + }, + thread: { + type: "object", + properties: { + historyScope: { + type: "string", + enum: ["thread", "channel"], + }, + inheritParent: { + type: "boolean", + }, + initialHistoryLimit: { + type: "integer", + minimum: 0, + maximum: 9007199254740991, + }, + }, + additionalProperties: false, + }, + actions: { + type: "object", + properties: { + reactions: { + type: "boolean", + }, + messages: { + type: "boolean", + }, + pins: { + type: "boolean", + }, + search: { + type: "boolean", + }, + permissions: { + type: "boolean", + }, + memberInfo: { + type: "boolean", + }, + channelInfo: { + type: "boolean", + }, + emojiList: { + type: "boolean", + }, + }, + additionalProperties: false, + }, + slashCommand: { + type: "object", + properties: { + enabled: { + type: "boolean", + }, + name: { + type: "string", + }, + sessionPrefix: { + type: "string", + }, + ephemeral: { + type: "boolean", + }, + }, + additionalProperties: false, + }, + dmPolicy: { + type: "string", + enum: ["pairing", "allowlist", "open", "disabled"], + }, + allowFrom: { + type: "array", + items: { + anyOf: [ + { + type: "string", + }, + { + type: "number", + }, + ], + }, + }, + defaultTo: { + type: "string", + }, + dm: { + type: "object", + properties: { + enabled: { + type: "boolean", + }, + policy: { + type: "string", + enum: ["pairing", "allowlist", "open", "disabled"], + }, + allowFrom: { + type: "array", + items: { + anyOf: [ + { + type: "string", + }, + { + type: "number", + }, + ], + }, + }, + groupEnabled: { + type: "boolean", + }, + groupChannels: { + type: "array", + items: { + anyOf: [ + { + type: "string", + }, + { + type: "number", + }, + ], + }, + }, + replyToMode: { + anyOf: [ + { + type: "string", + const: "off", + }, + { + type: "string", + const: "first", + }, + { + type: "string", + const: "all", + }, + ], + }, + }, + additionalProperties: false, + }, + channels: { + type: "object", + propertyNames: { + type: "string", + }, + additionalProperties: { + type: "object", + properties: { + enabled: { + type: "boolean", + }, + allow: { + type: "boolean", + }, + requireMention: { + type: "boolean", + }, + tools: { + type: "object", + properties: { + allow: { + type: "array", + items: { + type: "string", + }, + }, + alsoAllow: { + type: "array", + items: { + type: "string", + }, + }, + deny: { + type: "array", + items: { + type: "string", + }, + }, + }, + additionalProperties: false, + }, + toolsBySender: { + type: "object", + propertyNames: { + type: "string", + }, + additionalProperties: { + type: "object", + properties: { + allow: { + type: "array", + items: { + type: "string", + }, + }, + alsoAllow: { + type: "array", + items: { + type: "string", + }, + }, + deny: { + type: "array", + items: { + type: "string", + }, + }, + }, + additionalProperties: false, + }, + }, + allowBots: { + type: "boolean", + }, + users: { + type: "array", + items: { + anyOf: [ + { + type: "string", + }, + { + type: "number", + }, + ], + }, + }, + skills: { + type: "array", + items: { + type: "string", + }, + }, + systemPrompt: { + type: "string", + }, + }, + additionalProperties: false, + }, + }, + heartbeat: { + type: "object", + properties: { + showOk: { + type: "boolean", + }, + showAlerts: { + type: "boolean", + }, + useIndicator: { + type: "boolean", + }, + }, + additionalProperties: false, + }, + healthMonitor: { + type: "object", + properties: { + enabled: { + type: "boolean", + }, + }, + additionalProperties: false, + }, + responsePrefix: { + type: "string", + }, + ackReaction: { + type: "string", + }, + typingReaction: { + type: "string", + }, + }, + required: ["userTokenReadOnly"], + additionalProperties: false, + }, + }, + defaultAccount: { + type: "string", + }, + }, + required: ["mode", "webhookPath", "userTokenReadOnly", "groupPolicy"], + additionalProperties: false, + }, + uiHints: { + "": { + label: "Slack", + help: "Slack channel provider configuration for bot/app tokens, streaming behavior, and DM policy controls. Keep token handling and thread behavior explicit to avoid noisy workspace interactions.", + }, + "dm.policy": { + label: "Slack DM Policy", + help: 'Direct message access control ("pairing" recommended). "open" requires channels.slack.allowFrom=["*"] (legacy: channels.slack.dm.allowFrom).', + }, + dmPolicy: { + label: "Slack DM Policy", + help: 'Direct message access control ("pairing" recommended). "open" requires channels.slack.allowFrom=["*"].', + }, + configWrites: { + label: "Slack Config Writes", + help: "Allow Slack to write config in response to channel events/commands (default: true).", + }, + "commands.native": { + label: "Slack Native Commands", + help: 'Override native commands for Slack (bool or "auto").', + }, + "commands.nativeSkills": { + label: "Slack Native Skill Commands", + help: 'Override native skill commands for Slack (bool or "auto").', + }, + allowBots: { + label: "Slack Allow Bot Messages", + help: "Allow bot-authored messages to trigger Slack replies (default: false).", + }, + botToken: { + label: "Slack Bot Token", + help: "Slack bot token used for standard chat actions in the configured workspace. Keep this credential scoped and rotate if workspace app permissions change.", + }, + appToken: { + label: "Slack App Token", + help: "Slack app-level token used for Socket Mode connections and event transport when enabled. Use least-privilege app scopes and store this token as a secret.", + }, + userToken: { + label: "Slack User Token", + help: "Optional Slack user token for workflows requiring user-context API access beyond bot permissions. Use sparingly and audit scopes because this token can carry broader authority.", + }, + userTokenReadOnly: { + label: "Slack User Token Read Only", + help: "When true, treat configured Slack user token usage as read-only helper behavior where possible. Keep enabled if you only need supplemental reads without user-context writes.", + }, + "capabilities.interactiveReplies": { + label: "Slack Interactive Replies", + help: "Enable agent-authored Slack interactive reply directives (`[[slack_buttons: ...]]`, `[[slack_select: ...]]`). Default: false.", + }, + streaming: { + label: "Slack Streaming Mode", + help: 'Unified Slack stream preview mode: "off" | "partial" | "block" | "progress". Legacy boolean/streamMode keys are auto-mapped.', + }, + nativeStreaming: { + label: "Slack Native Streaming", + help: "Enable native Slack text streaming (chat.startStream/chat.appendStream/chat.stopStream) when channels.slack.streaming is partial (default: true).", + }, + streamMode: { + label: "Slack Stream Mode (Legacy)", + help: "Legacy Slack preview mode alias (replace | status_final | append); auto-migrated to channels.slack.streaming.", + }, + "thread.historyScope": { + label: "Slack Thread History Scope", + help: 'Scope for Slack thread history context ("thread" isolates per thread; "channel" reuses channel history).', + }, + "thread.inheritParent": { + label: "Slack Thread Parent Inheritance", + help: "If true, Slack thread sessions inherit the parent channel transcript (default: false).", + }, + "thread.initialHistoryLimit": { + label: "Slack Thread Initial History Limit", + help: "Maximum number of existing Slack thread messages to fetch when starting a new thread session (default: 20, set to 0 to disable).", + }, + }, + label: "Slack", + description: "supported (Socket Mode).", + }, + }, }, }, { @@ -2974,6 +14039,25 @@ export const GENERATED_BUNDLED_PLUGIN_METADATA = [ properties: {}, }, channels: ["synology-chat"], + channelConfigs: { + "synology-chat": { + schema: { + $schema: "http://json-schema.org/draft-07/schema#", + type: "object", + properties: { + dangerouslyAllowNameMatching: { + type: "boolean", + }, + dangerouslyAllowInheritedWebhookPath: { + type: "boolean", + }, + }, + additionalProperties: {}, + }, + label: "Synology Chat", + description: "Connect your Synology NAS Chat to OpenClaw with full agent capabilities.", + }, + }, }, }, { @@ -3108,6 +14192,2049 @@ export const GENERATED_BUNDLED_PLUGIN_METADATA = [ properties: {}, }, channels: ["telegram"], + channelConfigs: { + telegram: { + schema: { + $schema: "http://json-schema.org/draft-07/schema#", + type: "object", + properties: { + name: { + type: "string", + }, + capabilities: { + anyOf: [ + { + type: "array", + items: { + type: "string", + }, + }, + { + type: "object", + properties: { + inlineButtons: { + type: "string", + enum: ["off", "dm", "group", "all", "allowlist"], + }, + }, + additionalProperties: false, + }, + ], + }, + execApprovals: { + type: "object", + properties: { + enabled: { + type: "boolean", + }, + approvers: { + type: "array", + items: { + anyOf: [ + { + type: "string", + }, + { + type: "number", + }, + ], + }, + }, + agentFilter: { + type: "array", + items: { + type: "string", + }, + }, + sessionFilter: { + type: "array", + items: { + type: "string", + }, + }, + target: { + type: "string", + enum: ["dm", "channel", "both"], + }, + }, + additionalProperties: false, + }, + markdown: { + type: "object", + properties: { + tables: { + type: "string", + enum: ["off", "bullets", "code"], + }, + }, + additionalProperties: false, + }, + enabled: { + type: "boolean", + }, + commands: { + type: "object", + properties: { + native: { + anyOf: [ + { + type: "boolean", + }, + { + type: "string", + const: "auto", + }, + ], + }, + nativeSkills: { + anyOf: [ + { + type: "boolean", + }, + { + type: "string", + const: "auto", + }, + ], + }, + }, + additionalProperties: false, + }, + customCommands: { + type: "array", + items: { + type: "object", + properties: { + command: { + type: "string", + }, + description: { + type: "string", + }, + }, + required: ["command", "description"], + additionalProperties: false, + }, + }, + configWrites: { + type: "boolean", + }, + dmPolicy: { + default: "pairing", + type: "string", + enum: ["pairing", "allowlist", "open", "disabled"], + }, + botToken: { + anyOf: [ + { + type: "string", + }, + { + oneOf: [ + { + type: "object", + properties: { + source: { + type: "string", + const: "env", + }, + provider: { + type: "string", + pattern: "^[a-z][a-z0-9_-]{0,63}$", + }, + id: { + type: "string", + pattern: "^[A-Z][A-Z0-9_]{0,127}$", + }, + }, + required: ["source", "provider", "id"], + additionalProperties: false, + }, + { + type: "object", + properties: { + source: { + type: "string", + const: "file", + }, + provider: { + type: "string", + pattern: "^[a-z][a-z0-9_-]{0,63}$", + }, + id: { + type: "string", + }, + }, + required: ["source", "provider", "id"], + additionalProperties: false, + }, + { + type: "object", + properties: { + source: { + type: "string", + const: "exec", + }, + provider: { + type: "string", + pattern: "^[a-z][a-z0-9_-]{0,63}$", + }, + id: { + type: "string", + }, + }, + required: ["source", "provider", "id"], + additionalProperties: false, + }, + ], + }, + ], + }, + tokenFile: { + type: "string", + }, + replyToMode: { + anyOf: [ + { + type: "string", + const: "off", + }, + { + type: "string", + const: "first", + }, + { + type: "string", + const: "all", + }, + ], + }, + groups: { + type: "object", + propertyNames: { + type: "string", + }, + additionalProperties: { + type: "object", + properties: { + requireMention: { + type: "boolean", + }, + disableAudioPreflight: { + type: "boolean", + }, + groupPolicy: { + type: "string", + enum: ["open", "disabled", "allowlist"], + }, + tools: { + type: "object", + properties: { + allow: { + type: "array", + items: { + type: "string", + }, + }, + alsoAllow: { + type: "array", + items: { + type: "string", + }, + }, + deny: { + type: "array", + items: { + type: "string", + }, + }, + }, + additionalProperties: false, + }, + toolsBySender: { + type: "object", + propertyNames: { + type: "string", + }, + additionalProperties: { + type: "object", + properties: { + allow: { + type: "array", + items: { + type: "string", + }, + }, + alsoAllow: { + type: "array", + items: { + type: "string", + }, + }, + deny: { + type: "array", + items: { + type: "string", + }, + }, + }, + additionalProperties: false, + }, + }, + skills: { + type: "array", + items: { + type: "string", + }, + }, + enabled: { + type: "boolean", + }, + allowFrom: { + type: "array", + items: { + anyOf: [ + { + type: "string", + }, + { + type: "number", + }, + ], + }, + }, + systemPrompt: { + type: "string", + }, + topics: { + type: "object", + propertyNames: { + type: "string", + }, + additionalProperties: { + type: "object", + properties: { + requireMention: { + type: "boolean", + }, + disableAudioPreflight: { + type: "boolean", + }, + groupPolicy: { + type: "string", + enum: ["open", "disabled", "allowlist"], + }, + skills: { + type: "array", + items: { + type: "string", + }, + }, + enabled: { + type: "boolean", + }, + allowFrom: { + type: "array", + items: { + anyOf: [ + { + type: "string", + }, + { + type: "number", + }, + ], + }, + }, + systemPrompt: { + type: "string", + }, + agentId: { + type: "string", + }, + }, + additionalProperties: false, + }, + }, + }, + additionalProperties: false, + }, + }, + allowFrom: { + type: "array", + items: { + anyOf: [ + { + type: "string", + }, + { + type: "number", + }, + ], + }, + }, + defaultTo: { + anyOf: [ + { + type: "string", + }, + { + type: "number", + }, + ], + }, + groupAllowFrom: { + type: "array", + items: { + anyOf: [ + { + type: "string", + }, + { + type: "number", + }, + ], + }, + }, + groupPolicy: { + default: "allowlist", + type: "string", + enum: ["open", "disabled", "allowlist"], + }, + historyLimit: { + type: "integer", + minimum: 0, + maximum: 9007199254740991, + }, + dmHistoryLimit: { + type: "integer", + minimum: 0, + maximum: 9007199254740991, + }, + dms: { + type: "object", + propertyNames: { + type: "string", + }, + additionalProperties: { + type: "object", + properties: { + historyLimit: { + type: "integer", + minimum: 0, + maximum: 9007199254740991, + }, + }, + additionalProperties: false, + }, + }, + direct: { + type: "object", + propertyNames: { + type: "string", + }, + additionalProperties: { + type: "object", + properties: { + dmPolicy: { + type: "string", + enum: ["pairing", "allowlist", "open", "disabled"], + }, + tools: { + type: "object", + properties: { + allow: { + type: "array", + items: { + type: "string", + }, + }, + alsoAllow: { + type: "array", + items: { + type: "string", + }, + }, + deny: { + type: "array", + items: { + type: "string", + }, + }, + }, + additionalProperties: false, + }, + toolsBySender: { + type: "object", + propertyNames: { + type: "string", + }, + additionalProperties: { + type: "object", + properties: { + allow: { + type: "array", + items: { + type: "string", + }, + }, + alsoAllow: { + type: "array", + items: { + type: "string", + }, + }, + deny: { + type: "array", + items: { + type: "string", + }, + }, + }, + additionalProperties: false, + }, + }, + skills: { + type: "array", + items: { + type: "string", + }, + }, + enabled: { + type: "boolean", + }, + allowFrom: { + type: "array", + items: { + anyOf: [ + { + type: "string", + }, + { + type: "number", + }, + ], + }, + }, + systemPrompt: { + type: "string", + }, + topics: { + type: "object", + propertyNames: { + type: "string", + }, + additionalProperties: { + type: "object", + properties: { + requireMention: { + type: "boolean", + }, + disableAudioPreflight: { + type: "boolean", + }, + groupPolicy: { + type: "string", + enum: ["open", "disabled", "allowlist"], + }, + skills: { + type: "array", + items: { + type: "string", + }, + }, + enabled: { + type: "boolean", + }, + allowFrom: { + type: "array", + items: { + anyOf: [ + { + type: "string", + }, + { + type: "number", + }, + ], + }, + }, + systemPrompt: { + type: "string", + }, + agentId: { + type: "string", + }, + }, + additionalProperties: false, + }, + }, + requireTopic: { + type: "boolean", + }, + autoTopicLabel: { + anyOf: [ + { + type: "boolean", + }, + { + type: "object", + properties: { + enabled: { + type: "boolean", + }, + prompt: { + type: "string", + }, + }, + additionalProperties: false, + }, + ], + }, + }, + additionalProperties: false, + }, + }, + textChunkLimit: { + type: "integer", + exclusiveMinimum: 0, + maximum: 9007199254740991, + }, + chunkMode: { + type: "string", + enum: ["length", "newline"], + }, + streaming: { + anyOf: [ + { + type: "boolean", + }, + { + type: "string", + enum: ["off", "partial", "block", "progress"], + }, + ], + }, + blockStreaming: { + type: "boolean", + }, + draftChunk: { + type: "object", + properties: { + minChars: { + type: "integer", + exclusiveMinimum: 0, + maximum: 9007199254740991, + }, + maxChars: { + type: "integer", + exclusiveMinimum: 0, + maximum: 9007199254740991, + }, + breakPreference: { + anyOf: [ + { + type: "string", + const: "paragraph", + }, + { + type: "string", + const: "newline", + }, + { + type: "string", + const: "sentence", + }, + ], + }, + }, + additionalProperties: false, + }, + blockStreamingCoalesce: { + type: "object", + properties: { + minChars: { + type: "integer", + exclusiveMinimum: 0, + maximum: 9007199254740991, + }, + maxChars: { + type: "integer", + exclusiveMinimum: 0, + maximum: 9007199254740991, + }, + idleMs: { + type: "integer", + minimum: 0, + maximum: 9007199254740991, + }, + }, + additionalProperties: false, + }, + streamMode: { + type: "string", + enum: ["off", "partial", "block"], + }, + mediaMaxMb: { + type: "number", + exclusiveMinimum: 0, + }, + timeoutSeconds: { + type: "integer", + exclusiveMinimum: 0, + maximum: 9007199254740991, + }, + retry: { + type: "object", + properties: { + attempts: { + type: "integer", + minimum: 1, + maximum: 9007199254740991, + }, + minDelayMs: { + type: "integer", + minimum: 0, + maximum: 9007199254740991, + }, + maxDelayMs: { + type: "integer", + minimum: 0, + maximum: 9007199254740991, + }, + jitter: { + type: "number", + minimum: 0, + maximum: 1, + }, + }, + additionalProperties: false, + }, + network: { + type: "object", + properties: { + autoSelectFamily: { + type: "boolean", + }, + dnsResultOrder: { + type: "string", + enum: ["ipv4first", "verbatim"], + }, + }, + additionalProperties: false, + }, + proxy: { + type: "string", + }, + webhookUrl: { + description: + "Public HTTPS webhook URL registered with Telegram for inbound updates. This must be internet-reachable and requires channels.telegram.webhookSecret.", + type: "string", + }, + webhookSecret: { + description: + "Secret token sent to Telegram during webhook registration and verified on inbound webhook requests. Telegram returns this value for verification; this is not the gateway auth token and not the bot token.", + anyOf: [ + { + type: "string", + }, + { + oneOf: [ + { + type: "object", + properties: { + source: { + type: "string", + const: "env", + }, + provider: { + type: "string", + pattern: "^[a-z][a-z0-9_-]{0,63}$", + }, + id: { + type: "string", + pattern: "^[A-Z][A-Z0-9_]{0,127}$", + }, + }, + required: ["source", "provider", "id"], + additionalProperties: false, + }, + { + type: "object", + properties: { + source: { + type: "string", + const: "file", + }, + provider: { + type: "string", + pattern: "^[a-z][a-z0-9_-]{0,63}$", + }, + id: { + type: "string", + }, + }, + required: ["source", "provider", "id"], + additionalProperties: false, + }, + { + type: "object", + properties: { + source: { + type: "string", + const: "exec", + }, + provider: { + type: "string", + pattern: "^[a-z][a-z0-9_-]{0,63}$", + }, + id: { + type: "string", + }, + }, + required: ["source", "provider", "id"], + additionalProperties: false, + }, + ], + }, + ], + }, + webhookPath: { + description: + "Local webhook route path served by the gateway listener. Defaults to /telegram-webhook.", + type: "string", + }, + webhookHost: { + description: + "Local bind host for the webhook listener. Defaults to 127.0.0.1; keep loopback unless you intentionally expose direct ingress.", + type: "string", + }, + webhookPort: { + description: + "Local bind port for the webhook listener. Defaults to 8787; set to 0 to let the OS assign an ephemeral port.", + type: "integer", + minimum: 0, + maximum: 9007199254740991, + }, + webhookCertPath: { + description: + "Path to the self-signed certificate (PEM) to upload to Telegram during webhook registration. Required for self-signed certs (direct IP or no domain).", + type: "string", + }, + actions: { + type: "object", + properties: { + reactions: { + type: "boolean", + }, + sendMessage: { + type: "boolean", + }, + poll: { + type: "boolean", + }, + deleteMessage: { + type: "boolean", + }, + editMessage: { + type: "boolean", + }, + sticker: { + type: "boolean", + }, + createForumTopic: { + type: "boolean", + }, + editForumTopic: { + type: "boolean", + }, + }, + additionalProperties: false, + }, + threadBindings: { + type: "object", + properties: { + enabled: { + type: "boolean", + }, + idleHours: { + type: "number", + minimum: 0, + }, + maxAgeHours: { + type: "number", + minimum: 0, + }, + spawnSubagentSessions: { + type: "boolean", + }, + spawnAcpSessions: { + type: "boolean", + }, + }, + additionalProperties: false, + }, + reactionNotifications: { + type: "string", + enum: ["off", "own", "all"], + }, + reactionLevel: { + type: "string", + enum: ["off", "ack", "minimal", "extensive"], + }, + heartbeat: { + type: "object", + properties: { + showOk: { + type: "boolean", + }, + showAlerts: { + type: "boolean", + }, + useIndicator: { + type: "boolean", + }, + }, + additionalProperties: false, + }, + healthMonitor: { + type: "object", + properties: { + enabled: { + type: "boolean", + }, + }, + additionalProperties: false, + }, + linkPreview: { + type: "boolean", + }, + silentErrorReplies: { + type: "boolean", + }, + responsePrefix: { + type: "string", + }, + ackReaction: { + type: "string", + }, + apiRoot: { + type: "string", + format: "uri", + }, + autoTopicLabel: { + anyOf: [ + { + type: "boolean", + }, + { + type: "object", + properties: { + enabled: { + type: "boolean", + }, + prompt: { + type: "string", + }, + }, + additionalProperties: false, + }, + ], + }, + accounts: { + type: "object", + propertyNames: { + type: "string", + }, + additionalProperties: { + type: "object", + properties: { + name: { + type: "string", + }, + capabilities: { + anyOf: [ + { + type: "array", + items: { + type: "string", + }, + }, + { + type: "object", + properties: { + inlineButtons: { + type: "string", + enum: ["off", "dm", "group", "all", "allowlist"], + }, + }, + additionalProperties: false, + }, + ], + }, + execApprovals: { + type: "object", + properties: { + enabled: { + type: "boolean", + }, + approvers: { + type: "array", + items: { + anyOf: [ + { + type: "string", + }, + { + type: "number", + }, + ], + }, + }, + agentFilter: { + type: "array", + items: { + type: "string", + }, + }, + sessionFilter: { + type: "array", + items: { + type: "string", + }, + }, + target: { + type: "string", + enum: ["dm", "channel", "both"], + }, + }, + additionalProperties: false, + }, + markdown: { + type: "object", + properties: { + tables: { + type: "string", + enum: ["off", "bullets", "code"], + }, + }, + additionalProperties: false, + }, + enabled: { + type: "boolean", + }, + commands: { + type: "object", + properties: { + native: { + anyOf: [ + { + type: "boolean", + }, + { + type: "string", + const: "auto", + }, + ], + }, + nativeSkills: { + anyOf: [ + { + type: "boolean", + }, + { + type: "string", + const: "auto", + }, + ], + }, + }, + additionalProperties: false, + }, + customCommands: { + type: "array", + items: { + type: "object", + properties: { + command: { + type: "string", + }, + description: { + type: "string", + }, + }, + required: ["command", "description"], + additionalProperties: false, + }, + }, + configWrites: { + type: "boolean", + }, + dmPolicy: { + default: "pairing", + type: "string", + enum: ["pairing", "allowlist", "open", "disabled"], + }, + botToken: { + anyOf: [ + { + type: "string", + }, + { + oneOf: [ + { + type: "object", + properties: { + source: { + type: "string", + const: "env", + }, + provider: { + type: "string", + pattern: "^[a-z][a-z0-9_-]{0,63}$", + }, + id: { + type: "string", + pattern: "^[A-Z][A-Z0-9_]{0,127}$", + }, + }, + required: ["source", "provider", "id"], + additionalProperties: false, + }, + { + type: "object", + properties: { + source: { + type: "string", + const: "file", + }, + provider: { + type: "string", + pattern: "^[a-z][a-z0-9_-]{0,63}$", + }, + id: { + type: "string", + }, + }, + required: ["source", "provider", "id"], + additionalProperties: false, + }, + { + type: "object", + properties: { + source: { + type: "string", + const: "exec", + }, + provider: { + type: "string", + pattern: "^[a-z][a-z0-9_-]{0,63}$", + }, + id: { + type: "string", + }, + }, + required: ["source", "provider", "id"], + additionalProperties: false, + }, + ], + }, + ], + }, + tokenFile: { + type: "string", + }, + replyToMode: { + anyOf: [ + { + type: "string", + const: "off", + }, + { + type: "string", + const: "first", + }, + { + type: "string", + const: "all", + }, + ], + }, + groups: { + type: "object", + propertyNames: { + type: "string", + }, + additionalProperties: { + type: "object", + properties: { + requireMention: { + type: "boolean", + }, + disableAudioPreflight: { + type: "boolean", + }, + groupPolicy: { + type: "string", + enum: ["open", "disabled", "allowlist"], + }, + tools: { + type: "object", + properties: { + allow: { + type: "array", + items: { + type: "string", + }, + }, + alsoAllow: { + type: "array", + items: { + type: "string", + }, + }, + deny: { + type: "array", + items: { + type: "string", + }, + }, + }, + additionalProperties: false, + }, + toolsBySender: { + type: "object", + propertyNames: { + type: "string", + }, + additionalProperties: { + type: "object", + properties: { + allow: { + type: "array", + items: { + type: "string", + }, + }, + alsoAllow: { + type: "array", + items: { + type: "string", + }, + }, + deny: { + type: "array", + items: { + type: "string", + }, + }, + }, + additionalProperties: false, + }, + }, + skills: { + type: "array", + items: { + type: "string", + }, + }, + enabled: { + type: "boolean", + }, + allowFrom: { + type: "array", + items: { + anyOf: [ + { + type: "string", + }, + { + type: "number", + }, + ], + }, + }, + systemPrompt: { + type: "string", + }, + topics: { + type: "object", + propertyNames: { + type: "string", + }, + additionalProperties: { + type: "object", + properties: { + requireMention: { + type: "boolean", + }, + disableAudioPreflight: { + type: "boolean", + }, + groupPolicy: { + type: "string", + enum: ["open", "disabled", "allowlist"], + }, + skills: { + type: "array", + items: { + type: "string", + }, + }, + enabled: { + type: "boolean", + }, + allowFrom: { + type: "array", + items: { + anyOf: [ + { + type: "string", + }, + { + type: "number", + }, + ], + }, + }, + systemPrompt: { + type: "string", + }, + agentId: { + type: "string", + }, + }, + additionalProperties: false, + }, + }, + }, + additionalProperties: false, + }, + }, + allowFrom: { + type: "array", + items: { + anyOf: [ + { + type: "string", + }, + { + type: "number", + }, + ], + }, + }, + defaultTo: { + anyOf: [ + { + type: "string", + }, + { + type: "number", + }, + ], + }, + groupAllowFrom: { + type: "array", + items: { + anyOf: [ + { + type: "string", + }, + { + type: "number", + }, + ], + }, + }, + groupPolicy: { + default: "allowlist", + type: "string", + enum: ["open", "disabled", "allowlist"], + }, + historyLimit: { + type: "integer", + minimum: 0, + maximum: 9007199254740991, + }, + dmHistoryLimit: { + type: "integer", + minimum: 0, + maximum: 9007199254740991, + }, + dms: { + type: "object", + propertyNames: { + type: "string", + }, + additionalProperties: { + type: "object", + properties: { + historyLimit: { + type: "integer", + minimum: 0, + maximum: 9007199254740991, + }, + }, + additionalProperties: false, + }, + }, + direct: { + type: "object", + propertyNames: { + type: "string", + }, + additionalProperties: { + type: "object", + properties: { + dmPolicy: { + type: "string", + enum: ["pairing", "allowlist", "open", "disabled"], + }, + tools: { + type: "object", + properties: { + allow: { + type: "array", + items: { + type: "string", + }, + }, + alsoAllow: { + type: "array", + items: { + type: "string", + }, + }, + deny: { + type: "array", + items: { + type: "string", + }, + }, + }, + additionalProperties: false, + }, + toolsBySender: { + type: "object", + propertyNames: { + type: "string", + }, + additionalProperties: { + type: "object", + properties: { + allow: { + type: "array", + items: { + type: "string", + }, + }, + alsoAllow: { + type: "array", + items: { + type: "string", + }, + }, + deny: { + type: "array", + items: { + type: "string", + }, + }, + }, + additionalProperties: false, + }, + }, + skills: { + type: "array", + items: { + type: "string", + }, + }, + enabled: { + type: "boolean", + }, + allowFrom: { + type: "array", + items: { + anyOf: [ + { + type: "string", + }, + { + type: "number", + }, + ], + }, + }, + systemPrompt: { + type: "string", + }, + topics: { + type: "object", + propertyNames: { + type: "string", + }, + additionalProperties: { + type: "object", + properties: { + requireMention: { + type: "boolean", + }, + disableAudioPreflight: { + type: "boolean", + }, + groupPolicy: { + type: "string", + enum: ["open", "disabled", "allowlist"], + }, + skills: { + type: "array", + items: { + type: "string", + }, + }, + enabled: { + type: "boolean", + }, + allowFrom: { + type: "array", + items: { + anyOf: [ + { + type: "string", + }, + { + type: "number", + }, + ], + }, + }, + systemPrompt: { + type: "string", + }, + agentId: { + type: "string", + }, + }, + additionalProperties: false, + }, + }, + requireTopic: { + type: "boolean", + }, + autoTopicLabel: { + anyOf: [ + { + type: "boolean", + }, + { + type: "object", + properties: { + enabled: { + type: "boolean", + }, + prompt: { + type: "string", + }, + }, + additionalProperties: false, + }, + ], + }, + }, + additionalProperties: false, + }, + }, + textChunkLimit: { + type: "integer", + exclusiveMinimum: 0, + maximum: 9007199254740991, + }, + chunkMode: { + type: "string", + enum: ["length", "newline"], + }, + streaming: { + anyOf: [ + { + type: "boolean", + }, + { + type: "string", + enum: ["off", "partial", "block", "progress"], + }, + ], + }, + blockStreaming: { + type: "boolean", + }, + draftChunk: { + type: "object", + properties: { + minChars: { + type: "integer", + exclusiveMinimum: 0, + maximum: 9007199254740991, + }, + maxChars: { + type: "integer", + exclusiveMinimum: 0, + maximum: 9007199254740991, + }, + breakPreference: { + anyOf: [ + { + type: "string", + const: "paragraph", + }, + { + type: "string", + const: "newline", + }, + { + type: "string", + const: "sentence", + }, + ], + }, + }, + additionalProperties: false, + }, + blockStreamingCoalesce: { + type: "object", + properties: { + minChars: { + type: "integer", + exclusiveMinimum: 0, + maximum: 9007199254740991, + }, + maxChars: { + type: "integer", + exclusiveMinimum: 0, + maximum: 9007199254740991, + }, + idleMs: { + type: "integer", + minimum: 0, + maximum: 9007199254740991, + }, + }, + additionalProperties: false, + }, + streamMode: { + type: "string", + enum: ["off", "partial", "block"], + }, + mediaMaxMb: { + type: "number", + exclusiveMinimum: 0, + }, + timeoutSeconds: { + type: "integer", + exclusiveMinimum: 0, + maximum: 9007199254740991, + }, + retry: { + type: "object", + properties: { + attempts: { + type: "integer", + minimum: 1, + maximum: 9007199254740991, + }, + minDelayMs: { + type: "integer", + minimum: 0, + maximum: 9007199254740991, + }, + maxDelayMs: { + type: "integer", + minimum: 0, + maximum: 9007199254740991, + }, + jitter: { + type: "number", + minimum: 0, + maximum: 1, + }, + }, + additionalProperties: false, + }, + network: { + type: "object", + properties: { + autoSelectFamily: { + type: "boolean", + }, + dnsResultOrder: { + type: "string", + enum: ["ipv4first", "verbatim"], + }, + }, + additionalProperties: false, + }, + proxy: { + type: "string", + }, + webhookUrl: { + description: + "Public HTTPS webhook URL registered with Telegram for inbound updates. This must be internet-reachable and requires channels.telegram.webhookSecret.", + type: "string", + }, + webhookSecret: { + description: + "Secret token sent to Telegram during webhook registration and verified on inbound webhook requests. Telegram returns this value for verification; this is not the gateway auth token and not the bot token.", + anyOf: [ + { + type: "string", + }, + { + oneOf: [ + { + type: "object", + properties: { + source: { + type: "string", + const: "env", + }, + provider: { + type: "string", + pattern: "^[a-z][a-z0-9_-]{0,63}$", + }, + id: { + type: "string", + pattern: "^[A-Z][A-Z0-9_]{0,127}$", + }, + }, + required: ["source", "provider", "id"], + additionalProperties: false, + }, + { + type: "object", + properties: { + source: { + type: "string", + const: "file", + }, + provider: { + type: "string", + pattern: "^[a-z][a-z0-9_-]{0,63}$", + }, + id: { + type: "string", + }, + }, + required: ["source", "provider", "id"], + additionalProperties: false, + }, + { + type: "object", + properties: { + source: { + type: "string", + const: "exec", + }, + provider: { + type: "string", + pattern: "^[a-z][a-z0-9_-]{0,63}$", + }, + id: { + type: "string", + }, + }, + required: ["source", "provider", "id"], + additionalProperties: false, + }, + ], + }, + ], + }, + webhookPath: { + description: + "Local webhook route path served by the gateway listener. Defaults to /telegram-webhook.", + type: "string", + }, + webhookHost: { + description: + "Local bind host for the webhook listener. Defaults to 127.0.0.1; keep loopback unless you intentionally expose direct ingress.", + type: "string", + }, + webhookPort: { + description: + "Local bind port for the webhook listener. Defaults to 8787; set to 0 to let the OS assign an ephemeral port.", + type: "integer", + minimum: 0, + maximum: 9007199254740991, + }, + webhookCertPath: { + description: + "Path to the self-signed certificate (PEM) to upload to Telegram during webhook registration. Required for self-signed certs (direct IP or no domain).", + type: "string", + }, + actions: { + type: "object", + properties: { + reactions: { + type: "boolean", + }, + sendMessage: { + type: "boolean", + }, + poll: { + type: "boolean", + }, + deleteMessage: { + type: "boolean", + }, + editMessage: { + type: "boolean", + }, + sticker: { + type: "boolean", + }, + createForumTopic: { + type: "boolean", + }, + editForumTopic: { + type: "boolean", + }, + }, + additionalProperties: false, + }, + threadBindings: { + type: "object", + properties: { + enabled: { + type: "boolean", + }, + idleHours: { + type: "number", + minimum: 0, + }, + maxAgeHours: { + type: "number", + minimum: 0, + }, + spawnSubagentSessions: { + type: "boolean", + }, + spawnAcpSessions: { + type: "boolean", + }, + }, + additionalProperties: false, + }, + reactionNotifications: { + type: "string", + enum: ["off", "own", "all"], + }, + reactionLevel: { + type: "string", + enum: ["off", "ack", "minimal", "extensive"], + }, + heartbeat: { + type: "object", + properties: { + showOk: { + type: "boolean", + }, + showAlerts: { + type: "boolean", + }, + useIndicator: { + type: "boolean", + }, + }, + additionalProperties: false, + }, + healthMonitor: { + type: "object", + properties: { + enabled: { + type: "boolean", + }, + }, + additionalProperties: false, + }, + linkPreview: { + type: "boolean", + }, + silentErrorReplies: { + type: "boolean", + }, + responsePrefix: { + type: "string", + }, + ackReaction: { + type: "string", + }, + apiRoot: { + type: "string", + format: "uri", + }, + autoTopicLabel: { + anyOf: [ + { + type: "boolean", + }, + { + type: "object", + properties: { + enabled: { + type: "boolean", + }, + prompt: { + type: "string", + }, + }, + additionalProperties: false, + }, + ], + }, + }, + required: ["dmPolicy", "groupPolicy"], + additionalProperties: false, + }, + }, + defaultAccount: { + type: "string", + }, + }, + required: ["dmPolicy", "groupPolicy"], + additionalProperties: false, + }, + uiHints: { + "": { + label: "Telegram", + help: "Telegram channel provider configuration including auth tokens, retry behavior, and message rendering controls. Use this section to tune bot behavior for Telegram-specific API semantics.", + }, + customCommands: { + label: "Telegram Custom Commands", + help: "Additional Telegram bot menu commands (merged with native; conflicts ignored).", + }, + botToken: { + label: "Telegram Bot Token", + help: "Telegram bot token used to authenticate Bot API requests for this account/provider config. Use secret/env substitution and rotate tokens if exposure is suspected.", + }, + dmPolicy: { + label: "Telegram DM Policy", + help: 'Direct message access control ("pairing" recommended). "open" requires channels.telegram.allowFrom=["*"].', + }, + configWrites: { + label: "Telegram Config Writes", + help: "Allow Telegram to write config in response to channel events/commands (default: true).", + }, + "commands.native": { + label: "Telegram Native Commands", + help: 'Override native commands for Telegram (bool or "auto").', + }, + "commands.nativeSkills": { + label: "Telegram Native Skill Commands", + help: 'Override native skill commands for Telegram (bool or "auto").', + }, + streaming: { + label: "Telegram Streaming Mode", + help: 'Unified Telegram stream preview mode: "off" | "partial" | "block" | "progress" (default: "partial"). "progress" maps to "partial" on Telegram. Legacy boolean/streamMode keys are auto-mapped.', + }, + "retry.attempts": { + label: "Telegram Retry Attempts", + help: "Max retry attempts for outbound Telegram API calls (default: 3).", + }, + "retry.minDelayMs": { + label: "Telegram Retry Min Delay (ms)", + help: "Minimum retry delay in ms for Telegram outbound calls.", + }, + "retry.maxDelayMs": { + label: "Telegram Retry Max Delay (ms)", + help: "Maximum retry delay cap in ms for Telegram outbound calls.", + }, + "retry.jitter": { + label: "Telegram Retry Jitter", + help: "Jitter factor (0-1) applied to Telegram retry delays.", + }, + "network.autoSelectFamily": { + label: "Telegram autoSelectFamily", + help: "Override Node autoSelectFamily for Telegram (true=enable, false=disable).", + }, + timeoutSeconds: { + label: "Telegram API Timeout (seconds)", + help: "Max seconds before Telegram API requests are aborted (default: 500 per grammY).", + }, + silentErrorReplies: { + label: "Telegram Silent Error Replies", + help: "When true, Telegram bot replies marked as errors are sent silently (no notification sound). Default: false.", + }, + apiRoot: { + label: "Telegram API Root URL", + help: "Custom Telegram Bot API root URL. Use for self-hosted Bot API servers (https://github.com/tdlib/telegram-bot-api) or reverse proxies in regions where api.telegram.org is blocked.", + }, + autoTopicLabel: { + label: "Telegram Auto Topic Label", + help: "Auto-rename DM forum topics on first message using LLM. Default: true. Set to false to disable, or use object form { enabled: true, prompt: '...' } for custom prompt.", + }, + "autoTopicLabel.enabled": { + label: "Telegram Auto Topic Label Enabled", + help: "Whether auto topic labeling is enabled. Default: true.", + }, + "autoTopicLabel.prompt": { + label: "Telegram Auto Topic Label Prompt", + help: "Custom prompt for LLM-based topic naming. The user message is appended after the prompt.", + }, + "capabilities.inlineButtons": { + label: "Telegram Inline Buttons", + help: "Enable Telegram inline button components for supported command and interaction surfaces. Disable if your deployment needs plain-text-only compatibility behavior.", + }, + execApprovals: { + label: "Telegram Exec Approvals", + help: "Telegram-native exec approval routing and approver authorization. Enable this only when Telegram should act as an explicit exec-approval client for the selected bot account.", + }, + "execApprovals.enabled": { + label: "Telegram Exec Approvals Enabled", + help: "Enable Telegram exec approvals for this account. When false or unset, Telegram messages/buttons cannot approve exec requests.", + }, + "execApprovals.approvers": { + label: "Telegram Exec Approval Approvers", + help: "Telegram user IDs allowed to approve exec requests for this bot account. Use numeric Telegram user IDs; prompts are only delivered to these approvers when target includes dm.", + }, + "execApprovals.agentFilter": { + label: "Telegram Exec Approval Agent Filter", + help: 'Optional allowlist of agent IDs eligible for Telegram exec approvals, for example `["main", "ops-agent"]`. Use this to keep approval prompts scoped to the agents you actually operate from Telegram.', + }, + "execApprovals.sessionFilter": { + label: "Telegram Exec Approval Session Filter", + help: "Optional session-key filters matched as substring or regex-style patterns before Telegram approval routing is used. Use narrow patterns so Telegram approvals only appear for intended sessions.", + }, + "execApprovals.target": { + label: "Telegram Exec Approval Target", + help: 'Controls where Telegram approval prompts are sent: "dm" sends to approver DMs (default), "channel" sends to the originating Telegram chat/topic, and "both" sends to both. Channel delivery exposes the command text to the chat, so only use it in trusted groups/topics.', + }, + "threadBindings.enabled": { + label: "Telegram Thread Binding Enabled", + help: "Enable Telegram conversation binding features (/focus, /unfocus, /agents, and /session idle|max-age). Overrides session.threadBindings.enabled when set.", + }, + "threadBindings.idleHours": { + label: "Telegram Thread Binding Idle Timeout (hours)", + help: "Inactivity window in hours for Telegram bound sessions. Set 0 to disable idle auto-unfocus (default: 24). Overrides session.threadBindings.idleHours when set.", + }, + "threadBindings.maxAgeHours": { + label: "Telegram Thread Binding Max Age (hours)", + help: "Optional hard max age in hours for Telegram bound sessions. Set 0 to disable hard cap (default: 0). Overrides session.threadBindings.maxAgeHours when set.", + }, + "threadBindings.spawnSubagentSessions": { + label: "Telegram Thread-Bound Subagent Spawn", + help: "Allow subagent spawns with thread=true to auto-bind Telegram current conversations when supported.", + }, + "threadBindings.spawnAcpSessions": { + label: "Telegram Thread-Bound ACP Spawn", + help: "Allow ACP spawns with thread=true to auto-bind Telegram current conversations when supported.", + }, + }, + label: "Telegram", + description: + "simplest way to get started — register a bot with @BotFather and get going.", + }, + }, }, }, { @@ -3153,6 +16280,171 @@ export const GENERATED_BUNDLED_PLUGIN_METADATA = [ }, channels: ["tlon"], skills: ["node_modules/@tloncorp/tlon-skill"], + channelConfigs: { + tlon: { + schema: { + $schema: "http://json-schema.org/draft-07/schema#", + type: "object", + properties: { + name: { + type: "string", + }, + enabled: { + type: "boolean", + }, + ship: { + type: "string", + minLength: 1, + }, + url: { + type: "string", + }, + code: { + type: "string", + }, + allowPrivateNetwork: { + type: "boolean", + }, + groupChannels: { + type: "array", + items: { + type: "string", + minLength: 1, + }, + }, + dmAllowlist: { + type: "array", + items: { + type: "string", + minLength: 1, + }, + }, + autoDiscoverChannels: { + type: "boolean", + }, + showModelSignature: { + type: "boolean", + }, + responsePrefix: { + type: "string", + }, + autoAcceptDmInvites: { + type: "boolean", + }, + autoAcceptGroupInvites: { + type: "boolean", + }, + ownerShip: { + type: "string", + minLength: 1, + }, + authorization: { + type: "object", + properties: { + channelRules: { + type: "object", + propertyNames: { + type: "string", + }, + additionalProperties: { + type: "object", + properties: { + mode: { + type: "string", + enum: ["restricted", "open"], + }, + allowedShips: { + type: "array", + items: { + type: "string", + minLength: 1, + }, + }, + }, + additionalProperties: false, + }, + }, + }, + additionalProperties: false, + }, + defaultAuthorizedShips: { + type: "array", + items: { + type: "string", + minLength: 1, + }, + }, + accounts: { + type: "object", + propertyNames: { + type: "string", + }, + additionalProperties: { + type: "object", + properties: { + name: { + type: "string", + }, + enabled: { + type: "boolean", + }, + ship: { + type: "string", + minLength: 1, + }, + url: { + type: "string", + }, + code: { + type: "string", + }, + allowPrivateNetwork: { + type: "boolean", + }, + groupChannels: { + type: "array", + items: { + type: "string", + minLength: 1, + }, + }, + dmAllowlist: { + type: "array", + items: { + type: "string", + minLength: 1, + }, + }, + autoDiscoverChannels: { + type: "boolean", + }, + showModelSignature: { + type: "boolean", + }, + responsePrefix: { + type: "string", + }, + autoAcceptDmInvites: { + type: "boolean", + }, + autoAcceptGroupInvites: { + type: "boolean", + }, + ownerShip: { + type: "string", + minLength: 1, + }, + }, + additionalProperties: false, + }, + }, + }, + additionalProperties: false, + }, + label: "Tlon", + description: "decentralized messaging on Urbit; install the plugin to enable.", + }, + }, }, }, { @@ -3228,6 +16520,204 @@ export const GENERATED_BUNDLED_PLUGIN_METADATA = [ properties: {}, }, channels: ["twitch"], + channelConfigs: { + twitch: { + schema: { + $schema: "http://json-schema.org/draft-07/schema#", + anyOf: [ + { + allOf: [ + { + type: "object", + properties: { + name: { + type: "string", + }, + enabled: { + type: "boolean", + }, + markdown: { + type: "object", + properties: { + tables: { + type: "string", + enum: ["off", "bullets", "code"], + }, + }, + additionalProperties: false, + }, + }, + additionalProperties: false, + }, + { + type: "object", + properties: { + username: { + type: "string", + }, + accessToken: { + type: "string", + }, + clientId: { + type: "string", + }, + channel: { + type: "string", + minLength: 1, + }, + enabled: { + type: "boolean", + }, + allowFrom: { + type: "array", + items: { + type: "string", + }, + }, + allowedRoles: { + type: "array", + items: { + type: "string", + enum: ["moderator", "owner", "vip", "subscriber", "all"], + }, + }, + requireMention: { + type: "boolean", + }, + responsePrefix: { + type: "string", + }, + clientSecret: { + type: "string", + }, + refreshToken: { + type: "string", + }, + expiresIn: { + anyOf: [ + { + type: "number", + }, + { + type: "null", + }, + ], + }, + obtainmentTimestamp: { + type: "number", + }, + }, + required: ["username", "accessToken", "channel"], + additionalProperties: false, + }, + ], + }, + { + allOf: [ + { + type: "object", + properties: { + name: { + type: "string", + }, + enabled: { + type: "boolean", + }, + markdown: { + type: "object", + properties: { + tables: { + type: "string", + enum: ["off", "bullets", "code"], + }, + }, + additionalProperties: false, + }, + }, + additionalProperties: false, + }, + { + type: "object", + properties: { + accounts: { + type: "object", + propertyNames: { + type: "string", + }, + additionalProperties: { + type: "object", + properties: { + username: { + type: "string", + }, + accessToken: { + type: "string", + }, + clientId: { + type: "string", + }, + channel: { + type: "string", + minLength: 1, + }, + enabled: { + type: "boolean", + }, + allowFrom: { + type: "array", + items: { + type: "string", + }, + }, + allowedRoles: { + type: "array", + items: { + type: "string", + enum: ["moderator", "owner", "vip", "subscriber", "all"], + }, + }, + requireMention: { + type: "boolean", + }, + responsePrefix: { + type: "string", + }, + clientSecret: { + type: "string", + }, + refreshToken: { + type: "string", + }, + expiresIn: { + anyOf: [ + { + type: "number", + }, + { + type: "null", + }, + ], + }, + obtainmentTimestamp: { + type: "number", + }, + }, + required: ["username", "accessToken", "channel"], + additionalProperties: false, + }, + }, + }, + required: ["accounts"], + additionalProperties: false, + }, + ], + }, + ], + }, + label: "Twitch", + description: "Twitch chat integration", + }, + }, }, }, { @@ -4060,6 +17550,564 @@ export const GENERATED_BUNDLED_PLUGIN_METADATA = [ properties: {}, }, channels: ["whatsapp"], + channelConfigs: { + whatsapp: { + schema: { + $schema: "http://json-schema.org/draft-07/schema#", + type: "object", + properties: { + enabled: { + type: "boolean", + }, + capabilities: { + type: "array", + items: { + type: "string", + }, + }, + markdown: { + type: "object", + properties: { + tables: { + type: "string", + enum: ["off", "bullets", "code"], + }, + }, + additionalProperties: false, + }, + configWrites: { + type: "boolean", + }, + sendReadReceipts: { + type: "boolean", + }, + messagePrefix: { + type: "string", + }, + responsePrefix: { + type: "string", + }, + dmPolicy: { + default: "pairing", + type: "string", + enum: ["pairing", "allowlist", "open", "disabled"], + }, + selfChatMode: { + type: "boolean", + }, + allowFrom: { + type: "array", + items: { + type: "string", + }, + }, + defaultTo: { + type: "string", + }, + groupAllowFrom: { + type: "array", + items: { + type: "string", + }, + }, + groupPolicy: { + default: "allowlist", + type: "string", + enum: ["open", "disabled", "allowlist"], + }, + historyLimit: { + type: "integer", + minimum: 0, + maximum: 9007199254740991, + }, + dmHistoryLimit: { + type: "integer", + minimum: 0, + maximum: 9007199254740991, + }, + dms: { + type: "object", + propertyNames: { + type: "string", + }, + additionalProperties: { + type: "object", + properties: { + historyLimit: { + type: "integer", + minimum: 0, + maximum: 9007199254740991, + }, + }, + additionalProperties: false, + }, + }, + textChunkLimit: { + type: "integer", + exclusiveMinimum: 0, + maximum: 9007199254740991, + }, + chunkMode: { + type: "string", + enum: ["length", "newline"], + }, + blockStreaming: { + type: "boolean", + }, + blockStreamingCoalesce: { + type: "object", + properties: { + minChars: { + type: "integer", + exclusiveMinimum: 0, + maximum: 9007199254740991, + }, + maxChars: { + type: "integer", + exclusiveMinimum: 0, + maximum: 9007199254740991, + }, + idleMs: { + type: "integer", + minimum: 0, + maximum: 9007199254740991, + }, + }, + additionalProperties: false, + }, + groups: { + type: "object", + propertyNames: { + type: "string", + }, + additionalProperties: { + type: "object", + properties: { + requireMention: { + type: "boolean", + }, + tools: { + type: "object", + properties: { + allow: { + type: "array", + items: { + type: "string", + }, + }, + alsoAllow: { + type: "array", + items: { + type: "string", + }, + }, + deny: { + type: "array", + items: { + type: "string", + }, + }, + }, + additionalProperties: false, + }, + toolsBySender: { + type: "object", + propertyNames: { + type: "string", + }, + additionalProperties: { + type: "object", + properties: { + allow: { + type: "array", + items: { + type: "string", + }, + }, + alsoAllow: { + type: "array", + items: { + type: "string", + }, + }, + deny: { + type: "array", + items: { + type: "string", + }, + }, + }, + additionalProperties: false, + }, + }, + }, + additionalProperties: false, + }, + }, + ackReaction: { + type: "object", + properties: { + emoji: { + type: "string", + }, + direct: { + default: true, + type: "boolean", + }, + group: { + default: "mentions", + type: "string", + enum: ["always", "mentions", "never"], + }, + }, + required: ["direct", "group"], + additionalProperties: false, + }, + debounceMs: { + default: 0, + type: "integer", + minimum: 0, + maximum: 9007199254740991, + }, + heartbeat: { + type: "object", + properties: { + showOk: { + type: "boolean", + }, + showAlerts: { + type: "boolean", + }, + useIndicator: { + type: "boolean", + }, + }, + additionalProperties: false, + }, + healthMonitor: { + type: "object", + properties: { + enabled: { + type: "boolean", + }, + }, + additionalProperties: false, + }, + accounts: { + type: "object", + propertyNames: { + type: "string", + }, + additionalProperties: { + type: "object", + properties: { + enabled: { + type: "boolean", + }, + capabilities: { + type: "array", + items: { + type: "string", + }, + }, + markdown: { + type: "object", + properties: { + tables: { + type: "string", + enum: ["off", "bullets", "code"], + }, + }, + additionalProperties: false, + }, + configWrites: { + type: "boolean", + }, + sendReadReceipts: { + type: "boolean", + }, + messagePrefix: { + type: "string", + }, + responsePrefix: { + type: "string", + }, + dmPolicy: { + default: "pairing", + type: "string", + enum: ["pairing", "allowlist", "open", "disabled"], + }, + selfChatMode: { + type: "boolean", + }, + allowFrom: { + type: "array", + items: { + type: "string", + }, + }, + defaultTo: { + type: "string", + }, + groupAllowFrom: { + type: "array", + items: { + type: "string", + }, + }, + groupPolicy: { + default: "allowlist", + type: "string", + enum: ["open", "disabled", "allowlist"], + }, + historyLimit: { + type: "integer", + minimum: 0, + maximum: 9007199254740991, + }, + dmHistoryLimit: { + type: "integer", + minimum: 0, + maximum: 9007199254740991, + }, + dms: { + type: "object", + propertyNames: { + type: "string", + }, + additionalProperties: { + type: "object", + properties: { + historyLimit: { + type: "integer", + minimum: 0, + maximum: 9007199254740991, + }, + }, + additionalProperties: false, + }, + }, + textChunkLimit: { + type: "integer", + exclusiveMinimum: 0, + maximum: 9007199254740991, + }, + chunkMode: { + type: "string", + enum: ["length", "newline"], + }, + blockStreaming: { + type: "boolean", + }, + blockStreamingCoalesce: { + type: "object", + properties: { + minChars: { + type: "integer", + exclusiveMinimum: 0, + maximum: 9007199254740991, + }, + maxChars: { + type: "integer", + exclusiveMinimum: 0, + maximum: 9007199254740991, + }, + idleMs: { + type: "integer", + minimum: 0, + maximum: 9007199254740991, + }, + }, + additionalProperties: false, + }, + groups: { + type: "object", + propertyNames: { + type: "string", + }, + additionalProperties: { + type: "object", + properties: { + requireMention: { + type: "boolean", + }, + tools: { + type: "object", + properties: { + allow: { + type: "array", + items: { + type: "string", + }, + }, + alsoAllow: { + type: "array", + items: { + type: "string", + }, + }, + deny: { + type: "array", + items: { + type: "string", + }, + }, + }, + additionalProperties: false, + }, + toolsBySender: { + type: "object", + propertyNames: { + type: "string", + }, + additionalProperties: { + type: "object", + properties: { + allow: { + type: "array", + items: { + type: "string", + }, + }, + alsoAllow: { + type: "array", + items: { + type: "string", + }, + }, + deny: { + type: "array", + items: { + type: "string", + }, + }, + }, + additionalProperties: false, + }, + }, + }, + additionalProperties: false, + }, + }, + ackReaction: { + type: "object", + properties: { + emoji: { + type: "string", + }, + direct: { + default: true, + type: "boolean", + }, + group: { + default: "mentions", + type: "string", + enum: ["always", "mentions", "never"], + }, + }, + required: ["direct", "group"], + additionalProperties: false, + }, + debounceMs: { + default: 0, + type: "integer", + minimum: 0, + maximum: 9007199254740991, + }, + heartbeat: { + type: "object", + properties: { + showOk: { + type: "boolean", + }, + showAlerts: { + type: "boolean", + }, + useIndicator: { + type: "boolean", + }, + }, + additionalProperties: false, + }, + healthMonitor: { + type: "object", + properties: { + enabled: { + type: "boolean", + }, + }, + additionalProperties: false, + }, + name: { + type: "string", + }, + authDir: { + type: "string", + }, + mediaMaxMb: { + type: "integer", + exclusiveMinimum: 0, + maximum: 9007199254740991, + }, + }, + required: ["dmPolicy", "groupPolicy", "debounceMs"], + additionalProperties: false, + }, + }, + defaultAccount: { + type: "string", + }, + mediaMaxMb: { + default: 50, + type: "integer", + exclusiveMinimum: 0, + maximum: 9007199254740991, + }, + actions: { + type: "object", + properties: { + reactions: { + type: "boolean", + }, + sendMessage: { + type: "boolean", + }, + polls: { + type: "boolean", + }, + }, + additionalProperties: false, + }, + }, + required: ["dmPolicy", "groupPolicy", "debounceMs", "mediaMaxMb"], + additionalProperties: false, + }, + uiHints: { + "": { + label: "WhatsApp", + help: "WhatsApp channel provider configuration for access policy and message batching behavior. Use this section to tune responsiveness and direct-message routing safety for WhatsApp chats.", + }, + dmPolicy: { + label: "WhatsApp DM Policy", + help: 'Direct message access control ("pairing" recommended). "open" requires channels.whatsapp.allowFrom=["*"].', + }, + selfChatMode: { + label: "WhatsApp Self-Phone Mode", + help: "Same-phone setup (bot uses your personal WhatsApp number).", + }, + debounceMs: { + label: "WhatsApp Message Debounce (ms)", + help: "Debounce window (ms) for batching rapid consecutive messages from the same sender (0 to disable).", + }, + configWrites: { + label: "WhatsApp Config Writes", + help: "Allow WhatsApp to write config in response to channel events/commands (default: true).", + }, + }, + label: "WhatsApp", + description: "works with your own number; recommend a separate phone + eSIM.", + }, + }, }, }, { @@ -4321,6 +18369,432 @@ export const GENERATED_BUNDLED_PLUGIN_METADATA = [ properties: {}, }, channels: ["zalo"], + channelConfigs: { + zalo: { + schema: { + $schema: "http://json-schema.org/draft-07/schema#", + type: "object", + properties: { + name: { + type: "string", + }, + enabled: { + type: "boolean", + }, + markdown: { + type: "object", + properties: { + tables: { + type: "string", + enum: ["off", "bullets", "code"], + }, + }, + additionalProperties: false, + }, + botToken: { + anyOf: [ + { + type: "string", + }, + { + oneOf: [ + { + type: "object", + properties: { + source: { + type: "string", + const: "env", + }, + provider: { + type: "string", + pattern: "^[a-z][a-z0-9_-]{0,63}$", + }, + id: { + type: "string", + pattern: "^[A-Z][A-Z0-9_]{0,127}$", + }, + }, + required: ["source", "provider", "id"], + additionalProperties: false, + }, + { + type: "object", + properties: { + source: { + type: "string", + const: "file", + }, + provider: { + type: "string", + pattern: "^[a-z][a-z0-9_-]{0,63}$", + }, + id: { + type: "string", + }, + }, + required: ["source", "provider", "id"], + additionalProperties: false, + }, + { + type: "object", + properties: { + source: { + type: "string", + const: "exec", + }, + provider: { + type: "string", + pattern: "^[a-z][a-z0-9_-]{0,63}$", + }, + id: { + type: "string", + }, + }, + required: ["source", "provider", "id"], + additionalProperties: false, + }, + ], + }, + ], + }, + tokenFile: { + type: "string", + }, + webhookUrl: { + type: "string", + }, + webhookSecret: { + anyOf: [ + { + type: "string", + }, + { + oneOf: [ + { + type: "object", + properties: { + source: { + type: "string", + const: "env", + }, + provider: { + type: "string", + pattern: "^[a-z][a-z0-9_-]{0,63}$", + }, + id: { + type: "string", + pattern: "^[A-Z][A-Z0-9_]{0,127}$", + }, + }, + required: ["source", "provider", "id"], + additionalProperties: false, + }, + { + type: "object", + properties: { + source: { + type: "string", + const: "file", + }, + provider: { + type: "string", + pattern: "^[a-z][a-z0-9_-]{0,63}$", + }, + id: { + type: "string", + }, + }, + required: ["source", "provider", "id"], + additionalProperties: false, + }, + { + type: "object", + properties: { + source: { + type: "string", + const: "exec", + }, + provider: { + type: "string", + pattern: "^[a-z][a-z0-9_-]{0,63}$", + }, + id: { + type: "string", + }, + }, + required: ["source", "provider", "id"], + additionalProperties: false, + }, + ], + }, + ], + }, + webhookPath: { + type: "string", + }, + dmPolicy: { + type: "string", + enum: ["pairing", "allowlist", "open", "disabled"], + }, + allowFrom: { + type: "array", + items: { + anyOf: [ + { + type: "string", + }, + { + type: "number", + }, + ], + }, + }, + groupPolicy: { + type: "string", + enum: ["open", "disabled", "allowlist"], + }, + groupAllowFrom: { + type: "array", + items: { + anyOf: [ + { + type: "string", + }, + { + type: "number", + }, + ], + }, + }, + mediaMaxMb: { + type: "number", + }, + proxy: { + type: "string", + }, + responsePrefix: { + type: "string", + }, + accounts: { + type: "object", + properties: {}, + additionalProperties: { + type: "object", + properties: { + name: { + type: "string", + }, + enabled: { + type: "boolean", + }, + markdown: { + type: "object", + properties: { + tables: { + type: "string", + enum: ["off", "bullets", "code"], + }, + }, + additionalProperties: false, + }, + botToken: { + anyOf: [ + { + type: "string", + }, + { + oneOf: [ + { + type: "object", + properties: { + source: { + type: "string", + const: "env", + }, + provider: { + type: "string", + pattern: "^[a-z][a-z0-9_-]{0,63}$", + }, + id: { + type: "string", + pattern: "^[A-Z][A-Z0-9_]{0,127}$", + }, + }, + required: ["source", "provider", "id"], + additionalProperties: false, + }, + { + type: "object", + properties: { + source: { + type: "string", + const: "file", + }, + provider: { + type: "string", + pattern: "^[a-z][a-z0-9_-]{0,63}$", + }, + id: { + type: "string", + }, + }, + required: ["source", "provider", "id"], + additionalProperties: false, + }, + { + type: "object", + properties: { + source: { + type: "string", + const: "exec", + }, + provider: { + type: "string", + pattern: "^[a-z][a-z0-9_-]{0,63}$", + }, + id: { + type: "string", + }, + }, + required: ["source", "provider", "id"], + additionalProperties: false, + }, + ], + }, + ], + }, + tokenFile: { + type: "string", + }, + webhookUrl: { + type: "string", + }, + webhookSecret: { + anyOf: [ + { + type: "string", + }, + { + oneOf: [ + { + type: "object", + properties: { + source: { + type: "string", + const: "env", + }, + provider: { + type: "string", + pattern: "^[a-z][a-z0-9_-]{0,63}$", + }, + id: { + type: "string", + pattern: "^[A-Z][A-Z0-9_]{0,127}$", + }, + }, + required: ["source", "provider", "id"], + additionalProperties: false, + }, + { + type: "object", + properties: { + source: { + type: "string", + const: "file", + }, + provider: { + type: "string", + pattern: "^[a-z][a-z0-9_-]{0,63}$", + }, + id: { + type: "string", + }, + }, + required: ["source", "provider", "id"], + additionalProperties: false, + }, + { + type: "object", + properties: { + source: { + type: "string", + const: "exec", + }, + provider: { + type: "string", + pattern: "^[a-z][a-z0-9_-]{0,63}$", + }, + id: { + type: "string", + }, + }, + required: ["source", "provider", "id"], + additionalProperties: false, + }, + ], + }, + ], + }, + webhookPath: { + type: "string", + }, + dmPolicy: { + type: "string", + enum: ["pairing", "allowlist", "open", "disabled"], + }, + allowFrom: { + type: "array", + items: { + anyOf: [ + { + type: "string", + }, + { + type: "number", + }, + ], + }, + }, + groupPolicy: { + type: "string", + enum: ["open", "disabled", "allowlist"], + }, + groupAllowFrom: { + type: "array", + items: { + anyOf: [ + { + type: "string", + }, + { + type: "number", + }, + ], + }, + }, + mediaMaxMb: { + type: "number", + }, + proxy: { + type: "string", + }, + responsePrefix: { + type: "string", + }, + }, + additionalProperties: false, + }, + }, + defaultAccount: { + type: "string", + }, + }, + additionalProperties: false, + }, + label: "Zalo", + description: "Vietnam-focused messaging platform with Bot API.", + }, + }, }, }, { @@ -4366,6 +18840,256 @@ export const GENERATED_BUNDLED_PLUGIN_METADATA = [ properties: {}, }, channels: ["zalouser"], + channelConfigs: { + zalouser: { + schema: { + $schema: "http://json-schema.org/draft-07/schema#", + type: "object", + properties: { + name: { + type: "string", + }, + enabled: { + type: "boolean", + }, + markdown: { + type: "object", + properties: { + tables: { + type: "string", + enum: ["off", "bullets", "code"], + }, + }, + additionalProperties: false, + }, + profile: { + type: "string", + }, + dangerouslyAllowNameMatching: { + type: "boolean", + }, + dmPolicy: { + type: "string", + enum: ["pairing", "allowlist", "open", "disabled"], + }, + allowFrom: { + type: "array", + items: { + anyOf: [ + { + type: "string", + }, + { + type: "number", + }, + ], + }, + }, + historyLimit: { + type: "integer", + minimum: 0, + maximum: 9007199254740991, + }, + groupAllowFrom: { + type: "array", + items: { + anyOf: [ + { + type: "string", + }, + { + type: "number", + }, + ], + }, + }, + groupPolicy: { + default: "allowlist", + type: "string", + enum: ["open", "disabled", "allowlist"], + }, + groups: { + type: "object", + properties: {}, + additionalProperties: { + type: "object", + properties: { + allow: { + type: "boolean", + }, + enabled: { + type: "boolean", + }, + requireMention: { + type: "boolean", + }, + tools: { + type: "object", + properties: { + allow: { + type: "array", + items: { + type: "string", + }, + }, + alsoAllow: { + type: "array", + items: { + type: "string", + }, + }, + deny: { + type: "array", + items: { + type: "string", + }, + }, + }, + additionalProperties: false, + }, + }, + additionalProperties: false, + }, + }, + messagePrefix: { + type: "string", + }, + responsePrefix: { + type: "string", + }, + accounts: { + type: "object", + properties: {}, + additionalProperties: { + type: "object", + properties: { + name: { + type: "string", + }, + enabled: { + type: "boolean", + }, + markdown: { + type: "object", + properties: { + tables: { + type: "string", + enum: ["off", "bullets", "code"], + }, + }, + additionalProperties: false, + }, + profile: { + type: "string", + }, + dangerouslyAllowNameMatching: { + type: "boolean", + }, + dmPolicy: { + type: "string", + enum: ["pairing", "allowlist", "open", "disabled"], + }, + allowFrom: { + type: "array", + items: { + anyOf: [ + { + type: "string", + }, + { + type: "number", + }, + ], + }, + }, + historyLimit: { + type: "integer", + minimum: 0, + maximum: 9007199254740991, + }, + groupAllowFrom: { + type: "array", + items: { + anyOf: [ + { + type: "string", + }, + { + type: "number", + }, + ], + }, + }, + groupPolicy: { + default: "allowlist", + type: "string", + enum: ["open", "disabled", "allowlist"], + }, + groups: { + type: "object", + properties: {}, + additionalProperties: { + type: "object", + properties: { + allow: { + type: "boolean", + }, + enabled: { + type: "boolean", + }, + requireMention: { + type: "boolean", + }, + tools: { + type: "object", + properties: { + allow: { + type: "array", + items: { + type: "string", + }, + }, + alsoAllow: { + type: "array", + items: { + type: "string", + }, + }, + deny: { + type: "array", + items: { + type: "string", + }, + }, + }, + additionalProperties: false, + }, + }, + additionalProperties: false, + }, + }, + messagePrefix: { + type: "string", + }, + responsePrefix: { + type: "string", + }, + }, + required: ["groupPolicy"], + additionalProperties: false, + }, + }, + defaultAccount: { + type: "string", + }, + }, + required: ["groupPolicy"], + additionalProperties: false, + }, + label: "Zalo Personal", + description: "Zalo personal account via QR code login.", + }, + }, }, }, ] as const; diff --git a/src/plugins/bundled-plugin-metadata.test.ts b/src/plugins/bundled-plugin-metadata.test.ts index cb8d4f67d75..9478c4f350d 100644 --- a/src/plugins/bundled-plugin-metadata.test.ts +++ b/src/plugins/bundled-plugin-metadata.test.ts @@ -19,8 +19,10 @@ import { installGeneratedPluginTempRootCleanup(); describe("bundled plugin metadata", () => { - it("matches the generated metadata snapshot", () => { - expect(BUNDLED_PLUGIN_METADATA).toEqual(collectBundledPluginMetadata({ repoRoot })); + it("matches the generated metadata snapshot", async () => { + await expect(collectBundledPluginMetadata({ repoRoot })).resolves.toEqual( + BUNDLED_PLUGIN_METADATA, + ); }); it("captures setup-entry metadata for bundled channel plugins", () => { @@ -28,6 +30,11 @@ describe("bundled plugin metadata", () => { expect(discord?.source).toEqual({ source: "./index.ts", built: "index.js" }); expect(discord?.setupSource).toEqual({ source: "./setup-entry.ts", built: "setup-entry.js" }); expect(discord?.manifest.id).toBe("discord"); + expect(discord?.manifest.channelConfigs?.discord).toEqual( + expect.objectContaining({ + schema: expect.objectContaining({ type: "object" }), + }), + ); }); it("prefers built generated paths when present and falls back to source paths", () => { @@ -51,7 +58,7 @@ describe("bundled plugin metadata", () => { ).toBe(path.join(tempRoot, "plugin", "index.js")); }); - it("supports check mode for stale generated artifacts", () => { + it("supports check mode for stale generated artifacts", async () => { const tempRoot = createGeneratedPluginTempRoot("openclaw-bundled-plugin-generated-"); writeJson(path.join(tempRoot, "extensions", "alpha", "package.json"), { @@ -66,13 +73,13 @@ describe("bundled plugin metadata", () => { configSchema: { type: "object" }, }); - const initial = writeBundledPluginMetadataModule({ + const initial = await writeBundledPluginMetadataModule({ repoRoot: tempRoot, outputPath: "src/plugins/bundled-plugin-metadata.generated.ts", }); expect(initial.wrote).toBe(true); - const current = writeBundledPluginMetadataModule({ + const current = await writeBundledPluginMetadataModule({ repoRoot: tempRoot, outputPath: "src/plugins/bundled-plugin-metadata.generated.ts", check: true, @@ -86,7 +93,7 @@ describe("bundled plugin metadata", () => { "utf8", ); - const stale = writeBundledPluginMetadataModule({ + const stale = await writeBundledPluginMetadataModule({ repoRoot: tempRoot, outputPath: "src/plugins/bundled-plugin-metadata.generated.ts", check: true, @@ -94,4 +101,78 @@ describe("bundled plugin metadata", () => { expect(stale.changed).toBe(true); expect(stale.wrote).toBe(false); }); + + it("merges generated channel schema metadata with manifest-owned channel config fields", async () => { + const tempRoot = createGeneratedPluginTempRoot("openclaw-bundled-plugin-channel-configs-"); + + writeJson(path.join(tempRoot, "extensions", "alpha", "package.json"), { + name: "@openclaw/alpha", + version: "0.0.1", + openclaw: { + extensions: ["./index.ts"], + channel: { + id: "alpha", + label: "Alpha Root Label", + blurb: "Alpha Root Description", + }, + }, + }); + writeJson(path.join(tempRoot, "extensions", "alpha", "openclaw.plugin.json"), { + id: "alpha", + channels: ["alpha"], + configSchema: { type: "object" }, + channelConfigs: { + alpha: { + schema: { type: "object", properties: { stale: { type: "boolean" } } }, + label: "Manifest Label", + uiHints: { + "channels.alpha.explicitOnly": { + help: "manifest hint", + }, + }, + }, + }, + }); + fs.writeFileSync( + path.join(tempRoot, "extensions", "alpha", "index.ts"), + "export {};\n", + "utf8", + ); + fs.mkdirSync(path.join(tempRoot, "extensions", "alpha", "src"), { recursive: true }); + fs.writeFileSync( + path.join(tempRoot, "extensions", "alpha", "src", "config-schema.js"), + [ + "export const AlphaChannelConfigSchema = {", + " schema: {", + " type: 'object',", + " properties: { generated: { type: 'string' } },", + " },", + " uiHints: {", + " 'channels.alpha.generatedOnly': { help: 'generated hint' },", + " },", + "};", + "", + ].join("\n"), + "utf8", + ); + + const entries = await collectBundledPluginMetadata({ repoRoot: tempRoot }); + const channelConfigs = entries[0]?.manifest.channelConfigs as + | Record + | undefined; + expect(channelConfigs?.alpha).toEqual({ + schema: { + type: "object", + properties: { + generated: { type: "string" }, + }, + }, + label: "Manifest Label", + description: "Alpha Root Description", + uiHints: { + "channels.alpha.generatedOnly": { help: "generated hint" }, + "channels.alpha.explicitOnly": { help: "manifest hint" }, + }, + }); + }); }); diff --git a/src/plugins/manifest-registry.test.ts b/src/plugins/manifest-registry.test.ts index 069dbed436a..30236c3c672 100644 --- a/src/plugins/manifest-registry.test.ts +++ b/src/plugins/manifest-registry.test.ts @@ -42,6 +42,8 @@ function createPluginCandidate(params: { bundleFormat?: "codex" | "claude" | "cursor"; packageManifest?: OpenClawPackageManifest; packageDir?: string; + bundledManifest?: PluginCandidate["bundledManifest"]; + bundledManifestPath?: string; }): PluginCandidate { return { idHint: params.idHint, @@ -52,6 +54,8 @@ function createPluginCandidate(params: { bundleFormat: params.bundleFormat, packageManifest: params.packageManifest, packageDir: params.packageDir, + bundledManifest: params.bundledManifest, + bundledManifestPath: params.bundledManifestPath, }; } @@ -338,17 +342,24 @@ describe("loadPluginManifestRegistry", () => { it("hydrates bundled channel config metadata onto manifest records", () => { const dir = makeTempDir(); - writeManifest(dir, { - id: "telegram", - channels: ["telegram"], - configSchema: { type: "object" }, - }); - - const registry = loadSingleCandidateRegistry({ - idHint: "telegram", - rootDir: dir, - origin: "bundled", - }); + const registry = loadRegistry([ + createPluginCandidate({ + idHint: "telegram", + rootDir: dir, + origin: "bundled", + bundledManifestPath: path.join(dir, "openclaw.plugin.json"), + bundledManifest: { + id: "telegram", + configSchema: { type: "object" }, + channels: ["telegram"], + channelConfigs: { + telegram: { + schema: { type: "object" }, + }, + }, + }, + }), + ]); expect(registry.plugins[0]?.channelConfigs?.telegram).toEqual( expect.objectContaining({ diff --git a/src/plugins/manifest-registry.ts b/src/plugins/manifest-registry.ts index 6ca9c35c489..fc8c03cb44a 100644 --- a/src/plugins/manifest-registry.ts +++ b/src/plugins/manifest-registry.ts @@ -1,6 +1,5 @@ import fs from "node:fs"; import path from "node:path"; -import { BUNDLED_CHANNEL_CONFIG_METADATA } from "../config/bundled-channel-config-metadata.js"; import type { OpenClawConfig } from "../config/config.js"; import { resolveUserPath } from "../utils.js"; import { resolveRuntimeServiceVersion } from "../version.js"; @@ -169,7 +168,6 @@ function buildRecord(params: { schemaCacheKey?: string; configSchema?: Record; }): PluginManifestRecord { - const bundledChannelConfigs = resolveBundledChannelConfigs(params.manifest.id); return { id: params.manifest.id, name: normalizeManifestLabel(params.manifest.name) ?? params.candidate.packageName, @@ -201,7 +199,7 @@ function buildRecord(params: { configSchema: params.configSchema, configUiHints: params.manifest.uiHints, contracts: params.manifest.contracts, - channelConfigs: mergeChannelConfigs(bundledChannelConfigs, params.manifest.channelConfigs), + channelConfigs: params.manifest.channelConfigs, ...(params.candidate.packageManifest?.channel?.id ? { channelCatalogMeta: { @@ -221,40 +219,6 @@ function buildRecord(params: { }; } -function resolveBundledChannelConfigs( - pluginId: string, -): Record | undefined { - const entries = BUNDLED_CHANNEL_CONFIG_METADATA.filter((entry) => entry.pluginId === pluginId); - if (entries.length === 0) { - return undefined; - } - - return Object.fromEntries( - entries.map((entry) => [ - entry.channelId, - { - schema: entry.schema, - ...(entry.uiHints ? { uiHints: entry.uiHints } : {}), - ...(entry.label ? { label: entry.label } : {}), - ...(entry.description ? { description: entry.description } : {}), - }, - ]), - ); -} - -function mergeChannelConfigs( - generated: Record | undefined, - manifest: Record | undefined, -): Record | undefined { - if (!generated) { - return manifest; - } - if (!manifest) { - return generated; - } - return { ...generated, ...manifest }; -} - function buildBundleRecord(params: { manifest: { id: string;