export interface HulaApiConfig { baseUrl: string; apiKey: string; timeout?: number; } export interface ApiTrackedPlan { id: string; trackingName: string; issueNumber: number | null; title: string; trackingStatus: string; githubState: string; priority: string; project: { owner: string; name: string; fullName: string; }; prNumber?: number | null; prUrl?: string | null; githubUrl: string; createdAt: string; updatedAt: string; deploymentStatus?: 'pending' | 'success' | 'failed' | null; /** * Server-side owner id. Optional for backward compatibility with older * servers that did not expose this field. */ createdById?: string; } export interface PlanStatusResponse { plan: ApiTrackedPlan; copilotStatus: { status: string; isAssigned: boolean; hasPR: boolean; }; lastPolled: string; } export interface TrackPlanRequest { owner: string; repo: string; issueNumber: number; trackingName: string; title: string; priority?: string; planPath?: string; copilotAssigned?: boolean; } /** * One plan entry in a feature-group status response (hula-server PR #505, * `GET /api/v1/groups/:groupId`). */ export interface GroupPlanEntry { id: string; trackingName: string; trackingStatus: string; prNumber: number | null; prUrl: string | null; prMerged: boolean; deploymentStatus: string | null; prConflictStatus: string | null; githubState: string | null; issueNumber: number | null; githubUrl: string | null; updatedAt: string; project: { owner: string; name: string; fullName: string; }; latestTask: { id: string; status: string; startedAt: string | null; completedAt: string | null; } | null; } /** * Combined status for a feature group (hula-server PR #505). */ export interface GroupStatusResponse { groupId: string; total: number; completed: number; plans: GroupPlanEntry[]; } export interface ListPlansResponse { plans: ApiTrackedPlan[]; total: number; page: number; limit: number; totalPages: number; /** * The id of the authenticated user. Optional for backward compatibility * with older servers that did not expose this field. */ currentUserId?: string; } /** * HTTP client for communicating with hula-project REST API. * Handles authentication, retries, and error mapping. * * @example * const client = new HulaApiClient({ * baseUrl: 'https://hula.example.com', * apiKey: 'hula_sk_...' * }); * const plans = await client.listPlans(); */ export declare class HulaApiClient { private client; constructor(config: HulaApiConfig); /** * List all tracked plans for authenticated user */ listPlans(filters?: { status?: string; priority?: string; project?: string; page?: number; limit?: number; }): Promise; /** * Track a new plan */ trackPlan(data: TrackPlanRequest): Promise<{ plan: ApiTrackedPlan; }>; /** * Get detailed status for a specific plan */ getPlanStatus(owner: string, repo: string, issueNumber: number): Promise; /** * Update plan priority */ updatePlanPriority(planId: string, priority: string): Promise<{ plan: ApiTrackedPlan; }>; /** * Untrack a plan */ untrackPlan(planId: string): Promise<{ success: boolean; }>; /** * Fetch the latest Task's logs for a tracked plan (plain text). * Calls GET /api/v1/logs/:planName. * * The URL string `/api/v1/logs/` is preserved across the server * rename; only the underlying resolution semantics changed (the server * now resolves the name to a Plan and reads its latest Task's log). * * When `options.include` is provided it is forwarded as the `include` * query param (`logs` | `lessons` | `all`), selecting the persisted run * log, lessons markdown, or both instead of the default live output tail. * When omitted, no `include` param is sent and the server returns the * live `lastOutput` tail (unchanged default behavior). */ fetchTaskLogs(planName: string, options: { type?: 'log' | 'output'; lines?: number; project: string; include?: 'logs' | 'lessons' | 'all'; }): Promise; /** * Fetch the multi-key info object for a tracked plan (server PR #421). * Calls GET /api/v1/info/:planName. * * @param planName - plan tracking name (branch name) * @param options.include - one or more of 'logs'|'lastLogs'|'diff'|'initial'|'lessons' * @param options.project - 'owner/repo' (required by the server) * @param options.lines - trailing-line count for the `lastLogs` key only * @returns object with exactly the requested keys, each a string or null */ fetchInfo(planName: string, options: { include: Array<'logs' | 'lastLogs' | 'diff' | 'initial' | 'lessons'>; project: string; lines?: number; }): Promise>; /** * Fetch combined status for a feature group (hula-server PR #505). * Calls GET /api/v1/groups/:groupId. * * The endpoint is scoped by the caller's project membership (not by the API * key's project), so any member repo's key works. A 404 is intentionally * ambiguous server-side — it means either the group does not exist OR the * caller is not a member of any of its projects (the caller cannot * distinguish the two). A 404 can also mean the server predates feature * groups; callers surface that possibility in the user-facing message. * * @param groupId - The opaque group id (validated `^[A-Za-z0-9_-]{1,64}$`). * @returns The group's `total`/`completed` counts and per-plan entries. */ fetchGroupStatus(groupId: string): Promise; /** * Check the authenticated user's subscription plan. * Calls GET /api/v1/user/subscription. */ checkUserTier(): Promise<{ plan: 'free' | 'pro'; subscriptionStatus: string | null; currentPeriodEnd: string | null; }>; /** * Detects when a 404 came from the `/api/v1/plans` collection endpoint * and rethrows as an `IncompatibleServerError`. A collection 404 can * only mean the server predates the Plan/Project/Task rename. Per- * resource 404s (e.g. `/api/v1/plans/`) keep `NotFoundError` * semantics and are handled by `handleError()`. */ private maybeRethrowAsIncompatibleServer; /** * Handle API errors with user-friendly messages */ private handleError; } export declare class ApiError extends Error { statusCode?: number | undefined; constructor(message: string, statusCode?: number | undefined); } export declare class AuthenticationError extends ApiError { constructor(message: string); } export declare class AuthorizationError extends ApiError { constructor(message: string); } export declare class NotFoundError extends ApiError { constructor(message: string); } export declare class ConflictError extends ApiError { constructor(message: string); } export declare class RateLimitError extends ApiError { constructor(message: string); } export declare class ServerError extends ApiError { constructor(message: string); } export declare class TimeoutError extends ApiError { constructor(message: string); } export declare class NetworkError extends ApiError { constructor(message: string); } /** * Raised when hub-launch detects that the connected hula-server predates * the Plan/Project/Task rename (NoStackApp/hula-server PR #159) — i.e. a * 404 on the `/api/v1/plans` collection endpoint. */ export declare class IncompatibleServerError extends ApiError { constructor(); } //# sourceMappingURL=HulaApiClient.d.ts.map