feat(followup-audio): review full dialogue and bind roles before extraction

This commit is contained in:
2026-10-10 14:25:03 +08:00
parent f015b26ae1
commit b4acad8510
14 changed files with 360 additions and 43 deletions
@@ -96,7 +96,7 @@ final class FollowupAudioPipeline
self::assertTranscriptQuality($transcript, $segments);
if ($state['extraction']['state'] !== 'complete') {
$requestId = 'fa-' . bin2hex(random_bytes(16));
$payload = $this->extractRequest($transcript, $segments, $task['recorded_at'], FollowupAudioFields::catalog(), $requestId);
$payload = $this->extractRequest($transcript, $segments, $task['recorded_at'], FollowupAudioFields::catalog(), $requestId, FollowupAudioStore::taskChannelRoles($task));
self::beat($heartbeat, []);
$this->assertSource($audio['path'], $task['sha256']);
$next = $state; $next['extraction'] = ['state' => 'intent', 'request_id' => $requestId];
@@ -139,7 +139,7 @@ final class FollowupAudioPipeline
}
/** Pure production request builder for authorized cached-ASR acceptance; performs no network or state mutation. */
public function extractRequest(string $transcript, array $segments, string $recordedAt, array $catalog, ?string $requestId = null): array
public function extractRequest(string $transcript, array $segments, string $recordedAt, array $catalog, ?string $requestId = null, string $channelRoles = 'unconfirmed'): array
{
$part = $this->provider['extraction'];
$mode = $part['response_format'] ?? 'json_schema';
@@ -148,7 +148,7 @@ final class FollowupAudioPipeline
if (!in_array($mode, ['json_schema', 'json_object', 'prompt_json'], true)
|| !is_int($maxTokens) || $maxTokens < 256 || $maxTokens > 8192
|| ($thinking !== null && !is_bool($thinking))) { throw new FollowupAudioException('CONFIG_INVALID'); }
$prompt = FollowupAudioTranscriptPrompt::build($transcript, $segments, $recordedAt, $catalog);
$prompt = FollowupAudioTranscriptPrompt::build($transcript, $segments, $recordedAt, $catalog, $channelRoles);
self::assertTranscriptQuality($transcript, $segments);
if (($part['protocol'] ?? 'openai') === 'dify_chat') {
if ($mode !== 'prompt_json' || empty($part['binding_revision']) || $thinking !== null) { throw new FollowupAudioException('CONFIG_INVALID'); }