@vercel/dream 0.2.12 → 0.3.1

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/bin/dream.mjs ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ await import("../dist/dream.js");
package/dist/dream.js CHANGED
@@ -73,16 +73,57 @@ Each iteration follows this cycle:
73
73
 
74
74
  ## Subagent-First Execution
75
75
 
76
- Treat yourself as the manager agent. Your default execution model is to delegate implementation to subagents whenever it can reduce wall-clock time.
76
+ You are the manager agent. Your default is to delegate implementation to subagents to maximize parallelism and reduce wall-clock time.
77
77
 
78
- 1. Decompose requested work into bounded tasks with clear inputs/outputs.
79
- 2. Run independent tasks in parallel using multiple subagents.
80
- 3. Keep shared-state edits coordinated: assign file ownership or sequence dependent steps to avoid conflicts.
81
- 4. Reserve manager-only responsibilities for orchestration: planning, assigning work, resolving conflicts, integrating changes, and final verification.
82
- 5. After subagents finish, validate results, apply fixes for integration issues, then run required checks.
83
- 6. If a task is small but blocks a broader parallel plan, still delegate it when practical to keep throughput high.
78
+ ### Decompose into Bounded Tasks
84
79
 
85
- Prefer subagent parallelism over sequential single-agent implementation unless tasks are tightly coupled or delegation overhead is clearly higher than direct execution.
80
+ 1. Group work by independent domain \u2014 different routes, subsystems, or data models are natural boundaries.
81
+ 2. Each task must have a clear input (what exists), output (what should exist after), and scope (which files to touch).
82
+ 3. If two tasks must edit the same file, sequence them \u2014 never dispatch parallel subagents to the same file.
83
+ 4. If tasks are tightly coupled or you don't yet understand the problem, investigate sequentially first, then parallelize.
84
+
85
+ ### Subagent Prompt Template
86
+
87
+ When dispatching a subagent, provide a self-contained prompt with this structure:
88
+
89
+ \`\`\`
90
+ You are implementing: [task name]
91
+
92
+ ## Task
93
+ [Full text of what to build \u2014 paste requirements inline, never tell subagent to read spec files]
94
+
95
+ ## Context
96
+ [Where this fits: what already exists, dependencies, architectural constraints from specs]
97
+
98
+ ## Scope
99
+ - Files you may create/edit: [explicit list]
100
+ - Files you must NOT touch: [explicit list or "anything not listed above"]
101
+
102
+ ## Constraints
103
+ [Framework requirements, env var rules, forbidden patterns from specs]
104
+
105
+ ## When Done
106
+ Report: what you implemented, files changed, commands to verify, any issues or blockers found.
107
+ \`\`\`
108
+
109
+ Key rules:
110
+ - Provide all context inline \u2014 subagents start with empty context and cannot read your history.
111
+ - Be specific about file scope to prevent edit conflicts between parallel subagents.
112
+ - Include verification commands so the subagent can self-check before reporting.
113
+ - If a subagent encounters something unclear, it should report a blocker rather than guess.
114
+
115
+ ### After Subagents Return
116
+
117
+ 1. Read each subagent's report. Do not trust claims blindly \u2014 verify against actual files.
118
+ 2. Check for conflicts: did any subagent edit files outside its scope or overlap with another?
119
+ 3. Run integration verification (build, type check, tests) on the combined changes.
120
+ 4. Fix integration issues yourself \u2014 do not re-dispatch for small glue work.
121
+
122
+ ### When NOT to Parallelize
123
+
124
+ - Tasks share mutable state (same database migration, same config file).
125
+ - You are debugging \u2014 investigate root cause sequentially before dispatching fixes.
126
+ - The overhead of writing a self-contained prompt exceeds the time saved by parallelism (trivial single-file edits).
86
127
 
87
128
  ## PROGRESS.md Format
88
129
 
@@ -122,21 +163,22 @@ Each iteration should complete a coherent unit (not trivial single-file churn),
122
163
 
123
164
  **If tasks remain:** update \`PROGRESS.md\` and stop. Do NOT output completion signal.
124
165
 
125
- **When all work is done**, output completion signal only after all are true:
126
- - Every task in \`PROGRESS.md\` is complete
127
- - All specs in \`specs/\` are implemented
128
- - Required verification commands pass
129
- - No active blockers remain
130
- - Implementation artifacts are source-code-compliant with specs (not forbidden static fallback)
131
- - Generated deployment output conforms to Build Output API for the target deploy platform
166
+ **When all work is done**, output completion signal. The bar is:
167
+ 1. All tasks in \`PROGRESS.md\` are checked off
168
+ 2. \`npm run build\` (or equivalent) exits 0
169
+ 3. No blockers in \`PROGRESS.md\`
170
+
171
+ That's it. Do NOT loop on cosmetic verification (curling pages, grepping HTML, re-reading files you just wrote). If it builds clean and tasks are done, you are done.
132
172
 
133
173
  When complete, output exactly this on its own line:
134
174
 
135
175
  ${STOP_WORD}
136
176
 
137
- Without this signal, the system keeps launching new iterations.`;
177
+ **You MUST include text in every response.** If you only used tools, still output a one-line status summary. Responses with zero text cause unnecessary continuation.
178
+
179
+ Without the completion signal, the system keeps launching new iterations.`;
138
180
  var DEFAULT_TIMEOUT = 36e5;
139
- var DEFAULT_MAX_ITERATIONS = 100;
181
+ var DEFAULT_MAX_ITERATIONS = 20;
140
182
  var DEFAULT_MODEL = "vercel/anthropic/claude-opus-4.6";
141
183
  var DREAM_VERSION = readDreamVersion();
142
184
  var DEFAULT_BOOTSTRAP_SKILL_REPOS = [
@@ -321,6 +363,8 @@ ${INDENT_MAIN}${red("\u2717")} Runtime bootstrap failed: ${message}
321
363
  }
322
364
  printStep("Starting OpenCode...");
323
365
  const oidcToken = process.env.VERCEL_OIDC_TOKEN;
366
+ const gatewayApiKey = process.env.AI_GATEWAY_API_KEY;
367
+ const providerOptions = oidcToken ? { apiKey: oidcToken, headers: { "ai-gateway-auth-method": "oidc" } } : gatewayApiKey ? { apiKey: gatewayApiKey } : void 0;
324
368
  const { client, server } = await createOpencode({
325
369
  port: 0,
326
370
  config: {
@@ -338,15 +382,8 @@ ${INDENT_MAIN}${red("\u2717")} Runtime bootstrap failed: ${message}
338
382
  },
339
383
  provider: {
340
384
  vercel: {
341
- env: ["VERCEL_API_KEY", "VERCEL_OIDC_TOKEN"],
342
- ...oidcToken && {
343
- options: {
344
- apiKey: oidcToken,
345
- headers: {
346
- "ai-gateway-auth-method": "oidc"
347
- }
348
- }
349
- }
385
+ env: ["AI_GATEWAY_API_KEY", "VERCEL_API_KEY", "VERCEL_OIDC_TOKEN"],
386
+ ...providerOptions && { options: providerOptions }
350
387
  }
351
388
  },
352
389
  enabled_providers: ["vercel"]
@@ -385,6 +422,8 @@ ${INDENT_MAIN}Run ${cyan("opencode")} and authenticate the ${bold(providerId)} p
385
422
  process.on("SIGTERM", cleanup);
386
423
  const startTime = Date.now();
387
424
  let iteration = 0;
425
+ let noEditStreak = 0;
426
+ const MAX_NO_EDIT_STREAK = 3;
388
427
  try {
389
428
  while (iteration < maxIterations) {
390
429
  const elapsed = Date.now() - startTime;
@@ -425,10 +464,27 @@ ${INDENT_MAIN}${red("\u2717")} Session failed after ${bold(String(iteration))} i
425
464
  );
426
465
  process.exit(1);
427
466
  }
428
- printLine(
429
- `${INDENT_MAIN}${cyan(`[${iteration}]`)} ${dim(`${formatTime(iterElapsed)} \xB7 continuing...`)}
467
+ if (result === "stalled") {
468
+ noEditStreak++;
469
+ if (noEditStreak >= MAX_NO_EDIT_STREAK) {
470
+ printLine(
471
+ `
472
+ ${INDENT_MAIN}${red("\u2717")} Stalled: ${MAX_NO_EDIT_STREAK} consecutive iterations with no file edits. Stopping.
430
473
  `
431
- );
474
+ );
475
+ process.exit(1);
476
+ }
477
+ printLine(
478
+ `${INDENT_MAIN}${cyan(`[${iteration}]`)} ${dim(`${formatTime(iterElapsed)} \xB7 no edits (${noEditStreak}/${MAX_NO_EDIT_STREAK}) \xB7 continuing...`)}
479
+ `
480
+ );
481
+ } else {
482
+ noEditStreak = 0;
483
+ printLine(
484
+ `${INDENT_MAIN}${cyan(`[${iteration}]`)} ${dim(`${formatTime(iterElapsed)} \xB7 continuing...`)}
485
+ `
486
+ );
487
+ }
432
488
  }
433
489
  printLine(`
434
490
  ${INDENT_MAIN}${red("\u2717")} Max iterations reached
@@ -463,6 +519,7 @@ async function runSession(client, title, systemPrompt, verbose) {
463
519
  }
464
520
  let responseText = "";
465
521
  let toolCalls = 0;
522
+ let fileEdits = 0;
466
523
  let totalCost = 0;
467
524
  let totalTokensIn = 0;
468
525
  let totalTokensOut = 0;
@@ -536,6 +593,7 @@ ${INDENT_SESSION}`);
536
593
  if (event.type === "file.edited") {
537
594
  const file = event.properties.file;
538
595
  if (file) {
596
+ fileEdits++;
539
597
  if (lastOutput === "text") process.stdout.write("\n");
540
598
  const relative = file.replace(`${process.cwd()}/`, "");
541
599
  printSession(`${green("\u270E")} ${relative}`);
@@ -558,10 +616,15 @@ ${INDENT_SESSION}`);
558
616
  const cost = totalCost > 0 ? ` \xB7 $${totalCost.toFixed(2)}` : "";
559
617
  printSessionDim(`${toolCalls} tools \xB7 ${tokens}${cost}`);
560
618
  if (responseText.length === 0) {
619
+ if (toolCalls > 0) {
620
+ printSessionDim("no text response, continuing...");
621
+ return fileEdits > 0 ? "continue" : "stalled";
622
+ }
561
623
  printSessionError("No response from model");
562
624
  return "error";
563
625
  }
564
- return responseText.includes(STOP_WORD) ? "done" : "continue";
626
+ if (responseText.includes(STOP_WORD)) return "done";
627
+ return fileEdits > 0 ? "continue" : "stalled";
565
628
  }
566
629
  function formatTime(ms) {
567
630
  if (ms < 1e3) return `${ms}ms`;
package/package.json CHANGED
@@ -1,13 +1,14 @@
1
1
  {
2
2
  "name": "@vercel/dream",
3
- "version": "0.2.12",
3
+ "version": "0.3.1",
4
4
  "description": "A CLI that runs OpenCode in a loop until specs are complete",
5
5
  "type": "module",
6
6
  "bin": {
7
- "dream": "./dist/dream.js"
7
+ "dream": "./bin/dream.mjs"
8
8
  },
9
9
  "files": [
10
- "dist"
10
+ "dist",
11
+ "bin/dream.mjs"
11
12
  ],
12
13
  "dependencies": {
13
14
  "@ai-sdk/gateway": "^3.0.39",