Add projects
This commit is contained in:
parent
2d3a9ad623
commit
8b607dd700
1802 changed files with 503346 additions and 2 deletions
112
backend/internal/runtime/executor/claude_executor_diagnostics.go
Normal file
112
backend/internal/runtime/executor/claude_executor_diagnostics.go
Normal file
|
|
@ -0,0 +1,112 @@
|
|||
package executor
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"strings"
|
||||
|
||||
claudeauth "github.com/router-for-me/CLIProxyAPI/v7/internal/auth/claude"
|
||||
"github.com/router-for-me/CLIProxyAPI/v7/internal/runtime/executor/helps"
|
||||
cliproxyauth "github.com/router-for-me/CLIProxyAPI/v7/sdk/cliproxy/auth"
|
||||
"github.com/tidwall/gjson"
|
||||
"github.com/tidwall/sjson"
|
||||
)
|
||||
|
||||
type claudeDiagnosticsRequestState struct {
|
||||
key string
|
||||
sequence uint64
|
||||
}
|
||||
|
||||
func injectClaudeDiagnostics(body []byte, auth *cliproxyauth.Auth, sessionID string) ([]byte, claudeDiagnosticsRequestState) {
|
||||
key, sequence, previousMessageID := helps.BeginClaudeDiagnostics(claudeDiagnosticsCredentialIdentity(auth), sessionID)
|
||||
if key == "" {
|
||||
return body, claudeDiagnosticsRequestState{}
|
||||
}
|
||||
value := `{"previous_message_id":null}`
|
||||
if previousMessageID != "" {
|
||||
value = `{"previous_message_id":` + marshalJSONStringWithoutHTMLEscape(previousMessageID) + `}`
|
||||
}
|
||||
|
||||
if diagnostics := gjson.GetBytes(body, "diagnostics"); diagnostics.Exists() {
|
||||
updated, errSet := sjson.SetRawBytes(body, "diagnostics", []byte(value))
|
||||
if errSet == nil {
|
||||
return updated, claudeDiagnosticsRequestState{key: key, sequence: sequence}
|
||||
}
|
||||
}
|
||||
if contextManagement := gjson.GetBytes(body, "context_management"); contextManagement.Exists() {
|
||||
start := contextManagement.Index
|
||||
insertAt := start + len(contextManagement.Raw)
|
||||
if start >= 0 && insertAt >= start && insertAt <= len(body) && bytes.Equal(body[start:insertAt], []byte(contextManagement.Raw)) {
|
||||
updated := make([]byte, 0, len(body)+len(value)+len(`,"diagnostics":`))
|
||||
updated = append(updated, body[:insertAt]...)
|
||||
updated = append(updated, `,"diagnostics":`...)
|
||||
updated = append(updated, value...)
|
||||
updated = append(updated, body[insertAt:]...)
|
||||
return updated, claudeDiagnosticsRequestState{key: key, sequence: sequence}
|
||||
}
|
||||
}
|
||||
updated, errSet := sjson.SetRawBytes(body, "diagnostics", []byte(value))
|
||||
if errSet != nil {
|
||||
return body, claudeDiagnosticsRequestState{}
|
||||
}
|
||||
return updated, claudeDiagnosticsRequestState{key: key, sequence: sequence}
|
||||
}
|
||||
|
||||
func claudeDiagnosticsCredentialIdentity(auth *cliproxyauth.Auth) string {
|
||||
if auth == nil {
|
||||
return ""
|
||||
}
|
||||
if id := strings.TrimSpace(auth.ID); id != "" {
|
||||
return "id:" + id
|
||||
}
|
||||
if index := strings.TrimSpace(auth.Index); index != "" {
|
||||
return "index:" + index
|
||||
}
|
||||
deviceIDs := claudeauth.NormalizeDeviceIDPool(claudeauth.ReadDeviceIDPool(&auth.Metadata))
|
||||
if len(deviceIDs) > 0 {
|
||||
return "device:" + deviceIDs[0]
|
||||
}
|
||||
if accountUUID := helps.ClaudeCredentialAccountUUID(auth); accountUUID != "" {
|
||||
return "account:" + accountUUID
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func commitClaudeDiagnostics(state claudeDiagnosticsRequestState, messageID string) {
|
||||
helps.CommitClaudeDiagnostics(state.key, state.sequence, messageID)
|
||||
}
|
||||
|
||||
func claudeMessageIDFromResponse(data []byte) string {
|
||||
return strings.TrimSpace(gjson.GetBytes(data, "id").String())
|
||||
}
|
||||
|
||||
func observeClaudeStreamLine(line []byte, messageID *string, completed *bool) {
|
||||
line = bytes.TrimSpace(line)
|
||||
if !bytes.HasPrefix(line, []byte("data:")) {
|
||||
return
|
||||
}
|
||||
payload := bytes.TrimSpace(line[len("data:"):])
|
||||
if !gjson.ValidBytes(payload) {
|
||||
return
|
||||
}
|
||||
root := gjson.ParseBytes(payload)
|
||||
switch root.Get("type").String() {
|
||||
case "message_start":
|
||||
if id := strings.TrimSpace(root.Get("message.id").String()); id != "" {
|
||||
*messageID = id
|
||||
}
|
||||
case "message_stop":
|
||||
*completed = true
|
||||
}
|
||||
}
|
||||
|
||||
func claudeMessageIDFromSSE(data []byte) string {
|
||||
var messageID string
|
||||
completed := false
|
||||
for _, line := range bytes.Split(data, []byte("\n")) {
|
||||
observeClaudeStreamLine(line, &messageID, &completed)
|
||||
}
|
||||
if !completed {
|
||||
return ""
|
||||
}
|
||||
return messageID
|
||||
}
|
||||
Loading…
Reference in a new issue