mirror of
https://github.com/SHOGGOTH-SECTOR/sica-fondt.git
synced 2026-08-01 08:30:20 +00:00
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
209 lines
7.8 KiB
Python
209 lines
7.8 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 logging
|
|
from datetime import date, datetime
|
|
from typing import Any, Dict, Iterable, List, Literal, Optional, Type, Union
|
|
|
|
from pydantic import BaseModel, ValidationError
|
|
|
|
from dapr_agents.llm.utils.structure import StructureHandler
|
|
from dapr_agents.prompt.prompty import Prompty, PromptyHelper
|
|
from dapr_agents.tool.base import AgentTool
|
|
from dapr_agents.tool.utils.tool import ToolHelper
|
|
from dapr_agents.types.message import BaseMessage
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
def _make_json_serializable(obj: Any) -> Any:
|
|
"""Recursively convert datetime/date to ISO strings for JSON serialization."""
|
|
if isinstance(obj, datetime):
|
|
return obj.isoformat()
|
|
if isinstance(obj, date):
|
|
return obj.isoformat()
|
|
if isinstance(obj, dict):
|
|
return {k: _make_json_serializable(v) for k, v in obj.items()}
|
|
if isinstance(obj, list):
|
|
return [_make_json_serializable(v) for v in obj]
|
|
return obj
|
|
|
|
|
|
class RequestHandler:
|
|
"""
|
|
Handles the preparation of requests for language models.
|
|
"""
|
|
|
|
@staticmethod
|
|
def process_prompty_messages(
|
|
prompty: Prompty, inputs: Dict[str, Any] = {}
|
|
) -> List[Dict[str, Any]]:
|
|
"""
|
|
Process and format messages based on Prompty template and provided inputs.
|
|
|
|
Args:
|
|
prompty (Prompty): The Prompty instance containing the template and settings.
|
|
inputs (Dict[str, Any]): Input variables for the Prompty template (default is an empty dictionary).
|
|
|
|
Returns:
|
|
List[Dict[str, Any]]: Processed and prepared messages.
|
|
"""
|
|
# Prepare inputs and generate messages from Prompty content
|
|
api_type = prompty.model.api
|
|
prepared_inputs = PromptyHelper.prepare_inputs(
|
|
inputs, prompty.inputs, prompty.sample
|
|
)
|
|
messages = PromptyHelper.to_prompt(
|
|
prompty.content, prepared_inputs, api_type=api_type
|
|
)
|
|
|
|
return messages
|
|
|
|
@staticmethod
|
|
def normalize_chat_messages(
|
|
messages: Union[
|
|
str,
|
|
Dict[str, Any],
|
|
BaseMessage,
|
|
Iterable[Union[Dict[str, Any], BaseMessage]],
|
|
],
|
|
) -> List[Dict[str, Any]]:
|
|
"""
|
|
Normalize and validate the input messages into a list of dictionaries.
|
|
|
|
Args:
|
|
messages (Union[str, Dict[str, Any], BaseMessage, Iterable[Union[Dict[str, Any], BaseMessage]]]):
|
|
Input messages in various formats (string, dict, BaseMessage, or an iterable).
|
|
|
|
Returns:
|
|
List[Dict[str, Any]]: A list of normalized message dictionaries with keys 'role' and 'content'.
|
|
|
|
Raises:
|
|
ValueError: If the input format is unsupported or if required fields are missing in a dictionary.
|
|
"""
|
|
# Initialize an empty list to store the normalized messages
|
|
normalized_messages = []
|
|
|
|
# Use a queue to process messages iteratively and handle nested structures
|
|
queue = [messages]
|
|
|
|
while queue:
|
|
msg = queue.pop(0)
|
|
if isinstance(msg, str):
|
|
normalized_messages.append({"role": "user", "content": msg})
|
|
elif isinstance(msg, BaseMessage):
|
|
normalized_messages.append(msg.model_dump())
|
|
elif isinstance(msg, dict):
|
|
role = msg.get("role")
|
|
if role not in {"user", "assistant", "tool", "system"}:
|
|
raise ValueError(
|
|
f"Unrecognized role '{role}'. Supported roles are 'user', 'assistant', 'tool', or 'system'."
|
|
)
|
|
normalized_messages.append(msg)
|
|
elif isinstance(msg, Iterable) and not isinstance(msg, (str, dict)):
|
|
queue.extend(msg)
|
|
else:
|
|
raise ValueError(f"Unsupported message format: {type(msg)}")
|
|
return normalized_messages
|
|
|
|
@staticmethod
|
|
def process_params(
|
|
params: Dict[str, Any],
|
|
llm_provider: str,
|
|
tools: Optional[List[Union[AgentTool, Dict[str, Any]]]] = None,
|
|
response_format: Optional[Union[Type[BaseModel], Dict[str, Any]]] = None,
|
|
structured_mode: Literal["json", "function_call"] = "json",
|
|
) -> Dict[str, Any]:
|
|
"""
|
|
Prepare request parameters for the language model.
|
|
|
|
Args:
|
|
params: Raw request params (messages/inputs, model, etc.).
|
|
llm_provider: Provider key, e.g. "openai", "dapr".
|
|
tools: Tools to expose to the model (AgentTool or already-shaped dicts).
|
|
response_format:
|
|
- If structured_mode == "json": a JSON Schema dict or a Pydantic model
|
|
(we'll convert) to request raw JSON output.
|
|
- If structured_mode == "function_call": a Pydantic model describing
|
|
the function/tool signature for model-side function calling.
|
|
structured_mode: "json" for raw JSON structured output,
|
|
"function_call" for tool/function calling.
|
|
|
|
Returns:
|
|
A params dict ready for the target provider.
|
|
"""
|
|
|
|
# Tools
|
|
if tools:
|
|
logger.info("Tools are available in the request.")
|
|
params["tools"] = [
|
|
ToolHelper.format_tool(t, tool_format=llm_provider) for t in tools
|
|
]
|
|
|
|
# Structured output
|
|
if response_format:
|
|
logger.info(f"Structured Mode Activated! mode={structured_mode}")
|
|
|
|
# If we're on Dapr, we cannot rely on OpenAI-style `response_format`.
|
|
# Add a small system nudge to enforce JSON-only output so we can parse reliably.
|
|
if llm_provider == "dapr":
|
|
params = StructureHandler.ensure_json_only_system_prompt(params)
|
|
|
|
# Generate provider-specific request params
|
|
params = StructureHandler.generate_request(
|
|
response_format=response_format,
|
|
llm_provider=llm_provider,
|
|
structured_mode=structured_mode,
|
|
**params,
|
|
)
|
|
|
|
return params
|
|
|
|
@staticmethod
|
|
def make_params_json_serializable(params: Dict[str, Any]) -> Dict[str, Any]:
|
|
"""
|
|
Return a copy of params with datetime/date values converted to ISO strings
|
|
so the dict is safe for JSON serialization (e.g. OpenAI API request body).
|
|
"""
|
|
return _make_json_serializable(params)
|
|
|
|
@staticmethod
|
|
def validate_request(
|
|
request: Union[BaseModel, Dict[str, Any]], request_class: Type[BaseModel]
|
|
) -> BaseModel:
|
|
"""
|
|
Validate and transform a dictionary into a Pydantic object.
|
|
|
|
Args:
|
|
request (Union[BaseModel, Dict[str, Any]]): The request data as a dictionary or a Pydantic object.
|
|
request_class (Type[BaseModel]): The Pydantic model class for validation.
|
|
|
|
Returns:
|
|
BaseModel: A validated Pydantic object.
|
|
|
|
Raises:
|
|
ValueError: If validation fails.
|
|
"""
|
|
if isinstance(request, dict):
|
|
try:
|
|
request = request_class(**request)
|
|
except ValidationError as e:
|
|
raise ValueError(f"Validation error: {e}")
|
|
|
|
try:
|
|
validated_request = request_class.model_validate(request)
|
|
except ValidationError as e:
|
|
raise ValueError(f"Validation error: {e}")
|
|
|
|
return validated_request
|