@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,806 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Insight Tools - Clean Architecture Implementation
|
|
4
|
+
*
|
|
5
|
+
* SQL-like insights over Hailer workflows:
|
|
6
|
+
* - Workflows = Tables
|
|
7
|
+
* - Activities = Rows
|
|
8
|
+
* - Fields = Columns
|
|
9
|
+
*
|
|
10
|
+
* All 4 insight management tools in one file for cohesion.
|
|
11
|
+
*/
|
|
12
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
|
+
exports.listInsightsTool = exports.removeInsightTool = exports.getInsightDataTool = exports.previewInsightTool = exports.createInsightTool = void 0;
|
|
14
|
+
const zod_1 = require("zod");
|
|
15
|
+
const tool_registry_1 = require("../tool-registry");
|
|
16
|
+
const workspace_cache_1 = require("../workspace-cache");
|
|
17
|
+
const logger_1 = require("../../lib/logger");
|
|
18
|
+
const logger = (0, logger_1.createLogger)({ component: 'insight-tools' });
|
|
19
|
+
// ============================================================================
|
|
20
|
+
// SHARED TYPES & SCHEMAS
|
|
21
|
+
// ============================================================================
|
|
22
|
+
/**
|
|
23
|
+
* Field definition schema - either meta field or custom fieldId
|
|
24
|
+
*/
|
|
25
|
+
const fieldSchema = zod_1.z.object({
|
|
26
|
+
name: zod_1.z.string().describe("Column name in SQL query"),
|
|
27
|
+
}).and(zod_1.z.union([
|
|
28
|
+
zod_1.z.object({
|
|
29
|
+
meta: zod_1.z.enum([
|
|
30
|
+
'_id',
|
|
31
|
+
'uid',
|
|
32
|
+
'team',
|
|
33
|
+
'createdBy',
|
|
34
|
+
'name',
|
|
35
|
+
'created',
|
|
36
|
+
'updated',
|
|
37
|
+
'phaseId',
|
|
38
|
+
'phaseName',
|
|
39
|
+
'phaseLastMove',
|
|
40
|
+
'workflowId',
|
|
41
|
+
'workflowName',
|
|
42
|
+
'priority'
|
|
43
|
+
]).describe("Built-in activity property"),
|
|
44
|
+
}),
|
|
45
|
+
zod_1.z.object({
|
|
46
|
+
fieldId: zod_1.z.string().describe("Custom field ID from workflow"),
|
|
47
|
+
}),
|
|
48
|
+
]));
|
|
49
|
+
/**
|
|
50
|
+
* Source definition schema - workflow as SQL table
|
|
51
|
+
*/
|
|
52
|
+
const sourceSchema = zod_1.z.object({
|
|
53
|
+
name: zod_1.z.string().describe("Table alias for SQL query"),
|
|
54
|
+
workflowId: zod_1.z.string().describe("Workflow ID to query"),
|
|
55
|
+
fields: zod_1.z.array(fieldSchema).min(1).describe("Field mappings for SQL columns"),
|
|
56
|
+
});
|
|
57
|
+
// ============================================================================
|
|
58
|
+
// CREATE INSIGHT TOOL
|
|
59
|
+
// ============================================================================
|
|
60
|
+
const createInsightDescription = `๐งช [PLAYGROUND] Create SQL-like insights (workflows = tables, activities = rows, fields = columns)
|
|
61
|
+
|
|
62
|
+
โ ๏ธ **MANDATORY: YOU MUST LOAD SKILL FIRST**
|
|
63
|
+
**BEFORE calling this tool, you are REQUIRED to:**
|
|
64
|
+
1. Load the skill: \`get_skill({ skillName: "create-insight-skill" })\`
|
|
65
|
+
2. Read the query examples, JOIN patterns, and aggregation examples
|
|
66
|
+
3. Test your SQL with \`preview_insight\` first
|
|
67
|
+
**FAILURE TO LOAD THE SKILL FIRST IS AN ERROR**
|
|
68
|
+
|
|
69
|
+
**Required Parameters**:
|
|
70
|
+
- name: Insight name
|
|
71
|
+
- sources: Array with name (table alias), workflowId, fields (meta or fieldId)
|
|
72
|
+
- query: Standard SQL (SELECT, JOIN, WHERE, GROUP BY, ORDER BY, LIMIT)
|
|
73
|
+
|
|
74
|
+
**Meta Fields**: _id, uid, team, createdBy, name, created, updated, phaseId, phaseName, phaseLastMove, workflowId, workflowName, priority
|
|
75
|
+
**SQL Support**: All standard SQL features including JOINs and aggregations`;
|
|
76
|
+
exports.createInsightTool = {
|
|
77
|
+
name: 'create_insight',
|
|
78
|
+
group: tool_registry_1.ToolGroup.PLAYGROUND,
|
|
79
|
+
description: createInsightDescription,
|
|
80
|
+
schema: zod_1.z.object({
|
|
81
|
+
workspaceId: zod_1.z
|
|
82
|
+
.string()
|
|
83
|
+
.optional()
|
|
84
|
+
.describe("Optional workspace ID or name - defaults to current workspace"),
|
|
85
|
+
name: zod_1.z
|
|
86
|
+
.string()
|
|
87
|
+
.min(1)
|
|
88
|
+
.describe("Insight name"),
|
|
89
|
+
public: zod_1.z
|
|
90
|
+
.boolean()
|
|
91
|
+
.optional()
|
|
92
|
+
.default(false)
|
|
93
|
+
.describe("Whether insight is publicly accessible (default: false)"),
|
|
94
|
+
sources: zod_1.z
|
|
95
|
+
.array(sourceSchema)
|
|
96
|
+
.min(1)
|
|
97
|
+
.describe("Workflow sources (like SQL table references)"),
|
|
98
|
+
query: zod_1.z
|
|
99
|
+
.string()
|
|
100
|
+
.min(1)
|
|
101
|
+
.describe("SQL query (SELECT, JOIN, WHERE, GROUP BY, ORDER BY, etc.)"),
|
|
102
|
+
}),
|
|
103
|
+
async execute(args, context) {
|
|
104
|
+
logger.debug('Creating insight', {
|
|
105
|
+
name: args.name,
|
|
106
|
+
workspaceId: args.workspaceId,
|
|
107
|
+
sourcesCount: args.sources.length,
|
|
108
|
+
apiKey: context.apiKey.substring(0, 8) + '...'
|
|
109
|
+
});
|
|
110
|
+
try {
|
|
111
|
+
if (!context.workspaceCache) {
|
|
112
|
+
return {
|
|
113
|
+
content: [{
|
|
114
|
+
type: "text",
|
|
115
|
+
text: "โ Workspace cache not available",
|
|
116
|
+
}],
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
// Resolve workspace ID
|
|
120
|
+
const workspaceId = args.workspaceId
|
|
121
|
+
? (0, workspace_cache_1.resolveWorkspaceId)(context.workspaceCache, args.workspaceId)
|
|
122
|
+
: context.workspaceCache.currentWorkspace._id;
|
|
123
|
+
if (!workspaceId) {
|
|
124
|
+
return {
|
|
125
|
+
content: [{
|
|
126
|
+
type: "text",
|
|
127
|
+
text: `โ Could not resolve workspace: ${args.workspaceId}`,
|
|
128
|
+
}],
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
logger.debug('Calling v3.insight.create', {
|
|
132
|
+
workspaceId,
|
|
133
|
+
name: args.name,
|
|
134
|
+
sourcesCount: args.sources.length
|
|
135
|
+
});
|
|
136
|
+
// Build insight payload
|
|
137
|
+
const insightData = {
|
|
138
|
+
name: args.name,
|
|
139
|
+
public: args.public || false,
|
|
140
|
+
sources: args.sources,
|
|
141
|
+
query: args.query,
|
|
142
|
+
};
|
|
143
|
+
// Call v3.insight.create endpoint
|
|
144
|
+
const result = await context.hailer.request('v3.insight.create', [workspaceId, insightData]);
|
|
145
|
+
logger.debug('Insight creation successful', {
|
|
146
|
+
insightId: result.insightId || result._id,
|
|
147
|
+
result: JSON.stringify(result)
|
|
148
|
+
});
|
|
149
|
+
const insightId = result.insightId || result._id;
|
|
150
|
+
const discussionId = result.discussionId || result.discussion;
|
|
151
|
+
// Automatically join the insight's discussion
|
|
152
|
+
if (discussionId) {
|
|
153
|
+
try {
|
|
154
|
+
logger.debug('Automatically joining insight discussion', { discussionId });
|
|
155
|
+
await context.hailer.joinDiscussion(discussionId);
|
|
156
|
+
logger.debug('Successfully joined insight discussion', { discussionId });
|
|
157
|
+
}
|
|
158
|
+
catch (joinError) {
|
|
159
|
+
logger.warn('Failed to join insight discussion (non-fatal)', {
|
|
160
|
+
discussionId,
|
|
161
|
+
error: joinError instanceof Error ? joinError.message : String(joinError)
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
else {
|
|
166
|
+
logger.debug('No discussion ID in response, skipping auto-join');
|
|
167
|
+
}
|
|
168
|
+
// Build success response
|
|
169
|
+
let responseText = `โ
**Insight Created Successfully**\n\n`;
|
|
170
|
+
responseText += `**Insight Name:** ${args.name}\n`;
|
|
171
|
+
responseText += `**Insight ID:** \`${insightId}\`\n`;
|
|
172
|
+
responseText += `**Workspace:** ${workspaceId}\n`;
|
|
173
|
+
responseText += `**Public:** ${args.public ? 'Yes' : 'No'}\n`;
|
|
174
|
+
responseText += `**Sources:** ${args.sources.length} workflow(s)\n`;
|
|
175
|
+
if (discussionId) {
|
|
176
|
+
responseText += `**Discussion:** Automatically joined โ\n`;
|
|
177
|
+
}
|
|
178
|
+
responseText += `\n`;
|
|
179
|
+
// Show sources
|
|
180
|
+
responseText += `**Query Sources:**\n`;
|
|
181
|
+
args.sources.forEach((source) => {
|
|
182
|
+
responseText += `- \`${source.name}\` โ Workflow: \`${source.workflowId}\` (${source.fields.length} fields)\n`;
|
|
183
|
+
});
|
|
184
|
+
responseText += `\n**SQL Query:**\n\`\`\`sql\n${args.query}\n\`\`\`\n\n`;
|
|
185
|
+
responseText += `๐ก **Next Steps:**\n`;
|
|
186
|
+
responseText += `- Use \`get_insight_data\` to execute the query and see results\n`;
|
|
187
|
+
responseText += `- Use \`list_insights\` to see all insights in workspace\n`;
|
|
188
|
+
responseText += `- Use \`update_insight\` to modify the insight\n`;
|
|
189
|
+
responseText += `- Use \`preview_insight\` to test query changes before saving\n\n`;
|
|
190
|
+
if (args.public) {
|
|
191
|
+
responseText += `๐ **Public Insight:** This insight can be accessed without authentication.\n`;
|
|
192
|
+
}
|
|
193
|
+
return {
|
|
194
|
+
content: [{
|
|
195
|
+
type: "text",
|
|
196
|
+
text: responseText,
|
|
197
|
+
}],
|
|
198
|
+
};
|
|
199
|
+
}
|
|
200
|
+
catch (error) {
|
|
201
|
+
logger.error("Error creating insight", error);
|
|
202
|
+
let errorMessage = 'Unknown error occurred';
|
|
203
|
+
let errorDetails = '';
|
|
204
|
+
if (error instanceof Error) {
|
|
205
|
+
errorMessage = error.message;
|
|
206
|
+
if (error.stack) {
|
|
207
|
+
errorDetails = `\n\n**Stack trace:**\n\`\`\`\n${error.stack}\n\`\`\``;
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
else if (typeof error === 'object' && error !== null) {
|
|
211
|
+
try {
|
|
212
|
+
errorMessage = JSON.stringify(error, null, 2);
|
|
213
|
+
}
|
|
214
|
+
catch {
|
|
215
|
+
errorMessage = String(error);
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
else {
|
|
219
|
+
errorMessage = String(error);
|
|
220
|
+
}
|
|
221
|
+
// Handle SQL syntax errors
|
|
222
|
+
if (errorMessage.toLowerCase().includes('sql') || errorMessage.toLowerCase().includes('syntax')) {
|
|
223
|
+
return {
|
|
224
|
+
content: [{
|
|
225
|
+
type: "text",
|
|
226
|
+
text: `โ **SQL Query Error**\n\nThere's a problem with your SQL query.\n\n**Error:** ${errorMessage}\n\n**Tips:**\n- Check column names match field names in sources\n- Check table names match source names\n- Use \`preview_insight\` to test queries before creating\n- Make sure field IDs are correct (use \`get_workflow_schema\`)`,
|
|
227
|
+
}],
|
|
228
|
+
};
|
|
229
|
+
}
|
|
230
|
+
// Handle permission errors
|
|
231
|
+
if (errorMessage.includes('permission') || errorMessage.includes('PermissionDenied')) {
|
|
232
|
+
return {
|
|
233
|
+
content: [{
|
|
234
|
+
type: "text",
|
|
235
|
+
text: `โ **Permission Denied**\n\nYou may not have permission to create insights or access the specified workflows.\n\n**Error:** ${errorMessage}`,
|
|
236
|
+
}],
|
|
237
|
+
};
|
|
238
|
+
}
|
|
239
|
+
return {
|
|
240
|
+
content: [{
|
|
241
|
+
type: "text",
|
|
242
|
+
text: `โ **Error creating insight**\n\n**Error:** ${errorMessage}${errorDetails}\n\n**Common Issues:**\n- SQL query syntax errors\n- Invalid field IDs or workflow IDs\n- Workflow fields don't exist\n- Permission issues\n- Check field IDs with \`get_workflow_schema\`\n- Test query with \`preview_insight\` first`,
|
|
243
|
+
}],
|
|
244
|
+
};
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
};
|
|
248
|
+
// ============================================================================
|
|
249
|
+
// PREVIEW INSIGHT TOOL
|
|
250
|
+
// ============================================================================
|
|
251
|
+
const previewInsightDescription = `๐งช [PLAYGROUND] Preview insight - Test SQL on ~20 activities before saving
|
|
252
|
+
|
|
253
|
+
โ ๏ธ **MANDATORY: YOU MUST LOAD SKILL FIRST**
|
|
254
|
+
**BEFORE calling this tool, you are REQUIRED to:**
|
|
255
|
+
1. Load the skill: \`get_skill({ skillName: "preview-insight-skill" })\`
|
|
256
|
+
2. Read the debugging tips and security notes
|
|
257
|
+
3. Understand the SQL testing patterns
|
|
258
|
+
**FAILURE TO LOAD THE SKILL FIRST IS AN ERROR**
|
|
259
|
+
|
|
260
|
+
**Purpose**: Debug SQL syntax, test JOINs, verify field mappings without creating insight
|
|
261
|
+
|
|
262
|
+
**Required Parameters**:
|
|
263
|
+
- sources: Same format as create_insight (name, workflowId, fields)
|
|
264
|
+
- query: SQL query to test
|
|
265
|
+
- insightId (optional): Test changes to existing insight`;
|
|
266
|
+
exports.previewInsightTool = {
|
|
267
|
+
name: 'preview_insight',
|
|
268
|
+
group: tool_registry_1.ToolGroup.PLAYGROUND,
|
|
269
|
+
description: previewInsightDescription,
|
|
270
|
+
schema: zod_1.z.object({
|
|
271
|
+
workspaceId: zod_1.z
|
|
272
|
+
.string()
|
|
273
|
+
.optional()
|
|
274
|
+
.describe("Optional workspace ID or name - defaults to current workspace"),
|
|
275
|
+
sources: zod_1.z
|
|
276
|
+
.array(sourceSchema)
|
|
277
|
+
.min(1)
|
|
278
|
+
.describe("Workflow sources (like SQL table references)"),
|
|
279
|
+
query: zod_1.z
|
|
280
|
+
.string()
|
|
281
|
+
.min(1)
|
|
282
|
+
.describe("SQL query to test"),
|
|
283
|
+
insightId: zod_1.z
|
|
284
|
+
.string()
|
|
285
|
+
.optional()
|
|
286
|
+
.describe("Optional insight ID if previewing changes to existing insight"),
|
|
287
|
+
}),
|
|
288
|
+
async execute(args, context) {
|
|
289
|
+
logger.debug('Previewing insight', {
|
|
290
|
+
workspaceId: args.workspaceId,
|
|
291
|
+
sourcesCount: args.sources.length,
|
|
292
|
+
insightId: args.insightId,
|
|
293
|
+
apiKey: context.apiKey.substring(0, 8) + '...'
|
|
294
|
+
});
|
|
295
|
+
try {
|
|
296
|
+
if (!context.workspaceCache) {
|
|
297
|
+
return {
|
|
298
|
+
content: [{
|
|
299
|
+
type: "text",
|
|
300
|
+
text: "โ Workspace cache not available",
|
|
301
|
+
}],
|
|
302
|
+
};
|
|
303
|
+
}
|
|
304
|
+
// Resolve workspace ID
|
|
305
|
+
const workspaceId = args.workspaceId
|
|
306
|
+
? (0, workspace_cache_1.resolveWorkspaceId)(context.workspaceCache, args.workspaceId)
|
|
307
|
+
: context.workspaceCache.currentWorkspace._id;
|
|
308
|
+
if (!workspaceId) {
|
|
309
|
+
return {
|
|
310
|
+
content: [{
|
|
311
|
+
type: "text",
|
|
312
|
+
text: `โ Could not resolve workspace: ${args.workspaceId}`,
|
|
313
|
+
}],
|
|
314
|
+
};
|
|
315
|
+
}
|
|
316
|
+
logger.debug('Calling v3.insight.preview', {
|
|
317
|
+
workspaceId,
|
|
318
|
+
sourcesCount: args.sources.length,
|
|
319
|
+
insightId: args.insightId
|
|
320
|
+
});
|
|
321
|
+
// Build preview payload
|
|
322
|
+
const previewData = {
|
|
323
|
+
sources: args.sources,
|
|
324
|
+
query: args.query,
|
|
325
|
+
...(args.insightId && { insightId: args.insightId }),
|
|
326
|
+
};
|
|
327
|
+
// Call v3.insight.preview endpoint
|
|
328
|
+
const result = await context.hailer.request('v3.insight.preview', [workspaceId, previewData]);
|
|
329
|
+
logger.debug('Preview successful', {
|
|
330
|
+
columns: result.columns?.length,
|
|
331
|
+
rows: result.rows?.length
|
|
332
|
+
});
|
|
333
|
+
// Format results
|
|
334
|
+
let responseText = `โ
**Preview Results** (~${result.rows?.length || 0} rows)\n\n`;
|
|
335
|
+
if (!result.columns || !result.rows) {
|
|
336
|
+
responseText += `โ ๏ธ No data returned from preview\n`;
|
|
337
|
+
}
|
|
338
|
+
else if (result.rows.length === 0) {
|
|
339
|
+
responseText += `**Columns:** ${result.columns.join(', ')}\n\n`;
|
|
340
|
+
responseText += `โ ๏ธ **No rows matched** - Check your query filters\n`;
|
|
341
|
+
}
|
|
342
|
+
else {
|
|
343
|
+
responseText += `**Columns:** ${result.columns.join(', ')}\n\n`;
|
|
344
|
+
responseText += `**Sample Data:**\n\`\`\`\n`;
|
|
345
|
+
// Show column headers
|
|
346
|
+
responseText += result.columns.join(' | ') + '\n';
|
|
347
|
+
responseText += result.columns.map(() => '---').join(' | ') + '\n';
|
|
348
|
+
// Show first 10 rows
|
|
349
|
+
const rowsToShow = Math.min(result.rows.length, 10);
|
|
350
|
+
for (let i = 0; i < rowsToShow; i++) {
|
|
351
|
+
responseText += result.rows[i].map(v => String(v || '')).join(' | ') + '\n';
|
|
352
|
+
}
|
|
353
|
+
if (result.rows.length > 10) {
|
|
354
|
+
responseText += `\n... and ${result.rows.length - 10} more rows\n`;
|
|
355
|
+
}
|
|
356
|
+
responseText += `\`\`\`\n\n`;
|
|
357
|
+
}
|
|
358
|
+
responseText += `\nโ
**Query is valid!** Ready to use in \`create_insight\` or \`update_insight\`.`;
|
|
359
|
+
return {
|
|
360
|
+
content: [{
|
|
361
|
+
type: "text",
|
|
362
|
+
text: responseText,
|
|
363
|
+
}],
|
|
364
|
+
};
|
|
365
|
+
}
|
|
366
|
+
catch (error) {
|
|
367
|
+
logger.error("Error previewing insight", error);
|
|
368
|
+
let errorMessage = 'Unknown error occurred';
|
|
369
|
+
if (error instanceof Error) {
|
|
370
|
+
errorMessage = error.message;
|
|
371
|
+
}
|
|
372
|
+
else if (typeof error === 'object' && error !== null) {
|
|
373
|
+
try {
|
|
374
|
+
errorMessage = JSON.stringify(error, null, 2);
|
|
375
|
+
}
|
|
376
|
+
catch {
|
|
377
|
+
errorMessage = String(error);
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
else {
|
|
381
|
+
errorMessage = String(error);
|
|
382
|
+
}
|
|
383
|
+
return {
|
|
384
|
+
content: [{
|
|
385
|
+
type: "text",
|
|
386
|
+
text: `โ **Preview Failed**\n\n**Error:** ${errorMessage}\n\n**Tips:**\n- Check SQL syntax\n- Verify field names match source definitions\n- Ensure workflow IDs are correct\n- Check table aliases match source names`,
|
|
387
|
+
}],
|
|
388
|
+
};
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
};
|
|
392
|
+
// ============================================================================
|
|
393
|
+
// GET INSIGHT DATA TOOL
|
|
394
|
+
// ============================================================================
|
|
395
|
+
const getInsightDataDescription = `๐งช [PLAYGROUND] Get Insight Data - Execute insight and retrieve results
|
|
396
|
+
|
|
397
|
+
**What is Get Insight Data?**
|
|
398
|
+
Executes a saved insight's SQL query and returns the complete results. Unlike preview (limited to ~20 rows), this returns all matching activities.
|
|
399
|
+
|
|
400
|
+
**When to Use**:
|
|
401
|
+
- Get full results from a saved insight
|
|
402
|
+
- Export insight data
|
|
403
|
+
- Verify insight after creation
|
|
404
|
+
- Check updated data after changes
|
|
405
|
+
|
|
406
|
+
**Example - Basic Usage**:
|
|
407
|
+
\`\`\`javascript
|
|
408
|
+
get_insight_data({
|
|
409
|
+
insightId: '<insight-id>'
|
|
410
|
+
})
|
|
411
|
+
\`\`\`
|
|
412
|
+
|
|
413
|
+
**Update Option**:
|
|
414
|
+
- \`update: false\` (default) - Returns cached results (faster)
|
|
415
|
+
- \`update: true\` - Recalculates from current activity data (slower but fresh)
|
|
416
|
+
|
|
417
|
+
**Tips**:
|
|
418
|
+
- Use \`update: true\` if activity data has changed
|
|
419
|
+
- Results can be large - may take time for big datasets
|
|
420
|
+
- Use \`preview_insight\` first to test queries
|
|
421
|
+
- Get insight ID from \`create_insight\` or \`list_insights\``;
|
|
422
|
+
exports.getInsightDataTool = {
|
|
423
|
+
name: 'get_insight_data',
|
|
424
|
+
group: tool_registry_1.ToolGroup.PLAYGROUND,
|
|
425
|
+
description: getInsightDataDescription,
|
|
426
|
+
schema: zod_1.z.object({
|
|
427
|
+
insightId: zod_1.z
|
|
428
|
+
.string()
|
|
429
|
+
.describe("Insight ID to execute"),
|
|
430
|
+
update: zod_1.z
|
|
431
|
+
.boolean()
|
|
432
|
+
.optional()
|
|
433
|
+
.default(false)
|
|
434
|
+
.describe("Whether to recalculate data (true) or use cached results (false, default)"),
|
|
435
|
+
}),
|
|
436
|
+
async execute(args, context) {
|
|
437
|
+
logger.debug('Getting insight data', {
|
|
438
|
+
insightId: args.insightId,
|
|
439
|
+
update: args.update,
|
|
440
|
+
apiKey: context.apiKey.substring(0, 8) + '...'
|
|
441
|
+
});
|
|
442
|
+
try {
|
|
443
|
+
logger.debug('Calling v3.insight.data', {
|
|
444
|
+
insightId: args.insightId,
|
|
445
|
+
update: args.update
|
|
446
|
+
});
|
|
447
|
+
// Call v3.insight.data endpoint
|
|
448
|
+
const result = await context.hailer.request('v3.insight.data', [args.insightId, { update: args.update || false }]);
|
|
449
|
+
logger.debug('Insight data retrieved', {
|
|
450
|
+
headers: result.headers?.length,
|
|
451
|
+
rows: result.rows?.length,
|
|
452
|
+
fullResult: JSON.stringify(result).substring(0, 500)
|
|
453
|
+
});
|
|
454
|
+
// Format results
|
|
455
|
+
let responseText = `โ
**Insight Data Retrieved** (${result.rows?.length || 0} rows)\n\n`;
|
|
456
|
+
if (!result.headers || !result.rows) {
|
|
457
|
+
responseText += `โ ๏ธ No data returned\n`;
|
|
458
|
+
responseText += `**Debug:** Response keys: ${Object.keys(result).join(', ')}\n`;
|
|
459
|
+
responseText += `**Full response (truncated):** \`${JSON.stringify(result).substring(0, 300)}\`\n`;
|
|
460
|
+
}
|
|
461
|
+
else if (result.rows.length === 0) {
|
|
462
|
+
responseText += `**Columns:** ${result.headers.join(', ')}\n\n`;
|
|
463
|
+
responseText += `โ ๏ธ **No rows matched**\n`;
|
|
464
|
+
}
|
|
465
|
+
else {
|
|
466
|
+
responseText += `**Columns:** ${result.headers.join(', ')}\n\n`;
|
|
467
|
+
responseText += `**Sample Data (first 10 rows):**\n\`\`\`\n`;
|
|
468
|
+
// Show column headers
|
|
469
|
+
responseText += result.headers.join(' | ') + '\n';
|
|
470
|
+
responseText += result.headers.map(() => '---').join(' | ') + '\n';
|
|
471
|
+
// Show first 10 rows
|
|
472
|
+
const rowsToShow = Math.min(result.rows.length, 10);
|
|
473
|
+
for (let i = 0; i < rowsToShow; i++) {
|
|
474
|
+
responseText += result.rows[i].map(v => String(v || '')).join(' | ') + '\n';
|
|
475
|
+
}
|
|
476
|
+
if (result.rows.length > 10) {
|
|
477
|
+
responseText += `\n... and ${result.rows.length - 10} more rows\n`;
|
|
478
|
+
}
|
|
479
|
+
responseText += `\`\`\`\n`;
|
|
480
|
+
}
|
|
481
|
+
return {
|
|
482
|
+
content: [{
|
|
483
|
+
type: "text",
|
|
484
|
+
text: responseText,
|
|
485
|
+
}],
|
|
486
|
+
};
|
|
487
|
+
}
|
|
488
|
+
catch (error) {
|
|
489
|
+
logger.error("Error getting insight data", error);
|
|
490
|
+
let errorMessage = 'Unknown error occurred';
|
|
491
|
+
if (error instanceof Error) {
|
|
492
|
+
errorMessage = error.message;
|
|
493
|
+
}
|
|
494
|
+
else if (typeof error === 'object' && error !== null) {
|
|
495
|
+
try {
|
|
496
|
+
errorMessage = JSON.stringify(error, null, 2);
|
|
497
|
+
}
|
|
498
|
+
catch {
|
|
499
|
+
errorMessage = String(error);
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
else {
|
|
503
|
+
errorMessage = String(error);
|
|
504
|
+
}
|
|
505
|
+
return {
|
|
506
|
+
content: [{
|
|
507
|
+
type: "text",
|
|
508
|
+
text: `โ **Error getting insight data**\n\n**Error:** ${errorMessage}\n\n**Common Issues:**\n- Insight ID not found\n- Permission denied\n- Insight query has errors\n- Use \`list_insights\` to verify insight ID`,
|
|
509
|
+
}],
|
|
510
|
+
};
|
|
511
|
+
}
|
|
512
|
+
}
|
|
513
|
+
};
|
|
514
|
+
// ============================================================================
|
|
515
|
+
// REMOVE INSIGHT TOOL
|
|
516
|
+
// ============================================================================
|
|
517
|
+
const removeInsightDescription = `๐งช [PLAYGROUND] Remove Insight - โ ๏ธ DANGER: Permanently deletes insight and all its data
|
|
518
|
+
|
|
519
|
+
โ ๏ธ **MANDATORY: GATHER COMPLETE CONTEXT BEFORE CALLING THIS TOOL**
|
|
520
|
+
**BEFORE calling this tool, you are REQUIRED to:**
|
|
521
|
+
1. Load the skill: \`get_skill({ skillName: "remove-insight-skill" })\`
|
|
522
|
+
2. Fetch insight details with \`list_insights\` to get:
|
|
523
|
+
- Insight name and ID
|
|
524
|
+
- Workspace ID and name
|
|
525
|
+
- SQL query
|
|
526
|
+
- Source workflows
|
|
527
|
+
- Number of sources
|
|
528
|
+
3. Show comprehensive confirmation message including:
|
|
529
|
+
- Workspace ID and name
|
|
530
|
+
- Insight ID and name
|
|
531
|
+
- What will be deleted (definition, results, permissions, discussion)
|
|
532
|
+
- Sources being queried (workflows)
|
|
533
|
+
- Clear irreversibility warning
|
|
534
|
+
4. Wait for explicit user confirmation
|
|
535
|
+
**FAILURE TO GATHER AND SHOW THIS CONTEXT IS AN ERROR**
|
|
536
|
+
|
|
537
|
+
**Required**: insightId
|
|
538
|
+
**Permission**: Workspace administrator
|
|
539
|
+
|
|
540
|
+
**What Gets Deleted**:
|
|
541
|
+
- Insight definition (sources, query, name)
|
|
542
|
+
- Saved query results
|
|
543
|
+
- Insight permissions
|
|
544
|
+
- Associated discussion
|
|
545
|
+
|
|
546
|
+
**Example**:
|
|
547
|
+
\`\`\`javascript
|
|
548
|
+
remove_insight({
|
|
549
|
+
insightId: '<insight-id>'
|
|
550
|
+
})
|
|
551
|
+
\`\`\`
|
|
552
|
+
|
|
553
|
+
**Tips**:
|
|
554
|
+
- Use \`list_insights\` to find insight IDs
|
|
555
|
+
- Use \`get_insight_data\` to verify before deleting
|
|
556
|
+
- Operation cannot be undone - data is permanently lost`;
|
|
557
|
+
exports.removeInsightTool = {
|
|
558
|
+
name: 'remove_insight',
|
|
559
|
+
group: tool_registry_1.ToolGroup.NUCLEAR,
|
|
560
|
+
description: removeInsightDescription,
|
|
561
|
+
schema: zod_1.z.object({
|
|
562
|
+
insightId: zod_1.z
|
|
563
|
+
.string()
|
|
564
|
+
.describe("Insight ID to remove (get from list_insights or create_insight)"),
|
|
565
|
+
confirmed: zod_1.z
|
|
566
|
+
.boolean()
|
|
567
|
+
.optional()
|
|
568
|
+
.describe("First confirmation - must be true to proceed"),
|
|
569
|
+
secondConfirmed: zod_1.z
|
|
570
|
+
.boolean()
|
|
571
|
+
.optional()
|
|
572
|
+
.describe("Second confirmation - must be true to proceed (required for double-check safety)"),
|
|
573
|
+
}),
|
|
574
|
+
async execute(args, context) {
|
|
575
|
+
logger.debug('Removing insight', {
|
|
576
|
+
insightId: args.insightId,
|
|
577
|
+
confirmed: args.confirmed,
|
|
578
|
+
secondConfirmed: args.secondConfirmed,
|
|
579
|
+
apiKey: context.apiKey.substring(0, 8) + '...'
|
|
580
|
+
});
|
|
581
|
+
try {
|
|
582
|
+
if (!context.workspaceCache) {
|
|
583
|
+
return {
|
|
584
|
+
content: [{
|
|
585
|
+
type: "text",
|
|
586
|
+
text: "โ Workspace cache not available",
|
|
587
|
+
}],
|
|
588
|
+
};
|
|
589
|
+
}
|
|
590
|
+
const workspaceId = context.workspaceCache.currentWorkspace._id;
|
|
591
|
+
// Fetch insight info and workspace info
|
|
592
|
+
const [insightListResult, initData] = await Promise.all([
|
|
593
|
+
context.hailer.request('v3.insight.list', [workspaceId]),
|
|
594
|
+
context.hailer.request('v2.core.init', [["network"]])
|
|
595
|
+
]);
|
|
596
|
+
const insights = Array.isArray(insightListResult) ? insightListResult : (insightListResult.details || insightListResult.insights || []);
|
|
597
|
+
const insight = insights.find((i) => i._id === args.insightId);
|
|
598
|
+
const insightName = insight?.name || 'Unknown';
|
|
599
|
+
const workspaceName = initData.network?.name || 'Unknown';
|
|
600
|
+
// SAFETY CHECK: Require double confirmation
|
|
601
|
+
if (!args.confirmed || !args.secondConfirmed) {
|
|
602
|
+
let warningText = `โ ๏ธ **DESTRUCTIVE OPERATION - CONFIRMATION REQUIRED**\n\n`;
|
|
603
|
+
warningText += `You are about to **permanently delete** the following:\n\n`;
|
|
604
|
+
warningText += `**Insight:** ${insightName}\n`;
|
|
605
|
+
warningText += `**Insight ID:** \`${args.insightId}\`\n`;
|
|
606
|
+
warningText += `**Workspace:** ${workspaceName} (\`${workspaceId}\`)\n\n`;
|
|
607
|
+
warningText += `**โ ๏ธ This will permanently delete:**\n`;
|
|
608
|
+
warningText += `- Insight definition (sources, query, name)\n`;
|
|
609
|
+
warningText += `- Saved query results\n`;
|
|
610
|
+
warningText += `- Insight permissions\n`;
|
|
611
|
+
warningText += `- Associated discussion\n\n`;
|
|
612
|
+
warningText += `**๐จ THIS CANNOT BE UNDONE! ๐จ**\n\n`;
|
|
613
|
+
warningText += `**To proceed, you must:**\n`;
|
|
614
|
+
warningText += `1. Review the \`remove-insight-skill\` (REQUIRED)\n`;
|
|
615
|
+
warningText += `2. Call this tool again with BOTH confirmations:\n\n`;
|
|
616
|
+
warningText += `\`\`\`javascript\n`;
|
|
617
|
+
warningText += `remove_insight({\n`;
|
|
618
|
+
warningText += ` insightId: "${args.insightId}",\n`;
|
|
619
|
+
warningText += ` confirmed: true,\n`;
|
|
620
|
+
warningText += ` secondConfirmed: true\n`;
|
|
621
|
+
warningText += `})\n`;
|
|
622
|
+
warningText += `\`\`\`\n\n`;
|
|
623
|
+
warningText += `๐ก **Before proceeding:**\n`;
|
|
624
|
+
warningText += `- Load \`remove-insight-skill\` to review safety checklist\n`;
|
|
625
|
+
warningText += `- Use \`get_insight_data\` to verify before deleting\n`;
|
|
626
|
+
warningText += `- Verify with user that this is intentional`;
|
|
627
|
+
return {
|
|
628
|
+
content: [{
|
|
629
|
+
type: "text",
|
|
630
|
+
text: warningText,
|
|
631
|
+
}],
|
|
632
|
+
};
|
|
633
|
+
}
|
|
634
|
+
logger.debug('Calling v3.insight.remove', {
|
|
635
|
+
insightId: args.insightId,
|
|
636
|
+
insightName,
|
|
637
|
+
workspaceId,
|
|
638
|
+
workspaceName
|
|
639
|
+
});
|
|
640
|
+
// Call v3.insight.remove endpoint
|
|
641
|
+
await context.hailer.request('v3.insight.remove', [args.insightId]);
|
|
642
|
+
logger.debug('Insight removed successfully', {
|
|
643
|
+
insightId: args.insightId,
|
|
644
|
+
insightName
|
|
645
|
+
});
|
|
646
|
+
let responseText = `โ
**Insight Removed Successfully**\n\n`;
|
|
647
|
+
responseText += `**Insight:** ${insightName}\n`;
|
|
648
|
+
responseText += `**Insight ID:** \`${args.insightId}\`\n`;
|
|
649
|
+
responseText += `**Workspace:** ${workspaceName} (\`${workspaceId}\`)\n\n`;
|
|
650
|
+
responseText += `โ ๏ธ **The insight, its SQL definition, and all associated data have been permanently deleted.**\n\n`;
|
|
651
|
+
responseText += `๐ก Use \`list_insights\` to see remaining insights.`;
|
|
652
|
+
return {
|
|
653
|
+
content: [{
|
|
654
|
+
type: "text",
|
|
655
|
+
text: responseText,
|
|
656
|
+
}],
|
|
657
|
+
};
|
|
658
|
+
}
|
|
659
|
+
catch (error) {
|
|
660
|
+
logger.error("Error removing insight", error);
|
|
661
|
+
let errorMessage = 'Unknown error occurred';
|
|
662
|
+
if (error instanceof Error) {
|
|
663
|
+
errorMessage = error.message;
|
|
664
|
+
}
|
|
665
|
+
else if (typeof error === 'object' && error !== null) {
|
|
666
|
+
try {
|
|
667
|
+
errorMessage = JSON.stringify(error, null, 2);
|
|
668
|
+
}
|
|
669
|
+
catch {
|
|
670
|
+
errorMessage = String(error);
|
|
671
|
+
}
|
|
672
|
+
}
|
|
673
|
+
else {
|
|
674
|
+
errorMessage = String(error);
|
|
675
|
+
}
|
|
676
|
+
return {
|
|
677
|
+
content: [{
|
|
678
|
+
type: "text",
|
|
679
|
+
text: `โ **Error removing insight**\n\n**Error:** ${errorMessage}\n\n**Common Issues:**\n- Insight ID not found\n- Permission denied\n- Insight already deleted\n- Use \`list_insights\` to verify insight ID`,
|
|
680
|
+
}],
|
|
681
|
+
};
|
|
682
|
+
}
|
|
683
|
+
}
|
|
684
|
+
};
|
|
685
|
+
// ============================================================================
|
|
686
|
+
// LIST INSIGHTS TOOL
|
|
687
|
+
// ============================================================================
|
|
688
|
+
const listInsightsDescription = `๐งช [PLAYGROUND] List Insights - View all insights in workspace
|
|
689
|
+
|
|
690
|
+
**What are Insights?**
|
|
691
|
+
Insights are SQL-like reports over Hailer workflow data. They allow querying activities like database tables.
|
|
692
|
+
|
|
693
|
+
**Purpose**: List all insights in the workspace to find insight IDs.
|
|
694
|
+
|
|
695
|
+
**Example**:
|
|
696
|
+
\`\`\`javascript
|
|
697
|
+
list_insights({
|
|
698
|
+
workspaceId: "optional-workspace-id"
|
|
699
|
+
})
|
|
700
|
+
\`\`\`
|
|
701
|
+
|
|
702
|
+
**Response includes**:
|
|
703
|
+
- Insight ID and name
|
|
704
|
+
- SQL query
|
|
705
|
+
- Sources (workflows being queried)
|
|
706
|
+
- Public/private status
|
|
707
|
+
- Created/updated timestamps`;
|
|
708
|
+
exports.listInsightsTool = {
|
|
709
|
+
name: 'list_insights',
|
|
710
|
+
group: tool_registry_1.ToolGroup.PLAYGROUND,
|
|
711
|
+
description: listInsightsDescription,
|
|
712
|
+
schema: zod_1.z.object({
|
|
713
|
+
workspaceId: zod_1.z
|
|
714
|
+
.string()
|
|
715
|
+
.optional()
|
|
716
|
+
.describe("Optional workspace ID or name - defaults to current workspace"),
|
|
717
|
+
}),
|
|
718
|
+
async execute(args, context) {
|
|
719
|
+
logger.debug('Listing insights', {
|
|
720
|
+
workspaceId: args.workspaceId,
|
|
721
|
+
apiKey: context.apiKey.substring(0, 8) + '...'
|
|
722
|
+
});
|
|
723
|
+
try {
|
|
724
|
+
if (!context.workspaceCache) {
|
|
725
|
+
return {
|
|
726
|
+
content: [{
|
|
727
|
+
type: "text",
|
|
728
|
+
text: "โ Workspace cache not available",
|
|
729
|
+
}],
|
|
730
|
+
};
|
|
731
|
+
}
|
|
732
|
+
// Resolve workspace ID
|
|
733
|
+
const workspaceId = args.workspaceId
|
|
734
|
+
? (0, workspace_cache_1.resolveWorkspaceId)(context.workspaceCache, args.workspaceId)
|
|
735
|
+
: context.workspaceCache.currentWorkspace._id;
|
|
736
|
+
if (!workspaceId) {
|
|
737
|
+
return {
|
|
738
|
+
content: [{
|
|
739
|
+
type: "text",
|
|
740
|
+
text: `โ Could not resolve workspace: ${args.workspaceId}`,
|
|
741
|
+
}],
|
|
742
|
+
};
|
|
743
|
+
}
|
|
744
|
+
logger.debug('Calling v3.insight.list', { workspaceId });
|
|
745
|
+
// Call v3.insight.list endpoint
|
|
746
|
+
const result = await context.hailer.request('v3.insight.list', [workspaceId]);
|
|
747
|
+
// API returns array directly for list_insights
|
|
748
|
+
const insights = Array.isArray(result) ? result : (result.details || result.insights || []);
|
|
749
|
+
logger.debug('Insights retrieved', {
|
|
750
|
+
count: insights.length || 0,
|
|
751
|
+
isArray: Array.isArray(result),
|
|
752
|
+
responseKeys: Array.isArray(result) ? `array[${result.length}]` : Object.keys(result).join(',')
|
|
753
|
+
});
|
|
754
|
+
// Format output
|
|
755
|
+
let responseText = `๐ **Insights Found** (${insights.length || 0} total)\n\n`;
|
|
756
|
+
if (!insights || insights.length === 0) {
|
|
757
|
+
responseText += `No insights found in this workspace.\n\n`;
|
|
758
|
+
responseText += `๐ก Use \`create_insight\` to create a new SQL-like report.`;
|
|
759
|
+
}
|
|
760
|
+
else {
|
|
761
|
+
insights.forEach((insight, index) => {
|
|
762
|
+
responseText += `${index + 1}. **${insight.name}**\n`;
|
|
763
|
+
responseText += ` - Insight ID: \`${insight._id}\`\n`;
|
|
764
|
+
responseText += ` - Public: ${insight.public ? 'Yes' : 'No'}\n`;
|
|
765
|
+
responseText += ` - Sources: ${insight.sources.length} workflow(s)\n`;
|
|
766
|
+
responseText += ` - Query: \`${insight.query.substring(0, 80)}${insight.query.length > 80 ? '...' : ''}\`\n\n`;
|
|
767
|
+
});
|
|
768
|
+
responseText += `๐ก **Next Steps:**\n`;
|
|
769
|
+
responseText += `- Use \`get_insight_data\` to execute an insight\n`;
|
|
770
|
+
responseText += `- Use \`preview_insight\` to test query changes\n`;
|
|
771
|
+
responseText += `- Use \`remove_insight\` to delete an insight\n`;
|
|
772
|
+
}
|
|
773
|
+
return {
|
|
774
|
+
content: [{
|
|
775
|
+
type: "text",
|
|
776
|
+
text: responseText,
|
|
777
|
+
}],
|
|
778
|
+
};
|
|
779
|
+
}
|
|
780
|
+
catch (error) {
|
|
781
|
+
logger.error("Error listing insights", error);
|
|
782
|
+
let errorMessage = 'Unknown error occurred';
|
|
783
|
+
if (error instanceof Error) {
|
|
784
|
+
errorMessage = error.message;
|
|
785
|
+
}
|
|
786
|
+
else if (typeof error === 'object' && error !== null) {
|
|
787
|
+
try {
|
|
788
|
+
errorMessage = JSON.stringify(error, null, 2);
|
|
789
|
+
}
|
|
790
|
+
catch {
|
|
791
|
+
errorMessage = String(error);
|
|
792
|
+
}
|
|
793
|
+
}
|
|
794
|
+
else {
|
|
795
|
+
errorMessage = String(error);
|
|
796
|
+
}
|
|
797
|
+
return {
|
|
798
|
+
content: [{
|
|
799
|
+
type: "text",
|
|
800
|
+
text: `โ **Error listing insights**\n\n**Error:** ${errorMessage}\n\n**Tips:**\n- Check workspace ID is valid\n- Verify you have permission to list insights`,
|
|
801
|
+
}],
|
|
802
|
+
};
|
|
803
|
+
}
|
|
804
|
+
}
|
|
805
|
+
};
|
|
806
|
+
//# sourceMappingURL=insight.js.map
|