refactor(think): remove convention framework - #2063
Conversation
🦋 Changeset detectedLatest commit: 53a1e8a The changes in this PR will be included in the next version bump. This PR includes changesets to release 2 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
| // Requests without a child segment belong to the directory itself | ||
| // (including `/chat` and `/chat/mcp-callback`). | ||
| if (url.pathname.startsWith(SUB_AGENT_PREFIX)) { | ||
| const childPath = url.pathname.slice(SUB_AGENT_PREFIX.length); | ||
| return routeSubAgentRequest(request, directory, { | ||
| fromPath: `/sub/${SUB_AGENT_SEGMENT}/${childPath}` | ||
| }); | ||
| } | ||
|
|
||
| return directory.fetch(request); |
There was a problem hiding this comment.
🟡 Chat links naming a non-existent sub-chat silently open the parent directory instead of returning not-found
A chat URL whose child segment does not name a real child class is handed straight to the user's directory (directory.fetch(request) at examples/assistant/src/server.ts:102) instead of being rejected, so a malformed chat link quietly opens the directory conversation rather than reporting that the chat does not exist.
Impact: Users following a bad or stale chat link get connected to their top-level directory instead of a clear "not found", which is confusing and hides typos in links.
Why the fallthrough happens: prefix match is class-specific, and the parent ignores unresolvable sub markers
SUB_AGENT_PREFIX is the literal /chat/sub/my-assistant/ (examples/assistant/src/server.ts:38-39). A request such as /chat/sub/other-thing/abc does not match that prefix, so it takes the directory.fetch(request) branch. Inside the parent, Agent.fetch parses the sub marker against ctx.exports keys (packages/agents/src/index.ts:7015-7021); other-thing resolves to no exported class, parseSubAgentPath returns null, and the request is served by the directory itself via super.fetch.
The removed implementation routed the whole /chat* space through think.router.routeSubAgent(...), which returned 404 whenever a /sub/... segment could not be resolved for the declared parent. To keep that contract, detect any /chat/sub/ path that is not the known child prefix and return 404 before falling back to the directory.
| // Requests without a child segment belong to the directory itself | |
| // (including `/chat` and `/chat/mcp-callback`). | |
| if (url.pathname.startsWith(SUB_AGENT_PREFIX)) { | |
| const childPath = url.pathname.slice(SUB_AGENT_PREFIX.length); | |
| return routeSubAgentRequest(request, directory, { | |
| fromPath: `/sub/${SUB_AGENT_SEGMENT}/${childPath}` | |
| }); | |
| } | |
| return directory.fetch(request); | |
| // Requests without a child segment belong to the directory itself | |
| // (including `/chat` and `/chat/mcp-callback`). | |
| if (url.pathname.startsWith(SUB_AGENT_PREFIX)) { | |
| const childPath = url.pathname.slice(SUB_AGENT_PREFIX.length); | |
| return routeSubAgentRequest(request, directory, { | |
| fromPath: `/sub/${SUB_AGENT_SEGMENT}/${childPath}` | |
| }); | |
| } | |
| // Any other `/chat/sub/...` shape names a child that does not | |
| // exist — reject it rather than serving the directory. | |
| if (url.pathname.startsWith("/chat/sub/")) { | |
| return new Response("Not found", { status: 404 }); | |
| } | |
| return directory.fetch(request); |
Was this helpful? React with 👍 or 👎 to provide feedback.
agents
@cloudflare/ai-chat
@cloudflare/codemode
hono-agents
@cloudflare/shell
@cloudflare/think
@cloudflare/voice
@cloudflare/worker-bundler
commit: |
|
Tagging @threepointone to check this is the surface you had in mind for removal |
This PR removes Think's convention-driven Vite framework and CLI while keeping
@cloudflare/thinkas an explicit runtime for hand-written Worker entries. It also retires the coupled scaffolding and host-framework examples. Fixes #2046.Why
create-thinkto static templates, but that would preserve the convention layer's maintenance surface. The supported direction is explicit Worker entries, exports, bindings, migrations, and routing.cloudflare/agents-starterrepository and does not depend on these removed surfaces.Public API Surface
These removals are breaking:
@cloudflare/think/viteagents/vitefor decorators andagents:skills, plus@cloudflare/vite-plugin@cloudflare/think/framework@cloudflare/think/server-entryrouteAgentRequest,routeSubAgentRequest, and application-owned handlersthinkbinarycreate-thinkThe Think runtime, React integration, messengers, workflows, extensions, and tool entrypoints remain available.
Architectural Changes
Before:
After:
Code Changes
@cloudflare/thinkno longer builds or publishes the Vite plugin, framework helpers, server-entry helpers, CLI, or Studio bundle. Package dependencies and test wiring now cover only the retained runtime.examples/assistantnow uses an explicit Worker entry androuteSubAgentRequest. It exports the readableAssistantDirectoryandMyAssistantruntime classes directly and declares the root binding and migration explicitly.CodemodeRuntime, and its Vite configuration usesagents/vitedirectly for bundled Agent Skills.packages/create-think, the sixthink-starters, and the React Router and TanStack Start framework examples are removed.Compatibility
virtual:think/entrywith an explicit Worker entry and declare their Durable Object exports, bindings, migrations, and routing.Class.name.create-thinkreleases fetch templates from the deletedthink-starterspaths and are not retained as a compatibility path.npm create cloudflarewithcloudflare/agents-starterremains unaffected because that repository already uses an explicit Worker setup.