sshinmen Claude commited on
Commit
394ab74
·
1 Parent(s): bd5f2ec

Update handlers, registry and service

Browse files

- Update model definitions static data
- Update kiro gateway config
- Update SDK API handlers for claude, gemini, and openai
- Update cliproxy service

Co-Authored-By: Claude <noreply@anthropic.com>

internal/registry/model_definitions_static_data.go CHANGED
@@ -879,7 +879,7 @@ func GetKiroModels() []*ModelInfo {
879
  Type: "kiro",
880
  DisplayName: "Claude 3.7 Sonnet (Kiro)",
881
  Description: "Legacy model - hidden in Kiro API but still functional",
882
- ContextLength: 128000,
883
  MaxCompletionTokens: 8192,
884
  Thinking: &ThinkingSupport{Min: 1024, Max: 128000, ZeroAllowed: false, DynamicAllowed: false},
885
  },
 
879
  Type: "kiro",
880
  DisplayName: "Claude 3.7 Sonnet (Kiro)",
881
  Description: "Legacy model - hidden in Kiro API but still functional",
882
+ ContextLength: 200000,
883
  MaxCompletionTokens: 8192,
884
  Thinking: &ThinkingSupport{Min: 1024, Max: 128000, ZeroAllowed: false, DynamicAllowed: false},
885
  },
kiro-gateway/kiro/config.py CHANGED
@@ -37,45 +37,46 @@ load_dotenv()
37
  def _get_raw_env_value(var_name: str, env_file: str = ".env") -> Optional[str]:
38
  """
39
  Read variable value from .env file without processing escape sequences.
40
-
41
  This is necessary for correct handling of Windows paths where backslashes
42
  (e.g., D:\\Projects\\file.json) may be incorrectly interpreted
43
  as escape sequences (\\a -> bell, \\n -> newline, etc.).
44
-
45
  Args:
46
  var_name: Environment variable name
47
  env_file: Path to .env file (default ".env")
48
-
49
  Returns:
50
  Raw variable value or None if not found
51
  """
52
  env_path = Path(env_file)
53
  if not env_path.exists():
54
  return None
55
-
56
  try:
57
  # Read file as-is, without interpretation
58
  content = env_path.read_text(encoding="utf-8")
59
-
60
  # Search for variable considering different formats:
61
  # VAR="value" or VAR='value' or VAR=value
62
  # Pattern captures value with or without quotes
63
  pattern = rf'^{re.escape(var_name)}=(["\']?)(.+?)\1\s*$'
64
-
65
  for line in content.splitlines():
66
  line = line.strip()
67
  if line.startswith("#") or not line:
68
  continue
69
-
70
  match = re.match(pattern, line)
71
  if match:
72
  # Return value as-is, without processing escape sequences
73
  return match.group(2)
74
  except Exception:
75
  pass
76
-
77
  return None
78
 
 
79
  # ==================================================================================================
80
  # Server Settings
81
  # ==================================================================================================
@@ -198,7 +199,6 @@ HIDDEN_MODELS: Dict[str, str] = {
198
  # Claude 3.7 Sonnet - legacy flagship model, still works!
199
  # Hidden in Kiro API but functional. Great for users who prefer it.
200
  "claude-3.7-sonnet": "CLAUDE_3_7_SONNET_20250219_V1_0",
201
-
202
  # Add other hidden/experimental models here as discovered.
203
  # Example: "claude-secret-model": "INTERNAL_SECRET_MODEL_ID",
204
  }
@@ -220,6 +220,7 @@ FALLBACK_MODELS: List[Dict[str, str]] = [
220
  {"modelId": "claude-haiku-4.5"},
221
  {"modelId": "claude-sonnet-4.5"},
222
  {"modelId": "claude-opus-4.5"},
 
223
  ]
224
 
225
  # ==================================================================================================
@@ -323,10 +324,11 @@ def _warn_deprecated_debug_setting():
323
  """
324
  if _DEBUG_LAST_REQUEST_RAW and not _DEBUG_MODE_RAW:
325
  import sys
 
326
  # ANSI escape codes: yellow text
327
  YELLOW = "\033[93m"
328
  RESET = "\033[0m"
329
-
330
  warning_text = f"""
331
  {YELLOW}⚠️ DEPRECATED: DEBUG_LAST_REQUEST will be removed in future releases.
332
  Please use DEBUG_MODE instead:
@@ -344,16 +346,17 @@ def _warn_timeout_configuration():
344
  """
345
  Print warning if timeout configuration is suboptimal.
346
  Called at application startup.
347
-
348
  FIRST_TOKEN_TIMEOUT should be less than STREAMING_READ_TIMEOUT:
349
  - FIRST_TOKEN_TIMEOUT: time to wait for model to START responding
350
  - STREAMING_READ_TIMEOUT: time to wait BETWEEN chunks during streaming
351
  """
352
  if FIRST_TOKEN_TIMEOUT >= STREAMING_READ_TIMEOUT:
353
  import sys
 
354
  YELLOW = "\033[93m"
355
  RESET = "\033[0m"
356
-
357
  warning_text = f"""
358
  {YELLOW}⚠️ WARNING: Suboptimal timeout configuration detected.
359
 
@@ -371,6 +374,7 @@ def _warn_timeout_configuration():
371
  """
372
  print(warning_text, file=sys.stderr)
373
 
 
374
  # ==================================================================================================
375
  # Fake Reasoning Settings (Extended Thinking via Tag Injection)
376
  # ==================================================================================================
@@ -402,7 +406,9 @@ FAKE_REASONING_MAX_TOKENS: int = int(os.getenv("FAKE_REASONING_MAX_TOKENS", "400
402
  # - "strip_tags": Remove tags but keep thinking content in regular content
403
  #
404
  # Default: "as_reasoning_content"
405
- _FAKE_REASONING_HANDLING_RAW: str = os.getenv("FAKE_REASONING_HANDLING", "as_reasoning_content").lower()
 
 
406
  if _FAKE_REASONING_HANDLING_RAW in ("as_reasoning_content", "remove", "pass", "strip_tags"):
407
  FAKE_REASONING_HANDLING: str = _FAKE_REASONING_HANDLING_RAW
408
  else:
@@ -447,4 +453,3 @@ def get_kiro_api_host(region: str) -> str:
447
  def get_kiro_q_host(region: str) -> str:
448
  """Return Q API host for the specified region."""
449
  return KIRO_Q_HOST_TEMPLATE.format(region=region)
450
-
 
37
  def _get_raw_env_value(var_name: str, env_file: str = ".env") -> Optional[str]:
38
  """
39
  Read variable value from .env file without processing escape sequences.
40
+
41
  This is necessary for correct handling of Windows paths where backslashes
42
  (e.g., D:\\Projects\\file.json) may be incorrectly interpreted
43
  as escape sequences (\\a -> bell, \\n -> newline, etc.).
44
+
45
  Args:
46
  var_name: Environment variable name
47
  env_file: Path to .env file (default ".env")
48
+
49
  Returns:
50
  Raw variable value or None if not found
51
  """
52
  env_path = Path(env_file)
53
  if not env_path.exists():
54
  return None
55
+
56
  try:
57
  # Read file as-is, without interpretation
58
  content = env_path.read_text(encoding="utf-8")
59
+
60
  # Search for variable considering different formats:
61
  # VAR="value" or VAR='value' or VAR=value
62
  # Pattern captures value with or without quotes
63
  pattern = rf'^{re.escape(var_name)}=(["\']?)(.+?)\1\s*$'
64
+
65
  for line in content.splitlines():
66
  line = line.strip()
67
  if line.startswith("#") or not line:
68
  continue
69
+
70
  match = re.match(pattern, line)
71
  if match:
72
  # Return value as-is, without processing escape sequences
73
  return match.group(2)
74
  except Exception:
75
  pass
76
+
77
  return None
78
 
79
+
80
  # ==================================================================================================
81
  # Server Settings
82
  # ==================================================================================================
 
199
  # Claude 3.7 Sonnet - legacy flagship model, still works!
200
  # Hidden in Kiro API but functional. Great for users who prefer it.
201
  "claude-3.7-sonnet": "CLAUDE_3_7_SONNET_20250219_V1_0",
 
202
  # Add other hidden/experimental models here as discovered.
203
  # Example: "claude-secret-model": "INTERNAL_SECRET_MODEL_ID",
204
  }
 
220
  {"modelId": "claude-haiku-4.5"},
221
  {"modelId": "claude-sonnet-4.5"},
222
  {"modelId": "claude-opus-4.5"},
223
+ {"modelId": "claude-3.7-sonnet"},
224
  ]
225
 
226
  # ==================================================================================================
 
324
  """
325
  if _DEBUG_LAST_REQUEST_RAW and not _DEBUG_MODE_RAW:
326
  import sys
327
+
328
  # ANSI escape codes: yellow text
329
  YELLOW = "\033[93m"
330
  RESET = "\033[0m"
331
+
332
  warning_text = f"""
333
  {YELLOW}⚠️ DEPRECATED: DEBUG_LAST_REQUEST will be removed in future releases.
334
  Please use DEBUG_MODE instead:
 
346
  """
347
  Print warning if timeout configuration is suboptimal.
348
  Called at application startup.
349
+
350
  FIRST_TOKEN_TIMEOUT should be less than STREAMING_READ_TIMEOUT:
351
  - FIRST_TOKEN_TIMEOUT: time to wait for model to START responding
352
  - STREAMING_READ_TIMEOUT: time to wait BETWEEN chunks during streaming
353
  """
354
  if FIRST_TOKEN_TIMEOUT >= STREAMING_READ_TIMEOUT:
355
  import sys
356
+
357
  YELLOW = "\033[93m"
358
  RESET = "\033[0m"
359
+
360
  warning_text = f"""
361
  {YELLOW}⚠️ WARNING: Suboptimal timeout configuration detected.
362
 
 
374
  """
375
  print(warning_text, file=sys.stderr)
376
 
377
+
378
  # ==================================================================================================
379
  # Fake Reasoning Settings (Extended Thinking via Tag Injection)
380
  # ==================================================================================================
 
406
  # - "strip_tags": Remove tags but keep thinking content in regular content
407
  #
408
  # Default: "as_reasoning_content"
409
+ _FAKE_REASONING_HANDLING_RAW: str = os.getenv(
410
+ "FAKE_REASONING_HANDLING", "as_reasoning_content"
411
+ ).lower()
412
  if _FAKE_REASONING_HANDLING_RAW in ("as_reasoning_content", "remove", "pass", "strip_tags"):
413
  FAKE_REASONING_HANDLING: str = _FAKE_REASONING_HANDLING_RAW
414
  else:
 
453
  def get_kiro_q_host(region: str) -> str:
454
  """Return Q API host for the specified region."""
455
  return KIRO_Q_HOST_TEMPLATE.format(region=region)
 
sdk/api/handlers/claude/code_handlers.go CHANGED
@@ -53,7 +53,31 @@ func (h *ClaudeCodeAPIHandler) HandlerType() string {
53
  func (h *ClaudeCodeAPIHandler) Models() []map[string]any {
54
  // Get dynamic models from the global registry
55
  modelRegistry := registry.GetGlobalRegistry()
56
- return modelRegistry.GetAvailableModels("claude")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
57
  }
58
 
59
  // ClaudeMessages handles Claude-compatible streaming chat completions.
 
53
  func (h *ClaudeCodeAPIHandler) Models() []map[string]any {
54
  // Get dynamic models from the global registry
55
  modelRegistry := registry.GetGlobalRegistry()
56
+ models := modelRegistry.GetAvailableModels("claude")
57
+
58
+ // Always include static Kiro models
59
+ kiroModels := registry.GetKiroModels()
60
+ seen := make(map[string]bool)
61
+ for _, m := range models {
62
+ if id, ok := m["id"].(string); ok {
63
+ seen[id] = true
64
+ }
65
+ }
66
+ for _, km := range kiroModels {
67
+ if seen[km.ID] {
68
+ continue
69
+ }
70
+ models = append(models, map[string]any{
71
+ "id": km.ID,
72
+ "object": "model",
73
+ "created": km.Created,
74
+ "owned_by": "kiro",
75
+ "type": "model",
76
+ "display_name": km.DisplayName,
77
+ })
78
+ }
79
+
80
+ return models
81
  }
82
 
83
  // ClaudeMessages handles Claude-compatible streaming chat completions.
sdk/api/handlers/gemini/gemini_handlers.go CHANGED
@@ -42,7 +42,30 @@ func (h *GeminiAPIHandler) HandlerType() string {
42
  func (h *GeminiAPIHandler) Models() []map[string]any {
43
  // Get dynamic models from the global registry
44
  modelRegistry := registry.GetGlobalRegistry()
45
- return modelRegistry.GetAvailableModels("gemini")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
46
  }
47
 
48
  // GeminiModels handles the Gemini models listing endpoint.
 
42
  func (h *GeminiAPIHandler) Models() []map[string]any {
43
  // Get dynamic models from the global registry
44
  modelRegistry := registry.GetGlobalRegistry()
45
+ models := modelRegistry.GetAvailableModels("gemini")
46
+
47
+ // Always include static Kiro models (convert to Gemini format)
48
+ kiroModels := registry.GetKiroModels()
49
+ seen := make(map[string]bool)
50
+ for _, m := range models {
51
+ if name, ok := m["name"].(string); ok {
52
+ seen[name] = true
53
+ }
54
+ }
55
+ for _, km := range kiroModels {
56
+ name := "models/" + km.ID
57
+ if seen[name] {
58
+ continue
59
+ }
60
+ models = append(models, map[string]any{
61
+ "name": name,
62
+ "version": "1.0",
63
+ "displayName": km.DisplayName,
64
+ "supportedGenerationMethods": []string{"generateContent"},
65
+ })
66
+ }
67
+
68
+ return models
69
  }
70
 
71
  // GeminiModels handles the Gemini models listing endpoint.
sdk/api/handlers/openai/openai_handlers.go CHANGED
@@ -52,7 +52,29 @@ func (h *OpenAIAPIHandler) HandlerType() string {
52
  func (h *OpenAIAPIHandler) Models() []map[string]any {
53
  // Get dynamic models from the global registry
54
  modelRegistry := registry.GetGlobalRegistry()
55
- return modelRegistry.GetAvailableModels("openai")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
56
  }
57
 
58
  // OpenAIModels handles the /v1/models endpoint.
 
52
  func (h *OpenAIAPIHandler) Models() []map[string]any {
53
  // Get dynamic models from the global registry
54
  modelRegistry := registry.GetGlobalRegistry()
55
+ models := modelRegistry.GetAvailableModels("openai")
56
+
57
+ // Always include static Kiro models
58
+ kiroModels := registry.GetKiroModels()
59
+ seen := make(map[string]bool)
60
+ for _, m := range models {
61
+ if id, ok := m["id"].(string); ok {
62
+ seen[id] = true
63
+ }
64
+ }
65
+ for _, km := range kiroModels {
66
+ if seen[km.ID] {
67
+ continue
68
+ }
69
+ models = append(models, map[string]any{
70
+ "id": km.ID,
71
+ "object": "model",
72
+ "created": km.Created,
73
+ "owned_by": "kiro",
74
+ })
75
+ }
76
+
77
+ return models
78
  }
79
 
80
  // OpenAIModels handles the /v1/models endpoint.
sdk/api/handlers/openai/openai_responses_handlers.go CHANGED
@@ -49,7 +49,29 @@ func (h *OpenAIResponsesAPIHandler) HandlerType() string {
49
  func (h *OpenAIResponsesAPIHandler) Models() []map[string]any {
50
  // Get dynamic models from the global registry
51
  modelRegistry := registry.GetGlobalRegistry()
52
- return modelRegistry.GetAvailableModels("openai")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
53
  }
54
 
55
  // OpenAIResponsesModels handles the /v1/models endpoint.
 
49
  func (h *OpenAIResponsesAPIHandler) Models() []map[string]any {
50
  // Get dynamic models from the global registry
51
  modelRegistry := registry.GetGlobalRegistry()
52
+ models := modelRegistry.GetAvailableModels("openai")
53
+
54
+ // Always include static Kiro models
55
+ kiroModels := registry.GetKiroModels()
56
+ seen := make(map[string]bool)
57
+ for _, m := range models {
58
+ if id, ok := m["id"].(string); ok {
59
+ seen[id] = true
60
+ }
61
+ }
62
+ for _, km := range kiroModels {
63
+ if seen[km.ID] {
64
+ continue
65
+ }
66
+ models = append(models, map[string]any{
67
+ "id": km.ID,
68
+ "object": "model",
69
+ "created": km.Created,
70
+ "owned_by": "kiro",
71
+ })
72
+ }
73
+
74
+ return models
75
  }
76
 
77
  // OpenAIResponsesModels handles the /v1/models endpoint.
sdk/cliproxy/service.go CHANGED
@@ -774,6 +774,9 @@ func (s *Service) registerModelsForAuth(a *coreauth.Auth) {
774
  case "iflow":
775
  models = registry.GetIFlowModels()
776
  models = applyExcludedModels(models, excluded)
 
 
 
777
  default:
778
  // Handle OpenAI-compatibility providers by name using config
779
  if s.cfg != nil {
 
774
  case "iflow":
775
  models = registry.GetIFlowModels()
776
  models = applyExcludedModels(models, excluded)
777
+ case "kiro":
778
+ models = registry.GetKiroModels()
779
+ models = applyExcludedModels(models, excluded)
780
  default:
781
  // Handle OpenAI-compatibility providers by name using config
782
  if s.cfg != nil {