Routines created via Telegram (or any WASM channel) were invisible in the
web UI because the routines list endpoint filtered by GATEWAY_USER_ID,
which didn't match the Telegram user's ID stored on the routine.
Add list_all_routines() to the RoutineStore trait (both libSQL and
PostgreSQL backends) and use it in the web dashboard handlers so all
routines are visible regardless of which channel created them.
Co-authored-by: Claude Opus 4.6 (1M context) <[email protected]>
* feat: implement FullJob routine mode with scheduler dispatch
FullJob routines previously fell back to lightweight mode (single LLM call,
no tools) with a warning. This wires them to the existing Scheduler/Worker
infrastructure so they dispatch real jobs with full tool access.
Fire-and-forget model: the routine creates a job via ContextManager, schedules
it, links the routine_run to the job_id, and completes immediately. The job
runs independently with full tool access.
- Add RoutineError::JobDispatchFailed variant
- Add RoutineStore::link_routine_run_to_job (PostgreSQL + libSQL)
- Add execute_full_job() in routine_engine with context_manager/scheduler
- Wire context_manager + scheduler into RoutineEngine from agent_loop
- Fix pre-existing clippy warnings in tests/html_to_markdown.rs
Co-Authored-By: Claude Opus 4.6 <[email protected]>
* fix: persist job to DB before scheduling in execute_full_job
The worker emits job_actions and llm_calls rows that reference agent_jobs
via foreign key. Without persisting the job first, those inserts can fail.
Match the pattern from commands.rs: fetch JobContext, save_job(), then schedule.
Co-Authored-By: Claude Opus 4.6 <[email protected]>
* refactor: consolidate job dispatch into Scheduler::dispatch_job and wire max_iterations
Move the create + persist + schedule sequence into a single
Scheduler::dispatch_job() method so callers (commands.rs, routine_engine.rs)
don't duplicate the logic. FullJob routines now pass max_iterations via job
metadata, and the worker reads it (defaulting to 50 if unset).
Also removes the context_manager field from RoutineEngine since dispatch_job
handles everything internally.
Co-Authored-By: Claude Opus 4.6 <[email protected]>
* fix: clamp max_iterations to 500 and log category update failures
Address PR review feedback:
- worker.rs: clamp max_iterations from metadata to MAX_WORKER_ITERATIONS (500)
to prevent unbounded LLM token usage from malicious/buggy configs
- commands.rs: log warning on category update failure instead of silently
discarding the error
Co-Authored-By: Claude Opus 4.6 <[email protected]>
* feat: persist worker events to DB and fix activity tab rendering
In-process Worker (used by Scheduler::dispatch_job) now persists events
via save_job_event at key execution points: plan creation, LLM
responses, tool_use, tool_result, and job completion/failure/stuck.
Event data shapes match the container worker format so the gateway
activity tab renders them correctly.
Frontend: tool_result errors now show a red X icon with danger styling
instead of a silent empty output. The result event falls back to the
error field when message is absent.
Co-Authored-By: Claude Opus 4.6 <[email protected]>
---------
Co-authored-by: Claude Opus 4.6 <[email protected]>
* refactor: split large files and consolidate test stubs for contributor velocity
- Extract 7 Database sub-traits (ConversationStore, JobStore, SandboxStore,
RoutineStore, ToolFailureStore, SettingsStore, WorkspaceStore) with Database
as a supertrait combining them all
- Split libsql_backend.rs (2769 lines) into src/db/libsql/ directory with
one file per sub-trait implementation
- Split config.rs (1753 lines) into src/config/ directory with 16 domain files
- Consolidate 3 duplicate test LLM stubs into shared StubLlm in src/testing.rs
- Split server.rs handlers into src/channels/web/handlers/ directory
- Extract main.rs init phases into AppBuilder (src/app.rs)
- Add developer setup script (scripts/dev-setup.sh)
Co-Authored-By: Claude Opus 4.6 <[email protected]>
* refactor: move heartbeat test from examples/ to tests/
Convert standalone example binary into a proper #[ignore] integration
test, matching the convention of the other integration tests.
Co-Authored-By: Claude Opus 4.6 <[email protected]>
* style: fix rustfmt formatting for CI
Co-Authored-By: Claude Opus 4.6 <[email protected]>
* fix: address PR review comments from Copilot
- tunnel.rs: replace .ok().flatten() with ? to propagate env var errors
- secrets.rs: remove misleading "process-wide cache" comment
- database.rs: use uppercase "DATABASE_URL" in error key
- testing.rs: gate harness tests with #[cfg(feature = "libsql")]
Co-Authored-By: Claude Opus 4.6 <[email protected]>
---------
Co-authored-by: Illia Polosukhin <[email protected]>
Co-authored-by: Claude Opus 4.6 <[email protected]>