@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 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. The first reconnect attempt is **immediate** (0ms delay) for fast recovery from brief network blips, followed by exponential backoff starting at 200ms.
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: 200, // Default: 200 (used from 2nd attempt onward)
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, "completed", phaseFiles);
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, "validating", phaseFiles);
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: 200,
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 = reconnectAttempts === 0 ? 0 : computeBackoffMs(reconnectAttempts, retryCfg);
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
- if (delayMs === 0) {
667
- reconnectTimer = setTimeout(() => {
668
- reconnectTimer = null;
669
- connectNow();
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, autoRequestPreview, credentials, ...connectionOptions } = options;
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
- const iterator = parseNdjsonStream(resp.body)[Symbol.asyncIterator]();
1224
- const { value: start, done } = await iterator.next();
1225
- if (done || !start) {
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
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cf-vibesdk/sdk",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": {