Repository navigation
feat: worker-defined chat mentions (@kanban, @session, @trace) - #1334
Conversation
Any worker can now let a chat mention its items as `@<name>(id="<id>")`: it declares a mention provider in the metadata of a get function and registers a search function (crates/mention-contract). - ADE composer: `@` lists mention providers beside functions and files and searches every provider (one group each); Tab on a provider scopes the menu to `@<name>:` and its own search. Mentions render as pills (icon, color, name) in the composer and in messages, preview on hover (generic card or the worker's own via host.mentions.registerRenderer) and open their item on click. - Providers: kanban tickets (kanban::mention::*), sessions (session::mention::*) and engine traces (console::mentions::trace::*). - Agents: the judge binds a harness pre-generate hook that lists the mention names an agent may write and resolves the mentions users wrote into a one-line summary plus a pre-verified details call (offered only when the session's policy allows it); the default system prompt teaches the syntax. - The chat shows what the model was told as a quiet "Context for the agent" row instead of the raw note.
- ade/mentions (new): the full provider contract — the search and get functions, the metadata descriptor, ranking and view rules, icon/color vocabulary, open targets, Node/Rust/any-language registration, permissions, the optional hover renderer and the definition of done. - ade/SKILL, ade/injectable-ui: point to it; document host.mentions and the console's @trace provider functions. - kanban iii-node and ade-worker-design: a "Chat mentions" section with the Node registration shape and the host.mentions slot. - kanban and judge skills: how agents read and write mentions, and judge::mentions::resolve for verifying a provider.
A chat titled from its first prompt read the raw token (`what happened in @session(id="co…`). Mention tokens now read as the item's handle or name when its view is cached — it is, for an item just picked from the @ menu — and as @<provider> otherwise.
- The global @text menu lists each mention provider's group before functions & files: ten file hits used to push the groups out of view. - Opening a @trace pill while the traces screen follows turns no longer lands on the chat's latest turn: a turn that started before the explicit request is not new work to jump to. - A mention pill squeezed by its row (the "Context for the agent" summary) truncates its name instead of overlapping the next pill.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Important Review skippedToo many files! This PR contains 106 files, which is 6 over the limit of 100. To get a review, reduce the PR to 100 files or fewer by splitting it into smaller PRs or changing its base branch. Upgrade to a paid plan to raise the limit. This review couldn't start because sufficient usage credits or metered capacity aren't available. Add credits or update usage-based reviews in the billing tab, then retry. ⚙️ Run configuration
⛔ Files ignored due to path filters (5)
📒 Files selected for processing (106)
You can disable this status message by setting the
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
skill-check — worker0 verified, 82 skipped (no docs/).
Four for four. Nicely done. |
The lockfiles this PR touches carried rustls 0.23.44 from main, which the audit job flags; ade and judge are already on 0.23.45.
Registers host.mentions.registerRenderer for the kanban provider, so hovering a @kanban(id=…) pill shows the same ticket card a ticket function result renders, drawn from the mention view's data (board projection plus a description excerpt). Feature-detected; older consoles keep the generic card, and a view without ticket data falls back to it too.
Summary
Any worker can now make its records mentionable in chat as
@<name>(id="<id>")— a ticket, a session, a trace today; an email, a calendar event, a Slack user tomorrow — and both the person and the agent understand it:@lists the workers that offer mentions beside functions and files. From two characters on it searches all of them at once, one group per worker. Tab (or Enter) on a worker scopes the menu to@kanban:and that worker's own search. A picked item becomes a pill (icon, color, name) that previews on hover and opens on click (a worker page, a chat, or a trace in the traces screen).crates/mention-contract, and a new skill,ade/mentions, teaches agents to build their own providers.This PR ships three providers: kanban tickets (
@kanban), sessions (@session) and engine traces (@trace).Follow-ups:
@kanban's hover preview: feat(kanban): preview @kanban mentions as the ticket card #1335;Evidence
Recorded against workers built from this branch (
anderson-agoraproject, Claude Sonnet 5.5 via Claude Code, Judge on TypeSafe). The GIFs cut out the agent's thinking time; the MP4s are the full runs.Composer:
@menu → Tab into a worker → global groups → hover previewTranscript: what the agent was told → open a ticket → mention a trace, open it in the traces screen
Full runs: light (MP4) · dark (MP4)
@— the mention sources sit above functions & files@kan→@kanban, Tab to search it@kanban:— recent tickets, colored by priority@kanban:login— the worker's own ranking@webhook— one group per worker, above files@session:hello— past conversationskanban::ticket::get@trace:send— agent turns by name@menuHow it works
A provider is two functions and a descriptor (
crates/mention-contract){ query, limit?, context? }→{ items: [{ id, label, hint?, description?, icon?, color? }] }, best match first. An empty query means recent items.{ id }→ aMentionView(ornullfor an unknown id). The view carries:label,hint,description,icon,color;fields;open— a page with context, a chat session, or an http(s) URL;summary— one line for the agent;data— the domain object, for a worker's own preview.metadata.mentionon the get function. It holdsname,label,description,icon,color, thesearchfunction id, anddetails(the agent-facing function that returns the full record, e.g.kanban::ticket::get). The mention functions areinternalandtrace_hidden.@<name>(id="<id>"), with the id as a JSON string literal.fixtures/tokens.jsonholds the grammar cases, and the Rust and TypeScript parsers both run every one of them. A missing closing quote is tolerated on read, never written: testing showed a model dropping it, which left a raw token in the reply.Providers
@kanban(id="<uuid>")KAN-12,12,#12), then title prefix, title words, then description and labels; live tickets; most recent firstkanban::ticket::get@session(id="<session_id>")session::get@trace(id="<trace_id>")engine::traces::listby span name across spans, or an exact trace id; newest first; an engine without the memory exporter answers emptyengine::traces::treeADE
lib/mentions/:engine::functions::list { include_internal: true }, refreshed when a worker joins or leaves;WorkerMentionNodepill;MentionsPluginbuilds its rows from a purebuildGlobalMenu/buildScopedMenu, so groups, "more …" rows and drill-down are tested without an editor;@worker:menu, Enter never sends the half-typed search.host.mentions.registerRenderer(intypes/injectable-ui.tsandpackages/console-ui). It falls back to the generic card if the renderer throws.<mentions>reads as "Context for the agent" plus the pills;<mention_providers>is hidden.@traceclick opens the traces screen on that trace, and it wins over the session seed and over "follow turns".where does @kan-8 …), not by the raw token.Agent (judge + prompt)
The harness always runs
judge, so the judge hosts the mention hook:judge::mentions::pre-generate, bound toharness::hook::pre-generatewithfail_open.<mention_providers>: the names an agent may write. Appended once per session, and again when the set of providers changes.<mentions>: for each mention a user wrote that no earlier block resolved (at most 10, about 600 tokens), it adds:details: <function> <payload>with the canonical id, offered only when the session's policy allows that function.Both blocks are persisted and replayed by the harness, so the hook reads its own earlier blocks and never repeats one. It skips markdown code, attached files and other hooks' blocks.
judge::mentions::resolveexposes the same resolution to any caller, andJUDGE_MENTIONS=falseturns all of it off.harness/prompts/default.txtteaches the token, both blocks, thatdetailscalls are pre-verified, and the fallback through discovery. It is mirrored byte for byte intoiii-directory/prompts/iii.md, with a short version indefault.md/iii-minimal.md.Skills (for agents building their own mentions)
ade/mentions(new): the whole provider contract:ade/SKILLandade/injectable-uipoint to it and documenthost.mentionsand theconsole::mentions::trace::*functions;iii-nodeandade-worker-designgain a "Chat mentions" section and the slot;judge::mentions::resolve.template/skills/harnesscopy here is left to the nextsync.sh.Tests
crates/mention-contractkanbantests/mentions.rs: ranking, view, descriptor)session-managerade(Rust)rebind_starts_new_port_before_stopping_old_listeneris a flaky port test that failed once in a parallel run and passes alonejudgetests/mentions.rs; the boot test expects the mention functions and thefail_openhook)harnessworker_mention_syntax) and 6 prompt testsiii-directoryade/webtscclean; 3085 of 3087 passedNew web suites: token fixtures, menu builder, runtime parsing, view and search caches, the composer flow (
@kan→ Tab → pick), markdown pills, preview card and renderer fallback, note row, entry mapper, chat titles, trace focus.The two web failures are already on
mainand untouched here:icon-size-conformanceflagscomponents/chat/DeviceSignIn.tsx(from feat: providers declare default models and thinking levels; harness and ADE start on them #1306);MermaidDiagraminline-language test.The ADE web suite is not run in CI.
Clippy,
cargo fmt --checkand biome are clean on every changed crate and file.