rivet-design 0.9.2 → 0.9.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/mcp/agent-variants/SessionStore.d.ts +78 -2
- package/dist/mcp/agent-variants/SessionStore.d.ts.map +1 -1
- package/dist/mcp/agent-variants/SessionStore.js +464 -62
- package/dist/mcp/agent-variants/SessionStore.js.map +1 -1
- package/dist/mcp/agent-variants/WorktreeOrchestrator.d.ts +331 -9
- package/dist/mcp/agent-variants/WorktreeOrchestrator.d.ts.map +1 -1
- package/dist/mcp/agent-variants/WorktreeOrchestrator.js +1985 -61
- package/dist/mcp/agent-variants/WorktreeOrchestrator.js.map +1 -1
- package/dist/mcp/agent-variants/WorktreeOrchestrator.testHelpers.d.ts +65 -0
- package/dist/mcp/agent-variants/WorktreeOrchestrator.testHelpers.d.ts.map +1 -0
- package/dist/mcp/agent-variants/WorktreeOrchestrator.testHelpers.js +162 -0
- package/dist/mcp/agent-variants/WorktreeOrchestrator.testHelpers.js.map +1 -0
- package/dist/mcp/agent-variants/contracts.d.ts +2508 -10
- package/dist/mcp/agent-variants/contracts.d.ts.map +1 -1
- package/dist/mcp/agent-variants/contracts.js +295 -5
- package/dist/mcp/agent-variants/contracts.js.map +1 -1
- package/dist/mcp/agent-variants/createProjectArtifacts.d.ts +78 -0
- package/dist/mcp/agent-variants/createProjectArtifacts.d.ts.map +1 -0
- package/dist/mcp/agent-variants/createProjectArtifacts.js +123 -0
- package/dist/mcp/agent-variants/createProjectArtifacts.js.map +1 -0
- package/dist/mcp/agent-variants/createZeroToOneTool.d.ts +241 -0
- package/dist/mcp/agent-variants/createZeroToOneTool.d.ts.map +1 -0
- package/dist/mcp/agent-variants/createZeroToOneTool.js +213 -0
- package/dist/mcp/agent-variants/createZeroToOneTool.js.map +1 -0
- package/dist/mcp/agent-variants/designContextStore.d.ts +160 -0
- package/dist/mcp/agent-variants/designContextStore.d.ts.map +1 -0
- package/dist/mcp/agent-variants/designContextStore.js +295 -0
- package/dist/mcp/agent-variants/designContextStore.js.map +1 -0
- package/dist/mcp/agent-variants/elementRefToTarget.d.ts +21 -0
- package/dist/mcp/agent-variants/elementRefToTarget.d.ts.map +1 -0
- package/dist/mcp/agent-variants/elementRefToTarget.js +47 -0
- package/dist/mcp/agent-variants/elementRefToTarget.js.map +1 -0
- package/dist/mcp/agent-variants/errors.d.ts +1 -1
- package/dist/mcp/agent-variants/errors.d.ts.map +1 -1
- package/dist/mcp/agent-variants/errors.js +7 -0
- package/dist/mcp/agent-variants/errors.js.map +1 -1
- package/dist/mcp/agent-variants/index.d.ts +4 -2
- package/dist/mcp/agent-variants/index.d.ts.map +1 -1
- package/dist/mcp/agent-variants/index.js +7 -1
- package/dist/mcp/agent-variants/index.js.map +1 -1
- package/dist/mcp/agent-variants/inspirationDesignContext.d.ts +440 -0
- package/dist/mcp/agent-variants/inspirationDesignContext.d.ts.map +1 -0
- package/dist/mcp/agent-variants/inspirationDesignContext.js +2467 -0
- package/dist/mcp/agent-variants/inspirationDesignContext.js.map +1 -0
- package/dist/mcp/agent-variants/pendingChangesAdapter.d.ts.map +1 -1
- package/dist/mcp/agent-variants/pendingChangesAdapter.js +21 -7
- package/dist/mcp/agent-variants/pendingChangesAdapter.js.map +1 -1
- package/dist/mcp/agent-variants/previewQa.d.ts +61 -0
- package/dist/mcp/agent-variants/previewQa.d.ts.map +1 -0
- package/dist/mcp/agent-variants/previewQa.js +374 -0
- package/dist/mcp/agent-variants/previewQa.js.map +1 -0
- package/dist/mcp/agent-variants/sourceContext.d.ts +8 -0
- package/dist/mcp/agent-variants/sourceContext.d.ts.map +1 -0
- package/dist/mcp/agent-variants/sourceContext.js +183 -0
- package/dist/mcp/agent-variants/sourceContext.js.map +1 -0
- package/dist/mcp/agent-variants/tools.d.ts +36 -0
- package/dist/mcp/agent-variants/tools.d.ts.map +1 -1
- package/dist/mcp/agent-variants/tools.js +451 -19
- package/dist/mcp/agent-variants/tools.js.map +1 -1
- package/dist/mcp/changeBatchClassification.d.ts +30 -0
- package/dist/mcp/changeBatchClassification.d.ts.map +1 -0
- package/dist/mcp/changeBatchClassification.js +65 -0
- package/dist/mcp/changeBatchClassification.js.map +1 -0
- package/dist/mcp/server.d.ts.map +1 -1
- package/dist/mcp/server.js +258 -41
- package/dist/mcp/server.js.map +1 -1
- package/dist/prompts/agentModPrompts.js +4 -4
- package/dist/prompts/agentModPrompts.js.map +1 -1
- package/dist/proxy-middleware/proxy-config.d.ts.map +1 -1
- package/dist/proxy-middleware/proxy-config.js +1 -15
- package/dist/proxy-middleware/proxy-config.js.map +1 -1
- package/dist/routes/agentVariants.d.ts +3 -1
- package/dist/routes/agentVariants.d.ts.map +1 -1
- package/dist/routes/agentVariants.js +138 -13
- package/dist/routes/agentVariants.js.map +1 -1
- package/dist/routes/mcp.d.ts +7 -1
- package/dist/routes/mcp.d.ts.map +1 -1
- package/dist/routes/mcp.js +139 -16
- package/dist/routes/mcp.js.map +1 -1
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +23 -5
- package/dist/server.js.map +1 -1
- package/dist/services/ProjectDetectionService.d.ts.map +1 -1
- package/dist/services/ProjectDetectionService.js +9 -0
- package/dist/services/ProjectDetectionService.js.map +1 -1
- package/dist/services/SessionBridgeService.d.ts +22 -0
- package/dist/services/SessionBridgeService.d.ts.map +1 -1
- package/dist/services/SessionBridgeService.js +61 -0
- package/dist/services/SessionBridgeService.js.map +1 -1
- package/dist/services/TelemetryService.d.ts +121 -0
- package/dist/services/TelemetryService.d.ts.map +1 -1
- package/dist/services/TelemetryService.js +155 -0
- package/dist/services/TelemetryService.js.map +1 -1
- package/dist/services/WorktreeManager.d.ts +116 -6
- package/dist/services/WorktreeManager.d.ts.map +1 -1
- package/dist/services/WorktreeManager.js +394 -19
- package/dist/services/WorktreeManager.js.map +1 -1
- package/dist/services/agent/AgentModService.js +6 -6
- package/dist/services/agent/AgentModService.js.map +1 -1
- package/dist/services/templates/designCatalog.d.ts +27 -0
- package/dist/services/templates/designCatalog.d.ts.map +1 -0
- package/dist/services/templates/designCatalog.js +141 -0
- package/dist/services/templates/designCatalog.js.map +1 -0
- package/dist/services/templates/designmd/airbnb.md +545 -0
- package/dist/services/templates/designmd/airtable.md +554 -0
- package/dist/services/templates/designmd/apple.md +562 -0
- package/dist/services/templates/designmd/binance.md +634 -0
- package/dist/services/templates/designmd/bmw-m.md +503 -0
- package/dist/services/templates/designmd/bmw.md +544 -0
- package/dist/services/templates/designmd/bugatti.md +454 -0
- package/dist/services/templates/designmd/cal.md +542 -0
- package/dist/services/templates/designmd/claude.md +589 -0
- package/dist/services/templates/designmd/clay.md +541 -0
- package/dist/services/templates/designmd/cohere.md +451 -0
- package/dist/services/templates/designmd/cursor.md +537 -0
- package/dist/services/templates/designmd/expo.md +526 -0
- package/dist/services/templates/designmd/figma.md +578 -0
- package/dist/services/templates/designmd/framer.md +544 -0
- package/dist/services/templates/designmd/hp.md +670 -0
- package/dist/services/templates/designmd/linear.app.md +548 -0
- package/dist/services/templates/designmd/mintlify.md +852 -0
- package/dist/services/templates/designmd/miro.md +825 -0
- package/dist/services/templates/designmd/notion.md +821 -0
- package/dist/services/templates/designmd/raycast.md +669 -0
- package/dist/services/templates/designmd/resend.md +585 -0
- package/dist/services/templates/designmd/sentry.md +262 -0
- package/dist/services/templates/designmd/shopify.md +350 -0
- package/dist/services/templates/designmd/spotify.md +246 -0
- package/dist/services/templates/designmd/stripe.md +322 -0
- package/dist/services/templates/designmd/supabase.md +255 -0
- package/dist/services/templates/designmd/superhuman.md +252 -0
- package/dist/services/templates/designmd/uber.md +295 -0
- package/dist/services/templates/designmd/vercel.md +310 -0
- package/dist/services/templates/viteReactTs.d.ts +48 -0
- package/dist/services/templates/viteReactTs.d.ts.map +1 -0
- package/dist/services/templates/viteReactTs.js +274 -0
- package/dist/services/templates/viteReactTs.js.map +1 -0
- package/dist/types/change-request-types.d.ts +29 -3
- package/dist/types/change-request-types.d.ts.map +1 -1
- package/dist/utils/skills/claude-skill.d.ts +2 -2
- package/dist/utils/skills/claude-skill.d.ts.map +1 -1
- package/dist/utils/skills/claude-skill.js +19 -98
- package/dist/utils/skills/claude-skill.js.map +1 -1
- package/dist/utils/skills/cursor-rules.d.ts +2 -2
- package/dist/utils/skills/cursor-rules.d.ts.map +1 -1
- package/dist/utils/skills/cursor-rules.js +15 -80
- package/dist/utils/skills/cursor-rules.js.map +1 -1
- package/dist/utils/skills/shared-variants-protocol.d.ts +23 -0
- package/dist/utils/skills/shared-variants-protocol.d.ts.map +1 -0
- package/dist/utils/skills/shared-variants-protocol.js +130 -0
- package/dist/utils/skills/shared-variants-protocol.js.map +1 -0
- package/package.json +6 -6
- package/src/ui/dist/assets/main-CpX7fB64.js +382 -0
- package/src/ui/dist/assets/main-Qqe2_oMT.css +1 -0
- package/src/ui/dist/index.html +2 -2
- package/src/ui/dist/assets/main-AsPCtLsx.js +0 -382
- package/src/ui/dist/assets/main-BzmseUDd.css +0 -1
|
@@ -1,11 +1,59 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
2
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.normalizeAgentOutput = exports.slugifyPrompt = void 0;
|
|
3
7
|
exports.registerAgentVariantsTools = registerAgentVariantsTools;
|
|
8
|
+
exports.buildQaFailurePrompt = buildQaFailurePrompt;
|
|
9
|
+
const fs_1 = __importDefault(require("fs"));
|
|
10
|
+
const os_1 = __importDefault(require("os"));
|
|
11
|
+
const path_1 = __importDefault(require("path"));
|
|
4
12
|
const contracts_1 = require("./contracts");
|
|
5
13
|
const errors_1 = require("./errors");
|
|
14
|
+
const createZeroToOneTool_1 = require("./createZeroToOneTool");
|
|
15
|
+
Object.defineProperty(exports, "slugifyPrompt", { enumerable: true, get: function () { return createZeroToOneTool_1.slugifyPrompt; } });
|
|
16
|
+
const viteReactTs_1 = require("../../services/templates/viteReactTs");
|
|
17
|
+
const ProjectDetectionService_1 = require("../../services/ProjectDetectionService");
|
|
18
|
+
const SessionStore_1 = require("./SessionStore");
|
|
19
|
+
/**
|
|
20
|
+
* Coerce `output` to a structured value when an agent (incorrectly) sends a
|
|
21
|
+
* stringified JSON. The MCP schema accepts `z.unknown()` so the call doesn't
|
|
22
|
+
* fail validation, but downstream consumers (e.g. `output.html` in
|
|
23
|
+
* WorktreeOrchestrator) expect an object and silently no-op on strings —
|
|
24
|
+
* leaving the variant stuck at "not ready" until session expiry.
|
|
25
|
+
*/
|
|
26
|
+
const normalizeAgentOutput = (output) => {
|
|
27
|
+
if (typeof output !== 'string')
|
|
28
|
+
return output;
|
|
29
|
+
try {
|
|
30
|
+
return JSON.parse(output);
|
|
31
|
+
}
|
|
32
|
+
catch {
|
|
33
|
+
return output;
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
exports.normalizeAgentOutput = normalizeAgentOutput;
|
|
37
|
+
/**
|
|
38
|
+
* Reject caller-supplied fresh destinations at the generic variants boundary.
|
|
39
|
+
* Fresh projects must go through `create_zero_to_one_project`, where the
|
|
40
|
+
* server derives the destination path before delegating to the orchestrator.
|
|
41
|
+
*/
|
|
42
|
+
const validateFreshProjectInput = (args) => {
|
|
43
|
+
if (args.projectContext?.kind !== 'fresh')
|
|
44
|
+
return null;
|
|
45
|
+
return {
|
|
46
|
+
stage: 'failed',
|
|
47
|
+
errorCode: 'SCHEMA_VALIDATION_FAILED',
|
|
48
|
+
message: 'Fresh-project sessions must be started with create_zero_to_one_project so Rivet derives and validates the destination path.',
|
|
49
|
+
};
|
|
50
|
+
};
|
|
6
51
|
function registerAgentVariantsTools(mcp, deps) {
|
|
7
|
-
mcp.tool('propose_variants', '
|
|
52
|
+
mcp.tool('propose_variants', 'Stage 1 of the legacy variants flow with an in-chat brief approval gate. Prefer `start_variants` for new code paths — it collapses propose + report_briefs + approve + request_work into a single call. Use this only when the agent needs the user to review briefs before generation. Returns { sessionId, briefWorkItem }. Full protocol in the rivet skill.', contracts_1.proposeVariantsInput, async (args) => {
|
|
8
53
|
try {
|
|
54
|
+
const failure = validateFreshProjectInput(args);
|
|
55
|
+
if (failure)
|
|
56
|
+
return jsonResponse(failure);
|
|
9
57
|
const result = deps.orchestrator.propose({
|
|
10
58
|
sessionId: args.sessionId,
|
|
11
59
|
prompt: args.prompt,
|
|
@@ -13,6 +61,21 @@ function registerAgentVariantsTools(mcp, deps) {
|
|
|
13
61
|
target: args.target,
|
|
14
62
|
projectContext: args.projectContext,
|
|
15
63
|
});
|
|
64
|
+
if (result.stage === 'awaiting_source_plan') {
|
|
65
|
+
const out = {
|
|
66
|
+
sessionId: result.sessionId,
|
|
67
|
+
stage: 'awaiting_source_plan',
|
|
68
|
+
sourcePlanWorkItem: {
|
|
69
|
+
id: result.sourcePlanWorkItem.id,
|
|
70
|
+
kind: 'source_plan',
|
|
71
|
+
attempt: result.sourcePlanWorkItem.attempt,
|
|
72
|
+
input: result.sourcePlanWorkItem.input,
|
|
73
|
+
output_schema: SessionStore_1.SOURCE_PLAN_OUTPUT_SCHEMA,
|
|
74
|
+
},
|
|
75
|
+
nextAction: 'continue_variants',
|
|
76
|
+
};
|
|
77
|
+
return jsonResponse(out);
|
|
78
|
+
}
|
|
16
79
|
const out = {
|
|
17
80
|
sessionId: result.sessionId,
|
|
18
81
|
stage: 'awaiting_briefs',
|
|
@@ -21,7 +84,7 @@ function registerAgentVariantsTools(mcp, deps) {
|
|
|
21
84
|
kind: 'brief',
|
|
22
85
|
attempt: result.briefWorkItem.attempt,
|
|
23
86
|
input: result.briefWorkItem.input,
|
|
24
|
-
output_schema: { briefs: 'Array<{briefId, label, body}>' },
|
|
87
|
+
output_schema: { briefs: 'Array<{briefId, label: "≤4-word title", body: "ONE sentence ≤12 words"}>' },
|
|
25
88
|
},
|
|
26
89
|
nextAction: 'report_variant_briefs',
|
|
27
90
|
};
|
|
@@ -31,7 +94,7 @@ function registerAgentVariantsTools(mcp, deps) {
|
|
|
31
94
|
return errorResponse(err);
|
|
32
95
|
}
|
|
33
96
|
});
|
|
34
|
-
mcp.tool('report_variant_briefs', '
|
|
97
|
+
mcp.tool('report_variant_briefs', 'Report drafted briefs from the leased brief work item. Each brief: label ≤ 4 words, body = exactly ONE sentence ≤ 12 words — a single evocative descriptor, no bullets, no lists, no multi-clause run-ons. Body is shown directly to the user in the variants panel so it must be concise and immediately scannable. On success, transitions to awaiting_approval.', contracts_1.reportVariantBriefsInput, async (args) => {
|
|
35
98
|
try {
|
|
36
99
|
const result = deps.orchestrator.reportBriefs({
|
|
37
100
|
sessionId: args.sessionId,
|
|
@@ -43,6 +106,7 @@ function registerAgentVariantsTools(mcp, deps) {
|
|
|
43
106
|
const out = {
|
|
44
107
|
stage: 'awaiting_approval',
|
|
45
108
|
briefs: result.briefs,
|
|
109
|
+
approvalPrompt: buildApprovalPrompt(result.briefs),
|
|
46
110
|
nextAction: 'continue_variants',
|
|
47
111
|
};
|
|
48
112
|
return jsonResponse(out);
|
|
@@ -51,8 +115,45 @@ function registerAgentVariantsTools(mcp, deps) {
|
|
|
51
115
|
return errorResponse(err);
|
|
52
116
|
}
|
|
53
117
|
});
|
|
54
|
-
mcp.tool('
|
|
118
|
+
mcp.tool('report_source_plan', 'Report the consolidated source plan for a leased source_plan work item. Combines URL/role classification, source research findings, browser-extracted DESIGN.md per design_source URL, and the static_preview vs vite_app execution decision. Choose vite_app when the request needs large local assets (e.g. GLB models), model-viewer, Three.js, route structure, package dependencies, or files under public/; choose static_preview for self-contained HTML/CSS/JS prototypes. If the requirement is ambiguous, set executionPlan.userQuestion instead of guessing — Rivet will surface it as a clarification blocker at approve time. Reports unlock the brief work item for source-grounded fresh-project sessions.', contracts_1.reportSourcePlanInput, async (args) => {
|
|
119
|
+
try {
|
|
120
|
+
const result = deps.orchestrator.reportSourcePlan({
|
|
121
|
+
sessionId: args.sessionId,
|
|
122
|
+
workItemId: args.workItemId,
|
|
123
|
+
leaseId: args.leaseId,
|
|
124
|
+
attempt: args.attempt,
|
|
125
|
+
sourcePlan: args.sourcePlan,
|
|
126
|
+
});
|
|
127
|
+
const plan = args.sourcePlan.executionPlan;
|
|
128
|
+
const out = {
|
|
129
|
+
stage: 'awaiting_briefs',
|
|
130
|
+
briefWorkItem: {
|
|
131
|
+
id: result.briefWorkItem.id,
|
|
132
|
+
kind: 'brief',
|
|
133
|
+
attempt: result.briefWorkItem.attempt,
|
|
134
|
+
input: result.briefWorkItem.input,
|
|
135
|
+
output_schema: {
|
|
136
|
+
briefs: 'Array<{briefId, label: "≤4-word title", body: "ONE sentence ≤12 words"}>',
|
|
137
|
+
},
|
|
138
|
+
},
|
|
139
|
+
executionPlan: {
|
|
140
|
+
mode: plan.mode,
|
|
141
|
+
confidence: plan.confidence,
|
|
142
|
+
reason: plan.reason,
|
|
143
|
+
assetCount: plan.assetPlan?.length ?? 0,
|
|
144
|
+
runtimeRequirementCount: plan.runtimeRequirements?.length ?? 0,
|
|
145
|
+
},
|
|
146
|
+
nextAction: 'report_variant_briefs',
|
|
147
|
+
};
|
|
148
|
+
return jsonResponse(out);
|
|
149
|
+
}
|
|
150
|
+
catch (err) {
|
|
151
|
+
return errorResponse(err);
|
|
152
|
+
}
|
|
153
|
+
});
|
|
154
|
+
mcp.tool('approve_variant_briefs', 'Call AFTER showing the briefs to the user in chat and getting an affirmative ("looks good", "yep", "go") OR refined selections from them. Set confirmedByUser=true when the user approves. Only use bypassRequestedByUser=true (with bypassReason) if the user explicitly asks to bypass confirmation. Provide briefIds for ALL the briefs the user wants generated (typically all of them). Each approved brief gets a parallel code-gen work item — Rivet provisions one isolated worktree per item. Advance via continue_variants(action="request_work") to lease and run them in parallel. For tweak-with-feedback, use the selections form with bodyOverride per brief.', contracts_1.approveVariantBriefsInput, async (args) => {
|
|
55
155
|
try {
|
|
156
|
+
assertExplicitUserConfirmation('approve_variant_briefs', args, 'approve variant briefs');
|
|
56
157
|
const selections = args.selections ??
|
|
57
158
|
(args.briefIds ?? []).map((briefId) => ({ briefId }));
|
|
58
159
|
if (selections.length === 0) {
|
|
@@ -75,8 +176,9 @@ function registerAgentVariantsTools(mcp, deps) {
|
|
|
75
176
|
return errorResponse(err);
|
|
76
177
|
}
|
|
77
178
|
});
|
|
78
|
-
mcp.tool('commit_variant', "Call AFTER all variants have been generated AND you've shown each variant's diff/changes to the user in chat AND the user has picked one. Pass the variantId (the workItemId of the chosen variant). Rivet looks up that variant's captured diff and enqueues it onto the existing pending-changes channel — call get_pending_changes next to retrieve and apply. Idempotent on (sessionId, variantId).", contracts_1.commitVariantInput, async (args) => {
|
|
179
|
+
mcp.tool('commit_variant', "Call AFTER all variants have been generated AND you've shown each variant's diff/changes to the user in chat AND the user has picked one. Set confirmedByUser=true when the user confirms the pick. Only use bypassRequestedByUser=true (with bypassReason) if the user explicitly asks to bypass confirmation. Pass the variantId (the workItemId of the chosen variant). Rivet looks up that variant's captured diff and enqueues it onto the existing pending-changes channel — call get_pending_changes next to retrieve and apply. Idempotent on (sessionId, variantId).", contracts_1.commitVariantInput, async (args) => {
|
|
79
180
|
try {
|
|
181
|
+
assertExplicitUserConfirmation('commit_variant', args, 'commit a variant');
|
|
80
182
|
const result = await deps.orchestrator.commitVariant({
|
|
81
183
|
sessionId: args.sessionId,
|
|
82
184
|
variantId: args.variantId,
|
|
@@ -86,6 +188,8 @@ function registerAgentVariantsTools(mcp, deps) {
|
|
|
86
188
|
enqueued: result.enqueued,
|
|
87
189
|
duplicate: result.duplicate,
|
|
88
190
|
changedFilesCount: result.changedFilesCount,
|
|
191
|
+
payloadKind: result.payloadKind,
|
|
192
|
+
destinationPath: result.destinationPath,
|
|
89
193
|
};
|
|
90
194
|
return jsonResponse(out);
|
|
91
195
|
}
|
|
@@ -93,7 +197,7 @@ function registerAgentVariantsTools(mcp, deps) {
|
|
|
93
197
|
return errorResponse(err);
|
|
94
198
|
}
|
|
95
199
|
});
|
|
96
|
-
mcp.tool('continue_variants', 'Long-poll/state-pump the variants flow. action=check returns immediately; action=wait blocks up to ~5min for
|
|
200
|
+
mcp.tool('continue_variants', 'Long-poll/state-pump the variants flow. action=check returns immediately; action=wait blocks up to ~5min for state changes; action=request_work leases ready work items (source_research, static_preview, or code_gen depending on stage). static_preview is for fresh zero-to-one sessions and should return {html, css?, js?} so Rivet can show fast visual previews before Vite/code generation finishes.', contracts_1.continueVariantsInput, async (args) => {
|
|
97
201
|
try {
|
|
98
202
|
const stage = deps.orchestrator.getStage(args.sessionId);
|
|
99
203
|
if (stage === 'awaiting_briefs') {
|
|
@@ -102,24 +206,35 @@ function registerAgentVariantsTools(mcp, deps) {
|
|
|
102
206
|
throw new errors_1.AgentVariantsError('INVALID_STAGE_ACTION', 'Run the brief work item and call report_variant_briefs before continue_variants');
|
|
103
207
|
}
|
|
104
208
|
if (stage === 'awaiting_approval') {
|
|
209
|
+
const briefs = deps.orchestrator.getBriefs(args.sessionId);
|
|
105
210
|
return jsonResponse({
|
|
106
211
|
stage: 'awaiting_approval',
|
|
107
|
-
briefs
|
|
212
|
+
briefs,
|
|
213
|
+
approvalPrompt: buildApprovalPrompt(briefs),
|
|
108
214
|
});
|
|
109
215
|
}
|
|
110
|
-
if (
|
|
111
|
-
|
|
216
|
+
if (args.action === 'request_work' &&
|
|
217
|
+
(stage === 'awaiting_source_plan' ||
|
|
218
|
+
stage === 'work_items_ready' ||
|
|
219
|
+
stage === 'waiting_for_results')) {
|
|
220
|
+
// SessionStore.requestWork accepts both stages and expires stale
|
|
221
|
+
// leases before issuing new ones, so this also recycles wedged
|
|
222
|
+
// variants whose leases expired while the session was already in
|
|
223
|
+
// waiting_for_results.
|
|
112
224
|
const lease = deps.orchestrator.requestWork({
|
|
113
225
|
sessionId: args.sessionId,
|
|
114
226
|
leaseOwner: deps.leaseOwner(),
|
|
115
227
|
requestedLeaseCount: args.requestedLeaseCount,
|
|
116
228
|
});
|
|
117
|
-
|
|
118
|
-
|
|
229
|
+
const postLeaseStage = deps.orchestrator.getStage(args.sessionId);
|
|
230
|
+
const leasePayload = {
|
|
119
231
|
leaseId: lease.leaseId,
|
|
120
232
|
leaseTtlMs: lease.leaseTtlMs,
|
|
121
233
|
leasedWorkItems: lease.leasedWorkItems,
|
|
122
|
-
}
|
|
234
|
+
};
|
|
235
|
+
return jsonResponse(postLeaseStage === 'awaiting_source_plan'
|
|
236
|
+
? { stage: 'awaiting_source_plan', ...leasePayload }
|
|
237
|
+
: { stage: 'work_items_ready', ...leasePayload });
|
|
123
238
|
}
|
|
124
239
|
if (stage === 'work_items_ready' || stage === 'waiting_for_results') {
|
|
125
240
|
return jsonResponse({
|
|
@@ -127,17 +242,36 @@ function registerAgentVariantsTools(mcp, deps) {
|
|
|
127
242
|
progress: deps.orchestrator.getProgress(args.sessionId),
|
|
128
243
|
});
|
|
129
244
|
}
|
|
245
|
+
if (stage === 'awaiting_source_plan') {
|
|
246
|
+
return jsonResponse({
|
|
247
|
+
stage: 'awaiting_source_plan',
|
|
248
|
+
progress: deps.orchestrator.getProgress(args.sessionId),
|
|
249
|
+
});
|
|
250
|
+
}
|
|
130
251
|
// Terminal stages
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
252
|
+
{
|
|
253
|
+
const summary = deps.orchestrator.getSummary(args.sessionId);
|
|
254
|
+
const variants = deps.orchestrator.getVariants(args.sessionId);
|
|
255
|
+
const previewUrls = variants
|
|
256
|
+
.filter((v) => v.preview?.kind === 'static_artifact')
|
|
257
|
+
.map((v) => ({
|
|
258
|
+
label: v.label,
|
|
259
|
+
url: v.preview.url,
|
|
260
|
+
}));
|
|
261
|
+
const qaSurfacing = buildQaSurfacing(variants);
|
|
262
|
+
return jsonResponse({
|
|
263
|
+
stage,
|
|
264
|
+
summary,
|
|
265
|
+
...(previewUrls.length > 0 ? { previewUrls } : {}),
|
|
266
|
+
...qaSurfacing,
|
|
267
|
+
});
|
|
268
|
+
}
|
|
135
269
|
}
|
|
136
270
|
catch (err) {
|
|
137
271
|
return errorResponse(err);
|
|
138
272
|
}
|
|
139
273
|
});
|
|
140
|
-
mcp.tool('report_variant_complete', "Agent reports per-
|
|
274
|
+
mcp.tool('report_variant_complete', "Agent reports per-work-item status: running (heartbeat), succeeded, failed, or cancelled. Requires a valid leaseId and matching attempt obtained from continue_variants(action='request_work'). For benchmark instrumentation, agents can optionally include tokensIn, tokensOut, and model in the call so Rivet can record cost per variant.", contracts_1.reportVariantCompleteInput, async (args) => {
|
|
141
275
|
try {
|
|
142
276
|
const result = await deps.orchestrator.reportComplete({
|
|
143
277
|
sessionId: args.sessionId,
|
|
@@ -145,17 +279,31 @@ function registerAgentVariantsTools(mcp, deps) {
|
|
|
145
279
|
leaseId: args.leaseId,
|
|
146
280
|
attempt: args.attempt,
|
|
147
281
|
status: args.status,
|
|
148
|
-
output: args.output,
|
|
282
|
+
output: (0, exports.normalizeAgentOutput)(args.output),
|
|
149
283
|
error: args.error,
|
|
284
|
+
tokensIn: args.tokensIn,
|
|
285
|
+
tokensOut: args.tokensOut,
|
|
286
|
+
model: args.model,
|
|
150
287
|
});
|
|
151
288
|
let out;
|
|
152
289
|
if (result.stage === 'ready' ||
|
|
153
290
|
result.stage === 'degraded' ||
|
|
154
291
|
result.stage === 'failed' ||
|
|
155
292
|
result.stage === 'cancelled') {
|
|
293
|
+
const summary = result.summary ?? deps.orchestrator.getSummary(args.sessionId);
|
|
294
|
+
const variants = deps.orchestrator.getVariants(args.sessionId);
|
|
295
|
+
const previewUrls = variants
|
|
296
|
+
.filter((v) => v.preview?.kind === 'static_artifact')
|
|
297
|
+
.map((v) => ({
|
|
298
|
+
label: v.label,
|
|
299
|
+
url: v.preview.url,
|
|
300
|
+
}));
|
|
301
|
+
const qaSurfacing = buildQaSurfacing(variants);
|
|
156
302
|
out = {
|
|
157
303
|
stage: result.stage,
|
|
158
|
-
summary
|
|
304
|
+
summary,
|
|
305
|
+
...(previewUrls.length > 0 ? { previewUrls } : {}),
|
|
306
|
+
...qaSurfacing,
|
|
159
307
|
};
|
|
160
308
|
}
|
|
161
309
|
else {
|
|
@@ -186,6 +334,39 @@ function registerAgentVariantsTools(mcp, deps) {
|
|
|
186
334
|
return errorResponse(err);
|
|
187
335
|
}
|
|
188
336
|
});
|
|
337
|
+
mcp.tool('start_variants', 'Single-call kickoff for variants exploration. Spawns N variant worktrees, opens the visual editor, and returns a lease + worktreePaths — no follow-up detect_project / open_visual_editor / continue_variants needed. Pass `briefs` (one per variant) so each card has a distinct name and description; omitting them stubs every variant with the user prompt verbatim. `briefs.length` sets the count. mode="existing" for existing projects, "zero_to_one" for prompt-only fresh projects. For source-grounded fresh projects (inspiration URLs / custom design context) use create_zero_to_one_project instead. Full protocol in the rivet skill.', contracts_1.startVariantsInput, async (args) => {
|
|
338
|
+
try {
|
|
339
|
+
if (args.mode === 'zero_to_one') {
|
|
340
|
+
const out = await handleStartVariantsZeroToOne(args, deps);
|
|
341
|
+
return jsonResponse(out);
|
|
342
|
+
}
|
|
343
|
+
const out = await handleStartVariantsExisting(args, deps);
|
|
344
|
+
return jsonResponse(out);
|
|
345
|
+
}
|
|
346
|
+
catch (err) {
|
|
347
|
+
return errorResponse(err);
|
|
348
|
+
}
|
|
349
|
+
});
|
|
350
|
+
mcp.tool('cancel_variant', 'Cancel a single variant within an in-flight session without affecting its siblings. Called by the Rivet UI when the user clicks the cancel button on a variant card. Marks the variant cancelled and releases its lease; sibling variants continue. Idempotent on terminal states (already cancelled / succeeded / failed returns alreadyTerminal=true with the actual finalStatus). Per-variant worktree teardown happens at session commit/cancel time. Distinct from cancel_variants (plural), which kills the entire session.', contracts_1.cancelVariantInput, async (args) => {
|
|
351
|
+
try {
|
|
352
|
+
const result = await deps.orchestrator.cancelVariant({
|
|
353
|
+
sessionId: args.sessionId,
|
|
354
|
+
variantId: args.variantId,
|
|
355
|
+
reason: args.reason,
|
|
356
|
+
});
|
|
357
|
+
const out = {
|
|
358
|
+
sessionId: result.sessionId,
|
|
359
|
+
variantId: result.variantId,
|
|
360
|
+
finalStatus: result.finalStatus,
|
|
361
|
+
sessionStage: result.sessionStage,
|
|
362
|
+
alreadyTerminal: result.alreadyTerminal,
|
|
363
|
+
};
|
|
364
|
+
return jsonResponse(out);
|
|
365
|
+
}
|
|
366
|
+
catch (err) {
|
|
367
|
+
return errorResponse(err);
|
|
368
|
+
}
|
|
369
|
+
});
|
|
189
370
|
}
|
|
190
371
|
// --- Helpers --------------------------------------------------------------
|
|
191
372
|
// Return type is left implicit so the MCP SDK's overload selection picks the
|
|
@@ -218,4 +399,255 @@ function errorResponse(err) {
|
|
|
218
399
|
isError: true,
|
|
219
400
|
};
|
|
220
401
|
}
|
|
402
|
+
function assertExplicitUserConfirmation(toolName, confirmation, actionLabel) {
|
|
403
|
+
if (confirmation.confirmedByUser) {
|
|
404
|
+
return;
|
|
405
|
+
}
|
|
406
|
+
if (confirmation.bypassRequestedByUser &&
|
|
407
|
+
confirmation.bypassReason?.trim().length) {
|
|
408
|
+
return;
|
|
409
|
+
}
|
|
410
|
+
throw new errors_1.AgentVariantsError('MISSING_REQUIRED_INPUT', `${toolName} requires explicit user confirmation to ${actionLabel}. Set confirmedByUser=true after user confirmation, or set bypassRequestedByUser=true with bypassReason when the user explicitly asks to bypass.`);
|
|
411
|
+
}
|
|
412
|
+
function buildApprovalPrompt(briefs) {
|
|
413
|
+
const formattedBriefs = briefs
|
|
414
|
+
.map((brief, index) => `${index + 1}. name: ${brief.label}\n description: ${brief.body}`)
|
|
415
|
+
.join('\n');
|
|
416
|
+
return (`Review these variant briefs:\n${formattedBriefs}\n\n` +
|
|
417
|
+
'Do these look good, or do you want any adjustments before I proceed?');
|
|
418
|
+
}
|
|
419
|
+
/**
|
|
420
|
+
* Compose the QA surfacing block (`qaPrompt`, `qa[]`) attached to terminal
|
|
421
|
+
* tool responses. Returns an empty object when no variant has a recorded
|
|
422
|
+
* QA verdict so existing-project flows (which never trigger preview QA)
|
|
423
|
+
* remain a no-op.
|
|
424
|
+
*
|
|
425
|
+
* Exported indirectly via the orchestrator's terminal tool responses so
|
|
426
|
+
* the calling agent can show the user a concrete retry/continue/cancel
|
|
427
|
+
* choice when one or more variants fail QA.
|
|
428
|
+
*/
|
|
429
|
+
function buildQaSurfacing(variants) {
|
|
430
|
+
const withQa = variants.filter((v) => Boolean(v.qa) && v.qa.status !== 'not_run');
|
|
431
|
+
if (withQa.length === 0)
|
|
432
|
+
return {};
|
|
433
|
+
const qaEntries = withQa.map((v) => ({
|
|
434
|
+
workItemId: v.workItemId,
|
|
435
|
+
label: v.label,
|
|
436
|
+
qa: v.qa,
|
|
437
|
+
}));
|
|
438
|
+
const failures = withQa.filter((v) => v.qa.status === 'failed');
|
|
439
|
+
if (failures.length === 0) {
|
|
440
|
+
return { qa: qaEntries };
|
|
441
|
+
}
|
|
442
|
+
return {
|
|
443
|
+
qa: qaEntries,
|
|
444
|
+
qaPrompt: buildQaFailurePrompt(failures.map((v) => ({ label: v.label, qa: v.qa })), withQa.length - failures.length),
|
|
445
|
+
};
|
|
446
|
+
}
|
|
447
|
+
/**
|
|
448
|
+
* User-facing prompt template for QA failures. Lists each failed variant
|
|
449
|
+
* with its summary + first asset/console issue, then asks the user
|
|
450
|
+
* whether to retry, continue with healthy variants, or cancel. Kept as
|
|
451
|
+
* data (not a log line) so the calling agent can present the choice
|
|
452
|
+
* directly to the human.
|
|
453
|
+
*/
|
|
454
|
+
function buildQaFailurePrompt(failures, healthyCount) {
|
|
455
|
+
if (failures.length === 0) {
|
|
456
|
+
return '';
|
|
457
|
+
}
|
|
458
|
+
const lines = failures.map((failure) => {
|
|
459
|
+
const firstIssue = failure.qa.issues[0];
|
|
460
|
+
const issueDetail = firstIssue
|
|
461
|
+
? ` (${describeIssue(firstIssue.kind)}: ${firstIssue.detail}${firstIssue.message ? ` — ${firstIssue.message}` : ''})`
|
|
462
|
+
: '';
|
|
463
|
+
return `• ${failure.label}: ${failure.qa.summary}${issueDetail}`;
|
|
464
|
+
});
|
|
465
|
+
const healthyLine = healthyCount > 0
|
|
466
|
+
? `\n\n${healthyCount} other variant${healthyCount === 1 ? '' : 's'} passed QA and can still be committed.`
|
|
467
|
+
: '';
|
|
468
|
+
const intro = failures.length === 1
|
|
469
|
+
? '1 variant failed QA:'
|
|
470
|
+
: `${failures.length} variants failed QA:`;
|
|
471
|
+
return `${intro}\n${lines.join('\n')}${healthyLine}\n\nWould you like to retry the failed variant${failures.length === 1 ? '' : 's'}, continue with healthy variants only, or cancel?`;
|
|
472
|
+
}
|
|
473
|
+
const describeIssue = (kind) => {
|
|
474
|
+
switch (kind) {
|
|
475
|
+
case 'asset_load_failed':
|
|
476
|
+
return 'asset load failed';
|
|
477
|
+
case 'console_error':
|
|
478
|
+
return 'console/runtime error';
|
|
479
|
+
case 'preview_unavailable':
|
|
480
|
+
return 'preview unavailable';
|
|
481
|
+
}
|
|
482
|
+
};
|
|
483
|
+
/**
|
|
484
|
+
* Handle the zero-to-one branch of `start_variants`. Mirrors the
|
|
485
|
+
* destination-derivation, framework validation, and visual-editor
|
|
486
|
+
* auto-open behavior of `create_zero_to_one_project`, but skips the
|
|
487
|
+
* source-research / inspiration-extraction path. Source-grounded fresh
|
|
488
|
+
* projects must continue to use `create_zero_to_one_project`.
|
|
489
|
+
*/
|
|
490
|
+
async function handleStartVariantsZeroToOne(args, deps) {
|
|
491
|
+
const framework = args.framework ?? 'vite';
|
|
492
|
+
if (framework !== 'vite') {
|
|
493
|
+
return {
|
|
494
|
+
stage: 'failed',
|
|
495
|
+
errorCode: 'UNSUPPORTED_FRAMEWORK',
|
|
496
|
+
message: `start_variants(mode='zero_to_one') only supports framework='vite'; got '${framework}'.`,
|
|
497
|
+
};
|
|
498
|
+
}
|
|
499
|
+
const homedir = deps.homedir ?? os_1.default.homedir;
|
|
500
|
+
const destinationParent = args.destinationParent ?? homedir();
|
|
501
|
+
if (!path_1.default.isAbsolute(destinationParent)) {
|
|
502
|
+
return {
|
|
503
|
+
stage: 'failed',
|
|
504
|
+
errorCode: 'SCHEMA_VALIDATION_FAILED',
|
|
505
|
+
message: `destinationParent must be absolute; got '${destinationParent}'.`,
|
|
506
|
+
};
|
|
507
|
+
}
|
|
508
|
+
const slug = (0, createZeroToOneTool_1.slugifyPrompt)(args.prompt);
|
|
509
|
+
const destinationPath = path_1.default.join(destinationParent, slug);
|
|
510
|
+
if (!(0, viteReactTs_1.isDestinationEmpty)(destinationPath)) {
|
|
511
|
+
return {
|
|
512
|
+
stage: 'failed',
|
|
513
|
+
errorCode: 'DESTINATION_NOT_EMPTY',
|
|
514
|
+
message: `Destination '${destinationPath}' is not empty.`,
|
|
515
|
+
};
|
|
516
|
+
}
|
|
517
|
+
const hasSourceContext = args.sourceContext &&
|
|
518
|
+
((args.sourceContext.sourceUrls?.length ?? 0) > 0 ||
|
|
519
|
+
(args.sourceContext.sourceArtifacts?.length ?? 0) > 0 ||
|
|
520
|
+
Boolean(args.sourceContext.sourceIntent) ||
|
|
521
|
+
Boolean(args.sourceContext.artifact));
|
|
522
|
+
if (hasSourceContext) {
|
|
523
|
+
return {
|
|
524
|
+
stage: 'failed',
|
|
525
|
+
errorCode: 'INVALID_STAGE_ACTION',
|
|
526
|
+
message: "start_variants(mode='zero_to_one') cannot run source-grounded sessions. " +
|
|
527
|
+
'Use create_zero_to_one_project for inspiration URLs / source artifacts so the source_plan flow can run.',
|
|
528
|
+
};
|
|
529
|
+
}
|
|
530
|
+
fs_1.default.mkdirSync(destinationParent, { recursive: true });
|
|
531
|
+
const projectContext = {
|
|
532
|
+
kind: 'fresh',
|
|
533
|
+
workspacePath: destinationPath,
|
|
534
|
+
framework: 'vite',
|
|
535
|
+
};
|
|
536
|
+
const visualEditor = deps.ensureVisualEditorOpen
|
|
537
|
+
? await deps.ensureVisualEditorOpen({
|
|
538
|
+
projectPath: destinationPath,
|
|
539
|
+
framework: 'vite',
|
|
540
|
+
})
|
|
541
|
+
: undefined;
|
|
542
|
+
const result = await deps.orchestrator.startUnified({
|
|
543
|
+
prompt: args.prompt,
|
|
544
|
+
count: args.count,
|
|
545
|
+
target: args.target,
|
|
546
|
+
projectContext,
|
|
547
|
+
leaseOwner: deps.leaseOwner(),
|
|
548
|
+
briefs: args.briefs,
|
|
549
|
+
});
|
|
550
|
+
return assembleStartVariantsResponse({
|
|
551
|
+
mode: 'zero_to_one',
|
|
552
|
+
result,
|
|
553
|
+
destinationPath,
|
|
554
|
+
visualEditor,
|
|
555
|
+
});
|
|
556
|
+
}
|
|
557
|
+
/**
|
|
558
|
+
* Handle the existing-project branch of `start_variants`. Detects the
|
|
559
|
+
* project's framework server-side (cwd or the provided projectPath) so
|
|
560
|
+
* the agent doesn't need a separate detect_project call, auto-opens the
|
|
561
|
+
* visual editor on the resolved projectPath, and leases all variant
|
|
562
|
+
* work items so they're ready to code in the same response.
|
|
563
|
+
*/
|
|
564
|
+
async function handleStartVariantsExisting(args, deps) {
|
|
565
|
+
const projectPath = args.projectPath ?? process.cwd();
|
|
566
|
+
if (!path_1.default.isAbsolute(projectPath)) {
|
|
567
|
+
return {
|
|
568
|
+
stage: 'failed',
|
|
569
|
+
errorCode: 'SCHEMA_VALIDATION_FAILED',
|
|
570
|
+
message: `projectPath must be absolute; got '${projectPath}'.`,
|
|
571
|
+
};
|
|
572
|
+
}
|
|
573
|
+
let framework;
|
|
574
|
+
try {
|
|
575
|
+
framework = new ProjectDetectionService_1.ProjectDetectionService().detectFramework(projectPath);
|
|
576
|
+
}
|
|
577
|
+
catch (err) {
|
|
578
|
+
const msg = err instanceof Error ? err.message : 'Unknown detection error';
|
|
579
|
+
return {
|
|
580
|
+
stage: 'failed',
|
|
581
|
+
errorCode: 'SCHEMA_VALIDATION_FAILED',
|
|
582
|
+
message: `Could not detect project at '${projectPath}': ${msg}. Ensure it has a package.json, or pass projectPath explicitly.`,
|
|
583
|
+
};
|
|
584
|
+
}
|
|
585
|
+
// ensureVisualEditorOpen is typed for framework='vite' (matches the
|
|
586
|
+
// zero-to-one entry point), but it works against any projectPath. For
|
|
587
|
+
// existing projects with non-vite frameworks, the agent can still open
|
|
588
|
+
// the editor itself via the standalone open_visual_editor tool.
|
|
589
|
+
const visualEditor = deps.ensureVisualEditorOpen && framework === 'vite'
|
|
590
|
+
? await deps.ensureVisualEditorOpen({
|
|
591
|
+
projectPath,
|
|
592
|
+
framework: 'vite',
|
|
593
|
+
})
|
|
594
|
+
: undefined;
|
|
595
|
+
const result = await deps.orchestrator.startUnified({
|
|
596
|
+
prompt: args.prompt,
|
|
597
|
+
count: args.count,
|
|
598
|
+
target: args.target,
|
|
599
|
+
leaseOwner: deps.leaseOwner(),
|
|
600
|
+
briefs: args.briefs,
|
|
601
|
+
});
|
|
602
|
+
return assembleStartVariantsResponse({
|
|
603
|
+
mode: 'existing',
|
|
604
|
+
result,
|
|
605
|
+
project: { projectPath, framework },
|
|
606
|
+
visualEditor,
|
|
607
|
+
});
|
|
608
|
+
}
|
|
609
|
+
/**
|
|
610
|
+
* Build the StartVariantsOutput from a startUnified result + the lease
|
|
611
|
+
* info it surfaced. Pairs each variant in the original `variants` list
|
|
612
|
+
* with its `leasedWorkItems[]` entry from requestWork so the agent sees
|
|
613
|
+
* one consistent per-variant object with everything it needs.
|
|
614
|
+
*/
|
|
615
|
+
function assembleStartVariantsResponse(args) {
|
|
616
|
+
const { result } = args;
|
|
617
|
+
if (result.leaseId === undefined ||
|
|
618
|
+
result.leaseTtlMs === undefined ||
|
|
619
|
+
result.leasedWorkItems === undefined) {
|
|
620
|
+
return {
|
|
621
|
+
stage: 'failed',
|
|
622
|
+
errorCode: 'INVALID_STAGE_ACTION',
|
|
623
|
+
message: 'start_variants expected a lease to be issued by startUnified but none was returned.',
|
|
624
|
+
};
|
|
625
|
+
}
|
|
626
|
+
const itemById = new Map(result.leasedWorkItems.map((item) => [item.id, item]));
|
|
627
|
+
const variants = [];
|
|
628
|
+
for (const v of result.variants) {
|
|
629
|
+
const workItem = itemById.get(v.variantId);
|
|
630
|
+
if (!workItem) {
|
|
631
|
+
return {
|
|
632
|
+
stage: 'failed',
|
|
633
|
+
errorCode: 'INVALID_STAGE_ACTION',
|
|
634
|
+
message: `start_variants leased fewer items than variants — missing workItem for ${v.variantId}.`,
|
|
635
|
+
};
|
|
636
|
+
}
|
|
637
|
+
variants.push({ ...v, workItem });
|
|
638
|
+
}
|
|
639
|
+
return {
|
|
640
|
+
sessionId: result.sessionId,
|
|
641
|
+
stage: 'work_items_ready',
|
|
642
|
+
mode: args.mode,
|
|
643
|
+
leaseId: result.leaseId,
|
|
644
|
+
leaseTtlMs: result.leaseTtlMs,
|
|
645
|
+
variants,
|
|
646
|
+
scaffoldBaseWorkItemId: result.scaffoldBaseWorkItemId,
|
|
647
|
+
...(args.destinationPath ? { destinationPath: args.destinationPath } : {}),
|
|
648
|
+
...(args.visualEditor ? { visualEditor: args.visualEditor } : {}),
|
|
649
|
+
...(args.project ? { project: args.project } : {}),
|
|
650
|
+
nextAction: 'report_variant_complete',
|
|
651
|
+
};
|
|
652
|
+
}
|
|
221
653
|
//# sourceMappingURL=tools.js.map
|