use serde_json::{json, Value};
pub(super) fn chat_tool_definitions(has_default: bool) -> Vec<Value> {
let chat_session_palace_required: Vec<&str> = if has_default { vec![] } else { vec!["palace"] };
let chat_session_get_required: Vec<&str> = if has_default {
vec!["session_id"]
} else {
vec!["palace", "session_id"]
};
let chat_session_add_turn_required: Vec<&str> = if has_default {
vec!["session_id", "role", "content"]
} else {
vec!["palace", "session_id", "role", "content"]
};
let dream_consolidate_room_required: Vec<&str> =
if has_default { vec![] } else { vec!["palace"] };
let chat_turn_append_required: Vec<&str> = if has_default {
vec!["session_id", "prompt", "response"]
} else {
vec!["palace", "session_id", "prompt", "response"]
};
let chat_session_delete_required: Vec<&str> = if has_default {
vec!["session_id"]
} else {
vec!["palace", "session_id"]
};
vec![
json!({
"name": "chat_session_create",
"description": "Create a new chat session in a palace (spec-001 chat-session manager). Returns the session id, its creation timestamp, and the message count (0 for a fresh session). Pass an optional session_id to use a caller-chosen id (idempotent — an existing session is returned unchanged); pass an optional title to name a server-generated session. Sessions are stored in the palace's dedicated redb chat store, NOT the generic memory drawer surface.",
"inputSchema": {
"type": "object",
"properties": {
"palace": {"type": "string", "description": "Palace slug (optional if server started with --palace)"},
"session_id": {"type": "string", "description": "Optional caller-supplied session id; a UUID is generated when omitted."},
"title": {"type": "string", "description": "Optional session name (applied only when session_id is omitted)."}
},
"required": chat_session_palace_required,
}
}),
json!({
"name": "chat_session_add_turn",
"description": "Append a message (prompt or response) to a chat session's history. Creates the session if it does not yet exist. Returns the new message_count and updated_at. Bypasses the memory_remember signal/noise + dedup gates so sequential conversational turns persist verbatim.",
"inputSchema": {
"type": "object",
"properties": {
"palace": {"type": "string"},
"session_id": {"type": "string"},
"role": {"type": "string", "enum": ["user", "assistant", "system"]},
"content": {"type": "string"}
},
"required": chat_session_add_turn_required,
}
}),
json!({
"name": "chat_session_get",
"description": "Retrieve a full chat session: metadata plus every turn in chronological order. Errors if the session id is unknown.",
"inputSchema": {
"type": "object",
"properties": {
"palace": {"type": "string"},
"session_id": {"type": "string"}
},
"required": chat_session_get_required,
}
}),
json!({
"name": "chat_session_list",
"description": "List chat sessions in a palace as paginated metadata (id, title, timestamps, message_count) ordered most-recently-updated first. Does not include message bodies. Returns { sessions, total_count }.",
"inputSchema": {
"type": "object",
"properties": {
"palace": {"type": "string"},
"limit": {"type": "integer", "default": 50},
"offset": {"type": "integer", "default": 0}
},
"required": chat_session_palace_required,
}
}),
json!({
"name": "dream_consolidate_room",
"description": "Trigger LLM-driven semantic consolidation for one room (or all rooms) of a palace, on demand and synchronously (spec-001). Consolidates facts older than max_age_days into canonical summaries, then evicts the superseded originals so history shrinks. Task drawers are always skipped. No-op (zero counts) when no inference backend (OpenRouter key / local model) is configured. Returns { summary_facts_created, facts_evicted }.",
"inputSchema": {
"type": "object",
"properties": {
"palace": {"type": "string"},
"room": {"type": "string", "description": "Room to scope to (e.g. Backend, Planning, or a custom name). Omit or null to consolidate all rooms."},
"max_age_days": {"type": "integer", "default": 7, "description": "Only consolidate facts older than this many days."}
},
"required": dream_consolidate_room_required,
}
}),
json!({
"name": "palace_dream",
"description": "On-demand LLM-driven consolidation for a palace (issue #1721). Alias for dream_consolidate_room with the same parameters; use this name when following the palace_* convention. Triggers a scoped dream/consolidation cycle immediately for the named palace, optionally filtered to one room. Task drawers are always skipped. Gracefully returns zero counts when no inference backend is configured. Returns { palace, room, summary_facts_created, facts_evicted }.",
"inputSchema": {
"type": "object",
"properties": {
"palace": {"type": "string"},
"room": {"type": "string", "description": "Room to scope to. Omit or null to consolidate all rooms."},
"max_age_days": {"type": "integer", "default": 7, "description": "Only consolidate facts older than this many days."}
},
"required": dream_consolidate_room_required,
}
}),
json!({
"name": "chat_session_recall",
"description": "Retrieve a full chat session with all turns in order (alias for chat_session_get, preferred name for agent-facing recall). Errors if the session id is unknown.",
"inputSchema": {
"type": "object",
"properties": {
"palace": {"type": "string"},
"session_id": {"type": "string"}
},
"required": chat_session_get_required,
}
}),
json!({
"name": "chat_session_delete",
"description": "Delete a chat session (and its full history) from a palace. Idempotent: deleting an unknown session id is a no-op, not an error. Returns { deleted: session_id }.",
"inputSchema": {
"type": "object",
"properties": {
"palace": {"type": "string"},
"session_id": {"type": "string"}
},
"required": chat_session_delete_required,
}
}),
json!({
"name": "chat_turn_append",
"description": "Append a prompt/response PAIR to a chat session as two consecutive messages (user role then assistant role). Atomic at the session level — both messages are written together. Creates the session implicitly when it does not exist. Returns { message_count, updated_at }.",
"inputSchema": {
"type": "object",
"properties": {
"palace": {"type": "string"},
"session_id": {"type": "string"},
"prompt": {"type": "string", "description": "User-side message (stored with role=user)."},
"response": {"type": "string", "description": "Assistant-side message (stored with role=assistant)."}
},
"required": chat_turn_append_required,
}
}),
]
}