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, and mcp are boolean flags indicating active feature toggles
  • datasource contains comma-separated IDs for external data sources the assistant should query
  • mcp_servers lists active MCP (Model Context Protocol) server identifiers
  • assistant_id targets 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 dropdown
  • message: The sanitized user prompt
  • attachments: An array of uploaded file references
  • queryParams: The metadata object assembled earlier
  • clientId: 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: prepareChatSession in src/hooks/useChatActions.ts clears 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 queryParams object encapsulates UI toggles (search, deep_thinking, mcp), data source IDs, and the target assistant_id for 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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →