@jacobbd/relay-ai 0.9.8 → 0.10.1
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-P4IS6537.js → chunk-TFMHIGRX.js} +4 -2
- package/dist/{chunk-P4IS6537.js.map → chunk-TFMHIGRX.js.map} +1 -1
- package/dist/{chunk-WIXM2H2D.js → chunk-YYI6EJ2X.js} +174 -20
- package/dist/chunk-YYI6EJ2X.js.map +1 -0
- package/dist/cli.js +67 -13
- package/dist/cli.js.map +1 -1
- package/dist/core/index.d.ts +7 -0
- package/dist/core/index.js +86 -5
- package/dist/core/index.js.map +1 -1
- package/dist/{provider-templates-7M24FAAI.js → provider-templates-JWT6U5B7.js} +2 -2
- package/dist/{ui-command-JIRLAHM6.js → ui-command-LZWTWTQ6.js} +4 -4
- package/package.json +1 -1
- package/dist/chunk-WIXM2H2D.js.map +0 -1
- /package/dist/{provider-templates-7M24FAAI.js.map → provider-templates-JWT6U5B7.js.map} +0 -0
- /package/dist/{ui-command-JIRLAHM6.js.map → ui-command-LZWTWTQ6.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.1",
|
|
54
54
|
publishConfig: {
|
|
55
55
|
access: "public"
|
|
56
56
|
},
|
|
@@ -2099,7 +2099,9 @@ var PROVIDER_TEMPLATES = [
|
|
|
2099
2099
|
{
|
|
2100
2100
|
id: "antigravity",
|
|
2101
2101
|
name: "Cloud Code Assist OAuth (Google)",
|
|
2102
|
-
|
|
2102
|
+
// Compact label users actually recognise: every surface that shows this
|
|
2103
|
+
// provider calls it Antigravity, and it is also the shortest of the two.
|
|
2104
|
+
shortName: "Antigravity",
|
|
2103
2105
|
authType: "oauth",
|
|
2104
2106
|
npm: "@ai-sdk/openai-compatible",
|
|
2105
2107
|
signupUrl: "https://antigravity.google",
|
|
@@ -2204,6 +2206,55 @@ function isRelayCoreError(err) {
|
|
|
2204
2206
|
return err instanceof RelayCoreError;
|
|
2205
2207
|
}
|
|
2206
2208
|
|
|
2209
|
+
// src/opencode-session.ts
|
|
2210
|
+
import { randomUUID as randomUUID2 } from "crypto";
|
|
2211
|
+
var OPENCODE_SESSION_HEADER = "x-opencode-session";
|
|
2212
|
+
var MAX_OPENCODE_SESSION_LENGTH = 256;
|
|
2213
|
+
var RELAY_USER_AGENT = `relay-ai/${VERSION}`;
|
|
2214
|
+
function sanitizeSessionId(value) {
|
|
2215
|
+
if (typeof value !== "string") return void 0;
|
|
2216
|
+
const normalized = value.trim();
|
|
2217
|
+
if (!normalized || normalized.length > MAX_OPENCODE_SESSION_LENGTH) return void 0;
|
|
2218
|
+
if (/[\u0000-\u001f\u007f\r\n]/.test(normalized)) return void 0;
|
|
2219
|
+
return normalized;
|
|
2220
|
+
}
|
|
2221
|
+
function isOpenCodeGoEndpoint(providerId, endpoint) {
|
|
2222
|
+
const id = providerId?.trim().toLowerCase();
|
|
2223
|
+
if (id === "go" || id === "opencode-go") return true;
|
|
2224
|
+
if (!endpoint) return false;
|
|
2225
|
+
try {
|
|
2226
|
+
const url = new URL(endpoint);
|
|
2227
|
+
if (url.hostname.toLowerCase() !== "opencode.ai") return false;
|
|
2228
|
+
return url.pathname.split("/").some((segment) => segment.toLowerCase() === "go");
|
|
2229
|
+
} catch {
|
|
2230
|
+
return false;
|
|
2231
|
+
}
|
|
2232
|
+
}
|
|
2233
|
+
function mergeHeaders(base, overrides) {
|
|
2234
|
+
const result = {};
|
|
2235
|
+
for (const [key, value] of Object.entries(base ?? {})) {
|
|
2236
|
+
if (typeof value === "string") result[key] = value;
|
|
2237
|
+
}
|
|
2238
|
+
for (const [key, value] of Object.entries(overrides ?? {})) {
|
|
2239
|
+
for (const existing of Object.keys(result)) {
|
|
2240
|
+
if (existing.toLowerCase() === key.toLowerCase()) delete result[existing];
|
|
2241
|
+
}
|
|
2242
|
+
result[key] = value;
|
|
2243
|
+
}
|
|
2244
|
+
return result;
|
|
2245
|
+
}
|
|
2246
|
+
function openCodeGoHeaders(providerId, endpoint, sessionId, baseHeaders, options) {
|
|
2247
|
+
if (!isOpenCodeGoEndpoint(providerId, endpoint)) return void 0;
|
|
2248
|
+
let normalizedSessionId = sanitizeSessionId(sessionId);
|
|
2249
|
+
if (!normalizedSessionId && (options?.generateFallbackSession ?? true)) {
|
|
2250
|
+
normalizedSessionId = `relay-${randomUUID2()}`;
|
|
2251
|
+
}
|
|
2252
|
+
return mergeHeaders(baseHeaders, {
|
|
2253
|
+
"User-Agent": RELAY_USER_AGENT,
|
|
2254
|
+
...normalizedSessionId ? { [OPENCODE_SESSION_HEADER]: normalizedSessionId } : {}
|
|
2255
|
+
});
|
|
2256
|
+
}
|
|
2257
|
+
|
|
2207
2258
|
// src/core/reasoning.ts
|
|
2208
2259
|
var RELAY_REASONING_LEVELS = [
|
|
2209
2260
|
"off",
|
|
@@ -2277,6 +2328,22 @@ async function withReasoningProviderOptions(model, providerOptions) {
|
|
|
2277
2328
|
}
|
|
2278
2329
|
});
|
|
2279
2330
|
}
|
|
2331
|
+
async function withRequestHeaders(model, headers) {
|
|
2332
|
+
const { wrapLanguageModel: wrapLanguageModel2 } = await import("ai");
|
|
2333
|
+
return wrapLanguageModel2({
|
|
2334
|
+
model,
|
|
2335
|
+
middleware: {
|
|
2336
|
+
specificationVersion: "v3",
|
|
2337
|
+
transformParams: async ({ params }) => ({
|
|
2338
|
+
...params,
|
|
2339
|
+
headers: mergeHeaders(
|
|
2340
|
+
headers,
|
|
2341
|
+
params.headers
|
|
2342
|
+
)
|
|
2343
|
+
})
|
|
2344
|
+
}
|
|
2345
|
+
});
|
|
2346
|
+
}
|
|
2280
2347
|
|
|
2281
2348
|
// src/core/route-id.ts
|
|
2282
2349
|
var SEPARATOR = "::";
|
|
@@ -3509,7 +3576,7 @@ function providerRefreshToken(providerId, authType, authRef) {
|
|
|
3509
3576
|
}
|
|
3510
3577
|
|
|
3511
3578
|
// src/core/antigravity-model.ts
|
|
3512
|
-
import { randomUUID as
|
|
3579
|
+
import { randomUUID as randomUUID3 } from "crypto";
|
|
3513
3580
|
var CLOUD_CODE_BASES = ANTIGRAVITY_BASE_URLS.map((base) => base.replace(/\/+$/, ""));
|
|
3514
3581
|
var CLOUD_CODE_BASE = CLOUD_CODE_BASES[0];
|
|
3515
3582
|
var STREAM_URLS = CLOUD_CODE_BASES.map((base) => `${base}/${ANTIGRAVITY_API_VERSION}:streamGenerateContent?alt=sse`);
|
|
@@ -3596,7 +3663,7 @@ function createCloudCodeFetch(options, fetchImpl) {
|
|
|
3596
3663
|
const geminiBody = await readJsonBody(input, init);
|
|
3597
3664
|
const envelope = {
|
|
3598
3665
|
project: options.projectId,
|
|
3599
|
-
requestId:
|
|
3666
|
+
requestId: randomUUID3(),
|
|
3600
3667
|
model: options.modelId,
|
|
3601
3668
|
userAgent: ANTIGRAVITY_USER_AGENT,
|
|
3602
3669
|
requestType: "agent",
|
|
@@ -3791,7 +3858,21 @@ async function createRelayModel(routeId, options) {
|
|
|
3791
3858
|
const registry = loadCoreRegistry();
|
|
3792
3859
|
const { provider, model } = findRoute(registry, providerId, modelId, routeId);
|
|
3793
3860
|
const reasoningOptions = options?.reasoning === void 0 ? void 0 : resolveReasoningProviderOptions(options.reasoning, provider, model, routeId);
|
|
3794
|
-
const
|
|
3861
|
+
const transportHeaders = openCodeGoHeaders(
|
|
3862
|
+
provider.id,
|
|
3863
|
+
model.apiUrl ?? provider.api.url,
|
|
3864
|
+
options?.sessionId,
|
|
3865
|
+
provider.api.headers,
|
|
3866
|
+
// The returned model may be reused across conversations, so never fabricate a
|
|
3867
|
+
// session here — a baked-in id would blend histories. The host passes sessionId.
|
|
3868
|
+
{ generateFallbackSession: false }
|
|
3869
|
+
);
|
|
3870
|
+
const finish = async (built) => {
|
|
3871
|
+
let finished = built;
|
|
3872
|
+
if (reasoningOptions) finished = await withReasoningProviderOptions(finished, reasoningOptions);
|
|
3873
|
+
if (transportHeaders) finished = await withRequestHeaders(finished, transportHeaders);
|
|
3874
|
+
return finished;
|
|
3875
|
+
};
|
|
3795
3876
|
if (isAntigravityCloudCodeRoute(provider, model)) {
|
|
3796
3877
|
const apiKey2 = await resolveCredential(provider, routeId);
|
|
3797
3878
|
const providerData2 = await resolveProviderOAuthProviderData(provider.authRef);
|