@nordsym/apiclaw 2.1.0 → 2.2.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.
Files changed (185) hide show
  1. package/README.md +15 -2
  2. package/dist/bin-http.js +0 -0
  3. package/dist/bin.bundled.js +79288 -0
  4. package/dist/funnel-client.d.ts +24 -0
  5. package/dist/funnel-client.d.ts.map +1 -0
  6. package/dist/funnel-client.js +131 -0
  7. package/dist/funnel-client.js.map +1 -0
  8. package/dist/funnel.test.d.ts +2 -0
  9. package/dist/funnel.test.d.ts.map +1 -0
  10. package/dist/funnel.test.js +145 -0
  11. package/dist/funnel.test.js.map +1 -0
  12. package/dist/gateway-client.d.ts.map +1 -1
  13. package/dist/gateway-client.js +24 -2
  14. package/dist/gateway-client.js.map +1 -1
  15. package/dist/index.bundled.js +61263 -0
  16. package/dist/index.js +161 -74
  17. package/dist/index.js.map +1 -1
  18. package/dist/postinstall.d.ts +0 -5
  19. package/dist/postinstall.d.ts.map +1 -1
  20. package/dist/postinstall.js +24 -3
  21. package/dist/postinstall.js.map +1 -1
  22. package/dist/registration-guard.d.ts +29 -0
  23. package/dist/registration-guard.d.ts.map +1 -0
  24. package/dist/registration-guard.js +87 -0
  25. package/dist/registration-guard.js.map +1 -0
  26. package/package.json +7 -2
  27. package/.claude/settings.local.json +0 -9
  28. package/.env.prod +0 -1
  29. package/apiclaw-README.md +0 -494
  30. package/convex/_generated/api.d.ts +0 -137
  31. package/convex/_generated/api.js +0 -23
  32. package/convex/_generated/dataModel.d.ts +0 -60
  33. package/convex/_generated/server.d.ts +0 -143
  34. package/convex/_generated/server.js +0 -93
  35. package/convex/adminActivate.ts +0 -53
  36. package/convex/adminStats.ts +0 -306
  37. package/convex/agents.ts +0 -939
  38. package/convex/analytics.ts +0 -187
  39. package/convex/apiKeys.ts +0 -220
  40. package/convex/backfillAnalytics.ts +0 -272
  41. package/convex/backfillSearchLogs.ts +0 -35
  42. package/convex/billing.ts +0 -834
  43. package/convex/capabilities.ts +0 -157
  44. package/convex/chains.ts +0 -1318
  45. package/convex/credits.ts +0 -211
  46. package/convex/crons.ts +0 -50
  47. package/convex/debugFilestackLogs.ts +0 -16
  48. package/convex/debugGetToken.ts +0 -18
  49. package/convex/directCall.ts +0 -713
  50. package/convex/earnProgress.ts +0 -753
  51. package/convex/email.ts +0 -329
  52. package/convex/feedback.ts +0 -265
  53. package/convex/http.ts +0 -3430
  54. package/convex/inbound.ts +0 -32
  55. package/convex/logs.ts +0 -701
  56. package/convex/migrateFilestack.ts +0 -81
  57. package/convex/migratePartnersProd.ts +0 -174
  58. package/convex/migratePratham.ts +0 -126
  59. package/convex/migrateProviderWorkspaces.ts +0 -175
  60. package/convex/mou.ts +0 -91
  61. package/convex/providerKeys.ts +0 -289
  62. package/convex/providers.ts +0 -1135
  63. package/convex/purchases.ts +0 -183
  64. package/convex/ratelimit.ts +0 -104
  65. package/convex/schema.ts +0 -869
  66. package/convex/searchLogs.ts +0 -265
  67. package/convex/seedAPILayerAPIs.ts +0 -191
  68. package/convex/seedDirectCallConfigs.ts +0 -336
  69. package/convex/seedPratham.ts +0 -149
  70. package/convex/spendAlerts.ts +0 -442
  71. package/convex/stripeActions.ts +0 -607
  72. package/convex/teams.ts +0 -243
  73. package/convex/telemetry.ts +0 -81
  74. package/convex/tsconfig.json +0 -25
  75. package/convex/updateAPIStatus.ts +0 -44
  76. package/convex/usage.ts +0 -260
  77. package/convex/usageReports.ts +0 -357
  78. package/convex/waitlist.ts +0 -55
  79. package/convex/webhooks.ts +0 -494
  80. package/convex/workspaceSettings.ts +0 -143
  81. package/convex/workspaces.ts +0 -1331
  82. package/convex.json +0 -3
  83. package/direct-test.mjs +0 -51
  84. package/email-templates/filestack-provider-outreach.html +0 -162
  85. package/email-templates/partnership-template.html +0 -116
  86. package/email-templates/pratham-draft-preview.txt +0 -57
  87. package/email-templates/pratham-partnership-draft.html +0 -141
  88. package/reports/APIClaw-Session-Report-2026-04-05.pdf +0 -0
  89. package/reports/pipeline/PIPELINE-REPORT.json +0 -153
  90. package/reports/pipeline/acquire_apisguru.json +0 -17
  91. package/reports/pipeline/capabilities.json +0 -38
  92. package/reports/pipeline/discover_azure_recursive.json +0 -1551
  93. package/reports/pipeline/discover_github.json +0 -25
  94. package/reports/pipeline/discover_github_repos.json +0 -49
  95. package/reports/pipeline/discover_swaggerhub.json +0 -24
  96. package/reports/pipeline/discover_well_known.json +0 -23
  97. package/reports/pipeline/fetch_specs.json +0 -19
  98. package/reports/pipeline/generate_providers.json +0 -14
  99. package/reports/pipeline/match_registry.json +0 -11
  100. package/reports/pipeline/parse_specs.json +0 -17
  101. package/reports/pipeline/promote_candidates.json +0 -34
  102. package/reports/pipeline/validate.json +0 -30
  103. package/reports/pipeline/validate_smoke_details.json +0 -3835
  104. package/reports/session-report-2026-04-05.html +0 -433
  105. package/seed-apis-direct.mjs +0 -106
  106. package/src/access-control.ts +0 -174
  107. package/src/adapters/base.ts +0 -364
  108. package/src/adapters/claude-desktop.ts +0 -41
  109. package/src/adapters/cline.ts +0 -88
  110. package/src/adapters/continue.ts +0 -91
  111. package/src/adapters/cursor.ts +0 -43
  112. package/src/adapters/custom.ts +0 -188
  113. package/src/adapters/detect.ts +0 -202
  114. package/src/adapters/index.ts +0 -47
  115. package/src/adapters/windsurf.ts +0 -44
  116. package/src/bin-http.ts +0 -45
  117. package/src/bin.ts +0 -34
  118. package/src/capability-router.ts +0 -331
  119. package/src/chainExecutor.ts +0 -730
  120. package/src/chainResolver.test.ts +0 -246
  121. package/src/chainResolver.ts +0 -658
  122. package/src/cli/commands/demo.ts +0 -109
  123. package/src/cli/commands/doctor.ts +0 -435
  124. package/src/cli/commands/index.ts +0 -9
  125. package/src/cli/commands/login.ts +0 -203
  126. package/src/cli/commands/mcp-install.ts +0 -373
  127. package/src/cli/commands/restore.ts +0 -333
  128. package/src/cli/commands/setup.ts +0 -297
  129. package/src/cli/commands/uninstall.ts +0 -240
  130. package/src/cli/index.ts +0 -148
  131. package/src/cli.ts +0 -370
  132. package/src/confirmation.ts +0 -296
  133. package/src/credentials.ts +0 -455
  134. package/src/credits.ts +0 -329
  135. package/src/crypto.ts +0 -75
  136. package/src/discovery.ts +0 -568
  137. package/src/enterprise/env.ts +0 -156
  138. package/src/enterprise/index.ts +0 -7
  139. package/src/enterprise/script-generator.ts +0 -481
  140. package/src/execute-dynamic.ts +0 -617
  141. package/src/execute.ts +0 -2386
  142. package/src/gateway-client.ts +0 -192
  143. package/src/hivr-whitelist.ts +0 -110
  144. package/src/http-api.ts +0 -286
  145. package/src/http-server-minimal.ts +0 -154
  146. package/src/index.ts +0 -2611
  147. package/src/intelligent-gateway.ts +0 -339
  148. package/src/mcp-analytics.ts +0 -156
  149. package/src/metered.ts +0 -149
  150. package/src/open-apis-generated.ts +0 -157
  151. package/src/open-apis.ts +0 -558
  152. package/src/postinstall.ts +0 -18
  153. package/src/product-whitelist.ts +0 -246
  154. package/src/proxy.ts +0 -36
  155. package/src/session.ts +0 -129
  156. package/src/stripe.ts +0 -497
  157. package/src/telemetry.ts +0 -71
  158. package/src/test.ts +0 -135
  159. package/src/types/convex-api.d.ts +0 -20
  160. package/src/types/convex-api.ts +0 -21
  161. package/src/types.ts +0 -109
  162. package/src/ui/colors.ts +0 -219
  163. package/src/ui/errors.ts +0 -394
  164. package/src/ui/index.ts +0 -17
  165. package/src/ui/prompts.ts +0 -390
  166. package/src/ui/spinner.ts +0 -325
  167. package/src/utils/backup.ts +0 -224
  168. package/src/utils/config.ts +0 -318
  169. package/src/utils/os.ts +0 -124
  170. package/src/utils/paths.ts +0 -203
  171. package/src/webhook.ts +0 -107
  172. package/test-10-working.cjs +0 -97
  173. package/test-14-final.cjs +0 -96
  174. package/test-actual-handlers.ts +0 -92
  175. package/test-apilayer-all-14.ts +0 -249
  176. package/test-apilayer-fixed.ts +0 -248
  177. package/test-direct-endpoints.ts +0 -174
  178. package/test-exact-endpoints.ts +0 -144
  179. package/test-final.ts +0 -83
  180. package/test-full-routing.ts +0 -100
  181. package/test-handlers-correct.ts +0 -217
  182. package/test-numverify-key.ts +0 -41
  183. package/test-via-handlers.ts +0 -92
  184. package/test-worldnews.mjs +0 -26
  185. package/tsconfig.json +0 -20
@@ -1,109 +0,0 @@
1
- /**
2
- * APIClaw CLI Demo
3
- * Fires a real API call right in the terminal after login.
4
- * Shows the value in 5 seconds flat.
5
- */
6
-
7
- import ora from 'ora';
8
- import chalk from 'chalk';
9
- import { readSession } from '../../session.js';
10
- import { loginCommand } from './login.js';
11
-
12
- const CONVEX_SITE = 'https://adventurous-avocet-799.convex.site';
13
-
14
- async function convertCurrency(): Promise<void> {
15
- const res = await fetch(`${CONVEX_SITE}/proxy/apilayer`, {
16
- method: 'POST',
17
- headers: { 'Content-Type': 'application/json' },
18
- body: JSON.stringify({
19
- service: 'exchangerates_data',
20
- endpoint: '/latest',
21
- params: { base: 'USD', symbols: 'SEK,EUR,GBP,JPY,NOK,DKK' },
22
- }),
23
- });
24
-
25
- if (!res.ok) throw new Error(`HTTP ${res.status}`);
26
- const data = await res.json() as any;
27
-
28
- if (!data.success) throw new Error(data.message || 'API error');
29
-
30
- const rates = data.rates as Record<string, number>;
31
- const base = data.base;
32
- const date = data.date;
33
-
34
- console.log('');
35
- console.log(chalk.bold(` 💱 Live exchange rates · ${date}`));
36
- console.log(chalk.dim(` Base: 1 ${base}\n`));
37
-
38
- const pairs = [
39
- { code: 'SEK', flag: '🇸🇪', name: 'Swedish Krona' },
40
- { code: 'EUR', flag: '🇪🇺', name: 'Euro' },
41
- { code: 'GBP', flag: '🇬🇧', name: 'British Pound' },
42
- { code: 'JPY', flag: '🇯🇵', name: 'Japanese Yen' },
43
- { code: 'NOK', flag: '🇳🇴', name: 'Norwegian Krone' },
44
- { code: 'DKK', flag: '🇩🇰', name: 'Danish Krone' },
45
- ];
46
-
47
- for (const { code, flag, name } of pairs) {
48
- if (rates[code]) {
49
- const val = rates[code].toFixed(2);
50
- console.log(
51
- ` ${flag} ${chalk.bold((val + ' ' + code).padEnd(14))}${chalk.dim(name)}`
52
- );
53
- }
54
- }
55
-
56
- console.log('');
57
- console.log(
58
- chalk.dim(' Powered by APIClaw Direct Call · exchangerates_data via APILayer')
59
- );
60
- console.log(
61
- chalk.dim(` No API key needed. Your agent can call this too.\n`)
62
- );
63
- console.log(
64
- chalk.cyan(` Dashboard: https://apiclaw.cloud/workspace`) + '\n'
65
- );
66
- }
67
-
68
- export async function demoCommand(): Promise<void> {
69
- console.log('');
70
-
71
- // Ensure logged in
72
- let session = readSession();
73
- if (!session) {
74
- console.log(chalk.yellow(' Sign in first to run the demo:\n'));
75
- const result = await loginCommand({});
76
- if (!result) {
77
- console.error(chalk.red('\n Login failed. Run: npx @nordsym/apiclaw login\n'));
78
- process.exit(1);
79
- }
80
- session = readSession();
81
- console.log('');
82
- }
83
-
84
- console.log(
85
- chalk.bold(' 🦞 APIClaw Demo') +
86
- chalk.dim(' — a real API call, right now, no config needed\n')
87
- );
88
-
89
- const spinner = ora('Calling exchangerates_data via APIClaw...').start();
90
-
91
- try {
92
- await convertCurrency();
93
- spinner.stop();
94
-
95
- console.log(chalk.green(' ✓ That was a live Direct Call through APIClaw.'));
96
- console.log(chalk.dim(' 20 providers, hundreds of APIs. Zero API keys needed.\n'));
97
- console.log(
98
- chalk.bold(' Next step:') +
99
- chalk.dim(' add APIClaw to your AI agent:\n')
100
- );
101
- console.log(
102
- ' ' + chalk.cyan('npx @nordsym/apiclaw setup') +
103
- chalk.dim(' auto-detects Claude, Cursor, Windsurf\n')
104
- );
105
- } catch (err: any) {
106
- spinner.fail('Demo failed: ' + err.message);
107
- console.log(chalk.dim('\n Try again or check https://apiclaw.cloud\n'));
108
- }
109
- }
@@ -1,435 +0,0 @@
1
- /**
2
- * Doctor Command
3
- * Health check for APIClaw installation and MCP client configurations
4
- */
5
-
6
- import { existsSync } from 'fs';
7
- import { execSync } from 'child_process';
8
- import { getAllClients, getClientConfig, MCPClient } from '../../utils/paths.js';
9
- import { readConfig, hasApiclawConfig } from '../../utils/config.js';
10
- import { detectOS, getOSDisplayName } from '../../utils/os.js';
11
- import { getApiUrl, readEnvConfig, ENV_VARS } from '../../enterprise/env.js';
12
-
13
- export interface DoctorResult {
14
- healthy: boolean;
15
- checks: CheckResult[];
16
- summary: string;
17
- }
18
-
19
- export interface CheckResult {
20
- category: string;
21
- name: string;
22
- status: 'pass' | 'fail' | 'warn' | 'skip';
23
- message: string;
24
- details?: string;
25
- }
26
-
27
- /**
28
- * Check Node.js availability and version
29
- */
30
- function checkNode(): CheckResult {
31
- try {
32
- const version = execSync('node --version', { encoding: 'utf-8' }).trim();
33
- const major = parseInt(version.replace('v', '').split('.')[0], 10);
34
-
35
- if (major < 18) {
36
- return {
37
- category: 'System',
38
- name: 'Node.js',
39
- status: 'warn',
40
- message: `${version} (recommend v18+)`,
41
- };
42
- }
43
-
44
- return {
45
- category: 'System',
46
- name: 'Node.js',
47
- status: 'pass',
48
- message: version,
49
- };
50
- } catch {
51
- return {
52
- category: 'System',
53
- name: 'Node.js',
54
- status: 'fail',
55
- message: 'Not found',
56
- details: 'Node.js is required. Install from https://nodejs.org',
57
- };
58
- }
59
- }
60
-
61
- /**
62
- * Check npm availability
63
- */
64
- function checkNpm(): CheckResult {
65
- try {
66
- const version = execSync('npm --version', { encoding: 'utf-8' }).trim();
67
- return {
68
- category: 'System',
69
- name: 'npm',
70
- status: 'pass',
71
- message: `v${version}`,
72
- };
73
- } catch {
74
- return {
75
- category: 'System',
76
- name: 'npm',
77
- status: 'fail',
78
- message: 'Not found',
79
- details: 'npm is required for npx to work',
80
- };
81
- }
82
- }
83
-
84
- /**
85
- * Check npx availability
86
- */
87
- function checkNpx(): CheckResult {
88
- try {
89
- execSync('npx --version', { encoding: 'utf-8', stdio: 'pipe' });
90
- return {
91
- category: 'System',
92
- name: 'npx',
93
- status: 'pass',
94
- message: 'Available',
95
- };
96
- } catch {
97
- return {
98
- category: 'System',
99
- name: 'npx',
100
- status: 'fail',
101
- message: 'Not found',
102
- details: 'npx is required for MCP server execution',
103
- };
104
- }
105
- }
106
-
107
- /**
108
- * Check Codex CLI installation and surface its binary path
109
- */
110
- function checkCodex(): CheckResult {
111
- try {
112
- const binPath = execSync('which codex', { encoding: 'utf-8', stdio: 'pipe' }).trim();
113
- let version = '';
114
- try {
115
- version = execSync('codex --version', { encoding: 'utf-8', stdio: 'pipe' }).trim();
116
- } catch {
117
- // version flag may vary — path is enough
118
- }
119
- return {
120
- category: 'Tooling',
121
- name: 'Codex CLI',
122
- status: 'pass',
123
- message: version ? `${version} — ${binPath}` : binPath,
124
- };
125
- } catch {
126
- return {
127
- category: 'Tooling',
128
- name: 'Codex CLI',
129
- status: 'skip',
130
- message: 'Not installed',
131
- details: 'Install: npm install -g @openai/codex | Then: npx @nordsym/apiclaw setup --client codex',
132
- };
133
- }
134
- }
135
-
136
- /**
137
- * Check APIClaw MCP server binary path
138
- */
139
- function checkApiclawBin(): CheckResult {
140
- try {
141
- const binPath = execSync('which apiclaw', { encoding: 'utf-8', stdio: 'pipe' }).trim();
142
- return {
143
- category: 'Tooling',
144
- name: 'APIClaw binary',
145
- status: 'pass',
146
- message: binPath,
147
- };
148
- } catch {
149
- return {
150
- category: 'Tooling',
151
- name: 'APIClaw binary',
152
- status: 'skip',
153
- message: 'Not in PATH (using npx)',
154
- };
155
- }
156
- }
157
-
158
- /**
159
- * Check MCP client configuration
160
- */
161
- function checkClient(client: MCPClient, serverName = 'apiclaw'): CheckResult {
162
- const config = getClientConfig(client);
163
- const configPath = config.configPath;
164
-
165
- // Check if config file exists
166
- if (!existsSync(configPath)) {
167
- // Check if config directory exists (client might be installed but not configured)
168
- const dirExists = existsSync(config.configDir);
169
-
170
- if (dirExists) {
171
- return {
172
- category: 'MCP Clients',
173
- name: config.displayName,
174
- status: 'warn',
175
- message: 'Installed but not configured',
176
- details: `Config file: ${configPath}`,
177
- };
178
- }
179
-
180
- return {
181
- category: 'MCP Clients',
182
- name: config.displayName,
183
- status: 'skip',
184
- message: 'Not installed',
185
- };
186
- }
187
-
188
- // Read and check config
189
- const readResult = readConfig(configPath);
190
-
191
- if (!readResult.success) {
192
- return {
193
- category: 'MCP Clients',
194
- name: config.displayName,
195
- status: 'fail',
196
- message: 'Invalid config',
197
- details: readResult.error,
198
- };
199
- }
200
-
201
- // Check if APIClaw is configured
202
- if (readResult.config && hasApiclawConfig(readResult.config, serverName)) {
203
- return {
204
- category: 'MCP Clients',
205
- name: config.displayName,
206
- status: 'pass',
207
- message: 'Configured',
208
- };
209
- }
210
-
211
- return {
212
- category: 'MCP Clients',
213
- name: config.displayName,
214
- status: 'warn',
215
- message: 'APIClaw not configured',
216
- details: `Run: npx @nordsym/apiclaw setup --client ${client}`,
217
- };
218
- }
219
-
220
- /**
221
- * Check API connectivity
222
- */
223
- async function checkConnectivity(): Promise<CheckResult> {
224
- const apiUrl = getApiUrl();
225
- const convexUrl = process.env.CONVEX_URL || 'https://brilliant-puffin-712.eu-west-1.convex.cloud';
226
- const candidates = [
227
- `${apiUrl}/health`,
228
- 'https://apiclaw.cloud',
229
- `${convexUrl.replace('.cloud', '.site')}/workspace/poll`,
230
- ];
231
- const failures: string[] = [];
232
-
233
- for (const testUrl of candidates) {
234
- try {
235
- const controller = new AbortController();
236
- const timeout = setTimeout(() => controller.abort(), 5000);
237
- const response = await fetch(testUrl, {
238
- method: 'GET',
239
- signal: controller.signal,
240
- });
241
- clearTimeout(timeout);
242
-
243
- // Any HTTP response proves network + host reachability.
244
- if (response.ok) {
245
- return {
246
- category: 'Connectivity',
247
- name: 'API Server',
248
- status: 'pass',
249
- message: `${testUrl} reachable`,
250
- };
251
- }
252
-
253
- if (testUrl.includes('/workspace/poll') && response.status === 400) {
254
- return {
255
- category: 'Connectivity',
256
- name: 'API Server',
257
- status: 'pass',
258
- message: `${testUrl} reachable (auth endpoint responding)`,
259
- };
260
- }
261
-
262
- failures.push(`${testUrl} -> HTTP ${response.status}`);
263
- } catch (error) {
264
- const reason = error instanceof Error ? error.message : 'Unknown error';
265
- failures.push(`${testUrl} -> ${reason}`);
266
- }
267
- }
268
-
269
- return {
270
- category: 'Connectivity',
271
- name: 'API Server',
272
- status: 'skip',
273
- message: 'Could not reach API (offline or DNS/TLS issue?)',
274
- details: failures.join(' | '),
275
- };
276
- }
277
-
278
- /**
279
- * Check environment variables
280
- */
281
- function checkEnvVars(): CheckResult[] {
282
- const envConfig = readEnvConfig();
283
- const results: CheckResult[] = [];
284
-
285
- if (envConfig.workspace) {
286
- results.push({
287
- category: 'Environment',
288
- name: ENV_VARS.WORKSPACE,
289
- status: 'pass',
290
- message: envConfig.workspace,
291
- });
292
- }
293
-
294
- if (envConfig.apiUrl) {
295
- results.push({
296
- category: 'Environment',
297
- name: ENV_VARS.API_URL,
298
- status: 'pass',
299
- message: envConfig.apiUrl,
300
- });
301
- }
302
-
303
- if (envConfig.disableTelemetry) {
304
- results.push({
305
- category: 'Environment',
306
- name: ENV_VARS.DISABLE_TELEMETRY,
307
- status: 'pass',
308
- message: 'true',
309
- });
310
- }
311
-
312
- return results;
313
- }
314
-
315
- /**
316
- * Run all health checks
317
- */
318
- export async function runDoctor(options: { serverName?: string } = {}): Promise<DoctorResult> {
319
- const checks: CheckResult[] = [];
320
- const serverName = options.serverName || 'apiclaw';
321
-
322
- // System checks
323
- checks.push(checkNode());
324
- checks.push(checkNpm());
325
- checks.push(checkNpx());
326
-
327
- // Tooling checks
328
- checks.push(checkCodex());
329
- checks.push(checkApiclawBin());
330
-
331
- // Client checks
332
- for (const client of getAllClients()) {
333
- checks.push(checkClient(client, serverName));
334
- }
335
-
336
- // Connectivity check
337
- checks.push(await checkConnectivity());
338
-
339
- // Environment checks
340
- checks.push(...checkEnvVars());
341
-
342
- // Calculate health status
343
- const failures = checks.filter(c => c.status === 'fail');
344
- const warnings = checks.filter(c => c.status === 'warn');
345
- const passes = checks.filter(c => c.status === 'pass');
346
-
347
- let healthy = failures.length === 0;
348
- let summary: string;
349
-
350
- if (failures.length > 0) {
351
- summary = `${failures.length} issue(s) found`;
352
- } else if (warnings.length > 0) {
353
- summary = `All systems operational (${warnings.length} warning(s))`;
354
- } else {
355
- summary = 'All systems operational ✓';
356
- }
357
-
358
- return { healthy, checks, summary };
359
- }
360
-
361
- /**
362
- * Format doctor results for display
363
- */
364
- export function formatDoctorOutput(result: DoctorResult): string {
365
- const lines: string[] = [];
366
-
367
- lines.push('');
368
- lines.push('🔍 APIClaw Health Check');
369
- lines.push('========================');
370
- lines.push('');
371
-
372
- // Group checks by category
373
- const categories = new Map<string, CheckResult[]>();
374
-
375
- for (const check of result.checks) {
376
- const existing = categories.get(check.category) || [];
377
- existing.push(check);
378
- categories.set(check.category, existing);
379
- }
380
-
381
- // Format each category
382
- for (const [category, checks] of categories) {
383
- // Skip empty categories
384
- if (checks.length === 0) continue;
385
-
386
- lines.push(`${category}:`);
387
-
388
- for (const check of checks) {
389
- const icon = getStatusIcon(check.status);
390
- lines.push(` ${icon} ${check.name} - ${check.message}`);
391
-
392
- if (check.details && (check.status === 'fail' || check.status === 'warn')) {
393
- lines.push(` ${check.details}`);
394
- }
395
- }
396
-
397
- lines.push('');
398
- }
399
-
400
- // Summary
401
- lines.push(`Status: ${result.summary}`);
402
- lines.push('');
403
-
404
- return lines.join('\n');
405
- }
406
-
407
- /**
408
- * Get icon for status
409
- */
410
- function getStatusIcon(status: CheckResult['status']): string {
411
- switch (status) {
412
- case 'pass': return '✓';
413
- case 'fail': return '✗';
414
- case 'warn': return '⚠';
415
- case 'skip': return '○';
416
- }
417
- }
418
-
419
- /**
420
- * Doctor command handler
421
- */
422
- export async function doctorCommand(options: { serverName?: string; json?: boolean } = {}): Promise<void> {
423
- const result = await runDoctor(options);
424
-
425
- if (options.json) {
426
- console.log(JSON.stringify(result, null, 2));
427
- } else {
428
- console.log(formatDoctorOutput(result));
429
- }
430
-
431
- // Exit with error code if unhealthy
432
- if (!result.healthy) {
433
- process.exit(1);
434
- }
435
- }
@@ -1,9 +0,0 @@
1
- /**
2
- * CLI Commands Index
3
- * Exports all command handlers
4
- */
5
-
6
- export * from './setup.js';
7
- export * from './doctor.js';
8
- export * from './restore.js';
9
- export * from './uninstall.js';