@superblocksteam/vite-plugin-file-sync 2.0.86 → 2.0.87-next.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 (163) hide show
  1. package/dist/ai-service/agent/prompts/api-prompts.d.ts +33 -0
  2. package/dist/ai-service/agent/prompts/api-prompts.d.ts.map +1 -0
  3. package/dist/ai-service/agent/prompts/api-prompts.js +446 -0
  4. package/dist/ai-service/agent/prompts/api-prompts.js.map +1 -0
  5. package/dist/ai-service/agent/prompts/build-base-system-prompt.d.ts.map +1 -1
  6. package/dist/ai-service/agent/prompts/build-base-system-prompt.js +16 -154
  7. package/dist/ai-service/agent/prompts/build-base-system-prompt.js.map +1 -1
  8. package/dist/ai-service/agent/tool-message-utils.d.ts.map +1 -1
  9. package/dist/ai-service/agent/tool-message-utils.js +13 -2
  10. package/dist/ai-service/agent/tool-message-utils.js.map +1 -1
  11. package/dist/ai-service/agent/tools/apis/analysis.d.ts.map +1 -1
  12. package/dist/ai-service/agent/tools/apis/analysis.js +159 -15
  13. package/dist/ai-service/agent/tools/apis/analysis.js.map +1 -1
  14. package/dist/ai-service/agent/tools/apis/get-api-docs.d.ts +12 -0
  15. package/dist/ai-service/agent/tools/apis/get-api-docs.d.ts.map +1 -1
  16. package/dist/ai-service/agent/tools/apis/get-api-docs.js +3 -3
  17. package/dist/ai-service/agent/tools/apis/get-api-docs.js.map +1 -1
  18. package/dist/ai-service/agent/tools/apis/get-integration-types.d.ts +12 -0
  19. package/dist/ai-service/agent/tools/apis/get-integration-types.d.ts.map +1 -0
  20. package/dist/ai-service/agent/tools/apis/get-integration-types.js +76 -0
  21. package/dist/ai-service/agent/tools/apis/get-integration-types.js.map +1 -0
  22. package/dist/ai-service/agent/tools/apis/integration-types.js +4 -4
  23. package/dist/ai-service/agent/tools/apis/integration-types.js.map +1 -1
  24. package/dist/ai-service/agent/tools/apis/test-api.d.ts.map +1 -1
  25. package/dist/ai-service/agent/tools/apis/test-api.js +5 -4
  26. package/dist/ai-service/agent/tools/apis/test-api.js.map +1 -1
  27. package/dist/ai-service/agent/tools/build-capture-screenshot.d.ts.map +1 -1
  28. package/dist/ai-service/agent/tools/build-capture-screenshot.js +23 -0
  29. package/dist/ai-service/agent/tools/build-capture-screenshot.js.map +1 -1
  30. package/dist/ai-service/agent/tools/build-debug.d.ts.map +1 -1
  31. package/dist/ai-service/agent/tools/build-debug.js +13 -1
  32. package/dist/ai-service/agent/tools/build-debug.js.map +1 -1
  33. package/dist/ai-service/agent/tools/index.d.ts +1 -0
  34. package/dist/ai-service/agent/tools/index.d.ts.map +1 -1
  35. package/dist/ai-service/agent/tools/index.js +1 -0
  36. package/dist/ai-service/agent/tools/index.js.map +1 -1
  37. package/dist/ai-service/agent/tools/integrations/execute-request.d.ts.map +1 -1
  38. package/dist/ai-service/agent/tools/integrations/execute-request.js +14 -1
  39. package/dist/ai-service/agent/tools/integrations/execute-request.js.map +1 -1
  40. package/dist/ai-service/agent/tools/integrations/internal.d.ts +1 -0
  41. package/dist/ai-service/agent/tools/integrations/internal.d.ts.map +1 -1
  42. package/dist/ai-service/agent/tools/integrations/internal.js +9 -4
  43. package/dist/ai-service/agent/tools/integrations/internal.js.map +1 -1
  44. package/dist/ai-service/agent/tools.d.ts.map +1 -1
  45. package/dist/ai-service/agent/tools.js +19 -9
  46. package/dist/ai-service/agent/tools.js.map +1 -1
  47. package/dist/ai-service/agent/tools2/tools/web-fetch.d.ts.map +1 -1
  48. package/dist/ai-service/agent/tools2/tools/web-fetch.js +7 -1
  49. package/dist/ai-service/agent/tools2/tools/web-fetch.js.map +1 -1
  50. package/dist/ai-service/agent/utils.d.ts.map +1 -1
  51. package/dist/ai-service/agent/utils.js +11 -0
  52. package/dist/ai-service/agent/utils.js.map +1 -1
  53. package/dist/ai-service/app-interface/filesystem/index.d.ts +4 -1
  54. package/dist/ai-service/app-interface/filesystem/index.d.ts.map +1 -1
  55. package/dist/ai-service/app-interface/filesystem/index.js +3 -1
  56. package/dist/ai-service/app-interface/filesystem/index.js.map +1 -1
  57. package/dist/ai-service/app-interface/filesystem/path-validator.d.ts +43 -0
  58. package/dist/ai-service/app-interface/filesystem/path-validator.d.ts.map +1 -0
  59. package/dist/ai-service/app-interface/filesystem/path-validator.js +9 -0
  60. package/dist/ai-service/app-interface/filesystem/path-validator.js.map +1 -0
  61. package/dist/ai-service/app-interface/filesystem/sdk-path-validator.d.ts +50 -0
  62. package/dist/ai-service/app-interface/filesystem/sdk-path-validator.d.ts.map +1 -0
  63. package/dist/ai-service/app-interface/filesystem/sdk-path-validator.js +68 -0
  64. package/dist/ai-service/app-interface/filesystem/sdk-path-validator.js.map +1 -0
  65. package/dist/ai-service/app-interface/filesystem/validation.d.ts +25 -8
  66. package/dist/ai-service/app-interface/filesystem/validation.d.ts.map +1 -1
  67. package/dist/ai-service/app-interface/filesystem/validation.js +52 -28
  68. package/dist/ai-service/app-interface/filesystem/validation.js.map +1 -1
  69. package/dist/ai-service/app-interface/filesystem/virtual-file-system.d.ts +1 -0
  70. package/dist/ai-service/app-interface/filesystem/virtual-file-system.d.ts.map +1 -1
  71. package/dist/ai-service/app-interface/filesystem/virtual-file-system.js +4 -1
  72. package/dist/ai-service/app-interface/filesystem/virtual-file-system.js.map +1 -1
  73. package/dist/ai-service/app-interface/filesystem/yaml-path-validator.d.ts +49 -0
  74. package/dist/ai-service/app-interface/filesystem/yaml-path-validator.d.ts.map +1 -0
  75. package/dist/ai-service/app-interface/filesystem/yaml-path-validator.js +67 -0
  76. package/dist/ai-service/app-interface/filesystem/yaml-path-validator.js.map +1 -0
  77. package/dist/ai-service/app-interface/shell.d.ts +5 -2
  78. package/dist/ai-service/app-interface/shell.d.ts.map +1 -1
  79. package/dist/ai-service/app-interface/shell.js +11 -6
  80. package/dist/ai-service/app-interface/shell.js.map +1 -1
  81. package/dist/ai-service/chat/chat-session-store.js +3 -3
  82. package/dist/ai-service/chat/chat-session-store.js.map +1 -1
  83. package/dist/ai-service/clark-provider/clark-provider.d.ts +1 -0
  84. package/dist/ai-service/clark-provider/clark-provider.d.ts.map +1 -1
  85. package/dist/ai-service/clark-provider/clark-provider.js +6 -1
  86. package/dist/ai-service/clark-provider/clark-provider.js.map +1 -1
  87. package/dist/ai-service/features.d.ts +4 -0
  88. package/dist/ai-service/features.d.ts.map +1 -1
  89. package/dist/ai-service/features.js +4 -0
  90. package/dist/ai-service/features.js.map +1 -1
  91. package/dist/ai-service/index.d.ts +16 -0
  92. package/dist/ai-service/index.d.ts.map +1 -1
  93. package/dist/ai-service/index.js +101 -10
  94. package/dist/ai-service/index.js.map +1 -1
  95. package/dist/ai-service/judge/judge-eval-service-runner.d.ts.map +1 -1
  96. package/dist/ai-service/judge/judge-eval-service-runner.js +2 -0
  97. package/dist/ai-service/judge/judge-eval-service-runner.js.map +1 -1
  98. package/dist/ai-service/llm/context-v2/context.d.ts.map +1 -1
  99. package/dist/ai-service/llm/context-v2/context.js +4 -4
  100. package/dist/ai-service/llm/context-v2/context.js.map +1 -1
  101. package/dist/ai-service/llm/context-v2/phase1-tool-summarizer.d.ts.map +1 -1
  102. package/dist/ai-service/llm/context-v2/phase1-tool-summarizer.js +11 -2
  103. package/dist/ai-service/llm/context-v2/phase1-tool-summarizer.js.map +1 -1
  104. package/dist/ai-service/llm/context-v2/prompts/compaction.d.ts +1 -1
  105. package/dist/ai-service/llm/context-v2/prompts/compaction.d.ts.map +1 -1
  106. package/dist/ai-service/llm/context-v2/prompts/compaction.js +15 -6
  107. package/dist/ai-service/llm/context-v2/prompts/compaction.js.map +1 -1
  108. package/dist/ai-service/llm/context-v2/types.d.ts +4 -9
  109. package/dist/ai-service/llm/context-v2/types.d.ts.map +1 -1
  110. package/dist/ai-service/llm/context-v2/types.js +15 -45
  111. package/dist/ai-service/llm/context-v2/types.js.map +1 -1
  112. package/dist/ai-service/llm/stream/retry-engine.d.ts +4 -0
  113. package/dist/ai-service/llm/stream/retry-engine.d.ts.map +1 -1
  114. package/dist/ai-service/llm/stream/retry-engine.js +24 -1
  115. package/dist/ai-service/llm/stream/retry-engine.js.map +1 -1
  116. package/dist/ai-service/llm/types.d.ts +4 -1
  117. package/dist/ai-service/llm/types.d.ts.map +1 -1
  118. package/dist/ai-service/skills/system/superblocks-api/references/graphql.generated.d.ts +1 -1
  119. package/dist/ai-service/skills/system/superblocks-api/references/graphql.generated.d.ts.map +1 -1
  120. package/dist/ai-service/skills/system/superblocks-api/references/graphql.generated.js +28 -21
  121. package/dist/ai-service/skills/system/superblocks-api/references/graphql.generated.js.map +1 -1
  122. package/dist/ai-service/skills/system/superblocks-api/skill.generated.d.ts +1 -1
  123. package/dist/ai-service/skills/system/superblocks-api/skill.generated.d.ts.map +1 -1
  124. package/dist/ai-service/skills/system/superblocks-api/skill.generated.js +286 -116
  125. package/dist/ai-service/skills/system/superblocks-api/skill.generated.js.map +1 -1
  126. package/dist/ai-service/state-machine/clark-fsm.d.ts +7 -0
  127. package/dist/ai-service/state-machine/clark-fsm.d.ts.map +1 -1
  128. package/dist/ai-service/state-machine/handlers/agent-planning.d.ts.map +1 -1
  129. package/dist/ai-service/state-machine/handlers/agent-planning.js +14 -12
  130. package/dist/ai-service/state-machine/handlers/agent-planning.js.map +1 -1
  131. package/dist/ai-service/state-machine/handlers/idle.d.ts.map +1 -1
  132. package/dist/ai-service/state-machine/handlers/idle.js +18 -10
  133. package/dist/ai-service/state-machine/handlers/idle.js.map +1 -1
  134. package/dist/ai-service/state-machine/helpers/peer.d.ts +5 -0
  135. package/dist/ai-service/state-machine/helpers/peer.d.ts.map +1 -1
  136. package/dist/ai-service/state-machine/helpers/peer.js +19 -0
  137. package/dist/ai-service/state-machine/helpers/peer.js.map +1 -1
  138. package/dist/ai-service/template-renderer.d.ts +2 -1
  139. package/dist/ai-service/template-renderer.d.ts.map +1 -1
  140. package/dist/ai-service/template-renderer.js +28 -3
  141. package/dist/ai-service/template-renderer.js.map +1 -1
  142. package/dist/ai-service/types.d.ts +2 -0
  143. package/dist/ai-service/types.d.ts.map +1 -1
  144. package/dist/ai-service/types.js.map +1 -1
  145. package/dist/lock-service/activity-tracker.d.ts +5 -0
  146. package/dist/lock-service/activity-tracker.d.ts.map +1 -1
  147. package/dist/lock-service/activity-tracker.js +13 -0
  148. package/dist/lock-service/activity-tracker.js.map +1 -1
  149. package/dist/lock-service/index.d.ts +8 -0
  150. package/dist/lock-service/index.d.ts.map +1 -1
  151. package/dist/lock-service/index.js +54 -0
  152. package/dist/lock-service/index.js.map +1 -1
  153. package/dist/socket-manager.d.ts.map +1 -1
  154. package/dist/socket-manager.js +9 -0
  155. package/dist/socket-manager.js.map +1 -1
  156. package/dist/sync-service/index.d.ts.map +1 -1
  157. package/dist/sync-service/index.js +40 -7
  158. package/dist/sync-service/index.js.map +1 -1
  159. package/dist/util/log-sanitizer.d.ts +1 -0
  160. package/dist/util/log-sanitizer.d.ts.map +1 -1
  161. package/dist/util/log-sanitizer.js +8 -0
  162. package/dist/util/log-sanitizer.js.map +1 -1
  163. package/package.json +22 -11
@@ -18,12 +18,14 @@ This skill covers building backend APIs using Superblocks workflow blocks, integ
18
18
  ## Mental Model
19
19
 
20
20
  APIs in Superblocks are backend logic blocks that run in a secure server environment. They:
21
+
21
22
  - Execute integrations (database queries, API calls, etc.)
22
23
  - Process data with JavaScript or Python
23
24
  - Return data to the frontend
24
25
  - **Cannot** directly modify UI state
25
26
 
26
27
  **Superblocks APIs are NOT traditional backend services.** They are frontend-coupled workflow builders that:
28
+
27
29
  - Build declarative workflows using a chain of blocks
28
30
  - Receive input parameters passed from the frontend
29
31
  - Are visualized in the Superblocks editor
@@ -65,6 +67,25 @@ export default new Api("apiName", [
65
67
 
66
68
  **🚨 CRITICAL:** Only code inside \`new Api()\` is serialized. Constants/helpers defined outside cause \`ReferenceError\` at runtime.
67
69
 
70
+ ## Getting Integration-Specific Types
71
+
72
+ **BEFORE building APIs with integrations, call the \`getIntegrationTypes\` tool** with the integration IDs you plan to use.
73
+
74
+ This tool provides dynamic, integration-specific information that cannot be included in skill files:
75
+
76
+ - TypeScript class definitions (constructor signatures, config options, methods)
77
+ - Integration-specific examples and patterns
78
+ - SQL parameterized query syntax (for database integrations, if supported)
79
+
80
+ **Example:**
81
+
82
+ \`\`\`
83
+ getIntegrationTypes({ integrationIds: ["postgres-abc123", "snowflake-xyz789"] })
84
+ \`\`\`
85
+
86
+ The core patterns in this skill file (scoping rules, control flow, best practices) apply to ALL integrations.
87
+ The \`getIntegrationTypes\` tool provides the specific TypeScript types for the integration classes you're using.
88
+
68
89
  ## 🔍 Integration Exploration Workflow (CRITICAL)
69
90
 
70
91
  When exploring integrations and data sources, use \`grepMetadata\` to understand schema before querying:
@@ -72,6 +93,7 @@ When exploring integrations and data sources, use \`grepMetadata\` to understand
72
93
  ### 1. Start with metadata exploration
73
94
 
74
95
  Use \`grepMetadata\` to understand:
96
+
75
97
  - What tables/endpoints exist
76
98
  - Schema structure and
77
99
  - Available fields and data types
@@ -86,6 +108,7 @@ Use \`grepMetadata\` to understand:
86
108
  ### 3. Database vs OpenAPI key formats
87
109
 
88
110
  **DATABASE integrations** (Postgres, MySQL, Snowflake, Databricks):
111
+
89
112
  - Use **numeric array indices**: \`[0]\`, \`[1]\`, \`[2]\`, etc.
90
113
  - Pattern: Use \`\\\\d+\` to match any number
91
114
  - Structure: All databases use \`json.dbSchema.schemas[]\` and \`json.dbSchema.tables[]\`
@@ -96,6 +119,7 @@ Use \`grepMetadata\` to understand:
96
119
  - ❌ \`"\\\\.schema\\\\.tables"\` - WRONG! It's \`dbSchema\` not \`schema\`
97
120
 
98
121
  **OPENAPI integrations** (REST APIs with OpenAPI specs):
122
+
99
123
  - Use **string object keys**: \`["/users"]\`, \`["/repos"]\`
100
124
  - Pattern: Use \`.*\` to match any key (NOT \`\\\\d+\`!)
101
125
  - Examples:
@@ -105,6 +129,7 @@ Use \`grepMetadata\` to understand:
105
129
  ### 4. REST API vs OpenAPI Selection
106
130
 
107
131
  **🚨 CRITICAL: When working with REST API integrations:**
132
+
108
133
  1. ALWAYS call \`grepMetadata\` first to determine if the REST API is OpenAPI-backed
109
134
  2. If metadata shows it's an OpenAPI-backed API, you MUST use the \`OpenApi\` class with \`openapi.path\`
110
135
  3. Only use \`RestApi\` class for non-OpenAPI REST integrations
@@ -118,38 +143,56 @@ export type Binding<T> = T | ((state: State) => T);
118
143
 
119
144
  // Control Flow Blocks
120
145
  export declare class Conditional extends Block {
121
- constructor(name: string, config: {
122
- if: { when: Binding<boolean>; then: Block[] };
123
- elif?: { when: Binding<boolean>; then: Block[] }[];
124
- else?: Block[];
125
- });
146
+ constructor(
147
+ name: string,
148
+ config: {
149
+ if: { when: Binding<boolean>; then: Block[] };
150
+ elif?: { when: Binding<boolean>; then: Block[] }[];
151
+ else?: Block[];
152
+ },
153
+ );
126
154
  }
127
155
 
128
156
  export declare class Loop extends Block {
129
- constructor(name: string, config:
130
- | { type?: "TYPE_FOREACH"; over: Binding<JsonValue[]>; variables: { item: string; index: string }; blocks: Block[] }
131
- | { type: "TYPE_WHILE"; condition: Binding<boolean>; blocks: Block[] }
157
+ constructor(
158
+ name: string,
159
+ config:
160
+ | {
161
+ type?: "TYPE_FOREACH";
162
+ over: Binding<JsonValue[]>;
163
+ variables: { item: string; index: string };
164
+ blocks: Block[];
165
+ }
166
+ | { type: "TYPE_WHILE"; condition: Binding<boolean>; blocks: Block[] },
132
167
  );
133
168
  }
134
169
 
135
170
  export declare class Parallel extends Block {
136
- constructor(name: string, config:
137
- | { mode: "dynamic"; over: Binding<JsonValue[]>; blocks: Block[] }
138
- | { mode: "static"; paths: Record<string, Block[]> }
171
+ constructor(
172
+ name: string,
173
+ config:
174
+ | { mode: "dynamic"; over: Binding<JsonValue[]>; blocks: Block[] }
175
+ | { mode: "static"; paths: Record<string, Block[]> },
139
176
  );
140
177
  }
141
178
 
142
179
  export declare class Variables extends Block {
143
- constructor(name: string, variables: { key: string; value: Binding<JsonValue> }[]);
180
+ constructor(
181
+ name: string,
182
+ variables: { key: string; value: Binding<JsonValue> }[],
183
+ );
144
184
  }
145
185
 
146
186
  export declare class TryCatch extends Block {
147
- constructor(name: string, config: {
148
- try: Block[];
149
- catch: Block[];
150
- finally?: Block[];
151
- variables: { error: string };
152
- });
187
+ constructor(
188
+ name: string,
189
+ config: {
190
+ try: Block[];
191
+ catch: Block[];
192
+ finally?: Block[];
193
+ variables: { error: string };
194
+ },
195
+ );
153
196
  }
154
197
 
155
198
  export declare class Throw extends Block {
@@ -179,12 +222,14 @@ export declare class Api {
179
222
  **CRITICAL: Blocks can only access outputs from specific scopes.**
180
223
 
181
224
  ### What blocks CAN access:
225
+
182
226
  1. **Previous sibling blocks** at the same level (executed before them)
183
227
  2. **ALL ancestor block outputs** (parent, grandparent, etc.)
184
228
  3. **Parent control flow variables** (e.g., \`item\` and \`index\` in Loop)
185
229
  4. **Control flow block outputs** (equals output of their last child block)
186
230
 
187
231
  ### What blocks CANNOT access:
232
+
188
233
  - ❌ Outputs from blocks nested inside other control flow blocks
189
234
  - ❌ Outputs from blocks in other Conditional branches
190
235
  - ❌ Outputs from blocks that come after them
@@ -193,21 +238,22 @@ export declare class Api {
193
238
 
194
239
  \`\`\`typescript
195
240
  // ✅ CORRECT: Destructure variables/blocks you need
196
- when: ({ hasMore }) => !hasMore.value
197
- over: ({ items }) => items.output
198
- condition: ({ counter }) => counter.value < 10
241
+ when: ({ hasMore }) => !hasMore.value;
242
+ over: ({ items }) => items.output;
243
+ condition: ({ counter }) => counter.value < 10;
199
244
 
200
245
  // ✅ Multiple variables in one function
201
246
  fn: ({ results, page, hasMore }) => {
202
247
  results.set([...results.value, ...newItems]);
203
248
  page.set(page.value + 1);
204
- }
249
+ };
205
250
 
206
251
  // ❌ WRONG: Single param pattern causes runtime error!
207
- when: (p) => !p.hasMore.value // TypeError!
252
+ when: (p) => !p.hasMore.value; // TypeError!
208
253
  \`\`\`
209
254
 
210
255
  **Access patterns by type:**
256
+
211
257
  - **API Inputs**: Access directly (no \`.value\`)
212
258
  - **Step Outputs**: Use \`.output\`
213
259
  - **Loop Variables**: Use \`.value\`
@@ -217,6 +263,7 @@ when: (p) => !p.hasMore.value // TypeError!
217
263
  ## Input Discovery Rules
218
264
 
219
265
  **You do NOT need to explicitly declare API inputs.** They are automatically discovered when:
266
+
220
267
  1. Destructured in block functions but not defined elsewhere
221
268
  2. Referenced but not produced by any previous block
222
269
 
@@ -225,52 +272,96 @@ when: (p) => !p.hasMore.value // TypeError!
225
272
  \`\`\`typescript
226
273
  // ✅ CORRECT - Typed parameters
227
274
  new JavaScript("validate_email", {
228
- fn: ({ email }: { email: string }) => email.includes("@")
229
- })
275
+ fn: ({ email }: { email: string }) => email.includes("@"),
276
+ });
230
277
 
231
278
  new PostgreSQL("search_users", "postgres-id", {
232
279
  statement: ({ searchTerm, limit }: { searchTerm: string; limit: number }) =>
233
- \`SELECT * FROM users WHERE name ILIKE '%\${searchTerm}%' LIMIT \${limit}\`
234
- })
280
+ \`SELECT * FROM users WHERE name ILIKE '%\${searchTerm}%' LIMIT \${limit}\`,
281
+ });
235
282
 
236
283
  // ❌ WRONG - Untyped parameters
237
284
  new JavaScript("validate_email", {
238
- fn: ({ email }) => email.includes("@") // ❌ No type!
239
- })
285
+ fn: ({ email }) => email.includes("@"), // ❌ No type!
286
+ });
240
287
  \`\`\`
241
288
 
242
289
  ## SQL Best Practices
243
290
 
244
- ### 1. ONE Query Per Block Rule
291
+ ### 1. 🚨 ALWAYS Add Defensive Row Limits
292
+
293
+ **Every SELECT query MUST include a row limit to prevent timeouts and crashes.** Always include a row limit clause to prevent runaway queries. Use 100 as the default unless user specifies otherwise.
294
+
295
+ Different SQL dialects have different syntax:
296
+
297
+ | Database | Syntax | Example |
298
+ | --------------------------------------------------------- | ------------------------- | ------------------------------------------------------------------------ |
299
+ | PostgreSQL, MySQL, MariaDB, Snowflake, Redshift, BigQuery | \`LIMIT N\` | \`SELECT * FROM users LIMIT 100\` |
300
+ | SQL Server (MSSQL) | \`SELECT TOP N\` | \`SELECT TOP 100 * FROM users\` |
301
+ | SQL Server with ORDER BY | \`OFFSET...FETCH\` | \`SELECT * FROM users ORDER BY id OFFSET 0 ROWS FETCH NEXT 100 ROWS ONLY\` |
302
+ | Oracle | \`FETCH FIRST N ROWS ONLY\` | \`SELECT * FROM users FETCH FIRST 100 ROWS ONLY\` |
303
+
304
+ **Examples:**
305
+
306
+ \`\`\`sql
307
+ -- ✅ PostgreSQL/MySQL/Snowflake
308
+ SELECT * FROM orders ORDER BY created_at DESC LIMIT 100;
309
+
310
+ -- ✅ SQL Server
311
+ SELECT TOP 100 * FROM orders ORDER BY created_at DESC;
312
+
313
+ -- ✅ SQL Server with OFFSET (for pagination)
314
+ SELECT * FROM orders ORDER BY created_at DESC OFFSET 0 ROWS FETCH NEXT 100 ROWS ONLY;
315
+
316
+ -- ❌ WRONG - No limit! Can timeout or crash on large tables
317
+ SELECT * FROM orders ORDER BY created_at DESC;
318
+ \`\`\`
319
+
320
+ **Why this matters:**
321
+
322
+ - Tables can have millions of rows
323
+ - Queries without limits can timeout (30+ seconds)
324
+ - Large result sets crash the browser/app
325
+ - Even "small" tables can grow unexpectedly
326
+
327
+ ### 2. ONE Query Per Block Rule
245
328
 
246
329
  Each SQL block can execute **ONLY ONE SQL query**.
247
330
 
248
331
  ❌ **WRONG:**
332
+
249
333
  \`\`\`sql
250
334
  UPDATE users SET status = 'active';
251
335
  DELETE FROM logs WHERE created < '2023-01-01';
252
336
  \`\`\`
253
337
 
254
338
  ✅ **CORRECT:**
339
+
255
340
  \`\`\`typescript
256
- new PostgreSQL("update_status", "pg-id", {
257
- statement: "UPDATE users SET status = 'active'"
341
+ (new PostgreSQL("update_status", "pg-id", {
342
+ statement: "UPDATE users SET status = 'active'",
258
343
  }),
259
- new PostgreSQL("clean_logs", "pg-id", {
260
- statement: "DELETE FROM logs WHERE created < '2023-01-01'"
261
- })
344
+ new PostgreSQL("clean_logs", "pg-id", {
345
+ statement: "DELETE FROM logs WHERE created < '2023-01-01'",
346
+ }));
262
347
  \`\`\`
263
348
 
264
- ### 2. Sort, Don't Filter by Date (Default)
349
+ ### 3. Sort, Don't Filter by Date (Default)
265
350
 
266
351
  Do NOT add automatic date filters unless explicitly requested.
267
352
 
268
353
  ✅ **Default:** \`SELECT * FROM orders ORDER BY created_at DESC LIMIT 100\`
269
354
  ❌ **Avoid:** \`SELECT * FROM orders WHERE created_at >= CURRENT_DATE - INTERVAL '90 days'\`
270
355
 
271
- ### 3. Always Add Defensive Row Limits
356
+ ### 4. Always Specify Columns When Possible
272
357
 
273
- Always include a row limit (default 100) to prevent runaway queries.
358
+ \`\`\`sql
359
+ -- ✅ PREFERRED - Explicit columns
360
+ SELECT id, name, email, created_at FROM users LIMIT 100
361
+
362
+ -- ⚠️ AVOID when possible - Select all
363
+ SELECT * FROM users LIMIT 100
364
+ \`\`\`
274
365
 
275
366
  ## Database Naming Conventions
276
367
 
@@ -280,8 +371,8 @@ Databricks uses: \`catalog.schema.table\`
280
371
 
281
372
  \`\`\`sql
282
373
  -- Metadata shows: uber.default.orders
283
- SELECT * FROM uber.default.orders -- ✅ Full path
284
- SELECT * FROM uber.orders -- ❌ Missing schema part
374
+ SELECT * FROM uber.default.orders LIMIT 100 -- ✅ Full path + LIMIT
375
+ SELECT * FROM uber.orders LIMIT 100 -- ❌ Missing schema part
285
376
  \`\`\`
286
377
 
287
378
  **Note:** The word "default" in Databricks paths is NOT optional - it's the actual schema name.
@@ -292,8 +383,8 @@ Snowflake uses: \`schema.table\`
292
383
 
293
384
  \`\`\`sql
294
385
  -- If table has schema property "MASTERDATA"
295
- SELECT * FROM MASTERDATA.PRODUCTLINE -- ✅ Fully qualified
296
- SELECT * FROM PRODUCTLINE -- ❌ Will fail if no default schema
386
+ SELECT * FROM MASTERDATA.PRODUCTLINE LIMIT 100 -- ✅ Fully qualified + LIMIT
387
+ SELECT * FROM PRODUCTLINE LIMIT 100 -- ❌ Will fail if no default schema
297
388
  \`\`\`
298
389
 
299
390
  ## Runtime Safety and Defensive Coding
@@ -305,11 +396,12 @@ SELECT * FROM PRODUCTLINE -- ❌ Will fail if no default schema
305
396
  \`\`\`typescript
306
397
  // ✅ Defensive transformation
307
398
  new JavaScript("normalize_users", {
308
- fn: ({ fetch_users }) => (Array.isArray(fetch_users.output) ? fetch_users.output : []).map(u => ({
309
- id: u.id,
310
- name: (u.name ?? "Unknown").toString()
311
- }))
312
- })
399
+ fn: ({ fetch_users }) =>
400
+ (Array.isArray(fetch_users.output) ? fetch_users.output : []).map((u) => ({
401
+ id: u.id,
402
+ name: (u.name ?? "Unknown").toString(),
403
+ })),
404
+ });
313
405
  \`\`\`
314
406
 
315
407
  ## Common API Patterns
@@ -319,8 +411,18 @@ new JavaScript("normalize_users", {
319
411
  \`\`\`typescript
320
412
  export default new Api("getUsersApi", [
321
413
  new PostgreSQL("fetch_users", "postgres-id", {
322
- statement: "SELECT * FROM users LIMIT 100"
323
- })
414
+ // ALWAYS include LIMIT clause to prevent timeouts
415
+ statement:
416
+ "SELECT id, name, email FROM users ORDER BY created_at DESC LIMIT 100",
417
+ }),
418
+ ]);
419
+
420
+ // With dynamic limit from input
421
+ export default new Api("getUsersWithLimitApi", [
422
+ new PostgreSQL("fetch_users", "postgres-id", {
423
+ statement: ({ pageSize }: { pageSize?: number }) =>
424
+ \`SELECT id, name, email FROM users ORDER BY created_at DESC LIMIT \${pageSize || 100}\`,
425
+ }),
324
426
  ]);
325
427
  \`\`\`
326
428
 
@@ -330,21 +432,34 @@ export default new Api("getUsersApi", [
330
432
  export default new Api("createUserApi", [
331
433
  new Conditional("validate_inputs", {
332
434
  if: {
333
- when: ({ FirstNameInput, EmailInput }: { FirstNameInput: string; EmailInput: string }) =>
334
- !FirstNameInput || !EmailInput,
435
+ when: ({
436
+ FirstNameInput,
437
+ EmailInput,
438
+ }: {
439
+ FirstNameInput: string;
440
+ EmailInput: string;
441
+ }) => !FirstNameInput || !EmailInput,
335
442
  then: [
336
- new Throw("validation_error", { error: "First name and email are required" })
337
- ]
338
- }
443
+ new Throw("validation_error", {
444
+ error: "First name and email are required",
445
+ }),
446
+ ],
447
+ },
339
448
  }),
340
449
  new JavaScript("create_user", {
341
- fn: ({ FirstNameInput, EmailInput }: { FirstNameInput: string; EmailInput: string }) => ({
450
+ fn: ({
451
+ FirstNameInput,
452
+ EmailInput,
453
+ }: {
454
+ FirstNameInput: string;
455
+ EmailInput: string;
456
+ }) => ({
342
457
  id: Math.floor(Math.random() * 1000),
343
458
  name: FirstNameInput,
344
459
  email: EmailInput,
345
- created_at: new Date().toISOString()
346
- })
347
- })
460
+ created_at: new Date().toISOString(),
461
+ }),
462
+ }),
348
463
  ]);
349
464
  \`\`\`
350
465
 
@@ -355,8 +470,8 @@ export default new Api("processOrdersApi", [
355
470
  new JavaScript("get_orders", {
356
471
  fn: () => [
357
472
  { id: 1, status: "pending", amount: 100 },
358
- { id: 2, status: "pending", amount: 200 }
359
- ]
473
+ { id: 2, status: "pending", amount: 200 },
474
+ ],
360
475
  }),
361
476
  new Loop("process_each_order", {
362
477
  over: ({ get_orders }) => get_orders.output,
@@ -367,11 +482,11 @@ export default new Api("processOrdersApi", [
367
482
  ...order.value,
368
483
  tax: order.value.amount * 0.1,
369
484
  total: order.value.amount * 1.1,
370
- position: i.value
371
- })
372
- })
373
- ]
374
- })
485
+ position: i.value,
486
+ }),
487
+ }),
488
+ ],
489
+ }),
375
490
  ]);
376
491
  \`\`\`
377
492
 
@@ -384,21 +499,22 @@ export default new Api("paginatedFetchApi", [
384
499
  { key: "cursor", value: () => null },
385
500
  { key: "hasMore", value: () => true },
386
501
  ]),
387
-
502
+
388
503
  new Loop("fetch_all_pages", {
389
504
  type: "TYPE_FOREACH",
390
- over: () => [...Array(100).keys()], // Max iterations safety
505
+ over: () => [...Array(100).keys()], // Max iterations safety
391
506
  variables: { item: "_", index: "i" },
392
507
  blocks: [
393
508
  new Conditional("check_done", {
394
509
  if: {
395
510
  when: ({ hasMore }) => !hasMore.value,
396
- then: [new Break("exit_loop", { condition: () => true })]
397
- }
511
+ then: [new Break("exit_loop", { condition: () => true })],
512
+ },
398
513
  }),
399
514
  new RestApi("fetch_page", "rest-api-id", {
400
515
  method: "GET",
401
- url: ({ cursor }) => \`https://api.example.com/items\${cursor.value ? \`?cursor=\${cursor.value}\` : ""}\`,
516
+ url: ({ cursor }) =>
517
+ \`https://api.example.com/items\${cursor.value ? \`?cursor=\${cursor.value}\` : ""}\`,
402
518
  }),
403
519
  new JavaScript("accumulate", {
404
520
  fn: ({ fetch_page, allResults, cursor, hasMore }) => {
@@ -407,32 +523,34 @@ export default new Api("paginatedFetchApi", [
407
523
  cursor.set(response.nextCursor);
408
524
  hasMore.set(response.hasMore);
409
525
  return allResults.value;
410
- }
411
- })
412
- ]
526
+ },
527
+ }),
528
+ ],
413
529
  }),
414
-
530
+
415
531
  new JavaScript("return_results", {
416
- fn: ({ allResults }) => allResults.value
417
- })
532
+ fn: ({ allResults }) => allResults.value,
533
+ }),
418
534
  ]);
419
535
  \`\`\`
420
536
 
421
537
  ### File Uploads to S3/GCS
422
538
 
423
539
  **Frontend wraps files in \`{ files: [...] }\` format:**
540
+
424
541
  \`\`\`typescript
425
542
  const response = await runUploadApi({ userFiles: { files: selectedFiles } });
426
543
  \`\`\`
427
544
 
428
545
  **Backend API - pass files directly:**
546
+
429
547
  \`\`\`typescript
430
548
  export default new Api("uploadFilesApi", [
431
549
  new S3("upload_files", "your-s3-integration-id", {
432
550
  action: "UPLOAD_MULTIPLE_OBJECTS",
433
551
  resource: ({ bucketName }) => bucketName,
434
- fileObjects: ({ userFiles }) => userFiles.files // Direct pass-through
435
- })
552
+ fileObjects: ({ userFiles }) => userFiles.files, // Direct pass-through
553
+ }),
436
554
  ]);
437
555
  \`\`\`
438
556
 
@@ -443,10 +561,13 @@ new JavaScript("parse_csv", {
443
561
  fn: async ({ csvFile }) => {
444
562
  const file = csvFile.files[0];
445
563
  const content = await file.readContentsAsync();
446
- const headers = content.split("\\n")[0].split(",").map(h => h.trim());
564
+ const headers = content
565
+ .split("\\n")[0]
566
+ .split(",")
567
+ .map((h) => h.trim());
447
568
  return { fileName: file.name, headers };
448
- }
449
- })
569
+ },
570
+ });
450
571
  \`\`\`
451
572
 
452
573
  ## Error Handling Guidelines
@@ -454,10 +575,12 @@ new JavaScript("parse_csv", {
454
575
  **IMPORTANT: Do NOT use TryCatch blocks by default.** Only use when truly necessary.
455
576
 
456
577
  ### ❌ DO NOT use TryCatch for:
578
+
457
579
  - Standard database queries
458
580
  - Simple data transformations
459
581
 
460
582
  ### ✅ DO use TryCatch when:
583
+
461
584
  - User explicitly requests error handling
462
585
  - Continuing execution after failure is business-critical
463
586
  - Partial failure recovery in loops
@@ -470,6 +593,7 @@ When you encounter errors while building APIs:
470
593
  ### Read Error Messages Carefully
471
594
 
472
595
  Error messages contain specific guidance on how to fix the problem. Pay close attention to:
596
+
473
597
  - What operation failed (compilation, validation, execution)
474
598
  - Suggestions for how to resolve the issue
475
599
  - Whether metadata is missing
@@ -477,6 +601,7 @@ Error messages contain specific guidance on how to fix the problem. Pay close at
477
601
  ### When to Check Integration Metadata
478
602
 
479
603
  If you encounter errors mentioning:
604
+
480
605
  - "unknown column", "table not found", "invalid field"
481
606
  - "check integration metadata"
482
607
  - Integration type mismatches
@@ -491,6 +616,7 @@ You MUST call \`grepMetadata\` to get the correct schema/table structure before
491
616
  - **TYPE_WHILE**: Repeats while \`condition\` is true. Provides only \`index\` variable.
492
617
 
493
618
  **Breaking out of loops:**
619
+
494
620
  \`\`\`typescript
495
621
  new Loop("process_until_complete", {
496
622
  over: ({ items }) => items.output,
@@ -500,18 +626,18 @@ new Loop("process_until_complete", {
500
626
  if: {
501
627
  when: ({ current }) => current.value.status === "complete",
502
628
  then: [
503
- new Break("exit_loop", { condition: () => true }) // ✅ Only way to exit
504
- ]
505
- }
629
+ new Break("exit_loop", { condition: () => true }), // ✅ Only way to exit
630
+ ],
631
+ },
506
632
  }),
507
633
  new JavaScript("process_item", {
508
634
  fn: ({ current, i }) => ({
509
635
  processed: current.value,
510
- position: i.value
511
- })
512
- })
513
- ]
514
- })
636
+ position: i.value,
637
+ }),
638
+ }),
639
+ ],
640
+ });
515
641
  \`\`\`
516
642
 
517
643
  ## Response Interface Guidelines
@@ -521,15 +647,18 @@ The \`responseInterface\` describes what external code gets from \`apiName.respo
521
647
  ### Direct Response Types
522
648
 
523
649
  ✅ **CORRECT**: Direct array response
650
+
524
651
  \`\`\`typescript
525
652
  interface GetUsersApiResponse {
526
653
  id: number;
527
654
  name: string;
528
655
  email: string;
529
- }[]
656
+ }
657
+ [];
530
658
  \`\`\`
531
659
 
532
660
  ✅ **CORRECT**: Direct data structure
661
+
533
662
  \`\`\`typescript
534
663
  interface GetOrdersApiResponse {
535
664
  orders: Order[];
@@ -538,10 +667,11 @@ interface GetOrdersApiResponse {
538
667
  \`\`\`
539
668
 
540
669
  ❌ **WRONG**: Exposing internal steps
670
+
541
671
  \`\`\`typescript
542
672
  interface GetOrdersApiResponse {
543
- fetchStep: { output: Order[] }; // ❌ Steps are internal
544
- countStep: { output: number }; // ❌ Not visible outside
673
+ fetchStep: { output: Order[] }; // ❌ Steps are internal
674
+ countStep: { output: number }; // ❌ Not visible outside
545
675
  }
546
676
  \`\`\`
547
677
 
@@ -556,15 +686,17 @@ When uncertain if an API field will always be present, mark it optional:
556
686
  interface GitHubPRResponse {
557
687
  id: number;
558
688
  title: string;
559
- user?: { // ← Optional, can be null for deleted users
689
+ user?: {
690
+ // ← Optional, can be null for deleted users
560
691
  login: string;
561
692
  avatar_url: string;
562
693
  } | null;
563
- labels?: Label[]; // ← Optional, might be omitted in response
694
+ labels?: Label[]; // ← Optional, might be omitted in response
564
695
  }
565
696
  \`\`\`
566
697
 
567
698
  Mark fields optional when:
699
+
568
700
  1. **User/account references** - Can be null for deleted/deactivated accounts
569
701
  2. **Nested objects** - May be omitted in partial responses
570
702
  3. **Third-party APIs** - GitHub, Stripe, etc. often have nullable fields
@@ -582,7 +714,7 @@ type Global = {
582
714
  username: string;
583
715
  id: string;
584
716
  name: string;
585
- groups: Group[]
717
+ groups: Group[];
586
718
  };
587
719
  };
588
720
  \`\`\`
@@ -592,15 +724,20 @@ type Global = {
592
724
  \`\`\`typescript
593
725
  new JavaScript("check_groups", {
594
726
  fn: ({ Global }) => {
595
- const isFieldEngUser = Global.groups.some(group => group.name === "FieldEngineer");
727
+ const isFieldEngUser = Global.groups.some(
728
+ (group) => group.name === "FieldEngineer",
729
+ );
596
730
  if (isFieldEngUser) {
597
731
  // Perform actions for FieldEngineer
598
732
  } else {
599
733
  // Perform actions for non-FieldEngineer
600
734
  }
601
- return { isAdmin: Global.groups.some(g => g.name === "Admin"), userId: Global.user.id };
602
- }
603
- })
735
+ return {
736
+ isAdmin: Global.groups.some((g) => g.name === "Admin"),
737
+ userId: Global.user.id,
738
+ };
739
+ },
740
+ });
604
741
  \`\`\`
605
742
 
606
743
  **NEVER rely on frontend data for security-critical operations.**
@@ -636,18 +773,19 @@ export default new Api("MyApi", [
636
773
  \`\`\`typescript
637
774
  // ❌ WRONG - JavaScript in SQL block
638
775
  new PostgreSQL("bad", "id", {
639
- statement: ({ userId }) => \`SELECT * FROM users WHERE id = \${userId}\`
640
- })
776
+ statement: ({ userId }) => \`SELECT * FROM users WHERE id = \${userId}\`,
777
+ });
641
778
 
642
779
  // ❌ WRONG - SQL in JavaScript block
643
780
  new JavaScript("bad", {
644
- fn: "SELECT * FROM users" // This is SQL!
645
- })
781
+ fn: "SELECT * FROM users", // This is SQL!
782
+ });
646
783
 
647
784
  // ✅ CORRECT
648
785
  new PostgreSQL("good", "id", {
649
- statement: ({ userId }: { userId: string }) => \`SELECT * FROM users WHERE id = '\${userId}'\`
650
- })
786
+ statement: ({ userId }: { userId: string }) =>
787
+ \`SELECT * FROM users WHERE id = '\${userId}' LIMIT 1\`,
788
+ });
651
789
  \`\`\`
652
790
 
653
791
  ### 3. Fake Integration IDs
@@ -663,18 +801,18 @@ new PostgreSQL("query", "fake-postgres-id", { ... })
663
801
  // ❌ WRONG - Cannot set state in APIs
664
802
  new JavaScript("update", {
665
803
  fn: ({ userData }) => {
666
- userNameVar.value = userData.name; // ❌ Cannot do this!
804
+ userNameVar.value = userData.name; // ❌ Cannot do this!
667
805
  return userData;
668
- }
669
- })
806
+ },
807
+ });
670
808
 
671
809
  // ✅ CORRECT - Return data, frontend handles state
672
810
  new JavaScript("update", {
673
811
  fn: ({ userData }) => ({
674
812
  ...userData,
675
- fullName: \`\${userData.firstName} \${userData.lastName}\`
676
- })
677
- })
813
+ fullName: \`\${userData.firstName} \${userData.lastName}\`,
814
+ }),
815
+ });
678
816
  \`\`\`
679
817
 
680
818
  ### 5. Return Blocks Cannot Contain Statements
@@ -682,16 +820,43 @@ new JavaScript("update", {
682
820
  \`\`\`typescript
683
821
  // ✅ CORRECT - Returns data immediately
684
822
  new Return("test_return", {
685
- data: (({ records }) => ({ records, totalCount: records.length }))()
686
- })
823
+ data: (({ records }) => ({ records, totalCount: records.length }))(),
824
+ });
687
825
 
688
826
  // ❌ WRONG - Contains statements
689
827
  new Return("test_return", {
690
828
  data: (({ records }) => {
691
- const totalCount = records.length; // ❌ Statement not allowed
829
+ const totalCount = records.length; // ❌ Statement not allowed
692
830
  return { records, totalCount };
693
- })()
694
- })
831
+ })(),
832
+ });
833
+ \`\`\`
834
+
835
+ ### 6. Missing LIMIT Clause (Causes Timeouts)
836
+
837
+ \`\`\`typescript
838
+ // ❌ WRONG - No LIMIT, can timeout or crash
839
+ new PostgreSQL("fetch_all", "pg-id", {
840
+ statement: "SELECT * FROM orders",
841
+ });
842
+
843
+ new Snowflake("fetch_data", "sf-id", {
844
+ statement: "SELECT * FROM SCHEMA.LARGE_TABLE ORDER BY date",
845
+ });
846
+
847
+ // ✅ CORRECT - Always include LIMIT
848
+ new PostgreSQL("fetch_orders", "pg-id", {
849
+ statement: "SELECT * FROM orders ORDER BY created_at DESC LIMIT 100",
850
+ });
851
+
852
+ new Snowflake("fetch_data", "sf-id", {
853
+ statement: "SELECT * FROM SCHEMA.LARGE_TABLE ORDER BY date LIMIT 100",
854
+ });
855
+
856
+ // ✅ CORRECT - SQL Server syntax
857
+ new MicrosoftSql("fetch_orders", "mssql-id", {
858
+ statement: "SELECT TOP 100 * FROM orders ORDER BY created_at DESC",
859
+ });
695
860
  \`\`\`
696
861
 
697
862
  ## When to Load References
@@ -717,5 +882,10 @@ When creating APIs:
717
882
  8. ✅ Error handling only where appropriate
718
883
  9. ✅ NEVER change API name when editing existing API
719
884
  10. ✅ ALWAYS test after building
885
+ 11. ✅ **ALL SELECT queries have LIMIT clauses** (default 100) - use dialect-appropriate syntax
886
+
887
+ ## Interpreting testApi tool Results
888
+
889
+ **CRITICAL**: \\\`success: false\\\` or missing = FAILURE. Never show success toast. Even when \\\`success: true\\\`, verify the output data is valid before confirming success to the user.
720
890
  `;
721
891
  //# sourceMappingURL=skill.generated.js.map