@bivy/bivy 0.5.1-staging.64 → 0.5.1-staging.65

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 +31 -3
  2. package/package.json +1 -1
package/dist/server.js CHANGED
@@ -409,13 +409,14 @@ const approvals = new ApprovalManager();
409
409
  const questionManager = new QuestionManager();
410
410
  questionManager.onRequest((request) => {
411
411
  scheduleAdvertise();
412
- broadcast({ type: "session.question", sessionId: request.sessionId, requestId: request.id, questions: request.questions });
412
+ broadcast({ type: "session.question", sessionId: request.sessionId, requestId: request.id, questions: request.questions, createdAt: request.createdAt });
413
413
  // Notify unconditionally: a clarifying question always fires mid-turn (the
414
414
  // session is "working"), and it's a hard blocker the user must see to unblock
415
415
  // — matching the pre-refactor behavior.
416
416
  void sendNotificationHint({
417
417
  kind: "question_asked",
418
418
  sessionId: request.sessionId,
419
+ attentionId: request.id,
419
420
  title: "Bivy needs your input",
420
421
  body: `${sessionNotifyLabel(resolveSession(request.sessionId))} is asking a question — tap to answer.`,
421
422
  });
@@ -4320,16 +4321,37 @@ async function advertiseSessions() {
4320
4321
  // dropped; and with the remote flag off the map is empty, so the payload is
4321
4322
  // byte-identical to before.
4322
4323
  const agentServiceAddress = sessionAgentServiceAddress(record) ?? (record ? undefined : (await inMemorySessionLocations.lookup(s.id).catch(() => undefined))?.agentServiceAddress);
4324
+ const approvalAttention = approvals.list()
4325
+ .filter((a) => a.sessionId === s.id && a.status === "pending")
4326
+ .map((a) => ({
4327
+ id: a.id,
4328
+ kind: "approval",
4329
+ severity: a.risk === "critical" ? "critical" : a.risk === "high" ? "error" : "warning",
4330
+ createdAt: new Date(a.createdAt).toISOString(),
4331
+ }));
4332
+ const questionAttention = questionManager.list()
4333
+ .filter((q) => q.sessionId === s.id && q.status === "pending")
4334
+ .map((q) => ({ id: q.id, kind: "question", severity: "warning", createdAt: new Date(q.createdAt).toISOString() }));
4335
+ const failureAt = record?.lastFailureAt || (meta?.status === "failed" ? Date.parse(meta.updatedAt) : 0);
4336
+ const failureAttention = failureAt
4337
+ ? [{
4338
+ id: "last-failure",
4339
+ kind: (record?.source || meta?.source ? "automation" : "session"),
4340
+ severity: "error",
4341
+ createdAt: new Date(failureAt).toISOString(),
4342
+ }]
4343
+ : [];
4323
4344
  return {
4324
4345
  sessionId: s.id,
4325
- status: pendingApproval ? "needs_action" : (record ? (sessionBusy(record) ? "working" : "idle") : "saved"),
4326
- needsAction: pendingApproval,
4346
+ status: pendingApproval || failureAttention.length ? "needs_action" : (record ? (sessionBusy(record) ? "working" : "idle") : "saved"),
4347
+ needsAction: pendingApproval || failureAttention.length > 0,
4327
4348
  source: record?.source || meta?.source,
4328
4349
  titleEnc: name ? relay.sealString(name) : undefined,
4329
4350
  branch: record?.worktree?.branch || meta?.branch,
4330
4351
  agentServiceAddress,
4331
4352
  githubIssueUrl: record?.githubIssueUrl,
4332
4353
  prUrl: record?.prUrl,
4354
+ attention: [...approvalAttention, ...questionAttention, ...failureAttention],
4333
4355
  };
4334
4356
  }));
4335
4357
  try {
@@ -6612,6 +6634,8 @@ function markSessionWorking(record, activity) {
6612
6634
  record.isWorking = true;
6613
6635
  record.lastActivity = activity;
6614
6636
  record.workingStartedAt ||= Date.now();
6637
+ // A new attempt resolves the prior turn's failure condition at its source.
6638
+ record.lastFailureAt = undefined;
6615
6639
  metadata.touchSession(record.id, "working");
6616
6640
  if (!wasWorking)
6617
6641
  scheduleAdvertise(); // idle → working transition
@@ -6823,6 +6847,9 @@ function attachSessionListeners(record) {
6823
6847
  });
6824
6848
  }
6825
6849
  else if (turnError) {
6850
+ record.lastFailureAt = Date.now();
6851
+ metadata.touchSession(record.id, "failed");
6852
+ scheduleAdvertise();
6826
6853
  broadcast({ type: "session.error", sessionId: record.id, error: turnError });
6827
6854
  void sendNotificationHint({
6828
6855
  kind: "session_error",
@@ -7983,6 +8010,7 @@ approvals.onRequest((request) => {
7983
8010
  void sendNotificationHint({
7984
8011
  kind: "approval_requested",
7985
8012
  sessionId: request.sessionId,
8013
+ attentionId: request.id,
7986
8014
  title: "Approval needed",
7987
8015
  body: `${sessionNotifyLabel(rec)} wants to run something — tap to approve or deny.`,
7988
8016
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bivy/bivy",
3
- "version": "0.5.1-staging.64",
3
+ "version": "0.5.1-staging.65",
4
4
  "type": "module",
5
5
  "license": "FSL-1.1-ALv2",
6
6
  "description": "Run coding agents on machines you own. Source-available, self-hostable agent workspace.",