@hailer/mcp 0.0.1
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/.claude/commands/tool-builder.md +37 -0
- package/.claude/commands/ws-pull.md +44 -0
- package/.claude/settings.json +8 -0
- package/.claude/settings.local.json +49 -0
- package/.claude/skills/activity-api/SKILL.md +96 -0
- package/.claude/skills/activity-api/references/activity-endpoints.md +845 -0
- package/.claude/skills/add-app-member-skill/SKILL.md +977 -0
- package/.claude/skills/agent-building/SKILL.md +243 -0
- package/.claude/skills/agent-building/references/architecture-patterns.md +446 -0
- package/.claude/skills/agent-building/references/code-examples.md +587 -0
- package/.claude/skills/agent-building/references/implementation-guide.md +619 -0
- package/.claude/skills/app-api/SKILL.md +219 -0
- package/.claude/skills/app-api/references/app-endpoints.md +759 -0
- package/.claude/skills/building-hailer-apps-skill/SKILL.md +548 -0
- package/.claude/skills/create-app-skill/SKILL.md +1101 -0
- package/.claude/skills/create-insight-skill/SKILL.md +1317 -0
- package/.claude/skills/get-insight-data-skill/SKILL.md +1053 -0
- package/.claude/skills/hailer-api/SKILL.md +283 -0
- package/.claude/skills/hailer-api/references/activities.md +620 -0
- package/.claude/skills/hailer-api/references/authentication.md +216 -0
- package/.claude/skills/hailer-api/references/datasets.md +437 -0
- package/.claude/skills/hailer-api/references/files.md +301 -0
- package/.claude/skills/hailer-api/references/insights.md +469 -0
- package/.claude/skills/hailer-api/references/workflows.md +720 -0
- package/.claude/skills/hailer-api/references/workspaces-users.md +445 -0
- package/.claude/skills/insight-api/SKILL.md +185 -0
- package/.claude/skills/insight-api/references/insight-endpoints.md +514 -0
- package/.claude/skills/install-workflow-skill/SKILL.md +1056 -0
- package/.claude/skills/list-apps-skill/SKILL.md +1010 -0
- package/.claude/skills/list-workflows-minimal-skill/SKILL.md +992 -0
- package/.claude/skills/local-first-skill/SKILL.md +570 -0
- package/.claude/skills/mcp-tools/SKILL.md +419 -0
- package/.claude/skills/mcp-tools/references/api-endpoints.md +499 -0
- package/.claude/skills/mcp-tools/references/data-structures.md +554 -0
- package/.claude/skills/mcp-tools/references/implementation-patterns.md +717 -0
- package/.claude/skills/preview-insight-skill/SKILL.md +1290 -0
- package/.claude/skills/publish-hailer-app-skill/SKILL.md +453 -0
- package/.claude/skills/remove-app-member-skill/SKILL.md +671 -0
- package/.claude/skills/remove-app-skill/SKILL.md +985 -0
- package/.claude/skills/remove-insight-skill/SKILL.md +1011 -0
- package/.claude/skills/remove-workflow-skill/SKILL.md +920 -0
- package/.claude/skills/scaffold-hailer-app-skill/SKILL.md +1034 -0
- package/.claude/skills/skill-testing/README.md +137 -0
- package/.claude/skills/skill-testing/SKILL.md +348 -0
- package/.claude/skills/skill-testing/references/test-patterns.md +705 -0
- package/.claude/skills/skill-testing/references/testing-guide.md +603 -0
- package/.claude/skills/skill-testing/references/validation-checklist.md +537 -0
- package/.claude/skills/tool-builder/SKILL.md +328 -0
- package/.claude/skills/update-app-skill/SKILL.md +970 -0
- package/.claude/skills/update-workflow-field-skill/SKILL.md +1098 -0
- package/.env.example +81 -0
- package/.mcp.json +13 -0
- package/README.md +297 -0
- package/dist/app.d.ts +4 -0
- package/dist/app.js +74 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.js +5 -0
- package/dist/client/adaptive-documentation-bot.d.ts +108 -0
- package/dist/client/adaptive-documentation-bot.js +475 -0
- package/dist/client/adaptive-documentation-types.d.ts +66 -0
- package/dist/client/adaptive-documentation-types.js +9 -0
- package/dist/client/agent-activity-bot.d.ts +51 -0
- package/dist/client/agent-activity-bot.js +166 -0
- package/dist/client/agent-tracker.d.ts +499 -0
- package/dist/client/agent-tracker.js +659 -0
- package/dist/client/description-updater.d.ts +56 -0
- package/dist/client/description-updater.js +259 -0
- package/dist/client/log-parser.d.ts +72 -0
- package/dist/client/log-parser.js +387 -0
- package/dist/client/mcp-client.d.ts +50 -0
- package/dist/client/mcp-client.js +532 -0
- package/dist/client/message-processor.d.ts +35 -0
- package/dist/client/message-processor.js +352 -0
- package/dist/client/multi-bot-manager.d.ts +24 -0
- package/dist/client/multi-bot-manager.js +74 -0
- package/dist/client/providers/anthropic-provider.d.ts +19 -0
- package/dist/client/providers/anthropic-provider.js +631 -0
- package/dist/client/providers/llm-provider.d.ts +47 -0
- package/dist/client/providers/llm-provider.js +367 -0
- package/dist/client/providers/openai-provider.d.ts +23 -0
- package/dist/client/providers/openai-provider.js +621 -0
- package/dist/client/simple-llm-caller.d.ts +19 -0
- package/dist/client/simple-llm-caller.js +100 -0
- package/dist/client/skill-generator.d.ts +81 -0
- package/dist/client/skill-generator.js +386 -0
- package/dist/client/test-adaptive-bot.d.ts +9 -0
- package/dist/client/test-adaptive-bot.js +82 -0
- package/dist/client/token-pricing.d.ts +38 -0
- package/dist/client/token-pricing.js +127 -0
- package/dist/client/token-tracker.d.ts +232 -0
- package/dist/client/token-tracker.js +457 -0
- package/dist/client/token-usage-bot.d.ts +53 -0
- package/dist/client/token-usage-bot.js +153 -0
- package/dist/client/tool-executor.d.ts +69 -0
- package/dist/client/tool-executor.js +159 -0
- package/dist/client/tool-schema-loader.d.ts +60 -0
- package/dist/client/tool-schema-loader.js +178 -0
- package/dist/client/types.d.ts +69 -0
- package/dist/client/types.js +7 -0
- package/dist/config.d.ts +162 -0
- package/dist/config.js +296 -0
- package/dist/core.d.ts +26 -0
- package/dist/core.js +147 -0
- package/dist/lib/context-manager.d.ts +111 -0
- package/dist/lib/context-manager.js +431 -0
- package/dist/lib/logger.d.ts +74 -0
- package/dist/lib/logger.js +277 -0
- package/dist/lib/materialize.d.ts +3 -0
- package/dist/lib/materialize.js +101 -0
- package/dist/lib/normalizedName.d.ts +7 -0
- package/dist/lib/normalizedName.js +48 -0
- package/dist/lib/prompt-length-manager.d.ts +81 -0
- package/dist/lib/prompt-length-manager.js +457 -0
- package/dist/lib/terminal-prompt.d.ts +9 -0
- package/dist/lib/terminal-prompt.js +108 -0
- package/dist/mcp/UserContextCache.d.ts +56 -0
- package/dist/mcp/UserContextCache.js +163 -0
- package/dist/mcp/auth.d.ts +2 -0
- package/dist/mcp/auth.js +29 -0
- package/dist/mcp/hailer-clients.d.ts +42 -0
- package/dist/mcp/hailer-clients.js +246 -0
- package/dist/mcp/signal-handler.d.ts +45 -0
- package/dist/mcp/signal-handler.js +317 -0
- package/dist/mcp/tool-registry.d.ts +100 -0
- package/dist/mcp/tool-registry.js +306 -0
- package/dist/mcp/tools/activity.d.ts +15 -0
- package/dist/mcp/tools/activity.js +955 -0
- package/dist/mcp/tools/app.d.ts +20 -0
- package/dist/mcp/tools/app.js +1488 -0
- package/dist/mcp/tools/discussion.d.ts +19 -0
- package/dist/mcp/tools/discussion.js +950 -0
- package/dist/mcp/tools/file.d.ts +15 -0
- package/dist/mcp/tools/file.js +119 -0
- package/dist/mcp/tools/insight.d.ts +17 -0
- package/dist/mcp/tools/insight.js +806 -0
- package/dist/mcp/tools/skill.d.ts +10 -0
- package/dist/mcp/tools/skill.js +279 -0
- package/dist/mcp/tools/user.d.ts +10 -0
- package/dist/mcp/tools/user.js +108 -0
- package/dist/mcp/tools/workflow-template.d.ts +19 -0
- package/dist/mcp/tools/workflow-template.js +822 -0
- package/dist/mcp/tools/workflow.d.ts +18 -0
- package/dist/mcp/tools/workflow.js +1362 -0
- package/dist/mcp/utils/api-errors.d.ts +45 -0
- package/dist/mcp/utils/api-errors.js +160 -0
- package/dist/mcp/utils/data-transformers.d.ts +102 -0
- package/dist/mcp/utils/data-transformers.js +194 -0
- package/dist/mcp/utils/file-upload.d.ts +33 -0
- package/dist/mcp/utils/file-upload.js +148 -0
- package/dist/mcp/utils/hailer-api-client.d.ts +120 -0
- package/dist/mcp/utils/hailer-api-client.js +323 -0
- package/dist/mcp/utils/index.d.ts +13 -0
- package/dist/mcp/utils/index.js +39 -0
- package/dist/mcp/utils/logger.d.ts +42 -0
- package/dist/mcp/utils/logger.js +103 -0
- package/dist/mcp/utils/types.d.ts +286 -0
- package/dist/mcp/utils/types.js +7 -0
- package/dist/mcp/workspace-cache.d.ts +42 -0
- package/dist/mcp/workspace-cache.js +97 -0
- package/dist/mcp-server.d.ts +42 -0
- package/dist/mcp-server.js +280 -0
- package/package.json +56 -0
- package/tsconfig.json +23 -0
|
@@ -0,0 +1,1290 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Preview Hailer Insights
|
|
3
|
+
description: Complete guide for testing SQL queries before saving insights - use when debugging queries or designing reports
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Preview Hailer Insights - Complete Guide
|
|
7
|
+
|
|
8
|
+
Complete reference for testing SQL queries on Hailer workflow data using the `preview_insight` MCP tool.
|
|
9
|
+
|
|
10
|
+
## Table of Contents
|
|
11
|
+
1. [Quick Reference](#quick-reference)
|
|
12
|
+
2. [Overview](#overview)
|
|
13
|
+
3. [Core Concepts](#core-concepts)
|
|
14
|
+
4. [Basic Usage](#basic-usage)
|
|
15
|
+
5. [Development Workflow](#development-workflow)
|
|
16
|
+
6. [Testing Strategies](#testing-strategies)
|
|
17
|
+
7. [Debugging Queries](#debugging-queries)
|
|
18
|
+
8. [Common Scenarios](#common-scenarios)
|
|
19
|
+
9. [Performance Considerations](#performance-considerations)
|
|
20
|
+
10. [Best Practices](#best-practices)
|
|
21
|
+
11. [Troubleshooting](#troubleshooting)
|
|
22
|
+
|
|
23
|
+
## Quick Reference
|
|
24
|
+
|
|
25
|
+
**Test Simple Query:**
|
|
26
|
+
|
|
27
|
+
```javascript
|
|
28
|
+
preview_insight({
|
|
29
|
+
sources: [{
|
|
30
|
+
name: 'tasks',
|
|
31
|
+
workflowId: 'tasks-workflow-id',
|
|
32
|
+
fields: [
|
|
33
|
+
{ name: 'title', meta: 'name' },
|
|
34
|
+
{ name: 'dueDate', fieldId: 'due-date-field-id' }
|
|
35
|
+
]
|
|
36
|
+
}],
|
|
37
|
+
query: 'SELECT title, dueDate FROM tasks WHERE dueDate > "2024-01-01"'
|
|
38
|
+
})
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
**Test JOIN Query:**
|
|
42
|
+
|
|
43
|
+
```javascript
|
|
44
|
+
preview_insight({
|
|
45
|
+
sources: [
|
|
46
|
+
{
|
|
47
|
+
name: 'tasks',
|
|
48
|
+
workflowId: 'tasks-workflow-id',
|
|
49
|
+
fields: [
|
|
50
|
+
{ name: 'taskName', meta: 'name' },
|
|
51
|
+
{ name: 'projectLink', fieldId: 'project-link-field-id' }
|
|
52
|
+
]
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
name: 'projects',
|
|
56
|
+
workflowId: 'projects-workflow-id',
|
|
57
|
+
fields: [
|
|
58
|
+
{ name: 'id', meta: '_id' },
|
|
59
|
+
{ name: 'projectName', meta: 'name' }
|
|
60
|
+
]
|
|
61
|
+
}
|
|
62
|
+
],
|
|
63
|
+
query: `
|
|
64
|
+
SELECT tasks.taskName, projects.projectName
|
|
65
|
+
FROM tasks
|
|
66
|
+
LEFT JOIN projects ON tasks.projectLink = projects.id
|
|
67
|
+
`
|
|
68
|
+
})
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
**Preview Existing Insight Changes:**
|
|
72
|
+
|
|
73
|
+
```javascript
|
|
74
|
+
preview_insight({
|
|
75
|
+
insightId: 'existing-insight-id', // Preview changes to existing insight
|
|
76
|
+
sources: [...], // New sources
|
|
77
|
+
query: 'SELECT ...' // New query
|
|
78
|
+
})
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
**Key Features:**
|
|
82
|
+
- Tests SQL queries without creating insights
|
|
83
|
+
- Shows sample results (~20 activities)
|
|
84
|
+
- Fast iteration for query development
|
|
85
|
+
- Catches syntax errors immediately
|
|
86
|
+
- Safe testing - doesn't save anything
|
|
87
|
+
|
|
88
|
+
## Overview
|
|
89
|
+
|
|
90
|
+
**What is Preview?**
|
|
91
|
+
|
|
92
|
+
Preview lets you test SQL queries on a small sample of your workflow data before creating or updating an insight. It's the essential tool for insight development and debugging.
|
|
93
|
+
|
|
94
|
+
**Think of it as:**
|
|
95
|
+
- SQL query validation
|
|
96
|
+
- Dry run before committing
|
|
97
|
+
- Interactive query builder
|
|
98
|
+
- Debug console for insights
|
|
99
|
+
|
|
100
|
+
**Key Differences from create_insight:**
|
|
101
|
+
|
|
102
|
+
| Feature | preview_insight | create_insight |
|
|
103
|
+
|---------|----------------|----------------|
|
|
104
|
+
| Saves insight | โ No | โ
Yes |
|
|
105
|
+
| Data returned | ~20 activities | Not directly |
|
|
106
|
+
| Use case | Testing/debugging | Production use |
|
|
107
|
+
| Speed | Very fast | Slower (saves) |
|
|
108
|
+
| Iterations | Unlimited | Should minimize |
|
|
109
|
+
|
|
110
|
+
**When to Use:**
|
|
111
|
+
- Before creating new insights
|
|
112
|
+
- When debugging SQL errors
|
|
113
|
+
- Testing field mappings
|
|
114
|
+
- Verifying JOIN conditions
|
|
115
|
+
- Checking WHERE clause logic
|
|
116
|
+
- Validating aggregations
|
|
117
|
+
- Iterating on query design
|
|
118
|
+
|
|
119
|
+
**When NOT to Use:**
|
|
120
|
+
- Getting full dataset (use get_insight_data)
|
|
121
|
+
- Running production reports (create insight first)
|
|
122
|
+
- When query already works (just create it)
|
|
123
|
+
|
|
124
|
+
## Core Concepts
|
|
125
|
+
|
|
126
|
+
### Preview vs Create Workflow
|
|
127
|
+
|
|
128
|
+
**Recommended Flow:**
|
|
129
|
+
|
|
130
|
+
```
|
|
131
|
+
1. Design query structure
|
|
132
|
+
โ
|
|
133
|
+
2. Preview with minimal data
|
|
134
|
+
โ
|
|
135
|
+
3. Fix errors, iterate
|
|
136
|
+
โ
|
|
137
|
+
4. Preview until successful
|
|
138
|
+
โ
|
|
139
|
+
5. Create insight
|
|
140
|
+
โ
|
|
141
|
+
6. Get full data with get_insight_data
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
**Anti-Pattern (Don't Do This):**
|
|
145
|
+
|
|
146
|
+
```
|
|
147
|
+
1. Create insight immediately
|
|
148
|
+
โ
|
|
149
|
+
2. Get error
|
|
150
|
+
โ
|
|
151
|
+
3. Debug by trial and error
|
|
152
|
+
โ
|
|
153
|
+
4. Remove and recreate multiple times
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
### Sample Data Limitation
|
|
157
|
+
|
|
158
|
+
**Important:** Preview returns only ~20 activities per source.
|
|
159
|
+
|
|
160
|
+
**What this means:**
|
|
161
|
+
- Quick feedback on query structure
|
|
162
|
+
- May not show all edge cases
|
|
163
|
+
- Aggregations may not be representative
|
|
164
|
+
- JOINs might miss some relationships
|
|
165
|
+
|
|
166
|
+
**Good for:**
|
|
167
|
+
- SQL syntax validation
|
|
168
|
+
- Field mapping verification
|
|
169
|
+
- JOIN logic testing
|
|
170
|
+
- Column name checking
|
|
171
|
+
|
|
172
|
+
**Not good for:**
|
|
173
|
+
- Accurate COUNT results
|
|
174
|
+
- Complete data analysis
|
|
175
|
+
- Finding rare edge cases
|
|
176
|
+
- Production reporting
|
|
177
|
+
|
|
178
|
+
### Security Note
|
|
179
|
+
|
|
180
|
+
**Regular Users:**
|
|
181
|
+
- Can only preview with sources from existing insights they have access to
|
|
182
|
+
- Cannot test arbitrary workflow combinations
|
|
183
|
+
- Security restriction to prevent unauthorized data access
|
|
184
|
+
|
|
185
|
+
**Workspace Admins:**
|
|
186
|
+
- Can preview with any workflow sources
|
|
187
|
+
- Full testing capabilities
|
|
188
|
+
- No source restrictions
|
|
189
|
+
|
|
190
|
+
## Basic Usage
|
|
191
|
+
|
|
192
|
+
### Example 1: Test Simple Query
|
|
193
|
+
|
|
194
|
+
```javascript
|
|
195
|
+
// Step 1: Define sources and query
|
|
196
|
+
preview_insight({
|
|
197
|
+
sources: [{
|
|
198
|
+
name: 'tasks',
|
|
199
|
+
workflowId: '68446dc05b30685f67c6fcd4',
|
|
200
|
+
fields: [
|
|
201
|
+
{ name: 'title', meta: 'name' },
|
|
202
|
+
{ name: 'priority', fieldId: 'priority-field-id' }
|
|
203
|
+
]
|
|
204
|
+
}],
|
|
205
|
+
query: 'SELECT title, priority FROM tasks'
|
|
206
|
+
})
|
|
207
|
+
|
|
208
|
+
// Response:
|
|
209
|
+
// โ
Insight Preview Successful
|
|
210
|
+
//
|
|
211
|
+
// Query Results (showing up to 20 activities):
|
|
212
|
+
// | title | priority |
|
|
213
|
+
// |-------|----------|
|
|
214
|
+
// | Task 1 | High |
|
|
215
|
+
// | Task 2 | Medium |
|
|
216
|
+
// ...
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
### Example 2: Test with Filter
|
|
220
|
+
|
|
221
|
+
```javascript
|
|
222
|
+
preview_insight({
|
|
223
|
+
sources: [{
|
|
224
|
+
name: 'tasks',
|
|
225
|
+
workflowId: 'tasks-workflow-id',
|
|
226
|
+
fields: [
|
|
227
|
+
{ name: 'title', meta: 'name' },
|
|
228
|
+
{ name: 'priority', fieldId: 'priority-field-id' },
|
|
229
|
+
{ name: 'status', meta: 'phase' }
|
|
230
|
+
]
|
|
231
|
+
}],
|
|
232
|
+
query: `
|
|
233
|
+
SELECT title, priority, status
|
|
234
|
+
FROM tasks
|
|
235
|
+
WHERE priority = 'High' AND status != 'Done'
|
|
236
|
+
`
|
|
237
|
+
})
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
### Example 3: Test JOIN
|
|
241
|
+
|
|
242
|
+
```javascript
|
|
243
|
+
preview_insight({
|
|
244
|
+
sources: [
|
|
245
|
+
{
|
|
246
|
+
name: 'tasks',
|
|
247
|
+
workflowId: 'tasks-workflow-id',
|
|
248
|
+
fields: [
|
|
249
|
+
{ name: 'taskName', meta: 'name' },
|
|
250
|
+
{ name: 'projectId', fieldId: 'project-field-id' }
|
|
251
|
+
]
|
|
252
|
+
},
|
|
253
|
+
{
|
|
254
|
+
name: 'projects',
|
|
255
|
+
workflowId: 'projects-workflow-id',
|
|
256
|
+
fields: [
|
|
257
|
+
{ name: 'id', meta: '_id' },
|
|
258
|
+
{ name: 'projectName', meta: 'name' }
|
|
259
|
+
]
|
|
260
|
+
}
|
|
261
|
+
],
|
|
262
|
+
query: `
|
|
263
|
+
SELECT
|
|
264
|
+
tasks.taskName,
|
|
265
|
+
projects.projectName
|
|
266
|
+
FROM tasks
|
|
267
|
+
LEFT JOIN projects ON tasks.projectId = projects.id
|
|
268
|
+
`
|
|
269
|
+
})
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
### Example 4: Test Aggregation
|
|
273
|
+
|
|
274
|
+
```javascript
|
|
275
|
+
preview_insight({
|
|
276
|
+
sources: [{
|
|
277
|
+
name: 'tasks',
|
|
278
|
+
workflowId: 'tasks-workflow-id',
|
|
279
|
+
fields: [
|
|
280
|
+
{ name: 'priority', fieldId: 'priority-field-id' }
|
|
281
|
+
]
|
|
282
|
+
}],
|
|
283
|
+
query: `
|
|
284
|
+
SELECT priority, COUNT(*) AS count
|
|
285
|
+
FROM tasks
|
|
286
|
+
GROUP BY priority
|
|
287
|
+
ORDER BY count DESC
|
|
288
|
+
`
|
|
289
|
+
})
|
|
290
|
+
|
|
291
|
+
// Note: COUNT will only reflect ~20 sampled activities
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
## Development Workflow
|
|
295
|
+
|
|
296
|
+
### Workflow 1: Build Query Iteratively
|
|
297
|
+
|
|
298
|
+
**Start simple, add complexity gradually:**
|
|
299
|
+
|
|
300
|
+
```javascript
|
|
301
|
+
// Step 1: Start with SELECT *
|
|
302
|
+
preview_insight({
|
|
303
|
+
sources: [{
|
|
304
|
+
name: 'tasks',
|
|
305
|
+
workflowId: 'tasks-workflow-id',
|
|
306
|
+
fields: [
|
|
307
|
+
{ name: 'title', meta: 'name' }
|
|
308
|
+
]
|
|
309
|
+
}],
|
|
310
|
+
query: 'SELECT * FROM tasks'
|
|
311
|
+
})
|
|
312
|
+
// โ
Works? Continue.
|
|
313
|
+
|
|
314
|
+
// Step 2: Add specific columns
|
|
315
|
+
preview_insight({
|
|
316
|
+
sources: [{
|
|
317
|
+
name: 'tasks',
|
|
318
|
+
workflowId: 'tasks-workflow-id',
|
|
319
|
+
fields: [
|
|
320
|
+
{ name: 'title', meta: 'name' },
|
|
321
|
+
{ name: 'priority', fieldId: 'priority-field-id' }
|
|
322
|
+
]
|
|
323
|
+
}],
|
|
324
|
+
query: 'SELECT title, priority FROM tasks'
|
|
325
|
+
})
|
|
326
|
+
// โ
Works? Continue.
|
|
327
|
+
|
|
328
|
+
// Step 3: Add WHERE clause
|
|
329
|
+
preview_insight({
|
|
330
|
+
sources: [{
|
|
331
|
+
name: 'tasks',
|
|
332
|
+
workflowId: 'tasks-workflow-id',
|
|
333
|
+
fields: [
|
|
334
|
+
{ name: 'title', meta: 'name' },
|
|
335
|
+
{ name: 'priority', fieldId: 'priority-field-id' }
|
|
336
|
+
]
|
|
337
|
+
}],
|
|
338
|
+
query: 'SELECT title, priority FROM tasks WHERE priority = "High"'
|
|
339
|
+
})
|
|
340
|
+
// โ
Works? Continue.
|
|
341
|
+
|
|
342
|
+
// Step 4: Add ORDER BY
|
|
343
|
+
preview_insight({
|
|
344
|
+
sources: [{
|
|
345
|
+
name: 'tasks',
|
|
346
|
+
workflowId: 'tasks-workflow-id',
|
|
347
|
+
fields: [
|
|
348
|
+
{ name: 'title', meta: 'name' },
|
|
349
|
+
{ name: 'priority', fieldId: 'priority-field-id' },
|
|
350
|
+
{ name: 'created', meta: 'created' }
|
|
351
|
+
]
|
|
352
|
+
}],
|
|
353
|
+
query: `
|
|
354
|
+
SELECT title, priority, created
|
|
355
|
+
FROM tasks
|
|
356
|
+
WHERE priority = 'High'
|
|
357
|
+
ORDER BY created DESC
|
|
358
|
+
`
|
|
359
|
+
})
|
|
360
|
+
// โ
Works? Create insight!
|
|
361
|
+
```
|
|
362
|
+
|
|
363
|
+
### Workflow 2: Test JOIN Relationships
|
|
364
|
+
|
|
365
|
+
```javascript
|
|
366
|
+
// Step 1: Verify both sources independently
|
|
367
|
+
preview_insight({
|
|
368
|
+
sources: [{
|
|
369
|
+
name: 'tasks',
|
|
370
|
+
workflowId: 'tasks-workflow-id',
|
|
371
|
+
fields: [
|
|
372
|
+
{ name: 'id', meta: '_id' },
|
|
373
|
+
{ name: 'title', meta: 'name' }
|
|
374
|
+
]
|
|
375
|
+
}],
|
|
376
|
+
query: 'SELECT * FROM tasks LIMIT 5'
|
|
377
|
+
})
|
|
378
|
+
|
|
379
|
+
preview_insight({
|
|
380
|
+
sources: [{
|
|
381
|
+
name: 'projects',
|
|
382
|
+
workflowId: 'projects-workflow-id',
|
|
383
|
+
fields: [
|
|
384
|
+
{ name: 'id', meta: '_id' },
|
|
385
|
+
{ name: 'name', meta: 'name' }
|
|
386
|
+
]
|
|
387
|
+
}],
|
|
388
|
+
query: 'SELECT * FROM projects LIMIT 5'
|
|
389
|
+
})
|
|
390
|
+
|
|
391
|
+
// Step 2: Test JOIN without filters
|
|
392
|
+
preview_insight({
|
|
393
|
+
sources: [
|
|
394
|
+
{
|
|
395
|
+
name: 'tasks',
|
|
396
|
+
workflowId: 'tasks-workflow-id',
|
|
397
|
+
fields: [
|
|
398
|
+
{ name: 'title', meta: 'name' },
|
|
399
|
+
{ name: 'projectId', fieldId: 'project-field-id' }
|
|
400
|
+
]
|
|
401
|
+
},
|
|
402
|
+
{
|
|
403
|
+
name: 'projects',
|
|
404
|
+
workflowId: 'projects-workflow-id',
|
|
405
|
+
fields: [
|
|
406
|
+
{ name: 'id', meta: '_id' },
|
|
407
|
+
{ name: 'projectName', meta: 'name' }
|
|
408
|
+
]
|
|
409
|
+
}
|
|
410
|
+
],
|
|
411
|
+
query: `
|
|
412
|
+
SELECT tasks.title, projects.projectName
|
|
413
|
+
FROM tasks
|
|
414
|
+
LEFT JOIN projects ON tasks.projectId = projects.id
|
|
415
|
+
`
|
|
416
|
+
})
|
|
417
|
+
|
|
418
|
+
// Step 3: Add filters and sorting
|
|
419
|
+
preview_insight({
|
|
420
|
+
sources: [...],
|
|
421
|
+
query: `
|
|
422
|
+
SELECT tasks.title, projects.projectName
|
|
423
|
+
FROM tasks
|
|
424
|
+
LEFT JOIN projects ON tasks.projectId = projects.id
|
|
425
|
+
WHERE projects.projectName IS NOT NULL
|
|
426
|
+
ORDER BY projects.projectName, tasks.title
|
|
427
|
+
`
|
|
428
|
+
})
|
|
429
|
+
```
|
|
430
|
+
|
|
431
|
+
### Workflow 3: Fix Field Mapping Errors
|
|
432
|
+
|
|
433
|
+
```javascript
|
|
434
|
+
// Step 1: Preview with suspected incorrect field
|
|
435
|
+
preview_insight({
|
|
436
|
+
sources: [{
|
|
437
|
+
name: 'tasks',
|
|
438
|
+
workflowId: 'tasks-workflow-id',
|
|
439
|
+
fields: [
|
|
440
|
+
{ name: 'priority', fieldId: 'wrong-field-id' } // Wrong ID
|
|
441
|
+
]
|
|
442
|
+
}],
|
|
443
|
+
query: 'SELECT priority FROM tasks'
|
|
444
|
+
})
|
|
445
|
+
// โ Returns null or unexpected values
|
|
446
|
+
|
|
447
|
+
// Step 2: Get correct field ID
|
|
448
|
+
const schema = get_workflow_schema({
|
|
449
|
+
workflowId: 'tasks-workflow-id'
|
|
450
|
+
})
|
|
451
|
+
const priorityField = schema.fields.find(f => f.key === 'priority')
|
|
452
|
+
console.log('Correct field ID:', priorityField._id)
|
|
453
|
+
|
|
454
|
+
// Step 3: Retry with correct field ID
|
|
455
|
+
preview_insight({
|
|
456
|
+
sources: [{
|
|
457
|
+
name: 'tasks',
|
|
458
|
+
workflowId: 'tasks-workflow-id',
|
|
459
|
+
fields: [
|
|
460
|
+
{ name: 'priority', fieldId: priorityField._id } // Correct ID
|
|
461
|
+
]
|
|
462
|
+
}],
|
|
463
|
+
query: 'SELECT priority FROM tasks'
|
|
464
|
+
})
|
|
465
|
+
// โ
Works!
|
|
466
|
+
```
|
|
467
|
+
|
|
468
|
+
## Testing Strategies
|
|
469
|
+
|
|
470
|
+
### Strategy 1: Column-by-Column Verification
|
|
471
|
+
|
|
472
|
+
**Test each field individually:**
|
|
473
|
+
|
|
474
|
+
```javascript
|
|
475
|
+
// Test field 1
|
|
476
|
+
preview_insight({
|
|
477
|
+
sources: [{
|
|
478
|
+
name: 'tasks',
|
|
479
|
+
workflowId: 'tasks-workflow-id',
|
|
480
|
+
fields: [{ name: 'title', meta: 'name' }]
|
|
481
|
+
}],
|
|
482
|
+
query: 'SELECT title FROM tasks LIMIT 5'
|
|
483
|
+
})
|
|
484
|
+
|
|
485
|
+
// Test field 2
|
|
486
|
+
preview_insight({
|
|
487
|
+
sources: [{
|
|
488
|
+
name: 'tasks',
|
|
489
|
+
workflowId: 'tasks-workflow-id',
|
|
490
|
+
fields: [{ name: 'priority', fieldId: 'priority-field-id' }]
|
|
491
|
+
}],
|
|
492
|
+
query: 'SELECT priority FROM tasks LIMIT 5'
|
|
493
|
+
})
|
|
494
|
+
|
|
495
|
+
// Combine once both work
|
|
496
|
+
preview_insight({
|
|
497
|
+
sources: [{
|
|
498
|
+
name: 'tasks',
|
|
499
|
+
workflowId: 'tasks-workflow-id',
|
|
500
|
+
fields: [
|
|
501
|
+
{ name: 'title', meta: 'name' },
|
|
502
|
+
{ name: 'priority', fieldId: 'priority-field-id' }
|
|
503
|
+
]
|
|
504
|
+
}],
|
|
505
|
+
query: 'SELECT title, priority FROM tasks LIMIT 5'
|
|
506
|
+
})
|
|
507
|
+
```
|
|
508
|
+
|
|
509
|
+
### Strategy 2: WHERE Clause Testing
|
|
510
|
+
|
|
511
|
+
**Test filters incrementally:**
|
|
512
|
+
|
|
513
|
+
```javascript
|
|
514
|
+
// No filter
|
|
515
|
+
preview_insight({
|
|
516
|
+
sources: [...],
|
|
517
|
+
query: 'SELECT title, priority FROM tasks'
|
|
518
|
+
})
|
|
519
|
+
// Note: How many rows returned?
|
|
520
|
+
|
|
521
|
+
// Add first filter
|
|
522
|
+
preview_insight({
|
|
523
|
+
sources: [...],
|
|
524
|
+
query: 'SELECT title, priority FROM tasks WHERE priority = "High"'
|
|
525
|
+
})
|
|
526
|
+
// Note: Did rows decrease appropriately?
|
|
527
|
+
|
|
528
|
+
// Add second filter
|
|
529
|
+
preview_insight({
|
|
530
|
+
sources: [...],
|
|
531
|
+
query: `
|
|
532
|
+
SELECT title, priority, status
|
|
533
|
+
FROM tasks
|
|
534
|
+
WHERE priority = 'High' AND status != 'Done'
|
|
535
|
+
`
|
|
536
|
+
})
|
|
537
|
+
// Note: Further decrease makes sense?
|
|
538
|
+
```
|
|
539
|
+
|
|
540
|
+
### Strategy 3: JOIN Direction Testing
|
|
541
|
+
|
|
542
|
+
**Test different JOIN types:**
|
|
543
|
+
|
|
544
|
+
```javascript
|
|
545
|
+
// Test INNER JOIN (only matching)
|
|
546
|
+
preview_insight({
|
|
547
|
+
sources: [...],
|
|
548
|
+
query: `
|
|
549
|
+
SELECT tasks.title, projects.projectName
|
|
550
|
+
FROM tasks
|
|
551
|
+
INNER JOIN projects ON tasks.projectId = projects.id
|
|
552
|
+
`
|
|
553
|
+
})
|
|
554
|
+
// Note: Row count
|
|
555
|
+
|
|
556
|
+
// Test LEFT JOIN (all tasks)
|
|
557
|
+
preview_insight({
|
|
558
|
+
sources: [...],
|
|
559
|
+
query: `
|
|
560
|
+
SELECT tasks.title, projects.projectName
|
|
561
|
+
FROM tasks
|
|
562
|
+
LEFT JOIN projects ON tasks.projectId = projects.id
|
|
563
|
+
`
|
|
564
|
+
})
|
|
565
|
+
// Note: Should have more rows (tasks without projects included)
|
|
566
|
+
|
|
567
|
+
// Test RIGHT JOIN (all projects)
|
|
568
|
+
preview_insight({
|
|
569
|
+
sources: [...],
|
|
570
|
+
query: `
|
|
571
|
+
SELECT tasks.title, projects.projectName
|
|
572
|
+
FROM tasks
|
|
573
|
+
RIGHT JOIN projects ON tasks.projectId = projects.id
|
|
574
|
+
`
|
|
575
|
+
})
|
|
576
|
+
// Note: Different row count (projects without tasks included)
|
|
577
|
+
```
|
|
578
|
+
|
|
579
|
+
### Strategy 4: Aggregation Validation
|
|
580
|
+
|
|
581
|
+
**Check aggregation logic:**
|
|
582
|
+
|
|
583
|
+
```javascript
|
|
584
|
+
// Simple count
|
|
585
|
+
preview_insight({
|
|
586
|
+
sources: [{
|
|
587
|
+
name: 'tasks',
|
|
588
|
+
workflowId: 'tasks-workflow-id',
|
|
589
|
+
fields: [{ name: 'id', meta: '_id' }]
|
|
590
|
+
}],
|
|
591
|
+
query: 'SELECT COUNT(*) AS total FROM tasks'
|
|
592
|
+
})
|
|
593
|
+
// Note: Total (but remember, only ~20 activities sampled)
|
|
594
|
+
|
|
595
|
+
// Count by group
|
|
596
|
+
preview_insight({
|
|
597
|
+
sources: [{
|
|
598
|
+
name: 'tasks',
|
|
599
|
+
workflowId: 'tasks-workflow-id',
|
|
600
|
+
fields: [{ name: 'priority', fieldId: 'priority-field-id' }]
|
|
601
|
+
}],
|
|
602
|
+
query: `
|
|
603
|
+
SELECT priority, COUNT(*) AS count
|
|
604
|
+
FROM tasks
|
|
605
|
+
GROUP BY priority
|
|
606
|
+
`
|
|
607
|
+
})
|
|
608
|
+
// Note: Distributions (sample only)
|
|
609
|
+
|
|
610
|
+
// Verify with detail query
|
|
611
|
+
preview_insight({
|
|
612
|
+
sources: [{
|
|
613
|
+
name: 'tasks',
|
|
614
|
+
workflowId: 'tasks-workflow-id',
|
|
615
|
+
fields: [{ name: 'priority', fieldId: 'priority-field-id' }]
|
|
616
|
+
}],
|
|
617
|
+
query: 'SELECT priority FROM tasks'
|
|
618
|
+
})
|
|
619
|
+
// Note: Manually count to verify GROUP BY logic
|
|
620
|
+
```
|
|
621
|
+
|
|
622
|
+
## Debugging Queries
|
|
623
|
+
|
|
624
|
+
### Debug Pattern 1: SQL Syntax Errors
|
|
625
|
+
|
|
626
|
+
**Error:** SQL syntax error
|
|
627
|
+
|
|
628
|
+
**Debug steps:**
|
|
629
|
+
|
|
630
|
+
```javascript
|
|
631
|
+
// 1. Simplify to minimal query
|
|
632
|
+
preview_insight({
|
|
633
|
+
sources: [{
|
|
634
|
+
name: 'tasks',
|
|
635
|
+
workflowId: 'tasks-workflow-id',
|
|
636
|
+
fields: [{ name: 'title', meta: 'name' }]
|
|
637
|
+
}],
|
|
638
|
+
query: 'SELECT title FROM tasks'
|
|
639
|
+
})
|
|
640
|
+
// โ
Works? Syntax is valid.
|
|
641
|
+
|
|
642
|
+
// 2. Add back pieces one at a time
|
|
643
|
+
preview_insight({
|
|
644
|
+
sources: [...],
|
|
645
|
+
query: 'SELECT title FROM tasks WHERE priority = "High"'
|
|
646
|
+
})
|
|
647
|
+
// โ Error? Issue is in WHERE clause.
|
|
648
|
+
|
|
649
|
+
// 3. Fix WHERE clause (quotes)
|
|
650
|
+
preview_insight({
|
|
651
|
+
sources: [...],
|
|
652
|
+
query: "SELECT title FROM tasks WHERE priority = 'High'"
|
|
653
|
+
})
|
|
654
|
+
// โ
Works? Continue adding.
|
|
655
|
+
```
|
|
656
|
+
|
|
657
|
+
### Debug Pattern 2: Column Not Found
|
|
658
|
+
|
|
659
|
+
**Error:** Column name doesn't exist
|
|
660
|
+
|
|
661
|
+
**Debug steps:**
|
|
662
|
+
|
|
663
|
+
```javascript
|
|
664
|
+
// 1. List all available columns
|
|
665
|
+
preview_insight({
|
|
666
|
+
sources: [{
|
|
667
|
+
name: 'tasks',
|
|
668
|
+
workflowId: 'tasks-workflow-id',
|
|
669
|
+
fields: [
|
|
670
|
+
{ name: 'field1', meta: 'name' },
|
|
671
|
+
{ name: 'field2', fieldId: 'field-id' }
|
|
672
|
+
]
|
|
673
|
+
}],
|
|
674
|
+
query: 'SELECT * FROM tasks LIMIT 1'
|
|
675
|
+
})
|
|
676
|
+
// Note: What columns appear in result?
|
|
677
|
+
|
|
678
|
+
// 2. Use correct column name
|
|
679
|
+
preview_insight({
|
|
680
|
+
sources: [...],
|
|
681
|
+
query: 'SELECT field1, field2 FROM tasks'
|
|
682
|
+
})
|
|
683
|
+
// Must match name in field mapping
|
|
684
|
+
```
|
|
685
|
+
|
|
686
|
+
### Debug Pattern 3: JOIN Returns No Rows
|
|
687
|
+
|
|
688
|
+
**Problem:** JOIN returns empty result
|
|
689
|
+
|
|
690
|
+
**Debug steps:**
|
|
691
|
+
|
|
692
|
+
```javascript
|
|
693
|
+
// 1. Check both tables have data
|
|
694
|
+
preview_insight({
|
|
695
|
+
sources: [{
|
|
696
|
+
name: 'tasks',
|
|
697
|
+
workflowId: 'tasks-workflow-id',
|
|
698
|
+
fields: [{ name: 'id', meta: '_id' }]
|
|
699
|
+
}],
|
|
700
|
+
query: 'SELECT COUNT(*) FROM tasks'
|
|
701
|
+
})
|
|
702
|
+
|
|
703
|
+
preview_insight({
|
|
704
|
+
sources: [{
|
|
705
|
+
name: 'projects',
|
|
706
|
+
workflowId: 'projects-workflow-id',
|
|
707
|
+
fields: [{ name: 'id', meta: '_id' }]
|
|
708
|
+
}],
|
|
709
|
+
query: 'SELECT COUNT(*) FROM projects'
|
|
710
|
+
})
|
|
711
|
+
|
|
712
|
+
// 2. Check JOIN keys have values
|
|
713
|
+
preview_insight({
|
|
714
|
+
sources: [{
|
|
715
|
+
name: 'tasks',
|
|
716
|
+
workflowId: 'tasks-workflow-id',
|
|
717
|
+
fields: [
|
|
718
|
+
{ name: 'projectId', fieldId: 'project-field-id' }
|
|
719
|
+
]
|
|
720
|
+
}],
|
|
721
|
+
query: 'SELECT projectId FROM tasks WHERE projectId IS NOT NULL'
|
|
722
|
+
})
|
|
723
|
+
|
|
724
|
+
// 3. Use LEFT JOIN to see all tasks
|
|
725
|
+
preview_insight({
|
|
726
|
+
sources: [
|
|
727
|
+
{
|
|
728
|
+
name: 'tasks',
|
|
729
|
+
workflowId: 'tasks-workflow-id',
|
|
730
|
+
fields: [
|
|
731
|
+
{ name: 'title', meta: 'name' },
|
|
732
|
+
{ name: 'projectId', fieldId: 'project-field-id' }
|
|
733
|
+
]
|
|
734
|
+
},
|
|
735
|
+
{
|
|
736
|
+
name: 'projects',
|
|
737
|
+
workflowId: 'projects-workflow-id',
|
|
738
|
+
fields: [
|
|
739
|
+
{ name: 'id', meta: '_id' },
|
|
740
|
+
{ name: 'projectName', meta: 'name' }
|
|
741
|
+
]
|
|
742
|
+
}
|
|
743
|
+
],
|
|
744
|
+
query: `
|
|
745
|
+
SELECT tasks.title, tasks.projectId, projects.projectName
|
|
746
|
+
FROM tasks
|
|
747
|
+
LEFT JOIN projects ON tasks.projectId = projects.id
|
|
748
|
+
`
|
|
749
|
+
})
|
|
750
|
+
// Shows which tasks don't match projects
|
|
751
|
+
```
|
|
752
|
+
|
|
753
|
+
### Debug Pattern 4: Unexpected NULL Values
|
|
754
|
+
|
|
755
|
+
**Problem:** Fields show NULL when they shouldn't
|
|
756
|
+
|
|
757
|
+
**Debug steps:**
|
|
758
|
+
|
|
759
|
+
```javascript
|
|
760
|
+
// 1. Check field mapping
|
|
761
|
+
const schema = get_workflow_schema({
|
|
762
|
+
workflowId: 'workflow-id'
|
|
763
|
+
})
|
|
764
|
+
console.log('Available fields:', schema.fields.map(f => ({
|
|
765
|
+
id: f._id,
|
|
766
|
+
key: f.key,
|
|
767
|
+
label: f.label
|
|
768
|
+
})))
|
|
769
|
+
|
|
770
|
+
// 2. Verify field ID is correct
|
|
771
|
+
const field = schema.fields.find(f => f.key === 'priority')
|
|
772
|
+
console.log('Priority field ID:', field._id)
|
|
773
|
+
|
|
774
|
+
// 3. Test with correct field ID
|
|
775
|
+
preview_insight({
|
|
776
|
+
sources: [{
|
|
777
|
+
name: 'tasks',
|
|
778
|
+
workflowId: 'workflow-id',
|
|
779
|
+
fields: [
|
|
780
|
+
{ name: 'priority', fieldId: field._id } // Correct ID
|
|
781
|
+
]
|
|
782
|
+
}],
|
|
783
|
+
query: 'SELECT priority FROM tasks'
|
|
784
|
+
})
|
|
785
|
+
|
|
786
|
+
// 4. Check if field values actually exist
|
|
787
|
+
list_activities({
|
|
788
|
+
workflowId: 'workflow-id',
|
|
789
|
+
limit: 5,
|
|
790
|
+
returnFlat: true
|
|
791
|
+
})
|
|
792
|
+
// Verify activities have priority values
|
|
793
|
+
```
|
|
794
|
+
|
|
795
|
+
## Common Scenarios
|
|
796
|
+
|
|
797
|
+
### Scenario 1: Design New Report
|
|
798
|
+
|
|
799
|
+
```javascript
|
|
800
|
+
// Goal: Create "High Priority Overdue Tasks" report
|
|
801
|
+
|
|
802
|
+
// Step 1: Get field IDs
|
|
803
|
+
const schema = get_workflow_schema({
|
|
804
|
+
workflowId: 'tasks-workflow-id'
|
|
805
|
+
})
|
|
806
|
+
|
|
807
|
+
// Step 2: Preview basic query
|
|
808
|
+
preview_insight({
|
|
809
|
+
sources: [{
|
|
810
|
+
name: 'tasks',
|
|
811
|
+
workflowId: 'tasks-workflow-id',
|
|
812
|
+
fields: [
|
|
813
|
+
{ name: 'title', meta: 'name' },
|
|
814
|
+
{ name: 'priority', fieldId: 'priority-field-id' },
|
|
815
|
+
{ name: 'dueDate', fieldId: 'due-date-field-id' }
|
|
816
|
+
]
|
|
817
|
+
}],
|
|
818
|
+
query: `
|
|
819
|
+
SELECT title, priority, dueDate
|
|
820
|
+
FROM tasks
|
|
821
|
+
WHERE priority = 'High'
|
|
822
|
+
AND dueDate < date('now')
|
|
823
|
+
ORDER BY dueDate ASC
|
|
824
|
+
`
|
|
825
|
+
})
|
|
826
|
+
// โ
Works? Create insight.
|
|
827
|
+
|
|
828
|
+
// Step 3: Create the insight
|
|
829
|
+
create_insight({
|
|
830
|
+
name: 'High Priority Overdue Tasks',
|
|
831
|
+
sources: [...], // Same as preview
|
|
832
|
+
query: '...' // Same as preview
|
|
833
|
+
})
|
|
834
|
+
```
|
|
835
|
+
|
|
836
|
+
### Scenario 2: Modify Existing Insight
|
|
837
|
+
|
|
838
|
+
```javascript
|
|
839
|
+
// Goal: Update insight to include status field
|
|
840
|
+
|
|
841
|
+
// Step 1: Preview with new field
|
|
842
|
+
preview_insight({
|
|
843
|
+
insightId: 'existing-insight-id', // Optional: reference existing
|
|
844
|
+
sources: [{
|
|
845
|
+
name: 'tasks',
|
|
846
|
+
workflowId: 'tasks-workflow-id',
|
|
847
|
+
fields: [
|
|
848
|
+
{ name: 'title', meta: 'name' },
|
|
849
|
+
{ name: 'priority', fieldId: 'priority-field-id' },
|
|
850
|
+
{ name: 'status', meta: 'phase' } // New field
|
|
851
|
+
]
|
|
852
|
+
}],
|
|
853
|
+
query: `
|
|
854
|
+
SELECT title, priority, status
|
|
855
|
+
FROM tasks
|
|
856
|
+
WHERE priority = 'High'
|
|
857
|
+
`
|
|
858
|
+
})
|
|
859
|
+
// โ
Works? Update insight.
|
|
860
|
+
|
|
861
|
+
// Step 2: Update insight (use update_insight if available)
|
|
862
|
+
// Or remove and recreate with new query
|
|
863
|
+
```
|
|
864
|
+
|
|
865
|
+
### Scenario 3: Debug Broken Insight
|
|
866
|
+
|
|
867
|
+
```javascript
|
|
868
|
+
// Goal: Fix insight that's returning errors
|
|
869
|
+
|
|
870
|
+
// Step 1: Get insight definition
|
|
871
|
+
const insights = list_insights()
|
|
872
|
+
const broken = insights.find(i => i.name === 'Broken Report')
|
|
873
|
+
|
|
874
|
+
// Step 2: Preview with same query
|
|
875
|
+
preview_insight({
|
|
876
|
+
sources: broken.sources,
|
|
877
|
+
query: broken.query
|
|
878
|
+
})
|
|
879
|
+
// โ Error? Now you can debug interactively.
|
|
880
|
+
|
|
881
|
+
// Step 3: Simplify query to find issue
|
|
882
|
+
preview_insight({
|
|
883
|
+
sources: broken.sources,
|
|
884
|
+
query: 'SELECT * FROM tasks LIMIT 5'
|
|
885
|
+
})
|
|
886
|
+
// โ
Works? Issue is in complex query logic.
|
|
887
|
+
|
|
888
|
+
// Step 4: Add back complexity piece by piece
|
|
889
|
+
// ... debug until you find the problem
|
|
890
|
+
```
|
|
891
|
+
|
|
892
|
+
### Scenario 4: Test Performance
|
|
893
|
+
|
|
894
|
+
```javascript
|
|
895
|
+
// Goal: Ensure query performs well on sample data
|
|
896
|
+
|
|
897
|
+
// Test 1: Simple query (should be fast)
|
|
898
|
+
preview_insight({
|
|
899
|
+
sources: [{
|
|
900
|
+
name: 'tasks',
|
|
901
|
+
workflowId: 'tasks-workflow-id',
|
|
902
|
+
fields: [{ name: 'title', meta: 'name' }]
|
|
903
|
+
}],
|
|
904
|
+
query: 'SELECT title FROM tasks'
|
|
905
|
+
})
|
|
906
|
+
// Note: Response time
|
|
907
|
+
|
|
908
|
+
// Test 2: Complex query (might be slower)
|
|
909
|
+
preview_insight({
|
|
910
|
+
sources: [
|
|
911
|
+
{ name: 'tasks', ... },
|
|
912
|
+
{ name: 'projects', ... },
|
|
913
|
+
{ name: 'teams', ... }
|
|
914
|
+
],
|
|
915
|
+
query: `
|
|
916
|
+
SELECT ...
|
|
917
|
+
FROM tasks t
|
|
918
|
+
JOIN projects p ON t.projectId = p.id
|
|
919
|
+
JOIN teams tm ON p.teamId = tm.id
|
|
920
|
+
WHERE ...
|
|
921
|
+
GROUP BY ...
|
|
922
|
+
ORDER BY ...
|
|
923
|
+
`
|
|
924
|
+
})
|
|
925
|
+
// Note: Response time (if slow on sample, will be very slow on full data)
|
|
926
|
+
```
|
|
927
|
+
|
|
928
|
+
## Performance Considerations
|
|
929
|
+
|
|
930
|
+
### Preview Performance
|
|
931
|
+
|
|
932
|
+
**Preview is fast because:**
|
|
933
|
+
- Limited to ~20 activities per source
|
|
934
|
+
- No data persistence
|
|
935
|
+
- Simple validation
|
|
936
|
+
- Quick response
|
|
937
|
+
|
|
938
|
+
**Even preview can be slow if:**
|
|
939
|
+
- Many sources (complex JOINs)
|
|
940
|
+
- Complex aggregations
|
|
941
|
+
- Large result set (many columns)
|
|
942
|
+
- Server overloaded
|
|
943
|
+
|
|
944
|
+
### Optimizing Queries
|
|
945
|
+
|
|
946
|
+
**Fast queries:**
|
|
947
|
+
```sql
|
|
948
|
+
SELECT title, priority FROM tasks LIMIT 10
|
|
949
|
+
SELECT COUNT(*) FROM tasks
|
|
950
|
+
SELECT * FROM tasks WHERE status = 'Open'
|
|
951
|
+
```
|
|
952
|
+
|
|
953
|
+
**Slower queries:**
|
|
954
|
+
```sql
|
|
955
|
+
-- Many JOINs
|
|
956
|
+
SELECT * FROM t1 JOIN t2 JOIN t3 JOIN t4 JOIN t5
|
|
957
|
+
|
|
958
|
+
-- Complex aggregations
|
|
959
|
+
SELECT a, b, c, COUNT(*), SUM(x), AVG(y), MIN(z), MAX(w)
|
|
960
|
+
FROM tasks
|
|
961
|
+
GROUP BY a, b, c
|
|
962
|
+
HAVING COUNT(*) > 10
|
|
963
|
+
|
|
964
|
+
-- String operations
|
|
965
|
+
SELECT title || ' - ' || description || ' - ' || notes FROM tasks
|
|
966
|
+
```
|
|
967
|
+
|
|
968
|
+
## Best Practices
|
|
969
|
+
|
|
970
|
+
### 1. Always Preview Before Creating
|
|
971
|
+
|
|
972
|
+
**Bad:**
|
|
973
|
+
```javascript
|
|
974
|
+
// Create without testing
|
|
975
|
+
create_insight({
|
|
976
|
+
name: 'Report',
|
|
977
|
+
sources: [...],
|
|
978
|
+
query: 'SELECT ...' // Hope it works!
|
|
979
|
+
})
|
|
980
|
+
// โ Fails, have to debug and recreate
|
|
981
|
+
```
|
|
982
|
+
|
|
983
|
+
**Good:**
|
|
984
|
+
```javascript
|
|
985
|
+
// Preview first
|
|
986
|
+
preview_insight({
|
|
987
|
+
sources: [...],
|
|
988
|
+
query: 'SELECT ...'
|
|
989
|
+
})
|
|
990
|
+
// โ
Works!
|
|
991
|
+
|
|
992
|
+
// Then create
|
|
993
|
+
create_insight({
|
|
994
|
+
name: 'Report',
|
|
995
|
+
sources: [...],
|
|
996
|
+
query: 'SELECT ...'
|
|
997
|
+
})
|
|
998
|
+
```
|
|
999
|
+
|
|
1000
|
+
### 2. Start Simple, Build Complexity
|
|
1001
|
+
|
|
1002
|
+
```javascript
|
|
1003
|
+
// Step 1: Basic SELECT
|
|
1004
|
+
preview_insight({ query: 'SELECT * FROM tasks' })
|
|
1005
|
+
|
|
1006
|
+
// Step 2: Specific columns
|
|
1007
|
+
preview_insight({ query: 'SELECT title, priority FROM tasks' })
|
|
1008
|
+
|
|
1009
|
+
// Step 3: Add filter
|
|
1010
|
+
preview_insight({ query: 'SELECT title, priority FROM tasks WHERE priority = "High"' })
|
|
1011
|
+
|
|
1012
|
+
// Step 4: Add sorting
|
|
1013
|
+
preview_insight({ query: 'SELECT title, priority FROM tasks WHERE priority = "High" ORDER BY title' })
|
|
1014
|
+
```
|
|
1015
|
+
|
|
1016
|
+
### 3. Use LIMIT During Testing
|
|
1017
|
+
|
|
1018
|
+
```javascript
|
|
1019
|
+
// Good: Limited results for fast testing
|
|
1020
|
+
preview_insight({
|
|
1021
|
+
sources: [...],
|
|
1022
|
+
query: 'SELECT * FROM tasks LIMIT 5'
|
|
1023
|
+
})
|
|
1024
|
+
|
|
1025
|
+
// Then remove LIMIT when creating
|
|
1026
|
+
create_insight({
|
|
1027
|
+
sources: [...],
|
|
1028
|
+
query: 'SELECT * FROM tasks' // Full results
|
|
1029
|
+
})
|
|
1030
|
+
```
|
|
1031
|
+
|
|
1032
|
+
### 4. Verify Field Mappings
|
|
1033
|
+
|
|
1034
|
+
```javascript
|
|
1035
|
+
// Before preview, get field IDs
|
|
1036
|
+
const schema = get_workflow_schema({ workflowId: 'workflow-id' })
|
|
1037
|
+
schema.fields.forEach(f => {
|
|
1038
|
+
if (f.key) {
|
|
1039
|
+
console.log(`${f.key}: ${f._id}`)
|
|
1040
|
+
}
|
|
1041
|
+
})
|
|
1042
|
+
|
|
1043
|
+
// Use correct IDs in preview
|
|
1044
|
+
preview_insight({
|
|
1045
|
+
sources: [{
|
|
1046
|
+
fields: [
|
|
1047
|
+
{ name: 'priority', fieldId: 'verified-field-id' }
|
|
1048
|
+
]
|
|
1049
|
+
}],
|
|
1050
|
+
query: '...'
|
|
1051
|
+
})
|
|
1052
|
+
```
|
|
1053
|
+
|
|
1054
|
+
### 5. Test JOINs Independently
|
|
1055
|
+
|
|
1056
|
+
```javascript
|
|
1057
|
+
// Test each source independently first
|
|
1058
|
+
preview_insight({
|
|
1059
|
+
sources: [{ name: 'tasks', ... }],
|
|
1060
|
+
query: 'SELECT * FROM tasks LIMIT 5'
|
|
1061
|
+
})
|
|
1062
|
+
|
|
1063
|
+
preview_insight({
|
|
1064
|
+
sources: [{ name: 'projects', ... }],
|
|
1065
|
+
query: 'SELECT * FROM projects LIMIT 5'
|
|
1066
|
+
})
|
|
1067
|
+
|
|
1068
|
+
// Then test JOIN
|
|
1069
|
+
preview_insight({
|
|
1070
|
+
sources: [
|
|
1071
|
+
{ name: 'tasks', ... },
|
|
1072
|
+
{ name: 'projects', ... }
|
|
1073
|
+
],
|
|
1074
|
+
query: 'SELECT ... FROM tasks JOIN projects ...'
|
|
1075
|
+
})
|
|
1076
|
+
```
|
|
1077
|
+
|
|
1078
|
+
### 6. Document Your Iterations
|
|
1079
|
+
|
|
1080
|
+
```javascript
|
|
1081
|
+
// Keep track of what works
|
|
1082
|
+
console.log('Test 1: Basic query - โ
')
|
|
1083
|
+
preview_insight({ query: 'SELECT * FROM tasks' })
|
|
1084
|
+
|
|
1085
|
+
console.log('Test 2: With filter - โ
')
|
|
1086
|
+
preview_insight({ query: 'SELECT * FROM tasks WHERE priority = "High"' })
|
|
1087
|
+
|
|
1088
|
+
console.log('Test 3: With JOIN - โ Error: column not found')
|
|
1089
|
+
preview_insight({ query: 'SELECT ... JOIN ...' })
|
|
1090
|
+
|
|
1091
|
+
console.log('Test 4: Fixed JOIN - โ
')
|
|
1092
|
+
preview_insight({ query: 'SELECT ... LEFT JOIN ...' })
|
|
1093
|
+
```
|
|
1094
|
+
|
|
1095
|
+
### 7. Remember Sample Limitation
|
|
1096
|
+
|
|
1097
|
+
```javascript
|
|
1098
|
+
// Preview only shows ~20 activities
|
|
1099
|
+
preview_insight({
|
|
1100
|
+
sources: [...],
|
|
1101
|
+
query: 'SELECT COUNT(*) FROM tasks'
|
|
1102
|
+
})
|
|
1103
|
+
// Returns: 20 (not actual total!)
|
|
1104
|
+
|
|
1105
|
+
// To see actual count, create insight and use get_insight_data
|
|
1106
|
+
create_insight({ ... })
|
|
1107
|
+
get_insight_data({ insightId: '...' })
|
|
1108
|
+
// Returns: 1523 (actual total)
|
|
1109
|
+
```
|
|
1110
|
+
|
|
1111
|
+
## Troubleshooting
|
|
1112
|
+
|
|
1113
|
+
### Preview Returns No Data
|
|
1114
|
+
|
|
1115
|
+
**Causes:**
|
|
1116
|
+
1. No activities in workflow
|
|
1117
|
+
2. WHERE clause too restrictive
|
|
1118
|
+
3. INNER JOIN eliminates all rows
|
|
1119
|
+
|
|
1120
|
+
**Solutions:**
|
|
1121
|
+
|
|
1122
|
+
```javascript
|
|
1123
|
+
// 1. Check activity count
|
|
1124
|
+
list_activities({
|
|
1125
|
+
workflowId: 'workflow-id',
|
|
1126
|
+
limit: 1
|
|
1127
|
+
})
|
|
1128
|
+
|
|
1129
|
+
// 2. Remove WHERE clause
|
|
1130
|
+
preview_insight({
|
|
1131
|
+
sources: [...],
|
|
1132
|
+
query: 'SELECT * FROM tasks' // No filter
|
|
1133
|
+
})
|
|
1134
|
+
|
|
1135
|
+
// 3. Use LEFT JOIN
|
|
1136
|
+
preview_insight({
|
|
1137
|
+
sources: [...],
|
|
1138
|
+
query: 'SELECT ... FROM tasks LEFT JOIN projects ...'
|
|
1139
|
+
})
|
|
1140
|
+
```
|
|
1141
|
+
|
|
1142
|
+
### Error: "Column not found"
|
|
1143
|
+
|
|
1144
|
+
**Cause:** Field name in query doesn't match source definition.
|
|
1145
|
+
|
|
1146
|
+
**Solution:**
|
|
1147
|
+
|
|
1148
|
+
```javascript
|
|
1149
|
+
// Field names must match exactly
|
|
1150
|
+
sources: [{
|
|
1151
|
+
fields: [
|
|
1152
|
+
{ name: 'taskTitle', meta: 'name' } // Name is 'taskTitle'
|
|
1153
|
+
]
|
|
1154
|
+
}],
|
|
1155
|
+
query: 'SELECT taskTitle FROM tasks' // Must use 'taskTitle'
|
|
1156
|
+
```
|
|
1157
|
+
|
|
1158
|
+
### Error: "Table not found"
|
|
1159
|
+
|
|
1160
|
+
**Cause:** Table name in query doesn't match source name.
|
|
1161
|
+
|
|
1162
|
+
**Solution:**
|
|
1163
|
+
|
|
1164
|
+
```javascript
|
|
1165
|
+
// Source names must match
|
|
1166
|
+
sources: [{
|
|
1167
|
+
name: 'tasks', // Name is 'tasks'
|
|
1168
|
+
...
|
|
1169
|
+
}],
|
|
1170
|
+
query: 'SELECT * FROM tasks' // Must use 'tasks'
|
|
1171
|
+
```
|
|
1172
|
+
|
|
1173
|
+
### Error: "Permission denied"
|
|
1174
|
+
|
|
1175
|
+
**Cause:** Regular users can't test arbitrary workflow combinations.
|
|
1176
|
+
|
|
1177
|
+
**Solutions:**
|
|
1178
|
+
1. Use sources from existing insights you have access to
|
|
1179
|
+
2. Request workspace admin to test
|
|
1180
|
+
3. Admins can test any sources
|
|
1181
|
+
|
|
1182
|
+
### Preview Successful But create_insight Fails
|
|
1183
|
+
|
|
1184
|
+
**Cause:** Preview uses sample data; full data may have issues.
|
|
1185
|
+
|
|
1186
|
+
**Solutions:**
|
|
1187
|
+
1. Check for NULL values in full dataset
|
|
1188
|
+
2. Verify all activities have required fields
|
|
1189
|
+
3. Test with get_insight_data after creation
|
|
1190
|
+
|
|
1191
|
+
## Integration with Other Tools
|
|
1192
|
+
|
|
1193
|
+
### With create_insight
|
|
1194
|
+
|
|
1195
|
+
Standard workflow:
|
|
1196
|
+
|
|
1197
|
+
```javascript
|
|
1198
|
+
// 1. Preview
|
|
1199
|
+
preview_insight({
|
|
1200
|
+
sources: [...],
|
|
1201
|
+
query: '...'
|
|
1202
|
+
})
|
|
1203
|
+
|
|
1204
|
+
// 2. Create (use exact same sources and query)
|
|
1205
|
+
create_insight({
|
|
1206
|
+
name: 'My Report',
|
|
1207
|
+
sources: [...], // Same
|
|
1208
|
+
query: '...' // Same
|
|
1209
|
+
})
|
|
1210
|
+
```
|
|
1211
|
+
|
|
1212
|
+
### With get_workflow_schema
|
|
1213
|
+
|
|
1214
|
+
Get field IDs for preview:
|
|
1215
|
+
|
|
1216
|
+
```javascript
|
|
1217
|
+
// 1. Get schema
|
|
1218
|
+
const schema = get_workflow_schema({
|
|
1219
|
+
workflowId: 'workflow-id'
|
|
1220
|
+
})
|
|
1221
|
+
|
|
1222
|
+
// 2. Build field mappings
|
|
1223
|
+
const fields = schema.fields
|
|
1224
|
+
.filter(f => f.key)
|
|
1225
|
+
.map(f => ({
|
|
1226
|
+
name: f.key,
|
|
1227
|
+
fieldId: f._id
|
|
1228
|
+
}))
|
|
1229
|
+
|
|
1230
|
+
// 3. Preview with fields
|
|
1231
|
+
preview_insight({
|
|
1232
|
+
sources: [{
|
|
1233
|
+
workflowId: 'workflow-id',
|
|
1234
|
+
fields: fields
|
|
1235
|
+
}],
|
|
1236
|
+
query: '...'
|
|
1237
|
+
})
|
|
1238
|
+
```
|
|
1239
|
+
|
|
1240
|
+
### With list_activities
|
|
1241
|
+
|
|
1242
|
+
Compare results:
|
|
1243
|
+
|
|
1244
|
+
```javascript
|
|
1245
|
+
// Preview result
|
|
1246
|
+
preview_insight({
|
|
1247
|
+
sources: [...],
|
|
1248
|
+
query: 'SELECT * FROM tasks WHERE priority = "High"'
|
|
1249
|
+
})
|
|
1250
|
+
// Shows ~20 rows
|
|
1251
|
+
|
|
1252
|
+
// Compare with list_activities
|
|
1253
|
+
list_activities({
|
|
1254
|
+
workflowId: 'workflow-id',
|
|
1255
|
+
filters: [{ field: 'priority-field-id', operator: 'eq', value: 'High' }]
|
|
1256
|
+
})
|
|
1257
|
+
// Shows actual count
|
|
1258
|
+
```
|
|
1259
|
+
|
|
1260
|
+
## Summary
|
|
1261
|
+
|
|
1262
|
+
**Key Takeaways:**
|
|
1263
|
+
1. ๐งช **Test before create** - Always preview queries first
|
|
1264
|
+
2. ๐ **Sample data** - Preview shows ~20 activities only
|
|
1265
|
+
3. โก **Fast iteration** - Quick feedback loop for development
|
|
1266
|
+
4. ๐ **Debugging tool** - Catch errors before committing
|
|
1267
|
+
5. ๐ **Security aware** - Regular users have restrictions
|
|
1268
|
+
6. ๐๏ธ **Iterative building** - Start simple, add complexity
|
|
1269
|
+
7. โ
**Validation** - Verify syntax, fields, JOINs
|
|
1270
|
+
|
|
1271
|
+
**Quick Decision Tree:**
|
|
1272
|
+
|
|
1273
|
+
```
|
|
1274
|
+
Building an insight?
|
|
1275
|
+
โ
|
|
1276
|
+
โโ Query untested? โ Preview first
|
|
1277
|
+
โโ Getting SQL errors? โ Preview to debug
|
|
1278
|
+
โโ Unsure about JOINs? โ Preview each piece
|
|
1279
|
+
โโ Need full data? โ Create insight, use get_insight_data
|
|
1280
|
+
โโ Query works in preview? โ Create insight
|
|
1281
|
+
```
|
|
1282
|
+
|
|
1283
|
+
## Additional Resources
|
|
1284
|
+
|
|
1285
|
+
- See `create-insight-skill` for creating insights
|
|
1286
|
+
- See `get-insight-data-skill` for executing insights
|
|
1287
|
+
- See `remove-insight-skill` for deleting insights
|
|
1288
|
+
- See `insight-api` skill for comprehensive Insight API documentation
|
|
1289
|
+
- Use `get_workflow_schema` to find field IDs
|
|
1290
|
+
- Use `list_workflows` to find workflow IDs
|