@agentfield/sdk 0.1.91 → 0.1.92-rc.10

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 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;
@@ -1081,6 +1085,45 @@ declare class HarnessRunner {
1081
1085
  private sleep;
1082
1086
  }
1083
1087
 
1088
+ interface SessionDefinition {
1089
+ name: string;
1090
+ provider: string;
1091
+ transport: string;
1092
+ model?: string;
1093
+ modalities: string[];
1094
+ voice?: string;
1095
+ tools: string[];
1096
+ tags: string[];
1097
+ proposed_tags: string[];
1098
+ approved_tags: string[];
1099
+ metadata: Record<string, unknown>;
1100
+ }
1101
+ interface SessionOptions {
1102
+ provider: string;
1103
+ transport: string;
1104
+ model?: string;
1105
+ modalities?: string[];
1106
+ voice?: string;
1107
+ tools?: string[];
1108
+ tags?: string[];
1109
+ metadata?: Record<string, unknown>;
1110
+ }
1111
+ interface SessionTurn {
1112
+ text?: string;
1113
+ transcript?: string;
1114
+ audio?: unknown;
1115
+ audioFormat?: string;
1116
+ channel?: string;
1117
+ metadata?: Record<string, unknown>;
1118
+ }
1119
+ declare class RealtimeSession {
1120
+ readonly sessionId: string;
1121
+ readonly definition: SessionDefinition;
1122
+ constructor(sessionId: string, definition: SessionDefinition);
1123
+ input(): Promise<SessionTurn>;
1124
+ }
1125
+ declare function buildSessionDefinition(name: string, options: SessionOptions): SessionDefinition;
1126
+
1084
1127
  declare class Agent {
1085
1128
  readonly config: AgentConfig;
1086
1129
  readonly app: express.Express;
@@ -1097,6 +1140,7 @@ declare class Agent {
1097
1140
  private readonly memoryWatchers;
1098
1141
  private readonly localVerifier?;
1099
1142
  private readonly realtimeValidationFunctions;
1143
+ private readonly sessions;
1100
1144
  private readonly processLogRing;
1101
1145
  private readonly executionLogger;
1102
1146
  /** Tracks an AbortController per in-flight execution_id so the
@@ -1108,6 +1152,8 @@ declare class Agent {
1108
1152
  reasoner<TInput = any, TOutput = any>(name: string, handler: ReasonerHandler<TInput, TOutput>, options?: ReasonerOptions): this;
1109
1153
  skill<TInput = any, TOutput = any>(name: string, handler: SkillHandler<TInput, TOutput>, options?: SkillOptions): this;
1110
1154
  includeRouter(router: AgentRouter): void;
1155
+ session(name: string, options: SessionOptions, handler: (session: RealtimeSession) => Promise<unknown> | unknown): this;
1156
+ sessionDefinitions(): SessionDefinition[];
1111
1157
  handler(adapter?: (event: any, context?: any) => ServerlessEvent): AgentHandler;
1112
1158
  watchMemory(pattern: string | string[], handler: MemoryWatchHandler, options?: {
1113
1159
  scope?: string;
@@ -1780,11 +1826,15 @@ declare class MediaRouter {
1780
1826
  interface OpenRouterMediaProviderOptions {
1781
1827
  apiKey?: string;
1782
1828
  baseUrl?: string;
1829
+ openRouterSiteUrl?: string;
1830
+ openRouterAppName?: string;
1831
+ openRouterHeaders?: Record<string, string>;
1783
1832
  }
1784
1833
  declare class OpenRouterMediaProvider implements MediaProvider {
1785
1834
  readonly name = "openrouter";
1786
1835
  readonly supportedModalities: string[];
1787
1836
  private readonly baseUrl;
1837
+ private readonly attributionHeaders;
1788
1838
  constructor(options?: OpenRouterMediaProviderOptions);
1789
1839
  /**
1790
1840
  * Seed the metadata cache for a model. Useful when running against test
@@ -1921,4 +1971,23 @@ declare class ApprovalClient {
1921
1971
  waitForApproval(executionId: string, opts?: WaitForApprovalOptions): Promise<ApprovalStatusResponse>;
1922
1972
  }
1923
1973
 
1924
- export { ACTIVE_STATUSES, AIClient, type AIConfig, type AIEmbeddingOptions, type AIRequestOptions, type AIStream, type AIToolRequestOptions, Agent, type AgentCapability, type AgentConfig, type AgentHandler, AgentRouter, type AgentRouterOptions, type AgentState, ApprovalClient, type ApprovalRequestResponse, type ApprovalStatusResponse, Audio, type AudioOutput, type AudioRequest, type AuditTrailExport, type AuditTrailFilters, type Awaitable, CANONICAL_STATUSES, type CompactCapability, type CompactDiscoveryResponse, DIDAuthenticator, type DIDIdentity, type DIDIdentityPackage, type DIDRegistrationRequest, type DIDRegistrationResponse, type DeploymentType, DidClient, DidInterface, DidManager, type DiscoveryFormat, type DiscoveryOptions, type DiscoveryPagination, type DiscoveryResponse, type DiscoveryResult, ExecutionContext, type ExecutionCredential, type ExecutionLogAttributes, type ExecutionLogBatchPayload, type ExecutionLogContext, type ExecutionLogEmitOptions, type ExecutionLogEntry, type ExecutionLogLevel, type ExecutionLogTransport, type ExecutionLogTransportPayload, type ExecutionLogWireEntry, ExecutionLogger, type ExecutionLoggerOptions, type ExecutionMetadata, ExecutionStatus, type ExecutionStatusValue, File, type FileOutput, type GenerateCredentialOptions, type GenerateCredentialParams, HEADER_CALLER_DID, HEADER_DID_NONCE, HEADER_DID_SIGNATURE, HEADER_DID_TIMESTAMP, type HarnessConfig, type HarnessOptions, type HarnessProvider, type HarnessResult, HarnessRunner, type HealthStatus, Image, type ImageOutput, type ImageRequest, type MediaProvider, MediaProviderError, type MediaResponse, MediaRouter, type MemoryChangeEvent, MemoryClient, MemoryClientBase, type MemoryConfig, MemoryEventClient, type MemoryEventHandler, type MemoryEventHistoryOptions, MemoryInterface, type MemoryRequestMetadata, type MemoryRequestOptions, type MemoryScope, type MemoryWatchHandler, type Metrics, type MultimodalContent, MultimodalResponse, OpenRouterMediaProvider, type OpenRouterMediaProviderOptions, RateLimitError, type RateLimiterOptions, type RawExecutionContext, type RawResult, type ReasonerCapability, ReasonerContext, type ReasonerDefinition, type ReasonerHandler, type ReasonerOptions, type RequestApprovalPayload, SUPPORTED_PROVIDERS, type ServerlessAdapter, type ServerlessEvent, type ServerlessResponse, type SkillCapability, SkillContext, type SkillDefinition, type SkillHandler, type SkillOptions, StatelessRateLimiter, TERMINAL_STATUSES, Text, type ToolCallConfig, type ToolCallRecord, type ToolCallTrace, type ToolsOption, type VectorSearchOptions, type VectorSearchResult, Video, type VideoFrameImage, type VideoInputReference, type VideoRequest, type WaitForApprovalOptions, type WorkflowCredential, type WorkflowMetadata, type WorkflowProgressOptions, WorkflowReporter, type ZodSchema, audioFromBase64, audioFromBuffer, audioFromFile, audioFromUrl, buildProvider, buildToolConfig, capabilitiesToTools, capabilityToMetadataTool, capabilityToTool, createExecutionLogger, createHarnessResult, createMetrics, createMultimodalResponse, createRawResult, executeToolCallLoop, fileFromBase64, fileFromBuffer, fileFromPath, fileFromUrl, getCurrentContext, getCurrentSkillContext, imageFromBase64, imageFromBuffer, imageFromFile, imageFromUrl, isActive, isExecutionLogBatchPayload, isTerminal, normalizeExecutionLogEntry, normalizeStatus, serializeExecutionLogEntry, text, videoFromBase64, videoFromBuffer, videoFromFile, videoFromUrl };
1974
+ declare const SUPPORTED_SESSION_TRANSPORTS: {
1975
+ readonly openai: readonly ["webrtc", "websocket"];
1976
+ readonly openrouter: readonly ["audio_turns"];
1977
+ };
1978
+ type SessionProvider = keyof typeof SUPPORTED_SESSION_TRANSPORTS;
1979
+ type SessionTransport = (typeof SUPPORTED_SESSION_TRANSPORTS)[SessionProvider][number];
1980
+ interface SessionTransportCapability {
1981
+ provider: SessionProvider;
1982
+ transport: SessionTransport;
1983
+ }
1984
+ declare class SessionTransportError extends Error {
1985
+ readonly provider: string;
1986
+ readonly transport: string;
1987
+ readonly supported: readonly string[];
1988
+ constructor(provider: string, transport: string, supported: readonly string[]);
1989
+ }
1990
+ declare function normalizeSessionTransportValue(value: string): string;
1991
+ declare function validateSessionTransport(provider: string, transport: string): SessionTransportCapability;
1992
+
1993
+ export { ACTIVE_STATUSES, AIClient, type AIConfig, type AIEmbeddingOptions, type AIRequestOptions, type AIStream, type AIToolRequestOptions, Agent, type AgentCapability, type AgentConfig, type AgentHandler, AgentRouter, type AgentRouterOptions, type AgentState, ApprovalClient, type ApprovalRequestResponse, type ApprovalStatusResponse, Audio, type AudioOutput, type AudioRequest, type AuditTrailExport, type AuditTrailFilters, type Awaitable, CANONICAL_STATUSES, type CompactCapability, type CompactDiscoveryResponse, DIDAuthenticator, type DIDIdentity, type DIDIdentityPackage, type DIDRegistrationRequest, type DIDRegistrationResponse, type DeploymentType, DidClient, DidInterface, DidManager, type DiscoveryFormat, type DiscoveryOptions, type DiscoveryPagination, type DiscoveryResponse, type DiscoveryResult, ExecutionContext, type ExecutionCredential, type ExecutionLogAttributes, type ExecutionLogBatchPayload, type ExecutionLogContext, type ExecutionLogEmitOptions, type ExecutionLogEntry, type ExecutionLogLevel, type ExecutionLogTransport, type ExecutionLogTransportPayload, type ExecutionLogWireEntry, ExecutionLogger, type ExecutionLoggerOptions, type ExecutionMetadata, ExecutionStatus, type ExecutionStatusValue, File, type FileOutput, type GenerateCredentialOptions, type GenerateCredentialParams, HEADER_CALLER_DID, HEADER_DID_NONCE, HEADER_DID_SIGNATURE, HEADER_DID_TIMESTAMP, type HarnessConfig, type HarnessOptions, type HarnessProvider, type HarnessResult, HarnessRunner, type HealthStatus, Image, type ImageOutput, type ImageRequest, type MediaProvider, MediaProviderError, type MediaResponse, MediaRouter, type MemoryChangeEvent, MemoryClient, MemoryClientBase, type MemoryConfig, MemoryEventClient, type MemoryEventHandler, type MemoryEventHistoryOptions, MemoryInterface, type MemoryRequestMetadata, type MemoryRequestOptions, type MemoryScope, type MemoryWatchHandler, type Metrics, type MultimodalContent, MultimodalResponse, OpenRouterMediaProvider, type OpenRouterMediaProviderOptions, RateLimitError, type RateLimiterOptions, type RawExecutionContext, type RawResult, RealtimeSession, type ReasonerCapability, ReasonerContext, type ReasonerDefinition, type ReasonerHandler, type ReasonerOptions, type RequestApprovalPayload, SUPPORTED_PROVIDERS, SUPPORTED_SESSION_TRANSPORTS, type ServerlessAdapter, type ServerlessEvent, type ServerlessResponse, type SessionDefinition, type SessionOptions, type SessionProvider, type SessionTransport, type SessionTransportCapability, SessionTransportError, type SessionTurn, type SkillCapability, SkillContext, type SkillDefinition, type SkillHandler, type SkillOptions, StatelessRateLimiter, TERMINAL_STATUSES, Text, type ToolCallConfig, type ToolCallRecord, type ToolCallTrace, type ToolsOption, type VectorSearchOptions, type VectorSearchResult, Video, type VideoFrameImage, type VideoInputReference, type VideoRequest, type WaitForApprovalOptions, type WorkflowCredential, type WorkflowMetadata, type WorkflowProgressOptions, WorkflowReporter, type ZodSchema, audioFromBase64, audioFromBuffer, audioFromFile, audioFromUrl, buildProvider, buildSessionDefinition, buildToolConfig, capabilitiesToTools, capabilityToMetadataTool, capabilityToTool, createExecutionLogger, createHarnessResult, createMetrics, createMultimodalResponse, createRawResult, executeToolCallLoop, fileFromBase64, fileFromBuffer, fileFromPath, fileFromUrl, getCurrentContext, getCurrentSkillContext, imageFromBase64, imageFromBuffer, imageFromFile, imageFromUrl, isActive, isExecutionLogBatchPayload, isTerminal, normalizeExecutionLogEntry, normalizeSessionTransportValue, normalizeStatus, serializeExecutionLogEntry, text, validateSessionTransport, videoFromBase64, videoFromBuffer, videoFromFile, videoFromUrl };
package/dist/index.js CHANGED
@@ -27,13 +27,119 @@ import { readFile } from 'fs/promises';
27
27
 
28
28
  var __defProp = Object.defineProperty;
29
29
  var __getOwnPropNames = Object.getOwnPropertyNames;
30
- var __esm = (fn, res) => function __init() {
31
- return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
30
+ var __esm = (fn, res, err) => function __init() {
31
+ if (err) throw err[0];
32
+ try {
33
+ return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
34
+ } catch (e) {
35
+ throw err = [e], e;
36
+ }
32
37
  };
33
38
  var __export = (target, all) => {
34
39
  for (var name in all)
35
40
  __defProp(target, name, { get: all[name], enumerable: true });
36
41
  };
42
+
43
+ // src/ai/openrouterAttribution.ts
44
+ function isOpenRouterRequest(options) {
45
+ const provider = clean(options.provider)?.toLowerCase();
46
+ if (provider === "openrouter") {
47
+ return true;
48
+ }
49
+ const model = clean(options.model)?.toLowerCase();
50
+ if (model?.startsWith("openrouter/")) {
51
+ return true;
52
+ }
53
+ const baseUrl = clean(options.baseUrl)?.toLowerCase();
54
+ return Boolean(baseUrl?.includes("openrouter.ai"));
55
+ }
56
+ function openRouterAttributionEnabled(env = process.env) {
57
+ const raw = clean(env.AGENTFIELD_OPENROUTER_ATTRIBUTION);
58
+ if (!raw) {
59
+ return true;
60
+ }
61
+ return !["0", "false", "no", "off"].includes(raw.toLowerCase());
62
+ }
63
+ function resolveOpenRouterAttribution(options = {}) {
64
+ const env = options.env ?? process.env;
65
+ if (!openRouterAttributionEnabled(env)) {
66
+ return void 0;
67
+ }
68
+ const siteUrl = clean(options.siteUrl) ?? clean(env.AGENTFIELD_OPENROUTER_SITE_URL) ?? clean(env.OR_SITE_URL) ?? DEFAULT_OPENROUTER_SITE_URL;
69
+ const appName = clean(options.appName) ?? clean(env.AGENTFIELD_OPENROUTER_APP_NAME) ?? clean(env.OR_APP_NAME) ?? DEFAULT_OPENROUTER_APP_NAME;
70
+ return { siteUrl, appName };
71
+ }
72
+ function openRouterAttributionHeaders(options = {}) {
73
+ const resolved = resolveOpenRouterAttribution(options);
74
+ if (!resolved) {
75
+ return {};
76
+ }
77
+ return {
78
+ "HTTP-Referer": resolved.siteUrl,
79
+ "X-OpenRouter-Title": resolved.appName,
80
+ "X-Title": resolved.appName
81
+ };
82
+ }
83
+ function mergeOpenRouterAttributionHeaders(existing = {}, options = {}) {
84
+ const merged = {};
85
+ const lowerKeys = /* @__PURE__ */ new Set();
86
+ for (const [key, value] of Object.entries(existing)) {
87
+ const cleaned = clean(value);
88
+ if (!cleaned) {
89
+ continue;
90
+ }
91
+ merged[key] = cleaned;
92
+ lowerKeys.add(key.toLowerCase());
93
+ }
94
+ for (const [key, value] of Object.entries(openRouterAttributionHeaders(options))) {
95
+ if (!lowerKeys.has(key.toLowerCase())) {
96
+ merged[key] = value;
97
+ }
98
+ }
99
+ return merged;
100
+ }
101
+ function openRouterAttributionEnv(env = process.env) {
102
+ const resolved = resolveOpenRouterAttribution({ env });
103
+ if (!resolved) {
104
+ return {};
105
+ }
106
+ return {
107
+ AGENTFIELD_OPENROUTER_SITE_URL: resolved.siteUrl,
108
+ AGENTFIELD_OPENROUTER_APP_NAME: resolved.appName,
109
+ OR_SITE_URL: resolved.siteUrl,
110
+ OR_APP_NAME: resolved.appName
111
+ };
112
+ }
113
+ function applyOpenRouterAttributionEnv(env) {
114
+ if (!openRouterAttributionEnabled(env)) {
115
+ for (const key of [
116
+ "AGENTFIELD_OPENROUTER_SITE_URL",
117
+ "AGENTFIELD_OPENROUTER_APP_NAME",
118
+ "OR_SITE_URL",
119
+ "OR_APP_NAME"
120
+ ]) {
121
+ delete env[key];
122
+ }
123
+ return;
124
+ }
125
+ const attribution = openRouterAttributionEnv(env);
126
+ for (const [key, value] of Object.entries(attribution)) {
127
+ if (clean(env[key]) == null) {
128
+ env[key] = value;
129
+ }
130
+ }
131
+ }
132
+ function clean(value) {
133
+ const trimmed = value?.trim();
134
+ return trimmed ? trimmed : void 0;
135
+ }
136
+ var DEFAULT_OPENROUTER_SITE_URL, DEFAULT_OPENROUTER_APP_NAME;
137
+ var init_openrouterAttribution = __esm({
138
+ "src/ai/openrouterAttribution.ts"() {
139
+ DEFAULT_OPENROUTER_SITE_URL = "https://agentfield.ai";
140
+ DEFAULT_OPENROUTER_APP_NAME = "AgentField AI";
141
+ }
142
+ });
37
143
  function getZodConverter() {
38
144
  if (zodConverter !== void 0) {
39
145
  return zodConverter;
@@ -340,8 +446,10 @@ var init_claude = __esm({
340
446
  function runCli(cmd, options) {
341
447
  return new Promise((resolve2, reject) => {
342
448
  const [bin, ...args] = cmd;
449
+ const env = { ...process.env, ...options?.env };
450
+ applyOpenRouterAttributionEnv(env);
343
451
  const proc = spawn(bin, args, {
344
- env: { ...process.env, ...options?.env },
452
+ env,
345
453
  cwd: options?.cwd,
346
454
  stdio: ["pipe", "pipe", "pipe"]
347
455
  });
@@ -414,6 +522,7 @@ function extractFinalText(events) {
414
522
  }
415
523
  var init_cli = __esm({
416
524
  "src/harness/cli.ts"() {
525
+ init_openrouterAttribution();
417
526
  }
418
527
  });
419
528
 
@@ -566,6 +675,7 @@ var init_opencode = __esm({
566
675
  "src/harness/providers/opencode.ts"() {
567
676
  init_types();
568
677
  init_cli();
678
+ init_openrouterAttribution();
569
679
  OpenCodeProvider = class {
570
680
  bin;
571
681
  constructor(binPath = "opencode") {
@@ -593,6 +703,22 @@ USER REQUEST:
593
703
  ${prompt}`;
594
704
  }
595
705
  cmd.push(effectivePrompt);
706
+ const explicitModel = typeof options.model === "string" ? options.model : void 0;
707
+ if (explicitModel && isOpenRouterRequest({ model: explicitModel }) && !env.OPENCODE_CONFIG_CONTENT && !process.env.OPENCODE_CONFIG_CONTENT) {
708
+ const modelSlug = explicitModel.slice("openrouter/".length);
709
+ const headers = openRouterAttributionHeaders({ env: { ...process.env, ...env } });
710
+ if (modelSlug && Object.keys(headers).length > 0) {
711
+ env.OPENCODE_CONFIG_CONTENT = JSON.stringify({
712
+ provider: {
713
+ openrouter: {
714
+ models: {
715
+ [modelSlug]: { headers }
716
+ }
717
+ }
718
+ }
719
+ });
720
+ }
721
+ }
596
722
  const startApi = Date.now();
597
723
  try {
598
724
  const { stdout, stderr, exitCode } = await runCli(cmd, { env });
@@ -692,6 +818,7 @@ var init_runner = __esm({
692
818
  constructor(config) {
693
819
  this.config = config;
694
820
  }
821
+ config;
695
822
  async run(prompt, options = {}) {
696
823
  const { schema, ...rest } = options;
697
824
  const resolved = this.resolveOptions(this.config, rest);
@@ -1671,6 +1798,7 @@ function toError(error) {
1671
1798
  }
1672
1799
 
1673
1800
  // src/ai/AIClient.ts
1801
+ init_openrouterAttribution();
1674
1802
  function repairJsonText(text2) {
1675
1803
  let cleaned = text2.trim();
1676
1804
  const codeBlockMatch = cleaned.match(/```(?:json)?\s*([\s\S]*?)```/);
@@ -1772,6 +1900,7 @@ var AIClient = class {
1772
1900
  buildModel(options) {
1773
1901
  const provider = options.provider ?? this.config.provider ?? "openai";
1774
1902
  const modelName = options.model ?? this.config.model ?? "gpt-4o";
1903
+ const openRouterHeaders = this.openRouterHeaders(provider, modelName);
1775
1904
  switch (provider) {
1776
1905
  case "anthropic": {
1777
1906
  const anthropic = createAnthropic({
@@ -1825,7 +1954,8 @@ var AIClient = class {
1825
1954
  case "openrouter": {
1826
1955
  const openrouter = createOpenAI({
1827
1956
  apiKey: this.config.apiKey,
1828
- baseURL: this.config.baseUrl ?? "https://openrouter.ai/api/v1"
1957
+ baseURL: this.config.baseUrl ?? "https://openrouter.ai/api/v1",
1958
+ headers: openRouterHeaders
1829
1959
  });
1830
1960
  return openrouter.chat(modelName);
1831
1961
  }
@@ -1841,7 +1971,8 @@ var AIClient = class {
1841
1971
  default: {
1842
1972
  const openai = createOpenAI({
1843
1973
  apiKey: this.config.apiKey,
1844
- baseURL: this.config.baseUrl
1974
+ baseURL: this.config.baseUrl,
1975
+ ...openRouterHeaders ? { headers: openRouterHeaders } : {}
1845
1976
  });
1846
1977
  return openai(modelName);
1847
1978
  }
@@ -1850,6 +1981,7 @@ var AIClient = class {
1850
1981
  buildEmbeddingModel(options) {
1851
1982
  const provider = options.provider ?? this.config.provider ?? "openai";
1852
1983
  const modelName = options.model ?? this.config.embeddingModel ?? "text-embedding-3-small";
1984
+ const openRouterHeaders = this.openRouterHeaders(provider, modelName);
1853
1985
  const noEmbeddingProviders = ["anthropic", "xai", "deepseek", "groq"];
1854
1986
  if (noEmbeddingProviders.includes(provider)) {
1855
1987
  throw new Error(`Embedding generation is not supported for ${provider} provider`);
@@ -1882,12 +2014,22 @@ var AIClient = class {
1882
2014
  default: {
1883
2015
  const openai = createOpenAI({
1884
2016
  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)
2017
+ baseURL: this.config.baseUrl ?? (provider === "openrouter" ? "https://openrouter.ai/api/v1" : provider === "ollama" ? "http://localhost:11434/v1" : void 0),
2018
+ ...openRouterHeaders ? { headers: openRouterHeaders } : {}
1886
2019
  });
1887
2020
  return openai.embedding(modelName);
1888
2021
  }
1889
2022
  }
1890
2023
  }
2024
+ openRouterHeaders(provider, model) {
2025
+ if (!isOpenRouterRequest({ provider, model, baseUrl: this.config.baseUrl })) {
2026
+ return void 0;
2027
+ }
2028
+ return mergeOpenRouterAttributionHeaders(this.config.openRouterHeaders, {
2029
+ siteUrl: this.config.openRouterSiteUrl,
2030
+ appName: this.config.openRouterAppName
2031
+ });
2032
+ }
1891
2033
  getRateLimiter() {
1892
2034
  if (!this.rateLimiter) {
1893
2035
  this.rateLimiter = new StatelessRateLimiter({
@@ -3669,6 +3811,83 @@ function registerAgentfieldLogsRoute(app, ring) {
3669
3811
  });
3670
3812
  }
3671
3813
 
3814
+ // src/sessionTransport.ts
3815
+ var SUPPORTED_SESSION_TRANSPORTS = {
3816
+ openai: ["webrtc", "websocket"],
3817
+ openrouter: ["audio_turns"]
3818
+ };
3819
+ var SessionTransportError = class extends Error {
3820
+ provider;
3821
+ transport;
3822
+ supported;
3823
+ constructor(provider, transport, supported) {
3824
+ const supportedDisplay = supported.length > 0 ? supported.join(", ") : "none";
3825
+ super(
3826
+ `Unsupported session transport '${transport}' for provider '${provider}'. Supported transports: ${supportedDisplay}. AgentField does not infer or switch providers; set provider and transport explicitly.`
3827
+ );
3828
+ this.name = "SessionTransportError";
3829
+ this.provider = provider;
3830
+ this.transport = transport;
3831
+ this.supported = supported;
3832
+ }
3833
+ };
3834
+ function normalizeSessionTransportValue(value) {
3835
+ return value.trim().toLowerCase().replace(/-/g, "_");
3836
+ }
3837
+ function validateSessionTransport(provider, transport) {
3838
+ const normalizedProvider = normalizeSessionTransportValue(provider);
3839
+ const normalizedTransport = normalizeSessionTransportValue(transport);
3840
+ if (!normalizedProvider) {
3841
+ throw new Error("Session provider is required; AgentField does not infer providers.");
3842
+ }
3843
+ if (!normalizedTransport) {
3844
+ throw new Error("Session transport is required; AgentField does not infer transports.");
3845
+ }
3846
+ const supported = SUPPORTED_SESSION_TRANSPORTS[normalizedProvider];
3847
+ if (!supported) {
3848
+ const known = Object.keys(SUPPORTED_SESSION_TRANSPORTS).sort().join(", ");
3849
+ throw new Error(
3850
+ `Unknown session provider '${provider}'. Known providers: ${known}. Register provider capabilities before using a custom session provider.`
3851
+ );
3852
+ }
3853
+ if (!supported.includes(normalizedTransport)) {
3854
+ throw new SessionTransportError(normalizedProvider, normalizedTransport, supported);
3855
+ }
3856
+ return {
3857
+ provider: normalizedProvider,
3858
+ transport: normalizedTransport
3859
+ };
3860
+ }
3861
+
3862
+ // src/session.ts
3863
+ var RealtimeSession = class {
3864
+ sessionId;
3865
+ definition;
3866
+ constructor(sessionId, definition) {
3867
+ this.sessionId = sessionId;
3868
+ this.definition = definition;
3869
+ }
3870
+ async input() {
3871
+ throw new Error("session.input() is populated by the AgentField control plane transport adapter");
3872
+ }
3873
+ };
3874
+ function buildSessionDefinition(name, options) {
3875
+ const capability = validateSessionTransport(options.provider, options.transport);
3876
+ return {
3877
+ name,
3878
+ provider: capability.provider,
3879
+ transport: capability.transport,
3880
+ model: options.model,
3881
+ modalities: options.modalities ?? ["audio", "text"],
3882
+ voice: options.voice,
3883
+ tools: options.tools ?? [],
3884
+ tags: options.tags ?? [],
3885
+ proposed_tags: options.tags ?? [],
3886
+ approved_tags: [],
3887
+ metadata: options.metadata ?? {}
3888
+ };
3889
+ }
3890
+
3672
3891
  // src/agent/Agent.ts
3673
3892
  var TargetNotFoundError = class extends Error {
3674
3893
  };
@@ -3705,6 +3924,7 @@ var Agent = class {
3705
3924
  memoryWatchers = [];
3706
3925
  localVerifier;
3707
3926
  realtimeValidationFunctions = /* @__PURE__ */ new Set();
3927
+ sessions = /* @__PURE__ */ new Map();
3708
3928
  processLogRing = new ProcessLogRing();
3709
3929
  executionLogger;
3710
3930
  /** Tracks an AbortController per in-flight execution_id so the
@@ -3769,6 +3989,13 @@ var Agent = class {
3769
3989
  this.reasoners.includeRouter(router);
3770
3990
  this.skills.includeRouter(router);
3771
3991
  }
3992
+ session(name, options, handler) {
3993
+ this.sessions.set(name, { definition: buildSessionDefinition(name, options), handler });
3994
+ return this;
3995
+ }
3996
+ sessionDefinitions() {
3997
+ return Array.from(this.sessions.values()).map((entry) => entry.definition);
3998
+ }
3772
3999
  handler(adapter) {
3773
4000
  return async (event, res) => {
3774
4001
  if (res && typeof res === "object" && typeof res.setHeader === "function") {
@@ -4565,7 +4792,8 @@ var Agent = class {
4565
4792
  version: this.config.version,
4566
4793
  deployment_type: deploymentType,
4567
4794
  reasoners: this.reasonerDefinitions(),
4568
- skills: this.skillDefinitions()
4795
+ skills: this.skillDefinitions(),
4796
+ sessions: this.sessionDefinitions()
4569
4797
  };
4570
4798
  }
4571
4799
  async executeInvocation(params) {
@@ -4850,7 +5078,8 @@ var Agent = class {
4850
5078
  sdk: {
4851
5079
  language: "typescript",
4852
5080
  version: AGENTFIELD_TS_SDK_VERSION
4853
- }
5081
+ },
5082
+ sessions: this.sessionDefinitions()
4854
5083
  }
4855
5084
  }
4856
5085
  });
@@ -5644,6 +5873,7 @@ var MediaRouter = class {
5644
5873
  };
5645
5874
 
5646
5875
  // src/ai/OpenRouterMediaProvider.ts
5876
+ init_openrouterAttribution();
5647
5877
  var OPENROUTER_BASE = "https://openrouter.ai/api/v1";
5648
5878
  var DEFAULT_POLL_INTERVAL = 3e4;
5649
5879
  var DEFAULT_TIMEOUT = 6e5;
@@ -5735,9 +5965,14 @@ var OpenRouterMediaProvider = class {
5735
5965
  name = "openrouter";
5736
5966
  supportedModalities = ["image", "audio", "video"];
5737
5967
  baseUrl;
5968
+ attributionHeaders;
5738
5969
  constructor(options = {}) {
5739
5970
  const key = options.apiKey ?? process.env.OPENROUTER_API_KEY ?? "";
5740
5971
  this.baseUrl = options.baseUrl ?? OPENROUTER_BASE;
5972
+ this.attributionHeaders = mergeOpenRouterAttributionHeaders(options.openRouterHeaders, {
5973
+ siteUrl: options.openRouterSiteUrl,
5974
+ appName: options.openRouterAppName
5975
+ });
5741
5976
  if (!key) {
5742
5977
  throw new MediaProviderError("OpenRouter API key required: pass apiKey or set OPENROUTER_API_KEY", {
5743
5978
  provider: "openrouter"
@@ -5897,7 +6132,10 @@ var OpenRouterMediaProvider = class {
5897
6132
  } catch {
5898
6133
  }
5899
6134
  const dlRes = await fetch(videoUrl, {
5900
- headers: downloadHeaders,
6135
+ headers: mergeOpenRouterAttributionHeaders({
6136
+ ...this.attributionHeaders,
6137
+ ...downloadHeaders
6138
+ }),
5901
6139
  signal: AbortSignal.timeout(DOWNLOAD_TIMEOUT),
5902
6140
  redirect: "error"
5903
6141
  });
@@ -6189,10 +6427,11 @@ var OpenRouterMediaProvider = class {
6189
6427
  const key = apiKeyStore.get(this);
6190
6428
  return fetch(url, {
6191
6429
  method: "POST",
6192
- headers: {
6430
+ headers: mergeOpenRouterAttributionHeaders({
6431
+ ...this.attributionHeaders,
6193
6432
  "Content-Type": "application/json",
6194
6433
  Authorization: `Bearer ${key}`
6195
- },
6434
+ }),
6196
6435
  body: JSON.stringify(body),
6197
6436
  signal: AbortSignal.timeout(API_TIMEOUT)
6198
6437
  });
@@ -6201,9 +6440,10 @@ var OpenRouterMediaProvider = class {
6201
6440
  const key = apiKeyStore.get(this);
6202
6441
  return fetch(url, {
6203
6442
  method: "GET",
6204
- headers: {
6443
+ headers: mergeOpenRouterAttributionHeaders({
6444
+ ...this.attributionHeaders,
6205
6445
  Authorization: `Bearer ${key}`
6206
- },
6446
+ }),
6207
6447
  signal: AbortSignal.timeout(API_TIMEOUT)
6208
6448
  });
6209
6449
  }
@@ -6378,6 +6618,6 @@ function sleep2(ms) {
6378
6618
  return new Promise((resolve2) => setTimeout(resolve2, ms));
6379
6619
  }
6380
6620
 
6381
- export { ACTIVE_STATUSES, AIClient, Agent, AgentRouter, ApprovalClient, Audio, CANONICAL_STATUSES, DIDAuthenticator, DidClient, DidInterface, DidManager, ExecutionContext, ExecutionLogger, ExecutionStatus, File, HEADER_CALLER_DID, HEADER_DID_NONCE, HEADER_DID_SIGNATURE, HEADER_DID_TIMESTAMP, HarnessRunner, Image, MediaProviderError, MediaRouter, MemoryClient, MemoryClientBase, MemoryEventClient, MemoryInterface, MultimodalResponse, OpenRouterMediaProvider, RateLimitError, ReasonerContext, SUPPORTED_PROVIDERS, SkillContext, StatelessRateLimiter, TERMINAL_STATUSES, Text, Video, WorkflowReporter, audioFromBase64, audioFromBuffer, audioFromFile, audioFromUrl, buildProvider, buildToolConfig, capabilitiesToTools, capabilityToMetadataTool, capabilityToTool, createExecutionLogger, createHarnessResult, createMetrics, createMultimodalResponse, createRawResult, executeToolCallLoop, fileFromBase64, fileFromBuffer, fileFromPath, fileFromUrl, getCurrentContext, getCurrentSkillContext, imageFromBase64, imageFromBuffer, imageFromFile, imageFromUrl, isActive, isExecutionLogBatchPayload, isTerminal, normalizeExecutionLogEntry, normalizeStatus, serializeExecutionLogEntry, text, videoFromBase64, videoFromBuffer, videoFromFile, videoFromUrl };
6621
+ export { ACTIVE_STATUSES, AIClient, Agent, AgentRouter, ApprovalClient, Audio, CANONICAL_STATUSES, DIDAuthenticator, DidClient, DidInterface, DidManager, ExecutionContext, ExecutionLogger, ExecutionStatus, File, HEADER_CALLER_DID, HEADER_DID_NONCE, HEADER_DID_SIGNATURE, HEADER_DID_TIMESTAMP, HarnessRunner, Image, MediaProviderError, MediaRouter, MemoryClient, MemoryClientBase, MemoryEventClient, MemoryInterface, MultimodalResponse, OpenRouterMediaProvider, RateLimitError, RealtimeSession, ReasonerContext, SUPPORTED_PROVIDERS, SUPPORTED_SESSION_TRANSPORTS, SessionTransportError, SkillContext, StatelessRateLimiter, TERMINAL_STATUSES, Text, Video, WorkflowReporter, audioFromBase64, audioFromBuffer, audioFromFile, audioFromUrl, buildProvider, buildSessionDefinition, buildToolConfig, capabilitiesToTools, capabilityToMetadataTool, capabilityToTool, createExecutionLogger, createHarnessResult, createMetrics, createMultimodalResponse, createRawResult, executeToolCallLoop, fileFromBase64, fileFromBuffer, fileFromPath, fileFromUrl, getCurrentContext, getCurrentSkillContext, imageFromBase64, imageFromBuffer, imageFromFile, imageFromUrl, isActive, isExecutionLogBatchPayload, isTerminal, normalizeExecutionLogEntry, normalizeSessionTransportValue, normalizeStatus, serializeExecutionLogEntry, text, validateSessionTransport, videoFromBase64, videoFromBuffer, videoFromFile, videoFromUrl };
6382
6622
  //# sourceMappingURL=index.js.map
6383
6623
  //# sourceMappingURL=index.js.map