| package claude |
|
|
| import ( |
| "encoding/json" |
| "fmt" |
| "strings" |
|
|
| "ds2api/internal/util" |
| ) |
|
|
| func (s *claudeStreamRuntime) send(event string, v any) { |
| b, _ := json.Marshal(v) |
| _, _ = s.w.Write([]byte("event: ")) |
| _, _ = s.w.Write([]byte(event)) |
| _, _ = s.w.Write([]byte("\n")) |
| _, _ = s.w.Write([]byte("data: ")) |
| _, _ = s.w.Write(b) |
| _, _ = s.w.Write([]byte("\n\n")) |
| if s.canFlush { |
| _ = s.rc.Flush() |
| } |
| } |
|
|
| func (s *claudeStreamRuntime) sendError(message string) { |
| msg := strings.TrimSpace(message) |
| if msg == "" { |
| msg = "upstream stream error" |
| } |
| s.send("error", map[string]any{ |
| "type": "error", |
| "error": map[string]any{ |
| "type": "api_error", |
| "message": msg, |
| "code": "internal_error", |
| "param": nil, |
| }, |
| }) |
| } |
|
|
| func (s *claudeStreamRuntime) sendPing() { |
| s.send("ping", map[string]any{"type": "ping"}) |
| } |
|
|
| func (s *claudeStreamRuntime) sendMessageStart() { |
| inputTokens := countClaudeInputTokensFromText(s.promptTokenText, s.model) |
| if inputTokens == 0 { |
| inputTokens = util.CountPromptTokens(fmt.Sprintf("%v", s.messages), s.model) |
| } |
| s.send("message_start", map[string]any{ |
| "type": "message_start", |
| "message": map[string]any{ |
| "id": s.messageID, |
| "type": "message", |
| "role": "assistant", |
| "model": s.model, |
| "content": []any{}, |
| "stop_reason": nil, |
| "stop_sequence": nil, |
| "usage": map[string]any{"input_tokens": inputTokens, "output_tokens": 0}, |
| }, |
| }) |
| } |
|
|