-
Notifications
You must be signed in to change notification settings - Fork 8
feat: optimize config valid for runtime auth #28
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -16,7 +16,7 @@ | |||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| import re | ||||||||||||||||||||||||||||||||||||||||||
| from typing import List, Any | ||||||||||||||||||||||||||||||||||||||||||
| from dataclasses import fields | ||||||||||||||||||||||||||||||||||||||||||
| from dataclasses import fields, is_dataclass | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| from agentkit.toolkit.config.config import CommonConfig | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -82,7 +82,59 @@ def validate_common_config(config: CommonConfig) -> List[str]: | |||||||||||||||||||||||||||||||||||||||||
| return errors | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| @staticmethod | ||||||||||||||||||||||||||||||||||||||||||
| def _validate_conditional_fields(config: CommonConfig) -> List[str]: | ||||||||||||||||||||||||||||||||||||||||||
| def validate_dataclass(config: Any) -> List[str]: | ||||||||||||||||||||||||||||||||||||||||||
| if not is_dataclass(config): | ||||||||||||||||||||||||||||||||||||||||||
| return [] | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| errors: List[str] = [] | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| for field in fields(config): | ||||||||||||||||||||||||||||||||||||||||||
| if field.name.startswith("_"): | ||||||||||||||||||||||||||||||||||||||||||
| continue | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| validation = field.metadata.get("validation", {}) | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| if validation.get("type") == "conditional": | ||||||||||||||||||||||||||||||||||||||||||
| continue | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| value = getattr(config, field.name) | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| if validation.get("required") and ( | ||||||||||||||||||||||||||||||||||||||||||
| not value or (isinstance(value, str) and not value.strip()) | ||||||||||||||||||||||||||||||||||||||||||
| ): | ||||||||||||||||||||||||||||||||||||||||||
| desc = field.metadata.get("description", field.name) | ||||||||||||||||||||||||||||||||||||||||||
| errors.append(f"{desc} is required") | ||||||||||||||||||||||||||||||||||||||||||
| continue | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| pattern = validation.get("pattern") | ||||||||||||||||||||||||||||||||||||||||||
| if pattern and value and isinstance(value, str): | ||||||||||||||||||||||||||||||||||||||||||
| if not re.match(pattern, value): | ||||||||||||||||||||||||||||||||||||||||||
| desc = field.metadata.get("description", field.name) | ||||||||||||||||||||||||||||||||||||||||||
| msg = validation.get("message", "Invalid format") | ||||||||||||||||||||||||||||||||||||||||||
| errors.append(f"{desc}: {msg}") | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| choices = field.metadata.get("choices") | ||||||||||||||||||||||||||||||||||||||||||
| if choices and value: | ||||||||||||||||||||||||||||||||||||||||||
| valid_values = [] | ||||||||||||||||||||||||||||||||||||||||||
| if isinstance(choices, list): | ||||||||||||||||||||||||||||||||||||||||||
| if choices and isinstance(choices[0], dict): | ||||||||||||||||||||||||||||||||||||||||||
| valid_values = [c["value"] for c in choices] | ||||||||||||||||||||||||||||||||||||||||||
| else: | ||||||||||||||||||||||||||||||||||||||||||
| valid_values = choices | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| if valid_values and value not in valid_values: | ||||||||||||||||||||||||||||||||||||||||||
| desc = field.metadata.get("description", field.name) | ||||||||||||||||||||||||||||||||||||||||||
| errors.append( | ||||||||||||||||||||||||||||||||||||||||||
| f"{desc} must be one of: {', '.join(map(str, valid_values))}" | ||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+125
to
+130
|
||||||||||||||||||||||||||||||||||||||||||
| if valid_values and value not in valid_values: | |
| desc = field.metadata.get("description", field.name) | |
| errors.append( | |
| f"{desc} must be one of: {', '.join(map(str, valid_values))}" | |
| ) | |
| if valid_values: | |
| if isinstance(value, list): | |
| invalid_items = [v for v in value if v not in valid_values] | |
| if invalid_items: | |
| desc = field.metadata.get("description", field.name) | |
| errors.append( | |
| f"{desc} contains invalid value(s): {', '.join(map(str, invalid_items))}. " | |
| f"Allowed values are: {', '.join(map(str, valid_values))}" | |
| ) | |
| else: | |
| if value not in valid_values: | |
| desc = field.metadata.get("description", field.name) | |
| errors.append( | |
| f"{desc} must be one of: {', '.join(map(str, valid_values))}" | |
| ) |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -171,6 +171,11 @@ class HybridStrategyConfig(AutoSerializableMixin): | |||||||||||||||||||||||||||
| metadata={ | ||||||||||||||||||||||||||||
| "description": "CR instance type when auto-creating (Micro or Enterprise)", | ||||||||||||||||||||||||||||
| "icon": "⚙️", | ||||||||||||||||||||||||||||
| "choices": [ | ||||||||||||||||||||||||||||
| {"value": "Micro", "description": "Micro"}, | ||||||||||||||||||||||||||||
| {"value": "Enterprise", "description": "Enterprise"}, | ||||||||||||||||||||||||||||
| ], | ||||||||||||||||||||||||||||
| "hidden": True, | ||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||
| cr_image_full_url: str = field( | ||||||||||||||||||||||||||||
|
|
@@ -244,13 +249,33 @@ class HybridStrategyConfig(AutoSerializableMixin): | |||||||||||||||||||||||||||
| metadata={ | ||||||||||||||||||||||||||||
| "description": "OIDC Discovery URL for JWT validation (required when auth_type is custom_jwt)", | ||||||||||||||||||||||||||||
| "examples": "https://userpool-xxx.userpool.auth.id.cn-beijing.volces.com/.well-known/openid-configuration", | ||||||||||||||||||||||||||||
| "prompt_condition": { | ||||||||||||||||||||||||||||
| "depends_on": "runtime_auth_type", | ||||||||||||||||||||||||||||
| "values": [AUTH_TYPE_CUSTOM_JWT], | ||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||
| "validation": { | ||||||||||||||||||||||||||||
| "type": "conditional", | ||||||||||||||||||||||||||||
| "depends_on": "runtime_auth_type", | ||||||||||||||||||||||||||||
| "rules": { | ||||||||||||||||||||||||||||
| AUTH_TYPE_CUSTOM_JWT: { | ||||||||||||||||||||||||||||
| "required": True, | ||||||||||||||||||||||||||||
| "pattern": r"^https://.+", | ||||||||||||||||||||||||||||
| "hint": "(must be a valid https URL)", | ||||||||||||||||||||||||||||
| "message": "must be a valid https URL", | ||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||
| runtime_jwt_allowed_clients: List[str] = field( | ||||||||||||||||||||||||||||
| default_factory=list, | ||||||||||||||||||||||||||||
| metadata={ | ||||||||||||||||||||||||||||
| "description": "Allowed OAuth2 client IDs (required when auth_type is custom_jwt)", | ||||||||||||||||||||||||||||
| "examples": "['fa99ec54-8a1c-49b2-9a9e-3f3ba31d9a33']", | ||||||||||||||||||||||||||||
| "prompt_condition": { | ||||||||||||||||||||||||||||
| "depends_on": "runtime_auth_type", | ||||||||||||||||||||||||||||
| "values": [AUTH_TYPE_CUSTOM_JWT], | ||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
| }, | |
| }, | |
| "validation": { | |
| "type": "conditional", | |
| "depends_on": "runtime_auth_type", | |
| "rules": { | |
| AUTH_TYPE_CUSTOM_JWT: { | |
| "required": True, | |
| "min_items": 1, | |
| "message": "At least one allowed client ID must be specified when using custom_jwt authentication.", | |
| } | |
| }, | |
| }, |
Copilot
AI
Dec 16, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The field runtime_jwt_allowed_clients has a prompt_condition but is missing a validation configuration. If this field is required when runtime_auth_type is custom_jwt (as indicated in the description), it should have a conditional validation rule similar to runtime_jwt_discovery_url. Consider adding a validation block to ensure this field is properly validated.
| }, | |
| }, | |
| "validation": { | |
| "type": "conditional", | |
| "depends_on": "runtime_auth_type", | |
| "rules": { | |
| AUTH_TYPE_CUSTOM_JWT: { | |
| "required": True, | |
| "min_items": 1, | |
| "message": "At least one allowed client ID must be specified when using custom_jwt authentication.", | |
| } | |
| }, | |
| }, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The validation logic for required fields checks "not value" which will incorrectly treat empty lists, 0, False, and other falsy values as missing. Consider using "value is None" or "value is None or value == ''" for strings specifically to avoid false positives for legitimate falsy values.