Commit graph

704 commits

Author SHA1 Message Date
CREDO23
24b62a63b4 refactor(agents): introduce chat/ category; dissolve top-level agents/shared
Recursive shared-folder rule: a shared/ must be shared by ALL siblings at its
level. The kernel (context, compaction, retry_after, web_search) was shared by
only 2 of the agents -- anonymous_chat + multi_agent_chat -- never by podcaster
or video_presentation. Those 2 are the "chat" category, so their shared code
belongs in that category's shared/, not the top-level one.

  app/agents/anonymous_chat/   -> app/agents/chat/anonymous_chat/
  app/agents/multi_agent_chat/ -> app/agents/chat/multi_agent_chat/
  app/agents/shared/           -> app/agents/chat/shared/   (anon<->mac kernel)

Top-level app/agents/shared/ is gone: nothing was shared across all three
categories (chat / podcaster / video_presentation).

~289 import sites rewritten (app.agents.{anonymous_chat,multi_agent_chat,shared}
-> app.agents.chat.*); all moves are git renames (history preserved).
app/agents/ now: chat/, podcaster/, video_presentation/, runtime/.
2026-06-05 12:54:02 +02:00
CREDO23
d59bb2b5aa refactor(agents): evict mac-only tools/middleware from shared kernel
These were never shared with anonymous_chat (nor podcaster/video_presentation)
-- only multi_agent_chat (subagents/main agent) and the boundary use them:

  shared/tools/mcp/             -> multi_agent_chat/shared/tools/mcp/
  shared/tools/hitl.py          -> multi_agent_chat/shared/tools/hitl.py
  shared/tools/catalog.py       -> multi_agent_chat/shared/tools/catalog.py
  shared/middleware/dedup_tool_calls.py
                                -> multi_agent_chat/shared/middleware/dedup_tool_calls.py

app/agents/shared/ now holds only the genuine anon<->mac kernel:
context, middleware/{compaction,retry_after}, tools/web_search.
2026-06-05 12:50:46 +02:00
CREDO23
b7ea829371 refactor(agents): relocate boundary-only infra out of shared/
Neither module is imported by any sibling agent package, so neither belongs in
the cross-agent shared kernel:

- checkpointer.py -> app/agents/runtime/checkpointer.py
  LangGraph Postgres checkpoint saver. It's cross-agent *runtime infra* wired by
  the boundary (app lifespan + anonymous_chat & multi_agent_chat flows), not
  agent code. New app/agents/runtime/ layer holds boundary-wired agent infra.

- shared/system_prompt.py + shared/prompts/ -> app/prompts/
  The legacy single-agent prompt composer. The live agents don't use it
  (main_agent has its own system_prompt/ builder; anonymous_chat builds inline);
  its only consumer is new_llm_config_routes for displaying default instructions.
  Moved to the existing non-agent prompt domain:
    system_prompt.py        -> app/prompts/default_system_instructions.py
    prompts/                 -> app/prompts/system_prompt_composer/

app/agents/shared/ now contains only genuinely cross-agent code: context,
middleware/{compaction,retry_after,dedup_tool_calls}, tools/.

NOTE: get_default_system_instructions() (LLM-config UI) composes from the legacy
library, which differs from what the live agents actually run -- pre-existing
latent staleness, not changed here.
2026-06-05 12:36:44 +02:00
CREDO23
82c5dc5b02 refactor(agents): move mac-only modules out of the cross-agent shared kernel
app/agents/shared/ is a sibling of anonymous_chat/podcaster/multi_agent_chat/
video_presentation, so it should only hold code shared across 2+ of those
agents. In practice podcaster and video_presentation import nothing from it,
and anonymous_chat needs only context + compaction + retry_after + web_search.
Everything else was multi_agent_chat-only (the boundary just passes through).

Move the multi_agent_chat-only cluster into multi_agent_chat/shared/ (files
moved verbatim via git rename; ~116 import sites rewritten):

  errors, feature_flags, filesystem_selection, path_resolver, prompt_caching,
  sandbox, llm_config, mention_resolver
  middleware/busy_mutex, middleware/kb_persistence

busy_mutex/llm_config/mention_resolver are boundary-only but import the moved
modules, so they were folded in to avoid a backwards shared -> multi_agent_chat
dependency. main_agent builders now import the impls directly; the shared
middleware barrel keeps only the genuinely-shared compaction + retry_after.

Also delete the dead leftover shared/plugins and shared/skills dirs (live
copies already live under main_agent/).

Remaining in app/agents/shared/: context, system_prompt(+prompts), checkpointer,
middleware/{compaction,retry_after,dedup_tool_calls}, tools/. checkpointer and
system_prompt are boundary-only infra pending a dedicated home decision.
2026-06-05 12:30:15 +02:00
CREDO23
c51aca6ccc refactor(agents): group MCP tools into shared/tools/mcp/ subpackage
The three MCP siblings (mcp_client/mcp_tool/mcp_tools_cache) served one
objective but sat loose at the top of shared/tools. Grouped them into an
mcp/ package and dropped the redundant prefix: client.py, tool.py, cache.py.
Updated all importers (routes, mcp_tools subagent, e2e fake patch targets,
unit test) to the new paths.
2026-06-04 20:35:38 +02:00
CREDO23
003924062d refactor(agents): split tool registry into pure-data catalog, decouple connectors
Replace the connector-coupled BUILTIN_TOOLS registry with a pure-data
catalog so shared/tools no longer imports any connector module, making the
connector packages independently deletable.

- add shared/tools/catalog.py (ToolMetadata + TOOL_CATALOG, 41 tools, no imports)
- point GET /agent/tools (the only live consumer) at the catalog
- relocate ToolDefinition into action_log middleware (its sole consumer);
  drop the inert tool_definitions wiring (no tool defines reverse)
- delete shared/tools/registry.py: connector imports, dead factories,
  dead get_connector_gated_tools, and BUILTIN_TOOLS
- drop stale dedup-propagation test (path removed in C1) + refresh docstrings

import-all guardrail + agents unit suite green (987 passed).
2026-06-04 19:43:50 +02:00
CREDO23
5b45f78a16 refactor(chat): delete legacy stream_new_chat monolith (cutover complete)
The flows orchestrators (new_chat/resume_chat) are now the sole live path
after the byte-for-byte differential proof, so the monolith and its
monolith-vs-flows parity scaffolding are removed.

- Repoint the last live importer (anonymous_chat_routes) to
  streaming.agent.event_loop.stream_agent_events + shared.stream_result.StreamResult
  (drop-in; the keyword-only fallback-commit params default to inert for anon).
- Repoint e2e launcher patch targets to flows.shared.llm_bundle.
- Repoint helper unit tests (chunk_parts, thinking-step ids, tool-input
  streaming) to their flows homes to preserve coverage.
- Delete the monolith, the contract test, and the parity tests
  (parallel_refactor, stage_1, stage_2, orchestrator_frame) whose sole
  purpose was comparing against the now-removed monolith.

Full suite green (2622 passed, 1 skipped); the two excluded live-app dirs
(document_upload, composio) have a pre-existing, env-gated registration 404
unrelated to this change.
2026-06-04 14:35:45 +02:00
CREDO23
b9937cf4b1 refactor(chat): cut live chat streaming over to flows orchestrators (cutover)
Flip the live callers (new_chat_routes + gateway/agent_invoke) from the
legacy monolithic app.tasks.chat.stream_new_chat to the side-by-side
app.tasks.chat.streaming.flows orchestrators.

Adds a byte-for-byte differential parity test driving BOTH implementations
on identical, fully-deterministic glue inputs (frozen time/uuid, stubbed
LLM/persistence/agent seams). All glue paths are byte-identical:
  * new: auto-pin failure, LLM-load failure, persist-user fail,
    persist-assistant fail (full initial-frame ordering + handshake),
    pre-stream exception (top-level except path)
  * resume: persist-assistant fail

The differential test also surfaced one INTENTIONAL divergence: on a resume
turn whose auto-pin / LLM-load fails, the monolith crashes with
UnboundLocalError (_resume_premium_request_id read in finally before its
post-early-return definition); the flows version emits a clean terminal
error. The flows path is therefore byte-identical or strictly more correct.

The agent-content stream itself is shared, unforkable code
(stream_output -> EventRelay) so it cannot diverge.

Monolith + old parity test deletion follows in a separate commit.
2026-06-04 14:24:18 +02:00
CREDO23
64d2ad6451 refactor(agents): promote anonymous_agent to its own anonymous_chat/ package (slice 8)
The anonymous / free-chat agent is a distinct live agent (not part of the
single-agent stack and not shared infrastructure), so it gets its own top-level
package app/agents/anonymous_chat/ (sibling to multi_agent_chat). Moved
new_chat/anonymous_agent.py -> anonymous_chat/agent.py with a package __init__
re-exporting create_anonymous_chat_agent + build_anonymous_system_prompt.

Repointed its only new_chat import (the context shim) to app.agents.shared.context
and updated the single importer (anonymous_chat_routes). The test_import_all
guard auto-discovers the new package via pkgutil.walk_packages, so it is covered.
2026-06-04 13:25:23 +02:00
CREDO23
a019f18d1c refactor(agents): move connector_searchable_types, agent_cache, system_prompt + prompts to app/agents/shared (slice 7b)
Three live shared leaves discovered while taking stock after slice 7 (all are
consumed by the multi-agent stack and/or live routes, not single-agent-only):

- connector_searchable_types -> shared + shim (multi-agent factory uses it)
- agent_cache -> shared + shim (multi-agent runtime/agent_cache uses it)
- system_prompt + prompts/ (42 .md fragments) -> shared together + shim.
  Repointed composer's _PROMPTS_PACKAGE to app.agents.shared.prompts so
  importlib.resources fragment loading keeps working; system_prompt's relative
  ".prompts.composer" import is preserved by moving both as a unit.

Each keeps a re-export shim for the frozen chat_deepagent. After this slice,
new_chat/ holds only the frozen single-agent stack (chat_deepagent, subagents/,
__init__) plus shims.
2026-06-04 13:21:45 +02:00
CREDO23
aab95b9130 refactor(agents): move tools package to app/agents/shared (slice 6)
Relocate the entire new_chat/tools/ package (62 files incl. registry, hitl, MCP
cluster, and all connector subpackages: gmail/slack/discord/teams/drive/etc.)
to the shared kernel. The package turned out to be a clean cohesive cluster:
its only references to non-tools new_chat modules were comments, and its
middleware deps were already flipped to shared in slice 5c.

Flip 33 live importers (multi-agent, flows, routes, services, anonymous_agent,
tests). Re-export shims remain for the frozen single-agent stack: a package
__init__ mirroring the public surface (new_chat.__init__ imports it) plus
invalid_tool + registry submodule shims (chat_deepagent imports those).

Resolves slice 5c's two transient back-edges: shared/middleware/action_log
(TYPE_CHECKING ToolDefinition) and tool_call_repair (local INVALID_TOOL_NAME)
now point at app.agents.shared.tools.
2026-06-04 13:11:56 +02:00
CREDO23
227983a104 refactor(agents): move middleware package to app/agents/shared (slice 5c)
Relocate the entire new_chat/middleware/ package to the shared kernel as one
cohesive unit (it is live shared infrastructure: the multi-agent stack wraps
nearly every middleware via multi_agent_chat/middleware/main_agent/*, and
anonymous_agent consumes it too). Flip 69 live importers across both the
package-path and submodule-path forms.

Shims left for the frozen single-agent stack: a package __init__ re-export plus
submodule shims for permission, skills_backends, and scoped_model_fallback
(the three imported via submodule path by chat_deepagent/subagents).

Cycle break: importing shared.middleware previously reached back into
new_chat.tools at module load, which dragged in new_chat.__init__ ->
chat_deepagent -> the middleware shim -> half-initialized shared.middleware.
Made action_log's ToolDefinition import TYPE_CHECKING-only and
tool_call_repair's INVALID_TOOL_NAME import function-local. These tools-package
back-edges fully resolve in slice 6.

Asset note: skills_backends._default_builtin_root now walks to
app/agents/new_chat/skills/builtin (the skills/ tree migrates in slice 7).
2026-06-04 13:00:41 +02:00
CREDO23
6f488d9564 refactor(agents): move checkpointer + mention_resolver to app/agents/shared (slice 5b)
Two independent leaf modules (no intra-new_chat deps, no frozen importer),
consumed only by flows/routes/tests. Flipped 8 importers across both the
dotted-path and module-style (from app.agents.new_chat import mention_resolver)
forms. No shims needed.
2026-06-04 12:52:54 +02:00
CREDO23
946f8a8c5d refactor(agents): move llm_config + prompt_caching to app/agents/shared (slice 4b)
Relocate the mutually-dependent LLM config layer and the LiteLLM prompt-caching
helper to the shared kernel as one unit, rewiring their internal cross-reference
to the shared paths. Flip 21 non-frozen importers. Re-export shims remain at
new_chat/{llm_config,prompt_caching}.py for the frozen single-agent stack
(chat_deepagent); they will be removed when that stack is retired.
2026-06-04 12:41:52 +02:00
CREDO23
3efe51e6ec refactor(agents): move filesystem_state, path_resolver, sandbox to app/agents/shared (slice 3b)
Relocate three leaf filesystem-cluster modules to the shared kernel and flip
all 38 importers. No re-export shims needed (no frozen single-agent importer).
This also resolves the pre-existing shared->new_chat back-edge from
shared/receipt_command.py onto filesystem_state.

filesystem_backends is intentionally deferred to slice 5: it depends on
new_chat middleware (kb_postgres_backend, multi_root_local_folder_backend)
that have not yet moved, so relocating it now would create a shared->new_chat edge.
2026-06-04 12:34:28 +02:00
CREDO23
1b536b8aee refactor(agents): move filesystem_selection to app/agents/shared (slice 3a)
Promote the filesystem mode contracts (FilesystemMode, FilesystemSelection,
ClientPlatform, LocalFilesystemMount) out of `new_chat` into the cross-agent
`app/agents/shared` kernel.

Pure leaf consumed across the whole multi-agent filesystem middleware/tool tree,
the chat flows/monolith, routes and tests. git mv (content unchanged) + flipped
all ~48 importers. A re-export shim remains at new_chat/filesystem_selection.py
only for the not-yet-retired single-agent (chat_deepagent).

Also updated the stream parity test's annotation normalizer to strip the new
app.agents.shared.filesystem_selection. prefix (the dataclasses' __module__
changed with the move), keeping monolith<->flows signature parity intact.

Behavior-preserving: only import paths change. 1326 tests green.
2026-06-04 12:28:20 +02:00
CREDO23
a975754e7d refactor(agents): move feature flags to app/agents/shared/feature_flags (slice 2b)
Promote the agent feature-flag resolver (AgentFeatureFlags / get_flags) out of
`new_chat` into the cross-agent `app/agents/shared` kernel.

feature_flags is a pure leaf consumed across the multi-agent middleware stack,
the chat routes, and tests. Moved it via git mv (content unchanged) and flipped
all 37 importers to app.agents.shared.feature_flags. A thin re-export shim
remains at new_chat/feature_flags.py only for the not-yet-retired single-agent
(chat_deepagent); it goes away with the single-agent deletion.

Behavior-preserving: only import paths change. 1243 tests green.
2026-06-04 12:23:12 +02:00
CREDO23
9dab07f775 refactor: point notification callers at notifications module 2026-06-03 18:04:47 +02:00
CREDO23
5d2a36f579 refactor: serve notifications API from notifications module 2026-06-03 18:04:47 +02:00
CREDO23
a4b31929d0 feat(documents): persist original upload bytes on file upload 2026-06-02 16:10:50 +02:00
CREDO23
7dad9ec3a9 feat(api): mount file-storage router 2026-06-02 16:10:50 +02:00
Anish Sarkar
e3de7c4667 Merge remote-tracking branch 'upstream/dev' into feat/whatsapp-gateway-integration 2026-06-02 00:29:32 +05:30
Anish Sarkar
799a83239f feat(gateway): add Slack and Telegram gateway configuration and enablement checks 2026-06-01 23:58:28 +05:30
Anish Sarkar
fc2467be3d feat(gateway): improve WhatsApp account mode handling and connection filtering 2026-06-01 23:08:56 +05:30
Anish Sarkar
a151e8f729 feat(gateway): enhance WhatsApp account management and connection handling 2026-06-01 22:49:46 +05:30
Anish Sarkar
2d1a6be776 feat(gateway): implement search space management for messaging channels 2026-06-01 21:39:09 +05:30
Anish Sarkar
7860714f74 feat(gateway): add Discord gateway install flow 2026-06-01 20:59:31 +05:30
Anish Sarkar
9c7e093db4 feat(gateway): add Slack gateway webhook flow 2026-06-01 12:37:04 +05:30
DESKTOP-RTLN3BA\$punk
0f2e3c7655 refactor: anonymous/free chat experience
- Enhanced lambda function formatting in `_after_commit` for better clarity.
- Simplified generator expression in `_match_condition` for improved readability.
- Streamlined function signature in `_eligible` for consistency.
- Updated imports and refactored anonymous chat routes to use a new agent creation method.
- Added a new function `_load_anon_document` to handle document loading from Redis.
- Improved UI components by replacing legacy structures with modern alternatives, including alerts and separators.
- Refactored quota-related components to utilize new alert structures for better user feedback.
- Cleaned up unused variables and optimized component states for performance.
2026-05-31 15:58:21 -07:00
CREDO23
d2c4b046bf fix(documents): use ORM objects in bulk_move so session hooks fire 2026-05-29 22:25:04 +02:00
Anish Sarkar
389a51d494 feat(gateway): enhance WhatsApp bridge with pairing timeout and health check integration 2026-05-29 13:37:45 +05:30
DESKTOP-RTLN3BA\$punk
40ca9e6ed2 refactor: remove search_surfsense_docs tool and related references
- Deleted the `search_surfsense_docs` tool and its associated files, streamlining the agent's toolset.
- Updated various components and prompts to remove references to the now-removed tool, ensuring consistency across the codebase.
- Adjusted documentation to direct users to the SurfSense documentation link for product-related queries instead.
2026-05-28 22:35:14 -07:00
Anish Sarkar
185759de1f feat(gateway): register multi-platform gateway routes 2026-05-29 10:20:43 +05:30
Anish Sarkar
63f9fe61b5 feat(gateway): expose Baileys pairing endpoints 2026-05-29 10:19:29 +05:30
Anish Sarkar
dbd9966219 feat(gateway): add WhatsApp Cloud webhook intake 2026-05-29 10:18:58 +05:30
DESKTOP-RTLN3BA\$punk
94e834134f chore: linting 2026-05-28 19:21:29 -07:00
Rohan Verma
4dda02c06c
Merge pull request #1443 from CREDO23/feature-automations
[Feat] Automation V1 — Scheduled Agent Tasks, Created via Chat (HITL) or JSON
2026-05-28 12:41:41 -07:00
Anish Sarkar
72024353f9 fix(gateway): harden Telegram webhook intake 2026-05-28 04:37:41 +05:30
CREDO23
79f0218360 rbac: surface automations permissions in the UI
Backend already defined automations:create/read/update/delete/execute and
seeded them on Owner/Editor/Viewer roles, but the Settings → Roles UI was
missing the metadata to render them properly.

- backend: add PERMISSION_DESCRIPTIONS entries for the 5 automations perms so
  the role editor stops falling back to "Permission for automations:create".
- frontend: add automations to CATEGORY_CONFIG (Workflow icon, slotted between
  podcasts and connectors) so the role editor groups them as a real section.
- frontend: extend the three ROLE_PRESETS — Editor and Contributor get
  create/read/update/execute (mirroring backend Editor); Viewer gets read.

Prep work for the automations frontend; canPerform/usePermissionGate already
handle the runtime gating, so no new hook is needed.
2026-05-28 00:30:40 +02:00
CREDO23
c0232fdcfe refactor(automations): park manual trigger pending Run-now redesign
Manual-as-a-standalone-trigger conflates "user clicks Run now" with the
trigger model and forces ad-hoc input plumbing on the caller. Remove the
unreachable surface so the tree reflects reality (schedule is the only
v1 trigger).

- Unregister `manual`: drop import from triggers/__init__.py
- Delete `app/automations/triggers/manual/`
- Drop `RunService.dispatch_manual` (RunService is now read-only)
- Drop `POST /automations/{id}/run` and `RunDispatched` schema
- Keep `TriggerType.MANUAL` Python + PG enum value (reserved, documented)
  to avoid an Alembic round-trip when Run-now is redesigned
2026-05-27 22:29:51 +02:00
Anish Sarkar
d32e8c6a90 feat(gateway): expose binding and webhook APIs 2026-05-27 23:39:24 +05:30
CREDO23
dd6bc30f98 move automations api into vertical slice with service layer 2026-05-27 18:56:16 +02:00
CREDO23
861b91004d refactor(automations): extract dispatch_run; move manual adapter under triggers/manual/dispatch.py 2026-05-27 17:20:23 +02:00
CREDO23
cfbe2a7fe0 feat(automations): expose POST /automations/{id}/run 2026-05-27 15:30:45 +02:00
Anish Sarkar
a41b16b73e feat(web): enhance chat context and mention handling with connector support 2026-05-26 21:11:53 +05:30
Anish Sarkar
7a3b278b75 feat(connectors): add retry and auth telemetry events 2026-05-22 17:50:02 +05:30
Anish Sarkar
87a4dcfd05 feat(tasks): record indexing heartbeat metrics 2026-05-22 13:50:32 +05:30
CREDO23
49da7a57df Merge remote-tracking branch 'upstream/dev' into improvement-agent-speed
Resolves: surfsense_backend/app/agents/new_chat/middleware/memory_injection.py
- Took both imports: upstream moved MEMORY_HARD_LIMIT/SOFT_LIMIT to
  app.services.memory; kept our perf-logger import for timing.

Pulls in upstream changes:
- Memory document feature (services/memory refactor, removal of
  app.agents.new_chat.memory_extraction and background extraction in
  stream_new_chat — agent now drives memory via update_memory tool).
- BACKEND_URL env refactor across web tool-ui/editor/chat/dashboard/lib.
- GitHub Actions backend test workflow + pre-commit biome bump.
- Token-display polish in MessageInfoDropdown; save_memory no-update
  sentinel.

Verified: 1723 unit tests pass, ruff clean. No semantic regression in
stream_new_chat (their memory-extraction deletion and our preflight
removal touch different functions).
2026-05-20 21:23:48 +02:00
CREDO23
d5ee8cc4cd Merge remote-tracking branch 'upstream/dev' into improvement-agent-speed 2026-05-20 19:22:49 +02:00
CREDO23
704d1bf18f refactor(mcp): per-connector cache refresh on lifecycle events
Collapse the invalidate + warmup pair into a single
refresh_mcp_tools_cache_for_connector(connector_id, search_space_id)
helper and scope live discovery to the one connector that changed
instead of the whole search space.

- new mcp_tool.discover_single_mcp_connector: load one connector,
  refresh OAuth if needed, force live MCP discovery so its cached_tools
  row is rewritten; returned wrappers are discarded since the in-process
  LRU is rebuilt lazily on the next user query
- mcp_tools_cache.refresh_mcp_tools_cache_for_connector: synchronously
  evicts the per-space LRU (LRU keys cannot scope finer) and schedules
  the per-connector prefetch via loop.create_task
- routes (OAuth callback, MCP POST, MCP PUT) collapse their two
  back-to-back calls into a single refresh call; DELETE handlers keep
  using bare invalidate_mcp_tools_cache (nothing to prefetch)

No new automated tests: the new functions are I/O glue (DB + network)
where mocked unit tests would test implementation rather than behavior.
The existing 9 unit tests for the cached_tools data shape are unchanged.
2026-05-20 17:43:27 +02:00