import type { Server } from 'net'; export declare function readJsonSync(filePath: string): T; /** * 指定したミリ秒だけ待機する Promise を返す。 * `await new Promise((resolve) => setTimeout(resolve, ms))` の重複イディオムを集約する。 */ export declare function sleep(ms: number): Promise; export declare function atomicWriteFile(filePath: string, content: string, mode?: number): void; /** * オブジェクトを 2 スペースインデントの JSON として atomicWriteFile で書き込む。 * `atomicWriteFile(path, JSON.stringify(data, null, 2))` の重複を集約する。 */ export declare function atomicWriteJson(filePath: string, data: unknown, mode?: number): void; /** * base64 文字列を UTF-8 文字列にデコードする。 * `Buffer.from(value, 'base64').toString('utf-8')` の重複を集約する。 */ export declare function decodeBase64Utf8(value: string): string; /** * `net.Server.address()`(`string | AddressInfo | null`)から数値ポートを安全に取り出す。 * 未リッスン / UNIX ソケット等でポートを特定できない場合は undefined を返す * (`as AddressInfo` キャストの代替となるランタイムガード)。 */ export declare function getAddressPort(server: Server): number | undefined; /** * ディレクトリが存在しなければ再帰的に作成する。 * `if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true })` の重複イディオムを集約する。 * * `mode` を渡すと、新規作成されるディレクトリにそのパーミッションを適用する * (秘匿ディレクトリ向けに 0o700 等)。既に存在する場合は何もしない。 * * @param dir 作成するディレクトリパス * @param mode 新規作成時に適用するパーミッション(省略時は OS デフォルト) */ export declare function ensureDir(dir: string, mode?: number): void; /** * unknown な catch 値からメッセージ文字列を取り出す。 * Error なら `.message`、それ以外は `String()` を返す。 * `err instanceof Error ? err.message : String(err)` の重複イディオムを集約する。 */ export declare function toErrorMessage(error: unknown): string; /** * 許可リストのキーのうち、`process.env` に定義されている(undefined でない)ものだけを * 抽出した環境変数マップを返す。未定義キーは含めない。 * `buildSafeEnv` / `buildDockerEnv` の重複したパススルーループを共通化する。 */ export declare function pickPresentEnv(keys: readonly string[]): Record; /** * unknown な catch 値を Error インスタンスに正規化する。 * Error ならそのまま、それ以外は `String()` をメッセージにした Error を生成する。 * `err instanceof Error ? err : new Error(String(err))` の重複イディオムを集約する。 */ export declare function toError(error: unknown): Error; /** * AxiosError のレスポンスボディを型付けして取り出す。 * axios エラーでない・`response` が無い場合は undefined を返す。 * 各所で重複していた `error.response.data as Record | undefined` * の取り出しを集約する。 */ export declare function axiosResponseData(error: unknown): Record | undefined; /** * AxiosError の HTTP レスポンスステータスコードを安全に取り出す。 * axios エラーでない場合は undefined を返す(`as AxiosError` キャストの代替)。 */ export declare function axiosResponseStatus(error: unknown): number | undefined; /** * 任意の値を、ユーザー向けメッセージ/ログに埋め込める文字列へ変換する。 * * テンプレートリテラルへオブジェクトをそのまま埋めると `[object Object]` に * なってしまい、サーバーが構造化ボディ(バリデーションエラーの配列等)を返した * ときにメッセージが無意味になる。この関数はその防止を一箇所に集約する。 * * - 文字列はそのまま返す(既存の出力を一切変えないための後方互換) * - それ以外は `JSON.stringify` で可読化し、`MESSAGE_VALUE_MAX_LENGTH` で切り詰める * - 循環参照は `[Circular]` に置換して例外にしない。`JSON.stringify` 自体が * 投げるケース(BigInt・throw する toJSON 等)も握って `String()` に退避する * * 既知の制限: 訪問済みノードを WeakSet で記録するため、循環していない「同じ * オブジェクトが複数箇所に現れる」共有参照も、2 回目以降は `[Circular]` になる。 * 現在の呼び出し元は受信 JSON を `JSON.parse` した値のみで、`JSON.parse` は * 共有参照を作らないため実際には発現しない。プロセス内で組み立てた値に対して * 使う場合はこの欠落に注意すること(診断テキスト専用であり、データの復元用途に * 使う関数ではない)。 */ export declare function stringifyForMessage(value: unknown): string; /** * エラーから詳細なメッセージを抽出する。 * AxiosError の場合はレスポンスボディの message/error フィールドとHTTPステータスコードを含める。 * それ以外の Error はメッセージを、非 Error は String() を返す。 */ export declare function getErrorMessage(error: unknown): string; export declare function parseString(value: unknown): string | null; export declare function parseNumber(value: unknown): number | null; export declare function truncateString(text: string, limit: number, suffix?: string): string; /** * Sanitize a single name segment for use in generated identifiers: * lowercase the input and collapse every character outside `[a-z0-9-]` to `-`. * * This is the single source of truth for the `toLowerCase().replace(/[^a-z0-9-]/g, '-')` * idiom that was previously duplicated across the codebase (docker container * names, systemd unit names, launchd plist labels, scheduled-task names, and * the generated agentId). Keeping one implementation guarantees these * identifiers stay consistent so collision detection and name-based lookups * cannot drift between subsystems. */ export declare function sanitizeNameSegment(s: string): string; /** * Remove a single trailing slash from a path/prefix. * * Single source of truth for the `replace(/\/$/, '')` idiom used in * path-prefix containment checks (security path guards and Docker volume * mount builders), so the normalization stays identical across them. */ export declare function stripTrailingSlash(path: string): string; export declare function validateApiUrl(url: string): string | null; export declare function isAuthenticationError(error: unknown): boolean; /** * 認証エラー(401/403)を除く 4xx クライアントエラーかどうかを判定する。 * * 401/403 は再ログインで解消し得るため除外する。それ以外の 4xx は * 「コマンドが存在しない/無効」を意味し、再試行しても無駄なので判別に使う。 */ export declare function isNonAuthClientError(error: unknown): boolean; /** * AxiosError のレスポンスデータが SSO_AUTH_REQUIRED エラーかどうかを判定する。 * * AWS SSO 認証切れ時にサーバーが返す `error: 'SSO_AUTH_REQUIRED'` または * `errorCode: 'SSO_AUTH_REQUIRED'` フィールドを検出する。 * 各モジュールで重複していた同一ロジックをここに集約する。 */ export declare function isSsoAuthRequiredError(error: unknown): boolean; export declare function buildWsUrl(apiUrl: string, path: string): string; /** * Returns true when the agent is running inside a Docker container. * Controlled by the AI_SUPPORT_AGENT_IN_DOCKER=1 environment variable, * which is injected by volume-mount-builder and the service templates. */ export declare function isInDocker(): boolean; /** * Convert a localhost / 127.0.0.1 URL to host.docker.internal so that a * container can reach the host machine. * * Uses a boundary lookahead (`(?=$|[:/])`) to avoid false-positive matches on * hostnames like `localhost.example.com`. Handles both http and https schemes * and preserves any path / port that follows. * * Used by: * - docker/volume-mount-builder.ts (build-time, host→container URL rewrite) * - cli/service/*-service.ts (via wrapper-helpers re-export) */ export declare function toContainerApiUrl(apiUrl: string): string; /** * Docker コンテナ内から host の URL にアクセスするため * localhost / 127.0.0.1 を host.docker.internal に変換する。 * `AI_SUPPORT_AGENT_IN_DOCKER` が `'1'` のときのみ変換する。 */ export declare function resolveUrlForDocker(url: string): string; /** * Type guard for NodeJS.ErrnoException. * Narrows `unknown` catch values to ErrnoException and optionally checks the error code. * Avoids `instanceof Error` to stay compatible with Jest's `isolatedModules` environment * where filesystem errors may not pass the `instanceof` check. */ export declare function isErrnoException(err: unknown, code?: string): err is NodeJS.ErrnoException; /** * エラーメッセージをログに出力してプロセスを終了する。 * * `logger.error(msg)` + `process.exit(1)` のペアが agent-runner.ts / docker-runner.ts の * 複数箇所で繰り返されていたため集約する。 */ export declare function exitWithError(message: string): never; /** * Returns the current timestamp as an ISO 8601 string. * Centralizes `new Date().toISOString()` calls across the codebase. */ export declare function nowIso(): string; /** * Append `text` to `current` while keeping the total length within `limit` * bytes/chars. If the result would exceed `limit`, only the portion that fits * is appended and `truncated` is returned as `true` so the caller can emit a * one-time warning. Centralizes the cap-and-append idiom used by the Docker * container/build log accumulators. */ export declare function appendWithLimit(current: string, text: string, limit: number): { result: string; truncated: boolean; }; /** * Sweep `dir` for stale entries left behind by a crashed/killed process, * removing each one that matches `matches(name)` and is at least `maxAgeMs` * old (by mtime). * * Single source of truth for the "orphaned temp file/dir" sweep idiom that * was independently duplicated three times — `TerminalSession. * cleanupStaleSandboxes` (terminal-sandbox-* dirs in os.tmpdir()), * `cleanupStaleServerSetupDirs` (server-setup temp dirs holding an SSH * private key), and `cleanupStaleCommandMcpConfigs` (per-command MCP config * files carrying a plaintext token) — each with the same readdir → filter by * name → stat → age-check → rm shape, differing only in the match predicate, * whether removal is recursive, and how an individual removal failure is * reported. * * A missing/unreadable `dir` is treated as "nothing to clean" (returns 0), * matching all three previous implementations. * * @param dir directory to scan * @param matches predicate deciding whether an entry name is a candidate * @param options.maxAgeMs delete entries at least this old (ms); default 24h; * `0` removes every matching entry regardless of age * @param options.recursive passed through to `fs.rmSync` (true for * directories, false — the default — for plain files) * @param options.onError called (name, error) when removing a single matched * entry fails; the sweep continues with the remaining entries either way. * Omit to swallow the failure silently (matches the original * `cleanupStaleSandboxes` behavior). * @returns number of entries removed */ export declare function sweepStaleEntries(dir: string, matches: (name: string) => boolean, options?: { maxAgeMs?: number; recursive?: boolean; onError?: (name: string, error: unknown) => void; }): number; //# sourceMappingURL=utils.d.ts.map