Skip to content

Commit c717193

Browse files
committed
feat: initial scaffold
Vue 3 composable for Cloudflare Agents — a port of @cloudflare/ai-chat/react's useAgentChat hook, adapted to the Vue Composition API and @ai-sdk/vue. Public surface: - useAgentChat<AgentT, ChatMessage, State>(options) - WebSocketChatTransport (renamed from upstream) Tested in chromium browser mode (vitest-browser-vue), 59 tests covering clearHistory, autoContinue variants, addToolApprovalResponse, body option (static/sync/async), tool result/approval continuations, stream resumption, broadcast handling, lifecycle, and partial-hydration rebuild. Bug fixes vs the original Eslyn port: - addToolApprovalResponse now bails early on no match instead of crashing the AI SDK with undefined.parts. - preserveActiveStreamMessages adopts a broadcast's authoritative assistant id via tool-call overlap so continuations merge cleanly when the server remaps mid-stream.
0 parents  commit c717193

17 files changed

Lines changed: 8332 additions & 0 deletions

.github/workflows/ci.yml

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
name: CI
2+
3+
on:
4+
push:
5+
branches: [main]
6+
tags: ['v*']
7+
pull_request:
8+
branches: [main]
9+
10+
permissions:
11+
contents: read
12+
13+
jobs:
14+
check:
15+
runs-on: ubuntu-latest
16+
steps:
17+
- uses: actions/checkout@v4
18+
- uses: pnpm/action-setup@v4
19+
- uses: actions/setup-node@v4
20+
with:
21+
node-version: 22
22+
cache: pnpm
23+
- run: pnpm install --frozen-lockfile
24+
- run: pnpm exec playwright install chromium --with-deps
25+
- run: pnpm lint
26+
- run: pnpm typecheck
27+
- run: pnpm test
28+
- run: pnpm build
29+
30+
publish:
31+
needs: check
32+
if: startsWith(github.ref, 'refs/tags/v')
33+
runs-on: ubuntu-latest
34+
permissions:
35+
contents: read
36+
id-token: write
37+
steps:
38+
- uses: actions/checkout@v4
39+
- uses: pnpm/action-setup@v4
40+
- uses: actions/setup-node@v4
41+
with:
42+
node-version: 22
43+
cache: pnpm
44+
registry-url: 'https://registry.npmjs.org'
45+
- run: pnpm install --frozen-lockfile
46+
- run: pnpm build
47+
- run: pnpm publish --no-git-checks --access public
48+
env:
49+
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}

.gitignore

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
node_modules/
2+
dist/
3+
coverage/
4+
5+
# Vitest browser mode failure artifacts (screenshots, attachments)
6+
.vitest-attachments/
7+
__screenshots__/
8+
9+
*.log
10+
.DS_Store
11+
.idea/
12+
.vscode/

LICENSE

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
MIT License
2+
3+
Copyright (c) 2026 Yusuf Mansur Özer
4+
Portions copyright (c) 2025 Cloudflare, Inc. — original React
5+
implementation in @cloudflare/ai-chat (https://github.com/cloudflare/agents)
6+
7+
Permission is hereby granted, free of charge, to any person obtaining a copy
8+
of this software and associated documentation files (the "Software"), to deal
9+
in the Software without restriction, including without limitation the rights
10+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11+
copies of the Software, and to permit persons to whom the Software is
12+
furnished to do so, subject to the following conditions:
13+
14+
The above copyright notice and this permission notice shall be included in all
15+
copies or substantial portions of the Software.
16+
17+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23+
SOFTWARE.

README.md

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
# agents-vue
2+
3+
Vue 3 composable for [Cloudflare Agents](https://github.com/cloudflare/agents) — a port of `@cloudflare/ai-chat/react`'s `useAgentChat` hook to the Vue Composition API and `@ai-sdk/vue`.
4+
5+
> `agents-vue` is a Vue 3 port of [`@cloudflare/ai-chat`](https://github.com/cloudflare/agents/tree/main/packages/ai-chat)'s `useAgentChat` React hook. The protocol, semantics, and most of the algorithmic structure come directly from the upstream React implementation. This package adapts it to the Vue Composition API and `@ai-sdk/vue`.
6+
7+
## Status
8+
9+
v0.1 — early scaffold. The composable surface (`useAgentChat`, `WebSocketChatTransport`) lands in the first published release.
10+
11+
## Install
12+
13+
```bash
14+
pnpm add agents-vue
15+
```
16+
17+
Peer dependencies:
18+
19+
- `vue ^3.3.4`
20+
- `@ai-sdk/vue ^3.0.0`
21+
- `ai ^6.0.0`
22+
- `agents >=0.11.0 <1.0.0`
23+
24+
## Usage
25+
26+
```ts
27+
// Coming with v0.1.0 — see the changelog.
28+
```
29+
30+
## SSR
31+
32+
`agents-vue` is **client-only**. The composable opens a WebSocket on construction and will throw on Node / SSR contexts. Wrap call sites in `<ClientOnly>` (Nuxt) or defer to `onMounted`.
33+
34+
## License
35+
36+
MIT — see [LICENSE](./LICENSE). Includes attribution to the original Cloudflare React implementation.

build.config.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import { defineBuildConfig } from "unbuild";
2+
3+
export default defineBuildConfig({
4+
entries: ["src/index"],
5+
declaration: true,
6+
rollup: {
7+
emitCJS: false,
8+
},
9+
externals: ["vue", "ai", "@ai-sdk/vue", "agents", "agents/client", "agents/chat"],
10+
});

eslint.config.js

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import js from "@eslint/js";
2+
import tseslint from "typescript-eslint";
3+
4+
export default tseslint.config(
5+
{
6+
ignores: ["dist/", "node_modules/", "coverage/"],
7+
},
8+
js.configs.recommended,
9+
...tseslint.configs.recommended,
10+
{
11+
languageOptions: {
12+
ecmaVersion: 2022,
13+
sourceType: "module",
14+
},
15+
rules: {
16+
"@typescript-eslint/no-unused-vars": [
17+
"error",
18+
{ argsIgnorePattern: "^_", varsIgnorePattern: "^_", caughtErrorsIgnorePattern: "^_" },
19+
],
20+
},
21+
},
22+
);

package.json

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
{
2+
"name": "agents-vue",
3+
"version": "0.0.0",
4+
"description": "Vue 3 composable for Cloudflare Agents — a port of @cloudflare/ai-chat/react's useAgentChat.",
5+
"keywords": [
6+
"vue",
7+
"vue3",
8+
"cloudflare",
9+
"agents",
10+
"ai",
11+
"chat",
12+
"websocket",
13+
"ai-sdk",
14+
"composable"
15+
],
16+
"homepage": "https://github.com/ymansurozer/agents-vue",
17+
"bugs": "https://github.com/ymansurozer/agents-vue/issues",
18+
"repository": {
19+
"type": "git",
20+
"url": "git+https://github.com/ymansurozer/agents-vue.git"
21+
},
22+
"license": "MIT",
23+
"author": "Yusuf Mansur Özer",
24+
"type": "module",
25+
"sideEffects": false,
26+
"exports": {
27+
".": {
28+
"types": "./dist/index.d.mts",
29+
"import": "./dist/index.mjs"
30+
}
31+
},
32+
"main": "./dist/index.mjs",
33+
"module": "./dist/index.mjs",
34+
"types": "./dist/index.d.mts",
35+
"files": [
36+
"dist",
37+
"LICENSE",
38+
"README.md",
39+
"CHANGELOG.md"
40+
],
41+
"scripts": {
42+
"dev": "unbuild --watch",
43+
"build": "unbuild",
44+
"test": "vitest run",
45+
"test:watch": "vitest",
46+
"lint": "eslint .",
47+
"lint:fix": "eslint . --fix",
48+
"typecheck": "vue-tsc --noEmit",
49+
"release": "pnpm run lint && pnpm run typecheck && pnpm run test && pnpm run build && changelogen --release && git push --follow-tags"
50+
},
51+
"peerDependencies": {
52+
"@ai-sdk/vue": "^3.0.0",
53+
"agents": ">=0.11.0 <1.0.0",
54+
"ai": "^6.0.0",
55+
"vue": "^3.3.4"
56+
},
57+
"devDependencies": {
58+
"@ai-sdk/vue": "^3.0.0",
59+
"@eslint/js": "^9.0.0",
60+
"@types/node": "^22.0.0",
61+
"@vitest/browser": "^4.1.5",
62+
"@vitest/browser-playwright": "^4.1.5",
63+
"agents": "^0.11.4",
64+
"ai": "^6.0.0",
65+
"changelogen": "^0.6.2",
66+
"eslint": "^9.0.0",
67+
"playwright": "^1.49.0",
68+
"typescript": "^5.6.0",
69+
"typescript-eslint": "^8.0.0",
70+
"unbuild": "^3.0.0",
71+
"vitest": "^4.1.5",
72+
"vitest-browser-vue": "^2.1.0",
73+
"vue": "^3.5.0",
74+
"vue-tsc": "^3.0.0"
75+
},
76+
"publishConfig": {
77+
"access": "public"
78+
},
79+
"engines": {
80+
"node": ">=20"
81+
},
82+
"packageManager": "pnpm@9.0.0"
83+
}

0 commit comments

Comments
 (0)