Files
SuperCharged-Claude-Code-Up…/dexto/packages/webui/lib/stores/agentStore.ts
admin b52318eeae feat: Add intelligent auto-router and enhanced integrations
- Add intelligent-router.sh hook for automatic agent routing
- Add AUTO-TRIGGER-SUMMARY.md documentation
- Add FINAL-INTEGRATION-SUMMARY.md documentation
- Complete Prometheus integration (6 commands + 4 tools)
- Complete Dexto integration (12 commands + 5 tools)
- Enhanced Ralph with access to all agents
- Fix /clawd command (removed disable-model-invocation)
- Update hooks.json to v5 with intelligent routing
- 291 total skills now available
- All 21 commands with automatic routing

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2026-01-28 00:27:56 +04:00

299 lines
7.4 KiB
TypeScript

/**
* Agent Store
*
* Manages the agent's status and connection state.
* This is global state (not per-session) as there's one agent connection.
*/
import { create } from 'zustand';
// =============================================================================
// Types
// =============================================================================
/**
* Agent's current activity status
*/
export type AgentStatus =
| 'idle' // Ready for input
| 'thinking' // Processing/generating response
| 'executing_tool' // Running a tool
| 'awaiting_approval'; // Waiting for user approval
/**
* Connection status to the backend
*/
export type ConnectionStatus = 'connected' | 'disconnected' | 'reconnecting';
/**
* Agent state
*/
export interface AgentState {
/**
* Current agent activity status
*/
status: AgentStatus;
/**
* Connection status to the backend
*/
connectionStatus: ConnectionStatus;
/**
* Timestamp of last heartbeat (for connection health monitoring)
*/
lastHeartbeat: number | null;
/**
* Currently active session for the agent (for status context)
*/
activeSessionId: string | null;
/**
* Name of the tool currently being executed (if any)
*/
currentToolName: string | null;
/**
* Error message if connection failed
*/
connectionError: string | null;
/**
* Number of reconnection attempts
*/
reconnectAttempts: number;
}
// =============================================================================
// Store Interface
// =============================================================================
interface AgentStore extends AgentState {
// -------------------------------------------------------------------------
// Status Actions
// -------------------------------------------------------------------------
/**
* Set the agent's activity status
*/
setStatus: (status: AgentStatus, sessionId?: string) => void;
/**
* Set status to thinking
*/
setThinking: (sessionId: string) => void;
/**
* Set status to executing tool
*/
setExecutingTool: (sessionId: string, toolName: string) => void;
/**
* Set status to awaiting approval
*/
setAwaitingApproval: (sessionId: string) => void;
/**
* Set status to idle
*/
setIdle: () => void;
// -------------------------------------------------------------------------
// Connection Actions
// -------------------------------------------------------------------------
/**
* Set the connection status
*/
setConnectionStatus: (status: ConnectionStatus) => void;
/**
* Mark connection as established
*/
setConnected: () => void;
/**
* Mark connection as lost
*/
setDisconnected: (error?: string) => void;
/**
* Mark as attempting reconnection
*/
setReconnecting: () => void;
/**
* Update the heartbeat timestamp
*/
updateHeartbeat: () => void;
/**
* Increment reconnection attempt counter
*/
incrementReconnectAttempts: () => void;
/**
* Reset reconnection attempt counter
*/
resetReconnectAttempts: () => void;
// -------------------------------------------------------------------------
// Selectors
// -------------------------------------------------------------------------
/**
* Check if the agent is busy (not idle)
*/
isBusy: () => boolean;
/**
* Check if connected
*/
isConnected: () => boolean;
/**
* Check if the agent is working on a specific session
*/
isActiveForSession: (sessionId: string) => boolean;
/**
* Get time since last heartbeat (ms), or null if no heartbeat
*/
getHeartbeatAge: () => number | null;
}
// =============================================================================
// Default State
// =============================================================================
const defaultState: AgentState = {
status: 'idle',
connectionStatus: 'disconnected',
lastHeartbeat: null,
activeSessionId: null,
currentToolName: null,
connectionError: null,
reconnectAttempts: 0,
};
// =============================================================================
// Store Implementation
// =============================================================================
export const useAgentStore = create<AgentStore>()((set, get) => ({
...defaultState,
// -------------------------------------------------------------------------
// Status Actions
// -------------------------------------------------------------------------
setStatus: (status, sessionId) => {
set({
status,
activeSessionId: sessionId ?? (status === 'idle' ? null : get().activeSessionId),
// Clear tool name if not executing
currentToolName: status === 'executing_tool' ? get().currentToolName : null,
});
},
setThinking: (sessionId) => {
set({
status: 'thinking',
activeSessionId: sessionId,
currentToolName: null,
});
},
setExecutingTool: (sessionId, toolName) => {
set({
status: 'executing_tool',
activeSessionId: sessionId,
currentToolName: toolName,
});
},
setAwaitingApproval: (sessionId) => {
set({
status: 'awaiting_approval',
activeSessionId: sessionId,
currentToolName: null,
});
},
setIdle: () => {
set({
status: 'idle',
activeSessionId: null,
currentToolName: null,
});
},
// -------------------------------------------------------------------------
// Connection Actions
// -------------------------------------------------------------------------
setConnectionStatus: (status) => {
set({ connectionStatus: status });
},
setConnected: () => {
set({
connectionStatus: 'connected',
connectionError: null,
reconnectAttempts: 0,
lastHeartbeat: Date.now(),
});
},
setDisconnected: (error) => {
set({
connectionStatus: 'disconnected',
connectionError: error ?? null,
});
},
setReconnecting: () => {
set({
connectionStatus: 'reconnecting',
});
},
updateHeartbeat: () => {
set({ lastHeartbeat: Date.now() });
},
incrementReconnectAttempts: () => {
set((state) => ({
reconnectAttempts: state.reconnectAttempts + 1,
}));
},
resetReconnectAttempts: () => {
set({ reconnectAttempts: 0 });
},
// -------------------------------------------------------------------------
// Selectors
// -------------------------------------------------------------------------
isBusy: () => {
return get().status !== 'idle';
},
isConnected: () => {
return get().connectionStatus === 'connected';
},
isActiveForSession: (sessionId) => {
const state = get();
return state.status !== 'idle' && state.activeSessionId === sessionId;
},
getHeartbeatAge: () => {
const { lastHeartbeat } = get();
if (lastHeartbeat === null) return null;
return Date.now() - lastHeartbeat;
},
}));