@ai21/gateway 0.5.3
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 +91 -0
- package/dist/args.d.ts +74 -0
- package/dist/args.js +304 -0
- package/dist/args.js.map +1 -0
- package/dist/cli.d.ts +10 -0
- package/dist/cli.js +140 -0
- package/dist/cli.js.map +1 -0
- package/dist/config.d.ts +76 -0
- package/dist/config.js +187 -0
- package/dist/config.js.map +1 -0
- package/dist/login/browser.d.ts +7 -0
- package/dist/login/browser.js +41 -0
- package/dist/login/browser.js.map +1 -0
- package/dist/login/contract.d.ts +42 -0
- package/dist/login/contract.js +60 -0
- package/dist/login/contract.js.map +1 -0
- package/dist/login/loopback.d.ts +42 -0
- package/dist/login/loopback.js +192 -0
- package/dist/login/loopback.js.map +1 -0
- package/dist/login/session.d.ts +36 -0
- package/dist/login/session.js +75 -0
- package/dist/login/session.js.map +1 -0
- package/dist/prompt.d.ts +32 -0
- package/dist/prompt.js +72 -0
- package/dist/prompt.js.map +1 -0
- package/dist/report.d.ts +50 -0
- package/dist/report.js +214 -0
- package/dist/report.js.map +1 -0
- package/dist/result.d.ts +26 -0
- package/dist/result.js +22 -0
- package/dist/result.js.map +1 -0
- package/dist/revert.d.ts +60 -0
- package/dist/revert.js +230 -0
- package/dist/revert.js.map +1 -0
- package/dist/router.d.ts +21 -0
- package/dist/router.js +271 -0
- package/dist/router.js.map +1 -0
- package/dist/snippets.d.ts +52 -0
- package/dist/snippets.js +71 -0
- package/dist/snippets.js.map +1 -0
- package/dist/verify.d.ts +96 -0
- package/dist/verify.js +309 -0
- package/dist/verify.js.map +1 -0
- package/package.json +61 -0
package/README.md
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
# ai21-intelligent-gateway-cli
|
|
2
|
+
|
|
3
|
+
One command to point a local coding agent at the AI21 Intelligent Gateway.
|
|
4
|
+
Ships as the `@ai21/gateway` package.
|
|
5
|
+
|
|
6
|
+
## Usage
|
|
7
|
+
|
|
8
|
+
```bash
|
|
9
|
+
npx @ai21/gateway install --agent-id <AGENT_ID>
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
Merges `.claude/settings.json` so Claude Code routes through the gateway, then
|
|
13
|
+
sends one request to prove it works. The AI21 key is prompted for without echo —
|
|
14
|
+
pass `--key` only for scripting, since a key in argv stays in your shell history.
|
|
15
|
+
|
|
16
|
+
The dashboard prints this command for you (Add agent, or Reconnect on an existing
|
|
17
|
+
agent) and offers the key as a separate copy.
|
|
18
|
+
|
|
19
|
+
| Command | Does |
|
|
20
|
+
| ----------- | ------------------------------------------------ |
|
|
21
|
+
| `install` | write the config and verify it (default command) |
|
|
22
|
+
| `uninstall` | revert what this tool wrote |
|
|
23
|
+
|
|
24
|
+
`configure` is accepted as an alias for `install`: it was the verb's name through
|
|
25
|
+
0.3.x, so commands copied from an older dashboard keep working.
|
|
26
|
+
|
|
27
|
+
There is a third verb, `login`, which signs in through the browser and then
|
|
28
|
+
installs. It parses and runs but is **left out of `--help`**: it calls back to a
|
|
29
|
+
loopback listener, which only works from a locally served dashboard — Chrome's
|
|
30
|
+
Local Network Access gate makes a public page's request to `127.0.0.1` hang. Until
|
|
31
|
+
that has a real answer it is a local-dev path, and advertising it would send
|
|
32
|
+
readers into a dead end. `--app <url>` points it at a local webapp.
|
|
33
|
+
|
|
34
|
+
The gateway defaults to `https://api.ai21.com/gateway`. `--gateway <url>` points
|
|
35
|
+
somewhere else — staging is `https://api.ai21-stg.com/gateway`, and the dashboard
|
|
36
|
+
puts it in the command it prints for you.
|
|
37
|
+
|
|
38
|
+
`--print` renders the config instead of writing it, with the key masked. `--help`
|
|
39
|
+
lists the rest.
|
|
40
|
+
|
|
41
|
+
`--client <name>` picks which agent to configure. `claude-code` is the default and
|
|
42
|
+
the only one supported so far — an unsupported name is refused rather than
|
|
43
|
+
defaulted, so a `--client` we do not implement never writes Claude Code's file by
|
|
44
|
+
mistake.
|
|
45
|
+
|
|
46
|
+
> **Internal only.** The package is published to AI21's Artifact Registry, not
|
|
47
|
+
> public npm, so a bare `npx` cannot reach it yet — see below.
|
|
48
|
+
|
|
49
|
+
## Installing
|
|
50
|
+
|
|
51
|
+
`@ai21/gateway` is published to public npm, so nothing needs configuring:
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
npx @ai21/gateway --version
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
Run it from any directory other than this repo — inside the repo, `npx` finds the
|
|
58
|
+
local package and `ai21-gateway` is not on PATH.
|
|
59
|
+
|
|
60
|
+
Releases go out from the **Release and Publish** workflow (Actions tab), which runs
|
|
61
|
+
semantic-release: the version comes from the conventional-commit history since the
|
|
62
|
+
last tag. `package.json` stays at `0.0.0`; the git tag is the record.
|
|
63
|
+
|
|
64
|
+
`403` misleads: it reads as though the AI21 gateway rejected you, but it is npm
|
|
65
|
+
failing to reach the registry — before the CLI has run at all.
|
|
66
|
+
|
|
67
|
+
The last one catches people out: this project _is_ `@ai21/gateway`, so npx
|
|
68
|
+
resolves the name to the working directory instead of the registry, finds no
|
|
69
|
+
linked binary, and fails. The published artifact can never be exercised from its
|
|
70
|
+
own source tree — use a scratch directory.
|
|
71
|
+
|
|
72
|
+
## Development
|
|
73
|
+
|
|
74
|
+
Requires Node 20+ (`engines`); `.nvmrc` pins 22, which is what CI builds and
|
|
75
|
+
tests on. No runtime dependencies; TypeScript and `@types/node` are the only dev
|
|
76
|
+
dependencies.
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
./scripts/init.sh # pre-commit, nvm, registry auth, dependencies
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
Then day to day:
|
|
83
|
+
|
|
84
|
+
```bash
|
|
85
|
+
npm run lint # eslint (--max-warnings 0); `lint:fix` to autofix
|
|
86
|
+
npm run typecheck # tsc --noEmit
|
|
87
|
+
npm run format # prettier --write (@ai21/prettier-config)
|
|
88
|
+
npm run quality # audit + lint + typecheck + format:check — what CI runs
|
|
89
|
+
npm test # build, then node --test
|
|
90
|
+
npm run precommit # what the pre-commit hook runs
|
|
91
|
+
```
|
package/dist/args.d.ts
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Baked-in endpoints. Shipping these means the happy path needs no URL, and the
|
|
3
|
+
* snippets we tell people to copy carry no hostname that can go stale.
|
|
4
|
+
*/
|
|
5
|
+
/** Production, and the only baked-in set. `--gateway` points elsewhere. */
|
|
6
|
+
export declare const DEFAULT_URLS: {
|
|
7
|
+
readonly app: "https://app.ai21.com";
|
|
8
|
+
readonly gateway: "https://api.ai21.com/gateway";
|
|
9
|
+
readonly identity: "https://api.ai21.com";
|
|
10
|
+
};
|
|
11
|
+
export interface ResolvedUrls {
|
|
12
|
+
readonly app: string;
|
|
13
|
+
readonly gateway: string;
|
|
14
|
+
readonly identity: string;
|
|
15
|
+
readonly agents: string;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* `--gateway` overrides only the gateway itself — the escape hatch for a local
|
|
19
|
+
* or dev backend. `agents` is always derived from whichever gateway won, so an
|
|
20
|
+
* override stays internally consistent.
|
|
21
|
+
*/
|
|
22
|
+
export declare function resolveUrls(gatewayOverride?: string, appOverride?: string): ResolvedUrls;
|
|
23
|
+
/** The workspace dashboard, built from the baked-in origin rather than a given URL. */
|
|
24
|
+
export declare function dashboardUrl(urls: ResolvedUrls, workspaceId: string): string;
|
|
25
|
+
/** Which coding agent's config to write. Only Claude Code is implemented; the flag
|
|
26
|
+
* exists so the choice is explicit at the boundary rather than assumed throughout. */
|
|
27
|
+
export declare const CLIENTS: readonly ["claude-code"];
|
|
28
|
+
export type Client = (typeof CLIENTS)[number];
|
|
29
|
+
export declare const DEFAULT_CLIENT: Client;
|
|
30
|
+
export declare const VERBS: readonly ["install", "login", "uninstall"];
|
|
31
|
+
export type Verb = (typeof VERBS)[number];
|
|
32
|
+
export declare const DOCUMENTED_VERBS: readonly Verb[];
|
|
33
|
+
export type Target = "repo" | "user";
|
|
34
|
+
export interface ParsedArgs {
|
|
35
|
+
readonly verb: Verb;
|
|
36
|
+
readonly urls: ResolvedUrls;
|
|
37
|
+
readonly target: Target;
|
|
38
|
+
/** Whose config gets written. Defaults to Claude Code. */
|
|
39
|
+
readonly client: Client;
|
|
40
|
+
readonly agentId?: string | undefined;
|
|
41
|
+
readonly key?: string | undefined;
|
|
42
|
+
readonly userId?: string | undefined;
|
|
43
|
+
readonly agentIdGuard?: string | undefined;
|
|
44
|
+
/** Anthropic credential for the direct verifying ping. Never written to disk. */
|
|
45
|
+
readonly anthropicKey?: string | undefined;
|
|
46
|
+
readonly noVerify: boolean;
|
|
47
|
+
readonly print: boolean;
|
|
48
|
+
readonly json: boolean;
|
|
49
|
+
readonly yes: boolean;
|
|
50
|
+
readonly fromBackup: boolean;
|
|
51
|
+
}
|
|
52
|
+
export type ParseOutcome = {
|
|
53
|
+
readonly kind: "args";
|
|
54
|
+
readonly args: ParsedArgs;
|
|
55
|
+
} | {
|
|
56
|
+
readonly kind: "help";
|
|
57
|
+
} | {
|
|
58
|
+
readonly kind: "version";
|
|
59
|
+
} | {
|
|
60
|
+
readonly kind: "error";
|
|
61
|
+
readonly message: string;
|
|
62
|
+
};
|
|
63
|
+
/**
|
|
64
|
+
* Shared with the interactive prompt, which is a second way these values enter
|
|
65
|
+
* the program and must not be a second way the rule is skipped.
|
|
66
|
+
*/
|
|
67
|
+
export declare function containsControlCharacters(value: string): boolean;
|
|
68
|
+
/**
|
|
69
|
+
* A plain-http gateway that is not on this machine. `--gateway` allows http for
|
|
70
|
+
* local dev, but every request through it carries the AI21 key, so off-box http
|
|
71
|
+
* means credentials on the wire in the clear.
|
|
72
|
+
*/
|
|
73
|
+
export declare function isInsecureGateway(gateway: string): boolean;
|
|
74
|
+
export declare function parseCliArgs(argv: readonly string[]): ParseOutcome;
|
package/dist/args.js
ADDED
|
@@ -0,0 +1,304 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Argument parsing and per-verb validation.
|
|
3
|
+
*
|
|
4
|
+
* Everything here is pure: argv in, a resolved plan or an error message out. No
|
|
5
|
+
* I/O, no process access — that keeps the whole surface assertable without
|
|
6
|
+
* spawning anything.
|
|
7
|
+
*/
|
|
8
|
+
import { parseArgs } from "node:util";
|
|
9
|
+
/**
|
|
10
|
+
* Baked-in endpoints. Shipping these means the happy path needs no URL, and the
|
|
11
|
+
* snippets we tell people to copy carry no hostname that can go stale.
|
|
12
|
+
*/
|
|
13
|
+
/** Production, and the only baked-in set. `--gateway` points elsewhere. */
|
|
14
|
+
export const DEFAULT_URLS = {
|
|
15
|
+
app: "https://app.ai21.com",
|
|
16
|
+
gateway: "https://api.ai21.com/gateway",
|
|
17
|
+
identity: "https://api.ai21.com",
|
|
18
|
+
};
|
|
19
|
+
/**
|
|
20
|
+
* `--gateway` overrides only the gateway itself — the escape hatch for a local
|
|
21
|
+
* or dev backend. `agents` is always derived from whichever gateway won, so an
|
|
22
|
+
* override stays internally consistent.
|
|
23
|
+
*/
|
|
24
|
+
export function resolveUrls(gatewayOverride, appOverride) {
|
|
25
|
+
const base = DEFAULT_URLS;
|
|
26
|
+
// Trailing slashes are stripped so appending a path can't produce `//`, which
|
|
27
|
+
// some gateways treat as a different route than the one intended.
|
|
28
|
+
const gateway = (gatewayOverride ?? base.gateway).replace(/\/+$/, "");
|
|
29
|
+
return {
|
|
30
|
+
app: (appOverride ?? base.app).replace(/\/+$/, ""),
|
|
31
|
+
gateway,
|
|
32
|
+
identity: base.identity,
|
|
33
|
+
agents: `${gateway}/settings/agents`,
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
/** The workspace dashboard, built from the baked-in origin rather than a given URL. */
|
|
37
|
+
export function dashboardUrl(urls, workspaceId) {
|
|
38
|
+
return `${urls.app}/w/${encodeURIComponent(workspaceId)}`;
|
|
39
|
+
}
|
|
40
|
+
/** Which coding agent's config to write. Only Claude Code is implemented; the flag
|
|
41
|
+
* exists so the choice is explicit at the boundary rather than assumed throughout. */
|
|
42
|
+
export const CLIENTS = ["claude-code"];
|
|
43
|
+
export const DEFAULT_CLIENT = "claude-code";
|
|
44
|
+
export const VERBS = ["install", "login", "uninstall"];
|
|
45
|
+
/* What --help and the usage errors name. `login` is accepted but not advertised: it
|
|
46
|
+
* needs a webapp that answers its loopback callback, which is a local-dev-only setup
|
|
47
|
+
* today, so offering it to everyone reading --help only invites a dead end. */
|
|
48
|
+
export const DOCUMENTED_VERBS = ["install", "uninstall"];
|
|
49
|
+
/** `configure` was this verb's name through 0.3.x, and the dashboard printed it. Still
|
|
50
|
+
* accepted so a copied command keeps working; deliberately absent from help. (`setup`
|
|
51
|
+
* was never released, so it needs no alias.) */
|
|
52
|
+
const VERB_ALIASES = { configure: "install" };
|
|
53
|
+
/** Flags each verb accepts, beyond the global `--help` / `--version`. */
|
|
54
|
+
const ALLOWED_FLAGS = {
|
|
55
|
+
install: [
|
|
56
|
+
"app",
|
|
57
|
+
"agent-id",
|
|
58
|
+
"client",
|
|
59
|
+
"key",
|
|
60
|
+
"user-id",
|
|
61
|
+
"gateway",
|
|
62
|
+
"repo",
|
|
63
|
+
"user",
|
|
64
|
+
"print",
|
|
65
|
+
"json",
|
|
66
|
+
"yes",
|
|
67
|
+
"anthropic-key",
|
|
68
|
+
"no-verify",
|
|
69
|
+
],
|
|
70
|
+
// `login` ends in the same write-then-verify as `install`, so it takes the
|
|
71
|
+
// same verification flags.
|
|
72
|
+
// `--app` is the webapp counterpart of `--gateway`: the escape hatch for running
|
|
73
|
+
// `login` against a locally served webapp, which is the only way to develop the
|
|
74
|
+
// cross-repo handshake end to end.
|
|
75
|
+
login: ["gateway", "app", "client", "repo", "user", "print", "json", "anthropic-key", "no-verify"],
|
|
76
|
+
// `uninstall` needs --repo/--user for the same reason `install` does: it has to
|
|
77
|
+
// revert whichever settings.json was written, and a --user config would
|
|
78
|
+
// otherwise be unrevertable. It takes no --env/--gateway, though — it reads an
|
|
79
|
+
// existing file rather than resolving an endpoint. It will need `--client` the
|
|
80
|
+
// moment there is a second one, for the same unrevertable reason.
|
|
81
|
+
uninstall: ["agent-id", "from-backup", "yes", "json", "repo", "user"],
|
|
82
|
+
};
|
|
83
|
+
const OPTION_SPEC = {
|
|
84
|
+
help: { type: "boolean", short: "h" },
|
|
85
|
+
version: { type: "boolean", short: "v" },
|
|
86
|
+
key: { type: "string" },
|
|
87
|
+
"user-id": { type: "string" },
|
|
88
|
+
client: { type: "string" },
|
|
89
|
+
gateway: { type: "string" },
|
|
90
|
+
repo: { type: "boolean" },
|
|
91
|
+
user: { type: "boolean" },
|
|
92
|
+
print: { type: "boolean" },
|
|
93
|
+
json: { type: "boolean" },
|
|
94
|
+
yes: { type: "boolean" },
|
|
95
|
+
"from-backup": { type: "boolean" },
|
|
96
|
+
"agent-id": { type: "string" },
|
|
97
|
+
"anthropic-key": { type: "string" },
|
|
98
|
+
app: { type: "string" },
|
|
99
|
+
"no-verify": { type: "boolean" },
|
|
100
|
+
};
|
|
101
|
+
function fail(message) {
|
|
102
|
+
return { kind: "error", message };
|
|
103
|
+
}
|
|
104
|
+
function quoted(values) {
|
|
105
|
+
return values.map((value) => `'${value}'`).join(", ");
|
|
106
|
+
}
|
|
107
|
+
function asClient(value) {
|
|
108
|
+
return CLIENTS.includes(value) ? value : undefined;
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Flags whose values end up inside `ANTHROPIC_CUSTOM_HEADERS`, which is a
|
|
112
|
+
* `\n`-joined string. A newline in any of them forges an extra header that
|
|
113
|
+
* Claude Code would then send on every gateway request, so they are validated
|
|
114
|
+
* here at the boundary rather than in the snippet builders — those stay a
|
|
115
|
+
* faithful copy of the webapp's.
|
|
116
|
+
*
|
|
117
|
+
* This matters more than it looks: `login` will populate `key` and `agent-id`
|
|
118
|
+
* from a loopback HTTP callback, so these values stop being purely local input.
|
|
119
|
+
*/
|
|
120
|
+
const HEADER_VALUE_FLAGS = ["agent-id", "key", "user-id"];
|
|
121
|
+
/**
|
|
122
|
+
* Same rule, different reason: `--anthropic-key` is never written to disk, but it
|
|
123
|
+
* becomes the `x-api-key` header, where a bad value surfaces as a confusing 401.
|
|
124
|
+
*/
|
|
125
|
+
const REQUEST_HEADER_VALUE_FLAGS = ["anthropic-key"];
|
|
126
|
+
/** Flags that only mean something on a run that actually verifies. */
|
|
127
|
+
const VERIFY_FLAGS = ["anthropic-key", "no-verify"];
|
|
128
|
+
// C0 controls plus DEL — covers \n and \r, and leaves no exotic gaps.
|
|
129
|
+
// eslint-disable-next-line no-control-regex
|
|
130
|
+
const CONTROL_CHARS = /[\u0000-\u001F\u007F]/;
|
|
131
|
+
/**
|
|
132
|
+
* Shared with the interactive prompt, which is a second way these values enter
|
|
133
|
+
* the program and must not be a second way the rule is skipped.
|
|
134
|
+
*/
|
|
135
|
+
export function containsControlCharacters(value) {
|
|
136
|
+
return CONTROL_CHARS.test(value);
|
|
137
|
+
}
|
|
138
|
+
function validateHeaderValue(flag, value) {
|
|
139
|
+
if (value.trim() === "") {
|
|
140
|
+
return `--${flag} must not be empty.`;
|
|
141
|
+
}
|
|
142
|
+
if (CONTROL_CHARS.test(value)) {
|
|
143
|
+
return `--${flag} must not contain control characters — they would forge an extra request header.`;
|
|
144
|
+
}
|
|
145
|
+
return undefined;
|
|
146
|
+
}
|
|
147
|
+
/** Loopback never leaves the machine, so plain http there carries no exposure. */
|
|
148
|
+
function isLoopbackHost(hostname) {
|
|
149
|
+
return hostname === "127.0.0.1" || hostname === "localhost" || hostname === "::1" || hostname === "[::1]";
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* A plain-http gateway that is not on this machine. `--gateway` allows http for
|
|
153
|
+
* local dev, but every request through it carries the AI21 key, so off-box http
|
|
154
|
+
* means credentials on the wire in the clear.
|
|
155
|
+
*/
|
|
156
|
+
export function isInsecureGateway(gateway) {
|
|
157
|
+
try {
|
|
158
|
+
const { protocol, hostname } = new URL(gateway);
|
|
159
|
+
return protocol === "http:" && !isLoopbackHost(hostname);
|
|
160
|
+
}
|
|
161
|
+
catch {
|
|
162
|
+
return false;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
/** Rejects anything that isn't an absolute http(s) URL. */
|
|
166
|
+
function validateUrlFlag(flag, value) {
|
|
167
|
+
let parsed;
|
|
168
|
+
try {
|
|
169
|
+
parsed = new URL(value);
|
|
170
|
+
}
|
|
171
|
+
catch {
|
|
172
|
+
return `--${flag} must be an absolute URL, got '${value}'`;
|
|
173
|
+
}
|
|
174
|
+
if (parsed.protocol !== "https:" && parsed.protocol !== "http:") {
|
|
175
|
+
return `--${flag} must be http(s), got '${parsed.protocol}//'`;
|
|
176
|
+
}
|
|
177
|
+
return undefined;
|
|
178
|
+
}
|
|
179
|
+
const validateGateway = (value) => validateUrlFlag("gateway", value);
|
|
180
|
+
/**
|
|
181
|
+
* `--app` replaces an origin, so a path in it would be applied inconsistently: the
|
|
182
|
+
* sign-in URL is resolved against the origin and would drop it, while the dashboard
|
|
183
|
+
* link concatenates and would keep it.
|
|
184
|
+
*/
|
|
185
|
+
function validateOrigin(flag, value) {
|
|
186
|
+
const { pathname, search, hash } = new URL(value);
|
|
187
|
+
return pathname === "/" && search === "" && hash === ""
|
|
188
|
+
? undefined
|
|
189
|
+
: `--${flag} must be an origin with no path, got '${value}'`;
|
|
190
|
+
}
|
|
191
|
+
export function parseCliArgs(argv) {
|
|
192
|
+
let values;
|
|
193
|
+
let positionals;
|
|
194
|
+
try {
|
|
195
|
+
({ values, positionals } = parseArgs({
|
|
196
|
+
args: [...argv],
|
|
197
|
+
options: OPTION_SPEC,
|
|
198
|
+
strict: true,
|
|
199
|
+
allowPositionals: true,
|
|
200
|
+
}));
|
|
201
|
+
}
|
|
202
|
+
catch (err) {
|
|
203
|
+
return fail(err instanceof Error ? err.message : String(err));
|
|
204
|
+
}
|
|
205
|
+
// --help / --version win over everything, including an invalid verb.
|
|
206
|
+
if (values.help === true)
|
|
207
|
+
return { kind: "help" };
|
|
208
|
+
if (values.version === true)
|
|
209
|
+
return { kind: "version" };
|
|
210
|
+
const [first, ...restPositionals] = positionals;
|
|
211
|
+
let verb = "install";
|
|
212
|
+
if (first !== undefined) {
|
|
213
|
+
const resolved = VERB_ALIASES[first] ?? first;
|
|
214
|
+
if (!VERBS.includes(resolved)) {
|
|
215
|
+
return fail(`Unknown command '${first}'. Valid commands are ${quoted(DOCUMENTED_VERBS)}.`);
|
|
216
|
+
}
|
|
217
|
+
verb = resolved;
|
|
218
|
+
}
|
|
219
|
+
if (restPositionals.length > 0) {
|
|
220
|
+
return fail(`'${verb}' takes no positional arguments, got ${quoted(restPositionals)}.`);
|
|
221
|
+
}
|
|
222
|
+
const supplied = Object.keys(values).filter((flag) => values[flag] !== undefined);
|
|
223
|
+
const allowed = ALLOWED_FLAGS[verb];
|
|
224
|
+
const rejected = supplied.filter((flag) => flag !== "help" && flag !== "version" && !allowed.includes(flag));
|
|
225
|
+
if (rejected.length > 0) {
|
|
226
|
+
// Explicit rejection rather than silent ignore. `--key` on `uninstall`, say,
|
|
227
|
+
// reads as though it selects which config to revert; quietly dropping it
|
|
228
|
+
// would revert something the user did not name.
|
|
229
|
+
return fail(`${rejected.map((flag) => `--${flag}`).join(", ")} ${rejected.length === 1 ? "is" : "are"} not valid for '${verb}'. ` +
|
|
230
|
+
`Valid flags for '${verb}': ${allowed.map((flag) => `--${flag}`).join(", ")}.`);
|
|
231
|
+
}
|
|
232
|
+
for (const flag of [...HEADER_VALUE_FLAGS, ...REQUEST_HEADER_VALUE_FLAGS]) {
|
|
233
|
+
const value = values[flag];
|
|
234
|
+
if (typeof value !== "string")
|
|
235
|
+
continue;
|
|
236
|
+
const problem = validateHeaderValue(flag, value);
|
|
237
|
+
if (problem !== undefined)
|
|
238
|
+
return fail(problem);
|
|
239
|
+
}
|
|
240
|
+
const clientRaw = typeof values.client === "string" ? values.client : undefined;
|
|
241
|
+
let client = DEFAULT_CLIENT;
|
|
242
|
+
if (clientRaw !== undefined) {
|
|
243
|
+
const resolved = asClient(clientRaw);
|
|
244
|
+
if (resolved === undefined) {
|
|
245
|
+
// Named rather than silently defaulted: `--client codex` writing Claude Code's
|
|
246
|
+
// settings.json would configure a client the user did not ask for.
|
|
247
|
+
return fail(`Unsupported client '${clientRaw}'. Supported clients are ${quoted(CLIENTS)}.`);
|
|
248
|
+
}
|
|
249
|
+
client = resolved;
|
|
250
|
+
}
|
|
251
|
+
const gateway = typeof values.gateway === "string" ? values.gateway : undefined;
|
|
252
|
+
if (gateway !== undefined) {
|
|
253
|
+
const problem = validateGateway(gateway);
|
|
254
|
+
if (problem !== undefined)
|
|
255
|
+
return fail(problem);
|
|
256
|
+
}
|
|
257
|
+
const app = typeof values.app === "string" ? values.app : undefined;
|
|
258
|
+
if (app !== undefined) {
|
|
259
|
+
const problem = validateUrlFlag("app", app) ?? validateOrigin("app", app);
|
|
260
|
+
if (problem !== undefined)
|
|
261
|
+
return fail(problem);
|
|
262
|
+
}
|
|
263
|
+
if (values.repo === true && values.user === true) {
|
|
264
|
+
return fail("--repo and --user are mutually exclusive; pass at most one.");
|
|
265
|
+
}
|
|
266
|
+
// --print neither writes nor verifies. Rejected rather than ignored, per the rule
|
|
267
|
+
// the per-verb check above applies — and --anthropic-key carries a credential.
|
|
268
|
+
// `--app` sets the origin the loopback listener accepts, so it only means something
|
|
269
|
+
// for `login`, the one flow a browser takes part in.
|
|
270
|
+
if (values.app !== undefined && verb !== "login") {
|
|
271
|
+
return fail("--app only applies to 'login', the flow a browser takes part in.");
|
|
272
|
+
}
|
|
273
|
+
const strandedVerifyFlags = VERIFY_FLAGS.filter((flag) => values.print === true && values[flag] !== undefined);
|
|
274
|
+
if (strandedVerifyFlags.length > 0) {
|
|
275
|
+
return fail(`${strandedVerifyFlags.map((flag) => `--${flag}`).join(", ")} ` +
|
|
276
|
+
`${strandedVerifyFlags.length === 1 ? "has" : "have"} no effect with --print, which neither writes nor verifies.`);
|
|
277
|
+
}
|
|
278
|
+
/* The dashboard hands over by printing a command carrying the agent id, and the key
|
|
279
|
+
* is prompted for rather than pasted into a shell — so both arrive the ordinary way,
|
|
280
|
+
* and there is nothing for this to special-case. */
|
|
281
|
+
if (verb === "install" && typeof values["agent-id"] !== "string") {
|
|
282
|
+
return fail("--agent-id is required to install. Pass --agent-id <id>.");
|
|
283
|
+
}
|
|
284
|
+
return {
|
|
285
|
+
kind: "args",
|
|
286
|
+
args: {
|
|
287
|
+
verb,
|
|
288
|
+
urls: resolveUrls(gateway, app),
|
|
289
|
+
target: values.user === true ? "user" : "repo",
|
|
290
|
+
client,
|
|
291
|
+
agentId: verb === "install" && typeof values["agent-id"] === "string" ? values["agent-id"] : undefined,
|
|
292
|
+
key: typeof values.key === "string" ? values.key : undefined,
|
|
293
|
+
userId: typeof values["user-id"] === "string" ? values["user-id"] : undefined,
|
|
294
|
+
agentIdGuard: verb === "uninstall" && typeof values["agent-id"] === "string" ? values["agent-id"] : undefined,
|
|
295
|
+
anthropicKey: typeof values["anthropic-key"] === "string" ? values["anthropic-key"] : undefined,
|
|
296
|
+
noVerify: values["no-verify"] === true,
|
|
297
|
+
print: values.print === true,
|
|
298
|
+
json: values.json === true,
|
|
299
|
+
yes: values.yes === true,
|
|
300
|
+
fromBackup: values["from-backup"] === true,
|
|
301
|
+
},
|
|
302
|
+
};
|
|
303
|
+
}
|
|
304
|
+
//# sourceMappingURL=args.js.map
|
package/dist/args.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"args.js","sourceRoot":"","sources":["../src/args.ts"],"names":[],"mappings":"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"}
|
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { type RunResult } from "./result.js";
|
|
3
|
+
export { EXIT, type RunResult } from "./result.js";
|
|
4
|
+
export declare const USAGE = "ai21-gateway \u2014 point a local coding agent at the AI21 Intelligent Gateway\n\nUsage:\n ai21-gateway install --agent-id <id> configure a repo (default command)\n ai21-gateway uninstall revert what this tool wrote\n ai21-gateway --help\n ai21-gateway --version\n\nInstall flags:\n --agent-id <id> agent to attribute requests to (required)\n --key <key> AI21 key; prompted for without echo when omitted. Prefer the\n prompt: a key passed here is kept in your shell history\n --user-id <id> adds the x-ai21-user-id attribution header\n --client <name> which agent to configure; 'claude-code' (default) is the only\n one supported so far\n --gateway <url> override the gateway URL outright\n --repo | --user write repo-local (default) or to the home directory\n --yes overwrite an existing conflicting value\n --print render the resolved configuration instead of writing it\n (the key is always masked)\n --json machine-readable output\n\nUninstall flags:\n --agent-id <id> guard: refuse unless the stored agent matches\n --from-backup restore settings.json.bak verbatim instead of removing\n only this tool's keys \u2014 discards later edits\n --yes proceed with a --from-backup restore that discards changes\n --repo | --user which settings.json to revert\n\nBy default 'uninstall' removes only the keys this tool wrote, leaving unrelated\nsettings and any later edits of your own intact.\n\nVerification flags:\n --anthropic-key <key> Anthropic credential for the verifying request; used\n only when 'claude' is not on PATH, never written to disk\n --no-verify write the configuration without verifying it\n\nAfter a successful write the CLI sends one request through the gateway to confirm\nthe configuration works: 'claude -p' when it is on PATH, otherwise a direct\nrequest if an Anthropic credential is available. With neither, verification is\nskipped with a warning \u2014 it never changes the exit code.\n\nRe-running the same command is a no-op. An existing settings.json is backed up\nto settings.json.bak before it is changed, and is left untouched if the CLI\nrefuses.";
|
|
5
|
+
export declare function readVersion(): string;
|
|
6
|
+
/**
|
|
7
|
+
* Pure entry point: argv in, streams-and-exit-code out. Keeping I/O at the edge
|
|
8
|
+
* is what lets the whole CLI be asserted without spawning a process.
|
|
9
|
+
*/
|
|
10
|
+
export declare function run(argv: readonly string[]): Promise<RunResult>;
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { readFileSync, realpathSync } from "node:fs";
|
|
3
|
+
import { homedir } from "node:os";
|
|
4
|
+
import { dirname, join } from "node:path";
|
|
5
|
+
import { fileURLToPath } from "node:url";
|
|
6
|
+
import { parseCliArgs } from "./args.js";
|
|
7
|
+
import { EXIT } from "./result.js";
|
|
8
|
+
import { dispatch } from "./router.js";
|
|
9
|
+
import { nodeVerifyDeps } from "./verify.js";
|
|
10
|
+
import { nodeBrowserDeps, openBrowser } from "./login/browser.js";
|
|
11
|
+
import { startLoopback } from "./login/loopback.js";
|
|
12
|
+
export { EXIT } from "./result.js";
|
|
13
|
+
export const USAGE = `ai21-gateway — point a local coding agent at the AI21 Intelligent Gateway
|
|
14
|
+
|
|
15
|
+
Usage:
|
|
16
|
+
ai21-gateway install --agent-id <id> configure a repo (default command)
|
|
17
|
+
ai21-gateway uninstall revert what this tool wrote
|
|
18
|
+
ai21-gateway --help
|
|
19
|
+
ai21-gateway --version
|
|
20
|
+
|
|
21
|
+
Install flags:
|
|
22
|
+
--agent-id <id> agent to attribute requests to (required)
|
|
23
|
+
--key <key> AI21 key; prompted for without echo when omitted. Prefer the
|
|
24
|
+
prompt: a key passed here is kept in your shell history
|
|
25
|
+
--user-id <id> adds the x-ai21-user-id attribution header
|
|
26
|
+
--client <name> which agent to configure; 'claude-code' (default) is the only
|
|
27
|
+
one supported so far
|
|
28
|
+
--gateway <url> override the gateway URL outright
|
|
29
|
+
--repo | --user write repo-local (default) or to the home directory
|
|
30
|
+
--yes overwrite an existing conflicting value
|
|
31
|
+
--print render the resolved configuration instead of writing it
|
|
32
|
+
(the key is always masked)
|
|
33
|
+
--json machine-readable output
|
|
34
|
+
|
|
35
|
+
Uninstall flags:
|
|
36
|
+
--agent-id <id> guard: refuse unless the stored agent matches
|
|
37
|
+
--from-backup restore settings.json.bak verbatim instead of removing
|
|
38
|
+
only this tool's keys — discards later edits
|
|
39
|
+
--yes proceed with a --from-backup restore that discards changes
|
|
40
|
+
--repo | --user which settings.json to revert
|
|
41
|
+
|
|
42
|
+
By default 'uninstall' removes only the keys this tool wrote, leaving unrelated
|
|
43
|
+
settings and any later edits of your own intact.
|
|
44
|
+
|
|
45
|
+
Verification flags:
|
|
46
|
+
--anthropic-key <key> Anthropic credential for the verifying request; used
|
|
47
|
+
only when 'claude' is not on PATH, never written to disk
|
|
48
|
+
--no-verify write the configuration without verifying it
|
|
49
|
+
|
|
50
|
+
After a successful write the CLI sends one request through the gateway to confirm
|
|
51
|
+
the configuration works: 'claude -p' when it is on PATH, otherwise a direct
|
|
52
|
+
request if an Anthropic credential is available. With neither, verification is
|
|
53
|
+
skipped with a warning — it never changes the exit code.
|
|
54
|
+
|
|
55
|
+
Re-running the same command is a no-op. An existing settings.json is backed up
|
|
56
|
+
to settings.json.bak before it is changed, and is left untouched if the CLI
|
|
57
|
+
refuses.`;
|
|
58
|
+
/** Absolute path to the package root, resolved from this module's location. */
|
|
59
|
+
function packageRoot() {
|
|
60
|
+
return join(dirname(fileURLToPath(import.meta.url)), "..");
|
|
61
|
+
}
|
|
62
|
+
export function readVersion() {
|
|
63
|
+
const raw = readFileSync(join(packageRoot(), "package.json"), "utf8");
|
|
64
|
+
const { version } = JSON.parse(raw);
|
|
65
|
+
if (typeof version !== "string") {
|
|
66
|
+
throw new Error('package.json is missing a string "version"');
|
|
67
|
+
}
|
|
68
|
+
return version;
|
|
69
|
+
}
|
|
70
|
+
function versionResult() {
|
|
71
|
+
try {
|
|
72
|
+
return { code: EXIT.OK, out: `${readVersion()}\n`, err: "" };
|
|
73
|
+
}
|
|
74
|
+
catch {
|
|
75
|
+
// Deliberately no error detail: the underlying failure is an fs error
|
|
76
|
+
// carrying an absolute install path, and user-facing errors must not leak
|
|
77
|
+
// internal paths or stack traces.
|
|
78
|
+
return {
|
|
79
|
+
code: EXIT.INTERNAL,
|
|
80
|
+
out: "",
|
|
81
|
+
err: "ai21-gateway: could not read its own package metadata — the installation looks corrupt. Try reinstalling.\n",
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Pure entry point: argv in, streams-and-exit-code out. Keeping I/O at the edge
|
|
87
|
+
* is what lets the whole CLI be asserted without spawning a process.
|
|
88
|
+
*/
|
|
89
|
+
export async function run(argv) {
|
|
90
|
+
// Bare invocation is a request for orientation, not a failed `install`.
|
|
91
|
+
if (argv.length === 0)
|
|
92
|
+
return { code: EXIT.OK, out: `${USAGE}\n`, err: "" };
|
|
93
|
+
const outcome = parseCliArgs(argv);
|
|
94
|
+
switch (outcome.kind) {
|
|
95
|
+
case "help":
|
|
96
|
+
return { code: EXIT.OK, out: `${USAGE}\n`, err: "" };
|
|
97
|
+
case "version":
|
|
98
|
+
return versionResult();
|
|
99
|
+
case "error":
|
|
100
|
+
return { code: EXIT.USAGE, out: "", err: `${outcome.message}\n\n${USAGE}\n` };
|
|
101
|
+
case "args":
|
|
102
|
+
// Everything the CLI needs from the outside world is gathered here, at the
|
|
103
|
+
// edge, so every layer below stays pure and testable against a temp
|
|
104
|
+
// directory and a pair of fake streams.
|
|
105
|
+
return dispatch(outcome.args, {
|
|
106
|
+
paths: { cwd: process.cwd(), home: homedir() },
|
|
107
|
+
prompt: { input: process.stdin, output: process.stderr },
|
|
108
|
+
processEnv: process.env,
|
|
109
|
+
verify: nodeVerifyDeps(process.env),
|
|
110
|
+
login: {
|
|
111
|
+
startListener: startLoopback,
|
|
112
|
+
openBrowser: (url) => openBrowser(url, nodeBrowserDeps()),
|
|
113
|
+
},
|
|
114
|
+
// stderr, so `--json` on stdout stays a single parseable object even while
|
|
115
|
+
// login narrates its progress.
|
|
116
|
+
notify: (message) => process.stderr.write(`${message}\n`),
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
function isMain() {
|
|
121
|
+
const invoked = process.argv[1];
|
|
122
|
+
if (invoked === undefined)
|
|
123
|
+
return false;
|
|
124
|
+
try {
|
|
125
|
+
// realpath both sides: npm installs `bin` as a symlink into node_modules/.bin
|
|
126
|
+
return realpathSync(invoked) === realpathSync(fileURLToPath(import.meta.url));
|
|
127
|
+
}
|
|
128
|
+
catch {
|
|
129
|
+
return false;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
if (isMain()) {
|
|
133
|
+
const { code, out, err } = await run(process.argv.slice(2));
|
|
134
|
+
if (out !== "")
|
|
135
|
+
process.stdout.write(out);
|
|
136
|
+
if (err !== "")
|
|
137
|
+
process.stderr.write(err);
|
|
138
|
+
process.exit(code);
|
|
139
|
+
}
|
|
140
|
+
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|