You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This commit was created on GitHub.com and signed with GitHub’s verified signature.
Added
A question a Bot asks about work handed out from a group now shows in that group's sidebar row (waiting dot and "Waiting for your answer") and in the Agent inbox as a Needs your answer card whose Open takes you to the group, where the card takes the answer (#552).
The flybot service can now report approval activity: flybot.approvals.stats() returns, read-only, how many of each Bot's outbound sends were held and how many were approved, rejected or went stale, plus a team total. A plugin or a settings view can show it; nothing is changed by reading it.
A Bot can now record a decision that mattered — an option it considered and whether it used or rejected it, and why — with record_decision. It goes into a local, append-only log (<home>/decisions.jsonl, capped) that a reviewer can read to see near-misses and judgment drift, and it is fired on the activity feed as decision so the Timeline or an audit view can show it. Off by default (decisions: true turns it on); a key, token or password is refused.
When the tree merges two duplicate Bots, the archived Bot's own memory now moves into the Bot that keeps it, so a merge no longer drops what the duplicate had learned. It is capped at 20 entries and tagged source: merged. This uses a new plugin seam, flybot.memory (read a Bot's entries, append one), which is off unless the host names the plugin in flybot.memoryPlugins; without it the merge is unchanged.
Plugins can now make a short, sanctioned model call. flybot.model.ask({ prompt, system?, maxTokens? }) resolves { ok: true, text } or { ok: false, code } for a plugin the host allows — usably for a small classification, a title or a one-line summary that a plugin needs of its own. It is off by default (the host names the allowed plugins in flybot.modelPlugins), capped in input, output and rate, streams through the host's own model, returns text only (never a provider message) and refuses on a read-only host.
The Timeline window now reports how each Bot's turns ended — completed, aborted, error or lost — and lists its recent failed or aborted turns with their error code, so the panel or a tool can see a Bot's reliability at a glance. It is read-only and part of the existing timeline/window answer, so nothing new needs configuring.
The timeline window now also reports the open requests waiting longest (#469) and the tools each Bot used with their failures (#359), and timeline/health reduces the same window to per-Bot health signals and flags (#357).
The Timeline window now reports the token spend per Bot — how many model calls, and the input, output and cached tokens they used, when the adapter reports them — so where the team's model quota goes is visible next to the turns it ran. Read-only, counts only (never message text), and part of the existing timeline/window answer.
The tree can now group a Bot by meaning, not only by the words in its name and role. With modelClassify: true in the tree config (and the host allow-listing flybot-tree in flybot.modelPlugins), a Bot whose role the built-in vocabulary cannot place — a title it does not hold, a brief in another language — is sent to the model once for a single category, which is stored on the Bot and used the next time the tree reorganizes. It is off by default, asks at most once per role change, and the rules still win where they already found a category.
Changed
A Bot session on workspace-write without a usable sandbox backend now has a one-command preflight (node .github/scripts/sandbox-preflight.mjs) that names the missing backend and prints the unlock in one line, and the agent instructions say to report the block once instead of retrying every shell call (#607).
The integration guide now names the two plugin seams — flybot.model.ask and flybot.memory — with the host config that enables each (flybot.modelPlugins / flybot.memoryPlugins), so a plugin author finds them without reading the host source.
Fixed
Scheduled tasks no longer stop overnight in a group chat: the limit that let Bots start only three rounds there until you spoke again is turned off, because it blocked owner-set recurring runs without showing anything. Bot-to-Bot chain and per-round limits still apply (#557).
Sharing a Bot with a friend on a Bot Social server that lacks grant_bot_to_friend now tries the REST route and, when that is missing too, says Bot Social needs an update to share with a friend. Invite links still work. instead of showing the raw MCP error -32602: Tool grant_bot_to_friend not found (#563).
Sharing a Bot with a friend works again: Share with a friend names the friend by the friend's Bot id (the id list_friends returns) instead of an owner id the server never lists, the fallback route now matches Bot Social (POST /v1/bots/:id/grants), and a server that refuses the request says so in plain words instead of showing the raw MCP error -32602 text (#592).
The approval card in a group's details panel wraps its buttons, so 拒绝 and 允许一次 stay reachable at common desktop widths instead of overflowing off the left edge of the panel (#593).
A Main Bot the tree adopts only after the server started (onboarding creates it while dsh web runs) now gets the tree's team-building tools (create_team, create_child_bot, and the other gated tools) on its first turn instead of only after a restart; the plugin-tool mask is recomputed when a turn starts, not only when the Agent is created (#594).
A group member Bot's line that arrives while the group's turn is still running no longer shows up in the message bar above the composer with the internal [Group post from …] header; it appears at once as that Bot's own bubble, and the round still gets it when the turn ends (#595).
A Bot's own failure, stop or resume notice that lands while its group chat is still in a round no longer flashes FlyBot's internal [Group post from …] routing header in the queued-message bar above the composer; it waits until the round is done and the round still shows it as that event (#595).
The decision log (decisions.jsonl) is now bounded on disk: the host trims it to the newest 2000 entries and at most 1 MB as it appends, and a read parses at most that byte cap instead of the whole file, so the log no longer grows without bound (#603).
"Always allow" now keeps working when DSH opens its own retry turn after the owner answered: a turn with no message verdict in a Bot's own chat uses the Bot's standing approval instead of showing the same card again, and a grant that a turn cannot use says why once in the log (#608).
The sandbox preflight now answers for the file policy it is given (--mode, or FLYBOT_SANDBOX_MODE) instead of assuming workspace-write, never reports a danger-full-access session as blocked, reports the Windows ACL runner as unknown rather than unavailable, and separates "proven blocked" (exit 3) from "cannot tell" (exit 4), so an agent no longer stops shell work on a probe it cannot complete (#615).
The answers to deleting a Bot, setting a Main Bot, removing the Agent and deleting a group chat now carry only the signed-in member's own scope, like every other team view, instead of the whole team.
When someone has signed in, the one DSH Agent (and its Sessions: new session, adopt, rename, archive, remove) stays usable to that member while the team is alone, instead of every call being refused before it runs; with more than one member it follows the same shared-resource rule as adding the Agent.
After switching the Bot Social server, the stopped social layer can no longer restart its poll from a face poll that was still in flight, so the old server is not polled (and does not deliver messages) after the switch.
A hold on a send now blocks the task that was started last even when two tasks were started in the same millisecond: task order uses a strictly increasing stamp instead of the bare clock, so which task an untagged hold blocks no longer depends on timing.
The team-health view no longer calls a Bot idle while it is busy in one long turn that began before the window, and its failure rate is never reported as more failures than turns; a Bot busy through the window is flagged busy.
The timeline panel no longer issues a duplicate request when a window change supersedes a poll in flight and the tab is looked at again: a superseded answer no longer clears the in-flight guard of the request that replaced it.
Security
set-main no longer lets a member take another owner's Main Bot's place: the endpoint checks the Bot named in replace too, and setMain refuses a replace across owners, so a member cannot demote another owner's Main Bot or promote their own Bot over it (#613).
Untrusted-content fences are neutralized more strictly: a marker written with whitespace inside the tag (< / untrusted-message>) is now stripped too, since a parser that ignores whitespace reads the same closing marker. Text from friends' Bots and other untrusted sources stays data, never instructions.