fix: normalize OpenAI/GitHub finish_reason to Flynn stopReason conventions

OpenAI-compatible providers return 'stop' and 'tool_calls' as finish_reason
values, but Flynn's agent loop expects Anthropic-style 'end_turn' and
'tool_use'. This caused the agent to exit the tool loop prematurely when
falling back to GitHub Copilot (due to Anthropic API quota exhaustion).

- openai.ts: Map 'stop' → 'end_turn', 'length' → 'max_tokens', tool_calls
  with actual tools → 'tool_use', tool_calls without tools → 'end_turn'
- github.ts: Handle edge case where finish_reason is 'tool_calls' but no
  tools were parsed
- agent.ts: Accept both 'tool_use' and 'tool_calls' as valid stop reasons
  (belt-and-suspenders), extract toolCalls to local variable for TS narrowing
- openai.test.ts: Update expectations to match new normalized values
This commit is contained in:
William Valentin
2026-02-11 09:49:36 -08:00
parent 1aab006a7f
commit 01c3175fdb
4 changed files with 37 additions and 9 deletions
+2 -2
View File
@@ -29,7 +29,7 @@ describe('OpenAIClient', () => {
});
expect(response.content).toBe('Hello from GPT!');
expect(response.stopReason).toBe('stop');
expect(response.stopReason).toBe('end_turn');
expect(response.usage.inputTokens).toBe(10);
expect(response.usage.outputTokens).toBe(5);
});
@@ -66,7 +66,7 @@ describe('OpenAIClient tool use', () => {
}],
});
expect(response.stopReason).toBe('tool_calls');
expect(response.stopReason).toBe('tool_use');
expect(response.toolCalls).toHaveLength(1);
expect(response.toolCalls![0]).toEqual({
id: 'call_1',