When an OpenAI-compatible API returns a non-JSON response (e.g. plain
text "unsupported model: xxx" with HTTP 200), the OpenAI SDK raises a
JSONDecodeError whose message is the unhelpful "Expecting value: line 1
column 1 (char 0)". Extract the original response body from
JSONDecodeError.doc (or APIError.response.text) so users see the actual
error message from the API.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Mask sensitive fields (api_key/token/secret/password) in all display
surfaces, showing only the last 4 characters
- Replace all emoji with pure ASCII labels for consistent cross-platform
terminal rendering
- Extract _print_summary_panel helper, eliminating 5x duplicate table
construction in _show_summary
- Replace 3 one-line wrapper functions with declarative _SETTINGS_SECTIONS
dispatch tables and _MENU_DISPATCH in run_onboard
- Extract _handle_model_field / _handle_context_window_field into a
_FIELD_HANDLERS registry, shrinking _configure_pydantic_model
- Return FieldTypeInfo NamedTuple from _get_field_type_info for clarity
- Replace global mutable _PROVIDER_INFO / _CHANNEL_INFO with @lru_cache
- Use vars() instead of dir() in _get_channel_info for reliable config
class discovery
- Defer litellm import in model_info.py so non-wizard CLI paths stay fast
- Clarify README Quick Start wording (Add -> Configure)
Cherry-pick from d6acf1a with manual merge resolution.
Keep onboarding edits in draft state until users choose Done or Save and
Exit, so backing out or discarding the wizard no longer persists partial
changes.
Co-Authored-By: Jason Zhao <144443939+JasonZhaoWW@users.noreply.github.com>
--workspace and --config now work as initial defaults in interactive mode:
- The wizard starts with these values pre-filled
- Users can view and modify them in the wizard
- Final saved config reflects user's choices
This makes the CLI args more useful for interactive sessions while
still allowing full customization through the wizard.
Tests for non-interactive onboard mode now explicitly use --no-interactive
flag since the default changed to interactive mode.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add `_SELECT_FIELD_HINTS` for select fields with predefined choices
(e.g., reasoning_effort: low/medium/high with hint text)
- Add `_select_with_back()` using prompt_toolkit for custom key bindings
- Support Escape and Left arrow keys to go back in menus
- Apply to field config, provider selection, and channel selection menus
- Add model_info.py module with litellm-based model lookup
- Provide autocomplete suggestions for model names
- Auto-fill context_window_tokens when model changes (only at default)
- Add "Get recommended value" option for manual context lookup
- Dynamically load provider keywords from registry (no hardcoding)
Resolves#2018
Adjust the spawn tool description to keep the workspace-organizing hint while
avoiding language that sounds like the system automatically assigns a dedicated
working directory for subagents.
Made-with: Cursor
MCP servers (e.g. Zapier) return JSON Schema union types like
`"type": ["string", "null"]` for nullable parameters. The existing
`validate_params()` and `cast_params()` methods expected only simple
strings as `type`, causing `TypeError: unhashable type: 'list'` on
every MCP tool call with nullable parameters.
Add `_resolve_type()` helper that extracts the first non-null type
from union types, and use it in `_cast_value()` and `_validate()`.
Also handle `None` values correctly when the schema declares a
nullable type.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The root cause of "Pool timeout" errors is that long-polling (getUpdates)
and outbound API calls (send_message, send_photo, etc.) shared the same
HTTPXRequest pool — polling holds connections indefinitely, starving sends
under concurrent load (e.g. cron jobs + user chat).
- Split into two independent pools: API calls (default 32) and polling (4)
- Expose connection_pool_size / pool_timeout in TelegramConfig for tuning
- Add _call_with_retry() with exponential backoff (3 attempts) on TimedOut
- Apply retry to _send_text and remote media URL sends
Tests the helpers directly without needing CronService, covering all
schedule kinds, edge cases (missing fields, unknown status), and
combined state output.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Addresses review feedback: moves schedule formatting and state
formatting into dedicated static methods, removes duplicate
in-loop imports, and simplifies _list_jobs() to a clean loop.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Covers all three schedule kinds (cron/every/at), human-readable interval
formatting, run state display (last run, status, errors, next run),
and disabled job filtering.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
_list_jobs() only displayed job name, id, and schedule kind (e.g. "cron"),
omitting the actual timing and run state. The agent couldn't answer
"when does this run?" or "did it run?" even though CronSchedule and
CronJobState had all the data.
Now surfaces:
- Cron expression + timezone for cron jobs
- Human-readable interval for every jobs
- ISO timestamp for one-shot at jobs
- Enabled/disabled status
- Last run time + status (ok/error/skipped) + error message
- Next scheduled run time
Fixes#1496
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Fix double bold markers (****) when heading text already contains **
- Strip markdown formatting (**bold**, *italic*, ~~strike~~) from table cells
since Feishu table elements do not support markdown rendering
Fixes rendering issues where:
1. Headings like '**text**' were rendered as '****text****'
2. Table cells with '**bold**' showed raw markdown instead of plain text
Remove the in-progress reaction (reactEmoji) and optionally add a
done reaction (doneEmoji) when the final response is sent, so users
get visual feedback that processing has finished.
Signed-off-by: Sihyeon Jang <sihyeon.jang@navercorp.com>