@mathew-macharia/black-mamba 1.0.3 → 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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mathew-macharia/black-mamba",
3
- "version": "1.0.3",
3
+ "version": "1.0.5",
4
4
  "description": "OpenAI-compatible proxy that maps chat sessions onto DeepSeek web chat",
5
5
  "type": "module",
6
6
  "main": "index.js",
@@ -21,6 +21,21 @@ export function upstreamReason(jsonBody, rawText, status) {
21
21
  return jsonBody?.data?.biz_msg || jsonBody?.msg || (rawText ? rawText.slice(0, 200) : "") || `HTTP ${status}`;
22
22
  }
23
23
 
24
+ /** Safe fields from an auth-failure response for account logs. */
25
+ export function deepSeekAuthFacts(res, jsonBody = null) {
26
+ const facts = { http: res?.status ?? null };
27
+ const waf = res?.headers?.get?.("x-amzn-waf-action");
28
+ if (waf) facts.waf = waf;
29
+ if (jsonBody && typeof jsonBody === "object") {
30
+ if (jsonBody.code != null) facts.code = jsonBody.code;
31
+ if (jsonBody.msg != null) facts.msg = String(jsonBody.msg).slice(0, 300);
32
+ const data = jsonBody.data;
33
+ if (data?.biz_code != null) facts.biz_code = data.biz_code;
34
+ if (data?.biz_msg != null) facts.biz_msg = String(data.biz_msg).slice(0, 300);
35
+ }
36
+ return facts;
37
+ }
38
+
24
39
  /**
25
40
  * True only when DeepSeek tells us the chat session or parent message we referenced is gone.
26
41
  * Deliberately narrow: anything else is a real failure that must surface to the client.
@@ -3,6 +3,7 @@
3
3
  import { CONFIG } from "../config.js";
4
4
  import { DeepSeekAuthError, UpstreamContextRejectedError, UpstreamError } from "../errors.js";
5
5
  import {
6
+ deepSeekAuthFacts,
6
7
  isDeepSeekAuthFailure,
7
8
  isHumanChallengeRequired,
8
9
  isStaleContextRejection,
@@ -22,10 +23,12 @@ const SESSION_EXPIRED_NOTICE = "DeepSeek session expired. Paste a fresh cURL in
22
23
  * @param {(reason: string) => void} [deps.onAuthFailure] Called once per detected credential failure.
23
24
  */
24
25
  export function createDeepSeekClient({ auth, powSolver, fetchImpl = fetch, config = CONFIG.deepseek, onAuthFailure = () => {} }) {
25
- function authFailure(notice) {
26
+ function authFailure(notice, res, jsonBody = null) {
26
27
  auth.markInvalid();
27
- onAuthFailure(notice);
28
- return new DeepSeekAuthError(notice);
28
+ const facts = res ? deepSeekAuthFacts(res, jsonBody) : null;
29
+ if (facts) onAuthFailure(`${notice} ${JSON.stringify(facts)}`);
30
+ else onAuthFailure(notice);
31
+ return new DeepSeekAuthError(notice, facts ?? undefined);
29
32
  }
30
33
 
31
34
  function ensureCredentials() {
@@ -51,7 +54,7 @@ export function createDeepSeekClient({ auth, powSolver, fetchImpl = fetch, confi
51
54
  const json = await res.json().catch(() => null);
52
55
 
53
56
  if (isDeepSeekAuthFailure(res, json)) {
54
- throw authFailure("DeepSeek session expired while creating chat session. " + SESSION_EXPIRED_NOTICE);
57
+ throw authFailure("DeepSeek session expired while creating chat session. " + SESSION_EXPIRED_NOTICE, res, json);
55
58
  }
56
59
  const remoteId = json?.data?.biz_data?.id || json?.data?.biz_data?.chat_session?.id;
57
60
  if (!res.ok || typeof remoteId !== "string" || !remoteId) {
@@ -67,7 +70,7 @@ export function createDeepSeekClient({ auth, powSolver, fetchImpl = fetch, confi
67
70
  const res = await postJson(config.powChallengeUrl, { target_path: config.powTargetPath });
68
71
 
69
72
  if (isWafChallengeResponse(res)) {
70
- throw authFailure("AWS WAF cookie expired during PoW challenge. " + SESSION_EXPIRED_NOTICE);
73
+ throw authFailure("AWS WAF cookie expired during PoW challenge. " + SESSION_EXPIRED_NOTICE, res);
71
74
  }
72
75
  let json;
73
76
  try {
@@ -76,7 +79,11 @@ export function createDeepSeekClient({ auth, powSolver, fetchImpl = fetch, confi
76
79
  throw new UpstreamError(`Invalid PoW challenge response (HTTP ${res.status})`, { code: "pow_challenge_invalid" });
77
80
  }
78
81
  if (isDeepSeekAuthFailure(res, json)) {
79
- throw authFailure(isHumanChallengeRequired(json) ? HUMAN_CHALLENGE_NOTICE : "DeepSeek session expired during PoW challenge. " + SESSION_EXPIRED_NOTICE);
82
+ throw authFailure(
83
+ isHumanChallengeRequired(json) ? HUMAN_CHALLENGE_NOTICE : "DeepSeek session expired during PoW challenge. " + SESSION_EXPIRED_NOTICE,
84
+ res,
85
+ json
86
+ );
80
87
  }
81
88
  const challenge = json?.data?.biz_data?.challenge;
82
89
  if (!res.ok || !challenge) {
@@ -117,7 +124,7 @@ export function createDeepSeekClient({ auth, powSolver, fetchImpl = fetch, confi
117
124
  );
118
125
 
119
126
  if (isWafChallengeResponse(res) || res.status === 401) {
120
- throw authFailure("DeepSeek returned unauthorized / WAF challenge on chat completion. " + SESSION_EXPIRED_NOTICE);
127
+ throw authFailure("DeepSeek returned unauthorized / WAF challenge on chat completion. " + SESSION_EXPIRED_NOTICE, res);
121
128
  }
122
129
 
123
130
  const contentType = res.headers.get("content-type") || "";
@@ -130,7 +137,7 @@ export function createDeepSeekClient({ auth, powSolver, fetchImpl = fetch, confi
130
137
  // non-JSON body
131
138
  }
132
139
  if (isDeepSeekAuthFailure(res, errJson)) {
133
- throw authFailure(isHumanChallengeRequired(errJson) ? HUMAN_CHALLENGE_NOTICE : SESSION_EXPIRED_NOTICE);
140
+ throw authFailure(isHumanChallengeRequired(errJson) ? HUMAN_CHALLENGE_NOTICE : SESSION_EXPIRED_NOTICE, res, errJson);
134
141
  }
135
142
  const details = { status: res.status, body: errJson ?? rawText.slice(0, 500), chat_session_id: chatSessionId, parent_message_id: parentMessageId };
136
143
  if (isStaleContextRejection(res, errJson, config.staleContextBizCodes)) {