@closedloop-ai/cli 0.2.4 → 0.3.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/README.md +176 -270
- package/dist/THIRD_PARTY_NOTICES.txt +24 -0
- package/dist/closedloop.js +156 -0
- package/package.json +31 -62
- package/CONTRIBUTING.md +0 -437
- package/LICENSE +0 -21
- package/docs/CLI_COMMANDS.md +0 -522
- package/packages/cli/dist/__tests__/api.test.js +0 -151
- package/packages/cli/dist/__tests__/api.test.js.map +0 -1
- package/packages/cli/dist/__tests__/cli.test.js +0 -37
- package/packages/cli/dist/__tests__/cli.test.js.map +0 -1
- package/packages/cli/dist/__tests__/config.test.js +0 -33
- package/packages/cli/dist/__tests__/config.test.js.map +0 -1
- package/packages/cli/dist/__tests__/errors.test.js +0 -109
- package/packages/cli/dist/__tests__/errors.test.js.map +0 -1
- package/packages/cli/dist/__tests__/performance.test.js +0 -221
- package/packages/cli/dist/__tests__/performance.test.js.map +0 -1
- package/packages/cli/dist/__tests__/setup.js +0 -50
- package/packages/cli/dist/__tests__/setup.js.map +0 -1
- package/packages/cli/dist/__tests__/team-simple.test.js +0 -38
- package/packages/cli/dist/__tests__/team-simple.test.js.map +0 -1
- package/packages/cli/dist/__tests__/test-factories.js +0 -148
- package/packages/cli/dist/__tests__/test-factories.js.map +0 -1
- package/packages/cli/dist/__tests__/validation.test.js +0 -124
- package/packages/cli/dist/__tests__/validation.test.js.map +0 -1
- package/packages/cli/dist/api/auth.js +0 -27
- package/packages/cli/dist/api/auth.js.map +0 -1
- package/packages/cli/dist/api/feedback.js +0 -70
- package/packages/cli/dist/api/feedback.js.map +0 -1
- package/packages/cli/dist/api/ingest.js +0 -60
- package/packages/cli/dist/api/ingest.js.map +0 -1
- package/packages/cli/dist/api/input.js +0 -60
- package/packages/cli/dist/api/input.js.map +0 -1
- package/packages/cli/dist/api/team.js +0 -59
- package/packages/cli/dist/api/team.js.map +0 -1
- package/packages/cli/dist/api/usage.js +0 -49
- package/packages/cli/dist/api/usage.js.map +0 -1
- package/packages/cli/dist/cli.js +0 -201
- package/packages/cli/dist/cli.js.map +0 -1
- package/packages/cli/dist/commands/config.js +0 -186
- package/packages/cli/dist/commands/config.js.map +0 -1
- package/packages/cli/dist/commands/feedback.js +0 -234
- package/packages/cli/dist/commands/feedback.js.map +0 -1
- package/packages/cli/dist/commands/ingest.js +0 -391
- package/packages/cli/dist/commands/ingest.js.map +0 -1
- package/packages/cli/dist/commands/input.js +0 -370
- package/packages/cli/dist/commands/input.js.map +0 -1
- package/packages/cli/dist/commands/insight.js +0 -234
- package/packages/cli/dist/commands/insight.js.map +0 -1
- package/packages/cli/dist/commands/list.js +0 -81
- package/packages/cli/dist/commands/list.js.map +0 -1
- package/packages/cli/dist/commands/status.js +0 -93
- package/packages/cli/dist/commands/status.js.map +0 -1
- package/packages/cli/dist/commands/submit.js +0 -225
- package/packages/cli/dist/commands/submit.js.map +0 -1
- package/packages/cli/dist/commands/team.js +0 -82
- package/packages/cli/dist/commands/team.js.map +0 -1
- package/packages/cli/dist/commands/usage.js +0 -168
- package/packages/cli/dist/commands/usage.js.map +0 -1
- package/packages/cli/dist/config/constants.js +0 -38
- package/packages/cli/dist/config/constants.js.map +0 -1
- package/packages/cli/dist/config/index.js +0 -84
- package/packages/cli/dist/config/index.js.map +0 -1
- package/packages/cli/dist/types/index.js +0 -3
- package/packages/cli/dist/types/index.js.map +0 -1
- package/packages/cli/dist/utils/config.js +0 -55
- package/packages/cli/dist/utils/config.js.map +0 -1
- package/packages/cli/dist/utils/errors.js +0 -70
- package/packages/cli/dist/utils/errors.js.map +0 -1
- package/packages/cli/dist/utils/validation.js +0 -133
- package/packages/cli/dist/utils/validation.js.map +0 -1
package/docs/CLI_COMMANDS.md
DELETED
|
@@ -1,522 +0,0 @@
|
|
|
1
|
-
# ClosedLoop AI CLI Commands Reference
|
|
2
|
-
|
|
3
|
-
Complete reference for all CLI commands, parameters, and user experience.
|
|
4
|
-
|
|
5
|
-
## Table of Contents
|
|
6
|
-
|
|
7
|
-
- [Installation](#installation)
|
|
8
|
-
- [Configuration](#configuration)
|
|
9
|
-
- [How to Use API Keys](#how-to-use-api-keys)
|
|
10
|
-
- [Input Commands](#input-commands)
|
|
11
|
-
- [Feedback Commands](#feedback-commands)
|
|
12
|
-
- [Team Commands](#team-commands)
|
|
13
|
-
- [General Commands](#general-commands)
|
|
14
|
-
- [Error Handling](#error-handling)
|
|
15
|
-
- [Examples](#examples)
|
|
16
|
-
|
|
17
|
-
## Installation
|
|
18
|
-
|
|
19
|
-
### Global Installation (Recommended)
|
|
20
|
-
```bash
|
|
21
|
-
npm install -g @closedloop-ai/cli
|
|
22
|
-
```
|
|
23
|
-
|
|
24
|
-
### Local Installation
|
|
25
|
-
```bash
|
|
26
|
-
npm install @closedloop-ai/cli
|
|
27
|
-
npx cl --help
|
|
28
|
-
```
|
|
29
|
-
|
|
30
|
-
### Verify Installation
|
|
31
|
-
```bash
|
|
32
|
-
cl --version
|
|
33
|
-
# Output: 0.2.0
|
|
34
|
-
```
|
|
35
|
-
|
|
36
|
-
## Configuration
|
|
37
|
-
|
|
38
|
-
### Set API Key
|
|
39
|
-
```bash
|
|
40
|
-
cl config set --api-key your-api-key-here
|
|
41
|
-
```
|
|
42
|
-
|
|
43
|
-
### View Configuration
|
|
44
|
-
```bash
|
|
45
|
-
cl config
|
|
46
|
-
# Output:
|
|
47
|
-
# ⚙️ Configuration:
|
|
48
|
-
# ────────────────────────────────────────
|
|
49
|
-
# API Key: ✓ Configured
|
|
50
|
-
# Config File: /Users/jirikobelka/.closedloop/config.json
|
|
51
|
-
```
|
|
52
|
-
|
|
53
|
-
### JSON Configuration
|
|
54
|
-
```bash
|
|
55
|
-
cl config --json
|
|
56
|
-
# Output:
|
|
57
|
-
# {
|
|
58
|
-
# "success": true,
|
|
59
|
-
# "data": {
|
|
60
|
-
# "apiKey": "test-key...",
|
|
61
|
-
# "configFile": "/Users/jirikobelka/.closedloop/config.json",
|
|
62
|
-
# "configured": true
|
|
63
|
-
# }
|
|
64
|
-
# }
|
|
65
|
-
```
|
|
66
|
-
|
|
67
|
-
### Environment Variable
|
|
68
|
-
```bash
|
|
69
|
-
export CLOSEDLOOP_API_KEY="your-api-key-here"
|
|
70
|
-
cl config # Will use environment variable
|
|
71
|
-
```
|
|
72
|
-
|
|
73
|
-
## Ingest Commands
|
|
74
|
-
|
|
75
|
-
### Ingest Customer Product Feedback
|
|
76
|
-
|
|
77
|
-
#### Basic Ingestion
|
|
78
|
-
```bash
|
|
79
|
-
cl ingest "Your customer product feedback here"
|
|
80
|
-
```
|
|
81
|
-
|
|
82
|
-
#### With Metadata
|
|
83
|
-
```bash
|
|
84
|
-
cl ingest "The dashboard is confusing and hard to navigate" \
|
|
85
|
-
--title "Dashboard UX Issues" \
|
|
86
|
-
--customer "customer-123" \
|
|
87
|
-
--name "John Doe" \
|
|
88
|
-
--email "john@example.com" \
|
|
89
|
-
--url "https://support.example.com/ticket/456"
|
|
90
|
-
```
|
|
91
|
-
|
|
92
|
-
#### Wait for Processing
|
|
93
|
-
```bash
|
|
94
|
-
cl ingest "Customer complaint about performance" --wait
|
|
95
|
-
# Shows real-time processing status
|
|
96
|
-
```
|
|
97
|
-
|
|
98
|
-
#### JSON Output
|
|
99
|
-
```bash
|
|
100
|
-
cl ingest "Great product, love the new features!" --json
|
|
101
|
-
# Output: {"id":"74e3dd87-878f-41cf-8e5a-87527bbf7770","status":"submitted"}
|
|
102
|
-
```
|
|
103
|
-
|
|
104
|
-
### List Ingested Feedback
|
|
105
|
-
|
|
106
|
-
#### Basic List
|
|
107
|
-
```bash
|
|
108
|
-
cl ingest
|
|
109
|
-
# Shows table of recent ingests
|
|
110
|
-
```
|
|
111
|
-
|
|
112
|
-
#### With Pagination
|
|
113
|
-
```bash
|
|
114
|
-
cl ingest --page 2 --limit 10
|
|
115
|
-
# Shows page 2 with 10 items per page
|
|
116
|
-
```
|
|
117
|
-
|
|
118
|
-
#### JSON Output
|
|
119
|
-
```bash
|
|
120
|
-
cl ingest --json
|
|
121
|
-
# Output: {"data":[...],"pagination":{...}}
|
|
122
|
-
```
|
|
123
|
-
|
|
124
|
-
### View Specific Ingest
|
|
125
|
-
|
|
126
|
-
#### By ID
|
|
127
|
-
```bash
|
|
128
|
-
cl ingest 74e3dd87-878f-41cf-8e5a-87527bbf7770
|
|
129
|
-
# Shows detailed ingest information
|
|
130
|
-
```
|
|
131
|
-
|
|
132
|
-
#### JSON Output
|
|
133
|
-
```bash
|
|
134
|
-
cl ingest 74e3dd87-878f-41cf-8e5a-87527bbf7770 --json
|
|
135
|
-
# Output: {"id":"...","content":"...","status":"..."}
|
|
136
|
-
```
|
|
137
|
-
|
|
138
|
-
### Ingest Parameters
|
|
139
|
-
|
|
140
|
-
| Parameter | Type | Required | Description | Example |
|
|
141
|
-
|-----------|------|----------|-------------|---------|
|
|
142
|
-
| `content` | string | Yes | Customer product feedback content | `"The app crashes when uploading files"` |
|
|
143
|
-
| `--title` | string | No | Title for the feedback | `"File Upload Issue"` |
|
|
144
|
-
| `--customer` | string | No | Customer identifier | `"customer-123"` |
|
|
145
|
-
| `--name` | string | No | Reporter name | `"John Doe"` |
|
|
146
|
-
| `--email` | string | No | Reporter email | `"john@example.com"` |
|
|
147
|
-
| `--url` | string | No | Source URL | `"https://support.example.com/ticket/456"` |
|
|
148
|
-
| `--wait` | flag | No | Wait for processing to complete | `--wait` |
|
|
149
|
-
| `--json` | flag | No | Output in JSON format | `--json` |
|
|
150
|
-
| `--page` | number | No | Page number for listing | `--page 2` |
|
|
151
|
-
| `--limit` | number | No | Items per page (max 100) | `--limit 20` |
|
|
152
|
-
|
|
153
|
-
## Insight Commands
|
|
154
|
-
|
|
155
|
-
### List AI-Generated Insights
|
|
156
|
-
|
|
157
|
-
#### Basic List
|
|
158
|
-
```bash
|
|
159
|
-
cl insight
|
|
160
|
-
# Shows table of AI-generated insights
|
|
161
|
-
```
|
|
162
|
-
|
|
163
|
-
#### With Pagination
|
|
164
|
-
```bash
|
|
165
|
-
cl insight --page 2 --limit 5
|
|
166
|
-
# Shows page 2 with 5 items per page
|
|
167
|
-
```
|
|
168
|
-
|
|
169
|
-
#### JSON Output
|
|
170
|
-
```bash
|
|
171
|
-
cl insight --json
|
|
172
|
-
# Output: {"data":[...],"pagination":{...}}
|
|
173
|
-
```
|
|
174
|
-
|
|
175
|
-
### View Specific Insight
|
|
176
|
-
|
|
177
|
-
#### By ID
|
|
178
|
-
```bash
|
|
179
|
-
cl insight 2ea8f556-052b-4f5c-bf86-833780b3d00d
|
|
180
|
-
# Shows detailed insight information
|
|
181
|
-
```
|
|
182
|
-
|
|
183
|
-
#### JSON Output
|
|
184
|
-
```bash
|
|
185
|
-
cl insight 2ea8f556-052b-4f5c-bf86-833780b3d00d --json
|
|
186
|
-
# Output: {"id":"...","title":"...","content":"..."}
|
|
187
|
-
```
|
|
188
|
-
|
|
189
|
-
### Insight Parameters
|
|
190
|
-
|
|
191
|
-
| Parameter | Type | Required | Description | Example |
|
|
192
|
-
|-----------|------|----------|-------------|---------|
|
|
193
|
-
| `id` | string | Yes* | Insight ID for detailed view | `2ea8f556-052b-4f5c-bf86-833780b3d00d` |
|
|
194
|
-
| `--page` | number | No | Page number for listing | `--page 2` |
|
|
195
|
-
| `--limit` | number | No | Items per page (max 100) | `--limit 20` |
|
|
196
|
-
| `--json` | flag | No | Output in JSON format | `--json` |
|
|
197
|
-
|
|
198
|
-
*Required only for detailed view
|
|
199
|
-
|
|
200
|
-
## Team Commands
|
|
201
|
-
|
|
202
|
-
### Team Website Management
|
|
203
|
-
|
|
204
|
-
**Why set your product website?** ClosedLoop AI uses your product URL to learn about your product features, competitors, pricing, and positioning. This enables more accurate feedback attribution and product-specific insights. For example, if you're working on iPhone, use `https://apple.com/iphone` - this helps ClosedLoop AI understand that "camera quality" feedback is about iPhone cameras, not just any camera.
|
|
205
|
-
|
|
206
|
-
#### Show Current Website
|
|
207
|
-
```bash
|
|
208
|
-
cl team website
|
|
209
|
-
# Output: Website: https://example.com
|
|
210
|
-
# Updated: 2024-01-15T10:30:00Z
|
|
211
|
-
```
|
|
212
|
-
|
|
213
|
-
#### Set Team Website
|
|
214
|
-
```bash
|
|
215
|
-
cl team website "https://example.com"
|
|
216
|
-
# Output: Team website updated successfully
|
|
217
|
-
# Website: https://example.com
|
|
218
|
-
# Updated: 2024-01-15T10:30:00Z
|
|
219
|
-
```
|
|
220
|
-
|
|
221
|
-
#### JSON Output
|
|
222
|
-
```bash
|
|
223
|
-
# Show website in JSON format
|
|
224
|
-
cl team website --json
|
|
225
|
-
# Output: {"success": true, "data": {"website": "https://example.com", "updated_at": "2024-01-15T10:30:00Z"}}
|
|
226
|
-
|
|
227
|
-
# Set website in JSON format
|
|
228
|
-
cl team website "https://example.com" --json
|
|
229
|
-
# Output: {"success": true, "data": {"website": "https://example.com", "updated_at": "2024-01-15T10:30:00Z"}}
|
|
230
|
-
```
|
|
231
|
-
|
|
232
|
-
### Team Management
|
|
233
|
-
```bash
|
|
234
|
-
cl team
|
|
235
|
-
# Shows available team management commands
|
|
236
|
-
```
|
|
237
|
-
|
|
238
|
-
### Team Parameters
|
|
239
|
-
|
|
240
|
-
| Parameter | Type | Required | Description | Example |
|
|
241
|
-
|-----------|------|----------|-------------|---------|
|
|
242
|
-
| `website` | string | No | Team website URL (must include http:// or https://) | `"https://example.com"` |
|
|
243
|
-
| `--json` | flag | No | Output in JSON format | `--json` |
|
|
244
|
-
|
|
245
|
-
### Team Error Handling
|
|
246
|
-
|
|
247
|
-
#### Invalid Website URL
|
|
248
|
-
```bash
|
|
249
|
-
cl team website "invalid-url"
|
|
250
|
-
# Error: Invalid website URL format. Must include protocol (http:// or https://) and domain
|
|
251
|
-
```
|
|
252
|
-
|
|
253
|
-
#### Missing API Key
|
|
254
|
-
```bash
|
|
255
|
-
cl team website "https://example.com"
|
|
256
|
-
# Error: API key not configured. Run: cl config set --api-key <key>
|
|
257
|
-
```
|
|
258
|
-
|
|
259
|
-
## General Commands
|
|
260
|
-
|
|
261
|
-
### Version
|
|
262
|
-
```bash
|
|
263
|
-
cl --version
|
|
264
|
-
# Output: 0.2.0
|
|
265
|
-
|
|
266
|
-
cl version
|
|
267
|
-
# Output: 0.2.0
|
|
268
|
-
```
|
|
269
|
-
|
|
270
|
-
### Help
|
|
271
|
-
```bash
|
|
272
|
-
cl --help
|
|
273
|
-
# Shows main help
|
|
274
|
-
|
|
275
|
-
cl help
|
|
276
|
-
# Shows main help
|
|
277
|
-
|
|
278
|
-
cl help input
|
|
279
|
-
# Shows input command help
|
|
280
|
-
|
|
281
|
-
cl help feedback
|
|
282
|
-
# Shows feedback command help
|
|
283
|
-
```
|
|
284
|
-
|
|
285
|
-
### Help Parameters
|
|
286
|
-
|
|
287
|
-
| Command | Description | Example |
|
|
288
|
-
|---------|-------------|---------|
|
|
289
|
-
| `cl --help` | Main help with all commands | `cl --help` |
|
|
290
|
-
| `cl help <command>` | Specific command help | `cl help input` |
|
|
291
|
-
|
|
292
|
-
## Error Handling
|
|
293
|
-
|
|
294
|
-
### Common Error Messages
|
|
295
|
-
|
|
296
|
-
#### No API Key
|
|
297
|
-
```bash
|
|
298
|
-
cl input "Test feedback"
|
|
299
|
-
# Error: 🔑 No API key configured!
|
|
300
|
-
#
|
|
301
|
-
# To get started:
|
|
302
|
-
# 1. Go to https://closedloop.sh
|
|
303
|
-
# 2. Sign up for a free account
|
|
304
|
-
# 3. Generate your API key
|
|
305
|
-
# 4. Run: cl config --set-api-key <your-key>
|
|
306
|
-
```
|
|
307
|
-
|
|
308
|
-
#### Invalid API Key
|
|
309
|
-
```bash
|
|
310
|
-
cl input "Test feedback"
|
|
311
|
-
# Error: ❌ Invalid API key. Get your free API key at https://closedloop.sh
|
|
312
|
-
```
|
|
313
|
-
|
|
314
|
-
#### Validation Error
|
|
315
|
-
```bash
|
|
316
|
-
cl input ""
|
|
317
|
-
# Error: ❌ Validation Error: Content cannot be empty
|
|
318
|
-
```
|
|
319
|
-
|
|
320
|
-
#### API Error
|
|
321
|
-
```bash
|
|
322
|
-
cl input "Test feedback"
|
|
323
|
-
# Error: ❌ API Error: 500 - Internal server error
|
|
324
|
-
```
|
|
325
|
-
|
|
326
|
-
### Error Codes
|
|
327
|
-
|
|
328
|
-
| Code | Description | Solution |
|
|
329
|
-
|------|-------------|----------|
|
|
330
|
-
| `NO_API_KEY` | No API key configured | Run `cl config set --api-key <key>` |
|
|
331
|
-
| `INVALID_API_KEY` | API key is invalid | Get new key from https://closedloop.sh |
|
|
332
|
-
| `VALIDATION_ERROR` | Input validation failed | Check input format and requirements |
|
|
333
|
-
| `API_ERROR` | Server error | Check internet connection, try again later |
|
|
334
|
-
| `RATE_LIMITED` | Too many requests | Wait and retry |
|
|
335
|
-
| `NOT_FOUND` | Resource not found | Check ID is correct |
|
|
336
|
-
|
|
337
|
-
## Examples
|
|
338
|
-
|
|
339
|
-
### Basic Workflow
|
|
340
|
-
```bash
|
|
341
|
-
# 1. Configure API key
|
|
342
|
-
cl config set --api-key your-api-key-here
|
|
343
|
-
|
|
344
|
-
# 2. Ingest customer product feedback
|
|
345
|
-
cl ingest "The new dashboard is confusing and hard to navigate"
|
|
346
|
-
|
|
347
|
-
# 3. Wait for AI analysis
|
|
348
|
-
cl ingest "Customer complaint about performance" --wait
|
|
349
|
-
|
|
350
|
-
# 4. View AI-generated insights
|
|
351
|
-
cl insight
|
|
352
|
-
|
|
353
|
-
# 5. Get detailed insight
|
|
354
|
-
cl insight 2ea8f556-052b-4f5c-bf86-833780b3d00d
|
|
355
|
-
```
|
|
356
|
-
|
|
357
|
-
### Advanced Workflow
|
|
358
|
-
```bash
|
|
359
|
-
# 1. Ingest with full metadata
|
|
360
|
-
cl ingest "Great product, love the new features!" \
|
|
361
|
-
--title "Positive Feedback" \
|
|
362
|
-
--customer "enterprise-123" \
|
|
363
|
-
--name "Jane Smith" \
|
|
364
|
-
--email "jane@example.com" \
|
|
365
|
-
--url "https://support.example.com/ticket/789"
|
|
366
|
-
|
|
367
|
-
# 2. List all ingests with pagination
|
|
368
|
-
cl ingest --page 1 --limit 20
|
|
369
|
-
|
|
370
|
-
# 3. Get JSON output for scripting
|
|
371
|
-
cl insight --json | jq '.data[0].title'
|
|
372
|
-
|
|
373
|
-
# 4. View specific ingest details
|
|
374
|
-
cl ingest 74e3dd87-878f-41cf-8e5a-87527bbf7770 --json
|
|
375
|
-
```
|
|
376
|
-
|
|
377
|
-
### Scripting Examples
|
|
378
|
-
```bash
|
|
379
|
-
#!/bin/bash
|
|
380
|
-
# ingest-feedback.sh
|
|
381
|
-
|
|
382
|
-
# Ingest feedback and get ID
|
|
383
|
-
ID=$(cl ingest "$1" --json | jq -r '.id')
|
|
384
|
-
|
|
385
|
-
# Wait for processing
|
|
386
|
-
cl ingest "$ID" --wait
|
|
387
|
-
|
|
388
|
-
# Show results
|
|
389
|
-
cl insight
|
|
390
|
-
```
|
|
391
|
-
|
|
392
|
-
```bash
|
|
393
|
-
#!/bin/bash
|
|
394
|
-
# get-insights.sh
|
|
395
|
-
|
|
396
|
-
# Get all insights in JSON format
|
|
397
|
-
cl insight --json | jq '.data[] | {id: .id, title: .title, status: .status}'
|
|
398
|
-
```
|
|
399
|
-
|
|
400
|
-
## Output Formats
|
|
401
|
-
|
|
402
|
-
### Table Format (Default)
|
|
403
|
-
```
|
|
404
|
-
┌─────────────────────────────────────┬─────────────────────────────┬─────────────┬─────────────┐
|
|
405
|
-
│ ID │ Title │ Status │ Created │
|
|
406
|
-
├─────────────────────────────────────┼─────────────────────────────┼─────────────┼─────────────┤
|
|
407
|
-
│ 74e3dd87-878f-41cf-8e5a-87527bbf7770 │ Dashboard UX Issues │ completed │ 2024-01-15 │
|
|
408
|
-
│ 2ea8f556-052b-4f5c-bf86-833780b3d00d │ Performance Problems │ processing │ 2024-01-15 │
|
|
409
|
-
└─────────────────────────────────────┴─────────────────────────────┴─────────────┴─────────────┘
|
|
410
|
-
```
|
|
411
|
-
|
|
412
|
-
### JSON Format
|
|
413
|
-
```json
|
|
414
|
-
{
|
|
415
|
-
"data": [
|
|
416
|
-
{
|
|
417
|
-
"id": "74e3dd87-878f-41cf-8e5a-87527bbf7770",
|
|
418
|
-
"title": "Dashboard UX Issues",
|
|
419
|
-
"content": "The new dashboard is confusing...",
|
|
420
|
-
"status": "completed",
|
|
421
|
-
"created_at": "2024-01-15T10:30:00Z"
|
|
422
|
-
}
|
|
423
|
-
],
|
|
424
|
-
"pagination": {
|
|
425
|
-
"page": 1,
|
|
426
|
-
"limit": 20,
|
|
427
|
-
"total": 1,
|
|
428
|
-
"pages": 1
|
|
429
|
-
}
|
|
430
|
-
}
|
|
431
|
-
```
|
|
432
|
-
|
|
433
|
-
## Best Practices
|
|
434
|
-
|
|
435
|
-
### 1. Use Descriptive Titles
|
|
436
|
-
```bash
|
|
437
|
-
# Good
|
|
438
|
-
cl ingest "The app crashes when uploading files" --title "File Upload Crash"
|
|
439
|
-
|
|
440
|
-
# Bad
|
|
441
|
-
cl ingest "App broken" --title "Issue"
|
|
442
|
-
```
|
|
443
|
-
|
|
444
|
-
### 2. Include Customer Context
|
|
445
|
-
```bash
|
|
446
|
-
# Good
|
|
447
|
-
cl ingest "Feature request" --customer "enterprise-123" --name "John Doe"
|
|
448
|
-
|
|
449
|
-
# Bad
|
|
450
|
-
cl ingest "Feature request"
|
|
451
|
-
```
|
|
452
|
-
|
|
453
|
-
### 3. Use JSON for Scripting
|
|
454
|
-
```bash
|
|
455
|
-
# Good
|
|
456
|
-
cl insight --json | jq '.data[0].title'
|
|
457
|
-
|
|
458
|
-
# Bad
|
|
459
|
-
cl insight | grep "Title"
|
|
460
|
-
```
|
|
461
|
-
|
|
462
|
-
### 4. Handle Errors Gracefully
|
|
463
|
-
```bash
|
|
464
|
-
#!/bin/bash
|
|
465
|
-
if ! cl ingest "$1" --wait; then
|
|
466
|
-
echo "Failed to ingest feedback"
|
|
467
|
-
exit 1
|
|
468
|
-
fi
|
|
469
|
-
```
|
|
470
|
-
|
|
471
|
-
### 5. Use Pagination for Large Datasets
|
|
472
|
-
```bash
|
|
473
|
-
# Good - increase limit for larger datasets
|
|
474
|
-
cl ingest --page 1 --limit 50
|
|
475
|
-
|
|
476
|
-
# Also good - use default pagination
|
|
477
|
-
cl ingest --page 2 # Shows 20 items per page (default)
|
|
478
|
-
|
|
479
|
-
# Bad - trying to show too many at once
|
|
480
|
-
cl ingest --limit 200 # Will be capped at 100 (max limit)
|
|
481
|
-
```
|
|
482
|
-
|
|
483
|
-
## Troubleshooting
|
|
484
|
-
|
|
485
|
-
### CLI Not Found
|
|
486
|
-
```bash
|
|
487
|
-
# Check if installed globally
|
|
488
|
-
npm list -g @closedloop-ai/cli
|
|
489
|
-
|
|
490
|
-
# Reinstall if needed
|
|
491
|
-
npm install -g @closedloop-ai/cli
|
|
492
|
-
```
|
|
493
|
-
|
|
494
|
-
### Permission Denied
|
|
495
|
-
```bash
|
|
496
|
-
# Fix npm permissions
|
|
497
|
-
sudo chown -R $(whoami) $(npm config get prefix)/{lib/node_modules,bin,share}
|
|
498
|
-
```
|
|
499
|
-
|
|
500
|
-
### API Key Not Working
|
|
501
|
-
```bash
|
|
502
|
-
# Check configuration
|
|
503
|
-
cl config
|
|
504
|
-
|
|
505
|
-
# Reset API key
|
|
506
|
-
cl config set --api-key your-new-key-here
|
|
507
|
-
```
|
|
508
|
-
|
|
509
|
-
### Slow Performance
|
|
510
|
-
```bash
|
|
511
|
-
# Check internet connection
|
|
512
|
-
ping mcp.closedloop.sh
|
|
513
|
-
|
|
514
|
-
# Try with smaller batches
|
|
515
|
-
cl input --limit 10
|
|
516
|
-
```
|
|
517
|
-
|
|
518
|
-
## Support
|
|
519
|
-
|
|
520
|
-
- **Documentation**: [https://docs.closedloop.sh](https://docs.closedloop.sh)
|
|
521
|
-
- **GitHub Issues**: [https://github.com/closed-loop-ai/closedloop-cli/issues](https://github.com/closed-loop-ai/closedloop-cli/issues)
|
|
522
|
-
- **Email**: support@closedloop.sh
|
|
@@ -1,151 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
const axios_1 = __importDefault(require("axios"));
|
|
7
|
-
const team_1 = require("../api/team");
|
|
8
|
-
// Mock axios
|
|
9
|
-
jest.mock('axios');
|
|
10
|
-
const mockedAxios = axios_1.default;
|
|
11
|
-
// Mock config
|
|
12
|
-
jest.mock('../config', () => ({
|
|
13
|
-
config: {
|
|
14
|
-
get: jest.fn().mockReturnValue('test-api-key')
|
|
15
|
-
}
|
|
16
|
-
}));
|
|
17
|
-
// Mock constants
|
|
18
|
-
jest.mock('../config/constants', () => ({
|
|
19
|
-
CONFIG: {
|
|
20
|
-
API_BASE_URL: 'https://mcp.closedloop.sh'
|
|
21
|
-
}
|
|
22
|
-
}));
|
|
23
|
-
describe('API Client Integration Tests', () => {
|
|
24
|
-
beforeEach(() => {
|
|
25
|
-
jest.clearAllMocks();
|
|
26
|
-
mockedAxios.create.mockReturnValue(mockedAxios);
|
|
27
|
-
});
|
|
28
|
-
describe('getTeamWebsite', () => {
|
|
29
|
-
it('should make GET request to correct endpoint', async () => {
|
|
30
|
-
const mockResponse = {
|
|
31
|
-
data: {
|
|
32
|
-
success: true,
|
|
33
|
-
data: {
|
|
34
|
-
website: 'https://example.com',
|
|
35
|
-
updated_at: '2024-01-15T10:30:00Z'
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
};
|
|
39
|
-
mockedAxios.get.mockResolvedValue(mockResponse);
|
|
40
|
-
const result = await (0, team_1.getTeamWebsite)();
|
|
41
|
-
expect(mockedAxios.create).toHaveBeenCalledWith({
|
|
42
|
-
baseURL: 'https://mcp.closedloop.sh',
|
|
43
|
-
headers: {
|
|
44
|
-
'Authorization': 'Bearer test-api-key',
|
|
45
|
-
'Content-Type': 'application/json',
|
|
46
|
-
},
|
|
47
|
-
timeout: 30000,
|
|
48
|
-
});
|
|
49
|
-
expect(mockedAxios.get).toHaveBeenCalledWith('/team/website');
|
|
50
|
-
expect(result).toEqual({
|
|
51
|
-
website: 'https://example.com',
|
|
52
|
-
updated_at: '2024-01-15T10:30:00Z'
|
|
53
|
-
});
|
|
54
|
-
});
|
|
55
|
-
it('should handle API error responses', async () => {
|
|
56
|
-
const mockError = {
|
|
57
|
-
response: {
|
|
58
|
-
status: 404,
|
|
59
|
-
data: { message: 'Team not found' }
|
|
60
|
-
}
|
|
61
|
-
};
|
|
62
|
-
mockedAxios.get.mockRejectedValue(mockError);
|
|
63
|
-
await expect((0, team_1.getTeamWebsite)()).rejects.toThrow('Resource not found');
|
|
64
|
-
});
|
|
65
|
-
it('should handle network errors', async () => {
|
|
66
|
-
const mockError = {
|
|
67
|
-
code: 'ENOTFOUND',
|
|
68
|
-
message: 'Network error'
|
|
69
|
-
};
|
|
70
|
-
mockedAxios.get.mockRejectedValue(mockError);
|
|
71
|
-
await expect((0, team_1.getTeamWebsite)()).rejects.toThrow('Cannot connect to ClosedLoop AI servers');
|
|
72
|
-
});
|
|
73
|
-
});
|
|
74
|
-
describe('updateTeamWebsite', () => {
|
|
75
|
-
it('should make POST request with correct data', async () => {
|
|
76
|
-
const mockResponse = {
|
|
77
|
-
data: {
|
|
78
|
-
success: true,
|
|
79
|
-
data: {
|
|
80
|
-
website: 'https://example.com',
|
|
81
|
-
updated_at: '2024-01-15T10:30:00Z'
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
};
|
|
85
|
-
mockedAxios.post.mockResolvedValue(mockResponse);
|
|
86
|
-
const result = await (0, team_1.updateTeamWebsite)('https://example.com');
|
|
87
|
-
expect(mockedAxios.post).toHaveBeenCalledWith('/team/website', {
|
|
88
|
-
website: 'https://example.com'
|
|
89
|
-
});
|
|
90
|
-
expect(result).toEqual({
|
|
91
|
-
website: 'https://example.com',
|
|
92
|
-
updated_at: '2024-01-15T10:30:00Z'
|
|
93
|
-
});
|
|
94
|
-
});
|
|
95
|
-
it('should validate URL format before making request', async () => {
|
|
96
|
-
await expect((0, team_1.updateTeamWebsite)('invalid-url')).rejects.toThrow('Invalid website URL format');
|
|
97
|
-
expect(mockedAxios.post).not.toHaveBeenCalled();
|
|
98
|
-
});
|
|
99
|
-
it('should handle API error responses', async () => {
|
|
100
|
-
const mockError = {
|
|
101
|
-
response: {
|
|
102
|
-
status: 500,
|
|
103
|
-
data: { message: 'Internal server error' }
|
|
104
|
-
}
|
|
105
|
-
};
|
|
106
|
-
mockedAxios.post.mockRejectedValue(mockError);
|
|
107
|
-
await expect((0, team_1.updateTeamWebsite)('https://example.com')).rejects.toThrow('Server error');
|
|
108
|
-
});
|
|
109
|
-
it('should handle unsuccessful API responses', async () => {
|
|
110
|
-
const mockResponse = {
|
|
111
|
-
data: {
|
|
112
|
-
success: false,
|
|
113
|
-
message: 'Update failed'
|
|
114
|
-
}
|
|
115
|
-
};
|
|
116
|
-
mockedAxios.post.mockResolvedValue(mockResponse);
|
|
117
|
-
await expect((0, team_1.updateTeamWebsite)('https://example.com')).rejects.toThrow('Failed to update team website');
|
|
118
|
-
});
|
|
119
|
-
});
|
|
120
|
-
describe('Error Handling', () => {
|
|
121
|
-
it('should handle 401 unauthorized errors', async () => {
|
|
122
|
-
const mockError = {
|
|
123
|
-
response: {
|
|
124
|
-
status: 401,
|
|
125
|
-
data: { message: 'Unauthorized' }
|
|
126
|
-
}
|
|
127
|
-
};
|
|
128
|
-
mockedAxios.get.mockRejectedValue(mockError);
|
|
129
|
-
await expect((0, team_1.getTeamWebsite)()).rejects.toThrow('Invalid API key');
|
|
130
|
-
});
|
|
131
|
-
it('should handle 429 rate limit errors', async () => {
|
|
132
|
-
const mockError = {
|
|
133
|
-
response: {
|
|
134
|
-
status: 429,
|
|
135
|
-
data: { message: 'Rate limited' }
|
|
136
|
-
}
|
|
137
|
-
};
|
|
138
|
-
mockedAxios.get.mockRejectedValue(mockError);
|
|
139
|
-
await expect((0, team_1.getTeamWebsite)()).rejects.toThrow('Rate limit exceeded');
|
|
140
|
-
});
|
|
141
|
-
it('should handle timeout errors', async () => {
|
|
142
|
-
const mockError = {
|
|
143
|
-
code: 'ETIMEDOUT',
|
|
144
|
-
message: 'Request timeout'
|
|
145
|
-
};
|
|
146
|
-
mockedAxios.get.mockRejectedValue(mockError);
|
|
147
|
-
await expect((0, team_1.getTeamWebsite)()).rejects.toThrow('Request timed out');
|
|
148
|
-
});
|
|
149
|
-
});
|
|
150
|
-
});
|
|
151
|
-
//# sourceMappingURL=api.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"api.test.js","sourceRoot":"","sources":["../../src/__tests__/api.test.ts"],"names":[],"mappings":"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"}
|