18 KiB
Cursor Response JSON-Struktur - Spezifikation
Stand: Februar 2026 Zweck: Definition der JSON-Antwortstruktur fuer die Chat-API-Komponente, in der Antwortteile als einzelne Dokumente erfasst werden
1. Design-Prinzip
Eine LLM-Antwort besteht typischerweise aus verschiedenen Segmenten: erklaerenden Texten, Code-Referenzen, neuen Code-Bloecken, Tool-Aufrufen, Datei-Aenderungen und Plaenen. Diese Segmente werden als einzelne Dokumente in einem Array erfasst, um sie einzeln verarbeiten, rendern und referenzieren zu koennen.
2. Top-Level Response
{
"id": "chat_<uuid>",
"conversationId": "conv_<uuid>",
"model": "claude-4.6-opus",
"mode": "agent | plan | ask | debug",
"created": "2026-02-23T10:30:00Z",
"status": "completed | streaming | error",
"documents": [ /* Array von Document-Objekten */ ],
"usage": {
"promptTokens": 2450,
"completionTokens": 890,
"totalTokens": 3340
},
"metadata": {
"duration_ms": 4520,
"toolCallCount": 3,
"turnCount": 2
}
}
Feld-Beschreibung
| Feld | Typ | Beschreibung |
|---|---|---|
id |
string | Eindeutige ID dieser Antwort |
conversationId |
string | ID der laufenden Konversation (fuer Multi-Turn) |
model |
string | Verwendetes LLM-Modell |
mode |
enum | Aktiver Modus: agent, plan, ask, debug |
created |
ISO 8601 | Zeitstempel der Erstellung |
status |
enum | Status: completed, streaming, error |
documents |
array | Geordnetes Array der Antwort-Dokumente |
usage |
object | Token-Verbrauch |
metadata |
object | Zusaetzliche Metadaten |
3. Document Types
Jedes Dokument im documents[] Array hat folgende Basis-Struktur:
{
"id": "doc_<sequenzNummer>",
"type": "<documentType>",
"sequence": 1,
"content": "...",
"metadata": { /* typ-spezifische Metadaten */ }
}
3.1 text - Erklaerungstext
Freitext-Erklaerungen, Beschreibungen, Instruktionen des AI-Assistenten.
{
"id": "doc_001",
"type": "text",
"sequence": 1,
"content": "Ich werde eine Authentication-Middleware implementieren, die JWT-Token validiert und den Request-Context mit User-Informationen anreichert.\n\nDafuer sind folgende Schritte noetig:",
"metadata": {
"format": "markdown"
}
}
3.2 code_reference - Verweis auf existierenden Code
Referenz auf bestehenden Code im Projekt (Cursor's startLine:endLine:filepath Format).
{
"id": "doc_002",
"type": "code_reference",
"sequence": 2,
"content": "def main():\n app = Flask(__name__)\n app.register_blueprint(api_bp)",
"metadata": {
"filePath": "src/main.py",
"startLine": 12,
"endLine": 14,
"language": "python"
}
}
3.3 code_block - Neuer/vorgeschlagener Code
Code-Block fuer neuen oder vorgeschlagenen Code, der nicht direkt einer Datei zugeordnet ist.
{
"id": "doc_003",
"type": "code_block",
"sequence": 3,
"content": "from functools import wraps\nfrom flask import request, jsonify\nimport jwt\n\ndef authMiddleware(f):\n @wraps(f)\n def decorated(*args, **kwargs):\n token = request.headers.get('Authorization')\n if not token:\n return jsonify({'error': 'Token fehlt'}), 401\n try:\n data = jwt.decode(token, SECRET_KEY, algorithms=['HS256'])\n request.userId = data['userId']\n except jwt.InvalidTokenError:\n return jsonify({'error': 'Ungueltiger Token'}), 401\n return f(*args, **kwargs)\n return decorated",
"metadata": {
"language": "python",
"purpose": "new_code"
}
}
3.4 file_edit - Datei-Aenderung
Konkrete Aenderung an einer bestehenden oder neuen Datei.
{
"id": "doc_004",
"type": "file_edit",
"sequence": 4,
"content": "from functools import wraps\nfrom flask import request, jsonify\nimport jwt\n\nSECRET_KEY = 'your-secret-key'\n\ndef authMiddleware(f):\n ...",
"metadata": {
"filePath": "src/middleware/auth.py",
"operation": "create",
"language": "python",
"diff": null
}
}
Operationen:
| Operation | Beschreibung |
|---|---|
create |
Neue Datei erstellen |
edit |
Bestehende Datei aendern |
delete |
Datei loeschen |
rename |
Datei umbenennen |
Bei edit wird zusaetzlich ein Diff mitgeliefert:
{
"id": "doc_005",
"type": "file_edit",
"sequence": 5,
"content": "app.register_blueprint(api_bp)\napp.register_blueprint(auth_bp)",
"metadata": {
"filePath": "src/main.py",
"operation": "edit",
"language": "python",
"diff": {
"oldString": "app.register_blueprint(api_bp)",
"newString": "app.register_blueprint(api_bp)\napp.register_blueprint(auth_bp)",
"startLine": 14,
"endLine": 14
}
}
}
3.5 tool_call - Tool-Aufruf und Ergebnis
Dokumentiert einen Tool-Aufruf inklusive Argumente und Ergebnis.
{
"id": "doc_006",
"type": "tool_call",
"sequence": 6,
"content": null,
"metadata": {
"toolName": "codebase_search",
"toolCallId": "call_abc123",
"arguments": {
"query": "Where is the Flask app initialized?",
"target_directories": ["src/"],
"explanation": "Find the main app entry point"
},
"result": {
"status": "success",
"data": "Found in src/main.py:12 - app = Flask(__name__)"
},
"duration_ms": 320
}
}
3.6 terminal_command - Terminal-Ausfuehrung
Dokumentiert die Ausfuehrung eines Terminal-Kommandos.
{
"id": "doc_007",
"type": "terminal_command",
"sequence": 7,
"content": null,
"metadata": {
"command": "pip install PyJWT flask",
"workingDirectory": "/path/to/project",
"exitCode": 0,
"output": "Successfully installed PyJWT-2.8.0 flask-3.0.0",
"duration_ms": 5200,
"permissions": ["network"]
}
}
3.7 plan - Strukturierter Plan
Ergebnis des Plan-Modus oder eines create_plan Tool-Aufrufs.
{
"id": "doc_008",
"type": "plan",
"sequence": 8,
"content": "# Authentication Middleware\n\n## Uebersicht\nImplementierung einer JWT-basierten Auth-Middleware...\n\n## Dateien\n- `src/middleware/auth.py` (neu)\n- `src/main.py` (aendern)\n- `requirements.txt` (aendern)",
"metadata": {
"title": "Auth Middleware Implementation",
"overview": "JWT-basierte Authentication-Middleware mit Token-Validierung",
"todos": [
{
"id": "create-middleware",
"content": "Auth-Middleware-Modul erstellen",
"status": "pending",
"dependencies": []
},
{
"id": "register-blueprint",
"content": "Blueprint in main.py registrieren",
"status": "pending",
"dependencies": ["create-middleware"]
},
{
"id": "update-deps",
"content": "PyJWT zu requirements.txt hinzufuegen",
"status": "pending",
"dependencies": []
},
{
"id": "protect-routes",
"content": "Schuetzenswerte Routes mit Decorator versehen",
"status": "pending",
"dependencies": ["create-middleware", "register-blueprint"]
}
],
"format": "markdown"
}
}
3.8 clarification - Klaerende Frage
Klaerende Rueckfrage des AI-Assistenten an den User (haeufig im Plan Mode).
{
"id": "doc_009",
"type": "clarification",
"sequence": 9,
"content": "Bevor ich den Plan finalisiere, habe ich folgende Fragen:",
"metadata": {
"questions": [
{
"id": "q1",
"text": "Soll die Middleware JWT oder Session-basierte Auth verwenden?",
"options": [
{ "id": "jwt", "label": "JWT Token-basiert" },
{ "id": "session", "label": "Session-basiert mit Cookies" }
]
},
{
"id": "q2",
"text": "Welche Routes sollen geschuetzt werden?",
"options": [
{ "id": "all", "label": "Alle ausser Login/Register" },
{ "id": "selective", "label": "Nur explizit markierte Routes" }
]
}
]
}
}
3.9 error - Fehlermeldung
Fehlermeldung bei Tool-Ausfuehrung oder LLM-Fehler.
{
"id": "doc_010",
"type": "error",
"sequence": 10,
"content": "Die Datei konnte nicht gelesen werden",
"metadata": {
"errorCode": "FILE_NOT_FOUND",
"source": "read_file",
"details": "src/middleware/auth.py does not exist"
}
}
3.10 todo_update - Task-Status-Aenderung
Aenderung am Task-Tracking waehrend der Ausfuehrung.
{
"id": "doc_011",
"type": "todo_update",
"sequence": 11,
"content": null,
"metadata": {
"todos": [
{ "id": "create-middleware", "status": "completed" },
{ "id": "register-blueprint", "status": "in_progress" }
]
}
}
4. Vollstaendiges Response-Beispiel
Ein realistisches Beispiel fuer die Anfrage "Implementiere JWT Authentication":
{
"id": "chat_7f3a2b1c",
"conversationId": "conv_9e8d7c6b",
"model": "claude-4.6-opus",
"mode": "agent",
"created": "2026-02-23T10:30:00Z",
"status": "completed",
"documents": [
{
"id": "doc_001",
"type": "text",
"sequence": 1,
"content": "Ich analysiere zuerst die bestehende Projektstruktur, um die beste Integrationsstrategie zu finden.",
"metadata": { "format": "markdown" }
},
{
"id": "doc_002",
"type": "tool_call",
"sequence": 2,
"content": null,
"metadata": {
"toolName": "codebase_search",
"toolCallId": "call_001",
"arguments": {
"query": "Where is the Flask app initialized?",
"target_directories": ["src/"]
},
"result": { "status": "success", "data": "src/main.py:12" },
"duration_ms": 280
}
},
{
"id": "doc_003",
"type": "tool_call",
"sequence": 3,
"content": null,
"metadata": {
"toolName": "read_file",
"toolCallId": "call_002",
"arguments": { "target_file": "src/main.py" },
"result": {
"status": "success",
"data": "import os\nfrom flask import Flask\n\ndef main():\n app = Flask(__name__)\n app.register_blueprint(api_bp)\n return app"
},
"duration_ms": 45
}
},
{
"id": "doc_004",
"type": "code_reference",
"sequence": 4,
"content": "def main():\n app = Flask(__name__)\n app.register_blueprint(api_bp)\n return app",
"metadata": {
"filePath": "src/main.py",
"startLine": 5,
"endLine": 8,
"language": "python"
}
},
{
"id": "doc_005",
"type": "text",
"sequence": 5,
"content": "Ich erstelle jetzt die Auth-Middleware und integriere sie in die App.",
"metadata": { "format": "markdown" }
},
{
"id": "doc_006",
"type": "file_edit",
"sequence": 6,
"content": "from functools import wraps\nfrom flask import request, jsonify\nimport jwt\nimport os\n\nSECRET_KEY = os.environ.get('JWT_SECRET', 'dev-secret')\n\ndef authMiddleware(f):\n @wraps(f)\n def decorated(*args, **kwargs):\n token = request.headers.get('Authorization', '').replace('Bearer ', '')\n if not token:\n return jsonify({'error': 'Token required'}), 401\n try:\n data = jwt.decode(token, SECRET_KEY, algorithms=['HS256'])\n request.userId = data['userId']\n except jwt.InvalidTokenError:\n return jsonify({'error': 'Invalid token'}), 401\n return f(*args, **kwargs)\n return decorated",
"metadata": {
"filePath": "src/middleware/auth.py",
"operation": "create",
"language": "python"
}
},
{
"id": "doc_007",
"type": "file_edit",
"sequence": 7,
"content": "from middleware.auth import authMiddleware\n\napp.register_blueprint(api_bp)\napp.register_blueprint(auth_bp)",
"metadata": {
"filePath": "src/main.py",
"operation": "edit",
"language": "python",
"diff": {
"oldString": "app.register_blueprint(api_bp)",
"newString": "from middleware.auth import authMiddleware\n\napp.register_blueprint(api_bp)\napp.register_blueprint(auth_bp)",
"startLine": 6,
"endLine": 6
}
}
},
{
"id": "doc_008",
"type": "terminal_command",
"sequence": 8,
"content": null,
"metadata": {
"command": "pip install PyJWT",
"exitCode": 0,
"output": "Successfully installed PyJWT-2.8.0",
"duration_ms": 3200,
"permissions": ["network"]
}
},
{
"id": "doc_009",
"type": "text",
"sequence": 9,
"content": "Die JWT Authentication-Middleware ist implementiert. Du kannst jetzt Routes schuetzen mit dem `@authMiddleware` Decorator:\n\n```python\n@app.route('/api/protected')\n@authMiddleware\ndef protectedRoute():\n return jsonify({'userId': request.userId})\n```",
"metadata": { "format": "markdown" }
}
],
"usage": {
"promptTokens": 3200,
"completionTokens": 1450,
"totalTokens": 4650
},
"metadata": {
"duration_ms": 8750,
"toolCallCount": 2,
"turnCount": 3
}
}
5. Streaming-Format
Im Streaming-Modus wird jedes Dokument als Serie von Server-Sent Events uebertragen:
5.1 Event Types
| Event Type | Beschreibung |
|---|---|
document_start |
Neues Dokument beginnt, enthaelt id und type |
content_delta |
Text-Chunk fuer ein laufendes Dokument |
tool_call_start |
Tool-Aufruf beginnt |
tool_call_arguments |
Argumente des Tool-Aufrufs |
tool_result |
Ergebnis des Tool-Aufrufs |
document_end |
Dokument abgeschlossen |
done |
Gesamte Antwort abgeschlossen, enthaelt usage |
5.2 Event-Sequenz fuer ein Text-Dokument
event: document_start
data: {"id":"doc_001","type":"text","sequence":1}
event: content_delta
data: {"documentId":"doc_001","delta":"Ich analysiere "}
event: content_delta
data: {"documentId":"doc_001","delta":"zuerst die bestehende "}
event: content_delta
data: {"documentId":"doc_001","delta":"Projektstruktur..."}
event: document_end
data: {"documentId":"doc_001","finalContent":"Ich analysiere zuerst die bestehende Projektstruktur..."}
5.3 Event-Sequenz fuer einen Tool-Call
event: document_start
data: {"id":"doc_002","type":"tool_call","sequence":2}
event: tool_call_start
data: {"documentId":"doc_002","toolName":"read_file","toolCallId":"call_001"}
event: tool_call_arguments
data: {"documentId":"doc_002","arguments":{"target_file":"src/main.py"}}
event: tool_result
data: {"documentId":"doc_002","result":{"status":"success","data":"import os\n..."}}
event: document_end
data: {"documentId":"doc_002"}
6. TypeScript Interface-Definitionen
interface ChatResponse {
id: string;
conversationId: string;
model: string;
mode: "agent" | "plan" | "ask" | "debug";
created: string;
status: "completed" | "streaming" | "error";
documents: Document[];
usage: UsageInfo;
metadata: ResponseMetadata;
}
type DocumentType =
| "text"
| "code_reference"
| "code_block"
| "file_edit"
| "tool_call"
| "terminal_command"
| "plan"
| "clarification"
| "error"
| "todo_update";
interface Document {
id: string;
type: DocumentType;
sequence: number;
content: string | null;
metadata: Record<string, unknown>;
}
interface TextMetadata {
format: "markdown" | "plain";
}
interface CodeReferenceMetadata {
filePath: string;
startLine: number;
endLine: number;
language: string;
}
interface CodeBlockMetadata {
language: string;
purpose: "new_code" | "example" | "suggestion";
}
interface FileEditMetadata {
filePath: string;
operation: "create" | "edit" | "delete" | "rename";
language: string;
diff?: {
oldString: string;
newString: string;
startLine: number;
endLine: number;
};
}
interface ToolCallMetadata {
toolName: string;
toolCallId: string;
arguments: Record<string, unknown>;
result: {
status: "success" | "error";
data: unknown;
};
duration_ms: number;
}
interface TerminalCommandMetadata {
command: string;
workingDirectory?: string;
exitCode: number;
output: string;
duration_ms: number;
permissions: string[];
}
interface PlanMetadata {
title: string;
overview: string;
todos: PlanTodo[];
format: "markdown";
}
interface PlanTodo {
id: string;
content: string;
status: "pending" | "in_progress" | "completed" | "cancelled";
dependencies: string[];
}
interface ClarificationMetadata {
questions: ClarificationQuestion[];
}
interface ClarificationQuestion {
id: string;
text: string;
options: { id: string; label: string }[];
}
interface ErrorMetadata {
errorCode: string;
source: string;
details: string;
}
interface TodoUpdateMetadata {
todos: { id: string; status: string }[];
}
interface UsageInfo {
promptTokens: number;
completionTokens: number;
totalTokens: number;
}
interface ResponseMetadata {
duration_ms: number;
toolCallCount: number;
turnCount: number;
}
// Streaming Events
type StreamEventType =
| "document_start"
| "content_delta"
| "tool_call_start"
| "tool_call_arguments"
| "tool_result"
| "document_end"
| "done";
interface StreamEvent {
type: StreamEventType;
documentId?: string;
data: unknown;
}
7. Mapping: Cursor LLM Response → Document Types
Wie Cursor's roher LLM-Stream in Dokument-Typen umgewandelt wird:
LLM Output Stream
↓
Parser State Machine
│
├─> Erkennt freien Text → type: "text"
│ Akkumuliert bis naechster Segment-Beginn
│
├─> Erkennt ``` mit startLine:endLine:filepath → type: "code_reference"
│ Extrahiert: filePath, startLine, endLine, content
│
├─> Erkennt ``` mit Language-Tag → type: "code_block"
│ Extrahiert: language, content
│
├─> Erkennt Tool Call im Response
│ ├─> tool_name == "edit_file" → type: "file_edit"
│ ├─> tool_name == "run_terminal_cmd" → type: "terminal_command"
│ ├─> tool_name == "create_plan" → type: "plan"
│ ├─> tool_name == "todo_write" → type: "todo_update"
│ └─> alle anderen → type: "tool_call"
│
└─> Erkennt Fehler → type: "error"
Referenzen
- Cursor Architektur:
doc_cursor_ai_agent_architecture.md - API Integration Konzept:
doc_cursor_chat_api_integration_concept.md - OpenAI Chat Completions Streaming: https://platform.openai.com/docs/api-reference/chat/streaming
- Server-Sent Events Spec: https://html.spec.whatwg.org/multipage/server-sent-events.html