chore: normalize structure and split ipc handlers (#590)

Co-authored-by: Haze <709547807@qq.com>
This commit is contained in:
GASOT-GIT
2026-03-23 17:18:40 +08:00
committed by GitHub
Unverified
parent 884aa7c7f1
commit 6b82c6ccb4
7 changed files with 136 additions and 219 deletions

View File

@@ -8,116 +8,24 @@ import { hostApiFetch } from '@/lib/host-api';
import { useGatewayStore } from './gateway';
import { useAgentsStore } from './agents';
import { buildCronSessionHistoryPath, isCronSessionKey } from './chat/cron-session-utils';
import {
DEFAULT_CANONICAL_PREFIX,
DEFAULT_SESSION_KEY,
type AttachedFileMeta,
type ChatSession,
type ChatState,
type ContentBlock,
type RawMessage,
type ToolStatus,
} from './chat/types';
// ── Types ────────────────────────────────────────────────────────
/** Metadata for locally-attached files (not from Gateway) */
export interface AttachedFileMeta {
fileName: string;
mimeType: string;
fileSize: number;
preview: string | null;
filePath?: string;
}
/** Raw message from OpenClaw chat.history */
export interface RawMessage {
role: 'user' | 'assistant' | 'system' | 'toolresult';
content: unknown; // string | ContentBlock[]
timestamp?: number;
id?: string;
toolCallId?: string;
toolName?: string;
details?: unknown;
isError?: boolean;
/** Local-only: file metadata for user-uploaded attachments (not sent to/from Gateway) */
_attachedFiles?: AttachedFileMeta[];
}
/** Content block inside a message */
export interface ContentBlock {
type: 'text' | 'image' | 'thinking' | 'tool_use' | 'tool_result' | 'toolCall' | 'toolResult';
text?: string;
thinking?: string;
source?: { type: string; media_type?: string; data?: string; url?: string };
/** Flat image format from Gateway tool results (no source wrapper) */
data?: string;
mimeType?: string;
id?: string;
name?: string;
input?: unknown;
arguments?: unknown;
content?: unknown;
}
/** Session from sessions.list */
export interface ChatSession {
key: string;
label?: string;
displayName?: string;
thinkingLevel?: string;
model?: string;
updatedAt?: number;
}
export interface ToolStatus {
id?: string;
toolCallId?: string;
name: string;
status: 'running' | 'completed' | 'error';
durationMs?: number;
summary?: string;
updatedAt: number;
}
interface ChatState {
// Messages
messages: RawMessage[];
loading: boolean;
error: string | null;
// Streaming
sending: boolean;
activeRunId: string | null;
streamingText: string;
streamingMessage: unknown | null;
streamingTools: ToolStatus[];
pendingFinal: boolean;
lastUserMessageAt: number | null;
/** Images collected from tool results, attached to the next assistant message */
pendingToolImages: AttachedFileMeta[];
// Sessions
sessions: ChatSession[];
currentSessionKey: string;
currentAgentId: string;
/** First user message text per session key, used as display label */
sessionLabels: Record<string, string>;
/** Last message timestamp (ms) per session key, used for sorting */
sessionLastActivity: Record<string, number>;
// Thinking
showThinking: boolean;
thinkingLevel: string | null;
// Actions
loadSessions: () => Promise<void>;
switchSession: (key: string) => void;
newSession: () => void;
deleteSession: (key: string) => Promise<void>;
cleanupEmptySession: () => void;
loadHistory: (quiet?: boolean) => Promise<void>;
sendMessage: (
text: string,
attachments?: Array<{ fileName: string; mimeType: string; fileSize: number; stagedPath: string; preview: string | null }>,
targetAgentId?: string | null,
) => Promise<void>;
abortRun: () => Promise<void>;
handleChatEvent: (event: Record<string, unknown>) => void;
toggleThinking: () => void;
refresh: () => Promise<void>;
clearError: () => void;
}
export type {
AttachedFileMeta,
ChatSession,
ContentBlock,
RawMessage,
ToolStatus,
} from './chat/types';
// Module-level timestamp tracking the last chat event received.
// Used by the safety timeout to avoid false-positive "no response" errors
@@ -204,9 +112,6 @@ function isDuplicateChatEvent(eventState: string, event: Record<string, unknown>
return false;
}
const DEFAULT_CANONICAL_PREFIX = 'agent:main';
const DEFAULT_SESSION_KEY = `${DEFAULT_CANONICAL_PREFIX}:main`;
// ── Local image cache ─────────────────────────────────────────
// The Gateway doesn't store image attachments in session content blocks,
// so we cache them locally keyed by staged file path (which appears in the