anyray-connect 0.1.0
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 +95 -0
- package/dist/cli.js +383 -0
- package/dist/cli.js.map +1 -0
- package/dist/index.js +15 -0
- package/dist/index.js.map +1 -0
- package/dist/target.js +56 -0
- package/dist/target.js.map +1 -0
- package/dist/tools/claudeCode.js +131 -0
- package/dist/tools/claudeCode.js.map +1 -0
- package/dist/tools/codex.js +220 -0
- package/dist/tools/codex.js.map +1 -0
- package/dist/tools/index.js +20 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/manual.js +73 -0
- package/dist/tools/manual.js.map +1 -0
- package/dist/tools/shellEnv.js +77 -0
- package/dist/tools/shellEnv.js.map +1 -0
- package/dist/types.js +22 -0
- package/dist/types.js.map +1 -0
- package/dist/util/identity.js +25 -0
- package/dist/util/identity.js.map +1 -0
- package/dist/util/jsonFile.js +41 -0
- package/dist/util/jsonFile.js.map +1 -0
- package/dist/util/log.js +19 -0
- package/dist/util/log.js.map +1 -0
- package/dist/util/persist.js +27 -0
- package/dist/util/persist.js.map +1 -0
- package/dist/util/preflight.js +41 -0
- package/dist/util/preflight.js.map +1 -0
- package/dist/util/profile.js +54 -0
- package/dist/util/profile.js.map +1 -0
- package/dist/util/redeem.js +82 -0
- package/dist/util/redeem.js.map +1 -0
- package/package.json +44 -0
package/README.md
ADDED
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
# anyray-connect
|
|
2
|
+
|
|
3
|
+
The on-ramp. A small, dependency-free Node CLI that points a developer's local
|
|
4
|
+
coding tools at the **Anyray gateway** by writing each tool's base URL and a
|
|
5
|
+
**placeholder** API key. The gateway stays the brain (routing, spend store,
|
|
6
|
+
content encryption, optimizer) — this only does capture/onboarding.
|
|
7
|
+
|
|
8
|
+
```bash
|
|
9
|
+
npx anyray-connect --gateway https://gw.yourorg.internal --user you@yourorg.com
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
## Personal gateway keys (invites)
|
|
13
|
+
|
|
14
|
+
When the gateway is exposed publicly, each dev authenticates with a **personal
|
|
15
|
+
gateway key** (`ark_...`) instead of the shared placeholder:
|
|
16
|
+
|
|
17
|
+
1. An org admin creates an invite on the gateway (admin-token-gated):
|
|
18
|
+
`POST <gateway>/admin/invites` with `{ "user": "<email>", "team": "..." }`
|
|
19
|
+
→ an `ari_...` invite token. (`POST /admin/client-keys` mints a key
|
|
20
|
+
directly, skipping the invite step.)
|
|
21
|
+
2. The dev redeems it while connecting:
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
npx anyray-connect --gateway https://gw.yourorg.example --invite ari_xxxxxxxx
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Redemption (`POST <gateway>/connect/redeem`) is **single-use**: it returns the
|
|
28
|
+
personal key plus the user/team the invite was issued for, which become the
|
|
29
|
+
attribution defaults (explicit `--user`/`--team` win). The key is written
|
|
30
|
+
straight into the tool configs and never printed (the CLI shows only a masked
|
|
31
|
+
`ark_…xxxx`). Because redemption is single-use, `--dry-run` skips it — the
|
|
32
|
+
invite is not consumed on a dry run.
|
|
33
|
+
|
|
34
|
+
Already have a key? Set `ANYRAY_CLIENT_KEY` in the environment and run without
|
|
35
|
+
`--invite`; it's picked up the same way.
|
|
36
|
+
|
|
37
|
+
How the key is sent depends on the auth mode:
|
|
38
|
+
|
|
39
|
+
- **Placeholder mode** (default): the key replaces the shared placeholder as
|
|
40
|
+
the `Authorization` bearer.
|
|
41
|
+
- **`--subscription`**: the tool's seat OAuth token keeps the `Authorization`
|
|
42
|
+
header, and the personal key rides the `x-anyray-api-key` header instead so
|
|
43
|
+
the gateway can still identify the dev.
|
|
44
|
+
|
|
45
|
+
## What it changes
|
|
46
|
+
|
|
47
|
+
| Tool | How |
|
|
48
|
+
| --- | --- |
|
|
49
|
+
| **Claude Code** | Automatic — writes the `env` block in `~/.claude/settings.json` (`ANTHROPIC_BASE_URL`, placeholder `ANTHROPIC_AUTH_TOKEN`, and `ANTHROPIC_CUSTOM_HEADERS` carrying `x-anyray-metadata`). With `--subscription`, no auth token is written: Claude Code keeps its seat (Pro/Max/Team/Enterprise) sign-in and the gateway passes the OAuth token through (`x-anyray-auth-mode: passthrough`), so spend stays on the subscription. |
|
|
50
|
+
| **Codex CLI** | Automatic — appends a managed `[model_providers.anyray]` + `[profiles.anyray]` block to `~/.codex/config.toml`; opt in per run with `codex --profile anyray`. With `--subscription`, the provider sets `requires_openai_auth = true` and no static key: Codex attaches its ChatGPT sign-in itself, and the gateway passes the OAuth token through to the ChatGPT Codex backend (`x-anyray-custom-host`), so spend stays on the seat. |
|
|
51
|
+
| **Shell env** | Automatic — a managed, idempotent block in your shell profile with `OPENAI_BASE_URL` / `ANTHROPIC_BASE_URL` + placeholder keys (covers SDK jobs and scripts). |
|
|
52
|
+
| **Cursor / Windsurf** | Detect + print exact UI steps (their config is app state we don't script). |
|
|
53
|
+
|
|
54
|
+
The real provider key is never written here — it stays server-side in the
|
|
55
|
+
gateway (`ANYRAY_PROVIDER_KEY_*`), which swaps it in per request. Only metadata
|
|
56
|
+
(user/team) is attached for spend attribution; **prompt/response content is never
|
|
57
|
+
touched.**
|
|
58
|
+
|
|
59
|
+
## Common flags
|
|
60
|
+
|
|
61
|
+
```
|
|
62
|
+
--gateway <url> Gateway origin (default: $ANYRAY_GATEWAY_URL or http://localhost:8787)
|
|
63
|
+
--user <id> Attribute spend to this user (default: git email, else OS user)
|
|
64
|
+
--team <id> Attribute spend to this team
|
|
65
|
+
--tools <ids> Subset: claude-code, codex, cursor, windsurf, shell-env
|
|
66
|
+
--invite <token> Redeem an org invite (single-use) for a personal gateway key
|
|
67
|
+
and use it as your auth; defaults --user/--team from the
|
|
68
|
+
invite. Skipped under --dry-run (the invite isn't consumed).
|
|
69
|
+
Already have a key? Set $ANYRAY_CLIENT_KEY instead.
|
|
70
|
+
--subscription Seat-billed (subscription) auth: pass the tool's own OAuth
|
|
71
|
+
token through the gateway instead of the org API key.
|
|
72
|
+
Honored by Claude Code (Anthropic seats) and Codex (ChatGPT
|
|
73
|
+
seats); other tools configure as usual. With a personal
|
|
74
|
+
gateway key (--invite / $ANYRAY_CLIENT_KEY), the key rides
|
|
75
|
+
x-anyray-api-key while the seat token stays the bearer.
|
|
76
|
+
--dry-run Show what would change without writing
|
|
77
|
+
--yes, -y Skip confirmation (scripted/fleet rollout)
|
|
78
|
+
--revert Undo a previous run
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
## Adding a tool
|
|
82
|
+
|
|
83
|
+
Adapters live in `src/tools/` and are registered in `src/tools/index.ts`
|
|
84
|
+
(`REGISTRY`) — same open/closed seam as the optimizer's strategy registry. Write
|
|
85
|
+
an adapter implementing `ToolAdapter` (`detect` / `apply` / `revert`) and add one
|
|
86
|
+
line to the registry. Nothing in the CLI orchestrator changes.
|
|
87
|
+
|
|
88
|
+
## Develop
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
npm install
|
|
92
|
+
npm run dev -- --dry-run # run from source
|
|
93
|
+
npm test # node --test
|
|
94
|
+
npm run build # tsc → dist/
|
|
95
|
+
```
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,383 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `anyray-connect` CLI orchestration.
|
|
3
|
+
*
|
|
4
|
+
* Resolve the gateway target → detect installed tools → show the plan →
|
|
5
|
+
* (confirm) → apply each adapter → print a summary with a verify step. All
|
|
6
|
+
* intelligence stays in the gateway; this only writes base URLs + placeholder
|
|
7
|
+
* keys + content-free attribution.
|
|
8
|
+
*/
|
|
9
|
+
import { createInterface } from 'node:readline/promises';
|
|
10
|
+
import { resolveOrigin, resolveTarget } from './target.js';
|
|
11
|
+
import { checkGateway } from './util/preflight.js';
|
|
12
|
+
import { maskKey, redeemInvite } from './util/redeem.js';
|
|
13
|
+
import { REGISTRY, byId } from './tools/index.js';
|
|
14
|
+
import { metadataHeaderValue } from './types.js';
|
|
15
|
+
import { bold, cyan, dim, fail, heading, info, note, ok, warn, } from './util/log.js';
|
|
16
|
+
import { detectDisplayName } from './util/identity.js';
|
|
17
|
+
import { loadProfile, saveProfile } from './util/persist.js';
|
|
18
|
+
const HELP = `${bold('anyray-connect')} — point your local coding tools at the Anyray gateway
|
|
19
|
+
|
|
20
|
+
${bold('Usage')}
|
|
21
|
+
npx anyray-connect <gateway-url> [options]
|
|
22
|
+
npx anyray-connect [options] (gateway from $ANYRAY_GATEWAY_URL, the ~/.anyray cache, or http://localhost:8787)
|
|
23
|
+
|
|
24
|
+
${bold('Options')}
|
|
25
|
+
--gateway <url> Gateway origin (default: $ANYRAY_GATEWAY_URL, then the
|
|
26
|
+
~/.anyray cache, then http://localhost:8787)
|
|
27
|
+
--user <id> Attribute spend to this user (default: cached name, else
|
|
28
|
+
git config user.name/email, else OS user; '' clears the cache)
|
|
29
|
+
--team <id> Attribute spend to this team ('' clears the cached team)
|
|
30
|
+
--intent <id> Tag traffic with an intent (filterable as intent:<id> in the console)
|
|
31
|
+
--intent-label <s> Human-readable label for the intent
|
|
32
|
+
--session <id> Group requests under a session id in the console
|
|
33
|
+
--key <value> Placeholder API key to send (default: anyray-placeholder)
|
|
34
|
+
--invite <token> Redeem an org invite for a personal gateway key and use it
|
|
35
|
+
as your auth. The key replaces the placeholder bearer; with
|
|
36
|
+
--subscription it rides x-anyray-api-key instead (your seat
|
|
37
|
+
OAuth token stays the bearer). Defaults --user/--team from
|
|
38
|
+
the invite unless you pass them. Redemption is single-use,
|
|
39
|
+
so --dry-run skips it (the invite is not consumed).
|
|
40
|
+
Already have a key? Set $ANYRAY_CLIENT_KEY instead.
|
|
41
|
+
--subscription Keep seat (subscription) sign-in: the tool's own OAuth token
|
|
42
|
+
passes through the gateway instead of the org API key.
|
|
43
|
+
Honored by Claude Code (Anthropic seats) and Codex (ChatGPT
|
|
44
|
+
seats); other tools configure as usual.
|
|
45
|
+
--tools <ids> Comma-separated subset: ${REGISTRY.map((t) => t.id).join(', ')}
|
|
46
|
+
--dry-run Show what would change without writing anything
|
|
47
|
+
--yes, -y Don't prompt for confirmation (for scripted rollout)
|
|
48
|
+
--force Skip the gateway reachability check before writing
|
|
49
|
+
--revert Undo a previous run
|
|
50
|
+
--help, -h Show this help
|
|
51
|
+
|
|
52
|
+
${bold('What it does')}
|
|
53
|
+
Writes each tool's base URL + a ${dim('placeholder')} key so requests flow through the
|
|
54
|
+
gateway. The real provider key stays server-side (ANYRAY_PROVIDER_KEY_*); your
|
|
55
|
+
tools never hold it. Only metadata (user/team) is attached — never prompt content.
|
|
56
|
+
Gateway/name/team are remembered in ~/.anyray (mode 600) for zero-question re-runs.`;
|
|
57
|
+
const parseArgs = (argv) => {
|
|
58
|
+
const args = {
|
|
59
|
+
subscription: false,
|
|
60
|
+
dryRun: false,
|
|
61
|
+
yes: false,
|
|
62
|
+
revert: false,
|
|
63
|
+
force: false,
|
|
64
|
+
help: false,
|
|
65
|
+
};
|
|
66
|
+
for (let i = 0; i < argv.length; i++) {
|
|
67
|
+
const a = argv[i];
|
|
68
|
+
const next = () => argv[++i];
|
|
69
|
+
switch (a) {
|
|
70
|
+
case '--gateway':
|
|
71
|
+
args.gateway = next();
|
|
72
|
+
break;
|
|
73
|
+
case '--user':
|
|
74
|
+
args.user = next();
|
|
75
|
+
break;
|
|
76
|
+
case '--team':
|
|
77
|
+
args.team = next();
|
|
78
|
+
break;
|
|
79
|
+
case '--intent':
|
|
80
|
+
args.intent = next();
|
|
81
|
+
break;
|
|
82
|
+
case '--intent-label':
|
|
83
|
+
args.intentLabel = next();
|
|
84
|
+
break;
|
|
85
|
+
case '--session':
|
|
86
|
+
args.session = next();
|
|
87
|
+
break;
|
|
88
|
+
case '--key':
|
|
89
|
+
args.key = next();
|
|
90
|
+
break;
|
|
91
|
+
case '--invite':
|
|
92
|
+
args.invite = next();
|
|
93
|
+
break;
|
|
94
|
+
case '--subscription':
|
|
95
|
+
args.subscription = true;
|
|
96
|
+
break;
|
|
97
|
+
case '--tools':
|
|
98
|
+
args.tools = (next() ?? '')
|
|
99
|
+
.split(',')
|
|
100
|
+
.map((s) => s.trim())
|
|
101
|
+
.filter(Boolean);
|
|
102
|
+
break;
|
|
103
|
+
case '--dry-run':
|
|
104
|
+
args.dryRun = true;
|
|
105
|
+
break;
|
|
106
|
+
case '--yes':
|
|
107
|
+
case '-y':
|
|
108
|
+
args.yes = true;
|
|
109
|
+
break;
|
|
110
|
+
case '--force':
|
|
111
|
+
args.force = true;
|
|
112
|
+
break;
|
|
113
|
+
case '--revert':
|
|
114
|
+
args.revert = true;
|
|
115
|
+
break;
|
|
116
|
+
case '--help':
|
|
117
|
+
case '-h':
|
|
118
|
+
args.help = true;
|
|
119
|
+
break;
|
|
120
|
+
default:
|
|
121
|
+
// First non-flag token is the gateway URL; a second positional is an error.
|
|
122
|
+
if (!a.startsWith('-') && args.gateway === undefined) {
|
|
123
|
+
args.gateway = a;
|
|
124
|
+
}
|
|
125
|
+
else {
|
|
126
|
+
throw new Error(a.startsWith('-')
|
|
127
|
+
? `unknown option: ${a}`
|
|
128
|
+
: `unexpected argument: ${a} (gateway already set to ${args.gateway})`);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
return args;
|
|
133
|
+
};
|
|
134
|
+
/** Resolve which adapters to act on, honoring --tools and validating ids. */
|
|
135
|
+
const selectAdapters = (ids) => {
|
|
136
|
+
if (!ids || ids.length === 0)
|
|
137
|
+
return REGISTRY;
|
|
138
|
+
return ids.map((id) => {
|
|
139
|
+
const adapter = byId(id);
|
|
140
|
+
if (!adapter) {
|
|
141
|
+
throw new Error(`unknown tool "${id}". Known: ${REGISTRY.map((t) => t.id).join(', ')}`);
|
|
142
|
+
}
|
|
143
|
+
return adapter;
|
|
144
|
+
});
|
|
145
|
+
};
|
|
146
|
+
const printTarget = (target) => {
|
|
147
|
+
heading('Gateway target');
|
|
148
|
+
info(` Origin: ${cyan(target.origin)}`);
|
|
149
|
+
if (target.authMode === 'subscription') {
|
|
150
|
+
info(` Auth: subscription pass-through ${dim('(seat OAuth token; Claude Code + Codex)')}`);
|
|
151
|
+
if (target.clientKey) {
|
|
152
|
+
info(` Client key: personal gateway key (${maskKey(target.clientKey)}) ${dim('rides x-anyray-api-key')}`);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
else if (target.clientKey) {
|
|
156
|
+
info(` Auth: personal gateway key (${maskKey(target.clientKey)}) ${dim('(replaces the placeholder)')}`);
|
|
157
|
+
}
|
|
158
|
+
else {
|
|
159
|
+
info(` Placeholder: ${target.placeholderKey} ${dim('(gateway swaps in the real key)')}`);
|
|
160
|
+
}
|
|
161
|
+
info(` Attribution: ${metadataHeaderValue(target.metadata) ?? dim('(none — pass --user)')}`);
|
|
162
|
+
};
|
|
163
|
+
const confirm = async (question) => {
|
|
164
|
+
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
165
|
+
try {
|
|
166
|
+
const answer = (await rl.question(`${question} ${dim('[y/N]')} `)).trim();
|
|
167
|
+
return /^y(es)?$/i.test(answer);
|
|
168
|
+
}
|
|
169
|
+
finally {
|
|
170
|
+
rl.close();
|
|
171
|
+
}
|
|
172
|
+
};
|
|
173
|
+
const prompt = async (question, defaultValue) => {
|
|
174
|
+
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
175
|
+
try {
|
|
176
|
+
const hint = defaultValue ? ` ${dim(`[${defaultValue}]`)}` : '';
|
|
177
|
+
const raw = (await rl.question(`${question}${hint}: `)).trim();
|
|
178
|
+
return raw || defaultValue;
|
|
179
|
+
}
|
|
180
|
+
finally {
|
|
181
|
+
rl.close();
|
|
182
|
+
}
|
|
183
|
+
};
|
|
184
|
+
/** Explicit flag wins ('' clears the cache) → cached → detected, prompted on a TTY. */
|
|
185
|
+
const resolveDisplayName = async (explicit, cached, yes) => {
|
|
186
|
+
if (explicit !== undefined)
|
|
187
|
+
return explicit.trim() || undefined;
|
|
188
|
+
if (cached) {
|
|
189
|
+
note(`Your name: ${cached} ${dim('(cached — pass --user to change)')}`);
|
|
190
|
+
return cached;
|
|
191
|
+
}
|
|
192
|
+
const detected = detectDisplayName();
|
|
193
|
+
// Without a TTY, prompting would block forever on a silent pipe — behave like --yes.
|
|
194
|
+
if (yes || !process.stdin.isTTY) {
|
|
195
|
+
note(`Your name: ${detected} ${dim('(auto-detected — pass --user to change)')}`);
|
|
196
|
+
return detected;
|
|
197
|
+
}
|
|
198
|
+
return prompt('? Your name', detected);
|
|
199
|
+
};
|
|
200
|
+
/** Explicit flag wins ('' clears the cache) → cached → optional prompt on a TTY. */
|
|
201
|
+
const resolveTeam = async (explicit, cached, yes) => {
|
|
202
|
+
if (explicit !== undefined)
|
|
203
|
+
return explicit.trim() || undefined;
|
|
204
|
+
if (cached) {
|
|
205
|
+
note(`Team: ${cached} ${dim('(cached — pass --team to change)')}`);
|
|
206
|
+
return cached;
|
|
207
|
+
}
|
|
208
|
+
if (yes || !process.stdin.isTTY)
|
|
209
|
+
return undefined;
|
|
210
|
+
return prompt('? Team (optional)');
|
|
211
|
+
};
|
|
212
|
+
const runApply = async (adapters, target, opts, revert) => {
|
|
213
|
+
let changes = 0;
|
|
214
|
+
for (const adapter of adapters) {
|
|
215
|
+
const detected = await adapter.detect();
|
|
216
|
+
heading(`${adapter.title} ${dim(`(${adapter.id})`)}`);
|
|
217
|
+
if (!detected.installed && !revert) {
|
|
218
|
+
note(` not found — ${detected.detail ?? 'skipping'}`);
|
|
219
|
+
continue;
|
|
220
|
+
}
|
|
221
|
+
try {
|
|
222
|
+
const result = revert
|
|
223
|
+
? await adapter.revert(opts)
|
|
224
|
+
: await adapter.apply(target, opts);
|
|
225
|
+
for (const m of result.messages)
|
|
226
|
+
info(` ${m}`);
|
|
227
|
+
if (result.status === 'configured' || result.status === 'reverted') {
|
|
228
|
+
changes += result.changedFiles?.length ?? 0;
|
|
229
|
+
ok(` ${result.status}`);
|
|
230
|
+
}
|
|
231
|
+
else if (result.status === 'manual') {
|
|
232
|
+
warn(' manual step required (see above)');
|
|
233
|
+
}
|
|
234
|
+
else {
|
|
235
|
+
note(` ${result.status}`);
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
catch (error) {
|
|
239
|
+
fail(` failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
return changes;
|
|
243
|
+
};
|
|
244
|
+
export const run = async (argv) => {
|
|
245
|
+
let args;
|
|
246
|
+
try {
|
|
247
|
+
args = parseArgs(argv);
|
|
248
|
+
}
|
|
249
|
+
catch (error) {
|
|
250
|
+
fail(error.message);
|
|
251
|
+
info('\nRun `anyray-connect --help` for usage.');
|
|
252
|
+
return 1;
|
|
253
|
+
}
|
|
254
|
+
if (args.help) {
|
|
255
|
+
info(HELP);
|
|
256
|
+
return 0;
|
|
257
|
+
}
|
|
258
|
+
let adapters;
|
|
259
|
+
try {
|
|
260
|
+
adapters = selectAdapters(args.tools);
|
|
261
|
+
}
|
|
262
|
+
catch (error) {
|
|
263
|
+
fail(error.message);
|
|
264
|
+
return 1;
|
|
265
|
+
}
|
|
266
|
+
const profile = await loadProfile();
|
|
267
|
+
const cachedGateway = !args.gateway && !process.env.ANYRAY_GATEWAY_URL
|
|
268
|
+
? profile.gateway
|
|
269
|
+
: undefined;
|
|
270
|
+
if (cachedGateway)
|
|
271
|
+
args.gateway = cachedGateway;
|
|
272
|
+
// Validate before any prompt, and before a bad value can be re-persisted.
|
|
273
|
+
let origin;
|
|
274
|
+
try {
|
|
275
|
+
origin = resolveOrigin(args.gateway);
|
|
276
|
+
}
|
|
277
|
+
catch (error) {
|
|
278
|
+
fail(error.message);
|
|
279
|
+
return 1;
|
|
280
|
+
}
|
|
281
|
+
let resolvedUser;
|
|
282
|
+
let resolvedTeam;
|
|
283
|
+
info(bold(args.revert ? 'Anyray connect — revert' : 'Anyray connect'));
|
|
284
|
+
if (cachedGateway && !args.revert) {
|
|
285
|
+
note(`Gateway: ${origin} ${dim('(cached in ~/.anyray — pass a URL to change)')}`);
|
|
286
|
+
}
|
|
287
|
+
// Invite redemption — exchanges the single-use invite for a personal gateway
|
|
288
|
+
// key BEFORE the target is resolved, so the key + the invite's user/team
|
|
289
|
+
// (explicit flags win) flow into every adapter. A dry run must not consume
|
|
290
|
+
// the invite, and a revert doesn't need a key, so both skip redemption.
|
|
291
|
+
let clientKey;
|
|
292
|
+
if (args.invite && !args.revert) {
|
|
293
|
+
if (args.dryRun) {
|
|
294
|
+
note('dry run: invite not redeemed (redemption is single-use).');
|
|
295
|
+
}
|
|
296
|
+
else {
|
|
297
|
+
try {
|
|
298
|
+
const redeemed = await redeemInvite(origin, args.invite);
|
|
299
|
+
clientKey = redeemed.key;
|
|
300
|
+
args.user ||= redeemed.user;
|
|
301
|
+
args.team ||= redeemed.team;
|
|
302
|
+
ok(`Invite redeemed${redeemed.user ? ` for ${redeemed.user}` : ''} — personal gateway key received (not shown; it lands in your tool configs).`);
|
|
303
|
+
}
|
|
304
|
+
catch (error) {
|
|
305
|
+
fail(error instanceof Error ? error.message : String(error));
|
|
306
|
+
return 1;
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
// Skipped on revert — no attribution needed there.
|
|
311
|
+
if (!args.revert) {
|
|
312
|
+
resolvedUser = await resolveDisplayName(args.user, profile.name, args.yes);
|
|
313
|
+
resolvedTeam = await resolveTeam(args.team, profile.team, args.yes);
|
|
314
|
+
}
|
|
315
|
+
const target = resolveTarget({
|
|
316
|
+
origin,
|
|
317
|
+
placeholderKey: args.key,
|
|
318
|
+
clientKey,
|
|
319
|
+
subscription: args.subscription,
|
|
320
|
+
user: resolvedUser,
|
|
321
|
+
team: resolvedTeam,
|
|
322
|
+
intent: args.intent,
|
|
323
|
+
intentLabel: args.intentLabel,
|
|
324
|
+
session: args.session,
|
|
325
|
+
});
|
|
326
|
+
const opts = { dryRun: args.dryRun };
|
|
327
|
+
if (!args.revert)
|
|
328
|
+
printTarget(target);
|
|
329
|
+
if (args.dryRun)
|
|
330
|
+
note('\nDry run — no files will be written.');
|
|
331
|
+
if (!args.yes && !args.dryRun) {
|
|
332
|
+
const verb = args.revert ? 'remove Anyray config from' : 'configure';
|
|
333
|
+
const proceed = await confirm(`\n${verb} ${adapters.length} tool target(s)?`);
|
|
334
|
+
if (!proceed) {
|
|
335
|
+
note('Aborted. Nothing changed.');
|
|
336
|
+
return 0;
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
// Preflight: never repoint a working tool at a gateway that isn't answering.
|
|
340
|
+
// Skipped for dry-run (writes nothing) and revert (removing config, not adding
|
|
341
|
+
// it). `--force` is the escape hatch for configuring ahead of the gateway.
|
|
342
|
+
if (!args.dryRun && !args.revert && !args.force) {
|
|
343
|
+
const probe = await checkGateway(target.origin);
|
|
344
|
+
if (!probe.reachable) {
|
|
345
|
+
fail(`\nGateway ${target.origin} is not reachable (${probe.detail}).`);
|
|
346
|
+
info(dim(' Refusing to repoint your tools at a gateway that isn’t responding —\n' +
|
|
347
|
+
' that would break them until you re-run with --revert.'));
|
|
348
|
+
info('\n Start the gateway and try again, or pass --force to configure anyway.');
|
|
349
|
+
return 1;
|
|
350
|
+
}
|
|
351
|
+
ok(`Gateway reachable (${probe.detail}).`);
|
|
352
|
+
}
|
|
353
|
+
const changes = await runApply(adapters, target, opts, args.revert);
|
|
354
|
+
heading('Summary');
|
|
355
|
+
if (args.dryRun) {
|
|
356
|
+
note('Dry run complete — re-run without --dry-run to apply.');
|
|
357
|
+
}
|
|
358
|
+
else if (args.revert) {
|
|
359
|
+
ok(`Reverted (${changes} file(s) touched).`);
|
|
360
|
+
}
|
|
361
|
+
else {
|
|
362
|
+
ok(`Done (${changes} file(s) written).`);
|
|
363
|
+
info('\nVerify a request flows through the gateway:');
|
|
364
|
+
info(dim(
|
|
365
|
+
// Never echo a personal key — point at the tool config it landed in.
|
|
366
|
+
` curl ${target.openaiBaseUrl}/models -H "Authorization: Bearer ${target.clientKey
|
|
367
|
+
? `<your personal key (${maskKey(target.clientKey)}) — see your tool config>`
|
|
368
|
+
: target.placeholderKey}"`));
|
|
369
|
+
info(dim(' Revert: npx anyray-connect --revert'));
|
|
370
|
+
try {
|
|
371
|
+
await saveProfile({
|
|
372
|
+
gateway: target.origin,
|
|
373
|
+
name: resolvedUser,
|
|
374
|
+
team: resolvedTeam,
|
|
375
|
+
});
|
|
376
|
+
}
|
|
377
|
+
catch (error) {
|
|
378
|
+
warn(`Could not save profile: ${error instanceof Error ? error.message : String(error)}`);
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
return 0;
|
|
382
|
+
};
|
|
383
|
+
//# 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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"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* `anyray-connect` entry point. Thin shim: parse argv, run the CLI, set the
|
|
4
|
+
* exit code. All logic lives in cli.ts so it stays unit-testable.
|
|
5
|
+
*/
|
|
6
|
+
import { run } from './cli.js';
|
|
7
|
+
run(process.argv.slice(2))
|
|
8
|
+
.then((code) => {
|
|
9
|
+
process.exitCode = code;
|
|
10
|
+
})
|
|
11
|
+
.catch((error) => {
|
|
12
|
+
console.error(error);
|
|
13
|
+
process.exitCode = 1;
|
|
14
|
+
});
|
|
15
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA;;;GAGG;AAEH,OAAO,EAAE,GAAG,EAAE,MAAM,UAAU,CAAC;AAE/B,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;KACvB,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE;IACb,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC;AAC1B,CAAC,CAAC;KACD,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;IACf,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IACrB,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;AACvB,CAAC,CAAC,CAAC"}
|
package/dist/target.js
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resolve a `GatewayTarget` from CLI flags / env / sensible defaults.
|
|
3
|
+
*
|
|
4
|
+
* The gateway is OpenAI-compatible at `<origin>/v1/...` and accepts the
|
|
5
|
+
* Anthropic format at `<origin>/v1/messages`. The two SDK families want the base
|
|
6
|
+
* URL shaped differently, so we derive both from a single origin:
|
|
7
|
+
* - Anthropic SDK: base is the bare origin (it appends `/v1/messages`).
|
|
8
|
+
* - OpenAI SDK: base includes `/v1` (it appends `/chat/completions`).
|
|
9
|
+
*/
|
|
10
|
+
const DEFAULT_ORIGIN = 'http://localhost:8787';
|
|
11
|
+
const DEFAULT_PLACEHOLDER_KEY = 'anyray-placeholder';
|
|
12
|
+
/** Strip a trailing slash and any trailing `/v1` so we have a clean origin. */
|
|
13
|
+
export const normalizeOrigin = (raw) => {
|
|
14
|
+
let origin = raw.trim().replace(/\/+$/, '');
|
|
15
|
+
origin = origin.replace(/\/v1$/, '');
|
|
16
|
+
return origin;
|
|
17
|
+
};
|
|
18
|
+
/** A flag value, else an env fallback, else undefined — trimmed, never empty. */
|
|
19
|
+
const pick = (flag, envVar) => flag?.trim() || process.env[envVar]?.trim() || undefined;
|
|
20
|
+
/** Resolve the gateway origin (flag → env → default), validated as an http(s) URL. */
|
|
21
|
+
export const resolveOrigin = (origin) => {
|
|
22
|
+
const resolved = normalizeOrigin(origin || process.env.ANYRAY_GATEWAY_URL || DEFAULT_ORIGIN);
|
|
23
|
+
let parsed;
|
|
24
|
+
try {
|
|
25
|
+
parsed = new URL(resolved);
|
|
26
|
+
}
|
|
27
|
+
catch {
|
|
28
|
+
throw new Error(`invalid gateway URL: "${resolved}" (expected e.g. http://localhost:8787)`);
|
|
29
|
+
}
|
|
30
|
+
if (parsed.protocol !== 'http:' && parsed.protocol !== 'https:') {
|
|
31
|
+
throw new Error(`invalid gateway URL: "${resolved}" — must start with http:// or https://`);
|
|
32
|
+
}
|
|
33
|
+
return resolved;
|
|
34
|
+
};
|
|
35
|
+
export const resolveTarget = (input = {}) => {
|
|
36
|
+
const origin = resolveOrigin(input.origin);
|
|
37
|
+
const placeholderKey = input.placeholderKey?.trim() || DEFAULT_PLACEHOLDER_KEY;
|
|
38
|
+
const clientKey = input.clientKey?.trim() || process.env.ANYRAY_CLIENT_KEY?.trim() || undefined;
|
|
39
|
+
const metadata = {
|
|
40
|
+
user: input.user?.trim() || undefined,
|
|
41
|
+
team: input.team?.trim() || undefined,
|
|
42
|
+
intent: pick(input.intent, 'ANYRAY_METADATA_INTENT'),
|
|
43
|
+
intentLabel: pick(input.intentLabel, 'ANYRAY_METADATA_INTENT_LABEL'),
|
|
44
|
+
session: pick(input.session, 'ANYRAY_METADATA_SESSION'),
|
|
45
|
+
};
|
|
46
|
+
return {
|
|
47
|
+
origin,
|
|
48
|
+
anthropicBaseUrl: origin,
|
|
49
|
+
openaiBaseUrl: `${origin}/v1`,
|
|
50
|
+
placeholderKey,
|
|
51
|
+
clientKey,
|
|
52
|
+
authMode: input.subscription ? 'subscription' : 'placeholder',
|
|
53
|
+
metadata,
|
|
54
|
+
};
|
|
55
|
+
};
|
|
56
|
+
//# sourceMappingURL=target.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"target.js","sourceRoot":"","sources":["../src/target.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAIH,MAAM,cAAc,GAAG,uBAAuB,CAAC;AAC/C,MAAM,uBAAuB,GAAG,oBAAoB,CAAC;AAErD,+EAA+E;AAC/E,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,GAAW,EAAU,EAAE;IACrD,IAAI,MAAM,GAAG,GAAG,CAAC,IAAI,EAAE,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IAC5C,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;IACrC,OAAO,MAAM,CAAC;AAChB,CAAC,CAAC;AAeF,iFAAiF;AACjF,MAAM,IAAI,GAAG,CAAC,IAAwB,EAAE,MAAc,EAAsB,EAAE,CAC5E,IAAI,EAAE,IAAI,EAAE,IAAI,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,IAAI,SAAS,CAAC;AAE3D,sFAAsF;AACtF,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,MAAe,EAAU,EAAE;IACvD,MAAM,QAAQ,GAAG,eAAe,CAC9B,MAAM,IAAI,OAAO,CAAC,GAAG,CAAC,kBAAkB,IAAI,cAAc,CAC3D,CAAC;IACF,IAAI,MAAW,CAAC;IAChB,IAAI,CAAC;QACH,MAAM,GAAG,IAAI,GAAG,CAAC,QAAQ,CAAC,CAAC;IAC7B,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,KAAK,CACb,yBAAyB,QAAQ,yCAAyC,CAC3E,CAAC;IACJ,CAAC;IACD,IAAI,MAAM,CAAC,QAAQ,KAAK,OAAO,IAAI,MAAM,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;QAChE,MAAM,IAAI,KAAK,CACb,yBAAyB,QAAQ,yCAAyC,CAC3E,CAAC;IACJ,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,QAAqB,EAAE,EAAiB,EAAE;IACtE,MAAM,MAAM,GAAG,aAAa,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IAC3C,MAAM,cAAc,GAClB,KAAK,CAAC,cAAc,EAAE,IAAI,EAAE,IAAI,uBAAuB,CAAC;IAC1D,MAAM,SAAS,GACb,KAAK,CAAC,SAAS,EAAE,IAAI,EAAE,IAAI,OAAO,CAAC,GAAG,CAAC,iBAAiB,EAAE,IAAI,EAAE,IAAI,SAAS,CAAC;IAEhF,MAAM,QAAQ,GAAwB;QACpC,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,SAAS;QACrC,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,SAAS;QACrC,MAAM,EAAE,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,wBAAwB,CAAC;QACpD,WAAW,EAAE,IAAI,CAAC,KAAK,CAAC,WAAW,EAAE,8BAA8B,CAAC;QACpE,OAAO,EAAE,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,yBAAyB,CAAC;KACxD,CAAC;IAEF,OAAO;QACL,MAAM;QACN,gBAAgB,EAAE,MAAM;QACxB,aAAa,EAAE,GAAG,MAAM,KAAK;QAC7B,cAAc;QACd,SAAS;QACT,QAAQ,EAAE,KAAK,CAAC,YAAY,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,aAAa;QAC7D,QAAQ;KACT,CAAC;AACJ,CAAC,CAAC"}
|