anyray-connect 0.2.0 → 0.5.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 +5 -0
- package/dist/cli.js +242 -65
- package/dist/cli.js.map +1 -1
- package/dist/commands/doctor.js +86 -0
- package/dist/commands/doctor.js.map +1 -0
- package/dist/commands/hook.js +233 -0
- package/dist/commands/hook.js.map +1 -0
- package/dist/commands/shared.js +83 -0
- package/dist/commands/shared.js.map +1 -0
- package/dist/commands/status.js +71 -0
- package/dist/commands/status.js.map +1 -0
- package/dist/commands/sync.js +87 -0
- package/dist/commands/sync.js.map +1 -0
- package/dist/target.js +11 -1
- package/dist/target.js.map +1 -1
- package/dist/tools/claudeCode.js +88 -2
- package/dist/tools/claudeCode.js.map +1 -1
- package/dist/tools/codex.js +3 -3
- package/dist/tools/codex.js.map +1 -1
- package/dist/tools/shellEnv.js +40 -8
- package/dist/tools/shellEnv.js.map +1 -1
- package/dist/types.js +13 -0
- package/dist/types.js.map +1 -1
- package/dist/util/persist.js +32 -7
- package/dist/util/persist.js.map +1 -1
- package/dist/util/policySync.js +143 -0
- package/dist/util/policySync.js.map +1 -0
- package/dist/util/savings.js +71 -0
- package/dist/util/savings.js.map +1 -0
- package/dist/util/seatState.js +79 -0
- package/dist/util/seatState.js.map +1 -0
- package/dist/util/setupLink.js +5 -1
- package/dist/util/setupLink.js.map +1 -1
- package/dist/util/trimOutput.js +120 -0
- package/dist/util/trimOutput.js.map +1 -0
- package/dist/util/verify.js +192 -0
- package/dist/util/verify.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Seat-state detection — does this machine already have a subscription sign-in
|
|
3
|
+
* for each provider family? This is what makes the one-command flow autonomous:
|
|
4
|
+
* `authMode: 'auto'` reads it and rides the dev's own seat when present, falling
|
|
5
|
+
* back to the org key when not. No human input, no flags.
|
|
6
|
+
*
|
|
7
|
+
* Best-effort and SILENT: every probe is wrapped so a missing file, a denied
|
|
8
|
+
* keychain, or a slow `security` call resolves to "not signed in" rather than
|
|
9
|
+
* throwing — a detection miss just means we fall back to the org key, which
|
|
10
|
+
* always works. We read only whether a credential EXISTS, never its value: a
|
|
11
|
+
* keychain *metadata* lookup (no `-w`) doesn't prompt and doesn't expose the
|
|
12
|
+
* secret, and credential files are probed with `fileExists`, not read. The seat
|
|
13
|
+
* token itself stays in the tool; connect never holds it.
|
|
14
|
+
*
|
|
15
|
+
* Signals (macOS-first, since that's where coding tools mostly run):
|
|
16
|
+
* - Anthropic (Claude Code): `CLAUDE_CODE_OAUTH_TOKEN` env, `~/.claude/.oauth_token`,
|
|
17
|
+
* `~/.claude/.credentials.json` (Linux), or the macOS Keychain item
|
|
18
|
+
* `Claude Code-credentials`.
|
|
19
|
+
* - OpenAI (Codex): `~/.codex/auth.json` carrying a ChatGPT `tokens.access_token`
|
|
20
|
+
* (an API-key-only `auth.json` is NOT a subscription seat).
|
|
21
|
+
*/
|
|
22
|
+
import { homedir, platform } from 'node:os';
|
|
23
|
+
import { join } from 'node:path';
|
|
24
|
+
import { execFile } from 'node:child_process';
|
|
25
|
+
import { readFile } from 'node:fs/promises';
|
|
26
|
+
import { fileExists } from './jsonFile.js';
|
|
27
|
+
const KEYCHAIN_TIMEOUT_MS = 3000;
|
|
28
|
+
const CLAUDE_KEYCHAIN_SERVICE = 'Claude Code-credentials';
|
|
29
|
+
/** True if a Keychain generic-password item exists for `service`. Metadata-only
|
|
30
|
+
* lookup (no `-w`) so macOS does NOT prompt and the secret is never read. */
|
|
31
|
+
const keychainHasItem = (service) => new Promise((resolve) => {
|
|
32
|
+
try {
|
|
33
|
+
const child = execFile('security', ['find-generic-password', '-s', service], { timeout: KEYCHAIN_TIMEOUT_MS }, (err) => resolve(!err));
|
|
34
|
+
child.on('error', () => resolve(false));
|
|
35
|
+
}
|
|
36
|
+
catch {
|
|
37
|
+
resolve(false);
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
/** Detect an Anthropic subscription seat (Claude Code). */
|
|
41
|
+
export const detectAnthropicSeat = async () => {
|
|
42
|
+
if (process.env.CLAUDE_CODE_OAUTH_TOKEN?.trim())
|
|
43
|
+
return true;
|
|
44
|
+
const claudeDir = join(homedir(), '.claude');
|
|
45
|
+
if (await fileExists(join(claudeDir, '.oauth_token')))
|
|
46
|
+
return true;
|
|
47
|
+
if (await fileExists(join(claudeDir, '.credentials.json')))
|
|
48
|
+
return true;
|
|
49
|
+
if (platform() === 'darwin' && (await keychainHasItem(CLAUDE_KEYCHAIN_SERVICE))) {
|
|
50
|
+
return true;
|
|
51
|
+
}
|
|
52
|
+
return false;
|
|
53
|
+
};
|
|
54
|
+
/** Detect a ChatGPT subscription seat (Codex) — a `tokens.access_token` in
|
|
55
|
+
* `~/.codex/auth.json`. An API-key-only file is a keyed login, not a seat. */
|
|
56
|
+
export const detectOpenAiSeat = async () => {
|
|
57
|
+
const authPath = join(process.env.CODEX_HOME?.trim() || join(homedir(), '.codex'), 'auth.json');
|
|
58
|
+
if (!(await fileExists(authPath)))
|
|
59
|
+
return false;
|
|
60
|
+
try {
|
|
61
|
+
const parsed = JSON.parse(await readFile(authPath, 'utf-8'));
|
|
62
|
+
return typeof parsed.tokens?.access_token === 'string' &&
|
|
63
|
+
parsed.tokens.access_token.trim() !== ''
|
|
64
|
+
? true
|
|
65
|
+
: false;
|
|
66
|
+
}
|
|
67
|
+
catch {
|
|
68
|
+
return false;
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
/** Detect seat sign-in for every provider family in parallel. Never throws. */
|
|
72
|
+
export const detectSeatState = async () => {
|
|
73
|
+
const [anthropic, openai] = await Promise.all([
|
|
74
|
+
detectAnthropicSeat(),
|
|
75
|
+
detectOpenAiSeat(),
|
|
76
|
+
]);
|
|
77
|
+
return { anthropic, openai };
|
|
78
|
+
};
|
|
79
|
+
//# sourceMappingURL=seatState.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"seatState.js","sourceRoot":"","sources":["../../src/util/seatState.ts"],"names":[],"mappings":"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"}
|
package/dist/util/setupLink.js
CHANGED
|
@@ -74,6 +74,10 @@ export const resolveSetupLink = async (link, opts = {}) => {
|
|
|
74
74
|
if (!gatewayUrl) {
|
|
75
75
|
throw new Error('this setup link has no gateway configured yet — ask your admin to add a gateway in the Anyray console, then re-run.');
|
|
76
76
|
}
|
|
77
|
-
return {
|
|
77
|
+
return {
|
|
78
|
+
gatewayUrl,
|
|
79
|
+
org: optionalString(body.org),
|
|
80
|
+
seatMode: body.seatMode === true,
|
|
81
|
+
};
|
|
78
82
|
};
|
|
79
83
|
//# sourceMappingURL=setupLink.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"setupLink.js","sourceRoot":"","sources":["../../src/util/setupLink.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,MAAM,qBAAqB,GAAG,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"setupLink.js","sourceRoot":"","sources":["../../src/util/setupLink.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Local, deterministic trimming of oversized tool outputs.
|
|
3
|
+
*
|
|
4
|
+
* This is the cache-SAFE half of Anyray's optimization: it runs inside Claude
|
|
5
|
+
* Code (a `PostToolUse` hook) and caps a bulky tool result the moment it's
|
|
6
|
+
* produced — BEFORE it enters the conversation and gets a `cache_control`
|
|
7
|
+
* prefix. Trimming here keeps the cached prefix coherent (the trimmed text is
|
|
8
|
+
* what gets cached and re-sent every later turn), unlike a gateway rewrite that
|
|
9
|
+
* mutates already-cached content and busts Anthropic's prefix cache.
|
|
10
|
+
*
|
|
11
|
+
* The trim is lossy-but-bounded by design: we keep the head (orientation) and
|
|
12
|
+
* the tail (the result/conclusion — where the signal usually is for logs, shell
|
|
13
|
+
* output, and search dumps) and elide the middle behind a CONTENT-FREE marker.
|
|
14
|
+
* No network, no model call, no stash — a `connect` hook can't reach the
|
|
15
|
+
* gateway's `/v1/retrieve`, so this trades reversibility for cache-safety and
|
|
16
|
+
* zero data exposure. Char-based (a ~4 chars/token heuristic) to stay
|
|
17
|
+
* dependency-free and fast on the hot path.
|
|
18
|
+
*
|
|
19
|
+
* PRIVACY: nothing here logs or transmits the content; the marker carries only
|
|
20
|
+
* counts. The trimmed text is handed straight back to Claude Code.
|
|
21
|
+
*/
|
|
22
|
+
/** ~4 chars per token — the standard rough heuristic; good enough for a metric. */
|
|
23
|
+
const CHARS_PER_TOKEN = 4;
|
|
24
|
+
export const DEFAULT_TRIM = {
|
|
25
|
+
maxChars: 12_000,
|
|
26
|
+
headChars: 6_000,
|
|
27
|
+
tailChars: 4_000,
|
|
28
|
+
};
|
|
29
|
+
const passthrough = (text) => ({
|
|
30
|
+
text,
|
|
31
|
+
trimmed: false,
|
|
32
|
+
originalChars: text.length,
|
|
33
|
+
trimmedChars: text.length,
|
|
34
|
+
estTokensSaved: 0,
|
|
35
|
+
});
|
|
36
|
+
/**
|
|
37
|
+
* Trim a single string. Keeps `headChars` + a content-free marker + `tailChars`
|
|
38
|
+
* when the input exceeds `maxChars`; otherwise returns it untouched. Clamps the
|
|
39
|
+
* head/tail budget so the result is always strictly shorter than the original.
|
|
40
|
+
*/
|
|
41
|
+
export const trimText = (input, opts = {}) => {
|
|
42
|
+
if (typeof input !== 'string')
|
|
43
|
+
return passthrough(String(input ?? ''));
|
|
44
|
+
const maxChars = Math.max(1, opts.maxChars ?? DEFAULT_TRIM.maxChars);
|
|
45
|
+
if (input.length <= maxChars)
|
|
46
|
+
return passthrough(input);
|
|
47
|
+
let headChars = Math.max(0, opts.headChars ?? DEFAULT_TRIM.headChars);
|
|
48
|
+
let tailChars = Math.max(0, opts.tailChars ?? DEFAULT_TRIM.tailChars);
|
|
49
|
+
// Never keep so much that we fail to shrink: cap the kept budget under maxChars
|
|
50
|
+
// (leave room for the marker), preferring to shave the head first.
|
|
51
|
+
const keepBudget = maxChars - 1;
|
|
52
|
+
if (headChars + tailChars > keepBudget) {
|
|
53
|
+
tailChars = Math.min(tailChars, keepBudget);
|
|
54
|
+
headChars = Math.max(0, keepBudget - tailChars);
|
|
55
|
+
}
|
|
56
|
+
const head = input.slice(0, headChars);
|
|
57
|
+
const tail = tailChars > 0 ? input.slice(input.length - tailChars) : '';
|
|
58
|
+
const elided = input.length - head.length - tail.length;
|
|
59
|
+
const estTokensSaved = Math.round(elided / CHARS_PER_TOKEN);
|
|
60
|
+
const marker = `\n\n…[anyray-hook trimmed ${elided} chars (~${estTokensSaved} tokens) — full output elided locally, cache-safe]…\n\n`;
|
|
61
|
+
const text = head + marker + tail;
|
|
62
|
+
// Degenerate guard: if the marker made it longer (tiny maxChars), don't trim.
|
|
63
|
+
if (text.length >= input.length)
|
|
64
|
+
return passthrough(input);
|
|
65
|
+
return {
|
|
66
|
+
text,
|
|
67
|
+
trimmed: true,
|
|
68
|
+
originalChars: input.length,
|
|
69
|
+
trimmedChars: text.length,
|
|
70
|
+
estTokensSaved,
|
|
71
|
+
};
|
|
72
|
+
};
|
|
73
|
+
/** Keys whose string value is treated as the trimmable body of a tool output. */
|
|
74
|
+
const BODY_KEYS = ['stdout', 'content', 'output', 'text', 'result'];
|
|
75
|
+
/**
|
|
76
|
+
* Locate the trimmable text inside a tool output whose shape varies by tool
|
|
77
|
+
* (Bash `{stdout,stderr,exit_code}`, Read `{content}`, a bare string for some
|
|
78
|
+
* tools/MCP, …). Returns the body string plus a `rebuild` that puts a
|
|
79
|
+
* (possibly optimized) string back in the SAME field, preserving the structure
|
|
80
|
+
* Claude Code expects. Defensive about field names: first known body key, else
|
|
81
|
+
* the longest string-valued field. Returns null when there's nothing to trim.
|
|
82
|
+
*/
|
|
83
|
+
export const extractToolOutputBody = (output) => {
|
|
84
|
+
if (typeof output === 'string') {
|
|
85
|
+
return { body: output, rebuild: (s) => s };
|
|
86
|
+
}
|
|
87
|
+
if (!output || typeof output !== 'object' || Array.isArray(output)) {
|
|
88
|
+
return null;
|
|
89
|
+
}
|
|
90
|
+
const obj = output;
|
|
91
|
+
let key = BODY_KEYS.find((k) => typeof obj[k] === 'string');
|
|
92
|
+
if (!key) {
|
|
93
|
+
let bestLen = -1;
|
|
94
|
+
for (const [k, v] of Object.entries(obj)) {
|
|
95
|
+
if (typeof v === 'string' && v.length > bestLen) {
|
|
96
|
+
key = k;
|
|
97
|
+
bestLen = v.length;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
if (!key)
|
|
102
|
+
return null;
|
|
103
|
+
const field = key;
|
|
104
|
+
return { body: obj[field], rebuild: (s) => ({ ...obj, [field]: s }) };
|
|
105
|
+
};
|
|
106
|
+
/**
|
|
107
|
+
* Trim the body of a tool output locally (the fail-open fallback when the
|
|
108
|
+
* gateway/optimizer is unreachable — the smart strategies run server-side, see
|
|
109
|
+
* commands/hook.ts). Returns the rebuilt value plus the trim metrics.
|
|
110
|
+
*/
|
|
111
|
+
export const trimToolOutput = (output, opts = {}) => {
|
|
112
|
+
const found = extractToolOutputBody(output);
|
|
113
|
+
if (!found)
|
|
114
|
+
return { value: output, result: passthrough('') };
|
|
115
|
+
const result = trimText(found.body, opts);
|
|
116
|
+
if (!result.trimmed)
|
|
117
|
+
return { value: output, result };
|
|
118
|
+
return { value: found.rebuild(result.text), result };
|
|
119
|
+
};
|
|
120
|
+
//# sourceMappingURL=trimOutput.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"trimOutput.js","sourceRoot":"","sources":["../../src/util/trimOutput.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Post-apply smoke test — confirm the connection actually works, with the same
|
|
3
|
+
* shape of request the configured tool will send, and turn any failure into one
|
|
4
|
+
* specific next step instead of a cryptic 4xx on the dev's first real request.
|
|
5
|
+
*
|
|
6
|
+
* Two paths, because the two modes authenticate differently:
|
|
7
|
+
* - org key (placeholder): the gateway key is the bearer; we probe the
|
|
8
|
+
* OpenAI-compatible `/v1/chat/completions`. A 2xx means the gateway accepted
|
|
9
|
+
* the key and routed upstream end-to-end.
|
|
10
|
+
* - seat (subscription): the seat OAuth token lives in the *tool*, not connect,
|
|
11
|
+
* so we DON'T need (or want) the secret. We send a sentinel bearer with the
|
|
12
|
+
* pass-through headers to `/v1/messages` and read where it lands: if the
|
|
13
|
+
* gateway forwards it to Anthropic (which rejects the sentinel as an invalid
|
|
14
|
+
* bearer), pass-through is wired and the dev's real seat will work; if it
|
|
15
|
+
* comes back a Bedrock/org-provider error, pass-through ISN'T honored. This
|
|
16
|
+
* verifies the part connect owns — the gateway routing — without a keychain
|
|
17
|
+
* prompt and without ever false-alarming on a stale token (the tool itself
|
|
18
|
+
* tells the dev to re-`/login` if their seat lapsed).
|
|
19
|
+
*
|
|
20
|
+
* PRIVACY: probe bodies are fixed synthetic "ping"s — no user content; the
|
|
21
|
+
* sentinel is a literal non-secret string. Responses are read only to classify
|
|
22
|
+
* status + error type, never logged as content.
|
|
23
|
+
*/
|
|
24
|
+
import { effectiveSubscription, metadataHeaderValue } from '../types.js';
|
|
25
|
+
const VERIFY_TIMEOUT_MS = 12_000;
|
|
26
|
+
/** A deliberately-invalid bearer for the seat-wiring probe. Not a secret; its
|
|
27
|
+
* only job is to be rejected by whatever upstream the gateway forwards it to,
|
|
28
|
+
* so we can tell Anthropic-passthrough from org-provider routing. */
|
|
29
|
+
const WIRING_SENTINEL = 'anyray-wiring-probe-not-a-real-token';
|
|
30
|
+
/** Smallest valid OpenAI-style body; `anyray-default` lets gateway routing pick
|
|
31
|
+
* the real model/provider. `max_tokens: 1` keeps the probe a fraction of a cent. */
|
|
32
|
+
const PLACEHOLDER_PROBE_BODY = {
|
|
33
|
+
model: 'anyray-default',
|
|
34
|
+
messages: [{ role: 'user', content: 'ping' }],
|
|
35
|
+
max_tokens: 1,
|
|
36
|
+
};
|
|
37
|
+
/** Smallest valid Anthropic-style body for the seat-wiring probe. */
|
|
38
|
+
const WIRING_PROBE_BODY = {
|
|
39
|
+
model: 'claude-3-5-haiku-20241022',
|
|
40
|
+
max_tokens: 1,
|
|
41
|
+
messages: [{ role: 'user', content: 'ping' }],
|
|
42
|
+
};
|
|
43
|
+
/** A short, content-free snippet of an error body for the status line. */
|
|
44
|
+
const snippet = (bodyText) => {
|
|
45
|
+
const oneLine = bodyText.replace(/\s+/g, ' ').trim();
|
|
46
|
+
return oneLine.length > 160 ? `${oneLine.slice(0, 157)}…` : oneLine;
|
|
47
|
+
};
|
|
48
|
+
/** True when the body looks like the org's Bedrock path answered instead of the
|
|
49
|
+
* intended provider — the tell that pass-through didn't happen. */
|
|
50
|
+
const looksLikeOrgProvider = (bodyText) => {
|
|
51
|
+
const lower = bodyText.toLowerCase();
|
|
52
|
+
return lower.includes('bedrock') || lower.includes('unsupported model');
|
|
53
|
+
};
|
|
54
|
+
/** Classify the org-key probe (OpenAI-compatible completion). */
|
|
55
|
+
export const classifyPlaceholder = (status, bodyText) => {
|
|
56
|
+
if (status >= 200 && status < 300) {
|
|
57
|
+
return {
|
|
58
|
+
kind: 'ok',
|
|
59
|
+
detail: 'gateway served a completion with the org key — traffic flows.',
|
|
60
|
+
remedy: [],
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
if (status === 401 || status === 403) {
|
|
64
|
+
if (looksLikeOrgProvider(bodyText)) {
|
|
65
|
+
return {
|
|
66
|
+
kind: 'routed-elsewhere',
|
|
67
|
+
detail: `gateway routed to the org provider and it rejected the request: ${snippet(bodyText)}`,
|
|
68
|
+
remedy: [
|
|
69
|
+
'The org provider rejected the request — check the gateway’s provider',
|
|
70
|
+
'key/config (e.g. the model is enabled for that account).',
|
|
71
|
+
],
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
return {
|
|
75
|
+
kind: 'key-rejected',
|
|
76
|
+
detail: `gateway rejected the key (HTTP ${status}).`,
|
|
77
|
+
remedy: [
|
|
78
|
+
'The key was refused — the setup link may be expired; ask your admin for a fresh one.',
|
|
79
|
+
],
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
return {
|
|
83
|
+
kind: 'unknown',
|
|
84
|
+
detail: `gateway responded HTTP ${status}: ${snippet(bodyText)}`,
|
|
85
|
+
remedy: [],
|
|
86
|
+
};
|
|
87
|
+
};
|
|
88
|
+
/** Classify the seat-wiring probe (sentinel bearer through the gateway). */
|
|
89
|
+
export const classifySeatWiring = (status, bodyText) => {
|
|
90
|
+
if (looksLikeOrgProvider(bodyText)) {
|
|
91
|
+
return {
|
|
92
|
+
kind: 'routed-elsewhere',
|
|
93
|
+
detail: 'gateway sent the request to the org provider, not your subscription.',
|
|
94
|
+
remedy: [
|
|
95
|
+
'Pass-through isn’t being honored for this gateway — your seat token would',
|
|
96
|
+
'not be used. Check the gateway is current (subscription pass-through support).',
|
|
97
|
+
],
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
const lower = bodyText.toLowerCase();
|
|
101
|
+
// The sentinel reaching Anthropic and being rejected as a bad bearer is the
|
|
102
|
+
// SUCCESS signal: it proves the gateway forwards seat auth to Anthropic, so
|
|
103
|
+
// the dev's real (valid) seat token will be honored.
|
|
104
|
+
if (status === 401 ||
|
|
105
|
+
lower.includes('authentication_error') ||
|
|
106
|
+
lower.includes('invalid bearer') ||
|
|
107
|
+
lower.includes('"provider":"anthropic"')) {
|
|
108
|
+
return {
|
|
109
|
+
kind: 'ok',
|
|
110
|
+
detail: 'gateway passes your sign-in through to Anthropic — your Claude seat will be used.',
|
|
111
|
+
remedy: [],
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
if (status >= 200 && status < 300) {
|
|
115
|
+
return {
|
|
116
|
+
kind: 'ok',
|
|
117
|
+
detail: 'gateway pass-through reached the provider — your seat will be used.',
|
|
118
|
+
remedy: [],
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
return {
|
|
122
|
+
kind: 'unknown',
|
|
123
|
+
detail: `seat-wiring probe got HTTP ${status}: ${snippet(bodyText)}`,
|
|
124
|
+
remedy: [],
|
|
125
|
+
};
|
|
126
|
+
};
|
|
127
|
+
const probe = async (url, headers, body, timeoutMs) => {
|
|
128
|
+
const controller = new AbortController();
|
|
129
|
+
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
130
|
+
try {
|
|
131
|
+
const res = await fetch(url, {
|
|
132
|
+
method: 'POST',
|
|
133
|
+
headers: { 'content-type': 'application/json', ...headers },
|
|
134
|
+
body: JSON.stringify(body),
|
|
135
|
+
signal: controller.signal,
|
|
136
|
+
});
|
|
137
|
+
return { status: res.status, bodyText: await res.text() };
|
|
138
|
+
}
|
|
139
|
+
finally {
|
|
140
|
+
clearTimeout(timer);
|
|
141
|
+
}
|
|
142
|
+
};
|
|
143
|
+
const unreachable = (timeoutMs, error) => {
|
|
144
|
+
const reason = error instanceof Error && error.name === 'AbortError'
|
|
145
|
+
? `no response within ${timeoutMs}ms`
|
|
146
|
+
: error instanceof Error
|
|
147
|
+
? error.message
|
|
148
|
+
: String(error);
|
|
149
|
+
return {
|
|
150
|
+
kind: 'unreachable',
|
|
151
|
+
detail: `could not reach the gateway to verify (${reason}).`,
|
|
152
|
+
remedy: [
|
|
153
|
+
'Your config was still written — re-run the curl below once the gateway is reachable.',
|
|
154
|
+
],
|
|
155
|
+
};
|
|
156
|
+
};
|
|
157
|
+
/**
|
|
158
|
+
* Probe the gateway with the auth the Anthropic-family tool will use and return
|
|
159
|
+
* a classified verdict. Never throws — a transport failure becomes `unreachable`
|
|
160
|
+
* (the config was still written; the dev can re-test by hand). Anthropic is the
|
|
161
|
+
* representative family: its org path and its seat-passthrough path are exactly
|
|
162
|
+
* what this smoke test distinguishes.
|
|
163
|
+
*/
|
|
164
|
+
export const verifyConnection = async (target, opts = {}) => {
|
|
165
|
+
const timeoutMs = opts.timeoutMs ?? VERIFY_TIMEOUT_MS;
|
|
166
|
+
const meta = metadataHeaderValue(target.metadata);
|
|
167
|
+
try {
|
|
168
|
+
if (effectiveSubscription(target, 'anthropic')) {
|
|
169
|
+
const headers = {
|
|
170
|
+
Authorization: `Bearer ${WIRING_SENTINEL}`,
|
|
171
|
+
'anthropic-version': '2023-06-01',
|
|
172
|
+
'anthropic-beta': 'oauth-2025-04-20',
|
|
173
|
+
'x-anyray-auth-mode': 'passthrough',
|
|
174
|
+
'x-anyray-provider': 'anthropic',
|
|
175
|
+
};
|
|
176
|
+
if (meta)
|
|
177
|
+
headers['x-anyray-metadata'] = meta;
|
|
178
|
+
const { status, bodyText } = await probe(`${target.anthropicBaseUrl}/v1/messages`, headers, WIRING_PROBE_BODY, timeoutMs);
|
|
179
|
+
return classifySeatWiring(status, bodyText);
|
|
180
|
+
}
|
|
181
|
+
const key = target.clientKey ?? target.placeholderKey;
|
|
182
|
+
const headers = { Authorization: `Bearer ${key}` };
|
|
183
|
+
if (meta)
|
|
184
|
+
headers['x-anyray-metadata'] = meta;
|
|
185
|
+
const { status, bodyText } = await probe(`${target.openaiBaseUrl}/chat/completions`, headers, PLACEHOLDER_PROBE_BODY, timeoutMs);
|
|
186
|
+
return classifyPlaceholder(status, bodyText);
|
|
187
|
+
}
|
|
188
|
+
catch (error) {
|
|
189
|
+
return unreachable(timeoutMs, error);
|
|
190
|
+
}
|
|
191
|
+
};
|
|
192
|
+
//# sourceMappingURL=verify.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"verify.js","sourceRoot":"","sources":["../../src/util/verify.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "anyray-connect",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"description": "Anyray connect — points local coding tools (Claude Code, Cursor, Windsurf, SDKs) at the Anyray gateway by writing their base URL + a placeholder key. The gateway stays the brain; this is just the on-ramp.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|