Refactor: Clean up obsolete files and organize codebase structure
This commit removes deprecated modules and reorganizes code into logical directories: Deleted files (superseded by newer systems): - claude_code_server.py (replaced by agent-sdk direct integration) - heartbeat.py (superseded by scheduled_tasks.py) - pulse_brain.py (unused in production) - config/pulse_brain_config.py (obsolete config) Created directory structure: - examples/ (7 example files: example_*.py, demo_*.py) - tests/ (5 test files: test_*.py) Updated imports: - agent.py: Removed heartbeat module and all enable_heartbeat logic - bot_runner.py: Removed heartbeat parameter from Agent initialization - llm_interface.py: Updated deprecated claude_code_server message Preserved essential files: - hooks.py (for future use) - adapters/skill_integration.py (for future use) - All Google integration tools (Gmail, Calendar, Contacts) - GLM provider code (backward compatibility) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
174
examples/example_bot_with_skills.py
Normal file
174
examples/example_bot_with_skills.py
Normal file
@@ -0,0 +1,174 @@
|
||||
"""
|
||||
Example: Bot runner with local skills support.
|
||||
|
||||
This demonstrates how to use local skills from .claude/skills/
|
||||
in your bot, allowing users to invoke them from Slack/Telegram.
|
||||
"""
|
||||
|
||||
import asyncio
|
||||
|
||||
from adapters.base import AdapterConfig, InboundMessage
|
||||
from adapters.runtime import AdapterRuntime
|
||||
from adapters.skill_integration import SkillInvoker
|
||||
from adapters.slack.adapter import SlackAdapter
|
||||
from adapters.telegram.adapter import TelegramAdapter
|
||||
from agent import Agent
|
||||
|
||||
|
||||
def create_skill_preprocessor(
|
||||
skill_invoker: SkillInvoker, agent: Agent
|
||||
) -> callable:
|
||||
"""
|
||||
Preprocessor that allows invoking skills via /skill-name syntax.
|
||||
|
||||
Example messages:
|
||||
"/adapter-dev create Discord adapter"
|
||||
"/help"
|
||||
"/status check health of all adapters"
|
||||
"""
|
||||
|
||||
def preprocessor(
|
||||
message: InboundMessage,
|
||||
) -> InboundMessage:
|
||||
text = message.text.strip()
|
||||
|
||||
if not text.startswith("/"):
|
||||
return message
|
||||
|
||||
parts = text.split(maxsplit=1)
|
||||
skill_name = parts[0][1:]
|
||||
args = parts[1] if len(parts) > 1 else ""
|
||||
|
||||
available_skills = skill_invoker.list_available_skills()
|
||||
|
||||
if skill_name in available_skills:
|
||||
print(
|
||||
f"[Skills] Invoking /{skill_name} "
|
||||
f"with args: {args}"
|
||||
)
|
||||
|
||||
skill_info = skill_invoker.get_skill_info(skill_name)
|
||||
|
||||
if skill_info:
|
||||
skill_body = skill_info.get("body", "")
|
||||
skill_context = skill_body.replace(
|
||||
"$ARGUMENTS", args,
|
||||
)
|
||||
|
||||
arg_parts = args.split() if args else []
|
||||
for i, arg in enumerate(arg_parts):
|
||||
skill_context = skill_context.replace(
|
||||
f"${i}", arg,
|
||||
)
|
||||
|
||||
message.text = skill_context
|
||||
message.metadata["skill_invoked"] = skill_name
|
||||
print(f"[Skills] Skill /{skill_name} loaded")
|
||||
else:
|
||||
message.text = (
|
||||
f"Error: Could not load skill '{skill_name}'"
|
||||
)
|
||||
|
||||
elif skill_name in ["help", "skills"]:
|
||||
skills_list = "\n".join(
|
||||
f" - /{s}" for s in available_skills
|
||||
)
|
||||
message.text = (
|
||||
f"Available skills:\n{skills_list}\n\n"
|
||||
f"Use /skill-name to invoke."
|
||||
)
|
||||
message.metadata["builtin_command"] = True
|
||||
|
||||
return message
|
||||
|
||||
return preprocessor
|
||||
|
||||
|
||||
def create_skill_postprocessor() -> callable:
|
||||
"""Postprocessor that adds skill metadata to responses."""
|
||||
|
||||
def postprocessor(
|
||||
response: str, original: InboundMessage,
|
||||
) -> str:
|
||||
if original.metadata.get("skill_invoked"):
|
||||
skill_name = original.metadata["skill_invoked"]
|
||||
response += f"\n\n_[Powered by /{skill_name}]_"
|
||||
return response
|
||||
|
||||
return postprocessor
|
||||
|
||||
|
||||
async def main() -> None:
|
||||
print("=" * 60)
|
||||
print("Ajarbot with Local Skills")
|
||||
print("=" * 60)
|
||||
|
||||
# 1. Create agent
|
||||
agent = Agent(
|
||||
provider="claude",
|
||||
workspace_dir="./memory_workspace",
|
||||
enable_heartbeat=False,
|
||||
)
|
||||
|
||||
# 2. Initialize skill system
|
||||
skill_invoker = SkillInvoker()
|
||||
|
||||
print("\n[Skills] Available local skills:")
|
||||
for skill in skill_invoker.list_available_skills():
|
||||
info = skill_invoker.get_skill_info(skill)
|
||||
desc = (
|
||||
info.get("description", "No description")
|
||||
if info
|
||||
else "Unknown"
|
||||
)
|
||||
print(f" - /{skill} - {desc}")
|
||||
|
||||
# 3. Create runtime with skill support
|
||||
runtime = AdapterRuntime(agent)
|
||||
|
||||
runtime.add_preprocessor(
|
||||
create_skill_preprocessor(skill_invoker, agent),
|
||||
)
|
||||
runtime.add_postprocessor(create_skill_postprocessor())
|
||||
|
||||
# 4. Add adapters
|
||||
slack_adapter = SlackAdapter(AdapterConfig(
|
||||
platform="slack",
|
||||
enabled=True,
|
||||
credentials={
|
||||
"bot_token": "xoxb-YOUR-TOKEN",
|
||||
"app_token": "xapp-YOUR-TOKEN",
|
||||
},
|
||||
))
|
||||
runtime.add_adapter(slack_adapter)
|
||||
|
||||
telegram_adapter = TelegramAdapter(AdapterConfig(
|
||||
platform="telegram",
|
||||
enabled=True,
|
||||
credentials={"bot_token": "YOUR-TELEGRAM-TOKEN"},
|
||||
))
|
||||
runtime.add_adapter(telegram_adapter)
|
||||
|
||||
print("\n[Setup] Bot configured with skill support")
|
||||
print("\nUsers can now invoke skills from Slack/Telegram:")
|
||||
print(" Example: '/adapter-dev create Discord adapter'")
|
||||
print(" Example: '/skills' (list available skills)")
|
||||
|
||||
# 5. Start runtime
|
||||
await runtime.start()
|
||||
|
||||
print("\n" + "=" * 60)
|
||||
print("Bot is running! Press Ctrl+C to stop.")
|
||||
print("=" * 60 + "\n")
|
||||
|
||||
try:
|
||||
while True:
|
||||
await asyncio.sleep(1)
|
||||
except KeyboardInterrupt:
|
||||
print("\n[Shutdown] Stopping...")
|
||||
finally:
|
||||
await runtime.stop()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
Reference in New Issue
Block a user