Commit Graph
8 Commits
Author SHA1 Message Date
mika kuns 2700c3d817 fix(usage): stop 429s with an activity-dependent poll cadence + manual refresh
The usage monitor polled the undocumented OAuth usage endpoint every 60s and
earned 429s. It now polls every 5 min while any task is Running and every
15 min while idle (usage_poll_interval_active_seconds / _idle_seconds, both
clamped to >= 60; the old single usage_poll_interval_seconds key is gone).

A 429 comes back as UsageRateLimitedException carrying Retry-After and adds
exponential backoff on top, capped at 30 min and never shorter than the normal
cadence; the strike count resets on the first success. The schedule arithmetic
is the pure static UsagePollSchedule.NextDelay.

Since the idle cadence is slow on purpose, WorkerHub.RefreshUsage drives
UsageMonitorService.RefreshNowAsync behind a Refresh now button in the Usage
Monitor modal: an out-of-band poll that pushes the loop's next-due time out so
no double poll follows, with a 10s cooldown so click-spam can't earn a 429.

Staleness now measures against the slower (idle) interval so an idle worker
isn't flagged stale just for not polling.
2026-08-05 16:40:34 +02:00
mika kuns 20d17c6887 feat(worker): add OAuth usage client + poller
Adds Usage/ with ClaudeOAuthUsageClient (reads the access token Claude
Code keeps fresh at ~/.claude/.credentials.json, calls the Anthropic
OAuth usage endpoint, defensively parses buckets/limits), UsageState
(threadsafe last-good-snapshot holder that never regresses on
failure), and UsageMonitorService (BackgroundService polling on the
new usage_poll_interval_seconds config, min 15s, one poll at startup,
warns at most once per distinct error).
2026-08-05 10:00:25 +02:00
mika kuns c412a84fdf refactor(interactive): remove streaming interactive stack (superseded by ConPTY)
The embedded ConPTY terminal replaced the in-app streaming interactive session, so
delete the dead stack: StreamingClaudeSession, InteractiveSessionService,
ProcessClaudeStreamTransport, IClaudeStreamTransport, ILiveSession, LiveSessionRegistry,
IdleSessionReaper (+ WorkerConfig.InteractiveIdleTimeoutMinutes), the WorkerHub
interactive methods + HubBroadcaster events, IWorkerClient interactive members, the
TaskMonitorViewModel composer + SessionTerminalView composer markup, and the old
'Run interactively' entry. AskUser/PendingQuestionRegistry, the autonomous path,
planning, ResumeTaskInTerminal, and all ConPTY code are kept. Localization pruned.
2026-07-23 16:47:16 +02:00
Mika Kuns 711374e858 fix(worker): reap idle interactive sessions so they don't pile up
Changelog / changelog (push) Successful in 2s
Release / release (push) Successful in 51s
Interactive/streaming sessions are persistent claude.exe processes that
wait on stdin and never exit on their own. The only teardown was an
explicit StopInteractiveSession from the UI — there is no client-disconnect
or shutdown sweep — so an abandoned chat (UI closed, navigated away,
crashed) kept its claude.exe (+ conhost) alive for the worker's whole
lifetime. Under a long-running autostart worker these accumulate to dozens
of orphaned child processes.

LiveSessionRegistry now tracks per-session activity (Touch on every output
line and user action) and exposes ReapIdleAsync, which stops sessions idle
past a timeout while skipping any with a turn in flight. IdleSessionReaper
(BackgroundService) sweeps every 5 min; idle timeout defaults to 30 min,
configurable via interactive_idle_timeout_minutes (0 disables).
2026-06-26 16:11:53 +02:00
mika kunsandClaude Opus 4.8 17c7ff517a feat(worker,ui): Online Inbox config + auth hub plumbing (Phase 2)
Hub: GetOnlineInboxState / SetOnlineInboxConfig / SetOnlineInboxAuth /
ClearOnlineInboxAuth. WorkerConfig.SaveOnlineInbox persists only the
online_inbox section. OnlineTokenStore + config registered always so hub
methods work when sync is disabled. IWorkerClient surface + all test fakes
synced. RedirectUri config (default http://localhost:8765/callback).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-10 10:49:49 +02:00
mika kunsandClaude Opus 4.8 1ac9ced0bd feat(worker): Online Inbox sync engine (Phase 1)
Optional, opt-in (online_inbox.enabled, default false → zero network).
Worker-side reconcile loop: pull web-created tasks down as Idle, push the
list catalog and the Idle backlog mirror up. Auth behind IOnlineAuthProvider
(StaticTokenAuthProvider default; ZitadelAuthProvider stubbed for Phase 2).
DPAPI refresh-token store. 35 tests, no real network/Zitadel/Claude.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-10 09:55:20 +02:00
mika kunsandClaude Opus 4.7 45320427e8 feat(worker): add external MCP endpoint with API-key auth
A second WebApplication runs the external MCP server on its own port (default 47822) so it can expose a different tool set under different auth than the internal /mcp endpoint. Shared singletons (config, broadcaster, queue, db factory) are injected by instance so both apps share runtime state. ExternalMcpAuthMiddleware enforces an optional X-ClaudeDo-Key header; loopback-only trust when no key is configured.

Tools: ListTaskLists, ListTasks, GetTask, AddTask, UpdateTaskStatus, RunTaskNow, CancelTask.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-25 09:36:46 +02:00
Mika KunsandClaude Opus 4.6 f81ef02273 feat(data,worker): add db schema init and signalr hub skeleton
Data layer: Paths helper with ~/%USERPROFILE% expansion, SqliteConnectionFactory
(WAL + foreign keys), SchemaInitializer that applies the embedded schema.sql, and
POCO entities for lists/tasks/tags/worktrees.

Worker: WorkerConfig loader (~/.todo-app/worker.config.json with defaults),
WorkerHub exposing Ping(), and Program.cs wiring Kestrel to 127.0.0.1:<port>,
SignalR at /hub, schema applied on startup.

Pins Microsoft.Data.Sqlite and Microsoft.Extensions.Hosting to 8.x for net8.0
compatibility.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-13 12:00:47 +02:00