How `chat_create` Initializes a New Chat Session and Its Metadata in Coco App
When a user submits a message in Coco App, the createNewChat function in src/hooks/useChatActions.ts orchestrates session initialization by clearing UI state, generating unique timestamps, assembling query parameters, and invoking the chat_create command with structured metadata for both Tauri desktop and web environments.
The Coco App chat system, maintained in the infinilabs/coco-app repository, uses a unified hook-based architecture to bootstrap conversational sessions. Understanding how chat_create initializes these sessions requires examining the client-side preparation logic that runs before any network request reaches the backend.
The Session Initialization Flow
The initialization process begins when the UI invokes createNewChat, a React hook function that coordinates five distinct phases of session preparation before transmitting data to the server.
Preparing the Session with prepareChatSession
Before constructing the network payload, createNewChat calls prepareChatSession (lines 281‑302 in src/hooks/useChatActions.ts) to establish a clean execution environment. This utility performs critical housekeeping:
- Clears any pending streaming chunks via
clearAllChunkData()to prevent message bleeding between sessions - Resets the attachment list and UI input state
- Hides the start page and clears timeout flags
- Registers event listeners that will handle the streaming response once the session is established
This preparation ensures that each chat session starts from a deterministic state, regardless of previous interactions.
Generating Unique Identifiers
To prevent stream collisions and enable precise session tracking, the hook generates a millisecond-precision timestamp:
const timestamp = Date.now();
This timestamp (lines 50‑51) combines with a client identifier to form a unique stream ID formatted as chat-stream-${clientId}-${timestamp}. The composite ID travels with every request, allowing the backend to route streaming responses to the correct UI session even when multiple chats run concurrently.
Assembling Query Parameters and Metadata
The core metadata assembly occurs in src/hooks/useChatActions.ts (lines 54‑61), where the hook constructs a queryParams object reflecting the current UI configuration:
const queryParams = {
search: isSearchActive,
deep_thinking: isDeepThinkActive,
mcp: isMCPActive,
datasource: sourceDataIds?.join(",") || "",
mcp_servers: MCPIds?.join(",") || "",
assistant_id: currentAssistant?._id || "",
};
Each field serves a specific function:
search,deep_thinking, andmcpare boolean flags indicating active feature togglesdatasourcecontains comma-separated IDs for external data sources the assistant should querymcp_serverslists active MCP (Model Context Protocol) server identifiersassistant_idtargets a specific AI assistant when the user has multiple assistants configured
This metadata object travels with every chat_create invocation, ensuring the backend receives complete context about how to process the incoming message.
Backend Invocation: Desktop vs Web
Coco App supports two runtime environments—Tauri desktop and standard web browsers—each with distinct transport mechanisms for the chat_create command.
Tauri Desktop Path
When running as a desktop application, the hook invokes the backend through the Tauri bridge (lines 66‑74):
await platformAdapter.commands("chat_create", {
serverId,
message: userMessage,
attachments,
queryParams,
clientId: `chat-stream-${clientId}-${timestamp}`,
});
The payload includes:
serverId: The active server selected in the UI dropdownmessage: The sanitized user promptattachments: An array of uploaded file referencesqueryParams: The metadata object assembled earlierclientId: The unique stream identifier combining client ID and timestamp
According to the source code in src/commands/servers.ts, this command ultimately forwards the payload to the Coco AI backend, which initializes the session and begins streaming the response through Tauri's event system.
Web Browser Path
For browser deployments, the hook bypasses Tauri and sends a streaming HTTP POST request to /chat/_create (lines 78‑82 in src/hooks/useChatActions.ts):
await streamPost({
url: `${apiOrigin}/chat/_create`,
data: payload,
headers,
});
The payload structure mirrors the desktop version, ensuring consistent metadata handling across platforms. The streamPost utility (implemented in src/api/streamFetch.ts) manages Server-Sent Events (SSE) to deliver real-time tokens to the UI.
Post-Creation State Management
After the backend acknowledges session creation, createNewChat performs cleanup operations (lines 76‑94):
- Calls
resetChatState()to clear temporary UI flags and input buffers - Conditionally refreshes the chat history pane by invoking
getChatHistory()or its paginated variant, ensuring the new session appears in the sidebar immediately
The event listeners registered during prepareChatSession (via src/hooks/useWindows.ts) then capture the chat-create and chat-create-error events, routing the streaming content into the conversation view.
Summary
- Session preparation:
prepareChatSessioninsrc/hooks/useChatActions.tsclears previous state and registers streaming listeners before any network call occurs - Unique identification: Each session receives a millisecond timestamp combined into a
chat-stream-${clientId}-${timestamp}identifier to prevent collisions - Metadata assembly: The
queryParamsobject encapsulates UI toggles (search,deep_thinking,mcp), data source IDs, and the targetassistant_idfor backend routing - Dual transport: Desktop builds use
platformAdapter.commands("chat_create", ...)while web builds POST to/chat/_create, both carrying identical payload structures - State synchronization: Post-creation hooks reset the chat state and refresh history views to maintain UI consistency
Frequently Asked Questions
What is the purpose of the timestamp variable in createNewChat?
The timestamp generated via Date.now() (lines 50‑51) creates a unique temporal identifier for each chat stream. When combined with the client ID into the format chat-stream-${clientId}-${timestamp}, it enables the backend to route streaming responses to the correct session and prevents race conditions when multiple chats initialize simultaneously.
How does Coco App handle different assistant configurations during session creation?
The queryParams object includes an assistant_id field populated from currentAssistant?._id (lines 54‑61). When the user selects a specific assistant from the UI, this ID transmits to the backend via the chat_create payload, ensuring the server instantiates the correct model and context configuration for that particular assistant.
Where does the actual chat_create command execution happen in the codebase?
While src/hooks/useChatActions.ts contains the client-side orchestration logic that calls platformAdapter.commands("chat_create", ...), the low-level command implementation resides in src/commands/servers.ts. This file handles the bridge between the TypeScript frontend and the Rust-based Tauri backend, ultimately forwarding the request to the Coco AI server.
What happens if a user attaches files during session initialization?
The createNewChat function accepts an attachments array parameter that travels within the chat_create payload alongside the message and metadata. These attachments pass through the same transport layer (Tauri commands or HTTP POST) and are processed by the backend before the assistant begins generating its response.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →