@cf-vibesdk/sdk 0.0.3 → 0.0.4

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/dist/index.js CHANGED
@@ -213,6 +213,7 @@ class TypedEmitter {
213
213
 
214
214
  // src/state.ts
215
215
  var INITIAL_STATE = {
216
+ connection: "disconnected",
216
217
  generation: { status: "idle" },
217
218
  phase: { status: "idle" },
218
219
  preview: { status: "idle" },
@@ -235,6 +236,9 @@ class SessionStateStore {
235
236
  onChange(cb) {
236
237
  return this.emitter.on("change", ({ prev, next }) => cb(next, prev));
237
238
  }
239
+ setConnection(state) {
240
+ this.setState({ connection: state });
241
+ }
238
242
  applyWsMessage(msg) {
239
243
  switch (msg.type) {
240
244
  case "conversation_state": {
@@ -249,29 +253,57 @@ class SessionStateStore {
249
253
  }
250
254
  case "generation_started": {
251
255
  const m = msg;
252
- this.setState({ generation: { status: "running", totalFiles: m.totalFiles } });
256
+ this.setState({
257
+ generation: { status: "running", totalFiles: m.totalFiles, filesGenerated: 0 },
258
+ currentFile: undefined
259
+ });
253
260
  break;
254
261
  }
255
262
  case "generation_complete": {
256
263
  const m = msg;
257
264
  const previewURL = m.previewURL;
265
+ const prev = this.state.generation;
266
+ const filesGenerated = "filesGenerated" in prev ? prev.filesGenerated : 0;
258
267
  this.setState({
259
268
  generation: {
260
269
  status: "complete",
261
270
  instanceId: m.instanceId,
262
- previewURL
271
+ previewURL,
272
+ filesGenerated
263
273
  },
274
+ currentFile: undefined,
264
275
  ...previewURL ? { previewUrl: previewURL } : {}
265
276
  });
266
277
  break;
267
278
  }
268
279
  case "generation_stopped": {
269
280
  const m = msg;
270
- this.setState({ generation: { status: "stopped", instanceId: m.instanceId } });
281
+ const prev = this.state.generation;
282
+ const filesGenerated = "filesGenerated" in prev ? prev.filesGenerated : 0;
283
+ this.setState({
284
+ generation: { status: "stopped", instanceId: m.instanceId, filesGenerated }
285
+ });
271
286
  break;
272
287
  }
273
288
  case "generation_resumed": {
274
- this.setState({ generation: { status: "running" } });
289
+ const prev = this.state.generation;
290
+ const filesGenerated = "filesGenerated" in prev ? prev.filesGenerated : 0;
291
+ this.setState({ generation: { status: "running", filesGenerated } });
292
+ break;
293
+ }
294
+ case "file_generating": {
295
+ const m = msg;
296
+ this.setState({ currentFile: m.filePath });
297
+ break;
298
+ }
299
+ case "file_generated": {
300
+ const prev = this.state.generation;
301
+ if (prev.status === "running" || prev.status === "stopped") {
302
+ this.setState({
303
+ generation: { ...prev, filesGenerated: prev.filesGenerated + 1 },
304
+ currentFile: undefined
305
+ });
306
+ }
275
307
  break;
276
308
  }
277
309
  case "phase_generating": {
@@ -789,11 +821,18 @@ class BuildSession {
789
821
  ...Object.keys(headers).length ? { headers } : {},
790
822
  ...webSocketFactory ? { webSocketFactory } : {}
791
823
  };
824
+ this.state.setConnection("connecting");
792
825
  this.connection = createAgentConnection(this.websocketUrl, connectOptions);
793
826
  this.connection.on("ws:message", (m) => {
794
827
  this.workspace.applyWsMessage(m);
795
828
  this.state.applyWsMessage(m);
796
829
  });
830
+ this.connection.on("ws:open", () => {
831
+ this.state.setConnection("connected");
832
+ });
833
+ this.connection.on("ws:close", () => {
834
+ this.state.setConnection("disconnected");
835
+ });
797
836
  const credentials = agentOptions.credentials ?? this.init.defaultCredentials;
798
837
  const shouldRequestConversationState = autoRequestConversationState ?? true;
799
838
  this.connection.on("ws:open", () => {
@@ -1061,11 +1100,114 @@ class PhasicClient extends VibeClient {
1061
1100
  return super.build(prompt, { ...options, behaviorType: options.behaviorType ?? "phasic" });
1062
1101
  }
1063
1102
  }
1103
+ // src/blueprint.ts
1104
+ function isRecord2(v) {
1105
+ return Boolean(v) && typeof v === "object" && !Array.isArray(v);
1106
+ }
1107
+ function blueprintToMarkdown(bp) {
1108
+ const lines = [];
1109
+ const title = bp.title ?? bp.projectName ?? "Blueprint";
1110
+ lines.push(`# ${title}`);
1111
+ if (bp.description) {
1112
+ lines.push("");
1113
+ lines.push(bp.description);
1114
+ }
1115
+ if (bp.frameworks?.length) {
1116
+ lines.push("");
1117
+ lines.push("## Frameworks");
1118
+ for (const f of bp.frameworks)
1119
+ lines.push(`- ${f}`);
1120
+ }
1121
+ if (bp.detailedDescription) {
1122
+ lines.push("");
1123
+ lines.push("## Details");
1124
+ lines.push(bp.detailedDescription);
1125
+ }
1126
+ if (bp.views?.length) {
1127
+ lines.push("");
1128
+ lines.push("## Views");
1129
+ for (const v of bp.views)
1130
+ lines.push(`- **${v.name}**: ${v.description}`);
1131
+ }
1132
+ if (bp.plan?.length) {
1133
+ lines.push("");
1134
+ lines.push("## Plan");
1135
+ bp.plan.forEach((s, idx) => lines.push(`${idx + 1}. ${s}`));
1136
+ }
1137
+ if (bp.implementationRoadmap?.length) {
1138
+ lines.push("");
1139
+ lines.push("## Roadmap");
1140
+ for (const p of bp.implementationRoadmap)
1141
+ lines.push(`- **${p.phase}**: ${p.description}`);
1142
+ }
1143
+ return lines.join(`
1144
+ `);
1145
+ }
1146
+ function extractJsonStringField(raw, key) {
1147
+ const re = new RegExp(`"${key}"\\s*:\\s*"([^"\\n\\r]*)"`);
1148
+ const m = re.exec(raw);
1149
+ return m?.[1] ?? null;
1150
+ }
1151
+
1152
+ class BlueprintStreamParser {
1153
+ buffer = "";
1154
+ append(chunk) {
1155
+ this.buffer += chunk;
1156
+ return this.toMarkdown();
1157
+ }
1158
+ toMarkdown() {
1159
+ const startsLikeJson = /^\s*[\[{]/.test(this.buffer);
1160
+ if (!startsLikeJson) {
1161
+ return this.buffer;
1162
+ }
1163
+ try {
1164
+ const parsed = JSON.parse(this.buffer);
1165
+ if (isRecord2(parsed)) {
1166
+ return blueprintToMarkdown(parsed);
1167
+ }
1168
+ } catch {}
1169
+ const title = extractJsonStringField(this.buffer, "title") ?? extractJsonStringField(this.buffer, "projectName") ?? "Blueprint";
1170
+ const desc = extractJsonStringField(this.buffer, "description");
1171
+ const lines = [`# ${title}`, "", desc ? desc : "*Generating blueprint...*"];
1172
+ return lines.join(`
1173
+ `);
1174
+ }
1175
+ getRaw() {
1176
+ return this.buffer;
1177
+ }
1178
+ clear() {
1179
+ this.buffer = "";
1180
+ }
1181
+ }
1182
+ // src/utils.ts
1183
+ class TimeoutError extends Error {
1184
+ constructor(message) {
1185
+ super(message);
1186
+ this.name = "TimeoutError";
1187
+ }
1188
+ }
1189
+ async function withTimeout(promise, ms, message = "Operation timed out") {
1190
+ let timeoutId;
1191
+ const timeout = new Promise((_, reject) => {
1192
+ timeoutId = setTimeout(() => reject(new TimeoutError(message)), ms);
1193
+ });
1194
+ try {
1195
+ return await Promise.race([promise, timeout]);
1196
+ } finally {
1197
+ if (timeoutId !== undefined)
1198
+ clearTimeout(timeoutId);
1199
+ }
1200
+ }
1064
1201
  export {
1202
+ withTimeout,
1203
+ isRecord2 as isRecord,
1204
+ blueprintToMarkdown,
1065
1205
  WorkspaceStore,
1066
1206
  VibeClient,
1207
+ TimeoutError,
1067
1208
  SessionStateStore,
1068
1209
  PhasicClient,
1069
1210
  BuildSession,
1211
+ BlueprintStreamParser,
1070
1212
  AgenticClient
1071
1213
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cf-vibesdk/sdk",
3
- "version": "0.0.3",
3
+ "version": "0.0.4",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": {
@@ -34,5 +34,3 @@
34
34
  "typescript": "^5.9.3"
35
35
  }
36
36
  }
37
-
38
-