@hailer/mcp 0.1.6 โ 0.1.9
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/agents/agent-dmitri-activity-crud.md +3 -1
- package/.claude/agents/agent-giuseppe-app-builder.md +11 -12
- package/.claude/agents/agent-kenji-data-reader.md +5 -3
- package/.claude/hooks/sync-marketplace-agents.cjs +117 -56
- package/.claude/skills/hailer-app-builder/SKILL.md +506 -0
- package/.claude/skills/publish-hailer-app/SKILL.md +169 -0
- package/.claude/skills/tool-parameter-usage/SKILL.md +112 -0
- package/CHANGELOG.md +20 -0
- package/CLAUDE.md +37 -16
- package/REFACTOR_STATUS.md +127 -0
- package/dist/cli.js +0 -0
- package/dist/client/agents/base.d.ts +202 -0
- package/dist/client/agents/base.js +737 -0
- package/dist/client/agents/definitions.d.ts +53 -0
- package/dist/client/agents/definitions.js +178 -0
- package/dist/client/agents/orchestrator.d.ts +119 -0
- package/dist/client/agents/orchestrator.js +760 -0
- package/dist/client/agents/specialist.d.ts +86 -0
- package/dist/client/agents/specialist.js +340 -0
- package/dist/client/bot-manager.d.ts +44 -0
- package/dist/client/bot-manager.js +173 -0
- package/dist/client/chat-agent-daemon.d.ts +464 -0
- package/dist/client/chat-agent-daemon.js +1774 -0
- package/dist/client/daemon-factory.d.ts +106 -0
- package/dist/client/daemon-factory.js +301 -0
- package/dist/client/factory.d.ts +107 -0
- package/dist/client/factory.js +304 -0
- package/dist/client/index.d.ts +17 -0
- package/dist/client/index.js +38 -0
- package/dist/client/multi-bot-manager.d.ts +18 -0
- package/dist/client/multi-bot-manager.js +88 -1
- package/dist/client/orchestrator-daemon.d.ts +87 -0
- package/dist/client/orchestrator-daemon.js +444 -0
- package/dist/client/services/agent-registry.d.ts +108 -0
- package/dist/client/services/agent-registry.js +630 -0
- package/dist/client/services/conversation-manager.d.ts +50 -0
- package/dist/client/services/conversation-manager.js +136 -0
- package/dist/client/services/mcp-client.d.ts +48 -0
- package/dist/client/services/mcp-client.js +105 -0
- package/dist/client/services/message-classifier.d.ts +37 -0
- package/dist/client/services/message-classifier.js +187 -0
- package/dist/client/services/message-formatter.d.ts +84 -0
- package/dist/client/services/message-formatter.js +353 -0
- package/dist/client/services/session-logger.d.ts +106 -0
- package/dist/client/services/session-logger.js +446 -0
- package/dist/client/services/tool-executor.d.ts +41 -0
- package/dist/client/services/tool-executor.js +169 -0
- package/dist/client/services/workspace-schema-cache.d.ts +149 -0
- package/dist/client/services/workspace-schema-cache.js +732 -0
- package/dist/client/specialist-daemon.d.ts +77 -0
- package/dist/client/specialist-daemon.js +197 -0
- package/dist/client/specialists.d.ts +53 -0
- package/dist/client/specialists.js +178 -0
- package/dist/client/tool-schema-loader.d.ts +4 -3
- package/dist/client/tool-schema-loader.js +54 -8
- package/dist/client/types.d.ts +283 -55
- package/dist/client/types.js +113 -2
- package/dist/config.d.ts +1 -1
- package/dist/config.js +1 -1
- package/dist/core.d.ts +10 -2
- package/dist/core.js +43 -27
- package/dist/lib/logger.js +15 -3
- package/dist/mcp/UserContextCache.js +2 -2
- package/dist/mcp/hailer-clients.js +5 -5
- package/dist/mcp/signal-handler.js +27 -5
- package/dist/mcp/tools/activity.js +137 -65
- package/dist/mcp/tools/app-core.js +4 -140
- package/dist/mcp/tools/app-marketplace.js +15 -260
- package/dist/mcp/tools/app-member.js +2 -73
- package/dist/mcp/tools/app-scaffold.js +146 -87
- package/dist/mcp/tools/discussion.js +348 -73
- package/dist/mcp/tools/insight.js +74 -190
- package/dist/mcp/tools/workflow.js +20 -94
- package/dist/mcp/utils/hailer-api-client.d.ts +4 -2
- package/dist/mcp/utils/hailer-api-client.js +24 -10
- package/dist/mcp-server.d.ts +4 -0
- package/dist/mcp-server.js +24 -4
- package/dist/routes/agents.d.ts +44 -0
- package/dist/routes/agents.js +311 -0
- package/dist/services/agent-credential-store.d.ts +73 -0
- package/dist/services/agent-credential-store.js +212 -0
- package/lineup-manager/dist/assets/index-8ce6041d.css +1 -0
- package/lineup-manager/dist/assets/index-e168f265.js +600 -0
- package/lineup-manager/dist/index.html +15 -0
- package/lineup-manager/dist/manifest.json +17 -0
- package/lineup-manager/dist/vite.svg +1 -0
- package/package.json +1 -1
- package/dist/client/adaptive-documentation-bot.d.ts +0 -106
- package/dist/client/adaptive-documentation-bot.js +0 -464
- package/dist/client/adaptive-documentation-types.d.ts +0 -66
- package/dist/client/adaptive-documentation-types.js +0 -9
- package/dist/client/agent-activity-bot.d.ts +0 -51
- package/dist/client/agent-activity-bot.js +0 -166
- package/dist/client/agent-tracker.d.ts +0 -499
- package/dist/client/agent-tracker.js +0 -659
- package/dist/client/description-updater.d.ts +0 -56
- package/dist/client/description-updater.js +0 -259
- package/dist/client/log-parser.d.ts +0 -72
- package/dist/client/log-parser.js +0 -387
- package/dist/client/mcp-assistant.d.ts +0 -21
- package/dist/client/mcp-assistant.js +0 -58
- package/dist/client/mcp-client.d.ts +0 -50
- package/dist/client/mcp-client.js +0 -538
- package/dist/client/message-processor.d.ts +0 -35
- package/dist/client/message-processor.js +0 -357
- package/dist/client/providers/anthropic-provider.d.ts +0 -19
- package/dist/client/providers/anthropic-provider.js +0 -645
- package/dist/client/providers/assistant-provider.d.ts +0 -17
- package/dist/client/providers/assistant-provider.js +0 -51
- package/dist/client/providers/llm-provider.d.ts +0 -47
- package/dist/client/providers/llm-provider.js +0 -367
- package/dist/client/providers/openai-provider.d.ts +0 -23
- package/dist/client/providers/openai-provider.js +0 -630
- package/dist/client/simple-llm-caller.d.ts +0 -19
- package/dist/client/simple-llm-caller.js +0 -100
- package/dist/client/skill-generator.d.ts +0 -81
- package/dist/client/skill-generator.js +0 -386
- package/dist/client/test-adaptive-bot.d.ts +0 -9
- package/dist/client/test-adaptive-bot.js +0 -82
- package/dist/client/token-pricing.d.ts +0 -38
- package/dist/client/token-pricing.js +0 -127
- package/dist/client/token-tracker.d.ts +0 -232
- package/dist/client/token-tracker.js +0 -457
- package/dist/client/token-usage-bot.d.ts +0 -53
- package/dist/client/token-usage-bot.js +0 -153
- package/dist/client/tool-executor.d.ts +0 -69
- package/dist/client/tool-executor.js +0 -159
- package/dist/lib/materialize.d.ts +0 -3
- package/dist/lib/materialize.js +0 -101
- package/dist/lib/normalizedName.d.ts +0 -7
- package/dist/lib/normalizedName.js +0 -48
- package/dist/lib/terminal-prompt.d.ts +0 -9
- package/dist/lib/terminal-prompt.js +0 -108
- package/dist/mcp/tools/skill.d.ts +0 -10
- package/dist/mcp/tools/skill.js +0 -279
- package/dist/mcp/tools/workflow-template.d.ts +0 -19
- package/dist/mcp/tools/workflow-template.js +0 -822
|
@@ -21,31 +21,65 @@ const logger = (0, logger_1.createLogger)({ component: 'insight-tools' });
|
|
|
21
21
|
// ============================================================================
|
|
22
22
|
/**
|
|
23
23
|
* Field definition schema - either meta field or custom fieldId
|
|
24
|
+
* Accepts both 'id' and 'fieldId' for flexibility (LLMs often use 'id')
|
|
24
25
|
*/
|
|
25
26
|
const fieldSchema = zod_1.z.object({
|
|
26
27
|
name: zod_1.z.string().describe("Column name in SQL query"),
|
|
27
|
-
|
|
28
|
-
zod_1.z.
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
28
|
+
// Accept both 'id' and 'fieldId' - will be normalized to 'fieldId'
|
|
29
|
+
id: zod_1.z.string().optional().describe("Field ID (alias for fieldId)"),
|
|
30
|
+
fieldId: zod_1.z.string().optional().describe("Custom field ID from workflow"),
|
|
31
|
+
meta: zod_1.z.enum([
|
|
32
|
+
'_id',
|
|
33
|
+
'uid',
|
|
34
|
+
'team',
|
|
35
|
+
'createdBy',
|
|
36
|
+
'name',
|
|
37
|
+
'created',
|
|
38
|
+
'updated',
|
|
39
|
+
'phaseId',
|
|
40
|
+
'phaseName',
|
|
41
|
+
'phaseLastMove',
|
|
42
|
+
'workflowId',
|
|
43
|
+
'workflowName',
|
|
44
|
+
'priority'
|
|
45
|
+
]).optional().describe("Built-in activity property (alternative to fieldId)"),
|
|
46
|
+
}).refine((data) => data.meta || data.fieldId || data.id, { message: "Field must have either 'meta', 'fieldId', or 'id'" });
|
|
47
|
+
/**
|
|
48
|
+
* Sanitize field name to be SQL-identifier safe (no spaces, special chars)
|
|
49
|
+
*/
|
|
50
|
+
function sanitizeFieldName(name) {
|
|
51
|
+
// Convert to camelCase: "Injury Type" -> "InjuryType", "Expected Recovery" -> "ExpectedRecovery"
|
|
52
|
+
return name
|
|
53
|
+
.split(/\s+/)
|
|
54
|
+
.map((word, index) => {
|
|
55
|
+
if (index === 0)
|
|
56
|
+
return word.charAt(0).toLowerCase() + word.slice(1);
|
|
57
|
+
return word.charAt(0).toUpperCase() + word.slice(1);
|
|
58
|
+
})
|
|
59
|
+
.join('')
|
|
60
|
+
.replace(/[^a-zA-Z0-9_]/g, ''); // Remove any remaining special chars
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Normalize field definitions: convert 'id' to 'fieldId' and sanitize names
|
|
64
|
+
*/
|
|
65
|
+
function normalizeFields(sources) {
|
|
66
|
+
return sources.map(source => ({
|
|
67
|
+
...source,
|
|
68
|
+
fields: source.fields.map(field => {
|
|
69
|
+
let normalized = { ...field };
|
|
70
|
+
// Sanitize field name (remove spaces, make SQL-safe)
|
|
71
|
+
if (normalized.name) {
|
|
72
|
+
normalized.name = sanitizeFieldName(normalized.name);
|
|
73
|
+
}
|
|
74
|
+
// If 'id' is provided but not 'fieldId', use 'id' as 'fieldId'
|
|
75
|
+
if (field.id && !field.fieldId && !field.meta) {
|
|
76
|
+
const { id, ...rest } = normalized;
|
|
77
|
+
return { ...rest, fieldId: id };
|
|
78
|
+
}
|
|
79
|
+
return normalized;
|
|
80
|
+
}),
|
|
81
|
+
}));
|
|
82
|
+
}
|
|
49
83
|
/**
|
|
50
84
|
* Source definition schema - workflow as SQL table
|
|
51
85
|
*/
|
|
@@ -57,22 +91,7 @@ const sourceSchema = zod_1.z.object({
|
|
|
57
91
|
// ============================================================================
|
|
58
92
|
// CREATE INSIGHT TOOL
|
|
59
93
|
// ============================================================================
|
|
60
|
-
const createInsightDescription =
|
|
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`;
|
|
94
|
+
const createInsightDescription = `Create SQL insight over workflow data (workflows=tables, activities=rows, fields=columns)`;
|
|
76
95
|
exports.createInsightTool = {
|
|
77
96
|
name: 'create_insight',
|
|
78
97
|
group: tool_registry_1.ToolGroup.PLAYGROUND,
|
|
@@ -118,11 +137,13 @@ exports.createInsightTool = {
|
|
|
118
137
|
name: args.name,
|
|
119
138
|
sourcesCount: args.sources.length
|
|
120
139
|
});
|
|
140
|
+
// Normalize sources (convert 'id' to 'fieldId' if needed)
|
|
141
|
+
const normalizedSources = normalizeFields(args.sources);
|
|
121
142
|
// Build insight payload
|
|
122
143
|
const insightData = {
|
|
123
144
|
name: args.name,
|
|
124
145
|
public: args.public || false,
|
|
125
|
-
sources:
|
|
146
|
+
sources: normalizedSources,
|
|
126
147
|
query: args.query,
|
|
127
148
|
};
|
|
128
149
|
// Call v3.insight.create endpoint
|
|
@@ -233,21 +254,7 @@ exports.createInsightTool = {
|
|
|
233
254
|
// ============================================================================
|
|
234
255
|
// PREVIEW INSIGHT TOOL
|
|
235
256
|
// ============================================================================
|
|
236
|
-
const previewInsightDescription =
|
|
237
|
-
|
|
238
|
-
โ ๏ธ **MANDATORY: YOU MUST LOAD SKILL FIRST**
|
|
239
|
-
**BEFORE calling this tool, you are REQUIRED to:**
|
|
240
|
-
1. Load the skill: \`get_skill({ skillName: "preview-insight-skill" })\`
|
|
241
|
-
2. Read the debugging tips and security notes
|
|
242
|
-
3. Understand the SQL testing patterns
|
|
243
|
-
**FAILURE TO LOAD THE SKILL FIRST IS AN ERROR**
|
|
244
|
-
|
|
245
|
-
**Purpose**: Debug SQL syntax, test JOINs, verify field mappings without creating insight
|
|
246
|
-
|
|
247
|
-
**Required Parameters**:
|
|
248
|
-
- sources: Same format as create_insight (name, workflowId, fields)
|
|
249
|
-
- query: SQL query to test
|
|
250
|
-
- insightId (optional): Test changes to existing insight`;
|
|
257
|
+
const previewInsightDescription = `Test SQL query on sample data before creating/updating insight`;
|
|
251
258
|
exports.previewInsightTool = {
|
|
252
259
|
name: 'preview_insight',
|
|
253
260
|
group: tool_registry_1.ToolGroup.PLAYGROUND,
|
|
@@ -288,9 +295,11 @@ exports.previewInsightTool = {
|
|
|
288
295
|
sourcesCount: args.sources.length,
|
|
289
296
|
insightId: args.insightId
|
|
290
297
|
});
|
|
298
|
+
// Normalize sources (convert 'id' to 'fieldId' if needed)
|
|
299
|
+
const normalizedSources = normalizeFields(args.sources);
|
|
291
300
|
// Build preview payload
|
|
292
301
|
const previewData = {
|
|
293
|
-
sources:
|
|
302
|
+
sources: normalizedSources,
|
|
294
303
|
query: args.query,
|
|
295
304
|
...(args.insightId && { insightId: args.insightId }),
|
|
296
305
|
};
|
|
@@ -362,33 +371,7 @@ exports.previewInsightTool = {
|
|
|
362
371
|
// ============================================================================
|
|
363
372
|
// GET INSIGHT DATA TOOL
|
|
364
373
|
// ============================================================================
|
|
365
|
-
const getInsightDataDescription =
|
|
366
|
-
|
|
367
|
-
**What is Get Insight Data?**
|
|
368
|
-
Executes a saved insight's SQL query and returns the complete results. Unlike preview (limited to ~20 rows), this returns all matching activities.
|
|
369
|
-
|
|
370
|
-
**When to Use**:
|
|
371
|
-
- Get full results from a saved insight
|
|
372
|
-
- Export insight data
|
|
373
|
-
- Verify insight after creation
|
|
374
|
-
- Check updated data after changes
|
|
375
|
-
|
|
376
|
-
**Example - Basic Usage**:
|
|
377
|
-
\`\`\`javascript
|
|
378
|
-
get_insight_data({
|
|
379
|
-
insightId: '<insight-id>'
|
|
380
|
-
})
|
|
381
|
-
\`\`\`
|
|
382
|
-
|
|
383
|
-
**Update Option**:
|
|
384
|
-
- \`update: false\` (default) - Returns cached results (faster)
|
|
385
|
-
- \`update: true\` - Recalculates from current activity data (slower but fresh)
|
|
386
|
-
|
|
387
|
-
**Tips**:
|
|
388
|
-
- Use \`update: true\` if activity data has changed
|
|
389
|
-
- Results can be large - may take time for big datasets
|
|
390
|
-
- Use \`preview_insight\` first to test queries
|
|
391
|
-
- Get insight ID from \`create_insight\` or \`list_insights\``;
|
|
374
|
+
const getInsightDataDescription = `Execute insight and get results`;
|
|
392
375
|
exports.getInsightDataTool = {
|
|
393
376
|
name: 'get_insight_data',
|
|
394
377
|
group: tool_registry_1.ToolGroup.PLAYGROUND,
|
|
@@ -484,51 +467,7 @@ exports.getInsightDataTool = {
|
|
|
484
467
|
// ============================================================================
|
|
485
468
|
// UPDATE INSIGHT TOOL
|
|
486
469
|
// ============================================================================
|
|
487
|
-
const updateInsightDescription =
|
|
488
|
-
|
|
489
|
-
**What it does:**
|
|
490
|
-
Updates an existing insight's properties (name, query, sources, visibility).
|
|
491
|
-
|
|
492
|
-
**Required Parameters:**
|
|
493
|
-
- insightId - The insight ID to update
|
|
494
|
-
|
|
495
|
-
**Optional Parameters (include only what you want to change):**
|
|
496
|
-
- name - New insight name
|
|
497
|
-
- public - Change visibility (true/false)
|
|
498
|
-
- sources - Updated workflow sources
|
|
499
|
-
- query - Updated SQL query
|
|
500
|
-
|
|
501
|
-
**Example - Update name only:**
|
|
502
|
-
\`\`\`javascript
|
|
503
|
-
update_insight({
|
|
504
|
-
insightId: '<insight-id>',
|
|
505
|
-
name: 'New Insight Name'
|
|
506
|
-
})
|
|
507
|
-
\`\`\`
|
|
508
|
-
|
|
509
|
-
**Example - Update query:**
|
|
510
|
-
\`\`\`javascript
|
|
511
|
-
update_insight({
|
|
512
|
-
insightId: '<insight-id>',
|
|
513
|
-
query: 'SELECT * FROM players WHERE position = "Forward"'
|
|
514
|
-
})
|
|
515
|
-
\`\`\`
|
|
516
|
-
|
|
517
|
-
**Example - Full update:**
|
|
518
|
-
\`\`\`javascript
|
|
519
|
-
update_insight({
|
|
520
|
-
insightId: '<insight-id>',
|
|
521
|
-
name: 'Updated Insight',
|
|
522
|
-
public: true,
|
|
523
|
-
sources: [{ name: 'p', workflowId: 'xxx', fields: [...] }],
|
|
524
|
-
query: 'SELECT * FROM p'
|
|
525
|
-
})
|
|
526
|
-
\`\`\`
|
|
527
|
-
|
|
528
|
-
**Tips:**
|
|
529
|
-
- Use \`preview_insight\` to test query changes before updating
|
|
530
|
-
- Use \`list_insights\` to find insight IDs
|
|
531
|
-
- Only include fields you want to change`;
|
|
470
|
+
const updateInsightDescription = `Update existing insight (name, query, sources, or visibility)`;
|
|
532
471
|
exports.updateInsightTool = {
|
|
533
472
|
name: 'update_insight',
|
|
534
473
|
group: tool_registry_1.ToolGroup.PLAYGROUND,
|
|
@@ -572,7 +511,7 @@ exports.updateInsightTool = {
|
|
|
572
511
|
updateData.public = args.public;
|
|
573
512
|
}
|
|
574
513
|
if (args.sources !== undefined) {
|
|
575
|
-
updateData.sources = args.sources;
|
|
514
|
+
updateData.sources = normalizeFields(args.sources);
|
|
576
515
|
}
|
|
577
516
|
if (args.query !== undefined) {
|
|
578
517
|
updateData.query = args.query;
|
|
@@ -672,46 +611,7 @@ exports.updateInsightTool = {
|
|
|
672
611
|
// ============================================================================
|
|
673
612
|
// REMOVE INSIGHT TOOL
|
|
674
613
|
// ============================================================================
|
|
675
|
-
const removeInsightDescription =
|
|
676
|
-
|
|
677
|
-
โ ๏ธ **MANDATORY: GATHER COMPLETE CONTEXT BEFORE CALLING THIS TOOL**
|
|
678
|
-
**BEFORE calling this tool, you are REQUIRED to:**
|
|
679
|
-
1. Load the skill: \`get_skill({ skillName: "remove-insight-skill" })\`
|
|
680
|
-
2. Fetch insight details with \`list_insights\` to get:
|
|
681
|
-
- Insight name and ID
|
|
682
|
-
- Workspace ID and name
|
|
683
|
-
- SQL query
|
|
684
|
-
- Source workflows
|
|
685
|
-
- Number of sources
|
|
686
|
-
3. Show comprehensive confirmation message including:
|
|
687
|
-
- Workspace ID and name
|
|
688
|
-
- Insight ID and name
|
|
689
|
-
- What will be deleted (definition, results, permissions, discussion)
|
|
690
|
-
- Sources being queried (workflows)
|
|
691
|
-
- Clear irreversibility warning
|
|
692
|
-
4. Wait for explicit user confirmation
|
|
693
|
-
**FAILURE TO GATHER AND SHOW THIS CONTEXT IS AN ERROR**
|
|
694
|
-
|
|
695
|
-
**Required**: insightId
|
|
696
|
-
**Permission**: Workspace administrator
|
|
697
|
-
|
|
698
|
-
**What Gets Deleted**:
|
|
699
|
-
- Insight definition (sources, query, name)
|
|
700
|
-
- Saved query results
|
|
701
|
-
- Insight permissions
|
|
702
|
-
- Associated discussion
|
|
703
|
-
|
|
704
|
-
**Example**:
|
|
705
|
-
\`\`\`javascript
|
|
706
|
-
remove_insight({
|
|
707
|
-
insightId: '<insight-id>'
|
|
708
|
-
})
|
|
709
|
-
\`\`\`
|
|
710
|
-
|
|
711
|
-
**Tips**:
|
|
712
|
-
- Use \`list_insights\` to find insight IDs
|
|
713
|
-
- Use \`get_insight_data\` to verify before deleting
|
|
714
|
-
- Operation cannot be undone - data is permanently lost`;
|
|
614
|
+
const removeInsightDescription = `Delete insight permanently`;
|
|
715
615
|
exports.removeInsightTool = {
|
|
716
616
|
name: 'remove_insight',
|
|
717
617
|
group: tool_registry_1.ToolGroup.NUCLEAR,
|
|
@@ -839,26 +739,7 @@ exports.removeInsightTool = {
|
|
|
839
739
|
// ============================================================================
|
|
840
740
|
// LIST INSIGHTS TOOL
|
|
841
741
|
// ============================================================================
|
|
842
|
-
const listInsightsDescription =
|
|
843
|
-
|
|
844
|
-
**What are Insights?**
|
|
845
|
-
Insights are SQL-like reports over Hailer workflow data. They allow querying activities like database tables.
|
|
846
|
-
|
|
847
|
-
**Purpose**: List all insights in the workspace to find insight IDs.
|
|
848
|
-
|
|
849
|
-
**Example**:
|
|
850
|
-
\`\`\`javascript
|
|
851
|
-
list_insights({
|
|
852
|
-
workspaceId: "optional-workspace-id"
|
|
853
|
-
})
|
|
854
|
-
\`\`\`
|
|
855
|
-
|
|
856
|
-
**Response includes**:
|
|
857
|
-
- Insight ID and name
|
|
858
|
-
- SQL query
|
|
859
|
-
- Sources (workflows being queried)
|
|
860
|
-
- Public/private status
|
|
861
|
-
- Created/updated timestamps`;
|
|
742
|
+
const listInsightsDescription = `List all insights in workspace`;
|
|
862
743
|
exports.listInsightsTool = {
|
|
863
744
|
name: 'list_insights',
|
|
864
745
|
group: tool_registry_1.ToolGroup.PLAYGROUND,
|
|
@@ -901,8 +782,11 @@ exports.listInsightsTool = {
|
|
|
901
782
|
responseText += `${index + 1}. **${insight.name}**\n`;
|
|
902
783
|
responseText += ` - Insight ID: \`${insight._id}\`\n`;
|
|
903
784
|
responseText += ` - Public: ${insight.public ? 'Yes' : 'No'}\n`;
|
|
904
|
-
|
|
905
|
-
|
|
785
|
+
// Show source names (table aliases) - critical for SQL debugging
|
|
786
|
+
const sourceNames = insight.sources?.map((s) => s.name).join(', ') || 'none';
|
|
787
|
+
responseText += ` - Table names: \`${sourceNames}\` (use EXACTLY these in SQL FROM/JOIN)\n`;
|
|
788
|
+
responseText += ` - Sources: ${insight.sources?.length || 0} workflow(s)\n`;
|
|
789
|
+
responseText += ` - Query: \`${insight.query?.substring(0, 80)}${(insight.query?.length || 0) > 80 ? '...' : ''}\`\n\n`;
|
|
906
790
|
});
|
|
907
791
|
responseText += `๐ก **Next Steps:**\n`;
|
|
908
792
|
responseText += `- Use \`get_insight_data\` to execute an insight\n`;
|
|
@@ -60,6 +60,7 @@ exports.getWorkflowSchemaTool = {
|
|
|
60
60
|
schema: zod_1.z.object({
|
|
61
61
|
workflowId: zod_1.z.string().describe("Workflow ID to get schema from"),
|
|
62
62
|
phaseId: zod_1.z.string().describe("Phase ID to get schema from (use list_workflow_phases to get available phases)"),
|
|
63
|
+
compact: zod_1.z.boolean().optional().describe("Return compact summary instead of full field details (default: false)"),
|
|
63
64
|
}),
|
|
64
65
|
async execute(args, context) {
|
|
65
66
|
try {
|
|
@@ -78,6 +79,21 @@ exports.getWorkflowSchemaTool = {
|
|
|
78
79
|
// Get complete field definitions from workflow (includes keys and all metadata)
|
|
79
80
|
const workflowFields = workflow.fields || {};
|
|
80
81
|
const fieldsOrder = workflow.fieldsOrder || Object.keys(workflowFields);
|
|
82
|
+
// Compact mode: brief summary for chat agents WITH field IDs (required for insights)
|
|
83
|
+
if (args.compact) {
|
|
84
|
+
const fieldLines = fieldsOrder.map((fieldId) => {
|
|
85
|
+
const field = workflowFields[fieldId];
|
|
86
|
+
if (!field)
|
|
87
|
+
return null;
|
|
88
|
+
return `- ${field.label || 'Unnamed'} (${field.type}): fieldId="${fieldId}"`;
|
|
89
|
+
}).filter(Boolean);
|
|
90
|
+
return {
|
|
91
|
+
content: [{
|
|
92
|
+
type: "text",
|
|
93
|
+
text: `๐ **${workflow.name}** (workflowId: ${args.workflowId})\n\n**Fields:**\n${fieldLines.join('\n')}`,
|
|
94
|
+
}],
|
|
95
|
+
};
|
|
96
|
+
}
|
|
81
97
|
let responseText = `๐ **WORKFLOW SCHEMA** for "${workflow.name}":\n\n`;
|
|
82
98
|
if (schemaData.name) {
|
|
83
99
|
responseText += `**Name Field:**\n`;
|
|
@@ -336,45 +352,7 @@ exports.listWorkflowsTool = {
|
|
|
336
352
|
// ============================================================================
|
|
337
353
|
// TOOL 1: INSTALL WORKFLOW
|
|
338
354
|
// ============================================================================
|
|
339
|
-
const installWorkflowDescription =
|
|
340
|
-
|
|
341
|
-
โ ๏ธ **MANDATORY: YOU MUST LOAD SKILL FIRST**
|
|
342
|
-
**BEFORE calling this tool, you are REQUIRED to:**
|
|
343
|
-
1. Load the skill: \`get_skill({ skillName: "install-workflow-skill" })\`
|
|
344
|
-
2. Read the complete documentation
|
|
345
|
-
3. Follow the examples and patterns shown in the skill
|
|
346
|
-
**FAILURE TO LOAD THE SKILL FIRST IS AN ERROR**
|
|
347
|
-
|
|
348
|
-
โ ๏ธ COPY THIS EXACT STRUCTURE (modify values only):
|
|
349
|
-
\`\`\`json
|
|
350
|
-
{
|
|
351
|
-
"workflowTemplates": [{
|
|
352
|
-
"name": "My Workflow Name",
|
|
353
|
-
"fields": {
|
|
354
|
-
"_1000": { "label": "Title", "type": "text" }
|
|
355
|
-
},
|
|
356
|
-
"phases": {
|
|
357
|
-
"_2000": { "name": "To Do", "isInitial": true }
|
|
358
|
-
}
|
|
359
|
-
}]
|
|
360
|
-
}
|
|
361
|
-
\`\`\`
|
|
362
|
-
|
|
363
|
-
**CRITICAL RULES (breaking these causes API rejection):**
|
|
364
|
-
1. โ
MUST wrap in \`workflowTemplates\` array
|
|
365
|
-
2. โ
MUST use objects for fields/phases: \`{ "_1000": {...} }\` NOT arrays \`[{...}]\`
|
|
366
|
-
3. โ
MUST use \`label\` in fields (NOT "name")
|
|
367
|
-
4. โ
MUST use \`data\` for options (NOT "options")
|
|
368
|
-
5. โ
MUST use template IDs: \`_0001\`, \`_1000\`, \`_2000\` (underscore + 4 digits)
|
|
369
|
-
|
|
370
|
-
**Field properties allowed:**
|
|
371
|
-
- \`label\` (required) - Display name
|
|
372
|
-
- \`type\` (required) - Field type: text, date, numeric, textpredefinedoptions, activitylink
|
|
373
|
-
- \`key\` (recommended) - API key for readable names
|
|
374
|
-
- \`data\` (for dropdowns/links) - Array of options or workflow IDs
|
|
375
|
-
- \`required\` (optional) - Boolean
|
|
376
|
-
|
|
377
|
-
**Workflow = DB table, Fields = Columns, Activities = Rows**`;
|
|
355
|
+
const installWorkflowDescription = `Install workflow from template`;
|
|
378
356
|
const installWorkflowSchema = zod_1.z.object({
|
|
379
357
|
workspaceId: zod_1.z
|
|
380
358
|
.string()
|
|
@@ -534,27 +512,7 @@ exports.installWorkflowTool = {
|
|
|
534
512
|
// ============================================================================
|
|
535
513
|
// TOOL 2: REMOVE WORKFLOW
|
|
536
514
|
// ============================================================================
|
|
537
|
-
const removeWorkflowDescription =
|
|
538
|
-
|
|
539
|
-
โ ๏ธ **MANDATORY: GATHER COMPLETE CONTEXT BEFORE CALLING THIS TOOL**
|
|
540
|
-
**BEFORE calling this tool, you are REQUIRED to:**
|
|
541
|
-
1. Load the skill: \`get_skill({ skillName: "remove-workflow-skill" })\`
|
|
542
|
-
2. Fetch workflow details with \`list_workflows\` to get:
|
|
543
|
-
- Workflow name and ID
|
|
544
|
-
- Workspace ID and name
|
|
545
|
-
- Activity count
|
|
546
|
-
- Relationships (which workflows link to this one)
|
|
547
|
-
3. Show comprehensive confirmation message including:
|
|
548
|
-
- Workspace ID and name
|
|
549
|
-
- Workflow ID and name
|
|
550
|
-
- Exact count of activities that will be deleted
|
|
551
|
-
- Impact analysis - which other workflows will be affected (broken activity links)
|
|
552
|
-
- Clear irreversibility warning
|
|
553
|
-
4. Wait for explicit user confirmation
|
|
554
|
-
**FAILURE TO GATHER AND SHOW THIS CONTEXT IS AN ERROR**
|
|
555
|
-
|
|
556
|
-
**Required**: workflowId
|
|
557
|
-
**Permission**: Workspace administrator`;
|
|
515
|
+
const removeWorkflowDescription = `Delete workflow permanently`;
|
|
558
516
|
const removeWorkflowSchema = zod_1.z.object({
|
|
559
517
|
workflowId: zod_1.z
|
|
560
518
|
.string()
|
|
@@ -695,35 +653,7 @@ exports.removeWorkflowTool = {
|
|
|
695
653
|
// ============================================================================
|
|
696
654
|
// TOOL 3: UPDATE WORKFLOW FIELD
|
|
697
655
|
// ============================================================================
|
|
698
|
-
const updateWorkflowFieldDescription =
|
|
699
|
-
|
|
700
|
-
โ ๏ธ **MANDATORY: YOU MUST LOAD SKILL FIRST**
|
|
701
|
-
**BEFORE calling this tool, you are REQUIRED to:**
|
|
702
|
-
1. Load the skill: \`get_skill({ skillName: "update-workflow-field-skill" })\`
|
|
703
|
-
2. Read the examples and best practices
|
|
704
|
-
3. Understand function fields and field type restrictions
|
|
705
|
-
**FAILURE TO LOAD THE SKILL FIRST IS AN ERROR**
|
|
706
|
-
|
|
707
|
-
**Required Parameters**:
|
|
708
|
-
- workflowId: Workflow ID
|
|
709
|
-
- fieldId: Field ID to update
|
|
710
|
-
- fieldData: Properties to update (label, key, type, data, required, function, functionVariables, functionEnabled)
|
|
711
|
-
|
|
712
|
-
**IMPORTANT - Updating Labels Only:**
|
|
713
|
-
When updating ONLY the label (not the key), set \`autoGenerateKey: false\` to prevent key regeneration:
|
|
714
|
-
- โ
Correct: \`{ fieldData: { label: "Nationality" }, autoGenerateKey: false }\`
|
|
715
|
-
- โ Wrong: \`{ fieldData: { label: "Nationality" } }\` (will try to regenerate key and may fail)
|
|
716
|
-
|
|
717
|
-
**Auto-generate key**: When creating NEW keys, set label only and key auto-generates as camelCase ("Start Date" โ "startDate")
|
|
718
|
-
|
|
719
|
-
**Field Type Changes**: Avoid changing field types (text โ country, etc.) as this may be restricted by the API
|
|
720
|
-
|
|
721
|
-
**Use Cases**: Add keys, update labels, update activitylink targets, configure calculated fields, modify options
|
|
722
|
-
|
|
723
|
-
**Examples**:
|
|
724
|
-
- Update label only: \`update_workflow_field({ workflowId: "xxx", fieldId: "yyy", fieldData: { label: "New Label" }, autoGenerateKey: false })\`
|
|
725
|
-
- Update label and options: \`update_workflow_field({ workflowId: "xxx", fieldId: "yyy", fieldData: { label: "Status", data: ["Active", "Inactive"] }, autoGenerateKey: false })\`
|
|
726
|
-
- Add new key to field: \`update_workflow_field({ workflowId: "xxx", fieldId: "yyy", fieldData: { label: "My Field" }, autoGenerateKey: true })\` (generates key: "myField")`;
|
|
656
|
+
const updateWorkflowFieldDescription = `Update workflow field properties`;
|
|
727
657
|
const updateWorkflowFieldSchema = zod_1.z.object({
|
|
728
658
|
workflowId: zod_1.z
|
|
729
659
|
.string()
|
|
@@ -857,11 +787,7 @@ exports.updateWorkflowFieldTool = {
|
|
|
857
787
|
// ============================================================================
|
|
858
788
|
// TOOL 4: TEST FUNCTION FIELD
|
|
859
789
|
// ============================================================================
|
|
860
|
-
const testFunctionFieldDescription =
|
|
861
|
-
|
|
862
|
-
**Required**: activityId, fieldId, function (JavaScript accessing dep.variableName)
|
|
863
|
-
**Returns**: Result value, resolved dependencies, execution stats, or detailed errors
|
|
864
|
-
**Workflow**: Configure with update_workflow_field โ test โ fix โ re-test โ deploy`;
|
|
790
|
+
const testFunctionFieldDescription = `Test function field code against activity`;
|
|
865
791
|
const testFunctionFieldSchema = zod_1.z.object({
|
|
866
792
|
activityId: zod_1.z
|
|
867
793
|
.string()
|
|
@@ -72,12 +72,14 @@ export declare class HailerApiClient {
|
|
|
72
72
|
/**
|
|
73
73
|
* Join an activity's discussion by following the activity - uses Socket API
|
|
74
74
|
* This is the recommended way to join activity discussions.
|
|
75
|
-
* Returns true if now following
|
|
75
|
+
* Returns true if now following.
|
|
76
|
+
* IMPORTANT: activities.follow is a toggle, so if we accidentally toggle OFF, we toggle back ON.
|
|
76
77
|
*/
|
|
77
78
|
joinActivityDiscussion(activityId: string): Promise<boolean>;
|
|
78
79
|
/**
|
|
79
80
|
* Leave an activity's discussion by unfollowing the activity - uses Socket API
|
|
80
|
-
* Returns true if successfully unfollowed
|
|
81
|
+
* Returns true if successfully unfollowed.
|
|
82
|
+
* IMPORTANT: activities.follow is a toggle, so if we accidentally toggle ON, we toggle back OFF.
|
|
81
83
|
*/
|
|
82
84
|
leaveActivityDiscussion(activityId: string): Promise<boolean>;
|
|
83
85
|
/**
|
|
@@ -218,25 +218,39 @@ class HailerApiClient {
|
|
|
218
218
|
/**
|
|
219
219
|
* Join an activity's discussion by following the activity - uses Socket API
|
|
220
220
|
* This is the recommended way to join activity discussions.
|
|
221
|
-
* Returns true if now following
|
|
221
|
+
* Returns true if now following.
|
|
222
|
+
* IMPORTANT: activities.follow is a toggle, so if we accidentally toggle OFF, we toggle back ON.
|
|
222
223
|
*/
|
|
223
224
|
async joinActivityDiscussion(activityId) {
|
|
224
|
-
// activities.follow
|
|
225
|
-
|
|
226
|
-
//
|
|
225
|
+
// activities.follow TOGGLES the state:
|
|
226
|
+
// - returns true = now following (joined)
|
|
227
|
+
// - returns false = now NOT following (left)
|
|
227
228
|
const result = await this.request('activities.follow', [activityId]);
|
|
228
|
-
|
|
229
|
+
if (result === false) {
|
|
230
|
+
// Oops! We were already following and just toggled OFF (left).
|
|
231
|
+
// Toggle again to re-join.
|
|
232
|
+
this.logger.debug('Toggle resulted in unfollow, re-toggling to join', { activityId });
|
|
233
|
+
await this.request('activities.follow', [activityId]);
|
|
234
|
+
}
|
|
235
|
+
return true; // We're now following either way
|
|
229
236
|
}
|
|
230
237
|
/**
|
|
231
238
|
* Leave an activity's discussion by unfollowing the activity - uses Socket API
|
|
232
|
-
* Returns true if successfully unfollowed
|
|
239
|
+
* Returns true if successfully unfollowed.
|
|
240
|
+
* IMPORTANT: activities.follow is a toggle, so if we accidentally toggle ON, we toggle back OFF.
|
|
233
241
|
*/
|
|
234
242
|
async leaveActivityDiscussion(activityId) {
|
|
235
|
-
// activities.follow
|
|
236
|
-
|
|
237
|
-
//
|
|
243
|
+
// activities.follow TOGGLES the state:
|
|
244
|
+
// - returns true = now following (joined)
|
|
245
|
+
// - returns false = now NOT following (left)
|
|
238
246
|
const result = await this.request('activities.follow', [activityId]);
|
|
239
|
-
|
|
247
|
+
if (result === true) {
|
|
248
|
+
// Oops! We were NOT following and just toggled ON (joined).
|
|
249
|
+
// Toggle again to leave.
|
|
250
|
+
this.logger.debug('Toggle resulted in follow, re-toggling to leave', { activityId });
|
|
251
|
+
await this.request('activities.follow', [activityId]);
|
|
252
|
+
}
|
|
253
|
+
return true; // We're now NOT following either way
|
|
240
254
|
}
|
|
241
255
|
/**
|
|
242
256
|
* Leave a discussion directly - uses Socket API
|
package/dist/mcp-server.d.ts
CHANGED
package/dist/mcp-server.js
CHANGED
|
@@ -65,10 +65,13 @@ class MCPServerService {
|
|
|
65
65
|
});
|
|
66
66
|
res.on('finish', () => {
|
|
67
67
|
const duration = Date.now() - start;
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
duration
|
|
71
|
-
}
|
|
68
|
+
// Log at debug level for successful requests, info for errors
|
|
69
|
+
if (res.statusCode >= 400) {
|
|
70
|
+
requestLogger.info('Request failed', { statusCode: res.statusCode, duration });
|
|
71
|
+
}
|
|
72
|
+
else {
|
|
73
|
+
requestLogger.debug('Request completed', { statusCode: res.statusCode, duration });
|
|
74
|
+
}
|
|
72
75
|
});
|
|
73
76
|
}
|
|
74
77
|
// Add logger to request for route handlers
|
|
@@ -88,6 +91,22 @@ class MCPServerService {
|
|
|
88
91
|
};
|
|
89
92
|
res.json(health);
|
|
90
93
|
});
|
|
94
|
+
// Daemon status endpoint - monitor LLM context
|
|
95
|
+
this.app.get('/daemon/status', (_, res) => {
|
|
96
|
+
if (!this.config.getDaemonStatus) {
|
|
97
|
+
res.status(404).json({ error: 'Daemon mode not enabled' });
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
const status = this.config.getDaemonStatus();
|
|
101
|
+
if (!status) {
|
|
102
|
+
res.status(503).json({ error: 'Daemon not running' });
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
res.json({
|
|
106
|
+
timestamp: new Date().toISOString(),
|
|
107
|
+
daemons: status
|
|
108
|
+
});
|
|
109
|
+
});
|
|
91
110
|
// MCP Protocol endpoint - JSON-RPC 2.0 over SSE
|
|
92
111
|
this.app.post('/api/mcp', async (req, res) => {
|
|
93
112
|
req.logger.debug('MCP request received', { method: req.body?.method });
|
|
@@ -202,6 +221,7 @@ class MCPServerService {
|
|
|
202
221
|
this.logger.info('Routes configured', {
|
|
203
222
|
routes: [
|
|
204
223
|
'/health - Server health check',
|
|
224
|
+
'/daemon/status - Daemon context monitor',
|
|
205
225
|
'/api/mcp - MCP protocol (JSON-RPC 2.0)'
|
|
206
226
|
]
|
|
207
227
|
});
|