pi-provider-qoder-cn 0.2.19 → 0.2.20
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/dist/index.js +63 -25
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -2388,6 +2388,28 @@ function formatQoderStreamError(statusCode, rawBody, now = Date.now(), mode = "c
|
|
|
2388
2388
|
`- Next step: run /login qoder. You can also refresh credentials by exporting QODER_PERSONAL_ACCESS_TOKEN (PAT).`
|
|
2389
2389
|
].join("\n");
|
|
2390
2390
|
}
|
|
2391
|
+
if (code === "103" || /duplicate request/i.test(message)) {
|
|
2392
|
+
return isCn ? [
|
|
2393
|
+
`[Qoder \u91CD\u590D\u8BF7\u6C42] \u7F51\u5173\u628A\u8FD9\u6B21\u8BF7\u6C42\u5224\u5B9A\u4E3A\u91CD\u653E\u5E76\u62D2\u7EDD (\u9519\u8BEF\u7801 103 Duplicate request)`,
|
|
2394
|
+
`- \u539F\u56E0\uFF1A\u540C\u4E00\u4E2A\u5DF2\u7B7E\u540D\u7684\u8BF7\u6C42\u88AB\u518D\u6B21\u63D0\u4EA4\uFF08COSY Authorization/\u65F6\u95F4\u6233/\u7B7E\u540D \u672A\u5237\u65B0\uFF09\uFF0C\u5E76\u975E\u989D\u5EA6\u6216\u51ED\u8BC1\u95EE\u9898\u3002`,
|
|
2395
|
+
`- \u89E3\u51B3\u5EFA\u8BAE\uFF1A\u5BA2\u6237\u7AEF\u5E94\u4E3A\u6BCF\u6B21\u91CD\u8BD5\u91CD\u65B0\u7B7E\u540D\uFF1B\u82E5\u4ECD\u590D\u73B0\uFF0C\u8BF7\u7528 /model \u5207\u6362 Provider \u7A0D\u540E\u91CD\u8BD5\u3002`
|
|
2396
|
+
].join("\n") : [
|
|
2397
|
+
`[Qoder duplicate request] The gateway rejected this request as a replay (code 103 Duplicate request)`,
|
|
2398
|
+
`- Reason: an already-signed request (same COSY Authorization/timestamp/signature) was submitted again. This is a transient server error, not a quota or credential problem.`,
|
|
2399
|
+
`- Next step: every retry must be re-signed; if it keeps repeating, switch provider with /model and try again shortly.`
|
|
2400
|
+
].join("\n");
|
|
2401
|
+
}
|
|
2402
|
+
if (code === "10605" || /"isQueued"\s*:\s*true|isQueued/.test(message)) {
|
|
2403
|
+
return isCn ? [
|
|
2404
|
+
`[Qoder CN \u4E0A\u6E38\u6392\u961F] \u6A21\u578B\u7F51\u5173\u5F53\u524D\u5BB9\u91CF\u5DF2\u6EE1\uFF0C\u8BF7\u6C42\u8FDB\u5165\u7B49\u5F85\u961F\u5217 (\u9519\u8BEF\u7801 10605)`,
|
|
2405
|
+
`- \u8BF4\u660E\uFF1A\u51ED\u8BC1\u4E0E\u989D\u5EA6\u5747\u6B63\u5E38\uFF0C\u7EAF\u7CB9\u662F\u4E0A\u6E38\u6392\u961F\uFF1B\u5DF2\u6309\u7F51\u5173\u7ED9\u51FA\u7684 Retry-After \u91CD\u8BD5\u4ECD\u672A\u653E\u884C\u3002`,
|
|
2406
|
+
`- \u89E3\u51B3\u5EFA\u8BAE\uFF1A\u7A0D\u540E\u91CD\u8BD5\uFF0C\u6216\u7528 /model \u5207\u6362\u5230\u5176\u4ED6 Provider\uFF08\u5982\u5176\u4ED6\u6A21\u578B/\u6E20\u9053\uFF09\u3002`
|
|
2407
|
+
].join("\n") : [
|
|
2408
|
+
`[Qoder upstream queue] The model gateway is at capacity and parked this request (code 10605 isQueued)`,
|
|
2409
|
+
`- Meaning: credentials and quota are fine \u2014 this is pure upstream queuing; the gateway's own Retry-After wait did not clear it.`,
|
|
2410
|
+
`- Next step: retry shortly, or switch provider with /model while the queue drains.`
|
|
2411
|
+
].join("\n");
|
|
2412
|
+
}
|
|
2391
2413
|
if (rawBody === void 0 || rawBody === null) {
|
|
2392
2414
|
return `Upstream status ${statusCode}`;
|
|
2393
2415
|
}
|
|
@@ -3188,10 +3210,12 @@ function stableHash(prefix, ...inputs) {
|
|
|
3188
3210
|
}
|
|
3189
3211
|
return hash.digest("hex").slice(0, 16);
|
|
3190
3212
|
}
|
|
3191
|
-
function stableChatRecordID(model, messages, tools, maxTokens) {
|
|
3213
|
+
function stableChatRecordID(model, messages, tools, maxTokens, salt) {
|
|
3192
3214
|
const hash = crypto3.createHash("sha256");
|
|
3193
3215
|
hash.update("qoder-record");
|
|
3194
3216
|
hash.update("\0");
|
|
3217
|
+
hash.update(salt);
|
|
3218
|
+
hash.update("\0");
|
|
3195
3219
|
hash.update(model);
|
|
3196
3220
|
for (const msg of messages) {
|
|
3197
3221
|
if (msg?.role) {
|
|
@@ -3372,7 +3396,13 @@ function streamQoder(model, context, options) {
|
|
|
3372
3396
|
maxTokens = options.maxTokens;
|
|
3373
3397
|
}
|
|
3374
3398
|
const toolsRaw = resolved.tools.length > 0 ? transformTools(resolved.tools) : void 0;
|
|
3375
|
-
const recordID = stableChatRecordID(
|
|
3399
|
+
const recordID = stableChatRecordID(
|
|
3400
|
+
qoderModel,
|
|
3401
|
+
normalizedMessages,
|
|
3402
|
+
toolsRaw,
|
|
3403
|
+
maxTokens,
|
|
3404
|
+
`${sessionID}:${userID}`
|
|
3405
|
+
);
|
|
3376
3406
|
const requestedLevel = options?.reasoning;
|
|
3377
3407
|
const clamped = requestedLevel ? clampThinkingLevel(model, requestedLevel) : void 0;
|
|
3378
3408
|
const reasoningLevel = clamped === "off" ? void 0 : clamped;
|
|
@@ -3387,7 +3417,9 @@ function streamQoder(model, context, options) {
|
|
|
3387
3417
|
} else {
|
|
3388
3418
|
parameters.enable_thinking = false;
|
|
3389
3419
|
}
|
|
3390
|
-
const
|
|
3420
|
+
const modelSource = modelConfig.source || "system";
|
|
3421
|
+
const chatURL = getQoderChatURL(providerMode);
|
|
3422
|
+
const buildRequestBody = (attempt) => ({
|
|
3391
3423
|
request_id: crypto3.randomUUID(),
|
|
3392
3424
|
request_set_id: recordID,
|
|
3393
3425
|
chat_record_id: recordID,
|
|
@@ -3395,7 +3427,7 @@ function streamQoder(model, context, options) {
|
|
|
3395
3427
|
stream: true,
|
|
3396
3428
|
chat_task: "FREE_INPUT",
|
|
3397
3429
|
is_reply: true,
|
|
3398
|
-
is_retry:
|
|
3430
|
+
is_retry: attempt > 0,
|
|
3399
3431
|
source: 1,
|
|
3400
3432
|
version: "3",
|
|
3401
3433
|
session_type: "qodercli",
|
|
@@ -3436,18 +3468,31 @@ function streamQoder(model, context, options) {
|
|
|
3436
3468
|
name: lastUserText.substring(0, 30),
|
|
3437
3469
|
begin_at: Date.now()
|
|
3438
3470
|
}
|
|
3439
|
-
};
|
|
3440
|
-
const bodyBytes = Buffer.from(JSON.stringify(reqBody));
|
|
3441
|
-
const encodedBytes = qoderEncodeBody(bodyBytes);
|
|
3442
|
-
const chatURL = getQoderChatURL(providerMode);
|
|
3443
|
-
const headers = buildAuthHeaders(encodedBytes, chatURL, {
|
|
3444
|
-
userID,
|
|
3445
|
-
authToken: accessToken,
|
|
3446
|
-
name,
|
|
3447
|
-
email,
|
|
3448
|
-
machineID
|
|
3449
3471
|
});
|
|
3450
|
-
const
|
|
3472
|
+
const buildAttempt = (attempt) => {
|
|
3473
|
+
const encoded = qoderEncodeBody(Buffer.from(JSON.stringify(buildRequestBody(attempt))));
|
|
3474
|
+
return {
|
|
3475
|
+
encoded,
|
|
3476
|
+
headers: {
|
|
3477
|
+
"Content-Type": "application/json",
|
|
3478
|
+
Accept: "text/event-stream",
|
|
3479
|
+
"Cache-Control": "no-cache",
|
|
3480
|
+
"Accept-Encoding": "identity",
|
|
3481
|
+
"X-Model-Key": qoderModel,
|
|
3482
|
+
"X-Model-Source": modelSource,
|
|
3483
|
+
// Re-signed per attempt: the COSY payload carries its own requestId,
|
|
3484
|
+
// a second-granularity timestamp and a signature over the body, and
|
|
3485
|
+
// reusing any of them is what the gateway reads as a replay.
|
|
3486
|
+
...buildAuthHeaders(encoded, chatURL, {
|
|
3487
|
+
userID,
|
|
3488
|
+
authToken: accessToken,
|
|
3489
|
+
name,
|
|
3490
|
+
email,
|
|
3491
|
+
machineID
|
|
3492
|
+
})
|
|
3493
|
+
}
|
|
3494
|
+
};
|
|
3495
|
+
};
|
|
3451
3496
|
let queuedAttempt = 0;
|
|
3452
3497
|
await reader?.cancel().catch(() => {
|
|
3453
3498
|
});
|
|
@@ -3456,18 +3501,11 @@ function streamQoder(model, context, options) {
|
|
|
3456
3501
|
let buffer = "";
|
|
3457
3502
|
let bufferStart = 0;
|
|
3458
3503
|
for (; ; ) {
|
|
3504
|
+
const current = buildAttempt(queuedAttempt);
|
|
3459
3505
|
const response = await fetch(chatURL, {
|
|
3460
3506
|
method: "POST",
|
|
3461
|
-
headers:
|
|
3462
|
-
|
|
3463
|
-
Accept: "text/event-stream",
|
|
3464
|
-
"Cache-Control": "no-cache",
|
|
3465
|
-
"Accept-Encoding": "identity",
|
|
3466
|
-
"X-Model-Key": qoderModel,
|
|
3467
|
-
"X-Model-Source": modelSource,
|
|
3468
|
-
...headers
|
|
3469
|
-
},
|
|
3470
|
-
body: encodedBytes,
|
|
3507
|
+
headers: current.headers,
|
|
3508
|
+
body: current.encoded,
|
|
3471
3509
|
signal: options?.signal
|
|
3472
3510
|
});
|
|
3473
3511
|
if (!response.ok) {
|
package/package.json
CHANGED