rivet-design 0.10.8 → 0.11.0
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.d.ts +47 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +277 -123
- package/dist/index.js.map +1 -1
- package/dist/mcp/agent-variants/SessionStore.d.ts +28 -4
- package/dist/mcp/agent-variants/SessionStore.d.ts.map +1 -1
- package/dist/mcp/agent-variants/SessionStore.js +356 -123
- package/dist/mcp/agent-variants/SessionStore.js.map +1 -1
- package/dist/mcp/agent-variants/WorktreeOrchestrator.d.ts +84 -4
- package/dist/mcp/agent-variants/WorktreeOrchestrator.d.ts.map +1 -1
- package/dist/mcp/agent-variants/WorktreeOrchestrator.js +744 -145
- package/dist/mcp/agent-variants/WorktreeOrchestrator.js.map +1 -1
- package/dist/mcp/agent-variants/WorktreeOrchestrator.testHelpers.d.ts +8 -3
- package/dist/mcp/agent-variants/WorktreeOrchestrator.testHelpers.d.ts.map +1 -1
- package/dist/mcp/agent-variants/WorktreeOrchestrator.testHelpers.js +8 -3
- package/dist/mcp/agent-variants/WorktreeOrchestrator.testHelpers.js.map +1 -1
- package/dist/mcp/agent-variants/contracts.d.ts +7984 -1625
- package/dist/mcp/agent-variants/contracts.d.ts.map +1 -1
- package/dist/mcp/agent-variants/contracts.js +312 -154
- package/dist/mcp/agent-variants/contracts.js.map +1 -1
- package/dist/mcp/agent-variants/createZeroToOneTool.d.ts +2 -3
- package/dist/mcp/agent-variants/createZeroToOneTool.d.ts.map +1 -1
- package/dist/mcp/agent-variants/createZeroToOneTool.js +49 -39
- package/dist/mcp/agent-variants/createZeroToOneTool.js.map +1 -1
- package/dist/mcp/agent-variants/designCritique.d.ts +167 -0
- package/dist/mcp/agent-variants/designCritique.d.ts.map +1 -0
- package/dist/mcp/agent-variants/designCritique.js +717 -0
- package/dist/mcp/agent-variants/designCritique.js.map +1 -0
- package/dist/mcp/agent-variants/diffQa.d.ts +7 -0
- package/dist/mcp/agent-variants/diffQa.d.ts.map +1 -0
- package/dist/mcp/agent-variants/diffQa.js +67 -0
- package/dist/mcp/agent-variants/diffQa.js.map +1 -0
- package/dist/mcp/agent-variants/index.d.ts +3 -3
- package/dist/mcp/agent-variants/index.d.ts.map +1 -1
- package/dist/mcp/agent-variants/index.js +2 -1
- package/dist/mcp/agent-variants/index.js.map +1 -1
- package/dist/mcp/agent-variants/pinterestSourceContext.d.ts +4 -2
- package/dist/mcp/agent-variants/pinterestSourceContext.d.ts.map +1 -1
- package/dist/mcp/agent-variants/pinterestSourceContext.js +7 -6
- package/dist/mcp/agent-variants/pinterestSourceContext.js.map +1 -1
- package/dist/mcp/agent-variants/previewQa.d.ts +6 -4
- package/dist/mcp/agent-variants/previewQa.d.ts.map +1 -1
- package/dist/mcp/agent-variants/previewQa.js +140 -13
- package/dist/mcp/agent-variants/previewQa.js.map +1 -1
- package/dist/mcp/agent-variants/sourceContext.d.ts +20 -5
- package/dist/mcp/agent-variants/sourceContext.d.ts.map +1 -1
- package/dist/mcp/agent-variants/sourceContext.js +99 -115
- package/dist/mcp/agent-variants/sourceContext.js.map +1 -1
- package/dist/mcp/agent-variants/tools.d.ts +7 -0
- package/dist/mcp/agent-variants/tools.d.ts.map +1 -1
- package/dist/mcp/agent-variants/tools.js +216 -15
- package/dist/mcp/agent-variants/tools.js.map +1 -1
- package/dist/mcp/agent-variants/variantContext.d.ts +19 -0
- package/dist/mcp/agent-variants/variantContext.d.ts.map +1 -0
- package/dist/mcp/agent-variants/variantContext.js +355 -0
- package/dist/mcp/agent-variants/variantContext.js.map +1 -0
- package/dist/mcp/auth/httpOAuthProvider.d.ts +103 -0
- package/dist/mcp/auth/httpOAuthProvider.d.ts.map +1 -0
- package/dist/mcp/auth/httpOAuthProvider.js +454 -0
- package/dist/mcp/auth/httpOAuthProvider.js.map +1 -0
- package/dist/mcp/auth/tools.d.ts +2 -0
- package/dist/mcp/auth/tools.d.ts.map +1 -1
- package/dist/mcp/auth/tools.js +12 -5
- package/dist/mcp/auth/tools.js.map +1 -1
- package/dist/mcp/httpServer.d.ts +36 -0
- package/dist/mcp/httpServer.d.ts.map +1 -0
- package/dist/mcp/httpServer.js +307 -0
- package/dist/mcp/httpServer.js.map +1 -0
- package/dist/mcp/server.d.ts +17 -0
- package/dist/mcp/server.d.ts.map +1 -1
- package/dist/mcp/server.js +41 -19
- package/dist/mcp/server.js.map +1 -1
- package/dist/proxy-middleware/proxy-config.d.ts.map +1 -1
- package/dist/proxy-middleware/proxy-config.js +5 -2
- package/dist/proxy-middleware/proxy-config.js.map +1 -1
- package/dist/routes/agentVariants.d.ts.map +1 -1
- package/dist/routes/agentVariants.js +6 -4
- package/dist/routes/agentVariants.js.map +1 -1
- package/dist/routes/mcp.d.ts.map +1 -1
- package/dist/routes/mcp.js +2 -1
- package/dist/routes/mcp.js.map +1 -1
- package/dist/server.d.ts +9 -0
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +13 -5
- package/dist/server.js.map +1 -1
- package/dist/services/AuthService.d.ts +1 -0
- package/dist/services/AuthService.d.ts.map +1 -1
- package/dist/services/AuthService.js +11 -1
- package/dist/services/AuthService.js.map +1 -1
- package/dist/services/BrowserAgentClient.d.ts +54 -0
- package/dist/services/BrowserAgentClient.d.ts.map +1 -0
- package/dist/services/BrowserAgentClient.js +126 -0
- package/dist/services/BrowserAgentClient.js.map +1 -0
- package/dist/services/ConfigManager.d.ts +5 -0
- package/dist/services/ConfigManager.d.ts.map +1 -1
- package/dist/services/ConfigManager.js +25 -3
- package/dist/services/ConfigManager.js.map +1 -1
- package/dist/services/DevServerRuntimeService.d.ts +119 -0
- package/dist/services/DevServerRuntimeService.d.ts.map +1 -0
- package/dist/services/DevServerRuntimeService.js +657 -0
- package/dist/services/DevServerRuntimeService.js.map +1 -0
- package/dist/services/GatewayClient.d.ts +25 -0
- package/dist/services/GatewayClient.d.ts.map +1 -1
- package/dist/services/GatewayClient.js +70 -11
- package/dist/services/GatewayClient.js.map +1 -1
- package/dist/services/InlineVariantGenerationService.d.ts +2 -0
- package/dist/services/InlineVariantGenerationService.d.ts.map +1 -1
- package/dist/services/InlineVariantGenerationService.js +70 -3
- package/dist/services/InlineVariantGenerationService.js.map +1 -1
- package/dist/services/RequestAuthContext.d.ts +7 -1
- package/dist/services/RequestAuthContext.d.ts.map +1 -1
- package/dist/services/RequestAuthContext.js +15 -2
- package/dist/services/RequestAuthContext.js.map +1 -1
- package/dist/services/SessionBridgeService.d.ts +1 -0
- package/dist/services/SessionBridgeService.d.ts.map +1 -1
- package/dist/services/SessionBridgeService.js +16 -1
- package/dist/services/SessionBridgeService.js.map +1 -1
- package/dist/services/VariantRunService.d.ts +1 -0
- package/dist/services/VariantRunService.d.ts.map +1 -1
- package/dist/services/VariantRunService.js +1 -0
- package/dist/services/VariantRunService.js.map +1 -1
- package/dist/services/VariantsRuntime.d.ts.map +1 -1
- package/dist/services/VariantsRuntime.js +1 -0
- package/dist/services/VariantsRuntime.js.map +1 -1
- package/dist/services/WorktreeManager.d.ts +1 -8
- package/dist/services/WorktreeManager.d.ts.map +1 -1
- package/dist/services/WorktreeManager.js +1 -28
- package/dist/services/WorktreeManager.js.map +1 -1
- package/dist/services/createAgentVariantsOrchestrator.d.ts.map +1 -1
- package/dist/services/createAgentVariantsOrchestrator.js +7 -0
- package/dist/services/createAgentVariantsOrchestrator.js.map +1 -1
- package/dist/utils/skills/describe-motion-protocol.d.ts +2 -3
- package/dist/utils/skills/describe-motion-protocol.d.ts.map +1 -1
- package/dist/utils/skills/describe-motion-protocol.js +50 -35
- package/dist/utils/skills/describe-motion-protocol.js.map +1 -1
- package/dist/utils/skills/shared-variants-protocol.d.ts +1 -1
- package/dist/utils/skills/shared-variants-protocol.d.ts.map +1 -1
- package/dist/utils/skills/shared-variants-protocol.js +21 -15
- package/dist/utils/skills/shared-variants-protocol.js.map +1 -1
- package/dist/utils/variantSessionStart.d.ts +3 -0
- package/dist/utils/variantSessionStart.d.ts.map +1 -0
- package/dist/utils/variantSessionStart.js +7 -0
- package/dist/utils/variantSessionStart.js.map +1 -0
- package/package.json +2 -1
- package/src/ui/dist/assets/{main-WqlDU4Ou.js → main-Cw6Pd8ye.js} +204 -204
- package/src/ui/dist/assets/main-DkCj7b2K.css +1 -0
- package/src/ui/dist/index.html +2 -2
- package/dist/mcp/agent-variants/designContextStore.d.ts +0 -160
- package/dist/mcp/agent-variants/designContextStore.d.ts.map +0 -1
- package/dist/mcp/agent-variants/designContextStore.js +0 -295
- package/dist/mcp/agent-variants/designContextStore.js.map +0 -1
- package/dist/mcp/agent-variants/inspirationDesignContext.d.ts +0 -440
- package/dist/mcp/agent-variants/inspirationDesignContext.d.ts.map +0 -1
- package/dist/mcp/agent-variants/inspirationDesignContext.js +0 -2467
- package/dist/mcp/agent-variants/inspirationDesignContext.js.map +0 -1
- package/src/ui/dist/assets/main-auZA25j4.css +0 -1
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.SessionStore = exports.buildImageRefs = exports.SOURCE_PLAN_OUTPUT_SCHEMA = exports.SCAFFOLD_LEASE_TTL_MS = exports.DEFAULT_LEASE_TTL_MS = void 0;
|
|
3
|
+
exports.SessionStore = exports.buildImageRefs = exports.SOURCE_PLAN_ACTION_OPTIONS = exports.SOURCE_PLAN_OUTPUT_SCHEMA = exports.SCAFFOLD_LEASE_TTL_MS = exports.DEFAULT_LEASE_TTL_MS = void 0;
|
|
4
4
|
const crypto_1 = require("crypto");
|
|
5
5
|
const errors_1 = require("./errors");
|
|
6
6
|
const contracts_1 = require("./contracts");
|
|
7
|
-
const sourceContext_1 = require("./sourceContext");
|
|
8
7
|
const runLabel_1 = require("./runLabel");
|
|
9
8
|
const runPlan_1 = require("./runPlan");
|
|
10
9
|
const DEFAULT_VARIANT_COUNT = 4;
|
|
@@ -38,11 +37,27 @@ function descriptorFor(item) {
|
|
|
38
37
|
};
|
|
39
38
|
}
|
|
40
39
|
exports.SOURCE_PLAN_OUTPUT_SCHEMA = {
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
40
|
+
actions: "Required Array<{ id, kind: 'extract_design_system'|'describe_motion', sourceIds, reason }> — actions selected after inspecting raw input.userContext and the prompt. Use only kinds listed in input.availableActions. May be empty when no source warrants enrichment.",
|
|
41
|
+
metadata: "Required Array<{ id, kind: 'design_system'|'motion_guidance', sourceIds, actionId?, producedBy, data }> — additive metadata produced from the reported actions. Every action MUST produce its matching metadata kind (extract_design_system -> design_system, describe_motion -> motion_guidance). For URL-backed design_system, call capture_design_evidence({ sessionId, url }) before report_source_plan and set data.evidenceStatus. For design_system, data may include designMarkdown; otherwise Rivet synthesizes DESIGN.md from the structured observations. For motion_guidance, data may include motionMarkdown plus notes/timings. Raw userContext remains authoritative; metadata is additive shared guidance.",
|
|
42
|
+
bindings: "Optional Array<{ kind:'global', sourceIds, actionIds, metadataIds? } | { kind:'slot', slotIndex, sourceIds, actionIds, metadataIds? }> — omit for the default global context behavior.",
|
|
44
43
|
executionPlan: "{ mode: 'static_preview' | 'vite_app', confidence: low|medium|high, reason, assetPlan?: Array<{source, destination, referenceAs}>, runtimeRequirements?, userQuestion? } — choose vite_app for large local assets, model-viewer, Three.js, route structure, package deps, or files under public/; assetPlan.source must live under the approved asset root; static_preview for self-contained HTML/CSS/JS prototypes.",
|
|
45
44
|
};
|
|
45
|
+
exports.SOURCE_PLAN_ACTION_OPTIONS = [
|
|
46
|
+
{
|
|
47
|
+
kind: 'extract_design_system',
|
|
48
|
+
sourceTransports: ['url', 'file', 'text'],
|
|
49
|
+
capability: 'extract_inspiration_context',
|
|
50
|
+
produces: 'design_system',
|
|
51
|
+
instructions: 'Inspect visual references natively and use the existing inspiration/design-context extraction path to produce reusable design_system metadata.',
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
kind: 'describe_motion',
|
|
55
|
+
sourceTransports: ['url', 'file'],
|
|
56
|
+
capability: 'rivet_describe_motion',
|
|
57
|
+
produces: 'motion_guidance',
|
|
58
|
+
instructions: 'Inspect interaction references natively and use the Rivet Describe Motion protocol to produce motion_guidance metadata.',
|
|
59
|
+
},
|
|
60
|
+
];
|
|
46
61
|
/** Returns the completion payload shape required for each leased work item. */
|
|
47
62
|
function outputSchemaFor(kind) {
|
|
48
63
|
switch (kind) {
|
|
@@ -88,9 +103,25 @@ const createBriefWorkItem = (args) => ({
|
|
|
88
103
|
count: args.count,
|
|
89
104
|
target: args.target,
|
|
90
105
|
projectContext: args.projectContext,
|
|
106
|
+
...briefWorkItemContext(args.projectContext),
|
|
91
107
|
},
|
|
92
108
|
acceptedReports: [],
|
|
93
109
|
});
|
|
110
|
+
const briefWorkItemContext = (projectContext) => {
|
|
111
|
+
const bundle = projectContext.variantContext;
|
|
112
|
+
if (!bundle)
|
|
113
|
+
return {};
|
|
114
|
+
return {
|
|
115
|
+
context: {
|
|
116
|
+
contextBundlePath: bundle.contextBundlePath,
|
|
117
|
+
userContext: bundle.userContext,
|
|
118
|
+
rivetMetadata: bundle.rivetMetadata,
|
|
119
|
+
...(projectContext.kind === 'fresh' && projectContext.executionPlan
|
|
120
|
+
? { executionMode: projectContext.executionPlan.mode }
|
|
121
|
+
: {}),
|
|
122
|
+
},
|
|
123
|
+
};
|
|
124
|
+
};
|
|
94
125
|
// Source-artifact kinds that represent agent-described attached images.
|
|
95
126
|
// These need their own DESIGN.md slot in the source_plan output, alongside
|
|
96
127
|
// any URL-keyed entries. `siteBrief` / `urlText` are pasted text — they
|
|
@@ -118,24 +149,204 @@ const buildImageRefs = (artifacts) => {
|
|
|
118
149
|
exports.buildImageRefs = buildImageRefs;
|
|
119
150
|
/**
|
|
120
151
|
* Source-grounded fresh sessions require a single `source_plan` planning hop
|
|
121
|
-
* before briefs. The hop fires when
|
|
122
|
-
*
|
|
123
|
-
*
|
|
152
|
+
* before briefs. The hop fires when Rivet has captured a read-only user
|
|
153
|
+
* context bundle (the sole source-intake surface). The source-plan agent
|
|
154
|
+
* inspects raw context and reports actions plus metadata.
|
|
124
155
|
*/
|
|
125
|
-
const requiresSourcePlan = (projectContext) =>
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
const
|
|
137
|
-
|
|
138
|
-
|
|
156
|
+
const requiresSourcePlan = (projectContext) => projectContext.kind === 'fresh' && Boolean(projectContext.variantContext);
|
|
157
|
+
const listSection = (title, items) => {
|
|
158
|
+
if (items.length === 0)
|
|
159
|
+
return [];
|
|
160
|
+
return [`## ${title}`, '', ...items.map((item) => `- ${item}`), ''];
|
|
161
|
+
};
|
|
162
|
+
const hasSharedSource = (sourceIds, candidateSourceIds) => candidateSourceIds.some((sourceId) => sourceIds.includes(sourceId));
|
|
163
|
+
/**
|
|
164
|
+
* Formats motion metadata that applies to the same raw sources as the design metadata.
|
|
165
|
+
*/
|
|
166
|
+
const buildMotionGuidanceMarkdown = (sourceIds, metadata) => {
|
|
167
|
+
const matchingMotion = metadata.filter((entry) => entry.kind === 'motion_guidance' &&
|
|
168
|
+
hasSharedSource(sourceIds, entry.sourceIds));
|
|
169
|
+
if (matchingMotion.length === 0)
|
|
170
|
+
return [];
|
|
171
|
+
const lines = ['## Motion Guidance', ''];
|
|
172
|
+
for (const entry of matchingMotion) {
|
|
173
|
+
if (entry.data.motionMarkdown) {
|
|
174
|
+
lines.push(entry.data.motionMarkdown.trim(), '');
|
|
175
|
+
continue;
|
|
176
|
+
}
|
|
177
|
+
lines.push(...entry.data.notes.map((item) => `- ${item}`));
|
|
178
|
+
if (entry.data.timings && entry.data.timings.length > 0) {
|
|
179
|
+
lines.push('', '### Timings', '');
|
|
180
|
+
lines.push(...entry.data.timings.map((item) => `- ${item}`));
|
|
181
|
+
}
|
|
182
|
+
lines.push('');
|
|
183
|
+
}
|
|
184
|
+
return lines;
|
|
185
|
+
};
|
|
186
|
+
/**
|
|
187
|
+
* Converts design-system metadata into the markdown artifact variant agents consume.
|
|
188
|
+
*/
|
|
189
|
+
const buildDesignMarkdownFromMetadata = (entry, metadata) => {
|
|
190
|
+
if (entry.data.designMarkdown) {
|
|
191
|
+
return entry.data.designMarkdown;
|
|
192
|
+
}
|
|
193
|
+
const sourceRoleLines = entry.data.sourceRoles.map((role) => role.rationale
|
|
194
|
+
? `${role.role}: ${role.sourceId} (${role.rationale})`
|
|
195
|
+
: `${role.role}: ${role.sourceId}`);
|
|
196
|
+
const lines = [
|
|
197
|
+
'# Design System',
|
|
198
|
+
'',
|
|
199
|
+
...listSection('Source Findings', entry.data.sourceFindings),
|
|
200
|
+
...listSection('Section Inventory', entry.data.sectionInventory),
|
|
201
|
+
...listSection('Visual Observations', entry.data.visualObservations),
|
|
202
|
+
...listSection('Source Roles', sourceRoleLines),
|
|
203
|
+
...buildMotionGuidanceMarkdown(entry.sourceIds, metadata),
|
|
204
|
+
...listSection('Quality Bar', entry.data.qualityBar),
|
|
205
|
+
...(entry.data.risks ? listSection('Risks', entry.data.risks) : []),
|
|
206
|
+
];
|
|
207
|
+
return `${lines.join('\n').trim()}\n`;
|
|
208
|
+
};
|
|
209
|
+
/**
|
|
210
|
+
* Builds design-context entries from action metadata when the report does not provide them directly.
|
|
211
|
+
*/
|
|
212
|
+
const designContextsFromActionMetadata = (metadata) => {
|
|
213
|
+
if (!metadata)
|
|
214
|
+
return [];
|
|
215
|
+
return metadata
|
|
216
|
+
.filter((entry) => entry.kind === 'design_system')
|
|
217
|
+
.map((entry, index) => ({
|
|
218
|
+
label: index === 0 ? 'Design system' : `Design system ${index + 1}`,
|
|
219
|
+
markdown: buildDesignMarkdownFromMetadata(entry, metadata),
|
|
220
|
+
}));
|
|
221
|
+
};
|
|
222
|
+
const mergeVariantContext = (args) => {
|
|
223
|
+
if (!args.bundle)
|
|
224
|
+
return undefined;
|
|
225
|
+
const metadata = args.sourcePlan.metadata;
|
|
226
|
+
const metadataByActionId = new Map();
|
|
227
|
+
for (const entry of metadata) {
|
|
228
|
+
if (!entry.actionId)
|
|
229
|
+
continue;
|
|
230
|
+
const ids = metadataByActionId.get(entry.actionId) ?? [];
|
|
231
|
+
ids.push(entry.id);
|
|
232
|
+
metadataByActionId.set(entry.actionId, ids);
|
|
233
|
+
}
|
|
234
|
+
const actions = args.sourcePlan.actions.map((action) => ({
|
|
235
|
+
...action,
|
|
236
|
+
outputMetadataIds: action.outputMetadataIds ?? metadataByActionId.get(action.id),
|
|
237
|
+
}));
|
|
238
|
+
return {
|
|
239
|
+
...args.bundle,
|
|
240
|
+
sessionId: args.sessionId,
|
|
241
|
+
rivetActions: actions,
|
|
242
|
+
rivetMetadata: metadata,
|
|
243
|
+
...(args.sourcePlan.bindings ? { bindings: args.sourcePlan.bindings } : {}),
|
|
244
|
+
executionPlan: args.sourcePlan.executionPlan,
|
|
245
|
+
};
|
|
246
|
+
};
|
|
247
|
+
const METADATA_KIND_BY_ACTION_KIND = {
|
|
248
|
+
extract_design_system: 'design_system',
|
|
249
|
+
describe_motion: 'motion_guidance',
|
|
250
|
+
};
|
|
251
|
+
/**
|
|
252
|
+
* Validates the reported source plan's action/metadata invariants:
|
|
253
|
+
* - metadata is produced BY actions, so metadata reported with zero actions
|
|
254
|
+
* is rejected (it would otherwise build DESIGN.md from an orphaned payload);
|
|
255
|
+
* - every metadata entry references real raw-context sources;
|
|
256
|
+
* - every reported action produces the metadata kind it claims to.
|
|
257
|
+
*/
|
|
258
|
+
const validateActionMetadataOutputs = (args) => {
|
|
259
|
+
const actions = args.sourcePlan.actions;
|
|
260
|
+
const metadata = args.sourcePlan.metadata;
|
|
261
|
+
// Metadata is produced BY actions. A plan that reports metadata with no
|
|
262
|
+
// actions has nothing to produce it — reject rather than silently building
|
|
263
|
+
// design context from an orphaned, otherwise-unvalidated payload.
|
|
264
|
+
if (actions.length === 0 && metadata.length > 0) {
|
|
265
|
+
throw new errors_1.AgentVariantsError('SOURCE_CONTEXT_INVALID', 'source_plan reported metadata without any actions; metadata must be produced by a reported action');
|
|
266
|
+
}
|
|
267
|
+
const sourceIds = new Set(args.bundle?.userContext.map((source) => source.id) ?? []);
|
|
268
|
+
// Validate metadata sourceIds independently of `actions` so an empty action
|
|
269
|
+
// list can never skip the check wholesale.
|
|
270
|
+
for (const entry of metadata) {
|
|
271
|
+
const unknownSourceIds = entry.sourceIds.filter((sourceId) => sourceIds.size > 0 && !sourceIds.has(sourceId));
|
|
272
|
+
if (unknownSourceIds.length > 0) {
|
|
273
|
+
throw new errors_1.AgentVariantsError('SOURCE_CONTEXT_INVALID', `source_plan metadata ${entry.id} references unknown sourceIds: ${unknownSourceIds.join(', ')}`);
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
if (actions.length === 0)
|
|
277
|
+
return;
|
|
278
|
+
const metadataById = new Map(metadata.map((entry) => [entry.id, entry]));
|
|
279
|
+
for (const action of actions) {
|
|
280
|
+
const unknownSourceIds = action.sourceIds.filter((sourceId) => sourceIds.size > 0 && !sourceIds.has(sourceId));
|
|
281
|
+
if (unknownSourceIds.length > 0) {
|
|
282
|
+
throw new errors_1.AgentVariantsError('SOURCE_CONTEXT_INVALID', `source_plan action ${action.id} references unknown sourceIds: ${unknownSourceIds.join(', ')}`);
|
|
283
|
+
}
|
|
284
|
+
const expectedMetadataKind = METADATA_KIND_BY_ACTION_KIND[action.kind];
|
|
285
|
+
const linkedMetadata = [
|
|
286
|
+
...metadata.filter((entry) => entry.actionId === action.id),
|
|
287
|
+
...(action.outputMetadataIds ?? [])
|
|
288
|
+
.map((id) => metadataById.get(id))
|
|
289
|
+
.filter((entry) => Boolean(entry)),
|
|
290
|
+
];
|
|
291
|
+
const hasExpectedMetadata = linkedMetadata.some((entry) => entry.kind === expectedMetadataKind);
|
|
292
|
+
if (!hasExpectedMetadata) {
|
|
293
|
+
throw new errors_1.AgentVariantsError('SOURCE_CONTEXT_INVALID', `source_plan action ${action.id} (${action.kind}) must produce ${expectedMetadataKind} metadata`);
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
};
|
|
297
|
+
const collectSlotBoundIds = (bindings) => {
|
|
298
|
+
const sourceIds = new Set();
|
|
299
|
+
const actionIds = new Set();
|
|
300
|
+
const metadataIds = new Set();
|
|
301
|
+
for (const binding of bindings ?? []) {
|
|
302
|
+
if (binding.kind !== 'slot')
|
|
303
|
+
continue;
|
|
304
|
+
binding.sourceIds.forEach((id) => sourceIds.add(id));
|
|
305
|
+
binding.actionIds.forEach((id) => actionIds.add(id));
|
|
306
|
+
binding.metadataIds?.forEach((id) => metadataIds.add(id));
|
|
307
|
+
}
|
|
308
|
+
return { sourceIds, actionIds, metadataIds };
|
|
309
|
+
};
|
|
310
|
+
const collectMatchingIds = (bindings, slotIndex) => {
|
|
311
|
+
const sourceIds = new Set();
|
|
312
|
+
const actionIds = new Set();
|
|
313
|
+
const metadataIds = new Set();
|
|
314
|
+
for (const binding of bindings ?? []) {
|
|
315
|
+
if (binding.kind === 'slot' && binding.slotIndex !== slotIndex)
|
|
316
|
+
continue;
|
|
317
|
+
binding.sourceIds.forEach((id) => sourceIds.add(id));
|
|
318
|
+
binding.actionIds.forEach((id) => actionIds.add(id));
|
|
319
|
+
binding.metadataIds?.forEach((id) => metadataIds.add(id));
|
|
320
|
+
}
|
|
321
|
+
return { sourceIds, actionIds, metadataIds };
|
|
322
|
+
};
|
|
323
|
+
const resolveVariantWorkItemContext = (args) => {
|
|
324
|
+
if (!args.bundle)
|
|
325
|
+
return undefined;
|
|
326
|
+
const bindings = args.bundle.bindings;
|
|
327
|
+
const boundIds = collectSlotBoundIds(bindings);
|
|
328
|
+
const matchingIds = collectMatchingIds(bindings, args.slotIndex);
|
|
329
|
+
const userContext = args.bundle.userContext.filter((source) => !boundIds.sourceIds.has(source.id) ||
|
|
330
|
+
matchingIds.sourceIds.has(source.id));
|
|
331
|
+
const rivetMetadata = args.bundle.rivetMetadata.filter((metadata) => {
|
|
332
|
+
const isSlotBound = boundIds.metadataIds.has(metadata.id) ||
|
|
333
|
+
(metadata.actionId ? boundIds.actionIds.has(metadata.actionId) : false);
|
|
334
|
+
const isMatching = matchingIds.metadataIds.has(metadata.id) ||
|
|
335
|
+
(metadata.actionId
|
|
336
|
+
? matchingIds.actionIds.has(metadata.actionId)
|
|
337
|
+
: false);
|
|
338
|
+
return !isSlotBound || isMatching;
|
|
339
|
+
});
|
|
340
|
+
return {
|
|
341
|
+
contextBundlePath: args.bundle.contextBundlePath,
|
|
342
|
+
userContext,
|
|
343
|
+
rivetMetadata,
|
|
344
|
+
brief: args.brief,
|
|
345
|
+
...(args.projectContext.kind === 'fresh' &&
|
|
346
|
+
args.projectContext.executionPlan
|
|
347
|
+
? { executionMode: args.projectContext.executionPlan.mode }
|
|
348
|
+
: {}),
|
|
349
|
+
};
|
|
139
350
|
};
|
|
140
351
|
class SessionStore {
|
|
141
352
|
sessions = new Map();
|
|
@@ -153,8 +364,8 @@ class SessionStore {
|
|
|
153
364
|
kind: 'existing',
|
|
154
365
|
};
|
|
155
366
|
const count = clampCount(args.count);
|
|
156
|
-
const
|
|
157
|
-
? projectContext.
|
|
367
|
+
const bundle = projectContext.kind === 'fresh'
|
|
368
|
+
? projectContext.variantContext
|
|
158
369
|
: undefined;
|
|
159
370
|
const needsSourcePlan = requiresSourcePlan(projectContext);
|
|
160
371
|
const initialItem = needsSourcePlan
|
|
@@ -168,9 +379,14 @@ class SessionStore {
|
|
|
168
379
|
prompt: args.prompt,
|
|
169
380
|
count,
|
|
170
381
|
target: args.target,
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
382
|
+
...(bundle
|
|
383
|
+
? {
|
|
384
|
+
contextBundlePath: bundle.contextBundlePath,
|
|
385
|
+
userContext: bundle.userContext,
|
|
386
|
+
availableActions: exports.SOURCE_PLAN_ACTION_OPTIONS,
|
|
387
|
+
variantSlotCount: count,
|
|
388
|
+
}
|
|
389
|
+
: {}),
|
|
174
390
|
projectContext,
|
|
175
391
|
},
|
|
176
392
|
acceptedReports: [],
|
|
@@ -236,8 +452,25 @@ class SessionStore {
|
|
|
236
452
|
throw new errors_1.AgentVariantsError('STALE_LEASE', `attempt mismatch: expected ${item.attempt}, got ${args.attempt}`);
|
|
237
453
|
}
|
|
238
454
|
item.status = 'succeeded';
|
|
239
|
-
item.output = {
|
|
455
|
+
item.output = {
|
|
456
|
+
briefs: args.briefs,
|
|
457
|
+
...(args.bindings ? { bindings: args.bindings } : {}),
|
|
458
|
+
};
|
|
240
459
|
session.briefs = args.briefs;
|
|
460
|
+
if (args.bindings &&
|
|
461
|
+
session.projectContext.kind === 'fresh' &&
|
|
462
|
+
session.projectContext.variantContext) {
|
|
463
|
+
session.projectContext = {
|
|
464
|
+
...session.projectContext,
|
|
465
|
+
variantContext: {
|
|
466
|
+
...session.projectContext.variantContext,
|
|
467
|
+
bindings: [
|
|
468
|
+
...(session.projectContext.variantContext.bindings ?? []),
|
|
469
|
+
...args.bindings,
|
|
470
|
+
],
|
|
471
|
+
},
|
|
472
|
+
};
|
|
473
|
+
}
|
|
241
474
|
session.stage = 'awaiting_approval';
|
|
242
475
|
const result = { briefs: args.briefs };
|
|
243
476
|
session.acceptedFingerprints.set(fp, result);
|
|
@@ -262,110 +495,56 @@ class SessionStore {
|
|
|
262
495
|
throw new errors_1.AgentVariantsError('INVALID_STAGE_ACTION', `Work item ${args.workItemId} is not a source_plan item`);
|
|
263
496
|
}
|
|
264
497
|
this.validateLease(item, args.leaseId, args.attempt);
|
|
265
|
-
const {
|
|
266
|
-
//
|
|
267
|
-
//
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
: [];
|
|
275
|
-
const classifiedUrls = new Set(sourceIntent.sources
|
|
276
|
-
.map((e) => e.url)
|
|
277
|
-
.filter((u) => Boolean(u)));
|
|
278
|
-
const classifiedImageRefs = new Set(sourceIntent.sources
|
|
279
|
-
.map((e) => e.imageRef)
|
|
280
|
-
.filter((r) => Boolean(r)));
|
|
281
|
-
const missingClassification = [
|
|
282
|
-
...sessionSourceUrls.filter((url) => !classifiedUrls.has(url)),
|
|
283
|
-
...sessionImageRefs.filter((ref) => !classifiedImageRefs.has(ref)),
|
|
284
|
-
];
|
|
285
|
-
if (missingClassification.length > 0) {
|
|
286
|
-
throw new errors_1.AgentVariantsError('SOURCE_CONTEXT_INVALID', `source_plan missing sourceIntent classification for: ${missingClassification.join(', ')}`);
|
|
287
|
-
}
|
|
288
|
-
const designSourceUrls = sourceIntent.sources
|
|
289
|
-
.filter((entry) => entry.role === 'design_source' && Boolean(entry.url))
|
|
290
|
-
.map((entry) => entry.url);
|
|
291
|
-
const designSourceImageRefs = sourceIntent.sources
|
|
292
|
-
.filter((entry) => entry.role === 'design_source' && Boolean(entry.imageRef))
|
|
293
|
-
.map((entry) => entry.imageRef);
|
|
294
|
-
const reportedDesignUrls = new Set((designContexts ?? [])
|
|
295
|
-
.map((entry) => entry.url)
|
|
296
|
-
.filter((u) => Boolean(u)));
|
|
297
|
-
const reportedDesignImageRefs = new Set((designContexts ?? [])
|
|
298
|
-
.map((entry) => entry.imageRef)
|
|
299
|
-
.filter((r) => Boolean(r)));
|
|
300
|
-
const missingDesignContexts = [
|
|
301
|
-
...designSourceUrls.filter((url) => !reportedDesignUrls.has(url)),
|
|
302
|
-
...designSourceImageRefs.filter((ref) => !reportedDesignImageRefs.has(ref)),
|
|
303
|
-
];
|
|
304
|
-
if (missingDesignContexts.length > 0) {
|
|
305
|
-
throw new errors_1.AgentVariantsError('SOURCE_CONTEXT_INVALID', `Missing DESIGN.md for design source(s): ${missingDesignContexts.join(', ')}`);
|
|
306
|
-
}
|
|
307
|
-
const normalizedArtifact = (0, sourceContext_1.normalizeSourceContextArtifact)(sourceContext);
|
|
498
|
+
const { executionPlan, actions, metadata, bindings } = args.sourcePlan;
|
|
499
|
+
// Canonical path: every reported action must produce its matching metadata
|
|
500
|
+
// kind, and action sourceIds must reference real raw-context sources.
|
|
501
|
+
validateActionMetadataOutputs({
|
|
502
|
+
bundle: session.projectContext.kind === 'fresh'
|
|
503
|
+
? session.projectContext.variantContext
|
|
504
|
+
: undefined,
|
|
505
|
+
sourcePlan: args.sourcePlan,
|
|
506
|
+
});
|
|
308
507
|
if (session.projectContext.kind === 'fresh') {
|
|
309
|
-
//
|
|
310
|
-
//
|
|
311
|
-
//
|
|
312
|
-
// (provisionFreshWorktrees) reads slot [min(briefIndex, length-1)]
|
|
313
|
-
//
|
|
314
|
-
//
|
|
315
|
-
//
|
|
316
|
-
|
|
317
|
-
// order it shipped designContexts in. Without this alignment, an
|
|
318
|
-
// extra interaction_reference URL ahead of a design_source in the
|
|
319
|
-
// agent's payload would push the wrong DESIGN.md onto variant 0.
|
|
320
|
-
const designContextByUrl = new Map();
|
|
321
|
-
const designContextByImageRef = new Map();
|
|
322
|
-
for (const entry of designContexts ?? []) {
|
|
323
|
-
const payload = { label: entry.label, markdown: entry.markdown };
|
|
324
|
-
if (entry.url) {
|
|
325
|
-
designContextByUrl.set(entry.url, payload);
|
|
326
|
-
}
|
|
327
|
-
else if (entry.imageRef) {
|
|
328
|
-
designContextByImageRef.set(entry.imageRef, payload);
|
|
329
|
-
}
|
|
330
|
-
}
|
|
331
|
-
// Persist URL-keyed entries first (preserving the URL design_source
|
|
332
|
-
// order from sourceIntent), then image-keyed entries (preserving
|
|
333
|
-
// their design_source order). Brief fan-out reads slot
|
|
334
|
-
// [min(briefIndex, length-1)] with a slot-0 fallback, so this
|
|
335
|
-
// ordering puts URL inspirations on the early variant slots when
|
|
336
|
-
// both URLs and images are present.
|
|
337
|
-
const alignedDesignContexts = [
|
|
338
|
-
...designSourceUrls
|
|
339
|
-
.map((url) => designContextByUrl.get(url))
|
|
340
|
-
.filter((entry) => Boolean(entry)),
|
|
341
|
-
...designSourceImageRefs
|
|
342
|
-
.map((ref) => designContextByImageRef.get(ref))
|
|
343
|
-
.filter((entry) => Boolean(entry)),
|
|
344
|
-
];
|
|
508
|
+
// Derive DESIGN.md context directly from `design_system` action
|
|
509
|
+
// metadata. Each entry uses explicit `designMarkdown` when present, or
|
|
510
|
+
// is synthesized from the structured observations. Brief fan-out
|
|
511
|
+
// (provisionFreshWorktrees) reads slot [min(briefIndex, length-1)] with
|
|
512
|
+
// a slot-0 fallback, so a single design system ships one shared markdown
|
|
513
|
+
// while multiple design systems land on deterministic slots in report
|
|
514
|
+
// order.
|
|
515
|
+
const projectDesignContexts = designContextsFromActionMetadata(metadata);
|
|
345
516
|
session.projectContext = {
|
|
346
517
|
...session.projectContext,
|
|
347
|
-
...(
|
|
518
|
+
...(projectDesignContexts.length > 0
|
|
348
519
|
? {
|
|
349
|
-
designContext:
|
|
520
|
+
designContext: projectDesignContexts.map((entry) => ({
|
|
350
521
|
kind: 'markdown',
|
|
351
522
|
label: entry.label,
|
|
352
523
|
content: entry.markdown,
|
|
353
524
|
})),
|
|
354
525
|
}
|
|
355
526
|
: {}),
|
|
356
|
-
sourceContext: {
|
|
357
|
-
...(session.projectContext.sourceContext ?? {}),
|
|
358
|
-
sourceIntent,
|
|
359
|
-
artifact: normalizedArtifact,
|
|
360
|
-
},
|
|
361
527
|
executionPlan,
|
|
362
528
|
};
|
|
363
529
|
}
|
|
530
|
+
const updatedContext = mergeVariantContext({
|
|
531
|
+
bundle: session.projectContext.kind === 'fresh'
|
|
532
|
+
? session.projectContext.variantContext
|
|
533
|
+
: undefined,
|
|
534
|
+
sessionId: session.sessionId,
|
|
535
|
+
sourcePlan: args.sourcePlan,
|
|
536
|
+
});
|
|
537
|
+
if (updatedContext && session.projectContext.kind === 'fresh') {
|
|
538
|
+
session.projectContext = {
|
|
539
|
+
...session.projectContext,
|
|
540
|
+
variantContext: updatedContext,
|
|
541
|
+
};
|
|
542
|
+
}
|
|
364
543
|
item.status = 'succeeded';
|
|
365
544
|
item.output = {
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
...(
|
|
545
|
+
actions,
|
|
546
|
+
metadata,
|
|
547
|
+
...(bindings ? { bindings } : {}),
|
|
369
548
|
executionPlan,
|
|
370
549
|
};
|
|
371
550
|
item.lease = undefined;
|
|
@@ -444,6 +623,20 @@ class SessionStore {
|
|
|
444
623
|
const visualRef = brief.visualReferenceUrl
|
|
445
624
|
? { visualReferenceUrl: brief.visualReferenceUrl }
|
|
446
625
|
: {};
|
|
626
|
+
const context = resolveVariantWorkItemContext({
|
|
627
|
+
// Existing-project sessions also carry a server-owned context bundle
|
|
628
|
+
// (no source_plan stage), so thread it for both kinds.
|
|
629
|
+
bundle: session.projectContext.variantContext,
|
|
630
|
+
projectContext: session.projectContext,
|
|
631
|
+
brief,
|
|
632
|
+
slotIndex: briefIndex,
|
|
633
|
+
});
|
|
634
|
+
const freshDesignContext = session.projectContext.kind === 'fresh'
|
|
635
|
+
? session.projectContext.designContext
|
|
636
|
+
: undefined;
|
|
637
|
+
const designContextEntry = freshDesignContext
|
|
638
|
+
? freshDesignContext[Math.min(briefIndex, freshDesignContext.length - 1)]
|
|
639
|
+
: undefined;
|
|
447
640
|
if (wantsStaticPreview) {
|
|
448
641
|
// Generated + static_preview: HTML is the deliverable. No scaffold or
|
|
449
642
|
// code_gen — the static_preview item is leased directly.
|
|
@@ -459,6 +652,8 @@ class SessionStore {
|
|
|
459
652
|
briefBody: sel.bodyOverride ?? brief.body,
|
|
460
653
|
...visualRef,
|
|
461
654
|
projectContext: session.projectContext,
|
|
655
|
+
...(designContextEntry ? { designContextEntry } : {}),
|
|
656
|
+
...(context ? { context } : {}),
|
|
462
657
|
},
|
|
463
658
|
acceptedReports: [],
|
|
464
659
|
};
|
|
@@ -475,12 +670,6 @@ class SessionStore {
|
|
|
475
670
|
// when the session has fewer designContext entries than variants
|
|
476
671
|
// (the common case after report_source_plan ships one shared
|
|
477
672
|
// markdown).
|
|
478
|
-
const freshDesignContext = session.projectContext.kind === 'fresh'
|
|
479
|
-
? session.projectContext.designContext
|
|
480
|
-
: undefined;
|
|
481
|
-
const designContextEntry = freshDesignContext
|
|
482
|
-
? freshDesignContext[Math.min(briefIndex, freshDesignContext.length - 1)]
|
|
483
|
-
: undefined;
|
|
484
673
|
const codeGenItem = {
|
|
485
674
|
id: (0, crypto_1.randomUUID)(),
|
|
486
675
|
kind: 'code_gen',
|
|
@@ -495,6 +684,7 @@ class SessionStore {
|
|
|
495
684
|
target: session.target,
|
|
496
685
|
projectContext: session.projectContext,
|
|
497
686
|
...(designContextEntry ? { designContextEntry } : {}),
|
|
687
|
+
...(context ? { context } : {}),
|
|
498
688
|
},
|
|
499
689
|
acceptedReports: [],
|
|
500
690
|
};
|
|
@@ -636,6 +826,48 @@ class SessionStore {
|
|
|
636
826
|
session.acceptedFingerprints.set(fp, result);
|
|
637
827
|
return result;
|
|
638
828
|
}
|
|
829
|
+
/**
|
|
830
|
+
* Re-open a succeeded variant work item for one aesthetic regeneration.
|
|
831
|
+
* Consumes the agent's report (validating the lease), then resets the item
|
|
832
|
+
* to `pending` so it becomes leasable again via `request_work`, stashing the
|
|
833
|
+
* design critique onto its input so the re-leased descriptor carries the
|
|
834
|
+
* notes the agent must address before re-reporting.
|
|
835
|
+
*
|
|
836
|
+
* The work item never reaches a terminal status, so the session stays in
|
|
837
|
+
* `waiting_for_results` and never goes terminal off the back of a
|
|
838
|
+
* design-quality failure. Idempotent on replay via the accepted-fingerprint
|
|
839
|
+
* cache.
|
|
840
|
+
*/
|
|
841
|
+
requeueForDesignCritique(args) {
|
|
842
|
+
const session = this.requireSession(args.sessionId);
|
|
843
|
+
const fp = fingerprint([
|
|
844
|
+
'requeueForDesignCritique',
|
|
845
|
+
args.sessionId,
|
|
846
|
+
args.workItemId,
|
|
847
|
+
args.leaseId,
|
|
848
|
+
args.attempt,
|
|
849
|
+
]);
|
|
850
|
+
const cached = session.acceptedFingerprints.get(fp);
|
|
851
|
+
if (cached)
|
|
852
|
+
return cached;
|
|
853
|
+
this.assertStage(session, ['work_items_ready', 'waiting_for_results']);
|
|
854
|
+
const item = this.requireWorkItem(session, args.workItemId);
|
|
855
|
+
this.validateLease(item, args.leaseId, args.attempt);
|
|
856
|
+
// Reset to pending so request_work re-surfaces it. The re-lease increments
|
|
857
|
+
// `attempt`, so the regenerated report carries a fresh fingerprint.
|
|
858
|
+
item.status = 'pending';
|
|
859
|
+
item.lease = undefined;
|
|
860
|
+
item.output = undefined;
|
|
861
|
+
item.error = undefined;
|
|
862
|
+
const input = (item.input ?? {});
|
|
863
|
+
item.input = { ...input, designCritique: args.critique };
|
|
864
|
+
const result = {
|
|
865
|
+
stage: session.stage,
|
|
866
|
+
progress: this.progressOf(session),
|
|
867
|
+
};
|
|
868
|
+
session.acceptedFingerprints.set(fp, result);
|
|
869
|
+
return result;
|
|
870
|
+
}
|
|
639
871
|
/**
|
|
640
872
|
* Creates a refinable HTML work item for a completed static preview variant.
|
|
641
873
|
* The target variant remains the user-facing snapshot; this work item only
|
|
@@ -674,6 +906,7 @@ class SessionStore {
|
|
|
674
906
|
briefBody: targetInput.briefBody,
|
|
675
907
|
...(args.currentHtml ? { currentHtml: args.currentHtml } : {}),
|
|
676
908
|
projectContext: targetInput.projectContext ?? session.projectContext,
|
|
909
|
+
...(targetInput.context ? { context: targetInput.context } : {}),
|
|
677
910
|
},
|
|
678
911
|
acceptedReports: [],
|
|
679
912
|
};
|