10 KiB
CURRENT.md — session state
Last updated: 2026-09-13
This file tracks the work state. Read it first. Update it before you stop.
Current focus (broad)
The text layer is done. The web UI follows the Nocturne design handoff. Voice actions are in
progress: join/leave/move work; auto-leave and stay @user are next. Live verification and a full
QR approval are pending. The LLM attachment and MCP event delivery are parked.
In progress
- Voice actions are started:
voice.join(muted),voice.leave, andvoice.moveare implemented in the core, wired through the daemon, Web UI, and MCP, and mock-verified. The internalselectVoiceChannelandsetSelfMutelookups were probed live on the real client. - Auto-leave and
stay @userare the next voice step. - Voice audio is implemented: daemon-managed virtual devices (
veskslop_tts,veskslop_mic,veskslop_capture), TTS providers (local command + HTTP API), queued playback throughffplay, ducking onVOICE_SPEAKING, and WAV capture. The daemon startspulseaudiowhenpactlcannot reach a server and reports install hints. Verified live on 2026-09-13 after installingpulseaudio/ffmpeg: engine ok, devices created, PCM streamed. - The Web UI serves self-signed HTTPS (
openssl, stored under the state dir) so browser media APIs have a secure context.WEBUI_TLS=0disables it. - Capture and transcript are implemented: ffmpeg reads the client output, a VAD cuts it into
utterances, each becomes a WAV plus a transcript entry with the dominant speaker, and a
pluggable STT hook (local command or HTTP API) fills the text. Live events feed the console
Transcript tab;
get_transcriptand/api/transcriptread the store.VESKSLOP_CAPTURE_AUTO=1records calls automatically. Verified end to end with real PulseAudio on 2026-09-13. - STT uses Vosk (CPU, light):
poc/scripts/stt-vosk.pyplus a small model inpoc/models/(auto-detected). Verified with a TTS→capture→Vosk round trip. Other providers remain available viaVESKSLOP_STT_CMD/_API_URL. - TTS defaults to
espeak-ngwhen installed; engine and voice live in Settings → Client → Speech (daemon preferences, so all browsers share them). - Preferences moved to
<state dir>/preferences.jsonand no longer depend on the core, so guild visibility saves even while the client is down. API responses sendCache-Control: no-store. - Browser audio has an Enable browser audio button that requests the microphone permission, which browsers require before listing output devices.
- Browser microphone puppeting (talking through the bot) is next; it needs a mix sink, a
pacatinput, and echo handling. - The web UI follows the Nocturne design handoff (
poc/WebUIMockup.zip). The 7a shell is implemented and rendered headless for review: header, call strip, three-column body, composer, and the agent console. - Takeover is a client-side read-only gate. Off, the composer is locked. Manual sends are logged.
- Core process control is implemented and verified live: the daemon starts the client under auto-Xvfb, the bridge connects, and stop exits cleanly.
- Web QR login is implemented. The session reached
pendingagainst the real gateway; a full phone approval is pending.
Done
-
Validated core bridge: protocol, actions, validation, structured errors, hard outbound rate limit.
-
Auth persistence: pinned
DATA_DIR, token file, preload seeding,VESKSLOP_HEADLESS. -
Daemon on the core-bridge transport. CDP stays as a development fallback.
-
Trusted-only triggers: DMs and direct mentions. Trust tiers: user, trusted, admin.
-
Context: 15 messages or 4000 characters, time stamps, file names only, incremental fetch, tmp cache with a size limit, fetch cooldown.
-
Continuation window: a rushed follow-up joins the request context.
-
Response policy: origin channel or DM. Sensitive commands default to DM.
-
Persistent action log: triggers, commands, replies, errors, rotation, and secret redaction.
-
pollis paused (POLL_ENABLED = false). The parser and its tests stay. -
Human send pacing: first send of a burst waits 30-200 ms, later sends 500-2800 ms, and the burst resets after a random 5-20 s of quiet. Reads take 100-300 ms and do not reset the burst.
-
user.search: cache and guild-member lookup.voice.getsearches all guilds without aguildId. -
voice.overview: occupied voice channels and members for a guild. -
VOICE_STATE_UPDATEevents: normalized and pushed. Mock-verified. -
Voice actions:
voice.join(muted),voice.leave, andvoice.movein the core, with daemon routes (/api/voice/*), MCP tools, and Web UI wiring. Voice actions are paced 250-750 ms and written to the action log. The internal lookups were probed on the live client. -
Web UI voice rail: every voice channel is clickable. Clicking joins (muted); clicking the active channel leaves. Verified with the stateful mock.
-
Web UI startup: a Start server button appears left of Takeover while the bridge is down and hides when it connects. State reloads retry while the client boots, so guilds appear without a manual refresh. Core requests now time out after
VESKSLOP_REQUEST_TIMEOUT_MSinstead of hanging forever on a missing reply. -
Settings: "Visible guilds" stays top level; Audio sits under a collapsible "Client" group; Core process, Account login, and Action log sit under a collapsible "Server" group.
-
Web UI timestamps use the browser timezone by default; Settings → Client → Display can override it with any IANA zone. The choice is per browser (
localStorage). -
Web UI preferences: visible guilds persist server-side in the daemon state file (
/api/preferences), so every browser shares them. The Settings panel has an explicit Save button; selections filter the UI live and persist only on Save. -
DM list: recipients resolve from IDs through the user store, so names and avatars load.
-
Guild menu: fixed the light default button background.
-
Web UI: Nocturne design tokens in
poc/public/nocturne.css, the 7a debug shell, live guild and channel rail, messages, DMs, voice membership, agent console with a live event tab, and a Settings slide-over for core process, login, visible guilds, and the action log. Roadmap surfaces show as placeholders. -
Web UI data: opening a chat fetches the latest 50 messages into the client cache; attachments hotlink Discord CDN URLs and are never stored; avatars and guild icons load from the CDN with a monogram fallback; the page reloads itself when the bridge connects.
-
Web UI drafts: composer and TTS text persist per channel in
localStorageand survive re-renders, reconnects, and page reloads. -
Visible guilds: the Settings panel filters the guild switcher and picker.
-
Takeover: client-side read-only switch with
localStoragepersistence; manual sends are written to the action log withtype: "manual". -
dm.list: cached DM and group DM channels, exposed over MCP aslist_dms. -
Core process control: the daemon starts, stops, and restarts the client, reconnects the bridge after a restart, auto-starts Xvfb when
DISPLAYis missing, and stops what it started on exit. Override withVESKSLOP_CORE_CMD/ARGS; disable Xvfb withVESKSLOP_XVFB=0. -
Web QR login: the Settings panel runs the remote-auth session and renders the QR. The token file is written on approval and a running managed core restarts with the new token.
-
Unit tests cover the pacing policy.
pnpm lintandpnpm testTypespass at the root. -
Web UI navigation: Guild/DM scope tabs, a DM rail with unread badges (purple/orange, grey while Takeover is off), last-message times, favourite stars, and a People list of users seen in voice. Favourited users get presence and call tracking, grouped by call in In voice. Speaking shows level bars and bold names (2c marks for mute/deaf/video/share). The body dims while the bridge is down; the Start button becomes Refresh when the daemon is unreachable.
-
TTS settings are split into language and voice, grouped by base language with the requested languages pinned on top.
Next (in order)
- Voice auto-leave (
voiceLeaveDelaySeconds) and thestay @usercommand. - Live verification:
voice.join/voice.leaveend to end,user.search,voice.overview,VOICE_STATE_UPDATE, and a full web QR login approval on the real client. - Notification parsing: edits, deletes, reactions, and message references.
- Reply-to-puppet counts as a trigger.
- Per-user rate limit and command cooldowns.
- Collector account: read-only modules for voice membership fallback.
Open discussions (need the user)
- Web UI auth. Accepted: no auth, LAN or Tailscale only. Revisit before any wider exposure.
- MCP event delivery. Parked with the LLM attachment. Options stay in
TODO.md. - Untrusted logging. Untrusted interactions are ignored at this time. Confirm whether to log untrusted DMs and mentions again.
- Privacy pass. Only token-shaped and
mfa.strings are redacted, and only in the persistent action log. A fuller policy (retention, cache clearing, message redaction) is deferred. - Live checks.
reaction.add,user.search,voice.overview, and the voice state event normalization are mock-verified only. The QR login session reachedpendingandcancelagainst the real gateway; the approval path needs the phone. Confirm on the first real-client run.
Blocked / needs input
- The original repo
zib/Veskslophas a broken server-side git setup. Fetches and clones fail withbad pack headerbecause a script (/home/git/.sys_health_s3) runs on the Veskslop read path. The admin must fix it. Usezib/Veskslop-t(remoteveskslop-t) until then. mainon the original server is68fc8bb(zib, "Upload files to docs/images"). It diverged from the localmain(24447f5). Reconcile after the server is fixed.
Where to look
- Backlog:
TODO.md - Design documents:
docs/INDEX.md - Design handoff:
poc/WebUIMockup.zip(screen 7a is implemented) - Agent rules:
AGENTS.md - Daemon code:
poc/src/ - Web UI code:
poc/src/webui.ts,poc/public/ - Core bridge code:
src/shared/puppetProtocol.ts,src/renderer/puppet/,src/main/puppetBridge.ts