fix(acp): unify protocol compatibility, enhance authentication, and fix conversation history

This commit is contained in:
Haitao Pan 2026-04-17 17:41:16 +08:00
parent f30c8d4816
commit 00ef2ceeed
4 changed files with 235 additions and 819 deletions

File diff suppressed because it is too large Load Diff

View File

@ -4,6 +4,7 @@ import (
"encoding/json"
"net/http"
"xworkmate-bridge/internal/shared"
"xworkmate-bridge/internal/service"
)
@ -17,13 +18,24 @@ func NewTokenAuthHandler(service *service.StaticTokenAuthService) *TokenAuthHand
func (h *TokenAuthHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
if h.service == nil {
http.Error(w, "service unavailable", http.StatusServiceUnavailable)
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusServiceUnavailable)
_ = json.NewEncoder(w).Encode(shared.ErrorEnvelope(nil, -32000, "auth service unavailable"))
return
}
token := r.Header.Get("Authorization")
if !h.service.ValidateAuthorizationHeader(token) {
http.Error(w, "unauthorized", http.StatusUnauthorized)
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusUnauthorized)
// Return JSON error instead of plain text to satisfy Flutter's expectation
_ = json.NewEncoder(w).Encode(shared.ErrorEnvelope(nil, -32001, "unauthorized"))
return
}
_ = json.NewEncoder(w).Encode(map[string]any{"ok": true})
w.Header().Set("Content-Type", "application/json")
_ = json.NewEncoder(w).Encode(map[string]any{
"jsonrpc": "2.0",
"ok": true,
"type": "res",
"payload": map[string]any{"authenticated": true},
})
}

View File

@ -10,6 +10,7 @@ import (
type RPCRequest struct {
JSONRPC string `json:"jsonrpc,omitempty"`
Type string `json:"type,omitempty"`
ID any `json:"id,omitempty"`
Method string `json:"method,omitempty"`
Params map[string]any `json:"params,omitempty"`
@ -49,17 +50,25 @@ func ResultEnvelope(id any, result map[string]any) map[string]any {
"jsonrpc": "2.0",
"id": id,
"result": result,
// Backward compatibility with legacy GatewayRuntime
"type": "res",
"ok": true,
"payload": result,
}
}
func ErrorEnvelope(id any, code int, message string) map[string]any {
errPayload := map[string]any{
"code": code,
"message": message,
}
return map[string]any{
"jsonrpc": "2.0",
"id": id,
"error": map[string]any{
"code": code,
"message": message,
},
"error": errPayload,
// Backward compatibility with legacy GatewayRuntime
"type": "res",
"ok": false,
}
}
@ -68,41 +77,32 @@ func NotificationEnvelope(method string, params map[string]any) map[string]any {
"jsonrpc": "2.0",
"method": method,
"params": params,
// Backward compatibility with legacy GatewayRuntime
"type": "event",
"event": method,
"payload": params,
}
}
func ErrorResponse(id any, code int, message string) map[string]any {
return map[string]any{
"jsonrpc": "2.0",
"id": id,
"error": map[string]any{
"code": code,
"message": message,
},
}
return ErrorEnvelope(id, code, message)
}
func ToolTextResult(id any, content string) map[string]any {
return map[string]any{
"jsonrpc": "2.0",
"id": id,
"result": map[string]any{
"content": []map[string]any{
{"type": "text", "text": content},
},
result := map[string]any{
"content": []map[string]any{
{"type": "text", "text": content},
},
}
return ResultEnvelope(id, result)
}
func ToolErrorResult(id any, err error) map[string]any {
return map[string]any{
"jsonrpc": "2.0",
"id": id,
"result": map[string]any{
"content": []map[string]any{
{"type": "text", "text": fmt.Sprintf("Error: %v", err)},
},
"isError": true,
result := map[string]any{
"content": []map[string]any{
{"type": "text", "text": fmt.Sprintf("Error: %v", err)},
},
"isError": true,
}
return ResultEnvelope(id, result)
}

View File

@ -178,15 +178,35 @@ func AugmentPromptWithAttachments(prompt string, params map[string]any) string {
return builder.String()
}
func ComposeHistoryPrompt(history []string) string {
if len(history) == 0 {
return ""
}
func ComposeHistoryPrompt(history any) string {
var builder strings.Builder
for index, turn := range history {
_, _ = fmt.Fprintf(&builder, "## User Turn %d\n", index+1)
builder.WriteString(turn)
builder.WriteString("\n\n")
switch h := history.(type) {
case []string:
if len(h) == 0 {
return ""
}
for index, turn := range h {
_, _ = fmt.Fprintf(&builder, "## Turn %d\n", index+1)
builder.WriteString(turn)
builder.WriteString("\n\n")
}
case []map[string]string:
if len(h) == 0 {
return ""
}
turn := 1
for _, msg := range h {
role := msg["role"]
content := msg["content"]
if role == "user" {
_, _ = fmt.Fprintf(&builder, "## User Turn %d\n", turn)
turn++
} else {
builder.WriteString("## Assistant Response\n")
}
builder.WriteString(content)
builder.WriteString("\n\n")
}
}
return strings.TrimSpace(builder.String())
}