cremind 0.0.1__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.
- app/__init__.py +0 -0
- app/__main__.py +0 -0
- app/__version__.py +19 -0
- app/agent/__init__.py +4 -0
- app/agent/agent.py +352 -0
- app/agent/context_store.py +40 -0
- app/agent/executor.py +477 -0
- app/agent/reasoning_agent.py +1473 -0
- app/agent/skill_classifier.py +164 -0
- app/agent/stream_runner.py +565 -0
- app/agent/summary.py +45 -0
- app/alembic/__init__.py +0 -0
- app/alembic/env.py +83 -0
- app/alembic/script.py.mako +26 -0
- app/alembic/versions/20260509_baseline.py +106 -0
- app/alembic/versions/__init__.py +0 -0
- app/api/__init__.py +77 -0
- app/api/_auth.py +40 -0
- app/api/agents.py +720 -0
- app/api/channels.py +532 -0
- app/api/config.py +1658 -0
- app/api/conversations.py +520 -0
- app/api/embedding_stream.py +99 -0
- app/api/events.py +542 -0
- app/api/features.py +261 -0
- app/api/file_watchers.py +368 -0
- app/api/files.py +659 -0
- app/api/llm.py +422 -0
- app/api/logs_stream.py +70 -0
- app/api/oauth2.py +140 -0
- app/api/oauth_loopback.py +182 -0
- app/api/processes.py +491 -0
- app/api/profile_events.py +196 -0
- app/api/profiles.py +270 -0
- app/api/settings_stream.py +90 -0
- app/api/setup_stream.py +81 -0
- app/api/skills.py +253 -0
- app/api/system.py +77 -0
- app/api/system_vars.py +50 -0
- app/api/tokens.py +42 -0
- app/api/tools.py +768 -0
- app/api/upgrade.py +363 -0
- app/api/user_config.py +157 -0
- app/api/version.py +137 -0
- app/channels/__init__.py +17 -0
- app/channels/adapters/__init__.py +0 -0
- app/channels/adapters/discord.py +19 -0
- app/channels/adapters/messenger.py +19 -0
- app/channels/adapters/slack.py +19 -0
- app/channels/adapters/telegram.py +246 -0
- app/channels/adapters/telegram_userbot.py +363 -0
- app/channels/adapters/whatsapp.py +330 -0
- app/channels/base.py +857 -0
- app/channels/exceptions.py +17 -0
- app/channels/registry.py +193 -0
- app/channels/sidecars/__init__.py +0 -0
- app/channels/sidecars/bootstrap.py +136 -0
- app/channels/sidecars/whatsapp/.gitignore +1 -0
- app/channels/sidecars/whatsapp/index.js +269 -0
- app/channels/sidecars/whatsapp/package.json +17 -0
- app/cli/__init__.py +0 -0
- app/cli/client/__init__.py +11 -0
- app/cli/client/_base.py +179 -0
- app/cli/client/_sse.py +70 -0
- app/cli/client/_ws.py +58 -0
- app/cli/client/agents.py +75 -0
- app/cli/client/channels.py +131 -0
- app/cli/client/config.py +43 -0
- app/cli/client/conversations.py +137 -0
- app/cli/client/file_watchers.py +34 -0
- app/cli/client/llm.py +127 -0
- app/cli/client/me.py +50 -0
- app/cli/client/processes.py +97 -0
- app/cli/client/profiles.py +55 -0
- app/cli/client/setup.py +81 -0
- app/cli/client/skill_events.py +62 -0
- app/cli/client/system_vars.py +30 -0
- app/cli/client/tools.py +102 -0
- app/cli/commands/__init__.py +0 -0
- app/cli/commands/_helpers.py +41 -0
- app/cli/commands/agents.py +361 -0
- app/cli/commands/channels.py +401 -0
- app/cli/commands/chat.py +69 -0
- app/cli/commands/config.py +195 -0
- app/cli/commands/conv.py +405 -0
- app/cli/commands/db.py +167 -0
- app/cli/commands/file_watchers.py +208 -0
- app/cli/commands/llm.py +368 -0
- app/cli/commands/me.py +53 -0
- app/cli/commands/processes.py +562 -0
- app/cli/commands/profile.py +258 -0
- app/cli/commands/serve.py +38 -0
- app/cli/commands/setup.py +308 -0
- app/cli/commands/skill_events.py +271 -0
- app/cli/commands/system_vars.py +43 -0
- app/cli/commands/tools.py +352 -0
- app/cli/commands/upgrade.py +125 -0
- app/cli/config.py +74 -0
- app/cli/io/__init__.py +0 -0
- app/cli/io/raw_tty.py +122 -0
- app/cli/main.py +138 -0
- app/cli/output/__init__.py +21 -0
- app/cli/output/console.py +43 -0
- app/cli/output/formatting.py +29 -0
- app/cli/output/json_output.py +29 -0
- app/cli/output/tables.py +66 -0
- app/cli/streaming.py +167 -0
- app/cli/tui/__init__.py +0 -0
- app/cli/tui/chat.py +289 -0
- app/cli/tui/renderer.py +210 -0
- app/config/__init__.py +88 -0
- app/config/bootstrap.py +190 -0
- app/config/channels/discord.toml +40 -0
- app/config/channels/messenger.toml +41 -0
- app/config/channels/slack.toml +43 -0
- app/config/channels/telegram.toml +44 -0
- app/config/channels/whatsapp.toml +29 -0
- app/config/config_schema.py +261 -0
- app/config/credentials_file.py +285 -0
- app/config/embedding_state.py +238 -0
- app/config/install_catalog.py +274 -0
- app/config/install_catalog.toml +193 -0
- app/config/provider_auth.py +55 -0
- app/config/providers/anthropic.toml +80 -0
- app/config/providers/chutes.toml +50 -0
- app/config/providers/cloudflare-ai-gateway.toml +30 -0
- app/config/providers/deepseek.toml +29 -0
- app/config/providers/fireworks.toml +57 -0
- app/config/providers/github-copilot.toml +64 -0
- app/config/providers/google-gemini.toml +64 -0
- app/config/providers/groq.toml +66 -0
- app/config/providers/huggingface.toml +50 -0
- app/config/providers/litellm.toml +22 -0
- app/config/providers/minimax.toml +46 -0
- app/config/providers/mistral.toml +57 -0
- app/config/providers/moonshot.toml +46 -0
- app/config/providers/nvidia.toml +50 -0
- app/config/providers/ollama.toml +53 -0
- app/config/providers/openai.toml +117 -0
- app/config/providers/openrouter.toml +57 -0
- app/config/providers/perplexity.toml +43 -0
- app/config/providers/qwen.toml +67 -0
- app/config/providers/together.toml +64 -0
- app/config/providers/vertexai.toml +75 -0
- app/config/providers/vllm.toml +39 -0
- app/config/providers/xai.toml +44 -0
- app/config/settings.py +514 -0
- app/config/settings.toml +66 -0
- app/config/setup_profiles.py +185 -0
- app/config/setup_profiles.toml +201 -0
- app/config/system_vars.py +120 -0
- app/config/user_config.py +163 -0
- app/constants/__init__.py +17 -0
- app/constants/prompts.py +9 -0
- app/constants/status.py +10 -0
- app/databases/__init__.py +51 -0
- app/databases/base.py +130 -0
- app/databases/factory.py +59 -0
- app/databases/postgres.py +465 -0
- app/databases/sqlite.py +173 -0
- app/documents/__init__.py +34 -0
- app/documents/bundled/[cli]cremind agents.md +404 -0
- app/documents/bundled/[cli]cremind channels.md +521 -0
- app/documents/bundled/[cli]cremind chat.md +193 -0
- app/documents/bundled/[cli]cremind config.md +334 -0
- app/documents/bundled/[cli]cremind conv.md +545 -0
- app/documents/bundled/[cli]cremind file-watchers.md +423 -0
- app/documents/bundled/[cli]cremind llm.md +368 -0
- app/documents/bundled/[cli]cremind me.md +100 -0
- app/documents/bundled/[cli]cremind proc.md +454 -0
- app/documents/bundled/[cli]cremind profile.md +342 -0
- app/documents/bundled/[cli]cremind setup.md +343 -0
- app/documents/bundled/[cli]cremind skill-events.md +387 -0
- app/documents/bundled/[cli]cremind system-vars.md +103 -0
- app/documents/bundled/[cli]cremind tools.md +405 -0
- app/documents/bundled/document.md +130 -0
- app/documents/parser.py +101 -0
- app/documents/sync.py +486 -0
- app/documents/watcher.py +111 -0
- app/embeddings/__init__.py +31 -0
- app/embeddings/base.py +19 -0
- app/embeddings/gemma.py +36 -0
- app/embeddings/me5.py +29 -0
- app/events/__init__.py +35 -0
- app/events/conversations_list_bus.py +68 -0
- app/events/embedding_state_bus.py +73 -0
- app/events/file_watcher_admin_bus.py +54 -0
- app/events/file_watcher_manager.py +528 -0
- app/events/file_watcher_runner.py +147 -0
- app/events/log_stream_bus.py +89 -0
- app/events/manager.py +290 -0
- app/events/notifications_buffer.py +73 -0
- app/events/notifications_bus.py +69 -0
- app/events/processes_bus.py +53 -0
- app/events/profile_stream_fanout.py +70 -0
- app/events/queue.py +202 -0
- app/events/runner.py +134 -0
- app/events/settings_state_bus.py +74 -0
- app/events/setup_progress_bus.py +74 -0
- app/events/skill_events_admin_bus.py +54 -0
- app/events/stream_bus.py +166 -0
- app/features/__init__.py +28 -0
- app/features/installer.py +256 -0
- app/features/manifest.py +221 -0
- app/installer/__init__.py +0 -0
- app/installer/__main__.py +102 -0
- app/installer/catalog.py +117 -0
- app/installer/output.py +75 -0
- app/installer/releases.py +122 -0
- app/installer/tui.py +459 -0
- app/lib/__init__.py +0 -0
- app/lib/embedding.py +25 -0
- app/lib/embedding_lifecycle.py +430 -0
- app/lib/exception.py +15 -0
- app/lib/llm/__init__.py +29 -0
- app/lib/llm/__main__.py +125 -0
- app/lib/llm/anthropic.py +452 -0
- app/lib/llm/base.py +64 -0
- app/lib/llm/exceptions.py +47 -0
- app/lib/llm/factory.py +252 -0
- app/lib/llm/github_copilot.py +93 -0
- app/lib/llm/groq.py +251 -0
- app/lib/llm/model_groups.py +116 -0
- app/lib/llm/ollama.py +250 -0
- app/lib/llm/openai.py +253 -0
- app/lib/llm/vertexai.py +282 -0
- app/lib/llm/vllm.py +250 -0
- app/lib/template.py +185 -0
- app/middleware/__init__.py +31 -0
- app/runtime.py +70 -0
- app/server.py +1243 -0
- app/services/__init__.py +30 -0
- app/services/manifest.py +206 -0
- app/services/provisioner/__init__.py +35 -0
- app/services/provisioner/base.py +98 -0
- app/services/provisioner/docker.py +370 -0
- app/services/provisioner/external.py +48 -0
- app/services/provisioner/native.py +101 -0
- app/setup/__init__.py +0 -0
- app/skills/__init__.py +25 -0
- app/skills/builtin/caldav-calendar/SKILL.md +163 -0
- app/skills/builtin/caldav-calendar/events/new_event/.gitkeep +0 -0
- app/skills/builtin/caldav-calendar/events/updated_event/.gitkeep +0 -0
- app/skills/builtin/caldav-calendar/scripts/.gitignore +4 -0
- app/skills/builtin/caldav-calendar/scripts/README.md +93 -0
- app/skills/builtin/caldav-calendar/scripts/__main__.py +20 -0
- app/skills/builtin/caldav-calendar/scripts/app/__init__.py +0 -0
- app/skills/builtin/caldav-calendar/scripts/app/caldav_client.py +151 -0
- app/skills/builtin/caldav-calendar/scripts/app/cli.py +166 -0
- app/skills/builtin/caldav-calendar/scripts/app/config.py +58 -0
- app/skills/builtin/caldav-calendar/scripts/app/formatter.py +83 -0
- app/skills/builtin/caldav-calendar/scripts/app/ical.py +269 -0
- app/skills/builtin/caldav-calendar/scripts/app/listener.py +402 -0
- app/skills/builtin/caldav-calendar/scripts/app/operations.py +318 -0
- app/skills/builtin/caldav-calendar/scripts/event_listener.py +20 -0
- app/skills/builtin/confluence/SKILL.md +95 -0
- app/skills/builtin/confluence/scripts/.gitignore +5 -0
- app/skills/builtin/confluence/scripts/__main__.py +17 -0
- app/skills/builtin/confluence/scripts/app/__init__.py +0 -0
- app/skills/builtin/confluence/scripts/app/atlassian/__init__.py +0 -0
- app/skills/builtin/confluence/scripts/app/atlassian/account_key.py +40 -0
- app/skills/builtin/confluence/scripts/app/atlassian/auth.py +300 -0
- app/skills/builtin/confluence/scripts/app/atlassian/discovery.py +79 -0
- app/skills/builtin/confluence/scripts/app/cli.py +193 -0
- app/skills/builtin/confluence/scripts/app/config.py +32 -0
- app/skills/builtin/confluence/scripts/app/confluence_api.py +155 -0
- app/skills/builtin/confluence/scripts/app/formatter.py +55 -0
- app/skills/builtin/gcalendar/SKILL.md +152 -0
- app/skills/builtin/gcalendar/events/event_changed/.gitkeep +0 -0
- app/skills/builtin/gcalendar/scripts/.gitignore +8 -0
- app/skills/builtin/gcalendar/scripts/__main__.py +21 -0
- app/skills/builtin/gcalendar/scripts/app/__init__.py +0 -0
- app/skills/builtin/gcalendar/scripts/app/cli.py +225 -0
- app/skills/builtin/gcalendar/scripts/app/config.py +38 -0
- app/skills/builtin/gcalendar/scripts/app/formatter.py +148 -0
- app/skills/builtin/gcalendar/scripts/app/gcal_api.py +115 -0
- app/skills/builtin/gcalendar/scripts/app/google/__init__.py +0 -0
- app/skills/builtin/gcalendar/scripts/app/google/account_key.py +40 -0
- app/skills/builtin/gcalendar/scripts/app/google/auth.py +324 -0
- app/skills/builtin/gcalendar/scripts/app/google/discovery.py +137 -0
- app/skills/builtin/gcalendar/scripts/app/google/golden_account_keys.json +13 -0
- app/skills/builtin/gcalendar/scripts/app/google/relay_client.py +113 -0
- app/skills/builtin/gcalendar/scripts/app/listener.py +310 -0
- app/skills/builtin/gcalendar/scripts/event_listener.py +21 -0
- app/skills/builtin/gcalendar/scripts/tests/test_account_key.py +40 -0
- app/skills/builtin/gcalendar/scripts/tests/test_link_interrupt.py +86 -0
- app/skills/builtin/gmail/SKILL.md +146 -0
- app/skills/builtin/gmail/events/new_email/.gitkeep +0 -0
- app/skills/builtin/gmail/scripts/.gitignore +8 -0
- app/skills/builtin/gmail/scripts/__main__.py +21 -0
- app/skills/builtin/gmail/scripts/app/__init__.py +0 -0
- app/skills/builtin/gmail/scripts/app/cli.py +214 -0
- app/skills/builtin/gmail/scripts/app/config.py +43 -0
- app/skills/builtin/gmail/scripts/app/formatter.py +121 -0
- app/skills/builtin/gmail/scripts/app/gmail_api.py +146 -0
- app/skills/builtin/gmail/scripts/app/google/__init__.py +0 -0
- app/skills/builtin/gmail/scripts/app/google/account_key.py +40 -0
- app/skills/builtin/gmail/scripts/app/google/auth.py +324 -0
- app/skills/builtin/gmail/scripts/app/google/discovery.py +137 -0
- app/skills/builtin/gmail/scripts/app/google/golden_account_keys.json +13 -0
- app/skills/builtin/gmail/scripts/app/google/relay_client.py +113 -0
- app/skills/builtin/gmail/scripts/app/listener.py +336 -0
- app/skills/builtin/gmail/scripts/event_listener.py +21 -0
- app/skills/builtin/gmail/scripts/tests/test_account_key.py +40 -0
- app/skills/builtin/gmail/scripts/tests/test_link_interrupt.py +86 -0
- app/skills/builtin/imap-email/SKILL.md +43 -0
- app/skills/builtin/imap-email/events/test.md +46 -0
- app/skills/builtin/imap-email/scripts/.gitignore +4 -0
- app/skills/builtin/imap-email/scripts/README.md +173 -0
- app/skills/builtin/imap-email/scripts/__main__.py +15 -0
- app/skills/builtin/imap-email/scripts/app/__init__.py +0 -0
- app/skills/builtin/imap-email/scripts/app/__main__.py +0 -0
- app/skills/builtin/imap-email/scripts/app/cli.py +196 -0
- app/skills/builtin/imap-email/scripts/app/config.py +54 -0
- app/skills/builtin/imap-email/scripts/app/formatter.py +93 -0
- app/skills/builtin/imap-email/scripts/app/imap_client.py +317 -0
- app/skills/builtin/imap-email/scripts/app/listener.py +211 -0
- app/skills/builtin/imap-email/scripts/app/message.py +187 -0
- app/skills/builtin/imap-email/scripts/app/operations.py +180 -0
- app/skills/builtin/imap-email/scripts/app/search.py +63 -0
- app/skills/builtin/imap-email/scripts/app/smtp_client.py +53 -0
- app/skills/builtin/imap-email/scripts/event_listener.py +15 -0
- app/skills/builtin/jira/SKILL.md +161 -0
- app/skills/builtin/jira/events/issue_changed/.gitkeep +0 -0
- app/skills/builtin/jira/scripts/.gitignore +9 -0
- app/skills/builtin/jira/scripts/__main__.py +17 -0
- app/skills/builtin/jira/scripts/app/__init__.py +0 -0
- app/skills/builtin/jira/scripts/app/atlassian/__init__.py +0 -0
- app/skills/builtin/jira/scripts/app/atlassian/account_key.py +40 -0
- app/skills/builtin/jira/scripts/app/atlassian/auth.py +300 -0
- app/skills/builtin/jira/scripts/app/atlassian/discovery.py +86 -0
- app/skills/builtin/jira/scripts/app/atlassian/relay_client.py +111 -0
- app/skills/builtin/jira/scripts/app/cli.py +240 -0
- app/skills/builtin/jira/scripts/app/config.py +58 -0
- app/skills/builtin/jira/scripts/app/formatter.py +112 -0
- app/skills/builtin/jira/scripts/app/jira_api.py +171 -0
- app/skills/builtin/jira/scripts/app/listener.py +345 -0
- app/skills/builtin/jira/scripts/event_listener.py +18 -0
- app/skills/env_file.py +58 -0
- app/skills/importer.py +252 -0
- app/skills/scanner.py +248 -0
- app/skills/sync.py +401 -0
- app/skills/tool.py +116 -0
- app/skills/watcher.py +105 -0
- app/static/ui/.built-at +1 -0
- app/static/ui/agent-avatar.png +0 -0
- app/static/ui/assets/AboutPage-Bay673ON.css +1 -0
- app/static/ui/assets/AboutPage-DGshkxnc.js +1 -0
- app/static/ui/assets/AgentsToolsSettings-Buh23J8B.css +1 -0
- app/static/ui/assets/AgentsToolsSettings-p5xpfP2c.js +5 -0
- app/static/ui/assets/ChannelPairingDialog-VjAnCvl0.css +1 -0
- app/static/ui/assets/ChannelPairingDialog-rxLnDlCb.js +1 -0
- app/static/ui/assets/ChannelsPage-BLnI--Mx.js +1 -0
- app/static/ui/assets/ChannelsPage-DzSDiaQI.css +1 -0
- app/static/ui/assets/ChannelsSettings-BrOCcfNG.css +1 -0
- app/static/ui/assets/ChannelsSettings-CsLEd6iP.js +1 -0
- app/static/ui/assets/DeploymentModeRadio-1FyYt8_E.js +1 -0
- app/static/ui/assets/DeploymentModeRadio-DGkSGHUG.css +1 -0
- app/static/ui/assets/DeveloperPage-DN9Mmz96.css +1 -0
- app/static/ui/assets/DeveloperPage-DajPl07Q.js +8 -0
- app/static/ui/assets/EmbeddingSettings-DosgfNo_.js +1 -0
- app/static/ui/assets/EmbeddingSettings-DsniVY84.css +1 -0
- app/static/ui/assets/LLMParametersForm-ZUnInzzp.css +1 -0
- app/static/ui/assets/LLMParametersForm.vue_vue_type_script_setup_true_lang-CsE2YrxL.js +6 -0
- app/static/ui/assets/LLMSettings-CaRMl8ne.js +1 -0
- app/static/ui/assets/LLMSettings-CxEW2H8a.css +1 -0
- app/static/ui/assets/LoginPage-DUOxp0NS.js +1 -0
- app/static/ui/assets/LoginPage-Dqz8ApJ_.css +1 -0
- app/static/ui/assets/ProcessList-BFfXkaXr.css +1 -0
- app/static/ui/assets/ProcessList-ClpH7PHX.js +14 -0
- app/static/ui/assets/ProcessTerminal-C7MLjalD.css +1 -0
- app/static/ui/assets/ProcessTerminal-S6EOvMIc.js +1 -0
- app/static/ui/assets/ProfileSelector-DRoyskoP.css +1 -0
- app/static/ui/assets/ProfileSelector-DTeMeRNk.js +1 -0
- app/static/ui/assets/ProfileSettings-Bm6z-Otq.js +1 -0
- app/static/ui/assets/ProfileSettings-Dph35mkV.css +1 -0
- app/static/ui/assets/ProviderConfigFields-CDHncpjj.css +1 -0
- app/static/ui/assets/ProviderConfigFields-zeugKg6x.js +1 -0
- app/static/ui/assets/SettingsPage-Cjg5Aw-5.css +1 -0
- app/static/ui/assets/SettingsPage-CuSRVBhY.js +1 -0
- app/static/ui/assets/SetupWizard-Cac9EXqk.css +1 -0
- app/static/ui/assets/SetupWizard-DRD5rUg_.js +12 -0
- app/static/ui/assets/SkillEventsPage-BISy34dp.css +1 -0
- app/static/ui/assets/SkillEventsPage-D3vXsDg2.js +11 -0
- app/static/ui/assets/UpdatesSettings-BCyobg-4.js +1 -0
- app/static/ui/assets/UpdatesSettings-BHLgMLzd.css +1 -0
- app/static/ui/assets/UserConfigSettings-CwqAU5ku.css +1 -0
- app/static/ui/assets/UserConfigSettings-De77aD0M.js +1 -0
- app/static/ui/assets/github-BfC0goYb.css +10 -0
- app/static/ui/assets/github-dark-BEHUn5zE.css +10 -0
- app/static/ui/assets/index-BBXNjI-t.css +32 -0
- app/static/ui/assets/index-Dz2VcS8u.js +199 -0
- app/static/ui/assets/useLLMModels-Ddq715w-.js +1 -0
- app/static/ui/assets/useServerRestart-DRMby3la.js +1 -0
- app/static/ui/index.html +17 -0
- app/static/ui/logo.ico +0 -0
- app/static/ui/logo.png +0 -0
- app/static/ui/tray-logo-64x64.png +0 -0
- app/static/ui-electron/.built-at +1 -0
- app/static/ui-electron/agent-avatar.png +0 -0
- app/static/ui-electron/assets/AboutPage-BYGxzwoO.js +1 -0
- app/static/ui-electron/assets/AboutPage-Bay673ON.css +1 -0
- app/static/ui-electron/assets/AgentsToolsSettings-Buh23J8B.css +1 -0
- app/static/ui-electron/assets/AgentsToolsSettings-khxOsBT1.js +5 -0
- app/static/ui-electron/assets/ChannelPairingDialog-CoVN4B3J.js +1 -0
- app/static/ui-electron/assets/ChannelPairingDialog-VjAnCvl0.css +1 -0
- app/static/ui-electron/assets/ChannelsPage-DAPF3fth.js +1 -0
- app/static/ui-electron/assets/ChannelsPage-DzSDiaQI.css +1 -0
- app/static/ui-electron/assets/ChannelsSettings-BlCM1-iv.js +1 -0
- app/static/ui-electron/assets/ChannelsSettings-BrOCcfNG.css +1 -0
- app/static/ui-electron/assets/DeploymentModeRadio-C4kqRD5H.js +1 -0
- app/static/ui-electron/assets/DeploymentModeRadio-DGkSGHUG.css +1 -0
- app/static/ui-electron/assets/DeveloperPage-CkaY7nr5.js +8 -0
- app/static/ui-electron/assets/DeveloperPage-DN9Mmz96.css +1 -0
- app/static/ui-electron/assets/EmbeddingSettings-BvjQwMTO.js +1 -0
- app/static/ui-electron/assets/EmbeddingSettings-DsniVY84.css +1 -0
- app/static/ui-electron/assets/LLMParametersForm-ZUnInzzp.css +1 -0
- app/static/ui-electron/assets/LLMParametersForm.vue_vue_type_script_setup_true_lang-C5rC0IrP.js +6 -0
- app/static/ui-electron/assets/LLMSettings-BoGhbAi7.js +1 -0
- app/static/ui-electron/assets/LLMSettings-CxEW2H8a.css +1 -0
- app/static/ui-electron/assets/LoginPage-DM4dC1XU.js +1 -0
- app/static/ui-electron/assets/LoginPage-Dqz8ApJ_.css +1 -0
- app/static/ui-electron/assets/ProcessList-BFfXkaXr.css +1 -0
- app/static/ui-electron/assets/ProcessList-Bnu8-YEp.js +14 -0
- app/static/ui-electron/assets/ProcessTerminal-C7MLjalD.css +1 -0
- app/static/ui-electron/assets/ProcessTerminal-DSc5DMgs.js +1 -0
- app/static/ui-electron/assets/ProfileSelector-BciT1BgV.js +1 -0
- app/static/ui-electron/assets/ProfileSelector-DRoyskoP.css +1 -0
- app/static/ui-electron/assets/ProfileSettings-CbPGdXWB.js +1 -0
- app/static/ui-electron/assets/ProfileSettings-Dph35mkV.css +1 -0
- app/static/ui-electron/assets/ProviderConfigFields-CDHncpjj.css +1 -0
- app/static/ui-electron/assets/ProviderConfigFields-COOeDNdG.js +1 -0
- app/static/ui-electron/assets/SettingsPage-Cjg5Aw-5.css +1 -0
- app/static/ui-electron/assets/SettingsPage-OiC78qq_.js +1 -0
- app/static/ui-electron/assets/SetupWizard-Cac9EXqk.css +1 -0
- app/static/ui-electron/assets/SetupWizard-hoYGAgWs.js +12 -0
- app/static/ui-electron/assets/SkillEventsPage-BISy34dp.css +1 -0
- app/static/ui-electron/assets/SkillEventsPage-BXkDOfhc.js +11 -0
- app/static/ui-electron/assets/UpdatesSettings-BHLgMLzd.css +1 -0
- app/static/ui-electron/assets/UpdatesSettings-CTZQO3Ek.js +1 -0
- app/static/ui-electron/assets/UserConfigSettings-CwqAU5ku.css +1 -0
- app/static/ui-electron/assets/UserConfigSettings-DQqBJp3I.js +1 -0
- app/static/ui-electron/assets/github-BfC0goYb.css +10 -0
- app/static/ui-electron/assets/github-dark-BEHUn5zE.css +10 -0
- app/static/ui-electron/assets/index-B0y39_LV.js +199 -0
- app/static/ui-electron/assets/index-BBXNjI-t.css +32 -0
- app/static/ui-electron/assets/useLLMModels-PmLutXyj.js +1 -0
- app/static/ui-electron/assets/useServerRestart-f9hu5znm.js +1 -0
- app/static/ui-electron/index.html +17 -0
- app/static/ui-electron/logo.ico +0 -0
- app/static/ui-electron/logo.png +0 -0
- app/static/ui-electron/tray-logo-64x64.png +0 -0
- app/storage/__init__.py +100 -0
- app/storage/_sync_base.py +77 -0
- app/storage/autostart_storage.py +142 -0
- app/storage/backup.py +93 -0
- app/storage/conversation_storage.py +760 -0
- app/storage/dynamic_config_storage.py +162 -0
- app/storage/event_subscription_storage.py +160 -0
- app/storage/file_watcher_storage.py +175 -0
- app/storage/migrations.py +218 -0
- app/storage/models.py +348 -0
- app/storage/tool_storage.py +437 -0
- app/system/__init__.py +0 -0
- app/system/restart.py +77 -0
- app/templates/PERSONA.md +1 -0
- app/templates/assistant.jinja +52 -0
- app/tools/__init__.py +54 -0
- app/tools/a2a/__init__.py +17 -0
- app/tools/a2a/auth.py +392 -0
- app/tools/a2a/connection.py +194 -0
- app/tools/a2a/tool.py +290 -0
- app/tools/base.py +198 -0
- app/tools/builtin/__init__.py +549 -0
- app/tools/builtin/adapter.py +658 -0
- app/tools/builtin/base.py +235 -0
- app/tools/builtin/browser.py +1240 -0
- app/tools/builtin/change_working_directory.py +344 -0
- app/tools/builtin/documentation_search.py +424 -0
- app/tools/builtin/exec_shell.py +2105 -0
- app/tools/builtin/exec_shell_autostart.py +376 -0
- app/tools/builtin/exec_shell_classifier.py +86 -0
- app/tools/builtin/exec_shell_input_mode.py +261 -0
- app/tools/builtin/exec_shell_process_inspect.py +227 -0
- app/tools/builtin/exec_shell_pty.py +485 -0
- app/tools/builtin/exec_shell_rtk.py +111 -0
- app/tools/builtin/gg_calendar.py +235 -0
- app/tools/builtin/gg_places.py +748 -0
- app/tools/builtin/markdown_converter.py +318 -0
- app/tools/builtin/message_detail.py +126 -0
- app/tools/builtin/register_file_watcher.py +617 -0
- app/tools/builtin/register_skill_event.py +393 -0
- app/tools/builtin/sleep.py +93 -0
- app/tools/builtin/system_file.py +1022 -0
- app/tools/builtin/tool.py +232 -0
- app/tools/builtin/weather.py +210 -0
- app/tools/config_manager.py +128 -0
- app/tools/ids.py +77 -0
- app/tools/intrinsic/__init__.py +27 -0
- app/tools/intrinsic/base.py +64 -0
- app/tools/intrinsic/casual_chat.py +24 -0
- app/tools/intrinsic/final_answer.py +29 -0
- app/tools/mcp/__init__.py +32 -0
- app/tools/mcp/mcp_agent_adapter.py +598 -0
- app/tools/mcp/mcp_auth.py +519 -0
- app/tools/mcp/mcp_connection.py +205 -0
- app/tools/mcp/mcp_remote_shim.py +85 -0
- app/tools/mcp/tool.py +395 -0
- app/tools/registry.py +624 -0
- app/types/__init__.py +32 -0
- app/types/__main__.py +244 -0
- app/upgrade/__init__.py +0 -0
- app/upgrade/channel.py +373 -0
- app/upgrade/detached.py +230 -0
- app/upgrade/manifest.py +450 -0
- app/upgrade/runner.py +765 -0
- app/upgrade/status.py +205 -0
- app/upgrade/version_filter.py +33 -0
- app/utils/__init__.py +13 -0
- app/utils/accuweather.py +314 -0
- app/utils/client_storage.py +211 -0
- app/utils/common.py +392 -0
- app/utils/context_storage.py +71 -0
- app/utils/event_parser.py +72 -0
- app/utils/formatting.py +52 -0
- app/utils/logger.py +140 -0
- app/utils/message_tokens.py +68 -0
- app/utils/persona.py +62 -0
- app/utils/skill_source.py +38 -0
- app/utils/task_context.py +13 -0
- app/utils/template.py +185 -0
- app/utils/working_directory.py +150 -0
- app/vectorstores/__init__.py +3 -0
- app/vectorstores/base.py +315 -0
- app/vectorstores/cache.py +200 -0
- app/vectorstores/chroma.py +447 -0
- app/vectorstores/factory.py +33 -0
- app/vectorstores/qdrant.py +365 -0
- cremind-0.0.1.dist-info/METADATA +207 -0
- cremind-0.0.1.dist-info/RECORD +543 -0
- cremind-0.0.1.dist-info/WHEEL +4 -0
- cremind-0.0.1.dist-info/entry_points.txt +2 -0
- cremind-0.0.1.dist-info/licenses/LICENSE +21 -0
app/__init__.py
ADDED
|
File without changes
|
app/__main__.py
ADDED
|
File without changes
|
app/__version__.py
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"""Single source of truth for the Cremind version.
|
|
2
|
+
|
|
3
|
+
Read by ``pyproject.toml`` (via ``tool.hatch.version``) and by the runtime
|
|
4
|
+
``/version`` endpoint, the ``cremind version`` CLI, and the upgrader. Bump this
|
|
5
|
+
on release and the package metadata, the API response, and the CLI output
|
|
6
|
+
all move together.
|
|
7
|
+
|
|
8
|
+
Schema migrations are tracked separately by Alembic — see ``alembic/`` at the
|
|
9
|
+
repo root. ``MIN_SUPPORTED_UPGRADE_FROM`` is the oldest version this build
|
|
10
|
+
knows how to migrate from; the upgrader refuses to proceed when the live
|
|
11
|
+
install is older than this.
|
|
12
|
+
|
|
13
|
+
NOTE on ``"0.0.0"``: the upgrade floor accepts any install. Bump it the
|
|
14
|
+
next time Alembic introduces a migration that genuinely requires a minimum
|
|
15
|
+
schema version, not before.
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
__version__ = "0.0.1"
|
|
19
|
+
MIN_SUPPORTED_UPGRADE_FROM = "0.0.0"
|
app/agent/__init__.py
ADDED
app/agent/agent.py
ADDED
|
@@ -0,0 +1,352 @@
|
|
|
1
|
+
"""Top-level Cremind agent.
|
|
2
|
+
|
|
3
|
+
Wraps the registry-driven :class:`ReasoningAgent` for each profile and
|
|
4
|
+
manages the per-profile "high" group LLM. Tool-card embeddings are kept
|
|
5
|
+
per-profile -- each profile gets its own Qdrant collection
|
|
6
|
+
``tool_embeddings_<profile>`` and its own in-memory embedding table -- so
|
|
7
|
+
skill and tool visibility never leaks across profiles.
|
|
8
|
+
|
|
9
|
+
When a Qdrant vector store is available, tool embeddings are persisted so they
|
|
10
|
+
survive server restarts without re-calling the gRPC embedding service.
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
from __future__ import annotations
|
|
14
|
+
|
|
15
|
+
from typing import Any, AsyncGenerator, Iterable, List, Optional, TYPE_CHECKING
|
|
16
|
+
|
|
17
|
+
from app.agent.reasoning_agent import ReasoningAgent
|
|
18
|
+
from app.lib.embedding import LocalEmbeddings
|
|
19
|
+
from app.lib.llm import LLMProvider
|
|
20
|
+
from app.lib.llm.model_groups import ModelGroupManager
|
|
21
|
+
from app.storage import get_dynamic_config_storage
|
|
22
|
+
from app.storage.dynamic_config_storage import DynamicConfigStorage
|
|
23
|
+
from app.tools import ToolRegistry
|
|
24
|
+
from app.tools.base import ToolType
|
|
25
|
+
from app.types import EmbeddingTable, ReasoningStreamResponseType, ToolEmbeddingRecord
|
|
26
|
+
from app.utils import logger
|
|
27
|
+
|
|
28
|
+
if TYPE_CHECKING:
|
|
29
|
+
from app.vectorstores import VectorStore
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def _tool_embeddings_collection(profile: str) -> str:
|
|
33
|
+
return f"tool_embeddings_{profile}"
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def _card_to_embedding_text(card) -> str:
|
|
37
|
+
description = (card.description or "").strip()
|
|
38
|
+
skills = getattr(card, "skills", None) or []
|
|
39
|
+
skill_lines = []
|
|
40
|
+
for skill in skills:
|
|
41
|
+
sk_name = getattr(skill, "name", None) or getattr(skill, "id", None) or ""
|
|
42
|
+
sk_desc = (getattr(skill, "description", None) or "").strip()
|
|
43
|
+
if not sk_name and not sk_desc:
|
|
44
|
+
continue
|
|
45
|
+
skill_lines.append(f"{sk_name}: {sk_desc}" if sk_name else sk_desc)
|
|
46
|
+
if description and skill_lines:
|
|
47
|
+
return description + "\n\n" + "\n".join(skill_lines)
|
|
48
|
+
return description or "\n".join(skill_lines)
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
class CremindAgent:
|
|
52
|
+
"""Per-profile reasoning entry point."""
|
|
53
|
+
|
|
54
|
+
def __init__(
|
|
55
|
+
self,
|
|
56
|
+
registry: ToolRegistry,
|
|
57
|
+
embedding: LocalEmbeddings | None,
|
|
58
|
+
runner: LLMProvider | None = None,
|
|
59
|
+
model_group_mgr: ModelGroupManager | None = None,
|
|
60
|
+
config_storage: DynamicConfigStorage | None = None,
|
|
61
|
+
vector_store: VectorStore | None = None,
|
|
62
|
+
conversation_storage: Any | None = None,
|
|
63
|
+
):
|
|
64
|
+
self._runners: dict[str, LLMProvider] = {}
|
|
65
|
+
if runner is not None:
|
|
66
|
+
self._runners["admin"] = runner
|
|
67
|
+
self.registry = registry
|
|
68
|
+
self.embedding = embedding
|
|
69
|
+
self._model_group_mgr = model_group_mgr
|
|
70
|
+
self._config_storage = config_storage
|
|
71
|
+
self.vector_store = vector_store
|
|
72
|
+
self._conversation_storage = conversation_storage
|
|
73
|
+
self._embedding_tables: dict[str, EmbeddingTable] = {}
|
|
74
|
+
|
|
75
|
+
# Refresh embeddings whenever the registry mutates. The callback
|
|
76
|
+
# accepts an optional ``profile`` kwarg so skill-scoped changes only
|
|
77
|
+
# rebuild one table; global changes (builtin/a2a/mcp) rebuild all.
|
|
78
|
+
self.registry.set_change_callback(self.update_embeddings)
|
|
79
|
+
|
|
80
|
+
# ── embedding tables ────────────────────────────────────────────────
|
|
81
|
+
|
|
82
|
+
def _collect_tool_data(self, profile: str) -> dict[str, ToolEmbeddingRecord]:
|
|
83
|
+
"""Extract tool card data for ``profile`` (skip stubs / hidden).
|
|
84
|
+
|
|
85
|
+
Records are keyed by ``tool_id`` (stable registry identity) and carry
|
|
86
|
+
filter metadata (``tool_type``, ``name``, ``enabled``) so the vector
|
|
87
|
+
store payload can be queried by type without joining back to the
|
|
88
|
+
registry. Embedding text is the card description plus one line per
|
|
89
|
+
sub-skill — storing the full ``AgentCard`` JSON would bloat the input
|
|
90
|
+
with protocol/transport fields that carry no retrieval signal.
|
|
91
|
+
"""
|
|
92
|
+
agent_data: dict[str, ToolEmbeddingRecord] = {}
|
|
93
|
+
for tool in self.registry.tools_for_profile(profile):
|
|
94
|
+
if tool.hidden:
|
|
95
|
+
continue
|
|
96
|
+
if getattr(tool, "is_stub", False):
|
|
97
|
+
continue
|
|
98
|
+
card = tool.get_card()
|
|
99
|
+
if card is None:
|
|
100
|
+
continue
|
|
101
|
+
agent_data[tool.tool_id] = ToolEmbeddingRecord(
|
|
102
|
+
text=_card_to_embedding_text(card),
|
|
103
|
+
tool_id=tool.tool_id,
|
|
104
|
+
name=card.name,
|
|
105
|
+
tool_type=tool.tool_type.value,
|
|
106
|
+
enabled=self.registry.is_enabled_for_profile(tool, profile),
|
|
107
|
+
)
|
|
108
|
+
return agent_data
|
|
109
|
+
|
|
110
|
+
def _build_connected_embeddings(self, profile: str) -> Optional[EmbeddingTable]:
|
|
111
|
+
"""Build the embedding table for ``profile``.
|
|
112
|
+
|
|
113
|
+
Uses the shared cache helper to load from Qdrant when available,
|
|
114
|
+
falling back to in-process embedding generation and persisting for
|
|
115
|
+
next time. Returns ``None`` when embedding is disabled — callers
|
|
116
|
+
treat that as "no similarity ranking available" and fall back to
|
|
117
|
+
showing every tool.
|
|
118
|
+
"""
|
|
119
|
+
if self.embedding is None or self.vector_store is None:
|
|
120
|
+
return None
|
|
121
|
+
|
|
122
|
+
from app.vectorstores import get_or_build_embedding_table
|
|
123
|
+
|
|
124
|
+
agent_data = self._collect_tool_data(profile)
|
|
125
|
+
table = get_or_build_embedding_table(
|
|
126
|
+
vector_store=self.vector_store,
|
|
127
|
+
embedding=self.embedding,
|
|
128
|
+
data=agent_data,
|
|
129
|
+
collection_name=_tool_embeddings_collection(profile),
|
|
130
|
+
)
|
|
131
|
+
logger.debug(f"Tool card embeddings for '{profile}': {table.dataframe}")
|
|
132
|
+
return table
|
|
133
|
+
|
|
134
|
+
def embedding_table_for(self, profile: str) -> Optional[EmbeddingTable]:
|
|
135
|
+
"""Return the profile's embedding table, building it lazily.
|
|
136
|
+
|
|
137
|
+
Returns ``None`` when embedding is disabled.
|
|
138
|
+
"""
|
|
139
|
+
if self.embedding is None or self.vector_store is None:
|
|
140
|
+
return None
|
|
141
|
+
table = self._embedding_tables.get(profile)
|
|
142
|
+
if table is None:
|
|
143
|
+
built = self._build_connected_embeddings(profile)
|
|
144
|
+
if built is None:
|
|
145
|
+
return None
|
|
146
|
+
self._embedding_tables[profile] = built
|
|
147
|
+
table = built
|
|
148
|
+
return table
|
|
149
|
+
|
|
150
|
+
def update_embeddings(self, profile: str | None = None) -> None:
|
|
151
|
+
"""Rebuild the embedding table(s) after tools are added/removed.
|
|
152
|
+
|
|
153
|
+
- ``profile`` given → rebuild only that profile's table (skill sync).
|
|
154
|
+
- ``profile is None`` → rebuild every profile we have already touched
|
|
155
|
+
(builtin / a2a / mcp mutation that could affect anyone).
|
|
156
|
+
|
|
157
|
+
No-op when embedding is disabled — pandas is in the embeddings
|
|
158
|
+
extras group and importing the cache helpers would crash on a
|
|
159
|
+
thin install.
|
|
160
|
+
"""
|
|
161
|
+
if self.embedding is None or self.vector_store is None:
|
|
162
|
+
return
|
|
163
|
+
|
|
164
|
+
targets: Iterable[str]
|
|
165
|
+
if profile is not None:
|
|
166
|
+
targets = [profile]
|
|
167
|
+
else:
|
|
168
|
+
targets = list(self._embedding_tables.keys())
|
|
169
|
+
|
|
170
|
+
for p in targets:
|
|
171
|
+
built = self._build_connected_embeddings(p)
|
|
172
|
+
if built is None:
|
|
173
|
+
continue
|
|
174
|
+
self._embedding_tables[p] = built
|
|
175
|
+
logger.info(
|
|
176
|
+
f"Updated tool embeddings for '{p}' "
|
|
177
|
+
f"({len(self._embedding_tables[p])} entries)"
|
|
178
|
+
)
|
|
179
|
+
|
|
180
|
+
def drop_profile_embeddings(self, profile: str) -> None:
|
|
181
|
+
"""Remove a profile's embedding table and its Qdrant collection."""
|
|
182
|
+
self._embedding_tables.pop(profile, None)
|
|
183
|
+
if self.vector_store is None:
|
|
184
|
+
return
|
|
185
|
+
try:
|
|
186
|
+
from app.vectorstores.qdrant import QdrantClient as QdrantVectorClient
|
|
187
|
+
|
|
188
|
+
client: QdrantVectorClient = self.vector_store._client # type: ignore[assignment]
|
|
189
|
+
collection = _tool_embeddings_collection(profile)
|
|
190
|
+
if client.collection_exists(collection):
|
|
191
|
+
client.delete_collection(collection)
|
|
192
|
+
logger.info(f"Dropped embedding collection '{collection}'")
|
|
193
|
+
except Exception: # noqa: BLE001
|
|
194
|
+
logger.exception(
|
|
195
|
+
f"Failed to drop embedding collection for profile '{profile}'"
|
|
196
|
+
)
|
|
197
|
+
|
|
198
|
+
# ── runners ─────────────────────────────────────────────────────────
|
|
199
|
+
|
|
200
|
+
def _ensure_runner(self, profile: str) -> LLMProvider:
|
|
201
|
+
"""Create (or re-create) the LLM provider for ``profile`` from current config."""
|
|
202
|
+
if self._model_group_mgr is None:
|
|
203
|
+
self._model_group_mgr = ModelGroupManager(get_dynamic_config_storage())
|
|
204
|
+
|
|
205
|
+
if not self._model_group_mgr.config_storage.is_setup_complete():
|
|
206
|
+
raise ValueError("LLM provider is not configured. Run the setup wizard first.")
|
|
207
|
+
|
|
208
|
+
runner = self._model_group_mgr.create_llm_for_group("high", profile=profile)
|
|
209
|
+
self._runners[profile] = runner
|
|
210
|
+
return runner
|
|
211
|
+
|
|
212
|
+
def low_group_llm(self, profile: str) -> LLMProvider:
|
|
213
|
+
"""Return the profile's 'low' group LLM provider for cheap auxiliary calls."""
|
|
214
|
+
if self._model_group_mgr is None:
|
|
215
|
+
self._model_group_mgr = ModelGroupManager(get_dynamic_config_storage())
|
|
216
|
+
return self._model_group_mgr.create_llm_for_group("low", profile=profile)
|
|
217
|
+
|
|
218
|
+
async def _resolve_allowed_skill_ids(
|
|
219
|
+
self, query: str, profile: str,
|
|
220
|
+
) -> set[str] | None:
|
|
221
|
+
"""Return the skill tool_ids permitted for this run.
|
|
222
|
+
|
|
223
|
+
- ``None`` → no filtering (manual mode, or automatic mode with any
|
|
224
|
+
failure that warrants falling back to the full skill list so the
|
|
225
|
+
user isn't silently left with zero skills).
|
|
226
|
+
- non-empty set → restrict skills to this set (automatic mode, vector
|
|
227
|
+
search succeeded).
|
|
228
|
+
"""
|
|
229
|
+
storage = self._conversation_storage
|
|
230
|
+
if storage is None:
|
|
231
|
+
return None
|
|
232
|
+
try:
|
|
233
|
+
mode = await storage.get_skill_mode(profile)
|
|
234
|
+
except Exception: # noqa: BLE001
|
|
235
|
+
logger.exception(f"Failed to read skill_mode for profile '{profile}'")
|
|
236
|
+
return None
|
|
237
|
+
if mode != "automatic":
|
|
238
|
+
return None
|
|
239
|
+
if self.vector_store is None:
|
|
240
|
+
logger.warning(
|
|
241
|
+
f"Skill mode 'automatic' for profile '{profile}' but no vector "
|
|
242
|
+
f"store available; falling back to manual behavior."
|
|
243
|
+
)
|
|
244
|
+
return None
|
|
245
|
+
# Authoritative set of skills the user has enabled for this profile.
|
|
246
|
+
# The Qdrant payload also carries an ``enabled`` flag, but it's a
|
|
247
|
+
# cache; we intersect with the registry to guarantee we never return
|
|
248
|
+
# a skill the user has just disabled.
|
|
249
|
+
enabled_skill_ids = {
|
|
250
|
+
t.tool_id for t in self.registry.tools_for_profile(profile)
|
|
251
|
+
if t.tool_type is ToolType.SKILL
|
|
252
|
+
and self.registry.is_enabled_for_profile(t, profile)
|
|
253
|
+
}
|
|
254
|
+
if not enabled_skill_ids:
|
|
255
|
+
logger.debug(
|
|
256
|
+
f"Automatic skill mode for profile '{profile}': no enabled "
|
|
257
|
+
f"skills; nothing to search."
|
|
258
|
+
)
|
|
259
|
+
return set()
|
|
260
|
+
try:
|
|
261
|
+
results = self.vector_store.query(
|
|
262
|
+
query_text=query,
|
|
263
|
+
collection_name=_tool_embeddings_collection(profile),
|
|
264
|
+
embedding_function=self.embedding,
|
|
265
|
+
limit=10,
|
|
266
|
+
filter={"tool_type": ToolType.SKILL, "enabled": True},
|
|
267
|
+
)
|
|
268
|
+
except Exception: # noqa: BLE001
|
|
269
|
+
logger.exception(
|
|
270
|
+
f"Vector skill search failed for profile '{profile}'; "
|
|
271
|
+
f"falling back to manual behavior."
|
|
272
|
+
)
|
|
273
|
+
return None
|
|
274
|
+
allowed: set[str] = set()
|
|
275
|
+
for r in results or []:
|
|
276
|
+
metadata = r.get("metadata") or {}
|
|
277
|
+
tool_id = metadata.get("tool_id")
|
|
278
|
+
# Second line of defense: even if the Qdrant ``enabled`` payload
|
|
279
|
+
# is stale, only keep tool_ids the registry currently has enabled.
|
|
280
|
+
if tool_id and tool_id in enabled_skill_ids:
|
|
281
|
+
allowed.add(tool_id)
|
|
282
|
+
if not allowed:
|
|
283
|
+
logger.warning(
|
|
284
|
+
f"Vector skill search returned no enabled matches for profile "
|
|
285
|
+
f"'{profile}'; falling back to manual behavior."
|
|
286
|
+
)
|
|
287
|
+
return None
|
|
288
|
+
logger.debug(
|
|
289
|
+
f"Automatic skill mode for profile '{profile}': selected "
|
|
290
|
+
f"{len(allowed)} skill(s) via vector search: {sorted(allowed)}"
|
|
291
|
+
)
|
|
292
|
+
return allowed
|
|
293
|
+
|
|
294
|
+
async def run(
|
|
295
|
+
self,
|
|
296
|
+
query: str,
|
|
297
|
+
task_history: List[Any],
|
|
298
|
+
context_id: str | None,
|
|
299
|
+
profile: str,
|
|
300
|
+
reasoning: bool = True,
|
|
301
|
+
triggered_by_event: bool = False,
|
|
302
|
+
) -> AsyncGenerator[ReasoningStreamResponseType, None]:
|
|
303
|
+
logger.debug(f"Running CremindAgent with query: {query} and profile: {profile}")
|
|
304
|
+
|
|
305
|
+
# Block runs while the vector embedding subsystem is still loading.
|
|
306
|
+
# If the user enabled embedding in the wizard, the model load is
|
|
307
|
+
# in flight and the agent must not respond until it's ready —
|
|
308
|
+
# otherwise embedding-dependent features (Automatic Skill Mode,
|
|
309
|
+
# Google Places filter, doc search) silently degrade.
|
|
310
|
+
from app.config.settings import BaseConfig
|
|
311
|
+
from app.config.embedding_state import embedding_state, EmbeddingStatus
|
|
312
|
+
from app.constants import ChatCompletionTypeEnum
|
|
313
|
+
|
|
314
|
+
if BaseConfig.is_embedding_enabled() and embedding_state.status is not EmbeddingStatus.READY:
|
|
315
|
+
status = embedding_state.status.value
|
|
316
|
+
err = embedding_state.error
|
|
317
|
+
if status == "initializing":
|
|
318
|
+
msg = (
|
|
319
|
+
"Vector embedding is still initializing. The agent will be "
|
|
320
|
+
"ready in a moment — please retry."
|
|
321
|
+
)
|
|
322
|
+
elif status == "failed":
|
|
323
|
+
msg = (
|
|
324
|
+
"Vector embedding initialization failed: "
|
|
325
|
+
f"{err or 'unknown error'}. Disable Vector Embedding in "
|
|
326
|
+
"Settings or check the server logs."
|
|
327
|
+
)
|
|
328
|
+
else:
|
|
329
|
+
msg = (
|
|
330
|
+
"Vector embedding is enabled but not ready "
|
|
331
|
+
f"(status: {status}). Please wait or check server logs."
|
|
332
|
+
)
|
|
333
|
+
logger.warning(f"Refusing agent run while embedding {status}: {err}")
|
|
334
|
+
yield {"type": ChatCompletionTypeEnum.DONE, "data": msg}
|
|
335
|
+
return
|
|
336
|
+
|
|
337
|
+
runner = self._ensure_runner(profile)
|
|
338
|
+
# Ensure this profile's embedding table is built (lazy).
|
|
339
|
+
self.embedding_table_for(profile)
|
|
340
|
+
allowed_skill_ids = await self._resolve_allowed_skill_ids(query, profile)
|
|
341
|
+
reasoning_agent = ReasoningAgent(
|
|
342
|
+
llm=runner,
|
|
343
|
+
registry=self.registry,
|
|
344
|
+
profile=profile,
|
|
345
|
+
context_id=context_id,
|
|
346
|
+
reasoning=reasoning,
|
|
347
|
+
allowed_skill_ids=allowed_skill_ids,
|
|
348
|
+
triggered_by_event=triggered_by_event,
|
|
349
|
+
)
|
|
350
|
+
|
|
351
|
+
async for result in reasoning_agent.run(query, task_history):
|
|
352
|
+
yield result
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
from typing import Any, Dict, List, Optional
|
|
2
|
+
|
|
3
|
+
from app.utils.logger import logger
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class ReasoningContextStore:
|
|
7
|
+
"""Centralized storage for reasoning agent contexts."""
|
|
8
|
+
|
|
9
|
+
_instance: Optional["ReasoningContextStore"] = None
|
|
10
|
+
_storage: Dict[str, Dict[str, Any]]
|
|
11
|
+
|
|
12
|
+
def __new__(cls) -> "ReasoningContextStore":
|
|
13
|
+
if cls._instance is None:
|
|
14
|
+
cls._instance = super().__new__(cls)
|
|
15
|
+
cls._instance._storage = {}
|
|
16
|
+
return cls._instance
|
|
17
|
+
|
|
18
|
+
def get_context(self, context_id: str) -> Optional[Dict[str, Any]]:
|
|
19
|
+
return self._storage.get(context_id)
|
|
20
|
+
|
|
21
|
+
def save_context(
|
|
22
|
+
self,
|
|
23
|
+
context_id: str,
|
|
24
|
+
steps: List[str],
|
|
25
|
+
step_count: int) -> None:
|
|
26
|
+
self._storage[context_id] = {
|
|
27
|
+
'steps': steps.copy(),
|
|
28
|
+
'step_count': step_count,
|
|
29
|
+
}
|
|
30
|
+
logger.info(
|
|
31
|
+
f"Saved context for context_id: {context_id} with {len(steps)} total steps")
|
|
32
|
+
|
|
33
|
+
def clear_context(self, context_id: str) -> None:
|
|
34
|
+
if context_id in self._storage:
|
|
35
|
+
del self._storage[context_id]
|
|
36
|
+
logger.info(f"Cleared context for context_id: {context_id}")
|
|
37
|
+
|
|
38
|
+
def clear_all_contexts(self) -> None:
|
|
39
|
+
self._storage.clear()
|
|
40
|
+
logger.info("Cleared all saved contexts")
|