@hostwebhook/node-types 1.69.0 → 1.71.0

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.
Files changed (101) hide show
  1. package/dist/bucket-operations.d.ts +88 -0
  2. package/dist/bucket-operations.js +140 -0
  3. package/dist/calendar-toolkit.d.ts +1 -1
  4. package/dist/connections.d.ts +1 -1
  5. package/dist/connections.js +1 -0
  6. package/dist/discord-operations.d.ts +1 -1
  7. package/dist/discord-operations.js +4 -4
  8. package/dist/discord-toolkit.d.ts +1 -1
  9. package/dist/discord-toolkit.js +3 -3
  10. package/dist/dispatch.d.ts +1 -1
  11. package/dist/dispatch.js +1 -0
  12. package/dist/docs-toolkit.d.ts +1 -1
  13. package/dist/drive-toolkit.d.ts +1 -1
  14. package/dist/esm/bucket-operations.d.ts +88 -0
  15. package/dist/esm/bucket-operations.js +136 -0
  16. package/dist/esm/calendar-operations.d.ts +67 -0
  17. package/dist/esm/calendar-operations.js +176 -0
  18. package/dist/esm/calendar-toolkit.d.ts +50 -0
  19. package/dist/esm/calendar-toolkit.js +152 -0
  20. package/dist/esm/capacidad-de-credencial.d.ts +75 -0
  21. package/dist/esm/capacidad-de-credencial.js +68 -0
  22. package/dist/esm/connections.d.ts +17 -0
  23. package/dist/esm/connections.js +107 -0
  24. package/dist/esm/credentials.d.ts +144 -0
  25. package/dist/esm/credentials.js +199 -0
  26. package/dist/esm/discord-operations.d.ts +104 -0
  27. package/dist/esm/discord-operations.js +407 -0
  28. package/dist/esm/discord-toolkit.d.ts +64 -0
  29. package/dist/esm/discord-toolkit.js +260 -0
  30. package/dist/esm/dispatch.d.ts +16 -0
  31. package/dist/esm/dispatch.js +77 -0
  32. package/dist/esm/docs-operations.d.ts +99 -0
  33. package/dist/esm/docs-operations.js +127 -0
  34. package/dist/esm/docs-toolkit.d.ts +42 -0
  35. package/dist/esm/docs-toolkit.js +97 -0
  36. package/dist/esm/drive-operations.d.ts +103 -0
  37. package/dist/esm/drive-operations.js +319 -0
  38. package/dist/esm/drive-toolkit.d.ts +54 -0
  39. package/dist/esm/drive-toolkit.js +177 -0
  40. package/dist/esm/github-operations.d.ts +147 -0
  41. package/dist/esm/github-operations.js +551 -0
  42. package/dist/esm/gmail-operations.d.ts +190 -0
  43. package/dist/esm/gmail-operations.js +560 -0
  44. package/dist/esm/google-analytics-operations.d.ts +99 -0
  45. package/dist/esm/google-analytics-operations.js +222 -0
  46. package/dist/esm/google-contacts-operations.d.ts +93 -0
  47. package/dist/esm/google-contacts-operations.js +363 -0
  48. package/dist/esm/index.d.ts +68 -0
  49. package/dist/esm/index.js +51 -0
  50. package/dist/esm/jira-operations.d.ts +164 -0
  51. package/dist/esm/jira-operations.js +470 -0
  52. package/dist/esm/llm-models.d.ts +101 -0
  53. package/dist/esm/llm-models.js +230 -0
  54. package/dist/esm/mailchimp-operations.d.ts +56 -0
  55. package/dist/esm/mailchimp-operations.js +155 -0
  56. package/dist/esm/mongo-operations.d.ts +61 -0
  57. package/dist/esm/mongo-operations.js +120 -0
  58. package/dist/esm/notion-operations.d.ts +125 -0
  59. package/dist/esm/notion-operations.js +511 -0
  60. package/dist/esm/openrouter.d.ts +142 -0
  61. package/dist/esm/openrouter.js +99 -0
  62. package/dist/esm/package.json +4 -0
  63. package/dist/esm/postgres-operations.d.ts +60 -0
  64. package/dist/esm/postgres-operations.js +75 -0
  65. package/dist/esm/registry.d.ts +160 -0
  66. package/dist/esm/registry.js +885 -0
  67. package/dist/esm/sheets-operations.d.ts +78 -0
  68. package/dist/esm/sheets-operations.js +150 -0
  69. package/dist/esm/sheets-toolkit.d.ts +49 -0
  70. package/dist/esm/sheets-toolkit.js +127 -0
  71. package/dist/esm/shopify-operations.d.ts +95 -0
  72. package/dist/esm/shopify-operations.js +259 -0
  73. package/dist/esm/slack-operations.d.ts +81 -0
  74. package/dist/esm/slack-operations.js +244 -0
  75. package/dist/esm/slack-toolkit.d.ts +60 -0
  76. package/dist/esm/slack-toolkit.js +235 -0
  77. package/dist/esm/telegram-operations.d.ts +104 -0
  78. package/dist/esm/telegram-operations.js +351 -0
  79. package/dist/esm/telegram-toolkit.d.ts +52 -0
  80. package/dist/esm/telegram-toolkit.js +183 -0
  81. package/dist/esm/types.d.ts +149 -0
  82. package/dist/esm/types.js +8 -0
  83. package/dist/esm/ui.d.ts +13 -0
  84. package/dist/esm/ui.js +152 -0
  85. package/dist/esm/whatsapp-operations.d.ts +23 -0
  86. package/dist/esm/whatsapp-operations.js +36 -0
  87. package/dist/index.d.ts +68 -66
  88. package/dist/index.js +193 -187
  89. package/dist/openrouter.d.ts +1 -1
  90. package/dist/registry.d.ts +4 -4
  91. package/dist/registry.js +540 -210
  92. package/dist/sheets-toolkit.d.ts +1 -1
  93. package/dist/slack-operations.d.ts +1 -1
  94. package/dist/slack-operations.js +4 -4
  95. package/dist/slack-toolkit.d.ts +1 -1
  96. package/dist/slack-toolkit.js +3 -3
  97. package/dist/telegram-toolkit.d.ts +1 -1
  98. package/dist/types.d.ts +1 -1
  99. package/dist/ui.d.ts +1 -1
  100. package/dist/ui.js +2 -0
  101. package/package.json +21 -3
@@ -0,0 +1,470 @@
1
+ /**
2
+ * Las operaciones del nodo `jiraAction` — la lista que comparten la api, el
3
+ * dashboard y el broker.
4
+ *
5
+ * Mismo patrón que `github-operations.ts` y `shopify-operations.ts`.
6
+ *
7
+ * ── Contra qué está escrito ──
8
+ *
9
+ * Jira Cloud, **REST API v3**, servida en
10
+ * `https://api.atlassian.com/ex/jira/{cloudId}/rest/api/3/…`. El `cloudId` sale
11
+ * de la credencial `oauth2_atlassian`, que ya existe: la montó el trigger de
12
+ * Jira y aquí se reutiliza entera.
13
+ *
14
+ * El permiso que hace falta para escribir es **`write:jira-work`**. Se añadió a
15
+ * los de por defecto en api#384; toda credencial anterior a eso es de sólo
16
+ * lectura hasta que su dueño la reconecte, y el síntoma es un 403 al ejecutar,
17
+ * no un fallo al guardar.
18
+ *
19
+ * ── La decisión que ordena todo lo demás: ADF ──
20
+ *
21
+ * En la v3, `description` y el `body` de un comentario **no son texto**: son
22
+ * Atlassian Document Format, un árbol JSON de nodos tipados. Mandar una cadena
23
+ * da 400.
24
+ *
25
+ * La salida fácil sería escribir con la v2, que sí acepta texto plano y sigue
26
+ * soportada. No se hace, y el motivo está escrito en nuestro propio repositorio
27
+ * desde antes de este nodo: `jira-watch.service.ts` excluye `description` al
28
+ * hidratar campos y explica por qué — *"la REST devuelve ADF —un objeto— pero
29
+ * el webhook manda texto plano; mezclar formas rompería las plantillas de
30
+ * abajo, que esperan cadenas"*.
31
+ *
32
+ * O sea: si este nodo leyera con una versión y escribiera con otra,
33
+ * `{{payload.fields.description}}` significaría una cosa cuando el flujo lo
34
+ * dispara un trigger de Jira y otra cuando lo consulta este nodo. Por eso:
35
+ *
36
+ * - **Todo en v3**, para leer y para escribir.
37
+ * - Al escribir, el texto del usuario se envuelve en ADF.
38
+ * - Al leer, el ADF se aplana a texto, y el árbol original viaja en una clave
39
+ * hermana para quien lo necesite.
40
+ * - `bodyFormat` deja pegar ADF crudo a quien quiera tablas o paneles.
41
+ *
42
+ * ── La otra trampa: la búsqueda cambió de sitio ──
43
+ *
44
+ * `GET/POST /rest/api/3/search` está **deprecado**. El sustituto es
45
+ * `POST /rest/api/3/search/jql`, y no es un renombre: pagina con
46
+ * `nextPageToken` en vez de `startAt`, **no devuelve `total`** (para contar hay
47
+ * `/search/approximate-count`) y los campos hay que pedirlos explícitamente.
48
+ * Casi todo ejemplo que hay por internet usa el endpoint muerto.
49
+ *
50
+ * ── Lo que NO es una operación ──
51
+ *
52
+ * Listar proyectos, tipos de incidencia, transiciones, estados o usuarios
53
+ * asignables **no** son operaciones: son endpoints del controlador que alimentan
54
+ * los selectores, como Drive alimenta su selector de ficheros. Una operación
55
+ * existe para producir payload en una corrida; esto otro es para rellenar el
56
+ * formulario. Mezclarlos llena el desplegable de cosas que nadie quiere
57
+ * ejecutar.
58
+ *
59
+ * ── Decisiones propias de Jira ──
60
+ *
61
+ * - El proyecto y el tipo de incidencia se ELIGEN de una lista viva. Un
62
+ * `issuetype` se identifica por un id numérico que nadie sabe de memoria.
63
+ * - **Las transiciones no son una lista fija.** Dependen del flujo de trabajo
64
+ * Y del estado actual de la incidencia, así que el selector las pide para
65
+ * esa incidencia concreta. Ofrecer una lista global sería ofrecer
66
+ * transiciones que fallan al ejecutarse.
67
+ * - Los campos personalizados van en JSON crudo. Cada tipo tiene su forma
68
+ * (`select`, `date`, `relation`, usuario…) y fingir que caben en tres
69
+ * campos genéricos produce un 400 que no nombra el campo.
70
+ * - Ninguna operación declarada sin implementar: el enum ES el contrato de la
71
+ * pantalla, y una operación declarada se pinta en el desplegable y falla al
72
+ * ejecutarse.
73
+ */
74
+ export const JIRA_OPERATIONS = [
75
+ // Incidencias
76
+ 'createIssue', // POST /issue
77
+ 'getIssue', // GET /issue/{key}
78
+ 'updateIssue', // PUT /issue/{key}
79
+ 'deleteIssue', // DELETE /issue/{key}
80
+ 'assignIssue', // PUT /issue/{key}/assignee
81
+ 'transitionIssue', // POST /issue/{key}/transitions
82
+ // Comentarios
83
+ 'addComment', // POST /issue/{key}/comment
84
+ 'getComments', // GET /issue/{key}/comment → iterable
85
+ // Adjuntos y trabajo
86
+ 'addAttachment', // POST /issue/{key}/attachments
87
+ 'addWorklog', // POST /issue/{key}/worklog
88
+ // Relaciones
89
+ 'linkIssues', // POST /issueLink
90
+ // Transversal
91
+ 'searchIssues', // POST /search/jql → iterable
92
+ ];
93
+ /** Type guard — para validar entrada no fiable (DTOs, tool calls). */
94
+ export function isJiraOperation(value) {
95
+ return (typeof value === 'string' &&
96
+ JIRA_OPERATIONS.includes(value));
97
+ }
98
+ /**
99
+ * Las operaciones que devuelven un ARRAY y por tanto obligan a marcar
100
+ * `_meta.iterable` en `getOutputPayload`.
101
+ *
102
+ * Vive aquí y no sólo en la api porque olvidarlo no falla al compilar: falla
103
+ * en producción, callado, con el nodo de abajo recibiendo el sobre entero en
104
+ * vez de un elemento y el PayloadViewer pintando rutas con corchetes que nadie
105
+ * puede usar.
106
+ */
107
+ export const JIRA_ITERABLE_OPERATIONS = [
108
+ 'getComments',
109
+ 'searchIssues',
110
+ ];
111
+ /* Ayudantes — repetir el mismo objeto doce veces es cómo se desincronizan las
112
+ descripciones. */
113
+ const project = (required = true) => ({
114
+ name: 'projectKey',
115
+ label: 'Project',
116
+ type: 'jiraProject',
117
+ required,
118
+ description: 'De la lista de proyectos que alcanza esta credencial. Se guarda la clave (ACME).',
119
+ });
120
+ const issueKey = (label = 'Issue') => ({
121
+ name: 'issueKey',
122
+ label,
123
+ type: 'jiraIssueKey',
124
+ required: true,
125
+ placeholder: '{{payload.issueKey}}',
126
+ description: 'La clave que se ve en la URL (ACME-42), no el id interno. El trigger de Jira la deja en issueKey.',
127
+ });
128
+ /**
129
+ * El interruptor de formato para todo campo que Jira quiere en ADF.
130
+ *
131
+ * Por defecto `text`: se escribe normal y el nodo lo envuelve. `adf` es la
132
+ * salida para quien necesita tablas, paneles o menciones — cosas que el texto
133
+ * plano no sabe expresar y que no vale la pena inventarse un lenguaje para
134
+ * cubrir.
135
+ */
136
+ const bodyFormat = () => ({
137
+ name: 'bodyFormat',
138
+ label: 'Format',
139
+ type: 'select',
140
+ default: 'text',
141
+ advanced: true,
142
+ options: [
143
+ { value: 'text', label: 'Plain text (se convierte a ADF)' },
144
+ { value: 'adf', label: 'Atlassian Document Format en crudo' },
145
+ ],
146
+ description: 'Jira v3 guarda estos campos como ADF. En "plain text" el nodo lo envuelve por ti: un párrafo por bloque y salto de línea donde lo escribas.',
147
+ });
148
+ const customFields = () => ({
149
+ name: 'customFields',
150
+ label: 'Other fields (JSON)',
151
+ type: 'json',
152
+ advanced: true,
153
+ placeholder: '{ "customfield_10042": { "accountId": "..." }, "labels": ["urgente"] }',
154
+ description: 'Se mezcla tal cual dentro de `fields`. Cada tipo de campo de Jira tiene su forma; el esquema real se lee con el selector de campos de la pantalla.',
155
+ });
156
+ const maxResults = () => ({
157
+ name: 'maxResults',
158
+ label: 'How many at most',
159
+ type: 'number',
160
+ default: 50,
161
+ min: 1,
162
+ max: 100,
163
+ advanced: true,
164
+ description: 'Jira no devuelve más de 100 por página.',
165
+ });
166
+ export const JIRA_OPERATION_SPECS = {
167
+ createIssue: {
168
+ label: 'Create issue',
169
+ description: 'Crea una incidencia en un proyecto.',
170
+ apiRoute: 'POST /rest/api/3/issue',
171
+ params: [
172
+ project(),
173
+ {
174
+ name: 'issueTypeId',
175
+ label: 'Issue type',
176
+ type: 'jiraIssueType',
177
+ required: true,
178
+ description: 'Los tipos son del proyecto, no globales: se piden después de elegirlo.',
179
+ },
180
+ {
181
+ name: 'summary',
182
+ label: 'Summary',
183
+ type: 'template',
184
+ required: true,
185
+ placeholder: 'Fallo al exportar el informe',
186
+ description: 'El título. Es el único campo que Jira exige siempre.',
187
+ },
188
+ {
189
+ name: 'description',
190
+ label: 'Description',
191
+ type: 'textarea',
192
+ placeholder: 'Lo que pasó, con {{payload.x}} si hace falta.',
193
+ },
194
+ bodyFormat(),
195
+ {
196
+ name: 'assigneeAccountId',
197
+ label: 'Assignee',
198
+ type: 'jiraUser',
199
+ advanced: true,
200
+ description: 'Se guarda el accountId, que es como lo pide Jira.',
201
+ },
202
+ {
203
+ name: 'parentKey',
204
+ label: 'Parent issue',
205
+ type: 'template',
206
+ advanced: true,
207
+ placeholder: 'ACME-10',
208
+ description: 'Sólo para subtareas: la incidencia padre. Con un tipo que no sea subtarea, Jira lo rechaza.',
209
+ },
210
+ customFields(),
211
+ ],
212
+ },
213
+ getIssue: {
214
+ label: 'Get issue',
215
+ description: 'Lee una incidencia por su clave.',
216
+ apiRoute: 'GET /rest/api/3/issue/{issueIdOrKey}',
217
+ params: [
218
+ issueKey(),
219
+ {
220
+ name: 'fields',
221
+ label: 'Fields',
222
+ type: 'template',
223
+ advanced: true,
224
+ placeholder: 'summary,status,assignee',
225
+ description: 'Separados por comas. Vacío trae los de siempre. Pedir sólo lo que usas hace la respuesta mucho más pequeña.',
226
+ },
227
+ ],
228
+ },
229
+ updateIssue: {
230
+ label: 'Update issue',
231
+ description: 'Cambia campos de una incidencia.',
232
+ apiRoute: 'PUT /rest/api/3/issue/{issueIdOrKey}',
233
+ params: [
234
+ issueKey(),
235
+ {
236
+ name: 'summary',
237
+ label: 'Summary',
238
+ type: 'template',
239
+ description: 'Vacío = no se toca.',
240
+ },
241
+ {
242
+ name: 'description',
243
+ label: 'Description',
244
+ type: 'textarea',
245
+ description: 'Vacío = no se toca. REEMPLAZA la descripción entera.',
246
+ },
247
+ bodyFormat(),
248
+ customFields(),
249
+ ],
250
+ },
251
+ deleteIssue: {
252
+ label: 'Delete issue',
253
+ description: 'Borra una incidencia. No hay papelera.',
254
+ apiRoute: 'DELETE /rest/api/3/issue/{issueIdOrKey}',
255
+ params: [
256
+ issueKey(),
257
+ {
258
+ name: 'deleteSubtasks',
259
+ label: 'Delete its subtasks too',
260
+ type: 'booleanSelect',
261
+ options: [
262
+ { value: '', label: '— sin tocar —' },
263
+ { value: 'true', label: 'Sí, borrar las subtareas' },
264
+ { value: 'false', label: 'No' },
265
+ ],
266
+ description: 'Con subtareas y sin esto, Jira se niega a borrar y devuelve 400.',
267
+ },
268
+ ],
269
+ },
270
+ assignIssue: {
271
+ label: 'Assign issue',
272
+ description: 'Cambia a quién está asignada.',
273
+ apiRoute: 'PUT /rest/api/3/issue/{issueIdOrKey}/assignee',
274
+ params: [
275
+ issueKey(),
276
+ {
277
+ name: 'accountId',
278
+ label: 'Assignee',
279
+ type: 'jiraUser',
280
+ required: true,
281
+ description: 'Vacío deja la incidencia sin asignar.',
282
+ },
283
+ ],
284
+ },
285
+ transitionIssue: {
286
+ label: 'Move issue',
287
+ description: 'Mueve la incidencia de columna (transición del flujo).',
288
+ apiRoute: 'POST /rest/api/3/issue/{issueIdOrKey}/transitions',
289
+ params: [
290
+ issueKey(),
291
+ {
292
+ name: 'transitionId',
293
+ label: 'Transition',
294
+ type: 'jiraTransition',
295
+ required: true,
296
+ description: 'Las transiciones legales dependen del flujo de trabajo Y del estado actual, así que se piden para esta incidencia. Una que no aplique falla al ejecutarse.',
297
+ },
298
+ {
299
+ name: 'comment',
300
+ label: 'Comment (optional)',
301
+ type: 'textarea',
302
+ advanced: true,
303
+ description: 'Jira permite comentar en el mismo paso de la transición.',
304
+ },
305
+ bodyFormat(),
306
+ ],
307
+ },
308
+ addComment: {
309
+ label: 'Add comment',
310
+ description: 'Comenta en una incidencia.',
311
+ apiRoute: 'POST /rest/api/3/issue/{issueIdOrKey}/comment',
312
+ params: [
313
+ issueKey(),
314
+ {
315
+ name: 'body',
316
+ label: 'Comment',
317
+ type: 'textarea',
318
+ required: true,
319
+ placeholder: 'Desplegado en producción: {{payload.version}}',
320
+ },
321
+ bodyFormat(),
322
+ ],
323
+ },
324
+ getComments: {
325
+ label: 'Get comments',
326
+ description: 'Trae los comentarios de una incidencia.',
327
+ apiRoute: 'GET /rest/api/3/issue/{issueIdOrKey}/comment',
328
+ params: [
329
+ issueKey(),
330
+ {
331
+ name: 'orderBy',
332
+ label: 'Order',
333
+ type: 'select',
334
+ default: '-created',
335
+ advanced: true,
336
+ options: [
337
+ { value: '-created', label: 'Los más nuevos primero' },
338
+ { value: 'created', label: 'Los más viejos primero' },
339
+ ],
340
+ },
341
+ maxResults(),
342
+ ],
343
+ },
344
+ addAttachment: {
345
+ label: 'Attach file',
346
+ description: 'Sube un fichero a una incidencia.',
347
+ apiRoute: 'POST /rest/api/3/issue/{issueIdOrKey}/attachments',
348
+ params: [
349
+ issueKey(),
350
+ {
351
+ name: 'fileField',
352
+ label: 'File from payload',
353
+ type: 'template',
354
+ required: true,
355
+ placeholder: '{{payload.file}}',
356
+ description: 'La ruta del payload donde viene el fichero — lo que dejan el nodo de ficheros o un adjunto de Gmail.',
357
+ },
358
+ {
359
+ name: 'fileName',
360
+ label: 'File name',
361
+ type: 'template',
362
+ advanced: true,
363
+ placeholder: 'informe.pdf',
364
+ description: 'Vacío usa el nombre que traiga el propio fichero.',
365
+ },
366
+ ],
367
+ },
368
+ addWorklog: {
369
+ label: 'Log work',
370
+ description: 'Apunta tiempo trabajado en una incidencia.',
371
+ apiRoute: 'POST /rest/api/3/issue/{issueIdOrKey}/worklog',
372
+ params: [
373
+ issueKey(),
374
+ {
375
+ name: 'timeSpent',
376
+ label: 'Time spent',
377
+ type: 'template',
378
+ required: true,
379
+ placeholder: '3h 30m',
380
+ description: 'En el formato de Jira: 2d, 3h, 30m, o combinados. No admite decimales.',
381
+ },
382
+ {
383
+ name: 'comment',
384
+ label: 'Comment',
385
+ type: 'textarea',
386
+ advanced: true,
387
+ },
388
+ bodyFormat(),
389
+ {
390
+ name: 'started',
391
+ label: 'When',
392
+ type: 'template',
393
+ advanced: true,
394
+ placeholder: '{{payload.timestamp}}',
395
+ description: 'Vacío usa el momento de la ejecución.',
396
+ },
397
+ ],
398
+ },
399
+ linkIssues: {
400
+ label: 'Link issues',
401
+ description: 'Relaciona dos incidencias entre sí.',
402
+ apiRoute: 'POST /rest/api/3/issueLink',
403
+ params: [
404
+ {
405
+ name: 'inwardIssueKey',
406
+ label: 'From issue',
407
+ type: 'jiraIssueKey',
408
+ required: true,
409
+ placeholder: '{{payload.issueKey}}',
410
+ },
411
+ {
412
+ name: 'linkType',
413
+ label: 'Relationship',
414
+ type: 'jiraLinkType',
415
+ required: true,
416
+ description: 'Los tipos los define cada sitio: "Blocks", "Relates", "Duplicates"… Se piden a Jira.',
417
+ },
418
+ {
419
+ name: 'outwardIssueKey',
420
+ label: 'To issue',
421
+ type: 'jiraIssueKey',
422
+ required: true,
423
+ placeholder: 'ACME-99',
424
+ },
425
+ ],
426
+ },
427
+ searchIssues: {
428
+ label: 'Search issues (JQL)',
429
+ description: 'Busca incidencias con JQL. Devuelve una lista iterable.',
430
+ /* ⚠️ `/search/jql`, NO `/search`. El viejo está deprecado y pagina distinto:
431
+ `nextPageToken` en vez de `startAt`, y sin `total` en la respuesta. */
432
+ apiRoute: 'POST /rest/api/3/search/jql',
433
+ params: [
434
+ {
435
+ name: 'jql',
436
+ label: 'JQL',
437
+ type: 'textarea',
438
+ required: true,
439
+ placeholder: 'project = ACME AND status != Done ORDER BY created DESC',
440
+ description: 'La misma consulta que escribirías en el buscador de Jira. Admite {{payload.x}}.',
441
+ },
442
+ {
443
+ name: 'fields',
444
+ label: 'Fields',
445
+ type: 'template',
446
+ advanced: true,
447
+ placeholder: 'summary,status,assignee',
448
+ description: 'Separados por comas. En este endpoint los campos hay que pedirlos: sin esto sólo llegan las claves.',
449
+ },
450
+ maxResults(),
451
+ {
452
+ name: 'nextPageToken',
453
+ label: 'Page token',
454
+ type: 'template',
455
+ advanced: true,
456
+ placeholder: '{{payload.nextPageToken}}',
457
+ description: 'Para pedir la página siguiente desde un Loop. La salida de esta operación lo devuelve.',
458
+ },
459
+ ],
460
+ },
461
+ };
462
+ /**
463
+ * Lo que se ofrece en el desplegable de operación.
464
+ *
465
+ * Hoy son todas. Existe como constante aparte —y no como alias de
466
+ * `JIRA_OPERATIONS`— porque es el punto donde otros nodos han necesitado
467
+ * esconder una operación sin sacarla del enum: retirarla del enum rompe las que
468
+ * ya estaban guardadas en la base de datos.
469
+ */
470
+ export const JIRA_DROPDOWN_OPERATIONS = JIRA_OPERATIONS;
@@ -0,0 +1,101 @@
1
+ /**
2
+ * Canonical LLM provider + model catalog. Single source of truth for
3
+ * every place that names a model, used by:
4
+ *
5
+ * - dashboard pickers: AI nodes, LLM credentials, voice agents
6
+ * - api defaults: the AI node's `model` @Prop, the cheap model the
7
+ * tool generator and the fact extractor pick per provider
8
+ * - api summarization: context windows drive the chunk size
9
+ *
10
+ * It lived in `dashboard/lib/llm-models.ts` until 2026-08-18, with a
11
+ * comment arguing model strings were "dashboard chrome only". They were
12
+ * not: the api had its own hardcoded copies and nothing synced them. The
13
+ * picker offered `claude-haiku-4-5` while the api minted nodes on
14
+ * `claude-sonnet-4-20250514`, retired two months earlier. Same class of
15
+ * bug `credentials.ts` exists to kill — both sides import one list now.
16
+ *
17
+ * NOT here: the models HostWebhook runs on its own key (see the api's
18
+ * `common/llm-models.ts`) and the voice-platform catalogs. Retell and
19
+ * Vapi accept their own spellings — Retell says `claude-5-sonnet`, Vapi
20
+ * demands the dated Haiku id — so those live with their backends and
21
+ * follow the platform's docs, not the provider's.
22
+ *
23
+ * Last verified against provider docs: 2026-08-18
24
+ * - Anthropic: https://platform.claude.com/docs/en/about-claude/models/overview
25
+ * - OpenAI: https://developers.openai.com/api/docs/models
26
+ * - Google: https://ai.google.dev/gemini-api/docs/models
27
+ * - Groq: https://console.groq.com/docs/models
28
+ *
29
+ * NOT verified against docs, and on purpose: OpenRouter. Its catalog is not a
30
+ * list anybody types — see `LLM_MODELS.openrouter` and `openrouter.ts`.
31
+ */
32
+ export type LlmProvider = 'anthropic' | 'openai' | 'google' | 'groq'
33
+ /**
34
+ * A router, not a lab: OpenRouter resells ~425 models from everybody else
35
+ * behind one key. That is why it is the first provider here whose catalog
36
+ * is EMPTY below and fetched live instead — the shape of the entry is in
37
+ * `openrouter.ts`, and the price of each model travels with the model.
38
+ */
39
+ | 'openrouter';
40
+ export interface LlmProviderOption {
41
+ value: LlmProvider;
42
+ label: string;
43
+ }
44
+ export interface LlmModelOption {
45
+ value: string;
46
+ /** Friendly label for pickers; defaults to `value` when absent. */
47
+ label?: string;
48
+ /**
49
+ * The suggested default for new selections — exactly one per provider.
50
+ *
51
+ * It carries more weight than "preselected in a dropdown": the api
52
+ * reads it through `getDefaultModel` for the model a new AI node is
53
+ * born with, and for the cheap model it picks when generating a tool
54
+ * definition or extracting memory facts. So the recommended entry must
55
+ * be the cheapest CURRENT-tier model of that provider — pick a
56
+ * flagship here and every background call gets expensive at once.
57
+ */
58
+ recommended?: boolean;
59
+ }
60
+ export declare const LLM_PROVIDERS: ReadonlyArray<LlmProviderOption>;
61
+ export declare const LLM_MODELS: Record<LlmProvider, ReadonlyArray<LlmModelOption>>;
62
+ /**
63
+ * Effective context window per model, in TOKENS. The api sizes
64
+ * summarization chunks from this; a miss falls back to a conservative
65
+ * 32k window, which still produces a summary — just chopped into far
66
+ * more map calls than needed. That silence is why this table went four
67
+ * months without a single current model in it.
68
+ *
69
+ * Includes ids the pickers no longer offer: the AI node's model field is
70
+ * a free-text datalist, so a node may hold one by hand.
71
+ *
72
+ * ⚠️ NOT here: OpenRouter's ids. Same reason its models are not in
73
+ * `LLM_MODELS` — its API publishes `context_length` per model, so the number
74
+ * travels with the model instead of being copied 425 times into this table.
75
+ * Whoever chunks for an OpenRouter model reads it from the fetched entry
76
+ * (`ModeloDeOpenRouter.context_length`); a lookup here misses and falls back
77
+ * to the conservative 32k, which still summarizes, just in more calls.
78
+ */
79
+ export declare const MODEL_CONTEXT_WINDOWS: Record<string, number>;
80
+ /**
81
+ * The model catalog for a provider. Accepts both the raw provider name
82
+ * (`"anthropic"`) and the `llm_*` credential type prefix
83
+ * (`"llm_anthropic"`) so call sites that key off credential type can
84
+ * pass the type directly without stripping.
85
+ */
86
+ export declare function getModelsFor(provider: string): ReadonlyArray<LlmModelOption>;
87
+ /**
88
+ * The suggested default model for a provider, or `''` for one we do not
89
+ * catalog (Ollama runs whatever the user pulled, so it has no entry —
90
+ * callers fall back to the node's own model there).
91
+ *
92
+ * ⚠️ `'openrouter'` is the second `''`, and unlike Ollama it IS a provider in
93
+ * `LLM_PROVIDERS`, so callers that assumed "every provider in the list has a
94
+ * default" now have a case to handle. It is deliberate: its catalog is live
95
+ * (see `LLM_MODELS.openrouter`) and no static pick would survive. Treat `''`
96
+ * as "the user must choose", not as "fall back to something" — a node born
97
+ * with an empty model must not be sent to the API as-is.
98
+ */
99
+ export declare function getDefaultModel(provider: string): string;
100
+ /** The friendly label for a model value, or the value itself. */
101
+ export declare function getModelLabel(value: string): string;