rush-ai 0.10.0 → 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/commands/mcp/server.ts"],"sourcesContent":["import { Server } from '@modelcontextprotocol/sdk/server/index.js';\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';\nimport {\n CallToolRequestSchema,\n ListToolsRequestSchema,\n} from '@modelcontextprotocol/sdk/types.js';\nimport { getAuthToken } from '../../util/auth.js';\nimport { createClient } from '../../util/client.js';\nimport {\n consumeSSEStreamWithReconnect,\n type SSEEvent,\n} from '../../util/sse.js';\nimport type { McpServer as McpRegistryServer } from './index.js';\n\ninterface AgentListResponse {\n agents: Array<{\n id: string;\n name: string;\n description: string;\n capabilities: string[];\n skillCount: number;\n mcpCount: number;\n status: string;\n }>;\n total: number;\n}\n\ninterface TaskCreateResponse {\n id: string;\n status: string;\n}\n\ninterface TaskStatusResponse {\n id: string;\n status: string;\n agent: string;\n prompt: string;\n result?: unknown;\n error?: string;\n createdAt: string;\n updatedAt: string;\n}\n\ninterface TaskListResponse {\n tasks: TaskStatusResponse[];\n total: number;\n}\n\ninterface AgentDetailResponse {\n agent: {\n id: string;\n name: string;\n description: string | null;\n capabilities: string[] | null;\n skills: string[] | null;\n mcp_servers: unknown[] | null;\n status: string;\n visibility: string;\n provider_type: string;\n provider_model: string | null;\n system_prompt: string | null;\n created_at: string;\n updated_at: string;\n created_by_id: string | null;\n is_builtin: boolean;\n };\n}\n\ninterface TaskFile {\n id: string;\n filePath: string;\n fileName: string;\n ossPath?: string;\n ossUrl?: string;\n category: string;\n source: string;\n timestamp?: number;\n url?: string;\n conversationId?: string;\n}\n\ninterface TaskFilesResponse {\n files: TaskFile[];\n totalCount: number;\n}\n\nexport async function startMcpServer(): Promise<void> {\n const server = new Server(\n {\n name: 'rush-ai',\n version: '0.2.0',\n },\n {\n capabilities: {\n tools: {},\n },\n }\n );\n\n server.setRequestHandler(ListToolsRequestSchema, async () => {\n return {\n tools: [\n {\n name: 'rush_agent_list',\n description: 'List available Rush AI agents',\n inputSchema: {\n type: 'object' as const,\n properties: {},\n },\n },\n {\n name: 'rush_task_run',\n description:\n 'Run a task on a Rush AI agent. Creates an async task and polls until completion (up to 5 minutes).',\n inputSchema: {\n type: 'object' as const,\n properties: {\n agent: {\n type: 'string',\n description: 'Agent name',\n },\n prompt: {\n type: 'string',\n description: 'Task prompt',\n },\n skills: {\n type: 'array',\n items: { type: 'string' },\n description: 'Optional skills to add',\n },\n mcpServers: {\n type: 'array',\n items: { type: 'string' },\n description: 'Optional MCP servers to add',\n },\n timeout: {\n type: 'number',\n description:\n 'Max seconds to wait for completion (default: 300, max: 600)',\n },\n },\n required: ['agent', 'prompt'],\n },\n },\n {\n name: 'rush_task_send',\n description:\n 'Send a follow-up message to an existing task/project. Sends the message and polls until completion (up to 5 minutes).',\n inputSchema: {\n type: 'object' as const,\n properties: {\n id: {\n type: 'string',\n description: 'Task/Project ID',\n },\n prompt: {\n type: 'string',\n description: 'Message to send',\n },\n skills: {\n type: 'array',\n items: { type: 'string' },\n description: 'Optional skills to add',\n },\n mcpServers: {\n type: 'array',\n items: { type: 'string' },\n description: 'Optional MCP servers to add',\n },\n timeout: {\n type: 'number',\n description:\n 'Max seconds to wait for completion (default: 300, max: 600)',\n },\n },\n required: ['id', 'prompt'],\n },\n },\n {\n name: 'rush_task_create',\n description: 'Create an asynchronous task on a Rush AI agent',\n inputSchema: {\n type: 'object' as const,\n properties: {\n agent: {\n type: 'string',\n description: 'Agent name',\n },\n prompt: {\n type: 'string',\n description: 'Task prompt',\n },\n skills: {\n type: 'array',\n items: { type: 'string' },\n description: 'Optional skills to add',\n },\n mcpServers: {\n type: 'array',\n items: { type: 'string' },\n description: 'Optional MCP servers to add',\n },\n },\n required: ['agent', 'prompt'],\n },\n },\n {\n name: 'rush_task_status',\n description: 'Get the status of a task',\n inputSchema: {\n type: 'object' as const,\n properties: {\n id: {\n type: 'string',\n description: 'Task ID',\n },\n },\n required: ['id'],\n },\n },\n {\n name: 'rush_task_result',\n description: 'Get the result of a completed task',\n inputSchema: {\n type: 'object' as const,\n properties: {\n id: {\n type: 'string',\n description: 'Task ID',\n },\n },\n required: ['id'],\n },\n },\n {\n name: 'rush_task_list',\n description: 'List tasks',\n inputSchema: {\n type: 'object' as const,\n properties: {\n limit: {\n type: 'number',\n description: 'Max results (default: 20)',\n },\n status: {\n type: 'string',\n description:\n 'Filter by status: pending, running, completed, failed, cancelled',\n },\n },\n },\n },\n {\n name: 'rush_task_files',\n description:\n 'List files generated by a task (code, images, documents, etc.)',\n inputSchema: {\n type: 'object' as const,\n properties: {\n id: {\n type: 'string',\n description: 'Task ID',\n },\n category: {\n type: 'string',\n enum: ['code', 'image', 'document', 'other'],\n description: 'Optional filter by file category',\n },\n },\n required: ['id'],\n },\n },\n {\n name: 'rush_task_watch',\n description:\n 'Watch task execution in real-time. Blocks until task completes or timeout. Returns accumulated events.',\n inputSchema: {\n type: 'object' as const,\n properties: {\n id: {\n type: 'string',\n description: 'Task ID',\n },\n timeout: {\n type: 'number',\n description: 'Max seconds to watch (default: 300, max: 600)',\n },\n },\n required: ['id'],\n },\n },\n {\n name: 'rush_task_cancel',\n description: 'Cancel a running task',\n inputSchema: {\n type: 'object' as const,\n properties: {\n id: {\n type: 'string',\n description: 'Task ID',\n },\n },\n required: ['id'],\n },\n },\n {\n name: 'rush_agent_info',\n description: 'Get detailed information about a specific agent',\n inputSchema: {\n type: 'object' as const,\n properties: {\n id: {\n type: 'string',\n description: 'Agent ID',\n },\n },\n required: ['id'],\n },\n },\n {\n name: 'rush_mcp_list',\n description:\n 'List available MCP servers registered on the platform. Use to discover what MCP servers can be passed to the --mcp parameter when creating tasks.',\n inputSchema: {\n type: 'object' as const,\n properties: {\n category: {\n type: 'string',\n description:\n 'Filter by category (knowledge, dev-tools, observability, data, design, ci-cd, utilities)',\n },\n search: {\n type: 'string',\n description: 'Search by name or description',\n },\n page: {\n type: 'number',\n description: 'Page number (default: 1)',\n },\n },\n },\n },\n ],\n };\n });\n\n server.setRequestHandler(CallToolRequestSchema, async (request) => {\n const token = getAuthToken();\n if (!token) {\n return {\n content: [\n {\n type: 'text' as const,\n text: 'Error: Not authenticated. Run `rush-ai auth login` first.',\n },\n ],\n isError: true,\n };\n }\n\n const client = createClient();\n const args = (request.params.arguments ?? {}) as Record<string, unknown>;\n\n try {\n switch (request.params.name) {\n case 'rush_agent_list': {\n const { data } = await client.get<AgentListResponse>('/api/agents');\n return {\n content: [\n {\n type: 'text' as const,\n text: JSON.stringify(data, null, 2),\n },\n ],\n };\n }\n\n case 'rush_task_run': {\n // Create task via /api/tasks, then poll until completion\n const { data: created } = await client.post<TaskCreateResponse>(\n '/api/tasks',\n {\n agent: args.agent,\n prompt: args.prompt,\n skills: args.skills,\n mcpServers: args.mcpServers,\n }\n );\n\n const timeoutSec = Math.min(\n Math.max(Number(args.timeout) || 300, 1),\n 600\n );\n const deadline = Date.now() + timeoutSec * 1000;\n const TERMINAL = ['completed', 'failed', 'cancelled'];\n let status: TaskStatusResponse | null = null;\n\n while (Date.now() < deadline) {\n const { data: current } = await client.get<TaskStatusResponse>(\n `/api/tasks/${encodeURIComponent(created.id)}`\n );\n if (TERMINAL.includes(current.status)) {\n status = current;\n break;\n }\n // Poll every 2 seconds\n await new Promise((r) => setTimeout(r, 2000));\n }\n\n if (!status) {\n return {\n content: [\n {\n type: 'text' as const,\n text: JSON.stringify(\n {\n id: created.id,\n status: 'timeout',\n message: `Task did not complete within ${timeoutSec}s. Use rush_task_status to check later.`,\n },\n null,\n 2\n ),\n },\n ],\n };\n }\n\n // If completed, also fetch the result\n if (status.status === 'completed') {\n try {\n const { data: resultData } = await client.get<{\n result: unknown;\n }>(`/api/tasks/${encodeURIComponent(created.id)}/result`);\n return {\n content: [\n {\n type: 'text' as const,\n text: JSON.stringify(\n { ...status, result: resultData.result },\n null,\n 2\n ),\n },\n ],\n };\n } catch {\n // Fall through to return status without result\n }\n }\n\n return {\n content: [\n {\n type: 'text' as const,\n text: JSON.stringify(status, null, 2),\n },\n ],\n };\n }\n\n case 'rush_task_send': {\n // Send message to existing task via /api/tasks/{id}/send\n const { data: sendResult } = await client.post<TaskCreateResponse>(\n `/api/tasks/${encodeURIComponent(String(args.id))}/send`,\n {\n prompt: args.prompt,\n skills: args.skills,\n mcpServers: args.mcpServers,\n }\n );\n\n const sendTimeoutSec = Math.min(\n Math.max(Number(args.timeout) || 300, 1),\n 600\n );\n const sendDeadline = Date.now() + sendTimeoutSec * 1000;\n const SEND_TERMINAL = ['completed', 'failed', 'cancelled'];\n let sendStatus: TaskStatusResponse | null = null;\n\n while (Date.now() < sendDeadline) {\n const { data: current } = await client.get<TaskStatusResponse>(\n `/api/tasks/${encodeURIComponent(sendResult.id)}`\n );\n if (SEND_TERMINAL.includes(current.status)) {\n sendStatus = current;\n break;\n }\n // Poll every 2 seconds\n await new Promise((r) => setTimeout(r, 2000));\n }\n\n if (!sendStatus) {\n return {\n content: [\n {\n type: 'text' as const,\n text: JSON.stringify(\n {\n id: sendResult.id,\n status: 'timeout',\n message: `Task did not complete within ${sendTimeoutSec}s. Use rush_task_status to check later.`,\n },\n null,\n 2\n ),\n },\n ],\n };\n }\n\n // If completed, also fetch the result\n if (sendStatus.status === 'completed') {\n try {\n const { data: resultData } = await client.get<{\n result: unknown;\n }>(`/api/tasks/${encodeURIComponent(sendResult.id)}/result`);\n return {\n content: [\n {\n type: 'text' as const,\n text: JSON.stringify(\n { ...sendStatus, result: resultData.result },\n null,\n 2\n ),\n },\n ],\n };\n } catch {\n // Fall through to return status without result\n }\n }\n\n return {\n content: [\n {\n type: 'text' as const,\n text: JSON.stringify(sendStatus, null, 2),\n },\n ],\n };\n }\n\n case 'rush_task_create': {\n const { data } = await client.post<TaskCreateResponse>('/api/tasks', {\n agent: args.agent,\n prompt: args.prompt,\n skills: args.skills,\n mcpServers: args.mcpServers,\n });\n return {\n content: [\n {\n type: 'text' as const,\n text: JSON.stringify(data, null, 2),\n },\n ],\n };\n }\n\n case 'rush_task_status': {\n const { data } = await client.get<TaskStatusResponse>(\n `/api/tasks/${encodeURIComponent(String(args.id))}`\n );\n return {\n content: [\n {\n type: 'text' as const,\n text: JSON.stringify(data, null, 2),\n },\n ],\n };\n }\n\n case 'rush_task_result': {\n const { data } = await client.get<{\n result: unknown;\n }>(`/api/tasks/${encodeURIComponent(String(args.id))}/result`);\n return {\n content: [\n {\n type: 'text' as const,\n text: JSON.stringify(data, null, 2),\n },\n ],\n };\n }\n\n case 'rush_task_list': {\n const params = new URLSearchParams();\n if (args.limit) params.set('limit', String(args.limit));\n if (args.status) params.set('status', String(args.status));\n const { data } = await client.get<TaskListResponse>(\n `/api/tasks?${params.toString()}`\n );\n return {\n content: [\n {\n type: 'text' as const,\n text: JSON.stringify(data, null, 2),\n },\n ],\n };\n }\n\n case 'rush_task_files': {\n const { data } = await client.get<TaskFilesResponse>(\n `/api/chat/${encodeURIComponent(String(args.id))}/files`\n );\n const validCategories = ['code', 'image', 'document', 'other'];\n let files = data.files;\n if (\n args.category &&\n typeof args.category === 'string' &&\n validCategories.includes(args.category)\n ) {\n files = files.filter((f) => f.category === args.category);\n }\n return {\n content: [\n {\n type: 'text' as const,\n text: JSON.stringify(\n { files, totalCount: files.length },\n null,\n 2\n ),\n },\n ],\n };\n }\n\n case 'rush_task_watch': {\n const TERMINAL_STATUSES = ['completed', 'failed', 'cancelled'];\n const timeoutSec = Math.min(\n Math.max(Number(args.timeout) || 300, 1),\n 600\n );\n const events: SSEEvent[] = [];\n let truncated = false;\n let watchError: string | null = null;\n\n const controller = new AbortController();\n const timeoutId = setTimeout(() => {\n truncated = true;\n controller.abort();\n }, timeoutSec * 1000);\n\n try {\n const connectFn = async () => {\n const response = await client.fetchRaw(\n `/api/tasks/${encodeURIComponent(String(args.id))}/events`,\n { method: 'GET' }\n );\n if (!response.body) throw new Error('No response body');\n return response.body;\n };\n\n await consumeSSEStreamWithReconnect(\n connectFn,\n (event) => {\n events.push(event);\n },\n {\n signal: controller.signal,\n isTerminal: (event) =>\n event.type === 'status' &&\n TERMINAL_STATUSES.includes(event.data),\n }\n );\n } catch (err) {\n if (!truncated) {\n // Real error (not timeout) — report it\n watchError = err instanceof Error ? err.message : 'Unknown error';\n }\n } finally {\n clearTimeout(timeoutId);\n }\n\n // If we got no events and there was an error, return as error\n if (events.length === 0 && watchError) {\n return {\n content: [\n {\n type: 'text' as const,\n text: `Error: ${watchError}`,\n },\n ],\n isError: true,\n };\n }\n\n return {\n content: [\n {\n type: 'text' as const,\n text: JSON.stringify(\n {\n events,\n truncated,\n eventCount: events.length,\n ...(watchError ? { error: watchError } : {}),\n },\n null,\n 2\n ),\n },\n ],\n };\n }\n\n case 'rush_task_cancel': {\n await client.delete(\n `/api/tasks/${encodeURIComponent(String(args.id))}`\n );\n return {\n content: [\n {\n type: 'text' as const,\n text: JSON.stringify(\n { id: args.id, status: 'cancelled' },\n null,\n 2\n ),\n },\n ],\n };\n }\n\n case 'rush_agent_info': {\n const { data } = await client.get<AgentDetailResponse>(\n `/api/agents/${encodeURIComponent(String(args.id))}`\n );\n return {\n content: [\n {\n type: 'text' as const,\n text: JSON.stringify(data, null, 2),\n },\n ],\n };\n }\n\n case 'rush_mcp_list': {\n const params = new URLSearchParams();\n if (args.category) params.set('category', String(args.category));\n if (args.search) params.set('search', String(args.search));\n if (args.page) params.set('page', String(args.page));\n params.set('limit', '100');\n const { data } = await client.get<{\n data: McpRegistryServer[];\n }>(`/api/mcp-registry?${params.toString()}`);\n return {\n content: [\n {\n type: 'text' as const,\n text: JSON.stringify(data, null, 2),\n },\n ],\n };\n }\n\n default:\n return {\n content: [\n {\n type: 'text' as const,\n text: `Unknown tool: ${request.params.name}`,\n },\n ],\n isError: true,\n };\n }\n } catch (err) {\n return {\n content: [\n {\n type: 'text' as const,\n text: `Error: ${err instanceof Error ? err.message : 'Unknown error'}`,\n },\n ],\n isError: true,\n };\n }\n });\n\n const transport = new StdioServerTransport();\n await server.connect(transport);\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/commands/mcp/server.ts"],"sourcesContent":["import { Server } from '@modelcontextprotocol/sdk/server/index.js';\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';\nimport {\n CallToolRequestSchema,\n ListToolsRequestSchema,\n} from '@modelcontextprotocol/sdk/types.js';\nimport { getAuthToken } from '../../util/auth.js';\nimport { createClient } from '../../util/client.js';\nimport {\n consumeSSEStreamWithReconnect,\n type SSEEvent,\n} from '../../util/sse.js';\nimport type { McpServer as McpRegistryServer } from './index.js';\n\ninterface AgentListResponse {\n agents: Array<{\n id: string;\n name: string;\n description: string;\n capabilities: string[];\n skillCount: number;\n mcpCount: number;\n status: string;\n }>;\n total: number;\n}\n\ninterface TaskCreateResponse {\n id: string;\n status: string;\n}\n\ninterface TaskStatusResponse {\n id: string;\n status: string;\n agent: string;\n prompt: string;\n result?: unknown;\n error?: string;\n createdAt: string;\n updatedAt: string;\n}\n\ninterface TaskListResponse {\n tasks: TaskStatusResponse[];\n total: number;\n}\n\ninterface AgentDetailResponse {\n agent: {\n id: string;\n name: string;\n description: string | null;\n capabilities: string[] | null;\n skills: string[] | null;\n mcp_servers: unknown[] | null;\n status: string;\n visibility: string;\n provider_type: string;\n provider_model: string | null;\n system_prompt: string | null;\n created_at: string;\n updated_at: string;\n created_by_id: string | null;\n is_builtin: boolean;\n };\n}\n\ninterface TaskFile {\n id: string;\n filePath: string;\n fileName: string;\n ossPath?: string;\n ossUrl?: string;\n category: string;\n source: string;\n timestamp?: number;\n url?: string;\n conversationId?: string;\n}\n\ninterface TaskFilesResponse {\n files: TaskFile[];\n totalCount: number;\n}\n\nexport async function startMcpServer(): Promise<void> {\n const server = new Server(\n {\n name: 'rush-ai',\n version: '0.2.0',\n },\n {\n capabilities: {\n tools: {},\n },\n }\n );\n\n server.setRequestHandler(ListToolsRequestSchema, async () => {\n return {\n tools: [\n {\n name: 'rush_agent_list',\n description: 'List available Rush AI agents',\n inputSchema: {\n type: 'object' as const,\n properties: {},\n },\n },\n {\n name: 'rush_task_run',\n description:\n 'Run a task on a Rush AI agent. Creates an async task and polls until completion (up to 5 minutes).',\n inputSchema: {\n type: 'object' as const,\n properties: {\n agent: {\n type: 'string',\n description: 'Agent name',\n },\n prompt: {\n type: 'string',\n description: 'Task prompt',\n },\n skills: {\n type: 'array',\n items: { type: 'string' },\n description: 'Optional skills to add',\n },\n mcpServers: {\n type: 'array',\n items: { type: 'string' },\n description: 'Optional MCP servers to add',\n },\n timeout: {\n type: 'number',\n description:\n 'Max seconds to wait for completion (default: 300, max: 600)',\n },\n },\n required: ['agent', 'prompt'],\n },\n },\n {\n name: 'rush_task_send',\n description:\n 'Send a follow-up message to an existing task/project. Sends the message and polls until completion (up to 5 minutes).',\n inputSchema: {\n type: 'object' as const,\n properties: {\n id: {\n type: 'string',\n description: 'Task/Project ID',\n },\n prompt: {\n type: 'string',\n description: 'Message to send',\n },\n skills: {\n type: 'array',\n items: { type: 'string' },\n description: 'Optional skills to add',\n },\n mcpServers: {\n type: 'array',\n items: { type: 'string' },\n description: 'Optional MCP servers to add',\n },\n timeout: {\n type: 'number',\n description:\n 'Max seconds to wait for completion (default: 300, max: 600)',\n },\n },\n required: ['id', 'prompt'],\n },\n },\n {\n name: 'rush_task_create',\n description: 'Create an asynchronous task on a Rush AI agent',\n inputSchema: {\n type: 'object' as const,\n properties: {\n agent: {\n type: 'string',\n description: 'Agent name',\n },\n prompt: {\n type: 'string',\n description: 'Task prompt',\n },\n skills: {\n type: 'array',\n items: { type: 'string' },\n description: 'Optional skills to add',\n },\n mcpServers: {\n type: 'array',\n items: { type: 'string' },\n description: 'Optional MCP servers to add',\n },\n },\n required: ['agent', 'prompt'],\n },\n },\n {\n name: 'rush_task_status',\n description: 'Get the status of a task',\n inputSchema: {\n type: 'object' as const,\n properties: {\n id: {\n type: 'string',\n description: 'Task ID',\n },\n },\n required: ['id'],\n },\n },\n {\n name: 'rush_task_result',\n description: 'Get the result of a completed task',\n inputSchema: {\n type: 'object' as const,\n properties: {\n id: {\n type: 'string',\n description: 'Task ID',\n },\n },\n required: ['id'],\n },\n },\n {\n name: 'rush_task_list',\n description: 'List tasks',\n inputSchema: {\n type: 'object' as const,\n properties: {\n limit: {\n type: 'number',\n description: 'Max results (default: 20)',\n },\n status: {\n type: 'string',\n description:\n 'Filter by status: pending, running, completed, failed, cancelled',\n },\n },\n },\n },\n {\n name: 'rush_task_files',\n description:\n 'List files generated by a task (code, images, documents, etc.)',\n inputSchema: {\n type: 'object' as const,\n properties: {\n id: {\n type: 'string',\n description: 'Task ID',\n },\n category: {\n type: 'string',\n enum: ['code', 'image', 'document', 'other'],\n description: 'Optional filter by file category',\n },\n },\n required: ['id'],\n },\n },\n {\n name: 'rush_task_watch',\n description:\n 'Watch task execution in real-time. Blocks until task completes or timeout. Returns accumulated events.',\n inputSchema: {\n type: 'object' as const,\n properties: {\n id: {\n type: 'string',\n description: 'Task ID',\n },\n timeout: {\n type: 'number',\n description: 'Max seconds to watch (default: 300, max: 600)',\n },\n },\n required: ['id'],\n },\n },\n {\n name: 'rush_task_cancel',\n description: 'Cancel a running task',\n inputSchema: {\n type: 'object' as const,\n properties: {\n id: {\n type: 'string',\n description: 'Task ID',\n },\n },\n required: ['id'],\n },\n },\n {\n name: 'rush_agent_info',\n description: 'Get detailed information about a specific agent',\n inputSchema: {\n type: 'object' as const,\n properties: {\n id: {\n type: 'string',\n description: 'Agent ID',\n },\n },\n required: ['id'],\n },\n },\n {\n name: 'rush_mcp_list',\n description:\n 'List available MCP servers registered on the platform. Use to discover what MCP servers can be passed to the --mcp parameter when creating tasks.',\n inputSchema: {\n type: 'object' as const,\n properties: {\n category: {\n type: 'string',\n description:\n 'Filter by category (knowledge, dev-tools, observability, data, design, ci-cd, utilities)',\n },\n search: {\n type: 'string',\n description: 'Search by name or description',\n },\n page: {\n type: 'number',\n description: 'Page number (default: 1)',\n },\n },\n },\n },\n ],\n };\n });\n\n server.setRequestHandler(CallToolRequestSchema, async (request) => {\n const token = getAuthToken();\n if (!token) {\n return {\n content: [\n {\n type: 'text' as const,\n text: 'Error: Not authenticated. Run `rush-ai auth login` first.',\n },\n ],\n isError: true,\n };\n }\n\n const client = createClient();\n const args = (request.params.arguments ?? {}) as Record<string, unknown>;\n\n try {\n switch (request.params.name) {\n case 'rush_agent_list': {\n const { data } = await client.get<AgentListResponse>('/api/agents');\n return {\n content: [\n {\n type: 'text' as const,\n text: JSON.stringify(data, null, 2),\n },\n ],\n };\n }\n\n case 'rush_task_run': {\n // Create task via /api/tasks, then poll until completion\n const { data: created } = await client.post<TaskCreateResponse>(\n '/api/tasks',\n {\n agent: args.agent,\n prompt: args.prompt,\n skills: args.skills,\n mcpServers: args.mcpServers,\n }\n );\n\n const timeoutSec = Math.min(\n Math.max(Number(args.timeout) || 300, 1),\n 600\n );\n const deadline = Date.now() + timeoutSec * 1000;\n const TERMINAL = ['completed', 'failed', 'cancelled'];\n let status: TaskStatusResponse | null = null;\n\n while (Date.now() < deadline) {\n const { data: current } = await client.get<TaskStatusResponse>(\n `/api/tasks/${encodeURIComponent(created.id)}`\n );\n if (TERMINAL.includes(current.status)) {\n status = current;\n break;\n }\n // Poll every 2 seconds\n await new Promise((r) => setTimeout(r, 2000));\n }\n\n if (!status) {\n return {\n content: [\n {\n type: 'text' as const,\n text: JSON.stringify(\n {\n id: created.id,\n status: 'timeout',\n message: `Task did not complete within ${timeoutSec}s. Use rush_task_status to check later.`,\n },\n null,\n 2\n ),\n },\n ],\n };\n }\n\n // If completed, also fetch the result\n if (status.status === 'completed') {\n try {\n const { data: resultData } = await client.get<{\n result: unknown;\n }>(`/api/tasks/${encodeURIComponent(created.id)}/result`);\n return {\n content: [\n {\n type: 'text' as const,\n text: JSON.stringify(\n { ...status, result: resultData.result },\n null,\n 2\n ),\n },\n ],\n };\n } catch {\n // Fall through to return status without result\n }\n }\n\n return {\n content: [\n {\n type: 'text' as const,\n text: JSON.stringify(status, null, 2),\n },\n ],\n };\n }\n\n case 'rush_task_send': {\n // Send message to existing task via /api/tasks/{id}/send\n const { data: sendResult } = await client.post<TaskCreateResponse>(\n `/api/tasks/${encodeURIComponent(String(args.id))}/send`,\n {\n prompt: args.prompt,\n skills: args.skills,\n mcpServers: args.mcpServers,\n }\n );\n\n const sendTimeoutSec = Math.min(\n Math.max(Number(args.timeout) || 300, 1),\n 600\n );\n const sendDeadline = Date.now() + sendTimeoutSec * 1000;\n const SEND_TERMINAL = ['completed', 'failed', 'cancelled'];\n let sendStatus: TaskStatusResponse | null = null;\n\n while (Date.now() < sendDeadline) {\n const { data: current } = await client.get<TaskStatusResponse>(\n `/api/tasks/${encodeURIComponent(sendResult.id)}`\n );\n if (SEND_TERMINAL.includes(current.status)) {\n sendStatus = current;\n break;\n }\n // Poll every 2 seconds\n await new Promise((r) => setTimeout(r, 2000));\n }\n\n if (!sendStatus) {\n return {\n content: [\n {\n type: 'text' as const,\n text: JSON.stringify(\n {\n id: sendResult.id,\n status: 'timeout',\n message: `Task did not complete within ${sendTimeoutSec}s. Use rush_task_status to check later.`,\n },\n null,\n 2\n ),\n },\n ],\n };\n }\n\n // If completed, also fetch the result\n if (sendStatus.status === 'completed') {\n try {\n const { data: resultData } = await client.get<{\n result: unknown;\n }>(`/api/tasks/${encodeURIComponent(sendResult.id)}/result`);\n return {\n content: [\n {\n type: 'text' as const,\n text: JSON.stringify(\n { ...sendStatus, result: resultData.result },\n null,\n 2\n ),\n },\n ],\n };\n } catch {\n // Fall through to return status without result\n }\n }\n\n return {\n content: [\n {\n type: 'text' as const,\n text: JSON.stringify(sendStatus, null, 2),\n },\n ],\n };\n }\n\n case 'rush_task_create': {\n const { data } = await client.post<TaskCreateResponse>('/api/tasks', {\n agent: args.agent,\n prompt: args.prompt,\n skills: args.skills,\n mcpServers: args.mcpServers,\n });\n return {\n content: [\n {\n type: 'text' as const,\n text: JSON.stringify(data, null, 2),\n },\n ],\n };\n }\n\n case 'rush_task_status': {\n const { data } = await client.get<TaskStatusResponse>(\n `/api/tasks/${encodeURIComponent(String(args.id))}`\n );\n return {\n content: [\n {\n type: 'text' as const,\n text: JSON.stringify(data, null, 2),\n },\n ],\n };\n }\n\n case 'rush_task_result': {\n const { data } = await client.get<{\n result: unknown;\n }>(`/api/tasks/${encodeURIComponent(String(args.id))}/result`);\n return {\n content: [\n {\n type: 'text' as const,\n text: JSON.stringify(data, null, 2),\n },\n ],\n };\n }\n\n case 'rush_task_list': {\n const params = new URLSearchParams();\n if (args.limit) params.set('limit', String(args.limit));\n if (args.status) params.set('status', String(args.status));\n const { data } = await client.get<TaskListResponse>(\n `/api/tasks?${params.toString()}`\n );\n return {\n content: [\n {\n type: 'text' as const,\n text: JSON.stringify(data, null, 2),\n },\n ],\n };\n }\n\n case 'rush_task_files': {\n const { data } = await client.get<TaskFilesResponse>(\n `/api/chat/${encodeURIComponent(String(args.id))}/files`\n );\n const validCategories = ['code', 'image', 'document', 'other'];\n let files = data.files;\n if (\n args.category &&\n typeof args.category === 'string' &&\n validCategories.includes(args.category)\n ) {\n files = files.filter((f) => f.category === args.category);\n }\n return {\n content: [\n {\n type: 'text' as const,\n text: JSON.stringify(\n { files, totalCount: files.length },\n null,\n 2\n ),\n },\n ],\n };\n }\n\n case 'rush_task_watch': {\n const TERMINAL_STATUSES = ['completed', 'failed', 'cancelled'];\n const timeoutSec = Math.min(\n Math.max(Number(args.timeout) || 300, 1),\n 600\n );\n const events: SSEEvent[] = [];\n let truncated = false;\n let watchError: string | null = null;\n\n const controller = new AbortController();\n const timeoutId = setTimeout(() => {\n truncated = true;\n controller.abort();\n }, timeoutSec * 1000);\n\n try {\n const connectFn = async () => {\n const response = await client.fetchRaw(\n `/api/tasks/${encodeURIComponent(String(args.id))}/events`,\n { method: 'GET' }\n );\n if (!response.body) throw new Error('No response body');\n return response.body;\n };\n\n await consumeSSEStreamWithReconnect(\n connectFn,\n (event) => {\n events.push(event);\n },\n {\n signal: controller.signal,\n isTerminal: (event) =>\n event.type === 'status' &&\n TERMINAL_STATUSES.includes(event.data),\n }\n );\n } catch (err) {\n if (!truncated) {\n // Real error (not timeout) — report it\n watchError = err instanceof Error ? err.message : 'Unknown error';\n }\n } finally {\n clearTimeout(timeoutId);\n }\n\n // If we got no events and there was an error, return as error\n if (events.length === 0 && watchError) {\n return {\n content: [\n {\n type: 'text' as const,\n text: `Error: ${watchError}`,\n },\n ],\n isError: true,\n };\n }\n\n return {\n content: [\n {\n type: 'text' as const,\n text: JSON.stringify(\n {\n events,\n truncated,\n eventCount: events.length,\n ...(watchError ? { error: watchError } : {}),\n },\n null,\n 2\n ),\n },\n ],\n };\n }\n\n case 'rush_task_cancel': {\n await client.delete(\n `/api/tasks/${encodeURIComponent(String(args.id))}`\n );\n return {\n content: [\n {\n type: 'text' as const,\n text: JSON.stringify(\n { id: args.id, status: 'cancelled' },\n null,\n 2\n ),\n },\n ],\n };\n }\n\n case 'rush_agent_info': {\n const { data } = await client.get<AgentDetailResponse>(\n `/api/agents/${encodeURIComponent(String(args.id))}`\n );\n return {\n content: [\n {\n type: 'text' as const,\n text: JSON.stringify(data, null, 2),\n },\n ],\n };\n }\n\n case 'rush_mcp_list': {\n const params = new URLSearchParams();\n if (args.category) params.set('category', String(args.category));\n if (args.search) params.set('search', String(args.search));\n if (args.page) params.set('page', String(args.page));\n params.set('limit', '100');\n const { data } = await client.get<{\n data: McpRegistryServer[];\n }>(`/api/mcp-registry?${params.toString()}`);\n return {\n content: [\n {\n type: 'text' as const,\n text: JSON.stringify(data, null, 2),\n },\n ],\n };\n }\n\n default:\n return {\n content: [\n {\n type: 'text' as const,\n text: `Unknown tool: ${request.params.name}`,\n },\n ],\n isError: true,\n };\n }\n } catch (err) {\n return {\n content: [\n {\n type: 'text' as const,\n text: `Error: ${err instanceof Error ? err.message : 'Unknown error'}`,\n },\n ],\n isError: true,\n };\n }\n });\n\n const transport = new StdioServerTransport();\n await server.connect(transport);\n}\n"],"mappings":"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","names":[]}
@@ -57,7 +57,7 @@ Good prompt hygiene (all matter more for `-a rush` than for `-a web-builder`, wh
57
57
  - **State the output format explicitly.** "Return 3 bullet points." / "Return JSON with fields `{summary, keyRisks}`." / "Return a markdown table." Without this, the agent guesses and you'll waste a `task send` fixing the shape.
58
58
  - **Pass inputs inline when short.** If the user shared a brief document / data snippet, include it in the prompt body. For longer content, two reliable paths:
59
59
  - **Pipe via stdin**: `cat big-input.txt | npx rush-ai task create -a rush --json` — `task create` reads stdin when `-p` is omitted.
60
- - **Attach on the follow-up**: use `task send <id> -f <path>` after creating the task (see Playbook step 7). `task create` does NOT accept file attachments — only `task send` does, via `-f / --file` (repeatable).
60
+ - **Attach on the follow-up**: use `task send <id> --file <path>` after creating the task (see Playbook step 7). `task create` does NOT accept file attachments — only `task send` does, via repeatable `--file`.
61
61
  - **Name the audience or tone if relevant.** "Write for the CEO, ≤200 words" beats "Write a summary" nine times out of ten.
62
62
 
63
63
  ### 3. Create the task
@@ -145,14 +145,14 @@ If the output needs refinement — wrong tone, missed a requirement, needs a dif
145
145
  ```bash
146
146
  npx rush-ai task send <id> -p "<the refinement>" --json
147
147
 
148
- # Attach a file as additional context (repeatable; each -f uploads one file)
149
- npx rush-ai task send <id> -p "take this new data into account" -f ./extra.csv --json
148
+ # Attach a file as additional context (repeatable; each --file uploads one file)
149
+ npx rush-ai task send <id> -p "take this new data into account" --file ./extra.csv --json
150
150
  ```
151
151
 
152
152
  Note the flag asymmetry with `task create`:
153
153
 
154
154
  - `task send` does **not** accept `-a / --agent` — the agent is fixed to whatever the task was created with. Trying to pass `-a` on `send` is a common mis-invocation.
155
- - `task send` **does** support `-f / --file <path>` (repeatable) for attachments; `task create` does not.
155
+ - `task send` **does** support `--file <path>` (repeatable) for attachments; `task create` does not.
156
156
  - Both support `-p / --prompt`, `--skills`, and `--mcp`.
157
157
 
158
158
  The same task id keeps its conversation history server-side, so the follow-up builds on the first result. Poll `task status <id>` again for completion, then `task result <id>`.
@@ -185,5 +185,5 @@ Don't silently retry — the same prompt will likely produce the same failure.
185
185
  - ❌ **Running `task watch` just to wait.** `watch` streams every agent event over SSE. It's for debugging, not polling. Use `task status` every 15-30s.
186
186
  - ❌ **Hiding the task id from the user.** They may want to look at it in the Rush web UI, share it with a teammate, or come back to iterate later. Always print the id after creation.
187
187
  - ❌ **Claiming a file was produced when it wasn't.** Check `task files <id>` (no flags) first. If the list is empty, the task produced text only — don't invent a `--download <fake-filename>` that will fail.
188
- - ❌ **Inventing flags.** `task create` accepts `-a / --agent`, `-p / --prompt`, `--skills`, `--mcp` (plus global `--json`). `task send` accepts `-p / --prompt`, `--skills`, `--mcp`, `-f / --file` (repeatable) — note **no `-a` on `send`**; the agent is fixed to whatever the task was created with. `task files` accepts `--download`, `--download-all`, `-o / --output`, `-c / --category`. No `--format`, no `--timeout`, no `--retry`.
188
+ - ❌ **Inventing flags.** `task create` accepts `-a / --agent`, `-p / --prompt`, `--skills`, `--mcp` (plus global `--json`). `task send` accepts `-p / --prompt`, `--skills`, `--mcp`, `--file` (repeatable) — note **no `-a` on `send`**; the agent is fixed to whatever the task was created with. `task files` accepts `--download`, `--download-all`, `-o / --output`, `-c / --category`. No `--format`, no `--timeout`, no `--retry`.
189
189
  - ❌ **Routing specialist work through `rush`.** If the user named a specific agent ("use the HR analytics specialist"), go to [`agent-shelf.md`](./agent-shelf.md). `rush` is the *default*, not a *fallback-for-everything*.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rush-ai",
3
- "version": "0.10.0",
3
+ "version": "0.11.0",
4
4
  "description": "Rush CLI - Command-line interface for the Rush AI platform",
5
5
  "private": false,
6
6
  "type": "module",
@@ -13,13 +13,7 @@
13
13
  "exports": {
14
14
  ".": "./dist/index.js"
15
15
  },
16
- "files": [
17
- "dist",
18
- "skills",
19
- "README.md",
20
- "AGENTS.md",
21
- "LICENSE"
22
- ],
16
+ "files": ["dist", "skills", "README.md", "AGENTS.md", "LICENSE"],
23
17
  "publishConfig": {
24
18
  "access": "public",
25
19
  "registry": "https://registry.npmjs.org/"
@@ -29,13 +23,19 @@
29
23
  "url": "https://github.com/kanyun-inc/rush-app",
30
24
  "directory": "packages/rush-ai"
31
25
  },
32
- "keywords": [
33
- "rush",
34
- "ai",
35
- "cli",
36
- "agent",
37
- "mcp"
38
- ],
26
+ "keywords": ["rush", "ai", "cli", "agent", "mcp"],
27
+ "scripts": {
28
+ "build": "tsup",
29
+ "dev": "tsup --watch",
30
+ "typecheck": "tsc --noEmit",
31
+ "test": "vitest run",
32
+ "test:watch": "vitest",
33
+ "test:e2e": "vitest --config vitest.e2e.config.ts --no-watch",
34
+ "test:smoke": "vitest --config vitest.smoke.config.ts --no-watch",
35
+ "test:all": "pnpm test && pnpm test:e2e",
36
+ "eval": "vitest --config evals/vitest.eval.config.ts --no-watch",
37
+ "clean": "rm -rf dist node_modules"
38
+ },
39
39
  "dependencies": {
40
40
  "@iarna/toml": "^2.2.5",
41
41
  "@modelcontextprotocol/sdk": "^1.12.1",
@@ -50,17 +50,5 @@
50
50
  "tsup": "^8.4.0",
51
51
  "typescript": "^5.8.2",
52
52
  "vitest": "^4.0.4"
53
- },
54
- "scripts": {
55
- "build": "tsup",
56
- "dev": "tsup --watch",
57
- "typecheck": "tsc --noEmit",
58
- "test": "vitest run",
59
- "test:watch": "vitest",
60
- "test:e2e": "vitest --config vitest.e2e.config.ts --no-watch",
61
- "test:smoke": "vitest --config vitest.smoke.config.ts --no-watch",
62
- "test:all": "pnpm test && pnpm test:e2e",
63
- "eval": "vitest --config evals/vitest.eval.config.ts --no-watch",
64
- "clean": "rm -rf dist node_modules"
65
53
  }
66
- }
54
+ }
@@ -57,7 +57,7 @@ Good prompt hygiene (all matter more for `-a rush` than for `-a web-builder`, wh
57
57
  - **State the output format explicitly.** "Return 3 bullet points." / "Return JSON with fields `{summary, keyRisks}`." / "Return a markdown table." Without this, the agent guesses and you'll waste a `task send` fixing the shape.
58
58
  - **Pass inputs inline when short.** If the user shared a brief document / data snippet, include it in the prompt body. For longer content, two reliable paths:
59
59
  - **Pipe via stdin**: `cat big-input.txt | npx rush-ai task create -a rush --json` — `task create` reads stdin when `-p` is omitted.
60
- - **Attach on the follow-up**: use `task send <id> -f <path>` after creating the task (see Playbook step 7). `task create` does NOT accept file attachments — only `task send` does, via `-f / --file` (repeatable).
60
+ - **Attach on the follow-up**: use `task send <id> --file <path>` after creating the task (see Playbook step 7). `task create` does NOT accept file attachments — only `task send` does, via repeatable `--file`.
61
61
  - **Name the audience or tone if relevant.** "Write for the CEO, ≤200 words" beats "Write a summary" nine times out of ten.
62
62
 
63
63
  ### 3. Create the task
@@ -145,14 +145,14 @@ If the output needs refinement — wrong tone, missed a requirement, needs a dif
145
145
  ```bash
146
146
  npx rush-ai task send <id> -p "<the refinement>" --json
147
147
 
148
- # Attach a file as additional context (repeatable; each -f uploads one file)
149
- npx rush-ai task send <id> -p "take this new data into account" -f ./extra.csv --json
148
+ # Attach a file as additional context (repeatable; each --file uploads one file)
149
+ npx rush-ai task send <id> -p "take this new data into account" --file ./extra.csv --json
150
150
  ```
151
151
 
152
152
  Note the flag asymmetry with `task create`:
153
153
 
154
154
  - `task send` does **not** accept `-a / --agent` — the agent is fixed to whatever the task was created with. Trying to pass `-a` on `send` is a common mis-invocation.
155
- - `task send` **does** support `-f / --file <path>` (repeatable) for attachments; `task create` does not.
155
+ - `task send` **does** support `--file <path>` (repeatable) for attachments; `task create` does not.
156
156
  - Both support `-p / --prompt`, `--skills`, and `--mcp`.
157
157
 
158
158
  The same task id keeps its conversation history server-side, so the follow-up builds on the first result. Poll `task status <id>` again for completion, then `task result <id>`.
@@ -185,5 +185,5 @@ Don't silently retry — the same prompt will likely produce the same failure.
185
185
  - ❌ **Running `task watch` just to wait.** `watch` streams every agent event over SSE. It's for debugging, not polling. Use `task status` every 15-30s.
186
186
  - ❌ **Hiding the task id from the user.** They may want to look at it in the Rush web UI, share it with a teammate, or come back to iterate later. Always print the id after creation.
187
187
  - ❌ **Claiming a file was produced when it wasn't.** Check `task files <id>` (no flags) first. If the list is empty, the task produced text only — don't invent a `--download <fake-filename>` that will fail.
188
- - ❌ **Inventing flags.** `task create` accepts `-a / --agent`, `-p / --prompt`, `--skills`, `--mcp` (plus global `--json`). `task send` accepts `-p / --prompt`, `--skills`, `--mcp`, `-f / --file` (repeatable) — note **no `-a` on `send`**; the agent is fixed to whatever the task was created with. `task files` accepts `--download`, `--download-all`, `-o / --output`, `-c / --category`. No `--format`, no `--timeout`, no `--retry`.
188
+ - ❌ **Inventing flags.** `task create` accepts `-a / --agent`, `-p / --prompt`, `--skills`, `--mcp` (plus global `--json`). `task send` accepts `-p / --prompt`, `--skills`, `--mcp`, `--file` (repeatable) — note **no `-a` on `send`**; the agent is fixed to whatever the task was created with. `task files` accepts `--download`, `--download-all`, `-o / --output`, `-c / --category`. No `--format`, no `--timeout`, no `--retry`.
189
189
  - ❌ **Routing specialist work through `rush`.** If the user named a specific agent ("use the HR analytics specialist"), go to [`agent-shelf.md`](./agent-shelf.md). `rush` is the *default*, not a *fallback-for-everything*.
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/output/logger.ts","../src/version.ts","../src/util/config.ts","../src/util/auth.ts","../src/util/errors.ts","../src/util/verbosity.ts","../src/util/auth-session.ts","../src/util/retry.ts","../src/util/client.ts","../src/util/sse.ts"],"sourcesContent":["import chalk from 'chalk';\n\n/**\n * Output utilities.\n *\n * Design principle: stdout is for **content** (data the user wants to pipe/redirect).\n * Status messages (success, warn, info, dim) go to **stderr** so they don't pollute pipes.\n *\n * rush-ai task create --agent rush --prompt \"generate HTML\" --json > task.json\n * # stdout → task.json (task data)\n * # stderr → \"Success! Task xxx created.\" (status info, visible in terminal)\n */\nexport const output = {\n /** Content output → stdout. Use for data the user may pipe/redirect. */\n log(message: string): void {\n console.log(message);\n },\n\n /** Status → stderr */\n success(message: string): void {\n console.error(chalk.green('Success!'), message);\n },\n\n /** Error → stderr */\n error(message: string): void {\n console.error(chalk.red('Error:'), message);\n },\n\n /** Warning → stderr */\n warn(message: string): void {\n console.error(chalk.yellow('Warning:'), message);\n },\n\n /** Info → stderr */\n info(message: string): void {\n console.error(chalk.cyan('Info:'), message);\n },\n\n /** Dim status → stderr */\n dim(message: string): void {\n console.error(chalk.dim(message));\n },\n\n table(data: Record<string, string>[]): void {\n console.table(data);\n },\n\n /** Newline → stderr (status separator) */\n newline(): void {\n console.error();\n },\n\n link(text: string, url: string): string {\n return chalk.cyan.underline(url);\n },\n\n bold(text: string): string {\n return chalk.bold(text);\n },\n};\n","import { readFileSync } from 'node:fs';\nimport { dirname, resolve } from 'node:path';\nimport { fileURLToPath } from 'node:url';\n\n/**\n * Dynamically read version from package.json.\n *\n * Path resolution:\n * - tsup bundle: dist/index.js → __dirname = dist/ → ../package.json\n * - vitest source: src/version.ts → __dirname = src/ → ../package.json\n */\nexport function loadVersion(): string {\n const __dirname = dirname(fileURLToPath(import.meta.url));\n\n const candidates = [\n resolve(__dirname, '..', 'package.json'),\n resolve(__dirname, '..', '..', 'package.json'),\n ];\n\n for (const candidate of candidates) {\n try {\n const pkg = JSON.parse(readFileSync(candidate, 'utf-8'));\n if (pkg.name === 'rush-ai' && pkg.version) {\n return pkg.version;\n }\n } catch {\n // try next candidate\n }\n }\n console.error('[rush-ai] Warning: Could not read version from package.json');\n return '0.0.0-unknown';\n}\n\nexport const VERSION: string = loadVersion();\n","import { homedir } from 'node:os';\nimport { resolve } from 'node:path';\nimport Conf from 'conf';\n\nexport interface AuthConfig {\n token: string | null;\n expiresAt: number | null;\n refreshToken: string | null;\n /** How the token was obtained */\n method: 'cas' | 'api_key' | 'platform_token' | null;\n /** Platform Token jti (for remote revocation via DELETE /api/platform-tokens?id={tokenId}) */\n tokenId: string | null;\n /**\n * API base URL the token was issued against. Stored at login so we can\n * detect when the current profile's API URL drifts from where the token\n * came from (e.g. `config set api` pointed at a different environment).\n * `null` for tokens migrated from the v2 schema — treated as \"unknown\n * origin\", so we don't flag false positives on upgrade.\n */\n sourceUrl: string | null;\n}\n\nexport interface GlobalConfig {\n currentTeam: string | null;\n api: string;\n collectMetrics: boolean;\n}\n\nexport interface ProjectConfig {\n projectId: string | null;\n orgId: string | null;\n}\n\n// --- Profile store types ---\n\ninterface ProfiledGlobalStore {\n _version: number;\n activeProfile: string;\n profiles: Record<string, GlobalConfig>;\n}\n\ninterface ProfiledAuthStore {\n _version: number;\n [profileName: string]: AuthConfig | number; // profile entries + _version\n}\n\nconst AUTH_CONFIG_DIR = resolve(homedir(), '.rush');\nconst DEFAULT_API = 'https://rush.zhenguanyu.com';\n\nconst AUTH_DEFAULTS: AuthConfig = {\n token: null,\n expiresAt: null,\n refreshToken: null,\n method: null,\n tokenId: null,\n sourceUrl: null,\n};\n\nconst GLOBAL_DEFAULTS: GlobalConfig = {\n currentTeam: null,\n api: DEFAULT_API,\n collectMetrics: true,\n};\n\n// --- Raw stores (untyped to support migration) ---\n\nconst globalStore = new Conf<Record<string, unknown>>({\n projectName: 'rush-ai',\n cwd: AUTH_CONFIG_DIR,\n configName: 'config',\n defaults: {},\n});\n\nconst authStore = new Conf<Record<string, unknown>>({\n projectName: 'rush-ai',\n cwd: AUTH_CONFIG_DIR,\n configName: 'auth',\n defaults: {},\n});\n\n// --- Migration ---\n\nfunction migrateGlobalStoreIfNeeded(): void {\n const version = globalStore.get('_version');\n if (version === 2) return; // Already migrated\n\n // Check if this is old format (has 'api' at top level but no 'profiles')\n const hasOldFormat = globalStore.has('api') && !globalStore.has('profiles');\n const isEmpty = globalStore.size === 0;\n\n if (hasOldFormat) {\n // Migrate old flat format → profile format\n const oldConfig: GlobalConfig = {\n currentTeam: (globalStore.get('currentTeam') as string | null) ?? null,\n api: (globalStore.get('api') as string) ?? DEFAULT_API,\n collectMetrics: (globalStore.get('collectMetrics') as boolean) ?? true,\n };\n\n globalStore.clear();\n globalStore.set('_version', 2);\n globalStore.set('activeProfile', 'default');\n globalStore.set('profiles', { default: oldConfig });\n } else if (isEmpty || !globalStore.has('profiles')) {\n // Fresh install or incomplete state — initialize\n globalStore.set('_version', 2);\n if (!globalStore.has('activeProfile')) {\n globalStore.set('activeProfile', 'default');\n }\n if (!globalStore.has('profiles')) {\n globalStore.set('profiles', { default: { ...GLOBAL_DEFAULTS } });\n }\n }\n}\n\nfunction migrateAuthStoreIfNeeded(): void {\n const version = authStore.get('_version');\n if (version === 3) return;\n\n // v1 → v3: legacy flat format (`token` at top level).\n const hasOldFormat = authStore.has('token') || authStore.has('method');\n const isEmpty = authStore.size === 0;\n\n if (hasOldFormat) {\n const oldAuth: AuthConfig = {\n token: (authStore.get('token') as string | null) ?? null,\n expiresAt: (authStore.get('expiresAt') as number | null) ?? null,\n refreshToken: (authStore.get('refreshToken') as string | null) ?? null,\n method: (authStore.get('method') as AuthConfig['method']) ?? null,\n tokenId: (authStore.get('tokenId') as string | null) ?? null,\n sourceUrl: null,\n };\n\n authStore.clear();\n authStore.set('_version', 3);\n authStore.set('default', oldAuth);\n return;\n }\n\n if (isEmpty) {\n authStore.set('_version', 3);\n return;\n }\n\n // v2 → v3: profile-shaped but missing `sourceUrl`. Backfill null.\n if (version === 2) {\n for (const key of Object.keys(authStore.store)) {\n if (key === '_version') continue;\n const entry = authStore.get(key);\n if (!entry || typeof entry !== 'object') continue;\n const asAuth = entry as Record<string, unknown>;\n if (!('sourceUrl' in asAuth)) {\n authStore.set(key, { ...asAuth, sourceUrl: null });\n }\n }\n authStore.set('_version', 3);\n }\n}\n\n// Run migrations on module load\nmigrateGlobalStoreIfNeeded();\nmigrateAuthStoreIfNeeded();\n\n// --- Profile helpers ---\n\n/**\n * Get the active profile name.\n * RUSH_PROFILE env var takes precedence over stored activeProfile.\n */\nexport function getActiveProfile(): string {\n return (\n process.env.RUSH_PROFILE ??\n (globalStore.get('activeProfile') as string) ??\n 'default'\n );\n}\n\nexport function setActiveProfile(name: string): void {\n const profiles =\n (globalStore.get('profiles') as Record<string, GlobalConfig>) ?? {};\n if (!profiles[name]) {\n throw new Error(\n `Profile '${name}' does not exist. Available: ${Object.keys(profiles).join(', ')}`\n );\n }\n globalStore.set('activeProfile', name);\n}\n\nexport function listProfiles(): string[] {\n const profiles =\n (globalStore.get('profiles') as Record<string, GlobalConfig>) ?? {};\n return Object.keys(profiles);\n}\n\nexport function createProfile(\n name: string,\n config?: Partial<GlobalConfig>\n): void {\n const profiles =\n (globalStore.get('profiles') as Record<string, GlobalConfig>) ?? {};\n if (profiles[name]) {\n throw new Error(`Profile '${name}' already exists.`);\n }\n // Inherit from default profile\n const defaultConfig = profiles.default ?? GLOBAL_DEFAULTS;\n profiles[name] = { ...defaultConfig, ...config };\n globalStore.set('profiles', profiles);\n}\n\nexport function deleteProfile(name: string): void {\n if (name === 'default') {\n throw new Error(\"Cannot delete the 'default' profile.\");\n }\n const active = getActiveProfile();\n if (name === active) {\n throw new Error(\n `Cannot delete the active profile '${name}'. Switch to another profile first.`\n );\n }\n const profiles =\n (globalStore.get('profiles') as Record<string, GlobalConfig>) ?? {};\n if (!profiles[name]) {\n throw new Error(`Profile '${name}' does not exist.`);\n }\n delete profiles[name];\n globalStore.set('profiles', profiles);\n\n // Also clear auth for this profile\n authStore.delete(name);\n}\n\n// --- Auth config (profile-aware) ---\n\nexport function getAuthConfig(): AuthConfig {\n const profile = getActiveProfile();\n const profileAuth = authStore.get(profile) as AuthConfig | undefined;\n return {\n token: profileAuth?.token ?? null,\n expiresAt: profileAuth?.expiresAt ?? null,\n refreshToken: profileAuth?.refreshToken ?? null,\n method: profileAuth?.method ?? null,\n tokenId: profileAuth?.tokenId ?? null,\n sourceUrl: profileAuth?.sourceUrl ?? null,\n };\n}\n\nexport function setAuthConfig(config: Partial<AuthConfig>): void {\n const profile = getActiveProfile();\n const current = (authStore.get(profile) as AuthConfig) ?? {\n ...AUTH_DEFAULTS,\n };\n authStore.set(profile, { ...current, ...config });\n}\n\n/** Clear auth for the current profile only */\nexport function clearAuthConfig(): void {\n const profile = getActiveProfile();\n authStore.set(profile, { ...AUTH_DEFAULTS });\n}\n\n/** Clear auth for ALL profiles */\nexport function clearAllAuthConfig(): void {\n const profiles = listProfiles();\n for (const profile of profiles) {\n authStore.set(profile, { ...AUTH_DEFAULTS });\n }\n}\n\n// --- Global config (profile-aware) ---\n\nexport function getGlobalConfig(): GlobalConfig {\n const profile = getActiveProfile();\n const profiles =\n (globalStore.get('profiles') as Record<string, GlobalConfig>) ?? {};\n const profileConfig = profiles[profile] ?? GLOBAL_DEFAULTS;\n return {\n currentTeam: profileConfig.currentTeam ?? null,\n api: profileConfig.api ?? DEFAULT_API,\n collectMetrics: profileConfig.collectMetrics ?? true,\n };\n}\n\nexport function setGlobalConfig(config: Partial<GlobalConfig>): void {\n const profile = getActiveProfile();\n const profiles =\n (globalStore.get('profiles') as Record<string, GlobalConfig>) ?? {};\n const current = profiles[profile] ?? { ...GLOBAL_DEFAULTS };\n profiles[profile] = { ...current, ...config };\n globalStore.set('profiles', profiles);\n}\n\nexport function getConfigDir(): string {\n return AUTH_CONFIG_DIR;\n}\n\nexport function isLoggedIn(): boolean {\n const auth = getAuthConfig();\n if (!auth.token) return false;\n if (auth.expiresAt && Date.now() > auth.expiresAt) {\n // CAS tokens with refresh_token can still be renewed lazily by the client.\n return auth.method === 'cas' && Boolean(auth.refreshToken);\n }\n return true;\n}\n\n/** Normalize an API URL for comparison — strips trailing slashes + lowercases. */\nexport function normalizeApiUrl(url: string): string {\n return url.replace(/\\/+$/, '').toLowerCase();\n}\n\n/**\n * If the current profile's token was issued against a different API URL than\n * the profile currently points to, return both sides so the caller can prompt\n * the user to re-authenticate. Returns null when no mismatch (or when the\n * stored `sourceUrl` is null — migrated tokens with unknown origin). The\n * caller decides what to do; this function does NOT mutate or clear anything.\n *\n * @param overrideCurrentUrl use this URL instead of reading the current\n * global config. Useful when evaluating mismatch BEFORE writing a new API\n * URL in `config set`.\n */\nexport function checkAuthSourceMismatch(\n overrideCurrentUrl?: string\n): { stored: string; current: string } | null {\n const auth = getAuthConfig();\n if (!auth.token || !auth.sourceUrl) return null;\n const current = overrideCurrentUrl ?? getGlobalConfig().api;\n if (normalizeApiUrl(auth.sourceUrl) === normalizeApiUrl(current)) return null;\n return { stored: auth.sourceUrl, current };\n}\n\n/**\n * Get the config for a specific profile (for display purposes).\n */\nexport function getProfileConfig(name: string): GlobalConfig | null {\n const profiles =\n (globalStore.get('profiles') as Record<string, GlobalConfig>) ?? {};\n return profiles[name] ?? null;\n}\n\n/**\n * Get auth config for a specific profile (for display purposes).\n */\nexport function getProfileAuth(name: string): AuthConfig {\n const profileAuth = authStore.get(name) as AuthConfig | undefined;\n return {\n token: profileAuth?.token ?? null,\n expiresAt: profileAuth?.expiresAt ?? null,\n refreshToken: profileAuth?.refreshToken ?? null,\n method: profileAuth?.method ?? null,\n tokenId: profileAuth?.tokenId ?? null,\n sourceUrl: profileAuth?.sourceUrl ?? null,\n };\n}\n","import { getAuthConfig, getGlobalConfig } from './config.js';\n\nexport type AuthMethod = 'api_key' | 'cas' | 'platform_token' | null;\n\n/**\n * Determine the current authentication method.\n * Priority: RUSH_API_KEY env > stored CAS token > null\n */\nexport function getAuthMethod(): AuthMethod {\n if (process.env.RUSH_API_KEY) {\n return 'api_key';\n }\n const auth = getAuthConfig();\n if (auth.token) {\n // Use stored method if available; detect rush_sk_ prefix as fallback\n if (auth.method === 'api_key' || auth.token.startsWith('rush_sk_')) {\n return 'api_key';\n }\n if (auth.method === 'platform_token') {\n return 'platform_token';\n }\n return auth.method ?? 'cas';\n }\n return null;\n}\n\n/**\n * Get the active auth token.\n * Priority: RUSH_API_KEY env > stored token\n */\nexport function getAuthToken(): string | null {\n if (process.env.RUSH_API_KEY) {\n return process.env.RUSH_API_KEY;\n }\n const auth = getAuthConfig();\n return auth.token;\n}\n\nexport interface CasConfig {\n authorizeEndpoint: string;\n tokenEndpoint: string;\n revokeEndpoint: string;\n clientId: string;\n}\n\n/**\n * Get CAS PKCE configuration.\n * Supports env overrides for private deployments.\n */\nexport function getCasConfig(): CasConfig {\n const config = getGlobalConfig();\n const baseUrl = process.env.RUSH_API_URL ?? config.api;\n\n return {\n authorizeEndpoint:\n process.env.RUSH_CAS_AUTHORIZE_ENDPOINT ??\n `${baseUrl}/cas/oauth2/authorize`,\n tokenEndpoint:\n process.env.RUSH_CAS_TOKEN_ENDPOINT ?? `${baseUrl}/cas/oauth2/token`,\n revokeEndpoint:\n process.env.RUSH_CAS_REVOKE_ENDPOINT ?? `${baseUrl}/cas/oauth2/revoke`,\n clientId: process.env.RUSH_CAS_CLIENT_ID ?? 'rush-ai',\n };\n}\n\nexport interface Principal {\n provider: 'ldap' | 'service';\n subject: string;\n}\n\n/**\n * Build a Principal object from the current auth context.\n * M1: only ldap is supported.\n */\nexport function getPrincipal(subject: string): Principal {\n const method = getAuthMethod();\n return {\n provider: method === 'api_key' ? 'service' : 'ldap',\n subject,\n };\n}\n","export class RushError extends Error {\n public code: string;\n public meta: Record<string, unknown>;\n public exitCode: number;\n\n constructor(\n message: string,\n meta: Record<string, unknown> = {},\n code = 'RUSH_ERROR',\n exitCode = 2\n ) {\n super(message);\n this.name = 'RushError';\n this.code = code;\n this.meta = meta;\n this.exitCode = exitCode;\n }\n}\n\nexport class AuthError extends RushError {\n constructor(message = 'Not authenticated. Run `rush-ai auth login` first.') {\n super(message, {}, 'AUTH_ERROR', 3);\n this.name = 'AuthError';\n }\n}\n\nexport class TaskFailedError extends RushError {\n constructor(message: string, meta: Record<string, unknown> = {}) {\n super(message, meta, 'TASK_FAILED', 1);\n this.name = 'TaskFailedError';\n }\n}\n\n/**\n * Generate a user-friendly error message based on HTTP status.\n * Server-provided error messages take priority.\n */\nfunction friendlyMessage(status: number, serverMessage?: string): string {\n if (serverMessage) return serverMessage;\n\n switch (status) {\n case 401:\n return 'Authentication expired. Run `rush-ai auth login` to re-authenticate.';\n case 403:\n return 'Permission denied. You may not have access to this resource.';\n case 404:\n return 'Resource not found.';\n case 429:\n return 'Rate limited. The server is busy, please try again later.';\n case 502:\n case 503:\n case 504:\n return 'Service temporarily unavailable. Please try again in a moment.';\n default:\n return `Request failed with status ${status}.`;\n }\n}\n\nexport class ApiError extends RushError {\n public status: number;\n public retryAfter?: string;\n\n constructor(\n message: string,\n status: number,\n body?: string,\n retryAfter?: string\n ) {\n // Try to extract server error message from body\n let serverMessage: string | undefined;\n if (body) {\n try {\n const parsed = JSON.parse(body);\n if (parsed.error && typeof parsed.error === 'string') {\n serverMessage = parsed.error;\n }\n } catch {\n // Not JSON\n }\n }\n\n super(\n friendlyMessage(status, serverMessage),\n { status, body },\n 'API_ERROR'\n );\n this.name = 'ApiError';\n this.status = status;\n this.retryAfter = retryAfter;\n }\n}\n\nexport function isRushError(error: unknown): error is RushError {\n return error instanceof RushError;\n}\n","let _verbose = false;\nlet _debug = false;\n\nexport function setVerbosity(verbose: boolean, debug: boolean): void {\n _debug = debug;\n _verbose = verbose || debug;\n}\n\nexport const isVerbose = (): boolean => _verbose;\nexport const isDebug = (): boolean => _debug;\n","import { getAuthToken, getCasConfig } from './auth.js';\nimport { getAuthConfig, getGlobalConfig, setAuthConfig } from './config.js';\n\nconst VERIFY_PATH = '/api/skill-auth/me';\nconst REFRESH_SKEW_MS = 60_000;\nconst AUTH_REQUEST_TIMEOUT_MS = 8_000;\n\ninterface RefreshTokenResponse {\n access_token: string;\n expires_in?: number;\n refresh_token?: string;\n}\n\nexport interface AuthVerificationResult {\n valid: boolean;\n status: number | null;\n message?: string;\n}\n\nexport interface RefreshOptions {\n force?: boolean;\n refreshWindowMs?: number;\n}\n\nfunction getApiBaseUrl(): string {\n return process.env.RUSH_API_URL ?? getGlobalConfig().api;\n}\n\nfunction buildBearerHeaders(token: string): Record<string, string> {\n return {\n Authorization: `Bearer ${token}`,\n 'Content-Type': 'application/json',\n 'User-Agent': 'rush-ai/0.2.0',\n };\n}\n\nfunction shouldRefreshToken(options?: RefreshOptions): boolean {\n const auth = getAuthConfig();\n // Platform tokens don't support refresh; only CAS tokens do\n if (!auth.token || auth.method !== 'cas' || !auth.refreshToken) {\n return false;\n }\n if (options?.force) {\n return true;\n }\n if (!auth.expiresAt) {\n return false;\n }\n const refreshWindowMs = options?.refreshWindowMs ?? REFRESH_SKEW_MS;\n return Date.now() >= auth.expiresAt - refreshWindowMs;\n}\n\nexport async function refreshCasAccessToken(\n options?: RefreshOptions\n): Promise<boolean> {\n if (process.env.RUSH_API_KEY || !shouldRefreshToken(options)) {\n return false;\n }\n\n const auth = getAuthConfig();\n if (!auth.refreshToken) {\n return false;\n }\n\n const cas = getCasConfig();\n const body = new URLSearchParams({\n grant_type: 'refresh_token',\n refresh_token: auth.refreshToken,\n client_id: cas.clientId,\n }).toString();\n\n try {\n const response = await fetch(cas.tokenEndpoint, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/x-www-form-urlencoded',\n },\n body,\n signal: AbortSignal.timeout(AUTH_REQUEST_TIMEOUT_MS),\n });\n\n if (!response.ok) {\n return false;\n }\n\n const tokenData = (await response.json()) as RefreshTokenResponse;\n if (!tokenData.access_token) {\n return false;\n }\n\n const expiresAt = tokenData.expires_in\n ? Date.now() + tokenData.expires_in * 1000\n : auth.expiresAt;\n\n setAuthConfig({\n token: tokenData.access_token,\n expiresAt,\n refreshToken: tokenData.refresh_token ?? auth.refreshToken,\n method: 'cas',\n });\n\n return true;\n } catch {\n return false;\n }\n}\n\nexport async function verifyTokenOnline(\n token: string\n): Promise<AuthVerificationResult> {\n const url = `${getApiBaseUrl()}${VERIFY_PATH}`;\n\n try {\n const response = await fetch(url, {\n method: 'GET',\n headers: buildBearerHeaders(token),\n signal: AbortSignal.timeout(AUTH_REQUEST_TIMEOUT_MS),\n });\n\n if (response.ok) {\n return { valid: true, status: response.status };\n }\n\n const message = await response.text().catch(() => undefined);\n return {\n valid: false,\n status: response.status,\n message: message || `Server rejected token (${response.status})`,\n };\n } catch (error) {\n return {\n valid: false,\n status: null,\n message: `Network error: ${error instanceof Error ? error.message : 'unknown'}`,\n };\n }\n}\n\nexport async function verifyCurrentAuthSession(): Promise<AuthVerificationResult> {\n const token = getAuthToken();\n if (!token) {\n return {\n valid: false,\n status: null,\n message: 'Not authenticated',\n };\n }\n\n await refreshCasAccessToken();\n\n let activeToken = getAuthToken();\n if (!activeToken) {\n return {\n valid: false,\n status: null,\n message: 'Not authenticated',\n };\n }\n\n const result = await verifyTokenOnline(activeToken);\n if (result.valid || result.status !== 401 || process.env.RUSH_API_KEY) {\n return result;\n }\n\n const refreshed = await refreshCasAccessToken({ force: true });\n if (!refreshed) {\n return result;\n }\n\n activeToken = getAuthToken();\n if (!activeToken) {\n return result;\n }\n return verifyTokenOnline(activeToken);\n}\n\nasync function revokeToken(\n revokeEndpoint: string,\n clientId: string,\n token: string,\n tokenTypeHint: 'access_token' | 'refresh_token'\n): Promise<boolean> {\n const body = new URLSearchParams({\n token,\n token_type_hint: tokenTypeHint,\n client_id: clientId,\n }).toString();\n\n try {\n const response = await fetch(revokeEndpoint, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/x-www-form-urlencoded',\n },\n body,\n signal: AbortSignal.timeout(AUTH_REQUEST_TIMEOUT_MS),\n });\n return response.ok;\n } catch {\n return false;\n }\n}\n\nexport async function revokeCurrentSession(): Promise<boolean> {\n if (process.env.RUSH_API_KEY) {\n return false;\n }\n\n const auth = getAuthConfig();\n\n if (auth.method === 'platform_token') {\n return revokePlatformToken();\n }\n\n if (auth.method !== 'cas') {\n return false;\n }\n\n const cas = getCasConfig();\n const candidates: Array<{\n token: string;\n hint: 'access_token' | 'refresh_token';\n }> = [];\n if (auth.refreshToken) {\n candidates.push({ token: auth.refreshToken, hint: 'refresh_token' });\n }\n if (auth.token) {\n candidates.push({ token: auth.token, hint: 'access_token' });\n }\n\n if (candidates.length === 0) {\n return false;\n }\n\n let anyRevoked = false;\n for (const candidate of candidates) {\n const revoked = await revokeToken(\n cas.revokeEndpoint,\n cas.clientId,\n candidate.token,\n candidate.hint\n );\n if (revoked) {\n anyRevoked = true;\n }\n }\n\n return anyRevoked;\n}\n\n/** @deprecated Use revokeCurrentSession instead */\nexport const revokeCurrentCasSession = revokeCurrentSession;\n\nasync function revokePlatformToken(): Promise<boolean> {\n const auth = getAuthConfig();\n if (!auth.tokenId || !auth.token) {\n return false;\n }\n\n const baseUrl = getApiBaseUrl();\n const url = `${baseUrl}/api/platform-tokens?id=${encodeURIComponent(auth.tokenId)}`;\n\n try {\n const response = await fetch(url, {\n method: 'DELETE',\n headers: {\n Authorization: `Bearer ${auth.token}`,\n 'User-Agent': 'rush-ai/0.2.0',\n },\n signal: AbortSignal.timeout(AUTH_REQUEST_TIMEOUT_MS),\n });\n return response.ok;\n } catch {\n return false;\n }\n}\n","import { ApiError, RushError } from './errors.js';\n\nexport interface RetryOptions {\n /** Maximum number of retries (default: 3, total attempts = maxRetries + 1) */\n maxRetries?: number;\n /** Base delay in ms for exponential backoff (default: 1000) */\n baseDelay?: number;\n /** Maximum delay in ms (default: 30000) */\n maxDelay?: number;\n /** HTTP status codes eligible for retry (default: [429, 502, 503, 504]) */\n retryableStatuses?: number[];\n /** AbortSignal to cancel retries */\n signal?: AbortSignal;\n /** Called before each retry with attempt number (1-based) and delay in ms */\n onRetry?: (attempt: number, delayMs: number, status?: number) => void;\n}\n\n/**\n * Parse the Retry-After HTTP header value.\n * Supports both seconds (integer) and HTTP-date formats.\n * Returns delay in milliseconds, or null if unparseable.\n */\nexport function parseRetryAfter(value: string): number | null {\n // Try as integer seconds first\n const seconds = Number(value);\n if (!Number.isNaN(seconds) && seconds >= 0) {\n return seconds * 1000;\n }\n\n // Try as HTTP-date\n const date = new Date(value);\n if (!Number.isNaN(date.getTime())) {\n const delayMs = date.getTime() - Date.now();\n return delayMs > 0 ? delayMs : 0;\n }\n\n return null;\n}\n\n/**\n * Calculate delay with exponential backoff and jitter.\n */\nfunction calculateDelay(\n attempt: number,\n baseDelay: number,\n maxDelay: number\n): number {\n const exponential = baseDelay * 2 ** attempt;\n const jitter = Math.random() * baseDelay * 0.5;\n return Math.min(exponential + jitter, maxDelay);\n}\n\nfunction isRetryableError(\n error: unknown,\n retryableStatuses: number[]\n): boolean {\n // Network errors (fetch failures) are retryable\n if (error instanceof RushError && error.code === 'NETWORK_ERROR') {\n return true;\n }\n\n // API errors with retryable status codes\n if (error instanceof ApiError && retryableStatuses.includes(error.status)) {\n return true;\n }\n\n return false;\n}\n\nfunction getRetryAfterFromError(error: unknown): number | null {\n if (error instanceof ApiError && error.status === 429) {\n // Use Retry-After HTTP header (propagated via ApiError.retryAfter)\n if (error.retryAfter) {\n return parseRetryAfter(error.retryAfter);\n }\n }\n return null;\n}\n\n/**\n * Wrap an async function with retry logic using exponential backoff.\n *\n * Important: This should only be used for idempotent operations.\n * The caller (RushClient) is responsible for only wrapping GET/HEAD/DELETE.\n */\nexport async function withRetry<T>(\n fn: () => Promise<T>,\n options: RetryOptions = {}\n): Promise<T> {\n const {\n maxRetries = 3,\n baseDelay = 1000,\n maxDelay = 30_000,\n retryableStatuses = [429, 502, 503, 504],\n signal,\n onRetry,\n } = options;\n\n let lastError: unknown;\n\n for (let attempt = 0; attempt <= maxRetries; attempt++) {\n // Check abort before each attempt\n if (signal?.aborted) {\n throw lastError ?? new RushError('Request aborted', {}, 'ABORT_ERROR');\n }\n\n try {\n return await fn();\n } catch (error) {\n lastError = error;\n\n // Don't retry if this is the last attempt\n if (attempt >= maxRetries) {\n throw error;\n }\n\n // Don't retry non-retryable errors\n if (!isRetryableError(error, retryableStatuses)) {\n throw error;\n }\n\n // Check abort before waiting\n if (signal?.aborted) {\n throw error;\n }\n\n // Calculate delay: use Retry-After if available (for 429), otherwise backoff\n let delayMs: number;\n const retryAfterMs = getRetryAfterFromError(error);\n if (retryAfterMs !== null) {\n // Cap Retry-After at 120 seconds\n delayMs = Math.min(retryAfterMs, 120_000);\n } else {\n delayMs = calculateDelay(attempt, baseDelay, maxDelay);\n }\n\n const status = error instanceof ApiError ? error.status : undefined;\n onRetry?.(attempt + 1, delayMs, status);\n\n // Wait with abort support\n await new Promise<void>((resolve, reject) => {\n const timer = setTimeout(resolve, delayMs);\n if (signal) {\n const onAbort = () => {\n clearTimeout(timer);\n reject(lastError);\n };\n signal.addEventListener('abort', onAbort, { once: true });\n // Clean up listener after timer fires\n const origResolve = resolve;\n setTimeout(() => {\n signal.removeEventListener('abort', onAbort);\n origResolve();\n }, delayMs);\n }\n });\n }\n }\n\n // Should never reach here, but TypeScript needs it\n throw lastError;\n}\n","import { output } from '../output/logger.js';\nimport { VERSION } from '../version.js';\nimport { getAuthToken } from './auth.js';\nimport { refreshCasAccessToken } from './auth-session.js';\nimport { getAuthConfig, getGlobalConfig } from './config.js';\nimport { ApiError, RushError } from './errors.js';\nimport { withRetry } from './retry.js';\nimport { isDebug, isVerbose } from './verbosity.js';\n\nconst SENSITIVE_HEADERS = [\n 'authorization',\n 'cookie',\n 'set-cookie',\n 'x-api-key',\n];\n\nfunction maskSensitiveHeaders(headers: Headers): Record<string, string> {\n const result: Record<string, string> = {};\n headers.forEach((value, key) => {\n result[key] = SENSITIVE_HEADERS.includes(key.toLowerCase())\n ? '[REDACTED]'\n : value;\n });\n return result;\n}\n\nexport interface FetchOptions extends RequestInit {\n json?: boolean;\n}\n\nexport interface ApiResponse<T = unknown> {\n ok: boolean;\n status: number;\n data: T;\n}\n\nexport interface ApiErrorBody {\n error: string;\n code: string;\n retryable: boolean;\n}\n\nexport class RushClient {\n private baseUrl: string;\n\n constructor() {\n const config = getGlobalConfig();\n const raw = process.env.RUSH_API_URL ?? config.api;\n this.baseUrl = raw.replace(/\\/+$/, '');\n }\n\n private async getHeaders(): Promise<Record<string, string>> {\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n 'User-Agent': `rush-ai/${VERSION}`,\n };\n\n if (!process.env.RUSH_API_KEY) {\n await refreshCasAccessToken();\n }\n\n const token = getAuthToken();\n if (token) {\n // Both CAS token and service account API key (rush_sk_*) use Bearer.\n // Backend distinguishes by the rush_sk_ prefix.\n headers.Authorization = `Bearer ${token}`;\n }\n\n // Test mode: skip CAS auth in non-production environments\n if (process.env.RUSH_TEST_MODE === 'integration-test') {\n headers['X-Test-Mode'] = 'integration-test';\n }\n\n return headers;\n }\n\n /**\n * Merge default headers with per-request overrides. A `null` override value\n * drops the default entirely — used by multipart POSTs that need fetch to\n * synthesize its own Content-Type with a boundary. An empty string stays as\n * an empty-value header so callers can still send one intentionally.\n */\n private mergeHeaders(\n base: Record<string, string>,\n overrides: Record<string, string | null>\n ): Record<string, string> {\n const merged: Record<string, string> = { ...base };\n for (const [key, value] of Object.entries(overrides)) {\n if (value === null) {\n delete merged[key];\n } else {\n merged[key] = value;\n }\n }\n return merged;\n }\n\n private async performRequest(\n url: string,\n options: RequestInit,\n retryOnUnauthorized = true\n ): Promise<Response> {\n // Override headers may use `null` as a sentinel to drop a default\n // (see mergeHeaders). The public fetch signature doesn't know about this,\n // so we cast narrowly here.\n const requestHeaders =\n (options.headers as Record<string, string | null>) ?? {};\n const headers = await this.getHeaders();\n\n try {\n const response = await fetch(url, {\n ...options,\n headers: this.mergeHeaders(headers, requestHeaders),\n });\n\n if (\n response.status === 401 &&\n retryOnUnauthorized &&\n !process.env.RUSH_API_KEY\n ) {\n const auth = getAuthConfig();\n const canRefresh = auth.method === 'cas' && Boolean(auth.refreshToken);\n if (canRefresh && (await refreshCasAccessToken({ force: true }))) {\n const retryHeaders = await this.getHeaders();\n return await fetch(url, {\n ...options,\n headers: this.mergeHeaders(retryHeaders, requestHeaders),\n });\n }\n }\n\n return response;\n } catch (err) {\n throw new RushError(\n `Network error: ${err instanceof Error ? err.message : 'Failed to connect'}`,\n { url },\n 'NETWORK_ERROR'\n );\n }\n }\n\n /** Idempotent HTTP methods eligible for automatic retry */\n private static readonly RETRYABLE_METHODS = ['GET', 'HEAD', 'DELETE'];\n\n /**\n * Internal fetch with response parsing and error handling (no retry).\n */\n private async _doFetch<T = unknown>(\n path: string,\n options: FetchOptions = {}\n ): Promise<ApiResponse<T>> {\n const { json = true, ...fetchOptions } = options;\n const url = `${this.baseUrl}${path}`;\n const method = (fetchOptions.method ?? 'GET').toUpperCase();\n const startTime = Date.now();\n\n if (isVerbose()) {\n output.dim(`→ ${method} ${url}`);\n }\n\n const response = await this.performRequest(url, fetchOptions);\n\n if (isVerbose()) {\n output.dim(\n `← ${response.status} ${response.statusText} (${Date.now() - startTime}ms)`\n );\n }\n\n if (isDebug()) {\n output.dim(\n ` Response headers: ${JSON.stringify(maskSensitiveHeaders(response.headers))}`\n );\n }\n\n if (!response.ok) {\n const errorBody = await response.text().catch(() => 'Unknown error');\n const retryAfter = response.headers.get('retry-after') ?? undefined;\n\n throw new ApiError(\n `API request failed: ${response.status} ${response.statusText}`,\n response.status,\n errorBody,\n retryAfter\n );\n }\n\n const data = json\n ? ((await response.json()) as T)\n : ((await response.text()) as T);\n\n return {\n ok: true,\n status: response.status,\n data,\n };\n }\n\n /**\n * Fetch with response parsing, error handling, and automatic retry\n * for idempotent methods (GET, HEAD, DELETE).\n */\n async fetch<T = unknown>(\n path: string,\n options: FetchOptions = {}\n ): Promise<ApiResponse<T>> {\n const method = (options.method ?? 'GET').toUpperCase();\n const isRetryable = RushClient.RETRYABLE_METHODS.includes(method);\n\n if (!isRetryable) {\n return this._doFetch<T>(path, options);\n }\n\n return withRetry(() => this._doFetch<T>(path, options), {\n signal: options.signal ?? undefined,\n onRetry: (attempt, delayMs, status) => {\n const statusInfo = status ? ` (${status})` : '';\n console.error(\n `\\u27F3 Retrying ${method} ${path}${statusInfo} (attempt ${attempt}) in ${(delayMs / 1000).toFixed(1)}s...`\n );\n },\n });\n }\n\n /**\n * Raw fetch for streaming (SSE) responses.\n * Returns the raw Response object.\n */\n async fetchRaw(path: string, options: RequestInit = {}): Promise<Response> {\n const url = `${this.baseUrl}${path}`;\n\n const response = await this.performRequest(url, options);\n\n if (!response.ok) {\n const errorBody = await response.text().catch(() => 'Unknown error');\n throw new ApiError(\n `API request failed: ${response.status} ${response.statusText}`,\n response.status,\n errorBody\n );\n }\n\n return response;\n }\n\n async get<T = unknown>(path: string): Promise<ApiResponse<T>> {\n return this.fetch<T>(path, { method: 'GET' });\n }\n\n async post<T = unknown>(\n path: string,\n body?: unknown\n ): Promise<ApiResponse<T>> {\n return this.fetch<T>(path, {\n method: 'POST',\n body: body ? JSON.stringify(body) : undefined,\n });\n }\n\n /**\n * POST multipart/form-data. The default `Content-Type: application/json`\n * must be removed so fetch can set its own multipart boundary — passing\n * `null` as the header value tells mergeHeaders to drop the key.\n */\n async postFormData<T = unknown>(\n path: string,\n formData: FormData\n ): Promise<ApiResponse<T>> {\n return this._doFetch<T>(path, {\n method: 'POST',\n body: formData,\n // Cast: RequestInit.headers doesn't include null; mergeHeaders handles it.\n headers: { 'Content-Type': null } as unknown as HeadersInit,\n });\n }\n\n async put<T = unknown>(\n path: string,\n body?: unknown\n ): Promise<ApiResponse<T>> {\n return this.fetch<T>(path, {\n method: 'PUT',\n body: body ? JSON.stringify(body) : undefined,\n });\n }\n\n async delete<T = unknown>(path: string): Promise<ApiResponse<T>> {\n return this.fetch<T>(path, { method: 'DELETE' });\n }\n}\n\nexport function createClient(): RushClient {\n return new RushClient();\n}\n","/**\n * SSE (Server-Sent Events) line-buffered parser.\n * Handles events split across multiple chunks.\n */\nexport interface SSEEvent {\n type: string;\n data: string;\n}\n\nexport function createSSEParser(\n onEvent: (event: SSEEvent) => void,\n onDone?: () => void\n) {\n let buffer = '';\n\n return {\n feed(chunk: string): void {\n buffer += chunk;\n const lines = buffer.split('\\n');\n // Keep the last (possibly incomplete) line in the buffer\n buffer = lines.pop() ?? '';\n\n for (const line of lines) {\n if (line.startsWith('data: ')) {\n const data = line.slice(6);\n if (data === '[DONE]') {\n onDone?.();\n return;\n }\n try {\n const parsed = JSON.parse(data);\n onEvent({\n type: parsed.type ?? 'unknown',\n data:\n typeof parsed.data === 'string'\n ? parsed.data\n : JSON.stringify(parsed),\n });\n } catch {\n // Non-JSON SSE data\n onEvent({ type: 'raw', data });\n }\n }\n }\n },\n flush(): void {\n // Process any remaining buffered data\n if (buffer.startsWith('data: ')) {\n const data = buffer.slice(6);\n if (data !== '[DONE]') {\n try {\n const parsed = JSON.parse(data);\n onEvent({\n type: parsed.type ?? 'unknown',\n data:\n typeof parsed.data === 'string'\n ? parsed.data\n : JSON.stringify(parsed),\n });\n } catch {\n onEvent({ type: 'raw', data });\n }\n }\n }\n buffer = '';\n },\n };\n}\n\n/**\n * Consume an SSE ReadableStream with proper cross-chunk buffering.\n */\nexport async function consumeSSEStream(\n body: ReadableStream<Uint8Array>,\n onEvent: (event: SSEEvent) => void,\n onDone?: () => void\n): Promise<void> {\n const reader = body.getReader();\n const decoder = new TextDecoder();\n const parser = createSSEParser(onEvent, onDone);\n\n for (;;) {\n const { done, value } = await reader.read();\n if (done) break;\n parser.feed(decoder.decode(value, { stream: true }));\n }\n parser.flush();\n}\n\nexport interface SSEReconnectOptions {\n /** Maximum number of reconnection attempts (default: 5) */\n maxReconnects?: number;\n /** Initial reconnection delay in ms (default: 1000) */\n reconnectDelay?: number;\n /** AbortSignal to cancel the stream and reconnections */\n signal?: AbortSignal;\n /** Called before each reconnection attempt */\n onReconnect?: (attempt: number) => void;\n /**\n * Determines if an event represents a terminal state.\n * When this returns true, the stream stops and no reconnection occurs.\n */\n isTerminal?: (event: SSEEvent) => boolean;\n}\n\n/**\n * Consume an SSE stream with automatic reconnection and event deduplication.\n *\n * Key behaviors:\n * - [DONE] does NOT automatically stop the stream. Only `isTerminal(event)` stops it.\n * - If [DONE] is received without a terminal event, reconnection is triggered\n * (e.g., server 5-minute SSE connection lifetime timeout).\n * - On reconnection, the server replays all historical events from epoch.\n * Client-side deduplication skips already-seen events using an event counter.\n *\n * @param connectFn - Factory that creates a new SSE stream (called on each reconnect)\n * @param onEvent - Event handler (only called for new, non-duplicate events)\n * @param options - Reconnection options\n */\nexport async function consumeSSEStreamWithReconnect(\n connectFn: () => Promise<ReadableStream<Uint8Array>>,\n onEvent: (event: SSEEvent) => void,\n options: SSEReconnectOptions = {}\n): Promise<void> {\n const {\n maxReconnects = 5,\n reconnectDelay = 1000,\n signal,\n onReconnect,\n isTerminal,\n } = options;\n\n let emittedEventCount = 0;\n let reconnectAttempts = 0;\n let terminalReached = false;\n\n while (!terminalReached) {\n if (signal?.aborted) return;\n\n let receivedDone = false;\n let currentEventIndex = 0;\n\n try {\n const stream = await connectFn();\n const reader = stream.getReader();\n const decoder = new TextDecoder();\n\n // Note: We do NOT reset reconnectAttempts here.\n // For [DONE]+running scenarios (server 5-min timeout), each reconnect\n // should count toward the limit. The counter only resets after the\n // function is called fresh.\n\n const parser = createSSEParser(\n (event) => {\n currentEventIndex++;\n\n // Dedup: skip events we've already emitted in previous connections\n if (currentEventIndex <= emittedEventCount) {\n // Still check for terminal even on dedup'd events\n if (isTerminal?.(event)) {\n terminalReached = true;\n }\n return;\n }\n\n emittedEventCount++;\n onEvent(event);\n\n if (isTerminal?.(event)) {\n terminalReached = true;\n }\n },\n () => {\n receivedDone = true;\n }\n );\n\n for (;;) {\n if (signal?.aborted || terminalReached) {\n reader.cancel().catch(() => {});\n return;\n }\n\n const { done, value } = await reader.read();\n if (done) break;\n parser.feed(decoder.decode(value, { stream: true }));\n\n if (terminalReached) {\n reader.cancel().catch(() => {});\n return;\n }\n }\n parser.flush();\n } catch {\n // Stream error — will attempt reconnect below\n if (signal?.aborted || terminalReached) return;\n }\n\n // If terminal was reached, we're done\n if (terminalReached) return;\n\n // If [DONE] was received AND we already got a terminal event, stop\n // (This shouldn't happen because terminalReached would be true, but safety check)\n if (receivedDone && terminalReached) return;\n\n // Otherwise, reconnect: [DONE] without terminal = server timeout, or stream error\n reconnectAttempts++;\n if (reconnectAttempts > maxReconnects) {\n throw new Error(\n `SSE reconnection failed after ${maxReconnects} attempts`\n );\n }\n\n if (signal?.aborted) return;\n\n onReconnect?.(reconnectAttempts);\n\n // Exponential backoff for reconnection\n const delay = Math.min(\n reconnectDelay * 2 ** (reconnectAttempts - 1),\n 30_000\n );\n\n await new Promise<void>((resolve) => {\n const timer = setTimeout(resolve, delay);\n if (signal) {\n const onAbort = () => {\n clearTimeout(timer);\n resolve();\n };\n signal.addEventListener('abort', onAbort, { once: true });\n }\n });\n }\n}\n"],"mappings":"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","names":["resolve","resolve","resolve"]}