Chat Session File Format - NiclasOlofsson/remember-mcp-vscode GitHub Wiki
title: Chat Session File Format description: Canonical structure and semantics of chatSessions/.json files used by Copilot chat history scanning.
This document describes the canonical chat session artifact we already scan and transform into CopilotUsageEvents. Each file captures a finalized conversational / editing turn history at a coarse (turn) granularity – not every intermediate edit operation.
The file is a pruned, stable history of user ↔ Copilot interaction. A "turn" = one user message + the agent/model response (what we are renaming conceptually from requestId → turnId).
Pipeline lifecycle:
- User initiates a prompt / command.
- Client builds
message.parts(structured prompt context) +message.text(flattened view). - Agent / model invoked (modelRequestId lives elsewhere – not in this file).
- Streaming response chunks appended to
response[]. - Timings & metadata captured in
result. - Turn persisted into the session file under
requests[].
{
"version": number,
"sessionId": string,
"creationDate": number, // epoch (seconds or ms)
"lastMessageDate": number,
"requesterUsername": string,
"responderUsername": string,
"initialLocation": string,
"isImported"?: boolean,
"requests": CopilotChatRequest[]
}
Temporal fields:
-
creationDate: when the conversation started. -
lastMessageDate: timestamp for the last persisted turn (used for ordering / pruning).
Key fields (one object per turn):
| Field | Purpose |
|---|---|
requestId |
Unique turn identifier (conceptual turnId). |
responseId |
Identifier for the model's response (may differ from requestId). |
timestamp |
Turn start time. May need ms normalization. |
modelId? |
Backend model identifier (may be absent for non-model commands). |
isCanceled |
True if user canceled before completion (response may be partial). |
message |
User input (plain + structured parts). |
variableData? |
Explicit variable expansions (selection, file refs). |
agent? |
Agent persona; influences turn classification (editsAgent, explainAgent, etc.). |
response[] |
Streaming output chunks from the agent/model. |
result? |
Timings + additional metadata. |
contentReferences? |
Context files / ranges shown to the model. |
codeCitations? |
License/snippet citations (if provided). |
followups? |
Suggested follow-up prompts. |
message: {
text: string, // flattened prompt
parts: Array<object> // structured prompt segments
}
parts may include raw text, code selections, variable placeholders, system directives. text is a convenience flattening used for simple display & analytics.
response is an array because the client streams and appends chunks:
response: [ { value: string, kind?: string, ... }, ... ]
Different kind values (often omitted) could distinguish code vs plain text.
result: {
timings?: { totalElapsed: number; firstProgress: number; },
metadata?: { [k: string]: any },
...
}
-
totalElapsed: end-to-end latency. -
firstProgress: time until first streamed token/chunk.
contentReferences[] enumerate file or external URIs (with optional ranges) provided to the model. codeCitations[] capture licensed snippet attributions.
Model-suggested next steps (used for UX guidance / prompt chaining rate metrics).
| Missing Item | Where It Actually Lives |
|---|---|
telemetryInfo.requestId (per-file model call) |
Editing state file (linearHistory) & logs |
| File snapshot hashes | Editing state file (stops/entries) |
| Intermediate retries / partial model attempts | Logs and/or editing state |
| Metric | Source |
|---|---|
| Turn count | requests.length |
| Latency (avg) | result.timings.totalElapsed |
| Time to first token | result.timings.firstProgress |
| Model mix | modelId |
| Prompt length | message.text.length |
| Response size | Σ response[].value.length
|
| Citation adoption | presence of codeCitations
|
| Context density | contentReferences.length |
| Follow-up rate | followups.length > 0 |
| Pitfall | Clarification |
|---|---|
Assuming response is single string |
It is a chunk array. |
| Counting model requests by turns | Turn ≠ model HTTP call; possible retries hidden. |
Expecting modelId always present |
Slash/system commands may omit it. |
| Inferring file-level diffs | Not possible from this file alone. |
The current SessionDataTransformer consumes these turn objects directly, normalizing timestamps and producing CopilotUsageEvents. It does not augment with model attempts because they are absent here.
To attach per-turn model request details later, enrich transformed events with data derived from the editing state file (see separate document) keyed by (sessionId, requestId).
Revision History:
- v1 (initial extraction) – describes observed schema & usage patterns.