Skip to content

Commit 94b375b

Browse files
committed
create handleSlashCommands router
1 parent 653228c commit 94b375b

File tree

6 files changed

+188
-98
lines changed

6 files changed

+188
-98
lines changed

cli/src/chat.tsx

Lines changed: 44 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
import { TextAttributes } from '@opentui/core'
2-
import { useRenderer, useTerminalDimensions } from '@opentui/react'
31
import os from 'os'
42
import path from 'path'
3+
4+
import { useRenderer, useTerminalDimensions } from '@opentui/react'
55
import React, {
66
type ReactNode,
77
useCallback,
@@ -15,14 +15,14 @@ import { useShallow } from 'zustand/react/shallow'
1515

1616
import { AgentModeToggle } from './components/agent-mode-toggle'
1717
import { LoginModal } from './components/login-modal'
18-
import { TerminalLink } from './components/terminal-link'
1918
import {
2019
MultilineInput,
2120
type MultilineInputHandle,
2221
} from './components/multiline-input'
2322
import { Separator } from './components/separator'
2423
import { StatusIndicator, useHasStatus } from './components/status-indicator'
2524
import { SuggestionMenu } from './components/suggestion-menu'
25+
import { TerminalLink } from './components/terminal-link'
2626
import { SLASH_COMMANDS } from './data/slash-commands'
2727
import { useAgentValidation } from './hooks/use-agent-validation'
2828
import { useAuthQuery, useLogoutMutation } from './hooks/use-auth-query'
@@ -35,30 +35,32 @@ import { useMessageQueue } from './hooks/use-message-queue'
3535
import { useMessageRenderer } from './hooks/use-message-renderer'
3636
import { useChatScrollbox } from './hooks/use-scroll-management'
3737
import { useSendMessage } from './hooks/use-send-message'
38-
import type { SendMessageTimerEvent } from './hooks/use-send-message'
3938
import { useSuggestionEngine } from './hooks/use-suggestion-engine'
4039
import { useSystemThemeDetector } from './hooks/use-system-theme-detector'
4140
import { useChatStore } from './state/chat-store'
4241
import { flushAnalytics } from './utils/analytics'
4342
import { getUserCredentials } from './utils/auth'
4443
import { createChatScrollAcceleration } from './utils/chat-scroll-accel'
44+
import { createValidationErrorBlocks } from './utils/create-validation-error-blocks'
4545
import { formatQueuedPreview } from './utils/helpers'
4646
import {
4747
loadLocalAgents,
4848
type LocalAgentInfo,
4949
} from './utils/local-agent-registry'
5050
import { logger } from './utils/logger'
5151
import { buildMessageTree } from './utils/message-tree-utils'
52+
import { openFileAtPath } from './utils/open-file'
53+
import { handleSlashCommands } from './utils/slash-commands'
5254
import {
5355
chatThemes,
5456
createMarkdownPalette,
5557
type ChatTheme,
5658
} from './utils/theme-system'
57-
import { openFileAtPath } from './utils/open-file'
5859
import { formatValidationError } from './utils/validation-error-formatting'
59-
import { createValidationErrorBlocks } from './utils/create-validation-error-blocks'
6060

61+
import type { SendMessageTimerEvent } from './hooks/use-send-message'
6162
import type { User } from './utils/auth'
63+
import type { AgentMode } from './utils/constants'
6264
import type { ToolName } from '@codebuff/sdk'
6365
import type { ScrollBoxRenderable } from '@opentui/core'
6466

@@ -788,7 +790,7 @@ export const App = ({
788790

789791
const sendMessageRef =
790792
useRef<
791-
(content: string, params: { agentMode: 'FAST' | 'MAX' }) => Promise<void>
793+
(content: string, params: { agentMode: AgentMode }) => Promise<void>
792794
>()
793795

794796
const {
@@ -885,86 +887,41 @@ export const App = ({
885887
mainAgentTimer,
886888
)
887889

888-
const handleSubmit = useCallback(() => {
889-
const trimmed = inputValue.trim()
890-
if (!trimmed) return
891-
892-
const normalized = trimmed.startsWith('/') ? trimmed.slice(1) : trimmed
893-
const cmd = normalized.split(/\s+/)[0].toLowerCase()
894-
if (cmd === 'login' || cmd === 'signin') {
895-
const msg = {
896-
id: `sys-${Date.now()}`,
897-
variant: 'ai' as const,
898-
content: "You're already in the app. Use /logout to switch accounts.",
899-
timestamp: new Date().toISOString(),
900-
}
901-
setMessages((prev) => [...prev, msg])
902-
setInputValue('')
903-
return
904-
}
905-
if (cmd === 'logout' || cmd === 'signout') {
906-
abortControllerRef.current?.abort()
907-
stopStreaming()
908-
setCanProcessQueue(false)
909-
910-
logoutMutation.mutate(undefined, {
911-
onSettled: () => {
912-
const msg = {
913-
id: `sys-${Date.now()}`,
914-
variant: 'ai' as const,
915-
content: 'Logged out.',
916-
timestamp: new Date().toISOString(),
917-
}
918-
setMessages((prev) => [...prev, msg])
919-
setInputValue('')
920-
setTimeout(() => {
921-
setUser(null)
922-
setIsAuthenticated(false)
923-
}, 300)
924-
},
925-
})
926-
return
927-
}
928-
929-
if (cmd === 'exit' || cmd === 'quit') {
930-
abortControllerRef.current?.abort()
931-
stopStreaming()
932-
setCanProcessQueue(false)
933-
setInputValue('')
934-
handleCtrlC()
935-
return
936-
}
937-
938-
saveToHistory(trimmed)
939-
setInputValue('')
940-
941-
if (
942-
isStreaming ||
943-
streamMessageIdRef.current ||
944-
isChainInProgressRef.current
945-
) {
946-
addToQueue(trimmed)
947-
setInputFocused(true)
948-
inputRef.current?.focus()
949-
return
950-
}
951-
952-
sendMessage(trimmed, { agentMode })
953-
954-
setTimeout(() => {
955-
scrollToLatest()
956-
}, 0)
957-
}, [
958-
inputValue,
959-
isStreaming,
960-
sendMessage,
961-
saveToHistory,
962-
addToQueue,
963-
streamMessageIdRef,
964-
isChainInProgressRef,
965-
scrollToLatest,
966-
handleCtrlC,
967-
])
890+
const handleSubmit = useCallback(
891+
() => handleSlashCommands({
892+
abortControllerRef,
893+
agentMode,
894+
inputRef,
895+
inputValue,
896+
isChainInProgressRef,
897+
isStreaming,
898+
logoutMutation,
899+
streamMessageIdRef,
900+
addToQueue,
901+
handleCtrlC,
902+
saveToHistory,
903+
scrollToLatest,
904+
sendMessage,
905+
setCanProcessQueue,
906+
setInputFocused,
907+
setInputValue,
908+
setIsAuthenticated,
909+
setMessages,
910+
setUser,
911+
stopStreaming,
912+
}),
913+
[
914+
inputValue,
915+
isStreaming,
916+
sendMessage,
917+
saveToHistory,
918+
addToQueue,
919+
streamMessageIdRef,
920+
isChainInProgressRef,
921+
scrollToLatest,
922+
handleCtrlC,
923+
],
924+
)
968925

969926
useKeyboardHandlers({
970927
isStreaming,

cli/src/components/agent-mode-toggle.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
1+
import { AgentMode } from '../utils/constants'
12
import type { ChatTheme } from '../utils/theme-system'
23

34
export const AgentModeToggle = ({
45
mode,
56
theme,
67
onToggle,
78
}: {
8-
mode: 'FAST' | 'MAX'
9+
mode: AgentMode,
910
theme: ChatTheme
1011
onToggle: () => void
1112
}) => {

cli/src/hooks/use-send-message.ts

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,17 @@ import { useCallback, useEffect, useRef } from 'react'
22

33
import { getCodebuffClient, formatToolOutput } from '../utils/codebuff-client'
44
import { shouldHideAgent } from '../utils/constants'
5+
import { createValidationErrorBlocks } from '../utils/create-validation-error-blocks'
56
import { formatTimestamp } from '../utils/helpers'
67
import { loadAgentDefinitions } from '../utils/load-agent-definitions'
7-
import { logger } from '../utils/logger'
88
import { getLoadedAgentsData } from '../utils/local-agent-registry'
9-
import { createValidationErrorBlocks } from '../utils/create-validation-error-blocks'
9+
import { logger } from '../utils/logger'
1010

1111
import type { ChatMessage, ContentBlock } from '../chat'
12+
import type { ElapsedTimeTracker } from './use-elapsed-time'
13+
import type { AgentMode } from '../utils/constants'
1214
import type { AgentDefinition, ToolName } from '@codebuff/sdk'
1315
import type { SetStateAction } from 'react'
14-
import type { ElapsedTimeTracker } from './use-elapsed-time'
1516

1617
const hiddenToolNames = new Set<ToolName | 'spawn_agent_inline'>([
1718
'spawn_agent_inline',
@@ -350,7 +351,7 @@ export const useSendMessage = ({
350351
}, [flushPendingUpdates])
351352

352353
const sendMessage = useCallback(
353-
async (content: string, params: { agentMode: 'FAST' | 'MAX' }) => {
354+
async (content: string, params: { agentMode: AgentMode }) => {
354355
const { agentMode } = params
355356
const timestamp = formatTimestamp()
356357

@@ -410,7 +411,10 @@ export const useSendMessage = ({
410411
return
411412
}
412413
} catch (error) {
413-
logger.error({ error }, 'Validation before message send failed with exception')
414+
logger.error(
415+
{ error },
416+
'Validation before message send failed with exception',
417+
)
414418

415419
const errorMessage: ChatMessage = {
416420
id: `error-${Date.now()}`,
@@ -1420,7 +1424,8 @@ export const useSendMessage = ({
14201424

14211425
const elapsedMs = timerResult?.elapsedMs ?? 0
14221426
const elapsedSeconds = Math.floor(elapsedMs / 1000)
1423-
const completionTime = elapsedSeconds > 0 ? `${elapsedSeconds}s` : undefined
1427+
const completionTime =
1428+
elapsedSeconds > 0 ? `${elapsedSeconds}s` : undefined
14241429

14251430
applyMessageUpdate((prev) =>
14261431
prev.map((msg) =>

cli/src/state/chat-store.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,8 @@ import { enableMapSet } from 'immer'
22
import { create } from 'zustand'
33
import { immer } from 'zustand/middleware/immer'
44

5-
import { formatTimestamp } from '../utils/helpers'
6-
75
import type { ChatMessage } from '../chat'
6+
import type { AgentMode } from '../utils/constants'
87

98
export type ChatStoreState = {
109
messages: ChatMessage[]
@@ -17,7 +16,7 @@ export type ChatStoreState = {
1716
isChainInProgress: boolean
1817
slashSelectedIndex: number
1918
agentSelectedIndex: number
20-
agentMode: 'FAST' | 'MAX'
19+
agentMode: AgentMode
2120
}
2221

2322
type ChatStoreActions = {
@@ -41,7 +40,7 @@ type ChatStoreActions = {
4140
setIsChainInProgress: (active: boolean) => void
4241
setSlashSelectedIndex: (value: number | ((prev: number) => number)) => void
4342
setAgentSelectedIndex: (value: number | ((prev: number) => number)) => void
44-
setAgentMode: (mode: 'FAST' | 'MAX') => void
43+
setAgentMode: (mode: AgentMode) => void
4544
toggleAgentMode: () => void
4645
reset: () => void
4746
}

cli/src/utils/constants.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,6 @@ export const HIDDEN_AGENT_IDS = ['codebuff/context-pruner'] as const
77
export const shouldHideAgent = (agentId: string): boolean => {
88
return HIDDEN_AGENT_IDS.some((hiddenId) => agentId.includes(hiddenId))
99
}
10+
11+
const agentModes = ['FAST', 'MAX'] as const
12+
export type AgentMode = (typeof agentModes)[number]

0 commit comments

Comments
 (0)