@bivy/bivy 0.18.6 → 0.18.7-staging.2

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.
@@ -208,8 +208,10 @@ export class AppRegistry extends EventEmitter {
208
208
  this.views.set(entry.view.id, entry);
209
209
  this.persisted.set(app.id, { sessionId, workspace, manifest: structuredClone(input), id: app.id, viewIds: app.views.map((v) => v.id), createdAt: app.createdAt, ...(app.reviewMode ? { reviewMode: app.reviewMode } : {}), ...(app.agentNotes ? { agentNotes: true } : {}) });
210
210
  this.persistNotes(app.id);
211
- if (!restore)
211
+ if (!restore) {
212
212
  this.save();
213
+ this.emit("published", app.id);
214
+ }
213
215
  return structuredClone(app);
214
216
  }
215
217
  list(sessionId) {
@@ -78,14 +78,29 @@ export class NodeCredentialResolver {
78
78
  // under the store lock).
79
79
  let token = typeof cred.access === "string" ? cred.access : "";
80
80
  const expires = Number(cred.expires) || 0;
81
- if (!token || expires <= Date.now() + OAUTH_REFRESH_SKEW_MS || context?.rejectedToken === token) {
81
+ // Spent: the provider already refused this exact token, or its lifetime is
82
+ // over. A token merely inside the refresh skew is still live — that case
83
+ // refreshes early but may keep the current token if the refresh fails.
84
+ // An unknown expiry (0) is never assumed spent.
85
+ const spent = !token || context?.rejectedToken === token || (expires > 0 && expires <= Date.now());
86
+ if (spent || expires <= Date.now() + OAUTH_REFRESH_SKEW_MS) {
82
87
  // Refresh the SELECTED record (its label), not just the provider default —
83
88
  // so a second account on the same provider is left untouched. A provider
84
89
  // 401 forces refresh even before expiry; the rejected-token guard is
85
90
  // re-checked under the OAuth store lock to avoid duplicate rotations.
86
91
  const refreshed = await this.oauth.refresh(id, selection.record.label, context?.rejectedToken).catch(() => undefined);
87
- if (refreshed)
92
+ if (refreshed && refreshed !== token)
88
93
  token = refreshed;
94
+ // The refresh failed (commonly: the provider's own CLI rotated the refresh
95
+ // token out from under this copy) and what we hold is spent. Report NO
96
+ // credential rather than handing the agent a token that cannot work:
97
+ // Bivy's env var outranks the agent's own login, so returning it shadows a
98
+ // perfectly good `claude`/`codex` CLI session on this machine with a dead
99
+ // one — the "it ignored my local credentials" failure. With none, the
100
+ // agent falls back to that login, and an agent with no login of its own
101
+ // gets the vault's actionable "no credential" message instead of a 401.
102
+ else if (spent)
103
+ return undefined;
89
104
  }
90
105
  if (!token)
91
106
  return undefined;
package/dist/server.js CHANGED
@@ -1938,6 +1938,8 @@ const appService = new AppService(appRegistry, appGateway ?? remotePreview, {
1938
1938
  // the owner gets one push per burst of notes on a view ("2 notes on
1939
1939
  // Storefront"), which opens the Apps sheet at that app. Counts, names and IDs
1940
1940
  // only: the note text never goes through push.
1941
+ // The session advert carries published app IDs (operator reporting only).
1942
+ appRegistry.on("published", () => scheduleAdvertise());
1941
1943
  const NOTES_NOTIFY_MS = 20_000;
1942
1944
  const noteBursts = new Map();
1943
1945
  appRegistry.on("notes", (viewId) => {
@@ -4169,7 +4171,7 @@ async function advertiseSessions() {
4169
4171
  await fetch(`${sessionAdvertiseTarget.controlPlaneUrl.replace(/\/$/, "")}/node/sessions`, {
4170
4172
  method: "POST",
4171
4173
  headers: { "content-type": "application/json", authorization: `Bearer ${sessionAdvertiseTarget.enrollmentToken}` },
4172
- body: JSON.stringify({ sessions }),
4174
+ body: JSON.stringify({ sessions, apps: appRegistry.list().map((app) => app.id) }),
4173
4175
  });
4174
4176
  }
4175
4177
  catch {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bivy/bivy",
3
- "version": "0.18.6",
3
+ "version": "0.18.7-staging.2",
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.",