@inerrata-corporation/errata 2.0.6-dev.2115 → 2.0.6-dev.2138

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/errata.mjs +50 -4
  2. package/package.json +1 -1
package/errata.mjs CHANGED
@@ -77056,7 +77056,7 @@ function createWatchBreaker(deps) {
77056
77056
  }
77057
77057
 
77058
77058
  // src/engine.ts
77059
- var DAEMON_VERSION = true ? "2.0.6-dev.2115" : "2.0.0-alpha.0";
77059
+ var DAEMON_VERSION = true ? "2.0.6-dev.2138" : "2.0.0-alpha.0";
77060
77060
  var IGNORED_PATH = /[\\/](?:\.git|node_modules|\.errata|\.claude|\.codex|\.cursor|\.turbo|\.next|dist|coverage|test-results|playwright-report|__pycache__)(?:[\\/]|$)/;
77061
77061
  var IGNORED_NOISE = /castalia\.db|eventlog\.sqlite|turn-cursors/;
77062
77062
  var GIT_OP_MUTE_MS = 4e3;
@@ -82572,6 +82572,28 @@ import { execFileSync as execFileSync4 } from "node:child_process";
82572
82572
  import { existsSync as existsSync29, writeFileSync as writeFileSync22 } from "node:fs";
82573
82573
  import { join as join34 } from "node:path";
82574
82574
 
82575
+ // src/device-poll.ts
82576
+ var THROTTLED_POLL_MIN_WAIT_MS = 11e3;
82577
+ var THROTTLED_INTERVAL_CAP_MS = 6e4;
82578
+ function throttledPoll(res, intervalMs) {
82579
+ if (res.status !== 429 && res.status !== 503) return null;
82580
+ const next = Math.max(intervalMs, Math.min(intervalMs + 5e3, THROTTLED_INTERVAL_CAP_MS));
82581
+ return {
82582
+ intervalMs: next,
82583
+ waitMs: Math.max(next, retryAfterMs(res.headers) ?? 0, THROTTLED_POLL_MIN_WAIT_MS)
82584
+ };
82585
+ }
82586
+ function retryAfterMs(headers, now = Date.now()) {
82587
+ for (const name2 of ["retry-after", "x-retry-after"]) {
82588
+ const raw2 = headers.get(name2)?.trim();
82589
+ if (!raw2) continue;
82590
+ if (/^\d+$/.test(raw2)) return Number(raw2) * 1e3;
82591
+ const at = Date.parse(raw2);
82592
+ if (!Number.isNaN(at)) return Math.max(0, at - now);
82593
+ }
82594
+ return null;
82595
+ }
82596
+
82575
82597
  // src/oauth-login.ts
82576
82598
  init_src7();
82577
82599
  init_cloud_auth();
@@ -82626,10 +82648,12 @@ async function loginOAuthDevice(opts) {
82626
82648
  });
82627
82649
  const deadline = Date.now() + Math.min(code.expires_in * 1e3, opts.timeoutMs ?? Number.POSITIVE_INFINITY);
82628
82650
  let intervalMs = Math.max(2, code.interval ?? 5) * 1e3;
82651
+ let waitMs = intervalMs;
82629
82652
  let deviceSession = null;
82630
82653
  let approvedInstallation = null;
82631
82654
  while (Date.now() < deadline) {
82632
- await (opts.sleep ?? ((ms) => new Promise((resolve7) => setTimeout(resolve7, ms))))(intervalMs);
82655
+ await (opts.sleep ?? ((ms) => new Promise((resolve7) => setTimeout(resolve7, ms))))(waitMs);
82656
+ waitMs = intervalMs;
82633
82657
  const poll = await fetchFn(device.token, {
82634
82658
  method: "POST",
82635
82659
  headers: { "content-type": "application/json", accept: "application/json" },
@@ -82641,10 +82665,16 @@ async function loginOAuthDevice(opts) {
82641
82665
  });
82642
82666
  const payload = await poll.json().catch(() => null);
82643
82667
  if (!poll.ok) {
82668
+ const throttle = throttledPoll(poll, intervalMs);
82669
+ if (throttle) {
82670
+ ({ intervalMs, waitMs } = throttle);
82671
+ continue;
82672
+ }
82644
82673
  const error48 = typeof payload?.["error"] === "string" ? payload["error"] : "device_poll_failed";
82645
82674
  if (error48 === "authorization_pending") continue;
82646
82675
  if (error48 === "slow_down") {
82647
82676
  intervalMs += 5e3;
82677
+ waitMs = intervalMs;
82648
82678
  continue;
82649
82679
  }
82650
82680
  throw new Error(`device authorization failed: ${error48}`);
@@ -82855,9 +82885,11 @@ async function linkThroughConsole(opts) {
82855
82885
  });
82856
82886
  const deadline = Date.now() + Math.min(code.expires_in * 1e3, opts.timeoutMs ?? Number.POSITIVE_INFINITY);
82857
82887
  let intervalMs = Math.max(2, code.interval ?? 5) * 1e3;
82888
+ let waitMs = intervalMs;
82858
82889
  const sleep = opts.sleep ?? ((ms) => new Promise((resolve7) => setTimeout(resolve7, ms)));
82859
82890
  while (Date.now() < deadline) {
82860
- await sleep(intervalMs);
82891
+ await sleep(waitMs);
82892
+ waitMs = intervalMs;
82861
82893
  const poll = await fetchFn(device.token, {
82862
82894
  method: "POST",
82863
82895
  headers: { "content-type": "application/json", accept: "application/json" },
@@ -82869,10 +82901,16 @@ async function linkThroughConsole(opts) {
82869
82901
  });
82870
82902
  const payload = await poll.json().catch(() => null);
82871
82903
  if (!poll.ok) {
82904
+ const throttle = throttledPoll(poll, intervalMs);
82905
+ if (throttle) {
82906
+ ({ intervalMs, waitMs } = throttle);
82907
+ continue;
82908
+ }
82872
82909
  const error48 = typeof payload?.["error"] === "string" ? payload["error"] : "device_poll_failed";
82873
82910
  if (error48 === "authorization_pending") continue;
82874
82911
  if (error48 === "slow_down") {
82875
82912
  intervalMs += 5e3;
82913
+ waitMs = intervalMs;
82876
82914
  continue;
82877
82915
  }
82878
82916
  if (error48 === "access_denied") return { status: "denied" };
@@ -84898,9 +84936,11 @@ async function requestDeviceAuthorization(fetchFn, deviceEndpoint, p) {
84898
84936
  async function pollDeviceApproval(fetchFn, deviceEndpoint, p, sleep = (ms) => new Promise((r) => setTimeout(r, ms))) {
84899
84937
  const deadline = Date.now() + p.timeoutMs;
84900
84938
  let intervalMs = Math.max(1, p.intervalSeconds) * 1e3;
84939
+ let waitMs = intervalMs;
84901
84940
  for (; ; ) {
84902
84941
  if (Date.now() >= deadline) throw new Error("device approval timed out \u2014 run `errata login` again");
84903
- await sleep(intervalMs);
84942
+ await sleep(waitMs);
84943
+ waitMs = intervalMs;
84904
84944
  const res = await fetchFn(`${strip2(deviceEndpoint)}/token`, {
84905
84945
  method: "POST",
84906
84946
  headers: { "content-type": "application/json", accept: "application/json" },
@@ -84912,9 +84952,15 @@ async function pollDeviceApproval(fetchFn, deviceEndpoint, p, sleep = (ms) => ne
84912
84952
  });
84913
84953
  const j = await res.json().catch(() => ({}));
84914
84954
  if (res.ok && j.access_token) return j.access_token;
84955
+ const throttle = throttledPoll(res, intervalMs);
84956
+ if (throttle) {
84957
+ ({ intervalMs, waitMs } = throttle);
84958
+ continue;
84959
+ }
84915
84960
  if (j.error === "authorization_pending") continue;
84916
84961
  if (j.error === "slow_down") {
84917
84962
  intervalMs += 5e3;
84963
+ waitMs = intervalMs;
84918
84964
  continue;
84919
84965
  }
84920
84966
  throw new Error(`device approval failed: ${j.error ?? `HTTP ${res.status}`}`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@inerrata-corporation/errata",
3
- "version": "2.0.6-dev.2115",
3
+ "version": "2.0.6-dev.2138",
4
4
  "description": "errata - local-first observation engine for AI coding agents",
5
5
  "type": "module",
6
6
  "bin": {