chore: normalize structure and split ipc handlers (#590)
Co-authored-by: Haze <709547807@qq.com>
This commit is contained in:
committed by
GitHub
Unverified
parent
884aa7c7f1
commit
6b82c6ccb4
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user