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
manigent/server/app.py
ADDED
|
@@ -0,0 +1,807 @@
|
|
|
1
|
+
# SPDX-License-Identifier: BUSL-1.1
|
|
2
|
+
"""
|
|
3
|
+
manigent/server/app.py
|
|
4
|
+
FastAPI application factory.
|
|
5
|
+
|
|
6
|
+
This module creates the FastAPI app and registers all route modules.
|
|
7
|
+
Business logic has been extracted to:
|
|
8
|
+
- routes/ - HTTP and WebSocket route handlers
|
|
9
|
+
- services/ - Shared services and context
|
|
10
|
+
"""
|
|
11
|
+
from __future__ import annotations
|
|
12
|
+
|
|
13
|
+
import asyncio
|
|
14
|
+
import logging
|
|
15
|
+
import os
|
|
16
|
+
from pathlib import Path
|
|
17
|
+
from typing import Mapping, Optional
|
|
18
|
+
|
|
19
|
+
from fastapi import FastAPI
|
|
20
|
+
from fastapi.middleware.cors import CORSMiddleware
|
|
21
|
+
from fastapi.responses import FileResponse, RedirectResponse
|
|
22
|
+
|
|
23
|
+
from manigent.models.work_tracker import WorkTracker
|
|
24
|
+
from manigent.models.managed_job import ManagedJobStore
|
|
25
|
+
from manigent.models.user import User
|
|
26
|
+
from .ws_hub import WSHub
|
|
27
|
+
from .edge_hub import EdgeWSHub
|
|
28
|
+
from manigent.server.agent_capabilities import AgentCapabilityRegistry
|
|
29
|
+
from manigent.server.signup_policy import load_signup_policy, warn_if_exposed
|
|
30
|
+
from manigent.server.config import public_app_url
|
|
31
|
+
from manigent.server.isolation_gate import HeldWorkStore, IsolationGate, IsolationHeaderMiddleware
|
|
32
|
+
from manigent.server.isolation_notice import IsolationNotice
|
|
33
|
+
from manigent.server.coordinator_rule import ForeignCoordinator, compose_guards, coordinator_guard
|
|
34
|
+
from manigent.server.owner_isolation import OwnerIsolationService, OwnerIsolationStore
|
|
35
|
+
from manigent.server.serving_only import ServingOnlyMiddleware
|
|
36
|
+
from manigent.server.turn_tokens import TurnGrantStore, TurnTokenMiddleware, TurnTokenService
|
|
37
|
+
from manigent.server.routes.owner_isolation import create_owner_isolation_router
|
|
38
|
+
from manigent.server.routes.turn_tokens import create_turn_tokens_router
|
|
39
|
+
from manigent.server.hub.retain import migrate_local_retains
|
|
40
|
+
from manigent.server.requester_key_migration import (
|
|
41
|
+
migrate_hub_thread_marks, migrate_owner_coordinators, migrate_requester_keys, migrate_scoped_turn_projects,
|
|
42
|
+
)
|
|
43
|
+
from .auth import JWT_SECRET, AuthService
|
|
44
|
+
from .idempotency import IdempotencyMiddleware, IdempotencyStore
|
|
45
|
+
from .managed_job_events import restore_active_jobs
|
|
46
|
+
from .timeout_checker import BatchTimeoutChecker
|
|
47
|
+
from .message_scheduler import MessageScheduler
|
|
48
|
+
from .reflection_scheduler import ReflectionScheduler
|
|
49
|
+
from manigent.models.context import ModelContext
|
|
50
|
+
from manigent.models.project_report import backfill_report_published_at
|
|
51
|
+
from manigent.models.scheduled_message import ScheduledMessageStore
|
|
52
|
+
from manigent.models.reflection_schedule import ReflectionScheduleStore
|
|
53
|
+
from .reflection_completion_subscriber import ReflectionCompletionSubscriber
|
|
54
|
+
from .tunnel_subscriber import TunnelSubscriber
|
|
55
|
+
from .hub.room_bridge import RoomBridgeSubscriber
|
|
56
|
+
from .chat_search_index import ChatSearchIndex, ChatSearchIndexSubscriber
|
|
57
|
+
from manigent.utils.notification_center import NotificationCenter
|
|
58
|
+
from manigent.sync.runloop_manager import ChangelogRunloopManager
|
|
59
|
+
from .context import ServerContext
|
|
60
|
+
from .config import cors_allow_origins
|
|
61
|
+
from .routes.agents import create_agents_router
|
|
62
|
+
from .routes.public_agents import create_public_agents_router
|
|
63
|
+
from .routes.agent_env import create_agent_env_router
|
|
64
|
+
from .routes.isolation_check import create_isolation_check_router
|
|
65
|
+
from .routes.agent_fs import create_agent_fs_router
|
|
66
|
+
from .routes.auth import create_auth_router
|
|
67
|
+
from .routes.projects import create_projects_router
|
|
68
|
+
from .routes.chatrooms import create_chatrooms_router
|
|
69
|
+
from .routes.files import create_files_router
|
|
70
|
+
from .routes.messages import create_messages_router
|
|
71
|
+
from .routes.changelog import create_changelog_router
|
|
72
|
+
from .inspection import build_outside_ingress
|
|
73
|
+
from .room_flow import RoomFlowSwitch
|
|
74
|
+
from .routes.websocket import create_websocket_router
|
|
75
|
+
from .routes.announcements import create_announcements_router
|
|
76
|
+
from .routes.scheduled_messages import create_scheduled_messages_router
|
|
77
|
+
from .routes.managed_jobs import create_managed_jobs_router
|
|
78
|
+
from .routes.reflection import create_reflection_router
|
|
79
|
+
from .routes.model_defaults import create_model_defaults_router
|
|
80
|
+
from .routes.sharing import create_sharing_router
|
|
81
|
+
from .routes.skills import create_skills_router
|
|
82
|
+
from .routes.knowledge_packs import create_knowledge_packs_router
|
|
83
|
+
from .routes.brief_tabs import (
|
|
84
|
+
BriefBodyLimitMiddleware,
|
|
85
|
+
create_brief_tabs_router,
|
|
86
|
+
)
|
|
87
|
+
from .routes.hosts import create_hosts_router
|
|
88
|
+
from .routes.install import create_install_router
|
|
89
|
+
from .routes.desk_todos import create_desk_todos_router
|
|
90
|
+
from .routes.desk_sops import create_desk_sops_router
|
|
91
|
+
from .routes.desk_labels import create_desk_labels_router
|
|
92
|
+
from .routes.desk_read_state import create_desk_read_state_router
|
|
93
|
+
from .routes.desk_tour import create_desk_tour_router
|
|
94
|
+
from .routes.desk_sign_off import create_desk_sign_off_router
|
|
95
|
+
from .routes.desk_latest_messages import create_desk_latest_messages_router
|
|
96
|
+
from .routes.project_reports import create_project_reports_router
|
|
97
|
+
from .routes.project_plans import create_project_plans_router
|
|
98
|
+
from .routes.mcps import create_mcps_router
|
|
99
|
+
from .routes.oauth import create_oauth_router
|
|
100
|
+
from .routes.oauth_login import create_oauth_login_router
|
|
101
|
+
from .routes.templates import create_templates_router
|
|
102
|
+
from .routes.inbox import create_inbox_router
|
|
103
|
+
from manigent.ws_edge.terminal_relay import TerminalRelay
|
|
104
|
+
from .home_fs_relay import HomeFsRelay
|
|
105
|
+
from .socket_events import SocketEvents
|
|
106
|
+
from .routes.search import create_search_router
|
|
107
|
+
from .routes.channels import create_channels_router
|
|
108
|
+
from .routes.hub import create_hub_router, hub_error_response
|
|
109
|
+
from .routes.hub_channels import create_hub_channels_router
|
|
110
|
+
from .routes.public_requests import create_public_requests_router
|
|
111
|
+
from .hub.browser import HubError
|
|
112
|
+
from .routes.webchat import create_webchat_router
|
|
113
|
+
from .channels.adapter import ChannelAdapter
|
|
114
|
+
from .channels.gateway import GatewayOptions, build_channel_gateway
|
|
115
|
+
from .hub.runtime import HubRuntime, HubRuntimeOptions
|
|
116
|
+
from .channels.store import ChannelStore
|
|
117
|
+
from .skill_registry import SkillRegistry
|
|
118
|
+
from .mcp_registry import McpRegistry
|
|
119
|
+
from .oauth_state import OAuthStateStore
|
|
120
|
+
from .oauth_login.handoff import LoginHandoffStore
|
|
121
|
+
from .oauth_login.cli_state import CliOAuthStateStore
|
|
122
|
+
|
|
123
|
+
logger = logging.getLogger("manigent.server")
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
def _serve_spa_file(base_dir: Path, path: str, fallback: Path) -> FileResponse:
|
|
127
|
+
"""Serve a real static file under ``base_dir`` for an SPA catch-all route,
|
|
128
|
+
falling back to the SPA entry (``fallback``) for client-side routing.
|
|
129
|
+
|
|
130
|
+
``path`` comes straight from a ``{path:path}`` URL segment, so it is
|
|
131
|
+
untrusted: a URL-encoded ``..`` would otherwise let ``base_dir / path``
|
|
132
|
+
escape the served directory and read arbitrary files the server process can
|
|
133
|
+
reach. We resolve the candidate and confirm it stays within ``base_dir``
|
|
134
|
+
before serving it; anything that escapes (or isn't a real file) falls back
|
|
135
|
+
to the SPA entry.
|
|
136
|
+
"""
|
|
137
|
+
base_resolved = base_dir.resolve()
|
|
138
|
+
try:
|
|
139
|
+
candidate = (base_dir / path).resolve()
|
|
140
|
+
candidate.relative_to(base_resolved) # ValueError if it escapes base_dir
|
|
141
|
+
except ValueError:
|
|
142
|
+
return FileResponse(fallback)
|
|
143
|
+
if candidate.is_file():
|
|
144
|
+
return FileResponse(candidate)
|
|
145
|
+
return FileResponse(fallback)
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
def create_app(
|
|
149
|
+
data_dir: Path,
|
|
150
|
+
batch_timeout: int = 1800,
|
|
151
|
+
skills_dir: Path | None = None,
|
|
152
|
+
mcps_dir: Path | None = None,
|
|
153
|
+
agent_pool_dir: Path | None = None,
|
|
154
|
+
announcements_path: Path | None = None,
|
|
155
|
+
channel_env: Optional[Mapping[str, str]] = None,
|
|
156
|
+
channel_adapters: Optional[Mapping[str, ChannelAdapter]] = None,
|
|
157
|
+
channel_options: Optional[GatewayOptions] = None,
|
|
158
|
+
ws_mode: Optional[str] = None,
|
|
159
|
+
edge_link_url: Optional[str] = None,
|
|
160
|
+
edge_link_secret: Optional[str] = None,
|
|
161
|
+
hub_options: Optional[HubRuntimeOptions] = None,
|
|
162
|
+
) -> FastAPI:
|
|
163
|
+
"""Create and configure the FastAPI application.
|
|
164
|
+
|
|
165
|
+
Args:
|
|
166
|
+
data_dir: Base directory for all server data
|
|
167
|
+
batch_timeout: Batch timeout in seconds (default: 1800)
|
|
168
|
+
skills_dir: Directory containing skills registry (optional)
|
|
169
|
+
mcps_dir: Directory containing MCP servers registry (optional)
|
|
170
|
+
agent_pool_dir: A manigent-agents checkout: the agent catalog (optional)
|
|
171
|
+
announcements_path: Path to announcements.json (optional; defaults to
|
|
172
|
+
the repo-root file resolved by manigent/server/announcements.py)
|
|
173
|
+
channel_env: Environment the channel kill switch, channel settings and
|
|
174
|
+
hub settings are read from (default ``os.environ``; tests pass a dict).
|
|
175
|
+
channel_adapters: Channel name -> adapter. No real provider ships yet;
|
|
176
|
+
tests pass a fake one.
|
|
177
|
+
channel_options: Gateway clock, burst window, crash hooks (tests).
|
|
178
|
+
hub_options: The hub runtime's injection points: the socket's
|
|
179
|
+
connect, the reclaim's HTTP transport, the registration poll
|
|
180
|
+
(tests; production uses the defaults).
|
|
181
|
+
ws_mode: ``inprocess`` (default; this process holds the sockets) or
|
|
182
|
+
``edge`` (the websocket edge holds them and this process dials it).
|
|
183
|
+
Defaults to ``$MANIGENT_WS_MODE``.
|
|
184
|
+
edge_link_url / edge_link_secret: where to dial the edge and the
|
|
185
|
+
shared secret, in edge mode. Default to
|
|
186
|
+
``$MANIGENT_EDGE_LINK_URL`` / ``$MANIGENT_EDGE_LINK_SECRET``.
|
|
187
|
+
|
|
188
|
+
Returns:
|
|
189
|
+
Configured FastAPI application
|
|
190
|
+
|
|
191
|
+
Raises:
|
|
192
|
+
HubConfigError: ``MANIGENT_HUB_MODE`` is not ``off`` and the hub
|
|
193
|
+
settings are invalid (the message names each setting at fault).
|
|
194
|
+
The server must not start; a broken CHANNEL configuration, by
|
|
195
|
+
contrast, only keeps the channel gateway off.
|
|
196
|
+
"""
|
|
197
|
+
data_dir.mkdir(parents=True, exist_ok=True)
|
|
198
|
+
|
|
199
|
+
# Create shared ModelContext for file and message I/O
|
|
200
|
+
# This is the server-wide context used by UnifiedChangelog
|
|
201
|
+
model_ctx = ModelContext(base_dir=data_dir, notification_center=NotificationCenter())
|
|
202
|
+
|
|
203
|
+
# Initialize services
|
|
204
|
+
ws_mode = (ws_mode or os.environ.get("MANIGENT_WS_MODE") or "inprocess").strip().lower()
|
|
205
|
+
if ws_mode not in ("inprocess", "edge"):
|
|
206
|
+
raise RuntimeError(f"MANIGENT_WS_MODE must be 'inprocess' or 'edge', not {ws_mode!r}")
|
|
207
|
+
if ws_mode == "edge":
|
|
208
|
+
link_url = edge_link_url or os.environ.get("MANIGENT_EDGE_LINK_URL") or "ws://127.0.0.1:8091/link"
|
|
209
|
+
link_secret = edge_link_secret or os.environ.get("MANIGENT_EDGE_LINK_SECRET")
|
|
210
|
+
if not link_secret:
|
|
211
|
+
raise RuntimeError("MANIGENT_WS_MODE=edge needs MANIGENT_EDGE_LINK_SECRET")
|
|
212
|
+
if "MANIGENT_JWT_SECRET" not in os.environ:
|
|
213
|
+
# The edge checks user tokens itself; with a per-process random
|
|
214
|
+
# secret no browser could ever connect.
|
|
215
|
+
logger.warning("MANIGENT_WS_MODE=edge without MANIGENT_JWT_SECRET: browsers cannot connect")
|
|
216
|
+
ws_hub: WSHub = EdgeWSHub(link_url, link_secret, data_dir=data_dir, model_ctx=model_ctx)
|
|
217
|
+
else:
|
|
218
|
+
ws_hub = WSHub(data_dir=data_dir, model_ctx=model_ctx)
|
|
219
|
+
|
|
220
|
+
# Bridge WorkTracker state transitions to a WebSocket push so the frontend
|
|
221
|
+
# sidebar's active-work indicators and in-room typing indicators both read
|
|
222
|
+
# from the same signal (no polling).
|
|
223
|
+
from manigent.models.project import Project
|
|
224
|
+
|
|
225
|
+
async def _on_work_change(
|
|
226
|
+
project_id: str, chatroom_name: str, active_participants: list[str]
|
|
227
|
+
) -> None:
|
|
228
|
+
project = Project.get(project_id, model_ctx)
|
|
229
|
+
if project is None:
|
|
230
|
+
return
|
|
231
|
+
await ws_hub.broadcast_active_work_change(
|
|
232
|
+
project, chatroom_name, active_participants
|
|
233
|
+
)
|
|
234
|
+
|
|
235
|
+
work_tracker = WorkTracker(on_change=_on_work_change)
|
|
236
|
+
managed_job_store = ManagedJobStore(data_dir)
|
|
237
|
+
|
|
238
|
+
# Initialize auth service
|
|
239
|
+
auth = AuthService(model_ctx)
|
|
240
|
+
|
|
241
|
+
# Create runloop manager for per-project changelog processing
|
|
242
|
+
reflection_completion_subscriber = ReflectionCompletionSubscriber(model_ctx)
|
|
243
|
+
reflection_completion_subscriber.bind_ws_hub(ws_hub)
|
|
244
|
+
# TunnelSubscriber needs a back-reference to the runloop manager so it can
|
|
245
|
+
# append mirrored entries onto the other end of a binding. Construct it
|
|
246
|
+
# first (without the manager), then bind after the manager exists.
|
|
247
|
+
tunnel_subscriber = TunnelSubscriber(model_ctx)
|
|
248
|
+
# The room bridge: relays addressed workroom messages to retained hub
|
|
249
|
+
# agents (server/hub/room_bridge.py). Bound to the context below.
|
|
250
|
+
room_bridge_subscriber = RoomBridgeSubscriber()
|
|
251
|
+
# Derived FTS5 chat-message index. Registered immediately AFTER the
|
|
252
|
+
# subscriber that writes CHATS.ndjson, so it indexes a row that is already
|
|
253
|
+
# durable rather than racing the write.
|
|
254
|
+
chat_search_index = ChatSearchIndex(model_ctx)
|
|
255
|
+
chat_search_subscriber = ChatSearchIndexSubscriber(chat_search_index, model_ctx)
|
|
256
|
+
runloop_manager = ChangelogRunloopManager(
|
|
257
|
+
runloop_factory=lambda pid, pname, cid: (
|
|
258
|
+
model_ctx.changelog_dir(pid, pname),
|
|
259
|
+
[
|
|
260
|
+
model_ctx.changelog_subscriber(pid, pname),
|
|
261
|
+
chat_search_subscriber,
|
|
262
|
+
reflection_completion_subscriber,
|
|
263
|
+
tunnel_subscriber,
|
|
264
|
+
room_bridge_subscriber,
|
|
265
|
+
],
|
|
266
|
+
),
|
|
267
|
+
)
|
|
268
|
+
tunnel_subscriber.bind_runloop_manager(runloop_manager)
|
|
269
|
+
tunnel_subscriber.bind_ws_hub(ws_hub)
|
|
270
|
+
tunnel_subscriber.bind_work_tracker(work_tracker, batch_timeout)
|
|
271
|
+
|
|
272
|
+
# Create timeout checker for batch completion enforcement
|
|
273
|
+
timeout_checker = BatchTimeoutChecker(
|
|
274
|
+
work_tracker=work_tracker,
|
|
275
|
+
runloop_manager=runloop_manager,
|
|
276
|
+
ws_hub=ws_hub,
|
|
277
|
+
model_ctx=model_ctx,
|
|
278
|
+
batch_timeout=batch_timeout,
|
|
279
|
+
)
|
|
280
|
+
timeout_checker.bind_managed_job_store(managed_job_store)
|
|
281
|
+
|
|
282
|
+
# Create scheduled message store and scheduler
|
|
283
|
+
scheduled_message_store = ScheduledMessageStore(model_ctx)
|
|
284
|
+
message_scheduler = MessageScheduler(
|
|
285
|
+
store=scheduled_message_store,
|
|
286
|
+
runloop_manager=runloop_manager,
|
|
287
|
+
ws_hub=ws_hub,
|
|
288
|
+
model_ctx=model_ctx,
|
|
289
|
+
work_tracker=work_tracker,
|
|
290
|
+
batch_timeout=batch_timeout,
|
|
291
|
+
)
|
|
292
|
+
|
|
293
|
+
# Create reflection schedule store and scheduler
|
|
294
|
+
reflection_schedule_store = ReflectionScheduleStore(model_ctx)
|
|
295
|
+
reflection_scheduler = ReflectionScheduler(
|
|
296
|
+
store=reflection_schedule_store,
|
|
297
|
+
runloop_manager=runloop_manager,
|
|
298
|
+
ws_hub=ws_hub,
|
|
299
|
+
model_ctx=model_ctx,
|
|
300
|
+
)
|
|
301
|
+
|
|
302
|
+
# Who may sign up. A bad value stops boot here, like a bad hub config.
|
|
303
|
+
signup_policy = load_signup_policy()
|
|
304
|
+
warn_if_exposed(signup_policy, public_app_url())
|
|
305
|
+
|
|
306
|
+
# In-memory state store for the MCP OAuth relay flow
|
|
307
|
+
oauth_state_store = OAuthStateStore()
|
|
308
|
+
|
|
309
|
+
# In-memory single-use store for OAuth-login exchange handoff codes
|
|
310
|
+
login_handoff_store = LoginHandoffStore()
|
|
311
|
+
|
|
312
|
+
# In-memory single-use store for CLI OAuth pending states + PKCE bindings
|
|
313
|
+
cli_oauth_state_store = CliOAuthStateStore()
|
|
314
|
+
|
|
315
|
+
# Create server context
|
|
316
|
+
ctx = ServerContext(
|
|
317
|
+
model_ctx=model_ctx,
|
|
318
|
+
ws_hub=ws_hub,
|
|
319
|
+
work_tracker=work_tracker,
|
|
320
|
+
auth=auth,
|
|
321
|
+
runloop_manager=runloop_manager,
|
|
322
|
+
timeout_checker=timeout_checker,
|
|
323
|
+
scheduled_message_store=scheduled_message_store,
|
|
324
|
+
message_scheduler=message_scheduler,
|
|
325
|
+
reflection_schedule_store=reflection_schedule_store,
|
|
326
|
+
reflection_scheduler=reflection_scheduler,
|
|
327
|
+
managed_job_store=managed_job_store,
|
|
328
|
+
oauth_state_store=oauth_state_store,
|
|
329
|
+
login_handoff_store=login_handoff_store,
|
|
330
|
+
cli_oauth_state_store=cli_oauth_state_store,
|
|
331
|
+
chat_search_index=chat_search_index,
|
|
332
|
+
# In edge mode terminal sessions live in the edge, next to both sockets.
|
|
333
|
+
terminal_relay=(
|
|
334
|
+
TerminalRelay(ws_hub, model_ctx.participants_dir, JWT_SECRET)
|
|
335
|
+
if ws_mode == "inprocess" else None
|
|
336
|
+
),
|
|
337
|
+
home_fs_relay=HomeFsRelay(ws_hub, model_ctx.participants_dir),
|
|
338
|
+
batch_timeout=batch_timeout,
|
|
339
|
+
skills_dir=skills_dir,
|
|
340
|
+
mcps_dir=mcps_dir,
|
|
341
|
+
agent_pool_dir=agent_pool_dir,
|
|
342
|
+
announcements_path=announcements_path,
|
|
343
|
+
signup_policy=signup_policy,
|
|
344
|
+
)
|
|
345
|
+
|
|
346
|
+
ctx.socket_events = SocketEvents(ctx)
|
|
347
|
+
turn_token_service = TurnTokenService(
|
|
348
|
+
TurnGrantStore(data_dir / "isolation" / "turn_grants.sqlite3"), JWT_SECRET,
|
|
349
|
+
)
|
|
350
|
+
ctx.isolation_gate = IsolationGate(
|
|
351
|
+
model_ctx,
|
|
352
|
+
AgentCapabilityRegistry(ws_hub),
|
|
353
|
+
turn_token_service,
|
|
354
|
+
HeldWorkStore(data_dir / "isolation" / "held_work.sqlite3"),
|
|
355
|
+
JWT_SECRET,
|
|
356
|
+
)
|
|
357
|
+
ctx.isolation_gate.bind(ctx)
|
|
358
|
+
# Held because the agent cannot isolate: tell its owner and the requester.
|
|
359
|
+
ctx.isolation_gate.notice = IsolationNotice(ctx)
|
|
360
|
+
ctx.owner_isolation = OwnerIsolationService(
|
|
361
|
+
model_ctx, ws_hub, OwnerIsolationStore(data_dir / "isolation" / "owner_isolation.sqlite3"),
|
|
362
|
+
)
|
|
363
|
+
ctx.owner_isolation.capabilities = ctx.isolation_gate.capabilities
|
|
364
|
+
ctx.owner_isolation.load_enabled()
|
|
365
|
+
# Every outside message passes the inspection hook before it is stored;
|
|
366
|
+
# the append guard refuses one that did not (server/inspection.py).
|
|
367
|
+
ctx.outside_ingress = build_outside_ingress(
|
|
368
|
+
data_dir, model_ctx, env=channel_env if channel_env is not None else os.environ,
|
|
369
|
+
)
|
|
370
|
+
ctx.outside_ingress.bind(ctx)
|
|
371
|
+
ctx.room_flow = RoomFlowSwitch(ctx)
|
|
372
|
+
# Plus the own-coordinator rule (plan-owner-isolation section 4): no
|
|
373
|
+
# append may make a stand-in or another account's agent a coordinator.
|
|
374
|
+
runloop_manager.set_append_guard(compose_guards(ctx.outside_ingress.guard, coordinator_guard(model_ctx)))
|
|
375
|
+
ws_hub.isolation_gate = ctx.isolation_gate
|
|
376
|
+
if isinstance(ws_hub, EdgeWSHub):
|
|
377
|
+
ws_hub.bind(ctx)
|
|
378
|
+
|
|
379
|
+
# Channel gateway. The store opens either way; the gateway exists when the
|
|
380
|
+
# channel kill switch is on and its configuration is valid, when the hub is
|
|
381
|
+
# on, or while open hub rows remain to be swept (build_channel_gateway).
|
|
382
|
+
# Raises only HubConfigError, which must stop the server.
|
|
383
|
+
ctx.channel_store = ChannelStore(data_dir)
|
|
384
|
+
ctx.channel_gateway = build_channel_gateway(
|
|
385
|
+
ctx, ctx.channel_store, env=channel_env,
|
|
386
|
+
adapters=channel_adapters, options=channel_options,
|
|
387
|
+
)
|
|
388
|
+
# The hub runtime rides on the gateway (it exists whenever the hub is
|
|
389
|
+
# configured, or open hub rows remain); in mode off it builds no client.
|
|
390
|
+
if ctx.channel_gateway is not None:
|
|
391
|
+
ctx.hub_runtime = HubRuntime(ctx, ctx.channel_gateway, options=hub_options)
|
|
392
|
+
|
|
393
|
+
# TunnelSubscriber's detect-and-route path needs the full ServerContext to
|
|
394
|
+
# call `ensure_fd_routing_for_foreign_agents`. Bind after the context is
|
|
395
|
+
# constructed (chicken-and-egg with runloop_manager handled above).
|
|
396
|
+
tunnel_subscriber.bind_server_context(ctx)
|
|
397
|
+
room_bridge_subscriber.bind_server_context(ctx)
|
|
398
|
+
ctx.room_bridge_subscriber = room_bridge_subscriber
|
|
399
|
+
|
|
400
|
+
# What re-delivers a held outside message when its room reopens: each
|
|
401
|
+
# path's own append (server/inspection.py release_held).
|
|
402
|
+
from .inspection import OutsidePath
|
|
403
|
+
|
|
404
|
+
ingress = ctx.outside_ingress
|
|
405
|
+
ingress.register_deliverer(OutsidePath.CROSS_ACCOUNT_RELAY, tunnel_subscriber.deliver_held)
|
|
406
|
+
ingress.register_deliverer(OutsidePath.FRONT_DESK_REQUESTER, tunnel_subscriber.deliver_held)
|
|
407
|
+
# ...and what tells the sender side when one expires instead (expire_held).
|
|
408
|
+
ingress.register_closer(OutsidePath.CROSS_ACCOUNT_RELAY, tunnel_subscriber.close_held)
|
|
409
|
+
ingress.register_closer(OutsidePath.FRONT_DESK_REQUESTER, tunnel_subscriber.close_held)
|
|
410
|
+
# ...and what a block on release does beyond the audit and room note:
|
|
411
|
+
# the path's own live-block effects (release_held).
|
|
412
|
+
ingress.register_blocker(OutsidePath.CROSS_ACCOUNT_RELAY, tunnel_subscriber.block_held)
|
|
413
|
+
ingress.register_blocker(OutsidePath.FRONT_DESK_REQUESTER, tunnel_subscriber.block_held)
|
|
414
|
+
if ctx.channel_gateway is not None:
|
|
415
|
+
ingress.register_deliverer(OutsidePath.CHANNEL_INBOUND, ctx.channel_gateway.deliver_held)
|
|
416
|
+
ingress.register_deliverer(OutsidePath.HUB_INBOUND, ctx.channel_gateway.deliver_held)
|
|
417
|
+
ingress.register_blocker(OutsidePath.CHANNEL_INBOUND, ctx.channel_gateway.block_held)
|
|
418
|
+
ingress.register_blocker(OutsidePath.HUB_INBOUND, ctx.channel_gateway.block_held)
|
|
419
|
+
if ctx.hub_runtime is not None:
|
|
420
|
+
ingress.register_deliverer(OutsidePath.HUB_REPLY_DM, ctx.hub_runtime.mirror.deliver_held_reply)
|
|
421
|
+
ingress.register_deliverer(OutsidePath.HUB_REPLY_BRIDGE, ctx.hub_runtime.bridge.deliver_reply)
|
|
422
|
+
ingress.register_deliverer(OutsidePath.BRIDGE_OUTBOUND, ctx.hub_runtime.bridge.send_relay)
|
|
423
|
+
ingress.register_closer(OutsidePath.BRIDGE_OUTBOUND, ctx.hub_runtime.bridge.close_held_relay)
|
|
424
|
+
ingress.register_blocker(OutsidePath.HUB_REPLY_DM, ctx.hub_runtime.mirror.block_held_reply)
|
|
425
|
+
ingress.register_blocker(OutsidePath.HUB_REPLY_BRIDGE, ctx.hub_runtime.bridge.block_reply)
|
|
426
|
+
ingress.register_blocker(OutsidePath.BRIDGE_OUTBOUND, ctx.hub_runtime.bridge.block_held_relay)
|
|
427
|
+
from .routes.messages import FD_REQUESTER_POST, deliver_held_fd_requester_post
|
|
428
|
+
|
|
429
|
+
ingress.register_deliverer(
|
|
430
|
+
FD_REQUESTER_POST, lambda replay, ticket: deliver_held_fd_requester_post(ctx, replay, ticket),
|
|
431
|
+
)
|
|
432
|
+
|
|
433
|
+
# A direct post was answered "delivered on reopen": when it is blocked
|
|
434
|
+
# or expires instead, the requester's room (the one it was posted into)
|
|
435
|
+
# is told. Never quotes the message.
|
|
436
|
+
async def _tell_fd_requester(replay, tail: str) -> None:
|
|
437
|
+
await ingress.post_note(replay["project_id"], replay["chatroom"],
|
|
438
|
+
f"A message from {replay.get('author_name') or 'the requester'} {tail}")
|
|
439
|
+
|
|
440
|
+
ingress.register_blocker(
|
|
441
|
+
FD_REQUESTER_POST, lambda replay: _tell_fd_requester(replay, "was blocked; it was not delivered."),
|
|
442
|
+
)
|
|
443
|
+
ingress.register_closer(
|
|
444
|
+
FD_REQUESTER_POST,
|
|
445
|
+
lambda replay: _tell_fd_requester(replay, "was held for review and expired; it was not delivered."),
|
|
446
|
+
)
|
|
447
|
+
|
|
448
|
+
# Create skill registry (if skills_dir provided)
|
|
449
|
+
skill_registry: SkillRegistry | None = None
|
|
450
|
+
if skills_dir and skills_dir.exists():
|
|
451
|
+
skill_registry = SkillRegistry(skills_dir)
|
|
452
|
+
logger.info(f"Skill registry loaded from {skills_dir}")
|
|
453
|
+
|
|
454
|
+
# Create MCP registry (if mcps_dir provided)
|
|
455
|
+
mcp_registry: McpRegistry | None = None
|
|
456
|
+
if mcps_dir and mcps_dir.exists():
|
|
457
|
+
mcp_registry = McpRegistry(mcps_dir)
|
|
458
|
+
logger.info(f"MCP registry loaded from {mcps_dir}")
|
|
459
|
+
|
|
460
|
+
# Create FastAPI app
|
|
461
|
+
app = FastAPI(title="Manigent", version="0.1.0")
|
|
462
|
+
# The context behind every route; tests reach the channel gateway through it.
|
|
463
|
+
app.state.server_ctx = ctx
|
|
464
|
+
|
|
465
|
+
# Answers a retried write from the record of its first attempt. Added
|
|
466
|
+
# BEFORE CORS so CORS stays outermost and decorates replays too.
|
|
467
|
+
idempotency_store = IdempotencyStore(data_dir / "idempotency")
|
|
468
|
+
app.add_middleware(IdempotencyMiddleware, store=idempotency_store)
|
|
469
|
+
|
|
470
|
+
# CORS middleware — explicit allowlist (MANIGENT_CORS_ORIGINS +
|
|
471
|
+
# MANIGENT_APP_URL), env-configurable. Falls back to ["*"] only when
|
|
472
|
+
# nothing is configured (dev/test).
|
|
473
|
+
cors_origins = cors_allow_origins()
|
|
474
|
+
if cors_origins == ["*"]:
|
|
475
|
+
logger.info("CORS: no allowlist configured, allowing all origins (dev)")
|
|
476
|
+
else:
|
|
477
|
+
logger.info(f"CORS allowlist: {cors_origins}")
|
|
478
|
+
app.add_middleware(
|
|
479
|
+
CORSMiddleware,
|
|
480
|
+
allow_origins=cors_origins,
|
|
481
|
+
allow_credentials=True,
|
|
482
|
+
allow_methods=["*"],
|
|
483
|
+
allow_headers=["*"],
|
|
484
|
+
expose_headers=["*"],
|
|
485
|
+
)
|
|
486
|
+
|
|
487
|
+
# Rejects an oversized PUT /me/brief/tabs/{slug} on Content-Length
|
|
488
|
+
# BEFORE FastAPI buffers the body — the in-handler check runs after
|
|
489
|
+
# that buffering and so is a status code, not a mitigation. Scoped to
|
|
490
|
+
# that one path; every other request passes straight through.
|
|
491
|
+
app.add_middleware(BriefBodyLimitMiddleware)
|
|
492
|
+
|
|
493
|
+
# A turn token (a scoped turn's credential) reaches only the read routes
|
|
494
|
+
# of its grant's projects; anything else is answered turn_scope [403]
|
|
495
|
+
# before a route runs (server/turn_tokens.py).
|
|
496
|
+
app.add_middleware(
|
|
497
|
+
TurnTokenMiddleware,
|
|
498
|
+
service_getter=lambda: ctx.isolation_gate.turn_tokens if ctx.isolation_gate else None,
|
|
499
|
+
)
|
|
500
|
+
|
|
501
|
+
# Records X-Manigent-Isolation for the isolation gate's read check.
|
|
502
|
+
app.add_middleware(IsolationHeaderMiddleware)
|
|
503
|
+
# An owner-isolated agent's own token reaches only the serving-only
|
|
504
|
+
# allowlist (plan-owner-isolation 5d).
|
|
505
|
+
app.add_middleware(ServingOnlyMiddleware, ctx_getter=lambda: ctx)
|
|
506
|
+
|
|
507
|
+
# Register route modules
|
|
508
|
+
app.include_router(create_auth_router(ctx))
|
|
509
|
+
app.include_router(create_agents_router(ctx))
|
|
510
|
+
app.include_router(create_turn_tokens_router(ctx))
|
|
511
|
+
app.include_router(create_owner_isolation_router(ctx))
|
|
512
|
+
app.include_router(create_agent_env_router(ctx))
|
|
513
|
+
app.include_router(create_isolation_check_router(ctx))
|
|
514
|
+
app.include_router(create_agent_fs_router(ctx))
|
|
515
|
+
app.include_router(create_projects_router(ctx))
|
|
516
|
+
app.include_router(create_chatrooms_router(ctx))
|
|
517
|
+
app.include_router(create_files_router(ctx))
|
|
518
|
+
app.include_router(create_messages_router(ctx))
|
|
519
|
+
app.include_router(create_changelog_router(ctx))
|
|
520
|
+
if ws_mode == "inprocess":
|
|
521
|
+
app.include_router(create_websocket_router(ctx))
|
|
522
|
+
|
|
523
|
+
@app.get("/healthz/ready", include_in_schema=False)
|
|
524
|
+
async def healthz_ready():
|
|
525
|
+
"""200 once this process can serve sockets' traffic: always in
|
|
526
|
+
in-process mode, only while the edge link is up in edge mode."""
|
|
527
|
+
from fastapi.responses import JSONResponse
|
|
528
|
+
if isinstance(ws_hub, EdgeWSHub):
|
|
529
|
+
up = ws_hub.ready
|
|
530
|
+
return JSONResponse(
|
|
531
|
+
{"ws_mode": ws_mode, "edge_link": "up" if up else "down"},
|
|
532
|
+
status_code=200 if up else 503,
|
|
533
|
+
)
|
|
534
|
+
return {"ws_mode": ws_mode, "edge_link": "n/a"}
|
|
535
|
+
app.include_router(create_announcements_router(ctx))
|
|
536
|
+
app.include_router(create_scheduled_messages_router(ctx))
|
|
537
|
+
app.include_router(create_managed_jobs_router(ctx))
|
|
538
|
+
app.include_router(create_reflection_router(ctx))
|
|
539
|
+
app.include_router(create_model_defaults_router(ctx))
|
|
540
|
+
app.include_router(create_sharing_router(ctx))
|
|
541
|
+
app.include_router(create_knowledge_packs_router(ctx))
|
|
542
|
+
app.include_router(create_brief_tabs_router(ctx))
|
|
543
|
+
app.include_router(create_hosts_router(ctx))
|
|
544
|
+
app.include_router(create_install_router(ctx))
|
|
545
|
+
app.include_router(create_desk_todos_router(ctx))
|
|
546
|
+
app.include_router(create_desk_sops_router(ctx))
|
|
547
|
+
app.include_router(create_desk_labels_router(ctx))
|
|
548
|
+
app.include_router(create_desk_read_state_router(ctx))
|
|
549
|
+
app.include_router(create_desk_tour_router(ctx))
|
|
550
|
+
app.include_router(create_desk_sign_off_router(ctx))
|
|
551
|
+
app.include_router(create_desk_latest_messages_router(ctx))
|
|
552
|
+
app.include_router(create_project_reports_router(ctx))
|
|
553
|
+
app.include_router(create_project_plans_router(ctx))
|
|
554
|
+
app.include_router(create_inbox_router(ctx))
|
|
555
|
+
app.include_router(create_search_router(ctx))
|
|
556
|
+
app.include_router(create_channels_router(ctx))
|
|
557
|
+
app.include_router(create_hub_router(ctx))
|
|
558
|
+
app.include_router(create_hub_channels_router(ctx))
|
|
559
|
+
app.include_router(create_public_requests_router(ctx))
|
|
560
|
+
app.add_exception_handler(HubError, hub_error_response)
|
|
561
|
+
|
|
562
|
+
async def foreign_coordinator_response(_request, exc):
|
|
563
|
+
from fastapi.responses import JSONResponse
|
|
564
|
+
|
|
565
|
+
from manigent.server.coordinator_rule import CODE, MESSAGE
|
|
566
|
+
logger.warning("foreign_coordinator: %s", exc)
|
|
567
|
+
return JSONResponse(status_code=403, content={"detail": {"code": CODE, "message": MESSAGE}})
|
|
568
|
+
|
|
569
|
+
app.add_exception_handler(ForeignCoordinator, foreign_coordinator_response)
|
|
570
|
+
app.include_router(create_webchat_router(ctx))
|
|
571
|
+
app.include_router(create_public_agents_router(
|
|
572
|
+
ctx, Path(__file__).parent.parent / "web" / "frontend" / "dist" / "public.html",
|
|
573
|
+
))
|
|
574
|
+
app.include_router(create_oauth_router(ctx))
|
|
575
|
+
# OAuth invite-login (Google/GitHub) — mounted only when the four namespaced
|
|
576
|
+
# provider creds + MANIGENT_APP_URL are configured. Fail-fast from_env()
|
|
577
|
+
# raises when unset; we degrade to "feature off" rather than crash startup,
|
|
578
|
+
# mirroring the optional skill/mcp routers above.
|
|
579
|
+
try:
|
|
580
|
+
app.include_router(create_oauth_login_router(ctx))
|
|
581
|
+
logger.info("OAuth invite-login routes mounted (/auth/oauth/*)")
|
|
582
|
+
except RuntimeError as e:
|
|
583
|
+
logger.warning(f"OAuth invite-login not configured, routes not mounted: {e}")
|
|
584
|
+
if skill_registry:
|
|
585
|
+
app.include_router(create_skills_router(ctx, skill_registry))
|
|
586
|
+
if mcp_registry:
|
|
587
|
+
app.include_router(create_mcps_router(ctx, mcp_registry))
|
|
588
|
+
# The agent catalog: always routed, empty without a pool directory.
|
|
589
|
+
pool_dir = agent_pool_dir if agent_pool_dir and agent_pool_dir.exists() else None
|
|
590
|
+
app.include_router(create_templates_router(ctx, pool_dir))
|
|
591
|
+
if pool_dir:
|
|
592
|
+
logger.info(f"Agent pool loaded from {pool_dir}")
|
|
593
|
+
|
|
594
|
+
# Serve frontend static files
|
|
595
|
+
frontend_dist = Path(__file__).parent.parent / "web" / "frontend" / "dist"
|
|
596
|
+
|
|
597
|
+
if frontend_dist.exists():
|
|
598
|
+
logger.info(f"Frontend served from {frontend_dist}")
|
|
599
|
+
|
|
600
|
+
# Serve static assets at /app/assets/* (matches Vite build output)
|
|
601
|
+
@app.get("/app/assets/{file_path:path}", include_in_schema=False)
|
|
602
|
+
async def serve_static(file_path: str):
|
|
603
|
+
"""Serve static assets (JS, CSS, etc.)."""
|
|
604
|
+
asset_file = frontend_dist / "assets" / file_path
|
|
605
|
+
if asset_file.exists() and asset_file.is_file():
|
|
606
|
+
return FileResponse(asset_file)
|
|
607
|
+
return FileResponse(frontend_dist / "index.html", status_code=404)
|
|
608
|
+
|
|
609
|
+
# Serve landing page at root
|
|
610
|
+
@app.get("/", include_in_schema=False)
|
|
611
|
+
async def serve_root():
|
|
612
|
+
landing_file = frontend_dist / "landing.html"
|
|
613
|
+
if landing_file.exists():
|
|
614
|
+
return FileResponse(landing_file)
|
|
615
|
+
return RedirectResponse(url="/app")
|
|
616
|
+
|
|
617
|
+
# Serve TOS and Privacy pages
|
|
618
|
+
@app.get("/tos", include_in_schema=False)
|
|
619
|
+
async def serve_tos():
|
|
620
|
+
return FileResponse(frontend_dist / "tos.html")
|
|
621
|
+
|
|
622
|
+
@app.get("/privacy", include_in_schema=False)
|
|
623
|
+
async def serve_privacy():
|
|
624
|
+
return FileResponse(frontend_dist / "privacy.html")
|
|
625
|
+
|
|
626
|
+
# The hub operator terms (`manigent server hub register --accept-tos`).
|
|
627
|
+
@app.get("/hub/terms", include_in_schema=False)
|
|
628
|
+
async def serve_hub_terms():
|
|
629
|
+
return FileResponse(frontend_dist / "hub-terms.html")
|
|
630
|
+
|
|
631
|
+
@app.get("/private-beta-announcement", include_in_schema=False)
|
|
632
|
+
async def serve_private_beta_announcement():
|
|
633
|
+
return FileResponse(frontend_dist / "private-beta-announcement.html")
|
|
634
|
+
|
|
635
|
+
# Serve brand images for landing page
|
|
636
|
+
@app.get("/brand-hero.png", include_in_schema=False)
|
|
637
|
+
async def serve_brand_hero():
|
|
638
|
+
return FileResponse(frontend_dist / "brand-hero.png")
|
|
639
|
+
|
|
640
|
+
@app.get("/brand-hero-banner.png", include_in_schema=False)
|
|
641
|
+
async def serve_brand_hero_banner():
|
|
642
|
+
return FileResponse(frontend_dist / "brand-hero-banner.png")
|
|
643
|
+
|
|
644
|
+
@app.get("/icon.png", include_in_schema=False)
|
|
645
|
+
async def serve_icon():
|
|
646
|
+
return FileResponse(frontend_dist / "icon.png")
|
|
647
|
+
|
|
648
|
+
# Icons at the bare root. The HTML entries reference these through Vite's
|
|
649
|
+
# base ('/app/…'), so these routes are the fallback for the
|
|
650
|
+
# requests that never pass through our HTML: a bookmark/scraper hitting
|
|
651
|
+
# /favicon.svg, or iOS asking for /apple-touch-icon.png on "Add to Home
|
|
652
|
+
# Screen". Without them those paths fall to the 404 JSON handler.
|
|
653
|
+
@app.get("/favicon.png", include_in_schema=False)
|
|
654
|
+
async def serve_favicon():
|
|
655
|
+
return FileResponse(frontend_dist / "favicon.png")
|
|
656
|
+
|
|
657
|
+
@app.get("/favicon.svg", include_in_schema=False)
|
|
658
|
+
async def serve_favicon_svg():
|
|
659
|
+
return FileResponse(frontend_dist / "favicon.svg")
|
|
660
|
+
|
|
661
|
+
@app.get("/apple-touch-icon.png", include_in_schema=False)
|
|
662
|
+
async def serve_apple_touch_icon():
|
|
663
|
+
return FileResponse(frontend_dist / "apple-touch-icon.png")
|
|
664
|
+
|
|
665
|
+
# Serve landing page assets (CSS/JS built by Vite for the landing entry).
|
|
666
|
+
@app.get("/assets/{file_path:path}", include_in_schema=False)
|
|
667
|
+
async def serve_landing_assets(file_path: str):
|
|
668
|
+
asset_file = frontend_dist / "assets" / file_path
|
|
669
|
+
if asset_file.exists() and asset_file.is_file():
|
|
670
|
+
return FileResponse(asset_file)
|
|
671
|
+
return FileResponse(frontend_dist / "index.html", status_code=404)
|
|
672
|
+
|
|
673
|
+
# SPA base route
|
|
674
|
+
@app.get("/app", include_in_schema=False)
|
|
675
|
+
async def serve_app():
|
|
676
|
+
"""Serve SPA at /app."""
|
|
677
|
+
return FileResponse(frontend_dist / "index.html")
|
|
678
|
+
|
|
679
|
+
# SPA catch-all - serves static files if they exist, otherwise index.html for SPA routing
|
|
680
|
+
@app.get("/app/{path:path}", include_in_schema=False)
|
|
681
|
+
async def serve_spa(path: str):
|
|
682
|
+
"""Serve static files or SPA for /app/* routes."""
|
|
683
|
+
return _serve_spa_file(frontend_dist, path, frontend_dist / "index.html")
|
|
684
|
+
else:
|
|
685
|
+
@app.get("/", include_in_schema=False)
|
|
686
|
+
async def serve_root_fallback():
|
|
687
|
+
return {"message": "Manigent API", "frontend": "Not built. Run: cd manigent/web/frontend && npm run build"}
|
|
688
|
+
|
|
689
|
+
logger.warning(f"Frontend not found at {frontend_dist}. Run: cd manigent/web/frontend && npm run build")
|
|
690
|
+
|
|
691
|
+
background_tasks: list[asyncio.Task] = []
|
|
692
|
+
|
|
693
|
+
async def _sweep_idempotency_hourly() -> None:
|
|
694
|
+
while True:
|
|
695
|
+
try:
|
|
696
|
+
removed = await asyncio.to_thread(idempotency_store.sweep)
|
|
697
|
+
if removed:
|
|
698
|
+
logger.info(f"Swept {removed} expired idempotency hour dir(s)")
|
|
699
|
+
except Exception:
|
|
700
|
+
logger.warning("Idempotency sweep failed", exc_info=True)
|
|
701
|
+
await asyncio.sleep(3600)
|
|
702
|
+
|
|
703
|
+
# Startup event
|
|
704
|
+
@app.on_event("startup")
|
|
705
|
+
async def startup():
|
|
706
|
+
await User.initialize(model_ctx)
|
|
707
|
+
if isinstance(ws_hub, EdgeWSHub):
|
|
708
|
+
# Before the port binds: the snapshot settles every agent's status
|
|
709
|
+
# first, so the first request already sees the right one.
|
|
710
|
+
await ws_hub.start()
|
|
711
|
+
# One-shot idempotent reconcile of report_published_at against report.json
|
|
712
|
+
# for every project, so the denormalized field is correct from first
|
|
713
|
+
# deploy (projects with a pre-existing report predate the meta key). Only
|
|
714
|
+
# writes on a real delta, so re-running on every boot is cheap.
|
|
715
|
+
stamped = backfill_report_published_at(model_ctx)
|
|
716
|
+
if stamped:
|
|
717
|
+
logger.info(f"Backfilled report_published_at for {stamped} project(s)")
|
|
718
|
+
# One-time passes (server/requester_key_migration.py), each under its
|
|
719
|
+
# own guard so one failing never skips the others; each runs again at
|
|
720
|
+
# the next start. A failed scoped-turn pass fails closed: a project it
|
|
721
|
+
# had not keyed yet is still scoped by models/project.scope_key.
|
|
722
|
+
for migrate in (
|
|
723
|
+
# First: projects a scoped turn created keep their scope once
|
|
724
|
+
# remote_content stops isolating (plan-owner-isolation section 3).
|
|
725
|
+
migrate_scoped_turn_projects,
|
|
726
|
+
# Requester ends coordinated by a stand-in or another account's
|
|
727
|
+
# agent are reassigned to their owner (plan-owner-isolation 4).
|
|
728
|
+
migrate_owner_coordinators,
|
|
729
|
+
# Existing host conversations get their requester_key, so they
|
|
730
|
+
# are requester-scoped like new ones.
|
|
731
|
+
migrate_requester_keys,
|
|
732
|
+
migrate_hub_thread_marks,
|
|
733
|
+
# Same-server agents users already talk to are retained, so they
|
|
734
|
+
# stay in Cmd-K and the agents' rosters (server/hub/retain.py).
|
|
735
|
+
migrate_local_retains,
|
|
736
|
+
):
|
|
737
|
+
try:
|
|
738
|
+
await migrate(ctx, data_dir / "isolation")
|
|
739
|
+
except Exception:
|
|
740
|
+
logger.exception("%s failed; it will run again at next start", migrate.__name__)
|
|
741
|
+
# Managed jobs outlive the in-memory WorkTracker: rebuild their open
|
|
742
|
+
# requests before the checker's first pass, so a job whose process
|
|
743
|
+
# died while the server was down is reported as stalled.
|
|
744
|
+
try:
|
|
745
|
+
await restore_active_jobs(
|
|
746
|
+
managed_job_store, work_tracker, default_timeout=ctx.batch_timeout,
|
|
747
|
+
)
|
|
748
|
+
except Exception:
|
|
749
|
+
logger.exception("Managed job restore failed")
|
|
750
|
+
await timeout_checker.start()
|
|
751
|
+
background_tasks.append(asyncio.create_task(_sweep_idempotency_hourly()))
|
|
752
|
+
# Held outside messages past their ceiling go, with their closing notes.
|
|
753
|
+
background_tasks.append(asyncio.create_task(ctx.outside_ingress.run_expiry_sweep()))
|
|
754
|
+
# Work held for an agent that cannot isolate: closed at its ceiling,
|
|
755
|
+
# and the owner reminded at most daily.
|
|
756
|
+
background_tasks.append(asyncio.create_task(ctx.isolation_gate.notice.run_sweep()))
|
|
757
|
+
await message_scheduler.start()
|
|
758
|
+
await reflection_scheduler.start()
|
|
759
|
+
# Schema + FTS5 probe is synchronous and cheap; the reconcile that
|
|
760
|
+
# backfills existing history (and repairs any drift) runs as a
|
|
761
|
+
# background task so it never blocks boot. The endpoint answers while
|
|
762
|
+
# it runs, with `indexing: true`.
|
|
763
|
+
chat_search_index.open()
|
|
764
|
+
if chat_search_index.available:
|
|
765
|
+
asyncio.create_task(chat_search_index.reconcile_all())
|
|
766
|
+
if ctx.channel_gateway is not None:
|
|
767
|
+
try:
|
|
768
|
+
await ctx.channel_gateway.start()
|
|
769
|
+
except Exception as exc: # noqa: BLE001 — never stop the server booting
|
|
770
|
+
logger.error(
|
|
771
|
+
"Channel gateway OFF: unexpected %s during startup",
|
|
772
|
+
type(exc).__name__,
|
|
773
|
+
)
|
|
774
|
+
ctx.channel_gateway = None
|
|
775
|
+
ctx.hub_runtime = None
|
|
776
|
+
if ctx.hub_runtime is not None:
|
|
777
|
+
# After the gateway: reopen paused work, purge withdrawn hub
|
|
778
|
+
# keys, then (registered and mode not off) the first connect.
|
|
779
|
+
try:
|
|
780
|
+
await ctx.hub_runtime.start()
|
|
781
|
+
except Exception as exc: # noqa: BLE001 — never stop the server booting
|
|
782
|
+
logger.error("Hub runtime OFF: unexpected %s during startup", type(exc).__name__)
|
|
783
|
+
ctx.hub_runtime = None
|
|
784
|
+
logger.info(f"Server started with data_dir={data_dir}")
|
|
785
|
+
|
|
786
|
+
# Shutdown event
|
|
787
|
+
@app.on_event("shutdown")
|
|
788
|
+
async def shutdown():
|
|
789
|
+
for task in background_tasks:
|
|
790
|
+
task.cancel()
|
|
791
|
+
await reflection_scheduler.stop()
|
|
792
|
+
await message_scheduler.stop()
|
|
793
|
+
await timeout_checker.stop()
|
|
794
|
+
if ctx.hub_runtime is not None:
|
|
795
|
+
await ctx.hub_runtime.stop()
|
|
796
|
+
if ctx.channel_gateway is not None:
|
|
797
|
+
await ctx.channel_gateway.stop()
|
|
798
|
+
await ctx.socket_events.close()
|
|
799
|
+
if isinstance(ws_hub, EdgeWSHub):
|
|
800
|
+
await ws_hub.stop()
|
|
801
|
+
await runloop_manager.shutdown()
|
|
802
|
+
chat_search_index.close()
|
|
803
|
+
if ctx.channel_store is not None:
|
|
804
|
+
ctx.channel_store.close()
|
|
805
|
+
logger.info("Server shutdown complete")
|
|
806
|
+
|
|
807
|
+
return app
|