/** * ForgeOS Engine HTTP client — shared between MCP server and CLI binary. * * Improvements over the original src/client.ts: * - Structured error handling via ForgeAPIError (parses engine error envelope) * - delete() method * - Auto-generated Idempotency-Key header on POST/PUT/PATCH * - Retry on 429/503 with exponential backoff (up to 3 retries, respects Retry-After) * - healthCheck() convenience method * - Configurable timeout (constructor param) * - Retry guard prevents infinite loops (max 3 rate-limit retries, 1 network retry) * - Local-only mode: loopback/local-engine calls allowed, non-loopback outbound blocked * - Engine version capture: stores X-ForgeOS-Engine-Version from response headers * * Sprint 1 DX additions : * - findProjectConfig(): walks up the directory tree looking for .forgeos/config.json * - Project config schema: { schema_version, project_id, endpoint, profile } * - Callers can use findProjectConfig() to auto-populate project_id / engine URL * without requiring explicit --project flags. * * Design constraints preserved from original: * - X-ForgeOS-API-Key header (not Authorization Bearer) for engine auth * - Module-level singleton for the stdio transport path (single-tenant) * - HTTP transport MUST NOT use the singleton — construct per-request instances * - 10-second default timeout per request * - One retry on network errors (TypeError from fetch) * * Local-only mode (resolved in order): * 1. FORGE_LOCAL_ONLY=true environment variable * 2. local_only: true in ~/.forgeos/config.json * Semantics: "talk only to local/loopback services; never phone home." When * active, calls to loopback hosts (127.0.0.0/8, localhost, ::1 — including the * local engine on 127.0.0.1:8400) proceed normally; only genuine non-loopback * outbound throws LocalOnlyError. Trust/score commands (which never call the * engine) are unaffected either way. */ /** * Schema for the project-local .forgeos/config.json file written by `forge init`. * Fields introduced in Sprint 1 (schema_version, endpoint, profile) coexist with * the legacy fields (project_id, platform, local_only, created_at) written by * the existing init wizard. */ export interface ProjectLocalConfig { /** Format version — "1" for Sprint 1 and later. May be absent in legacy configs. */ schema_version?: string; project_id: string; /** Engine endpoint override for this project. Falls back to global config / env. */ endpoint?: string; /** Profile name applied at init time (e.g. "backend-service"). */ profile?: string; /** Legacy fields written by the original init command. */ platform?: string; local_only?: boolean; created_at?: string; } /** * Walk up the directory tree from `startDir` looking for `.forgeos/config.json`. * Returns the parsed config and the directory where it was found, or null if * no config is found before reaching the filesystem root. * * Resolution order (first match wins): * 1. /.forgeos/config.json * 2. /.forgeos/config.json * … up to filesystem root */ export declare function findProjectConfig(startDir?: string): { config: ProjectLocalConfig; dir: string; } | null; /** * True when `host` is a loopback / local address that stays on this machine. * * local-only mode is about *never phoning home* — loopback traffic (your local * engine on 127.0.0.1:8400, localhost, ::1) never leaves the box, so it must be * allowed. Only genuine non-loopback outbound is blocked. * * Covers: localhost (and *.localhost), the whole 127.0.0.0/8 range, and IPv6 * loopback ::1 (with or without brackets). */ export declare function isLoopbackHost(host: string): boolean; /** * Error thrown when local-only mode blocks a *non-loopback* outbound call. * * Note the semantics: local-only does NOT disable all networking — it permits * loopback/local-engine traffic and refuses only calls that would leave the * machine. This error is therefore only ever raised for a genuine phone-home. */ export declare class LocalOnlyError extends Error { readonly host: string; constructor(host: string); } export declare class ForgeOSClient { private baseUrl; private apiKey; private timeout; /** * Last engine version observed from X-ForgeOS-Engine-Version response header. * Null until a successful response is received. */ private _engineVersion; /** * Last API schema version observed from X-ForgeOS-API-Schema response header. * Null until a successful response is received. */ private _apiSchema; /** * @param baseUrl Engine base URL. Defaults to FORGEOS_ENGINE_URL or http://localhost:8400. * @param apiKey API key sent as X-ForgeOS-API-Key. Pass explicitly; do NOT read from env here. * @param timeout Per-request timeout in ms. Default 10 000. */ constructor(baseUrl?: string, apiKey?: string, timeout?: number); /** Engine version last seen in X-ForgeOS-Engine-Version header. Null if no call made yet. */ get engineVersion(): string | null; /** API schema version last seen in X-ForgeOS-API-Schema header. Null if no call made yet. */ get apiSchema(): string | null; get(path: string, params?: Record): Promise; post(path: string, body?: unknown): Promise; patch(path: string, body?: unknown): Promise; put(path: string, body?: unknown): Promise; delete(path: string): Promise; /** * Lightweight liveness check. Returns true if the engine responds 2xx on * GET /health, false otherwise. Never throws. Respects local-only mode * (returns false immediately when local-only is active). */ healthCheck(): Promise; /** * Execute an HTTP request with: * - AbortController timeout * - Auto Idempotency-Key on mutating methods * - Retry on network errors (up to MAX_NETWORK_RETRIES) * - Retry on 429/503 (up to MAX_RATE_RETRIES, respects Retry-After) * - ForgeAPIError on non-ok HTTP responses */ private request; } /** * Module-level singleton for the stdio transport path. * Reads credentials from env at startup — safe because stdio is single-tenant * (one process = one user). * * The HTTP transport MUST NOT use this singleton. It constructs per-request * ForgeOSClient instances with the key extracted from the Authorization header. */ export declare const client: ForgeOSClient; //# sourceMappingURL=client.d.ts.map