@essentialai/cogent-bridge
Version:
Cogent Bridge — cross-agent comms for Claude Code, OpenAI Codex and Slack. Codex users: install with `curl -fsSL https://cogent.tools/install.sh | sh`, then start with `cogent-codex` for real-time peer wake.
76 lines • 3.81 kB
TypeScript
/**
* Authenticated HTTP client for cloud relay server communication.
* Uses Node built-in fetch() (Node 18+) with Bearer token auth.
* Maps HTTP error responses to BridgeError for consistent error handling.
*/
export declare class HttpClient {
private readonly baseUrl;
private token;
constructor(baseUrl: string, token: string);
private headers;
/**
* fetch() with an AbortController timeout. Node's fetch has NO default
* timeout, so a stalled relay connection would otherwise block forever and
* stall the WS poll fallback. An abort maps to a NETWORK_TIMEOUT BridgeError;
* every other rejection (DNS, connection refused, etc.) propagates unchanged.
*/
private fetchWithTimeout;
/**
* Parse a SUCCESS body, turning an unparseable one into a BridgeError.
*
* 🔴 WHY THIS EXISTS. `throwMappedError` has always guarded the NON-2xx path, so an nginx 502 or
* 413 HTML page arrives as a clean BridgeError. The 2xx path did not: `return resp.json()` let a
* truncated or empty success body escape as a raw `SyntaxError` carrying no code, no suggestion,
* and nothing in the signature to warn a caller it could happen — callers at
* http-backend.ts (list peers / get history / health check) simply propagated it.
*
* That is the worst corner of the trade-off the vault describes (how much information a failure
* carries vs how strictly consumers must handle it —
* memory/typescript-master-vault/concepts/Error_Handling.md), in a codebase whose own
* BridgeError(code, message, suggestion) is the answer to it.
*
* A 2xx with an unreadable body is REAL: @hono/node-server can answer with a null body or append
* `Error: …` to an already-streaming response (handleResponseError), and any proxy may truncate a
* long /poll body. STARTUP_FAILED is deliberately the same code throwMappedError falls back to
* for a non-JSON error body, so both directions of "the relay said something we cannot read"
* report identically rather than inventing a second vocabulary.
*/
private parseJson;
/**
* Perform an authenticated GET request.
* Appends query parameters to the URL if provided.
*/
get<T>(path: string, query?: Record<string, string>): Promise<T>;
/**
* Perform an authenticated POST request with a JSON body.
*/
post<T>(path: string, body: unknown): Promise<T>;
/**
* Perform an authenticated PATCH request with a JSON body.
* Used to update existing resources (e.g., message response fields).
*/
patch<T>(path: string, body: unknown): Promise<T>;
/**
* Perform an authenticated DELETE request.
* Returns the RESPONSE HEADERS (a 204 carries no body, but the relay conveys
* out-of-band signals — e.g. Cogent Mail F3's `X-Cogent-Mailbox-Deprovisioned` —
* via headers, so callers that need them can read them without a body).
*
* When no body is provided, Content-Type is omitted so servers don't try
* to parse an empty payload as JSON. This was the root cause of a
* "Malformed JSON in request body" 400 from cogent-server <=3.1.2 when
* any client (including third-party tools) DELETEd a peer without a body.
*/
delete(path: string, body?: unknown): Promise<Headers>;
/**
* Update the Bearer token (e.g., after join-session returns a new token).
*/
updateToken(newToken: string): void;
/**
* Parse an error response from the server and throw a BridgeError.
* If the server returns a cogent ErrorCode, it is passed through.
* For non-JSON error responses, STARTUP_FAILED is used as a fallback code.
*/
private throwMappedError;
}
//# sourceMappingURL=http-client.d.ts.map