diff --git a/src/main/services/agents/BaseService.ts b/src/main/services/agents/BaseService.ts index 3f0282d3e4..73a1a1828a 100644 --- a/src/main/services/agents/BaseService.ts +++ b/src/main/services/agents/BaseService.ts @@ -2,7 +2,7 @@ import { type Client, createClient } from '@libsql/client' import { loggerService } from '@logger' import { mcpApiService } from '@main/apiServer/services/mcp' import { ModelValidationError, validateModelId } from '@main/apiServer/utils' -import { AgentType, MCPTool, objectKeys, Provider, Tool } from '@types' +import { AgentType, MCPTool, objectKeys, Provider, SlashCommand, Tool } from '@types' import { drizzle, type LibSQLDatabase } from 'drizzle-orm/libsql' import fs from 'fs' import path from 'path' @@ -11,6 +11,7 @@ import { MigrationService } from './database/MigrationService' import * as schema from './database/schema' import { dbPath } from './drizzle.config' import { AgentModelField, AgentModelValidationError } from './errors' +import { builtinSlashCommands } from './services/claudecode/commands' import { builtinTools } from './services/claudecode/tools' const logger = loggerService.withContext('BaseService') @@ -76,6 +77,13 @@ export abstract class BaseService { return tools } + public async listSlashCommands(agentType: AgentType): Promise { + if (agentType === 'claude-code') { + return builtinSlashCommands + } + return [] + } + private static async performInitialization(): Promise { const maxRetries = 3 let lastError: Error diff --git a/src/main/services/agents/services/SessionService.ts b/src/main/services/agents/services/SessionService.ts index fae7c136fc..5fcb60600d 100644 --- a/src/main/services/agents/services/SessionService.ts +++ b/src/main/services/agents/services/SessionService.ts @@ -110,6 +110,7 @@ export class SessionService extends BaseService { const session = this.deserializeJsonFields(result[0]) as GetAgentSessionResponse session.tools = await this.listMcpTools(session.agent_type, session.mcps) + session.slash_commands = await this.listSlashCommands(session.agent_type) return session } diff --git a/src/main/services/agents/services/claudecode/commands.ts b/src/main/services/agents/services/claudecode/commands.ts new file mode 100644 index 0000000000..ce90e0978a --- /dev/null +++ b/src/main/services/agents/services/claudecode/commands.ts @@ -0,0 +1,25 @@ +import { SlashCommand } from '@types' + +export const builtinSlashCommands: SlashCommand[] = [ + { command: '/add-dir', description: 'Add additional working directories' }, + { command: '/agents', description: 'Manage custom AI subagents for specialized tasks' }, + { command: '/bug', description: 'Report bugs (sends conversation to Anthropic)' }, + { command: '/clear', description: 'Clear conversation history' }, + { command: '/compact', description: 'Compact conversation with optional focus instructions' }, + { command: '/config', description: 'View/modify configuration' }, + { command: '/cost', description: 'Show token usage statistics' }, + { command: '/doctor', description: 'Checks the health of your Claude Code installation' }, + { command: '/help', description: 'Get usage help' }, + { command: '/init', description: 'Initialize project with CLAUDE.md guide' }, + { command: '/login', description: 'Switch Anthropic accounts' }, + { command: '/logout', description: 'Sign out from your Anthropic account' }, + { command: '/mcp', description: 'Manage MCP server connections and OAuth authentication' }, + { command: '/memory', description: 'Edit CLAUDE.md memory files' }, + { command: '/model', description: 'Select or change the AI model' }, + { command: '/permissions', description: 'View or update permissions' }, + { command: '/pr_comments', description: 'View pull request comments' }, + { command: '/review', description: 'Request code review' }, + { command: '/status', description: 'View account and system statuses' }, + { command: '/terminal-setup', description: 'Install Shift+Enter key binding for newlines (iTerm2 and VSCode only)' }, + { command: '/vim', description: 'Enter vim mode for alternating insert and command modes' } +] diff --git a/src/renderer/src/types/agent.ts b/src/renderer/src/types/agent.ts index eecce7dc33..126584f1e4 100644 --- a/src/renderer/src/types/agent.ts +++ b/src/renderer/src/types/agent.ts @@ -42,11 +42,18 @@ export const ToolSchema = z.object({ export type Tool = z.infer +export const SlashCommandSchema = z.object({ + command: z.string(), // e.g. '/status' + description: z.string().optional() // e.g. 'Show help information' +}) + +export type SlashCommand = z.infer + // ------------------ Agent configuration & base schema ------------------ export const AgentConfigurationSchema = z .object({ avatar: z.string().optional(), // URL or path to avatar image - slash_commands: z.array(z.string()).optional(), // Array of slash commands to trigger the agent + slash_commands: z.array(z.string()).optional(), // Array of slash commands to trigger the agent, this is from agent init response // https://docs.claude.com/en/docs/claude-code/sdk/sdk-permissions#mode-specific-behaviors permission_mode: PermissionModeSchema.default('default'), // Permission mode, default to 'default' @@ -255,7 +262,8 @@ export interface UpdateSessionRequest extends Partial {} export const GetAgentSessionResponseSchema = AgentSessionEntitySchema.extend({ tools: z.array(ToolSchema).optional(), // All tools available to the session (including built-in and custom) - messages: z.array(AgentSessionMessageEntitySchema).optional() // Messages in the session + messages: z.array(AgentSessionMessageEntitySchema).optional(), // Messages in the session + slash_commands: z.array(SlashCommandSchema).optional() // Array of slash commands to trigger the agent }) export type GetAgentSessionResponse = z.infer