@superblocksteam/vite-plugin-file-sync 2.0.59-next.0 → 2.0.59-next.10
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.
- package/dist/ai-service/agent/prompts/build-base-system-prompt.d.ts.map +1 -1
- package/dist/ai-service/agent/prompts/build-base-system-prompt.js +25 -9
- package/dist/ai-service/agent/prompts/build-base-system-prompt.js.map +1 -1
- package/dist/ai-service/agent/subagents/apis/examples.d.ts.map +1 -1
- package/dist/ai-service/agent/subagents/apis/examples.js +137 -10
- package/dist/ai-service/agent/subagents/apis/examples.js.map +1 -1
- package/dist/ai-service/agent/subagents/apis/static-analysis.d.ts.map +1 -1
- package/dist/ai-service/agent/subagents/apis/static-analysis.js +14 -7
- package/dist/ai-service/agent/subagents/apis/static-analysis.js.map +1 -1
- package/dist/ai-service/agent/tool-message-utils.d.ts.map +1 -1
- package/dist/ai-service/agent/tool-message-utils.js +6 -2
- package/dist/ai-service/agent/tool-message-utils.js.map +1 -1
- package/dist/ai-service/agent/tools/apis/analysis.d.ts +9 -0
- package/dist/ai-service/agent/tools/apis/analysis.d.ts.map +1 -0
- package/dist/ai-service/agent/tools/apis/analysis.js +358 -0
- package/dist/ai-service/agent/tools/apis/analysis.js.map +1 -0
- package/dist/ai-service/agent/{subagents → tools}/apis/api-executor.d.ts +35 -10
- package/dist/ai-service/agent/tools/apis/api-executor.d.ts.map +1 -0
- package/dist/ai-service/agent/{subagents → tools}/apis/api-executor.js +179 -94
- package/dist/ai-service/agent/tools/apis/api-executor.js.map +1 -0
- package/dist/ai-service/agent/tools/apis/api-source.d.ts +19 -0
- package/dist/ai-service/agent/tools/apis/api-source.d.ts.map +1 -0
- package/dist/ai-service/agent/tools/apis/api-source.js +73 -0
- package/dist/ai-service/agent/tools/apis/api-source.js.map +1 -0
- package/dist/ai-service/agent/tools/apis/api-validation-orchestrator.d.ts +51 -0
- package/dist/ai-service/agent/tools/apis/api-validation-orchestrator.d.ts.map +1 -0
- package/dist/ai-service/agent/tools/apis/api-validation-orchestrator.js +510 -0
- package/dist/ai-service/agent/tools/apis/api-validation-orchestrator.js.map +1 -0
- package/dist/ai-service/agent/tools/apis/build-api-artifact.d.ts +32 -0
- package/dist/ai-service/agent/tools/apis/build-api-artifact.d.ts.map +1 -0
- package/dist/ai-service/agent/tools/apis/build-api-artifact.js +313 -0
- package/dist/ai-service/agent/tools/apis/build-api-artifact.js.map +1 -0
- package/dist/ai-service/agent/tools/apis/build-api.d.ts +1 -10
- package/dist/ai-service/agent/tools/apis/build-api.d.ts.map +1 -1
- package/dist/ai-service/agent/tools/apis/build-api.js +26 -238
- package/dist/ai-service/agent/tools/apis/build-api.js.map +1 -1
- package/dist/ai-service/agent/tools/apis/get-api-docs.d.ts +11 -0
- package/dist/ai-service/agent/tools/apis/get-api-docs.d.ts.map +1 -0
- package/dist/ai-service/agent/tools/apis/get-api-docs.js +1841 -0
- package/dist/ai-service/agent/tools/apis/get-api-docs.js.map +1 -0
- package/dist/ai-service/agent/tools/apis/integration-types.d.ts +37 -0
- package/dist/ai-service/agent/tools/apis/integration-types.d.ts.map +1 -0
- package/dist/ai-service/agent/tools/apis/integration-types.js +689 -0
- package/dist/ai-service/agent/tools/apis/integration-types.js.map +1 -0
- package/dist/ai-service/agent/tools/apis/test-api.d.ts +25 -0
- package/dist/ai-service/agent/tools/apis/test-api.d.ts.map +1 -0
- package/dist/ai-service/agent/tools/apis/test-api.js +194 -0
- package/dist/ai-service/agent/tools/apis/test-api.js.map +1 -0
- package/dist/ai-service/agent/tools/apis/write-api.d.ts +11 -0
- package/dist/ai-service/agent/tools/apis/write-api.d.ts.map +1 -0
- package/dist/ai-service/agent/tools/apis/write-api.js +41 -0
- package/dist/ai-service/agent/tools/apis/write-api.js.map +1 -0
- package/dist/ai-service/agent/tools/build-read-files.js +2 -2
- package/dist/ai-service/agent/tools/build-read-files.js.map +1 -1
- package/dist/ai-service/agent/tools.d.ts +2 -5
- package/dist/ai-service/agent/tools.d.ts.map +1 -1
- package/dist/ai-service/agent/tools.js +51 -22
- package/dist/ai-service/agent/tools.js.map +1 -1
- package/dist/ai-service/agent/tools2/access-control.d.ts +1 -0
- package/dist/ai-service/agent/tools2/access-control.d.ts.map +1 -1
- package/dist/ai-service/agent/tools2/access-control.js +15 -13
- package/dist/ai-service/agent/tools2/access-control.js.map +1 -1
- package/dist/ai-service/agent/tools2/registry.d.ts +2 -1
- package/dist/ai-service/agent/tools2/registry.d.ts.map +1 -1
- package/dist/ai-service/agent/tools2/registry.js +4 -3
- package/dist/ai-service/agent/tools2/registry.js.map +1 -1
- package/dist/ai-service/agent/tools2/tools/exit-plan-mode.d.ts.map +1 -1
- package/dist/ai-service/agent/tools2/tools/exit-plan-mode.js +73 -127
- package/dist/ai-service/agent/tools2/tools/exit-plan-mode.js.map +1 -1
- package/dist/ai-service/agent/tools2/tools/grep-metadata.d.ts.map +1 -1
- package/dist/ai-service/agent/tools2/tools/grep-metadata.js +25 -4
- package/dist/ai-service/agent/tools2/tools/grep-metadata.js.map +1 -1
- package/dist/ai-service/agent/tools2/types.d.ts +1 -1
- package/dist/ai-service/agent/tools2/types.d.ts.map +1 -1
- package/dist/ai-service/agent/tools2/types.js.map +1 -1
- package/dist/ai-service/agent/tools2/utils.d.ts.map +1 -1
- package/dist/ai-service/agent/tools2/utils.js +4 -1
- package/dist/ai-service/agent/tools2/utils.js.map +1 -1
- package/dist/ai-service/agent/utils.d.ts +1 -3
- package/dist/ai-service/agent/utils.d.ts.map +1 -1
- package/dist/ai-service/agent/utils.js +55 -13
- package/dist/ai-service/agent/utils.js.map +1 -1
- package/dist/ai-service/app-interface/shell.d.ts +5 -0
- package/dist/ai-service/app-interface/shell.d.ts.map +1 -1
- package/dist/ai-service/app-interface/shell.js +17 -2
- package/dist/ai-service/app-interface/shell.js.map +1 -1
- package/dist/ai-service/chat/chat-session-store.d.ts +7 -0
- package/dist/ai-service/chat/chat-session-store.d.ts.map +1 -1
- package/dist/ai-service/chat/chat-session-store.js +26 -0
- package/dist/ai-service/chat/chat-session-store.js.map +1 -1
- package/dist/ai-service/const.d.ts +3 -1
- package/dist/ai-service/const.d.ts.map +1 -1
- package/dist/ai-service/const.js +3 -0
- package/dist/ai-service/const.js.map +1 -1
- package/dist/ai-service/index.d.ts +5 -1
- package/dist/ai-service/index.d.ts.map +1 -1
- package/dist/ai-service/index.js +55 -7
- package/dist/ai-service/index.js.map +1 -1
- package/dist/ai-service/integrations/metadata-storage/index.d.ts +10 -0
- package/dist/ai-service/integrations/metadata-storage/index.d.ts.map +1 -1
- package/dist/ai-service/integrations/metadata-storage/local.d.ts +4 -2
- package/dist/ai-service/integrations/metadata-storage/local.d.ts.map +1 -1
- package/dist/ai-service/integrations/metadata-storage/local.js +35 -9
- package/dist/ai-service/integrations/metadata-storage/local.js.map +1 -1
- package/dist/ai-service/integrations/store.d.ts +27 -2
- package/dist/ai-service/integrations/store.d.ts.map +1 -1
- package/dist/ai-service/integrations/store.js +129 -62
- package/dist/ai-service/integrations/store.js.map +1 -1
- package/dist/ai-service/llm/client.d.ts +123 -0
- package/dist/ai-service/llm/client.d.ts.map +1 -0
- package/dist/ai-service/llm/client.js +168 -0
- package/dist/ai-service/llm/client.js.map +1 -0
- package/dist/ai-service/llm/context/context-handle.d.ts +4 -4
- package/dist/ai-service/llm/context/context-handle.d.ts.map +1 -1
- package/dist/ai-service/llm/context/context-handle.js +7 -3
- package/dist/ai-service/llm/context/context-handle.js.map +1 -1
- package/dist/ai-service/llm/context/context.d.ts +28 -0
- package/dist/ai-service/llm/context/context.d.ts.map +1 -1
- package/dist/ai-service/llm/context/context.js +119 -0
- package/dist/ai-service/llm/context/context.js.map +1 -1
- package/dist/ai-service/llm/context/manager.d.ts +22 -2
- package/dist/ai-service/llm/context/manager.d.ts.map +1 -1
- package/dist/ai-service/llm/context/manager.js +86 -13
- package/dist/ai-service/llm/context/manager.js.map +1 -1
- package/dist/ai-service/llm/context/storage/index.d.ts +1 -0
- package/dist/ai-service/llm/context/storage/index.d.ts.map +1 -1
- package/dist/ai-service/llm/context/storage/local.d.ts +1 -0
- package/dist/ai-service/llm/context/storage/local.d.ts.map +1 -1
- package/dist/ai-service/llm/context/storage/local.js +13 -1
- package/dist/ai-service/llm/context/storage/local.js.map +1 -1
- package/dist/ai-service/llm/context/utils/message-utils.d.ts.map +1 -1
- package/dist/ai-service/llm/context/utils/message-utils.js +6 -2
- package/dist/ai-service/llm/context/utils/message-utils.js.map +1 -1
- package/dist/ai-service/llm/error.d.ts +14 -4
- package/dist/ai-service/llm/error.d.ts.map +1 -1
- package/dist/ai-service/llm/error.js +49 -4
- package/dist/ai-service/llm/error.js.map +1 -1
- package/dist/ai-service/llm/interaction/adapters/vercel.d.ts +67 -0
- package/dist/ai-service/llm/interaction/adapters/vercel.d.ts.map +1 -0
- package/dist/ai-service/llm/interaction/adapters/vercel.js +111 -0
- package/dist/ai-service/llm/interaction/adapters/vercel.js.map +1 -0
- package/dist/ai-service/llm/interaction/compose.d.ts +71 -0
- package/dist/ai-service/llm/interaction/compose.d.ts.map +1 -0
- package/dist/ai-service/llm/interaction/compose.js +88 -0
- package/dist/ai-service/llm/interaction/compose.js.map +1 -0
- package/dist/ai-service/llm/interaction/index.d.ts +68 -0
- package/dist/ai-service/llm/interaction/index.d.ts.map +1 -0
- package/dist/ai-service/llm/interaction/index.js +70 -0
- package/dist/ai-service/llm/interaction/index.js.map +1 -0
- package/dist/ai-service/llm/interaction/middleware.d.ts +52 -0
- package/dist/ai-service/llm/interaction/middleware.d.ts.map +1 -0
- package/dist/ai-service/llm/interaction/middleware.js +17 -0
- package/dist/ai-service/llm/interaction/middleware.js.map +1 -0
- package/dist/ai-service/llm/interaction/middlewares/llmobs.d.ts +45 -0
- package/dist/ai-service/llm/interaction/middlewares/llmobs.d.ts.map +1 -0
- package/dist/ai-service/llm/interaction/middlewares/llmobs.js +85 -0
- package/dist/ai-service/llm/interaction/middlewares/llmobs.js.map +1 -0
- package/dist/ai-service/llm/interaction/middlewares/logging.d.ts +88 -0
- package/dist/ai-service/llm/interaction/middlewares/logging.d.ts.map +1 -0
- package/dist/ai-service/llm/interaction/middlewares/logging.js +238 -0
- package/dist/ai-service/llm/interaction/middlewares/logging.js.map +1 -0
- package/dist/ai-service/llm/interaction/middlewares/profiler.d.ts +47 -0
- package/dist/ai-service/llm/interaction/middlewares/profiler.d.ts.map +1 -0
- package/dist/ai-service/llm/interaction/middlewares/profiler.js +183 -0
- package/dist/ai-service/llm/interaction/middlewares/profiler.js.map +1 -0
- package/dist/ai-service/llm/interaction/middlewares/stream-retry.d.ts +121 -0
- package/dist/ai-service/llm/interaction/middlewares/stream-retry.d.ts.map +1 -0
- package/dist/ai-service/llm/interaction/middlewares/stream-retry.js +291 -0
- package/dist/ai-service/llm/interaction/middlewares/stream-retry.js.map +1 -0
- package/dist/ai-service/llm/interaction/provider.d.ts +173 -0
- package/dist/ai-service/llm/interaction/provider.d.ts.map +1 -0
- package/dist/ai-service/llm/interaction/provider.js +15 -0
- package/dist/ai-service/llm/interaction/provider.js.map +1 -0
- package/dist/ai-service/llm/interaction/result-utils.d.ts +43 -0
- package/dist/ai-service/llm/interaction/result-utils.d.ts.map +1 -0
- package/dist/ai-service/llm/interaction/result-utils.js +49 -0
- package/dist/ai-service/llm/interaction/result-utils.js.map +1 -0
- package/dist/ai-service/llm/interaction/stream-lifecycle.d.ts +48 -0
- package/dist/ai-service/llm/interaction/stream-lifecycle.d.ts.map +1 -0
- package/dist/ai-service/llm/interaction/stream-lifecycle.js +129 -0
- package/dist/ai-service/llm/interaction/stream-lifecycle.js.map +1 -0
- package/dist/ai-service/llm/provider.d.ts +1 -2
- package/dist/ai-service/llm/provider.d.ts.map +1 -1
- package/dist/ai-service/llm/provider.js +3 -6
- package/dist/ai-service/llm/provider.js.map +1 -1
- package/dist/ai-service/llmobs/helpers.d.ts +7 -8
- package/dist/ai-service/llmobs/helpers.d.ts.map +1 -1
- package/dist/ai-service/llmobs/helpers.js +8 -48
- package/dist/ai-service/llmobs/helpers.js.map +1 -1
- package/dist/ai-service/llmobs/middleware/stream-text.d.ts +19 -21
- package/dist/ai-service/llmobs/middleware/stream-text.d.ts.map +1 -1
- package/dist/ai-service/llmobs/middleware/stream-text.js +98 -106
- package/dist/ai-service/llmobs/middleware/stream-text.js.map +1 -1
- package/dist/ai-service/llmobs/types.d.ts +14 -1
- package/dist/ai-service/llmobs/types.d.ts.map +1 -1
- package/dist/ai-service/state-machine/clark-fsm.d.ts +75 -5
- package/dist/ai-service/state-machine/clark-fsm.d.ts.map +1 -1
- package/dist/ai-service/state-machine/clark-fsm.js +100 -0
- package/dist/ai-service/state-machine/clark-fsm.js.map +1 -1
- package/dist/ai-service/state-machine/handlers/agent-planning.d.ts.map +1 -1
- package/dist/ai-service/state-machine/handlers/agent-planning.js +4 -0
- package/dist/ai-service/state-machine/handlers/agent-planning.js.map +1 -1
- package/dist/ai-service/state-machine/handlers/llm-generating.d.ts.map +1 -1
- package/dist/ai-service/state-machine/handlers/llm-generating.js +91 -456
- package/dist/ai-service/state-machine/handlers/llm-generating.js.map +1 -1
- package/dist/ai-service/state-machine/handlers/runtime-reviewing.js +1 -1
- package/dist/ai-service/state-machine/handlers/runtime-reviewing.js.map +1 -1
- package/dist/ai-service/state-machine/helpers/peer.d.ts.map +1 -1
- package/dist/ai-service/state-machine/helpers/peer.js +15 -0
- package/dist/ai-service/state-machine/helpers/peer.js.map +1 -1
- package/dist/ai-service/state-machine/mocks.d.ts.map +1 -1
- package/dist/ai-service/state-machine/mocks.js +1 -0
- package/dist/ai-service/state-machine/mocks.js.map +1 -1
- package/dist/ai-service/template-renderer.js +1 -1
- package/dist/ai-service/template-renderer.js.map +1 -1
- package/dist/ai-service/types.d.ts +30 -0
- package/dist/ai-service/types.d.ts.map +1 -1
- package/dist/binding-extraction/extract-identifiers.d.ts +14 -0
- package/dist/binding-extraction/extract-identifiers.d.ts.map +1 -1
- package/dist/binding-extraction/extract-identifiers.js +46 -1
- package/dist/binding-extraction/extract-identifiers.js.map +1 -1
- package/dist/binding-extraction/js-identifiers.d.ts +14 -0
- package/dist/binding-extraction/js-identifiers.d.ts.map +1 -1
- package/dist/binding-extraction/js-identifiers.js +168 -0
- package/dist/binding-extraction/js-identifiers.js.map +1 -1
- package/dist/binding-extraction/python-identifiers.d.ts +5 -0
- package/dist/binding-extraction/python-identifiers.d.ts.map +1 -1
- package/dist/binding-extraction/python-identifiers.js +76 -7
- package/dist/binding-extraction/python-identifiers.js.map +1 -1
- package/dist/file-sync-vite-plugin.d.ts.map +1 -1
- package/dist/file-sync-vite-plugin.js +73 -3
- package/dist/file-sync-vite-plugin.js.map +1 -1
- package/dist/file-system-manager.d.ts.map +1 -1
- package/dist/file-system-manager.js +6 -4
- package/dist/file-system-manager.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/lock-service/activity-tracker.d.ts +14 -2
- package/dist/lock-service/activity-tracker.d.ts.map +1 -1
- package/dist/lock-service/activity-tracker.js +43 -6
- package/dist/lock-service/activity-tracker.js.map +1 -1
- package/dist/lock-service/index.d.ts +13 -2
- package/dist/lock-service/index.d.ts.map +1 -1
- package/dist/lock-service/index.js +130 -44
- package/dist/lock-service/index.js.map +1 -1
- package/dist/parsing/jsx.d.ts.map +1 -1
- package/dist/parsing/jsx.js +78 -66
- package/dist/parsing/jsx.js.map +1 -1
- package/dist/socket-manager.js +1 -1
- package/dist/socket-manager.js.map +1 -1
- package/dist/sync-service/list-dir.d.ts.map +1 -1
- package/dist/sync-service/list-dir.js +41 -18
- package/dist/sync-service/list-dir.js.map +1 -1
- package/dist/vite-plugin-yaml-types.d.ts.map +1 -1
- package/dist/vite-plugin-yaml-types.js +2 -4
- package/dist/vite-plugin-yaml-types.js.map +1 -1
- package/package.json +7 -7
- package/dist/ai-service/agent/subagents/apis/api-executor.d.ts.map +0 -1
- package/dist/ai-service/agent/subagents/apis/api-executor.js.map +0 -1
- package/dist/ai-service/agent/subagents/apis/context.d.ts +0 -12
- package/dist/ai-service/agent/subagents/apis/context.d.ts.map +0 -1
- package/dist/ai-service/agent/subagents/apis/context.js +0 -18
- package/dist/ai-service/agent/subagents/apis/context.js.map +0 -1
- package/dist/ai-service/agent/subagents/apis/generate-api-source.d.ts +0 -40
- package/dist/ai-service/agent/subagents/apis/generate-api-source.d.ts.map +0 -1
- package/dist/ai-service/agent/subagents/apis/generate-api-source.js +0 -516
- package/dist/ai-service/agent/subagents/apis/generate-api-source.js.map +0 -1
- package/dist/ai-service/agent/subagents/apis/state.d.ts +0 -49
- package/dist/ai-service/agent/subagents/apis/state.d.ts.map +0 -1
- package/dist/ai-service/agent/subagents/apis/state.js +0 -25
- package/dist/ai-service/agent/subagents/apis/state.js.map +0 -1
- package/dist/ai-service/agent/subagents/apis/system-prompt.d.ts +0 -3
- package/dist/ai-service/agent/subagents/apis/system-prompt.d.ts.map +0 -1
- package/dist/ai-service/agent/subagents/apis/system-prompt.js +0 -1704
- package/dist/ai-service/agent/subagents/apis/system-prompt.js.map +0 -1
- package/dist/ai-service/agent/tools/apis/finalize-api.d.ts +0 -11
- package/dist/ai-service/agent/tools/apis/finalize-api.d.ts.map +0 -1
- package/dist/ai-service/agent/tools/apis/finalize-api.js +0 -133
- package/dist/ai-service/agent/tools/apis/finalize-api.js.map +0 -1
- package/dist/ai-service/llm/middleware/retry.d.ts +0 -112
- package/dist/ai-service/llm/middleware/retry.d.ts.map +0 -1
- package/dist/ai-service/llm/middleware/retry.js +0 -239
- package/dist/ai-service/llm/middleware/retry.js.map +0 -1
|
@@ -0,0 +1,1841 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { selectExamplesByTags, formatSelectedExamples, } from "../../subagents/apis/example-selector.js";
|
|
3
|
+
import { POSITIVE_EXAMPLES, } from "../../subagents/apis/examples.js";
|
|
4
|
+
import { createToolFactory, ToolCategory } from "../../tools2/types.js";
|
|
5
|
+
import { getIntegrationTypeDefinition } from "./integration-types.js";
|
|
6
|
+
/**
|
|
7
|
+
* Core type definitions - control flow and base types only
|
|
8
|
+
* Integration-specific types are provided by getIntegrationTypeDefinition
|
|
9
|
+
*/
|
|
10
|
+
const TYPE_DEFINITIONS = `
|
|
11
|
+
## Core Type Definitions
|
|
12
|
+
|
|
13
|
+
These are the core type definitions for control flow blocks and base types in Superblocks APIs:
|
|
14
|
+
|
|
15
|
+
\`\`\`typescript
|
|
16
|
+
// @superblocksteam/library
|
|
17
|
+
|
|
18
|
+
export type JsonValue = any;
|
|
19
|
+
|
|
20
|
+
export type State = { [key: string]: JsonValue };
|
|
21
|
+
|
|
22
|
+
export type Binding<T> = T | ((state: State) => T);
|
|
23
|
+
|
|
24
|
+
export declare abstract class Block {
|
|
25
|
+
protected name: string;
|
|
26
|
+
|
|
27
|
+
constructor(name: string);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export declare abstract class Integration extends Block {
|
|
31
|
+
constructor(name: string, integration: string);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// Control Flow Blocks
|
|
35
|
+
|
|
36
|
+
export type Condition = {
|
|
37
|
+
when: Binding<boolean>;
|
|
38
|
+
then: Block[];
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
export type Conditions = {
|
|
42
|
+
if: Condition;
|
|
43
|
+
elif?: Condition[];
|
|
44
|
+
else?: Block[];
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
export declare class Conditional extends Block {
|
|
48
|
+
public conditions: Conditions;
|
|
49
|
+
|
|
50
|
+
constructor(name: string, config: Conditions);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export declare class Loop extends Block {
|
|
54
|
+
constructor(
|
|
55
|
+
name: string,
|
|
56
|
+
config: {
|
|
57
|
+
over: Binding<JsonValue[]>;
|
|
58
|
+
variables: { item: string; index: string };
|
|
59
|
+
blocks: Block[];
|
|
60
|
+
},
|
|
61
|
+
);
|
|
62
|
+
public static fromJSON(json: any, entities: string[]): Loop;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export declare class TryCatch extends Block {
|
|
66
|
+
constructor(
|
|
67
|
+
name: string,
|
|
68
|
+
config: {
|
|
69
|
+
try: Block[];
|
|
70
|
+
catch: Block[];
|
|
71
|
+
finally?: Block[];
|
|
72
|
+
variables: { error: string };
|
|
73
|
+
},
|
|
74
|
+
);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export declare class Throw extends Block {
|
|
78
|
+
constructor(
|
|
79
|
+
name: string,
|
|
80
|
+
config: {
|
|
81
|
+
error: Binding<JsonValue>;
|
|
82
|
+
},
|
|
83
|
+
);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export declare class Return extends Block {
|
|
87
|
+
constructor(
|
|
88
|
+
name: string,
|
|
89
|
+
config: {
|
|
90
|
+
data: Binding<JsonValue>;
|
|
91
|
+
},
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export declare class Break extends Block {
|
|
96
|
+
constructor(
|
|
97
|
+
name: string,
|
|
98
|
+
config: {
|
|
99
|
+
condition: Binding<JsonValue>;
|
|
100
|
+
},
|
|
101
|
+
);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// API and Authorization
|
|
105
|
+
|
|
106
|
+
export type Authorization =
|
|
107
|
+
| {
|
|
108
|
+
type: "AUTHORIZATION_TYPE_APP_USERS";
|
|
109
|
+
}
|
|
110
|
+
| {
|
|
111
|
+
type: "AUTHORIZATION_TYPE_JS_EXPRESSION";
|
|
112
|
+
expression: Binding<boolean>;
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
export declare class Api {
|
|
116
|
+
constructor(name: string, blocks?: Block[], authorization?: Authorization);
|
|
117
|
+
}
|
|
118
|
+
\`\`\`
|
|
119
|
+
|
|
120
|
+
**Note:** Integration-specific type definitions (PostgreSQL, Snowflake, OpenApi, etc.) are provided when you specify \`integrationIds\` in the tool call. JavaScript and Python block definitions are included in the "Built-in Blocks" section.
|
|
121
|
+
`;
|
|
122
|
+
/**
|
|
123
|
+
* Integration exploration workflow - critical for understanding integrations
|
|
124
|
+
*/
|
|
125
|
+
const INTEGRATION_EXPLORATION_WORKFLOW = `
|
|
126
|
+
## 🔍 Integration Exploration Workflow (CRITICAL)
|
|
127
|
+
|
|
128
|
+
When exploring integrations and data sources:
|
|
129
|
+
|
|
130
|
+
### 1. Start with metadata exploration
|
|
131
|
+
|
|
132
|
+
Use \`grepMetadata\` to understand:
|
|
133
|
+
- What tables/endpoints exist
|
|
134
|
+
- Schema structure and organization
|
|
135
|
+
- Available fields and data types
|
|
136
|
+
|
|
137
|
+
Query actual data (\`executeRequestToIntegration\`) only when you need:
|
|
138
|
+
- Specific data values for analysis
|
|
139
|
+
- Sample records to understand data patterns
|
|
140
|
+
- Actual data for application functionality
|
|
141
|
+
|
|
142
|
+
**💡 KEY PRINCIPLE:** For "tell me about the data" type questions, metadata exploration is usually sufficient and more efficient
|
|
143
|
+
|
|
144
|
+
### 2. NEVER use SQL/API queries for metadata exploration
|
|
145
|
+
|
|
146
|
+
❌ **WRONG**: \`SHOW COLUMNS FROM users\`, \`DESCRIBE table\`, \`SELECT * FROM INFORMATION_SCHEMA\`
|
|
147
|
+
❌ **WRONG**: API calls just to see what endpoints exist
|
|
148
|
+
✅ **CORRECT**: \`grepMetadata({ grepPattern: "\\\\.columns\\\\[\\\\d+\\\\]\\\\.name" })\` to find all columns (database)
|
|
149
|
+
✅ **CORRECT**: \`grepMetadata({ grepPattern: "\\\\.paths\\\\[\\".*repo.*\\"\\\\]" })\` for API paths with "repo" (OpenAPI)
|
|
150
|
+
|
|
151
|
+
### 3. Progressive Exploration for Large Integrations (100+ tables/endpoints)
|
|
152
|
+
|
|
153
|
+
**⚠️ Use this workflow ONLY for exploratory prompts** ("tell me about @databricks", "what data is available").
|
|
154
|
+
**When user mentions specific topics** ("weather app", "user orders"), search for those or similar keywords directly instead.
|
|
155
|
+
|
|
156
|
+
#### Step 1: Discover Top-Level Organization
|
|
157
|
+
- **Database Pattern**: \`"\\\\.dbSchema\\\\.schemas\\\\[\\\\d+\\\\]\\\\.name"\` (returns all unique schemas)
|
|
158
|
+
- **OpenAPI Pattern**: \`"\\\\.paths\\\\[.*\\\\]"\` (returns all API paths)
|
|
159
|
+
- **GraphQL Pattern**: \`"\\\\.types\\\\[\\\\d+\\\\]\\\\.name"\` (returns all GraphQL types)
|
|
160
|
+
|
|
161
|
+
#### Step 2: Explore Specific Area (User-Directed)
|
|
162
|
+
- **Database Pattern**:
|
|
163
|
+
- \`"\\\\.tables\\\\[\\\\d+\\\\]\\\\.name = \\".*\\""\` (get all table names)
|
|
164
|
+
- \`"\\\\.tables\\\\[\\\\d+\\\\]\\\\.name"\` (shorter - just find table name fields)
|
|
165
|
+
- **⚠️ NOT** \`"\\\\.schema\\\\.tables"\` - the field is \`dbSchema\` not \`schema\`!
|
|
166
|
+
- **OpenAPI Pattern**: \`"\\\\.paths\\\\[\\".*category.*\\"\\\\]"\` (paths matching category)
|
|
167
|
+
- **GraphQL Pattern**: \`"\\\\.types\\\\[\\\\d+\\\\]\\\\.name = \\".*User.*\\""\` (types matching pattern)
|
|
168
|
+
|
|
169
|
+
#### Step 3: Dive Into Specifics
|
|
170
|
+
- **Database Pattern**: \`"\\\\.tables\\\\[\\\\d+\\\\]\\\\.name = \\"exact_table\\""\` (returns full table with all columns!)
|
|
171
|
+
- **OpenAPI Pattern**: \`"\\\\.paths\\\\[\\"/exact/path\\"\\\\]\\\\..*"\` (all details for that endpoint)
|
|
172
|
+
- **GraphQL Pattern**: \`"\\\\.types\\\\[\\\\d+\\\\]\\\\.name = \\"User\\"|" + "\\\\.fields\\\\[\\\\d+\\\\]\\\\.name"\` (get fields for a type)
|
|
173
|
+
|
|
174
|
+
### 4. Critical: Different integration types use different key formats
|
|
175
|
+
|
|
176
|
+
#### DATABASE integrations (Postgres, MySQL, Snowflake, Databricks, etc.)
|
|
177
|
+
- **Structure**: All databases use \`json.dbSchema.schemas[]\` and \`json.dbSchema.tables[]\`
|
|
178
|
+
- **⚠️ CRITICAL**: It's \`dbSchema\` (NOT \`schema\`!) - the field name is \`dbSchema\`
|
|
179
|
+
- Use **numeric array indices**: \`[0]\`, \`[1]\`, \`[2]\`, etc.
|
|
180
|
+
- Pattern: Use \`\\\\d+\` to match any number
|
|
181
|
+
- Examples:
|
|
182
|
+
- ✅ \`"\\\\.dbSchema\\\\.schemas\\\\[\\\\d+\\\\]\\\\.name"\` - Find schema names
|
|
183
|
+
- ✅ \`"\\\\.tables\\\\[\\\\d+\\\\]\\\\.name = \\".*user.*\\""\` - Find tables
|
|
184
|
+
- ❌ \`"\\\\.schema\\\\.tables"\` - WRONG! It's \`dbSchema\` not \`schema\`
|
|
185
|
+
|
|
186
|
+
#### OPENAPI integrations (REST APIs with OpenAPI specs)
|
|
187
|
+
- Use **string object keys**: \`["/users"]\`, \`["/repos"]\`
|
|
188
|
+
- Pattern: Use \`.*\` to match any key (NOT \`\\\\d+\`!)
|
|
189
|
+
- **Structure**: Path string IS the key (not a field!)
|
|
190
|
+
- Format: \`json.openApiSpec.paths["/users"].get.operationId\`
|
|
191
|
+
- Examples:
|
|
192
|
+
- ✅ \`"\\\\.paths\\\\[\\".*repos.*\\"\\\\]"\` - Find paths with "repos"
|
|
193
|
+
- ✅ \`"\\\\.paths\\\\[\\"/exact/path\\"\\\\]"\` - Exact path match
|
|
194
|
+
- ❌ \`"\\\\.paths\\\\[\\\\d+\\\\]"\` - WRONG! OpenAPI doesn't use numeric indices
|
|
195
|
+
|
|
196
|
+
#### GRAPHQL integrations
|
|
197
|
+
- **Structure**: GraphQL uses standard introspection response format at \`json.graphql.data.__schema\`
|
|
198
|
+
- Use **numeric array indices**: \`[0]\`, \`[1]\`, \`[2]\`, etc.
|
|
199
|
+
- **Two-step workflow** (recommended for large schemas):
|
|
200
|
+
1. **Exploration**: Use \`includeDetails: false\` to get type with field names
|
|
201
|
+
2. **Detailed lookup**: Search for 1-3 specific fields at a time
|
|
202
|
+
|
|
203
|
+
### 5. Pagination and Truncation
|
|
204
|
+
|
|
205
|
+
**Understanding \`truncated: true\`**:
|
|
206
|
+
- Truncation is **NORMAL and EXPECTED** for large schemas
|
|
207
|
+
- It means: "Here's what I found so far"
|
|
208
|
+
|
|
209
|
+
**When to paginate:**
|
|
210
|
+
1. User explicitly wants ALL results: "Give me ALL tables"
|
|
211
|
+
2. Specific search truncated AND you need more
|
|
212
|
+
3. User requests continuation: "Show me more"
|
|
213
|
+
|
|
214
|
+
**When NOT to paginate:**
|
|
215
|
+
1. Sample is sufficient for the question
|
|
216
|
+
2. Can refine search instead
|
|
217
|
+
|
|
218
|
+
### 6. REST API vs OpenAPI Selection
|
|
219
|
+
|
|
220
|
+
**🚨 CRITICAL: When working with REST API integrations:**
|
|
221
|
+
1. **ALWAYS call \`grepMetadata\` first** to determine if the REST API is OpenAPI-backed
|
|
222
|
+
2. **If metadata shows it's an OpenAPI-backed API, you MUST:**
|
|
223
|
+
- Use the \`OpenApi\` class, NOT \`RestApi\`
|
|
224
|
+
- Supply the required \`openapi.path\` property
|
|
225
|
+
- Example: \`new OpenApi("api_call", "integration-id", {...}, { path: "/endpoint" })\`
|
|
226
|
+
3. **Only use \`RestApi\` class for non-OpenAPI REST integrations**
|
|
227
|
+
`;
|
|
228
|
+
/**
|
|
229
|
+
* Block output scoping rules - critical for understanding variable access
|
|
230
|
+
*/
|
|
231
|
+
const BLOCK_OUTPUT_SCOPING_RULES = `
|
|
232
|
+
## Block Output Scoping Rules
|
|
233
|
+
|
|
234
|
+
**CRITICAL: Blocks can only access outputs from specific scopes based on their position in the hierarchy.**
|
|
235
|
+
|
|
236
|
+
### Scoping Hierarchy
|
|
237
|
+
Control flow blocks (Loop, Conditional, TryCatch) create new scopes for their children. Regular blocks (JavaScript, PostgreSQL, etc.) do not create scopes.
|
|
238
|
+
|
|
239
|
+
### What blocks CAN access:
|
|
240
|
+
1. **Previous sibling blocks** at the same level (executed before them)
|
|
241
|
+
2. **ALL ancestor block outputs** (parent, grandparent, etc. up the chain)
|
|
242
|
+
3. **Parent control flow variables** (e.g., \`item\` and \`index\` in Loop, \`error\` in TryCatch)
|
|
243
|
+
4. **Control flow block outputs** (equals the output of their last child block)
|
|
244
|
+
|
|
245
|
+
### What blocks CANNOT access:
|
|
246
|
+
- ❌ Outputs from blocks nested inside other control flow blocks
|
|
247
|
+
- ❌ Outputs from blocks in other Conditional branches
|
|
248
|
+
- ❌ Outputs from blocks that come after them at the same level
|
|
249
|
+
|
|
250
|
+
### Example Hierarchy:
|
|
251
|
+
|
|
252
|
+
\`\`\`typescript
|
|
253
|
+
// Structure: A → B(Loop) → [B1, B2, B3] → C → D
|
|
254
|
+
|
|
255
|
+
new JavaScript("A_fetch_data", { fn: () => [...] }), // Block A
|
|
256
|
+
|
|
257
|
+
new Loop("B_process_items", { // Block B (control flow)
|
|
258
|
+
over: ({ A_fetch_data }) => A_fetch_data.output,
|
|
259
|
+
variables: { item: "current", index: "i" },
|
|
260
|
+
blocks: [
|
|
261
|
+
new JavaScript("B1_validate", { // Block B1
|
|
262
|
+
fn: ({ current, i, A_fetch_data }) => {
|
|
263
|
+
// ✅ Can access: current, i (loop vars), A_fetch_data
|
|
264
|
+
return { valid: true };
|
|
265
|
+
}
|
|
266
|
+
}),
|
|
267
|
+
new JavaScript("B2_transform", { // Block B2
|
|
268
|
+
fn: ({ B1_validate, current }) => {
|
|
269
|
+
// ✅ Can access: B1_validate, current, A_fetch_data
|
|
270
|
+
return { transformed: current.value };
|
|
271
|
+
}
|
|
272
|
+
}),
|
|
273
|
+
new JavaScript("B3_save", { // Block B3
|
|
274
|
+
fn: ({ B2_transform, B1_validate }) => {
|
|
275
|
+
// ✅ Can access: B2_transform, B1_validate, loop vars, A_fetch_data
|
|
276
|
+
return { saved: true };
|
|
277
|
+
}
|
|
278
|
+
})
|
|
279
|
+
]
|
|
280
|
+
}),
|
|
281
|
+
|
|
282
|
+
new JavaScript("C_aggregate", { // Block C
|
|
283
|
+
fn: ({ B_process_items, A_fetch_data }) => {
|
|
284
|
+
// ✅ Can access: B_process_items.output (= B3's output), A_fetch_data
|
|
285
|
+
// ❌ CANNOT access: B1_validate, B2_transform, B3_save (inside B's scope)
|
|
286
|
+
return { total: B_process_items.output.length };
|
|
287
|
+
}
|
|
288
|
+
}),
|
|
289
|
+
|
|
290
|
+
new JavaScript("D_finalize", { // Block D
|
|
291
|
+
fn: ({ C_aggregate, B_process_items, A_fetch_data }) => {
|
|
292
|
+
// ✅ Can access: C_aggregate, B_process_items, A_fetch_data
|
|
293
|
+
// ❌ CANNOT access: B1_validate, B2_transform, B3_save (inside B's scope)
|
|
294
|
+
return { complete: true };
|
|
295
|
+
}
|
|
296
|
+
})
|
|
297
|
+
\`\`\`
|
|
298
|
+
|
|
299
|
+
### Conditional Branch Scoping:
|
|
300
|
+
|
|
301
|
+
\`\`\`typescript
|
|
302
|
+
new Conditional("check_user_type", {
|
|
303
|
+
if: {
|
|
304
|
+
when: ({ userRole }) => userRole === "admin",
|
|
305
|
+
then: [
|
|
306
|
+
new JavaScript("admin_process", {
|
|
307
|
+
fn: () => ({ adminData: "..." })
|
|
308
|
+
})
|
|
309
|
+
]
|
|
310
|
+
},
|
|
311
|
+
elif: [{
|
|
312
|
+
when: ({ userRole }) => userRole === "user",
|
|
313
|
+
then: [
|
|
314
|
+
new JavaScript("user_process", {
|
|
315
|
+
fn: () => ({ userData: "..." })
|
|
316
|
+
})
|
|
317
|
+
]
|
|
318
|
+
}]
|
|
319
|
+
}),
|
|
320
|
+
|
|
321
|
+
new JavaScript("next_step", {
|
|
322
|
+
fn: ({ check_user_type }) => {
|
|
323
|
+
// ✅ Can access: check_user_type.output (from whichever branch executed)
|
|
324
|
+
// ❌ CANNOT access: admin_process or user_process directly
|
|
325
|
+
return check_user_type.output;
|
|
326
|
+
}
|
|
327
|
+
})
|
|
328
|
+
\`\`\`
|
|
329
|
+
|
|
330
|
+
### Variable Access Patterns
|
|
331
|
+
|
|
332
|
+
**Control Block Variables:**
|
|
333
|
+
\`\`\`typescript
|
|
334
|
+
// Always use .value for Loop, TryCatch variables
|
|
335
|
+
new Loop("process_items", {
|
|
336
|
+
variables: { item: "order", index: "i" },
|
|
337
|
+
blocks: [
|
|
338
|
+
new JavaScript("process", {
|
|
339
|
+
fn: ({ order, i }) => ({
|
|
340
|
+
id: order.value.id, // ✅ .value
|
|
341
|
+
position: i.value // ✅ .value
|
|
342
|
+
})
|
|
343
|
+
})
|
|
344
|
+
]
|
|
345
|
+
})
|
|
346
|
+
\`\`\`
|
|
347
|
+
|
|
348
|
+
**Previous Block Outputs:**
|
|
349
|
+
\`\`\`typescript
|
|
350
|
+
// Use .output for previous block results
|
|
351
|
+
new JavaScript("get_data", {
|
|
352
|
+
fn: () => [{ id: 1, name: "John" }, { id: 2, name: "Jane" }]
|
|
353
|
+
}),
|
|
354
|
+
new JavaScript("process_data", {
|
|
355
|
+
fn: ({ get_data }) => get_data.output.length // ✅ .output
|
|
356
|
+
})
|
|
357
|
+
\`\`\`
|
|
358
|
+
|
|
359
|
+
**Inputs:**
|
|
360
|
+
\`\`\`typescript
|
|
361
|
+
// Direct access inputs - no .value needed!
|
|
362
|
+
new PostgreSQL("insert_user", "valid-postgres-id", {
|
|
363
|
+
statement: ({ FirstName, LastName }) =>
|
|
364
|
+
\`INSERT INTO users VALUES ('\${FirstName}', '\${LastName}')\`
|
|
365
|
+
// ✅ FirstName and LastName are API inputs - accessed directly, no .value
|
|
366
|
+
})
|
|
367
|
+
|
|
368
|
+
// Compare with step outputs which DO need .output:
|
|
369
|
+
new JavaScript("process", {
|
|
370
|
+
fn: ({ FirstName, insert_user }) => {
|
|
371
|
+
// FirstName is an API input - no .value needed
|
|
372
|
+
if (FirstName) { ... } // ✅ CORRECT
|
|
373
|
+
|
|
374
|
+
// insert_user is a step output - needs .output
|
|
375
|
+
if (insert_user.output) { ... } // ✅ CORRECT
|
|
376
|
+
}
|
|
377
|
+
})
|
|
378
|
+
\`\`\`
|
|
379
|
+
`;
|
|
380
|
+
/**
|
|
381
|
+
* Input discovery rules - how variables become API inputs
|
|
382
|
+
*/
|
|
383
|
+
const INPUT_DISCOVERY_RULES = `
|
|
384
|
+
## 🎯 API Input Discovery Rules (CRITICAL)
|
|
385
|
+
|
|
386
|
+
**IMPORTANT: You do NOT need to explicitly declare API inputs. They are automatically discovered through code analysis.**
|
|
387
|
+
|
|
388
|
+
### How Variables Become API Inputs
|
|
389
|
+
|
|
390
|
+
Variables are **implicitly discovered** as API inputs when they are:
|
|
391
|
+
1. **Destructured in block functions** but not defined elsewhere
|
|
392
|
+
2. **Referenced but not produced** by any previous block
|
|
393
|
+
3. **External to the API scope** (not step outputs or control flow variables)
|
|
394
|
+
|
|
395
|
+
### 🚨 CRITICAL: Always Type Your Input Parameters
|
|
396
|
+
|
|
397
|
+
**EVERY input parameter MUST have a TypeScript type annotation.**
|
|
398
|
+
|
|
399
|
+
When you reference input variables in your API code, you MUST add type annotations to the destructured parameters:
|
|
400
|
+
|
|
401
|
+
#### ✅ CORRECT - Typed parameters:
|
|
402
|
+
\`\`\`typescript
|
|
403
|
+
// Single typed parameter
|
|
404
|
+
new JavaScript("validate_email", {
|
|
405
|
+
fn: ({ email }: { email: string }) => {
|
|
406
|
+
return email.includes("@");
|
|
407
|
+
}
|
|
408
|
+
})
|
|
409
|
+
|
|
410
|
+
// Multiple typed parameters
|
|
411
|
+
new PostgreSQL("search_users", "postgres-id", {
|
|
412
|
+
statement: ({ searchTerm, limit }: { searchTerm: string; limit: number }) =>
|
|
413
|
+
\`SELECT * FROM users WHERE name ILIKE '%\${searchTerm}%' LIMIT \${limit}\`
|
|
414
|
+
})
|
|
415
|
+
|
|
416
|
+
// Optional parameters with union types
|
|
417
|
+
new JavaScript("process_filters", {
|
|
418
|
+
fn: ({ status, category }: { status?: string; category?: string | null }) => {
|
|
419
|
+
const filters = [];
|
|
420
|
+
if (status) filters.push(\`status = '\${status}'\`);
|
|
421
|
+
if (category) filters.push(\`category = '\${category}'\`);
|
|
422
|
+
return filters.join(" AND ");
|
|
423
|
+
}
|
|
424
|
+
})
|
|
425
|
+
\`\`\`
|
|
426
|
+
|
|
427
|
+
#### ❌ WRONG - Untyped parameters:
|
|
428
|
+
\`\`\`typescript
|
|
429
|
+
// Missing type annotations
|
|
430
|
+
new JavaScript("validate_email", {
|
|
431
|
+
fn: ({ email }) => { // ❌ No type annotation!
|
|
432
|
+
return email.includes("@");
|
|
433
|
+
}
|
|
434
|
+
})
|
|
435
|
+
|
|
436
|
+
new PostgreSQL("search_users", "postgres-id", {
|
|
437
|
+
statement: ({ searchTerm, limit }) => // ❌ No types!
|
|
438
|
+
\`SELECT * FROM users WHERE name ILIKE '%\${searchTerm}%' LIMIT \${limit}\`
|
|
439
|
+
})
|
|
440
|
+
\`\`\`
|
|
441
|
+
|
|
442
|
+
#### Type Inference from Context
|
|
443
|
+
|
|
444
|
+
Use appropriate types based on the parameter's usage:
|
|
445
|
+
- **String fields**: \`name: string\`, \`email: string\`, \`description: string\`
|
|
446
|
+
- **Numeric values**: \`age: number\`, \`price: number\`, \`quantity: number\`
|
|
447
|
+
- **Booleans**: \`isActive: boolean\`, \`hasPermission: boolean\`
|
|
448
|
+
- **Optional values**: \`category?: string\`, \`userId?: number\`
|
|
449
|
+
- **Nullable values**: \`middleName: string | null\`, \`avatar: string | null | undefined\`
|
|
450
|
+
- **Arrays**: \`tags: string[]\`, \`ids: number[]\`
|
|
451
|
+
- **Objects**: \`user: { id: number; name: string }\`
|
|
452
|
+
- **Union types**: \`status: "active" | "pending" | "inactive"\`
|
|
453
|
+
|
|
454
|
+
#### Why This Matters
|
|
455
|
+
|
|
456
|
+
Typed parameters enable:
|
|
457
|
+
1. **Automatic type extraction** - The buildApi tool extracts these types to generate accurate input interfaces
|
|
458
|
+
2. **Better IDE support** - Type checking catches errors before runtime
|
|
459
|
+
3. **Self-documenting code** - Types show what inputs are expected
|
|
460
|
+
4. **Frontend integration** - Generated type definition files provide accurate TypeScript types for the frontend
|
|
461
|
+
|
|
462
|
+
**REMEMBER**: Every input parameter MUST have a type annotation. The system will automatically extract these to generate the API's input interface.
|
|
463
|
+
|
|
464
|
+
### ⚠️ CRITICAL: When to Use .value vs Direct Access
|
|
465
|
+
|
|
466
|
+
**API Inputs** - Access DIRECTLY (no .value):
|
|
467
|
+
\`\`\`typescript
|
|
468
|
+
fn: ({ statusFilter, emailFilter }) => {
|
|
469
|
+
if (statusFilter) { ... } // ✅ CORRECT - direct access
|
|
470
|
+
if (statusFilter.value) { ... } // ❌ WRONG - don't use .value
|
|
471
|
+
}
|
|
472
|
+
\`\`\`
|
|
473
|
+
|
|
474
|
+
**Step Outputs** - Use .output:
|
|
475
|
+
\`\`\`typescript
|
|
476
|
+
fn: ({ previous_step }) => {
|
|
477
|
+
return previous_step.output; // ✅ CORRECT - use .output
|
|
478
|
+
return previous_step; // ❌ WRONG - missing .output
|
|
479
|
+
}
|
|
480
|
+
\`\`\`
|
|
481
|
+
|
|
482
|
+
**Loop Variables** - Use .value:
|
|
483
|
+
\`\`\`typescript
|
|
484
|
+
fn: ({ item, index }) => { // Loop variables from Loop block
|
|
485
|
+
return item.value.id; // ✅ CORRECT - use .value
|
|
486
|
+
return item.id; // ❌ WRONG - missing .value
|
|
487
|
+
}
|
|
488
|
+
\`\`\`
|
|
489
|
+
|
|
490
|
+
**TryCatch Error Variables** - Use .value:
|
|
491
|
+
\`\`\`typescript
|
|
492
|
+
fn: ({ error }) => { // Error variable from TryCatch
|
|
493
|
+
return error.value.message; // ✅ CORRECT - use .value
|
|
494
|
+
return error.message; // ❌ WRONG - missing .value
|
|
495
|
+
}
|
|
496
|
+
\`\`\`
|
|
497
|
+
|
|
498
|
+
### Automatic Input Detection
|
|
499
|
+
|
|
500
|
+
\`\`\`typescript
|
|
501
|
+
// Example: startDate and endDate automatically become API inputs
|
|
502
|
+
export default new Api("GetOrders", [
|
|
503
|
+
new JavaScript("build_query", {
|
|
504
|
+
fn: ({ startDate, endDate }) => { // ✅ These become inputs automatically
|
|
505
|
+
let query = "SELECT * FROM orders";
|
|
506
|
+
|
|
507
|
+
if (startDate) {
|
|
508
|
+
query += \` WHERE date >= '\${startDate}'\`;
|
|
509
|
+
}
|
|
510
|
+
if (endDate) {
|
|
511
|
+
query += \` AND date <= '\${endDate}'\`;
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
return query;
|
|
515
|
+
}
|
|
516
|
+
}),
|
|
517
|
+
|
|
518
|
+
new PostgreSQL("fetch_orders", "postgres-id", {
|
|
519
|
+
statement: ({ build_query }) => build_query.output // ❌ NOT an input (it's a block output)
|
|
520
|
+
})
|
|
521
|
+
]);
|
|
522
|
+
\`\`\`
|
|
523
|
+
|
|
524
|
+
### What Does NOT Become an Input
|
|
525
|
+
|
|
526
|
+
1. **Previous block outputs** (accessed via \`.output\`):
|
|
527
|
+
\`\`\`typescript
|
|
528
|
+
new JavaScript("process", {
|
|
529
|
+
fn: ({ fetch_data }) => fetch_data.output // ❌ NOT an input - it's a block reference
|
|
530
|
+
})
|
|
531
|
+
\`\`\`
|
|
532
|
+
|
|
533
|
+
2. **Control flow variables** (accessed via \`.value\`):
|
|
534
|
+
\`\`\`typescript
|
|
535
|
+
new Loop("process_items", {
|
|
536
|
+
variables: { item: "order", index: "i" },
|
|
537
|
+
blocks: [
|
|
538
|
+
new JavaScript("transform", {
|
|
539
|
+
fn: ({ order, i }) => ({ // ❌ NOT inputs - they're loop variables
|
|
540
|
+
id: order.value.id,
|
|
541
|
+
position: i.value
|
|
542
|
+
})
|
|
543
|
+
})
|
|
544
|
+
]
|
|
545
|
+
})
|
|
546
|
+
\`\`\`
|
|
547
|
+
|
|
548
|
+
3. **Error variables in TryCatch**:
|
|
549
|
+
\`\`\`typescript
|
|
550
|
+
new TryCatch("safe_operation", {
|
|
551
|
+
catch: [
|
|
552
|
+
new JavaScript("handle_error", {
|
|
553
|
+
fn: ({ err }) => err.value // ❌ NOT an input - it's a catch variable
|
|
554
|
+
})
|
|
555
|
+
],
|
|
556
|
+
variables: { error: "err" }
|
|
557
|
+
})
|
|
558
|
+
\`\`\`
|
|
559
|
+
|
|
560
|
+
### Type Generation
|
|
561
|
+
|
|
562
|
+
When you build an API, the system automatically:
|
|
563
|
+
1. **Analyzes your code** to find all undefined external variables
|
|
564
|
+
2. **Generates TypeScript interfaces** for the inputs
|
|
565
|
+
3. **Creates a types.d.ts file** with the proper types
|
|
566
|
+
|
|
567
|
+
Example generated types for the GetOrders API above:
|
|
568
|
+
\`\`\`typescript
|
|
569
|
+
// Auto-generated by Superblocks
|
|
570
|
+
interface GetOrdersInput {
|
|
571
|
+
startDate?: any;
|
|
572
|
+
endDate?: any;
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
type GetOrdersResponse = any;
|
|
576
|
+
\`\`\`
|
|
577
|
+
|
|
578
|
+
### How APIs Are Called
|
|
579
|
+
|
|
580
|
+
Once built, APIs can be called from the frontend with the discovered inputs:
|
|
581
|
+
|
|
582
|
+
\`\`\`typescript
|
|
583
|
+
// In React component
|
|
584
|
+
const { run: runGetOrders } = useApi("GetOrders");
|
|
585
|
+
|
|
586
|
+
const response = await runGetOrders({
|
|
587
|
+
startDate: "2024-01-01",
|
|
588
|
+
endDate: "2024-12-31"
|
|
589
|
+
});
|
|
590
|
+
|
|
591
|
+
// The API returns the output of the last block directly
|
|
592
|
+
const orders = response || [];
|
|
593
|
+
\`\`\`
|
|
594
|
+
|
|
595
|
+
### Best Practices
|
|
596
|
+
|
|
597
|
+
1. **Use descriptive parameter names** that clearly indicate their purpose
|
|
598
|
+
2. **Don't worry about declaring inputs** - the system handles it automatically
|
|
599
|
+
3. **Focus on using the variables** where you need them - inputs are inferred
|
|
600
|
+
4. **Check the build output** to see which inputs were detected
|
|
601
|
+
|
|
602
|
+
### Common Patterns
|
|
603
|
+
|
|
604
|
+
**Filter parameters automatically become inputs:**
|
|
605
|
+
\`\`\`typescript
|
|
606
|
+
new JavaScript("build_filter", {
|
|
607
|
+
fn: ({ statusFilter, userIdFilter, dateRangeFilter }) => {
|
|
608
|
+
// All three filters automatically become API inputs
|
|
609
|
+
const conditions = [];
|
|
610
|
+
if (statusFilter) conditions.push(\`status = '\${statusFilter}'\`);
|
|
611
|
+
if (userIdFilter) conditions.push(\`user_id = \${userIdFilter}\`);
|
|
612
|
+
if (dateRangeFilter) conditions.push(\`date BETWEEN ...\`);
|
|
613
|
+
return conditions;
|
|
614
|
+
}
|
|
615
|
+
})
|
|
616
|
+
\`\`\`
|
|
617
|
+
|
|
618
|
+
**Pagination parameters:**
|
|
619
|
+
\`\`\`typescript
|
|
620
|
+
new JavaScript("paginate", {
|
|
621
|
+
fn: ({ page = 1, pageSize = 20 }) => {
|
|
622
|
+
// page and pageSize become optional inputs with defaults
|
|
623
|
+
const offset = (page - 1) * pageSize;
|
|
624
|
+
return { offset, limit: pageSize };
|
|
625
|
+
}
|
|
626
|
+
})
|
|
627
|
+
\`\`\`
|
|
628
|
+
`;
|
|
629
|
+
/**
|
|
630
|
+
* Common API patterns including the critical two-block dynamic SQL pattern
|
|
631
|
+
*/
|
|
632
|
+
const COMMON_API_PATTERNS = `
|
|
633
|
+
## 🔄 Common API Patterns
|
|
634
|
+
|
|
635
|
+
### Groups check
|
|
636
|
+
\`\`\`typescript
|
|
637
|
+
new JavaScript("check_groups", {
|
|
638
|
+
fn: ({ Global }) => {
|
|
639
|
+
const isFieldEngUser = Global.groups.some(group => group.name === "FieldEngineer");
|
|
640
|
+
if (isFieldEngUser) {
|
|
641
|
+
// Perform actions for FieldEngineer
|
|
642
|
+
} else {
|
|
643
|
+
// Perform actions for non-FieldEngineer
|
|
644
|
+
}
|
|
645
|
+
}
|
|
646
|
+
})
|
|
647
|
+
\`\`\`
|
|
648
|
+
|
|
649
|
+
### Simple Data Retrieval
|
|
650
|
+
\`\`\`typescript
|
|
651
|
+
export default new Api("getUsersApi", [
|
|
652
|
+
new JavaScript("fetch_users", {
|
|
653
|
+
fn: () => [
|
|
654
|
+
{ id: 1, name: "John Doe", email: "john@example.com" },
|
|
655
|
+
{ id: 2, name: "Jane Smith", email: "jane@example.com" }
|
|
656
|
+
]
|
|
657
|
+
})
|
|
658
|
+
]);
|
|
659
|
+
\`\`\`
|
|
660
|
+
|
|
661
|
+
### Input Validation + Processing
|
|
662
|
+
\`\`\`typescript
|
|
663
|
+
export default new Api("createUserApi", [
|
|
664
|
+
new Conditional("validate_inputs", {
|
|
665
|
+
if: {
|
|
666
|
+
when: ({ FirstNameInput, EmailInput }: { FirstNameInput: string; EmailInput: string }): boolean =>
|
|
667
|
+
!FirstNameInput || !EmailInput,
|
|
668
|
+
then: [
|
|
669
|
+
new Throw("validation_error", {
|
|
670
|
+
error: "First name and email are required"
|
|
671
|
+
})
|
|
672
|
+
]
|
|
673
|
+
}
|
|
674
|
+
}),
|
|
675
|
+
new JavaScript("create_user", {
|
|
676
|
+
fn: ({ FirstNameInput, EmailInput }: { FirstNameInput: string; EmailInput: string }) => ({
|
|
677
|
+
id: Math.floor(Math.random() * 1000),
|
|
678
|
+
name: FirstNameInput,
|
|
679
|
+
email: EmailInput,
|
|
680
|
+
created_at: new Date().toISOString()
|
|
681
|
+
})
|
|
682
|
+
})
|
|
683
|
+
]);
|
|
684
|
+
\`\`\`
|
|
685
|
+
|
|
686
|
+
### Data Processing with Loops
|
|
687
|
+
\`\`\`typescript
|
|
688
|
+
export default new Api("processOrdersApi", [
|
|
689
|
+
new JavaScript("get_orders", {
|
|
690
|
+
fn: () => [
|
|
691
|
+
{ id: 1, status: "pending", amount: 100 },
|
|
692
|
+
{ id: 2, status: "pending", amount: 200 }
|
|
693
|
+
]
|
|
694
|
+
}),
|
|
695
|
+
new Loop("process_each_order", {
|
|
696
|
+
over: ({ get_orders }) => get_orders.output,
|
|
697
|
+
variables: { item: "order", index: "i" },
|
|
698
|
+
blocks: [
|
|
699
|
+
new JavaScript("calculate_tax", {
|
|
700
|
+
fn: ({ order, i }) => ({
|
|
701
|
+
...order.value,
|
|
702
|
+
tax: order.value.amount * 0.1,
|
|
703
|
+
total: order.value.amount * 1.1,
|
|
704
|
+
position: i.value
|
|
705
|
+
})
|
|
706
|
+
})
|
|
707
|
+
]
|
|
708
|
+
})
|
|
709
|
+
]);
|
|
710
|
+
\`\`\`
|
|
711
|
+
|
|
712
|
+
### 🚨 Dynamic SQL Queries (Two-Block Pattern) - CRITICAL
|
|
713
|
+
\`\`\`typescript
|
|
714
|
+
import {
|
|
715
|
+
Api,
|
|
716
|
+
JavaScript,
|
|
717
|
+
PostgreSQL,
|
|
718
|
+
} from "@superblocksteam/library";
|
|
719
|
+
|
|
720
|
+
export default new Api("searchOrdersApi", [
|
|
721
|
+
// Block 1: Build the dynamic SQL query in JavaScript
|
|
722
|
+
new JavaScript("build_search_query", {
|
|
723
|
+
fn: ({ EmailFilter, StatusFilter }: { EmailFilter?: string; StatusFilter?: string }) => {
|
|
724
|
+
let query = \`
|
|
725
|
+
SELECT id, user_email, product, price, status, date_purchased
|
|
726
|
+
FROM orders
|
|
727
|
+
\`;
|
|
728
|
+
|
|
729
|
+
const conditions = [];
|
|
730
|
+
|
|
731
|
+
if (EmailFilter && EmailFilter.trim()) {
|
|
732
|
+
conditions.push(\`user_email ILIKE '%\${EmailFilter}%'\`);
|
|
733
|
+
}
|
|
734
|
+
|
|
735
|
+
if (StatusFilter && StatusFilter !== 'all') {
|
|
736
|
+
conditions.push(\`status = '\${StatusFilter}'\`);
|
|
737
|
+
}
|
|
738
|
+
|
|
739
|
+
if (conditions.length > 0) {
|
|
740
|
+
query += \` WHERE \${conditions.join(' AND ')}\`;
|
|
741
|
+
}
|
|
742
|
+
|
|
743
|
+
return query + \` ORDER BY date_purchased DESC LIMIT 100\`;
|
|
744
|
+
}
|
|
745
|
+
}),
|
|
746
|
+
// Block 2: Execute the dynamically built SQL query
|
|
747
|
+
new PostgreSQL("execute_search", "your-postgresql-integration-id", {
|
|
748
|
+
statement: ({ build_search_query }) => build_search_query.output
|
|
749
|
+
})
|
|
750
|
+
]);
|
|
751
|
+
\`\`\`
|
|
752
|
+
|
|
753
|
+
**Why the Two-Block Pattern?**
|
|
754
|
+
- **SQL blocks can ONLY contain SQL** - no JavaScript logic allowed
|
|
755
|
+
- **JavaScript blocks build the dynamic query** based on conditions
|
|
756
|
+
- **SQL blocks execute the prepared query** from the JavaScript block
|
|
757
|
+
- This separation maintains clean language boundaries
|
|
758
|
+
`;
|
|
759
|
+
/**
|
|
760
|
+
* Error handling guidelines - when to use TryCatch
|
|
761
|
+
*/
|
|
762
|
+
const ERROR_HANDLING_GUIDELINES = `
|
|
763
|
+
## ⚠️ Error Handling: When to Use TryCatch
|
|
764
|
+
|
|
765
|
+
**IMPORTANT: Do NOT use TryCatch blocks by default. Only use them when truly necessary.**
|
|
766
|
+
|
|
767
|
+
Wrapping everything in try/catch adds unnecessary complexity that makes workflows harder to understand and debug.
|
|
768
|
+
|
|
769
|
+
### ❌ DO NOT use TryCatch for:
|
|
770
|
+
|
|
771
|
+
1. **Standard operations that should fail fast:**
|
|
772
|
+
\`\`\`typescript
|
|
773
|
+
// ❌ WRONG - Unnecessary try/catch for normal database query
|
|
774
|
+
new TryCatch("wrapped_query", {
|
|
775
|
+
try: [
|
|
776
|
+
new PostgreSQL("fetch_users", "postgres-id", {
|
|
777
|
+
statement: "SELECT * FROM users LIMIT 100"
|
|
778
|
+
})
|
|
779
|
+
],
|
|
780
|
+
catch: [
|
|
781
|
+
new JavaScript("handle_error", {
|
|
782
|
+
fn: ({ err }) => ({ error: err.value })
|
|
783
|
+
})
|
|
784
|
+
],
|
|
785
|
+
variables: { error: "err" }
|
|
786
|
+
})
|
|
787
|
+
|
|
788
|
+
// ✅ CORRECT - Let the query fail naturally if there's an issue
|
|
789
|
+
new PostgreSQL("fetch_users", "postgres-id", {
|
|
790
|
+
statement: "SELECT * FROM users LIMIT 100"
|
|
791
|
+
})
|
|
792
|
+
\`\`\`
|
|
793
|
+
|
|
794
|
+
2. **Simple data transformations:**
|
|
795
|
+
\`\`\`typescript
|
|
796
|
+
// ❌ WRONG - Wrapping basic JavaScript logic
|
|
797
|
+
new TryCatch("safe_transform", {
|
|
798
|
+
try: [
|
|
799
|
+
new JavaScript("transform_data", {
|
|
800
|
+
fn: ({ userData }) => userData.output.map(u => u.name)
|
|
801
|
+
})
|
|
802
|
+
],
|
|
803
|
+
catch: [
|
|
804
|
+
new Return("empty_array", { data: () => [] })
|
|
805
|
+
],
|
|
806
|
+
variables: { error: "err" }
|
|
807
|
+
})
|
|
808
|
+
|
|
809
|
+
// ✅ CORRECT - Direct transformation
|
|
810
|
+
new JavaScript("transform_data", {
|
|
811
|
+
fn: ({ userData }) => userData.output.map(u => u.name)
|
|
812
|
+
})
|
|
813
|
+
\`\`\`
|
|
814
|
+
|
|
815
|
+
### ✅ DO use TryCatch when:
|
|
816
|
+
|
|
817
|
+
1. **User explicitly requests error handling**
|
|
818
|
+
|
|
819
|
+
2. **Continuing execution after failure is business-critical:**
|
|
820
|
+
\`\`\`typescript
|
|
821
|
+
// ✅ Process must continue even if notification fails
|
|
822
|
+
new TryCatch("attempt_notification", {
|
|
823
|
+
try: [
|
|
824
|
+
new Email("send_notification", {
|
|
825
|
+
from: "noreply@example.com",
|
|
826
|
+
to: ({ userEmail }) => userEmail,
|
|
827
|
+
subject: "Order Confirmed",
|
|
828
|
+
body: "Your order has been confirmed"
|
|
829
|
+
})
|
|
830
|
+
],
|
|
831
|
+
catch: [
|
|
832
|
+
new JavaScript("log_notification_failure", {
|
|
833
|
+
fn: ({ err }) => ({
|
|
834
|
+
emailFailed: true,
|
|
835
|
+
error: err.value.message
|
|
836
|
+
})
|
|
837
|
+
})
|
|
838
|
+
],
|
|
839
|
+
variables: { error: "err" }
|
|
840
|
+
}),
|
|
841
|
+
// Continue processing regardless of email success
|
|
842
|
+
new JavaScript("finalize_order", {
|
|
843
|
+
fn: ({ orderData }) => ({ status: "complete" })
|
|
844
|
+
})
|
|
845
|
+
\`\`\`
|
|
846
|
+
|
|
847
|
+
3. **Partial failure recovery in loops:**
|
|
848
|
+
\`\`\`typescript
|
|
849
|
+
// ✅ Process all items even if some fail
|
|
850
|
+
new Loop("process_all_orders", {
|
|
851
|
+
over: ({ orders }) => orders.output,
|
|
852
|
+
variables: { item: "order", index: "i" },
|
|
853
|
+
blocks: [
|
|
854
|
+
new TryCatch("safe_process", {
|
|
855
|
+
try: [
|
|
856
|
+
new RestApi("external_validation", "rest-id", {
|
|
857
|
+
method: "POST",
|
|
858
|
+
url: "https://validator.example.com/check",
|
|
859
|
+
body: ({ order }) => JSON.stringify(order.value)
|
|
860
|
+
})
|
|
861
|
+
],
|
|
862
|
+
catch: [
|
|
863
|
+
new JavaScript("mark_failed", {
|
|
864
|
+
fn: ({ order, err }) => ({
|
|
865
|
+
orderId: order.value.id,
|
|
866
|
+
failed: true,
|
|
867
|
+
error: err.value
|
|
868
|
+
})
|
|
869
|
+
})
|
|
870
|
+
],
|
|
871
|
+
variables: { error: "err" }
|
|
872
|
+
})
|
|
873
|
+
]
|
|
874
|
+
})
|
|
875
|
+
\`\`\`
|
|
876
|
+
|
|
877
|
+
4. **Graceful degradation with fallback data:**
|
|
878
|
+
\`\`\`typescript
|
|
879
|
+
// ✅ Use cached data if live fetch fails
|
|
880
|
+
new TryCatch("fetch_with_fallback", {
|
|
881
|
+
try: [
|
|
882
|
+
new RestApi("fetch_live_prices", "rest-id", {
|
|
883
|
+
method: "GET",
|
|
884
|
+
url: "https://api.example.com/prices"
|
|
885
|
+
})
|
|
886
|
+
],
|
|
887
|
+
catch: [
|
|
888
|
+
new PostgreSQL("fetch_cached_prices", "postgres-id", {
|
|
889
|
+
statement: "SELECT * FROM cached_prices WHERE updated_at > NOW() - INTERVAL '1 hour'"
|
|
890
|
+
})
|
|
891
|
+
],
|
|
892
|
+
variables: { error: "err" }
|
|
893
|
+
})
|
|
894
|
+
\`\`\`
|
|
895
|
+
|
|
896
|
+
### General Rule:
|
|
897
|
+
|
|
898
|
+
**If you can't clearly articulate why the try/catch is necessary for business logic, don't use it.** Error messages are more helpful to users when they surface naturally rather than being caught and hidden.
|
|
899
|
+
`;
|
|
900
|
+
/**
|
|
901
|
+
* SQL best practices section
|
|
902
|
+
*/
|
|
903
|
+
const SQL_BEST_PRACTICES = `
|
|
904
|
+
## 📝 SQL Best Practices
|
|
905
|
+
|
|
906
|
+
### 1. ONE Query Per Block Rule
|
|
907
|
+
Each SQL block (PostgreSQL, Snowflake, MySQL, MicrosoftSql, Databricks) can execute **ONLY ONE SQL query**.
|
|
908
|
+
|
|
909
|
+
❌ **WRONG - Multiple queries in one block:**
|
|
910
|
+
\`\`\`sql
|
|
911
|
+
UPDATE users SET status = 'active';
|
|
912
|
+
DELETE FROM logs WHERE created < '2023-01-01';
|
|
913
|
+
INSERT INTO audit VALUES ('done');
|
|
914
|
+
\`\`\`
|
|
915
|
+
|
|
916
|
+
✅ **CORRECT - One query per block:**
|
|
917
|
+
\`\`\`typescript
|
|
918
|
+
new PostgreSQL("update_status", "postgres-id", {
|
|
919
|
+
statement: "UPDATE users SET status = 'active'"
|
|
920
|
+
}),
|
|
921
|
+
new PostgreSQL("clean_logs", "postgres-id", {
|
|
922
|
+
statement: "DELETE FROM logs WHERE created < '2023-01-01'"
|
|
923
|
+
})
|
|
924
|
+
\`\`\`
|
|
925
|
+
|
|
926
|
+
### 2. Sort, Don't Filter by Date (Default)
|
|
927
|
+
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.
|
|
928
|
+
|
|
929
|
+
✅ **Default approach:**
|
|
930
|
+
\`\`\`sql
|
|
931
|
+
SELECT * FROM orders ORDER BY created_at DESC LIMIT 100;
|
|
932
|
+
\`\`\`
|
|
933
|
+
|
|
934
|
+
❌ **Avoid automatic filtering:**
|
|
935
|
+
\`\`\`sql
|
|
936
|
+
SELECT * FROM orders WHERE created_at >= CURRENT_DATE - INTERVAL '90 days'; -- Can return empty results
|
|
937
|
+
\`\`\`
|
|
938
|
+
|
|
939
|
+
Only add date WHERE clauses when users explicitly ask for time-based filtering.
|
|
940
|
+
|
|
941
|
+
### 3. Always Add Defensive LIMIT Clauses
|
|
942
|
+
Always include a LIMIT clause to prevent runaway queries. Use 100 as the default unless user specifies otherwise.
|
|
943
|
+
|
|
944
|
+
✅ **Default approach:**
|
|
945
|
+
\`\`\`sql
|
|
946
|
+
SELECT * FROM orders ORDER BY created_at DESC LIMIT 100;
|
|
947
|
+
\`\`\`
|
|
948
|
+
|
|
949
|
+
❌ **Avoid unlimited queries:**
|
|
950
|
+
\`\`\`sql
|
|
951
|
+
SELECT * FROM orders ORDER BY created_at DESC; -- Can timeout or crash
|
|
952
|
+
\`\`\`
|
|
953
|
+
`;
|
|
954
|
+
/**
|
|
955
|
+
* Database naming conventions
|
|
956
|
+
*/
|
|
957
|
+
const DATABASE_NAMING_CONVENTIONS = `
|
|
958
|
+
## 📊 Database Schema Naming Conventions
|
|
959
|
+
|
|
960
|
+
### Databricks Three-Part Naming
|
|
961
|
+
Databricks uses a **three-part naming convention**: \`catalog.schema.table\`
|
|
962
|
+
|
|
963
|
+
When you see Databricks metadata like:
|
|
964
|
+
- \`uber.default.orders\` - Use the FULL path: \`uber.default.orders\`
|
|
965
|
+
- \`production.analytics.users\` - Use: \`production.analytics.users\`
|
|
966
|
+
|
|
967
|
+
**❌ WRONG for Databricks:**
|
|
968
|
+
\`\`\`sql
|
|
969
|
+
-- Metadata shows: uber.default.orders
|
|
970
|
+
SELECT * FROM uber.orders -- ❌ Missing schema part
|
|
971
|
+
SELECT * FROM orders -- ❌ Missing catalog and schema
|
|
972
|
+
\`\`\`
|
|
973
|
+
|
|
974
|
+
**✅ CORRECT for Databricks:**
|
|
975
|
+
\`\`\`sql
|
|
976
|
+
-- Always use the full three-part name
|
|
977
|
+
SELECT * FROM uber.default.orders -- ✅ Full path
|
|
978
|
+
SELECT * FROM catalog.schema.table -- ✅ Pattern
|
|
979
|
+
\`\`\`
|
|
980
|
+
|
|
981
|
+
**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.
|
|
982
|
+
|
|
983
|
+
### Snowflake Two-Part Naming
|
|
984
|
+
Snowflake uses **schema-qualified table names**: \`schema.table\`
|
|
985
|
+
|
|
986
|
+
When you see Snowflake metadata where tables have a \`schema\` property, **you MUST qualify table names**:
|
|
987
|
+
|
|
988
|
+
**Metadata structure:**
|
|
989
|
+
\`\`\`json
|
|
990
|
+
{
|
|
991
|
+
"schema": {
|
|
992
|
+
"tables": [
|
|
993
|
+
{
|
|
994
|
+
"name": "PRODUCTLINE",
|
|
995
|
+
"schema": "MASTERDATA",
|
|
996
|
+
"columns": [...]
|
|
997
|
+
}
|
|
998
|
+
]
|
|
999
|
+
}
|
|
1000
|
+
}
|
|
1001
|
+
\`\`\`
|
|
1002
|
+
|
|
1003
|
+
**❌ WRONG for Snowflake:**
|
|
1004
|
+
\`\`\`sql
|
|
1005
|
+
-- Missing schema qualification
|
|
1006
|
+
SELECT * FROM PRODUCTLINE -- ❌ Will fail if no default schema
|
|
1007
|
+
\`\`\`
|
|
1008
|
+
|
|
1009
|
+
**✅ CORRECT for Snowflake:**
|
|
1010
|
+
\`\`\`sql
|
|
1011
|
+
-- Always use schema.table format when schema property exists
|
|
1012
|
+
SELECT * FROM MASTERDATA.PRODUCTLINE -- ✅ Fully qualified
|
|
1013
|
+
\`\`\`
|
|
1014
|
+
|
|
1015
|
+
**Rule**: If a table object has a non-empty \`schema\` property, use \`{schema}.{name}\` format in your SQL queries.
|
|
1016
|
+
|
|
1017
|
+
### Traditional SQL Databases (PostgreSQL, MySQL, etc.)
|
|
1018
|
+
Traditional databases use **two-part naming**: \`schema.table\`
|
|
1019
|
+
- PostgreSQL: \`public.orders\` or just \`orders\`
|
|
1020
|
+
- MySQL: \`database.orders\` or just \`orders\`
|
|
1021
|
+
`;
|
|
1022
|
+
/**
|
|
1023
|
+
* Response interface guidelines
|
|
1024
|
+
*/
|
|
1025
|
+
const RESPONSE_INTERFACE_GUIDELINES = `
|
|
1026
|
+
## 📝 Response Interface for finalizeApi
|
|
1027
|
+
|
|
1028
|
+
The \`responseInterface\` describes what external code gets from \`apiName.response\`. Internal blocks/steps are NOT visible externally.
|
|
1029
|
+
|
|
1030
|
+
### Direct Response Types
|
|
1031
|
+
|
|
1032
|
+
✅ **CORRECT**: Direct array response
|
|
1033
|
+
\`\`\`typescript
|
|
1034
|
+
interface GetUsersApiResponse {
|
|
1035
|
+
id: number;
|
|
1036
|
+
name: string;
|
|
1037
|
+
email: string;
|
|
1038
|
+
}[]
|
|
1039
|
+
\`\`\`
|
|
1040
|
+
|
|
1041
|
+
✅ **CORRECT**: Direct data structure
|
|
1042
|
+
\`\`\`typescript
|
|
1043
|
+
interface GetOrdersApiResponse {
|
|
1044
|
+
orders: Order[];
|
|
1045
|
+
totalCount: number;
|
|
1046
|
+
}
|
|
1047
|
+
\`\`\`
|
|
1048
|
+
|
|
1049
|
+
❌ **WRONG**: Exposing internal steps
|
|
1050
|
+
\`\`\`typescript
|
|
1051
|
+
interface GetOrdersApiResponse {
|
|
1052
|
+
fetchStep: { output: Order[] }; // ❌ Steps are internal
|
|
1053
|
+
countStep: { output: number }; // ❌ Not visible outside
|
|
1054
|
+
}
|
|
1055
|
+
\`\`\`
|
|
1056
|
+
|
|
1057
|
+
### Type Safety for API Response Interfaces
|
|
1058
|
+
|
|
1059
|
+
**CRITICAL: When defining response interfaces, consider runtime reality, not just happy-path data.**
|
|
1060
|
+
|
|
1061
|
+
#### Making Fields Optional
|
|
1062
|
+
|
|
1063
|
+
When uncertain if an API field will always be present, mark it optional:
|
|
1064
|
+
|
|
1065
|
+
✅ **CORRECT** - Accounts for real-world API behavior:
|
|
1066
|
+
\`\`\`typescript
|
|
1067
|
+
interface GitHubPRResponse {
|
|
1068
|
+
id: number;
|
|
1069
|
+
title: string;
|
|
1070
|
+
user?: { // ← Optional, can be null for deleted users
|
|
1071
|
+
login: string;
|
|
1072
|
+
avatar_url: string;
|
|
1073
|
+
} | null;
|
|
1074
|
+
labels?: Label[]; // ← Optional, might be omitted in response
|
|
1075
|
+
}
|
|
1076
|
+
\`\`\`
|
|
1077
|
+
|
|
1078
|
+
❌ **WRONG** - False confidence:
|
|
1079
|
+
\`\`\`typescript
|
|
1080
|
+
interface GitHubPRResponse {
|
|
1081
|
+
user: { // ← Marked required, but API can return null
|
|
1082
|
+
login: string;
|
|
1083
|
+
avatar_url: string;
|
|
1084
|
+
};
|
|
1085
|
+
}
|
|
1086
|
+
\`\`\`
|
|
1087
|
+
|
|
1088
|
+
#### When to Make Fields Optional
|
|
1089
|
+
|
|
1090
|
+
Mark fields optional when:
|
|
1091
|
+
1. **User/account references** - Can be null for deleted/deactivated accounts
|
|
1092
|
+
2. **Nested objects** - May be omitted in partial responses
|
|
1093
|
+
3. **Third-party APIs** - GitHub, Stripe, etc. often have nullable fields
|
|
1094
|
+
4. **Loading states** - Data may not be available during initial render
|
|
1095
|
+
5. **Uncertain API behavior** - When in doubt, mark optional
|
|
1096
|
+
|
|
1097
|
+
This prevents downstream runtime errors when frontend code accesses these fields.
|
|
1098
|
+
`;
|
|
1099
|
+
/**
|
|
1100
|
+
* Runtime safety and defensive coding
|
|
1101
|
+
*/
|
|
1102
|
+
const RUNTIME_SAFETY = `
|
|
1103
|
+
## Runtime Safety and Defensive Coding (CRITICAL)
|
|
1104
|
+
|
|
1105
|
+
- Prefer safe access patterns that tolerate partial/missing data. When reading nested fields, assume null/undefined is possible unless guaranteed otherwise.
|
|
1106
|
+
- Use optional chaining and nullish coalescing when producing outputs that the frontend will consume; avoid throwing on missing optional fields.
|
|
1107
|
+
- For REST/OpenAPI/GraphQL responses, treat non-required fields as optional in interfaces. If unsure, mark as optional and document assumptions in finalize summary.
|
|
1108
|
+
- Avoid catching and suppressing unexpected errors with TryCatch unless explicitly asked; surface meaningful errors. Use validation (Conditional + Throw) for expected preconditions.
|
|
1109
|
+
- When transforming arrays or objects from external sources, default to empty arrays/objects when inputs are absent.
|
|
1110
|
+
|
|
1111
|
+
Examples:
|
|
1112
|
+
\`\`\`typescript
|
|
1113
|
+
// Optional fields
|
|
1114
|
+
type User = { id: number; name?: string | null };
|
|
1115
|
+
|
|
1116
|
+
// Defensive transformation
|
|
1117
|
+
new JavaScript("normalize_users", {
|
|
1118
|
+
fn: ({ fetch_users }) => (Array.isArray(fetch_users.output) ? fetch_users.output : []).map(u => ({
|
|
1119
|
+
id: u.id,
|
|
1120
|
+
name: (u.name ?? "Unknown").toString()
|
|
1121
|
+
}))
|
|
1122
|
+
})
|
|
1123
|
+
|
|
1124
|
+
// Guarded access
|
|
1125
|
+
new Conditional("validate_email", {
|
|
1126
|
+
if: {
|
|
1127
|
+
when: ({ EmailInput }) => !EmailInput,
|
|
1128
|
+
then: [new Throw("missing_email", { error: "Email is required" })]
|
|
1129
|
+
}
|
|
1130
|
+
})
|
|
1131
|
+
\`\`\`
|
|
1132
|
+
`;
|
|
1133
|
+
/**
|
|
1134
|
+
* Error recovery strategies
|
|
1135
|
+
*/
|
|
1136
|
+
const ERROR_RECOVERY_STRATEGIES = `
|
|
1137
|
+
## 🚨 Error Handling and Recovery
|
|
1138
|
+
|
|
1139
|
+
When you encounter errors while building APIs, follow these guidelines:
|
|
1140
|
+
|
|
1141
|
+
### Read Error Messages Carefully
|
|
1142
|
+
|
|
1143
|
+
Error messages contain specific guidance on how to fix the problem. Pay close attention to:
|
|
1144
|
+
- What operation failed (compilation, validation, execution)
|
|
1145
|
+
- Suggestions for how to resolve the issue
|
|
1146
|
+
- Whether metadata is missing
|
|
1147
|
+
|
|
1148
|
+
### When to Check Integration Metadata
|
|
1149
|
+
|
|
1150
|
+
If you encounter errors mentioning:
|
|
1151
|
+
- "unknown column", "table not found", "invalid field"
|
|
1152
|
+
- "check integration metadata"
|
|
1153
|
+
- Integration type mismatches
|
|
1154
|
+
|
|
1155
|
+
You MUST call \`readIntegrationMetadata\` to get the correct schema/table structure before retrying.
|
|
1156
|
+
`;
|
|
1157
|
+
/**
|
|
1158
|
+
* Loop control patterns
|
|
1159
|
+
*/
|
|
1160
|
+
const LOOP_CONTROL = `
|
|
1161
|
+
## 🔄 Loop Control
|
|
1162
|
+
|
|
1163
|
+
**Breaking out of loops:**
|
|
1164
|
+
\`\`\`typescript
|
|
1165
|
+
new Loop("process_until_complete", {
|
|
1166
|
+
over: ({ items }) => items.output,
|
|
1167
|
+
variables: { item: "current", index: "i" },
|
|
1168
|
+
blocks: [
|
|
1169
|
+
new Conditional("check_stop_condition", {
|
|
1170
|
+
if: {
|
|
1171
|
+
when: ({ current }) => current.value.status === "complete",
|
|
1172
|
+
then: [
|
|
1173
|
+
new Break("exit_loop", { condition: () => true }) // ✅ Only way to exit
|
|
1174
|
+
]
|
|
1175
|
+
}
|
|
1176
|
+
}),
|
|
1177
|
+
new JavaScript("process_item", {
|
|
1178
|
+
fn: ({ current, i }) => ({
|
|
1179
|
+
processed: current.value,
|
|
1180
|
+
position: i.value
|
|
1181
|
+
})
|
|
1182
|
+
})
|
|
1183
|
+
]
|
|
1184
|
+
})
|
|
1185
|
+
\`\`\`
|
|
1186
|
+
`;
|
|
1187
|
+
/**
|
|
1188
|
+
* API structure requirements
|
|
1189
|
+
*/
|
|
1190
|
+
const API_STRUCTURE = `
|
|
1191
|
+
## 🏗️ API Structure Requirements
|
|
1192
|
+
|
|
1193
|
+
### File Structure
|
|
1194
|
+
\`\`\`typescript
|
|
1195
|
+
// Path: /apis/apiName.ts
|
|
1196
|
+
|
|
1197
|
+
// ✅ ALWAYS import the required types from the library
|
|
1198
|
+
import {
|
|
1199
|
+
Api,
|
|
1200
|
+
JavaScript,
|
|
1201
|
+
Python,
|
|
1202
|
+
Databricks,
|
|
1203
|
+
Snowflake,
|
|
1204
|
+
PostgreSQL,
|
|
1205
|
+
GraphQL,
|
|
1206
|
+
RestApi,
|
|
1207
|
+
S3,
|
|
1208
|
+
Email,
|
|
1209
|
+
Conditional,
|
|
1210
|
+
TryCatch,
|
|
1211
|
+
Loop,
|
|
1212
|
+
Throw,
|
|
1213
|
+
Return,
|
|
1214
|
+
Break,
|
|
1215
|
+
} from "@superblocksteam/library";
|
|
1216
|
+
|
|
1217
|
+
// ✅ Export default API with consistent naming
|
|
1218
|
+
export default new Api("apiName", [
|
|
1219
|
+
// Workflow blocks here
|
|
1220
|
+
]);
|
|
1221
|
+
\`\`\`
|
|
1222
|
+
|
|
1223
|
+
### Basic Workflow Structure
|
|
1224
|
+
\`\`\`typescript
|
|
1225
|
+
// 1. Input validation
|
|
1226
|
+
// 2. Data fetching (integrations)
|
|
1227
|
+
// 3. Data processing (JavaScript/Python)
|
|
1228
|
+
// 4. Error handling (Try/Catch)
|
|
1229
|
+
// 5. Return formatted output
|
|
1230
|
+
\`\`\`
|
|
1231
|
+
`;
|
|
1232
|
+
/**
|
|
1233
|
+
* Critical mistakes to avoid
|
|
1234
|
+
*/
|
|
1235
|
+
const CRITICAL_MISTAKES = `
|
|
1236
|
+
## 🚨 Critical Mistakes to Avoid
|
|
1237
|
+
|
|
1238
|
+
### 1. OVERUSING TRYCATCH BLOCKS
|
|
1239
|
+
See the Error Handling section - only use TryCatch when truly necessary, not by default.
|
|
1240
|
+
|
|
1241
|
+
### 2. WRONG LANGUAGE FOR INTEGRATION TYPE
|
|
1242
|
+
|
|
1243
|
+
❌ **NEVER put JavaScript in PostgreSQL statement:**
|
|
1244
|
+
\`\`\`typescript
|
|
1245
|
+
new PostgreSQL("bad_query", "valid-postgres-id", {
|
|
1246
|
+
statement: ({ userId }) => \`SELECT * FROM users WHERE id = \${userId}\` // ❌ This is JavaScript!
|
|
1247
|
+
})
|
|
1248
|
+
\`\`\`
|
|
1249
|
+
|
|
1250
|
+
❌ **NEVER put SQL in JavaScript fn:**
|
|
1251
|
+
\`\`\`typescript
|
|
1252
|
+
new JavaScript("bad_js", {
|
|
1253
|
+
fn: "SELECT * FROM users" // ❌ This is SQL, not JavaScript!
|
|
1254
|
+
})
|
|
1255
|
+
\`\`\`
|
|
1256
|
+
|
|
1257
|
+
❌ **NEVER put multiple queries in one SQL block:**
|
|
1258
|
+
\`\`\`typescript
|
|
1259
|
+
new PostgreSQL("bad_multiple_queries", "postgres-id", {
|
|
1260
|
+
statement: \`
|
|
1261
|
+
UPDATE users SET status = 'active';
|
|
1262
|
+
DELETE FROM logs WHERE created < '2023-01-01';
|
|
1263
|
+
INSERT INTO audit VALUES ('done');
|
|
1264
|
+
\` // ❌ Multiple queries in one block will fail!
|
|
1265
|
+
})
|
|
1266
|
+
\`\`\`
|
|
1267
|
+
|
|
1268
|
+
✅ **CORRECT Language Matching:**
|
|
1269
|
+
\`\`\`typescript
|
|
1270
|
+
// ✅ PostgreSQL gets SQL in statement with typed parameters
|
|
1271
|
+
new PostgreSQL("good_query", "your-postgresql-integration-id", {
|
|
1272
|
+
statement: ({ userId }: { userId: string }) => \`SELECT * FROM users WHERE id = '\${userId}'\`
|
|
1273
|
+
})
|
|
1274
|
+
|
|
1275
|
+
// ✅ JavaScript gets JavaScript function in fn with typed parameters
|
|
1276
|
+
new JavaScript("good_js", {
|
|
1277
|
+
fn: ({ userData }: { userData: Array<{ id: number; name: string; email: string }> }) =>
|
|
1278
|
+
userData.map(user => ({ id: user.id, name: user.name }))
|
|
1279
|
+
})
|
|
1280
|
+
|
|
1281
|
+
// ✅ Python gets Python string in fn (types in function signature)
|
|
1282
|
+
new Python("good_python", {
|
|
1283
|
+
fn: \`
|
|
1284
|
+
def main(userId: str) -> str:
|
|
1285
|
+
return f"Processing user {userId}"
|
|
1286
|
+
\`
|
|
1287
|
+
})
|
|
1288
|
+
\`\`\`
|
|
1289
|
+
|
|
1290
|
+
### 3. Wrong Variable Access
|
|
1291
|
+
\`\`\`typescript
|
|
1292
|
+
// WRONG - accessing non-existent variables
|
|
1293
|
+
new JavaScript("bad_example", {
|
|
1294
|
+
fn: ({ SomeVariable }) => SomeVariable
|
|
1295
|
+
// ❌ SomeVariable must be provided as an input when the API is called!
|
|
1296
|
+
})
|
|
1297
|
+
\`\`\`
|
|
1298
|
+
|
|
1299
|
+
### 4. Fake Integration IDs
|
|
1300
|
+
\`\`\`typescript
|
|
1301
|
+
// WRONG - making up integration IDs
|
|
1302
|
+
new PostgreSQL("query", "fake-postgres-id", { // ❌ Never do this!
|
|
1303
|
+
statement: "SELECT * FROM users"
|
|
1304
|
+
})
|
|
1305
|
+
\`\`\`
|
|
1306
|
+
|
|
1307
|
+
### 5. APIs Cannot Set Frontend State
|
|
1308
|
+
APIs are backend workflows that can only READ state, never SET it. State mutations MUST happen on the frontend.
|
|
1309
|
+
|
|
1310
|
+
❌ **NEVER attempt to set state inside API blocks:**
|
|
1311
|
+
\`\`\`typescript
|
|
1312
|
+
new JavaScript("update_data", {
|
|
1313
|
+
fn: ({ userData }) => {
|
|
1314
|
+
userNameVar.value = userData.name; // ❌ CANNOT set state here!
|
|
1315
|
+
selectedUserVar.value = userData; // ❌ CANNOT set state here!
|
|
1316
|
+
UserInput.value = userData.email; // ❌ CANNOT set component values here!
|
|
1317
|
+
return userData;
|
|
1318
|
+
}
|
|
1319
|
+
})
|
|
1320
|
+
\`\`\`
|
|
1321
|
+
|
|
1322
|
+
✅ **CORRECT: APIs return data, frontend handles state updates:**
|
|
1323
|
+
\`\`\`typescript
|
|
1324
|
+
new JavaScript("update_data", {
|
|
1325
|
+
fn: ({ userData }) => {
|
|
1326
|
+
// Process data, perform calculations, transformations
|
|
1327
|
+
const processedUser = {
|
|
1328
|
+
...userData,
|
|
1329
|
+
fullName: \`\${userData.firstName} \${userData.lastName}\`,
|
|
1330
|
+
lastUpdated: new Date().toISOString()
|
|
1331
|
+
};
|
|
1332
|
+
return processedUser; // Frontend will handle state updates in onSuccess
|
|
1333
|
+
}
|
|
1334
|
+
})
|
|
1335
|
+
\`\`\`
|
|
1336
|
+
`;
|
|
1337
|
+
/**
|
|
1338
|
+
* API checklist
|
|
1339
|
+
*/
|
|
1340
|
+
const API_CHECKLIST = `
|
|
1341
|
+
## 📝 API Checklist
|
|
1342
|
+
|
|
1343
|
+
When creating APIs, you MUST follow this mental checklist:
|
|
1344
|
+
|
|
1345
|
+
1. **CORRECT LANGUAGE FOR EACH INTEGRATION** - SQL for PostgreSQL/Redshift/Snowflake, JavaScript for JavaScript blocks, Python strings for Python blocks
|
|
1346
|
+
2. **CORRECT CLASS FOR REST APIs** - Use \`OpenApi\` class with \`openapi.path\` when \`grepMetadata\` shows OpenAPI spec exists, otherwise use \`RestApi\`
|
|
1347
|
+
3. All imports included
|
|
1348
|
+
4. Correct variable access patterns (.value, .output, and .output.data for GraphQL)
|
|
1349
|
+
5. No fake or placeholder integration IDs
|
|
1350
|
+
6. No placeholder logic
|
|
1351
|
+
7. Descriptive block names
|
|
1352
|
+
8. Error handling where appropriate - **avoid TryCatch blocks unless truly necessary**
|
|
1353
|
+
9. Consistent naming across the API
|
|
1354
|
+
10. NEVER change the API name when editing an existing API. Even if the prompt suggests another name, you must leave it as-is, or the API will break.
|
|
1355
|
+
11. **ALWAYS** test the API after building to ensure it works as expected before moving on to other work.
|
|
1356
|
+
12. Response interface describes ONLY what's available as \`apiName.response\` - no internal steps
|
|
1357
|
+
|
|
1358
|
+
Remember: Superblocks APIs are reactive workflow builders that transform inputs into backend operations. Keep them declarative and focused.
|
|
1359
|
+
`;
|
|
1360
|
+
/**
|
|
1361
|
+
* Core documentation that applies to all APIs - now much more comprehensive
|
|
1362
|
+
*/
|
|
1363
|
+
const CORE_DOCUMENTATION = `# Superblocks API Documentation
|
|
1364
|
+
|
|
1365
|
+
## Mental Model
|
|
1366
|
+
|
|
1367
|
+
APIs in Superblocks are backend logic blocks that run in a secure server environment. They:
|
|
1368
|
+
- Execute integrations (database queries, API calls, etc.)
|
|
1369
|
+
- Process data with JavaScript or Python
|
|
1370
|
+
- Return data to the frontend
|
|
1371
|
+
- Cannot directly modify UI state
|
|
1372
|
+
|
|
1373
|
+
**Superblocks APIs are NOT traditional backend services.** They are frontend-coupled workflow builders that:
|
|
1374
|
+
- **Build declarative workflows** - using a chain of blocks to provide I/O and control flow
|
|
1375
|
+
- **Access inputs the user provides when they call the API from the frontend** - APIs receive input parameters passed from the application
|
|
1376
|
+
- **Are visualized in the Superblocks editor** - APIs are represented in the Superblocks UI in a way that any user can understand
|
|
1377
|
+
|
|
1378
|
+
## 🚨 Critical Rules
|
|
1379
|
+
|
|
1380
|
+
### 1. Language Must Match Integration Type
|
|
1381
|
+
|
|
1382
|
+
**NEVER mix languages between integration types. This is the #1 cause of API failures.**
|
|
1383
|
+
|
|
1384
|
+
- **SQL integrations** (PostgreSQL, MySQL, Snowflake, etc.): Use SQL syntax
|
|
1385
|
+
- **JavaScript blocks**: Use JavaScript/TypeScript syntax
|
|
1386
|
+
- **Python blocks**: Use Python syntax
|
|
1387
|
+
- **REST/GraphQL**: Use appropriate query languages
|
|
1388
|
+
|
|
1389
|
+
**The API will completely fail if you provide the wrong language to an integration.**
|
|
1390
|
+
|
|
1391
|
+
### 2. Variable Scoping
|
|
1392
|
+
|
|
1393
|
+
Variables referenced in API blocks can ONLY come from these sources:
|
|
1394
|
+
- **Outputs of previous blocks** in the same API (accessed via block name)
|
|
1395
|
+
- **Inputs from the user calling the API in their app** (passed as destructured parameters)
|
|
1396
|
+
|
|
1397
|
+
Important: Input variables from the frontend are GLOBAL for all API blocks. Do not shadow user input variables with local variables in your code.
|
|
1398
|
+
|
|
1399
|
+
### 4. Block Execution Order
|
|
1400
|
+
- Blocks execute sequentially from top to bottom
|
|
1401
|
+
- Each block can access outputs from previous blocks
|
|
1402
|
+
- Use control flow blocks (Loop, Conditional, Try/Catch) for complex logic
|
|
1403
|
+
|
|
1404
|
+
### 5. GraphQL Output Structure
|
|
1405
|
+
GraphQL steps return \`{ data: {...}, errors?: [...] }\`. Access query results via \`stepName.output.data\`, not \`stepName.output\` directly.
|
|
1406
|
+
|
|
1407
|
+
## ✅ Best Practices
|
|
1408
|
+
|
|
1409
|
+
1. **Single Responsibility**: Each API should do one thing well
|
|
1410
|
+
2. **Clear Naming**: Use descriptive names for blocks and APIs
|
|
1411
|
+
3. **Input Validation**: Validate inputs early in the API
|
|
1412
|
+
4. **Error Boundaries**: Use Try/Catch for external operations (but only when truly necessary)
|
|
1413
|
+
5. **Documentation**: Comment complex logic
|
|
1414
|
+
6. **Performance**: Minimize database round trips
|
|
1415
|
+
7. **Security**: Never expose sensitive data in responses
|
|
1416
|
+
8. **Reasonable Guardrails**: Use LIMIT clauses in SQL queries, validate input ranges
|
|
1417
|
+
9. **Plan the workflow**: Think through the sequence of operations before coding
|
|
1418
|
+
10. **No placeholder logic**: Always implement real functionality
|
|
1419
|
+
|
|
1420
|
+
## Parallel Generation
|
|
1421
|
+
|
|
1422
|
+
Whenever you have multiple APIs to create, parallelize the tool calls as much as possible to minimize latency.
|
|
1423
|
+
|
|
1424
|
+
## Permissions
|
|
1425
|
+
|
|
1426
|
+
If the user request's checking user data, like email, ID, or group membership, you MUST use \`Global\` in your API code. This is injected by the backend API execution engine.
|
|
1427
|
+
|
|
1428
|
+
\`\`\`
|
|
1429
|
+
type Global = {
|
|
1430
|
+
user: {
|
|
1431
|
+
email: string;
|
|
1432
|
+
username: string;
|
|
1433
|
+
id: string;
|
|
1434
|
+
name: string;
|
|
1435
|
+
groups: Group[]
|
|
1436
|
+
};
|
|
1437
|
+
};
|
|
1438
|
+
\`\`\`
|
|
1439
|
+
|
|
1440
|
+
\`Global\` is always available to use inside your API code, include it as a parameter when you need to access user data.
|
|
1441
|
+
`;
|
|
1442
|
+
/**
|
|
1443
|
+
* Get documentation for built-in blocks (JavaScript and Python)
|
|
1444
|
+
*/
|
|
1445
|
+
function getBuiltInBlockDocumentation() {
|
|
1446
|
+
return `## Built-in Blocks
|
|
1447
|
+
|
|
1448
|
+
### JavaScript Blocks
|
|
1449
|
+
|
|
1450
|
+
JavaScript blocks execute code directly in the API runtime environment. They're used for data transformation, validation, and business logic.
|
|
1451
|
+
|
|
1452
|
+
#### TypeScript Definition
|
|
1453
|
+
\`\`\`typescript
|
|
1454
|
+
export class JavaScript extends Integration {
|
|
1455
|
+
constructor(
|
|
1456
|
+
name: string,
|
|
1457
|
+
config: {
|
|
1458
|
+
fn: (state: State) => any; // Function that receives state with all previous blocks
|
|
1459
|
+
}
|
|
1460
|
+
);
|
|
1461
|
+
}
|
|
1462
|
+
\`\`\`
|
|
1463
|
+
|
|
1464
|
+
#### Usage Pattern
|
|
1465
|
+
\`\`\`typescript
|
|
1466
|
+
new JavaScript("TransformData", {
|
|
1467
|
+
fn: ({ GetUsers, statusFilter }) => {
|
|
1468
|
+
// Access previous block outputs directly
|
|
1469
|
+
const users = GetUsers.output;
|
|
1470
|
+
|
|
1471
|
+
// Access frontend variables
|
|
1472
|
+
const status = statusFilter.value;
|
|
1473
|
+
|
|
1474
|
+
// Transform and return data
|
|
1475
|
+
return users
|
|
1476
|
+
.filter(user => user.status === status)
|
|
1477
|
+
.map(user => ({
|
|
1478
|
+
...user,
|
|
1479
|
+
fullName: \`\${user.firstName} \${user.lastName}\`
|
|
1480
|
+
}));
|
|
1481
|
+
}
|
|
1482
|
+
})
|
|
1483
|
+
\`\`\`
|
|
1484
|
+
|
|
1485
|
+
#### Key Points
|
|
1486
|
+
- Use \`fn\` property with a JavaScript function
|
|
1487
|
+
- Access previous blocks via destructured parameters
|
|
1488
|
+
- Can access frontend variables in the same way
|
|
1489
|
+
- Return value becomes the block's output
|
|
1490
|
+
- Supports async/await for asynchronous operations
|
|
1491
|
+
|
|
1492
|
+
### Python Blocks
|
|
1493
|
+
|
|
1494
|
+
Python blocks execute Python code strings. They're ideal for data science operations, complex calculations, and when Python libraries are needed.
|
|
1495
|
+
|
|
1496
|
+
#### TypeScript Definition
|
|
1497
|
+
\`\`\`typescript
|
|
1498
|
+
export class Python extends Integration {
|
|
1499
|
+
constructor(
|
|
1500
|
+
name: string,
|
|
1501
|
+
config: {
|
|
1502
|
+
fn: string; // Python code as a string
|
|
1503
|
+
}
|
|
1504
|
+
);
|
|
1505
|
+
}
|
|
1506
|
+
\`\`\`
|
|
1507
|
+
|
|
1508
|
+
#### Usage Pattern
|
|
1509
|
+
\`\`\`typescript
|
|
1510
|
+
new Python("AnalyzeData", {
|
|
1511
|
+
fn: \`
|
|
1512
|
+
def main(GetUsers, statusFilter):
|
|
1513
|
+
import pandas as pd
|
|
1514
|
+
|
|
1515
|
+
# Access previous block outputs directly
|
|
1516
|
+
users = GetUsers['output']
|
|
1517
|
+
|
|
1518
|
+
# Access input parameters directly
|
|
1519
|
+
status = statusFilter
|
|
1520
|
+
|
|
1521
|
+
# Convert to DataFrame
|
|
1522
|
+
df = pd.DataFrame(users)
|
|
1523
|
+
|
|
1524
|
+
# Filter by status
|
|
1525
|
+
df_filtered = df[df['status'] == status]
|
|
1526
|
+
|
|
1527
|
+
# Perform analysis
|
|
1528
|
+
summary = {
|
|
1529
|
+
'total_count': len(df_filtered),
|
|
1530
|
+
'avg_age': df_filtered['age'].mean(),
|
|
1531
|
+
'status_distribution': df_filtered['status'].value_counts().to_dict()
|
|
1532
|
+
}
|
|
1533
|
+
|
|
1534
|
+
# Return as JSON-serializable object
|
|
1535
|
+
return summary
|
|
1536
|
+
\`
|
|
1537
|
+
})
|
|
1538
|
+
\`\`\`
|
|
1539
|
+
|
|
1540
|
+
#### Key Points
|
|
1541
|
+
- Use \`fn\` property with a Python code string containing a \`main\` function
|
|
1542
|
+
- Access previous blocks and inputs as function parameters
|
|
1543
|
+
- Previous block outputs accessed as \`blockName['output']\`
|
|
1544
|
+
- Input parameters accessed directly (no \`.value\` needed)
|
|
1545
|
+
- Must return JSON-serializable data
|
|
1546
|
+
- Common libraries available: pandas, numpy, scipy, etc.
|
|
1547
|
+
- DON'T FORGET to return the result using the \`return\` statement
|
|
1548
|
+
|
|
1549
|
+
### 🚨 Critical: Never Mix Languages
|
|
1550
|
+
|
|
1551
|
+
**CORRECT:**
|
|
1552
|
+
- JavaScript block: \`fn: ({ data }) => data.map(...)\`
|
|
1553
|
+
- Python block: \`fn: "import pandas as pd\\ndf = pd.DataFrame(data)"\`
|
|
1554
|
+
- SQL block: \`statement: "SELECT * FROM users"\`
|
|
1555
|
+
|
|
1556
|
+
**INCORRECT:**
|
|
1557
|
+
- JavaScript block with Python: \`fn: "import pandas"\` ❌
|
|
1558
|
+
- Python block with JavaScript: \`fn: ({ data }) => ...\` ❌
|
|
1559
|
+
- SQL block with JavaScript: \`statement: "users.map(u => u.id)"\` ❌`;
|
|
1560
|
+
}
|
|
1561
|
+
/**
|
|
1562
|
+
* Get integration-specific documentation based on plugin type
|
|
1563
|
+
*/
|
|
1564
|
+
function getIntegrationSpecificDocs(pluginId) {
|
|
1565
|
+
const specialDocs = {
|
|
1566
|
+
snowflake: `### Snowflake Specific Patterns
|
|
1567
|
+
- Use two-part naming: \`schema.table\` or \`"SCHEMA"."TABLE"\`
|
|
1568
|
+
- Case sensitivity: Unquoted identifiers are uppercase
|
|
1569
|
+
- Use \`FLATTEN\` for JSON data
|
|
1570
|
+
- Leverage warehouse-specific settings when needed`,
|
|
1571
|
+
databricks: `### Databricks Specific Patterns
|
|
1572
|
+
- Use three-part naming: \`catalog.schema.table\`
|
|
1573
|
+
- Default catalog is 'main' if not specified
|
|
1574
|
+
- Supports both SQL and Python notebooks
|
|
1575
|
+
- Use Unity Catalog for governance`,
|
|
1576
|
+
postgres: `### PostgreSQL Specific Patterns
|
|
1577
|
+
- Use schema-qualified names: \`schema.table\` or \`"schema"."table"\`
|
|
1578
|
+
- Case sensitivity: Unquoted identifiers are lowercase
|
|
1579
|
+
- Use \`::type\` for type casting
|
|
1580
|
+
- Leverage JSONB operators for JSON data`,
|
|
1581
|
+
mongodb: `### MongoDB Specific Patterns
|
|
1582
|
+
- Use proper operation names: find, insertOne, updateMany, etc.
|
|
1583
|
+
- Structure queries as JSON objects
|
|
1584
|
+
- Use aggregation pipelines for complex queries
|
|
1585
|
+
- Remember to specify the collection name`,
|
|
1586
|
+
};
|
|
1587
|
+
return specialDocs[pluginId] || "";
|
|
1588
|
+
}
|
|
1589
|
+
/**
|
|
1590
|
+
* Build documentation for specific integrations including TypeScript types
|
|
1591
|
+
*/
|
|
1592
|
+
function buildIntegrationDocumentation(integrationIds, services) {
|
|
1593
|
+
const sections = [];
|
|
1594
|
+
const processedPluginIds = new Set();
|
|
1595
|
+
for (const integrationId of integrationIds) {
|
|
1596
|
+
// Get integration header from store
|
|
1597
|
+
const header = services.integrationStore.getHeader(integrationId);
|
|
1598
|
+
if (!header) {
|
|
1599
|
+
continue;
|
|
1600
|
+
}
|
|
1601
|
+
const plugin = header.plugin;
|
|
1602
|
+
// Avoid duplicating docs for same plugin type
|
|
1603
|
+
if (processedPluginIds.has(plugin.id)) {
|
|
1604
|
+
continue;
|
|
1605
|
+
}
|
|
1606
|
+
processedPluginIds.add(plugin.id);
|
|
1607
|
+
// Get TypeScript type definition
|
|
1608
|
+
const typeDef = getIntegrationTypeDefinition(plugin);
|
|
1609
|
+
if (!typeDef) {
|
|
1610
|
+
continue;
|
|
1611
|
+
}
|
|
1612
|
+
// Build section for this integration
|
|
1613
|
+
const integrationSection = [
|
|
1614
|
+
`## ${typeDef.className} Integration`,
|
|
1615
|
+
"",
|
|
1616
|
+
`**Integration ID**: \`${integrationId}\``,
|
|
1617
|
+
`**Plugin Type**: ${plugin.id}`,
|
|
1618
|
+
`**Description**: ${typeDef.description}`,
|
|
1619
|
+
"",
|
|
1620
|
+
"### TypeScript Type Definition",
|
|
1621
|
+
"```typescript",
|
|
1622
|
+
typeDef.typeDefinition,
|
|
1623
|
+
"```",
|
|
1624
|
+
"",
|
|
1625
|
+
];
|
|
1626
|
+
// Add example if available
|
|
1627
|
+
if (typeDef.example) {
|
|
1628
|
+
integrationSection.push("### Example Usage", "```typescript", typeDef.example, "```", "");
|
|
1629
|
+
}
|
|
1630
|
+
// Add integration-specific patterns/rules
|
|
1631
|
+
const specificDocs = getIntegrationSpecificDocs(plugin.id);
|
|
1632
|
+
if (specificDocs) {
|
|
1633
|
+
integrationSection.push(specificDocs, "");
|
|
1634
|
+
}
|
|
1635
|
+
sections.push(integrationSection.join("\n"));
|
|
1636
|
+
}
|
|
1637
|
+
return sections.join("\n\n");
|
|
1638
|
+
}
|
|
1639
|
+
/**
|
|
1640
|
+
* Get relevant examples based on integration types
|
|
1641
|
+
*/
|
|
1642
|
+
function getRelevantExamples(integrationIds, services) {
|
|
1643
|
+
const tags = [];
|
|
1644
|
+
const pluginTypes = new Set();
|
|
1645
|
+
// Collect plugin types from integration IDs
|
|
1646
|
+
for (const integrationId of integrationIds) {
|
|
1647
|
+
const header = services.integrationStore.getHeader(integrationId);
|
|
1648
|
+
if (header) {
|
|
1649
|
+
pluginTypes.add(header.plugin.id);
|
|
1650
|
+
}
|
|
1651
|
+
}
|
|
1652
|
+
// Map plugin types to relevant tags
|
|
1653
|
+
if (pluginTypes.has("snowflake"))
|
|
1654
|
+
tags.push("snowflake");
|
|
1655
|
+
if (pluginTypes.has("databricks"))
|
|
1656
|
+
tags.push("databricks");
|
|
1657
|
+
if (pluginTypes.has("postgres") ||
|
|
1658
|
+
pluginTypes.has("mysql") ||
|
|
1659
|
+
pluginTypes.has("mssql")) {
|
|
1660
|
+
tags.push("sql-query");
|
|
1661
|
+
}
|
|
1662
|
+
if (pluginTypes.size > 1)
|
|
1663
|
+
tags.push("multi-integration");
|
|
1664
|
+
// If no integrations provided, default to data transformation examples
|
|
1665
|
+
if (integrationIds.length === 0) {
|
|
1666
|
+
tags.push("data-transformation", "variable-access");
|
|
1667
|
+
}
|
|
1668
|
+
// Always include some common patterns
|
|
1669
|
+
tags.push("error-handling", "variable-access");
|
|
1670
|
+
// Select and format examples
|
|
1671
|
+
const selectedExamples = selectExamplesByTags(tags, {
|
|
1672
|
+
maxExamples: 3,
|
|
1673
|
+
includeNegative: true,
|
|
1674
|
+
maxTokenBudget: 3000,
|
|
1675
|
+
});
|
|
1676
|
+
// If no examples were selected, use a fallback example
|
|
1677
|
+
if (selectedExamples.length === 0) {
|
|
1678
|
+
// Find a basic data transformation example as fallback
|
|
1679
|
+
const fallbackExample = POSITIVE_EXAMPLES.find((ex) => ex.metadata.tags.includes("data-transformation") &&
|
|
1680
|
+
ex.metadata.tags.includes("variable-access")) || POSITIVE_EXAMPLES[0]; // Ultimate fallback to first example
|
|
1681
|
+
if (fallbackExample) {
|
|
1682
|
+
// Create metadata object with id for formatting
|
|
1683
|
+
const fallbackMetadata = {
|
|
1684
|
+
id: fallbackExample.id,
|
|
1685
|
+
...fallbackExample.metadata,
|
|
1686
|
+
};
|
|
1687
|
+
const formattedFallback = formatSelectedExamples([fallbackMetadata]);
|
|
1688
|
+
return `## Relevant Examples
|
|
1689
|
+
|
|
1690
|
+
${formattedFallback}`;
|
|
1691
|
+
}
|
|
1692
|
+
}
|
|
1693
|
+
const formattedExamples = formatSelectedExamples(selectedExamples);
|
|
1694
|
+
return `## Relevant Examples
|
|
1695
|
+
|
|
1696
|
+
${formattedExamples}`;
|
|
1697
|
+
}
|
|
1698
|
+
export const getApiDocsToolFactory = createToolFactory("getApiDocs", (_clark, services) => ({
|
|
1699
|
+
category: ToolCategory.API,
|
|
1700
|
+
readOnly: true,
|
|
1701
|
+
description: `
|
|
1702
|
+
Retrieve comprehensive API development documentation with TypeScript type definitions and examples.
|
|
1703
|
+
|
|
1704
|
+
This tool provides:
|
|
1705
|
+
- Core API development rules and best practices
|
|
1706
|
+
- Complete TypeScript type definitions for all blocks and integrations
|
|
1707
|
+
- Integration exploration workflow (grepMetadata patterns)
|
|
1708
|
+
- Block output scoping rules
|
|
1709
|
+
- Common API patterns including dynamic SQL two-block pattern
|
|
1710
|
+
- Error handling and TryCatch usage guidelines
|
|
1711
|
+
- SQL best practices (LIMIT, no auto date filtering, one query per block)
|
|
1712
|
+
- Database naming conventions (Databricks, Snowflake, PostgreSQL)
|
|
1713
|
+
- Response interface guidelines
|
|
1714
|
+
- Runtime safety and defensive coding patterns
|
|
1715
|
+
- Integration-specific patterns and syntax rules
|
|
1716
|
+
- Relevant code examples based on integration types
|
|
1717
|
+
|
|
1718
|
+
ALWAYS call this before building or modifying APIs to ensure you follow the correct patterns.
|
|
1719
|
+
`,
|
|
1720
|
+
inputSchema: z.object({
|
|
1721
|
+
integrationIds: z
|
|
1722
|
+
.array(z.string())
|
|
1723
|
+
.describe("Integration IDs to include type definitions and specific documentation for. Pass the actual integration IDs from your page context.")
|
|
1724
|
+
.optional(),
|
|
1725
|
+
sections: z
|
|
1726
|
+
.array(z.enum([
|
|
1727
|
+
"core",
|
|
1728
|
+
"types",
|
|
1729
|
+
"integration-workflow",
|
|
1730
|
+
"scoping",
|
|
1731
|
+
"patterns",
|
|
1732
|
+
"error-handling",
|
|
1733
|
+
"sql-best-practices",
|
|
1734
|
+
"database-naming",
|
|
1735
|
+
"response-interface",
|
|
1736
|
+
"runtime-safety",
|
|
1737
|
+
"error-recovery",
|
|
1738
|
+
"loop-control",
|
|
1739
|
+
"api-structure",
|
|
1740
|
+
"critical-mistakes",
|
|
1741
|
+
"checklist",
|
|
1742
|
+
"built-in-blocks",
|
|
1743
|
+
"examples",
|
|
1744
|
+
]))
|
|
1745
|
+
.optional()
|
|
1746
|
+
.describe("Specific sections to include. If not specified, all sections are included."),
|
|
1747
|
+
verbosity: z
|
|
1748
|
+
.enum(["minimal", "standard", "comprehensive"])
|
|
1749
|
+
.optional()
|
|
1750
|
+
.describe("Level of detail to include. Defaults to comprehensive."),
|
|
1751
|
+
}),
|
|
1752
|
+
execute: async ({ integrationIds = [], sections, verbosity = "comprehensive", }) => {
|
|
1753
|
+
const documentationSections = {
|
|
1754
|
+
core: CORE_DOCUMENTATION,
|
|
1755
|
+
types: TYPE_DEFINITIONS,
|
|
1756
|
+
"integration-workflow": INTEGRATION_EXPLORATION_WORKFLOW,
|
|
1757
|
+
scoping: BLOCK_OUTPUT_SCOPING_RULES,
|
|
1758
|
+
"input-discovery": INPUT_DISCOVERY_RULES,
|
|
1759
|
+
patterns: COMMON_API_PATTERNS,
|
|
1760
|
+
"error-handling": ERROR_HANDLING_GUIDELINES,
|
|
1761
|
+
"sql-best-practices": SQL_BEST_PRACTICES,
|
|
1762
|
+
"database-naming": DATABASE_NAMING_CONVENTIONS,
|
|
1763
|
+
"response-interface": RESPONSE_INTERFACE_GUIDELINES,
|
|
1764
|
+
"runtime-safety": RUNTIME_SAFETY,
|
|
1765
|
+
"error-recovery": ERROR_RECOVERY_STRATEGIES,
|
|
1766
|
+
"loop-control": LOOP_CONTROL,
|
|
1767
|
+
"api-structure": API_STRUCTURE,
|
|
1768
|
+
"critical-mistakes": CRITICAL_MISTAKES,
|
|
1769
|
+
checklist: API_CHECKLIST,
|
|
1770
|
+
"built-in-blocks": getBuiltInBlockDocumentation(),
|
|
1771
|
+
};
|
|
1772
|
+
// Determine which sections to include
|
|
1773
|
+
let sectionsToInclude = [];
|
|
1774
|
+
if (sections && sections.length > 0) {
|
|
1775
|
+
// Use only specified sections
|
|
1776
|
+
sectionsToInclude = sections;
|
|
1777
|
+
}
|
|
1778
|
+
else {
|
|
1779
|
+
// Include sections based on verbosity
|
|
1780
|
+
switch (verbosity) {
|
|
1781
|
+
case "minimal":
|
|
1782
|
+
sectionsToInclude = ["core", "critical-mistakes", "checklist"];
|
|
1783
|
+
break;
|
|
1784
|
+
case "standard":
|
|
1785
|
+
sectionsToInclude = [
|
|
1786
|
+
"core",
|
|
1787
|
+
"integration-workflow",
|
|
1788
|
+
"scoping",
|
|
1789
|
+
"input-discovery",
|
|
1790
|
+
"patterns",
|
|
1791
|
+
"error-handling",
|
|
1792
|
+
"sql-best-practices",
|
|
1793
|
+
"database-naming",
|
|
1794
|
+
"critical-mistakes",
|
|
1795
|
+
"checklist",
|
|
1796
|
+
];
|
|
1797
|
+
break;
|
|
1798
|
+
case "comprehensive":
|
|
1799
|
+
default:
|
|
1800
|
+
sectionsToInclude = Object.keys(documentationSections);
|
|
1801
|
+
break;
|
|
1802
|
+
}
|
|
1803
|
+
}
|
|
1804
|
+
// Build documentation sections
|
|
1805
|
+
const outputSections = [];
|
|
1806
|
+
// Add requested sections, but handle built-in-blocks specially
|
|
1807
|
+
for (const section of sectionsToInclude) {
|
|
1808
|
+
// Skip built-in-blocks if integrations are provided, unless explicitly requested
|
|
1809
|
+
if (section === "built-in-blocks" &&
|
|
1810
|
+
integrationIds.length > 0 &&
|
|
1811
|
+
(!sections || !sections.includes("built-in-blocks"))) {
|
|
1812
|
+
continue;
|
|
1813
|
+
}
|
|
1814
|
+
if (documentationSections[section]) {
|
|
1815
|
+
outputSections.push(documentationSections[section]);
|
|
1816
|
+
}
|
|
1817
|
+
}
|
|
1818
|
+
// Add integration-specific documentation if integrationIds provided
|
|
1819
|
+
if (integrationIds.length > 0) {
|
|
1820
|
+
const integrationDocs = buildIntegrationDocumentation(integrationIds, services);
|
|
1821
|
+
if (integrationDocs) {
|
|
1822
|
+
outputSections.push(integrationDocs);
|
|
1823
|
+
}
|
|
1824
|
+
}
|
|
1825
|
+
// Always add relevant examples if requested or in comprehensive mode
|
|
1826
|
+
if (sectionsToInclude.includes("examples") ||
|
|
1827
|
+
verbosity === "comprehensive") {
|
|
1828
|
+
const examples = getRelevantExamples(integrationIds, services);
|
|
1829
|
+
if (examples) {
|
|
1830
|
+
outputSections.push(examples);
|
|
1831
|
+
}
|
|
1832
|
+
}
|
|
1833
|
+
return {
|
|
1834
|
+
documentation: outputSections.filter(Boolean).join("\n\n---\n\n"),
|
|
1835
|
+
integrationCount: integrationIds.length,
|
|
1836
|
+
sectionsIncluded: sectionsToInclude,
|
|
1837
|
+
verbosity,
|
|
1838
|
+
};
|
|
1839
|
+
},
|
|
1840
|
+
}));
|
|
1841
|
+
//# sourceMappingURL=get-api-docs.js.map
|