@molecule/api-ai-deepseek 1.0.10 → 1.0.11

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.
@@ -1 +1 @@
1
- {"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../src/provider.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAIH,OAAO,KAAK,EACV,UAAU,EAIV,SAAS,EAET,UAAU,EAGX,MAAM,kBAAkB,CAAA;AASzB,OAAO,cAAc,CAAA;AAErB,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAA;AAsGhD,8DAA8D;AAC9D,eAAO,MAAM,8BAA8B,QAAS,CAAA;AAgGpD;;;;GAIG;AACH,cAAM,sBAAuB,YAAW,UAAU;IAChD,QAAQ,CAAC,IAAI,cAAa;IAC1B,OAAO,CAAC,MAAM,CAAQ;IACtB,OAAO,CAAC,YAAY,CAAQ;IAC5B,OAAO,CAAC,SAAS,CAAQ;IACzB,OAAO,CAAC,OAAO,CAAQ;IACvB,OAAO,CAAC,eAAe,CAAQ;IAC/B,OAAO,CAAC,QAAQ,CAAwB;IACxC,OAAO,CAAC,WAAW,CAAC,CAAqB;IACzC,OAAO,CAAC,aAAa,CAAC,CAAuB;IAC7C,OAAO,CAAC,mBAAmB,CAAQ;IACnC,OAAO,CAAC,sBAAsB,CAAQ;gBAE1B,MAAM,GAAE,cAAmB;IAwBvC;;;;;OAKG;IACI,IAAI,CAAC,MAAM,EAAE,UAAU,GAAG,aAAa,CAAC,SAAS,CAAC;IAqPzD;;;;;;;;;OASG;YACW,2BAA2B;IA0EzC;;;;;;;OAOG;IACH,OAAO,CAAC,iBAAiB;IA2BzB;;;;;;;OAOG;IACH,OAAO,CAAC,cAAc;IAgFtB;;;;;OAKG;IACH,OAAO,CAAC,WAAW;IAWnB;;;;;OAKG;IACH,OAAO,CAAE,yBAAyB;IAuDlC;;;;;;;;;;;;OAYG;YACY,sBAAsB;IA2GrC;;;;;;;;;;OAUG;IACH,OAAO,CAAE,eAAe;CA2KzB;AAED;;GAEG;AACH,eAAO,MAAM,kBAAkB,+BAAyB,CAAA;AAExD;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,MAAM,CAAC,EAAE,cAAc,GAAG,UAAU,CAElE"}
1
+ {"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../src/provider.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAIH,OAAO,KAAK,EACV,UAAU,EAIV,SAAS,EAET,UAAU,EAGX,MAAM,kBAAkB,CAAA;AASzB,OAAO,cAAc,CAAA;AAErB,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAA;AAsGhD,8DAA8D;AAC9D,eAAO,MAAM,8BAA8B,QAAS,CAAA;AAgGpD;;;;GAIG;AACH,cAAM,sBAAuB,YAAW,UAAU;IAChD,QAAQ,CAAC,IAAI,cAAa;IAC1B,OAAO,CAAC,MAAM,CAAQ;IACtB,OAAO,CAAC,YAAY,CAAQ;IAC5B,OAAO,CAAC,SAAS,CAAQ;IACzB,OAAO,CAAC,OAAO,CAAQ;IACvB,OAAO,CAAC,eAAe,CAAQ;IAC/B,OAAO,CAAC,QAAQ,CAAwB;IACxC,OAAO,CAAC,WAAW,CAAC,CAAqB;IACzC,OAAO,CAAC,aAAa,CAAC,CAAuB;IAC7C,OAAO,CAAC,mBAAmB,CAAQ;IACnC,OAAO,CAAC,sBAAsB,CAAQ;gBAE1B,MAAM,GAAE,cAAmB;IAwBvC;;;;;OAKG;IACI,IAAI,CAAC,MAAM,EAAE,UAAU,GAAG,aAAa,CAAC,SAAS,CAAC;IAiRzD;;;;;;;;;OASG;YACW,2BAA2B;IA0EzC;;;;;;;OAOG;IACH,OAAO,CAAC,iBAAiB;IA2BzB;;;;;;;OAOG;IACH,OAAO,CAAC,cAAc;IAgFtB;;;;;OAKG;IACH,OAAO,CAAC,WAAW;IAWnB;;;;;OAKG;IACH,OAAO,CAAE,yBAAyB;IAuDlC;;;;;;;;;;;;OAYG;YACY,sBAAsB;IA2GrC;;;;;;;;;;OAUG;IACH,OAAO,CAAE,eAAe;CA0LzB;AAED;;GAEG;AACH,eAAO,MAAM,kBAAkB,+BAAyB,CAAA;AAExD;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,MAAM,CAAC,EAAE,cAAc,GAAG,UAAU,CAElE"}
package/dist/provider.js CHANGED
@@ -298,18 +298,44 @@ class DeepseekAIProviderImpl {
298
298
  detail = errorBody;
299
299
  }
300
300
  logger.error('DeepSeek API error', { status: response.status, detail, errorBody });
301
+ // The status ladder decides what the CALLER can do, so every branch
302
+ // must stay distinguishable downstream: the turn classifier keys on
303
+ // these sentences, and an exhausted account must never read as
304
+ // "try again" (2026-10-20: a −$0.09 DeepSeek account answered 402 on
305
+ // every request and each one surfaced as the generic error — sixteen
306
+ // benchmark runs died at their first request, indistinguishable from
307
+ // an outage and each given a retry that could never succeed).
301
308
  const clientMessage = response.status === 429
302
309
  ? 'AI rate limit exceeded. Please try again shortly.'
303
310
  : response.status === 401
304
- ? 'AI service configuration error.'
305
- : response.status === 400 &&
306
- /prompt is too long|too many tokens|token.*limit|context.*length/i.test(detail)
307
- ? "Conversation too long for the model's context window. Use /compact to free space, or start a new conversation."
308
- : response.status === 400
309
- ? 'AI request was invalid — check the model and request parameters.'
310
- : response.status === 503
311
- ? 'AI service is temporarily overloaded. Please try again in a moment.'
312
- : 'AI service error. Please try again.';
311
+ ? // The status rides in the text: the turn classifier is
312
+ // text-only, and an auth failure must classify `auth`
313
+ // (never retried) — not the unknown bucket's pity retry.
314
+ 'AI service configuration error (HTTP 401) — the API key was rejected.'
315
+ : response.status === 402 ||
316
+ /insufficient balance|credit balance|payment required/i.test(detail)
317
+ ? // An exhausted account is a platform billing condition, not a
318
+ // request problem and not a transient outage — no retry can
319
+ // restore a negative balance.
320
+ 'AI service is unavailable — provider credit balance too low.'
321
+ : response.status === 400 &&
322
+ /prompt is too long|too many tokens|token.*limit|context.*length/i.test(detail)
323
+ ? "Conversation too long for the model's context window. Use /compact to free space, or start a new conversation."
324
+ : response.status === 400
325
+ ? 'AI request was invalid — check the model and request parameters.'
326
+ : response.status === 500 ||
327
+ response.status === 502 ||
328
+ response.status === 503 ||
329
+ response.status === 504 ||
330
+ response.status === 529
331
+ ? // The outage statuses the turn classifier reads as transient —
332
+ // one shared sentence, so a provider shed rides the retry
333
+ // ladder instead of killing the turn (was: 503 only).
334
+ 'AI service is temporarily overloaded. Please try again in a moment.'
335
+ : // Anything else still names its status, so a never-before-seen
336
+ // code is classifiable (and 5xx-shaped ones ride `http 5xx`
337
+ // into the transient class) instead of a bare "try again".
338
+ `AI service error (HTTP ${response.status}). Please try again.`;
313
339
  yield { type: 'error', message: clientMessage, errorKey: 'ai.error.apiError' };
314
340
  return;
315
341
  }
@@ -821,11 +847,24 @@ class DeepseekAIProviderImpl {
821
847
  code: streamError.code,
822
848
  message: streamError.message,
823
849
  });
824
- const clientMessage = /overload|capacity|503|529/i.test(detail)
825
- ? 'AI service is temporarily overloaded. Please try again in a moment.'
826
- : /rate.?limit|429|quota/i.test(detail)
827
- ? 'AI rate limit exceeded. Please try again shortly.'
828
- : 'AI service error. Please try again.';
850
+ // Same distinctions as the pre-flight ladder, in the same precedence
851
+ // the turn classifier applies (rate → auth → context → balance →
852
+ // transient): an exhausted account is a billing state (never
853
+ // transient, never "try again"), an auth failure stays `auth`, a
854
+ // context overflow stays recoverable. There is no HTTP status here —
855
+ // the stream answered 200 — so each class keys on the provider's own
856
+ // wording, plus numeric codes some hosts send as `code`.
857
+ const clientMessage = /rate.?limit|\b429\b|quota/i.test(detail)
858
+ ? 'AI rate limit exceeded. Please try again shortly.'
859
+ : /\b401\b|authentication|unauthorized/i.test(detail)
860
+ ? 'AI service authentication/configuration error — the API key was rejected.'
861
+ : /context.?length|context.?window|too long|too many tokens|token.?limit/i.test(detail)
862
+ ? "Conversation too long for the model's context window. Use /compact to free space, or start a new conversation."
863
+ : /insufficient balance|credit balance|payment required|\b402\b/i.test(detail)
864
+ ? 'AI service is unavailable — provider credit balance too low.'
865
+ : /overload|capacity|\b(?:500|502|503|504|529)\b/i.test(detail)
866
+ ? 'AI service is temporarily overloaded. Please try again in a moment.'
867
+ : 'AI service error. Please try again.';
829
868
  yield { type: 'error', message: clientMessage, errorKey: 'ai.error.apiError' };
830
869
  continue;
831
870
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@molecule/api-ai-deepseek",
3
- "version": "1.0.10",
3
+ "version": "1.0.11",
4
4
  "description": "DeepSeek AI provider for molecule.dev",
5
5
  "homepage": "https://www.molecule.dev/packages/api-ai-deepseek",
6
6
  "type": "module",