fix(a2a-client): poll watches crashed on null delays; lost tasks and crashed watches end with a notice
- A2AWatchRegistry.Shared was initialised before DefaultPollDelays (static fields run in source order), so the bot's registry had null poll delays and every poll watch crashed on its first wait, then sat in the registry doing nothing until a restart. The delays now come first; a test reads them through Shared. - TaskNotFound from the remote ends the watch at once with a "(lost)" notice instead of retrying for a day. - A crashed watch loop restarts by polling after a pause; the third crash in a row ends it with a "(stopped)" notice.
This commit is contained in:
@@ -346,7 +346,10 @@ Each check reads `agents.json` again: an agent removed from it ends the watch wi
|
||||
file is treated as a passing failure (the user may be editing it) and the watch keeps going. A watch keeps its
|
||||
connection (card and client) between checks and reconnects after a failure or when the agent's entry changes. After
|
||||
`WatchTimeout` (1 day by default) from its start the watch gives up with a `(no result)` notice suggesting
|
||||
`action=status`. The shared handler turns on TCP keepalive (probes after 60 s of silence, every 15 s, 4 tries) and
|
||||
`action=status`. A remote that answers `TaskNotFound` has forgotten the task (typically it restarted): the watch ends
|
||||
at once with a `(lost)` notice suggesting to send the request again. A crash of a watch's loop (a bug, not a remote
|
||||
failure) restarts it by polling after 1 s, 5 s, 15 s; the third crash in a row ends it with a `(stopped)` notice
|
||||
suggesting `action=status`, so no watch stays listed while doing nothing. The shared handler turns on TCP keepalive (probes after 60 s of silence, every 15 s, 4 tries) and
|
||||
HTTP/2 pings, so a dead connection fails instead of hanging. The log has one line when a watch starts or is restored
|
||||
(task, agent, chat, source, watch id), when a stream slice ends on a running task (`subscribing again`), when a
|
||||
result is delivered or kept, and for every failed check. On a settled task it saves files like `send` does and, for push watches, deletes the push config
|
||||
|
||||
@@ -136,6 +136,8 @@ Watch record, persisted in `<workspace>/.volcanic/a2a/pending.json`:
|
||||
token, body)`, which checks the token (constant-time) and returns false for unknown watches or bad tokens (→ 404).
|
||||
- **End**: on a terminal state or `input-required`/`auth-required`, the registry builds a result text and hands it to
|
||||
`IA2AResultDelivery`, then removes the watch (and deletes the push config remotely, best effort).
|
||||
- **Lost / crashed**: `TaskNotFound` from the remote ends the watch at once with a `(lost)` notice. A crashed watch loop
|
||||
restarts by polling; after 3 crashes in a row it ends with a `(stopped)` notice.
|
||||
- **Timeout**: after `WatchTimeout`, deliver "travel-bot gave no result for task <id> within 24h; you can check it with
|
||||
action=status" and remove the watch.
|
||||
- **Restore**: at startup the host calls `A2AWatchRegistry.Shared.RestoreAsync(workspaces)`, which reads every
|
||||
|
||||
Reference in New Issue
Block a user