@vibes.diy/base 14.3.114 → 14.3.115
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/components/vibe-menu/VibeMenu.js +2 -9
- package/components/vibe-menu/VibeMenu.js.map +1 -1
- package/components/vibe-menu/cards/CodeCard.d.ts +1 -1
- package/components/vibe-menu/cards/CodeCard.js +13 -6
- package/components/vibe-menu/cards/CodeCard.js.map +1 -1
- package/components/vibe-menu/cards/CodeModeWorkspace.d.ts +2 -1
- package/components/vibe-menu/cards/CodeModeWorkspace.js +8 -6
- package/components/vibe-menu/cards/CodeModeWorkspace.js.map +1 -1
- package/components/vibe-menu/geometry.d.ts +1 -0
- package/components/vibe-menu/geometry.js +5 -0
- package/components/vibe-menu/geometry.js.map +1 -1
- package/components/vibe-menu/index.d.ts +3 -0
- package/components/vibe-menu/index.js +3 -0
- package/components/vibe-menu/index.js.map +1 -1
- package/components/vibe-menu/parts/Chip.d.ts +2 -1
- package/components/vibe-menu/parts/Chip.js +26 -2
- package/components/vibe-menu/parts/Chip.js.map +1 -1
- package/components/vibe-menu/parts/Composer.d.ts +11 -0
- package/components/vibe-menu/parts/Composer.js +44 -1
- package/components/vibe-menu/parts/Composer.js.map +1 -1
- package/components/vibe-menu/parts/LookRestyleSection.d.ts +51 -0
- package/components/vibe-menu/parts/LookRestyleSection.js +290 -0
- package/components/vibe-menu/parts/LookRestyleSection.js.map +1 -0
- package/components/vibe-menu/parts/MomentLine.d.ts +1 -0
- package/components/vibe-menu/parts/MomentLine.js +4 -2
- package/components/vibe-menu/parts/MomentLine.js.map +1 -1
- package/components/vibe-menu/parts/SendCap.d.ts +8 -0
- package/components/vibe-menu/parts/SendCap.js +10 -0
- package/components/vibe-menu/parts/SendCap.js.map +1 -0
- package/components/vibe-menu/parts/StatusChipRow.d.ts +8 -1
- package/components/vibe-menu/parts/StatusChipRow.js +20 -5
- package/components/vibe-menu/parts/StatusChipRow.js.map +1 -1
- package/components/vibe-menu/parts/SurveyStrip.d.ts +3 -1
- package/components/vibe-menu/parts/SurveyStrip.js +9 -1
- package/components/vibe-menu/parts/SurveyStrip.js.map +1 -1
- package/components/vibe-menu/parts/agent-log-frame.d.ts +9 -0
- package/components/vibe-menu/parts/agent-log-frame.js +10 -0
- package/components/vibe-menu/parts/agent-log-frame.js.map +1 -0
- package/components/vibe-menu/parts/use-composer-draft.js +30 -0
- package/components/vibe-menu/parts/use-composer-draft.js.map +1 -1
- package/components/vibe-menu/shell/shell.styles.js +62 -2
- package/components/vibe-menu/shell/shell.styles.js.map +1 -1
- package/components/vibe-menu/slices.d.ts +3 -4
- package/components/vibe-menu/slices.js.map +1 -1
- package/components/vibe-menu/vibe-menu.styles.d.ts +3 -3
- package/components/vibe-menu/vibe-menu.styles.js +99 -1
- package/components/vibe-menu/vibe-menu.styles.js.map +1 -1
- package/hooks/img-gen/use-img-gen.d.ts +1 -0
- package/hooks/img-gen/use-img-gen.js +374 -304
- package/hooks/img-gen/use-img-gen.js.map +1 -1
- package/package.json +5 -5
|
@@ -149,6 +149,10 @@ let imgGenProbeDeadlineMs = IMG_GEN_PROBE_DEADLINE_MS;
|
|
|
149
149
|
export function __setImgGenProbeDeadlineMsForTests(ms) {
|
|
150
150
|
imgGenProbeDeadlineMs = ms ?? IMG_GEN_PROBE_DEADLINE_MS;
|
|
151
151
|
}
|
|
152
|
+
const imgGenLeases = new Map();
|
|
153
|
+
export function __resetImgGenLeasesForTests() {
|
|
154
|
+
imgGenLeases.clear();
|
|
155
|
+
}
|
|
152
156
|
const IMG_GEN_COMMIT_REPROBE_DELAYS_MS = [500, 1000, 2000, 4000, 8000, 15000];
|
|
153
157
|
let imgGenCommitReprobeDelaysMs = IMG_GEN_COMMIT_REPROBE_DELAYS_MS;
|
|
154
158
|
export function __setImgGenCommitReprobeDelaysMsForTests(ms) {
|
|
@@ -248,6 +252,8 @@ export function useImgGen(opts) {
|
|
|
248
252
|
const playgroundSpentKeyRef = useRef(undefined);
|
|
249
253
|
const currentGenRef = useRef(null);
|
|
250
254
|
const probeInFlightRef = useRef(null);
|
|
255
|
+
const leaseWaitRef = useRef(null);
|
|
256
|
+
const ownedLeaseRef = useRef(null);
|
|
251
257
|
const commitProbeInFlightRef = useRef(null);
|
|
252
258
|
const displayReadBackRef = useRef(null);
|
|
253
259
|
const committedGenRef = useRef(null);
|
|
@@ -310,13 +316,18 @@ export function useImgGen(opts) {
|
|
|
310
316
|
};
|
|
311
317
|
}, [skip, _id, mediaDb, db]);
|
|
312
318
|
useEffect(() => {
|
|
313
|
-
if (skip || !_id)
|
|
319
|
+
if (skip || !_id) {
|
|
320
|
+
leaseWaitRef.current = null;
|
|
314
321
|
return;
|
|
322
|
+
}
|
|
315
323
|
const inputMeta = inputImage;
|
|
316
324
|
const inputKey = inputMeta
|
|
317
325
|
? `${inputMeta.uploadId ?? ""}|${inputMeta.name ?? ""}|${inputMeta.lastModified ?? ""}|${inputMeta.size ?? ""}|${inputMeta.type ?? ""}`
|
|
318
326
|
: "";
|
|
319
327
|
const genKey = `${_id}-${generationId ?? ""}-${inputKey}-${model ?? ""}-${myHandle ?? ""}`;
|
|
328
|
+
const leaseWaitKey = `${mediaDbName(dbName)}\u0000${genKey}\u0000${prompt ?? ""}`;
|
|
329
|
+
if (leaseWaitRef.current !== leaseWaitKey)
|
|
330
|
+
leaseWaitRef.current = null;
|
|
320
331
|
if (currentGenRef.current === genKey)
|
|
321
332
|
return;
|
|
322
333
|
currentGenRef.current = genKey;
|
|
@@ -496,14 +507,14 @@ export function useImgGen(opts) {
|
|
|
496
507
|
}
|
|
497
508
|
const promptForProbeKey = prompt ?? existingDoc?.prompt;
|
|
498
509
|
const inputIsStoredRef = incomingSourceKey !== undefined;
|
|
499
|
-
if (authoritative === false &&
|
|
500
|
-
!isRegen &&
|
|
501
|
-
(inputImage === undefined || inputIsStoredRef) &&
|
|
502
|
-
(readStartedPending || readPending())) {
|
|
510
|
+
if (authoritative === false && !isRegen && (inputImage === undefined || inputIsStoredRef)) {
|
|
503
511
|
if (existingDoc)
|
|
504
512
|
setDocument(existingDoc);
|
|
505
513
|
setPending(true);
|
|
506
514
|
if (confirmedMediaProbe === undefined || confirmedMediaProbe === null) {
|
|
515
|
+
if (readStartedPending === false && readPending() === false) {
|
|
516
|
+
return decide(mediaDocs, legacyDoc, true);
|
|
517
|
+
}
|
|
507
518
|
currentGenRef.current = null;
|
|
508
519
|
if (readPending() === false)
|
|
509
520
|
setDeferTick((t) => t + 1);
|
|
@@ -560,339 +571,398 @@ export function useImgGen(opts) {
|
|
|
560
571
|
setDocument(existingDoc);
|
|
561
572
|
return;
|
|
562
573
|
}
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
const
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
},
|
|
591
|
-
}));
|
|
592
|
-
if (rFiles.isErr()) {
|
|
593
|
-
if (earlyPreviewRef.current?.genKey === genKey)
|
|
594
|
-
dropEarlyPreview();
|
|
595
|
-
const message = rFiles.Err().message;
|
|
596
|
-
if (message === IMG_GEN_NEEDS_TAP || message === IMG_GEN_CANCELLED) {
|
|
597
|
-
if (existingDoc)
|
|
598
|
-
setDocument(existingDoc);
|
|
599
|
-
playgroundSpentKeyRef.current = genKey;
|
|
600
|
-
playgroundModeRef.current = true;
|
|
601
|
-
currentGenRef.current = null;
|
|
602
|
-
setNeedsTap(true);
|
|
574
|
+
const leaseKey = `${mediaDbName(dbName)}\u0000${hostDocId}\u0000${myHandle}`;
|
|
575
|
+
if (unmountSignalRef.current.aborted)
|
|
576
|
+
return;
|
|
577
|
+
const liveLease = imgGenLeases.get(leaseKey);
|
|
578
|
+
const previousLease = ownedLeaseRef.current;
|
|
579
|
+
const replacesOwnLease = previousLease !== null && previousLease.genKey !== genKey && previousLease.promise === liveLease;
|
|
580
|
+
const deliberateRequest = isRegen || (inputImage !== undefined && inputIsStoredRef === false);
|
|
581
|
+
if (liveLease !== undefined && replacesOwnLease === false && deliberateRequest === false) {
|
|
582
|
+
setPending(true);
|
|
583
|
+
const waitKey = leaseWaitKey;
|
|
584
|
+
currentGenRef.current = null;
|
|
585
|
+
if (leaseWaitRef.current === waitKey)
|
|
586
|
+
return;
|
|
587
|
+
leaseWaitRef.current = waitKey;
|
|
588
|
+
await liveLease;
|
|
589
|
+
if (unmountSignalRef.current.aborted || leaseWaitRef.current !== waitKey)
|
|
590
|
+
return;
|
|
591
|
+
if (currentGenRef.current !== null)
|
|
592
|
+
return;
|
|
593
|
+
const rRead = await exception2Result(loadMediaDocs);
|
|
594
|
+
if (unmountSignalRef.current.aborted || leaseWaitRef.current !== waitKey || currentGenRef.current !== null)
|
|
595
|
+
return;
|
|
596
|
+
leaseWaitRef.current = null;
|
|
597
|
+
currentGenRef.current = genKey;
|
|
598
|
+
if (rRead.isErr()) {
|
|
599
|
+
setError(rRead.Err());
|
|
600
|
+
setPending(false);
|
|
603
601
|
setLoading(false);
|
|
602
|
+
currentGenRef.current = null;
|
|
604
603
|
return;
|
|
605
604
|
}
|
|
606
|
-
|
|
607
|
-
vibe.log("warn", IMG_GEN_SOURCE_UNUSABLE, { docId: hostDocId, dbName });
|
|
608
|
-
}
|
|
609
|
-
if (message === IMG_GEN_UNREACHABLE) {
|
|
610
|
-
playgroundModeRef.current = true;
|
|
611
|
-
setError(new Error(IMG_GEN_UNREACHABLE_MESSAGE));
|
|
612
|
-
}
|
|
613
|
-
else {
|
|
614
|
-
setError(rFiles.Err());
|
|
615
|
-
}
|
|
616
|
-
setLoading(false);
|
|
617
|
-
if (playgroundModeRef.current)
|
|
618
|
-
setNeedsTap(true);
|
|
619
|
-
currentGenRef.current = null;
|
|
620
|
-
return;
|
|
621
|
-
}
|
|
622
|
-
const { files, docWritten } = rFiles.Ok();
|
|
623
|
-
playgroundModeRef.current = false;
|
|
624
|
-
const file = files[0];
|
|
625
|
-
const early = earlyPreviewRef.current?.genKey === genKey ? earlyPreviewRef.current : null;
|
|
626
|
-
if (early !== null) {
|
|
627
|
-
earlyPreviewRef.current = null;
|
|
628
|
-
if (previewUrlsRef.current.has(file.uploadId) === false)
|
|
629
|
-
previewUrlsRef.current.set(file.uploadId, early.url);
|
|
630
|
-
else
|
|
631
|
-
URL.revokeObjectURL(early.url);
|
|
605
|
+
return decide(rRead.Ok(), legacyDoc, false);
|
|
632
606
|
}
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
607
|
+
let resolveLease = () => undefined;
|
|
608
|
+
const lease = new Promise((resolve) => {
|
|
609
|
+
resolveLease = resolve;
|
|
610
|
+
});
|
|
611
|
+
imgGenLeases.set(leaseKey, lease);
|
|
612
|
+
if (replacesOwnLease && previousLease !== null)
|
|
613
|
+
previousLease.release();
|
|
614
|
+
function releaseLease() {
|
|
615
|
+
if (imgGenLeases.get(leaseKey) === lease)
|
|
616
|
+
imgGenLeases.delete(leaseKey);
|
|
617
|
+
resolveLease();
|
|
618
|
+
if (ownedLeaseRef.current?.release === releaseLease)
|
|
619
|
+
ownedLeaseRef.current = null;
|
|
640
620
|
}
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
621
|
+
ownedLeaseRef.current = { genKey, promise: lease, release: releaseLease };
|
|
622
|
+
const generationHandle = myHandle;
|
|
623
|
+
const generationPrompt = promptText;
|
|
624
|
+
async function generate() {
|
|
625
|
+
dropEarlyPreview();
|
|
626
|
+
setPreviewUrl(undefined);
|
|
627
|
+
setLoading(true);
|
|
628
|
+
setProgress(10);
|
|
629
|
+
setError(null);
|
|
630
|
+
const target = {
|
|
631
|
+
dbName,
|
|
632
|
+
docId: hostDocId,
|
|
633
|
+
regen: isRegen,
|
|
634
|
+
...(incomingSourceKey !== undefined ? { sourceKey: incomingSourceKey } : {}),
|
|
635
|
+
};
|
|
636
|
+
const tapRun = tapStarted && generationId !== undefined && tapSpentRef.current !== generationId;
|
|
637
|
+
if (tapRun)
|
|
638
|
+
tapSpentRef.current = generationId;
|
|
639
|
+
const rFiles = await exception2Result(() => imgGen(generationPrompt, {
|
|
640
|
+
inputImage,
|
|
641
|
+
model,
|
|
642
|
+
target,
|
|
643
|
+
...(tapRun ? { userActivation: true } : {}),
|
|
644
|
+
onPreview: (blob) => {
|
|
645
|
+
if (currentGenRef.current !== genKey || unmountSignalRef.current.aborted)
|
|
646
|
+
return;
|
|
647
|
+
if (earlyPreviewRef.current !== null)
|
|
648
|
+
return;
|
|
649
|
+
const url = URL.createObjectURL(blob);
|
|
650
|
+
earlyPreviewRef.current = { genKey, url, blob };
|
|
651
|
+
setPreviewUrl(url);
|
|
652
|
+
},
|
|
653
|
+
}));
|
|
654
|
+
if (rFiles.isErr()) {
|
|
655
|
+
if (earlyPreviewRef.current?.genKey === genKey)
|
|
656
|
+
dropEarlyPreview();
|
|
657
|
+
const message = rFiles.Err().message;
|
|
658
|
+
if (message === IMG_GEN_NEEDS_TAP || message === IMG_GEN_CANCELLED) {
|
|
659
|
+
if (existingDoc)
|
|
660
|
+
setDocument(existingDoc);
|
|
661
|
+
playgroundSpentKeyRef.current = genKey;
|
|
662
|
+
playgroundModeRef.current = true;
|
|
658
663
|
currentGenRef.current = null;
|
|
659
|
-
|
|
660
|
-
if (landedLocally) {
|
|
661
|
-
setDocument(composeDocument({
|
|
662
|
-
hostDocId,
|
|
663
|
-
versionDocs: sortVersionDocs(after),
|
|
664
|
-
pointer: findPointerDoc(after, myHandle),
|
|
665
|
-
legacyDoc,
|
|
666
|
-
}));
|
|
667
|
-
setProgress(100);
|
|
664
|
+
setNeedsTap(true);
|
|
668
665
|
setLoading(false);
|
|
669
666
|
return;
|
|
670
667
|
}
|
|
671
|
-
if (
|
|
672
|
-
|
|
673
|
-
return;
|
|
668
|
+
if (message === IMG_GEN_SOURCE_UNUSABLE) {
|
|
669
|
+
vibe.log("warn", IMG_GEN_SOURCE_UNUSABLE, { docId: hostDocId, dbName });
|
|
674
670
|
}
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
hostDocId,
|
|
679
|
-
versionDocs: sortVersionDocs(after),
|
|
680
|
-
pointer: findPointerDoc(after, myHandle),
|
|
681
|
-
legacyDoc,
|
|
682
|
-
}));
|
|
683
|
-
setPending(true);
|
|
684
|
-
setLoading(false);
|
|
685
|
-
currentGenRef.current = null;
|
|
671
|
+
if (message === IMG_GEN_UNREACHABLE) {
|
|
672
|
+
playgroundModeRef.current = true;
|
|
673
|
+
setError(new Error(IMG_GEN_UNREACHABLE_MESSAGE));
|
|
686
674
|
}
|
|
687
675
|
else {
|
|
688
|
-
|
|
689
|
-
currentGenRef.current = null;
|
|
676
|
+
setError(rFiles.Err());
|
|
690
677
|
}
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
678
|
+
setLoading(false);
|
|
679
|
+
if (playgroundModeRef.current)
|
|
680
|
+
setNeedsTap(true);
|
|
681
|
+
currentGenRef.current = null;
|
|
682
|
+
return;
|
|
683
|
+
}
|
|
684
|
+
const { files, docWritten } = rFiles.Ok();
|
|
685
|
+
playgroundModeRef.current = false;
|
|
686
|
+
const file = files[0];
|
|
687
|
+
const early = earlyPreviewRef.current?.genKey === genKey ? earlyPreviewRef.current : null;
|
|
688
|
+
if (early !== null) {
|
|
689
|
+
earlyPreviewRef.current = null;
|
|
690
|
+
if (previewUrlsRef.current.has(file.uploadId) === false)
|
|
691
|
+
previewUrlsRef.current.set(file.uploadId, early.url);
|
|
692
|
+
else
|
|
693
|
+
URL.revokeObjectURL(early.url);
|
|
694
|
+
}
|
|
695
|
+
else if (file.preview instanceof Blob && previewUrlsRef.current.has(file.uploadId) === false) {
|
|
696
|
+
previewUrlsRef.current.set(file.uploadId, URL.createObjectURL(file.preview));
|
|
697
|
+
}
|
|
698
|
+
const ownBytes = early?.blob ?? (file.preview instanceof Blob ? file.preview : undefined);
|
|
699
|
+
if (ownBytes !== undefined && pictures !== undefined) {
|
|
700
|
+
void pictures.seed(file.uploadId, ownBytes);
|
|
701
|
+
seededRef.current.add(file.uploadId);
|
|
702
|
+
}
|
|
703
|
+
const rRun = await exception2Result(async () => {
|
|
704
|
+
setProgress(90);
|
|
705
|
+
const showCommitted = async (uploadId, clientWrite) => {
|
|
706
|
+
releaseLease();
|
|
707
|
+
if (currentGenRef.current !== genKey)
|
|
708
|
+
return;
|
|
709
|
+
committedGenRef.current = { genKey, uploadId };
|
|
710
|
+
let after = await loadMediaDocs();
|
|
711
|
+
const landedLocally = sortVersionDocs(after).some((vd) => Object.values(vd._files).some((f) => f.uploadId === uploadId && f.url !== undefined));
|
|
712
|
+
const waitForSync = (rows) => {
|
|
713
|
+
setDocument(composeDocument({
|
|
714
|
+
hostDocId,
|
|
715
|
+
versionDocs: sortVersionDocs(rows),
|
|
716
|
+
pointer: findPointerDoc(rows, myHandle),
|
|
717
|
+
legacyDoc,
|
|
718
|
+
}));
|
|
719
|
+
setPending(true);
|
|
720
|
+
setLoading(false);
|
|
721
|
+
currentGenRef.current = null;
|
|
722
|
+
};
|
|
723
|
+
if (landedLocally) {
|
|
724
|
+
setDocument(composeDocument({
|
|
725
|
+
hostDocId,
|
|
726
|
+
versionDocs: sortVersionDocs(after),
|
|
727
|
+
pointer: findPointerDoc(after, myHandle),
|
|
728
|
+
legacyDoc,
|
|
729
|
+
}));
|
|
730
|
+
setProgress(100);
|
|
731
|
+
setLoading(false);
|
|
732
|
+
return;
|
|
733
|
+
}
|
|
734
|
+
if (confirmedMediaProbe === undefined || confirmedMediaProbe === null) {
|
|
735
|
+
waitForSync(after);
|
|
736
|
+
return;
|
|
737
|
+
}
|
|
738
|
+
const heldLocally = sortVersionDocs(after).some((vd) => Object.values(vd._files).some((f) => f.uploadId === uploadId));
|
|
739
|
+
if (heldLocally) {
|
|
740
|
+
setDocument(composeDocument({
|
|
741
|
+
hostDocId,
|
|
742
|
+
versionDocs: sortVersionDocs(after),
|
|
743
|
+
pointer: findPointerDoc(after, myHandle),
|
|
744
|
+
legacyDoc,
|
|
745
|
+
}));
|
|
746
|
+
setPending(true);
|
|
747
|
+
setLoading(false);
|
|
748
|
+
currentGenRef.current = null;
|
|
749
|
+
}
|
|
750
|
+
else {
|
|
751
|
+
setPending(true);
|
|
752
|
+
currentGenRef.current = null;
|
|
753
|
+
}
|
|
754
|
+
const probeKey = `${genKey}\u0000${promptText}`;
|
|
755
|
+
const stillOurs = () => unmountSignalRef.current.aborted === false &&
|
|
756
|
+
commitProbeInFlightRef.current === probeKey &&
|
|
757
|
+
(currentGenRef.current === null || currentGenRef.current === genKey);
|
|
758
|
+
commitProbeInFlightRef.current = probeKey;
|
|
759
|
+
let ourSeq = clientWrite?.seq;
|
|
760
|
+
let rekeeps = 0;
|
|
761
|
+
let collided = false;
|
|
762
|
+
const readBack = () => readBackFromServer({
|
|
763
|
+
probe: confirmedMediaProbe,
|
|
764
|
+
dbName,
|
|
765
|
+
hostDocId,
|
|
766
|
+
signal: unmountSignalRef.current,
|
|
767
|
+
stillOurs,
|
|
768
|
+
logEvent: "imggen-commit-probe-failed",
|
|
769
|
+
examine: async (probedDocs, probedLegacy) => {
|
|
770
|
+
const probedVersions = sortVersionDocs(probedDocs);
|
|
771
|
+
if (holdsUpload(probedVersions, uploadId, true)) {
|
|
772
|
+
commitProbeInFlightRef.current = null;
|
|
773
|
+
currentGenRef.current = genKey;
|
|
774
|
+
setDocument(composeDocument({
|
|
775
|
+
hostDocId,
|
|
776
|
+
versionDocs: probedVersions,
|
|
777
|
+
pointer: laterPointer(findPointerDoc(after, myHandle), findPointerDoc(probedDocs, myHandle)),
|
|
778
|
+
legacyDoc: probedLegacy ?? legacyDoc,
|
|
779
|
+
}));
|
|
780
|
+
setPending(false);
|
|
781
|
+
setProgress(100);
|
|
782
|
+
setLoading(false);
|
|
783
|
+
return { done: true, value: "shown" };
|
|
784
|
+
}
|
|
785
|
+
const taken = clientWrite !== undefined &&
|
|
786
|
+
ourSeq !== undefined &&
|
|
787
|
+
probedVersions.some((vd) => vd.seq === ourSeq && holdsUpload([vd], uploadId, false) === false);
|
|
788
|
+
if (taken === false || clientWrite === undefined)
|
|
789
|
+
return { done: false };
|
|
790
|
+
collided = true;
|
|
791
|
+
if (rekeeps >= IMG_GEN_MAX_REKEEPS)
|
|
792
|
+
return { done: true, value: "unkept" };
|
|
793
|
+
rekeeps++;
|
|
794
|
+
vibe.log("warn", "imggen-version-seq-taken", { docId: hostDocId, dbName, seq: ourSeq ?? 0 });
|
|
795
|
+
const rekept = await clientWrite.rekeep(probedVersions);
|
|
796
|
+
if (rekept === undefined)
|
|
797
|
+
return { done: true, value: "unkept" };
|
|
798
|
+
ourSeq = rekept;
|
|
799
|
+
after = await loadMediaDocs();
|
|
726
800
|
return { done: false };
|
|
801
|
+
},
|
|
802
|
+
});
|
|
803
|
+
let outcome = await readBack();
|
|
804
|
+
while (outcome.kind === "exhausted" &&
|
|
805
|
+
clientWrite !== undefined &&
|
|
806
|
+
ourSeq !== undefined &&
|
|
807
|
+
rekeeps < IMG_GEN_MAX_REKEEPS) {
|
|
808
|
+
const localVersions = sortVersionDocs(await loadMediaDocs());
|
|
809
|
+
if (stillOurs() === false)
|
|
810
|
+
return;
|
|
811
|
+
const lostLocally = localVersions.some((vd) => vd.seq === ourSeq && holdsUpload([vd], uploadId, false) === false);
|
|
812
|
+
if (lostLocally === false)
|
|
813
|
+
break;
|
|
727
814
|
collided = true;
|
|
728
|
-
if (rekeeps >= IMG_GEN_MAX_REKEEPS)
|
|
729
|
-
return { done: true, value: "unkept" };
|
|
730
815
|
rekeeps++;
|
|
731
|
-
vibe.log("warn", "imggen-version-seq-taken", { docId: hostDocId, dbName, seq: ourSeq
|
|
732
|
-
const rekept = await clientWrite.rekeep(
|
|
733
|
-
if (rekept === undefined)
|
|
734
|
-
|
|
816
|
+
vibe.log("warn", "imggen-version-seq-taken", { docId: hostDocId, dbName, seq: ourSeq });
|
|
817
|
+
const rekept = await clientWrite.rekeep(localVersions);
|
|
818
|
+
if (rekept === undefined) {
|
|
819
|
+
outcome = { kind: "done", value: "unkept" };
|
|
820
|
+
break;
|
|
821
|
+
}
|
|
735
822
|
ourSeq = rekept;
|
|
736
823
|
after = await loadMediaDocs();
|
|
737
|
-
|
|
738
|
-
}
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
clientWrite !== undefined &&
|
|
743
|
-
ourSeq !== undefined &&
|
|
744
|
-
rekeeps < IMG_GEN_MAX_REKEEPS) {
|
|
745
|
-
const localVersions = sortVersionDocs(await loadMediaDocs());
|
|
824
|
+
outcome = await readBack();
|
|
825
|
+
}
|
|
826
|
+
if (outcome.kind === "lost" || (outcome.kind === "done" && outcome.value === "shown"))
|
|
827
|
+
return;
|
|
828
|
+
const latest = await loadMediaDocs();
|
|
746
829
|
if (stillOurs() === false)
|
|
747
830
|
return;
|
|
748
|
-
|
|
749
|
-
|
|
831
|
+
commitProbeInFlightRef.current = null;
|
|
832
|
+
const shownFiles = (documentRef.current?._files ?? {});
|
|
833
|
+
if (Object.values(shownFiles).some((f) => f.uploadId === uploadId && f.url !== undefined))
|
|
834
|
+
return;
|
|
835
|
+
const lostAtOurSeq = ourSeq !== undefined &&
|
|
836
|
+
sortVersionDocs(latest).some((vd) => vd.seq === ourSeq && holdsUpload([vd], uploadId, false) === false);
|
|
837
|
+
if ((outcome.kind === "done" && outcome.value === "unkept") || lostAtOurSeq) {
|
|
838
|
+
vibe.log("warn", "imggen-version-unkept", { docId: hostDocId, dbName, uploadId, rekeeps, collided });
|
|
839
|
+
setDocument(composeDocument({
|
|
840
|
+
hostDocId,
|
|
841
|
+
versionDocs: sortVersionDocs(latest),
|
|
842
|
+
pointer: findPointerDoc(latest, myHandle),
|
|
843
|
+
legacyDoc,
|
|
844
|
+
}));
|
|
845
|
+
setError(new Error(IMG_GEN_UNKEPT_MESSAGE));
|
|
846
|
+
setPending(false);
|
|
847
|
+
setLoading(false);
|
|
848
|
+
currentGenRef.current = null;
|
|
849
|
+
return;
|
|
850
|
+
}
|
|
851
|
+
waitForSync(latest);
|
|
852
|
+
};
|
|
853
|
+
if (docWritten === true) {
|
|
854
|
+
await showCommitted(file.uploadId);
|
|
855
|
+
return;
|
|
856
|
+
}
|
|
857
|
+
const fileMeta = {
|
|
858
|
+
uploadId: file.uploadId,
|
|
859
|
+
type: file.mimeType,
|
|
860
|
+
size: file.size,
|
|
861
|
+
lastModified: Date.now(),
|
|
862
|
+
...(temporaryDraft && file.url !== undefined ? { url: file.url } : {}),
|
|
863
|
+
};
|
|
864
|
+
const putVersionAt = (seq) => {
|
|
865
|
+
const versionBody = buildMediaVersionDoc({
|
|
866
|
+
hostDocId,
|
|
867
|
+
promptKey: PROMPT_KEY,
|
|
868
|
+
seq,
|
|
869
|
+
authorHandle: generationHandle,
|
|
870
|
+
files: { [`m${seq}`]: fileMeta },
|
|
871
|
+
prompt: promptText,
|
|
872
|
+
model,
|
|
873
|
+
sourceKey: incomingSourceKey,
|
|
874
|
+
});
|
|
875
|
+
return exception2Result(() => mediaDb.put({ ...versionBody, _id: mediaVersionDocId(hostDocId, PROMPT_KEY, seq) }));
|
|
876
|
+
};
|
|
877
|
+
const movePointerTo = async (seq) => {
|
|
878
|
+
const freshPointerRead = await loadMediaDocs();
|
|
879
|
+
const freshCurrentSeq = findPointerDoc(freshPointerRead, myHandle)?.currentSeq ?? 0;
|
|
880
|
+
if (seq <= freshCurrentSeq)
|
|
881
|
+
return;
|
|
882
|
+
const pointerBody = buildMediaPointerDoc({
|
|
883
|
+
hostDocId,
|
|
884
|
+
promptKey: PROMPT_KEY,
|
|
885
|
+
authorHandle: generationHandle,
|
|
886
|
+
currentSeq: seq,
|
|
887
|
+
});
|
|
888
|
+
await mediaDb.put({ ...pointerBody, _id: mediaPointerDocId(hostDocId, generationHandle) });
|
|
889
|
+
};
|
|
890
|
+
const nextFreeSeq = (...lanes) => {
|
|
891
|
+
const seqs = lanes.flat().map((vd) => vd.seq);
|
|
892
|
+
return seqs.length > 0 ? Math.max(...seqs) + 1 : 1;
|
|
893
|
+
};
|
|
894
|
+
let latestRead = await loadMediaDocs();
|
|
895
|
+
let freshVersions = sortVersionDocs(latestRead);
|
|
896
|
+
let serverVersions = [];
|
|
897
|
+
if (confirmedMediaProbe !== undefined && confirmedMediaProbe !== null) {
|
|
898
|
+
const rServer = await probeWithDeadline(confirmedMediaProbe, dbName, hostDocId);
|
|
899
|
+
if (rServer.isOk())
|
|
900
|
+
serverVersions = sortVersionDocs(rServer.Ok().mediaDocs);
|
|
901
|
+
else
|
|
902
|
+
vibe.log("warn", "imggen-seq-probe-failed", {
|
|
903
|
+
docId: hostDocId,
|
|
904
|
+
dbName,
|
|
905
|
+
deadlineMs: imgGenProbeDeadlineMs,
|
|
906
|
+
message: rServer.Err().message,
|
|
907
|
+
});
|
|
908
|
+
}
|
|
909
|
+
if (holdsUpload([...freshVersions, ...serverVersions], fileMeta.uploadId, false)) {
|
|
910
|
+
await showCommitted(fileMeta.uploadId);
|
|
911
|
+
return;
|
|
912
|
+
}
|
|
913
|
+
let committedSeq;
|
|
914
|
+
let adopted = false;
|
|
915
|
+
let terminalError;
|
|
916
|
+
for (let attempt = 0; attempt < 3; attempt++) {
|
|
917
|
+
const nextSeq = nextFreeSeq(freshVersions, serverVersions);
|
|
918
|
+
const rPut = await putVersionAt(nextSeq);
|
|
919
|
+
if (rPut.isOk()) {
|
|
920
|
+
committedSeq = nextSeq;
|
|
921
|
+
break;
|
|
922
|
+
}
|
|
923
|
+
if (isConflictClassPutError(rPut.Err()) === false) {
|
|
924
|
+
terminalError = rPut.Err();
|
|
750
925
|
break;
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
outcome = { kind: "done", value: "unkept" };
|
|
926
|
+
}
|
|
927
|
+
latestRead = await loadMediaDocs();
|
|
928
|
+
freshVersions = sortVersionDocs(latestRead);
|
|
929
|
+
if (holdsUpload(freshVersions, fileMeta.uploadId, false)) {
|
|
930
|
+
adopted = true;
|
|
757
931
|
break;
|
|
758
932
|
}
|
|
759
|
-
ourSeq = rekept;
|
|
760
|
-
after = await loadMediaDocs();
|
|
761
|
-
outcome = await readBack();
|
|
762
933
|
}
|
|
763
|
-
if (
|
|
764
|
-
|
|
765
|
-
const latest = await loadMediaDocs();
|
|
766
|
-
if (stillOurs() === false)
|
|
767
|
-
return;
|
|
768
|
-
commitProbeInFlightRef.current = null;
|
|
769
|
-
const shownFiles = (documentRef.current?._files ?? {});
|
|
770
|
-
if (Object.values(shownFiles).some((f) => f.uploadId === uploadId && f.url !== undefined))
|
|
771
|
-
return;
|
|
772
|
-
const lostAtOurSeq = ourSeq !== undefined &&
|
|
773
|
-
sortVersionDocs(latest).some((vd) => vd.seq === ourSeq && holdsUpload([vd], uploadId, false) === false);
|
|
774
|
-
if ((outcome.kind === "done" && outcome.value === "unkept") || lostAtOurSeq) {
|
|
775
|
-
vibe.log("warn", "imggen-version-unkept", { docId: hostDocId, dbName, uploadId, rekeeps, collided });
|
|
776
|
-
setDocument(composeDocument({
|
|
777
|
-
hostDocId,
|
|
778
|
-
versionDocs: sortVersionDocs(latest),
|
|
779
|
-
pointer: findPointerDoc(latest, myHandle),
|
|
780
|
-
legacyDoc,
|
|
781
|
-
}));
|
|
782
|
-
setError(new Error(IMG_GEN_UNKEPT_MESSAGE));
|
|
783
|
-
setPending(false);
|
|
934
|
+
if (committedSeq === undefined && adopted === false) {
|
|
935
|
+
setError(terminalError ?? new Error("Image generated but could not be saved after repeated write conflicts — please try again"));
|
|
784
936
|
setLoading(false);
|
|
785
937
|
currentGenRef.current = null;
|
|
786
938
|
return;
|
|
787
939
|
}
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
if (docWritten === true) {
|
|
791
|
-
await showCommitted(file.uploadId);
|
|
792
|
-
return;
|
|
793
|
-
}
|
|
794
|
-
const fileMeta = {
|
|
795
|
-
uploadId: file.uploadId,
|
|
796
|
-
type: file.mimeType,
|
|
797
|
-
size: file.size,
|
|
798
|
-
lastModified: Date.now(),
|
|
799
|
-
...(temporaryDraft && file.url !== undefined ? { url: file.url } : {}),
|
|
800
|
-
};
|
|
801
|
-
const putVersionAt = (seq) => {
|
|
802
|
-
const versionBody = buildMediaVersionDoc({
|
|
803
|
-
hostDocId,
|
|
804
|
-
promptKey: PROMPT_KEY,
|
|
805
|
-
seq,
|
|
806
|
-
authorHandle: myHandle,
|
|
807
|
-
files: { [`m${seq}`]: fileMeta },
|
|
808
|
-
prompt: promptText,
|
|
809
|
-
model,
|
|
810
|
-
sourceKey: incomingSourceKey,
|
|
811
|
-
});
|
|
812
|
-
return exception2Result(() => mediaDb.put({ ...versionBody, _id: mediaVersionDocId(hostDocId, PROMPT_KEY, seq) }));
|
|
813
|
-
};
|
|
814
|
-
const movePointerTo = async (seq) => {
|
|
815
|
-
const freshPointerRead = await loadMediaDocs();
|
|
816
|
-
const freshCurrentSeq = findPointerDoc(freshPointerRead, myHandle)?.currentSeq ?? 0;
|
|
817
|
-
if (seq <= freshCurrentSeq)
|
|
940
|
+
if (committedSeq === undefined) {
|
|
941
|
+
await showCommitted(fileMeta.uploadId);
|
|
818
942
|
return;
|
|
819
|
-
const pointerBody = buildMediaPointerDoc({ hostDocId, promptKey: PROMPT_KEY, authorHandle: myHandle, currentSeq: seq });
|
|
820
|
-
await mediaDb.put({ ...pointerBody, _id: mediaPointerDocId(hostDocId, myHandle) });
|
|
821
|
-
};
|
|
822
|
-
const nextFreeSeq = (...lanes) => {
|
|
823
|
-
const seqs = lanes.flat().map((vd) => vd.seq);
|
|
824
|
-
return seqs.length > 0 ? Math.max(...seqs) + 1 : 1;
|
|
825
|
-
};
|
|
826
|
-
let latestRead = await loadMediaDocs();
|
|
827
|
-
let freshVersions = sortVersionDocs(latestRead);
|
|
828
|
-
let serverVersions = [];
|
|
829
|
-
if (confirmedMediaProbe !== undefined && confirmedMediaProbe !== null) {
|
|
830
|
-
const rServer = await probeWithDeadline(confirmedMediaProbe, dbName, hostDocId);
|
|
831
|
-
if (rServer.isOk())
|
|
832
|
-
serverVersions = sortVersionDocs(rServer.Ok().mediaDocs);
|
|
833
|
-
else
|
|
834
|
-
vibe.log("warn", "imggen-seq-probe-failed", {
|
|
835
|
-
docId: hostDocId,
|
|
836
|
-
dbName,
|
|
837
|
-
deadlineMs: imgGenProbeDeadlineMs,
|
|
838
|
-
message: rServer.Err().message,
|
|
839
|
-
});
|
|
840
|
-
}
|
|
841
|
-
if (holdsUpload([...freshVersions, ...serverVersions], fileMeta.uploadId, false)) {
|
|
842
|
-
await showCommitted(fileMeta.uploadId);
|
|
843
|
-
return;
|
|
844
|
-
}
|
|
845
|
-
let committedSeq;
|
|
846
|
-
let adopted = false;
|
|
847
|
-
let terminalError;
|
|
848
|
-
for (let attempt = 0; attempt < 3; attempt++) {
|
|
849
|
-
const nextSeq = nextFreeSeq(freshVersions, serverVersions);
|
|
850
|
-
const rPut = await putVersionAt(nextSeq);
|
|
851
|
-
if (rPut.isOk()) {
|
|
852
|
-
committedSeq = nextSeq;
|
|
853
|
-
break;
|
|
854
|
-
}
|
|
855
|
-
if (isConflictClassPutError(rPut.Err()) === false) {
|
|
856
|
-
terminalError = rPut.Err();
|
|
857
|
-
break;
|
|
858
943
|
}
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
944
|
+
await movePointerTo(committedSeq);
|
|
945
|
+
await showCommitted(fileMeta.uploadId, {
|
|
946
|
+
seq: committedSeq,
|
|
947
|
+
rekeep: async (probedVersions) => {
|
|
948
|
+
const seq = nextFreeSeq(sortVersionDocs(await loadMediaDocs()), probedVersions);
|
|
949
|
+
const rPut = await putVersionAt(seq);
|
|
950
|
+
if (rPut.isErr()) {
|
|
951
|
+
vibe.log("warn", "imggen-rekeep-failed", { docId: hostDocId, dbName, seq, message: rPut.Err().message });
|
|
952
|
+
return undefined;
|
|
953
|
+
}
|
|
954
|
+
await movePointerTo(seq);
|
|
955
|
+
return seq;
|
|
956
|
+
},
|
|
957
|
+
});
|
|
958
|
+
});
|
|
959
|
+
if (rRun.isErr()) {
|
|
960
|
+
setError(rRun.Err());
|
|
868
961
|
setLoading(false);
|
|
869
962
|
currentGenRef.current = null;
|
|
870
|
-
return;
|
|
871
|
-
}
|
|
872
|
-
if (committedSeq === undefined) {
|
|
873
|
-
await showCommitted(fileMeta.uploadId);
|
|
874
|
-
return;
|
|
875
963
|
}
|
|
876
|
-
await movePointerTo(committedSeq);
|
|
877
|
-
await showCommitted(fileMeta.uploadId, {
|
|
878
|
-
seq: committedSeq,
|
|
879
|
-
rekeep: async (probedVersions) => {
|
|
880
|
-
const seq = nextFreeSeq(sortVersionDocs(await loadMediaDocs()), probedVersions);
|
|
881
|
-
const rPut = await putVersionAt(seq);
|
|
882
|
-
if (rPut.isErr()) {
|
|
883
|
-
vibe.log("warn", "imggen-rekeep-failed", { docId: hostDocId, dbName, seq, message: rPut.Err().message });
|
|
884
|
-
return undefined;
|
|
885
|
-
}
|
|
886
|
-
await movePointerTo(seq);
|
|
887
|
-
return seq;
|
|
888
|
-
},
|
|
889
|
-
});
|
|
890
|
-
});
|
|
891
|
-
if (rRun.isErr()) {
|
|
892
|
-
setError(rRun.Err());
|
|
893
|
-
setLoading(false);
|
|
894
|
-
currentGenRef.current = null;
|
|
895
964
|
}
|
|
965
|
+
await generate().finally(releaseLease);
|
|
896
966
|
}
|
|
897
967
|
run();
|
|
898
968
|
}, [
|