manigent-server 0.1.0__py3-none-any.whl
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.
- manigent/_catalog/mcps/chess/README.md +38 -0
- manigent/_catalog/mcps/chess/mcp.json +9 -0
- manigent/_catalog/mcps/registry.json +9 -0
- manigent/_catalog/skills/brief/SKILL.md +339 -0
- manigent/_catalog/skills/broaden-options/SKILL.md +133 -0
- manigent/_catalog/skills/calendar/SKILL.md +44 -0
- manigent/_catalog/skills/calendar/starter_config.jsonc +25 -0
- manigent/_catalog/skills/gmail/SKILL.md +73 -0
- manigent/_catalog/skills/google-calendar/SKILL.md +44 -0
- manigent/_catalog/skills/google-drive/SKILL.md +42 -0
- manigent/_catalog/skills/google-drive-write/SKILL.md +45 -0
- manigent/_catalog/skills/google-drive-write/starter_config.jsonc +45 -0
- manigent/_catalog/skills/grill-me/SKILL.md +173 -0
- manigent/_catalog/skills/homekit/SKILL.md +37 -0
- manigent/_catalog/skills/http-api/SKILL.md +117 -0
- manigent/_catalog/skills/ib/SKILL.md +89 -0
- manigent/_catalog/skills/ib/starter_config.jsonc +35 -0
- manigent/_catalog/skills/mailbox/SKILL.md +47 -0
- manigent/_catalog/skills/mailbox/starter_config.jsonc +38 -0
- manigent/_catalog/skills/media/SKILL.md +93 -0
- manigent/_catalog/skills/media/starter_config.jsonc +63 -0
- manigent/_catalog/skills/osxphotos/SKILL.md +41 -0
- manigent/_catalog/skills/photo-story/SKILL.md +285 -0
- manigent/_catalog/skills/playwright-browser/SKILL.md +291 -0
- manigent/_catalog/skills/playwright-browser/starter_config.jsonc +44 -0
- manigent/_catalog/skills/playwright-save-skill/SKILL.md +149 -0
- manigent/_catalog/skills/registry.json +166 -0
- manigent/_catalog/skills/web-artifacts/SKILL.md +194 -0
- manigent/api/action_executor.py +404 -0
- manigent/api/action_validator.py +531 -0
- manigent/api/actions.py +221 -0
- manigent/api/client.py +558 -0
- manigent/api/control.py +806 -0
- manigent/api/edge_protocol.py +123 -0
- manigent/api/fs_protocol.py +450 -0
- manigent/api/host_protocol.py +298 -0
- manigent/api/managed_job_client.py +124 -0
- manigent/api/responses.py +342 -0
- manigent/api/retry_transport.py +178 -0
- manigent/api/turn_protocol.py +78 -0
- manigent/cli_lifecycle.py +467 -0
- manigent/cli_server.py +978 -0
- manigent/doctor.py +1167 -0
- manigent/hub_protocol/canonical.py +375 -0
- manigent/hub_protocol/codes.py +171 -0
- manigent/hub_protocol/constants.py +71 -0
- manigent/hub_protocol/envelope.py +218 -0
- manigent/hub_protocol/frames.py +788 -0
- manigent/hub_protocol/http.py +260 -0
- manigent/hub_protocol/ids.py +170 -0
- manigent/hub_protocol/keys.py +195 -0
- manigent/hub_protocol/text.py +75 -0
- manigent/llm/base.py +1072 -0
- manigent/llm/prompt_builder.py +2450 -0
- manigent/llm/triggers.py +68 -0
- manigent/models/agent.py +2905 -0
- manigent/models/agent_bundle.py +298 -0
- manigent/models/brief_tab.py +311 -0
- manigent/models/chat_message.py +231 -0
- manigent/models/chatroom.py +1108 -0
- manigent/models/context.py +1159 -0
- manigent/models/desk_label.py +836 -0
- manigent/models/desk_read_state.py +220 -0
- manigent/models/desk_sign_off.py +267 -0
- manigent/models/desk_sop.py +965 -0
- manigent/models/desk_todo.py +1603 -0
- manigent/models/desk_todo_link.py +404 -0
- manigent/models/file_cache.py +75 -0
- manigent/models/host.py +732 -0
- manigent/models/install_token.py +401 -0
- manigent/models/invitation_code.py +162 -0
- manigent/models/knowledge_pack.py +552 -0
- manigent/models/managed_job.py +295 -0
- manigent/models/model_config.py +564 -0
- manigent/models/model_defaults.py +238 -0
- manigent/models/onboarding_plan.py +161 -0
- manigent/models/participant.py +449 -0
- manigent/models/persistable.py +892 -0
- manigent/models/plan_markdown.py +1774 -0
- manigent/models/project.py +1343 -0
- manigent/models/project_plan.py +8104 -0
- manigent/models/project_report.py +145 -0
- manigent/models/provenance.py +261 -0
- manigent/models/provider_agents.py +101 -0
- manigent/models/public_request.py +108 -0
- manigent/models/reflection_schedule.py +191 -0
- manigent/models/scheduled_message.py +285 -0
- manigent/models/share_token.py +190 -0
- manigent/models/skill_version.py +31 -0
- manigent/models/sop_template.py +187 -0
- manigent/models/thinking_partner_plan.py +187 -0
- manigent/models/tunnel_binding.py +129 -0
- manigent/models/user.py +1276 -0
- manigent/models/work_tracker.py +510 -0
- manigent/runner/invocation_registry.py +187 -0
- manigent/server/agent_capabilities.py +119 -0
- manigent/server/agent_visibility.py +119 -0
- manigent/server/announcements.py +119 -0
- manigent/server/app.py +807 -0
- manigent/server/auth.py +355 -0
- manigent/server/batch_timeout.py +94 -0
- manigent/server/channels/access.py +194 -0
- manigent/server/channels/adapter.py +295 -0
- manigent/server/channels/config.py +693 -0
- manigent/server/channels/contacts.py +39 -0
- manigent/server/channels/email_adapter.py +436 -0
- manigent/server/channels/email_address.py +145 -0
- manigent/server/channels/email_form.py +242 -0
- manigent/server/channels/email_format.py +285 -0
- manigent/server/channels/email_mail.py +427 -0
- manigent/server/channels/email_mailgun.py +164 -0
- manigent/server/channels/email_text.py +280 -0
- manigent/server/channels/file_links.py +127 -0
- manigent/server/channels/gateway.py +2998 -0
- manigent/server/channels/hub_delivery.py +211 -0
- manigent/server/channels/hub_store.py +1730 -0
- manigent/server/channels/line.py +645 -0
- manigent/server/channels/line_format.py +589 -0
- manigent/server/channels/log_redaction.py +145 -0
- manigent/server/channels/store.py +3316 -0
- manigent/server/channels/telegram.py +422 -0
- manigent/server/channels/telegram_format.py +312 -0
- manigent/server/channels/webchat.py +261 -0
- manigent/server/channels/webchat_widget.js +1310 -0
- manigent/server/channels/whatsapp.py +707 -0
- manigent/server/channels/whatsapp_format.py +511 -0
- manigent/server/chat_search_index.py +1203 -0
- manigent/server/config.py +61 -0
- manigent/server/context.py +121 -0
- manigent/server/coordinator_rule.py +115 -0
- manigent/server/desk_todo_notify.py +300 -0
- manigent/server/edge_hub.py +577 -0
- manigent/server/email.py +354 -0
- manigent/server/errors.py +83 -0
- manigent/server/home_fs_relay.py +392 -0
- manigent/server/hub/adapter.py +1395 -0
- manigent/server/hub/agent_send_guard.py +196 -0
- manigent/server/hub/avatar.py +342 -0
- manigent/server/hub/browser.py +778 -0
- manigent/server/hub/client.py +859 -0
- manigent/server/hub/demand.py +49 -0
- manigent/server/hub/directory.py +385 -0
- manigent/server/hub/enroll.py +400 -0
- manigent/server/hub/http.py +134 -0
- manigent/server/hub/identity.py +61 -0
- manigent/server/hub/keys.py +588 -0
- manigent/server/hub/mirror.py +802 -0
- manigent/server/hub/operator.py +817 -0
- manigent/server/hub/retain.py +361 -0
- manigent/server/hub/room_bridge.py +741 -0
- manigent/server/hub/runtime.py +691 -0
- manigent/server/hub/trust.py +182 -0
- manigent/server/hub/views.py +316 -0
- manigent/server/idempotency.py +205 -0
- manigent/server/in_flight_restore.py +181 -0
- manigent/server/inspection.py +816 -0
- manigent/server/isolation_gate.py +516 -0
- manigent/server/isolation_notice.py +310 -0
- manigent/server/managed_job_events.py +242 -0
- manigent/server/mcp_registry.py +118 -0
- manigent/server/message_forward.py +78 -0
- manigent/server/message_scheduler.py +176 -0
- manigent/server/notification_assets.py +164 -0
- manigent/server/oauth_login/cli_state.py +120 -0
- manigent/server/oauth_login/config.py +90 -0
- manigent/server/oauth_login/errors.py +78 -0
- manigent/server/oauth_login/flow.py +223 -0
- manigent/server/oauth_login/handoff.py +63 -0
- manigent/server/oauth_login/providers.py +45 -0
- manigent/server/oauth_state.py +81 -0
- manigent/server/owner_isolation.py +466 -0
- manigent/server/participant_liveness.py +82 -0
- manigent/server/public_profile.py +149 -0
- manigent/server/public_requests/candidates.py +116 -0
- manigent/server/public_requests/dispatch.py +121 -0
- manigent/server/public_requests/ranking.py +153 -0
- manigent/server/recent_activity.py +250 -0
- manigent/server/reflection_completion_subscriber.py +151 -0
- manigent/server/reflection_scheduler.py +239 -0
- manigent/server/requester_key_migration.py +261 -0
- manigent/server/room_flow.py +139 -0
- manigent/server/routes/_batch.py +218 -0
- manigent/server/routes/_fd_routing.py +155 -0
- manigent/server/routes/_mentions.py +70 -0
- manigent/server/routes/agent_env.py +188 -0
- manigent/server/routes/agent_fs.py +450 -0
- manigent/server/routes/agents.py +1206 -0
- manigent/server/routes/announcements.py +79 -0
- manigent/server/routes/auth.py +387 -0
- manigent/server/routes/brief_tabs.py +404 -0
- manigent/server/routes/changelog.py +237 -0
- manigent/server/routes/channels.py +993 -0
- manigent/server/routes/chatrooms.py +871 -0
- manigent/server/routes/desk_labels.py +298 -0
- manigent/server/routes/desk_latest_messages.py +116 -0
- manigent/server/routes/desk_read_state.py +110 -0
- manigent/server/routes/desk_sign_off.py +88 -0
- manigent/server/routes/desk_sops.py +216 -0
- manigent/server/routes/desk_todos.py +692 -0
- manigent/server/routes/desk_tour.py +44 -0
- manigent/server/routes/files.py +572 -0
- manigent/server/routes/hosts.py +484 -0
- manigent/server/routes/hub.py +534 -0
- manigent/server/routes/hub_channels.py +234 -0
- manigent/server/routes/inbox.py +581 -0
- manigent/server/routes/install.ps1 +436 -0
- manigent/server/routes/install.py +324 -0
- manigent/server/routes/install.sh +566 -0
- manigent/server/routes/isolation_check.py +145 -0
- manigent/server/routes/knowledge_packs.py +477 -0
- manigent/server/routes/managed_jobs.py +196 -0
- manigent/server/routes/mcps.py +271 -0
- manigent/server/routes/messages.py +1972 -0
- manigent/server/routes/model_defaults.py +279 -0
- manigent/server/routes/oauth.py +237 -0
- manigent/server/routes/oauth_login.py +351 -0
- manigent/server/routes/owner_isolation.py +91 -0
- manigent/server/routes/project_plans.py +1521 -0
- manigent/server/routes/project_reports.py +235 -0
- manigent/server/routes/projects.py +2047 -0
- manigent/server/routes/public_agents.py +151 -0
- manigent/server/routes/public_requests.py +181 -0
- manigent/server/routes/reflection.py +93 -0
- manigent/server/routes/scheduled_messages.py +263 -0
- manigent/server/routes/search.py +94 -0
- manigent/server/routes/sharing.py +156 -0
- manigent/server/routes/skills.py +406 -0
- manigent/server/routes/templates.py +219 -0
- manigent/server/routes/turn_tokens.py +119 -0
- manigent/server/routes/webchat.py +406 -0
- manigent/server/routes/websocket.py +431 -0
- manigent/server/serving_only.py +200 -0
- manigent/server/signup_policy.py +120 -0
- manigent/server/skill_registry.py +164 -0
- manigent/server/socket_events.py +858 -0
- manigent/server/timeout_checker.py +446 -0
- manigent/server/tunnel_subscriber.py +1000 -0
- manigent/server/turn_tokens.py +285 -0
- manigent/server/ws_hub.py +556 -0
- manigent/server_cli.py +31 -0
- manigent/sync/changelog.py +885 -0
- manigent/sync/console_subscriber.py +222 -0
- manigent/sync/runloop.py +619 -0
- manigent/sync/runloop_manager.py +197 -0
- manigent/sync/subscriber.py +98 -0
- manigent/utils/agent_processes.py +276 -0
- manigent/utils/agent_storage.py +125 -0
- manigent/utils/email.py +563 -0
- manigent/utils/env_store.py +174 -0
- manigent/utils/extra_dirs.py +85 -0
- manigent/utils/file_io.py +485 -0
- manigent/utils/invoke_timeout.py +87 -0
- manigent/utils/jsonc.py +78 -0
- manigent/utils/knowledge_index.py +148 -0
- manigent/utils/nofollow_fs.py +279 -0
- manigent/utils/notification_center.py +67 -0
- manigent/utils/version.py +57 -0
- manigent/web/frontend/.design-sync-entry.tsx +74 -0
- manigent/web/frontend/.design-sync-provider.tsx +46 -0
- manigent/web/frontend/.eslintrc.cjs +183 -0
- manigent/web/frontend/.gitignore +6 -0
- manigent/web/frontend/app/page.tsx +39 -0
- manigent/web/frontend/hub-terms.html +192 -0
- manigent/web/frontend/index.html +15 -0
- manigent/web/frontend/landing.html +15 -0
- manigent/web/frontend/package-lock.json +8028 -0
- manigent/web/frontend/package.json +55 -0
- manigent/web/frontend/postcss.config.js +6 -0
- manigent/web/frontend/privacy.html +217 -0
- manigent/web/frontend/private-beta-announcement.html +19 -0
- manigent/web/frontend/public/apple-touch-icon.png +0 -0
- manigent/web/frontend/public/brand-hero-banner.png +0 -0
- manigent/web/frontend/public/brand-hero.png +0 -0
- manigent/web/frontend/public/favicon.png +0 -0
- manigent/web/frontend/public/favicon.svg +8 -0
- manigent/web/frontend/public/icon-transparent-sm.png +0 -0
- manigent/web/frontend/public/icon.png +0 -0
- manigent/web/frontend/public/manigent-mark.svg +7 -0
- manigent/web/frontend/public/vite.svg +5 -0
- manigent/web/frontend/public.html +15 -0
- manigent/web/frontend/src/App.activeAccountRedirect.test.tsx +236 -0
- manigent/web/frontend/src/App.hubHostDm.test.tsx +119 -0
- manigent/web/frontend/src/App.hubHostProject.test.tsx +142 -0
- manigent/web/frontend/src/App.hubRoutes.test.tsx +187 -0
- manigent/web/frontend/src/App.oauthAddCallback.test.tsx +263 -0
- manigent/web/frontend/src/App.tsx +246 -0
- manigent/web/frontend/src/api/attachments.ts +32 -0
- manigent/web/frontend/src/api/batchLoader.test.ts +212 -0
- manigent/web/frontend/src/api/batchLoader.ts +124 -0
- manigent/web/frontend/src/api/chatroomsBatch.test.tsx +392 -0
- manigent/web/frontend/src/api/client.ts +321 -0
- manigent/web/frontend/src/api/crossAccountAuth.test.ts +388 -0
- manigent/web/frontend/src/api/endpoints/agentEnv.ts +24 -0
- manigent/web/frontend/src/api/endpoints/agentFs.ts +125 -0
- manigent/web/frontend/src/api/endpoints/agentSearch.ts +19 -0
- manigent/web/frontend/src/api/endpoints/agents.ts +66 -0
- manigent/web/frontend/src/api/endpoints/announcements.ts +26 -0
- manigent/web/frontend/src/api/endpoints/auth.ts +361 -0
- manigent/web/frontend/src/api/endpoints/authLogin.test.ts +236 -0
- manigent/web/frontend/src/api/endpoints/batch.ts +64 -0
- manigent/web/frontend/src/api/endpoints/briefTabs.ts +81 -0
- manigent/web/frontend/src/api/endpoints/channels.ts +285 -0
- manigent/web/frontend/src/api/endpoints/computers.ts +212 -0
- manigent/web/frontend/src/api/endpoints/deskLabels.ts +151 -0
- manigent/web/frontend/src/api/endpoints/deskLatestMessages.ts +23 -0
- manigent/web/frontend/src/api/endpoints/deskReadState.ts +41 -0
- manigent/web/frontend/src/api/endpoints/deskSignOffs.ts +74 -0
- manigent/web/frontend/src/api/endpoints/deskSops.ts +53 -0
- manigent/web/frontend/src/api/endpoints/deskTodoAttachments.ts +69 -0
- manigent/web/frontend/src/api/endpoints/deskTodoProjects.test.ts +99 -0
- manigent/web/frontend/src/api/endpoints/deskTodoProjects.ts +114 -0
- manigent/web/frontend/src/api/endpoints/deskTodos.ts +164 -0
- manigent/web/frontend/src/api/endpoints/deskTour.ts +16 -0
- manigent/web/frontend/src/api/endpoints/dm.ts +137 -0
- manigent/web/frontend/src/api/endpoints/files.ts +55 -0
- manigent/web/frontend/src/api/endpoints/hub.contract.test.ts +94 -0
- manigent/web/frontend/src/api/endpoints/hub.keys.ts +260 -0
- manigent/web/frontend/src/api/endpoints/hub.test.ts +203 -0
- manigent/web/frontend/src/api/endpoints/hub.ts +654 -0
- manigent/web/frontend/src/api/endpoints/index.ts +15 -0
- manigent/web/frontend/src/api/endpoints/install.ts +74 -0
- manigent/web/frontend/src/api/endpoints/isolationCheck.ts +36 -0
- manigent/web/frontend/src/api/endpoints/knowledgePacks.ts +179 -0
- manigent/web/frontend/src/api/endpoints/mcps.ts +36 -0
- manigent/web/frontend/src/api/endpoints/messages.held.test.ts +43 -0
- manigent/web/frontend/src/api/endpoints/messages.ts +95 -0
- manigent/web/frontend/src/api/endpoints/modelConfigs.ts +232 -0
- manigent/web/frontend/src/api/endpoints/oauthApi.test.ts +110 -0
- manigent/web/frontend/src/api/endpoints/projectPlans.ts +608 -0
- manigent/web/frontend/src/api/endpoints/projectReports.ts +36 -0
- manigent/web/frontend/src/api/endpoints/projects.ts +124 -0
- manigent/web/frontend/src/api/endpoints/publicRequests.ts +75 -0
- manigent/web/frontend/src/api/endpoints/reflection.ts +32 -0
- manigent/web/frontend/src/api/endpoints/roomFlow.ts +14 -0
- manigent/web/frontend/src/api/endpoints/scheduledMessages.ts +60 -0
- manigent/web/frontend/src/api/endpoints/search.ts +27 -0
- manigent/web/frontend/src/api/endpoints/sharing.ts +42 -0
- manigent/web/frontend/src/api/endpoints/skills.ts +67 -0
- manigent/web/frontend/src/api/endpoints/templates.ts +72 -0
- manigent/web/frontend/src/api/loaders.ts +22 -0
- manigent/web/frontend/src/api/singleIssuer.test.ts +148 -0
- manigent/web/frontend/src/api/transientRetry.test.ts +176 -0
- manigent/web/frontend/src/api/transientRetry.ts +140 -0
- manigent/web/frontend/src/api/websocket.resync.test.ts +111 -0
- manigent/web/frontend/src/api/websocket.ts +335 -0
- manigent/web/frontend/src/components/agent/AgentNameLink.tsx +24 -0
- manigent/web/frontend/src/components/agent/AgentViewActions.test.tsx +41 -0
- manigent/web/frontend/src/components/agent/AgentViewActions.tsx +89 -0
- manigent/web/frontend/src/components/agent/CreateAgentPage.tsx +535 -0
- manigent/web/frontend/src/components/agent/JsonConfigEditor.tsx +33 -0
- manigent/web/frontend/src/components/agent/KnowledgePackList.tsx +103 -0
- manigent/web/frontend/src/components/agent/McpCatalog.tsx +261 -0
- manigent/web/frontend/src/components/agent/McpConfigModal.tsx +224 -0
- manigent/web/frontend/src/components/agent/PreConsentModal.tsx +172 -0
- manigent/web/frontend/src/components/agent/SkillCatalog.tsx +364 -0
- manigent/web/frontend/src/components/agent/SkillConfigModal.tsx +221 -0
- manigent/web/frontend/src/components/auth/AddAccountPage.test.tsx +181 -0
- manigent/web/frontend/src/components/auth/AddAccountPage.tsx +201 -0
- manigent/web/frontend/src/components/auth/AuthShell.tsx +462 -0
- manigent/web/frontend/src/components/auth/LoginPage.test.tsx +384 -0
- manigent/web/frontend/src/components/auth/LoginPage.tsx +129 -0
- manigent/web/frontend/src/components/auth/OAuthCallbackPage.test.tsx +185 -0
- manigent/web/frontend/src/components/auth/OAuthCallbackPage.tsx +154 -0
- manigent/web/frontend/src/components/auth/OAuthLinkedBanner.tsx +44 -0
- manigent/web/frontend/src/components/auth/ProviderButtons.tsx +94 -0
- manigent/web/frontend/src/components/auth/SignupPage.tsx +437 -0
- manigent/web/frontend/src/components/auth/StepProgress.tsx +60 -0
- manigent/web/frontend/src/components/auth/VerifyEmailPage.test.tsx +155 -0
- manigent/web/frontend/src/components/auth/VerifyEmailPage.tsx +211 -0
- manigent/web/frontend/src/components/auth/index.ts +3 -0
- manigent/web/frontend/src/components/auth/oauthErrors.test.ts +107 -0
- manigent/web/frontend/src/components/auth/oauthErrors.ts +82 -0
- manigent/web/frontend/src/components/auth/useUsernameCheck.test.tsx +68 -0
- manigent/web/frontend/src/components/auth/useUsernameCheck.ts +86 -0
- manigent/web/frontend/src/components/beta/BetaPage.tsx +21 -0
- manigent/web/frontend/src/components/beta/DayAtMyDesk.tsx +120 -0
- manigent/web/frontend/src/components/beta/Footer.tsx +82 -0
- manigent/web/frontend/src/components/beta/Hero.tsx +224 -0
- manigent/web/frontend/src/components/beta/Nav.tsx +51 -0
- manigent/web/frontend/src/components/beta/Pillars.tsx +172 -0
- manigent/web/frontend/src/components/beta/TwoModels.tsx +146 -0
- manigent/web/frontend/src/components/beta/constants.ts +3 -0
- manigent/web/frontend/src/components/briefing/BriefingFrame.test.tsx +208 -0
- manigent/web/frontend/src/components/briefing/BriefingFrame.tsx +151 -0
- manigent/web/frontend/src/components/briefing/BriefingPage.test.tsx +176 -0
- manigent/web/frontend/src/components/briefing/BriefingPage.tsx +157 -0
- manigent/web/frontend/src/components/briefing/BriefingPage.wsDelete.test.tsx +177 -0
- manigent/web/frontend/src/components/briefing/briefing.css +147 -0
- manigent/web/frontend/src/components/briefing/heightBootstrap.test.ts +121 -0
- manigent/web/frontend/src/components/briefing/heightBootstrap.ts +224 -0
- manigent/web/frontend/src/components/briefing/parseBriefMessage.test.ts +90 -0
- manigent/web/frontend/src/components/briefing/sampleBriefing.ts +148 -0
- manigent/web/frontend/src/components/channels/ChannelBadge.tsx +35 -0
- manigent/web/frontend/src/components/chatroom/ChannelThreadControls.tsx +127 -0
- manigent/web/frontend/src/components/chatroom/ChannelThreadNotice.test.tsx +207 -0
- manigent/web/frontend/src/components/chatroom/ChannelThreadNotice.tsx +80 -0
- manigent/web/frontend/src/components/chatroom/ChatroomView.channel.test.tsx +550 -0
- manigent/web/frontend/src/components/chatroom/ChatroomView.flow.test.tsx +186 -0
- manigent/web/frontend/src/components/chatroom/ChatroomView.isolation.test.tsx +70 -0
- manigent/web/frontend/src/components/chatroom/ChatroomView.tsx +450 -0
- manigent/web/frontend/src/components/chatroom/DelegationRow.test.tsx +170 -0
- manigent/web/frontend/src/components/chatroom/DelegationRow.tsx +217 -0
- manigent/web/frontend/src/components/chatroom/DeliveryStatusLine.test.tsx +33 -0
- manigent/web/frontend/src/components/chatroom/DeliveryStatusLine.tsx +46 -0
- manigent/web/frontend/src/components/chatroom/ForwardModal.test.tsx +109 -0
- manigent/web/frontend/src/components/chatroom/ForwardModal.tsx +304 -0
- manigent/web/frontend/src/components/chatroom/HeldNotice.tsx +77 -0
- manigent/web/frontend/src/components/chatroom/MentionDropdown.tsx +97 -0
- manigent/web/frontend/src/components/chatroom/MessageInput.tsx +408 -0
- manigent/web/frontend/src/components/chatroom/MessageItem.tsx +425 -0
- manigent/web/frontend/src/components/chatroom/MessageList.outside.test.tsx +98 -0
- manigent/web/frontend/src/components/chatroom/MessageList.test.tsx +245 -0
- manigent/web/frontend/src/components/chatroom/MessageList.tsx +406 -0
- manigent/web/frontend/src/components/chatroom/OfflineRemedyNote.test.tsx +211 -0
- manigent/web/frontend/src/components/chatroom/OfflineRemedyNote.tsx +182 -0
- manigent/web/frontend/src/components/chatroom/OutsideBadge.tsx +18 -0
- manigent/web/frontend/src/components/chatroom/RoomFlowControl.tsx +49 -0
- manigent/web/frontend/src/components/chatroom/RoomFlowStrip.test.tsx +47 -0
- manigent/web/frontend/src/components/chatroom/RoomFlowStrip.tsx +25 -0
- manigent/web/frontend/src/components/chatroom/SaveToPackModal.tsx +350 -0
- manigent/web/frontend/src/components/chatroom/StagedAttachments.test.tsx +56 -0
- manigent/web/frontend/src/components/chatroom/StagedAttachments.tsx +160 -0
- manigent/web/frontend/src/components/chatroom/SystemNote.tsx +18 -0
- manigent/web/frontend/src/components/chatroom/contactSender.test.tsx +130 -0
- manigent/web/frontend/src/components/chatroom/index.ts +3 -0
- manigent/web/frontend/src/components/chatroom/recipientStatus.test.ts +344 -0
- manigent/web/frontend/src/components/chatroom/recipientStatus.ts +197 -0
- manigent/web/frontend/src/components/common/AnnouncementBanners.test.tsx +221 -0
- manigent/web/frontend/src/components/common/AnnouncementBanners.tsx +180 -0
- manigent/web/frontend/src/components/common/Avatar.test.tsx +50 -0
- manigent/web/frontend/src/components/common/Avatar.tsx +102 -0
- manigent/web/frontend/src/components/common/Badge.tsx +30 -0
- manigent/web/frontend/src/components/common/BrandName.tsx +16 -0
- manigent/web/frontend/src/components/common/ClearHistoryButton.tsx +74 -0
- manigent/web/frontend/src/components/common/CollapsibleHeader.tsx +64 -0
- manigent/web/frontend/src/components/common/ConnectionStatus.test.tsx +56 -0
- manigent/web/frontend/src/components/common/ConnectionStatus.tsx +28 -0
- manigent/web/frontend/src/components/common/DropOverlay.tsx +27 -0
- manigent/web/frontend/src/components/common/InlineEditableTitle.test.tsx +369 -0
- manigent/web/frontend/src/components/common/InlineEditableTitle.tsx +287 -0
- manigent/web/frontend/src/components/common/IsolationUnavailablePanel.tsx +19 -0
- manigent/web/frontend/src/components/common/Loading.tsx +22 -0
- manigent/web/frontend/src/components/common/ModelSelector.tsx +248 -0
- manigent/web/frontend/src/components/common/Overlay.tsx +15 -0
- manigent/web/frontend/src/components/common/ResizeHandle.tsx +52 -0
- manigent/web/frontend/src/components/common/TagAutocompleteInput.test.tsx +92 -0
- manigent/web/frontend/src/components/common/TagAutocompleteInput.tsx +246 -0
- manigent/web/frontend/src/components/common/TagPillInput.tsx +181 -0
- manigent/web/frontend/src/components/common/TeamAndAgentPicker.tsx +83 -0
- manigent/web/frontend/src/components/common/Timestamp.tsx +61 -0
- manigent/web/frontend/src/components/common/VerifiedBadge.tsx +20 -0
- manigent/web/frontend/src/components/common/index.ts +8 -0
- manigent/web/frontend/src/components/composer/PhPopover.tsx +239 -0
- manigent/web/frontend/src/components/composer/PromptEditor.test.tsx +472 -0
- manigent/web/frontend/src/components/composer/PromptEditor.tsx +540 -0
- manigent/web/frontend/src/components/composer/caret.ts +159 -0
- manigent/web/frontend/src/components/composer/placeholders.test.ts +352 -0
- manigent/web/frontend/src/components/composer/placeholders.ts +354 -0
- manigent/web/frontend/src/components/composer/promptEditor.css +161 -0
- manigent/web/frontend/src/components/computer/ComputerPage.test.tsx +452 -0
- manigent/web/frontend/src/components/computer/ComputerPage.tsx +811 -0
- manigent/web/frontend/src/components/computer/ConnectComputerModal.tsx +135 -0
- manigent/web/frontend/src/components/computer/CopyCommand.tsx +77 -0
- manigent/web/frontend/src/components/computer/DisconnectComputerModal.tsx +121 -0
- manigent/web/frontend/src/components/computer/SoftwareCard.tsx +145 -0
- manigent/web/frontend/src/components/computer/TerminalCard.test.tsx +114 -0
- manigent/web/frontend/src/components/computer/TerminalCard.tsx +131 -0
- manigent/web/frontend/src/components/computer/TerminalPanel.tsx +226 -0
- manigent/web/frontend/src/components/computer/TrustPanel.test.tsx +58 -0
- manigent/web/frontend/src/components/computer/TrustPanel.tsx +143 -0
- manigent/web/frontend/src/components/computer/computerCopy.test.ts +322 -0
- manigent/web/frontend/src/components/computer/computerCopy.ts +413 -0
- manigent/web/frontend/src/components/computer/sections.ts +21 -0
- manigent/web/frontend/src/components/computer/terminalProtocol.test.ts +135 -0
- manigent/web/frontend/src/components/computer/terminalProtocol.ts +170 -0
- manigent/web/frontend/src/components/context/ContextGuide.test.tsx +26 -0
- manigent/web/frontend/src/components/context/ContextGuide.tsx +144 -0
- manigent/web/frontend/src/components/context/ContextLanding.tsx +46 -0
- manigent/web/frontend/src/components/desk/CardBand.a11y.test.tsx +138 -0
- manigent/web/frontend/src/components/desk/CardBand.tsx +132 -0
- manigent/web/frontend/src/components/desk/DashTile.tsx +81 -0
- manigent/web/frontend/src/components/desk/DeskAgentPicker.retained.test.tsx +79 -0
- manigent/web/frontend/src/components/desk/DeskAgentPicker.tsx +151 -0
- manigent/web/frontend/src/components/desk/DeskComposer.detachTodo.test.tsx +233 -0
- manigent/web/frontend/src/components/desk/DeskComposer.dispatch.test.tsx +208 -0
- manigent/web/frontend/src/components/desk/DeskComposer.loadTodoDraft.test.tsx +242 -0
- manigent/web/frontend/src/components/desk/DeskComposer.restage.test.tsx +258 -0
- manigent/web/frontend/src/components/desk/DeskComposer.saveTodo.test.tsx +265 -0
- manigent/web/frontend/src/components/desk/DeskComposer.tsx +828 -0
- manigent/web/frontend/src/components/desk/DeskPage.crossHighlight.test.tsx +427 -0
- manigent/web/frontend/src/components/desk/DeskPage.link.test.tsx +271 -0
- manigent/web/frontend/src/components/desk/DeskPage.tsx +1066 -0
- manigent/web/frontend/src/components/desk/DeskPage.welcomeTour.test.tsx +262 -0
- manigent/web/frontend/src/components/desk/DeskSideRail.tsx +100 -0
- manigent/web/frontend/src/components/desk/DeskWelcomeTour.tsx +513 -0
- manigent/web/frontend/src/components/desk/DeskZeroState.tsx +45 -0
- manigent/web/frontend/src/components/desk/LabelChip.tsx +147 -0
- manigent/web/frontend/src/components/desk/LabelFilter.tsx +474 -0
- manigent/web/frontend/src/components/desk/LabelInput.test.tsx +439 -0
- manigent/web/frontend/src/components/desk/LabelInput.tsx +477 -0
- manigent/web/frontend/src/components/desk/LabelManageSheet.test.tsx +384 -0
- manigent/web/frontend/src/components/desk/LabelManageSheet.tsx +498 -0
- manigent/web/frontend/src/components/desk/PhaseRail.test.tsx +170 -0
- manigent/web/frontend/src/components/desk/PhaseRail.tsx +120 -0
- manigent/web/frontend/src/components/desk/PlanBand.test.tsx +655 -0
- manigent/web/frontend/src/components/desk/PlanBand.tsx +216 -0
- manigent/web/frontend/src/components/desk/SaveTodoModal.tsx +126 -0
- manigent/web/frontend/src/components/desk/SopEditor.tsx +280 -0
- manigent/web/frontend/src/components/desk/SopItem.tsx +171 -0
- manigent/web/frontend/src/components/desk/SopRail.test.tsx +517 -0
- manigent/web/frontend/src/components/desk/SopRail.tsx +250 -0
- manigent/web/frontend/src/components/desk/TicketChip.tsx +51 -0
- manigent/web/frontend/src/components/desk/TodoItem.attachments.test.tsx +96 -0
- manigent/web/frontend/src/components/desk/TodoItem.menu.test.tsx +142 -0
- manigent/web/frontend/src/components/desk/TodoItem.tsx +573 -0
- manigent/web/frontend/src/components/desk/TodoRail.longpress.test.tsx +396 -0
- manigent/web/frontend/src/components/desk/TodoRail.test.tsx +1155 -0
- manigent/web/frontend/src/components/desk/TodoRail.tsx +918 -0
- manigent/web/frontend/src/components/desk/TodoRowMenu.tsx +147 -0
- manigent/web/frontend/src/components/desk/UpdateCard.bands.test.tsx +308 -0
- manigent/web/frontend/src/components/desk/UpdateCard.sendBack.test.tsx +444 -0
- manigent/web/frontend/src/components/desk/UpdateCard.tsx +943 -0
- manigent/web/frontend/src/components/desk/UpdateCard.untrusted.test.tsx +161 -0
- manigent/web/frontend/src/components/desk/desk.css +1921 -0
- manigent/web/frontend/src/components/desk/desk.css.test.ts +582 -0
- manigent/web/frontend/src/components/desk/deskBands.test.ts +389 -0
- manigent/web/frontend/src/components/desk/deskBands.ts +226 -0
- manigent/web/frontend/src/components/desk/m16Surfaces.test.ts +134 -0
- manigent/web/frontend/src/components/desk/sopSyntax.ts +73 -0
- manigent/web/frontend/src/components/discovery/AgentDirectory.tsx +71 -0
- manigent/web/frontend/src/components/discovery/AgentFilterBar.tsx +46 -0
- manigent/web/frontend/src/components/discovery/AgentSearchBar.tsx +56 -0
- manigent/web/frontend/src/components/dm/AgentSummaryCard.tsx +154 -0
- manigent/web/frontend/src/components/dm/ComposeFields.tsx +145 -0
- manigent/web/frontend/src/components/dm/DMChatView.flow.test.tsx +374 -0
- manigent/web/frontend/src/components/dm/DMChatView.tsx +841 -0
- manigent/web/frontend/src/components/dm/DMZeroState.tsx +204 -0
- manigent/web/frontend/src/components/dm/DmComposeModal.tsx +301 -0
- manigent/web/frontend/src/components/dm/PersonalizeModal.tsx +366 -0
- manigent/web/frontend/src/components/dm/index.ts +1 -0
- manigent/web/frontend/src/components/files/FileItem.tsx +138 -0
- manigent/web/frontend/src/components/files/FileList.outside.test.tsx +29 -0
- manigent/web/frontend/src/components/files/FileList.tsx +48 -0
- manigent/web/frontend/src/components/files/FilePreview.test.tsx +75 -0
- manigent/web/frontend/src/components/files/FilePreview.tsx +325 -0
- manigent/web/frontend/src/components/files/FileViewerModal.test.tsx +157 -0
- manigent/web/frontend/src/components/files/FileViewerModal.tsx +261 -0
- manigent/web/frontend/src/components/files/HighlightedCode.tsx +39 -0
- manigent/web/frontend/src/components/files/SaveToAgentPanel.test.tsx +156 -0
- manigent/web/frontend/src/components/files/SaveToAgentPanel.tsx +545 -0
- manigent/web/frontend/src/components/files/index.ts +3 -0
- manigent/web/frontend/src/components/hero/AgentAvatar.tsx +66 -0
- manigent/web/frontend/src/components/hero/Button.tsx +66 -0
- manigent/web/frontend/src/components/hero/Hero.tsx +133 -0
- manigent/web/frontend/src/components/homefs/HomeFolderBrowser.test.tsx +393 -0
- manigent/web/frontend/src/components/homefs/HomeFolderBrowser.tsx +792 -0
- manigent/web/frontend/src/components/hub/BridgeDeliveryLine.test.tsx +40 -0
- manigent/web/frontend/src/components/hub/BridgeDeliveryLine.tsx +36 -0
- manigent/web/frontend/src/components/hub/HubAvatar.test.tsx +93 -0
- manigent/web/frontend/src/components/hub/HubAvatar.tsx +33 -0
- manigent/web/frontend/src/components/hub/HubChatView.test.tsx +695 -0
- manigent/web/frontend/src/components/hub/HubChatView.tsx +504 -0
- manigent/web/frontend/src/components/hub/HubContactLabel.test.tsx +92 -0
- manigent/web/frontend/src/components/hub/HubContactLabel.tsx +47 -0
- manigent/web/frontend/src/components/hub/HubDeliveryLine.tsx +49 -0
- manigent/web/frontend/src/components/hub/HubDisclosure.tsx +49 -0
- manigent/web/frontend/src/components/hub/HubEnrollmentDialog.test.tsx +144 -0
- manigent/web/frontend/src/components/hub/HubEnrollmentDialog.tsx +244 -0
- manigent/web/frontend/src/components/hub/HubMessageBody.test.tsx +26 -0
- manigent/web/frontend/src/components/hub/HubMessageBody.tsx +14 -0
- manigent/web/frontend/src/components/hub/HubOfflineConfirm.tsx +45 -0
- manigent/web/frontend/src/components/hub/HubThreadBanner.tsx +33 -0
- manigent/web/frontend/src/components/hub/HubThreadGuard.tsx +59 -0
- manigent/web/frontend/src/components/hub/RemoteAgentCard.test.tsx +50 -0
- manigent/web/frontend/src/components/hub/RemoteAgentCard.tsx +174 -0
- manigent/web/frontend/src/components/hub/RemoteAgentSection.test.tsx +446 -0
- manigent/web/frontend/src/components/hub/RemoteAgentSection.tsx +219 -0
- manigent/web/frontend/src/components/hub/ReportDialog.test.tsx +96 -0
- manigent/web/frontend/src/components/hub/ReportDialog.tsx +162 -0
- manigent/web/frontend/src/components/hub/RetainButton.test.tsx +103 -0
- manigent/web/frontend/src/components/hub/RetainButton.tsx +114 -0
- manigent/web/frontend/src/components/hub/RetainDialog.test.tsx +68 -0
- manigent/web/frontend/src/components/hub/RetainDialog.tsx +115 -0
- manigent/web/frontend/src/components/hub/RetainedList.test.tsx +94 -0
- manigent/web/frontend/src/components/hub/RetainedList.tsx +32 -0
- manigent/web/frontend/src/components/hub/RetainedRow.tsx +129 -0
- manigent/web/frontend/src/components/hub/StandInChip.test.tsx +37 -0
- manigent/web/frontend/src/components/hub/StandInChip.tsx +43 -0
- manigent/web/frontend/src/components/hub/UnusualNameChip.test.tsx +81 -0
- manigent/web/frontend/src/components/hub/UnusualNameChip.tsx +22 -0
- manigent/web/frontend/src/components/hub/hubLint.test.ts +265 -0
- manigent/web/frontend/src/components/landing/ComparisonSection.tsx +92 -0
- manigent/web/frontend/src/components/landing/ConsoleSection.tsx +402 -0
- manigent/web/frontend/src/components/landing/CrewSection.tsx +224 -0
- manigent/web/frontend/src/components/landing/FAQ.tsx +68 -0
- manigent/web/frontend/src/components/landing/Footer.tsx +58 -0
- manigent/web/frontend/src/components/landing/HowItWorks.tsx +117 -0
- manigent/web/frontend/src/components/landing/KnowledgeSection.tsx +91 -0
- manigent/web/frontend/src/components/landing/LandingPage.test.tsx +134 -0
- manigent/web/frontend/src/components/landing/LearningSection.tsx +486 -0
- manigent/web/frontend/src/components/landing/Nav.tsx +68 -0
- manigent/web/frontend/src/components/landing/Pricing.tsx +263 -0
- manigent/web/frontend/src/components/landing/Section.tsx +98 -0
- manigent/web/frontend/src/components/landing/StaffingSection.tsx +122 -0
- manigent/web/frontend/src/components/landing/WhyNowSection.tsx +92 -0
- manigent/web/frontend/src/components/landing/WhyTeamSection.tsx +73 -0
- manigent/web/frontend/src/components/landing/earlyAccess.ts +23 -0
- manigent/web/frontend/src/components/layout/AppLayout.tsx +77 -0
- manigent/web/frontend/src/components/layout/Sidebar.tsx +172 -0
- manigent/web/frontend/src/components/layout/index.ts +2 -0
- manigent/web/frontend/src/components/project/ActivityFeed.tsx +247 -0
- manigent/web/frontend/src/components/project/CreateProjectPage.tsx +543 -0
- manigent/web/frontend/src/components/project/DeleteProjectButton.tsx +39 -0
- manigent/web/frontend/src/components/project/ProjectPlanTab.phase.test.tsx +107 -0
- manigent/web/frontend/src/components/project/ProjectPlanTab.test.tsx +994 -0
- manigent/web/frontend/src/components/project/ProjectPlanTab.tsx +166 -0
- manigent/web/frontend/src/components/project/ProjectReportTab.tsx +139 -0
- manigent/web/frontend/src/components/project/ProjectView.tsx +390 -0
- manigent/web/frontend/src/components/project/index.ts +2 -0
- manigent/web/frontend/src/components/project/plan/PlanAcceptance.test.tsx +460 -0
- manigent/web/frontend/src/components/project/plan/PlanAcceptance.tsx +111 -0
- manigent/web/frontend/src/components/project/plan/PlanBlockEdit.tsx +111 -0
- manigent/web/frontend/src/components/project/plan/PlanBlockEditing.test.tsx +1132 -0
- manigent/web/frontend/src/components/project/plan/PlanBody.test.tsx +495 -0
- manigent/web/frontend/src/components/project/plan/PlanBody.tsx +992 -0
- manigent/web/frontend/src/components/project/plan/PlanCollide.tsx +254 -0
- manigent/web/frontend/src/components/project/plan/PlanCommentList.test.tsx +420 -0
- manigent/web/frontend/src/components/project/plan/PlanCommentList.tsx +391 -0
- manigent/web/frontend/src/components/project/plan/PlanDecisionNudge.test.tsx +226 -0
- manigent/web/frontend/src/components/project/plan/PlanDecisionNudge.tsx +128 -0
- manigent/web/frontend/src/components/project/plan/PlanDestructiveAccept.test.tsx +209 -0
- manigent/web/frontend/src/components/project/plan/PlanDiff.test.tsx +126 -0
- manigent/web/frontend/src/components/project/plan/PlanDiff.tsx +131 -0
- manigent/web/frontend/src/components/project/plan/PlanDiffSeries.test.tsx +500 -0
- manigent/web/frontend/src/components/project/plan/PlanDiffSeries.tsx +125 -0
- manigent/web/frontend/src/components/project/plan/PlanEditor.mounts.test.tsx +504 -0
- manigent/web/frontend/src/components/project/plan/PlanEditor.tsx +2159 -0
- manigent/web/frontend/src/components/project/plan/PlanHistory.tsx +69 -0
- manigent/web/frontend/src/components/project/plan/PlanInlineNotes.test.tsx +2398 -0
- manigent/web/frontend/src/components/project/plan/PlanNoteBase.test.tsx +215 -0
- manigent/web/frontend/src/components/project/plan/PlanNoteRow.test.tsx +562 -0
- manigent/web/frontend/src/components/project/plan/PlanNoteRow.tsx +908 -0
- manigent/web/frontend/src/components/project/plan/PlanQuotePop.tsx +254 -0
- manigent/web/frontend/src/components/project/plan/PlanStaleReconcile.test.tsx +244 -0
- manigent/web/frontend/src/components/project/plan/PlanSubmitWindow.test.tsx +281 -0
- manigent/web/frontend/src/components/project/plan/PlanTray.tsx +184 -0
- manigent/web/frontend/src/components/project/plan/PlanTrayMirror.test.tsx +242 -0
- manigent/web/frontend/src/components/project/plan/plan.css +1151 -0
- manigent/web/frontend/src/components/project/plan/planAnchor.test.tsx +459 -0
- manigent/web/frontend/src/components/project/plan/planAnchor.tsx +277 -0
- manigent/web/frontend/src/components/project/plan/planBlocks.test.tsx +470 -0
- manigent/web/frontend/src/components/project/plan/planBlocks.ts +242 -0
- manigent/web/frontend/src/components/project/plan/planContrast.test.ts +229 -0
- manigent/web/frontend/src/components/project/plan/planDiffs.test.ts +455 -0
- manigent/web/frontend/src/components/project/plan/planDiffs.ts +358 -0
- manigent/web/frontend/src/components/project/plan/planTestServer.ts +741 -0
- manigent/web/frontend/src/components/project/plan/planTransport.test.ts +160 -0
- manigent/web/frontend/src/components/project/plan/planTrayLogic.test.ts +1201 -0
- manigent/web/frontend/src/components/project/plan/planTrayLogic.ts +1164 -0
- manigent/web/frontend/src/components/publicAgents/PublicAgentsAccount.tsx +162 -0
- manigent/web/frontend/src/components/publicAgents/api.ts +55 -0
- manigent/web/frontend/src/components/publicAgents/parts.tsx +54 -0
- manigent/web/frontend/src/components/publicAgents/publicAgents.css +53 -0
- manigent/web/frontend/src/components/publicAgents/publicAgents.test.tsx +86 -0
- manigent/web/frontend/src/components/publicAgents/widget.test.ts +148 -0
- manigent/web/frontend/src/components/publicAgents/widget.ts +40 -0
- manigent/web/frontend/src/components/publicRequests/AgentDrawer.tsx +101 -0
- manigent/web/frontend/src/components/publicRequests/AgentPanel.tsx +173 -0
- manigent/web/frontend/src/components/publicRequests/AgentRankList.tsx +61 -0
- manigent/web/frontend/src/components/publicRequests/MatchRetainButton.tsx +67 -0
- manigent/web/frontend/src/components/publicRequests/ProgressBoard.tsx +74 -0
- manigent/web/frontend/src/components/publicRequests/PublicRequestsPage.tsx +57 -0
- manigent/web/frontend/src/components/publicRequests/RequestHome.tsx +99 -0
- manigent/web/frontend/src/components/publicRequests/RequestRoom.tsx +126 -0
- manigent/web/frontend/src/components/publicRequests/agentView.ts +65 -0
- manigent/web/frontend/src/components/publicRequests/publicRequests.css +209 -0
- manigent/web/frontend/src/components/publicRequests/publicRequests.test.tsx +172 -0
- manigent/web/frontend/src/components/publicRequests/requestCopy.ts +121 -0
- manigent/web/frontend/src/components/sample-request/SampleIdeaList.test.tsx +190 -0
- manigent/web/frontend/src/components/sample-request/SampleIdeaList.tsx +180 -0
- manigent/web/frontend/src/components/sample-request/SampleRequestBody.tsx +276 -0
- manigent/web/frontend/src/components/sample-request/assistantStarterSamples.ts +62 -0
- manigent/web/frontend/src/components/sample-request/sampleIdeaList.css +106 -0
- manigent/web/frontend/src/components/scheduled/CronPicker.tsx +80 -0
- manigent/web/frontend/src/components/scheduled/ScheduleMessageModal.tsx +341 -0
- manigent/web/frontend/src/components/scheduled/ScheduledMessagesList.tsx +157 -0
- manigent/web/frontend/src/components/settings/AgentSettingsPage.tsx +366 -0
- manigent/web/frontend/src/components/settings/ConnectedAccounts.tsx +277 -0
- manigent/web/frontend/src/components/settings/DefaultModelSection.test.tsx +96 -0
- manigent/web/frontend/src/components/settings/DefaultModelSection.tsx +212 -0
- manigent/web/frontend/src/components/settings/DisconnectConfirmModal.tsx +93 -0
- manigent/web/frontend/src/components/settings/FrontDeskSettingsPage.isolation.test.tsx +66 -0
- manigent/web/frontend/src/components/settings/FrontDeskSettingsPage.tsx +134 -0
- manigent/web/frontend/src/components/settings/InvitableAgentsPicker.tsx +182 -0
- manigent/web/frontend/src/components/settings/KnowledgePacksSection.tsx +867 -0
- manigent/web/frontend/src/components/settings/ModelConfigDialog.catalogDriven.test.tsx +79 -0
- manigent/web/frontend/src/components/settings/ModelConfigDialog.tsx +343 -0
- manigent/web/frontend/src/components/settings/ModelConfigSection.smartRouting.test.tsx +109 -0
- manigent/web/frontend/src/components/settings/ModelConfigSection.tsx +599 -0
- manigent/web/frontend/src/components/settings/ReflectionScheduleSection.tsx +170 -0
- manigent/web/frontend/src/components/settings/UserSettingsPage.tsx +168 -0
- manigent/web/frontend/src/components/settings/agent/AgentStatusStrip.tsx +71 -0
- manigent/web/frontend/src/components/settings/agent/BlockedDeploymentsCard.test.tsx +81 -0
- manigent/web/frontend/src/components/settings/agent/BlockedDeploymentsCard.tsx +62 -0
- manigent/web/frontend/src/components/settings/agent/ChannelIsolationLine.tsx +21 -0
- manigent/web/frontend/src/components/settings/agent/ChannelsSection.test.tsx +879 -0
- manigent/web/frontend/src/components/settings/agent/ChannelsSection.tsx +1124 -0
- manigent/web/frontend/src/components/settings/agent/EnvVarsCard.test.ts +15 -0
- manigent/web/frontend/src/components/settings/agent/EnvVarsCard.tsx +301 -0
- manigent/web/frontend/src/components/settings/agent/ExtraDirsList.tsx +85 -0
- manigent/web/frontend/src/components/settings/agent/GeneralSection.tsx +88 -0
- manigent/web/frontend/src/components/settings/agent/HostDisclaimerSlot.test.tsx +32 -0
- manigent/web/frontend/src/components/settings/agent/HostDisclaimerSlot.tsx +30 -0
- manigent/web/frontend/src/components/settings/agent/HubChannelCard.test.tsx +449 -0
- manigent/web/frontend/src/components/settings/agent/HubChannelCard.tsx +312 -0
- manigent/web/frontend/src/components/settings/agent/HubInvitableAgentsCard.test.tsx +83 -0
- manigent/web/frontend/src/components/settings/agent/HubInvitableAgentsCard.tsx +64 -0
- manigent/web/frontend/src/components/settings/agent/HubSendUsageCard.test.tsx +69 -0
- manigent/web/frontend/src/components/settings/agent/HubSendUsageCard.tsx +42 -0
- manigent/web/frontend/src/components/settings/agent/HubTurnOffDialog.tsx +88 -0
- manigent/web/frontend/src/components/settings/agent/IsolationRecheckButton.test.tsx +26 -0
- manigent/web/frontend/src/components/settings/agent/IsolationRecheckButton.tsx +68 -0
- manigent/web/frontend/src/components/settings/agent/KnowledgeSection.tsx +68 -0
- manigent/web/frontend/src/components/settings/agent/LineChannelCard.test.tsx +428 -0
- manigent/web/frontend/src/components/settings/agent/LineChannelCard.tsx +343 -0
- manigent/web/frontend/src/components/settings/agent/RuntimeSection.test.tsx +164 -0
- manigent/web/frontend/src/components/settings/agent/RuntimeSection.tsx +118 -0
- manigent/web/frontend/src/components/settings/agent/StorageSection.tsx +78 -0
- manigent/web/frontend/src/components/settings/agent/WebChatChannelCard.test.tsx +253 -0
- manigent/web/frontend/src/components/settings/agent/WebChatChannelCard.tsx +401 -0
- manigent/web/frontend/src/components/settings/agent/WhatsAppChannelCard.test.tsx +462 -0
- manigent/web/frontend/src/components/settings/agent/WhatsAppChannelCard.tsx +289 -0
- manigent/web/frontend/src/components/settings/agent/agentSettings.test.tsx +109 -0
- manigent/web/frontend/src/components/settings/agent/channelSetupGuides.test.tsx +162 -0
- manigent/web/frontend/src/components/settings/agent/channelSetupGuides.tsx +119 -0
- manigent/web/frontend/src/components/settings/agent/channelsShared.ts +83 -0
- manigent/web/frontend/src/components/settings/agent/fields.tsx +67 -0
- manigent/web/frontend/src/components/settings/agent/sections.ts +36 -0
- manigent/web/frontend/src/components/settings/agent/useAgentSettingsDraft.ts +129 -0
- manigent/web/frontend/src/components/settings/agent/useInstallSelection.ts +38 -0
- manigent/web/frontend/src/components/settings/primitives.tsx +98 -0
- manigent/web/frontend/src/components/shared/ExpandToggle.tsx +45 -0
- manigent/web/frontend/src/components/shared/MarkdownBody.tsx +218 -0
- manigent/web/frontend/src/components/shared/MarkdownBody.untrusted.test.tsx +97 -0
- manigent/web/frontend/src/components/shared/RenderBody.tsx +90 -0
- manigent/web/frontend/src/components/shared/rehypeHideComments.test.tsx +115 -0
- manigent/web/frontend/src/components/shared/rehypeHideComments.ts +124 -0
- manigent/web/frontend/src/components/sharing/AcceptSharePage.tsx +141 -0
- manigent/web/frontend/src/components/sharing/ShareLandingPage.tsx +89 -0
- manigent/web/frontend/src/components/sidebar/AccountChip.test.tsx +337 -0
- manigent/web/frontend/src/components/sidebar/AccountChip.tsx +407 -0
- manigent/web/frontend/src/components/sidebar/ActiveWorkDot.tsx +9 -0
- manigent/web/frontend/src/components/sidebar/AgentProfile.tsx +44 -0
- manigent/web/frontend/src/components/sidebar/AgentRow.tsx +71 -0
- manigent/web/frontend/src/components/sidebar/AgentsPanel.retained.test.tsx +105 -0
- manigent/web/frontend/src/components/sidebar/AgentsPanel.tsx +231 -0
- manigent/web/frontend/src/components/sidebar/AssistantHero.tsx +48 -0
- manigent/web/frontend/src/components/sidebar/ChatroomItem.tsx +48 -0
- manigent/web/frontend/src/components/sidebar/CommandPalette.channelThreads.test.tsx +76 -0
- manigent/web/frontend/src/components/sidebar/CommandPalette.reopen.test.tsx +206 -0
- manigent/web/frontend/src/components/sidebar/CommandPalette.test.tsx +725 -0
- manigent/web/frontend/src/components/sidebar/CommandPalette.tsx +774 -0
- manigent/web/frontend/src/components/sidebar/ComputersPanel.tsx +144 -0
- manigent/web/frontend/src/components/sidebar/DmIcon.tsx +46 -0
- manigent/web/frontend/src/components/sidebar/DmsPanel.tsx +226 -0
- manigent/web/frontend/src/components/sidebar/FrontDeskPanel.channels.test.tsx +582 -0
- manigent/web/frontend/src/components/sidebar/FrontDeskPanel.test.tsx +151 -0
- manigent/web/frontend/src/components/sidebar/FrontDeskPanel.tsx +454 -0
- manigent/web/frontend/src/components/sidebar/HotkeysHelp.tsx +101 -0
- manigent/web/frontend/src/components/sidebar/MessageHitRow.test.tsx +84 -0
- manigent/web/frontend/src/components/sidebar/MessageHitRow.tsx +57 -0
- manigent/web/frontend/src/components/sidebar/MyDeskRailPanel.crossHighlight.test.tsx +247 -0
- manigent/web/frontend/src/components/sidebar/MyDeskRailPanel.delete.test.tsx +273 -0
- manigent/web/frontend/src/components/sidebar/MyDeskRailPanel.tsx +351 -0
- manigent/web/frontend/src/components/sidebar/PanelShell.tsx +48 -0
- manigent/web/frontend/src/components/sidebar/ProjectItem.tsx +161 -0
- manigent/web/frontend/src/components/sidebar/ProjectRow.tsx +151 -0
- manigent/web/frontend/src/components/sidebar/ProjectsPanel.tsx +80 -0
- manigent/web/frontend/src/components/sidebar/PublicPanel.counterpart.test.tsx +85 -0
- manigent/web/frontend/src/components/sidebar/PublicPanel.hub.test.tsx +147 -0
- manigent/web/frontend/src/components/sidebar/PublicPanel.tsx +271 -0
- manigent/web/frontend/src/components/sidebar/RecencyHeader.tsx +17 -0
- manigent/web/frontend/src/components/sidebar/ScheduledPanel.tsx +58 -0
- manigent/web/frontend/src/components/sidebar/SidebarAvatar.tsx +128 -0
- manigent/web/frontend/src/components/sidebar/SidebarRail.tsx +163 -0
- manigent/web/frontend/src/components/sidebar/TeamGroup.tsx +67 -0
- manigent/web/frontend/src/components/sidebar/dmPrefill.test.ts +69 -0
- manigent/web/frontend/src/components/sidebar/dmPrefill.ts +80 -0
- manigent/web/frontend/src/components/sidebar/index.ts +18 -0
- manigent/web/frontend/src/components/sidebar/railShortcuts.ts +18 -0
- manigent/web/frontend/src/components/today/lib.test.ts +70 -0
- manigent/web/frontend/src/components/today/lib.ts +296 -0
- manigent/web/frontend/src/components/today/today.css +113 -0
- manigent/web/frontend/src/components/welcome/RunnerSetup.css +253 -0
- manigent/web/frontend/src/components/welcome/RunnerSetup.tsx +148 -0
- manigent/web/frontend/src/components/welcome/WelcomePage.css +383 -0
- manigent/web/frontend/src/components/welcome/WelcomePage.tsx +329 -0
- manigent/web/frontend/src/components/welcome/welcomeCopy.test.ts +382 -0
- manigent/web/frontend/src/components/welcome/welcomeCopy.ts +313 -0
- manigent/web/frontend/src/config/llmProviders.test.ts +161 -0
- manigent/web/frontend/src/config/llmProviders.ts +109 -0
- manigent/web/frontend/src/config/providerIds.fixture.json +13 -0
- manigent/web/frontend/src/hooks/accountNavigation.test.tsx +138 -0
- manigent/web/frontend/src/hooks/index.ts +10 -0
- manigent/web/frontend/src/hooks/useActiveWorkBootstrap.ts +86 -0
- manigent/web/frontend/src/hooks/useAgentAccess.test.tsx +30 -0
- manigent/web/frontend/src/hooks/useAgentAccess.ts +204 -0
- manigent/web/frontend/src/hooks/useAgentSampleRequests.ts +27 -0
- manigent/web/frontend/src/hooks/useAgentSearch.ts +10 -0
- manigent/web/frontend/src/hooks/useAgents.ts +46 -0
- manigent/web/frontend/src/hooks/useAnnouncements.test.ts +112 -0
- manigent/web/frontend/src/hooks/useAnnouncements.ts +100 -0
- manigent/web/frontend/src/hooks/useAssistantAgent.ts +24 -0
- manigent/web/frontend/src/hooks/useAutoResizeTextarea.ts +18 -0
- manigent/web/frontend/src/hooks/useBridgeDeliveries.test.tsx +79 -0
- manigent/web/frontend/src/hooks/useBriefTabs.ts +122 -0
- manigent/web/frontend/src/hooks/useChannelThreads.ts +69 -0
- manigent/web/frontend/src/hooks/useComposeForm.ts +80 -0
- manigent/web/frontend/src/hooks/useComputers.ts +123 -0
- manigent/web/frontend/src/hooks/useContextFirstItem.ts +118 -0
- manigent/web/frontend/src/hooks/useCreateProject.ts +78 -0
- manigent/web/frontend/src/hooks/useDebouncedValue.ts +16 -0
- manigent/web/frontend/src/hooks/useDeleteProject.ts +27 -0
- manigent/web/frontend/src/hooks/useDeskDispatch.test.tsx +170 -0
- manigent/web/frontend/src/hooks/useDeskDispatch.ts +135 -0
- manigent/web/frontend/src/hooks/useDeskReadState.test.tsx +85 -0
- manigent/web/frontend/src/hooks/useDeskReadState.ts +150 -0
- manigent/web/frontend/src/hooks/useDeskRecentlyDone.test.tsx +222 -0
- manigent/web/frontend/src/hooks/useDeskRecentlyDone.ts +225 -0
- manigent/web/frontend/src/hooks/useDeskTour.ts +37 -0
- manigent/web/frontend/src/hooks/useDeskUpdates.channelThreads.test.tsx +91 -0
- manigent/web/frontend/src/hooks/useDeskUpdates.hubThreads.test.tsx +93 -0
- manigent/web/frontend/src/hooks/useDeskUpdates.ts +353 -0
- manigent/web/frontend/src/hooks/useDisconnectIntegration.ts +23 -0
- manigent/web/frontend/src/hooks/useDmThreads.ts +99 -0
- manigent/web/frontend/src/hooks/useFileDropzone.ts +93 -0
- manigent/web/frontend/src/hooks/useFileUpload.ts +38 -0
- manigent/web/frontend/src/hooks/useFiles.ts +98 -0
- manigent/web/frontend/src/hooks/useHub.test.tsx +237 -0
- manigent/web/frontend/src/hooks/useHub.ts +502 -0
- manigent/web/frontend/src/hooks/useInstall.ts +82 -0
- manigent/web/frontend/src/hooks/useLabels.test.tsx +294 -0
- manigent/web/frontend/src/hooks/useLabels.ts +287 -0
- manigent/web/frontend/src/hooks/useLogout.ts +49 -0
- manigent/web/frontend/src/hooks/useMentionDetection.ts +90 -0
- manigent/web/frontend/src/hooks/useMessageAttachments.deskLimit.test.ts +264 -0
- manigent/web/frontend/src/hooks/useMessageAttachments.ts +283 -0
- manigent/web/frontend/src/hooks/useMessageDeepLink.test.tsx +70 -0
- manigent/web/frontend/src/hooks/useMessageDeepLink.ts +32 -0
- manigent/web/frontend/src/hooks/useMessageSearch.ts +78 -0
- manigent/web/frontend/src/hooks/useModelConfigs.ts +178 -0
- manigent/web/frontend/src/hooks/useMyAgents.ts +18 -0
- manigent/web/frontend/src/hooks/usePointerReorder.ts +270 -0
- manigent/web/frontend/src/hooks/usePrefersReducedMotion.ts +18 -0
- manigent/web/frontend/src/hooks/useProjectPlan.ts +36 -0
- manigent/web/frontend/src/hooks/useProjectReport.ts +19 -0
- manigent/web/frontend/src/hooks/useProjects.ts +104 -0
- manigent/web/frontend/src/hooks/useProjectsWithChatrooms.ts +97 -0
- manigent/web/frontend/src/hooks/usePublicRequests.ts +89 -0
- manigent/web/frontend/src/hooks/useRecentAgents.ts +38 -0
- manigent/web/frontend/src/hooks/useRenameProject.test.tsx +185 -0
- manigent/web/frontend/src/hooks/useRenameProject.ts +192 -0
- manigent/web/frontend/src/hooks/useRoomTrust.ts +56 -0
- manigent/web/frontend/src/hooks/useSharing.ts +46 -0
- manigent/web/frontend/src/hooks/useSopRecents.ts +55 -0
- manigent/web/frontend/src/hooks/useSopSchedules.ts +25 -0
- manigent/web/frontend/src/hooks/useSops.ts +99 -0
- manigent/web/frontend/src/hooks/useSwitchAccount.ts +41 -0
- manigent/web/frontend/src/hooks/useTeamGroups.ts +48 -0
- manigent/web/frontend/src/hooks/useThreadOutbox.ts +68 -0
- manigent/web/frontend/src/hooks/useTodos.add.test.tsx +89 -0
- manigent/web/frontend/src/hooks/useTodos.linkProject.test.tsx +115 -0
- manigent/web/frontend/src/hooks/useTodos.saveDraft.test.tsx +188 -0
- manigent/web/frontend/src/hooks/useTodos.ts +396 -0
- manigent/web/frontend/src/hooks/useUntrustedBodies.test.tsx +87 -0
- manigent/web/frontend/src/hooks/useUntrustedBodies.ts +51 -0
- manigent/web/frontend/src/hooks/useWebSocket.briefTab.test.tsx +148 -0
- manigent/web/frontend/src/hooks/useWebSocket.channelThreads.test.tsx +82 -0
- manigent/web/frontend/src/hooks/useWebSocket.hostSync.test.tsx +92 -0
- manigent/web/frontend/src/hooks/useWebSocket.hub.test.tsx +114 -0
- manigent/web/frontend/src/hooks/useWebSocket.labelSync.test.tsx +168 -0
- manigent/web/frontend/src/hooks/useWebSocket.plan.test.tsx +168 -0
- manigent/web/frontend/src/hooks/useWebSocket.reconnect.test.tsx +166 -0
- manigent/web/frontend/src/hooks/useWebSocket.runnerVersions.test.tsx +167 -0
- manigent/web/frontend/src/hooks/useWebSocket.ts +495 -0
- manigent/web/frontend/src/hooks/useWindowFileDropGuard.ts +33 -0
- manigent/web/frontend/src/landing.tsx +11 -0
- manigent/web/frontend/src/main.tsx +17 -0
- manigent/web/frontend/src/private-beta.tsx +10 -0
- manigent/web/frontend/src/public.tsx +42 -0
- manigent/web/frontend/src/queryClient.ts +16 -0
- manigent/web/frontend/src/stores/activeWorkStore.ts +88 -0
- manigent/web/frontend/src/stores/announcementStore.test.ts +217 -0
- manigent/web/frontend/src/stores/announcementStore.ts +169 -0
- manigent/web/frontend/src/stores/authStore.multiSession.test.ts +304 -0
- manigent/web/frontend/src/stores/authStore.test.ts +235 -0
- manigent/web/frontend/src/stores/authStore.ts +693 -0
- manigent/web/frontend/src/stores/deskLabelViewStore.test.ts +162 -0
- manigent/web/frontend/src/stores/deskLabelViewStore.ts +234 -0
- manigent/web/frontend/src/stores/deskLinkStore.ts +54 -0
- manigent/web/frontend/src/stores/deskStore.test.ts +53 -0
- manigent/web/frontend/src/stores/deskStore.ts +93 -0
- manigent/web/frontend/src/stores/heldPostsStore.ts +78 -0
- manigent/web/frontend/src/stores/mcpAuthStore.ts +52 -0
- manigent/web/frontend/src/stores/modelSelectionStore.ts +33 -0
- manigent/web/frontend/src/stores/perUserStores.ts +79 -0
- manigent/web/frontend/src/stores/runnerVersionStore.test.ts +81 -0
- manigent/web/frontend/src/stores/runnerVersionStore.ts +60 -0
- manigent/web/frontend/src/stores/skillAuthStore.ts +54 -0
- manigent/web/frontend/src/stores/switchReset.test.ts +236 -0
- manigent/web/frontend/src/stores/tokenExp.ts +32 -0
- manigent/web/frontend/src/stores/uiStore.ts +186 -0
- manigent/web/frontend/src/stores/unreadStore.ts +204 -0
- manigent/web/frontend/src/stores/unsavedGuard.ts +22 -0
- manigent/web/frontend/src/styles/design/fonts/JetBrainsMono-Latin.woff2 +0 -0
- manigent/web/frontend/src/styles/design/fonts/Nunito-Latin.woff2 +0 -0
- manigent/web/frontend/src/styles/design/fonts/Nunito-LatinExt.woff2 +0 -0
- manigent/web/frontend/src/styles/design/tokens.css +160 -0
- manigent/web/frontend/src/styles/homepage.css +242 -0
- manigent/web/frontend/src/styles/index.css +126 -0
- manigent/web/frontend/src/styles/landing.css +52 -0
- manigent/web/frontend/src/test/authFixtures.ts +154 -0
- manigent/web/frontend/src/test/fetchHarness.ts +203 -0
- manigent/web/frontend/src/test/fixtures/channelThreads.smoke.json +42 -0
- manigent/web/frontend/src/test/hubFixtures.ts +212 -0
- manigent/web/frontend/src/test/queryWrapper.tsx +9 -0
- manigent/web/frontend/src/test/suiteHygiene.test.ts +212 -0
- manigent/web/frontend/src/types/channelThreadName.test.ts +16 -0
- manigent/web/frontend/src/types/index.ts +903 -0
- manigent/web/frontend/src/utils/agentAccessCopy.test.ts +53 -0
- manigent/web/frontend/src/utils/agentAccessCopy.ts +231 -0
- manigent/web/frontend/src/utils/agentDisplay.ts +81 -0
- manigent/web/frontend/src/utils/briefSchedule.ts +25 -0
- manigent/web/frontend/src/utils/channelThreads.test.ts +109 -0
- manigent/web/frontend/src/utils/channelThreads.ts +179 -0
- manigent/web/frontend/src/utils/chatroomDisplay.ts +11 -0
- manigent/web/frontend/src/utils/deskLinks.test.ts +155 -0
- manigent/web/frontend/src/utils/deskLinks.ts +115 -0
- manigent/web/frontend/src/utils/deskRecipient.ts +29 -0
- manigent/web/frontend/src/utils/formatDate.ts +102 -0
- manigent/web/frontend/src/utils/frontDesk.ts +65 -0
- manigent/web/frontend/src/utils/hubChannelView.test.ts +178 -0
- manigent/web/frontend/src/utils/hubChannelView.ts +307 -0
- manigent/web/frontend/src/utils/hubDelivery.test.ts +105 -0
- manigent/web/frontend/src/utils/hubDelivery.ts +137 -0
- manigent/web/frontend/src/utils/hubDisplay.test.ts +157 -0
- manigent/web/frontend/src/utils/hubDisplay.ts +221 -0
- manigent/web/frontend/src/utils/hubThread.test.ts +184 -0
- manigent/web/frontend/src/utils/hubThread.ts +247 -0
- manigent/web/frontend/src/utils/labelErrors.test.ts +127 -0
- manigent/web/frontend/src/utils/labelErrors.ts +123 -0
- manigent/web/frontend/src/utils/labelView.test.ts +846 -0
- manigent/web/frontend/src/utils/labelView.ts +760 -0
- manigent/web/frontend/src/utils/legalUrls.ts +11 -0
- manigent/web/frontend/src/utils/messageSender.test.ts +32 -0
- manigent/web/frontend/src/utils/messageSender.ts +29 -0
- manigent/web/frontend/src/utils/oauthScopeCopy.ts +73 -0
- manigent/web/frontend/src/utils/personalize.ts +49 -0
- manigent/web/frontend/src/utils/reachableAgents.test.ts +36 -0
- manigent/web/frontend/src/utils/reachableAgents.ts +24 -0
- manigent/web/frontend/src/utils/recencyBuckets.ts +61 -0
- manigent/web/frontend/src/utils/roomTrust.test.ts +94 -0
- manigent/web/frontend/src/utils/roomTrust.ts +111 -0
- manigent/web/frontend/src/utils/snippetHighlight.test.ts +63 -0
- manigent/web/frontend/src/utils/snippetHighlight.ts +42 -0
- manigent/web/frontend/src/utils/sopRecipient.ts +37 -0
- manigent/web/frontend/src/utils/sopRequest.test.ts +91 -0
- manigent/web/frontend/src/utils/sopRequest.ts +68 -0
- manigent/web/frontend/src/utils/sopSchedule.ts +26 -0
- manigent/web/frontend/src/utils/sopSection.test.ts +148 -0
- manigent/web/frontend/src/utils/sopSection.ts +143 -0
- manigent/web/frontend/src/utils/textSearch.test.ts +60 -0
- manigent/web/frontend/src/utils/textSearch.ts +43 -0
- manigent/web/frontend/src/utils/thoughtPartner.ts +26 -0
- manigent/web/frontend/src/utils/threadName.test.ts +131 -0
- manigent/web/frontend/src/utils/threadName.ts +122 -0
- manigent/web/frontend/src/utils/ticketView.test.ts +296 -0
- manigent/web/frontend/src/utils/ticketView.ts +175 -0
- manigent/web/frontend/src/utils/todoAttachments.desiredState.test.ts +180 -0
- manigent/web/frontend/src/utils/todoAttachments.ts +126 -0
- manigent/web/frontend/src/utils/todoDraft.test.ts +84 -0
- manigent/web/frontend/src/utils/todoDraft.ts +46 -0
- manigent/web/frontend/src/utils/todoSearch.test.ts +82 -0
- manigent/web/frontend/src/utils/todoSearch.ts +43 -0
- manigent/web/frontend/src/utils/versionMatch.test.ts +295 -0
- manigent/web/frontend/src/utils/versionMatch.ts +245 -0
- manigent/web/frontend/src/vite-env.d.ts +1 -0
- manigent/web/frontend/tailwind.config.js +86 -0
- manigent/web/frontend/tos.html +188 -0
- manigent/web/frontend/tsconfig.dts.json +25 -0
- manigent/web/frontend/tsconfig.json +26 -0
- manigent/web/frontend/tsconfig.node.json +11 -0
- manigent/web/frontend/vite.config.ts +41 -0
- manigent/web/frontend/vitest.config.ts +16 -0
- manigent/ws_edge/app.py +514 -0
- manigent/ws_edge/auth.py +104 -0
- manigent/ws_edge/link.py +282 -0
- manigent/ws_edge/registry.py +206 -0
- manigent/ws_edge/terminal_relay.py +269 -0
- manigent_server-0.1.0.dist-info/METADATA +138 -0
- manigent_server-0.1.0.dist-info/RECORD +1004 -0
- manigent_server-0.1.0.dist-info/WHEEL +4 -0
- manigent_server-0.1.0.dist-info/entry_points.txt +2 -0
- manigent_server-0.1.0.dist-info/licenses/LICENSE +68 -0
|
@@ -0,0 +1,841 @@
|
|
|
1
|
+
import { useEffect, useMemo, useRef, useState, ChangeEvent } from 'react'
|
|
2
|
+
import { useNavigate, useParams, useSearchParams } from 'react-router-dom'
|
|
3
|
+
import { FileText, Paperclip, Clock, GraduationCap, X, Send, Loader2, Trash2 } from 'lucide-react'
|
|
4
|
+
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'
|
|
5
|
+
import { useUIStore } from '../../stores/uiStore'
|
|
6
|
+
import { useAuthStore } from '../../stores/authStore'
|
|
7
|
+
import { useUnsavedGuard } from '../../stores/unsavedGuard'
|
|
8
|
+
import { useAgents } from '../../hooks/useAgents'
|
|
9
|
+
import { useChatroom, useUserProjects } from '../../hooks/useProjects'
|
|
10
|
+
import { useRoomTrust } from '../../hooks/useRoomTrust'
|
|
11
|
+
import { useSetRoomFlow } from '../../hooks/useAgentAccess'
|
|
12
|
+
import { useRenameProject } from '../../hooks/useRenameProject'
|
|
13
|
+
import { useDeleteProject } from '../../hooks/useDeleteProject'
|
|
14
|
+
import { useActiveWorkStore, selectActiveParticipants } from '../../stores/activeWorkStore'
|
|
15
|
+
import { useModelSelectionStore } from '../../stores/modelSelectionStore'
|
|
16
|
+
import { useModelConfigs } from '../../hooks/useModelConfigs'
|
|
17
|
+
import { getMessages } from '../../api/endpoints'
|
|
18
|
+
import { sendDMMessage, createDMThread, createFDThread } from '../../api/endpoints/dm'
|
|
19
|
+
import { hubError } from '../../api/endpoints/hub'
|
|
20
|
+
import { accessErrorText, FLOW_COPY } from '../../utils/agentAccessCopy'
|
|
21
|
+
import { outsideFileNames } from '../../utils/roomTrust'
|
|
22
|
+
import RoomFlowStrip from '../chatroom/RoomFlowStrip'
|
|
23
|
+
import { useHeldPostsStore } from '../../stores/heldPostsStore'
|
|
24
|
+
import { HeldNotices } from '../chatroom/HeldNotice'
|
|
25
|
+
import { useFiles } from '../../hooks/useFiles'
|
|
26
|
+
import { useMessageDeepLink } from '../../hooks/useMessageDeepLink'
|
|
27
|
+
import PromptEditor, { type PromptEditorHandle } from '../composer/PromptEditor'
|
|
28
|
+
import { useMessageAttachments } from '../../hooks/useMessageAttachments'
|
|
29
|
+
import { useFileDropzone } from '../../hooks/useFileDropzone'
|
|
30
|
+
import { AgentStatus, isChatFileEvent, isScheduledDMProject } from '../../types'
|
|
31
|
+
import { displayName as agentDisplayName } from '../../utils/agentDisplay'
|
|
32
|
+
import { buildPersonalizeMessage, isAssistantAgent } from '../../utils/personalize'
|
|
33
|
+
import Loading from '../common/Loading'
|
|
34
|
+
import Avatar from '../common/Avatar'
|
|
35
|
+
import ModelSelector from '../common/ModelSelector'
|
|
36
|
+
import MessageList from '../chatroom/MessageList'
|
|
37
|
+
import StagedAttachments from '../chatroom/StagedAttachments'
|
|
38
|
+
import DMZeroState from './DMZeroState'
|
|
39
|
+
import PersonalizeModal, { type PersonalizeResult } from './PersonalizeModal'
|
|
40
|
+
import { buildRecipientStatusIndex } from '../chatroom/recipientStatus'
|
|
41
|
+
import FileList from '../files/FileList'
|
|
42
|
+
import Overlay from '../common/Overlay'
|
|
43
|
+
import DropOverlay from '../common/DropOverlay'
|
|
44
|
+
import ResizeHandle from '../common/ResizeHandle'
|
|
45
|
+
import ScheduleMessageModal from '../scheduled/ScheduleMessageModal'
|
|
46
|
+
import ClearHistoryButton from '../common/ClearHistoryButton'
|
|
47
|
+
import CollapsibleHeader from '../common/CollapsibleHeader'
|
|
48
|
+
import InlineEditableTitle from '../common/InlineEditableTitle'
|
|
49
|
+
import HomeFolderBrowser from '../homefs/HomeFolderBrowser'
|
|
50
|
+
import AgentViewActions from '../agent/AgentViewActions'
|
|
51
|
+
import AgentNameLink from '../agent/AgentNameLink'
|
|
52
|
+
|
|
53
|
+
// DM chat view — ChatGPT/Claude thread model, N threads per agent for BOTH own
|
|
54
|
+
// and foreign (Front Desk) agents. Routes:
|
|
55
|
+
// /dm/:agentName → a fresh, ephemeral "New chat" draft (nothing
|
|
56
|
+
// created until the first send), for own OR
|
|
57
|
+
// foreign agents.
|
|
58
|
+
// /dm/:agentName/:threadId → an existing thread project bound directly to
|
|
59
|
+
// `threadId` (own-agent DM thread or foreign FD
|
|
60
|
+
// thread — both requester-owned).
|
|
61
|
+
// Either way the `user-communication` chatroom IS the DM thread. The first send
|
|
62
|
+
// from a draft mints an own-DM thread (createDMThread) for own agents or an FD
|
|
63
|
+
// thread (createFDThread, tunnel-wired) for foreign agents.
|
|
64
|
+
export default function DMChatView() {
|
|
65
|
+
const { agentName = '', threadId } = useParams<{ agentName: string; threadId?: string }>()
|
|
66
|
+
const navigate = useNavigate()
|
|
67
|
+
const [searchParams, setSearchParams] = useSearchParams()
|
|
68
|
+
const queryClient = useQueryClient()
|
|
69
|
+
const {
|
|
70
|
+
isMobileRightPanelOpen,
|
|
71
|
+
openMobileRightPanel,
|
|
72
|
+
closeMobileRightPanel,
|
|
73
|
+
rightPanelWidth,
|
|
74
|
+
setRightPanelWidth,
|
|
75
|
+
setRailContext,
|
|
76
|
+
} = useUIStore()
|
|
77
|
+
const user = useAuthStore((state) => state.user)
|
|
78
|
+
const { data: allAgents, isLoading: agentsLoading } = useAgents()
|
|
79
|
+
|
|
80
|
+
const fileInputRef = useRef<HTMLInputElement>(null)
|
|
81
|
+
const [showScheduleModal, setShowScheduleModal] = useState(false)
|
|
82
|
+
const [showPersonalizeModal, setShowPersonalizeModal] = useState(false)
|
|
83
|
+
|
|
84
|
+
const agent = useMemo(
|
|
85
|
+
() => allAgents?.find((a) => a.name === agentName),
|
|
86
|
+
[allAgents, agentName]
|
|
87
|
+
)
|
|
88
|
+
const agentLabel = agent ? agentDisplayName(agent, user ?? null) : agentName
|
|
89
|
+
|
|
90
|
+
const isOwnAgent = !!user && !!agent && agent.registered_by === user.id
|
|
91
|
+
// The user's own assistant gets the method-picker modal; every other agent
|
|
92
|
+
// keeps today's role-anchored deep-research prefill (buildPersonalizeMessage).
|
|
93
|
+
const isAssistant = isAssistantAgent(agent, user)
|
|
94
|
+
// No thread in the URL = a fresh ephemeral "New chat" draft (own OR foreign
|
|
95
|
+
// agent): the draft lives in local state only; NO project row is created
|
|
96
|
+
// until the first message is sent. Abandon it → no trace.
|
|
97
|
+
const isNewChatDraft = !!user && !!agent && !threadId
|
|
98
|
+
|
|
99
|
+
// Threads (own DM or foreign FD) bind directly to the `threadId` in the URL;
|
|
100
|
+
// a new-chat draft resolves to no project yet.
|
|
101
|
+
const dmProjectId = threadId ?? ''
|
|
102
|
+
const chatroomName = dmProjectId ? 'user-communication' : ''
|
|
103
|
+
// A draft renders immediately; a bound thread comes straight from the URL.
|
|
104
|
+
const projectLoading = agentsLoading || (!isNewChatDraft && !dmProjectId)
|
|
105
|
+
|
|
106
|
+
// Header title = the thread project's display_name (item e). Read from the
|
|
107
|
+
// SAME user-projects cache the sidebar row reads, so the auto-title flips
|
|
108
|
+
// header + row together on one list refetch. Drafts/foreign fall back.
|
|
109
|
+
const { data: userProjects } = useUserProjects()
|
|
110
|
+
// A search hit links a host-side Hub Request (a Front Desk project) here,
|
|
111
|
+
// so its bodies follow the same trust rule as ChatroomView: the whole room,
|
|
112
|
+
// and per author (another account's agent, a requester).
|
|
113
|
+
const trust = useRoomTrust(dmProjectId, chatroomName)
|
|
114
|
+
const threadProject = useMemo(
|
|
115
|
+
() => (threadId ? userProjects?.find((p) => p.id === threadId) : undefined),
|
|
116
|
+
[userProjects, threadId],
|
|
117
|
+
)
|
|
118
|
+
// The header title is always the agent; the thread's own name (once it has
|
|
119
|
+
// one) sits on the line under it and stays click-to-rename.
|
|
120
|
+
const threadName = isNewChatDraft ? '' : threadProject?.display_name || ''
|
|
121
|
+
// Same mutation as the project page: a DM thread IS a Project, so the header
|
|
122
|
+
// rename is one hook and one endpoint on both surfaces.
|
|
123
|
+
const renameThread = useRenameProject()
|
|
124
|
+
// A DM thread dedicated to scheduled messages ({username}-dm-{short}-schedule).
|
|
125
|
+
const isScheduledThread = !!threadProject && isScheduledDMProject(threadProject)
|
|
126
|
+
|
|
127
|
+
// Settings/Delete agent live on the agent view (/dm/:agentName, no thread),
|
|
128
|
+
// not inside a conversation. Owner-only; the assistant is never deletable.
|
|
129
|
+
const showAgentActions = isOwnAgent && !!agent && !threadId
|
|
130
|
+
// The home-folder navigator replaces the transcript on the agent view
|
|
131
|
+
// (`?view=home`), so the settings page can link straight to it.
|
|
132
|
+
const homeFolderOpen = showAgentActions && agent.home_folder_browsable === true && searchParams.get('view') === 'home'
|
|
133
|
+
|
|
134
|
+
// Conversation delete moved here from the DMs rail row. useDeleteProject
|
|
135
|
+
// drops back to the agent's new-chat draft when the open thread goes.
|
|
136
|
+
const deleteThreadMutation = useDeleteProject()
|
|
137
|
+
const canDeleteThread = !!threadProject && !threadProject.is_viewer
|
|
138
|
+
// The thread's owner may stop and resume outside messages, as in the room.
|
|
139
|
+
const isThreadOwner = canDeleteThread && !!user && threadProject.created_by === user.id
|
|
140
|
+
const { data: chatroom } = useChatroom(dmProjectId, chatroomName)
|
|
141
|
+
const resumeFlow = useSetRoomFlow(dmProjectId, chatroomName)
|
|
142
|
+
const handleDeleteThread = () => {
|
|
143
|
+
const title = threadName || `chat with ${agentLabel}`
|
|
144
|
+
if (!window.confirm(`Delete conversation "${title}"? This cannot be undone.`)) return
|
|
145
|
+
deleteThreadMutation.mutate(dmProjectId)
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
// Fetch messages
|
|
149
|
+
const { data: messages, isLoading: messagesLoading } = useQuery({
|
|
150
|
+
queryKey: ['messages', dmProjectId, chatroomName],
|
|
151
|
+
queryFn: () => getMessages(dmProjectId, chatroomName),
|
|
152
|
+
enabled: !!dmProjectId,
|
|
153
|
+
refetchInterval: 5000,
|
|
154
|
+
})
|
|
155
|
+
|
|
156
|
+
// Processing-agent ids come from the activeWorkStore, driven by the
|
|
157
|
+
// ACTIVE_WORK_CHANGE WebSocket envelope (bootstrapped via /me/active-work).
|
|
158
|
+
const processingAgentIds = useActiveWorkStore(selectActiveParticipants(dmProjectId, chatroomName))
|
|
159
|
+
|
|
160
|
+
// Fetch files
|
|
161
|
+
const { data: files, isLoading: filesLoading } = useFiles(dmProjectId, chatroomName)
|
|
162
|
+
// The Files sidebar follows the per-author rule, as in ChatroomView: a file
|
|
163
|
+
// another account's agent posted opens untrusted (no "Open in new tab").
|
|
164
|
+
const outsideFiles = useMemo(
|
|
165
|
+
() => outsideFileNames(chatroom, trust.ownerId, (files ?? []).map((f) => f.name), (messages ?? []).filter(isChatFileEvent)),
|
|
166
|
+
[chatroom, trust.ownerId, files, messages],
|
|
167
|
+
)
|
|
168
|
+
// `?msg=` deep-link target from ⌘K message search, consumed and cleared the
|
|
169
|
+
// same way this view already handles `?draft=`.
|
|
170
|
+
const { targetMessageId, clearTarget } = useMessageDeepLink()
|
|
171
|
+
|
|
172
|
+
const {
|
|
173
|
+
stagedFiles,
|
|
174
|
+
files: attachmentFiles,
|
|
175
|
+
addFiles,
|
|
176
|
+
removeStagedFile,
|
|
177
|
+
clearStagedFiles,
|
|
178
|
+
attachmentError,
|
|
179
|
+
} = useMessageAttachments()
|
|
180
|
+
|
|
181
|
+
// Per-request model override (spec #3): the resolved active config for this
|
|
182
|
+
// DM's target agent — the transient selector pick, else the agent's backend
|
|
183
|
+
// default — sent as `model_config_name` so the override is explicit and
|
|
184
|
+
// verifiable. Fetched only for OWN agents (foreign FD agents 403 on the
|
|
185
|
+
// configs route + get no selector), so a foreign DM sends nothing ⇒ the
|
|
186
|
+
// server silently uses that agent's own default.
|
|
187
|
+
const { data: modelConfigData } = useModelConfigs(isOwnAgent ? agent?.id : undefined)
|
|
188
|
+
const selectedConfigName = useModelSelectionStore((s) => (agent ? s.byAgent[agent.id] : undefined))
|
|
189
|
+
const modelConfigName = selectedConfigName ?? modelConfigData?.default ?? undefined
|
|
190
|
+
|
|
191
|
+
// Send into an existing thread / FD project.
|
|
192
|
+
const recordSend = useHeldPostsStore((s) => s.record)
|
|
193
|
+
const beginSend = useHeldPostsStore((s) => s.begin)
|
|
194
|
+
const endSend = useHeldPostsStore((s) => s.end)
|
|
195
|
+
// The send carries its own thread: the view stays mounted across threads, so
|
|
196
|
+
// a send that settles after the user switched must record, refetch and report
|
|
197
|
+
// against the thread it was posted to, never the one now open.
|
|
198
|
+
type SendVars = { projectId: string; room: string; content: string; files: File[] }
|
|
199
|
+
const sendMessageMutation = useMutation({
|
|
200
|
+
onMutate: (vars: SendVars) => beginSend(vars.projectId, vars.room, vars.content),
|
|
201
|
+
onSettled: (_r, _e, vars) => endSend(vars.projectId, vars.room, vars.content),
|
|
202
|
+
mutationFn: (vars: SendVars) =>
|
|
203
|
+
sendDMMessage(vars.projectId, vars.room, vars.content, vars.files, modelConfigName),
|
|
204
|
+
onSuccess: (result, vars) => {
|
|
205
|
+
// 202: stored and delivered later. Shown as held; never resent.
|
|
206
|
+
recordSend(vars.projectId, vars.room, vars.content, result)
|
|
207
|
+
// The composer stayed disabled while this send was pending (in any
|
|
208
|
+
// thread), so what it holds is still this send's text and files.
|
|
209
|
+
clearComposer()
|
|
210
|
+
clearStagedFiles()
|
|
211
|
+
queryClient.invalidateQueries({ queryKey: ['messages', vars.projectId, vars.room] })
|
|
212
|
+
queryClient.invalidateQueries({ queryKey: ['files', vars.projectId, vars.room] })
|
|
213
|
+
},
|
|
214
|
+
})
|
|
215
|
+
|
|
216
|
+
// (item d) First send from a "New chat" draft materializes a NEW thread
|
|
217
|
+
// project, then posts the message into it, then binds the view to the real
|
|
218
|
+
// thread and surfaces the row at the top of DM / Chats. A per-draft
|
|
219
|
+
// idempotency key guards the double-send race (two creates → one thread).
|
|
220
|
+
const draftKeyRef = useRef<string>()
|
|
221
|
+
if (!draftKeyRef.current) draftKeyRef.current = crypto.randomUUID()
|
|
222
|
+
// Regenerate the key whenever a FRESH draft begins (no threadId), so a 2nd
|
|
223
|
+
// "New chat" with the same agent can't reuse the prior draft's key. Without
|
|
224
|
+
// this, RRv6 renders the sibling `/dm/:agentName` and `/dm/:agentName/:threadId`
|
|
225
|
+
// routes at the same tree position and PRESERVES this instance across
|
|
226
|
+
// navigation — leaving `draftKeyRef` holding the stale key, which the
|
|
227
|
+
// backend's (user.id, key) idempotency cache would HIT and silently merge the
|
|
228
|
+
// new message into the prior thread (breaking the N-per-agent model).
|
|
229
|
+
// Correctness must NOT depend on remount behavior, so we reset explicitly.
|
|
230
|
+
useEffect(() => {
|
|
231
|
+
if (!threadId) draftKeyRef.current = crypto.randomUUID()
|
|
232
|
+
}, [threadId, agentName])
|
|
233
|
+
const createThreadMutation = useMutation({
|
|
234
|
+
mutationFn: async (vars: { content: string; files: File[] }): Promise<string> => {
|
|
235
|
+
// Own agents mint an own-DM thread; foreign agents mint a tunnel-wired
|
|
236
|
+
// Front Desk thread. Both are requester-owned, N-per-agent. Staged files
|
|
237
|
+
// ride the first message into the freshly-minted thread.
|
|
238
|
+
const thread = isOwnAgent
|
|
239
|
+
? await createDMThread(agentName, draftKeyRef.current)
|
|
240
|
+
: await createFDThread(agentName, draftKeyRef.current)
|
|
241
|
+
const sent = await sendDMMessage(thread.id, 'user-communication', vars.content, vars.files, modelConfigName)
|
|
242
|
+
recordSend(thread.id, 'user-communication', vars.content, sent)
|
|
243
|
+
return thread.id
|
|
244
|
+
},
|
|
245
|
+
onSuccess: (newThreadId) => {
|
|
246
|
+
clearComposer()
|
|
247
|
+
clearStagedFiles()
|
|
248
|
+
queryClient.invalidateQueries({ queryKey: ['user-projects'] })
|
|
249
|
+
queryClient.invalidateQueries({ queryKey: ['all-projects'] })
|
|
250
|
+
// Surface the freshly-created thread in the rail: switch to the DMs
|
|
251
|
+
// context so the user sees DMs › agent › (new thread) instead of staying
|
|
252
|
+
// on whatever context they launched the draft from (usually Agents).
|
|
253
|
+
setRailContext('dms')
|
|
254
|
+
navigate(`/dm/${encodeURIComponent(agentName)}/${newThreadId}`, { replace: true })
|
|
255
|
+
},
|
|
256
|
+
})
|
|
257
|
+
|
|
258
|
+
const isSending = sendMessageMutation.isPending || createThreadMutation.isPending
|
|
259
|
+
// A refused send keeps the draft (the composer clears only on success) and
|
|
260
|
+
// says why in the agent-access copy; a stopped room offers its owner Resume.
|
|
261
|
+
// Only this thread's refusal is shown: a send posted from another thread
|
|
262
|
+
// keeps its error to itself, and so does its Resume.
|
|
263
|
+
const sendError =
|
|
264
|
+
(sendMessageMutation.variables?.projectId === dmProjectId ? sendMessageMutation.error : null) ??
|
|
265
|
+
(isNewChatDraft ? createThreadMutation.error : null)
|
|
266
|
+
const sendErrorBody = sendError ? hubError(sendError) : null
|
|
267
|
+
const sendErrorText = sendError ? accessErrorText(sendErrorBody) ?? sendError.message : null
|
|
268
|
+
const canResume = sendErrorBody?.code === 'room_flow_stopped' && isThreadOwner
|
|
269
|
+
// The view stays mounted across threads (see the draft key above), so a
|
|
270
|
+
// settled refusal is cleared on a switch. A send still in flight is NOT
|
|
271
|
+
// reset: reset() only detaches the observer, so the composer would re-enable
|
|
272
|
+
// while the old send keeps running and its onSuccess later wipes whatever
|
|
273
|
+
// was typed in the new thread. It keeps the composer disabled until it
|
|
274
|
+
// settles; the per-thread gate on `sendError` above hides its outcome here.
|
|
275
|
+
const sendStateRef = useRef({ send: sendMessageMutation, create: createThreadMutation })
|
|
276
|
+
sendStateRef.current = { send: sendMessageMutation, create: createThreadMutation }
|
|
277
|
+
useEffect(() => {
|
|
278
|
+
const { send, create } = sendStateRef.current
|
|
279
|
+
if (!send.isPending) send.reset()
|
|
280
|
+
if (!create.isPending) create.reset()
|
|
281
|
+
}, [threadId, agentName])
|
|
282
|
+
|
|
283
|
+
// Drag files onto the composer card → same staging path as the paperclip.
|
|
284
|
+
const { isDragging, dragHandlers } = useFileDropzone({
|
|
285
|
+
onFiles: addFiles,
|
|
286
|
+
disabled: isSending,
|
|
287
|
+
})
|
|
288
|
+
|
|
289
|
+
const setGuardDirty = useUnsavedGuard((s) => s.setDirty)
|
|
290
|
+
|
|
291
|
+
// Starts empty: the `?draft=` deep-link is applied solely by the effect
|
|
292
|
+
// below, which routes through prefillComposer (and so keeps the
|
|
293
|
+
// don't-clobber confirm). Seeding here too would double-apply it.
|
|
294
|
+
const [dmMessage, setDmMessage] = useState('')
|
|
295
|
+
const dmEditorRef = useRef<PromptEditorHandle>(null)
|
|
296
|
+
// Mirror for the prefill guard, which must read the live draft.
|
|
297
|
+
const dmMessageRef = useRef('')
|
|
298
|
+
|
|
299
|
+
// Focus the composer on selection (agent DM or a specific thread) so the user
|
|
300
|
+
// can type immediately. Re-fires when switching agents/threads; the
|
|
301
|
+
// projectLoading dep ensures it runs once the composer has mounted.
|
|
302
|
+
useEffect(() => {
|
|
303
|
+
if (!projectLoading) dmEditorRef.current?.focusEnd()
|
|
304
|
+
}, [agentName, dmProjectId, projectLoading])
|
|
305
|
+
|
|
306
|
+
// Route the send: a draft creates-then-sends (item d); a bound thread/FD
|
|
307
|
+
// project sends directly. The pending gate blocks a double-submit either way.
|
|
308
|
+
const submitMessage = () => {
|
|
309
|
+
const content = dmMessage.trim()
|
|
310
|
+
if ((!content && stagedFiles.length === 0) || isSending) return
|
|
311
|
+
// Never ship a half-filled template to an agent.
|
|
312
|
+
if (dmEditorRef.current?.nudgeEmpty()) return
|
|
313
|
+
const vars = { content, files: attachmentFiles }
|
|
314
|
+
// The draft stays until the send succeeds (the editor is disabled while
|
|
315
|
+
// it is pending), so a refused post is never lost.
|
|
316
|
+
if (isNewChatDraft) {
|
|
317
|
+
createThreadMutation.mutate(vars)
|
|
318
|
+
} else if (dmProjectId) {
|
|
319
|
+
sendMessageMutation.mutate({ ...vars, projectId: dmProjectId, room: chatroomName })
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
function clearComposer() {
|
|
324
|
+
setDmMessage('')
|
|
325
|
+
dmMessageRef.current = ''
|
|
326
|
+
dmEditorRef.current?.clear()
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
const handleSendMessage = (e: React.FormEvent<HTMLFormElement>) => {
|
|
330
|
+
e.preventDefault()
|
|
331
|
+
submitMessage()
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
const handleFileSelect = () => {
|
|
335
|
+
fileInputRef.current?.click()
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
// Single source of truth for "write the composer": sets the draft and focuses
|
|
339
|
+
// the textarea. If a different non-empty draft already exists, confirm before
|
|
340
|
+
// replacing so we never silently clobber what the user was typing. Shared by
|
|
341
|
+
// the zero-state sample cards and the personalize CTA.
|
|
342
|
+
const prefillComposer = (text: string) => {
|
|
343
|
+
const current = dmMessageRef.current.trim()
|
|
344
|
+
if (
|
|
345
|
+
current &&
|
|
346
|
+
current !== text.trim() &&
|
|
347
|
+
!window.confirm('Replace your current draft?')
|
|
348
|
+
) {
|
|
349
|
+
return
|
|
350
|
+
}
|
|
351
|
+
dmEditorRef.current?.setPlain(text, true)
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
// Hover/focus counterpart to prefillComposer, for the zero-state idea rows.
|
|
355
|
+
// Pure decoration: no draft write, and so no replace-your-draft confirm —
|
|
356
|
+
// the ghost is gated on `data-blank='1'` in CSS, so a draft simply hides it.
|
|
357
|
+
const previewInComposer = (text: string | null) => {
|
|
358
|
+
dmEditorRef.current?.setGhost(text)
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
// Apply a `?draft=...` deep-link into the composer, then strip the param so
|
|
362
|
+
// back-nav / refresh doesn't re-prefill. Applying here (not only in the
|
|
363
|
+
// useState initializer) also covers SPA navigations that DON'T remount this
|
|
364
|
+
// view — clicking a sidebar `+` while already on the assistant DM, or
|
|
365
|
+
// switching into a draft URL from another agent. prefillComposer confirms
|
|
366
|
+
// before overwriting a draft you've already started typing.
|
|
367
|
+
useEffect(() => {
|
|
368
|
+
const draft = searchParams.get('draft')
|
|
369
|
+
if (!draft) return
|
|
370
|
+
prefillComposer(draft)
|
|
371
|
+
const next = new URLSearchParams(searchParams)
|
|
372
|
+
next.delete('draft')
|
|
373
|
+
setSearchParams(next, { replace: true })
|
|
374
|
+
// prefillComposer is recreated each render; the `draft` guard makes re-runs
|
|
375
|
+
// a no-op, so it's intentionally omitted from the dep list.
|
|
376
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
377
|
+
}, [searchParams, setSearchParams])
|
|
378
|
+
|
|
379
|
+
// Personalize sends (or prefills) through the same composer, so it waits for
|
|
380
|
+
// a pending send like Send does: after a thread switch that send still holds
|
|
381
|
+
// its staged files, and a send here would carry them into this thread.
|
|
382
|
+
const handlePersonalize = () => {
|
|
383
|
+
if (!user || !agent || isSending) return
|
|
384
|
+
// Assistant → open the method-picker modal; workers → today's prefill.
|
|
385
|
+
if (isAssistant) {
|
|
386
|
+
setShowPersonalizeModal(true)
|
|
387
|
+
return
|
|
388
|
+
}
|
|
389
|
+
prefillComposer(buildPersonalizeMessage(agent, agentLabel, isAssistant))
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
// Route a confirmed personalize method to a send. 'upload' needs a file
|
|
393
|
+
// (staged via the composer paperclip), so it prefills the composer body and
|
|
394
|
+
// opens the native file picker instead of sending; 'export'/'questions' send
|
|
395
|
+
// the templated DM straight away, reusing the existing send path (create the
|
|
396
|
+
// thread first if this is a fresh "New chat" draft, else send into the open one).
|
|
397
|
+
const handlePersonalizeConfirm = (r: PersonalizeResult) => {
|
|
398
|
+
setShowPersonalizeModal(false)
|
|
399
|
+
if (isSending) return
|
|
400
|
+
if (r.method === 'upload') {
|
|
401
|
+
prefillComposer(r.body)
|
|
402
|
+
fileInputRef.current?.click()
|
|
403
|
+
return
|
|
404
|
+
}
|
|
405
|
+
const vars = { content: r.body, files: attachmentFiles }
|
|
406
|
+
if (isNewChatDraft) {
|
|
407
|
+
createThreadMutation.mutate(vars)
|
|
408
|
+
} else if (dmProjectId) {
|
|
409
|
+
sendMessageMutation.mutate({ ...vars, projectId: dmProjectId, room: chatroomName })
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
// Personalize button tooltip. The control is icon-only in the toolbar, so the
|
|
414
|
+
// tooltip carries the label AND the payoff — it is the only place the words
|
|
415
|
+
// appear once the DM has messages in it (the zero state still shows the full
|
|
416
|
+
// gradient CTA).
|
|
417
|
+
const personalizeHint = isAssistant
|
|
418
|
+
? 'Personalize — teach it who you are and how you work'
|
|
419
|
+
: `Train as expert — deep-research @${agentLabel} into your field`
|
|
420
|
+
|
|
421
|
+
const handleFileChange = (e: ChangeEvent<HTMLInputElement>) => {
|
|
422
|
+
if (e.target.files && e.target.files.length > 0) {
|
|
423
|
+
addFiles(e.target.files)
|
|
424
|
+
}
|
|
425
|
+
e.target.value = ''
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
// Guard against navigating away with an unsent draft or staged attachments.
|
|
429
|
+
const isDirty = dmMessage.trim().length > 0 || stagedFiles.length > 0
|
|
430
|
+
useEffect(() => {
|
|
431
|
+
setGuardDirty(isDirty, 'Discard your unsent message and attachments?')
|
|
432
|
+
return () => setGuardDirty(false)
|
|
433
|
+
}, [isDirty, setGuardDirty])
|
|
434
|
+
useEffect(() => {
|
|
435
|
+
if (!isDirty) return
|
|
436
|
+
const handler = (e: BeforeUnloadEvent) => {
|
|
437
|
+
e.preventDefault()
|
|
438
|
+
e.returnValue = ''
|
|
439
|
+
}
|
|
440
|
+
window.addEventListener('beforeunload', handler)
|
|
441
|
+
return () => window.removeEventListener('beforeunload', handler)
|
|
442
|
+
}, [isDirty])
|
|
443
|
+
|
|
444
|
+
// `isMobileRightPanelOpen` is global UI state, so a panel left open on a
|
|
445
|
+
// thread would silently re-open when the user navigates back to one after
|
|
446
|
+
// visiting the agent page. Reset it whenever the panel isn't available.
|
|
447
|
+
useEffect(() => {
|
|
448
|
+
if (!dmProjectId) closeMobileRightPanel()
|
|
449
|
+
}, [dmProjectId, closeMobileRightPanel])
|
|
450
|
+
|
|
451
|
+
// Pass the full ChatLogEntry stream — buildRecipientStatusIndex needs
|
|
452
|
+
// batch_timeout rows in addition to messages so it can flip a recipient
|
|
453
|
+
// from AWAITING to TIMED OUT. Filtering to messages here (as this did
|
|
454
|
+
// before batch-timeout support landed) leaves the chip stuck on AWAITING
|
|
455
|
+
// forever. ChatroomView passes the same unfiltered stream.
|
|
456
|
+
const statusIndex = useMemo(
|
|
457
|
+
() =>
|
|
458
|
+
buildRecipientStatusIndex(
|
|
459
|
+
messages || [],
|
|
460
|
+
allAgents || [],
|
|
461
|
+
processingAgentIds,
|
|
462
|
+
),
|
|
463
|
+
[messages, allAgents, processingAgentIds],
|
|
464
|
+
)
|
|
465
|
+
|
|
466
|
+
// The Files panel only has anything to show once a thread exists. On the
|
|
467
|
+
// agent page (`/dm/:agentName`, a draft) there is no project yet, so the
|
|
468
|
+
// files query is disabled and the panel would render a permanently-empty
|
|
469
|
+
// "Files (0)" column — hide the whole right rail (and its mobile toggle /
|
|
470
|
+
// resize handle) there instead. Gated on `dmProjectId`, NOT on "zero state
|
|
471
|
+
// showing": DMZeroState also renders for a real-but-empty thread, where
|
|
472
|
+
// Files is still live.
|
|
473
|
+
const showFilesPanel = !!dmProjectId
|
|
474
|
+
|
|
475
|
+
// Onboarding launchpad instead of a transcript: either a draft thread with no
|
|
476
|
+
// project yet, or a real thread nobody has written in. Also drives the taller
|
|
477
|
+
// resting composer, so a hovered idea's 3-line ghost preview fits without the
|
|
478
|
+
// box ever changing size.
|
|
479
|
+
const showZeroState = !dmProjectId || (messages?.length ?? 0) === 0
|
|
480
|
+
|
|
481
|
+
if (projectLoading) {
|
|
482
|
+
return (
|
|
483
|
+
<div className="flex-1 flex items-center justify-center">
|
|
484
|
+
<Loading size="lg" />
|
|
485
|
+
</div>
|
|
486
|
+
)
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
const fileCount = files?.length || 0
|
|
490
|
+
|
|
491
|
+
return (
|
|
492
|
+
<div className="flex flex-col h-full">
|
|
493
|
+
{/* Header */}
|
|
494
|
+
<CollapsibleHeader className="border-b border-border px-6 py-3 pl-14 lg:pl-6">
|
|
495
|
+
<div className="flex items-center justify-between">
|
|
496
|
+
<div className="flex items-center gap-4">
|
|
497
|
+
<div className="flex items-center gap-3">
|
|
498
|
+
{agent && (
|
|
499
|
+
<Avatar
|
|
500
|
+
name={agentLabel}
|
|
501
|
+
status={agent.status as AgentStatus}
|
|
502
|
+
size="md"
|
|
503
|
+
/>
|
|
504
|
+
)}
|
|
505
|
+
<div className="min-w-0">
|
|
506
|
+
<h2 className="flex items-center gap-2 text-lg text-channel-active min-w-0">
|
|
507
|
+
{agent ? (
|
|
508
|
+
<AgentNameLink agentName={agent.name} className="truncate">
|
|
509
|
+
{agentLabel}
|
|
510
|
+
</AgentNameLink>
|
|
511
|
+
) : (
|
|
512
|
+
<span className="truncate">{agentLabel}</span>
|
|
513
|
+
)}
|
|
514
|
+
{isScheduledThread && (
|
|
515
|
+
<span
|
|
516
|
+
className="inline-flex shrink-0 items-center gap-1 rounded-full bg-purple-50 px-2 py-0.5 text-[10px] font-bold uppercase tracking-wide text-accent-deep"
|
|
517
|
+
title="Scheduled messages thread"
|
|
518
|
+
>
|
|
519
|
+
<Clock className="w-3 h-3" />
|
|
520
|
+
Scheduled
|
|
521
|
+
</span>
|
|
522
|
+
)}
|
|
523
|
+
</h2>
|
|
524
|
+
{threadName ? (
|
|
525
|
+
<p className="text-sm text-channel min-w-0">
|
|
526
|
+
<InlineEditableTitle
|
|
527
|
+
value={threadName}
|
|
528
|
+
label="Conversation name"
|
|
529
|
+
editable={!!threadProject && !threadProject.is_viewer}
|
|
530
|
+
onSave={(next) =>
|
|
531
|
+
renameThread.mutateAsync({ projectId: dmProjectId, displayName: next })
|
|
532
|
+
}
|
|
533
|
+
/>
|
|
534
|
+
</p>
|
|
535
|
+
) : (
|
|
536
|
+
!isOwnAgent && agent?.description && (
|
|
537
|
+
<p className="text-sm text-channel truncate">{agent.description}</p>
|
|
538
|
+
)
|
|
539
|
+
)}
|
|
540
|
+
</div>
|
|
541
|
+
</div>
|
|
542
|
+
</div>
|
|
543
|
+
<div className="flex items-center gap-1">
|
|
544
|
+
{/* Files toggle button - visible only on mobile */}
|
|
545
|
+
{showFilesPanel && (
|
|
546
|
+
<button
|
|
547
|
+
onClick={openMobileRightPanel}
|
|
548
|
+
className="p-2 rounded-md hover:bg-sidebar-hover transition-colors relative lg:hidden"
|
|
549
|
+
aria-label="Show files panel"
|
|
550
|
+
title="Files"
|
|
551
|
+
>
|
|
552
|
+
<FileText className="w-5 h-5 text-channel" />
|
|
553
|
+
{fileCount > 0 && (
|
|
554
|
+
<span className="absolute -top-1 -right-1 bg-accent text-white text-xs rounded-full w-4 h-4 flex items-center justify-center">
|
|
555
|
+
{fileCount > 9 ? '9+' : fileCount}
|
|
556
|
+
</span>
|
|
557
|
+
)}
|
|
558
|
+
</button>
|
|
559
|
+
)}
|
|
560
|
+
{dmProjectId && chatroomName && (
|
|
561
|
+
<ClearHistoryButton
|
|
562
|
+
projectId={dmProjectId}
|
|
563
|
+
chatroomName={chatroomName}
|
|
564
|
+
confirmLabel={`@${agentLabel}`}
|
|
565
|
+
/>
|
|
566
|
+
)}
|
|
567
|
+
{showAgentActions && (
|
|
568
|
+
<AgentViewActions agent={agent} agentLabel={agentLabel} active={homeFolderOpen ? 'home' : 'start'} />
|
|
569
|
+
)}
|
|
570
|
+
{canDeleteThread && (
|
|
571
|
+
<button
|
|
572
|
+
type="button"
|
|
573
|
+
onClick={handleDeleteThread}
|
|
574
|
+
disabled={deleteThreadMutation.isPending}
|
|
575
|
+
className="p-2 rounded-md hover:bg-red-100 transition-colors text-channel hover:text-red-600 disabled:opacity-50"
|
|
576
|
+
aria-label="Delete conversation"
|
|
577
|
+
title="Delete conversation"
|
|
578
|
+
>
|
|
579
|
+
<Trash2 className="w-5 h-5" />
|
|
580
|
+
</button>
|
|
581
|
+
)}
|
|
582
|
+
</div>
|
|
583
|
+
</div>
|
|
584
|
+
</CollapsibleHeader>
|
|
585
|
+
|
|
586
|
+
{/* Content */}
|
|
587
|
+
{homeFolderOpen ? (
|
|
588
|
+
<HomeFolderBrowser
|
|
589
|
+
key={`${agent.id}:${searchParams.get('path') ?? ''}`}
|
|
590
|
+
agentId={agent.id}
|
|
591
|
+
agentLabel={agentLabel}
|
|
592
|
+
initialPath={searchParams.get('path') ?? ''}
|
|
593
|
+
/>
|
|
594
|
+
) : (
|
|
595
|
+
<div className="flex-1 flex overflow-hidden relative">
|
|
596
|
+
{/* Main message area */}
|
|
597
|
+
<div className="flex-1 flex flex-col overflow-hidden">
|
|
598
|
+
{/* Messages */}
|
|
599
|
+
{messagesLoading ? (
|
|
600
|
+
<div className="flex-1 flex items-center justify-center">
|
|
601
|
+
<Loading />
|
|
602
|
+
</div>
|
|
603
|
+
) : showZeroState ? (
|
|
604
|
+
<DMZeroState
|
|
605
|
+
agent={agent}
|
|
606
|
+
onUseSample={prefillComposer}
|
|
607
|
+
onPreviewSample={previewInComposer}
|
|
608
|
+
onPersonalize={handlePersonalize}
|
|
609
|
+
/>
|
|
610
|
+
) : (
|
|
611
|
+
<MessageList
|
|
612
|
+
messages={messages || []}
|
|
613
|
+
agents={allAgents || []}
|
|
614
|
+
projectId={dmProjectId}
|
|
615
|
+
chatroomName={chatroomName}
|
|
616
|
+
statusIndex={statusIndex}
|
|
617
|
+
targetMessageId={targetMessageId}
|
|
618
|
+
onTargetResolved={clearTarget}
|
|
619
|
+
untrustedBodies={trust.untrustedBodies}
|
|
620
|
+
isOutsideAuthor={trust.isOutsideAuthor}
|
|
621
|
+
/>
|
|
622
|
+
)}
|
|
623
|
+
|
|
624
|
+
<RoomFlowStrip flow={chatroom?.flow} viewerIsOwner={isThreadOwner} />
|
|
625
|
+
{dmProjectId && (
|
|
626
|
+
<HeldNotices projectId={dmProjectId} room={chatroomName} messages={messages} viewerId={user?.id} />
|
|
627
|
+
)}
|
|
628
|
+
|
|
629
|
+
{sendErrorText && (
|
|
630
|
+
<p role="alert" className="px-4 py-1 text-sm text-red-600" data-testid="dm-send-error">
|
|
631
|
+
{sendErrorText}
|
|
632
|
+
{canResume && (
|
|
633
|
+
<button
|
|
634
|
+
type="button"
|
|
635
|
+
className="ml-2 font-semibold text-accent-deep underline disabled:opacity-50"
|
|
636
|
+
disabled={resumeFlow.isPending}
|
|
637
|
+
onClick={() => resumeFlow.mutate('open', { onSuccess: () => sendMessageMutation.reset() })}
|
|
638
|
+
data-testid="dm-resume-flow"
|
|
639
|
+
>
|
|
640
|
+
{FLOW_COPY.resume}
|
|
641
|
+
</button>
|
|
642
|
+
)}
|
|
643
|
+
</p>
|
|
644
|
+
)}
|
|
645
|
+
|
|
646
|
+
{/* Attachment error (e.g. over the size limit) */}
|
|
647
|
+
{attachmentError && (
|
|
648
|
+
<div className="px-4 py-1 text-sm text-red-600">{attachmentError}</div>
|
|
649
|
+
)}
|
|
650
|
+
|
|
651
|
+
{/* Message input */}
|
|
652
|
+
<form onSubmit={handleSendMessage} className="p-4 border-t border-border">
|
|
653
|
+
<div
|
|
654
|
+
className="relative rounded-2xl border border-gray-200 bg-white shadow-sm focus-within:border-purple-300 focus-within:shadow-[0_0_0_3px_rgba(168,85,247,0.10)] transition-all"
|
|
655
|
+
{...dragHandlers}
|
|
656
|
+
>
|
|
657
|
+
<DropOverlay visible={isDragging} />
|
|
658
|
+
{/* Header: avatar + you → @agent */}
|
|
659
|
+
<div className="flex items-center gap-2 px-4 pt-3 pb-1">
|
|
660
|
+
{user && <Avatar name={user.username} size="xs" />}
|
|
661
|
+
<span className="text-xs">
|
|
662
|
+
<span className="font-medium text-gray-700">you</span>
|
|
663
|
+
<span className="text-gray-300 mx-1.5">→</span>
|
|
664
|
+
<span className="font-mono text-gray-500">@{agentLabel}</span>
|
|
665
|
+
</span>
|
|
666
|
+
</div>
|
|
667
|
+
|
|
668
|
+
{/* Message — rich: an SOP's {{blanks}} become fillable chips */}
|
|
669
|
+
<PromptEditor
|
|
670
|
+
ref={dmEditorRef}
|
|
671
|
+
wrapClassName="px-4 pt-1 pb-2"
|
|
672
|
+
className="text-gray-900 text-sm"
|
|
673
|
+
minHeight={showZeroState ? 76 : 52}
|
|
674
|
+
maxHeight={200}
|
|
675
|
+
placeholder={`Message @${agentLabel}...`}
|
|
676
|
+
disabled={isSending}
|
|
677
|
+
agents={allAgents ?? []}
|
|
678
|
+
viewer={user ?? null}
|
|
679
|
+
onChange={(t) => {
|
|
680
|
+
setDmMessage(t)
|
|
681
|
+
dmMessageRef.current = t
|
|
682
|
+
}}
|
|
683
|
+
onSubmit={submitMessage}
|
|
684
|
+
/>
|
|
685
|
+
|
|
686
|
+
{/* Staged attachments (client-side; uploaded on send) */}
|
|
687
|
+
<StagedAttachments files={stagedFiles} onRemove={removeStagedFile} disabled={isSending} />
|
|
688
|
+
|
|
689
|
+
{/* Footer: draft actions only, right-aligned. `flex-wrap` so adding
|
|
690
|
+
the model selector never pushes the send button out of a narrow
|
|
691
|
+
column. Every control here is icon-sized except `command`,
|
|
692
|
+
so the row holds on a phone. */}
|
|
693
|
+
<div className="flex flex-wrap items-center justify-end gap-2 px-3 pb-2">
|
|
694
|
+
<div className="flex items-center gap-0.5 shrink-0">
|
|
695
|
+
{/* Model for this agent — quick-edit shortcut to Agent Settings */}
|
|
696
|
+
<ModelSelector agent={agent} />
|
|
697
|
+
|
|
698
|
+
{/* File upload (staged; sent with the message) */}
|
|
699
|
+
<button
|
|
700
|
+
type="button"
|
|
701
|
+
onClick={handleFileSelect}
|
|
702
|
+
disabled={isSending}
|
|
703
|
+
className="p-1.5 text-gray-400 hover:text-gray-700 rounded transition-colors disabled:opacity-50"
|
|
704
|
+
title="Attach file"
|
|
705
|
+
>
|
|
706
|
+
<Paperclip className="w-4 h-4" />
|
|
707
|
+
</button>
|
|
708
|
+
<input
|
|
709
|
+
ref={fileInputRef}
|
|
710
|
+
type="file"
|
|
711
|
+
multiple
|
|
712
|
+
className="hidden"
|
|
713
|
+
onChange={handleFileChange}
|
|
714
|
+
/>
|
|
715
|
+
|
|
716
|
+
{/* Schedule */}
|
|
717
|
+
<button
|
|
718
|
+
type="button"
|
|
719
|
+
onClick={() => setShowScheduleModal(true)}
|
|
720
|
+
disabled={!dmProjectId}
|
|
721
|
+
className="p-1.5 text-gray-400 hover:text-gray-700 rounded transition-colors disabled:opacity-50"
|
|
722
|
+
title="Schedule message"
|
|
723
|
+
>
|
|
724
|
+
<Clock className="w-4 h-4" />
|
|
725
|
+
</button>
|
|
726
|
+
|
|
727
|
+
{/* Setup CTA, collapsed to an icon so it costs one slot in a
|
|
728
|
+
row that already flexes instead of a band of its own.
|
|
729
|
+
Mortarboard, not a sparkle: a sparkle means "AI did
|
|
730
|
+
something" everywhere else in this app, whereas a
|
|
731
|
+
graduation cap reads as teach/train/qualify — which is
|
|
732
|
+
exactly the action for both roles (the assistant learns
|
|
733
|
+
the USER, every other agent is deep-researched into a
|
|
734
|
+
field expert). Tinted accent so it does not disappear
|
|
735
|
+
into the gray attach/schedule pair; the words live in the
|
|
736
|
+
tooltip and in the zero-state CTA. */}
|
|
737
|
+
<button
|
|
738
|
+
type="button"
|
|
739
|
+
onClick={handlePersonalize}
|
|
740
|
+
disabled={!agent || isSending}
|
|
741
|
+
title={personalizeHint}
|
|
742
|
+
aria-label={isAssistant ? 'Personalize' : 'Train as expert'}
|
|
743
|
+
className="p-1.5 text-accent/70 hover:text-accent-deep hover:bg-purple-50 rounded transition-colors disabled:opacity-50 disabled:cursor-not-allowed"
|
|
744
|
+
>
|
|
745
|
+
<GraduationCap className="w-4 h-4" />
|
|
746
|
+
</button>
|
|
747
|
+
|
|
748
|
+
{/* Send */}
|
|
749
|
+
<button
|
|
750
|
+
type="submit"
|
|
751
|
+
disabled={isSending || (!dmMessage.trim() && stagedFiles.length === 0)}
|
|
752
|
+
title="Command (⌘/Ctrl+Enter)"
|
|
753
|
+
className="ml-1 inline-flex items-center gap-1.5 px-2.5 py-1.5 rounded-md text-xs font-medium text-white bg-accent hover:bg-accent-deep disabled:bg-accent-soft disabled:cursor-not-allowed transition-colors"
|
|
754
|
+
>
|
|
755
|
+
{isSending ? (
|
|
756
|
+
<Loader2 className="w-3.5 h-3.5 animate-spin" />
|
|
757
|
+
) : (
|
|
758
|
+
<Send className="w-3.5 h-3.5" />
|
|
759
|
+
)}
|
|
760
|
+
<span>command</span>
|
|
761
|
+
</button>
|
|
762
|
+
</div>
|
|
763
|
+
</div>
|
|
764
|
+
</div>
|
|
765
|
+
</form>
|
|
766
|
+
</div>
|
|
767
|
+
|
|
768
|
+
{showFilesPanel && (
|
|
769
|
+
<>
|
|
770
|
+
{/* Backdrop overlay for mobile files panel */}
|
|
771
|
+
<Overlay isOpen={isMobileRightPanelOpen} onClose={closeMobileRightPanel} />
|
|
772
|
+
|
|
773
|
+
<ResizeHandle side="right" onResize={setRightPanelWidth} />
|
|
774
|
+
|
|
775
|
+
{/* Files sidebar - slide-in on mobile, static on desktop */}
|
|
776
|
+
<aside
|
|
777
|
+
className={`
|
|
778
|
+
fixed inset-y-0 right-0 z-50 bg-sidebar border-l border-border flex flex-col overflow-y-auto scrollbar-thin flex-shrink-0
|
|
779
|
+
transform transition-transform duration-300 ease-in-out
|
|
780
|
+
lg:relative lg:translate-x-0 lg:transform-none lg:transition-none lg:z-auto
|
|
781
|
+
${isMobileRightPanelOpen ? 'translate-x-0' : 'translate-x-full'}
|
|
782
|
+
`}
|
|
783
|
+
style={{ width: rightPanelWidth }}
|
|
784
|
+
>
|
|
785
|
+
{/* Close button - visible only on mobile */}
|
|
786
|
+
<button
|
|
787
|
+
onClick={closeMobileRightPanel}
|
|
788
|
+
className="absolute top-3 right-3 p-1 rounded-md hover:bg-sidebar-hover transition-colors lg:hidden z-10"
|
|
789
|
+
aria-label="Close panel"
|
|
790
|
+
>
|
|
791
|
+
<X className="w-5 h-5 text-channel" />
|
|
792
|
+
</button>
|
|
793
|
+
|
|
794
|
+
{/* Files */}
|
|
795
|
+
<div className="flex flex-col flex-1 min-h-0 mt-8 lg:mt-0">
|
|
796
|
+
<div className="px-4 py-3 border-b border-border">
|
|
797
|
+
<h3 className="text-xs font-extrabold text-channel uppercase tracking-wider">
|
|
798
|
+
Files ({fileCount})
|
|
799
|
+
</h3>
|
|
800
|
+
</div>
|
|
801
|
+
<div className="flex-1 overflow-y-auto scrollbar-thin p-2">
|
|
802
|
+
{filesLoading ? (
|
|
803
|
+
<div className="flex justify-center py-4">
|
|
804
|
+
<Loading size="sm" />
|
|
805
|
+
</div>
|
|
806
|
+
) : (
|
|
807
|
+
<FileList
|
|
808
|
+
files={files || []}
|
|
809
|
+
projectId={dmProjectId}
|
|
810
|
+
chatroomName={chatroomName}
|
|
811
|
+
isOutsideFile={(name) => outsideFiles.has(name)}
|
|
812
|
+
/>
|
|
813
|
+
)}
|
|
814
|
+
</div>
|
|
815
|
+
</div>
|
|
816
|
+
</aside>
|
|
817
|
+
</>
|
|
818
|
+
)}
|
|
819
|
+
</div>
|
|
820
|
+
)}
|
|
821
|
+
|
|
822
|
+
{/* Schedule message modal */}
|
|
823
|
+
{showScheduleModal && dmProjectId && (
|
|
824
|
+
<ScheduleMessageModal
|
|
825
|
+
projectId={dmProjectId}
|
|
826
|
+
chatroomName={chatroomName}
|
|
827
|
+
onClose={() => setShowScheduleModal(false)}
|
|
828
|
+
/>
|
|
829
|
+
)}
|
|
830
|
+
|
|
831
|
+
{/* Personalize method-picker modal (assistant only) */}
|
|
832
|
+
{showPersonalizeModal && agent && (
|
|
833
|
+
<PersonalizeModal
|
|
834
|
+
agentLabel={agentLabel}
|
|
835
|
+
onConfirm={handlePersonalizeConfirm}
|
|
836
|
+
onClose={() => setShowPersonalizeModal(false)}
|
|
837
|
+
/>
|
|
838
|
+
)}
|
|
839
|
+
</div>
|
|
840
|
+
)
|
|
841
|
+
}
|