Repository navigation
Open
Labels
pluginsPlugin system roadmapPlugin system roadmap
Description
Part of the plugin system epic #3. Depends on #7 and #8. Phase 5 lets plugins shape what agents see and do inside a turn.
- Turn lifecycle hooks. (2026-10-31,
feat/plugins-server-hooks:turns.onRuntimeRequestanswers approvals and questions, and send hooks can replace or block a message.) Partly built in feat(plugins): run-completed hook, richer send hook and agent plugin tools #21:beforeDispatchgets the message id, attachment summaries and the requested model;turns.afterRunCompleteddelivers every ended run with a stored cursor (one per registration, in order).onRuntimeRequestis not built: answering approvals needs per-plugin rules the user sets. Original text:turns.beforeDispatch(from Phase 3) gains the full message with attachments and the thread's model selection; addturns.afterRunCompleted(run)(reacts to run completion events with the run's items available for reading),turns.onRuntimeRequest(request)(approval or question raised by the provider; plugin may auto-answer under rules the user configured in its settings). Each hook is an event reaction overstreamStoredEventsFrom({ afterSequence, eventType })with the plugin's acknowledged sequence stored inPluginStorage, so a plugin that was off when the run finished catches up on start.streamDomainEventsstarts at the latest sequence and cannot be used for catch-up. Shape modelled on saphid's feat(server): deliver finished runs to plugins from an acknowledged cursor pingdotgg/t3code#16048. - Context injection. (2026-10-31: send hooks append or replace text, and web plugins add
@items, shown as chips since 2026-11-01, see Plugins Phase 4: web plugin runtime and UI contribution registries #8.) A plugin can registercontext.providersthat contribute text blocks to the outgoing turn, each shown as a composer chip on web so the user sees what was added and can remove it for that message. Server records which plugin added what in the message metadata. - Skills and instructions. (2026-10-31,
feat/plugins-server-hooks: askills/folder andagents.addInstructionsreach Claude and Codex. ACP agents, OpenCode, Cursor, Pi and Muse take neither from T3. 2026-11-01,feat/plugins-server-gaps: the$picker lists plugin skills for Claude and Codex as<plugin>: <skill>.) A plugin directory may containskills/in the same format the composer's$skill picker already understands (ServerProviderSkill). Plugin skills appear in the picker labelled with the plugin name, for every provider that supports skill injection. - Slash commands with server handlers. (2026-10-31,
feat/plugins-server-hooks:slashCommands.registerlists the command for every client through the server-supplied list and runs the handler at dispatch, which returns text to send or a block. 2026-11-01,feat/plugins-server-gaps, with Ash's approval for oneOrchestrator.tscommand: a handler can return{ reply }, recorded with the command as an already finished run, so no agent turn starts and every client shows it unchanged.) Delivered through the existing server-suppliedprovider-slash-commandmenu variant (see Phase 4b). A plugin slash command may rewrite the message, dispatch a different message, or answer directly without a model call (rendered through theplg_dynamic tool renderer from Phase 4c). - MCP tool policy. (Done in Phase 3.) Plugins can mark their tools as read or write (Phase 3) and the thread's runtime mode gates write tools the same way built-ins are gated.
- Agent-facing management. (feat(plugins): run-completed hook, richer send hook and agent plugin tools #21; both tools are writes and appear only once a plugin is installed.) MCP tools
t3_plugins_invoke(call a plugin RPC by name, write access) so an agent can drive a plugin, andt3_plugins_set_enabledguarded as a write.
Measurements
message.dispatch latency with zero hooks registered: unchanged from Phase 3. With one no-op hook: report the added milliseconds.
Tests
A beforeDispatch hook that appends a context block shows up in the persisted message and in the provider input (use the Replay dev provider). afterRunCompleted fires once per run and catches up after a restart from the stored cursor. An onRuntimeRequest hook that answers an approval results in the approval event. A plugin skill appears in the skill list for Claude.
Done when
Draft PR feat(plugins): turn lifecycle hooks, context injection and plugin skills on the fork.
Metadata
Metadata
Assignees
Labels
pluginsPlugin system roadmapPlugin system roadmap
Activity