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 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
@@ -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"}