更新
This commit is contained in:
@@ -100,11 +100,14 @@ assistantStreamExpect(
|
||||
);
|
||||
assistantStreamExpect(
|
||||
str_contains($controller, "'text' => \$delta")
|
||||
&& str_contains($controller, "'code' => 'AI_ASSISTANT_FAILED'")
|
||||
&& str_contains($controller, 'DiagnosisAiLogic::getAssistantErrorCode()')
|
||||
&& str_contains($controller, 'DiagnosisAiLogic::getError()')
|
||||
&& str_contains($controller, 'ignore_user_abort(true)')
|
||||
&& str_contains($controller, 'connection_aborted() === 1')
|
||||
&& !str_contains($controller, "DiagnosisAiLogic::getError()\n ]"),
|
||||
'delta carries text, disconnects abort upstream, and errors use a generic prompt-free payload'
|
||||
&& str_contains($logic, '!$deliveredDelta')
|
||||
&& str_contains($logic, "['UPSTREAM_REJECTED', 'INCOMPLETE_RESPONSE', 'EMPTY_RESPONSE']")
|
||||
&& str_contains($logic, 'DifyChatService::chat('),
|
||||
'delta carries text, disconnects abort upstream, and pre-delta stream failures safely fall back once'
|
||||
);
|
||||
assistantStreamExpect(
|
||||
str_contains($logic, 'DifyChatService::chat(')
|
||||
|
||||
@@ -95,6 +95,37 @@ $explicitOpenAi = callDifyStreamPrivate('buildRequestSpecs', [
|
||||
difyStreamExpect(count($explicitDify) === 1 && $explicitDify[0]['protocol'] === 'dify', 'explicit Dify endpoint never changes protocol');
|
||||
difyStreamExpect(count($explicitOpenAi) === 1 && $explicitOpenAi[0]['protocol'] === 'openai', 'explicit OpenAI endpoint never changes protocol');
|
||||
|
||||
$retryableStream = [
|
||||
'errno' => 0,
|
||||
'http_code' => 200,
|
||||
'emitted' => false,
|
||||
'upstream_error' => true,
|
||||
'finished' => false,
|
||||
];
|
||||
difyStreamExpect(
|
||||
callDifyStreamPrivate('shouldTryNextProtocol', [$retryableStream, true]) === true,
|
||||
'a terminal-free stream error before any delta tries the alternate protocol'
|
||||
);
|
||||
$retryableStream['emitted'] = true;
|
||||
difyStreamExpect(
|
||||
callDifyStreamPrivate('shouldTryNextProtocol', [$retryableStream, true]) === false,
|
||||
'an emitted delta forbids protocol retry'
|
||||
);
|
||||
difyStreamExpect(
|
||||
callDifyStreamPrivate('shouldTryNextProtocol', [[
|
||||
'errno' => 0,
|
||||
'http_code' => 400,
|
||||
], false]) === true,
|
||||
'an ambiguous endpoint rejected before generation tries the alternate protocol'
|
||||
);
|
||||
difyStreamExpect(
|
||||
callDifyStreamPrivate('shouldTryNextProtocol', [[
|
||||
'errno' => 0,
|
||||
'http_code' => 401,
|
||||
], true]) === false,
|
||||
'credential failures are not hidden by protocol retry'
|
||||
);
|
||||
|
||||
$difyWire = ": ping\r\n\r\n"
|
||||
. "data: {\"event\":\"message\",\"answer\":\"你\",\"message_id\":\"msg-safe\"}\r\n\r\n"
|
||||
. "data: {\"event\":\"agent_message\",\"answer\":\"好\"}\r\n\r\n"
|
||||
|
||||
@@ -192,6 +192,40 @@ expectSame(false, callPrivate('shouldRetryWithoutFiles', [400, []]), 'a text-onl
|
||||
expectSame(false, callPrivate('shouldRetryWithoutFiles', [401, $capped['kept']]), 'a credential failure is not retried');
|
||||
expectSame(false, callPrivate('shouldRetryWithoutFiles', [500, $capped['kept']]), 'an upstream outage is not retried here');
|
||||
|
||||
// 协议回退会把最初的“附件被拒”换成另一协议的状态码(Dify 400 -> OpenAI 404),
|
||||
// 降级判断必须按每次响应累计,否则去掉附件的重试永远不会发生。
|
||||
expectSame(
|
||||
true,
|
||||
callPrivate('isFileRejection', [['errno' => 0, 'http_code' => 400], $capped['kept']]),
|
||||
'an attachment rejection is recognised on the response that carried it'
|
||||
);
|
||||
expectSame(
|
||||
false,
|
||||
callPrivate('isFileRejection', [['errno' => 0, 'http_code' => 404], $capped['kept']]),
|
||||
'the fallback protocol 404 is not itself an attachment rejection'
|
||||
);
|
||||
expectSame(
|
||||
true,
|
||||
callPrivate('isFileRejection', [
|
||||
['errno' => 0, 'http_code' => 200, 'upstream_error' => true],
|
||||
$capped['kept'],
|
||||
]),
|
||||
'a 200 stream carrying event:error counts as an attachment rejection'
|
||||
);
|
||||
expectSame(
|
||||
false,
|
||||
callPrivate('isFileRejection', [
|
||||
['errno' => 0, 'http_code' => 200, 'upstream_error' => true],
|
||||
[],
|
||||
]),
|
||||
'a text-only request never degrades further'
|
||||
);
|
||||
expectSame(
|
||||
false,
|
||||
callPrivate('isFileRejection', [['errno' => 28, 'http_code' => 0], $capped['kept']]),
|
||||
'a transport failure is not mistaken for an attachment rejection'
|
||||
);
|
||||
|
||||
// Dify 的 inputs 必须是 JSON 对象。PHP 空数组会被编码成 [],上游以
|
||||
// invalid_param 拒绝整单——空 inputs 的调用方会 100% 失败。
|
||||
$emptyInputs = callPrivate('buildRequestSpecs', [
|
||||
|
||||
Reference in New Issue
Block a user