Claude 24f816b6a3
Consolidate 22 sibling repos into layered organism structure
Place useful parts of the surrounding repos into sica-fondt by layer, per the
body model (Ada = membrane; brain/endocrine/capabilities/knowledge non-Ada):

- brain/        LLM reasoning + providers (dapr, hermes, MoMoA)
- capabilities/ REPRAG sidecars: hermes tools/skills, dapr tools, parallel
                dispatch, A51 channels, and the OSINT cluster
- knowledge/    LORAG corpus: 754 cyber-skills, agency personas, secure-coding,
                MITRE ATT&CK data
- reference/    defensive threat-reference (C3, shhbruh doc) + AdaYaml parser

License handling: AGPL sources (worldosint, advanced_evolution, mercury,
Reticulum) and GPL DeTTECT are SPEC-only clean-room/port descriptions — no
copyleft code copied. MIT/Apache/data parts copied as working trees.

Safety: shhbruh escape/persistence material and C3 covert-C2 kept as reference
only, not wired into the running organism. See CONSOLIDATION.md.

https://claude.ai/code/session_01UehUqEXXJJCsHoA4voCU5c
2026-06-10 06:53:01 +00:00

682 lines
27 KiB
Python

#
# Copyright 2026 The Dapr Authors
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
# http://www.apache.org/licenses/LICENSE-2.0
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
import json
import logging
from collections.abc import Iterable
from typing import (
Annotated,
Any,
Dict,
List,
Literal,
Optional,
Type,
TypeVar,
Union,
get_args,
get_origin,
)
from pydantic import BaseModel, Field, TypeAdapter, ValidationError, create_model
from dapr_agents.tool.utils.function_calling import to_function_call_definition
from dapr_agents.types import (
AssistantMessage,
OAIJSONSchema,
OAIResponseFormatSchema,
StructureError,
)
logger = logging.getLogger(__name__)
T = TypeVar("T", bound=BaseModel)
class StructureHandler:
@staticmethod
def is_json_string(input_string: str) -> bool:
"""
Check if the given input is a valid JSON string.
Args:
input_string (str): The string to check.
Returns:
bool: True if the input is a valid JSON string, False otherwise.
"""
try:
json.loads(input_string)
return True
except json.JSONDecodeError:
return False
@staticmethod
def normalize_iterable_format(tp: Any) -> Any:
origin = get_origin(tp)
args = get_args(tp)
if origin in (list, List, tuple, Iterable) and args:
item_type = args[0]
if isinstance(item_type, type) and issubclass(item_type, BaseModel):
logger.debug(
"Detected iterable of BaseModel. Wrapping in generated Pydantic model."
)
return StructureHandler.create_iterable_model(item_type)
return tp
@staticmethod
def generate_request(
response_format: Union[Type[T], Dict[str, Any], Iterable[Type[T]]],
llm_provider: str,
structured_mode: Literal["json", "function_call"] = "json",
**params,
) -> Dict[str, Any]:
"""
Generates a structured request that conforms to a specified API format using the given Pydantic model.
This function prepares a request configuration that includes the model as a tool specification and
sets the necessary parameters for the API call.
Args:
response_format (Union[Type[T], Dict[str, Any], Iterable[Type[T]]]): Defines the response structure.
- If `structured_mode="json"`: Can be a Pydantic model (converted to JSON schema) or a JSON schema dictionary.
- If `structured_mode="function_call"`: Must be a Pydantic model or an iterable of models.
- If an iterable of models is provided in either mode, it is treated as a list schema.
llm_provider (str): The LLM provider (e.g., "openai", "claude").
structured_mode (Literal["json", "function_call"]): Determines the response structure.
- "json": Generates and enforces a strict JSON schema.
- "function_call": Converts a Pydantic model to a function-call definition.
**params: Additional request parameters.
Returns:
Dict[str, Any]: Updated request parameters, including tools or response format.
Raises:
ValueError: If an unsupported `structured_mode` is provided.
TypeError: If `response_format` is invalid for the selected mode.
"""
logger.debug(f"Structured response mode: {structured_mode}")
response_format = StructureHandler.normalize_iterable_format(response_format)
# Handle iterable models in both modes
if structured_mode == "function_call":
model_cls = StructureHandler.resolve_response_model(response_format)
if not model_cls:
raise TypeError(
"function_call mode requires a single, unambiguous Pydantic model."
)
name = model_cls.__name__
description = model_cls.__doc__ or ""
model_tool_format = to_function_call_definition(
name, description, model_cls, llm_provider
)
params["tools"] = [model_tool_format]
params["tool_choice"] = {
"type": "function",
"function": {"name": model_tool_format["function"]["name"]},
}
return params
elif structured_mode == "json":
try:
logger.debug(
f"generate_request called with type={type(response_format)}, mode={structured_mode}, provider={llm_provider}"
)
# If it's a dict, assume it's already a JSON schema; otherwise, try to create from model
if isinstance(response_format, dict):
raw_schema = response_format
name = response_format.get("name", "custom_schema")
description = response_format.get("description")
elif isinstance(response_format, type) and issubclass(
response_format, BaseModel
):
raw_schema = response_format.model_json_schema()
name = response_format.__name__
description = response_format.__doc__
else:
raise TypeError("json mode requires a dict or a Pydantic model.")
# Enforce strict JSON schema (process $refs, $defs, etc.)
logger.debug(f"Raw Schema: {raw_schema}")
strict_schema = StructureHandler.enforce_strict_json_schema(raw_schema)
# Construct the JSON schema object using OAIJSONSchema
json_schema_obj = OAIJSONSchema(
name=name,
description=description,
schema_=strict_schema,
strict=True,
)
# Wrap it in the top-level response format object
response_format_obj = OAIResponseFormatSchema(
json_schema=json_schema_obj
)
logger.debug(
f"Generated JSON schema: {response_format_obj.model_dump()}"
)
# Use model_dump() to serialize the response format into a dictionary
params["response_format"] = response_format_obj.model_dump(
by_alias=True
)
except ValidationError as e:
logger.error(f"Validation error in JSON schema: {e}")
raise ValueError(f"Invalid response_format provided: {e}")
return params
else:
raise ValueError(
f"Unsupported structured_mode: {structured_mode}. Must be 'json' or 'function_call'."
)
@staticmethod
def create_iterable_model(
model: Type[BaseModel],
model_name: Optional[str] = None,
model_description: Optional[str] = None,
) -> Type[BaseModel]:
"""
Constructs an iterable Pydantic model for a given Pydantic model.
Args:
model (Type[BaseModel]): The original Pydantic model to capture a list of objects of the original model type.
model_name (Optional[str]): The name of the new iterable model. Defaults to None.
model_description (Optional[str]): The description of the new iterable model. Defaults to None.
Returns:
Type[BaseModel]: A new Pydantic model class representing a list of the original Pydantic model.
"""
model_name = model.__name__ if model_name is None else model_name
iterable_model_name = f"Iterable{model_name}"
objects_field = (
List[model],
Field(..., description=f"A list of `{model_name}` objects"),
)
iterable_model = create_model(
iterable_model_name, objects=objects_field, __base__=(BaseModel,)
)
iterable_model.__doc__ = (
f"A Pydantic model to capture `{iterable_model_name}` objects"
if model_description is None
else model_description
)
return iterable_model
@staticmethod
def extract_structured_response(
message: AssistantMessage,
llm_provider: str,
structured_mode: Literal["json", "function_call"] = "json",
) -> Union[str, Dict[str, Any]]:
"""
Extracts the structured JSON string or content from the response.
Args:
message (AssistantMessage): The API response data to extract.
llm_provider (str): The LLM provider (e.g., 'openai').
structured_mode (Literal["json", "function_call"]): The structured response mode.
Returns:
Union[str, Dict[str, Any]]: The extracted structured response.
Raises:
StructureError: If the structured response is not found or extraction fails.
"""
try:
logger.debug(f"Processing structured response for mode: {structured_mode}")
if llm_provider in ("openai", "nvidia", "huggingface", "dapr"):
if structured_mode == "function_call":
tool_calls = getattr(message, "tool_calls", None)
if tool_calls:
function = getattr(tool_calls[0], "function", None)
if function and hasattr(function, "arguments"):
extracted_response = function.arguments
logger.debug(
f"Extracted function-call response: {extracted_response}"
)
return extracted_response
# Fallback: LLM ignored tool_choice and returned plain JSON text
content = getattr(message, "content", None)
if content and isinstance(content, str):
try:
json.loads(content)
logger.warning(
"function_call mode: no tool_calls in response; "
"falling back to content as JSON."
)
return content
except json.JSONDecodeError:
pass
raise StructureError("No tool_calls found for function_call mode.")
elif structured_mode == "json":
content = getattr(message, "content", None)
refusal = getattr(message, "refusal", None)
if refusal:
logger.warning(
f"Model refused to fulfill the request: {refusal}"
)
raise StructureError(f"Request refused by the model: {refusal}")
if not content:
raise StructureError("No content found for JSON mode.")
# Try to parse content as JSON first
try:
if isinstance(content, str):
parsed = json.loads(content)
logger.debug(f"Successfully parsed JSON content: {parsed}")
return parsed
except json.JSONDecodeError:
pass
# If parsing fails or content is not a string, return as is
logger.debug(f"Returning raw content: {content}")
return content
else:
raise ValueError(
f"Unsupported structured_mode: {structured_mode}. Must be 'json' or 'function_call'."
)
else:
raise StructureError(f"Unsupported LLM provider: {llm_provider}")
except Exception as e:
logger.error(f"Error while extracting structured response: {e}")
raise StructureError(f"Extraction failed: {e}")
@staticmethod
def validate_response(response: Union[str, dict], model: Type[T]) -> T:
"""
Validates a JSON string or a dictionary using a specified Pydantic model.
This method checks whether the response is a JSON string or a dictionary.
If the response is a JSON string, it validates it using the `model_validate_json` method.
If the response is a dictionary, it validates it using the `model_validate` method.
Args:
response (Union[str, dict]): The JSON string or dictionary to validate.
model (Type[T]): The Pydantic model that defines the expected structure of the response.
Returns:
T: An instance of the Pydantic model populated with the validated data.
Raises:
StructureError: If the validation fails.
"""
try:
if isinstance(response, str) and StructureHandler.is_json_string(response):
return model.model_validate_json(response)
elif isinstance(response, dict):
# If it's a dictionary, use model_validate
return model.model_validate(response)
else:
raise ValueError("Response must be a JSON string or a dictionary.")
except ValidationError as e:
logger.error(f"Validation error while parsing structured response: {e}")
raise StructureError(f"Validation failed for structured response: {e}")
@staticmethod
def expand_local_refs(part: Dict[str, Any], root: Dict[str, Any]) -> Dict[str, Any]:
"""
Recursively expand all local $refs in the schema, including nested references.
Args:
part (Dict[str, Any]): The schema part to process.
root (Dict[str, Any]): The root schema for resolving $refs.
Returns:
Dict[str, Any]: The schema part with all $refs expanded.
"""
ref = part.pop("$ref", None)
if ref:
logger.debug(f"Found $ref: {ref}")
if not ref.startswith("#/$defs/"):
raise ValueError(f"Unexpected $ref format: {ref}")
ref_name = ref.split("/")[-1]
defs_section = root.get("$defs", {})
if ref_name not in defs_section:
raise ValueError(f"Reference '{ref_name}' not found in $defs.")
# Merge the referenced schema with the current part, resolving nested $refs
merged = {
**defs_section[ref_name],
**{k: v for k, v in part.items() if k != "$ref"},
}
return StructureHandler.expand_local_refs(merged, root)
# Process objects and their properties
if part.get("type") == "object" and "properties" in part:
for key, value in part["properties"].items():
part["properties"][key] = StructureHandler.expand_local_refs(
value, root
)
# Process arrays and their items
if part.get("type") == "array" and "items" in part:
part["items"] = StructureHandler.expand_local_refs(part["items"], root)
# Process anyOf and allOf schemas
for key in ("anyOf", "allOf"):
if key in part and isinstance(part[key], list):
part[key] = [
StructureHandler.expand_local_refs(subschema, root)
for subschema in part[key]
]
return part
@staticmethod
def enforce_strict_json_schema(schema: Dict[str, Any]) -> Dict[str, Any]:
"""
Enforces strict JSON schema constraints while making it OpenAI-compatible.
- Expands all local $refs by resolving them from the $defs section.
- Ensures "additionalProperties": false for object schemas.
- Removes default values and replaces optional fields with `anyOf: [{"type": T}, {"type": "null"}]`.
- Converts optional arrays to `anyOf: [{"type": "array", "items": T}, {"type": "null"}]`.
- Ensures all `array` schemas define `items`.
- Converts optional integers and floats to `anyOf: [{"type": T}, {"type": "null"}]`.
- Prevents the use of `anyOf` at the root level of an array.
Args:
schema (Dict[str, Any]): The JSON schema dictionary to process.
Returns:
Dict[str, Any]: The updated schema with strict constraints applied.
"""
# Expand all $refs (resolves and removes them)
schema = StructureHandler.expand_local_refs(schema, schema)
# Ensure "additionalProperties": false for all objects
if schema.get("type") == "object":
schema.setdefault("additionalProperties", False)
required_fields = set(schema.get("required", []))
for key, value in schema.get("properties", {}).items():
schema["properties"][key] = StructureHandler.enforce_strict_json_schema(
value
)
# Remove default values (not allowed by OpenAI)
schema["properties"][key].pop("default", None)
# Convert optional fields (string, number, integer) to `anyOf`
if key not in required_fields:
field_type = schema["properties"][key].get("type")
if field_type and not isinstance(
field_type, list
): # Ensure it's not already `anyOf`
if field_type in ["string", "integer", "number"]:
schema["properties"][key]["anyOf"] = [
{"type": field_type},
{"type": "null"},
]
schema["properties"][key].pop(
"type", None
) # Remove direct "type" field
# Ensure field is included in "required" (even if it allows null)
required_fields.add(key)
# Handle optional arrays inside object properties
if schema["properties"][key].get("anyOf") and isinstance(
schema["properties"][key]["anyOf"], list
):
for subschema in schema["properties"][key]["anyOf"]:
if subschema.get("type") == "array":
schema["properties"][key] = {
"anyOf": [
{
"type": "array",
"items": subschema.get("items", {}),
},
{"type": "null"},
]
}
# Ensure all required fields are explicitly listed
schema["required"] = list(required_fields)
# Process arrays and enforce strictness
if schema.get("type") == "array":
# Ensure `items` is always present in arrays
if "items" not in schema:
raise ValueError(f"Array schema missing 'items': {schema}")
schema["items"] = StructureHandler.enforce_strict_json_schema(
schema["items"]
)
# Convert optional arrays from `anyOf` to `anyOf: [{"type": "array", "items": T}, {"type": "null"}]`
if "anyOf" in schema and isinstance(schema["anyOf"], list):
if any(
subschema.get("type") == "array" for subschema in schema["anyOf"]
):
schema["anyOf"] = [
{"type": "array", "items": schema["items"]},
{"type": "null"},
]
schema.pop("type", None) # Remove direct "type" field
schema.pop(
"minItems", None
) # Remove `minItems`, not needed with null
# Process $defs and remove after expansion
if "$defs" in schema:
for def_name, def_schema in schema["$defs"].items():
schema["$defs"][def_name] = StructureHandler.enforce_strict_json_schema(
def_schema
)
schema.pop("$defs", None)
# Process anyOf and allOf schemas recursively
for key in ("anyOf", "allOf"):
if key in schema and isinstance(schema[key], list):
schema[key] = [
StructureHandler.enforce_strict_json_schema(subschema)
for subschema in schema[key]
]
return schema
@staticmethod
def unwrap_annotated_type(tp: Any) -> Any:
origin = get_origin(tp)
if origin is Annotated:
args = get_args(tp)
return StructureHandler.unwrap_annotated_type(args[0])
if hasattr(tp, "__supertype__"): # for NewType
return StructureHandler.unwrap_annotated_type(tp.__supertype__)
return tp
@staticmethod
def resolve_all_pydantic_models(tp: Any) -> List[Type[BaseModel]]:
models = []
tp = StructureHandler.unwrap_annotated_type(tp)
origin = get_origin(tp)
args = get_args(tp)
if isinstance(tp, type):
try:
if issubclass(tp, BaseModel):
return [tp]
except TypeError:
pass
if origin in (list, List, tuple, Iterable) and args:
inner = args[0]
if isinstance(inner, type):
try:
if issubclass(inner, BaseModel):
return [inner]
except TypeError:
pass
else:
logger.debug(
f"[resolve] Skipping non-class inner: {inner} ({type(inner)})"
)
if origin is Union:
for arg in args:
if isinstance(arg, type):
try:
if issubclass(arg, BaseModel):
models.append(arg)
except TypeError:
continue
return list(dict.fromkeys(models))
@staticmethod
def resolve_response_model(tp: Any) -> Optional[Type[BaseModel]]:
"""
Resolves a single Pydantic model from a type annotation if available.
This method attempts to extract exactly one BaseModel from the given type. It is used
to determine if structured output formatting (e.g., JSON schema or function call) should be applied.
- If the annotation is a BaseModel or a container of one (e.g., List[BaseModel]), it returns the model.
- If no Pydantic models are found (e.g., str, int), it returns None without logging.
- If multiple Pydantic models are found (e.g., Union[ModelA, ModelB]), it logs a warning and returns None.
Args:
tp (Any): The return type annotation to analyze.
Returns:
Optional[Type[BaseModel]]: The resolved model class, or None if not applicable or ambiguous.
"""
tp = StructureHandler.unwrap_annotated_type(tp)
models = StructureHandler.resolve_all_pydantic_models(tp)
if len(models) == 1:
return models[0]
elif len(models) == 0:
return None # No model = primitive or unsupported type → silently skip
else:
logger.warning(
f"Ambiguous model resolution: found multiple models in {tp}. Returning None."
)
return None
@staticmethod
def validate_against_signature(result: Any, expected_type: Any) -> Any:
"""
Validates a result against an expected return annotation type.
Supports:
- Single BaseModel
- List[BaseModel]
- Union[BaseModel, ...]
- Primitives (int, str, bool, etc.)
- Dict[str, Any], List[Dict[str, Any]]
Returns:
Any: The validated and possibly transformed result (e.g., model_dump()).
Raises:
TypeError: If validation fails or types mismatch.
"""
expected_type = StructureHandler.unwrap_annotated_type(expected_type)
origin = get_origin(expected_type)
args = get_args(expected_type)
# Handle one or more BaseModels
models = StructureHandler.resolve_all_pydantic_models(expected_type)
if models:
validation_errors = {}
for model_cls in models:
try:
# Always validate the entire result against the model class
# Don't try to validate individual list items
validated = StructureHandler.validate_response(result, model_cls)
return validated.model_dump()
except ValidationError as e:
validation_errors[model_cls.__name__] = e
continue
# If we get here, all models failed validation
if validation_errors:
error_details = "\n".join(
f"{model}: {error}" for model, error in validation_errors.items()
)
raise TypeError(
f"Validation failed for all possible models:\n{error_details}"
)
# Handle Union[str, dict, etc.]
if origin is Union:
for variant in args:
if isinstance(variant, type) and isinstance(result, variant):
return result
# Handle Dict[str, Any]
if origin is dict and isinstance(result, dict):
return result
# Handle List[Dict[str, Any]]
if origin is list and args and args[0] is dict and isinstance(result, list):
return result
# Fallback for primitives via TypeAdapter
try:
logger.debug(f"Falling back to TypeAdapter for type: {expected_type}")
adapter = TypeAdapter(expected_type)
return adapter.validate_python(result)
except ValidationError as e:
raise TypeError(f"Validation failed for type {expected_type}: {e}")
@staticmethod
def ensure_json_only_system_prompt(params: Dict[str, Any]) -> Dict[str, Any]:
"""
Dapr's chat client (today) does NOT forward OpenAI-style `response_format`
(e.g., {"type":"json_schema", ...}). That means the model won't be hard-constrained
to your schema. As a fallback, we prepend a system message that instructs the
model to return strict JSON so downstream parsing doesn't break.
Note:
- Dapr uses "inputs" (not "messages") for the message array.
- If "inputs" isn't present (future providers), we fall back to "messages".
"""
collection_key = "inputs" if "inputs" in params else "messages"
msgs = list(params.get(collection_key, []))
msgs.insert(
0,
{
"role": "system",
"content": (
"Return ONLY a valid JSON object that matches the provided schema. "
"No markdown, no code fences, no explanations—JSON object only."
),
},
)
params[collection_key] = msgs
return params