- Introduced llm_timeout_secs in ProviderConfig and LLMProviderConfig to specify timeout for LLM requests. - Updated OpenAIProvider and AnthropicProvider to utilize the timeout setting when creating HTTP clients. - Enhanced error handling for API responses to include timeout information. - Modified SessionManager to support agent-specific provider configurations, allowing for more flexible agent management. - Added tests to verify the correct behavior of timeout settings and agent task validation.
170 lines
5.4 KiB
Markdown
170 lines
5.4 KiB
Markdown
PicoBot
|
|
|
|
Skills (initial implementation)
|
|
|
|
Agent profile injection
|
|
|
|
PicoBot maintains a persistent agent profile file at ~/.picobot/agent/AGENT.md.
|
|
|
|
Behavior:
|
|
- The directory ~/.picobot/agent is created automatically when needed.
|
|
- If AGENT.md does not exist yet, PicoBot creates it with a default profile.
|
|
- When the active conversation is empty or has just been reset, AGENT.md is loaded as the first system message in the active history.
|
|
- After every configured number of user turns, PicoBot injects the latest AGENT.md content again before the next user message is appended.
|
|
|
|
Config:
|
|
- Set gateway.agent_prompt_reinject_every in ~/.picobot/config.json.
|
|
- Default value is 100.
|
|
- Set it to 0 to disable periodic reinjection.
|
|
|
|
This profile is persisted in session history, while the skills index system prompt is still injected dynamically by AgentLoop.
|
|
|
|
PicoBot now supports filesystem skills.
|
|
|
|
Skill discovery locations:
|
|
- Project skills: .picobot/skills/*/SKILL.md
|
|
- User skills: ~/.picobot/skills/*/SKILL.md
|
|
|
|
Minimal required SKILL.md format:
|
|
|
|
---
|
|
description: Summarize code architecture for Rust projects
|
|
---
|
|
Optional detailed instructions go here.
|
|
|
|
Notes:
|
|
- The only required frontmatter field is description.
|
|
- If name is missing, the folder name is used as the skill name.
|
|
- Invalid skill files are skipped with warning logs.
|
|
|
|
How it is injected:
|
|
- AgentLoop adds a system message containing the available skills list (name + description).
|
|
- The model can call tool skill_activate with {"name":"<skill-name>"}.
|
|
- PicoBot returns the skill body as tool output so the model can follow detailed instructions.
|
|
|
|
Skill management tool
|
|
|
|
PicoBot exposes a built-in tool named skill_manage for runtime skill administration.
|
|
PicoBot also exposes a read-only tool named skill_list for listing discovered skills without mutation.
|
|
|
|
Supported actions:
|
|
- list: List discovered skills
|
|
- get: Read one skill by name
|
|
- create: Create a skill under project or user scope
|
|
- update: Update description and/or body for an existing skill
|
|
- delete: Delete a skill directory
|
|
- reload: Re-scan skill directories and refresh the in-memory catalog
|
|
|
|
Defaults:
|
|
- scope defaults to project
|
|
- reload defaults to true for create, update, and delete
|
|
|
|
Example payloads:
|
|
|
|
skill_list takes no parameters.
|
|
|
|
{"action":"list"}
|
|
{"action":"create","scope":"project","name":"demo-skill","description":"Use when summarizing a Rust crate","body":"Step 1..."}
|
|
{"action":"update","scope":"project","name":"demo-skill","description":"Use when reviewing a Rust crate"}
|
|
{"action":"delete","scope":"project","name":"demo-skill"}
|
|
{"action":"reload"}
|
|
|
|
Config (optional)
|
|
|
|
Add skills in config.json:
|
|
|
|
{
|
|
"skills": {
|
|
"enabled": true,
|
|
"sources": ["project", "user"],
|
|
"max_index_chars": 4000,
|
|
"max_listed_skills": 32
|
|
}
|
|
}
|
|
|
|
Scheduler
|
|
|
|
PicoBot now includes a DB-backed scheduler for heartbeat, delayed jobs, interval jobs, one-shot absolute-time jobs, and cron jobs.
|
|
|
|
Current behavior:
|
|
- Scheduler runs as a background loop inside gateway lifecycle.
|
|
- Job definitions and runtime state are persisted in SQLite instead of JSON files.
|
|
- Supported schedule types: delay, interval, at, cron.
|
|
- Supported job kinds: internal_event, outbound_message, agent_task.
|
|
- Built-in internal event: session_cleanup, used to clear expired in-memory channel sessions.
|
|
- Built-in management tool: scheduler_manage.
|
|
|
|
Config example:
|
|
|
|
{
|
|
"scheduler": {
|
|
"enabled": true,
|
|
"tick_resolution_ms": 1000,
|
|
"misfire_policy": "skip",
|
|
"jobs": [
|
|
{
|
|
"id": "session.cleanup",
|
|
"kind": "internal_event",
|
|
"schedule": {
|
|
"type": "interval",
|
|
"seconds": 300
|
|
},
|
|
"payload": {
|
|
"event": "session_cleanup"
|
|
}
|
|
},
|
|
{
|
|
"id": "agent.daily_summary",
|
|
"kind": "agent_task",
|
|
"schedule": {
|
|
"type": "cron",
|
|
"expression": "30 18 * * *"
|
|
},
|
|
"target": {
|
|
"channel": "feishu",
|
|
"chat_id": "oc_xxx"
|
|
},
|
|
"payload": {
|
|
"prompt": "请总结今天的项目进展,并列出明天的优先事项",
|
|
"agent": "default",
|
|
"fresh_session": true,
|
|
"system_prompt": "你是日报助手,输出时先给摘要,再给待办。",
|
|
"sender_id": "scheduler-daily-summary",
|
|
"metadata": {
|
|
"job_type": "daily_summary",
|
|
"source": "scheduler"
|
|
}
|
|
}
|
|
},
|
|
{
|
|
"id": "daily.reminder",
|
|
"kind": "outbound_message",
|
|
"schedule": {
|
|
"type": "cron",
|
|
"expression": "0 9 * * *"
|
|
},
|
|
"target": {
|
|
"channel": "feishu",
|
|
"chat_id": "oc_xxx"
|
|
},
|
|
"payload": {
|
|
"content": "每日提醒"
|
|
}
|
|
}
|
|
]
|
|
}
|
|
}
|
|
|
|
Runtime management:
|
|
- Use scheduler_manage with action=list|get|put|delete|pause|resume.
|
|
- Jobs created by the tool are written into SQLite and picked up by the scheduler loop.
|
|
- Config-defined jobs are also synced into SQLite on startup.
|
|
- agent_task reuses the normal agent pipeline: it creates a synthetic user turn from payload.prompt and runs tools, persistence, and outbound rendering through SessionManager.
|
|
- agent_task payload fields:
|
|
- prompt: required, synthetic user input.
|
|
- agent: optional, choose which configured agent definition to use. default or any configured agent name.
|
|
- fresh_session: optional, when true reset the active chat segment before running.
|
|
- system_prompt: optional, append a task-specific system message before the synthetic user turn.
|
|
- sender_id: optional, overrides the synthetic sender id used for tool context and memory scoping.
|
|
- metadata: optional, attached to outbound messages emitted by this task.
|