@bivy/bivy 0.21.1 → 0.21.2-staging.10
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/bin/archive-install.mjs +150 -0
- package/bin/bivy.mjs +66 -7
- package/bin/cli-commands.mjs +1 -1
- package/bin/guides/add-an-agent.md +39 -0
- package/bin/prune-sessions.mjs +46 -14
- package/dist/agent-cli.js +91 -63
- package/dist/agents/claude-code/runtime.js +19 -10
- package/dist/apps/styles.css +1 -50
- package/dist/automation-reseal.js +2 -0
- package/dist/node-config.js +18 -0
- package/dist/node-update.js +26 -1
- package/dist/plugin-cli.js +3 -4
- package/dist/plugin-sdk/manifest.js +19 -11
- package/dist/runtime/cli-parsers.js +18 -1
- package/dist/runtime/index.js +71 -41
- package/dist/server.js +38 -34
- package/dist/worktree.js +17 -0
- package/package.json +1 -1
- package/web/assets/AutomationsView-DRwMTpsz.js +51 -0
- package/web/assets/{ChangesCard-CxQKGf6b.js → ChangesCard-C5rvJ8Cq.js} +3 -3
- package/web/assets/{LibraryView-D3uu06xU.js → LibraryView-CIJ-Pfv-.js} +1 -1
- package/web/assets/ProviderConnect-DiFSOT6L.js +1 -0
- package/web/assets/SessionList-CxRibKT5.js +1 -0
- package/web/assets/{Settings-DrK5DKuy.js → Settings-BukJBTwA.js} +8 -8
- package/web/assets/{Sheet-C8gx0OoI.js → Sheet-CfbcQeWy.js} +1 -1
- package/web/assets/{Terminal-DrqMIIhr.js → Terminal-7Q0Os9n9.js} +5 -5
- package/web/assets/{VoiceSettings-CBBuyKN7.js → VoiceSettings-DwIi92pR.js} +1 -1
- package/web/assets/{abnfDiagram-VCTEODGH-CgIjZZoL.js → abnfDiagram-VCTEODGH-Czjfvfve.js} +1 -1
- package/web/assets/architecture-7GRP2DOG-DD5qRKOE.js +1 -0
- package/web/assets/{architectureDiagram-5GKGNRK7-BMOlU5hT.js → architectureDiagram-5GKGNRK7-DYay_IWI.js} +1 -1
- package/web/assets/{blockDiagram-I7D4REHJ-DkwymH1p.js → blockDiagram-I7D4REHJ-CPlmINAT.js} +1 -1
- package/web/assets/{c4Diagram-7LVT6UL2-B0UDgtWS.js → c4Diagram-7LVT6UL2-DYcLdJNN.js} +1 -1
- package/web/assets/channel-BUg-Y_4E.js +1 -0
- package/web/assets/{chunk-4HAMMTFA-1y76NzcS.js → chunk-4HAMMTFA-CdyB2GrZ.js} +1 -1
- package/web/assets/{chunk-75Z2AOVW-CPFkG_FO.js → chunk-75Z2AOVW-D7h9tbn8.js} +1 -1
- package/web/assets/{chunk-DU6HZSFF-Dy4LQ-iK.js → chunk-DU6HZSFF-BISdfBlT.js} +1 -1
- package/web/assets/{chunk-F27PBJKO-cjpOzWOK.js → chunk-F27PBJKO-2JkB2zU9.js} +1 -1
- package/web/assets/{chunk-GMAD6QVW-CpYC8bxK.js → chunk-GMAD6QVW-BfxS2p5H.js} +1 -1
- package/web/assets/{chunk-GVQU2GXP-DUT271z8.js → chunk-GVQU2GXP-vBPS78dh.js} +1 -1
- package/web/assets/{chunk-IMKFNOWR-C-G3w5yT.js → chunk-IMKFNOWR-C1PvbEPt.js} +1 -1
- package/web/assets/{chunk-L3NEJ4N5-C5N0po6u.js → chunk-L3NEJ4N5-wug0ZtiI.js} +1 -1
- package/web/assets/{chunk-OSK3NFVY-7_vZDCyQ.js → chunk-OSK3NFVY-CSx22WTp.js} +1 -1
- package/web/assets/{chunk-P2QGCYS3-BhXxw6WP.js → chunk-P2QGCYS3-BEJVL1Uw.js} +1 -1
- package/web/assets/{chunk-POPQ4Y6H-iw5O0upC.js → chunk-POPQ4Y6H-DuEsyMhL.js} +1 -1
- package/web/assets/{chunk-PWAF6VOD-C8u0Giuo.js → chunk-PWAF6VOD-DVLOKu0r.js} +1 -1
- package/web/assets/{chunk-SHT3W25Y-BM_QeCu-.js → chunk-SHT3W25Y-Opayr0C_.js} +1 -1
- package/web/assets/{chunk-SVP7TREG-cLDkReFI.js → chunk-SVP7TREG-DgHJUbyu.js} +1 -1
- package/web/assets/{chunk-TICWLB2K-C8fbKbO_.js → chunk-TICWLB2K-DOOCLkvY.js} +1 -1
- package/web/assets/classDiagram-ZZMXUADV-DPpdYhAI.js +1 -0
- package/web/assets/classDiagram-v2-VYDZK3BY-DPpdYhAI.js +1 -0
- package/web/assets/{cynefin-OW5HDTMX-6kzYNsQ0.js → cynefin-OW5HDTMX-1MBj3btC.js} +1 -1
- package/web/assets/{cynefinDiagram-5FMLGOSQ-B3tl5cyI.js → cynefinDiagram-5FMLGOSQ-Cc6rrG7K.js} +1 -1
- package/web/assets/{dagre-GXQ25YYZ-mHX4cPQQ.js → dagre-GXQ25YYZ-DFG3Ndtk.js} +1 -1
- package/web/assets/{diagram-S7CK7UJ4-DhOtHdTh.js → diagram-S7CK7UJ4-SiM6_pqS.js} +1 -1
- package/web/assets/{diagram-UQ7AKVKN-B6BD-P5q.js → diagram-UQ7AKVKN-BUI0Ju7Z.js} +1 -1
- package/web/assets/{diagram-VSXAHHWV-DWXWifeJ.js → diagram-VSXAHHWV-CXMYZkbm.js} +1 -1
- package/web/assets/{diagram-VX7I27RA-DcU0vblN.js → diagram-VX7I27RA-CNCbmY76.js} +1 -1
- package/web/assets/{diagram-Z3DM3KII-Tc32VaTG.js → diagram-Z3DM3KII-Cf3mrdyV.js} +1 -1
- package/web/assets/{ebnfDiagram-PWID7BFC-fbSC7Ytl.js → ebnfDiagram-PWID7BFC-Ban7TN8N.js} +1 -1
- package/web/assets/{erDiagram-RLTQ6QDP-VCd4vHPL.js → erDiagram-RLTQ6QDP-yDvXNUaN.js} +1 -1
- package/web/assets/eventmodeling-NTZA5JFV-BktxSOvh.js +1 -0
- package/web/assets/flowDiagram-HODETNUW-CuT_k3cJ.js +1 -0
- package/web/assets/{ganttDiagram-EL5Y4UJY-qlPJPHC9.js → ganttDiagram-EL5Y4UJY-CRtk9R_T.js} +1 -1
- package/web/assets/{gitGraph-4MIJSDKK-Frn6_UlZ.js → gitGraph-4MIJSDKK-DVCE-pa5.js} +1 -1
- package/web/assets/{gitGraphDiagram-WWUBYQGX-CJv1U3iy.js → gitGraphDiagram-WWUBYQGX-BGNEoPtQ.js} +1 -1
- package/web/assets/{index-DoVsvSyc.js → index-Bkcd452U.js} +2 -2
- package/web/assets/index-CkoStrAe.css +1 -0
- package/web/assets/{info-A6RAGUB7-x2ehGecF.js → info-A6RAGUB7-CmlSnIUY.js} +1 -1
- package/web/assets/{infoDiagram-27XIBGKW-CzHIphTX.js → infoDiagram-27XIBGKW-CV6e39nj.js} +1 -1
- package/web/assets/{ishikawaDiagram-5VMMS53U-1aIpAo5f.js → ishikawaDiagram-5VMMS53U-BZ317iz5.js} +1 -1
- package/web/assets/{journeyDiagram-3NMN7TZE-DZFs2eed.js → journeyDiagram-3NMN7TZE-aRfKE67B.js} +1 -1
- package/web/assets/{kanban-definition-UXKFOSKX-CFPF7vk4.js → kanban-definition-UXKFOSKX-DRAkPvek.js} +1 -1
- package/web/assets/{mermaid-parser.core-eET97OnM.js → mermaid-parser.core-BzKTg0uA.js} +3 -3
- package/web/assets/{mermaid.core-D-l2iyMD.js → mermaid.core-cF9385Jc.js} +4 -4
- package/web/assets/{mindmap-definition-YA3MSWOX-CzO4WiUd.js → mindmap-definition-YA3MSWOX-CLiDn2-4.js} +1 -1
- package/web/assets/mount-DdwNnK_L.js +36 -0
- package/web/assets/{packet-AYTQ26CC-DiT50-0V.js → packet-AYTQ26CC-C_A2hl_f.js} +1 -1
- package/web/assets/{pegDiagram-XKGWAZYB-DG3Ad8mS.js → pegDiagram-XKGWAZYB-DzWlf-iX.js} +1 -1
- package/web/assets/{pie-WAS4IAKB-BGJZoyxN.js → pie-WAS4IAKB-C8_wbVGt.js} +1 -1
- package/web/assets/{pieDiagram-E7YTZNPT-C_IdKjBF.js → pieDiagram-E7YTZNPT-CqlAZb6C.js} +1 -1
- package/web/assets/{quadrantDiagram-AXDQQJYC-CVvfK1li.js → quadrantDiagram-AXDQQJYC-BmL5gqum.js} +1 -1
- package/web/assets/{radar-RG4KPBEZ-C14GlZJM.js → radar-RG4KPBEZ-wXteP-ND.js} +1 -1
- package/web/assets/{railroad-74A4TZTK-Cg3OXIZS.js → railroad-74A4TZTK-CiAiQ98V.js} +1 -1
- package/web/assets/railroad-abnf-HS5TGJTU-7KYSR92O.js +1 -0
- package/web/assets/railroad-ebnf-LZEXJU2U-Dt8zrJqM.js +1 -0
- package/web/assets/railroad-peg-WCYAUIDC-NioqZSpU.js +1 -0
- package/web/assets/{railroadDiagram-O6MQD6OU-_oTlqB8E.js → railroadDiagram-O6MQD6OU-m83Fr2E6.js} +1 -1
- package/web/assets/{requirementDiagram-BXWQKSXE-6_cpGq7p.js → requirementDiagram-BXWQKSXE-DdiUlbNn.js} +1 -1
- package/web/assets/{sankeyDiagram-P5KCCOFB-CIDdTiIM.js → sankeyDiagram-P5KCCOFB-DgRmQoC3.js} +1 -1
- package/web/assets/{sequenceDiagram-WJ2MYXX4-OmglouV4.js → sequenceDiagram-WJ2MYXX4-CLvzUry_.js} +1 -1
- package/web/assets/{settingsRoute-Y4aQ907P.js → settingsRoute-CY886TNp.js} +1 -1
- package/web/assets/{stateDiagram-D77RDMKH-lmR5zsjq.js → stateDiagram-D77RDMKH-CXEsod-X.js} +1 -1
- package/web/assets/stateDiagram-v2-MP3YSRHH-sOazOE8m.js +1 -0
- package/web/assets/{swimlanes-42K2YHIH-BRP1y0vF.js → swimlanes-42K2YHIH-BIXrBhfr.js} +1 -1
- package/web/assets/swimlanesDiagram-VR7AAH4N-CEQROFH_.js +8 -0
- package/web/assets/{timeline-definition-24CTP7MA-74uE748S.js → timeline-definition-24CTP7MA-CHNGDuRJ.js} +1 -1
- package/web/assets/{treeView-Q6P3EWNA-C7rSzN0q.js → treeView-Q6P3EWNA-B5PrKFUx.js} +1 -1
- package/web/assets/{treemap-WGGIJYW6-B-Eqh7wJ.js → treemap-WGGIJYW6-CyfiLDp3.js} +1 -1
- package/web/assets/useStore-BirjskHz.js +16 -0
- package/web/assets/{vennDiagram-4TSXK5OY-9HXkWxEw.js → vennDiagram-4TSXK5OY-DsQXSlTg.js} +1 -1
- package/web/assets/{wardley-WFR3VGLG-Bvwh4mZv.js → wardley-WFR3VGLG-BzGhnDYD.js} +1 -1
- package/web/assets/{wardleyDiagram-VM6X3IG4-D_t1chE2.js → wardleyDiagram-VM6X3IG4-BIxMxWJH.js} +1 -1
- package/web/assets/{xychartDiagram-S5SC5T6Z-BwaxhGtz.js → xychartDiagram-S5SC5T6Z-B6m5ol80.js} +1 -1
- package/web/index.html +2 -2
- package/web/sw.js +1 -1
- package/web/assets/AutomationsView-Cw3-fec-.js +0 -51
- package/web/assets/ProviderConnect-BVnL5_ML.js +0 -1
- package/web/assets/SessionList-qypmhsdJ.js +0 -1
- package/web/assets/architecture-7GRP2DOG-DjnOFWJ6.js +0 -1
- package/web/assets/channel-B7AEPkF6.js +0 -1
- package/web/assets/classDiagram-ZZMXUADV-BEtpnW4V.js +0 -1
- package/web/assets/classDiagram-v2-VYDZK3BY-BEtpnW4V.js +0 -1
- package/web/assets/eventmodeling-NTZA5JFV-CYiUVM8V.js +0 -1
- package/web/assets/flowDiagram-HODETNUW-kSHsw5bd.js +0 -1
- package/web/assets/index-CtJDDeFG.css +0 -1
- package/web/assets/mount-Cnz2WLxO.js +0 -36
- package/web/assets/railroad-abnf-HS5TGJTU-CzpKO8Mq.js +0 -1
- package/web/assets/railroad-ebnf-LZEXJU2U-BBhUgg4O.js +0 -1
- package/web/assets/railroad-peg-WCYAUIDC-C2WJ96PH.js +0 -1
- package/web/assets/stateDiagram-v2-MP3YSRHH-DJ79XS5i.js +0 -1
- package/web/assets/swimlanesDiagram-VR7AAH4N-D08eaEQz.js +0 -8
- package/web/assets/useStore-TM8ZVr6X.js +0 -16
package/dist/server.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
// First: drop agent-session markers the node inherited before anything reads them.
|
|
4
4
|
import "./node-env.js";
|
|
5
5
|
import fs from "node:fs";
|
|
6
|
-
import { createNodeUpdateChecker, managedInstall, updateRegistryUrl } from "./node-update.js";
|
|
6
|
+
import { createNodeUpdateChecker, isArchiveInstall, managedInstall, updateRegistryUrl } from "./node-update.js";
|
|
7
7
|
import { createRemoteSessionAdmission, RemoteSessionAdmissionError } from "./session/remote-session-admission.js";
|
|
8
8
|
import { requiresExistingSession, resolveTargetSession } from "./session/target-session.js";
|
|
9
9
|
import path from "node:path";
|
|
@@ -114,7 +114,7 @@ import { SessionAllowRules } from "./policy/session-allow.js";
|
|
|
114
114
|
import { TerminalManager } from "./terminal.js";
|
|
115
115
|
import { launchCommand } from "./command-launch.js";
|
|
116
116
|
import { listMultiplexerSessions } from "./multiplexer.js";
|
|
117
|
-
import { createWorktree, removeWorktree, gitRepoRoot } from "./worktree.js";
|
|
117
|
+
import { createWorktree, removeWorktree, gitRepoRoot, isManagedWorktreePath, reapedWorktreeBranch } from "./worktree.js";
|
|
118
118
|
import { HarnessManager } from "./harness/manager.js";
|
|
119
119
|
import { startEgressProxyIfEnabled, applySessionSandboxEgress, stopSessionEgress } from "./harness/egress.js";
|
|
120
120
|
import { initSharedDepCache, sharedDepCacheRoot } from "./harness/dep-cache.js";
|
|
@@ -240,9 +240,6 @@ try {
|
|
|
240
240
|
if (process.env[key] === undefined)
|
|
241
241
|
process.env[key] = value;
|
|
242
242
|
}
|
|
243
|
-
if (canonicalNodeConfig.agents && process.env.BIVY_CUSTOM_AGENTS === undefined) {
|
|
244
|
-
process.env.BIVY_CUSTOM_AGENTS = JSON.stringify(Object.entries(canonicalNodeConfig.agents).map(([id, spec]) => ({ id, ...spec })));
|
|
245
|
-
}
|
|
246
243
|
if (canonicalNodeConfig.automation?.checks && process.env.BIVY_AUTOMATION_CHECKS === undefined) {
|
|
247
244
|
process.env.BIVY_AUTOMATION_CHECKS = JSON.stringify(canonicalNodeConfig.automation.checks);
|
|
248
245
|
}
|
|
@@ -827,9 +824,10 @@ const sessionRunPolicy = {
|
|
|
827
824
|
if (process.env.BIVY_SESSION_MODEL_FALLBACK) {
|
|
828
825
|
console.log(`[policy] in-session model reroute enabled: ${process.env.BIVY_SESSION_MODEL_FALLBACK}`);
|
|
829
826
|
}
|
|
827
|
+
const archiveInstalled = isArchiveInstall(repoRoot);
|
|
830
828
|
const nodeUpdates = createNodeUpdateChecker({
|
|
831
829
|
current: currentVersion() ?? "",
|
|
832
|
-
registryUrl: () => updateRegistryUrl(appDir, process.env.BIVY_UPDATE_REGISTRY_URL),
|
|
830
|
+
registryUrl: () => updateRegistryUrl(appDir, process.env.BIVY_UPDATE_REGISTRY_URL, archiveInstalled),
|
|
833
831
|
publish: (state) => broadcast(state),
|
|
834
832
|
});
|
|
835
833
|
function runtimeSummary(rt) {
|
|
@@ -1081,7 +1079,7 @@ const linkedDevices = createLinkedDeviceController({
|
|
|
1081
1079
|
syncPairingMetadata();
|
|
1082
1080
|
relay?.pushRotate(deliveries);
|
|
1083
1081
|
broadcast({ type: "devices.updated", devices });
|
|
1084
|
-
void
|
|
1082
|
+
void checkAutomationTemplates();
|
|
1085
1083
|
},
|
|
1086
1084
|
});
|
|
1087
1085
|
const accessDevices = createAccessDeviceController({
|
|
@@ -2123,11 +2121,9 @@ retireTranscriptsDir();
|
|
|
2123
2121
|
const sessionNewDedupe = createSessionNewDedupe();
|
|
2124
2122
|
const dedupeSessionNew = (requestId, create) => sessionNewDedupe.run(requestId, create);
|
|
2125
2123
|
// Idempotency for `prompt`, keyed by the client's clientMessageId (the same
|
|
2126
|
-
// generic key->promise cache as above, reused for a different key)
|
|
2127
|
-
//
|
|
2128
|
-
//
|
|
2129
|
-
// FollowupCoordinator.retrySending) resends it verbatim after reconnecting;
|
|
2130
|
-
// this makes that safe by collapsing a retried clientMessageId onto the
|
|
2124
|
+
// generic key->promise cache as above, reused for a different key). A client
|
|
2125
|
+
// that isn't sure whether a prompt reached the node before the socket dropped
|
|
2126
|
+
// resends it verbatim after reconnecting; this makes that safe by collapsing a retried clientMessageId onto the
|
|
2131
2127
|
// original broadcast + turn instead of double-prompting the runtime. The key is
|
|
2132
2128
|
// kept for a day, not session.new's 10 minutes: a phone backgrounded mid-send
|
|
2133
2129
|
// can reconnect long after the turn ended, and an expired key turned its
|
|
@@ -3548,7 +3544,7 @@ function startRelayIfConfigured() {
|
|
|
3548
3544
|
if (config.controlPlaneUrl && config.enrollmentToken) {
|
|
3549
3545
|
sessionAdvertiseTarget = { controlPlaneUrl: config.controlPlaneUrl, enrollmentToken: config.enrollmentToken };
|
|
3550
3546
|
void syncModelAuthFromControlPlane();
|
|
3551
|
-
void
|
|
3547
|
+
void checkAutomationTemplates();
|
|
3552
3548
|
if (remoteRuntimeEnabled()) {
|
|
3553
3549
|
// Stage 3: layer a control-plane-backed location registry UNDER the in-memory
|
|
3554
3550
|
// one (so a lookup surviving a restart resolves from durable state), then
|
|
@@ -3678,27 +3674,36 @@ async function modelAuthFetch(pathname, init = {}) {
|
|
|
3678
3674
|
}
|
|
3679
3675
|
// A device revoke rotates the room key. Re-seal this node's stored automation
|
|
3680
3676
|
// instructions under the new key so the node and its devices can still read
|
|
3681
|
-
// them, then drop the retired keys.
|
|
3682
|
-
|
|
3683
|
-
|
|
3684
|
-
|
|
3677
|
+
// them, then drop the retired keys. Instructions no key opens are flagged so the
|
|
3678
|
+
// automation list asks for them again. Runs at every start (retried there until
|
|
3679
|
+
// it completes), after a revoke, and when a run can't open its instructions.
|
|
3680
|
+
let automationTemplateCheck = null;
|
|
3681
|
+
function checkAutomationTemplates() {
|
|
3682
|
+
automationTemplateCheck ??= reconcileAutomationTemplates().finally(() => { automationTemplateCheck = null; });
|
|
3683
|
+
return automationTemplateCheck;
|
|
3684
|
+
}
|
|
3685
|
+
async function reconcileAutomationTemplates() {
|
|
3686
|
+
if (!sessionAdvertiseTarget)
|
|
3685
3687
|
return;
|
|
3688
|
+
const retired = pairingStore.retiredRoomKeys();
|
|
3686
3689
|
const current = pairingStore.roomKey();
|
|
3687
3690
|
try {
|
|
3688
3691
|
const res = await modelAuthFetch("/node/automation-templates");
|
|
3689
3692
|
if (!res?.ok)
|
|
3690
3693
|
throw new Error(`control plane returned ${res?.status}`);
|
|
3691
3694
|
const { templates } = await res.json();
|
|
3695
|
+
const call = async (pathname, init) => {
|
|
3696
|
+
const out = await modelAuthFetch(pathname, init);
|
|
3697
|
+
if (!out?.ok)
|
|
3698
|
+
throw new Error(`control plane returned ${out?.status}`);
|
|
3699
|
+
};
|
|
3692
3700
|
const result = await resealAutomationTemplates({
|
|
3693
3701
|
nodeId: identity.nodeId,
|
|
3694
3702
|
current,
|
|
3695
3703
|
retired,
|
|
3696
3704
|
templates,
|
|
3697
|
-
save:
|
|
3698
|
-
|
|
3699
|
-
if (!saved?.ok)
|
|
3700
|
-
throw new Error(`control plane returned ${saved?.status}`);
|
|
3701
|
-
},
|
|
3705
|
+
save: (id, templateCiphertext) => call(`/node/automation-templates/${encodeURIComponent(id)}`, { method: "PUT", body: JSON.stringify({ templateCiphertext }) }),
|
|
3706
|
+
markUnreadable: (id) => call(`/node/automation-templates/${encodeURIComponent(id)}/unreadable`, { method: "POST" }),
|
|
3702
3707
|
});
|
|
3703
3708
|
if (result.resealed)
|
|
3704
3709
|
console.log(`[automation-reseal] re-sealed ${result.resealed} automation template(s) under the rotated room key`);
|
|
@@ -3706,8 +3711,9 @@ async function resealRetiredAutomationTemplates() {
|
|
|
3706
3711
|
console.warn(`[automation-reseal] ${result.unreadable.length} automation template(s) were sealed under a key this node no longer has: ${result.unreadable.join(", ")}`);
|
|
3707
3712
|
// Another rotation during this pass retired `current`; run again for it.
|
|
3708
3713
|
if (!pairingStore.roomKey().equals(current))
|
|
3709
|
-
return
|
|
3710
|
-
|
|
3714
|
+
return reconcileAutomationTemplates();
|
|
3715
|
+
if (retired.length)
|
|
3716
|
+
pairingStore.forgetRetiredRoomKeys();
|
|
3711
3717
|
}
|
|
3712
3718
|
catch (error) {
|
|
3713
3719
|
console.warn("[automation-reseal] will retry at next start:", error.message);
|
|
@@ -5477,6 +5483,7 @@ async function executeWorkItem(item, report, signal) {
|
|
|
5477
5483
|
item = { ...item, body: template.instructions };
|
|
5478
5484
|
}
|
|
5479
5485
|
catch {
|
|
5486
|
+
void checkAutomationTemplates();
|
|
5480
5487
|
throw new Error("could not decrypt automation instructions on this node");
|
|
5481
5488
|
}
|
|
5482
5489
|
}
|
|
@@ -7004,10 +7011,6 @@ function closeIdleSessions() {
|
|
|
7004
7011
|
closeSessionRecord(record, "idle-timeout");
|
|
7005
7012
|
}
|
|
7006
7013
|
}
|
|
7007
|
-
function isManagedWorktreePath(wtPath) {
|
|
7008
|
-
const parts = path.resolve(wtPath).split(path.sep);
|
|
7009
|
-
return parts.length >= 3 && parts[parts.length - 3] === ".bivy" && parts[parts.length - 2] === "worktrees";
|
|
7010
|
-
}
|
|
7011
7014
|
function sessionTimestampMs(value) {
|
|
7012
7015
|
const ms = value ? new Date(value).getTime() : NaN;
|
|
7013
7016
|
return Number.isFinite(ms) ? ms : 0;
|
|
@@ -8447,8 +8450,8 @@ async function tryAttachLiveRemote(sessionId, options) {
|
|
|
8447
8450
|
}
|
|
8448
8451
|
}
|
|
8449
8452
|
/** Re-open a runtime that still reports streaming shortly after a manual Stop.
|
|
8450
|
-
* The client is settled immediately by the abort handler; prompts arriving
|
|
8451
|
-
*
|
|
8453
|
+
* The client is settled immediately by the abort handler; prompts arriving
|
|
8454
|
+
* right after the Stop await this promise and therefore cannot be steered into the
|
|
8452
8455
|
* stale in-process Pi turn. */
|
|
8453
8456
|
async function recoverRecordAfterAbort(record) {
|
|
8454
8457
|
const oldSession = record.session;
|
|
@@ -8621,20 +8624,21 @@ async function createSession(workspace = defaultWorkspace, sessionFile, opts = {
|
|
|
8621
8624
|
// or branch is gone, we leave it to the invariant to fail safe rather than
|
|
8622
8625
|
// corrupt a neighbour. The clone root is reconstructed from `source`
|
|
8623
8626
|
// (`repo:owner/repo`) because stored `workspace` is the old worktree path.
|
|
8624
|
-
|
|
8625
|
-
|
|
8627
|
+
const reapedBranch = requestedSessionFile && !worktree ? reapedWorktreeBranch(storedMeta) : undefined;
|
|
8628
|
+
if (reapedBranch) {
|
|
8629
|
+
const parsedSource = parseRepoSource(storedMeta?.source);
|
|
8626
8630
|
if (parsedSource) {
|
|
8627
8631
|
const repoDir = path.join(reposRoot, `${parsedSource.owner}__${parsedSource.repo}`);
|
|
8628
8632
|
try {
|
|
8629
8633
|
// Clear any stale registration left by a dir that was rm'd out from under
|
|
8630
8634
|
// git, so re-adding the branch's worktree doesn't hit "already checked out".
|
|
8631
8635
|
runGit(["worktree", "prune"], repoDir);
|
|
8632
|
-
const reprovisioned = await createWorktree({ repoDir, id:
|
|
8636
|
+
const reprovisioned = await createWorktree({ repoDir, id: reapedBranch, branch: reapedBranch });
|
|
8633
8637
|
worktree = reprovisioned;
|
|
8634
8638
|
runtimeWorkspace = reprovisioned.path;
|
|
8635
8639
|
}
|
|
8636
8640
|
catch (error) {
|
|
8637
|
-
console.warn(`Could not re-provision worktree for resumed session on ${
|
|
8641
|
+
console.warn(`Could not re-provision worktree for resumed session on ${reapedBranch}: ${error instanceof Error ? error.message : String(error)}`);
|
|
8638
8642
|
}
|
|
8639
8643
|
}
|
|
8640
8644
|
}
|
package/dist/worktree.js
CHANGED
|
@@ -19,6 +19,23 @@ export function branchSlug(input) {
|
|
|
19
19
|
.replace(/^[-.]+|[-.]+$/g, "")
|
|
20
20
|
.slice(0, 60) || "task");
|
|
21
21
|
}
|
|
22
|
+
/** A Bivy-managed worktree lives at `<repo>/.bivy/worktrees/<name>`. */
|
|
23
|
+
export function isManagedWorktreePath(wtPath) {
|
|
24
|
+
const parts = path.resolve(wtPath).split(path.sep);
|
|
25
|
+
return parts.length >= 3 && parts[parts.length - 3] === ".bivy" && parts[parts.length - 2] === "worktrees";
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* The branch to re-provision when a worktree session is reopened after its
|
|
29
|
+
* directory was removed, else undefined. Worktree cleanup clears `worktree` but
|
|
30
|
+
* leaves `workspace` on the old managed path, so either one marks the session
|
|
31
|
+
* as having run in a worktree.
|
|
32
|
+
*/
|
|
33
|
+
export function reapedWorktreeBranch(meta) {
|
|
34
|
+
if (!meta?.branch)
|
|
35
|
+
return undefined;
|
|
36
|
+
const wtPath = meta.worktree ?? (meta.workspace && isManagedWorktreePath(meta.workspace) ? meta.workspace : undefined);
|
|
37
|
+
return wtPath && !fs.existsSync(wtPath) ? meta.branch : undefined;
|
|
38
|
+
}
|
|
22
39
|
/** The toplevel of the git repo containing `dir`, or undefined if not a repo. */
|
|
23
40
|
export async function gitRepoRoot(dir) {
|
|
24
41
|
try {
|