@x12i/openrouter-runtime 1.0.5 → 1.1.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/index.d.cts CHANGED
@@ -3,7 +3,12 @@ type ResolvedApiMode = "chat" | "responses";
3
3
  type ToolMode = "disabled" | "allowed" | "required";
4
4
  interface OpenRouterRuntime {
5
5
  run(request: RuntimeRequest): Promise<RuntimeResponse>;
6
- stream?(request: RuntimeRequest): AsyncIterable<RuntimeStreamEvent>;
6
+ /**
7
+ * Explicit streaming chat API. Separate from `run()` by design — never an argument, never the default.
8
+ * Always sends OpenRouter Chat Completions with `stream: true` and yields typed SSE events.
9
+ * The old `stream()` name was removed so mistaken/old clients break loudly.
10
+ */
11
+ executeStreamingChat(request: RuntimeRequest): AsyncIterable<RuntimeStreamEvent>;
7
12
  }
8
13
  interface OpenRouterRuntimeOptions {
9
14
  apiKey?: string;
@@ -360,9 +365,60 @@ interface RuntimePolicyViolation {
360
365
  details?: unknown;
361
366
  }
362
367
  interface RuntimeStreamEvent {
363
- type: string;
368
+ type: RuntimeStreamEventType;
369
+ requestId: string;
364
370
  data?: unknown;
365
371
  }
372
+ type RuntimeStreamEventType = "stream.start" | "stream.text.delta" | "stream.tool_call.delta" | "stream.usage" | "stream.warning" | "stream.error" | "stream.done";
373
+ interface RuntimeStreamStartEvent extends RuntimeStreamEvent {
374
+ type: "stream.start";
375
+ data: {
376
+ model: string;
377
+ apiMode: "chat";
378
+ entrypoint: "executeStreamingChat";
379
+ };
380
+ }
381
+ interface RuntimeStreamTextDeltaEvent extends RuntimeStreamEvent {
382
+ type: "stream.text.delta";
383
+ data: {
384
+ text: string;
385
+ };
386
+ }
387
+ interface RuntimeStreamToolCallDeltaEvent extends RuntimeStreamEvent {
388
+ type: "stream.tool_call.delta";
389
+ data: {
390
+ index: number;
391
+ id?: string;
392
+ name?: string;
393
+ argumentsDelta?: string;
394
+ };
395
+ }
396
+ interface RuntimeStreamUsageEvent extends RuntimeStreamEvent {
397
+ type: "stream.usage";
398
+ data: {
399
+ usage: RuntimeUsage;
400
+ };
401
+ }
402
+ interface RuntimeStreamWarningEvent extends RuntimeStreamEvent {
403
+ type: "stream.warning";
404
+ data: {
405
+ warning: RuntimeWarning;
406
+ };
407
+ }
408
+ interface RuntimeStreamErrorEvent extends RuntimeStreamEvent {
409
+ type: "stream.error";
410
+ data: {
411
+ error: RuntimeError;
412
+ };
413
+ }
414
+ interface RuntimeStreamDoneEvent extends RuntimeStreamEvent {
415
+ type: "stream.done";
416
+ data: {
417
+ text: string;
418
+ finishReason?: string;
419
+ model: string;
420
+ };
421
+ }
366
422
  type RuntimePatchApplier = (patch: RuntimePatchProposal) => Promise<unknown> | unknown;
367
423
 
368
424
  declare function createOpenRouterRuntime(options: OpenRouterRuntimeOptions): OpenRouterRuntime;
@@ -407,4 +463,7 @@ declare class OpenRouterHttpError extends Error {
407
463
 
408
464
  declare function buildOpenRouterServerTools(policy?: RuntimeServerToolsPolicy): OpenRouterTool[];
409
465
 
410
- export { type AdvisorPolicy, type ApplyPatchPolicy, type CompiledOpenRouterRequest, type DatetimePolicy, type FusionPolicy, type ImageGenerationPolicy, OpenRouterHttpError, type OpenRouterRuntime, type OpenRouterRuntimeOptions, type RuntimeCitation, RuntimeConfigError, type RuntimeDefaults, type RuntimeError, type RuntimeFunctionToolDefinition, type RuntimeGeneratedImage, type RuntimeMessage, type RuntimePatchProposal, type RuntimePolicyViolation, type RuntimeRequest, type RuntimeResponse, type RuntimeServerToolsPolicy, type RuntimeToolExecutor, type RuntimeToolUsage, type RuntimeUsage, type RuntimeWarning, type ServerToolKey, type ServerToolUsage, type SubagentPolicy, type WebFetchPolicy, type WebSearchPolicy, buildOpenRouterServerTools, compileRuntimeRequest, createOpenRouterRuntime };
466
+ declare function isRuntimeLoggingEnabled(env?: Record<string, string | undefined> | undefined): boolean;
467
+ declare function createConsoleLogger(): RuntimeLogger;
468
+
469
+ export { type AdvisorPolicy, type ApplyPatchPolicy, type CompiledOpenRouterRequest, type DatetimePolicy, type FusionPolicy, type ImageGenerationPolicy, OpenRouterHttpError, type OpenRouterRuntime, type OpenRouterRuntimeOptions, type RuntimeCitation, RuntimeConfigError, type RuntimeDefaults, type RuntimeError, type RuntimeFunctionToolDefinition, type RuntimeGeneratedImage, type RuntimeLogger, type RuntimeMessage, type RuntimePatchProposal, type RuntimePolicyViolation, type RuntimeRequest, type RuntimeResponse, type RuntimeServerToolsPolicy, type RuntimeStreamDoneEvent, type RuntimeStreamErrorEvent, type RuntimeStreamEvent, type RuntimeStreamEventType, type RuntimeStreamStartEvent, type RuntimeStreamTextDeltaEvent, type RuntimeStreamToolCallDeltaEvent, type RuntimeStreamUsageEvent, type RuntimeStreamWarningEvent, type RuntimeToolExecutor, type RuntimeToolUsage, type RuntimeUsage, type RuntimeWarning, type ServerToolKey, type ServerToolUsage, type SubagentPolicy, type WebFetchPolicy, type WebSearchPolicy, buildOpenRouterServerTools, compileRuntimeRequest, createConsoleLogger, createOpenRouterRuntime, isRuntimeLoggingEnabled };
package/dist/index.d.ts CHANGED
@@ -3,7 +3,12 @@ type ResolvedApiMode = "chat" | "responses";
3
3
  type ToolMode = "disabled" | "allowed" | "required";
4
4
  interface OpenRouterRuntime {
5
5
  run(request: RuntimeRequest): Promise<RuntimeResponse>;
6
- stream?(request: RuntimeRequest): AsyncIterable<RuntimeStreamEvent>;
6
+ /**
7
+ * Explicit streaming chat API. Separate from `run()` by design — never an argument, never the default.
8
+ * Always sends OpenRouter Chat Completions with `stream: true` and yields typed SSE events.
9
+ * The old `stream()` name was removed so mistaken/old clients break loudly.
10
+ */
11
+ executeStreamingChat(request: RuntimeRequest): AsyncIterable<RuntimeStreamEvent>;
7
12
  }
8
13
  interface OpenRouterRuntimeOptions {
9
14
  apiKey?: string;
@@ -360,9 +365,60 @@ interface RuntimePolicyViolation {
360
365
  details?: unknown;
361
366
  }
362
367
  interface RuntimeStreamEvent {
363
- type: string;
368
+ type: RuntimeStreamEventType;
369
+ requestId: string;
364
370
  data?: unknown;
365
371
  }
372
+ type RuntimeStreamEventType = "stream.start" | "stream.text.delta" | "stream.tool_call.delta" | "stream.usage" | "stream.warning" | "stream.error" | "stream.done";
373
+ interface RuntimeStreamStartEvent extends RuntimeStreamEvent {
374
+ type: "stream.start";
375
+ data: {
376
+ model: string;
377
+ apiMode: "chat";
378
+ entrypoint: "executeStreamingChat";
379
+ };
380
+ }
381
+ interface RuntimeStreamTextDeltaEvent extends RuntimeStreamEvent {
382
+ type: "stream.text.delta";
383
+ data: {
384
+ text: string;
385
+ };
386
+ }
387
+ interface RuntimeStreamToolCallDeltaEvent extends RuntimeStreamEvent {
388
+ type: "stream.tool_call.delta";
389
+ data: {
390
+ index: number;
391
+ id?: string;
392
+ name?: string;
393
+ argumentsDelta?: string;
394
+ };
395
+ }
396
+ interface RuntimeStreamUsageEvent extends RuntimeStreamEvent {
397
+ type: "stream.usage";
398
+ data: {
399
+ usage: RuntimeUsage;
400
+ };
401
+ }
402
+ interface RuntimeStreamWarningEvent extends RuntimeStreamEvent {
403
+ type: "stream.warning";
404
+ data: {
405
+ warning: RuntimeWarning;
406
+ };
407
+ }
408
+ interface RuntimeStreamErrorEvent extends RuntimeStreamEvent {
409
+ type: "stream.error";
410
+ data: {
411
+ error: RuntimeError;
412
+ };
413
+ }
414
+ interface RuntimeStreamDoneEvent extends RuntimeStreamEvent {
415
+ type: "stream.done";
416
+ data: {
417
+ text: string;
418
+ finishReason?: string;
419
+ model: string;
420
+ };
421
+ }
366
422
  type RuntimePatchApplier = (patch: RuntimePatchProposal) => Promise<unknown> | unknown;
367
423
 
368
424
  declare function createOpenRouterRuntime(options: OpenRouterRuntimeOptions): OpenRouterRuntime;
@@ -407,4 +463,7 @@ declare class OpenRouterHttpError extends Error {
407
463
 
408
464
  declare function buildOpenRouterServerTools(policy?: RuntimeServerToolsPolicy): OpenRouterTool[];
409
465
 
410
- export { type AdvisorPolicy, type ApplyPatchPolicy, type CompiledOpenRouterRequest, type DatetimePolicy, type FusionPolicy, type ImageGenerationPolicy, OpenRouterHttpError, type OpenRouterRuntime, type OpenRouterRuntimeOptions, type RuntimeCitation, RuntimeConfigError, type RuntimeDefaults, type RuntimeError, type RuntimeFunctionToolDefinition, type RuntimeGeneratedImage, type RuntimeMessage, type RuntimePatchProposal, type RuntimePolicyViolation, type RuntimeRequest, type RuntimeResponse, type RuntimeServerToolsPolicy, type RuntimeToolExecutor, type RuntimeToolUsage, type RuntimeUsage, type RuntimeWarning, type ServerToolKey, type ServerToolUsage, type SubagentPolicy, type WebFetchPolicy, type WebSearchPolicy, buildOpenRouterServerTools, compileRuntimeRequest, createOpenRouterRuntime };
466
+ declare function isRuntimeLoggingEnabled(env?: Record<string, string | undefined> | undefined): boolean;
467
+ declare function createConsoleLogger(): RuntimeLogger;
468
+
469
+ export { type AdvisorPolicy, type ApplyPatchPolicy, type CompiledOpenRouterRequest, type DatetimePolicy, type FusionPolicy, type ImageGenerationPolicy, OpenRouterHttpError, type OpenRouterRuntime, type OpenRouterRuntimeOptions, type RuntimeCitation, RuntimeConfigError, type RuntimeDefaults, type RuntimeError, type RuntimeFunctionToolDefinition, type RuntimeGeneratedImage, type RuntimeLogger, type RuntimeMessage, type RuntimePatchProposal, type RuntimePolicyViolation, type RuntimeRequest, type RuntimeResponse, type RuntimeServerToolsPolicy, type RuntimeStreamDoneEvent, type RuntimeStreamErrorEvent, type RuntimeStreamEvent, type RuntimeStreamEventType, type RuntimeStreamStartEvent, type RuntimeStreamTextDeltaEvent, type RuntimeStreamToolCallDeltaEvent, type RuntimeStreamUsageEvent, type RuntimeStreamWarningEvent, type RuntimeToolExecutor, type RuntimeToolUsage, type RuntimeUsage, type RuntimeWarning, type ServerToolKey, type ServerToolUsage, type SubagentPolicy, type WebFetchPolicy, type WebSearchPolicy, buildOpenRouterServerTools, compileRuntimeRequest, createConsoleLogger, createOpenRouterRuntime, isRuntimeLoggingEnabled };
package/dist/index.js CHANGED
@@ -1,11 +1,36 @@
1
+ // src/utils/console-logger.ts
2
+ var TRUTHY = /* @__PURE__ */ new Set(["1", "true", "yes", "on"]);
3
+ function isRuntimeLoggingEnabled(env = typeof process === "undefined" ? void 0 : process.env) {
4
+ const value = env?.OPENROUTER_RUNTIME_LOGS?.trim().toLowerCase();
5
+ return value !== void 0 && TRUTHY.has(value);
6
+ }
7
+ function createConsoleLogger() {
8
+ return {
9
+ debug(event, data) {
10
+ console.debug(`[openrouter-runtime] ${event}`, data ?? "");
11
+ },
12
+ info(event, data) {
13
+ console.info(`[openrouter-runtime] ${event}`, data ?? "");
14
+ },
15
+ warn(event, data) {
16
+ console.warn(`[openrouter-runtime] ${event}`, data ?? "");
17
+ },
18
+ error(event, data) {
19
+ console.error(`[openrouter-runtime] ${event}`, data ?? "");
20
+ }
21
+ };
22
+ }
23
+
1
24
  // src/config/defaults.ts
2
25
  function resolveRuntimeOptions(options) {
26
+ const logger = options.logger ?? (isRuntimeLoggingEnabled() ? createConsoleLogger() : void 0);
3
27
  return {
4
28
  ...options,
5
29
  apiKey: options.apiKey ?? readOpenRouterApiKeyFromEnv() ?? "",
6
30
  baseUrl: options.baseUrl ?? "https://openrouter.ai/api/v1",
7
31
  defaultHeaders: options.defaultHeaders ?? {},
8
- fetch: options.fetch ?? globalThis.fetch
32
+ fetch: options.fetch ?? globalThis.fetch,
33
+ ...logger ? { logger } : {}
9
34
  };
10
35
  }
11
36
  function resolveDefaults(options) {
@@ -893,14 +918,42 @@ function compileRuntimeRequest(request, defaults, options = { apiKey: "" }, cont
893
918
  };
894
919
  }
895
920
  function enforceStreamingPolicyForRun(body, warnings, context) {
896
- if (context.streaming) return;
897
- if (body.stream === true) {
921
+ if (context.streaming) {
922
+ body.stream = true;
923
+ return;
924
+ }
925
+ if (body.stream !== void 0 && body.stream !== false) {
898
926
  warnings.push({
899
927
  code: "STREAMING_OVERRIDE_IGNORED_FOR_RUN",
900
- message: "runtime.run() is non-streaming. Use runtime.stream() when streaming is implemented."
928
+ message: "runtime.run() is non-streaming. Use runtime.executeStreamingChat() for streaming.",
929
+ details: { ignoredStreamValue: body.stream }
930
+ });
931
+ }
932
+ body.stream = false;
933
+ stripAdvisorStreaming(body, warnings);
934
+ }
935
+ function stripAdvisorStreaming(body, warnings) {
936
+ const tools = body.tools;
937
+ if (!Array.isArray(tools)) return;
938
+ let stripped = 0;
939
+ for (const tool of tools) {
940
+ if (!tool || typeof tool !== "object") continue;
941
+ const record = tool;
942
+ if (record.type !== "openrouter:advisor") continue;
943
+ const parameters = record.parameters;
944
+ if (!parameters || typeof parameters !== "object") continue;
945
+ const params = parameters;
946
+ if (params.stream === void 0 || params.stream === false) continue;
947
+ params.stream = false;
948
+ stripped += 1;
949
+ }
950
+ if (stripped > 0) {
951
+ warnings.push({
952
+ code: "ADVISOR_STREAMING_IGNORED_FOR_RUN",
953
+ message: "runtime.run() disables advisor.stream. Nested advisor streaming is not supported on the non-streaming entrypoint.",
954
+ details: { advisorsStripped: stripped }
901
955
  });
902
956
  }
903
- delete body.stream;
904
957
  }
905
958
  function resolveApiMode(request, defaultMode = "auto", serverTools) {
906
959
  const mode = request.apiMode ?? defaultMode;
@@ -934,7 +987,7 @@ function buildChatBody(request, baseBody) {
934
987
  return clean({
935
988
  ...baseBody,
936
989
  messages,
937
- max_tokens: request.maxTokens,
990
+ max_completion_tokens: request.maxTokens,
938
991
  response_format: request.responseFormat
939
992
  });
940
993
  }
@@ -1275,12 +1328,333 @@ function optional6(key, value) {
1275
1328
  return value === void 0 ? {} : { [key]: value };
1276
1329
  }
1277
1330
 
1331
+ // src/openrouter/stream-client.ts
1332
+ async function openOpenRouterStream(compiled, options, timeoutMs) {
1333
+ const controller = new AbortController();
1334
+ const timeout = setTimeout(() => controller.abort(), timeoutMs);
1335
+ const cleanup = () => clearTimeout(timeout);
1336
+ try {
1337
+ const response = await options.fetch(compiled.url, {
1338
+ method: "POST",
1339
+ headers: {
1340
+ ...compiled.headers,
1341
+ Accept: "text/event-stream"
1342
+ },
1343
+ body: JSON.stringify(compiled.body),
1344
+ signal: controller.signal
1345
+ });
1346
+ if (!response.ok) {
1347
+ const text = await response.text();
1348
+ cleanup();
1349
+ const body = text ? parseBody2(text) : void 0;
1350
+ const message = extractMessage2(body) ?? `OpenRouter stream failed with status ${response.status}.`;
1351
+ throw new OpenRouterHttpError(
1352
+ response.status,
1353
+ classifyProviderFailure2(response.status, message, body),
1354
+ message,
1355
+ body,
1356
+ isRetryableStatus2(response.status)
1357
+ );
1358
+ }
1359
+ return { response, cleanup };
1360
+ } catch (error) {
1361
+ cleanup();
1362
+ if (error instanceof OpenRouterHttpError) throw error;
1363
+ if (error instanceof Error && error.name === "AbortError") {
1364
+ throw new OpenRouterHttpError(408, "PROVIDER_GATEWAY_UNREACHABLE", "OpenRouter stream timed out.", void 0, true);
1365
+ }
1366
+ throw new OpenRouterHttpError(
1367
+ 503,
1368
+ "PROVIDER_GATEWAY_UNREACHABLE",
1369
+ error instanceof Error ? error.message : "OpenRouter stream failed before receiving a response.",
1370
+ void 0,
1371
+ true
1372
+ );
1373
+ }
1374
+ }
1375
+ async function* parseSseStream(response) {
1376
+ const body = response.body;
1377
+ if (!body) {
1378
+ throw new OpenRouterHttpError(
1379
+ 503,
1380
+ "PROVIDER_GATEWAY_UNREACHABLE",
1381
+ "OpenRouter stream response had no body.",
1382
+ void 0,
1383
+ true
1384
+ );
1385
+ }
1386
+ const reader = body.getReader();
1387
+ const decoder = new TextDecoder();
1388
+ let buffer = "";
1389
+ while (true) {
1390
+ const { done, value } = await reader.read();
1391
+ if (done) break;
1392
+ buffer += decoder.decode(value, { stream: true });
1393
+ const parts = buffer.split(/\r?\n/);
1394
+ buffer = parts.pop() ?? "";
1395
+ for (const part of parts) {
1396
+ const line = part.trim();
1397
+ if (!line || line.startsWith(":")) continue;
1398
+ if (!line.startsWith("data:")) continue;
1399
+ const data = line.slice(5).trim();
1400
+ if (!data) continue;
1401
+ if (data === "[DONE]") return;
1402
+ try {
1403
+ yield JSON.parse(data);
1404
+ } catch {
1405
+ }
1406
+ }
1407
+ }
1408
+ const trailing = buffer.trim();
1409
+ if (trailing.startsWith("data:")) {
1410
+ const data = trailing.slice(5).trim();
1411
+ if (data && data !== "[DONE]") {
1412
+ try {
1413
+ yield JSON.parse(data);
1414
+ } catch {
1415
+ }
1416
+ }
1417
+ }
1418
+ }
1419
+ function parseBody2(text) {
1420
+ try {
1421
+ return JSON.parse(text);
1422
+ } catch {
1423
+ return text;
1424
+ }
1425
+ }
1426
+ function extractMessage2(body) {
1427
+ if (typeof body !== "object" || body === null) return void 0;
1428
+ const record = body;
1429
+ const error = record.error;
1430
+ if (typeof error === "object" && error !== null && typeof error.message === "string") {
1431
+ return error.message;
1432
+ }
1433
+ return typeof record.message === "string" ? record.message : void 0;
1434
+ }
1435
+ function classifyProviderFailure2(status, message, body) {
1436
+ const haystack = `${message} ${JSON.stringify(body ?? "")}`.toLowerCase();
1437
+ if (status === 401 || status === 403) return "PROVIDER_AUTH_FAILED";
1438
+ if (status === 402 || /\b(quota|credit|credits|billing|balance|insufficient funds|insufficient credit)\b/.test(haystack)) {
1439
+ return "PROVIDER_QUOTA_EXCEEDED";
1440
+ }
1441
+ if (status === 404 || /\bmodel\b.*\b(not found|not a valid|invalid|unavailable)\b/.test(haystack) || /\b(no endpoints found|not a valid model id)\b/.test(haystack)) {
1442
+ return "PROVIDER_MODEL_NOT_FOUND";
1443
+ }
1444
+ if (status === 429) return "PROVIDER_RATE_LIMITED";
1445
+ if (status === 408 || status >= 500) return "PROVIDER_GATEWAY_UNREACHABLE";
1446
+ return "PROVIDER_REQUEST_FAILED";
1447
+ }
1448
+ function isRetryableStatus2(status) {
1449
+ return status === 429 || status === 500 || status === 502 || status === 503 || status === 504;
1450
+ }
1451
+
1278
1452
  // src/runtime/streaming.ts
1279
- async function* streamNotImplemented() {
1280
- throw new RuntimeConfigError(
1281
- "STREAMING_NOT_IMPLEMENTED",
1282
- "Streaming is reserved for a later phase. Use runtime.run() for non-streaming execution."
1283
- );
1453
+ async function* executeStreamingChat(request, context) {
1454
+ const requestId = request.id ?? "unknown";
1455
+ const options = context.options;
1456
+ const defaults = context.defaults;
1457
+ options.logger?.info?.("runtime.executeStreamingChat.started", {
1458
+ requestId,
1459
+ streaming: true,
1460
+ entrypoint: "executeStreamingChat"
1461
+ });
1462
+ try {
1463
+ assertStreamingChatRequest(request, defaults);
1464
+ const streamingRequest = {
1465
+ ...request,
1466
+ apiMode: "chat"
1467
+ };
1468
+ const compiled = compileRuntimeRequest(streamingRequest, defaults, options, { streaming: true });
1469
+ if (compiled.body.stream !== true) {
1470
+ throw new RuntimeConfigError(
1471
+ "STREAMING_CHAT_MISCONFIGURED",
1472
+ "executeStreamingChat() requires stream=true on the compiled OpenRouter body."
1473
+ );
1474
+ }
1475
+ for (const warning of compiled.warnings) {
1476
+ yield warningEvent(requestId, warning);
1477
+ }
1478
+ const model = typeof compiled.body.model === "string" ? compiled.body.model : "";
1479
+ yield startEvent(requestId, model);
1480
+ await options.hooks?.beforeOpenRouterRequest?.(compiled);
1481
+ const timeoutMs = request.execution?.timeoutMs ?? defaults.timeoutMs;
1482
+ const session = await openOpenRouterStream(compiled, options, timeoutMs);
1483
+ let text = "";
1484
+ let finishReason;
1485
+ let resolvedModel = model;
1486
+ try {
1487
+ for await (const chunk of parseSseStream(session.response)) {
1488
+ if (!isRecord(chunk)) continue;
1489
+ if (chunk.error) {
1490
+ const message = isRecord(chunk.error) && typeof chunk.error.message === "string" ? chunk.error.message : "OpenRouter stream returned an error chunk.";
1491
+ const error = {
1492
+ code: "PROVIDER_REQUEST_FAILED",
1493
+ message,
1494
+ source: "openrouter",
1495
+ details: chunk.error
1496
+ };
1497
+ yield errorEvent(requestId, error);
1498
+ throw new OpenRouterHttpError(500, "PROVIDER_REQUEST_FAILED", message, chunk, false);
1499
+ }
1500
+ if (typeof chunk.model === "string") resolvedModel = chunk.model;
1501
+ const choice = Array.isArray(chunk.choices) && isRecord(chunk.choices[0]) ? chunk.choices[0] : void 0;
1502
+ const delta = choice && isRecord(choice.delta) ? choice.delta : void 0;
1503
+ if (delta && typeof delta.content === "string" && delta.content.length > 0) {
1504
+ text += delta.content;
1505
+ yield textDeltaEvent(requestId, delta.content);
1506
+ }
1507
+ if (delta && Array.isArray(delta.tool_calls)) {
1508
+ for (const toolCall of delta.tool_calls) {
1509
+ if (!isRecord(toolCall)) continue;
1510
+ const index = typeof toolCall.index === "number" ? toolCall.index : 0;
1511
+ const fn = isRecord(toolCall.function) ? toolCall.function : {};
1512
+ yield toolCallDeltaEvent(requestId, {
1513
+ index,
1514
+ ...typeof toolCall.id === "string" ? { id: toolCall.id } : {},
1515
+ ...typeof fn.name === "string" ? { name: fn.name } : {},
1516
+ ...typeof fn.arguments === "string" ? { argumentsDelta: fn.arguments } : {}
1517
+ });
1518
+ }
1519
+ }
1520
+ if (choice && typeof choice.finish_reason === "string") {
1521
+ finishReason = choice.finish_reason;
1522
+ }
1523
+ if (chunk.usage) {
1524
+ const usage = normalizeUsage(chunk.usage);
1525
+ if (usage) yield usageEvent(requestId, usage);
1526
+ }
1527
+ }
1528
+ } finally {
1529
+ session.cleanup();
1530
+ }
1531
+ await options.hooks?.afterOpenRouterResponse?.({ streamed: true, text, finishReason, model: resolvedModel });
1532
+ yield doneEvent(requestId, {
1533
+ text,
1534
+ model: resolvedModel,
1535
+ ...finishReason ? { finishReason } : {}
1536
+ });
1537
+ options.logger?.info?.("runtime.executeStreamingChat.completed", {
1538
+ requestId,
1539
+ streaming: true,
1540
+ entrypoint: "executeStreamingChat",
1541
+ finishReason,
1542
+ textLength: text.length
1543
+ });
1544
+ } catch (error) {
1545
+ const runtimeError = toRuntimeError(error);
1546
+ yield errorEvent(requestId, runtimeError);
1547
+ options.logger?.error?.("runtime.executeStreamingChat.failed", {
1548
+ requestId,
1549
+ streaming: true,
1550
+ code: runtimeError.code,
1551
+ message: runtimeError.message
1552
+ });
1553
+ throw error instanceof Error ? error : new Error(runtimeError.message);
1554
+ }
1555
+ }
1556
+ function assertStreamingChatRequest(request, defaults) {
1557
+ if (request.apiMode === "responses") {
1558
+ throw new RuntimeConfigError(
1559
+ "STREAMING_CHAT_REQUIRES_CHAT_API",
1560
+ "executeStreamingChat() only supports Chat Completions. Use runtime.run() for Responses API requests."
1561
+ );
1562
+ }
1563
+ if (request.serverTools?.applyPatch?.mode && request.serverTools.applyPatch.mode !== "disabled") {
1564
+ throw new RuntimeConfigError(
1565
+ "STREAMING_CHAT_DOES_NOT_SUPPORT_APPLY_PATCH",
1566
+ "executeStreamingChat() does not support applyPatch. Use runtime.run() instead."
1567
+ );
1568
+ }
1569
+ if (defaults.serverTools?.applyPatch?.mode && defaults.serverTools.applyPatch.mode !== "disabled") {
1570
+ const requestPatch = request.serverTools?.applyPatch;
1571
+ if (!requestPatch || requestPatch.mode !== "disabled") {
1572
+ throw new RuntimeConfigError(
1573
+ "STREAMING_CHAT_DOES_NOT_SUPPORT_APPLY_PATCH",
1574
+ "executeStreamingChat() does not support applyPatch defaults. Use runtime.run() instead."
1575
+ );
1576
+ }
1577
+ }
1578
+ }
1579
+ function startEvent(requestId, model) {
1580
+ return {
1581
+ type: "stream.start",
1582
+ requestId,
1583
+ data: {
1584
+ model,
1585
+ apiMode: "chat",
1586
+ entrypoint: "executeStreamingChat"
1587
+ }
1588
+ };
1589
+ }
1590
+ function textDeltaEvent(requestId, text) {
1591
+ return {
1592
+ type: "stream.text.delta",
1593
+ requestId,
1594
+ data: { text }
1595
+ };
1596
+ }
1597
+ function toolCallDeltaEvent(requestId, data) {
1598
+ return {
1599
+ type: "stream.tool_call.delta",
1600
+ requestId,
1601
+ data
1602
+ };
1603
+ }
1604
+ function usageEvent(requestId, usage) {
1605
+ return {
1606
+ type: "stream.usage",
1607
+ requestId,
1608
+ data: { usage }
1609
+ };
1610
+ }
1611
+ function warningEvent(requestId, warning) {
1612
+ return {
1613
+ type: "stream.warning",
1614
+ requestId,
1615
+ data: { warning }
1616
+ };
1617
+ }
1618
+ function errorEvent(requestId, error) {
1619
+ return {
1620
+ type: "stream.error",
1621
+ requestId,
1622
+ data: { error }
1623
+ };
1624
+ }
1625
+ function doneEvent(requestId, data) {
1626
+ return {
1627
+ type: "stream.done",
1628
+ requestId,
1629
+ data
1630
+ };
1631
+ }
1632
+ function toRuntimeError(error) {
1633
+ if (error instanceof RuntimeConfigError) {
1634
+ return {
1635
+ code: error.code,
1636
+ message: error.message,
1637
+ source: "validation",
1638
+ details: error.details
1639
+ };
1640
+ }
1641
+ if (error instanceof OpenRouterHttpError) {
1642
+ return {
1643
+ code: error.code,
1644
+ message: error.message,
1645
+ source: "openrouter",
1646
+ retryable: error.retryable,
1647
+ details: {
1648
+ providerAttempts: error.providerAttempts,
1649
+ ...error.body === void 0 ? {} : { response: error.body }
1650
+ }
1651
+ };
1652
+ }
1653
+ return {
1654
+ code: "RUNTIME_ERROR",
1655
+ message: error instanceof Error ? error.message : String(error),
1656
+ source: "runtime"
1657
+ };
1284
1658
  }
1285
1659
 
1286
1660
  // src/runtime/create-runtime.ts
@@ -1292,24 +1666,38 @@ function createOpenRouterRuntime(options) {
1292
1666
  async run(request) {
1293
1667
  const requestWithId = { ...request, id: request.id ?? createRuntimeId() };
1294
1668
  try {
1295
- resolvedOptions.logger?.info?.("runtime.request.started", { requestId: requestWithId.id });
1669
+ resolvedOptions.logger?.info?.("runtime.request.started", {
1670
+ requestId: requestWithId.id,
1671
+ streaming: false,
1672
+ entrypoint: "run"
1673
+ });
1296
1674
  await resolvedOptions.hooks?.beforeCompile?.(requestWithId);
1297
1675
  const compiled = compileRuntimeRequest(requestWithId, defaults, resolvedOptions, { streaming: false });
1298
1676
  await resolvedOptions.hooks?.afterCompile?.(compiled);
1299
1677
  resolvedOptions.logger?.debug?.("runtime.request.compiled", {
1300
1678
  requestId: requestWithId.id,
1301
- apiMode: compiled.apiMode
1679
+ apiMode: compiled.apiMode,
1680
+ streaming: false,
1681
+ bodyStream: compiled.body.stream,
1682
+ streamingWarnings: compiled.warnings.filter((warning) => warning.code.includes("STREAMING") || warning.code.includes("ADVISOR_STREAMING")).map((warning) => warning.code)
1302
1683
  });
1303
1684
  await resolvedOptions.hooks?.beforeOpenRouterRequest?.(compiled);
1304
1685
  const response = compiled.apiMode === "chat" ? await runChat(requestWithId, compiled, context) : await runResponses(requestWithId, compiled, context);
1305
1686
  await resolvedOptions.hooks?.afterOpenRouterResponse?.(response.raw.response);
1306
- resolvedOptions.logger?.info?.("runtime.response.normalized", { requestId: requestWithId.id, status: response.status });
1687
+ resolvedOptions.logger?.info?.("runtime.response.normalized", {
1688
+ requestId: requestWithId.id,
1689
+ status: response.status,
1690
+ streaming: false
1691
+ });
1307
1692
  return response;
1308
1693
  } catch (error) {
1309
1694
  return errorResponse(requestWithId, error);
1310
1695
  }
1311
1696
  },
1312
- stream: streamNotImplemented
1697
+ executeStreamingChat(request) {
1698
+ const requestWithId = { ...request, id: request.id ?? createRuntimeId() };
1699
+ return executeStreamingChat(requestWithId, context);
1700
+ }
1313
1701
  };
1314
1702
  function errorResponse(request, error) {
1315
1703
  const runtimeError = normalizeError(error);
@@ -1401,6 +1789,8 @@ export {
1401
1789
  RuntimeConfigError,
1402
1790
  buildOpenRouterServerTools,
1403
1791
  compileRuntimeRequest,
1404
- createOpenRouterRuntime
1792
+ createConsoleLogger,
1793
+ createOpenRouterRuntime,
1794
+ isRuntimeLoggingEnabled
1405
1795
  };
1406
1796
  //# sourceMappingURL=index.js.map