@askalf/dario 5.5.89 → 5.5.90

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.
@@ -114,6 +114,27 @@ export declare function createResponsesTranslator(model: string): {
114
114
  /** Everything seen so far, as one non-streaming chat.completion body. */
115
115
  complete(): Record<string, unknown>;
116
116
  };
117
+ /**
118
+ * Fields the ChatGPT Codex backend accepts on /responses.
119
+ *
120
+ * It is NOT the public Responses API: it rejects a whole class of sampling and
121
+ * metadata parameters outright, one 400 at a time —
122
+ * 400 {"detail":"Unsupported parameter: <name>"}
123
+ * Probed directly against a live subscription (2026-08-30); rejected were
124
+ * temperature, top_p, max_output_tokens, presence_penalty, frequency_penalty,
125
+ * seed, metadata, top_logprobs, truncation and service_tier.
126
+ *
127
+ * This is an ALLOWLIST rather than a list of the ten known-bad names on
128
+ * purpose. The backend is undocumented and clearly restrictive, so the failure
129
+ * we must not have is "we started sending a new field and every request 400s".
130
+ * Dropping an unknown field degrades one request; sending one breaks all of
131
+ * them. Both request builders stay correct for an API-key Responses endpoint —
132
+ * which does accept these — because the scrub happens HERE, at the transport
133
+ * that knows which backend it is talking to.
134
+ */
135
+ export declare const CODEX_SUPPORTED_FIELDS: readonly string[];
136
+ /** Drop every field this backend does not accept. Pure; exported for tests. */
137
+ export declare function toCodexSupportedBody(body: Record<string, unknown>): Record<string, unknown>;
117
138
  export declare function buildCodexHeaders(creds: CodexAccountCredentials): Record<string, string>;
118
139
  /**
119
140
  * Serve a request from a stored Codex account, in either client wire shape.
@@ -377,6 +377,37 @@ export function createResponsesTranslator(model) {
377
377
  },
378
378
  };
379
379
  }
380
+ /**
381
+ * Fields the ChatGPT Codex backend accepts on /responses.
382
+ *
383
+ * It is NOT the public Responses API: it rejects a whole class of sampling and
384
+ * metadata parameters outright, one 400 at a time —
385
+ * 400 {"detail":"Unsupported parameter: <name>"}
386
+ * Probed directly against a live subscription (2026-08-30); rejected were
387
+ * temperature, top_p, max_output_tokens, presence_penalty, frequency_penalty,
388
+ * seed, metadata, top_logprobs, truncation and service_tier.
389
+ *
390
+ * This is an ALLOWLIST rather than a list of the ten known-bad names on
391
+ * purpose. The backend is undocumented and clearly restrictive, so the failure
392
+ * we must not have is "we started sending a new field and every request 400s".
393
+ * Dropping an unknown field degrades one request; sending one breaks all of
394
+ * them. Both request builders stay correct for an API-key Responses endpoint —
395
+ * which does accept these — because the scrub happens HERE, at the transport
396
+ * that knows which backend it is talking to.
397
+ */
398
+ export const CODEX_SUPPORTED_FIELDS = [
399
+ 'model', 'input', 'stream', 'store', 'instructions',
400
+ 'tools', 'tool_choice', 'parallel_tool_calls', 'reasoning',
401
+ ];
402
+ /** Drop every field this backend does not accept. Pure; exported for tests. */
403
+ export function toCodexSupportedBody(body) {
404
+ const out = {};
405
+ for (const k of CODEX_SUPPORTED_FIELDS) {
406
+ if (body[k] !== undefined)
407
+ out[k] = body[k];
408
+ }
409
+ return out;
410
+ }
380
411
  export function buildCodexHeaders(creds) {
381
412
  const headers = {
382
413
  'Content-Type': 'application/json',
@@ -434,17 +465,7 @@ export async function forwardToCodex(req, res, body, creds, corsOrigin, security
434
465
  const upstreamBody = isAnthropic
435
466
  ? { ...anthropicToResponsesRequest(parsed, model), stream: true }
436
467
  : chatCompletionsToResponses(parsed);
437
- // The ChatGPT Codex backend REJECTS an output cap outright:
438
- // 400 {"detail":"Unsupported parameter: max_output_tokens"}
439
- // Both builders set it from the client's max_tokens / max_completion_tokens,
440
- // so BOTH shapes 400 whenever a client asks for one. It stayed hidden because
441
- // every smoke test so far happened to omit max_tokens; it then showed up as a
442
- // 100% failure on the Anthropic path, where the Messages API REQUIRES
443
- // max_tokens and so always produced it. Stripped here rather than in either
444
- // translator because it is a property of THIS backend, not of either wire
445
- // format — the same builders are correct against an API-key Responses
446
- // endpoint, which does support the parameter.
447
- delete upstreamBody.max_output_tokens;
468
+ const scrubbed = toCodexSupportedBody(upstreamBody);
448
469
  const target = `${CODEX_BACKEND_BASE_URL.replace(/\/$/, '')}/responses`;
449
470
  const abort = new AbortController();
450
471
  const timeout = setTimeout(() => abort.abort(), upstreamTimeoutMs);
@@ -454,7 +475,7 @@ export async function forwardToCodex(req, res, body, creds, corsOrigin, security
454
475
  const upstream = await fetchImpl(target, {
455
476
  method: 'POST',
456
477
  headers: buildCodexHeaders(creds),
457
- body: JSON.stringify(upstreamBody),
478
+ body: JSON.stringify(scrubbed),
458
479
  signal: abort.signal,
459
480
  });
460
481
  if (!upstream.ok) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@askalf/dario",
3
- "version": "5.5.89",
3
+ "version": "5.5.90",
4
4
  "description": "Use your Claude Pro/Max subscription in any tool — Cursor, Cline, Aider, the Agent SDK, your scripts — at subscription pricing, not per-token API bills. One local Anthropic + OpenAI-compatible endpoint.",
5
5
  "type": "module",
6
6
  "bin": {