repoburg 1.3.201 → 1.3.204
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/dist/index.js +2714 -32395
- package/agent-pane/backend/dist/server.js +45304 -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/agentPane.js +128 -0
- package/daemon/dist/agentPane.spec.js +183 -0
- package/daemon/dist/api/services.js +4 -0
- package/daemon/dist/index.js +28 -8
- 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/daemon/package.json +1 -1
- package/package.json +15 -2
- 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/.prettierignore +0 -5
- package/agent-pane/.prettierrc +0 -8
- package/agent-pane/backend/coverage/base.css +0 -224
- package/agent-pane/backend/coverage/block-navigation.js +0 -87
- package/agent-pane/backend/coverage/clover.xml +0 -887
- package/agent-pane/backend/coverage/coverage-final.json +0 -10
- package/agent-pane/backend/coverage/favicon.png +0 -0
- package/agent-pane/backend/coverage/index.html +0 -176
- package/agent-pane/backend/coverage/prettify.css +0 -1
- package/agent-pane/backend/coverage/prettify.js +0 -2
- package/agent-pane/backend/coverage/sort-arrow-sprite.png +0 -0
- package/agent-pane/backend/coverage/sorter.js +0 -210
- package/agent-pane/backend/coverage/src/codex/codex-provider.ts.html +0 -1402
- package/agent-pane/backend/coverage/src/codex/index.html +0 -131
- package/agent-pane/backend/coverage/src/codex/item-mapper.ts.html +0 -331
- package/agent-pane/backend/coverage/src/db/index.html +0 -131
- package/agent-pane/backend/coverage/src/db/index.ts.html +0 -436
- package/agent-pane/backend/coverage/src/db/schema.ts.html +0 -175
- package/agent-pane/backend/coverage/src/index.html +0 -116
- package/agent-pane/backend/coverage/src/index.ts.html +0 -262
- package/agent-pane/backend/coverage/src/routes/index.html +0 -146
- package/agent-pane/backend/coverage/src/routes/sessions.ts.html +0 -991
- package/agent-pane/backend/coverage/src/routes/turns.ts.html +0 -256
- package/agent-pane/backend/coverage/src/routes/workspaces.ts.html +0 -406
- package/agent-pane/backend/coverage/src/ws/index.html +0 -116
- package/agent-pane/backend/coverage/src/ws/index.ts.html +0 -238
- package/agent-pane/backend/data.db +0 -0
- package/agent-pane/backend/data.db-shm +0 -0
- package/agent-pane/backend/data.db-wal +0 -0
- package/agent-pane/backend/package-lock.json +0 -5945
- package/agent-pane/backend/package.json +0 -33
- package/agent-pane/backend/scripts/backfill-from-jsonl.ts +0 -206
- package/agent-pane/backend/scripts/import-session-from-jsonl.ts +0 -264
- package/agent-pane/backend/src/claude/claude-message-mapper.test.ts +0 -271
- package/agent-pane/backend/src/claude/claude-message-mapper.ts +0 -259
- package/agent-pane/backend/src/claude/claude-provider.test.ts +0 -455
- package/agent-pane/backend/src/claude/claude-provider.ts +0 -1319
- package/agent-pane/backend/src/claude/claude-types.ts +0 -45
- package/agent-pane/backend/src/codex/app-server-client.test.ts +0 -183
- package/agent-pane/backend/src/codex/app-server-client.ts +0 -247
- package/agent-pane/backend/src/codex/app-server-types.ts +0 -259
- package/agent-pane/backend/src/codex/codex-provider-runtime-config.test.ts +0 -56
- package/agent-pane/backend/src/codex/codex-provider.test.ts +0 -60
- package/agent-pane/backend/src/codex/codex-provider.ts +0 -619
- package/agent-pane/backend/src/codex/item-mapper.test.ts +0 -221
- package/agent-pane/backend/src/codex/item-mapper.ts +0 -86
- package/agent-pane/backend/src/codex/shared-app-server.ts +0 -25
- package/agent-pane/backend/src/db/index.test.ts +0 -125
- package/agent-pane/backend/src/db/index.ts +0 -230
- package/agent-pane/backend/src/db/schema.ts +0 -34
- package/agent-pane/backend/src/index.ts +0 -89
- package/agent-pane/backend/src/integration/__fixtures__/cancel-turn.json +0 -29
- package/agent-pane/backend/src/integration/__fixtures__/delta-streaming.json +0 -40
- package/agent-pane/backend/src/integration/__fixtures__/failed-turn.json +0 -16
- package/agent-pane/backend/src/integration/__fixtures__/mcp-tool-call.json +0 -60
- package/agent-pane/backend/src/integration/__fixtures__/missing-item-started.json +0 -34
- package/agent-pane/backend/src/integration/__fixtures__/multi-item-turn.json +0 -85
- package/agent-pane/backend/src/integration/__fixtures__/multi-turn.json +0 -48
- package/agent-pane/backend/src/integration/__fixtures__/simple-turn.json +0 -35
- package/agent-pane/backend/src/integration/delta-streaming.test.ts +0 -130
- package/agent-pane/backend/src/integration/helpers/app-server-mock.ts +0 -272
- package/agent-pane/backend/src/integration/helpers/test-app.ts +0 -110
- package/agent-pane/backend/src/integration/helpers/ws-capture.ts +0 -64
- package/agent-pane/backend/src/integration/item-lifecycle.test.ts +0 -133
- package/agent-pane/backend/src/integration/mcp-tool-call.test.ts +0 -102
- package/agent-pane/backend/src/integration/missing-item-started.test.ts +0 -91
- package/agent-pane/backend/src/integration/multi-turn.test.ts +0 -121
- package/agent-pane/backend/src/integration/session-operations.test.ts +0 -175
- package/agent-pane/backend/src/integration/threads-claude-fork.test.ts +0 -241
- package/agent-pane/backend/src/integration/threads.test.ts +0 -309
- package/agent-pane/backend/src/integration/title-generation.test.ts +0 -109
- package/agent-pane/backend/src/integration/turn-cancel.test.ts +0 -111
- package/agent-pane/backend/src/integration/turn-failure.test.ts +0 -97
- package/agent-pane/backend/src/integration/turn-lifecycle.test.ts +0 -141
- package/agent-pane/backend/src/providers/index.ts +0 -16
- package/agent-pane/backend/src/providers/registry.test.ts +0 -92
- package/agent-pane/backend/src/providers/registry.ts +0 -43
- package/agent-pane/backend/src/providers/runtime-provider.ts +0 -43
- package/agent-pane/backend/src/repoburg/action-mapping.ts +0 -216
- package/agent-pane/backend/src/repoburg/agent-runtime-client.test.ts +0 -271
- package/agent-pane/backend/src/repoburg/agent-runtime-client.ts +0 -262
- package/agent-pane/backend/src/repoburg/backend-resolver.test.ts +0 -271
- package/agent-pane/backend/src/repoburg/backend-resolver.ts +0 -246
- package/agent-pane/backend/src/repoburg/repoburg-client.test.ts +0 -159
- package/agent-pane/backend/src/repoburg/repoburg-client.ts +0 -181
- package/agent-pane/backend/src/repoburg/repoburg-provider.test.ts +0 -723
- package/agent-pane/backend/src/repoburg/repoburg-provider.ts +0 -422
- package/agent-pane/backend/src/repoburg/turn-projector.test.ts +0 -475
- package/agent-pane/backend/src/repoburg/turn-projector.ts +0 -537
- package/agent-pane/backend/src/routes/files.ts +0 -31
- package/agent-pane/backend/src/routes/mcp.ts +0 -33
- package/agent-pane/backend/src/routes/models.test.ts +0 -92
- package/agent-pane/backend/src/routes/models.ts +0 -16
- package/agent-pane/backend/src/routes/plugins.ts +0 -40
- package/agent-pane/backend/src/routes/providers.test.ts +0 -86
- package/agent-pane/backend/src/routes/providers.ts +0 -86
- package/agent-pane/backend/src/routes/sessions.test.ts +0 -558
- package/agent-pane/backend/src/routes/sessions.ts +0 -504
- package/agent-pane/backend/src/routes/skills.test.ts +0 -114
- package/agent-pane/backend/src/routes/skills.ts +0 -70
- package/agent-pane/backend/src/routes/threads.ts +0 -323
- package/agent-pane/backend/src/routes/turns.test.ts +0 -196
- package/agent-pane/backend/src/routes/turns.ts +0 -103
- package/agent-pane/backend/src/routes/workspaces.test.ts +0 -197
- package/agent-pane/backend/src/routes/workspaces.ts +0 -128
- package/agent-pane/backend/src/ws/index.test.ts +0 -107
- package/agent-pane/backend/src/ws/index.ts +0 -51
- package/agent-pane/backend/tsconfig.json +0 -25
- package/agent-pane/backend/vitest.config.ts +0 -20
- package/agent-pane/eslint.config.js +0 -33
- package/agent-pane/frontend/coverage/base.css +0 -224
- package/agent-pane/frontend/coverage/block-navigation.js +0 -87
- package/agent-pane/frontend/coverage/clover.xml +0 -2962
- package/agent-pane/frontend/coverage/coverage-final.json +0 -37
- package/agent-pane/frontend/coverage/favicon.png +0 -0
- package/agent-pane/frontend/coverage/index.html +0 -251
- package/agent-pane/frontend/coverage/prettify.css +0 -1
- package/agent-pane/frontend/coverage/prettify.js +0 -2
- package/agent-pane/frontend/coverage/sort-arrow-sprite.png +0 -0
- package/agent-pane/frontend/coverage/sorter.js +0 -210
- package/agent-pane/frontend/coverage/src/App.tsx.html +0 -217
- package/agent-pane/frontend/coverage/src/AppInitializer.tsx.html +0 -223
- package/agent-pane/frontend/coverage/src/api/client.ts.html +0 -187
- package/agent-pane/frontend/coverage/src/api/index.html +0 -161
- package/agent-pane/frontend/coverage/src/api/sessions.ts.html +0 -316
- package/agent-pane/frontend/coverage/src/api/websocket.ts.html +0 -544
- package/agent-pane/frontend/coverage/src/api/workspaces.ts.html +0 -199
- package/agent-pane/frontend/coverage/src/components/CollapsibleToolCalls.tsx.html +0 -226
- package/agent-pane/frontend/coverage/src/components/CommandInputBar.tsx.html +0 -382
- package/agent-pane/frontend/coverage/src/components/CommandPalette.tsx.html +0 -715
- package/agent-pane/frontend/coverage/src/components/IdeWorkspace.tsx.html +0 -160
- package/agent-pane/frontend/coverage/src/components/ModelSelector.tsx.html +0 -478
- package/agent-pane/frontend/coverage/src/components/NewSessionDialog.tsx.html +0 -472
- package/agent-pane/frontend/coverage/src/components/RenderArea.tsx.html +0 -574
- package/agent-pane/frontend/coverage/src/components/RightPanel.tsx.html +0 -205
- package/agent-pane/frontend/coverage/src/components/RuntimeIcon.tsx.html +0 -133
- package/agent-pane/frontend/coverage/src/components/SessionTabs.tsx.html +0 -217
- package/agent-pane/frontend/coverage/src/components/StatusBar.tsx.html +0 -271
- package/agent-pane/frontend/coverage/src/components/StatusDot.tsx.html +0 -109
- package/agent-pane/frontend/coverage/src/components/Toast.tsx.html +0 -313
- package/agent-pane/frontend/coverage/src/components/TurnContent.tsx.html +0 -1216
- package/agent-pane/frontend/coverage/src/components/WorkspaceSidebar.tsx.html +0 -1138
- package/agent-pane/frontend/coverage/src/components/index.html +0 -326
- package/agent-pane/frontend/coverage/src/components/panels/ChangesPanel.tsx.html +0 -247
- package/agent-pane/frontend/coverage/src/components/panels/LogsPanel.tsx.html +0 -160
- package/agent-pane/frontend/coverage/src/components/panels/MetricsPanel.tsx.html +0 -427
- package/agent-pane/frontend/coverage/src/components/panels/TurnsPanel.tsx.html +0 -397
- package/agent-pane/frontend/coverage/src/components/panels/index.html +0 -161
- package/agent-pane/frontend/coverage/src/constants/index.html +0 -116
- package/agent-pane/frontend/coverage/src/constants/models.ts.html +0 -406
- package/agent-pane/frontend/coverage/src/hooks/index.html +0 -146
- package/agent-pane/frontend/coverage/src/hooks/useEscapeKey.ts.html +0 -124
- package/agent-pane/frontend/coverage/src/hooks/useOutsideClick.ts.html +0 -142
- package/agent-pane/frontend/coverage/src/hooks/useSessionStatus.ts.html +0 -187
- package/agent-pane/frontend/coverage/src/index.html +0 -146
- package/agent-pane/frontend/coverage/src/main.tsx.html +0 -115
- package/agent-pane/frontend/coverage/src/store/index.html +0 -116
- package/agent-pane/frontend/coverage/src/store/store.ts.html +0 -2404
- package/agent-pane/frontend/coverage/src/test/component-helpers.ts.html +0 -190
- package/agent-pane/frontend/coverage/src/test/fixtures.ts.html +0 -367
- package/agent-pane/frontend/coverage/src/test/index.html +0 -131
- package/agent-pane/frontend/coverage/src/types/index.html +0 -116
- package/agent-pane/frontend/coverage/src/types/index.ts.html +0 -466
- package/agent-pane/frontend/coverage/src/utils/changes.ts.html +0 -202
- package/agent-pane/frontend/coverage/src/utils/duration.ts.html +0 -127
- package/agent-pane/frontend/coverage/src/utils/index.html +0 -131
- package/agent-pane/frontend/dist/assets/index-34WaZYsW.css +0 -1
- package/agent-pane/frontend/dist/assets/index-y7xlT86e.js +0 -362
- package/agent-pane/frontend/dist/index.html +0 -19
- package/agent-pane/frontend/index.html +0 -18
- package/agent-pane/frontend/package-lock.json +0 -4211
- package/agent-pane/frontend/package.json +0 -35
- package/agent-pane/frontend/src/App.test.tsx +0 -74
- package/agent-pane/frontend/src/App.tsx +0 -44
- package/agent-pane/frontend/src/AppInitializer.test.tsx +0 -142
- package/agent-pane/frontend/src/AppInitializer.tsx +0 -46
- package/agent-pane/frontend/src/__tests__/ThreadsPanel.test.tsx +0 -192
- package/agent-pane/frontend/src/api/client.test.ts +0 -126
- package/agent-pane/frontend/src/api/client.ts +0 -34
- package/agent-pane/frontend/src/api/models.ts +0 -7
- package/agent-pane/frontend/src/api/providers.ts +0 -17
- package/agent-pane/frontend/src/api/sessions.test.ts +0 -245
- package/agent-pane/frontend/src/api/sessions.ts +0 -97
- package/agent-pane/frontend/src/api/skills.ts +0 -12
- package/agent-pane/frontend/src/api/websocket.test.ts +0 -288
- package/agent-pane/frontend/src/api/websocket.ts +0 -238
- package/agent-pane/frontend/src/api/workspaces.test.ts +0 -112
- package/agent-pane/frontend/src/api/workspaces.ts +0 -38
- package/agent-pane/frontend/src/components/CollapsibleToolCalls.test.tsx +0 -49
- package/agent-pane/frontend/src/components/CollapsibleToolCalls.tsx +0 -56
- package/agent-pane/frontend/src/components/CommandInputBar.test.tsx +0 -133
- package/agent-pane/frontend/src/components/CommandInputBar.tsx +0 -584
- package/agent-pane/frontend/src/components/CommandPalette.test.tsx +0 -226
- package/agent-pane/frontend/src/components/CommandPalette.tsx +0 -194
- package/agent-pane/frontend/src/components/CommentableText.test.tsx +0 -196
- package/agent-pane/frontend/src/components/CommentableText.tsx +0 -379
- package/agent-pane/frontend/src/components/IdeWorkspace.test.tsx +0 -39
- package/agent-pane/frontend/src/components/IdeWorkspace.tsx +0 -51
- package/agent-pane/frontend/src/components/ModelSelector.test.tsx +0 -129
- package/agent-pane/frontend/src/components/ModelSelector.tsx +0 -191
- package/agent-pane/frontend/src/components/NewSessionDialog.test.tsx +0 -95
- package/agent-pane/frontend/src/components/NewSessionDialog.tsx +0 -129
- package/agent-pane/frontend/src/components/RenderArea.test.tsx +0 -160
- package/agent-pane/frontend/src/components/RenderArea.tsx +0 -170
- package/agent-pane/frontend/src/components/ResizeHandle.tsx +0 -29
- package/agent-pane/frontend/src/components/RightPanel.test.tsx +0 -43
- package/agent-pane/frontend/src/components/RightPanel.tsx +0 -46
- package/agent-pane/frontend/src/components/RuntimeIcon.test.tsx +0 -32
- package/agent-pane/frontend/src/components/RuntimeIcon.tsx +0 -16
- package/agent-pane/frontend/src/components/SessionTabs.test.tsx +0 -72
- package/agent-pane/frontend/src/components/SessionTabs.tsx +0 -49
- package/agent-pane/frontend/src/components/StatusBar.test.tsx +0 -56
- package/agent-pane/frontend/src/components/StatusBar.tsx +0 -129
- package/agent-pane/frontend/src/components/StatusDot.test.tsx +0 -25
- package/agent-pane/frontend/src/components/StatusDot.tsx +0 -8
- package/agent-pane/frontend/src/components/Toast.test.tsx +0 -79
- package/agent-pane/frontend/src/components/Toast.tsx +0 -76
- package/agent-pane/frontend/src/components/TurnContent.test.tsx +0 -298
- package/agent-pane/frontend/src/components/TurnContent.tsx +0 -548
- package/agent-pane/frontend/src/components/WorkspaceSidebar.test.tsx +0 -297
- package/agent-pane/frontend/src/components/WorkspaceSidebar.tsx +0 -351
- package/agent-pane/frontend/src/components/input/OptionSubPopup.tsx +0 -32
- package/agent-pane/frontend/src/components/input/SkillMentionPopup.test.tsx +0 -63
- package/agent-pane/frontend/src/components/input/SkillMentionPopup.tsx +0 -78
- package/agent-pane/frontend/src/components/input/SlashPopup.test.tsx +0 -96
- package/agent-pane/frontend/src/components/input/SlashPopup.tsx +0 -82
- package/agent-pane/frontend/src/components/panels/ChangesPanel.test.tsx +0 -61
- package/agent-pane/frontend/src/components/panels/ChangesPanel.tsx +0 -54
- package/agent-pane/frontend/src/components/panels/TasksPanel.test.tsx +0 -97
- package/agent-pane/frontend/src/components/panels/TasksPanel.tsx +0 -208
- package/agent-pane/frontend/src/components/panels/ThreadsPanel.tsx +0 -382
- package/agent-pane/frontend/src/components/panels/TurnsPanel.test.tsx +0 -83
- package/agent-pane/frontend/src/components/panels/TurnsPanel.tsx +0 -126
- package/agent-pane/frontend/src/constants/models.test.ts +0 -97
- package/agent-pane/frontend/src/constants/models.ts +0 -166
- package/agent-pane/frontend/src/hooks/useEscapeKey.test.ts +0 -42
- package/agent-pane/frontend/src/hooks/useEscapeKey.ts +0 -13
- package/agent-pane/frontend/src/hooks/useOutsideClick.test.ts +0 -92
- package/agent-pane/frontend/src/hooks/useOutsideClick.ts +0 -19
- package/agent-pane/frontend/src/hooks/useProvider.ts +0 -44
- package/agent-pane/frontend/src/hooks/useResizable.test.ts +0 -97
- package/agent-pane/frontend/src/hooks/useResizable.ts +0 -75
- package/agent-pane/frontend/src/hooks/useSessionStatus.test.ts +0 -116
- package/agent-pane/frontend/src/hooks/useSessionStatus.ts +0 -34
- package/agent-pane/frontend/src/main.test.tsx +0 -37
- package/agent-pane/frontend/src/main.tsx +0 -10
- package/agent-pane/frontend/src/store/sessionSlice.ts +0 -440
- package/agent-pane/frontend/src/store/store.test.ts +0 -1319
- package/agent-pane/frontend/src/store/store.ts +0 -37
- package/agent-pane/frontend/src/store/threadSlice.ts +0 -136
- package/agent-pane/frontend/src/store/uiSlice.ts +0 -133
- package/agent-pane/frontend/src/store/workspaceSlice.ts +0 -77
- package/agent-pane/frontend/src/store/wsSlice.ts +0 -361
- package/agent-pane/frontend/src/styles/app.css +0 -611
- package/agent-pane/frontend/src/styles/tokens.css +0 -62
- package/agent-pane/frontend/src/test/component-helpers.ts +0 -38
- package/agent-pane/frontend/src/test/fixtures.ts +0 -100
- package/agent-pane/frontend/src/test-setup.ts +0 -5
- package/agent-pane/frontend/src/types/index.test.ts +0 -128
- package/agent-pane/frontend/src/types/index.ts +0 -132
- package/agent-pane/frontend/src/utils/changes.test.ts +0 -81
- package/agent-pane/frontend/src/utils/changes.ts +0 -39
- package/agent-pane/frontend/src/utils/duration.test.ts +0 -75
- package/agent-pane/frontend/src/utils/duration.ts +0 -14
- package/agent-pane/frontend/tsconfig.json +0 -25
- package/agent-pane/frontend/vite.config.ts +0 -22
- package/agent-pane/frontend/vitest.config.ts +0 -29
- package/agent-pane/package-lock.json +0 -1527
- package/agent-pane/package.json +0 -19
- package/agent-pane/shared/provider-types.ts +0 -67
- package/agent-pane/shared/types.ts +0 -167
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
|
|
2
|
-
import { render, screen, fireEvent, cleanup } from '@testing-library/react';
|
|
3
|
-
import Toast from './Toast.tsx';
|
|
4
|
-
import { useStore } from '../store/store.ts';
|
|
5
|
-
import { resetStore } from '../test/component-helpers.ts';
|
|
6
|
-
|
|
7
|
-
describe('Toast', () => {
|
|
8
|
-
beforeEach(() => {
|
|
9
|
-
vi.useFakeTimers();
|
|
10
|
-
resetStore();
|
|
11
|
-
});
|
|
12
|
-
afterEach(() => {
|
|
13
|
-
cleanup();
|
|
14
|
-
vi.useRealTimers();
|
|
15
|
-
});
|
|
16
|
-
|
|
17
|
-
it('returns null when no toasts', () => {
|
|
18
|
-
const { container } = render(<Toast />);
|
|
19
|
-
expect(container.firstChild).toBeNull();
|
|
20
|
-
});
|
|
21
|
-
|
|
22
|
-
it('renders toast container with toast items', () => {
|
|
23
|
-
useStore.setState({ toasts: [{ id: 't1', type: 'info', message: 'Hello' }] });
|
|
24
|
-
render(<Toast />);
|
|
25
|
-
expect(screen.getByText('Hello')).toBeInTheDocument();
|
|
26
|
-
expect(screen.getByText('Hello').closest('.toast')).toHaveClass('toast-info');
|
|
27
|
-
});
|
|
28
|
-
|
|
29
|
-
it('auto-dismisses after 4000ms', () => {
|
|
30
|
-
useStore.setState({ toasts: [{ id: 't1', type: 'success', message: 'Auto dismiss' }] });
|
|
31
|
-
render(<Toast />);
|
|
32
|
-
expect(useStore.getState().toasts).toHaveLength(1);
|
|
33
|
-
vi.advanceTimersByTime(4000);
|
|
34
|
-
expect(useStore.getState().toasts).toHaveLength(0);
|
|
35
|
-
});
|
|
36
|
-
|
|
37
|
-
it('hover pauses auto-dismiss timer', () => {
|
|
38
|
-
useStore.setState({ toasts: [{ id: 't1', type: 'info', message: 'Hover test' }] });
|
|
39
|
-
render(<Toast />);
|
|
40
|
-
const toastEl = screen.getByText('Hover test').closest('.toast')!;
|
|
41
|
-
fireEvent.mouseEnter(toastEl);
|
|
42
|
-
vi.advanceTimersByTime(4000);
|
|
43
|
-
// Still present — timer was cleared
|
|
44
|
-
expect(useStore.getState().toasts).toHaveLength(1);
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
it('mouse leave restarts timer with 2000ms delay', () => {
|
|
48
|
-
useStore.setState({ toasts: [{ id: 't1', type: 'info', message: 'Mouse leave' }] });
|
|
49
|
-
render(<Toast />);
|
|
50
|
-
const toastEl = screen.getByText('Mouse leave').closest('.toast')!;
|
|
51
|
-
fireEvent.mouseEnter(toastEl);
|
|
52
|
-
fireEvent.mouseLeave(toastEl);
|
|
53
|
-
vi.advanceTimersByTime(1999);
|
|
54
|
-
expect(useStore.getState().toasts).toHaveLength(1);
|
|
55
|
-
vi.advanceTimersByTime(1);
|
|
56
|
-
expect(useStore.getState().toasts).toHaveLength(0);
|
|
57
|
-
});
|
|
58
|
-
|
|
59
|
-
it('undo button calls undoAction then removes toast', () => {
|
|
60
|
-
const undoFn = vi.fn();
|
|
61
|
-
useStore.setState({
|
|
62
|
-
toasts: [{ id: 't1', type: 'error', message: 'Deleted', undoAction: undoFn, undoLabel: 'Undo' }],
|
|
63
|
-
});
|
|
64
|
-
render(<Toast />);
|
|
65
|
-
const undoBtn = document.querySelector('.toast-undo') as HTMLElement;
|
|
66
|
-
fireEvent.click(undoBtn);
|
|
67
|
-
expect(undoFn).toHaveBeenCalled();
|
|
68
|
-
expect(useStore.getState().toasts).toHaveLength(0);
|
|
69
|
-
});
|
|
70
|
-
|
|
71
|
-
it('close button removes toast', () => {
|
|
72
|
-
useStore.setState({ toasts: [{ id: 't1', type: 'warn', message: 'Warning' }] });
|
|
73
|
-
render(<Toast />);
|
|
74
|
-
// The close button contains an X icon — find by the .toast-close class
|
|
75
|
-
const closeBtn = document.querySelector('.toast-close') as HTMLElement;
|
|
76
|
-
fireEvent.click(closeBtn);
|
|
77
|
-
expect(useStore.getState().toasts).toHaveLength(0);
|
|
78
|
-
});
|
|
79
|
-
});
|
|
@@ -1,76 +0,0 @@
|
|
|
1
|
-
import { useEffect, useRef } from 'react';
|
|
2
|
-
import { useStore } from '../store/store.ts';
|
|
3
|
-
import { X, CheckCircle, AlertCircle, Info, AlertTriangle, Undo2 } from 'lucide-react';
|
|
4
|
-
import type { Toast as ToastType } from '../store/store.ts';
|
|
5
|
-
|
|
6
|
-
const ICONS: Record<ToastType['type'], typeof CheckCircle> = {
|
|
7
|
-
success: CheckCircle,
|
|
8
|
-
error: AlertCircle,
|
|
9
|
-
info: Info,
|
|
10
|
-
warn: AlertTriangle,
|
|
11
|
-
};
|
|
12
|
-
|
|
13
|
-
const AUTO_DISMISS_MS = 4000;
|
|
14
|
-
|
|
15
|
-
function ToastItem({ toast }: { toast: ToastType }) {
|
|
16
|
-
const removeToast = useStore((s) => s.removeToast);
|
|
17
|
-
const Icon = ICONS[toast.type];
|
|
18
|
-
const timerRef = useRef<ReturnType<typeof setTimeout> | null>(null);
|
|
19
|
-
|
|
20
|
-
// Manage auto-dismiss with hover-to-pause
|
|
21
|
-
useEffect(() => {
|
|
22
|
-
function startTimer() {
|
|
23
|
-
timerRef.current = setTimeout(() => removeToast(toast.id), AUTO_DISMISS_MS);
|
|
24
|
-
}
|
|
25
|
-
startTimer();
|
|
26
|
-
return () => {
|
|
27
|
-
if (timerRef.current) clearTimeout(timerRef.current);
|
|
28
|
-
};
|
|
29
|
-
}, [toast.id, removeToast]);
|
|
30
|
-
|
|
31
|
-
function handleMouseEnter() {
|
|
32
|
-
if (timerRef.current) {
|
|
33
|
-
clearTimeout(timerRef.current);
|
|
34
|
-
timerRef.current = null;
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
function handleMouseLeave() {
|
|
39
|
-
timerRef.current = setTimeout(() => removeToast(toast.id), 2000);
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
return (
|
|
43
|
-
<div className={`toast toast-${toast.type}`} onMouseEnter={handleMouseEnter} onMouseLeave={handleMouseLeave}>
|
|
44
|
-
<Icon size={16} />
|
|
45
|
-
<span className="toast-message">{toast.message}</span>
|
|
46
|
-
{toast.undoAction && (
|
|
47
|
-
<button
|
|
48
|
-
className="toast-undo"
|
|
49
|
-
onClick={() => {
|
|
50
|
-
toast.undoAction?.();
|
|
51
|
-
removeToast(toast.id);
|
|
52
|
-
}}
|
|
53
|
-
>
|
|
54
|
-
<Undo2 size={12} /> {toast.undoLabel || 'Undo'}
|
|
55
|
-
</button>
|
|
56
|
-
)}
|
|
57
|
-
<button className="toast-close" onClick={() => removeToast(toast.id)}>
|
|
58
|
-
<X size={14} />
|
|
59
|
-
</button>
|
|
60
|
-
</div>
|
|
61
|
-
);
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
export default function Toast() {
|
|
65
|
-
const toasts = useStore((s) => s.toasts);
|
|
66
|
-
|
|
67
|
-
if (toasts.length === 0) return null;
|
|
68
|
-
|
|
69
|
-
return (
|
|
70
|
-
<div className="toast-container">
|
|
71
|
-
{toasts.map((toast) => (
|
|
72
|
-
<ToastItem key={toast.id} toast={toast} />
|
|
73
|
-
))}
|
|
74
|
-
</div>
|
|
75
|
-
);
|
|
76
|
-
}
|
|
@@ -1,298 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect, afterEach } from 'vitest';
|
|
2
|
-
import { render, screen, fireEvent, cleanup } from '@testing-library/react';
|
|
3
|
-
import TurnContent from './TurnContent.tsx';
|
|
4
|
-
import { makeTurn, makeItem } from '../test/fixtures.ts';
|
|
5
|
-
import type { Turn, Item } from '@agentpane/shared';
|
|
6
|
-
|
|
7
|
-
/** Helper: build a turn with items. */
|
|
8
|
-
function turnWithItems(items: Item[], overrides: Partial<Turn> = {}): Turn {
|
|
9
|
-
return makeTurn('t1', 's1', { items, ...overrides });
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
/** Non-tool items (reasoning, todo_list, error) are in otherItems — visible when intermediate expanded. */
|
|
13
|
-
function turnWithNonToolItem(item: Item): Turn {
|
|
14
|
-
return turnWithItems([item], { status: 'running' });
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
/** Tool items (command_execution, file_change, mcp_tool_call, web_search) go after agent_message — always visible. */
|
|
18
|
-
function turnWithToolItem(item: Item): Turn {
|
|
19
|
-
const agentMsg = makeItem('i-agent', 't1', 'agent_message');
|
|
20
|
-
agentMsg.data = { text: 'Done' };
|
|
21
|
-
return turnWithItems([agentMsg, item], { status: 'completed', agent_response: 'Done' });
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
describe('TurnContent', () => {
|
|
25
|
-
afterEach(() => {
|
|
26
|
-
cleanup();
|
|
27
|
-
});
|
|
28
|
-
|
|
29
|
-
it('renders user_prompt at top', () => {
|
|
30
|
-
const turn = turnWithItems([], { user_prompt: 'Fix the bug' });
|
|
31
|
-
render(<TurnContent turn={turn} />);
|
|
32
|
-
expect(screen.getByText('Fix the bug')).toBeInTheDocument();
|
|
33
|
-
});
|
|
34
|
-
|
|
35
|
-
it('renders agent_message item with markdown', () => {
|
|
36
|
-
const item = makeItem('i1', 't1', 'agent_message');
|
|
37
|
-
item.data = { text: 'Hello **world**' };
|
|
38
|
-
const turn = turnWithItems([item], { agent_response: 'Hello **world**' });
|
|
39
|
-
render(<TurnContent turn={turn} />);
|
|
40
|
-
expect(screen.getByText('world').tagName).toBe('STRONG');
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
it('renders Claude icon (CL / ic-claude) when runtimeType is "claude"', () => {
|
|
44
|
-
const item = makeItem('i1', 't1', 'agent_message');
|
|
45
|
-
item.data = { text: 'Hello' };
|
|
46
|
-
const turn = turnWithItems([item], { agent_response: 'Hello' });
|
|
47
|
-
render(<TurnContent turn={turn} runtimeType="claude" />);
|
|
48
|
-
const icon = document.querySelector('.ic-claude');
|
|
49
|
-
expect(icon).toBeTruthy();
|
|
50
|
-
expect(icon?.textContent).toBe('CL');
|
|
51
|
-
});
|
|
52
|
-
|
|
53
|
-
it('renders reasoning item with "Reasoning" header', () => {
|
|
54
|
-
const item = makeItem('i1', 't1', 'reasoning');
|
|
55
|
-
item.data = { text: 'Thinking about it' };
|
|
56
|
-
render(<TurnContent turn={turnWithNonToolItem(item)} />);
|
|
57
|
-
expect(screen.getByText('Reasoning')).toBeInTheDocument();
|
|
58
|
-
});
|
|
59
|
-
|
|
60
|
-
it('renders command_execution item with command in pre', () => {
|
|
61
|
-
const item = makeItem('i1', 't1', 'command_execution');
|
|
62
|
-
item.data = { command: '/bin/zsh -lc "echo hello"', aggregated_output: 'hello', exit_code: 0 };
|
|
63
|
-
render(<TurnContent turn={turnWithToolItem(item)} />);
|
|
64
|
-
expect(screen.getByText('Command')).toBeInTheDocument();
|
|
65
|
-
expect(screen.getByText('echo hello')).toBeInTheDocument();
|
|
66
|
-
expect(screen.getByText('exit 0')).toBeInTheDocument();
|
|
67
|
-
});
|
|
68
|
-
|
|
69
|
-
it('shows truncation toggle when output exceeds 10KB', () => {
|
|
70
|
-
const item = makeItem('i1', 't1', 'command_execution');
|
|
71
|
-
const longOutput = 'x'.repeat(11_000);
|
|
72
|
-
item.data = { command: 'ls', aggregated_output: longOutput, exit_code: 0 };
|
|
73
|
-
render(<TurnContent turn={turnWithToolItem(item)} />);
|
|
74
|
-
expect(screen.getByText(/Show full output/)).toBeInTheDocument();
|
|
75
|
-
});
|
|
76
|
-
|
|
77
|
-
it('renders file_change item with file list and A/D/M status', () => {
|
|
78
|
-
const item = makeItem('i1', 't1', 'file_change');
|
|
79
|
-
item.data = { changes: [{ path: 'src/new.ts', kind: 'add' }, { path: 'src/old.ts', kind: 'delete' }] };
|
|
80
|
-
render(<TurnContent turn={turnWithToolItem(item)} />);
|
|
81
|
-
expect(screen.getByText('src/new.ts')).toBeInTheDocument();
|
|
82
|
-
expect(screen.getByText('src/old.ts')).toBeInTheDocument();
|
|
83
|
-
expect(screen.getByText('A')).toBeInTheDocument();
|
|
84
|
-
expect(screen.getByText('D')).toBeInTheDocument();
|
|
85
|
-
});
|
|
86
|
-
|
|
87
|
-
it('renders mcp_tool_call item with tool name and server', () => {
|
|
88
|
-
const item = makeItem('i1', 't1', 'mcp_tool_call');
|
|
89
|
-
item.data = { tool: 'search', server: 'my-server', arguments: { query: 'test' } };
|
|
90
|
-
render(<TurnContent turn={turnWithToolItem(item)} />);
|
|
91
|
-
expect(screen.getByText(/search/)).toBeInTheDocument();
|
|
92
|
-
expect(screen.getByText('my-server')).toBeInTheDocument();
|
|
93
|
-
});
|
|
94
|
-
|
|
95
|
-
it('renders web_search item with query', () => {
|
|
96
|
-
const item = makeItem('i1', 't1', 'web_search');
|
|
97
|
-
item.data = { query: 'how to test react' };
|
|
98
|
-
render(<TurnContent turn={turnWithToolItem(item)} />);
|
|
99
|
-
expect(screen.getByText('Web Search')).toBeInTheDocument();
|
|
100
|
-
expect(screen.getByText('how to test react')).toBeInTheDocument();
|
|
101
|
-
});
|
|
102
|
-
|
|
103
|
-
it('renders todo_list item with completed and pending items', () => {
|
|
104
|
-
const item = makeItem('i1', 't1', 'todo_list');
|
|
105
|
-
item.data = { items: [{ text: 'Task 1', completed: true }, { text: 'Task 2', completed: false }] };
|
|
106
|
-
render(<TurnContent turn={turnWithNonToolItem(item)} />);
|
|
107
|
-
expect(screen.getByText(/Task 1/)).toBeInTheDocument();
|
|
108
|
-
expect(screen.getByText(/Task 2/)).toBeInTheDocument();
|
|
109
|
-
});
|
|
110
|
-
|
|
111
|
-
it('renders error item with error message', () => {
|
|
112
|
-
const item = makeItem('i1', 't1', 'error');
|
|
113
|
-
item.data = { message: 'Something broke' };
|
|
114
|
-
render(<TurnContent turn={turnWithNonToolItem(item)} />);
|
|
115
|
-
expect(screen.getByText('Error')).toBeInTheDocument();
|
|
116
|
-
expect(screen.getByText('Something broke')).toBeInTheDocument();
|
|
117
|
-
});
|
|
118
|
-
|
|
119
|
-
it('auto-expands intermediate steps when turn status is running', () => {
|
|
120
|
-
const cmd = makeItem('i1', 't1', 'command_execution');
|
|
121
|
-
cmd.data = { command: 'ls', aggregated_output: 'output', exit_code: 0 };
|
|
122
|
-
const agentMsg = makeItem('i2', 't1', 'agent_message');
|
|
123
|
-
agentMsg.data = { text: 'Done' };
|
|
124
|
-
// Command is intermediate (before final agent_message)
|
|
125
|
-
const turn = turnWithItems([cmd, agentMsg], { status: 'running', agent_response: 'Done' });
|
|
126
|
-
render(<TurnContent turn={turn} />);
|
|
127
|
-
// Auto-expanded — Level 2 nested tool-calls header (wrench icon) visible
|
|
128
|
-
expect(document.querySelectorAll('.lucide-wrench').length).toBe(1);
|
|
129
|
-
});
|
|
130
|
-
|
|
131
|
-
it('auto-collapses intermediate steps when turn status is completed', () => {
|
|
132
|
-
const cmd = makeItem('i1', 't1', 'command_execution');
|
|
133
|
-
cmd.data = { command: 'ls', aggregated_output: 'out', exit_code: 0 };
|
|
134
|
-
const agentMsg = makeItem('i2', 't1', 'agent_message');
|
|
135
|
-
agentMsg.data = { text: 'Done' };
|
|
136
|
-
const turn = turnWithItems([cmd, agentMsg], { status: 'completed', agent_response: 'Done' });
|
|
137
|
-
render(<TurnContent turn={turn} />);
|
|
138
|
-
// Collapsed — command header not visible
|
|
139
|
-
expect(screen.queryByText('Command')).not.toBeInTheDocument();
|
|
140
|
-
});
|
|
141
|
-
|
|
142
|
-
it('intermediate steps header click toggles expand', () => {
|
|
143
|
-
const cmd = makeItem('i1', 't1', 'command_execution');
|
|
144
|
-
cmd.data = { command: 'ls', aggregated_output: 'output', exit_code: 0 };
|
|
145
|
-
const agentMsg = makeItem('i2', 't1', 'agent_message');
|
|
146
|
-
agentMsg.data = { text: 'Done' };
|
|
147
|
-
const turn = turnWithItems([cmd, agentMsg], { status: 'completed', agent_response: 'Done' });
|
|
148
|
-
render(<TurnContent turn={turn} />);
|
|
149
|
-
// Initially collapsed — Level 2 nested header (wrench icon) not visible
|
|
150
|
-
expect(document.querySelectorAll('.lucide-wrench').length).toBe(0);
|
|
151
|
-
// Click Level 1 header to expand
|
|
152
|
-
const header = document.querySelector('.tool-calls-header')!;
|
|
153
|
-
fireEvent.click(header);
|
|
154
|
-
// Level 2 header now visible
|
|
155
|
-
expect(document.querySelectorAll('.lucide-wrench').length).toBe(1);
|
|
156
|
-
});
|
|
157
|
-
|
|
158
|
-
it('shows "Waiting to start…" for pending turn with no items', () => {
|
|
159
|
-
const turn = turnWithItems([], { status: 'pending' });
|
|
160
|
-
render(<TurnContent turn={turn} />);
|
|
161
|
-
expect(screen.getByText('Waiting to start…')).toBeInTheDocument();
|
|
162
|
-
});
|
|
163
|
-
|
|
164
|
-
it('shows "Agent is thinking…" for running turn with no items', () => {
|
|
165
|
-
const turn = turnWithItems([], { status: 'running' });
|
|
166
|
-
render(<TurnContent turn={turn} />);
|
|
167
|
-
expect(screen.getByText('Agent is thinking…')).toBeInTheDocument();
|
|
168
|
-
});
|
|
169
|
-
|
|
170
|
-
// --- command_execution edge cases ---
|
|
171
|
-
|
|
172
|
-
it('command_execution in_progress shows "running…" summary', () => {
|
|
173
|
-
const item = makeItem('i1', 't1', 'command_execution');
|
|
174
|
-
item.status = 'in_progress';
|
|
175
|
-
item.data = { command: 'ls', aggregated_output: 'partial', exit_code: null };
|
|
176
|
-
render(<TurnContent turn={turnWithToolItem(item)} />);
|
|
177
|
-
expect(screen.getByText('running…')).toBeInTheDocument();
|
|
178
|
-
});
|
|
179
|
-
|
|
180
|
-
it('command_execution with no output renders no output pre', () => {
|
|
181
|
-
const item = makeItem('i1', 't1', 'command_execution');
|
|
182
|
-
item.data = { command: 'ls', exit_code: 0 };
|
|
183
|
-
render(<TurnContent turn={turnWithToolItem(item)} />);
|
|
184
|
-
expect(screen.getByText('ls')).toBeInTheDocument();
|
|
185
|
-
expect(document.querySelector('.cmd-output')).not.toBeInTheDocument();
|
|
186
|
-
});
|
|
187
|
-
|
|
188
|
-
it('command_execution truncate toggle click expands and collapses', () => {
|
|
189
|
-
const item = makeItem('i1', 't1', 'command_execution');
|
|
190
|
-
item.data = { command: 'ls', aggregated_output: 'x'.repeat(11_000), exit_code: 0 };
|
|
191
|
-
render(<TurnContent turn={turnWithToolItem(item)} />);
|
|
192
|
-
const toggle = screen.getByText(/Show full output/);
|
|
193
|
-
fireEvent.click(toggle);
|
|
194
|
-
expect(screen.getByText('Show less')).toBeInTheDocument();
|
|
195
|
-
fireEvent.click(screen.getByText('Show less'));
|
|
196
|
-
expect(screen.getByText(/Show full output/)).toBeInTheDocument();
|
|
197
|
-
});
|
|
198
|
-
|
|
199
|
-
// --- file_change edge cases ---
|
|
200
|
-
|
|
201
|
-
it('file_change with single file shows singular "file"', () => {
|
|
202
|
-
const item = makeItem('i1', 't1', 'file_change');
|
|
203
|
-
item.data = { changes: [{ path: 'src/one.ts', kind: 'modify' }] };
|
|
204
|
-
render(<TurnContent turn={turnWithToolItem(item)} />);
|
|
205
|
-
expect(screen.getByText('1 file')).toBeInTheDocument();
|
|
206
|
-
expect(screen.getByText('M')).toBeInTheDocument();
|
|
207
|
-
});
|
|
208
|
-
|
|
209
|
-
it('file_change with modify kind shows M and fc-mod class', () => {
|
|
210
|
-
const item = makeItem('i1', 't1', 'file_change');
|
|
211
|
-
item.data = { changes: [{ path: 'src/mod.ts', kind: 'modify' }] };
|
|
212
|
-
render(<TurnContent turn={turnWithToolItem(item)} />);
|
|
213
|
-
const statusSpan = document.querySelector('.fc-status')!;
|
|
214
|
-
expect(statusSpan).toHaveClass('fc-mod');
|
|
215
|
-
expect(statusSpan.textContent).toBe('M');
|
|
216
|
-
});
|
|
217
|
-
|
|
218
|
-
// --- mcp_tool_call edge cases ---
|
|
219
|
-
|
|
220
|
-
it('mcp_tool_call failed status shows "failed" summary', () => {
|
|
221
|
-
const item = makeItem('i1', 't1', 'mcp_tool_call');
|
|
222
|
-
item.status = 'failed';
|
|
223
|
-
item.data = { tool: 'broken', server: 'srv' };
|
|
224
|
-
render(<TurnContent turn={turnWithToolItem(item)} />);
|
|
225
|
-
expect(screen.getByText('failed')).toBeInTheDocument();
|
|
226
|
-
});
|
|
227
|
-
|
|
228
|
-
it('mcp_tool_call with code arg renders in pre block', () => {
|
|
229
|
-
const item = makeItem('i1', 't1', 'mcp_tool_call');
|
|
230
|
-
item.data = { tool: 'exec', arguments: { code: 'console.log(1)' } };
|
|
231
|
-
render(<TurnContent turn={turnWithToolItem(item)} />);
|
|
232
|
-
expect(screen.getByText('console.log(1)')).toBeInTheDocument();
|
|
233
|
-
});
|
|
234
|
-
|
|
235
|
-
it('mcp_tool_call with non-string arg renders JSON', () => {
|
|
236
|
-
const item = makeItem('i1', 't1', 'mcp_tool_call');
|
|
237
|
-
item.data = { tool: 'exec', arguments: { count: 42 } };
|
|
238
|
-
render(<TurnContent turn={turnWithToolItem(item)} />);
|
|
239
|
-
expect(screen.getByText('42')).toBeInTheDocument();
|
|
240
|
-
});
|
|
241
|
-
|
|
242
|
-
it('mcp_tool_call with result text renders pre', () => {
|
|
243
|
-
const item = makeItem('i1', 't1', 'mcp_tool_call');
|
|
244
|
-
item.data = {
|
|
245
|
-
tool: 'query',
|
|
246
|
-
result: { content: [{ type: 'text', text: 'result here' }] },
|
|
247
|
-
};
|
|
248
|
-
render(<TurnContent turn={turnWithToolItem(item)} />);
|
|
249
|
-
expect(screen.getByText('result here')).toBeInTheDocument();
|
|
250
|
-
});
|
|
251
|
-
|
|
252
|
-
it('mcp_tool_call with error renders error in red pre', () => {
|
|
253
|
-
const item = makeItem('i1', 't1', 'mcp_tool_call');
|
|
254
|
-
item.data = { tool: 'fail', error: 'MCP failed' };
|
|
255
|
-
render(<TurnContent turn={turnWithToolItem(item)} />);
|
|
256
|
-
expect(screen.getByText('MCP failed')).toBeInTheDocument();
|
|
257
|
-
});
|
|
258
|
-
|
|
259
|
-
it('mcp_tool_call with no args and no server renders minimal', () => {
|
|
260
|
-
const item = makeItem('i1', 't1', 'mcp_tool_call');
|
|
261
|
-
item.data = { tool: 'noop' };
|
|
262
|
-
render(<TurnContent turn={turnWithToolItem(item)} />);
|
|
263
|
-
expect(screen.getByText(/noop/)).toBeInTheDocument();
|
|
264
|
-
expect(document.querySelector('.mcp-args')).not.toBeInTheDocument();
|
|
265
|
-
});
|
|
266
|
-
|
|
267
|
-
// --- turn-level edge cases ---
|
|
268
|
-
|
|
269
|
-
it('renders turn.error in error block', () => {
|
|
270
|
-
const turn = turnWithItems([], { status: 'failed', error: 'Turn failed' });
|
|
271
|
-
render(<TurnContent turn={turn} />);
|
|
272
|
-
expect(screen.getByText('Turn failed')).toBeInTheDocument();
|
|
273
|
-
});
|
|
274
|
-
|
|
275
|
-
it('renders items after final agent_message', () => {
|
|
276
|
-
const agentMsg = makeItem('i1', 't1', 'agent_message');
|
|
277
|
-
agentMsg.data = { text: 'Final answer' };
|
|
278
|
-
const errorItem = makeItem('i2', 't1', 'error');
|
|
279
|
-
errorItem.data = { message: 'Post-error' };
|
|
280
|
-
const turn = turnWithItems([agentMsg, errorItem], { status: 'completed', agent_response: 'Final answer' });
|
|
281
|
-
render(<TurnContent turn={turn} />);
|
|
282
|
-
expect(screen.getByText('Final answer')).toBeInTheDocument();
|
|
283
|
-
expect(screen.getByText('Post-error')).toBeInTheDocument();
|
|
284
|
-
});
|
|
285
|
-
|
|
286
|
-
it('unknown item type renders null (default case)', () => {
|
|
287
|
-
const item = makeItem('i1', 't1', 'unknown_type' as never);
|
|
288
|
-
item.data = {};
|
|
289
|
-
const agentMsg = makeItem('i2', 't1', 'agent_message');
|
|
290
|
-
agentMsg.data = { text: 'Done' };
|
|
291
|
-
const turn = turnWithItems([item, agentMsg], { status: 'completed', agent_response: 'Done' });
|
|
292
|
-
render(<TurnContent turn={turn} />);
|
|
293
|
-
// Agent message renders, unknown item produces no content card
|
|
294
|
-
expect(screen.getByText('Done')).toBeInTheDocument();
|
|
295
|
-
// The unknown item is intermediate — no card for it
|
|
296
|
-
expect(document.querySelectorAll('.render-content').length).toBeLessThan(3);
|
|
297
|
-
});
|
|
298
|
-
});
|