@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,97 @@
1
+ /**
2
+ * Google Docs AI Toolkit — las herramientas que un docsAction expone cuando
3
+ * `aiEnabled` está encendido.
4
+ *
5
+ * Se escribe **una sola vez**, aquí, y la importan la api
6
+ * (`mcp-servers/toolkit-specs.ts`) y el dashboard (`NodeAsToolPicker`,
7
+ * `DocsActionDetail`). Es el sexto toolkit que vive en el paquete —van Gmail,
8
+ * native email, Calendar, Drive, Telegram y Sheets—; los que siguen con copia a
9
+ * mano en los dos repos son WhatsApp, Discord, Slack y Contacts, y de ese
10
+ * reparto salió que Contacts anunciara 15 herramientas y expusiera una.
11
+ *
12
+ * La forma es la que ya consume `toolkitSpecToMcpTool` en la api, para poder
13
+ * usarse sin adaptador. Los textos van en inglés porque los lee el modelo y
14
+ * quien mire la lista de herramientas del servidor MCP.
15
+ */
16
+ const p = (name, description, required = true, type = 'string') => ({ name, type, description, required });
17
+ /*
18
+ * El documento del nodo va como **defecto** y el modelo puede cambiarlo — la
19
+ * misma decisión y la misma maquinaria que la hoja de Sheets:
20
+ * `toolkitSpecToMcpTool(spec, nombre, { documentId })` lo saca de `required`
21
+ * **y le cuenta el valor al modelo** en la descripción. Las dos cosas o
22
+ * ninguna: mientras el esquema diga `required`, el LLM siempre lo rellena y el
23
+ * documento configurado no se usaría jamás.
24
+ *
25
+ * Por eso aquí se declara `required: true`: lo es para la API de Google, y es
26
+ * el defecto del nodo quien lo vuelve opcional, nodo por nodo.
27
+ *
28
+ * `create_doc` es el único que NO lo declara —todavía no hay documento al que
29
+ * apuntar— y su nombre de campo es `title`. Si se llamara `documentId`, la
30
+ * inyección de defectos se lo rellenaría con el documento del nodo y el
31
+ * documento nuevo nacería con el id del viejo por título.
32
+ */
33
+ const documento = () => p('documentId', 'Id of the Google Docs document — the long chunk of its URL, between /d/ and /edit.');
34
+ export const DOCS_TOOLKIT_SPECS = [
35
+ {
36
+ operation: 'readDoc',
37
+ label: 'Read document',
38
+ toolName: 'read_doc',
39
+ description: 'Read the whole document as plain text. Use it before editing when you do not know what the document already says — replace_text and append_text act blindly otherwise.',
40
+ parameters: [documento()],
41
+ },
42
+ {
43
+ operation: 'createDoc',
44
+ label: 'Create document',
45
+ toolName: 'create_doc',
46
+ description: 'Create a new Google Docs document and return its id. The id it returns is what the other tools take as documentId.',
47
+ parameters: [
48
+ p('title', 'Name of the new document.'),
49
+ p('content', 'Initial body, as HTML. Basic tags work (<p>, <b>, <i>, <ul>, <li>, <h1>…). Plain text is fine too. Leave it out for an empty document.', false),
50
+ ],
51
+ destructive: true,
52
+ },
53
+ {
54
+ operation: 'appendText',
55
+ label: 'Append text',
56
+ toolName: 'append_text',
57
+ description: 'Add content at the END of the document. It never replaces what is already there, so it is the safe way to add a paragraph, a note or a log line.',
58
+ parameters: [
59
+ p('content', 'What to add, as HTML. Basic tags work (<p>, <b>, <i>, <ul>, <li>, <h1>…). Plain text is fine too.'),
60
+ documento(),
61
+ ],
62
+ destructive: true,
63
+ },
64
+ {
65
+ operation: 'replaceText',
66
+ label: 'Replace text',
67
+ toolName: 'replace_text',
68
+ description: 'Find every occurrence of a piece of text and swap it for another. It matches literally and it is case-sensitive; a search string that appears nowhere changes nothing and is not an error.',
69
+ parameters: [
70
+ p('searchText', 'Exact text to look for. Every occurrence is replaced, not just the first.'),
71
+ p('replaceWith', 'Text to put in its place. An empty string deletes the matches.'),
72
+ documento(),
73
+ ],
74
+ destructive: true,
75
+ },
76
+ {
77
+ operation: 'insertTable',
78
+ label: 'Insert table',
79
+ toolName: 'insert_table',
80
+ description: 'Insert an empty table at the end of the document. It creates the grid only — fill the cells afterwards with replace_text, or build the content as HTML and use append_text instead.',
81
+ parameters: [
82
+ p('rows', 'Number of rows, including the header row if you want one.', true, 'number'),
83
+ p('cols', 'Number of columns.', true, 'number'),
84
+ documento(),
85
+ ],
86
+ destructive: true,
87
+ },
88
+ ];
89
+ /** Las herramientas por nombre, para despachar una llamada del modelo. */
90
+ export const DOCS_TOOLKIT_BY_TOOL_NAME = Object.fromEntries(DOCS_TOOLKIT_SPECS.map((s) => [s.toolName, s]));
91
+ /**
92
+ * El parámetro que el nodo puede rellenar por defecto. Se exporta para que la
93
+ * api y el dashboard no vuelvan a escribir la lista a mano — `create_doc` no
94
+ * lo declara y por eso se queda fuera de la inyección sin necesidad de
95
+ * excepciones.
96
+ */
97
+ export const DOCS_TOOLKIT_DEFAULTABLE = ['documentId'];
@@ -0,0 +1,103 @@
1
+ /**
2
+ * Google Drive operation enum — single source of truth across the API,
3
+ * Dashboard, and Message Broker. Used by:
4
+ * - driveAction entity / DTO (api): operation field + validation
5
+ * - dashboard DriveAction operation type
6
+ * - broker hostwebhook types + tool schemas
7
+ * - MCP toolkit specs (when aiEnabled: true)
8
+ *
9
+ * Same pattern as gmail-operations.ts and calendar-operations.ts.
10
+ *
11
+ * Op semantics (anti-n8n choices):
12
+ * - delete = move to trash (recoverable for 30 days), NOT permanent erase
13
+ * - upload / download stream via the api Files / R2 layer, never load
14
+ * full file contents into memory (n8n breaks past ~70MB)
15
+ * - download returns a `_file` ref so downstream FileTransform / AI /
16
+ * HTTP nodes can chain on it directly (n8n returns raw binary, often
17
+ * misformatted as HTML on errors)
18
+ */
19
+ export declare const DRIVE_OPERATIONS: readonly ["upload", "download", "copy", "move", "delete", "share", "update", "list", "get", "createFolder", "export", "getPermissions"];
20
+ export type DriveOperation = (typeof DRIVE_OPERATIONS)[number];
21
+ /** Type guard — useful when validating untrusted input (DTOs, tool calls). */
22
+ export declare function isDriveOperation(value: unknown): value is DriveOperation;
23
+ export type DriveParamType =
24
+ /** Live file picker (needs a credential) + templated paste. */
25
+ 'driveFile'
26
+ /** Text input with `{{payload.*}}` autocomplete. */
27
+ | 'template'
28
+ /** Plain `<select>`; the labels are not the values, so `options` is required. */
29
+ | 'select'
30
+ /**
31
+ * Searchable mime-type dropdown. The option list is long and shared with
32
+ * other screens, so it stays in the dashboard (`lib/drive-mime-options`)
33
+ * and the schema only says "this field is a mime picker".
34
+ */
35
+ | 'mimeSelect' | 'number'
36
+ /**
37
+ * A `<select>` whose values are `''` / `'true'` / `'false'` but which is
38
+ * stored as a BOOLEAN, or omitted entirely when `''`.
39
+ *
40
+ * This is the shape that keeps `starred` honest: the api applies it with
41
+ * `typeof config.starred === 'boolean'`, so "— don't change —" has to mean
42
+ * *no key at all*. A plain Switch cannot express that third state, and
43
+ * storing `''` or `'false'` would silently stop the star from ever changing.
44
+ */
45
+ | 'booleanSelect'
46
+ /**
47
+ * Full-width explainer card that toggles: icon, title, prose and bullets,
48
+ * with the switch on the right. The card's rich body is JSX, so it lives in
49
+ * the page keyed by param name — the schema only declares the field.
50
+ */
51
+ | 'switchCard'
52
+ /** Live multi-select of the starting folder's immediate children. */
53
+ | 'driveSubfolders';
54
+ export interface DriveParamSpec {
55
+ /** The `operationConfig` key. This is what the api reads — not a UI name. */
56
+ name: string;
57
+ label: string;
58
+ type: DriveParamType;
59
+ required?: boolean;
60
+ /**
61
+ * Help text under the field. Plain text on purpose: the package holds no
62
+ * React, so the `<code>` spans the page used to have are gone. Deliberate.
63
+ */
64
+ description?: string;
65
+ placeholder?: string;
66
+ /** Prefilled when the saved config has no value for this key. */
67
+ default?: string | number;
68
+ /** Required for `select` and `booleanSelect` — label and value differ. */
69
+ options?: ReadonlyArray<{
70
+ value: string;
71
+ label: string;
72
+ }>;
73
+ min?: number;
74
+ max?: number;
75
+ /**
76
+ * Renders in the "Advanced" tab instead of "Config". The page used to keep
77
+ * a two-name `ADVANCED_FIELDS` array while the advanced *tab* actually held
78
+ * four fields, so `recursive` and `subfolderIds` only showed up because
79
+ * `list` happened to also carry one of the two named fields. Marking all
80
+ * four here removes that coincidence.
81
+ */
82
+ advanced?: boolean;
83
+ /**
84
+ * Only shown when a sibling field holds one of these values. No other node's
85
+ * schema needed this yet; Drive has three cases (the two share targets and
86
+ * the subfolder scope).
87
+ */
88
+ showWhen?: {
89
+ field: string;
90
+ in: ReadonlyArray<string>;
91
+ };
92
+ }
93
+ export interface DriveOperationSpec {
94
+ /** UI label for the operation dropdown row. */
95
+ label: string;
96
+ /** Sub-line under the label in the dropdown. */
97
+ description: string;
98
+ /** Drive API method it maps to (developers.google.com/drive/api/reference). */
99
+ apiMethod: string;
100
+ /** Parameter schema. Order matters: it is the on-screen order. */
101
+ params: DriveParamSpec[];
102
+ }
103
+ export declare const DRIVE_OPERATION_SPECS: Record<DriveOperation, DriveOperationSpec>;
@@ -0,0 +1,319 @@
1
+ /**
2
+ * Google Drive operation enum — single source of truth across the API,
3
+ * Dashboard, and Message Broker. Used by:
4
+ * - driveAction entity / DTO (api): operation field + validation
5
+ * - dashboard DriveAction operation type
6
+ * - broker hostwebhook types + tool schemas
7
+ * - MCP toolkit specs (when aiEnabled: true)
8
+ *
9
+ * Same pattern as gmail-operations.ts and calendar-operations.ts.
10
+ *
11
+ * Op semantics (anti-n8n choices):
12
+ * - delete = move to trash (recoverable for 30 days), NOT permanent erase
13
+ * - upload / download stream via the api Files / R2 layer, never load
14
+ * full file contents into memory (n8n breaks past ~70MB)
15
+ * - download returns a `_file` ref so downstream FileTransform / AI /
16
+ * HTTP nodes can chain on it directly (n8n returns raw binary, often
17
+ * misformatted as HTML on errors)
18
+ */
19
+ export const DRIVE_OPERATIONS = [
20
+ 'upload', // upload a file (from _file ref or inline content)
21
+ 'download', // download a file → _file ref
22
+ 'copy', // duplicate a file in place or to another folder
23
+ 'move', // relocate a file to a different folder
24
+ 'delete', // trash a file (recoverable; permanent erase is opt-in)
25
+ 'share', // grant viewer/commenter/editor permission to email/domain/anyone
26
+ 'update', // rename or set metadata (description, starred, etc.)
27
+ 'list', // search by name / mimeType / parent / query → iterable output
28
+ 'get', // get metadata for one file
29
+ 'createFolder', // create a new folder (with optional parent)
30
+ 'export', // export Google native doc → PDF / DOCX / XLSX / etc.
31
+ 'getPermissions', // list current permissions on a file
32
+ ];
33
+ /** Type guard — useful when validating untrusted input (DTOs, tool calls). */
34
+ export function isDriveOperation(value) {
35
+ return typeof value === 'string' && DRIVE_OPERATIONS.includes(value);
36
+ }
37
+ /* Fábricas de los campos que se repiten, para que un cambio de copy no haya
38
+ que perseguirlo por doce operaciones. */
39
+ const fileId = () => ({
40
+ name: 'fileId',
41
+ label: 'Drive File',
42
+ type: 'driveFile',
43
+ required: true,
44
+ description: 'Pick a file from Drive or paste a templated value like {{payload.driveFileId}}.',
45
+ });
46
+ const parentFolderId = () => ({
47
+ name: 'parentFolderId',
48
+ label: 'Parent Folder ID (override)',
49
+ type: 'template',
50
+ advanced: true,
51
+ placeholder: 'Empty = use Default Folder above',
52
+ description: "Folder id used for this operation only. Leave empty to use the action's Default Folder. Templates work — e.g. {{payload.folderId}}.",
53
+ });
54
+ /** El filtro por tipo de upload/list. En `export` el mismo `mimeType` es otra
55
+ cosa y se declara aparte. */
56
+ const mimeTypeFilter = () => ({
57
+ name: 'mimeType',
58
+ label: 'File type filter (optional)',
59
+ type: 'mimeSelect',
60
+ description: 'Restrict the operation to files of this type. Leave as "Any" to match every file.',
61
+ });
62
+ const ORDER_BY_OPTIONS = [
63
+ { value: 'modifiedTime desc', label: 'Modified time (newest first)' },
64
+ { value: 'modifiedTime', label: 'Modified time (oldest first)' },
65
+ { value: 'createdTime desc', label: 'Created time (newest first)' },
66
+ { value: 'createdTime', label: 'Created time (oldest first)' },
67
+ { value: 'name', label: 'Name (A→Z)' },
68
+ { value: 'name desc', label: 'Name (Z→A)' },
69
+ ];
70
+ const EXPORT_FORMAT_OPTIONS = [
71
+ { value: 'application/pdf', label: 'PDF (.pdf)' },
72
+ {
73
+ value: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
74
+ label: 'Word (.docx) — for Google Docs',
75
+ },
76
+ {
77
+ value: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
78
+ label: 'Excel (.xlsx) — for Google Sheets',
79
+ },
80
+ {
81
+ value: 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
82
+ label: 'PowerPoint (.pptx) — for Google Slides',
83
+ },
84
+ { value: 'text/plain', label: 'Plain text (.txt)' },
85
+ { value: 'text/csv', label: 'CSV (.csv) — for Google Sheets' },
86
+ { value: 'text/html', label: 'HTML (.html)' },
87
+ ];
88
+ export const DRIVE_OPERATION_SPECS = {
89
+ upload: {
90
+ label: 'Upload File',
91
+ description: 'Stream a file from a payload _file ref into Drive',
92
+ apiMethod: 'files.create',
93
+ params: [
94
+ {
95
+ name: 'fileName',
96
+ label: 'Destination File Name',
97
+ type: 'template',
98
+ placeholder: '{{payload.name}} — leave blank to use _file.originalName',
99
+ },
100
+ {
101
+ name: 'sourceField',
102
+ label: 'Source Field (payload path)',
103
+ type: 'template',
104
+ placeholder: '_file',
105
+ default: '_file',
106
+ description: 'Where the _file ref lives in the incoming payload. Default _file. For nested refs use a dotted path (e.g. doc if upstream is { doc: { _file: ... } }).',
107
+ },
108
+ mimeTypeFilter(),
109
+ parentFolderId(),
110
+ ],
111
+ },
112
+ download: {
113
+ label: 'Download File',
114
+ description: 'Fetch a Drive file → payload _file ref for downstream nodes',
115
+ apiMethod: 'files.get (alt=media)',
116
+ params: [fileId()],
117
+ },
118
+ list: {
119
+ label: 'List / Search',
120
+ description: 'List or search files (iterable output)',
121
+ apiMethod: 'files.list',
122
+ params: [
123
+ {
124
+ name: 'query',
125
+ label: 'Search Query',
126
+ type: 'template',
127
+ placeholder: 'Substring to match against file names — empty = list all',
128
+ },
129
+ mimeTypeFilter(),
130
+ {
131
+ name: 'pageSize',
132
+ label: 'Max Results',
133
+ type: 'number',
134
+ min: 1,
135
+ max: 100,
136
+ default: 50,
137
+ description: 'Up to 100 per call. Output is iterable — downstream nodes process each file independently.',
138
+ },
139
+ {
140
+ name: 'orderBy',
141
+ label: 'Order By',
142
+ type: 'select',
143
+ default: 'modifiedTime desc',
144
+ options: ORDER_BY_OPTIONS,
145
+ },
146
+ parentFolderId(),
147
+ { name: 'recursive', label: 'Search subfolders too', type: 'switchCard', advanced: true },
148
+ {
149
+ name: 'subfolderIds',
150
+ label: 'Limit to specific subfolders',
151
+ type: 'driveSubfolders',
152
+ advanced: true,
153
+ showWhen: { field: 'recursive', in: ['true'] },
154
+ },
155
+ {
156
+ name: 'downloadResults',
157
+ label: 'Auto-download matching files',
158
+ type: 'switchCard',
159
+ advanced: true,
160
+ },
161
+ ],
162
+ },
163
+ get: {
164
+ label: 'Get Metadata',
165
+ description: 'Read metadata for one file (no bytes)',
166
+ apiMethod: 'files.get',
167
+ params: [fileId()],
168
+ },
169
+ copy: {
170
+ label: 'Copy File',
171
+ description: 'Duplicate a file, optionally rename and/or move',
172
+ apiMethod: 'files.copy',
173
+ params: [
174
+ fileId(),
175
+ {
176
+ name: 'newName',
177
+ label: 'New File Name',
178
+ type: 'template',
179
+ placeholder: "Optional — defaults to 'Copy of <original>'",
180
+ },
181
+ parentFolderId(),
182
+ ],
183
+ },
184
+ move: {
185
+ label: 'Move File',
186
+ description: 'Move a file to a different folder',
187
+ apiMethod: 'files.update (addParents / removeParents)',
188
+ params: [fileId(), parentFolderId()],
189
+ },
190
+ delete: {
191
+ label: 'Delete (Trash)',
192
+ description: 'Move to trash — recoverable for 30 days',
193
+ apiMethod: 'files.update (trashed) / files.delete when permanent',
194
+ params: [
195
+ fileId(),
196
+ {
197
+ name: 'permanent',
198
+ label: 'Delete Permanently?',
199
+ type: 'booleanSelect',
200
+ options: [
201
+ { value: '', label: 'No — move to trash (recoverable)' },
202
+ { value: 'true', label: '⚠️ Yes — erase forever (irreversible)' },
203
+ ],
204
+ },
205
+ ],
206
+ },
207
+ share: {
208
+ label: 'Share File',
209
+ description: 'Grant viewer / commenter / editor permission',
210
+ apiMethod: 'permissions.create',
211
+ params: [
212
+ fileId(),
213
+ {
214
+ name: 'type',
215
+ label: 'Share With',
216
+ type: 'select',
217
+ default: 'user',
218
+ options: [
219
+ { value: 'user', label: 'Specific user (email)' },
220
+ { value: 'group', label: 'Group (email)' },
221
+ { value: 'domain', label: 'Entire domain' },
222
+ { value: 'anyone', label: '⚠️ Anyone with the link (public)' },
223
+ ],
224
+ },
225
+ {
226
+ name: 'role',
227
+ label: 'Permission Role',
228
+ type: 'select',
229
+ default: 'reader',
230
+ options: [
231
+ { value: 'reader', label: 'Viewer (read-only)' },
232
+ { value: 'commenter', label: 'Commenter' },
233
+ { value: 'writer', label: 'Editor' },
234
+ ],
235
+ },
236
+ {
237
+ name: 'emailAddress',
238
+ label: 'Email Address',
239
+ type: 'template',
240
+ placeholder: 'user@example.com or {{payload.email}}',
241
+ showWhen: { field: 'type', in: ['user', 'group'] },
242
+ },
243
+ {
244
+ name: 'domain',
245
+ label: 'Domain',
246
+ type: 'template',
247
+ placeholder: 'example.com',
248
+ showWhen: { field: 'type', in: ['domain'] },
249
+ },
250
+ {
251
+ name: 'sendNotificationEmail',
252
+ label: 'Notify Recipient',
253
+ type: 'booleanSelect',
254
+ options: [
255
+ { value: '', label: "No — don't send email" },
256
+ { value: 'true', label: 'Yes — send share notification email' },
257
+ ],
258
+ },
259
+ ],
260
+ },
261
+ update: {
262
+ label: 'Update Metadata',
263
+ description: 'Rename, set description, or star/unstar',
264
+ apiMethod: 'files.update',
265
+ params: [
266
+ fileId(),
267
+ { name: 'name', label: 'New Name', type: 'template', placeholder: '{{payload.title}}' },
268
+ {
269
+ name: 'description',
270
+ label: 'Description (optional)',
271
+ type: 'template',
272
+ placeholder: '{{payload.description}}',
273
+ },
274
+ {
275
+ name: 'starred',
276
+ label: 'Starred (optional)',
277
+ type: 'booleanSelect',
278
+ options: [
279
+ { value: '', label: "— don't change —" },
280
+ { value: 'true', label: '⭐ Star' },
281
+ { value: 'false', label: 'Un-star' },
282
+ ],
283
+ },
284
+ ],
285
+ },
286
+ createFolder: {
287
+ label: 'Create Folder',
288
+ description: 'Create a new folder, optionally inside a parent',
289
+ apiMethod: 'files.create (folder mimeType)',
290
+ params: [
291
+ /* Mismo `name` que en update, con otra etiqueta y otro placeholder: por
292
+ eso los params son por operación y no un registro global de campos. */
293
+ { name: 'name', label: 'Folder Name', type: 'template', placeholder: 'Reports' },
294
+ parentFolderId(),
295
+ ],
296
+ },
297
+ export: {
298
+ label: 'Export Google Doc',
299
+ description: 'Export a Doc / Sheet / Slide to PDF / DOCX / XLSX',
300
+ apiMethod: 'files.export',
301
+ params: [
302
+ fileId(),
303
+ {
304
+ name: 'mimeType',
305
+ label: 'Export Format',
306
+ type: 'select',
307
+ default: 'application/pdf',
308
+ options: EXPORT_FORMAT_OPTIONS,
309
+ description: 'Export only works on Google native docs (Docs, Sheets, Slides, Drawings). For regular files use Download instead.',
310
+ },
311
+ ],
312
+ },
313
+ getPermissions: {
314
+ label: 'List Permissions',
315
+ description: 'List who has access (audit before changing)',
316
+ apiMethod: 'permissions.list',
317
+ params: [fileId()],
318
+ },
319
+ };
@@ -0,0 +1,54 @@
1
+ /**
2
+ * Drive AI Toolkit — las herramientas que un driveAction expone cuando
3
+ * `aiEnabled` está encendido.
4
+ *
5
+ * **Se escribe una sola vez**, como el de Sheets y el de Telegram. Antes vivía
6
+ * TRES veces, y las tres a mano:
7
+ *
8
+ * 1. `dashboard/components/drive-actions/drive-operations-schemas.ts`
9
+ * 2. `api/src/mcp-servers/toolkit-specs.ts`
10
+ * 3. la página de detalle, que pintaba las doce herramientas como doce
11
+ * `<li>` escritos a mano, con el número `12` también a mano en tres sitios
12
+ *
13
+ * La 1 y la 2 no habían derivado todavía (medido el 2026-08-10: cero
14
+ * diferencias, al contrario que Slack con 13 y WhatsApp con 4). Esto es lo que
15
+ * hace que sigan sin derivar.
16
+ *
17
+ * El ORDEN de este array importa: `AiToolkitPreview` pinta el encabezado de
18
+ * grupo sólo cuando cambia respecto a la fila anterior, así que las
19
+ * herramientas del mismo grupo tienen que ir seguidas. Los tres grupos son los
20
+ * que ya inventaba el JSX que sustituye.
21
+ */
22
+ import type { DriveOperation } from './drive-operations.js';
23
+ export interface DriveToolkitParameter {
24
+ name: string;
25
+ type: 'string' | 'number' | 'boolean';
26
+ description: string;
27
+ required: boolean;
28
+ }
29
+ export interface DriveToolkitSpec {
30
+ operation: DriveOperation;
31
+ /** Etiqueta corta de la fila en la lista de herramientas. */
32
+ label: string;
33
+ /**
34
+ * Nombre con el que el LLM llama a la herramienta. Todas llevan `_drive_` o
35
+ * `_to_drive` para no chocar con las de Gmail, Sheets o Calendar cuando un
36
+ * mismo AI Node tiene varios toolkits encendidos.
37
+ */
38
+ toolName: string;
39
+ /** Descripción (más reglas de uso) que ve el LLM. */
40
+ description: string;
41
+ parameters: DriveToolkitParameter[];
42
+ /** Encabezado de grupo de la página de detalle. El orden es el que agrupa. */
43
+ group?: string;
44
+ /**
45
+ * Marca que la herramienta cambia algo difícil de deshacer, para que la página
46
+ * lo enseñe y el AI Node pida confirmación. Son **dos**, las mismas que ya
47
+ * estaban marcadas: `delete_drive_file` y `share_drive_file`. `move` no lo
48
+ * lleva, y es defendible — deshacerlo es otro move.
49
+ */
50
+ destructive?: boolean;
51
+ }
52
+ export declare const DRIVE_TOOLKIT_SPECS: DriveToolkitSpec[];
53
+ /** Índice por nombre de herramienta, para enrutar un `tools/call` sin recorrer. */
54
+ export declare const DRIVE_TOOLKIT_BY_TOOL_NAME: Record<string, DriveToolkitSpec>;