automagik-forge 0.1.13 → 0.1.14
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/README.md +143 -447
- package/dist/linux-x64/automagik-forge-mcp.zip +0 -0
- package/{npx-cli/automagik-forge-0.0.55.tgz → dist/linux-x64/automagik-forge.zip} +0 -0
- package/package.json +13 -23
- package/.cargo/config.toml +0 -13
- package/.claude/commands/commit.md +0 -376
- package/.claude/commands/prompt.md +0 -871
- package/.env.example +0 -20
- package/.github/actions/setup-node/action.yml +0 -29
- package/.github/images/automagik-logo.png +0 -0
- package/.github/workflows/pre-release.yml +0 -470
- package/.github/workflows/publish.yml +0 -145
- package/.github/workflows/test.yml +0 -63
- package/.mcp.json +0 -57
- package/AGENT.md +0 -40
- package/CLAUDE.md +0 -40
- package/CODE-OF-CONDUCT.md +0 -89
- package/Cargo.toml +0 -19
- package/Dockerfile +0 -43
- package/LICENSE +0 -201
- package/Makefile +0 -97
- package/backend/.sqlx/query-01b7e2bac1261d8be3d03c03df3e5220590da6c31c77f161074fc62752d63881.json +0 -12
- package/backend/.sqlx/query-03f2b02ba6dc5ea2b3cf6b1004caea0ad6bcc10ebd63f441d321a389f026e263.json +0 -12
- package/backend/.sqlx/query-0923b77d137a29fc54d399a873ff15fc4af894490bc65a4d344a7575cb0d8643.json +0 -12
- package/backend/.sqlx/query-0f808bcdb63c5f180836e448dd64c435c51758b2fc54a52ce9e67495b1ab200e.json +0 -68
- package/backend/.sqlx/query-1268afe9ca849daa6722e3df7ca8e9e61f0d37052e782bb5452ab8e1018d9b63.json +0 -12
- package/backend/.sqlx/query-1b082630a9622f8667ee7a9aba2c2d3176019a68c6bb83d33008594821415a57.json +0 -12
- package/backend/.sqlx/query-1c7b06ba1e112abf6b945a2ff08a0b40ec23f3738c2e7399f067b558cf8d490e.json +0 -12
- package/backend/.sqlx/query-1f619f01f46859a64ded531dd0ef61abacfe62e758abe7030a6aa745140b95ca.json +0 -104
- package/backend/.sqlx/query-1fca1ce14b4b20205364cd1f1f45ebe1d2e30cd745e59e189d56487b5639dfbb.json +0 -12
- package/backend/.sqlx/query-212828320e8d871ab9d83705a040b23bcf0393dc7252177fc539a74657f578ef.json +0 -32
- package/backend/.sqlx/query-290ce5c152be8d36e58ff42570f9157beb07ab9e77a03ec6fc30b4f56f9b8f6b.json +0 -56
- package/backend/.sqlx/query-2b471d2c2e8ffbe0cd42d2a91b814c0d79f9d09200f147e3cea33ba4ce673c8a.json +0 -68
- package/backend/.sqlx/query-354a48c705bb9bb2048c1b7f10fcb714e23f9db82b7a4ea6932486197b2ede6a.json +0 -92
- package/backend/.sqlx/query-36c9e3dd10648e94b949db5c91a774ecb1e10a899ef95da74066eccedca4d8b2.json +0 -12
- package/backend/.sqlx/query-36e4ba7bbd81b402d5a20b6005755eafbb174c8dda442081823406ac32809a94.json +0 -56
- package/backend/.sqlx/query-3a5b3c98a55ca183ab20c74708e3d7e579dda37972c059e7515c4ceee4bd8dd3.json +0 -62
- package/backend/.sqlx/query-3d0a1cabf2a52e9d90cdfd29c509ca89aeb448d0c1d2446c65cd43db40735e86.json +0 -62
- package/backend/.sqlx/query-3d6bd16fbce59efe30b7f67ea342e0e4ea6d1432389c02468ad79f1f742d4031.json +0 -56
- package/backend/.sqlx/query-4049ca413b285a05aca6b25385e9c8185575f01e9069e4e8581aa45d713f612f.json +0 -32
- package/backend/.sqlx/query-412bacd3477d86369082e90f52240407abce436cb81292d42b2dbe1e5c18eea1.json +0 -104
- package/backend/.sqlx/query-417a8b1ff4e51de82aea0159a3b97932224dc325b23476cb84153d690227fd8b.json +0 -62
- package/backend/.sqlx/query-461cc1b0bb6fd909afc9dd2246e8526b3771cfbb0b22ae4b5d17b51af587b9e2.json +0 -56
- package/backend/.sqlx/query-58408c7a8cdeeda0bef359f1f9bd91299a339dc2b191462fc58c9736a56d5227.json +0 -92
- package/backend/.sqlx/query-5a886026d75d515c01f347cc203c8d99dd04c61dc468e2e4c5aa548436d13834.json +0 -62
- package/backend/.sqlx/query-5b902137b11022d2e1a5c4f6a9c83fec1a856c6a710aff831abd2382ede76b43.json +0 -12
- package/backend/.sqlx/query-5ed1238e52e59bb5f76c0f153fd99a14093f7ce2585bf9843585608f17ec575b.json +0 -104
- package/backend/.sqlx/query-6e8b860b14decfc2227dc57213f38442943d3fbef5c8418fd6b634c6e0f5e2ea.json +0 -104
- package/backend/.sqlx/query-6ec414276994c4ccb2433eaa5b1b342168557d17ddf5a52dac84cb1b59b9de8f.json +0 -68
- package/backend/.sqlx/query-6ecfa16d0cf825aacf233544b5baf151e9adfdca26c226ad71020d291fd802d5.json +0 -62
- package/backend/.sqlx/query-72509d252c39fce77520aa816cb2acbc1fb35dc2605e7be893610599b2427f2e.json +0 -62
- package/backend/.sqlx/query-75239b2da188f749707d77f3c1544332ca70db3d6d6743b2601dc0d167536437.json +0 -62
- package/backend/.sqlx/query-83d10e29f8478aff33434f9ac67068e013b888b953a2657e2bb72a6f619d04f2.json +0 -50
- package/backend/.sqlx/query-8610803360ea18b9b9d078a6981ea56abfbfe84e6354fc1d5ae4c622e01410ed.json +0 -68
- package/backend/.sqlx/query-86d03eb70eef39c59296416867f2ee66c9f7cd8b7f961fbda2f89fc0a1c442c2.json +0 -12
- package/backend/.sqlx/query-87d0feb5a6b442bad9c60068ea7569599cc6fc91a0e2692ecb42e93b03201b9d.json +0 -68
- package/backend/.sqlx/query-8a67b3b3337248f06a57bdf8a908f7ef23177431eaed82dc08c94c3e5944340e.json +0 -12
- package/backend/.sqlx/query-8f01ebd64bdcde6a090479f14810d73ba23020e76fd70854ac57f2da251702c3.json +0 -12
- package/backend/.sqlx/query-90fd607fcb2dca72239ff25e618e21e174b195991eaa33722cbf5f76da84cfab.json +0 -62
- package/backend/.sqlx/query-92e8bdbcd80c5ff3db7a35cf79492048803ef305cbdef0d0a1fe5dc881ca8c71.json +0 -104
- package/backend/.sqlx/query-93a1605f90e9672dad29b472b6ad85fa9a55ea3ffa5abcb8724b09d61be254ca.json +0 -20
- package/backend/.sqlx/query-9472c8fb477958167f5fae40b85ac44252468c5226b2cdd7770f027332eed6d7.json +0 -104
- package/backend/.sqlx/query-96036c4f9e0f48bdc5a4a4588f0c5f288ac7aaa5425cac40fc33f337e1a351f2.json +0 -56
- package/backend/.sqlx/query-9edb2c01e91fd0f0fe7b56e988c7ae0393150f50be3f419a981e035c0121dfc7.json +0 -104
- package/backend/.sqlx/query-a157cf00616f703bfba21927f1eb1c9eec2a81c02da15f66efdba0b6c375de1b.json +0 -26
- package/backend/.sqlx/query-a31fff84f3b8e532fd1160447d89d700f06ae08821fee00c9a5b60492b05259c.json +0 -62
- package/backend/.sqlx/query-a5ba908419fb3e456bdd2daca41ba06cc3212ffffb8520fc7dbbcc8b60ada314.json +0 -12
- package/backend/.sqlx/query-a6d2961718dbc3b1a925e549f49a159c561bef58c105529275f274b27e2eba5b.json +0 -104
- package/backend/.sqlx/query-a9e93d5b09b29faf66e387e4d7596a792d81e75c4d3726e83c2963e8d7c9b56f.json +0 -104
- package/backend/.sqlx/query-ac5247c8d7fb86e4650c4b0eb9420031614c831b7b085083bac20c1af314c538.json +0 -12
- package/backend/.sqlx/query-afef9467be74c411c4cb119a8b2b1aea53049877dfc30cc60b486134ba4b4c9f.json +0 -68
- package/backend/.sqlx/query-b2b2c6b4d0b1a347b5c4cb63c3a46a265d4db53be9554989a814b069d0af82f2.json +0 -62
- package/backend/.sqlx/query-c50d2ff0b12e5bcc81e371089ee2d007e233e7db93aefba4fef08e7aa68f5ab7.json +0 -20
- package/backend/.sqlx/query-c614e6056b244ca07f1b9d44e7edc9d5819225c6f8d9e077070c6e518a17f50b.json +0 -12
- package/backend/.sqlx/query-c67259be8bf4ee0cfd32167b2aa3b7fe9192809181a8171bf1c2d6df731967ae.json +0 -12
- package/backend/.sqlx/query-d2d0a1b985ebbca6a2b3e882a221a219f3199890fa640afc946ef1a792d6d8de.json +0 -12
- package/backend/.sqlx/query-d30aa5786757f32bf2b9c5fe51a45e506c71c28c5994e430d9b0546adb15ffa2.json +0 -20
- package/backend/.sqlx/query-d3b9ea1de1576af71b312924ce7f4ea8ae5dbe2ac138ea3b4470f2d5cd734846.json +0 -12
- package/backend/.sqlx/query-ed8456646fa69ddd412441955f06ff22bfb790f29466450735e0b8bb1bc4ec94.json +0 -12
- package/backend/Cargo.toml +0 -71
- package/backend/build.rs +0 -32
- package/backend/migrations/20250617183714_init.sql +0 -44
- package/backend/migrations/20250620212427_execution_processes.sql +0 -25
- package/backend/migrations/20250620214100_remove_stdout_stderr_from_task_attempts.sql +0 -28
- package/backend/migrations/20250621120000_relate_activities_to_execution_processes.sql +0 -23
- package/backend/migrations/20250623120000_executor_sessions.sql +0 -17
- package/backend/migrations/20250623130000_add_executor_type_to_execution_processes.sql +0 -4
- package/backend/migrations/20250625000000_add_dev_script_to_projects.sql +0 -4
- package/backend/migrations/20250701000000_add_branch_to_task_attempts.sql +0 -2
- package/backend/migrations/20250701000001_add_pr_tracking_to_task_attempts.sql +0 -5
- package/backend/migrations/20250701120000_add_assistant_message_to_executor_sessions.sql +0 -2
- package/backend/migrations/20250708000000_add_base_branch_to_task_attempts.sql +0 -2
- package/backend/migrations/20250709000000_add_worktree_deleted_flag.sql +0 -2
- package/backend/migrations/20250710000000_add_setup_completion.sql +0 -3
- package/backend/migrations/20250715154859_add_task_templates.sql +0 -25
- package/backend/migrations/20250716143725_add_default_templates.sql +0 -174
- package/backend/migrations/20250716161432_update_executor_names_to_kebab_case.sql +0 -20
- package/backend/migrations/20250716170000_add_parent_task_to_tasks.sql +0 -7
- package/backend/migrations/20250717000000_drop_task_attempt_activities.sql +0 -9
- package/backend/migrations/20250719000000_add_cleanup_script_to_projects.sql +0 -2
- package/backend/migrations/20250720000000_add_cleanupscript_to_process_type_constraint.sql +0 -25
- package/backend/migrations/20250723000000_add_wish_to_tasks.sql +0 -7
- package/backend/migrations/20250724000000_remove_unique_wish_constraint.sql +0 -5
- package/backend/scripts/toast-notification.ps1 +0 -23
- package/backend/sounds/abstract-sound1.wav +0 -0
- package/backend/sounds/abstract-sound2.wav +0 -0
- package/backend/sounds/abstract-sound3.wav +0 -0
- package/backend/sounds/abstract-sound4.wav +0 -0
- package/backend/sounds/cow-mooing.wav +0 -0
- package/backend/sounds/phone-vibration.wav +0 -0
- package/backend/sounds/rooster.wav +0 -0
- package/backend/src/app_state.rs +0 -218
- package/backend/src/bin/generate_types.rs +0 -189
- package/backend/src/bin/mcp_task_server.rs +0 -191
- package/backend/src/execution_monitor.rs +0 -1193
- package/backend/src/executor.rs +0 -1053
- package/backend/src/executors/amp.rs +0 -697
- package/backend/src/executors/ccr.rs +0 -91
- package/backend/src/executors/charm_opencode.rs +0 -113
- package/backend/src/executors/claude.rs +0 -887
- package/backend/src/executors/cleanup_script.rs +0 -124
- package/backend/src/executors/dev_server.rs +0 -53
- package/backend/src/executors/echo.rs +0 -79
- package/backend/src/executors/gemini/config.rs +0 -67
- package/backend/src/executors/gemini/streaming.rs +0 -363
- package/backend/src/executors/gemini.rs +0 -765
- package/backend/src/executors/mod.rs +0 -23
- package/backend/src/executors/opencode_ai.rs +0 -113
- package/backend/src/executors/setup_script.rs +0 -130
- package/backend/src/executors/sst_opencode/filter.rs +0 -184
- package/backend/src/executors/sst_opencode/tools.rs +0 -139
- package/backend/src/executors/sst_opencode.rs +0 -756
- package/backend/src/lib.rs +0 -45
- package/backend/src/main.rs +0 -324
- package/backend/src/mcp/mod.rs +0 -1
- package/backend/src/mcp/task_server.rs +0 -850
- package/backend/src/middleware/mod.rs +0 -3
- package/backend/src/middleware/model_loaders.rs +0 -242
- package/backend/src/models/api_response.rs +0 -36
- package/backend/src/models/config.rs +0 -375
- package/backend/src/models/execution_process.rs +0 -430
- package/backend/src/models/executor_session.rs +0 -225
- package/backend/src/models/mod.rs +0 -12
- package/backend/src/models/project.rs +0 -356
- package/backend/src/models/task.rs +0 -345
- package/backend/src/models/task_attempt.rs +0 -1214
- package/backend/src/models/task_template.rs +0 -146
- package/backend/src/openapi.rs +0 -93
- package/backend/src/routes/auth.rs +0 -297
- package/backend/src/routes/config.rs +0 -385
- package/backend/src/routes/filesystem.rs +0 -228
- package/backend/src/routes/health.rs +0 -16
- package/backend/src/routes/mod.rs +0 -9
- package/backend/src/routes/projects.rs +0 -562
- package/backend/src/routes/stream.rs +0 -244
- package/backend/src/routes/task_attempts.rs +0 -1172
- package/backend/src/routes/task_templates.rs +0 -229
- package/backend/src/routes/tasks.rs +0 -353
- package/backend/src/services/analytics.rs +0 -216
- package/backend/src/services/git_service.rs +0 -1321
- package/backend/src/services/github_service.rs +0 -307
- package/backend/src/services/mod.rs +0 -13
- package/backend/src/services/notification_service.rs +0 -263
- package/backend/src/services/pr_monitor.rs +0 -214
- package/backend/src/services/process_service.rs +0 -940
- package/backend/src/utils/path.rs +0 -96
- package/backend/src/utils/shell.rs +0 -19
- package/backend/src/utils/text.rs +0 -24
- package/backend/src/utils/worktree_manager.rs +0 -578
- package/backend/src/utils.rs +0 -125
- package/backend/test.db +0 -0
- package/build-npm-package.sh +0 -61
- package/dev_assets_seed/config.json +0 -19
- package/frontend/.eslintrc.json +0 -25
- package/frontend/.prettierrc.json +0 -8
- package/frontend/components.json +0 -17
- package/frontend/index.html +0 -19
- package/frontend/package-lock.json +0 -7321
- package/frontend/package.json +0 -61
- package/frontend/postcss.config.js +0 -6
- package/frontend/public/android-chrome-192x192.png +0 -0
- package/frontend/public/android-chrome-512x512.png +0 -0
- package/frontend/public/apple-touch-icon.png +0 -0
- package/frontend/public/automagik-forge-logo-dark.svg +0 -3
- package/frontend/public/automagik-forge-logo.svg +0 -3
- package/frontend/public/automagik-forge-screenshot-overview.png +0 -0
- package/frontend/public/favicon-16x16.png +0 -0
- package/frontend/public/favicon-32x32.png +0 -0
- package/frontend/public/favicon.ico +0 -0
- package/frontend/public/site.webmanifest +0 -1
- package/frontend/public/viba-kanban-favicon.png +0 -0
- package/frontend/src/App.tsx +0 -157
- package/frontend/src/components/DisclaimerDialog.tsx +0 -106
- package/frontend/src/components/GitHubLoginDialog.tsx +0 -314
- package/frontend/src/components/OnboardingDialog.tsx +0 -185
- package/frontend/src/components/PrivacyOptInDialog.tsx +0 -130
- package/frontend/src/components/ProvidePatDialog.tsx +0 -98
- package/frontend/src/components/TaskTemplateManager.tsx +0 -336
- package/frontend/src/components/config-provider.tsx +0 -119
- package/frontend/src/components/context/TaskDetailsContextProvider.tsx +0 -470
- package/frontend/src/components/context/taskDetailsContext.ts +0 -125
- package/frontend/src/components/keyboard-shortcuts-demo.tsx +0 -35
- package/frontend/src/components/layout/navbar.tsx +0 -86
- package/frontend/src/components/logo.tsx +0 -44
- package/frontend/src/components/projects/ProjectCard.tsx +0 -155
- package/frontend/src/components/projects/project-detail.tsx +0 -251
- package/frontend/src/components/projects/project-form-fields.tsx +0 -238
- package/frontend/src/components/projects/project-form.tsx +0 -301
- package/frontend/src/components/projects/project-list.tsx +0 -200
- package/frontend/src/components/projects/projects-page.tsx +0 -20
- package/frontend/src/components/tasks/BranchSelector.tsx +0 -169
- package/frontend/src/components/tasks/DeleteFileConfirmationDialog.tsx +0 -94
- package/frontend/src/components/tasks/EditorSelectionDialog.tsx +0 -119
- package/frontend/src/components/tasks/TaskCard.tsx +0 -154
- package/frontend/src/components/tasks/TaskDetails/CollapsibleToolbar.tsx +0 -33
- package/frontend/src/components/tasks/TaskDetails/DiffCard.tsx +0 -109
- package/frontend/src/components/tasks/TaskDetails/DiffChunkSection.tsx +0 -135
- package/frontend/src/components/tasks/TaskDetails/DiffFile.tsx +0 -296
- package/frontend/src/components/tasks/TaskDetails/DiffTab.tsx +0 -32
- package/frontend/src/components/tasks/TaskDetails/DisplayConversationEntry.tsx +0 -392
- package/frontend/src/components/tasks/TaskDetails/LogsTab/Conversation.tsx +0 -256
- package/frontend/src/components/tasks/TaskDetails/LogsTab/ConversationEntry.tsx +0 -56
- package/frontend/src/components/tasks/TaskDetails/LogsTab/NormalizedConversationViewer.tsx +0 -92
- package/frontend/src/components/tasks/TaskDetails/LogsTab/Prompt.tsx +0 -22
- package/frontend/src/components/tasks/TaskDetails/LogsTab/SetupScriptRunning.tsx +0 -49
- package/frontend/src/components/tasks/TaskDetails/LogsTab.tsx +0 -186
- package/frontend/src/components/tasks/TaskDetails/ProcessesTab.tsx +0 -288
- package/frontend/src/components/tasks/TaskDetails/RelatedTasksTab.tsx +0 -216
- package/frontend/src/components/tasks/TaskDetails/TabNavigation.tsx +0 -93
- package/frontend/src/components/tasks/TaskDetailsHeader.tsx +0 -169
- package/frontend/src/components/tasks/TaskDetailsPanel.tsx +0 -126
- package/frontend/src/components/tasks/TaskDetailsToolbar.tsx +0 -302
- package/frontend/src/components/tasks/TaskFollowUpSection.tsx +0 -130
- package/frontend/src/components/tasks/TaskFormDialog.tsx +0 -400
- package/frontend/src/components/tasks/TaskKanbanBoard.tsx +0 -180
- package/frontend/src/components/tasks/Toolbar/CreateAttempt.tsx +0 -259
- package/frontend/src/components/tasks/Toolbar/CreatePRDialog.tsx +0 -243
- package/frontend/src/components/tasks/Toolbar/CurrentAttempt.tsx +0 -899
- package/frontend/src/components/tasks/index.ts +0 -2
- package/frontend/src/components/theme-provider.tsx +0 -82
- package/frontend/src/components/theme-toggle.tsx +0 -36
- package/frontend/src/components/ui/alert.tsx +0 -59
- package/frontend/src/components/ui/auto-expanding-textarea.tsx +0 -70
- package/frontend/src/components/ui/badge.tsx +0 -36
- package/frontend/src/components/ui/button.tsx +0 -56
- package/frontend/src/components/ui/card.tsx +0 -86
- package/frontend/src/components/ui/checkbox.tsx +0 -44
- package/frontend/src/components/ui/chip.tsx +0 -25
- package/frontend/src/components/ui/dialog.tsx +0 -124
- package/frontend/src/components/ui/dropdown-menu.tsx +0 -198
- package/frontend/src/components/ui/file-search-textarea.tsx +0 -292
- package/frontend/src/components/ui/folder-picker.tsx +0 -279
- package/frontend/src/components/ui/input.tsx +0 -25
- package/frontend/src/components/ui/label.tsx +0 -24
- package/frontend/src/components/ui/loader.tsx +0 -26
- package/frontend/src/components/ui/markdown-renderer.tsx +0 -75
- package/frontend/src/components/ui/select.tsx +0 -160
- package/frontend/src/components/ui/separator.tsx +0 -31
- package/frontend/src/components/ui/shadcn-io/kanban/index.tsx +0 -185
- package/frontend/src/components/ui/table.tsx +0 -117
- package/frontend/src/components/ui/tabs.tsx +0 -53
- package/frontend/src/components/ui/textarea.tsx +0 -22
- package/frontend/src/components/ui/tooltip.tsx +0 -28
- package/frontend/src/hooks/useNormalizedConversation.ts +0 -440
- package/frontend/src/index.css +0 -225
- package/frontend/src/lib/api.ts +0 -630
- package/frontend/src/lib/keyboard-shortcuts.ts +0 -266
- package/frontend/src/lib/responsive-config.ts +0 -70
- package/frontend/src/lib/types.ts +0 -39
- package/frontend/src/lib/utils.ts +0 -10
- package/frontend/src/main.tsx +0 -50
- package/frontend/src/pages/McpServers.tsx +0 -418
- package/frontend/src/pages/Settings.tsx +0 -610
- package/frontend/src/pages/project-tasks.tsx +0 -575
- package/frontend/src/pages/projects.tsx +0 -18
- package/frontend/src/vite-env.d.ts +0 -1
- package/frontend/tailwind.config.js +0 -125
- package/frontend/tsconfig.json +0 -26
- package/frontend/tsconfig.node.json +0 -10
- package/frontend/vite.config.ts +0 -33
- package/npx-cli/README.md +0 -159
- package/npx-cli/automagik-forge-0.1.0.tgz +0 -0
- package/npx-cli/automagik-forge-0.1.10.tgz +0 -0
- package/npx-cli/package.json +0 -17
- package/npx-cli/vibe-kanban-0.0.55.tgz +0 -0
- package/pnpm-workspace.yaml +0 -2
- package/rust-toolchain.toml +0 -11
- package/rustfmt.toml +0 -3
- package/scripts/load-env.js +0 -43
- package/scripts/mcp_test.js +0 -374
- package/scripts/prepare-db.js +0 -45
- package/scripts/setup-dev-environment.js +0 -274
- package/scripts/start-mcp-sse.js +0 -70
- package/scripts/test-debug.js +0 -32
- package/scripts/test-mcp-sse.js +0 -138
- package/scripts/test-simple.js +0 -44
- package/scripts/test-wish-final.js +0 -179
- package/scripts/test-wish-system.js +0 -221
- package/shared/types.ts +0 -182
- package/test-npm-package.sh +0 -42
- /package/{npx-cli/bin → bin}/cli.js +0 -0
@@ -1,392 +0,0 @@
|
|
1
|
-
import { useContext, useMemo, useState } from 'react';
|
2
|
-
import { DiffCard } from './DiffCard';
|
3
|
-
import MarkdownRenderer from '@/components/ui/markdown-renderer.tsx';
|
4
|
-
import {
|
5
|
-
AlertCircle,
|
6
|
-
Bot,
|
7
|
-
Brain,
|
8
|
-
CheckSquare,
|
9
|
-
ChevronRight,
|
10
|
-
ChevronUp,
|
11
|
-
Edit,
|
12
|
-
Eye,
|
13
|
-
Globe,
|
14
|
-
Plus,
|
15
|
-
Search,
|
16
|
-
Settings,
|
17
|
-
Terminal,
|
18
|
-
User,
|
19
|
-
} from 'lucide-react';
|
20
|
-
import {
|
21
|
-
NormalizedEntry,
|
22
|
-
type NormalizedEntryType,
|
23
|
-
type WorktreeDiff,
|
24
|
-
} from 'shared/types.ts';
|
25
|
-
import { TaskDiffContext } from '@/components/context/taskDetailsContext.ts';
|
26
|
-
|
27
|
-
type Props = {
|
28
|
-
entry: NormalizedEntry;
|
29
|
-
index: number;
|
30
|
-
diffDeletable?: boolean;
|
31
|
-
};
|
32
|
-
|
33
|
-
const getEntryIcon = (entryType: NormalizedEntryType) => {
|
34
|
-
if (entryType.type === 'user_message') {
|
35
|
-
return <User className="h-4 w-4 text-blue-600" />;
|
36
|
-
}
|
37
|
-
if (entryType.type === 'assistant_message') {
|
38
|
-
return <Bot className="h-4 w-4 text-green-600" />;
|
39
|
-
}
|
40
|
-
if (entryType.type === 'system_message') {
|
41
|
-
return <Settings className="h-4 w-4 text-gray-600" />;
|
42
|
-
}
|
43
|
-
if (entryType.type === 'thinking') {
|
44
|
-
return <Brain className="h-4 w-4 text-purple-600" />;
|
45
|
-
}
|
46
|
-
if (entryType.type === 'error_message') {
|
47
|
-
return <AlertCircle className="h-4 w-4 text-red-600" />;
|
48
|
-
}
|
49
|
-
if (entryType.type === 'tool_use') {
|
50
|
-
const { action_type, tool_name } = entryType;
|
51
|
-
|
52
|
-
// Special handling for TODO tools
|
53
|
-
if (
|
54
|
-
tool_name &&
|
55
|
-
(tool_name.toLowerCase() === 'todowrite' ||
|
56
|
-
tool_name.toLowerCase() === 'todoread' ||
|
57
|
-
tool_name.toLowerCase() === 'todo_write' ||
|
58
|
-
tool_name.toLowerCase() === 'todo_read')
|
59
|
-
) {
|
60
|
-
return <CheckSquare className="h-4 w-4 text-purple-600" />;
|
61
|
-
}
|
62
|
-
|
63
|
-
if (action_type.action === 'file_read') {
|
64
|
-
return <Eye className="h-4 w-4 text-orange-600" />;
|
65
|
-
}
|
66
|
-
if (action_type.action === 'file_write') {
|
67
|
-
return <Edit className="h-4 w-4 text-red-600" />;
|
68
|
-
}
|
69
|
-
if (action_type.action === 'command_run') {
|
70
|
-
return <Terminal className="h-4 w-4 text-yellow-600" />;
|
71
|
-
}
|
72
|
-
if (action_type.action === 'search') {
|
73
|
-
return <Search className="h-4 w-4 text-indigo-600" />;
|
74
|
-
}
|
75
|
-
if (action_type.action === 'web_fetch') {
|
76
|
-
return <Globe className="h-4 w-4 text-cyan-600" />;
|
77
|
-
}
|
78
|
-
if (action_type.action === 'task_create') {
|
79
|
-
return <Plus className="h-4 w-4 text-teal-600" />;
|
80
|
-
}
|
81
|
-
if (action_type.action === 'plan_presentation') {
|
82
|
-
return <CheckSquare className="h-4 w-4 text-blue-600" />;
|
83
|
-
}
|
84
|
-
return <Settings className="h-4 w-4 text-gray-600" />;
|
85
|
-
}
|
86
|
-
return <Settings className="h-4 w-4 text-gray-400" />;
|
87
|
-
};
|
88
|
-
|
89
|
-
const getContentClassName = (entryType: NormalizedEntryType) => {
|
90
|
-
const baseClasses = 'text-sm whitespace-pre-wrap break-words';
|
91
|
-
|
92
|
-
if (
|
93
|
-
entryType.type === 'tool_use' &&
|
94
|
-
entryType.action_type.action === 'command_run'
|
95
|
-
) {
|
96
|
-
return `${baseClasses} font-mono`;
|
97
|
-
}
|
98
|
-
|
99
|
-
if (entryType.type === 'error_message') {
|
100
|
-
return `${baseClasses} text-red-600 font-mono bg-red-50 dark:bg-red-950/20 px-2 py-1 rounded`;
|
101
|
-
}
|
102
|
-
|
103
|
-
// Special styling for TODO lists
|
104
|
-
if (
|
105
|
-
entryType.type === 'tool_use' &&
|
106
|
-
entryType.tool_name &&
|
107
|
-
(entryType.tool_name.toLowerCase() === 'todowrite' ||
|
108
|
-
entryType.tool_name.toLowerCase() === 'todoread' ||
|
109
|
-
entryType.tool_name.toLowerCase() === 'todo_write' ||
|
110
|
-
entryType.tool_name.toLowerCase() === 'todo_read')
|
111
|
-
) {
|
112
|
-
return `${baseClasses} font-mono text-purple-700 dark:text-purple-300 bg-purple-50 dark:bg-purple-950/20 px-2 py-1 rounded`;
|
113
|
-
}
|
114
|
-
|
115
|
-
// Special styling for plan presentations
|
116
|
-
if (
|
117
|
-
entryType.type === 'tool_use' &&
|
118
|
-
entryType.action_type.action === 'plan_presentation'
|
119
|
-
) {
|
120
|
-
return `${baseClasses} text-blue-700 dark:text-blue-300 bg-blue-50 dark:bg-blue-950/20 px-3 py-2 rounded-md border-l-4 border-blue-400`;
|
121
|
-
}
|
122
|
-
|
123
|
-
return baseClasses;
|
124
|
-
};
|
125
|
-
|
126
|
-
// Parse file path from content (handles various formats)
|
127
|
-
const parseFilePathFromContent = (content: string): string | null => {
|
128
|
-
// Try to extract path from backticks: `path/to/file.ext`
|
129
|
-
const backtickMatch = content.match(/`([^`]+)`/);
|
130
|
-
if (backtickMatch) {
|
131
|
-
return backtickMatch[1];
|
132
|
-
}
|
133
|
-
|
134
|
-
// Try to extract from common patterns like "Edit file: path" or "Write file: path"
|
135
|
-
const actionMatch = content.match(
|
136
|
-
/(?:Edit|Write|Create)\s+file:\s*([^\s\n]+)/i
|
137
|
-
);
|
138
|
-
if (actionMatch) {
|
139
|
-
return actionMatch[1];
|
140
|
-
}
|
141
|
-
|
142
|
-
return null;
|
143
|
-
};
|
144
|
-
|
145
|
-
// Helper function to determine if a tool call modifies files
|
146
|
-
const isFileModificationToolCall = (
|
147
|
-
entryType: NormalizedEntryType
|
148
|
-
): boolean => {
|
149
|
-
if (entryType.type !== 'tool_use') {
|
150
|
-
return false;
|
151
|
-
}
|
152
|
-
|
153
|
-
// Check for direct file write action
|
154
|
-
if (entryType.action_type.action === 'file_write') {
|
155
|
-
return true;
|
156
|
-
}
|
157
|
-
|
158
|
-
// Check for "other" actions that are file modification tools
|
159
|
-
if (entryType.action_type.action === 'other') {
|
160
|
-
const fileModificationTools = [
|
161
|
-
'edit',
|
162
|
-
'write',
|
163
|
-
'create_file',
|
164
|
-
'multiedit',
|
165
|
-
'edit_file',
|
166
|
-
];
|
167
|
-
return fileModificationTools.includes(
|
168
|
-
entryType.tool_name?.toLowerCase() || ''
|
169
|
-
);
|
170
|
-
}
|
171
|
-
|
172
|
-
return false;
|
173
|
-
};
|
174
|
-
|
175
|
-
// Extract file path from tool call
|
176
|
-
const extractFilePathFromToolCall = (entry: NormalizedEntry): string | null => {
|
177
|
-
if (entry.entry_type.type !== 'tool_use') {
|
178
|
-
return null;
|
179
|
-
}
|
180
|
-
|
181
|
-
const { action_type, tool_name } = entry.entry_type;
|
182
|
-
|
183
|
-
// Direct path extraction from action_type
|
184
|
-
if (action_type.action === 'file_write') {
|
185
|
-
return action_type.path || null;
|
186
|
-
}
|
187
|
-
|
188
|
-
// For "other" actions, check if it's a known file modification tool
|
189
|
-
if (action_type.action === 'other') {
|
190
|
-
const fileModificationTools = [
|
191
|
-
'edit',
|
192
|
-
'write',
|
193
|
-
'create_file',
|
194
|
-
'multiedit',
|
195
|
-
'edit_file',
|
196
|
-
];
|
197
|
-
|
198
|
-
if (fileModificationTools.includes(tool_name.toLowerCase())) {
|
199
|
-
// Parse file path from content field
|
200
|
-
return parseFilePathFromContent(entry.content);
|
201
|
-
}
|
202
|
-
}
|
203
|
-
|
204
|
-
return null;
|
205
|
-
};
|
206
|
-
|
207
|
-
// Create filtered diff showing only specific files
|
208
|
-
const createIncrementalDiff = (
|
209
|
-
fullDiff: WorktreeDiff | null,
|
210
|
-
targetFilePaths: string[]
|
211
|
-
): WorktreeDiff | null => {
|
212
|
-
if (!fullDiff || targetFilePaths.length === 0) {
|
213
|
-
return null;
|
214
|
-
}
|
215
|
-
|
216
|
-
// Filter files to only include the target file paths
|
217
|
-
const filteredFiles = fullDiff.files.filter((file) =>
|
218
|
-
targetFilePaths.some(
|
219
|
-
(targetPath) =>
|
220
|
-
file.path === targetPath ||
|
221
|
-
file.path.endsWith('/' + targetPath) ||
|
222
|
-
targetPath.endsWith('/' + file.path)
|
223
|
-
)
|
224
|
-
);
|
225
|
-
|
226
|
-
if (filteredFiles.length === 0) {
|
227
|
-
return null;
|
228
|
-
}
|
229
|
-
|
230
|
-
return {
|
231
|
-
...fullDiff,
|
232
|
-
files: filteredFiles,
|
233
|
-
};
|
234
|
-
};
|
235
|
-
|
236
|
-
// Helper function to determine if content should be rendered as markdown
|
237
|
-
const shouldRenderMarkdown = (entryType: NormalizedEntryType) => {
|
238
|
-
// Render markdown for assistant messages, plan presentations, and tool outputs that contain backticks
|
239
|
-
return (
|
240
|
-
entryType.type === 'assistant_message' ||
|
241
|
-
(entryType.type === 'tool_use' &&
|
242
|
-
entryType.action_type.action === 'plan_presentation') ||
|
243
|
-
(entryType.type === 'tool_use' &&
|
244
|
-
entryType.tool_name &&
|
245
|
-
(entryType.tool_name.toLowerCase() === 'todowrite' ||
|
246
|
-
entryType.tool_name.toLowerCase() === 'todoread' ||
|
247
|
-
entryType.tool_name.toLowerCase() === 'todo_write' ||
|
248
|
-
entryType.tool_name.toLowerCase() === 'todo_read' ||
|
249
|
-
entryType.tool_name.toLowerCase() === 'glob' ||
|
250
|
-
entryType.tool_name.toLowerCase() === 'ls' ||
|
251
|
-
entryType.tool_name.toLowerCase() === 'list_directory' ||
|
252
|
-
entryType.tool_name.toLowerCase() === 'read' ||
|
253
|
-
entryType.tool_name.toLowerCase() === 'read_file' ||
|
254
|
-
entryType.tool_name.toLowerCase() === 'write' ||
|
255
|
-
entryType.tool_name.toLowerCase() === 'create_file' ||
|
256
|
-
entryType.tool_name.toLowerCase() === 'edit' ||
|
257
|
-
entryType.tool_name.toLowerCase() === 'edit_file' ||
|
258
|
-
entryType.tool_name.toLowerCase() === 'multiedit' ||
|
259
|
-
entryType.tool_name.toLowerCase() === 'bash' ||
|
260
|
-
entryType.tool_name.toLowerCase() === 'run_command' ||
|
261
|
-
entryType.tool_name.toLowerCase() === 'grep' ||
|
262
|
-
entryType.tool_name.toLowerCase() === 'search' ||
|
263
|
-
entryType.tool_name.toLowerCase() === 'webfetch' ||
|
264
|
-
entryType.tool_name.toLowerCase() === 'web_fetch' ||
|
265
|
-
entryType.tool_name.toLowerCase() === 'task'))
|
266
|
-
);
|
267
|
-
};
|
268
|
-
|
269
|
-
function DisplayConversationEntry({ entry, index, diffDeletable }: Props) {
|
270
|
-
const { diff } = useContext(TaskDiffContext);
|
271
|
-
const [expandedErrors, setExpandedErrors] = useState<Set<number>>(new Set());
|
272
|
-
|
273
|
-
const toggleErrorExpansion = (index: number) => {
|
274
|
-
setExpandedErrors((prev) => {
|
275
|
-
const newSet = new Set(prev);
|
276
|
-
if (newSet.has(index)) {
|
277
|
-
newSet.delete(index);
|
278
|
-
} else {
|
279
|
-
newSet.add(index);
|
280
|
-
}
|
281
|
-
return newSet;
|
282
|
-
});
|
283
|
-
};
|
284
|
-
|
285
|
-
const isErrorMessage = entry.entry_type.type === 'error_message';
|
286
|
-
const isExpanded = expandedErrors.has(index);
|
287
|
-
const hasMultipleLines = isErrorMessage && entry.content.includes('\n');
|
288
|
-
const isFileModification = useMemo(
|
289
|
-
() => isFileModificationToolCall(entry.entry_type),
|
290
|
-
[entry.entry_type]
|
291
|
-
);
|
292
|
-
|
293
|
-
// Extract file path from this specific tool call
|
294
|
-
const modifiedFilePath = useMemo(
|
295
|
-
() => (isFileModification ? extractFilePathFromToolCall(entry) : null),
|
296
|
-
[isFileModification, entry]
|
297
|
-
);
|
298
|
-
|
299
|
-
// Create incremental diff showing only the files modified by this specific tool call
|
300
|
-
const incrementalDiff = useMemo(
|
301
|
-
() =>
|
302
|
-
modifiedFilePath && diff
|
303
|
-
? createIncrementalDiff(diff, [modifiedFilePath])
|
304
|
-
: null,
|
305
|
-
[modifiedFilePath, diff]
|
306
|
-
);
|
307
|
-
|
308
|
-
// Show incremental diff for this specific file modification
|
309
|
-
const shouldShowDiff =
|
310
|
-
isFileModification && incrementalDiff && incrementalDiff.files.length > 0;
|
311
|
-
|
312
|
-
return (
|
313
|
-
<div key={index}>
|
314
|
-
<div className="flex items-start gap-3">
|
315
|
-
<div className="flex-shrink-0 mt-1">
|
316
|
-
{isErrorMessage && hasMultipleLines ? (
|
317
|
-
<button
|
318
|
-
onClick={() => toggleErrorExpansion(index)}
|
319
|
-
className="transition-colors hover:opacity-70"
|
320
|
-
>
|
321
|
-
{getEntryIcon(entry.entry_type)}
|
322
|
-
</button>
|
323
|
-
) : (
|
324
|
-
getEntryIcon(entry.entry_type)
|
325
|
-
)}
|
326
|
-
</div>
|
327
|
-
<div className="flex-1 min-w-0">
|
328
|
-
{isErrorMessage && hasMultipleLines ? (
|
329
|
-
<div className={isExpanded ? 'space-y-2' : ''}>
|
330
|
-
<div className={getContentClassName(entry.entry_type)}>
|
331
|
-
{isExpanded ? (
|
332
|
-
shouldRenderMarkdown(entry.entry_type) ? (
|
333
|
-
<MarkdownRenderer
|
334
|
-
content={entry.content}
|
335
|
-
className="whitespace-pre-wrap break-words"
|
336
|
-
/>
|
337
|
-
) : (
|
338
|
-
entry.content
|
339
|
-
)
|
340
|
-
) : (
|
341
|
-
<>
|
342
|
-
{entry.content.split('\n')[0]}
|
343
|
-
<button
|
344
|
-
onClick={() => toggleErrorExpansion(index)}
|
345
|
-
className="ml-2 inline-flex items-center gap-1 text-xs text-red-600 hover:text-red-700 dark:text-red-400 dark:hover:text-red-300 transition-colors"
|
346
|
-
>
|
347
|
-
<ChevronRight className="h-3 w-3" />
|
348
|
-
Show more
|
349
|
-
</button>
|
350
|
-
</>
|
351
|
-
)}
|
352
|
-
</div>
|
353
|
-
{isExpanded && (
|
354
|
-
<button
|
355
|
-
onClick={() => toggleErrorExpansion(index)}
|
356
|
-
className="flex items-center gap-1 text-xs text-red-600 hover:text-red-700 dark:text-red-400 dark:hover:text-red-300 transition-colors"
|
357
|
-
>
|
358
|
-
<ChevronUp className="h-3 w-3" />
|
359
|
-
Show less
|
360
|
-
</button>
|
361
|
-
)}
|
362
|
-
</div>
|
363
|
-
) : (
|
364
|
-
<div className={getContentClassName(entry.entry_type)}>
|
365
|
-
{shouldRenderMarkdown(entry.entry_type) ? (
|
366
|
-
<MarkdownRenderer
|
367
|
-
content={entry.content}
|
368
|
-
className="whitespace-pre-wrap break-words"
|
369
|
-
/>
|
370
|
-
) : (
|
371
|
-
entry.content
|
372
|
-
)}
|
373
|
-
</div>
|
374
|
-
)}
|
375
|
-
</div>
|
376
|
-
</div>
|
377
|
-
|
378
|
-
{/* Render incremental diff card inline after file modification entries */}
|
379
|
-
{shouldShowDiff && incrementalDiff && (
|
380
|
-
<div className="mt-4 mb-2">
|
381
|
-
<DiffCard
|
382
|
-
diff={incrementalDiff}
|
383
|
-
deletable={diffDeletable}
|
384
|
-
compact={true}
|
385
|
-
/>
|
386
|
-
</div>
|
387
|
-
)}
|
388
|
-
</div>
|
389
|
-
);
|
390
|
-
}
|
391
|
-
|
392
|
-
export default DisplayConversationEntry;
|
@@ -1,256 +0,0 @@
|
|
1
|
-
import { NormalizedConversationViewer } from '@/components/tasks/TaskDetails/LogsTab/NormalizedConversationViewer.tsx';
|
2
|
-
import {
|
3
|
-
useCallback,
|
4
|
-
useContext,
|
5
|
-
useEffect,
|
6
|
-
useMemo,
|
7
|
-
useRef,
|
8
|
-
useState,
|
9
|
-
} from 'react';
|
10
|
-
import { TaskAttemptDataContext } from '@/components/context/taskDetailsContext.ts';
|
11
|
-
import { Loader } from '@/components/ui/loader.tsx';
|
12
|
-
import { Button } from '@/components/ui/button';
|
13
|
-
import Prompt from './Prompt';
|
14
|
-
import ConversationEntry from './ConversationEntry';
|
15
|
-
import { ConversationEntryDisplayType } from '@/lib/types';
|
16
|
-
|
17
|
-
function Conversation() {
|
18
|
-
const { attemptData } = useContext(TaskAttemptDataContext);
|
19
|
-
const [shouldAutoScrollLogs, setShouldAutoScrollLogs] = useState(true);
|
20
|
-
const [conversationUpdateTrigger, setConversationUpdateTrigger] = useState(0);
|
21
|
-
const [visibleCount, setVisibleCount] = useState(100);
|
22
|
-
const [visibleRunningEntriesCount, setVisibleRunningEntriesCount] =
|
23
|
-
useState(0);
|
24
|
-
|
25
|
-
const scrollContainerRef = useRef<HTMLDivElement>(null);
|
26
|
-
|
27
|
-
// Callback to trigger auto-scroll when conversation updates
|
28
|
-
const handleConversationUpdate = useCallback(() => {
|
29
|
-
setConversationUpdateTrigger((prev) => prev + 1);
|
30
|
-
}, []);
|
31
|
-
|
32
|
-
useEffect(() => {
|
33
|
-
if (shouldAutoScrollLogs && scrollContainerRef.current) {
|
34
|
-
scrollContainerRef.current.scrollTop =
|
35
|
-
scrollContainerRef.current.scrollHeight;
|
36
|
-
}
|
37
|
-
}, [attemptData.allLogs, conversationUpdateTrigger, shouldAutoScrollLogs]);
|
38
|
-
|
39
|
-
const handleLogsScroll = useCallback(() => {
|
40
|
-
if (scrollContainerRef.current) {
|
41
|
-
const { scrollTop, scrollHeight, clientHeight } =
|
42
|
-
scrollContainerRef.current;
|
43
|
-
const isAtBottom = scrollTop + clientHeight >= scrollHeight - 5;
|
44
|
-
|
45
|
-
if (isAtBottom && !shouldAutoScrollLogs) {
|
46
|
-
setShouldAutoScrollLogs(true);
|
47
|
-
} else if (!isAtBottom && shouldAutoScrollLogs) {
|
48
|
-
setShouldAutoScrollLogs(false);
|
49
|
-
}
|
50
|
-
}
|
51
|
-
}, [shouldAutoScrollLogs]);
|
52
|
-
|
53
|
-
// Find main and follow-up processes from allLogs
|
54
|
-
const mainCodingAgentLog = useMemo(
|
55
|
-
() =>
|
56
|
-
attemptData.allLogs.find(
|
57
|
-
(log) =>
|
58
|
-
log.process_type.toLowerCase() === 'codingagent' &&
|
59
|
-
log.command === 'executor'
|
60
|
-
),
|
61
|
-
[attemptData.allLogs]
|
62
|
-
);
|
63
|
-
const followUpLogs = useMemo(
|
64
|
-
() =>
|
65
|
-
attemptData.allLogs.filter(
|
66
|
-
(log) =>
|
67
|
-
log.process_type.toLowerCase() === 'codingagent' &&
|
68
|
-
log.command === 'followup_executor'
|
69
|
-
),
|
70
|
-
[attemptData.allLogs]
|
71
|
-
);
|
72
|
-
|
73
|
-
// Combine all logs in order (main first, then follow-ups)
|
74
|
-
const allProcessLogs = useMemo(
|
75
|
-
() =>
|
76
|
-
[mainCodingAgentLog, ...followUpLogs].filter(Boolean) as Array<
|
77
|
-
NonNullable<typeof mainCodingAgentLog>
|
78
|
-
>,
|
79
|
-
[mainCodingAgentLog, followUpLogs]
|
80
|
-
);
|
81
|
-
|
82
|
-
// Flatten all entries, keeping process info for each entry
|
83
|
-
const allEntries = useMemo(() => {
|
84
|
-
const entries: Array<ConversationEntryDisplayType> = [];
|
85
|
-
allProcessLogs.forEach((log, processIndex) => {
|
86
|
-
if (!log) return;
|
87
|
-
if (log.status === 'running') return; // Skip static entries for running processes
|
88
|
-
const processId = String(log.id); // Ensure string
|
89
|
-
const processPrompt = log.normalized_conversation.prompt || undefined; // Ensure undefined, not null
|
90
|
-
const entriesArr = log.normalized_conversation.entries || [];
|
91
|
-
entriesArr.forEach((entry, entryIndex) => {
|
92
|
-
entries.push({
|
93
|
-
entry,
|
94
|
-
processId,
|
95
|
-
processPrompt,
|
96
|
-
processStatus: log.status,
|
97
|
-
processIsRunning: false, // Only completed processes here
|
98
|
-
process: log,
|
99
|
-
isFirstInProcess: entryIndex === 0,
|
100
|
-
processIndex,
|
101
|
-
entryIndex,
|
102
|
-
});
|
103
|
-
});
|
104
|
-
});
|
105
|
-
// Sort by timestamp (entries without timestamp go last)
|
106
|
-
entries.sort((a, b) => {
|
107
|
-
if (a.entry.timestamp && b.entry.timestamp) {
|
108
|
-
return a.entry.timestamp.localeCompare(b.entry.timestamp);
|
109
|
-
}
|
110
|
-
if (a.entry.timestamp) return -1;
|
111
|
-
if (b.entry.timestamp) return 1;
|
112
|
-
return 0;
|
113
|
-
});
|
114
|
-
return entries;
|
115
|
-
}, [allProcessLogs]);
|
116
|
-
|
117
|
-
// Identify running processes (main + follow-ups)
|
118
|
-
const runningProcessLogs = useMemo(
|
119
|
-
() => allProcessLogs.filter((log) => log.status === 'running'),
|
120
|
-
[allProcessLogs]
|
121
|
-
);
|
122
|
-
|
123
|
-
// Paginate: show only the last visibleCount entries
|
124
|
-
const visibleEntries = useMemo(
|
125
|
-
() => allEntries.slice(-(visibleCount - visibleRunningEntriesCount)),
|
126
|
-
[allEntries, visibleCount, visibleRunningEntriesCount]
|
127
|
-
);
|
128
|
-
|
129
|
-
const renderedVisibleEntries = useMemo(
|
130
|
-
() =>
|
131
|
-
visibleEntries.map((entry, index) => (
|
132
|
-
<ConversationEntry
|
133
|
-
key={entry.entry.timestamp || index}
|
134
|
-
idx={index}
|
135
|
-
item={entry}
|
136
|
-
handleConversationUpdate={handleConversationUpdate}
|
137
|
-
visibleEntriesLength={visibleEntries.length}
|
138
|
-
runningProcessDetails={attemptData.runningProcessDetails}
|
139
|
-
/>
|
140
|
-
)),
|
141
|
-
[
|
142
|
-
visibleEntries,
|
143
|
-
handleConversationUpdate,
|
144
|
-
attemptData.runningProcessDetails,
|
145
|
-
]
|
146
|
-
);
|
147
|
-
|
148
|
-
const renderedRunningProcessLogs = useMemo(() => {
|
149
|
-
return runningProcessLogs.map((log, i) => {
|
150
|
-
const runningProcess = attemptData.runningProcessDetails[String(log.id)];
|
151
|
-
if (!runningProcess) return null;
|
152
|
-
// Show prompt only if this is the first entry in the process (i.e., no completed entries for this process)
|
153
|
-
const showPrompt =
|
154
|
-
log.normalized_conversation.prompt &&
|
155
|
-
!allEntries.some((e) => e.processId === String(log.id));
|
156
|
-
return (
|
157
|
-
<div key={String(log.id)} className={i > 0 ? 'mt-8' : ''}>
|
158
|
-
{showPrompt && (
|
159
|
-
<Prompt prompt={log.normalized_conversation.prompt || ''} />
|
160
|
-
)}
|
161
|
-
<NormalizedConversationViewer
|
162
|
-
executionProcess={runningProcess}
|
163
|
-
onConversationUpdate={handleConversationUpdate}
|
164
|
-
diffDeletable
|
165
|
-
visibleEntriesNum={visibleCount}
|
166
|
-
onDisplayEntriesChange={setVisibleRunningEntriesCount}
|
167
|
-
/>
|
168
|
-
</div>
|
169
|
-
);
|
170
|
-
});
|
171
|
-
}, [
|
172
|
-
runningProcessLogs,
|
173
|
-
attemptData.runningProcessDetails,
|
174
|
-
handleConversationUpdate,
|
175
|
-
allEntries,
|
176
|
-
visibleCount,
|
177
|
-
]);
|
178
|
-
|
179
|
-
// Check if we should show the status banner - only if the most recent process failed/stopped
|
180
|
-
const getMostRecentProcess = () => {
|
181
|
-
if (followUpLogs.length > 0) {
|
182
|
-
// Sort by creation time or use last in array as most recent
|
183
|
-
return followUpLogs[followUpLogs.length - 1];
|
184
|
-
}
|
185
|
-
return mainCodingAgentLog;
|
186
|
-
};
|
187
|
-
|
188
|
-
const mostRecentProcess = getMostRecentProcess();
|
189
|
-
const showStatusBanner =
|
190
|
-
mostRecentProcess &&
|
191
|
-
(mostRecentProcess.status === 'failed' ||
|
192
|
-
mostRecentProcess.status === 'killed');
|
193
|
-
|
194
|
-
return (
|
195
|
-
<div
|
196
|
-
ref={scrollContainerRef}
|
197
|
-
onScroll={handleLogsScroll}
|
198
|
-
className="h-full overflow-y-auto"
|
199
|
-
>
|
200
|
-
{visibleCount - visibleRunningEntriesCount < allEntries.length && (
|
201
|
-
<div className="flex justify-center mb-4">
|
202
|
-
<Button
|
203
|
-
variant="outline"
|
204
|
-
className="w-full"
|
205
|
-
onClick={() => setVisibleCount((c) => c + 100)}
|
206
|
-
>
|
207
|
-
Load previous logs
|
208
|
-
</Button>
|
209
|
-
</div>
|
210
|
-
)}
|
211
|
-
{visibleEntries.length > 0 && (
|
212
|
-
<div className="space-y-2">{renderedVisibleEntries}</div>
|
213
|
-
)}
|
214
|
-
{/* Render live viewers for running processes (after paginated list) */}
|
215
|
-
{renderedRunningProcessLogs}
|
216
|
-
{/* If nothing to show at all, show loader */}
|
217
|
-
{visibleEntries.length === 0 && runningProcessLogs.length === 0 && (
|
218
|
-
<Loader
|
219
|
-
message={
|
220
|
-
<>
|
221
|
-
Coding Agent Starting
|
222
|
-
<br />
|
223
|
-
Initializing conversation...
|
224
|
-
</>
|
225
|
-
}
|
226
|
-
size={48}
|
227
|
-
className="py-8"
|
228
|
-
/>
|
229
|
-
)}
|
230
|
-
|
231
|
-
{/* Status banner for failed/stopped states - shown at bottom */}
|
232
|
-
{showStatusBanner && mostRecentProcess && (
|
233
|
-
<div className="mt-4 p-4 rounded-lg border">
|
234
|
-
<p
|
235
|
-
className={`text-lg font-semibold mb-2 ${
|
236
|
-
mostRecentProcess.status === 'failed'
|
237
|
-
? 'text-destructive'
|
238
|
-
: 'text-orange-600'
|
239
|
-
}`}
|
240
|
-
>
|
241
|
-
{mostRecentProcess.status === 'failed'
|
242
|
-
? 'Coding Agent Failed'
|
243
|
-
: 'Coding Agent Stopped'}
|
244
|
-
</p>
|
245
|
-
<p className="text-muted-foreground">
|
246
|
-
{mostRecentProcess.status === 'failed'
|
247
|
-
? 'The coding agent encountered an error.'
|
248
|
-
: 'The coding agent was stopped.'}
|
249
|
-
</p>
|
250
|
-
</div>
|
251
|
-
)}
|
252
|
-
</div>
|
253
|
-
);
|
254
|
-
}
|
255
|
-
|
256
|
-
export default Conversation;
|
@@ -1,56 +0,0 @@
|
|
1
|
-
import { ConversationEntryDisplayType } from '@/lib/types';
|
2
|
-
import DisplayConversationEntry from '../DisplayConversationEntry';
|
3
|
-
import { NormalizedConversationViewer } from './NormalizedConversationViewer';
|
4
|
-
import Prompt from './Prompt';
|
5
|
-
import { Loader } from '@/components/ui/loader.tsx';
|
6
|
-
import { ExecutionProcess } from 'shared/types';
|
7
|
-
|
8
|
-
type Props = {
|
9
|
-
item: ConversationEntryDisplayType;
|
10
|
-
idx: number;
|
11
|
-
handleConversationUpdate: () => void;
|
12
|
-
visibleEntriesLength: number;
|
13
|
-
runningProcessDetails: Record<string, ExecutionProcess>;
|
14
|
-
};
|
15
|
-
|
16
|
-
const ConversationEntry = ({
|
17
|
-
item,
|
18
|
-
idx,
|
19
|
-
handleConversationUpdate,
|
20
|
-
visibleEntriesLength,
|
21
|
-
runningProcessDetails,
|
22
|
-
}: Props) => {
|
23
|
-
const showPrompt = item.isFirstInProcess && item.processPrompt;
|
24
|
-
// For running processes, render the live viewer below the static entries
|
25
|
-
if (item.processIsRunning && idx === visibleEntriesLength - 1) {
|
26
|
-
// Only render the live viewer for the last entry of a running process
|
27
|
-
const runningProcess = runningProcessDetails[item.processId];
|
28
|
-
if (runningProcess) {
|
29
|
-
return (
|
30
|
-
<div key={item.entry.timestamp || idx}>
|
31
|
-
{showPrompt && <Prompt prompt={item.processPrompt || ''} />}
|
32
|
-
<NormalizedConversationViewer
|
33
|
-
executionProcess={runningProcess}
|
34
|
-
onConversationUpdate={handleConversationUpdate}
|
35
|
-
diffDeletable
|
36
|
-
/>
|
37
|
-
</div>
|
38
|
-
);
|
39
|
-
}
|
40
|
-
// Fallback: show loading if not found
|
41
|
-
return <Loader message="Loading live logs..." size={24} className="py-4" />;
|
42
|
-
} else {
|
43
|
-
return (
|
44
|
-
<div key={item.entry.timestamp || idx}>
|
45
|
-
{showPrompt && <Prompt prompt={item.processPrompt || ''} />}
|
46
|
-
<DisplayConversationEntry
|
47
|
-
entry={item.entry}
|
48
|
-
index={idx}
|
49
|
-
diffDeletable
|
50
|
-
/>
|
51
|
-
</div>
|
52
|
-
);
|
53
|
-
}
|
54
|
-
};
|
55
|
-
|
56
|
-
export default ConversationEntry;
|