@superblocksteam/vite-plugin-file-sync 2.0.83-next.1 → 2.0.83

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 (312) hide show
  1. package/dist/ai-service/agent/middleware.d.ts +0 -36
  2. package/dist/ai-service/agent/middleware.d.ts.map +1 -1
  3. package/dist/ai-service/agent/middleware.js +1 -65
  4. package/dist/ai-service/agent/middleware.js.map +1 -1
  5. package/dist/ai-service/agent/prompts/build-base-system-prompt.d.ts +1 -1
  6. package/dist/ai-service/agent/prompts/build-base-system-prompt.d.ts.map +1 -1
  7. package/dist/ai-service/agent/prompts/build-base-system-prompt.js +57 -101
  8. package/dist/ai-service/agent/prompts/build-base-system-prompt.js.map +1 -1
  9. package/dist/ai-service/agent/tool-message-utils.js +1 -1
  10. package/dist/ai-service/agent/tool-message-utils.js.map +1 -1
  11. package/dist/ai-service/agent/tools/apis/api-executor.js +1 -1
  12. package/dist/ai-service/agent/tools/apis/api-executor.js.map +1 -1
  13. package/dist/ai-service/agent/tools/apis/api-validation-orchestrator.d.ts.map +1 -1
  14. package/dist/ai-service/agent/tools/apis/api-validation-orchestrator.js +1 -1
  15. package/dist/ai-service/agent/tools/apis/api-validation-orchestrator.js.map +1 -1
  16. package/dist/ai-service/agent/tools/apis/build-api-artifact.d.ts.map +1 -1
  17. package/dist/ai-service/agent/tools/apis/build-api-artifact.js +7 -23
  18. package/dist/ai-service/agent/tools/apis/build-api-artifact.js.map +1 -1
  19. package/dist/ai-service/agent/tools/apis/build-api.d.ts.map +1 -1
  20. package/dist/ai-service/agent/tools/apis/build-api.js +19 -36
  21. package/dist/ai-service/agent/tools/apis/build-api.js.map +1 -1
  22. package/dist/ai-service/agent/tools/apis/get-api-docs.d.ts +1 -1
  23. package/dist/ai-service/agent/tools/apis/sample-json.js +1 -1
  24. package/dist/ai-service/agent/tools/apis/sample-json.js.map +1 -1
  25. package/dist/ai-service/agent/tools/apis/test-api.d.ts +1 -11
  26. package/dist/ai-service/agent/tools/apis/test-api.d.ts.map +1 -1
  27. package/dist/ai-service/agent/tools/apis/test-api.js +54 -95
  28. package/dist/ai-service/agent/tools/apis/test-api.js.map +1 -1
  29. package/dist/ai-service/agent/tools/build-capture-screenshot.d.ts +0 -3
  30. package/dist/ai-service/agent/tools/build-capture-screenshot.d.ts.map +1 -1
  31. package/dist/ai-service/agent/tools/build-capture-screenshot.js +8 -12
  32. package/dist/ai-service/agent/tools/build-capture-screenshot.js.map +1 -1
  33. package/dist/ai-service/agent/tools/build-debug.d.ts.map +1 -1
  34. package/dist/ai-service/agent/tools/build-debug.js +10 -30
  35. package/dist/ai-service/agent/tools/build-debug.js.map +1 -1
  36. package/dist/ai-service/agent/tools/build-delete-file.d.ts.map +1 -1
  37. package/dist/ai-service/agent/tools/build-delete-file.js +2 -6
  38. package/dist/ai-service/agent/tools/build-delete-file.js.map +1 -1
  39. package/dist/ai-service/agent/tools/build-edit-file.d.ts.map +1 -1
  40. package/dist/ai-service/agent/tools/build-edit-file.js +5 -20
  41. package/dist/ai-service/agent/tools/build-edit-file.js.map +1 -1
  42. package/dist/ai-service/agent/tools/build-finalize.d.ts.map +1 -1
  43. package/dist/ai-service/agent/tools/build-finalize.js +4 -30
  44. package/dist/ai-service/agent/tools/build-finalize.js.map +1 -1
  45. package/dist/ai-service/agent/tools/build-manage-checklist.d.ts +1 -1
  46. package/dist/ai-service/agent/tools/build-multi-edit-file.d.ts.map +1 -1
  47. package/dist/ai-service/agent/tools/build-multi-edit-file.js +4 -14
  48. package/dist/ai-service/agent/tools/build-multi-edit-file.js.map +1 -1
  49. package/dist/ai-service/agent/tools/build-read-file.d.ts.map +1 -1
  50. package/dist/ai-service/agent/tools/build-read-file.js +11 -23
  51. package/dist/ai-service/agent/tools/build-read-file.js.map +1 -1
  52. package/dist/ai-service/agent/tools/debug-cache.js +1 -1
  53. package/dist/ai-service/agent/tools/debug-cache.js.map +1 -1
  54. package/dist/ai-service/agent/tools/get-console-logs.d.ts +29 -0
  55. package/dist/ai-service/agent/tools/get-console-logs.d.ts.map +1 -0
  56. package/dist/ai-service/agent/tools/get-console-logs.js +171 -0
  57. package/dist/ai-service/agent/tools/get-console-logs.js.map +1 -0
  58. package/dist/ai-service/agent/tools/index.d.ts +1 -1
  59. package/dist/ai-service/agent/tools/index.d.ts.map +1 -1
  60. package/dist/ai-service/agent/tools/index.js +1 -1
  61. package/dist/ai-service/agent/tools/index.js.map +1 -1
  62. package/dist/ai-service/agent/tools/integrations/execute-request.d.ts.map +1 -1
  63. package/dist/ai-service/agent/tools/integrations/execute-request.js +5 -20
  64. package/dist/ai-service/agent/tools/integrations/execute-request.js.map +1 -1
  65. package/dist/ai-service/agent/tools/integrations/internal.d.ts.map +1 -1
  66. package/dist/ai-service/agent/tools/integrations/internal.js +3 -12
  67. package/dist/ai-service/agent/tools/integrations/internal.js.map +1 -1
  68. package/dist/ai-service/agent/tools.d.ts.map +1 -1
  69. package/dist/ai-service/agent/tools.js +28 -19
  70. package/dist/ai-service/agent/tools.js.map +1 -1
  71. package/dist/ai-service/agent/tools2/registry.d.ts.map +1 -1
  72. package/dist/ai-service/agent/tools2/registry.js +15 -37
  73. package/dist/ai-service/agent/tools2/registry.js.map +1 -1
  74. package/dist/ai-service/agent/tools2/tools/bash.d.ts +1 -1
  75. package/dist/ai-service/agent/tools2/tools/edit.d.ts.map +1 -1
  76. package/dist/ai-service/agent/tools2/tools/edit.js +4 -9
  77. package/dist/ai-service/agent/tools2/tools/edit.js.map +1 -1
  78. package/dist/ai-service/agent/tools2/tools/grep.d.ts.map +1 -1
  79. package/dist/ai-service/agent/tools2/tools/grep.js +7 -73
  80. package/dist/ai-service/agent/tools2/tools/grep.js.map +1 -1
  81. package/dist/ai-service/agent/tools2/tools/read.d.ts.map +1 -1
  82. package/dist/ai-service/agent/tools2/tools/read.js +4 -9
  83. package/dist/ai-service/agent/tools2/tools/read.js.map +1 -1
  84. package/dist/ai-service/agent/tools2/types.d.ts +8 -40
  85. package/dist/ai-service/agent/tools2/types.d.ts.map +1 -1
  86. package/dist/ai-service/agent/tools2/types.js +3 -41
  87. package/dist/ai-service/agent/tools2/types.js.map +1 -1
  88. package/dist/ai-service/app-interface/filesystem/handlers/skill-handler.d.ts +1 -0
  89. package/dist/ai-service/app-interface/filesystem/handlers/skill-handler.d.ts.map +1 -1
  90. package/dist/ai-service/app-interface/filesystem/handlers/skill-handler.js +54 -60
  91. package/dist/ai-service/app-interface/filesystem/handlers/skill-handler.js.map +1 -1
  92. package/dist/ai-service/chat/chat-session-store.d.ts +0 -6
  93. package/dist/ai-service/chat/chat-session-store.d.ts.map +1 -1
  94. package/dist/ai-service/chat/chat-session-store.js +0 -44
  95. package/dist/ai-service/chat/chat-session-store.js.map +1 -1
  96. package/dist/ai-service/features.d.ts +0 -8
  97. package/dist/ai-service/features.d.ts.map +1 -1
  98. package/dist/ai-service/features.js +0 -8
  99. package/dist/ai-service/features.js.map +1 -1
  100. package/dist/ai-service/index.d.ts +2 -34
  101. package/dist/ai-service/index.d.ts.map +1 -1
  102. package/dist/ai-service/index.js +18 -112
  103. package/dist/ai-service/index.js.map +1 -1
  104. package/dist/ai-service/integrations/metadata-storage/local.d.ts.map +1 -1
  105. package/dist/ai-service/integrations/metadata-storage/local.js +2 -4
  106. package/dist/ai-service/integrations/metadata-storage/local.js.map +1 -1
  107. package/dist/ai-service/integrations/store.d.ts +3 -6
  108. package/dist/ai-service/integrations/store.d.ts.map +1 -1
  109. package/dist/ai-service/integrations/store.js +6 -96
  110. package/dist/ai-service/integrations/store.js.map +1 -1
  111. package/dist/ai-service/judge/judge-executor.js +1 -1
  112. package/dist/ai-service/judge/judge-executor.js.map +1 -1
  113. package/dist/ai-service/judge/tools/playwright-action.d.ts +1 -1
  114. package/dist/ai-service/llm/client.d.ts.map +1 -1
  115. package/dist/ai-service/llm/client.js +13 -26
  116. package/dist/ai-service/llm/client.js.map +1 -1
  117. package/dist/ai-service/llm/context-v2/adapter.d.ts +0 -2
  118. package/dist/ai-service/llm/context-v2/adapter.d.ts.map +1 -1
  119. package/dist/ai-service/llm/context-v2/adapter.js +0 -6
  120. package/dist/ai-service/llm/context-v2/adapter.js.map +1 -1
  121. package/dist/ai-service/llm/context-v2/context.d.ts +0 -17
  122. package/dist/ai-service/llm/context-v2/context.d.ts.map +1 -1
  123. package/dist/ai-service/llm/context-v2/context.js +1 -54
  124. package/dist/ai-service/llm/context-v2/context.js.map +1 -1
  125. package/dist/ai-service/llm/context-v2/conversation-context.d.ts +1 -11
  126. package/dist/ai-service/llm/context-v2/conversation-context.d.ts.map +1 -1
  127. package/dist/ai-service/llm/context-v2/phase1-tool-summarizer.d.ts +1 -1
  128. package/dist/ai-service/llm/context-v2/phase1-tool-summarizer.d.ts.map +1 -1
  129. package/dist/ai-service/llm/context-v2/phase1-tool-summarizer.js +6 -42
  130. package/dist/ai-service/llm/context-v2/phase1-tool-summarizer.js.map +1 -1
  131. package/dist/ai-service/llm/context-v2/types.d.ts +0 -4
  132. package/dist/ai-service/llm/context-v2/types.d.ts.map +1 -1
  133. package/dist/ai-service/llm/context-v2/types.js.map +1 -1
  134. package/dist/ai-service/llm/error.js +1 -1
  135. package/dist/ai-service/llm/error.js.map +1 -1
  136. package/dist/ai-service/llm/interaction/adapters/vercel.js +5 -5
  137. package/dist/ai-service/llm/stream/config.d.ts +1 -1
  138. package/dist/ai-service/llm/stream/config.d.ts.map +1 -1
  139. package/dist/ai-service/llm/stream/config.js.map +1 -1
  140. package/dist/ai-service/llm/stream/observers/llmobs.js +1 -1
  141. package/dist/ai-service/llm/stream/observers/llmobs.js.map +1 -1
  142. package/dist/ai-service/llm/stream/observers/logging.d.ts +0 -20
  143. package/dist/ai-service/llm/stream/observers/logging.d.ts.map +1 -1
  144. package/dist/ai-service/llm/stream/observers/logging.js +18 -115
  145. package/dist/ai-service/llm/stream/observers/logging.js.map +1 -1
  146. package/dist/ai-service/llm/stream/observers/retry-notification.d.ts.map +1 -1
  147. package/dist/ai-service/llm/stream/observers/retry-notification.js +1 -2
  148. package/dist/ai-service/llm/stream/observers/retry-notification.js.map +1 -1
  149. package/dist/ai-service/llm/stream/orchestrator.js +4 -4
  150. package/dist/ai-service/llm/stream/orchestrator.js.map +1 -1
  151. package/dist/ai-service/llm/stream/retry-engine.d.ts.map +1 -1
  152. package/dist/ai-service/llm/stream/retry-engine.js +1 -1
  153. package/dist/ai-service/llm/stream/retry-engine.js.map +1 -1
  154. package/dist/ai-service/llmobs/otel-exporter.d.ts +14 -111
  155. package/dist/ai-service/llmobs/otel-exporter.d.ts.map +1 -1
  156. package/dist/ai-service/llmobs/otel-exporter.js +66 -441
  157. package/dist/ai-service/llmobs/otel-exporter.js.map +1 -1
  158. package/dist/ai-service/llmobs/tracer.d.ts.map +1 -1
  159. package/dist/ai-service/llmobs/tracer.js +4 -40
  160. package/dist/ai-service/llmobs/tracer.js.map +1 -1
  161. package/dist/ai-service/mcp/playwright-server.d.ts.map +1 -1
  162. package/dist/ai-service/mcp/playwright-server.js +2 -11
  163. package/dist/ai-service/mcp/playwright-server.js.map +1 -1
  164. package/dist/ai-service/security/safety-classifier.d.ts.map +1 -1
  165. package/dist/ai-service/security/safety-classifier.js +3 -9
  166. package/dist/ai-service/security/safety-classifier.js.map +1 -1
  167. package/dist/ai-service/skills/index.d.ts +11 -23
  168. package/dist/ai-service/skills/index.d.ts.map +1 -1
  169. package/dist/ai-service/skills/index.js +21 -86
  170. package/dist/ai-service/skills/index.js.map +1 -1
  171. package/dist/ai-service/skills/system/superblocks-api/references/code-blocks.generated.d.ts +1 -1
  172. package/dist/ai-service/skills/system/superblocks-api/references/code-blocks.generated.d.ts.map +1 -1
  173. package/dist/ai-service/skills/system/superblocks-api/references/code-blocks.generated.js +0 -56
  174. package/dist/ai-service/skills/system/superblocks-api/references/code-blocks.generated.js.map +1 -1
  175. package/dist/ai-service/skills/system/superblocks-api/references/sql-databases.generated.d.ts +1 -1
  176. package/dist/ai-service/skills/system/superblocks-api/references/sql-databases.generated.d.ts.map +1 -1
  177. package/dist/ai-service/skills/system/superblocks-api/references/sql-databases.generated.js +11 -143
  178. package/dist/ai-service/skills/system/superblocks-api/references/sql-databases.generated.js.map +1 -1
  179. package/dist/ai-service/skills/system/superblocks-api/skill.generated.d.ts +1 -1
  180. package/dist/ai-service/skills/system/superblocks-api/skill.generated.d.ts.map +1 -1
  181. package/dist/ai-service/skills/system/superblocks-api/skill.generated.js +3 -130
  182. package/dist/ai-service/skills/system/superblocks-api/skill.generated.js.map +1 -1
  183. package/dist/ai-service/skills/system/superblocks-frontend/skill.generated.d.ts +1 -1
  184. package/dist/ai-service/skills/system/superblocks-frontend/skill.generated.d.ts.map +1 -1
  185. package/dist/ai-service/skills/system/superblocks-frontend/skill.generated.js +17 -97
  186. package/dist/ai-service/skills/system/superblocks-frontend/skill.generated.js.map +1 -1
  187. package/dist/ai-service/skills/types.d.ts +0 -24
  188. package/dist/ai-service/skills/types.d.ts.map +1 -1
  189. package/dist/ai-service/skills/types.js +0 -45
  190. package/dist/ai-service/skills/types.js.map +1 -1
  191. package/dist/ai-service/state-machine/clark-fsm.d.ts +2 -33
  192. package/dist/ai-service/state-machine/clark-fsm.d.ts.map +1 -1
  193. package/dist/ai-service/state-machine/clark-fsm.js +1 -6
  194. package/dist/ai-service/state-machine/clark-fsm.js.map +1 -1
  195. package/dist/ai-service/state-machine/handlers/agent-planning.d.ts.map +1 -1
  196. package/dist/ai-service/state-machine/handlers/agent-planning.js +21 -24
  197. package/dist/ai-service/state-machine/handlers/agent-planning.js.map +1 -1
  198. package/dist/ai-service/state-machine/handlers/llm-generating.d.ts.map +1 -1
  199. package/dist/ai-service/state-machine/handlers/llm-generating.js +5 -120
  200. package/dist/ai-service/state-machine/handlers/llm-generating.js.map +1 -1
  201. package/dist/ai-service/state-machine/mocks.d.ts.map +1 -1
  202. package/dist/ai-service/state-machine/mocks.js +0 -23
  203. package/dist/ai-service/state-machine/mocks.js.map +1 -1
  204. package/dist/ai-service/state-machine/traced-fsm.d.ts.map +1 -1
  205. package/dist/ai-service/state-machine/traced-fsm.js +1 -1
  206. package/dist/ai-service/state-machine/traced-fsm.js.map +1 -1
  207. package/dist/ai-service/test-utils/anthropic-service-mock.d.ts +2 -0
  208. package/dist/ai-service/test-utils/anthropic-service-mock.d.ts.map +1 -0
  209. package/dist/ai-service/test-utils/anthropic-service-mock.js +91 -0
  210. package/dist/ai-service/test-utils/anthropic-service-mock.js.map +1 -0
  211. package/dist/ai-service/test-utils/app-generation-mocks/orders-app.d.ts +3 -0
  212. package/dist/ai-service/test-utils/app-generation-mocks/orders-app.d.ts.map +1 -0
  213. package/dist/ai-service/test-utils/app-generation-mocks/orders-app.js +886 -0
  214. package/dist/ai-service/test-utils/app-generation-mocks/orders-app.js.map +1 -0
  215. package/dist/ai-service/test-utils/app-generation-mocks/reprompt.d.ts +3 -0
  216. package/dist/ai-service/test-utils/app-generation-mocks/reprompt.d.ts.map +1 -0
  217. package/dist/ai-service/test-utils/app-generation-mocks/reprompt.js +70 -0
  218. package/dist/ai-service/test-utils/app-generation-mocks/reprompt.js.map +1 -0
  219. package/dist/ai-service/test-utils/app-generation-mocks/smoketest.d.ts +3 -0
  220. package/dist/ai-service/test-utils/app-generation-mocks/smoketest.d.ts.map +1 -0
  221. package/dist/ai-service/test-utils/app-generation-mocks/smoketest.js +109 -0
  222. package/dist/ai-service/test-utils/app-generation-mocks/smoketest.js.map +1 -0
  223. package/dist/ai-service/test-utils/mock-utils.d.ts +12 -0
  224. package/dist/ai-service/test-utils/mock-utils.d.ts.map +1 -0
  225. package/dist/ai-service/test-utils/mock-utils.js +70 -0
  226. package/dist/ai-service/test-utils/mock-utils.js.map +1 -0
  227. package/dist/ai-service/util/safe-stringify.d.ts +2 -0
  228. package/dist/ai-service/util/safe-stringify.d.ts.map +1 -0
  229. package/dist/ai-service/util/safe-stringify.js +75 -0
  230. package/dist/ai-service/util/safe-stringify.js.map +1 -0
  231. package/dist/file-sync-vite-plugin.d.ts.map +1 -1
  232. package/dist/file-sync-vite-plugin.js +22 -52
  233. package/dist/file-sync-vite-plugin.js.map +1 -1
  234. package/dist/ids.d.ts +0 -1
  235. package/dist/ids.d.ts.map +1 -1
  236. package/dist/ids.js +0 -3
  237. package/dist/ids.js.map +1 -1
  238. package/dist/refactor/entities.d.ts.map +1 -1
  239. package/dist/refactor/entities.js +1 -0
  240. package/dist/refactor/entities.js.map +1 -1
  241. package/dist/socket-manager.d.ts.map +1 -1
  242. package/dist/socket-manager.js +3 -21
  243. package/dist/socket-manager.js.map +1 -1
  244. package/dist/sync-service/index.d.ts +0 -4
  245. package/dist/sync-service/index.d.ts.map +1 -1
  246. package/dist/sync-service/index.js +0 -6
  247. package/dist/sync-service/index.js.map +1 -1
  248. package/dist/util/logger.d.ts +0 -4
  249. package/dist/util/logger.d.ts.map +1 -1
  250. package/dist/util/logger.js +19 -77
  251. package/dist/util/logger.js.map +1 -1
  252. package/package.json +14 -17
  253. package/dist/ai-service/agent/tools/get-logs.d.ts +0 -72
  254. package/dist/ai-service/agent/tools/get-logs.d.ts.map +0 -1
  255. package/dist/ai-service/agent/tools/get-logs.js +0 -343
  256. package/dist/ai-service/agent/tools/get-logs.js.map +0 -1
  257. package/dist/ai-service/agent/tools/integrations/errors.d.ts +0 -9
  258. package/dist/ai-service/agent/tools/integrations/errors.d.ts.map +0 -1
  259. package/dist/ai-service/agent/tools/integrations/errors.js +0 -35
  260. package/dist/ai-service/agent/tools/integrations/errors.js.map +0 -1
  261. package/dist/ai-service/facts/helpers.d.ts +0 -9
  262. package/dist/ai-service/facts/helpers.d.ts.map +0 -1
  263. package/dist/ai-service/facts/helpers.js +0 -72
  264. package/dist/ai-service/facts/helpers.js.map +0 -1
  265. package/dist/ai-service/facts/index.d.ts +0 -4
  266. package/dist/ai-service/facts/index.d.ts.map +0 -1
  267. package/dist/ai-service/facts/index.js +0 -3
  268. package/dist/ai-service/facts/index.js.map +0 -1
  269. package/dist/ai-service/facts/knowledge-manager.d.ts +0 -50
  270. package/dist/ai-service/facts/knowledge-manager.d.ts.map +0 -1
  271. package/dist/ai-service/facts/knowledge-manager.js +0 -195
  272. package/dist/ai-service/facts/knowledge-manager.js.map +0 -1
  273. package/dist/ai-service/recording/index.d.ts +0 -25
  274. package/dist/ai-service/recording/index.d.ts.map +0 -1
  275. package/dist/ai-service/recording/index.js +0 -27
  276. package/dist/ai-service/recording/index.js.map +0 -1
  277. package/dist/ai-service/recording/recorders/llm-recorder.d.ts +0 -35
  278. package/dist/ai-service/recording/recorders/llm-recorder.d.ts.map +0 -1
  279. package/dist/ai-service/recording/recorders/llm-recorder.js +0 -221
  280. package/dist/ai-service/recording/recorders/llm-recorder.js.map +0 -1
  281. package/dist/ai-service/recording/recorders/socket-recorder.d.ts +0 -38
  282. package/dist/ai-service/recording/recorders/socket-recorder.d.ts.map +0 -1
  283. package/dist/ai-service/recording/recorders/socket-recorder.js +0 -44
  284. package/dist/ai-service/recording/recorders/socket-recorder.js.map +0 -1
  285. package/dist/ai-service/recording/recorders/tool-recorder.d.ts +0 -25
  286. package/dist/ai-service/recording/recorders/tool-recorder.d.ts.map +0 -1
  287. package/dist/ai-service/recording/recorders/tool-recorder.js +0 -58
  288. package/dist/ai-service/recording/recorders/tool-recorder.js.map +0 -1
  289. package/dist/ai-service/recording/recording-manager.d.ts +0 -104
  290. package/dist/ai-service/recording/recording-manager.d.ts.map +0 -1
  291. package/dist/ai-service/recording/recording-manager.js +0 -308
  292. package/dist/ai-service/recording/recording-manager.js.map +0 -1
  293. package/dist/ai-service/recording/storage/session-recording-storage.d.ts +0 -143
  294. package/dist/ai-service/recording/storage/session-recording-storage.d.ts.map +0 -1
  295. package/dist/ai-service/recording/storage/session-recording-storage.js +0 -374
  296. package/dist/ai-service/recording/storage/session-recording-storage.js.map +0 -1
  297. package/dist/ai-service/recording/types.d.ts +0 -148
  298. package/dist/ai-service/recording/types.d.ts.map +0 -1
  299. package/dist/ai-service/recording/types.js +0 -8
  300. package/dist/ai-service/recording/types.js.map +0 -1
  301. package/dist/ai-service/skills/system/_registry.generated.d.ts +0 -6
  302. package/dist/ai-service/skills/system/_registry.generated.d.ts.map +0 -1
  303. package/dist/ai-service/skills/system/_registry.generated.js +0 -24
  304. package/dist/ai-service/skills/system/_registry.generated.js.map +0 -1
  305. package/dist/ai-service/skills/system/superblocks-frontend/references/embedding.generated.d.ts +0 -2
  306. package/dist/ai-service/skills/system/superblocks-frontend/references/embedding.generated.d.ts.map +0 -1
  307. package/dist/ai-service/skills/system/superblocks-frontend/references/embedding.generated.js +0 -155
  308. package/dist/ai-service/skills/system/superblocks-frontend/references/embedding.generated.js.map +0 -1
  309. package/dist/util/log-sanitizer.d.ts +0 -42
  310. package/dist/util/log-sanitizer.d.ts.map +0 -1
  311. package/dist/util/log-sanitizer.js +0 -177
  312. package/dist/util/log-sanitizer.js.map +0 -1
@@ -7,9 +7,9 @@ Reference documentation for working with SQL databases in Superblocks APIs.
7
7
  ## Supported Databases
8
8
 
9
9
  - PostgreSQL, MySQL, MariaDB, MSSQL
10
- - Snowflake, Redshift, BigQuery, Athena
11
- - Databricks, SingleStore, Lakebase
12
- - CockroachDB, YugabyteDB, OracleDB
10
+ - Snowflake, Redshift, BigQuery
11
+ - Databricks, SingleStore
12
+ - CockroachDB, YugabyteDB
13
13
 
14
14
  ## SQL Block Classes
15
15
 
@@ -23,10 +23,8 @@ import {
23
23
  Snowflake,
24
24
  Redshift,
25
25
  BigQuery,
26
- Athena,
27
26
  Databricks,
28
27
  SingleStore,
29
- OracleDB,
30
28
  } from "@superblocksteam/library";
31
29
  \`\`\`
32
30
 
@@ -40,45 +38,7 @@ new PostgreSQL("get_users", "postgres-integration-id", {
40
38
 
41
39
  ## Parameterized Queries
42
40
 
43
- ### SQL Security Priority
44
-
45
- **ALWAYS prefer parameterized queries over string interpolation for user input values.**
46
-
47
- Use \`parameters: "[var1, var2]"\` with the database-specific SQL placeholders:
48
-
49
- | Database | Placeholder Syntax | Example |
50
- |----------|-------------------|---------|
51
- | PostgreSQL, Redshift, CockroachDB | \`$1\`, \`$2\`, \`$3\` | \`WHERE id = $1 AND status = $2\` |
52
- | MySQL, MariaDB, Snowflake, BigQuery, Athena | \`?\`, \`?\`, \`?\` | \`WHERE id = ? AND status = ?\` |
53
- | MSSQL | \`@PARAM_1\`, \`@PARAM_2\` | \`WHERE id = @PARAM_1 AND status = @PARAM_2\` |
54
- | Databricks | \`:PARAM_1\`, \`:PARAM_2\` | \`WHERE id = :PARAM_1 AND status = :PARAM_2\` |
55
- | OracleDB | \`:1\`, \`:2\`, \`:3\` | \`WHERE id = :1 AND status = :2\` |
56
-
57
- Only use binding functions for truly dynamic SQL elements like table/column names.
58
-
59
- ### Parameters Syntax vs Statement Syntax
60
-
61
- **Important:** \`parameters\` is a JavaScript expression string that gets evaluated directly. Do NOT use \`\${}\` interpolation or binding functions.
62
-
63
- \`\`\`typescript
64
- // ❌ WRONG - Don't use \${} interpolation in parameters
65
- parameters: "[\${build_query.output.userId}, \${searchTerm}]"
66
-
67
- // ❌ WRONG - Don't use binding functions for parameters
68
- parameters: ({ build_query }) => JSON.stringify(build_query.output.params)
69
-
70
- // ✅ CORRECT - Write expressions directly (they get evaluated as JS)
71
- parameters: "[build_query.output.userId, searchTerm, limit]"
72
-
73
- // ✅ CORRECT - Reference block output array directly
74
- parameters: "build_query.output.params"
75
- \`\`\`
76
-
77
- This is different from \`statement\`, where binding functions with \`\${}\` ARE used to interpolate values into SQL.
78
-
79
- ### String Interpolation (Alternative)
80
-
81
- For simpler cases, string interpolation also works:
41
+ **ALWAYS use parameterized queries for user input:**
82
42
 
83
43
  \`\`\`typescript
84
44
  // ✅ CORRECT - String interpolation for WHERE clauses
@@ -94,38 +54,9 @@ new PostgreSQL("insert_user", "postgres-id", {
94
54
  })
95
55
  \`\`\`
96
56
 
97
- ### Dynamic SQL with Optional Filters
98
-
99
- Use the \`parameters\` array with the "OR NULL" pattern for optional filters:
100
- - \`WHERE (column = $1 OR $1::type IS NULL)\` makes the condition a no-op when parameter is null
101
- - Cast parameters to their type when checking for NULL (PostgreSQL can't infer types from NULL values)
102
- - Always pass all parameters, using null for unused filters
103
- - NEVER interpolate user values directly into SQL strings
104
-
105
57
  ## Best Practices
106
58
 
107
- ### 1. ONE Query Per Block Rule
108
-
109
- Each SQL block (PostgreSQL, Snowflake, MySQL, MicrosoftSql, Databricks) can execute **ONLY ONE SQL query**.
110
-
111
- ❌ **WRONG - Multiple queries in one block:**
112
- \`\`\`sql
113
- UPDATE users SET status = 'active';
114
- DELETE FROM logs WHERE created < '2023-01-01';
115
- INSERT INTO audit VALUES ('done');
116
- \`\`\`
117
-
118
- ✅ **CORRECT - One query per block:**
119
- \`\`\`typescript
120
- new PostgreSQL("update_status", "postgres-id", {
121
- statement: "UPDATE users SET status = 'active'"
122
- }),
123
- new PostgreSQL("clean_logs", "postgres-id", {
124
- statement: "DELETE FROM logs WHERE created < '2023-01-01'"
125
- })
126
- \`\`\`
127
-
128
- ### 2. Use Meaningful Block Names
59
+ ### 1. Use Meaningful Block Names
129
60
 
130
61
  \`\`\`typescript
131
62
  // ✅ GOOD
@@ -137,7 +68,7 @@ new PostgreSQL("query1", "pg-id", { ... })
137
68
  new PostgreSQL("sql", "pg-id", { ... })
138
69
  \`\`\`
139
70
 
140
- ### 3. Always Specify Columns
71
+ ### 2. Always Specify Columns
141
72
 
142
73
  \`\`\`typescript
143
74
  // ✅ PREFERRED - Explicit columns
@@ -147,44 +78,14 @@ SELECT id, name, email, created_at FROM users
147
78
  SELECT * FROM users
148
79
  \`\`\`
149
80
 
150
- ### 4. Always Add Defensive Row Limits
81
+ ### 3. Use LIMIT for Safety
151
82
 
152
- Always include a row limit clause to prevent runaway queries. Use 100 as the default unless user specifies otherwise.
153
-
154
- Different SQL dialects have different syntax:
155
- - **MySQL/PostgreSQL/SQLite**: \`LIMIT N\`
156
- - **SQL Server**: \`SELECT TOP N\`
157
- - **ANSI SQL (SQL Server, Oracle, DB2)**: \`OFFSET 0 ROWS FETCH NEXT N ROWS ONLY\`
158
-
159
- \`\`\`sql
160
- -- ✅ PostgreSQL/MySQL
161
- SELECT * FROM orders ORDER BY created_at DESC LIMIT 100;
162
-
163
- -- ✅ SQL Server
164
- SELECT TOP 100 * FROM orders ORDER BY created_at DESC;
165
-
166
- -- ✅ ANSI SQL (SQL Server with ORDER BY)
167
- SELECT * FROM orders ORDER BY created_at DESC OFFSET 0 ROWS FETCH NEXT 100 ROWS ONLY;
168
-
169
- -- ❌ Avoid unlimited queries
170
- SELECT * FROM orders ORDER BY created_at DESC; -- Can timeout or crash
171
- \`\`\`
172
-
173
- ### 5. Sort, Don't Filter by Date (Default)
174
-
175
- Do NOT add automatic date filters (e.g., "last 90 days") unless the user explicitly requests them. This is a common cause of unexpected empty SQL results.
176
-
177
- \`\`\`sql
178
- -- ✅ Default approach
179
- SELECT * FROM orders ORDER BY created_at DESC LIMIT 100;
180
-
181
- -- ❌ Avoid automatic filtering
182
- SELECT * FROM orders WHERE created_at >= CURRENT_DATE - INTERVAL '90 days'; -- Can return empty results
83
+ \`\`\`typescript
84
+ // ✅ Always include LIMIT for queries that could return many rows
85
+ SELECT * FROM orders LIMIT 1000
183
86
  \`\`\`
184
87
 
185
- Only add date WHERE clauses when users explicitly ask for time-based filtering.
186
-
187
- ### 6. Handle NULL Values
88
+ ### 4. Handle NULL Values
188
89
 
189
90
  \`\`\`typescript
190
91
  // ✅ Use COALESCE for default values
@@ -211,10 +112,6 @@ new PostgreSQL("json_query", "pg-id", {
211
112
  })
212
113
  \`\`\`
213
114
 
214
- - Use schema-qualified names: \`schema.table\` or \`"schema"."table"\`
215
- - Case sensitivity: Unquoted identifiers are lowercase
216
- - Use \`::type\` for type casting
217
-
218
115
  ### Snowflake
219
116
 
220
117
  \`\`\`typescript
@@ -228,35 +125,6 @@ new Snowflake("ranked_query", "snowflake-id", {
228
125
  })
229
126
  \`\`\`
230
127
 
231
- **Snowflake Two-Part Naming:** Snowflake uses \`schema.table\`
232
-
233
- When you see Snowflake metadata where tables have a \`schema\` property, **you MUST qualify table names**:
234
-
235
- \`\`\`sql
236
- -- If table has schema property "MASTERDATA"
237
- SELECT * FROM MASTERDATA.PRODUCTLINE -- ✅ Fully qualified
238
- SELECT * FROM PRODUCTLINE -- ❌ Will fail if no default schema
239
- \`\`\`
240
-
241
- **Rule**: If a table object has a non-empty \`schema\` property, use \`{schema}.{name}\` format in your SQL queries.
242
-
243
- ### Databricks
244
-
245
- **Databricks Three-Part Naming:** Databricks uses \`catalog.schema.table\`
246
-
247
- When you see Databricks metadata like:
248
- - \`uber.default.orders\` - Use the FULL path: \`uber.default.orders\`
249
- - \`production.analytics.users\` - Use: \`production.analytics.users\`
250
-
251
- \`\`\`sql
252
- -- Metadata shows: uber.default.orders
253
- SELECT * FROM uber.default.orders -- ✅ Full path
254
- SELECT * FROM uber.orders -- ❌ Missing schema part
255
- SELECT * FROM orders -- ❌ Missing catalog and schema
256
- \`\`\`
257
-
258
- **Note:** The word "default" in Databricks paths is NOT optional - it's the actual schema name. Always include all three parts exactly as shown in the metadata.
259
-
260
128
  ### BigQuery
261
129
 
262
130
  \`\`\`typescript
@@ -1 +1 @@
1
- {"version":3,"file":"sql-databases.generated.js","sourceRoot":"","sources":["../../../../../../src/ai-service/skills/system/superblocks-api/references/sql-databases.generated.ts"],"names":[],"mappings":"AAAA,+FAA+F;AAC/F,mDAAmD;AAEnD,MAAM,CAAC,MAAM,OAAO,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAyVtB,CAAC"}
1
+ {"version":3,"file":"sql-databases.generated.js","sourceRoot":"","sources":["../../../../../../src/ai-service/skills/system/superblocks-api/references/sql-databases.generated.ts"],"names":[],"mappings":"AAAA,+FAA+F;AAC/F,mDAAmD;AAEnD,MAAM,CAAC,MAAM,OAAO,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAqNtB,CAAC"}
@@ -1,2 +1,2 @@
1
- export declare const content = "---\nname: superblocks-api\ndescription: |\n Build backend APIs using Superblocks workflow blocks.\n Use when creating or modifying APIs, working with integrations, explaining API patterns, or troubleshooting API issues.\nreadOnly: true\nmetadata:\n author: superblocks\n version: \"1.0\"\n---\n\n# Superblocks API Development\n\nThis skill covers building backend APIs using Superblocks workflow blocks, integrations, and control flow patterns.\n\n## Mental Model\n\nAPIs in Superblocks are backend logic blocks that run in a secure server environment. They:\n- Execute integrations (database queries, API calls, etc.)\n- Process data with JavaScript or Python\n- Return data to the frontend\n- **Cannot** directly modify UI state\n\n**Superblocks APIs are NOT traditional backend services.** They are frontend-coupled workflow builders that:\n- Build declarative workflows using a chain of blocks\n- Receive input parameters passed from the frontend\n- Are visualized in the Superblocks editor\n\n## API File Structure\n\n```typescript\n// Path: /apis/apiName.ts\n\n// \u2705 ALWAYS import required types from the library\nimport {\n Api,\n JavaScript,\n Python,\n PostgreSQL,\n Snowflake,\n RestApi,\n OpenApi,\n GraphQL,\n S3,\n Email,\n Conditional,\n TryCatch,\n Loop,\n Parallel,\n Variables,\n Throw,\n Return,\n Break,\n} from \"@superblocksteam/library\";\n\n// \u274C NEVER define constants here - they won't be serialized!\n\n// \u2705 ALL logic must be inside new Api()\nexport default new Api(\"apiName\", [\n // Workflow blocks here\n]);\n```\n\n**\uD83D\uDEA8 CRITICAL:** Only code inside `new Api()` is serialized. Constants/helpers defined outside cause `ReferenceError` at runtime.\n\n## \uD83D\uDD0D Integration Exploration Workflow (CRITICAL)\n\nWhen exploring integrations and data sources, use `grepMetadata` to understand schema before querying:\n\n### 1. Start with metadata exploration\n\nUse `grepMetadata` to understand:\n- What tables/endpoints exist\n- Schema structure and\n- Available fields and data types\n\n**\uD83D\uDCA1 KEY PRINCIPLE:** For \"tell me about the data\" questions, metadata exploration is usually sufficient and more efficient.\n\n### 2. NEVER use SQL/API queries for metadata exploration\n\n\u274C **WRONG**: `SHOW COLUMNS FROM users`, `DESCRIBE table`, `SELECT * FROM INFORMATION_SCHEMA`\n\u2705 **CORRECT**: `grepMetadata({ grepPattern: \"\\\\.columns\\\\[\\\\d+\\\\]\\\\.name\" })` to find all columns\n\n### 3. Database vs OpenAPI key formats\n\n**DATABASE integrations** (Postgres, MySQL, Snowflake, Databricks):\n- Use **numeric array indices**: `[0]`, `[1]`, `[2]`, etc.\n- Pattern: Use `\\\\d+` to match any number\n- Structure: All databases use `json.dbSchema.schemas[]` and `json.dbSchema.tables[]`\n- **\u26A0\uFE0F CRITICAL**: It's `dbSchema` (NOT `schema`!) - the field name is `dbSchema`\n- Examples:\n - \u2705 `\"\\\\.dbSchema\\\\.schemas\\\\[\\\\d+\\\\]\\\\.name\"` - Find schema names\n - \u2705 `\"\\\\.tables\\\\[\\\\d+\\\\]\\\\.name = \\\\\".*user.*\\\\\"\"` - Find tables\n - \u274C `\"\\\\.schema\\\\.tables\"` - WRONG! It's `dbSchema` not `schema`\n\n**OPENAPI integrations** (REST APIs with OpenAPI specs):\n- Use **string object keys**: `[\"/users\"]`, `[\"/repos\"]`\n- Pattern: Use `.*` to match any key (NOT `\\\\d+`!)\n- Examples:\n - \u2705 `\"\\\\.paths\\\\[\\\\\".*repos.*\\\\\"\\\\]\"` - Find paths with \"repos\"\n - \u274C `\"\\\\.paths\\\\[\\\\d+\\\\]\"` - WRONG! OpenAPI doesn't use numeric indices\n\n### 4. REST API vs OpenAPI Selection\n\n**\uD83D\uDEA8 CRITICAL: When working with REST API integrations:**\n1. ALWAYS call `grepMetadata` first to determine if the REST API is OpenAPI-backed\n2. If metadata shows it's an OpenAPI-backed API, you MUST use the `OpenApi` class with `openapi.path`\n3. Only use `RestApi` class for non-OpenAPI REST integrations\n\n## Core Type Definitions\n\n```typescript\nexport type JsonValue = any;\nexport type State = { [key: string]: JsonValue };\nexport type Binding<T> = T | ((state: State) => T);\n\n// Control Flow Blocks\nexport declare class Conditional extends Block {\n constructor(name: string, config: {\n if: { when: Binding<boolean>; then: Block[] };\n elif?: { when: Binding<boolean>; then: Block[] }[];\n else?: Block[];\n });\n}\n\nexport declare class Loop extends Block {\n constructor(name: string, config:\n | { type?: \"TYPE_FOREACH\"; over: Binding<JsonValue[]>; variables: { item: string; index: string }; blocks: Block[] }\n | { type: \"TYPE_WHILE\"; condition: Binding<boolean>; blocks: Block[] }\n );\n}\n\nexport declare class Parallel extends Block {\n constructor(name: string, config:\n | { mode: \"dynamic\"; over: Binding<JsonValue[]>; blocks: Block[] }\n | { mode: \"static\"; paths: Record<string, Block[]> }\n );\n}\n\nexport declare class Variables extends Block {\n constructor(name: string, variables: { key: string; value: Binding<JsonValue> }[]);\n}\n\nexport declare class TryCatch extends Block {\n constructor(name: string, config: {\n try: Block[];\n catch: Block[];\n finally?: Block[];\n variables: { error: string };\n });\n}\n\nexport declare class Throw extends Block {\n constructor(name: string, config: { error: Binding<JsonValue> });\n}\n\nexport declare class Return extends Block {\n constructor(name: string, config: { data: Binding<JsonValue> });\n}\n\nexport declare class Break extends Block {\n constructor(name: string, config: { condition: Binding<JsonValue> });\n}\n\n// API Authorization\nexport type Authorization =\n | { type: \"AUTHORIZATION_TYPE_APP_USERS\" }\n | { type: \"AUTHORIZATION_TYPE_JS_EXPRESSION\"; expression: Binding<boolean> };\n\nexport declare class Api {\n constructor(name: string, blocks?: Block[], authorization?: Authorization);\n}\n```\n\n## Block Output Scoping Rules\n\n**CRITICAL: Blocks can only access outputs from specific scopes.**\n\n### What blocks CAN access:\n1. **Previous sibling blocks** at the same level (executed before them)\n2. **ALL ancestor block outputs** (parent, grandparent, etc.)\n3. **Parent control flow variables** (e.g., `item` and `index` in Loop)\n4. **Control flow block outputs** (equals output of their last child block)\n\n### What blocks CANNOT access:\n- \u274C Outputs from blocks nested inside other control flow blocks\n- \u274C Outputs from blocks in other Conditional branches\n- \u274C Outputs from blocks that come after them\n\n### Variable Access Patterns\n\n```typescript\n// \u2705 CORRECT: Destructure variables/blocks you need\nwhen: ({ hasMore }) => !hasMore.value\nover: ({ items }) => items.output\ncondition: ({ counter }) => counter.value < 10\n\n// \u2705 Multiple variables in one function\nfn: ({ results, page, hasMore }) => {\n results.set([...results.value, ...newItems]);\n page.set(page.value + 1);\n}\n\n// \u274C WRONG: Single param pattern causes runtime error!\nwhen: (p) => !p.hasMore.value // TypeError!\n```\n\n**Access patterns by type:**\n- **API Inputs**: Access directly (no `.value`)\n- **Step Outputs**: Use `.output`\n- **Loop Variables**: Use `.value`\n- **TryCatch Error Variables**: Use `.value`\n- **GraphQL Outputs**: Use `.output.data` (GraphQL returns `{ data: {...}, errors?: [...] }`)\n\n## Input Discovery Rules\n\n**You do NOT need to explicitly declare API inputs.** They are automatically discovered when:\n1. Destructured in block functions but not defined elsewhere\n2. Referenced but not produced by any previous block\n\n### \uD83D\uDEA8 CRITICAL: Always Type Your Input Parameters\n\n```typescript\n// \u2705 CORRECT - Typed parameters\nnew JavaScript(\"validate_email\", {\n fn: ({ email }: { email: string }) => email.includes(\"@\")\n})\n\nnew PostgreSQL(\"search_users\", \"postgres-id\", {\n statement: ({ searchTerm, limit }: { searchTerm: string; limit: number }) =>\n `SELECT * FROM users WHERE name ILIKE '%${searchTerm}%' LIMIT ${limit}`\n})\n\n// \u274C WRONG - Untyped parameters\nnew JavaScript(\"validate_email\", {\n fn: ({ email }) => email.includes(\"@\") // \u274C No type!\n})\n```\n\n## SQL Best Practices\n\n### 1. ONE Query Per Block Rule\n\nEach SQL block can execute **ONLY ONE SQL query**.\n\n\u274C **WRONG:**\n```sql\nUPDATE users SET status = 'active';\nDELETE FROM logs WHERE created < '2023-01-01';\n```\n\n\u2705 **CORRECT:**\n```typescript\nnew PostgreSQL(\"update_status\", \"pg-id\", {\n statement: \"UPDATE users SET status = 'active'\"\n}),\nnew PostgreSQL(\"clean_logs\", \"pg-id\", {\n statement: \"DELETE FROM logs WHERE created < '2023-01-01'\"\n})\n```\n\n### 2. Sort, Don't Filter by Date (Default)\n\nDo NOT add automatic date filters unless explicitly requested.\n\n\u2705 **Default:** `SELECT * FROM orders ORDER BY created_at DESC LIMIT 100`\n\u274C **Avoid:** `SELECT * FROM orders WHERE created_at >= CURRENT_DATE - INTERVAL '90 days'`\n\n### 3. Always Add Defensive Row Limits\n\nAlways include a row limit (default 100) to prevent runaway queries.\n\n## Database Naming Conventions\n\n### Databricks Three-Part Naming\n\nDatabricks uses: `catalog.schema.table`\n\n```sql\n-- Metadata shows: uber.default.orders\nSELECT * FROM uber.default.orders -- \u2705 Full path\nSELECT * FROM uber.orders -- \u274C Missing schema part\n```\n\n**Note:** The word \"default\" in Databricks paths is NOT optional - it's the actual schema name.\n\n### Snowflake Two-Part Naming\n\nSnowflake uses: `schema.table`\n\n```sql\n-- If table has schema property \"MASTERDATA\"\nSELECT * FROM MASTERDATA.PRODUCTLINE -- \u2705 Fully qualified\nSELECT * FROM PRODUCTLINE -- \u274C Will fail if no default schema\n```\n\n## Runtime Safety and Defensive Coding\n\n- Use optional chaining and nullish coalescing when producing outputs\n- For REST/OpenAPI/GraphQL responses, treat non-required fields as optional\n- Default to empty arrays/objects when inputs are absent\n\n```typescript\n// \u2705 Defensive transformation\nnew JavaScript(\"normalize_users\", {\n fn: ({ fetch_users }) => (Array.isArray(fetch_users.output) ? fetch_users.output : []).map(u => ({\n id: u.id,\n name: (u.name ?? \"Unknown\").toString()\n }))\n})\n```\n\n## Common API Patterns\n\n### Simple Data Retrieval\n\n```typescript\nexport default new Api(\"getUsersApi\", [\n new PostgreSQL(\"fetch_users\", \"postgres-id\", {\n statement: \"SELECT * FROM users LIMIT 100\"\n })\n]);\n```\n\n### Input Validation + Processing\n\n```typescript\nexport default new Api(\"createUserApi\", [\n new Conditional(\"validate_inputs\", {\n if: {\n when: ({ FirstNameInput, EmailInput }: { FirstNameInput: string; EmailInput: string }) =>\n !FirstNameInput || !EmailInput,\n then: [\n new Throw(\"validation_error\", { error: \"First name and email are required\" })\n ]\n }\n }),\n new JavaScript(\"create_user\", {\n fn: ({ FirstNameInput, EmailInput }: { FirstNameInput: string; EmailInput: string }) => ({\n id: Math.floor(Math.random() * 1000),\n name: FirstNameInput,\n email: EmailInput,\n created_at: new Date().toISOString()\n })\n })\n]);\n```\n\n### Loop with Data Processing\n\n```typescript\nexport default new Api(\"processOrdersApi\", [\n new JavaScript(\"get_orders\", {\n fn: () => [\n { id: 1, status: \"pending\", amount: 100 },\n { id: 2, status: \"pending\", amount: 200 }\n ]\n }),\n new Loop(\"process_each_order\", {\n over: ({ get_orders }) => get_orders.output,\n variables: { item: \"order\", index: \"i\" },\n blocks: [\n new JavaScript(\"calculate_tax\", {\n fn: ({ order, i }) => ({\n ...order.value,\n tax: order.value.amount * 0.1,\n total: order.value.amount * 1.1,\n position: i.value\n })\n })\n ]\n })\n]);\n```\n\n### Variables for Pagination State\n\n```typescript\nexport default new Api(\"paginatedFetchApi\", [\n new Variables(\"pagination_state\", [\n { key: \"allResults\", value: () => [] },\n { key: \"cursor\", value: () => null },\n { key: \"hasMore\", value: () => true },\n ]),\n \n new Loop(\"fetch_all_pages\", {\n type: \"TYPE_FOREACH\",\n over: () => [...Array(100).keys()], // Max iterations safety\n variables: { item: \"_\", index: \"i\" },\n blocks: [\n new Conditional(\"check_done\", {\n if: {\n when: ({ hasMore }) => !hasMore.value,\n then: [new Break(\"exit_loop\", { condition: () => true })]\n }\n }),\n new RestApi(\"fetch_page\", \"rest-api-id\", {\n method: \"GET\",\n url: ({ cursor }) => `https://api.example.com/items${cursor.value ? `?cursor=${cursor.value}` : \"\"}`,\n }),\n new JavaScript(\"accumulate\", {\n fn: ({ fetch_page, allResults, cursor, hasMore }) => {\n const response = fetch_page.output;\n allResults.set([...allResults.value, ...response.items]);\n cursor.set(response.nextCursor);\n hasMore.set(response.hasMore);\n return allResults.value;\n }\n })\n ]\n }),\n \n new JavaScript(\"return_results\", {\n fn: ({ allResults }) => allResults.value\n })\n]);\n```\n\n### File Uploads to S3/GCS\n\n**Frontend wraps files in `{ files: [...] }` format:**\n```typescript\nconst response = await runUploadApi({ userFiles: { files: selectedFiles } });\n```\n\n**Backend API - pass files directly:**\n```typescript\nexport default new Api(\"uploadFilesApi\", [\n new S3(\"upload_files\", \"your-s3-integration-id\", {\n action: \"UPLOAD_MULTIPLE_OBJECTS\",\n resource: ({ bucketName }) => bucketName,\n fileObjects: ({ userFiles }) => userFiles.files // Direct pass-through\n })\n]);\n```\n\n### Reading File Content in JavaScript\n\n```typescript\nnew JavaScript(\"parse_csv\", {\n fn: async ({ csvFile }) => {\n const file = csvFile.files[0];\n const content = await file.readContentsAsync();\n const headers = content.split(\"\\n\")[0].split(\",\").map(h => h.trim());\n return { fileName: file.name, headers };\n }\n})\n```\n\n## Error Handling Guidelines\n\n**IMPORTANT: Do NOT use TryCatch blocks by default.** Only use when truly necessary.\n\n### \u274C DO NOT use TryCatch for:\n- Standard database queries\n- Simple data transformations\n\n### \u2705 DO use TryCatch when:\n- User explicitly requests error handling\n- Continuing execution after failure is business-critical\n- Partial failure recovery in loops\n- Graceful degradation with fallback data\n\n## Error Recovery Strategies\n\nWhen you encounter errors while building APIs:\n\n### Read Error Messages Carefully\n\nError messages contain specific guidance on how to fix the problem. Pay close attention to:\n- What operation failed (compilation, validation, execution)\n- Suggestions for how to resolve the issue\n- Whether metadata is missing\n\n### When to Check Integration Metadata\n\nIf you encounter errors mentioning:\n- \"unknown column\", \"table not found\", \"invalid field\"\n- \"check integration metadata\"\n- Integration type mismatches\n\nYou MUST call `grepMetadata` to get the correct schema/table structure before retrying.\n\n## Loop Control\n\n### Loop Types\n\n- **TYPE_FOREACH** (default): Iterates over an array using `over`. Provides `item` and `index` variables.\n- **TYPE_WHILE**: Repeats while `condition` is true. Provides only `index` variable.\n\n**Breaking out of loops:**\n```typescript\nnew Loop(\"process_until_complete\", {\n over: ({ items }) => items.output,\n variables: { item: \"current\", index: \"i\" },\n blocks: [\n new Conditional(\"check_stop_condition\", {\n if: {\n when: ({ current }) => current.value.status === \"complete\",\n then: [\n new Break(\"exit_loop\", { condition: () => true }) // \u2705 Only way to exit\n ]\n }\n }),\n new JavaScript(\"process_item\", {\n fn: ({ current, i }) => ({\n processed: current.value,\n position: i.value\n })\n })\n ]\n})\n```\n\n## Response Interface Guidelines\n\nThe `responseInterface` describes what external code gets from `apiName.response`. Internal blocks/steps are NOT visible externally.\n\n### Direct Response Types\n\n\u2705 **CORRECT**: Direct array response\n```typescript\ninterface GetUsersApiResponse {\n id: number;\n name: string;\n email: string;\n}[]\n```\n\n\u2705 **CORRECT**: Direct data structure\n```typescript\ninterface GetOrdersApiResponse {\n orders: Order[];\n totalCount: number;\n}\n```\n\n\u274C **WRONG**: Exposing internal steps\n```typescript\ninterface GetOrdersApiResponse {\n fetchStep: { output: Order[] }; // \u274C Steps are internal\n countStep: { output: number }; // \u274C Not visible outside\n}\n```\n\n### Type Safety for API Response Interfaces\n\n**CRITICAL: When defining response interfaces, consider runtime reality, not just happy-path data.**\n\nWhen uncertain if an API field will always be present, mark it optional:\n\n```typescript\n// \u2705 CORRECT - Accounts for real-world API behavior\ninterface GitHubPRResponse {\n id: number;\n title: string;\n user?: { // \u2190 Optional, can be null for deleted users\n login: string;\n avatar_url: string;\n } | null;\n labels?: Label[]; // \u2190 Optional, might be omitted in response\n}\n```\n\nMark fields optional when:\n1. **User/account references** - Can be null for deleted/deactivated accounts\n2. **Nested objects** - May be omitted in partial responses\n3. **Third-party APIs** - GitHub, Stripe, etc. often have nullable fields\n4. **Loading states** - Data may not be available during initial render\n5. **Uncertain API behavior** - When in doubt, mark optional\n\n## Permissions (Global Object)\n\nFor user-specific operations, use the `Global` object (injected by backend):\n\n```typescript\ntype Global = {\n user: {\n email: string;\n username: string;\n id: string;\n name: string;\n groups: Group[]\n };\n};\n```\n\n### Groups Check Pattern\n\n```typescript\nnew JavaScript(\"check_groups\", {\n fn: ({ Global }) => {\n const isFieldEngUser = Global.groups.some(group => group.name === \"FieldEngineer\");\n if (isFieldEngUser) {\n // Perform actions for FieldEngineer\n } else {\n // Perform actions for non-FieldEngineer\n }\n return { isAdmin: Global.groups.some(g => g.name === \"Admin\"), userId: Global.user.id };\n }\n})\n```\n\n**NEVER rely on frontend data for security-critical operations.**\n\n## Critical Mistakes to Avoid\n\n### 1. Defining Constants Outside the API\n\n```typescript\n// \u274C WRONG - Not serialized!\nconst MAX_BATCHES = 100;\nexport default new Api(\"MyApi\", [\n new Loop(\"loop\", {\n condition: ({ count }) => count.value < MAX_BATCHES, // ReferenceError!\n blocks: [...]\n })\n]);\n\n// \u2705 CORRECT - Use Variables block\nexport default new Api(\"MyApi\", [\n new Variables(\"state\", [\n { key: \"maxBatches\", value: () => 100 },\n ]),\n new Loop(\"loop\", {\n condition: ({ count, maxBatches }) => count.value < maxBatches.value,\n blocks: [...]\n })\n]);\n```\n\n### 2. Wrong Language for Integration Type\n\n```typescript\n// \u274C WRONG - JavaScript in SQL block\nnew PostgreSQL(\"bad\", \"id\", {\n statement: ({ userId }) => `SELECT * FROM users WHERE id = ${userId}`\n})\n\n// \u274C WRONG - SQL in JavaScript block\nnew JavaScript(\"bad\", {\n fn: \"SELECT * FROM users\" // This is SQL!\n})\n\n// \u2705 CORRECT\nnew PostgreSQL(\"good\", \"id\", {\n statement: ({ userId }: { userId: string }) => `SELECT * FROM users WHERE id = '${userId}'`\n})\n```\n\n### 3. Fake Integration IDs\n\n```typescript\n// \u274C NEVER make up integration IDs\nnew PostgreSQL(\"query\", \"fake-postgres-id\", { ... })\n```\n\n### 4. APIs Cannot Set Frontend State\n\n```typescript\n// \u274C WRONG - Cannot set state in APIs\nnew JavaScript(\"update\", {\n fn: ({ userData }) => {\n userNameVar.value = userData.name; // \u274C Cannot do this!\n return userData;\n }\n})\n\n// \u2705 CORRECT - Return data, frontend handles state\nnew JavaScript(\"update\", {\n fn: ({ userData }) => ({\n ...userData,\n fullName: `${userData.firstName} ${userData.lastName}`\n })\n})\n```\n\n### 5. Return Blocks Cannot Contain Statements\n\n```typescript\n// \u2705 CORRECT - Returns data immediately\nnew Return(\"test_return\", {\n data: (({ records }) => ({ records, totalCount: records.length }))()\n})\n\n// \u274C WRONG - Contains statements\nnew Return(\"test_return\", {\n data: (({ records }) => {\n const totalCount = records.length; // \u274C Statement not allowed\n return { records, totalCount };\n })()\n})\n```\n\n## When to Load References\n\nFor integration-specific guidance, load the appropriate reference file:\n\n- SQL databases (PostgreSQL, MySQL, Snowflake, etc.) \u2192 `references/sql-databases.md`\n- REST APIs and OpenAPI \u2192 `references/rest-apis.md`\n- GraphQL \u2192 `references/graphql.md`\n- JavaScript/Python blocks \u2192 `references/code-blocks.md`\n\n## API Checklist\n\nWhen creating APIs:\n\n1. \u2705 Correct language for each integration type\n2. \u2705 Use `OpenApi` class when `grepMetadata` shows OpenAPI spec\n3. \u2705 All imports included\n4. \u2705 Correct variable access patterns (`.value`, `.output`, `.output.data` for GraphQL)\n5. \u2705 No fake integration IDs\n6. \u2705 No placeholder logic\n7. \u2705 Descriptive block names\n8. \u2705 Error handling only where appropriate\n9. \u2705 NEVER change API name when editing existing API\n10. \u2705 ALWAYS test after building\n";
1
+ export declare const content = "---\nname: superblocks-api\ndescription: |\n Build backend APIs using Superblocks workflow blocks.\n Use when creating or modifying APIs, working with integrations, explaining API patterns, or troubleshooting API issues.\nreadOnly: true\nmetadata:\n author: superblocks\n version: \"1.0\"\n---\n\n# Superblocks API Development\n\nThis skill covers building backend APIs using Superblocks workflow blocks, integrations, and control flow patterns.\n\n## Mental Model\n\nAPIs in Superblocks are backend logic blocks that run in a secure server environment. They:\n- Execute integrations (database queries, API calls, etc.)\n- Process data with JavaScript or Python\n- Return data to the frontend\n- **Cannot** directly modify UI state\n\n**Superblocks APIs are NOT traditional backend services.** They are frontend-coupled workflow builders that:\n- Build declarative workflows using a chain of blocks\n- Receive input parameters passed from the frontend\n- Are visualized in the Superblocks editor\n\n## API File Structure\n\n```typescript\n// Path: /apis/apiName.ts\n\n// \u2705 ALWAYS import required types from the library\nimport {\n Api,\n JavaScript,\n Python,\n PostgreSQL,\n Snowflake,\n RestApi,\n OpenApi,\n GraphQL,\n S3,\n Email,\n Conditional,\n TryCatch,\n Loop,\n Parallel,\n Variables,\n Throw,\n Return,\n Break,\n} from \"@superblocksteam/library\";\n\n// \u274C NEVER define constants here - they won't be serialized!\n\n// \u2705 ALL logic must be inside new Api()\nexport default new Api(\"apiName\", [\n // Workflow blocks here\n]);\n```\n\n**\uD83D\uDEA8 CRITICAL:** Only code inside `new Api()` is serialized. Constants/helpers defined outside cause `ReferenceError` at runtime.\n\n## \uD83D\uDD0D Integration Exploration Workflow (CRITICAL)\n\nWhen exploring integrations and data sources, use `grepMetadata` to understand schema before querying:\n\n### 1. Start with metadata exploration\n\nUse `grepMetadata` to understand:\n- What tables/endpoints exist\n- Schema structure and organization\n- Available fields and data types\n\n**\uD83D\uDCA1 KEY PRINCIPLE:** For \"tell me about the data\" questions, metadata exploration is usually sufficient and more efficient.\n\n### 2. NEVER use SQL/API queries for metadata exploration\n\n\u274C **WRONG**: `SHOW COLUMNS FROM users`, `DESCRIBE table`, `SELECT * FROM INFORMATION_SCHEMA`\n\u2705 **CORRECT**: `grepMetadata({ grepPattern: \"\\\\.columns\\\\[\\\\d+\\\\]\\\\.name\" })` to find all columns\n\n### 3. Database vs OpenAPI key formats\n\n**DATABASE integrations** (Postgres, MySQL, Snowflake, Databricks):\n- Use **numeric array indices**: `[0]`, `[1]`, `[2]`, etc.\n- Pattern: Use `\\\\d+` to match any number\n- Structure: All databases use `json.dbSchema.schemas[]` and `json.dbSchema.tables[]`\n- **\u26A0\uFE0F CRITICAL**: It's `dbSchema` (NOT `schema`!) - the field name is `dbSchema`\n- Examples:\n - \u2705 `\"\\\\.dbSchema\\\\.schemas\\\\[\\\\d+\\\\]\\\\.name\"` - Find schema names\n - \u2705 `\"\\\\.tables\\\\[\\\\d+\\\\]\\\\.name = \\\\\".*user.*\\\\\"\"` - Find tables\n - \u274C `\"\\\\.schema\\\\.tables\"` - WRONG! It's `dbSchema` not `schema`\n\n**OPENAPI integrations** (REST APIs with OpenAPI specs):\n- Use **string object keys**: `[\"/users\"]`, `[\"/repos\"]`\n- Pattern: Use `.*` to match any key (NOT `\\\\d+`!)\n- Examples:\n - \u2705 `\"\\\\.paths\\\\[\\\\\".*repos.*\\\\\"\\\\]\"` - Find paths with \"repos\"\n - \u274C `\"\\\\.paths\\\\[\\\\d+\\\\]\"` - WRONG! OpenAPI doesn't use numeric indices\n\n### 4. REST API vs OpenAPI Selection\n\n**\uD83D\uDEA8 CRITICAL: When working with REST API integrations:**\n1. ALWAYS call `grepMetadata` first to determine if the REST API is OpenAPI-backed\n2. If metadata shows it's an OpenAPI-backed API, you MUST use the `OpenApi` class with `openapi.path`\n3. Only use `RestApi` class for non-OpenAPI REST integrations\n\n## Core Type Definitions\n\n```typescript\nexport type JsonValue = any;\nexport type State = { [key: string]: JsonValue };\nexport type Binding<T> = T | ((state: State) => T);\n\n// Control Flow Blocks\nexport declare class Conditional extends Block {\n constructor(name: string, config: {\n if: { when: Binding<boolean>; then: Block[] };\n elif?: { when: Binding<boolean>; then: Block[] }[];\n else?: Block[];\n });\n}\n\nexport declare class Loop extends Block {\n constructor(name: string, config:\n | { type?: \"TYPE_FOREACH\"; over: Binding<JsonValue[]>; variables: { item: string; index: string }; blocks: Block[] }\n | { type: \"TYPE_WHILE\"; condition: Binding<boolean>; blocks: Block[] }\n );\n}\n\nexport declare class Parallel extends Block {\n constructor(name: string, config:\n | { mode: \"dynamic\"; over: Binding<JsonValue[]>; blocks: Block[] }\n | { mode: \"static\"; paths: Record<string, Block[]> }\n );\n}\n\nexport declare class Variables extends Block {\n constructor(name: string, variables: { key: string; value: Binding<JsonValue> }[]);\n}\n\nexport declare class TryCatch extends Block {\n constructor(name: string, config: {\n try: Block[];\n catch: Block[];\n finally?: Block[];\n variables: { error: string };\n });\n}\n\nexport declare class Throw extends Block {\n constructor(name: string, config: { error: Binding<JsonValue> });\n}\n\nexport declare class Return extends Block {\n constructor(name: string, config: { data: Binding<JsonValue> });\n}\n\nexport declare class Break extends Block {\n constructor(name: string, config: { condition: Binding<JsonValue> });\n}\n\n// API Authorization\nexport type Authorization =\n | { type: \"AUTHORIZATION_TYPE_APP_USERS\" }\n | { type: \"AUTHORIZATION_TYPE_JS_EXPRESSION\"; expression: Binding<boolean> };\n\nexport declare class Api {\n constructor(name: string, blocks?: Block[], authorization?: Authorization);\n}\n```\n\n## Block Output Scoping Rules\n\n**CRITICAL: Blocks can only access outputs from specific scopes.**\n\n### What blocks CAN access:\n1. **Previous sibling blocks** at the same level (executed before them)\n2. **ALL ancestor block outputs** (parent, grandparent, etc.)\n3. **Parent control flow variables** (e.g., `item` and `index` in Loop)\n4. **Control flow block outputs** (equals output of their last child block)\n\n### What blocks CANNOT access:\n- \u274C Outputs from blocks nested inside other control flow blocks\n- \u274C Outputs from blocks in other Conditional branches\n- \u274C Outputs from blocks that come after them\n\n### Variable Access Patterns\n\n```typescript\n// \u2705 CORRECT: Destructure variables/blocks you need\nwhen: ({ hasMore }) => !hasMore.value\nover: ({ items }) => items.output\ncondition: ({ counter }) => counter.value < 10\n\n// \u2705 Multiple variables in one function\nfn: ({ results, page, hasMore }) => {\n results.set([...results.value, ...newItems]);\n page.set(page.value + 1);\n}\n\n// \u274C WRONG: Single param pattern causes runtime error!\nwhen: (p) => !p.hasMore.value // TypeError!\n```\n\n**Access patterns by type:**\n- **API Inputs**: Access directly (no `.value`)\n- **Step Outputs**: Use `.output`\n- **Loop Variables**: Use `.value`\n- **TryCatch Error Variables**: Use `.value`\n- **GraphQL Outputs**: Use `.output.data` (GraphQL returns `{ data: {...}, errors?: [...] }`)\n\n## Input Discovery Rules\n\n**You do NOT need to explicitly declare API inputs.** They are automatically discovered when:\n1. Destructured in block functions but not defined elsewhere\n2. Referenced but not produced by any previous block\n\n### \uD83D\uDEA8 CRITICAL: Always Type Your Input Parameters\n\n```typescript\n// \u2705 CORRECT - Typed parameters\nnew JavaScript(\"validate_email\", {\n fn: ({ email }: { email: string }) => email.includes(\"@\")\n})\n\nnew PostgreSQL(\"search_users\", \"postgres-id\", {\n statement: ({ searchTerm, limit }: { searchTerm: string; limit: number }) =>\n `SELECT * FROM users WHERE name ILIKE '%${searchTerm}%' LIMIT ${limit}`\n})\n\n// \u274C WRONG - Untyped parameters\nnew JavaScript(\"validate_email\", {\n fn: ({ email }) => email.includes(\"@\") // \u274C No type!\n})\n```\n\n## SQL Best Practices\n\n### 1. ONE Query Per Block Rule\n\nEach SQL block can execute **ONLY ONE SQL query**.\n\n\u274C **WRONG:**\n```sql\nUPDATE users SET status = 'active';\nDELETE FROM logs WHERE created < '2023-01-01';\n```\n\n\u2705 **CORRECT:**\n```typescript\nnew PostgreSQL(\"update_status\", \"pg-id\", {\n statement: \"UPDATE users SET status = 'active'\"\n}),\nnew PostgreSQL(\"clean_logs\", \"pg-id\", {\n statement: \"DELETE FROM logs WHERE created < '2023-01-01'\"\n})\n```\n\n### 2. Sort, Don't Filter by Date (Default)\n\nDo NOT add automatic date filters unless explicitly requested.\n\n\u2705 **Default:** `SELECT * FROM orders ORDER BY created_at DESC LIMIT 100`\n\u274C **Avoid:** `SELECT * FROM orders WHERE created_at >= CURRENT_DATE - INTERVAL '90 days'`\n\n### 3. Always Add Defensive Row Limits\n\nAlways include a row limit (default 100) to prevent runaway queries.\n\n## Database Naming Conventions\n\n### Databricks Three-Part Naming\n\nDatabricks uses: `catalog.schema.table`\n\n```sql\n-- Metadata shows: uber.default.orders\nSELECT * FROM uber.default.orders -- \u2705 Full path\nSELECT * FROM uber.orders -- \u274C Missing schema part\n```\n\n**Note:** The word \"default\" in Databricks paths is NOT optional - it's the actual schema name.\n\n### Snowflake Two-Part Naming\n\nSnowflake uses: `schema.table`\n\n```sql\n-- If table has schema property \"MASTERDATA\"\nSELECT * FROM MASTERDATA.PRODUCTLINE -- \u2705 Fully qualified\nSELECT * FROM PRODUCTLINE -- \u274C Will fail if no default schema\n```\n\n## Runtime Safety and Defensive Coding\n\n- Use optional chaining and nullish coalescing when producing outputs\n- For REST/OpenAPI/GraphQL responses, treat non-required fields as optional\n- Default to empty arrays/objects when inputs are absent\n\n```typescript\n// \u2705 Defensive transformation\nnew JavaScript(\"normalize_users\", {\n fn: ({ fetch_users }) => (Array.isArray(fetch_users.output) ? fetch_users.output : []).map(u => ({\n id: u.id,\n name: (u.name ?? \"Unknown\").toString()\n }))\n})\n```\n\n## Common API Patterns\n\n### Simple Data Retrieval\n\n```typescript\nexport default new Api(\"getUsersApi\", [\n new PostgreSQL(\"fetch_users\", \"postgres-id\", {\n statement: \"SELECT * FROM users LIMIT 100\"\n })\n]);\n```\n\n### Input Validation + Processing\n\n```typescript\nexport default new Api(\"createUserApi\", [\n new Conditional(\"validate_inputs\", {\n if: {\n when: ({ FirstNameInput, EmailInput }: { FirstNameInput: string; EmailInput: string }) =>\n !FirstNameInput || !EmailInput,\n then: [\n new Throw(\"validation_error\", { error: \"First name and email are required\" })\n ]\n }\n }),\n new JavaScript(\"create_user\", {\n fn: ({ FirstNameInput, EmailInput }: { FirstNameInput: string; EmailInput: string }) => ({\n id: Math.floor(Math.random() * 1000),\n name: FirstNameInput,\n email: EmailInput,\n created_at: new Date().toISOString()\n })\n })\n]);\n```\n\n### Loop with Data Processing\n\n```typescript\nexport default new Api(\"processOrdersApi\", [\n new JavaScript(\"get_orders\", {\n fn: () => [\n { id: 1, status: \"pending\", amount: 100 },\n { id: 2, status: \"pending\", amount: 200 }\n ]\n }),\n new Loop(\"process_each_order\", {\n over: ({ get_orders }) => get_orders.output,\n variables: { item: \"order\", index: \"i\" },\n blocks: [\n new JavaScript(\"calculate_tax\", {\n fn: ({ order, i }) => ({\n ...order.value,\n tax: order.value.amount * 0.1,\n total: order.value.amount * 1.1,\n position: i.value\n })\n })\n ]\n })\n]);\n```\n\n### Variables for Pagination State\n\n```typescript\nexport default new Api(\"paginatedFetchApi\", [\n new Variables(\"pagination_state\", [\n { key: \"allResults\", value: () => [] },\n { key: \"cursor\", value: () => null },\n { key: \"hasMore\", value: () => true },\n ]),\n \n new Loop(\"fetch_all_pages\", {\n type: \"TYPE_FOREACH\",\n over: () => [...Array(100).keys()], // Max iterations safety\n variables: { item: \"_\", index: \"i\" },\n blocks: [\n new Conditional(\"check_done\", {\n if: {\n when: ({ hasMore }) => !hasMore.value,\n then: [new Break(\"exit_loop\", { condition: () => true })]\n }\n }),\n new RestApi(\"fetch_page\", \"rest-api-id\", {\n method: \"GET\",\n url: ({ cursor }) => `https://api.example.com/items${cursor.value ? `?cursor=${cursor.value}` : \"\"}`,\n }),\n new JavaScript(\"accumulate\", {\n fn: ({ fetch_page, allResults, cursor, hasMore }) => {\n const response = fetch_page.output;\n allResults.set([...allResults.value, ...response.items]);\n cursor.set(response.nextCursor);\n hasMore.set(response.hasMore);\n return allResults.value;\n }\n })\n ]\n }),\n \n new JavaScript(\"return_results\", {\n fn: ({ allResults }) => allResults.value\n })\n]);\n```\n\n### File Uploads to S3/GCS\n\n**Frontend wraps files in `{ files: [...] }` format:**\n```typescript\nconst response = await runUploadApi({ userFiles: { files: selectedFiles } });\n```\n\n**Backend API - pass files directly:**\n```typescript\nexport default new Api(\"uploadFilesApi\", [\n new S3(\"upload_files\", \"your-s3-integration-id\", {\n action: \"UPLOAD_MULTIPLE_OBJECTS\",\n resource: ({ bucketName }) => bucketName,\n fileObjects: ({ userFiles }) => userFiles.files // Direct pass-through\n })\n]);\n```\n\n### Reading File Content in JavaScript\n\n```typescript\nnew JavaScript(\"parse_csv\", {\n fn: async ({ csvFile }) => {\n const file = csvFile.files[0];\n const content = await file.readContentsAsync();\n const headers = content.split(\"\\n\")[0].split(\",\").map(h => h.trim());\n return { fileName: file.name, headers };\n }\n})\n```\n\n## Error Handling Guidelines\n\n**IMPORTANT: Do NOT use TryCatch blocks by default.** Only use when truly necessary.\n\n### \u274C DO NOT use TryCatch for:\n- Standard database queries\n- Simple data transformations\n\n### \u2705 DO use TryCatch when:\n- User explicitly requests error handling\n- Continuing execution after failure is business-critical\n- Partial failure recovery in loops\n- Graceful degradation with fallback data\n\n## Permissions (Global Object)\n\nFor user-specific operations, use the `Global` object (injected by backend):\n\n```typescript\nnew JavaScript(\"check_groups\", {\n fn: ({ Global }) => {\n const isAdmin = Global.groups.some(group => group.name === \"Admin\");\n return { isAdmin, userId: Global.user.id };\n }\n})\n```\n\n**NEVER rely on frontend data for security-critical operations.**\n\n## Critical Mistakes to Avoid\n\n### 1. Defining Constants Outside the API\n\n```typescript\n// \u274C WRONG - Not serialized!\nconst MAX_BATCHES = 100;\nexport default new Api(\"MyApi\", [\n new Loop(\"loop\", {\n condition: ({ count }) => count.value < MAX_BATCHES, // ReferenceError!\n blocks: [...]\n })\n]);\n\n// \u2705 CORRECT - Use Variables block\nexport default new Api(\"MyApi\", [\n new Variables(\"state\", [\n { key: \"maxBatches\", value: () => 100 },\n ]),\n new Loop(\"loop\", {\n condition: ({ count, maxBatches }) => count.value < maxBatches.value,\n blocks: [...]\n })\n]);\n```\n\n### 2. Wrong Language for Integration Type\n\n```typescript\n// \u274C WRONG - JavaScript in SQL block\nnew PostgreSQL(\"bad\", \"id\", {\n statement: ({ userId }) => `SELECT * FROM users WHERE id = ${userId}`\n})\n\n// \u274C WRONG - SQL in JavaScript block\nnew JavaScript(\"bad\", {\n fn: \"SELECT * FROM users\" // This is SQL!\n})\n\n// \u2705 CORRECT\nnew PostgreSQL(\"good\", \"id\", {\n statement: ({ userId }: { userId: string }) => `SELECT * FROM users WHERE id = '${userId}'`\n})\n```\n\n### 3. Fake Integration IDs\n\n```typescript\n// \u274C NEVER make up integration IDs\nnew PostgreSQL(\"query\", \"fake-postgres-id\", { ... })\n```\n\n### 4. APIs Cannot Set Frontend State\n\n```typescript\n// \u274C WRONG - Cannot set state in APIs\nnew JavaScript(\"update\", {\n fn: ({ userData }) => {\n userNameVar.value = userData.name; // \u274C Cannot do this!\n return userData;\n }\n})\n\n// \u2705 CORRECT - Return data, frontend handles state\nnew JavaScript(\"update\", {\n fn: ({ userData }) => ({\n ...userData,\n fullName: `${userData.firstName} ${userData.lastName}`\n })\n})\n```\n\n### 5. Return Blocks Cannot Contain Statements\n\n```typescript\n// \u2705 CORRECT - Returns data immediately\nnew Return(\"test_return\", {\n data: (({ records }) => ({ records, totalCount: records.length }))()\n})\n\n// \u274C WRONG - Contains statements\nnew Return(\"test_return\", {\n data: (({ records }) => {\n const totalCount = records.length; // \u274C Statement not allowed\n return { records, totalCount };\n })()\n})\n```\n\n## When to Load References\n\nFor integration-specific guidance, load the appropriate reference file:\n\n- SQL databases (PostgreSQL, MySQL, Snowflake, etc.) \u2192 `references/sql-databases.md`\n- REST APIs and OpenAPI \u2192 `references/rest-apis.md`\n- GraphQL \u2192 `references/graphql.md`\n- JavaScript/Python blocks \u2192 `references/code-blocks.md`\n\n## API Checklist\n\nWhen creating APIs:\n\n1. \u2705 Correct language for each integration type\n2. \u2705 Use `OpenApi` class when `grepMetadata` shows OpenAPI spec\n3. \u2705 All imports included\n4. \u2705 Correct variable access patterns (`.value`, `.output`, `.output.data` for GraphQL)\n5. \u2705 No fake integration IDs\n6. \u2705 No placeholder logic\n7. \u2705 Descriptive block names\n8. \u2705 Error handling only where appropriate\n9. \u2705 NEVER change API name when editing existing API\n10. \u2705 ALWAYS test after building\n";
2
2
  //# sourceMappingURL=skill.generated.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"skill.generated.d.ts","sourceRoot":"","sources":["../../../../../src/ai-service/skills/system/superblocks-api/skill.generated.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,OAAO,qmqBA6sBnB,CAAC"}
1
+ {"version":3,"file":"skill.generated.d.ts","sourceRoot":"","sources":["../../../../../src/ai-service/skills/system/superblocks-api/skill.generated.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,OAAO,6njBA8kBnB,CAAC"}
@@ -73,7 +73,7 @@ When exploring integrations and data sources, use \`grepMetadata\` to understand
73
73
 
74
74
  Use \`grepMetadata\` to understand:
75
75
  - What tables/endpoints exist
76
- - Schema structure and
76
+ - Schema structure and organization
77
77
  - Available fields and data types
78
78
 
79
79
  **💡 KEY PRINCIPLE:** For "tell me about the data" questions, metadata exploration is usually sufficient and more efficient.
@@ -463,142 +463,15 @@ new JavaScript("parse_csv", {
463
463
  - Partial failure recovery in loops
464
464
  - Graceful degradation with fallback data
465
465
 
466
- ## Error Recovery Strategies
467
-
468
- When you encounter errors while building APIs:
469
-
470
- ### Read Error Messages Carefully
471
-
472
- Error messages contain specific guidance on how to fix the problem. Pay close attention to:
473
- - What operation failed (compilation, validation, execution)
474
- - Suggestions for how to resolve the issue
475
- - Whether metadata is missing
476
-
477
- ### When to Check Integration Metadata
478
-
479
- If you encounter errors mentioning:
480
- - "unknown column", "table not found", "invalid field"
481
- - "check integration metadata"
482
- - Integration type mismatches
483
-
484
- You MUST call \`grepMetadata\` to get the correct schema/table structure before retrying.
485
-
486
- ## Loop Control
487
-
488
- ### Loop Types
489
-
490
- - **TYPE_FOREACH** (default): Iterates over an array using \`over\`. Provides \`item\` and \`index\` variables.
491
- - **TYPE_WHILE**: Repeats while \`condition\` is true. Provides only \`index\` variable.
492
-
493
- **Breaking out of loops:**
494
- \`\`\`typescript
495
- new Loop("process_until_complete", {
496
- over: ({ items }) => items.output,
497
- variables: { item: "current", index: "i" },
498
- blocks: [
499
- new Conditional("check_stop_condition", {
500
- if: {
501
- when: ({ current }) => current.value.status === "complete",
502
- then: [
503
- new Break("exit_loop", { condition: () => true }) // ✅ Only way to exit
504
- ]
505
- }
506
- }),
507
- new JavaScript("process_item", {
508
- fn: ({ current, i }) => ({
509
- processed: current.value,
510
- position: i.value
511
- })
512
- })
513
- ]
514
- })
515
- \`\`\`
516
-
517
- ## Response Interface Guidelines
518
-
519
- The \`responseInterface\` describes what external code gets from \`apiName.response\`. Internal blocks/steps are NOT visible externally.
520
-
521
- ### Direct Response Types
522
-
523
- ✅ **CORRECT**: Direct array response
524
- \`\`\`typescript
525
- interface GetUsersApiResponse {
526
- id: number;
527
- name: string;
528
- email: string;
529
- }[]
530
- \`\`\`
531
-
532
- ✅ **CORRECT**: Direct data structure
533
- \`\`\`typescript
534
- interface GetOrdersApiResponse {
535
- orders: Order[];
536
- totalCount: number;
537
- }
538
- \`\`\`
539
-
540
- ❌ **WRONG**: Exposing internal steps
541
- \`\`\`typescript
542
- interface GetOrdersApiResponse {
543
- fetchStep: { output: Order[] }; // ❌ Steps are internal
544
- countStep: { output: number }; // ❌ Not visible outside
545
- }
546
- \`\`\`
547
-
548
- ### Type Safety for API Response Interfaces
549
-
550
- **CRITICAL: When defining response interfaces, consider runtime reality, not just happy-path data.**
551
-
552
- When uncertain if an API field will always be present, mark it optional:
553
-
554
- \`\`\`typescript
555
- // ✅ CORRECT - Accounts for real-world API behavior
556
- interface GitHubPRResponse {
557
- id: number;
558
- title: string;
559
- user?: { // ← Optional, can be null for deleted users
560
- login: string;
561
- avatar_url: string;
562
- } | null;
563
- labels?: Label[]; // ← Optional, might be omitted in response
564
- }
565
- \`\`\`
566
-
567
- Mark fields optional when:
568
- 1. **User/account references** - Can be null for deleted/deactivated accounts
569
- 2. **Nested objects** - May be omitted in partial responses
570
- 3. **Third-party APIs** - GitHub, Stripe, etc. often have nullable fields
571
- 4. **Loading states** - Data may not be available during initial render
572
- 5. **Uncertain API behavior** - When in doubt, mark optional
573
-
574
466
  ## Permissions (Global Object)
575
467
 
576
468
  For user-specific operations, use the \`Global\` object (injected by backend):
577
469
 
578
- \`\`\`typescript
579
- type Global = {
580
- user: {
581
- email: string;
582
- username: string;
583
- id: string;
584
- name: string;
585
- groups: Group[]
586
- };
587
- };
588
- \`\`\`
589
-
590
- ### Groups Check Pattern
591
-
592
470
  \`\`\`typescript
593
471
  new JavaScript("check_groups", {
594
472
  fn: ({ Global }) => {
595
- const isFieldEngUser = Global.groups.some(group => group.name === "FieldEngineer");
596
- if (isFieldEngUser) {
597
- // Perform actions for FieldEngineer
598
- } else {
599
- // Perform actions for non-FieldEngineer
600
- }
601
- return { isAdmin: Global.groups.some(g => g.name === "Admin"), userId: Global.user.id };
473
+ const isAdmin = Global.groups.some(group => group.name === "Admin");
474
+ return { isAdmin, userId: Global.user.id };
602
475
  }
603
476
  })
604
477
  \`\`\`
@@ -1 +1 @@
1
- {"version":3,"file":"skill.generated.js","sourceRoot":"","sources":["../../../../../src/ai-service/skills/system/superblocks-api/skill.generated.ts"],"names":[],"mappings":"AAAA,4EAA4E;AAC5E,mDAAmD;AAEnD,MAAM,CAAC,MAAM,OAAO,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA6sBtB,CAAC"}
1
+ {"version":3,"file":"skill.generated.js","sourceRoot":"","sources":["../../../../../src/ai-service/skills/system/superblocks-api/skill.generated.ts"],"names":[],"mappings":"AAAA,4EAA4E;AAC5E,mDAAmD;AAEnD,MAAM,CAAC,MAAM,OAAO,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA8kBtB,CAAC"}
@@ -1,2 +1,2 @@
1
- export declare const content = "---\nname: superblocks-frontend\ndescription: |\n Build frontend UI using React, Tailwind CSS, and Superblocks components. Essential for connecting Superblocks UIs with APIs.\n Use when creating pages, components, handling user interactions, or working with the design system.\nreadOnly: true\nmetadata:\n author: superblocks\n version: \"1.0\"\n---\n\n# Superblocks Frontend Development\n\nThis skill covers building frontend UI for Superblocks applications using React, Tailwind CSS v4, and the Superblocks component library.\n\n## Platform Overview\n\nThis is a React-based web application platform. Use standard React patterns:\n- `useState`, `useEffect`, `useCallback`, `useMemo`\n- Event handlers and controlled components\n- JSX with Tailwind CSS classes\n\n## Using APIs from Frontend\n\nYou **must** use the `useApi` hook for calling backend APIs:\n\n```typescript\nimport { useApi } from \"@superblocksteam/library\";\nimport { toast } from \"sonner\";\n\nexport default function useGetUsers({ email, name }: { email: string | undefined, name: string | undefined }) {\n const { run: runGetUsers } = useApi(\"GetUsers\"); // matches folder apis/GetUsers/api.yaml\n const [loading, setLoading] = useState(false);\n const [users, setUsers] = useState<User[]>([]);\n\n const getUsers = useCallback(async () => {\n setLoading(true);\n try {\n // ALWAYS include ALL inputs, even if they are empty\n const response = await runGetUsers({ email: email ?? null, name: name ?? null });\n setUsers(response?.users ?? []);\n } catch (error) {\n // API errors are thrown as strings, not Error objects\n console.error(error);\n toast.error(\"Error fetching users: \" + error);\n } finally {\n setLoading(false);\n }\n }, [email, name, runGetUsers]);\n\n return { getUsers, loading, users };\n}\n```\n\n### Critical API Rules\n\n1. **MUST call API by exact name**: Format is `<ApiName>` matching folder `apis/<ApiName>/api.yaml`\n2. **Always pass parameters**: `await api({ param1: value1, param2: value2 })`\n3. **Store response in React state**: Use `useState`, `useReducer`, etc.\n4. **Use async/await pattern**: APIs are async functions\n5. **Track loading and error states**: Always show visual feedback\n6. **ALWAYS check API interfaces**: NEVER guess the response structure\n7. **Include all parameters**: Even optional ones should be passed as `null`\n8. **ALWAYS use try/catch**: APIs throw string errors when they fail - wrap ALL API calls in try/catch blocks\n9. **Prevent HMR loops**: Guard `useEffect` with a ref:\n\n```tsx\nconst hasLoadedRef = useRef(false);\nuseEffect(() => {\n if (hasLoadedRef.current) return;\n hasLoadedRef.current = true;\n fetchData();\n}, []);\n```\n\n### File Handling\n\n**CRITICAL: Files must be wrapped in `{ files: [...] }` format:**\n\n```tsx\n// \u2705 CORRECT - Frontend: wrap files in { files: [...] }\nconst response = await runUploadApi({ userFile: { files: selectedFiles } });\n\n// \u274C WRONG - backend cannot process unwrapped files\nconst response = await runUploadApi({ userFile: selectedFiles });\n```\n\n## Platform Hooks\n\nAvailable hooks from `@superblocksteam/library`:\n\n```typescript\nimport { \n useSuperblocksUser,\n useSuperblocksGroups,\n useSuperblocksProfiles,\n} from \"@superblocksteam/library\";\n\n// Get current user info\nconst user = useSuperblocksUser();\n// user.name, user.email, user.id, user.groups, user.username, user.metadata\n\n// Get organization groups\nconst groups = useSuperblocksGroups();\n\n// Manage profiles\nconst { profiles, setProfile } = useSuperblocksProfiles();\n```\n\n**For embedded applications**, see the `references/embedding.md` file for `useEmbedProperties`, `useEmbedEvent`, and `useEmitEmbedEvent` hooks.\n\n## Application Architecture\n\n### App.tsx Layout Structure\n\n**For single-page applications:**\n- Put all content in `pages/<pageName>/index.tsx`\n- Use components to compose and build the page\n- Keep `App.tsx` minimal with just `<AppProvider>` and `<Outlet />`\n\n**For multi-page applications:**\n- Put shared navigation/layout in `App.tsx` (sidebars, headers, footers)\n- Always include `<Outlet />` for page content\n- Always include `<AppProvider />` wrapper\n- Individual pages focus on content, not layout\n\n```tsx\n// \u2705 CORRECT - Multi-page App.tsx layout\n<AppProvider>\n <div className=\"flex flex-row size-screen\">\n {/* Sidebar - persistent across all pages */}\n <div className=\"flex bg-sidebar border-r w-[250px]\">\n <Navigation />\n </div>\n\n {/* Main content area */}\n <div className=\"flex flex-1 h-full flex-col\">\n {/* Header - persistent across all pages */}\n <div className=\"flex bg-header border-b h-[60px]\">\n <Header />\n </div>\n\n {/* Page content area */}\n <div className=\"flex p-4 flex-1 overflow-auto\">\n <Outlet />\n </div>\n </div>\n </div>\n</AppProvider>\n```\n\n**PROTECTED: NEVER remove `<AppProvider>` or `<Outlet />` from App.tsx!**\n\n### Page Structure\n\n```tsx\n// \u2705 CORRECT - Page focuses on content only\n<div className=\"flex flex-col gap-4 size-screen overflow-auto\">\n <h1 className=\"text-3xl font-bold\">Dashboard Content</h1>\n <Card>\n {/* Page-specific content */}\n </Card>\n</div>\n```\n\n**IMPORTANT**: The first div on the page must have `overflow-auto` so the user's page can scroll.\n\n## Routing\n\nUse `react-router@7` in data mode. Standard patterns apply:\n- `useNavigate()` for programmatic navigation\n- `useParams()` for route parameters\n- `useSearchParams()` for query strings\n\n**If you add new pages or rename files, you MUST update the router.**\n\n## Design System (Tailwind CSS v4)\n\n**All design tokens are defined in `index.css`**. Apps come with a professional black-and-white theme by default.\n\n### Semantic Tokens Rule\n\n**ALWAYS use semantic tokens** \u2014 NEVER raw Tailwind utilities:\n\n```tsx\n// \u2705 CORRECT\n<Card className=\"bg-background text-foreground border border-border\" />\n\n// \u274C WRONG\n<Card className=\"bg-white text-black border-gray-200\" />\n```\n\n### When to Modify index.css\n\nOnly modify when:\n- User explicitly requests branding/theme changes\n- Replicating a specific brand look (e.g., Yelp, Instacart)\n- Feature requests (lists, filters, CRUD) do NOT require changes\n\n**Modification Rules:**\n- All colors must be in OKLCH format\n- Use semantic names (`--color-warning`, `--shadow-elevated`)\n- Do not remove or rename existing tokens\n- Limit color palette to 5 colors max\n- Avoid gradients unless explicitly requested\n- Minimal font sizes (3 max: body, section heading, main heading)\n\n### Component Variants\n\nUse or create variants instead of one-off styles:\n\n```tsx\n// \u274C WRONG - Hacky inline overrides\n<Button className=\"text-white border-white hover:bg-white\" />\n\n// \u2705 CORRECT - Use a variant\n<Button variant=\"secondary\" />\n```\n\n## Icons\n\nUse icons from Lucide React library:\n\n```tsx\nimport { Icon } from \"@/components/ui/icon\";\n<Icon icon=\"heart\" />\n\nimport { Button } from \"@/components/ui/button\";\n<Button><Icon icon=\"plus\" /> Add Item</Button>\n```\n\n**Always use icons rather than emojis unless explicitly requested.**\n\n## Custom Components\n\n**CRITICAL: Component composition is MANDATORY. DO NOT create monolithic pages.**\n\n### The Composition Rule\n\nWhen building ANY feature:\n1. **First**, identify reusable parts (list items, cards, forms, filters, headers)\n2. **Then**, create separate component files\n3. **Finally**, compose them together in the page\n\n### When to Create Components\n\n- **Rendering any list** - Extract to a component\n- **Building cards/complex UI** - Each card type is a component\n- **Creating forms** - Form sections are components\n- **Adding filters/headers** - These are components\n- **Page has >50 lines JSX** - Break it down\n\n### Component Boundary Rules\n\n**Inside a custom component:**\n- \u2705 Use React hooks (useState, useReducer, useEffect, etc.)\n- \u2705 Use local React state\n- \u2705 Use internal helper components\n- \u2705 Use other registered components\n- \u274C CANNOT call APIs - must pass data into the component\n\n### Example: Proper Component Structure\n\n```tsx\n// components/ProductCard/index.tsx - Extract to component\nimport { Card } from \"@/components/ui/card\";\nimport { Button } from \"@/components/ui/button\";\n\ntype ProductCardProps = {\n product: {\n id: string;\n name: string;\n image: string;\n };\n};\n\nexport default function ProductCard(props: ProductCardProps) {\n return (\n <Card>\n <img src={props.product.image} />\n <h3 className=\"text-lg font-semibold\">{props.product.name}</h3>\n <Button>Add</Button>\n </Card>\n );\n}\n\n// pages/Products/index.tsx - Clean composition\nimport ProductCard from \"@/components/ProductCard\";\n\nconst ProductsPage = () => {\n const [products, setProducts] = useState([]);\n\n return (\n <div className=\"grid grid-cols-3 gap-4\">\n {products.map(p => <ProductCard key={p.id} product={p} />)}\n </div>\n );\n};\n```\n\n## Visual Excellence\n\n**Prioritize visual excellence from the start:**\n\n1. **Design System Enhancement**: Start by enhancing `index.css` with app-specific colors that match the target aesthetic\n2. **Professional Layout Architecture**: Use sophisticated layouts with proper spacing, responsive design\n3. **Rich Interactive Components**: Leverage advanced components with proper variants and states\n4. **Visual Polish**: Add shadows, smooth transitions, skeleton loaders, hover effects, typography hierarchy\n5. **Real-World UI Patterns**: Create layouts that feel like professional applications\n\n**Make applications that look and feel like real, polished products - not basic wireframes.**\n\n### Loading States\n\n**Always represent loading with skeletons (shimmers), not spinners or empty screens.**\n\n### Efficient Loading Patterns\n\n1. **Default to Smart Loading**: Check for existing data before showing loading states\n2. **Loading State Hierarchy**:\n - Empty state \u2192 Full loading\n - Has data \u2192 Keep showing data during refetch\n - Error state \u2192 Show error with retry option\n3. **Debounce Rapid Requests**: Prevent multiple API calls in short succession\n4. **Use hooks to encapsulate API logic**: Avoid repeating code\n\n## Performance Rules\n\n### 1. ALWAYS Paginate Tables and Lists\n\n**NEVER render more than 50 rows without pagination.** Always add client-side pagination:\n\n```tsx\nfunction PaginatedTable({ data }: { data: any[] }) {\n const PAGE_SIZE = 20;\n const [page, setPage] = useState(0);\n const totalPages = Math.ceil(data.length / PAGE_SIZE);\n const pageData = useMemo(() => data.slice(page * PAGE_SIZE, (page + 1) * PAGE_SIZE), [data, page]);\n\n useEffect(() => { setPage(0); }, [data.length]);\n\n return (<>\n <Table>{/* render pageData rows */}</Table>\n <span>Page {page + 1} of {totalPages} ({data.length} total rows)</span>\n <Button onClick={() => setPage((p) => Math.max(0, p - 1))} disabled={page === 0}>Previous</Button>\n <Button onClick={() => setPage((p) => Math.min(totalPages - 1, p + 1))} disabled={page >= totalPages - 1}>Next</Button>\n </>);\n}\n```\n\nFor 200+ rows, prefer **server-side pagination**; use cursor/keyset pagination for high offsets instead of `LIMIT`/`OFFSET`.\n\nFor 500+ item lists where pagination doesn't fit the UX (chat messages, infinite scroll feeds, large dropdowns), use **virtualization** (`react-virtuoso` or `@tanstack/react-virtual`) to render only the items visible in the viewport.\n\n### 2. ALWAYS Debounce Input-Driven API Calls\n\n**NEVER call an API directly from onChange.** Debounce search/filter inputs with a 300ms timer:\n\n```tsx\nfunction DebouncedSearch({ onSearch }: { onSearch: (query: string) => void }) {\n const [localValue, setLocalValue] = useState(\"\");\n const timerRef = useRef<ReturnType<typeof setTimeout>>();\n const handleChange = useCallback((e: React.ChangeEvent<HTMLInputElement>) => {\n setLocalValue(e.target.value);\n clearTimeout(timerRef.current);\n timerRef.current = setTimeout(() => onSearch(e.target.value), 300);\n }, [onSearch]);\n useEffect(() => () => clearTimeout(timerRef.current), []);\n\n return <Input value={localValue} onChange={handleChange} placeholder=\"Search...\" />;\n}\n```\n\n### 3. Memoize Expensive Renders\n\nUse memoization (`memo()`, `useMemo`, `useCallback`) when it prevents measurable re-renders or expensive recomputation:\n\n```tsx\nconst OrderRow = memo(function OrderRow({ order, onSelect }: { order: Order; onSelect: (id: string) => void }) {\n return <TableRow onClick={() => onSelect(order.id)}><TableCell>{order.id}</TableCell>...</TableRow>;\n});\n\nconst handleSelect = useCallback((id: string) => {\n setSelectedId(id);\n}, []);\n\nconst filtered = useMemo(\n () => orders.filter(o => o.status === status).sort((a, b) => b.total - a.total),\n [orders, status],\n);\n```\n\n### 4. ALWAYS Clean Up Side Effects\n\nClean up timers, event listeners, and subscriptions in `useEffect` return functions:\n\n```tsx\nuseEffect(() => {\n const handler = (e: KeyboardEvent) => { /* ... */ };\n window.addEventListener(\"keydown\", handler);\n return () => window.removeEventListener(\"keydown\", handler);\n}, []);\n```\n\n### 5. Cancel In-Flight API Requests on Unmount\n\nWhen debouncing or fetching data, use the `cancel()` function from `useApi` to cancel in-flight requests when the component unmounts or a newer request supersedes the previous one:\n\n```tsx\nconst { run, cancel } = useApi(\"SearchProducts\");\n\nuseEffect(() => {\n if (!query) return;\n run({ query }).then(res => setResults(res?.products ?? [])).catch(console.error);\n return () => { void cancel(); };\n}, [query, run, cancel]);\n```\n";
1
+ export declare const content = "---\nname: superblocks-frontend\ndescription: |\n Build frontend UI using React, Tailwind CSS, and Superblocks components. Essential for connecting Superblocks UIs with APIs.\n Use when creating pages, components, handling user interactions, or working with the design system.\nreadOnly: true\nmetadata:\n author: superblocks\n version: \"1.0\"\n---\n\n# Superblocks Frontend Development\n\nThis skill covers building frontend UI for Superblocks applications using React, Tailwind CSS v4, and the Superblocks component library.\n\n## Platform Overview\n\nThis is a React-based web application platform. Use standard React patterns:\n- `useState`, `useEffect`, `useCallback`, `useMemo`\n- Event handlers and controlled components\n- JSX with Tailwind CSS classes\n\n## Using APIs from Frontend\n\nYou **must** use the `useApi` hook for calling backend APIs:\n\n```typescript\nimport { useApi } from \"@superblocksteam/library\";\nimport { toast } from \"sonner\";\n\nexport default function useGetUsers({ email, name }: { email: string | undefined, name: string | undefined }) {\n const { run: runGetUsers } = useApi(\"GetUsers\"); // matches folder apis/GetUsers/api.yaml\n const [loading, setLoading] = useState(false);\n const [users, setUsers] = useState<User[]>([]);\n\n const getUsers = useCallback(async () => {\n setLoading(true);\n try {\n // ALWAYS include ALL inputs, even if they are empty\n const response = await runGetUsers({ email: email ?? null, name: name ?? null });\n setUsers(response?.users ?? []);\n } catch (error) {\n console.error(error);\n toast.error(\"Error fetching users: \" + (error as Error).message);\n } finally {\n setLoading(false);\n }\n }, [email, name, runGetUsers]);\n\n return { getUsers, loading, users };\n}\n```\n\n### Critical API Rules\n\n1. **MUST call API by exact name**: Format is `<ApiName>` matching folder `apis/<ApiName>/api.yaml`\n2. **Always pass parameters**: `await api({ param1: value1, param2: value2 })`\n3. **Store response in React state**: Use `useState`, `useReducer`, etc.\n4. **Use async/await pattern**: APIs are async functions\n5. **Track loading and error states**: Always show visual feedback\n6. **ALWAYS check API interfaces**: NEVER guess the response structure\n7. **Include all parameters**: Even optional ones should be passed as `null`\n8. **Handle errors**: Always show error messages to the user\n9. **Prevent HMR loops**: Guard `useEffect` with a ref:\n\n```tsx\nconst hasLoadedRef = useRef(false);\nuseEffect(() => {\n if (hasLoadedRef.current) return;\n hasLoadedRef.current = true;\n fetchData();\n}, []);\n```\n\n### File Handling\n\n**CRITICAL: Files must be wrapped in `{ files: [...] }` format:**\n\n```tsx\n// \u2705 CORRECT - Frontend: wrap files in { files: [...] }\nconst response = await runUploadApi({ userFile: { files: selectedFiles } });\n\n// \u274C WRONG - backend cannot process unwrapped files\nconst response = await runUploadApi({ userFile: selectedFiles });\n```\n\n## Platform Hooks\n\nAvailable hooks from `@superblocksteam/library`:\n\n```typescript\nimport { \n useSuperblocksUser,\n useSuperblocksGroups,\n useSuperblocksProfiles,\n useEmbedProperties,\n useEmbedEvent,\n useEmitEmbedEvent,\n} from \"@superblocksteam/library\";\n\n// Get current user info\nconst user = useSuperblocksUser();\n// user.name, user.email, user.id, user.groups, user.username, user.metadata\n\n// Get organization groups\nconst groups = useSuperblocksGroups();\n\n// Manage profiles\nconst { profiles, setProfile } = useSuperblocksProfiles();\n\n// For embedded apps - read properties from embedder\nconst properties = useEmbedProperties();\n\n// Listen to events from embedder\nuseEmbedEvent(\"refreshData\", (payload) => {\n refetchData();\n});\n\n// Emit events to embedder\nconst emitEvent = useEmitEmbedEvent();\nemitEvent(\"formSubmitted\", { timestamp: Date.now(), data });\n```\n\n## Application Architecture\n\n### App.tsx Layout Structure\n\n**For single-page applications:**\n- Put all content in `pages/<pageName>/index.tsx`\n- Use components to compose and build the page\n- Keep `App.tsx` minimal with just `<AppProvider>` and `<Outlet />`\n\n**For multi-page applications:**\n- Put shared navigation/layout in `App.tsx` (sidebars, headers, footers)\n- Always include `<Outlet />` for page content\n- Always include `<AppProvider />` wrapper\n- Individual pages focus on content, not layout\n\n```tsx\n// \u2705 CORRECT - Multi-page App.tsx layout\n<AppProvider>\n <div className=\"flex flex-row size-screen\">\n {/* Sidebar - persistent across all pages */}\n <div className=\"flex bg-sidebar border-r w-[250px]\">\n <Navigation />\n </div>\n\n {/* Main content area */}\n <div className=\"flex flex-1 h-full flex-col\">\n {/* Header - persistent across all pages */}\n <div className=\"flex bg-header border-b h-[60px]\">\n <Header />\n </div>\n\n {/* Page content area */}\n <div className=\"flex p-4 flex-1 overflow-auto\">\n <Outlet />\n </div>\n </div>\n </div>\n</AppProvider>\n```\n\n**PROTECTED: NEVER remove `<AppProvider>` or `<Outlet />` from App.tsx!**\n\n### Page Structure\n\n```tsx\n// \u2705 CORRECT - Page focuses on content only\n<div className=\"flex flex-col gap-4 size-screen overflow-auto\">\n <h1 className=\"text-3xl font-bold\">Dashboard Content</h1>\n <Card>\n {/* Page-specific content */}\n </Card>\n</div>\n```\n\n**IMPORTANT**: The first div on the page must have `overflow-auto` so the user's page can scroll.\n\n## Routing\n\nUse `react-router@7` in data mode. Standard patterns apply:\n- `useNavigate()` for programmatic navigation\n- `useParams()` for route parameters\n- `useSearchParams()` for query strings\n\n**If you add new pages or rename files, you MUST update the router.**\n\n## Design System (Tailwind CSS v4)\n\n**All design tokens are defined in `index.css`**. Apps come with a professional black-and-white theme by default.\n\n### Semantic Tokens Rule\n\n**ALWAYS use semantic tokens** \u2014 NEVER raw Tailwind utilities:\n\n```tsx\n// \u2705 CORRECT\n<Card className=\"bg-background text-foreground border border-border\" />\n\n// \u274C WRONG\n<Card className=\"bg-white text-black border-gray-200\" />\n```\n\n### When to Modify index.css\n\nOnly modify when:\n- User explicitly requests branding/theme changes\n- Replicating a specific brand look (e.g., Yelp, Instacart)\n- Feature requests (lists, filters, CRUD) do NOT require changes\n\n**Modification Rules:**\n- All colors must be in OKLCH format\n- Use semantic names (`--color-warning`, `--shadow-elevated`)\n- Do not remove or rename existing tokens\n- Limit color palette to 5 colors max\n- Avoid gradients unless explicitly requested\n- Minimal font sizes (3 max: body, section heading, main heading)\n\n### Component Variants\n\nUse or create variants instead of one-off styles:\n\n```tsx\n// \u274C WRONG - Hacky inline overrides\n<Button className=\"text-white border-white hover:bg-white\" />\n\n// \u2705 CORRECT - Use a variant\n<Button variant=\"secondary\" />\n```\n\n## Icons\n\nUse icons from Lucide React library:\n\n```tsx\nimport { Icon } from \"@/components/ui/icon\";\n<Icon icon=\"heart\" />\n\nimport { Button } from \"@/components/ui/button\";\n<Button><Icon icon=\"plus\" /> Add Item</Button>\n```\n\n**Always use icons rather than emojis unless explicitly requested.**\n\n## Custom Components\n\n**CRITICAL: Component composition is MANDATORY. DO NOT create monolithic pages.**\n\n### The Composition Rule\n\nWhen building ANY feature:\n1. **First**, identify reusable parts (list items, cards, forms, filters, headers)\n2. **Then**, create separate component files\n3. **Finally**, compose them together in the page\n\n### When to Create Components\n\n- **Rendering any list** - Extract to a component\n- **Building cards/complex UI** - Each card type is a component\n- **Creating forms** - Form sections are components\n- **Adding filters/headers** - These are components\n- **Page has >50 lines JSX** - Break it down\n\n### Component Boundary Rules\n\n**Inside a custom component:**\n- \u2705 Use React hooks (useState, useReducer, useEffect, etc.)\n- \u2705 Use local React state\n- \u2705 Use internal helper components\n- \u2705 Use other registered components\n- \u274C CANNOT call APIs - must pass data into the component\n\n### Example: Proper Component Structure\n\n```tsx\n// components/ProductCard/index.tsx - Extract to component\nimport { Card } from \"@/components/ui/card\";\nimport { Button } from \"@/components/ui/button\";\n\ntype ProductCardProps = {\n product: {\n id: string;\n name: string;\n image: string;\n };\n};\n\nexport default function ProductCard(props: ProductCardProps) {\n return (\n <Card>\n <img src={props.product.image} />\n <h3 className=\"text-lg font-semibold\">{props.product.name}</h3>\n <Button>Add</Button>\n </Card>\n );\n}\n\n// pages/Products/index.tsx - Clean composition\nimport ProductCard from \"@/components/ProductCard\";\n\nconst ProductsPage = () => {\n const [products, setProducts] = useState([]);\n\n return (\n <div className=\"grid grid-cols-3 gap-4\">\n {products.map(p => <ProductCard key={p.id} product={p} />)}\n </div>\n );\n};\n```\n\n## Visual Excellence\n\n**Prioritize visual excellence from the start:**\n\n1. **Design System Enhancement**: Start by enhancing `index.css` with app-specific colors that match the target aesthetic\n2. **Professional Layout Architecture**: Use sophisticated layouts with proper spacing, responsive design\n3. **Rich Interactive Components**: Leverage advanced components with proper variants and states\n4. **Visual Polish**: Add shadows, smooth transitions, skeleton loaders, hover effects, typography hierarchy\n5. **Real-World UI Patterns**: Create layouts that feel like professional applications\n\n**Make applications that look and feel like real, polished products - not basic wireframes.**\n\n### Loading States\n\n**Always represent loading with skeletons (shimmers), not spinners or empty screens.**\n\n### Efficient Loading Patterns\n\n1. **Default to Smart Loading**: Check for existing data before showing loading states\n2. **Loading State Hierarchy**:\n - Empty state \u2192 Full loading\n - Has data \u2192 Keep showing data during refetch\n - Error state \u2192 Show error with retry option\n3. **Debounce Rapid Requests**: Prevent multiple API calls in short succession\n4. **Use hooks to encapsulate API logic**: Avoid repeating code\n";
2
2
  //# sourceMappingURL=skill.generated.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"skill.generated.d.ts","sourceRoot":"","sources":["../../../../../src/ai-service/skills/system/superblocks-frontend/skill.generated.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,OAAO,slbAianB,CAAC"}
1
+ {"version":3,"file":"skill.generated.d.ts","sourceRoot":"","sources":["../../../../../src/ai-service/skills/system/superblocks-frontend/skill.generated.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,OAAO,m2UAiVnB,CAAC"}