feat: add slash command functionality to agent services

This commit is contained in:
Vaayne 2025-09-27 10:26:48 +08:00
parent 8018ac1a97
commit ae9e12b276
4 changed files with 45 additions and 3 deletions

View File

@ -2,7 +2,7 @@ import { type Client, createClient } from '@libsql/client'
import { loggerService } from '@logger' import { loggerService } from '@logger'
import { mcpApiService } from '@main/apiServer/services/mcp' import { mcpApiService } from '@main/apiServer/services/mcp'
import { ModelValidationError, validateModelId } from '@main/apiServer/utils' 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 { drizzle, type LibSQLDatabase } from 'drizzle-orm/libsql'
import fs from 'fs' import fs from 'fs'
import path from 'path' import path from 'path'
@ -11,6 +11,7 @@ import { MigrationService } from './database/MigrationService'
import * as schema from './database/schema' import * as schema from './database/schema'
import { dbPath } from './drizzle.config' import { dbPath } from './drizzle.config'
import { AgentModelField, AgentModelValidationError } from './errors' import { AgentModelField, AgentModelValidationError } from './errors'
import { builtinSlashCommands } from './services/claudecode/commands'
import { builtinTools } from './services/claudecode/tools' import { builtinTools } from './services/claudecode/tools'
const logger = loggerService.withContext('BaseService') const logger = loggerService.withContext('BaseService')
@ -76,6 +77,13 @@ export abstract class BaseService {
return tools return tools
} }
public async listSlashCommands(agentType: AgentType): Promise<SlashCommand[]> {
if (agentType === 'claude-code') {
return builtinSlashCommands
}
return []
}
private static async performInitialization(): Promise<void> { private static async performInitialization(): Promise<void> {
const maxRetries = 3 const maxRetries = 3
let lastError: Error let lastError: Error

View File

@ -110,6 +110,7 @@ export class SessionService extends BaseService {
const session = this.deserializeJsonFields(result[0]) as GetAgentSessionResponse const session = this.deserializeJsonFields(result[0]) as GetAgentSessionResponse
session.tools = await this.listMcpTools(session.agent_type, session.mcps) session.tools = await this.listMcpTools(session.agent_type, session.mcps)
session.slash_commands = await this.listSlashCommands(session.agent_type)
return session return session
} }

View File

@ -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' }
]

View File

@ -42,11 +42,18 @@ export const ToolSchema = z.object({
export type Tool = z.infer<typeof ToolSchema> export type Tool = z.infer<typeof ToolSchema>
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<typeof SlashCommandSchema>
// ------------------ Agent configuration & base schema ------------------ // ------------------ Agent configuration & base schema ------------------
export const AgentConfigurationSchema = z export const AgentConfigurationSchema = z
.object({ .object({
avatar: z.string().optional(), // URL or path to avatar image 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 // https://docs.claude.com/en/docs/claude-code/sdk/sdk-permissions#mode-specific-behaviors
permission_mode: PermissionModeSchema.default('default'), // Permission mode, default to 'default' permission_mode: PermissionModeSchema.default('default'), // Permission mode, default to 'default'
@ -255,7 +262,8 @@ export interface UpdateSessionRequest extends Partial<AgentBase> {}
export const GetAgentSessionResponseSchema = AgentSessionEntitySchema.extend({ export const GetAgentSessionResponseSchema = AgentSessionEntitySchema.extend({
tools: z.array(ToolSchema).optional(), // All tools available to the session (including built-in and custom) 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<typeof GetAgentSessionResponseSchema> export type GetAgentSessionResponse = z.infer<typeof GetAgentSessionResponseSchema>