Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ require (
github.com/pion/sdp/v3 v3.0.20
github.com/pion/stun/v3 v3.1.7
github.com/pion/webrtc/v4 v4.2.22
github.com/router-for-me/CLIProxyAPI/v8 v8.0.22
github.com/router-for-me/CLIProxyAPI/v8 v8.0.23
github.com/router-for-me/CLIProxyAPI/v8/gptload-embedded v0.0.0
github.com/sirupsen/logrus v1.10.2
github.com/tidwall/gjson v1.19.0
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -245,8 +245,8 @@ github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
github.com/rogpeppe/go-internal v1.15.0 h1:D0RCU5rMAp+SpgkiNdrjfJ+LX4J1M32V2NeCY7EJ6hc=
github.com/rogpeppe/go-internal v1.15.0/go.mod h1:DrUVZyrJU+txYW5/1kwtXQSMFio52ZOxX7yM1VHvnxs=
github.com/router-for-me/CLIProxyAPI/v8 v8.0.22 h1:KX7c+ThdMlhG+SiDSYrMLByAbaqhU4Azl7yR9ihu2HY=
github.com/router-for-me/CLIProxyAPI/v8 v8.0.22/go.mod h1:j1Mtcj0TrC66O1JwbSBB03lY3uYPx4J7yHNvU6nDBCo=
github.com/router-for-me/CLIProxyAPI/v8 v8.0.23 h1:q1bfXpXxPV8BbpSFNJGeqJnReMLyZEW8pAG0y/MHPSQ=
github.com/router-for-me/CLIProxyAPI/v8 v8.0.23/go.mod h1:j1Mtcj0TrC66O1JwbSBB03lY3uYPx4J7yHNvU6nDBCo=
github.com/rs/xid v1.6.0/go.mod h1:7XoLgs4eV+QndskICGsho+ADou8ySMSjJKDIan90Nz0=
github.com/rs/zerolog v1.34.0 h1:k43nTLIwcTVQAncfCw4KZ2VY6ukYoZaBPNOE8txlOeY=
github.com/rs/zerolog v1.34.0/go.mod h1:bJsvje4Z08ROH4Nhs5iH600c3IkWhwp44iRc54W6wYQ=
Expand Down
2 changes: 1 addition & 1 deletion internal/catalog/codex_client_models.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ const (
// CodexModelCatalogVersion identifies the Codex client contract represented by the embedded snapshot.
CodexModelCatalogVersion = modelcatalog.ClientVersion
// CodexModelCatalogCPASDKVersion identifies the CPA SDK release tested with this snapshot.
CodexModelCatalogCPASDKVersion = "v8.0.22"
CodexModelCatalogCPASDKVersion = "v8.0.23"
codexModelCatalogSHA256 = modelcatalog.ClientSHA256
codexFallbackModel = "gpt-5.5"
)
Expand Down
12 changes: 10 additions & 2 deletions internal/gateway/websocket_interrupt.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,14 @@ func (s *websocketConnection) handleInterrupt(turn websocketTurn, fields map[str
binding := s.binding
parent, found := s.parents[responseID]
s.mu.Unlock()
if binding == nil || !found || parent.complete || (turn.lane != "" && turn.lane != parent.lane) {
if binding == nil || !found || (turn.lane != "" && turn.lane != parent.lane) {
s.emitReason(turn.lane, reasonWebsocketResponseNotActive)
return
}
// 已结束响应的迟到中断不应留下 error 帧污染下一轮。
if parent.complete {
return
}
if !websocketGroupEnabled(snapshot, key, binding.ref.GroupID) {
s.emitReason(parent.lane, reasonWebsocketDisabled)
return
Expand All @@ -49,11 +53,15 @@ func (s *websocketConnection) handleInterrupt(turn websocketTurn, fields map[str
}
s.mu.Lock()
parent, found = s.parents[responseID]
if !found || parent.complete {
if !found {
s.mu.Unlock()
s.emitReason(turn.lane, reasonWebsocketResponseNotActive)
return
}
if parent.complete {
s.mu.Unlock()
return
}
// 先登记意图:上游可能在控制帧写入返回前就交付中断终态。
interrupt := &websocketInterrupt{done: make(chan struct{})}
parent.interruptRequested = true
Expand Down
8 changes: 5 additions & 3 deletions internal/gateway/websocket_interrupt_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -128,10 +128,12 @@ func TestWebsocketInterruptBypassesActiveTurnAndContinues(t *testing.T) {
t.Fatal(err)
}
read("response.incomplete")
if err := conn.WriteMessage(websocket.TextMessage, interrupt); err != nil {
t.Fatal(err)
// 迟到或重复的中断不能留下 error 帧,影响下一轮读取。
for range 2 {
if err := conn.WriteMessage(websocket.TextMessage, interrupt); err != nil {
t.Fatal(err)
}
}
read("error")
if err := conn.WriteMessage(websocket.TextMessage, []byte(`{"type":"response.create","model":"public","previous_response_id":"resp_1","input":"answer","store":false}`)); err != nil {
t.Fatal(err)
}
Expand Down
6 changes: 2 additions & 4 deletions third_party/cpaembedded/embedded/codex_websocket.go
Original file line number Diff line number Diff line change
Expand Up @@ -248,9 +248,7 @@ func (s *CodexWSSession) ExecuteTurn(ctx context.Context, payload json.RawMessag
defer s.mu.Unlock()
s.activeResponseID = id
interrupted := status == "incomplete" && reason == "interrupted" && s.interruptResponseID == id && id != ""
if status == "completed" || status == "incomplete" || status == "failed" || status == "cancelled" {
s.activeResponseID = ""
}
// 保留本轮 ID 到收尾,让 CPA 忽略终态交付期间到达的迟到中断。
return interrupted
},
}
Expand Down Expand Up @@ -359,7 +357,7 @@ func (s *CodexWSSession) ExecuteTurn(ctx context.Context, payload json.RawMessag
return result, nil
}

// Interrupt 复用 CPA 的控制帧接口,只允许中断当前正在生成的响应。
// Interrupt 复用 CPA 的控制帧接口,只处理本轮响应;已结束响应的迟到中断由 CPA 忽略。
func (s *CodexWSSession) Interrupt(ctx context.Context, payload []byte) error {
if s == nil {
return codexWSError("response_not_active")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,11 @@ func testCodexWSSessionInterruptAndContinue(t *testing.T, eventType string, outp
if event.Type == "response.created" {
close(created)
}
if event.Type == eventType {
if err := sender.Interrupt(t.Context(), interrupt); err != nil {
t.Errorf("interrupt during terminal delivery: %v", err)
}
}
return nil
})
}()
Expand Down
2 changes: 1 addition & 1 deletion third_party/cpaembedded/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ require (
github.com/andybalholm/brotli v1.2.6
github.com/google/uuid v1.6.0
github.com/gorilla/websocket v1.5.3
github.com/router-for-me/CLIProxyAPI/v8 v8.0.22
github.com/router-for-me/CLIProxyAPI/v8 v8.0.23
github.com/sirupsen/logrus v1.10.2
github.com/tidwall/gjson v1.19.0
github.com/tidwall/sjson v1.2.5
Expand Down
4 changes: 2 additions & 2 deletions third_party/cpaembedded/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,8 @@ github.com/redis/go-redis/v9 v9.19.0 h1:XPVaaPSnG6RhYf7p+rmSa9zZfeVAnWsH5h3lxthO
github.com/redis/go-redis/v9 v9.19.0/go.mod h1:v/M13XI1PVCDcm01VtPFOADfZtHf8YW3baQf57KlIkA=
github.com/refraction-networking/utls v1.8.2 h1:j4Q1gJj0xngdeH+Ox/qND11aEfhpgoEvV+S9iJ2IdQo=
github.com/refraction-networking/utls v1.8.2/go.mod h1:jkSOEkLqn+S/jtpEHPOsVv/4V4EVnelwbMQl4vCWXAM=
github.com/router-for-me/CLIProxyAPI/v8 v8.0.22 h1:KX7c+ThdMlhG+SiDSYrMLByAbaqhU4Azl7yR9ihu2HY=
github.com/router-for-me/CLIProxyAPI/v8 v8.0.22/go.mod h1:j1Mtcj0TrC66O1JwbSBB03lY3uYPx4J7yHNvU6nDBCo=
github.com/router-for-me/CLIProxyAPI/v8 v8.0.23 h1:q1bfXpXxPV8BbpSFNJGeqJnReMLyZEW8pAG0y/MHPSQ=
github.com/router-for-me/CLIProxyAPI/v8 v8.0.23/go.mod h1:j1Mtcj0TrC66O1JwbSBB03lY3uYPx4J7yHNvU6nDBCo=
github.com/sirupsen/logrus v1.10.2 h1:G2SED73/qrAu6YwbdxOD6peLkCBI3z7L+ykJFTXJBBo=
github.com/sirupsen/logrus v1.10.2/go.mod h1:SLEg8TqYulVKKfIGHldVp2K2aYz2DKSVBq4g/H5bR7Q=
github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966 h1:JIAuq3EEf9cgbU6AtGPK4CTG3Zf6CKMNqf0MHTggAUA=
Expand Down
Loading