/** * El nodo de Jira como AI toolkit: sus doce operaciones como herramientas que * un AI Node, un servidor MCP o un agente de voz pueden llamar. * * ## Qué pidió Ariel (2026-09-27) * * «Haz el AI Toolkit de Jira y Notion», con el criterio de los anteriores: * como si fuera single operation, con TODOS los campos de cada operación * (`JIRA_OPERATION_SPECS`). Y tres decisiones suyas: * * - `delete_issue` nace BLOQUEADA: Jira no tiene papelera por API. * - El alcance nace en el PROYECTO del nodo, y el dueño lo puede abrir a * todos (`toolkitScope: 'any'`), como la base de Airtable. Se comprueba * por la clave (`ACME-42` es de ACME) y el JQL se acota al proyecto. * - «Attach file» entra POR URL: el modelo no puede mandar un fichero, así * que manda una URL pública y el nodo la descarga con el guardia de SSRF. * [2026-10-03] O el id de un fichero del evento: es lo único que el AI * Node le enseña («Files in this event»), y con sólo la URL un agente no * podía adjuntar el fichero que le había llegado. Como `upload_slack_file` * en 1.123.3. * * ## Los nombres en vez de los IDs * * En single operation la pantalla elige el tipo de incidencia, la transición * y la persona en un desplegable y guarda su ID. El modelo no tiene * desplegable: `issue_type`, `transition` y `assignee` admiten el ID O el * nombre (y la persona también por su correo), y el nodo lo resuelve contra * Jira. Si no encaja, el error trae las opciones que sí valen — es lo que el * modelo necesita para corregirse. * * [2026-10-03] Single operation resuelve igual: con la incidencia en una * plantilla no hay desplegable que pedir, y el nombre de la transición o la * persona por su correo es lo único que alguien sabe escribir. */ import type { CampoDeToolkit } from './argumentos-de-toolkit.js'; export type JiraToolkitOperation = 'createIssue' | 'getIssue' | 'updateIssue' | 'deleteIssue' | 'assignIssue' | 'transitionIssue' | 'addComment' | 'getComments' | 'addAttachment' | 'addWorklog' | 'linkIssues' | 'searchIssues' | 'createUser' | 'deleteUser' | 'addUserToGroup' | 'removeUserFromGroup'; export interface JiraToolkitParameter { name: string; type: 'string' | 'number' | 'boolean'; description: string; required: boolean; } export interface JiraToolkitSpec { operation: JiraToolkitOperation; label: string; toolName: string; description: string; parameters: JiraToolkitParameter[]; destructive?: boolean; /** Nace bloqueada en el nodo; el dueño la desbloquea. Ver `toolkits.ts`. */ bloqueadaPorDefecto?: boolean; } /** Los parámetros que el nodo puede traer configurados: el modelo los omite * y se usa el proyecto del nodo. */ export declare const JIRA_TOOLKIT_DEFAULTABLE: readonly ["project_key"]; /** Cuántas incidencias o comentarios vuelven si el modelo no dice otra cosa: * cada uno entra en su contexto, y una incidencia de Jira pesa. */ export declare const JIRA_TOOLKIT_RESULTADOS_POR_DEFECTO = 20; /** Hasta dónde llega el modelo. `node` (el de fábrica): el proyecto del nodo. * `any`: cualquier proyecto que alcance la credencial. */ export declare const JIRA_TOOLKIT_ALCANCES: readonly ["node", "any"]; export type JiraToolkitAlcance = (typeof JIRA_TOOLKIT_ALCANCES)[number]; /** El tope de la descarga de `add_issue_attachment`: lo mismo que el cuerpo * de fichero del nodo HTTP. Jira Cloud acepta más, pero el fichero pasa por * la memoria del proceso. */ export declare const JIRA_TOOLKIT_ADJUNTO_MAX_BYTES: number; export declare const JIRA_TOOLKIT_SPECS: JiraToolkitSpec[]; export declare const JIRA_TOOLKIT_SPECS_BY_TOOL_NAME: Readonly>; export declare const JIRA_TOOLKIT_CAMPOS: Readonly>>>; /** El proyecto de una clave de incidencia (`ACME-42` → `ACME`), o `null` si * no tiene forma de clave — un id numérico no dice de qué proyecto es. */ export declare function proyectoDeLaClave(clave: string): string | null; /** * Acota un JQL al proyecto: `project = "ACME" AND () ORDER BY …`. * * 🔒 El JQL lo escribe el modelo, así que se lee como hostil. Envolverlo en * paréntesis no basta: con `x) OR (project = OTRO` el texto cerraría nuestro * paréntesis y el `OR` escaparía del proyecto. Por eso se recorre fuera de * comillas y se exige que sus paréntesis estén EQUILIBRADOS y nunca bajen de * cero. El `ORDER BY` se saca fuera del paréntesis, que es donde Jira lo * admite. * * Devuelve el JQL acotado o `{ error }` con lo que el modelo tiene que * corregir. */ export declare function jqlDelProyecto(jql: string, proyecto: string): { jql: string; } | { error: string; };