@bivy/bivy 0.12.0-staging.405 → 0.12.0-staging.406

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.
Files changed (2) hide show
  1. package/dist/server.js +14 -9
  2. package/package.json +1 -1
package/dist/server.js CHANGED
@@ -4625,18 +4625,23 @@ function invalidateGitHubApps() {
4625
4625
  // token nor an app key. When BIVY_HOSTED_MINT is set they mint a fresh,
4626
4626
  // short-lived token from the control plane per git op — cached until ~5 min
4627
4627
  // before expiry so a burst of git ops is a single round trip. This is the final
4628
- // fallback rung after local apps and BIVY_GITHUB_TOKEN.
4629
- let hostedMintCache;
4630
- async function hostedMintToken() {
4628
+ // fallback rung after local apps and BIVY_GITHUB_TOKEN. Passing the repo lets
4629
+ // the control plane pick the matching central-app installation and scope the
4630
+ // token down to that repo, so the cache is keyed per repo.
4631
+ const hostedMintCache = new Map();
4632
+ async function hostedMintToken(repo) {
4631
4633
  if (!process.env.BIVY_HOSTED_MINT || !sessionAdvertiseTarget)
4632
4634
  return undefined;
4635
+ const cacheKey = repo ?? "";
4633
4636
  const now = Date.now();
4634
- if (hostedMintCache && hostedMintCache.expiresAt - now > 5 * 60 * 1000)
4635
- return hostedMintCache.token;
4637
+ const cached = hostedMintCache.get(cacheKey);
4638
+ if (cached && cached.expiresAt - now > 5 * 60 * 1000)
4639
+ return cached.token;
4636
4640
  try {
4637
4641
  const res = await fetch(`${sessionAdvertiseTarget.controlPlaneUrl.replace(/\/$/, "")}/node/hosted-git-credential`, {
4638
4642
  method: "POST",
4639
- headers: { authorization: `Bearer ${sessionAdvertiseTarget.enrollmentToken}` },
4643
+ headers: { authorization: `Bearer ${sessionAdvertiseTarget.enrollmentToken}`, "content-type": "application/json" },
4644
+ body: JSON.stringify(repo ? { repo } : {}),
4640
4645
  });
4641
4646
  if (!res.ok)
4642
4647
  return undefined;
@@ -4644,7 +4649,7 @@ async function hostedMintToken() {
4644
4649
  if (!data.token)
4645
4650
  return undefined;
4646
4651
  const parsed = data.expiresAt ? Date.parse(data.expiresAt) : NaN;
4647
- hostedMintCache = { token: data.token, expiresAt: Number.isFinite(parsed) ? parsed : now + 55 * 60 * 1000 };
4652
+ hostedMintCache.set(cacheKey, { token: data.token, expiresAt: Number.isFinite(parsed) ? parsed : now + 55 * 60 * 1000 });
4648
4653
  return data.token;
4649
4654
  }
4650
4655
  catch {
@@ -4668,7 +4673,7 @@ async function resolveTokenForWorkItem(item) {
4668
4673
  }
4669
4674
  }
4670
4675
  }
4671
- return (await resolveGitHubToken()) ?? (await hostedMintToken());
4676
+ return (await resolveGitHubToken()) ?? (await hostedMintToken(item.repo));
4672
4677
  }
4673
4678
  /**
4674
4679
  * The token for interactive repo operations (clone/fetch/push/PR) on `owner/repo`.
@@ -4716,7 +4721,7 @@ async function resolveTokenForRepo(owner, repo) {
4716
4721
  }
4717
4722
  }
4718
4723
  }
4719
- return (await resolveGitHubToken()) ?? (await hostedMintToken());
4724
+ return (await resolveGitHubToken()) ?? (await hostedMintToken(`${owner}/${repo}`));
4720
4725
  }
4721
4726
  /** The session source a Linear-issue pickup advertises, keyed by the issue's
4722
4727
  * provider-native id so the control plane can correlate a re-dispatch to it
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bivy/bivy",
3
- "version": "0.12.0-staging.405",
3
+ "version": "0.12.0-staging.406",
4
4
  "type": "module",
5
5
  "license": "AGPL-3.0-only",
6
6
  "description": "Run coding agents on machines you own. Open-source, self-hostable agent workspace.",