ework-web 0.10.66 → 0.10.67
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/webhooks.ts +20 -4
package/package.json
CHANGED
package/src/webhooks.ts
CHANGED
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
// the full retry trail rather than an opaque final status.
|
|
17
17
|
|
|
18
18
|
import { createHmac, randomUUID } from "node:crypto";
|
|
19
|
-
import { getDB } from "./db";
|
|
19
|
+
import { getDB, getConfigAll } from "./db";
|
|
20
20
|
import { log } from "./logger";
|
|
21
21
|
import { loadConfig } from "./config";
|
|
22
22
|
import {
|
|
@@ -312,6 +312,7 @@ interface IssueEventPayload {
|
|
|
312
312
|
commit_id?: string;
|
|
313
313
|
commit_url?: string;
|
|
314
314
|
url?: string;
|
|
315
|
+
dispatch_off?: boolean;
|
|
315
316
|
}
|
|
316
317
|
|
|
317
318
|
interface CommentEventPayload {
|
|
@@ -638,9 +639,23 @@ export async function emitIssueEvent(
|
|
|
638
639
|
const issue = await getIssueById(issueId);
|
|
639
640
|
if (!issue) { log.warn(`emitIssueEvent: issue ${issueId} not found — silent skip prevented`); return; }
|
|
640
641
|
|
|
641
|
-
// Web is a dumb message bus — always fan out.
|
|
642
|
-
//
|
|
643
|
-
//
|
|
642
|
+
// Web is a dumb message bus for comments — always fan out.
|
|
643
|
+
// BUT for issue_opened, dispatch state is a subscription-level switch:
|
|
644
|
+
// if dispatch is off (global/project/issue), don't emit at all.
|
|
645
|
+
// This is the "webhook switch" — downstream never sees the event.
|
|
646
|
+
// We still include dispatch_off in payload for defense-in-depth.
|
|
647
|
+
const cfg = await getConfigAll();
|
|
648
|
+
const scopeKey = `${project.owner}/${project.name}`;
|
|
649
|
+
const globalOff = cfg["dispatchEnabled"] === "false";
|
|
650
|
+
const projectOff = cfg[`dispatchOff:${scopeKey}`] === "1";
|
|
651
|
+
const issueOff = issue.ai_status === "dispatch_off" || issue.ai_status === "halted";
|
|
652
|
+
const dispatchOff = globalOff || projectOff || issueOff;
|
|
653
|
+
|
|
654
|
+
if (action === "opened" && dispatchOff) {
|
|
655
|
+
log.info(`webhook: issue_opened suppressed (dispatch off: global=${globalOff} project=${projectOff} issue=${issueOff}) for ${scopeKey}#${issue.number}`);
|
|
656
|
+
return;
|
|
657
|
+
}
|
|
658
|
+
|
|
644
659
|
const commentCount = await countCommentsSafe(issueId);
|
|
645
660
|
// Resolve model: project override > global default. Empty string = no
|
|
646
661
|
// override (daemon omits --model, lets opencode pick). globalDefault
|
|
@@ -650,6 +665,7 @@ export async function emitIssueEvent(
|
|
|
650
665
|
const labels = await toPayloadLabels(issueId);
|
|
651
666
|
const payload = buildIssuePayload(issue, project, commentCount, action, origin, model, labels);
|
|
652
667
|
(payload as IssueEventPayload).event_id = randomUUID();
|
|
668
|
+
(payload as IssueEventPayload).dispatch_off = dispatchOff;
|
|
653
669
|
const rawBody = JSON.stringify(payload);
|
|
654
670
|
await fanOut(projectId, "issues", rawBody);
|
|
655
671
|
} catch (e) {
|