feat: add create_order, list_orders and update_order_status chat tools

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01V57jSQPqwkGG8BuAXg59X5
This commit is contained in:
Jonny 2026-09-13 19:11:01 +02:00
parent c10fd61c54
commit c0185bbbf7
2 changed files with 85 additions and 0 deletions

View File

@ -776,6 +776,52 @@ MEMORY_TOOLS = [
},
]
ORDER_TOOLS = [
{
"name": "create_order",
"description": "Create a new customer order, stored as a card in the 'Offen' (open) column of the Bestellungen Deck board.",
"input_schema": {
"type": "object",
"properties": {
"customer": {"type": "string", "description": "Customer or ordering party name"},
"description": {"type": "string", "description": "What was ordered"},
"due_date": {"type": "string", "description": "Optional due date in ISO 8601, e.g. 2026-09-20"},
},
"required": ["customer", "description"],
},
},
{
"name": "list_orders",
"description": "List orders from the Bestellungen Deck board, optionally filtered by status.",
"input_schema": {
"type": "object",
"properties": {
"status": {
"type": "string",
"description": "Filter by column: 'Offen', 'In Arbeit' or 'Erledigt'. Omit to list all.",
"enum": ["Offen", "In Arbeit", "Erledigt"],
},
},
},
},
{
"name": "update_order_status",
"description": "Move an order to a different status column (e.g. mark it 'In Arbeit' or 'Erledigt'). Call list_orders first if you don't already know the order's id.",
"input_schema": {
"type": "object",
"properties": {
"order_id": {"type": "integer", "description": "The order's id, from list_orders or create_order"},
"status": {
"type": "string",
"description": "New status column",
"enum": ["Offen", "In Arbeit", "Erledigt"],
},
},
"required": ["order_id", "status"],
},
},
]
CALENDAR_ASSISTANT_INSTRUCTIONS = (
"Du hast Zugriff auf den Kalender 'FFW-Onza-Alle' ueber die Tools "
"list_calendar_events, create_calendar_event, update_calendar_event und "
@ -808,6 +854,17 @@ MEMORY_ASSISTANT_INSTRUCTIONS = (
"und frage nach, welcher gemeint ist, statt den falschen zu loeschen."
)
ORDER_ASSISTANT_INSTRUCTIONS = (
"Du hast ausserdem Zugriff auf Bestellungen ueber die Tools "
"create_order, list_orders und update_order_status - sie leben als "
"Karten im Nextcloud-Deck-Board 'Bestellungen' mit den Spalten Offen, "
"In Arbeit und Erledigt. Du kannst alle drei Tools direkt aufrufen, "
"sobald du die noetigen Angaben hast - keine Rueckfrage noetig, da "
"nichts davon zerstoerend ist (es gibt kein Loeschen). Fuer "
"update_order_status brauchst du die order_id - ruf dafuer zuerst "
"list_orders auf, falls du sie noch nicht aus dem Gespraech kennst."
)
async def execute_tool(name: str, tool_input: dict) -> str:
if name == "list_calendar_events":
@ -845,6 +902,17 @@ async def execute_tool(name: str, tool_input: dict) -> str:
if name == "forget_fact":
result = await forget_fact(tool_input["query"])
return json.dumps(result)
if name == "create_order":
result = await create_order(
tool_input["customer"], tool_input["description"], tool_input.get("due_date")
)
return json.dumps(result)
if name == "list_orders":
result = await list_orders(tool_input.get("status"))
return json.dumps(result)
if name == "update_order_status":
result = await update_order_status(tool_input["order_id"], tool_input["status"])
return json.dumps(result)
raise ValueError(f"Unknown tool: {name}")

View File

@ -263,3 +263,20 @@ async def test_update_order_status_raises_when_card_not_found():
):
with pytest.raises(ValueError):
await main.update_order_status(999, "Erledigt")
@pytest.mark.asyncio
async def test_execute_tool_dispatches_order_tools():
with patch.object(main, "create_order", new=AsyncMock(return_value={"id": 1, "customer": "X"})):
result = await main.execute_tool(
"create_order", {"customer": "X", "description": "Y"}
)
assert json.loads(result) == {"id": 1, "customer": "X"}
with patch.object(main, "list_orders", new=AsyncMock(return_value=[{"id": 1}])):
result = await main.execute_tool("list_orders", {})
assert json.loads(result) == [{"id": 1}]
with patch.object(main, "update_order_status", new=AsyncMock(return_value={"id": 1, "status": "Erledigt"})):
result = await main.execute_tool("update_order_status", {"order_id": 1, "status": "Erledigt"})
assert json.loads(result) == {"id": 1, "status": "Erledigt"}