/** * `discoverChannelUrl` — resolves the smee.io channel URL for the doorbell to * consume. Five-stage lookup: env override → webhook-config (via `gh api * /hooks`) → workspace walk-up → absolute workspace-mirror path → * cluster-internal fallback. Never throws; malformed input logs a warning and * returns null. * * Contract: `specs/988-summary-cockpit-auto-doorbell/contracts/channel-discovery.md`. */ import type { PathLike } from 'node:fs'; import { z } from 'zod'; import type { CommandRunner } from '@generacy-ai/cockpit'; export declare const DEFAULT_CHANNEL_FILE_PATH = "/var/lib/generacy/smee-channel"; export declare const DEFAULT_WORKSPACE_MIRROR_PATH = "/workspaces/.generacy/cockpit/smee-channel"; export declare const DEFAULT_WEBHOOK_CONFIG_TIMEOUT_MS = 5000; export declare const SMEE_URL_PATTERN: RegExp; export type ChannelSource = 'env' | 'webhook-config' | 'workspace-walkup' | 'workspace-absolute' | 'file'; export interface ChannelDiscoveryResult { url: string; source: ChannelSource; } interface ReadFileFn { (path: PathLike, encoding: BufferEncoding): Promise; } export interface ChannelDiscoveryInput { env: NodeJS.ProcessEnv; channelFilePath: string; fs: { readFile: ReadFileFn; }; logger?: { warn?: (msg: string) => void; }; /** Starting directory for walk-up scan. Defaults to `process.cwd()`. */ cwd?: string; /** Absolute fallback if walk-up produces no hit. */ workspaceMirrorPath?: string; /** * Pre-parsed target repos for the webhook-config stage, primary-first. * The caller (`doorbell.ts`) derives this via `resolveWebhookTargets`. * When absent or empty, the webhook-config stage is skipped. */ targets?: Array<{ owner: string; repo: string; }>; /** * Command runner used to invoke `gh api …/hooks`. When absent, the * webhook-config stage is skipped even if `targets` is non-empty. */ runner?: CommandRunner; /** * Per-call timeout for the `gh api …/hooks` invocation. Default 5000ms * (spec FR-009). Exposed for tests. */ webhookConfigTimeoutMs?: number; } export declare const SmeeHookSchema: z.ZodObject<{ id: z.ZodNumber; active: z.ZodBoolean; config: z.ZodObject<{ url: z.ZodString; }, "strip", z.ZodTypeAny, { url: string; }, { url: string; }>; updated_at: z.ZodString; }, "passthrough", z.ZodTypeAny, z.objectOutputType<{ id: z.ZodNumber; active: z.ZodBoolean; config: z.ZodObject<{ url: z.ZodString; }, "strip", z.ZodTypeAny, { url: string; }, { url: string; }>; updated_at: z.ZodString; }, z.ZodTypeAny, "passthrough">, z.objectInputType<{ id: z.ZodNumber; active: z.ZodBoolean; config: z.ZodObject<{ url: z.ZodString; }, "strip", z.ZodTypeAny, { url: string; }, { url: string; }>; updated_at: z.ZodString; }, z.ZodTypeAny, "passthrough">>; export type SmeeHook = z.infer; /** * Pure tie-break for `/hooks` payloads (FR-005). * 1. Keep only `active === true`. * 2. Keep only entries whose `config.url` matches `SMEE_URL_PATTERN`. * 3. Sort by `Date.parse(updated_at)` desc; `NaN` sorts last (`-Infinity`). * 4. Return the first entry or `null`. */ export declare function pickSmeeHook(hooks: SmeeHook[]): SmeeHook | null; export declare function discoverChannelUrl(input: ChannelDiscoveryInput): Promise; export {}; //# sourceMappingURL=channel-discovery.d.ts.map