/** * Zoe SDK — Shared TypeScript types * * This file is the single source of truth for all SDK interfaces. * Every SDK module imports from here. */ import type { ZoeError as ZoeErrorType } from "./errors.js"; import type { Middleware } from "./middleware.js"; export type ProviderType = "openai" | "anthropic" | "glm" | "openai-compatible"; export interface MultiProviderConfig { openai?: { apiKey: string; model?: string; }; anthropic?: { apiKey: string; model?: string; }; glm?: { apiKey: string; model?: string; }; "openai-compatible"?: { apiKey: string; baseUrl: string; model?: string; }; default: ProviderType; } export type ToolRiskCategory = "safe" | "edit" | "communications" | "destructive"; export type PermissionLevel = "strict" | "moderate" | "permissive"; export interface Message { id: string; role: "system" | "user" | "assistant" | "tool"; content: string; toolCalls?: ToolCall[]; toolCallId?: string; timestamp: number; } export interface ToolCall { id: string; name: string; arguments: Record; result?: string; } export interface StepResult { type: "text" | "tool_call" | "text_delta" | "tool_progress"; content?: string; toolCall?: { id: string; name: string; args: Record; result: string; duration: number; }; /** For tool_progress: identifies which in-flight tool call the chunk belongs to. */ toolCallId?: string; /** For tool_progress: the tool name + args (so the UI can render the block). */ name?: string; args?: Record; /** Tool-specific structured payload (e.g. write_file's FileWriteMetadata) for * adapters to render. Populated only on `tool_call` steps whose handler * returned a ToolResult with metadata. NEVER enters message history. */ metadata?: Record; timestamp: number; } export interface Usage { promptTokens: number; completionTokens: number; totalTokens: number; cost: number; } export interface CumulativeUsage { totalPromptTokens: number; totalCompletionTokens: number; totalCost: number; requestCount: number; } export interface UserToolDefinition { name?: string; description: string; parameters: unknown; execute: (args: unknown, context: ToolContext) => Promise; } export interface ToolContext { onUpdate?: (progress: { percentage?: number; message?: string; }) => void; signal?: AbortSignal; config?: Record; } export interface ToolResult { output: string; success: boolean; metadata?: Record; } export interface ApproveToolCall { name: string; args: Record; } /** * Adapter-provided callback invoked before every tool execution. * Return `true` to approve, `false` to deny (the tool is skipped * and "User denied tool execution" is returned as the tool output). * * Each adapter implements its own UX: * - CLI: inquirer prompt (with ESC interrupt suspended) * - SDK: user-supplied callback or auto-approve * - Server: WebSocket round-trip to client */ export type ApproveToolFn = (call: ApproveToolCall) => Promise; export interface Hooks { beforeToolCall?: (call: { name: string; args: Record; }) => void | Promise; afterToolCall?: (result: { name: string; output: string; duration: number; }) => void | Promise; onStep?: (step: StepResult) => void | Promise; onError?: (error: ZoeErrorType) => void | Promise; onFinish?: (result: GenerateTextResult) => void | Promise; } export interface GenerateTextOptions { model?: string; provider?: ProviderType; systemPrompt?: string; tools?: string[] | UserToolDefinition[]; skills?: string[]; maxSteps?: number; temperature?: number; maxTokens?: number; output?: unknown; hooks?: Hooks; signal?: AbortSignal; config?: Record; metadata?: Record; middleware?: Middleware[]; approveTool?: ApproveToolFn; permissionLevel?: PermissionLevel; } export interface GenerateTextResult { text: string; data?: unknown; error?: { message: string; issues: unknown; }; steps: StepResult[]; toolCalls: ToolCall[]; usage: Usage; finishReason: "stop" | "length" | "max_steps" | "error"; messages: Message[]; } export interface StreamTextOptions extends GenerateTextOptions { onText?: (delta: string) => void; onToolCall?: (tool: { name: string; args: Record; callId: string; }) => void; onToolResult?: (result: { callId: string; output: string; success: boolean; }) => void; onStep?: (step: StepResult) => void; onError?: (error: ZoeErrorType) => void; } export interface StreamTextResult { textStream: AsyncIterable; steps: AsyncIterable; fullText: Promise; usage: Promise; finishReason: Promise; abort: () => void; toResponse: () => Response; toSSEStream: () => ReadableStream; } export interface AgentCreateOptions { model?: string; provider?: ProviderType; systemPrompt?: string; tools?: string[] | UserToolDefinition[]; skills?: string[]; maxSteps?: number; permissionLevel?: PermissionLevel; persist?: string | PersistenceBackend | PersistenceConfig | SessionStore; hooks?: Hooks; config?: Record; metadata?: Record; middleware?: Middleware[]; approveTool?: ApproveToolFn; } export interface SdkAgent { chat(message: string): Promise; chatStream(message: string, options?: StreamTextOptions): Promise; switchProvider(provider: ProviderType, model?: string): Promise; setSystemPrompt(prompt: string): void; setTools(tools: string[]): void; abort(): void; clear(): void; getHistory(): Message[]; getUsage(): CumulativeUsage; } export interface AgentResponse { text: string; toolCalls: ToolCall[]; usage: Usage; } /** * Composable persistence backend. Implementations handle raw storage * (file system, Redis, SQLite, etc.). Server-specific metadata (TTL, * apiKeyHash) flows through the `metadata` field on `SessionData`. */ export interface PersistenceBackend { /** Brand discriminator to distinguish from SessionStore */ __persistenceBackend: true; save(id: string, data: SessionData): Promise; load(id: string): Promise; delete(id: string): Promise; list(): Promise; } /** * Configuration object for creating a persistence backend via the factory. * `type` selects the backend; remaining keys are backend-specific options. */ export interface PersistenceConfig { type: string; [key: string]: unknown; } /** * @deprecated Use `PersistenceBackend` instead. Kept for backward compatibility. */ export interface SessionStore { save(sessionId: string, messages: Message[]): Promise; load(sessionId: string): Promise; delete(sessionId: string): Promise; list(): Promise; } export interface SessionData { id: string; messages: Message[]; createdAt: number; updatedAt: number; provider?: ProviderType; model?: string; /** Arbitrary metadata for backends or consumers (e.g., TTL, apiKeyHash). */ metadata?: Record; } export interface SkillMetadata { name: string; description: string; tags: string[]; } export { ZoeError, ProviderError, ToolError, MaxStepsError, AbortedError } from "./errors.js";