Commit Graph

18 Commits

Author SHA1 Message Date
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
d51438e665 feat(telegram): several admins via ADMIN_USER_IDS, each impersonating independently
ADMIN_USER_IDS (Telegram:AdminUserIds) takes a comma separated list; the older
ADMIN_USER_ID / Telegram:AdminUserId still works, also takes a list and is merged.
Empty entries and duplicates are ignored, non-numeric entries fail validation.
Impersonation is now per admin: one admin per target, an impersonating admin
can't be impersonated, and every admin's chat menu lists /impersonate.
2026-10-15 14:02:59 +00:00
EugeneTes
7fef3ce94e feat(telegram): ElevenLabs text to speech for the voice tool
ElevenLabs speaks for the voice tool when ELEVENLABS_API_KEY and ELEVENLABS_VOICE_ID
are set (TTS_PROVIDER=elevenlabs|openai picks, the other is the fallback). Opus output
(opus_48000_64) goes to Telegram as is; voice names resolve through /v2/voices;
instructions become audio tags on eleven_v3 and are ignored on other models. The key
is redacted from tool output and never reaches agent processes.
2026-10-14 13:07:36 +00:00
EugeneTes
0cae6f600a feat(telegram): pass GOOGLE_CLIENT_SECRET to agent processes, still redacted
GOOGLE_CLIENT_SECRET is no longer denied by name in the core defaults (the
*_SECRET glob still removes it); the Telegram host allows it by default so
workspace skills (gmail, gdrive) can use the Google OAuth client. Its value
stays in SecretValues: redacted from tool output, and aliases with the same
value are still removed.
2026-10-12 15:10:49 +00:00
EugeneTes
dccdf3a8ed fix(core): skills live in <cwd>/.volcanic/skills, next to the rest of the workspace config 2026-10-10 14:16:20 +00:00
EugeneTes
c3095c69ca feat(core): per-workspace Agent Skills listed in the system prompt, /skills in Telegram
Skills live in <cwd>/.claude/skills/<name>/SKILL.md (frontmatter name + description).
SkillCatalog re-reads them on every run and the prompt lists name, description and
path; the model reads the full SKILL.md with the read tool when a task matches.
2026-10-10 14:13:42 +00:00
EugeneTes
891a644590 feat(mcp): remote MCP servers per chat with sealed keys and owner-only commands
Streamable HTTP/SSE servers from the workspace's .volcanic/mcp/servers.json.
Headers are sealed with AES-GCM; the chat and the visible fields are the
associated data, so only /mcp_add|remove|tools change servers. Tools
<server>__<tool> go live in the session. An unreachable server is skipped
and reported in the system prompt. Keys are redacted from tool results, and
Telegram deletes messages that carry one.
2026-10-09 21:11:01 +00:00
EugeneTes
87240238cc feat(telegram): voice tool sends spoken replies as Telegram voice notes
OpenAI gpt-4o-mini-tts (female voice nova by default; TTS_MODEL/TTS_VOICE) renders OGG/Opus,
sent with sendVoice in order with rendered output. Up to 4500 characters per call, split
into 1500-character parts at paragraph/sentence/word boundaries; all parts are synthesized
before any is sent, and API errors come back to the agent as text with the key hidden.
On whenever OPENAI_API_KEY is set.
2026-10-09 10:09:46 +00:00
EugeneTes
5e50d902af docs(a2a): A2A client guide, configuration and Telegram notes 2026-10-08 14:34:02 +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
EugeneTes
cabec7ad70 docs(telegram): groups and Jev topic triggers 2026-10-05 16:29:07 +00:00
EugeneTes
92a0061fdd feat(telegram): ADMIN_USER_ID may /impersonate another user
While on, the admin's updates are routed as the target user's (allow-list,
chat, workspace, session, settings, jobs) and the target chat's output goes
to the admin's chat. The target's own updates are dropped with a notice that
an admin is working with their account. In memory; /impersonate 0 stops.
2026-10-05 07:24:07 +00:00
EugeneTes
3a57b81d88 feat(docker): trust every git repository through GIT_CONFIG_* in compose 2026-10-02 09:21:24 +00:00
EugeneTes
28bbfbc759 feat(scheduler): store jobs per chat and import VolcanicSecretary job files
Each chat's jobs live in <workspace>/.volcanic/scheduler/jobs.json. On start the
scheduler loads every chat's file, moves the retired shared
<agentDir>/scheduler/jobs.json into them and renames it .migrated-<ts>.
A VolcanicSecretary jobs.json (bare array) in a chat's folder is converted
in place for that chat; the original is kept as .secretary-<ts>.

Also adds the VolcanicSecretary data migration plan.
2026-10-02 07:29:48 +00:00
EugeneTes
28c6f90d91 feat(docker): bind the data volumes to /media/disk1/containers/volcanic_secretary_core
The entrypoint chowns the three mount roots before dropping to app, since
Docker creates missing bind directories as root.
2026-09-29 09:40:28 +00:00
EugeneTes
c3a0cf234c feat(google-calendar): store each chat's token in its workspace
Tokens now live in <cwd>/.volcanic/google-calendar/token.json, as in the
VolcanicSecretary reference, instead of <agentDir>/google-calendar/<chat
key>/. GoogleCalendarOptions.TokenDirectory, when set, keeps the old
per-chat layout under that root. Spec, docs and CLAUDE.md updated.
2026-09-28 20:42:58 +02:00
EugeneTes
7bb41f0b5b fix(docker): address review findings
Entrypoint drops the capability bounding set and sets no_new_privs. Security docs
and spec no longer claim the agent can't reach the secrets; docker exec fallbacks
use a clean environment. PLAYWRIGHT_ENABLED drops the nested compose default.
Tests pin the Dockerfile's Playwright install step and the compose model fallback.
2026-09-27 12:34:58 +02:00
EugeneTes
f0c511f953 docs(docker): Docker and Coolify deployment guide
Image contents, build arguments, the environment table with what the agent's processes can't see, volumes, Coolify steps, first Claude login, updating (the npm layer is cached: build without cache or pin CLAUDE_CODE_VERSION), extensions, troubleshooting and security.
2026-09-27 12:15:45 +02:00