feature/web-search-and-cron-improvements #2

Merged
tanyar09 merged 12 commits from feature/web-search-and-cron-improvements into feature/cleanup-providers-llama-only 2026-03-06 13:20:19 -05:00
10 changed files with 422 additions and 0 deletions
Showing only changes of commit 7db96541a6 - Show all commits

View File

@ -101,6 +101,15 @@ Your workspace is at: {workspace_path}
- History log: {workspace_path}/memory/HISTORY.md (grep-searchable)
- Custom skills: {workspace_path}/skills/{{skill-name}}/SKILL.md
## Gitea API (This Repository)
**CRITICAL**: This repository uses Gitea at `http://10.0.30.169:3000/api/v1`, NOT GitHub.
- Repository: `ilia/nanobot`
- Token: `$NANOBOT_GITLE_TOKEN`
- **NEVER use placeholder URLs like `gitea.example.com`**
- **ALWAYS use `http://` (NOT `https://`)** - Gitea runs on HTTP, using HTTPS causes SSL errors
- Always detect from `git remote get-url origin` or use `http://10.0.30.169:3000/api/v1`
- Example: `curl -H "Authorization: token $NANOBOT_GITLE_TOKEN" "http://10.0.30.169:3000/api/v1/repos/ilia/nanobot/pulls"`
IMPORTANT: When responding to direct questions or conversations, reply directly with your text response.
Only use the 'message' tool when the user explicitly asks you to send a message to someone else or to a different channel.
For normal conversation, acknowledgments (Thanks, OK, etc.), or when the user is talking to YOU, just respond with text - do NOT call the message tool.

View File

@ -74,6 +74,10 @@ For data analysis tasks (Excel, CSV, JSON files), use Python with pandas:
async def execute(self, command: str, working_dir: str | None = None, **kwargs: Any) -> str:
cwd = working_dir or self.working_dir or os.getcwd()
# Sanitize Gitea API URLs: convert HTTPS to HTTP for 10.0.30.169:3000
command = self._sanitize_gitea_urls(command)
guard_error = self._guard_command(command, cwd)
if guard_error:
return guard_error
@ -83,11 +87,14 @@ For data analysis tasks (Excel, CSV, JSON files), use Python with pandas:
logger.debug(f"ExecTool: command={command[:200]}, cwd={cwd}, working_dir={working_dir}")
try:
# Ensure environment variables are available (including from .env file)
env = os.environ.copy()
process = await asyncio.create_subprocess_shell(
command,
stdout=asyncio.subprocess.PIPE,
stderr=asyncio.subprocess.PIPE,
cwd=cwd,
env=env,
)
try:
@ -200,3 +207,33 @@ For data analysis tasks (Excel, CSV, JSON files), use Python with pandas:
return "Error: Command blocked by safety guard (path outside working dir)"
return None
def _sanitize_gitea_urls(self, command: str) -> str:
"""
Sanitize Gitea API URLs in curl commands: convert HTTPS to HTTP.
Gitea API at 10.0.30.169:3000 runs on HTTP, not HTTPS.
This prevents SSL/TLS errors when the agent generates HTTPS URLs.
"""
# Pattern to match https://10.0.30.169:3000/api/... in curl commands
# This handles various curl formats:
# - curl "https://10.0.30.169:3000/api/..."
# - curl -X GET https://10.0.30.169:3000/api/...
# - curl -H "..." "https://10.0.30.169:3000/api/..."
# Matches URLs with or without quotes, and captures the full path
pattern = r'https://10\.0\.30\.169:3000(/api/[^\s"\']*)'
def replace_url(match):
path = match.group(1)
return f'http://10.0.30.169:3000{path}'
sanitized = re.sub(pattern, replace_url, command)
# Log if we made a change
if sanitized != command:
from loguru import logger
logger.info(f"ExecTool: Sanitized Gitea API URL (HTTPS -> HTTP)")
logger.debug(f"Original: {command[:200]}...")
logger.debug(f"Sanitized: {sanitized[:200]}...")
return sanitized

View File

@ -517,6 +517,7 @@ def agent(
from nanobot.cron.service import CronService
from loguru import logger
# Load config (this also loads .env file into environment)
config = load_config()
bus = MessageBus()

View File

@ -1,6 +1,7 @@
"""Configuration loading utilities."""
import json
import os
from pathlib import Path
from nanobot.config.schema import Config
@ -17,6 +18,43 @@ def get_data_dir() -> Path:
return get_data_path()
def _load_env_file(workspace: Path | None = None) -> None:
"""Load .env file from workspace directory if it exists."""
if workspace:
env_file = Path(workspace) / ".env"
else:
# Try current directory and workspace
env_file = Path(".env")
if not env_file.exists():
# Try workspace directory
try:
from nanobot.utils.helpers import get_workspace_path
workspace_path = get_workspace_path()
env_file = workspace_path / ".env"
except:
pass
if env_file.exists():
try:
with open(env_file) as f:
for line in f:
line = line.strip()
# Skip comments and empty lines
if not line or line.startswith("#"):
continue
# Parse KEY=VALUE format
if "=" in line:
key, value = line.split("=", 1)
key = key.strip()
value = value.strip().strip('"').strip("'")
# Only set if not already in environment
if key and key not in os.environ:
os.environ[key] = value
except Exception:
# Silently fail if .env can't be loaded
pass
def load_config(config_path: Path | None = None) -> Config:
"""
Load configuration from file or create default.
@ -27,6 +65,15 @@ def load_config(config_path: Path | None = None) -> Config:
Returns:
Loaded configuration object.
"""
# Load .env file before loading config (so env vars are available to pydantic)
try:
from nanobot.utils.helpers import get_workspace_path
workspace = get_workspace_path()
_load_env_file(workspace)
except:
# Fallback to current directory
_load_env_file()
path = config_path or get_config_path()
if path.exists():

View File

@ -0,0 +1,52 @@
---
name: gitea
description: "Interact with Gitea API using curl. This repository uses Gitea (NOT GitHub) at http://10.0.30.169:3000/api/v1. ALWAYS use HTTP (not HTTPS)."
metadata: {"nanobot":{"emoji":"🔧","requires":{"env":["NANOBOT_GITLE_TOKEN"]}}}
---
# Gitea Skill
**CRITICAL**: This repository uses Gitea at `http://10.0.30.169:3000/api/v1`, NOT GitHub.
## Important Rules
1. **ALWAYS use `http://` (NOT `https://`)** - Gitea runs on HTTP port 3000
2. **ALWAYS include Authorization header** with `$NANOBOT_GITLE_TOKEN`
3. **Repository**: `ilia/nanobot`
4. **API Base**: `http://10.0.30.169:3000/api/v1`
## Pull Requests
List all pull requests:
```bash
curl -H "Authorization: token $NANOBOT_GITLE_TOKEN" \
"http://10.0.30.169:3000/api/v1/repos/ilia/nanobot/pulls"
```
List open pull requests:
```bash
curl -H "Authorization: token $NANOBOT_GITLE_TOKEN" \
"http://10.0.30.169:3000/api/v1/repos/ilia/nanobot/pulls?state=open"
```
## Issues
List open issues:
```bash
curl -H "Authorization: token $NANOBOT_GITLE_TOKEN" \
"http://10.0.30.169:3000/api/v1/repos/ilia/nanobot/issues?state=open"
```
## Helper Script
You can also use the helper script:
```bash
./workspace/gitea_api.sh prs
./workspace/gitea_api.sh issues open
```
## Common Mistakes to Avoid
**WRONG**: `curl https://10.0.30.169:3000/api/...` (SSL error)
**WRONG**: `curl http://gitea.example.com/api/...` (placeholder URL)
**CORRECT**: `curl -H "Authorization: token $NANOBOT_GITLE_TOKEN" "http://10.0.30.169:3000/api/v1/repos/ilia/nanobot/pulls"`

View File

@ -2,6 +2,34 @@
You are a helpful AI assistant. Be concise, accurate, and friendly.
## 🚨 CRITICAL: Gitea API Requests
**When user asks to list PRs, issues, or use Gitea API:**
**MANDATORY COMMAND FORMAT:**
```bash
curl -H "Authorization: token $NANOBOT_GITLE_TOKEN" "http://10.0.30.169:3000/api/v1/repos/ilia/nanobot/pulls"
```
**CRITICAL RULES:**
1. **DO NOT use web_search** - execute the curl command directly
2. **MUST use `http://` (NOT `https://`)** - Gitea runs on HTTP port 3000
3. **MUST include Authorization header** with `$NANOBOT_GITLE_TOKEN`
4. **Copy the exact command above** - do not modify the protocol to HTTPS
**WRONG (will fail):**
- `curl -X GET https://10.0.30.169:3000/api/...` ❌ (SSL error)
- `curl https://10.0.30.169:3000/api/...` ❌ (SSL error)
**CORRECT:**
- `curl -H "Authorization: token $NANOBOT_GITLE_TOKEN" "http://10.0.30.169:3000/api/v1/repos/ilia/nanobot/pulls"`
**OR use the helper script (recommended - avoids HTTPS mistakes):**
```bash
./workspace/gitea_api.sh prs
./workspace/gitea_api.sh issues open
```
## Guidelines
- Always explain what you're doing before taking actions
@ -88,3 +116,114 @@ Task format examples:
```
When the user asks you to add a recurring/periodic task, update `HEARTBEAT.md` instead of creating a one-time reminder. Keep the file small to minimize token usage.
## ⚠️ CRITICAL: Gitea API Access
**THIS REPOSITORY USES GITEA, NOT GITHUB. NEVER USE PLACEHOLDER URLS.**
When user asks about pull requests, issues, or Gitea API:
1. **ALWAYS detect the real Gitea URL from git remote first**
2. **NEVER use placeholder URLs like `gitea.example.com` or `https://gitea.example.com`**
3. **The correct Gitea API base is: `http://10.0.30.169:3000/api/v1`**
To access Gitea API:
1. **Detect Gitea URL from git remote:**
```bash
git remote get-url origin
# Returns: gitea@10.0.30.169:ilia/nanobot.git
# Extract host: 10.0.30.169
# API base: http://10.0.30.169:3000/api/v1
# Repo: ilia/nanobot
```
2. **Use the token from environment:**
```bash
TOKEN=$NANOBOT_GITLE_TOKEN
curl -H "Authorization: token $TOKEN" \
"http://10.0.30.169:3000/api/v1/repos/ilia/nanobot/pulls"
```
3. **Or use the helper script:**
```bash
source workspace/get_gitea_info.sh
curl -H "Authorization: token $NANOBOT_GITLE_TOKEN" \
"${GITEA_API_BASE}/repos/${GITEA_REPO}/pulls"
```
**Important:** Never use placeholder URLs like `gitea.example.com`. Always detect from git remote or use the actual host `10.0.30.169:3000`.
## 🚨 GITEA URL DETECTION (MANDATORY)
**BEFORE making any Gitea API call, you MUST:**
1. Run: `git remote get-url origin`
- This returns: `gitea@10.0.30.169:ilia/nanobot.git`
2. Extract the host: `10.0.30.169`
- Command: `git remote get-url origin | sed 's/.*@\([^:]*\).*/\1/'`
3. Extract the repo: `ilia/nanobot`
- Command: `git remote get-url origin | sed 's/.*:\(.*\)\.git/\1/'`
4. Construct API URL: `http://10.0.30.169:3000/api/v1/repos/ilia/nanobot/...`
**Example correct command (MUST use $NANOBOT_GITLE_TOKEN variable):**
```bash
curl -H "Authorization: token $NANOBOT_GITLE_TOKEN" \
"http://10.0.30.169:3000/api/v1/repos/ilia/nanobot/pulls"
```
**CRITICAL**: Always use `$NANOBOT_GITLE_TOKEN` in the curl command. The token is automatically loaded from `.env` file into the environment when nanobot starts. Do NOT hardcode the token value.
**WRONG (never use):**
- `https://gitea.example.com/api/...`
- `https://gitea.example.com/ap...`
- Any placeholder URL ❌
## Gitea API Token Usage
**MANDATORY**: When making Gitea API calls, you **MUST** include the Authorization header with the token:
```bash
# ✅ CORRECT - includes Authorization header with token
curl -H "Authorization: token $NANOBOT_GITLE_TOKEN" \
"http://10.0.30.169:3000/api/v1/repos/ilia/nanobot/pulls"
# ❌ WRONG - missing Authorization header (will get 401 error)
curl -X GET "http://10.0.30.169:3000/api/v1/repos/ilia/nanobot/pulls"
# ❌ WRONG - missing token in header
curl "http://10.0.30.169:3000/api/v1/repos/ilia/nanobot/pulls"
```
**CRITICAL RULES:**
1. **ALWAYS** include `-H "Authorization: token $NANOBOT_GITLE_TOKEN"` in curl commands
2. **ALWAYS use `http://` (NOT `https://`)** - Gitea runs on HTTP, not HTTPS
3. The token is automatically loaded from `.env` file when nanobot starts
4. The `$NANOBOT_GITLE_TOKEN` environment variable is available in all exec commands
5. Without the Authorization header, you will get a 401 Unauthorized error
6. Using `https://` will cause SSL/TLS errors - always use `http://10.0.30.169:3000`
## Direct Gitea API Execution
When user asks to "list PRs" or "show issues" using Gitea API:
**DO THIS:**
1. Run the curl command directly (no web_search needed)
2. Use the exact command format below
3. Parse and display the results
**Example - List PRs:**
```bash
curl -H "Authorization: token $NANOBOT_GITLE_TOKEN" \
"http://10.0.30.169:3000/api/v1/repos/ilia/nanobot/pulls" | \
python3 -m json.tool
```
**DO NOT:**
- Use web_search to find API documentation
- Search for "how to use Gitea API"
- Ask for clarification - just execute the command
You already have all the information you need in this file. Just execute the curl command.

46
workspace/GITEA_API.md Normal file
View File

@ -0,0 +1,46 @@
# Gitea API Quick Reference
**CRITICAL: This repository uses Gitea, NOT GitHub. Never use placeholder URLs.**
## Correct Gitea API Information
- **API Base URL**: `http://10.0.30.169:3000/api/v1`
- **Repository**: `ilia/nanobot`
- **Token**: Available in `$NANOBOT_GITLE_TOKEN` environment variable
## How to Detect (if needed)
```bash
# Get git remote
REMOTE=$(git remote get-url origin)
# Returns: gitea@10.0.30.169:ilia/nanobot.git
# Extract host (remove gitea@ and :repo.git)
HOST=$(echo "$REMOTE" | sed 's/.*@\([^:]*\).*/\1/')
# Returns: 10.0.30.169
# Extract repo path
REPO=$(echo "$REMOTE" | sed 's/.*:\(.*\)\.git/\1/')
# Returns: ilia/nanobot
# API base (Gitea runs on port 3000)
API_BASE="http://${HOST}:3000/api/v1"
```
## Example API Calls
```bash
# List pull requests
curl -H "Authorization: token $NANOBOT_GITLE_TOKEN" \
"http://10.0.30.169:3000/api/v1/repos/ilia/nanobot/pulls"
# List open issues
curl -H "Authorization: token $NANOBOT_GITLE_TOKEN" \
"http://10.0.30.169:3000/api/v1/repos/ilia/nanobot/issues?state=open"
# Get repository info
curl -H "Authorization: token $NANOBOT_GITLE_TOKEN" \
"http://10.0.30.169:3000/api/v1/repos/ilia/nanobot"
```
**DO NOT USE**: `gitea.example.com` or any placeholder URLs. Always use `10.0.30.169:3000`.

38
workspace/GITEA_INFO.md Normal file
View File

@ -0,0 +1,38 @@
# Gitea Configuration
## API Information
- **Gitea API Base URL**: `http://10.0.30.169:3000/api/v1`
- **Repository**: `ilia/nanobot`
- **Token Environment Variable**: `NANOBOT_GITLE_TOKEN`
## How to Use
When making Gitea API calls, use:
```bash
# Get token from environment
TOKEN=$NANOBOT_GITLE_TOKEN
# List open issues
curl -H "Authorization: token $TOKEN" \
"http://10.0.30.169:3000/api/v1/repos/ilia/nanobot/issues?state=open"
# List pull requests
curl -H "Authorization: token $TOKEN" \
"http://10.0.30.169:3000/api/v1/repos/ilia/nanobot/pulls"
# Get repository info
curl -H "Authorization: token $TOKEN" \
"http://10.0.30.169:3000/api/v1/repos/ilia/nanobot"
```
## Detecting Repository Info
You can detect the repository from git remote:
```bash
# Get repo path (owner/repo)
git remote get-url origin | sed 's/.*:\(.*\)\.git/\1/'
# Gitea host is: 10.0.30.169:3000
# API base: http://10.0.30.169:3000/api/v1

25
workspace/get_gitea_info.sh Executable file
View File

@ -0,0 +1,25 @@
#!/bin/bash
# Helper script to get Gitea API information from git remote
REMOTE=$(git remote get-url origin 2>/dev/null)
if [ -z "$REMOTE" ]; then
echo "Error: No git remote found"
exit 1
fi
# Extract host (assuming format: gitea@HOST:repo.git or ssh://gitea@HOST/repo.git)
if [[ $REMOTE == *"@"* ]]; then
HOST=$(echo "$REMOTE" | sed 's/.*@\([^:]*\).*/\1/')
else
HOST=$(echo "$REMOTE" | sed 's|.*://\([^/]*\).*|\1|')
fi
# Extract repo path (owner/repo)
REPO=$(echo "$REMOTE" | sed 's/.*:\(.*\)\.git/\1/' | sed 's|.*/\(.*/.*\)|\1|')
# Gitea typically runs on port 3000
API_BASE="http://${HOST}:3000/api/v1"
echo "GITEA_HOST=${HOST}"
echo "GITEA_REPO=${REPO}"
echo "GITEA_API_BASE=${API_BASE}"

28
workspace/gitea_api.sh Executable file
View File

@ -0,0 +1,28 @@
#!/bin/bash
# Gitea API helper script - ALWAYS uses HTTP (not HTTPS)
API_BASE="http://10.0.30.169:3000/api/v1"
REPO="ilia/nanobot"
TOKEN="${NANOBOT_GITLE_TOKEN}"
if [ -z "$TOKEN" ]; then
echo "Error: NANOBOT_GITLE_TOKEN not set"
exit 1
fi
case "$1" in
prs|pulls)
curl -s -H "Authorization: token $TOKEN" \
"${API_BASE}/repos/${REPO}/pulls"
;;
issues)
curl -s -H "Authorization: token $TOKEN" \
"${API_BASE}/repos/${REPO}/issues?state=${2:-open}"
;;
*)
echo "Usage: $0 {prs|pulls|issues} [state]"
echo "Example: $0 prs"
echo "Example: $0 issues open"
exit 1
;;
esac