basant307/AI_Governance_Project
048
1/**2 * @license3 * Copyright 2025 Qwen Team4 * SPDX-License-Identifier: Apache-2.05 */6import type { Application } from 'express';7import type { DaemonStatusProvider } from '@qwen-code/acp-bridge';8import type { DaemonLogger } from './daemon-logger.js';9import type { DaemonMetricsBucket, DaemonPerfSnapshot, DaemonStartupSnapshot } from './daemon-status.js';10import type { ChannelWorkerSnapshot } from './channel-worker-supervisor.js';11import type { DeviceFlowProvider, DeviceFlowRegistry } from './auth/device-flow.js';12import { ClientMcpSenderRegistry } from './acp-http/client-mcp-sender-registry.js';13import { type AcpSessionBridge } from './acp-session-bridge.js';14import { type ServeAuthProviderInstallRequest, type ServeAuthProviderInstallResult, type ServeOptions } from './types.js';15import type { WorkspaceFileSystemFactory } from './fs/index.js';16import { type DaemonWorkspaceService } from './workspace-service/index.js';17import { type WorkspaceVoiceRouteDeps } from './routes/workspace-voice.js';18import { type TotalSessionAdmissionSnapshot } from './total-session-admission.js';19import { type WorkspaceRegistry, type WorkspaceRuntimeEnvMetadata } from './workspace-registry.js';20export { createDefaultFsAuditEmit, resolveBoundWorkspacesFromIdeEnv, resolveBridgeFsFactory, } from './server/fs-factory.js';21export { PromptDeadlineExceededError, resolvePromptDeadlineMs, } from './server/prompt-deadline.js';22export { detectFromLoopback } from './server/request-helpers.js';23export { InvalidCursorError, listWorkspaceSessionsForResponse, } from './server/session-list.js';24export type { ListWorkspaceSessionsOptions, ListWorkspaceSessionsResult, } from './server/session-list.js';25export { getActiveSseCount } from './routes/sse-events.js';26export interface ServeAppDeps {27 /** Bridge instance; tests inject a fake. Defaults to a fresh real one. */28 bridge?: AcpSessionBridge;29 /**30 * Enables resident management of scheduled-task-owned sessions: a periodic31 * keepalive (so their schedulers aren't idle-reaped) and a boot-time32 * rehydration (so they re-arm after a restart). Opt-in — only the real33 * long-running daemon (`runQwenServe`) sets it. Tests and direct embeds34 * leave it off so `createServeApp` neither spawns sessions on boot nor holds35 * a heartbeat timer.36 */37 manageScheduledTaskSessions?: boolean;38 /**39 * Directory of the built Web Shell SPA (`index.html` + `assets/`). When40 * set (and `opts.serveWebShell !== false`), `createServeApp` mounts the41 * UI at the daemon root before `bearerAuth`. Production `runQwenServe`42 * resolves this via `resolveWebShellDir()` and injects it here; direct43 * embeds / tests opt in by passing a fixture dir, so the default44 * `createServeApp` (no injection) stays API-only and existing route tests45 * are unaffected.46 */47 webShellDir?: string;48 /**49 * Qwen Code version advertised to web/SDK clients. Production passes the50 * resolved CLI package version; tests/direct embeds may omit it.51 */52 qwenCodeVersion?: string;53 /**54 * Pre-canonicalized workspace path. When supplied, `createServeApp`55 * skips its own `canonicalizeWorkspace` call (which would issue a56 * redundant `realpathSync.native` syscall — idempotent, but a hot57 * boot-time stat we can avoid). `runQwenServe` passes this after58 * its own boot-time canonicalize so the value used by59 * `/capabilities`, the `POST /session` cwd fallback, and the60 * bridge are all the SAME canonical form. Callers that haven't61 * canonicalized yet (tests, direct embeds) omit this and62 * `createServeApp` falls back to canonicalizing `opts.workspace ??63 * process.cwd()` itself.64 */65 boundWorkspace?: string;66 /**67 * Workspace filesystem boundary factory. When supplied, file routes68 * pull a per-request `WorkspaceFileSystem` off it; when omitted,69 * `createServeApp` builds a strict default (`trusted: false`,70 * warn-once no-op `emit`) so an upstream refactor that forgets to71 * inject `fsFactory` never silently allows writes against an72 * untrusted workspace.73 */74 fsFactory?: WorkspaceFileSystemFactory;75 /**76 * Device-flow auth registry. Tests inject a fake; production callers77 * omit this and `createServeApp` constructs a default wired to the78 * shipped Qwen provider, the bridge's `publishWorkspaceEvent`,79 * and a stderr audit sink.80 */81 deviceFlowRegistry?: DeviceFlowRegistry;82 maxExtensionOperationHistory?: number;83 /**84 * Extra device-flow providers for tests / future extensions.85 * Production builds register only `QwenOAuthDeviceFlowProvider`;86 * passing extra entries here registers them in addition.87 */88 deviceFlowProviders?: DeviceFlowProvider[];89 /**90 * Installs an LLM auth provider by applying the same provider install plan91 * used by interactive `/auth`. Production `runQwenServe` injects a92 * settings-backed implementation; tests/direct embeds may omit it, in which93 * case the route reports `not_implemented`.94 */95 installAuthProvider?: (req: ServeAuthProviderInstallRequest) => Promise<ServeAuthProviderInstallResult>;96 /**97 * Optional daemon logger. When provided, `sendBridgeError` routes98 * each 5xx error through `daemonLog.error(...)` (which tees to stderr +99 * the daemon log file). When omitted, falls back to existing100 * stderr-only behavior.101 */102 daemonLog?: DaemonLogger;103 startup?: DaemonStartupSnapshot;104 getChannelWorkerSnapshot?: () => ChannelWorkerSnapshot;105 getPerfSnapshot?: () => DaemonPerfSnapshot;106 /** Rolling metrics series for the Daemon Status charts (oldest→newest). */107 getMetricsSeries?: () => DaemonMetricsBucket[];108 getTotalSessionAdmissionSnapshot?: () => TotalSessionAdmissionSnapshot;109 /**110 * Sink fed one (durationMs, statusCode) per matched daemon HTTP request, so111 * the metrics ring can bucket request rate and latency for the charts.112 */113 recordDaemonRequest?: (durationMs: number, statusCode: number) => void;114 workspace?: DaemonWorkspaceService;115 statusProvider?: DaemonStatusProvider;116 persistDisabledTools?: (workspace: string, toolName: string, enabled: boolean) => Promise<void>;117 contextFilename?: string;118 persistSetting?: (workspace: string, scope: import('../config/settings.js').SettingScope, key: string, value: unknown) => Promise<void | import('../config/settings.js').LoadedSettings>;119 persistSettings?: (workspace: string, writes: Array<{120 scope: import('../config/settings.js').SettingScope;121 key: string;122 value: unknown;123 }>) => Promise<void>;124 /**125 * Reverse tool channel (issue #5626, Phase 2). Shared sender registry that126 * bridges the daemon WS (per-connection `ClientMcpRegistrar`) and the ACP127 * child's `client_mcp/message` ext-method. `runQwenServe` constructs ONE and128 * passes the SAME instance here AND to its `createAcpSessionBridge` call (as129 * `clientMcpSender: registry.lookup`) so the bridge that answers the child130 * and the WS provider that registers senders agree. When omitted (the131 * standalone `createServeApp` path with no injected bridge), `createServeApp`132 * builds its own registry and wires it into the bridge it creates.133 */134 clientMcpSenderRegistry?: ClientMcpSenderRegistry;135 workspaceRegistry?: WorkspaceRegistry;136 primaryWorkspaceTrusted?: boolean;137 primaryRuntimeEnv?: WorkspaceRuntimeEnvMetadata;138 voiceTranscriber?: WorkspaceVoiceRouteDeps['transcribe'];139}140/**141 * Sizes the keepalive heartbeat interval so a resident task session is beaten142 * BEFORE the idle reaper closes it. Targets a third of the reaper window, but143 * never exceeds HALF of it — so at least one heartbeat lands in time even for a144 * small custom timeout, where the 30s floor would otherwise overshoot the whole145 * window and let the session be reaped before the first beat. When the reaper is146 * disabled (idle timeout ≤ 0) sessions are never reaped, so heartbeats aren't147 * needed — the loop still runs (to revive re-enabled bound sessions) but at the148 * relaxed max cadence.149 */150export declare function computeKeepaliveIntervalMs(idleTimeoutMs: number): number;151export declare function createServeApp(opts: ServeOptions, getPort?: () => number, deps?: ServeAppDeps): Application;152 