Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/eve-extension-eve-0-83.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@upstash/agentkit-eve-extension": patch
---

Rebuild against eve 0.83.0 and raise the `eve` peer floor to `>=0.83.0`. The compiled extension now declares tool contract 102, dynamicTool 92 and hook 51, which only eve 0.83.0 accepts (0.82.0 and earlier reject them; eve 0.83.0 also rejects the tool 96 / dynamicTool 88 / hook 48 stamps of an eve 0.82.0 build).
5 changes: 5 additions & 0 deletions .changeset/eve-sandbox-eve-0-75.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@upstash/agentkit-eve": patch
---

`UpstashSandbox` now works on eve 0.75 and later: the provider handle uses eve's renamed `onSandboxStop` / `onSandboxDelete` hooks (the old names are never called by eve 0.75+, so boxes were not paused or deleted). `setNetworkPolicy` is typed by the exported `UpstashSandboxSession`, since eve removed `MutableNetworkSandboxSession`. The `eve` peer floor is raised to `>=0.75.0`.
5 changes: 5 additions & 0 deletions .changeset/tanstack-ai-activities-store.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@upstash/agentkit-tanstack-ai": minor
---

`upstashPersistence()` now includes an `activities` store (TanStack AI's `ActivityStore`): frontend-only AG-UI activity rows are persisted per thread in Redis, with the same TTL as the transcript, so they survive reloads and instance changes. It passes `@tanstack/ai-persistence` 0.10's conformance suite. Peer floors are raised to `@tanstack/ai` `>=0.65.0` and `@tanstack/ai-persistence` `>=0.8.0`.
13 changes: 8 additions & 5 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -126,9 +126,9 @@ implements TanStack AI's own backend contracts (see its section below) — keep
npm/yarn hoisted layouts — was fixed upstream in eve 0.25.3; no workaround needed on ≥0.25.3.)
**Consumer eve version:** `eve extension build` stamps the manifest's `requires` with the building
eve's *current* contribution-format versions, and a consumer rejects any version not in its own
supported list — the current dist, built with **eve 0.74.0**, stamps formatVersion 2; extension 1 /
**tool 78** / **dynamicTool 73** / **hook 39** / instructions 2 / config 1, which needs consumers on
**eve ≥0.74.0** — 0.74.0 is the first release accepting all three (0.72.0–0.73.0 refuse them: a pack of this dist built
supported list — the current dist, built with **eve 0.83.0**, stamps formatVersion 2; extension 1 /
**tool 102** / **dynamicTool 92** / **hook 51** / instructions 2 / config 1, which needs consumers on
**eve ≥0.83.0** — 0.83.0 is the first release accepting all three (0.82.0 refuses them, and **0.83.0 in turn refuses the 0.82.0 stamps 96/88/48** — verified by packing a 0.82.0-built dist into an `eve@0.83.0` consumer: "requires tool contract v96 … supports …"; 0.75.0–0.81.1 refuse them too; the 0.74.0 build stamped 78/73/39 with floor 0.74.0, published `0.16.0`; 0.72.0–0.73.0 refuse those: a pack of this dist built
against 0.72.0/0.72.1/0.73.0 fails `eve build` with the obtuse "has no compile or runtime usage" error; the intermediate
0.72.1 build stamped 76/72/38 with floor 0.72.0 and was never released; 0.72.0 **dropped tool 71–75**; the published dist, built with 0.69.0, stamped
71/68/35 with floor 0.69.0 and fails on eve ≥0.72.0). Earlier: 0.69.0 was the first release accepting any of 71/68/35 (0.65.0–0.68.0 accept none
Expand Down Expand Up @@ -164,7 +164,7 @@ implements TanStack AI's own backend contracts (see its section below) — keep
release's worth of headroom. Since ~0.50 eve also **drops** contracts out of the middle of its
supported range, so a *newer* eve is not automatically compatible either: the floor has repeatedly
landed on the pinned version itself, with **no back-compat window at all**.
The `eve` peer is **`">=0.74.0"`, not `"*"`** — issue #22 proved the wildcard is a trap: eve
The `eve` peer is **`">=0.83.0"`, not `"*"`** — issue #22 proved the wildcard is a trap: eve
0.33 dropped hook contracts ≤9 *nine hours* after 0.32 shipped, so a wildcard install succeeds and
then fails at `eve build` with a manifest error. The manifest is still the real compatibility tie;
the peer floor is the install-time guard. **On every eve devDep bump: rebuild, read the new
Expand Down Expand Up @@ -888,7 +888,7 @@ implements TanStack AI's own backend contracts (see its section below) — keep

## Eve framework facts
- **The repo is split (since 2026-09-30): `packages/eve-extension` + `examples/eve-extension-demo` are
on `eve@0.74.0` (extension peer `>=0.74.0`, since 2026-10-08; 0.70.0 / `>=0.70.0` and 0.72.1 / `>=0.72.0` were never released);
on `eve@0.83.0` (extension peer `>=0.83.0`, since 2026-10-23; `>=0.82.0` since 2026-10-22, never released; `>=0.74.0` since 2026-10-08; 0.70.0 / `>=0.70.0` and 0.72.1 / `>=0.72.0` were never released);
`packages/eve` + `examples/eve-demo` stay on `eve@0.65.0` (peer `>=0.65.0`)** — see the 0.68.0 → 0.69.0
and 0.65.0 → 0.68.0 bump notes below. Before that (2026-09-23)
it was one `eve@0.65.0` everywhere, with both packages declaring `eve: ">=0.65.0"`. (For one
Expand Down Expand Up @@ -1075,6 +1075,9 @@ implements TanStack AI's own backend contracts (see its section below) — keep
implementation needed **no** new member for 0.55.0 — `pnpm typecheck` is clean across all four packages.
Even the extension's compiled output is unchanged: **`_manifest.json` is the only file in
`packages/eve-extension/dist` that differs from published `0.10.0`.**
- **TanStack AI 1.0.0 (2026-10-22) is NOT applied yet; `packages/tanstack-ai` + `examples/tanstack-ai-demo` stay on 0.71.0 / ai-persistence 0.10.1.** Against 1.0.0 `src` builds and the persistence conformance suite passes, but `pnpm typecheck` fails in tests only: `chat()` now requires `threadId` (`middleware.test.ts`, `search-tools.test.ts`; 4 runtime failures "chat() needs a threadId"), and `ArtifactRecord` requires `blobKey` (`persistence.test.ts` fixtures). Also: `@tanstack/ai@1.0.0`'s own `.d.ts` has a broken import (`spawn.d.ts`: `import('../../..')`), so `skipLibCheck: false` consumers get TS2307 from upstream. New 1.0 contracts not implemented yet: `SessionIndexStore`, `CredentialStore` (BYOK). ai 7.0.149+ added the `interrupted` finish reason; `@ai-sdk/react` pins `ai` exactly, so keep it in step (`^4.0.154` for ai 7.0.150).
- **eve 0.83.0 (2026-10-23) is applied to the extension only; `packages/eve` stays on 0.82.0.** 0.83.0 dropped the 0.82.0 contract stamps (extension rebuild: tool 96→102, dynamicTool 88→92, hook 48→51; extension peer `>=0.83.0`) and also **broke `packages/eve/src/sandbox.ts`'s typing** (not migrated yet — needs a source change): `eve/sandbox/provider` no longer exports `SandboxProviderHandle`/`SandboxProviderResources`; `NetworkPolicy` lists are mutable `string[]` (ours are `readonly`); `SandboxSession` requires `writeFiles`; `SandboxPrepareContext` lost `resources`/`sourceRevision`; the connection no longer has `handle`/`sandbox`/`onSandboxDelete`. Until that migration lands, `packages/eve` + `examples/eve-demo` pin `eve ^0.82.0` (two eve versions in the workspace on purpose).
- **The 0.74.0 → 0.82.0 bump (2026-10-22) moves everything, with a source migration in `packages/eve`.** eve 0.75.0 renamed the sandbox provider handle hooks `onSessionStop`/`onSessionDelete` → `onSandboxStop`/`onSandboxDelete`, and eve 0.66.0 had removed `MutableNetworkSandboxSession` (network policy became provider-specific). `packages/eve/src/sandbox.ts` now declares its own `UpstashSandboxSession = SandboxSession & { setNetworkPolicy }` (exported; what `ctx.getSandbox(environment)` returns) and uses the new hook names, so the `eve` peer floor moved `>=0.65.0` → **`>=0.75.0`** (floor read off the 0.74.0 vs 0.75.0 tarballs: `onSessionStop` present vs absent in `shared/sandbox-provider.d.ts`; not verified by a full `tsc` against 0.75.0). `packages/eve` + `examples/eve-demo` are on eve ^0.82.0. The extension rebuild re-stamps **tool 78→96, dynamicTool 73→88, hook 39→48**; only 0.82.0 accepts them (0.75.0–0.81.1 do not), floor `>=0.74.0` → **`>=0.82.0`**. `upstashPersistence` gained an `activities` store (`ActivityStore`, one JSON doc per thread at `<prefix>:activities:<threadId>`, same TTL as messages) because `@tanstack/ai-persistence` ≥0.8.0's conformance suite requires it, so ai-persistence moves 0.7.2 → 0.10.1 and the peer floors become `@tanstack/ai` `>=0.65.0` (`ActivityRecord` type), `@tanstack/ai-persistence` `>=0.8.0` (`ActivityStore` type). ai 7.0.148, @tanstack/ai 0.71.0, -memory 0.2.16 and the demo packages are bumped.
- **The 0.72.1 → 0.74.0 bump (2026-10-08) is EXTENSION-ONLY again** (same reason: `packages/eve` still imports the removed
`MutableNetworkSandboxSession`, `TS2305` in `src/sandbox.ts`/`sandbox.test.ts` on 0.74.0; `packages/eve` + `examples/eve-demo` stay on 0.65.0). The rebuild re-stamps
**tool 76→78, dynamicTool 72→73, hook 38→39**; only 0.74.0 accepts them (verified by building the packed dist against a consumer on each of
Expand Down
4 changes: 2 additions & 2 deletions examples/ai-sdk-demo/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@
},
"dependencies": {
"@ai-sdk/openai": "^4.0.71",
"@ai-sdk/react": "^4.0.110",
"@ai-sdk/react": "^4.0.154",
"@upstash/agentkit-ai-sdk": "workspace:*",
"@upstash/agentkit-sdk": "workspace:*",
"@upstash/redis": "^1.38.4",
"ai": "7.0.133",
"ai": "7.0.150",
"dotenv": "^16.4.5",
"next": "16.2.9",
"react": "19.2.6",
Expand Down
4 changes: 2 additions & 2 deletions examples/eve-demo/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,11 @@
"@upstash/box": "^0.7.5",
"@upstash/redis": "^1.38.4",
"@vercel/connect": "0.2.2",
"ai": "7.0.133",
"ai": "7.0.150",
"class-variance-authority": "0.7.1",
"clsx": "2.1.1",
"cmdk": "1.1.1",
"eve": "^0.65.0",
"eve": "^0.82.0",
"lucide-react": "1.16.0",
"motion": "12.40.0",
"nanoid": "5.1.11",
Expand Down
4 changes: 2 additions & 2 deletions examples/eve-extension-demo/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@
"@upstash/agentkit-eve-extension": "workspace:*",
"@upstash/redis": "^1.38.4",
"@vercel/connect": "0.2.2",
"ai": "7.0.133",
"eve": "^0.74.0",
"ai": "7.0.150",
"eve": "^0.83.0",
"zod": "4.4.3"
},
"devDependencies": {
Expand Down
12 changes: 6 additions & 6 deletions examples/tanstack-ai-demo/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,12 @@
"e2e": "vitest run --config e2e/vitest.config.ts"
},
"dependencies": {
"@tanstack/ai": "0.65.1",
"@tanstack/ai-client": "0.38.0",
"@tanstack/ai-memory": "0.2.10",
"@tanstack/ai-openai": "0.27.0",
"@tanstack/ai-persistence": "0.7.2",
"@tanstack/ai-react": "0.30.0",
"@tanstack/ai": "0.71.0",
"@tanstack/ai-client": "0.40.1",
"@tanstack/ai-memory": "0.2.16",
"@tanstack/ai-openai": "0.31.0",
"@tanstack/ai-persistence": "0.10.1",
"@tanstack/ai-react": "0.31.1",
"@upstash/agentkit-tanstack-ai": "workspace:*",
"@upstash/redis": "^1.38.4",
"next": "16.2.9",
Expand Down
2 changes: 1 addition & 1 deletion packages/ai-sdk/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@
"@ai-sdk/openai": "^4.0.71",
"@ai-sdk/provider": "^4.0.17",
"@upstash/redis": "^1.38.4",
"ai": "7.0.133",
"ai": "7.0.150",
"dotenv": "^16.4.5"
},
"peerDependencies": {
Expand Down
2 changes: 1 addition & 1 deletion packages/eve-extension/AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ unavailable, use https://eve.dev/docs/extensions as a fallback.
agent-shaped source tree into `dist/extension/`, emits type declarations and a
compatibility manifest, and fills the package `exports` map. Ship `dist/` only.
`eve` is a required peer so the consumer's eve is the one that runs, but NOT a
wildcard: keep the floor (`>=0.74.0`) in sync with what the built manifest's
wildcard: keep the floor (`>=0.83.0`) in sync with what the built manifest's
contracts require, so an incompatible eve fails at install instead of at
`eve build` (see issue #22). eve validates the real compatibility from the
generated manifest.
2 changes: 1 addition & 1 deletion packages/eve-extension/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ no repeated schemas; upgrades come through the package manager.

`<ns>` is the mount file's basename — the examples below use `agentkit`.

Start from an eve project (eve ≥ 0.74.0 — the prebuilt extension is built with eve 0.74.0 and its compatibility manifest requires tool contract v78 (dynamicTool v73, hook v39), which eve 0.74.0 is the first release to support; the package declares this as its `eve` peer range), then:
Start from an eve project (eve ≥ 0.83.0 — the prebuilt extension is built with eve 0.83.0 and its compatibility manifest requires tool contract v102 (dynamicTool v92, hook v51), which eve 0.83.0 is the first release to support; the package declares this as its `eve` peer range), then:

```bash
pnpm add @upstash/agentkit-eve-extension
Expand Down
4 changes: 2 additions & 2 deletions packages/eve-extension/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -56,10 +56,10 @@
},
"devDependencies": {
"@types/node": "24.x",
"eve": "^0.74.0",
"eve": "^0.83.0",
"typescript": "7.0.2"
},
"peerDependencies": {
"eve": ">=0.74.0"
"eve": ">=0.83.0"
}
}
6 changes: 3 additions & 3 deletions packages/eve/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -60,14 +60,14 @@
"devDependencies": {
"@upstash/box": "^0.7.5",
"@upstash/redis": "^1.38.4",
"ai": "7.0.133",
"ai": "7.0.150",
"dotenv": "^16.4.5",
"eve": "^0.65.0"
"eve": "^0.82.0"
},
"peerDependencies": {
"@upstash/box": ">=0.7.1",
"@upstash/redis": ">=1.38.4",
"eve": ">=0.65.0"
"eve": ">=0.75.0"
},
"peerDependenciesMeta": {
"@upstash/box": {
Expand Down
20 changes: 10 additions & 10 deletions packages/eve/src/sandbox.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { config } from "dotenv";
import { afterEach, describe, expect, it, vi } from "vitest";
import { Box } from "@upstash/box";
import type { SandboxProviderImplementation } from "eve/sandbox/provider";
import type { MutableNetworkSandboxSession } from "eve/sandbox";
import type { UpstashSandboxSession } from "./sandbox.js";
import {
UpstashSandbox,
rewriteWorkspacePaths,
Expand All @@ -18,7 +18,7 @@ type Impl = SandboxProviderImplementation<
{ networkPolicy?: unknown } | undefined,
{ snapshotId: string | null },
{ boxId: string; version: 1 },
MutableNetworkSandboxSession
UpstashSandboxSession
>;

/**
Expand Down Expand Up @@ -237,16 +237,16 @@ describe("UpstashSandbox provider (offline)", () => {
vi.spyOn(Box, "create").mockResolvedValue(fakeBox(calls) as unknown as Box);
const { handle } = await implementationOf().start(sessionCtx(), undefined, noArtifact);

await handle.onSessionStop();
await handle.onSandboxStop();
await handle.onRuntimeShutdown();
expect(calls).toEqual(["pause", "pause"]);

await handle.onSessionDelete();
await handle.onSandboxDelete();
expect(calls).toEqual(["pause", "pause", "delete"]);

// Gone: repeat teardown is a no-op (eve can still call shutdown on a deleted handle).
await handle.onSessionDelete();
await handle.onSessionStop();
await handle.onSandboxDelete();
await handle.onSandboxStop();
await handle.onRuntimeShutdown();
expect(calls).toEqual(["pause", "pause", "delete"]);
});
Expand All @@ -256,15 +256,15 @@ describe("UpstashSandbox provider (offline)", () => {
box.pause.mockRejectedValue(new Error("keep-alive boxes cannot be paused"));
vi.spyOn(Box, "create").mockResolvedValue(box as unknown as Box);
const { handle } = await implementationOf().start(sessionCtx(), undefined, noArtifact);
await expect(handle.onSessionStop()).rejects.toThrow(/keep-alive/);
await expect(handle.onSandboxStop()).rejects.toThrow(/keep-alive/);
await expect(handle.onRuntimeShutdown()).resolves.toBeUndefined();
});

it("delete rejects an already-aborted signal without deleting", async () => {
const calls: string[] = [];
vi.spyOn(Box, "create").mockResolvedValue(fakeBox(calls) as unknown as Box);
const { handle } = await implementationOf().start(sessionCtx(), undefined, noArtifact);
await expect(handle.onSessionDelete({ abortSignal: AbortSignal.abort() })).rejects.toThrow();
await expect(handle.onSandboxDelete({ abortSignal: AbortSignal.abort() })).rejects.toThrow();
expect(calls).toEqual([]);
});
});
Expand Down Expand Up @@ -336,13 +336,13 @@ describe.skipIf(!hasBoxCreds)("UpstashSandbox provider (live Upstash Box)", () =

// stop = pause; resume reattaches the SAME box (state survives), network policy included.
await s.writeTextFile({ path: "turn1.txt", content: "kept" });
await handle.onSessionStop();
await handle.onSandboxStop();
const resumed = await impl.resume(sessionCtx("live"), artifact, state);
expect(await resumed.sandbox.readTextFile({ path: "turn1.txt" })).toBe("kept");
expect((await resumed.sandbox.run({ command: fetchCmd })).exitCode).toBe(0);

// delete = gone for good; resuming it now fails instead of silently making a new box.
await resumed.onSessionDelete();
await resumed.onSandboxDelete();
await expect(impl.resume(sessionCtx("live"), artifact, state)).rejects.toThrow(
/no longer available/,
);
Expand Down
Loading
Loading