/
outbreak
/
kilocode
Обзор
Документация
Войти
/
outbreak
/
kilocode
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
packages/cloud/src/CloudAPI.ts
147 строк
4 KB
John Richmond
Add a RCC credit balance display (#9386)
20 ноя 2025, 05:36
Не верифицирован
20 ноя 2025, 05:36
f1bf436
Код
Авторство
О чём код?
import { z } from "zod" import { type AuthService, type ShareVisibility, type ShareResponse, shareResponseSchema } from "@roo-code/types" import { getRooCodeApiUrl } from "./config.js" import { getUserAgent } from "./utils.js" import { AuthenticationError, CloudAPIError, NetworkError, TaskNotFoundError } from "./errors.js" interface CloudAPIRequestOptions extends Omit<RequestInit, "headers"> { timeout?: number headers?: Record<string, string> } export class CloudAPI { private authService: AuthService private log: (...args: unknown[]) => void private baseUrl: string constructor(authService: AuthService, log?: (...args: unknown[]) => void) { this.authService = authService this.log = log || console.log this.baseUrl = getRooCodeApiUrl() } private async request<T>( endpoint: string, options: CloudAPIRequestOptions & { parseResponse?: (data: unknown) => T } = {}, ): Promise<T> { const { timeout = 30_000, parseResponse, headers = {}, ...fetchOptions } = options const sessionToken = this.authService.getSessionToken() if (!sessionToken) { throw new AuthenticationError() } const url = `${this.baseUrl}${endpoint}` const requestHeaders = { "Content-Type": "application/json", Authorization: `Bearer ${sessionToken}`, "User-Agent": getUserAgent(), ...headers, } try { const response = await fetch(url, { ...fetchOptions, headers: requestHeaders, signal: AbortSignal.timeout(timeout), }) if (!response.ok) { await this.handleErrorResponse(response, endpoint) } const data = await response.json() if (parseResponse) { return parseResponse(data) } return data as T } catch (error) { if (error instanceof TypeError && error.message.includes("fetch")) { throw new NetworkError(`Network error while calling ${endpoint}`) } if (error instanceof CloudAPIError) { throw error } if (error instanceof Error && error.name === "AbortError") { throw new CloudAPIError(`Request to ${endpoint} timed out`, undefined, undefined) } throw new CloudAPIError( `Unexpected error while calling ${endpoint}: ${error instanceof Error ? error.message : String(error)}`, ) } } private async handleErrorResponse(response: Response, endpoint: string): Promise<never> { let responseBody: unknown try { responseBody = await response.json() } catch { responseBody = await response.text() } switch (response.status) { case 401: throw new AuthenticationError() case 404: if (endpoint.includes("/share")) { throw new TaskNotFoundError() } throw new CloudAPIError(`Resource not found: ${endpoint}`, 404, responseBody) default: throw new CloudAPIError( `HTTP ${response.status}: ${response.statusText}`, response.status, responseBody, ) } } async shareTask(taskId: string, visibility: ShareVisibility = "organization"): Promise<ShareResponse> { this.log(`[CloudAPI] Sharing task ${taskId} with visibility: ${visibility}`) const response = await this.request("/api/extension/share", { method: "POST", body: JSON.stringify({ taskId, visibility }), parseResponse: (data) => shareResponseSchema.parse(data), }) this.log("[CloudAPI] Share response:", response) return response } async bridgeConfig() { return this.request("/api/extension/bridge/config", { method: "GET", parseResponse: (data) => z .object({ userId: z.string(), socketBridgeUrl: z.string(), token: z.string(), }) .parse(data), }) } async creditBalance(): Promise<number> { return this.request("/api/extension/credit-balance", { method: "GET", parseResponse: (data) => { const result = z.object({ balance: z.number() }).parse(data) return result.balance }, }) } }