repoburg 1.3.201 → 1.3.202
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 +478 -250
- package/agent-pane/backend/src/db/index.ts +6 -0
- package/agent-pane/backend/src/providers/runtime-provider.ts +6 -0
- package/agent-pane/backend/src/repoburg/action-mapping.test.ts +122 -0
- package/agent-pane/backend/src/repoburg/action-mapping.ts +89 -11
- package/agent-pane/backend/src/repoburg/agent-runtime-client.ts +23 -0
- package/agent-pane/backend/src/repoburg/backend-resolver.test.ts +85 -0
- package/agent-pane/backend/src/repoburg/backend-resolver.ts +28 -13
- package/agent-pane/backend/src/repoburg/repoburg-client.test.ts +21 -0
- package/agent-pane/backend/src/repoburg/repoburg-client.ts +13 -0
- package/agent-pane/backend/src/repoburg/repoburg-provider.test.ts +57 -0
- package/agent-pane/backend/src/repoburg/repoburg-provider.ts +49 -0
- package/agent-pane/backend/src/repoburg/turn-projector.test.ts +147 -1
- package/agent-pane/backend/src/repoburg/turn-projector.ts +101 -1
- package/agent-pane/backend/src/routes/sessions.test.ts +215 -1
- package/agent-pane/backend/src/routes/sessions.ts +70 -9
- package/agent-pane/frontend/dist/assets/index-CJxD4YmJ.js +370 -0
- package/agent-pane/frontend/dist/assets/{index-34WaZYsW.css → index-r-xwfOKQ.css} +1 -1
- package/agent-pane/frontend/dist/index.html +2 -2
- package/agent-pane/frontend/src/api/sessions.test.ts +1 -0
- package/agent-pane/frontend/src/api/websocket.test.ts +2 -2
- package/agent-pane/frontend/src/api/websocket.ts +3 -1
- package/agent-pane/frontend/src/components/AskUserItem.test.tsx +143 -0
- package/agent-pane/frontend/src/components/AskUserItem.tsx +207 -0
- package/agent-pane/frontend/src/components/TurnContent.test.tsx +79 -0
- package/agent-pane/frontend/src/components/TurnContent.tsx +49 -3
- package/agent-pane/frontend/src/components/panels/TurnsPanel.test.tsx +48 -0
- package/agent-pane/frontend/src/components/panels/TurnsPanel.tsx +7 -2
- package/agent-pane/frontend/src/store/store.test.ts +19 -0
- package/agent-pane/frontend/src/store/wsSlice.ts +10 -3
- package/agent-pane/frontend/src/styles/app.css +16 -0
- package/agent-pane/frontend/src/test/fixtures.ts +1 -0
- package/agent-pane/frontend/src/types/index.ts +2 -0
- package/agent-pane/frontend/src/utils/duration.test.ts +1 -0
- package/agent-pane/shared/types.ts +17 -0
- package/askuser-after-step5-postgres-selected.png +0 -0
- package/askuser-after-step7-answer-sent.png +0 -0
- package/askuser-card-visible.png +0 -0
- package/backend/dist/src/agent-runtime/agent-runtime-event-emitter.d.ts +16 -0
- package/backend/dist/src/agent-runtime/agent-runtime-event-emitter.js +87 -0
- package/backend/dist/src/agent-runtime/agent-runtime-event-emitter.js.map +1 -1
- package/backend/dist/src/agent-runtime/agent-runtime.types.d.ts +16 -1
- package/backend/dist/src/app.controller.d.ts +1 -0
- package/backend/dist/src/app.service.d.ts +1 -0
- package/backend/dist/src/app.service.js +4 -1
- package/backend/dist/src/app.service.js.map +1 -1
- package/backend/dist/src/interactive-chat/chat.service.d.ts +4 -0
- package/backend/dist/src/interactive-chat/chat.service.js +21 -1
- package/backend/dist/src/interactive-chat/chat.service.js.map +1 -1
- package/backend/dist/src/llm-orchestration/action-handlers/invoke-subagent.handler.js +12 -1
- package/backend/dist/src/llm-orchestration/action-handlers/invoke-subagent.handler.js.map +1 -1
- package/backend/dist/src/llm-orchestration/llm-orchestration.interfaces.d.ts +1 -0
- package/backend/dist/src/llm-orchestration/llm-orchestration.interfaces.js +1 -0
- package/backend/dist/src/llm-orchestration/llm-orchestration.interfaces.js.map +1 -1
- package/backend/dist/src/llm-orchestration/llm-turn-processor.service.js +2 -0
- package/backend/dist/src/llm-orchestration/llm-turn-processor.service.js.map +1 -1
- package/backend/dist/tsconfig.build.tsbuildinfo +1 -1
- package/daemon/dist/api/services.js +4 -0
- package/daemon/dist/serviceManager.js +30 -11
- package/daemon/dist/serviceManager.spec.js +26 -0
- package/daemon/dist/workspace-validation.js +63 -0
- package/daemon/dist/workspace-validation.spec.js +63 -0
- package/package.json +1 -1
- package/r2-step4-apple-banana.png +0 -0
- package/r2-step5-after-rewind-apple-last.png +0 -0
- package/r2-step7-apple-cherry.png +0 -0
- package/r2-step8-cherry-menu-no-restore.png +0 -0
- package/r3-step3-live-task-card-running.png +0 -0
- package/r3-step4-after-completion.png +0 -0
- package/r3-step5-persistence-after-reload.png +0 -0
- package/r3-step6-tasks-tab-card.png +0 -0
- package/reverify-answered-state-answer-sent.png +0 -0
- package/reverify-card-visible-after-completion.png +0 -0
- package/rewind-step3-apple-banana-turns.png +0 -0
- package/rewind-step5-ui-unchanged-after-confirmed-rewind.png +0 -0
- package/rewind-step6-apple-menu-no-restore.png +0 -0
- package/rewind-step7-final-turnlist-unchanged.png +0 -0
- package/rewind-step7-negative-error-toast.png +0 -0
- package/rewind-step7-negative-error-toast2.png +0 -0
- package/subagent-r2-step5-turn-after-reload-no-card.png +0 -0
- package/subagent-r2-step6-tasks-panel-card.png +0 -0
- package/subagent-step3-tasks-tab-done-card.png +0 -0
- package/subagent-step4-turn-stuck-no-cards.png +0 -0
- package/agent-pane/frontend/dist/assets/index-y7xlT86e.js +0 -362
|
@@ -21,6 +21,44 @@ function turnWithToolItem(item: Item): Turn {
|
|
|
21
21
|
return turnWithItems([agentMsg, item], { status: 'completed', agent_response: 'Done' });
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
+
describe('TurnContent — sub-agent cards + response fallback', () => {
|
|
25
|
+
it('renders the agent_response fallback when no agent_message item exists (final-action turns)', () => {
|
|
26
|
+
const turn = turnWithItems([], { status: 'completed', agent_response: 'Confirmed: the answer.' });
|
|
27
|
+
render(<TurnContent turn={turn} />);
|
|
28
|
+
expect(screen.getByText(/Confirmed: the answer\./)).toBeInTheDocument();
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
it('renders no fallback while running or when an agent_message item exists', () => {
|
|
32
|
+
const { rerender } = render(
|
|
33
|
+
<TurnContent turn={turnWithItems([], { status: 'running', agent_response: 'partial' })} />,
|
|
34
|
+
);
|
|
35
|
+
expect(screen.queryByText('partial')).not.toBeInTheDocument();
|
|
36
|
+
|
|
37
|
+
const agentMsg = makeItem('i-agent', 't1', 'agent_message');
|
|
38
|
+
agentMsg.data = { text: 'Item text wins' };
|
|
39
|
+
rerender(<TurnContent turn={turnWithItems([agentMsg], { status: 'completed', agent_response: 'stale fallback' })} />);
|
|
40
|
+
expect(screen.getByText('Item text wins')).toBeInTheDocument();
|
|
41
|
+
expect(screen.queryByText('stale fallback')).not.toBeInTheDocument();
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
it('renders a background_task card in the turn flow (running and completed)', () => {
|
|
45
|
+
const runningTask = makeItem('i-task', 't1', 'background_task');
|
|
46
|
+
runningTask.data = { description: 'run_command: npm test', task_type: 'subagent', status: 'running', token_count: 42, last_tool_name: 'run_command' };
|
|
47
|
+
const { rerender } = render(
|
|
48
|
+
<TurnContent turn={turnWithItems([runningTask], { status: 'running' })} />,
|
|
49
|
+
);
|
|
50
|
+
expect(screen.getByText('run_command: npm test')).toBeInTheDocument();
|
|
51
|
+
|
|
52
|
+
const doneTask = { ...runningTask, status: 'completed' as const, data: { ...runningTask.data, status: 'completed', summary: 'Task finished' } };
|
|
53
|
+
rerender(<TurnContent turn={turnWithItems([doneTask], { status: 'completed' })} />);
|
|
54
|
+
// Card stays visible with the done status; the summary lives in the
|
|
55
|
+
// Tasks panel (Claude-parity compact card).
|
|
56
|
+
expect(screen.getByText('run_command: npm test')).toBeInTheDocument();
|
|
57
|
+
expect(screen.getByText('done')).toBeInTheDocument();
|
|
58
|
+
expect(screen.queryByText('last tool: run_command')).not.toBeInTheDocument();
|
|
59
|
+
});
|
|
60
|
+
});
|
|
61
|
+
|
|
24
62
|
describe('TurnContent', () => {
|
|
25
63
|
afterEach(() => {
|
|
26
64
|
cleanup();
|
|
@@ -283,6 +321,47 @@ describe('TurnContent', () => {
|
|
|
283
321
|
expect(screen.getByText('Post-error')).toBeInTheDocument();
|
|
284
322
|
});
|
|
285
323
|
|
|
324
|
+
it('renders ask_user item after the final agent_message (question card)', () => {
|
|
325
|
+
const agentMsg = makeItem('i1', 't1', 'agent_message');
|
|
326
|
+
agentMsg.data = { text: 'Need your input' };
|
|
327
|
+
const askItem = makeItem('i2', 't1', 'ask_user');
|
|
328
|
+
askItem.data = {
|
|
329
|
+
question: '',
|
|
330
|
+
groups: [{ question: 'Which one?', selections: ['A', 'B'] }],
|
|
331
|
+
};
|
|
332
|
+
const turn = turnWithItems([agentMsg, askItem], {
|
|
333
|
+
status: 'completed',
|
|
334
|
+
agent_response: 'Need your input',
|
|
335
|
+
});
|
|
336
|
+
render(<TurnContent turn={turn} />);
|
|
337
|
+
expect(screen.getByText('Which one?')).toBeInTheDocument();
|
|
338
|
+
expect(screen.getByText('A')).toBeInTheDocument();
|
|
339
|
+
expect(screen.getByText('B')).toBeInTheDocument();
|
|
340
|
+
});
|
|
341
|
+
|
|
342
|
+
it('renders the ask_user card for an ask_user-ONLY turn after completion (always-visible section)', () => {
|
|
343
|
+
const askItem = makeItem('i1', 't1', 'ask_user');
|
|
344
|
+
askItem.data = {
|
|
345
|
+
question: '',
|
|
346
|
+
groups: [{ question: 'Proceed?', selections: ['yes', 'no'] }],
|
|
347
|
+
};
|
|
348
|
+
const turn = turnWithItems([askItem], { status: 'completed' });
|
|
349
|
+
render(<TurnContent turn={turn} />);
|
|
350
|
+
expect(screen.getByText('Proceed?')).toBeInTheDocument();
|
|
351
|
+
expect(screen.getByText('yes')).toBeInTheDocument();
|
|
352
|
+
});
|
|
353
|
+
|
|
354
|
+
it('renders the ask_user card even while the turn is running (disabled by the store state)', () => {
|
|
355
|
+
const askItem = makeItem('i1', 't1', 'ask_user');
|
|
356
|
+
askItem.data = {
|
|
357
|
+
question: '',
|
|
358
|
+
groups: [{ question: 'Proceed?', selections: ['yes', 'no'] }],
|
|
359
|
+
};
|
|
360
|
+
const turn = turnWithItems([askItem], { status: 'running' });
|
|
361
|
+
render(<TurnContent turn={turn} />);
|
|
362
|
+
expect(screen.getByText('Proceed?')).toBeInTheDocument();
|
|
363
|
+
});
|
|
364
|
+
|
|
286
365
|
it('unknown item type renders null (default case)', () => {
|
|
287
366
|
const item = makeItem('i1', 't1', 'unknown_type' as never);
|
|
288
367
|
item.data = {};
|
|
@@ -9,6 +9,7 @@ import type { Turn, Item, DiscussionThread, Attachment } from '../types/index.ts
|
|
|
9
9
|
import { runtimeIcon } from '../types/index.ts';
|
|
10
10
|
import CollapsibleToolCalls, { isToolItem } from './CollapsibleToolCalls.tsx';
|
|
11
11
|
import CommentableText from './CommentableText.tsx';
|
|
12
|
+
import AskUserItem from './AskUserItem.tsx';
|
|
12
13
|
|
|
13
14
|
marked.setOptions({ breaks: true, gfm: true });
|
|
14
15
|
|
|
@@ -306,6 +307,10 @@ function ItemCard({ item, runtimeType, turn, threads }: { item: Item; runtimeTyp
|
|
|
306
307
|
);
|
|
307
308
|
}
|
|
308
309
|
|
|
310
|
+
case 'ask_user': {
|
|
311
|
+
return <AskUserItem item={item} turn={turn} />;
|
|
312
|
+
}
|
|
313
|
+
|
|
309
314
|
case 'background_task': {
|
|
310
315
|
const data = item.data || {};
|
|
311
316
|
const taskType = (data.task_type as string) || 'unknown';
|
|
@@ -427,15 +432,35 @@ function TurnContentBase({ turn, runtimeType, threads = [] }: Props) {
|
|
|
427
432
|
// Intermediate = everything before final agent_message (or ALL items if running)
|
|
428
433
|
const intermediateItems = hasFinalResponse ? turn.items.slice(0, lastAgentIdx) : turn.items;
|
|
429
434
|
|
|
435
|
+
// Fallback final response — some runtime turns (repoburg final-action
|
|
436
|
+
// rounds) never produce an agent_message item; their final text lives on
|
|
437
|
+
// turn.agent_response instead. Synthesize the final card from it.
|
|
438
|
+
const responseFallback: Item | null =
|
|
439
|
+
!hasFinalResponse && turn.status === 'completed' && turn.agent_response
|
|
440
|
+
? {
|
|
441
|
+
id: `response-${turn.id}`,
|
|
442
|
+
turn_id: turn.id,
|
|
443
|
+
external_item_id: `response-${turn.id}`,
|
|
444
|
+
type: 'agent_message',
|
|
445
|
+
data: { text: turn.agent_response },
|
|
446
|
+
status: 'completed',
|
|
447
|
+
created_at: turn.created_at,
|
|
448
|
+
updated_at: turn.updated_at,
|
|
449
|
+
}
|
|
450
|
+
: null;
|
|
451
|
+
|
|
430
452
|
// Filter out empty reasoning items (text is "" — signed-empty thinking blocks from Claude SDK).
|
|
431
453
|
// These inflate the intermediate step count and render as empty cards.
|
|
432
454
|
const visibleIntermediate = intermediateItems.filter(
|
|
433
455
|
(item) => !(item.type === 'reasoning' && (!item.data?.text || item.data.text === '')),
|
|
434
456
|
);
|
|
435
457
|
|
|
436
|
-
// Filter main flow: remove background_task items (they belong in Tasks panel)
|
|
458
|
+
// Filter main flow: remove background_task items (they belong in Tasks panel)
|
|
459
|
+
// and ask_user items (always-visible section below — the answer flow must
|
|
460
|
+
// never hide behind the collapsed intermediate section).
|
|
437
461
|
const mainIntermediate = visibleIntermediate.filter((item) => {
|
|
438
462
|
if (item.type === 'background_task') return false;
|
|
463
|
+
if (item.type === 'ask_user') return false;
|
|
439
464
|
return true;
|
|
440
465
|
});
|
|
441
466
|
|
|
@@ -517,11 +542,32 @@ function TurnContentBase({ turn, runtimeType, threads = [] }: Props) {
|
|
|
517
542
|
</div>
|
|
518
543
|
)}
|
|
519
544
|
|
|
545
|
+
{/* background_task cards — always visible in the turn flow (live sub-agent
|
|
546
|
+
/ monitor lifecycle), outside the collapsible intermediate section.
|
|
547
|
+
Rendered before the final answer to match the chronological flow
|
|
548
|
+
(task ran, then the agent responded). Mirrors the Tasks panel entries
|
|
549
|
+
but inline with the conversation. */}
|
|
550
|
+
{turn.items.filter((i) => i.type === 'background_task').map((item) => (
|
|
551
|
+
<MemoItemCard key={`task-${item.id}`} item={item} runtimeType={runtimeType} turn={turn} threads={threads} />
|
|
552
|
+
))}
|
|
553
|
+
|
|
520
554
|
{/* Final agent message — always visible */}
|
|
521
555
|
{hasFinalResponse && <MemoItemCard key={turn.items[lastAgentIdx].id} item={turn.items[lastAgentIdx]} runtimeType={runtimeType} turn={turn} threads={threads} />}
|
|
522
556
|
|
|
523
|
-
{/*
|
|
524
|
-
{
|
|
557
|
+
{/* Fallback final response (turn.agent_response with no agent_message item). */}
|
|
558
|
+
{responseFallback && (
|
|
559
|
+
<MemoItemCard key={responseFallback.id} item={responseFallback} runtimeType={runtimeType} turn={turn} threads={threads} />
|
|
560
|
+
)}
|
|
561
|
+
|
|
562
|
+
{/* Items after final agent message (rare — errors, etc.; ask_user and
|
|
563
|
+
background_task render in the dedicated always-visible sections below). */}
|
|
564
|
+
{hasFinalResponse && turn.items.slice(lastAgentIdx + 1).filter((i) => i.type !== 'ask_user' && i.type !== 'background_task').map((item) => <MemoItemCard key={item.id} item={item} runtimeType={runtimeType} turn={turn} threads={threads} />)}
|
|
565
|
+
|
|
566
|
+
{/* ask_user cards — always visible + interactive, outside the collapsible
|
|
567
|
+
intermediate section (works even for ask_user-only turns). */}
|
|
568
|
+
{turn.items.filter((i) => i.type === 'ask_user').map((item) => (
|
|
569
|
+
<MemoItemCard key={`ask-${item.id}`} item={item} runtimeType={runtimeType} turn={turn} threads={threads} />
|
|
570
|
+
))}
|
|
525
571
|
|
|
526
572
|
{/* Pending state (no items at all) */}
|
|
527
573
|
{turn.items.length === 0 && !turn.error && (turn.status === 'pending' || turn.status === 'running') && (
|
|
@@ -80,4 +80,52 @@ describe('TurnsPanel', () => {
|
|
|
80
80
|
fireEvent.click(screen.getByText('Branch from Here'));
|
|
81
81
|
expect(branchFromTurn).toHaveBeenCalledWith('s1', 't1');
|
|
82
82
|
});
|
|
83
|
+
|
|
84
|
+
it('shows Restore Rewind for rewound non-repoburg sessions', () => {
|
|
85
|
+
const detail = makeDetail('s1', [makeTurn('t1', 's1'), makeTurn('t2', 's1')], {
|
|
86
|
+
runtime_type: 'codex',
|
|
87
|
+
rewound_at_turn_id: 't1',
|
|
88
|
+
});
|
|
89
|
+
resetStore({ activeSessionId: 's1', sessionDetails: { s1: detail } });
|
|
90
|
+
render(<TurnsPanel />);
|
|
91
|
+
fireEvent.contextMenu(document.querySelector('.turn-item')!);
|
|
92
|
+
expect(screen.getByText('Restore Rewind')).toBeInTheDocument();
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
it('hides Restore Rewind for rewound repoburg sessions (hard delete — no restore)', () => {
|
|
96
|
+
const detail = makeDetail('s1', [makeTurn('t1', 's1'), makeTurn('t2', 's1')], {
|
|
97
|
+
runtime_type: 'repoburg',
|
|
98
|
+
rewound_at_turn_id: 't1',
|
|
99
|
+
});
|
|
100
|
+
resetStore({ activeSessionId: 's1', sessionDetails: { s1: detail } });
|
|
101
|
+
render(<TurnsPanel />);
|
|
102
|
+
fireEvent.contextMenu(document.querySelector('.turn-item')!);
|
|
103
|
+
expect(screen.queryByText('Restore Rewind')).not.toBeInTheDocument();
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
it('repoburg rewind confirm says the runtime history is permanently deleted', () => {
|
|
107
|
+
const confirmSpy = vi.spyOn(window, 'confirm').mockReturnValue(false);
|
|
108
|
+
const rewindToTurn = vi.fn();
|
|
109
|
+
const detail = makeDetail('s1', [makeTurn('t1', 's1'), makeTurn('t2', 's1')], {
|
|
110
|
+
runtime_type: 'repoburg',
|
|
111
|
+
});
|
|
112
|
+
resetStore({ activeSessionId: 's1', sessionDetails: { s1: detail }, rewindToTurn });
|
|
113
|
+
render(<TurnsPanel />);
|
|
114
|
+
fireEvent.contextMenu(document.querySelectorAll('.turn-item')[0]);
|
|
115
|
+
fireEvent.click(screen.getByText('Rewind to Here'));
|
|
116
|
+
expect(confirmSpy).toHaveBeenCalledWith(
|
|
117
|
+
'Rewind to this turn? Runtime history after this point is PERMANENTLY deleted and cannot be restored.',
|
|
118
|
+
);
|
|
119
|
+
expect(rewindToTurn).not.toHaveBeenCalled();
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
it('non-repoburg rewind confirm keeps the restore-later copy', () => {
|
|
123
|
+
const confirmSpy = vi.spyOn(window, 'confirm').mockReturnValue(false);
|
|
124
|
+
const detail = makeDetail('s1', [makeTurn('t1', 's1'), makeTurn('t2', 's1')]);
|
|
125
|
+
resetStore({ activeSessionId: 's1', sessionDetails: { s1: detail } });
|
|
126
|
+
render(<TurnsPanel />);
|
|
127
|
+
fireEvent.contextMenu(document.querySelectorAll('.turn-item')[0]);
|
|
128
|
+
fireEvent.click(screen.getByText('Rewind to Here'));
|
|
129
|
+
expect(confirmSpy).toHaveBeenCalledWith('Rewind to this turn? Hidden turns can be restored later.');
|
|
130
|
+
});
|
|
83
131
|
});
|
|
@@ -26,6 +26,11 @@ export default function TurnsPanel() {
|
|
|
26
26
|
const turns = detail?.turns ?? [];
|
|
27
27
|
const isRunning = detail?.is_running === 1;
|
|
28
28
|
const isRewound = !!detail?.rewound_at_turn_id;
|
|
29
|
+
// Repoburg rewind = platform-parity hard delete — no restore, permanent copy.
|
|
30
|
+
const isRepoburg = detail?.runtime_type === 'repoburg';
|
|
31
|
+
const rewindConfirm = isRepoburg
|
|
32
|
+
? 'Rewind to this turn? Runtime history after this point is PERMANENTLY deleted and cannot be restored.'
|
|
33
|
+
: 'Rewind to this turn? Hidden turns can be restored later.';
|
|
29
34
|
|
|
30
35
|
const [ctxMenu, setCtxMenu] = useState<TurnContextMenu | null>(null);
|
|
31
36
|
const ctxRef = useRef<HTMLDivElement>(null);
|
|
@@ -91,7 +96,7 @@ export default function TurnsPanel() {
|
|
|
91
96
|
className={`ctx-menu-item ${ctxMenu.isLast || isRunning || ctxMenu.isSlashCommand ? 'ctx-disabled' : ''}`}
|
|
92
97
|
onClick={() => {
|
|
93
98
|
if (ctxMenu.isLast || isRunning || ctxMenu.isSlashCommand) return;
|
|
94
|
-
if (window.confirm(
|
|
99
|
+
if (window.confirm(rewindConfirm)) {
|
|
95
100
|
rewindToTurn(activeSessionId!, ctxMenu.turnId);
|
|
96
101
|
}
|
|
97
102
|
setCtxMenu(null);
|
|
@@ -99,7 +104,7 @@ export default function TurnsPanel() {
|
|
|
99
104
|
>
|
|
100
105
|
<Rewind size={12} /> Rewind to Here{ctxMenu.isSlashCommand ? ' (slash command)' : ''}
|
|
101
106
|
</div>
|
|
102
|
-
{isRewound && (
|
|
107
|
+
{isRewound && !isRepoburg && (
|
|
103
108
|
<div
|
|
104
109
|
className="ctx-menu-item"
|
|
105
110
|
onClick={() => {
|
|
@@ -438,6 +438,25 @@ describe('onTurnCompleted', () => {
|
|
|
438
438
|
expect(useStore.getState().sessionDetails['s1'].has_unreviewed).toBe(1);
|
|
439
439
|
expect(useStore.getState().sessions[0].has_unreviewed).toBe(1);
|
|
440
440
|
});
|
|
441
|
+
it('stores the response text when provided and not already streamed', () => {
|
|
442
|
+
const turn = makeTurn('t1', 's1', { status: 'running' });
|
|
443
|
+
const detail = makeDetail('s1', [turn], { is_running: 1 });
|
|
444
|
+
resetStore({ sessionDetails: { s1: detail }, sessions: [makeSession('s1', { is_running: 1 })] });
|
|
445
|
+
|
|
446
|
+
useStore.getState().onTurnCompleted('s1', 't1', makeUsage(), true, 'Confirmed: done.');
|
|
447
|
+
|
|
448
|
+
expect(useStore.getState().sessionDetails['s1'].turns[0].agent_response).toBe('Confirmed: done.');
|
|
449
|
+
});
|
|
450
|
+
|
|
451
|
+
it('keeps streamed agent_response over the event response', () => {
|
|
452
|
+
const turn = makeTurn('t1', 's1', { status: 'running', agent_response: 'streamed text' });
|
|
453
|
+
const detail = makeDetail('s1', [turn], { is_running: 1 });
|
|
454
|
+
resetStore({ sessionDetails: { s1: detail }, sessions: [makeSession('s1', { is_running: 1 })] });
|
|
455
|
+
|
|
456
|
+
useStore.getState().onTurnCompleted('s1', 't1', makeUsage(), true, 'event text');
|
|
457
|
+
|
|
458
|
+
expect(useStore.getState().sessionDetails['s1'].turns[0].agent_response).toBe('streamed text');
|
|
459
|
+
});
|
|
441
460
|
|
|
442
461
|
it('does not change has_unreviewed when hasUnreviewed is falsy', () => {
|
|
443
462
|
const turn = makeTurn('t1', 's1', { status: 'running' });
|
|
@@ -16,7 +16,7 @@ export type WsSlice = {
|
|
|
16
16
|
onItemUpdated: (sessionId: string, turnId: string, item: Item) => void;
|
|
17
17
|
onItemCompleted: (sessionId: string, turnId: string, item: Item) => void;
|
|
18
18
|
onItemDelta: (sessionId: string, turnId: string, itemId: string, delta: string) => void;
|
|
19
|
-
onTurnCompleted: (sessionId: string, turnId: string, usage?: TokenUsage | null, hasUnreviewed?: boolean) => void;
|
|
19
|
+
onTurnCompleted: (sessionId: string, turnId: string, usage?: TokenUsage | null, hasUnreviewed?: boolean, response?: string) => void;
|
|
20
20
|
onTokenUsageUpdated: (sessionId: string, turnId: string, usage: TokenUsage) => void;
|
|
21
21
|
onContextUsageUpdated: (sessionId: string, ctx: ContextUsage) => void;
|
|
22
22
|
onTurnFailed: (sessionId: string, turnId: string, error: string) => void;
|
|
@@ -141,7 +141,7 @@ export const createWsSlice: StateCreator<StoreState, [], [], WsSlice> = (set, ge
|
|
|
141
141
|
});
|
|
142
142
|
},
|
|
143
143
|
|
|
144
|
-
onTurnCompleted: (sessionId, turnId, usage, hasUnreviewed) => {
|
|
144
|
+
onTurnCompleted: (sessionId, turnId, usage, hasUnreviewed, response) => {
|
|
145
145
|
const inTok = usage?.input_tokens ?? 0;
|
|
146
146
|
const outTok = usage?.output_tokens ?? 0;
|
|
147
147
|
get().addLogEntry('INFO', `turn:completed — ${inTok} in / ${outTok} out`);
|
|
@@ -160,7 +160,14 @@ export const createWsSlice: StateCreator<StoreState, [], [], WsSlice> = (set, ge
|
|
|
160
160
|
has_unreviewed: hasUnreviewed ? 1 : detail.has_unreviewed,
|
|
161
161
|
turns: detail.turns.map((t) =>
|
|
162
162
|
t.id === turnId
|
|
163
|
-
? {
|
|
163
|
+
? {
|
|
164
|
+
...t,
|
|
165
|
+
status: 'completed',
|
|
166
|
+
token_usage: usage ?? t.token_usage ?? null,
|
|
167
|
+
// Final text for turns that produce no agent_message item
|
|
168
|
+
// (repoburg final-action rounds) — keep any streamed text.
|
|
169
|
+
...(response && !t.agent_response ? { agent_response: response } : {}),
|
|
170
|
+
}
|
|
164
171
|
: t,
|
|
165
172
|
),
|
|
166
173
|
},
|
|
@@ -609,3 +609,19 @@ mark[data-thread-id].thread-mark-resolved { background: transparent; border-bott
|
|
|
609
609
|
.agent-call-status.running { color: var(--accent); background: var(--accent-soft); }
|
|
610
610
|
.agent-call-status.done { color: var(--green); background: rgba(34,197,94,0.08); }
|
|
611
611
|
.agent-call-status.failed { color: var(--red); background: rgba(239,68,68,0.08); }
|
|
612
|
+
|
|
613
|
+
/* === Ask-user selection buttons (platform parity) === */
|
|
614
|
+
.ask-user-card { border-left: 3px solid var(--accent); }
|
|
615
|
+
.ask-user-groups { display: flex; flex-direction: column; gap: 10px; margin-top: 6px; }
|
|
616
|
+
.ask-user-group { display: flex; flex-direction: column; gap: 6px; }
|
|
617
|
+
.ask-user-question { font-size: 12px; font-weight: 600; color: var(--text-2); }
|
|
618
|
+
.ask-user-options { display: flex; flex-wrap: wrap; gap: 6px; }
|
|
619
|
+
.ask-user-option { padding: 4px 10px; font-size: 12px; font-family: var(--font-sans); color: var(--text-2); background: var(--canvas); border: 1px solid var(--border); border-radius: var(--r-sm); cursor: pointer; transition: all var(--dur-fast) var(--ease); }
|
|
620
|
+
.ask-user-option:not(:disabled):hover { border-color: var(--accent); color: var(--accent); }
|
|
621
|
+
.ask-user-option.selected { background: var(--accent); border-color: var(--accent); color: #fff; }
|
|
622
|
+
.ask-user-option:disabled { opacity: 0.55; cursor: default; }
|
|
623
|
+
.ask-user-option.selected:disabled { opacity: 0.8; }
|
|
624
|
+
.ask-user-send { display: inline-flex; align-items: center; gap: 5px; padding: 4px 12px; font-size: 12px; font-family: var(--font-sans); color: #fff; background: var(--accent); border: none; border-radius: var(--r-sm); cursor: pointer; align-self: flex-start; transition: background var(--dur-fast) var(--ease); }
|
|
625
|
+
.ask-user-send:disabled { opacity: 0.4; cursor: default; }
|
|
626
|
+
.ask-user-send:not(:disabled):hover { background: var(--accent-hover); }
|
|
627
|
+
.ask-user-submitted { font-size: 11px; color: var(--text-muted); font-style: italic; }
|
|
@@ -15,6 +15,8 @@ export type {
|
|
|
15
15
|
DiscussionThread,
|
|
16
16
|
Attachment,
|
|
17
17
|
ContextUsage,
|
|
18
|
+
AskUserItemData,
|
|
19
|
+
AskUserSelectionGroup,
|
|
18
20
|
} from '@agentpane/shared';
|
|
19
21
|
|
|
20
22
|
export type { ProviderDefinition, ProviderCapabilities, ProviderSlashCommand, SessionRuntimeConfig, ModelInfo, Extension } from '@agentpane/shared';
|
|
@@ -22,10 +22,24 @@ export type ItemType =
|
|
|
22
22
|
| 'todo_list'
|
|
23
23
|
| 'context_compaction'
|
|
24
24
|
| 'background_task'
|
|
25
|
+
| 'ask_user'
|
|
25
26
|
| 'error';
|
|
26
27
|
/** Item processing state. */
|
|
27
28
|
export type ItemStatus = 'in_progress' | 'completed' | 'failed';
|
|
28
29
|
|
|
30
|
+
/** One ask_user selection group — a question with clickable options. */
|
|
31
|
+
export interface AskUserSelectionGroup {
|
|
32
|
+
question: string;
|
|
33
|
+
selections: string[];
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/** ask_user item data — the runtime's ask_user action payload. */
|
|
37
|
+
export interface AskUserItemData {
|
|
38
|
+
/** Fallback plain text when the selections payload is malformed. */
|
|
39
|
+
question: string;
|
|
40
|
+
groups: AskUserSelectionGroup[];
|
|
41
|
+
}
|
|
42
|
+
|
|
29
43
|
/** A session row — maps directly to the `sessions` SQLite table. */
|
|
30
44
|
export interface Session {
|
|
31
45
|
id: string;
|
|
@@ -90,6 +104,9 @@ export interface TurnBase {
|
|
|
90
104
|
thread_id: string | null;
|
|
91
105
|
/** Attachments sent with the user prompt (images, PDFs, text files). Null = no attachments. */
|
|
92
106
|
attachments: Attachment[] | null;
|
|
107
|
+
/** Runtime input ids composing this turn (rewind anchor mapping — repoburg;
|
|
108
|
+
* JSON array in the DB). Null = not recorded (turn predates the mapping). */
|
|
109
|
+
runtime_input_ids: string[] | null;
|
|
93
110
|
created_at: string;
|
|
94
111
|
updated_at: string;
|
|
95
112
|
}
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -3,6 +3,7 @@ export declare class AgentRuntimeEventEmitter {
|
|
|
3
3
|
private readonly logger;
|
|
4
4
|
private readonly clients;
|
|
5
5
|
private readonly turnStates;
|
|
6
|
+
private readonly subagents;
|
|
6
7
|
hasSubscribers(sessionId: string): boolean;
|
|
7
8
|
subscribe(sessionId: string, listener: (message: AgentRuntimeMessage) => void, opts?: {
|
|
8
9
|
deltas?: boolean;
|
|
@@ -17,4 +18,19 @@ export declare class AgentRuntimeEventEmitter {
|
|
|
17
18
|
result: string;
|
|
18
19
|
errors?: string[];
|
|
19
20
|
}): void;
|
|
21
|
+
registerSubagent(childSessionId: string, meta: {
|
|
22
|
+
parentId: string;
|
|
23
|
+
inputId: string;
|
|
24
|
+
actionId: string;
|
|
25
|
+
agentName: string;
|
|
26
|
+
description: string;
|
|
27
|
+
}): void;
|
|
28
|
+
unregisterSubagent(childSessionId: string): void;
|
|
29
|
+
emitSubagentStarted(childSessionId: string): void;
|
|
30
|
+
emitSubagentSettled(childSessionId: string, settlement: {
|
|
31
|
+
success: boolean;
|
|
32
|
+
summary: string;
|
|
33
|
+
}): void;
|
|
34
|
+
private emitSubagentEvent;
|
|
35
|
+
private resolveDeliveryParent;
|
|
20
36
|
}
|
|
@@ -20,6 +20,7 @@ let AgentRuntimeEventEmitter = AgentRuntimeEventEmitter_1 = class AgentRuntimeEv
|
|
|
20
20
|
this.logger = new common_1.Logger(AgentRuntimeEventEmitter_1.name);
|
|
21
21
|
this.clients = new Map();
|
|
22
22
|
this.turnStates = new Map();
|
|
23
|
+
this.subagents = new Map();
|
|
23
24
|
}
|
|
24
25
|
hasSubscribers(sessionId) {
|
|
25
26
|
return (this.clients.get(sessionId)?.size ?? 0) > 0;
|
|
@@ -58,6 +59,20 @@ let AgentRuntimeEventEmitter = AgentRuntimeEventEmitter_1 = class AgentRuntimeEv
|
|
|
58
59
|
this.emit({ type: 'stream_event', sessionId, inputId, delta });
|
|
59
60
|
}
|
|
60
61
|
emitAssistant(sessionId, inputId, content, usage) {
|
|
62
|
+
const sub = this.subagents.get(sessionId);
|
|
63
|
+
if (sub) {
|
|
64
|
+
if (usage) {
|
|
65
|
+
sub.usage.input_tokens += usage.input_tokens ?? 0;
|
|
66
|
+
sub.usage.output_tokens += usage.output_tokens ?? 0;
|
|
67
|
+
sub.usage.cache_read_input_tokens += usage.cache_read_input_tokens ?? 0;
|
|
68
|
+
sub.usage.cache_creation_input_tokens +=
|
|
69
|
+
usage.cache_creation_input_tokens ?? 0;
|
|
70
|
+
sub.tokenCount +=
|
|
71
|
+
(usage.input_tokens ?? 0) + (usage.output_tokens ?? 0);
|
|
72
|
+
}
|
|
73
|
+
this.emitSubagentEvent(sessionId, sub, 'progress');
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
61
76
|
const state = this.turnStates.get(sessionId) ?? {
|
|
62
77
|
rounds: 0,
|
|
63
78
|
usage: emptyUsage(),
|
|
@@ -81,6 +96,20 @@ let AgentRuntimeEventEmitter = AgentRuntimeEventEmitter_1 = class AgentRuntimeEv
|
|
|
81
96
|
this.emit(message);
|
|
82
97
|
}
|
|
83
98
|
emitToolResult(sessionId, inputId, toolResult) {
|
|
99
|
+
const sub = this.subagents.get(sessionId);
|
|
100
|
+
if (sub) {
|
|
101
|
+
const action = toolResult.action;
|
|
102
|
+
if (action.action_type !== 'final' &&
|
|
103
|
+
action.action_type !== 'html_final') {
|
|
104
|
+
const detail = action.file_path ?? action.command_string ?? action.tool_name ?? '';
|
|
105
|
+
sub.description = detail
|
|
106
|
+
? `${action.action_type}: ${detail}`
|
|
107
|
+
: action.action_type;
|
|
108
|
+
sub.lastToolName = action.action_type;
|
|
109
|
+
}
|
|
110
|
+
this.emitSubagentEvent(sessionId, sub, 'progress');
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
84
113
|
const message = {
|
|
85
114
|
type: 'user',
|
|
86
115
|
sessionId,
|
|
@@ -90,6 +119,8 @@ let AgentRuntimeEventEmitter = AgentRuntimeEventEmitter_1 = class AgentRuntimeEv
|
|
|
90
119
|
this.emit(message);
|
|
91
120
|
}
|
|
92
121
|
emitResult(sessionId, partial) {
|
|
122
|
+
if (this.subagents.has(sessionId))
|
|
123
|
+
return;
|
|
93
124
|
const state = this.turnStates.get(sessionId);
|
|
94
125
|
const message = {
|
|
95
126
|
type: 'result',
|
|
@@ -104,6 +135,62 @@ let AgentRuntimeEventEmitter = AgentRuntimeEventEmitter_1 = class AgentRuntimeEv
|
|
|
104
135
|
this.turnStates.delete(sessionId);
|
|
105
136
|
this.emit(message);
|
|
106
137
|
}
|
|
138
|
+
registerSubagent(childSessionId, meta) {
|
|
139
|
+
this.subagents.set(childSessionId, {
|
|
140
|
+
parentId: meta.parentId,
|
|
141
|
+
inputId: meta.inputId,
|
|
142
|
+
actionId: meta.actionId,
|
|
143
|
+
agentName: meta.agentName,
|
|
144
|
+
description: meta.description,
|
|
145
|
+
lastToolName: null,
|
|
146
|
+
tokenCount: 0,
|
|
147
|
+
usage: emptyUsage(),
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
unregisterSubagent(childSessionId) {
|
|
151
|
+
this.subagents.delete(childSessionId);
|
|
152
|
+
}
|
|
153
|
+
emitSubagentStarted(childSessionId) {
|
|
154
|
+
const sub = this.subagents.get(childSessionId);
|
|
155
|
+
if (sub)
|
|
156
|
+
this.emitSubagentEvent(childSessionId, sub, 'started');
|
|
157
|
+
}
|
|
158
|
+
emitSubagentSettled(childSessionId, settlement) {
|
|
159
|
+
const sub = this.subagents.get(childSessionId);
|
|
160
|
+
if (!sub)
|
|
161
|
+
return;
|
|
162
|
+
this.emitSubagentEvent(childSessionId, sub, settlement.success ? 'completed' : 'failed', { summary: settlement.summary });
|
|
163
|
+
this.subagents.delete(childSessionId);
|
|
164
|
+
}
|
|
165
|
+
emitSubagentEvent(childSessionId, sub, event, extra = {}) {
|
|
166
|
+
const message = {
|
|
167
|
+
type: 'subagent',
|
|
168
|
+
sessionId: this.resolveDeliveryParent(sub),
|
|
169
|
+
event,
|
|
170
|
+
task_id: childSessionId,
|
|
171
|
+
agent_name: sub.agentName,
|
|
172
|
+
description: sub.description,
|
|
173
|
+
input_id: sub.inputId,
|
|
174
|
+
action_id: sub.actionId,
|
|
175
|
+
...(sub.lastToolName !== null || event !== 'started'
|
|
176
|
+
? { last_tool_name: sub.lastToolName }
|
|
177
|
+
: {}),
|
|
178
|
+
...(sub.tokenCount > 0 ? { token_count: sub.tokenCount } : {}),
|
|
179
|
+
...(event === 'completed' || event === 'failed'
|
|
180
|
+
? { summary: extra.summary ?? '', usage: sub.usage }
|
|
181
|
+
: {}),
|
|
182
|
+
};
|
|
183
|
+
this.emit(message);
|
|
184
|
+
}
|
|
185
|
+
resolveDeliveryParent(sub) {
|
|
186
|
+
let parentId = sub.parentId;
|
|
187
|
+
let guard = 0;
|
|
188
|
+
while (this.subagents.has(parentId) && guard < 100) {
|
|
189
|
+
parentId = this.subagents.get(parentId).parentId;
|
|
190
|
+
guard += 1;
|
|
191
|
+
}
|
|
192
|
+
return parentId;
|
|
193
|
+
}
|
|
107
194
|
};
|
|
108
195
|
exports.AgentRuntimeEventEmitter = AgentRuntimeEventEmitter;
|
|
109
196
|
exports.AgentRuntimeEventEmitter = AgentRuntimeEventEmitter = AgentRuntimeEventEmitter_1 = __decorate([
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent-runtime-event-emitter.js","sourceRoot":"","sources":["../../../src/agent-runtime/agent-runtime-event-emitter.ts"],"names":[],"mappings":";;;;;;;;;;AAAA,2CAAoD;AA0BpD,MAAM,UAAU,GAAG,GAAsB,EAAE,CAAC,CAAC;IAC3C,YAAY,EAAE,CAAC;IACf,aAAa,EAAE,CAAC;IAChB,uBAAuB,EAAE,CAAC;IAC1B,2BAA2B,EAAE,CAAC;CAC/B,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"agent-runtime-event-emitter.js","sourceRoot":"","sources":["../../../src/agent-runtime/agent-runtime-event-emitter.ts"],"names":[],"mappings":"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"}
|
|
@@ -26,6 +26,7 @@ export interface AgentRuntimeActionInfo {
|
|
|
26
26
|
tool_name: string | null;
|
|
27
27
|
arguments: string | null;
|
|
28
28
|
plain: string | null;
|
|
29
|
+
selections: string | null;
|
|
29
30
|
order_of_execution: number;
|
|
30
31
|
}
|
|
31
32
|
export interface AgentRuntimeToolResultBlock {
|
|
@@ -63,6 +64,20 @@ export interface UserMessage {
|
|
|
63
64
|
inputId: string;
|
|
64
65
|
content: AgentRuntimeToolResultBlock[];
|
|
65
66
|
}
|
|
67
|
+
export interface SubagentMessage {
|
|
68
|
+
type: 'subagent';
|
|
69
|
+
sessionId: string;
|
|
70
|
+
event: 'started' | 'progress' | 'completed' | 'failed';
|
|
71
|
+
task_id: string;
|
|
72
|
+
agent_name: string;
|
|
73
|
+
description: string;
|
|
74
|
+
input_id: string;
|
|
75
|
+
action_id: string;
|
|
76
|
+
last_tool_name?: string | null;
|
|
77
|
+
token_count?: number;
|
|
78
|
+
summary?: string;
|
|
79
|
+
usage?: AgentRuntimeUsage;
|
|
80
|
+
}
|
|
66
81
|
export type AgentRuntimeResultSubtype = 'success' | 'error_during_execution' | 'aborted';
|
|
67
82
|
export interface ResultMessage {
|
|
68
83
|
type: 'result';
|
|
@@ -74,4 +89,4 @@ export interface ResultMessage {
|
|
|
74
89
|
num_rounds: number;
|
|
75
90
|
errors?: string[];
|
|
76
91
|
}
|
|
77
|
-
export type AgentRuntimeMessage = SystemInitMessage | StreamEventMessage | AssistantMessage | UserMessage | ResultMessage;
|
|
92
|
+
export type AgentRuntimeMessage = SystemInitMessage | StreamEventMessage | AssistantMessage | UserMessage | SubagentMessage | ResultMessage;
|