@bridge4dev/runner 0.50.0 → 0.51.0

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/index.js CHANGED
@@ -465,6 +465,12 @@ function runnerCapabilities(apiUrlOverride) {
465
465
  ? ['verify_start', 'verify_status', 'verify_cancel', 'preview_checkout', 'preview_stop']
466
466
  : []),
467
467
  ...(agentInstallEnabled ? ['agent_install'] : []),
468
+ // «Перемерить версии агентов сейчас» — единственный путь, которым машину
469
+ // можно СПРОСИТЬ про версии; всё остальное она присылает сама и по своему
470
+ // расписанию. Объявлено отдельно от `agent_install` и БЕЗ его условия:
471
+ // это чтение, а не установка, и машину, чей владелец запретил ставить из
472
+ // дашборда, спросить о том, что на ней стоит, по-прежнему можно.
473
+ 'agent_versions_refresh',
468
474
  ],
469
475
  };
470
476
  }
@@ -244,7 +244,17 @@ export declare class Supervisor {
244
244
  agent: string;
245
245
  from: string | null;
246
246
  to: string;
247
- }): Promise<void>;
247
+ },
248
+ /**
249
+ * Force a fresh probe on a path the reason alone does not describe.
250
+ *
251
+ * «Перемерить сейчас» sends `measured` — it IS a plain measurement — but it
252
+ * is also the one caller that must not be answered out of the hour-long
253
+ * cache, because a person pressed a button precisely to get past it.
254
+ */
255
+ options?: {
256
+ force?: boolean;
257
+ }): Promise<AgentVersionsMeasurement | null>;
248
258
  private queueVersionChange;
249
259
  /**
250
260
  * Р13: the agent of a starting session, moved forward in the background.
@@ -259,14 +259,22 @@ export class Supervisor {
259
259
  * missing audit lines are not the problem worth solving.
260
260
  */
261
261
  static MAX_PENDING_VERSION_CHANGES = 8;
262
- async publishAgentVersions(reason, changed) {
262
+ async publishAgentVersions(reason, changed,
263
+ /**
264
+ * Force a fresh probe on a path the reason alone does not describe.
265
+ *
266
+ * «Перемерить сейчас» sends `measured` — it IS a plain measurement — but it
267
+ * is also the one caller that must not be answered out of the hour-long
268
+ * cache, because a person pressed a button precisely to get past it.
269
+ */
270
+ options) {
263
271
  try {
264
272
  const measure = this.opts.measureAgentVersions ?? measureAgentVersions;
265
273
  // After an install — ours or the auto one — the cached number is a lie,
266
274
  // and a stale `at` with it would be dropped by the API's ordering guard
267
275
  // together with the audit line the install owes. Forcing it here means a
268
276
  // caller cannot forget to invalidate the cache first.
269
- const measurement = await measure({ force: reason !== 'measured' });
277
+ const measurement = await measure({ force: options?.force ?? reason !== 'measured' });
270
278
  // A plain tick carries an earlier install's news rather than replacing it.
271
279
  // The API keys the audit line by the measurement's `at`, so the same
272
280
  // change arriving under a later `at` is one line, not two.
@@ -294,11 +302,15 @@ export class Supervisor {
294
302
  void this.publishAgentVersions('measured');
295
303
  }
296
304
  }
305
+ // Handed back so a caller can answer with EXACTLY what was published,
306
+ // rather than measuring a second time and hoping the two agree.
307
+ return measurement;
297
308
  }
298
309
  catch (error) {
299
310
  if (changed && reason !== 'measured')
300
311
  this.queueVersionChange({ reason, changed });
301
312
  log.warn('supervisor: could not report agent versions', { error: String(error) });
313
+ return null;
302
314
  }
303
315
  }
304
316
  queueVersionChange(entry) {
@@ -5119,6 +5131,43 @@ export class Supervisor {
5119
5131
  void this.publishAgentVersions('manual', moved);
5120
5132
  return;
5121
5133
  }
5134
+ /**
5135
+ * «Перемерить версии агентов прямо сейчас» — за кнопкой «Check again».
5136
+ *
5137
+ * Единственный путь, которым машину можно СПРОСИТЬ про версии. Всё
5138
+ * остальное присылает она сама и по своему расписанию: кадр уходит на
5139
+ * каждом переподключении (из кэша), раз в час по таймеру, и свежий —
5140
+ * только после установки, которую сделал сам DevBridge.
5141
+ *
5142
+ * Отсюда и дыра, которую эта команда закрывает: человек обновил агента
5143
+ * руками через `claude update` на машине, раннеру об этом никто не
5144
+ * сказал, и карточка держала старое число до часа. «Новая сессия
5145
+ * чинила» его побочным эффектом — автообновление шло ставить, честно
5146
+ * мерило перед установкой и сбрасывало кэш, — а на машине с
5147
+ * ВЫКЛЮЧЕННЫМ автообновлением не происходило и этого.
5148
+ *
5149
+ * Меряем один раз и отдаём измеренное в ответе, а не только кадром:
5150
+ * кадр и ответ идут по одному сокету, но обрабатываются на той стороне
5151
+ * независимо, и запрос, который вернулся раньше, чем доехала запись,
5152
+ * оставил бы на экране ровно то устаревшее число, ради которого кнопку
5153
+ * и нажали. Кадр при этом всё равно уходит — у него свой путь с
5154
+ * аудитом, и повторная запись с тем же `at` отбрасывается сторожем
5155
+ * порядка на стороне API.
5156
+ */
5157
+ case 'agent_versions_refresh': {
5158
+ // Один замер на нажатие, и это структура, а не совпадение: публикация
5159
+ // отдаёт то, что измерила, и ответ собирается из НЕГО. Мерить второй
5160
+ // раз «для ответа» значило бы держаться за кэш, который вызывающий не
5161
+ // видит, — а кэш здесь и есть то, мимо чего нажимают кнопку.
5162
+ const snapshot = await this.publishAgentVersions('measured', undefined, { force: true });
5163
+ if (!snapshot) {
5164
+ return void reply({ ok: false, error: 'Could not measure the agents' });
5165
+ }
5166
+ return void reply({
5167
+ ok: true,
5168
+ result: { at: snapshot.at, reason: 'measured', agents: snapshot.agents },
5169
+ });
5170
+ }
5122
5171
  /**
5123
5172
  * «Would this file reach the agent, and how big is it» (ticket #192).
5124
5173
  *
package/dist/version.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- export declare const RUNNER_VERSION = "0.50.0";
1
+ export declare const RUNNER_VERSION = "0.51.0";
2
2
  //# sourceMappingURL=version.d.ts.map
package/dist/version.js CHANGED
@@ -1,3 +1,3 @@
1
1
  // Kept in sync with package.json by the release script (manual for now).
2
- export const RUNNER_VERSION = '0.50.0';
2
+ export const RUNNER_VERSION = '0.51.0';
3
3
  //# sourceMappingURL=version.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bridge4dev/runner",
3
- "version": "0.50.0",
3
+ "version": "0.51.0",
4
4
  "description": "DevBridge dev runner — connects a dev server to DevBridge and runs agent sessions (Claude Code / Codex)",
5
5
  "homepage": "https://bridge4.dev",
6
6
  "license": "MIT",