@agentfield/sdk 0.1.70-rc.1 → 0.1.70-rc.3
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 +133 -1
- package/dist/index.js +377 -3
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -1569,6 +1569,138 @@ declare class MultimodalResponse {
|
|
|
1569
1569
|
*/
|
|
1570
1570
|
declare function createMultimodalResponse(rawResponse: unknown, text?: string): MultimodalResponse;
|
|
1571
1571
|
|
|
1572
|
+
/**
|
|
1573
|
+
* MediaProvider interface and MediaRouter for multi-provider media generation.
|
|
1574
|
+
* Mirrors the Python SDK's MediaProvider abstraction.
|
|
1575
|
+
*/
|
|
1576
|
+
/** Custom error class for media provider failures with structured context. */
|
|
1577
|
+
declare class MediaProviderError extends Error {
|
|
1578
|
+
readonly provider?: string;
|
|
1579
|
+
readonly model?: string;
|
|
1580
|
+
readonly endpoint?: string;
|
|
1581
|
+
constructor(message: string, options?: {
|
|
1582
|
+
provider?: string;
|
|
1583
|
+
model?: string;
|
|
1584
|
+
endpoint?: string;
|
|
1585
|
+
cause?: unknown;
|
|
1586
|
+
});
|
|
1587
|
+
}
|
|
1588
|
+
interface VideoRequest {
|
|
1589
|
+
prompt: string;
|
|
1590
|
+
model?: string;
|
|
1591
|
+
duration?: number;
|
|
1592
|
+
resolution?: '480p' | '720p' | '1080p' | '1K' | '2K' | '4K';
|
|
1593
|
+
aspectRatio?: '16:9' | '9:16' | '1:1' | '4:3' | '3:4' | '21:9' | '9:21';
|
|
1594
|
+
generateAudio?: boolean;
|
|
1595
|
+
seed?: number;
|
|
1596
|
+
frameImages?: Array<{
|
|
1597
|
+
type: string;
|
|
1598
|
+
imageUrl: {
|
|
1599
|
+
url: string;
|
|
1600
|
+
};
|
|
1601
|
+
frameType?: string;
|
|
1602
|
+
}>;
|
|
1603
|
+
inputReferences?: Array<{
|
|
1604
|
+
type: string;
|
|
1605
|
+
imageUrl: {
|
|
1606
|
+
url: string;
|
|
1607
|
+
};
|
|
1608
|
+
}>;
|
|
1609
|
+
pollInterval?: number;
|
|
1610
|
+
timeout?: number;
|
|
1611
|
+
}
|
|
1612
|
+
interface ImageRequest {
|
|
1613
|
+
prompt: string;
|
|
1614
|
+
model?: string;
|
|
1615
|
+
size?: string;
|
|
1616
|
+
quality?: string;
|
|
1617
|
+
imageConfig?: {
|
|
1618
|
+
aspectRatio?: string;
|
|
1619
|
+
imageSize?: string;
|
|
1620
|
+
superResolutionReferences?: string[];
|
|
1621
|
+
fontInputs?: Array<{
|
|
1622
|
+
fontUrl: string;
|
|
1623
|
+
text: string;
|
|
1624
|
+
}>;
|
|
1625
|
+
};
|
|
1626
|
+
}
|
|
1627
|
+
interface AudioRequest {
|
|
1628
|
+
text: string;
|
|
1629
|
+
model?: string;
|
|
1630
|
+
voice?: string;
|
|
1631
|
+
format?: string;
|
|
1632
|
+
}
|
|
1633
|
+
interface MediaResponse {
|
|
1634
|
+
text: string;
|
|
1635
|
+
images: Array<{
|
|
1636
|
+
url?: string;
|
|
1637
|
+
b64Json?: string;
|
|
1638
|
+
revisedPrompt?: string;
|
|
1639
|
+
}>;
|
|
1640
|
+
audio: {
|
|
1641
|
+
data?: string;
|
|
1642
|
+
format: string;
|
|
1643
|
+
url?: string;
|
|
1644
|
+
} | null;
|
|
1645
|
+
files: Array<{
|
|
1646
|
+
url?: string;
|
|
1647
|
+
data?: string;
|
|
1648
|
+
mimeType?: string;
|
|
1649
|
+
filename?: string;
|
|
1650
|
+
}>;
|
|
1651
|
+
videos: Array<{
|
|
1652
|
+
url?: string;
|
|
1653
|
+
data?: string;
|
|
1654
|
+
mimeType?: string;
|
|
1655
|
+
filename?: string;
|
|
1656
|
+
duration?: number;
|
|
1657
|
+
resolution?: string;
|
|
1658
|
+
aspectRatio?: string;
|
|
1659
|
+
hasAudio?: boolean;
|
|
1660
|
+
costUsd?: number;
|
|
1661
|
+
}>;
|
|
1662
|
+
rawResponse: unknown;
|
|
1663
|
+
}
|
|
1664
|
+
interface MediaProvider {
|
|
1665
|
+
readonly name: string;
|
|
1666
|
+
readonly supportedModalities: string[];
|
|
1667
|
+
generateImage(request: ImageRequest): Promise<MediaResponse>;
|
|
1668
|
+
generateAudio(request: AudioRequest): Promise<MediaResponse>;
|
|
1669
|
+
generateVideo(request: VideoRequest): Promise<MediaResponse>;
|
|
1670
|
+
}
|
|
1671
|
+
/**
|
|
1672
|
+
* Prefix-based media provider router.
|
|
1673
|
+
* Resolves model strings to providers by longest-prefix match.
|
|
1674
|
+
*/
|
|
1675
|
+
declare class MediaRouter {
|
|
1676
|
+
private providers;
|
|
1677
|
+
register(prefix: string, provider: MediaProvider): void;
|
|
1678
|
+
resolve(model: string, capability: string): MediaProvider;
|
|
1679
|
+
}
|
|
1680
|
+
|
|
1681
|
+
/**
|
|
1682
|
+
* OpenRouter-backed MediaProvider implementation.
|
|
1683
|
+
* Supports video generation (async job), image generation, and audio generation via SSE.
|
|
1684
|
+
*/
|
|
1685
|
+
|
|
1686
|
+
interface OpenRouterMediaProviderOptions {
|
|
1687
|
+
apiKey?: string;
|
|
1688
|
+
baseUrl?: string;
|
|
1689
|
+
}
|
|
1690
|
+
declare class OpenRouterMediaProvider implements MediaProvider {
|
|
1691
|
+
readonly name = "openrouter";
|
|
1692
|
+
readonly supportedModalities: string[];
|
|
1693
|
+
private readonly baseUrl;
|
|
1694
|
+
constructor(options?: OpenRouterMediaProviderOptions);
|
|
1695
|
+
/** Prevent API key from leaking via JSON.stringify (CR-03). */
|
|
1696
|
+
toJSON(): Record<string, unknown>;
|
|
1697
|
+
generateVideo(request: VideoRequest): Promise<MediaResponse>;
|
|
1698
|
+
generateImage(request: ImageRequest): Promise<MediaResponse>;
|
|
1699
|
+
generateAudio(request: AudioRequest): Promise<MediaResponse>;
|
|
1700
|
+
private post;
|
|
1701
|
+
private get;
|
|
1702
|
+
}
|
|
1703
|
+
|
|
1572
1704
|
declare const SUPPORTED_PROVIDERS: Set<string>;
|
|
1573
1705
|
declare function buildProvider(config: HarnessConfig): Promise<HarnessProvider>;
|
|
1574
1706
|
|
|
@@ -1676,4 +1808,4 @@ declare class ApprovalClient {
|
|
|
1676
1808
|
waitForApproval(executionId: string, opts?: WaitForApprovalOptions): Promise<ApprovalStatusResponse>;
|
|
1677
1809
|
}
|
|
1678
1810
|
|
|
1679
|
-
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 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 MemoryChangeEvent, MemoryClient, MemoryClientBase, type MemoryConfig, MemoryEventClient, type MemoryEventHandler, type MemoryEventHistoryOptions, MemoryInterface, type MemoryRequestMetadata, type MemoryRequestOptions, type MemoryScope, type MemoryWatchHandler, type Metrics, type MultimodalContent, MultimodalResponse, 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, 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 };
|
|
1811
|
+
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, 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 };
|
package/dist/index.js
CHANGED
|
@@ -5382,6 +5382,380 @@ function extractSingleFile(data) {
|
|
|
5382
5382
|
return null;
|
|
5383
5383
|
}
|
|
5384
5384
|
|
|
5385
|
+
// src/ai/MediaProvider.ts
|
|
5386
|
+
var MediaProviderError = class extends Error {
|
|
5387
|
+
provider;
|
|
5388
|
+
model;
|
|
5389
|
+
endpoint;
|
|
5390
|
+
constructor(message, options) {
|
|
5391
|
+
super(message, options?.cause ? { cause: options.cause } : void 0);
|
|
5392
|
+
this.name = "MediaProviderError";
|
|
5393
|
+
this.provider = options?.provider;
|
|
5394
|
+
this.model = options?.model;
|
|
5395
|
+
this.endpoint = options?.endpoint;
|
|
5396
|
+
}
|
|
5397
|
+
};
|
|
5398
|
+
var MediaRouter = class {
|
|
5399
|
+
providers = [];
|
|
5400
|
+
register(prefix, provider) {
|
|
5401
|
+
this.providers.push({ prefix, provider });
|
|
5402
|
+
this.providers.sort((a, b) => b.prefix.length - a.prefix.length);
|
|
5403
|
+
}
|
|
5404
|
+
resolve(model, capability) {
|
|
5405
|
+
for (const { prefix, provider } of this.providers) {
|
|
5406
|
+
if (model.startsWith(prefix) && provider.supportedModalities.includes(capability)) {
|
|
5407
|
+
return provider;
|
|
5408
|
+
}
|
|
5409
|
+
}
|
|
5410
|
+
throw new MediaProviderError(
|
|
5411
|
+
`No provider for model '${model}' with '${capability}' capability`,
|
|
5412
|
+
{ model }
|
|
5413
|
+
);
|
|
5414
|
+
}
|
|
5415
|
+
};
|
|
5416
|
+
|
|
5417
|
+
// src/ai/OpenRouterMediaProvider.ts
|
|
5418
|
+
var OPENROUTER_BASE = "https://openrouter.ai/api/v1";
|
|
5419
|
+
var DEFAULT_POLL_INTERVAL = 3e4;
|
|
5420
|
+
var DEFAULT_TIMEOUT = 6e5;
|
|
5421
|
+
var API_TIMEOUT = 3e4;
|
|
5422
|
+
var DOWNLOAD_TIMEOUT = 12e4;
|
|
5423
|
+
var MAX_CONSECUTIVE_PARSE_ERRORS = 50;
|
|
5424
|
+
var apiKeyStore = /* @__PURE__ */ new WeakMap();
|
|
5425
|
+
function emptyMediaResponse(raw) {
|
|
5426
|
+
return { text: "", images: [], audio: null, files: [], videos: [], rawResponse: raw };
|
|
5427
|
+
}
|
|
5428
|
+
function stripPrefix(model) {
|
|
5429
|
+
return model.startsWith("openrouter/") ? model.slice("openrouter/".length) : model;
|
|
5430
|
+
}
|
|
5431
|
+
function assertSafeUrl(urlStr) {
|
|
5432
|
+
let parsed;
|
|
5433
|
+
try {
|
|
5434
|
+
parsed = new URL(urlStr);
|
|
5435
|
+
} catch {
|
|
5436
|
+
throw new MediaProviderError(`Invalid download URL: ${urlStr}`);
|
|
5437
|
+
}
|
|
5438
|
+
if (parsed.protocol !== "https:") {
|
|
5439
|
+
throw new MediaProviderError(
|
|
5440
|
+
`Refusing to download from non-HTTPS URL: ${urlStr}`
|
|
5441
|
+
);
|
|
5442
|
+
}
|
|
5443
|
+
const host = parsed.hostname.toLowerCase();
|
|
5444
|
+
if (host === "localhost" || host === "127.0.0.1" || host === "[::1]" || host === "::1" || host === "0.0.0.0") {
|
|
5445
|
+
throw new MediaProviderError(`Refusing to download from localhost: ${urlStr}`);
|
|
5446
|
+
}
|
|
5447
|
+
const ipv4Match = host.match(/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/);
|
|
5448
|
+
if (ipv4Match) {
|
|
5449
|
+
const [, a, b] = ipv4Match.map(Number);
|
|
5450
|
+
if (a === 10 || a === 172 && b >= 16 && b <= 31 || a === 192 && b === 168 || a === 169 && b === 254 || a === 0) {
|
|
5451
|
+
throw new MediaProviderError(
|
|
5452
|
+
`Refusing to download from private IP: ${urlStr}`
|
|
5453
|
+
);
|
|
5454
|
+
}
|
|
5455
|
+
}
|
|
5456
|
+
}
|
|
5457
|
+
var OpenRouterMediaProvider = class {
|
|
5458
|
+
name = "openrouter";
|
|
5459
|
+
supportedModalities = ["image", "audio", "video"];
|
|
5460
|
+
baseUrl;
|
|
5461
|
+
constructor(options = {}) {
|
|
5462
|
+
const key = options.apiKey ?? process.env.OPENROUTER_API_KEY ?? "";
|
|
5463
|
+
this.baseUrl = options.baseUrl ?? OPENROUTER_BASE;
|
|
5464
|
+
if (!key) {
|
|
5465
|
+
throw new MediaProviderError("OpenRouter API key required: pass apiKey or set OPENROUTER_API_KEY", {
|
|
5466
|
+
provider: "openrouter"
|
|
5467
|
+
});
|
|
5468
|
+
}
|
|
5469
|
+
apiKeyStore.set(this, key);
|
|
5470
|
+
}
|
|
5471
|
+
/** Prevent API key from leaking via JSON.stringify (CR-03). */
|
|
5472
|
+
toJSON() {
|
|
5473
|
+
return {
|
|
5474
|
+
name: this.name,
|
|
5475
|
+
supportedModalities: this.supportedModalities,
|
|
5476
|
+
baseUrl: this.baseUrl
|
|
5477
|
+
};
|
|
5478
|
+
}
|
|
5479
|
+
// ── Video ──────────────────────────────────────────────────────────
|
|
5480
|
+
async generateVideo(request) {
|
|
5481
|
+
const model = stripPrefix(request.model ?? "google/veo-3");
|
|
5482
|
+
const pollInterval = request.pollInterval ?? DEFAULT_POLL_INTERVAL;
|
|
5483
|
+
const timeout = request.timeout ?? DEFAULT_TIMEOUT;
|
|
5484
|
+
const body = {
|
|
5485
|
+
model,
|
|
5486
|
+
prompt: request.prompt
|
|
5487
|
+
};
|
|
5488
|
+
if (request.duration != null) body.duration = request.duration;
|
|
5489
|
+
if (request.resolution) body.resolution = request.resolution;
|
|
5490
|
+
if (request.aspectRatio) body.aspect_ratio = request.aspectRatio;
|
|
5491
|
+
if (request.generateAudio != null) body.generate_audio = request.generateAudio;
|
|
5492
|
+
if (request.seed != null) body.seed = request.seed;
|
|
5493
|
+
if (request.frameImages) body.frame_images = request.frameImages;
|
|
5494
|
+
if (request.inputReferences) body.input_references = request.inputReferences;
|
|
5495
|
+
const submitEndpoint = `${this.baseUrl}/videos`;
|
|
5496
|
+
const submitRes = await this.post(submitEndpoint, body);
|
|
5497
|
+
if (!submitRes.ok) {
|
|
5498
|
+
throw new MediaProviderError(
|
|
5499
|
+
`Video submit failed [model=${model}] [endpoint=${submitEndpoint}]: ${submitRes.status} ${await submitRes.text()}`,
|
|
5500
|
+
{ provider: "openrouter", model, endpoint: submitEndpoint }
|
|
5501
|
+
);
|
|
5502
|
+
}
|
|
5503
|
+
const submitData = await submitRes.json();
|
|
5504
|
+
const jobId = submitData.id;
|
|
5505
|
+
if (!jobId) {
|
|
5506
|
+
throw new MediaProviderError("No job id returned from video submit", {
|
|
5507
|
+
provider: "openrouter",
|
|
5508
|
+
model,
|
|
5509
|
+
endpoint: submitEndpoint
|
|
5510
|
+
});
|
|
5511
|
+
}
|
|
5512
|
+
const deadline = Date.now() + timeout;
|
|
5513
|
+
let jobData = {};
|
|
5514
|
+
const pollEndpoint = `${this.baseUrl}/videos/${jobId}`;
|
|
5515
|
+
while (true) {
|
|
5516
|
+
const remaining = deadline - Date.now();
|
|
5517
|
+
if (remaining <= 0) break;
|
|
5518
|
+
await sleep(Math.min(pollInterval, remaining));
|
|
5519
|
+
if (Date.now() >= deadline) break;
|
|
5520
|
+
const pollRes = await this.get(pollEndpoint);
|
|
5521
|
+
if (!pollRes.ok) {
|
|
5522
|
+
throw new MediaProviderError(
|
|
5523
|
+
`Video poll failed [model=${model}] [endpoint=${pollEndpoint}]: ${pollRes.status} ${await pollRes.text()}`,
|
|
5524
|
+
{ provider: "openrouter", model, endpoint: pollEndpoint }
|
|
5525
|
+
);
|
|
5526
|
+
}
|
|
5527
|
+
jobData = await pollRes.json();
|
|
5528
|
+
const status = jobData.status;
|
|
5529
|
+
if (status === "completed") break;
|
|
5530
|
+
if (status === "failed" || status === "error") {
|
|
5531
|
+
throw new MediaProviderError(
|
|
5532
|
+
`Video generation failed [model=${model}]: ${JSON.stringify(jobData)}`,
|
|
5533
|
+
{ provider: "openrouter", model }
|
|
5534
|
+
);
|
|
5535
|
+
}
|
|
5536
|
+
}
|
|
5537
|
+
if (jobData.status !== "completed") {
|
|
5538
|
+
throw new MediaProviderError(
|
|
5539
|
+
`Video generation timed out [model=${model}] after ${timeout}ms`,
|
|
5540
|
+
{ provider: "openrouter", model }
|
|
5541
|
+
);
|
|
5542
|
+
}
|
|
5543
|
+
const unsignedUrl = jobData.unsigned_url;
|
|
5544
|
+
const signedUrl = jobData.url;
|
|
5545
|
+
const videoUrl = unsignedUrl ?? signedUrl;
|
|
5546
|
+
let videoData;
|
|
5547
|
+
if (videoUrl) {
|
|
5548
|
+
assertSafeUrl(videoUrl);
|
|
5549
|
+
const dlRes = await fetch(videoUrl, {
|
|
5550
|
+
signal: AbortSignal.timeout(DOWNLOAD_TIMEOUT),
|
|
5551
|
+
redirect: "error"
|
|
5552
|
+
});
|
|
5553
|
+
if (dlRes.ok) {
|
|
5554
|
+
const buf = Buffer.from(await dlRes.arrayBuffer());
|
|
5555
|
+
videoData = buf.toString("base64");
|
|
5556
|
+
}
|
|
5557
|
+
}
|
|
5558
|
+
const resp = emptyMediaResponse(jobData);
|
|
5559
|
+
resp.videos.push({
|
|
5560
|
+
url: videoUrl,
|
|
5561
|
+
data: videoData,
|
|
5562
|
+
mimeType: "video/mp4",
|
|
5563
|
+
duration: request.duration,
|
|
5564
|
+
resolution: request.resolution,
|
|
5565
|
+
aspectRatio: request.aspectRatio,
|
|
5566
|
+
hasAudio: request.generateAudio,
|
|
5567
|
+
costUsd: jobData.cost_usd
|
|
5568
|
+
});
|
|
5569
|
+
return resp;
|
|
5570
|
+
}
|
|
5571
|
+
// ── Image ──────────────────────────────────────────────────────────
|
|
5572
|
+
async generateImage(request) {
|
|
5573
|
+
const model = stripPrefix(request.model ?? "openai/gpt-image-1");
|
|
5574
|
+
const messages = [{ role: "user", content: request.prompt }];
|
|
5575
|
+
const body = {
|
|
5576
|
+
model,
|
|
5577
|
+
messages,
|
|
5578
|
+
modalities: ["image", "text"]
|
|
5579
|
+
};
|
|
5580
|
+
if (request.size) body.size = request.size;
|
|
5581
|
+
if (request.quality) body.quality = request.quality;
|
|
5582
|
+
if (request.imageConfig) body.image_config = request.imageConfig;
|
|
5583
|
+
const endpoint = `${this.baseUrl}/chat/completions`;
|
|
5584
|
+
const res = await this.post(endpoint, body);
|
|
5585
|
+
if (!res.ok) {
|
|
5586
|
+
throw new MediaProviderError(
|
|
5587
|
+
`Image generation failed [model=${model}] [endpoint=${endpoint}]: ${res.status} ${await res.text()}`,
|
|
5588
|
+
{ provider: "openrouter", model, endpoint }
|
|
5589
|
+
);
|
|
5590
|
+
}
|
|
5591
|
+
const data = await res.json();
|
|
5592
|
+
const resp = emptyMediaResponse(data);
|
|
5593
|
+
const choices = data.choices;
|
|
5594
|
+
if (choices) {
|
|
5595
|
+
for (const choice of choices) {
|
|
5596
|
+
const msg = choice.message;
|
|
5597
|
+
if (!msg) continue;
|
|
5598
|
+
if (typeof msg.content === "string") {
|
|
5599
|
+
resp.text += msg.content;
|
|
5600
|
+
}
|
|
5601
|
+
if (Array.isArray(msg.content)) {
|
|
5602
|
+
for (const part of msg.content) {
|
|
5603
|
+
const p = part;
|
|
5604
|
+
if (p.type === "text") {
|
|
5605
|
+
resp.text += p.text;
|
|
5606
|
+
} else if (p.type === "image_url") {
|
|
5607
|
+
const imgUrl = p.image_url;
|
|
5608
|
+
const url = imgUrl?.url;
|
|
5609
|
+
if (url?.startsWith("data:")) {
|
|
5610
|
+
const b64 = url.split(",", 2)[1];
|
|
5611
|
+
resp.images.push({ url, b64Json: b64 });
|
|
5612
|
+
} else if (url) {
|
|
5613
|
+
resp.images.push({ url });
|
|
5614
|
+
}
|
|
5615
|
+
}
|
|
5616
|
+
}
|
|
5617
|
+
}
|
|
5618
|
+
}
|
|
5619
|
+
}
|
|
5620
|
+
return resp;
|
|
5621
|
+
}
|
|
5622
|
+
// ── Audio ──────────────────────────────────────────────────────────
|
|
5623
|
+
async generateAudio(request) {
|
|
5624
|
+
const model = stripPrefix(request.model ?? "openai/gpt-4o-mini-tts");
|
|
5625
|
+
const messages = [{ role: "user", content: request.text }];
|
|
5626
|
+
const body = {
|
|
5627
|
+
model,
|
|
5628
|
+
messages,
|
|
5629
|
+
modalities: ["text", "audio"],
|
|
5630
|
+
stream: true,
|
|
5631
|
+
audio: {
|
|
5632
|
+
voice: request.voice ?? "alloy",
|
|
5633
|
+
format: request.format ?? "wav"
|
|
5634
|
+
}
|
|
5635
|
+
};
|
|
5636
|
+
const endpoint = `${this.baseUrl}/chat/completions`;
|
|
5637
|
+
const res = await this.post(endpoint, body);
|
|
5638
|
+
if (!res.ok) {
|
|
5639
|
+
throw new MediaProviderError(
|
|
5640
|
+
`Audio generation failed [model=${model}] [endpoint=${endpoint}]: ${res.status} ${await res.text()}`,
|
|
5641
|
+
{ provider: "openrouter", model, endpoint }
|
|
5642
|
+
);
|
|
5643
|
+
}
|
|
5644
|
+
const audioChunks = [];
|
|
5645
|
+
let textContent = "";
|
|
5646
|
+
const reader = res.body?.getReader();
|
|
5647
|
+
if (!reader) {
|
|
5648
|
+
throw new MediaProviderError("No response body stream available", {
|
|
5649
|
+
provider: "openrouter",
|
|
5650
|
+
model,
|
|
5651
|
+
endpoint
|
|
5652
|
+
});
|
|
5653
|
+
}
|
|
5654
|
+
const decoder = new TextDecoder();
|
|
5655
|
+
let buffer = "";
|
|
5656
|
+
let consecutiveParseErrors = 0;
|
|
5657
|
+
while (true) {
|
|
5658
|
+
const { done, value } = await reader.read();
|
|
5659
|
+
if (done) break;
|
|
5660
|
+
buffer += decoder.decode(value, { stream: true });
|
|
5661
|
+
const lines = buffer.split("\n");
|
|
5662
|
+
buffer = lines.pop() ?? "";
|
|
5663
|
+
for (const line of lines) {
|
|
5664
|
+
const trimmed = line.trim();
|
|
5665
|
+
if (!trimmed.startsWith("data:")) continue;
|
|
5666
|
+
const payload = trimmed.slice(5).trim();
|
|
5667
|
+
if (payload === "[DONE]") continue;
|
|
5668
|
+
try {
|
|
5669
|
+
const chunk = JSON.parse(payload);
|
|
5670
|
+
consecutiveParseErrors = 0;
|
|
5671
|
+
const choices = chunk.choices;
|
|
5672
|
+
if (!choices) continue;
|
|
5673
|
+
for (const choice of choices) {
|
|
5674
|
+
const delta = choice.delta;
|
|
5675
|
+
if (!delta) continue;
|
|
5676
|
+
if (typeof delta.content === "string") {
|
|
5677
|
+
textContent += delta.content;
|
|
5678
|
+
}
|
|
5679
|
+
const audioDelta = delta.audio;
|
|
5680
|
+
if (audioDelta?.data) {
|
|
5681
|
+
audioChunks.push(audioDelta.data);
|
|
5682
|
+
}
|
|
5683
|
+
}
|
|
5684
|
+
} catch {
|
|
5685
|
+
consecutiveParseErrors++;
|
|
5686
|
+
if (consecutiveParseErrors > MAX_CONSECUTIVE_PARSE_ERRORS) {
|
|
5687
|
+
throw new MediaProviderError(
|
|
5688
|
+
`Too many consecutive SSE parse errors (>${MAX_CONSECUTIVE_PARSE_ERRORS}) [model=${model}]`,
|
|
5689
|
+
{ provider: "openrouter", model, endpoint }
|
|
5690
|
+
);
|
|
5691
|
+
}
|
|
5692
|
+
}
|
|
5693
|
+
}
|
|
5694
|
+
}
|
|
5695
|
+
if (buffer.trim()) {
|
|
5696
|
+
const remaining = buffer.trim();
|
|
5697
|
+
if (remaining.startsWith("data:")) {
|
|
5698
|
+
const payload = remaining.slice(5).trim();
|
|
5699
|
+
if (payload && payload !== "[DONE]") {
|
|
5700
|
+
try {
|
|
5701
|
+
const chunk = JSON.parse(payload);
|
|
5702
|
+
const choices = chunk.choices;
|
|
5703
|
+
if (choices) {
|
|
5704
|
+
for (const choice of choices) {
|
|
5705
|
+
const delta = choice.delta;
|
|
5706
|
+
if (!delta) continue;
|
|
5707
|
+
if (typeof delta.content === "string") {
|
|
5708
|
+
textContent += delta.content;
|
|
5709
|
+
}
|
|
5710
|
+
const audioDelta = delta.audio;
|
|
5711
|
+
if (audioDelta?.data) {
|
|
5712
|
+
audioChunks.push(audioDelta.data);
|
|
5713
|
+
}
|
|
5714
|
+
}
|
|
5715
|
+
}
|
|
5716
|
+
} catch {
|
|
5717
|
+
}
|
|
5718
|
+
}
|
|
5719
|
+
}
|
|
5720
|
+
}
|
|
5721
|
+
const resp = emptyMediaResponse(null);
|
|
5722
|
+
resp.text = textContent;
|
|
5723
|
+
if (audioChunks.length > 0) {
|
|
5724
|
+
resp.audio = {
|
|
5725
|
+
data: audioChunks.join(""),
|
|
5726
|
+
format: request.format ?? "wav"
|
|
5727
|
+
};
|
|
5728
|
+
}
|
|
5729
|
+
return resp;
|
|
5730
|
+
}
|
|
5731
|
+
// ── Helpers ────────────────────────────────────────────────────────
|
|
5732
|
+
post(url, body) {
|
|
5733
|
+
const key = apiKeyStore.get(this);
|
|
5734
|
+
return fetch(url, {
|
|
5735
|
+
method: "POST",
|
|
5736
|
+
headers: {
|
|
5737
|
+
"Content-Type": "application/json",
|
|
5738
|
+
Authorization: `Bearer ${key}`
|
|
5739
|
+
},
|
|
5740
|
+
body: JSON.stringify(body),
|
|
5741
|
+
signal: AbortSignal.timeout(API_TIMEOUT)
|
|
5742
|
+
});
|
|
5743
|
+
}
|
|
5744
|
+
get(url) {
|
|
5745
|
+
const key = apiKeyStore.get(this);
|
|
5746
|
+
return fetch(url, {
|
|
5747
|
+
method: "GET",
|
|
5748
|
+
headers: {
|
|
5749
|
+
Authorization: `Bearer ${key}`
|
|
5750
|
+
},
|
|
5751
|
+
signal: AbortSignal.timeout(API_TIMEOUT)
|
|
5752
|
+
});
|
|
5753
|
+
}
|
|
5754
|
+
};
|
|
5755
|
+
function sleep(ms) {
|
|
5756
|
+
return new Promise((resolve2) => setTimeout(resolve2, ms));
|
|
5757
|
+
}
|
|
5758
|
+
|
|
5385
5759
|
// src/harness/index.ts
|
|
5386
5760
|
init_types();
|
|
5387
5761
|
init_factory();
|
|
@@ -5527,7 +5901,7 @@ var ApprovalClient = class {
|
|
|
5527
5901
|
`Approval for execution ${executionId} timed out after ${timeout}ms`
|
|
5528
5902
|
);
|
|
5529
5903
|
}
|
|
5530
|
-
await
|
|
5904
|
+
await sleep2(interval);
|
|
5531
5905
|
let data;
|
|
5532
5906
|
try {
|
|
5533
5907
|
data = await this.getApprovalStatus(executionId);
|
|
@@ -5542,10 +5916,10 @@ var ApprovalClient = class {
|
|
|
5542
5916
|
}
|
|
5543
5917
|
}
|
|
5544
5918
|
};
|
|
5545
|
-
function
|
|
5919
|
+
function sleep2(ms) {
|
|
5546
5920
|
return new Promise((resolve2) => setTimeout(resolve2, ms));
|
|
5547
5921
|
}
|
|
5548
5922
|
|
|
5549
|
-
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, MemoryClient, MemoryClientBase, MemoryEventClient, MemoryInterface, MultimodalResponse, RateLimitError, ReasonerContext, SUPPORTED_PROVIDERS, SkillContext, StatelessRateLimiter, TERMINAL_STATUSES, Text, 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 };
|
|
5923
|
+
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, 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 };
|
|
5550
5924
|
//# sourceMappingURL=index.js.map
|
|
5551
5925
|
//# sourceMappingURL=index.js.map
|