Covers both data connector (read messages) and messaging channel (DM the agent).
Includes the full App Manifest JSON, required scopes table, and all the gotchas
we discovered (Request URL, reinstall requirement, App Token vs Bot Token, etc.).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- When binding a SendBlue channel and no ChannelBridge exists, create
one with a DeepResearchAgent wired to the knowledge store
- Fix _build_deep_research_tools scoping issue via self-import
- Fix model name resolution to fall back to app.state.model
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replaced raw slack-sdk SocketModeClient with slack-bolt App which
properly handles event subscriptions, self-event filtering, and
message routing. Bot says "Message received! Researching now..."
then runs DeepResearchAgent and replies with the research result.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
When /api/lines returns no numbers (free/shared line tier), the wizard
now shows a manual input with instructions to copy the phone number
from the "Send from" field in the SendBlue dashboard, instead of
showing an error.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Backend:
- POST /v1/channels/sendblue/verify — validates API keys, auto-fetches
assigned phone numbers from SendBlue GET /api/lines
- POST /v1/channels/sendblue/register-webhook — auto-registers the
/webhooks/sendblue callback URL with SendBlue
- POST /v1/channels/sendblue/test — sends a test iMessage to verify setup
Frontend:
- SendBlueWizard component with multi-step guided flow:
Step 1: "Open SendBlue signup" button (opens in new tab)
Step 2: Paste API Key + Secret → "Verify & Find Number" auto-fetches
Step 3: Shows discovered phone number → "Activate Phone Number"
Step 4: Success state with "Send Test" button
- Active state shows agent's number + test message sender
- Generic channels (Slack, WhatsApp, SMS, local iMessage) listed below
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
When user connects Slack in the Messaging tab, the backend now creates
a SlackChannel with Socket Mode, registers a handler that routes incoming
DMs to DeepResearchAgent, and starts listening. Unbinding disconnects
the Socket Mode client.
Requires slack-sdk installed and both bot_token (xoxb-) + app_token (xapp-).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The 2-second polling interval was replacing local messages (with _usage,
_telemetry) with server messages (without those fields). Now stores
metadata in a ref and merges it back when polling refreshes.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The progress indicator now only shows when waitingForResponse or sending
is true, preventing it from persisting after the response arrives due to
stale isAgentWorking/hasPending checks. Agent response bubbles now display
elapsed time, tool call count, and a copy button in an XRay-style footer.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Learning log entries (query_start, tool_call, tool_result, query_complete)
now persist to SQLite and appear in the Logs tab. Fixed result.output->content
attribute name and removed debug print statements.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Replace "Run Now" button with "Chat ready" hint when on the Interact
tab so users know they can just type a message without pressing Run.
- Add learning log entries in generate_deep_research() for query start,
tool calls, tool results, query completion, and errors so interactive
queries are visible in the Logs tab.
- Rewrite LogsTab to poll every 5 seconds, merge execution traces with
learning log entries into a unified timeline sorted by timestamp.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Refactor sendAgentMessage to accept onProgress/onContentDelta/onDone
callbacks so the InteractTab can show content as it arrives word by
word, display tool-call progress labels (e.g. "Querying data with
SQL"), and render an elapsed-time footer. The backend now streams
tool_progress SSE events from DeepResearchAgent before the final
content, matching the Chat tab's polished streaming UX.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Added waitingForResponse state that stays true during the entire stream
consumption. Shows a pulsing indicator with descriptive text so the user
knows the agent is working (searching, analyzing, writing report).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1. InteractTab now displays the streamed agent response as a bubble
immediately after it finishes (was being discarded)
2. Connecting a source auto-triggers background ingest into KnowledgeStore
so Google Drive data appears with chunk counts immediately
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The Google OAuth flow runs in a background thread. The frontend now polls
every 3s after connecting to detect when the token arrives, and auto-refreshes
every 10s to catch background completions.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The streaming endpoint was calling engine.stream_full() directly without
tools, so the agent responded as a generic chatbot. Now detects
deep_research agent type and runs the full DeepResearchAgent.run() loop
with knowledge_search, knowledge_sql, scan_chunks, and think tools,
then streams the result as SSE.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The OAuth callback server blocks with handle_request(). Running it in a
daemon thread prevents it from freezing the FastAPI event loop.
Also accept system_prompt kwarg in DeepResearchAgent.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The Interact tab was sending messages without stream:true, so the backend
just stored them as pending without running the agent. Now consumes the
SSE stream and displays the full response.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Covers setup instructions and troubleshooting for all 12 connectors:
Gmail, Google Drive, Calendar, Contacts, Slack, Notion, Granola,
Apple Notes, iMessage, Outlook, Obsidian, Dropbox.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add exchange_google_token() and run_oauth_flow() to oauth.py for the
full authorization code exchange. Update gdrive, gcalendar, and
gcontacts connectors to trigger the browser-based OAuth flow when a
client_id:client_secret pair is provided, prefer access_token over raw
token, and require an actual access_token for is_connected(). auth_url()
now returns the Cloud Console credentials page when no client_id is
stored.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Connected sources now show a "Reconnect" button that expands the inline setup
flow to re-enter credentials. Sources with 0 chunks show "Connected — no data
synced yet" in amber instead of "0 items" in green.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Remove duplicate gmail OAuth entry, rename gmail_imap to gmail in frontend
so it matches the backend connector ID that has the actual data.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Rewrite ChannelsTab to show connector data sources (Gmail, Slack, Notion,
etc.) with chunk counts, connected/not-connected states, and inline setup
with step-by-step instructions. Add new MessagingTab for phone/platform
messaging (iMessage, Slack, WhatsApp, SMS). Update DETAIL_TABS to include
both tabs with Database and Wifi icons respectively.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Adds StepByStepPanel component to SourceConnectFlow that renders numbered
setup steps with optional links and input fields for each connector. Wires
it as the primary panel for any connector with steps defined, with existing
OAuth/Local/Filesystem panels as fallbacks. Also updates connectors.ts to
use ConnectorMeta (with SetupStep/inputFields) as the canonical type and
exports SourceCard as a backward-compatible alias.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds iMessage, Slack, WhatsApp, and SMS (Twilio) channel binding UI to
the agent detail view, with expandable connect forms and active/disconnect states.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Remove "Cloud Savings for Agent" card title. Add "Agent Statistics"
as section title over the usage metrics, aligned with "Local
Utilization" and "Dollars Saved vs." — all three sections now have
matching uppercase labels at the same vertical position.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Three grouped sections inside the savings card, separated by
vertical dividers: usage metrics | Local Utilization (compute,
energy) | Dollars Saved vs. (GPT-5.3, Claude, Gemini). Section
titles are small uppercase labels above each group.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Vertical "SAVED vs." label between the divider and provider costs
makes it clear the dollar amounts represent money avoided by
running locally instead of using cloud APIs.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Single card with "Cloud Savings for Agent" header. All metrics
(queries, tokens, compute, energy, dollar savings) in one flex row
with vertical dividers separating usage | compute+energy | costs.
Large bold values above small labels. Consistent typography.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
All bubbles (Total Queries, Input Tokens, Output Tokens, Compute,
Energy, and per-provider dollar savings) now sit in one flex row
under "Cloud Savings for Agent". Each bubble has the value (bold)
above the label, with consistent styling. Green for savings values.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Usage stats (Total Queries, Input Tokens, Output Tokens) and Cloud
Savings (Compute, Energy, Dollar Savings) now use flex rows with
compact padding, left-aligned, wrapping naturally without filling
the full width.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>