ductor v0.20.0
ductor v0.20.0
A community release through and through: nine contributor PRs merged, three reported bugs squashed, and two security issues found and fixed during review. Grok Build joins as the fifth provider CLI, topics can now live in their own project directories, and cron got serious reliability upgrades. Thank you all. 💜
TL;DR
- Grok Build provider — xAI's
grokCLI is ductor's fifth provider: model discovery,/modelwizard with reasoning effort, all 8 languages. - Per-topic project roots — map a forum topic to a project directory; the CLI runs in your project while bot memory stays in the workspace.
- Inter-agent sessions, scoped — sessions created by agents are isolated per chat & topic, capped at 32 with oldest-idle eviction, and no longer consume your session quota.
- Cron hardened — failed result deliveries are retried automatically, and opt-in preflight hooks can gate job execution (fail-open, never blocks on hook errors).
- Quieter startup — model-cache observers only start for CLIs that are actually installed and authenticated.
- Secrets stay out of logs — command logs redact environment values, and persisted-config logging writes key names only (an API token could previously end up in the log).
- Big memories work again — a
MAINMEMORY.mdbeyond ~96 KiB no longer kills new Claude sessions with E2BIG; oversized system prompts go through a temp file. - The bot survives flaky networks at startup — transient Telegram errors during boot are retried with capped backoff instead of terminating the process.
Grok Build provider (#180)
@s94084sammy added support for xAI's grok CLI as a full provider: auth detection, streaming, session resume, and a model-cache observer feeding the /model wizard. Post-merge we hardened the stream parser (dispatch-table refactor), wired reasoning-effort validation, and added the selector texts to all 8 locales.
Per-topic project roots (#178)
@minakovd built what #127 (@doongzzi) and #131 (@Aut0-Mat) asked for: name a forum topic after a key in project_roots and every CLI call in that topic runs with the mapped directory as its working directory — code questions land in the right repo without any per-message ceremony. A follow-up pins the bot's memory system to its absolute workspace path so it doesn't get lost inside project checkouts, and the matched root is logged at startup for transparency.
Inter-agent sessions, scoped (#174)
@ryuhaneul isolated agent-created named sessions by sender chat and topic, so two chats can no longer collide on the same session name. Follow-ups cap these sessions at 32 per chat (oldest-idle is evicted, running sessions are never touched) and exclude them from the user-facing session list and quota.
Cron: delivery retry & preflight hooks (#172, #173)
Both by @zhark0vv:
- Delivery retry (#172) — if Telegram is down when a cron result lands, ductor now resends the preserved result automatically instead of just marking it failed. Hardened against racing executions with a compare-and-clear so a retry can never clobber a newer result.
- Preflight hooks (#173) — an optional command that runs before each cron job and can skip the run (non-zero exit). Fail-open by design: a hook that crashes, hangs, or can't spawn never blocks the job. The hook's process group is killed safely on timeout.
Security & logging
- Command-log redaction (#175, @ryuhaneul) — environment assignments in logged CLI commands are redacted (nonstandard forms included);
DUCTOR_TASK_IDstays visible via an explicit allowlist so task logs remain debuggable. - Config values never logged —
update_config_fileused to log full key/value pairs, which could put an API token into the log; it now logs key names only. Found during release review. - Allowlist identity fix (#177, @minakovd) —
AuthMiddlewarekept a stale copy of the user allowlist, so runtime allowlist updates were silently ignored; it now shares the live set.
Reliability
- E2BIG on big memories (#182, reported by @F1n1k) — once
MAINMEMORY.mdgrew past the kernel's argv limit, every new Claude session died with "An internal error occurred". Prompts over 96 KiB are now passed via--append-system-prompt-filewith a temp file (Docker path mapping included, cleanup guaranteed). - Startup retry (#181, reported by @Tony-ooo) — a transient Telegram/network error while the main agent booted terminated the whole bot. Transient failures now retry with capped backoff (5–60 s) indefinitely; genuinely fatal errors still stop the process.
- Wake hooks reject overrides (#176, reported by @askhatsoltanov1984-lang) —
webhook_add/webhook_editinwakemode silently ignored--provider/--model/--reasoning-effort/--cli-parameters. They now fail with a clear error pointing tocron_taskmode; legacy hooks with stored overrides log a warning at execution time. - Observer gating (#171, @zhark0vv) — model-cache observers (Gemini, Antigravity, Codex, Grok) start only for providers that passed auth detection, ending startup noise from CLIs that aren't installed.
- Topic model/effort persists (#179, @ryuhaneul) — changing model or effort in a topic without a live session is no longer discarded.
Merged PRs
- #180 by @s94084sammy — Grok Build provider
- #178 by @minakovd — per-topic project roots (closes #127, #131)
- #177 by @minakovd — allowlist identity fix
- #174 by @ryuhaneul — inter-agent session scoping
- #175 by @ryuhaneul — command-log redaction
- #179 by @ryuhaneul — topic model/effort persistence
- #171 by @zhark0vv — auth-gated model observers
- #172 by @zhark0vv — cron delivery retry
- #173 by @zhark0vv — cron preflight hooks
Full diff: 4122 tests (up from 4003), zero warnings under ruff's ALL profile and mypy strict.