Previously, grammY's default bot.start() processed updates sequentially,
blocking all Telegram messages while one was being handled. This made
maxConcurrent settings ineffective for Telegram.
Now uses @grammyjs/runner which processes updates concurrently, matching
the behavior of Discord (Promise.all) and WhatsApp (fire-and-forget).
Benefits:
- Ack reactions (👀) appear immediately, not after queue clears
- Multiple chats can be processed in parallel
- maxConcurrent setting now works correctly for Telegram
- Long-running tool calls no longer block other conversations
When the conversation context exceeds the model's limit, instead of
throwing an opaque error or returning raw JSON, we now:
1. Detect context overflow errors (413, request_too_large, etc.)
2. Return a user-friendly message explaining the issue
3. Suggest using /new or /reset to start fresh
This prevents the assistant from becoming completely unresponsive
when context grows too large (e.g., from many screenshots or long
tool outputs).
Addresses issue #394
Claude API on Vertex AI (Cloud Code Assist) rejects nested anyOf schemas
as invalid JSON Schema draft 2020-12. This change:
- Add tryFlattenLiteralAnyOf() to convert Type.Union([Type.Literal(...)])
patterns from anyOf with const values to flat enum arrays
- Update stringEnum helper in bash-tools to use Type.Unsafe with flat enum
- Flatten BrowserActSchema from discriminated union to single object
- Simplify TelegramToolSchema to use Type.String() for IDs
Fixes 400 errors when sending messages through WhatsApp/Telegram providers.
Add 5 tests for agent-specific tool restrictions:
- Apply global tool policy when no agent-specific policy exists
- Apply agent-specific tool policy
- Allow different tool policies for different agents
- Combine global and agent-specific deny lists
- Work with sandbox tools filtering
All tests pass.
Add 6 tests for agent-specific sandbox configuration:
- Use global sandbox config when no agent-specific config exists
- Override with agent-specific sandbox mode 'off'
- Use agent-specific sandbox mode 'all'
- Use agent-specific scope
- Use agent-specific workspaceRoot
- Prefer agent config over global for multiple agents
All tests pass.
Add 7 tests for resolveAgentConfig():
- Return undefined when no agents config exists
- Return undefined when agent id does not exist
- Return basic agent config (name, workspace, agentDir, model)
- Return agent-specific sandbox config
- Return agent-specific tools config
- Return both sandbox and tools config
- Normalize agent id
All tests pass.
Changes to defaultSandboxConfig():
- Add optional agentId parameter
- Load routing.agents[agentId].sandbox if available
- Prefer agent-specific settings over global agent.sandbox
Update callers in resolveSandboxContext() and
ensureSandboxWorkspaceForSession() to extract agentId
from sessionKey and pass it to defaultSandboxConfig().
This enables per-agent sandbox modes (e.g., main: off, family: all).
Return newly added fields from routing.agents config:
- sandbox: agent-specific sandbox configuration
- tools: agent-specific tool restrictions
This makes per-agent sandbox and tool settings accessible
to other parts of the codebase.