Skip to content

refactor(think): remove convention framework - #2063

Open
cjol wants to merge 1 commit into
mainfrom
investigate-2046
Open

refactor(think): remove convention framework#2063
cjol wants to merge 1 commit into
mainfrom
investigate-2046

Conversation

@cjol

@cjol cjol commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

This PR removes Think's convention-driven Vite framework and CLI while keeping @cloudflare/think as an explicit runtime for hand-written Worker entries. It also retires the coupled scaffolding and host-framework examples. Fixes #2046.

Why

  • The experimental framework generated Worker entries, virtual modules, Durable Object exports, routes, Wrangler configuration, and types from repository conventions. This created a second configuration layer over standard Workers and Agents primitives.
  • The Vite plugin and CLI shipped with an explicit warning that they could change or be removed in any release.
  • We could retain compatibility stubs or convert create-think to static templates, but that would preserve the convention layer's maintenance surface. The supported direction is explicit Worker entries, exports, bindings, migrations, and routing.
  • Create Cloudflare remains available through the separate cloudflare/agents-starter repository and does not depend on these removed surfaces.

Public API Surface

These removals are breaking:

Surface Change Replacement
@cloudflare/think/vite Removed agents/vite for decorators and agents:skills, plus @cloudflare/vite-plugin
@cloudflare/think/framework Removed Explicit Worker classes and configuration
@cloudflare/think/server-entry Removed routeAgentRequest, routeSubAgentRequest, and application-owned handlers
think binary Removed Wrangler, Vite, and explicit source/configuration files
create-think Removed from the repository Create Cloudflare or a manually configured Think Worker

The Think runtime, React integration, messengers, workflows, extensions, and tool entrypoints remain available.

Architectural Changes

Before:

agents/ conventions
        |
@cloudflare/think/vite
        |
virtual:think/* modules
        |
generated Worker entry, exports, routing, types, and config

After:

Think subclasses
        |
explicit src/server.ts exports and routing
        |
explicit wrangler.jsonc bindings and migrations
        |
agents/vite + @cloudflare/vite-plugin where needed

Code Changes

  • @cloudflare/think no 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/assistant now uses an explicit Worker entry and routeSubAgentRequest. It exports the readable AssistantDirectory and MyAssistant runtime classes directly and declares the root binding and migration explicitly.
  • The explicit Assistant entry exports CodemodeRuntime, and its Vite configuration uses agents/vite directly for bundled Agent Skills.
  • packages/create-think, the six think-starters, and the React Router and TanStack Start framework examples are removed.
  • Current Think documentation now shows explicit Worker exports, Wrangler bindings and migrations, routing, and Agent Skills plugin registration.
  • Workspace, lockfile, changeset, package-build, test-matrix, and reproduction-skill wiring no longer reference the deleted projects.

Compatibility

  • Applications using the removed Vite plugin must replace virtual:think/entry with an explicit Worker entry and declare their Durable Object exports, bindings, migrations, and routing.
  • Persistently deployed applications must preserve their generated Durable Object class names and migration history when moving to explicit entries. TypeScript aliases alone are not enough when sub-agent registries depend on Class.name.
  • Historical create-think releases fetch templates from the deleted think-starters paths and are not retained as a compatibility path.
  • npm create cloudflare with cloudflare/agents-starter remains unaffected because that repository already uses an explicit Worker setup.

Open in Devin Review

@changeset-bot

changeset-bot Bot commented Aug 6, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 53a1e8a

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 2 packages
Name Type
@cloudflare/think Minor
@cloudflare/agent-think Patch

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

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devin Review found 1 potential issue.

View 1 additional finding in Devin Review.

Open in Devin Review

Comment on lines +93 to +102
// 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);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 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.

Suggested change
// 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);
Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

@pkg-pr-new

pkg-pr-new Bot commented Aug 6, 2026

Copy link
Copy Markdown

Open in StackBlitz

agents

npm i https://pkg.pr.new/agents@2063

@cloudflare/ai-chat

npm i https://pkg.pr.new/@cloudflare/ai-chat@2063

@cloudflare/codemode

npm i https://pkg.pr.new/@cloudflare/codemode@2063

hono-agents

npm i https://pkg.pr.new/hono-agents@2063

@cloudflare/shell

npm i https://pkg.pr.new/@cloudflare/shell@2063

@cloudflare/think

npm i https://pkg.pr.new/@cloudflare/think@2063

@cloudflare/voice

npm i https://pkg.pr.new/@cloudflare/voice@2063

@cloudflare/worker-bundler

npm i https://pkg.pr.new/@cloudflare/worker-bundler@2063

commit: 53a1e8a

@cjol

cjol commented Aug 6, 2026

Copy link
Copy Markdown
Contributor Author

Tagging @threepointone to check this is the surface you had in mind for removal

@cjol
cjol requested a review from threepointone August 6, 2026 14:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

remove the think vite plugin and cli

1 participant