@signaliz/sdk 1.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/dist/cli.js ADDED
@@ -0,0 +1,599 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+
4
+ // src/errors.ts
5
+ var SignalizError = class extends Error {
6
+ constructor(data) {
7
+ super(data.message);
8
+ this.name = "SignalizError";
9
+ this.code = data.code;
10
+ this.errorType = data.errorType;
11
+ this.retryAfter = data.retryAfter;
12
+ this.details = data.details;
13
+ }
14
+ get isRetryable() {
15
+ return this.errorType === "rate_limited" || this.errorType === "timeout" || this.errorType === "provider_error";
16
+ }
17
+ };
18
+ function parseError(status, body) {
19
+ if (body?.error && typeof body.error === "object") {
20
+ return new SignalizError({
21
+ code: body.error.code || `HTTP_${status}`,
22
+ message: body.error.message || `Request failed with status ${status}`,
23
+ errorType: mapErrorType(body.error.code, status),
24
+ retryAfter: body.error.retry_after,
25
+ details: body.error.details
26
+ });
27
+ }
28
+ return new SignalizError({
29
+ code: `HTTP_${status}`,
30
+ message: body?.message || body?.error || `Request failed with status ${status}`,
31
+ errorType: mapErrorType(void 0, status)
32
+ });
33
+ }
34
+ function mapErrorType(code, status) {
35
+ if (code === "RATE_LIMITED" || status === 429) return "rate_limited";
36
+ if (code === "VALIDATION_ERROR" || status === 400) return "validation";
37
+ if (code === "NOT_FOUND" || status === 404) return "not_found";
38
+ if (code === "AUTH_EXPIRED" || status === 401) return "auth_expired";
39
+ if (code === "INSUFFICIENT_CREDITS" || status === 402) return "insufficient_credits";
40
+ if (code === "TIMEOUT" || status === 504) return "timeout";
41
+ if (status >= 500) return "provider_error";
42
+ return "unknown";
43
+ }
44
+
45
+ // src/client.ts
46
+ var DEFAULT_BASE_URL = "https://api.signaliz.com/functions/v1";
47
+ var DEFAULT_TIMEOUT = 12e4;
48
+ var DEFAULT_MAX_RETRIES = 3;
49
+ var HttpClient = class {
50
+ constructor(config) {
51
+ this.baseUrl = config.baseUrl?.replace(/\/$/, "") || DEFAULT_BASE_URL;
52
+ this.timeout = config.timeout ?? DEFAULT_TIMEOUT;
53
+ this.maxRetries = config.maxRetries ?? DEFAULT_MAX_RETRIES;
54
+ this.apiKey = config.apiKey;
55
+ this.clientId = config.clientId;
56
+ this.clientSecret = config.clientSecret;
57
+ if (!this.apiKey && !(this.clientId && this.clientSecret)) {
58
+ throw new Error("Signaliz: provide either apiKey or clientId + clientSecret");
59
+ }
60
+ }
61
+ async request(functionName, body, method = "POST") {
62
+ let lastError;
63
+ for (let attempt = 0; attempt <= this.maxRetries; attempt++) {
64
+ try {
65
+ const token = await this.getToken();
66
+ const url = `${this.baseUrl}/${functionName}`;
67
+ const controller = new AbortController();
68
+ const timer = setTimeout(() => controller.abort(), this.timeout);
69
+ const init = {
70
+ method,
71
+ headers: {
72
+ "Content-Type": "application/json",
73
+ Authorization: `Bearer ${token}`
74
+ },
75
+ signal: controller.signal
76
+ };
77
+ if (method === "POST") {
78
+ init.body = JSON.stringify(body);
79
+ }
80
+ const res = await fetch(url, init);
81
+ clearTimeout(timer);
82
+ if (!res.ok) {
83
+ const errBody = await res.json().catch(() => ({}));
84
+ const err = parseError(res.status, errBody);
85
+ if (err.isRetryable && attempt < this.maxRetries) {
86
+ const wait = err.retryAfter ? err.retryAfter * 1e3 : Math.min(1e3 * Math.pow(2, attempt), 1e4);
87
+ await sleep(wait);
88
+ lastError = err;
89
+ continue;
90
+ }
91
+ throw err;
92
+ }
93
+ return await res.json();
94
+ } catch (e) {
95
+ if (e instanceof SignalizError) throw e;
96
+ if (e.name === "AbortError") {
97
+ const timeout = new SignalizError({
98
+ code: "TIMEOUT",
99
+ message: `Request timed out after ${this.timeout}ms`,
100
+ errorType: "timeout"
101
+ });
102
+ if (attempt < this.maxRetries) {
103
+ lastError = timeout;
104
+ await sleep(1e3 * Math.pow(2, attempt));
105
+ continue;
106
+ }
107
+ throw timeout;
108
+ }
109
+ lastError = e;
110
+ if (attempt < this.maxRetries) {
111
+ await sleep(1e3 * Math.pow(2, attempt));
112
+ continue;
113
+ }
114
+ }
115
+ }
116
+ throw lastError || new Error("Request failed after retries");
117
+ }
118
+ /** Convenience wrapper for POST-based edge function calls */
119
+ async post(functionName, body) {
120
+ return this.request(functionName, body, "POST");
121
+ }
122
+ /** JSON-RPC call to the MCP server */
123
+ async mcp(method, params = {}) {
124
+ const token = await this.getToken();
125
+ const url = `${this.baseUrl}/signaliz-mcp`;
126
+ const res = await fetch(url, {
127
+ method: "POST",
128
+ headers: {
129
+ "Content-Type": "application/json",
130
+ Authorization: `Bearer ${token}`
131
+ },
132
+ body: JSON.stringify({
133
+ jsonrpc: "2.0",
134
+ id: Date.now(),
135
+ method,
136
+ params
137
+ })
138
+ });
139
+ const data = await res.json();
140
+ if (data.error) {
141
+ throw new SignalizError({
142
+ code: data.error.code?.toString() || "MCP_ERROR",
143
+ message: data.error.message || "MCP request failed",
144
+ errorType: "unknown"
145
+ });
146
+ }
147
+ if (data.result?.content?.[0]?.text) {
148
+ try {
149
+ return JSON.parse(data.result.content[0].text);
150
+ } catch {
151
+ return data.result.content[0].text;
152
+ }
153
+ }
154
+ if (data.result?.structuredContent) {
155
+ return data.result.structuredContent;
156
+ }
157
+ return data.result;
158
+ }
159
+ async getToken() {
160
+ if (this.apiKey) return this.apiKey;
161
+ if (this.accessToken) return this.accessToken;
162
+ const res = await fetch("https://api.signaliz.com/token", {
163
+ method: "POST",
164
+ headers: { "Content-Type": "application/json" },
165
+ body: JSON.stringify({
166
+ grant_type: "client_credentials",
167
+ client_id: this.clientId,
168
+ client_secret: this.clientSecret
169
+ })
170
+ });
171
+ if (!res.ok) {
172
+ throw new SignalizError({
173
+ code: "AUTH_FAILED",
174
+ message: "Failed to obtain access token",
175
+ errorType: "auth_expired"
176
+ });
177
+ }
178
+ const data = await res.json();
179
+ this.accessToken = data.access_token;
180
+ return this.accessToken;
181
+ }
182
+ };
183
+ function sleep(ms) {
184
+ return new Promise((r) => setTimeout(r, ms));
185
+ }
186
+
187
+ // src/resources/emails.ts
188
+ var Emails = class {
189
+ constructor(client) {
190
+ this.client = client;
191
+ }
192
+ /** Find and verify an email address for a person at a company */
193
+ async find(params) {
194
+ const body = {
195
+ company_domain: params.companyDomain
196
+ };
197
+ if (params.fullName) body.full_name = params.fullName;
198
+ if (params.firstName) body.first_name = params.firstName;
199
+ if (params.lastName) body.last_name = params.lastName;
200
+ if (params.linkedinUrl) body.linkedin_url = params.linkedinUrl;
201
+ if (params.companyName) body.company_name = params.companyName;
202
+ const data = await this.client.mcp("tools/call", {
203
+ name: "find_emails_with_verification",
204
+ arguments: body
205
+ });
206
+ return {
207
+ email: data.email,
208
+ firstName: data.first_name,
209
+ lastName: data.last_name,
210
+ confidence: data.confidence ?? data.confidence_score ?? 0,
211
+ verificationStatus: data.verification_status ?? "unknown",
212
+ providerUsed: data.provider_used ?? data.source ?? "unknown"
213
+ };
214
+ }
215
+ /** Verify a single email address */
216
+ async verify(email) {
217
+ const data = await this.client.mcp("tools/call", {
218
+ name: "verify_email",
219
+ arguments: { email }
220
+ });
221
+ return {
222
+ email: data.email ?? email,
223
+ isValid: data.is_valid ?? false,
224
+ isDeliverable: data.is_deliverable ?? false,
225
+ isCatchAll: data.is_catch_all ?? false,
226
+ provider: data.provider,
227
+ confidenceScore: data.confidence_score ?? 0,
228
+ verificationSource: data.verification_source
229
+ };
230
+ }
231
+ };
232
+
233
+ // src/resources/signals.ts
234
+ var Signals = class {
235
+ constructor(client) {
236
+ this.client = client;
237
+ }
238
+ /** Enrich a company with actionable signals (V1) */
239
+ async enrich(params) {
240
+ const args = {
241
+ company_name: params.companyName
242
+ };
243
+ if (params.domain) args.domain = params.domain;
244
+ if (params.researchPrompt) args.research_prompt = params.researchPrompt;
245
+ if (params.signalTypes) args.signal_types = params.signalTypes;
246
+ const data = await this.client.mcp("tools/call", {
247
+ name: "enrich_company_signals",
248
+ arguments: args
249
+ });
250
+ return {
251
+ companyName: data.company_name ?? params.companyName,
252
+ signals: (data.signals ?? []).map((s) => ({
253
+ title: s.title,
254
+ signalType: s.signal_type,
255
+ confidenceScore: s.confidence_score ?? 0,
256
+ detectedAt: s.detected_at ?? "",
257
+ url: s.url,
258
+ content: s.content ?? ""
259
+ })),
260
+ totalSignals: data.total_signals ?? data.signals?.length ?? 0,
261
+ fromCache: data.from_cache ?? false
262
+ };
263
+ }
264
+ /** Enrich a company with actionable signals (V2 — clean response + online mode) */
265
+ async enrichV2(params) {
266
+ const args = {};
267
+ if (params.companyName) args.company_name = params.companyName;
268
+ if (params.domain) args.domain = params.domain;
269
+ if (params.companyDomain) args.company_domain = params.companyDomain;
270
+ if (params.researchPrompt) args.research_prompt = params.researchPrompt;
271
+ if (params.signalTypes) args.signal_types = params.signalTypes;
272
+ if (params.online !== void 0) args.online = params.online;
273
+ if (params.targetSignalCount) args.target_signal_count = params.targetSignalCount;
274
+ if (params.lookbackDays) args.lookback_days = params.lookbackDays;
275
+ if (params.model) args.model = params.model;
276
+ if (params.enableDeepSearch) args.enable_deep_search = params.enableDeepSearch;
277
+ if (params.enableOutreachIntelligence) args.enable_outreach_intelligence = params.enableOutreachIntelligence;
278
+ if (params.enablePredictiveIntelligence) args.enable_predictive_intelligence = params.enablePredictiveIntelligence;
279
+ if (params.icpId) args.icp_id = params.icpId;
280
+ if (params.cacheTtlHours !== void 0) args.cache_ttl_hours = params.cacheTtlHours;
281
+ if (params.skipCache) args.skip_cache = params.skipCache;
282
+ const data = await this.client.post("company-signal-enrichment-v2", args);
283
+ return {
284
+ success: data.success ?? false,
285
+ company: {
286
+ name: data.company?.name ?? null,
287
+ domain: data.company?.domain ?? null
288
+ },
289
+ signals: (data.signals ?? []).map((s) => ({
290
+ id: s.id,
291
+ title: s.title,
292
+ type: s.type,
293
+ content: s.content ?? "",
294
+ date: s.date ?? null,
295
+ sourceUrl: s.source_url ?? null,
296
+ sourceType: s.source_type ?? "unknown",
297
+ confidence: s.confidence ?? null
298
+ })),
299
+ signalCount: data.signal_count ?? 0,
300
+ intelligence: data.intelligence ? {
301
+ executiveSummary: data.intelligence.executive_summary ?? null,
302
+ keyThemes: data.intelligence.key_themes ?? [],
303
+ relevanceScore: data.intelligence.relevance_score ?? null,
304
+ outreach: data.intelligence.outreach ? {
305
+ urgencyScore: data.intelligence.outreach.urgency_score ?? null,
306
+ bestTiming: data.intelligence.outreach.best_timing ?? null,
307
+ primaryAngle: data.intelligence.outreach.primary_angle ?? null,
308
+ ctas: data.intelligence.outreach.ctas ? {
309
+ soft: data.intelligence.outreach.ctas.soft,
310
+ direct: data.intelligence.outreach.ctas.direct,
311
+ valueFirst: data.intelligence.outreach.ctas.value_first
312
+ } : null,
313
+ conversationStarters: data.intelligence.outreach.conversation_starters ?? []
314
+ } : null,
315
+ predictions: (data.intelligence.predictions ?? []).map((p) => ({
316
+ prediction: p.prediction,
317
+ confidence: p.confidence,
318
+ targetPersona: p.target_persona ?? null,
319
+ recommendedAction: p.recommended_action ?? null
320
+ }))
321
+ } : null,
322
+ credits: {
323
+ charged: data.credits?.charged ?? 0,
324
+ billingType: data.credits?.billing_type ?? "unknown",
325
+ breakdown: {
326
+ signalCredits: data.credits?.breakdown?.signal_credits ?? 0,
327
+ modelCostUsd: data.credits?.breakdown?.model_cost_usd ?? 0,
328
+ modelCredits: data.credits?.breakdown?.model_credits ?? 0,
329
+ explanation: data.credits?.breakdown?.explanation ?? ""
330
+ }
331
+ },
332
+ metadata: {
333
+ version: data.metadata?.version ?? "",
334
+ model: data.metadata?.model ?? "",
335
+ online: data.metadata?.online ?? false,
336
+ processingTimeMs: data.metadata?.processing_time_ms ?? 0
337
+ }
338
+ };
339
+ }
340
+ };
341
+
342
+ // src/resources/systems.ts
343
+ var Systems = class {
344
+ constructor(client) {
345
+ this.client = client;
346
+ }
347
+ /** Create a new pipeline/system */
348
+ async create(params) {
349
+ const data = await this.client.mcp("tools/call", {
350
+ name: "create_system",
351
+ arguments: {
352
+ name: params.name,
353
+ description: params.description,
354
+ capabilities: params.capabilities,
355
+ field_mappings: params.fieldMappings
356
+ }
357
+ });
358
+ return {
359
+ id: data.system_id ?? data.id,
360
+ name: data.name ?? params.name,
361
+ status: data.status ?? "created",
362
+ nodeCount: data.node_count ?? params.capabilities.length,
363
+ createdAt: data.created_at ?? (/* @__PURE__ */ new Date()).toISOString()
364
+ };
365
+ }
366
+ /** Run a system with input data */
367
+ async run(systemId, params) {
368
+ const data = await this.client.mcp("tools/call", {
369
+ name: "run_system",
370
+ arguments: {
371
+ system_id: systemId,
372
+ input_data: params.data,
373
+ async: params.async ?? false
374
+ }
375
+ });
376
+ return {
377
+ runId: data.run_id ?? data.id,
378
+ status: data.status ?? "running",
379
+ totalRows: data.total_rows,
380
+ completedRows: data.completed_rows ?? 0,
381
+ creditsUsed: data.credits_used ?? 0
382
+ };
383
+ }
384
+ /** Get a system by ID */
385
+ async get(systemId) {
386
+ const data = await this.client.mcp("tools/call", {
387
+ name: "get_system",
388
+ arguments: { system_id: systemId }
389
+ });
390
+ return {
391
+ id: data.id ?? systemId,
392
+ name: data.name,
393
+ status: data.status,
394
+ nodeCount: data.node_count ?? 0,
395
+ createdAt: data.created_at
396
+ };
397
+ }
398
+ /** List all systems */
399
+ async list() {
400
+ const data = await this.client.mcp("tools/call", {
401
+ name: "list_systems",
402
+ arguments: {}
403
+ });
404
+ return (data.systems ?? data ?? []).map((s) => ({
405
+ id: s.id,
406
+ name: s.name,
407
+ status: s.status,
408
+ nodeCount: s.node_count ?? 0,
409
+ createdAt: s.created_at
410
+ }));
411
+ }
412
+ };
413
+
414
+ // src/resources/runs.ts
415
+ var Runs = class {
416
+ constructor(client) {
417
+ this.client = client;
418
+ }
419
+ /** Get run status */
420
+ async get(runId) {
421
+ const data = await this.client.mcp("tools/call", {
422
+ name: "get_run_results",
423
+ arguments: { run_id: runId }
424
+ });
425
+ return {
426
+ runId: data.run_id ?? runId,
427
+ status: data.status,
428
+ totalRows: data.total_rows,
429
+ completedRows: data.completed_rows ?? 0,
430
+ creditsUsed: data.credits_used ?? 0
431
+ };
432
+ }
433
+ /** Poll until a run completes. Returns final result. */
434
+ async waitForCompletion(runId, pollIntervalMs = 2e3) {
435
+ while (true) {
436
+ const run = await this.get(runId);
437
+ if (["completed", "failed", "cancelled", "crashed", "timed_out", "interrupted", "system_failure"].includes(run.status)) {
438
+ return run;
439
+ }
440
+ await new Promise((r) => setTimeout(r, pollIntervalMs));
441
+ }
442
+ }
443
+ /**
444
+ * Stream run progress as an async iterator.
445
+ * Usage: for await (const event of signaliz.runs.stream(runId)) { ... }
446
+ */
447
+ async *stream(runId, pollIntervalMs = 1500) {
448
+ let lastCompleted = -1;
449
+ while (true) {
450
+ const run = await this.get(runId);
451
+ const event = {
452
+ runId,
453
+ status: run.status,
454
+ completedRows: run.completedRows ?? 0,
455
+ totalRows: run.totalRows ?? 0,
456
+ creditsUsed: run.creditsUsed ?? 0
457
+ };
458
+ if (event.completedRows !== lastCompleted) {
459
+ lastCompleted = event.completedRows;
460
+ yield event;
461
+ }
462
+ if (["completed", "failed", "cancelled"].includes(run.status)) {
463
+ return;
464
+ }
465
+ await new Promise((r) => setTimeout(r, pollIntervalMs));
466
+ }
467
+ }
468
+ };
469
+
470
+ // src/resources/http.ts
471
+ var Http = class {
472
+ constructor(client) {
473
+ this.client = client;
474
+ }
475
+ /** Proxy an HTTP request through Signaliz */
476
+ async request(params) {
477
+ const data = await this.client.mcp("tools/call", {
478
+ name: "http_request",
479
+ arguments: {
480
+ url: params.url,
481
+ method: params.method,
482
+ headers: params.headers,
483
+ body: params.body ? JSON.stringify(params.body) : void 0
484
+ }
485
+ });
486
+ return {
487
+ statusCode: data.status_code ?? data.statusCode ?? 200,
488
+ headers: data.headers ?? {},
489
+ body: data.body ?? data.response ?? data
490
+ };
491
+ }
492
+ };
493
+
494
+ // src/index.ts
495
+ var Signaliz = class {
496
+ constructor(config) {
497
+ this.client = new HttpClient(config);
498
+ this.emails = new Emails(this.client);
499
+ this.signals = new Signals(this.client);
500
+ this.systems = new Systems(this.client);
501
+ this.runs = new Runs(this.client);
502
+ this.http = new Http(this.client);
503
+ }
504
+ /** Get current workspace info including credits */
505
+ async getWorkspace() {
506
+ const data = await this.client.mcp("tools/call", {
507
+ name: "get_workspace",
508
+ arguments: {}
509
+ });
510
+ return {
511
+ id: data.workspace_id ?? data.id,
512
+ name: data.workspace_name ?? data.name ?? "Unknown",
513
+ creditsRemaining: data.credits_remaining ?? data.credits ?? 0,
514
+ plan: data.plan ?? "unknown"
515
+ };
516
+ }
517
+ /** List all available MCP tools */
518
+ async listTools() {
519
+ const data = await this.client.mcp("tools/list", {});
520
+ const tools = data?.tools ?? data ?? [];
521
+ return tools.map((t) => ({
522
+ name: t.name,
523
+ description: (t.description ?? "").slice(0, 120),
524
+ category: t.annotations?.category,
525
+ costCredits: t.annotations?.cost_credits
526
+ }));
527
+ }
528
+ /** Discover tools by natural language query */
529
+ async discover(query, category) {
530
+ const data = await this.client.mcp("tools/call", {
531
+ name: "discover_capabilities",
532
+ arguments: { query, category }
533
+ });
534
+ return (data.matches ?? []).map((m) => ({
535
+ name: m.tool,
536
+ description: m.description,
537
+ category: m.category,
538
+ costCredits: m.cost_credits
539
+ }));
540
+ }
541
+ };
542
+
543
+ // src/cli.ts
544
+ var apiKey = process.env.SIGNALIZ_API_KEY;
545
+ async function main() {
546
+ const command = process.argv[2];
547
+ if (!apiKey) {
548
+ console.error("\u274C SIGNALIZ_API_KEY environment variable is required.");
549
+ console.error(" Set it with: export SIGNALIZ_API_KEY=sk_...");
550
+ process.exit(1);
551
+ }
552
+ const signaliz = new Signaliz({ apiKey });
553
+ switch (command) {
554
+ case "test": {
555
+ try {
556
+ const ws = await signaliz.getWorkspace();
557
+ console.log(`\u2705 Connected to workspace: ${ws.name} (${ws.creditsRemaining.toLocaleString()} credits remaining)`);
558
+ } catch (e) {
559
+ console.error(`\u274C Connection failed: ${e.message}`);
560
+ process.exit(1);
561
+ }
562
+ break;
563
+ }
564
+ case "tools": {
565
+ try {
566
+ const tools = await signaliz.listTools();
567
+ console.log(`
568
+ \u{1F4CB} Available tools (${tools.length}):
569
+ `);
570
+ console.log("Name".padEnd(40) + "Category".padEnd(15) + "Credits".padEnd(10) + "Description");
571
+ console.log("\u2500".repeat(100));
572
+ for (const t of tools) {
573
+ console.log(
574
+ (t.name ?? "").padEnd(40) + (t.category ?? "-").padEnd(15) + String(t.costCredits ?? "-").padEnd(10) + (t.description ?? "").slice(0, 60)
575
+ );
576
+ }
577
+ } catch (e) {
578
+ console.error(`\u274C Failed to list tools: ${e.message}`);
579
+ process.exit(1);
580
+ }
581
+ break;
582
+ }
583
+ default:
584
+ console.log(`
585
+ Signaliz CLI v1.0.0
586
+
587
+ Usage:
588
+ signaliz test Verify API connectivity
589
+ signaliz tools List all available MCP tools
590
+
591
+ Environment:
592
+ SIGNALIZ_API_KEY Your API key (required)
593
+ `);
594
+ }
595
+ }
596
+ main().catch((e) => {
597
+ console.error(e);
598
+ process.exit(1);
599
+ });
package/dist/cli.mjs ADDED
@@ -0,0 +1,62 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ Signaliz
4
+ } from "./chunk-R657OZE7.mjs";
5
+
6
+ // src/cli.ts
7
+ var apiKey = process.env.SIGNALIZ_API_KEY;
8
+ async function main() {
9
+ const command = process.argv[2];
10
+ if (!apiKey) {
11
+ console.error("\u274C SIGNALIZ_API_KEY environment variable is required.");
12
+ console.error(" Set it with: export SIGNALIZ_API_KEY=sk_...");
13
+ process.exit(1);
14
+ }
15
+ const signaliz = new Signaliz({ apiKey });
16
+ switch (command) {
17
+ case "test": {
18
+ try {
19
+ const ws = await signaliz.getWorkspace();
20
+ console.log(`\u2705 Connected to workspace: ${ws.name} (${ws.creditsRemaining.toLocaleString()} credits remaining)`);
21
+ } catch (e) {
22
+ console.error(`\u274C Connection failed: ${e.message}`);
23
+ process.exit(1);
24
+ }
25
+ break;
26
+ }
27
+ case "tools": {
28
+ try {
29
+ const tools = await signaliz.listTools();
30
+ console.log(`
31
+ \u{1F4CB} Available tools (${tools.length}):
32
+ `);
33
+ console.log("Name".padEnd(40) + "Category".padEnd(15) + "Credits".padEnd(10) + "Description");
34
+ console.log("\u2500".repeat(100));
35
+ for (const t of tools) {
36
+ console.log(
37
+ (t.name ?? "").padEnd(40) + (t.category ?? "-").padEnd(15) + String(t.costCredits ?? "-").padEnd(10) + (t.description ?? "").slice(0, 60)
38
+ );
39
+ }
40
+ } catch (e) {
41
+ console.error(`\u274C Failed to list tools: ${e.message}`);
42
+ process.exit(1);
43
+ }
44
+ break;
45
+ }
46
+ default:
47
+ console.log(`
48
+ Signaliz CLI v1.0.0
49
+
50
+ Usage:
51
+ signaliz test Verify API connectivity
52
+ signaliz tools List all available MCP tools
53
+
54
+ Environment:
55
+ SIGNALIZ_API_KEY Your API key (required)
56
+ `);
57
+ }
58
+ }
59
+ main().catch((e) => {
60
+ console.error(e);
61
+ process.exit(1);
62
+ });