Commit Graph
26 Commits
Author SHA1 Message Date
pierre df4d00ee29 harness: throttle bubble edits — cap 12/bubble, min 8s interval
Element X chokes loading rooms with long m.replace edit chains (the tool
bubble got an edit per tool call — dozens per turn). Throttle pushes; the
final state still flushes via the reply/closing path.
2026-09-24 18:09:49 +03:00
pierreandLetta Code 890970de81 harness: fix double free of streamed chunk text (chunk payloads are borrowed per letta.zig contract)
onProgressEvent freed .chunk text that handleLine also frees via defer —
double free corrupted the heap mid-turn; DebugAllocator caught it and
the reply tail was silently lost (delivered messages missing their final
characters while the CLI transcript held the full text).

👾 Generated with [Letta Code](https://letta.com)

Co-Authored-By: Letta Code <noreply@letta.com>
2026-09-21 16:10:20 +03:00
pierreandLetta Code 27327e94b0 letta: fix truncated replies — process final unterminated line at EOF
The stream reader only handled lines terminated by newline. The letta
CLI final JSON line arrives without trailing newline at EOF, so the last
assistant message (or result line) sat in the line buffer and was
silently dropped — replies ended mid-sentence. Also: read errors no
longer silently end collection (logged), and stream completeness is
tracked via the result line with a warning when absent.

👾 Generated with [Letta Code](https://letta.com)

Co-Authored-By: Letta Code <noreply@letta.com>
2026-09-21 06:02:59 +03:00
pierreandLetta Code 81fcbabefc harness: markdown tool bubble (bold names, fenced outputs, --- separator) + streamed reply message; letta: structured tool_call/tool_return events, escaped-key arg extraction; matrix: editText with formatted_body
Fixes included: bubble body off-by-one, reply chunk duplication, use-after-free in escaped-key truncation, fence/header concatenation swallowing headers, Read file_path arg extraction.

👾 Generated with [Letta Code](https://letta.com)

Co-Authored-By: Letta Code <noreply@letta.com>
2026-09-20 15:26:12 +03:00
pierreandLetta Code 8d89e3baeb harness: live tool-call bubble during agent turns (one message, m.replace edits, capped at 10 lines/3.5k chars, final reply as fresh message)
👾 Generated with [Letta Code](https://letta.com)

Co-Authored-By: Letta Code <noreply@letta.com>
2026-09-20 14:20:13 +03:00
pierreandLetta Code 58a66700c6 harness: pin bridge conversation to local-conv-487 (CONVERSATION_ID constant, --agent omitted for pinned convs)
👾 Generated with [Letta Code](https://letta.com)

Co-Authored-By: Letta Code <noreply@letta.com>
2026-09-20 13:54:15 +03:00
pierre 65e2ee083e setTyping: failure diagnostics (journald log on error) — API confirmed working via curl (200); if Element shows no indicator during turns, it's display-side 2026-09-06 13:12:38 +03:00
pierre b958eaab4c typing: refresh every 2s 2026-09-05 11:43:30 +03:00
pierre bf40b50f52 harness: typing indicator during agent turns (keepalive refreshes 60s window, cleared on reply) 2026-09-05 03:15:58 +03:00
pierre 2f0890a61c gitignore build artifacts + local letta dir 2026-09-05 01:21:31 +03:00
pierre 861ac201cb untrack .matrix-env (contains bridge password) — never commit secrets 2026-09-05 01:11:54 +03:00
pierre cbe99e89d0 harness: attachments named by real m.filename, not the caption; mimetype-derived extension fallback 2026-09-05 01:11:29 +03:00
pierreandLetta Code e212e3e120 matrix: file transfer both ways — send-file one-shot (upload + m.image/m.file by ext), incoming attachments downloaded to /tmp/matrix-files and path forwarded to agent
👾 Generated with [Letta Code](https://letta.com)

Co-Authored-By: Letta Code <noreply@letta.com>
2026-09-03 23:51:09 +03:00
pierre dcf6d8df75 harness: proactive send mode + persistent backlog seen-state
- 'matrix_harness send "text"' — one-shot unprompted messaging to the
  pinned room (agent announcements/alerts)
- backlog no longer re-forwards read messages: last homeserver
  origin_server_ts persisted to /tmp/matrix-harness.state, advanced on
  every processed event; events at/below it are skipped
- 30-min staleness window retained as outer bound
2026-09-03 00:58:42 +03:00
pierre 9f1a839a22 matrix bridge: proper JSON sync parsing, backlog forwarding, message provenance
- sync(): std.json walk of rooms.join.*.timeline (old string-window scraper
  misattributed senders across events); Event gains ts
- startup backlog: peer messages from last 30min forwarded to agent as
  context (reply suppressed); failures logged, never fatal (systemd
  Restart=on-failure would otherwise re-forward every 3s)
- messages to agent prefixed [matrix HH:MMZ] with UTC event timestamp
- sendText: jsonEscape covers control chars (\u00XX), markdown -> HTML
  formatted_body (bold/italic/code/fences) for Element rendering
- no startup banner in room; harness now runs as systemd user service
  matrix-harness (unit + .matrix-env, untracked)
2026-09-02 08:57:43 +03:00
pierre 77f3150af4 matrix: widen sync event window backwards — sender precedes type marker 2026-09-02 02:22:38 +03:00
pierreandLetta Code a6d4e29589 matrix harness: persistent room (MATRIX_ROOM env) — no more DM-per-run
Reuses the fixed room when MATRIX_ROOM is set; only creates a fresh DM
when unset. All replies go to the pinned room.

👾 Generated with [Letta Code](https://letta.com)

Co-Authored-By: Letta Code <noreply@letta.com>
2026-09-02 02:17:27 +03:00
pierreandLetta Code da50dea0d1 Matrix bridge scaffold: test harness with texting E2E
- src/matrix.zig: minimal Matrix client (conduwuit @ matrix.chaosmith.systems)
  via curl subprocess transport (native TLS swap later): login, createRoom
  (trusted_private_chat, unencrypted — no olm), sendText, sync polling with
  window-scan event extraction reusing letta.jsonStr
- src/matrix_harness.zig: standalone entrypoint (independent of tray daemon):
  login -> DM with peer -> sync loop -> peer messages routed through letta
  CLI (chaos-prime) -> replies sent back to the room
- build.zig: second exe matrix_harness; use_llvm fix promoted into build.zig
  for both executables (native lld vs GCC16 .sframe relocations)
- calling/Element Call (livekit SFU already deployed on ass-host) layers on
  top of this harness next

👾 Generated with [Letta Code](https://letta.com)

Co-Authored-By: Letta Code <noreply@letta.com>
2026-09-02 02:09:42 +03:00
pierreandLetta Code 187bac9aa4 overlay: preserve explicit newlines in bubbles (raw \n to <br>)
Qt rich text collapses raw newlines to whitespace; convert before render.

👾 Generated with [Letta Code](https://letta.com)

Co-Authored-By: Letta Code <noreply@letta.com>
2026-09-01 23:20:31 +03:00
pierreandLetta Code 2fdc812a13 Agent + conversation pickers, prefs persistence
- tray submenus: Agent (from letta agents list, radio-style) and
  Conversation (from local backend storage, CLI has no listing surface)
- conversation entries show preview: summary or last-message text
- conversation menu refreshes on aboutToShow (KDE DBus menu syncs a
  step behind eager mutation)
- CLI rule honored: --agent only with --conversation default; named
  conversations imply the agent
- plain-text fallback parsing for non-stream-json output
- empty-reply debug: raw stream tail dump
- prefs: ~/.local/inferon/prefs.json, saved on pick, loaded at startup,
  HOME-resolved paths (std.c.getenv), owned buffers (no alias double-free)
- leak fixes: agent name fallback, quit-path drains for menu entries

👾 Generated with [Letta Code](https://letta.com)

Co-Authored-By: Letta Code <noreply@letta.com>
2026-09-01 23:15:58 +03:00
pierreandLetta Code bcd48a3443 Streaming voice pipeline: sentence-level TTS, zero temp files
- playback.zig: sentence queue + playback thread — agent reply chunks are
  split on sentence boundaries and each sentence is synthesized+played as it
  completes, so voice starts after the first sentence, not after the reply
- melo_server.py v2: WAV written to /dev/shm, raw s16le PCM + sample rate
  streamed over stdout (WAV n rate header + bytes), file deleted immediately;
  melo stdout chatter rerouted to stderr to keep the protocol clean
- melo.zig: speakRaw returns in-memory PCM; pw-play fed via stdin pipe
  (no on-disk TTS files at all)
- whisper: --language auto
- fix: double-close of pw-play stdin panicked Threaded Io in debug
- fix: quit-path frees for transcript cache, bubble lists, sentence queue,
  reply buffer (debug allocator leak panic)

👾 Generated with [Letta Code](https://letta.com)

Co-Authored-By: Letta Code <noreply@letta.com>
2026-09-01 20:48:16 +03:00
pierreandLetta Code 2b2235ff86 Streaming overlay: chat GUI for agent responses
- overlay.zig: frameless translucent panel (fixed bg + rounded corners,
  only bubbles scroll), drag handle, hover-to-full-opacity, top-right spawn
- chat layout: per-message QLabel bubbles (user purple / agent green /
  tool steps grey mono), transcript retained across turns, End-conversation
  resets
- agent reply streams into its own growing bubble (re-render per chunk)
- basic markdown in all messages: **bold**, *italic*, `code`, HTML-escaped
- tool steps truncated to 90 chars, click to expand/collapse
- polite autoscroll: pins to bottom unless user scrolled up
- letta.zig: streamInfer() — --output-format stream-json, per-event callback
  (tool calls, returns, reply chunks), full reply still returned for TTS
- whisper: --language auto (no more hardcoded English)
- fix: stderr_log leak crashing Quit via debug allocator

👾 Generated with [Letta Code](https://letta.com)

Co-Authored-By: Letta Code <noreply@letta.com>
2026-09-01 20:37:45 +03:00
pierreandLetta Code 5b050c09e3 Worker thread + tray icon repaint fix
- processUtterance runs on a detached std.Thread; Qt event loop stays
  responsive during whisper/letta/melo (icon repaints, menu works)
- setState marshals to main thread via threading.async with thread-id check
- rapid double-click race guarded: state claimed before spawn
- icon: QPainter-drawn antialiased circle (dark rim, transparent bg) —
  bare pixmap.fill rendered blank on the KDE SNI host
- new qt libs: qbrush, qpainter, qrect, qt6zigthreading

👾 Generated with [Letta Code](https://letta.com)

Co-Authored-By: Letta Code <noreply@letta.com>
2026-09-01 19:29:03 +03:00
pierreandLetta Code f4c08cae74 README + idempotent setup script (MeloTTS venv, checkpoint, sanity checks)
👾 Generated with [Letta Code](https://letta.com)

Co-Authored-By: Letta Code <noreply@letta.com>
2026-08-25 00:56:54 +03:00
pierreandLetta Code 90b59e20f3 MeloTTS voice output, signal handling, auto pipeline
- melo_server.py subprocess (MeloTTS v3 EN-Newest, speed 1.3): line protocol
  stdin->stdout, model loaded once, warmup before READY
- src/melo.zig: lifecycle ownership (spawn/kill with inferon), line protocol
  client, reply sanitizer (newlines/markdown stripped before synthesis)
- SIGINT/SIGTERM handlers: async-signal-safe kill of whisper/melo/recorder,
  default disposition restored + re-raise for truthful exit status
- processUtterance: transcribe->infer->speak chains automatically after
  stop-click; mid-pipeline clicks are no-ops; back to idle after reply
- temp cleanup: recording WAV deleted after transcription, TTS WAV after
  playback
- whisper: pid() export for signal handler

👾 Generated with [Letta Code](https://letta.com)

Co-Authored-By: Letta Code <noreply@letta.com>
2026-08-25 00:53:48 +03:00
pierre 3ddb0e77bc holy fuck voice to agent response works kinda sorta 2026-08-24 03:26:43 +03:00