@profoundlogic/coderflow-cli 0.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.
- package/LICENSE.txt +322 -0
- package/README.md +102 -0
- package/coder.js +202 -0
- package/lib/commands/apply.js +238 -0
- package/lib/commands/attach.js +143 -0
- package/lib/commands/config.js +226 -0
- package/lib/commands/containers.js +213 -0
- package/lib/commands/discard.js +167 -0
- package/lib/commands/interactive.js +292 -0
- package/lib/commands/jira.js +464 -0
- package/lib/commands/license.js +172 -0
- package/lib/commands/list.js +104 -0
- package/lib/commands/login.js +329 -0
- package/lib/commands/logs.js +66 -0
- package/lib/commands/profile.js +539 -0
- package/lib/commands/reject.js +53 -0
- package/lib/commands/results.js +89 -0
- package/lib/commands/run.js +237 -0
- package/lib/commands/server.js +537 -0
- package/lib/commands/status.js +39 -0
- package/lib/commands/test.js +335 -0
- package/lib/config.js +378 -0
- package/lib/help.js +444 -0
- package/lib/http-client.js +180 -0
- package/lib/oidc.js +126 -0
- package/lib/profile.js +296 -0
- package/lib/state-capture.js +336 -0
- package/lib/task-grouping.js +210 -0
- package/lib/terminal-client.js +162 -0
- package/package.json +35 -0
package/lib/help.js
ADDED
|
@@ -0,0 +1,444 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Help text and usage information
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
const commandHelp = {
|
|
6
|
+
apply: `
|
|
7
|
+
Usage: coder apply [task-id] [options]
|
|
8
|
+
|
|
9
|
+
Apply patches from a completed task to your local repositories.
|
|
10
|
+
Changes are staged (git add) but not committed.
|
|
11
|
+
|
|
12
|
+
Arguments:
|
|
13
|
+
task-id Task ID to apply (optional - interactive selection if omitted)
|
|
14
|
+
|
|
15
|
+
Options:
|
|
16
|
+
--include=<pattern> Only apply files matching glob pattern
|
|
17
|
+
|
|
18
|
+
Examples:
|
|
19
|
+
coder apply # Interactive selection from completed tasks
|
|
20
|
+
coder apply 1759542727986-3uoyf48lr # Apply specific task
|
|
21
|
+
coder apply --include="*.js" # Only apply JavaScript files
|
|
22
|
+
`,
|
|
23
|
+
|
|
24
|
+
discard: `
|
|
25
|
+
Usage: coder discard [options]
|
|
26
|
+
|
|
27
|
+
Discard all uncommitted changes from repositories (unstage, restore, clean).
|
|
28
|
+
Use this to undo changes applied with 'coder apply'.
|
|
29
|
+
|
|
30
|
+
Options:
|
|
31
|
+
--env=<environment> Environment to discard changes from (uses default if omitted)
|
|
32
|
+
--yes Skip confirmation prompt
|
|
33
|
+
|
|
34
|
+
Examples:
|
|
35
|
+
coder discard # Discard changes in default environment
|
|
36
|
+
coder discard --env=hello # Discard changes in specific environment
|
|
37
|
+
coder discard --yes # Skip confirmation
|
|
38
|
+
`,
|
|
39
|
+
|
|
40
|
+
attach: `
|
|
41
|
+
Usage: coder attach [container-id] [options]
|
|
42
|
+
|
|
43
|
+
Connect to a running container.
|
|
44
|
+
|
|
45
|
+
Arguments:
|
|
46
|
+
container-id Container ID to attach to (optional - uses last container if omitted)
|
|
47
|
+
|
|
48
|
+
Options:
|
|
49
|
+
--agent=<agent> Agent to use (claude, codex)
|
|
50
|
+
--shell Start bash shell instead of agent
|
|
51
|
+
|
|
52
|
+
Examples:
|
|
53
|
+
coder attach # Reconnect to last container
|
|
54
|
+
coder attach 188b8e72d656 # Connect to specific container
|
|
55
|
+
coder attach --shell # Connect with bash shell
|
|
56
|
+
coder attach --agent=codex # Connect with specific agent
|
|
57
|
+
`,
|
|
58
|
+
|
|
59
|
+
login: `
|
|
60
|
+
Usage: coder login [options]
|
|
61
|
+
|
|
62
|
+
Authenticate with the CoderFlow server.
|
|
63
|
+
|
|
64
|
+
Options:
|
|
65
|
+
--sso Use Single Sign-On (OIDC) authentication
|
|
66
|
+
|
|
67
|
+
Without --sso, prompts for username and password.
|
|
68
|
+
With --sso, opens browser for OIDC device flow authentication.
|
|
69
|
+
|
|
70
|
+
Examples:
|
|
71
|
+
coder login # Username/password login
|
|
72
|
+
coder login --sso # SSO/OIDC login
|
|
73
|
+
`,
|
|
74
|
+
|
|
75
|
+
config: `
|
|
76
|
+
Usage: coder config <command> [key] [value]
|
|
77
|
+
|
|
78
|
+
Manage CLI configuration settings.
|
|
79
|
+
|
|
80
|
+
Commands:
|
|
81
|
+
show Show all configuration
|
|
82
|
+
get <key> Get a configuration value
|
|
83
|
+
set <key> <value> Set a configuration value
|
|
84
|
+
remove <key> Remove a configuration value
|
|
85
|
+
|
|
86
|
+
Keys:
|
|
87
|
+
serverUrl Server URL
|
|
88
|
+
apiKey API key (use 'coder login' instead)
|
|
89
|
+
defaultEnvironment Default environment for commands
|
|
90
|
+
|
|
91
|
+
Examples:
|
|
92
|
+
coder config show
|
|
93
|
+
coder config set serverUrl http://localhost:3000
|
|
94
|
+
coder config get serverUrl
|
|
95
|
+
coder config remove defaultEnvironment
|
|
96
|
+
`,
|
|
97
|
+
|
|
98
|
+
profile: `
|
|
99
|
+
Usage: coder profile <command> [options]
|
|
100
|
+
|
|
101
|
+
Manage CLI configuration profiles for multiple servers/environments.
|
|
102
|
+
|
|
103
|
+
Commands:
|
|
104
|
+
list List all profiles
|
|
105
|
+
show [name] Show profile details (active if no name)
|
|
106
|
+
create <name> Create a new profile
|
|
107
|
+
switch <name> Switch to a different profile
|
|
108
|
+
delete <name> Delete a profile
|
|
109
|
+
copy <source> <dest> Copy a profile
|
|
110
|
+
set <key> <value> Set a value in the active profile
|
|
111
|
+
get <key> Get a value from the active profile
|
|
112
|
+
current Show the current active profile name
|
|
113
|
+
migrate <name> Create profile from legacy config
|
|
114
|
+
|
|
115
|
+
Examples:
|
|
116
|
+
coder profile list
|
|
117
|
+
coder profile create prod
|
|
118
|
+
coder profile switch prod
|
|
119
|
+
coder profile set serverUrl https://prod.example.com
|
|
120
|
+
coder --profile=prod list # Use profile for single command
|
|
121
|
+
`,
|
|
122
|
+
|
|
123
|
+
run: `
|
|
124
|
+
Usage: coder run [task-type] [options]
|
|
125
|
+
|
|
126
|
+
Create and run a task. Usually done in the Web UI, but available here
|
|
127
|
+
for scripting or when browser access isn't available.
|
|
128
|
+
|
|
129
|
+
Arguments:
|
|
130
|
+
task-type Task template name (optional - interactive if omitted)
|
|
131
|
+
|
|
132
|
+
Options:
|
|
133
|
+
--env=<environment> Environment to run in
|
|
134
|
+
--<param>=<value> Template parameters (varies by template)
|
|
135
|
+
|
|
136
|
+
Examples:
|
|
137
|
+
coder run # Interactive task creation
|
|
138
|
+
coder run add-function --function_name=multiply # Run with template
|
|
139
|
+
coder run fix-test --env=hello --verbose=true # Specify environment
|
|
140
|
+
`,
|
|
141
|
+
|
|
142
|
+
status: `
|
|
143
|
+
Usage: coder status <task-id>
|
|
144
|
+
|
|
145
|
+
Check the status of a task.
|
|
146
|
+
|
|
147
|
+
Arguments:
|
|
148
|
+
task-id Task ID to check (required)
|
|
149
|
+
|
|
150
|
+
Examples:
|
|
151
|
+
coder status 1759542727986-3uoyf48lr
|
|
152
|
+
`,
|
|
153
|
+
|
|
154
|
+
results: `
|
|
155
|
+
Usage: coder results <task-id>
|
|
156
|
+
|
|
157
|
+
Get the results of a completed task.
|
|
158
|
+
|
|
159
|
+
Arguments:
|
|
160
|
+
task-id Task ID to get results for (required)
|
|
161
|
+
|
|
162
|
+
Examples:
|
|
163
|
+
coder results 1759542727986-3uoyf48lr
|
|
164
|
+
`,
|
|
165
|
+
|
|
166
|
+
logs: `
|
|
167
|
+
Usage: coder logs <task-id> [options]
|
|
168
|
+
|
|
169
|
+
Show logs from a task.
|
|
170
|
+
|
|
171
|
+
Arguments:
|
|
172
|
+
task-id Task ID to show logs for (required)
|
|
173
|
+
|
|
174
|
+
Options:
|
|
175
|
+
--tail=<N> Show last N lines only
|
|
176
|
+
|
|
177
|
+
Examples:
|
|
178
|
+
coder logs 1759542727986-3uoyf48lr
|
|
179
|
+
coder logs 1759542727986-3uoyf48lr --tail=100
|
|
180
|
+
`,
|
|
181
|
+
|
|
182
|
+
list: `
|
|
183
|
+
Usage: coder list [options]
|
|
184
|
+
|
|
185
|
+
List tasks with optional filters.
|
|
186
|
+
|
|
187
|
+
Options:
|
|
188
|
+
--status=<status> Filter by status (pending, running, completed, failed)
|
|
189
|
+
--environment=<name> Filter by environment
|
|
190
|
+
|
|
191
|
+
Examples:
|
|
192
|
+
coder list
|
|
193
|
+
coder list --status=completed
|
|
194
|
+
coder list --environment=hello --status=running
|
|
195
|
+
`,
|
|
196
|
+
|
|
197
|
+
reject: `
|
|
198
|
+
Usage: coder reject <task-id> [options]
|
|
199
|
+
|
|
200
|
+
Reject task results.
|
|
201
|
+
|
|
202
|
+
Arguments:
|
|
203
|
+
task-id Task ID to reject (required)
|
|
204
|
+
|
|
205
|
+
Options:
|
|
206
|
+
--cleanup Also delete task artifacts
|
|
207
|
+
|
|
208
|
+
Examples:
|
|
209
|
+
coder reject 1759542727986-3uoyf48lr
|
|
210
|
+
coder reject 1759542727986-3uoyf48lr --cleanup
|
|
211
|
+
`,
|
|
212
|
+
|
|
213
|
+
start: `
|
|
214
|
+
Usage: coder start <environment> [options]
|
|
215
|
+
|
|
216
|
+
Start an interactive session with an AI agent.
|
|
217
|
+
Usually done in the Web UI, but available here for CLI workflows.
|
|
218
|
+
|
|
219
|
+
Arguments:
|
|
220
|
+
environment Environment to start session in (required)
|
|
221
|
+
|
|
222
|
+
Options:
|
|
223
|
+
--agent=<agent> Agent to use (claude, codex)
|
|
224
|
+
--no-attach Start container but don't auto-connect
|
|
225
|
+
--branch <repo>=<branch> Override branch for specific repository
|
|
226
|
+
--env=<KEY>=<value> Pass custom environment variables
|
|
227
|
+
|
|
228
|
+
Examples:
|
|
229
|
+
coder start hello
|
|
230
|
+
coder start hello --agent=codex
|
|
231
|
+
coder start hello --no-attach
|
|
232
|
+
coder start hello --branch profoundjs=feature-xyz
|
|
233
|
+
`,
|
|
234
|
+
|
|
235
|
+
shell: `
|
|
236
|
+
Usage: coder shell <environment> [options]
|
|
237
|
+
|
|
238
|
+
Start an interactive bash shell session in an environment.
|
|
239
|
+
Usually done in the Web UI, but available here for CLI workflows.
|
|
240
|
+
|
|
241
|
+
Arguments:
|
|
242
|
+
environment Environment to start shell in (required)
|
|
243
|
+
|
|
244
|
+
Options:
|
|
245
|
+
--no-attach Start container but don't auto-connect
|
|
246
|
+
--branch <repo>=<branch> Override branch for specific repository
|
|
247
|
+
--env=<KEY>=<value> Pass custom environment variables
|
|
248
|
+
|
|
249
|
+
Examples:
|
|
250
|
+
coder shell hello
|
|
251
|
+
coder shell hello --branch profoundjs=feature-xyz
|
|
252
|
+
`,
|
|
253
|
+
|
|
254
|
+
test: `
|
|
255
|
+
Usage: coder test <test-name> [options]
|
|
256
|
+
|
|
257
|
+
Run tests in an ephemeral container with your local repository state.
|
|
258
|
+
|
|
259
|
+
Arguments:
|
|
260
|
+
test-name Name of the test to run (from environment's tests.json)
|
|
261
|
+
|
|
262
|
+
Options:
|
|
263
|
+
--env=<environment> Environment to run test in (uses default if omitted)
|
|
264
|
+
--cmd="<command>" Run custom command instead of named test
|
|
265
|
+
--list List available tests for the environment
|
|
266
|
+
--no-local-state Don't capture local repo state
|
|
267
|
+
|
|
268
|
+
Examples:
|
|
269
|
+
coder test mytest --env=hello # Run named test
|
|
270
|
+
coder test --list --env=hello # List available tests
|
|
271
|
+
coder test --cmd="npm test" # Run custom command
|
|
272
|
+
coder test mytest --no-local-state # Run without local changes
|
|
273
|
+
`,
|
|
274
|
+
|
|
275
|
+
containers: `
|
|
276
|
+
Usage: coder containers [command] [options]
|
|
277
|
+
|
|
278
|
+
List or clean containers.
|
|
279
|
+
|
|
280
|
+
Commands:
|
|
281
|
+
(none) List all containers
|
|
282
|
+
clean Clean up containers
|
|
283
|
+
|
|
284
|
+
Options (for clean):
|
|
285
|
+
--stopped Clean stopped containers
|
|
286
|
+
--older-than=<time> Clean containers older than time (e.g., 7d, 24h)
|
|
287
|
+
--dry-run Show what would be cleaned without doing it
|
|
288
|
+
--yes Skip confirmation
|
|
289
|
+
|
|
290
|
+
Examples:
|
|
291
|
+
coder containers
|
|
292
|
+
coder containers clean --stopped --yes
|
|
293
|
+
coder containers clean --older-than=7d --dry-run
|
|
294
|
+
`
|
|
295
|
+
};
|
|
296
|
+
|
|
297
|
+
/**
|
|
298
|
+
* Show help for a specific command
|
|
299
|
+
*/
|
|
300
|
+
export function showCommandHelp(command) {
|
|
301
|
+
const help = commandHelp[command];
|
|
302
|
+
if (help) {
|
|
303
|
+
console.log(help);
|
|
304
|
+
return true;
|
|
305
|
+
}
|
|
306
|
+
return false;
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
export function showHelp() {
|
|
310
|
+
console.log(`
|
|
311
|
+
CoderFlow CLI
|
|
312
|
+
|
|
313
|
+
Usage: coder <command> [options]
|
|
314
|
+
|
|
315
|
+
Commands:
|
|
316
|
+
coder apply [task-id] Apply patches from completed task to local repos
|
|
317
|
+
coder discard [--env=<environment>] [--yes] Discard applied changes from repos
|
|
318
|
+
coder attach [container-id] [options] Connect to a running container
|
|
319
|
+
|
|
320
|
+
Setup:
|
|
321
|
+
coder login [--sso] Authenticate with server
|
|
322
|
+
coder config <set|get|remove|show> [key] [value] Manage CLI configuration
|
|
323
|
+
coder profile <command> [options] Manage connection profiles
|
|
324
|
+
|
|
325
|
+
Global Options:
|
|
326
|
+
--profile=<name> Use a specific profile for this command
|
|
327
|
+
|
|
328
|
+
Examples:
|
|
329
|
+
coder apply # Interactively select a completed task to apply
|
|
330
|
+
coder apply 1759542727986-3uoyf48lr # Apply patches from specific task
|
|
331
|
+
coder discard # Undo applied changes in default environment
|
|
332
|
+
coder discard --env=hello # Undo changes in specific environment
|
|
333
|
+
coder attach # Connect to last container
|
|
334
|
+
coder attach --shell # Connect and start bash shell
|
|
335
|
+
|
|
336
|
+
Task creation and management is best done in the Web UI.
|
|
337
|
+
For CLI alternatives to Web UI features: coder --help-all
|
|
338
|
+
|
|
339
|
+
Run 'coder <command> --help' for detailed command usage.
|
|
340
|
+
`);
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
export function showExtendedHelp() {
|
|
344
|
+
console.log(`
|
|
345
|
+
CoderFlow CLI - All Commands
|
|
346
|
+
|
|
347
|
+
================================================================================
|
|
348
|
+
CORE COMMANDS
|
|
349
|
+
================================================================================
|
|
350
|
+
|
|
351
|
+
These are the primary CLI commands for working with your local repositories.
|
|
352
|
+
|
|
353
|
+
Applying Changes:
|
|
354
|
+
coder apply [task-id] Apply patches from completed task to local repos
|
|
355
|
+
coder discard [--env=<environment>] [--yes] Discard applied changes from repos
|
|
356
|
+
|
|
357
|
+
Connecting to Containers:
|
|
358
|
+
coder attach [container-id] [--agent=<agent>] [--shell] Connect to a running container
|
|
359
|
+
|
|
360
|
+
Setup & Configuration:
|
|
361
|
+
coder login [--sso] Authenticate with server
|
|
362
|
+
coder config <set|get|remove|show> [key] [value] Manage CLI configuration
|
|
363
|
+
coder profile <command> [options] Manage connection profiles
|
|
364
|
+
|
|
365
|
+
================================================================================
|
|
366
|
+
CLI ALTERNATIVES TO WEB UI
|
|
367
|
+
================================================================================
|
|
368
|
+
|
|
369
|
+
These commands provide command-line access to features typically managed
|
|
370
|
+
through the Web UI. Use these when you prefer command-line workflows or
|
|
371
|
+
don't have browser access.
|
|
372
|
+
|
|
373
|
+
Task Management:
|
|
374
|
+
coder run <task-type> [--env=<env>] [--param=val] Create and run a task with template
|
|
375
|
+
coder run Create and run a task interactively
|
|
376
|
+
coder status <task-id> Check status of a task
|
|
377
|
+
coder results <task-id> Get results of a completed task
|
|
378
|
+
coder logs <task-id> [--tail=N] Show task logs
|
|
379
|
+
coder list [--status=...] [--environment=...] List tasks with optional filters
|
|
380
|
+
coder reject <task-id> [--cleanup] Reject task results
|
|
381
|
+
|
|
382
|
+
Interactive Sessions:
|
|
383
|
+
coder start <environment> [options] Start interactive session with AI agent
|
|
384
|
+
coder shell <environment> [options] Start interactive session with bash shell
|
|
385
|
+
|
|
386
|
+
Testing & Containers:
|
|
387
|
+
coder test <test-name> [--env=<environment>] Run tests in environment
|
|
388
|
+
coder containers [clean] [options] List or clean containers
|
|
389
|
+
|
|
390
|
+
================================================================================
|
|
391
|
+
PROFILE COMMANDS
|
|
392
|
+
================================================================================
|
|
393
|
+
|
|
394
|
+
coder profile list List all profiles (shows active profile)
|
|
395
|
+
coder profile show [name] Show profile details (active if no name)
|
|
396
|
+
coder profile create <name> Create a new profile
|
|
397
|
+
coder profile switch <name> Switch to a different profile
|
|
398
|
+
coder profile delete <name> Delete a profile
|
|
399
|
+
coder profile copy <source> <dest> Copy an existing profile
|
|
400
|
+
coder profile set <key> <value> Set a value in the active profile
|
|
401
|
+
coder profile get <key> Get a value from the active profile
|
|
402
|
+
coder profile current Show the current active profile name
|
|
403
|
+
coder profile migrate <name> Create profile from legacy config
|
|
404
|
+
|
|
405
|
+
================================================================================
|
|
406
|
+
ENVIRONMENT VARIABLES
|
|
407
|
+
================================================================================
|
|
408
|
+
|
|
409
|
+
CODER_SERVER_URL Server URL (default: http://localhost:3000)
|
|
410
|
+
CODER_API_KEY API key for authentication (use 'coder login' to generate)
|
|
411
|
+
CODER_PROFILE Override active profile (takes precedence over config)
|
|
412
|
+
|
|
413
|
+
================================================================================
|
|
414
|
+
EXAMPLES
|
|
415
|
+
================================================================================
|
|
416
|
+
|
|
417
|
+
Core Workflow:
|
|
418
|
+
coder apply # Interactively select a completed task
|
|
419
|
+
coder apply 1759542727986-3uoyf48lr # Apply patches from specific task
|
|
420
|
+
coder discard # Undo all changes in default environment
|
|
421
|
+
coder discard --env=hello --yes # Undo changes, skip confirmation
|
|
422
|
+
coder attach # Connect to last container
|
|
423
|
+
coder attach 188b8e72d656 --shell # Connect to specific container with shell
|
|
424
|
+
|
|
425
|
+
Setup:
|
|
426
|
+
coder login # Authenticate with username/password
|
|
427
|
+
coder login --sso # Authenticate with SSO/OIDC
|
|
428
|
+
coder config set serverUrl http://localhost:3000 # Set server URL
|
|
429
|
+
coder profile create prod # Create a new profile
|
|
430
|
+
coder profile switch prod # Switch to prod profile
|
|
431
|
+
|
|
432
|
+
Task Management (Web UI alternative):
|
|
433
|
+
coder run add-function --function_name=multiply # Run task with template
|
|
434
|
+
coder run add-function --env=hello --verbose=true # Run in specific environment
|
|
435
|
+
coder status 1759542727986-3uoyf48lr # Check task status
|
|
436
|
+
coder results 1759542727986-3uoyf48lr # Get task results
|
|
437
|
+
coder list --status=completed # List completed tasks
|
|
438
|
+
|
|
439
|
+
Interactive Sessions (Web UI alternative):
|
|
440
|
+
coder start hello # Start AI agent in environment
|
|
441
|
+
coder start hello --agent=codex # Start with specific agent
|
|
442
|
+
coder shell hello # Start bash shell in environment
|
|
443
|
+
`);
|
|
444
|
+
}
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HTTP client for Coder Server API
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { getServerUrl, getApiKey } from './config.js';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Format a helpful error message based on error type
|
|
9
|
+
*/
|
|
10
|
+
function formatErrorMessage(error, url, response, serverUrl) {
|
|
11
|
+
// Connection errors
|
|
12
|
+
if (error.code === 'ECONNREFUSED' || error.cause?.code === 'ECONNREFUSED') {
|
|
13
|
+
console.error(`\nError: Cannot connect to Coder server at ${serverUrl}`);
|
|
14
|
+
console.error('\nPossible solutions:');
|
|
15
|
+
console.error(' 1. Start the server:');
|
|
16
|
+
console.error(' cd packages/server && CODER_SETUP_PATH=/path/to/coder-setup npm start');
|
|
17
|
+
console.error(' 2. Check if server is running on a different port');
|
|
18
|
+
console.error(' 3. Set CODER_SERVER_URL environment variable if using non-default port');
|
|
19
|
+
return true;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
if (error.code === 'ENOTFOUND' || error.cause?.code === 'ENOTFOUND') {
|
|
23
|
+
console.error(`\nError: Cannot resolve hostname: ${serverUrl}`);
|
|
24
|
+
console.error('\nCheck CODER_SERVER_URL environment variable');
|
|
25
|
+
return true;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// HTTP errors with response
|
|
29
|
+
if (response) {
|
|
30
|
+
const status = response.status;
|
|
31
|
+
const message = error.message;
|
|
32
|
+
|
|
33
|
+
// Special case: 404 on local-state-summary is expected (file not created yet)
|
|
34
|
+
// Don't treat as fatal error, allow retry logic to handle it
|
|
35
|
+
if (status === 404 && url.includes('/local-state-summary')) {
|
|
36
|
+
return false; // Not fatal, caller can retry
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
console.error(`\nError: ${message}`);
|
|
40
|
+
|
|
41
|
+
// Provide actionable guidance based on status code
|
|
42
|
+
if (status === 401) {
|
|
43
|
+
console.error('\nAuthentication required.');
|
|
44
|
+
console.error('Possible solutions:');
|
|
45
|
+
console.error(' 1. Log in: coder login');
|
|
46
|
+
console.error(' 2. Set API key: export CODER_API_KEY=your-key');
|
|
47
|
+
console.error(' 3. Your session may have expired - log in again');
|
|
48
|
+
} else if (status === 403) {
|
|
49
|
+
console.error('\nPermission denied.');
|
|
50
|
+
console.error('You do not have permission to access this resource.');
|
|
51
|
+
console.error('Contact an administrator if you believe this is an error.');
|
|
52
|
+
} else if (status === 404) {
|
|
53
|
+
if (url.includes('/tasks/')) {
|
|
54
|
+
console.error('\nThe requested task was not found.');
|
|
55
|
+
console.error('Possible solutions:');
|
|
56
|
+
console.error(' 1. Check the task ID is correct');
|
|
57
|
+
console.error(' 2. Use "coder list" to see all tasks');
|
|
58
|
+
console.error(' 3. Server may have been restarted (task state is not persistent)');
|
|
59
|
+
} else if (url.includes('/containers/')) {
|
|
60
|
+
console.error('\nThe requested container was not found.');
|
|
61
|
+
console.error('Possible solutions:');
|
|
62
|
+
console.error(' 1. Check the container ID is correct');
|
|
63
|
+
console.error(' 2. Use "coder containers" to list all containers');
|
|
64
|
+
} else if (url.includes('/environments/')) {
|
|
65
|
+
console.error('\nThe requested environment was not found.');
|
|
66
|
+
console.error('Possible solutions:');
|
|
67
|
+
console.error(' 1. Check environment name spelling');
|
|
68
|
+
console.error(' 2. Use "coder run --env=<name>" with a valid environment');
|
|
69
|
+
console.error(' 3. Check environments/ directory in your coder-setup');
|
|
70
|
+
}
|
|
71
|
+
} else if (status === 400) {
|
|
72
|
+
console.error('\nBad request - check your command arguments');
|
|
73
|
+
} else if (status === 413) {
|
|
74
|
+
console.error('\nRequest too large.');
|
|
75
|
+
console.error('\nThe data you are trying to send is too large for the server to process.');
|
|
76
|
+
console.error('This typically occurs when capturing local state with large diffs.');
|
|
77
|
+
console.error('\nPossible solutions:');
|
|
78
|
+
console.error(' 1. Commit or stash large changes before capturing local state');
|
|
79
|
+
console.error(' 2. Reduce the number of modified files');
|
|
80
|
+
console.error(' 3. Contact an administrator to increase server payload limits');
|
|
81
|
+
} else if (status === 500) {
|
|
82
|
+
console.error('\nServer error occurred.');
|
|
83
|
+
|
|
84
|
+
// Show detailed error message if available
|
|
85
|
+
if (error.detailedError && error.detailedError !== message) {
|
|
86
|
+
console.error(`\nServer Error Details:`);
|
|
87
|
+
console.error(` ${error.detailedError}`);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
console.error('\nPossible solutions:');
|
|
91
|
+
console.error(' 1. Check server logs for details');
|
|
92
|
+
console.error(' 2. Verify Docker is running: docker ps');
|
|
93
|
+
console.error(' 3. Check CODER_SETUP_PATH is set correctly');
|
|
94
|
+
console.error(' 4. Verify coder-setup configuration files are valid');
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
return true;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
return false;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Make HTTP request to Coder Server
|
|
105
|
+
*/
|
|
106
|
+
export async function request(path, options = {}) {
|
|
107
|
+
const serverUrl = await getServerUrl();
|
|
108
|
+
const url = `${serverUrl}${path}`;
|
|
109
|
+
|
|
110
|
+
try {
|
|
111
|
+
const { parse = 'json', ...fetchOptions } = options;
|
|
112
|
+
|
|
113
|
+
// Get API key and add to headers if available
|
|
114
|
+
const apiKey = await getApiKey();
|
|
115
|
+
const headers = {
|
|
116
|
+
'Content-Type': 'application/json',
|
|
117
|
+
...fetchOptions.headers
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
if (apiKey) {
|
|
121
|
+
headers['Authorization'] = `Bearer ${apiKey}`;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
const response = await fetch(url, {
|
|
125
|
+
...fetchOptions,
|
|
126
|
+
headers
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
let data;
|
|
130
|
+
|
|
131
|
+
if (parse === 'text') {
|
|
132
|
+
data = await response.text();
|
|
133
|
+
} else {
|
|
134
|
+
const contentType = response.headers.get('content-type') || '';
|
|
135
|
+
if (contentType.includes('application/json')) {
|
|
136
|
+
data = await response.json();
|
|
137
|
+
} else {
|
|
138
|
+
data = await response.text();
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
if (!response.ok) {
|
|
143
|
+
let message;
|
|
144
|
+
let detailedError = null;
|
|
145
|
+
|
|
146
|
+
if (typeof data === 'string') {
|
|
147
|
+
message = data.trim() || `HTTP ${response.status}`;
|
|
148
|
+
// Try to parse error details from string response
|
|
149
|
+
detailedError = data.trim();
|
|
150
|
+
} else {
|
|
151
|
+
message = data?.error || data?.message || `HTTP ${response.status}`;
|
|
152
|
+
// Capture additional error details if available
|
|
153
|
+
if (data?.error && data?.message) {
|
|
154
|
+
detailedError = `${data.error}: ${data.message}`;
|
|
155
|
+
} else if (data?.message) {
|
|
156
|
+
detailedError = data.message;
|
|
157
|
+
} else if (data?.error) {
|
|
158
|
+
detailedError = data.error;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
const error = new Error(message);
|
|
163
|
+
error.detailedError = detailedError;
|
|
164
|
+
error.statusCode = response.status;
|
|
165
|
+
|
|
166
|
+
if (formatErrorMessage(error, url, response, serverUrl)) {
|
|
167
|
+
process.exit(1);
|
|
168
|
+
}
|
|
169
|
+
throw error;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
return data;
|
|
173
|
+
} catch (error) {
|
|
174
|
+
// Handle network/connection errors
|
|
175
|
+
if (formatErrorMessage(error, url, null, serverUrl)) {
|
|
176
|
+
process.exit(1);
|
|
177
|
+
}
|
|
178
|
+
throw error;
|
|
179
|
+
}
|
|
180
|
+
}
|