Skip to content

Commit ccc2b75

Browse files
committed
feat(cli): add foundational stores for future refactoring
Create three new Zustand stores to prepare for reducing prop drilling: - queue-store.ts: Message queue and streaming status management - stream-store.ts: Streaming agents and chain progress state - ui-store.ts: UI-related state (focused agent, input focus) These stores are not yet integrated but provide the foundation for future incremental migration to reduce prop drilling in Chat component.
1 parent 942ab09 commit ccc2b75

File tree

3 files changed

+193
-0
lines changed

3 files changed

+193
-0
lines changed

cli/src/state/queue-store.ts

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
import { create } from 'zustand'
2+
import { immer } from 'zustand/middleware/immer'
3+
4+
export type StreamStatus = 'idle' | 'waiting' | 'streaming'
5+
6+
export type QueueStoreState = {
7+
queuedMessages: string[]
8+
streamStatus: StreamStatus
9+
canProcessQueue: boolean
10+
queuePaused: boolean
11+
}
12+
13+
export type QueueStoreActions = {
14+
addToQueue: (message: string) => void
15+
clearQueue: () => string[]
16+
pauseQueue: () => void
17+
resumeQueue: () => void
18+
setStreamStatus: (status: StreamStatus) => void
19+
setCanProcessQueue: (can: boolean) => void
20+
startStreaming: () => void
21+
stopStreaming: () => void
22+
}
23+
24+
export type QueueStore = QueueStoreState & QueueStoreActions
25+
26+
const initialState: QueueStoreState = {
27+
queuedMessages: [],
28+
streamStatus: 'idle',
29+
canProcessQueue: true,
30+
queuePaused: false,
31+
}
32+
33+
export const useQueueStore = create<QueueStore>()(
34+
immer((set, get) => ({
35+
...initialState,
36+
37+
addToQueue: (message) =>
38+
set((state) => {
39+
state.queuedMessages.push(message)
40+
}),
41+
42+
clearQueue: () => {
43+
const current = get().queuedMessages
44+
set((state) => {
45+
state.queuedMessages = []
46+
})
47+
return current
48+
},
49+
50+
pauseQueue: () =>
51+
set((state) => {
52+
state.queuePaused = true
53+
state.canProcessQueue = false
54+
}),
55+
56+
resumeQueue: () =>
57+
set((state) => {
58+
state.queuePaused = false
59+
state.canProcessQueue = true
60+
}),
61+
62+
setStreamStatus: (status) =>
63+
set((state) => {
64+
state.streamStatus = status
65+
}),
66+
67+
setCanProcessQueue: (can) =>
68+
set((state) => {
69+
state.canProcessQueue = can
70+
}),
71+
72+
startStreaming: () =>
73+
set((state) => {
74+
state.streamStatus = 'streaming'
75+
state.canProcessQueue = false
76+
}),
77+
78+
stopStreaming: () =>
79+
set((state) => {
80+
const wasPaused = state.queuePaused
81+
state.streamStatus = 'idle'
82+
state.canProcessQueue = !wasPaused
83+
}),
84+
})),
85+
)

cli/src/state/stream-store.ts

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
import { create } from 'zustand'
2+
import { immer } from 'zustand/middleware/immer'
3+
4+
export type StreamStoreState = {
5+
streamingAgents: Set<string>
6+
activeSubagents: Set<string>
7+
isChainInProgress: boolean
8+
abortController: AbortController | null
9+
}
10+
11+
export type StreamStoreActions = {
12+
setStreamingAgents: (
13+
value: Set<string> | ((prev: Set<string>) => Set<string>),
14+
) => void
15+
setActiveSubagents: (
16+
value: Set<string> | ((prev: Set<string>) => Set<string>),
17+
) => void
18+
setIsChainInProgress: (value: boolean) => void
19+
setAbortController: (controller: AbortController | null) => void
20+
abortStream: () => void
21+
}
22+
23+
export type StreamStore = StreamStoreState & StreamStoreActions
24+
25+
const initialState: StreamStoreState = {
26+
streamingAgents: new Set<string>(),
27+
activeSubagents: new Set<string>(),
28+
isChainInProgress: false,
29+
abortController: null,
30+
}
31+
32+
export const useStreamStore = create<StreamStore>()(
33+
immer((set, get) => ({
34+
...initialState,
35+
36+
setStreamingAgents: (value) =>
37+
set((state) => {
38+
state.streamingAgents =
39+
typeof value === 'function'
40+
? value(state.streamingAgents)
41+
: value
42+
}),
43+
44+
setActiveSubagents: (value) =>
45+
set((state) => {
46+
state.activeSubagents =
47+
typeof value === 'function'
48+
? value(state.activeSubagents)
49+
: value
50+
}),
51+
52+
setIsChainInProgress: (value) =>
53+
set((state) => {
54+
state.isChainInProgress = value
55+
}),
56+
57+
setAbortController: (controller) =>
58+
set((state) => {
59+
state.abortController = controller
60+
}),
61+
62+
abortStream: () => {
63+
const controller = get().abortController
64+
controller?.abort()
65+
set((state) => {
66+
state.abortController = null
67+
})
68+
},
69+
})),
70+
)

cli/src/state/ui-store.ts

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import { create } from 'zustand'
2+
import { immer } from 'zustand/middleware/immer'
3+
4+
export type UiStoreState = {
5+
focusedAgentId: string | null
6+
inputFocused: boolean
7+
}
8+
9+
export type UiStoreActions = {
10+
setFocusedAgentId: (
11+
value: string | null | ((prev: string | null) => string | null),
12+
) => void
13+
setInputFocused: (focused: boolean) => void
14+
}
15+
16+
export type UiStore = UiStoreState & UiStoreActions
17+
18+
const initialState: UiStoreState = {
19+
focusedAgentId: null,
20+
inputFocused: true,
21+
}
22+
23+
export const useUiStore = create<UiStore>()(
24+
immer((set) => ({
25+
...initialState,
26+
27+
setFocusedAgentId: (value) =>
28+
set((state) => {
29+
state.focusedAgentId =
30+
typeof value === 'function' ? value(state.focusedAgentId) : value
31+
}),
32+
33+
setInputFocused: (focused) =>
34+
set((state) => {
35+
state.inputFocused = focused
36+
}),
37+
})),
38+
)

0 commit comments

Comments
 (0)