@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 +2 -0
- package/dist/dream.js +93 -30
- package/package.json +4 -3
package/bin/dream.mjs
ADDED
package/dist/dream.js
CHANGED
|
@@ -73,16 +73,57 @@ Each iteration follows this cycle:
|
|
|
73
73
|
|
|
74
74
|
## Subagent-First Execution
|
|
75
75
|
|
|
76
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
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
|
-
|
|
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 =
|
|
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
|
-
...
|
|
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
|
-
|
|
429
|
-
|
|
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
|
-
|
|
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.
|
|
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": "./
|
|
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",
|