@bubblelab/bubble-core 0.1.106 → 0.1.109

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 (76) hide show
  1. package/dist/bubble-bundle.d.ts +129 -52
  2. package/dist/bubbles/service-bubble/ai-agent.d.ts +55 -4
  3. package/dist/bubbles/service-bubble/ai-agent.d.ts.map +1 -1
  4. package/dist/bubbles/service-bubble/ai-agent.js +122 -0
  5. package/dist/bubbles/service-bubble/ai-agent.js.map +1 -1
  6. package/dist/bubbles/service-bubble/airtable.d.ts.map +1 -1
  7. package/dist/bubbles/service-bubble/airtable.js +8 -4
  8. package/dist/bubbles/service-bubble/airtable.js.map +1 -1
  9. package/dist/bubbles/service-bubble/apify/actors/instagram-hashtag-scraper.d.ts +2 -2
  10. package/dist/bubbles/service-bubble/apify/actors/instagram-scraper.d.ts +8 -8
  11. package/dist/bubbles/service-bubble/apify/actors/linkedin-posts-search.d.ts +4 -4
  12. package/dist/bubbles/service-bubble/apify/actors/linkedin-profile-posts.d.ts +14 -14
  13. package/dist/bubbles/service-bubble/apify/actors/twitter-scraper.d.ts +6 -6
  14. package/dist/bubbles/service-bubble/apify/actors/youtube-scraper.d.ts +6 -6
  15. package/dist/bubbles/service-bubble/apify/apify-scraper.schema.d.ts +30 -30
  16. package/dist/bubbles/service-bubble/apify/apify.d.ts +4 -4
  17. package/dist/bubbles/service-bubble/browserbase/browserbase.d.ts +1 -1
  18. package/dist/bubbles/service-bubble/browserbase/browserbase.schema.d.ts +1 -1
  19. package/dist/bubbles/service-bubble/crustdata/crustdata.d.ts +8 -8
  20. package/dist/bubbles/service-bubble/crustdata/crustdata.schema.d.ts +16 -16
  21. package/dist/bubbles/service-bubble/firecrawl.d.ts +10 -10
  22. package/dist/bubbles/service-bubble/gmail.d.ts +84 -84
  23. package/dist/bubbles/service-bubble/google-drive.d.ts +32 -32
  24. package/dist/bubbles/service-bubble/http.d.ts +2 -2
  25. package/dist/bubbles/service-bubble/jira/jira.d.ts +16 -16
  26. package/dist/bubbles/service-bubble/jira/jira.schema.d.ts +18 -18
  27. package/dist/bubbles/service-bubble/notion/notion.d.ts +24 -24
  28. package/dist/bubbles/service-bubble/notion/property-schemas.d.ts +8 -8
  29. package/dist/bubbles/service-bubble/resend.d.ts +4 -4
  30. package/dist/bubbles/service-bubble/slack/slack.d.ts +96 -96
  31. package/dist/bubbles/service-bubble/stripe/stripe.d.ts +22 -22
  32. package/dist/bubbles/service-bubble/stripe/stripe.schema.d.ts +26 -26
  33. package/dist/bubbles/tool-bubble/amazon-shopping-tool/amazon-shopping-tool.d.ts +4 -4
  34. package/dist/bubbles/tool-bubble/amazon-shopping-tool/amazon-shopping-tool.schema.d.ts +6 -6
  35. package/dist/bubbles/tool-bubble/linkedin-tool.d.ts +74 -74
  36. package/dist/bubbles/tool-bubble/tiktok-tool.d.ts +8 -8
  37. package/dist/bubbles/tool-bubble/twitter-tool.d.ts +38 -38
  38. package/dist/bubbles/tool-bubble/yc-scraper-tool.d.ts +8 -8
  39. package/dist/bubbles/tool-bubble/youtube-tool.d.ts +10 -10
  40. package/dist/bubbles/workflow-bubble/pdf-form-operations.workflow.d.ts +8 -8
  41. package/dist/bubbles/workflow-bubble/pdf-ocr.workflow.d.ts +16 -16
  42. package/dist/bubbles/workflow-bubble/slack-formatter-agent.d.ts +16 -16
  43. package/dist/bubbles.json +51 -6
  44. package/dist/capabilities/define-capability.d.ts +53 -0
  45. package/dist/capabilities/define-capability.d.ts.map +1 -0
  46. package/dist/capabilities/define-capability.js +50 -0
  47. package/dist/capabilities/define-capability.js.map +1 -0
  48. package/dist/capabilities/index.d.ts +3 -0
  49. package/dist/capabilities/index.d.ts.map +1 -0
  50. package/dist/capabilities/index.js +3 -0
  51. package/dist/capabilities/index.js.map +1 -0
  52. package/dist/capabilities/registry.d.ts +13 -0
  53. package/dist/capabilities/registry.d.ts.map +1 -0
  54. package/dist/capabilities/registry.js +26 -0
  55. package/dist/capabilities/registry.js.map +1 -0
  56. package/dist/index.d.ts +1 -0
  57. package/dist/index.d.ts.map +1 -1
  58. package/dist/index.js +2 -0
  59. package/dist/index.js.map +1 -1
  60. package/package.json +2 -2
  61. package/dist/bubbles/service-bubble/salesforce/index.d.ts +0 -4
  62. package/dist/bubbles/service-bubble/salesforce/index.d.ts.map +0 -1
  63. package/dist/bubbles/service-bubble/salesforce/index.js +0 -4
  64. package/dist/bubbles/service-bubble/salesforce/index.js.map +0 -1
  65. package/dist/bubbles/service-bubble/salesforce/salesforce.d.ts +0 -1331
  66. package/dist/bubbles/service-bubble/salesforce/salesforce.d.ts.map +0 -1
  67. package/dist/bubbles/service-bubble/salesforce/salesforce.js +0 -618
  68. package/dist/bubbles/service-bubble/salesforce/salesforce.js.map +0 -1
  69. package/dist/bubbles/service-bubble/salesforce/salesforce.schema.d.ts +0 -1445
  70. package/dist/bubbles/service-bubble/salesforce/salesforce.schema.d.ts.map +0 -1
  71. package/dist/bubbles/service-bubble/salesforce/salesforce.schema.js +0 -609
  72. package/dist/bubbles/service-bubble/salesforce/salesforce.schema.js.map +0 -1
  73. package/dist/bubbles/service-bubble/salesforce/salesforce.utils.d.ts +0 -87
  74. package/dist/bubbles/service-bubble/salesforce/salesforce.utils.d.ts.map +0 -1
  75. package/dist/bubbles/service-bubble/salesforce/salesforce.utils.js +0 -181
  76. package/dist/bubbles/service-bubble/salesforce/salesforce.utils.js.map +0 -1
@@ -195,12 +195,12 @@ declare const PDFOcrWorkflowResultSchema: z.ZodDiscriminatedUnion<"mode", [z.Zod
195
195
  fieldName: z.ZodString;
196
196
  confidence: z.ZodNumber;
197
197
  }, "strip", z.ZodTypeAny, {
198
- id: number;
199
198
  fieldName: string;
199
+ id: number;
200
200
  confidence: number;
201
201
  }, {
202
- id: number;
203
202
  fieldName: string;
203
+ id: number;
204
204
  confidence: number;
205
205
  }>, "many">;
206
206
  discoveryData: z.ZodObject<{
@@ -258,8 +258,8 @@ declare const PDFOcrWorkflowResultSchema: z.ZodDiscriminatedUnion<"mode", [z.Zod
258
258
  convertedPages: number;
259
259
  };
260
260
  extractedFields: {
261
- id: number;
262
261
  fieldName: string;
262
+ id: number;
263
263
  confidence: number;
264
264
  }[];
265
265
  discoveryData: {
@@ -283,8 +283,8 @@ declare const PDFOcrWorkflowResultSchema: z.ZodDiscriminatedUnion<"mode", [z.Zod
283
283
  convertedPages: number;
284
284
  };
285
285
  extractedFields: {
286
- id: number;
287
286
  fieldName: string;
287
+ id: number;
288
288
  confidence: number;
289
289
  }[];
290
290
  discoveryData: {
@@ -307,14 +307,14 @@ declare const PDFOcrWorkflowResultSchema: z.ZodDiscriminatedUnion<"mode", [z.Zod
307
307
  confidence: z.ZodNumber;
308
308
  }, "strip", z.ZodTypeAny, {
309
309
  value: string;
310
- id: number;
311
310
  fieldName: string;
311
+ id: number;
312
312
  confidence: number;
313
313
  originalFieldName?: string | undefined;
314
314
  }, {
315
315
  value: string;
316
- id: number;
317
316
  fieldName: string;
317
+ id: number;
318
318
  confidence: number;
319
319
  originalFieldName?: string | undefined;
320
320
  }>, "many">;
@@ -386,8 +386,8 @@ declare const PDFOcrWorkflowResultSchema: z.ZodDiscriminatedUnion<"mode", [z.Zod
386
386
  };
387
387
  extractedFields: {
388
388
  value: string;
389
- id: number;
390
389
  fieldName: string;
390
+ id: number;
391
391
  confidence: number;
392
392
  originalFieldName?: string | undefined;
393
393
  }[];
@@ -418,8 +418,8 @@ declare const PDFOcrWorkflowResultSchema: z.ZodDiscriminatedUnion<"mode", [z.Zod
418
418
  };
419
419
  extractedFields: {
420
420
  value: string;
421
- id: number;
422
421
  fieldName: string;
422
+ id: number;
423
423
  confidence: number;
424
424
  originalFieldName?: string | undefined;
425
425
  }[];
@@ -628,12 +628,12 @@ export declare class PDFOcrWorkflow<T extends PDFOcrWorkflowParams = PDFOcrWorkf
628
628
  fieldName: z.ZodString;
629
629
  confidence: z.ZodNumber;
630
630
  }, "strip", z.ZodTypeAny, {
631
- id: number;
632
631
  fieldName: string;
632
+ id: number;
633
633
  confidence: number;
634
634
  }, {
635
- id: number;
636
635
  fieldName: string;
636
+ id: number;
637
637
  confidence: number;
638
638
  }>, "many">;
639
639
  discoveryData: z.ZodObject<{
@@ -691,8 +691,8 @@ export declare class PDFOcrWorkflow<T extends PDFOcrWorkflowParams = PDFOcrWorkf
691
691
  convertedPages: number;
692
692
  };
693
693
  extractedFields: {
694
- id: number;
695
694
  fieldName: string;
695
+ id: number;
696
696
  confidence: number;
697
697
  }[];
698
698
  discoveryData: {
@@ -716,8 +716,8 @@ export declare class PDFOcrWorkflow<T extends PDFOcrWorkflowParams = PDFOcrWorkf
716
716
  convertedPages: number;
717
717
  };
718
718
  extractedFields: {
719
- id: number;
720
719
  fieldName: string;
720
+ id: number;
721
721
  confidence: number;
722
722
  }[];
723
723
  discoveryData: {
@@ -740,14 +740,14 @@ export declare class PDFOcrWorkflow<T extends PDFOcrWorkflowParams = PDFOcrWorkf
740
740
  confidence: z.ZodNumber;
741
741
  }, "strip", z.ZodTypeAny, {
742
742
  value: string;
743
- id: number;
744
743
  fieldName: string;
744
+ id: number;
745
745
  confidence: number;
746
746
  originalFieldName?: string | undefined;
747
747
  }, {
748
748
  value: string;
749
- id: number;
750
749
  fieldName: string;
750
+ id: number;
751
751
  confidence: number;
752
752
  originalFieldName?: string | undefined;
753
753
  }>, "many">;
@@ -819,8 +819,8 @@ export declare class PDFOcrWorkflow<T extends PDFOcrWorkflowParams = PDFOcrWorkf
819
819
  };
820
820
  extractedFields: {
821
821
  value: string;
822
- id: number;
823
822
  fieldName: string;
823
+ id: number;
824
824
  confidence: number;
825
825
  originalFieldName?: string | undefined;
826
826
  }[];
@@ -851,8 +851,8 @@ export declare class PDFOcrWorkflow<T extends PDFOcrWorkflowParams = PDFOcrWorkf
851
851
  };
852
852
  extractedFields: {
853
853
  value: string;
854
- id: number;
855
854
  fieldName: string;
855
+ id: number;
856
856
  confidence: number;
857
857
  originalFieldName?: string | undefined;
858
858
  }[];
@@ -154,12 +154,13 @@ declare const SlackFormatterAgentResultSchema: z.ZodObject<{
154
154
  verbatim?: boolean | undefined;
155
155
  }>, "many">>;
156
156
  }, "strip", z.ZodTypeAny, {
157
- type: "input" | "image" | "file" | "section" | "header" | "divider" | "context" | "actions";
157
+ type: "image" | "input" | "file" | "section" | "divider" | "header" | "context" | "actions";
158
158
  title?: {
159
159
  type: "plain_text";
160
160
  text: string;
161
161
  emoji?: boolean | undefined;
162
162
  } | undefined;
163
+ optional?: boolean | undefined;
163
164
  text?: {
164
165
  type: "plain_text" | "mrkdwn";
165
166
  text: string;
@@ -167,7 +168,6 @@ declare const SlackFormatterAgentResultSchema: z.ZodObject<{
167
168
  verbatim?: boolean | undefined;
168
169
  } | undefined;
169
170
  image_url?: string | undefined;
170
- optional?: boolean | undefined;
171
171
  fields?: {
172
172
  type: "plain_text" | "mrkdwn";
173
173
  text: string;
@@ -187,12 +187,13 @@ declare const SlackFormatterAgentResultSchema: z.ZodObject<{
187
187
  label?: unknown;
188
188
  hint?: unknown;
189
189
  }, {
190
- type: "input" | "image" | "file" | "section" | "header" | "divider" | "context" | "actions";
190
+ type: "image" | "input" | "file" | "section" | "divider" | "header" | "context" | "actions";
191
191
  title?: {
192
192
  type: "plain_text";
193
193
  text: string;
194
194
  emoji?: boolean | undefined;
195
195
  } | undefined;
196
+ optional?: boolean | undefined;
196
197
  text?: {
197
198
  type: "plain_text" | "mrkdwn";
198
199
  text: string;
@@ -200,7 +201,6 @@ declare const SlackFormatterAgentResultSchema: z.ZodObject<{
200
201
  verbatim?: boolean | undefined;
201
202
  } | undefined;
202
203
  image_url?: string | undefined;
203
- optional?: boolean | undefined;
204
204
  fields?: {
205
205
  type: "plain_text" | "mrkdwn";
206
206
  text: string;
@@ -269,12 +269,13 @@ declare const SlackFormatterAgentResultSchema: z.ZodObject<{
269
269
  output?: unknown;
270
270
  }[] | undefined;
271
271
  blocks?: {
272
- type: "input" | "image" | "file" | "section" | "header" | "divider" | "context" | "actions";
272
+ type: "image" | "input" | "file" | "section" | "divider" | "header" | "context" | "actions";
273
273
  title?: {
274
274
  type: "plain_text";
275
275
  text: string;
276
276
  emoji?: boolean | undefined;
277
277
  } | undefined;
278
+ optional?: boolean | undefined;
278
279
  text?: {
279
280
  type: "plain_text" | "mrkdwn";
280
281
  text: string;
@@ -282,7 +283,6 @@ declare const SlackFormatterAgentResultSchema: z.ZodObject<{
282
283
  verbatim?: boolean | undefined;
283
284
  } | undefined;
284
285
  image_url?: string | undefined;
285
- optional?: boolean | undefined;
286
286
  fields?: {
287
287
  type: "plain_text" | "mrkdwn";
288
288
  text: string;
@@ -319,12 +319,13 @@ declare const SlackFormatterAgentResultSchema: z.ZodObject<{
319
319
  output?: unknown;
320
320
  }[] | undefined;
321
321
  blocks?: {
322
- type: "input" | "image" | "file" | "section" | "header" | "divider" | "context" | "actions";
322
+ type: "image" | "input" | "file" | "section" | "divider" | "header" | "context" | "actions";
323
323
  title?: {
324
324
  type: "plain_text";
325
325
  text: string;
326
326
  emoji?: boolean | undefined;
327
327
  } | undefined;
328
+ optional?: boolean | undefined;
328
329
  text?: {
329
330
  type: "plain_text" | "mrkdwn";
330
331
  text: string;
@@ -332,7 +333,6 @@ declare const SlackFormatterAgentResultSchema: z.ZodObject<{
332
333
  verbatim?: boolean | undefined;
333
334
  } | undefined;
334
335
  image_url?: string | undefined;
335
- optional?: boolean | undefined;
336
336
  fields?: {
337
337
  type: "plain_text" | "mrkdwn";
338
338
  text: string;
@@ -512,12 +512,13 @@ export declare class SlackFormatterAgentBubble extends WorkflowBubble<SlackForma
512
512
  verbatim?: boolean | undefined;
513
513
  }>, "many">>;
514
514
  }, "strip", z.ZodTypeAny, {
515
- type: "input" | "image" | "file" | "section" | "header" | "divider" | "context" | "actions";
515
+ type: "image" | "input" | "file" | "section" | "divider" | "header" | "context" | "actions";
516
516
  title?: {
517
517
  type: "plain_text";
518
518
  text: string;
519
519
  emoji?: boolean | undefined;
520
520
  } | undefined;
521
+ optional?: boolean | undefined;
521
522
  text?: {
522
523
  type: "plain_text" | "mrkdwn";
523
524
  text: string;
@@ -525,7 +526,6 @@ export declare class SlackFormatterAgentBubble extends WorkflowBubble<SlackForma
525
526
  verbatim?: boolean | undefined;
526
527
  } | undefined;
527
528
  image_url?: string | undefined;
528
- optional?: boolean | undefined;
529
529
  fields?: {
530
530
  type: "plain_text" | "mrkdwn";
531
531
  text: string;
@@ -545,12 +545,13 @@ export declare class SlackFormatterAgentBubble extends WorkflowBubble<SlackForma
545
545
  label?: unknown;
546
546
  hint?: unknown;
547
547
  }, {
548
- type: "input" | "image" | "file" | "section" | "header" | "divider" | "context" | "actions";
548
+ type: "image" | "input" | "file" | "section" | "divider" | "header" | "context" | "actions";
549
549
  title?: {
550
550
  type: "plain_text";
551
551
  text: string;
552
552
  emoji?: boolean | undefined;
553
553
  } | undefined;
554
+ optional?: boolean | undefined;
554
555
  text?: {
555
556
  type: "plain_text" | "mrkdwn";
556
557
  text: string;
@@ -558,7 +559,6 @@ export declare class SlackFormatterAgentBubble extends WorkflowBubble<SlackForma
558
559
  verbatim?: boolean | undefined;
559
560
  } | undefined;
560
561
  image_url?: string | undefined;
561
- optional?: boolean | undefined;
562
562
  fields?: {
563
563
  type: "plain_text" | "mrkdwn";
564
564
  text: string;
@@ -627,12 +627,13 @@ export declare class SlackFormatterAgentBubble extends WorkflowBubble<SlackForma
627
627
  output?: unknown;
628
628
  }[] | undefined;
629
629
  blocks?: {
630
- type: "input" | "image" | "file" | "section" | "header" | "divider" | "context" | "actions";
630
+ type: "image" | "input" | "file" | "section" | "divider" | "header" | "context" | "actions";
631
631
  title?: {
632
632
  type: "plain_text";
633
633
  text: string;
634
634
  emoji?: boolean | undefined;
635
635
  } | undefined;
636
+ optional?: boolean | undefined;
636
637
  text?: {
637
638
  type: "plain_text" | "mrkdwn";
638
639
  text: string;
@@ -640,7 +641,6 @@ export declare class SlackFormatterAgentBubble extends WorkflowBubble<SlackForma
640
641
  verbatim?: boolean | undefined;
641
642
  } | undefined;
642
643
  image_url?: string | undefined;
643
- optional?: boolean | undefined;
644
644
  fields?: {
645
645
  type: "plain_text" | "mrkdwn";
646
646
  text: string;
@@ -677,12 +677,13 @@ export declare class SlackFormatterAgentBubble extends WorkflowBubble<SlackForma
677
677
  output?: unknown;
678
678
  }[] | undefined;
679
679
  blocks?: {
680
- type: "input" | "image" | "file" | "section" | "header" | "divider" | "context" | "actions";
680
+ type: "image" | "input" | "file" | "section" | "divider" | "header" | "context" | "actions";
681
681
  title?: {
682
682
  type: "plain_text";
683
683
  text: string;
684
684
  emoji?: boolean | undefined;
685
685
  } | undefined;
686
+ optional?: boolean | undefined;
686
687
  text?: {
687
688
  type: "plain_text" | "mrkdwn";
688
689
  text: string;
@@ -690,7 +691,6 @@ export declare class SlackFormatterAgentBubble extends WorkflowBubble<SlackForma
690
691
  verbatim?: boolean | undefined;
691
692
  } | undefined;
692
693
  image_url?: string | undefined;
693
- optional?: boolean | undefined;
694
694
  fields?: {
695
695
  type: "plain_text" | "mrkdwn";
696
696
  text: string;
package/dist/bubbles.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "version": "2.0.0",
3
- "generatedAt": "2026-02-06T01:34:34.710Z",
3
+ "generatedAt": "2026-02-06T10:24:31.616Z",
4
4
  "totalCount": 60,
5
5
  "bubbles": [
6
6
  {
@@ -453,6 +453,51 @@
453
453
  "default": false,
454
454
  "description": "Enable real-time streaming of tokens, tool calls, and iteration progress"
455
455
  },
456
+ "capabilities": {
457
+ "type": "array",
458
+ "items": {
459
+ "type": "object",
460
+ "properties": {
461
+ "id": {
462
+ "type": "string",
463
+ "minLength": 1,
464
+ "description": "Capability ID (e.g., \"google-doc-knowledge-base\")"
465
+ },
466
+ "inputs": {
467
+ "type": "object",
468
+ "additionalProperties": {
469
+ "anyOf": [
470
+ {
471
+ "type": "string"
472
+ },
473
+ {
474
+ "type": "number"
475
+ },
476
+ {
477
+ "type": "boolean"
478
+ }
479
+ ]
480
+ },
481
+ "default": {},
482
+ "description": "Input parameter values for this capability"
483
+ },
484
+ "credentials": {
485
+ "type": "object",
486
+ "additionalProperties": {
487
+ "type": "string"
488
+ },
489
+ "default": {},
490
+ "description": "Capability-specific credentials (injected at runtime)"
491
+ }
492
+ },
493
+ "required": [
494
+ "id"
495
+ ],
496
+ "additionalProperties": false
497
+ },
498
+ "default": [],
499
+ "description": "Capabilities that extend the agent with bundled tools, prompts, and credentials. Example: [{ id: \"google-doc-knowledge-base\", inputs: { docId: \"your-doc-id\" } }]"
500
+ },
456
501
  "expectedOutputSchema": {
457
502
  "anyOf": [
458
503
  {},
@@ -529,7 +574,7 @@
529
574
  ],
530
575
  "additionalProperties": false
531
576
  },
532
- "usageExample": "// Example usage of ai-agent bubble\nconst aiAgent = new AIAgentBubble({\n message: \"example string\", // The message or question to send to the AI agent,\n images: [{ type: \"base64\" // default, data: \"example string\", mimeType: \"image/png\" // default, description: \"example string\" }] // example for array, // Array of base64 encoded images to include with the message (for multimodal AI models). Example: [{type: \"base64\", data: \"base64...\", mimeType: \"image/png\", description: \"A beautiful image of a cat\"}] or [{type: \"url\", url: \"https://example.com/image.png\", description: \"A beautiful image of a cat\"}],\n conversationHistory: [{ role: \"user\" // options: \"user\", \"assistant\", \"tool\" // The role of the message sender, content: \"example string\" // The message content, toolCallId: \"example string\" // Tool call ID for tool messages, name: \"example string\" // Tool name for tool messages }], // Previous conversation messages for multi-turn conversations. When provided, messages are sent as separate turns to enable KV cache optimization. Format: [{role: \"user\", content: \"...\"}, {role: \"assistant\", content: \"...\"}, ...],\n systemPrompt: \"You are a helpful AI assistant\" // default, // System prompt that defines the AI agents behavior and personality,\n name: \"AI Agent\" // default, // A friendly name for the AI agent,\n model: { model: \"openai/gpt-5\" // options: \"openai/gpt-5\", \"openai/gpt-5-mini\", \"openai/gpt-5.1\", \"openai/gpt-5.2\", \"google/gemini-2.5-pro\", \"google/gemini-2.5-flash\", \"google/gemini-2.5-flash-lite\", \"google/gemini-2.5-flash-image-preview\", \"google/gemini-3-pro-preview\", \"google/gemini-3-pro-image-preview\", \"google/gemini-3-flash-preview\", \"anthropic/claude-sonnet-4-5\", \"anthropic/claude-opus-4-5\", \"anthropic/claude-haiku-4-5\", \"openrouter/x-ai/grok-code-fast-1\", \"openrouter/z-ai/glm-4.6\", \"openrouter/z-ai/glm-4.7\", \"openrouter/anthropic/claude-sonnet-4.5\", \"openrouter/anthropic/claude-opus-4.5\", \"openrouter/google/gemini-3-pro-preview\", \"openrouter/morph/morph-v3-large\", \"openrouter/openai/gpt-oss-120b\", \"openrouter/openai/o3-deep-research\", \"openrouter/openai/o4-mini-deep-research\" // AI model to use (format: provider/model-name)., temperature: 1 // default // Temperature for response randomness (0 = deterministic, 2 = very random), maxTokens: 64000 // default // Maximum number of tokens to generate in response, keep at default of 40000 unless the response is expected to be certain length, reasoningEffort: \"low\" // options: \"low\", \"medium\", \"high\" // Reasoning effort for model. If not specified, uses primary model reasoningEffort., maxRetries: 3 // default // Maximum number of retries for API calls (default: 3). Useful for handling transient errors like 503 Service Unavailable., provider: [\"example string\"] // Providers for ai agent (open router only)., jsonMode: false // default // When true, returns clean JSON response, you must provide the exact JSON schema in the system prompt, backupModel: { model: \"openai/gpt-5\" // options: \"openai/gpt-5\", \"openai/gpt-5-mini\", \"openai/gpt-5.1\", \"openai/gpt-5.2\", \"google/gemini-2.5-pro\", \"google/gemini-2.5-flash\", \"google/gemini-2.5-flash-lite\", \"google/gemini-2.5-flash-image-preview\", \"google/gemini-3-pro-preview\", \"google/gemini-3-pro-image-preview\", \"google/gemini-3-flash-preview\", \"anthropic/claude-sonnet-4-5\", \"anthropic/claude-opus-4-5\", \"anthropic/claude-haiku-4-5\", \"openrouter/x-ai/grok-code-fast-1\", \"openrouter/z-ai/glm-4.6\", \"openrouter/z-ai/glm-4.7\", \"openrouter/anthropic/claude-sonnet-4.5\", \"openrouter/anthropic/claude-opus-4.5\", \"openrouter/google/gemini-3-pro-preview\", \"openrouter/morph/morph-v3-large\", \"openrouter/openai/gpt-oss-120b\", \"openrouter/openai/o3-deep-research\", \"openrouter/openai/o4-mini-deep-research\" // Backup AI model to use if the primary model fails (format: provider/model-name)., temperature: 42 // Temperature for backup model. If not specified, uses primary model temperature., maxTokens: 42 // Max tokens for backup model. If not specified, uses primary model maxTokens., reasoningEffort: \"low\" // options: \"low\", \"medium\", \"high\" // Reasoning effort for backup model. If not specified, uses primary model reasoningEffort., maxRetries: 42 // Max retries for backup model. If not specified, uses primary model maxRetries. } // structure // Backup model configuration to use if the primary model fails. } // structure, // AI model configuration including provider, temperature, and tokens, retries, and json mode. Always include this.,\n tools: [{ name: \"web-search-tool\" // options: \"web-search-tool\", \"web-scrape-tool\", \"web-crawl-tool\", \"web-extract-tool\", \"research-agent-tool\", \"reddit-scrape-tool\", \"instagram-tool\", \"list-bubbles-tool\", \"get-bubble-details-tool\", \"get-trigger-detail-tool\", \"bubbleflow-validation-tool\", \"code-edit-tool\", \"chart-js-tool\", \"amazon-shopping-tool\", \"linkedin-tool\", \"tiktok-tool\", \"twitter-tool\", \"google-maps-tool\", \"youtube-tool\", \"people-search-tool\", \"sql-query-tool\" // Name of the tool type or tool bubble to enable for the AI agent, config: {} // Configuration for the tool or tool bubble }] // example for array, // Array of pre-registered tools the AI agent can use. Can be tool types (web-search-tool, web-scrape-tool, web-crawl-tool, web-extract-tool, instagram-tool). If using image models, set the tools to [],\n customTools: [{ name: \"example string\" // Unique name for your custom tool (e.g., \"calculate-tax\"), description: \"example string\" // Description of what the tool does - helps the AI know when to use it, schema: {} // Zod schema object defining the tool parameters. Can be either a plain object (e.g., { amount: z.number() }) or a Zod object directly (e.g., z.object({ amount: z.number() })). }] // example for array, // Array of custom runtime-defined tools with their own schemas and functions. Use this to add domain-specific tools without pre-registration. Example: [{ name: \"calculate-tax\", description: \"Calculates sales tax\", schema: { amount: z.number() }, func: async (input) => {...} }],\n maxIterations: 40 // default, // Maximum number of iterations for the agent workflow, 5 iterations per turn of conversation,\n streaming: false // default, // Enable real-time streaming of tokens, tool calls, and iteration progress,\n expectedOutputSchema: \"example string\", // Zod schema or JSON schema string that defines the expected structure of the AI response. When provided, automatically enables JSON mode and instructs the AI to output in the exact format. Example: z.object({ summary: z.string(), items: z.array(z.object({ name: z.string(), score: z.number() })) }),\n});\n\nconst result = await aiAgent.action();\n\n// Always check success status before using data\nif (!result.success) {\n throw new Error(`${metadata.name} failed: ${result.error}`);\n}\n\n// outputSchema for result.data:\n// {\n// response: string // The AI agents final response to the user message. For text responses, returns plain text. If JSON mode is enabled, returns a JSON string. For image generation models (like gemini-2.5-flash-image-preview), returns base64-encoded image data with data URI format (data:image/png;base64,...),\n// reasoning: string | null | undefined // The reasoning/thinking tokens from the model (if available). Present for deep research models and reasoning models.,\n// toolCalls: { tool: string // Name of the tool that was called, input: unknown // Input parameters passed to the tool, output: unknown // Output returned by the tool }[] // Array of tool calls made during the conversation,\n// iterations: number // Number of back-and-forth iterations in the agent workflow,\n// totalCost: number | undefined // Total cost in USD for this request (includes tokens + web search for deep research models),\n// error: string // Error message of the run, undefined if successful,\n// success: boolean // Whether the agent execution completed successfully\n// }\n\n// Access the actual data\nconst actualData = result.data;\nconsole.log(actualData);",
577
+ "usageExample": "// Example usage of ai-agent bubble\nconst aiAgent = new AIAgentBubble({\n message: \"example string\", // The message or question to send to the AI agent,\n images: [{ type: \"base64\" // default, data: \"example string\", mimeType: \"image/png\" // default, description: \"example string\" }] // example for array, // Array of base64 encoded images to include with the message (for multimodal AI models). Example: [{type: \"base64\", data: \"base64...\", mimeType: \"image/png\", description: \"A beautiful image of a cat\"}] or [{type: \"url\", url: \"https://example.com/image.png\", description: \"A beautiful image of a cat\"}],\n conversationHistory: [{ role: \"user\" // options: \"user\", \"assistant\", \"tool\" // The role of the message sender, content: \"example string\" // The message content, toolCallId: \"example string\" // Tool call ID for tool messages, name: \"example string\" // Tool name for tool messages }], // Previous conversation messages for multi-turn conversations. When provided, messages are sent as separate turns to enable KV cache optimization. Format: [{role: \"user\", content: \"...\"}, {role: \"assistant\", content: \"...\"}, ...],\n systemPrompt: \"You are a helpful AI assistant\" // default, // System prompt that defines the AI agents behavior and personality,\n name: \"AI Agent\" // default, // A friendly name for the AI agent,\n model: { model: \"openai/gpt-5\" // options: \"openai/gpt-5\", \"openai/gpt-5-mini\", \"openai/gpt-5.1\", \"openai/gpt-5.2\", \"google/gemini-2.5-pro\", \"google/gemini-2.5-flash\", \"google/gemini-2.5-flash-lite\", \"google/gemini-2.5-flash-image-preview\", \"google/gemini-3-pro-preview\", \"google/gemini-3-pro-image-preview\", \"google/gemini-3-flash-preview\", \"anthropic/claude-sonnet-4-5\", \"anthropic/claude-opus-4-5\", \"anthropic/claude-haiku-4-5\", \"openrouter/x-ai/grok-code-fast-1\", \"openrouter/z-ai/glm-4.6\", \"openrouter/z-ai/glm-4.7\", \"openrouter/anthropic/claude-sonnet-4.5\", \"openrouter/anthropic/claude-opus-4.5\", \"openrouter/google/gemini-3-pro-preview\", \"openrouter/morph/morph-v3-large\", \"openrouter/openai/gpt-oss-120b\", \"openrouter/openai/o3-deep-research\", \"openrouter/openai/o4-mini-deep-research\" // AI model to use (format: provider/model-name)., temperature: 1 // default // Temperature for response randomness (0 = deterministic, 2 = very random), maxTokens: 64000 // default // Maximum number of tokens to generate in response, keep at default of 40000 unless the response is expected to be certain length, reasoningEffort: \"low\" // options: \"low\", \"medium\", \"high\" // Reasoning effort for model. If not specified, uses primary model reasoningEffort., maxRetries: 3 // default // Maximum number of retries for API calls (default: 3). Useful for handling transient errors like 503 Service Unavailable., provider: [\"example string\"] // Providers for ai agent (open router only)., jsonMode: false // default // When true, returns clean JSON response, you must provide the exact JSON schema in the system prompt, backupModel: { model: \"openai/gpt-5\" // options: \"openai/gpt-5\", \"openai/gpt-5-mini\", \"openai/gpt-5.1\", \"openai/gpt-5.2\", \"google/gemini-2.5-pro\", \"google/gemini-2.5-flash\", \"google/gemini-2.5-flash-lite\", \"google/gemini-2.5-flash-image-preview\", \"google/gemini-3-pro-preview\", \"google/gemini-3-pro-image-preview\", \"google/gemini-3-flash-preview\", \"anthropic/claude-sonnet-4-5\", \"anthropic/claude-opus-4-5\", \"anthropic/claude-haiku-4-5\", \"openrouter/x-ai/grok-code-fast-1\", \"openrouter/z-ai/glm-4.6\", \"openrouter/z-ai/glm-4.7\", \"openrouter/anthropic/claude-sonnet-4.5\", \"openrouter/anthropic/claude-opus-4.5\", \"openrouter/google/gemini-3-pro-preview\", \"openrouter/morph/morph-v3-large\", \"openrouter/openai/gpt-oss-120b\", \"openrouter/openai/o3-deep-research\", \"openrouter/openai/o4-mini-deep-research\" // Backup AI model to use if the primary model fails (format: provider/model-name)., temperature: 42 // Temperature for backup model. If not specified, uses primary model temperature., maxTokens: 42 // Max tokens for backup model. If not specified, uses primary model maxTokens., reasoningEffort: \"low\" // options: \"low\", \"medium\", \"high\" // Reasoning effort for backup model. If not specified, uses primary model reasoningEffort., maxRetries: 42 // Max retries for backup model. If not specified, uses primary model maxRetries. } // structure // Backup model configuration to use if the primary model fails. } // structure, // AI model configuration including provider, temperature, and tokens, retries, and json mode. Always include this.,\n tools: [{ name: \"web-search-tool\" // options: \"web-search-tool\", \"web-scrape-tool\", \"web-crawl-tool\", \"web-extract-tool\", \"research-agent-tool\", \"reddit-scrape-tool\", \"instagram-tool\", \"list-bubbles-tool\", \"get-bubble-details-tool\", \"get-trigger-detail-tool\", \"bubbleflow-validation-tool\", \"code-edit-tool\", \"chart-js-tool\", \"amazon-shopping-tool\", \"linkedin-tool\", \"tiktok-tool\", \"twitter-tool\", \"google-maps-tool\", \"youtube-tool\", \"people-search-tool\", \"sql-query-tool\" // Name of the tool type or tool bubble to enable for the AI agent, config: {} // Configuration for the tool or tool bubble }] // example for array, // Array of pre-registered tools the AI agent can use. Can be tool types (web-search-tool, web-scrape-tool, web-crawl-tool, web-extract-tool, instagram-tool). If using image models, set the tools to [],\n customTools: [{ name: \"example string\" // Unique name for your custom tool (e.g., \"calculate-tax\"), description: \"example string\" // Description of what the tool does - helps the AI know when to use it, schema: {} // Zod schema object defining the tool parameters. Can be either a plain object (e.g., { amount: z.number() }) or a Zod object directly (e.g., z.object({ amount: z.number() })). }] // example for array, // Array of custom runtime-defined tools with their own schemas and functions. Use this to add domain-specific tools without pre-registration. Example: [{ name: \"calculate-tax\", description: \"Calculates sales tax\", schema: { amount: z.number() }, func: async (input) => {...} }],\n maxIterations: 40 // default, // Maximum number of iterations for the agent workflow, 5 iterations per turn of conversation,\n streaming: false // default, // Enable real-time streaming of tokens, tool calls, and iteration progress,\n capabilities: [{ id: \"example string\" // Capability ID (e.g., \"google-doc-knowledge-base\"), inputs: { \"example_key\": \"example string\" } // structure // Input parameter values for this capability }] // example for array, // Capabilities that extend the agent with bundled tools, prompts, and credentials. Example: [{ id: \"google-doc-knowledge-base\", inputs: { docId: \"your-doc-id\" } }],\n expectedOutputSchema: \"example string\", // Zod schema or JSON schema string that defines the expected structure of the AI response. When provided, automatically enables JSON mode and instructs the AI to output in the exact format. Example: z.object({ summary: z.string(), items: z.array(z.object({ name: z.string(), score: z.number() })) }),\n});\n\nconst result = await aiAgent.action();\n\n// Always check success status before using data\nif (!result.success) {\n throw new Error(`${metadata.name} failed: ${result.error}`);\n}\n\n// outputSchema for result.data:\n// {\n// response: string // The AI agents final response to the user message. For text responses, returns plain text. If JSON mode is enabled, returns a JSON string. For image generation models (like gemini-2.5-flash-image-preview), returns base64-encoded image data with data URI format (data:image/png;base64,...),\n// reasoning: string | null | undefined // The reasoning/thinking tokens from the model (if available). Present for deep research models and reasoning models.,\n// toolCalls: { tool: string // Name of the tool that was called, input: unknown // Input parameters passed to the tool, output: unknown // Output returned by the tool }[] // Array of tool calls made during the conversation,\n// iterations: number // Number of back-and-forth iterations in the agent workflow,\n// totalCost: number | undefined // Total cost in USD for this request (includes tokens + web search for deep research models),\n// error: string // Error message of the run, undefined if successful,\n// success: boolean // Whether the agent execution completed successfully\n// }\n\n// Access the actual data\nconst actualData = result.data;\nconsole.log(actualData);",
533
578
  "requiredCredentials": [
534
579
  "OPENAI_CRED",
535
580
  "GOOGLE_GEMINI_CRED",
@@ -39951,15 +39996,15 @@
39951
39996
  "string"
39952
39997
  ],
39953
39998
  "default": "json",
39954
- "description": "Format for cell values: json (structured) or string (formatted)"
39999
+ "description": "Format for cell values: json (structured) or string (formatted). When using \"string\", timeZone and userLocale are required by the Airtable API (defaults to UTC/en-US if omitted)"
39955
40000
  },
39956
40001
  "timeZone": {
39957
40002
  "type": "string",
39958
- "description": "Time zone for date/time fields (e.g., \"America/Los_Angeles\")"
40003
+ "description": "Time zone for date/time fields (e.g., \"America/Los_Angeles\"). Required when cellFormat is \"string\", defaults to \"UTC\""
39959
40004
  },
39960
40005
  "userLocale": {
39961
40006
  "type": "string",
39962
- "description": "Locale for formatting (e.g., \"en-US\")"
40007
+ "description": "Locale for formatting (e.g., \"en-US\"). Required when cellFormat is \"string\", defaults to \"en-US\""
39963
40008
  },
39964
40009
  "offset": {
39965
40010
  "type": "string",
@@ -41477,7 +41522,7 @@
41477
41522
  }
41478
41523
  ]
41479
41524
  },
41480
- "usageExample": "// List Records example\nconst airtable_list_records = new AirtableBubble({\n operation: \"list_records\", // List records from an Airtable table with filtering and sorting\n baseId: \"example string\", // Airtable base ID (e.g., appXXXXXXXXXXXXXX)\n tableIdOrName: \"example string\", // Table ID (e.g., tblXXXXXXXXXXXXXX) or table name\n fields: [\"example string\"], // Array of field names to include in results (returns all fields if not specified)\n filterByFormula: \"example string\", // Airtable formula to filter records (e.g., \"{Status} = 'Done'\")\n maxRecords: 42, // Maximum number of records to return (1-100, returns all if not specified)\n pageSize: 100 // default, // Number of records per page for pagination (1-100)\n sort: [{ field: \"example string\" // Field name to sort by, direction: \"asc\" // options: \"asc\", \"desc\" // Sort direction (asc or desc) }], // Array of sort specifications to order records\n view: \"example string\", // View name or ID to use (includes view's filters and sorts)\n cellFormat: \"json\" // options: \"json\", \"string\", // Format for cell values: json (structured) or string (formatted)\n timeZone: \"example string\", // Time zone for date/time fields (e.g., \"America/Los_Angeles\")\n userLocale: \"example string\", // Locale for formatting (e.g., \"en-US\")\n offset: \"example string\", // Pagination offset from previous response\n});\n\nconst result = await airtable_list_records.action();\n// outputSchema for result.data when operation === 'list_records':\n// {\n// operation: \"list_records\" // List records from an Airtable table with filtering and sorting,\n// ok: boolean // Whether the Airtable API call was successful,\n// records: { id: string // Unique record identifier (starts with rec), createdTime: string // ISO 8601 datetime when record was created, fields: Record<string, unknown> // Record field values as key-value pairs }[] | undefined // Array of record objects,\n// offset: string | undefined // Pagination offset for retrieving next page of results,\n// error: string // Error message if operation failed,\n// success: boolean // Whether the operation was successful\n// }\n\n\n// Get Record example\nconst airtable_get_record = new AirtableBubble({\n operation: \"get_record\", // Retrieve a single record by its ID\n baseId: \"example string\", // Airtable base ID (e.g., appXXXXXXXXXXXXXX)\n tableIdOrName: \"example string\", // Table ID (e.g., tblXXXXXXXXXXXXXX) or table name\n recordId: \"example string\", // Record ID to retrieve (starts with rec)\n});\n\nconst result = await airtable_get_record.action();\n// outputSchema for result.data when operation === 'get_record':\n// {\n// operation: \"get_record\" // Retrieve a single record by its ID,\n// ok: boolean // Whether the Airtable API call was successful,\n// record: { id: string // Unique record identifier (starts with rec), createdTime: string // ISO 8601 datetime when record was created, fields: Record<string, unknown> // Record field values as key-value pairs } | undefined // Record object,\n// error: string // Error message if operation failed,\n// success: boolean // Whether the operation was successful\n// }\n\n\n// Create Records example\nconst airtable_create_records = new AirtableBubble({\n operation: \"create_records\", // Create one or more new records in an Airtable table\n baseId: \"example string\", // Airtable base ID (e.g., appXXXXXXXXXXXXXX)\n tableIdOrName: \"example string\", // Table ID (e.g., tblXXXXXXXXXXXXXX) or table name\n records: [{ fields: { \"example_key\": [] } // Field values for the new record }], // Array of records to create (max 10 per request)\n typecast: false // default, // Automatically convert field values to the appropriate type\n});\n\nconst result = await airtable_create_records.action();\n// outputSchema for result.data when operation === 'create_records':\n// {\n// operation: \"create_records\" // Create one or more new records in an Airtable table,\n// ok: boolean // Whether the Airtable API call was successful,\n// records: { id: string // Unique record identifier (starts with rec), createdTime: string // ISO 8601 datetime when record was created, fields: Record<string, unknown> // Record field values as key-value pairs }[] | undefined // Array of created record objects,\n// error: string // Error message if operation failed,\n// success: boolean // Whether the operation was successful\n// }\n\n\n// Update Records example\nconst airtable_update_records = new AirtableBubble({\n operation: \"update_records\", // Update existing records in an Airtable table\n baseId: \"example string\", // Airtable base ID (e.g., appXXXXXXXXXXXXXX)\n tableIdOrName: \"example string\", // Table ID (e.g., tblXXXXXXXXXXXXXX) or table name\n records: [{ id: \"example string\" // Record ID to update (starts with rec), fields: { \"example_key\": [] } // Field values to update (only specified fields will be updated) }], // Array of records to update (max 10 per request)\n typecast: false // default, // Automatically convert field values to the appropriate type\n});\n\nconst result = await airtable_update_records.action();\n// outputSchema for result.data when operation === 'update_records':\n// {\n// operation: \"update_records\" // Update existing records in an Airtable table,\n// ok: boolean // Whether the Airtable API call was successful,\n// records: { id: string // Unique record identifier (starts with rec), createdTime: string // ISO 8601 datetime when record was created, fields: Record<string, unknown> // Record field values as key-value pairs }[] | undefined // Array of updated record objects,\n// error: string // Error message if operation failed,\n// success: boolean // Whether the operation was successful\n// }\n\n\n// Delete Records example\nconst airtable_delete_records = new AirtableBubble({\n operation: \"delete_records\", // Delete one or more records from an Airtable table\n baseId: \"example string\", // Airtable base ID (e.g., appXXXXXXXXXXXXXX)\n tableIdOrName: \"example string\", // Table ID (e.g., tblXXXXXXXXXXXXXX) or table name\n recordIds: [\"example string\"], // Array of record IDs to delete (max 10 per request)\n});\n\nconst result = await airtable_delete_records.action();\n// outputSchema for result.data when operation === 'delete_records':\n// {\n// operation: \"delete_records\" // Delete one or more records from an Airtable table,\n// ok: boolean // Whether the Airtable API call was successful,\n// records: { id: string // ID of deleted record, deleted: boolean // Whether the record was deleted }[] | undefined // Array of deletion confirmation objects,\n// error: string // Error message if operation failed,\n// success: boolean // Whether the operation was successful\n// }\n\n\n// List Bases example\nconst airtable_list_bases = new AirtableBubble({\n operation: \"list_bases\", // List all bases accessible with the current API key\n});\n\nconst result = await airtable_list_bases.action();\n// outputSchema for result.data when operation === 'list_bases':\n// {\n// operation: \"list_bases\" // List all bases accessible with the current API key,\n// ok: boolean // Whether the Airtable API call was successful,\n// bases: { id: string // Base ID, name: string // Base name, permissionLevel: string // Permission level for this base }[] | undefined // Array of base objects,\n// error: string // Error message if operation failed,\n// success: boolean // Whether the operation was successful\n// }\n\n\n// Get Base Schema example\nconst airtable_get_base_schema = new AirtableBubble({\n operation: \"get_base_schema\", // Get the schema for a specific base including all tables and fields\n baseId: \"example string\", // Airtable base ID (e.g., appXXXXXXXXXXXXXX)\n});\n\nconst result = await airtable_get_base_schema.action();\n// outputSchema for result.data when operation === 'get_base_schema':\n// {\n// operation: \"get_base_schema\" // Get the schema for a specific base including all tables and fields,\n// ok: boolean // Whether the Airtable API call was successful,\n// tables: { id: string // Table ID, name: string // Table name, description: string | undefined // Table description, primaryFieldId: string // ID of the primary field, fields: { id: string // Field ID, name: string // Field name, type: string // Field type, description: string | undefined // Field description, options: Record<string, unknown> | undefined // Field options }[] // Array of field definitions, views: { id: string // View ID, name: string // View name, type: string // View type }[] | undefined // Array of view definitions }[] | undefined // Array of table schemas,\n// error: string // Error message if operation failed,\n// success: boolean // Whether the operation was successful\n// }\n\n\n// Create Table example\nconst airtable_create_table = new AirtableBubble({\n operation: \"create_table\", // Create a new table in an Airtable base\n baseId: \"example string\", // Airtable base ID (e.g., appXXXXXXXXXXXXXX)\n name: \"example string\", // Name for the new table\n description: \"example string\", // Optional description for the table\n fields: [{ name: \"example string\" // Field name, type: \"singleLineText\" // options: \"singleLineText\", \"multilineText\", \"richText\", \"email\", \"url\", \"phoneNumber\", \"number\", \"percent\", \"currency\", \"rating\", \"duration\", \"singleSelect\", \"multipleSelects\", \"singleCollaborator\", \"multipleCollaborators\", \"date\", \"dateTime\", \"checkbox\", \"multipleRecordLinks\", \"multipleAttachments\", \"barcode\", \"button\", \"formula\", \"createdTime\", \"lastModifiedTime\", \"createdBy\", \"lastModifiedBy\", \"autoNumber\", \"externalSyncSource\", \"count\", \"lookup\", \"rollup\" // Field type, description: \"example string\" // Field description, options: {} // Field options }], // Array of field definitions for the table\n});\n\nconst result = await airtable_create_table.action();\n// outputSchema for result.data when operation === 'create_table':\n// {\n// operation: \"create_table\" // Create a new table in an Airtable base,\n// ok: boolean // Whether the Airtable API call was successful,\n// table: { id: string // Table ID, name: string // Table name, description: string | undefined // Table description, primaryFieldId: string // ID of the primary field, fields: { id: string // Field ID, name: string // Field name, type: \"singleLineText\" | \"multilineText\" | \"richText\" | \"email\" | \"url\" | \"phoneNumber\" | \"number\" | \"percent\" | \"currency\" | \"rating\" | \"duration\" | \"singleSelect\" | \"multipleSelects\" | \"singleCollaborator\" | \"multipleCollaborators\" | \"date\" | \"dateTime\" | \"checkbox\" | \"multipleRecordLinks\" | \"multipleAttachments\" | \"barcode\" | \"button\" | \"formula\" | \"createdTime\" | \"lastModifiedTime\" | \"createdBy\" | \"lastModifiedBy\" | \"autoNumber\" | \"externalSyncSource\" | \"count\" | \"lookup\" | \"rollup\" // Field type }[] // Array of field definitions } | undefined // Created table object,\n// error: string // Error message if operation failed,\n// success: boolean // Whether the operation was successful\n// }\n\n\n// Update Table example\nconst airtable_update_table = new AirtableBubble({\n operation: \"update_table\", // Update table properties like name and description\n baseId: \"example string\", // Airtable base ID (e.g., appXXXXXXXXXXXXXX)\n tableIdOrName: \"example string\", // Table ID (e.g., tblXXXXXXXXXXXXXX) or table name\n name: \"example string\", // New name for the table\n description: \"example string\", // New description for the table\n});\n\nconst result = await airtable_update_table.action();\n// outputSchema for result.data when operation === 'update_table':\n// {\n// operation: \"update_table\" // Update table properties like name and description,\n// ok: boolean // Whether the Airtable API call was successful,\n// table: { id: string // Table ID, name: string // Table name, description: string | undefined // Table description } | undefined // Updated table object,\n// error: string // Error message if operation failed,\n// success: boolean // Whether the operation was successful\n// }\n\n\n// Create Field example\nconst airtable_create_field = new AirtableBubble({\n operation: \"create_field\", // Create a new field in an Airtable table\n baseId: \"example string\", // Airtable base ID (e.g., appXXXXXXXXXXXXXX)\n tableIdOrName: \"example string\", // Table ID (e.g., tblXXXXXXXXXXXXXX) or table name\n name: \"example string\", // Name for the new field\n type: \"singleLineText\" // options: \"singleLineText\", \"multilineText\", \"richText\", \"email\", \"url\", \"phoneNumber\", \"number\", \"percent\", \"currency\", \"rating\", \"duration\", \"singleSelect\", \"multipleSelects\", \"singleCollaborator\", \"multipleCollaborators\", \"date\", \"dateTime\", \"checkbox\", \"multipleRecordLinks\", \"multipleAttachments\", \"barcode\", \"button\", \"formula\", \"createdTime\", \"lastModifiedTime\", \"createdBy\", \"lastModifiedBy\", \"autoNumber\", \"externalSyncSource\", \"count\", \"lookup\", \"rollup\", // Field type\n description: \"example string\", // Field description\n options: {}, // Field-specific options\n});\n\nconst result = await airtable_create_field.action();\n// outputSchema for result.data when operation === 'create_field':\n// {\n// operation: \"create_field\" // Create a new field in an Airtable table,\n// ok: boolean // Whether the Airtable API call was successful,\n// field: { id: string // Field ID, name: string // Field name, type: string // Field type, description: string | undefined // Field description } | undefined // Created field object,\n// error: string // Error message if operation failed,\n// success: boolean // Whether the operation was successful\n// }\n\n\n// Update Field example\nconst airtable_update_field = new AirtableBubble({\n operation: \"update_field\", // Update field properties like name, type, or description\n baseId: \"example string\", // Airtable base ID (e.g., appXXXXXXXXXXXXXX)\n tableIdOrName: \"example string\", // Table ID (e.g., tblXXXXXXXXXXXXXX) or table name\n fieldIdOrName: \"example string\", // Field ID (e.g., fldXXXXXXXXXXXXXX) or field name\n name: \"example string\", // New name for the field\n description: \"example string\", // New description for the field\n});\n\nconst result = await airtable_update_field.action();\n// outputSchema for result.data when operation === 'update_field':\n// {\n// operation: \"update_field\" // Update field properties like name, type, or description,\n// ok: boolean // Whether the Airtable API call was successful,\n// field: { id: string // Field ID, name: string // Field name, type: string // Field type, description: string | undefined // Field description } | undefined // Updated field object,\n// error: string // Error message if operation failed,\n// success: boolean // Whether the operation was successful\n// }\n\n\n// Always check success status before using data\nif (!result.success) {\n throw new Error(`airtable failed: ${result.error}`);\n}\n\n// Access the actual data\nconst actualData = result.data;\nconsole.log(actualData);",
41525
+ "usageExample": "// List Records example\nconst airtable_list_records = new AirtableBubble({\n operation: \"list_records\", // List records from an Airtable table with filtering and sorting\n baseId: \"example string\", // Airtable base ID (e.g., appXXXXXXXXXXXXXX)\n tableIdOrName: \"example string\", // Table ID (e.g., tblXXXXXXXXXXXXXX) or table name\n fields: [\"example string\"], // Array of field names to include in results (returns all fields if not specified)\n filterByFormula: \"example string\", // Airtable formula to filter records (e.g., \"{Status} = 'Done'\")\n maxRecords: 42, // Maximum number of records to return (1-100, returns all if not specified)\n pageSize: 100 // default, // Number of records per page for pagination (1-100)\n sort: [{ field: \"example string\" // Field name to sort by, direction: \"asc\" // options: \"asc\", \"desc\" // Sort direction (asc or desc) }], // Array of sort specifications to order records\n view: \"example string\", // View name or ID to use (includes view's filters and sorts)\n cellFormat: \"json\" // options: \"json\", \"string\", // Format for cell values: json (structured) or string (formatted). When using \"string\", timeZone and userLocale are required by the Airtable API (defaults to UTC/en-US if omitted)\n timeZone: \"example string\", // Time zone for date/time fields (e.g., \"America/Los_Angeles\"). Required when cellFormat is \"string\", defaults to \"UTC\"\n userLocale: \"example string\", // Locale for formatting (e.g., \"en-US\"). Required when cellFormat is \"string\", defaults to \"en-US\"\n offset: \"example string\", // Pagination offset from previous response\n});\n\nconst result = await airtable_list_records.action();\n// outputSchema for result.data when operation === 'list_records':\n// {\n// operation: \"list_records\" // List records from an Airtable table with filtering and sorting,\n// ok: boolean // Whether the Airtable API call was successful,\n// records: { id: string // Unique record identifier (starts with rec), createdTime: string // ISO 8601 datetime when record was created, fields: Record<string, unknown> // Record field values as key-value pairs }[] | undefined // Array of record objects,\n// offset: string | undefined // Pagination offset for retrieving next page of results,\n// error: string // Error message if operation failed,\n// success: boolean // Whether the operation was successful\n// }\n\n\n// Get Record example\nconst airtable_get_record = new AirtableBubble({\n operation: \"get_record\", // Retrieve a single record by its ID\n baseId: \"example string\", // Airtable base ID (e.g., appXXXXXXXXXXXXXX)\n tableIdOrName: \"example string\", // Table ID (e.g., tblXXXXXXXXXXXXXX) or table name\n recordId: \"example string\", // Record ID to retrieve (starts with rec)\n});\n\nconst result = await airtable_get_record.action();\n// outputSchema for result.data when operation === 'get_record':\n// {\n// operation: \"get_record\" // Retrieve a single record by its ID,\n// ok: boolean // Whether the Airtable API call was successful,\n// record: { id: string // Unique record identifier (starts with rec), createdTime: string // ISO 8601 datetime when record was created, fields: Record<string, unknown> // Record field values as key-value pairs } | undefined // Record object,\n// error: string // Error message if operation failed,\n// success: boolean // Whether the operation was successful\n// }\n\n\n// Create Records example\nconst airtable_create_records = new AirtableBubble({\n operation: \"create_records\", // Create one or more new records in an Airtable table\n baseId: \"example string\", // Airtable base ID (e.g., appXXXXXXXXXXXXXX)\n tableIdOrName: \"example string\", // Table ID (e.g., tblXXXXXXXXXXXXXX) or table name\n records: [{ fields: { \"example_key\": [] } // Field values for the new record }], // Array of records to create (max 10 per request)\n typecast: false // default, // Automatically convert field values to the appropriate type\n});\n\nconst result = await airtable_create_records.action();\n// outputSchema for result.data when operation === 'create_records':\n// {\n// operation: \"create_records\" // Create one or more new records in an Airtable table,\n// ok: boolean // Whether the Airtable API call was successful,\n// records: { id: string // Unique record identifier (starts with rec), createdTime: string // ISO 8601 datetime when record was created, fields: Record<string, unknown> // Record field values as key-value pairs }[] | undefined // Array of created record objects,\n// error: string // Error message if operation failed,\n// success: boolean // Whether the operation was successful\n// }\n\n\n// Update Records example\nconst airtable_update_records = new AirtableBubble({\n operation: \"update_records\", // Update existing records in an Airtable table\n baseId: \"example string\", // Airtable base ID (e.g., appXXXXXXXXXXXXXX)\n tableIdOrName: \"example string\", // Table ID (e.g., tblXXXXXXXXXXXXXX) or table name\n records: [{ id: \"example string\" // Record ID to update (starts with rec), fields: { \"example_key\": [] } // Field values to update (only specified fields will be updated) }], // Array of records to update (max 10 per request)\n typecast: false // default, // Automatically convert field values to the appropriate type\n});\n\nconst result = await airtable_update_records.action();\n// outputSchema for result.data when operation === 'update_records':\n// {\n// operation: \"update_records\" // Update existing records in an Airtable table,\n// ok: boolean // Whether the Airtable API call was successful,\n// records: { id: string // Unique record identifier (starts with rec), createdTime: string // ISO 8601 datetime when record was created, fields: Record<string, unknown> // Record field values as key-value pairs }[] | undefined // Array of updated record objects,\n// error: string // Error message if operation failed,\n// success: boolean // Whether the operation was successful\n// }\n\n\n// Delete Records example\nconst airtable_delete_records = new AirtableBubble({\n operation: \"delete_records\", // Delete one or more records from an Airtable table\n baseId: \"example string\", // Airtable base ID (e.g., appXXXXXXXXXXXXXX)\n tableIdOrName: \"example string\", // Table ID (e.g., tblXXXXXXXXXXXXXX) or table name\n recordIds: [\"example string\"], // Array of record IDs to delete (max 10 per request)\n});\n\nconst result = await airtable_delete_records.action();\n// outputSchema for result.data when operation === 'delete_records':\n// {\n// operation: \"delete_records\" // Delete one or more records from an Airtable table,\n// ok: boolean // Whether the Airtable API call was successful,\n// records: { id: string // ID of deleted record, deleted: boolean // Whether the record was deleted }[] | undefined // Array of deletion confirmation objects,\n// error: string // Error message if operation failed,\n// success: boolean // Whether the operation was successful\n// }\n\n\n// List Bases example\nconst airtable_list_bases = new AirtableBubble({\n operation: \"list_bases\", // List all bases accessible with the current API key\n});\n\nconst result = await airtable_list_bases.action();\n// outputSchema for result.data when operation === 'list_bases':\n// {\n// operation: \"list_bases\" // List all bases accessible with the current API key,\n// ok: boolean // Whether the Airtable API call was successful,\n// bases: { id: string // Base ID, name: string // Base name, permissionLevel: string // Permission level for this base }[] | undefined // Array of base objects,\n// error: string // Error message if operation failed,\n// success: boolean // Whether the operation was successful\n// }\n\n\n// Get Base Schema example\nconst airtable_get_base_schema = new AirtableBubble({\n operation: \"get_base_schema\", // Get the schema for a specific base including all tables and fields\n baseId: \"example string\", // Airtable base ID (e.g., appXXXXXXXXXXXXXX)\n});\n\nconst result = await airtable_get_base_schema.action();\n// outputSchema for result.data when operation === 'get_base_schema':\n// {\n// operation: \"get_base_schema\" // Get the schema for a specific base including all tables and fields,\n// ok: boolean // Whether the Airtable API call was successful,\n// tables: { id: string // Table ID, name: string // Table name, description: string | undefined // Table description, primaryFieldId: string // ID of the primary field, fields: { id: string // Field ID, name: string // Field name, type: string // Field type, description: string | undefined // Field description, options: Record<string, unknown> | undefined // Field options }[] // Array of field definitions, views: { id: string // View ID, name: string // View name, type: string // View type }[] | undefined // Array of view definitions }[] | undefined // Array of table schemas,\n// error: string // Error message if operation failed,\n// success: boolean // Whether the operation was successful\n// }\n\n\n// Create Table example\nconst airtable_create_table = new AirtableBubble({\n operation: \"create_table\", // Create a new table in an Airtable base\n baseId: \"example string\", // Airtable base ID (e.g., appXXXXXXXXXXXXXX)\n name: \"example string\", // Name for the new table\n description: \"example string\", // Optional description for the table\n fields: [{ name: \"example string\" // Field name, type: \"singleLineText\" // options: \"singleLineText\", \"multilineText\", \"richText\", \"email\", \"url\", \"phoneNumber\", \"number\", \"percent\", \"currency\", \"rating\", \"duration\", \"singleSelect\", \"multipleSelects\", \"singleCollaborator\", \"multipleCollaborators\", \"date\", \"dateTime\", \"checkbox\", \"multipleRecordLinks\", \"multipleAttachments\", \"barcode\", \"button\", \"formula\", \"createdTime\", \"lastModifiedTime\", \"createdBy\", \"lastModifiedBy\", \"autoNumber\", \"externalSyncSource\", \"count\", \"lookup\", \"rollup\" // Field type, description: \"example string\" // Field description, options: {} // Field options }], // Array of field definitions for the table\n});\n\nconst result = await airtable_create_table.action();\n// outputSchema for result.data when operation === 'create_table':\n// {\n// operation: \"create_table\" // Create a new table in an Airtable base,\n// ok: boolean // Whether the Airtable API call was successful,\n// table: { id: string // Table ID, name: string // Table name, description: string | undefined // Table description, primaryFieldId: string // ID of the primary field, fields: { id: string // Field ID, name: string // Field name, type: \"singleLineText\" | \"multilineText\" | \"richText\" | \"email\" | \"url\" | \"phoneNumber\" | \"number\" | \"percent\" | \"currency\" | \"rating\" | \"duration\" | \"singleSelect\" | \"multipleSelects\" | \"singleCollaborator\" | \"multipleCollaborators\" | \"date\" | \"dateTime\" | \"checkbox\" | \"multipleRecordLinks\" | \"multipleAttachments\" | \"barcode\" | \"button\" | \"formula\" | \"createdTime\" | \"lastModifiedTime\" | \"createdBy\" | \"lastModifiedBy\" | \"autoNumber\" | \"externalSyncSource\" | \"count\" | \"lookup\" | \"rollup\" // Field type }[] // Array of field definitions } | undefined // Created table object,\n// error: string // Error message if operation failed,\n// success: boolean // Whether the operation was successful\n// }\n\n\n// Update Table example\nconst airtable_update_table = new AirtableBubble({\n operation: \"update_table\", // Update table properties like name and description\n baseId: \"example string\", // Airtable base ID (e.g., appXXXXXXXXXXXXXX)\n tableIdOrName: \"example string\", // Table ID (e.g., tblXXXXXXXXXXXXXX) or table name\n name: \"example string\", // New name for the table\n description: \"example string\", // New description for the table\n});\n\nconst result = await airtable_update_table.action();\n// outputSchema for result.data when operation === 'update_table':\n// {\n// operation: \"update_table\" // Update table properties like name and description,\n// ok: boolean // Whether the Airtable API call was successful,\n// table: { id: string // Table ID, name: string // Table name, description: string | undefined // Table description } | undefined // Updated table object,\n// error: string // Error message if operation failed,\n// success: boolean // Whether the operation was successful\n// }\n\n\n// Create Field example\nconst airtable_create_field = new AirtableBubble({\n operation: \"create_field\", // Create a new field in an Airtable table\n baseId: \"example string\", // Airtable base ID (e.g., appXXXXXXXXXXXXXX)\n tableIdOrName: \"example string\", // Table ID (e.g., tblXXXXXXXXXXXXXX) or table name\n name: \"example string\", // Name for the new field\n type: \"singleLineText\" // options: \"singleLineText\", \"multilineText\", \"richText\", \"email\", \"url\", \"phoneNumber\", \"number\", \"percent\", \"currency\", \"rating\", \"duration\", \"singleSelect\", \"multipleSelects\", \"singleCollaborator\", \"multipleCollaborators\", \"date\", \"dateTime\", \"checkbox\", \"multipleRecordLinks\", \"multipleAttachments\", \"barcode\", \"button\", \"formula\", \"createdTime\", \"lastModifiedTime\", \"createdBy\", \"lastModifiedBy\", \"autoNumber\", \"externalSyncSource\", \"count\", \"lookup\", \"rollup\", // Field type\n description: \"example string\", // Field description\n options: {}, // Field-specific options\n});\n\nconst result = await airtable_create_field.action();\n// outputSchema for result.data when operation === 'create_field':\n// {\n// operation: \"create_field\" // Create a new field in an Airtable table,\n// ok: boolean // Whether the Airtable API call was successful,\n// field: { id: string // Field ID, name: string // Field name, type: string // Field type, description: string | undefined // Field description } | undefined // Created field object,\n// error: string // Error message if operation failed,\n// success: boolean // Whether the operation was successful\n// }\n\n\n// Update Field example\nconst airtable_update_field = new AirtableBubble({\n operation: \"update_field\", // Update field properties like name, type, or description\n baseId: \"example string\", // Airtable base ID (e.g., appXXXXXXXXXXXXXX)\n tableIdOrName: \"example string\", // Table ID (e.g., tblXXXXXXXXXXXXXX) or table name\n fieldIdOrName: \"example string\", // Field ID (e.g., fldXXXXXXXXXXXXXX) or field name\n name: \"example string\", // New name for the field\n description: \"example string\", // New description for the field\n});\n\nconst result = await airtable_update_field.action();\n// outputSchema for result.data when operation === 'update_field':\n// {\n// operation: \"update_field\" // Update field properties like name, type, or description,\n// ok: boolean // Whether the Airtable API call was successful,\n// field: { id: string // Field ID, name: string // Field name, type: string // Field type, description: string | undefined // Field description } | undefined // Updated field object,\n// error: string // Error message if operation failed,\n// success: boolean // Whether the operation was successful\n// }\n\n\n// Always check success status before using data\nif (!result.success) {\n throw new Error(`airtable failed: ${result.error}`);\n}\n\n// Access the actual data\nconst actualData = result.data;\nconsole.log(actualData);",
41481
41526
  "requiredCredentials": [
41482
41527
  "AIRTABLE_CRED",
41483
41528
  "AIRTABLE_OAUTH"
@@ -0,0 +1,53 @@
1
+ import type { CapabilityMetadata, CapabilityInput } from '@bubblelab/shared-schemas';
2
+ import type { CredentialType } from '@bubblelab/shared-schemas';
3
+ import type { ToolHookBefore, ToolHookAfter } from '../bubbles/service-bubble/ai-agent.js';
4
+ import type { BubbleContext } from '../types/bubble.js';
5
+ import { z } from 'zod';
6
+ /** Runtime context passed to capability tool factories and system prompt factories. */
7
+ export interface CapabilityRuntimeContext {
8
+ credentials: Partial<Record<CredentialType, string>>;
9
+ inputs: Record<string, string | number | boolean>;
10
+ bubbleContext?: BubbleContext;
11
+ }
12
+ /** A single capability tool function that accepts parsed parameters and returns a result. */
13
+ export type CapabilityToolFunc = (params: Record<string, unknown>) => Promise<unknown>;
14
+ /** Factory that creates tool functions given a runtime context. */
15
+ export type CapabilityToolFactory = (context: CapabilityRuntimeContext) => Record<string, CapabilityToolFunc>;
16
+ /** Factory that creates a system prompt addition given a runtime context. */
17
+ export type CapabilitySystemPromptFactory = (context: CapabilityRuntimeContext) => string;
18
+ /** Full runtime capability definition with metadata + factories. */
19
+ export interface CapabilityDefinition {
20
+ metadata: CapabilityMetadata;
21
+ createTools: CapabilityToolFactory;
22
+ createSystemPrompt?: CapabilitySystemPromptFactory;
23
+ hooks?: {
24
+ beforeToolCall?: ToolHookBefore;
25
+ afterToolCall?: ToolHookAfter;
26
+ };
27
+ }
28
+ /** Options for the defineCapability() helper — ergonomic API for creating capabilities. */
29
+ export interface DefineCapabilityOptions {
30
+ id: string;
31
+ name: string;
32
+ description: string;
33
+ icon?: string;
34
+ category?: string;
35
+ version?: string;
36
+ requiredCredentials: CredentialType[];
37
+ inputs: CapabilityInput[];
38
+ tools: Array<{
39
+ name: string;
40
+ description: string;
41
+ schema: z.ZodObject<z.ZodRawShape>;
42
+ func: (ctx: CapabilityRuntimeContext) => CapabilityToolFunc;
43
+ }>;
44
+ systemPrompt?: string | CapabilitySystemPromptFactory;
45
+ hooks?: CapabilityDefinition['hooks'];
46
+ }
47
+ /**
48
+ * Creates a CapabilityDefinition from a user-friendly options object.
49
+ * Converts Zod schemas to JSON Schema for serializable metadata,
50
+ * and wraps tool functions with context currying.
51
+ */
52
+ export declare function defineCapability(options: DefineCapabilityOptions): CapabilityDefinition;
53
+ //# sourceMappingURL=define-capability.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"define-capability.d.ts","sourceRoot":"","sources":["../../src/capabilities/define-capability.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,kBAAkB,EAClB,eAAe,EAEhB,MAAM,2BAA2B,CAAC;AACnC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAChE,OAAO,KAAK,EACV,cAAc,EACd,aAAa,EACd,MAAM,uCAAuC,CAAC;AAC/C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,uFAAuF;AACvF,MAAM,WAAW,wBAAwB;IACvC,WAAW,EAAE,OAAO,CAAC,MAAM,CAAC,cAAc,EAAE,MAAM,CAAC,CAAC,CAAC;IACrD,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,CAAC;IAClD,aAAa,CAAC,EAAE,aAAa,CAAC;CAC/B;AAED,6FAA6F;AAC7F,MAAM,MAAM,kBAAkB,GAAG,CAC/B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAC5B,OAAO,CAAC,OAAO,CAAC,CAAC;AAEtB,mEAAmE;AACnE,MAAM,MAAM,qBAAqB,GAAG,CAClC,OAAO,EAAE,wBAAwB,KAC9B,MAAM,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAAC;AAExC,6EAA6E;AAC7E,MAAM,MAAM,6BAA6B,GAAG,CAC1C,OAAO,EAAE,wBAAwB,KAC9B,MAAM,CAAC;AAEZ,oEAAoE;AACpE,MAAM,WAAW,oBAAoB;IACnC,QAAQ,EAAE,kBAAkB,CAAC;IAC7B,WAAW,EAAE,qBAAqB,CAAC;IACnC,kBAAkB,CAAC,EAAE,6BAA6B,CAAC;IACnD,KAAK,CAAC,EAAE;QACN,cAAc,CAAC,EAAE,cAAc,CAAC;QAChC,aAAa,CAAC,EAAE,aAAa,CAAC;KAC/B,CAAC;CACH;AAED,2FAA2F;AAC3F,MAAM,WAAW,uBAAuB;IACtC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,mBAAmB,EAAE,cAAc,EAAE,CAAC;IACtC,MAAM,EAAE,eAAe,EAAE,CAAC;IAC1B,KAAK,EAAE,KAAK,CAAC;QACX,IAAI,EAAE,MAAM,CAAC;QACb,WAAW,EAAE,MAAM,CAAC;QACpB,MAAM,EAAE,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC;QACnC,IAAI,EAAE,CAAC,GAAG,EAAE,wBAAwB,KAAK,kBAAkB,CAAC;KAC7D,CAAC,CAAC;IACH,YAAY,CAAC,EAAE,MAAM,GAAG,6BAA6B,CAAC;IACtD,KAAK,CAAC,EAAE,oBAAoB,CAAC,OAAO,CAAC,CAAC;CACvC;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,uBAAuB,GAC/B,oBAAoB,CAgDtB"}