repoburg 1.3.196 → 1.3.197
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/agent-pane/backend/data.db-shm +0 -0
- package/agent-pane/backend/data.db-wal +0 -0
- package/agent-pane/backend/dist/index.js +13399 -10390
- package/agent-pane/backend/package-lock.json +162 -92
- package/agent-pane/backend/scripts/backfill-from-jsonl.ts +206 -0
- package/agent-pane/backend/scripts/import-session-from-jsonl.ts +264 -0
- package/agent-pane/backend/src/claude/claude-message-mapper.test.ts +116 -8
- package/agent-pane/backend/src/claude/claude-message-mapper.ts +114 -9
- package/agent-pane/backend/src/claude/claude-provider.ts +918 -84
- package/agent-pane/backend/src/claude/claude-types.ts +16 -4
- package/agent-pane/backend/src/codex/app-server-client.ts +22 -0
- package/agent-pane/backend/src/db/index.ts +102 -0
- package/agent-pane/backend/src/db/schema.ts +4 -0
- package/agent-pane/backend/src/index.ts +3 -1
- package/agent-pane/backend/src/integration/helpers/test-app.ts +2 -0
- package/agent-pane/backend/src/integration/session-operations.test.ts +18 -11
- package/agent-pane/backend/src/integration/threads.test.ts +309 -0
- package/agent-pane/backend/src/providers/runtime-provider.ts +19 -1
- package/agent-pane/backend/src/routes/providers.ts +11 -0
- package/agent-pane/backend/src/routes/sessions.test.ts +143 -9
- package/agent-pane/backend/src/routes/sessions.ts +133 -28
- package/agent-pane/backend/src/routes/threads.ts +308 -0
- package/agent-pane/backend/src/routes/turns.ts +32 -9
- package/agent-pane/frontend/dist/assets/index-BYo-lnxm.js +362 -0
- package/agent-pane/frontend/dist/assets/index-Dwwhx7YN.css +1 -0
- package/agent-pane/frontend/dist/index.html +2 -2
- package/agent-pane/frontend/package-lock.json +51 -9
- package/agent-pane/frontend/src/__tests__/ThreadsPanel.test.tsx +192 -0
- package/agent-pane/frontend/src/api/providers.ts +6 -1
- package/agent-pane/frontend/src/api/sessions.test.ts +4 -0
- package/agent-pane/frontend/src/api/sessions.ts +13 -5
- package/agent-pane/frontend/src/api/websocket.ts +65 -1
- package/agent-pane/frontend/src/components/CollapsibleToolCalls.test.tsx +4 -4
- package/agent-pane/frontend/src/components/CollapsibleToolCalls.tsx +13 -4
- package/agent-pane/frontend/src/components/CommandInputBar.test.tsx +2 -2
- package/agent-pane/frontend/src/components/CommandInputBar.tsx +292 -29
- package/agent-pane/frontend/src/components/CommandPalette.test.tsx +0 -4
- package/agent-pane/frontend/src/components/CommandPalette.tsx +1 -17
- package/agent-pane/frontend/src/components/CommentableText.tsx +291 -0
- package/agent-pane/frontend/src/components/RenderArea.tsx +9 -2
- package/agent-pane/frontend/src/components/RightPanel.test.tsx +5 -5
- package/agent-pane/frontend/src/components/RightPanel.tsx +20 -14
- package/agent-pane/frontend/src/components/SessionTabs.tsx +7 -2
- package/agent-pane/frontend/src/components/StatusBar.tsx +68 -1
- package/agent-pane/frontend/src/components/TurnContent.test.tsx +29 -18
- package/agent-pane/frontend/src/components/TurnContent.tsx +199 -28
- package/agent-pane/frontend/src/components/input/SlashPopup.tsx +24 -5
- package/agent-pane/frontend/src/components/panels/TasksPanel.test.tsx +97 -0
- package/agent-pane/frontend/src/components/panels/TasksPanel.tsx +208 -0
- package/agent-pane/frontend/src/components/panels/ThreadsPanel.tsx +350 -0
- package/agent-pane/frontend/src/components/panels/TurnsPanel.tsx +47 -25
- package/agent-pane/frontend/src/hooks/useSessionStatus.test.ts +2 -0
- package/agent-pane/frontend/src/store/sessionSlice.ts +29 -6
- package/agent-pane/frontend/src/store/store.test.ts +5 -5
- package/agent-pane/frontend/src/store/store.ts +4 -1
- package/agent-pane/frontend/src/store/threadSlice.ts +136 -0
- package/agent-pane/frontend/src/store/wsSlice.ts +72 -3
- package/agent-pane/frontend/src/styles/app.css +150 -19
- package/agent-pane/frontend/src/test/fixtures.ts +4 -0
- package/agent-pane/frontend/src/types/index.ts +5 -2
- package/agent-pane/frontend/src/utils/duration.test.ts +4 -0
- package/agent-pane/frontend/vite.config.ts +2 -2
- package/agent-pane/shared/provider-types.ts +14 -0
- package/agent-pane/shared/types.ts +60 -0
- package/package.json +1 -1
- package/agent-pane/frontend/dist/assets/index-Bg0PF2aV.css +0 -1
- package/agent-pane/frontend/dist/assets/index-BlybeX5e.js +0 -281
- package/agent-pane/frontend/src/components/panels/LogsPanel.test.tsx +0 -58
- package/agent-pane/frontend/src/components/panels/LogsPanel.tsx +0 -25
- package/agent-pane/frontend/src/components/panels/MetricsPanel.test.tsx +0 -71
- package/agent-pane/frontend/src/components/panels/MetricsPanel.tsx +0 -114
|
@@ -23,14 +23,19 @@ export interface ItemDescriptor {
|
|
|
23
23
|
externalId: string; // Claude content block ID (or UUID)
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
-
/** Map assistant content blocks to item descriptors.
|
|
26
|
+
/** Map assistant content blocks to item descriptors.
|
|
27
|
+
* @param thinkingTexts — Optional map of content-block index → accumulated thinking_delta text.
|
|
28
|
+
* When a `thinking` block has empty `thinking` (signed-empty), the mapper falls back to
|
|
29
|
+
* the accumulated text from stream events. */
|
|
27
30
|
export function mapAssistantContent(
|
|
28
31
|
content: BetaContentBlock[],
|
|
29
32
|
messageId: string,
|
|
33
|
+
thinkingTexts?: Map<number, string>,
|
|
30
34
|
): ItemDescriptor[] {
|
|
31
35
|
const descriptors: ItemDescriptor[] = [];
|
|
32
36
|
|
|
33
|
-
for (
|
|
37
|
+
for (let i = 0; i < content.length; i++) {
|
|
38
|
+
const block = content[i];
|
|
34
39
|
switch (block.type) {
|
|
35
40
|
case 'text': {
|
|
36
41
|
const tb = block as BetaTextBlock;
|
|
@@ -44,9 +49,13 @@ export function mapAssistantContent(
|
|
|
44
49
|
|
|
45
50
|
case 'thinking': {
|
|
46
51
|
const tb = block as BetaThinkingBlock;
|
|
52
|
+
let text = tb.thinking;
|
|
53
|
+
if (!text && thinkingTexts) {
|
|
54
|
+
text = thinkingTexts.get(i) ?? '';
|
|
55
|
+
}
|
|
47
56
|
descriptors.push({
|
|
48
57
|
type: 'reasoning',
|
|
49
|
-
data: { text
|
|
58
|
+
data: { text },
|
|
50
59
|
externalId: messageId,
|
|
51
60
|
});
|
|
52
61
|
break;
|
|
@@ -92,10 +101,7 @@ function mapToolUse(block: BetaToolUseBlock): ItemDescriptor {
|
|
|
92
101
|
if (block.name === 'Edit' || block.name === 'Write' || block.name === 'MultiEdit' || block.name === 'NotebookEdit') {
|
|
93
102
|
return {
|
|
94
103
|
type: 'file_change',
|
|
95
|
-
data:
|
|
96
|
-
changes: input,
|
|
97
|
-
status: 'in_progress',
|
|
98
|
-
},
|
|
104
|
+
data: deriveFileChangeData(input, block.name),
|
|
99
105
|
externalId: block.id,
|
|
100
106
|
};
|
|
101
107
|
}
|
|
@@ -115,10 +121,109 @@ function mapToolUse(block: BetaToolUseBlock): ItemDescriptor {
|
|
|
115
121
|
};
|
|
116
122
|
}
|
|
117
123
|
|
|
124
|
+
// ---------------------------------------------------------------------------
|
|
125
|
+
// Tool-result mapping — pure functions shared by the live provider and the
|
|
126
|
+
// JSONL backfill script. Kept free of DB / SDK-specific types so both callers
|
|
127
|
+
// (which hold different shapes: typed SDK blocks vs parsed JSON) can use them.
|
|
128
|
+
// ---------------------------------------------------------------------------
|
|
129
|
+
|
|
130
|
+
/** Derive the canonical file_change data from a Claude file-edit tool_use input.
|
|
131
|
+
* Each Edit/Write/MultiEdit/NotebookEdit touches a single file → one change.
|
|
132
|
+
* Frontend expects `changes: Array<{ path, kind }>` (matches Codex app-server). */
|
|
133
|
+
export function deriveFileChangeData(
|
|
134
|
+
input: Record<string, unknown>,
|
|
135
|
+
toolName: string,
|
|
136
|
+
): { changes: Array<{ path: string; kind: string }>; status: string } {
|
|
137
|
+
const path = (input.file_path ?? input.notebook_path ?? '') as string;
|
|
138
|
+
const kind = toolName === 'Write' ? 'add' : 'modify';
|
|
139
|
+
return { changes: [{ path, kind }], status: 'in_progress' };
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/** Loose shape of a `tool_result` content block — works for SDK blocks and parsed JSONL. */
|
|
143
|
+
export interface ToolResultLike {
|
|
144
|
+
tool_use_id?: string;
|
|
145
|
+
is_error?: boolean;
|
|
146
|
+
content?: unknown;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/** Extract concatenated text from a tool_result `content` (string or array of text blocks). */
|
|
150
|
+
export function extractToolResultText(content: unknown): string {
|
|
151
|
+
if (!content) return '';
|
|
152
|
+
if (typeof content === 'string') return content;
|
|
153
|
+
if (Array.isArray(content)) {
|
|
154
|
+
return content
|
|
155
|
+
.map((b) => {
|
|
156
|
+
if (b && typeof b === 'object' && (b as { type?: string }).type === 'text') {
|
|
157
|
+
return String((b as { text?: unknown }).text ?? '');
|
|
158
|
+
}
|
|
159
|
+
return '';
|
|
160
|
+
})
|
|
161
|
+
.filter(Boolean)
|
|
162
|
+
.join('\n');
|
|
163
|
+
}
|
|
164
|
+
return '';
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/** Build the updated item `data` after a tool_result arrives. Pure; no DB access.
|
|
168
|
+
*
|
|
169
|
+
* - `command_execution`: aggregated_output from the result text (Bash stdout) plus
|
|
170
|
+
* structured stderr when present; exit_code heuristically from is_error (the Claude
|
|
171
|
+
* SDK does not expose a real exit code for Bash).
|
|
172
|
+
* - `mcp_tool_call`: result text from the tool_result content; error when is_error.
|
|
173
|
+
* - `file_change`: the `changes` array was set at tool_use time — just mark status.
|
|
174
|
+
* @param itemType — DB item type ('command_execution' | 'file_change' | 'mcp_tool_call').
|
|
175
|
+
* @param existingData — current `data` object stored on the item.
|
|
176
|
+
* @param toolResult — the tool_result content block (may be null if only structured output exists).
|
|
177
|
+
* @param toolUseResult — the SDK `tool_use_result` structured object (per-tool shape; Bash → {stdout, stderr}).
|
|
178
|
+
* @param isError — whether the tool_result flagged an error. */
|
|
179
|
+
export function applyToolResult(
|
|
180
|
+
itemType: string,
|
|
181
|
+
existingData: Record<string, unknown>,
|
|
182
|
+
toolResult: ToolResultLike | null,
|
|
183
|
+
toolUseResult: unknown,
|
|
184
|
+
isError: boolean,
|
|
185
|
+
): Record<string, unknown> {
|
|
186
|
+
switch (itemType) {
|
|
187
|
+
case 'command_execution': {
|
|
188
|
+
const text = extractToolResultText(toolResult?.content);
|
|
189
|
+
const tur = (toolUseResult && typeof toolUseResult === 'object' ? toolUseResult : {}) as Record<string, unknown>;
|
|
190
|
+
const stdout = typeof tur.stdout === 'string' ? tur.stdout : '';
|
|
191
|
+
const stderr = typeof tur.stderr === 'string' ? tur.stderr : '';
|
|
192
|
+
let aggregated = text || stdout;
|
|
193
|
+
if (stderr) aggregated = aggregated ? `${aggregated}\n${stderr}` : stderr;
|
|
194
|
+
return {
|
|
195
|
+
...existingData,
|
|
196
|
+
aggregated_output: aggregated,
|
|
197
|
+
exit_code: isError ? 1 : 0,
|
|
198
|
+
status: isError ? 'failed' : 'completed',
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
case 'mcp_tool_call': {
|
|
203
|
+
const text = extractToolResultText(toolResult?.content);
|
|
204
|
+
return {
|
|
205
|
+
...existingData,
|
|
206
|
+
result: text ? [{ type: 'text', text }] : (toolUseResult ?? null),
|
|
207
|
+
error: isError ? (text || 'Tool error') : null,
|
|
208
|
+
status: isError ? 'failed' : 'completed',
|
|
209
|
+
};
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
case 'file_change': {
|
|
213
|
+
// `changes` was derived at tool_use time; only flip the inner status.
|
|
214
|
+
return { ...existingData, status: isError ? 'failed' : 'completed' };
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
default:
|
|
218
|
+
return existingData;
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
|
|
118
222
|
/** Result of mapping a partial (streaming) delta event. */
|
|
119
223
|
export interface DeltaResult {
|
|
120
224
|
kind: 'text' | 'thinking';
|
|
121
225
|
text: string;
|
|
226
|
+
index: number;
|
|
122
227
|
}
|
|
123
228
|
|
|
124
229
|
/** Map a streaming delta event to a text or thinking fragment. Returns null for non-delta events. */
|
|
@@ -128,10 +233,10 @@ export function mapPartialDelta(event: unknown): DeltaResult | null {
|
|
|
128
233
|
|
|
129
234
|
const delta = e.delta as unknown as Record<string, unknown>;
|
|
130
235
|
if (delta.type === 'text_delta') {
|
|
131
|
-
return { kind: 'text', text: delta.text as string };
|
|
236
|
+
return { kind: 'text', text: delta.text as string, index: e.index };
|
|
132
237
|
}
|
|
133
238
|
if (delta.type === 'thinking_delta') {
|
|
134
|
-
return { kind: 'thinking', text: delta.thinking as string };
|
|
239
|
+
return { kind: 'thinking', text: delta.thinking as string, index: e.index };
|
|
135
240
|
}
|
|
136
241
|
|
|
137
242
|
return null;
|