@cf-vibesdk/sdk 0.1.0 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -78
- package/dist/index.d.ts +9 -26
- package/dist/index.js +23 -56
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -94,53 +94,6 @@ const session = await client.build('Build a weather dashboard', {
|
|
|
94
94
|
});
|
|
95
95
|
```
|
|
96
96
|
|
|
97
|
-
#### Blueprint Streaming
|
|
98
|
-
|
|
99
|
-
The server streams blueprint chunks as the AI generates the project plan. By default, `build()` waits for all chunks before returning:
|
|
100
|
-
|
|
101
|
-
```ts
|
|
102
|
-
// Default behavior: waits for blueprint to complete
|
|
103
|
-
const session = await client.build('Build a todo app', {
|
|
104
|
-
onBlueprintChunk: (chunk) => {
|
|
105
|
-
// Called in real-time as chunks arrive
|
|
106
|
-
blueprintText += chunk;
|
|
107
|
-
},
|
|
108
|
-
});
|
|
109
|
-
// Session returned after all blueprint chunks received
|
|
110
|
-
```
|
|
111
|
-
|
|
112
|
-
For faster startup, set `waitForBlueprint: false` to return immediately and stream chunks in the background:
|
|
113
|
-
|
|
114
|
-
```ts
|
|
115
|
-
const session = await client.build('Build a todo app', {
|
|
116
|
-
waitForBlueprint: false, // Return immediately after start event
|
|
117
|
-
onBlueprintChunk: (chunk) => {
|
|
118
|
-
// Still called in real-time as chunks arrive
|
|
119
|
-
blueprintText += chunk;
|
|
120
|
-
},
|
|
121
|
-
onBlueprintError: (error) => {
|
|
122
|
-
// Called if streaming fails (session is auto-closed)
|
|
123
|
-
console.error('Blueprint streaming failed:', error);
|
|
124
|
-
},
|
|
125
|
-
});
|
|
126
|
-
// Session returned immediately, blueprint streams in background
|
|
127
|
-
```
|
|
128
|
-
|
|
129
|
-
Use the `BlueprintStreamParser` utility to convert chunks to readable Markdown:
|
|
130
|
-
|
|
131
|
-
```ts
|
|
132
|
-
import { BlueprintStreamParser } from '@cf-vibesdk/sdk';
|
|
133
|
-
|
|
134
|
-
const parser = new BlueprintStreamParser();
|
|
135
|
-
const session = await client.build('Build a todo app', {
|
|
136
|
-
waitForBlueprint: false,
|
|
137
|
-
onBlueprintChunk: (chunk) => {
|
|
138
|
-
const markdown = parser.append(chunk);
|
|
139
|
-
console.log(markdown); // Rendered as Markdown
|
|
140
|
-
},
|
|
141
|
-
});
|
|
142
|
-
```
|
|
143
|
-
|
|
144
97
|
### `client.connect(agentId)`
|
|
145
98
|
|
|
146
99
|
Connect to an existing app session. State is automatically restored from the agent, including:
|
|
@@ -369,14 +322,14 @@ session.workspace.onChange((change) => {
|
|
|
369
322
|
|
|
370
323
|
## WebSocket Reliability
|
|
371
324
|
|
|
372
|
-
Connections automatically reconnect with exponential backoff.
|
|
325
|
+
Connections automatically reconnect with exponential backoff.
|
|
373
326
|
|
|
374
327
|
```ts
|
|
375
328
|
// Custom retry config
|
|
376
329
|
await session.connect({
|
|
377
330
|
retry: {
|
|
378
331
|
enabled: true, // Default: true
|
|
379
|
-
initialDelayMs:
|
|
332
|
+
initialDelayMs: 1000, // Default: 1000
|
|
380
333
|
maxDelayMs: 30000, // Default: 30000
|
|
381
334
|
maxRetries: 10, // Default: Infinity
|
|
382
335
|
},
|
|
@@ -386,35 +339,6 @@ await session.connect({
|
|
|
386
339
|
await session.connect({ retry: { enabled: false } });
|
|
387
340
|
```
|
|
388
341
|
|
|
389
|
-
### Auto-Preview on Reconnect
|
|
390
|
-
|
|
391
|
-
When connecting to an **existing app** (via `client.connect()`), the SDK automatically sends a `preview` message on connect and reconnect to ensure the preview deployment stays active:
|
|
392
|
-
|
|
393
|
-
```ts
|
|
394
|
-
// Existing app - auto-preview is enabled by default
|
|
395
|
-
const session = await client.connect('agent-id');
|
|
396
|
-
await session.connect(); // Sends preview message automatically
|
|
397
|
-
|
|
398
|
-
// Override for new builds or disable
|
|
399
|
-
await session.connect({ autoRequestPreview: false });
|
|
400
|
-
|
|
401
|
-
// Force enable for new builds
|
|
402
|
-
const session = await client.build('Build a todo app');
|
|
403
|
-
await session.connect({ autoRequestPreview: true });
|
|
404
|
-
```
|
|
405
|
-
|
|
406
|
-
### Reconnect Events
|
|
407
|
-
|
|
408
|
-
```ts
|
|
409
|
-
session.on('ws:reconnecting', ({ attempt, delayMs, reason }) => {
|
|
410
|
-
console.log(`Reconnecting (attempt ${attempt}, delay ${delayMs}ms, reason: ${reason})`);
|
|
411
|
-
});
|
|
412
|
-
|
|
413
|
-
session.on('ws:reconnected', () => {
|
|
414
|
-
console.log('Reconnected successfully');
|
|
415
|
-
});
|
|
416
|
-
```
|
|
417
|
-
|
|
418
342
|
## HTTP Retry
|
|
419
343
|
|
|
420
344
|
HTTP requests automatically retry on 5xx errors.
|
package/dist/index.d.ts
CHANGED
|
@@ -795,10 +795,16 @@ interface PhasicState extends BaseProjectState {
|
|
|
795
795
|
reviewCycles?: number;
|
|
796
796
|
currentPhase?: PhaseConceptType;
|
|
797
797
|
}
|
|
798
|
+
interface PreflightState {
|
|
799
|
+
questionsAsked: number;
|
|
800
|
+
isWaitingForAnswer: boolean;
|
|
801
|
+
}
|
|
798
802
|
interface AgenticState extends BaseProjectState {
|
|
799
803
|
behaviorType: "agentic";
|
|
800
804
|
blueprint: AgenticBlueprint;
|
|
801
805
|
currentPlan: Plan;
|
|
806
|
+
preflightQuestions?: string;
|
|
807
|
+
preflightState?: PreflightState;
|
|
802
808
|
}
|
|
803
809
|
export type AgentState = PhasicState | AgenticState;
|
|
804
810
|
interface FileObject {
|
|
@@ -1145,6 +1151,7 @@ type ScreenshotCaptureSuccessMessage = {
|
|
|
1145
1151
|
};
|
|
1146
1152
|
screenshotSize: number;
|
|
1147
1153
|
timestamp: string;
|
|
1154
|
+
screenshotUrl?: string;
|
|
1148
1155
|
};
|
|
1149
1156
|
type ScreenshotCaptureErrorMessage = {
|
|
1150
1157
|
type: "screenshot_capture_error";
|
|
@@ -1320,6 +1327,8 @@ interface CodeGenArgs {
|
|
|
1320
1327
|
behaviorType?: BehaviorType;
|
|
1321
1328
|
projectType?: ProjectType;
|
|
1322
1329
|
images?: ImageAttachment[];
|
|
1330
|
+
/** Optional preflight questions context to ask the user before building */
|
|
1331
|
+
preflightQuestions?: string;
|
|
1323
1332
|
/** Optional ephemeral credentials (BYOK / gateway override) for sdk */
|
|
1324
1333
|
credentials?: CredentialsPayload;
|
|
1325
1334
|
}
|
|
@@ -5453,21 +5462,7 @@ type CodeGenArgs$1 = CodeGenArgs;
|
|
|
5453
5462
|
export type BuildOptions = Omit<CodeGenArgs$1, "query"> & {
|
|
5454
5463
|
autoConnect?: boolean;
|
|
5455
5464
|
autoGenerate?: boolean;
|
|
5456
|
-
/**
|
|
5457
|
-
* Called for each blueprint chunk as it streams from the server.
|
|
5458
|
-
*/
|
|
5459
5465
|
onBlueprintChunk?: (chunk: string) => void;
|
|
5460
|
-
/**
|
|
5461
|
-
* Called if blueprint streaming fails. The session will be closed automatically.
|
|
5462
|
-
* Only relevant when `waitForBlueprint` is false.
|
|
5463
|
-
*/
|
|
5464
|
-
onBlueprintError?: (error: Error) => void;
|
|
5465
|
-
/**
|
|
5466
|
-
* If true (default), `build()` waits for all blueprint chunks before returning.
|
|
5467
|
-
* If false, `build()` returns immediately after receiving the start event,
|
|
5468
|
-
* and blueprint chunks stream in the background via `onBlueprintChunk`.
|
|
5469
|
-
*/
|
|
5470
|
-
waitForBlueprint?: boolean;
|
|
5471
5466
|
};
|
|
5472
5467
|
type TemplateFiles = Record<string, string>;
|
|
5473
5468
|
export type BuildStartEvent = {
|
|
@@ -5568,7 +5563,6 @@ export type AgentEventMap = {
|
|
|
5568
5563
|
delayMs: number;
|
|
5569
5564
|
reason: "close" | "error";
|
|
5570
5565
|
};
|
|
5571
|
-
"ws:reconnected": undefined;
|
|
5572
5566
|
"ws:raw": {
|
|
5573
5567
|
raw: unknown;
|
|
5574
5568
|
};
|
|
@@ -5864,19 +5858,12 @@ type WaitUntilReadyOptions = WaitOptions;
|
|
|
5864
5858
|
type BuildSessionConnectOptions = Omit<AgentConnectionOptions, "credentials"> & {
|
|
5865
5859
|
/** If true (default), send `get_conversation_state` on socket open. */
|
|
5866
5860
|
autoRequestConversationState?: boolean;
|
|
5867
|
-
/**
|
|
5868
|
-
* If true, send `preview` message on connect and reconnect to ensure preview exists.
|
|
5869
|
-
* Defaults to true for existing apps (via `client.connect()`), false for new builds.
|
|
5870
|
-
*/
|
|
5871
|
-
autoRequestPreview?: boolean;
|
|
5872
5861
|
/** Credentials to send via session_init after connection. */
|
|
5873
5862
|
credentials?: Credentials;
|
|
5874
5863
|
};
|
|
5875
5864
|
type BuildSessionInit = {
|
|
5876
5865
|
httpClient: HttpClient;
|
|
5877
5866
|
defaultCredentials?: Credentials;
|
|
5878
|
-
/** True if this session is for an existing app (via client.connect). */
|
|
5879
|
-
isExistingApp?: boolean;
|
|
5880
5867
|
};
|
|
5881
5868
|
export declare class BuildSession {
|
|
5882
5869
|
private init;
|
|
@@ -5970,10 +5957,6 @@ export declare class VibeClient {
|
|
|
5970
5957
|
get baseUrl(): string;
|
|
5971
5958
|
/**
|
|
5972
5959
|
* Creates a new agent/app from a prompt and returns a BuildSession.
|
|
5973
|
-
*
|
|
5974
|
-
* By default, waits for all blueprint chunks before returning. Set
|
|
5975
|
-
* `waitForBlueprint: false` to return immediately after the start event,
|
|
5976
|
-
* with blueprint chunks streaming in the background.
|
|
5977
5960
|
*/
|
|
5978
5961
|
build(prompt: string, options?: BuildOptions): Promise<BuildSession>;
|
|
5979
5962
|
/** Connect to an existing agent/app by id. */
|
package/dist/index.js
CHANGED
|
@@ -409,7 +409,7 @@ class SessionStateStore {
|
|
|
409
409
|
const m = msg;
|
|
410
410
|
const phaseInfo = extractPhaseInfo(m);
|
|
411
411
|
const phaseFiles = extractPhaseFiles(m);
|
|
412
|
-
const phases = this.updateOrAddPhase(phaseInfo, "
|
|
412
|
+
const phases = this.updateOrAddPhase(phaseInfo, "validating", phaseFiles);
|
|
413
413
|
this.setState({
|
|
414
414
|
phase: { status: "implemented", ...phaseInfo },
|
|
415
415
|
phases
|
|
@@ -431,7 +431,7 @@ class SessionStateStore {
|
|
|
431
431
|
const m = msg;
|
|
432
432
|
const phaseInfo = extractPhaseInfo(m);
|
|
433
433
|
const phaseFiles = extractPhaseFiles(m);
|
|
434
|
-
const phases = this.updateOrAddPhase(phaseInfo, "
|
|
434
|
+
const phases = this.updateOrAddPhase(phaseInfo, "completed", phaseFiles);
|
|
435
435
|
this.setState({
|
|
436
436
|
phase: { status: "validated", ...phaseInfo },
|
|
437
437
|
phases
|
|
@@ -618,7 +618,7 @@ async function withTimeout(promise, ms, message = "Operation timed out") {
|
|
|
618
618
|
// src/ws.ts
|
|
619
619
|
var WS_RETRY_DEFAULTS = {
|
|
620
620
|
enabled: true,
|
|
621
|
-
initialDelayMs:
|
|
621
|
+
initialDelayMs: 1000,
|
|
622
622
|
maxDelayMs: 30000,
|
|
623
623
|
maxRetries: Infinity
|
|
624
624
|
};
|
|
@@ -630,7 +630,6 @@ function createAgentConnection(getUrl, options = {}) {
|
|
|
630
630
|
let closedByUser = false;
|
|
631
631
|
let reconnectAttempts = 0;
|
|
632
632
|
let reconnectTimer = null;
|
|
633
|
-
let hasConnectedBefore = false;
|
|
634
633
|
const pendingSends = [];
|
|
635
634
|
const maxPendingSends = 1000;
|
|
636
635
|
function clearReconnectTimer() {
|
|
@@ -656,34 +655,22 @@ function createAgentConnection(getUrl, options = {}) {
|
|
|
656
655
|
return;
|
|
657
656
|
if (reconnectTimer)
|
|
658
657
|
return;
|
|
659
|
-
const delayMs =
|
|
658
|
+
const delayMs = computeBackoffMs(reconnectAttempts, retryCfg);
|
|
660
659
|
emitter.emit("ws:reconnecting", {
|
|
661
660
|
attempt: reconnectAttempts + 1,
|
|
662
661
|
delayMs,
|
|
663
662
|
reason
|
|
664
663
|
});
|
|
665
664
|
reconnectAttempts += 1;
|
|
666
|
-
|
|
667
|
-
reconnectTimer =
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
}, 0);
|
|
671
|
-
} else {
|
|
672
|
-
reconnectTimer = setTimeout(() => {
|
|
673
|
-
reconnectTimer = null;
|
|
674
|
-
connectNow();
|
|
675
|
-
}, delayMs);
|
|
676
|
-
}
|
|
665
|
+
reconnectTimer = setTimeout(() => {
|
|
666
|
+
reconnectTimer = null;
|
|
667
|
+
connectNow();
|
|
668
|
+
}, delayMs);
|
|
677
669
|
}
|
|
678
670
|
function onOpen() {
|
|
679
|
-
const isReconnect = hasConnectedBefore;
|
|
680
|
-
hasConnectedBefore = true;
|
|
681
671
|
isOpen = true;
|
|
682
672
|
reconnectAttempts = 0;
|
|
683
673
|
emitter.emit("ws:open", undefined);
|
|
684
|
-
if (isReconnect) {
|
|
685
|
-
emitter.emit("ws:reconnected", undefined);
|
|
686
|
-
}
|
|
687
674
|
flushPendingSends();
|
|
688
675
|
}
|
|
689
676
|
function onClose(e) {
|
|
@@ -1018,7 +1005,7 @@ class BuildSession {
|
|
|
1018
1005
|
async connect(options = {}) {
|
|
1019
1006
|
if (this.connection)
|
|
1020
1007
|
return this.connection;
|
|
1021
|
-
const { autoRequestConversationState,
|
|
1008
|
+
const { autoRequestConversationState, credentials, ...connectionOptions } = options;
|
|
1022
1009
|
const getUrl = async () => {
|
|
1023
1010
|
const { ticket } = await this.init.httpClient.getWsTicket(this.agentId);
|
|
1024
1011
|
const base = this.websocketUrl;
|
|
@@ -1039,7 +1026,6 @@ class BuildSession {
|
|
|
1039
1026
|
});
|
|
1040
1027
|
const sessionCredentials = credentials ?? this.init.defaultCredentials;
|
|
1041
1028
|
const shouldRequestConversationState = autoRequestConversationState ?? true;
|
|
1042
|
-
const shouldRequestPreview = autoRequestPreview ?? (this.init.isExistingApp ?? false);
|
|
1043
1029
|
this.connection.on("ws:open", () => {
|
|
1044
1030
|
if (sessionCredentials) {
|
|
1045
1031
|
this.connection?.send({
|
|
@@ -1050,14 +1036,6 @@ class BuildSession {
|
|
|
1050
1036
|
if (shouldRequestConversationState) {
|
|
1051
1037
|
this.connection?.send({ type: "get_conversation_state" });
|
|
1052
1038
|
}
|
|
1053
|
-
if (shouldRequestPreview) {
|
|
1054
|
-
this.connection?.send({ type: "preview" });
|
|
1055
|
-
}
|
|
1056
|
-
});
|
|
1057
|
-
this.connection.on("ws:reconnected", () => {
|
|
1058
|
-
if (shouldRequestPreview) {
|
|
1059
|
-
this.connection?.send({ type: "preview" });
|
|
1060
|
-
}
|
|
1061
1039
|
});
|
|
1062
1040
|
return this.connection;
|
|
1063
1041
|
}
|
|
@@ -1210,7 +1188,8 @@ class VibeClient {
|
|
|
1210
1188
|
behaviorType: options.behaviorType,
|
|
1211
1189
|
projectType: options.projectType,
|
|
1212
1190
|
images: options.images,
|
|
1213
|
-
credentials: options.credentials
|
|
1191
|
+
credentials: options.credentials,
|
|
1192
|
+
preflightQuestions: options.preflightQuestions
|
|
1214
1193
|
};
|
|
1215
1194
|
const resp = await this.http.fetchRaw("/api/agent", {
|
|
1216
1195
|
method: "POST",
|
|
@@ -1220,35 +1199,24 @@ class VibeClient {
|
|
|
1220
1199
|
if (!resp.body) {
|
|
1221
1200
|
throw new Error("Missing response body from /api/agent");
|
|
1222
1201
|
}
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1202
|
+
let start = null;
|
|
1203
|
+
for await (const obj of parseNdjsonStream(resp.body)) {
|
|
1204
|
+
if (!start) {
|
|
1205
|
+
start = obj;
|
|
1206
|
+
continue;
|
|
1207
|
+
}
|
|
1208
|
+
const o = obj;
|
|
1209
|
+
if (typeof o.chunk === "string") {
|
|
1210
|
+
options.onBlueprintChunk?.(o.chunk);
|
|
1211
|
+
}
|
|
1212
|
+
}
|
|
1213
|
+
if (!start) {
|
|
1226
1214
|
throw new Error("No start event received from /api/agent");
|
|
1227
1215
|
}
|
|
1228
1216
|
const session = new BuildSession(start, {
|
|
1229
1217
|
httpClient: this.http,
|
|
1230
1218
|
...options.credentials ? { defaultCredentials: options.credentials } : {}
|
|
1231
1219
|
});
|
|
1232
|
-
const waitForBlueprint = options.waitForBlueprint ?? true;
|
|
1233
|
-
const processChunks = async () => {
|
|
1234
|
-
let result = await iterator.next();
|
|
1235
|
-
while (!result.done) {
|
|
1236
|
-
const obj = result.value;
|
|
1237
|
-
if (typeof obj.chunk === "string") {
|
|
1238
|
-
options.onBlueprintChunk?.(obj.chunk);
|
|
1239
|
-
}
|
|
1240
|
-
result = await iterator.next();
|
|
1241
|
-
}
|
|
1242
|
-
};
|
|
1243
|
-
if (waitForBlueprint) {
|
|
1244
|
-
await processChunks();
|
|
1245
|
-
} else {
|
|
1246
|
-
processChunks().catch((error) => {
|
|
1247
|
-
const err = error instanceof Error ? error : new Error(String(error));
|
|
1248
|
-
options.onBlueprintError?.(err);
|
|
1249
|
-
session.close();
|
|
1250
|
-
});
|
|
1251
|
-
}
|
|
1252
1220
|
if (options.autoConnect ?? true) {
|
|
1253
1221
|
await session.connect();
|
|
1254
1222
|
if (options.autoGenerate ?? true) {
|
|
@@ -1268,7 +1236,6 @@ class VibeClient {
|
|
|
1268
1236
|
};
|
|
1269
1237
|
return new BuildSession(start, {
|
|
1270
1238
|
httpClient: this.http,
|
|
1271
|
-
isExistingApp: true,
|
|
1272
1239
|
...options.credentials ? { defaultCredentials: options.credentials } : {}
|
|
1273
1240
|
});
|
|
1274
1241
|
}
|