import type { ApiClient } from './api-client'; import { type AppSyncSubscriber, type AppSyncNotification } from './appsync-subscriber'; import type { TransportKind } from './ipc-types'; import { TerminalWebSocket } from './terminal'; import { VsCodeTunnelWebSocket } from './vscode'; import type { ConfigSyncState, ConfigSyncDeps } from './agent-config-sync'; export interface TransportState { heartbeatTimer: ReturnType | null; subscriber: AppSyncSubscriber | null; terminalWs: TerminalWebSocket | null; vsCodeWs: VsCodeTunnelWebSocket | null; configSyncDebounceTimer: ReturnType | null; /** * サーバーによる恒久的な認証拒否で停止したトランスポート('terminal'/'vscode')。 * heartbeat でバックエンドに報告し、管理画面でプロジェクト単位の機能停止を可視化する。 * agentId はプロセス起動時に確定するため、設定修正後は必ず再起動が必要で、 * 再起動でこの集合は空に戻る(→ サーバー側で属性が削除される)。 */ authRejectedTransports: Set; /** * Command IDs this process is currently executing. * * The server keeps a claimed command in `PENDING` until its result arrives, * so `getPendingCommands` keeps returning commands we are still running, and * `claimCommand` answers 200 (not 409) to the instance that already owns the * claim. Without this guard the periodic sweep would start a second local * execution of any command that takes longer than the sweep interval — * duplicating its side effects (SSH/Ansible runs, ECS task launches). */ inFlightCommands: Set; /** * Set by `ProjectAgent.shutdown()` once graceful shutdown has begun. New * commands are declined (without being fetched/acknowledged) while this is * true — see `processCommand` / `checkPendingCommands` — so the process only * has to wait for commands already in flight before releasing its slot. * Defaults to false. */ draining: boolean; } export interface TransportDeps { client: ApiClient; agentId: string; prefix: string; apiUrl: string; token: string; projectDir: string | undefined; tenantCode: string; projectCode: string; /** @deprecated pollInterval is no longer used. Kept for backward compatibility with CLI options. */ pollInterval: number; heartbeatInterval: number; /** * サーバーによる恒久的な認証拒否(Agent ID トークンバインディング不一致等)で * terminal-ws / vscode-ws の接続が停止した際に呼ばれる。子プロセスから親プロセスへ * 通知するために使う(ログに埋もれさせないため)。transport は拒否された接続の種別。 */ onAuthRejected?: (transport: TransportKind) => void; /** * Called when a heartbeat reports that this replica lost its slot (it was * evicted so a newer replica could run under the plan's replica limit). * The agent must stop serving work and go back to standby. */ onEvicted?: () => void; } export interface CommandContext { configSyncState: ConfigSyncState; configSyncDeps: ConfigSyncDeps; transportState: TransportState; /** * `commandId`, when present, is the id of the `setup`/`config_sync` command * itself — threaded through so a Docker-mode config sync that detects a * customization change and fires `performDockerRebuild()` can pass it to * `shutdown({ excludeCommandId })`. See `ConfigSyncDeps.onDockerRebuild`'s * doc comment in agent-config-sync.ts. */ onSetup: (commandId?: string) => Promise; onConfigSync: (commandId?: string) => Promise; /** * `commandId` is the id of the 'reboot' command itself, threaded through so * `ProjectAgent.performReboot()` can pass it to `shutdown({ excludeCommandId })` * — without it, shutdown()'s drain would wait forever for this very command * (still in `inFlightCommands` until this handler returns) to finish. See * `ProjectAgent.shutdown` for the full explanation. */ onReboot: (commandId?: string) => Promise; /** Same self-reference concern as `onReboot` — see its doc comment. */ onUpdate: (commandId?: string) => Promise; onSyncRepository: (repositoryCode: string, branch?: string) => Promise; } /** * Start subscription mode via AppSync WebSocket. */ export declare function startSubscriptionMode(deps: TransportDeps, state: TransportState, ctx: CommandContext, AppSyncSubscriberClass: new (url: string, authToken: string) => AppSyncSubscriber, appsyncUrl: string, authToken: string): Promise; /** * Start heartbeat interval. */ /** * terminal-ws / vscode-ws がサーバーによる恒久的な認証拒否で停止した際に呼ばれる。 * ローカルで再起動が必要な状態を記録し、次回 heartbeat でバックエンドに報告する * (管理画面での可視化)とともに、既存の外部通知(子→親 IPC 等)にも中継する。 */ export declare function onTransportAuthRejected(deps: TransportDeps, state: TransportState, transport: TransportKind): void; export declare function startHeartbeat(deps: TransportDeps, state: TransportState, configSyncState: ConfigSyncState, configSyncDeps: ConfigSyncDeps): void; /** * Start terminal WebSocket connection. * @param wsUrl - サーバーから返されたWebSocket URL(指定時はapiUrlの代わりに使用) * @param configSyncState - PTY セッション起動時に最新の envVars を取り出すための参照 */ export declare function startTerminalWebSocket(deps: TransportDeps, state: TransportState, wsUrl?: string, configSyncState?: ConfigSyncState): void; /** * Start VS Code tunnel WebSocket connection. * @param wsUrl - サーバーから返されたWebSocket URL(指定時はapiUrlの代わりに使用) * @param configSyncState - code-server プロセス起動時に最新の envVars を取り出すための参照 */ export declare function startVsCodeTunnel(deps: TransportDeps, state: TransportState, wsUrl?: string, configSyncState?: ConfigSyncState): void; /** * Handle an incoming AppSync notification. */ export declare function handleNotification(deps: TransportDeps, state: TransportState, ctx: CommandContext, notification: AppSyncNotification): Promise; /** * Check for pending commands (used after reconnection). */ export declare function checkPendingCommands(deps: TransportDeps, ctx: CommandContext): Promise; /** * Stop all transport resources. */ /** * Stop the transport (heartbeat, subscriptions, WebSockets). * * `inFlightCommands` is deliberately NOT cleared: a transport restart * (token update, eviction → standby) does not abort commands that are already * running, and clearing the set would let the same process pick the same * command up again while the first execution is still going. * Each `processCommand` removes its own entry in `finally`. */ export declare function stopTransport(state: TransportState): void; //# sourceMappingURL=agent-transport.d.ts.map