@jacobbd/relay-ai 0.9.8 → 0.10.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/dist/{chunk-WIXM2H2D.js → chunk-2NXLK3O6.js} +173 -19
- package/dist/chunk-2NXLK3O6.js.map +1 -0
- package/dist/cli.js +66 -12
- package/dist/cli.js.map +1 -1
- package/dist/core/index.d.ts +7 -0
- package/dist/core/index.js +83 -4
- package/dist/core/index.js.map +1 -1
- package/dist/{ui-command-JIRLAHM6.js → ui-command-6ZMM5K5K.js} +2 -2
- package/package.json +1 -1
- package/dist/chunk-WIXM2H2D.js.map +0 -1
- /package/dist/{ui-command-JIRLAHM6.js.map → ui-command-6ZMM5K5K.js.map} +0 -0
package/dist/core/index.d.ts
CHANGED
|
@@ -16,6 +16,13 @@ type RelayCoreErrorCode = 'INVALID_ROUTE_ID' | 'ROUTE_NOT_FOUND' | 'PROVIDER_DIS
|
|
|
16
16
|
*/
|
|
17
17
|
type RelayReasoningLevel = 'off' | 'none' | 'minimal' | 'low' | 'medium' | 'high' | 'xhigh' | 'max';
|
|
18
18
|
interface CreateRelayModelOptions {
|
|
19
|
+
/**
|
|
20
|
+
* Optional stable conversation identifier for OpenCode Go. Relay sends this
|
|
21
|
+
* as `x-opencode-session` on every upstream model call for the returned model.
|
|
22
|
+
* The value is treated as opaque and bounded to OpenCode's 256-character
|
|
23
|
+
* header limit. Per-call `headers` supplied to the AI SDK take precedence.
|
|
24
|
+
*/
|
|
25
|
+
sessionId?: string;
|
|
19
26
|
/**
|
|
20
27
|
* Optional sanitized transport diagnostics. Messages contain event types,
|
|
21
28
|
* field names, counts, and lengths — never credentials, prompts, or bodies.
|
package/dist/core/index.js
CHANGED
|
@@ -50,7 +50,7 @@ import { join as join2 } from "path";
|
|
|
50
50
|
// package.json
|
|
51
51
|
var package_default = {
|
|
52
52
|
name: "@jacobbd/relay-ai",
|
|
53
|
-
version: "0.
|
|
53
|
+
version: "0.10.0",
|
|
54
54
|
publishConfig: {
|
|
55
55
|
access: "public"
|
|
56
56
|
},
|
|
@@ -2204,6 +2204,55 @@ function isRelayCoreError(err) {
|
|
|
2204
2204
|
return err instanceof RelayCoreError;
|
|
2205
2205
|
}
|
|
2206
2206
|
|
|
2207
|
+
// src/opencode-session.ts
|
|
2208
|
+
import { randomUUID as randomUUID2 } from "crypto";
|
|
2209
|
+
var OPENCODE_SESSION_HEADER = "x-opencode-session";
|
|
2210
|
+
var MAX_OPENCODE_SESSION_LENGTH = 256;
|
|
2211
|
+
var RELAY_USER_AGENT = `relay-ai/${VERSION}`;
|
|
2212
|
+
function sanitizeSessionId(value) {
|
|
2213
|
+
if (typeof value !== "string") return void 0;
|
|
2214
|
+
const normalized = value.trim();
|
|
2215
|
+
if (!normalized || normalized.length > MAX_OPENCODE_SESSION_LENGTH) return void 0;
|
|
2216
|
+
if (/[\u0000-\u001f\u007f\r\n]/.test(normalized)) return void 0;
|
|
2217
|
+
return normalized;
|
|
2218
|
+
}
|
|
2219
|
+
function isOpenCodeGoEndpoint(providerId, endpoint) {
|
|
2220
|
+
const id = providerId?.trim().toLowerCase();
|
|
2221
|
+
if (id === "go" || id === "opencode-go") return true;
|
|
2222
|
+
if (!endpoint) return false;
|
|
2223
|
+
try {
|
|
2224
|
+
const url = new URL(endpoint);
|
|
2225
|
+
if (url.hostname.toLowerCase() !== "opencode.ai") return false;
|
|
2226
|
+
return url.pathname.split("/").some((segment) => segment.toLowerCase() === "go");
|
|
2227
|
+
} catch {
|
|
2228
|
+
return false;
|
|
2229
|
+
}
|
|
2230
|
+
}
|
|
2231
|
+
function mergeHeaders(base, overrides) {
|
|
2232
|
+
const result = {};
|
|
2233
|
+
for (const [key, value] of Object.entries(base ?? {})) {
|
|
2234
|
+
if (typeof value === "string") result[key] = value;
|
|
2235
|
+
}
|
|
2236
|
+
for (const [key, value] of Object.entries(overrides ?? {})) {
|
|
2237
|
+
for (const existing of Object.keys(result)) {
|
|
2238
|
+
if (existing.toLowerCase() === key.toLowerCase()) delete result[existing];
|
|
2239
|
+
}
|
|
2240
|
+
result[key] = value;
|
|
2241
|
+
}
|
|
2242
|
+
return result;
|
|
2243
|
+
}
|
|
2244
|
+
function openCodeGoHeaders(providerId, endpoint, sessionId, baseHeaders, options) {
|
|
2245
|
+
if (!isOpenCodeGoEndpoint(providerId, endpoint)) return void 0;
|
|
2246
|
+
let normalizedSessionId = sanitizeSessionId(sessionId);
|
|
2247
|
+
if (!normalizedSessionId && (options?.generateFallbackSession ?? true)) {
|
|
2248
|
+
normalizedSessionId = `relay-${randomUUID2()}`;
|
|
2249
|
+
}
|
|
2250
|
+
return mergeHeaders(baseHeaders, {
|
|
2251
|
+
"User-Agent": RELAY_USER_AGENT,
|
|
2252
|
+
...normalizedSessionId ? { [OPENCODE_SESSION_HEADER]: normalizedSessionId } : {}
|
|
2253
|
+
});
|
|
2254
|
+
}
|
|
2255
|
+
|
|
2207
2256
|
// src/core/reasoning.ts
|
|
2208
2257
|
var RELAY_REASONING_LEVELS = [
|
|
2209
2258
|
"off",
|
|
@@ -2277,6 +2326,22 @@ async function withReasoningProviderOptions(model, providerOptions) {
|
|
|
2277
2326
|
}
|
|
2278
2327
|
});
|
|
2279
2328
|
}
|
|
2329
|
+
async function withRequestHeaders(model, headers) {
|
|
2330
|
+
const { wrapLanguageModel: wrapLanguageModel2 } = await import("ai");
|
|
2331
|
+
return wrapLanguageModel2({
|
|
2332
|
+
model,
|
|
2333
|
+
middleware: {
|
|
2334
|
+
specificationVersion: "v3",
|
|
2335
|
+
transformParams: async ({ params }) => ({
|
|
2336
|
+
...params,
|
|
2337
|
+
headers: mergeHeaders(
|
|
2338
|
+
headers,
|
|
2339
|
+
params.headers
|
|
2340
|
+
)
|
|
2341
|
+
})
|
|
2342
|
+
}
|
|
2343
|
+
});
|
|
2344
|
+
}
|
|
2280
2345
|
|
|
2281
2346
|
// src/core/route-id.ts
|
|
2282
2347
|
var SEPARATOR = "::";
|
|
@@ -3509,7 +3574,7 @@ function providerRefreshToken(providerId, authType, authRef) {
|
|
|
3509
3574
|
}
|
|
3510
3575
|
|
|
3511
3576
|
// src/core/antigravity-model.ts
|
|
3512
|
-
import { randomUUID as
|
|
3577
|
+
import { randomUUID as randomUUID3 } from "crypto";
|
|
3513
3578
|
var CLOUD_CODE_BASES = ANTIGRAVITY_BASE_URLS.map((base) => base.replace(/\/+$/, ""));
|
|
3514
3579
|
var CLOUD_CODE_BASE = CLOUD_CODE_BASES[0];
|
|
3515
3580
|
var STREAM_URLS = CLOUD_CODE_BASES.map((base) => `${base}/${ANTIGRAVITY_API_VERSION}:streamGenerateContent?alt=sse`);
|
|
@@ -3596,7 +3661,7 @@ function createCloudCodeFetch(options, fetchImpl) {
|
|
|
3596
3661
|
const geminiBody = await readJsonBody(input, init);
|
|
3597
3662
|
const envelope = {
|
|
3598
3663
|
project: options.projectId,
|
|
3599
|
-
requestId:
|
|
3664
|
+
requestId: randomUUID3(),
|
|
3600
3665
|
model: options.modelId,
|
|
3601
3666
|
userAgent: ANTIGRAVITY_USER_AGENT,
|
|
3602
3667
|
requestType: "agent",
|
|
@@ -3791,7 +3856,21 @@ async function createRelayModel(routeId, options) {
|
|
|
3791
3856
|
const registry = loadCoreRegistry();
|
|
3792
3857
|
const { provider, model } = findRoute(registry, providerId, modelId, routeId);
|
|
3793
3858
|
const reasoningOptions = options?.reasoning === void 0 ? void 0 : resolveReasoningProviderOptions(options.reasoning, provider, model, routeId);
|
|
3794
|
-
const
|
|
3859
|
+
const transportHeaders = openCodeGoHeaders(
|
|
3860
|
+
provider.id,
|
|
3861
|
+
model.apiUrl ?? provider.api.url,
|
|
3862
|
+
options?.sessionId,
|
|
3863
|
+
provider.api.headers,
|
|
3864
|
+
// The returned model may be reused across conversations, so never fabricate a
|
|
3865
|
+
// session here — a baked-in id would blend histories. The host passes sessionId.
|
|
3866
|
+
{ generateFallbackSession: false }
|
|
3867
|
+
);
|
|
3868
|
+
const finish = async (built) => {
|
|
3869
|
+
let finished = built;
|
|
3870
|
+
if (reasoningOptions) finished = await withReasoningProviderOptions(finished, reasoningOptions);
|
|
3871
|
+
if (transportHeaders) finished = await withRequestHeaders(finished, transportHeaders);
|
|
3872
|
+
return finished;
|
|
3873
|
+
};
|
|
3795
3874
|
if (isAntigravityCloudCodeRoute(provider, model)) {
|
|
3796
3875
|
const apiKey2 = await resolveCredential(provider, routeId);
|
|
3797
3876
|
const providerData2 = await resolveProviderOAuthProviderData(provider.authRef);
|