Skip to content

Commit dbcf51f

Browse files
committed
feat: implement phase timeline management and state tracking in SDK
1 parent f565aff commit dbcf51f

File tree

8 files changed

+707
-13
lines changed

8 files changed

+707
-13
lines changed

sdk/README.md

Lines changed: 78 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,13 +96,21 @@ const session = await client.build('Build a weather dashboard', {
9696

9797
### `client.connect(agentId)`
9898

99-
Connect to an existing app session.
99+
Connect to an existing app session. State is automatically restored from the agent, including:
100+
- Phase timeline with completion status
101+
- Generated files
102+
- Agent metadata (query, projectName, behaviorType, etc.)
100103

101104
```ts
102105
const session = await client.connect('agent-id-here', {
103106
credentials: { ... }, // Optional
104107
});
105108
await session.connect();
109+
110+
// State is now seeded from the agent
111+
console.log('Original query:', session.state.get().query);
112+
console.log('Phases:', session.phases.list());
113+
console.log('Files:', session.files.listPaths());
106114
```
107115

108116
## App Management
@@ -215,6 +223,53 @@ const snapshot = session.files.snapshot(); // { 'src/App.tsx': '...', ... }
215223
const tree = session.files.tree(); // Nested file tree structure
216224
```
217225

226+
### Phase Timeline
227+
228+
Access the full phase timeline for phasic builds. The timeline is automatically seeded when connecting to an existing agent and updated as phases progress.
229+
230+
```ts
231+
// Get all phases
232+
const phases = session.phases.list();
233+
// [{ id: 'phase-0', name: 'Core Setup', status: 'completed', files: [...] }, ...]
234+
235+
// Get current active phase
236+
const current = session.phases.current();
237+
if (current) {
238+
console.log(`Working on: ${current.name}`);
239+
console.log(`Status: ${current.status}`); // 'generating' | 'implementing' | 'validating'
240+
}
241+
242+
// Get completed phases
243+
const done = session.phases.completed();
244+
console.log(`Progress: ${done.length}/${session.phases.count()}`);
245+
246+
// Check if all phases are done
247+
if (session.phases.allCompleted()) {
248+
console.log('Build complete!');
249+
}
250+
251+
// Get phase by ID
252+
const phase = session.phases.get('phase-0');
253+
```
254+
255+
Each phase contains:
256+
257+
```ts
258+
type PhaseInfo = {
259+
id: string; // 'phase-0', 'phase-1', etc.
260+
name: string; // 'Core Setup', 'Authentication', etc.
261+
description: string; // What the phase accomplishes
262+
status: PhaseStatus; // 'pending' | 'generating' | 'implementing' | 'validating' | 'completed' | 'cancelled'
263+
files: PhaseFile[]; // Files in this phase
264+
};
265+
266+
type PhaseFile = {
267+
path: string; // 'src/App.tsx'
268+
purpose: string; // 'Main application component'
269+
status: PhaseFileStatus; // 'pending' | 'generating' | 'completed' | 'cancelled'
270+
};
271+
```
272+
218273
### State
219274

220275
```ts
@@ -226,6 +281,16 @@ console.log(state.phase); // { status: 'idle' | 'generating' | ... }
226281
console.log(state.preview); // Preview deployment state
227282
console.log(state.cloudflare); // Cloudflare deployment state
228283

284+
// Phase timeline (array of all phases)
285+
console.log(state.phases); // [{ id, name, status, files }, ...]
286+
287+
// Agent metadata (seeded from agent_connected)
288+
console.log(state.behaviorType); // 'phasic' | 'agentic'
289+
console.log(state.projectType); // 'app' | 'workflow' | etc.
290+
console.log(state.query); // Original user prompt
291+
console.log(state.projectName); // Project name from blueprint
292+
console.log(state.shouldBeGenerating); // Whether agent is actively generating
293+
229294
// Subscribe to changes
230295
session.state.onChange((next, prev) => {
231296
console.log('State changed:', next);
@@ -324,10 +389,22 @@ All types are exported:
324389

325390
```ts
326391
import type {
392+
// Client & Session
327393
VibeClientOptions,
328394
BuildOptions,
329395
BuildSession,
330396
SessionState,
397+
SessionFiles,
398+
SessionPhases,
399+
400+
// Phase Timeline
401+
PhaseInfo,
402+
PhaseFile,
403+
PhaseStatus,
404+
PhaseFileStatus,
405+
PhaseEventType,
406+
407+
// API
331408
ApiResponse,
332409
AppDetails,
333410
Credentials,

sdk/package.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@cf-vibesdk/sdk",
3-
"version": "0.0.7",
3+
"version": "0.0.8",
44
"type": "module",
55
"exports": {
66
".": {
@@ -22,7 +22,8 @@
2222
"bundle-types": "dts-bundle-generator --export-referenced-types false --no-check --project ./tsconfig.protocol.json -o ./dist/index.d.ts ./src/index.ts && bun run scripts/expand-drizzle-types.ts",
2323
"typecheck": "tsc -p ./tsconfig.json --noEmit",
2424
"test": "bun test test/*.test.ts",
25-
"test:integration": "bun test --timeout 600000 test/integration/*.test.ts"
25+
"test:integration": "bun test --timeout 600000 test/integration/*.test.ts",
26+
"package": "bun run typecheck && bun run test && bun run build && bun run bundle-types"
2627
},
2728
"devDependencies": {
2829
"@cloudflare/workers-types": "^4.20241218.0",

sdk/src/index.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,15 @@ export type {
3434
GitCloneTokenData,
3535
PaginationInfo,
3636
PhaseEventType,
37+
PhaseFile,
38+
PhaseFileStatus,
39+
PhaseInfo,
40+
PhaseStatus,
3741
ProjectType,
3842
PublicAppsQuery,
3943
SessionDeployable,
4044
SessionFiles,
45+
SessionPhases,
4146
ToggleResult,
4247
UrlProvider,
4348
VibeClientOptions,

sdk/src/protocol.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ export type {
1515

1616
export type { AgentState } from '../../worker/agents/core/state';
1717
export type { BehaviorType, ProjectType } from '../../worker/agents/core/types';
18-
export type { FileOutputType } from '../../worker/agents/schemas';
18+
export type { FileOutputType, FileConceptType, PhaseConceptType } from '../../worker/agents/schemas';
1919
export type { TemplateDetails } from '../../worker/services/sandbox/sandboxTypes';
2020

2121
export type {

sdk/src/session.ts

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import type {
88
FileTreeNode,
99
ImageAttachment,
1010
PhaseEventType,
11+
PhaseInfo,
1112
ProjectType,
1213
SessionDeployable,
1314
SessionFiles,
@@ -101,6 +102,35 @@ export class BuildSession {
101102
tree: () => buildFileTree(this.workspace.paths()),
102103
};
103104

105+
/**
106+
* High-level API for accessing the phase timeline.
107+
* Phases are seeded from agent_connected and updated on phase events.
108+
*/
109+
readonly phases = {
110+
/** Get all phases in the timeline. */
111+
list: (): PhaseInfo[] => this.state.get().phases,
112+
113+
/** Get the currently active phase (first non-completed phase), or undefined. */
114+
current: (): PhaseInfo | undefined =>
115+
this.state.get().phases.find((p) => p.status !== 'completed' && p.status !== 'cancelled'),
116+
117+
/** Get all completed phases. */
118+
completed: (): PhaseInfo[] =>
119+
this.state.get().phases.filter((p) => p.status === 'completed'),
120+
121+
/** Get a phase by its id (e.g., "phase-0"). */
122+
get: (id: string): PhaseInfo | undefined =>
123+
this.state.get().phases.find((p) => p.id === id),
124+
125+
/** Get the total count of phases. */
126+
count: (): number => this.state.get().phases.length,
127+
128+
/** Check if all phases are completed. */
129+
allCompleted: (): boolean =>
130+
this.state.get().phases.length > 0 &&
131+
this.state.get().phases.every((p) => p.status === 'completed'),
132+
};
133+
104134
readonly wait = {
105135
generationStarted: (options: WaitOptions = {}) => this.waitForGenerationStarted(options),
106136
generationComplete: (options: WaitOptions = {}) => this.waitForGenerationComplete(options),

0 commit comments

Comments
 (0)