@bill10/agent-007 0.12.2001 → 0.12.2002

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/VERSION CHANGED
@@ -1 +1 @@
1
- 0.12.2.1
1
+ 0.12.2.2
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bill10/agent-007",
3
- "version": "0.12.2001",
3
+ "version": "0.12.2002",
4
4
  "description": "From web terminals for your coding agents to a self-running agent company: Claude Code and Codex in parallel git worktrees, a job board they pick work from, and one agent that runs the board from a goal.",
5
5
  "license": "MIT",
6
6
  "repository": {
package/server/owner.js CHANGED
@@ -59,11 +59,17 @@ async function call(method, params, { env = process.env, signal } = {}) {
59
59
  ...(form ? { body: params } : { headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(params) }),
60
60
  signal,
61
61
  });
62
- body = await res.json().catch(() => ({ ok: false, description: `HTTP ${res.status}` }));
62
+ body = await res.json().catch(() => ({ ok: false, error_code: res.status, description: `HTTP ${res.status}` }));
63
63
  } catch (err) {
64
- throw new Error(redact(err.cause?.message || err.message, env));
64
+ // reason: a short label for the poll loop's offline line.
65
+ const reason = /ENOTFOUND|EAI_AGAIN/.test(err.cause?.code) ? 'DNS'
66
+ : err.name === 'TimeoutError' || /timeout/i.test(err.message) ? 'timeout' : 'no network';
67
+ throw Object.assign(new Error(redact(err.cause?.message || err.message, env)), { reason });
68
+ }
69
+ if (!body?.ok) {
70
+ const status = body?.error_code;
71
+ throw Object.assign(new Error(redact(body?.description || 'Telegram said no', env)), { status, reason: status ? `HTTP ${status}` : 'Telegram said no' });
65
72
  }
66
- if (!body?.ok) throw new Error(redact(body?.description || 'Telegram said no', env));
67
73
  return body.result;
68
74
  }
69
75
 
@@ -414,6 +420,16 @@ export async function pollOnce(offset, { broadcast, env = process.env, signal }
414
420
 
415
421
  let stopper = null;
416
422
 
423
+ // Failures that retrying will not fix, and what the owner should do about them.
424
+ const POLL_HINTS = {
425
+ 401: 'the bot token is wrong or revoked',
426
+ 409: 'another process is polling this bot',
427
+ };
428
+ const OFFLINE_AFTER_MS = 60 * 1000;
429
+ const OFFLINE_AFTER_FAILURES = 3;
430
+
431
+ const since = ms => ms < 120e3 ? `${Math.round(ms / 1000)}s` : `${Math.round(ms / 60e3)}m`;
432
+
417
433
  const pause = (ms, signal) => new Promise(resolve => {
418
434
  const timer = setTimeout(resolve, ms);
419
435
  signal.addEventListener('abort', () => { clearTimeout(timer); resolve(); }, { once: true });
@@ -432,13 +448,27 @@ export function startTelegram({ broadcast, env = process.env } = {}) {
432
448
  (async () => {
433
449
  let offset = 0;
434
450
  let backoff = 1000;
451
+ // Sleep, wake and network changes fail a poll or two; log only going
452
+ // offline and coming back, not every retry.
453
+ let failures = 0, failingSince = 0, offline = false;
435
454
  while (!controller.signal.aborted) {
436
455
  try {
437
456
  offset = await pollOnce(offset, { broadcast, env, signal: controller.signal });
457
+ if (offline) console.log(`Telegram: back online after ${since(Date.now() - failingSince)}`);
458
+ failures = 0;
459
+ offline = false;
438
460
  backoff = 1000;
439
461
  } catch (err) {
440
462
  if (controller.signal.aborted) break;
441
- console.error(`Telegram: getUpdates failed (${err.message}); retrying in ${backoff / 1000}s`);
463
+ if (!failures++) failingSince = Date.now();
464
+ const hint = POLL_HINTS[err.status];
465
+ // A hint logs even mid-outage: a token revoked while offline still needs saying.
466
+ if (hint ? offline !== hint : !offline && (failures >= OFFLINE_AFTER_FAILURES || Date.now() - failingSince > OFFLINE_AFTER_MS)) {
467
+ offline = hint || true;
468
+ console.error(hint
469
+ ? `Telegram: getUpdates failed (${err.message}): ${hint}; retrying quietly`
470
+ : `Telegram: offline (${err.reason || 'no network'}), retrying quietly`);
471
+ }
442
472
  await pause(backoff, controller.signal);
443
473
  backoff = Math.min(backoff * 2, MAX_BACKOFF_MS);
444
474
  }