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,556 @@
|
|
|
1
|
+
# SPDX-License-Identifier: BUSL-1.1
|
|
2
|
+
"""
|
|
3
|
+
manigent/server/ws_hub.py
|
|
4
|
+
|
|
5
|
+
WebSocket hub for managing agent and user connections.
|
|
6
|
+
|
|
7
|
+
``Hub`` is the interface the rest of core uses to reach a socket; ``WSHub`` is
|
|
8
|
+
its in-process implementation, where a socket is the ``asyncio.Queue`` its
|
|
9
|
+
endpoint's send task drains. What happens when a socket opens or closes is not
|
|
10
|
+
the hub's business — that is ``server/socket_events.py``.
|
|
11
|
+
"""
|
|
12
|
+
from __future__ import annotations
|
|
13
|
+
|
|
14
|
+
import asyncio
|
|
15
|
+
import itertools
|
|
16
|
+
import logging
|
|
17
|
+
from datetime import UTC, datetime
|
|
18
|
+
from pathlib import Path
|
|
19
|
+
from typing import TYPE_CHECKING, Hashable, Optional, Protocol
|
|
20
|
+
|
|
21
|
+
from manigent.api.control import (
|
|
22
|
+
ActiveWorkChangePayload,
|
|
23
|
+
AgentStatusChangePayload,
|
|
24
|
+
ControlEnvelope,
|
|
25
|
+
ControlMessageType,
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
if TYPE_CHECKING:
|
|
29
|
+
from manigent.models.context import ModelContext
|
|
30
|
+
from manigent.models.project import Project
|
|
31
|
+
|
|
32
|
+
logger = logging.getLogger("manigent.server")
|
|
33
|
+
|
|
34
|
+
# One live socket, as the hub names it. In-process that is the socket's
|
|
35
|
+
# outbound ``asyncio.Queue``; callers only compare and pass it back, never
|
|
36
|
+
# look inside.
|
|
37
|
+
ConnId = Hashable
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
class Hub(Protocol):
|
|
41
|
+
"""What core may ask of the socket layer — every call site goes through
|
|
42
|
+
these names and nothing else, so a hub living in another process can stand
|
|
43
|
+
in for ``WSHub`` without touching them."""
|
|
44
|
+
|
|
45
|
+
async def send_to(self, participant_id: str, envelope: ControlEnvelope) -> bool: ...
|
|
46
|
+
async def send_to_many(self, participant_ids: list[str], envelope: ControlEnvelope) -> int: ...
|
|
47
|
+
async def send_frame(self, conn: ConnId, frame: dict) -> bool: ...
|
|
48
|
+
async def broadcast_status_change(
|
|
49
|
+
self, agent_id: str, agent_name: str, new_status: str, recipient_ids: list[str],
|
|
50
|
+
) -> None: ...
|
|
51
|
+
async def broadcast_active_work_change(
|
|
52
|
+
self, project: "Project", chatroom_name: str, active_participants: list[str],
|
|
53
|
+
) -> int: ...
|
|
54
|
+
async def broadcast_to_project(self, envelope: ControlEnvelope, project: "Project") -> int: ...
|
|
55
|
+
async def close_connection(self, agent_id: str) -> bool: ...
|
|
56
|
+
async def connected_agents(self) -> list[str]: ...
|
|
57
|
+
def is_connected(self, agent_id: str) -> bool: ...
|
|
58
|
+
def get_connection_info(self, agent_id: str) -> Optional[dict]: ...
|
|
59
|
+
def newest_connection(self, agent_id: str) -> Optional[tuple[ConnId, dict]]: ...
|
|
60
|
+
def runners_for_owner(self, owner_id: str) -> list[dict]: ...
|
|
61
|
+
def recipients_for_project(self, project: "Project") -> set[str]: ...
|
|
62
|
+
async def send_to_host(self, host_id: str, frame: dict) -> bool: ...
|
|
63
|
+
async def close_host_connection(self, host_id: str) -> bool: ...
|
|
64
|
+
def is_host_connected(self, host_id: str) -> bool: ...
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
class WSHub:
|
|
68
|
+
"""
|
|
69
|
+
In-memory WebSocket hub for managing agent, user, and host connections.
|
|
70
|
+
Lives only for the lifetime of the server process.
|
|
71
|
+
|
|
72
|
+
A single participant (agent or user) may hold **multiple** live
|
|
73
|
+
connections at once — e.g. a user with two browsers open, or a runner
|
|
74
|
+
that briefly overlaps an old and new socket during a reconnect. The hub
|
|
75
|
+
therefore keeps a *set of queues* per participant and every delivery
|
|
76
|
+
primitive (``send_to``, ``close_connection``, the ``broadcast_*``
|
|
77
|
+
methods) fans out to all of that participant's live sessions. This is
|
|
78
|
+
what makes desk events (``desk_read_state_sync`` / ``desk_todo_sync`` /
|
|
79
|
+
``brief_tab_sync``) reach every open device live, not just the
|
|
80
|
+
most-recently-connected one.
|
|
81
|
+
"""
|
|
82
|
+
|
|
83
|
+
#: Set by create_app (server/isolation_gate.py). Filters every project
|
|
84
|
+
#: broadcast so an isolated project's changelog notices reach only agents
|
|
85
|
+
#: whose runners can run an isolated turn. None in hand-built test hubs.
|
|
86
|
+
isolation_gate = None
|
|
87
|
+
|
|
88
|
+
def __init__(
|
|
89
|
+
self,
|
|
90
|
+
data_dir: Optional[Path] = None,
|
|
91
|
+
model_ctx: Optional["ModelContext"] = None,
|
|
92
|
+
) -> None:
|
|
93
|
+
# participant_id -> set of live outbound queues (one per open socket)
|
|
94
|
+
self._conns: dict[str, set[asyncio.Queue]] = {}
|
|
95
|
+
# per-connection metadata (ip, connected_since, manigent_version,
|
|
96
|
+
# owner_id, agent_name), keyed by queue identity
|
|
97
|
+
self._conn_info: dict[asyncio.Queue, dict] = {}
|
|
98
|
+
# host_id -> set of live outbound queues, for /ws/host/{host_id}.
|
|
99
|
+
# A SEPARATE dict from `_conns`, not a second kind of entry in it:
|
|
100
|
+
# `connected_agents`, `runners_for_owner`, `broadcast_to_project` and
|
|
101
|
+
# every recipient list in the app read `_conns`, and a machine is not a
|
|
102
|
+
# participant of anything. Keeping the two apart is what makes "a host
|
|
103
|
+
# id can never turn up in a project broadcast" structural rather than a
|
|
104
|
+
# filter someone has to remember to write. Host queues carry plain
|
|
105
|
+
# dicts, not ControlEnvelopes: the other end is the `manigent-daemon`
|
|
106
|
+
# distribution, which ships without pydantic.
|
|
107
|
+
self._host_conns: dict[str, set[asyncio.Queue]] = {}
|
|
108
|
+
self._lock = asyncio.Lock()
|
|
109
|
+
# Connect order, recorded per socket. ``newest_connection`` picks by
|
|
110
|
+
# this rather than by ``connected_since``: two sockets can share a
|
|
111
|
+
# timestamp, they can never share a sequence number.
|
|
112
|
+
self._conn_seq = itertools.count()
|
|
113
|
+
self._data_dir = data_dir
|
|
114
|
+
self._model_ctx = model_ctx
|
|
115
|
+
|
|
116
|
+
async def connect(
|
|
117
|
+
self,
|
|
118
|
+
agent_id: str,
|
|
119
|
+
queue: asyncio.Queue,
|
|
120
|
+
client_ip: Optional[str] = None,
|
|
121
|
+
*,
|
|
122
|
+
manigent_version: Optional[str] = None,
|
|
123
|
+
owner_id: Optional[str] = None,
|
|
124
|
+
agent_name: Optional[str] = None,
|
|
125
|
+
capabilities: Optional[frozenset[str]] = None,
|
|
126
|
+
) -> None:
|
|
127
|
+
"""Register a live socket.
|
|
128
|
+
|
|
129
|
+
``manigent_version`` is the runner's self-reported manigent version
|
|
130
|
+
(``str``), or ``None`` when the runner sent no version field at all
|
|
131
|
+
(an older release) or could not determine its own version. Keyword-only
|
|
132
|
+
with a ``None`` default so every existing call site — the
|
|
133
|
+
``/ws/user/{id}`` browser socket and the tests — keeps working
|
|
134
|
+
unchanged.
|
|
135
|
+
|
|
136
|
+
``owner_id`` (``participant.registered_by``) and ``agent_name``
|
|
137
|
+
(``participant.name``) are the same shape and for the same reason:
|
|
138
|
+
keyword-only, ``None`` by default, and passed ONLY by the ``/ws/{id}``
|
|
139
|
+
agent endpoint. That is what makes ``runners_for_owner`` able to answer
|
|
140
|
+
"which runners does this user own" from memory alone — with no owner
|
|
141
|
+
recorded, a browser socket can never appear in anyone's list, so there
|
|
142
|
+
is nothing to filter out by id afterwards.
|
|
143
|
+
|
|
144
|
+
``capabilities`` is the set of optional frames the runner said it
|
|
145
|
+
answers (``api/fs_protocol.FS_CAPABILITY`` today); empty for an older
|
|
146
|
+
runner and for every browser socket. Same per-socket, never-persisted
|
|
147
|
+
rule as the version: it describes the code on the other end of THIS
|
|
148
|
+
socket.
|
|
149
|
+
|
|
150
|
+
All of these are stored in the same per-queue ``_conn_info`` dict that
|
|
151
|
+
already holds ``{ip, connected_since}``: that dict is already
|
|
152
|
+
per-connection, already dies with the socket, and already handles the
|
|
153
|
+
multi-session case. Nothing persists any of it — a version that is not
|
|
154
|
+
backed by a live socket does not exist, by design.
|
|
155
|
+
"""
|
|
156
|
+
async with self._lock:
|
|
157
|
+
self._conns.setdefault(agent_id, set()).add(queue)
|
|
158
|
+
self._conn_info[queue] = {
|
|
159
|
+
"ip": client_ip,
|
|
160
|
+
"connected_since": datetime.now(UTC).isoformat(),
|
|
161
|
+
"manigent_version": manigent_version,
|
|
162
|
+
"owner_id": owner_id,
|
|
163
|
+
"agent_name": agent_name,
|
|
164
|
+
"capabilities": frozenset(capabilities or ()),
|
|
165
|
+
"seq": next(self._conn_seq),
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
async def disconnect(
|
|
169
|
+
self,
|
|
170
|
+
agent_id: str,
|
|
171
|
+
queue: Optional[asyncio.Queue] = None,
|
|
172
|
+
) -> None:
|
|
173
|
+
"""Remove a participant's connection(s).
|
|
174
|
+
|
|
175
|
+
With ``queue`` given, only that specific socket is removed — the
|
|
176
|
+
correct behavior when one of several sessions closes (closing device
|
|
177
|
+
A must not drop device B's queue). With ``queue`` omitted, every
|
|
178
|
+
session for the participant is removed (legacy "remove all"; used by
|
|
179
|
+
tests and hard resets). When the last session goes, the participant
|
|
180
|
+
key is deleted so ``is_connected`` stays accurate and empty sets do
|
|
181
|
+
not leak.
|
|
182
|
+
"""
|
|
183
|
+
async with self._lock:
|
|
184
|
+
conns = self._conns.get(agent_id)
|
|
185
|
+
if conns is None:
|
|
186
|
+
return
|
|
187
|
+
if queue is None:
|
|
188
|
+
for q in conns:
|
|
189
|
+
self._conn_info.pop(q, None)
|
|
190
|
+
del self._conns[agent_id]
|
|
191
|
+
else:
|
|
192
|
+
conns.discard(queue)
|
|
193
|
+
self._conn_info.pop(queue, None)
|
|
194
|
+
if not conns:
|
|
195
|
+
del self._conns[agent_id]
|
|
196
|
+
|
|
197
|
+
async def close_connection(self, agent_id: str) -> bool:
|
|
198
|
+
"""Ask the participant's send task(s) to close the WebSocket.
|
|
199
|
+
|
|
200
|
+
Enqueues a `None` sentinel on EVERY live session; the endpoint's
|
|
201
|
+
`send_from_queue` coroutine reads it and issues
|
|
202
|
+
`websocket.close(code=4004)`. Used by delete_agent so the runner
|
|
203
|
+
reconnects immediately, gets the 4004 close code, and self-destructs
|
|
204
|
+
— instead of waiting for the next heartbeat-driven reconnect. All of
|
|
205
|
+
a participant's sockets are signalled, not just one.
|
|
206
|
+
|
|
207
|
+
Returns True if at least one connection was present to signal.
|
|
208
|
+
"""
|
|
209
|
+
conns = list(self._conns.get(agent_id, ()))
|
|
210
|
+
if not conns:
|
|
211
|
+
return False
|
|
212
|
+
for q in conns:
|
|
213
|
+
await q.put(None)
|
|
214
|
+
return True
|
|
215
|
+
|
|
216
|
+
async def connected_agents(self) -> list[str]:
|
|
217
|
+
return list(self._conns.keys())
|
|
218
|
+
|
|
219
|
+
def is_connected(self, agent_id: str) -> bool:
|
|
220
|
+
return agent_id in self._conns
|
|
221
|
+
|
|
222
|
+
def get_connection_info(self, agent_id: str) -> Optional[dict]:
|
|
223
|
+
"""Get connection metadata for a participant.
|
|
224
|
+
|
|
225
|
+
A participant may have several live sessions; return the metadata of
|
|
226
|
+
the most-recently-connected one (max ``connected_since``) so callers
|
|
227
|
+
that expect a single ``{ip, connected_since, manigent_version}`` dict
|
|
228
|
+
keep working.
|
|
229
|
+
"""
|
|
230
|
+
conns = self._conns.get(agent_id)
|
|
231
|
+
if not conns:
|
|
232
|
+
return None
|
|
233
|
+
infos = [self._conn_info[q] for q in conns if q in self._conn_info]
|
|
234
|
+
if not infos:
|
|
235
|
+
return None
|
|
236
|
+
return max(infos, key=lambda i: i.get("connected_since") or "")
|
|
237
|
+
|
|
238
|
+
def newest_connection(
|
|
239
|
+
self, agent_id: str
|
|
240
|
+
) -> Optional[tuple[ConnId, dict]]:
|
|
241
|
+
"""``(conn, info)`` of the participant's most recently connected
|
|
242
|
+
socket, or None when it holds none.
|
|
243
|
+
|
|
244
|
+
For request/reply traffic that must run exactly once (the home-folder
|
|
245
|
+
relay): ``send_to`` fans out to every session, which is right for a
|
|
246
|
+
notification and wrong for "write this file". Picks by connect order
|
|
247
|
+
(``seq``), so of two overlapping sockets during a reconnect the new one
|
|
248
|
+
wins. ``info`` is the live dict; callers read it, never write it.
|
|
249
|
+
"""
|
|
250
|
+
conns = self._conns.get(agent_id)
|
|
251
|
+
if not conns:
|
|
252
|
+
return None
|
|
253
|
+
live = [(q, self._conn_info[q]) for q in conns if q in self._conn_info]
|
|
254
|
+
if not live:
|
|
255
|
+
return None
|
|
256
|
+
return max(live, key=lambda item: item[1].get("seq", -1))
|
|
257
|
+
|
|
258
|
+
async def send_frame(self, conn: ConnId, frame: dict) -> bool:
|
|
259
|
+
"""Queue one plain-dict frame for exactly ONE socket. False if that
|
|
260
|
+
socket is no longer registered.
|
|
261
|
+
|
|
262
|
+
For request/reply traffic (the home-folder relay), where the caller has
|
|
263
|
+
already picked the socket with ``newest_connection`` and a fan-out
|
|
264
|
+
would run the request twice. The agent endpoint's send task writes a
|
|
265
|
+
dict as compact JSON, untouched.
|
|
266
|
+
"""
|
|
267
|
+
if conn not in self._conn_info:
|
|
268
|
+
return False
|
|
269
|
+
await conn.put(frame)
|
|
270
|
+
return True
|
|
271
|
+
|
|
272
|
+
def runners_for_owner(self, owner_id: str) -> list[dict]:
|
|
273
|
+
"""``[{id, name, version}, …]`` for every live runner registered by
|
|
274
|
+
``owner_id``.
|
|
275
|
+
|
|
276
|
+
**Pure read of in-memory state — no ``Agent.list_all_cards``, no disk,
|
|
277
|
+
no lock.** This is the whole efficiency win of the redesign: the push
|
|
278
|
+
that calls this fires on machine events (every runner connect and
|
|
279
|
+
disconnect, every browser connect), and the version it needs is
|
|
280
|
+
already sitting in ``_conn_info``. Do not reintroduce a roster scan
|
|
281
|
+
here — the previous design read one ``card.json`` per agent across the
|
|
282
|
+
ENTIRE deployment on each of those events.
|
|
283
|
+
|
|
284
|
+
Only *live* connections appear. A runner that has disconnected is
|
|
285
|
+
absent entirely, which is the mechanism behind "offline runners do not
|
|
286
|
+
count": there is no persistence path, so the reported version dies
|
|
287
|
+
with the socket. Browser sockets carry no ``owner_id`` at all (see
|
|
288
|
+
``connect``), so they can never appear in any owner's list.
|
|
289
|
+
|
|
290
|
+
Multi-session: when one agent id holds several sockets (two machines,
|
|
291
|
+
or an overlapping reconnect), the newest by ``connected_since`` wins —
|
|
292
|
+
the same tie-break ``get_connection_info`` uses, so the two can never
|
|
293
|
+
disagree. Name and version are both taken from that ONE winning info
|
|
294
|
+
dict, so they cannot end up sourced from different sockets.
|
|
295
|
+
|
|
296
|
+
Sorted by ``(name, id)`` so two browser tabs and two consecutive
|
|
297
|
+
pushes render in the same order.
|
|
298
|
+
"""
|
|
299
|
+
# A falsy owner would otherwise collide with the ``None`` recorded on
|
|
300
|
+
# every browser socket and return them as if they were runners. Call
|
|
301
|
+
# sites already guard on ``participant.registered_by``; this is the
|
|
302
|
+
# backstop that keeps the guarantee local to the method.
|
|
303
|
+
if not owner_id:
|
|
304
|
+
return []
|
|
305
|
+
|
|
306
|
+
runners: list[dict] = []
|
|
307
|
+
for participant_id, conns in self._conns.items():
|
|
308
|
+
infos = [
|
|
309
|
+
self._conn_info[q]
|
|
310
|
+
for q in conns
|
|
311
|
+
if q in self._conn_info and self._conn_info[q].get("owner_id") == owner_id
|
|
312
|
+
]
|
|
313
|
+
if not infos:
|
|
314
|
+
continue
|
|
315
|
+
newest = max(infos, key=lambda i: i.get("connected_since") or "")
|
|
316
|
+
runners.append({
|
|
317
|
+
"id": participant_id,
|
|
318
|
+
"name": newest.get("agent_name"),
|
|
319
|
+
"version": newest.get("manigent_version"),
|
|
320
|
+
})
|
|
321
|
+
runners.sort(key=lambda r: (r["name"] or "", r["id"]))
|
|
322
|
+
return runners
|
|
323
|
+
|
|
324
|
+
# --- host sockets (one user's computer) ---
|
|
325
|
+
|
|
326
|
+
async def connect_host(self, host_id: str, queue: asyncio.Queue) -> None:
|
|
327
|
+
"""Register a live host socket.
|
|
328
|
+
|
|
329
|
+
No metadata is recorded alongside it. Everything the UI shows about a
|
|
330
|
+
machine — its name, its software version, which of its agents are
|
|
331
|
+
running — is on the persisted ``HostRecord``, and the ONE thing the hub
|
|
332
|
+
knows that the record cannot is whether a socket exists right now.
|
|
333
|
+
Duplicating any of the rest here would create a second source of truth
|
|
334
|
+
that dies on server restart.
|
|
335
|
+
"""
|
|
336
|
+
async with self._lock:
|
|
337
|
+
self._host_conns.setdefault(host_id, set()).add(queue)
|
|
338
|
+
|
|
339
|
+
async def disconnect_host(
|
|
340
|
+
self, host_id: str, queue: Optional[asyncio.Queue] = None
|
|
341
|
+
) -> None:
|
|
342
|
+
"""Remove one host socket, or all of them when ``queue`` is omitted.
|
|
343
|
+
|
|
344
|
+
Same per-queue discipline as :meth:`disconnect`: a machine can briefly
|
|
345
|
+
hold two sockets across a reconnect, and dropping both when one closes
|
|
346
|
+
would report it offline while it is talking to us.
|
|
347
|
+
"""
|
|
348
|
+
async with self._lock:
|
|
349
|
+
conns = self._host_conns.get(host_id)
|
|
350
|
+
if conns is None:
|
|
351
|
+
return
|
|
352
|
+
if queue is None:
|
|
353
|
+
del self._host_conns[host_id]
|
|
354
|
+
return
|
|
355
|
+
conns.discard(queue)
|
|
356
|
+
if not conns:
|
|
357
|
+
del self._host_conns[host_id]
|
|
358
|
+
|
|
359
|
+
def is_host_connected(self, host_id: str) -> bool:
|
|
360
|
+
"""The live-socket half of ``models.host.derive_status``.
|
|
361
|
+
|
|
362
|
+
Pure read of in-memory state, like ``runners_for_owner``: nothing
|
|
363
|
+
persists a host connection, so a machine that is not connected right now
|
|
364
|
+
cannot be reported as online — including across a server restart, when
|
|
365
|
+
every machine is correctly offline until it reconnects.
|
|
366
|
+
"""
|
|
367
|
+
return host_id in self._host_conns
|
|
368
|
+
|
|
369
|
+
async def send_to_host(self, host_id: str, frame: dict) -> bool:
|
|
370
|
+
"""Queue one frame for a machine. False if it holds no live socket.
|
|
371
|
+
|
|
372
|
+
The False is the whole point at the call site: it is how a route answers
|
|
373
|
+
"your computer is not reachable right now" instead of accepting a
|
|
374
|
+
command that will never run.
|
|
375
|
+
"""
|
|
376
|
+
conns = list(self._host_conns.get(host_id, ()))
|
|
377
|
+
for q in conns:
|
|
378
|
+
await q.put(frame)
|
|
379
|
+
return bool(conns)
|
|
380
|
+
|
|
381
|
+
async def close_host_connection(self, host_id: str) -> bool:
|
|
382
|
+
"""Ask a machine's send task(s) to close the socket.
|
|
383
|
+
|
|
384
|
+
Used by "Disconnect this computer": the revocation has already
|
|
385
|
+
destroyed the credential, and this is what makes the machine let go
|
|
386
|
+
immediately instead of at its next reconnect. The ``None`` sentinel is
|
|
387
|
+
read by the endpoint's send loop, which closes with
|
|
388
|
+
``CLOSE_NO_HOST`` so the daemon self-destructs rather than
|
|
389
|
+
reconnect-looping against a token that will never work again.
|
|
390
|
+
"""
|
|
391
|
+
conns = list(self._host_conns.get(host_id, ()))
|
|
392
|
+
for q in conns:
|
|
393
|
+
await q.put(None)
|
|
394
|
+
return bool(conns)
|
|
395
|
+
|
|
396
|
+
async def send_to(self, participant_id: str, envelope: "ControlEnvelope") -> bool:
|
|
397
|
+
"""Send a control envelope to a connected participant.
|
|
398
|
+
|
|
399
|
+
Fans out to every live session the participant holds. Returns True if
|
|
400
|
+
the participant had at least one connection and the message was
|
|
401
|
+
queued (preserves the prior bool contract).
|
|
402
|
+
"""
|
|
403
|
+
conns = list(self._conns.get(participant_id, ()))
|
|
404
|
+
delivered = False
|
|
405
|
+
for q in conns:
|
|
406
|
+
await q.put(envelope)
|
|
407
|
+
delivered = True
|
|
408
|
+
return delivered
|
|
409
|
+
|
|
410
|
+
async def send_to_many(
|
|
411
|
+
self,
|
|
412
|
+
participant_ids: list[str],
|
|
413
|
+
envelope: "ControlEnvelope",
|
|
414
|
+
) -> int:
|
|
415
|
+
"""Queue the same envelope for every connected participant in ``participant_ids``.
|
|
416
|
+
|
|
417
|
+
Returns the number of participants that received the message (each
|
|
418
|
+
counted once, regardless of how many sessions they hold). Caller is
|
|
419
|
+
responsible for assembling the recipient list (e.g. enumerating peers
|
|
420
|
+
owned by a user); WSHub stays a pure delivery primitive and does not
|
|
421
|
+
know about agent-ownership semantics.
|
|
422
|
+
"""
|
|
423
|
+
count = 0
|
|
424
|
+
for pid in participant_ids:
|
|
425
|
+
if await self.send_to(pid, envelope):
|
|
426
|
+
count += 1
|
|
427
|
+
return count
|
|
428
|
+
|
|
429
|
+
# --- Broadcast methods ---
|
|
430
|
+
|
|
431
|
+
async def broadcast_status_change(
|
|
432
|
+
self,
|
|
433
|
+
agent_id: str,
|
|
434
|
+
agent_name: str,
|
|
435
|
+
new_status: str,
|
|
436
|
+
recipient_ids: list[str],
|
|
437
|
+
) -> None:
|
|
438
|
+
"""Broadcast agent status change to multiple recipients.
|
|
439
|
+
|
|
440
|
+
Args:
|
|
441
|
+
agent_id: ID of the agent whose status changed
|
|
442
|
+
agent_name: Name of the agent
|
|
443
|
+
new_status: New status ("online" or "offline")
|
|
444
|
+
recipient_ids: List of participant IDs (agents, assistants, or users)
|
|
445
|
+
"""
|
|
446
|
+
envelope = ControlEnvelope(
|
|
447
|
+
type=ControlMessageType.AGENT_STATUS_CHANGE,
|
|
448
|
+
payload=AgentStatusChangePayload(
|
|
449
|
+
agent_id=agent_id,
|
|
450
|
+
agent_name=agent_name,
|
|
451
|
+
new_status=new_status,
|
|
452
|
+
),
|
|
453
|
+
)
|
|
454
|
+
|
|
455
|
+
for recipient_id in recipient_ids:
|
|
456
|
+
if recipient_id == agent_id:
|
|
457
|
+
continue # Don't notify self
|
|
458
|
+
|
|
459
|
+
for q in list(self._conns.get(recipient_id, ())):
|
|
460
|
+
await q.put(envelope)
|
|
461
|
+
|
|
462
|
+
async def broadcast_active_work_change(
|
|
463
|
+
self,
|
|
464
|
+
project: "Project",
|
|
465
|
+
chatroom_name: str,
|
|
466
|
+
active_participants: list[str],
|
|
467
|
+
) -> int:
|
|
468
|
+
envelope = ControlEnvelope(
|
|
469
|
+
type=ControlMessageType.ACTIVE_WORK_CHANGE,
|
|
470
|
+
payload=ActiveWorkChangePayload(
|
|
471
|
+
project_id=project.id,
|
|
472
|
+
project_name=project.name,
|
|
473
|
+
chatroom_name=chatroom_name,
|
|
474
|
+
active_participants=list(active_participants),
|
|
475
|
+
),
|
|
476
|
+
)
|
|
477
|
+
return await self.broadcast_to_project(envelope, project)
|
|
478
|
+
|
|
479
|
+
def recipients_for_project(self, project: "Project") -> set[str]:
|
|
480
|
+
"""Everyone a project broadcast is for, connected or not.
|
|
481
|
+
|
|
482
|
+
- All participating agents
|
|
483
|
+
- The coordinator (assistant)
|
|
484
|
+
- The project owner (user)
|
|
485
|
+
- Users the project is shared with read-only
|
|
486
|
+
- The cross-user Front Desk requester of a DM project
|
|
487
|
+
|
|
488
|
+
Sends nothing; ``broadcast_to_project`` delivers to whichever of these
|
|
489
|
+
hold a live socket.
|
|
490
|
+
"""
|
|
491
|
+
recipients: set[str] = set(project.participating_agents)
|
|
492
|
+
recipients.add(project.coordinator_id)
|
|
493
|
+
recipients.add(project.created_by)
|
|
494
|
+
|
|
495
|
+
if self._data_dir:
|
|
496
|
+
from manigent.models.share_token import get_viewers_for_project
|
|
497
|
+
for viewer_id in get_viewers_for_project(project.id, self._data_dir):
|
|
498
|
+
recipients.add(viewer_id)
|
|
499
|
+
|
|
500
|
+
# Cross-user Front Desk: the requester reads/writes this DM channel via
|
|
501
|
+
# the fd_requester_name predicate (messages.py:_is_fd_requester) but is
|
|
502
|
+
# neither owner, participant, nor viewer — so add them, or they never
|
|
503
|
+
# get the ACTIVE_WORK_CHANGE push and the "processing" indicator never
|
|
504
|
+
# appears (and reply pushes fall back to the 5s poll).
|
|
505
|
+
if self._model_ctx is not None and project.is_dm_project and project.fd_requester_name:
|
|
506
|
+
from manigent.models.user import User
|
|
507
|
+
requester = User.get_by_username(project.fd_requester_name, self._model_ctx)
|
|
508
|
+
if requester is not None:
|
|
509
|
+
recipients.add(requester.id)
|
|
510
|
+
return recipients
|
|
511
|
+
|
|
512
|
+
def deliverable_recipients(self, project: "Project") -> set[str]:
|
|
513
|
+
"""``recipients_for_project`` minus the agents the isolation gate
|
|
514
|
+
withholds this project from (incapable runners, isolated project)."""
|
|
515
|
+
recipients = self.recipients_for_project(project)
|
|
516
|
+
gate = self.isolation_gate
|
|
517
|
+
if gate is None:
|
|
518
|
+
return recipients
|
|
519
|
+
return {r for r in recipients if gate.may_deliver(r, project)}
|
|
520
|
+
|
|
521
|
+
async def broadcast_to_project(
|
|
522
|
+
self,
|
|
523
|
+
envelope: ControlEnvelope,
|
|
524
|
+
project: "Project",
|
|
525
|
+
) -> int:
|
|
526
|
+
"""Broadcast envelope to all participants of a project.
|
|
527
|
+
|
|
528
|
+
Sends the same envelope to every live session of everyone in
|
|
529
|
+
``recipients_for_project``.
|
|
530
|
+
|
|
531
|
+
Args:
|
|
532
|
+
envelope: The control envelope to broadcast (no 'to' field needed)
|
|
533
|
+
project: The project whose participants should receive the message
|
|
534
|
+
|
|
535
|
+
Returns:
|
|
536
|
+
Number of recipients notified (each counted once, regardless of
|
|
537
|
+
how many live sessions they hold)
|
|
538
|
+
"""
|
|
539
|
+
count = 0
|
|
540
|
+
recipients = self.deliverable_recipients(project)
|
|
541
|
+
|
|
542
|
+
logger.info(f"Broadcasting to project {project.id[:8]}: {len(recipients)} recipients")
|
|
543
|
+
|
|
544
|
+
# Send same envelope to each connected recipient (fanning out across
|
|
545
|
+
# all of a recipient's live sessions)
|
|
546
|
+
for recipient_id in recipients:
|
|
547
|
+
conns = list(self._conns.get(recipient_id, ()))
|
|
548
|
+
logger.debug(f" Participant {recipient_id[:8]}: sessions={len(conns)}")
|
|
549
|
+
|
|
550
|
+
if conns:
|
|
551
|
+
for q in conns:
|
|
552
|
+
await q.put(envelope)
|
|
553
|
+
count += 1
|
|
554
|
+
|
|
555
|
+
logger.info(f"Broadcast complete: {count} recipients notified")
|
|
556
|
+
return count
|
manigent/server_cli.py
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# SPDX-License-Identifier: BUSL-1.1
|
|
2
|
+
"""
|
|
3
|
+
Server-only CLI entry point for the manigent-server package.
|
|
4
|
+
|
|
5
|
+
The installed command is ``manigent-server``; it carries exactly the two
|
|
6
|
+
server-host groups the monorepo's ``manigent/cli.py`` gets from cli_server
|
|
7
|
+
(``server`` and ``admin``), so commands read ``manigent-server server start``.
|
|
8
|
+
Copied to ``manigent/server_cli.py`` by scripts/build-server-package.sh, a
|
|
9
|
+
path of its own so it never collides with the runner's ``manigent/cli.py``.
|
|
10
|
+
"""
|
|
11
|
+
from __future__ import annotations
|
|
12
|
+
|
|
13
|
+
import typer
|
|
14
|
+
|
|
15
|
+
from manigent.cli_server import admin_app, server_app
|
|
16
|
+
|
|
17
|
+
app = typer.Typer(
|
|
18
|
+
name="manigent-server",
|
|
19
|
+
help="Manigent server: run the HTTP + WebSocket server and operate on its data dir.",
|
|
20
|
+
no_args_is_help=True,
|
|
21
|
+
)
|
|
22
|
+
app.add_typer(server_app, name="server")
|
|
23
|
+
app.add_typer(admin_app, name="admin")
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def main() -> None:
|
|
27
|
+
app()
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
if __name__ == "__main__":
|
|
31
|
+
main()
|