Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
64e6bc1
feat(runtime\provider):初步重构多模态机制
phantom5099 Apr 15, 2026
0728dc6
fix(tui): remove legacy compatibility path and restore multimodal/ses…
xgopilot Apr 15, 2026
6618ee6
fix(provider): validate parts and simplify message conversion
xgopilot Apr 16, 2026
9bdd63a
Merge pull request #19 from phantom5099/fork-pr-315-1776306016
phantom5099 Apr 16, 2026
7107222
fix(runtime): align todo integration test with parts input
xgopilot Apr 16, 2026
c300874
Merge pull request #20 from phantom5099/fork-pr-315-1776306016
phantom5099 Apr 16, 2026
e874d44
merge(main): resolve PR #315 conflicts for runtime parts/todo integra…
xgopilot Apr 16, 2026
13eec8c
Merge pull request #21 from phantom5099/fork-pr-315-1776306016
phantom5099 Apr 16, 2026
8472088
Merge remote-tracking branch 'upstream/main'
phantom5099 Apr 16, 2026
491af12
pref(runtime\provider):重构多模态机制
phantom5099 Apr 16, 2026
0232b2c
fix(provider): tighten multimodal part validation and empty message s…
xgopilot Apr 16, 2026
f917dbc
Merge pull request #22 from phantom5099/fork-pr-322-1776338584
phantom5099 Apr 16, 2026
26fc9d4
fix(multimodal): redact transcript image identifiers and tighten memo…
xgopilot Apr 16, 2026
738ed47
Merge pull request #24 from phantom5099/fork-pr-322-1776338584
phantom5099 Apr 16, 2026
a154b10
fix(multimodal): preserve blocked input and validate blank image url
xgopilot Apr 16, 2026
88414d5
Merge pull request #25 from phantom5099/fork-pr-322-1776345239
phantom5099 Apr 16, 2026
d27da6a
Merge branch 'main' into main
phantom5099 Apr 16, 2026
e3271a9
修复错误
phantom5099 Apr 16, 2026
5b7a8c0
test(pr322): fix tui compile break and increase multimodal coverage
xgopilot Apr 16, 2026
8ac26e4
Merge pull request #26 from phantom5099/fork-pr-322-1776345239
phantom5099 Apr 16, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 11 additions & 11 deletions internal/app/bootstrap_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1121,13 +1121,13 @@ func TestRuntimeMemoExtractorFuncSchedule(t *testing.T) {
if sessionID != "session-1" {
t.Fatalf("unexpected session id %q", sessionID)
}
if len(messages) != 1 || messages[0].Content != "hi" {
if len(messages) != 1 || renderPartsForTest(messages[0].Parts) != "hi" {
t.Fatalf("unexpected messages %+v", messages)
}
})

extractor.Schedule("session-1", []providertypes.Message{
{Role: providertypes.RoleUser, Content: "hi"},
{Role: providertypes.RoleUser, Parts: []providertypes.ContentPart{providertypes.NewTextPart("hi")}},
})

if !called {
Expand All @@ -1144,14 +1144,14 @@ func TestTextGenAdapterGenerate(t *testing.T) {
if prompt != "prompt" {
t.Fatalf("unexpected prompt %q", prompt)
}
if len(msgs) != 1 || msgs[0].Content != "msg" {
if len(msgs) != 1 || renderPartsForTest(msgs[0].Parts) != "msg" {
t.Fatalf("unexpected messages %+v", msgs)
}
return "ok", nil
})

result, err := adapter.Generate(context.Background(), "prompt", []providertypes.Message{
{Role: providertypes.RoleUser, Content: "msg"},
{Role: providertypes.RoleUser, Parts: []providertypes.ContentPart{providertypes.NewTextPart("msg")}},
})
if err != nil {
t.Fatalf("Generate() error = %v", err)
Expand All @@ -1173,7 +1173,7 @@ func TestNewMemoExtractorAdapterSkipsWhenSchedulerNil(t *testing.T) {
extractor := newMemoExtractorAdapter(nil, manager, nil)

extractor.Schedule("session-1", []providertypes.Message{
{Role: providertypes.RoleUser, Content: "remember this"},
{Role: providertypes.RoleUser, Parts: []providertypes.ContentPart{providertypes.NewTextPart("remember this")}},
})
}

Expand All @@ -1187,7 +1187,7 @@ func TestNewMemoExtractorAdapterSkipsWhenResolveProviderFails(t *testing.T) {
extractor := newMemoExtractorAdapter(nil, manager, scheduler)

extractor.Schedule("session-1", []providertypes.Message{
{Role: providertypes.RoleUser, Content: "remember this"},
{Role: providertypes.RoleUser, Parts: []providertypes.ContentPart{providertypes.NewTextPart("remember this")}},
})

if scheduler.called {
Expand Down Expand Up @@ -1218,7 +1218,7 @@ func TestNewMemoExtractorAdapterSchedulesExtractorAndGenerates(t *testing.T) {
extractor := newMemoExtractorAdapter(factory, manager, scheduler)

inputMessages := []providertypes.Message{
{Role: providertypes.RoleUser, Content: "remember 我偏好 Go"},
{Role: providertypes.RoleUser, Parts: []providertypes.ContentPart{providertypes.NewTextPart("remember 我偏好 Go")}},
}
extractor.Schedule("session-1", inputMessages)

Expand Down Expand Up @@ -1266,14 +1266,14 @@ func TestNewMemoExtractorAdapterBuildsProviderSafeMemoWindow(t *testing.T) {
extractor := newMemoExtractorAdapter(factory, manager, scheduler)

inputMessages := []providertypes.Message{
{Role: providertypes.RoleUser, Content: "first"},
{Role: providertypes.RoleUser, Parts: []providertypes.ContentPart{providertypes.NewTextPart("first")}},
{
Role: providertypes.RoleAssistant,
ToolCalls: []providertypes.ToolCall{
{ID: "call_1", Name: "filesystem_read_file", Arguments: `{}`},
},
},
{Role: providertypes.RoleUser, Content: "second"},
{Role: providertypes.RoleUser, Parts: []providertypes.ContentPart{providertypes.NewTextPart("second")}},
}
extractor.Schedule("session-1", inputMessages)
if !scheduler.called || scheduler.extractor == nil {
Expand Down Expand Up @@ -1319,7 +1319,7 @@ func TestNewMemoExtractorAdapterKeepsScheduledConfigSnapshot(t *testing.T) {
scheduler := &stubMemoExtractorScheduler{}
extractor := newMemoExtractorAdapter(factory, manager, scheduler)

messages := []providertypes.Message{{Role: providertypes.RoleUser, Content: "remember snapshot"}}
messages := []providertypes.Message{{Role: providertypes.RoleUser, Parts: []providertypes.ContentPart{providertypes.NewTextPart("remember snapshot")}}}
extractor.Schedule("session-1", messages)
if !scheduler.called || scheduler.extractor == nil {
t.Fatalf("expected scheduler to receive extractor")
Expand Down Expand Up @@ -1358,7 +1358,7 @@ func TestNewMemoExtractorAdapterPropagatesFactoryBuildError(t *testing.T) {
extractor := newMemoExtractorAdapter(factory, manager, scheduler)

inputMessages := []providertypes.Message{
{Role: providertypes.RoleUser, Content: "remember coding style"},
{Role: providertypes.RoleUser, Parts: []providertypes.ContentPart{providertypes.NewTextPart("remember coding style")}},
}
extractor.Schedule("session-1", inputMessages)
if !scheduler.called || scheduler.extractor == nil {
Expand Down
20 changes: 20 additions & 0 deletions internal/app/parts_render_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package app

import (
"strings"

providertypes "neo-code/internal/provider/types"
)

func renderPartsForTest(parts []providertypes.ContentPart) string {
var builder strings.Builder
for _, part := range parts {
switch part.Kind {
case providertypes.ContentPartText:
builder.WriteString(part.Text)
case providertypes.ContentPartImage:
builder.WriteString("[Image]")
}
}
return builder.String()
}
2 changes: 1 addition & 1 deletion internal/config/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,7 @@ const (

QiniuName = "qiniu"
QiniuDefaultBaseURL = "https://api.qnaigc.com/v1"
Comment thread
phantom5099 marked this conversation as resolved.
QiniuDefaultModel = "openai/gpt-5"
QiniuDefaultModel = "z-ai/glm-5.1"
Comment thread
phantom5099 marked this conversation as resolved.
QiniuDefaultAPIKeyEnv = "QINIU_API_KEY"
)

Expand Down
Loading
Loading