Skip to content

Commit 595412f

Browse files
committed
chore(web): remove dead OpenNext/Cloudflare machinery now that web is on Vercel
Web is hosted on Vercel, so strip the CF-web build/deploy artifacts from apps/web: - scripts: build -> 'next build' (was opennext build); drop deploy/preview/upload/ cf-typegen (web deploys via Vercel CI now). - next.config: drop output:standalone + the OpenNext dev shim (pure Vercel build). - delete apps/web/wrangler.jsonc + open-next.config.ts (dead). (The @opennextjs/cloudflare + wrangler devDeps are now unused but left in place to avoid lockfile churn right after a verified deploy; prune in a follow-up.) Includes other in-tree changes: Composio tool-list hardening + doc updates.
1 parent 76d7dc8 commit 595412f

10 files changed

Lines changed: 54 additions & 120 deletions

File tree

AGENTS.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ explicitly asks to delete the V1 code by name — see `plan.md` Section 20.
2222
| Database | Supabase Postgres via Hyperdrive + Drizzle 0.45.2 |
2323
| Auth | Clerk 7.3.4 |
2424
| Billing | Polar 0.46.4 |
25-
| OAuth tools | Composio `@composio/core@0.8.1` |
25+
| OAuth tools | Composio `@composio/core@0.10.0` |
2626
| Storage | R2 (no Supabase Storage) |
2727
| Observability | Workers Logs + Workers Tracing + Workers Analytics Engine (no third-party APM in V1) |
2828
| Lint/format | Biome 2.4 (single config, no ESLint+Prettier except next plugin) |

CLAUDE.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ Direct competitors: Manus (generalist async agent), HappyCapy (GUI workstation +
2121
| Database | **Supabase Postgres via Cloudflare Hyperdrive** + **Drizzle 0.45.2** (no `service_role` from Workers — uses `app_worker` role) |
2222
| Auth | **Clerk 7.3.4** (Workers JWT verify) |
2323
| Billing | **Polar 0.46.4** (no fixed cost, rev-share only) |
24-
| OAuth tool integrations | **Composio `@composio/core@0.8.1`** |
24+
| OAuth tool integrations | **Composio `@composio/core@0.10.0`** |
2525
| Storage | **R2** (no Supabase Storage; zero egress) |
2626
| Observability | **Cloudflare Workers Logs + Workers Tracing + Workers Analytics Engine** — no Sentry, no Langfuse, no Axiom |
2727
| Default models | Claude Sonnet 4.6 (code) / GPT-5.4 Thinking (reasoning) / GPT-5.4 Mini fallback |

apps/web/next-env.d.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/// <reference types="next" />
22
/// <reference types="next/image-types/global" />
3-
import "./.next/dev/types/routes.d.ts";
3+
import "./.next/types/routes.d.ts";
44

55
// NOTE: This file should not be edited
66
// see https://nextjs.org/docs/app/api-reference/config/typescript for more information.

apps/web/next.config.ts

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -8,20 +8,8 @@ const nextConfig = {
88
qualities: [75],
99
minimumCacheTTL: 14_400,
1010
},
11-
// `standalone` is required by the OpenNext/Cloudflare build but conflicts with
12-
// Vercel's managed output, so emit it everywhere EXCEPT Vercel builds.
13-
...(process.env["VERCEL"] ? {} : { output: "standalone" as const }),
1411
} satisfies NextConfig;
1512

1613
const withNextIntl = createNextIntlPlugin("./src/lib/intl/request.ts");
1714

1815
export default withNextIntl(nextConfig);
19-
20-
// Local-dev only: wire OpenNext's Cloudflare binding shim for `next dev`. Loaded
21-
// via dynamic import behind a dev guard so production builds (incl. Vercel, which
22-
// has no @opennextjs/cloudflare and no CF runtime) never resolve it.
23-
if (process.env["NODE_ENV"] === "development") {
24-
void import("@opennextjs/cloudflare")
25-
.then((m) => m.initOpenNextCloudflareForDev())
26-
.catch(() => undefined);
27-
}

apps/web/open-next.config.ts

Lines changed: 0 additions & 17 deletions
This file was deleted.

apps/web/package.json

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,10 @@
55
"type": "module",
66
"packageManager": "pnpm@10.33.2",
77
"scripts": {
8-
"build": "next build --webpack && opennextjs-cloudflare build --skipNextBuild",
9-
"cf-typegen": "wrangler types --env-interface CloudflareEnv cloudflare-env.d.ts",
10-
"deploy": "CHEATCODE_REQUIRE_WEB_PUBLIC_ENV=true tsx ../../scripts/require-production-approval.ts && NEXT_PUBLIC_GATEWAY_URL=https://gateway.trycheatcode.com pnpm build && opennextjs-cloudflare deploy",
8+
"build": "next build",
119
"dev": "next dev --webpack",
1210
"lint": "biome check .",
13-
"preview": "pnpm build && opennextjs-cloudflare preview -- --port 3001",
14-
"typecheck": "tsc -p tsconfig.json --noEmit",
15-
"upload": "CHEATCODE_REQUIRE_WEB_PUBLIC_ENV=true tsx ../../scripts/require-production-approval.ts && NEXT_PUBLIC_GATEWAY_URL=https://gateway.trycheatcode.com pnpm build && opennextjs-cloudflare upload"
11+
"typecheck": "tsc -p tsconfig.json --noEmit"
1612
},
1713
"dependencies": {
1814
"@ai-sdk/react": "catalog:",

apps/web/wrangler.jsonc

Lines changed: 0 additions & 80 deletions
This file was deleted.

packages/agent-core/src/mastra/tools/composio-tool.ts

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,18 @@ const COMPOSIO_LIST_LIMIT = 500;
1818
// The SDK default base URL is already backend.composio.dev; pin it explicitly so a
1919
// future SDK default change can't silently repoint Workers at an unresolvable host.
2020
const COMPOSIO_BASE_URL = "https://backend.composio.dev";
21+
// Concrete toolkit versions pinned for deterministic discovery + execution. Without a
22+
// pin the SDK uses base version 00000000_00 (which can expose fewer actions than the
23+
// live toolkit), and "latest" would make manual tools.execute throw
24+
// ComposioToolVersionRequiredError. Fetched from GET /api/v3/toolkits/<slug> -> meta.version
25+
// on 2026-06-16; bump periodically. The LLM-supplied `version` in composio_execute still overrides.
26+
const COMPOSIO_TOOLKIT_VERSIONS: Record<string, string> = {
27+
github: "20260501_01",
28+
gmail: "20260615_00",
29+
linear: "20260615_00",
30+
notion: "20260615_00",
31+
slack: "20260615_00",
32+
};
2133
const composioIntegrationNameSchema = z.enum(["github", "gmail", "slack", "notion", "linear"]);
2234

2335
const requestContextReaderSchema = {
@@ -174,7 +186,12 @@ interface BoundedJson {
174186
// actually fires.
175187
async function createComposioToolClient(apiKey: string): Promise<ComposioToolClient> {
176188
const { Composio } = await import("@composio/core");
177-
const composio = new Composio({ allowTracking: false, apiKey, baseURL: COMPOSIO_BASE_URL });
189+
const composio = new Composio({
190+
allowTracking: false,
191+
apiKey,
192+
baseURL: COMPOSIO_BASE_URL,
193+
toolkitVersions: COMPOSIO_TOOLKIT_VERSIONS,
194+
});
178195
return {
179196
execute: (slug, body) => composio.tools.execute(slug, body),
180197
getRawTools: (options) => composio.tools.getRawComposioTools(options),

plan.md

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,7 @@ catalog:
163163
'@clerk/backend': 3.4.9
164164
'@clerk/nextjs': 7.3.4
165165
'@polar-sh/sdk': 0.46.4
166-
'@composio/core': 0.8.1
166+
'@composio/core': 0.10.0
167167
# ── Data ──
168168
drizzle-orm: 0.45.2
169169
pg: 8.21.0 # Required by Hyperdrive + Drizzle node-postgres setup (§7.3); omitted in the original catalog.
@@ -6421,6 +6421,35 @@ skill_invoke, skill_read_reference
64216421
64226422
**Naming rules:** domain-first (LLM intent matches better), verb after, snake_case, ≤6 properties per tool (split if larger). Destructive or production-impacting actions require explicit first-class user commands and audit logging; V1 has no generic approve/reject tool gate.
64236423
6424+
**Integration approach (deliberate — verified 2026-06-16):** The agent calls
6425+
`@composio/core`'s low-level `tools.getRawComposioTools` (framework-agnostic
6426+
discovery) and `tools.execute` directly, with **no Composio provider** set, and
6427+
hand-wraps them in exactly two Mastra `createTool` meta-tools
6428+
(`composio_list_tools` for runtime discovery, `composio_execute` for the
6429+
action). Discovery projects each raw action to `{ slug, name, description,
6430+
inputParameters, version, isDeprecated }` — the fields needed to then call
6431+
`composio_execute` — rather than the default `OpenAIProvider` function envelope.
6432+
Discovery passes the documented max `limit` (500; the API silently caps at ~20
6433+
otherwise — github alone has 800+ actions) and accepts an optional `search`
6434+
keyword so the model can narrow large toolkits server-side; the projected list is
6435+
bounded into **valid JSON** by whole-tool count (never sliced mid-object). The
6436+
client pins concrete per-toolkit `toolkitVersions` (fetched from
6437+
`GET /api/v3/toolkits/<slug>` → `meta.version`) so discovery and `tools.execute`
6438+
agree on one version and manual execute never throws `ComposioToolVersionRequiredError`;
6439+
it also sets `baseURL` (= the SDK default `backend.composio.dev`, pinned) and
6440+
`allowTracking: false` (no edge telemetry fetches). The LLM sees only these two
6441+
tools — never N expanded per-action tools — so the tool list and token budget
6442+
stay bounded. `@composio/core`
6443+
(~1.2 MB) is dynamically `import()`-ed only when a tool fires, to stay under the
6444+
Worker startup-CPU limit; per-request BYOK key, `userId`, and
6445+
`connectedAccountId` are injected via Mastra `requestContext`. We deliberately
6446+
do **not** use the framework providers `@composio/vercel` (emits a Vercel AI SDK
6447+
`ToolSet`) or `@composio/mastra` (emits Mastra `createTool`s): both expand every
6448+
action into its own tool, build the tool set eagerly, and capture a `Composio`
6449+
instance at construction — which would regress the bounded tool surface, the
6450+
lazy-import mitigation, and per-request BYOK/quota control. They are additive on
6451+
top of `@composio/core`, not equivalent to it.
6452+
64246453
**Composio execution contract:** `composio_list_tools` lists actions for an
64256454
active user-connected integration. `composio_execute` resolves the user's
64266455
`connectedAccountId` from `v2_user_integrations`, meters the call through the

research-log.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ Major SDK decisions verified before Week 1 implementation.
44

55
| Date | Source | Version / Topic | Implementation implication | Plan status |
66
|---|---|---|---|---|
7+
| 2026-06-16 | Context7 `/composiohq/composio`, npm registry (`@composio/vercel`, `@composio/mastra`), Vercel AI SDK v6 `tool()` spec, codebase `packages/agent-core/src/mastra/tools/composio-tool.ts` | `@composio/core` pin + the `@composio/vercel` "equivalence" claim | `@composio/core` is now pinned at **0.10.0** (was 0.8.1; `pnpm-workspace.yaml:17` was already correct, docs had drifted). `@composio/vercel` is a real, maintained, *separate* package (peer-deps `@composio/core` + `ai ^5\|\|^6`) whose `VercelProvider` wraps each action into a Vercel AI SDK `tool()` (`ToolSet`) and auto-executes via the SDK loop; `@composio/mastra` (`MastraProvider`) is the canonical Mastra provider. Both are **additive** (sit on top of `@composio/core`) and **not equivalent** to our usage: we call `@composio/core`'s `tools.get`/`tools.execute` directly with **no provider** (so the SDK's silent default `OpenAIProvider` is irrelevant), wrapped in two Mastra `createTool` meta-tools. The prior note that "`@composio/core` via Mastra is equivalent to `@composio/vercel` — no new dep" had the right conclusion (no new dep) but wrong framing (Mastra does not integrate Composio for us; "equivalent" is false). | KEEP the 2-meta-tool pattern; do **not** adopt `@composio/vercel`/`@composio/mastra` (they would expand to N eager tools, bind a `Composio` at construction, and defeat the lazy-import startup-CPU mitigation + per-request BYOK/quota control). plan.md §4 catalog + §25, CLAUDE.md, AGENTS.md updated 0.8.1→0.10.0. |
78
| 2026-05-28 | Context7 `/vercel/ai`, Context7 `/browserbase/stagehand`, Firecrawl scrape of official Gemini pricing, npm registry | Google/Gemini BYOK runtime support | Current AI SDK docs use `@ai-sdk/google` and `createGoogle(...)` / `google("gemini-2.5-flash")`; Stagehand v3 docs support `model: "google/gemini-2.5-flash"` with `GOOGLE_GENERATIVE_AI_API_KEY`. npm reports latest stable `@ai-sdk/google@3.0.80`, depending on provider v3 utilities compatible with AI SDK v6. Official Gemini pricing lists `gemini-2.5-flash` paid-tier pricing at `$0.30 / MTok` input and `$2.50 / MTok` output. | Confirms the existing `google` BYOK provider should be wired into agent model selection, budget estimation, and Stagehand browser credentials instead of remaining validation-only; `plan.md` Section 4 and catalog updated. |
89
| 2026-05-28 | Context7 `/vercel/ai`, Context7 `/mastra-ai/mastra`, npm registry | AI SDK v6 peer alignment with Mastra 1.35 | Current AI SDK docs still use `@ai-sdk/react` with `DefaultChatTransport` from `ai`, and Mastra docs require `toAISdkStream(..., { version: "v6" })` for AI SDK v6 streams. `@mastra/core@1.35.0` depends on `chat@^4.24.0`; current resolution `chat@4.29.0` peers `ai@^6.0.182`, and `@ai-sdk/react@3.0.184` depends on exactly `ai@6.0.182`. | Contradicted prior `ai@6.0.84` / `@ai-sdk/react@3.0.86` pins; `plan.md` Section 4 and the catalog were updated before continuing. |
910
| 2026-05-26 | npm registry | `remend@0.3.2` unavailable; `remend@1.3.0` current | Lockfile sync failed because the plan-pinned `remend@0.3.2` no longer exists in the npm registry. `streamdown@2.5.0` declares `remend@1.3.0`, and `pnpm view remend version` reports `1.3.0`; Section 4 and the catalog were updated before implementation continued. | Contradicted plan; updated plan/catalog to `remend@1.3.0`. |

0 commit comments

Comments
 (0)