Skip to content

Commit b2fc217

Browse files
authored
Merge pull request #277 from cloudflare/feat/client-sdk
Feat: Client SDK for vibesdk
2 parents ee7a83f + e68369b commit b2fc217

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

45 files changed

+2959
-177
lines changed

.husky/pre-commit

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
# Add common bun installation paths to PATH
22
export PATH="/opt/homebrew/bin:$HOME/.bun/bin:$PATH"
33

4+
# Never run SDK integration tests in pre-commit.
5+
unset VIBESDK_RUN_INTEGRATION_TESTS
6+
47
# Optional override flags
58
# - SKIP_TESTS=1: skip all pre-commit checks
69
# - RUN_ALL_TESTS=1: run full suite instead of related
@@ -36,7 +39,7 @@ fi
3639
# Exclude heavy directories that are not relevant at commit time.
3740
if [ "${RUN_ALL_TESTS:-}" = "1" ]; then
3841
echo "[pre-commit] RUN_ALL_TESTS=1 set; running full test suite"
39-
bunx vitest run --passWithNoTests --exclude "container/**" --exclude "generated/**"
42+
bunx vitest run --passWithNoTests --exclude "container/**" --exclude "generated/**" --exclude "sdk/test/integration/**"
4043
exit $?
4144
fi
4245

@@ -63,4 +66,4 @@ EOF
6366

6467
echo "[pre-commit] Running related tests for staged files"
6568
# Vitest takes file paths as filters.
66-
bunx vitest related --run --passWithNoTests --exclude "container/**" --exclude "generated/**" "$@"
69+
bunx vitest related --run --passWithNoTests --exclude "container/**" --exclude "generated/**" --exclude "sdk/test/integration/**" "$@"

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
"tui": "tsx --tsconfig tsconfig.app.json cli/tui.tsx",
1717
"cf-typegen": "wrangler types --include-runtime false",
1818
"test": "vitest run",
19+
"test:integration": "VIBESDK_RUN_INTEGRATION_TESTS=1 vitest run sdk/test/integration/integration.test.ts",
1920
"test:watch": "vitest",
2021
"test:coverage": "vitest run --coverage",
2122
"test:bun": "bun run vitest run",

sdk/README.md

Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
# @cf-vibesdk/sdk
2+
3+
Client SDK for the VibeSDK platform.
4+
5+
## Install
6+
7+
```bash
8+
npm install @cf-vibesdk/sdk
9+
```
10+
11+
## Quickstart (Bun)
12+
13+
```ts
14+
import { PhasicClient } from '@cf-vibesdk/sdk';
15+
16+
const client = new PhasicClient({
17+
baseUrl: 'http://localhost:5173',
18+
apiKey: process.env.VIBESDK_API_KEY!,
19+
});
20+
21+
const session = await client.build('Build a simple hello world page.', {
22+
projectType: 'app',
23+
autoGenerate: true,
24+
});
25+
26+
// High-level lifecycle waits
27+
await session.wait.generationStarted();
28+
await session.wait.deployable();
29+
30+
// Preview deployment (command + awaitable)
31+
const previewWait = session.wait.previewDeployed();
32+
session.deployPreview();
33+
const deployed = await previewWait;
34+
35+
console.log('Preview URL:', deployed.previewURL);
36+
37+
// Workspace is always kept in sync from agent state + WS events
38+
console.log(session.files.listPaths());
39+
console.log(session.files.read('README.md'));
40+
41+
session.close();
42+
```
43+
44+
## Quickstart (Node)
45+
46+
Node requires a WebSocket factory (the browser `WebSocket` global is not available):
47+
48+
```ts
49+
import { PhasicClient } from '@cf-vibesdk/sdk';
50+
import { createNodeWebSocketFactory } from '@cf-vibesdk/sdk/node';
51+
52+
const client = new PhasicClient({
53+
baseUrl: 'http://localhost:5173',
54+
apiKey: process.env.VIBESDK_API_KEY!,
55+
webSocketFactory: createNodeWebSocketFactory(),
56+
});
57+
58+
const session = await client.build('Build a simple hello world page.', {
59+
projectType: 'app',
60+
autoGenerate: true,
61+
});
62+
63+
await session.wait.generationStarted();
64+
await session.wait.deployable();
65+
session.close();
66+
```
67+
68+
## Authentication
69+
70+
Use either:
71+
72+
- `apiKey`: a VibeSDK API key (recommended for CLIs and automation)
73+
- `token`: an already-minted JWT access token
74+
75+
When `apiKey` is provided, the SDK exchanges it for a short-lived access token and caches it.
76+
77+
## Workspace (no platform file APIs)
78+
79+
The SDK reconstructs and maintains a local view of the codebase using:
80+
81+
- `agent_connected.state.generatedFilesMap`
82+
- `cf_agent_state.state.generatedFilesMap`
83+
- incremental `file_*` messages
84+
85+
APIs:
86+
87+
- `session.files.listPaths()`
88+
- `session.files.read(path)`
89+
- `session.files.snapshot()`
90+
- `session.files.tree()`
91+
92+
## Waiting primitives
93+
94+
Use high-level waits instead of depending on agent-internal message ordering:
95+
96+
- `session.wait.generationStarted()`
97+
- `session.wait.generationComplete()`
98+
- `session.wait.deployable()` (phasic resolves on `phase_validated`)
99+
- `session.wait.previewDeployed()`
100+
- `session.wait.cloudflareDeployed()`
101+
102+
All waits default to a long timeout (10 minutes). You can override per call:
103+
104+
```ts
105+
await session.wait.generationComplete({ timeoutMs: 2 * 60_000 });
106+
```
107+
108+
## Reliable WebSocket connections
109+
110+
Connections automatically reconnect with exponential backoff + jitter.
111+
112+
Events:
113+
114+
- `session.on('ws:reconnecting', ({ attempt, delayMs, reason }) => { ... })`
115+
116+
To disable reconnect:
117+
118+
```ts
119+
session.connect({ retry: { enabled: false } });
120+
```
121+
122+
## Low-level access
123+
124+
For advanced clients, you can subscribe to the raw typed WS stream:
125+
126+
- `session.on('ws:message', (msg) => { ... })`
127+
128+
The SDK also exposes `ws:raw` when the platform sends malformed/untyped payloads.
129+
130+
## Tests
131+
132+
From `sdk/`:
133+
134+
- Unit: `bun run test`
135+
- Integration (requires local platform + API key): `bun run test:integration`
136+
137+
Integration expects:
138+
139+
- `VIBESDK_INTEGRATION_API_KEY`
140+
- optional `VIBESDK_INTEGRATION_BASE_URL` (default `http://localhost:5173`)

sdk/bun.lock

Lines changed: 61 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

sdk/package.json

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
{
2+
"name": "@cf-vibesdk/sdk",
3+
"version": "0.0.2",
4+
"type": "module",
5+
"exports": {
6+
".": {
7+
"types": "./dist/index.d.ts",
8+
"default": "./dist/index.js"
9+
},
10+
"./node": {
11+
"types": "./dist/node.d.ts",
12+
"default": "./dist/node.js"
13+
}
14+
},
15+
"files": [
16+
"dist"
17+
],
18+
"publishConfig": {
19+
"access": "public"
20+
},
21+
"scripts": {
22+
"build": "rm -rf ./dist && bun build ./src/index.ts ./src/node.ts --outdir ./dist --target bun",
23+
"bundle-types": "dts-bundle-generator --export-referenced-types false --project ./tsconfig.protocol.json -o ./dist/index.d.ts ./src/index.ts && dts-bundle-generator --export-referenced-types false --project ./tsconfig.protocol.json -o ./dist/node.d.ts ./src/node.ts",
24+
"typecheck": "tsc -p ./tsconfig.json --noEmit",
25+
"test": "bun test test/*.test.ts",
26+
"test:integration": "bun test --timeout 600000 test/integration/*.test.ts"
27+
},
28+
"dependencies": {
29+
"ws": "^8.18.3"
30+
},
31+
"devDependencies": {
32+
"@types/ws": "^8.18.1",
33+
"dts-bundle-generator": "^9.5.1",
34+
"typescript": "^5.9.3"
35+
}
36+
}
37+
38+

sdk/src/agentic.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import type { VibeClientOptions } from './types';
2+
import { VibeClient } from './client';
3+
4+
export class AgenticClient extends VibeClient {
5+
constructor(options: VibeClientOptions) {
6+
super(options);
7+
}
8+
9+
override async build(prompt: string, options: Parameters<VibeClient['build']>[1] = {}) {
10+
return super.build(prompt, { ...options, behaviorType: options.behaviorType ?? 'agentic' });
11+
}
12+
}

0 commit comments

Comments
 (0)