patchrelay 0.67.2 → 0.68.1

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.
@@ -17,13 +17,15 @@ export class AgentSessionHandler {
17
17
  db;
18
18
  linearProvider;
19
19
  codex;
20
+ wakeDispatcher;
20
21
  logger;
21
22
  feed;
22
- constructor(config, db, linearProvider, codex, logger, feed) {
23
+ constructor(config, db, linearProvider, codex, wakeDispatcher, logger, feed) {
23
24
  this.config = config;
24
25
  this.db = db;
25
26
  this.linearProvider = linearProvider;
26
27
  this.codex = codex;
28
+ this.wakeDispatcher = wakeDispatcher;
27
29
  this.logger = logger;
28
30
  this.feed = feed;
29
31
  }
@@ -184,23 +186,17 @@ export class AgentSessionHandler {
184
186
  return;
185
187
  }
186
188
  if (promptBody && existingIssue && automationEnabled) {
187
- const hadPendingWake = this.db.issueSessions.peekIssueSessionWake(project.id, normalized.issue.id) !== undefined;
188
189
  if (!directReply && promptIntent && followupIntentIsNonActionable(promptIntent)) {
189
190
  await this.publishAgentActivity(linear, normalized.agentSession.id, buildNonActionableFollowupActivity(promptIntent));
190
191
  return;
191
192
  }
192
- this.db.issueSessions.appendIssueSessionEventRespectingActiveLease(project.id, normalized.issue.id, {
193
- projectId: project.id,
194
- linearIssueId: normalized.issue.id,
193
+ const queuedRunType = this.wakeDispatcher.recordEventAndDispatch(project.id, normalized.issue.id, {
195
194
  eventType: directReply ? "direct_reply" : "followup_prompt",
196
195
  eventJson: JSON.stringify({
197
196
  text: promptBody,
198
197
  source: "linear_agent_prompt",
199
198
  }),
200
199
  });
201
- const queuedRunType = hadPendingWake
202
- ? params.peekPendingSessionWakeRunType(project.id, normalized.issue.id)
203
- : params.enqueuePendingSessionWake(project.id, normalized.issue.id);
204
200
  const latestIssue = this.db.issues.getIssue(project.id, normalized.issue.id);
205
201
  await this.syncAgentSession(linear, normalized.agentSession.id, latestIssue ?? trackedIssue, params.peekPendingSessionWakeRunType, { pendingRunType: queuedRunType ?? wakeRunType ?? (existingIssue.prReviewState === "changes_requested" ? "review_fix" : "implementation") });
206
202
  await this.publishAgentActivity(linear, normalized.agentSession.id, buildPromptDeliveredThought(queuedRunType ?? wakeRunType ?? "implementation"), { ephemeral: true });
@@ -6,11 +6,13 @@ const ENQUEUEABLE_STATES = new Set(["pr_open", "changes_requested", "implementin
6
6
  export class CommentWakeHandler {
7
7
  db;
8
8
  codex;
9
+ wakeDispatcher;
9
10
  logger;
10
11
  feed;
11
- constructor(db, codex, logger, feed) {
12
+ constructor(db, codex, wakeDispatcher, logger, feed) {
12
13
  this.db = db;
13
14
  this.codex = codex;
15
+ this.wakeDispatcher = wakeDispatcher;
14
16
  this.logger = logger;
15
17
  this.feed = feed;
16
18
  }
@@ -35,9 +37,7 @@ export class CommentWakeHandler {
35
37
  const selfAuthored = isPatchRelayManagedCommentAuthor(installation, normalized.actor, normalized.comment.userName);
36
38
  const inertPatchRelayComment = isInertPatchRelayComment(issue, normalized.comment.id, trimmedBody, normalized.actor?.type);
37
39
  if (selfAuthored || inertPatchRelayComment) {
38
- this.db.issueSessions.appendIssueSessionEventRespectingActiveLease(project.id, normalized.issue.id, {
39
- projectId: project.id,
40
- linearIssueId: normalized.issue.id,
40
+ this.wakeDispatcher.recordEventAndDispatch(project.id, normalized.issue.id, {
41
41
  eventType: "self_comment",
42
42
  eventJson: JSON.stringify({
43
43
  body: trimmedBody,
@@ -76,9 +76,7 @@ export class CommentWakeHandler {
76
76
  return;
77
77
  }
78
78
  if (intent === "stop") {
79
- this.db.issueSessions.appendIssueSessionEventRespectingActiveLease(project.id, normalized.issue.id, {
80
- projectId: project.id,
81
- linearIssueId: normalized.issue.id,
79
+ this.wakeDispatcher.recordEventAndDispatch(project.id, normalized.issue.id, {
82
80
  eventType: "stop_requested",
83
81
  eventJson: JSON.stringify({
84
82
  body: trimmedBody,
@@ -112,19 +110,13 @@ export class CommentWakeHandler {
112
110
  return;
113
111
  }
114
112
  const runType = issue.prReviewState === "changes_requested" ? "review_fix" : "implementation";
115
- const hadPendingWake = this.db.issueSessions.peekIssueSessionWake(project.id, normalized.issue.id) !== undefined;
116
- this.db.issueSessions.appendIssueSessionEventRespectingActiveLease(project.id, normalized.issue.id, {
117
- projectId: project.id,
118
- linearIssueId: normalized.issue.id,
113
+ const queuedRunType = this.wakeDispatcher.recordEventAndDispatch(project.id, normalized.issue.id, {
119
114
  eventType: directReply ? "direct_reply" : "followup_comment",
120
115
  eventJson: JSON.stringify({
121
116
  body: trimmedBody,
122
117
  author: normalized.comment.userName,
123
118
  }),
124
119
  });
125
- const queuedRunType = hadPendingWake
126
- ? params.peekPendingSessionWakeRunType(project.id, normalized.issue.id)
127
- : params.enqueuePendingSessionWake(project.id, normalized.issue.id);
128
120
  this.feed?.publish({
129
121
  level: "info",
130
122
  kind: "comment",
@@ -158,9 +150,7 @@ export class CommentWakeHandler {
158
150
  activeRunId: null,
159
151
  factoryState: "awaiting_input",
160
152
  });
161
- this.db.issueSessions.appendIssueSessionEventRespectingActiveLease(project.id, normalized.issue.id, {
162
- projectId: project.id,
163
- linearIssueId: normalized.issue.id,
153
+ this.wakeDispatcher.recordEventAndDispatch(project.id, normalized.issue.id, {
164
154
  eventType: "stop_requested",
165
155
  eventJson: JSON.stringify({
166
156
  body: trimmedBody,
@@ -214,20 +204,14 @@ export class CommentWakeHandler {
214
204
  }
215
205
  catch (error) {
216
206
  this.logger.warn({ issueKey: trackedIssue?.issueKey, error: error instanceof Error ? error.message : String(error) }, "Failed to deliver follow-up comment");
217
- const hadPendingWake = this.db.issueSessions.hasPendingIssueSessionEvents(project.id, normalized.issue.id);
218
207
  const directReply = params.isDirectReplyToOutstandingQuestion(issue);
219
- this.db.issueSessions.appendIssueSessionEventRespectingActiveLease(project.id, normalized.issue.id, {
220
- projectId: project.id,
221
- linearIssueId: normalized.issue.id,
208
+ this.wakeDispatcher.recordEventAndDispatch(project.id, normalized.issue.id, {
222
209
  eventType: directReply ? "direct_reply" : "followup_comment",
223
210
  eventJson: JSON.stringify({
224
211
  body: trimmedBody,
225
212
  author: normalized.comment.userName,
226
213
  }),
227
214
  });
228
- if (!hadPendingWake) {
229
- params.enqueuePendingSessionWake(project.id, normalized.issue.id);
230
- }
231
215
  this.feed?.publish({
232
216
  level: "warn",
233
217
  kind: "comment",
@@ -1,8 +1,10 @@
1
1
  export class DependencyReadinessHandler {
2
2
  db;
3
+ wakeDispatcher;
3
4
  peekPendingSessionWakeRunType;
4
- constructor(db, peekPendingSessionWakeRunType) {
5
+ constructor(db, wakeDispatcher, peekPendingSessionWakeRunType) {
5
6
  this.db = db;
7
+ this.wakeDispatcher = wakeDispatcher;
6
8
  this.peekPendingSessionWakeRunType = peekPendingSessionWakeRunType;
7
9
  }
8
10
  reconcile(projectId, blockerLinearIssueId) {
@@ -40,9 +42,7 @@ export class DependencyReadinessHandler {
40
42
  pendingRunContextJson: null,
41
43
  });
42
44
  }
43
- this.db.issueSessions.appendIssueSessionEventRespectingActiveLease(projectId, dependent.linearIssueId, {
44
- projectId,
45
- linearIssueId: dependent.linearIssueId,
45
+ this.wakeDispatcher.recordEventAndDispatch(projectId, dependent.linearIssueId, {
46
46
  eventType: "delegated",
47
47
  dedupeKey: `delegated:${dependent.linearIssueId}`,
48
48
  });
@@ -11,10 +11,12 @@ import { deriveLinkedPrAdoptionOutcome } from "../delegation-linked-pr.js";
11
11
  export class DesiredStageRecorder {
12
12
  db;
13
13
  linearProvider;
14
+ wakeDispatcher;
14
15
  feed;
15
- constructor(db, linearProvider, feed) {
16
+ constructor(db, linearProvider, wakeDispatcher, feed) {
16
17
  this.db = db;
17
18
  this.linearProvider = linearProvider;
19
+ this.wakeDispatcher = wakeDispatcher;
18
20
  this.feed = feed;
19
21
  }
20
22
  async record(params) {
@@ -288,6 +290,7 @@ export class DesiredStageRecorder {
288
290
  },
289
291
  eventType: "child_changed",
290
292
  changeKind: "detached",
293
+ wakeDispatcher: this.wakeDispatcher,
291
294
  });
292
295
  }
293
296
  if (currentParentIssueId) {
@@ -311,6 +314,7 @@ export class DesiredStageRecorder {
311
314
  child: issue,
312
315
  eventType,
313
316
  changeKind,
317
+ wakeDispatcher: this.wakeDispatcher,
314
318
  });
315
319
  }
316
320
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "patchrelay",
3
- "version": "0.67.2",
3
+ "version": "0.68.1",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "repository": {