@bivy/bivy 0.17.3-staging.12 → 0.17.3-staging.14
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/apps/styles.css +3 -2
- package/dist/server.js +16 -4
- package/package.json +1 -1
package/dist/apps/styles.css
CHANGED
|
@@ -1271,6 +1271,7 @@ button.sheet-action:last-child { border-bottom: 0; }
|
|
|
1271
1271
|
.fork-select-field select { width: 100%; padding: 10px 12px; border: 1px solid var(--line-strong); border-radius: var(--radius-md); background: var(--surface); color: var(--ink); }
|
|
1272
1272
|
.fork-toggle { display: flex; align-items: center; gap: 8px; padding: 10px 12px; font-size: 13px; color: var(--ink); }
|
|
1273
1273
|
.fork-toggle input { width: 16px; height: 16px; }
|
|
1274
|
+
.fork-note { margin: 0; padding: var(--space-2) var(--space-3); color: var(--muted); font-size: var(--text-sm); line-height: var(--lh-sm); }
|
|
1274
1275
|
.fork-error { margin: 4px 12px; padding: 8px 10px; border-radius: var(--radius-md); background: var(--surface-2); color: var(--danger); font-size: 12px; }
|
|
1275
1276
|
.fork-warn { margin: 4px 12px; padding: 8px 10px; border-radius: var(--radius-md); background: var(--surface-2); color: var(--muted); font-size: 12px; }
|
|
1276
1277
|
.fork-submit { width: calc(100% - 24px); margin: var(--space-2) var(--space-3); }
|
|
@@ -3202,7 +3203,7 @@ select.picker-search { appearance: auto; }
|
|
|
3202
3203
|
.automation-history-view .autom-section-head > strong { min-width: 0; line-height: var(--lh-lg); }
|
|
3203
3204
|
}
|
|
3204
3205
|
|
|
3205
|
-
/*
|
|
3206
|
-
itself, with one line of
|
|
3206
|
+
/* Handoff notes above the composer (HandoffBanner, StandbyNotice): shaped like
|
|
3207
|
+
the composer itself, with one line of another device's draft. */
|
|
3207
3208
|
.handoff-banner { border-radius: var(--radius-md); }
|
|
3208
3209
|
.handoff-preview { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
package/dist/server.js
CHANGED
|
@@ -1834,6 +1834,20 @@ const replication = new ReplicationService({
|
|
|
1834
1834
|
},
|
|
1835
1835
|
log: (m) => console.error(`[replication] ${m}`),
|
|
1836
1836
|
});
|
|
1837
|
+
/** Take over a replicated session on this node (manual promotion). Once it
|
|
1838
|
+
* wins the epoch it is this node's session, not a standby copy: retag it so
|
|
1839
|
+
* every client stops offering "Continue here", and push the new list. */
|
|
1840
|
+
async function promoteReplicaHere(sessionId) {
|
|
1841
|
+
const epoch = await replication.promote(sessionId, identity.nodeId);
|
|
1842
|
+
if (epoch === undefined)
|
|
1843
|
+
return undefined;
|
|
1844
|
+
const source = metadata.getSession(sessionId)?.source;
|
|
1845
|
+
if (source?.startsWith("replica"))
|
|
1846
|
+
metadata.upsertSession({ id: sessionId, source: source.replace(/^replica/, "promoted") });
|
|
1847
|
+
broadcastSessionsList();
|
|
1848
|
+
scheduleAdvertise();
|
|
1849
|
+
return epoch;
|
|
1850
|
+
}
|
|
1837
1851
|
// Retire the legacy overlay sidecars. The append-only log is the sole overlay
|
|
1838
1852
|
// store now and every session was migrated into it by the prior release's boot
|
|
1839
1853
|
// migration (.migrated-overlays-v1), verified complete on-disk before this landed.
|
|
@@ -2779,10 +2793,9 @@ const RELAY_COMMANDS = {
|
|
|
2779
2793
|
const sessionId = String(msg.sessionId ?? "").trim();
|
|
2780
2794
|
if (!sessionId)
|
|
2781
2795
|
return ctx.reply({ type: "session.promote.result", requestId, ok: false, error: "Missing sessionId" });
|
|
2782
|
-
const epoch = await
|
|
2796
|
+
const epoch = await promoteReplicaHere(sessionId);
|
|
2783
2797
|
if (epoch === undefined)
|
|
2784
2798
|
return ctx.reply({ type: "session.promote.result", requestId, ok: false, error: "Promotion lost the epoch race" });
|
|
2785
|
-
scheduleAdvertise();
|
|
2786
2799
|
ctx.reply({ type: "session.promote.result", requestId, ok: true, sessionId, epoch });
|
|
2787
2800
|
},
|
|
2788
2801
|
// Ephemeral provisioning transport (node-broker path). A remote device that
|
|
@@ -11265,10 +11278,9 @@ app.post("/api/session/promote", async (req, res, next) => {
|
|
|
11265
11278
|
const sessionId = String(req.body?.sessionId ?? "").trim();
|
|
11266
11279
|
if (!sessionId)
|
|
11267
11280
|
return res.status(400).json({ error: "Missing sessionId" });
|
|
11268
|
-
const epoch = await
|
|
11281
|
+
const epoch = await promoteReplicaHere(sessionId);
|
|
11269
11282
|
if (epoch === undefined)
|
|
11270
11283
|
return res.status(409).json({ error: "Promotion lost the epoch race (another node owns it, or it isn't replicated)" });
|
|
11271
|
-
scheduleAdvertise();
|
|
11272
11284
|
res.json({ ok: true, epoch });
|
|
11273
11285
|
}
|
|
11274
11286
|
catch (error) {
|
package/package.json
CHANGED