@askalf/dario 4.8.22 → 4.8.24

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.
@@ -264,6 +264,10 @@ export declare function resolveMaxTokens(flag: number | 'client' | undefined, cl
264
264
  /** Valid values for the `--effort` flag. Mirrors CC's effort set (`low|medium|high|xhigh|max`) plus CC's `ultracode` mode and dario's pseudo-value `'client'` for passthrough. `'ultracode'` is CC's xhigh-plus-dynamic-workflow-orchestration mode (CC 2.1.154); the Messages API accepts only low|medium|high|xhigh|max, so dario normalizes ultracode → 'xhigh' on the wire (see normalizeEffortForWire). `'client'` passes through the client's own `output_config.effort` (falling back to `'xhigh'`). dario#87, `'max'` added in dario#190, `'ultracode'` added 2026-05-28. */
265
265
  export type EffortValue = 'low' | 'medium' | 'high' | 'xhigh' | 'ultracode' | 'max' | 'client';
266
266
  export declare const VALID_EFFORT_VALUES: ReadonlyArray<EffortValue>;
267
+ export declare function parseEffortSuffix(model: string): {
268
+ model: string;
269
+ effort?: EffortValue;
270
+ };
267
271
  /**
268
272
  * Resolve the outbound `output_config.effort` value.
269
273
  *
@@ -893,6 +893,27 @@ export function resolveMaxTokens(flag, clientBody) {
893
893
  return flag;
894
894
  }
895
895
  export const VALID_EFFORT_VALUES = ['low', 'medium', 'high', 'xhigh', 'ultracode', 'max', 'client'];
896
+ /**
897
+ * dario#419 — strip an optional effort suffix off a model name, so OpenAI-compat
898
+ * clients that can't set `output_config.effort` (e.g. Cursor) can choose effort
899
+ * by model name: `opus-4-8:high` (colon) or Cursor-style `claude-opus-4-8-high`
900
+ * (hyphen). Only the wire-valid effort levels are recognized as a suffix — any
901
+ * other trailing token is left as part of the model name, and a bare model that
902
+ * IS an effort word (e.g. just "high") is left alone. Returns the model with the
903
+ * suffix removed plus the parsed effort (undefined when none). Exported for tests.
904
+ */
905
+ const SUFFIX_EFFORTS = ['ultracode', 'medium', 'xhigh', 'high', 'low', 'max'];
906
+ export function parseEffortSuffix(model) {
907
+ for (const e of SUFFIX_EFFORTS) {
908
+ for (const sep of [':', '-']) {
909
+ const tag = sep + e;
910
+ if (model.length > tag.length && model.endsWith(tag)) {
911
+ return { model: model.slice(0, -tag.length), effort: e };
912
+ }
913
+ }
914
+ }
915
+ return { model };
916
+ }
896
917
  /**
897
918
  * Normalize an effort value to a wire-valid `output_config.effort`. The
898
919
  * Messages API accepts only low|medium|high|xhigh|max. CC's `ultracode` is a
@@ -282,7 +282,7 @@ export declare function _resetInstalledVersionProbeForTest(): void;
282
282
  */
283
283
  export declare const SUPPORTED_CC_RANGE: {
284
284
  readonly min: "1.0.0";
285
- readonly maxTested: "2.1.159";
285
+ readonly maxTested: "2.1.160";
286
286
  };
287
287
  /**
288
288
  * Compare two dotted-numeric version strings. Returns negative if `a<b`,
@@ -786,7 +786,7 @@ export function _resetInstalledVersionProbeForTest() {
786
786
  */
787
787
  export const SUPPORTED_CC_RANGE = {
788
788
  min: '1.0.0',
789
- maxTested: '2.1.159',
789
+ maxTested: '2.1.160',
790
790
  };
791
791
  /**
792
792
  * Compare two dotted-numeric version strings. Returns negative if `a<b`,
package/dist/proxy.js CHANGED
@@ -6,7 +6,7 @@ import { join } from 'node:path';
6
6
  import { homedir } from 'node:os';
7
7
  import { arch, platform } from 'node:process';
8
8
  import { getAccessToken, getStatus } from './oauth.js';
9
- import { buildCCRequest, reverseMapResponse, createStreamingReverseMapper, orderHeadersForOutbound, CC_TEMPLATE } from './cc-template.js';
9
+ import { buildCCRequest, parseEffortSuffix, reverseMapResponse, createStreamingReverseMapper, orderHeadersForOutbound, CC_TEMPLATE } from './cc-template.js';
10
10
  import { describeTemplate, detectDrift, checkCCCompat } from './live-fingerprint.js';
11
11
  import { AccountPool, computeStickyKey, parseRateLimits, modelFamily, isInAuthCooldown, authCooldownMs } from './pool.js';
12
12
  import { Analytics, billingBucketFromClaim } from './analytics.js';
@@ -1242,6 +1242,7 @@ export async function startProxy(opts = {}) {
1242
1242
  // built-in `claude-*` name collision (Cursor reroutes any name it
1243
1243
  // recognizes through its own Anthropic gateway, bypassing localhost).
1244
1244
  let forcedProvider = cliProviderOverride;
1245
+ let requestEffort; // dario#419 — per-request effort parsed from a model-name suffix (model:high / model-high)
1245
1246
  if (body.length > 0) {
1246
1247
  try {
1247
1248
  const parsed = JSON.parse(body.toString());
@@ -1249,14 +1250,26 @@ export async function startProxy(opts = {}) {
1249
1250
  const prefix = parseProviderPrefix(rawModel);
1250
1251
  if (prefix) {
1251
1252
  forcedProvider = prefix.provider;
1253
+ // dario#419 — optional effort suffix (model:high / model-high). Claude
1254
+ // path ONLY: OpenAI backends keep their own -high/-low suffixes, so we
1255
+ // strip it before the alias lookup only when routing to the subscription.
1256
+ let providerModel = prefix.model;
1257
+ if (prefix.provider === 'claude') {
1258
+ const eff = parseEffortSuffix(providerModel);
1259
+ if (eff.effort) {
1260
+ requestEffort = eff.effort;
1261
+ providerModel = eff.model;
1262
+ }
1263
+ }
1252
1264
  const resolvedModel = prefix.provider === 'claude'
1253
- ? resolveClaudeAlias(prefix.model)
1254
- : prefix.model;
1265
+ ? resolveClaudeAlias(providerModel)
1266
+ : providerModel;
1255
1267
  parsed.model = resolvedModel;
1256
1268
  body = Buffer.from(JSON.stringify(parsed));
1257
1269
  if (verbose) {
1258
- const aliasNote = resolvedModel !== prefix.model ? ` (alias: ${prefix.model} → ${resolvedModel})` : '';
1259
- console.log(`[dario] provider prefix: ${rawModel} ${prefix.provider} backend with model ${resolvedModel}${aliasNote}`);
1270
+ const aliasNote = resolvedModel !== providerModel ? ` (alias: ${providerModel} → ${resolvedModel})` : '';
1271
+ const effNote = requestEffort ? ` (effort: ${requestEffort})` : '';
1272
+ console.log(`[dario] provider prefix: ${rawModel} → ${prefix.provider} backend with model ${resolvedModel}${aliasNote}${effNote}`);
1260
1273
  }
1261
1274
  }
1262
1275
  else if (cliProviderOverride === 'openai' && cliModelRaw) {
@@ -1266,6 +1279,19 @@ export async function startProxy(opts = {}) {
1266
1279
  parsed.model = cliModelRaw;
1267
1280
  body = Buffer.from(JSON.stringify(parsed));
1268
1281
  }
1282
+ else if (!isOpenAIModel(rawModel) && forcedProvider !== 'openai') {
1283
+ // dario#419 — bare Claude model name carrying an effort suffix with no
1284
+ // provider prefix (e.g. Cursor's `claude-opus-4-8-high`). OpenAI-bound
1285
+ // models are excluded so their own suffixes pass through untouched.
1286
+ const eff = parseEffortSuffix(rawModel);
1287
+ if (eff.effort) {
1288
+ requestEffort = eff.effort;
1289
+ parsed.model = eff.model;
1290
+ body = Buffer.from(JSON.stringify(parsed));
1291
+ if (verbose)
1292
+ console.log(`[dario] effort suffix: ${rawModel} → model ${eff.model} (effort: ${eff.effort})`);
1293
+ }
1294
+ }
1269
1295
  }
1270
1296
  catch { /* not JSON — fall through */ }
1271
1297
  }
@@ -1388,7 +1414,7 @@ export async function startProxy(opts = {}) {
1388
1414
  hybridTools: opts.hybridTools ?? false,
1389
1415
  mergeTools: opts.mergeTools ?? false,
1390
1416
  noAutoDetect: opts.noAutoDetect ?? false,
1391
- effort: opts.effort,
1417
+ effort: requestEffort ?? opts.effort,
1392
1418
  maxTokens: opts.maxTokens,
1393
1419
  systemPrompt: opts.systemPrompt,
1394
1420
  skipFields,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@askalf/dario",
3
- "version": "4.8.22",
3
+ "version": "4.8.24",
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": {