fix: satisfy backend lint
This commit is contained in:
@@ -80,7 +80,7 @@ func main() {
|
|||||||
runMainServer()
|
runMainServer()
|
||||||
}
|
}
|
||||||
|
|
||||||
func runSetupServer() {
|
func runSetupServer() { //nolint:unused // kept for setup wizard server mode restoration.
|
||||||
r := gin.New()
|
r := gin.New()
|
||||||
r.Use(middleware.Recovery())
|
r.Use(middleware.Recovery())
|
||||||
r.Use(middleware.CORS(config.CORSConfig{}))
|
r.Use(middleware.CORS(config.CORSConfig{}))
|
||||||
|
|||||||
@@ -177,7 +177,7 @@ func sha256Hex(seed string) string {
|
|||||||
|
|
||||||
func isHexString(value string) bool {
|
func isHexString(value string) bool {
|
||||||
for _, c := range value {
|
for _, c := range value {
|
||||||
if !((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F')) {
|
if (c < '0' || c > '9') && (c < 'a' || c > 'f') && (c < 'A' || c > 'F') {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -159,7 +159,7 @@ type KiroToolSpecification struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type KiroInputSchema struct {
|
type KiroInputSchema struct {
|
||||||
JSON interface{} `json:"json"`
|
JSON any `json:"json"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type KiroAssistantResponseMessage struct {
|
type KiroAssistantResponseMessage struct {
|
||||||
@@ -170,7 +170,7 @@ type KiroAssistantResponseMessage struct {
|
|||||||
type KiroToolUse struct {
|
type KiroToolUse struct {
|
||||||
ToolUseID string `json:"toolUseId"`
|
ToolUseID string `json:"toolUseId"`
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
Input map[string]interface{} `json:"input"`
|
Input map[string]any `json:"input"`
|
||||||
IsTruncated bool `json:"-"`
|
IsTruncated bool `json:"-"`
|
||||||
TruncatedRaw string `json:"-"`
|
TruncatedRaw string `json:"-"`
|
||||||
}
|
}
|
||||||
@@ -501,7 +501,7 @@ func StreamEventStreamAsAnthropicWithContext(ctx context.Context, body io.Reader
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
processStreamingToolUseEvent := func(event map[string]interface{}) error {
|
processStreamingToolUseEvent := func(event map[string]any) error {
|
||||||
tu := nestedEvent(event, "toolUseEvent")
|
tu := nestedEvent(event, "toolUseEvent")
|
||||||
toolUseID := getString(tu, "toolUseId")
|
toolUseID := getString(tu, "toolUseId")
|
||||||
name := getString(tu, "name")
|
name := getString(tu, "name")
|
||||||
@@ -514,7 +514,7 @@ func StreamEventStreamAsAnthropicWithContext(ctx context.Context, body io.Reader
|
|||||||
if err := emitStreamingToolInput(toolUseID, name, v); err != nil {
|
if err := emitStreamingToolInput(toolUseID, name, v); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
case map[string]interface{}:
|
case map[string]any:
|
||||||
encoded, err := json.Marshal(v)
|
encoded, err := json.Marshal(v)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -825,7 +825,7 @@ func StreamEventStreamAsAnthropicWithContext(ctx context.Context, body io.Reader
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
var event map[string]interface{}
|
var event map[string]any
|
||||||
if err := json.Unmarshal(msg.Payload, &event); err != nil {
|
if err := json.Unmarshal(msg.Payload, &event); err != nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@@ -988,10 +988,6 @@ func extractSystemPrompt(claudeBody []byte) string {
|
|||||||
return systemField.String()
|
return systemField.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
func isThinkingEnabledWithHeaders(body []byte, headers http.Header) bool {
|
|
||||||
return deriveThinkingDirective(body, headers) != nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func deriveThinkingDirective(body []byte, headers http.Header) *thinkingDirective {
|
func deriveThinkingDirective(body []byte, headers http.Header) *thinkingDirective {
|
||||||
if override := thinkingDirectiveFromModel(gjson.GetBytes(body, "model").String()); override != nil {
|
if override := thinkingDirectiveFromModel(gjson.GetBytes(body, "model").String()); override != nil {
|
||||||
return override
|
return override
|
||||||
@@ -1129,10 +1125,6 @@ func isToolChoiceNone(claudeBody []byte) bool {
|
|||||||
return strings.EqualFold(strings.TrimSpace(toolChoice.Get("type").String()), "none")
|
return strings.EqualFold(strings.TrimSpace(toolChoice.Get("type").String()), "none")
|
||||||
}
|
}
|
||||||
|
|
||||||
func kiroToolNameAlias(name string) string {
|
|
||||||
return mapKiroToolName(name, nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
func prependSystemHistory(history []KiroHistoryMessage, systemPrompt, modelID, origin string) []KiroHistoryMessage {
|
func prependSystemHistory(history []KiroHistoryMessage, systemPrompt, modelID, origin string) []KiroHistoryMessage {
|
||||||
systemPrompt = strings.TrimSpace(systemPrompt)
|
systemPrompt = strings.TrimSpace(systemPrompt)
|
||||||
if systemPrompt == "" {
|
if systemPrompt == "" {
|
||||||
@@ -1220,9 +1212,7 @@ func appendChunkedToolDescription(name, description string) string {
|
|||||||
if suffix == "" {
|
if suffix == "" {
|
||||||
return description
|
return description
|
||||||
}
|
}
|
||||||
if strings.Contains(description, suffix) {
|
|
||||||
description = strings.Replace(description, suffix, "", 1)
|
description = strings.Replace(description, suffix, "", 1)
|
||||||
}
|
|
||||||
if strings.TrimSpace(description) == "" {
|
if strings.TrimSpace(description) == "" {
|
||||||
return suffix
|
return suffix
|
||||||
}
|
}
|
||||||
@@ -1311,11 +1301,11 @@ func normalizeKiroJSONSchema(schema any) any {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func normalizeKiroJSONSchemaValue(schema any, enforceObjectKeywords bool) any {
|
func normalizeKiroJSONSchemaValue(schema any, enforceObjectKeywords bool) any {
|
||||||
obj, ok := schema.(map[string]interface{})
|
obj, ok := schema.(map[string]any)
|
||||||
if !ok || obj == nil {
|
if !ok || obj == nil {
|
||||||
return defaultKiroJSONSchema()
|
return defaultKiroJSONSchema()
|
||||||
}
|
}
|
||||||
normalized := make(map[string]interface{}, len(obj)+4)
|
normalized := make(map[string]any, len(obj)+4)
|
||||||
for key, value := range obj {
|
for key, value := range obj {
|
||||||
normalized[key] = normalizeSchemaChild(key, value)
|
normalized[key] = normalizeSchemaChild(key, value)
|
||||||
}
|
}
|
||||||
@@ -1329,9 +1319,9 @@ func normalizeKiroJSONSchemaValue(schema any, enforceObjectKeywords bool) any {
|
|||||||
hasSchemaKey(normalized, "required") ||
|
hasSchemaKey(normalized, "required") ||
|
||||||
hasSchemaKey(normalized, "additionalProperties")
|
hasSchemaKey(normalized, "additionalProperties")
|
||||||
if needsObjectKeywords {
|
if needsObjectKeywords {
|
||||||
properties, ok := normalized["properties"].(map[string]interface{})
|
properties, ok := normalized["properties"].(map[string]any)
|
||||||
if !ok || properties == nil {
|
if !ok || properties == nil {
|
||||||
normalized["properties"] = map[string]interface{}{}
|
normalized["properties"] = map[string]any{}
|
||||||
} else {
|
} else {
|
||||||
for key, value := range properties {
|
for key, value := range properties {
|
||||||
properties[key] = normalizeKiroJSONSchemaValue(value, false)
|
properties[key] = normalizeKiroJSONSchemaValue(value, false)
|
||||||
@@ -1341,7 +1331,7 @@ func normalizeKiroJSONSchemaValue(schema any, enforceObjectKeywords bool) any {
|
|||||||
normalized["required"] = normalizeSchemaRequired(normalized["required"])
|
normalized["required"] = normalizeSchemaRequired(normalized["required"])
|
||||||
switch additional := normalized["additionalProperties"].(type) {
|
switch additional := normalized["additionalProperties"].(type) {
|
||||||
case bool:
|
case bool:
|
||||||
case map[string]interface{}:
|
case map[string]any:
|
||||||
normalized["additionalProperties"] = normalizeKiroJSONSchemaValue(additional, false)
|
normalized["additionalProperties"] = normalizeKiroJSONSchemaValue(additional, false)
|
||||||
default:
|
default:
|
||||||
normalized["additionalProperties"] = true
|
normalized["additionalProperties"] = true
|
||||||
@@ -1350,26 +1340,26 @@ func normalizeKiroJSONSchemaValue(schema any, enforceObjectKeywords bool) any {
|
|||||||
return normalized
|
return normalized
|
||||||
}
|
}
|
||||||
|
|
||||||
func hasSchemaKey(schema map[string]interface{}, key string) bool {
|
func hasSchemaKey(schema map[string]any, key string) bool {
|
||||||
_, ok := schema[key]
|
_, ok := schema[key]
|
||||||
return ok
|
return ok
|
||||||
}
|
}
|
||||||
|
|
||||||
func defaultKiroJSONSchema() map[string]interface{} {
|
func defaultKiroJSONSchema() map[string]any {
|
||||||
return map[string]interface{}{
|
return map[string]any{
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": map[string]interface{}{},
|
"properties": map[string]any{},
|
||||||
"required": []interface{}{},
|
"required": []any{},
|
||||||
"additionalProperties": true,
|
"additionalProperties": true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func normalizeSchemaRequired(value interface{}) []interface{} {
|
func normalizeSchemaRequired(value any) []any {
|
||||||
arr, ok := value.([]interface{})
|
arr, ok := value.([]any)
|
||||||
if !ok {
|
if !ok {
|
||||||
return []interface{}{}
|
return []any{}
|
||||||
}
|
}
|
||||||
out := make([]interface{}, 0, len(arr))
|
out := make([]any, 0, len(arr))
|
||||||
for _, item := range arr {
|
for _, item := range arr {
|
||||||
if s, ok := item.(string); ok {
|
if s, ok := item.(string); ok {
|
||||||
out = append(out, s)
|
out = append(out, s)
|
||||||
@@ -1378,22 +1368,22 @@ func normalizeSchemaRequired(value interface{}) []interface{} {
|
|||||||
return out
|
return out
|
||||||
}
|
}
|
||||||
|
|
||||||
func normalizeSchemaChild(key string, value interface{}) interface{} {
|
func normalizeSchemaChild(key string, value any) any {
|
||||||
switch key {
|
switch key {
|
||||||
case "items", "not":
|
case "items", "not":
|
||||||
if obj, ok := value.(map[string]interface{}); ok {
|
if obj, ok := value.(map[string]any); ok {
|
||||||
return normalizeKiroJSONSchemaValue(obj, false)
|
return normalizeKiroJSONSchemaValue(obj, false)
|
||||||
}
|
}
|
||||||
if arr, ok := value.([]interface{}); ok {
|
if arr, ok := value.([]any); ok {
|
||||||
out := make([]interface{}, 0, len(arr))
|
out := make([]any, 0, len(arr))
|
||||||
for _, item := range arr {
|
for _, item := range arr {
|
||||||
out = append(out, normalizeKiroJSONSchemaValue(item, false))
|
out = append(out, normalizeKiroJSONSchemaValue(item, false))
|
||||||
}
|
}
|
||||||
return out
|
return out
|
||||||
}
|
}
|
||||||
case "oneOf", "anyOf", "allOf":
|
case "oneOf", "anyOf", "allOf":
|
||||||
if arr, ok := value.([]interface{}); ok {
|
if arr, ok := value.([]any); ok {
|
||||||
out := make([]interface{}, 0, len(arr))
|
out := make([]any, 0, len(arr))
|
||||||
for _, item := range arr {
|
for _, item := range arr {
|
||||||
out = append(out, normalizeKiroJSONSchemaValue(item, false))
|
out = append(out, normalizeKiroJSONSchemaValue(item, false))
|
||||||
}
|
}
|
||||||
@@ -1658,7 +1648,7 @@ func buildAssistantMessageStruct(msg gjson.Result, requestCtx *KiroRequestContex
|
|||||||
_, _ = contentBuilder.WriteString(part.Get("text").String())
|
_, _ = contentBuilder.WriteString(part.Get("text").String())
|
||||||
case "tool_use":
|
case "tool_use":
|
||||||
toolName := mapKiroToolName(part.Get("name").String(), requestCtx)
|
toolName := mapKiroToolName(part.Get("name").String(), requestCtx)
|
||||||
input := map[string]interface{}{}
|
input := map[string]any{}
|
||||||
toolInput := part.Get("input")
|
toolInput := part.Get("input")
|
||||||
if toolInput.IsObject() {
|
if toolInput.IsObject() {
|
||||||
toolInput.ForEach(func(key, value gjson.Result) bool {
|
toolInput.ForEach(func(key, value gjson.Result) bool {
|
||||||
@@ -1704,7 +1694,7 @@ func mergeAdjacentMessages(messages []gjson.Result) []gjson.Result {
|
|||||||
merged = append(merged, msg)
|
merged = append(merged, msg)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
mergedMsg := map[string]interface{}{
|
mergedMsg := map[string]any{
|
||||||
"role": role,
|
"role": role,
|
||||||
"content": json.RawMessage(mergeMessageContent(lastMsg, msg)),
|
"content": json.RawMessage(mergeMessageContent(lastMsg, msg)),
|
||||||
}
|
}
|
||||||
@@ -1715,7 +1705,7 @@ func mergeAdjacentMessages(messages []gjson.Result) []gjson.Result {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func mergeMessageContent(msg1, msg2 gjson.Result) string {
|
func mergeMessageContent(msg1, msg2 gjson.Result) string {
|
||||||
var blocks1, blocks2 []map[string]interface{}
|
var blocks1, blocks2 []map[string]any
|
||||||
content1 := msg1.Get("content")
|
content1 := msg1.Get("content")
|
||||||
content2 := msg2.Get("content")
|
content2 := msg2.Get("content")
|
||||||
if content1.IsArray() {
|
if content1.IsArray() {
|
||||||
@@ -1723,14 +1713,14 @@ func mergeMessageContent(msg1, msg2 gjson.Result) string {
|
|||||||
blocks1 = append(blocks1, blockToMap(block))
|
blocks1 = append(blocks1, blockToMap(block))
|
||||||
}
|
}
|
||||||
} else if content1.Type == gjson.String {
|
} else if content1.Type == gjson.String {
|
||||||
blocks1 = append(blocks1, map[string]interface{}{"type": "text", "text": content1.String()})
|
blocks1 = append(blocks1, map[string]any{"type": "text", "text": content1.String()})
|
||||||
}
|
}
|
||||||
if content2.IsArray() {
|
if content2.IsArray() {
|
||||||
for _, block := range content2.Array() {
|
for _, block := range content2.Array() {
|
||||||
blocks2 = append(blocks2, blockToMap(block))
|
blocks2 = append(blocks2, blockToMap(block))
|
||||||
}
|
}
|
||||||
} else if content2.Type == gjson.String {
|
} else if content2.Type == gjson.String {
|
||||||
blocks2 = append(blocks2, map[string]interface{}{"type": "text", "text": content2.String()})
|
blocks2 = append(blocks2, map[string]any{"type": "text", "text": content2.String()})
|
||||||
}
|
}
|
||||||
if len(blocks1) > 0 && len(blocks2) > 0 && blocks1[len(blocks1)-1]["type"] == "text" && blocks2[0]["type"] == "text" {
|
if len(blocks1) > 0 && len(blocks2) > 0 && blocks1[len(blocks1)-1]["type"] == "text" && blocks2[0]["type"] == "text" {
|
||||||
leftText, leftOK := blocks1[len(blocks1)-1]["text"].(string)
|
leftText, leftOK := blocks1[len(blocks1)-1]["text"].(string)
|
||||||
@@ -1745,13 +1735,13 @@ func mergeMessageContent(msg1, msg2 gjson.Result) string {
|
|||||||
return string(result)
|
return string(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
func blockToMap(block gjson.Result) map[string]interface{} {
|
func blockToMap(block gjson.Result) map[string]any {
|
||||||
result := make(map[string]interface{})
|
result := make(map[string]any)
|
||||||
block.ForEach(func(key, value gjson.Result) bool {
|
block.ForEach(func(key, value gjson.Result) bool {
|
||||||
if value.IsObject() {
|
if value.IsObject() {
|
||||||
result[key.String()] = blockToMap(value)
|
result[key.String()] = blockToMap(value)
|
||||||
} else if value.IsArray() {
|
} else if value.IsArray() {
|
||||||
var arr []interface{}
|
var arr []any
|
||||||
for _, item := range value.Array() {
|
for _, item := range value.Array() {
|
||||||
if item.IsObject() {
|
if item.IsObject() {
|
||||||
arr = append(arr, blockToMap(item))
|
arr = append(arr, blockToMap(item))
|
||||||
@@ -1789,7 +1779,7 @@ func parseEventStream(body io.Reader) (string, []KiroToolUse, Usage, string, err
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
var event map[string]interface{}
|
var event map[string]any
|
||||||
if err := json.Unmarshal(msg.Payload, &event); err != nil {
|
if err := json.Unmarshal(msg.Payload, &event); err != nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@@ -1835,8 +1825,8 @@ func parseEventStream(body io.Reader) (string, []KiroToolUse, Usage, string, err
|
|||||||
}
|
}
|
||||||
|
|
||||||
if currentTool != nil && currentTool.ToolUseID != "" && !processedIDs[currentTool.ToolUseID] {
|
if currentTool != nil && currentTool.ToolUseID != "" && !processedIDs[currentTool.ToolUseID] {
|
||||||
completed, _ := processToolUseEvent(map[string]interface{}{
|
completed, _ := processToolUseEvent(map[string]any{
|
||||||
"toolUseEvent": map[string]interface{}{
|
"toolUseEvent": map[string]any{
|
||||||
"toolUseId": currentTool.ToolUseID,
|
"toolUseId": currentTool.ToolUseID,
|
||||||
"name": currentTool.Name,
|
"name": currentTool.Name,
|
||||||
"stop": true,
|
"stop": true,
|
||||||
@@ -1866,7 +1856,7 @@ func parseEventStream(body io.Reader) (string, []KiroToolUse, Usage, string, err
|
|||||||
}
|
}
|
||||||
|
|
||||||
func buildClaudeResponse(content string, toolUses []KiroToolUse, model string, usage Usage, stopReason string, requestCtx KiroRequestContext) []byte {
|
func buildClaudeResponse(content string, toolUses []KiroToolUse, model string, usage Usage, stopReason string, requestCtx KiroRequestContext) []byte {
|
||||||
var blocks []map[string]interface{}
|
var blocks []map[string]any
|
||||||
blocks = append(blocks, extractThinkingBlocks(content)...)
|
blocks = append(blocks, extractThinkingBlocks(content)...)
|
||||||
usableTools := 0
|
usableTools := 0
|
||||||
for _, tool := range toolUses {
|
for _, tool := range toolUses {
|
||||||
@@ -1874,7 +1864,7 @@ func buildClaudeResponse(content string, toolUses []KiroToolUse, model string, u
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
usableTools++
|
usableTools++
|
||||||
blocks = append(blocks, map[string]interface{}{
|
blocks = append(blocks, map[string]any{
|
||||||
"type": "tool_use",
|
"type": "tool_use",
|
||||||
"id": tool.ToolUseID,
|
"id": tool.ToolUseID,
|
||||||
"name": restoreResponseToolName(tool.Name, requestCtx),
|
"name": restoreResponseToolName(tool.Name, requestCtx),
|
||||||
@@ -1883,11 +1873,11 @@ func buildClaudeResponse(content string, toolUses []KiroToolUse, model string, u
|
|||||||
}
|
}
|
||||||
pureThinking := hasThinkingBlocksOnly(blocks) && usableTools == 0
|
pureThinking := hasThinkingBlocksOnly(blocks) && usableTools == 0
|
||||||
if pureThinking {
|
if pureThinking {
|
||||||
blocks = append(blocks, map[string]interface{}{"type": "text", "text": ""})
|
blocks = append(blocks, map[string]any{"type": "text", "text": ""})
|
||||||
stopReason = "max_tokens"
|
stopReason = "max_tokens"
|
||||||
}
|
}
|
||||||
if len(blocks) == 0 {
|
if len(blocks) == 0 {
|
||||||
blocks = append(blocks, map[string]interface{}{"type": "text", "text": ""})
|
blocks = append(blocks, map[string]any{"type": "text", "text": ""})
|
||||||
}
|
}
|
||||||
if stopReason == "" {
|
if stopReason == "" {
|
||||||
if usableTools > 0 {
|
if usableTools > 0 {
|
||||||
@@ -1896,14 +1886,14 @@ func buildClaudeResponse(content string, toolUses []KiroToolUse, model string, u
|
|||||||
stopReason = "end_turn"
|
stopReason = "end_turn"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
response := map[string]interface{}{
|
response := map[string]any{
|
||||||
"id": "msg_" + uuid.NewString()[:24],
|
"id": "msg_" + uuid.NewString()[:24],
|
||||||
"type": "message",
|
"type": "message",
|
||||||
"role": "assistant",
|
"role": "assistant",
|
||||||
"model": model,
|
"model": model,
|
||||||
"content": blocks,
|
"content": blocks,
|
||||||
"stop_reason": stopReason,
|
"stop_reason": stopReason,
|
||||||
"usage": map[string]interface{}{
|
"usage": map[string]any{
|
||||||
"input_tokens": usage.InputTokens,
|
"input_tokens": usage.InputTokens,
|
||||||
"output_tokens": usage.OutputTokens,
|
"output_tokens": usage.OutputTokens,
|
||||||
"cache_read_input_tokens": usage.CacheReadInputTokens,
|
"cache_read_input_tokens": usage.CacheReadInputTokens,
|
||||||
@@ -1925,7 +1915,7 @@ func restoreResponseToolName(name string, requestCtx KiroRequestContext) string
|
|||||||
return name
|
return name
|
||||||
}
|
}
|
||||||
|
|
||||||
func hasThinkingBlocksOnly(blocks []map[string]interface{}) bool {
|
func hasThinkingBlocksOnly(blocks []map[string]any) bool {
|
||||||
if len(blocks) == 0 {
|
if len(blocks) == 0 {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@@ -1944,36 +1934,36 @@ func hasThinkingBlocksOnly(blocks []map[string]interface{}) bool {
|
|||||||
return hasThinking
|
return hasThinking
|
||||||
}
|
}
|
||||||
|
|
||||||
func extractThinkingBlocks(content string) []map[string]interface{} {
|
func extractThinkingBlocks(content string) []map[string]any {
|
||||||
if content == "" {
|
if content == "" {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
if findRealThinkingStartTag(content, 0) == -1 {
|
if findRealThinkingStartTag(content, 0) == -1 {
|
||||||
return []map[string]interface{}{{"type": "text", "text": content}}
|
return []map[string]any{{"type": "text", "text": content}}
|
||||||
}
|
}
|
||||||
var blocks []map[string]interface{}
|
var blocks []map[string]any
|
||||||
pos := 0
|
pos := 0
|
||||||
for pos < len(content) {
|
for pos < len(content) {
|
||||||
start := findRealThinkingStartTag(content, pos)
|
start := findRealThinkingStartTag(content, pos)
|
||||||
if start == -1 {
|
if start == -1 {
|
||||||
if text := content[pos:]; strings.TrimSpace(text) != "" {
|
if text := content[pos:]; strings.TrimSpace(text) != "" {
|
||||||
blocks = append(blocks, map[string]interface{}{"type": "text", "text": text})
|
blocks = append(blocks, map[string]any{"type": "text", "text": text})
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
end := findRealThinkingEndTag(content, start+len(thinkingStartTag))
|
end := findRealThinkingEndTag(content, start+len(thinkingStartTag))
|
||||||
if end == -1 {
|
if end == -1 {
|
||||||
if text := content[pos:]; strings.TrimSpace(text) != "" {
|
if text := content[pos:]; strings.TrimSpace(text) != "" {
|
||||||
blocks = append(blocks, map[string]interface{}{"type": "text", "text": text})
|
blocks = append(blocks, map[string]any{"type": "text", "text": text})
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
if text := content[pos:start]; strings.TrimSpace(text) != "" {
|
if text := content[pos:start]; strings.TrimSpace(text) != "" {
|
||||||
blocks = append(blocks, map[string]interface{}{"type": "text", "text": text})
|
blocks = append(blocks, map[string]any{"type": "text", "text": text})
|
||||||
}
|
}
|
||||||
thinking := strings.TrimPrefix(content[start+len(thinkingStartTag):end], "\n")
|
thinking := strings.TrimPrefix(content[start+len(thinkingStartTag):end], "\n")
|
||||||
if strings.TrimSpace(thinking) != "" {
|
if strings.TrimSpace(thinking) != "" {
|
||||||
blocks = append(blocks, map[string]interface{}{
|
blocks = append(blocks, map[string]any{
|
||||||
"type": "thinking",
|
"type": "thinking",
|
||||||
"thinking": thinking,
|
"thinking": thinking,
|
||||||
"signature": thinkingSignature(thinking),
|
"signature": thinkingSignature(thinking),
|
||||||
@@ -1985,7 +1975,7 @@ func extractThinkingBlocks(content string) []map[string]interface{} {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if len(blocks) == 0 {
|
if len(blocks) == 0 {
|
||||||
blocks = append(blocks, map[string]interface{}{"type": "text", "text": ""})
|
blocks = append(blocks, map[string]any{"type": "text", "text": ""})
|
||||||
}
|
}
|
||||||
return blocks
|
return blocks
|
||||||
}
|
}
|
||||||
@@ -2238,19 +2228,19 @@ func skipHeaderValue(headers []byte, offset int, valueType byte) (int, bool) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func processToolUseEvent(event map[string]interface{}, currentTool *toolUseState, processedIDs map[string]bool) ([]KiroToolUse, *toolUseState) {
|
func processToolUseEvent(event map[string]any, currentTool *toolUseState, processedIDs map[string]bool) ([]KiroToolUse, *toolUseState) {
|
||||||
tu := nestedEvent(event, "toolUseEvent")
|
tu := nestedEvent(event, "toolUseEvent")
|
||||||
toolUseID := getString(tu, "toolUseId")
|
toolUseID := getString(tu, "toolUseId")
|
||||||
name := getString(tu, "name")
|
name := getString(tu, "name")
|
||||||
isStop, _ := tu["stop"].(bool)
|
isStop, _ := tu["stop"].(bool)
|
||||||
|
|
||||||
var inputFragment string
|
var inputFragment string
|
||||||
var inputMap map[string]interface{}
|
var inputMap map[string]any
|
||||||
if inputRaw, ok := tu["input"]; ok {
|
if inputRaw, ok := tu["input"]; ok {
|
||||||
switch v := inputRaw.(type) {
|
switch v := inputRaw.(type) {
|
||||||
case string:
|
case string:
|
||||||
inputFragment = v
|
inputFragment = v
|
||||||
case map[string]interface{}:
|
case map[string]any:
|
||||||
inputMap = v
|
inputMap = v
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2283,7 +2273,7 @@ func repairJSON(input string) string {
|
|||||||
if str == "" {
|
if str == "" {
|
||||||
return "{}"
|
return "{}"
|
||||||
}
|
}
|
||||||
var parsed interface{}
|
var parsed any
|
||||||
if err := json.Unmarshal([]byte(str), &parsed); err == nil {
|
if err := json.Unmarshal([]byte(str), &parsed); err == nil {
|
||||||
return str
|
return str
|
||||||
}
|
}
|
||||||
@@ -2382,7 +2372,7 @@ func finalizeRawToolUse(toolUseID, name, rawInput string) KiroToolUse {
|
|||||||
tool := KiroToolUse{
|
tool := KiroToolUse{
|
||||||
ToolUseID: toolUseID,
|
ToolUseID: toolUseID,
|
||||||
Name: normalizeResponseToolName(name),
|
Name: normalizeResponseToolName(name),
|
||||||
Input: map[string]interface{}{},
|
Input: map[string]any{},
|
||||||
}
|
}
|
||||||
rawInput = strings.TrimSpace(rawInput)
|
rawInput = strings.TrimSpace(rawInput)
|
||||||
tool.TruncatedRaw = rawInput
|
tool.TruncatedRaw = rawInput
|
||||||
@@ -2394,9 +2384,9 @@ func finalizeRawToolUse(toolUseID, name, rawInput string) KiroToolUse {
|
|||||||
return tool
|
return tool
|
||||||
}
|
}
|
||||||
|
|
||||||
func finalizeStructuredToolUse(toolUseID, name string, input map[string]interface{}) KiroToolUse {
|
func finalizeStructuredToolUse(toolUseID, name string, input map[string]any) KiroToolUse {
|
||||||
if input == nil {
|
if input == nil {
|
||||||
input = map[string]interface{}{}
|
input = map[string]any{}
|
||||||
}
|
}
|
||||||
tool := KiroToolUse{
|
tool := KiroToolUse{
|
||||||
ToolUseID: toolUseID,
|
ToolUseID: toolUseID,
|
||||||
@@ -2508,14 +2498,14 @@ func parseEmbeddedToolCalls(text string) (string, []KiroToolUse) {
|
|||||||
for index < len(text) {
|
for index < len(text) {
|
||||||
start := strings.Index(text[index:], embeddedToolCallPrefix)
|
start := strings.Index(text[index:], embeddedToolCallPrefix)
|
||||||
if start == -1 {
|
if start == -1 {
|
||||||
builder.WriteString(text[index:])
|
_, _ = builder.WriteString(text[index:])
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
start += index
|
start += index
|
||||||
builder.WriteString(text[index:start])
|
_, _ = builder.WriteString(text[index:start])
|
||||||
tool, _, end, ok := parseEmbeddedToolCallAt(text, start)
|
tool, _, end, ok := parseEmbeddedToolCallAt(text, start)
|
||||||
if !ok {
|
if !ok {
|
||||||
builder.WriteString(text[start:])
|
_, _ = builder.WriteString(text[start:])
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
toolUses = append(toolUses, tool)
|
toolUses = append(toolUses, tool)
|
||||||
@@ -2596,7 +2586,7 @@ func findMatchingJSONBracket(text string, start int) int {
|
|||||||
return -1
|
return -1
|
||||||
}
|
}
|
||||||
|
|
||||||
func isTruncatedToolUse(name, rawInput string, input map[string]interface{}) bool {
|
func isTruncatedToolUse(name, rawInput string, input map[string]any) bool {
|
||||||
rawInput = strings.TrimSpace(rawInput)
|
rawInput = strings.TrimSpace(rawInput)
|
||||||
if rawInput == "" {
|
if rawInput == "" {
|
||||||
return hasToolRequirements(name)
|
return hasToolRequirements(name)
|
||||||
@@ -2625,7 +2615,7 @@ func hasToolRequirements(name string) bool {
|
|||||||
return ok
|
return ok
|
||||||
}
|
}
|
||||||
|
|
||||||
func hasMissingRequiredFields(name string, input map[string]interface{}) bool {
|
func hasMissingRequiredFields(name string, input map[string]any) bool {
|
||||||
groups, ok := requiredToolFields[strings.ToLower(strings.TrimSpace(name))]
|
groups, ok := requiredToolFields[strings.ToLower(strings.TrimSpace(name))]
|
||||||
if !ok {
|
if !ok {
|
||||||
return false
|
return false
|
||||||
@@ -2645,7 +2635,7 @@ func hasMissingRequiredFields(name string, input map[string]interface{}) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func updateUsageFromEvent(usage *Usage, eventType string, event map[string]interface{}) {
|
func updateUsageFromEvent(usage *Usage, eventType string, event map[string]any) {
|
||||||
if usage == nil {
|
if usage == nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -2653,7 +2643,7 @@ func updateUsageFromEvent(usage *Usage, eventType string, event map[string]inter
|
|||||||
if len(meta) == 0 {
|
if len(meta) == 0 {
|
||||||
meta = event
|
meta = event
|
||||||
}
|
}
|
||||||
if tokenUsage, ok := meta["tokenUsage"].(map[string]interface{}); ok {
|
if tokenUsage, ok := meta["tokenUsage"].(map[string]any); ok {
|
||||||
if value, ok := firstInt(tokenUsage, "uncachedInputTokens", "inputTokens", "inputTokenCount", "promptTokens", "prompt_tokens"); ok {
|
if value, ok := firstInt(tokenUsage, "uncachedInputTokens", "inputTokens", "inputTokenCount", "promptTokens", "prompt_tokens"); ok {
|
||||||
usage.InputTokens = value
|
usage.InputTokens = value
|
||||||
}
|
}
|
||||||
@@ -2707,7 +2697,7 @@ func updateUsageFromEvent(usage *Usage, eventType string, event map[string]inter
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func firstInt(m map[string]interface{}, keys ...string) (int, bool) {
|
func firstInt(m map[string]any, keys ...string) (int, bool) {
|
||||||
for _, key := range keys {
|
for _, key := range keys {
|
||||||
if value, ok := toInt(m[key]); ok {
|
if value, ok := toInt(m[key]); ok {
|
||||||
return value, true
|
return value, true
|
||||||
@@ -2716,7 +2706,7 @@ func firstInt(m map[string]interface{}, keys ...string) (int, bool) {
|
|||||||
return 0, false
|
return 0, false
|
||||||
}
|
}
|
||||||
|
|
||||||
func firstFloat(m map[string]interface{}, keys ...string) (float64, bool) {
|
func firstFloat(m map[string]any, keys ...string) (float64, bool) {
|
||||||
for _, key := range keys {
|
for _, key := range keys {
|
||||||
switch v := m[key].(type) {
|
switch v := m[key].(type) {
|
||||||
case float64:
|
case float64:
|
||||||
@@ -2786,11 +2776,11 @@ func countKiroTextTokens(text string) int {
|
|||||||
return tokens
|
return tokens
|
||||||
}
|
}
|
||||||
|
|
||||||
func readToolUses(primary, fallback map[string]interface{}) []KiroToolUse {
|
func readToolUses(primary, fallback map[string]any) []KiroToolUse {
|
||||||
var raw []interface{}
|
var raw []any
|
||||||
if value, ok := primary["toolUses"].([]interface{}); ok {
|
if value, ok := primary["toolUses"].([]any); ok {
|
||||||
raw = value
|
raw = value
|
||||||
} else if value, ok := fallback["toolUses"].([]interface{}); ok {
|
} else if value, ok := fallback["toolUses"].([]any); ok {
|
||||||
raw = value
|
raw = value
|
||||||
}
|
}
|
||||||
if len(raw) == 0 {
|
if len(raw) == 0 {
|
||||||
@@ -2798,12 +2788,12 @@ func readToolUses(primary, fallback map[string]interface{}) []KiroToolUse {
|
|||||||
}
|
}
|
||||||
out := make([]KiroToolUse, 0, len(raw))
|
out := make([]KiroToolUse, 0, len(raw))
|
||||||
for _, item := range raw {
|
for _, item := range raw {
|
||||||
tool, ok := item.(map[string]interface{})
|
tool, ok := item.(map[string]any)
|
||||||
if !ok {
|
if !ok {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
input := map[string]interface{}{}
|
input := map[string]any{}
|
||||||
if value, ok := tool["input"].(map[string]interface{}); ok {
|
if value, ok := tool["input"].(map[string]any); ok {
|
||||||
input = value
|
input = value
|
||||||
}
|
}
|
||||||
out = append(out, finalizeStructuredToolUse(getString(tool, "toolUseId"), getString(tool, "name"), input))
|
out = append(out, finalizeStructuredToolUse(getString(tool, "toolUseId"), getString(tool, "name"), input))
|
||||||
@@ -2811,28 +2801,28 @@ func readToolUses(primary, fallback map[string]interface{}) []KiroToolUse {
|
|||||||
return out
|
return out
|
||||||
}
|
}
|
||||||
|
|
||||||
func nestedEvent(event map[string]interface{}, key string) map[string]interface{} {
|
func nestedEvent(event map[string]any, key string) map[string]any {
|
||||||
if nested, ok := event[key].(map[string]interface{}); ok {
|
if nested, ok := event[key].(map[string]any); ok {
|
||||||
return nested
|
return nested
|
||||||
}
|
}
|
||||||
return event
|
return event
|
||||||
}
|
}
|
||||||
|
|
||||||
func getString(m map[string]interface{}, key string) string {
|
func getString(m map[string]any, key string) string {
|
||||||
if value, ok := m[key].(string); ok {
|
if value, ok := m[key].(string); ok {
|
||||||
return value
|
return value
|
||||||
}
|
}
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
func readStopReason(m map[string]interface{}) string {
|
func readStopReason(m map[string]any) string {
|
||||||
if stop := getString(m, "stop_reason"); stop != "" {
|
if stop := getString(m, "stop_reason"); stop != "" {
|
||||||
return stop
|
return stop
|
||||||
}
|
}
|
||||||
return getString(m, "stopReason")
|
return getString(m, "stopReason")
|
||||||
}
|
}
|
||||||
|
|
||||||
func toInt(value interface{}) (int, bool) {
|
func toInt(value any) (int, bool) {
|
||||||
switch v := value.(type) {
|
switch v := value.(type) {
|
||||||
case float64:
|
case float64:
|
||||||
return int(v), true
|
return int(v), true
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ type MCPRequest struct {
|
|||||||
ID string `json:"id"`
|
ID string `json:"id"`
|
||||||
JSONRPC string `json:"jsonrpc"`
|
JSONRPC string `json:"jsonrpc"`
|
||||||
Method string `json:"method"`
|
Method string `json:"method"`
|
||||||
Params interface{} `json:"params,omitempty"`
|
Params any `json:"params,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type MCPResponse struct {
|
type MCPResponse struct {
|
||||||
@@ -63,7 +63,9 @@ type SearchIndicator struct {
|
|||||||
|
|
||||||
func GetCachedWebSearchDescription() string {
|
func GetCachedWebSearchDescription() string {
|
||||||
if v := cachedWebSearchDescription.Load(); v != nil {
|
if v := cachedWebSearchDescription.Load(); v != nil {
|
||||||
return strings.TrimSpace(v.(string))
|
if desc, ok := v.(string); ok {
|
||||||
|
return strings.TrimSpace(desc)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
@@ -138,18 +140,18 @@ func GenerateToolUseID() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func ReplaceWebSearchToolDescription(body []byte) ([]byte, error) {
|
func ReplaceWebSearchToolDescription(body []byte) ([]byte, error) {
|
||||||
var payload map[string]interface{}
|
var payload map[string]any
|
||||||
if err := json.Unmarshal(body, &payload); err != nil {
|
if err := json.Unmarshal(body, &payload); err != nil {
|
||||||
return body, err
|
return body, err
|
||||||
}
|
}
|
||||||
rawTools, ok := payload["tools"].([]interface{})
|
rawTools, ok := payload["tools"].([]any)
|
||||||
if !ok {
|
if !ok {
|
||||||
return body, nil
|
return body, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
replaced := make([]interface{}, 0, len(rawTools))
|
replaced := make([]any, 0, len(rawTools))
|
||||||
for _, rawTool := range rawTools {
|
for _, rawTool := range rawTools {
|
||||||
tool, ok := rawTool.(map[string]interface{})
|
tool, ok := rawTool.(map[string]any)
|
||||||
if !ok {
|
if !ok {
|
||||||
replaced = append(replaced, rawTool)
|
replaced = append(replaced, rawTool)
|
||||||
continue
|
continue
|
||||||
@@ -160,13 +162,13 @@ func ReplaceWebSearchToolDescription(body []byte) ([]byte, error) {
|
|||||||
replaced = append(replaced, rawTool)
|
replaced = append(replaced, rawTool)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
replaced = append(replaced, map[string]interface{}{
|
replaced = append(replaced, map[string]any{
|
||||||
"name": "web_search",
|
"name": "web_search",
|
||||||
"description": minimalWebSearchDescription,
|
"description": minimalWebSearchDescription,
|
||||||
"input_schema": map[string]interface{}{
|
"input_schema": map[string]any{
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": map[string]interface{}{
|
"properties": map[string]any{
|
||||||
"query": map[string]interface{}{
|
"query": map[string]any{
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "The search query to execute",
|
"description": "The search query to execute",
|
||||||
},
|
},
|
||||||
@@ -186,42 +188,42 @@ func ReplaceWebSearchToolDescription(body []byte) ([]byte, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func InjectToolResultsClaude(claudePayload []byte, toolUseID, query string, results *WebSearchResults) ([]byte, error) {
|
func InjectToolResultsClaude(claudePayload []byte, toolUseID, query string, results *WebSearchResults) ([]byte, error) {
|
||||||
var payload map[string]interface{}
|
var payload map[string]any
|
||||||
if err := json.Unmarshal(claudePayload, &payload); err != nil {
|
if err := json.Unmarshal(claudePayload, &payload); err != nil {
|
||||||
return claudePayload, fmt.Errorf("parse claude payload: %w", err)
|
return claudePayload, fmt.Errorf("parse claude payload: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
rawMessages, ok := payload["messages"].([]interface{})
|
rawMessages, ok := payload["messages"].([]any)
|
||||||
if !ok {
|
if !ok {
|
||||||
return claudePayload, fmt.Errorf("claude payload missing messages array")
|
return claudePayload, fmt.Errorf("claude payload missing messages array")
|
||||||
}
|
}
|
||||||
|
|
||||||
assistantMsg := map[string]interface{}{
|
assistantMsg := map[string]any{
|
||||||
"role": "assistant",
|
"role": "assistant",
|
||||||
"content": []interface{}{
|
"content": []any{
|
||||||
map[string]interface{}{
|
map[string]any{
|
||||||
"type": "tool_use",
|
"type": "tool_use",
|
||||||
"id": toolUseID,
|
"id": toolUseID,
|
||||||
"name": "web_search",
|
"name": "web_search",
|
||||||
"input": map[string]interface{}{"query": query},
|
"input": map[string]any{"query": query},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
userContent := []interface{}{
|
userContent := []any{
|
||||||
map[string]interface{}{
|
map[string]any{
|
||||||
"type": "tool_result",
|
"type": "tool_result",
|
||||||
"tool_use_id": toolUseID,
|
"tool_use_id": toolUseID,
|
||||||
"content": formatToolResultText(results),
|
"content": formatToolResultText(results),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
if guidance := searchGuidanceText(); guidance != "" {
|
if guidance := searchGuidanceText(); guidance != "" {
|
||||||
userContent = append(userContent, map[string]interface{}{
|
userContent = append(userContent, map[string]any{
|
||||||
"type": "text",
|
"type": "text",
|
||||||
"text": guidance,
|
"text": guidance,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
userMsg := map[string]interface{}{
|
userMsg := map[string]any{
|
||||||
"role": "user",
|
"role": "user",
|
||||||
"content": userContent,
|
"content": userContent,
|
||||||
}
|
}
|
||||||
@@ -240,20 +242,20 @@ func InjectSearchIndicatorsInResponse(responsePayload []byte, searches []SearchI
|
|||||||
return responsePayload, nil
|
return responsePayload, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var response map[string]interface{}
|
var response map[string]any
|
||||||
if err := json.Unmarshal(responsePayload, &response); err != nil {
|
if err := json.Unmarshal(responsePayload, &response); err != nil {
|
||||||
return responsePayload, err
|
return responsePayload, err
|
||||||
}
|
}
|
||||||
content, _ := response["content"].([]interface{})
|
content, _ := response["content"].([]any)
|
||||||
updated := make([]interface{}, 0, len(searches)*2+len(content))
|
updated := make([]any, 0, len(searches)*2+len(content))
|
||||||
for _, search := range searches {
|
for _, search := range searches {
|
||||||
updated = append(updated, map[string]interface{}{
|
updated = append(updated, map[string]any{
|
||||||
"type": "server_tool_use",
|
"type": "server_tool_use",
|
||||||
"id": search.ToolUseID,
|
"id": search.ToolUseID,
|
||||||
"name": "web_search",
|
"name": "web_search",
|
||||||
"input": map[string]interface{}{"query": search.Query},
|
"input": map[string]any{"query": search.Query},
|
||||||
})
|
})
|
||||||
updated = append(updated, map[string]interface{}{
|
updated = append(updated, map[string]any{
|
||||||
"type": "web_search_tool_result",
|
"type": "web_search_tool_result",
|
||||||
"content": buildSearchResultContent(search.Results),
|
"content": buildSearchResultContent(search.Results),
|
||||||
})
|
})
|
||||||
@@ -268,8 +270,8 @@ func InjectSearchIndicatorsInResponse(responsePayload []byte, searches []SearchI
|
|||||||
return encoded, nil
|
return encoded, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func buildSearchResultContent(results *WebSearchResults) []map[string]interface{} {
|
func buildSearchResultContent(results *WebSearchResults) []map[string]any {
|
||||||
content := make([]map[string]interface{}, 0)
|
content := make([]map[string]any, 0)
|
||||||
if results == nil {
|
if results == nil {
|
||||||
return content
|
return content
|
||||||
}
|
}
|
||||||
@@ -278,7 +280,7 @@ func buildSearchResultContent(results *WebSearchResults) []map[string]interface{
|
|||||||
if result.Snippet != nil {
|
if result.Snippet != nil {
|
||||||
snippet = strings.TrimSpace(*result.Snippet)
|
snippet = strings.TrimSpace(*result.Snippet)
|
||||||
}
|
}
|
||||||
content = append(content, map[string]interface{}{
|
content = append(content, map[string]any{
|
||||||
"type": "web_search_result",
|
"type": "web_search_result",
|
||||||
"title": result.Title,
|
"title": result.Title,
|
||||||
"url": result.URL,
|
"url": result.URL,
|
||||||
@@ -325,7 +327,7 @@ func isWebSearchToolName(name, toolType string) bool {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func getInterfaceString(v interface{}) string {
|
func getInterfaceString(v any) string {
|
||||||
if v == nil {
|
if v == nil {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,14 +14,14 @@ type BufferedStreamResult struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func GenerateSearchIndicatorEvents(query, toolUseID string, results *WebSearchResults, startIndex int) [][]byte {
|
func GenerateSearchIndicatorEvents(query, toolUseID string, results *WebSearchResults, startIndex int) [][]byte {
|
||||||
searchContent := make([]map[string]interface{}, 0)
|
searchContent := make([]map[string]any, 0)
|
||||||
if results != nil {
|
if results != nil {
|
||||||
for _, result := range results.Results {
|
for _, result := range results.Results {
|
||||||
snippet := ""
|
snippet := ""
|
||||||
if result.Snippet != nil {
|
if result.Snippet != nil {
|
||||||
snippet = strings.TrimSpace(*result.Snippet)
|
snippet = strings.TrimSpace(*result.Snippet)
|
||||||
}
|
}
|
||||||
searchContent = append(searchContent, map[string]interface{}{
|
searchContent = append(searchContent, map[string]any{
|
||||||
"type": "web_search_result",
|
"type": "web_search_result",
|
||||||
"title": result.Title,
|
"title": result.Title,
|
||||||
"url": result.URL,
|
"url": result.URL,
|
||||||
@@ -33,21 +33,21 @@ func GenerateSearchIndicatorEvents(query, toolUseID string, results *WebSearchRe
|
|||||||
|
|
||||||
inputJSON, _ := json.Marshal(map[string]string{"query": query})
|
inputJSON, _ := json.Marshal(map[string]string{"query": query})
|
||||||
|
|
||||||
events := []map[string]interface{}{
|
events := []map[string]any{
|
||||||
{
|
{
|
||||||
"type": "content_block_start",
|
"type": "content_block_start",
|
||||||
"index": startIndex,
|
"index": startIndex,
|
||||||
"content_block": map[string]interface{}{
|
"content_block": map[string]any{
|
||||||
"type": "server_tool_use",
|
"type": "server_tool_use",
|
||||||
"id": toolUseID,
|
"id": toolUseID,
|
||||||
"name": "web_search",
|
"name": "web_search",
|
||||||
"input": map[string]interface{}{},
|
"input": map[string]any{},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "content_block_delta",
|
"type": "content_block_delta",
|
||||||
"index": startIndex,
|
"index": startIndex,
|
||||||
"delta": map[string]interface{}{
|
"delta": map[string]any{
|
||||||
"type": "input_json_delta",
|
"type": "input_json_delta",
|
||||||
"partial_json": string(inputJSON),
|
"partial_json": string(inputJSON),
|
||||||
},
|
},
|
||||||
@@ -59,7 +59,7 @@ func GenerateSearchIndicatorEvents(query, toolUseID string, results *WebSearchRe
|
|||||||
{
|
{
|
||||||
"type": "content_block_start",
|
"type": "content_block_start",
|
||||||
"index": startIndex + 1,
|
"index": startIndex + 1,
|
||||||
"content_block": map[string]interface{}{
|
"content_block": map[string]any{
|
||||||
"type": "web_search_tool_result",
|
"type": "web_search_tool_result",
|
||||||
"content": searchContent,
|
"content": searchContent,
|
||||||
},
|
},
|
||||||
@@ -96,20 +96,20 @@ func AnalyzeBufferedStream(chunks [][]byte) BufferedStreamResult {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
var event map[string]interface{}
|
var event map[string]any
|
||||||
if err := json.Unmarshal([]byte(payload), &event); err != nil {
|
if err := json.Unmarshal([]byte(payload), &event); err != nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
switch eventType, _ := event["type"].(string); eventType {
|
switch eventType, _ := event["type"].(string); eventType {
|
||||||
case "message_delta":
|
case "message_delta":
|
||||||
if delta, ok := event["delta"].(map[string]interface{}); ok {
|
if delta, ok := event["delta"].(map[string]any); ok {
|
||||||
if stopReason, ok := delta["stop_reason"].(string); ok && strings.TrimSpace(stopReason) != "" {
|
if stopReason, ok := delta["stop_reason"].(string); ok && strings.TrimSpace(stopReason) != "" {
|
||||||
result.StopReason = stopReason
|
result.StopReason = stopReason
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case "content_block_start":
|
case "content_block_start":
|
||||||
contentBlock, ok := event["content_block"].(map[string]interface{})
|
contentBlock, ok := event["content_block"].(map[string]any)
|
||||||
if !ok {
|
if !ok {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@@ -130,7 +130,7 @@ func AnalyzeBufferedStream(chunks [][]byte) BufferedStreamResult {
|
|||||||
if currentToolName == "" {
|
if currentToolName == "" {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
delta, ok := event["delta"].(map[string]interface{})
|
delta, ok := event["delta"].(map[string]any)
|
||||||
if !ok {
|
if !ok {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@@ -139,7 +139,7 @@ func AnalyzeBufferedStream(chunks [][]byte) BufferedStreamResult {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if partialJSON, ok := delta["partial_json"].(string); ok {
|
if partialJSON, ok := delta["partial_json"].(string); ok {
|
||||||
toolInputBuilder.WriteString(partialJSON)
|
_, _ = toolInputBuilder.WriteString(partialJSON)
|
||||||
}
|
}
|
||||||
case "content_block_stop":
|
case "content_block_stop":
|
||||||
if !isWebSearchToolName(currentToolName, "") {
|
if !isWebSearchToolName(currentToolName, "") {
|
||||||
@@ -191,7 +191,7 @@ func MaxContentBlockIndex(chunks [][]byte) int {
|
|||||||
if payload == "" || payload == "[DONE]" {
|
if payload == "" || payload == "[DONE]" {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
var event map[string]interface{}
|
var event map[string]any
|
||||||
if err := json.Unmarshal([]byte(payload), &event); err != nil {
|
if err := json.Unmarshal([]byte(payload), &event); err != nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@@ -221,7 +221,7 @@ func filterSSEChunk(chunk []byte, webSearchToolUseIndex, indexOffset int) ([]byt
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
builder.WriteString(line + "\n")
|
_, _ = builder.WriteString(line + "\n")
|
||||||
hasContent = true
|
hasContent = true
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@@ -238,12 +238,12 @@ func filterSSEChunk(chunk []byte, webSearchToolUseIndex, indexOffset int) ([]byt
|
|||||||
if adjusted == "" {
|
if adjusted == "" {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
builder.WriteString("data: " + adjusted + "\n")
|
_, _ = builder.WriteString("data: " + adjusted + "\n")
|
||||||
hasContent = true
|
hasContent = true
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
builder.WriteString(line + "\n")
|
_, _ = builder.WriteString(line + "\n")
|
||||||
if strings.TrimSpace(line) != "" {
|
if strings.TrimSpace(line) != "" {
|
||||||
hasContent = true
|
hasContent = true
|
||||||
}
|
}
|
||||||
@@ -259,7 +259,7 @@ func shouldSuppressEventPayload(payload string, webSearchToolUseIndex int) bool
|
|||||||
if payload == "" {
|
if payload == "" {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
var event map[string]interface{}
|
var event map[string]any
|
||||||
if err := json.Unmarshal([]byte(payload), &event); err != nil {
|
if err := json.Unmarshal([]byte(payload), &event); err != nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@@ -280,7 +280,7 @@ func adjustEventPayload(payload string, indexOffset int) string {
|
|||||||
if payload == "" || indexOffset == 0 {
|
if payload == "" || indexOffset == 0 {
|
||||||
return payload
|
return payload
|
||||||
}
|
}
|
||||||
var event map[string]interface{}
|
var event map[string]any
|
||||||
if err := json.Unmarshal([]byte(payload), &event); err != nil {
|
if err := json.Unmarshal([]byte(payload), &event); err != nil {
|
||||||
return payload
|
return payload
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -185,7 +185,7 @@ func (s *Store) ReserveRequest(ctx context.Context, tokenKey string) (time.Durat
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, fmt.Errorf("kiro cooldown reserve request: %w", err)
|
return 0, fmt.Errorf("kiro cooldown reserve request: %w", err)
|
||||||
}
|
}
|
||||||
parts, ok := values.([]interface{})
|
parts, ok := values.([]any)
|
||||||
if !ok || len(parts) != 3 {
|
if !ok || len(parts) != 3 {
|
||||||
return 0, fmt.Errorf("kiro cooldown reserve request: unexpected response %T", values)
|
return 0, fmt.Errorf("kiro cooldown reserve request: unexpected response %T", values)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -84,7 +84,7 @@ func buildKiroRequestID(resp *http.Response) string {
|
|||||||
return strings.TrimSpace(resp.Header.Get("x-amz-request-id"))
|
return strings.TrimSpace(resp.Header.Get("x-amz-request-id"))
|
||||||
}
|
}
|
||||||
|
|
||||||
func isKiroInvalidModelIDBody(respBody []byte) bool {
|
func isKiroInvalidModelIDBody(respBody []byte) bool { //nolint:unused // exercised by internal tests for error classification.
|
||||||
var payload struct {
|
var payload struct {
|
||||||
Reason string `json:"reason"`
|
Reason string `json:"reason"`
|
||||||
Message string `json:"message"`
|
Message string `json:"message"`
|
||||||
|
|||||||
@@ -491,7 +491,7 @@ func buildKiroEndpoints(account *Account) []kiroEndpointConfig {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func buildKiroPayloadForAccount(ctx context.Context, account *Account, anthropicBody []byte, modelID, token, requestModel string, headers http.Header) ([]byte, error) {
|
func buildKiroPayloadForAccount(ctx context.Context, account *Account, anthropicBody []byte, modelID, token, requestModel string, headers http.Header) ([]byte, error) { //nolint:unused // exercised by package tests as a narrow payload helper.
|
||||||
result, err := buildKiroPayloadForAccountWithRepo(ctx, nil, account, anthropicBody, modelID, token, requestModel, headers)
|
result, err := buildKiroPayloadForAccountWithRepo(ctx, nil, account, anthropicBody, modelID, token, requestModel, headers)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|||||||
@@ -357,11 +357,11 @@ func buildKiroWebSearchMCPRequest(query string) kiropkg.MCPRequest {
|
|||||||
ID: fmt.Sprintf("web_search_%s", kiropkg.GenerateToolUseID()),
|
ID: fmt.Sprintf("web_search_%s", kiropkg.GenerateToolUseID()),
|
||||||
JSONRPC: "2.0",
|
JSONRPC: "2.0",
|
||||||
Method: "tools/call",
|
Method: "tools/call",
|
||||||
Params: map[string]interface{}{
|
Params: map[string]any{
|
||||||
"name": "web_search",
|
"name": "web_search",
|
||||||
"arguments": map[string]interface{}{
|
"arguments": map[string]any{
|
||||||
"query": query,
|
"query": query,
|
||||||
"_meta": map[string]interface{}{
|
"_meta": map[string]any{
|
||||||
"_isValid": true,
|
"_isValid": true,
|
||||||
"_activePath": []string{"query"},
|
"_activePath": []string{"query"},
|
||||||
"_completedPaths": [][]string{{"query"}},
|
"_completedPaths": [][]string{{"query"}},
|
||||||
|
|||||||
Reference in New Issue
Block a user