@atolis-hq/wake 0.3.74 → 0.3.75

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.
@@ -108,4 +108,4 @@ export function resolveWakeVersion(options = {}) {
108
108
  return `g${headHash.slice(0, 7)}`;
109
109
  return '0.1.0-dev';
110
110
  }
111
- export const wakeVersion = "gb6b6a2c";
111
+ export const wakeVersion = "g370f0e6";
@@ -1,4 +1,5 @@
1
1
  const defaultMaximumGitHubResponseBytes = 8 * 1024 * 1024;
2
+ const defaultGitHubRequestTimeoutMs = 30_000;
2
3
  export class GitHubResponseTooLargeError extends Error {
3
4
  maximumBytes;
4
5
  observedBytes;
@@ -9,9 +10,39 @@ export class GitHubResponseTooLargeError extends Error {
9
10
  this.name = 'GitHubResponseTooLargeError';
10
11
  }
11
12
  }
12
- export function createBoundedGitHubFetch(baseFetch = globalThis.fetch, maximumResponseBytes = defaultMaximumGitHubResponseBytes) {
13
+ // Neither Octokit nor the underlying fetch implementation bounds how long a
14
+ // single request may hang: a connection that never responds (rather than
15
+ // returning a clean error status) blocks forever. Every caller of the GitHub
16
+ // client boundary — reads and mutations alike — currently awaits that call
17
+ // inline within the runner's single serialized tick, so one hung request
18
+ // stalls Advancement for every other, unrelated work item too.
19
+ export class GitHubRequestTimeoutError extends Error {
20
+ timeoutMs;
21
+ constructor(timeoutMs) {
22
+ super(`GitHub request did not complete within ${timeoutMs}ms`);
23
+ this.timeoutMs = timeoutMs;
24
+ this.name = 'GitHubRequestTimeoutError';
25
+ }
26
+ }
27
+ export function createBoundedGitHubFetch(baseFetch = globalThis.fetch, maximumResponseBytes = defaultMaximumGitHubResponseBytes, timeoutMs = defaultGitHubRequestTimeoutMs) {
13
28
  return async (input, init) => {
14
- const response = await baseFetch(input, init);
29
+ const timeoutController = new AbortController();
30
+ const timer = setTimeout(() => timeoutController.abort(), timeoutMs);
31
+ const signal = init?.signal
32
+ ? AbortSignal.any([init.signal, timeoutController.signal])
33
+ : timeoutController.signal;
34
+ let response;
35
+ try {
36
+ response = await baseFetch(input, { ...init, signal });
37
+ }
38
+ catch (error) {
39
+ if (timeoutController.signal.aborted)
40
+ throw new GitHubRequestTimeoutError(timeoutMs);
41
+ throw error;
42
+ }
43
+ finally {
44
+ clearTimeout(timer);
45
+ }
15
46
  const declaredBytes = contentLength(response);
16
47
  if (declaredBytes !== undefined && declaredBytes > maximumResponseBytes) {
17
48
  await response.body?.cancel();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atolis-hq/wake",
3
- "version": "0.3.74",
3
+ "version": "0.3.75",
4
4
  "description": "Local autonomous agent control plane for software development",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {