diff --git a/flexus_simple_bots/frog/frog_bot.py b/flexus_simple_bots/frog/frog_bot.py index 7422a5b2..bcd11e78 100644 --- a/flexus_simple_bots/frog/frog_bot.py +++ b/flexus_simple_bots/frog/frog_bot.py @@ -86,10 +86,58 @@ }, ) +DRINK_TOOL = ckit_cloudtool.CloudTool( + strict=True, + name="drink", + description="Make the frog drink water or pond water to stay hydrated.", + parameters={ + "type": "object", + "properties": { + "amount": {"type": "integer", "description": "Amount to drink in milliliters"}, + "drink_type": {"type": "string", "enum": ["water", "pond_water"], "description": "Type of liquid to drink"}, + }, + "required": ["amount", "drink_type"], + "additionalProperties": False, + }, +) + +EAT_TOOL = ckit_cloudtool.CloudTool( + strict=True, + name="eat", + description="Eat food to satisfy hunger.", + parameters={ + "type": "object", + "properties": { + "food_type": {"type": "string", "description": "Type of food to eat (e.g., 'fly', 'bug', 'lettuce')"}, + "quantity": {"type": "integer", "description": "How many items to eat"}, + }, + "required": ["food_type", "quantity"], + "additionalProperties": False, + }, +) + +FIGHT_TOOL = ckit_cloudtool.CloudTool( + strict=True, + name="fight", + description="Fight an opponent using different combat styles.", + parameters={ + "type": "object", + "properties": { + "opponent": {"type": "string", "description": "The name of the opponent to fight"}, + "style": {"type": "string", "enum": ["kick", "punch", "bite"], "description": "Combat style to use"}, + }, + "required": ["opponent", "style"], + "additionalProperties": False, + }, +) + TOOLS = [ RIBBIT_TOOL, CATCH_INSECTS_TOOL, MAKE_POND_REPORT_TOOL, + DRINK_TOOL, + EAT_TOOL, + FIGHT_TOOL, fi_mongo_store.MONGO_STORE_TOOL, fi_pdoc.POLICY_DOCUMENT_TOOL, ] @@ -109,7 +157,24 @@ async def frog_main_loop(fclient: ckit_client.FlexusClient, rcx: ckit_bot_exec.R @rcx.on_updated_message async def updated_message_in_db(msg: ckit_ask_model.FThreadMessageOutput): - pass + if msg.ftm_role != "user": + return + content = msg.ftm_content + if isinstance(content, str): + try: + content = json.loads(content) + except (json.JSONDecodeError, TypeError): + pass + text_content = "" + if isinstance(content, str): + text_content = content + elif isinstance(content, list): + for part in content: + if isinstance(part, dict) and part.get("m_type") == "text": + text_content += part.get("m_content", "") + if "cool bros" in text_content.lower(): + http = await rcx.fclient.use_http() + await ckit_ask_model.thread_add_user_message(http, msg.ftm_belongs_to_ft_id, "ribbit", "frog_auto_ribbit", 100) @rcx.on_updated_thread async def updated_thread_in_db(th: ckit_ask_model.FThreadOutput): @@ -202,6 +267,43 @@ async def toolcall_make_pond_report(toolcall: ckit_cloudtool.FCloudtoolCall, mod await pdoc_integration.pdoc_create(path, json.dumps(pond_report_doc), fuser_id) return f"✍️ {path}\n\n✓ Successfully updated\n\n" + @rcx.on_tool_call(DRINK_TOOL.name) + async def toolcall_drink(toolcall: ckit_cloudtool.FCloudtoolCall, model_produced_args: Dict[str, Any]) -> str: + amount = model_produced_args["amount"] + drink_type = model_produced_args["drink_type"] + + drink_descriptions = { + "water": "clean, refreshing water", + "pond_water": "tasty pond water", + } + + description = drink_descriptions.get(drink_type, drink_type) + result = f"Glug glug! Frog drank {amount}ml of {description} and is refreshed!" + + logger.info(f"Frog drank {amount}ml of {drink_type}") + return result + + @rcx.on_tool_call(EAT_TOOL.name) + async def toolcall_eat(toolcall: ckit_cloudtool.FCloudtoolCall, model_produced_args: Dict[str, Any]) -> str: + food_type = model_produced_args["food_type"] + quantity = model_produced_args["quantity"] + logger.info(f"Frog ate {quantity} {food_type}(s)") + return f"Nom nom! Frog ate {quantity} {food_type}s. Burp!" + + @rcx.on_tool_call(FIGHT_TOOL.name) + async def toolcall_fight(toolcall: ckit_cloudtool.FCloudtoolCall, model_produced_args: Dict[str, Any]) -> str: + opponent = model_produced_args["opponent"] + style = model_produced_args["style"] + logger.info(f"Frog fought {opponent} using {style}") + + if style == "kick": + return f"Ribbit! Frog kicked {opponent} with powerful hind legs and won!" + elif style == "punch": + return f"Ribbit! Frog punched {opponent} with tiny frog fists - surprisingly effective!" + elif style == "bite": + return f"Ribbit! Frog bit {opponent} and won! Sticky tongue victory!" + return f"Ribbit! Frog {style}ed {opponent} and won!" + @rcx.on_tool_call(fi_mongo_store.MONGO_STORE_TOOL.name) async def toolcall_mongo_store(toolcall: ckit_cloudtool.FCloudtoolCall, model_produced_args: Dict[str, Any]) -> str: return await fi_mongo_store.handle_mongo_store( diff --git a/flexus_simple_bots/version_common.py b/flexus_simple_bots/version_common.py index e4304632..b17b0e40 100644 --- a/flexus_simple_bots/version_common.py +++ b/flexus_simple_bots/version_common.py @@ -1 +1 @@ -SIMPLE_BOTS_COMMON_VERSION = "0.2.23" +SIMPLE_BOTS_COMMON_VERSION = "0.2.27"