Files
claudia/src/lib/api.ts
2025-08-10 01:46:10 +08:00

2409 lines
66 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { invoke } from "@tauri-apps/api/core";
import type { HooksConfiguration } from '@/types/hooks';
/** Process type for tracking in ProcessRegistry */
export type ProcessType =
| { AgentRun: { agent_id: number; agent_name: string } }
| { ClaudeSession: { session_id: string } };
/** Information about a running process */
export interface ProcessInfo {
run_id: number;
process_type: ProcessType;
pid: number;
started_at: string;
project_path: string;
task: string;
model: string;
}
/**
* Represents a project in the ~/.claude/projects directory
*/
export interface Project {
/** The project ID (derived from the directory name) */
id: string;
/** The original project path (decoded from the directory name) */
path: string;
/** List of session IDs (JSONL file names without extension) */
sessions: string[];
/** Unix timestamp when the project directory was created */
created_at: number;
}
/**
* Represents a session with its metadata
*/
export interface Session {
/** The session ID (UUID) */
id: string;
/** The project ID this session belongs to */
project_id: string;
/** The project path */
project_path: string;
/** Optional todo data associated with this session */
todo_data?: any;
/** Unix timestamp when the session file was created */
created_at: number;
/** First user message content (if available) */
first_message?: string;
/** Timestamp of the first user message (if available) */
message_timestamp?: string;
}
/**
* Represents the settings from ~/.claude/settings.json
*/
export interface ClaudeSettings {
[key: string]: any;
}
/**
* Represents the Claude Code version status
*/
export interface ClaudeVersionStatus {
/** Whether Claude Code is installed and working */
is_installed: boolean;
/** The version string if available */
version?: string;
/** The full output from the command */
output: string;
}
/**
* Represents a CLAUDE.md file found in the project
*/
export interface ClaudeMdFile {
/** Relative path from the project root */
relative_path: string;
/** Absolute path to the file */
absolute_path: string;
/** File size in bytes */
size: number;
/** Last modified timestamp */
modified: number;
}
/**
* Represents a file or directory entry
*/
export interface FileEntry {
name: string;
path: string;
is_directory: boolean;
size: number;
extension?: string;
}
/**
* Represents a Claude installation found on the system
*/
export interface ClaudeInstallation {
/** Full path to the Claude binary */
path: string;
/** Version string if available */
version?: string;
/** Source of discovery (e.g., "nvm", "system", "homebrew", "which") */
source: string;
/** Type of installation */
installation_type: "System" | "Custom";
}
// Agent API types
export interface Agent {
id?: number;
name: string;
icon: string;
system_prompt: string;
default_task?: string;
model: string;
hooks?: string; // JSON string of HooksConfiguration
created_at: string;
updated_at: string;
}
export interface AgentExport {
version: number;
exported_at: string;
agent: {
name: string;
icon: string;
system_prompt: string;
default_task?: string;
model: string;
hooks?: string;
};
}
export interface GitHubAgentFile {
name: string;
path: string;
download_url: string;
size: number;
sha: string;
}
export interface AgentRun {
id?: number;
agent_id: number;
agent_name: string;
agent_icon: string;
task: string;
model: string;
project_path: string;
session_id: string;
status: string; // 'pending', 'running', 'completed', 'failed', 'cancelled'
pid?: number;
process_started_at?: string;
created_at: string;
completed_at?: string;
}
export interface AgentRunMetrics {
duration_ms?: number;
total_tokens?: number;
cost_usd?: number;
message_count?: number;
}
export interface AgentRunWithMetrics {
id?: number;
agent_id: number;
agent_name: string;
agent_icon: string;
task: string;
model: string;
project_path: string;
session_id: string;
status: string; // 'pending', 'running', 'completed', 'failed', 'cancelled'
pid?: number;
process_started_at?: string;
created_at: string;
completed_at?: string;
metrics?: AgentRunMetrics;
output?: string; // Real-time JSONL content
}
// Usage Dashboard types
export interface UsageEntry {
project: string;
timestamp: string;
model: string;
input_tokens: number;
output_tokens: number;
cache_write_tokens: number;
cache_read_tokens: number;
cost: number;
}
export interface ModelUsage {
model: string;
total_cost: number;
total_tokens: number;
input_tokens: number;
output_tokens: number;
cache_creation_tokens: number;
cache_read_tokens: number;
session_count: number;
}
export interface DailyUsage {
date: string;
total_cost: number;
total_tokens: number;
// Detailed per-day breakdowns (backend added)
input_tokens: number;
output_tokens: number;
cache_creation_tokens: number;
cache_read_tokens: number;
request_count: number;
models_used: string[];
}
export interface ProjectUsage {
project_path: string;
project_name: string;
total_cost: number;
total_tokens: number;
session_count: number;
last_used: string;
}
export interface UsageStats {
total_cost: number;
total_tokens: number;
total_input_tokens: number;
total_output_tokens: number;
total_cache_creation_tokens: number;
total_cache_read_tokens: number;
total_sessions: number;
by_model: ModelUsage[];
by_date: DailyUsage[];
by_project: ProjectUsage[];
}
/**
* Represents a checkpoint in the session timeline
*/
export interface Checkpoint {
id: string;
sessionId: string;
projectId: string;
messageIndex: number;
timestamp: string;
description?: string;
parentCheckpointId?: string;
metadata: CheckpointMetadata;
}
/**
* Metadata associated with a checkpoint
*/
export interface CheckpointMetadata {
totalTokens: number;
modelUsed: string;
userPrompt: string;
fileChanges: number;
snapshotSize: number;
}
/**
* Represents a file snapshot at a checkpoint
*/
export interface FileSnapshot {
checkpointId: string;
filePath: string;
content: string;
hash: string;
isDeleted: boolean;
permissions?: number;
size: number;
}
/**
* Represents a node in the timeline tree
*/
export interface TimelineNode {
checkpoint: Checkpoint;
children: TimelineNode[];
fileSnapshotIds: string[];
}
/**
* The complete timeline for a session
*/
export interface SessionTimeline {
sessionId: string;
rootNode?: TimelineNode;
currentCheckpointId?: string;
autoCheckpointEnabled: boolean;
checkpointStrategy: CheckpointStrategy;
totalCheckpoints: number;
}
/**
* Strategy for automatic checkpoint creation
*/
export type CheckpointStrategy = 'manual' | 'per_prompt' | 'per_tool_use' | 'smart';
/**
* Result of a checkpoint operation
*/
export interface CheckpointResult {
checkpoint: Checkpoint;
filesProcessed: number;
warnings: string[];
}
/**
* Diff between two checkpoints
*/
export interface CheckpointDiff {
fromCheckpointId: string;
toCheckpointId: string;
modifiedFiles: FileDiff[];
addedFiles: string[];
deletedFiles: string[];
tokenDelta: number;
}
/**
* Diff for a single file
*/
export interface FileDiff {
path: string;
additions: number;
deletions: number;
diffContent?: string;
}
/**
* Represents an MCP server configuration
*/
export interface MCPServer {
/** Server name/identifier */
name: string;
/** Transport type: "stdio" or "sse" */
transport: string;
/** Command to execute (for stdio) */
command?: string;
/** Command arguments (for stdio) */
args: string[];
/** Environment variables */
env: Record<string, string>;
/** URL endpoint (for SSE) */
url?: string;
/** Configuration scope: "local", "project", or "user" */
scope: string;
/** Whether the server is currently active */
is_active: boolean;
/** Server status */
status: ServerStatus;
}
/**
* Server status information
*/
export interface ServerStatus {
/** Whether the server is running */
running: boolean;
/** Last error message if any */
error?: string;
/** Last checked timestamp */
last_checked?: number;
}
/**
* MCP configuration for project scope (.mcp.json)
*/
export interface MCPProjectConfig {
mcpServers: Record<string, MCPServerConfig>;
}
/**
* Individual server configuration in .mcp.json
*/
export interface MCPServerConfig {
command: string;
args: string[];
env: Record<string, string>;
}
/**
* Represents a custom slash command
*/
export interface SlashCommand {
/** Unique identifier for the command */
id: string;
/** Command name (without prefix) */
name: string;
/** Full command with prefix (e.g., "/project:optimize") */
full_command: string;
/** Command scope: "project" or "user" */
scope: string;
/** Optional namespace (e.g., "frontend" in "/project:frontend:component") */
namespace?: string;
/** Path to the markdown file */
file_path: string;
/** Command content (markdown body) */
content: string;
/** Optional description from frontmatter */
description?: string;
/** Allowed tools from frontmatter */
allowed_tools: string[];
/** Whether the command has bash commands (!) */
has_bash_commands: boolean;
/** Whether the command has file references (@) */
has_file_references: boolean;
/** Whether the command uses $ARGUMENTS placeholder */
accepts_arguments: boolean;
}
/**
* Result of adding a server
*/
export interface AddServerResult {
success: boolean;
message: string;
server_name?: string;
}
/**
* Import result for multiple servers
*/
export interface ImportResult {
imported_count: number;
failed_count: number;
servers: ImportServerResult[];
}
/**
* Result for individual server import
*/
export interface ImportServerResult {
name: string;
success: boolean;
error?: string;
}
// ================================
// Relay Station Types
// ================================
/** 中转站适配器类型 */
export type RelayStationAdapter =
| 'packycode' // PackyCode 平台(默认)
| 'newapi' // NewAPI 兼容平台
| 'oneapi' // OneAPI 兼容平台
| 'yourapi' // YourAPI 特定平台
| 'custom'; // 自定义简单配置
/** 认证方式 */
export type AuthMethod =
| 'bearer_token' // Bearer Token 认证(推荐)
| 'api_key' // API Key 认证
| 'custom'; // 自定义认证方式
/** 中转站配置 */
export interface RelayStation {
id: string; // 唯一标识符
name: string; // 显示名称
description?: string; // 描述信息
api_url: string; // API 基础 URL
adapter: RelayStationAdapter; // 适配器类型
auth_method: AuthMethod; // 认证方式
system_token: string; // 系统令牌
user_id?: string; // 用户 IDNewAPI 必需)
adapter_config?: Record<string, any>; // 适配器特定配置
enabled: boolean; // 启用状态
created_at: number; // 创建时间
updated_at: number; // 更新时间
}
/** 创建中转站请求 */
export interface CreateRelayStationRequest {
name: string;
description?: string;
api_url: string;
adapter: RelayStationAdapter;
auth_method: AuthMethod;
system_token: string;
user_id?: string;
adapter_config?: Record<string, any>;
enabled: boolean;
}
/** 更新中转站请求 */
export interface UpdateRelayStationRequest {
id: string;
name: string;
description?: string;
api_url: string;
adapter: RelayStationAdapter;
auth_method: AuthMethod;
system_token: string;
user_id?: string;
adapter_config?: Record<string, any>;
enabled: boolean;
}
/** 站点信息 */
export interface StationInfo {
name: string; // 站点名称
announcement?: string; // 公告信息
api_url: string; // API 地址
version?: string; // 版本信息
metadata?: Record<string, any>; // 扩展元数据
quota_per_unit?: number; // 单位配额(用于价格转换)
}
/** 用户信息 */
export interface UserInfo {
user_id: string; // 用户 ID
username?: string; // 用户名
email?: string; // 邮箱
balance_remaining?: number; // 剩余余额(美元)
amount_used?: number; // 已用金额(美元)
request_count?: number; // 请求次数
status?: string; // 账户状态
metadata?: Record<string, any>; // 原始数据
}
/** 连接测试结果 */
export interface ConnectionTestResult {
success: boolean; // 连接是否成功
response_time?: number; // 响应时间(毫秒)
message: string; // 结果消息
error?: string; // 错误信息
}
/** Token 信息 */
export interface TokenInfo {
id: string;
name: string;
token: string;
quota?: number;
used_quota?: number;
status: string;
created_at: number;
updated_at: number;
}
/** Token 分页响应 */
export interface TokenPaginationResponse {
tokens: TokenInfo[];
total: number;
page: number;
size: number;
}
// ============= PackyCode Nodes =============
/** PackyCode 节点类型 */
export type NodeType =
| 'direct' // 直连节点
| 'backup' // 备用节点
| 'emergency'; // 紧急节点
/** PackyCode 节点信息 */
export interface PackycodeNode {
name: string; // 节点名称
url: string; // 节点 URL
node_type: NodeType; // 节点类型
description: string; // 节点描述
response_time?: number; // 响应时间(毫秒)
available?: boolean; // 是否可用
}
/** 节点测速结果 */
export interface NodeSpeedTestResult {
node: PackycodeNode; // 节点信息
response_time: number; // 响应时间
success: boolean; // 是否成功
error?: string; // 错误信息
}
/** PackyCode 用户额度信息 */
export interface PackycodeUserQuota {
daily_budget_usd: number; // 日预算(美元)
daily_spent_usd: number; // 日已使用(美元)
monthly_budget_usd: number; // 月预算(美元)
monthly_spent_usd: number; // 月已使用(美元)
balance_usd: number; // 账户余额(美元)
total_spent_usd: number; // 总消费(美元)
plan_type: string; // 计划类型 (pro, basic, etc.)
plan_expires_at: string; // 计划过期时间
username?: string; // 用户名
email?: string; // 邮箱
}
/**
* API client for interacting with the Rust backend
*/
export const api = {
/**
* Lists all projects in the ~/.claude/projects directory
* @returns Promise resolving to an array of projects
*/
async listProjects(): Promise<Project[]> {
try {
return await invoke<Project[]>("list_projects");
} catch (error) {
console.error("Failed to list projects:", error);
throw error;
}
},
/**
* Retrieves sessions for a specific project
* @param projectId - The ID of the project to retrieve sessions for
* @returns Promise resolving to an array of sessions
*/
async getProjectSessions(projectId: string): Promise<Session[]> {
try {
return await invoke<Session[]>('get_project_sessions', { projectId });
} catch (error) {
console.error("Failed to get project sessions:", error);
throw error;
}
},
/**
* Fetch list of agents from GitHub repository
* @returns Promise resolving to list of available agents on GitHub
*/
async fetchGitHubAgents(): Promise<GitHubAgentFile[]> {
try {
return await invoke<GitHubAgentFile[]>('fetch_github_agents');
} catch (error) {
console.error("Failed to fetch GitHub agents:", error);
throw error;
}
},
/**
* Fetch and preview a specific agent from GitHub
* @param downloadUrl - The download URL for the agent file
* @returns Promise resolving to the agent export data
*/
async fetchGitHubAgentContent(downloadUrl: string): Promise<AgentExport> {
try {
return await invoke<AgentExport>('fetch_github_agent_content', { downloadUrl });
} catch (error) {
console.error("Failed to fetch GitHub agent content:", error);
throw error;
}
},
/**
* Import an agent directly from GitHub
* @param downloadUrl - The download URL for the agent file
* @returns Promise resolving to the imported agent
*/
async importAgentFromGitHub(downloadUrl: string): Promise<Agent> {
try {
return await invoke<Agent>('import_agent_from_github', { downloadUrl });
} catch (error) {
console.error("Failed to import agent from GitHub:", error);
throw error;
}
},
/**
* Reads the Claude settings file
* @returns Promise resolving to the settings object
*/
async getClaudeSettings(): Promise<ClaudeSettings> {
try {
const result = await invoke<{ data: ClaudeSettings }>("get_claude_settings");
console.log("Raw result from get_claude_settings:", result);
// The Rust backend returns ClaudeSettings { data: ... }
// We need to extract the data field
if (result && typeof result === 'object' && 'data' in result) {
return result.data;
}
// If the result is already the settings object, return it
return result as ClaudeSettings;
} catch (error) {
console.error("Failed to get Claude settings:", error);
throw error;
}
},
/**
* Opens a new Claude Code session
* @param path - Optional path to open the session in
* @returns Promise resolving when the session is opened
*/
async openNewSession(path?: string): Promise<string> {
try {
return await invoke<string>("open_new_session", { path });
} catch (error) {
console.error("Failed to open new session:", error);
throw error;
}
},
/**
* Reads the CLAUDE.md system prompt file
* @returns Promise resolving to the system prompt content
*/
async getSystemPrompt(): Promise<string> {
try {
return await invoke<string>("get_system_prompt");
} catch (error) {
console.error("Failed to get system prompt:", error);
throw error;
}
},
/**
* Checks if Claude Code is installed and gets its version
* @returns Promise resolving to the version status
*/
async checkClaudeVersion(): Promise<ClaudeVersionStatus> {
try {
return await invoke<ClaudeVersionStatus>("check_claude_version");
} catch (error) {
console.error("Failed to check Claude version:", error);
throw error;
}
},
/**
* Saves the CLAUDE.md system prompt file
* @param content - The new content for the system prompt
* @returns Promise resolving when the file is saved
*/
async saveSystemPrompt(content: string): Promise<string> {
try {
return await invoke<string>("save_system_prompt", { content });
} catch (error) {
console.error("Failed to save system prompt:", error);
throw error;
}
},
/**
* Saves the Claude settings file
* @param settings - The settings object to save
* @returns Promise resolving when the settings are saved
*/
async saveClaudeSettings(settings: ClaudeSettings): Promise<string> {
try {
return await invoke<string>("save_claude_settings", { settings });
} catch (error) {
console.error("Failed to save Claude settings:", error);
throw error;
}
},
/**
* Finds all CLAUDE.md files in a project directory
* @param projectPath - The absolute path to the project
* @returns Promise resolving to an array of CLAUDE.md files
*/
async findClaudeMdFiles(projectPath: string): Promise<ClaudeMdFile[]> {
try {
return await invoke<ClaudeMdFile[]>("find_claude_md_files", { projectPath });
} catch (error) {
console.error("Failed to find CLAUDE.md files:", error);
throw error;
}
},
/**
* Reads a specific CLAUDE.md file
* @param filePath - The absolute path to the file
* @returns Promise resolving to the file content
*/
async readClaudeMdFile(filePath: string): Promise<string> {
try {
return await invoke<string>("read_claude_md_file", { filePath });
} catch (error) {
console.error("Failed to read CLAUDE.md file:", error);
throw error;
}
},
/**
* Saves a specific CLAUDE.md file
* @param filePath - The absolute path to the file
* @param content - The new content for the file
* @returns Promise resolving when the file is saved
*/
async saveClaudeMdFile(filePath: string, content: string): Promise<string> {
try {
return await invoke<string>("save_claude_md_file", { filePath, content });
} catch (error) {
console.error("Failed to save CLAUDE.md file:", error);
throw error;
}
},
// Agent API methods
/**
* Lists all CC agents
* @returns Promise resolving to an array of agents
*/
async listAgents(): Promise<Agent[]> {
try {
return await invoke<Agent[]>('list_agents');
} catch (error) {
console.error("Failed to list agents:", error);
throw error;
}
},
/**
* Creates a new agent
* @param name - The agent name
* @param icon - The icon identifier
* @param system_prompt - The system prompt for the agent
* @param default_task - Optional default task
* @param model - Optional model (defaults to 'sonnet')
* @param hooks - Optional hooks configuration as JSON string
* @returns Promise resolving to the created agent
*/
async createAgent(
name: string,
icon: string,
system_prompt: string,
default_task?: string,
model?: string,
hooks?: string
): Promise<Agent> {
try {
return await invoke<Agent>('create_agent', {
name,
icon,
systemPrompt: system_prompt,
defaultTask: default_task,
model,
hooks
});
} catch (error) {
console.error("Failed to create agent:", error);
throw error;
}
},
/**
* Updates an existing agent
* @param id - The agent ID
* @param name - The updated name
* @param icon - The updated icon
* @param system_prompt - The updated system prompt
* @param default_task - Optional default task
* @param model - Optional model
* @param hooks - Optional hooks configuration as JSON string
* @returns Promise resolving to the updated agent
*/
async updateAgent(
id: number,
name: string,
icon: string,
system_prompt: string,
default_task?: string,
model?: string,
hooks?: string
): Promise<Agent> {
try {
return await invoke<Agent>('update_agent', {
id,
name,
icon,
systemPrompt: system_prompt,
defaultTask: default_task,
model,
hooks
});
} catch (error) {
console.error("Failed to update agent:", error);
throw error;
}
},
/**
* Deletes an agent
* @param id - The agent ID to delete
* @returns Promise resolving when the agent is deleted
*/
async deleteAgent(id: number): Promise<void> {
try {
return await invoke('delete_agent', { id });
} catch (error) {
console.error("Failed to delete agent:", error);
throw error;
}
},
/**
* Gets a single agent by ID
* @param id - The agent ID
* @returns Promise resolving to the agent
*/
async getAgent(id: number): Promise<Agent> {
try {
return await invoke<Agent>('get_agent', { id });
} catch (error) {
console.error("Failed to get agent:", error);
throw error;
}
},
/**
* Exports a single agent to JSON format
* @param id - The agent ID to export
* @returns Promise resolving to the JSON string
*/
async exportAgent(id: number): Promise<string> {
try {
return await invoke<string>('export_agent', { id });
} catch (error) {
console.error("Failed to export agent:", error);
throw error;
}
},
/**
* Imports an agent from JSON data
* @param jsonData - The JSON string containing the agent export
* @returns Promise resolving to the imported agent
*/
async importAgent(jsonData: string): Promise<Agent> {
try {
return await invoke<Agent>('import_agent', { jsonData });
} catch (error) {
console.error("Failed to import agent:", error);
throw error;
}
},
/**
* Imports an agent from a file
* @param filePath - The path to the JSON file
* @returns Promise resolving to the imported agent
*/
async importAgentFromFile(filePath: string): Promise<Agent> {
try {
return await invoke<Agent>('import_agent_from_file', { filePath });
} catch (error) {
console.error("Failed to import agent from file:", error);
throw error;
}
},
/**
* Executes an agent
* @param agentId - The agent ID to execute
* @param projectPath - The project path to run the agent in
* @param task - The task description
* @param model - Optional model override
* @returns Promise resolving to the run ID when execution starts
*/
async executeAgent(agentId: number, projectPath: string, task: string, model?: string): Promise<number> {
try {
return await invoke<number>('execute_agent', { agentId, projectPath, task, model });
} catch (error) {
console.error("Failed to execute agent:", error);
// Return a sentinel value to indicate error
throw new Error(`Failed to execute agent: ${error instanceof Error ? error.message : 'Unknown error'}`);
}
},
/**
* Lists agent runs with metrics
* @param agentId - Optional agent ID to filter runs
* @returns Promise resolving to an array of agent runs with metrics
*/
async listAgentRuns(agentId?: number): Promise<AgentRunWithMetrics[]> {
try {
return await invoke<AgentRunWithMetrics[]>('list_agent_runs', { agentId });
} catch (error) {
console.error("Failed to list agent runs:", error);
// Return empty array instead of throwing to prevent UI crashes
return [];
}
},
/**
* Gets a single agent run by ID with metrics
* @param id - The run ID
* @returns Promise resolving to the agent run with metrics
*/
async getAgentRun(id: number): Promise<AgentRunWithMetrics> {
try {
return await invoke<AgentRunWithMetrics>('get_agent_run', { id });
} catch (error) {
console.error("Failed to get agent run:", error);
throw new Error(`Failed to get agent run: ${error instanceof Error ? error.message : 'Unknown error'}`);
}
},
/**
* Gets a single agent run by ID with real-time metrics from JSONL
* @param id - The run ID
* @returns Promise resolving to the agent run with metrics
*/
async getAgentRunWithRealTimeMetrics(id: number): Promise<AgentRunWithMetrics> {
try {
return await invoke<AgentRunWithMetrics>('get_agent_run_with_real_time_metrics', { id });
} catch (error) {
console.error("Failed to get agent run with real-time metrics:", error);
throw new Error(`Failed to get agent run with real-time metrics: ${error instanceof Error ? error.message : 'Unknown error'}`);
}
},
/**
* Lists all currently running agent sessions
* @returns Promise resolving to list of running agent sessions
*/
async listRunningAgentSessions(): Promise<AgentRun[]> {
try {
return await invoke<AgentRun[]>('list_running_sessions');
} catch (error) {
console.error("Failed to list running agent sessions:", error);
throw new Error(`Failed to list running agent sessions: ${error instanceof Error ? error.message : 'Unknown error'}`);
}
},
/**
* Kills a running agent session
* @param runId - The run ID to kill
* @returns Promise resolving to whether the session was successfully killed
*/
async killAgentSession(runId: number): Promise<boolean> {
try {
return await invoke<boolean>('kill_agent_session', { runId });
} catch (error) {
console.error("Failed to kill agent session:", error);
throw new Error(`Failed to kill agent session: ${error instanceof Error ? error.message : 'Unknown error'}`);
}
},
/**
* Gets the status of a specific agent session
* @param runId - The run ID to check
* @returns Promise resolving to the session status or null if not found
*/
async getSessionStatus(runId: number): Promise<string | null> {
try {
return await invoke<string | null>('get_session_status', { runId });
} catch (error) {
console.error("Failed to get session status:", error);
throw new Error(`Failed to get session status: ${error instanceof Error ? error.message : 'Unknown error'}`);
}
},
/**
* Cleanup finished processes and update their status
* @returns Promise resolving to list of run IDs that were cleaned up
*/
async cleanupFinishedProcesses(): Promise<number[]> {
try {
return await invoke<number[]>('cleanup_finished_processes');
} catch (error) {
console.error("Failed to cleanup finished processes:", error);
throw new Error(`Failed to cleanup finished processes: ${error instanceof Error ? error.message : 'Unknown error'}`);
}
},
/**
* Get real-time output for a running session (with live output fallback)
* @param runId - The run ID to get output for
* @returns Promise resolving to the current session output (JSONL format)
*/
async getSessionOutput(runId: number): Promise<string> {
try {
return await invoke<string>('get_session_output', { runId });
} catch (error) {
console.error("Failed to get session output:", error);
throw new Error(`Failed to get session output: ${error instanceof Error ? error.message : 'Unknown error'}`);
}
},
/**
* Get live output directly from process stdout buffer
* @param runId - The run ID to get live output for
* @returns Promise resolving to the current live output
*/
async getLiveSessionOutput(runId: number): Promise<string> {
try {
return await invoke<string>('get_live_session_output', { runId });
} catch (error) {
console.error("Failed to get live session output:", error);
throw new Error(`Failed to get live session output: ${error instanceof Error ? error.message : 'Unknown error'}`);
}
},
/**
* Start streaming real-time output for a running session
* @param runId - The run ID to stream output for
* @returns Promise that resolves when streaming starts
*/
async streamSessionOutput(runId: number): Promise<void> {
try {
return await invoke<void>('stream_session_output', { runId });
} catch (error) {
console.error("Failed to start streaming session output:", error);
throw new Error(`Failed to start streaming session output: ${error instanceof Error ? error.message : 'Unknown error'}`);
}
},
/**
* Loads the JSONL history for a specific session
*/
async loadSessionHistory(sessionId: string, projectId: string): Promise<any[]> {
return invoke("load_session_history", { sessionId, projectId });
},
/**
* Loads the JSONL history for a specific agent session
* Similar to loadSessionHistory but searches across all project directories
* @param sessionId - The session ID (UUID)
* @returns Promise resolving to array of session messages
*/
async loadAgentSessionHistory(sessionId: string): Promise<any[]> {
try {
return await invoke<any[]>('load_agent_session_history', { sessionId });
} catch (error) {
console.error("Failed to load agent session history:", error);
throw error;
}
},
/**
* Executes a new interactive Claude Code session with streaming output
*/
async executeClaudeCode(projectPath: string, prompt: string, model: string): Promise<void> {
return invoke("execute_claude_code", { projectPath, prompt, model });
},
/**
* Continues an existing Claude Code conversation with streaming output
*/
async continueClaudeCode(projectPath: string, prompt: string, model: string): Promise<void> {
return invoke("continue_claude_code", { projectPath, prompt, model });
},
/**
* Resumes an existing Claude Code session by ID with streaming output
*/
async resumeClaudeCode(projectPath: string, sessionId: string, prompt: string, model: string): Promise<void> {
return invoke("resume_claude_code", { projectPath, sessionId, prompt, model });
},
/**
* Cancels the currently running Claude Code execution
* @param sessionId - Optional session ID to cancel a specific session
*/
async cancelClaudeExecution(sessionId?: string): Promise<void> {
return invoke("cancel_claude_execution", { sessionId });
},
/**
* Lists all currently running Claude sessions
* @returns Promise resolving to list of running Claude sessions
*/
async listRunningClaudeSessions(): Promise<any[]> {
return invoke("list_running_claude_sessions");
},
/**
* Gets live output from a Claude session
* @param sessionId - The session ID to get output for
* @returns Promise resolving to the current live output
*/
async getClaudeSessionOutput(sessionId: string): Promise<string> {
return invoke("get_claude_session_output", { sessionId });
},
/**
* Lists files and directories in a given path
*/
async listDirectoryContents(directoryPath: string): Promise<FileEntry[]> {
return invoke("list_directory_contents", { directoryPath });
},
/**
* Searches for files and directories matching a pattern
*/
async searchFiles(basePath: string, query: string): Promise<FileEntry[]> {
return invoke("search_files", { basePath, query });
},
/**
* Gets overall usage statistics
* @returns Promise resolving to usage statistics
*/
async getUsageStats(): Promise<UsageStats> {
try {
return await invoke<UsageStats>("get_usage_stats");
} catch (error) {
console.error("Failed to get usage stats:", error);
throw error;
}
},
/**
* Gets usage statistics filtered by date range
* @param startDate - Start date (ISO format)
* @param endDate - End date (ISO format)
* @returns Promise resolving to usage statistics
*/
async getUsageByDateRange(startDate: string, endDate: string): Promise<UsageStats> {
try {
return await invoke<UsageStats>("get_usage_by_date_range", { startDate, endDate });
} catch (error) {
console.error("Failed to get usage by date range:", error);
throw error;
}
},
/**
* Gets usage statistics grouped by session
* @param since - Optional start date (YYYYMMDD)
* @param until - Optional end date (YYYYMMDD)
* @param order - Optional sort order ('asc' or 'desc')
* @returns Promise resolving to an array of session usage data
*/
async getSessionStats(
since?: string,
until?: string,
order?: "asc" | "desc"
): Promise<ProjectUsage[]> {
try {
return await invoke<ProjectUsage[]>("get_session_stats", {
since,
until,
order,
});
} catch (error) {
console.error("Failed to get session stats:", error);
throw error;
}
},
/**
* Gets detailed usage entries with optional filtering
* @param limit - Optional limit for number of entries
* @returns Promise resolving to array of usage entries
*/
async getUsageDetails(limit?: number): Promise<UsageEntry[]> {
try {
return await invoke<UsageEntry[]>("get_usage_details", { limit });
} catch (error) {
console.error("Failed to get usage details:", error);
throw error;
}
},
/**
* Creates a checkpoint for the current session state
*/
async createCheckpoint(
sessionId: string,
projectId: string,
projectPath: string,
messageIndex?: number,
description?: string
): Promise<CheckpointResult> {
return invoke("create_checkpoint", {
sessionId,
projectId,
projectPath,
messageIndex,
description
});
},
/**
* Restores a session to a specific checkpoint
*/
async restoreCheckpoint(
checkpointId: string,
sessionId: string,
projectId: string,
projectPath: string
): Promise<CheckpointResult> {
return invoke("restore_checkpoint", {
checkpointId,
sessionId,
projectId,
projectPath
});
},
/**
* Lists all checkpoints for a session
*/
async listCheckpoints(
sessionId: string,
projectId: string,
projectPath: string
): Promise<Checkpoint[]> {
return invoke("list_checkpoints", {
sessionId,
projectId,
projectPath
});
},
/**
* Forks a new timeline branch from a checkpoint
*/
async forkFromCheckpoint(
checkpointId: string,
sessionId: string,
projectId: string,
projectPath: string,
newSessionId: string,
description?: string
): Promise<CheckpointResult> {
return invoke("fork_from_checkpoint", {
checkpointId,
sessionId,
projectId,
projectPath,
newSessionId,
description
});
},
/**
* Gets the timeline for a session
*/
async getSessionTimeline(
sessionId: string,
projectId: string,
projectPath: string
): Promise<SessionTimeline> {
return invoke("get_session_timeline", {
sessionId,
projectId,
projectPath
});
},
/**
* Updates checkpoint settings for a session
*/
async updateCheckpointSettings(
sessionId: string,
projectId: string,
projectPath: string,
autoCheckpointEnabled: boolean,
checkpointStrategy: CheckpointStrategy
): Promise<void> {
return invoke("update_checkpoint_settings", {
sessionId,
projectId,
projectPath,
autoCheckpointEnabled,
checkpointStrategy
});
},
/**
* Gets diff between two checkpoints
*/
async getCheckpointDiff(
fromCheckpointId: string,
toCheckpointId: string,
sessionId: string,
projectId: string
): Promise<CheckpointDiff> {
try {
return await invoke<CheckpointDiff>("get_checkpoint_diff", {
fromCheckpointId,
toCheckpointId,
sessionId,
projectId
});
} catch (error) {
console.error("Failed to get checkpoint diff:", error);
throw error;
}
},
/**
* Tracks a message for checkpointing
*/
async trackCheckpointMessage(
sessionId: string,
projectId: string,
projectPath: string,
message: string
): Promise<void> {
try {
await invoke("track_checkpoint_message", {
sessionId,
projectId,
projectPath,
message
});
} catch (error) {
console.error("Failed to track checkpoint message:", error);
throw error;
}
},
/**
* Checks if auto-checkpoint should be triggered
*/
async checkAutoCheckpoint(
sessionId: string,
projectId: string,
projectPath: string,
message: string
): Promise<boolean> {
try {
return await invoke<boolean>("check_auto_checkpoint", {
sessionId,
projectId,
projectPath,
message
});
} catch (error) {
console.error("Failed to check auto checkpoint:", error);
throw error;
}
},
/**
* Triggers cleanup of old checkpoints
*/
async cleanupOldCheckpoints(
sessionId: string,
projectId: string,
projectPath: string,
keepCount: number
): Promise<number> {
try {
return await invoke<number>("cleanup_old_checkpoints", {
sessionId,
projectId,
projectPath,
keepCount
});
} catch (error) {
console.error("Failed to cleanup old checkpoints:", error);
throw error;
}
},
/**
* Gets checkpoint settings for a session
*/
async getCheckpointSettings(
sessionId: string,
projectId: string,
projectPath: string
): Promise<{
auto_checkpoint_enabled: boolean;
checkpoint_strategy: CheckpointStrategy;
total_checkpoints: number;
current_checkpoint_id?: string;
}> {
try {
return await invoke("get_checkpoint_settings", {
sessionId,
projectId,
projectPath
});
} catch (error) {
console.error("Failed to get checkpoint settings:", error);
throw error;
}
},
/**
* Clears checkpoint manager for a session (cleanup on session end)
*/
async clearCheckpointManager(sessionId: string): Promise<void> {
try {
await invoke("clear_checkpoint_manager", { sessionId });
} catch (error) {
console.error("Failed to clear checkpoint manager:", error);
throw error;
}
},
/**
* Tracks a batch of messages for a session for checkpointing
*/
trackSessionMessages: (
sessionId: string,
projectId: string,
projectPath: string,
messages: string[]
): Promise<void> =>
invoke("track_session_messages", { sessionId, projectId, projectPath, messages }),
/**
* Adds a new MCP server
*/
async mcpAdd(
name: string,
transport: string,
command?: string,
args: string[] = [],
env: Record<string, string> = {},
url?: string,
scope: string = "local"
): Promise<AddServerResult> {
try {
return await invoke<AddServerResult>("mcp_add", {
name,
transport,
command,
args,
env,
url,
scope
});
} catch (error) {
console.error("Failed to add MCP server:", error);
throw error;
}
},
/**
* Lists all configured MCP servers
*/
async mcpList(): Promise<MCPServer[]> {
try {
console.log("API: Calling mcp_list...");
const result = await invoke<MCPServer[]>("mcp_list");
console.log("API: mcp_list returned:", result);
return result;
} catch (error) {
console.error("API: Failed to list MCP servers:", error);
throw error;
}
},
/**
* Gets details for a specific MCP server
*/
async mcpGet(name: string): Promise<MCPServer> {
try {
return await invoke<MCPServer>("mcp_get", { name });
} catch (error) {
console.error("Failed to get MCP server:", error);
throw error;
}
},
/**
* Removes an MCP server
*/
async mcpRemove(name: string): Promise<string> {
try {
return await invoke<string>("mcp_remove", { name });
} catch (error) {
console.error("Failed to remove MCP server:", error);
throw error;
}
},
/**
* Adds an MCP server from JSON configuration
*/
async mcpAddJson(name: string, jsonConfig: string, scope: string = "local"): Promise<AddServerResult> {
try {
return await invoke<AddServerResult>("mcp_add_json", { name, jsonConfig, scope });
} catch (error) {
console.error("Failed to add MCP server from JSON:", error);
throw error;
}
},
/**
* Imports MCP servers from Claude Desktop
*/
async mcpAddFromClaudeDesktop(scope: string = "local"): Promise<ImportResult> {
try {
return await invoke<ImportResult>("mcp_add_from_claude_desktop", { scope });
} catch (error) {
console.error("Failed to import from Claude Desktop:", error);
throw error;
}
},
/**
* Starts Claude Code as an MCP server
*/
async mcpServe(): Promise<string> {
try {
return await invoke<string>("mcp_serve");
} catch (error) {
console.error("Failed to start MCP server:", error);
throw error;
}
},
/**
* Tests connection to an MCP server
*/
async mcpTestConnection(name: string): Promise<string> {
try {
return await invoke<string>("mcp_test_connection", { name });
} catch (error) {
console.error("Failed to test MCP connection:", error);
throw error;
}
},
/**
* Resets project-scoped server approval choices
*/
async mcpResetProjectChoices(): Promise<string> {
try {
return await invoke<string>("mcp_reset_project_choices");
} catch (error) {
console.error("Failed to reset project choices:", error);
throw error;
}
},
/**
* Gets the status of MCP servers
*/
async mcpGetServerStatus(): Promise<Record<string, ServerStatus>> {
try {
return await invoke<Record<string, ServerStatus>>("mcp_get_server_status");
} catch (error) {
console.error("Failed to get server status:", error);
throw error;
}
},
/**
* Reads .mcp.json from the current project
*/
async mcpReadProjectConfig(projectPath: string): Promise<MCPProjectConfig> {
try {
return await invoke<MCPProjectConfig>("mcp_read_project_config", { projectPath });
} catch (error) {
console.error("Failed to read project MCP config:", error);
throw error;
}
},
/**
* Saves .mcp.json to the current project
*/
async mcpSaveProjectConfig(projectPath: string, config: MCPProjectConfig): Promise<string> {
try {
return await invoke<string>("mcp_save_project_config", { projectPath, config });
} catch (error) {
console.error("Failed to save project MCP config:", error);
throw error;
}
},
/**
* Get the stored Claude binary path from settings
* @returns Promise resolving to the path if set, null otherwise
*/
async getClaudeBinaryPath(): Promise<string | null> {
try {
return await invoke<string | null>("get_claude_binary_path");
} catch (error) {
console.error("Failed to get Claude binary path:", error);
throw error;
}
},
/**
* Set the Claude binary path in settings
* @param path - The absolute path to the Claude binary
* @returns Promise resolving when the path is saved
*/
async setClaudeBinaryPath(path: string): Promise<void> {
try {
return await invoke<void>("set_claude_binary_path", { path });
} catch (error) {
console.error("Failed to set Claude binary path:", error);
throw error;
}
},
/**
* List all available Claude installations on the system
* @returns Promise resolving to an array of Claude installations
*/
async listClaudeInstallations(): Promise<ClaudeInstallation[]> {
try {
return await invoke<ClaudeInstallation[]>("list_claude_installations");
} catch (error) {
console.error("Failed to list Claude installations:", error);
throw error;
}
},
// Storage API methods
/**
* Lists all tables in the SQLite database
* @returns Promise resolving to an array of table information
*/
async storageListTables(): Promise<any[]> {
try {
return await invoke<any[]>("storage_list_tables");
} catch (error) {
console.error("Failed to list tables:", error);
throw error;
}
},
/**
* Reads table data with pagination
* @param tableName - Name of the table to read
* @param page - Page number (1-indexed)
* @param pageSize - Number of rows per page
* @param searchQuery - Optional search query
* @returns Promise resolving to table data with pagination info
*/
async storageReadTable(
tableName: string,
page: number,
pageSize: number,
searchQuery?: string
): Promise<any> {
try {
return await invoke<any>("storage_read_table", {
tableName,
page,
pageSize,
searchQuery,
});
} catch (error) {
console.error("Failed to read table:", error);
throw error;
}
},
/**
* Updates a row in a table
* @param tableName - Name of the table
* @param primaryKeyValues - Map of primary key column names to values
* @param updates - Map of column names to new values
* @returns Promise resolving when the row is updated
*/
async storageUpdateRow(
tableName: string,
primaryKeyValues: Record<string, any>,
updates: Record<string, any>
): Promise<void> {
try {
return await invoke<void>("storage_update_row", {
tableName,
primaryKeyValues,
updates,
});
} catch (error) {
console.error("Failed to update row:", error);
throw error;
}
},
/**
* Deletes a row from a table
* @param tableName - Name of the table
* @param primaryKeyValues - Map of primary key column names to values
* @returns Promise resolving when the row is deleted
*/
async storageDeleteRow(
tableName: string,
primaryKeyValues: Record<string, any>
): Promise<void> {
try {
return await invoke<void>("storage_delete_row", {
tableName,
primaryKeyValues,
});
} catch (error) {
console.error("Failed to delete row:", error);
throw error;
}
},
/**
* Inserts a new row into a table
* @param tableName - Name of the table
* @param values - Map of column names to values
* @returns Promise resolving to the last insert row ID
*/
async storageInsertRow(
tableName: string,
values: Record<string, any>
): Promise<number> {
try {
return await invoke<number>("storage_insert_row", {
tableName,
values,
});
} catch (error) {
console.error("Failed to insert row:", error);
throw error;
}
},
/**
* Executes a raw SQL query
* @param query - SQL query string
* @returns Promise resolving to query result
*/
async storageExecuteSql(query: string): Promise<any> {
try {
return await invoke<any>("storage_execute_sql", { query });
} catch (error) {
console.error("Failed to execute SQL:", error);
throw error;
}
},
/**
* Resets the entire database
* @returns Promise resolving when the database is reset
*/
async storageResetDatabase(): Promise<void> {
try {
return await invoke<void>("storage_reset_database");
} catch (error) {
console.error("Failed to reset database:", error);
throw error;
}
},
// Theme settings helpers
/**
* Gets a setting from the app_settings table
* @param key - The setting key to retrieve
* @returns Promise resolving to the setting value or null if not found
*/
async getSetting(key: string): Promise<string | null> {
try {
// Use storageReadTable to safely query the app_settings table
const result = await this.storageReadTable('app_settings', 1, 1000);
const setting = result?.data?.find((row: any) => row.key === key);
return setting?.value || null;
} catch (error) {
console.error(`Failed to get setting ${key}:`, error);
return null;
}
},
/**
* Saves a setting to the app_settings table (insert or update)
* @param key - The setting key
* @param value - The setting value
* @returns Promise resolving when the setting is saved
*/
async saveSetting(key: string, value: string): Promise<void> {
try {
// Try to update first
try {
await this.storageUpdateRow(
'app_settings',
{ key },
{ value }
);
} catch (updateError) {
// If update fails (row doesn't exist), insert new row
await this.storageInsertRow('app_settings', { key, value });
}
} catch (error) {
console.error(`Failed to save setting ${key}:`, error);
throw error;
}
},
/**
* Get hooks configuration for a specific scope
* @param scope - The configuration scope: 'user', 'project', or 'local'
* @param projectPath - Project path (required for project and local scopes)
* @returns Promise resolving to the hooks configuration
*/
async getHooksConfig(scope: 'user' | 'project' | 'local', projectPath?: string): Promise<HooksConfiguration> {
try {
return await invoke<HooksConfiguration>("get_hooks_config", { scope, projectPath });
} catch (error) {
console.error("Failed to get hooks config:", error);
throw error;
}
},
/**
* Update hooks configuration for a specific scope
* @param scope - The configuration scope: 'user', 'project', or 'local'
* @param hooks - The hooks configuration to save
* @param projectPath - Project path (required for project and local scopes)
* @returns Promise resolving to success message
*/
async updateHooksConfig(
scope: 'user' | 'project' | 'local',
hooks: HooksConfiguration,
projectPath?: string
): Promise<string> {
try {
return await invoke<string>("update_hooks_config", { scope, projectPath, hooks });
} catch (error) {
console.error("Failed to update hooks config:", error);
throw error;
}
},
/**
* Validate a hook command syntax
* @param command - The shell command to validate
* @returns Promise resolving to validation result
*/
async validateHookCommand(command: string): Promise<{ valid: boolean; message: string }> {
try {
return await invoke<{ valid: boolean; message: string }>("validate_hook_command", { command });
} catch (error) {
console.error("Failed to validate hook command:", error);
throw error;
}
},
/**
* Get merged hooks configuration (respecting priority)
* @param projectPath - The project path
* @returns Promise resolving to merged hooks configuration
*/
async getMergedHooksConfig(projectPath: string): Promise<HooksConfiguration> {
try {
const [userHooks, projectHooks, localHooks] = await Promise.all([
this.getHooksConfig('user'),
this.getHooksConfig('project', projectPath),
this.getHooksConfig('local', projectPath)
]);
// Import HooksManager for merging
const { HooksManager } = await import('@/lib/hooksManager');
return HooksManager.mergeConfigs(userHooks, projectHooks, localHooks);
} catch (error) {
console.error("Failed to get merged hooks config:", error);
throw error;
}
},
// Slash Commands API methods
/**
* Lists all available slash commands
* @param projectPath - Optional project path to include project-specific commands
* @returns Promise resolving to array of slash commands
*/
async slashCommandsList(projectPath?: string): Promise<SlashCommand[]> {
try {
return await invoke<SlashCommand[]>("slash_commands_list", { projectPath });
} catch (error) {
console.error("Failed to list slash commands:", error);
throw error;
}
},
/**
* Gets a single slash command by ID
* @param commandId - Unique identifier of the command
* @returns Promise resolving to the slash command
*/
async slashCommandGet(commandId: string): Promise<SlashCommand> {
try {
return await invoke<SlashCommand>("slash_command_get", { commandId });
} catch (error) {
console.error("Failed to get slash command:", error);
throw error;
}
},
/**
* Creates or updates a slash command
* @param scope - Command scope: "project" or "user"
* @param name - Command name (without prefix)
* @param namespace - Optional namespace for organization
* @param content - Markdown content of the command
* @param description - Optional description
* @param allowedTools - List of allowed tools for this command
* @param projectPath - Required for project scope commands
* @returns Promise resolving to the saved command
*/
async slashCommandSave(
scope: string,
name: string,
namespace: string | undefined,
content: string,
description: string | undefined,
allowedTools: string[],
projectPath?: string
): Promise<SlashCommand> {
try {
return await invoke<SlashCommand>("slash_command_save", {
scope,
name,
namespace,
content,
description,
allowedTools,
projectPath
});
} catch (error) {
console.error("Failed to save slash command:", error);
throw error;
}
},
/**
* Deletes a slash command
* @param commandId - Unique identifier of the command to delete
* @param projectPath - Optional project path for deleting project commands
* @returns Promise resolving to deletion message
*/
async slashCommandDelete(commandId: string, projectPath?: string): Promise<string> {
try {
return await invoke<string>("slash_command_delete", { commandId, projectPath });
} catch (error) {
console.error("Failed to delete slash command:", error);
throw error;
}
},
// ================================
// Language Settings
// ================================
/**
* Gets the current language setting
* @returns Promise resolving to the current language locale
*/
async getCurrentLanguage(): Promise<string> {
try {
return await invoke<string>("get_current_language");
} catch (error) {
console.error("Failed to get current language:", error);
throw error;
}
},
/**
* Sets the language setting
* @param locale - Language locale to set (e.g., 'en-US', 'zh-CN')
* @returns Promise resolving when language is set
*/
async setLanguage(locale: string): Promise<void> {
try {
await invoke<void>("set_language", { locale });
} catch (error) {
console.error("Failed to set language:", error);
throw error;
}
},
/**
* Gets the list of supported languages
* @returns Promise resolving to array of supported language locales
*/
async getSupportedLanguages(): Promise<string[]> {
try {
return await invoke<string[]>("get_supported_languages");
} catch (error) {
console.error("Failed to get supported languages:", error);
throw error;
}
},
// ================================
// Relay Stations
// ================================
/**
* Lists all relay stations
* @returns Promise resolving to array of relay stations
*/
async relayStationsList(): Promise<RelayStation[]> {
try {
return await invoke<RelayStation[]>("relay_stations_list");
} catch (error) {
console.error("Failed to list relay stations:", error);
throw error;
}
},
/**
* Gets a single relay station by ID
* @param id - The relay station ID
* @returns Promise resolving to the relay station
*/
async relayStationGet(id: string): Promise<RelayStation> {
try {
return await invoke<RelayStation>("relay_station_get", { id });
} catch (error) {
console.error("Failed to get relay station:", error);
throw error;
}
},
/**
* Creates a new relay station
* @param request - The relay station creation request
* @returns Promise resolving to the created relay station
*/
async relayStationCreate(request: CreateRelayStationRequest): Promise<RelayStation> {
try {
return await invoke<RelayStation>("relay_station_create", { request });
} catch (error) {
console.error("Failed to create relay station:", error);
throw error;
}
},
/**
* Updates an existing relay station
* @param request - The relay station update request
* @returns Promise resolving to the updated relay station
*/
async relayStationUpdate(request: UpdateRelayStationRequest): Promise<RelayStation> {
try {
return await invoke<RelayStation>("relay_station_update", { request });
} catch (error) {
console.error("Failed to update relay station:", error);
throw error;
}
},
/**
* Deletes a relay station
* @param id - The relay station ID
* @returns Promise resolving to success message
*/
async relayStationDelete(id: string): Promise<string> {
try {
return await invoke<string>("relay_station_delete", { id });
} catch (error) {
console.error("Failed to delete relay station:", error);
throw error;
}
},
/**
* Toggles relay station enable status (ensures only one station is enabled)
* @param id - The relay station ID
* @param enabled - Whether to enable or disable the station
* @returns Promise resolving to success message
*/
async relayStationToggleEnable(id: string, enabled: boolean): Promise<string> {
try {
return await invoke<string>("relay_station_toggle_enable", { id, enabled });
} catch (error) {
console.error("Failed to toggle relay station enable status:", error);
throw error;
}
},
/**
* Syncs relay station config to Claude settings.json
* @returns Promise resolving to sync result message
*/
async relayStationSyncConfig(): Promise<string> {
try {
return await invoke<string>("relay_station_sync_config");
} catch (error) {
console.error("Failed to sync relay station config:", error);
throw error;
}
},
/**
* Restores Claude config from backup
* @returns Promise resolving to restore result message
*/
async relayStationRestoreConfig(): Promise<string> {
try {
return await invoke<string>("relay_station_restore_config");
} catch (error) {
console.error("Failed to restore config:", error);
throw error;
}
},
/**
* Gets current API config from Claude settings
* @returns Promise resolving to current config info
*/
async relayStationGetCurrentConfig(): Promise<Record<string, string | null>> {
try {
return await invoke<Record<string, string | null>>("relay_station_get_current_config");
} catch (error) {
console.error("Failed to get current config:", error);
throw error;
}
},
/**
* Gets relay station information
* @param stationId - The relay station ID
* @returns Promise resolving to station information
*/
async relayStationGetInfo(stationId: string): Promise<StationInfo> {
try {
return await invoke<StationInfo>("relay_station_get_info", { stationId });
} catch (error) {
console.error("Failed to get station info:", error);
throw error;
}
},
/**
* Gets user information from relay station
* @param stationId - The relay station ID
* @param userId - The user ID
* @returns Promise resolving to user information
*/
async relayStationGetUserInfo(stationId: string, userId: string): Promise<UserInfo> {
try {
return await invoke<UserInfo>("relay_station_get_user_info", { stationId, userId });
} catch (error) {
console.error("Failed to get user info:", error);
throw error;
}
},
/**
* Tests relay station connection
* @param stationId - The relay station ID
* @returns Promise resolving to connection test result
*/
async relayStationTestConnection(stationId: string): Promise<ConnectionTestResult> {
try {
return await invoke<ConnectionTestResult>("relay_station_test_connection", { stationId });
} catch (error) {
console.error("Failed to test connection:", error);
throw error;
}
},
/**
* Gets usage logs from relay station
* @param stationId - The relay station ID
* @param userId - The user ID
* @param page - Page number (optional)
* @param size - Page size (optional)
* @returns Promise resolving to usage logs
*/
async relayStationGetUsageLogs(
stationId: string,
userId: string,
page?: number,
size?: number
): Promise<any> {
try {
return await invoke<any>("relay_station_get_usage_logs", { stationId, userId, page, size });
} catch (error) {
console.error("Failed to get usage logs:", error);
throw error;
}
},
/**
* Lists tokens from relay station
* @param stationId - The relay station ID
* @param page - Page number (optional)
* @param size - Page size (optional)
* @returns Promise resolving to token pagination response
*/
async relayStationListTokens(
stationId: string,
page?: number,
size?: number
): Promise<TokenPaginationResponse> {
try {
return await invoke<TokenPaginationResponse>("relay_station_list_tokens", { stationId, page, size });
} catch (error) {
console.error("Failed to list tokens:", error);
throw error;
}
},
/**
* Creates a new token on relay station
* @param stationId - The relay station ID
* @param name - Token name
* @param quota - Token quota (optional)
* @returns Promise resolving to created token info
*/
async relayStationCreateToken(
stationId: string,
name: string,
quota?: number
): Promise<TokenInfo> {
try {
return await invoke<TokenInfo>("relay_station_create_token", { stationId, name, quota });
} catch (error) {
console.error("Failed to create token:", error);
throw error;
}
},
/**
* Updates a token on relay station
* @param stationId - The relay station ID
* @param tokenId - The token ID
* @param name - New token name (optional)
* @param quota - New token quota (optional)
* @returns Promise resolving to updated token info
*/
async relayStationUpdateToken(
stationId: string,
tokenId: string,
name?: string,
quota?: number
): Promise<TokenInfo> {
try {
return await invoke<TokenInfo>("relay_station_update_token", { stationId, tokenId, name, quota });
} catch (error) {
console.error("Failed to update token:", error);
throw error;
}
},
/**
* Deletes a token from relay station
* @param stationId - The relay station ID
* @param tokenId - The token ID
* @returns Promise resolving to success message
*/
async relayStationDeleteToken(stationId: string, tokenId: string): Promise<string> {
try {
return await invoke<string>("relay_station_delete_token", { stationId, tokenId });
} catch (error) {
console.error("Failed to delete token:", error);
throw error;
}
},
// ============= PackyCode Nodes =============
/**
* Tests all PackyCode nodes and returns speed test results
* @returns Promise resolving to array of node speed test results
*/
async testAllPackycodeNodes(): Promise<NodeSpeedTestResult[]> {
try {
return await invoke<NodeSpeedTestResult[]>("test_all_packycode_nodes");
} catch (error) {
console.error("Failed to test PackyCode nodes:", error);
throw error;
}
},
/**
* Automatically selects the best PackyCode node based on speed
* @returns Promise resolving to the best node
*/
async autoSelectBestNode(): Promise<PackycodeNode> {
try {
return await invoke<PackycodeNode>("auto_select_best_node");
} catch (error) {
console.error("Failed to auto-select best node:", error);
throw error;
}
},
/**
* Gets all available PackyCode nodes
* @returns Promise resolving to array of PackyCode nodes
*/
async getPackycodeNodes(): Promise<PackycodeNode[]> {
try {
return await invoke<PackycodeNode[]>("get_packycode_nodes");
} catch (error) {
console.error("Failed to get PackyCode nodes:", error);
throw error;
}
},
/**
* Gets PackyCode user quota information
* @param stationId - The relay station ID
* @returns Promise resolving to the user quota information
*/
async getPackycodeUserQuota(stationId: string): Promise<PackycodeUserQuota> {
try {
return await invoke<PackycodeUserQuota>("packycode_get_user_quota", { stationId });
} catch (error) {
console.error("Failed to get PackyCode user quota:", error);
throw error;
}
}
};