55 lines
1.5 KiB
Python
55 lines
1.5 KiB
Python
"""Shared contracts for platform-owned conversation system tools."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from collections.abc import Iterable, Mapping
|
|
from typing import Any
|
|
|
|
|
|
SYSTEM_TOOL_KINDS = frozenset(
|
|
{
|
|
"end_conversation",
|
|
"update_state",
|
|
"skip_turn",
|
|
"request_human_handoff",
|
|
}
|
|
)
|
|
|
|
|
|
def normalize_system_tools(values: Iterable[Any] | None) -> tuple[str, ...]:
|
|
"""Return known tool names once each while preserving editor order."""
|
|
return tuple(
|
|
dict.fromkeys(
|
|
str(value)
|
|
for value in values or ()
|
|
if str(value) in SYSTEM_TOOL_KINDS
|
|
)
|
|
)
|
|
|
|
|
|
def state_update_properties(
|
|
definitions: Mapping[str, Mapping[str, Any]] | None,
|
|
*,
|
|
allowed_names: Iterable[str] | None = None,
|
|
) -> dict[str, dict[str, Any]]:
|
|
"""Build an explicit LLM schema for writable declared variables."""
|
|
definitions = definitions or {}
|
|
names = (
|
|
list(dict.fromkeys(str(name) for name in allowed_names))
|
|
if allowed_names is not None
|
|
else list(definitions)
|
|
)
|
|
properties: dict[str, dict[str, Any]] = {}
|
|
for name in names:
|
|
definition = definitions.get(name)
|
|
if not isinstance(definition, Mapping):
|
|
continue
|
|
variable_type = str(definition.get("type") or "string")
|
|
if variable_type not in {"string", "number", "boolean"}:
|
|
continue
|
|
properties[name] = {
|
|
"type": variable_type,
|
|
"description": f"更新动态变量 {name}。",
|
|
}
|
|
return properties
|