feat: harden Ana Telegram memory and actions#383
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 4d082603bb
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Telegram Conversation & Workflow System - Add conversation tracking: persist Telegram conversations and messages with direction (inbound/outbound) in SQLite - Add workflow system: create cross-chat workflow requests that relay replies back to the originating chat - Add `ask-title` command to telegram-action-cli for initiating workflows - Add six new API endpoints for listing conversations, messages, workflows, events, and executing workflow requests - Wire TELEGRAM_WORKFLOW_URL env var into mission runner AI Provider OAuth & Account Email - Extract email from Anthropic token response (account.email_address) instead of relying on userinfo endpoint blocked by Cloudflare - Add browser-side fallback: when server can't fetch email, return access token to frontend for client-side userinfo fetch - Accept account_email in provider update requests - Add userinfo_access_token field to OAuth callback response Claude Code Usage & Rotation - Fix credential scopes: include user:sessions:claude_code so Claude Code can use normal Pro/Max allocation (not just extra usage) - Classify "out of extra usage" / "out of usage" as rate-limit errors so automatic account rotation triggers correctly - Improve fetch_anthropic_account_email logging with Cloudflare detection and POST method fallback
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: ccd96cce8b
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 158f1a73f2
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 8850703198
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 4b6ce5ff7d
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
- Fix @username/@target chat resolution passing chat_title as username instead of None for initial mapping match (telegram.rs) - Fix telegram-action CLI helper truncating multi-word text args by joining all remaining argv tokens with spaces (mission_runner.rs) - Fix premature "no matches" message in Telegram memory search UI by checking that a search was actually performed before displaying empty-results state (page.tsx) Co-Authored-By: Claude Opus 4.5 <[email protected]>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 527dc8dc5c
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Keep ana_lfgbot username unchanged per request. Co-Authored-By: Claude Opus 4.5 <[email protected]>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 3d37579f9b
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
…are command LLMs (particularly GLM-5.1 via OpenCode) were calling `telegram-action` as a bare command instead of using `$TELEGRAM_ACTION_COMMAND`. The script lived in the workspace directory which wasn't in PATH, causing "command not found" errors. Appending (not prepending) the workspace directory to PATH makes `telegram-action` discoverable while keeping system binaries at higher priority to avoid shadowing risks. Applied to both Claude Code and OpenCode backend execution paths. Co-Authored-By: Claude Opus 4.5 <[email protected]>
- control.rs: Replace hardcoded `true` for telegram_actions_available with proper gate checking build_internal_telegram_action_token() and localhost_api_base_url_from_env(), matching mission_runner.rs logic - control.rs: Use chrono_tz::Tz directly in cron evaluation instead of snapshotting a FixedOffset, so DST transitions are handled correctly by croner's find_next_occurrence - mission_runner.rs: Make localhost_api_base_url_from_env pub(super) so control.rs can access it for the action availability check Co-Authored-By: Claude Opus 4.5 <[email protected]>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 466b0218e3
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
…llback When telegram-action targets a @username that isn't found in telegram_chat_missions, the resolver now: 1. Searches telegram_conversations for matching titles/usernames 2. For @username targets, checks known group chats and resolves to a shared group where the target can be mentioned 3. Falls back to Telegram's getChat API for public groups/channels Also adds send-chat-id and ask-chat-id CLI commands for direct numeric chat_id targeting as a fallback. Co-Authored-By: Claude Opus 4.5 <[email protected]>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: b41b8054b1
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
When telegram-action targets a @username that gets resolved to a shared group chat (username-to-group fallback), the message text now starts with @username so the target bot actually receives it as a mention via its webhook. Without this, the message was sent to the group but the target bot had no way to know it was addressed. Co-Authored-By: Claude Opus 4.5 <[email protected]>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 82f8b3ceaf
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
The action execution log was storing the original text without the prepended @mention, making it inconsistent with what was actually sent to Telegram. Co-Authored-By: Claude Opus 4.5 <[email protected]>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 7f459872d5
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
…ce failures Fix two clippy lints (manual_is_multiple_of, redundant_closure) and rustfmt formatting across six files. Also log provider account email persistence errors instead of silently discarding them. Co-Authored-By: Claude Opus 4.5 <[email protected]>
Three fixes for mission reliability: 1. Plain OpenCode JSON mode now tracks tool depth from tool_use/step_finish events, preventing the 30s text-output idle timeout from killing processes during active MCP tool execution (web fetch, search). 2. When idle timeout kills an OpenCode process with partial output, append a truncation notice so the user knows the response is incomplete. 3. Proactively refresh OAuth credentials before copying to mission directory when host credentials are expired/near-expiry. Also extend maybe_recover_soft_llm_error to handle AuthError — if the agent produced substantive output, downgrade to TurnComplete instead of marking the mission as Failed.
…copy When a mission's credential file exists and hasn't expired locally but the host has a different (refreshed) token, re-copy the host credentials. This catches server-side token revocations where the old token's local expiry hasn't passed yet but the token was already revoked when OAuth refresh minted a new one.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: bb93a361c4
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| workflow.status = TelegramWorkflowStatus::Completed; | ||
| workflow.updated_at = now_string(); | ||
| workflow.completed_at = Some(workflow.updated_at.clone()); | ||
| let _ = ctx | ||
| .mission_store | ||
| .update_telegram_workflow(workflow.clone()) | ||
| .await; |
There was a problem hiding this comment.
Keep workflow pending until origin relay finishes
This path marks a workflow as Completed and persists it before relay_workflow_reply_to_origin runs, but the relay itself is asynchronous and can be lost on process crash/restart between these steps. In that failure window the workflow is no longer waiting_external, so the timeout/recovery sweep will never pick it up, and the external reply is effectively dropped instead of being relayed back to the origin mission/chat.
Useful? React with 👍 / 👎.
| ); | ||
| automation_manager.scope = McpScope::Workspace; | ||
| automation_manager.default_enabled = false; | ||
| automation_manager.default_enabled = true; |
There was a problem hiding this comment.
Provide API_URL when enabling automation-manager by default
automation-manager is now enabled by default, but its process falls back to http://localhost:3000 when API_URL is missing, while workspace env wiring only sets API_URL when PORT is present. In deployments where the server listens on a non-3000 configured port without exporting PORT, the MCP will boot automatically and send every request to the wrong endpoint, causing tool failures until operators manually override env.
Useful? React with 👍 / 👎.
- CLI helpers: skip rewriting files when content hasn't changed - PATH safety: use dedicated .sandboxed-sh-bin/ subdirectory instead of workspace root to prevent repo files from shadowing system binaries - React state updater: fix async side-effects and stale closure in toggleExpand by reading state before calling setter - CI cache: add restore-keys fallback for dashboard-bun cache step - Telegram memory UI: guard "no matches" message behind data-loaded check
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: f5e2df40aa
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| tracing::warn!(timezone = %tz, "Unknown timezone, falling back to UTC"); | ||
| Some(chrono_tz::Tz::UTC) |
There was a problem hiding this comment.
Reject unknown cron timezones instead of defaulting to UTC
In resolve_tz, an unrecognized timezone is coerced to UTC rather than rejected, so a typo like America/NewYork will silently run on UTC time while the automation still appears valid. That produces incorrect trigger times (often by hours) and is hard to diagnose from the API side; this path should fail closed (or validation should reject invalid timezones on create/update) instead of silently changing semantics.
Useful? React with 👍 / 👎.
| "Invalid cron expression, skipping: {}", e | ||
| ); | ||
| false |
There was a problem hiding this comment.
Reject malformed cron expressions before persisting automation
When cron parsing fails, the scheduler only logs and returns false, leaving the automation active but permanently non-executing; this turns malformed expressions into silent no-op automations that keep emitting warnings on each scheduler pass. Because creation/update does not validate cron syntax up front, users can save broken schedules that never run instead of receiving a request-time error.
Useful? React with 👍 / 👎.
Add the backend infrastructure for relaying FIDO/SSH signing requests to the iOS app: - FidoSigningHub: oneshot-channel map for pending approval requests - POST /api/fido/request: called by the FIDO agent proxy, blocks until iOS responds or 60s timeout - POST /api/fido/respond: called by iOS app to approve/deny - AgentEvent::FidoSignRequest: broadcast via SSE to connected clients
…elay New binary that listens on a Unix socket, speaks the SSH agent protocol, and intercepts FIDO/SK key sign requests. Non-FIDO operations are forwarded to the upstream agent. FIDO sign requests are relayed to the backend for mobile app approval via POST /api/fido/request.
When the FIDO agent proxy socket exists at /run/sandboxed-sh/fido-agent.sock, bind-mount it into containers and set SSH_AUTH_SOCK so SSH inside containers automatically uses the signing relay.
- FidoSignRequest model + AutoApprovalRule with expiration/biometric logic - FidoApprovalState: @observable singleton handling SSE events, rule matching, Face ID authentication, and approval/denial API calls - FidoApprovalOverlay: glass-morphism bottom sheet with countdown timer, request details, quick "auto-approve SSH for 5 min" chip, and approve/deny buttons - AutoApprovalRulesView: settings sub-view for managing active rules - Wired into ControlView SSE event stream and MainTabView overlay - Settings section for "Require Face ID for all requests" toggle
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit cd36ea2. Configure here.
| "Failed to persist provider account email" | ||
| ); | ||
| } | ||
| } |
There was a problem hiding this comment.
Provider account email overwritten for all same-type providers
Medium Severity
When updating a provider's account_email, the code calls update_provider_account with updated.provider_type.id() (e.g., "anthropic"), which is the provider type identifier, not the individual provider instance UUID. This means setting account_email on one Anthropic provider overwrites the stored account email for all Anthropic providers in provider_accounts.json, since update_provider_account keys by the type string. Users with multiple accounts of the same provider type will lose track of which account belongs to which instance.
Reviewed by Cursor Bugbot for commit cd36ea2. Configure here.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: cd36ea212d
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| ); | ||
|
|
||
| // Broadcast to all connected SSE clients (iOS app picks it up). | ||
| if let Some(control) = state.control.get_any_session_events_tx() { |
There was a problem hiding this comment.
Route FIDO approval events to the caller's session
post_fido_request emits FidoSignRequest through get_any_session_events_tx(), which selects only one arbitrary control session (values().next()) rather than the authenticated caller’s session. In multi-session/multi-user setups this can send the approval prompt to the wrong client while the real requester blocks until timeout, and it also leaks signing metadata to an unrelated session. The request path should bind to the current authenticated user/session and publish there (or deliberately fan out to all sessions with proper scoping).
Useful? React with 👍 / 👎.
| // Simple hash — just use first 16 bytes as a display fingerprint | ||
| // (full SHA256 would require a dependency; this is good enough for display) | ||
| let mut hex = String::with_capacity(48); | ||
| for (i, byte) in blob.iter().take(16).enumerate() { |
There was a problem hiding this comment.
Compute a real fingerprint for key-based auto-approval
The proxy labels this value as a key fingerprint but actually uses only the first 16 bytes of the SSH key blob, which are largely header/key-type bytes and can collide across different keys. Any auto-approval rule keyed by key_fingerprint can therefore match unrelated keys and approve unintended signatures. Use a full digest (e.g., SHA-256 over the key blob) for stable, unique key identity.
Useful? React with 👍 / 👎.


Summary
Testing
Note
Medium Risk
Touches authentication identity resolution for single-tenant/disabled auth modes and adds new iOS approval flows, which could affect access partitioning and user interactions if misconfigured. CI/caching and dashboard additions are low risk but may surface latent API/contract mismatches.
Overview
CI is modernized and sped up by bumping GitHub Actions to
@v5, splitting Cargo registry vstargetcaches, caching dashboard Bun/Next.js artifacts, and enforcingcargo --locked(including harness contract scripts).Telegram admin visibility is expanded in the dashboard with new API types/endpoints for listing recent action executions, scheduled messages, and structured memory plus ranked memory search, all loaded when a bot row is expanded.
iOS dashboard adds FIDO signing approvals via an SSE-driven
fido_sign_requesthandler, a full-screen approve/deny overlay with countdown, and persisted auto-approval rules (optionally requiring Face ID), backed by a newPOST /api/fido/respondclient call.Backend auth/provider flows are hardened by allowing an override for the implicit single-tenant user ID via env vars, persisting
account_emailupdates from the frontend, and making Anthropic userinfo fetching more resilient (GET→POST fallback and better logging).Reviewed by Cursor Bugbot for commit cd36ea2. Bugbot is set up for automated code reviews on this repo. Configure here.