Skip to content

Releases: yexrob/bingo

v0.6.6

Choose a tag to compare

@github-actions github-actions released this 02 Oct 16:52
6aa04cb

Feishu answer metadata

  • Add an English-language footer to finalized assistant answers with the model, reasoning effort, current-turn token and cache usage, and context utilization when available.
  • Keep the footer within Feishu's text budget and outside code blocks, including when a long answer is clipped or a partial answer ends inside a Markdown fence.

Reliable long-running chats

  • Renew streaming cards before Feishu's ten-minute timeout and recover both timed-out and closed streams.
  • Apply the same renewal and recovery path to the final write, so a quiet long-running turn does not fall back to a duplicate plain message merely because its card expired.

Command results in the chat

  • Display slash-command results and errors in the requesting chat, including commands queued behind an active turn.
  • Render supported command tables as Markdown tables and keep LF, CRLF, and CR line endings within their cells.
  • Apply platform length and formatting limits to command results and their fallback messages. Keep the new UI labels in English.

Thanks to @contsun for the Feishu contributions in #91 and #92.

Full changelog: v0.6.5...v0.6.6

v0.6.5

Choose a tag to compare

@github-actions github-actions released this 27 Sep 17:08

Bounded session transport

  • Add opt-in, byte-bounded session heads, history pages, child discovery, snapshots, and live-event delivery for reference-aware RPC clients, including Rei v0.1.1.
  • Retrieve oversized items, snapshot fields, and events explicitly through scoped, immutable references and UTF-8-aligned parts. Expired references, quota exhaustion, stale generations, and responses that cannot fit the requested budget fail explicitly.
  • Keep existing TUI, print, legacy RPC behavior, and original journal content intact. This release bounds transport; cold resume still replays the stored journal.

Feishu channel controls

  • Map /new to a fresh conversation session and /stop to an interrupt, without sending those controls as model prompts. Configure additional aliases under channels.feishu.commandMappings.
  • Persist released and renamed routing keys so a fresh session retains its route across restart and the previous session remains recoverable by ID.
  • Preserve the previous streamed answer, including pending coalesced text, when switching sessions. Send stop notices separately and keep new-session confirmations in their originating thread.
  • Retire old question cards when switching sessions.

Thanks to @contsun for the Feishu command-mapping contribution in #90.

Model configuration

  • Honor explicitly selected thinking levels even when the model capability catalogue does not declare reasoning support.

Full changelog: v0.6.4...v0.6.5

v0.6.4

Choose a tag to compare

@github-actions github-actions released this 21 Sep 08:49

Scheduler recovery (M106)

  • Replace the scheduler's PID sentinel with a permanent OS-locked file. Exiting or crashing releases ownership without leaving a stale modern lock behind.
  • Already-running bingo processes stand by and retry once a second, automatically taking over when the owner leaves.
  • Wait for an in-flight dispatch to finish before releasing ownership during shutdown. Cancelled scheduler and wake loops do not begin new deliveries.
  • Distinguish a running owner, standby, migration barriers, and storage errors in scheduler status. gateway doctor --fix preserves modern lock files whether held or free.

One-time scheduler upgrade procedure

Older releases used a different locking protocol. Stop all bingo processes sharing the data directory before migrating an existing legacy schedules/runner.lock. Run one bingo gateway doctor --fix to remove a dead PID sentinel, then start the upgraded binaries. Inspect empty or unrecognized legacy files before removing them. Do not run concurrent repair commands or mix old and new scheduler binaries.

Once migrated, the modern runner.lock is permanent: do not delete or replace it while bingo is running. Normal exits and crashes release the OS lock automatically. This release does not change channel locks, the 60-second cross-process schedule-directory rescan, or expired one-shot creation behavior.

Settings and plugin controls (M97–M101)

  • Read and write settings as TOML, preserving comments when updating a setting. Existing JSON settings migrate to TOML at startup, with the old file retained as a backup and the paths reported.
  • Inspect and persist plugin switches through /plugins (alias /modules) and bingo plugins list|enable|disable. Disabled external plugins are not spawned; plugins required for the current configuration cannot be disabled.
  • Add the configurable persona plugin and its guide-persona page.
  • Complete command arguments after the verb, including plugin names, and update bundled guides for the new configuration format and controls.

Sub-agent management (M102)

  • Stop a running child with StopAgent or /agents stop, and dismiss an idle child with DismissAgent or /agents dismiss.
  • Reopen an existing child with SpawnAgent { reopen: true }, retaining its session and memory.
  • Show each agent's model, message count, and token usage in the roster.
  • Keep child transcripts across replayed close events and remove deleted children from the TUI tree.

Images and file access (M103–M105)

  • Remove image payloads from subsequent model requests after three assistant responses, retaining a textual reference and the original journal/transcript record.
  • Bound images before sending them to the model, reducing repeated large uploads.
  • Report when Read returns a bounded rendering and identify the source file's type and byte size. Use Read { original: true } to inspect the original within the journal's size cap.

Terminal fixes

  • Continue walking command history past a recalled command.
  • Enable the required tmux passthrough mode for picture rendering.

Full changelog: v0.6.3...v0.6.4

v0.6.3

Choose a tag to compare

@github-actions github-actions released this 15 Sep 01:57

A request is cut for silence, not for size (M93, ADR-0056)

  • A slow upload completes. Both HTTP providers used to end a request 60 s after send() began, upload included, so a long session on a slow relay was cut mid-body and retried forever while the relay logged a 400 "Failed to read request body". Now connecting has its own bound (20 s) and everything after it is cut only when no byte has moved on the wire in either direction for 300 s. The body goes out metered in 64 KiB frames, keeps its Content-Length, and the sign-in-again retry still works.
  • A reasoning model that is quiet for under five minutes is no longer cut either.

A sleep is not a wait (M94, ADR-0018 §9)

  • A bare foreground sleep is refused with the way round: end the turn and let the job or agent wake you, run the same sleep with background: true as a timer, or put the check in the same call when a pause must precede it. The Bash description and every job-start receipt now say that ending the turn is how you wait.

The window follows the stream (M96, ADR-0018 §8)

  • notify_all no longer waits a fixed thirty seconds. The quiet window starts at zero, so a slow stream wakes the session on every line; a burst grows the window by its observed rate (two seconds per line per second, capped at thirty); a line held inside the window goes out when the window ends instead of riding the next hit, so the delay is bounded by the window the notice names.
  • Every notice says its pace: the clock time, the lines and seconds since the last notice, and how soon the next can come. notify_quiet (milliseconds) pins the window when the model would rather choose; it is refused without notify_all.

The foot is a row away (M95)

  • While the transcript is scrolled back, the activity band's first row carries ↓ 37 lines below · end or click to follow, centred on the raised bar. A click on it follows the tail again, as end does. It rides a row the frame already holds, so nothing moves.

v0.6.2

Choose a tag to compare

@github-actions github-actions released this 10 Sep 18:12

Rooms: one purpose, four verbs (M88, ADR-0053)

  • A room says what it is for. OpenRoom takes a purpose and refuses a name that is already standing; reopening a room can no longer silently evict its members. The reading header shows it: [#design — <purpose>, since you last read].
  • Seat, Unseat, CloseRoom. New tools for the holder or opener, each a signed post in the room; an unseated member is told. /room close <name> in the TUI. A post into a closed room is refused.
  • A bounce is cheap to retry. SendMessage { to, again: true } re-posts the latest bounced draft without regenerating it.

ACP agents keep their own context (M91, ADR-0055)

  • An ACP agent that holds its context is measured and compacted by the agent, not by bingo: no more futile compactions or 2,367,503/191,808 · /compact from a turn bill read as context. The status line shows the agent's own count, the agent's compaction lands as one row, and /compact is refused in words (exit 1 in --print).

The selection follows the hand (M92)

  • Dragging a selection past the top or bottom edge scrolls the transcript with it; releasing the mouse copies and says copied N lines. ? lists it as v · drag.

Also since v0.6.1

  • Esc ends a turn at once — an interrupt is now seen at every await of a round, not only mid-stream; the multi-second stalls at turn start and between rounds are gone.
  • A picture is a file (M87, ADR-0052): a pasted or Feishu picture is written to disk first, and the model is told its path.
  • Every plugin writes its own page (M90, ADR-0054): guide is a short map; each plugin's page is a guide-<name> skill (acp, agents, channels, experience, hooks, mcp, memory, permissions, rewind, rooms, schedule, skills, tasks, tui).
  • Prose fills the terminal (M89): the fixed text measure is gone; tui.measure caps it if you want one.

Fixed

  • An MCP server's tools keep one order across reconnects.

v0.6.1

Choose a tag to compare

@github-actions github-actions released this 09 Sep 06:13

Feishu: the chat carries more than words (M86, ADR-0051)

  • Every message is heard. Rich post runs (links, code blocks, dividers, emoji, mentions), interactive cards, shared chats, merged forwards and stickers all reach the model as words; no message type is dropped any more.
  • Attachments in. A file, voice note or video lands under <data_dir>/channels/feishu/attachments/<message>/<name> and the message carries its path; a text or markdown file up to 100 KiB is inlined. Merged forwards are fetched (im:message scope) and flattened under the message.
  • Files out. A new SendFile { path, caption? } tool posts a file from disk into the chat the session lives in; it exists only while the channel surface runs. Feishu routes pictures, opus audio, mp4, office documents and everything else to the right endpoint.
  • Who may speak. channels.<adapter>.access — admins, a rule for direct chats, a rule for groups, per-chat overrides; policies open | allowlist | blocklist | admins | off, and mention: false engages a group on every message. The default is what ran before.
  • A working sign. The message you sent gets a Typing reaction while the bot works, loses it when done, and a ❌ marks a failed turn (im:message.reactions:write_only).

Fixed

  • The permission card was refused by card JSON 2.0 (action container), so every permission had fallen back to a numbered list; buttons are a column row now.
  • The streaming card never closed (settings must be a JSON string), so every answer was posted a second time as plain text.

Also since v0.6.0

  • Memory has one writer (M83, ADR-0049): the model writes memory; the extractor is gone.
  • The worked row (M84): ✻ Worked for 15m 11s · done 13:48 closes the transcript.
  • MCP servers that need signing in (M85, ADR-0050): OAuth 2.1 for HTTP MCP servers — /mcp login|logout|tools, bingo mcp list|get|add|remove|login|logout.
  • A command lists the words its argument takes; the command completion channel is gone.

v0.6.0

Choose a tag to compare

@github-actions github-actions released this 08 Sep 01:39

Thirty-seven commits since v0.5.4. Two of them change what a model or a plugin sees, so the minor moves.

Agents

  • The wait is the turn's end. WaitAgent is gone. A parent that started a background agent waits by ending its turn; the reply wakes it. A join tool beside SpawnAgent was what the model reached for first, and every call held the person's turn on a wait it did not need. Plan M81.
  • Say what an idle session is waiting on. Between turns, while agents the session started are still at work, the activity row reads ✻ Waiting for 2 background agents to finish, breathing at the pace a tool holds a turn. Before, the row left with the turn and the parent looked finished. Plan M82.
  • SpawnAgent says things once. Its model-facing text is 16 % shorter; nothing it taught is dropped. The room protocol (read at the head of a turn, @name and @all wake you, post the result back) now comes from the rooms plugin itself, only to a session seated in a room, and is journalled so a compaction says it again.

Context

  • Stable request prefixes. Project instructions and memory have stable knowledge baselines with explicit refresh boundaries; internal context stays in the journal with its provenance but out of ordinary UI; compaction reuses the parent request's prefix; OpenAI requests carry a session-derived prompt_cache_key and cache-write tokens are counted once. Shell guidance chooses foreground or background by dependency, not duration. Plan M80.
  • Experience stays on by default. Set experience.enabled: false and the plugin registers nothing: no tools, no command, no prompt lines. schedule.wakes: false likewise unregisters the Wake tool instead of offering one that refuses.

Fixes

  • A root session the client fell behind on no longer ends the whole tree stream in silence.
  • The bash plugin ends every background job when it stops, on the same grace a kill gets.
  • The ACP proxy exits when its bridge closes instead of hanging on an outstanding stdin read.
  • Print offers only the permission answers the interaction actually carries; y on a prompt without an allow-once rung is a refusal, not an error from the kernel.

Inside

  • The gateway daemon is its own crate, bingo-gateway; the binary keeps only composition.
  • The plugin RPC wire holds at protocol 1 until a plugin outside this repository speaks it.
  • The Windows cargo check job is blocking; tests there stay advisory until the shell dialect is decided.
  • Nine ADRs say what is true now, with dated lines for what they said before.

v0.5.4

Choose a tag to compare

@github-actions github-actions released this 06 Sep 11:20

One change since v0.5.3.

  • A run of thoughts is one thought. Some endpoints close a reasoning item and open the next as the model goes on thinking, so one long think arrived as ten ✻ Thought for Ns rows in a row. Adjacent thoughts now draw as one block: ✻ Thinking… while the last is still being had, ✻ Thought for 3m 21s once it is over, the newest two rows of the whole run under it, one click or ctrl+o for all of it. The journal and every other surface still carry the items one by one. Plan M79.

v0.5.3

Choose a tag to compare

@github-actions github-actions released this 06 Sep 01:51

One change since v0.5.2.

  • A finished thought holds where it ended. v0.5.2 fixed the height of the block under ✻ Thinking… while a thought streams; the close still took its two rows away, so everything above the block dropped by two when the thinking was over. Now the heading becomes ✻ Thought for 2s and the two rows under it stay exactly as the last delta left them — no cut mark, no new row, nothing above moves. A click still goes round: the whole thought in place, then the row alone, then back to the two rows. Plan M78.

v0.5.2

Choose a tag to compare

@github-actions github-actions released this 05 Sep 21:35

Three changes since v0.5.1.

  • A streaming thought holds its height. The two rows under ✻ Thinking… were the last two lines of the thought, wrapped afterwards — a paragraph is one line, so the block was any number of rows and changed on every delta, and the whole transcript above it moved with it (reported on Windows, where a narrower console made it worse; the same everywhere). The tail is now measured in rows as drawn: exactly two while a thought streams, three under a running tool, whatever the width. Plan M77.
  • A spawn names the level it thinks at. SpawnAgent takes thinking beside model and provider, a child inherits the parent's level unless told otherwise, off is a level, and a SetThinking tool lets an agent move its own or a child's mid-run. The level rides the session spec, so session/open on the wire and the next turn agree. ADR-0047, plan M76.
  • An attached client may open the browser itself. BINGO_BROWSER_MODE=client tells ShowPage and login to hand the URL to the client instead of spawning the platform opener; BINGO_NO_BROWSER still wins. ADR-0046.