feat: Introduce model alias resolution, enhanced configuration options, and improved OpenAI/Claude adapter handling for responses, embeddings, and tool calls.

This commit is contained in:
CJACK
2026-02-18 23:06:18 +08:00
parent 27ecb4b69b
commit 3a75b75ae0
28 changed files with 1665 additions and 183 deletions

View File

@@ -10,6 +10,7 @@ import (
var toolCallPattern = regexp.MustCompile(`\{\s*["']tool_calls["']\s*:\s*\[(.*?)\]\s*\}`)
var fencedJSONPattern = regexp.MustCompile("(?s)```(?:json)?\\s*(.*?)\\s*```")
var fencedBlockPattern = regexp.MustCompile("(?s)```.*?```")
type ParsedToolCall struct {
Name string `json:"name"`
@@ -20,6 +21,10 @@ func ParseToolCalls(text string, availableToolNames []string) []ParsedToolCall {
if strings.TrimSpace(text) == "" {
return nil
}
text = stripFencedCodeBlocks(text)
if strings.TrimSpace(text) == "" {
return nil
}
candidates := buildToolCallCandidates(text)
var parsed []ParsedToolCall
@@ -45,11 +50,6 @@ func ParseStandaloneToolCalls(text string, availableToolNames []string) []Parsed
return nil
}
candidates := []string{trimmed}
if strings.HasPrefix(trimmed, "```") && strings.HasSuffix(trimmed, "```") {
if m := fencedJSONPattern.FindStringSubmatch(trimmed); len(m) >= 2 {
candidates = append(candidates, strings.TrimSpace(m[1]))
}
}
for _, candidate := range candidates {
candidate = strings.TrimSpace(candidate)
if candidate == "" {
@@ -321,23 +321,14 @@ func looksLikeToolExampleContext(text string) bool {
if t == "" {
return false
}
cues := []string{
"```",
"示例",
"例子",
"for example",
"example",
"demo",
"请勿执行",
"不要执行",
"do not execute",
return strings.Contains(t, "```")
}
func stripFencedCodeBlocks(text string) string {
if strings.TrimSpace(text) == "" {
return ""
}
for _, cue := range cues {
if strings.Contains(t, cue) {
return true
}
}
return false
return fencedBlockPattern.ReplaceAllString(text, " ")
}
func FormatOpenAIToolCalls(calls []ParsedToolCall) []map[string]any {

View File

@@ -19,11 +19,8 @@ func TestParseToolCalls(t *testing.T) {
func TestParseToolCallsFromFencedJSON(t *testing.T) {
text := "I will call tools now\n```json\n{\"tool_calls\":[{\"name\":\"search\",\"input\":{\"q\":\"news\"}}]}\n```"
calls := ParseToolCalls(text, []string{"search"})
if len(calls) != 1 {
t.Fatalf("expected 1 call, got %d", len(calls))
}
if calls[0].Input["q"] != "news" {
t.Fatalf("unexpected args: %#v", calls[0].Input)
if len(calls) != 0 {
t.Fatalf("expected fenced tool_call example to be ignored, got %#v", calls)
}
}

View File

@@ -416,18 +416,6 @@ func TestParseStandaloneToolCallsFencedCodeBlock(t *testing.T) {
// ─── looksLikeToolExampleContext ─────────────────────────────────────
func TestLooksLikeToolExampleContextChinese(t *testing.T) {
if !looksLikeToolExampleContext("下面是示例") {
t.Fatal("expected true for Chinese example context")
}
}
func TestLooksLikeToolExampleContextEnglish(t *testing.T) {
if !looksLikeToolExampleContext("here is an example of") {
t.Fatal("expected true for English example context")
}
}
func TestLooksLikeToolExampleContextNone(t *testing.T) {
if looksLikeToolExampleContext("I will call the tool now") {
t.Fatal("expected false for non-example context")