@dharta/cli 0.6.77 → 0.6.78
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 +1 -1
- package/README.md +215 -11
- package/dist/agent.js +3 -2
- package/dist/agent.js.map +1 -1
- package/dist/api-error.js +6 -6
- package/dist/api-error.js.map +1 -1
- package/dist/cli.d.ts +3 -0
- package/dist/cli.js +860 -149
- package/dist/cli.js.map +1 -1
- package/dist/command-tree.d.ts +3 -0
- package/dist/command-tree.js +10 -0
- package/dist/command-tree.js.map +1 -0
- package/dist/commands/agents.d.ts +54 -17
- package/dist/commands/agents.js +246 -136
- package/dist/commands/agents.js.map +1 -1
- package/dist/commands/analytics.js +6 -5
- package/dist/commands/analytics.js.map +1 -1
- package/dist/commands/api.js +71 -86
- package/dist/commands/api.js.map +1 -1
- package/dist/commands/appearance.js +5 -6
- package/dist/commands/appearance.js.map +1 -1
- package/dist/commands/artifact.js +7 -6
- package/dist/commands/artifact.js.map +1 -1
- package/dist/commands/audit-log.js +2 -1
- package/dist/commands/audit-log.js.map +1 -1
- package/dist/commands/auth.js +26 -6
- package/dist/commands/auth.js.map +1 -1
- package/dist/commands/caps.js +11 -15
- package/dist/commands/caps.js.map +1 -1
- package/dist/commands/deploy.js +25 -10
- package/dist/commands/deploy.js.map +1 -1
- package/dist/commands/dev.d.ts +10 -1
- package/dist/commands/dev.js +56 -25
- package/dist/commands/dev.js.map +1 -1
- package/dist/commands/doctor.d.ts +2 -0
- package/dist/commands/doctor.js +60 -0
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/embed-keys.js +4 -13
- package/dist/commands/embed-keys.js.map +1 -1
- package/dist/commands/env.js +4 -7
- package/dist/commands/env.js.map +1 -1
- package/dist/commands/files.js +3 -4
- package/dist/commands/files.js.map +1 -1
- package/dist/commands/fleet.d.ts +129 -0
- package/dist/commands/fleet.js +408 -0
- package/dist/commands/fleet.js.map +1 -0
- package/dist/commands/genui.d.ts +2 -0
- package/dist/commands/genui.js +53 -0
- package/dist/commands/genui.js.map +1 -0
- package/dist/commands/git-credential.js +2 -3
- package/dist/commands/git-credential.js.map +1 -1
- package/dist/commands/kartas.d.ts +9 -0
- package/dist/commands/kartas.js +33 -11
- package/dist/commands/kartas.js.map +1 -1
- package/dist/commands/keys.d.ts +17 -18
- package/dist/commands/keys.js +108 -19
- package/dist/commands/keys.js.map +1 -1
- package/dist/commands/login.js +2 -1
- package/dist/commands/login.js.map +1 -1
- package/dist/commands/members.d.ts +10 -0
- package/dist/commands/members.js +20 -6
- package/dist/commands/members.js.map +1 -1
- package/dist/commands/model-connections.d.ts +44 -0
- package/dist/commands/model-connections.js +435 -0
- package/dist/commands/model-connections.js.map +1 -0
- package/dist/commands/open.d.ts +2 -2
- package/dist/commands/open.js +4 -3
- package/dist/commands/open.js.map +1 -1
- package/dist/commands/org.d.ts +9 -0
- package/dist/commands/org.js +42 -0
- package/dist/commands/org.js.map +1 -0
- package/dist/commands/organization.d.ts +16 -0
- package/dist/commands/organization.js +118 -0
- package/dist/commands/organization.js.map +1 -0
- package/dist/commands/parity.js +1 -3
- package/dist/commands/parity.js.map +1 -1
- package/dist/commands/repos.d.ts +4 -0
- package/dist/commands/repos.js +17 -0
- package/dist/commands/repos.js.map +1 -0
- package/dist/commands/rollback.js +2 -3
- package/dist/commands/rollback.js.map +1 -1
- package/dist/commands/schedules.js +26 -21
- package/dist/commands/schedules.js.map +1 -1
- package/dist/commands/scopes.js +8 -1
- package/dist/commands/scopes.js.map +1 -1
- package/dist/commands/sessions.js +9 -3
- package/dist/commands/sessions.js.map +1 -1
- package/dist/commands/setup.js +5 -4
- package/dist/commands/setup.js.map +1 -1
- package/dist/commands/update.d.ts +1 -0
- package/dist/commands/update.js +24 -11
- package/dist/commands/update.js.map +1 -1
- package/dist/commands/webhooks.d.ts +4 -1
- package/dist/commands/webhooks.js +21 -16
- package/dist/commands/webhooks.js.map +1 -1
- package/dist/completions.js +24 -13
- package/dist/completions.js.map +1 -1
- package/dist/config.d.ts +12 -0
- package/dist/config.js +121 -7
- package/dist/config.js.map +1 -1
- package/dist/context.d.ts +2 -0
- package/dist/context.js +23 -7
- package/dist/context.js.map +1 -1
- package/dist/docs/cli-reference.d.ts +2 -0
- package/dist/docs/cli-reference.js +191 -0
- package/dist/docs/cli-reference.js.map +1 -0
- package/dist/exit-codes.d.ts +25 -0
- package/dist/exit-codes.js +107 -0
- package/dist/exit-codes.js.map +1 -0
- package/dist/genui.d.ts +178 -0
- package/dist/genui.js +1130 -0
- package/dist/genui.js.map +1 -0
- package/dist/harnesses.js +2 -1
- package/dist/harnesses.js.map +1 -1
- package/dist/jq.d.ts +4 -0
- package/dist/jq.js +91 -0
- package/dist/jq.js.map +1 -0
- package/dist/login-offer.js +6 -2
- package/dist/login-offer.js.map +1 -1
- package/dist/manifest.d.ts +12 -0
- package/dist/manifest.js +126 -0
- package/dist/manifest.js.map +1 -1
- package/dist/model-auth.d.ts +29 -0
- package/dist/model-auth.js +117 -0
- package/dist/model-auth.js.map +1 -0
- package/dist/model-settings.d.ts +23 -0
- package/dist/model-settings.js +186 -0
- package/dist/model-settings.js.map +1 -0
- package/dist/money.js +2 -1
- package/dist/money.js.map +1 -1
- package/dist/output.d.ts +6 -0
- package/dist/output.js +54 -0
- package/dist/output.js.map +1 -1
- package/dist/runtime.d.ts +1 -1
- package/dist/runtime.js +1 -1
- package/dist/scaffold.js +2 -1
- package/dist/scaffold.js.map +1 -1
- package/dist/validators.js +17 -11
- package/dist/validators.js.map +1 -1
- package/dist/version-check.d.ts +1 -1
- package/dist/version-check.js +1 -1
- package/dist/version-check.js.map +1 -1
- package/node_modules/@dharta/contracts/LICENSE +21 -0
- package/node_modules/@dharta/contracts/README.md +45 -0
- package/node_modules/@dharta/contracts/artifact-runtime.json +750 -0
- package/node_modules/@dharta/contracts/dist/activity.d.ts +62 -0
- package/node_modules/@dharta/contracts/dist/activity.d.ts.map +1 -0
- package/node_modules/@dharta/contracts/dist/activity.js +178 -0
- package/node_modules/@dharta/contracts/dist/activity.js.map +1 -0
- package/node_modules/@dharta/contracts/dist/artifact-runtime-formats.d.ts +20 -0
- package/node_modules/@dharta/contracts/dist/artifact-runtime-formats.d.ts.map +1 -0
- package/node_modules/@dharta/contracts/dist/artifact-runtime-formats.js +53 -0
- package/node_modules/@dharta/contracts/dist/artifact-runtime-formats.js.map +1 -0
- package/node_modules/@dharta/contracts/dist/artifact-runtime-validators.generated.d.ts +37 -0
- package/node_modules/@dharta/contracts/dist/artifact-runtime-validators.generated.d.ts.map +1 -0
- package/node_modules/@dharta/contracts/dist/artifact-runtime-validators.generated.js +5107 -0
- package/node_modules/@dharta/contracts/dist/artifact-runtime-validators.generated.js.map +1 -0
- package/node_modules/@dharta/contracts/dist/artifact-runtime.d.ts +154 -0
- package/node_modules/@dharta/contracts/dist/artifact-runtime.d.ts.map +1 -0
- package/node_modules/@dharta/contracts/dist/artifact-runtime.generated.d.ts +1670 -0
- package/node_modules/@dharta/contracts/dist/artifact-runtime.generated.d.ts.map +1 -0
- package/node_modules/@dharta/contracts/dist/artifact-runtime.generated.js +1903 -0
- package/node_modules/@dharta/contracts/dist/artifact-runtime.generated.js.map +1 -0
- package/node_modules/@dharta/contracts/dist/artifact-runtime.js +377 -0
- package/node_modules/@dharta/contracts/dist/artifact-runtime.js.map +1 -0
- package/node_modules/@dharta/contracts/dist/index.d.ts +6 -0
- package/node_modules/@dharta/contracts/dist/index.d.ts.map +1 -0
- package/node_modules/@dharta/contracts/dist/index.js +6 -0
- package/node_modules/@dharta/contracts/dist/index.js.map +1 -0
- package/node_modules/@dharta/contracts/dist/model-auth.d.ts +31 -0
- package/node_modules/@dharta/contracts/dist/model-auth.d.ts.map +1 -0
- package/node_modules/@dharta/contracts/dist/model-auth.js +45 -0
- package/node_modules/@dharta/contracts/dist/model-auth.js.map +1 -0
- package/node_modules/@dharta/contracts/dist/tasks.d.ts +44 -0
- package/node_modules/@dharta/contracts/dist/tasks.d.ts.map +1 -0
- package/node_modules/@dharta/contracts/dist/tasks.js +127 -0
- package/node_modules/@dharta/contracts/dist/tasks.js.map +1 -0
- package/node_modules/@dharta/contracts/dist/wire-events.d.ts +71 -0
- package/node_modules/@dharta/contracts/dist/wire-events.d.ts.map +1 -0
- package/node_modules/@dharta/contracts/dist/wire-events.js +48 -0
- package/node_modules/@dharta/contracts/dist/wire-events.js.map +1 -0
- package/node_modules/@dharta/contracts/model-auth-capabilities-v1.json +168 -0
- package/node_modules/@dharta/contracts/model-auth-reasons-v1.json +38 -0
- package/node_modules/@dharta/contracts/package.json +44 -0
- package/node_modules/@dharta/contracts/src/activity.ts +215 -0
- package/node_modules/@dharta/contracts/src/artifact-runtime-formats.ts +54 -0
- package/node_modules/@dharta/contracts/src/artifact-runtime-validators.generated.ts +29 -0
- package/node_modules/@dharta/contracts/src/artifact-runtime.generated.ts +2093 -0
- package/node_modules/@dharta/contracts/src/artifact-runtime.ts +520 -0
- package/node_modules/@dharta/contracts/src/index.ts +5 -0
- package/node_modules/@dharta/contracts/src/model-auth.ts +82 -0
- package/node_modules/@dharta/contracts/src/tasks.ts +142 -0
- package/node_modules/@dharta/contracts/src/wire-events.ts +150 -0
- package/node_modules/@dharta/contracts/wire-events.json +29 -0
- package/node_modules/@dharta/sdk/LICENSE +1 -1
- package/node_modules/@dharta/sdk/README.md +22 -8
- package/node_modules/@dharta/sdk/dist/errors.d.ts +9 -7
- package/node_modules/@dharta/sdk/dist/errors.d.ts.map +1 -1
- package/node_modules/@dharta/sdk/dist/errors.js +36 -18
- package/node_modules/@dharta/sdk/dist/errors.js.map +1 -1
- package/node_modules/@dharta/sdk/dist/fleet.d.ts +69 -0
- package/node_modules/@dharta/sdk/dist/fleet.d.ts.map +1 -0
- package/node_modules/@dharta/sdk/dist/fleet.js +240 -0
- package/node_modules/@dharta/sdk/dist/fleet.js.map +1 -0
- package/node_modules/@dharta/sdk/dist/http.d.ts +6 -2
- package/node_modules/@dharta/sdk/dist/http.d.ts.map +1 -1
- package/node_modules/@dharta/sdk/dist/http.js +71 -12
- package/node_modules/@dharta/sdk/dist/http.js.map +1 -1
- package/node_modules/@dharta/sdk/dist/idempotency.d.ts +12 -0
- package/node_modules/@dharta/sdk/dist/idempotency.d.ts.map +1 -0
- package/node_modules/@dharta/sdk/dist/idempotency.js +72 -0
- package/node_modules/@dharta/sdk/dist/idempotency.js.map +1 -0
- package/node_modules/@dharta/sdk/dist/index.d.ts +20 -6
- package/node_modules/@dharta/sdk/dist/index.d.ts.map +1 -1
- package/node_modules/@dharta/sdk/dist/index.js +27 -4
- package/node_modules/@dharta/sdk/dist/index.js.map +1 -1
- package/node_modules/@dharta/sdk/dist/resources.d.ts +108 -13
- package/node_modules/@dharta/sdk/dist/resources.d.ts.map +1 -1
- package/node_modules/@dharta/sdk/dist/resources.js +403 -57
- package/node_modules/@dharta/sdk/dist/resources.js.map +1 -1
- package/node_modules/@dharta/sdk/dist/types.d.ts +436 -16
- package/node_modules/@dharta/sdk/dist/types.d.ts.map +1 -1
- package/node_modules/@dharta/sdk/dist/types.js +31 -2
- package/node_modules/@dharta/sdk/dist/types.js.map +1 -1
- package/node_modules/@dharta/sdk/package.json +9 -3
- package/node_modules/@dharta/sdk/src/errors.ts +41 -18
- package/node_modules/@dharta/sdk/src/fleet.ts +339 -0
- package/node_modules/@dharta/sdk/src/http.ts +110 -17
- package/node_modules/@dharta/sdk/src/idempotency.ts +101 -0
- package/node_modules/@dharta/sdk/src/index.ts +50 -11
- package/node_modules/@dharta/sdk/src/resources.ts +549 -68
- package/node_modules/@dharta/sdk/src/types.ts +629 -20
- package/package.json +16 -6
- package/src/agent.ts +3 -2
- package/src/api-error.ts +6 -5
- package/src/cli.ts +978 -163
- package/src/command-tree.ts +13 -0
- package/src/commands/agents.ts +365 -167
- package/src/commands/analytics.ts +6 -5
- package/src/commands/api.ts +73 -92
- package/src/commands/appearance.ts +5 -6
- package/src/commands/artifact.ts +7 -6
- package/src/commands/audit-log.ts +2 -1
- package/src/commands/auth.ts +25 -5
- package/src/commands/caps.ts +11 -15
- package/src/commands/deploy.ts +18 -4
- package/src/commands/dev.ts +86 -25
- package/src/commands/doctor.ts +69 -0
- package/src/commands/embed-keys.ts +4 -14
- package/src/commands/env.ts +4 -7
- package/src/commands/files.ts +3 -4
- package/src/commands/fleet.ts +672 -0
- package/src/commands/genui.ts +59 -0
- package/src/commands/git-credential.ts +2 -3
- package/src/commands/kartas.ts +45 -11
- package/src/commands/keys.ts +152 -35
- package/src/commands/login.ts +2 -1
- package/src/commands/members.ts +31 -6
- package/src/commands/model-connections.ts +547 -0
- package/src/commands/open.ts +5 -4
- package/src/commands/org.ts +57 -0
- package/src/commands/organization.ts +153 -0
- package/src/commands/parity.ts +1 -3
- package/src/commands/repos.ts +23 -0
- package/src/commands/rollback.ts +2 -3
- package/src/commands/schedules.ts +33 -22
- package/src/commands/scopes.ts +8 -1
- package/src/commands/sessions.ts +9 -3
- package/src/commands/setup.ts +5 -4
- package/src/commands/update.ts +28 -12
- package/src/commands/webhooks.ts +30 -19
- package/src/completions.ts +25 -13
- package/src/config.ts +141 -9
- package/src/context.ts +34 -7
- package/src/docs/cli-reference.ts +206 -0
- package/src/exit-codes.ts +122 -0
- package/src/genui.ts +1398 -0
- package/src/harnesses.ts +2 -1
- package/src/jq.ts +109 -0
- package/src/login-offer.ts +6 -2
- package/src/manifest.ts +134 -0
- package/src/model-auth.ts +173 -0
- package/src/model-settings.ts +222 -0
- package/src/money.ts +5 -1
- package/src/output.ts +60 -0
- package/src/runtime.ts +1 -1
- package/src/scaffold.ts +2 -1
- package/src/validators.ts +18 -11
- package/src/version-check.ts +1 -1
- package/dist/commands/model-keys.d.ts +0 -22
- package/dist/commands/model-keys.js +0 -222
- package/dist/commands/model-keys.js.map +0 -1
- package/src/commands/model-keys.ts +0 -278
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
// The public CLI reference (apps/docs-site/cli/reference.mdx) is generated from
|
|
2
|
+
// the command tree, not written by hand (RFC 0048 P5). A hand-maintained page
|
|
3
|
+
// is a second copy of the command surface, and the old one had drifted: it
|
|
4
|
+
// never listed `files` or `artifact`, and it still told readers to run
|
|
5
|
+
// `karta --help`.
|
|
6
|
+
//
|
|
7
|
+
// `npm run docs:cli` rewrites the page. A vitest gate renders the same text in
|
|
8
|
+
// memory and fails when the committed file differs, so a new command cannot
|
|
9
|
+
// ship undocumented.
|
|
10
|
+
|
|
11
|
+
import type { Argument, Command, Option } from "commander";
|
|
12
|
+
|
|
13
|
+
import { visibleSubcommands } from "../command-tree.js";
|
|
14
|
+
|
|
15
|
+
// Flags registered on every node by cli.ts. They belong in one section, not in
|
|
16
|
+
// every row of every table.
|
|
17
|
+
const GLOBAL_FLAGS = new Set([
|
|
18
|
+
"--json",
|
|
19
|
+
"--jq",
|
|
20
|
+
"--profile",
|
|
21
|
+
"--idempotency-key",
|
|
22
|
+
"--help",
|
|
23
|
+
"--version",
|
|
24
|
+
]);
|
|
25
|
+
|
|
26
|
+
const FRONT_MATTER = `---
|
|
27
|
+
title: CLI command reference
|
|
28
|
+
sidebarTitle: Command reference
|
|
29
|
+
description: "Every dharta CLI command, grouped the way \`dharta --help\` groups them, with arguments, options, global flags, and exit codes."
|
|
30
|
+
---`;
|
|
31
|
+
|
|
32
|
+
const INTRO = `{/* Generated by \`npm run docs:cli\` in sdks/typescript-cli. Do not edit by hand. */}
|
|
33
|
+
|
|
34
|
+
The fastest local reference is always:
|
|
35
|
+
|
|
36
|
+
\`\`\`bash
|
|
37
|
+
dharta --help
|
|
38
|
+
dharta <command> --help
|
|
39
|
+
\`\`\`
|
|
40
|
+
|
|
41
|
+
The groups below are the groups \`dharta --help\` prints. Commands that take a
|
|
42
|
+
positional agent slug infer it from the current folder when you leave it out.`;
|
|
43
|
+
|
|
44
|
+
const GLOBAL_FLAGS_SECTION = `## Global flags
|
|
45
|
+
|
|
46
|
+
These work on every command, wherever you put them on the line.
|
|
47
|
+
|
|
48
|
+
| Flag | Purpose |
|
|
49
|
+
| --- | --- |
|
|
50
|
+
| \`--json\` | Print the result as JSON on stdout. Progress narration goes to stderr, so stdout stays parseable. Stream commands (\`dev\`, \`logs\`, \`completion\`, and git-mode \`deploy\`) reject it instead of ignoring it. |
|
|
51
|
+
| \`--jq <expr>\` | Filter the JSON result through a built-in jq. Implies \`--json\`. Each result prints on its own line, compact; a result that is a string prints without quotes, so \`--jq .name\` pipes cleanly. A filter that matches nothing prints nothing. Rejected wherever \`--json\` is rejected. |
|
|
52
|
+
| \`--profile <name>\` | Use a named profile from \`~/.dharta/config.toml\`. Resolution order is \`--profile\`, then \`DHARTA_PROFILE\`, then the config's default profile. \`dharta login --profile <name>\` creates one; \`dharta auth logout --profile <name>\` removes it. |
|
|
53
|
+
| \`--idempotency-key <key>\` | Send this \`Idempotency-Key\` on every request the command makes, instead of the fresh one each mutation mints. Give a CI job a key it can reuse and a rerun after an ambiguous failure replays the first response, including a secret that is otherwise shown once. Printable ASCII with no spaces, at most 200 characters; the SDK enforces the same shape on every key it is handed, up to the API's 255. |
|
|
54
|
+
|
|
55
|
+
### Reusing an idempotency key
|
|
56
|
+
|
|
57
|
+
A mutation that times out may or may not have been performed, and without a key
|
|
58
|
+
you have no way to find out but to look. Every \`dharta\` mutation mints a fresh
|
|
59
|
+
key per process, which protects one run from itself but cannot help a second
|
|
60
|
+
run: to the platform, the retry is a new request.
|
|
61
|
+
|
|
62
|
+
Pin the key to the job, not to the process:
|
|
63
|
+
|
|
64
|
+
\`\`\`bash
|
|
65
|
+
dharta keys create ci-release --scope releases:write \\
|
|
66
|
+
--idempotency-key "release-$GITHUB_RUN_ID"
|
|
67
|
+
\`\`\`
|
|
68
|
+
|
|
69
|
+
Rerun that step with the same \`GITHUB_RUN_ID\` and you get the first run's
|
|
70
|
+
response back, secret included, instead of a second key.
|
|
71
|
+
|
|
72
|
+
Four rules come with it:
|
|
73
|
+
|
|
74
|
+
- **One key per command.** The platform binds a key to the request it first saw
|
|
75
|
+
and answers a different request under the same key with \`422\`. Two commands
|
|
76
|
+
sharing one key collide, so give each mutating step its own.
|
|
77
|
+
- **A command that writes more than once splits the key for you.** \`dharta
|
|
78
|
+
send\` opens a session and then runs a turn; \`dharta schedules create
|
|
79
|
+
--run-now\` creates a schedule and then queues a run of it; \`dharta dev\`
|
|
80
|
+
runs a turn per prompt. Each write gets a suffix naming its operation, so the
|
|
81
|
+
wire carries \`<key>.sessions.create\` and \`<key>.sessions.turn\`, or
|
|
82
|
+
\`<key>.schedules.create\` and \`<key>.schedules.run\`. The writes never
|
|
83
|
+
collide with each other, and a rerun under the same key replays every one of
|
|
84
|
+
them instead of opening a second session, creating a second schedule, or
|
|
85
|
+
paying for a second inference. That is why the key is capped at 200 rather
|
|
86
|
+
than the platform's 255 - the rest is reserved for the suffix. A command that
|
|
87
|
+
writes once sends your key exactly as you typed it.
|
|
88
|
+
- **Retry \`5xx\` and \`429\` with the same key.** Those answers are never
|
|
89
|
+
stored, so reusing the key re-drives the work rather than replaying a failure.
|
|
90
|
+
- **A command with nothing to protect refuses the flag.** \`dharta login\`,
|
|
91
|
+
\`create\`, \`setup\`, \`genui\`, \`artifact\`, \`doctor\`,
|
|
92
|
+
\`update\`, \`completion\`, \`auth token\` and \`auth logout\` perform
|
|
93
|
+
no mutation the key could cover. Some of them do call Dharta - \`login\`
|
|
94
|
+
reads \`/me\`, \`create\` fetches the template list - but none of them
|
|
95
|
+
writes. Passing the key there exits 2 rather than being quietly dropped.
|
|
96
|
+
Read-only commands do accept it, because they are steps in a run that writes
|
|
97
|
+
and the header is ignored server-side.
|
|
98
|
+
|
|
99
|
+
## Exit codes
|
|
100
|
+
|
|
101
|
+
Scripts can branch on the exit code instead of parsing messages.
|
|
102
|
+
|
|
103
|
+
| Code | Meaning |
|
|
104
|
+
| --- | --- |
|
|
105
|
+
| 0 | Success. |
|
|
106
|
+
| 1 | General failure. |
|
|
107
|
+
| 2 | Usage error: an unknown flag, a bad value, a missing argument, or an unknown profile. |
|
|
108
|
+
| 3 | Not authenticated. No credential is stored, or the API answered 401. |
|
|
109
|
+
| 4 | Forbidden. The API answered 403, usually a missing scope on the key. |
|
|
110
|
+
| 5 | Not found. The API answered 404. |
|
|
111
|
+
| 6 | Validation failure. The API answered 409 or 422. |
|
|
112
|
+
| 7 | The API host could not be reached. |
|
|
113
|
+
|
|
114
|
+
\`dharta doctor\` is the exception: it exits 1 when a local check fails, which is
|
|
115
|
+
a report, not an error.`;
|
|
116
|
+
|
|
117
|
+
export function renderCliReference(program: Command): string {
|
|
118
|
+
const sections = groupCommands(program).map(([group, commands]) => renderGroup(group, commands));
|
|
119
|
+
return [FRONT_MATTER, "", INTRO, "", ...sections, GLOBAL_FLAGS_SECTION, ""].join("\n");
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// Group heading -> the top-level commands in it, in tree order. Commander
|
|
123
|
+
// stores the heading with a trailing colon ("Management:"); the page uses it as
|
|
124
|
+
// a title, so the colon comes off.
|
|
125
|
+
function groupCommands(program: Command): Array<[string, Command[]]> {
|
|
126
|
+
const groups = new Map<string, Command[]>();
|
|
127
|
+
for (const cmd of visibleSubcommands(program)) {
|
|
128
|
+
const heading = cmd.helpGroup().replace(/:$/, "");
|
|
129
|
+
if (!heading) {
|
|
130
|
+
throw new Error(`\`dharta ${cmd.name()}\` has no help group, so it has nowhere to go in the reference.`);
|
|
131
|
+
}
|
|
132
|
+
const bucket = groups.get(heading);
|
|
133
|
+
if (bucket) bucket.push(cmd);
|
|
134
|
+
else groups.set(heading, [cmd]);
|
|
135
|
+
}
|
|
136
|
+
return [...groups.entries()];
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
function renderGroup(heading: string, commands: Command[]): string {
|
|
140
|
+
const rows = commands.flatMap((cmd) => flatten(cmd)).map(renderRow);
|
|
141
|
+
return [
|
|
142
|
+
`## ${heading}`,
|
|
143
|
+
"",
|
|
144
|
+
"| Command | Arguments | Options | Description |",
|
|
145
|
+
"| --- | --- | --- | --- |",
|
|
146
|
+
...rows,
|
|
147
|
+
"",
|
|
148
|
+
].join("\n");
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
function flatten(cmd: Command): Command[] {
|
|
152
|
+
return [cmd, ...visibleSubcommands(cmd).flatMap(flatten)];
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
function renderRow(cmd: Command): string {
|
|
156
|
+
return `| ${code(commandPath(cmd))} | ${code(argumentList(cmd))} | ${optionList(cmd)} | ${prose(cmd.description())} |`;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
// `dharta send|run`, matching how commander prints an aliased command.
|
|
160
|
+
function commandPath(cmd: Command): string {
|
|
161
|
+
const names: string[] = [];
|
|
162
|
+
let cursor: Command | null = cmd;
|
|
163
|
+
while (cursor) {
|
|
164
|
+
const aliases = cursor.aliases();
|
|
165
|
+
names.unshift(cursor === cmd && aliases.length > 0 ? [cursor.name(), ...aliases].join("|") : cursor.name());
|
|
166
|
+
cursor = cursor.parent;
|
|
167
|
+
}
|
|
168
|
+
return names.join(" ");
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
function argumentList(cmd: Command): string {
|
|
172
|
+
return cmd.registeredArguments
|
|
173
|
+
.map((arg: Argument) => {
|
|
174
|
+
const name = `${arg.name()}${arg.variadic ? "..." : ""}`;
|
|
175
|
+
return arg.required ? `<${name}>` : `[${name}]`;
|
|
176
|
+
})
|
|
177
|
+
.join(" ");
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
function optionList(cmd: Command): string {
|
|
181
|
+
const flags = cmd.options
|
|
182
|
+
.filter((option: Option) => !option.hidden && !GLOBAL_FLAGS.has(option.long ?? ""))
|
|
183
|
+
.map((option: Option) => code(option.flags));
|
|
184
|
+
return flags.length > 0 ? flags.join(", ") : escapePipes("Global flags only");
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
function code(text: string): string {
|
|
188
|
+
return text ? `\`${escapePipes(text)}\`` : "";
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
function prose(text: string): string {
|
|
192
|
+
const collapsed = text.replace(/\s+/g, " ").trim();
|
|
193
|
+
// MDX parses `<` as JSX and `{` as an expression, but not inside an inline
|
|
194
|
+
// code span - and escaping inside one would print the entity. Split on code
|
|
195
|
+
// spans and escape only the prose between them.
|
|
196
|
+
const escaped = collapsed
|
|
197
|
+
.split(/(`[^`]*`)/)
|
|
198
|
+
.map((part) => (part.startsWith("`") ? part : part.replace(/</g, "<").replace(/\{/g, "{")))
|
|
199
|
+
.join("");
|
|
200
|
+
return escapePipes(escaped);
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
// A bare `|` would end the table cell, including inside a code span.
|
|
204
|
+
function escapePipes(text: string): string {
|
|
205
|
+
return text.replace(/\|/g, "\\|");
|
|
206
|
+
}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
// Exit-code taxonomy (RFC 0048 D1/P5). A script that pipes `dharta` needs to
|
|
2
|
+
// branch on *why* a command failed without parsing English, so every failure
|
|
3
|
+
// maps to one of these codes. The numbers are a public contract: change a
|
|
4
|
+
// meaning and every caller's `if [ $? -eq 4 ]` silently means something else.
|
|
5
|
+
//
|
|
6
|
+
// `dharta doctor` is the one exception: it reports an unhealthy local setup
|
|
7
|
+
// with its own exit 1 without throwing, so it never reaches this map.
|
|
8
|
+
|
|
9
|
+
import { INVALID_IDEMPOTENCY_KEY_CODE } from "@dharta/sdk";
|
|
10
|
+
|
|
11
|
+
export const EXIT_SUCCESS = 0;
|
|
12
|
+
export const EXIT_GENERAL = 1;
|
|
13
|
+
export const EXIT_USAGE = 2;
|
|
14
|
+
export const EXIT_NOT_AUTHENTICATED = 3;
|
|
15
|
+
export const EXIT_FORBIDDEN = 4;
|
|
16
|
+
export const EXIT_NOT_FOUND = 5;
|
|
17
|
+
export const EXIT_VALIDATION = 6;
|
|
18
|
+
export const EXIT_NETWORK = 7;
|
|
19
|
+
|
|
20
|
+
// A wrong invocation: an unknown flag, a bad choice, a missing argument, a
|
|
21
|
+
// profile that is not in the config file. Commander raises its own version of
|
|
22
|
+
// this; throw CliUsageError for the ones the CLI detects itself.
|
|
23
|
+
//
|
|
24
|
+
// The line, applied across every curated command (RFC 0048 P9): a throw that
|
|
25
|
+
// rejects a value the caller TYPED is a usage error. A throw that reports the
|
|
26
|
+
// state of the world - a file that is not there, a server too old to answer, a
|
|
27
|
+
// build that failed - is a plain Error and exits 1. `test/usage-exit-code.test.ts`
|
|
28
|
+
// holds both halves: a table exercising each validator, and a source scan that
|
|
29
|
+
// makes a new plain Error in a command module argue for itself.
|
|
30
|
+
export class CliUsageError extends Error {
|
|
31
|
+
constructor(message: string) {
|
|
32
|
+
super(message);
|
|
33
|
+
this.name = "CliUsageError";
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// The control plane answered with a non-2xx status.
|
|
38
|
+
export class CliApiError extends Error {
|
|
39
|
+
readonly status: number;
|
|
40
|
+
readonly body: unknown;
|
|
41
|
+
|
|
42
|
+
constructor(message: string, status: number, body: unknown) {
|
|
43
|
+
super(message);
|
|
44
|
+
this.name = "CliApiError";
|
|
45
|
+
this.status = status;
|
|
46
|
+
this.body = body;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// The control plane could not be reached at all (DNS, refused connection, TLS).
|
|
51
|
+
// Distinct from CliApiError: retrying may help, and no request was authorized.
|
|
52
|
+
export class CliNetworkError extends Error {
|
|
53
|
+
readonly url: string;
|
|
54
|
+
|
|
55
|
+
constructor(message: string, url: string) {
|
|
56
|
+
super(message);
|
|
57
|
+
this.name = "CliNetworkError";
|
|
58
|
+
this.url = url;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// Commander's own failures. `commander.helpDisplayed` and `commander.version`
|
|
63
|
+
// are successful runs that unwind through the same catch, so they keep their
|
|
64
|
+
// own exit code (0); everything else commander raises is a usage error.
|
|
65
|
+
interface CommanderErrorShape {
|
|
66
|
+
code?: unknown;
|
|
67
|
+
exitCode?: unknown;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export function isCommanderError(err: unknown): boolean {
|
|
71
|
+
const code = (err as CommanderErrorShape | null)?.code;
|
|
72
|
+
return typeof code === "string" && code.startsWith("commander.");
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export function exitCodeForError(err: unknown): number {
|
|
76
|
+
if (isCommanderError(err)) {
|
|
77
|
+
const exitCode = (err as CommanderErrorShape).exitCode;
|
|
78
|
+
return exitCode === 0 ? EXIT_SUCCESS : EXIT_USAGE;
|
|
79
|
+
}
|
|
80
|
+
if (err instanceof CliUsageError) return EXIT_USAGE;
|
|
81
|
+
// The SDK rejects a malformed Idempotency-Key wherever it was supplied,
|
|
82
|
+
// including a header a caller wrote by hand with `dharta api -H`, which never
|
|
83
|
+
// passes through a CLI validator. It is still a value the caller typed, so it
|
|
84
|
+
// gets the code every other rejected value gets. Matched on the stable `code`
|
|
85
|
+
// rather than the class, so a duplicated SDK install cannot break it.
|
|
86
|
+
if (isInvalidIdempotencyKeyError(err)) return EXIT_USAGE;
|
|
87
|
+
if (err instanceof CliNetworkError) return EXIT_NETWORK;
|
|
88
|
+
|
|
89
|
+
const status = (err as { status?: unknown } | null)?.status;
|
|
90
|
+
if (typeof status === "number") return exitCodeForStatus(status);
|
|
91
|
+
if (isNotAuthenticatedError(err)) return EXIT_NOT_AUTHENTICATED;
|
|
92
|
+
return EXIT_GENERAL;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// `Not logged in.` is raised locally when no credential is stored, before any
|
|
96
|
+
// request goes out. It is the same condition a 401 reports, so it gets the same
|
|
97
|
+
// exit code - otherwise `dharta whoami` means one thing logged out and another
|
|
98
|
+
// with a revoked key. Commands that fall back when unauthenticated test the
|
|
99
|
+
// same predicate, so the two readings cannot drift apart.
|
|
100
|
+
export function isInvalidIdempotencyKeyError(err: unknown): boolean {
|
|
101
|
+
return (err as { code?: unknown } | null)?.code === INVALID_IDEMPOTENCY_KEY_CODE;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
export function isNotAuthenticatedError(err: unknown): boolean {
|
|
105
|
+
return err instanceof Error && /^Not logged in\b/.test(err.message);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
export function exitCodeForStatus(status: number): number {
|
|
109
|
+
switch (status) {
|
|
110
|
+
case 401:
|
|
111
|
+
return EXIT_NOT_AUTHENTICATED;
|
|
112
|
+
case 403:
|
|
113
|
+
return EXIT_FORBIDDEN;
|
|
114
|
+
case 404:
|
|
115
|
+
return EXIT_NOT_FOUND;
|
|
116
|
+
case 409:
|
|
117
|
+
case 422:
|
|
118
|
+
return EXIT_VALIDATION;
|
|
119
|
+
default:
|
|
120
|
+
return EXIT_GENERAL;
|
|
121
|
+
}
|
|
122
|
+
}
|