@hailer/mcp 1.0.23 → 1.0.25
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/.env.example +7 -26
- package/dist/app.js +10 -40
- package/dist/bot/chat-bot.js +1 -0
- package/dist/cli.d.ts +1 -9
- package/dist/cli.js +2 -71
- package/dist/config.d.ts +3 -96
- package/dist/config.js +6 -146
- package/dist/core.d.ts +0 -46
- package/dist/core.js +2 -351
- package/dist/lib/logger.js +2 -8
- package/dist/mcp/UserContextCache.js +10 -13
- package/dist/mcp/hailer-clients.js +11 -12
- package/dist/mcp/signal-handler.js +2 -18
- package/dist/mcp/tool-registry.d.ts +15 -4
- package/dist/mcp/tool-registry.js +24 -78
- package/dist/mcp/tools/activity.js +54 -6
- package/dist/mcp/tools/discussion.js +0 -25
- package/dist/mcp/tools/user.d.ts +4 -2
- package/dist/mcp/tools/user.js +48 -4
- package/dist/mcp/tools/workflow.js +40 -109
- package/dist/mcp/webhook-handler.d.ts +3 -64
- package/dist/mcp/webhook-handler.js +7 -214
- package/dist/mcp-server.d.ts +0 -4
- package/dist/mcp-server.js +18 -229
- package/dist/stdio-server.js +22 -9
- package/package.json +10 -10
- package/.claude/skills/client-bot-architecture/skill.md +0 -340
- package/dist/commands/setup.d.ts +0 -11
- package/dist/commands/setup.js +0 -320
- package/scripts/test-hal-tools.ts +0 -154
package/dist/commands/setup.js
DELETED
|
@@ -1,320 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* Setup wizard for Claude Desktop integration
|
|
4
|
-
*
|
|
5
|
-
* Automatically configures Claude Desktop to use Hailer MCP server
|
|
6
|
-
* by generating the correct config with detected paths.
|
|
7
|
-
*/
|
|
8
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
9
|
-
if (k2 === undefined) k2 = k;
|
|
10
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
11
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
12
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
13
|
-
}
|
|
14
|
-
Object.defineProperty(o, k2, desc);
|
|
15
|
-
}) : (function(o, m, k, k2) {
|
|
16
|
-
if (k2 === undefined) k2 = k;
|
|
17
|
-
o[k2] = m[k];
|
|
18
|
-
}));
|
|
19
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
20
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
21
|
-
}) : function(o, v) {
|
|
22
|
-
o["default"] = v;
|
|
23
|
-
});
|
|
24
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
25
|
-
var ownKeys = function(o) {
|
|
26
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
27
|
-
var ar = [];
|
|
28
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
29
|
-
return ar;
|
|
30
|
-
};
|
|
31
|
-
return ownKeys(o);
|
|
32
|
-
};
|
|
33
|
-
return function (mod) {
|
|
34
|
-
if (mod && mod.__esModule) return mod;
|
|
35
|
-
var result = {};
|
|
36
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
37
|
-
__setModuleDefault(result, mod);
|
|
38
|
-
return result;
|
|
39
|
-
};
|
|
40
|
-
})();
|
|
41
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
42
|
-
exports.runSetup = runSetup;
|
|
43
|
-
const fs = __importStar(require("fs"));
|
|
44
|
-
const path = __importStar(require("path"));
|
|
45
|
-
const os = __importStar(require("os"));
|
|
46
|
-
const readline = __importStar(require("readline"));
|
|
47
|
-
// ANSI colors for terminal output
|
|
48
|
-
const colors = {
|
|
49
|
-
reset: '\x1b[0m',
|
|
50
|
-
bright: '\x1b[1m',
|
|
51
|
-
green: '\x1b[32m',
|
|
52
|
-
yellow: '\x1b[33m',
|
|
53
|
-
red: '\x1b[31m',
|
|
54
|
-
cyan: '\x1b[36m',
|
|
55
|
-
};
|
|
56
|
-
function log(message) {
|
|
57
|
-
console.log(message);
|
|
58
|
-
}
|
|
59
|
-
function success(message) {
|
|
60
|
-
console.log(`${colors.green}✓${colors.reset} ${message}`);
|
|
61
|
-
}
|
|
62
|
-
function warn(message) {
|
|
63
|
-
console.log(`${colors.yellow}⚠${colors.reset} ${message}`);
|
|
64
|
-
}
|
|
65
|
-
function error(message) {
|
|
66
|
-
console.log(`${colors.red}✗${colors.reset} ${message}`);
|
|
67
|
-
}
|
|
68
|
-
function header(message) {
|
|
69
|
-
console.log(`\n${colors.bright}${colors.cyan}${message}${colors.reset}\n`);
|
|
70
|
-
}
|
|
71
|
-
/**
|
|
72
|
-
* Get Claude Desktop config path based on OS
|
|
73
|
-
*/
|
|
74
|
-
function getClaudeConfigPath() {
|
|
75
|
-
const platform = os.platform();
|
|
76
|
-
const home = os.homedir();
|
|
77
|
-
switch (platform) {
|
|
78
|
-
case 'darwin': // macOS
|
|
79
|
-
return path.join(home, 'Library', 'Application Support', 'Claude', 'claude_desktop_config.json');
|
|
80
|
-
case 'win32': // Windows
|
|
81
|
-
return path.join(process.env.APPDATA || path.join(home, 'AppData', 'Roaming'), 'Claude', 'claude_desktop_config.json');
|
|
82
|
-
case 'linux':
|
|
83
|
-
return path.join(home, '.config', 'Claude', 'claude_desktop_config.json');
|
|
84
|
-
default:
|
|
85
|
-
throw new Error(`Unsupported platform: ${platform}`);
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
/**
|
|
89
|
-
* Get the path to the installed @hailer/mcp app.js
|
|
90
|
-
*/
|
|
91
|
-
function getAppJsPath() {
|
|
92
|
-
// __dirname in compiled JS will be dist/commands
|
|
93
|
-
// app.js is at dist/app.js
|
|
94
|
-
const distDir = path.dirname(__dirname);
|
|
95
|
-
const appJsPath = path.join(distDir, 'app.js');
|
|
96
|
-
if (!fs.existsSync(appJsPath)) {
|
|
97
|
-
throw new Error(`app.js not found at ${appJsPath}. ` +
|
|
98
|
-
`Make sure @hailer/mcp is installed globally: npm install -g @hailer/mcp`);
|
|
99
|
-
}
|
|
100
|
-
return appJsPath;
|
|
101
|
-
}
|
|
102
|
-
/**
|
|
103
|
-
* Get the path to Node.js executable
|
|
104
|
-
*/
|
|
105
|
-
function getNodePath() {
|
|
106
|
-
// process.execPath gives us the actual node binary path
|
|
107
|
-
// This works correctly with nvm, fnm, volta, etc.
|
|
108
|
-
const nodePath = process.execPath;
|
|
109
|
-
// Verify it's actually node (not npm or npx)
|
|
110
|
-
const basename = path.basename(nodePath).toLowerCase();
|
|
111
|
-
if (!basename.startsWith('node')) {
|
|
112
|
-
throw new Error(`Unexpected executable: ${nodePath}. ` +
|
|
113
|
-
`Expected node binary. Please run this script with node directly.`);
|
|
114
|
-
}
|
|
115
|
-
return nodePath;
|
|
116
|
-
}
|
|
117
|
-
/**
|
|
118
|
-
* Prompt for user input with optional default value
|
|
119
|
-
*/
|
|
120
|
-
async function prompt(rl, question, defaultValue) {
|
|
121
|
-
const defaultText = defaultValue ? ` [${defaultValue}]` : '';
|
|
122
|
-
return new Promise((resolve) => {
|
|
123
|
-
rl.question(`${question}${defaultText}: `, (answer) => {
|
|
124
|
-
resolve(answer.trim() || defaultValue || '');
|
|
125
|
-
});
|
|
126
|
-
});
|
|
127
|
-
}
|
|
128
|
-
/**
|
|
129
|
-
* Prompt for password (hidden input)
|
|
130
|
-
*/
|
|
131
|
-
async function promptPassword(question) {
|
|
132
|
-
return new Promise((resolve) => {
|
|
133
|
-
const stdin = process.stdin;
|
|
134
|
-
const stdout = process.stdout;
|
|
135
|
-
stdout.write(`${question}: `);
|
|
136
|
-
// Pause stdin first to clear any buffered input
|
|
137
|
-
stdin.pause();
|
|
138
|
-
// Enable raw mode to capture keystrokes without echo
|
|
139
|
-
if (stdin.isTTY) {
|
|
140
|
-
stdin.setRawMode(true);
|
|
141
|
-
}
|
|
142
|
-
stdin.resume();
|
|
143
|
-
stdin.setEncoding('utf8');
|
|
144
|
-
let password = '';
|
|
145
|
-
const onData = (key) => {
|
|
146
|
-
switch (key) {
|
|
147
|
-
case '\n':
|
|
148
|
-
case '\r':
|
|
149
|
-
case '\u0004': // Ctrl+D
|
|
150
|
-
// Restore terminal state
|
|
151
|
-
stdin.removeListener('data', onData);
|
|
152
|
-
stdin.setRawMode(false);
|
|
153
|
-
stdin.pause();
|
|
154
|
-
stdout.write('\n');
|
|
155
|
-
resolve(password);
|
|
156
|
-
break;
|
|
157
|
-
case '\u0003': // Ctrl+C
|
|
158
|
-
// Restore terminal state and exit
|
|
159
|
-
stdin.setRawMode(false);
|
|
160
|
-
stdout.write('\n');
|
|
161
|
-
process.exit(1);
|
|
162
|
-
break;
|
|
163
|
-
case '\u007F': // Backspace
|
|
164
|
-
case '\b': // Backspace (alternative)
|
|
165
|
-
if (password.length > 0) {
|
|
166
|
-
password = password.slice(0, -1);
|
|
167
|
-
stdout.write('\b \b'); // Erase last asterisk
|
|
168
|
-
}
|
|
169
|
-
break;
|
|
170
|
-
default:
|
|
171
|
-
// Only add printable characters
|
|
172
|
-
if (key.length === 1 && key.charCodeAt(0) >= 32) {
|
|
173
|
-
password += key;
|
|
174
|
-
stdout.write('*');
|
|
175
|
-
}
|
|
176
|
-
break;
|
|
177
|
-
}
|
|
178
|
-
};
|
|
179
|
-
stdin.on('data', onData);
|
|
180
|
-
});
|
|
181
|
-
}
|
|
182
|
-
/**
|
|
183
|
-
* Read existing Claude Desktop config
|
|
184
|
-
*/
|
|
185
|
-
function readExistingConfig(configPath) {
|
|
186
|
-
try {
|
|
187
|
-
if (fs.existsSync(configPath)) {
|
|
188
|
-
const content = fs.readFileSync(configPath, 'utf8');
|
|
189
|
-
return JSON.parse(content);
|
|
190
|
-
}
|
|
191
|
-
}
|
|
192
|
-
catch (err) {
|
|
193
|
-
warn(`Could not read existing config: ${err instanceof Error ? err.message : String(err)}`);
|
|
194
|
-
}
|
|
195
|
-
return {};
|
|
196
|
-
}
|
|
197
|
-
/**
|
|
198
|
-
* Write config to file, creating directories if needed
|
|
199
|
-
*/
|
|
200
|
-
function writeConfig(configPath, config) {
|
|
201
|
-
const configDir = path.dirname(configPath);
|
|
202
|
-
// Create directory if it doesn't exist
|
|
203
|
-
if (!fs.existsSync(configDir)) {
|
|
204
|
-
fs.mkdirSync(configDir, { recursive: true });
|
|
205
|
-
success(`Created directory: ${configDir}`);
|
|
206
|
-
}
|
|
207
|
-
// Write config with nice formatting
|
|
208
|
-
fs.writeFileSync(configPath, JSON.stringify(config, null, 2) + '\n', 'utf8');
|
|
209
|
-
}
|
|
210
|
-
/**
|
|
211
|
-
* Main setup function
|
|
212
|
-
*/
|
|
213
|
-
async function runSetup() {
|
|
214
|
-
header('Hailer MCP Setup for Claude Desktop');
|
|
215
|
-
// Detect environment
|
|
216
|
-
log('Detecting environment...\n');
|
|
217
|
-
let nodePath;
|
|
218
|
-
let appJsPath;
|
|
219
|
-
let configPath;
|
|
220
|
-
try {
|
|
221
|
-
nodePath = getNodePath();
|
|
222
|
-
success(`Node.js: ${nodePath}`);
|
|
223
|
-
}
|
|
224
|
-
catch (err) {
|
|
225
|
-
error(`Failed to detect Node.js: ${err instanceof Error ? err.message : String(err)}`);
|
|
226
|
-
process.exit(1);
|
|
227
|
-
}
|
|
228
|
-
try {
|
|
229
|
-
appJsPath = getAppJsPath();
|
|
230
|
-
success(`MCP Server: ${appJsPath}`);
|
|
231
|
-
}
|
|
232
|
-
catch (err) {
|
|
233
|
-
error(`${err instanceof Error ? err.message : String(err)}`);
|
|
234
|
-
log('\nTo install globally, run:');
|
|
235
|
-
log(` ${colors.cyan}npm install -g @hailer/mcp${colors.reset}`);
|
|
236
|
-
log('\nThen run setup again:');
|
|
237
|
-
log(` ${colors.cyan}hailer-mcp setup${colors.reset}`);
|
|
238
|
-
process.exit(1);
|
|
239
|
-
}
|
|
240
|
-
try {
|
|
241
|
-
configPath = getClaudeConfigPath();
|
|
242
|
-
success(`Config path: ${configPath}`);
|
|
243
|
-
}
|
|
244
|
-
catch (err) {
|
|
245
|
-
error(`${err instanceof Error ? err.message : String(err)}`);
|
|
246
|
-
process.exit(1);
|
|
247
|
-
}
|
|
248
|
-
// Create readline interface
|
|
249
|
-
const rl = readline.createInterface({
|
|
250
|
-
input: process.stdin,
|
|
251
|
-
output: process.stdout,
|
|
252
|
-
});
|
|
253
|
-
try {
|
|
254
|
-
header('Hailer Credentials');
|
|
255
|
-
log('Enter your Hailer account credentials.');
|
|
256
|
-
log('(Recommended: use a dedicated bot account with access to one workspace)\n');
|
|
257
|
-
const email = await prompt(rl, 'Hailer email');
|
|
258
|
-
if (!email) {
|
|
259
|
-
error('Email is required');
|
|
260
|
-
process.exit(1);
|
|
261
|
-
}
|
|
262
|
-
// Close readline temporarily for password input
|
|
263
|
-
rl.close();
|
|
264
|
-
const password = await promptPassword('Hailer password');
|
|
265
|
-
if (!password) {
|
|
266
|
-
error('Password is required');
|
|
267
|
-
process.exit(1);
|
|
268
|
-
}
|
|
269
|
-
// Reopen readline for remaining prompts
|
|
270
|
-
const rl2 = readline.createInterface({
|
|
271
|
-
input: process.stdin,
|
|
272
|
-
output: process.stdout,
|
|
273
|
-
});
|
|
274
|
-
const apiUrl = await prompt(rl2, 'API URL', 'https://api.hailer.com');
|
|
275
|
-
rl2.close();
|
|
276
|
-
// Generate config
|
|
277
|
-
header('Generating Configuration');
|
|
278
|
-
const existingConfig = readExistingConfig(configPath);
|
|
279
|
-
const existingServers = existingConfig.mcpServers || {};
|
|
280
|
-
// Check if hailer config already exists
|
|
281
|
-
if (existingServers.hailer) {
|
|
282
|
-
warn('Existing "hailer" MCP server configuration found - will be updated');
|
|
283
|
-
}
|
|
284
|
-
const newConfig = {
|
|
285
|
-
...existingConfig,
|
|
286
|
-
mcpServers: {
|
|
287
|
-
...existingServers,
|
|
288
|
-
hailer: {
|
|
289
|
-
command: nodePath,
|
|
290
|
-
args: [appJsPath],
|
|
291
|
-
env: {
|
|
292
|
-
MCP_CLIENT_API_KEY: 'claude-desktop',
|
|
293
|
-
HAILER_EMAIL: email,
|
|
294
|
-
HAILER_PASSWORD: password,
|
|
295
|
-
HAILER_API_URL: apiUrl,
|
|
296
|
-
},
|
|
297
|
-
},
|
|
298
|
-
},
|
|
299
|
-
};
|
|
300
|
-
// Write config
|
|
301
|
-
writeConfig(configPath, newConfig);
|
|
302
|
-
success(`Config written to ${configPath}`);
|
|
303
|
-
// Success message
|
|
304
|
-
header('Setup Complete!');
|
|
305
|
-
log('Claude Desktop is now configured to use Hailer MCP.');
|
|
306
|
-
log('');
|
|
307
|
-
log(`${colors.bright}Next steps:${colors.reset}`);
|
|
308
|
-
log(' 1. Restart Claude Desktop (quit and reopen)');
|
|
309
|
-
log(' 2. Look for "hailer" in the MCP tools list');
|
|
310
|
-
log(' 3. Try asking Claude to list your Hailer workflows');
|
|
311
|
-
log('');
|
|
312
|
-
warn('Security note: Your password is stored in plain text in the config file.');
|
|
313
|
-
log('Consider using a dedicated bot account with limited permissions.');
|
|
314
|
-
}
|
|
315
|
-
catch (err) {
|
|
316
|
-
error(`Setup failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
317
|
-
process.exit(1);
|
|
318
|
-
}
|
|
319
|
-
}
|
|
320
|
-
//# sourceMappingURL=setup.js.map
|
|
@@ -1,154 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env npx ts-node
|
|
2
|
-
/**
|
|
3
|
-
* HAL Tools Test - Simple version
|
|
4
|
-
* Just calls each tool and shows the result. No magic.
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import * as dotenv from 'dotenv';
|
|
8
|
-
import * as path from 'path';
|
|
9
|
-
|
|
10
|
-
dotenv.config({ path: path.join(__dirname, '..', '.env.local') });
|
|
11
|
-
|
|
12
|
-
const MCP_URL = process.env.MCP_SERVER_URL || 'http://localhost:3030/api/mcp';
|
|
13
|
-
|
|
14
|
-
async function call(apiKey: string, tool: string, args: Record<string, unknown> = {}) {
|
|
15
|
-
console.log(`\n>>> ${tool}`);
|
|
16
|
-
console.log(` args: ${JSON.stringify(args)}`);
|
|
17
|
-
|
|
18
|
-
const res = await fetch(`${MCP_URL}?apiKey=${apiKey}`, {
|
|
19
|
-
method: 'POST',
|
|
20
|
-
headers: { 'Content-Type': 'application/json' },
|
|
21
|
-
body: JSON.stringify({
|
|
22
|
-
jsonrpc: '2.0',
|
|
23
|
-
id: '1',
|
|
24
|
-
method: 'tools/call',
|
|
25
|
-
params: { name: tool, arguments: args },
|
|
26
|
-
}),
|
|
27
|
-
});
|
|
28
|
-
|
|
29
|
-
const text = await res.text();
|
|
30
|
-
for (const line of text.split('\n')) {
|
|
31
|
-
if (line.startsWith('data: ')) {
|
|
32
|
-
const data = JSON.parse(line.substring(6));
|
|
33
|
-
if (data.error) {
|
|
34
|
-
console.log(`<<< ERROR: ${data.error.message}`);
|
|
35
|
-
return { error: true, data: null };
|
|
36
|
-
}
|
|
37
|
-
const content = data.result?.content?.[0]?.text || '';
|
|
38
|
-
// Show first 500 chars
|
|
39
|
-
console.log(`<<< ${content.substring(0, 500)}${content.length > 500 ? '...' : ''}`);
|
|
40
|
-
return { error: false, content };
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
console.log('<<< NO RESPONSE');
|
|
44
|
-
return { error: true, data: null };
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
async function main() {
|
|
48
|
-
const apiKey = process.env.MCP_CLIENT_API_KEY;
|
|
49
|
-
if (!apiKey) {
|
|
50
|
-
console.error('Set MCP_CLIENT_API_KEY in .env.local');
|
|
51
|
-
process.exit(1);
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
console.log('=== HAL TOOLS TEST ===\n');
|
|
55
|
-
|
|
56
|
-
// Get a workflow to work with
|
|
57
|
-
const wf = await call(apiKey, 'list_workflows_minimal', {});
|
|
58
|
-
const wfMatch = wf.content?.match(/`([a-f0-9]{24})`/);
|
|
59
|
-
const workflowId = wfMatch?.[1];
|
|
60
|
-
console.log(`\n[Using workflowId: ${workflowId}]`);
|
|
61
|
-
|
|
62
|
-
if (!workflowId) {
|
|
63
|
-
console.log('No workflow found, stopping');
|
|
64
|
-
process.exit(1);
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
// Get phase
|
|
68
|
-
const ph = await call(apiKey, 'list_workflow_phases', { workflowId });
|
|
69
|
-
const phMatch = ph.content?.match(/`([a-f0-9]{24})`/);
|
|
70
|
-
const phaseId = phMatch?.[1];
|
|
71
|
-
console.log(`\n[Using phaseId: ${phaseId}]`);
|
|
72
|
-
|
|
73
|
-
// Schema
|
|
74
|
-
await call(apiKey, 'get_workflow_schema', { workflowId, phaseId });
|
|
75
|
-
|
|
76
|
-
// List activities
|
|
77
|
-
await call(apiKey, 'list_activities', { workflowId, phaseId, fields: '[]' });
|
|
78
|
-
|
|
79
|
-
// Count
|
|
80
|
-
await call(apiKey, 'count_activities', { workflowId });
|
|
81
|
-
|
|
82
|
-
// Create activity
|
|
83
|
-
const created = await call(apiKey, 'create_activity', {
|
|
84
|
-
workflowId,
|
|
85
|
-
name: `TEST_${Date.now()}`
|
|
86
|
-
});
|
|
87
|
-
const actMatch = created.content?.match(/\*\*ID\*\*:\s*([a-f0-9]{24})/);
|
|
88
|
-
const activityId = actMatch?.[1];
|
|
89
|
-
console.log(`\n[Created activityId: ${activityId}]`);
|
|
90
|
-
|
|
91
|
-
if (activityId) {
|
|
92
|
-
// Show it
|
|
93
|
-
await call(apiKey, 'show_activity_by_id', { activityId });
|
|
94
|
-
|
|
95
|
-
// Update it
|
|
96
|
-
await call(apiKey, 'update_activity', { activityId, name: `UPDATED_${Date.now()}` });
|
|
97
|
-
|
|
98
|
-
// Delete it (this tool doesn't exist yet)
|
|
99
|
-
await call(apiKey, 'delete_activity', { activityId });
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
// Insights
|
|
103
|
-
await call(apiKey, 'list_insights', {});
|
|
104
|
-
|
|
105
|
-
const sources = [{
|
|
106
|
-
name: 'src',
|
|
107
|
-
workflowId,
|
|
108
|
-
fields: [{ meta: 'name', name: 'Name', as: 'name' }]
|
|
109
|
-
}];
|
|
110
|
-
|
|
111
|
-
await call(apiKey, 'preview_insight', { sources, query: 'SELECT * FROM src LIMIT 3' });
|
|
112
|
-
|
|
113
|
-
const ins = await call(apiKey, 'create_insight', {
|
|
114
|
-
name: `TEST_${Date.now()}`,
|
|
115
|
-
sources,
|
|
116
|
-
query: 'SELECT * FROM src LIMIT 3'
|
|
117
|
-
});
|
|
118
|
-
const insMatch = ins.content?.match(/`([a-f0-9]{24})`/);
|
|
119
|
-
const insightId = insMatch?.[1];
|
|
120
|
-
|
|
121
|
-
if (insightId) {
|
|
122
|
-
await call(apiKey, 'get_insight_data', { insightId });
|
|
123
|
-
await call(apiKey, 'remove_insight', { insightId });
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
// Discussions
|
|
127
|
-
await call(apiKey, 'list_my_discussions', {});
|
|
128
|
-
|
|
129
|
-
if (activityId) {
|
|
130
|
-
await call(apiKey, 'join_discussion', { activityId });
|
|
131
|
-
// Get discussion from activity
|
|
132
|
-
const act = await call(apiKey, 'show_activity_by_id', { activityId });
|
|
133
|
-
const discMatch = act.content?.match(/discussion.*?([a-f0-9]{24})/i);
|
|
134
|
-
const discussionId = discMatch?.[1];
|
|
135
|
-
|
|
136
|
-
if (discussionId) {
|
|
137
|
-
await call(apiKey, 'fetch_discussion_messages', { discussionId });
|
|
138
|
-
await call(apiKey, 'add_discussion_message', { discussionId, content: 'TEST' });
|
|
139
|
-
await call(apiKey, 'get_activity_from_discussion', { discussionId });
|
|
140
|
-
await call(apiKey, 'leave_discussion', { discussionId });
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
// Other
|
|
145
|
-
await call(apiKey, 'list_workflows', {});
|
|
146
|
-
await call(apiKey, 'list_apps', {});
|
|
147
|
-
await call(apiKey, 'list_templates', {});
|
|
148
|
-
await call(apiKey, 'get_workspace_balance', {});
|
|
149
|
-
await call(apiKey, 'search_workspace_users', { query: 'test' });
|
|
150
|
-
|
|
151
|
-
console.log('\n=== DONE ===');
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
main().catch(console.error);
|