apex-dev 2.1.3 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.local/share/amp/history.jsonl +30 -0
- package/.local/share/amp/session.json +2 -2
- package/.local/share/amp/threads/T-019c9769-4a8a-77b8-beab-f48973276f9a.json +1541 -0
- package/.local/share/amp/threads/T-019c9772-edac-7075-b26e-0ada1f8697d2.json +7 -0
- package/.local/share/amp/threads/T-019c97e8-a9ab-71a1-a8f9-109c540c98bf.json +111 -0
- package/.local/share/amp/threads/T-019c97e9-2277-753c-8c5d-df745fa6cfff.json +7 -0
- package/.local/share/amp/threads/T-019c97e9-f28e-758d-9663-e37047a8ed95.json +111 -0
- package/.local/share/amp/threads/T-019c97ea-17c7-77b8-92b2-f641c069bcc9.json +71 -0
- package/.local/share/amp/threads/T-019c97ea-44c6-75b8-88bc-d88113194f6a.json +1611 -0
- package/.local/share/amp/threads/T-019c97ec-abae-7251-a5f6-693adf496a1c.json +7 -0
- package/.local/share/amp/threads/T-019c97f5-8e61-73ad-8c5d-2637abedcde6.json +1341 -0
- package/.local/share/amp/threads/T-019c989d-4f4e-7249-bde0-21d19455ccae.json +163 -0
- package/.local/share/amp/threads/T-019c989d-9024-73c4-bee8-e2ae45028a39.json +124 -0
- package/.local/share/amp/threads/T-019c989e-1394-74ad-8234-ac573fcdb4c7.json +1260 -0
- package/.local/share/amp/threads/T-019c989f-e3dd-772e-85ac-525d0fc88fda.json +403 -0
- package/.local/share/amp/threads/T-019c98a1-7b0c-778a-b311-2e1cff85d710.json +3422 -0
- package/.local/share/amp/threads/T-019c98c5-4b7f-7284-99e9-88aa8c18ba66.json +1830 -0
- package/.local/share/amp/threads/T-019c98d0-f27f-76ec-be10-6df96f22be99.json +4061 -0
- package/.local/share/amp/threads/T-019c98f9-d031-704d-a0c2-f2f395f68f2b.json +509 -0
- package/.local/share/amp/threads/T-019c9919-f9ee-766c-90be-af7a07f6a4c6.json +2075 -0
- package/.local/share/amp/threads/T-019c991c-b98b-7158-9083-cc52408beb13.json +7 -0
- package/.local/share/amp/threads/T-019c991d-66d6-72aa-a9a1-105f7df0ea06.json +7 -0
- package/.local/share/amp/threads/T-019c9c2e-71a4-77ff-bd7f-b053da7f9000.json +1637 -0
- package/.local/share/amp/threads/T-019c9c45-27ca-728b-ba77-835115dfa9b2.json +3893 -0
- package/.local/share/amp/threads/T-019c9c48-45dc-736a-9752-e4119fe698f9.json +7 -0
- package/.local/share/amp/threads/T-019c9c4d-266b-72d0-b56e-74a5777e6583.json +7 -0
- package/.local/share/amp/threads/T-019c9c52-ab89-758f-9178-bda99c39d10b.json +7 -0
- package/.local/share/opencode/opencode.db +0 -0
- package/.local/share/opencode/opencode.db-shm +0 -0
- package/.local/share/opencode/opencode.db-wal +0 -0
- package/.local/share/opencode/storage/agent-usage-reminder/ses_36870ea98ffe8S5ZOCE4F11yFh.json +6 -0
- package/.local/share/opencode/storage/agent-usage-reminder/ses_3687a3e9affewUnHBzvpiPR6df.json +6 -0
- package/.local/share/opencode/storage/agent-usage-reminder/ses_36886e68dffeKVgUWf6lzXdEEt.json +6 -0
- package/.local/share/opencode/storage/session_diff/ses_36870ea98ffe8S5ZOCE4F11yFh.json +1 -0
- package/.local/share/opencode/storage/session_diff/ses_3687a3e9affewUnHBzvpiPR6df.json +1 -0
- package/.local/share/opencode/storage/session_diff/ses_36886e68dffeKVgUWf6lzXdEEt.json +1 -0
- package/.local/state/replit/log-query.db +0 -0
- package/.local/state/replit/log-query.db-shm +0 -0
- package/.local/state/replit/log-query.db-wal +0 -0
- package/.upm/store.json +1 -1
- package/AGENTS.md +32 -0
- package/bun.lock +137 -103
- package/index.jsx +24 -0
- package/package.json +9 -9
- package/src/agent.js +252 -169
- package/src/app.jsx +96 -0
- package/src/commands.js +66 -38
- package/src/components/AssistantMessage.jsx +83 -0
- package/src/components/ChatArea.jsx +84 -0
- package/src/components/DiffView.jsx +26 -0
- package/src/components/Divider.jsx +8 -0
- package/src/components/Header.jsx +44 -0
- package/src/components/HelpModal.jsx +81 -0
- package/src/components/InputBar.jsx +32 -0
- package/src/components/Spinner.jsx +23 -0
- package/src/components/StatusBar.jsx +44 -0
- package/src/components/SystemMessage.jsx +31 -0
- package/src/components/ThinkBlock.jsx +29 -0
- package/src/components/ToolCallItem.jsx +43 -0
- package/src/components/UserMessage.jsx +11 -0
- package/src/components/Welcome.jsx +14 -0
- package/src/config.js +118 -2
- package/src/hooks/useLayout.js +15 -0
- package/src/hooks/useStore.js +6 -0
- package/src/prompt.js +67 -48
- package/src/store.js +99 -0
- package/src/theme.js +19 -0
- package/src/thinking.js +0 -24
- package/src/toolExecutors.js +521 -23
- package/src/tools.js +124 -4
- package/src/utils.js +32 -0
- package/tsconfig.json +10 -0
- package/index.js +0 -92
- package/src/ui.js +0 -269
|
@@ -0,0 +1,1637 @@
|
|
|
1
|
+
{
|
|
2
|
+
"v": 4788,
|
|
3
|
+
"id": "T-019c9c2e-71a4-77ff-bd7f-b053da7f9000",
|
|
4
|
+
"created": 1772146815401,
|
|
5
|
+
"messages": [
|
|
6
|
+
{
|
|
7
|
+
"role": "user",
|
|
8
|
+
"messageId": 0,
|
|
9
|
+
"content": [
|
|
10
|
+
{
|
|
11
|
+
"type": "text",
|
|
12
|
+
"text": "fix response streaming."
|
|
13
|
+
}
|
|
14
|
+
],
|
|
15
|
+
"userState": {
|
|
16
|
+
"currentlyVisibleFiles": []
|
|
17
|
+
},
|
|
18
|
+
"agentMode": "smart",
|
|
19
|
+
"meta": {
|
|
20
|
+
"sentAt": 1772146825420
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
"role": "assistant",
|
|
25
|
+
"messageId": 1,
|
|
26
|
+
"content": [
|
|
27
|
+
{
|
|
28
|
+
"type": "text",
|
|
29
|
+
"text": "\n\n"
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
"type": "thinking",
|
|
33
|
+
"thinking": "Let me first understand the codebase structure to find where response streaming is implemented.",
|
|
34
|
+
"signature": "EokCCkgICxACGAIqQKlkcYFkCYPLgmkqaX+DwLLfzGond9Yt50NmHXXKeT1TF5e0UQIhuDADtQonQX3SvGA5zm3jT3lE61cxTpQ5HegSDImrD1zAS7MzTDywIBoMk+0hWZJJD72/bkd8IjDQyEYra4Im0HK12V5SbiLJ+8GWKEyHjbQO59OAbUmUbIutrpga6EHeeZ5PN2YxSfgqb16aI5vh1QnUGmxwfgLq2jzb23+E8FrNhRJBNuJCCDdVjfOcv9plrFKfyz4RwixAWSQSLDrhA05F6xq+bltBj3gtwoFYpyH0F9Dj437Pf3Gtg9lhi1kJRgQENt1uPnopt9GFSRcNsnsSKZ0B17f4/xgB",
|
|
35
|
+
"provider": "anthropic"
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
"type": "tool_use",
|
|
39
|
+
"complete": true,
|
|
40
|
+
"id": "toolu_vrtx_01HuEuNhz6fnHpFkbrYjEQAH",
|
|
41
|
+
"name": "Read",
|
|
42
|
+
"input": {
|
|
43
|
+
"path": "/home/runner/workspace/src"
|
|
44
|
+
}
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
"type": "tool_use",
|
|
48
|
+
"complete": true,
|
|
49
|
+
"id": "toolu_vrtx_01AzxgvT7KzKf9zBNKk6zRHq",
|
|
50
|
+
"name": "Read",
|
|
51
|
+
"input": {
|
|
52
|
+
"path": "/home/runner/workspace/index.jsx"
|
|
53
|
+
}
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
"type": "tool_use",
|
|
57
|
+
"complete": true,
|
|
58
|
+
"id": "toolu_vrtx_01WP9PoJW6a4JEgx1fEbrhse",
|
|
59
|
+
"name": "Read",
|
|
60
|
+
"input": {
|
|
61
|
+
"path": "/home/runner/workspace/package.json"
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
],
|
|
65
|
+
"state": {
|
|
66
|
+
"type": "complete",
|
|
67
|
+
"stopReason": "tool_use"
|
|
68
|
+
},
|
|
69
|
+
"usage": {
|
|
70
|
+
"model": "claude-opus-4-6",
|
|
71
|
+
"maxInputTokens": 168000,
|
|
72
|
+
"inputTokens": 3,
|
|
73
|
+
"outputTokens": 177,
|
|
74
|
+
"cacheCreationInputTokens": 1590,
|
|
75
|
+
"cacheReadInputTokens": 13127,
|
|
76
|
+
"totalInputTokens": 14720,
|
|
77
|
+
"timestamp": "2026-02-26T23:00:30.568Z"
|
|
78
|
+
}
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
"role": "user",
|
|
82
|
+
"messageId": 2,
|
|
83
|
+
"content": [
|
|
84
|
+
{
|
|
85
|
+
"type": "tool_result",
|
|
86
|
+
"toolUseID": "toolu_vrtx_01HuEuNhz6fnHpFkbrYjEQAH",
|
|
87
|
+
"run": {
|
|
88
|
+
"status": "done",
|
|
89
|
+
"progress": {},
|
|
90
|
+
"result": {
|
|
91
|
+
"absolutePath": "/home/runner/workspace/src",
|
|
92
|
+
"content": "components/\nhooks/\nagent.js\napp.jsx\ncommands.js\nconfig.js\nprompt.js\nstore.js\ntheme.js\nthinking.js\ntoolExecutors.js\ntools.js\nutils.js",
|
|
93
|
+
"isDirectory": true,
|
|
94
|
+
"directoryEntries": [
|
|
95
|
+
"components/",
|
|
96
|
+
"hooks/",
|
|
97
|
+
"agent.js",
|
|
98
|
+
"app.jsx",
|
|
99
|
+
"commands.js",
|
|
100
|
+
"config.js",
|
|
101
|
+
"prompt.js",
|
|
102
|
+
"store.js",
|
|
103
|
+
"theme.js",
|
|
104
|
+
"thinking.js",
|
|
105
|
+
"toolExecutors.js",
|
|
106
|
+
"tools.js",
|
|
107
|
+
"utils.js"
|
|
108
|
+
]
|
|
109
|
+
},
|
|
110
|
+
"trackFiles": [
|
|
111
|
+
"file:///home/runner/workspace/src"
|
|
112
|
+
]
|
|
113
|
+
}
|
|
114
|
+
},
|
|
115
|
+
{
|
|
116
|
+
"type": "tool_result",
|
|
117
|
+
"toolUseID": "toolu_vrtx_01AzxgvT7KzKf9zBNKk6zRHq",
|
|
118
|
+
"run": {
|
|
119
|
+
"status": "done",
|
|
120
|
+
"progress": {},
|
|
121
|
+
"result": {
|
|
122
|
+
"absolutePath": "/home/runner/workspace/index.jsx",
|
|
123
|
+
"content": "1: #!/usr/bin/env bun\n2: import { createCliRenderer } from '@opentui/core';\n3: import { createRoot } from '@opentui/react';\n4: import { setRenderer } from './src/store.js';\n5: import App from './src/app.jsx';\n6: \n7: async function main() {\n8: const renderer = await createCliRenderer({\n9: useAlternateScreen: true,\n10: exitOnCtrlC: false,\n11: useMouse: true,\n12: });\n13: \n14: setRenderer(renderer);\n15: \n16: const root = createRoot(renderer);\n17: root.render(<App />);\n18: renderer.start();\n19: }\n20: \n21: main().catch(err => {\n22: console.error('Failed to start Apex:', err);\n23: process.exit(1);\n24: });"
|
|
124
|
+
},
|
|
125
|
+
"trackFiles": [
|
|
126
|
+
"file:///home/runner/workspace/index.jsx"
|
|
127
|
+
]
|
|
128
|
+
}
|
|
129
|
+
},
|
|
130
|
+
{
|
|
131
|
+
"type": "tool_result",
|
|
132
|
+
"toolUseID": "toolu_vrtx_01WP9PoJW6a4JEgx1fEbrhse",
|
|
133
|
+
"run": {
|
|
134
|
+
"status": "done",
|
|
135
|
+
"progress": {},
|
|
136
|
+
"result": {
|
|
137
|
+
"absolutePath": "/home/runner/workspace/package.json",
|
|
138
|
+
"content": "1: {\n2: \"name\": \"apex-dev\",\n3: \"version\": \"2.1.3\",\n4: \"description\": \"Apex AI - a friendly agentic coding assistant for the terminal\",\n5: \"main\": \"index.jsx\",\n6: \"bin\": {\n7: \"apex\": \"./index.jsx\"\n8: },\n9: \"scripts\": {\n10: \"start\": \"bun index.jsx\",\n11: \"test\": \"echo \\\"Error: no test specified\\\" && exit 1\"\n12: },\n13: \"keywords\": [],\n14: \"author\": \"\",\n15: \"license\": \"ISC\",\n16: \"dependencies\": {\n17: \"@opentui/core\": \"^0.1.83\",\n18: \"@opentui/react\": \"^0.1.83\",\n19: \"@sourcegraph/amp\": \"^0.0.1772067340-g53cd9b\",\n20: \"openai\": \"^6.25.0\",\n21: \"opencode-ai\": \"1.2.14\",\n22: \"react\": \"^19.2.4\"\n23: }\n24: }"
|
|
139
|
+
},
|
|
140
|
+
"trackFiles": [
|
|
141
|
+
"file:///home/runner/workspace/package.json"
|
|
142
|
+
]
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
]
|
|
146
|
+
},
|
|
147
|
+
{
|
|
148
|
+
"role": "assistant",
|
|
149
|
+
"messageId": 3,
|
|
150
|
+
"content": [
|
|
151
|
+
{
|
|
152
|
+
"type": "tool_use",
|
|
153
|
+
"complete": true,
|
|
154
|
+
"id": "toolu_vrtx_01KfdnfJpMQwqTZWvjSGU57u",
|
|
155
|
+
"name": "Read",
|
|
156
|
+
"input": {
|
|
157
|
+
"path": "/home/runner/workspace/src/agent.js"
|
|
158
|
+
}
|
|
159
|
+
},
|
|
160
|
+
{
|
|
161
|
+
"type": "tool_use",
|
|
162
|
+
"complete": true,
|
|
163
|
+
"id": "toolu_vrtx_014NoW2JgeX3iWTBpwQ9KTuE",
|
|
164
|
+
"name": "Read",
|
|
165
|
+
"input": {
|
|
166
|
+
"path": "/home/runner/workspace/src/store.js"
|
|
167
|
+
}
|
|
168
|
+
},
|
|
169
|
+
{
|
|
170
|
+
"type": "tool_use",
|
|
171
|
+
"complete": true,
|
|
172
|
+
"id": "toolu_vrtx_01C7nG9YpWYPnfXHyyhV9rZ4",
|
|
173
|
+
"name": "Read",
|
|
174
|
+
"input": {
|
|
175
|
+
"path": "/home/runner/workspace/src/components"
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
],
|
|
179
|
+
"state": {
|
|
180
|
+
"type": "complete",
|
|
181
|
+
"stopReason": "tool_use"
|
|
182
|
+
},
|
|
183
|
+
"usage": {
|
|
184
|
+
"model": "claude-opus-4-6",
|
|
185
|
+
"maxInputTokens": 168000,
|
|
186
|
+
"inputTokens": 1,
|
|
187
|
+
"outputTokens": 150,
|
|
188
|
+
"cacheCreationInputTokens": 2568,
|
|
189
|
+
"cacheReadInputTokens": 13127,
|
|
190
|
+
"totalInputTokens": 15696,
|
|
191
|
+
"timestamp": "2026-02-26T23:00:34.519Z"
|
|
192
|
+
}
|
|
193
|
+
},
|
|
194
|
+
{
|
|
195
|
+
"role": "user",
|
|
196
|
+
"messageId": 4,
|
|
197
|
+
"content": [
|
|
198
|
+
{
|
|
199
|
+
"type": "tool_result",
|
|
200
|
+
"toolUseID": "toolu_vrtx_01KfdnfJpMQwqTZWvjSGU57u",
|
|
201
|
+
"run": {
|
|
202
|
+
"status": "done",
|
|
203
|
+
"progress": {},
|
|
204
|
+
"result": {
|
|
205
|
+
"absolutePath": "/home/runner/workspace/src/agent.js",
|
|
206
|
+
"content": "1: 'use strict';\n2: \n3: const {\n4: NVIDIA_MODEL,\n5: MAX_TOOL_ITERATIONS,\n6: nvidiaClient,\n7: session,\n8: sleep,\n9: } = require('./config');\n10: const { buildSystemPrompt } = require('./prompt');\n11: const { toolDefs } = require('./tools');\n12: const { executeTool } = require('./toolExecutors');\n13: const { toolDetailStr } = require('./utils');\n14: const store = require('./store');\n15: const {\n16: parseThinkBlocks,\n17: findThinkClose,\n18: stripStrayCloseTag,\n19: splitAtPartialTag,\n20: } = require('./thinking');\n21: \n22: // ===== State =====\n23: let isProcessing = false;\n24: \n25: function getIsProcessing() { return isProcessing; }\n26: \n27: // ===== Exploration Detection =====\n28: const EXPLORATION_KEYWORDS = [\n29: 'explore', 'find files', 'where is', 'search for', 'locate',\n30: 'what files', 'which files', 'show me all', 'list all',\n31: 'find code', 'search code', 'find function', 'find class',\n32: 'find module', 'find component', 'find endpoint', 'find route',\n33: 'find api', 'find service', 'find model', 'find controller',\n34: 'where can i find', 'how do i find', 'look for',\n35: 'codebase structure', 'project structure', 'directory structure'\n36: ];\n37: \n38: function isExplorationTask(text) {\n39: const lower = text.toLowerCase();\n40: return EXPLORATION_KEYWORDS.some(keyword => lower.includes(keyword));\n41: }\n42: \n43: // ===== AI Conversation — Agentic Loop =====\n44: async function handleUserInput(userInput) {\n45: isProcessing = true;\n46: store.setState({ isProcessing: true });\n47: session.turnCount++;\n48: \n49: store.addMessage({ role: 'user', content: userInput });\n50: session.conversationHistory.push({ role: 'user', content: userInput });\n51: \n52: // Auto-delegate to FilePickerMax for exploration tasks\n53: if (isExplorationTask(userInput)) {\n54: const exploreId = store.addMessage({ role: 'system', content: 'Exploring codebase...', label: '🔍 Exploring' });\n55: try {\n56: const pickerResult = await executeTool('FilePickerMax', { prompt: userInput }, (partial) => {\n57: store.updateMessage(exploreId, { content: partial, label: '🔍 Exploring' });\n58: });\n59: store.updateMessage(exploreId, { content: pickerResult, label: '🔍 Codebase Exploration Results' });\n60: session.conversationHistory.push({\n61: role: 'assistant',\n62: content: `I've explored the codebase and found the following relevant files:\\n\\n${pickerResult}`,\n63: });\n64: } catch (err) {\n65: store.updateMessage(exploreId, { content: `Exploration failed: ${err.message}` });\n66: }\n67: }\n68: \n69: const startTime = Date.now();\n70: let turnTokens = 0;\n71: let turnToolCalls = 0;\n72: \n73: try {\n74: // Add assistant header message\n75: store.addMessage({ role: 'divider' });\n76: \n77: const systemPrompt = buildSystemPrompt();\n78: let messages = [\n79: { role: 'system', content: systemPrompt },\n80: ...session.conversationHistory,\n81: ];\n82: \n83: let iterations = 0;\n84: \n85: while (iterations < MAX_TOOL_ITERATIONS) {\n86: iterations++;\n87: \n88: let stream;\n89: const maxRetries = 3;\n90: for (let attempt = 0; attempt <= maxRetries; attempt++) {\n91: try {\n92: stream = await nvidiaClient.chat.completions.create({\n93: model: NVIDIA_MODEL,\n94: messages: messages.map(m => {\n95: const clean = { role: m.role, content: m.content };\n96: if (m.tool_calls) clean.tool_calls = m.tool_calls.map(tc => ({\n97: id: tc.id, type: 'function',\n98: function: { name: tc.function.name, arguments: tc.function.arguments },\n99: }));\n100: if (m.tool_call_id) clean.tool_call_id = m.tool_call_id;\n101: if (m.role === 'assistant' && !m.content) clean.content = null;\n102: return clean;\n103: }),\n104: max_tokens: 4096,\n105: temperature: 0.6,\n106: top_p: 0.95,\n107: tools: toolDefs,\n108: tool_choice: 'auto',\n109: stream: true,\n110: });\n111: break;\n112: } catch (apiErr) {\n113: if (attempt < maxRetries && apiErr.status >= 400 && apiErr.status < 500) {\n114: await sleep(1000 * Math.pow(2, attempt));\n115: continue;\n116: }\n117: throw apiErr;\n118: }\n119: }\n120: \n121: // Accumulate streamed response\n122: let fullContent = '';\n123: const toolCallDeltas = {};\n124: const toolCallMsgIds = {};\n125: const seenToolCalls = new Set();\n126: let finishReason = null;\n127: let streamUsage = null;\n128: let reasoningText = '';\n129: \n130: // Display state\n131: let displayState = 'buffering';\n132: let contentAccum = '';\n133: let thinkAccum = '';\n134: let displayContent = '';\n135: let thinkContent = '';\n136: let lastFlushTime = Date.now();\n137: \n138: for await (const chunk of stream) {\n139: if (chunk.usage) streamUsage = chunk.usage;\n140: \n141: const delta = chunk.choices?.[0]?.delta;\n142: if (!delta) {\n143: if (chunk.choices?.[0]?.finish_reason) finishReason = chunk.choices[0].finish_reason;\n144: continue;\n145: }\n146: if (chunk.choices[0].finish_reason) finishReason = chunk.choices[0].finish_reason;\n147: \n148: // Tool call deltas\n149: if (delta.tool_calls) {\n150: for (const tc of delta.tool_calls) {\n151: const idx = tc.index;\n152: if (!toolCallDeltas[idx]) {\n153: toolCallDeltas[idx] = { id: tc.id || '', name: tc.function?.name || '', arguments: '' };\n154: }\n155: if (tc.id) toolCallDeltas[idx].id = tc.id;\n156: if (tc.function?.name) {\n157: toolCallDeltas[idx].name = tc.function.name;\n158: if (!seenToolCalls.has(idx)) {\n159: seenToolCalls.add(idx);\n160: toolCallMsgIds[idx] = store.addMessage({\n161: role: 'tool',\n162: name: tc.function.name,\n163: detail: '...',\n164: status: 'pending',\n165: });\n166: }\n167: }\n168: if (tc.function?.arguments) {\n169: toolCallDeltas[idx].arguments += tc.function.arguments;\n170: }\n171: }\n172: }\n173: \n174: if (delta.reasoning_content) {\n175: reasoningText += delta.reasoning_content;\n176: }\n177: \n178: // Handle content tokens\n179: if (delta.content) {\n180: fullContent += delta.content;\n181: const hasTool = Object.keys(toolCallDeltas).length > 0;\n182: \n183: if (displayState === 'streaming') {\n184: contentAccum += delta.content;\n185: contentAccum = stripStrayCloseTag(contentAccum);\n186: const openIdx = contentAccum.indexOf('<think>');\n187: if (openIdx !== -1) {\n188: if (openIdx > 0) displayContent += contentAccum.slice(0, openIdx);\n189: thinkAccum = contentAccum.slice(openIdx + 7);\n190: contentAccum = '';\n191: displayState = 'thinking';\n192: const closeMatch = findThinkClose(thinkAccum);\n193: if (closeMatch) {\n194: const thought = thinkAccum.slice(0, closeMatch.pos).trim();\n195: const after = thinkAccum.slice(closeMatch.pos + closeMatch.len);\n196: thinkAccum = '';\n197: if (thought) store.addMessage({ role: 'thinking', content: thought });\n198: displayState = 'streaming';\n199: contentAccum = after;\n200: if (!hasTool && after) displayContent += after;\n201: contentAccum = '';\n202: thinkContent = '';\n203: } else {\n204: thinkContent = thinkAccum;\n205: }\n206: } else {\n207: const { safe, pending } = splitAtPartialTag(contentAccum);\n208: contentAccum = pending;\n209: if (!hasTool && safe) displayContent += safe;\n210: }\n211: store.updateStreaming(displayContent, thinkContent);\n212: \n213: } else if (displayState === 'thinking') {\n214: thinkAccum += delta.content;\n215: const closeMatch = findThinkClose(thinkAccum);\n216: if (closeMatch) {\n217: const thought = thinkAccum.slice(0, closeMatch.pos).trim();\n218: const after = thinkAccum.slice(closeMatch.pos + closeMatch.len);\n219: thinkAccum = '';\n220: if (thought) store.addMessage({ role: 'thinking', content: thought });\n221: displayState = 'streaming';\n222: contentAccum = after;\n223: if (!hasTool && after) displayContent += after;\n224: contentAccum = '';\n225: thinkContent = '';\n226: store.updateStreaming(displayContent, '');\n227: } else {\n228: thinkContent = thinkAccum;\n229: store.updateStreaming(displayContent, thinkContent);\n230: }\n231: \n232: } else {\n233: // buffering\n234: contentAccum += delta.content;\n235: contentAccum = stripStrayCloseTag(contentAccum);\n236: const openIdx = contentAccum.indexOf('<think>');\n237: if (openIdx !== -1) {\n238: const before = contentAccum.slice(0, openIdx);\n239: thinkAccum = contentAccum.slice(openIdx + 7);\n240: contentAccum = '';\n241: if (!hasTool && before.trim()) displayContent += before;\n242: displayState = 'thinking';\n243: const closeMatch = findThinkClose(thinkAccum);\n244: if (closeMatch) {\n245: const thought = thinkAccum.slice(0, closeMatch.pos).trim();\n246: const after = thinkAccum.slice(closeMatch.pos + closeMatch.len);\n247: thinkAccum = '';\n248: if (thought) store.addMessage({ role: 'thinking', content: thought });\n249: displayState = 'streaming';\n250: contentAccum = after;\n251: if (!hasTool && after) displayContent += after;\n252: contentAccum = '';\n253: thinkContent = '';\n254: } else {\n255: thinkContent = thinkAccum;\n256: }\n257: store.updateStreaming(displayContent, thinkContent);\n258: } else {\n259: const { safe, pending } = splitAtPartialTag(contentAccum);\n260: if (safe.length > 0) {\n261: displayState = 'streaming';\n262: if (!hasTool) displayContent += safe;\n263: contentAccum = pending;\n264: store.updateStreaming(displayContent, '');\n265: }\n266: }\n267: }\n268: }\n269: \n270: // Yield to the event loop periodically so the terminal renderer can paint\n271: const now = Date.now();\n272: if (now - lastFlushTime > 16) {\n273: lastFlushTime = now;\n274: await new Promise(r => setTimeout(r, 1));\n275: }\n276: }\n277: \n278: // Stream ended — flush remaining buffers\n279: if (displayState === 'thinking') {\n280: const thought = (thinkAccum + contentAccum).trim();\n281: if (thought) store.addMessage({ role: 'thinking', content: thought });\n282: thinkAccum = '';\n283: contentAccum = '';\n284: } else if (displayState === 'buffering') {\n285: const hasTool = Object.keys(toolCallDeltas).length > 0;\n286: if (!hasTool && contentAccum.trim()) displayContent += contentAccum;\n287: contentAccum = '';\n288: } else if (contentAccum) {\n289: const hasTool = Object.keys(toolCallDeltas).length > 0;\n290: if (!hasTool) displayContent += contentAccum;\n291: contentAccum = '';\n292: }\n293: \n294: // Show reasoning from reasoning_content field\n295: if (reasoningText.trim()) {\n296: store.addMessage({ role: 'thinking', content: reasoningText.trim() });\n297: }\n298: \n299: store.clearStreaming();\n300: \n301: const { content: parsedContent } = parseThinkBlocks(fullContent);\n302: turnTokens += streamUsage?.total_tokens || 0;\n303: \n304: // Reconstruct tool calls\n305: const sortedIndices = Object.keys(toolCallDeltas).sort((a, b) => a - b);\n306: const toolCalls = sortedIndices.map(idx => ({\n307: id: toolCallDeltas[idx].id,\n308: type: 'function',\n309: function: { name: toolCallDeltas[idx].name, arguments: toolCallDeltas[idx].arguments },\n310: }));\n311: \n312: const msg = {\n313: role: 'assistant',\n314: content: fullContent || null,\n315: ...(toolCalls.length > 0 ? { tool_calls: toolCalls } : {}),\n316: };\n317: \n318: // If the model wants to call tools\n319: if (toolCalls.length > 0) {\n320: messages.push(msg);\n321: \n322: // Show intermediate text if any\n323: if (displayContent.trim()) {\n324: store.addMessage({ role: 'assistant', content: displayContent.trim() });\n325: }\n326: \n327: // Update tool messages with full args and execute\n328: sortedIndices.forEach((idx, i) => {\n329: const tc = toolCalls[i];\n330: let toolArgs;\n331: try { toolArgs = JSON.parse(tc.function.arguments); } catch { toolArgs = {}; }\n332: const detail = toolDetailStr(tc.function.name, toolArgs);\n333: const msgId = toolCallMsgIds[idx];\n334: if (msgId) store.updateMessage(msgId, { detail, status: 'running' });\n335: });\n336: \n337: const toolPromises = toolCalls.map(async (toolCall, i) => {\n338: const toolName = toolCall.function.name;\n339: let toolArgs;\n340: try { toolArgs = JSON.parse(toolCall.function.arguments); } catch { toolArgs = {}; }\n341: const detail = toolDetailStr(toolName, toolArgs);\n342: const callStart = Date.now();\n343: const msgId = toolCallMsgIds[sortedIndices[i]];\n344: \n345: const result = await executeTool(toolName, toolArgs, (partial) => {\n346: if (msgId) store.updateMessage(msgId, { output: partial });\n347: });\n348: const success = !result.startsWith('Error');\n349: const elapsed = Date.now() - callStart;\n350: \n351: session.toolCallCount++;\n352: turnToolCalls++;\n353: \n354: if (msgId) {\n355: store.updateMessage(msgId, {\n356: detail,\n357: status: success ? 'done' : 'error',\n358: success,\n359: elapsed,\n360: output: result,\n361: });\n362: }\n363: \n364: // Show diff for edit operations\n365: if ((toolName === 'Edit' || toolName === 'Patch') && success) {\n366: store.addMessage({ role: 'diff', filename: toolArgs.path, content: result });\n367: }\n368: \n369: return { id: toolCall.id, result };\n370: });\n371: \n372: const toolResults = await Promise.all(toolPromises);\n373: \n374: for (const { id, result } of toolResults) {\n375: messages.push({ role: 'tool', tool_call_id: id, content: result });\n376: }\n377: \n378: if (finishReason === 'stop') break;\n379: displayContent = '';\n380: continue;\n381: }\n382: \n383: // No tool calls — final text response\n384: if (fullContent) {\n385: const cleanedContent = parsedContent.trim() || fullContent.replace(/<think>[\\s\\S]*?<\\/think>/g, '').trim();\n386: if (cleanedContent) {\n387: store.addMessage({ role: 'assistant', content: cleanedContent });\n388: }\n389: session.conversationHistory.push({ role: 'assistant', content: cleanedContent || fullContent });\n390: }\n391: break;\n392: }\n393: \n394: if (iterations >= MAX_TOOL_ITERATIONS) {\n395: store.addMessage({ role: 'system', content: `⚠ Reached maximum tool iterations (${MAX_TOOL_ITERATIONS}). Stopping.` });\n396: }\n397: \n398: session.totalTokens += turnTokens;\n399: \n400: // Auto-delegate to CodeReview for code changes\n401: if (session.filesModified.size > 0) {\n402: const reviewId = store.addMessage({ role: 'system', content: 'Reviewing code changes...', label: '📋 Code Review' });\n403: try {\n404: const reviewPrompt = `User request: ${userInput}\\n\\n${turnTokens > 0 ? `Processed with ${turnTokens} tokens and ${turnToolCalls} tool calls.` : ''}`;\n405: const reviewResult = await executeTool('CodeReview', { prompt: reviewPrompt }, (partial) => {\n406: store.updateMessage(reviewId, { content: partial, label: '📋 Code Review' });\n407: });\n408: store.updateMessage(reviewId, { content: reviewResult, label: '📋 Code Review' });\n409: session.conversationHistory.push({\n410: role: 'assistant',\n411: content: `\\n\\n--- Code Review ---\\n${reviewResult}`,\n412: });\n413: } catch (err) {\n414: store.updateMessage(reviewId, { content: `Code review failed: ${err.message}` });\n415: }\n416: }\n417: } catch (err) {\n418: store.clearStreaming();\n419: let errorMsg = `Error: ${err.message}`;\n420: if (err.status) {\n421: errorMsg += `\\nStatus: ${err.status}`;\n422: }\n423: if (!process.env.NVIDIA_API_KEY) {\n424: errorMsg += '\\nSet the NVIDIA_API_KEY environment variable with your API key from build.nvidia.com';\n425: }\n426: store.addMessage({ role: 'system', content: errorMsg });\n427: }\n428: \n429: store.addMessage({ role: 'divider' });\n430: isProcessing = false;\n431: store.setState({ isProcessing: false });\n432: }\n433: \n434: module.exports = {\n435: handleUserInput,\n436: getIsProcessing,\n437: };"
|
|
207
|
+
},
|
|
208
|
+
"trackFiles": [
|
|
209
|
+
"file:///home/runner/workspace/src/agent.js"
|
|
210
|
+
]
|
|
211
|
+
}
|
|
212
|
+
},
|
|
213
|
+
{
|
|
214
|
+
"type": "tool_result",
|
|
215
|
+
"toolUseID": "toolu_vrtx_014NoW2JgeX3iWTBpwQ9KTuE",
|
|
216
|
+
"run": {
|
|
217
|
+
"status": "done",
|
|
218
|
+
"progress": {},
|
|
219
|
+
"result": {
|
|
220
|
+
"absolutePath": "/home/runner/workspace/src/store.js",
|
|
221
|
+
"content": "1: 'use strict';\n2: \n3: let state = {\n4: messages: [],\n5: streamingContent: '',\n6: streamingThinking: '',\n7: isProcessing: false,\n8: showHelp: false,\n9: showSummary: false,\n10: };\n11: \n12: let nextId = 1;\n13: const listeners = new Set();\n14: let renderer = null;\n15: \n16: function getSnapshot() { return state; }\n17: \n18: function subscribe(listener) {\n19: listeners.add(listener);\n20: return () => listeners.delete(listener);\n21: }\n22: \n23: function notify() {\n24: for (const fn of listeners) fn();\n25: if (renderer) renderer.requestRender();\n26: }\n27: \n28: function setState(partial) {\n29: state = { ...state, ...partial };\n30: notify();\n31: }\n32: \n33: function addMessage(msg) {\n34: const id = nextId++;\n35: state = { ...state, messages: [...state.messages, { id, ...msg }] };\n36: notify();\n37: return id;\n38: }\n39: \n40: function updateMessage(id, updates) {\n41: state = {\n42: ...state,\n43: messages: state.messages.map(m => m.id === id ? { ...m, ...updates } : m),\n44: };\n45: notify();\n46: }\n47: \n48: function toggleMessageExpanded(id) {\n49: state = {\n50: ...state,\n51: messages: state.messages.map(m => m.id === id ? { ...m, expanded: !m.expanded } : m),\n52: };\n53: notify();\n54: }\n55: \n56: function updateStreaming(content, thinking) {\n57: state = { ...state, streamingContent: content || '', streamingThinking: thinking || '' };\n58: notify();\n59: }\n60: \n61: function clearStreaming() {\n62: state = { ...state, streamingContent: '', streamingThinking: '' };\n63: notify();\n64: }\n65: \n66: function clearMessages() {\n67: state = { ...state, messages: [] };\n68: notify();\n69: }\n70: \n71: function setRenderer(r) { renderer = r; }\n72: function getRenderer() { return renderer; }\n73: \n74: module.exports = {\n75: getSnapshot,\n76: subscribe,\n77: setState,\n78: addMessage,\n79: updateMessage,\n80: toggleMessageExpanded,\n81: updateStreaming,\n82: clearStreaming,\n83: clearMessages,\n84: setRenderer,\n85: getRenderer,\n86: };"
|
|
222
|
+
},
|
|
223
|
+
"trackFiles": [
|
|
224
|
+
"file:///home/runner/workspace/src/store.js"
|
|
225
|
+
]
|
|
226
|
+
}
|
|
227
|
+
},
|
|
228
|
+
{
|
|
229
|
+
"type": "tool_result",
|
|
230
|
+
"toolUseID": "toolu_vrtx_01C7nG9YpWYPnfXHyyhV9rZ4",
|
|
231
|
+
"run": {
|
|
232
|
+
"status": "done",
|
|
233
|
+
"progress": {},
|
|
234
|
+
"result": {
|
|
235
|
+
"absolutePath": "/home/runner/workspace/src/components",
|
|
236
|
+
"content": "AssistantMessage.jsx\nChatArea.jsx\nDiffView.jsx\nDivider.jsx\nHeader.jsx\nHelpModal.jsx\nInputBar.jsx\nSpinner.jsx\nStatusBar.jsx\nSystemMessage.jsx\nThinkBlock.jsx\nToolCallItem.jsx\nUserMessage.jsx\nWelcome.jsx",
|
|
237
|
+
"isDirectory": true,
|
|
238
|
+
"directoryEntries": [
|
|
239
|
+
"AssistantMessage.jsx",
|
|
240
|
+
"ChatArea.jsx",
|
|
241
|
+
"DiffView.jsx",
|
|
242
|
+
"Divider.jsx",
|
|
243
|
+
"Header.jsx",
|
|
244
|
+
"HelpModal.jsx",
|
|
245
|
+
"InputBar.jsx",
|
|
246
|
+
"Spinner.jsx",
|
|
247
|
+
"StatusBar.jsx",
|
|
248
|
+
"SystemMessage.jsx",
|
|
249
|
+
"ThinkBlock.jsx",
|
|
250
|
+
"ToolCallItem.jsx",
|
|
251
|
+
"UserMessage.jsx",
|
|
252
|
+
"Welcome.jsx"
|
|
253
|
+
]
|
|
254
|
+
},
|
|
255
|
+
"trackFiles": [
|
|
256
|
+
"file:///home/runner/workspace/src/components"
|
|
257
|
+
]
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
]
|
|
261
|
+
},
|
|
262
|
+
{
|
|
263
|
+
"role": "assistant",
|
|
264
|
+
"messageId": 5,
|
|
265
|
+
"content": [
|
|
266
|
+
{
|
|
267
|
+
"type": "tool_use",
|
|
268
|
+
"complete": true,
|
|
269
|
+
"id": "toolu_vrtx_01C7p2Dk4ezj6TNqLsaZgaji",
|
|
270
|
+
"name": "Read",
|
|
271
|
+
"input": {
|
|
272
|
+
"path": "/home/runner/workspace/src/components/ChatArea.jsx"
|
|
273
|
+
}
|
|
274
|
+
},
|
|
275
|
+
{
|
|
276
|
+
"type": "tool_use",
|
|
277
|
+
"complete": true,
|
|
278
|
+
"id": "toolu_vrtx_01BFA59jj7HfhhQrQb8zEt5i",
|
|
279
|
+
"name": "Read",
|
|
280
|
+
"input": {
|
|
281
|
+
"path": "/home/runner/workspace/src/hooks"
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
],
|
|
285
|
+
"state": {
|
|
286
|
+
"type": "complete",
|
|
287
|
+
"stopReason": "tool_use"
|
|
288
|
+
},
|
|
289
|
+
"usage": {
|
|
290
|
+
"model": "claude-opus-4-6",
|
|
291
|
+
"maxInputTokens": 168000,
|
|
292
|
+
"inputTokens": 1,
|
|
293
|
+
"outputTokens": 108,
|
|
294
|
+
"cacheCreationInputTokens": 9325,
|
|
295
|
+
"cacheReadInputTokens": 13127,
|
|
296
|
+
"totalInputTokens": 22453,
|
|
297
|
+
"timestamp": "2026-02-26T23:00:44.353Z"
|
|
298
|
+
}
|
|
299
|
+
},
|
|
300
|
+
{
|
|
301
|
+
"role": "user",
|
|
302
|
+
"messageId": 6,
|
|
303
|
+
"content": [
|
|
304
|
+
{
|
|
305
|
+
"type": "tool_result",
|
|
306
|
+
"toolUseID": "toolu_vrtx_01C7p2Dk4ezj6TNqLsaZgaji",
|
|
307
|
+
"run": {
|
|
308
|
+
"status": "done",
|
|
309
|
+
"progress": {},
|
|
310
|
+
"result": {
|
|
311
|
+
"absolutePath": "/home/runner/workspace/src/components/ChatArea.jsx",
|
|
312
|
+
"content": "1: import { TextAttributes } from '@opentui/core';\n2: import { colors } from '../theme.js';\n3: import { useLayout } from '../hooks/useLayout.js';\n4: import Welcome from './Welcome.jsx';\n5: import UserMessage from './UserMessage.jsx';\n6: import AssistantMessage from './AssistantMessage.jsx';\n7: import ThinkBlock from './ThinkBlock.jsx';\n8: import ToolCallItem from './ToolCallItem.jsx';\n9: import DiffView from './DiffView.jsx';\n10: import SystemMessage from './SystemMessage.jsx';\n11: import Spinner from './Spinner.jsx';\n12: import { toggleMessageExpanded } from '../store.js';\n13: \n14: function MessageItem({ message }) {\n15: const { width } = useLayout();\n16: switch (message.role) {\n17: case 'user':\n18: return <UserMessage content={message.content} />;\n19: case 'assistant':\n20: return (\n21: <box style={{ flexDirection: 'column', marginTop: 1 }}>\n22: <text fg={colors.primary} attributes={TextAttributes.BOLD} style={{ paddingLeft: 1 }} content=\"Apex\" />\n23: <AssistantMessage content={message.content} />\n24: </box>\n25: );\n26: case 'thinking':\n27: return (\n28: <ThinkBlock\n29: content={message.content}\n30: expanded={message.expanded}\n31: onToggle={() => toggleMessageExpanded(message.id)}\n32: />\n33: );\n34: case 'tool':\n35: return <ToolCallItem message={message} />;\n36: case 'diff':\n37: return <DiffView filename={message.filename} content={message.content} />;\n38: case 'system':\n39: return <SystemMessage message={message} />;\n40: case 'divider':\n41: return <text fg={colors.dim} style={{ paddingLeft: 1 }} content={'─'.repeat(Math.max(width - 2, 10))} />;\n42: default:\n43: return null;\n44: }\n45: }\n46: \n47: export default function ChatArea({ messages, streamingContent, streamingThinking, isProcessing }) {\n48: const { indent } = useLayout();\n49: return (\n50: <scrollbox\n51: style={{ flexGrow: 1 }}\n52: focused\n53: stickyScroll\n54: stickyStart=\"bottom\"\n55: scrollY\n56: >\n57: <box style={{ flexDirection: 'column' }}>\n58: <Welcome />\n59: {messages.map(msg => (\n60: <MessageItem key={msg.id} message={msg} />\n61: ))}\n62: {streamingThinking ? (\n63: <box style={{ paddingLeft: 2, marginTop: 0 }}>\n64: <text fg={colors.dim} attributes={TextAttributes.ITALIC}>\n65: <span fg={colors.dim}>{'▸ Thinking: '}</span>\n66: <span fg={colors.dim}>{streamingThinking.slice(-100)}</span>\n67: </text>\n68: </box>\n69: ) : null}\n70: {streamingContent ? (\n71: <box style={{ flexDirection: 'column', marginTop: 0 }}>\n72: <AssistantMessage content={streamingContent} isStreaming />\n73: </box>\n74: ) : null}\n75: {isProcessing && !streamingContent && !streamingThinking ? (\n76: <box style={{ paddingLeft: indent, marginTop: 1 }}>\n77: <Spinner label=\"Reasoning...\" />\n78: </box>\n79: ) : null}\n80: <box style={{ height: 1 }} />\n81: </box>\n82: </scrollbox>\n83: );\n84: }"
|
|
313
|
+
},
|
|
314
|
+
"trackFiles": [
|
|
315
|
+
"file:///home/runner/workspace/src/components/ChatArea.jsx"
|
|
316
|
+
]
|
|
317
|
+
}
|
|
318
|
+
},
|
|
319
|
+
{
|
|
320
|
+
"type": "tool_result",
|
|
321
|
+
"toolUseID": "toolu_vrtx_01BFA59jj7HfhhQrQb8zEt5i",
|
|
322
|
+
"run": {
|
|
323
|
+
"status": "done",
|
|
324
|
+
"progress": {},
|
|
325
|
+
"result": {
|
|
326
|
+
"absolutePath": "/home/runner/workspace/src/hooks",
|
|
327
|
+
"content": "useLayout.js\nuseStore.js",
|
|
328
|
+
"isDirectory": true,
|
|
329
|
+
"directoryEntries": [
|
|
330
|
+
"useLayout.js",
|
|
331
|
+
"useStore.js"
|
|
332
|
+
]
|
|
333
|
+
},
|
|
334
|
+
"trackFiles": [
|
|
335
|
+
"file:///home/runner/workspace/src/hooks"
|
|
336
|
+
]
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
]
|
|
340
|
+
},
|
|
341
|
+
{
|
|
342
|
+
"role": "assistant",
|
|
343
|
+
"messageId": 7,
|
|
344
|
+
"content": [
|
|
345
|
+
{
|
|
346
|
+
"type": "thinking",
|
|
347
|
+
"thinking": "Let me understand the streaming flow. The agent.js creates a stream, processes chunks, and calls `store.updateStreaming(displayContent, thinkContent)` to update the streaming state. The ChatArea.jsx component renders `streamingContent` and `streamingThinking`.\n\nLet me look at the issue more carefully. I need to understand what's broken with streaming.\n\nLooking at the streaming logic in agent.js:\n\n1. When `displayState === 'streaming'`, it appends to `contentAccum`, checks for `<think>` tags, and calls `store.updateStreaming(displayContent, thinkContent)`.\n\n2. When `displayState === 'buffering'`, it buffers content until it has enough to determine if it's a `<think>` tag or not.\n\n\n3. When `displayState === 'thinking'`, it accumulates think content.\n\nNow I'm examining the state machine more closely. The streaming path looks like it's accumulating content, stripping stray close tags, and checking for the opening `<think>` tag to determine whether to route content to display or thinking. Let me trace through what happens when that tag is found...\n\nWhen there's no `<think>` tag yet, the code splits the accumulated content at partial tags to separate safe characters from pending fragments, then adds the safe portion to display content while keeping the pending part for the next iteration. This seems correct—the display content builds up character by character while protecting incomplete tags.\n\nNow I'm checking the `store.updateStreaming` call placement in both states. In the streaming state it's called at the end of the block, which is right. But in the thinking state, I notice the store gets updated both when the closing tag is found and when it's not—let me trace through whether that's causing the issue. I see the issue now—when all content is pending during buffering, the store doesn't get updated, so the UI stays frozen. That's intentional to avoid showing partial `<think>` tags, but I need to understand what the actual streaming bug is. Let me check the helper functions in thinking.js to trace through the logic.",
|
|
348
|
+
"signature": "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",
|
|
349
|
+
"provider": "anthropic"
|
|
350
|
+
},
|
|
351
|
+
{
|
|
352
|
+
"type": "tool_use",
|
|
353
|
+
"complete": true,
|
|
354
|
+
"id": "toolu_vrtx_01N7Zmmmo1r2SEzAejZctxYP",
|
|
355
|
+
"name": "Read",
|
|
356
|
+
"input": {
|
|
357
|
+
"path": "/home/runner/workspace/src/thinking.js"
|
|
358
|
+
}
|
|
359
|
+
},
|
|
360
|
+
{
|
|
361
|
+
"type": "tool_use",
|
|
362
|
+
"complete": true,
|
|
363
|
+
"id": "toolu_vrtx_01UCqWbJtLuBbh9FvTCrGFZV",
|
|
364
|
+
"name": "Read",
|
|
365
|
+
"input": {
|
|
366
|
+
"path": "/home/runner/workspace/src/config.js"
|
|
367
|
+
}
|
|
368
|
+
},
|
|
369
|
+
{
|
|
370
|
+
"type": "tool_use",
|
|
371
|
+
"complete": true,
|
|
372
|
+
"id": "toolu_vrtx_01B4UW7AisRtwaVELL1YYnFX",
|
|
373
|
+
"name": "Read",
|
|
374
|
+
"input": {
|
|
375
|
+
"path": "/home/runner/workspace/src/components/AssistantMessage.jsx"
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
],
|
|
379
|
+
"state": {
|
|
380
|
+
"type": "complete",
|
|
381
|
+
"stopReason": "tool_use"
|
|
382
|
+
},
|
|
383
|
+
"usage": {
|
|
384
|
+
"model": "claude-opus-4-6",
|
|
385
|
+
"maxInputTokens": 168000,
|
|
386
|
+
"inputTokens": 1,
|
|
387
|
+
"outputTokens": 1223,
|
|
388
|
+
"cacheCreationInputTokens": 1290,
|
|
389
|
+
"cacheReadInputTokens": 22452,
|
|
390
|
+
"totalInputTokens": 23743,
|
|
391
|
+
"timestamp": "2026-02-26T23:01:11.357Z"
|
|
392
|
+
}
|
|
393
|
+
},
|
|
394
|
+
{
|
|
395
|
+
"role": "user",
|
|
396
|
+
"messageId": 8,
|
|
397
|
+
"content": [
|
|
398
|
+
{
|
|
399
|
+
"type": "tool_result",
|
|
400
|
+
"toolUseID": "toolu_vrtx_01N7Zmmmo1r2SEzAejZctxYP",
|
|
401
|
+
"run": {
|
|
402
|
+
"status": "done",
|
|
403
|
+
"progress": {},
|
|
404
|
+
"result": {
|
|
405
|
+
"absolutePath": "/home/runner/workspace/src/thinking.js",
|
|
406
|
+
"content": "1: 'use strict';\n2: \n3: function parseThinkBlocks(text) {\n4: const thinkRegex = /<think>([\\s\\S]*?)(?:<\\/think>|think>)/g;\n5: const thoughts = [];\n6: let match;\n7: while ((match = thinkRegex.exec(text)) !== null) {\n8: const content = match[1].trim();\n9: if (content) thoughts.push(content);\n10: }\n11: const cleaned = text.replace(/<think>[\\s\\S]*?(?:<\\/think>|think>)/g, '').trim();\n12: return { thoughts, content: cleaned };\n13: }\n14: \n15: function findThinkClose(text) {\n16: const fullClose = text.indexOf('</think>');\n17: if (fullClose !== -1) return { pos: fullClose, len: 8 };\n18: let searchFrom = 0;\n19: while (searchFrom < text.length) {\n20: const idx = text.indexOf('think>', searchFrom);\n21: if (idx === -1) break;\n22: if (idx === 0 || text[idx - 1] !== '<') return { pos: idx, len: 6 };\n23: searchFrom = idx + 6;\n24: }\n25: return null;\n26: }\n27: \n28: function stripStrayCloseTag(text) {\n29: return text.replace(/<\\/think>/g, '').replace(/(?<!<)think>/g, '');\n30: }\n31: \n32: function splitAtPartialTag(text) {\n33: const prefixes = [\n34: '</think>', '</think', '</thin', '</thi', '</th', '</t', '</',\n35: '<think>', '<think', '<thin', '<thi', '<th', '<t',\n36: 'think>', 'think', 'thin', 'thi', 'th',\n37: '<',\n38: ];\n39: for (const prefix of prefixes) {\n40: if (text.endsWith(prefix)) {\n41: if (prefix === '</think>' || prefix === 'think>') {\n42: return { safe: text.slice(0, -prefix.length), pending: '' };\n43: }\n44: return { safe: text.slice(0, -prefix.length), pending: prefix };\n45: }\n46: }\n47: return { safe: text, pending: '' };\n48: }\n49: \n50: module.exports = {\n51: parseThinkBlocks,\n52: findThinkClose,\n53: stripStrayCloseTag,\n54: splitAtPartialTag,\n55: };"
|
|
407
|
+
},
|
|
408
|
+
"trackFiles": [
|
|
409
|
+
"file:///home/runner/workspace/src/thinking.js"
|
|
410
|
+
]
|
|
411
|
+
}
|
|
412
|
+
},
|
|
413
|
+
{
|
|
414
|
+
"type": "tool_result",
|
|
415
|
+
"toolUseID": "toolu_vrtx_01UCqWbJtLuBbh9FvTCrGFZV",
|
|
416
|
+
"run": {
|
|
417
|
+
"status": "done",
|
|
418
|
+
"progress": {},
|
|
419
|
+
"result": {
|
|
420
|
+
"absolutePath": "/home/runner/workspace/src/config.js",
|
|
421
|
+
"content": "1: 'use strict';\n2: \n3: const OpenAI = require('openai');\n4: \n5: // ===== Config =====\n6: const NVIDIA_MODEL = 'z-ai/glm4.7';\n7: const REVIEWER_MODEL = 'nvidia/llama-3.3-nemotron-70b-instruct';\n8: const FILE_PICKER_MODEL = 'qwen/qwen3-coder-480b-a35b-instruct';\n9: const MAX_TOOL_ITERATIONS = 50;\n10: const MAX_OUTPUT_LEN = 12000;\n11: const TOOL_TIMEOUT = 60000;\n12: const PROJECT_ROOT = process.cwd();\n13: \n14: const REVIEWER_SYSTEM_PROMPT = `You are a senior code reviewer. An AI coding assistant just made changes to a codebase. Your job is to review those changes thoroughly and report issues. Be specific — reference exact line numbers, function names, and variables.\n15: \n16: The caller must always specify the exact files and changes to review. If you receive a vague or generic prompt, review only what is explicitly provided — do NOT infer or assume scope.\n17: \n18: Focus on:\n19: 1. **Bugs & logic errors** — incorrect conditions, off-by-one, null/undefined risks, race conditions\n20: 2. **Security** — exposed secrets, injection risks, unsafe operations\n21: 3. **Edge cases** — unhandled inputs, missing error handling at boundaries\n22: 4. **Code quality** — naming, readability, dead code, unnecessary complexity\n23: 5. **Correctness** — does the code actually fulfil the stated intent?\n24: \n25: If everything looks good, say so briefly. If there are problems, list them clearly with severity (critical / warning / nit). You have no tools; your only output is this review.`;\n26: \n27: const FILE_PICKER_SYSTEM_PROMPT = `You are a precision file-picker agent embedded inside a coding assistant. Your ONLY job is to identify the files in a codebase that are relevant to a given prompt.\n28: \n29: You will receive:\n30: 1. A full recursive directory tree of the project.\n31: 2. A preview (first 8 lines) of every source file.\n32: 3. A prompt specifying the exact type of files to find.\n33: \n34: Your task:\n35: - Analyze the directory tree and file previews carefully.\n36: - Select ONLY the files that are directly relevant to the prompt.\n37: - Rank them by relevance (most relevant first).\n38: - Be precise — do NOT include files that are only tangentially related.\n39: - If no files match, say so.\n40: - The caller must always specify the exact type of files they need. If you receive a vague or generic prompt like \"give me an overview of the codebase\", respond with an empty array — do NOT guess.\n41: \n42: Output format — return ONLY a JSON array of objects, nothing else:\n43: [\n44: { \"path\": \"relative/path/to/file.js\", \"reason\": \"Brief explanation of why this file is relevant\" }\n45: ]\n46: \n47: Do NOT wrap in markdown code fences. Output raw JSON only.`;\n48: \n49: const nvidiaClient = new OpenAI({\n50: apiKey: process.env.NVIDIA_API_KEY || '',\n51: baseURL: 'https://integrate.api.nvidia.com/v1',\n52: });\n53: \n54: // ===== Session State =====\n55: const session = {\n56: conversationHistory: [],\n57: totalTokens: 0,\n58: totalCost: 0,\n59: toolCallCount: 0,\n60: filesModified: new Set(),\n61: filesRead: new Set(),\n62: commandsRun: [],\n63: editHistory: [], // { path, before, after, timestamp }\n64: startTime: Date.now(),\n65: turnCount: 0,\n66: };\n67: \n68: // ===== Shared Utilities =====\n69: function truncateOutput(str) {\n70: if (str.length > MAX_OUTPUT_LEN) {\n71: return str.slice(0, MAX_OUTPUT_LEN) + `\\n... (truncated, ${str.length} chars total)`;\n72: }\n73: return str;\n74: }\n75: \n76: const path = require('path');\n77: \n78: function resolvePath(p) {\n79: if (!p) return PROJECT_ROOT;\n80: return path.isAbsolute(p) ? p : path.resolve(PROJECT_ROOT, p);\n81: }\n82: \n83: function timestamp() {\n84: return new Date().toLocaleTimeString([], { hour: '2-digit', minute: '2-digit', second: '2-digit' });\n85: }\n86: \n87: function sleep(ms) {\n88: return new Promise(r => setTimeout(r, ms));\n89: }\n90: \n91: module.exports = {\n92: NVIDIA_MODEL,\n93: REVIEWER_MODEL,\n94: MAX_TOOL_ITERATIONS,\n95: MAX_OUTPUT_LEN,\n96: TOOL_TIMEOUT,\n97: PROJECT_ROOT,\n98: FILE_PICKER_MODEL,\n99: FILE_PICKER_SYSTEM_PROMPT,\n100: REVIEWER_SYSTEM_PROMPT,\n101: nvidiaClient,\n102: session,\n103: truncateOutput,\n104: resolvePath,\n105: timestamp,\n106: sleep,\n107: };"
|
|
422
|
+
},
|
|
423
|
+
"trackFiles": [
|
|
424
|
+
"file:///home/runner/workspace/src/config.js"
|
|
425
|
+
]
|
|
426
|
+
}
|
|
427
|
+
},
|
|
428
|
+
{
|
|
429
|
+
"type": "tool_result",
|
|
430
|
+
"toolUseID": "toolu_vrtx_01B4UW7AisRtwaVELL1YYnFX",
|
|
431
|
+
"run": {
|
|
432
|
+
"status": "done",
|
|
433
|
+
"progress": {},
|
|
434
|
+
"result": {
|
|
435
|
+
"absolutePath": "/home/runner/workspace/src/components/AssistantMessage.jsx",
|
|
436
|
+
"content": "1: import { TextAttributes } from '@opentui/core';\n2: import { colors } from '../theme.js';\n3: import { useLayout } from '../hooks/useLayout.js';\n4: \n5: export default function AssistantMessage({ content, isStreaming }) {\n6: const { indent, isNarrow, width } = useLayout();\n7: const codeIndent = isNarrow ? 1 : 2;\n8: const separatorWidth = Math.min(width - indent - codeIndent, isNarrow ? 40 : 60);\n9: if (!content) return null;\n10: \n11: const lines = content.split('\\n');\n12: const rendered = [];\n13: let inCodeBlock = false;\n14: let codeLines = [];\n15: let codeLang = '';\n16: \n17: for (let i = 0; i < lines.length; i++) {\n18: const line = lines[i];\n19: \n20: if (line.startsWith('```') && !inCodeBlock) {\n21: inCodeBlock = true;\n22: codeLang = line.slice(3).trim() || 'code';\n23: codeLines = [];\n24: } else if (line.startsWith('```') && inCodeBlock) {\n25: inCodeBlock = false;\n26: rendered.push(\n27: <box key={`code-${i}`} style={{ flexDirection: 'column', paddingLeft: codeIndent, marginTop: 0 }}>\n28: <text fg={colors.dim} content={`── ${codeLang} ──`} />\n29: {codeLines.map((cl, j) => (\n30: <text key={j}>\n31: <span fg={colors.dim}>{String(j + 1).padStart(isNarrow ? 2 : 3) + ' │ '}</span>\n32: <span fg={colors.text}>{cl}</span>\n33: </text>\n34: ))}\n35: <text fg={colors.dim} content={'─'.repeat(Math.max(separatorWidth, 10))} />\n36: </box>\n37: );\n38: } else if (inCodeBlock) {\n39: codeLines.push(line);\n40: } else {\n41: const processed = line.replace(/`([^`]+)`/g, '«$1»');\n42: if (processed.includes('«')) {\n43: const parts = processed.split(/«|»/);\n44: rendered.push(\n45: <text key={`line-${i}`}>\n46: {parts.map((part, j) =>\n47: j % 2 === 0\n48: ? <span key={j} fg={colors.text}>{part}</span>\n49: : <span key={j} fg={colors.cyan}>{part}</span>\n50: )}\n51: </text>\n52: );\n53: } else {\n54: rendered.push(\n55: <text key={`line-${i}`}>\n56: <span fg={colors.text}>{line}</span>\n57: </text>\n58: );\n59: }\n60: }\n61: }\n62: \n63: if (inCodeBlock && codeLines.length > 0) {\n64: rendered.push(\n65: <box key=\"code-tail\" style={{ flexDirection: 'column', paddingLeft: codeIndent }}>\n66: <text fg={colors.dim} content={`── ${codeLang} ──`} />\n67: {codeLines.map((cl, j) => (\n68: <text key={j}>\n69: <span fg={colors.dim}>{String(j + 1).padStart(isNarrow ? 2 : 3) + ' │ '}</span>\n70: <span fg={colors.text}>{cl}</span>\n71: </text>\n72: ))}\n73: </box>\n74: );\n75: }\n76: \n77: return (\n78: <box style={{ flexDirection: 'column', paddingLeft: indent }}>\n79: {rendered}\n80: {isStreaming ? <text fg={colors.accent} content=\"▊\" /> : null}\n81: </box>\n82: );\n83: }"
|
|
437
|
+
},
|
|
438
|
+
"trackFiles": [
|
|
439
|
+
"file:///home/runner/workspace/src/components/AssistantMessage.jsx"
|
|
440
|
+
]
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
]
|
|
444
|
+
},
|
|
445
|
+
{
|
|
446
|
+
"role": "assistant",
|
|
447
|
+
"messageId": 9,
|
|
448
|
+
"content": [
|
|
449
|
+
{
|
|
450
|
+
"type": "thinking",
|
|
451
|
+
"thinking": "Now I need to understand the streaming issue more carefully. Let me trace through the logic:\n\n1. The streaming loop processes chunks from the API\n2. For each chunk with `delta.content`, it goes through a state machine with states: `buffering`, `streaming`, `thinking`\n3. The `store.updateStreaming(displayContent, thinkContent)` is called to update the UI\n\nLet me look at the key issues:\n\n**Issue 1: `displayContent` is a local string variable, not reset between iterations**\n\nLook at line 134: `let displayContent = '';`\nAnd line 379: `displayContent = '';`\n\nSo `displayContent` is reset at the end of each agentic loop iteration when there are tool calls. \n\n**Issue 2: The streaming content is only shown while streaming, but the final message is added as an `addMessage` call**\n\nWhen streaming ends without tool calls, the code cleans up the content by removing thinking tags and trimming whitespace, then adds the final message to the store. Before that happens, `clearStreaming()` is called to clear the streaming UI state.\n\nLet me trace through the actual flow to see if there's a gap between clearing the streaming display and adding the final message. The stream ends, remaining buffers are flushed, then `clearStreaming()` is called, followed by parsing and reconstruction logic. If there are no tool calls, the final message gets added right after. So there shouldn't be a visible gap where nothing is displayed.\n\nNow I'm looking more carefully at how the streaming display is built. The issue is that `hasTool` gets computed once per content token, but tool call deltas can arrive before content tokens do. If the model sends tool calls first, then content afterward, the `hasTool` flag might not be set correctly when deciding whether to display the content.\n\nActually, thinking about the API behavior—when a model returns both content and tool calls, they're often interleaved, and the code intentionally suppresses content display during tool calls since it would just be noise. Let me trace through the exact flow to understand what's happening: starting from the buffering state, when the first content token arrives, it gets accumulated and split at any partial tags, then added to the display if there are no active tool calls.\n\nNow I'm checking what happens with edge cases, like if content starts with a partial tag or if there's unexpected formatting.\n\nWhen a token arrives with `<think>` at the beginning, the code detects the opening tag immediately, extracts everything after it into the thinking accumulator, and switches the display state to thinking mode. Then when the closing `</think>` tag arrives in the next token, it processes that boundary and transitions back to displaying the response content. I'm seeing the issue now—`contentAccum` gets set to `after` but then immediately cleared to an empty string, while the content is already added to `displayContent`. This could be problematic if `after` contains a partial `<think>` tag since it won't be re-checked. I'm trying to identify what visible symptoms this bug would actually produce: missing content during streaming, garbled output, content disappearing and reappearing, duplicates, or a hanging stream.\n\nContinuing to trace through the state transitions when moving between streaming and thinking modes...\n\nStill analyzing the code flow... I'm realizing there might be an issue with how partial tags are handled when transitioning from thinking back to streaming content. The `after` content gets added to the display buffer without going through the partial tag check, which could cause problems if it contains an incomplete tag. Let me trace through the streaming state logic again to see if there are other edge cases I'm missing.\n\nActually, I'm noticing something important about the tool call flow: when `hasTool` is true, content gets accumulated in the display buffer but never actually shown to the user because of that flag. Then after the stream ends, if there's any trimmed content in the display buffer, it gets added as an assistant message. But I need to check what happens in the buffering state when tools are present...\n\nLooking at the conditions more carefully, I see that content is only added to `displayContent` when `!hasTool` is true across all three states. This means when tool calls are present, any text the model outputs alongside them gets completely skipped and never reaches `displayContent`. The content does get stored in `fullContent` though, so I need to trace where that's actually being used. I'm checking whether `thinkContent` gets properly cleared when transitioning from a think block to streaming output. Looking at the flow, `thinkContent` is reset to an empty string when entering the streaming state, and then on each content token it's passed to `store.updateStreaming` along with the accumulated display content. Let me trace through to confirm this is working correctly throughout the streaming phase. Now I'm checking how the UI consumes the streaming state from the store to render the assistant's message.",
|
|
452
|
+
"signature": "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",
|
|
453
|
+
"provider": "anthropic"
|
|
454
|
+
},
|
|
455
|
+
{
|
|
456
|
+
"type": "tool_use",
|
|
457
|
+
"complete": true,
|
|
458
|
+
"id": "toolu_vrtx_01AfdxdKZEpZMTY49jrKT2S5",
|
|
459
|
+
"name": "Read",
|
|
460
|
+
"input": {
|
|
461
|
+
"path": "/home/runner/workspace/src/app.jsx"
|
|
462
|
+
}
|
|
463
|
+
},
|
|
464
|
+
{
|
|
465
|
+
"type": "tool_use",
|
|
466
|
+
"complete": true,
|
|
467
|
+
"id": "toolu_vrtx_01NTSQpyrzFCh1p8VbgNCkvR",
|
|
468
|
+
"name": "Read",
|
|
469
|
+
"input": {
|
|
470
|
+
"path": "/home/runner/workspace/src/hooks/useStore.js"
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
],
|
|
474
|
+
"state": {
|
|
475
|
+
"type": "complete",
|
|
476
|
+
"stopReason": "tool_use"
|
|
477
|
+
},
|
|
478
|
+
"usage": {
|
|
479
|
+
"model": "claude-opus-4-6",
|
|
480
|
+
"maxInputTokens": 168000,
|
|
481
|
+
"inputTokens": 1,
|
|
482
|
+
"outputTokens": 3537,
|
|
483
|
+
"cacheCreationInputTokens": 4575,
|
|
484
|
+
"cacheReadInputTokens": 23742,
|
|
485
|
+
"totalInputTokens": 28318,
|
|
486
|
+
"timestamp": "2026-02-26T23:02:19.614Z"
|
|
487
|
+
}
|
|
488
|
+
},
|
|
489
|
+
{
|
|
490
|
+
"role": "user",
|
|
491
|
+
"messageId": 10,
|
|
492
|
+
"content": [
|
|
493
|
+
{
|
|
494
|
+
"type": "tool_result",
|
|
495
|
+
"toolUseID": "toolu_vrtx_01AfdxdKZEpZMTY49jrKT2S5",
|
|
496
|
+
"run": {
|
|
497
|
+
"status": "done",
|
|
498
|
+
"progress": {},
|
|
499
|
+
"result": {
|
|
500
|
+
"absolutePath": "/home/runner/workspace/src/app.jsx",
|
|
501
|
+
"content": "1: import { useCallback } from 'react';\n2: import { useKeyboard } from '@opentui/react';\n3: import { useStore } from './hooks/useStore.js';\n4: import { setState, addMessage, clearMessages, getRenderer } from './store.js';\n5: import { session } from './config.js';\n6: import { handleUserInput } from './agent.js';\n7: import { handleSlashCommand } from './commands.js';\n8: import Header from './components/Header.jsx';\n9: import Divider from './components/Divider.jsx';\n10: import ChatArea from './components/ChatArea.jsx';\n11: import InputBar from './components/InputBar.jsx';\n12: import StatusBar from './components/StatusBar.jsx';\n13: import HelpModal from './components/HelpModal.jsx';\n14: \n15: function exitApp() {\n16: const renderer = getRenderer();\n17: if (renderer) renderer.destroy();\n18: \n19: const elapsed = ((Date.now() - session.startTime) / 1000 / 60).toFixed(1);\n20: const parts = [\n21: `${elapsed} min`,\n22: `${session.turnCount} turns`,\n23: `${session.toolCallCount} tool calls`,\n24: `${session.totalTokens.toLocaleString()} tokens`,\n25: `$${session.totalCost.toFixed(4)}`,\n26: ];\n27: if (session.filesModified.size > 0) parts.push(`${session.filesModified.size} files modified`);\n28: if (session.commandsRun.length > 0) parts.push(`${session.commandsRun.length} commands`);\n29: \n30: console.log(`\\n Session: ${parts.join(' · ')}\\n`);\n31: console.log(' Goodbye! ✦\\n');\n32: process.exit(0);\n33: }\n34: \n35: export default function App() {\n36: const state = useStore();\n37: \n38: useKeyboard((key) => {\n39: if (key.ctrl && key.name === 'c') {\n40: exitApp();\n41: }\n42: });\n43: \n44: const handleInput = useCallback(async (value) => {\n45: if (value === 'exit' || value === 'quit') {\n46: exitApp();\n47: return;\n48: }\n49: \n50: if (value.startsWith('/')) {\n51: const result = await handleSlashCommand(value);\n52: if (result?.action === 'quit') {\n53: exitApp();\n54: }\n55: return;\n56: }\n57: \n58: handleUserInput(value).catch(err => {\n59: addMessage({ role: 'system', content: `Error: ${err.message}` });\n60: setState({ isProcessing: false });\n61: });\n62: }, []);\n63: \n64: const handleHelpCommand = useCallback((cmd) => {\n65: if (cmd) {\n66: handleSlashCommand(cmd).then(result => {\n67: if (result?.action === 'quit') exitApp();\n68: });\n69: }\n70: }, []);\n71: \n72: return (\n73: <box style={{ flexDirection: 'column', flexGrow: 1 }}>\n74: <Header />\n75: <Divider />\n76: <ChatArea\n77: messages={state.messages}\n78: streamingContent={state.streamingContent}\n79: streamingThinking={state.streamingThinking}\n80: isProcessing={state.isProcessing}\n81: />\n82: <Divider />\n83: <StatusBar isProcessing={state.isProcessing} />\n84: <InputBar\n85: disabled={state.isProcessing || state.showHelp}\n86: onSubmit={handleInput}\n87: />\n88: {state.showHelp ? (\n89: <HelpModal\n90: onClose={() => setState({ showHelp: false })}\n91: onCommand={handleHelpCommand}\n92: />\n93: ) : null}\n94: </box>\n95: );\n96: }"
|
|
502
|
+
},
|
|
503
|
+
"trackFiles": [
|
|
504
|
+
"file:///home/runner/workspace/src/app.jsx"
|
|
505
|
+
]
|
|
506
|
+
}
|
|
507
|
+
},
|
|
508
|
+
{
|
|
509
|
+
"type": "tool_result",
|
|
510
|
+
"toolUseID": "toolu_vrtx_01NTSQpyrzFCh1p8VbgNCkvR",
|
|
511
|
+
"run": {
|
|
512
|
+
"status": "done",
|
|
513
|
+
"progress": {},
|
|
514
|
+
"result": {
|
|
515
|
+
"absolutePath": "/home/runner/workspace/src/hooks/useStore.js",
|
|
516
|
+
"content": "1: import { useSyncExternalStore } from 'react';\n2: import { subscribe, getSnapshot } from '../store.js';\n3: \n4: export function useStore() {\n5: return useSyncExternalStore(subscribe, getSnapshot);\n6: }"
|
|
517
|
+
},
|
|
518
|
+
"trackFiles": [
|
|
519
|
+
"file:///home/runner/workspace/src/hooks/useStore.js"
|
|
520
|
+
]
|
|
521
|
+
}
|
|
522
|
+
}
|
|
523
|
+
]
|
|
524
|
+
},
|
|
525
|
+
{
|
|
526
|
+
"role": "assistant",
|
|
527
|
+
"messageId": 11,
|
|
528
|
+
"content": [
|
|
529
|
+
{
|
|
530
|
+
"type": "thinking",
|
|
531
|
+
"thinking": "Now I need to understand the streaming issue. Let me analyze the code more carefully.\n\nThe `useStore` hook uses `useSyncExternalStore` with `subscribe` and `getSnapshot`. Let me look at the store:\n\n```javascript\nfunction getSnapshot() { return state; }\n```\n\nThis returns the `state` object directly. The key issue with `useSyncExternalStore` is that it uses `Object.is` to compare the old and new snapshots. If `getSnapshot` returns a new object reference each time (which `setState` does by creating a new object with `{...state, ...partial}`), then React should trigger a re-render.\n \nSo `getSnapshot` returns the module-level `state` variable, and each time `setState` or other mutators run, they assign a new object to `state`, meaning `useSyncExternalStore` should detect the reference change and re-render. But there's also `renderer.requestRender()` being called in the `notify` function—I should check if that's actually necessary. The real issue might be that `updateStreaming` fires so frequently with each token that the notifications or renders are getting batched or debounced somewhere.\n\nLooking at the store code, every `updateStreaming` call creates a fresh state object and triggers `notify()`, which calls `renderer.requestRender()`, so re-renders should happen. Tracing through the streaming flow in `agent.js`: the API stream processes each chunk, calls `store.updateStreaming()`, and yields to the event loop every 16ms with `setTimeout(r, 1)` to let the renderer paint. That seems fine, but there might be a module interop issue—`agent.js` uses CommonJS `require()` while the store also uses `module.exports`, but the hooks and components are using ES modules.\n\nI'm realizing this could be a dual module instance problem. If `agent.js` loads the store as CommonJS and the React hooks load it as ES modules, Bun might create two separate module instances, meaning `agent.js` is updating one state object while the hooks are reading from a completely different one.\n\nLooking at the imports across the codebase confirms this — `agent.js` uses `require()` while all the other files use `import` statements, so they're likely operating on different store instances. That would explain why the streaming updates never reach the UI.\n\nBut wait, if that were true, messages wouldn't appear at all, and the user said they do. Bun actually has pretty solid CJS/ESM interoperability, so maybe the dual instance theory doesn't hold here...\n\nLet me look at the store implementation more carefully. The `getSnapshot` function returns the state object directly, which should be stable as long as the state reference doesn't change unnecessarily. And `updateStreaming` creates a new state object each time it's called, which triggers the notify function to alert subscribers. So that part seems correct too.\n\nNow I'm tracing through what happens when content starts buffering and gets streamed out. When the display state is buffering and there's safe content to show, it switches to streaming mode, accumulates the content, and calls `updateStreaming` to push that to the store. Let me check what happens next in the buffering logic...\n\nWhen `splitAtPartialTag` encounters something like `'<t'`, it checks against a list of possible tag prefixes to see if we're in the middle of a tag that might be `<think>`. Checking the prefix matching logic... I've already covered that scenario. The buffering approach for partial tags might delay the first few characters, but that's intentional to properly detect think blocks.\n\nLet me reconsider what \"fix response streaming\" could actually mean by examining potential bugs. One issue could be content duplication when transitioning between buffering and streaming states—when a think tag opens and closes immediately, the content after it gets added to displayContent, then on the next token fresh content appends without duplication, so that seems fine. Another possibility is lost content when the stream ends while still in buffering state.\n\nLooking at the cleanup logic, when displayState is buffering and the stream ends, any accumulated content gets added to displayContent before clearing. Then clearStreaming() is called and the final message is added separately through addMessage(). The content isn't actually lost, but there's a potential visual glitch—between clearing the streaming display and adding the final message, the user might briefly see the \"Reasoning...\" spinner reappear since isProcessing is still true while streamingContent is empty.\n\nBut the real issue emerges when tool calls are involved: the conditional check `if (!hasTool && contentAccum.trim())` means displayContent never gets updated with final chunks when tools are present, so the addMessage() call at the end would be adding empty or incomplete content.\n\nActually, let me reconsider whether this is intentional—the model's reasoning is already captured through the thinking mechanism, so maybe suppressing content during tool calls is by design. Let me trace through the code more carefully to see what I'm actually missing here.\n\nI'm looking at the streaming state when there's no think block and no tool calls, and I notice that `thinkContent` might be stale when we call `store.updateStreaming`. Let me verify the flow: `thinkContent` starts empty, gets cleared after exiting a think block, and is properly reset before the update call. So that's not the issue.\n\nChecking where `displayContent` gets accumulated...\n\nActually, I'm seeing a potential mismatch. During streaming, `displayContent` builds up from safe content chunks, but at the end when the stream finishes, we parse `fullContent` (which includes everything with think tags) and strip out the think blocks. The question is whether what was shown during streaming matches what gets saved as the final message. tokens with `<think>` blocks removed via the state machine.\n\n`cleanedContent` is built by applying `parseThinkBlocks` to `fullContent` (which includes think tags). `parseThinkBlocks` strips `<think>...</think>` blocks.\n\nThese SHOULD produce the same text. But wait — `displayContent` goes through `stripStrayCloseTag` which removes stray `</think>` and `think>` tags. And `parseThinkBlocks` uses the regex `/<think>[\\s\\S]*?(?:<\\/think>|think>)/g` which matches `<think>...</think>` or `<think>...think>`.\n\nIf there are mismatched tags, these could produce different results. But in practice, they should be the same.\n\nWhen streaming ends without tool calls, `clearStreaming()` removes the streaming display, then `addMessage()` adds the final content as a permanent message. Between clearing the stream and adding the message, there's a series of fast synchronous operations — parsing think blocks, updating token counts, and reconstructing tool calls — but this brief gap could create a momentary flicker where the user sees nothing before the final message appears.\n\nThe real issue might be with how the stream itself is being handled. The API call uses `stream: true`, returning an async iterable that I need to examine more closely.\n\nLooking at the retry logic, I see it retries on 4xx status codes, but that seems wrong since 4xx errors typically indicate client-side issues that won't be fixed by retrying. Meanwhile, 5xx server errors—which actually benefit from retries—would immediately throw without any retry attempt. This logic is inverted, and it means rate-limit errors (429) get retried while actual server failures don't.\n\nNow I'm looking at the streaming parsing logic more carefully. There's a function that strips out `</think>` and `think>` tags, and it's being called every single time a new content token arrives during streaming. This repeated stripping could be problematic because it's processing the entire accumulated content buffer over and over again instead of just handling new deltas.\n\nLet me trace through the `useStore` hook to understand how the state management works... I'm realizing the real bottleneck might be that `App` re-renders entirely whenever any state changes, even just streaming content updates, which cascades down to all child components like `InputBar` and `StatusBar` unnecessarily. This is a performance issue rather than a correctness problem, but worth investigating what's actually causing the lag.\n\nLet me look more carefully at the stream handling in `agent.js` — specifically how content tokens are being processed and accumulated, and whether the OpenAI SDK is properly streaming chunks.\n\nThe newer SDK versions return an `AsyncIterable<ChatCompletionChunk>` where each chunk's `choices[0].delta` can contain `content`, `tool_calls`, `role`, and potentially other fields like `refusal`. The NVIDIA-hosted model might have different streaming behavior than standard OpenAI models — it could be sending `reasoning_content` fields or embedding think tags directly in the content, which the code does handle. Let me check if there's something specific about how this model formats its delta chunks that might be causing the streaming to break.\n\nLooking at the code, I see it captures `delta.reasoning_content` and accumulates it into `reasoningText`, but this only gets added as a message after the stream completes. The issue is that during streaming, `thinkContent` only tracks `<think>` blocks within the content itself, not the `reasoning_content` field. So if the model relies on `reasoning_content` for its thinking output, the user would see a \"Reasoning...\" spinner but no actual thinking content displayed until the stream finishes. The real problem might be that the streaming display isn't properly handling this model's specific output format. Continuing to trace through the token stream, I'm checking whether \" how\" contains any partial tag prefixes that would need to be held back, and it looks like it doesn't, so the full token gets added to the display.\n\nNow I'm moving into a more complex scenario where the model actually sends a `<think>` tag to see how the buffering logic handles it. Continuing through the token stream, when `>` arrives the opening tag is finally complete, so I transition to thinking mode with an empty accumulator and no closing tag found yet. As \"Let me\" streams in, the thinking content builds up and gets displayed. Now I'm checking what happens when \" think\" arrives to see if it completes the closing tag pattern. store.updateStreaming('', 'Let me think...</think') ✓\n\n9. Token `>`:\n - `thinkAccum = 'Let me think...</think>'`\n - `findThinkClose(...)`:\n - `text.indexOf('</think>')` → 11 (found!)\n - Extracts `thinkContent = 'Let me think...'`\n - Returns `{ content: 'Let me think...', remaining: '' }`\n - Exits thinking mode, `thinkContent` is finalized\n - `store.updateStreaming('Let me think...', '')` ✓\n\nSo the logic correctly handles the streaming case where `</think>` arrives in fragments across multiple tokens. Now as the stream continues, I'm processing the regular content tokens—\"Here\" and \"'s my answer\"—which flow through the normal streaming path since there are no thinking tags, and the display updates to show the accumulated response text.\n\nOnce the stream ends, the parsed content gets saved as a message. But I'm realizing the actual issue might be different—when tool calls arrive after content, the code checks for tool deltas while processing content, but at that point the tool calls haven't been received yet, so it treats the message as pure content and displays it immediately. Then when tool call deltas do arrive later, the already-displayed content stays visible.\n\nChecking the conditional logic... I'm looking at the `splitAtPartialTag` function that handles incomplete XML tags at the end of text chunks—it checks for various partial closing and opening tag patterns to determine what's safe to display versus what needs to be held back as pending content.\n\nI'm realizing there's a problem with how it treats the word \"think\" as a prefix to match. If the content ends with the word \"think\" (like \"Let me think\"), the function would hold it as pending even though it's just regular English text, not part of a tag. This delays common words unnecessarily, and if \"think\" happens to be the final token in the stream, it would get stuck in the pending buffer and never be flushed.\n\nThe flush logic does eventually output the accumulated content, so it's not a correctness issue, but there are other partial matches that cause similar latency problems—words ending in \"t\" followed by \"h\" like \"with\" or \"path\" would have their last two characters buffered at token boundaries, creating unnecessary delays.\n\nI've been scrutinizing the state machine logic and haven't found an obvious streaming bug yet. The issue might be elsewhere: the NVIDIA API could be returning a stream that isn't properly async iterable, or there could be something subtle in how `finish_reason` is being tracked across the different conditional branches.\n\nNow I'm wondering if the real problem is in how the CommonJS module imports interact with the Bun runtime, particularly around the `store` object and whether those update methods are actually being called correctly. Checking if Bun treats CJS and ESM modules as the same instance when importing across formats, since this could be the dual package hazard issue where Node.js creates separate instances but Bun might handle it differently.\n\nWait, I'm noticing that `agent.js` uses `require('./store')` without the `.js` extension while ESM imports use `'../store.js'` with it — could Bun be resolving these to different files? Both should resolve to the same `store.js` file though, and Bun shares the module cache between CJS and ESM anyway.\n\nLet me step back and look at the actual symptoms instead of getting lost in module resolution details. The streaming content is probably flickering or jumping between when `clearStreaming()` runs and when the final content gets added.\n\nActually, I think I found it — during streaming, `updateStreaming()` displays the content temporarily, then `clearStreaming()` removes it, and `addMessage()` adds it back as a permanent message. The user would see the content disappear and reappear, which feels janky even though it's technically the normal flow for streaming chat. The real issue would only occur if `clearStreaming()` doesn't properly clean up or if the content differs between the streaming and final versions.\n\nThe key question is whether `clearStreaming()` and `addMessage()` are batched together in React 18+. They're not in the same synchronous block — there's code between them — so they might trigger separate renders. And if `requestRender()` is synchronous, it could cause a visible flicker before the final message appears.\n\nLet me step back and focus on the most likely culprits for streaming bugs: content not appearing during streaming, or content appearing but then disappearing unexpectedly.\n\nI'm noticing something in the final message handling after tool calls complete — when the loop breaks on `finishReason === 'stop'`, the final content has already been added to messages and potentially displayed, but then the code continues to line 383 where it checks `fullContent`, which might be causing duplicate or conflicting content to appear.\n\nActually, looking more carefully at the variable declarations, they're all scoped inside the while loop, so they reset each iteration. Let me reconsider what's actually happening here. Maybe the real issue is that when the model returns only tool calls without any content, the streaming UI just shows a spinner with no intermediate text feedback, or there's an error during tool execution that isn't being properly caught and handled.\n\nWait, I'm noticing something about the store's notification system—every state update triggers all listeners and requests a render, which could happen hundreds of times per second during streaming. There's a throttle on the event loop yield, but `updateStreaming` gets called on every content delta, potentially causing performance degradation or rendering issues. jank or lag. Let me step back and focus on what could actually be broken. I'm going to trace through the state transitions systematically—specifically checking whether `updateStreaming` gets called in every code path that handles content. Looking at the buffering state, I can see the think block detection and content accumulation logic, but I need to verify all branches are properly updating the store.\n\nScanning through the different states and their conditions, I notice there's a gap: when buffering with no think tag and no safe content to display, the code doesn't call `updateStreaming` at all. That's the bug—content could get stuck in the accumulator without ever being flushed to the store.\n\nNow let me trace through what happens when the stream ends to see how the remaining buffers get handled.\n\nLooking at the end-of-stream logic, I see that when we're in the buffering state, any accumulated content gets flushed to `displayContent`, which is then passed to `store.addMessage()` if there are no tool calls or if there's actual content to display. So the buffering mechanism is essentially a safety check to avoid showing incomplete `<think>` tags, and once we're confident about what we have, it gets added to the message store. cases where they might diverge—like malformed think tags or nested structures—could cause the stored message to differ from what was displayed. Let me trace through a potential edge case to see if there's actually a bug here. I'm checking whether the spacing works out correctly when content before and after the `<think>` tags gets combined — it should preserve the original text. But I'm realizing the real issue might be simpler: the OpenAI SDK's stream implementation for the NVIDIA endpoint could be failing to properly handle the async iteration, or the stream itself might be stalling partway through.\n\nLooking at the SDK version being used, it's v6, which may have changed how streaming works compared to earlier versions. The `for await` loop should theoretically work regardless, but I'm wondering if there's a module format mismatch — the code uses CommonJS with `require()` and `module.exports`, which could be causing compatibility issues with how the stream is being consumed.\n\nNow I'm realizing the real issue might be the module system itself. Without a `\"type\"` field in package.json, Bun treats `.js` files as CommonJS while `.jsx` files are always ESM, so there's a mix of module formats across the codebase that could be breaking the stream handling. I'm tracing through how the store updates propagate: when `updateStreaming` is called in `agent.js`, it updates the state object, triggers `notify()` to call all listeners, React's subscriber gets the new snapshot via `getSnapshot()`, and since it's a new object reference, React detects the change and re-renders. The `renderer.requestRender()` should then handle the terminal repaint. I've been circling around the module sharing and subscription flow, so let me focus on identifying and fixing the actual issues rather than continuing to verify what should already work.\n\nLooking at the specific problems: `thinkContent` might carry over from previous iterations in the non-think-block case, the initial content gets delayed when buffering until enough characters accumulate, there's a potential visual jump when streaming content transitions to the final message due to slight differences in how they're processed, and `clearStreaming` followed by `addMessage` aren't atomic which could cause a brief flash. Let me examine that last issue more closely since it seems like the most likely culprit for visible glitches.\n\nThe problem is that between clearing the streaming state and adding the final message, there's a window where `isProcessing` is still true but both `streamingContent` and `streamingThinking` are empty, which triggers the reasoning spinner to appear momentarily before the final message renders.\n\nThe cleanest solution would be to defer clearing the streaming display until after the final message is added to the store, or only clear it when there are actual tool calls to process. Looking at the code flow, `clearStreaming()` gets called at line 299 inside the while loop before checking for tool calls, which is where the timing issue originates. I need to clear the streaming state before executing tools since that can take time, but for the final response path I should clear it right before adding the message to avoid that gap. The simplest solution is to move `clearStreaming()` into both branches—call it before tool execution and again before `addMessage()` when there are no tool calls. I'm realizing the cleanest approach is to combine the clearing and message addition into a single atomic operation in the store, so there's no flash between state updates when the streaming content disappears and the final message appears. I see the issue now—even if I add the message first and then clear streaming, there's still a frame where both the streaming content and final message are visible together, creating a jarring duplicate. What I really need is to batch these operations into a single state update that clears the streaming content and adds the final message at the same time, so the UI transitions cleanly without showing both versions.\n\nLet me verify the module exports and imports are consistent across the codebase...\n\nChecking CommonJS usage...\n\nThe React component imports from the store using ESM syntax, which should work fine with Bun's interop layer. Now I'm thinking the real issue might be that the streaming display shows different content than what gets saved as the final message—like accumulated safe chunks versus the full parsed content—causing a jarring transition when streaming completes.\n\nLooking at the final message logic, I see it's using `parsedContent.trim()` as the primary source, falling back to stripping think blocks from the full content. The difference between what was shown during streaming and what appears after could come from how whitespace is handled differently between the accumulated display chunks and the regex-based cleanup. I'm identifying the core issues causing problems with response streaming: the spinner flickers because `clearStreaming()` runs before `addMessage()`, the partial tag detection is too sensitive and causes stuttering when common substrings appear at token boundaries, and while `reasoning_content` gets accumulated during streaming, it's only displayed after the stream completes rather than in real-time. Let me address these problems.\n\nActually, I need to verify something about how `reasoning_content` flows through the system. The `streamingThinking` prop only updates when think blocks appear in the main `content`, not when `reasoning_content` arrives, so users just see a spinner during the reasoning phase and then the thoughts dump all at once when streaming ends. This is likely the main issue I need to fix by streaming `reasoning_content` to the thinking display as it arrives.\n\nLet me check how ChatArea renders the thinking display...\n\nChecking the rendering logic... Looking at the tool call path, when `clearStreaming()` is called and tools are executed, any intermediate text gets added as a message, then the loop either continues to start a new stream or breaks if the finish reason is 'stop'. If it breaks, we exit the while loop entirely.\n\nBut I'm realizing there's a gap here — when the loop breaks after tool calls, the final response content that accompanied those tool calls never gets pushed to the conversation history. The `displayContent` was shown as intermediate text, but the full assistant message with the tool calls themselves needs to be added to the messages array so the conversation state is complete.\n\nAfter the loop exits, I'm checking if we've hit the max iterations limit and adding a system message if so, then updating the session's token count. If files were modified during tool execution, there's logic to potentially auto-delegate to a code review process. I'm realizing there's a potential bug here — when the model finishes with `stop` after making tool calls, those tool results never get saved back to the conversation history, so they're lost on the next turn. The issue is that `finish_reason` can be `stop` even when tool calls are present, and the break statement exits before the history gets updated with those interactions. The `finishReason` check is probably a safety mechanism to prevent infinite loops when a model returns `stop` alongside tool calls, though in practice the finish reason should be `tool_calls` when tools are invoked. Let me focus on the actual bugs: `reasoning_content` isn't being streamed to the UI, leaving users with just a spinner, and there's a flash between clearing the streaming state and adding the final message.\n\nUpdating the streaming loop to handle `reasoning_content` would conflict with how `updateStreaming` currently uses the thinking parameter for `<think>` blocks, so I need to reconsider the approach. I'm realizing that `reasoning_content` and `<think>` blocks are mutually exclusive in practice, so I can handle them separately without worrying about overlap — whichever one is present gets streamed to the store, and the other will be empty.\n\nActually, wait — both could theoretically be non-empty at the same time, which means the last update would overwrite the thinking display. The safest approach is to use a fallback pattern where I check for `thinkContent` first, then fall back to `reasoningText` if that's empty. I could also make the streaming updates atomic by combining the clear and add operations into a single store function to prevent any visual flashing between states.\n\nLooking at the prefix matching logic more carefully, some of those patterns like `'think'`, `'thin'`, `'thi'` are matching too broadly — they'd catch those letter sequences in regular English text, not just in XML tags. These should only trigger when they're actually part of a tag boundary. idea is that `</think>` might arrive as `</` + `think>`, and the code handles stray `think>` separately.\n\nBut `'think'`, `'thin'`, `'thi'`, `'th'` at the end of text are checking for partial `think>` (a partial stray close tag). For example:\n- Text: `\"some text th\"` → held back because `\"th\"` might be the start of `\"think>\"`\n- Next token: `\"the answer\"` → text becomes `\"the answer\"`, safe to display\n\nBut this is too aggressive. \"th\" appears at the end of tons of English words (\"with\", \"math\", etc.). A better approach would be to only hold back if the end matches a pattern that could start a tag, like `<` or `</`.\n\nThe real issue is that checking for bare `'think'`, `'thin'`, `'thi'`, `'th'` at the end of text creates false positives with common English words. I should refactor the prefix list to only include patterns that start with `<`, since that's the actual indicator of a tag beginning. The `'think>'` case is rare enough in normal text that it only needs special handling when it's preceded by `</` or appears at the start of the accumulator.\n\nI'm also wondering if the core problem is simpler—maybe the NVIDIA API doesn't stream chunks properly, or the stream never yields at all. Let me check the API call to see if streaming is actually enabled.\n\nThe model is `'z-ai/glm4.7'`, and if it doesn't support streaming on NVIDIA's platform, the request might return all data at once or fail silently. But the code should handle both cases fine, so that's probably not the issue.\n\nAlright, I'm going to implement these fixes: stream `reasoning_content` to the thinking display, add an atomic `finishStreaming` action to the store, use it in the no-tool-call path, and simplify `splitAtPartialTag` to stop holding back common words. Let me start coding.\n\nActually, wait—let me reconsider what \"fix response streaming\" really means. Maybe the response isn't streaming at all? I'm looking at the code path again, checking if something's preventing the stream from working. The NVIDIA client is set to `stream: true`, and the code loops through chunks, accumulating content and handling deltas...\n\nExamining the streaming logic...\n\nThe issue might be with how the API returns chunks—if the NVIDIA endpoint doesn't actually support streaming for this model, or if the chunk format differs from what the code expects, the streaming would fail silently. Let me think about whether the SDK version or the API's response format could be the culprit here. different behavior. Let me look at the specific version we're using — `\"openai\": \"^6.25.0\"` is quite recent, so there might be some nuances I'm missing with how streaming works in this version.\n\nActually, I think I'm overcomplicating this. Let me focus on the concrete fixes that'll have the most impact: streaming the reasoning content to the thinking display, ensuring atomic streaming finishes, and fixing the `splitAtPartialTag` function. I should also verify whether there's an issue with how CommonJS `require()` handles the `openai` package in Bun, since `agent.js` is importing from `config.js` which exports the client.\n\nWait — OpenAI SDK v6 is ESM-only, and using `require()` on an ESM package could be causing the streaming problem. If the import isn't resolving correctly, the client might not be returning a proper stream object. Though if it completely failed, the app would crash on startup, so it's probably working at some level. But Bun does handle CJS/ESM interop transparently, so `require('openai')` should work fine.\n\nThe real issue might be that the streaming API changed between versions. In v4, passing `stream: true` to `.create()` would return a `Stream<ChatCompletionChunk>` object that you could iterate over with `for await`. But v6 might have a different streaming interface — maybe a separate `.stream()` method or a different async iteration protocol altogether.\n\nLet me check what version is actually installed and focus on the obvious bugs in the code. Looking at `splitAtPartialTag`, it's checking for incomplete `'think'` tag prefixes like `'th'` and `'thi'`, which seems like it's trying to handle cases where the tag gets split across chunk boundaries.\n\nThe real issues are that `reasoning_content` isn't being streamed at all, so users see nothing while the model is thinking, and there's an unnecessary `clearStreaming()` call that causes a visual flash. The most impactful fix is to handle the partial tag matching more carefully and actually stream the reasoning content as it comes in. The timer resolution issue might not actually be the problem since the `for await` loop already yields between chunks as they arrive, and the `setTimeout` just prevents rapid buffered chunks from blocking the renderer. I'm overthinking this—let me focus on implementing the three concrete issues I've identified rather than continuing to second-guess myself.\n\nLooking at the actual streaming problems users encounter, the most likely culprit here is that when the model uses `reasoning_content` during its thinking phase, the user only sees \"Reasoning...\" with no progress indication, making it feel like streaming has stalled. Then the actual response suddenly appears. That's probably the primary issue I should fix.\n\nI also notice that `splitAtPartialTag` might be holding back too much content during the initial buffering phase, which could prevent content from appearing in real-time. I'm going to implement three targeted fixes: first, I'll remove the overly aggressive prefix matching in the tag-splitting logic that's unnecessarily buffering content. Second, I'll add an atomic method to clear the streaming state and finalize the message in a single update to prevent flickering. Third, I'll modify the agent to actually stream the reasoning content so users see progress, and use that new finalization method to eliminate the flicker when there's no tool call.\n\nLet me start implementing these changes now.",
|
|
532
|
+
"signature": "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",
|
|
533
|
+
"provider": "anthropic"
|
|
534
|
+
},
|
|
535
|
+
{
|
|
536
|
+
"type": "tool_use",
|
|
537
|
+
"complete": true,
|
|
538
|
+
"id": "toolu_vrtx_01CGC5X2H6nPp8w973EkU2Tv",
|
|
539
|
+
"name": "Read",
|
|
540
|
+
"input": {
|
|
541
|
+
"path": "/home/runner/workspace/src/utils.js"
|
|
542
|
+
}
|
|
543
|
+
}
|
|
544
|
+
],
|
|
545
|
+
"state": {
|
|
546
|
+
"type": "complete",
|
|
547
|
+
"stopReason": "tool_use"
|
|
548
|
+
},
|
|
549
|
+
"usage": {
|
|
550
|
+
"model": "claude-opus-4-6",
|
|
551
|
+
"maxInputTokens": 168000,
|
|
552
|
+
"inputTokens": 1,
|
|
553
|
+
"outputTokens": 21962,
|
|
554
|
+
"cacheCreationInputTokens": 4746,
|
|
555
|
+
"cacheReadInputTokens": 28317,
|
|
556
|
+
"totalInputTokens": 33064,
|
|
557
|
+
"timestamp": "2026-02-26T23:09:20.166Z"
|
|
558
|
+
}
|
|
559
|
+
},
|
|
560
|
+
{
|
|
561
|
+
"role": "user",
|
|
562
|
+
"messageId": 12,
|
|
563
|
+
"content": [
|
|
564
|
+
{
|
|
565
|
+
"type": "tool_result",
|
|
566
|
+
"toolUseID": "toolu_vrtx_01CGC5X2H6nPp8w973EkU2Tv",
|
|
567
|
+
"run": {
|
|
568
|
+
"status": "done",
|
|
569
|
+
"progress": {},
|
|
570
|
+
"result": {
|
|
571
|
+
"absolutePath": "/home/runner/workspace/src/utils.js",
|
|
572
|
+
"content": "1: 'use strict';\n2: \n3: function toolDetailStr(name, args) {\n4: if (!args) return '';\n5: switch (name) {\n6: case 'Bash': return args.command || '';\n7: case 'Grep': return `\"${args.pattern}\"${args.path ? ` in ${args.path}` : ''}`;\n8: case 'Glob': return args.pattern || '';\n9: case 'ListDir': return args.path || '.';\n10: case 'Read': {\n11: let d = args.path || '';\n12: if (args.start_line) d += `:${args.start_line}-${args.end_line || ''}`;\n13: return d;\n14: }\n15: case 'Write': return args.path || '';\n16: case 'Edit': return args.path || '';\n17: case 'Patch': return `${args.path} (${(args.edits || []).length} edits)`;\n18: case 'UndoEdit': return args.path || '';\n19: case 'Task': return args.description || '';\n20: case 'CodeReview': return 'reviewing changes';\n21: case 'FilePickerMax': return args.prompt ? args.prompt.slice(0, 40) : '';\n22: default: return JSON.stringify(args).slice(0, 60);\n23: }\n24: }\n25: \n26: module.exports = { toolDetailStr };"
|
|
573
|
+
},
|
|
574
|
+
"trackFiles": [
|
|
575
|
+
"file:///home/runner/workspace/src/utils.js"
|
|
576
|
+
]
|
|
577
|
+
}
|
|
578
|
+
}
|
|
579
|
+
]
|
|
580
|
+
},
|
|
581
|
+
{
|
|
582
|
+
"role": "assistant",
|
|
583
|
+
"messageId": 13,
|
|
584
|
+
"content": [
|
|
585
|
+
{
|
|
586
|
+
"type": "thinking",
|
|
587
|
+
"thinking": "OK, now I have a thorough understanding. Let me implement the fixes.\n\nLet me focus on the three main issues:\n\n1. **`reasoning_content` not streamed to UI** — The user sees \"Reasoning...\" spinner instead of thinking progress\n2. **Flash/flicker between streaming and final message** — `clearStreaming()` called before `addMessage()`\n3. **`splitAtPartialTag` too aggressive** — Holds back common words like \"think\", \"thin\", etc.\n\nLet me implement all three fixes.",
|
|
588
|
+
"signature": "EvgECkgICxACGAIqQDmt4nBduNdCk2MfhqrgTTZEiDjPqoCdL/1JQgy43x0hYSecjhfeABOmVa7spNiyr9dGvx/ZdU5tfht5syLhGXQSDNf3ckKPbdMtRSNVNxoMfdTPn6L0CQfOUYYlIjC5FPSYaz/I9kxzHDuIbel7uk52vd3gCKLrdruBJvggFavZi81S8gAjWCRBXaI5oPQq3QNLkjFfPUh+2OSW7fOSPK1ktJuRDJj3YfRL0L2ryUeOv10ZBsG+hkvo+yoN/DyZ2F2uO+SFTA0piZgZiXu0VpA1Wni7exjUxidHYXJP+70S6eKn889H66BuTssmDJEDtCODj87bVDiMs2pLm36sw5wyvQhoVA3404aEyLycWr6m7ABKF6+md9r2rFwRD+oTylzWM/64iJAaoiAw5EMUijNevnJKXa6obi97EshE+3yvHcQGcRQoWytwsMBqbORIlRh6VLrdZn3M2uWgTLPXqaHkB2T7NtFT9yRHAXV1xwD7c/cKlr6btUWvIRmTrkt0nQf2qLBkUVAyfBO6s8GzTKXHXgHb+/pw2e+w4izA+JNWS/WWwSNA+SBrYx2sMEnzdXrLhLqNR0RbbdSltGOY8ULsKb/+Vr/3EB3v2x0INfTQe0H0/FrCgyhwxGWIiGB1bZQk/LgzHD8R+uaNROLCKsANmG9R0sAOWY7okXhDatdgefHxva/kkGvdofJN6A0dzQF7HCsqQIdiFv3mOXBU3NGzZvzBMTlAhV85QyJ0CnMAFOt7BSICCgPEd1IQuRpKOB8w6uLeo3y2/FULbfj0I3recZPYAGNZGD6ewiijJze74hKY9oKJ+btaTTJhISAYAQ==",
|
|
589
|
+
"provider": "anthropic"
|
|
590
|
+
},
|
|
591
|
+
{
|
|
592
|
+
"type": "text",
|
|
593
|
+
"text": "I've identified three bugs in the streaming pipeline:\n\n1. **`reasoning_content` never shown during streaming** — user sees only a spinner while the model thinks\n2. **Flicker between streaming→final message** — `clearStreaming()` fires before `addMessage()`, briefly showing the spinner\n3. **`splitAtPartialTag` holds back common words** — bare prefixes like `\"think\"`, `\"th\"` match normal English, causing stuttery output\n\nLet me fix all three:"
|
|
594
|
+
},
|
|
595
|
+
{
|
|
596
|
+
"type": "tool_use",
|
|
597
|
+
"complete": true,
|
|
598
|
+
"id": "toolu_vrtx_01NdeiM7zJhCyNc9NZLXFvjE",
|
|
599
|
+
"name": "edit_file",
|
|
600
|
+
"input": {
|
|
601
|
+
"path": "/home/runner/workspace/src/thinking.js",
|
|
602
|
+
"old_str": " const prefixes = [\n '</think>', '</think', '</thin', '</thi', '</th', '</t', '</',\n '<think>', '<think', '<thin', '<thi', '<th', '<t',\n 'think>', 'think', 'thin', 'thi', 'th',\n '<',\n ];",
|
|
603
|
+
"new_str": " const prefixes = [\n '</think>', '</think', '</thin', '</thi', '</th', '</t', '</',\n '<think>', '<think', '<thin', '<thi', '<th', '<t',\n '<',\n ];"
|
|
604
|
+
}
|
|
605
|
+
}
|
|
606
|
+
],
|
|
607
|
+
"state": {
|
|
608
|
+
"type": "complete",
|
|
609
|
+
"stopReason": "tool_use"
|
|
610
|
+
},
|
|
611
|
+
"usage": {
|
|
612
|
+
"model": "claude-opus-4-6",
|
|
613
|
+
"maxInputTokens": 168000,
|
|
614
|
+
"inputTokens": 1,
|
|
615
|
+
"outputTokens": 482,
|
|
616
|
+
"cacheCreationInputTokens": 40656,
|
|
617
|
+
"cacheReadInputTokens": 14380,
|
|
618
|
+
"totalInputTokens": 55037,
|
|
619
|
+
"timestamp": "2026-02-26T23:09:31.784Z"
|
|
620
|
+
}
|
|
621
|
+
},
|
|
622
|
+
{
|
|
623
|
+
"role": "user",
|
|
624
|
+
"messageId": 14,
|
|
625
|
+
"content": [
|
|
626
|
+
{
|
|
627
|
+
"type": "tool_result",
|
|
628
|
+
"toolUseID": "toolu_vrtx_01NdeiM7zJhCyNc9NZLXFvjE",
|
|
629
|
+
"run": {
|
|
630
|
+
"status": "done",
|
|
631
|
+
"progress": {},
|
|
632
|
+
"result": {
|
|
633
|
+
"diff": "```diff\nIndex: /home/runner/workspace/src/thinking.js\n===================================================================\n--- /home/runner/workspace/src/thinking.js\toriginal\n+++ /home/runner/workspace/src/thinking.js\tmodified\n@@ -32,9 +32,8 @@\n function splitAtPartialTag(text) {\n const prefixes = [\n '</think>', '</think', '</thin', '</thi', '</th', '</t', '</',\n '<think>', '<think', '<thin', '<thi', '<th', '<t',\n- 'think>', 'think', 'thin', 'thi', 'th',\n '<',\n ];\n for (const prefix of prefixes) {\n if (text.endsWith(prefix)) {\n```",
|
|
634
|
+
"lineRange": [
|
|
635
|
+
33,
|
|
636
|
+
37
|
|
637
|
+
]
|
|
638
|
+
},
|
|
639
|
+
"trackFiles": [
|
|
640
|
+
"file:///home/runner/workspace/src/thinking.js"
|
|
641
|
+
]
|
|
642
|
+
}
|
|
643
|
+
}
|
|
644
|
+
]
|
|
645
|
+
},
|
|
646
|
+
{
|
|
647
|
+
"role": "assistant",
|
|
648
|
+
"messageId": 15,
|
|
649
|
+
"content": [
|
|
650
|
+
{
|
|
651
|
+
"type": "tool_use",
|
|
652
|
+
"complete": true,
|
|
653
|
+
"id": "toolu_vrtx_01SAj69XJFRui7acZYaJd8MP",
|
|
654
|
+
"name": "edit_file",
|
|
655
|
+
"input": {
|
|
656
|
+
"path": "/home/runner/workspace/src/store.js",
|
|
657
|
+
"old_str": "function clearStreaming() {\n state = { ...state, streamingContent: '', streamingThinking: '' };\n notify();\n}",
|
|
658
|
+
"new_str": "function clearStreaming() {\n state = { ...state, streamingContent: '', streamingThinking: '' };\n notify();\n}\n\nfunction finishStreaming(msg) {\n const id = nextId++;\n state = {\n ...state,\n streamingContent: '',\n streamingThinking: '',\n messages: [...state.messages, { id, ...msg }],\n };\n notify();\n return id;\n}"
|
|
659
|
+
}
|
|
660
|
+
}
|
|
661
|
+
],
|
|
662
|
+
"state": {
|
|
663
|
+
"type": "complete",
|
|
664
|
+
"stopReason": "tool_use"
|
|
665
|
+
},
|
|
666
|
+
"usage": {
|
|
667
|
+
"model": "claude-opus-4-6",
|
|
668
|
+
"maxInputTokens": 168000,
|
|
669
|
+
"inputTokens": 1,
|
|
670
|
+
"outputTokens": 235,
|
|
671
|
+
"cacheCreationInputTokens": 694,
|
|
672
|
+
"cacheReadInputTokens": 55036,
|
|
673
|
+
"totalInputTokens": 55731,
|
|
674
|
+
"timestamp": "2026-02-26T23:09:36.369Z"
|
|
675
|
+
}
|
|
676
|
+
},
|
|
677
|
+
{
|
|
678
|
+
"role": "user",
|
|
679
|
+
"messageId": 16,
|
|
680
|
+
"content": [
|
|
681
|
+
{
|
|
682
|
+
"type": "tool_result",
|
|
683
|
+
"toolUseID": "toolu_vrtx_01SAj69XJFRui7acZYaJd8MP",
|
|
684
|
+
"run": {
|
|
685
|
+
"status": "done",
|
|
686
|
+
"progress": {},
|
|
687
|
+
"result": {
|
|
688
|
+
"diff": "```diff\nIndex: /home/runner/workspace/src/store.js\n===================================================================\n--- /home/runner/workspace/src/store.js\toriginal\n+++ /home/runner/workspace/src/store.js\tmodified\n@@ -62,8 +62,20 @@\n state = { ...state, streamingContent: '', streamingThinking: '' };\n notify();\n }\n \n+function finishStreaming(msg) {\n+ const id = nextId++;\n+ state = {\n+ ...state,\n+ streamingContent: '',\n+ streamingThinking: '',\n+ messages: [...state.messages, { id, ...msg }],\n+ };\n+ notify();\n+ return id;\n+}\n+\n function clearMessages() {\n state = { ...state, messages: [] };\n notify();\n }\n```",
|
|
689
|
+
"lineRange": [
|
|
690
|
+
61,
|
|
691
|
+
76
|
|
692
|
+
]
|
|
693
|
+
},
|
|
694
|
+
"trackFiles": [
|
|
695
|
+
"file:///home/runner/workspace/src/store.js"
|
|
696
|
+
]
|
|
697
|
+
}
|
|
698
|
+
}
|
|
699
|
+
]
|
|
700
|
+
},
|
|
701
|
+
{
|
|
702
|
+
"role": "assistant",
|
|
703
|
+
"messageId": 17,
|
|
704
|
+
"content": [
|
|
705
|
+
{
|
|
706
|
+
"type": "tool_use",
|
|
707
|
+
"complete": true,
|
|
708
|
+
"id": "toolu_vrtx_019YvkcKM9Qr1R7mgJR6wrFu",
|
|
709
|
+
"name": "edit_file",
|
|
710
|
+
"input": {
|
|
711
|
+
"path": "/home/runner/workspace/src/store.js",
|
|
712
|
+
"old_str": "module.exports = {\n getSnapshot,\n subscribe,\n setState,\n addMessage,\n updateMessage,\n toggleMessageExpanded,\n updateStreaming,\n clearStreaming,\n clearMessages,\n setRenderer,\n getRenderer,\n};",
|
|
713
|
+
"new_str": "module.exports = {\n getSnapshot,\n subscribe,\n setState,\n addMessage,\n updateMessage,\n toggleMessageExpanded,\n updateStreaming,\n clearStreaming,\n finishStreaming,\n clearMessages,\n setRenderer,\n getRenderer,\n};"
|
|
714
|
+
}
|
|
715
|
+
}
|
|
716
|
+
],
|
|
717
|
+
"state": {
|
|
718
|
+
"type": "complete",
|
|
719
|
+
"stopReason": "tool_use"
|
|
720
|
+
},
|
|
721
|
+
"usage": {
|
|
722
|
+
"model": "claude-opus-4-6",
|
|
723
|
+
"maxInputTokens": 168000,
|
|
724
|
+
"inputTokens": 1,
|
|
725
|
+
"outputTokens": 235,
|
|
726
|
+
"cacheCreationInputTokens": 475,
|
|
727
|
+
"cacheReadInputTokens": 55730,
|
|
728
|
+
"totalInputTokens": 56206,
|
|
729
|
+
"timestamp": "2026-02-26T23:09:50.655Z"
|
|
730
|
+
}
|
|
731
|
+
},
|
|
732
|
+
{
|
|
733
|
+
"role": "user",
|
|
734
|
+
"messageId": 18,
|
|
735
|
+
"content": [
|
|
736
|
+
{
|
|
737
|
+
"type": "tool_result",
|
|
738
|
+
"toolUseID": "toolu_vrtx_019YvkcKM9Qr1R7mgJR6wrFu",
|
|
739
|
+
"run": {
|
|
740
|
+
"status": "done",
|
|
741
|
+
"progress": {},
|
|
742
|
+
"result": {
|
|
743
|
+
"diff": "```diff\nIndex: /home/runner/workspace/src/store.js\n===================================================================\n--- /home/runner/workspace/src/store.js\toriginal\n+++ /home/runner/workspace/src/store.js\tmodified\n@@ -91,8 +91,9 @@\n updateMessage,\n toggleMessageExpanded,\n updateStreaming,\n clearStreaming,\n+ finishStreaming,\n clearMessages,\n setRenderer,\n getRenderer,\n };\n```",
|
|
744
|
+
"lineRange": [
|
|
745
|
+
86,
|
|
746
|
+
99
|
|
747
|
+
]
|
|
748
|
+
},
|
|
749
|
+
"trackFiles": [
|
|
750
|
+
"file:///home/runner/workspace/src/store.js"
|
|
751
|
+
]
|
|
752
|
+
}
|
|
753
|
+
}
|
|
754
|
+
]
|
|
755
|
+
},
|
|
756
|
+
{
|
|
757
|
+
"role": "assistant",
|
|
758
|
+
"messageId": 19,
|
|
759
|
+
"content": [
|
|
760
|
+
{
|
|
761
|
+
"type": "text",
|
|
762
|
+
"text": "Now fix agent.js — stream `reasoning_content` to the thinking display, and use `finishStreaming` for the no-tool-call path:"
|
|
763
|
+
},
|
|
764
|
+
{
|
|
765
|
+
"type": "tool_use",
|
|
766
|
+
"complete": true,
|
|
767
|
+
"id": "toolu_vrtx_01SiAWvygi9z7CjU5qw3bbEo",
|
|
768
|
+
"name": "edit_file",
|
|
769
|
+
"input": {
|
|
770
|
+
"path": "/home/runner/workspace/src/agent.js",
|
|
771
|
+
"old_str": " if (delta.reasoning_content) {\n reasoningText += delta.reasoning_content;\n }",
|
|
772
|
+
"new_str": " if (delta.reasoning_content) {\n reasoningText += delta.reasoning_content;\n store.updateStreaming(displayContent, reasoningText);\n }"
|
|
773
|
+
}
|
|
774
|
+
}
|
|
775
|
+
],
|
|
776
|
+
"state": {
|
|
777
|
+
"type": "complete",
|
|
778
|
+
"stopReason": "tool_use"
|
|
779
|
+
},
|
|
780
|
+
"usage": {
|
|
781
|
+
"model": "claude-opus-4-6",
|
|
782
|
+
"maxInputTokens": 168000,
|
|
783
|
+
"inputTokens": 1,
|
|
784
|
+
"outputTokens": 200,
|
|
785
|
+
"cacheCreationInputTokens": 384,
|
|
786
|
+
"cacheReadInputTokens": 56205,
|
|
787
|
+
"totalInputTokens": 56590,
|
|
788
|
+
"timestamp": "2026-02-26T23:09:55.629Z"
|
|
789
|
+
}
|
|
790
|
+
},
|
|
791
|
+
{
|
|
792
|
+
"role": "user",
|
|
793
|
+
"messageId": 20,
|
|
794
|
+
"content": [
|
|
795
|
+
{
|
|
796
|
+
"type": "tool_result",
|
|
797
|
+
"toolUseID": "toolu_vrtx_01SiAWvygi9z7CjU5qw3bbEo",
|
|
798
|
+
"run": {
|
|
799
|
+
"status": "done",
|
|
800
|
+
"progress": {},
|
|
801
|
+
"result": {
|
|
802
|
+
"diff": "```diff\nIndex: /home/runner/workspace/src/agent.js\n===================================================================\n--- /home/runner/workspace/src/agent.js\toriginal\n+++ /home/runner/workspace/src/agent.js\tmodified\n@@ -172,8 +172,9 @@\n }\n \n if (delta.reasoning_content) {\n reasoningText += delta.reasoning_content;\n+ store.updateStreaming(displayContent, reasoningText);\n }\n \n // Handle content tokens\n if (delta.content) {\n```",
|
|
803
|
+
"lineRange": [
|
|
804
|
+
174,
|
|
805
|
+
177
|
|
806
|
+
]
|
|
807
|
+
},
|
|
808
|
+
"trackFiles": [
|
|
809
|
+
"file:///home/runner/workspace/src/agent.js"
|
|
810
|
+
]
|
|
811
|
+
}
|
|
812
|
+
}
|
|
813
|
+
]
|
|
814
|
+
},
|
|
815
|
+
{
|
|
816
|
+
"role": "assistant",
|
|
817
|
+
"messageId": 21,
|
|
818
|
+
"content": [
|
|
819
|
+
{
|
|
820
|
+
"type": "text",
|
|
821
|
+
"text": "Now fix the no-tool-call path to use `finishStreaming` instead of separate `clearStreaming` + `addMessage`:"
|
|
822
|
+
},
|
|
823
|
+
{
|
|
824
|
+
"type": "tool_use",
|
|
825
|
+
"complete": true,
|
|
826
|
+
"id": "toolu_vrtx_01EVTKMaSg5K1ujo4HRVapw8",
|
|
827
|
+
"name": "edit_file",
|
|
828
|
+
"input": {
|
|
829
|
+
"path": "/home/runner/workspace/src/agent.js",
|
|
830
|
+
"old_str": " store.clearStreaming();\n\n const { content: parsedContent } = parseThinkBlocks(fullContent);",
|
|
831
|
+
"new_str": " const { content: parsedContent } = parseThinkBlocks(fullContent);"
|
|
832
|
+
}
|
|
833
|
+
}
|
|
834
|
+
],
|
|
835
|
+
"state": {
|
|
836
|
+
"type": "complete",
|
|
837
|
+
"stopReason": "tool_use"
|
|
838
|
+
},
|
|
839
|
+
"usage": {
|
|
840
|
+
"model": "claude-opus-4-6",
|
|
841
|
+
"maxInputTokens": 168000,
|
|
842
|
+
"inputTokens": 1,
|
|
843
|
+
"outputTokens": 177,
|
|
844
|
+
"cacheCreationInputTokens": 363,
|
|
845
|
+
"cacheReadInputTokens": 56589,
|
|
846
|
+
"totalInputTokens": 56953,
|
|
847
|
+
"timestamp": "2026-02-26T23:10:00.547Z"
|
|
848
|
+
}
|
|
849
|
+
},
|
|
850
|
+
{
|
|
851
|
+
"role": "user",
|
|
852
|
+
"messageId": 22,
|
|
853
|
+
"content": [
|
|
854
|
+
{
|
|
855
|
+
"type": "tool_result",
|
|
856
|
+
"toolUseID": "toolu_vrtx_01EVTKMaSg5K1ujo4HRVapw8",
|
|
857
|
+
"run": {
|
|
858
|
+
"status": "done",
|
|
859
|
+
"progress": {},
|
|
860
|
+
"result": {
|
|
861
|
+
"diff": "```diff\nIndex: /home/runner/workspace/src/agent.js\n===================================================================\n--- /home/runner/workspace/src/agent.js\toriginal\n+++ /home/runner/workspace/src/agent.js\tmodified\n@@ -296,10 +296,8 @@\n if (reasoningText.trim()) {\n store.addMessage({ role: 'thinking', content: reasoningText.trim() });\n }\n \n- store.clearStreaming();\n-\n const { content: parsedContent } = parseThinkBlocks(fullContent);\n turnTokens += streamUsage?.total_tokens || 0;\n \n // Reconstruct tool calls\n```",
|
|
862
|
+
"lineRange": [
|
|
863
|
+
300,
|
|
864
|
+
300
|
|
865
|
+
]
|
|
866
|
+
},
|
|
867
|
+
"trackFiles": [
|
|
868
|
+
"file:///home/runner/workspace/src/agent.js"
|
|
869
|
+
]
|
|
870
|
+
}
|
|
871
|
+
}
|
|
872
|
+
]
|
|
873
|
+
},
|
|
874
|
+
{
|
|
875
|
+
"role": "assistant",
|
|
876
|
+
"messageId": 23,
|
|
877
|
+
"content": [
|
|
878
|
+
{
|
|
879
|
+
"type": "text",
|
|
880
|
+
"text": "Now add `clearStreaming` in the tool-call branch and use `finishStreaming` in the no-tool-call branch:"
|
|
881
|
+
},
|
|
882
|
+
{
|
|
883
|
+
"type": "tool_use",
|
|
884
|
+
"complete": true,
|
|
885
|
+
"id": "toolu_vrtx_01SS8y1G8HvjS2UNvj58eoo6",
|
|
886
|
+
"name": "edit_file",
|
|
887
|
+
"input": {
|
|
888
|
+
"path": "/home/runner/workspace/src/agent.js",
|
|
889
|
+
"old_str": " // If the model wants to call tools\n if (toolCalls.length > 0) {\n messages.push(msg);\n\n // Show intermediate text if any\n if (displayContent.trim()) {\n store.addMessage({ role: 'assistant', content: displayContent.trim() });\n }",
|
|
890
|
+
"new_str": " // If the model wants to call tools\n if (toolCalls.length > 0) {\n store.clearStreaming();\n messages.push(msg);\n\n // Show intermediate text if any\n if (displayContent.trim()) {\n store.addMessage({ role: 'assistant', content: displayContent.trim() });\n }"
|
|
891
|
+
}
|
|
892
|
+
}
|
|
893
|
+
],
|
|
894
|
+
"state": {
|
|
895
|
+
"type": "complete",
|
|
896
|
+
"stopReason": "tool_use"
|
|
897
|
+
},
|
|
898
|
+
"usage": {
|
|
899
|
+
"model": "claude-opus-4-6",
|
|
900
|
+
"maxInputTokens": 168000,
|
|
901
|
+
"inputTokens": 1,
|
|
902
|
+
"outputTokens": 285,
|
|
903
|
+
"cacheCreationInputTokens": 372,
|
|
904
|
+
"cacheReadInputTokens": 56952,
|
|
905
|
+
"totalInputTokens": 57325,
|
|
906
|
+
"timestamp": "2026-02-26T23:10:10.882Z"
|
|
907
|
+
}
|
|
908
|
+
},
|
|
909
|
+
{
|
|
910
|
+
"role": "user",
|
|
911
|
+
"messageId": 24,
|
|
912
|
+
"content": [
|
|
913
|
+
{
|
|
914
|
+
"type": "tool_result",
|
|
915
|
+
"toolUseID": "toolu_vrtx_01SS8y1G8HvjS2UNvj58eoo6",
|
|
916
|
+
"run": {
|
|
917
|
+
"status": "done",
|
|
918
|
+
"progress": {},
|
|
919
|
+
"result": {
|
|
920
|
+
"diff": "```diff\nIndex: /home/runner/workspace/src/agent.js\n===================================================================\n--- /home/runner/workspace/src/agent.js\toriginal\n+++ /home/runner/workspace/src/agent.js\tmodified\n@@ -315,8 +315,9 @@\n };\n \n // If the model wants to call tools\n if (toolCalls.length > 0) {\n+ store.clearStreaming();\n messages.push(msg);\n \n // Show intermediate text if any\n if (displayContent.trim()) {\n```",
|
|
921
|
+
"lineRange": [
|
|
922
|
+
317,
|
|
923
|
+
325
|
|
924
|
+
]
|
|
925
|
+
},
|
|
926
|
+
"trackFiles": [
|
|
927
|
+
"file:///home/runner/workspace/src/agent.js"
|
|
928
|
+
]
|
|
929
|
+
}
|
|
930
|
+
}
|
|
931
|
+
]
|
|
932
|
+
},
|
|
933
|
+
{
|
|
934
|
+
"role": "assistant",
|
|
935
|
+
"messageId": 25,
|
|
936
|
+
"content": [
|
|
937
|
+
{
|
|
938
|
+
"type": "text",
|
|
939
|
+
"text": "Now update the no-tool-call path to use `finishStreaming`:"
|
|
940
|
+
},
|
|
941
|
+
{
|
|
942
|
+
"type": "tool_use",
|
|
943
|
+
"complete": true,
|
|
944
|
+
"id": "toolu_vrtx_01RY2kv5X3c4Wj4PTf1qxwDf",
|
|
945
|
+
"name": "edit_file",
|
|
946
|
+
"input": {
|
|
947
|
+
"path": "/home/runner/workspace/src/agent.js",
|
|
948
|
+
"old_str": " // No tool calls — final text response\n if (fullContent) {\n const cleanedContent = parsedContent.trim() || fullContent.replace(/<think>[\\s\\S]*?<\\/think>/g, '').trim();\n if (cleanedContent) {\n store.addMessage({ role: 'assistant', content: cleanedContent });\n }\n session.conversationHistory.push({ role: 'assistant', content: cleanedContent || fullContent });\n }\n break;",
|
|
949
|
+
"new_str": " // No tool calls — final text response\n if (fullContent) {\n const cleanedContent = parsedContent.trim() || fullContent.replace(/<think>[\\s\\S]*?<\\/think>/g, '').trim();\n if (cleanedContent) {\n store.finishStreaming({ role: 'assistant', content: cleanedContent });\n } else {\n store.clearStreaming();\n }\n session.conversationHistory.push({ role: 'assistant', content: cleanedContent || fullContent });\n } else {\n store.clearStreaming();\n }\n break;"
|
|
950
|
+
}
|
|
951
|
+
}
|
|
952
|
+
],
|
|
953
|
+
"state": {
|
|
954
|
+
"type": "complete",
|
|
955
|
+
"stopReason": "tool_use"
|
|
956
|
+
},
|
|
957
|
+
"usage": {
|
|
958
|
+
"model": "claude-opus-4-6",
|
|
959
|
+
"maxInputTokens": 168000,
|
|
960
|
+
"inputTokens": 1,
|
|
961
|
+
"outputTokens": 380,
|
|
962
|
+
"cacheCreationInputTokens": 450,
|
|
963
|
+
"cacheReadInputTokens": 57324,
|
|
964
|
+
"totalInputTokens": 57775,
|
|
965
|
+
"timestamp": "2026-02-26T23:10:17.351Z"
|
|
966
|
+
}
|
|
967
|
+
},
|
|
968
|
+
{
|
|
969
|
+
"role": "user",
|
|
970
|
+
"messageId": 26,
|
|
971
|
+
"content": [
|
|
972
|
+
{
|
|
973
|
+
"type": "tool_result",
|
|
974
|
+
"toolUseID": "toolu_vrtx_01RY2kv5X3c4Wj4PTf1qxwDf",
|
|
975
|
+
"run": {
|
|
976
|
+
"status": "done",
|
|
977
|
+
"progress": {},
|
|
978
|
+
"result": {
|
|
979
|
+
"diff": "```diff\nIndex: /home/runner/workspace/src/agent.js\n===================================================================\n--- /home/runner/workspace/src/agent.js\toriginal\n+++ /home/runner/workspace/src/agent.js\tmodified\n@@ -383,11 +383,15 @@\n // No tool calls — final text response\n if (fullContent) {\n const cleanedContent = parsedContent.trim() || fullContent.replace(/<think>[\\s\\S]*?<\\/think>/g, '').trim();\n if (cleanedContent) {\n- store.addMessage({ role: 'assistant', content: cleanedContent });\n+ store.finishStreaming({ role: 'assistant', content: cleanedContent });\n+ } else {\n+ store.clearStreaming();\n }\n session.conversationHistory.push({ role: 'assistant', content: cleanedContent || fullContent });\n+ } else {\n+ store.clearStreaming();\n }\n break;\n }\n \n```",
|
|
980
|
+
"lineRange": [
|
|
981
|
+
383,
|
|
982
|
+
395
|
|
983
|
+
]
|
|
984
|
+
},
|
|
985
|
+
"trackFiles": [
|
|
986
|
+
"file:///home/runner/workspace/src/agent.js"
|
|
987
|
+
]
|
|
988
|
+
}
|
|
989
|
+
}
|
|
990
|
+
]
|
|
991
|
+
},
|
|
992
|
+
{
|
|
993
|
+
"role": "assistant",
|
|
994
|
+
"messageId": 27,
|
|
995
|
+
"content": [
|
|
996
|
+
{
|
|
997
|
+
"type": "text",
|
|
998
|
+
"text": "Now also update the `updateStreaming` calls in the content handler to include `reasoningText` as a fallback for the thinking display:"
|
|
999
|
+
},
|
|
1000
|
+
{
|
|
1001
|
+
"type": "tool_use",
|
|
1002
|
+
"complete": true,
|
|
1003
|
+
"id": "toolu_vrtx_01QweeaebydyQskrTa1heXJJ",
|
|
1004
|
+
"name": "Read",
|
|
1005
|
+
"input": {
|
|
1006
|
+
"path": "/home/runner/workspace/src/agent.js",
|
|
1007
|
+
"read_range": [
|
|
1008
|
+
180,
|
|
1009
|
+
270
|
|
1010
|
+
]
|
|
1011
|
+
}
|
|
1012
|
+
}
|
|
1013
|
+
],
|
|
1014
|
+
"state": {
|
|
1015
|
+
"type": "complete",
|
|
1016
|
+
"stopReason": "tool_use"
|
|
1017
|
+
},
|
|
1018
|
+
"usage": {
|
|
1019
|
+
"model": "claude-opus-4-6",
|
|
1020
|
+
"maxInputTokens": 168000,
|
|
1021
|
+
"inputTokens": 1,
|
|
1022
|
+
"outputTokens": 117,
|
|
1023
|
+
"cacheCreationInputTokens": 656,
|
|
1024
|
+
"cacheReadInputTokens": 57774,
|
|
1025
|
+
"totalInputTokens": 58431,
|
|
1026
|
+
"timestamp": "2026-02-26T23:10:26.743Z"
|
|
1027
|
+
}
|
|
1028
|
+
},
|
|
1029
|
+
{
|
|
1030
|
+
"role": "user",
|
|
1031
|
+
"messageId": 28,
|
|
1032
|
+
"content": [
|
|
1033
|
+
{
|
|
1034
|
+
"type": "tool_result",
|
|
1035
|
+
"toolUseID": "toolu_vrtx_01QweeaebydyQskrTa1heXJJ",
|
|
1036
|
+
"run": {
|
|
1037
|
+
"status": "done",
|
|
1038
|
+
"progress": {},
|
|
1039
|
+
"result": {
|
|
1040
|
+
"absolutePath": "/home/runner/workspace/src/agent.js",
|
|
1041
|
+
"content": "[... omitted lines 1 to 179 ...]\n180: if (delta.content) {\n181: fullContent += delta.content;\n182: const hasTool = Object.keys(toolCallDeltas).length > 0;\n183: \n184: if (displayState === 'streaming') {\n185: contentAccum += delta.content;\n186: contentAccum = stripStrayCloseTag(contentAccum);\n187: const openIdx = contentAccum.indexOf('<think>');\n188: if (openIdx !== -1) {\n189: if (openIdx > 0) displayContent += contentAccum.slice(0, openIdx);\n190: thinkAccum = contentAccum.slice(openIdx + 7);\n191: contentAccum = '';\n192: displayState = 'thinking';\n193: const closeMatch = findThinkClose(thinkAccum);\n194: if (closeMatch) {\n195: const thought = thinkAccum.slice(0, closeMatch.pos).trim();\n196: const after = thinkAccum.slice(closeMatch.pos + closeMatch.len);\n197: thinkAccum = '';\n198: if (thought) store.addMessage({ role: 'thinking', content: thought });\n199: displayState = 'streaming';\n200: contentAccum = after;\n201: if (!hasTool && after) displayContent += after;\n202: contentAccum = '';\n203: thinkContent = '';\n204: } else {\n205: thinkContent = thinkAccum;\n206: }\n207: } else {\n208: const { safe, pending } = splitAtPartialTag(contentAccum);\n209: contentAccum = pending;\n210: if (!hasTool && safe) displayContent += safe;\n211: }\n212: store.updateStreaming(displayContent, thinkContent);\n213: \n214: } else if (displayState === 'thinking') {\n215: thinkAccum += delta.content;\n216: const closeMatch = findThinkClose(thinkAccum);\n217: if (closeMatch) {\n218: const thought = thinkAccum.slice(0, closeMatch.pos).trim();\n219: const after = thinkAccum.slice(closeMatch.pos + closeMatch.len);\n220: thinkAccum = '';\n221: if (thought) store.addMessage({ role: 'thinking', content: thought });\n222: displayState = 'streaming';\n223: contentAccum = after;\n224: if (!hasTool && after) displayContent += after;\n225: contentAccum = '';\n226: thinkContent = '';\n227: store.updateStreaming(displayContent, '');\n228: } else {\n229: thinkContent = thinkAccum;\n230: store.updateStreaming(displayContent, thinkContent);\n231: }\n232: \n233: } else {\n234: // buffering\n235: contentAccum += delta.content;\n236: contentAccum = stripStrayCloseTag(contentAccum);\n237: const openIdx = contentAccum.indexOf('<think>');\n238: if (openIdx !== -1) {\n239: const before = contentAccum.slice(0, openIdx);\n240: thinkAccum = contentAccum.slice(openIdx + 7);\n241: contentAccum = '';\n242: if (!hasTool && before.trim()) displayContent += before;\n243: displayState = 'thinking';\n244: const closeMatch = findThinkClose(thinkAccum);\n245: if (closeMatch) {\n246: const thought = thinkAccum.slice(0, closeMatch.pos).trim();\n247: const after = thinkAccum.slice(closeMatch.pos + closeMatch.len);\n248: thinkAccum = '';\n249: if (thought) store.addMessage({ role: 'thinking', content: thought });\n250: displayState = 'streaming';\n251: contentAccum = after;\n252: if (!hasTool && after) displayContent += after;\n253: contentAccum = '';\n254: thinkContent = '';\n255: } else {\n256: thinkContent = thinkAccum;\n257: }\n258: store.updateStreaming(displayContent, thinkContent);\n259: } else {\n260: const { safe, pending } = splitAtPartialTag(contentAccum);\n261: if (safe.length > 0) {\n262: displayState = 'streaming';\n263: if (!hasTool) displayContent += safe;\n264: contentAccum = pending;\n265: store.updateStreaming(displayContent, '');\n266: }\n267: }\n268: }\n269: }\n270: \n[... omitted lines 271 to 441 ...]"
|
|
1042
|
+
},
|
|
1043
|
+
"trackFiles": [
|
|
1044
|
+
"file:///home/runner/workspace/src/agent.js"
|
|
1045
|
+
]
|
|
1046
|
+
}
|
|
1047
|
+
}
|
|
1048
|
+
]
|
|
1049
|
+
},
|
|
1050
|
+
{
|
|
1051
|
+
"role": "assistant",
|
|
1052
|
+
"messageId": 29,
|
|
1053
|
+
"content": [
|
|
1054
|
+
{
|
|
1055
|
+
"type": "thinking",
|
|
1056
|
+
"thinking": "The `updateStreaming` calls in the content handler use `thinkContent` (from `<think>` blocks). When `reasoning_content` is being streamed, `thinkContent` would be empty but `reasoningText` would have content. I need to make these calls use `thinkContent || reasoningText` so that the thinking display shows whichever source is active.\n\nActually, wait. The `reasoning_content` delta handler already calls `store.updateStreaming(displayContent, reasoningText)`. And the content delta handler calls `store.updateStreaming(displayContent, thinkContent)`. \n\nIf both `reasoning_content` and `content` arrive in the same chunk, the content handler would overwrite the reasoning display with `thinkContent` (which is `''` if no `<think>` block is active). \n\nThis would cause flickering in the reasoning display, so I need to update the content handler to use `thinkContent || reasoningText` instead, ensuring whichever content is active stays visible.",
|
|
1057
|
+
"signature": "EqcICkgICxACGAIqQJ/tiX2pEgi0KMyQI/TUfIiaj+r2sD0e1XY6d7laxd0Cpx1yyiTb3CnpsvUGNwtj9eNXTmX42gvjPWHBgFYiog0SDJt4byAr/KLpIWvBLRoMRMe0vmkZQMIJEf9FIjBqcC5TmLzybQMti9bg0alBqiYmLYzbameodtfMaat/DV6hwIiJ4aMx9iUaZr4MYIAqjAcFyw7bxvA+FbPvSf3iOwMm0zk4wQUSVcf/GQOcSYbPV9SguAzgyt970BWfKg1sBIzQiT3j1GQPn9FWJ43FZ3Leax552u79pEm8vVqvl6dHNbF/D3ATAc4IEKt2tlrv7znI297xWFVUeL1tSUyTe6WQ4YYVRaaliB4VEY3ywdRTQyiMeBQtQ4Mx9Lu9X1zx4GmAhiq8JbNrT21+bA7HlUYnJslaTOscy0gEhQTirtcOyzRfWQrWwRBAOL+zMp085by8wZ+9jd1utlwPAape9re4Ze59wG4AQibaU8JVH8BSX9dPYxJnch5TdzO7aQJJyhX2XAtCCpkRJiwPKZcOMDV7rAoLzKHey+qBWBE9JVUr6d8vtmuq2iGB3z/3RFvBOTniomt3ng4fKr0vKarFmmySTLflNtS4a7kvx/3TukuEbz11TBVB285p6mZM16s+7C0lSdQo6ifaK0vuA7C03ZuI9x8Q+Mmy/H/bRfr2Du58B4Xtq/blnvh0Fe8Nug10uN++aueRwgm84XsBDMro/SbHAgjR6J87Ts3/DW1zTfm6q2ASVXtxEIEcAMs0dKBeSqxa1YxX1wuyENbIqWpTQMyVAhiP5Y9XtA+VjSUKBE9fyyt317muDhZNNxjZBvUiTKh5q3JSoXW995KKW2PpR3151EF6ZWntI4r0tqP7VSxBUkE28V+clbRprW71heXgCpkHh8JimrzECvPOell0vIpKtwC83cKsY0K0NwkhfEy+lWkfflrgS1ny4U9lLcMn2SQc9A/3PdruALSIAc8qH7S9rkpUj+AeYBeg6et2LVVjd4gGpHQo5DWjwyq/K//mz6eK1uiiLaKn7JBLN20PtdjeaDgKJ2mPM9WeRT0Yiq+Fpy2Rdl/goeVfaCL29x0fFe8ahC3dAatHPO8l9ctdKKftB9UkWYhnLo5vYXHXiEULGzEdHESaVwRQ0gIWmvqSEep2ZFX1N2hOdPLp2hnLdBXe4t4AqQKOWwJRwrMm+x9HhfRaw5aXBNwKzKio3cVh2quk++CDKfjIbNaHlf8PZJUO0TjMJ5k0qHIxCk7drrGtagZdRIriwns8C/7JU7la6exk2p6o9vXjQZSTBdos2RS1Adu30PMxIueL9wjcBMtowtTWlP+GAgGwpMvx6zYUoVM6svx3QFXDpkhgFvQC49BK0KD5gEqZK08/zF8z0nsdq/rM4O/c8amQllOkThgB",
|
|
1058
|
+
"provider": "anthropic"
|
|
1059
|
+
},
|
|
1060
|
+
{
|
|
1061
|
+
"type": "text",
|
|
1062
|
+
"text": "The content handler's `updateStreaming` calls should fall back to `reasoningText` when there's no active `<think>` block:"
|
|
1063
|
+
},
|
|
1064
|
+
{
|
|
1065
|
+
"type": "tool_use",
|
|
1066
|
+
"complete": true,
|
|
1067
|
+
"id": "toolu_vrtx_01CKeQfPfQCAKGpptVM7Mnfa",
|
|
1068
|
+
"name": "edit_file",
|
|
1069
|
+
"input": {
|
|
1070
|
+
"path": "/home/runner/workspace/src/agent.js",
|
|
1071
|
+
"old_str": " store.updateStreaming(displayContent, thinkContent);\n\n } else if (displayState === 'thinking') {\n thinkAccum += delta.content;\n const closeMatch = findThinkClose(thinkAccum);\n if (closeMatch) {\n const thought = thinkAccum.slice(0, closeMatch.pos).trim();\n const after = thinkAccum.slice(closeMatch.pos + closeMatch.len);\n thinkAccum = '';\n if (thought) store.addMessage({ role: 'thinking', content: thought });\n displayState = 'streaming';\n contentAccum = after;\n if (!hasTool && after) displayContent += after;\n contentAccum = '';\n thinkContent = '';\n store.updateStreaming(displayContent, '');\n } else {\n thinkContent = thinkAccum;\n store.updateStreaming(displayContent, thinkContent);\n }\n\n } else {\n // buffering\n contentAccum += delta.content;\n contentAccum = stripStrayCloseTag(contentAccum);\n const openIdx = contentAccum.indexOf('<think>');\n if (openIdx !== -1) {\n const before = contentAccum.slice(0, openIdx);\n thinkAccum = contentAccum.slice(openIdx + 7);\n contentAccum = '';\n if (!hasTool && before.trim()) displayContent += before;\n displayState = 'thinking';\n const closeMatch = findThinkClose(thinkAccum);\n if (closeMatch) {\n const thought = thinkAccum.slice(0, closeMatch.pos).trim();\n const after = thinkAccum.slice(closeMatch.pos + closeMatch.len);\n thinkAccum = '';\n if (thought) store.addMessage({ role: 'thinking', content: thought });\n displayState = 'streaming';\n contentAccum = after;\n if (!hasTool && after) displayContent += after;\n contentAccum = '';\n thinkContent = '';\n } else {\n thinkContent = thinkAccum;\n }\n store.updateStreaming(displayContent, thinkContent);\n } else {\n const { safe, pending } = splitAtPartialTag(contentAccum);\n if (safe.length > 0) {\n displayState = 'streaming';\n if (!hasTool) displayContent += safe;\n contentAccum = pending;\n store.updateStreaming(displayContent, '');\n }\n }\n }",
|
|
1072
|
+
"new_str": " store.updateStreaming(displayContent, thinkContent || reasoningText);\n\n } else if (displayState === 'thinking') {\n thinkAccum += delta.content;\n const closeMatch = findThinkClose(thinkAccum);\n if (closeMatch) {\n const thought = thinkAccum.slice(0, closeMatch.pos).trim();\n const after = thinkAccum.slice(closeMatch.pos + closeMatch.len);\n thinkAccum = '';\n if (thought) store.addMessage({ role: 'thinking', content: thought });\n displayState = 'streaming';\n contentAccum = after;\n if (!hasTool && after) displayContent += after;\n contentAccum = '';\n thinkContent = '';\n store.updateStreaming(displayContent, reasoningText);\n } else {\n thinkContent = thinkAccum;\n store.updateStreaming(displayContent, thinkContent || reasoningText);\n }\n\n } else {\n // buffering\n contentAccum += delta.content;\n contentAccum = stripStrayCloseTag(contentAccum);\n const openIdx = contentAccum.indexOf('<think>');\n if (openIdx !== -1) {\n const before = contentAccum.slice(0, openIdx);\n thinkAccum = contentAccum.slice(openIdx + 7);\n contentAccum = '';\n if (!hasTool && before.trim()) displayContent += before;\n displayState = 'thinking';\n const closeMatch = findThinkClose(thinkAccum);\n if (closeMatch) {\n const thought = thinkAccum.slice(0, closeMatch.pos).trim();\n const after = thinkAccum.slice(closeMatch.pos + closeMatch.len);\n thinkAccum = '';\n if (thought) store.addMessage({ role: 'thinking', content: thought });\n displayState = 'streaming';\n contentAccum = after;\n if (!hasTool && after) displayContent += after;\n contentAccum = '';\n thinkContent = '';\n } else {\n thinkContent = thinkAccum;\n }\n store.updateStreaming(displayContent, thinkContent || reasoningText);\n } else {\n const { safe, pending } = splitAtPartialTag(contentAccum);\n if (safe.length > 0) {\n displayState = 'streaming';\n if (!hasTool) displayContent += safe;\n contentAccum = pending;\n store.updateStreaming(displayContent, reasoningText);\n }\n }\n }"
|
|
1073
|
+
}
|
|
1074
|
+
}
|
|
1075
|
+
],
|
|
1076
|
+
"state": {
|
|
1077
|
+
"type": "complete",
|
|
1078
|
+
"stopReason": "tool_use"
|
|
1079
|
+
},
|
|
1080
|
+
"usage": {
|
|
1081
|
+
"model": "claude-opus-4-6",
|
|
1082
|
+
"maxInputTokens": 168000,
|
|
1083
|
+
"inputTokens": 1,
|
|
1084
|
+
"outputTokens": 1631,
|
|
1085
|
+
"cacheCreationInputTokens": 1396,
|
|
1086
|
+
"cacheReadInputTokens": 58430,
|
|
1087
|
+
"totalInputTokens": 59827,
|
|
1088
|
+
"timestamp": "2026-02-26T23:10:44.716Z"
|
|
1089
|
+
}
|
|
1090
|
+
},
|
|
1091
|
+
{
|
|
1092
|
+
"role": "user",
|
|
1093
|
+
"messageId": 30,
|
|
1094
|
+
"content": [
|
|
1095
|
+
{
|
|
1096
|
+
"type": "tool_result",
|
|
1097
|
+
"toolUseID": "toolu_vrtx_01CKeQfPfQCAKGpptVM7Mnfa",
|
|
1098
|
+
"run": {
|
|
1099
|
+
"status": "done",
|
|
1100
|
+
"progress": {},
|
|
1101
|
+
"result": {
|
|
1102
|
+
"diff": "```diff\nIndex: /home/runner/workspace/src/agent.js\n===================================================================\n--- /home/runner/workspace/src/agent.js\toriginal\n+++ /home/runner/workspace/src/agent.js\tmodified\n@@ -208,9 +208,9 @@\n const { safe, pending } = splitAtPartialTag(contentAccum);\n contentAccum = pending;\n if (!hasTool && safe) displayContent += safe;\n }\n- store.updateStreaming(displayContent, thinkContent);\n+ store.updateStreaming(displayContent, thinkContent || reasoningText);\n \n } else if (displayState === 'thinking') {\n thinkAccum += delta.content;\n const closeMatch = findThinkClose(thinkAccum);\n@@ -223,12 +223,12 @@\n contentAccum = after;\n if (!hasTool && after) displayContent += after;\n contentAccum = '';\n thinkContent = '';\n- store.updateStreaming(displayContent, '');\n+ store.updateStreaming(displayContent, reasoningText);\n } else {\n thinkContent = thinkAccum;\n- store.updateStreaming(displayContent, thinkContent);\n+ store.updateStreaming(displayContent, thinkContent || reasoningText);\n }\n \n } else {\n // buffering\n@@ -254,16 +254,16 @@\n thinkContent = '';\n } else {\n thinkContent = thinkAccum;\n }\n- store.updateStreaming(displayContent, thinkContent);\n+ store.updateStreaming(displayContent, thinkContent || reasoningText);\n } else {\n const { safe, pending } = splitAtPartialTag(contentAccum);\n if (safe.length > 0) {\n displayState = 'streaming';\n if (!hasTool) displayContent += safe;\n contentAccum = pending;\n- store.updateStreaming(displayContent, '');\n+ store.updateStreaming(displayContent, reasoningText);\n }\n }\n }\n }\n```",
|
|
1103
|
+
"lineRange": [
|
|
1104
|
+
212,
|
|
1105
|
+
268
|
|
1106
|
+
]
|
|
1107
|
+
},
|
|
1108
|
+
"trackFiles": [
|
|
1109
|
+
"file:///home/runner/workspace/src/agent.js"
|
|
1110
|
+
]
|
|
1111
|
+
}
|
|
1112
|
+
}
|
|
1113
|
+
]
|
|
1114
|
+
},
|
|
1115
|
+
{
|
|
1116
|
+
"role": "assistant",
|
|
1117
|
+
"messageId": 31,
|
|
1118
|
+
"content": [
|
|
1119
|
+
{
|
|
1120
|
+
"type": "text",
|
|
1121
|
+
"text": "Let me verify the final state of the changed files:"
|
|
1122
|
+
},
|
|
1123
|
+
{
|
|
1124
|
+
"type": "tool_use",
|
|
1125
|
+
"complete": true,
|
|
1126
|
+
"id": "toolu_vrtx_01GuL1uwZkYcHAdHnYMm6tsF",
|
|
1127
|
+
"name": "Read",
|
|
1128
|
+
"input": {
|
|
1129
|
+
"path": "/home/runner/workspace/src/agent.js",
|
|
1130
|
+
"read_range": [
|
|
1131
|
+
170,
|
|
1132
|
+
180
|
|
1133
|
+
]
|
|
1134
|
+
}
|
|
1135
|
+
},
|
|
1136
|
+
{
|
|
1137
|
+
"type": "tool_use",
|
|
1138
|
+
"complete": true,
|
|
1139
|
+
"id": "toolu_vrtx_013YfW5CRkCV8FkQM6YPn7GE",
|
|
1140
|
+
"name": "Read",
|
|
1141
|
+
"input": {
|
|
1142
|
+
"path": "/home/runner/workspace/src/agent.js",
|
|
1143
|
+
"read_range": [
|
|
1144
|
+
295,
|
|
1145
|
+
305
|
|
1146
|
+
]
|
|
1147
|
+
}
|
|
1148
|
+
},
|
|
1149
|
+
{
|
|
1150
|
+
"type": "tool_use",
|
|
1151
|
+
"complete": true,
|
|
1152
|
+
"id": "toolu_vrtx_014osavw2SDoADr8D7E26ouD",
|
|
1153
|
+
"name": "Read",
|
|
1154
|
+
"input": {
|
|
1155
|
+
"path": "/home/runner/workspace/src/agent.js",
|
|
1156
|
+
"read_range": [
|
|
1157
|
+
380,
|
|
1158
|
+
400
|
|
1159
|
+
]
|
|
1160
|
+
}
|
|
1161
|
+
}
|
|
1162
|
+
],
|
|
1163
|
+
"state": {
|
|
1164
|
+
"type": "complete",
|
|
1165
|
+
"stopReason": "tool_use"
|
|
1166
|
+
},
|
|
1167
|
+
"usage": {
|
|
1168
|
+
"model": "claude-opus-4-6",
|
|
1169
|
+
"maxInputTokens": 168000,
|
|
1170
|
+
"inputTokens": 1,
|
|
1171
|
+
"outputTokens": 236,
|
|
1172
|
+
"cacheCreationInputTokens": 2191,
|
|
1173
|
+
"cacheReadInputTokens": 59826,
|
|
1174
|
+
"totalInputTokens": 62018,
|
|
1175
|
+
"timestamp": "2026-02-26T23:10:53.649Z"
|
|
1176
|
+
}
|
|
1177
|
+
},
|
|
1178
|
+
{
|
|
1179
|
+
"role": "user",
|
|
1180
|
+
"messageId": 32,
|
|
1181
|
+
"content": [
|
|
1182
|
+
{
|
|
1183
|
+
"type": "tool_result",
|
|
1184
|
+
"toolUseID": "toolu_vrtx_01GuL1uwZkYcHAdHnYMm6tsF",
|
|
1185
|
+
"run": {
|
|
1186
|
+
"status": "done",
|
|
1187
|
+
"progress": {},
|
|
1188
|
+
"result": {
|
|
1189
|
+
"absolutePath": "/home/runner/workspace/src/agent.js",
|
|
1190
|
+
"content": "[... omitted lines 1 to 169 ...]\n170: }\n171: }\n172: }\n173: \n174: if (delta.reasoning_content) {\n175: reasoningText += delta.reasoning_content;\n176: store.updateStreaming(displayContent, reasoningText);\n177: }\n178: \n179: // Handle content tokens\n180: if (delta.content) {\n[... omitted lines 181 to 441 ...]"
|
|
1191
|
+
},
|
|
1192
|
+
"trackFiles": [
|
|
1193
|
+
"file:///home/runner/workspace/src/agent.js"
|
|
1194
|
+
]
|
|
1195
|
+
}
|
|
1196
|
+
},
|
|
1197
|
+
{
|
|
1198
|
+
"type": "tool_result",
|
|
1199
|
+
"toolUseID": "toolu_vrtx_013YfW5CRkCV8FkQM6YPn7GE",
|
|
1200
|
+
"run": {
|
|
1201
|
+
"status": "done",
|
|
1202
|
+
"progress": {},
|
|
1203
|
+
"result": {
|
|
1204
|
+
"absolutePath": "/home/runner/workspace/src/agent.js",
|
|
1205
|
+
"content": "[... omitted lines 1 to 294 ...]\n295: // Show reasoning from reasoning_content field\n296: if (reasoningText.trim()) {\n297: store.addMessage({ role: 'thinking', content: reasoningText.trim() });\n298: }\n299: \n300: const { content: parsedContent } = parseThinkBlocks(fullContent);\n301: turnTokens += streamUsage?.total_tokens || 0;\n302: \n303: // Reconstruct tool calls\n304: const sortedIndices = Object.keys(toolCallDeltas).sort((a, b) => a - b);\n305: const toolCalls = sortedIndices.map(idx => ({\n[... omitted lines 306 to 441 ...]"
|
|
1206
|
+
},
|
|
1207
|
+
"trackFiles": [
|
|
1208
|
+
"file:///home/runner/workspace/src/agent.js"
|
|
1209
|
+
]
|
|
1210
|
+
}
|
|
1211
|
+
},
|
|
1212
|
+
{
|
|
1213
|
+
"type": "tool_result",
|
|
1214
|
+
"toolUseID": "toolu_vrtx_014osavw2SDoADr8D7E26ouD",
|
|
1215
|
+
"run": {
|
|
1216
|
+
"status": "done",
|
|
1217
|
+
"progress": {},
|
|
1218
|
+
"result": {
|
|
1219
|
+
"absolutePath": "/home/runner/workspace/src/agent.js",
|
|
1220
|
+
"content": "[... omitted lines 1 to 379 ...]\n380: continue;\n381: }\n382: \n383: // No tool calls — final text response\n384: if (fullContent) {\n385: const cleanedContent = parsedContent.trim() || fullContent.replace(/<think>[\\s\\S]*?<\\/think>/g, '').trim();\n386: if (cleanedContent) {\n387: store.finishStreaming({ role: 'assistant', content: cleanedContent });\n388: } else {\n389: store.clearStreaming();\n390: }\n391: session.conversationHistory.push({ role: 'assistant', content: cleanedContent || fullContent });\n392: } else {\n393: store.clearStreaming();\n394: }\n395: break;\n396: }\n397: \n398: if (iterations >= MAX_TOOL_ITERATIONS) {\n399: store.addMessage({ role: 'system', content: `⚠ Reached maximum tool iterations (${MAX_TOOL_ITERATIONS}). Stopping.` });\n400: }\n[... omitted lines 401 to 441 ...]"
|
|
1221
|
+
},
|
|
1222
|
+
"trackFiles": [
|
|
1223
|
+
"file:///home/runner/workspace/src/agent.js"
|
|
1224
|
+
]
|
|
1225
|
+
}
|
|
1226
|
+
}
|
|
1227
|
+
]
|
|
1228
|
+
},
|
|
1229
|
+
{
|
|
1230
|
+
"role": "assistant",
|
|
1231
|
+
"messageId": 33,
|
|
1232
|
+
"content": [
|
|
1233
|
+
{
|
|
1234
|
+
"type": "text",
|
|
1235
|
+
"text": "All three fixes are in place:\n\n1. **`reasoning_content` now streams live** — `store.updateStreaming(displayContent, reasoningText)` is called as reasoning tokens arrive, so the thinking indicator updates in real-time instead of showing a static spinner\n2. **No more flicker on finish** — `store.finishStreaming()` atomically clears the streaming display and adds the final message in a single state update/render\n3. **`splitAtPartialTag` no longer stutters on common words** — removed bare `'think'`, `'thin'`, `'thi'`, `'th'` prefixes that were matching endings of words like \"with\", \"math\", etc."
|
|
1236
|
+
}
|
|
1237
|
+
],
|
|
1238
|
+
"state": {
|
|
1239
|
+
"type": "complete",
|
|
1240
|
+
"stopReason": "end_turn"
|
|
1241
|
+
},
|
|
1242
|
+
"usage": {
|
|
1243
|
+
"model": "claude-opus-4-6",
|
|
1244
|
+
"maxInputTokens": 168000,
|
|
1245
|
+
"inputTokens": 1,
|
|
1246
|
+
"outputTokens": 161,
|
|
1247
|
+
"cacheCreationInputTokens": 989,
|
|
1248
|
+
"cacheReadInputTokens": 62017,
|
|
1249
|
+
"totalInputTokens": 63007,
|
|
1250
|
+
"timestamp": "2026-02-26T23:10:59.948Z"
|
|
1251
|
+
},
|
|
1252
|
+
"turnElapsedMs": 634526
|
|
1253
|
+
}
|
|
1254
|
+
],
|
|
1255
|
+
"agentMode": "smart",
|
|
1256
|
+
"nextMessageId": 34,
|
|
1257
|
+
"meta": {
|
|
1258
|
+
"traces": [
|
|
1259
|
+
{
|
|
1260
|
+
"name": "agent",
|
|
1261
|
+
"id": "ww9fA",
|
|
1262
|
+
"startTime": "2026-02-26T23:00:25.422Z",
|
|
1263
|
+
"context": {
|
|
1264
|
+
"messageId": 0
|
|
1265
|
+
},
|
|
1266
|
+
"endTime": "2026-02-26T23:10:59.949Z"
|
|
1267
|
+
},
|
|
1268
|
+
{
|
|
1269
|
+
"name": "inference",
|
|
1270
|
+
"id": "tqWbC",
|
|
1271
|
+
"parent": "ww9fA",
|
|
1272
|
+
"startTime": "2026-02-26T23:00:25.424Z",
|
|
1273
|
+
"context": {
|
|
1274
|
+
"messageId": 0
|
|
1275
|
+
},
|
|
1276
|
+
"endTime": "2026-02-26T23:00:30.570Z"
|
|
1277
|
+
},
|
|
1278
|
+
{
|
|
1279
|
+
"name": "tools",
|
|
1280
|
+
"id": "rBVPE",
|
|
1281
|
+
"parent": "ww9fA",
|
|
1282
|
+
"startTime": "2026-02-26T23:00:30.569Z",
|
|
1283
|
+
"context": {
|
|
1284
|
+
"messageId": 1
|
|
1285
|
+
},
|
|
1286
|
+
"endTime": "2026-02-26T23:00:30.586Z"
|
|
1287
|
+
},
|
|
1288
|
+
{
|
|
1289
|
+
"name": "inference",
|
|
1290
|
+
"id": "G3NSn",
|
|
1291
|
+
"parent": "ww9fA",
|
|
1292
|
+
"startTime": "2026-02-26T23:00:30.587Z",
|
|
1293
|
+
"context": {
|
|
1294
|
+
"messageId": 0
|
|
1295
|
+
},
|
|
1296
|
+
"endTime": "2026-02-26T23:00:34.521Z"
|
|
1297
|
+
},
|
|
1298
|
+
{
|
|
1299
|
+
"name": "tools",
|
|
1300
|
+
"id": "zsm2V",
|
|
1301
|
+
"parent": "ww9fA",
|
|
1302
|
+
"startTime": "2026-02-26T23:00:34.520Z",
|
|
1303
|
+
"context": {
|
|
1304
|
+
"messageId": 3
|
|
1305
|
+
},
|
|
1306
|
+
"endTime": "2026-02-26T23:00:34.542Z"
|
|
1307
|
+
},
|
|
1308
|
+
{
|
|
1309
|
+
"name": "inference",
|
|
1310
|
+
"id": "7hZuS",
|
|
1311
|
+
"parent": "ww9fA",
|
|
1312
|
+
"startTime": "2026-02-26T23:00:34.542Z",
|
|
1313
|
+
"context": {
|
|
1314
|
+
"messageId": 0
|
|
1315
|
+
},
|
|
1316
|
+
"endTime": "2026-02-26T23:00:44.354Z"
|
|
1317
|
+
},
|
|
1318
|
+
{
|
|
1319
|
+
"name": "tools",
|
|
1320
|
+
"id": "nNV8J",
|
|
1321
|
+
"parent": "ww9fA",
|
|
1322
|
+
"startTime": "2026-02-26T23:00:44.354Z",
|
|
1323
|
+
"context": {
|
|
1324
|
+
"messageId": 5
|
|
1325
|
+
},
|
|
1326
|
+
"endTime": "2026-02-26T23:00:44.365Z"
|
|
1327
|
+
},
|
|
1328
|
+
{
|
|
1329
|
+
"name": "inference",
|
|
1330
|
+
"id": "ih7ll",
|
|
1331
|
+
"parent": "ww9fA",
|
|
1332
|
+
"startTime": "2026-02-26T23:00:44.367Z",
|
|
1333
|
+
"context": {
|
|
1334
|
+
"messageId": 0
|
|
1335
|
+
},
|
|
1336
|
+
"endTime": "2026-02-26T23:01:11.358Z"
|
|
1337
|
+
},
|
|
1338
|
+
{
|
|
1339
|
+
"name": "tools",
|
|
1340
|
+
"id": "Ii5bI",
|
|
1341
|
+
"parent": "ww9fA",
|
|
1342
|
+
"startTime": "2026-02-26T23:01:11.358Z",
|
|
1343
|
+
"context": {
|
|
1344
|
+
"messageId": 7
|
|
1345
|
+
},
|
|
1346
|
+
"endTime": "2026-02-26T23:01:11.380Z"
|
|
1347
|
+
},
|
|
1348
|
+
{
|
|
1349
|
+
"name": "inference",
|
|
1350
|
+
"id": "inAhW",
|
|
1351
|
+
"parent": "ww9fA",
|
|
1352
|
+
"startTime": "2026-02-26T23:01:11.381Z",
|
|
1353
|
+
"context": {
|
|
1354
|
+
"messageId": 0
|
|
1355
|
+
},
|
|
1356
|
+
"endTime": "2026-02-26T23:02:19.615Z"
|
|
1357
|
+
},
|
|
1358
|
+
{
|
|
1359
|
+
"name": "tools",
|
|
1360
|
+
"id": "N7tpl",
|
|
1361
|
+
"parent": "ww9fA",
|
|
1362
|
+
"startTime": "2026-02-26T23:02:19.614Z",
|
|
1363
|
+
"context": {
|
|
1364
|
+
"messageId": 9
|
|
1365
|
+
},
|
|
1366
|
+
"endTime": "2026-02-26T23:02:19.657Z"
|
|
1367
|
+
},
|
|
1368
|
+
{
|
|
1369
|
+
"name": "inference",
|
|
1370
|
+
"id": "ZX5Ay",
|
|
1371
|
+
"parent": "ww9fA",
|
|
1372
|
+
"startTime": "2026-02-26T23:02:19.657Z",
|
|
1373
|
+
"context": {
|
|
1374
|
+
"messageId": 0
|
|
1375
|
+
},
|
|
1376
|
+
"endTime": "2026-02-26T23:09:20.167Z"
|
|
1377
|
+
},
|
|
1378
|
+
{
|
|
1379
|
+
"name": "tools",
|
|
1380
|
+
"id": "3asC7",
|
|
1381
|
+
"parent": "ww9fA",
|
|
1382
|
+
"startTime": "2026-02-26T23:09:20.167Z",
|
|
1383
|
+
"context": {
|
|
1384
|
+
"messageId": 11
|
|
1385
|
+
},
|
|
1386
|
+
"endTime": "2026-02-26T23:09:20.391Z"
|
|
1387
|
+
},
|
|
1388
|
+
{
|
|
1389
|
+
"name": "inference",
|
|
1390
|
+
"id": "H78SK",
|
|
1391
|
+
"parent": "ww9fA",
|
|
1392
|
+
"startTime": "2026-02-26T23:09:20.392Z",
|
|
1393
|
+
"context": {
|
|
1394
|
+
"messageId": 0
|
|
1395
|
+
},
|
|
1396
|
+
"endTime": "2026-02-26T23:09:31.785Z"
|
|
1397
|
+
},
|
|
1398
|
+
{
|
|
1399
|
+
"name": "tools",
|
|
1400
|
+
"id": "FD8ly",
|
|
1401
|
+
"parent": "ww9fA",
|
|
1402
|
+
"startTime": "2026-02-26T23:09:31.784Z",
|
|
1403
|
+
"context": {
|
|
1404
|
+
"messageId": 13
|
|
1405
|
+
},
|
|
1406
|
+
"endTime": "2026-02-26T23:09:31.801Z"
|
|
1407
|
+
},
|
|
1408
|
+
{
|
|
1409
|
+
"name": "inference",
|
|
1410
|
+
"id": "nCyrW",
|
|
1411
|
+
"parent": "ww9fA",
|
|
1412
|
+
"startTime": "2026-02-26T23:09:31.802Z",
|
|
1413
|
+
"context": {
|
|
1414
|
+
"messageId": 0
|
|
1415
|
+
},
|
|
1416
|
+
"endTime": "2026-02-26T23:09:36.370Z"
|
|
1417
|
+
},
|
|
1418
|
+
{
|
|
1419
|
+
"name": "tools",
|
|
1420
|
+
"id": "qSezH",
|
|
1421
|
+
"parent": "ww9fA",
|
|
1422
|
+
"startTime": "2026-02-26T23:09:36.370Z",
|
|
1423
|
+
"context": {
|
|
1424
|
+
"messageId": 15
|
|
1425
|
+
},
|
|
1426
|
+
"endTime": "2026-02-26T23:09:36.381Z"
|
|
1427
|
+
},
|
|
1428
|
+
{
|
|
1429
|
+
"name": "inference",
|
|
1430
|
+
"id": "DK4XP",
|
|
1431
|
+
"parent": "ww9fA",
|
|
1432
|
+
"startTime": "2026-02-26T23:09:36.382Z",
|
|
1433
|
+
"context": {
|
|
1434
|
+
"messageId": 0
|
|
1435
|
+
},
|
|
1436
|
+
"endTime": "2026-02-26T23:09:50.655Z"
|
|
1437
|
+
},
|
|
1438
|
+
{
|
|
1439
|
+
"name": "tools",
|
|
1440
|
+
"id": "GkQLd",
|
|
1441
|
+
"parent": "ww9fA",
|
|
1442
|
+
"startTime": "2026-02-26T23:09:50.655Z",
|
|
1443
|
+
"context": {
|
|
1444
|
+
"messageId": 17
|
|
1445
|
+
},
|
|
1446
|
+
"endTime": "2026-02-26T23:09:50.665Z"
|
|
1447
|
+
},
|
|
1448
|
+
{
|
|
1449
|
+
"name": "inference",
|
|
1450
|
+
"id": "ksl69",
|
|
1451
|
+
"parent": "ww9fA",
|
|
1452
|
+
"startTime": "2026-02-26T23:09:50.666Z",
|
|
1453
|
+
"context": {
|
|
1454
|
+
"messageId": 0
|
|
1455
|
+
},
|
|
1456
|
+
"endTime": "2026-02-26T23:09:55.630Z"
|
|
1457
|
+
},
|
|
1458
|
+
{
|
|
1459
|
+
"name": "tools",
|
|
1460
|
+
"id": "oUURF",
|
|
1461
|
+
"parent": "ww9fA",
|
|
1462
|
+
"startTime": "2026-02-26T23:09:55.630Z",
|
|
1463
|
+
"context": {
|
|
1464
|
+
"messageId": 19
|
|
1465
|
+
},
|
|
1466
|
+
"endTime": "2026-02-26T23:09:55.644Z"
|
|
1467
|
+
},
|
|
1468
|
+
{
|
|
1469
|
+
"name": "inference",
|
|
1470
|
+
"id": "U7V6Z",
|
|
1471
|
+
"parent": "ww9fA",
|
|
1472
|
+
"startTime": "2026-02-26T23:09:55.645Z",
|
|
1473
|
+
"context": {
|
|
1474
|
+
"messageId": 0
|
|
1475
|
+
},
|
|
1476
|
+
"endTime": "2026-02-26T23:10:00.547Z"
|
|
1477
|
+
},
|
|
1478
|
+
{
|
|
1479
|
+
"name": "tools",
|
|
1480
|
+
"id": "6cWIp",
|
|
1481
|
+
"parent": "ww9fA",
|
|
1482
|
+
"startTime": "2026-02-26T23:10:00.547Z",
|
|
1483
|
+
"context": {
|
|
1484
|
+
"messageId": 21
|
|
1485
|
+
},
|
|
1486
|
+
"endTime": "2026-02-26T23:10:00.571Z"
|
|
1487
|
+
},
|
|
1488
|
+
{
|
|
1489
|
+
"name": "inference",
|
|
1490
|
+
"id": "8GCHl",
|
|
1491
|
+
"parent": "ww9fA",
|
|
1492
|
+
"startTime": "2026-02-26T23:10:00.572Z",
|
|
1493
|
+
"context": {
|
|
1494
|
+
"messageId": 0
|
|
1495
|
+
},
|
|
1496
|
+
"endTime": "2026-02-26T23:10:10.883Z"
|
|
1497
|
+
},
|
|
1498
|
+
{
|
|
1499
|
+
"name": "tools",
|
|
1500
|
+
"id": "LgDSz",
|
|
1501
|
+
"parent": "ww9fA",
|
|
1502
|
+
"startTime": "2026-02-26T23:10:10.882Z",
|
|
1503
|
+
"context": {
|
|
1504
|
+
"messageId": 23
|
|
1505
|
+
},
|
|
1506
|
+
"endTime": "2026-02-26T23:10:10.902Z"
|
|
1507
|
+
},
|
|
1508
|
+
{
|
|
1509
|
+
"name": "inference",
|
|
1510
|
+
"id": "318Yw",
|
|
1511
|
+
"parent": "ww9fA",
|
|
1512
|
+
"startTime": "2026-02-26T23:10:10.903Z",
|
|
1513
|
+
"context": {
|
|
1514
|
+
"messageId": 0
|
|
1515
|
+
},
|
|
1516
|
+
"endTime": "2026-02-26T23:10:17.351Z"
|
|
1517
|
+
},
|
|
1518
|
+
{
|
|
1519
|
+
"name": "tools",
|
|
1520
|
+
"id": "vyTLs",
|
|
1521
|
+
"parent": "ww9fA",
|
|
1522
|
+
"startTime": "2026-02-26T23:10:17.351Z",
|
|
1523
|
+
"context": {
|
|
1524
|
+
"messageId": 25
|
|
1525
|
+
},
|
|
1526
|
+
"endTime": "2026-02-26T23:10:17.375Z"
|
|
1527
|
+
},
|
|
1528
|
+
{
|
|
1529
|
+
"name": "inference",
|
|
1530
|
+
"id": "9iFWV",
|
|
1531
|
+
"parent": "ww9fA",
|
|
1532
|
+
"startTime": "2026-02-26T23:10:17.377Z",
|
|
1533
|
+
"context": {
|
|
1534
|
+
"messageId": 0
|
|
1535
|
+
},
|
|
1536
|
+
"endTime": "2026-02-26T23:10:26.744Z"
|
|
1537
|
+
},
|
|
1538
|
+
{
|
|
1539
|
+
"name": "tools",
|
|
1540
|
+
"id": "OabDN",
|
|
1541
|
+
"parent": "ww9fA",
|
|
1542
|
+
"startTime": "2026-02-26T23:10:26.743Z",
|
|
1543
|
+
"context": {
|
|
1544
|
+
"messageId": 27
|
|
1545
|
+
},
|
|
1546
|
+
"endTime": "2026-02-26T23:10:26.756Z"
|
|
1547
|
+
},
|
|
1548
|
+
{
|
|
1549
|
+
"name": "inference",
|
|
1550
|
+
"id": "6Oh4b",
|
|
1551
|
+
"parent": "ww9fA",
|
|
1552
|
+
"startTime": "2026-02-26T23:10:26.758Z",
|
|
1553
|
+
"context": {
|
|
1554
|
+
"messageId": 0
|
|
1555
|
+
},
|
|
1556
|
+
"endTime": "2026-02-26T23:10:44.717Z"
|
|
1557
|
+
},
|
|
1558
|
+
{
|
|
1559
|
+
"name": "tools",
|
|
1560
|
+
"id": "GJOuf",
|
|
1561
|
+
"parent": "ww9fA",
|
|
1562
|
+
"startTime": "2026-02-26T23:10:44.717Z",
|
|
1563
|
+
"context": {
|
|
1564
|
+
"messageId": 29
|
|
1565
|
+
},
|
|
1566
|
+
"endTime": "2026-02-26T23:10:44.752Z"
|
|
1567
|
+
},
|
|
1568
|
+
{
|
|
1569
|
+
"name": "inference",
|
|
1570
|
+
"id": "xZ4Qq",
|
|
1571
|
+
"parent": "ww9fA",
|
|
1572
|
+
"startTime": "2026-02-26T23:10:44.754Z",
|
|
1573
|
+
"context": {
|
|
1574
|
+
"messageId": 0
|
|
1575
|
+
},
|
|
1576
|
+
"endTime": "2026-02-26T23:10:53.650Z"
|
|
1577
|
+
},
|
|
1578
|
+
{
|
|
1579
|
+
"name": "tools",
|
|
1580
|
+
"id": "Ekzpk",
|
|
1581
|
+
"parent": "ww9fA",
|
|
1582
|
+
"startTime": "2026-02-26T23:10:53.650Z",
|
|
1583
|
+
"context": {
|
|
1584
|
+
"messageId": 31
|
|
1585
|
+
},
|
|
1586
|
+
"endTime": "2026-02-26T23:10:53.666Z"
|
|
1587
|
+
},
|
|
1588
|
+
{
|
|
1589
|
+
"name": "inference",
|
|
1590
|
+
"id": "E8HcZ",
|
|
1591
|
+
"parent": "ww9fA",
|
|
1592
|
+
"startTime": "2026-02-26T23:10:53.667Z",
|
|
1593
|
+
"context": {
|
|
1594
|
+
"messageId": 0
|
|
1595
|
+
},
|
|
1596
|
+
"endTime": "2026-02-26T23:10:59.950Z"
|
|
1597
|
+
}
|
|
1598
|
+
]
|
|
1599
|
+
},
|
|
1600
|
+
"env": {
|
|
1601
|
+
"initial": {
|
|
1602
|
+
"trees": [
|
|
1603
|
+
{
|
|
1604
|
+
"displayName": "workspace",
|
|
1605
|
+
"uri": "file:///home/runner/workspace"
|
|
1606
|
+
}
|
|
1607
|
+
],
|
|
1608
|
+
"platform": {
|
|
1609
|
+
"os": "linux",
|
|
1610
|
+
"osVersion": "Ubuntu 24.04.2 LTS",
|
|
1611
|
+
"cpuArchitecture": "x64",
|
|
1612
|
+
"webBrowser": false,
|
|
1613
|
+
"client": "CLI",
|
|
1614
|
+
"clientVersion": "0.0.1772067340-g53cd9b",
|
|
1615
|
+
"clientType": "cli",
|
|
1616
|
+
"installationID": "990855e2-5987-4061-ad34-8c29deacfa95",
|
|
1617
|
+
"deviceFingerprint": "v1:fp_5e0b4aaea6d8b2adcf3c155505cf5c39765fb8ea3e8157ac186424d91df98615"
|
|
1618
|
+
},
|
|
1619
|
+
"tags": [
|
|
1620
|
+
"model:claude-opus-4-6"
|
|
1621
|
+
]
|
|
1622
|
+
}
|
|
1623
|
+
},
|
|
1624
|
+
"title": "Fix response streaming",
|
|
1625
|
+
"~debug": {
|
|
1626
|
+
"lastInferenceUsage": {
|
|
1627
|
+
"model": "claude-opus-4-6",
|
|
1628
|
+
"maxInputTokens": 168000,
|
|
1629
|
+
"inputTokens": 3,
|
|
1630
|
+
"outputTokens": 21962,
|
|
1631
|
+
"cacheCreationInputTokens": 40656,
|
|
1632
|
+
"cacheReadInputTokens": 62017,
|
|
1633
|
+
"totalInputTokens": 63007,
|
|
1634
|
+
"timestamp": "2026-02-26T23:10:59.948Z"
|
|
1635
|
+
}
|
|
1636
|
+
}
|
|
1637
|
+
}
|