@agentfield/sdk 0.1.91 → 0.1.92-rc.2
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/index.d.ts +8 -0
- package/dist/index.js +156 -9
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -45,6 +45,7 @@ declare class AIClient {
|
|
|
45
45
|
getModel(options?: AIRequestOptions): _ai_sdk_provider.LanguageModelV3;
|
|
46
46
|
private buildModel;
|
|
47
47
|
private buildEmbeddingModel;
|
|
48
|
+
private openRouterHeaders;
|
|
48
49
|
private getRateLimiter;
|
|
49
50
|
private withRateLimitRetry;
|
|
50
51
|
}
|
|
@@ -869,6 +870,9 @@ interface AIConfig {
|
|
|
869
870
|
embeddingModel?: string;
|
|
870
871
|
apiKey?: string;
|
|
871
872
|
baseUrl?: string;
|
|
873
|
+
openRouterSiteUrl?: string;
|
|
874
|
+
openRouterAppName?: string;
|
|
875
|
+
openRouterHeaders?: Record<string, string>;
|
|
872
876
|
temperature?: number;
|
|
873
877
|
maxTokens?: number;
|
|
874
878
|
enableRateLimitRetry?: boolean;
|
|
@@ -1780,11 +1784,15 @@ declare class MediaRouter {
|
|
|
1780
1784
|
interface OpenRouterMediaProviderOptions {
|
|
1781
1785
|
apiKey?: string;
|
|
1782
1786
|
baseUrl?: string;
|
|
1787
|
+
openRouterSiteUrl?: string;
|
|
1788
|
+
openRouterAppName?: string;
|
|
1789
|
+
openRouterHeaders?: Record<string, string>;
|
|
1783
1790
|
}
|
|
1784
1791
|
declare class OpenRouterMediaProvider implements MediaProvider {
|
|
1785
1792
|
readonly name = "openrouter";
|
|
1786
1793
|
readonly supportedModalities: string[];
|
|
1787
1794
|
private readonly baseUrl;
|
|
1795
|
+
private readonly attributionHeaders;
|
|
1788
1796
|
constructor(options?: OpenRouterMediaProviderOptions);
|
|
1789
1797
|
/**
|
|
1790
1798
|
* Seed the metadata cache for a model. Useful when running against test
|
package/dist/index.js
CHANGED
|
@@ -34,6 +34,107 @@ var __export = (target, all) => {
|
|
|
34
34
|
for (var name in all)
|
|
35
35
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
36
36
|
};
|
|
37
|
+
|
|
38
|
+
// src/ai/openrouterAttribution.ts
|
|
39
|
+
function isOpenRouterRequest(options) {
|
|
40
|
+
const provider = clean(options.provider)?.toLowerCase();
|
|
41
|
+
if (provider === "openrouter") {
|
|
42
|
+
return true;
|
|
43
|
+
}
|
|
44
|
+
const model = clean(options.model)?.toLowerCase();
|
|
45
|
+
if (model?.startsWith("openrouter/")) {
|
|
46
|
+
return true;
|
|
47
|
+
}
|
|
48
|
+
const baseUrl = clean(options.baseUrl)?.toLowerCase();
|
|
49
|
+
return Boolean(baseUrl?.includes("openrouter.ai"));
|
|
50
|
+
}
|
|
51
|
+
function openRouterAttributionEnabled(env = process.env) {
|
|
52
|
+
const raw = clean(env.AGENTFIELD_OPENROUTER_ATTRIBUTION);
|
|
53
|
+
if (!raw) {
|
|
54
|
+
return true;
|
|
55
|
+
}
|
|
56
|
+
return !["0", "false", "no", "off"].includes(raw.toLowerCase());
|
|
57
|
+
}
|
|
58
|
+
function resolveOpenRouterAttribution(options = {}) {
|
|
59
|
+
const env = options.env ?? process.env;
|
|
60
|
+
if (!openRouterAttributionEnabled(env)) {
|
|
61
|
+
return void 0;
|
|
62
|
+
}
|
|
63
|
+
const siteUrl = clean(options.siteUrl) ?? clean(env.AGENTFIELD_OPENROUTER_SITE_URL) ?? clean(env.OR_SITE_URL) ?? DEFAULT_OPENROUTER_SITE_URL;
|
|
64
|
+
const appName = clean(options.appName) ?? clean(env.AGENTFIELD_OPENROUTER_APP_NAME) ?? clean(env.OR_APP_NAME) ?? DEFAULT_OPENROUTER_APP_NAME;
|
|
65
|
+
return { siteUrl, appName };
|
|
66
|
+
}
|
|
67
|
+
function openRouterAttributionHeaders(options = {}) {
|
|
68
|
+
const resolved = resolveOpenRouterAttribution(options);
|
|
69
|
+
if (!resolved) {
|
|
70
|
+
return {};
|
|
71
|
+
}
|
|
72
|
+
return {
|
|
73
|
+
"HTTP-Referer": resolved.siteUrl,
|
|
74
|
+
"X-OpenRouter-Title": resolved.appName,
|
|
75
|
+
"X-Title": resolved.appName
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
function mergeOpenRouterAttributionHeaders(existing = {}, options = {}) {
|
|
79
|
+
const merged = {};
|
|
80
|
+
const lowerKeys = /* @__PURE__ */ new Set();
|
|
81
|
+
for (const [key, value] of Object.entries(existing)) {
|
|
82
|
+
const cleaned = clean(value);
|
|
83
|
+
if (!cleaned) {
|
|
84
|
+
continue;
|
|
85
|
+
}
|
|
86
|
+
merged[key] = cleaned;
|
|
87
|
+
lowerKeys.add(key.toLowerCase());
|
|
88
|
+
}
|
|
89
|
+
for (const [key, value] of Object.entries(openRouterAttributionHeaders(options))) {
|
|
90
|
+
if (!lowerKeys.has(key.toLowerCase())) {
|
|
91
|
+
merged[key] = value;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
return merged;
|
|
95
|
+
}
|
|
96
|
+
function openRouterAttributionEnv(env = process.env) {
|
|
97
|
+
const resolved = resolveOpenRouterAttribution({ env });
|
|
98
|
+
if (!resolved) {
|
|
99
|
+
return {};
|
|
100
|
+
}
|
|
101
|
+
return {
|
|
102
|
+
AGENTFIELD_OPENROUTER_SITE_URL: resolved.siteUrl,
|
|
103
|
+
AGENTFIELD_OPENROUTER_APP_NAME: resolved.appName,
|
|
104
|
+
OR_SITE_URL: resolved.siteUrl,
|
|
105
|
+
OR_APP_NAME: resolved.appName
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
function applyOpenRouterAttributionEnv(env) {
|
|
109
|
+
if (!openRouterAttributionEnabled(env)) {
|
|
110
|
+
for (const key of [
|
|
111
|
+
"AGENTFIELD_OPENROUTER_SITE_URL",
|
|
112
|
+
"AGENTFIELD_OPENROUTER_APP_NAME",
|
|
113
|
+
"OR_SITE_URL",
|
|
114
|
+
"OR_APP_NAME"
|
|
115
|
+
]) {
|
|
116
|
+
delete env[key];
|
|
117
|
+
}
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
const attribution = openRouterAttributionEnv(env);
|
|
121
|
+
for (const [key, value] of Object.entries(attribution)) {
|
|
122
|
+
if (clean(env[key]) == null) {
|
|
123
|
+
env[key] = value;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
function clean(value) {
|
|
128
|
+
const trimmed = value?.trim();
|
|
129
|
+
return trimmed ? trimmed : void 0;
|
|
130
|
+
}
|
|
131
|
+
var DEFAULT_OPENROUTER_SITE_URL, DEFAULT_OPENROUTER_APP_NAME;
|
|
132
|
+
var init_openrouterAttribution = __esm({
|
|
133
|
+
"src/ai/openrouterAttribution.ts"() {
|
|
134
|
+
DEFAULT_OPENROUTER_SITE_URL = "https://agentfield.ai";
|
|
135
|
+
DEFAULT_OPENROUTER_APP_NAME = "AgentField AI";
|
|
136
|
+
}
|
|
137
|
+
});
|
|
37
138
|
function getZodConverter() {
|
|
38
139
|
if (zodConverter !== void 0) {
|
|
39
140
|
return zodConverter;
|
|
@@ -340,8 +441,10 @@ var init_claude = __esm({
|
|
|
340
441
|
function runCli(cmd, options) {
|
|
341
442
|
return new Promise((resolve2, reject) => {
|
|
342
443
|
const [bin, ...args] = cmd;
|
|
444
|
+
const env = { ...process.env, ...options?.env };
|
|
445
|
+
applyOpenRouterAttributionEnv(env);
|
|
343
446
|
const proc = spawn(bin, args, {
|
|
344
|
-
env
|
|
447
|
+
env,
|
|
345
448
|
cwd: options?.cwd,
|
|
346
449
|
stdio: ["pipe", "pipe", "pipe"]
|
|
347
450
|
});
|
|
@@ -414,6 +517,7 @@ function extractFinalText(events) {
|
|
|
414
517
|
}
|
|
415
518
|
var init_cli = __esm({
|
|
416
519
|
"src/harness/cli.ts"() {
|
|
520
|
+
init_openrouterAttribution();
|
|
417
521
|
}
|
|
418
522
|
});
|
|
419
523
|
|
|
@@ -566,6 +670,7 @@ var init_opencode = __esm({
|
|
|
566
670
|
"src/harness/providers/opencode.ts"() {
|
|
567
671
|
init_types();
|
|
568
672
|
init_cli();
|
|
673
|
+
init_openrouterAttribution();
|
|
569
674
|
OpenCodeProvider = class {
|
|
570
675
|
bin;
|
|
571
676
|
constructor(binPath = "opencode") {
|
|
@@ -593,6 +698,22 @@ USER REQUEST:
|
|
|
593
698
|
${prompt}`;
|
|
594
699
|
}
|
|
595
700
|
cmd.push(effectivePrompt);
|
|
701
|
+
const explicitModel = typeof options.model === "string" ? options.model : void 0;
|
|
702
|
+
if (explicitModel && isOpenRouterRequest({ model: explicitModel }) && !env.OPENCODE_CONFIG_CONTENT && !process.env.OPENCODE_CONFIG_CONTENT) {
|
|
703
|
+
const modelSlug = explicitModel.slice("openrouter/".length);
|
|
704
|
+
const headers = openRouterAttributionHeaders({ env: { ...process.env, ...env } });
|
|
705
|
+
if (modelSlug && Object.keys(headers).length > 0) {
|
|
706
|
+
env.OPENCODE_CONFIG_CONTENT = JSON.stringify({
|
|
707
|
+
provider: {
|
|
708
|
+
openrouter: {
|
|
709
|
+
models: {
|
|
710
|
+
[modelSlug]: { headers }
|
|
711
|
+
}
|
|
712
|
+
}
|
|
713
|
+
}
|
|
714
|
+
});
|
|
715
|
+
}
|
|
716
|
+
}
|
|
596
717
|
const startApi = Date.now();
|
|
597
718
|
try {
|
|
598
719
|
const { stdout, stderr, exitCode } = await runCli(cmd, { env });
|
|
@@ -1671,6 +1792,7 @@ function toError(error) {
|
|
|
1671
1792
|
}
|
|
1672
1793
|
|
|
1673
1794
|
// src/ai/AIClient.ts
|
|
1795
|
+
init_openrouterAttribution();
|
|
1674
1796
|
function repairJsonText(text2) {
|
|
1675
1797
|
let cleaned = text2.trim();
|
|
1676
1798
|
const codeBlockMatch = cleaned.match(/```(?:json)?\s*([\s\S]*?)```/);
|
|
@@ -1772,6 +1894,7 @@ var AIClient = class {
|
|
|
1772
1894
|
buildModel(options) {
|
|
1773
1895
|
const provider = options.provider ?? this.config.provider ?? "openai";
|
|
1774
1896
|
const modelName = options.model ?? this.config.model ?? "gpt-4o";
|
|
1897
|
+
const openRouterHeaders = this.openRouterHeaders(provider, modelName);
|
|
1775
1898
|
switch (provider) {
|
|
1776
1899
|
case "anthropic": {
|
|
1777
1900
|
const anthropic = createAnthropic({
|
|
@@ -1825,7 +1948,8 @@ var AIClient = class {
|
|
|
1825
1948
|
case "openrouter": {
|
|
1826
1949
|
const openrouter = createOpenAI({
|
|
1827
1950
|
apiKey: this.config.apiKey,
|
|
1828
|
-
baseURL: this.config.baseUrl ?? "https://openrouter.ai/api/v1"
|
|
1951
|
+
baseURL: this.config.baseUrl ?? "https://openrouter.ai/api/v1",
|
|
1952
|
+
headers: openRouterHeaders
|
|
1829
1953
|
});
|
|
1830
1954
|
return openrouter.chat(modelName);
|
|
1831
1955
|
}
|
|
@@ -1841,7 +1965,8 @@ var AIClient = class {
|
|
|
1841
1965
|
default: {
|
|
1842
1966
|
const openai = createOpenAI({
|
|
1843
1967
|
apiKey: this.config.apiKey,
|
|
1844
|
-
baseURL: this.config.baseUrl
|
|
1968
|
+
baseURL: this.config.baseUrl,
|
|
1969
|
+
...openRouterHeaders ? { headers: openRouterHeaders } : {}
|
|
1845
1970
|
});
|
|
1846
1971
|
return openai(modelName);
|
|
1847
1972
|
}
|
|
@@ -1850,6 +1975,7 @@ var AIClient = class {
|
|
|
1850
1975
|
buildEmbeddingModel(options) {
|
|
1851
1976
|
const provider = options.provider ?? this.config.provider ?? "openai";
|
|
1852
1977
|
const modelName = options.model ?? this.config.embeddingModel ?? "text-embedding-3-small";
|
|
1978
|
+
const openRouterHeaders = this.openRouterHeaders(provider, modelName);
|
|
1853
1979
|
const noEmbeddingProviders = ["anthropic", "xai", "deepseek", "groq"];
|
|
1854
1980
|
if (noEmbeddingProviders.includes(provider)) {
|
|
1855
1981
|
throw new Error(`Embedding generation is not supported for ${provider} provider`);
|
|
@@ -1882,12 +2008,22 @@ var AIClient = class {
|
|
|
1882
2008
|
default: {
|
|
1883
2009
|
const openai = createOpenAI({
|
|
1884
2010
|
apiKey: this.config.apiKey ?? (provider === "ollama" ? "ollama" : void 0),
|
|
1885
|
-
baseURL: this.config.baseUrl ?? (provider === "openrouter" ? "https://openrouter.ai/api/v1" : provider === "ollama" ? "http://localhost:11434/v1" : void 0)
|
|
2011
|
+
baseURL: this.config.baseUrl ?? (provider === "openrouter" ? "https://openrouter.ai/api/v1" : provider === "ollama" ? "http://localhost:11434/v1" : void 0),
|
|
2012
|
+
...openRouterHeaders ? { headers: openRouterHeaders } : {}
|
|
1886
2013
|
});
|
|
1887
2014
|
return openai.embedding(modelName);
|
|
1888
2015
|
}
|
|
1889
2016
|
}
|
|
1890
2017
|
}
|
|
2018
|
+
openRouterHeaders(provider, model) {
|
|
2019
|
+
if (!isOpenRouterRequest({ provider, model, baseUrl: this.config.baseUrl })) {
|
|
2020
|
+
return void 0;
|
|
2021
|
+
}
|
|
2022
|
+
return mergeOpenRouterAttributionHeaders(this.config.openRouterHeaders, {
|
|
2023
|
+
siteUrl: this.config.openRouterSiteUrl,
|
|
2024
|
+
appName: this.config.openRouterAppName
|
|
2025
|
+
});
|
|
2026
|
+
}
|
|
1891
2027
|
getRateLimiter() {
|
|
1892
2028
|
if (!this.rateLimiter) {
|
|
1893
2029
|
this.rateLimiter = new StatelessRateLimiter({
|
|
@@ -5644,6 +5780,7 @@ var MediaRouter = class {
|
|
|
5644
5780
|
};
|
|
5645
5781
|
|
|
5646
5782
|
// src/ai/OpenRouterMediaProvider.ts
|
|
5783
|
+
init_openrouterAttribution();
|
|
5647
5784
|
var OPENROUTER_BASE = "https://openrouter.ai/api/v1";
|
|
5648
5785
|
var DEFAULT_POLL_INTERVAL = 3e4;
|
|
5649
5786
|
var DEFAULT_TIMEOUT = 6e5;
|
|
@@ -5735,9 +5872,14 @@ var OpenRouterMediaProvider = class {
|
|
|
5735
5872
|
name = "openrouter";
|
|
5736
5873
|
supportedModalities = ["image", "audio", "video"];
|
|
5737
5874
|
baseUrl;
|
|
5875
|
+
attributionHeaders;
|
|
5738
5876
|
constructor(options = {}) {
|
|
5739
5877
|
const key = options.apiKey ?? process.env.OPENROUTER_API_KEY ?? "";
|
|
5740
5878
|
this.baseUrl = options.baseUrl ?? OPENROUTER_BASE;
|
|
5879
|
+
this.attributionHeaders = mergeOpenRouterAttributionHeaders(options.openRouterHeaders, {
|
|
5880
|
+
siteUrl: options.openRouterSiteUrl,
|
|
5881
|
+
appName: options.openRouterAppName
|
|
5882
|
+
});
|
|
5741
5883
|
if (!key) {
|
|
5742
5884
|
throw new MediaProviderError("OpenRouter API key required: pass apiKey or set OPENROUTER_API_KEY", {
|
|
5743
5885
|
provider: "openrouter"
|
|
@@ -5897,7 +6039,10 @@ var OpenRouterMediaProvider = class {
|
|
|
5897
6039
|
} catch {
|
|
5898
6040
|
}
|
|
5899
6041
|
const dlRes = await fetch(videoUrl, {
|
|
5900
|
-
headers:
|
|
6042
|
+
headers: mergeOpenRouterAttributionHeaders({
|
|
6043
|
+
...this.attributionHeaders,
|
|
6044
|
+
...downloadHeaders
|
|
6045
|
+
}),
|
|
5901
6046
|
signal: AbortSignal.timeout(DOWNLOAD_TIMEOUT),
|
|
5902
6047
|
redirect: "error"
|
|
5903
6048
|
});
|
|
@@ -6189,10 +6334,11 @@ var OpenRouterMediaProvider = class {
|
|
|
6189
6334
|
const key = apiKeyStore.get(this);
|
|
6190
6335
|
return fetch(url, {
|
|
6191
6336
|
method: "POST",
|
|
6192
|
-
headers: {
|
|
6337
|
+
headers: mergeOpenRouterAttributionHeaders({
|
|
6338
|
+
...this.attributionHeaders,
|
|
6193
6339
|
"Content-Type": "application/json",
|
|
6194
6340
|
Authorization: `Bearer ${key}`
|
|
6195
|
-
},
|
|
6341
|
+
}),
|
|
6196
6342
|
body: JSON.stringify(body),
|
|
6197
6343
|
signal: AbortSignal.timeout(API_TIMEOUT)
|
|
6198
6344
|
});
|
|
@@ -6201,9 +6347,10 @@ var OpenRouterMediaProvider = class {
|
|
|
6201
6347
|
const key = apiKeyStore.get(this);
|
|
6202
6348
|
return fetch(url, {
|
|
6203
6349
|
method: "GET",
|
|
6204
|
-
headers: {
|
|
6350
|
+
headers: mergeOpenRouterAttributionHeaders({
|
|
6351
|
+
...this.attributionHeaders,
|
|
6205
6352
|
Authorization: `Bearer ${key}`
|
|
6206
|
-
},
|
|
6353
|
+
}),
|
|
6207
6354
|
signal: AbortSignal.timeout(API_TIMEOUT)
|
|
6208
6355
|
});
|
|
6209
6356
|
}
|