9 Commits

Author SHA1 Message Date
EugeneTes
cb877f697a 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.
2026-10-16 14:46:59 +00:00
EugeneTes
f42b00cb1c fix(a2a-client): watches no longer hang on a silently dead task stream
Hour-long remote tasks were never delivered: a subscribe watch held one SSE stream for up to a day, the remote
sent nothing while its agent worked without text, and once the quiet connection died on the way (no FIN/RST) the
watch waited on it with no error and no log line.

- A subscription lasts at most 5 minutes (SubscriptionSlice), then GetTask and a new subscription: a pause, not a
  failure. A slice ended mid-read counts as ours even when it surfaces as an I/O error.
- The shared handler connects with TCP keepalive (60 s, every 15 s, 4 probes) and HTTP/2 pings.
- Log lines when a watch starts or is restored, when a slice ends on a running task, when a result is delivered or
  kept; the Telegram host's console log carries a UTC timestamp.
- action=status on a settled task ends its watch, so the result isn't delivered a second time.
- A "context busy" refusal of send says nothing was sent, names the watched task in that context and that its
  result will arrive by itself; refusals never touch a watch.
2026-10-16 13:48:32 +00:00
EugeneTes
6893ee8197 fix(a2a-client): read 0.3-shaped file parts and report parts the SDK can't read
The 1.0 SDK ignores unknown part fields, so a file part shaped {kind:file, file:{bytes|uri,
name, mimeType}} arrived as an empty part and vanished. A2AWireCompat rewrites such parts
to {raw|url, filename, mediaType} in JSON and SSE responses before the SDK reads them, and
marks any part it still can't read so the result lists it with its field names.
2026-10-12 16:26:11 +00:00
EugeneTes
a92623b89b fix(a2a-client): save every file the remote agent returns, per task, with size and type
File parts were only taken from artifacts as inline bytes up to 10 MB; parts in the
status message or the history were dropped silently, URL parts were never downloaded,
and a plain message reply lost its files. Files now go to inbox/a2a/<taskId>/ from
artifacts, status message and recent agent messages (deduplicated), URLs are streamed
to disk (agent key only on the agent's origin, else https without it), the cap is the
new MaxReceivedFileBytes (200 MB), and results list path, bytes and media type or why
a file was not saved. Re-saving a task overwrites, so action=status refetches files.
2026-10-12 16:16:14 +00:00
EugeneTes
923a6e04ac docs(a2a): client exposures, URLs without queries, README/architecture 2026-10-08 14:42:18 +00:00
EugeneTes
5e50d902af docs(a2a): A2A client guide, configuration and Telegram notes 2026-10-08 14:34:02 +00:00
EugeneTes
3360c320e7 docs(a2a): security reach, ports and limits 2026-10-07 14:32:33 +00:00
EugeneTes
0d1ddcc4df fix(a2a): unambiguous session scopes and validated context ids 2026-10-07 14:29:50 +00:00
EugeneTes
d542fcfe42 docs(a2a): A2A server guide, architecture, Telegram and Docker notes
Add docs/a2a.md (concepts, file formats, endpoints, sessions, task
lifecycle, configuration, security notes, curl examples) describing
what src/Volcanic.AgenticCore.A2A.Server actually does. Add an A2A
project paragraph to architecture.md, an "A2A" section to
telegram-bot.md (/a2a, notify_owner, isolated sessions, port 8080),
A2A_ENABLED/A2A_PUBLIC_URL and the aspnet image to docker.md, and
project-map/test-command updates to CLAUDE.md.

Mark the A2A server design spec implemented and record the deviations
found while building it (A2AHostOptions, synchronous
IA2ACallerDirectory.Find, generic WorkspaceCallerDirectory, per-status
push payload, split file-part error handling, the outbound guarded
handler, the per-caller server/router architecture, the restart grace
period, the owner= log field, the aspnet image, and the actual push
retry schedule). Note the aspnet image in the docker-deployment spec
too, without rewriting its historical decisions.
2026-10-07 14:20:19 +00:00