/** * HTTP client for the Cursell Agent Hub API. * Calls the public endpoints at /api/v1/agents/*. * Auth token is optional — only needed for private/org agents. */ export declare class HubApiError extends Error { status: number; constructor(status: number, message: string); } /** * Phase 3 of agent-namespace: thrown when the server replies 403 * with the `requires_username` shape — i.e. the caller authenticated * but their workspace has not yet claimed a username, so any * agent-bearing route is gated. Surfaces the operator-facing claim * URL (relative path, e.g. `/onboarding/username`) so the CLI can * print a hint and the MCP server can return a content block * explaining the next step. Never thrown as a side-effect of * unrelated 403s — only when the response body's `requires_username` * field is true. */ export declare class RequiresUsernameError extends Error { readonly claimUrl: string; constructor(claimUrl: string); } export interface AgentSummary { id: string; slug: string; name: string; description: string; category: string; tags: string[]; visibility: string; authorId: string; /** * Cross-phase contract (post agent-namespace): the server's * `serializeAgent` narrows these three fields to non-null and * filters null-username rows out of every public-list route * before serialization (see packages/server/src/serializers/ * agent.ts and routes/agents.ts `filterPublishable`). The CLI * type mirrors that contract so a future consumer can't add a * `?? fallback` against a value the server guarantees — the * "single source of normalization across server + CLI + website" * parity the cross-phase audit calls out. Defensive runtime * checks elsewhere (`checkRegistryRefMatch`, registry zod * `.nullable()` parser for back-compat with older server * versions) stay as belt-and-suspenders. */ authorUsername: string; authorName: string | null; authorAvatarUrl: string | null; canonicalRef: string; canonicalUrl: string; /** * The workspace that owns the agent. `null` for legacy public agents * created before workspaces were tracked. Used by mutation pre-checks to * mirror the server's `canMutateAgent` workspace gate. */ workspaceId: string | null; currentVersion: string; sizeWords: number; sizeTag: "lightweight" | "medium" | "large"; votes: number; downloads: number; } export interface AgentDetail extends AgentSummary { content: string; /** * Trust-contract fields populated after Phase 2B (NOT NULL in * production). Optional in the type so older registry versions * that don't yet emit these fields don't fail to type-check; * Phase 4b code that depends on them validates with Zod and * raises a clear error if absent. */ contentHash?: { algo: "sha256-v1"; value: string; }; publishedBy?: string; publishedAt?: string; } export interface SearchResult { agents: AgentSummary[]; hasMore: boolean; limit: number; offset: number; } export declare class HubApiClient { private apiUrl; private token?; constructor(apiUrl: string, token?: string | undefined); private request; search(params: { query?: string; category?: string; tag?: string; limit?: number; offset?: number; }): Promise; getAgent(ref: string): Promise<{ agent: AgentDetail; }>; /** * Fetch a specific version of an agent. The server returns the * same shape as `getAgent(slug)` but with `currentVersion`, * `content`, `contentHash`, `publishedBy`, `publishedAt` * populated from that exact version's record. Used by Phase 4b * `cursell add @` to pin the resolved version, and by * `cursell install` to re-fetch a missing cache entry. */ getAgentVersion(ref: string, version: string): Promise<{ agent: AgentDetail; }>; trackDownload(ref: string): Promise; createAgent(payload: { name: string; /** * Phase 3 of agent-namespace: explicit canonical slug, NFKC-folded * + lowercased + ASCII-regex validated upstream via the shared * `validateAgentSlug`. Server re-runs the same validator before * insert so the canonical pipeline is single-sourced. */ slug: string; description: string; category: string; tags?: string[]; visibility?: "public" | "private"; content: string; version?: string; }): Promise<{ agent: AgentDetail; }>; updateAgent(ref: string, payload: { name?: string; description?: string; category?: string; tags?: string[]; visibility?: "public" | "private"; content?: string; version?: string; changelog?: string; }): Promise<{ agent: AgentDetail; }>; /** * Returns the authenticated user + workspace context. * * Hits `/api/auth/context` rather than `/api/auth/me` because the CLI * authenticates with API tokens (issued by `cursell hub login`), and * `/me` only validates Better Auth sessions — API tokens get 401 there. * `/context` accepts both session cookies and Bearer tokens (session OR * API), which is what `cursell hub login` already validates against. */ getAuthContext(): Promise<{ userId: string; workspaceId: string; user: { id: string; email: string; name: string | null; avatarUrl: string | null; hasCompletedOnboarding: boolean; /** * Phase 3 of agent-namespace: server emits `username` on this * payload (`null` when the workspace has not yet claimed one). * Typed here so the CLI / MCP author-side flows can read it * without an unsafe cast — a future server rename surfaces as * a type error rather than a soft runtime divergence. */ username: string | null; }; }>; }