@x12i/openrouter-runtime 1.0.4 → 1.0.5

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/README.md CHANGED
@@ -70,3 +70,47 @@ const runtime = createOpenRouterRuntime({
70
70
  ```
71
71
 
72
72
  Function calls are executed locally and looped back to OpenRouter until a final response is produced or `maxToolIterations` is reached.
73
+
74
+ ## Streaming
75
+
76
+ `runtime.run(request)` is non-streaming by design. Use it for background tasks, graph nodes, tool calls, structured output, research jobs, classification, extraction, patch generation, and automation.
77
+
78
+ ```ts
79
+ const response = await runtime.run({
80
+ model: "openai/gpt-5.2",
81
+ prompt: "Summarize this document."
82
+ });
83
+ ```
84
+
85
+ This sends a normal non-streaming OpenRouter request and returns a completed `RuntimeResponse`.
86
+
87
+ ### Why `run()` is not streaming
88
+
89
+ `run()` is designed for reliable runtime execution, not token-by-token UI delivery.
90
+
91
+ Most runtime calls are background operations: graph nodes, tool loops, extraction, classification, research, patch generation, and structured output. For those workloads, streaming adds connection complexity without improving the final result.
92
+
93
+ When streaming support is added, it will be available through `runtime.stream(request)`, not through `runtime.run(request)`.
94
+
95
+ ```ts
96
+ // Future API
97
+ for await (const event of runtime.stream(request)) {
98
+ // send token deltas to browser/client
99
+ }
100
+ ```
101
+
102
+ Today, `stream()` is reserved and throws `STREAMING_NOT_IMPLEMENTED`. The package should be treated as a non-streaming runtime.
103
+
104
+ Do not pass streaming through raw overrides:
105
+
106
+ ```ts
107
+ await runtime.run({
108
+ model: "openai/gpt-5.2",
109
+ prompt: "Summarize this document.",
110
+ rawOpenRouterOverrides: {
111
+ stream: true
112
+ }
113
+ });
114
+ ```
115
+
116
+ If `rawOpenRouterOverrides.stream = true` is provided to `runtime.run()`, it is ignored and reported as a `STREAMING_OVERRIDE_IGNORED_FOR_RUN` warning.
package/dist/index.cjs CHANGED
@@ -890,8 +890,9 @@ function buildSubagentTool(policy) {
890
890
  }
891
891
 
892
892
  // src/runtime/runtime.ts
893
- function compileRuntimeRequest(request, defaults, options = { apiKey: "" }) {
893
+ function compileRuntimeRequest(request, defaults, options = { apiKey: "" }, context = {}) {
894
894
  const warnings = [];
895
+ const effectiveContext = { streaming: false, ...context };
895
896
  const requestedModel = request.model ?? options.defaultModel ?? "";
896
897
  const normalized = normalizeModel(requestedModel);
897
898
  warnings.push(...normalized.warnings);
@@ -912,6 +913,7 @@ function compileRuntimeRequest(request, defaults, options = { apiKey: "" }) {
912
913
  const headers = buildHeaders(options);
913
914
  const baseBody = buildBaseBody(request, normalized.model, defaults, tools, serverTools);
914
915
  const body = apiMode === "chat" ? buildChatBody(request, baseBody) : buildResponsesBody(request, baseBody);
916
+ enforceStreamingPolicyForRun(body, warnings, effectiveContext);
915
917
  return {
916
918
  apiMode,
917
919
  url: endpointFor(options.baseUrl ?? "https://openrouter.ai/api/v1", apiMode),
@@ -920,6 +922,16 @@ function compileRuntimeRequest(request, defaults, options = { apiKey: "" }) {
920
922
  warnings
921
923
  };
922
924
  }
925
+ function enforceStreamingPolicyForRun(body, warnings, context) {
926
+ if (context.streaming) return;
927
+ if (body.stream === true) {
928
+ warnings.push({
929
+ code: "STREAMING_OVERRIDE_IGNORED_FOR_RUN",
930
+ message: "runtime.run() is non-streaming. Use runtime.stream() when streaming is implemented."
931
+ });
932
+ }
933
+ delete body.stream;
934
+ }
923
935
  function resolveApiMode(request, defaultMode = "auto", serverTools) {
924
936
  const mode = request.apiMode ?? defaultMode;
925
937
  if (mode === "chat") return "chat";
@@ -1293,6 +1305,14 @@ function optional6(key, value) {
1293
1305
  return value === void 0 ? {} : { [key]: value };
1294
1306
  }
1295
1307
 
1308
+ // src/runtime/streaming.ts
1309
+ async function* streamNotImplemented() {
1310
+ throw new RuntimeConfigError(
1311
+ "STREAMING_NOT_IMPLEMENTED",
1312
+ "Streaming is reserved for a later phase. Use runtime.run() for non-streaming execution."
1313
+ );
1314
+ }
1315
+
1296
1316
  // src/runtime/create-runtime.ts
1297
1317
  function createOpenRouterRuntime(options) {
1298
1318
  const resolvedOptions = resolveRuntimeOptions(options);
@@ -1304,7 +1324,7 @@ function createOpenRouterRuntime(options) {
1304
1324
  try {
1305
1325
  resolvedOptions.logger?.info?.("runtime.request.started", { requestId: requestWithId.id });
1306
1326
  await resolvedOptions.hooks?.beforeCompile?.(requestWithId);
1307
- const compiled = compileRuntimeRequest(requestWithId, defaults, resolvedOptions);
1327
+ const compiled = compileRuntimeRequest(requestWithId, defaults, resolvedOptions, { streaming: false });
1308
1328
  await resolvedOptions.hooks?.afterCompile?.(compiled);
1309
1329
  resolvedOptions.logger?.debug?.("runtime.request.compiled", {
1310
1330
  requestId: requestWithId.id,
@@ -1318,7 +1338,8 @@ function createOpenRouterRuntime(options) {
1318
1338
  } catch (error) {
1319
1339
  return errorResponse(requestWithId, error);
1320
1340
  }
1321
- }
1341
+ },
1342
+ stream: streamNotImplemented
1322
1343
  };
1323
1344
  function errorResponse(request, error) {
1324
1345
  const runtimeError = normalizeError(error);