rivet-design 0.11.10 → 0.11.12
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/config/flags.d.ts +3 -0
- package/dist/config/flags.d.ts.map +1 -1
- package/dist/config/flags.js +3 -0
- package/dist/config/flags.js.map +1 -1
- package/dist/mcp/agent-variants/SessionStore.d.ts +150 -10
- package/dist/mcp/agent-variants/SessionStore.d.ts.map +1 -1
- package/dist/mcp/agent-variants/SessionStore.js +472 -28
- package/dist/mcp/agent-variants/SessionStore.js.map +1 -1
- package/dist/mcp/agent-variants/WorktreeOrchestrator.d.ts +143 -51
- package/dist/mcp/agent-variants/WorktreeOrchestrator.d.ts.map +1 -1
- package/dist/mcp/agent-variants/WorktreeOrchestrator.js +465 -299
- package/dist/mcp/agent-variants/WorktreeOrchestrator.js.map +1 -1
- package/dist/mcp/agent-variants/WorktreeOrchestrator.testHelpers.d.ts +5 -4
- package/dist/mcp/agent-variants/WorktreeOrchestrator.testHelpers.d.ts.map +1 -1
- package/dist/mcp/agent-variants/WorktreeOrchestrator.testHelpers.js +24 -5
- package/dist/mcp/agent-variants/WorktreeOrchestrator.testHelpers.js.map +1 -1
- package/dist/mcp/agent-variants/contracts.d.ts +103 -90
- package/dist/mcp/agent-variants/contracts.d.ts.map +1 -1
- package/dist/mcp/agent-variants/contracts.js +43 -16
- package/dist/mcp/agent-variants/contracts.js.map +1 -1
- package/dist/mcp/agent-variants/createZeroToOneTool.d.ts.map +1 -1
- package/dist/mcp/agent-variants/createZeroToOneTool.js +4 -6
- package/dist/mcp/agent-variants/createZeroToOneTool.js.map +1 -1
- 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 +1 -2
- package/dist/mcp/agent-variants/index.js.map +1 -1
- package/dist/mcp/agent-variants/previewQa.d.ts.map +1 -1
- package/dist/mcp/agent-variants/previewQa.js +0 -6
- package/dist/mcp/agent-variants/previewQa.js.map +1 -1
- package/dist/mcp/agent-variants/tools.d.ts +12 -4
- package/dist/mcp/agent-variants/tools.d.ts.map +1 -1
- package/dist/mcp/agent-variants/tools.js +69 -13
- 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 -1
- package/dist/mcp/changeBatchClassification.js +76 -0
- package/dist/mcp/changeBatchClassification.js.map +1 -1
- package/dist/mcp/instructions.d.ts.map +1 -1
- package/dist/mcp/instructions.js +7 -1
- package/dist/mcp/instructions.js.map +1 -1
- package/dist/mcp/server.d.ts +51 -3
- package/dist/mcp/server.d.ts.map +1 -1
- package/dist/mcp/server.js +404 -156
- package/dist/mcp/server.js.map +1 -1
- package/dist/mcp/watchLoopResumePrompt.d.ts +16 -0
- package/dist/mcp/watchLoopResumePrompt.d.ts.map +1 -0
- package/dist/mcp/watchLoopResumePrompt.js +21 -0
- package/dist/mcp/watchLoopResumePrompt.js.map +1 -0
- package/dist/proxy-middleware/proxy-config.d.ts +13 -0
- package/dist/proxy-middleware/proxy-config.d.ts.map +1 -1
- package/dist/proxy-middleware/proxy-config.js +61 -1
- package/dist/proxy-middleware/proxy-config.js.map +1 -1
- package/dist/routes/agentVariants.d.ts +10 -1
- package/dist/routes/agentVariants.d.ts.map +1 -1
- package/dist/routes/agentVariants.js +236 -5
- package/dist/routes/agentVariants.js.map +1 -1
- package/dist/routes/integrations.d.ts +8 -0
- package/dist/routes/integrations.d.ts.map +1 -0
- package/dist/routes/integrations.js +50 -0
- package/dist/routes/integrations.js.map +1 -0
- package/dist/routes/mcp.d.ts.map +1 -1
- package/dist/routes/mcp.js +106 -47
- package/dist/routes/mcp.js.map +1 -1
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +2 -0
- package/dist/server.js.map +1 -1
- package/dist/services/BridgeBatchPipeline.d.ts +99 -0
- package/dist/services/BridgeBatchPipeline.d.ts.map +1 -0
- package/dist/services/BridgeBatchPipeline.js +278 -0
- package/dist/services/BridgeBatchPipeline.js.map +1 -0
- package/dist/services/BridgeQueueStore.d.ts +28 -0
- package/dist/services/BridgeQueueStore.d.ts.map +1 -0
- package/dist/services/BridgeQueueStore.js +88 -0
- package/dist/services/BridgeQueueStore.js.map +1 -0
- package/dist/services/InlineVariantGenerationService.d.ts.map +1 -1
- package/dist/services/InlineVariantGenerationService.js +15 -3
- package/dist/services/InlineVariantGenerationService.js.map +1 -1
- package/dist/services/IntegrationsClient.d.ts +24 -0
- package/dist/services/IntegrationsClient.d.ts.map +1 -1
- package/dist/services/IntegrationsClient.js +71 -1
- package/dist/services/IntegrationsClient.js.map +1 -1
- package/dist/services/SessionBridgeService.d.ts +127 -31
- package/dist/services/SessionBridgeService.d.ts.map +1 -1
- package/dist/services/SessionBridgeService.js +428 -83
- package/dist/services/SessionBridgeService.js.map +1 -1
- package/dist/services/TelemetryService.d.ts +30 -0
- package/dist/services/TelemetryService.d.ts.map +1 -1
- package/dist/services/TelemetryService.js +42 -0
- package/dist/services/TelemetryService.js.map +1 -1
- package/dist/services/WorktreeManager.d.ts +29 -2
- package/dist/services/WorktreeManager.d.ts.map +1 -1
- package/dist/services/WorktreeManager.js +73 -7
- package/dist/services/WorktreeManager.js.map +1 -1
- package/dist/services/createAgentVariantsOrchestrator.d.ts +0 -8
- package/dist/services/createAgentVariantsOrchestrator.d.ts.map +1 -1
- package/dist/services/createAgentVariantsOrchestrator.js +1 -18
- package/dist/services/createAgentVariantsOrchestrator.js.map +1 -1
- package/dist/utils/portUtils.d.ts +9 -0
- package/dist/utils/portUtils.d.ts.map +1 -1
- package/dist/utils/portUtils.js +26 -0
- package/dist/utils/portUtils.js.map +1 -1
- package/dist/utils/skills/claude-skill.d.ts +1 -1
- package/dist/utils/skills/claude-skill.d.ts.map +1 -1
- package/dist/utils/skills/claude-skill.js +31 -12
- package/dist/utils/skills/claude-skill.js.map +1 -1
- package/dist/utils/skills/cursor-rules.d.ts +1 -1
- package/dist/utils/skills/cursor-rules.d.ts.map +1 -1
- package/dist/utils/skills/cursor-rules.js +26 -11
- package/dist/utils/skills/cursor-rules.js.map +1 -1
- package/dist/utils/skills/shared-variants-protocol.d.ts +28 -0
- package/dist/utils/skills/shared-variants-protocol.d.ts.map +1 -1
- package/dist/utils/skills/shared-variants-protocol.js +88 -14
- package/dist/utils/skills/shared-variants-protocol.js.map +1 -1
- package/package.json +2 -1
- package/src/ui/dist/assets/logo-animation/clasp.png +0 -0
- package/src/ui/dist/assets/logo-animation/eraser.png +0 -0
- package/src/ui/dist/assets/logo-animation/playdough.png +0 -0
- package/src/ui/dist/assets/logo-animation/sea/bubblephone.png +0 -0
- package/src/ui/dist/assets/logo-animation/sea/cart.png +0 -0
- package/src/ui/dist/assets/logo-animation/sea/chair.png +0 -0
- package/src/ui/dist/assets/logo-animation/sea/desk.png +0 -0
- package/src/ui/dist/assets/logo-animation/sea/mug.png +0 -0
- package/src/ui/dist/assets/logo-animation/sea/pitcher.png +0 -0
- package/src/ui/dist/assets/logo-animation/sea/pot.png +0 -0
- package/src/ui/dist/assets/logo-animation/sea/startac.png +0 -0
- package/src/ui/dist/assets/logo-animation/sea/terracotta-1.png +0 -0
- package/src/ui/dist/assets/logo-animation/sea/terracotta-2.png +0 -0
- package/src/ui/dist/assets/logo-animation/sea/vhsplant.png +0 -0
- package/src/ui/dist/assets/main-DREt3GGU.css +1 -0
- package/src/ui/dist/assets/main-DZ_9EXU9.js +655 -0
- package/src/ui/dist/index.html +2 -2
- package/dist/mcp/agent-variants/designCritique.d.ts +0 -167
- package/dist/mcp/agent-variants/designCritique.d.ts.map +0 -1
- package/dist/mcp/agent-variants/designCritique.js +0 -774
- package/dist/mcp/agent-variants/designCritique.js.map +0 -1
- package/src/ui/dist/assets/main-CYm60Rod.js +0 -641
- package/src/ui/dist/assets/main-IY99De7M.css +0 -1
|
@@ -7,7 +7,6 @@ const contracts_1 = require("./contracts");
|
|
|
7
7
|
const runLabel_1 = require("./runLabel");
|
|
8
8
|
const runPlan_1 = require("./runPlan");
|
|
9
9
|
const DEFAULT_VARIANT_COUNT = 4;
|
|
10
|
-
const MAX_VARIANT_COUNT = 8;
|
|
11
10
|
/** TTL for a lease on a code_gen work item. Bumped to 20min after a timing
|
|
12
11
|
* audit found first-variant single-round code-gen routinely runs 540–950s
|
|
13
12
|
* (4+ Task sub-agents in parallel), so the previous 10min cap was the most
|
|
@@ -20,6 +19,17 @@ exports.DEFAULT_LEASE_TTL_MS = 20 * 60 * 1000;
|
|
|
20
19
|
* code_gen bump; scaffold timing has never bound, but a longer lease is safe. */
|
|
21
20
|
exports.SCAFFOLD_LEASE_TTL_MS = 30 * 60 * 1000;
|
|
22
21
|
const SYSTEM_CLOCK = { now: () => Date.now() };
|
|
22
|
+
/** True when a work item is a past variant adopted into the active session
|
|
23
|
+
* (see {@link SessionStore.appendAdoptedStaticVariant}). Adopted variants are
|
|
24
|
+
* surfaced as session members but excluded from generation accounting. */
|
|
25
|
+
function isAdoptedVariant(item) {
|
|
26
|
+
return Boolean(item.input.adoptedFrom);
|
|
27
|
+
}
|
|
28
|
+
/** True when a static preview is a Vary sibling forked from another variant. */
|
|
29
|
+
function isForkedStaticPreviewVariant(item) {
|
|
30
|
+
return (item.kind === 'static_preview' &&
|
|
31
|
+
Boolean(item.input.sourceVariantId));
|
|
32
|
+
}
|
|
23
33
|
function fingerprint(parts) {
|
|
24
34
|
return parts.map((p) => (p === undefined ? '∅' : String(p))).join('|');
|
|
25
35
|
}
|
|
@@ -719,7 +729,23 @@ class SessionStore {
|
|
|
719
729
|
}
|
|
720
730
|
leasable = [target];
|
|
721
731
|
}
|
|
722
|
-
|
|
732
|
+
else if (args.workItemIds !== undefined) {
|
|
733
|
+
// Scoped lease: restrict to a specific batch's work items so concurrent
|
|
734
|
+
// owners (e.g. several watchers each handling their own Vary run) don't
|
|
735
|
+
// greedily lease each other's items. Leases whatever subset of the
|
|
736
|
+
// requested ids is still leasable; only errors if NONE are.
|
|
737
|
+
const wanted = new Set(args.workItemIds);
|
|
738
|
+
leasable = leasable.filter((item) => wanted.has(item.id));
|
|
739
|
+
if (leasable.length === 0) {
|
|
740
|
+
throw new errors_1.AgentVariantsError('INVALID_STAGE_ACTION', 'None of the requested work items are currently leasable (already leased, running, or done)');
|
|
741
|
+
}
|
|
742
|
+
}
|
|
743
|
+
// `workItemIds` takes precedence over `requestedLeaseCount`: a scoped batch
|
|
744
|
+
// leases ALL of its still-leasable items, not a count-capped subset (the
|
|
745
|
+
// scoping above already narrowed `leasable` to exactly that batch).
|
|
746
|
+
const limit = args.workItemIds !== undefined
|
|
747
|
+
? leasable.length
|
|
748
|
+
: (args.requestedLeaseCount ?? leasable.length);
|
|
723
749
|
const issued = leasable.slice(0, Math.max(0, limit));
|
|
724
750
|
if (issued.length === 0) {
|
|
725
751
|
throw new errors_1.AgentVariantsError('INVALID_STAGE_ACTION', 'No work items currently leasable (all running, blocked by deps, or done)');
|
|
@@ -812,6 +838,16 @@ class SessionStore {
|
|
|
812
838
|
item.status = args.status;
|
|
813
839
|
item.output = args.output;
|
|
814
840
|
item.error = args.error;
|
|
841
|
+
// Apply an agent-synthesized title/description so the variant card shows a
|
|
842
|
+
// meaningful name (parent identity + the change) instead of the provisional
|
|
843
|
+
// instruction text. Only on success; capped so the label stays short.
|
|
844
|
+
if (args.status === 'succeeded' && (args.title || args.description)) {
|
|
845
|
+
const input = item.input;
|
|
846
|
+
if (args.title)
|
|
847
|
+
input.briefLabel = args.title.trim().slice(0, 80);
|
|
848
|
+
if (args.description)
|
|
849
|
+
input.briefBody = args.description.trim();
|
|
850
|
+
}
|
|
815
851
|
item.acceptedReports.push(fp);
|
|
816
852
|
item.lease = undefined;
|
|
817
853
|
if (args.status === 'failed') {
|
|
@@ -825,21 +861,20 @@ class SessionStore {
|
|
|
825
861
|
return result;
|
|
826
862
|
}
|
|
827
863
|
/**
|
|
828
|
-
* Re-open a succeeded variant work item for one
|
|
864
|
+
* Re-open a succeeded variant work item for one QA-driven regeneration.
|
|
829
865
|
* Consumes the agent's report (validating the lease), then resets the item
|
|
830
866
|
* to `pending` so it becomes leasable again via `request_work`, stashing the
|
|
831
|
-
*
|
|
832
|
-
*
|
|
867
|
+
* QA notes onto its input so the re-leased descriptor carries the notes the
|
|
868
|
+
* agent must address before re-reporting.
|
|
833
869
|
*
|
|
834
870
|
* The work item never reaches a terminal status, so the session stays in
|
|
835
|
-
* `waiting_for_results` and never goes terminal off the back of a
|
|
836
|
-
*
|
|
837
|
-
* cache.
|
|
871
|
+
* `waiting_for_results` and never goes terminal off the back of a QA
|
|
872
|
+
* failure. Idempotent on replay via the accepted-fingerprint cache.
|
|
838
873
|
*/
|
|
839
|
-
|
|
874
|
+
requeueForRegeneration(args) {
|
|
840
875
|
const session = this.requireSession(args.sessionId);
|
|
841
876
|
const fp = fingerprint([
|
|
842
|
-
'
|
|
877
|
+
'requeueForRegeneration',
|
|
843
878
|
args.sessionId,
|
|
844
879
|
args.workItemId,
|
|
845
880
|
args.leaseId,
|
|
@@ -858,7 +893,7 @@ class SessionStore {
|
|
|
858
893
|
item.output = undefined;
|
|
859
894
|
item.error = undefined;
|
|
860
895
|
const input = (item.input ?? {});
|
|
861
|
-
item.input = { ...input,
|
|
896
|
+
item.input = { ...input, qaRetry: args.qaRetry };
|
|
862
897
|
const result = {
|
|
863
898
|
stage: session.stage,
|
|
864
899
|
progress: this.progressOf(session),
|
|
@@ -903,6 +938,8 @@ class SessionStore {
|
|
|
903
938
|
briefLabel: targetInput.briefLabel,
|
|
904
939
|
briefBody: targetInput.briefBody,
|
|
905
940
|
...(args.currentHtml ? { currentHtml: args.currentHtml } : {}),
|
|
941
|
+
...(args.targetElement ? { targetElement: args.targetElement } : {}),
|
|
942
|
+
...(args.requestId ? { requestId: args.requestId } : {}),
|
|
906
943
|
projectContext: targetInput.projectContext ?? session.projectContext,
|
|
907
944
|
...(targetInput.context ? { context: targetInput.context } : {}),
|
|
908
945
|
},
|
|
@@ -913,6 +950,373 @@ class SessionStore {
|
|
|
913
950
|
session.stage = 'work_items_ready';
|
|
914
951
|
return item;
|
|
915
952
|
}
|
|
953
|
+
/**
|
|
954
|
+
* Fork a completed static_preview variant into N NEW sibling variants. Unlike
|
|
955
|
+
* {@link createRefineVariantWorkItem} (which overwrites the source variant in
|
|
956
|
+
* place), each forked item is a fresh `static_preview` work item with its own
|
|
957
|
+
* id, seeded from the source variant's HTML (`currentHtml`) plus the user's
|
|
958
|
+
* instruction. This backs the "Vary" action, where `variantRequest.count`
|
|
959
|
+
* asks for N new explorations rather than an in-place edit. Returns the
|
|
960
|
+
* created items so the caller can lease them via the normal request-work path.
|
|
961
|
+
*/
|
|
962
|
+
createForkedStaticPreviewWorkItems(args) {
|
|
963
|
+
const session = this.requireSession(args.sessionId);
|
|
964
|
+
const source = this.requireWorkItem(session, args.sourceVariantId);
|
|
965
|
+
if (source.kind !== 'static_preview' || source.status !== 'succeeded') {
|
|
966
|
+
throw new errors_1.AgentVariantsError('VARIANT_NOT_EDITABLE', 'Only completed static_preview variants can be varied');
|
|
967
|
+
}
|
|
968
|
+
if (session.variantPick) {
|
|
969
|
+
throw new errors_1.AgentVariantsError('PENDING_CHANGE_CONFLICT', 'Cannot vary a variant after one has already been sent');
|
|
970
|
+
}
|
|
971
|
+
const activeRefinement = [...session.workItems.values()].find((item) => {
|
|
972
|
+
if (item.kind !== 'refine_variant')
|
|
973
|
+
return false;
|
|
974
|
+
const input = item.input;
|
|
975
|
+
return (input.variantId === args.sourceVariantId &&
|
|
976
|
+
(item.status === 'pending' || item.status === 'running'));
|
|
977
|
+
});
|
|
978
|
+
if (activeRefinement) {
|
|
979
|
+
throw new errors_1.AgentVariantsError('PENDING_CHANGE_CONFLICT', 'Cannot vary a variant while an in-place refinement is pending or running');
|
|
980
|
+
}
|
|
981
|
+
const sourceInput = source.input;
|
|
982
|
+
const seedHtml = args.currentHtml ??
|
|
983
|
+
source.output?.html;
|
|
984
|
+
const total = Math.min(Math.max(Math.trunc(args.count) || 1, 1), contracts_1.VARIANT_COUNT_MAX);
|
|
985
|
+
// Label/describe forked variants by the CHANGE requested (the Vary
|
|
986
|
+
// instruction), not the source brief — otherwise every run on the same
|
|
987
|
+
// variant reads identically ("<source> · variation N") and concurrent runs
|
|
988
|
+
// are indistinguishable in the Directions list.
|
|
989
|
+
const instruction = args.instruction.trim();
|
|
990
|
+
const prettyInstruction = instruction
|
|
991
|
+
? instruction.charAt(0).toUpperCase() + instruction.slice(1)
|
|
992
|
+
: (sourceInput.briefLabel ?? 'Variant');
|
|
993
|
+
const LABEL_MAX = 48;
|
|
994
|
+
const created = [];
|
|
995
|
+
for (let i = 0; i < total; i++) {
|
|
996
|
+
const suffix = total > 1 ? ` · ${i + 1}` : '';
|
|
997
|
+
const labelBase = prettyInstruction.length > LABEL_MAX - suffix.length
|
|
998
|
+
? `${prettyInstruction.slice(0, LABEL_MAX - suffix.length - 1)}…`
|
|
999
|
+
: prettyInstruction;
|
|
1000
|
+
const item = {
|
|
1001
|
+
id: (0, crypto_1.randomUUID)(),
|
|
1002
|
+
kind: 'static_preview',
|
|
1003
|
+
status: 'pending',
|
|
1004
|
+
attempt: 0,
|
|
1005
|
+
dependsOn: [],
|
|
1006
|
+
input: {
|
|
1007
|
+
briefId: `${sourceInput.briefId ?? 'v'}-vary-${(0, crypto_1.randomUUID)().slice(0, 8)}`,
|
|
1008
|
+
// Provisional name/description (the change) shown while generating;
|
|
1009
|
+
// the agent reports a synthesized title/description on completion.
|
|
1010
|
+
briefLabel: `${labelBase}${suffix}`,
|
|
1011
|
+
briefBody: prettyInstruction,
|
|
1012
|
+
instruction: args.instruction,
|
|
1013
|
+
sourceVariantId: args.sourceVariantId,
|
|
1014
|
+
// Parent identity, so the agent can synthesize a name/description that
|
|
1015
|
+
// combines the source variant with the requested change.
|
|
1016
|
+
...(sourceInput.briefLabel
|
|
1017
|
+
? { sourceLabel: sourceInput.briefLabel }
|
|
1018
|
+
: {}),
|
|
1019
|
+
...(sourceInput.briefBody
|
|
1020
|
+
? { sourceBody: sourceInput.briefBody }
|
|
1021
|
+
: {}),
|
|
1022
|
+
...(seedHtml ? { currentHtml: seedHtml } : {}),
|
|
1023
|
+
...(args.targetElement ? { targetElement: args.targetElement } : {}),
|
|
1024
|
+
...(args.requestId ? { requestId: args.requestId } : {}),
|
|
1025
|
+
projectContext: sourceInput.projectContext ?? session.projectContext,
|
|
1026
|
+
...(sourceInput.context ? { context: sourceInput.context } : {}),
|
|
1027
|
+
},
|
|
1028
|
+
acceptedReports: [],
|
|
1029
|
+
};
|
|
1030
|
+
session.workItems.set(item.id, item);
|
|
1031
|
+
// Surface newest siblings at the top of the Directions list: unshift each
|
|
1032
|
+
// in creation order so the batch ends up [variation N … variation 1]
|
|
1033
|
+
// ahead of the pre-existing variants.
|
|
1034
|
+
session.workItemOrder.unshift(item.id);
|
|
1035
|
+
created.push(item);
|
|
1036
|
+
}
|
|
1037
|
+
session.stage = 'work_items_ready';
|
|
1038
|
+
return created;
|
|
1039
|
+
}
|
|
1040
|
+
/**
|
|
1041
|
+
* Append new code_gen variants to an EXISTING-project session that already
|
|
1042
|
+
* holds variants — the worktree-backed analog of
|
|
1043
|
+
* {@link createForkedStaticPreviewWorkItems}. A second "Vary" on an existing
|
|
1044
|
+
* project lands here so its variants ACCUMULATE in the live session instead
|
|
1045
|
+
* of orphaning the prior ones in a fresh, superseding session. The new items
|
|
1046
|
+
* are leasable via {@link requestWork} exactly like the initial code_gen
|
|
1047
|
+
* batch; the orchestrator provisions a worktree per item and runs each
|
|
1048
|
+
* through the normal completion/preview pipeline.
|
|
1049
|
+
*
|
|
1050
|
+
* Reopens the session to `work_items_ready` so the appended pending work is
|
|
1051
|
+
* visible and drives the stage back through generation to ready/degraded.
|
|
1052
|
+
*/
|
|
1053
|
+
appendExistingCodeGenVariants(args) {
|
|
1054
|
+
const session = this.requireSession(args.sessionId);
|
|
1055
|
+
if (session.projectContext.kind !== 'existing') {
|
|
1056
|
+
throw new errors_1.AgentVariantsError('INVALID_STAGE_ACTION', 'Only existing-project sessions can append code_gen variants');
|
|
1057
|
+
}
|
|
1058
|
+
if (session.variantPick) {
|
|
1059
|
+
throw new errors_1.AgentVariantsError('PENDING_CHANGE_CONFLICT', 'Cannot append variants after one has already been committed');
|
|
1060
|
+
}
|
|
1061
|
+
if (session.stage === 'cancelled' || session.stage === 'failed') {
|
|
1062
|
+
throw new errors_1.AgentVariantsError('INVALID_STAGE_ACTION', `Cannot append variants to a ${session.stage} session`);
|
|
1063
|
+
}
|
|
1064
|
+
if (args.briefs.length === 0) {
|
|
1065
|
+
throw new errors_1.AgentVariantsError('MISSING_REQUIRED_INPUT', 'At least one brief is required to append variants');
|
|
1066
|
+
}
|
|
1067
|
+
const createdWorkItemIds = [];
|
|
1068
|
+
for (const brief of args.briefs) {
|
|
1069
|
+
const context = resolveVariantWorkItemContext({
|
|
1070
|
+
bundle: args.variantContext ?? session.projectContext.variantContext,
|
|
1071
|
+
projectContext: session.projectContext,
|
|
1072
|
+
brief,
|
|
1073
|
+
slotIndex: session.briefs.length,
|
|
1074
|
+
});
|
|
1075
|
+
const visualRef = brief.visualReferenceUrl
|
|
1076
|
+
? { visualReferenceUrl: brief.visualReferenceUrl }
|
|
1077
|
+
: {};
|
|
1078
|
+
const item = {
|
|
1079
|
+
id: (0, crypto_1.randomUUID)(),
|
|
1080
|
+
kind: 'code_gen',
|
|
1081
|
+
status: 'pending',
|
|
1082
|
+
attempt: 0,
|
|
1083
|
+
dependsOn: [],
|
|
1084
|
+
input: {
|
|
1085
|
+
briefId: brief.briefId,
|
|
1086
|
+
briefLabel: brief.label,
|
|
1087
|
+
briefBody: brief.body,
|
|
1088
|
+
...visualRef,
|
|
1089
|
+
...(args.runLabel ? { runLabel: args.runLabel } : {}),
|
|
1090
|
+
target: session.target,
|
|
1091
|
+
projectContext: session.projectContext,
|
|
1092
|
+
...(context ? { context } : {}),
|
|
1093
|
+
},
|
|
1094
|
+
acceptedReports: [],
|
|
1095
|
+
};
|
|
1096
|
+
session.workItems.set(item.id, item);
|
|
1097
|
+
// Surface the newest Vary batch at the top of the Directions list, matching
|
|
1098
|
+
// the static-preview fork ordering.
|
|
1099
|
+
session.workItemOrder.unshift(item.id);
|
|
1100
|
+
session.briefs.push(brief);
|
|
1101
|
+
createdWorkItemIds.push(item.id);
|
|
1102
|
+
}
|
|
1103
|
+
session.stage = 'work_items_ready';
|
|
1104
|
+
return { createdWorkItemIds, briefs: args.briefs };
|
|
1105
|
+
}
|
|
1106
|
+
/**
|
|
1107
|
+
* Fork a succeeded code_gen variant into N NEW sibling variants. Each forked
|
|
1108
|
+
* item is seeded from the source variant's worktree (not git HEAD / Original)
|
|
1109
|
+
* and carries `sourceVariantId` so the orchestrator can copy the parent's
|
|
1110
|
+
* tree when provisioning. Backs code_gen "Vary" when the UI targets a parent
|
|
1111
|
+
* variant with `variantRequest.count > 0`.
|
|
1112
|
+
*/
|
|
1113
|
+
createForkedCodeGenWorkItems(args) {
|
|
1114
|
+
const session = this.requireSession(args.sessionId);
|
|
1115
|
+
const source = this.requireWorkItem(session, args.sourceVariantId);
|
|
1116
|
+
if (source.kind !== 'code_gen' || source.status !== 'succeeded') {
|
|
1117
|
+
throw new errors_1.AgentVariantsError('VARIANT_NOT_EDITABLE', 'Only completed code_gen variants can be varied');
|
|
1118
|
+
}
|
|
1119
|
+
if (session.projectContext.kind !== 'existing') {
|
|
1120
|
+
throw new errors_1.AgentVariantsError('INVALID_STAGE_ACTION', 'Only existing-project sessions can fork code_gen variants');
|
|
1121
|
+
}
|
|
1122
|
+
if (session.variantPick) {
|
|
1123
|
+
throw new errors_1.AgentVariantsError('PENDING_CHANGE_CONFLICT', 'Cannot vary a variant after one has already been committed');
|
|
1124
|
+
}
|
|
1125
|
+
if (session.stage === 'cancelled' || session.stage === 'failed') {
|
|
1126
|
+
throw new errors_1.AgentVariantsError('INVALID_STAGE_ACTION', `Cannot fork variants in a ${session.stage} session`);
|
|
1127
|
+
}
|
|
1128
|
+
if (args.briefs.length === 0) {
|
|
1129
|
+
throw new errors_1.AgentVariantsError('MISSING_REQUIRED_INPUT', 'At least one brief is required to fork variants');
|
|
1130
|
+
}
|
|
1131
|
+
const activeRefinement = [...session.workItems.values()].find((item) => {
|
|
1132
|
+
if (item.kind !== 'refine_variant')
|
|
1133
|
+
return false;
|
|
1134
|
+
const input = item.input;
|
|
1135
|
+
return (input.variantId === args.sourceVariantId &&
|
|
1136
|
+
(item.status === 'pending' || item.status === 'running'));
|
|
1137
|
+
});
|
|
1138
|
+
if (activeRefinement) {
|
|
1139
|
+
throw new errors_1.AgentVariantsError('PENDING_CHANGE_CONFLICT', 'Cannot vary a variant while an in-place refinement is pending or running');
|
|
1140
|
+
}
|
|
1141
|
+
const sourceInput = source.input;
|
|
1142
|
+
const createdWorkItemIds = [];
|
|
1143
|
+
for (const brief of args.briefs) {
|
|
1144
|
+
const context = resolveVariantWorkItemContext({
|
|
1145
|
+
bundle: args.variantContext ?? session.projectContext.variantContext,
|
|
1146
|
+
projectContext: session.projectContext,
|
|
1147
|
+
brief,
|
|
1148
|
+
slotIndex: session.briefs.length,
|
|
1149
|
+
});
|
|
1150
|
+
const visualRef = brief.visualReferenceUrl
|
|
1151
|
+
? { visualReferenceUrl: brief.visualReferenceUrl }
|
|
1152
|
+
: {};
|
|
1153
|
+
const item = {
|
|
1154
|
+
id: (0, crypto_1.randomUUID)(),
|
|
1155
|
+
kind: 'code_gen',
|
|
1156
|
+
status: 'pending',
|
|
1157
|
+
attempt: 0,
|
|
1158
|
+
dependsOn: [],
|
|
1159
|
+
input: {
|
|
1160
|
+
briefId: brief.briefId,
|
|
1161
|
+
briefLabel: brief.label,
|
|
1162
|
+
briefBody: brief.body,
|
|
1163
|
+
...visualRef,
|
|
1164
|
+
...(args.runLabel ? { runLabel: args.runLabel } : {}),
|
|
1165
|
+
sourceVariantId: args.sourceVariantId,
|
|
1166
|
+
...(sourceInput.briefLabel
|
|
1167
|
+
? { sourceLabel: sourceInput.briefLabel }
|
|
1168
|
+
: {}),
|
|
1169
|
+
...(sourceInput.briefBody ? { sourceBody: sourceInput.briefBody } : {}),
|
|
1170
|
+
target: session.target,
|
|
1171
|
+
projectContext: session.projectContext,
|
|
1172
|
+
...(context ? { context } : {}),
|
|
1173
|
+
},
|
|
1174
|
+
acceptedReports: [],
|
|
1175
|
+
};
|
|
1176
|
+
session.workItems.set(item.id, item);
|
|
1177
|
+
session.workItemOrder.unshift(item.id);
|
|
1178
|
+
session.briefs.push(brief);
|
|
1179
|
+
createdWorkItemIds.push(item.id);
|
|
1180
|
+
}
|
|
1181
|
+
session.stage = 'work_items_ready';
|
|
1182
|
+
return { createdWorkItemIds, briefs: args.briefs };
|
|
1183
|
+
}
|
|
1184
|
+
/**
|
|
1185
|
+
* Adopt a PAST variant (from a prior session's persisted history) into THIS
|
|
1186
|
+
* active session as a first-class, already-`succeeded` `static_preview`
|
|
1187
|
+
* variant. Triggered when the user makes their first edit (a comment or a
|
|
1188
|
+
* Vary) on a selected past direction: the past variant is rehydrated as a
|
|
1189
|
+
* live session member so the comment/refine machinery scopes and routes to it
|
|
1190
|
+
* exactly like a freshly-generated variant. The caller (orchestrator) registers
|
|
1191
|
+
* the static-preview record that points at the rehydrated files so the snapshot
|
|
1192
|
+
* surfaces it as a `static_artifact`.
|
|
1193
|
+
*
|
|
1194
|
+
* Kept as `static_preview` regardless of the host session's primary variant
|
|
1195
|
+
* kind so {@link createRefineVariantWorkItem} / {@link createForkedStaticPreviewWorkItems}
|
|
1196
|
+
* accept it. Adopted variants are pre-completed artifacts, so they are excluded
|
|
1197
|
+
* from progress/summary/terminal accounting and never reopen the session.
|
|
1198
|
+
*
|
|
1199
|
+
* Idempotent: re-adopting the same `{sessionId, variantId}` returns the
|
|
1200
|
+
* existing work item id (`created: false`) rather than duplicating it.
|
|
1201
|
+
*/
|
|
1202
|
+
appendAdoptedStaticVariant(args) {
|
|
1203
|
+
const session = this.requireSession(args.sessionId);
|
|
1204
|
+
if (session.stage === 'cancelled' || session.stage === 'failed') {
|
|
1205
|
+
throw new errors_1.AgentVariantsError('INVALID_STAGE_ACTION', `Cannot adopt a variant into a ${session.stage} session`);
|
|
1206
|
+
}
|
|
1207
|
+
const existing = this.findAdoptedVariant(session, args.source);
|
|
1208
|
+
if (existing) {
|
|
1209
|
+
const input = existing.input;
|
|
1210
|
+
return {
|
|
1211
|
+
workItemId: existing.id,
|
|
1212
|
+
briefId: input.briefId ?? '',
|
|
1213
|
+
created: false,
|
|
1214
|
+
};
|
|
1215
|
+
}
|
|
1216
|
+
if (session.variantPick) {
|
|
1217
|
+
throw new errors_1.AgentVariantsError('PENDING_CHANGE_CONFLICT', 'Cannot adopt a variant after one has already been committed');
|
|
1218
|
+
}
|
|
1219
|
+
const briefId = `adopted-${(0, crypto_1.randomUUID)().slice(0, 8)}`;
|
|
1220
|
+
const item = {
|
|
1221
|
+
id: (0, crypto_1.randomUUID)(),
|
|
1222
|
+
kind: 'static_preview',
|
|
1223
|
+
status: 'succeeded',
|
|
1224
|
+
attempt: 0,
|
|
1225
|
+
dependsOn: [],
|
|
1226
|
+
input: {
|
|
1227
|
+
briefId,
|
|
1228
|
+
briefLabel: args.label,
|
|
1229
|
+
...(args.description ? { briefBody: args.description } : {}),
|
|
1230
|
+
...(args.runLabel ? { runLabel: args.runLabel } : {}),
|
|
1231
|
+
adoptedFrom: { ...args.source },
|
|
1232
|
+
projectContext: session.projectContext,
|
|
1233
|
+
},
|
|
1234
|
+
acceptedReports: [],
|
|
1235
|
+
};
|
|
1236
|
+
session.workItems.set(item.id, item);
|
|
1237
|
+
// Adoption is triggered by the user's first in-place edit (a comment /
|
|
1238
|
+
// refine) on an ALREADY-DISPLAYED past direction — not a request for a new
|
|
1239
|
+
// exploration. Appending (rather than unshifting to the top) preserves the
|
|
1240
|
+
// positions of the existing active variants so a refined card does NOT
|
|
1241
|
+
// leapfrog a newer Vary/fork batch. Genuinely new variants (Vary / fork /
|
|
1242
|
+
// append) still surface at the top via their own `unshift` paths. Stage is
|
|
1243
|
+
// intentionally left untouched — the adopted variant is already complete,
|
|
1244
|
+
// so the session must not reopen to `work_items_ready`.
|
|
1245
|
+
session.workItemOrder.push(item.id);
|
|
1246
|
+
return { workItemId: item.id, briefId, created: true };
|
|
1247
|
+
}
|
|
1248
|
+
/**
|
|
1249
|
+
* Create an active session whose initial visible direction is a static
|
|
1250
|
+
* variant rehydrated from persisted history.
|
|
1251
|
+
*
|
|
1252
|
+
* This is the no-usable-session counterpart to
|
|
1253
|
+
* {@link appendAdoptedStaticVariant}: the session starts terminal/ready
|
|
1254
|
+
* because the adopted artifact is already generated, and the adopted work item
|
|
1255
|
+
* remains excluded from generation progress because this run did not generate
|
|
1256
|
+
* fresh variants.
|
|
1257
|
+
*/
|
|
1258
|
+
createSessionFromStaticHistoryVariant(args) {
|
|
1259
|
+
const sessionId = (0, crypto_1.randomUUID)();
|
|
1260
|
+
const record = {
|
|
1261
|
+
sessionId,
|
|
1262
|
+
stage: 'ready',
|
|
1263
|
+
prompt: args.prompt,
|
|
1264
|
+
runLabel: args.runLabel?.trim() || undefined,
|
|
1265
|
+
count: 0,
|
|
1266
|
+
projectContext: args.projectContext,
|
|
1267
|
+
briefs: [],
|
|
1268
|
+
approvedBriefs: [],
|
|
1269
|
+
workItems: new Map(),
|
|
1270
|
+
workItemOrder: [],
|
|
1271
|
+
acceptedFingerprints: new Map(),
|
|
1272
|
+
createdAt: this.clock.now(),
|
|
1273
|
+
};
|
|
1274
|
+
this.sessions.set(sessionId, record);
|
|
1275
|
+
const adopted = this.appendAdoptedStaticVariant({
|
|
1276
|
+
sessionId,
|
|
1277
|
+
source: args.source,
|
|
1278
|
+
label: args.label,
|
|
1279
|
+
description: args.description,
|
|
1280
|
+
runLabel: args.runLabel,
|
|
1281
|
+
});
|
|
1282
|
+
return {
|
|
1283
|
+
sessionId,
|
|
1284
|
+
workItemId: adopted.workItemId,
|
|
1285
|
+
briefId: adopted.briefId,
|
|
1286
|
+
};
|
|
1287
|
+
}
|
|
1288
|
+
/** Find an already-adopted variant by its source identity, or undefined. */
|
|
1289
|
+
findAdoptedVariant(session, source) {
|
|
1290
|
+
for (const item of session.workItems.values()) {
|
|
1291
|
+
if (item.removed)
|
|
1292
|
+
continue;
|
|
1293
|
+
const adoptedFrom = item.input
|
|
1294
|
+
.adoptedFrom;
|
|
1295
|
+
if (adoptedFrom &&
|
|
1296
|
+
adoptedFrom.sessionId === source.sessionId &&
|
|
1297
|
+
adoptedFrom.variantId === source.variantId) {
|
|
1298
|
+
return item;
|
|
1299
|
+
}
|
|
1300
|
+
}
|
|
1301
|
+
return undefined;
|
|
1302
|
+
}
|
|
1303
|
+
/**
|
|
1304
|
+
* Stamp a UI correlation id onto already-created variant work items so the
|
|
1305
|
+
* snapshot surfaces it and the panel can map its optimistic placeholders to
|
|
1306
|
+
* the real cards (see {@link ActiveVariantSnapshot.requestId}). Skips ids
|
|
1307
|
+
* that are unknown to the session. Used by `start_variants` for both the
|
|
1308
|
+
* initial batch and the appended (accumulated) batch.
|
|
1309
|
+
*/
|
|
1310
|
+
assignVariantRequestId(sessionId, workItemIds, requestId) {
|
|
1311
|
+
const session = this.requireSession(sessionId);
|
|
1312
|
+
for (const id of workItemIds) {
|
|
1313
|
+
const item = session.workItems.get(id);
|
|
1314
|
+
if (!item)
|
|
1315
|
+
continue;
|
|
1316
|
+
const input = (item.input ?? {});
|
|
1317
|
+
item.input = { ...input, requestId };
|
|
1318
|
+
}
|
|
1319
|
+
}
|
|
916
1320
|
/**
|
|
917
1321
|
* Fold a newer instruction into a variant's still-pending refinement. Used
|
|
918
1322
|
* when a second refinement is requested for a variant that already has a
|
|
@@ -1349,8 +1753,13 @@ class SessionStore {
|
|
|
1349
1753
|
const kind = this.variantWorkItemKind(session);
|
|
1350
1754
|
// Removed variants are excluded everywhere progress/summary/terminal
|
|
1351
1755
|
// accounting reads from, so a removed variant neither blocks the session
|
|
1352
|
-
// from going terminal nor inflates the ready/total counts.
|
|
1353
|
-
|
|
1756
|
+
// from going terminal nor inflates the ready/total counts. Adopted past
|
|
1757
|
+
// variants are likewise excluded: they are pre-completed artifacts pulled in
|
|
1758
|
+
// for editing, not part of this run's generation, so they must not inflate
|
|
1759
|
+
// progress/total or flip a failed run to degraded.
|
|
1760
|
+
return [...session.workItems.values()].filter((i) => (i.kind === kind || isForkedStaticPreviewVariant(i)) &&
|
|
1761
|
+
!i.removed &&
|
|
1762
|
+
!isAdoptedVariant(i));
|
|
1354
1763
|
}
|
|
1355
1764
|
/**
|
|
1356
1765
|
* The work-item kind that represents a user-facing variant for this
|
|
@@ -1434,6 +1843,13 @@ class SessionStore {
|
|
|
1434
1843
|
}),
|
|
1435
1844
|
};
|
|
1436
1845
|
}
|
|
1846
|
+
refinementSnapshotPriority(item) {
|
|
1847
|
+
if (item.status === 'running')
|
|
1848
|
+
return 2;
|
|
1849
|
+
if (item.status === 'pending')
|
|
1850
|
+
return 1;
|
|
1851
|
+
return 0;
|
|
1852
|
+
}
|
|
1437
1853
|
variantsOf(session) {
|
|
1438
1854
|
const kind = this.variantWorkItemKind(session);
|
|
1439
1855
|
const refinementsByVariantId = new Map();
|
|
@@ -1443,30 +1859,58 @@ class SessionStore {
|
|
|
1443
1859
|
const input = item.input;
|
|
1444
1860
|
if (!input.variantId)
|
|
1445
1861
|
continue;
|
|
1446
|
-
refinementsByVariantId.
|
|
1862
|
+
const existing = refinementsByVariantId.get(input.variantId);
|
|
1863
|
+
if (!existing ||
|
|
1864
|
+
this.refinementSnapshotPriority(item) >
|
|
1865
|
+
this.refinementSnapshotPriority(existing)) {
|
|
1866
|
+
refinementsByVariantId.set(input.variantId, item);
|
|
1867
|
+
}
|
|
1447
1868
|
}
|
|
1448
|
-
return
|
|
1449
|
-
.
|
|
1869
|
+
return session.workItemOrder
|
|
1870
|
+
.map((id) => session.workItems.get(id))
|
|
1871
|
+
.filter((i) => !!i &&
|
|
1872
|
+
!i.removed &&
|
|
1873
|
+
(i.kind === kind ||
|
|
1874
|
+
isAdoptedVariant(i) ||
|
|
1875
|
+
isForkedStaticPreviewVariant(i)))
|
|
1450
1876
|
.map((item) => {
|
|
1451
1877
|
const input = item.input;
|
|
1878
|
+
const refineItem = refinementsByVariantId.get(item.id);
|
|
1879
|
+
const refineRequestId = refineItem?.input
|
|
1880
|
+
?.requestId;
|
|
1452
1881
|
return {
|
|
1453
1882
|
workItemId: item.id,
|
|
1454
1883
|
briefId: input.briefId ?? '',
|
|
1455
1884
|
label: input.briefLabel ?? 'Variant',
|
|
1456
1885
|
status: item.status,
|
|
1457
1886
|
createdAt: new Date(session.createdAt).toISOString(),
|
|
1458
|
-
|
|
1887
|
+
// Prefer the per-item label stamped by an appended Vary batch; the
|
|
1888
|
+
// session-level fallback is correct only for the first batch (its
|
|
1889
|
+
// prompt is the session prompt). Without this, accumulated batches
|
|
1890
|
+
// all show batch 1's tag.
|
|
1891
|
+
runLabel: input.runLabel ??
|
|
1892
|
+
session.runLabel ??
|
|
1893
|
+
(0, runLabel_1.deriveRunLabel)(session.prompt),
|
|
1894
|
+
// Correlation id of the UI request that produced this variant (a fork)
|
|
1895
|
+
// or, for an in-place refine, the request driving its refinement —
|
|
1896
|
+
// lets the UI map its optimistic placeholders to real cards.
|
|
1897
|
+
...(input.requestId
|
|
1898
|
+
? { requestId: input.requestId }
|
|
1899
|
+
: refineRequestId
|
|
1900
|
+
? { requestId: refineRequestId }
|
|
1901
|
+
: {}),
|
|
1459
1902
|
...(input.briefBody ? { description: input.briefBody } : {}),
|
|
1903
|
+
...(input.adoptedFrom
|
|
1904
|
+
? { adoptedSource: { ...input.adoptedFrom } }
|
|
1905
|
+
: {}),
|
|
1460
1906
|
design: variantDesignFromInput(input.designContextEntry),
|
|
1461
|
-
...(
|
|
1907
|
+
...(refineItem
|
|
1462
1908
|
? {
|
|
1463
1909
|
refinement: {
|
|
1464
|
-
workItemId:
|
|
1465
|
-
status:
|
|
1466
|
-
...(
|
|
1467
|
-
? {
|
|
1468
|
-
errorCode: String(refinementsByVariantId.get(item.id).error?.code),
|
|
1469
|
-
}
|
|
1910
|
+
workItemId: refineItem.id,
|
|
1911
|
+
status: refineItem.status,
|
|
1912
|
+
...(refineItem.error?.code
|
|
1913
|
+
? { errorCode: String(refineItem.error.code) }
|
|
1470
1914
|
: {}),
|
|
1471
1915
|
},
|
|
1472
1916
|
}
|
|
@@ -1480,10 +1924,10 @@ exports.SessionStore = SessionStore;
|
|
|
1480
1924
|
function clampCount(count) {
|
|
1481
1925
|
if (count === undefined)
|
|
1482
1926
|
return DEFAULT_VARIANT_COUNT;
|
|
1483
|
-
if (count <
|
|
1484
|
-
return
|
|
1485
|
-
if (count >
|
|
1486
|
-
return
|
|
1927
|
+
if (count < contracts_1.VARIANT_COUNT_MIN)
|
|
1928
|
+
return contracts_1.VARIANT_COUNT_MIN;
|
|
1929
|
+
if (count > contracts_1.VARIANT_COUNT_MAX)
|
|
1930
|
+
return contracts_1.VARIANT_COUNT_MAX;
|
|
1487
1931
|
return count;
|
|
1488
1932
|
}
|
|
1489
1933
|
//# sourceMappingURL=SessionStore.js.map
|