Ctrl K
ComunidadGuías…

lib/project-issues.js

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
var mcp = require("./issues-mcp-server");
var resolveIssueWorkSession = require("./issue-work-session").resolveIssueWorkSession;
function attachProjectIssues(ctx) {
  function user(ws) {
    return !ctx.isMate && ctx.service && ctx.service.bindUser({ projectSlug: ctx.projectSlug, userId: ws._clayUser && ws._clayUser.id,
      analyzeGithub: ctx.resolveDefaultAi ? async function (before, prompt) {
        var actor = ws._clayUser;
        if (!ctx.resolveDefaultAi) throw new Error('Default AI is unavailable for duplicate checking.');
        var selection = await ctx.resolveDefaultAi(ws);
        if (ws.readyState !== 1 || ws._clayUser !== actor || !ctx.getClients().has(ws)) throw new Error('The requesting connection changed.');
        if (!selection || !selection.ready) throw new Error(selection && selection.error || 'Configure Default AI before checking duplicates.');
        var text = await require('./tool-llm').complete({ adapters: ctx.adapters, cwd: before.path, selection: selection,
          linuxUser: before.osIdentity && before.osIdentity.user, args: { prompt: prompt, model: 'standard' } });
        if (ws.readyState !== 1 || ws._clayUser !== actor || !ctx.getClients().has(ws)) throw new Error('The requesting connection changed.');
        return text;
      } : undefined });
  }
  function notify(entry, type) {
    for (var ws of ctx.getClients()) {
      if (!ws || ws.readyState !== 1 || ws._clayPane) continue;
      try { var bound = user(ws); if (bound) { if (entry.deleted) bound.readIssueTombstone({ ref: entry.ref }); else bound.readIssue({ ref: entry.ref }); ctx.sendTo(ws, Object.assign({ type: type || "issue_updated", projectSlug: ctx.projectSlug, ref: entry.ref, status: entry.status, title: entry.title, revision: entry.revision }, type === "issue_deleted" ? { deleted: true } : {})); } } catch (error) { /* Access may have changed. */ }
    }
    return entry;
  }
  function sessionBound(session) {
    var bound = !ctx.isMate && ctx.service && session && ctx.service.bindProjectSession({ projectSlug: ctx.projectSlug, session: session });
    if (!bound) return null;
    ["createIssue", "updateIssue", "reviewIssueComment"].forEach(function (method) {
      var original = bound[method];
      bound[method] = async function (args) { var result = await original(args); if (method === "reviewIssueComment") return notify(result, "issue_commented"); return notify(result); };
    });
    return bound;
  }
  // Contract variant for the person's Issues and Sticky Notes settings, or
  // undefined for the unchanged default (Mates and sessions outside the policy).
  function contractOptions(session) {
    var view = ctx.agentBehavior && session ? ctx.agentBehavior.view(session) : null;
    if (!view || !view.active) return undefined;
    return { linked: view.issueLinkedNotes, mode: view.mode("issues") === "request" ? "request" : "auto" };
  }
  function defs(session) { return ctx.isMate || !ctx.service || (session && !sessionBound(session)) ? [] : mcp.getToolDefs(sessionBound(session), contractOptions(session)); }
  function handleMessage(ws, msg) {
    var methods = { issues_list: "listIssues", issue_read: "readIssue", issue_create: "createIssue", issue_update: "updateIssue", issue_history: "issueHistory", issue_revision: "readIssueRevision", issue_comment: "commentIssue", issue_delete: "removeIssue" };
    Object.assign(methods, { issue_github_search: 'searchGithubIssue', issue_github_link: 'linkGithubIssue', issue_github_create: 'createGithubIssue' });
    if (!methods[msg.type] && msg.type !== "issue_start_work" && msg.type !== "issue_open_work") return false;
    Promise.resolve().then(async function () {
      var bound = user(ws);
      if (!bound) throw new Error("Issues are unavailable for this project.");
      var result;
      if (msg.type === "issue_open_work") {
        var session = resolveIssueWorkSession(bound, msg.args || {});
        ctx.sm.switchSession(session.localId, ws); ws._clayActiveSession = session.localId;
        result = { sessionId: session.localId };
      } else if (msg.type === "issue_start_work") { result = await ctx.startWork(ws, msg, bound); notify(bound.readIssue({ ref: msg.args.ref })); }
      else {
        result = await bound[methods[msg.type]](msg.args || {});
        if (msg.type === 'issue_github_search' && result && result.linked) notify(result.linked);
        if (msg.type === "issue_create" || msg.type === "issue_update" || msg.type === 'issue_github_link' || msg.type === 'issue_github_create') notify(result);
        else if (msg.type === "issue_comment") notify(result, "issue_commented");
        else if (msg.type === "issue_delete") notify(result, "issue_deleted");
      }
      if (msg.type === "issue_read" && result) {
        result = Object.assign({}, result, { githubLinks: [] });
        (result.linkedWorkSessions || []).forEach(function (link) {
          try {
            var work = bound.resolveWorkSession({ ref: result.ref, sessionOriginId: link.sessionId });
            (work.githubLinks || []).forEach(function (item) {
              if (!result.githubLinks.some(function (existing) { return existing.url === item.url; })) result.githubLinks.push(item);
            });
          } catch (error) { /* Linked work may no longer be visible. */ }
        });
      }
      ctx.sendTo(ws, { type: "issues_result", requestId: msg.requestId, action: msg.type, result: result, canDelete: bound.canDelete === true });
    }).catch(function (error) {
      var result = error && error.sessionId ? { sessionId: error.sessionId } : undefined;
      if (msg.type === 'issue_github_create') {
        try {
          var current = user(ws);
          if (current) {
            result = current.readIssue({ ref: msg.args.ref });
            if (result.revision !== msg.args.expectedRevision) notify(result);
          }
        } catch (ignored) { /* Access may have changed. */ }
      }
      ctx.sendTo(ws, { type: "issues_result", requestId: msg.requestId, action: msg.type, error: error.message, result: result });
    });
    return true;
  }
  return {
    handleMessage: handleMessage, notify: notify,
    getDynamicToolDefs: function (session) { return defs(session).map(function (tool) { tool.permissionName = "mcp__clay-issues__" + tool.name; return tool; }); },
    createMcpServer: function (adapter, session) { return ctx.isMate || !ctx.service || !adapter.createToolServer ? null : adapter.createToolServer({ name: "clay-issues", version: "1.0.0", tools: defs(session) }); },
    getBridgeTools: function (session, normalize) { return defs(session).map(function (tool) { return { server: "clay-issues", name: tool.name, description: tool.description, inputSchema: normalize(tool.inputSchema) }; }); },
    callBridgeTool: function (session, name, args) { var tool = defs(session).find(function (item) { return item.name === name; }); if (!tool || !session) return Promise.reject(new Error("Issue tool unavailable.")); return tool.handler(args); },
    getSystemPrompt: function (session) { return sessionBound(session) ? "--- Project Issues ---\n" + mcp.contract(contractOptions(session)) : ""; },
  };
}
module.exports = { attachProjectIssues: attachProjectIssues };