ework-daemon 0.4.55 → 0.4.57
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/package.json +1 -1
- package/src/opencode.ts +28 -17
package/package.json
CHANGED
package/src/opencode.ts
CHANGED
|
@@ -98,28 +98,24 @@ const RECENT_BOT_REPLY_THRESHOLD_MS = 5 * 60_000; // 5 minutes
|
|
|
98
98
|
|
|
99
99
|
/**
|
|
100
100
|
* Determine whether any non-system bot reply exists that is causally after
|
|
101
|
-
* `promptTime` (when provided)
|
|
102
|
-
*
|
|
103
|
-
*
|
|
101
|
+
* `promptTime` (when provided) AND within a 5-minute absolute window.
|
|
102
|
+
* The causal bound prevents preempt/nudge false-done detection (a reply from
|
|
103
|
+
* the previous run must not satisfy this run); the recency bound prevents an
|
|
104
|
+
* early ack from satisfying a long run that ended silently (awork policy).
|
|
105
|
+
* Exported for unit testing.
|
|
104
106
|
*/
|
|
105
107
|
export function hasRecentBotReply(
|
|
106
108
|
comments: TrackerComment[],
|
|
107
109
|
isBotUser: (author: string) => boolean,
|
|
108
110
|
promptTime?: number,
|
|
109
111
|
): boolean {
|
|
110
|
-
if (promptTime) {
|
|
111
|
-
return comments.some(c => {
|
|
112
|
-
if (!isBotUser(c.author) || c.body.startsWith(SYSTEM_PREFIX)) return false;
|
|
113
|
-
if (!c.createdAt) return false;
|
|
114
|
-
return new Date(c.createdAt).getTime() > promptTime;
|
|
115
|
-
});
|
|
116
|
-
}
|
|
117
112
|
const now = Date.now();
|
|
118
113
|
return comments.some(c => {
|
|
119
114
|
if (!isBotUser(c.author) || c.body.startsWith(SYSTEM_PREFIX)) return false;
|
|
120
|
-
if (!c.createdAt) return
|
|
121
|
-
const
|
|
122
|
-
|
|
115
|
+
if (!c.createdAt) return !promptTime;
|
|
116
|
+
const created = new Date(c.createdAt).getTime();
|
|
117
|
+
if (promptTime && created <= promptTime) return false;
|
|
118
|
+
return now - created < RECENT_BOT_REPLY_THRESHOLD_MS;
|
|
123
119
|
});
|
|
124
120
|
}
|
|
125
121
|
|
|
@@ -336,6 +332,7 @@ export class Engine {
|
|
|
336
332
|
private startedAt = new Map<string, number>();
|
|
337
333
|
private progressCommentId = new Map<string, string>();
|
|
338
334
|
private pickupCommentId = new Map<string, string>();
|
|
335
|
+
private forwardCommentId = new Map<string, string>();
|
|
339
336
|
|
|
340
337
|
private nudgeRounds = new Map<string, number>();
|
|
341
338
|
private emptyResponseRounds = new Map<string, number>();
|
|
@@ -898,7 +895,10 @@ export class Engine {
|
|
|
898
895
|
);
|
|
899
896
|
|
|
900
897
|
// Immediate ack
|
|
901
|
-
|
|
898
|
+
{
|
|
899
|
+
const c = await tracker.createComment(ref, `[system] ✓ Message forwarded to **${session.name}**${this.running.has(this.sessionKey(session, issue)) ? " (running)" : ""}.\n> session: ${this.sessionRef(session)} | workdir: ${this.workdirLink(workdir)}`);
|
|
900
|
+
if (!session.opencodeSessionId) this.forwardCommentId.set(this.sessionKey(session, issue), c.id);
|
|
901
|
+
}
|
|
902
902
|
|
|
903
903
|
await this.enqueueOrRun(session, issue, prompt, comment.id, model);
|
|
904
904
|
} else {
|
|
@@ -1234,10 +1234,17 @@ export class Engine {
|
|
|
1234
1234
|
const pickupId = this.pickupCommentId.get(k);
|
|
1235
1235
|
if (pickupId) {
|
|
1236
1236
|
this.pickupCommentId.delete(k);
|
|
1237
|
+
this.forwardCommentId.delete(k);
|
|
1237
1238
|
await tracker
|
|
1238
1239
|
.editComment(ref, pickupId, `[system] 🔄 **${session.name}** picked up this issue.\n> session: ${this.sessionRef(session)} | workdir: ${this.workdirLink(workdir)}`)
|
|
1239
1240
|
.catch((err) => log.error(`engine: failed to rewrite pickup comment for ${k}:`, (err as Error).message));
|
|
1240
1241
|
}
|
|
1242
|
+
const forwardId = this.forwardCommentId.get(k);
|
|
1243
|
+
if (forwardId) {
|
|
1244
|
+
this.forwardCommentId.delete(k);
|
|
1245
|
+
const body = `[system] ✓ Message forwarded to **${session.name}**${this.running.has(k) ? " (running)" : ""}.\n> session: ${this.sessionRef(session)} | workdir: ${this.workdirLink(workdir)}`;
|
|
1246
|
+
await tracker.editComment(ref, forwardId, body).catch(() => { /* cosmetic rewrite */ });
|
|
1247
|
+
}
|
|
1241
1248
|
}
|
|
1242
1249
|
},
|
|
1243
1250
|
},
|
|
@@ -1361,9 +1368,13 @@ export class Engine {
|
|
|
1361
1368
|
const hasRecent = this.hasRecentBotReply(commentsNow, tracker, started ?? undefined);
|
|
1362
1369
|
|
|
1363
1370
|
if (hasRecent) {
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1371
|
+
const nowMs = Date.now();
|
|
1372
|
+
const matched = [...commentsNow].reverse().find(c => {
|
|
1373
|
+
if (!tracker.isBotUser(c.author) || this.isSystemComment(c) || !c.createdAt) return false;
|
|
1374
|
+
const created = new Date(c.createdAt).getTime();
|
|
1375
|
+
if (started && created <= started) return false;
|
|
1376
|
+
return nowMs - created < RECENT_BOT_REPLY_THRESHOLD_MS;
|
|
1377
|
+
});
|
|
1367
1378
|
log.info(`engine: [bot] reply found for ${k} after prompt (comment ${matched?.id ?? "?"} createdAt ${matched?.createdAt ?? "?"}), marking done`);
|
|
1368
1379
|
if (matched && !usedModel) {
|
|
1369
1380
|
const fromSession = await this.backend.lastSessionModel(session.opencodeSessionId).catch(() => ({ model: "" }));
|