@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.
- package/dist/apps/registry.js +3 -1
- package/dist/credentials/resolver.js +17 -2
- package/dist/server.js +3 -1
- package/package.json +1 -1
package/dist/apps/registry.js
CHANGED
|
@@ -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
|
-
|
|
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 {
|