@atolis-hq/wake 0.3.57 → 0.3.59

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.
@@ -33,6 +33,8 @@ execution:
33
33
  standard: [fake]
34
34
  deep: [fake]
35
35
  defaultRunnerPool: standard
36
+ # A resumed agent session must have complete durable usage under this limit.
37
+ maxResumableSessionTokens: 200000
36
38
 
37
39
  # Tick dispatch cap and resident-loop idle backoff; the built-in defaults
38
40
  # are fine for a first run.
@@ -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 = "g17796f1";
111
+ export const wakeVersion = "g58abde5";
@@ -39,7 +39,7 @@ async function attemptExecution(runtime, activation, context) {
39
39
  stage: activation.stage,
40
40
  ...(context.sessionPolicy === undefined ? {} : { policy: context.sessionPolicy }),
41
41
  };
42
- const resume = resumeContextFor(resumeCandidates, runner, resumeScope);
42
+ const resume = resumeContextFor(resumeCandidates, runner, resumeScope, runtime.config.maxResumableSessionTokens ?? 200_000);
43
43
  const existing = existingRun(prior, runtime.dependencies.clock, owner);
44
44
  if (existing !== undefined)
45
45
  return existing;
@@ -233,19 +233,22 @@ async function releasePreStartResources(runtime, activation, currentRunId, lease
233
233
  export function resumeSessionIdFor(prior, cli, scope, runnerName) {
234
234
  return resumeRunFor(prior, cli, runnerName, scope)?.agent?.metadata.sessionId;
235
235
  }
236
- function resumeContextFor(candidates, runner, scope) {
236
+ function resumeContextFor(candidates, runner, scope, maximumTokens = 200_000) {
237
237
  if (runner.supportsSessionResume !== true)
238
238
  return {};
239
239
  const resumedRun = resumeRunFor(candidates, runner.cli, runner.name, scope);
240
240
  const sessionId = resumedRun?.agent?.metadata.sessionId;
241
+ const usageBaseline = sessionId === undefined
242
+ ? undefined
243
+ : usageBaselineFor(candidates, runner.cli, sessionId, scope, runner.name);
244
+ if (sessionId === undefined ||
245
+ usageBaseline === undefined ||
246
+ usageBaseline.input + usageBaseline.output > maximumTokens)
247
+ return {};
241
248
  return {
242
- ...(sessionId === undefined ? {} : { sessionId }),
249
+ sessionId,
243
250
  ...(resumedRun?.startedAt === undefined ? {} : { startedAt: resumedRun.startedAt }),
244
- ...(sessionId === undefined
245
- ? {}
246
- : {
247
- usageBaseline: usageBaselineFor(candidates, runner.cli, sessionId, scope, runner.name),
248
- }),
251
+ usageBaseline,
249
252
  };
250
253
  }
251
254
  function resumeRunFor(prior, cli, runnerName, scope) {
@@ -31,5 +31,6 @@ export const executionConfigSchema = z
31
31
  leaseDurationMs: z.number().int().positive().optional(),
32
32
  leaseRenewalIntervalMs: z.number().int().positive().optional(),
33
33
  maxAmbiguityReconciliationAttempts: z.number().int().positive().optional(),
34
+ maxResumableSessionTokens: z.number().int().positive().default(200_000),
34
35
  })
35
36
  .strict();
@@ -50,15 +50,16 @@ export async function listPullRequests(octokit, cache, owner, repo, maxResults)
50
50
  });
51
51
  return pullRequests.map(normalizePullRequestState);
52
52
  }
53
- export async function listReviews(octokit, cache, owner, repo, pullNumber, pageSize) {
53
+ export async function listReviews(octokit, cache, owner, repo, pullNumber, options) {
54
54
  const reviews = await fetchPaginatedWithEtag({
55
55
  cache,
56
56
  key: `reviews:${owner}/${repo}#${pullNumber}`,
57
+ ...(options.maxResults === undefined ? {} : { maxResults: options.maxResults }),
57
58
  pages: (headers) => octokit.paginate.iterator(octokit.rest.pulls.listReviews, {
58
59
  owner,
59
60
  repo,
60
61
  pull_number: pullNumber,
61
- per_page: pageSize,
62
+ per_page: boundedCommentPageSize(options),
62
63
  ...(headers === undefined ? {} : { headers }),
63
64
  }),
64
65
  });
@@ -71,15 +72,16 @@ export async function listReviews(octokit, cache, owner, repo, pullNumber, pageS
71
72
  ...(review.user === undefined ? {} : { user: review.user }),
72
73
  }));
73
74
  }
74
- export async function listReviewComments(octokit, cache, owner, repo, pullNumber, pageSize) {
75
+ export async function listReviewComments(octokit, cache, owner, repo, pullNumber, options) {
75
76
  const comments = await fetchPaginatedWithEtag({
76
77
  cache,
77
78
  key: `review-comments:${owner}/${repo}#${pullNumber}`,
79
+ ...(options.maxResults === undefined ? {} : { maxResults: options.maxResults }),
78
80
  pages: (headers) => octokit.paginate.iterator(octokit.rest.pulls.listReviewComments, {
79
81
  owner,
80
82
  repo,
81
83
  pull_number: pullNumber,
82
- per_page: Math.min(pageSize, 100),
84
+ per_page: boundedCommentPageSize(options),
83
85
  ...(headers === undefined ? {} : { headers }),
84
86
  }),
85
87
  });
@@ -94,37 +96,40 @@ export async function listReviewComments(octokit, cache, owner, repo, pullNumber
94
96
  ...(comment.side === undefined ? {} : { side: comment.side }),
95
97
  }));
96
98
  }
97
- export async function listPullRequestFiles(octokit, cache, owner, repo, pullNumber) {
99
+ export async function listPullRequestFiles(octokit, cache, owner, repo, pullNumber, maxResults) {
98
100
  const files = await fetchPaginatedWithEtag({
99
101
  cache,
100
102
  key: `pull-files:${owner}/${repo}#${pullNumber}`,
103
+ ...(maxResults === undefined ? {} : { maxResults }),
101
104
  pages: (headers) => octokit.paginate.iterator(octokit.rest.pulls.listFiles, {
102
105
  owner,
103
106
  repo,
104
107
  pull_number: pullNumber,
105
- per_page: 100,
108
+ per_page: boundedPageSize(maxResults),
106
109
  ...(headers === undefined ? {} : { headers }),
107
110
  }),
108
111
  });
109
112
  return files.map((file) => file.filename);
110
113
  }
111
- export function listCheckRunsForRef(octokit, cache, owner, repo, ref) {
114
+ export function listCheckRunsForRef(octokit, cache, owner, repo, ref, maxResults) {
112
115
  return fetchPaginatedWithEtag({
113
116
  cache,
114
117
  key: `check-runs:${owner}/${repo}@${ref}`,
118
+ ...(maxResults === undefined ? {} : { maxResults }),
115
119
  pages: (headers) => octokit.paginate.iterator(octokit.rest.checks.listForRef, {
116
120
  owner,
117
121
  repo,
118
122
  ref,
119
- per_page: 100,
123
+ per_page: boundedPageSize(maxResults),
120
124
  ...(headers === undefined ? {} : { headers }),
121
125
  }),
122
126
  });
123
127
  }
124
- export function getCombinedStatusForRef(octokit, cache, owner, repo, ref) {
128
+ export function getCombinedStatusForRef(octokit, cache, owner, repo, ref, maxResults) {
125
129
  return fetchPaginatedWithEtag({
126
130
  cache,
127
131
  key: `combined-status:${owner}/${repo}@${ref}`,
132
+ ...(maxResults === undefined ? {} : { maxResults }),
128
133
  pages: (headers) => ({
129
134
  async *[Symbol.asyncIterator]() {
130
135
  let page = 1;
@@ -134,14 +139,14 @@ export function getCombinedStatusForRef(octokit, cache, owner, repo, ref) {
134
139
  owner,
135
140
  repo,
136
141
  ref,
137
- per_page: 100,
142
+ per_page: boundedPageSize(maxResults),
138
143
  page,
139
144
  ...(headers === undefined ? {} : { headers }),
140
145
  });
141
146
  const statuses = response.data.statuses;
142
147
  count += statuses.length;
143
148
  yield { data: statuses, headers: response.headers };
144
- if (statuses.length < 100 || count >= response.data.total_count)
149
+ if (statuses.length < boundedPageSize(maxResults) || count >= response.data.total_count)
145
150
  return;
146
151
  page += 1;
147
152
  }
@@ -215,11 +220,12 @@ export async function listIssueComments(octokit, cache, owner, repo, issueNumber
215
220
  const comments = await fetchPaginatedWithEtag({
216
221
  cache,
217
222
  key: `issue-comments:${owner}/${repo}#${issueNumber}:since:${options.since ?? 'bootstrap'}`,
223
+ ...(options.maxResults === undefined ? {} : { maxResults: options.maxResults }),
218
224
  pages: (headers) => octokit.paginate.iterator(octokit.rest.issues.listComments, {
219
225
  owner,
220
226
  repo,
221
227
  issue_number: issueNumber,
222
- per_page: Math.min(options.pageSize, 100),
228
+ per_page: boundedCommentPageSize(options),
223
229
  ...(options.since === undefined ? {} : { since: options.since }),
224
230
  ...(headers === undefined ? {} : { headers }),
225
231
  }),
@@ -232,3 +238,9 @@ export async function listIssueComments(octokit, cache, owner, repo, issueNumber
232
238
  ...(comment.user === undefined ? {} : { user: comment.user }),
233
239
  }));
234
240
  }
241
+ function boundedPageSize(maxResults) {
242
+ return Math.min(maxResults ?? 100, 100);
243
+ }
244
+ function boundedCommentPageSize(options) {
245
+ return Math.min(options.pageSize, boundedPageSize(options.maxResults));
246
+ }
@@ -33,14 +33,8 @@ export function createGitHubClient(token) {
33
33
  });
34
34
  const cache = createEtagCache();
35
35
  return {
36
+ ...createGitHubReadClient(octokit, cache),
36
37
  authenticatedLogin: async () => (await octokit.rest.users.getAuthenticated()).data.login,
37
- listIssues: (owner, repo, maxResults, since) => listIssues(octokit, cache, owner, repo, maxResults, since),
38
- listPullRequests: (owner, repo, maxResults) => listPullRequests(octokit, cache, owner, repo, maxResults),
39
- listIssueComments: (owner, repo, issueNumber, pageSize, since) => listIssueComments(octokit, cache, owner, repo, issueNumber, {
40
- pageSize,
41
- ...(since === undefined ? {} : { since }),
42
- }),
43
- listReviewComments: (owner, repo, pullNumber, pageSize) => listReviewComments(octokit, cache, owner, repo, pullNumber, pageSize),
44
38
  collaboratorPermission: async (owner, repo, login) => {
45
39
  const { data } = await octokit.rest.repos.getCollaboratorPermissionLevel({
46
40
  owner,
@@ -49,7 +43,6 @@ export function createGitHubClient(token) {
49
43
  });
50
44
  return providerPermission(data.permission);
51
45
  },
52
- getIssueLabels: (owner, repo, issueNumber) => getIssueLabels(octokit, cache, owner, repo, issueNumber),
53
46
  getIssueLabelsFresh: async (owner, repo, issueNumber) => {
54
47
  const response = await octokit.rest.issues.get({ owner, repo, issue_number: issueNumber });
55
48
  return response.data.labels.flatMap((label) => typeof label === 'string' ? [label] : label.name === undefined ? [] : [label.name]);
@@ -66,13 +59,32 @@ export function createGitHubClient(token) {
66
59
  labels: [...labels],
67
60
  });
68
61
  },
62
+ deliver: (command) => deliver(octokit, command),
63
+ };
64
+ }
65
+ function createGitHubReadClient(octokit, cache) {
66
+ return {
67
+ listIssues: (owner, repo, maxResults, since) => listIssues(octokit, cache, owner, repo, maxResults, since),
68
+ listPullRequests: (owner, repo, maxResults) => listPullRequests(octokit, cache, owner, repo, maxResults),
69
+ listIssueComments: (owner, repo, issueNumber, pageSize, since, maxResults) => listIssueComments(octokit, cache, owner, repo, issueNumber, {
70
+ pageSize,
71
+ ...(since === undefined ? {} : { since }),
72
+ ...(maxResults === undefined ? {} : { maxResults }),
73
+ }),
74
+ listReviewComments: (owner, repo, pullNumber, pageSize, maxResults) => listReviewComments(octokit, cache, owner, repo, pullNumber, {
75
+ pageSize,
76
+ ...(maxResults === undefined ? {} : { maxResults }),
77
+ }),
78
+ getIssueLabels: (owner, repo, issueNumber) => getIssueLabels(octokit, cache, owner, repo, issueNumber),
69
79
  getPullRequest: (owner, repo, pullNumber) => getPullRequest(octokit, cache, owner, repo, pullNumber),
70
- listReviews: (owner, repo, pullNumber, pageSize) => listReviews(octokit, cache, owner, repo, pullNumber, pageSize),
71
- listCheckRunsForRef: (owner, repo, ref) => listCheckRunsForRef(octokit, cache, owner, repo, ref),
72
- listPullRequestFiles: (owner, repo, pullNumber) => listPullRequestFiles(octokit, cache, owner, repo, pullNumber),
73
- getCombinedStatusForRef: (owner, repo, ref) => getCombinedStatusForRef(octokit, cache, owner, repo, ref),
80
+ listReviews: (owner, repo, pullNumber, pageSize, maxResults) => listReviews(octokit, cache, owner, repo, pullNumber, {
81
+ pageSize,
82
+ ...(maxResults === undefined ? {} : { maxResults }),
83
+ }),
84
+ listCheckRunsForRef: (owner, repo, ref, maxResults) => listCheckRunsForRef(octokit, cache, owner, repo, ref, maxResults),
85
+ listPullRequestFiles: (owner, repo, pullNumber, maxResults) => listPullRequestFiles(octokit, cache, owner, repo, pullNumber, maxResults),
86
+ getCombinedStatusForRef: (owner, repo, ref, maxResults) => getCombinedStatusForRef(octokit, cache, owner, repo, ref, maxResults),
74
87
  branch: (owner, repo, name) => branch(octokit, cache, owner, repo, name),
75
- deliver: (command) => deliver(octokit, command),
76
88
  };
77
89
  }
78
90
  function providerPermission(permission) {
@@ -7,7 +7,7 @@ export async function reviewCommentEventsFor(context, pullRequests) {
7
7
  return { drafts: [], succeeded: true };
8
8
  const items = await Promise.all(pullRequests.map(async (pullRequest) => {
9
9
  try {
10
- const comments = await context.client.listReviewComments(context.owner, context.repo, pullRequest.number, context.config.polling.commentPageSize);
10
+ const comments = await context.client.listReviewComments(context.owner, context.repo, pullRequest.number, context.config.polling.commentPageSize, context.config.polling.maxPerRepo);
11
11
  return {
12
12
  succeeded: true,
13
13
  drafts: (await Promise.all(comments.map((comment) => issueCommentEventsForComment(context, pullRequest, comment)))).flat(),
@@ -23,7 +23,7 @@ export async function reviewCommentEventsFor(context, pullRequests) {
23
23
  export async function reviewEventsFor(context, pullRequests) {
24
24
  const items = await Promise.all(pullRequests.map(async (pullRequest) => {
25
25
  try {
26
- const reviews = await context.client.listReviews(context.owner, context.repo, pullRequest.number, context.config.polling.commentPageSize);
26
+ const reviews = await context.client.listReviews(context.owner, context.repo, pullRequest.number, context.config.polling.commentPageSize, context.config.polling.maxPerRepo);
27
27
  return {
28
28
  succeeded: true,
29
29
  drafts: reviews.flatMap((review) => githubReviewObservation({
@@ -44,7 +44,7 @@ export async function reviewEventsFor(context, pullRequests) {
44
44
  export async function issueCommentEventsFor(context, issues, since) {
45
45
  const items = await Promise.all(issues.map(async (issue) => {
46
46
  try {
47
- const comments = await context.client.listIssueComments(context.owner, context.repo, issue.number, context.config.polling.commentPageSize, since);
47
+ const comments = await context.client.listIssueComments(context.owner, context.repo, issue.number, context.config.polling.commentPageSize, since, context.config.polling.maxPerRepo);
48
48
  return {
49
49
  succeeded: true,
50
50
  drafts: (await Promise.all(comments.map((comment) => issueCommentEventsForComment(context, issue, comment)))).flat(),
@@ -18,8 +18,8 @@ export function createGitHubPullRequestSource(input) {
18
18
  signal.throwIfAborted();
19
19
  const headRevision = fallback(pullRequest.head?.sha, pullRequest.updated_at);
20
20
  const [evidence, changedFiles] = await Promise.all([
21
- readCheckEvidence(input.client, owner, repo, headRevision),
22
- readChangedFiles(input.client, owner, repo, pullRequest.number),
21
+ readCheckEvidence(input.client, owner, repo, headRevision, input.maxResults),
22
+ readChangedFiles(input.client, owner, repo, pullRequest.number, input.maxResults),
23
23
  ]);
24
24
  return pullRequestObservation({
25
25
  repository: input.repository,
@@ -91,11 +91,11 @@ function normalizeCheckEvidence(checkRuns, statuses) {
91
91
  return PullRequestCheckState.Passing;
92
92
  return PullRequestCheckState.Unknown;
93
93
  }
94
- async function readCheckEvidence(client, owner, repo, headRevision) {
94
+ async function readCheckEvidence(client, owner, repo, headRevision, maxResults) {
95
95
  try {
96
96
  const [checkRuns, statuses] = await Promise.all([
97
- client.listCheckRunsForRef(owner, repo, headRevision),
98
- client.getCombinedStatusForRef(owner, repo, headRevision),
97
+ client.listCheckRunsForRef(owner, repo, headRevision, maxResults),
98
+ client.getCombinedStatusForRef(owner, repo, headRevision, maxResults),
99
99
  ]);
100
100
  return { available: true, checkRuns, statuses };
101
101
  }
@@ -103,9 +103,9 @@ async function readCheckEvidence(client, owner, repo, headRevision) {
103
103
  return { available: false, checkRuns: [], statuses: [] };
104
104
  }
105
105
  }
106
- async function readChangedFiles(client, owner, repo, pullNumber) {
106
+ async function readChangedFiles(client, owner, repo, pullNumber, maxResults) {
107
107
  try {
108
- return await client.listPullRequestFiles(owner, repo, pullNumber);
108
+ return await client.listPullRequestFiles(owner, repo, pullNumber, maxResults);
109
109
  }
110
110
  catch {
111
111
  return undefined;
@@ -54,15 +54,15 @@ function limitGitHubSourceClient(client, requests) {
54
54
  ...client,
55
55
  listIssues: (owner, repo, maxResults, since) => requests.run(() => client.listIssues(owner, repo, maxResults, since)),
56
56
  listPullRequests: (owner, repo, maxResults) => requests.run(() => client.listPullRequests(owner, repo, maxResults)),
57
- listCheckRunsForRef: (owner, repo, ref) => requests.run(() => client.listCheckRunsForRef(owner, repo, ref)),
58
- getCombinedStatusForRef: (owner, repo, ref) => requests.run(() => client.getCombinedStatusForRef(owner, repo, ref)),
59
- listPullRequestFiles: (owner, repo, pullNumber) => requests.run(() => client.listPullRequestFiles(owner, repo, pullNumber)),
60
- listIssueComments: (owner, repo, issueNumber, pageSize, since) => requests.run(() => client.listIssueComments(owner, repo, issueNumber, pageSize, since)),
61
- listReviews: (owner, repo, pullNumber, pageSize) => requests.run(() => client.listReviews(owner, repo, pullNumber, pageSize)),
57
+ listCheckRunsForRef: (owner, repo, ref, maxResults) => requests.run(() => client.listCheckRunsForRef(owner, repo, ref, maxResults)),
58
+ getCombinedStatusForRef: (owner, repo, ref, maxResults) => requests.run(() => client.getCombinedStatusForRef(owner, repo, ref, maxResults)),
59
+ listPullRequestFiles: (owner, repo, pullNumber, maxResults) => requests.run(() => client.listPullRequestFiles(owner, repo, pullNumber, maxResults)),
60
+ listIssueComments: (owner, repo, issueNumber, pageSize, since, maxResults) => requests.run(() => client.listIssueComments(owner, repo, issueNumber, pageSize, since, maxResults)),
61
+ listReviews: (owner, repo, pullNumber, pageSize, maxResults) => requests.run(() => client.listReviews(owner, repo, pullNumber, pageSize, maxResults)),
62
62
  ...(client.listReviewComments === undefined
63
63
  ? {}
64
64
  : {
65
- listReviewComments: (owner, repo, pullNumber, pageSize) => requests.run(() => client.listReviewComments(owner, repo, pullNumber, pageSize)),
65
+ listReviewComments: (owner, repo, pullNumber, pageSize, maxResults) => requests.run(() => client.listReviewComments(owner, repo, pullNumber, pageSize, maxResults)),
66
66
  }),
67
67
  ...(client.collaboratorPermission === undefined
68
68
  ? {}
@@ -39,7 +39,22 @@ export class ProjectionRunner {
39
39
  if (this.caughtUpToGlobalPosition !== undefined &&
40
40
  latestGlobalPosition <= this.caughtUpToGlobalPosition)
41
41
  return 0;
42
- const counts = await Promise.all(this.registered.map((definition) => this.applyFrom(definition, allEvents, limit)));
42
+ let failed = false;
43
+ let firstFailure;
44
+ const counts = await Promise.all(this.registered.map(async (definition) => {
45
+ try {
46
+ return await this.applyFrom(definition, allEvents, limit);
47
+ }
48
+ catch (error) {
49
+ if (!failed) {
50
+ failed = true;
51
+ firstFailure = error;
52
+ }
53
+ return 0;
54
+ }
55
+ }));
56
+ if (failed)
57
+ throw firstFailure;
43
58
  if (counts.every((count) => count < limit))
44
59
  this.caughtUpToGlobalPosition = latestGlobalPosition;
45
60
  return counts.reduce((total, count) => total + count, 0);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atolis-hq/wake",
3
- "version": "0.3.57",
3
+ "version": "0.3.59",
4
4
  "description": "Local autonomous agent control plane for software development",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {