diff --git a/plugin.json b/plugin.json index 98364d2..04a0b77 100644 --- a/plugin.json +++ b/plugin.json @@ -13,6 +13,9 @@ "issues.create", "issues.update", "issue.comments.create", + "issue.comments.read", + "agents.read", + "agents.invoke", "agent.tools.register", "http.outbound", "plugin.state.read", diff --git a/src/worker.ts b/src/worker.ts index d2fa2eb..a4fd7c2 100644 --- a/src/worker.ts +++ b/src/worker.ts @@ -517,6 +517,89 @@ const plugin = definePlugin({ } }); + // Route user comments through CEO agent + const CEO_AGENT_ID = "752cebdd-6748-4a04-aacd-c7ab0294ef33"; + + ctx.events.on("issue.comment.created", async (event) => { + // Only intercept human comments — not agent comments (prevents loops) + if (event.actorType !== "user") return; + if (!event.companyId) return; + + // entityId is the comment ID — fetch the comment to get issueId + body + const entityId = event.entityId; + if (!entityId) return; + + // The event payload may contain the issueId directly + const payload = event.payload as { + issueId?: string; + body?: string; + } | null; + + let issueId = payload?.issueId; + let commentBody = payload?.body; + + // If issueId is not in payload, try to find it from the comment entity + if (!issueId) { + ctx.logger.warn( + "issue.comment.created event missing issueId in payload, skipping", + { entityId, payload }, + ); + return; + } + + // Fetch issue details for context + const issue = await ctx.issues.get(issueId, event.companyId); + if (!issue) { + ctx.logger.warn("Could not fetch issue for comment routing", { + issueId, + }); + return; + } + + // If comment body not in payload, fetch from API + if (!commentBody) { + try { + const comments = await ctx.issues.listComments( + issueId, + event.companyId, + ); + const latest = comments[comments.length - 1]; + commentBody = latest?.body || "(לא ניתן לקרוא את התגובה)"; + } catch { + commentBody = "(שגיאה בקריאת התגובה)"; + } + } + + // Wake the CEO agent with the comment context + try { + const { runId } = await ctx.agents.invoke( + CEO_AGENT_ID, + event.companyId, + { + prompt: [ + `תגובה חדשה מחיים על issue "${issue.title}" (${issue.identifier || issueId}):`, + "", + commentBody, + "", + `קרא את ה-comments האחרונים על ה-issue, הבן מה חיים מבקש, והחלט מה לעשות.`, + `אם ההוראה ברורה — נתב לסוכן המתאים. אם לא ברור — שאל את חיים.`, + ].join("\n"), + reason: `user_commented_on_${issue.identifier || issueId}`, + }, + ); + ctx.logger.info("Routed user comment to CEO agent", { + issueId, + commentId: entityId, + runId, + }); + } catch (err) { + ctx.logger.error("Failed to invoke CEO agent for comment routing", { + issueId, + error: String(err), + }); + } + }); + // ── Jobs ─────────────────────────────────────────────────────── ctx.jobs.register("sync-case-status", async (job) => {