false, 'error_code' => 'INCOMPLETE_RESPONSE', 'error' => 'fixture']; } public static function chat($profile, $inputs, $query, $user, $files = [], $options = []): array { self::$blocking[] = $options; return ['ok' => true, 'content' => '合成模型最终回答']; } } } namespace { require dirname(__DIR__) . '/vendor/autoload.php'; use app\adminapi\logic\tcm\DiagnosisAiLogic; use app\adminapi\service\AssistantSseTiming; use app\common\service\DifyChatService; function retryExpect(bool $ok, string $message): void { if (!$ok) throw new \RuntimeException($message); } $prepared = ['profile' => 'qwen', 'task' => 'summary', 'query' => '合成资料', 'upstream_timeout' => 90]; DifyChatService::$delayUs = 2000; $run = static function (array $request, ?callable $abort = null) { return DiagnosisAiLogic::streamPreparedAssistant($request, static fn (string $text): bool => true, $abort, new AssistantSseTiming()); }; retryExpect($run($prepared) !== null && count(DifyChatService::$blocking) === 1, 'one pre-delta compatibility retry is retained'); $timeout = DifyChatService::$blocking[0]['timeout']; retryExpect($timeout > 0 && $timeout < 90, 'blocking retry only gets the remaining original budget'); DifyChatService::$blocking = []; DifyChatService::$emit = true; retryExpect($run($prepared) === null && DifyChatService::$blocking === [], 'no re-submission after real text delivery'); DifyChatService::$emit = false; retryExpect($run($prepared, static fn (): bool => true) === null && DifyChatService::$blocking === [], 'no compatibility request after disconnect'); DifyChatService::$delayUs = 1100000; $prepared['upstream_timeout'] = 1; retryExpect($run($prepared) === null && DifyChatService::$blocking === [], 'an exhausted stream cannot start another timeout window'); echo "Diagnosis AI assistant retry budget: OK\n"; }