Repository navigation
Replies: 1 comment 1 reply
|
I really like the idea. I was thinking to build additional set of controls or integrations with task management for example. +1 to the idea. |
1 reply
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Original proposal (outdated)
T3 Code SDK
A T3 Code SDK to expose the existing HTTP endpoints and WebSocket streams from T3 Codes server, so a web app can read threads, dispatch commands, and follow events live reusing the existing auth and reconnect logic.
For the UI, a new configurable surface reusing the browser surface. Point it at your web app's URL and the app renders "inside" T3 Code. Adding a custom surface is also the moment to tell someone that the app may act on their behalf. Web apps can optionally expose MCP servers for the agents in the T3 threads to respond to.
@t3tools/sdk, a typed client for the endpoints that already exist.@t3tools/ui, the components T3 renders, packaged for local apps. Nice to have.A plugin is a page your own app serves. T3 opens it in the browser surface it already ships, hands it a one-time code, and the page then calls the T3 server directly.
What a plugin can and cannot do
orchestration:readThe first cannot row is deliberate. Asking a focused T3 client to reveal a thread needs a server-side broker, host registration, and desktop IPC, which is more machinery than the rest of this issue combined. It belongs in its own proposal.
Part 1, the SDK
A thin Promise-first client over what the server already exposes: the public descriptor for discovery, bearer or code-exchange auth, shell and thread snapshots, typed command dispatch, and subscriptions that resume with
afterSequenceafter a dropped socket. It would needeffectand a narrow public entry into@t3tools/contracts, leaving the internal RPC, settings, provider, and IPC contracts private.This runs in the plugin page itself. No backend, no proxy. The server sends
access-control-allow-origin: *withauthorizationin its allowed headers (apps/server/src/httpCors.ts:11), so a page on any origin can call/api/*with a bearer token today, andWS /wssits outside CORS entirely.Writes are the same client.
thread.createandthread.turn.startare the wire shapes T3's own clients send, and they carry boilerplate an integrator should never hand-roll (commandId,messageId,createdAt, the message envelope,runtimeMode,interactionMode), so the SDK should mint all of it.Failures should reject with typed classes, so a caller can tell an expired grant from a rejected command.
Part 2, adding a plugin
Add one tile to the surface picker: Add plugin. Paste an http(s) URL, T3 fetches that page once for its title, favicon, and description, and the entry is saved per project in server settings (
settings.json, already a validated and watched JSON store atapps/server/src/config.ts:118). Entry names stay within[a-z0-9-], because the name becomes a tool prefix later.Opening an entry substitutes
{threadId}and{projectId}, and appends a fragment carrying the environment base URL and a one-time code. An unresolved{threadId}is left alone, so the same template also works for a project-level open. Right-panel surfaces are per thread already (rightPanelStore.ts:52), so each thread opens its own instance with its own thread id.The page exchanges that code at
POST /oauth/token, the RFC 8693 exchange the server already serves for pairing, and gets a short-lived token scoped toorchestration:read. A plugin can ask for more, and what it asked for appears on the consent screen in plain words.The consent screen
Adding a plugin means handing a third party a token that acts as you, so T3 says so before it happens. One screen, two separate grants, both keyed to the origin:
The origin is the identity, since a page's title and favicon are self-reported and can change at any time. Those are shown as decoration and labelled as coming from the page. A grant is remembered until it is revoked, appears in
t3 auth session list, and dies witht3 auth session revoke. Changing the title cannot inherit another origin's grant.The optional MCP URL
An entry can declare an MCP URL, which T3 merges into an agent session's
mcpServersbeside its ownt3-codeentry. That wiring already exists for one server (ClaudeAdapter.ts:3551,type: "http"plus an auth header) and is resolved per thread at session start, so a registered plugin's tools are available in every thread of that project. HTTP only, and no headers, which keeps T3 out of the business of storing your plugin's secrets. A plugin that already serves a page can serve/mcpfrom the same process, so this asks for no extra bridge.Tools show up to the agent as
mcp__<entry-name>__<tool>, the same shape as T3's ownmcp__t3-code__*tools.Part 3, the UI components (nice to have)
Move the UI primitives T3 already has, such as button, dialog, command palette, tooltip, and the form controls, into
@t3tools/uiwith the theme stylesheet beside them. A plugin page then renders the same components as the app around it. T3 keeps rendering the same code, and nothing changes visually.Parts 1 and 2 stand on their own, so this one can wait or be dropped.
Compatibility and safety
t3 auth session list.postMessageAPI.Questions for maintainers
Package names and which entry points are public and stable. Whether the one-time code should ride the URL fragment or wait for a real handoff channel. Whether
@t3tools/uishould be shared with external apps at all, or stay internal with a documented copy path.Related
#377 asked for a server SDK. #1582 proposed an extension system with a marketplace. #5020 proposed a Pi-style extension API. #6158 is an open local plugin implementation. #3993 was an earlier plugin attempt that closed after the orchestration foundation changed.
Update: this works today with no changes to T3 Code
Since orchestration V2, an outside web app can already do most of what this proposal asks for using the pairing flow T3 ships. You open the app in T3's browser panel, pair it once, and from then on it can start threads, follow them live, and link back to them in T3.
To build one you pair your app like any other client: make a pairing code in Settings > Sharing & access, swap it for a token at
POST /oauth/token, then open/wswith a ticket fromPOST /api/auth/websocket-ticket. After that it's normal RPC calls over the socket,launchThreadto start a thread andsubscribeThreadto watch it. HTTP calls need thex-t3-orchestration-protocol: 2header, the socket speaks Effect RPC as JSON so you have to ack every chunk, andvp run devneedsT3CODE_DEV_ALLOWED_ORIGINSset to your app's origin.What's still missing in T3 is the "Add plugin" tile that hands the page a thread id and code, a consent screen, an SDK, and skipping the "Open this t3code link?" prompt for T3's own thread links.
All reactions