docs: fix inaccuracies and add missing translations

Fixes cross-checked against v0.2.3 codebase:
- MaixCam: server_address → host + port (config.go MaixCamConfig)
- IRC: use_tls → tls, channels_to_join → channels (all languages)
- WeCom AI Bot: port 18791 → 18790 (shared gateway, all languages)
- credential_encryption: base_url → api_base, remove passphrase-only mode (not supported by code)
- migration guide: agents.defaults.model → model_name in "After" example
- troubleshooting: agents.defaults.model → model_name (all languages)
- spawn-tasks: fix truncated file, add Heartbeat introduction
- tools_configuration: add Tavily/SearXNG/GLMSearch, exec allow_remote/timeout_seconds, cron allow_command, skills github/cache
- ANTIGRAVITY_AUTH: fix file path cmd_auth.go → internal/auth/helpers.go, Go >= 1.25
- Matrix links: fix docs/ prefix in relative paths (fr/pt-br/vi)
- configuration: HEARTBEAT.md marked as auto-generated
- README family: add Hardware Compatibility entry to ja/fr/pt-br/vi

New translations (5 languages × 5 docs = 25 files):
- debug.md, credential_encryption.md, hardware-compatibility.md
- ANTIGRAVITY_AUTH.md, ANTIGRAVITY_USAGE.md
This commit is contained in:
BeaconCat 2026-03-20 14:54:00 +08:00
parent 71134babb9
commit 8c6f2376ad
55 changed files with 7312 additions and 97 deletions

View file

@ -105,6 +105,8 @@ _*Les versions récentes peuvent utiliser 1020 Mo en raison des fusions rapid
<img src="assets/compare.jpg" alt="PicoClaw" width="512">
> 📋 **[Liste de Compatibilité Matérielle](docs/hardware-compatibility.md)** — Voir toutes les cartes testées, du RISC-V à $5 au Raspberry Pi en passant par les téléphones Android. Votre carte n'est pas listée ? Soumettez une PR !
## 🦾 Démonstration
### 🛠️ Flux de Travail Standard de l'Assistant
@ -200,6 +202,7 @@ Pour des guides détaillés, consultez la documentation ci-dessous. Ce README ne
| 🔄 [Spawn & Tâches Asynchrones](docs/fr/spawn-tasks.md) | Tâches rapides, tâches longues avec spawn, orchestration asynchrone de sous-agents |
| 🐛 [Dépannage](docs/fr/troubleshooting.md) | Problèmes courants et solutions |
| 🔧 [Configuration des Outils](docs/fr/tools_configuration.md) | Activation/désactivation par outil, politiques exec |
| 📋 [Compatibilité Matérielle](docs/hardware-compatibility.md) | Cartes testées, exigences minimales, comment ajouter votre carte |
## <img src="assets/clawdchat-icon.png" width="24" height="24" alt="ClawdChat"> Rejoignez le Réseau Social d'Agents

View file

@ -105,6 +105,8 @@ _*最近のバージョンでは急速な機能マージにより 10〜20MB に
<img src="assets/compare.jpg" alt="PicoClaw" width="512">
> 📋 **[ハードウェア互換性リスト](docs/hardware-compatibility.md)** — テスト済みの全ボード一覧($5 RISC-V から Raspberry Pi、Android スマートフォンまで。お使いのボードが未掲載PR を送ってください!
## 🦾 デモンストレーション
### 🛠️ スタンダードアシスタントワークフロー
@ -200,6 +202,7 @@ make install
| 🔄 [Spawn & 非同期タスク](docs/ja/spawn-tasks.md) | クイックタスク、spawn による長時間タスク、非同期サブエージェントオーケストレーション |
| 🐛 [トラブルシューティング](docs/ja/troubleshooting.md) | よくある問題と解決策 |
| 🔧 [ツール設定](docs/ja/tools_configuration.md) | ツールごとの有効/無効、exec ポリシー |
| 📋 [ハードウェア互換性](docs/hardware-compatibility.md) | テスト済みボード、最小要件、ボードの追加方法 |
## <img src="assets/clawdchat-icon.png" width="24" height="24" alt="ClawdChat"> エージェントソーシャルネットワークに参加

794
README.md
View file

@ -105,6 +105,8 @@ _*Recent versions may use 1020MB due to rapid feature merges. Resource optimi
<img src="assets/compare.jpg" alt="PicoClaw" width="512">
> 📋 **[Hardware Compatibility List](docs/hardware-compatibility.md)** — See all tested boards, from $5 RISC-V to Raspberry Pi to Android phones. Your board not listed? Submit a PR!
## 🦾 Demonstration
### 🛠️ Standard Assistant Workflows
@ -741,4 +743,796 @@ User Groups:
discord: <https://discord.gg/V4sAZ9XWpN>
<img src="assets/wechat.png" alt="PicoClaw" width="512"> center">
<img src="assets/logo.webp" alt="PicoClaw" width="512">
<h1>PicoClaw: Ultra-Efficient AI Assistant in Go</h1>
<h3>$10 Hardware · <10MB RAM · <1s Boot · 皮皮虾我们走</h3>
<p>
<img src="https://img.shields.io/badge/Go-1.25+-00ADD8?style=flat&logo=go&logoColor=white" alt="Go">
<img src="https://img.shields.io/badge/Arch-x86__64%2C%20ARM64%2C%20MIPS%2C%20RISC--V%2C%20LoongArch-blue" alt="Hardware">
<img src="https://img.shields.io/badge/license-MIT-green" alt="License">
<br>
<a href="https://picoclaw.io"><img src="https://img.shields.io/badge/Website-picoclaw.io-blue?style=flat&logo=google-chrome&logoColor=white" alt="Website"></a>
<a href="https://docs.picoclaw.io/"><img src="https://img.shields.io/badge/Docs-Official-007acc?style=flat&logo=read-the-docs&logoColor=white" alt="Docs"></a>
<a href="https://deepwiki.com/sipeed/picoclaw"><img src="https://img.shields.io/badge/Wiki-DeepWiki-FFA500?style=flat&logo=wikipedia&logoColor=white" alt="Wiki"></a>
<br>
<a href="https://x.com/SipeedIO"><img src="https://img.shields.io/badge/X_(Twitter)-SipeedIO-black?style=flat&logo=x&logoColor=white" alt="Twitter"></a>
<a href="./assets/wechat.png"><img src="https://img.shields.io/badge/WeChat-Group-41d56b?style=flat&logo=wechat&logoColor=white"></a>
<a href="https://discord.gg/V4sAZ9XWpN"><img src="https://img.shields.io/badge/Discord-Community-4c60eb?style=flat&logo=discord&logoColor=white" alt="Discord"></a>
</p>
[中文](README.zh.md) | [日本語](README.ja.md) | [Português](README.pt-br.md) | [Tiếng Việt](README.vi.md) | [Français](README.fr.md) | [Italiano](README.it.md) | [Bahasa Indonesia](README.id.md) | **English**
</div>
---
> **PicoClaw** is an independent open-source project initiated by [Sipeed](https://sipeed.com). It is written entirely in **Go** — not a fork of OpenClaw, NanoBot, or any other project.
🦐 PicoClaw is an ultra-lightweight personal AI Assistant inspired by [NanoBot](https://github.com/HKUDS/nanobot), refactored from the ground up in Go through a self-bootstrapping process, where the AI agent itself drove the entire architectural migration and code optimization.
⚡️ Runs on $10 hardware with <10MB RAM: That's 99% less memory than OpenClaw and 98% cheaper than a Mac mini!
<table align="center">
<tr align="center">
<td align="center" valign="top">
<p align="center">
<img src="assets/picoclaw_mem.gif" width="360" height="240">
</p>
</td>
<td align="center" valign="top">
<p align="center">
<img src="assets/licheervnano.png" width="400" height="240">
</p>
</td>
</tr>
</table>
> [!CAUTION]
> **🚨 SECURITY & OFFICIAL CHANNELS / 安全声明**
>
> * **NO CRYPTO:** PicoClaw has **NO** official token/coin. All claims on `pump.fun` or other trading platforms are **SCAMS**.
>
> * **OFFICIAL DOMAIN:** The **ONLY** official website is **[picoclaw.io](https://picoclaw.io)**, and company website is **[sipeed.com](https://sipeed.com)**
> * **Warning:** Many `.ai/.org/.com/.net/...` domains are registered by third parties.
> * **Warning:** picoclaw is in early development now and may have unresolved network security issues. Do not deploy to production environments before the v1.0 release.
> * **Note:** picoclaw has recently merged a lot of PRs, which may result in a larger memory footprint (1020MB) in the latest versions. We plan to prioritize resource optimization as soon as the current feature set reaches a stable state.
## 📢 News
2026-03-17 🚀 **v0.2.3 Released!** System tray UI (Windows & Linux), sub-agent status tracking (`spawn_status`), experimental gateway hot-reload, cron security gates, and 2 security fixes. PicoClaw now at **25K ⭐**!
2026-03-09 🎉 **v0.2.1 — Biggest update yet!** MCP protocol support, 4 new channels (Matrix/IRC/WeCom/Discord Proxy), 3 new providers (Kimi/Minimax/Avian), vision pipeline, JSONL memory store, and model routing.
2026-02-28 📦 **v0.2.0** released with Docker Compose support and Web UI launcher.
2026-02-26 🎉 PicoClaw hit **20K stars** in just 17 days! Channel auto-orchestration and capability interfaces landed.
<details>
<summary>Older news...</summary>
2026-02-16 🎉 PicoClaw hit 12K stars in one week! Community maintainer roles and [roadmap](ROADMAP.md) officially posted.
2026-02-13 🎉 PicoClaw hit 5000 stars in 4 days! Project Roadmap and Developer Group setup underway.
2026-02-09 🎉 **PicoClaw Launched!** Built in 1 day to bring AI Agents to $10 hardware with <10MB RAM. 🦐 PicoClawLet's Go
</details>
## ✨ Features
🪶 **Ultra-Lightweight**: <10MB Memory footprint 99% smaller than OpenClaw core functionality.*
💰 **Minimal Cost**: Efficient enough to run on $10 Hardware — 98% cheaper than a Mac mini.
⚡️ **Lightning Fast**: 400X Faster startup time, boot in <1 second even on 0.6GHz single core.
🌍 **True Portability**: Single self-contained binary across RISC-V, ARM, MIPS, and x86, One-click to Go!
🤖 **AI-Bootstrapped**: Autonomous Go-native implementation — 95% Agent-generated core with human-in-the-loop refinement.
🔌 **MCP Support**: Native [Model Context Protocol](https://modelcontextprotocol.io/) integration — connect any MCP server to extend agent capabilities.
👁️ **Vision Pipeline**: Send images and files directly to the agent — automatic base64 encoding for multimodal LLMs.
🧠 **Smart Routing**: Rule-based model routing — simple queries go to lightweight models, saving API costs.
_*Recent versions may use 1020MB due to rapid feature merges. Resource optimization is planned. Startup comparison based on 0.8GHz single-core benchmarks (see table below)._
| | OpenClaw | NanoBot | **PicoClaw** |
| ----------------------------- | ------------- | ------------------------ | ----------------------------------------- |
| **Language** | TypeScript | Python | **Go** |
| **RAM** | >1GB | >100MB | **< 10MB*** |
| **Startup**</br>(0.8GHz core) | >500s | >30s | **<1s** |
| **Cost** | Mac Mini $599 | Most Linux SBC </br>~$50 | **Any Linux Board**</br>**As low as $10** |
<img src="assets/compare.jpg" alt="PicoClaw" width="512">
> 📋 **[Hardware Compatibility List](docs/hardware-compatibility.md)** — See all tested boards, from $5 RISC-V to Raspberry Pi to Android phones. Your board not listed? Submit a PR!
## 🦾 Demonstration
### 🛠️ Standard Assistant Workflows
<table align="center">
<tr align="center">
<th><p align="center">🧩 Full-Stack Engineer</p></th>
<th><p align="center">🗂️ Logging & Planning Management</p></th>
<th><p align="center">🔎 Web Search & Learning</p></th>
</tr>
<tr>
<td align="center"><p align="center"><img src="assets/picoclaw_code.gif" width="240" height="180"></p></td>
<td align="center"><p align="center"><img src="assets/picoclaw_memory.gif" width="240" height="180"></p></td>
<td align="center"><p align="center"><img src="assets/picoclaw_search.gif" width="240" height="180"></p></td>
</tr>
<tr>
<td align="center">Develop • Deploy • Scale</td>
<td align="center">Schedule • Automate • Memory</td>
<td align="center">Discovery • Insights • Trends</td>
</tr>
</table>
### 📱 Run on old Android Phones
Give your decade-old phone a second life! Turn it into a smart AI Assistant with PicoClaw. Quick Start:
1. **Install [Termux](https://github.com/termux/termux-app)** (Download from [GitHub Releases](https://github.com/termux/termux-app/releases), or search in F-Droid / Google Play).
2. **Execute cmds**
```bash
# Download the latest release from https://github.com/sipeed/picoclaw/releases
wget https://github.com/sipeed/picoclaw/releases/latest/download/picoclaw_Linux_arm64.tar.gz
tar xzf picoclaw_Linux_arm64.tar.gz
pkg install proot
termux-chroot ./picoclaw onboard
```
And then follow the instructions in the "Quick Start" section to complete the configuration!
<img src="assets/termux.jpg" alt="PicoClaw" width="512">
### 🐜 Innovative Low-Footprint Deploy
PicoClaw can be deployed on almost any Linux device!
- $9.9 [LicheeRV-Nano](https://www.aliexpress.com/item/1005006519668532.html) E(Ethernet) or W(WiFi6) version, for Minimal Home Assistant
- $30~50 [NanoKVM](https://www.aliexpress.com/item/1005007369816019.html), or $100 [NanoKVM-Pro](https://www.aliexpress.com/item/1005010048471263.html) for Automated Server Maintenance
- $50 [MaixCAM](https://www.aliexpress.com/item/1005008053333693.html) or $100 [MaixCAM2](https://www.kickstarter.com/projects/zepan/maixcam2-build-your-next-gen-4k-ai-camera) for Smart Monitoring
<https://private-user-images.githubusercontent.com/83055338/547056448-e7b031ff-d6f5-4468-bcca-5726b6fecb5c.mp4>
🌟 More Deployment Cases Await
## 📦 Install
### Install with precompiled binary
Download the binary for your platform from the [Releases](https://github.com/sipeed/picoclaw/releases) page.
### Install from source (latest features, recommended for development)
```bash
git clone https://github.com/sipeed/picoclaw.git
cd picoclaw
make deps
# Build, no need to install
make build
# Build for multiple platforms
make build-all
# Build for Raspberry Pi Zero 2 W (32-bit: make build-linux-arm; 64-bit: make build-linux-arm64)
make build-pi-zero
# Build And Install
make install
```
**Raspberry Pi Zero 2 W:** Use the binary that matches your OS: 32-bit Raspberry Pi OS → `make build-linux-arm`; 64-bit → `make build-linux-arm64`. Or run `make build-pi-zero` to build both.
## 📚 Documentation
For detailed guides, see the docs below. The README covers quick start only.
```bash
# 1. Clone this repo
git clone https://github.com/sipeed/picoclaw.git
cd picoclaw
# 2. First run — auto-generates docker/data/config.json then exits
docker compose -f docker/docker-compose.yml --profile gateway up
# The container prints "First-run setup complete." and stops.
# 3. Set your API keys
vim docker/data/config.json # Set provider API keys, bot tokens, etc.
# 4. Start
docker compose -f docker/docker-compose.yml --profile gateway up -d
```
> [!TIP]
> **Docker Users**: By default, the Gateway listens on `127.0.0.1` which is not accessible from the host. If you need to access the health endpoints or expose ports, set `PICOCLAW_GATEWAY_HOST=0.0.0.0` in your environment or update `config.json`.
```bash
# 5. Check logs
docker compose -f docker/docker-compose.yml logs -f picoclaw-gateway
# 6. Stop
docker compose -f docker/docker-compose.yml --profile gateway down
```
### Launcher Mode (Web Console)
The `launcher` image includes all three binaries (`picoclaw`, `picoclaw-launcher`, `picoclaw-launcher-tui`) and starts the web console by default, which provides a browser-based UI for configuration and chat.
```bash
docker compose -f docker/docker-compose.yml --profile launcher up -d
```
Open http://localhost:18800 in your browser. The launcher manages the gateway process automatically.
> [!WARNING]
> The web console does not yet support authentication. Avoid exposing it to the public internet.
### Agent Mode (One-shot)
```bash
# Ask a question
docker compose -f docker/docker-compose.yml run --rm picoclaw-agent -m "What is 2+2?"
# Interactive mode
docker compose -f docker/docker-compose.yml run --rm picoclaw-agent
```
### Update
```bash
docker compose -f docker/docker-compose.yml pull
docker compose -f docker/docker-compose.yml --profile gateway up -d
```
### 🚀 Quick Start
> [!TIP]
> Set your API Key in `~/.picoclaw/config.json`. Get API Keys: [Volcengine (CodingPlan)](https://console.volcengine.com) (LLM) · [OpenRouter](https://openrouter.ai/keys) (LLM) · [Zhipu](https://open.bigmodel.cn/usercenter/proj-mgmt/apikeys) (LLM). Web search is optional — get a free [Tavily API](https://tavily.com) (1000 free queries/month) or [Brave Search API](https://brave.com/search/api) (2000 free queries/month).
**1. Initialize**
```bash
picoclaw onboard
```
**2. Configure** (`~/.picoclaw/config.json`)
```json
{
"agents": {
"defaults": {
"workspace": "~/.picoclaw/workspace",
"model_name": "gpt-5.4",
"max_tokens": 8192,
"temperature": 0.7,
"max_tool_iterations": 20
}
},
"model_list": [
{
"model_name": "ark-code-latest",
"model": "volcengine/ark-code-latest",
"api_key": "sk-your-api-key"
},
{
"model_name": "gpt-5.4",
"model": "openai/gpt-5.4",
"api_key": "your-api-key",
"request_timeout": 300
},
{
"model_name": "claude-sonnet-4.6",
"model": "anthropic/claude-sonnet-4.6",
"api_key": "your-anthropic-key"
}
],
"tools": {
"web": {
"brave": {
"enabled": false,
"api_key": "YOUR_BRAVE_API_KEY",
"max_results": 5
},
"tavily": {
"enabled": false,
"api_key": "YOUR_TAVILY_API_KEY",
"max_results": 5
},
"duckduckgo": {
"enabled": true,
"max_results": 5
},
"perplexity": {
"enabled": false,
"api_key": "YOUR_PERPLEXITY_API_KEY",
"max_results": 5
},
"searxng": {
"enabled": false,
"base_url": "http://your-searxng-instance:8888",
"max_results": 5
}
}
}
}
```
> **New**: The `model_list` configuration format allows zero-code provider addition. See [Model Configuration](#model-configuration-model_list) for details.
> `request_timeout` is optional and uses seconds. If omitted or set to `<= 0`, PicoClaw uses the default timeout (120s).
**3. Get API Keys**
* **LLM Provider**: [OpenRouter](https://openrouter.ai/keys) · [Zhipu](https://open.bigmodel.cn/usercenter/proj-mgmt/apikeys) · [Anthropic](https://console.anthropic.com) · [OpenAI](https://platform.openai.com) · [Gemini](https://aistudio.google.com/api-keys)
* **Web Search** (optional):
* [Brave Search](https://brave.com/search/api) - Paid ($5/1000 queries, ~$5-6/month)
* [Perplexity](https://www.perplexity.ai) - AI-powered search with chat interface
* [SearXNG](https://github.com/searxng/searxng) - Self-hosted metasearch engine (free, no API key needed)
* [Tavily](https://tavily.com) - Optimized for AI Agents (1000 requests/month)
* DuckDuckGo - Built-in fallback (no API key required)
> **Note**: See `config.example.json` for a complete configuration template.
**4. Chat**
```bash
picoclaw agent -m "What is 2+2?"
```
That's it! You have a working AI assistant in 2 minutes.
---
## 💬 Chat Apps
Talk to your picoclaw through Telegram, Discord, WhatsApp, Matrix, QQ, DingTalk, LINE, or WeCom
> **Note**: All webhook-based channels (LINE, WeCom, etc.) are served on a single shared Gateway HTTP server (`gateway.host`:`gateway.port`, default `127.0.0.1:18790`). There are no per-channel ports to configure. Note: Feishu uses WebSocket/SDK mode and does not use the shared HTTP webhook server.
| Channel | Setup |
| ------------ | ---------------------------------- |
| **Telegram** | Easy (just a token) |
| **Discord** | Easy (bot token + intents) |
| **WhatsApp** | Easy (native: QR scan; or bridge URL) |
| **Matrix** | Medium (homeserver + bot access token) |
| **QQ** | Easy (AppID + AppSecret) |
| **DingTalk** | Medium (app credentials) |
| **LINE** | Medium (credentials + webhook URL) |
| **WeCom AI Bot** | Medium (Token + AES key) |
<details>
<summary><b>Telegram</b> (Recommended)</summary>
**1. Create a bot**
* Open Telegram, search `@BotFather`
* Send `/newbot`, follow prompts
* Copy the token
**2. Configure**
```json
{
"channels": {
"telegram": {
"enabled": true,
"token": "YOUR_BOT_TOKEN",
"allow_from": ["YOUR_USER_ID"]
}
}
}
```
> Get your user ID from `@userinfobot` on Telegram.
**3. Run**
```bash
picoclaw gateway
```
**4. Telegram command menu (auto-registered at startup)**
PicoClaw now keeps command definitions in one shared registry. On startup, Telegram will automatically register supported bot commands (for example `/start`, `/help`, `/show`, `/list`) so command menu and runtime behavior stay in sync.
Telegram command menu registration remains channel-local discovery UX; generic command execution is handled centrally in the agent loop via the commands executor.
If command registration fails (network/API transient errors), the channel still starts and PicoClaw retries registration in the background.
</details>
<details>
<summary><b>Discord</b></summary>
**1. Create a bot**
* Go to <https://discord.com/developers/applications>
* Create an application → Bot → Add Bot
* Copy the bot token
**2. Enable intents**
* In the Bot settings, enable **MESSAGE CONTENT INTENT**
* (Optional) Enable **SERVER MEMBERS INTENT** if you plan to use allow lists based on member data
**3. Get your User ID**
* Discord Settings → Advanced → enable **Developer Mode**
* Right-click your avatar → **Copy User ID**
**4. Configure**
```json
{
"channels": {
"discord": {
"enabled": true,
"token": "YOUR_BOT_TOKEN",
"allow_from": ["YOUR_USER_ID"]
}
}
}
```
**5. Invite the bot**
* OAuth2 → URL Generator
* Scopes: `bot`
* Bot Permissions: `Send Messages`, `Read Message History`
* Open the generated invite URL and add the bot to your server
**Optional: Group trigger mode**
By default the bot responds to all messages in a server channel. To restrict responses to @-mentions only, add:
```json
{
"channels": {
"discord": {
"group_trigger": { "mention_only": true }
}
}
}
```
You can also trigger by keyword prefixes (e.g. `!bot`):
```json
{
"channels": {
"discord": {
"group_trigger": { "prefixes": ["!bot"] }
}
}
}
```
**6. Run**
```bash
picoclaw gateway
```
</details>
<details>
<summary><b>WhatsApp</b> (native via whatsmeow)</summary>
PicoClaw can connect to WhatsApp in two ways:
- **Native (recommended):** In-process using [whatsmeow](https://github.com/tulir/whatsmeow). No separate bridge. Set `"use_native": true` and leave `bridge_url` empty. On first run, scan the QR code with WhatsApp (Linked Devices). Session is stored under your workspace (e.g. `workspace/whatsapp/`). The native channel is **optional** to keep the default binary small; build with `-tags whatsapp_native` (e.g. `make build-whatsapp-native` or `go build -tags whatsapp_native ./cmd/...`).
- **Bridge:** Connect to an external WebSocket bridge. Set `bridge_url` (e.g. `ws://localhost:3001`) and keep `use_native` false.
**Configure (native)**
```json
{
"channels": {
"whatsapp": {
"enabled": true,
"use_native": true,
"session_store_path": "",
"allow_from": []
}
}
}
```
If `session_store_path` is empty, the session is stored in `&lt;workspace&gt;/whatsapp/`. Run `picoclaw gateway`; on first run, scan the QR code printed in the terminal with WhatsApp → Linked Devices.
</details>
<details>
<summary><b>QQ</b></summary>
**1. Create a bot**
- Go to [QQ Open Platform](https://q.qq.com/#)
- Create an application → Get **AppID** and **AppSecret**
**2. Configure**
```json
{
"channels": {
"qq": {
"enabled": true,
"app_id": "YOUR_APP_ID",
"app_secret": "YOUR_APP_SECRET",
"allow_from": []
}
}
}
```
> Set `allow_from` to empty to allow all users, or specify QQ numbers to restrict access.
**3. Run**
```bash
picoclaw gateway
```
</details>
<details>
<summary><b>DingTalk</b></summary>
**1. Create a bot**
* Go to [Open Platform](https://open.dingtalk.com/)
* Create an internal app
* Copy Client ID and Client Secret
**2. Configure**
```json
{
"channels": {
"dingtalk": {
"enabled": true,
"client_id": "YOUR_CLIENT_ID",
"client_secret": "YOUR_CLIENT_SECRET",
"allow_from": []
}
}
}
```
> Set `allow_from` to empty to allow all users, or specify DingTalk user IDs to restrict access.
**3. Run**
```bash
picoclaw gateway
```
</details>
<details>
<summary><b>Matrix</b></summary>
**1. Prepare bot account**
* Use your preferred homeserver (e.g. `https://matrix.org` or self-hosted)
* Create a bot user and obtain its access token
**2. Configure**
```json
{
"channels": {
"matrix": {
"enabled": true,
"homeserver": "https://matrix.org",
"user_id": "@your-bot:matrix.org",
"access_token": "YOUR_MATRIX_ACCESS_TOKEN",
"allow_from": []
}
}
}
```
**3. Run**
```bash
picoclaw gateway
```
For full options (`device_id`, `join_on_invite`, `group_trigger`, `placeholder`, `reasoning_channel_id`), see [Matrix Channel Configuration Guide](docs/channels/matrix/README.md).
</details>
<details>
<summary><b>LINE</b></summary>
**1. Create a LINE Official Account**
- Go to [LINE Developers Console](https://developers.line.biz/)
- Create a provider → Create a Messaging API channel
- Copy **Channel Secret** and **Channel Access Token**
**2. Configure**
```json
{
"channels": {
"line": {
"enabled": true,
"channel_secret": "YOUR_CHANNEL_SECRET",
"channel_access_token": "YOUR_CHANNEL_ACCESS_TOKEN",
"webhook_path": "/webhook/line",
"allow_from": []
}
}
}
```
> LINE webhook is served on the shared Gateway server (`gateway.host`:`gateway.port`, default `127.0.0.1:18790`).
**3. Set up Webhook URL**
LINE requires HTTPS for webhooks. Use a reverse proxy or tunnel:
```bash
# Example with ngrok (gateway default port is 18790)
ngrok http 18790
```
Then set the Webhook URL in LINE Developers Console to `https://your-domain/webhook/line` and enable **Use webhook**.
**4. Run**
```bash
picoclaw gateway
```
> In group chats, the bot responds only when @mentioned. Replies quote the original message.
</details>
<details>
<summary><b>WeCom (企业微信)</b></summary>
PicoClaw supports three types of WeCom integration:
**Option 1: WeCom Bot (Bot)** - Easier setup, supports group chats
**Option 2: WeCom App (Custom App)** - More features, proactive messaging, private chat only
**Option 3: WeCom AI Bot (AI Bot)** - Official AI Bot, streaming replies, supports group & private chat
See [WeCom AI Bot Configuration Guide](docs/channels/wecom/wecom_aibot/README.zh.md) for detailed setup instructions.
**Quick Setup - WeCom AI Bot:**
**1. Create an AI Bot**
* Go to WeCom Admin Console → AI Bot
* Create a new AI Bot → Set name, avatar, etc.
* Copy **Bot ID** and **Secret**
**2. Configure**
```json
{
"channels": {
"wecom_aibot": {
"enabled": true,
"bot_id": "YOUR_BOT_ID",
"secret": "YOUR_SECRET",
"allow_from": [],
"welcome_message": "Hello! How can I help you?"
}
}
}
```
**3. Run**
```bash
picoclaw gateway
```
> **Note**: WeCom AI Bot uses streaming pull protocol — no reply timeout concerns. Long tasks (>30 seconds) automatically switch to `response_url` push delivery.
</details>
## <img src="assets/clawdchat-icon.png" width="24" height="24" alt="ClawdChat"> Join the Agent Social Network
Connect Picoclaw to the Agent Social Network simply by sending a single message via the CLI or any integrated Chat App.
**Read `https://clawdchat.ai/skill.md` and follow the instructions to join [ClawdChat.ai](https://clawdchat.ai)**
## 🖥️ CLI Reference
| Command | Description |
| ------------------------- | ----------------------------- |
| `picoclaw onboard` | Initialize config & workspace |
| `picoclaw agent -m "..."` | Chat with the agent |
| `picoclaw agent` | Interactive chat mode |
| `picoclaw gateway` | Start the gateway |
| `picoclaw status` | Show status |
| `picoclaw version` | Show version info |
| `picoclaw cron list` | List all scheduled jobs |
| `picoclaw cron add ...` | Add a scheduled job |
| `picoclaw cron disable` | Disable a scheduled job |
| `picoclaw cron remove` | Remove a scheduled job |
| `picoclaw skills list` | List installed skills |
| `picoclaw skills install` | Install a skill |
| `picoclaw migrate` | Migrate data from older versions |
| `picoclaw auth login` | Authenticate with providers |
### Scheduled Tasks / Reminders
PicoClaw supports scheduled reminders and recurring tasks through the `cron` tool:
* **One-time reminders**: "Remind me in 10 minutes" → triggers once after 10min
* **Recurring tasks**: "Remind me every 2 hours" → triggers every 2 hours
* **Cron expressions**: "Remind me at 9am daily" → uses cron expression
## 🤝 Contribute & Roadmap
PRs welcome! The codebase is intentionally small and readable. 🤗
See our full [Community Roadmap](https://github.com/sipeed/picoclaw/blob/main/ROADMAP.md).
Developer group building, join after your first merged PR!
User Groups:
discord: <https://discord.gg/V4sAZ9XWpN>
<img src="assets/wechat.png" alt="PicoClaw" width="512">
## <img src="assets/clawdchat-icon.png" width="24" height="24" alt="ClawdChat"> Join the Agent Social Network
Connect Picoclaw to the Agent Social Network simply by sending a single message via the CLI or any integrated Chat App.
**Read `https://clawdchat.ai/skill.md` and follow the instructions to join [ClawdChat.ai](https://clawdchat.ai)**
## 🖥️ CLI Reference
| Command | Description |
| ------------------------- | ----------------------------- |
| `picoclaw onboard` | Initialize config & workspace |
| `picoclaw agent -m "..."` | Chat with the agent |
| `picoclaw agent` | Interactive chat mode |
| `picoclaw gateway` | Start the gateway |
| `picoclaw status` | Show status |
| `picoclaw version` | Show version info |
| `picoclaw cron list` | List all scheduled jobs |
| `picoclaw cron add ...` | Add a scheduled job |
| `picoclaw cron disable` | Disable a scheduled job |
| `picoclaw cron remove` | Remove a scheduled job |
| `picoclaw skills list` | List installed skills |
| `picoclaw skills install` | Install a skill |
| `picoclaw migrate` | Migrate data from older versions |
| `picoclaw auth login` | Authenticate with providers |
### Scheduled Tasks / Reminders
PicoClaw supports scheduled reminders and recurring tasks through the `cron` tool:
* **One-time reminders**: "Remind me in 10 minutes" → triggers once after 10min
* **Recurring tasks**: "Remind me every 2 hours" → triggers every 2 hours
* **Cron expressions**: "Remind me at 9am daily" → uses cron expression
## 🤝 Contribute & Roadmap
PRs welcome! The codebase is intentionally small and readable. 🤗
See our full [Community Roadmap](https://github.com/sipeed/picoclaw/blob/main/ROADMAP.md).
Developer group building, join after your first merged PR!
User Groups:
discord: <https://discord.gg/V4sAZ9XWpN>
<img src="assets/wechat.png" alt="PicoClaw" width="512">

View file

@ -105,6 +105,8 @@ _*Versões recentes podem usar 1020MB devido a merges rápidos de funcionalid
<img src="assets/compare.jpg" alt="PicoClaw" width="512">
> 📋 **[Lista de Compatibilidade de Hardware](docs/hardware-compatibility.md)** — Veja todas as placas testadas, de RISC-V de $5 a Raspberry Pi e telefones Android. Sua placa não está listada? Envie um PR!
## 🦾 Demonstração
### 🛠️ Fluxos de Trabalho Padrão do Assistente
@ -200,6 +202,7 @@ Para guias detalhados, consulte a documentação abaixo. Este README cobre apena
| 🔄 [Spawn & Tarefas Assíncronas](docs/pt-br/spawn-tasks.md) | Tarefas rápidas, tarefas longas com spawn, orquestração assíncrona de sub-agentes |
| 🐛 [Solução de Problemas](docs/pt-br/troubleshooting.md) | Problemas comuns e soluções |
| 🔧 [Configuração de Ferramentas](docs/pt-br/tools_configuration.md) | Habilitar/desabilitar por ferramenta, políticas de execução |
| 📋 [Compatibilidade de Hardware](docs/hardware-compatibility.md) | Placas testadas, requisitos mínimos, como adicionar sua placa |
## <img src="assets/clawdchat-icon.png" width="24" height="24" alt="ClawdChat"> Junte-se à Rede Social de Agentes

View file

@ -105,6 +105,8 @@ _*Các phiên bản gần đây có thể sử dụng 1020MB do merge tính n
<img src="assets/compare.jpg" alt="PicoClaw" width="512">
> 📋 **[Danh Sách Tương Thích Phần Cứng](docs/hardware-compatibility.md)** — Xem tất cả các board đã được kiểm tra, từ RISC-V $5 đến Raspberry Pi và điện thoại Android. Board của bạn chưa có? Gửi PR!
## 🦾 Demo
### 🛠️ Quy trình trợ lý tiêu chuẩn
@ -200,6 +202,7 @@ make install
| 🔄 [Spawn & Tác vụ bất đồng bộ](docs/vi/spawn-tasks.md) | Tác vụ nhanh, tác vụ dài với spawn, điều phối sub-agent bất đồng bộ |
| 🐛 [Xử lý sự cố](docs/vi/troubleshooting.md) | Các vấn đề thường gặp và giải pháp |
| 🔧 [Cấu hình Công cụ](docs/vi/tools_configuration.md) | Bật/tắt từng công cụ, chính sách thực thi |
| 📋 [Tương Thích Phần Cứng](docs/hardware-compatibility.md) | Các board đã kiểm tra, yêu cầu tối thiểu, cách thêm board |
## <img src="assets/clawdchat-icon.png" width="24" height="24" alt="ClawdChat"> Tham gia Mạng xã hội Agent

View file

@ -104,6 +104,8 @@ _*近期版本因快速合并 PR 可能占用 1020MB资源优化已列入
<img src="assets/compare.jpg" alt="PicoClaw" width="512">
> 📋 **[硬件兼容列表](docs/hardware-compatibility.md)** — 查看所有已测试的板卡,从 $5 RISC-V 到树莓派到安卓手机。你的板卡没在列表中?欢迎提交 PR
## 🦾 演示
### 🛠️ 标准助手工作流
@ -199,6 +201,7 @@ make install
| 🔄 [异步任务与 Spawn](docs/zh/spawn-tasks.md) | 快速任务、长任务与 Spawn、异步子 Agent 编排 |
| 🐛 [疑难解答](docs/zh/troubleshooting.md) | 常见问题与解决方案 |
| 🔧 [工具配置](docs/zh/tools_configuration.md) | 工具启用/禁用、执行策略 |
| 📋 [硬件兼容列表](docs/hardware-compatibility.md) | 已测试板卡、最低要求、如何添加你的板卡 |
## <img src="assets/clawdchat-icon.png" width="24" height="24" alt="ClawdChat"> 加入 Agent 社交网络

View file

@ -438,7 +438,7 @@ type ProviderAuthResult = {
### 1. Required Environment/Dependencies
- Go ≥ 1.21
- Go ≥ 1.25
- PicoClaw codebase (`pkg/providers/` and `pkg/auth/`)
- `crypto` and `net/http` standard library packages
@ -674,7 +674,7 @@ Add a default entry in `pkg/config/defaults.go`:
#### 5. Add Auth Support (Optional)
If your provider requires OAuth or special authentication, add a case to `cmd/picoclaw/cmd_auth.go`:
If your provider requires OAuth or special authentication, add a case to `cmd/picoclaw/internal/auth/helpers.go`:
```go
case "your-provider":
@ -736,7 +736,7 @@ export PICOCLAW_MODEL_LIST='[{"model_name":"your-model","model":"your-provider/m
- `pkg/auth/store.go` - Auth credential storage (`~/.picoclaw/auth.json`)
- `pkg/providers/factory.go` - Provider factory and protocol routing
- `pkg/providers/types.go` - Provider interface definitions
- `cmd/picoclaw/cmd_auth.go` - Auth CLI commands
- `cmd/picoclaw/internal/auth/helpers.go` - Auth CLI commands
- **Documentation:**
- `docs/ANTIGRAVITY_USAGE.md` - Antigravity usage guide

View file

@ -9,18 +9,20 @@ MaixCam 是专用于连接矽速科技 MaixCAM 与 MaixCAM2 AI 摄像设备的
"channels": {
"maixcam": {
"enabled": true,
"server_address": "0.0.0.0:8899",
"host": "0.0.0.0",
"port": 18790,
"allow_from": []
}
}
}
```
| 字段 | 类型 | 必填 | 描述 |
| -------------- | ------ | ---- | -------------------------------- |
| enabled | bool | 是 | 是否启用 MaixCam 频道 |
| server_address | string | 是 | TCP 服务器监听地址和端口 |
| allow_from | array | 否 | 设备ID白名单空表示允许所有设备 |
| 字段 | 类型 | 必填 | 描述 |
| ---------- | ------ | ---- | -------------------------------- |
| enabled | bool | 是 | 是否启用 MaixCam 频道 |
| host | string | 是 | TCP 服务器监听地址 |
| port | int | 是 | TCP 服务器监听端口 |
| allow_from | array | 否 | 设备ID白名单空表示允许所有设备 |
## 使用场景

View file

@ -42,6 +42,7 @@
| group_trigger | object | 否 | 群聊触发策略(支持 `mention_only` / `prefixes` |
| placeholder | object | 否 | 占位消息配置 |
| reasoning_channel_id | string | 否 | 思维链输出目标通道 |
| message_format | string | 否 | 消息格式:`richtext`(富文本)或 `plain`(纯文本) |
## 3. 当前支持

View file

@ -97,7 +97,7 @@
1. 登录 [企业微信管理后台](https://work.weixin.qq.com/wework_admin)
2. 进入"应用管理" → "智能机器人",创建或选择一个 AI Bot
3. 在 AI Bot 配置页面,填写"消息接收"信息:
- **URL**`http://<your-server-ip>:18791/webhook/wecom-aibot`
- **URL**`http://<your-server-ip>:18790/webhook/wecom-aibot`
- **Token**:随机生成或自定义
- **EncodingAESKey**:点击"随机生成",得到 43 字符密钥
4. 将 Token 和 EncodingAESKey 填入 PicoClaw 配置文件,启动服务后回到管理后台保存
@ -159,6 +159,7 @@ PicoClaw 立即返回 {finish: false}Agent 开始处理)
### 回调 URL 验证失败
- 确认 `token``encoding_aes_key` 填写正确
- 确认服务器防火墙已开放对应端口
- 检查 PicoClaw 日志是否收到了来自企业微信的验证请求

View file

@ -265,7 +265,7 @@ picoclaw gateway
picoclaw gateway
```
For full options (`device_id`, `join_on_invite`, `group_trigger`, `placeholder`, `reasoning_channel_id`), see [Matrix Channel Configuration Guide](docs/channels/matrix/README.md).
For full options (`device_id`, `join_on_invite`, `group_trigger`, `placeholder`, `reasoning_channel_id`), see [Matrix Channel Configuration Guide](channels/matrix/README.md).
</details>
@ -400,7 +400,7 @@ picoclaw gateway
**1. Create an AI Bot**
* Go to WeCom Admin Console → App Management → AI Bot
* In the AI Bot settings, configure callback URL: `http://your-server:18791/webhook/wecom-aibot`
* In the AI Bot settings, configure callback URL: `http://your-server:18790/webhook/wecom-aibot`
* Copy **Token** and click "Random Generate" for **EncodingAESKey**
**2. Configure**

View file

@ -57,7 +57,7 @@ By default, skills are loaded from:
1. `~/.picoclaw/workspace/skills` (workspace)
2. `~/.picoclaw/skills` (global)
3. `<current-working-directory>/skills` (builtin)
3. `<binary-embedded-path>/skills` (builtin, set at build time)
For advanced/test setups, you can override the builtin skills root with:

View file

@ -31,7 +31,7 @@ enc://AAAA...base64...
{
"model_name": "gpt-4o",
"api_key": "enc://AAAA...base64...",
"base_url": "https://api.openai.com/v1"
"api_base": "https://api.openai.com/v1"
}
]
}
@ -54,20 +54,12 @@ enc://AAAA...base64...
### Key Derivation
Encryption uses **HKDF-SHA256** with an optional SSH private key as a second factor.
Encryption uses **HKDF-SHA256** with an SSH private key as a second factor.
```
Without SSH key (passphrase only):
ikm = SHA256(passphrase)
aes_key = HKDF-SHA256(ikm, salt, info="picoclaw-credential-v1", 32 bytes)
With SSH key (recommended):
sshHash = SHA256(ssh_private_key_file_bytes)
ikm = HMAC-SHA256(key=sshHash, message=passphrase)
aes_key = HKDF-SHA256(ikm, salt, info="picoclaw-credential-v1", 32 bytes)
sshHash = SHA256(ssh_private_key_file_bytes)
ikm = HMAC-SHA256(key=sshHash, message=passphrase)
aes_key = HKDF-SHA256(ikm, salt, info="picoclaw-credential-v1", 32 bytes)
```
### Encryption
@ -125,7 +117,7 @@ This means a leaked config file alone is not sufficient to recover the API key,
| Variable | Required | Description |
|----------|----------|-------------|
| `PICOCLAW_KEY_PASSPHRASE` | Yes (for `enc://`) | Passphrase used for key derivation |
| `PICOCLAW_SSH_KEY_PATH` | No | Path to SSH private key. Set to `""` to disable auto-detection and use passphrase-only mode |
| `PICOCLAW_SSH_KEY_PATH` | No | Path to SSH private key. If not set, auto-detects from `~/.ssh/picoclaw_ed25519.key` |
### SSH Key Auto-Detection
@ -140,11 +132,7 @@ Run `picoclaw onboard` to generate it automatically.
`os.UserHomeDir()` is used for cross-platform home directory resolution (reads `USERPROFILE` on Windows, `HOME` on Unix/macOS).
To explicitly disable SSH key usage and use passphrase-only mode:
```bash
export PICOCLAW_SSH_KEY_PATH=""
```
> **Note:** An SSH key file is required for credential encryption. If no key is found and `PICOCLAW_SSH_KEY_PATH` is not set, encryption/decryption will fail. Run `picoclaw onboard` to generate the key automatically.
---
@ -162,7 +150,7 @@ No re-encryption is needed.
## Security Considerations
- **Passphrase strength matters in passphrase-only mode.** Without an SSH key, a weak passphrase can be brute-forced offline. Use `PICOCLAW_SSH_KEY_PATH=""` only in environments where no SSH key is available and the passphrase is sufficiently strong (≥ 32 random characters).
- **Both passphrase and SSH key are required.** The SSH key acts as a second factor — without it, encryption/decryption will fail. Run `picoclaw onboard` to generate the key if it doesn't exist.
- **The SSH key is read-only at runtime.** PicoClaw never writes to or modifies the SSH key file.
- **Plaintext keys remain supported.** Existing configs without `enc://` are unaffected.
- **The `enc://` format is versioned** via the HKDF `info` field (`picoclaw-credential-v1`), allowing future algorithm upgrades without breaking existing encrypted values.

809
docs/fr/ANTIGRAVITY_AUTH.md Normal file
View file

@ -0,0 +1,809 @@
> Retour au [README](../../README.fr.md)
# Guide d'authentification et d'intégration Antigravity
## Aperçu
**Antigravity** (Google Cloud Code Assist) est un fournisseur de modèles IA soutenu par Google qui offre l'accès à des modèles tels que Claude Opus 4.6 et Gemini via l'infrastructure cloud de Google. Ce document fournit un guide complet sur le fonctionnement de l'authentification, la récupération des modèles et l'implémentation d'un nouveau fournisseur dans PicoClaw.
---
## Table des matières
1. [Flux d'authentification](#flux-dauthentification)
2. [Détails de l'implémentation OAuth](#détails-de-limplémentation-oauth)
3. [Gestion des jetons](#gestion-des-jetons)
4. [Récupération de la liste des modèles](#récupération-de-la-liste-des-modèles)
5. [Suivi de l'utilisation](#suivi-de-lutilisation)
6. [Structure du plugin fournisseur](#structure-du-plugin-fournisseur)
7. [Exigences d'intégration](#exigences-dintégration)
8. [Points de terminaison API](#points-de-terminaison-api)
9. [Configuration](#configuration)
10. [Créer un nouveau fournisseur dans PicoClaw](#créer-un-nouveau-fournisseur-dans-picoclaw)
---
## Flux d'authentification
### 1. OAuth 2.0 avec PKCE
Antigravity utilise **OAuth 2.0 avec PKCE (Proof Key for Code Exchange)** pour une authentification sécurisée :
```
┌─────────────┐ ┌─────────────────┐
│ Client │ ───(1) Generate PKCE Pair────────> │ │
│ │ ───(2) Open Auth URL─────────────> │ Google OAuth │
│ │ │ Server │
│ │ <──(3) Redirect with Code───────── │ │
│ │ └─────────────────┘
│ │ ───(4) Exchange Code for Tokens──> │ Token URL │
│ │ │ │
│ │ <──(5) Access + Refresh Tokens──── │ │
└─────────────┘ └─────────────────┘
```
### 2. Étapes détaillées
#### Étape 1 : Générer les paramètres PKCE
```typescript
function generatePkce(): { verifier: string; challenge: string } {
const verifier = randomBytes(32).toString("hex");
const challenge = createHash("sha256").update(verifier).digest("base64url");
return { verifier, challenge };
}
```
#### Étape 2 : Construire l'URL d'autorisation
```typescript
const AUTH_URL = "https://accounts.google.com/o/oauth2/v2/auth";
const REDIRECT_URI = "http://localhost:51121/oauth-callback";
function buildAuthUrl(params: { challenge: string; state: string }): string {
const url = new URL(AUTH_URL);
url.searchParams.set("client_id", CLIENT_ID);
url.searchParams.set("response_type", "code");
url.searchParams.set("redirect_uri", REDIRECT_URI);
url.searchParams.set("scope", SCOPES.join(" "));
url.searchParams.set("code_challenge", params.challenge);
url.searchParams.set("code_challenge_method", "S256");
url.searchParams.set("state", params.state);
url.searchParams.set("access_type", "offline");
url.searchParams.set("prompt", "consent");
return url.toString();
}
```
**Portées requises :**
```typescript
const SCOPES = [
"https://www.googleapis.com/auth/cloud-platform",
"https://www.googleapis.com/auth/userinfo.email",
"https://www.googleapis.com/auth/userinfo.profile",
"https://www.googleapis.com/auth/cclog",
"https://www.googleapis.com/auth/experimentsandconfigs",
];
```
#### Étape 3 : Gérer le callback OAuth
**Mode automatique (développement local) :**
- Démarrer un serveur HTTP local sur le port 51121
- Attendre la redirection de Google
- Extraire le code d'autorisation des paramètres de requête
**Mode manuel (distant/sans interface graphique) :**
- Afficher l'URL d'autorisation à l'utilisateur
- L'utilisateur complète l'authentification dans son navigateur
- L'utilisateur colle l'URL de redirection complète dans le terminal
- Analyser le code depuis l'URL collée
#### Étape 4 : Échanger le code contre des jetons
```typescript
const TOKEN_URL = "https://oauth2.googleapis.com/token";
async function exchangeCode(params: {
code: string;
verifier: string;
}): Promise<{ access: string; refresh: string; expires: number }> {
const response = await fetch(TOKEN_URL, {
method: "POST",
headers: { "Content-Type": "application/x-www-form-urlencoded" },
body: new URLSearchParams({
client_id: CLIENT_ID,
client_secret: CLIENT_SECRET,
code: params.code,
grant_type: "authorization_code",
redirect_uri: REDIRECT_URI,
code_verifier: params.verifier,
}),
});
const data = await response.json();
return {
access: data.access_token,
refresh: data.refresh_token,
expires: Date.now() + data.expires_in * 1000 - 5 * 60 * 1000, // 5 min buffer
};
}
```
#### Étape 5 : Récupérer les données utilisateur supplémentaires
**E-mail de l'utilisateur :**
```typescript
async function fetchUserEmail(accessToken: string): Promise<string | undefined> {
const response = await fetch(
"https://www.googleapis.com/oauth2/v1/userinfo?alt=json",
{ headers: { Authorization: `Bearer ${accessToken}` } }
);
const data = await response.json();
return data.email;
}
```
**ID du projet (requis pour les appels API) :**
```typescript
async function fetchProjectId(accessToken: string): Promise<string> {
const headers = {
Authorization: `Bearer ${accessToken}`,
"Content-Type": "application/json",
"User-Agent": "google-api-nodejs-client/9.15.1",
"X-Goog-Api-Client": "google-cloud-sdk vscode_cloudshelleditor/0.1",
"Client-Metadata": JSON.stringify({
ideType: "IDE_UNSPECIFIED",
platform: "PLATFORM_UNSPECIFIED",
pluginType: "GEMINI",
}),
};
const response = await fetch(
"https://cloudcode-pa.googleapis.com/v1internal:loadCodeAssist",
{
method: "POST",
headers,
body: JSON.stringify({
metadata: {
ideType: "IDE_UNSPECIFIED",
platform: "PLATFORM_UNSPECIFIED",
pluginType: "GEMINI",
},
}),
}
);
const data = await response.json();
return data.cloudaicompanionProject || "rising-fact-p41fc"; // Valeur par défaut
}
```
---
## Détails de l'implémentation OAuth
### Identifiants client
**Important :** Ceux-ci sont encodés en base64 dans le code source pour la synchronisation avec pi-ai :
```typescript
const decode = (s: string) => Buffer.from(s, "base64").toString();
const CLIENT_ID = decode(
"MTA3MTAwNjA2MDU5MS10bWhzc2luMmgyMWxjcmUyMzV2dG9sb2poNGc0MDNlcC5hcHBzLmdvb2dsZXVzZXJjb250ZW50LmNvbQ=="
);
const CLIENT_SECRET = decode("R09DU1BYLUs1OEZXUjQ4NkxkTEoxbUxCOHNYQzR6NnFEQWY=");
```
### Modes de flux OAuth
1. **Flux automatique** (machines locales avec navigateur) :
- Ouvre le navigateur automatiquement
- Le serveur de callback local capture la redirection
- Aucune interaction utilisateur requise après l'authentification initiale
2. **Flux manuel** (distant/sans interface/WSL2) :
- URL affichée pour copier-coller manuellement
- L'utilisateur complète l'authentification dans un navigateur externe
- L'utilisateur colle l'URL de redirection complète
```typescript
function shouldUseManualOAuthFlow(isRemote: boolean): boolean {
return isRemote || isWSL2Sync();
}
```
---
## Gestion des jetons
### Structure du profil d'authentification
```typescript
type OAuthCredential = {
type: "oauth";
provider: "google-antigravity";
access: string; // Jeton d'accès
refresh: string; // Jeton de rafraîchissement
expires: number; // Horodatage d'expiration (ms depuis epoch)
email?: string; // E-mail de l'utilisateur
projectId?: string; // ID du projet Google Cloud
};
```
### Rafraîchissement des jetons
Les identifiants incluent un jeton de rafraîchissement qui peut être utilisé pour obtenir de nouveaux jetons d'accès lorsque le jeton actuel expire. L'expiration est définie avec un tampon de 5 minutes pour éviter les conditions de concurrence.
---
## Récupération de la liste des modèles
### Récupérer les modèles disponibles
```typescript
const BASE_URL = "https://cloudcode-pa.googleapis.com";
async function fetchAvailableModels(
accessToken: string,
projectId: string
): Promise<Model[]> {
const headers = {
Authorization: `Bearer ${accessToken}`,
"Content-Type": "application/json",
"User-Agent": "antigravity",
"X-Goog-Api-Client": "google-cloud-sdk vscode_cloudshelleditor/0.1",
};
const response = await fetch(
`${BASE_URL}/v1internal:fetchAvailableModels`,
{
method: "POST",
headers,
body: JSON.stringify({ project: projectId }),
}
);
const data = await response.json();
// Retourne les modèles avec les informations de quota
return Object.entries(data.models).map(([modelId, modelInfo]) => ({
id: modelId,
displayName: modelInfo.displayName,
quotaInfo: {
remainingFraction: modelInfo.quotaInfo?.remainingFraction,
resetTime: modelInfo.quotaInfo?.resetTime,
isExhausted: modelInfo.quotaInfo?.isExhausted,
},
}));
}
```
### Format de réponse
```typescript
type FetchAvailableModelsResponse = {
models?: Record<string, {
displayName?: string;
quotaInfo?: {
remainingFraction?: number | string;
resetTime?: string; // Horodatage ISO 8601
isExhausted?: boolean;
};
}>;
};
```
---
## Suivi de l'utilisation
### Récupérer les données d'utilisation
```typescript
export async function fetchAntigravityUsage(
token: string,
timeoutMs: number
): Promise<ProviderUsageSnapshot> {
// 1. Récupérer les crédits et les informations du plan
const loadCodeAssistRes = await fetch(
`${BASE_URL}/v1internal:loadCodeAssist`,
{
method: "POST",
headers: {
Authorization: `Bearer ${token}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
metadata: {
ideType: "ANTIGRAVITY",
platform: "PLATFORM_UNSPECIFIED",
pluginType: "GEMINI",
},
}),
}
);
// Extraire les informations de crédits
const { availablePromptCredits, planInfo, currentTier } = data;
// 2. Récupérer les quotas des modèles
const modelsRes = await fetch(
`${BASE_URL}/v1internal:fetchAvailableModels`,
{
method: "POST",
headers: { Authorization: `Bearer ${token}` },
body: JSON.stringify({ project: projectId }),
}
);
// Construire les fenêtres d'utilisation
return {
provider: "google-antigravity",
displayName: "Google Antigravity",
windows: [
{ label: "Credits", usedPercent: calculateUsedPercent(available, monthly) },
// Quotas individuels des modèles...
],
plan: currentTier?.name || planType,
};
}
```
### Structure de la réponse d'utilisation
```typescript
type ProviderUsageSnapshot = {
provider: "google-antigravity";
displayName: string;
windows: UsageWindow[];
plan?: string;
error?: string;
};
type UsageWindow = {
label: string; // "Credits" ou ID du modèle
usedPercent: number; // 0-100
resetAt?: number; // Horodatage de réinitialisation du quota
};
```
---
## Structure du plugin fournisseur
### Définition du plugin
```typescript
const antigravityPlugin = {
id: "google-antigravity-auth",
name: "Google Antigravity Auth",
description: "OAuth flow for Google Antigravity (Cloud Code Assist)",
configSchema: emptyPluginConfigSchema(),
register(api: PicoClawPluginApi) {
api.registerProvider({
id: "google-antigravity",
label: "Google Antigravity",
docsPath: "/providers/models",
aliases: ["antigravity"],
auth: [
{
id: "oauth",
label: "Google OAuth",
hint: "PKCE + localhost callback",
kind: "oauth",
run: async (ctx: ProviderAuthContext) => {
// Implémentation OAuth ici
},
},
],
});
},
};
```
### ProviderAuthContext
```typescript
type ProviderAuthContext = {
config: PicoClawConfig;
agentDir?: string;
workspaceDir?: string;
prompter: WizardPrompter; // Invites/notifications UI
runtime: RuntimeEnv; // Journalisation, etc.
isRemote: boolean; // Exécution à distance ou non
openUrl: (url: string) => Promise<void>; // Ouverture du navigateur
oauth: {
createVpsAwareHandlers: Function;
};
};
```
### ProviderAuthResult
```typescript
type ProviderAuthResult = {
profiles: Array<{
profileId: string;
credential: AuthProfileCredential;
}>;
configPatch?: Partial<PicoClawConfig>;
defaultModel?: string;
notes?: string[];
};
```
---
## Exigences d'intégration
### 1. Environnement/dépendances requis
- Go ≥ 1.25
- Base de code PicoClaw (`pkg/providers/` et `pkg/auth/`)
- Packages de la bibliothèque standard `crypto` et `net/http`
### 2. En-têtes requis pour les appels API
```typescript
const REQUIRED_HEADERS = {
"Authorization": `Bearer ${accessToken}`,
"Content-Type": "application/json",
"User-Agent": "antigravity", // ou "google-api-nodejs-client/9.15.1"
"X-Goog-Api-Client": "google-cloud-sdk vscode_cloudshelleditor/0.1",
};
// Pour les appels loadCodeAssist, inclure également :
const CLIENT_METADATA = {
ideType: "ANTIGRAVITY", // ou "IDE_UNSPECIFIED"
platform: "PLATFORM_UNSPECIFIED",
pluginType: "GEMINI",
};
```
### 3. Assainissement des schémas de modèles
Antigravity utilise des modèles compatibles Gemini, les schémas d'outils doivent donc être assainis :
```typescript
const GOOGLE_SCHEMA_UNSUPPORTED_KEYWORDS = new Set([
"patternProperties",
"additionalProperties",
"$schema",
"$id",
"$ref",
"$defs",
"definitions",
"examples",
"minLength",
"maxLength",
"minimum",
"maximum",
"multipleOf",
"pattern",
"format",
"minItems",
"maxItems",
"uniqueItems",
"minProperties",
"maxProperties",
]);
// Nettoyer le schéma avant l'envoi
function cleanToolSchemaForGemini(schema: Record<string, unknown>): unknown {
// Supprimer les mots-clés non supportés
// S'assurer que le niveau supérieur a type: "object"
// Aplatir les unions anyOf/oneOf
}
```
### 4. Gestion des blocs de réflexion (modèles Claude)
Pour les modèles Claude via Antigravity, les blocs de réflexion nécessitent un traitement spécial :
```typescript
const ANTIGRAVITY_SIGNATURE_RE = /^[A-Za-z0-9+/]+={0,2}$/;
export function sanitizeAntigravityThinkingBlocks(
messages: AgentMessage[]
): AgentMessage[] {
// Valider les signatures de réflexion
// Normaliser les champs de signature
// Rejeter les blocs de réflexion non signés
}
```
---
## Points de terminaison API
### Points de terminaison d'authentification
| Point de terminaison | Méthode | Objectif |
|---------------------|---------|----------|
| `https://accounts.google.com/o/oauth2/v2/auth` | GET | Autorisation OAuth |
| `https://oauth2.googleapis.com/token` | POST | Échange de jetons |
| `https://www.googleapis.com/oauth2/v1/userinfo` | GET | Informations utilisateur (e-mail) |
### Points de terminaison Cloud Code Assist
| Point de terminaison | Méthode | Objectif |
|---------------------|---------|----------|
| `https://cloudcode-pa.googleapis.com/v1internal:loadCodeAssist` | POST | Charger les infos du projet, crédits, plan |
| `https://cloudcode-pa.googleapis.com/v1internal:fetchAvailableModels` | POST | Lister les modèles disponibles avec quotas |
| `https://cloudcode-pa.googleapis.com/v1internal:streamGenerateContent?alt=sse` | POST | Point de terminaison de streaming de chat |
**Format de requête API (chat) :**
Le point de terminaison `v1internal:streamGenerateContent` attend une enveloppe encapsulant la requête Gemini standard :
```json
{
"project": "your-project-id",
"model": "model-id",
"request": {
"contents": [...],
"systemInstruction": {...},
"generationConfig": {...},
"tools": [...]
},
"requestType": "agent",
"userAgent": "antigravity",
"requestId": "agent-timestamp-random"
}
```
**Format de réponse API (SSE) :**
Chaque message SSE (`data: {...}`) est encapsulé dans un champ `response` :
```json
{
"response": {
"candidates": [...],
"usageMetadata": {...},
"modelVersion": "...",
"responseId": "..."
},
"traceId": "...",
"metadata": {}
}
```
---
## Configuration
### Configuration config.json
```json
{
"model_list": [
{
"model_name": "gemini-flash",
"model": "antigravity/gemini-3-flash",
"auth_method": "oauth"
}
],
"agents": {
"defaults": {
"model": "gemini-flash"
}
}
}
```
### Stockage du profil d'authentification
Les profils d'authentification sont stockés dans `~/.picoclaw/auth.json` :
```json
{
"credentials": {
"google-antigravity": {
"access_token": "ya29...",
"refresh_token": "1//...",
"expires_at": "2026-01-01T00:00:00Z",
"provider": "google-antigravity",
"auth_method": "oauth",
"email": "user@example.com",
"project_id": "my-project-id"
}
}
}
```
---
## Créer un nouveau fournisseur dans PicoClaw
Les fournisseurs PicoClaw sont implémentés en tant que packages Go sous `pkg/providers/`. Pour ajouter un nouveau fournisseur :
### Implémentation étape par étape
#### 1. Créer le fichier du fournisseur
Créez un nouveau fichier Go dans `pkg/providers/` :
```
pkg/providers/
└── your_provider.go
```
#### 2. Implémenter l'interface Provider
Votre fournisseur doit implémenter l'interface `Provider` définie dans `pkg/providers/types.go` :
```go
package providers
type YourProvider struct {
apiKey string
apiBase string
}
func NewYourProvider(apiKey, apiBase, proxy string) *YourProvider {
if apiBase == "" {
apiBase = "https://api.your-provider.com/v1"
}
return &YourProvider{apiKey: apiKey, apiBase: apiBase}
}
func (p *YourProvider) Chat(ctx context.Context, messages []Message, tools []Tool, cb StreamCallback) error {
// Implémenter la complétion de chat avec streaming
}
```
#### 3. Enregistrer dans la factory
Ajoutez votre fournisseur au switch de protocole dans `pkg/providers/factory.go` :
```go
case "your-provider":
return NewYourProvider(sel.apiKey, sel.apiBase, sel.proxy), nil
```
#### 4. Ajouter la configuration par défaut (optionnel)
Ajoutez une entrée par défaut dans `pkg/config/defaults.go` :
```go
{
ModelName: "your-model",
Model: "your-provider/model-name",
APIKey: "",
},
```
#### 5. Ajouter le support d'authentification (optionnel)
Si votre fournisseur nécessite OAuth ou une authentification spéciale, ajoutez un cas dans `cmd/picoclaw/internal/auth/helpers.go` :
```go
case "your-provider":
authLoginYourProvider()
```
#### 6. Configurer via `config.json`
```json
{
"model_list": [
{
"model_name": "your-model",
"model": "your-provider/model-name",
"api_key": "your-api-key",
"api_base": "https://api.your-provider.com/v1"
}
]
}
```
---
## Tester votre implémentation
### Commandes CLI
```bash
# S'authentifier avec un fournisseur
picoclaw auth login --provider your-provider
# Lister les modèles (pour Antigravity)
picoclaw auth models
# Démarrer la passerelle
picoclaw gateway
# Exécuter un agent avec un modèle spécifique
picoclaw agent -m "Hello" --model your-model
```
### Variables d'environnement pour les tests
```bash
# Remplacer le modèle par défaut
export PICOCLAW_AGENTS_DEFAULTS_MODEL=your-model
# Remplacer les paramètres du fournisseur
export PICOCLAW_MODEL_LIST='[{"model_name":"your-model","model":"your-provider/model-name","api_key":"..."}]'
```
---
## Références
- **Fichiers source :**
- `pkg/providers/antigravity_provider.go` - Implémentation du fournisseur Antigravity
- `pkg/auth/oauth.go` - Implémentation du flux OAuth
- `pkg/auth/store.go` - Stockage des identifiants d'authentification (`~/.picoclaw/auth.json`)
- `pkg/providers/factory.go` - Factory des fournisseurs et routage de protocole
- `pkg/providers/types.go` - Définitions de l'interface fournisseur
- `cmd/picoclaw/internal/auth/helpers.go` - Commandes CLI d'authentification
- **Documentation :**
- `docs/ANTIGRAVITY_USAGE.md` - Guide d'utilisation d'Antigravity
- `docs/migration/model-list-migration.md` - Guide de migration
---
## Notes
1. **Projet Google Cloud :** Antigravity nécessite que Gemini for Google Cloud soit activé sur votre projet Google Cloud
2. **Quotas :** Utilise les quotas du projet Google Cloud (pas de facturation séparée)
3. **Accès aux modèles :** Les modèles disponibles dépendent de la configuration de votre projet Google Cloud
4. **Blocs de réflexion :** Les modèles Claude via Antigravity nécessitent un traitement spécial des blocs de réflexion avec signatures
5. **Assainissement des schémas :** Les schémas d'outils doivent être assainis pour supprimer les mots-clés JSON Schema non supportés
---
---
## Gestion des erreurs courantes
### 1. Limitation de débit (HTTP 429)
Antigravity retourne une erreur 429 lorsque les quotas du projet/modèle sont épuisés. La réponse d'erreur contient souvent un `quotaResetDelay` dans le champ `details`.
**Exemple d'erreur 429 :**
```json
{
"error": {
"code": 429,
"message": "You have exhausted your capacity on this model. Your quota will reset after 4h30m28s.",
"status": "RESOURCE_EXHAUSTED",
"details": [
{
"@type": "type.googleapis.com/google.rpc.ErrorInfo",
"metadata": {
"quotaResetDelay": "4h30m28.060903746s"
}
}
]
}
}
```
### 2. Réponses vides (modèles restreints)
Certains modèles peuvent apparaître dans la liste des modèles disponibles mais retourner une réponse vide (200 OK mais flux SSE vide). Cela se produit généralement pour les modèles en préversion ou restreints que le projet actuel n'a pas la permission d'utiliser.
**Traitement :** Traiter les réponses vides comme des erreurs informant l'utilisateur que le modèle pourrait être restreint ou invalide pour son projet.
---
## Dépannage
### "Token expired" (jeton expiré)
- Rafraîchir les jetons OAuth : `picoclaw auth login --provider antigravity`
### "Gemini for Google Cloud is not enabled" (Gemini for Google Cloud n'est pas activé)
- Activer l'API dans votre Google Cloud Console
### "Project not found" (projet non trouvé)
- Vérifier que votre projet Google Cloud a les API nécessaires activées
- Vérifier que l'ID du projet est correctement récupéré lors de l'authentification
### Les modèles n'apparaissent pas dans la liste
- Vérifier que l'authentification OAuth s'est terminée avec succès
- Vérifier le stockage du profil d'authentification : `~/.picoclaw/auth.json`
- Relancer `picoclaw auth login --provider antigravity`

View file

@ -0,0 +1,72 @@
> Retour au [README](../../README.fr.md)
# Utiliser le fournisseur Antigravity dans PicoClaw
Ce guide explique comment configurer et utiliser le fournisseur **Antigravity** (Google Cloud Code Assist) dans PicoClaw.
## Prérequis
1. Un compte Google.
2. Google Cloud Code Assist activé (généralement disponible via l'intégration « Gemini for Google Cloud »).
## 1. Authentification
Pour vous authentifier avec Antigravity, exécutez la commande suivante :
```bash
picoclaw auth login --provider antigravity
```
### Authentification manuelle (Headless/VPS)
Si vous exécutez PicoClaw sur un serveur (Coolify/Docker) et ne pouvez pas accéder à `localhost`, suivez ces étapes :
1. Exécutez la commande ci-dessus.
2. Copiez l'URL fournie et ouvrez-la dans votre navigateur local.
3. Complétez la connexion.
4. Votre navigateur sera redirigé vers une URL `localhost:51121` (qui ne se chargera pas).
5. **Copiez cette URL finale** depuis la barre d'adresse de votre navigateur.
6. **Collez-la dans le terminal** où PicoClaw attend.
PicoClaw extraira automatiquement le code d'autorisation et terminera le processus.
## 2. Gestion des modèles
### Lister les modèles disponibles
Pour voir quels modèles sont accessibles à votre projet et vérifier leurs quotas :
```bash
picoclaw auth models
```
### Changer de modèle
Vous pouvez modifier le modèle par défaut dans `~/.picoclaw/config.json` ou le remplacer via le CLI :
```bash
# Remplacer pour une seule commande
picoclaw agent -m "Hello" --model claude-opus-4-6-thinking
```
## 3. Utilisation en production (Coolify/Docker)
Si vous déployez via Coolify ou Docker, suivez ces étapes pour tester :
1. **Variables d'environnement** :
* `PICOCLAW_AGENTS_DEFAULTS_MODEL=gemini-flash`
2. **Persistance de l'authentification** :
Si vous vous êtes connecté localement, vous pouvez copier vos identifiants vers le serveur :
```bash
scp ~/.picoclaw/auth.json user@your-server:~/.picoclaw/
```
*Alternativement*, exécutez la commande `auth login` une fois sur le serveur si vous avez un accès terminal.
## 4. Dépannage
* **Réponse vide** : Si un modèle renvoie une réponse vide, il peut être restreint pour votre projet. Essayez `gemini-3-flash` ou `claude-opus-4-6-thinking`.
* **429 Limite de débit** : Antigravity a des quotas stricts. PicoClaw affichera le « temps de réinitialisation » dans le message d'erreur si vous atteignez une limite.
* **404 Non trouvé** : Assurez-vous d'utiliser un ID de modèle provenant de la liste `picoclaw auth models`. Utilisez l'ID court (par ex. `gemini-3-flash`) et non le chemin complet.
## 5. Résumé des modèles fonctionnels
D'après les tests, les modèles suivants sont les plus fiables :
* `gemini-3-flash` (Rapide, haute disponibilité)
* `gemini-2.5-flash-lite` (Léger)
* `claude-opus-4-6-thinking` (Puissant, inclut le raisonnement)

View file

@ -261,7 +261,7 @@ picoclaw gateway
picoclaw gateway
```
Pour toutes les options (`device_id`, `join_on_invite`, `group_trigger`, `placeholder`, `reasoning_channel_id`), voir le [Guide de Configuration du Canal Matrix](docs/channels/matrix/README.md).
Pour toutes les options (`device_id`, `join_on_invite`, `group_trigger`, `placeholder`, `reasoning_channel_id`), voir le [Guide de Configuration du Canal Matrix](channels/matrix/README.md).
</details>
@ -396,7 +396,7 @@ picoclaw gateway
**1. Créer un AI Bot**
* Allez dans la console d'administration WeCom → Gestion des applications → AI Bot
* Dans les paramètres du AI Bot, configurez l'URL de callback : `http://your-server:18791/webhook/wecom-aibot`
* Dans les paramètres du AI Bot, configurez l'URL de callback : `http://your-server:18790/webhook/wecom-aibot`
* Copiez **Token** et cliquez sur "Générer aléatoirement" pour **EncodingAESKey**
**2. Configurer**
@ -511,7 +511,7 @@ picoclaw gateway
"server": "irc.example.com:6697",
"nick": "picoclaw-bot",
"channel": "#your-channel",
"use_tls": true,
"tls": true,
"allow_from": []
}
}

View file

@ -0,0 +1,158 @@
> Retour au [README](../../README.fr.md)
# Chiffrement des identifiants
PicoClaw prend en charge le chiffrement des valeurs `api_key` dans les entrées de configuration `model_list`.
Les clés chiffrées sont stockées sous forme de chaînes `enc://<base64>` et déchiffrées automatiquement au démarrage.
---
## Démarrage rapide
**1. Définir votre phrase secrète**
```bash
export PICOCLAW_KEY_PASSPHRASE="your-passphrase"
```
**2. Chiffrer une clé API**
Exécutez `picoclaw onboard` — il vous demande votre phrase secrète et génère la clé SSH,
puis re-chiffre automatiquement toutes les entrées `api_key` en clair dans votre configuration
lors du prochain appel à `SaveConfig`. La valeur `enc://` résultante ressemblera à :
```
enc://AAAA...base64...
```
**3. Coller la sortie dans votre configuration**
```json
{
"model_list": [
{
"model_name": "gpt-4o",
"api_key": "enc://AAAA...base64...",
"api_base": "https://api.openai.com/v1"
}
]
}
```
---
## Formats `api_key` pris en charge
| Format | Exemple | Comportement |
|--------|---------|--------------|
| Texte clair | `sk-abc123` | Utilisé tel quel |
| Référence fichier | `file://openai.key` | Contenu lu depuis le même répertoire que le fichier de configuration |
| Chiffré | `enc://<base64>` | Déchiffré au démarrage avec `PICOCLAW_KEY_PASSPHRASE` |
| Vide | `""` | Transmis tel quel (utilisé avec `auth_method: oauth`) |
---
## Conception cryptographique
### Dérivation de clé
Le chiffrement utilise **HKDF-SHA256** avec une clé privée SSH comme second facteur.
```
sshHash = SHA256(ssh_private_key_file_bytes)
ikm = HMAC-SHA256(key=sshHash, message=passphrase)
aes_key = HKDF-SHA256(ikm, salt, info="picoclaw-credential-v1", 32 bytes)
```
### Chiffrement
```
AES-256-GCM(key=aes_key, nonce=random[12], plaintext=api_key)
```
### Format de transmission
```
enc://<base64( salt[16] + nonce[12] + ciphertext )>
```
| Champ | Taille | Description |
|-------|--------|-------------|
| `salt` | 16 octets | Aléatoire par chiffrement ; fourni à HKDF |
| `nonce` | 12 octets | Aléatoire par chiffrement ; IV AES-GCM |
| `ciphertext` | variable | Texte chiffré AES-256-GCM + tag d'authentification de 16 octets |
Le tag d'authentification GCM est automatiquement ajouté au texte chiffré. Toute altération provoque l'échec du déchiffrement avec une erreur plutôt que de retourner un texte clair corrompu.
### Performance
| Opération | Durée (ARM Cortex-A) |
|-----------|----------------------|
| Dérivation de clé (HKDF) | < 1 ms |
| Déchiffrement AES-256-GCM | < 1 ms |
| **Surcoût total au démarrage** | **< 2 ms par clé** |
---
## Sécurité à deux facteurs avec clé SSH
Lorsqu'une clé privée SSH est fournie, casser le chiffrement nécessite **les deux** :
1. La **phrase secrète** (`PICOCLAW_KEY_PASSPHRASE`)
2. Le **fichier de clé privée SSH**
Cela signifie qu'un fichier de configuration divulgué seul ne suffit pas pour récupérer la clé API, même si la phrase secrète est faible. La clé SSH apporte 256 bits d'entropie (Ed25519) indépendamment de la force de la phrase secrète.
### Modèle de menace
| Ce que l'attaquant possède | Peut-il déchiffrer ? |
|---------------------------|---------------------|
| Fichier de configuration uniquement | Non — nécessite la phrase secrète + la clé SSH |
| Clé SSH uniquement | Non — nécessite la phrase secrète |
| Phrase secrète uniquement | Non — nécessite la clé SSH |
| Fichier de configuration + clé SSH + phrase secrète | Oui — compromission totale |
---
## Variables d'environnement
| Variable | Requis | Description |
|----------|--------|-------------|
| `PICOCLAW_KEY_PASSPHRASE` | Oui (pour `enc://`) | Phrase secrète utilisée pour la dérivation de clé |
| `PICOCLAW_SSH_KEY_PATH` | Non | Chemin vers la clé privée SSH. Si non défini, détection automatique depuis `~/.ssh/picoclaw_ed25519.key` |
### Détection automatique de la clé SSH
Si `PICOCLAW_SSH_KEY_PATH` n'est pas défini, PicoClaw recherche la clé dédiée :
```
~/.ssh/picoclaw_ed25519.key
```
Ce fichier dédié évite les conflits avec les clés SSH existantes de l'utilisateur.
Exécutez `picoclaw onboard` pour le générer automatiquement.
`os.UserHomeDir()` est utilisé pour la résolution multiplateforme du répertoire personnel (lit `USERPROFILE` sous Windows, `HOME` sous Unix/macOS).
> **Remarque :** Un fichier de clé SSH est requis pour le chiffrement des identifiants. Si aucune clé n'est trouvée et que `PICOCLAW_SSH_KEY_PATH` n'est pas défini, le chiffrement/déchiffrement échouera. Exécutez `picoclaw onboard` pour générer la clé automatiquement.
---
## Migration
Étant donné que les seuls éléments secrets sont `PICOCLAW_KEY_PASSPHRASE` et le fichier de clé privée SSH, la migration est simple :
1. Copiez le fichier de configuration sur la nouvelle machine.
2. Définissez `PICOCLAW_KEY_PASSPHRASE` avec la même valeur.
3. Copiez le fichier de clé privée SSH au même chemin (ou définissez `PICOCLAW_SSH_KEY_PATH` vers son nouvel emplacement).
Aucun re-chiffrement n'est nécessaire.
---
## Considérations de sécurité
- **La phrase secrète et la clé SSH sont toutes deux requises.** La clé SSH agit comme un second facteur — sans elle, le chiffrement/déchiffrement échouera. Exécutez `picoclaw onboard` pour générer la clé si elle n'existe pas.
- **La clé SSH est en lecture seule à l'exécution.** PicoClaw n'écrit ni ne modifie jamais le fichier de clé SSH.
- **Les clés en texte clair restent prises en charge.** Les configurations existantes sans `enc://` ne sont pas affectées.
- **Le format `enc://` est versionné** via le champ `info` de HKDF (`picoclaw-credential-v1`), permettant de futures mises à niveau d'algorithme sans casser les valeurs chiffrées existantes.

36
docs/fr/debug.md Normal file
View file

@ -0,0 +1,36 @@
# Débogage de PicoClaw
> Retour au [README](../../README.fr.md)
PicoClaw effectue de multiples interactions complexes en arrière-plan pour chaque requête qu'il reçoit — du routage des messages et de l'évaluation de la complexité, à l'exécution des outils et à l'adaptation aux défaillances de modèle. Pouvoir voir exactement ce qui se passe est crucial, non seulement pour résoudre les problèmes potentiels, mais aussi pour véritablement comprendre le fonctionnement de l'agent.
## Démarrer PicoClaw en mode débogage
Pour obtenir des informations détaillées sur ce que fait l'agent (requêtes LLM, appels d'outils, routage des messages), vous pouvez démarrer la passerelle PicoClaw avec le drapeau de débogage :
```bash
picoclaw gateway --debug
# or
picoclaw gateway -d
```
Dans ce mode, le système formate les logs de manière détaillée et affiche des aperçus des prompts système et des résultats d'exécution des outils.
## Désactiver la troncature des logs (logs complets)
Par défaut, PicoClaw tronque les chaînes très longues (comme le *Prompt Système* ou les résultats JSON volumineux) dans les logs de débogage afin de garder la console lisible.
Si vous avez besoin d'inspecter la sortie complète d'une commande ou le payload exact envoyé au modèle LLM, vous pouvez utiliser le drapeau `--no-truncate`.
**Remarque :** Ce drapeau fonctionne *uniquement* en combinaison avec le mode `--debug`.
```bash
picoclaw gateway --debug --no-truncate
```
Lorsque ce drapeau est actif, la fonction de troncature globale est désactivée. Cela est extrêmement utile pour :
* Vérifier la syntaxe exacte des messages envoyés au fournisseur.
* Lire la sortie complète d'outils comme `exec`, `web_fetch` ou `read_file`.
* Déboguer l'historique de session sauvegardé en mémoire.

View file

@ -0,0 +1,152 @@
> Retour au [README](../../README.fr.md)
# 🖥️ PicoClaw Liste de compatibilité matérielle
PicoClaw fonctionne sur pratiquement n'importe quel appareil Linux. Cette page répertorie les puces, produits et cartes de développement vérifiés.
**Votre matériel n'est pas listé ?** Soumettez une PR pour l'ajouter ! Les fabricants de matériel sont invités à contribuer et à co-promouvoir.
---
## 1. Support de puces vérifié
### x86
| Fabricant | Puce | Notes |
|-----------|------|-------|
| Intel | Any x86 CPU (i386+) | Tous les processeurs de bureau/serveur/portable |
| AMD | Any x86 CPU | Tous les processeurs de bureau/serveur/portable |
### ARM
| Sous-arch | Puces typiques | Notes |
|-----------|----------------|-------|
| ARMv6 | [BCM2835](https://www.raspberrypi.com/documentation/computers/processors.html#bcm2835) (Raspberry Pi 1/Zero) | Monocœur ARM1176JZF-S |
| ARMv7 | [Allwinner V3s](https://linux-sunxi.org/V3s) | Monocœur Cortex-A7, utilisé dans LicheePi Zero |
| ARM64 | [Allwinner H618](https://linux-sunxi.org/H618) | Quadricœur Cortex-A53, utilisé dans Orange Pi Zero 3 |
| ARM64 | [BCM2711](https://www.raspberrypi.com/documentation/computers/processors.html#bcm2711) (Raspberry Pi 4) | Quadricœur Cortex-A72 |
| ARM64 | [BCM2712](https://www.raspberrypi.com/documentation/computers/processors.html#bcm2712) (Raspberry Pi 5) | Quadricœur Cortex-A76 |
| ARM64 | [AX630C](https://www.axera-tech.com/) (爱芯元智) | Bicœur Cortex-A53 + NPU, utilisé dans NanoKVM-Pro / MaixCAM2 |
### RISC-V (riscv64)
| Fabricant | Puce | Cœur | Notes |
|-----------|------|------|-------|
| [SOPHGO (算能)](https://www.sophgo.com/) | SG2002 | C906 @ 1GHz | 256MB DDR3 intégré, utilisé dans LicheeRV-Nano / NanoKVM / MaixCAM |
| [Allwinner (全志)](https://www.allwinnertech.com/) | V861 | Dual C907 | 128MB DDR3L intégré, 1 TOPS NPU, caméra AI 4K SiP |
| [Allwinner (全志)](https://www.allwinnertech.com/) | V881 | C907 | Série de caméras AI RISC-V |
| [Arterytek (匠芯创)](https://www.arterytek.com/) | D213 | RISC-V | Utilisé dans HaaS506-LD1 RTU industriel |
| [SpacemiT (进迭)](https://www.spacemit.com/) | K1 | 8x X60 @ 1.8GHz | Utilisé dans Milk-V Jupiter, BananaPi BPI-F3 |
| [SpacemiT (进迭)](https://www.spacemit.com/) | K3 | 8x X100 @ 2.5GHz | Conforme RVA23, RVV 1024 bits, inférence AI FP8 |
| [Zhihe (知合)](https://www.zhihe-tech.com/) | A210 | High-perf RISC-V | 8 cœurs, 16MB cache L3, classe bureau |
| [Canaan (嘉楠)](https://www.canaan-creative.com/) | K230 | Dual C908 @ 1.6GHz | 6 TOPS KPU, utilisé dans CanMV-K230 |
### MIPS
| Fabricant | Puce | Notes |
|-----------|------|-------|
| MediaTek | [MT7620](https://www.mediatek.com/products/home-networking/mt7620) | MIPS24KEc @ 580MHz, utilisé dans de nombreux routeurs OpenWrt (ex. Xiaomi Router 3G) |
### LoongArch (loong64)
| Fabricant | Puce | Notes |
|-----------|------|-------|
| [Loongson (龙芯)](https://www.loongson.cn/) | 3A5000 | Quadricœur LA464 @ 2.5GHz, bureau/station de travail |
| [Loongson (龙芯)](https://www.loongson.cn/) | 3A6000 | Quadricœur 4C/8T @ 2.5GHz, IPC comparable à Intel 10e génération |
| [Loongson (龙芯)](https://www.loongson.cn/) | 2K1000LA | Bicœur @ 1GHz, applications industrielles/IoT |
---
## 2. Produits vérifiés (par date de sortie)
Produits grand public, routeurs et appareils industriels testés avec PicoClaw.
| Année | Produit | Arch | SoC | RAM | Catégorie |
|-------|---------|------|-----|-----|-----------|
| 2009 | Nokia N900 | ARM (A8) | OMAP3430 | 256MB | Smartphone |
| 2012 | Samsung Galaxy Note 10.1 (N8000) | ARM (A9) | Exynos 4412 | 2GB | Tablette |
| 2016 | Xiaomi Router 3G (小米路由器3G) | MIPS | MT7620 | 256MB | Routeur (OpenWrt) |
| 2018 | Phicomm N1 (斐讯N1) | ARM64 (A53) | S905D | 2GB | Boîtier TV / Serveur domestique |
| 2019 | Xiaomi AI Speaker (小爱音箱) | ARM64 (A53) | — | 256MB | Enceinte connectée |
| 2024 | [NanoKVM](https://wiki.sipeed.com/hardware/en/kvm/NanoKVM/introduction.html) | RISC-V | SG2002 | 256MB | IP-KVM |
| 2025 | HaaS506-LD1 | RISC-V | D213 | 128MB | RTU industriel |
| 2025 | [NanoKVM-Pro](https://wiki.sipeed.com/hardware/en/kvm/NanoKVM_Pro/introduction.html) | ARM64 (A53) | AX630C | 1GB | IP-KVM Pro |
| 2026 | [MaixCAM2](https://wiki.sipeed.com/hardware/en/maixcam/index.html) | ARM64 (A53) | AX630C | 1/4GB | Caméra AI 4K |
---
## 3. Cartes de développement vérifiées (par date de sortie)
| Année | Carte | Arch | SoC | RAM | Lien d'achat |
|-------|-------|------|-----|-----|--------------|
| 2012 | [Raspberry Pi 1 Model B](https://www.raspberrypi.com/products/) | ARMv6 | BCM2835 | 512MB | — |
| 2015 | [Raspberry Pi 2 Model B](https://www.raspberrypi.com/products/raspberry-pi-2-model-b/) | ARMv7 (A7) | BCM2836 | 1GB | — |
| 2015 | [Raspberry Pi Zero](https://www.raspberrypi.com/products/raspberry-pi-zero/) | ARMv6 | BCM2835 | 512MB | — |
| 2016 | [Raspberry Pi 3 Model B](https://www.raspberrypi.com/products/raspberry-pi-3-model-b/) | ARM64 (A53) | BCM2837 | 1GB | — |
| 2017 | [LicheePi Zero](https://wiki.sipeed.com/hardware/en/lichee/Zero/Zero.html) | ARMv7 (A7) | Allwinner V3s | 64MB | [Sipeed](https://sipeed.com/) |
| 2019 | [Raspberry Pi 4 Model B](https://www.raspberrypi.com/products/raspberry-pi-4-model-b/) | ARM64 (A72) | BCM2711 | 1~8GB | [RPi](https://www.raspberrypi.com/) |
| 2023 | [Raspberry Pi 5](https://www.raspberrypi.com/products/raspberry-pi-5/) | ARM64 (A76) | BCM2712 | 2~8GB | [RPi](https://www.raspberrypi.com/) |
| 2024 | [LicheeRV-Nano](https://wiki.sipeed.com/hardware/en/lichee/RV_Nano/1_intro.html) | RISC-V | SG2002 | 256MB | [AliExpress](https://www.aliexpress.com/item/1005006519668532.html) |
| 2024 | [MaixCAM-Pro](https://wiki.sipeed.com/hardware/en/maixcam/index.html) | RISC-V | SG2002 | 256MB | [Sipeed](https://sipeed.com/) |
| 2024 | [Milk-V Duo 64M](https://milkv.io/docs/duo/getting-started/duo) | RISC-V | CV1800B | 64MB | [Milk-V](https://milkv.io/) |
| 2024 | [CanMV-K230](https://developer.canaan-creative.com/k230_canmv/en/main/) | RISC-V | K230 | 512MB | [Canaan](https://www.canaan-creative.com/) |
---
## 4. Fonctionne également sur
### Téléphones Android (via Termux)
Tout téléphone Android ARM64 (2015+) avec 1 Go+ de RAM. Installez [Termux](https://github.com/termux/termux-app), utilisez `proot` pour exécuter PicoClaw.
> Voir [README : Exécuter sur d'anciens téléphones Android](../README.md#-run-on-old-android-phones) pour les instructions de configuration.
### Bureau / Serveur / Cloud
| Plateforme | Notes |
|------------|-------|
| x86_64 Linux | Binaire natif, aucune dépendance |
| x86_64 Windows | Binaire natif |
| macOS (Intel / Apple Silicon) | Binaire natif |
| Docker (any platform) | `docker compose` en une ligne, voir [Guide Docker](docker.md) |
| OpenWrt routers | Builds MIPS/ARM, nécessite >32 Mo de RAM libre |
| FreeBSD / NetBSD | Builds x86_64 et arm64 disponibles |
---
## 5. Configuration minimale requise
| Ressource | Minimum | Recommandé |
|-----------|---------|------------|
| RAM | 10 Mo libres | 32 Mo+ libres |
| Stockage | 20 Mo (binaire) | 50 Mo+ (avec espace de travail) |
| CPU | N'importe lequel (monocœur 0,6 GHz+) | — |
| OS | Linux (kernel 3.x+) | Linux 5.x+ |
| Réseau | Requis (pour les appels API LLM) | Ethernet ou WiFi |
---
## 6. Comment tester et contribuer
```bash
# 1. Télécharger pour votre architecture
wget https://github.com/sipeed/picoclaw/releases/latest/download/picoclaw_Linux_arm64.tar.gz
tar xzf picoclaw_Linux_arm64.tar.gz
# 2. Initialiser
./picoclaw onboard
# 3. Tester
./picoclaw agent -m "Hello, what board am I running on?"
```
Builds disponibles : `linux-amd64`, `linux-arm64`, `linux-arm`, `linux-riscv64`, `linux-loong64`, `linux-mipsle`
### Ajouter votre matériel
1. Forkez ce dépôt
2. Ajoutez votre puce / produit / carte dans le tableau approprié
3. Incluez : nom, architecture, SoC, RAM, année et un lien si disponible
4. Soumettez une PR
Fabricants de matériel : vous souhaitez ajouter un support officiel ou co-promouvoir ? Ouvrez une issue ou contactez-nous via [Discord](https://discord.gg/V4sAZ9XWpN).

View file

@ -16,7 +16,7 @@
**Correction :** Dans `~/.picoclaw/config.json` (ou votre chemin de configuration) :
1. **agents.defaults.model** doit correspondre à un `model_name` dans `model_list` (par ex. `"openrouter-free"`).
1. **agents.defaults.model_name** doit correspondre à un `model_name` dans `model_list` (par ex. `"openrouter-free"`).
2. Le **model** de cette entrée doit être un identifiant de modèle OpenRouter valide, par exemple :
- `"openrouter/free"` niveau gratuit automatique
- `"google/gemini-2.0-flash-exp:free"`
@ -28,7 +28,7 @@ Exemple :
{
"agents": {
"defaults": {
"model": "openrouter-free"
"model_name": "openrouter-free"
}
},
"model_list": [

View file

@ -0,0 +1,150 @@
# 🖥️ PicoClaw Hardware Compatibility List
PicoClaw runs on virtually any Linux device. This page tracks verified chips, products, and development boards.
**Your hardware not listed?** Submit a PR to add it! Hardware vendors are welcome to contribute and co-promote.
---
## 1. Verified Chip Support
### x86
| Vendor | Chip | Notes |
|--------|------|-------|
| Intel | Any x86 CPU (i386+) | All desktop/server/laptop processors |
| AMD | Any x86 CPU | All desktop/server/laptop processors |
### ARM
| Sub-arch | Typical Chips | Notes |
|----------|--------------|-------|
| ARMv6 | [BCM2835](https://www.raspberrypi.com/documentation/computers/processors.html#bcm2835) (Raspberry Pi 1/Zero) | Single-core ARM1176JZF-S |
| ARMv7 | [Allwinner V3s](https://linux-sunxi.org/V3s) | Single-core Cortex-A7, used in LicheePi Zero |
| ARM64 | [Allwinner H618](https://linux-sunxi.org/H618) | Quad-core Cortex-A53, used in Orange Pi Zero 3 |
| ARM64 | [BCM2711](https://www.raspberrypi.com/documentation/computers/processors.html#bcm2711) (Raspberry Pi 4) | Quad-core Cortex-A72 |
| ARM64 | [BCM2712](https://www.raspberrypi.com/documentation/computers/processors.html#bcm2712) (Raspberry Pi 5) | Quad-core Cortex-A76 |
| ARM64 | [AX630C](https://www.axera-tech.com/) (爱芯元智) | Dual-core Cortex-A53 + NPU, used in NanoKVM-Pro / MaixCAM2 |
### RISC-V (riscv64)
| Vendor | Chip | Core | Notes |
|--------|------|------|-------|
| [SOPHGO (算能)](https://www.sophgo.com/) | SG2002 | C906 @ 1GHz | 256MB DDR3 on-chip, used in LicheeRV-Nano / NanoKVM / MaixCAM |
| [Allwinner (全志)](https://www.allwinnertech.com/) | V861 | Dual C907 | 128MB DDR3L on-chip, 1 TOPS NPU, 4K AI camera SiP |
| [Allwinner (全志)](https://www.allwinnertech.com/) | V881 | C907 | RISC-V AI camera series |
| [Arterytek (匠芯创)](https://www.arterytek.com/) | D213 | RISC-V | Used in HaaS506-LD1 industrial RTU |
| [SpacemiT (进迭)](https://www.spacemit.com/) | K1 | 8x X60 @ 1.8GHz | Used in Milk-V Jupiter, BananaPi BPI-F3 |
| [SpacemiT (进迭)](https://www.spacemit.com/) | K3 | 8x X100 @ 2.5GHz | RVA23 compliant, 1024-bit RVV, FP8 AI inference |
| [Zhihe (知合)](https://www.zhihe-tech.com/) | A210 | High-perf RISC-V | 8-core, 16MB L3 cache, desktop-class |
| [Canaan (嘉楠)](https://www.canaan-creative.com/) | K230 | Dual C908 @ 1.6GHz | 6 TOPS KPU, used in CanMV-K230 |
### MIPS
| Vendor | Chip | Notes |
|--------|------|-------|
| MediaTek | [MT7620](https://www.mediatek.com/products/home-networking/mt7620) | MIPS24KEc @ 580MHz, used in many OpenWrt routers (e.g. Xiaomi Router 3G) |
### LoongArch (loong64)
| Vendor | Chip | Notes |
|--------|------|-------|
| [Loongson (龙芯)](https://www.loongson.cn/) | 3A5000 | Quad-core LA464 @ 2.5GHz, desktop/workstation |
| [Loongson (龙芯)](https://www.loongson.cn/) | 3A6000 | Quad-core 4C/8T @ 2.5GHz, IPC comparable to Intel 10th gen |
| [Loongson (龙芯)](https://www.loongson.cn/) | 2K1000LA | Dual-core @ 1GHz, industrial/IoT applications |
---
## 2. Verified Products (by release date)
Consumer products, routers, and industrial devices that have been tested with PicoClaw.
| Year | Product | Arch | SoC | RAM | Category |
|------|---------|------|-----|-----|----------|
| 2009 | Nokia N900 | ARM (A8) | OMAP3430 | 256MB | Smartphone |
| 2012 | Samsung Galaxy Note 10.1 (N8000) | ARM (A9) | Exynos 4412 | 2GB | Tablet |
| 2016 | Xiaomi Router 3G (小米路由器3G) | MIPS | MT7620 | 256MB | Router (OpenWrt) |
| 2018 | Phicomm N1 (斐讯N1) | ARM64 (A53) | S905D | 2GB | TV Box / Home Server |
| 2019 | Xiaomi AI Speaker (小爱音箱) | ARM64 (A53) | — | 256MB | Smart Speaker |
| 2024 | [NanoKVM](https://wiki.sipeed.com/hardware/en/kvm/NanoKVM/introduction.html) | RISC-V | SG2002 | 256MB | IP-KVM |
| 2025 | HaaS506-LD1 | RISC-V | D213 | 128MB | Industrial RTU |
| 2025 | [NanoKVM-Pro](https://wiki.sipeed.com/hardware/en/kvm/NanoKVM_Pro/introduction.html) | ARM64 (A53) | AX630C | 1GB | Pro IP-KVM |
| 2026 | [MaixCAM2](https://wiki.sipeed.com/hardware/en/maixcam/index.html) | ARM64 (A53) | AX630C | 1/4GB | 4K AI Camera |
---
## 3. Verified Development Boards (by release date)
| Year | Board | Arch | SoC | RAM | Buy Link |
|------|-------|------|-----|-----|----------|
| 2012 | [Raspberry Pi 1 Model B](https://www.raspberrypi.com/products/) | ARMv6 | BCM2835 | 512MB | — |
| 2015 | [Raspberry Pi 2 Model B](https://www.raspberrypi.com/products/raspberry-pi-2-model-b/) | ARMv7 (A7) | BCM2836 | 1GB | — |
| 2015 | [Raspberry Pi Zero](https://www.raspberrypi.com/products/raspberry-pi-zero/) | ARMv6 | BCM2835 | 512MB | — |
| 2016 | [Raspberry Pi 3 Model B](https://www.raspberrypi.com/products/raspberry-pi-3-model-b/) | ARM64 (A53) | BCM2837 | 1GB | — |
| 2017 | [LicheePi Zero](https://wiki.sipeed.com/hardware/en/lichee/Zero/Zero.html) | ARMv7 (A7) | Allwinner V3s | 64MB | [Sipeed](https://sipeed.com/) |
| 2019 | [Raspberry Pi 4 Model B](https://www.raspberrypi.com/products/raspberry-pi-4-model-b/) | ARM64 (A72) | BCM2711 | 1~8GB | [RPi](https://www.raspberrypi.com/) |
| 2023 | [Raspberry Pi 5](https://www.raspberrypi.com/products/raspberry-pi-5/) | ARM64 (A76) | BCM2712 | 2~8GB | [RPi](https://www.raspberrypi.com/) |
| 2024 | [LicheeRV-Nano](https://wiki.sipeed.com/hardware/en/lichee/RV_Nano/1_intro.html) | RISC-V | SG2002 | 256MB | [AliExpress](https://www.aliexpress.com/item/1005006519668532.html) |
| 2024 | [MaixCAM-Pro](https://wiki.sipeed.com/hardware/en/maixcam/index.html) | RISC-V | SG2002 | 256MB | [Sipeed](https://sipeed.com/) |
| 2024 | [Milk-V Duo 64M](https://milkv.io/docs/duo/getting-started/duo) | RISC-V | CV1800B | 64MB | [Milk-V](https://milkv.io/) |
| 2024 | [CanMV-K230](https://developer.canaan-creative.com/k230_canmv/en/main/) | RISC-V | K230 | 512MB | [Canaan](https://www.canaan-creative.com/) |
---
## 4. Also Works On
### Android Phones (via Termux)
Any ARM64 Android phone (2015+) with 1GB+ RAM. Install [Termux](https://github.com/termux/termux-app), use `proot` to run PicoClaw.
> See [README: Run on old Android Phones](../README.md#-run-on-old-android-phones) for setup instructions.
### Desktop / Server / Cloud
| Platform | Notes |
|----------|-------|
| x86_64 Linux | Native binary, no dependencies |
| x86_64 Windows | Native binary |
| macOS (Intel / Apple Silicon) | Native binary |
| Docker (any platform) | `docker compose` one-liner, see [Docker Guide](docker.md) |
| OpenWrt routers | MIPS/ARM builds, requires >32MB free RAM |
| FreeBSD / NetBSD | x86_64 and arm64 builds available |
---
## 5. Minimum Requirements
| Resource | Minimum | Recommended |
|----------|---------|-------------|
| RAM | 10MB free | 32MB+ free |
| Storage | 20MB (binary) | 50MB+ (with workspace) |
| CPU | Any (single core 0.6GHz+) | — |
| OS | Linux (kernel 3.x+) | Linux 5.x+ |
| Network | Required (for LLM API calls) | Ethernet or WiFi |
---
## 6. How to Test & Contribute
```bash
# 1. Download for your architecture
wget https://github.com/sipeed/picoclaw/releases/latest/download/picoclaw_Linux_arm64.tar.gz
tar xzf picoclaw_Linux_arm64.tar.gz
# 2. Initialize
./picoclaw onboard
# 3. Test
./picoclaw agent -m "Hello, what board am I running on?"
```
Available builds: `linux-amd64`, `linux-arm64`, `linux-arm`, `linux-riscv64`, `linux-loong64`, `linux-mipsle`
### Add Your Hardware
1. Fork this repo
2. Add your chip / product / board to the appropriate table
3. Include: name, arch, SoC, RAM, year, and a link if available
4. Submit a PR
Hardware vendors: want to add official support or co-promote? Open an issue or reach out via [Discord](https://discord.gg/V4sAZ9XWpN).

809
docs/ja/ANTIGRAVITY_AUTH.md Normal file
View file

@ -0,0 +1,809 @@
> [README](../../README.ja.md) に戻る
# Antigravity 認証・統合ガイド
## 概要
**Antigravity**Google Cloud Code Assistは、Google が提供する AI モデルプロバイダーで、Google のクラウドインフラストラクチャを通じて Claude Opus 4.6 や Gemini などのモデルへのアクセスを提供します。本ドキュメントでは、認証の仕組み、モデルの取得方法、PicoClaw での新しいプロバイダーの実装方法について完全なガイドを提供します。
---
## 目次
1. [認証フロー](#認証フロー)
2. [OAuth 実装の詳細](#oauth-実装の詳細)
3. [トークン管理](#トークン管理)
4. [モデルリストの取得](#モデルリストの取得)
5. [使用量トラッキング](#使用量トラッキング)
6. [プロバイダープラグイン構造](#プロバイダープラグイン構造)
7. [統合要件](#統合要件)
8. [API エンドポイント](#api-エンドポイント)
9. [設定](#設定)
10. [PicoClaw での新しいプロバイダーの作成](#picoclaw-での新しいプロバイダーの作成)
---
## 認証フロー
### 1. PKCE 付き OAuth 2.0
Antigravity はセキュアな認証のために **OAuth 2.0 with PKCEProof Key for Code Exchange** を使用します:
```
┌─────────────┐ ┌─────────────────┐
│ Client │ ───(1) Generate PKCE Pair────────> │ │
│ │ ───(2) Open Auth URL─────────────> │ Google OAuth │
│ │ │ Server │
│ │ <──(3) Redirect with Code───────── │ │
│ │ └─────────────────┘
│ │ ───(4) Exchange Code for Tokens──> │ Token URL │
│ │ │ │
│ │ <──(5) Access + Refresh Tokens──── │ │
└─────────────┘ └─────────────────┘
```
### 2. 詳細手順
#### ステップ 1PKCE パラメータの生成
```typescript
function generatePkce(): { verifier: string; challenge: string } {
const verifier = randomBytes(32).toString("hex");
const challenge = createHash("sha256").update(verifier).digest("base64url");
return { verifier, challenge };
}
```
#### ステップ 2認可 URL の構築
```typescript
const AUTH_URL = "https://accounts.google.com/o/oauth2/v2/auth";
const REDIRECT_URI = "http://localhost:51121/oauth-callback";
function buildAuthUrl(params: { challenge: string; state: string }): string {
const url = new URL(AUTH_URL);
url.searchParams.set("client_id", CLIENT_ID);
url.searchParams.set("response_type", "code");
url.searchParams.set("redirect_uri", REDIRECT_URI);
url.searchParams.set("scope", SCOPES.join(" "));
url.searchParams.set("code_challenge", params.challenge);
url.searchParams.set("code_challenge_method", "S256");
url.searchParams.set("state", params.state);
url.searchParams.set("access_type", "offline");
url.searchParams.set("prompt", "consent");
return url.toString();
}
```
**必要なスコープ:**
```typescript
const SCOPES = [
"https://www.googleapis.com/auth/cloud-platform",
"https://www.googleapis.com/auth/userinfo.email",
"https://www.googleapis.com/auth/userinfo.profile",
"https://www.googleapis.com/auth/cclog",
"https://www.googleapis.com/auth/experimentsandconfigs",
];
```
#### ステップ 3OAuth コールバックの処理
**自動モード(ローカル開発):**
- ポート 51121 でローカル HTTP サーバーを起動
- Google からのリダイレクトを待機
- クエリパラメータから認可コードを抽出
**手動モード(リモート/ヘッドレス):**
- ユーザーに認可 URL を表示
- ユーザーがブラウザで認証を完了
- ユーザーが完全なリダイレクト URL をターミナルに貼り付け
- 貼り付けられた URL からコードを解析
#### ステップ 4コードをトークンに交換
```typescript
const TOKEN_URL = "https://oauth2.googleapis.com/token";
async function exchangeCode(params: {
code: string;
verifier: string;
}): Promise<{ access: string; refresh: string; expires: number }> {
const response = await fetch(TOKEN_URL, {
method: "POST",
headers: { "Content-Type": "application/x-www-form-urlencoded" },
body: new URLSearchParams({
client_id: CLIENT_ID,
client_secret: CLIENT_SECRET,
code: params.code,
grant_type: "authorization_code",
redirect_uri: REDIRECT_URI,
code_verifier: params.verifier,
}),
});
const data = await response.json();
return {
access: data.access_token,
refresh: data.refresh_token,
expires: Date.now() + data.expires_in * 1000 - 5 * 60 * 1000, // 5 min buffer
};
}
```
#### ステップ 5追加のユーザーデータの取得
**ユーザーメール:**
```typescript
async function fetchUserEmail(accessToken: string): Promise<string | undefined> {
const response = await fetch(
"https://www.googleapis.com/oauth2/v1/userinfo?alt=json",
{ headers: { Authorization: `Bearer ${accessToken}` } }
);
const data = await response.json();
return data.email;
}
```
**プロジェクト IDAPI 呼び出しに必須):**
```typescript
async function fetchProjectId(accessToken: string): Promise<string> {
const headers = {
Authorization: `Bearer ${accessToken}`,
"Content-Type": "application/json",
"User-Agent": "google-api-nodejs-client/9.15.1",
"X-Goog-Api-Client": "google-cloud-sdk vscode_cloudshelleditor/0.1",
"Client-Metadata": JSON.stringify({
ideType: "IDE_UNSPECIFIED",
platform: "PLATFORM_UNSPECIFIED",
pluginType: "GEMINI",
}),
};
const response = await fetch(
"https://cloudcode-pa.googleapis.com/v1internal:loadCodeAssist",
{
method: "POST",
headers,
body: JSON.stringify({
metadata: {
ideType: "IDE_UNSPECIFIED",
platform: "PLATFORM_UNSPECIFIED",
pluginType: "GEMINI",
},
}),
}
);
const data = await response.json();
return data.cloudaicompanionProject || "rising-fact-p41fc"; // デフォルトのフォールバック
}
```
---
## OAuth 実装の詳細
### クライアント認証情報
**重要:** これらは pi-ai との同期のためにソースコード内で base64 エンコードされています:
```typescript
const decode = (s: string) => Buffer.from(s, "base64").toString();
const CLIENT_ID = decode(
"MTA3MTAwNjA2MDU5MS10bWhzc2luMmgyMWxjcmUyMzV2dG9sb2poNGc0MDNlcC5hcHBzLmdvb2dsZXVzZXJjb250ZW50LmNvbQ=="
);
const CLIENT_SECRET = decode("R09DU1BYLUs1OEZXUjQ4NkxkTEoxbUxCOHNYQzR6NnFEQWY=");
```
### OAuth フローモード
1. **自動フロー**(ブラウザのあるローカルマシン):
- ブラウザを自動的に開く
- ローカルコールバックサーバーがリダイレクトをキャプチャ
- 初回認証後はユーザー操作不要
2. **手動フロー**(リモート/ヘッドレス/WSL2
- 手動コピー&ペースト用の URL を表示
- ユーザーが外部ブラウザで認証を完了
- ユーザーが完全なリダイレクト URL を貼り付け
```typescript
function shouldUseManualOAuthFlow(isRemote: boolean): boolean {
return isRemote || isWSL2Sync();
}
```
---
## トークン管理
### 認証プロファイル構造
```typescript
type OAuthCredential = {
type: "oauth";
provider: "google-antigravity";
access: string; // アクセストークン
refresh: string; // リフレッシュトークン
expires: number; // 有効期限タイムスタンプ(エポックからのミリ秒)
email?: string; // ユーザーメール
projectId?: string; // Google Cloud プロジェクト ID
};
```
### トークンの更新
認証情報にはリフレッシュトークンが含まれており、現在のアクセストークンが期限切れになった際に新しいアクセストークンを取得するために使用できます。有効期限は競合状態を防ぐために 5 分のバッファを設けています。
---
## モデルリストの取得
### 利用可能なモデルの取得
```typescript
const BASE_URL = "https://cloudcode-pa.googleapis.com";
async function fetchAvailableModels(
accessToken: string,
projectId: string
): Promise<Model[]> {
const headers = {
Authorization: `Bearer ${accessToken}`,
"Content-Type": "application/json",
"User-Agent": "antigravity",
"X-Goog-Api-Client": "google-cloud-sdk vscode_cloudshelleditor/0.1",
};
const response = await fetch(
`${BASE_URL}/v1internal:fetchAvailableModels`,
{
method: "POST",
headers,
body: JSON.stringify({ project: projectId }),
}
);
const data = await response.json();
// クォータ情報付きのモデルを返す
return Object.entries(data.models).map(([modelId, modelInfo]) => ({
id: modelId,
displayName: modelInfo.displayName,
quotaInfo: {
remainingFraction: modelInfo.quotaInfo?.remainingFraction,
resetTime: modelInfo.quotaInfo?.resetTime,
isExhausted: modelInfo.quotaInfo?.isExhausted,
},
}));
}
```
### レスポンス形式
```typescript
type FetchAvailableModelsResponse = {
models?: Record<string, {
displayName?: string;
quotaInfo?: {
remainingFraction?: number | string;
resetTime?: string; // ISO 8601 タイムスタンプ
isExhausted?: boolean;
};
}>;
};
```
---
## 使用量トラッキング
### 使用量データの取得
```typescript
export async function fetchAntigravityUsage(
token: string,
timeoutMs: number
): Promise<ProviderUsageSnapshot> {
// 1. クレジットとプラン情報を取得
const loadCodeAssistRes = await fetch(
`${BASE_URL}/v1internal:loadCodeAssist`,
{
method: "POST",
headers: {
Authorization: `Bearer ${token}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
metadata: {
ideType: "ANTIGRAVITY",
platform: "PLATFORM_UNSPECIFIED",
pluginType: "GEMINI",
},
}),
}
);
// クレジット情報を抽出
const { availablePromptCredits, planInfo, currentTier } = data;
// 2. モデルクォータを取得
const modelsRes = await fetch(
`${BASE_URL}/v1internal:fetchAvailableModels`,
{
method: "POST",
headers: { Authorization: `Bearer ${token}` },
body: JSON.stringify({ project: projectId }),
}
);
// 使用量ウィンドウを構築
return {
provider: "google-antigravity",
displayName: "Google Antigravity",
windows: [
{ label: "Credits", usedPercent: calculateUsedPercent(available, monthly) },
// 個別モデルクォータ...
],
plan: currentTier?.name || planType,
};
}
```
### 使用量レスポンス構造
```typescript
type ProviderUsageSnapshot = {
provider: "google-antigravity";
displayName: string;
windows: UsageWindow[];
plan?: string;
error?: string;
};
type UsageWindow = {
label: string; // "Credits" またはモデル ID
usedPercent: number; // 0-100
resetAt?: number; // クォータがリセットされるタイムスタンプ
};
```
---
## プロバイダープラグイン構造
### プラグイン定義
```typescript
const antigravityPlugin = {
id: "google-antigravity-auth",
name: "Google Antigravity Auth",
description: "OAuth flow for Google Antigravity (Cloud Code Assist)",
configSchema: emptyPluginConfigSchema(),
register(api: PicoClawPluginApi) {
api.registerProvider({
id: "google-antigravity",
label: "Google Antigravity",
docsPath: "/providers/models",
aliases: ["antigravity"],
auth: [
{
id: "oauth",
label: "Google OAuth",
hint: "PKCE + localhost callback",
kind: "oauth",
run: async (ctx: ProviderAuthContext) => {
// OAuth 実装はここに記述
},
},
],
});
},
};
```
### ProviderAuthContext
```typescript
type ProviderAuthContext = {
config: PicoClawConfig;
agentDir?: string;
workspaceDir?: string;
prompter: WizardPrompter; // UI プロンプト/通知
runtime: RuntimeEnv; // ログなど
isRemote: boolean; // リモート実行かどうか
openUrl: (url: string) => Promise<void>; // ブラウザオープナー
oauth: {
createVpsAwareHandlers: Function;
};
};
```
### ProviderAuthResult
```typescript
type ProviderAuthResult = {
profiles: Array<{
profileId: string;
credential: AuthProfileCredential;
}>;
configPatch?: Partial<PicoClawConfig>;
defaultModel?: string;
notes?: string[];
};
```
---
## 統合要件
### 1. 必要な環境/依存関係
- Go ≥ 1.25
- PicoClaw コードベース(`pkg/providers/` および `pkg/auth/`
- `crypto` および `net/http` 標準ライブラリパッケージ
### 2. API 呼び出しに必要なヘッダー
```typescript
const REQUIRED_HEADERS = {
"Authorization": `Bearer ${accessToken}`,
"Content-Type": "application/json",
"User-Agent": "antigravity", // または "google-api-nodejs-client/9.15.1"
"X-Goog-Api-Client": "google-cloud-sdk vscode_cloudshelleditor/0.1",
};
// loadCodeAssist 呼び出しには以下も含める:
const CLIENT_METADATA = {
ideType: "ANTIGRAVITY", // または "IDE_UNSPECIFIED"
platform: "PLATFORM_UNSPECIFIED",
pluginType: "GEMINI",
};
```
### 3. モデルスキーマのサニタイズ
Antigravity は Gemini 互換モデルを使用するため、ツールスキーマのサニタイズが必要です:
```typescript
const GOOGLE_SCHEMA_UNSUPPORTED_KEYWORDS = new Set([
"patternProperties",
"additionalProperties",
"$schema",
"$id",
"$ref",
"$defs",
"definitions",
"examples",
"minLength",
"maxLength",
"minimum",
"maximum",
"multipleOf",
"pattern",
"format",
"minItems",
"maxItems",
"uniqueItems",
"minProperties",
"maxProperties",
]);
// 送信前にスキーマをクリーンアップ
function cleanToolSchemaForGemini(schema: Record<string, unknown>): unknown {
// サポートされていないキーワードを削除
// トップレベルに type: "object" があることを確認
// anyOf/oneOf ユニオンをフラット化
}
```
### 4. 思考ブロックの処理Claude モデル)
Antigravity の Claude モデルでは、思考ブロックに特別な処理が必要です:
```typescript
const ANTIGRAVITY_SIGNATURE_RE = /^[A-Za-z0-9+/]+={0,2}$/;
export function sanitizeAntigravityThinkingBlocks(
messages: AgentMessage[]
): AgentMessage[] {
// 思考シグネチャを検証
// シグネチャフィールドを正規化
// 署名されていない思考ブロックを破棄
}
```
---
## API エンドポイント
### 認証エンドポイント
| エンドポイント | メソッド | 用途 |
|---------------|---------|------|
| `https://accounts.google.com/o/oauth2/v2/auth` | GET | OAuth 認可 |
| `https://oauth2.googleapis.com/token` | POST | トークン交換 |
| `https://www.googleapis.com/oauth2/v1/userinfo` | GET | ユーザー情報(メール) |
### Cloud Code Assist エンドポイント
| エンドポイント | メソッド | 用途 |
|---------------|---------|------|
| `https://cloudcode-pa.googleapis.com/v1internal:loadCodeAssist` | POST | プロジェクト情報、クレジット、プランの読み込み |
| `https://cloudcode-pa.googleapis.com/v1internal:fetchAvailableModels` | POST | クォータ付き利用可能モデルの一覧 |
| `https://cloudcode-pa.googleapis.com/v1internal:streamGenerateContent?alt=sse` | POST | チャットストリーミングエンドポイント |
**API リクエスト形式(チャット):**
`v1internal:streamGenerateContent` エンドポイントは、標準の Gemini リクエストをラップするエンベロープ形式を期待します:
```json
{
"project": "your-project-id",
"model": "model-id",
"request": {
"contents": [...],
"systemInstruction": {...},
"generationConfig": {...},
"tools": [...]
},
"requestType": "agent",
"userAgent": "antigravity",
"requestId": "agent-timestamp-random"
}
```
**API レスポンス形式SSE**
各 SSE メッセージ(`data: {...}`)は `response` フィールドでラップされます:
```json
{
"response": {
"candidates": [...],
"usageMetadata": {...},
"modelVersion": "...",
"responseId": "..."
},
"traceId": "...",
"metadata": {}
}
```
---
## 設定
### config.json の設定
```json
{
"model_list": [
{
"model_name": "gemini-flash",
"model": "antigravity/gemini-3-flash",
"auth_method": "oauth"
}
],
"agents": {
"defaults": {
"model": "gemini-flash"
}
}
}
```
### 認証プロファイルの保存
認証プロファイルは `~/.picoclaw/auth.json` に保存されます:
```json
{
"credentials": {
"google-antigravity": {
"access_token": "ya29...",
"refresh_token": "1//...",
"expires_at": "2026-01-01T00:00:00Z",
"provider": "google-antigravity",
"auth_method": "oauth",
"email": "user@example.com",
"project_id": "my-project-id"
}
}
}
```
---
## PicoClaw での新しいプロバイダーの作成
PicoClaw のプロバイダーは `pkg/providers/` 配下の Go パッケージとして実装されます。新しいプロバイダーを追加するには:
### ステップバイステップの実装
#### 1. プロバイダーファイルの作成
`pkg/providers/` に新しい Go ファイルを作成します:
```
pkg/providers/
└── your_provider.go
```
#### 2. Provider インターフェースの実装
プロバイダーは `pkg/providers/types.go` で定義された `Provider` インターフェースを実装する必要があります:
```go
package providers
type YourProvider struct {
apiKey string
apiBase string
}
func NewYourProvider(apiKey, apiBase, proxy string) *YourProvider {
if apiBase == "" {
apiBase = "https://api.your-provider.com/v1"
}
return &YourProvider{apiKey: apiKey, apiBase: apiBase}
}
func (p *YourProvider) Chat(ctx context.Context, messages []Message, tools []Tool, cb StreamCallback) error {
// ストリーミング付きチャット補完を実装
}
```
#### 3. ファクトリーへの登録
`pkg/providers/factory.go` のプロトコルスイッチにプロバイダーを追加します:
```go
case "your-provider":
return NewYourProvider(sel.apiKey, sel.apiBase, sel.proxy), nil
```
#### 4. デフォルト設定の追加(オプション)
`pkg/config/defaults.go` にデフォルトエントリを追加します:
```go
{
ModelName: "your-model",
Model: "your-provider/model-name",
APIKey: "",
},
```
#### 5. 認証サポートの追加(オプション)
プロバイダーが OAuth や特別な認証を必要とする場合、`cmd/picoclaw/internal/auth/helpers.go` にケースを追加します:
```go
case "your-provider":
authLoginYourProvider()
```
#### 6. `config.json` での設定
```json
{
"model_list": [
{
"model_name": "your-model",
"model": "your-provider/model-name",
"api_key": "your-api-key",
"api_base": "https://api.your-provider.com/v1"
}
]
}
```
---
## 実装のテスト
### CLI コマンド
```bash
# プロバイダーで認証
picoclaw auth login --provider your-provider
# モデルの一覧表示Antigravity 用)
picoclaw auth models
# ゲートウェイの起動
picoclaw gateway
# 特定のモデルでエージェントを実行
picoclaw agent -m "Hello" --model your-model
```
### テスト用環境変数
```bash
# デフォルトモデルの上書き
export PICOCLAW_AGENTS_DEFAULTS_MODEL=your-model
# プロバイダー設定の上書き
export PICOCLAW_MODEL_LIST='[{"model_name":"your-model","model":"your-provider/model-name","api_key":"..."}]'
```
---
## 参考資料
- **ソースファイル:**
- `pkg/providers/antigravity_provider.go` - Antigravity プロバイダー実装
- `pkg/auth/oauth.go` - OAuth フロー実装
- `pkg/auth/store.go` - 認証情報ストレージ(`~/.picoclaw/auth.json`
- `pkg/providers/factory.go` - プロバイダーファクトリーとプロトコルルーティング
- `pkg/providers/types.go` - プロバイダーインターフェース定義
- `cmd/picoclaw/internal/auth/helpers.go` - 認証 CLI コマンド
- **ドキュメント:**
- `docs/ANTIGRAVITY_USAGE.md` - Antigravity 使用ガイド
- `docs/migration/model-list-migration.md` - 移行ガイド
---
## 注意事項
1. **Google Cloud プロジェクト:** Antigravity は Google Cloud プロジェクトで Gemini for Google Cloud が有効になっている必要があります
2. **クォータ:** Google Cloud プロジェクトのクォータを使用します(個別の課金ではありません)
3. **モデルアクセス:** 利用可能なモデルは Google Cloud プロジェクトの設定に依存します
4. **思考ブロック:** Antigravity 経由の Claude モデルは、署名付き思考ブロックの特別な処理が必要です
5. **スキーマサニタイズ:** ツールスキーマはサポートされていない JSON Schema キーワードを削除するためにサニタイズが必要です
---
---
## 一般的なエラー処理
### 1. レート制限HTTP 429
プロジェクト/モデルのクォータが枯渇すると、Antigravity は 429 エラーを返します。エラーレスポンスには通常、`details` フィールドに `quotaResetDelay` が含まれます。
**429 エラーの例:**
```json
{
"error": {
"code": 429,
"message": "You have exhausted your capacity on this model. Your quota will reset after 4h30m28s.",
"status": "RESOURCE_EXHAUSTED",
"details": [
{
"@type": "type.googleapis.com/google.rpc.ErrorInfo",
"metadata": {
"quotaResetDelay": "4h30m28.060903746s"
}
}
]
}
}
```
### 2. 空のレスポンス(制限付きモデル)
一部のモデルは利用可能モデルリストに表示されますが、空のレスポンスを返す場合があります200 OK だが SSE ストリームが空)。これは通常、現在のプロジェクトに使用権限がないプレビュー版または制限付きモデルで発生します。
**対処法:** 空のレスポンスをエラーとして扱い、そのモデルがプロジェクトに対して制限されているか無効である可能性があることをユーザーに通知します。
---
## トラブルシューティング
### "Token expired"(トークン期限切れ)
- OAuth トークンを更新:`picoclaw auth login --provider antigravity`
### "Gemini for Google Cloud is not enabled"Gemini for Google Cloud が有効になっていない)
- Google Cloud Console で API を有効にしてください
### "Project not found"(プロジェクトが見つからない)
- Google Cloud プロジェクトで必要な API が有効になっていることを確認してください
- 認証中にプロジェクト ID が正しく取得されているか確認してください
### モデルがリストに表示されない
- OAuth 認証が正常に完了したことを確認してください
- 認証プロファイルストレージを確認:`~/.picoclaw/auth.json`
- `picoclaw auth login --provider antigravity` を再実行してください

View file

@ -0,0 +1,72 @@
> [README](../../README.ja.md) に戻る
# PicoClaw で Antigravity プロバイダーを使用する
このガイドでは、PicoClaw で **Antigravity**Google Cloud Code Assistプロバイダーをセットアップして使用する方法を説明します。
## 前提条件
1. Google アカウント。
2. Google Cloud Code Assist が有効であること通常「Gemini for Google Cloud」のオンボーディングから利用可能
## 1. 認証
Antigravity で認証するには、以下のコマンドを実行します:
```bash
picoclaw auth login --provider antigravity
```
### 手動認証(ヘッドレス/VPS
サーバーCoolify/Docker上で実行しており、`localhost` にアクセスできない場合は、以下の手順に従ってください:
1. 上記のコマンドを実行します。
2. 表示された URL をコピーし、ローカルブラウザで開きます。
3. ログインを完了します。
4. ブラウザが `localhost:51121` URL にリダイレクトされます(ページは読み込めません)。
5. **ブラウザのアドレスバーからその最終 URL をコピーします**
6. **PicoClaw が待機しているターミナルにそれを貼り付けます**
PicoClaw が自動的に認証コードを抽出し、プロセスを完了します。
## 2. モデルの管理
### 利用可能なモデルの一覧
プロジェクトがアクセスできるモデルとそのクォータを確認するには:
```bash
picoclaw auth models
```
### モデルの切り替え
`~/.picoclaw/config.json` でデフォルトモデルを変更するか、CLI でオーバーライドできます:
```bash
# 単一コマンドでオーバーライド
picoclaw agent -m "Hello" --model claude-opus-4-6-thinking
```
## 3. 実際の使用方法Coolify/Docker
Coolify または Docker でデプロイしている場合、以下の手順でテストしてください:
1. **環境変数**
* `PICOCLAW_AGENTS_DEFAULTS_MODEL=gemini-flash`
2. **認証の永続化**
ローカルでログイン済みの場合、認証情報をサーバーにコピーできます:
```bash
scp ~/.picoclaw/auth.json user@your-server:~/.picoclaw/
```
*または*、ターミナルアクセスがある場合、サーバー上で `auth login` コマンドを一度実行してください。
## 4. トラブルシューティング
* **空のレスポンス**:モデルが空の応答を返す場合、プロジェクトで制限されている可能性があります。`gemini-3-flash` または `claude-opus-4-6-thinking` を試してください。
* **429 レート制限**Antigravity には厳格なクォータがあります。制限に達した場合、PicoClaw はエラーメッセージに「リセット時間」を表示します。
* **404 Not Found**`picoclaw auth models` リストのモデル ID を使用していることを確認してください。フルパスではなく、短い ID`gemini-3-flash`)を使用してください。
## 5. 動作確認済みモデルのまとめ
テストに基づき、以下のモデルが最も信頼性が高いです:
* `gemini-3-flash`(高速、高可用性)
* `gemini-2.5-flash-lite`(軽量)
* `claude-opus-4-6-thinking`(高性能、推論機能を含む)

View file

@ -281,8 +281,8 @@ picoclaw gateway
"enabled": true,
"server": "irc.libera.chat:6697",
"nick": "picoclaw-bot",
"use_tls": true,
"channels_to_join": ["#your-channel"],
"tls": true,
"channels": ["#your-channel"],
"allow_from": []
}
}
@ -496,7 +496,7 @@ picoclaw gateway
**1. AI Bot を作成**
* WeCom 管理コンソール → アプリ管理 → AI Bot
* AI Bot 設定でコールバック URL を設定:`http://your-server:18791/webhook/wecom-aibot`
* AI Bot 設定でコールバック URL を設定:`http://your-server:18790/webhook/wecom-aibot`
* **Token** をコピーし、「ランダム生成」をクリックして **EncodingAESKey** を取得
**2. 設定**

View file

@ -0,0 +1,157 @@
> [README](../../README.ja.md) に戻る
# クレデンシャル暗号化
PicoClaw は `model_list` 設定エントリの `api_key` 値の暗号化をサポートしています。
暗号化されたキーは `enc://<base64>` 文字列として保存され、起動時に自動的に復号されます。
---
## クイックスタート
**1. パスフレーズを設定する**
```bash
export PICOCLAW_KEY_PASSPHRASE="your-passphrase"
```
**2. API キーを暗号化する**
`picoclaw onboard` を実行します — パスフレーズの入力を求められ、SSH キーが生成されます。
その後、次の `SaveConfig` 呼び出し時に、設定内のすべての平文 `api_key` エントリが自動的に再暗号化されます。生成される `enc://` 値は以下のようになります:
```
enc://AAAA...base64...
```
**3. 出力を設定に貼り付ける**
```json
{
"model_list": [
{
"model_name": "gpt-4o",
"api_key": "enc://AAAA...base64...",
"api_base": "https://api.openai.com/v1"
}
]
}
```
---
## サポートされる `api_key` 形式
| 形式 | 例 | 動作 |
|------|---|------|
| 平文 | `sk-abc123` | そのまま使用 |
| ファイル参照 | `file://openai.key` | 設定ファイルと同じディレクトリから内容を読み取り |
| 暗号化 | `enc://<base64>` | 起動時に `PICOCLAW_KEY_PASSPHRASE` を使用して復号 |
| 空 | `""` | そのまま渡される(`auth_method: oauth` で使用) |
---
## 暗号設計
### 鍵導出
暗号化には **HKDF-SHA256** を使用し、SSH 秘密鍵を第二要素とします。
```
sshHash = SHA256(ssh_private_key_file_bytes)
ikm = HMAC-SHA256(key=sshHash, message=passphrase)
aes_key = HKDF-SHA256(ikm, salt, info="picoclaw-credential-v1", 32 bytes)
```
### 暗号化
```
AES-256-GCM(key=aes_key, nonce=random[12], plaintext=api_key)
```
### ワイヤーフォーマット
```
enc://<base64( salt[16] + nonce[12] + ciphertext )>
```
| フィールド | サイズ | 説明 |
|-----------|--------|------|
| `salt` | 16 バイト | 暗号化ごとにランダム生成HKDF に入力 |
| `nonce` | 12 バイト | 暗号化ごとにランダム生成AES-GCM IV |
| `ciphertext` | 可変 | AES-256-GCM 暗号文 + 16 バイト認証タグ |
GCM 認証タグは暗号文に自動的に付加されます。改ざんがあった場合、破損した平文を返すのではなく、エラーで復号が失敗します。
### パフォーマンス
| 操作 | 所要時間 (ARM Cortex-A) |
|------|------------------------|
| 鍵導出 (HKDF) | < 1 ms |
| AES-256-GCM 復号 | < 1 ms |
| **起動時の総オーバーヘッド** | **キーあたり < 2 ms** |
---
## SSH キーによる二要素セキュリティ
SSH 秘密鍵が提供されている場合、暗号を破るには**両方**が必要です:
1. **パスフレーズ** (`PICOCLAW_KEY_PASSPHRASE`)
2. **SSH 秘密鍵ファイル**
これは、設定ファイルが漏洩しただけでは、パスフレーズが弱い場合でも API キーを復元できないことを意味します。SSH キーはパスフレーズの強度に関係なく、256 ビットのエントロピーEd25519を提供します。
### 脅威モデル
| 攻撃者が持っているもの | 復号可能か? |
|----------------------|-------------|
| 設定ファイルのみ | いいえ — パスフレーズ + SSH キーが必要 |
| SSH キーのみ | いいえ — パスフレーズが必要 |
| パスフレーズのみ | いいえ — SSH キーが必要 |
| 設定ファイル + SSH キー + パスフレーズ | はい — 完全な侵害 |
---
## 環境変数
| 変数 | 必須 | 説明 |
|------|------|------|
| `PICOCLAW_KEY_PASSPHRASE` | はい(`enc://` 使用時) | 鍵導出に使用するパスフレーズ |
| `PICOCLAW_SSH_KEY_PATH` | いいえ | SSH 秘密鍵のパス。未設定の場合、`~/.ssh/picoclaw_ed25519.key` から自動検出 |
### SSH キーの自動検出
`PICOCLAW_SSH_KEY_PATH` が設定されていない場合、PicoClaw は専用キーを探します:
```
~/.ssh/picoclaw_ed25519.key
```
この専用ファイルにより、ユーザーの既存の SSH キーとの競合を回避します。
`picoclaw onboard` を実行すると自動的に生成されます。
`os.UserHomeDir()` はクロスプラットフォームのホームディレクトリ解決に使用されますWindows では `USERPROFILE`、Unix/macOS では `HOME` を読み取ります)。
> **注意:** SSH キーファイルはクレデンシャル暗号化に必須です。キーが見つからず `PICOCLAW_SSH_KEY_PATH` も設定されていない場合、暗号化/復号は失敗します。`picoclaw onboard` を実行してキーを自動生成してください。
---
## 移行
唯一の秘密情報は `PICOCLAW_KEY_PASSPHRASE` と SSH 秘密鍵ファイルであるため、移行は簡単です:
1. 設定ファイルを新しいマシンにコピーします。
2. `PICOCLAW_KEY_PASSPHRASE` を同じ値に設定します。
3. SSH 秘密鍵ファイルを同じパスにコピーします(または `PICOCLAW_SSH_KEY_PATH` を新しい場所に設定します)。
再暗号化は不要です。
---
## セキュリティに関する考慮事項
- **パスフレーズと SSH キーの両方が必須です。** SSH キーは第二要素として機能します — これがなければ暗号化/復号は失敗します。キーが存在しない場合は `picoclaw onboard` を実行して生成してください。
- **SSH キーは実行時に読み取り専用です。** PicoClaw は SSH キーファイルへの書き込みや変更を行いません。
- **平文キーは引き続きサポートされます。** `enc://` を使用しない既存の設定は影響を受けません。
- **`enc://` 形式はバージョン管理されています。** HKDF `info` フィールド(`picoclaw-credential-v1`)により、既存の暗号化値を壊すことなく将来のアルゴリズムアップグレードが可能です。

36
docs/ja/debug.md Normal file
View file

@ -0,0 +1,36 @@
# PicoClaw のデバッグ
> [README](../../README.ja.md) に戻る
PicoClaw は、受信するすべてのリクエストに対して、メッセージのルーティングや複雑度の評価、ツールの実行、モデル障害への適応など、多くの複雑な処理をバックグラウンドで実行しています。何が起きているかを正確に把握できることは、潜在的な問題のトラブルシューティングだけでなく、エージェントの動作を真に理解するためにも非常に重要です。
## デバッグモードで PicoClaw を起動する
エージェントの動作に関する詳細情報LLM リクエスト、ツール呼び出し、メッセージルーティング)を取得するには、デバッグフラグを付けて PicoClaw ゲートウェイを起動します:
```bash
picoclaw gateway --debug
# or
picoclaw gateway -d
```
このモードでは、システムがログを詳細にフォーマットし、システムプロンプトやツール実行結果のプレビューを表示します。
## ログの切り詰めを無効にする(完全なログ)
デフォルトでは、PicoClaw はコンソールの可読性を保つために、デバッグログ内の非常に長い文字列(*システムプロンプト*や大きな JSON 出力結果など)を切り詰めます。
コマンドの完全な出力や、LLM モデルに送信された正確なペイロードを確認する必要がある場合は、`--no-truncate` フラグを使用できます。
**注意:** このフラグは `--debug` モードと組み合わせた場合に*のみ*機能します。
```bash
picoclaw gateway --debug --no-truncate
```
このフラグが有効な場合、グローバルな切り詰め機能が無効になります。これは以下の場合に非常に便利です:
* プロバイダーに送信されるメッセージの正確な構文を確認する。
* `exec``web_fetch``read_file` などのツールの完全な出力を読む。
* メモリに保存されたセッション履歴をデバッグする。

View file

@ -0,0 +1,152 @@
> [README](../../README.ja.md) に戻る
# 🖥️ PicoClaw ハードウェア互換性リスト
PicoClaw はほぼすべての Linux デバイスで動作します。このページでは、検証済みのチップ、製品、開発ボードを記録しています。
**お使いのハードウェアがリストにない場合は?** PR を送信して追加してください!ハードウェアベンダーの貢献と共同プロモーションを歓迎します。
---
## 1. 検証済みチップサポート
### x86
| ベンダー | チップ | 備考 |
|----------|--------|------|
| Intel | Any x86 CPU (i386+) | すべてのデスクトップ/サーバー/ートPC プロセッサ |
| AMD | Any x86 CPU | すべてのデスクトップ/サーバー/ートPC プロセッサ |
### ARM
| サブアーキテクチャ | 代表的なチップ | 備考 |
|--------------------|----------------|------|
| ARMv6 | [BCM2835](https://www.raspberrypi.com/documentation/computers/processors.html#bcm2835) (Raspberry Pi 1/Zero) | シングルコア ARM1176JZF-S |
| ARMv7 | [Allwinner V3s](https://linux-sunxi.org/V3s) | シングルコア Cortex-A7、LicheePi Zero で使用 |
| ARM64 | [Allwinner H618](https://linux-sunxi.org/H618) | クアッドコア Cortex-A53、Orange Pi Zero 3 で使用 |
| ARM64 | [BCM2711](https://www.raspberrypi.com/documentation/computers/processors.html#bcm2711) (Raspberry Pi 4) | クアッドコア Cortex-A72 |
| ARM64 | [BCM2712](https://www.raspberrypi.com/documentation/computers/processors.html#bcm2712) (Raspberry Pi 5) | クアッドコア Cortex-A76 |
| ARM64 | [AX630C](https://www.axera-tech.com/) (爱芯元智) | デュアルコア Cortex-A53 + NPU、NanoKVM-Pro / MaixCAM2 で使用 |
### RISC-V (riscv64)
| ベンダー | チップ | コア | 備考 |
|----------|--------|------|------|
| [SOPHGO (算能)](https://www.sophgo.com/) | SG2002 | C906 @ 1GHz | 256MB DDR3 オンチップ、LicheeRV-Nano / NanoKVM / MaixCAM で使用 |
| [Allwinner (全志)](https://www.allwinnertech.com/) | V861 | Dual C907 | 128MB DDR3L オンチップ、1 TOPS NPU、4K AI カメラ SiP |
| [Allwinner (全志)](https://www.allwinnertech.com/) | V881 | C907 | RISC-V AI カメラシリーズ |
| [Arterytek (匠芯创)](https://www.arterytek.com/) | D213 | RISC-V | HaaS506-LD1 産業用 RTU で使用 |
| [SpacemiT (进迭)](https://www.spacemit.com/) | K1 | 8x X60 @ 1.8GHz | Milk-V Jupiter, BananaPi BPI-F3 で使用 |
| [SpacemiT (进迭)](https://www.spacemit.com/) | K3 | 8x X100 @ 2.5GHz | RVA23 準拠、1024 ビット RVV、FP8 AI 推論 |
| [Zhihe (知合)](https://www.zhihe-tech.com/) | A210 | High-perf RISC-V | 8 コア、16MB L3 キャッシュ、デスクトップクラス |
| [Canaan (嘉楠)](https://www.canaan-creative.com/) | K230 | Dual C908 @ 1.6GHz | 6 TOPS KPU、CanMV-K230 で使用 |
### MIPS
| ベンダー | チップ | 備考 |
|----------|--------|------|
| MediaTek | [MT7620](https://www.mediatek.com/products/home-networking/mt7620) | MIPS24KEc @ 580MHz、多くの OpenWrt ルーターで使用Xiaomi Router 3G |
### LoongArch (loong64)
| ベンダー | チップ | 備考 |
|----------|--------|------|
| [Loongson (龙芯)](https://www.loongson.cn/) | 3A5000 | クアッドコア LA464 @ 2.5GHz、デスクトップ/ワークステーション |
| [Loongson (龙芯)](https://www.loongson.cn/) | 3A6000 | クアッドコア 4C/8T @ 2.5GHz、IPC は Intel 第10世代に匹敵 |
| [Loongson (龙芯)](https://www.loongson.cn/) | 2K1000LA | デュアルコア @ 1GHz、産業/IoT アプリケーション |
---
## 2. 検証済み製品(発売日順)
PicoClaw でテスト済みのコンシューマー製品、ルーター、産業用デバイス。
| 年 | 製品 | アーキテクチャ | SoC | RAM | カテゴリ |
|----|------|----------------|-----|-----|----------|
| 2009 | Nokia N900 | ARM (A8) | OMAP3430 | 256MB | スマートフォン |
| 2012 | Samsung Galaxy Note 10.1 (N8000) | ARM (A9) | Exynos 4412 | 2GB | タブレット |
| 2016 | Xiaomi Router 3G (小米路由器3G) | MIPS | MT7620 | 256MB | ルーター (OpenWrt) |
| 2018 | Phicomm N1 (斐讯N1) | ARM64 (A53) | S905D | 2GB | TV ボックス / ホームサーバー |
| 2019 | Xiaomi AI Speaker (小爱音箱) | ARM64 (A53) | — | 256MB | スマートスピーカー |
| 2024 | [NanoKVM](https://wiki.sipeed.com/hardware/en/kvm/NanoKVM/introduction.html) | RISC-V | SG2002 | 256MB | IP-KVM |
| 2025 | HaaS506-LD1 | RISC-V | D213 | 128MB | 産業用 RTU |
| 2025 | [NanoKVM-Pro](https://wiki.sipeed.com/hardware/en/kvm/NanoKVM_Pro/introduction.html) | ARM64 (A53) | AX630C | 1GB | プロ IP-KVM |
| 2026 | [MaixCAM2](https://wiki.sipeed.com/hardware/en/maixcam/index.html) | ARM64 (A53) | AX630C | 1/4GB | 4K AI カメラ |
---
## 3. 検証済み開発ボード(発売日順)
| 年 | ボード | アーキテクチャ | SoC | RAM | 購入リンク |
|----|--------|----------------|-----|-----|------------|
| 2012 | [Raspberry Pi 1 Model B](https://www.raspberrypi.com/products/) | ARMv6 | BCM2835 | 512MB | — |
| 2015 | [Raspberry Pi 2 Model B](https://www.raspberrypi.com/products/raspberry-pi-2-model-b/) | ARMv7 (A7) | BCM2836 | 1GB | — |
| 2015 | [Raspberry Pi Zero](https://www.raspberrypi.com/products/raspberry-pi-zero/) | ARMv6 | BCM2835 | 512MB | — |
| 2016 | [Raspberry Pi 3 Model B](https://www.raspberrypi.com/products/raspberry-pi-3-model-b/) | ARM64 (A53) | BCM2837 | 1GB | — |
| 2017 | [LicheePi Zero](https://wiki.sipeed.com/hardware/en/lichee/Zero/Zero.html) | ARMv7 (A7) | Allwinner V3s | 64MB | [Sipeed](https://sipeed.com/) |
| 2019 | [Raspberry Pi 4 Model B](https://www.raspberrypi.com/products/raspberry-pi-4-model-b/) | ARM64 (A72) | BCM2711 | 1~8GB | [RPi](https://www.raspberrypi.com/) |
| 2023 | [Raspberry Pi 5](https://www.raspberrypi.com/products/raspberry-pi-5/) | ARM64 (A76) | BCM2712 | 2~8GB | [RPi](https://www.raspberrypi.com/) |
| 2024 | [LicheeRV-Nano](https://wiki.sipeed.com/hardware/en/lichee/RV_Nano/1_intro.html) | RISC-V | SG2002 | 256MB | [AliExpress](https://www.aliexpress.com/item/1005006519668532.html) |
| 2024 | [MaixCAM-Pro](https://wiki.sipeed.com/hardware/en/maixcam/index.html) | RISC-V | SG2002 | 256MB | [Sipeed](https://sipeed.com/) |
| 2024 | [Milk-V Duo 64M](https://milkv.io/docs/duo/getting-started/duo) | RISC-V | CV1800B | 64MB | [Milk-V](https://milkv.io/) |
| 2024 | [CanMV-K230](https://developer.canaan-creative.com/k230_canmv/en/main/) | RISC-V | K230 | 512MB | [Canaan](https://www.canaan-creative.com/) |
---
## 4. その他の対応環境
### Android スマートフォンTermux 経由)
1GB 以上の RAM を搭載した ARM64 Android スマートフォン2015年以降。[Termux](https://github.com/termux/termux-app) をインストールし、`proot` を使用して PicoClaw を実行します。
> セットアップ手順は [README古い Android スマートフォンで実行](../README.md#-run-on-old-android-phones) を参照してください。
### デスクトップ / サーバー / クラウド
| プラットフォーム | 備考 |
|------------------|------|
| x86_64 Linux | ネイティブバイナリ、依存関係なし |
| x86_64 Windows | ネイティブバイナリ |
| macOS (Intel / Apple Silicon) | ネイティブバイナリ |
| Docker (any platform) | `docker compose` ワンライナー、[Docker ガイド](docker.md) を参照 |
| OpenWrt routers | MIPS/ARM ビルド、32MB 以上の空きメモリが必要 |
| FreeBSD / NetBSD | x86_64 および arm64 ビルドが利用可能 |
---
## 5. 最小要件
| リソース | 最小 | 推奨 |
|----------|------|------|
| RAM | 10MB 空き | 32MB 以上空き |
| ストレージ | 20MBバイナリ | 50MB 以上(ワークスペース含む) |
| CPU | 任意(シングルコア 0.6GHz 以上) | — |
| OS | Linux (kernel 3.x+) | Linux 5.x+ |
| ネットワーク | 必須LLM API 呼び出し用) | イーサネットまたは WiFi |
---
## 6. テストと貢献の方法
```bash
# 1. お使いのアーキテクチャ向けをダウンロード
wget https://github.com/sipeed/picoclaw/releases/latest/download/picoclaw_Linux_arm64.tar.gz
tar xzf picoclaw_Linux_arm64.tar.gz
# 2. 初期化
./picoclaw onboard
# 3. テスト
./picoclaw agent -m "Hello, what board am I running on?"
```
利用可能なビルド:`linux-amd64`, `linux-arm64`, `linux-arm`, `linux-riscv64`, `linux-loong64`, `linux-mipsle`
### ハードウェアを追加する
1. このリポジトリをフォーク
2. 該当するテーブルにチップ/製品/ボードを追加
3. 名前、アーキテクチャ、SoC、RAM、年、リンクあればを含める
4. PR を送信
ハードウェアベンダーの方へ公式サポートの追加や共同プロモーションをご希望ですかIssue を作成するか、[Discord](https://discord.gg/V4sAZ9XWpN) でお問い合わせください。

View file

@ -16,7 +16,7 @@
**修正方法:** `~/.picoclaw/config.json`(またはお使いの設定パス)で:
1. **agents.defaults.model** は `model_list` 内の `model_name` と一致する必要があります(例:`"openrouter-free"`)。
1. **agents.defaults.model_name** は `model_list` 内の `model_name` と一致する必要があります(例:`"openrouter-free"`)。
2. そのエントリの **model** は有効な OpenRouter モデル ID である必要があります。例:
- `"openrouter/free"` 自動無料枠
- `"google/gemini-2.0-flash-exp:free"`
@ -28,7 +28,7 @@
{
"agents": {
"defaults": {
"model": "openrouter-free"
"model_name": "openrouter-free"
}
},
"model_list": [

View file

@ -70,7 +70,7 @@ The new `model_list` configuration offers several advantages:
],
"agents": {
"defaults": {
"model": "gpt4"
"model_name": "gpt4"
}
}
}
@ -184,7 +184,7 @@ During the migration period, your existing `providers` configuration will contin
- [ ] Identify all providers you're currently using
- [ ] Create `model_list` entries for each provider
- [ ] Use appropriate protocol prefixes
- [ ] Update `agents.defaults.model` to reference the new `model_name`
- [ ] Update `agents.defaults.model_name` to reference the new `model_name`
- [ ] Test that all models work correctly
- [ ] Remove or comment out the old `providers` section
@ -196,7 +196,7 @@ During the migration period, your existing `providers` configuration will contin
model "xxx" not found in model_list or providers
```
**Solution**: Ensure the `model_name` in `model_list` matches the value in `agents.defaults.model`.
**Solution**: Ensure the `model_name` in `model_list` matches the value in `agents.defaults.model_name`.
### Unknown protocol error

View file

@ -0,0 +1,809 @@
> Voltar ao [README](../../README.pt-br.md)
# Guia de Autenticação e Integração do Antigravity
## Visão Geral
**Antigravity** (Google Cloud Code Assist) é um provedor de modelos de IA apoiado pelo Google que oferece acesso a modelos como Claude Opus 4.6 e Gemini através da infraestrutura de nuvem do Google. Este documento fornece um guia completo sobre como a autenticação funciona, como buscar modelos e como implementar um novo provedor no PicoClaw.
---
## Índice
1. [Fluxo de Autenticação](#fluxo-de-autenticação)
2. [Detalhes da Implementação OAuth](#detalhes-da-implementação-oauth)
3. [Gerenciamento de Tokens](#gerenciamento-de-tokens)
4. [Busca da Lista de Modelos](#busca-da-lista-de-modelos)
5. [Rastreamento de Uso](#rastreamento-de-uso)
6. [Estrutura do Plugin do Provedor](#estrutura-do-plugin-do-provedor)
7. [Requisitos de Integração](#requisitos-de-integração)
8. [Endpoints da API](#endpoints-da-api)
9. [Configuração](#configuração)
10. [Criando um Novo Provedor no PicoClaw](#criando-um-novo-provedor-no-picoclaw)
---
## Fluxo de Autenticação
### 1. OAuth 2.0 com PKCE
O Antigravity utiliza **OAuth 2.0 com PKCE (Proof Key for Code Exchange)** para autenticação segura:
```
┌─────────────┐ ┌─────────────────┐
│ Client │ ───(1) Generate PKCE Pair────────> │ │
│ │ ───(2) Open Auth URL─────────────> │ Google OAuth │
│ │ │ Server │
│ │ <──(3) Redirect with Code───────── │ │
│ │ └─────────────────┘
│ │ ───(4) Exchange Code for Tokens──> │ Token URL │
│ │ │ │
│ │ <──(5) Access + Refresh Tokens──── │ │
└─────────────┘ └─────────────────┘
```
### 2. Etapas Detalhadas
#### Etapa 1: Gerar Parâmetros PKCE
```typescript
function generatePkce(): { verifier: string; challenge: string } {
const verifier = randomBytes(32).toString("hex");
const challenge = createHash("sha256").update(verifier).digest("base64url");
return { verifier, challenge };
}
```
#### Etapa 2: Construir a URL de Autorização
```typescript
const AUTH_URL = "https://accounts.google.com/o/oauth2/v2/auth";
const REDIRECT_URI = "http://localhost:51121/oauth-callback";
function buildAuthUrl(params: { challenge: string; state: string }): string {
const url = new URL(AUTH_URL);
url.searchParams.set("client_id", CLIENT_ID);
url.searchParams.set("response_type", "code");
url.searchParams.set("redirect_uri", REDIRECT_URI);
url.searchParams.set("scope", SCOPES.join(" "));
url.searchParams.set("code_challenge", params.challenge);
url.searchParams.set("code_challenge_method", "S256");
url.searchParams.set("state", params.state);
url.searchParams.set("access_type", "offline");
url.searchParams.set("prompt", "consent");
return url.toString();
}
```
**Escopos Necessários:**
```typescript
const SCOPES = [
"https://www.googleapis.com/auth/cloud-platform",
"https://www.googleapis.com/auth/userinfo.email",
"https://www.googleapis.com/auth/userinfo.profile",
"https://www.googleapis.com/auth/cclog",
"https://www.googleapis.com/auth/experimentsandconfigs",
];
```
#### Etapa 3: Tratar o Callback OAuth
**Modo Automático (Desenvolvimento Local):**
- Iniciar um servidor HTTP local na porta 51121
- Aguardar o redirecionamento do Google
- Extrair o código de autorização dos parâmetros da query
**Modo Manual (Remoto/Sem Interface Gráfica):**
- Exibir a URL de autorização para o usuário
- O usuário completa a autenticação no navegador
- O usuário cola a URL de redirecionamento completa no terminal
- Analisar o código da URL colada
#### Etapa 4: Trocar o Código por Tokens
```typescript
const TOKEN_URL = "https://oauth2.googleapis.com/token";
async function exchangeCode(params: {
code: string;
verifier: string;
}): Promise<{ access: string; refresh: string; expires: number }> {
const response = await fetch(TOKEN_URL, {
method: "POST",
headers: { "Content-Type": "application/x-www-form-urlencoded" },
body: new URLSearchParams({
client_id: CLIENT_ID,
client_secret: CLIENT_SECRET,
code: params.code,
grant_type: "authorization_code",
redirect_uri: REDIRECT_URI,
code_verifier: params.verifier,
}),
});
const data = await response.json();
return {
access: data.access_token,
refresh: data.refresh_token,
expires: Date.now() + data.expires_in * 1000 - 5 * 60 * 1000, // 5 min buffer
};
}
```
#### Etapa 5: Buscar Dados Adicionais do Usuário
**E-mail do Usuário:**
```typescript
async function fetchUserEmail(accessToken: string): Promise<string | undefined> {
const response = await fetch(
"https://www.googleapis.com/oauth2/v1/userinfo?alt=json",
{ headers: { Authorization: `Bearer ${accessToken}` } }
);
const data = await response.json();
return data.email;
}
```
**ID do Projeto (Necessário para chamadas de API):**
```typescript
async function fetchProjectId(accessToken: string): Promise<string> {
const headers = {
Authorization: `Bearer ${accessToken}`,
"Content-Type": "application/json",
"User-Agent": "google-api-nodejs-client/9.15.1",
"X-Goog-Api-Client": "google-cloud-sdk vscode_cloudshelleditor/0.1",
"Client-Metadata": JSON.stringify({
ideType: "IDE_UNSPECIFIED",
platform: "PLATFORM_UNSPECIFIED",
pluginType: "GEMINI",
}),
};
const response = await fetch(
"https://cloudcode-pa.googleapis.com/v1internal:loadCodeAssist",
{
method: "POST",
headers,
body: JSON.stringify({
metadata: {
ideType: "IDE_UNSPECIFIED",
platform: "PLATFORM_UNSPECIFIED",
pluginType: "GEMINI",
},
}),
}
);
const data = await response.json();
return data.cloudaicompanionProject || "rising-fact-p41fc"; // Valor padrão de fallback
}
```
---
## Detalhes da Implementação OAuth
### Credenciais do Cliente
**Importante:** Estas são codificadas em base64 no código-fonte para sincronização com pi-ai:
```typescript
const decode = (s: string) => Buffer.from(s, "base64").toString();
const CLIENT_ID = decode(
"MTA3MTAwNjA2MDU5MS10bWhzc2luMmgyMWxjcmUyMzV2dG9sb2poNGc0MDNlcC5hcHBzLmdvb2dsZXVzZXJjb250ZW50LmNvbQ=="
);
const CLIENT_SECRET = decode("R09DU1BYLUs1OEZXUjQ4NkxkTEoxbUxCOHNYQzR6NnFEQWY=");
```
### Modos do Fluxo OAuth
1. **Fluxo Automático** (máquinas locais com navegador):
- Abre o navegador automaticamente
- O servidor de callback local captura o redirecionamento
- Nenhuma interação do usuário necessária após a autenticação inicial
2. **Fluxo Manual** (remoto/sem interface/WSL2):
- URL exibida para copiar e colar manualmente
- O usuário completa a autenticação em um navegador externo
- O usuário cola a URL de redirecionamento completa de volta
```typescript
function shouldUseManualOAuthFlow(isRemote: boolean): boolean {
return isRemote || isWSL2Sync();
}
```
---
## Gerenciamento de Tokens
### Estrutura do Perfil de Autenticação
```typescript
type OAuthCredential = {
type: "oauth";
provider: "google-antigravity";
access: string; // Token de acesso
refresh: string; // Token de atualização
expires: number; // Timestamp de expiração (ms desde epoch)
email?: string; // E-mail do usuário
projectId?: string; // ID do projeto Google Cloud
};
```
### Atualização de Tokens
A credencial inclui um token de atualização que pode ser usado para obter novos tokens de acesso quando o atual expira. A expiração é definida com um buffer de 5 minutos para evitar condições de corrida.
---
## Busca da Lista de Modelos
### Buscar Modelos Disponíveis
```typescript
const BASE_URL = "https://cloudcode-pa.googleapis.com";
async function fetchAvailableModels(
accessToken: string,
projectId: string
): Promise<Model[]> {
const headers = {
Authorization: `Bearer ${accessToken}`,
"Content-Type": "application/json",
"User-Agent": "antigravity",
"X-Goog-Api-Client": "google-cloud-sdk vscode_cloudshelleditor/0.1",
};
const response = await fetch(
`${BASE_URL}/v1internal:fetchAvailableModels`,
{
method: "POST",
headers,
body: JSON.stringify({ project: projectId }),
}
);
const data = await response.json();
// Retorna modelos com informações de cota
return Object.entries(data.models).map(([modelId, modelInfo]) => ({
id: modelId,
displayName: modelInfo.displayName,
quotaInfo: {
remainingFraction: modelInfo.quotaInfo?.remainingFraction,
resetTime: modelInfo.quotaInfo?.resetTime,
isExhausted: modelInfo.quotaInfo?.isExhausted,
},
}));
}
```
### Formato da Resposta
```typescript
type FetchAvailableModelsResponse = {
models?: Record<string, {
displayName?: string;
quotaInfo?: {
remainingFraction?: number | string;
resetTime?: string; // Timestamp ISO 8601
isExhausted?: boolean;
};
}>;
};
```
---
## Rastreamento de Uso
### Buscar Dados de Uso
```typescript
export async function fetchAntigravityUsage(
token: string,
timeoutMs: number
): Promise<ProviderUsageSnapshot> {
// 1. Buscar créditos e informações do plano
const loadCodeAssistRes = await fetch(
`${BASE_URL}/v1internal:loadCodeAssist`,
{
method: "POST",
headers: {
Authorization: `Bearer ${token}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
metadata: {
ideType: "ANTIGRAVITY",
platform: "PLATFORM_UNSPECIFIED",
pluginType: "GEMINI",
},
}),
}
);
// Extrair informações de créditos
const { availablePromptCredits, planInfo, currentTier } = data;
// 2. Buscar cotas dos modelos
const modelsRes = await fetch(
`${BASE_URL}/v1internal:fetchAvailableModels`,
{
method: "POST",
headers: { Authorization: `Bearer ${token}` },
body: JSON.stringify({ project: projectId }),
}
);
// Construir janelas de uso
return {
provider: "google-antigravity",
displayName: "Google Antigravity",
windows: [
{ label: "Credits", usedPercent: calculateUsedPercent(available, monthly) },
// Cotas individuais dos modelos...
],
plan: currentTier?.name || planType,
};
}
```
### Estrutura da Resposta de Uso
```typescript
type ProviderUsageSnapshot = {
provider: "google-antigravity";
displayName: string;
windows: UsageWindow[];
plan?: string;
error?: string;
};
type UsageWindow = {
label: string; // "Credits" ou ID do modelo
usedPercent: number; // 0-100
resetAt?: number; // Timestamp de quando a cota é redefinida
};
```
---
## Estrutura do Plugin do Provedor
### Definição do Plugin
```typescript
const antigravityPlugin = {
id: "google-antigravity-auth",
name: "Google Antigravity Auth",
description: "OAuth flow for Google Antigravity (Cloud Code Assist)",
configSchema: emptyPluginConfigSchema(),
register(api: PicoClawPluginApi) {
api.registerProvider({
id: "google-antigravity",
label: "Google Antigravity",
docsPath: "/providers/models",
aliases: ["antigravity"],
auth: [
{
id: "oauth",
label: "Google OAuth",
hint: "PKCE + localhost callback",
kind: "oauth",
run: async (ctx: ProviderAuthContext) => {
// Implementação OAuth aqui
},
},
],
});
},
};
```
### ProviderAuthContext
```typescript
type ProviderAuthContext = {
config: PicoClawConfig;
agentDir?: string;
workspaceDir?: string;
prompter: WizardPrompter; // Prompts/notificações da UI
runtime: RuntimeEnv; // Logging, etc.
isRemote: boolean; // Se está executando remotamente
openUrl: (url: string) => Promise<void>; // Abridor de navegador
oauth: {
createVpsAwareHandlers: Function;
};
};
```
### ProviderAuthResult
```typescript
type ProviderAuthResult = {
profiles: Array<{
profileId: string;
credential: AuthProfileCredential;
}>;
configPatch?: Partial<PicoClawConfig>;
defaultModel?: string;
notes?: string[];
};
```
---
## Requisitos de Integração
### 1. Ambiente/Dependências Necessários
- Go ≥ 1.25
- Base de código do PicoClaw (`pkg/providers/` e `pkg/auth/`)
- Pacotes da biblioteca padrão `crypto` e `net/http`
### 2. Cabeçalhos Necessários para Chamadas de API
```typescript
const REQUIRED_HEADERS = {
"Authorization": `Bearer ${accessToken}`,
"Content-Type": "application/json",
"User-Agent": "antigravity", // ou "google-api-nodejs-client/9.15.1"
"X-Goog-Api-Client": "google-cloud-sdk vscode_cloudshelleditor/0.1",
};
// Para chamadas loadCodeAssist, incluir também:
const CLIENT_METADATA = {
ideType: "ANTIGRAVITY", // ou "IDE_UNSPECIFIED"
platform: "PLATFORM_UNSPECIFIED",
pluginType: "GEMINI",
};
```
### 3. Sanitização de Schemas de Modelos
O Antigravity usa modelos compatíveis com Gemini, então os schemas de ferramentas devem ser sanitizados:
```typescript
const GOOGLE_SCHEMA_UNSUPPORTED_KEYWORDS = new Set([
"patternProperties",
"additionalProperties",
"$schema",
"$id",
"$ref",
"$defs",
"definitions",
"examples",
"minLength",
"maxLength",
"minimum",
"maximum",
"multipleOf",
"pattern",
"format",
"minItems",
"maxItems",
"uniqueItems",
"minProperties",
"maxProperties",
]);
// Limpar schema antes de enviar
function cleanToolSchemaForGemini(schema: Record<string, unknown>): unknown {
// Remover palavras-chave não suportadas
// Garantir que o nível superior tenha type: "object"
// Achatar uniões anyOf/oneOf
}
```
### 4. Tratamento de Blocos de Pensamento (Modelos Claude)
Para modelos Claude via Antigravity, os blocos de pensamento requerem tratamento especial:
```typescript
const ANTIGRAVITY_SIGNATURE_RE = /^[A-Za-z0-9+/]+={0,2}$/;
export function sanitizeAntigravityThinkingBlocks(
messages: AgentMessage[]
): AgentMessage[] {
// Validar assinaturas de pensamento
// Normalizar campos de assinatura
// Descartar blocos de pensamento não assinados
}
```
---
## Endpoints da API
### Endpoints de Autenticação
| Endpoint | Método | Finalidade |
|----------|--------|-----------|
| `https://accounts.google.com/o/oauth2/v2/auth` | GET | Autorização OAuth |
| `https://oauth2.googleapis.com/token` | POST | Troca de tokens |
| `https://www.googleapis.com/oauth2/v1/userinfo` | GET | Informações do usuário (e-mail) |
### Endpoints do Cloud Code Assist
| Endpoint | Método | Finalidade |
|----------|--------|-----------|
| `https://cloudcode-pa.googleapis.com/v1internal:loadCodeAssist` | POST | Carregar informações do projeto, créditos, plano |
| `https://cloudcode-pa.googleapis.com/v1internal:fetchAvailableModels` | POST | Listar modelos disponíveis com cotas |
| `https://cloudcode-pa.googleapis.com/v1internal:streamGenerateContent?alt=sse` | POST | Endpoint de streaming de chat |
**Formato de Requisição da API (Chat):**
O endpoint `v1internal:streamGenerateContent` espera um envelope encapsulando a requisição Gemini padrão:
```json
{
"project": "your-project-id",
"model": "model-id",
"request": {
"contents": [...],
"systemInstruction": {...},
"generationConfig": {...},
"tools": [...]
},
"requestType": "agent",
"userAgent": "antigravity",
"requestId": "agent-timestamp-random"
}
```
**Formato de Resposta da API (SSE):**
Cada mensagem SSE (`data: {...}`) é encapsulada em um campo `response`:
```json
{
"response": {
"candidates": [...],
"usageMetadata": {...},
"modelVersion": "...",
"responseId": "..."
},
"traceId": "...",
"metadata": {}
}
```
---
## Configuração
### Configuração do config.json
```json
{
"model_list": [
{
"model_name": "gemini-flash",
"model": "antigravity/gemini-3-flash",
"auth_method": "oauth"
}
],
"agents": {
"defaults": {
"model": "gemini-flash"
}
}
}
```
### Armazenamento do Perfil de Autenticação
Os perfis de autenticação são armazenados em `~/.picoclaw/auth.json`:
```json
{
"credentials": {
"google-antigravity": {
"access_token": "ya29...",
"refresh_token": "1//...",
"expires_at": "2026-01-01T00:00:00Z",
"provider": "google-antigravity",
"auth_method": "oauth",
"email": "user@example.com",
"project_id": "my-project-id"
}
}
}
```
---
## Criando um Novo Provedor no PicoClaw
Os provedores do PicoClaw são implementados como pacotes Go em `pkg/providers/`. Para adicionar um novo provedor:
### Implementação Passo a Passo
#### 1. Criar o Arquivo do Provedor
Crie um novo arquivo Go em `pkg/providers/`:
```
pkg/providers/
└── your_provider.go
```
#### 2. Implementar a Interface Provider
Seu provedor deve implementar a interface `Provider` definida em `pkg/providers/types.go`:
```go
package providers
type YourProvider struct {
apiKey string
apiBase string
}
func NewYourProvider(apiKey, apiBase, proxy string) *YourProvider {
if apiBase == "" {
apiBase = "https://api.your-provider.com/v1"
}
return &YourProvider{apiKey: apiKey, apiBase: apiBase}
}
func (p *YourProvider) Chat(ctx context.Context, messages []Message, tools []Tool, cb StreamCallback) error {
// Implementar conclusão de chat com streaming
}
```
#### 3. Registrar na Factory
Adicione seu provedor ao switch de protocolo em `pkg/providers/factory.go`:
```go
case "your-provider":
return NewYourProvider(sel.apiKey, sel.apiBase, sel.proxy), nil
```
#### 4. Adicionar Configuração Padrão (Opcional)
Adicione uma entrada padrão em `pkg/config/defaults.go`:
```go
{
ModelName: "your-model",
Model: "your-provider/model-name",
APIKey: "",
},
```
#### 5. Adicionar Suporte de Autenticação (Opcional)
Se seu provedor requer OAuth ou autenticação especial, adicione um caso em `cmd/picoclaw/internal/auth/helpers.go`:
```go
case "your-provider":
authLoginYourProvider()
```
#### 6. Configurar via `config.json`
```json
{
"model_list": [
{
"model_name": "your-model",
"model": "your-provider/model-name",
"api_key": "your-api-key",
"api_base": "https://api.your-provider.com/v1"
}
]
}
```
---
## Testando Sua Implementação
### Comandos CLI
```bash
# Autenticar com um provedor
picoclaw auth login --provider your-provider
# Listar modelos (para Antigravity)
picoclaw auth models
# Iniciar o gateway
picoclaw gateway
# Executar um agente com um modelo específico
picoclaw agent -m "Hello" --model your-model
```
### Variáveis de Ambiente para Testes
```bash
# Substituir o modelo padrão
export PICOCLAW_AGENTS_DEFAULTS_MODEL=your-model
# Substituir configurações do provedor
export PICOCLAW_MODEL_LIST='[{"model_name":"your-model","model":"your-provider/model-name","api_key":"..."}]'
```
---
## Referências
- **Arquivos Fonte:**
- `pkg/providers/antigravity_provider.go` - Implementação do provedor Antigravity
- `pkg/auth/oauth.go` - Implementação do fluxo OAuth
- `pkg/auth/store.go` - Armazenamento de credenciais de autenticação (`~/.picoclaw/auth.json`)
- `pkg/providers/factory.go` - Factory de provedores e roteamento de protocolo
- `pkg/providers/types.go` - Definições da interface do provedor
- `cmd/picoclaw/internal/auth/helpers.go` - Comandos CLI de autenticação
- **Documentação:**
- `docs/ANTIGRAVITY_USAGE.md` - Guia de uso do Antigravity
- `docs/migration/model-list-migration.md` - Guia de migração
---
## Observações
1. **Projeto Google Cloud:** O Antigravity requer que o Gemini for Google Cloud esteja habilitado no seu projeto Google Cloud
2. **Cotas:** Usa cotas do projeto Google Cloud (sem cobrança separada)
3. **Acesso a Modelos:** Os modelos disponíveis dependem da configuração do seu projeto Google Cloud
4. **Blocos de Pensamento:** Modelos Claude via Antigravity requerem tratamento especial de blocos de pensamento com assinaturas
5. **Sanitização de Schemas:** Os schemas de ferramentas devem ser sanitizados para remover palavras-chave JSON Schema não suportadas
---
---
## Tratamento de Erros Comuns
### 1. Limitação de Taxa (HTTP 429)
O Antigravity retorna um erro 429 quando as cotas do projeto/modelo estão esgotadas. A resposta de erro frequentemente contém um `quotaResetDelay` no campo `details`.
**Exemplo de Erro 429:**
```json
{
"error": {
"code": 429,
"message": "You have exhausted your capacity on this model. Your quota will reset after 4h30m28s.",
"status": "RESOURCE_EXHAUSTED",
"details": [
{
"@type": "type.googleapis.com/google.rpc.ErrorInfo",
"metadata": {
"quotaResetDelay": "4h30m28.060903746s"
}
}
]
}
}
```
### 2. Respostas Vazias (Modelos Restritos)
Alguns modelos podem aparecer na lista de modelos disponíveis, mas retornar uma resposta vazia (200 OK mas stream SSE vazio). Isso geralmente acontece com modelos em preview ou restritos que o projeto atual não tem permissão para usar.
**Tratamento:** Tratar respostas vazias como erros informando ao usuário que o modelo pode estar restrito ou inválido para seu projeto.
---
## Solução de Problemas
### "Token expired" (token expirado)
- Atualizar tokens OAuth: `picoclaw auth login --provider antigravity`
### "Gemini for Google Cloud is not enabled" (Gemini for Google Cloud não está habilitado)
- Habilitar a API no seu Google Cloud Console
### "Project not found" (projeto não encontrado)
- Verificar se seu projeto Google Cloud tem as APIs necessárias habilitadas
- Verificar se o ID do projeto foi obtido corretamente durante a autenticação
### Modelos não aparecem na lista
- Verificar se a autenticação OAuth foi concluída com sucesso
- Verificar o armazenamento do perfil de autenticação: `~/.picoclaw/auth.json`
- Executar novamente `picoclaw auth login --provider antigravity`

View file

@ -0,0 +1,72 @@
> Voltar ao [README](../../README.pt-br.md)
# Usando o provedor Antigravity no PicoClaw
Este guia explica como configurar e usar o provedor **Antigravity** (Google Cloud Code Assist) no PicoClaw.
## Pré-requisitos
1. Uma conta Google.
2. Google Cloud Code Assist habilitado (geralmente disponível através da integração "Gemini for Google Cloud").
## 1. Autenticação
Para se autenticar com o Antigravity, execute o seguinte comando:
```bash
picoclaw auth login --provider antigravity
```
### Autenticação manual (Headless/VPS)
Se você está executando em um servidor (Coolify/Docker) e não consegue acessar `localhost`, siga estas etapas:
1. Execute o comando acima.
2. Copie a URL fornecida e abra-a no seu navegador local.
3. Complete o login.
4. Seu navegador será redirecionado para uma URL `localhost:51121` (que não carregará).
5. **Copie essa URL final** da barra de endereços do seu navegador.
6. **Cole-a de volta no terminal** onde o PicoClaw está aguardando.
O PicoClaw extrairá automaticamente o código de autorização e completará o processo.
## 2. Gerenciando modelos
### Listar modelos disponíveis
Para ver quais modelos seu projeto tem acesso e verificar suas cotas:
```bash
picoclaw auth models
```
### Trocar de modelo
Você pode alterar o modelo padrão em `~/.picoclaw/config.json` ou substituí-lo via CLI:
```bash
# Substituir para um único comando
picoclaw agent -m "Hello" --model claude-opus-4-6-thinking
```
## 3. Uso em produção (Coolify/Docker)
Se você está implantando via Coolify ou Docker, siga estas etapas para testar:
1. **Variáveis de ambiente**:
* `PICOCLAW_AGENTS_DEFAULTS_MODEL=gemini-flash`
2. **Persistência da autenticação**:
Se você já fez login localmente, pode copiar suas credenciais para o servidor:
```bash
scp ~/.picoclaw/auth.json user@your-server:~/.picoclaw/
```
*Alternativamente*, execute o comando `auth login` uma vez no servidor se você tiver acesso ao terminal.
## 4. Solução de problemas
* **Resposta vazia**: Se um modelo retorna uma resposta vazia, ele pode estar restrito para o seu projeto. Tente `gemini-3-flash` ou `claude-opus-4-6-thinking`.
* **429 Limite de taxa**: O Antigravity possui cotas rigorosas. O PicoClaw exibirá o "tempo de redefinição" na mensagem de erro se você atingir um limite.
* **404 Não encontrado**: Certifique-se de que está usando um ID de modelo da lista `picoclaw auth models`. Use o ID curto (ex.: `gemini-3-flash`) e não o caminho completo.
## 5. Resumo dos modelos funcionais
Com base nos testes, os seguintes modelos são os mais confiáveis:
* `gemini-3-flash` (Rápido, alta disponibilidade)
* `gemini-2.5-flash-lite` (Leve)
* `claude-opus-4-6-thinking` (Poderoso, inclui raciocínio)

View file

@ -261,7 +261,7 @@ picoclaw gateway
picoclaw gateway
```
Para opções completas (`device_id`, `join_on_invite`, `group_trigger`, `placeholder`, `reasoning_channel_id`), veja o [Guia de Configuração do Canal Matrix](docs/channels/matrix/README.md).
Para opções completas (`device_id`, `join_on_invite`, `group_trigger`, `placeholder`, `reasoning_channel_id`), veja o [Guia de Configuração do Canal Matrix](channels/matrix/README.md).
</details>
@ -396,7 +396,7 @@ picoclaw gateway
**1. Criar um AI Bot**
* Acesse o Console de Administração WeCom → Gerenciamento de Apps → AI Bot
* Nas configurações do AI Bot, configure a URL de callback: `http://your-server:18791/webhook/wecom-aibot`
* Nas configurações do AI Bot, configure a URL de callback: `http://your-server:18790/webhook/wecom-aibot`
* Copie o **Token** e clique em "Gerar Aleatoriamente" para o **EncodingAESKey**
**2. Configurar**

View file

@ -0,0 +1,158 @@
> Voltar ao [README](../../README.pt-br.md)
# Criptografia de Credenciais
O PicoClaw suporta a criptografia de valores `api_key` nas entradas de configuração `model_list`.
As chaves criptografadas são armazenadas como strings `enc://<base64>` e descriptografadas automaticamente na inicialização.
---
## Início Rápido
**1. Defina sua frase secreta**
```bash
export PICOCLAW_KEY_PASSPHRASE="your-passphrase"
```
**2. Criptografe uma chave de API**
Execute `picoclaw onboard` — ele solicita sua frase secreta e gera a chave SSH,
depois recriptografa automaticamente quaisquer entradas `api_key` em texto simples na sua configuração
na próxima chamada `SaveConfig`. O valor `enc://` resultante será semelhante a:
```
enc://AAAA...base64...
```
**3. Cole a saída na sua configuração**
```json
{
"model_list": [
{
"model_name": "gpt-4o",
"api_key": "enc://AAAA...base64...",
"api_base": "https://api.openai.com/v1"
}
]
}
```
---
## Formatos de `api_key` Suportados
| Formato | Exemplo | Comportamento |
|---------|---------|---------------|
| Texto simples | `sk-abc123` | Usado como está |
| Referência de arquivo | `file://openai.key` | Conteúdo lido do mesmo diretório do arquivo de configuração |
| Criptografado | `enc://<base64>` | Descriptografado na inicialização usando `PICOCLAW_KEY_PASSPHRASE` |
| Vazio | `""` | Passado sem alteração (usado com `auth_method: oauth`) |
---
## Design Criptográfico
### Derivação de Chave
A criptografia utiliza **HKDF-SHA256** com uma chave privada SSH como segundo fator.
```
sshHash = SHA256(ssh_private_key_file_bytes)
ikm = HMAC-SHA256(key=sshHash, message=passphrase)
aes_key = HKDF-SHA256(ikm, salt, info="picoclaw-credential-v1", 32 bytes)
```
### Criptografia
```
AES-256-GCM(key=aes_key, nonce=random[12], plaintext=api_key)
```
### Formato de Transmissão
```
enc://<base64( salt[16] + nonce[12] + ciphertext )>
```
| Campo | Tamanho | Descrição |
|-------|---------|-----------|
| `salt` | 16 bytes | Aleatório por criptografia; alimentado no HKDF |
| `nonce` | 12 bytes | Aleatório por criptografia; IV do AES-GCM |
| `ciphertext` | variável | Texto cifrado AES-256-GCM + tag de autenticação de 16 bytes |
O tag de autenticação GCM é anexado automaticamente ao texto cifrado. Qualquer adulteração faz com que a descriptografia falhe com um erro em vez de retornar texto simples corrompido.
### Desempenho
| Operação | Tempo (ARM Cortex-A) |
|----------|----------------------|
| Derivação de chave (HKDF) | < 1 ms |
| Descriptografia AES-256-GCM | < 1 ms |
| **Sobrecarga total na inicialização** | **< 2 ms por chave** |
---
## Segurança de Dois Fatores com Chave SSH
Quando uma chave privada SSH é fornecida, quebrar a criptografia requer **ambos**:
1. A **frase secreta** (`PICOCLAW_KEY_PASSPHRASE`)
2. O **arquivo de chave privada SSH**
Isso significa que um arquivo de configuração vazado sozinho não é suficiente para recuperar a chave de API, mesmo que a frase secreta seja fraca. A chave SSH contribui com 256 bits de entropia (Ed25519) independentemente da força da frase secreta.
### Modelo de Ameaça
| O que o atacante possui | Pode descriptografar? |
|------------------------|----------------------|
| Apenas o arquivo de configuração | Não — necessita da frase secreta + chave SSH |
| Apenas a chave SSH | Não — necessita da frase secreta |
| Apenas a frase secreta | Não — necessita da chave SSH |
| Arquivo de configuração + chave SSH + frase secreta | Sim — comprometimento total |
---
## Variáveis de Ambiente
| Variável | Obrigatório | Descrição |
|----------|-------------|-----------|
| `PICOCLAW_KEY_PASSPHRASE` | Sim (para `enc://`) | Frase secreta usada para derivação de chave |
| `PICOCLAW_SSH_KEY_PATH` | Não | Caminho para a chave privada SSH. Se não definido, detecta automaticamente em `~/.ssh/picoclaw_ed25519.key` |
### Detecção Automática da Chave SSH
Se `PICOCLAW_SSH_KEY_PATH` não estiver definido, o PicoClaw procura a chave dedicada:
```
~/.ssh/picoclaw_ed25519.key
```
Este arquivo dedicado evita conflitos com as chaves SSH existentes do usuário.
Execute `picoclaw onboard` para gerá-lo automaticamente.
`os.UserHomeDir()` é usado para resolução multiplataforma do diretório home (lê `USERPROFILE` no Windows, `HOME` no Unix/macOS).
> **Nota:** Um arquivo de chave SSH é obrigatório para a criptografia de credenciais. Se nenhuma chave for encontrada e `PICOCLAW_SSH_KEY_PATH` não estiver definido, a criptografia/descriptografia falhará. Execute `picoclaw onboard` para gerar a chave automaticamente.
---
## Migração
Como os únicos materiais secretos são `PICOCLAW_KEY_PASSPHRASE` e o arquivo de chave privada SSH, a migração é simples:
1. Copie o arquivo de configuração para a nova máquina.
2. Defina `PICOCLAW_KEY_PASSPHRASE` com o mesmo valor.
3. Copie o arquivo de chave privada SSH para o mesmo caminho (ou defina `PICOCLAW_SSH_KEY_PATH` para sua nova localização).
Nenhuma recriptografia é necessária.
---
## Considerações de Segurança
- **Tanto a frase secreta quanto a chave SSH são obrigatórias.** A chave SSH atua como um segundo fator — sem ela, a criptografia/descriptografia falhará. Execute `picoclaw onboard` para gerar a chave se ela não existir.
- **A chave SSH é somente leitura em tempo de execução.** O PicoClaw nunca escreve ou modifica o arquivo de chave SSH.
- **Chaves em texto simples continuam sendo suportadas.** Configurações existentes sem `enc://` não são afetadas.
- **O formato `enc://` é versionado** através do campo `info` do HKDF (`picoclaw-credential-v1`), permitindo futuras atualizações de algoritmo sem quebrar valores criptografados existentes.

36
docs/pt-br/debug.md Normal file
View file

@ -0,0 +1,36 @@
# Depuração do PicoClaw
> Voltar ao [README](../../README.pt-br.md)
O PicoClaw realiza múltiplas interações complexas nos bastidores para cada requisição que recebe — desde o roteamento de mensagens e avaliação de complexidade, até a execução de ferramentas e adaptação a falhas de modelo. Poder ver exatamente o que está acontecendo é crucial, não apenas para solucionar problemas potenciais, mas também para realmente entender como o agente opera.
## Iniciando o PicoClaw em modo de depuração
Para obter informações detalhadas sobre o que o agente está fazendo (requisições LLM, chamadas de ferramentas, roteamento de mensagens), você pode iniciar o gateway do PicoClaw com a flag de depuração:
```bash
picoclaw gateway --debug
# or
picoclaw gateway -d
```
Neste modo, o sistema formata os logs de forma detalhada e exibe prévias dos prompts do sistema e dos resultados de execução das ferramentas.
## Desabilitando a truncagem de logs (logs completos)
Por padrão, o PicoClaw trunca strings muito longas (como o *Prompt do Sistema* ou resultados JSON grandes) nos logs de depuração para manter o console legível.
Se você precisar inspecionar a saída completa de um comando ou o payload exato enviado ao modelo LLM, pode usar a flag `--no-truncate`.
**Nota:** Esta flag *só* funciona quando combinada com o modo `--debug`.
```bash
picoclaw gateway --debug --no-truncate
```
Quando esta flag está ativa, a função de truncagem global é desabilitada. Isso é extremamente útil para:
* Verificar a sintaxe exata das mensagens enviadas ao provedor.
* Ler a saída completa de ferramentas como `exec`, `web_fetch` ou `read_file`.
* Depurar o histórico de sessão salvo na memória.

View file

@ -0,0 +1,152 @@
> Voltar ao [README](../../README.pt-br.md)
# 🖥️ PicoClaw Lista de compatibilidade de hardware
O PicoClaw roda em praticamente qualquer dispositivo Linux. Esta página registra chips, produtos e placas de desenvolvimento verificados.
**Seu hardware não está na lista?** Envie um PR para adicioná-lo! Fabricantes de hardware são bem-vindos para contribuir e co-promover.
---
## 1. Suporte a chips verificado
### x86
| Fabricante | Chip | Notas |
|------------|------|-------|
| Intel | Any x86 CPU (i386+) | Todos os processadores desktop/servidor/notebook |
| AMD | Any x86 CPU | Todos os processadores desktop/servidor/notebook |
### ARM
| Sub-arq | Chips típicos | Notas |
|---------|---------------|-------|
| ARMv6 | [BCM2835](https://www.raspberrypi.com/documentation/computers/processors.html#bcm2835) (Raspberry Pi 1/Zero) | Single-core ARM1176JZF-S |
| ARMv7 | [Allwinner V3s](https://linux-sunxi.org/V3s) | Single-core Cortex-A7, usado no LicheePi Zero |
| ARM64 | [Allwinner H618](https://linux-sunxi.org/H618) | Quad-core Cortex-A53, usado no Orange Pi Zero 3 |
| ARM64 | [BCM2711](https://www.raspberrypi.com/documentation/computers/processors.html#bcm2711) (Raspberry Pi 4) | Quad-core Cortex-A72 |
| ARM64 | [BCM2712](https://www.raspberrypi.com/documentation/computers/processors.html#bcm2712) (Raspberry Pi 5) | Quad-core Cortex-A76 |
| ARM64 | [AX630C](https://www.axera-tech.com/) (爱芯元智) | Dual-core Cortex-A53 + NPU, usado no NanoKVM-Pro / MaixCAM2 |
### RISC-V (riscv64)
| Fabricante | Chip | Núcleo | Notas |
|------------|------|--------|-------|
| [SOPHGO (算能)](https://www.sophgo.com/) | SG2002 | C906 @ 1GHz | 256MB DDR3 integrado, usado no LicheeRV-Nano / NanoKVM / MaixCAM |
| [Allwinner (全志)](https://www.allwinnertech.com/) | V861 | Dual C907 | 128MB DDR3L integrado, 1 TOPS NPU, câmera AI 4K SiP |
| [Allwinner (全志)](https://www.allwinnertech.com/) | V881 | C907 | Série de câmeras AI RISC-V |
| [Arterytek (匠芯创)](https://www.arterytek.com/) | D213 | RISC-V | Usado no HaaS506-LD1 RTU industrial |
| [SpacemiT (进迭)](https://www.spacemit.com/) | K1 | 8x X60 @ 1.8GHz | Usado no Milk-V Jupiter, BananaPi BPI-F3 |
| [SpacemiT (进迭)](https://www.spacemit.com/) | K3 | 8x X100 @ 2.5GHz | Compatível com RVA23, RVV de 1024 bits, inferência AI FP8 |
| [Zhihe (知合)](https://www.zhihe-tech.com/) | A210 | High-perf RISC-V | 8 núcleos, 16MB cache L3, classe desktop |
| [Canaan (嘉楠)](https://www.canaan-creative.com/) | K230 | Dual C908 @ 1.6GHz | 6 TOPS KPU, usado no CanMV-K230 |
### MIPS
| Fabricante | Chip | Notas |
|------------|------|-------|
| MediaTek | [MT7620](https://www.mediatek.com/products/home-networking/mt7620) | MIPS24KEc @ 580MHz, usado em muitos roteadores OpenWrt (ex. Xiaomi Router 3G) |
### LoongArch (loong64)
| Fabricante | Chip | Notas |
|------------|------|-------|
| [Loongson (龙芯)](https://www.loongson.cn/) | 3A5000 | Quad-core LA464 @ 2.5GHz, desktop/estação de trabalho |
| [Loongson (龙芯)](https://www.loongson.cn/) | 3A6000 | Quad-core 4C/8T @ 2.5GHz, IPC comparável ao Intel 10ª geração |
| [Loongson (龙芯)](https://www.loongson.cn/) | 2K1000LA | Dual-core @ 1GHz, aplicações industriais/IoT |
---
## 2. Produtos verificados (por data de lançamento)
Produtos de consumo, roteadores e dispositivos industriais testados com o PicoClaw.
| Ano | Produto | Arq | SoC | RAM | Categoria |
|-----|---------|-----|-----|-----|-----------|
| 2009 | Nokia N900 | ARM (A8) | OMAP3430 | 256MB | Smartphone |
| 2012 | Samsung Galaxy Note 10.1 (N8000) | ARM (A9) | Exynos 4412 | 2GB | Tablet |
| 2016 | Xiaomi Router 3G (小米路由器3G) | MIPS | MT7620 | 256MB | Roteador (OpenWrt) |
| 2018 | Phicomm N1 (斐讯N1) | ARM64 (A53) | S905D | 2GB | TV Box / Servidor doméstico |
| 2019 | Xiaomi AI Speaker (小爱音箱) | ARM64 (A53) | — | 256MB | Alto-falante inteligente |
| 2024 | [NanoKVM](https://wiki.sipeed.com/hardware/en/kvm/NanoKVM/introduction.html) | RISC-V | SG2002 | 256MB | IP-KVM |
| 2025 | HaaS506-LD1 | RISC-V | D213 | 128MB | RTU industrial |
| 2025 | [NanoKVM-Pro](https://wiki.sipeed.com/hardware/en/kvm/NanoKVM_Pro/introduction.html) | ARM64 (A53) | AX630C | 1GB | IP-KVM Pro |
| 2026 | [MaixCAM2](https://wiki.sipeed.com/hardware/en/maixcam/index.html) | ARM64 (A53) | AX630C | 1/4GB | Câmera AI 4K |
---
## 3. Placas de desenvolvimento verificadas (por data de lançamento)
| Ano | Placa | Arq | SoC | RAM | Link de compra |
|-----|-------|-----|-----|-----|----------------|
| 2012 | [Raspberry Pi 1 Model B](https://www.raspberrypi.com/products/) | ARMv6 | BCM2835 | 512MB | — |
| 2015 | [Raspberry Pi 2 Model B](https://www.raspberrypi.com/products/raspberry-pi-2-model-b/) | ARMv7 (A7) | BCM2836 | 1GB | — |
| 2015 | [Raspberry Pi Zero](https://www.raspberrypi.com/products/raspberry-pi-zero/) | ARMv6 | BCM2835 | 512MB | — |
| 2016 | [Raspberry Pi 3 Model B](https://www.raspberrypi.com/products/raspberry-pi-3-model-b/) | ARM64 (A53) | BCM2837 | 1GB | — |
| 2017 | [LicheePi Zero](https://wiki.sipeed.com/hardware/en/lichee/Zero/Zero.html) | ARMv7 (A7) | Allwinner V3s | 64MB | [Sipeed](https://sipeed.com/) |
| 2019 | [Raspberry Pi 4 Model B](https://www.raspberrypi.com/products/raspberry-pi-4-model-b/) | ARM64 (A72) | BCM2711 | 1~8GB | [RPi](https://www.raspberrypi.com/) |
| 2023 | [Raspberry Pi 5](https://www.raspberrypi.com/products/raspberry-pi-5/) | ARM64 (A76) | BCM2712 | 2~8GB | [RPi](https://www.raspberrypi.com/) |
| 2024 | [LicheeRV-Nano](https://wiki.sipeed.com/hardware/en/lichee/RV_Nano/1_intro.html) | RISC-V | SG2002 | 256MB | [AliExpress](https://www.aliexpress.com/item/1005006519668532.html) |
| 2024 | [MaixCAM-Pro](https://wiki.sipeed.com/hardware/en/maixcam/index.html) | RISC-V | SG2002 | 256MB | [Sipeed](https://sipeed.com/) |
| 2024 | [Milk-V Duo 64M](https://milkv.io/docs/duo/getting-started/duo) | RISC-V | CV1800B | 64MB | [Milk-V](https://milkv.io/) |
| 2024 | [CanMV-K230](https://developer.canaan-creative.com/k230_canmv/en/main/) | RISC-V | K230 | 512MB | [Canaan](https://www.canaan-creative.com/) |
---
## 4. Também funciona em
### Celulares Android (via Termux)
Qualquer celular Android ARM64 (2015+) com 1GB+ de RAM. Instale o [Termux](https://github.com/termux/termux-app), use `proot` para rodar o PicoClaw.
> Veja [README: Rodar em celulares Android antigos](../README.md#-run-on-old-android-phones) para instruções de configuração.
### Desktop / Servidor / Nuvem
| Plataforma | Notas |
|------------|-------|
| x86_64 Linux | Binário nativo, sem dependências |
| x86_64 Windows | Binário nativo |
| macOS (Intel / Apple Silicon) | Binário nativo |
| Docker (any platform) | `docker compose` em uma linha, veja [Guia Docker](docker.md) |
| OpenWrt routers | Builds MIPS/ARM, requer >32MB de RAM livre |
| FreeBSD / NetBSD | Builds x86_64 e arm64 disponíveis |
---
## 5. Requisitos mínimos
| Recurso | Mínimo | Recomendado |
|---------|--------|-------------|
| RAM | 10MB livres | 32MB+ livres |
| Armazenamento | 20MB (binário) | 50MB+ (com workspace) |
| CPU | Qualquer (single-core 0,6GHz+) | — |
| OS | Linux (kernel 3.x+) | Linux 5.x+ |
| Rede | Necessária (para chamadas de API LLM) | Ethernet ou WiFi |
---
## 6. Como testar e contribuir
```bash
# 1. Baixar para sua arquitetura
wget https://github.com/sipeed/picoclaw/releases/latest/download/picoclaw_Linux_arm64.tar.gz
tar xzf picoclaw_Linux_arm64.tar.gz
# 2. Inicializar
./picoclaw onboard
# 3. Testar
./picoclaw agent -m "Hello, what board am I running on?"
```
Builds disponíveis: `linux-amd64`, `linux-arm64`, `linux-arm`, `linux-riscv64`, `linux-loong64`, `linux-mipsle`
### Adicionar seu hardware
1. Faça fork deste repositório
2. Adicione seu chip / produto / placa na tabela apropriada
3. Inclua: nome, arquitetura, SoC, RAM, ano e um link se disponível
4. Envie um PR
Fabricantes de hardware: deseja adicionar suporte oficial ou co-promover? Abra uma issue ou entre em contato via [Discord](https://discord.gg/V4sAZ9XWpN).

View file

@ -16,7 +16,7 @@
**Correção:** Em `~/.picoclaw/config.json` (ou seu caminho de configuração):
1. **agents.defaults.model** deve corresponder a um `model_name` em `model_list` (ex.: `"openrouter-free"`).
1. **agents.defaults.model_name** deve corresponder a um `model_name` em `model_list` (ex.: `"openrouter-free"`).
2. O **model** dessa entrada deve ser um ID de modelo OpenRouter válido, por exemplo:
- `"openrouter/free"` nível gratuito automático
- `"google/gemini-2.0-flash-exp:free"`
@ -28,7 +28,7 @@ Exemplo:
{
"agents": {
"defaults": {
"model": "openrouter-free"
"model_name": "openrouter-free"
}
},
"model_list": [

View file

@ -2,6 +2,15 @@
> Back to [README](../README.md)
PicoClaw supports **asynchronous task execution** via the `spawn` tool. This is primarily used by the **Heartbeat** system to run long-running tasks without blocking the main agent loop.
## Heartbeat
The heartbeat system periodically checks `workspace/HEARTBEAT.md` for scheduled tasks. On first run, a default template is auto-generated. You can customize it to define quick tasks (handled inline) and long tasks (delegated via `spawn`).
**Example `HEARTBEAT.md`:**
```markdown
## Quick Tasks (respond directly)
- Report current time

View file

@ -41,11 +41,12 @@ General settings for fetching and processing webpage content.
### Brave
| Config | Type | Default | Description |
|---------------|--------|---------|---------------------------|
| `enabled` | bool | false | Enable Brave search |
| `api_key` | string | - | Brave Search API key |
| `max_results` | int | 5 | Maximum number of results |
| Config | Type | Default | Description |
|---------------|----------|---------|------------------------------------------------|
| `enabled` | bool | false | Enable Brave search |
| `api_key` | string | - | Brave Search API key |
| `api_keys` | string[] | - | Multiple API keys for rotation (takes priority over `api_key`) |
| `max_results` | int | 5 | Maximum number of results |
### DuckDuckGo
@ -56,11 +57,46 @@ General settings for fetching and processing webpage content.
### Perplexity
| Config | Type | Default | Description |
|---------------|----------|---------|------------------------------------------------|
| `enabled` | bool | false | Enable Perplexity search |
| `api_key` | string | - | Perplexity API key |
| `api_keys` | string[] | - | Multiple API keys for rotation (takes priority over `api_key`) |
| `max_results` | int | 5 | Maximum number of results |
### Tavily
| Config | Type | Default | Description |
|---------------|--------|---------|---------------------------|
| `enabled` | bool | false | Enable Perplexity search |
| `api_key` | string | - | Perplexity API key |
| `max_results` | int | 5 | Maximum number of results |
| `enabled` | bool | false | Enable Tavily search |
| `api_key` | string | - | Tavily API key |
| `base_url` | string | - | Custom Tavily API base URL |
| `max_results` | int | 0 | Maximum number of results (0 = default) |
### SearXNG
| Config | Type | Default | Description |
|---------------|--------|--------------------------|---------------------------|
| `enabled` | bool | false | Enable SearXNG search |
| `base_url` | string | `http://localhost:8888` | SearXNG instance URL |
| `max_results` | int | 5 | Maximum number of results |
### GLM Search
| Config | Type | Default | Description |
|-----------------|--------|------------------------------------------------------|---------------------------|
| `enabled` | bool | false | Enable GLM Search |
| `api_key` | string | - | GLM API key |
| `base_url` | string | `https://open.bigmodel.cn/api/paas/v4/web_search` | GLM Search API URL |
| `search_engine` | string | `search_std` | Search engine type |
| `max_results` | int | 5 | Maximum number of results |
### Additional Web Settings
| Config | Type | Default | Description |
|--------------------------|----------|---------|----------------------------------------------------------------|
| `prefer_native` | bool | true | Prefer provider's native search over configured search engines |
| `private_host_whitelist` | string[] | `[]` | Private/internal hosts allowed for web fetching |
## Exec Tool
@ -155,6 +191,7 @@ The cron tool is used for scheduling periodic tasks.
| Config | Type | Default | Description |
|------------------------|------|---------|------------------------------------------------|
| `exec_timeout_minutes` | int | 5 | Execution timeout in minutes, 0 means no limit |
| `allow_command` | bool | false | Allow cron tasks to execute shell commands |
## MCP Tool
@ -370,9 +407,27 @@ The skills tool configures skill discovery and installation via registries like
| `registries.clawhub.enabled` | bool | true | Enable ClawHub registry |
| `registries.clawhub.base_url` | string | `https://clawhub.ai` | ClawHub base URL |
| `registries.clawhub.auth_token` | string | `""` | Optional Bearer token for higher rate limits |
| `registries.clawhub.search_path` | string | `/api/v1/search` | Search API path |
| `registries.clawhub.skills_path` | string | `/api/v1/skills` | Skills API path |
| `registries.clawhub.download_path` | string | `/api/v1/download` | Download API path |
| `registries.clawhub.search_path` | string | `""` | Search API path |
| `registries.clawhub.skills_path` | string | `""` | Skills API path |
| `registries.clawhub.download_path` | string | `""` | Download API path |
| `registries.clawhub.timeout` | int | 0 | Request timeout in seconds (0 = default) |
| `registries.clawhub.max_zip_size` | int | 0 | Max skill zip size in bytes (0 = default) |
| `registries.clawhub.max_response_size` | int | 0 | Max API response size in bytes (0 = default) |
### GitHub Integration
| Config | Type | Default | Description |
|------------------|--------|---------|--------------------------------------|
| `github.proxy` | string | `""` | HTTP proxy for GitHub API requests |
| `github.token` | string | `""` | GitHub personal access token |
### Search Settings
| Config | Type | Default | Description |
|---------------------------|------|---------|--------------------------------------------|
| `max_concurrent_searches` | int | 2 | Max concurrent skill search requests |
| `search_cache.max_size` | int | 50 | Max cached search results |
| `search_cache.ttl_seconds`| int | 300 | Cache TTL in seconds |
### Configuration Example
@ -384,11 +439,17 @@ The skills tool configures skill discovery and installation via registries like
"clawhub": {
"enabled": true,
"base_url": "https://clawhub.ai",
"auth_token": "",
"search_path": "/api/v1/search",
"skills_path": "/api/v1/skills",
"download_path": "/api/v1/download"
"auth_token": ""
}
},
"github": {
"proxy": "",
"token": ""
},
"max_concurrent_searches": 2,
"search_cache": {
"max_size": 50,
"ttl_seconds": 300
}
}
}

View file

@ -14,7 +14,7 @@
**Fix:** In `~/.picoclaw/config.json` (or your config path):
1. **agents.defaults.model** must match a `model_name` in `model_list` (e.g. `"openrouter-free"`).
1. **agents.defaults.model_name** must match a `model_name` in `model_list` (e.g. `"openrouter-free"`).
2. That entrys **model** must be a valid OpenRouter model ID, for example:
- `"openrouter/free"` auto free-tier
- `"google/gemini-2.0-flash-exp:free"`
@ -26,7 +26,7 @@ Example snippet:
{
"agents": {
"defaults": {
"model": "openrouter-free"
"model_name": "openrouter-free"
}
},
"model_list": [

807
docs/vi/ANTIGRAVITY_AUTH.md Normal file
View file

@ -0,0 +1,807 @@
> Quay lại [README](../../README.vi.md)
# Hướng dẫn Xác thực và Tích hợp Antigravity
## Tổng quan
**Antigravity** (Google Cloud Code Assist) là nhà cung cấp mô hình AI được Google hỗ trợ, cung cấp quyền truy cập vào các mô hình như Claude Opus 4.6 và Gemini thông qua hạ tầng đám mây của Google. Tài liệu này cung cấp hướng dẫn đầy đủ về cách xác thực hoạt động, cách lấy danh sách mô hình và cách triển khai nhà cung cấp mới trong PicoClaw.
---
## Mục lục
1. [Luồng xác thực](#luồng-xác-thực)
2. [Chi tiết triển khai OAuth](#chi-tiết-triển-khai-oauth)
3. [Quản lý token](#quản-lý-token)
4. [Lấy danh sách mô hình](#lấy-danh-sách-mô-hình)
5. [Theo dõi mức sử dụng](#theo-dõi-mức-sử-dụng)
6. [Cấu trúc plugin nhà cung cấp](#cấu-trúc-plugin-nhà-cung-cấp)
7. [Yêu cầu tích hợp](#yêu-cầu-tích-hợp)
8. [Các endpoint API](#các-endpoint-api)
9. [Cấu hình](#cấu-hình)
10. [Tạo nhà cung cấp mới trong PicoClaw](#tạo-nhà-cung-cấp-mới-trong-picoclaw)
---
## Luồng xác thực
### 1. OAuth 2.0 với PKCE
Antigravity sử dụng **OAuth 2.0 với PKCE (Proof Key for Code Exchange)** để xác thực an toàn:
```
┌─────────────┐ ┌─────────────────┐
│ Client │ ───(1) Generate PKCE Pair────────> │ │
│ │ ───(2) Open Auth URL─────────────> │ Google OAuth │
│ │ │ Server │
│ │ <──(3) Redirect with Code───────── │ │
│ │ └─────────────────┘
│ │ ───(4) Exchange Code for Tokens──> │ Token URL │
│ │ │ │
│ │ <──(5) Access + Refresh Tokens──── │ │
└─────────────┘ └─────────────────┘
```
### 2. Các bước chi tiết
#### Bước 1: Tạo tham số PKCE
```typescript
function generatePkce(): { verifier: string; challenge: string } {
const verifier = randomBytes(32).toString("hex");
const challenge = createHash("sha256").update(verifier).digest("base64url");
return { verifier, challenge };
}
```
#### Bước 2: Xây dựng URL ủy quyền
```typescript
const AUTH_URL = "https://accounts.google.com/o/oauth2/v2/auth";
const REDIRECT_URI = "http://localhost:51121/oauth-callback";
function buildAuthUrl(params: { challenge: string; state: string }): string {
const url = new URL(AUTH_URL);
url.searchParams.set("client_id", CLIENT_ID);
url.searchParams.set("response_type", "code");
url.searchParams.set("redirect_uri", REDIRECT_URI);
url.searchParams.set("scope", SCOPES.join(" "));
url.searchParams.set("code_challenge", params.challenge);
url.searchParams.set("code_challenge_method", "S256");
url.searchParams.set("state", params.state);
url.searchParams.set("access_type", "offline");
url.searchParams.set("prompt", "consent");
return url.toString();
}
```
**Các phạm vi quyền cần thiết:**
```typescript
const SCOPES = [
"https://www.googleapis.com/auth/cloud-platform",
"https://www.googleapis.com/auth/userinfo.email",
"https://www.googleapis.com/auth/userinfo.profile",
"https://www.googleapis.com/auth/cclog",
"https://www.googleapis.com/auth/experimentsandconfigs",
];
```
#### Bước 3: Xử lý callback OAuth
**Chế độ tự động (Phát triển cục bộ):**
- Khởi động máy chủ HTTP cục bộ trên cổng 51121
- Chờ chuyển hướng từ Google
- Trích xuất mã ủy quyền từ tham số truy vấn
**Chế độ thủ công (Từ xa/Không có giao diện):**
- Hiển thị URL ủy quyền cho người dùng
- Người dùng hoàn tất xác thực trong trình duyệt
- Người dùng dán URL chuyển hướng đầy đủ vào terminal
- Phân tích mã từ URL đã dán
#### Bước 4: Đổi mã lấy token
```typescript
const TOKEN_URL = "https://oauth2.googleapis.com/token";
async function exchangeCode(params: {
code: string;
verifier: string;
}): Promise<{ access: string; refresh: string; expires: number }> {
const response = await fetch(TOKEN_URL, {
method: "POST",
headers: { "Content-Type": "application/x-www-form-urlencoded" },
body: new URLSearchParams({
client_id: CLIENT_ID,
client_secret: CLIENT_SECRET,
code: params.code,
grant_type: "authorization_code",
redirect_uri: REDIRECT_URI,
code_verifier: params.verifier,
}),
});
const data = await response.json();
return {
access: data.access_token,
refresh: data.refresh_token,
expires: Date.now() + data.expires_in * 1000 - 5 * 60 * 1000, // 5 min buffer
};
}
```
#### Bước 5: Lấy dữ liệu người dùng bổ sung
**Email người dùng:**
```typescript
async function fetchUserEmail(accessToken: string): Promise<string | undefined> {
const response = await fetch(
"https://www.googleapis.com/oauth2/v1/userinfo?alt=json",
{ headers: { Authorization: `Bearer ${accessToken}` } }
);
const data = await response.json();
return data.email;
}
```
**ID dự án (Bắt buộc cho các lệnh gọi API):**
```typescript
async function fetchProjectId(accessToken: string): Promise<string> {
const headers = {
Authorization: `Bearer ${accessToken}`,
"Content-Type": "application/json",
"User-Agent": "google-api-nodejs-client/9.15.1",
"X-Goog-Api-Client": "google-cloud-sdk vscode_cloudshelleditor/0.1",
"Client-Metadata": JSON.stringify({
ideType: "IDE_UNSPECIFIED",
platform: "PLATFORM_UNSPECIFIED",
pluginType: "GEMINI",
}),
};
const response = await fetch(
"https://cloudcode-pa.googleapis.com/v1internal:loadCodeAssist",
{
method: "POST",
headers,
body: JSON.stringify({
metadata: {
ideType: "IDE_UNSPECIFIED",
platform: "PLATFORM_UNSPECIFIED",
pluginType: "GEMINI",
},
}),
}
);
const data = await response.json();
return data.cloudaicompanionProject || "rising-fact-p41fc"; // Giá trị mặc định dự phòng
}
```
---
## Chi tiết triển khai OAuth
### Thông tin xác thực client
**Quan trọng:** Các giá trị này được mã hóa base64 trong mã nguồn để đồng bộ với pi-ai:
```typescript
const decode = (s: string) => Buffer.from(s, "base64").toString();
const CLIENT_ID = decode(
"MTA3MTAwNjA2MDU5MS10bWhzc2luMmgyMWxjcmUyMzV2dG9sb2poNGc0MDNlcC5hcHBzLmdvb2dsZXVzZXJjb250ZW50LmNvbQ=="
);
const CLIENT_SECRET = decode("R09DU1BYLUs1OEZXUjQ4NkxkTEoxbUxCOHNYQzR6NnFEQWY=");
```
### Các chế độ luồng OAuth
1. **Luồng tự động** (Máy cục bộ có trình duyệt):
- Tự động mở trình duyệt
- Máy chủ callback cục bộ bắt chuyển hướng
- Không cần tương tác người dùng sau xác thực ban đầu
2. **Luồng thủ công** (Từ xa/Không có giao diện/WSL2):
- Hiển thị URL để sao chép-dán thủ công
- Người dùng hoàn tất xác thực trong trình duyệt bên ngoài
- Người dùng dán lại URL chuyển hướng đầy đủ
```typescript
function shouldUseManualOAuthFlow(isRemote: boolean): boolean {
return isRemote || isWSL2Sync();
}
```
---
## Quản lý token
### Cấu trúc hồ sơ xác thực
```typescript
type OAuthCredential = {
type: "oauth";
provider: "google-antigravity";
access: string; // Token truy cập
refresh: string; // Token làm mới
expires: number; // Dấu thời gian hết hạn (ms kể từ epoch)
email?: string; // Email người dùng
projectId?: string; // ID dự án Google Cloud
};
```
### Làm mới token
Thông tin xác thực bao gồm token làm mới có thể được sử dụng để lấy token truy cập mới khi token hiện tại hết hạn. Thời gian hết hạn được đặt với bộ đệm 5 phút để tránh điều kiện tranh chấp.
---
## Lấy danh sách mô hình
### Lấy các mô hình khả dụng
```typescript
const BASE_URL = "https://cloudcode-pa.googleapis.com";
async function fetchAvailableModels(
accessToken: string,
projectId: string
): Promise<Model[]> {
const headers = {
Authorization: `Bearer ${accessToken}`,
"Content-Type": "application/json",
"User-Agent": "antigravity",
"X-Goog-Api-Client": "google-cloud-sdk vscode_cloudshelleditor/0.1",
};
const response = await fetch(
`${BASE_URL}/v1internal:fetchAvailableModels`,
{
method: "POST",
headers,
body: JSON.stringify({ project: projectId }),
}
);
const data = await response.json();
// Trả về các mô hình kèm thông tin hạn mức
return Object.entries(data.models).map(([modelId, modelInfo]) => ({
id: modelId,
displayName: modelInfo.displayName,
quotaInfo: {
remainingFraction: modelInfo.quotaInfo?.remainingFraction,
resetTime: modelInfo.quotaInfo?.resetTime,
isExhausted: modelInfo.quotaInfo?.isExhausted,
},
}));
}
```
### Định dạng phản hồi
```typescript
type FetchAvailableModelsResponse = {
models?: Record<string, {
displayName?: string;
quotaInfo?: {
remainingFraction?: number | string;
resetTime?: string; // Dấu thời gian ISO 8601
isExhausted?: boolean;
};
}>;
};
```
---
## Theo dõi mức sử dụng
### Lấy dữ liệu sử dụng
```typescript
export async function fetchAntigravityUsage(
token: string,
timeoutMs: number
): Promise<ProviderUsageSnapshot> {
// 1. Lấy thông tin tín dụng và gói dịch vụ
const loadCodeAssistRes = await fetch(
`${BASE_URL}/v1internal:loadCodeAssist`,
{
method: "POST",
headers: {
Authorization: `Bearer ${token}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
metadata: {
ideType: "ANTIGRAVITY",
platform: "PLATFORM_UNSPECIFIED",
pluginType: "GEMINI",
},
}),
}
);
// Trích xuất thông tin tín dụng
const { availablePromptCredits, planInfo, currentTier } = data;
// 2. Lấy hạn mức mô hình
const modelsRes = await fetch(
`${BASE_URL}/v1internal:fetchAvailableModels`,
{
method: "POST",
headers: { Authorization: `Bearer ${token}` },
body: JSON.stringify({ project: projectId }),
}
);
// Xây dựng cửa sổ sử dụng
return {
provider: "google-antigravity",
displayName: "Google Antigravity",
windows: [
{ label: "Credits", usedPercent: calculateUsedPercent(available, monthly) },
// Hạn mức từng mô hình...
],
plan: currentTier?.name || planType,
};
}
```
### Cấu trúc phản hồi sử dụng
```typescript
type ProviderUsageSnapshot = {
provider: "google-antigravity";
displayName: string;
windows: UsageWindow[];
plan?: string;
error?: string;
};
type UsageWindow = {
label: string; // "Credits" hoặc ID mô hình
usedPercent: number; // 0-100
resetAt?: number; // Dấu thời gian khi hạn mức được đặt lại
};
```
---
## Cấu trúc plugin nhà cung cấp
### Định nghĩa plugin
```typescript
const antigravityPlugin = {
id: "google-antigravity-auth",
name: "Google Antigravity Auth",
description: "OAuth flow for Google Antigravity (Cloud Code Assist)",
configSchema: emptyPluginConfigSchema(),
register(api: PicoClawPluginApi) {
api.registerProvider({
id: "google-antigravity",
label: "Google Antigravity",
docsPath: "/providers/models",
aliases: ["antigravity"],
auth: [
{
id: "oauth",
label: "Google OAuth",
hint: "PKCE + localhost callback",
kind: "oauth",
run: async (ctx: ProviderAuthContext) => {
// Triển khai OAuth tại đây
},
},
],
});
},
};
```
### ProviderAuthContext
```typescript
type ProviderAuthContext = {
config: PicoClawConfig;
agentDir?: string;
workspaceDir?: string;
prompter: WizardPrompter; // Lời nhắc/thông báo UI
runtime: RuntimeEnv; // Ghi log, v.v.
isRemote: boolean; // Có đang chạy từ xa không
openUrl: (url: string) => Promise<void>; // Mở trình duyệt
oauth: {
createVpsAwareHandlers: Function;
};
};
```
### ProviderAuthResult
```typescript
type ProviderAuthResult = {
profiles: Array<{
profileId: string;
credential: AuthProfileCredential;
}>;
configPatch?: Partial<PicoClawConfig>;
defaultModel?: string;
notes?: string[];
};
```
---
## Yêu cầu tích hợp
### 1. Môi trường/Phụ thuộc cần thiết
- Go ≥ 1.25
- Mã nguồn PicoClaw (`pkg/providers/``pkg/auth/`)
- Các gói thư viện chuẩn `crypto``net/http`
### 2. Các header bắt buộc cho lệnh gọi API
```typescript
const REQUIRED_HEADERS = {
"Authorization": `Bearer ${accessToken}`,
"Content-Type": "application/json",
"User-Agent": "antigravity", // hoặc "google-api-nodejs-client/9.15.1"
"X-Goog-Api-Client": "google-cloud-sdk vscode_cloudshelleditor/0.1",
};
// Đối với các lệnh gọi loadCodeAssist, cũng bao gồm:
const CLIENT_METADATA = {
ideType: "ANTIGRAVITY", // hoặc "IDE_UNSPECIFIED"
platform: "PLATFORM_UNSPECIFIED",
pluginType: "GEMINI",
};
```
### 3. Làm sạch schema mô hình
Antigravity sử dụng các mô hình tương thích Gemini, vì vậy schema công cụ phải được làm sạch:
```typescript
const GOOGLE_SCHEMA_UNSUPPORTED_KEYWORDS = new Set([
"patternProperties",
"additionalProperties",
"$schema",
"$id",
"$ref",
"$defs",
"definitions",
"examples",
"minLength",
"maxLength",
"minimum",
"maximum",
"multipleOf",
"pattern",
"format",
"minItems",
"maxItems",
"uniqueItems",
"minProperties",
"maxProperties",
]);
// Làm sạch schema trước khi gửi
function cleanToolSchemaForGemini(schema: Record<string, unknown>): unknown {
// Xóa các từ khóa không được hỗ trợ
// Đảm bảo cấp cao nhất có type: "object"
// Làm phẳng các union anyOf/oneOf
}
```
### 4. Xử lý khối suy nghĩ (Mô hình Claude)
Đối với các mô hình Claude qua Antigravity, khối suy nghĩ cần xử lý đặc biệt:
```typescript
const ANTIGRAVITY_SIGNATURE_RE = /^[A-Za-z0-9+/]+={0,2}$/;
export function sanitizeAntigravityThinkingBlocks(
messages: AgentMessage[]
): AgentMessage[] {
// Xác thực chữ ký suy nghĩ
// Chuẩn hóa các trường chữ ký
// Loại bỏ các khối suy nghĩ chưa ký
}
```
---
## Các endpoint API
### Endpoint xác thực
| Endpoint | Phương thức | Mục đích |
|----------|------------|----------|
| `https://accounts.google.com/o/oauth2/v2/auth` | GET | Ủy quyền OAuth |
| `https://oauth2.googleapis.com/token` | POST | Trao đổi token |
| `https://www.googleapis.com/oauth2/v1/userinfo` | GET | Thông tin người dùng (email) |
### Endpoint Cloud Code Assist
| Endpoint | Phương thức | Mục đích |
|----------|------------|----------|
| `https://cloudcode-pa.googleapis.com/v1internal:loadCodeAssist` | POST | Tải thông tin dự án, tín dụng, gói dịch vụ |
| `https://cloudcode-pa.googleapis.com/v1internal:fetchAvailableModels` | POST | Liệt kê các mô hình khả dụng kèm hạn mức |
| `https://cloudcode-pa.googleapis.com/v1internal:streamGenerateContent?alt=sse` | POST | Endpoint streaming chat |
**Định dạng yêu cầu API (Chat):**
Endpoint `v1internal:streamGenerateContent` yêu cầu một envelope bao bọc yêu cầu Gemini tiêu chuẩn:
```json
{
"project": "your-project-id",
"model": "model-id",
"request": {
"contents": [...],
"systemInstruction": {...},
"generationConfig": {...},
"tools": [...]
},
"requestType": "agent",
"userAgent": "antigravity",
"requestId": "agent-timestamp-random"
}
```
**Định dạng phản hồi API (SSE):**
Mỗi thông điệp SSE (`data: {...}`) được bao bọc trong trường `response`:
```json
{
"response": {
"candidates": [...],
"usageMetadata": {...},
"modelVersion": "...",
"responseId": "..."
},
"traceId": "...",
"metadata": {}
}
```
---
## Cấu hình
### Cấu hình config.json
```json
{
"model_list": [
{
"model_name": "gemini-flash",
"model": "antigravity/gemini-3-flash",
"auth_method": "oauth"
}
],
"agents": {
"defaults": {
"model": "gemini-flash"
}
}
}
```
### Lưu trữ hồ sơ xác thực
Hồ sơ xác thực được lưu trữ trong `~/.picoclaw/auth.json`:
```json
{
"credentials": {
"google-antigravity": {
"access_token": "ya29...",
"refresh_token": "1//...",
"expires_at": "2026-01-01T00:00:00Z",
"provider": "google-antigravity",
"auth_method": "oauth",
"email": "user@example.com",
"project_id": "my-project-id"
}
}
}
```
---
## Tạo nhà cung cấp mới trong PicoClaw
Các nhà cung cấp PicoClaw được triển khai dưới dạng gói Go trong `pkg/providers/`. Để thêm nhà cung cấp mới:
### Triển khai từng bước
#### 1. Tạo file nhà cung cấp
Tạo file Go mới trong `pkg/providers/`:
```
pkg/providers/
└── your_provider.go
```
#### 2. Triển khai interface Provider
Nhà cung cấp của bạn phải triển khai interface `Provider` được định nghĩa trong `pkg/providers/types.go`:
```go
package providers
type YourProvider struct {
apiKey string
apiBase string
}
func NewYourProvider(apiKey, apiBase, proxy string) *YourProvider {
if apiBase == "" {
apiBase = "https://api.your-provider.com/v1"
}
return &YourProvider{apiKey: apiKey, apiBase: apiBase}
}
func (p *YourProvider) Chat(ctx context.Context, messages []Message, tools []Tool, cb StreamCallback) error {
// Triển khai hoàn thành chat với streaming
}
```
#### 3. Đăng ký trong factory
Thêm nhà cung cấp của bạn vào switch giao thức trong `pkg/providers/factory.go`:
```go
case "your-provider":
return NewYourProvider(sel.apiKey, sel.apiBase, sel.proxy), nil
```
#### 4. Thêm cấu hình mặc định (Tùy chọn)
Thêm mục mặc định trong `pkg/config/defaults.go`:
```go
{
ModelName: "your-model",
Model: "your-provider/model-name",
APIKey: "",
},
```
#### 5. Thêm hỗ trợ xác thực (Tùy chọn)
Nếu nhà cung cấp của bạn yêu cầu OAuth hoặc xác thực đặc biệt, thêm case vào `cmd/picoclaw/internal/auth/helpers.go`:
```go
case "your-provider":
authLoginYourProvider()
```
#### 6. Cấu hình qua `config.json`
```json
{
"model_list": [
{
"model_name": "your-model",
"model": "your-provider/model-name",
"api_key": "your-api-key",
"api_base": "https://api.your-provider.com/v1"
}
]
}
```
---
## Kiểm thử triển khai của bạn
### Lệnh CLI
```bash
# Xác thực với nhà cung cấp
picoclaw auth login --provider your-provider
# Liệt kê mô hình (cho Antigravity)
picoclaw auth models
# Khởi động gateway
picoclaw gateway
# Chạy agent với mô hình cụ thể
picoclaw agent -m "Hello" --model your-model
```
### Biến môi trường cho kiểm thử
```bash
# Ghi đè mô hình mặc định
export PICOCLAW_AGENTS_DEFAULTS_MODEL=your-model
# Ghi đè cài đặt nhà cung cấp
export PICOCLAW_MODEL_LIST='[{"model_name":"your-model","model":"your-provider/model-name","api_key":"..."}]'
```
---
## Tài liệu tham khảo
- **File nguồn:**
- `pkg/providers/antigravity_provider.go` - Triển khai nhà cung cấp Antigravity
- `pkg/auth/oauth.go` - Triển khai luồng OAuth
- `pkg/auth/store.go` - Lưu trữ thông tin xác thực (`~/.picoclaw/auth.json`)
- `pkg/providers/factory.go` - Factory nhà cung cấp và định tuyến giao thức
- `pkg/providers/types.go` - Định nghĩa interface nhà cung cấp
- `cmd/picoclaw/internal/auth/helpers.go` - Lệnh CLI xác thực
- **Tài liệu:**
- `docs/ANTIGRAVITY_USAGE.md` - Hướng dẫn sử dụng Antigravity
- `docs/migration/model-list-migration.md` - Hướng dẫn di chuyển
---
## Lưu ý
1. **Dự án Google Cloud:** Antigravity yêu cầu Gemini for Google Cloud được bật trên dự án Google Cloud của bạn
2. **Hạn mức:** Sử dụng hạn mức dự án Google Cloud (không tính phí riêng)
3. **Truy cập mô hình:** Các mô hình khả dụng phụ thuộc vào cấu hình dự án Google Cloud của bạn
4. **Khối suy nghĩ:** Mô hình Claude qua Antigravity yêu cầu xử lý đặc biệt khối suy nghĩ có chữ ký
5. **Làm sạch schema:** Schema công cụ phải được làm sạch để loại bỏ các từ khóa JSON Schema không được hỗ trợ
---
## Xử lý lỗi thường gặp
### 1. Giới hạn tốc độ (HTTP 429)
Antigravity trả về lỗi 429 khi hạn mức dự án/mô hình đã cạn kiệt. Phản hồi lỗi thường chứa `quotaResetDelay` trong trường `details`.
**Ví dụ lỗi 429:**
```json
{
"error": {
"code": 429,
"message": "You have exhausted your capacity on this model. Your quota will reset after 4h30m28s.",
"status": "RESOURCE_EXHAUSTED",
"details": [
{
"@type": "type.googleapis.com/google.rpc.ErrorInfo",
"metadata": {
"quotaResetDelay": "4h30m28.060903746s"
}
}
]
}
}
```
### 2. Phản hồi trống (Mô hình bị hạn chế)
Một số mô hình có thể xuất hiện trong danh sách mô hình khả dụng nhưng trả về phản hồi trống (200 OK nhưng luồng SSE trống). Điều này thường xảy ra với các mô hình xem trước hoặc bị hạn chế mà dự án hiện tại không có quyền sử dụng.
**Cách xử lý:** Coi phản hồi trống là lỗi, thông báo cho người dùng rằng mô hình có thể bị hạn chế hoặc không hợp lệ cho dự án của họ.
---
## Khắc phục sự cố
### "Token expired" (Token đã hết hạn)
- Làm mới token OAuth: `picoclaw auth login --provider antigravity`
### "Gemini for Google Cloud is not enabled" (Gemini for Google Cloud chưa được bật)
- Bật API trong Google Cloud Console của bạn
### "Project not found" (Không tìm thấy dự án)
- Đảm bảo dự án Google Cloud của bạn đã bật các API cần thiết
- Kiểm tra xem ID dự án có được lấy chính xác trong quá trình xác thực không
### Mô hình không xuất hiện trong danh sách
- Xác minh xác thực OAuth đã hoàn tất thành công
- Kiểm tra lưu trữ hồ sơ xác thực: `~/.picoclaw/auth.json`
- Chạy lại `picoclaw auth login --provider antigravity`

View file

@ -0,0 +1,72 @@
> Quay lại [README](../../README.vi.md)
# Sử dụng nhà cung cấp Antigravity trong PicoClaw
Hướng dẫn này giải thích cách thiết lập và sử dụng nhà cung cấp **Antigravity** (Google Cloud Code Assist) trong PicoClaw.
## Điều kiện tiên quyết
1. Một tài khoản Google.
2. Đã kích hoạt Google Cloud Code Assist (thường có sẵn thông qua quy trình giới thiệu "Gemini for Google Cloud").
## 1. Xác thực
Để xác thực với Antigravity, chạy lệnh sau:
```bash
picoclaw auth login --provider antigravity
```
### Xác thực thủ công (Headless/VPS)
Nếu bạn đang chạy trên máy chủ (Coolify/Docker) và không thể truy cập `localhost`, hãy làm theo các bước sau:
1. Chạy lệnh ở trên.
2. Sao chép URL được cung cấp và mở nó trong trình duyệt cục bộ của bạn.
3. Hoàn tất đăng nhập.
4. Trình duyệt của bạn sẽ chuyển hướng đến URL `localhost:51121` (trang sẽ không tải được).
5. **Sao chép URL cuối cùng đó** từ thanh địa chỉ trình duyệt.
6. **Dán nó vào terminal** nơi PicoClaw đang chờ.
PicoClaw sẽ tự động trích xuất mã ủy quyền và hoàn tất quy trình.
## 2. Quản lý mô hình
### Liệt kê các mô hình khả dụng
Để xem dự án của bạn có quyền truy cập vào những mô hình nào và kiểm tra hạn mức của chúng:
```bash
picoclaw auth models
```
### Chuyển đổi mô hình
Bạn có thể thay đổi mô hình mặc định trong `~/.picoclaw/config.json` hoặc ghi đè qua CLI:
```bash
# Ghi đè cho một lệnh duy nhất
picoclaw agent -m "Hello" --model claude-opus-4-6-thinking
```
## 3. Sử dụng thực tế (Coolify/Docker)
Nếu bạn đang triển khai qua Coolify hoặc Docker, hãy làm theo các bước sau để kiểm tra:
1. **Biến môi trường**:
* `PICOCLAW_AGENTS_DEFAULTS_MODEL=gemini-flash`
2. **Lưu trữ xác thực**:
Nếu bạn đã đăng nhập cục bộ, bạn có thể sao chép thông tin xác thực lên máy chủ:
```bash
scp ~/.picoclaw/auth.json user@your-server:~/.picoclaw/
```
*Hoặc*, chạy lệnh `auth login` một lần trên máy chủ nếu bạn có quyền truy cập terminal.
## 4. Khắc phục sự cố
* **Phản hồi trống**: Nếu một mô hình trả về phản hồi trống, nó có thể bị hạn chế cho dự án của bạn. Hãy thử `gemini-3-flash` hoặc `claude-opus-4-6-thinking`.
* **429 Giới hạn tốc độ**: Antigravity có hạn mức nghiêm ngặt. PicoClaw sẽ hiển thị "thời gian đặt lại" trong thông báo lỗi nếu bạn đạt đến giới hạn.
* **404 Không tìm thấy**: Đảm bảo bạn đang sử dụng ID mô hình từ danh sách `picoclaw auth models`. Sử dụng ID ngắn (ví dụ: `gemini-3-flash`) thay vì đường dẫn đầy đủ.
## 5. Tóm tắt các mô hình hoạt động tốt
Dựa trên kiểm tra, các mô hình sau đáng tin cậy nhất:
* `gemini-3-flash` (Nhanh, khả dụng cao)
* `gemini-2.5-flash-lite` (Nhẹ)
* `claude-opus-4-6-thinking` (Mạnh mẽ, bao gồm khả năng suy luận)

View file

@ -261,7 +261,7 @@ picoclaw gateway
picoclaw gateway
```
Để xem đầy đủ các tùy chọn (`device_id`, `join_on_invite`, `group_trigger`, `placeholder`, `reasoning_channel_id`), xem [Hướng Dẫn Cấu Hình Kênh Matrix](docs/channels/matrix/README.md).
Để xem đầy đủ các tùy chọn (`device_id`, `join_on_invite`, `group_trigger`, `placeholder`, `reasoning_channel_id`), xem [Hướng Dẫn Cấu Hình Kênh Matrix](channels/matrix/README.md).
</details>
@ -396,7 +396,7 @@ picoclaw gateway
**1. Tạo AI Bot**
* Truy cập Console Quản Trị WeCom → Quản Lý App → AI Bot
* Trong cài đặt AI Bot, cấu hình callback URL: `http://your-server:18791/webhook/wecom-aibot`
* Trong cài đặt AI Bot, cấu hình callback URL: `http://your-server:18790/webhook/wecom-aibot`
* Sao chép **Token** và nhấp "Tạo Ngẫu Nhiên" cho **EncodingAESKey**
**2. Cấu hình**

View file

@ -0,0 +1,158 @@
> Quay lại [README](../../README.vi.md)
# Mã hóa Thông tin Xác thực
PicoClaw hỗ trợ mã hóa các giá trị `api_key` trong các mục cấu hình `model_list`.
Các khóa đã mã hóa được lưu trữ dưới dạng chuỗi `enc://<base64>` và được giải mã tự động khi khởi động.
---
## Bắt đầu Nhanh
**1. Đặt cụm mật khẩu**
```bash
export PICOCLAW_KEY_PASSPHRASE="your-passphrase"
```
**2. Mã hóa khóa API**
Chạy `picoclaw onboard` — nó yêu cầu nhập cụm mật khẩu và tạo khóa SSH,
sau đó tự động mã hóa lại tất cả các mục `api_key` dạng văn bản thuần trong cấu hình
ở lần gọi `SaveConfig` tiếp theo. Giá trị `enc://` kết quả sẽ có dạng:
```
enc://AAAA...base64...
```
**3. Dán kết quả vào cấu hình**
```json
{
"model_list": [
{
"model_name": "gpt-4o",
"api_key": "enc://AAAA...base64...",
"api_base": "https://api.openai.com/v1"
}
]
}
```
---
## Các Định dạng `api_key` được Hỗ trợ
| Định dạng | Ví dụ | Hành vi |
|-----------|-------|---------|
| Văn bản thuần | `sk-abc123` | Sử dụng nguyên trạng |
| Tham chiếu tệp | `file://openai.key` | Nội dung được đọc từ cùng thư mục với tệp cấu hình |
| Đã mã hóa | `enc://<base64>` | Giải mã khi khởi động bằng `PICOCLAW_KEY_PASSPHRASE` |
| Trống | `""` | Truyền qua không thay đổi (dùng với `auth_method: oauth`) |
---
## Thiết kế Mật mã
### Dẫn xuất Khóa
Mã hóa sử dụng **HKDF-SHA256** với khóa riêng SSH làm yếu tố thứ hai.
```
sshHash = SHA256(ssh_private_key_file_bytes)
ikm = HMAC-SHA256(key=sshHash, message=passphrase)
aes_key = HKDF-SHA256(ikm, salt, info="picoclaw-credential-v1", 32 bytes)
```
### Mã hóa
```
AES-256-GCM(key=aes_key, nonce=random[12], plaintext=api_key)
```
### Định dạng Truyền tải
```
enc://<base64( salt[16] + nonce[12] + ciphertext )>
```
| Trường | Kích thước | Mô tả |
|--------|-----------|-------|
| `salt` | 16 byte | Ngẫu nhiên mỗi lần mã hóa; đưa vào HKDF |
| `nonce` | 12 byte | Ngẫu nhiên mỗi lần mã hóa; IV của AES-GCM |
| `ciphertext` | thay đổi | Bản mã AES-256-GCM + thẻ xác thực 16 byte |
Thẻ xác thực GCM được tự động nối vào bản mã. Bất kỳ sự giả mạo nào đều khiến giải mã thất bại với lỗi thay vì trả về văn bản thuần bị hỏng.
### Hiệu suất
| Thao tác | Thời gian (ARM Cortex-A) |
|----------|--------------------------|
| Dẫn xuất khóa (HKDF) | < 1 ms |
| Giải mã AES-256-GCM | < 1 ms |
| **Tổng chi phí khởi động** | **< 2 ms mỗi khóa** |
---
## Bảo mật Hai Yếu tố với Khóa SSH
Khi khóa riêng SSH được cung cấp, việc phá vỡ mã hóa yêu cầu **cả hai**:
1. **Cụm mật khẩu** (`PICOCLAW_KEY_PASSPHRASE`)
2. **Tệp khóa riêng SSH**
Điều này có nghĩa là chỉ rò rỉ tệp cấu hình không đủ để khôi phục khóa API, ngay cả khi cụm mật khẩu yếu. Khóa SSH đóng góp 256 bit entropy (Ed25519) bất kể độ mạnh của cụm mật khẩu.
### Mô hình Mối đe dọa
| Kẻ tấn công có | Có thể giải mã? |
|----------------|-----------------|
| Chỉ tệp cấu hình | Không — cần cụm mật khẩu + khóa SSH |
| Chỉ khóa SSH | Không — cần cụm mật khẩu |
| Chỉ cụm mật khẩu | Không — cần khóa SSH |
| Tệp cấu hình + khóa SSH + cụm mật khẩu | Có — xâm phạm hoàn toàn |
---
## Biến Môi trường
| Biến | Bắt buộc | Mô tả |
|------|----------|-------|
| `PICOCLAW_KEY_PASSPHRASE` | Có (cho `enc://`) | Cụm mật khẩu dùng để dẫn xuất khóa |
| `PICOCLAW_SSH_KEY_PATH` | Không | Đường dẫn đến khóa riêng SSH. Nếu không đặt, tự động phát hiện từ `~/.ssh/picoclaw_ed25519.key` |
### Tự động Phát hiện Khóa SSH
Nếu `PICOCLAW_SSH_KEY_PATH` không được đặt, PicoClaw tìm khóa chuyên dụng:
```
~/.ssh/picoclaw_ed25519.key
```
Tệp chuyên dụng này tránh xung đột với các khóa SSH hiện có của người dùng.
Chạy `picoclaw onboard` để tạo tự động.
`os.UserHomeDir()` được sử dụng để phân giải thư mục home đa nền tảng (đọc `USERPROFILE` trên Windows, `HOME` trên Unix/macOS).
> **Lưu ý:** Tệp khóa SSH là bắt buộc cho mã hóa thông tin xác thực. Nếu không tìm thấy khóa và `PICOCLAW_SSH_KEY_PATH` không được đặt, mã hóa/giải mã sẽ thất bại. Chạy `picoclaw onboard` để tạo khóa tự động.
---
## Di chuyển
Vì tài liệu bí mật duy nhất là `PICOCLAW_KEY_PASSPHRASE` và tệp khóa riêng SSH, việc di chuyển rất đơn giản:
1. Sao chép tệp cấu hình sang máy mới.
2. Đặt `PICOCLAW_KEY_PASSPHRASE` với cùng giá trị.
3. Sao chép tệp khóa riêng SSH đến cùng đường dẫn (hoặc đặt `PICOCLAW_SSH_KEY_PATH` đến vị trí mới).
Không cần mã hóa lại.
---
## Lưu ý về Bảo mật
- **Cả cụm mật khẩu và khóa SSH đều bắt buộc.** Khóa SSH đóng vai trò yếu tố thứ hai — không có nó, mã hóa/giải mã sẽ thất bại. Chạy `picoclaw onboard` để tạo khóa nếu chưa tồn tại.
- **Khóa SSH chỉ đọc khi chạy.** PicoClaw không bao giờ ghi hoặc sửa đổi tệp khóa SSH.
- **Khóa văn bản thuần vẫn được hỗ trợ.** Các cấu hình hiện có không dùng `enc://` không bị ảnh hưởng.
- **Định dạng `enc://` được quản lý phiên bản** thông qua trường `info` của HKDF (`picoclaw-credential-v1`), cho phép nâng cấp thuật toán trong tương lai mà không làm hỏng các giá trị đã mã hóa hiện có.

36
docs/vi/debug.md Normal file
View file

@ -0,0 +1,36 @@
# Gỡ lỗi PicoClaw
> Quay lại [README](../../README.vi.md)
PicoClaw thực hiện nhiều tương tác phức tạp ở hậu trường cho mỗi yêu cầu nhận được — từ định tuyến tin nhắn và đánh giá độ phức tạp, đến thực thi công cụ và thích ứng với lỗi mô hình. Khả năng xem chính xác những gì đang xảy ra là rất quan trọng, không chỉ để khắc phục các sự cố tiềm ẩn, mà còn để thực sự hiểu cách agent hoạt động.
## Khởi động PicoClaw ở chế độ gỡ lỗi
Để nhận thông tin chi tiết về những gì agent đang thực hiện (yêu cầu LLM, lệnh gọi công cụ, định tuyến tin nhắn), bạn có thể khởi động gateway PicoClaw với cờ gỡ lỗi:
```bash
picoclaw gateway --debug
# or
picoclaw gateway -d
```
Ở chế độ này, hệ thống sẽ định dạng log chi tiết và hiển thị bản xem trước của prompt hệ thống và kết quả thực thi công cụ.
## Tắt cắt ngắn log (log đầy đủ)
Theo mặc định, PicoClaw cắt ngắn các chuỗi rất dài (như *Prompt Hệ thống* hoặc kết quả JSON lớn) trong log gỡ lỗi để giữ cho console dễ đọc.
Nếu bạn cần kiểm tra đầu ra đầy đủ của một lệnh hoặc payload chính xác được gửi đến mô hình LLM, bạn có thể sử dụng cờ `--no-truncate`.
**Lưu ý:** Cờ này *chỉ* hoạt động khi kết hợp với chế độ `--debug`.
```bash
picoclaw gateway --debug --no-truncate
```
Khi cờ này được kích hoạt, chức năng cắt ngắn toàn cục sẽ bị vô hiệu hóa. Điều này cực kỳ hữu ích để:
* Xác minh cú pháp chính xác của các tin nhắn được gửi đến nhà cung cấp.
* Đọc đầu ra đầy đủ của các công cụ như `exec`, `web_fetch` hoặc `read_file`.
* Gỡ lỗi lịch sử phiên được lưu trong bộ nhớ.

View file

@ -0,0 +1,152 @@
> Quay lại [README](../../README.vi.md)
# 🖥️ PicoClaw Danh sách tương thích phần cứng
PicoClaw chạy được trên hầu hết mọi thiết bị Linux. Trang này ghi nhận các chip, sản phẩm và bo mạch phát triển đã được xác minh.
**Phần cứng của bạn chưa có trong danh sách?** Gửi PR để thêm vào! Các nhà sản xuất phần cứng được hoan nghênh đóng góp và đồng quảng bá.
---
## 1. Hỗ trợ chip đã xác minh
### x86
| Nhà sản xuất | Chip | Ghi chú |
|--------------|------|---------|
| Intel | Any x86 CPU (i386+) | Tất cả bộ xử lý desktop/server/laptop |
| AMD | Any x86 CPU | Tất cả bộ xử lý desktop/server/laptop |
### ARM
| Kiến trúc phụ | Chip tiêu biểu | Ghi chú |
|----------------|----------------|---------|
| ARMv6 | [BCM2835](https://www.raspberrypi.com/documentation/computers/processors.html#bcm2835) (Raspberry Pi 1/Zero) | Đơn nhân ARM1176JZF-S |
| ARMv7 | [Allwinner V3s](https://linux-sunxi.org/V3s) | Đơn nhân Cortex-A7, dùng trong LicheePi Zero |
| ARM64 | [Allwinner H618](https://linux-sunxi.org/H618) | Bốn nhân Cortex-A53, dùng trong Orange Pi Zero 3 |
| ARM64 | [BCM2711](https://www.raspberrypi.com/documentation/computers/processors.html#bcm2711) (Raspberry Pi 4) | Bốn nhân Cortex-A72 |
| ARM64 | [BCM2712](https://www.raspberrypi.com/documentation/computers/processors.html#bcm2712) (Raspberry Pi 5) | Bốn nhân Cortex-A76 |
| ARM64 | [AX630C](https://www.axera-tech.com/) (爱芯元智) | Hai nhân Cortex-A53 + NPU, dùng trong NanoKVM-Pro / MaixCAM2 |
### RISC-V (riscv64)
| Nhà sản xuất | Chip | Lõi | Ghi chú |
|--------------|------|-----|---------|
| [SOPHGO (算能)](https://www.sophgo.com/) | SG2002 | C906 @ 1GHz | 256MB DDR3 tích hợp, dùng trong LicheeRV-Nano / NanoKVM / MaixCAM |
| [Allwinner (全志)](https://www.allwinnertech.com/) | V861 | Dual C907 | 128MB DDR3L tích hợp, 1 TOPS NPU, camera AI 4K SiP |
| [Allwinner (全志)](https://www.allwinnertech.com/) | V881 | C907 | Dòng camera AI RISC-V |
| [Arterytek (匠芯创)](https://www.arterytek.com/) | D213 | RISC-V | Dùng trong HaaS506-LD1 RTU công nghiệp |
| [SpacemiT (进迭)](https://www.spacemit.com/) | K1 | 8x X60 @ 1.8GHz | Dùng trong Milk-V Jupiter, BananaPi BPI-F3 |
| [SpacemiT (进迭)](https://www.spacemit.com/) | K3 | 8x X100 @ 2.5GHz | Tuân thủ RVA23, RVV 1024-bit, suy luận AI FP8 |
| [Zhihe (知合)](https://www.zhihe-tech.com/) | A210 | High-perf RISC-V | 8 lõi, 16MB cache L3, cấp desktop |
| [Canaan (嘉楠)](https://www.canaan-creative.com/) | K230 | Dual C908 @ 1.6GHz | 6 TOPS KPU, dùng trong CanMV-K230 |
### MIPS
| Nhà sản xuất | Chip | Ghi chú |
|--------------|------|---------|
| MediaTek | [MT7620](https://www.mediatek.com/products/home-networking/mt7620) | MIPS24KEc @ 580MHz, dùng trong nhiều router OpenWrt (vd. Xiaomi Router 3G) |
### LoongArch (loong64)
| Nhà sản xuất | Chip | Ghi chú |
|--------------|------|---------|
| [Loongson (龙芯)](https://www.loongson.cn/) | 3A5000 | Bốn nhân LA464 @ 2.5GHz, desktop/máy trạm |
| [Loongson (龙芯)](https://www.loongson.cn/) | 3A6000 | Bốn nhân 4C/8T @ 2.5GHz, IPC tương đương Intel thế hệ 10 |
| [Loongson (龙芯)](https://www.loongson.cn/) | 2K1000LA | Hai nhân @ 1GHz, ứng dụng công nghiệp/IoT |
---
## 2. Sản phẩm đã xác minh (theo ngày phát hành)
Sản phẩm tiêu dùng, router và thiết bị công nghiệp đã được kiểm thử với PicoClaw.
| Năm | Sản phẩm | Kiến trúc | SoC | RAM | Danh mục |
|-----|----------|-----------|-----|-----|----------|
| 2009 | Nokia N900 | ARM (A8) | OMAP3430 | 256MB | Điện thoại thông minh |
| 2012 | Samsung Galaxy Note 10.1 (N8000) | ARM (A9) | Exynos 4412 | 2GB | Máy tính bảng |
| 2016 | Xiaomi Router 3G (小米路由器3G) | MIPS | MT7620 | 256MB | Router (OpenWrt) |
| 2018 | Phicomm N1 (斐讯N1) | ARM64 (A53) | S905D | 2GB | TV Box / Máy chủ gia đình |
| 2019 | Xiaomi AI Speaker (小爱音箱) | ARM64 (A53) | — | 256MB | Loa thông minh |
| 2024 | [NanoKVM](https://wiki.sipeed.com/hardware/en/kvm/NanoKVM/introduction.html) | RISC-V | SG2002 | 256MB | IP-KVM |
| 2025 | HaaS506-LD1 | RISC-V | D213 | 128MB | RTU công nghiệp |
| 2025 | [NanoKVM-Pro](https://wiki.sipeed.com/hardware/en/kvm/NanoKVM_Pro/introduction.html) | ARM64 (A53) | AX630C | 1GB | IP-KVM Pro |
| 2026 | [MaixCAM2](https://wiki.sipeed.com/hardware/en/maixcam/index.html) | ARM64 (A53) | AX630C | 1/4GB | Camera AI 4K |
---
## 3. Bo mạch phát triển đã xác minh (theo ngày phát hành)
| Năm | Bo mạch | Kiến trúc | SoC | RAM | Liên kết mua |
|-----|---------|-----------|-----|-----|--------------|
| 2012 | [Raspberry Pi 1 Model B](https://www.raspberrypi.com/products/) | ARMv6 | BCM2835 | 512MB | — |
| 2015 | [Raspberry Pi 2 Model B](https://www.raspberrypi.com/products/raspberry-pi-2-model-b/) | ARMv7 (A7) | BCM2836 | 1GB | — |
| 2015 | [Raspberry Pi Zero](https://www.raspberrypi.com/products/raspberry-pi-zero/) | ARMv6 | BCM2835 | 512MB | — |
| 2016 | [Raspberry Pi 3 Model B](https://www.raspberrypi.com/products/raspberry-pi-3-model-b/) | ARM64 (A53) | BCM2837 | 1GB | — |
| 2017 | [LicheePi Zero](https://wiki.sipeed.com/hardware/en/lichee/Zero/Zero.html) | ARMv7 (A7) | Allwinner V3s | 64MB | [Sipeed](https://sipeed.com/) |
| 2019 | [Raspberry Pi 4 Model B](https://www.raspberrypi.com/products/raspberry-pi-4-model-b/) | ARM64 (A72) | BCM2711 | 1~8GB | [RPi](https://www.raspberrypi.com/) |
| 2023 | [Raspberry Pi 5](https://www.raspberrypi.com/products/raspberry-pi-5/) | ARM64 (A76) | BCM2712 | 2~8GB | [RPi](https://www.raspberrypi.com/) |
| 2024 | [LicheeRV-Nano](https://wiki.sipeed.com/hardware/en/lichee/RV_Nano/1_intro.html) | RISC-V | SG2002 | 256MB | [AliExpress](https://www.aliexpress.com/item/1005006519668532.html) |
| 2024 | [MaixCAM-Pro](https://wiki.sipeed.com/hardware/en/maixcam/index.html) | RISC-V | SG2002 | 256MB | [Sipeed](https://sipeed.com/) |
| 2024 | [Milk-V Duo 64M](https://milkv.io/docs/duo/getting-started/duo) | RISC-V | CV1800B | 64MB | [Milk-V](https://milkv.io/) |
| 2024 | [CanMV-K230](https://developer.canaan-creative.com/k230_canmv/en/main/) | RISC-V | K230 | 512MB | [Canaan](https://www.canaan-creative.com/) |
---
## 4. Cũng hoạt động trên
### Điện thoại Android (qua Termux)
Bất kỳ điện thoại Android ARM64 nào (2015+) với 1GB+ RAM. Cài đặt [Termux](https://github.com/termux/termux-app), sử dụng `proot` để chạy PicoClaw.
> Xem [README: Chạy trên điện thoại Android cũ](../README.md#-run-on-old-android-phones) để biết hướng dẫn cài đặt.
### Desktop / Máy chủ / Đám mây
| Nền tảng | Ghi chú |
|----------|---------|
| x86_64 Linux | Binary gốc, không phụ thuộc |
| x86_64 Windows | Binary gốc |
| macOS (Intel / Apple Silicon) | Binary gốc |
| Docker (any platform) | `docker compose` một dòng lệnh, xem [Hướng dẫn Docker](docker.md) |
| OpenWrt routers | Bản dựng MIPS/ARM, yêu cầu >32MB RAM trống |
| FreeBSD / NetBSD | Có bản dựng x86_64 và arm64 |
---
## 5. Yêu cầu tối thiểu
| Tài nguyên | Tối thiểu | Khuyến nghị |
|------------|-----------|-------------|
| RAM | 10MB trống | 32MB+ trống |
| Lưu trữ | 20MB (binary) | 50MB+ (với workspace) |
| CPU | Bất kỳ (đơn nhân 0.6GHz+) | — |
| OS | Linux (kernel 3.x+) | Linux 5.x+ |
| Mạng | Bắt buộc (cho các lệnh gọi API LLM) | Ethernet hoặc WiFi |
---
## 6. Cách kiểm thử và đóng góp
```bash
# 1. Tải xuống cho kiến trúc của bạn
wget https://github.com/sipeed/picoclaw/releases/latest/download/picoclaw_Linux_arm64.tar.gz
tar xzf picoclaw_Linux_arm64.tar.gz
# 2. Khởi tạo
./picoclaw onboard
# 3. Kiểm thử
./picoclaw agent -m "Hello, what board am I running on?"
```
Các bản dựng có sẵn: `linux-amd64`, `linux-arm64`, `linux-arm`, `linux-riscv64`, `linux-loong64`, `linux-mipsle`
### Thêm phần cứng của bạn
1. Fork kho lưu trữ này
2. Thêm chip / sản phẩm / bo mạch của bạn vào bảng tương ứng
3. Bao gồm: tên, kiến trúc, SoC, RAM, năm và liên kết nếu có
4. Gửi PR
Nhà sản xuất phần cứng: muốn thêm hỗ trợ chính thức hoặc đồng quảng bá? Mở issue hoặc liên hệ qua [Discord](https://discord.gg/V4sAZ9XWpN).

View file

@ -16,7 +16,7 @@
**Cách sửa:** Trong `~/.picoclaw/config.json` (hoặc đường dẫn cấu hình của bạn):
1. **agents.defaults.model** phải khớp với một `model_name` trong `model_list` (ví dụ: `"openrouter-free"`).
1. **agents.defaults.model_name** phải khớp với một `model_name` trong `model_list` (ví dụ: `"openrouter-free"`).
2. **model** của mục đó phải là ID mô hình OpenRouter hợp lệ, ví dụ:
- `"openrouter/free"` tầng miễn phí tự động
- `"google/gemini-2.0-flash-exp:free"`
@ -28,7 +28,7 @@ Ví dụ:
{
"agents": {
"defaults": {
"model": "openrouter-free"
"model_name": "openrouter-free"
}
},
"model_list": [

809
docs/zh/ANTIGRAVITY_AUTH.md Normal file
View file

@ -0,0 +1,809 @@
> 返回 [README](../../README.zh.md)
# Antigravity 认证与集成指南
## 概述
**Antigravity**Google Cloud Code Assist是由 Google 支持的 AI 模型提供商,通过 Google 的云基础设施提供对 Claude Opus 4.6 和 Gemini 等模型的访问。本文档提供了关于认证工作原理、如何获取模型以及如何在 PicoClaw 中实现新提供商的完整指南。
---
## 目录
1. [认证流程](#认证流程)
2. [OAuth 实现细节](#oauth-实现细节)
3. [令牌管理](#令牌管理)
4. [模型列表获取](#模型列表获取)
5. [用量追踪](#用量追踪)
6. [提供商插件结构](#提供商插件结构)
7. [集成要求](#集成要求)
8. [API 端点](#api-端点)
9. [配置](#配置)
10. [在 PicoClaw 中创建新提供商](#在-picoclaw-中创建新提供商)
---
## 认证流程
### 1. 带 PKCE 的 OAuth 2.0
Antigravity 使用 **OAuth 2.0 with PKCEProof Key for Code Exchange** 进行安全认证:
```
┌─────────────┐ ┌─────────────────┐
│ Client │ ───(1) Generate PKCE Pair────────> │ │
│ │ ───(2) Open Auth URL─────────────> │ Google OAuth │
│ │ │ Server │
│ │ <──(3) Redirect with Code───────── │ │
│ │ └─────────────────┘
│ │ ───(4) Exchange Code for Tokens──> │ Token URL │
│ │ │ │
│ │ <──(5) Access + Refresh Tokens──── │ │
└─────────────┘ └─────────────────┘
```
### 2. 详细步骤
#### 步骤 1生成 PKCE 参数
```typescript
function generatePkce(): { verifier: string; challenge: string } {
const verifier = randomBytes(32).toString("hex");
const challenge = createHash("sha256").update(verifier).digest("base64url");
return { verifier, challenge };
}
```
#### 步骤 2构建授权 URL
```typescript
const AUTH_URL = "https://accounts.google.com/o/oauth2/v2/auth";
const REDIRECT_URI = "http://localhost:51121/oauth-callback";
function buildAuthUrl(params: { challenge: string; state: string }): string {
const url = new URL(AUTH_URL);
url.searchParams.set("client_id", CLIENT_ID);
url.searchParams.set("response_type", "code");
url.searchParams.set("redirect_uri", REDIRECT_URI);
url.searchParams.set("scope", SCOPES.join(" "));
url.searchParams.set("code_challenge", params.challenge);
url.searchParams.set("code_challenge_method", "S256");
url.searchParams.set("state", params.state);
url.searchParams.set("access_type", "offline");
url.searchParams.set("prompt", "consent");
return url.toString();
}
```
**所需权限范围:**
```typescript
const SCOPES = [
"https://www.googleapis.com/auth/cloud-platform",
"https://www.googleapis.com/auth/userinfo.email",
"https://www.googleapis.com/auth/userinfo.profile",
"https://www.googleapis.com/auth/cclog",
"https://www.googleapis.com/auth/experimentsandconfigs",
];
```
#### 步骤 3处理 OAuth 回调
**自动模式(本地开发):**
- 在端口 51121 上启动本地 HTTP 服务器
- 等待来自 Google 的重定向
- 从查询参数中提取授权码
**手动模式(远程/无头环境):**
- 向用户显示授权 URL
- 用户在浏览器中完成认证
- 用户将完整的重定向 URL 粘贴回终端
- 从粘贴的 URL 中解析授权码
#### 步骤 4用授权码交换令牌
```typescript
const TOKEN_URL = "https://oauth2.googleapis.com/token";
async function exchangeCode(params: {
code: string;
verifier: string;
}): Promise<{ access: string; refresh: string; expires: number }> {
const response = await fetch(TOKEN_URL, {
method: "POST",
headers: { "Content-Type": "application/x-www-form-urlencoded" },
body: new URLSearchParams({
client_id: CLIENT_ID,
client_secret: CLIENT_SECRET,
code: params.code,
grant_type: "authorization_code",
redirect_uri: REDIRECT_URI,
code_verifier: params.verifier,
}),
});
const data = await response.json();
return {
access: data.access_token,
refresh: data.refresh_token,
expires: Date.now() + data.expires_in * 1000 - 5 * 60 * 1000, // 5 min buffer
};
}
```
#### 步骤 5获取额外的用户数据
**用户邮箱:**
```typescript
async function fetchUserEmail(accessToken: string): Promise<string | undefined> {
const response = await fetch(
"https://www.googleapis.com/oauth2/v1/userinfo?alt=json",
{ headers: { Authorization: `Bearer ${accessToken}` } }
);
const data = await response.json();
return data.email;
}
```
**项目 IDAPI 调用必需):**
```typescript
async function fetchProjectId(accessToken: string): Promise<string> {
const headers = {
Authorization: `Bearer ${accessToken}`,
"Content-Type": "application/json",
"User-Agent": "google-api-nodejs-client/9.15.1",
"X-Goog-Api-Client": "google-cloud-sdk vscode_cloudshelleditor/0.1",
"Client-Metadata": JSON.stringify({
ideType: "IDE_UNSPECIFIED",
platform: "PLATFORM_UNSPECIFIED",
pluginType: "GEMINI",
}),
};
const response = await fetch(
"https://cloudcode-pa.googleapis.com/v1internal:loadCodeAssist",
{
method: "POST",
headers,
body: JSON.stringify({
metadata: {
ideType: "IDE_UNSPECIFIED",
platform: "PLATFORM_UNSPECIFIED",
pluginType: "GEMINI",
},
}),
}
);
const data = await response.json();
return data.cloudaicompanionProject || "rising-fact-p41fc"; // 默认回退值
}
```
---
## OAuth 实现细节
### 客户端凭据
**重要:** 这些凭据在源代码中以 base64 编码存储,用于与 pi-ai 同步:
```typescript
const decode = (s: string) => Buffer.from(s, "base64").toString();
const CLIENT_ID = decode(
"MTA3MTAwNjA2MDU5MS10bWhzc2luMmgyMWxjcmUyMzV2dG9sb2poNGc0MDNlcC5hcHBzLmdvb2dsZXVzZXJjb250ZW50LmNvbQ=="
);
const CLIENT_SECRET = decode("R09DU1BYLUs1OEZXUjQ4NkxkTEoxbUxCOHNYQzR6NnFEQWY=");
```
### OAuth 流程模式
1. **自动流程**(有浏览器的本地机器):
- 自动打开浏览器
- 本地回调服务器捕获重定向
- 初始认证后无需用户交互
2. **手动流程**(远程/无头/WSL2 环境):
- 显示 URL 供手动复制粘贴
- 用户在外部浏览器中完成认证
- 用户将完整的重定向 URL 粘贴回来
```typescript
function shouldUseManualOAuthFlow(isRemote: boolean): boolean {
return isRemote || isWSL2Sync();
}
```
---
## 令牌管理
### 认证配置文件结构
```typescript
type OAuthCredential = {
type: "oauth";
provider: "google-antigravity";
access: string; // 访问令牌
refresh: string; // 刷新令牌
expires: number; // 过期时间戳(毫秒,自 epoch 起)
email?: string; // 用户邮箱
projectId?: string; // Google Cloud 项目 ID
};
```
### 令牌刷新
凭据包含一个刷新令牌,可在当前访问令牌过期时用于获取新的访问令牌。过期时间设置了 5 分钟的缓冲区以防止竞态条件。
---
## 模型列表获取
### 获取可用模型
```typescript
const BASE_URL = "https://cloudcode-pa.googleapis.com";
async function fetchAvailableModels(
accessToken: string,
projectId: string
): Promise<Model[]> {
const headers = {
Authorization: `Bearer ${accessToken}`,
"Content-Type": "application/json",
"User-Agent": "antigravity",
"X-Goog-Api-Client": "google-cloud-sdk vscode_cloudshelleditor/0.1",
};
const response = await fetch(
`${BASE_URL}/v1internal:fetchAvailableModels`,
{
method: "POST",
headers,
body: JSON.stringify({ project: projectId }),
}
);
const data = await response.json();
// 返回带有配额信息的模型
return Object.entries(data.models).map(([modelId, modelInfo]) => ({
id: modelId,
displayName: modelInfo.displayName,
quotaInfo: {
remainingFraction: modelInfo.quotaInfo?.remainingFraction,
resetTime: modelInfo.quotaInfo?.resetTime,
isExhausted: modelInfo.quotaInfo?.isExhausted,
},
}));
}
```
### 响应格式
```typescript
type FetchAvailableModelsResponse = {
models?: Record<string, {
displayName?: string;
quotaInfo?: {
remainingFraction?: number | string;
resetTime?: string; // ISO 8601 时间戳
isExhausted?: boolean;
};
}>;
};
```
---
## 用量追踪
### 获取用量数据
```typescript
export async function fetchAntigravityUsage(
token: string,
timeoutMs: number
): Promise<ProviderUsageSnapshot> {
// 1. 获取额度和计划信息
const loadCodeAssistRes = await fetch(
`${BASE_URL}/v1internal:loadCodeAssist`,
{
method: "POST",
headers: {
Authorization: `Bearer ${token}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
metadata: {
ideType: "ANTIGRAVITY",
platform: "PLATFORM_UNSPECIFIED",
pluginType: "GEMINI",
},
}),
}
);
// 提取额度信息
const { availablePromptCredits, planInfo, currentTier } = data;
// 2. 获取模型配额
const modelsRes = await fetch(
`${BASE_URL}/v1internal:fetchAvailableModels`,
{
method: "POST",
headers: { Authorization: `Bearer ${token}` },
body: JSON.stringify({ project: projectId }),
}
);
// 构建用量窗口
return {
provider: "google-antigravity",
displayName: "Google Antigravity",
windows: [
{ label: "Credits", usedPercent: calculateUsedPercent(available, monthly) },
// 各模型配额...
],
plan: currentTier?.name || planType,
};
}
```
### 用量响应结构
```typescript
type ProviderUsageSnapshot = {
provider: "google-antigravity";
displayName: string;
windows: UsageWindow[];
plan?: string;
error?: string;
};
type UsageWindow = {
label: string; // "Credits" 或模型 ID
usedPercent: number; // 0-100
resetAt?: number; // 配额重置的时间戳
};
```
---
## 提供商插件结构
### 插件定义
```typescript
const antigravityPlugin = {
id: "google-antigravity-auth",
name: "Google Antigravity Auth",
description: "OAuth flow for Google Antigravity (Cloud Code Assist)",
configSchema: emptyPluginConfigSchema(),
register(api: PicoClawPluginApi) {
api.registerProvider({
id: "google-antigravity",
label: "Google Antigravity",
docsPath: "/providers/models",
aliases: ["antigravity"],
auth: [
{
id: "oauth",
label: "Google OAuth",
hint: "PKCE + localhost callback",
kind: "oauth",
run: async (ctx: ProviderAuthContext) => {
// OAuth 实现在此处
},
},
],
});
},
};
```
### ProviderAuthContext
```typescript
type ProviderAuthContext = {
config: PicoClawConfig;
agentDir?: string;
workspaceDir?: string;
prompter: WizardPrompter; // UI 提示/通知
runtime: RuntimeEnv; // 日志等
isRemote: boolean; // 是否在远程运行
openUrl: (url: string) => Promise<void>; // 浏览器打开器
oauth: {
createVpsAwareHandlers: Function;
};
};
```
### ProviderAuthResult
```typescript
type ProviderAuthResult = {
profiles: Array<{
profileId: string;
credential: AuthProfileCredential;
}>;
configPatch?: Partial<PicoClawConfig>;
defaultModel?: string;
notes?: string[];
};
```
---
## 集成要求
### 1. 所需环境/依赖
- Go ≥ 1.25
- PicoClaw 代码库(`pkg/providers/``pkg/auth/`
- `crypto``net/http` 标准库包
### 2. API 调用所需的请求头
```typescript
const REQUIRED_HEADERS = {
"Authorization": `Bearer ${accessToken}`,
"Content-Type": "application/json",
"User-Agent": "antigravity", // 或 "google-api-nodejs-client/9.15.1"
"X-Goog-Api-Client": "google-cloud-sdk vscode_cloudshelleditor/0.1",
};
// 对于 loadCodeAssist 调用,还需包含:
const CLIENT_METADATA = {
ideType: "ANTIGRAVITY", // 或 "IDE_UNSPECIFIED"
platform: "PLATFORM_UNSPECIFIED",
pluginType: "GEMINI",
};
```
### 3. 模型 Schema 清理
Antigravity 使用兼容 Gemini 的模型,因此工具 schema 必须进行清理:
```typescript
const GOOGLE_SCHEMA_UNSUPPORTED_KEYWORDS = new Set([
"patternProperties",
"additionalProperties",
"$schema",
"$id",
"$ref",
"$defs",
"definitions",
"examples",
"minLength",
"maxLength",
"minimum",
"maximum",
"multipleOf",
"pattern",
"format",
"minItems",
"maxItems",
"uniqueItems",
"minProperties",
"maxProperties",
]);
// 发送前清理 schema
function cleanToolSchemaForGemini(schema: Record<string, unknown>): unknown {
// 移除不支持的关键字
// 确保顶层有 type: "object"
// 展平 anyOf/oneOf 联合类型
}
```
### 4. 思维块处理Claude 模型)
对于 Antigravity 的 Claude 模型,思维块需要特殊处理:
```typescript
const ANTIGRAVITY_SIGNATURE_RE = /^[A-Za-z0-9+/]+={0,2}$/;
export function sanitizeAntigravityThinkingBlocks(
messages: AgentMessage[]
): AgentMessage[] {
// 验证思维签名
// 规范化签名字段
// 丢弃未签名的思维块
}
```
---
## API 端点
### 认证端点
| 端点 | 方法 | 用途 |
|------|------|------|
| `https://accounts.google.com/o/oauth2/v2/auth` | GET | OAuth 授权 |
| `https://oauth2.googleapis.com/token` | POST | 令牌交换 |
| `https://www.googleapis.com/oauth2/v1/userinfo` | GET | 用户信息(邮箱) |
### Cloud Code Assist 端点
| 端点 | 方法 | 用途 |
|------|------|------|
| `https://cloudcode-pa.googleapis.com/v1internal:loadCodeAssist` | POST | 加载项目信息、额度、计划 |
| `https://cloudcode-pa.googleapis.com/v1internal:fetchAvailableModels` | POST | 列出可用模型及配额 |
| `https://cloudcode-pa.googleapis.com/v1internal:streamGenerateContent?alt=sse` | POST | 聊天流式端点 |
**API 请求格式(聊天):**
`v1internal:streamGenerateContent` 端点期望一个包装标准 Gemini 请求的信封格式:
```json
{
"project": "your-project-id",
"model": "model-id",
"request": {
"contents": [...],
"systemInstruction": {...},
"generationConfig": {...},
"tools": [...]
},
"requestType": "agent",
"userAgent": "antigravity",
"requestId": "agent-timestamp-random"
}
```
**API 响应格式SSE**
每条 SSE 消息(`data: {...}`)被包装在 `response` 字段中:
```json
{
"response": {
"candidates": [...],
"usageMetadata": {...},
"modelVersion": "...",
"responseId": "..."
},
"traceId": "...",
"metadata": {}
}
```
---
## 配置
### config.json 配置
```json
{
"model_list": [
{
"model_name": "gemini-flash",
"model": "antigravity/gemini-3-flash",
"auth_method": "oauth"
}
],
"agents": {
"defaults": {
"model": "gemini-flash"
}
}
}
```
### 认证配置文件存储
认证配置文件存储在 `~/.picoclaw/auth.json` 中:
```json
{
"credentials": {
"google-antigravity": {
"access_token": "ya29...",
"refresh_token": "1//...",
"expires_at": "2026-01-01T00:00:00Z",
"provider": "google-antigravity",
"auth_method": "oauth",
"email": "user@example.com",
"project_id": "my-project-id"
}
}
}
```
---
## 在 PicoClaw 中创建新提供商
PicoClaw 提供商以 Go 包的形式实现,位于 `pkg/providers/` 下。要添加新提供商:
### 分步实现
#### 1. 创建提供商文件
`pkg/providers/` 中创建新的 Go 文件:
```
pkg/providers/
└── your_provider.go
```
#### 2. 实现 Provider 接口
你的提供商必须实现 `pkg/providers/types.go` 中定义的 `Provider` 接口:
```go
package providers
type YourProvider struct {
apiKey string
apiBase string
}
func NewYourProvider(apiKey, apiBase, proxy string) *YourProvider {
if apiBase == "" {
apiBase = "https://api.your-provider.com/v1"
}
return &YourProvider{apiKey: apiKey, apiBase: apiBase}
}
func (p *YourProvider) Chat(ctx context.Context, messages []Message, tools []Tool, cb StreamCallback) error {
// 实现带流式传输的聊天补全
}
```
#### 3. 在工厂中注册
将你的提供商添加到 `pkg/providers/factory.go` 中的协议分支:
```go
case "your-provider":
return NewYourProvider(sel.apiKey, sel.apiBase, sel.proxy), nil
```
#### 4. 添加默认配置(可选)
`pkg/config/defaults.go` 中添加默认条目:
```go
{
ModelName: "your-model",
Model: "your-provider/model-name",
APIKey: "",
},
```
#### 5. 添加认证支持(可选)
如果你的提供商需要 OAuth 或特殊认证,在 `cmd/picoclaw/internal/auth/helpers.go` 中添加分支:
```go
case "your-provider":
authLoginYourProvider()
```
#### 6. 通过 `config.json` 配置
```json
{
"model_list": [
{
"model_name": "your-model",
"model": "your-provider/model-name",
"api_key": "your-api-key",
"api_base": "https://api.your-provider.com/v1"
}
]
}
```
---
## 测试你的实现
### CLI 命令
```bash
# 使用提供商进行认证
picoclaw auth login --provider your-provider
# 列出模型(用于 Antigravity
picoclaw auth models
# 启动网关
picoclaw gateway
# 使用指定模型运行代理
picoclaw agent -m "Hello" --model your-model
```
### 测试用环境变量
```bash
# 覆盖默认模型
export PICOCLAW_AGENTS_DEFAULTS_MODEL=your-model
# 覆盖提供商设置
export PICOCLAW_MODEL_LIST='[{"model_name":"your-model","model":"your-provider/model-name","api_key":"..."}]'
```
---
## 参考资料
- **源文件:**
- `pkg/providers/antigravity_provider.go` - Antigravity 提供商实现
- `pkg/auth/oauth.go` - OAuth 流程实现
- `pkg/auth/store.go` - 认证凭据存储(`~/.picoclaw/auth.json`
- `pkg/providers/factory.go` - 提供商工厂和协议路由
- `pkg/providers/types.go` - 提供商接口定义
- `cmd/picoclaw/internal/auth/helpers.go` - 认证 CLI 命令
- **文档:**
- `docs/ANTIGRAVITY_USAGE.md` - Antigravity 使用指南
- `docs/migration/model-list-migration.md` - 迁移指南
---
## 注意事项
1. **Google Cloud 项目:** Antigravity 要求在你的 Google Cloud 项目上启用 Gemini for Google Cloud
2. **配额:** 使用 Google Cloud 项目配额(非独立计费)
3. **模型访问:** 可用模型取决于你的 Google Cloud 项目配置
4. **思维块:** 通过 Antigravity 使用的 Claude 模型需要对带签名的思维块进行特殊处理
5. **Schema 清理:** 工具 schema 必须清理以移除不支持的 JSON Schema 关键字
---
---
## 常见错误处理
### 1. 速率限制HTTP 429
当项目/模型配额耗尽时Antigravity 会返回 429 错误。错误响应通常在 `details` 字段中包含 `quotaResetDelay`
**429 错误示例:**
```json
{
"error": {
"code": 429,
"message": "You have exhausted your capacity on this model. Your quota will reset after 4h30m28s.",
"status": "RESOURCE_EXHAUSTED",
"details": [
{
"@type": "type.googleapis.com/google.rpc.ErrorInfo",
"metadata": {
"quotaResetDelay": "4h30m28.060903746s"
}
}
]
}
}
```
### 2. 空响应(受限模型)
某些模型可能出现在可用模型列表中但返回空响应200 OK 但 SSE 流为空)。这通常发生在当前项目没有权限使用的预览版或受限模型上。
**处理方式:** 将空响应视为错误,通知用户该模型可能对其项目受限或无效。
---
## 故障排除
### "Token expired"(令牌已过期)
- 刷新 OAuth 令牌:`picoclaw auth login --provider antigravity`
### "Gemini for Google Cloud is not enabled"Gemini for Google Cloud 未启用)
- 在 Google Cloud Console 中启用该 API
### "Project not found"(项目未找到)
- 确保你的 Google Cloud 项目已启用必要的 API
- 检查认证过程中项目 ID 是否正确获取
### 模型未出现在列表中
- 验证 OAuth 认证是否成功完成
- 检查认证配置文件存储:`~/.picoclaw/auth.json`
- 重新运行 `picoclaw auth login --provider antigravity`

View file

@ -0,0 +1,72 @@
> 返回 [README](../../README.zh.md)
# 在 PicoClaw 中使用 Antigravity 提供商
本指南介绍如何在 PicoClaw 中设置和使用 **Antigravity**Google Cloud Code Assist提供商。
## 前提条件
1. 一个 Google 账户。
2. 已启用 Google Cloud Code Assist通常通过"Gemini for Google Cloud"引导流程获取)。
## 1. 身份验证
要使用 Antigravity 进行身份验证,请运行以下命令:
```bash
picoclaw auth login --provider antigravity
```
### 手动验证(无界面/VPS 环境)
如果你在服务器Coolify/Docker上运行且无法访问 `localhost`,请按照以下步骤操作:
1. 运行上述命令。
2. 复制提供的 URL 并在本地浏览器中打开。
3. 完成登录。
4. 浏览器将重定向到 `localhost:51121` URL页面将无法加载
5. **从浏览器地址栏复制该最终 URL**
6. **将其粘贴回 PicoClaw 正在等待的终端中**
PicoClaw 将自动提取授权码并完成流程。
## 2. 管理模型
### 列出可用模型
查看你的项目可以访问哪些模型并检查其配额:
```bash
picoclaw auth models
```
### 切换模型
你可以在 `~/.picoclaw/config.json` 中更改默认模型,或通过 CLI 覆盖:
```bash
# 为单个命令覆盖
picoclaw agent -m "Hello" --model claude-opus-4-6-thinking
```
## 3. 实际使用Coolify/Docker
如果你通过 Coolify 或 Docker 部署,请按照以下步骤进行测试:
1. **环境变量**
* `PICOCLAW_AGENTS_DEFAULTS_MODEL=gemini-flash`
2. **身份验证持久化**
如果你已在本地登录,可以将凭据复制到服务器:
```bash
scp ~/.picoclaw/auth.json user@your-server:~/.picoclaw/
```
*或者*,如果你有终端访问权限,可以在服务器上运行一次 `auth login` 命令。
## 4. 故障排除
* **空响应**:如果模型返回空回复,可能是该模型在你的项目中受到限制。请尝试 `gemini-3-flash``claude-opus-4-6-thinking`
* **429 速率限制**Antigravity 有严格的配额限制。如果触发限制PicoClaw 将在错误消息中显示"重置时间"。
* **404 未找到**:确保你使用的是 `picoclaw auth models` 列表中的模型 ID。请使用短 ID例如 `gemini-3-flash`),而非完整路径。
## 5. 可用模型总结
根据测试,以下模型最为可靠:
* `gemini-3-flash`(快速,高可用性)
* `gemini-2.5-flash-lite`(轻量级)
* `claude-opus-4-6-thinking`(强大,包含推理能力)

View file

@ -281,8 +281,8 @@ picoclaw gateway
"enabled": true,
"server": "irc.libera.chat:6697",
"nick": "picoclaw-bot",
"use_tls": true,
"channels_to_join": ["#your-channel"],
"tls": true,
"channels": ["#your-channel"],
"allow_from": []
}
}
@ -496,7 +496,7 @@ picoclaw gateway
**1. 创建 AI Bot**
* 企业微信管理后台 → 应用管理 → AI Bot
* 在 AI Bot 设置中配置回调 URL`http://your-server:18791/webhook/wecom-aibot`
* 在 AI Bot 设置中配置回调 URL`http://your-server:18790/webhook/wecom-aibot`
* 复制 **Token** 并点击"随机生成" **EncodingAESKey**
**2. 配置**

View file

@ -0,0 +1,157 @@
> 返回 [README](../../README.zh.md)
# 凭据加密
PicoClaw 支持对 `model_list` 配置条目中的 `api_key` 值进行加密。
加密后的密钥以 `enc://<base64>` 字符串形式存储,并在启动时自动解密。
---
## 快速开始
**1. 设置密码短语**
```bash
export PICOCLAW_KEY_PASSPHRASE="your-passphrase"
```
**2. 加密 API 密钥**
运行 `picoclaw onboard` — 它会提示你输入密码短语并生成 SSH 密钥,
然后在下一次 `SaveConfig` 调用时自动重新加密配置中所有明文 `api_key` 条目。生成的 `enc://` 值如下所示:
```
enc://AAAA...base64...
```
**3. 将输出粘贴到你的配置中**
```json
{
"model_list": [
{
"model_name": "gpt-4o",
"api_key": "enc://AAAA...base64...",
"api_base": "https://api.openai.com/v1"
}
]
}
```
---
## 支持的 `api_key` 格式
| 格式 | 示例 | 行为 |
|------|------|------|
| 明文 | `sk-abc123` | 直接使用 |
| 文件引用 | `file://openai.key` | 从配置文件所在目录读取内容 |
| 加密 | `enc://<base64>` | 启动时使用 `PICOCLAW_KEY_PASSPHRASE` 解密 |
| 空值 | `""` | 原样传递(用于 `auth_method: oauth` |
---
## 加密设计
### 密钥派生
加密使用 **HKDF-SHA256**,并以 SSH 私钥作为第二因子。
```
sshHash = SHA256(ssh_private_key_file_bytes)
ikm = HMAC-SHA256(key=sshHash, message=passphrase)
aes_key = HKDF-SHA256(ikm, salt, info="picoclaw-credential-v1", 32 bytes)
```
### 加密
```
AES-256-GCM(key=aes_key, nonce=random[12], plaintext=api_key)
```
### 传输格式
```
enc://<base64( salt[16] + nonce[12] + ciphertext )>
```
| 字段 | 大小 | 描述 |
|------|------|------|
| `salt` | 16 字节 | 每次加密随机生成;输入 HKDF |
| `nonce` | 12 字节 | 每次加密随机生成AES-GCM IV |
| `ciphertext` | 可变 | AES-256-GCM 密文 + 16 字节认证标签 |
GCM 认证标签会自动附加到密文之后。任何篡改都会导致解密失败并报错,而不是返回损坏的明文。
### 性能
| 操作 | 耗时 (ARM Cortex-A) |
|------|---------------------|
| 密钥派生 (HKDF) | < 1 ms |
| AES-256-GCM 解密 | < 1 ms |
| **启动总开销** | **每个密钥 < 2 ms** |
---
## 使用 SSH 密钥的双因子安全
当提供 SSH 私钥时,破解加密需要**同时具备**
1. **密码短语** (`PICOCLAW_KEY_PASSPHRASE`)
2. **SSH 私钥文件**
这意味着仅泄露配置文件不足以恢复 API 密钥即使密码短语较弱也是如此。SSH 密钥贡献 256 位熵Ed25519与密码短语强度无关。
### 威胁模型
| 攻击者拥有 | 能否解密? |
|------------|-----------|
| 仅配置文件 | 否 — 需要密码短语 + SSH 密钥 |
| 仅 SSH 密钥 | 否 — 需要密码短语 |
| 仅密码短语 | 否 — 需要 SSH 密钥 |
| 配置文件 + SSH 密钥 + 密码短语 | 是 — 完全泄露 |
---
## 环境变量
| 变量 | 是否必需 | 描述 |
|------|----------|------|
| `PICOCLAW_KEY_PASSPHRASE` | 是(用于 `enc://` | 用于密钥派生的密码短语 |
| `PICOCLAW_SSH_KEY_PATH` | 否 | SSH 私钥路径。如未设置,自动从 `~/.ssh/picoclaw_ed25519.key` 检测 |
### SSH 密钥自动检测
如果未设置 `PICOCLAW_SSH_KEY_PATH`PicoClaw 会查找专用密钥:
```
~/.ssh/picoclaw_ed25519.key
```
此专用文件避免与用户现有的 SSH 密钥冲突。
运行 `picoclaw onboard` 可自动生成该密钥。
`os.UserHomeDir()` 用于跨平台主目录解析(在 Windows 上读取 `USERPROFILE`,在 Unix/macOS 上读取 `HOME`)。
> **注意:** SSH 密钥文件是凭据加密的必要条件。如果未找到密钥且未设置 `PICOCLAW_SSH_KEY_PATH`,加密/解密将失败。运行 `picoclaw onboard` 可自动生成密钥。
---
## 迁移
由于唯一的密钥材料是 `PICOCLAW_KEY_PASSPHRASE` 和 SSH 私钥文件,迁移非常简单:
1. 将配置文件复制到新机器。
2. 将 `PICOCLAW_KEY_PASSPHRASE` 设置为相同的值。
3. 将 SSH 私钥文件复制到相同路径(或将 `PICOCLAW_SSH_KEY_PATH` 设置为新位置)。
无需重新加密。
---
## 安全注意事项
- **密码短语和 SSH 密钥都是必需的。** SSH 密钥作为第二因子 — 没有它,加密/解密将失败。如果密钥不存在,运行 `picoclaw onboard` 生成。
- **SSH 密钥在运行时为只读。** PicoClaw 不会写入或修改 SSH 密钥文件。
- **仍然支持明文密钥。** 不使用 `enc://` 的现有配置不受影响。
- **`enc://` 格式通过版本控制**,通过 HKDF `info` 字段(`picoclaw-credential-v1`)实现,允许未来升级算法而不破坏现有加密值。

36
docs/zh/debug.md Normal file
View file

@ -0,0 +1,36 @@
# 调试 PicoClaw
> 返回 [README](../../README.zh.md)
PicoClaw 在处理每一个请求时,都会在后台执行多个复杂的交互操作——从消息路由和复杂度评估,到工具执行和模型故障适配。能够准确地看到正在发生什么至关重要,这不仅有助于排查潜在问题,也有助于真正理解代理的运作方式。
## 以调试模式启动 PicoClaw
要获取代理运行的详细信息LLM 请求、工具调用、消息路由),可以使用调试标志启动 PicoClaw 网关:
```bash
picoclaw gateway --debug
# or
picoclaw gateway -d
```
在此模式下,系统会对日志进行详细格式化,并显示系统提示词和工具执行结果的预览。
## 禁用日志截断(完整日志)
默认情况下PicoClaw 会在调试日志中截断过长的字符串(例如*系统提示词*或大型 JSON 输出结果),以保持控制台的可读性。
如果你需要检查某个命令的完整输出,或发送给 LLM 模型的确切载荷,可以使用 `--no-truncate` 标志。
**注意:** 此标志*仅*在与 `--debug` 模式组合使用时有效。
```bash
picoclaw gateway --debug --no-truncate
```
当此标志激活时,全局截断功能将被禁用。这在以下场景中非常有用:
* 验证发送给提供商的消息的确切语法。
* 读取 `exec``web_fetch``read_file` 等工具的完整输出。
* 调试保存在内存中的会话历史。

View file

@ -0,0 +1,152 @@
> 返回 [README](../../README.zh.md)
# 🖥️ PicoClaw 硬件兼容性列表
PicoClaw 几乎可以在任何 Linux 设备上运行。本页面记录了已验证的芯片、产品和开发板。
**你的硬件不在列表中?** 提交 PR 来添加它!欢迎硬件厂商贡献和联合推广。
---
## 1. 已验证的芯片支持
### x86
| 厂商 | 芯片 | 备注 |
|------|------|------|
| Intel | Any x86 CPU (i386+) | 所有桌面/服务器/笔记本处理器 |
| AMD | Any x86 CPU | 所有桌面/服务器/笔记本处理器 |
### ARM
| 子架构 | 典型芯片 | 备注 |
|--------|----------|------|
| ARMv6 | [BCM2835](https://www.raspberrypi.com/documentation/computers/processors.html#bcm2835) (Raspberry Pi 1/Zero) | 单核 ARM1176JZF-S |
| ARMv7 | [Allwinner V3s](https://linux-sunxi.org/V3s) | 单核 Cortex-A7用于 LicheePi Zero |
| ARM64 | [Allwinner H618](https://linux-sunxi.org/H618) | 四核 Cortex-A53用于 Orange Pi Zero 3 |
| ARM64 | [BCM2711](https://www.raspberrypi.com/documentation/computers/processors.html#bcm2711) (Raspberry Pi 4) | 四核 Cortex-A72 |
| ARM64 | [BCM2712](https://www.raspberrypi.com/documentation/computers/processors.html#bcm2712) (Raspberry Pi 5) | 四核 Cortex-A76 |
| ARM64 | [AX630C](https://www.axera-tech.com/) (爱芯元智) | 双核 Cortex-A53 + NPU用于 NanoKVM-Pro / MaixCAM2 |
### RISC-V (riscv64)
| 厂商 | 芯片 | 核心 | 备注 |
|------|------|------|------|
| [SOPHGO (算能)](https://www.sophgo.com/) | SG2002 | C906 @ 1GHz | 256MB DDR3 片上内存,用于 LicheeRV-Nano / NanoKVM / MaixCAM |
| [Allwinner (全志)](https://www.allwinnertech.com/) | V861 | Dual C907 | 128MB DDR3L 片上内存1 TOPS NPU4K AI 摄像头 SiP |
| [Allwinner (全志)](https://www.allwinnertech.com/) | V881 | C907 | RISC-V AI 摄像头系列 |
| [Arterytek (匠芯创)](https://www.arterytek.com/) | D213 | RISC-V | 用于 HaaS506-LD1 工业 RTU |
| [SpacemiT (进迭)](https://www.spacemit.com/) | K1 | 8x X60 @ 1.8GHz | 用于 Milk-V Jupiter, BananaPi BPI-F3 |
| [SpacemiT (进迭)](https://www.spacemit.com/) | K3 | 8x X100 @ 2.5GHz | 符合 RVA23 规范1024 位 RVVFP8 AI 推理 |
| [Zhihe (知合)](https://www.zhihe-tech.com/) | A210 | High-perf RISC-V | 8 核16MB L3 缓存,桌面级 |
| [Canaan (嘉楠)](https://www.canaan-creative.com/) | K230 | Dual C908 @ 1.6GHz | 6 TOPS KPU用于 CanMV-K230 |
### MIPS
| 厂商 | 芯片 | 备注 |
|------|------|------|
| MediaTek | [MT7620](https://www.mediatek.com/products/home-networking/mt7620) | MIPS24KEc @ 580MHz用于许多 OpenWrt 路由器(如小米路由器 3G |
### LoongArch (loong64)
| 厂商 | 芯片 | 备注 |
|------|------|------|
| [Loongson (龙芯)](https://www.loongson.cn/) | 3A5000 | 四核 LA464 @ 2.5GHz,桌面/工作站 |
| [Loongson (龙芯)](https://www.loongson.cn/) | 3A6000 | 四核 4C/8T @ 2.5GHzIPC 可与 Intel 第十代相媲美 |
| [Loongson (龙芯)](https://www.loongson.cn/) | 2K1000LA | 双核 @ 1GHz工业/物联网应用 |
---
## 2. 已验证的产品(按发布日期排列)
已通过 PicoClaw 测试的消费产品、路由器和工业设备。
| 年份 | 产品 | 架构 | SoC | 内存 | 类别 |
|------|------|------|-----|------|------|
| 2009 | Nokia N900 | ARM (A8) | OMAP3430 | 256MB | 智能手机 |
| 2012 | Samsung Galaxy Note 10.1 (N8000) | ARM (A9) | Exynos 4412 | 2GB | 平板电脑 |
| 2016 | Xiaomi Router 3G (小米路由器3G) | MIPS | MT7620 | 256MB | 路由器 (OpenWrt) |
| 2018 | Phicomm N1 (斐讯N1) | ARM64 (A53) | S905D | 2GB | 电视盒子 / 家庭服务器 |
| 2019 | Xiaomi AI Speaker (小爱音箱) | ARM64 (A53) | — | 256MB | 智能音箱 |
| 2024 | [NanoKVM](https://wiki.sipeed.com/hardware/en/kvm/NanoKVM/introduction.html) | RISC-V | SG2002 | 256MB | IP-KVM |
| 2025 | HaaS506-LD1 | RISC-V | D213 | 128MB | 工业 RTU |
| 2025 | [NanoKVM-Pro](https://wiki.sipeed.com/hardware/en/kvm/NanoKVM_Pro/introduction.html) | ARM64 (A53) | AX630C | 1GB | 专业 IP-KVM |
| 2026 | [MaixCAM2](https://wiki.sipeed.com/hardware/en/maixcam/index.html) | ARM64 (A53) | AX630C | 1/4GB | 4K AI 摄像头 |
---
## 3. 已验证的开发板(按发布日期排列)
| 年份 | 开发板 | 架构 | SoC | 内存 | 购买链接 |
|------|--------|------|-----|------|----------|
| 2012 | [Raspberry Pi 1 Model B](https://www.raspberrypi.com/products/) | ARMv6 | BCM2835 | 512MB | — |
| 2015 | [Raspberry Pi 2 Model B](https://www.raspberrypi.com/products/raspberry-pi-2-model-b/) | ARMv7 (A7) | BCM2836 | 1GB | — |
| 2015 | [Raspberry Pi Zero](https://www.raspberrypi.com/products/raspberry-pi-zero/) | ARMv6 | BCM2835 | 512MB | — |
| 2016 | [Raspberry Pi 3 Model B](https://www.raspberrypi.com/products/raspberry-pi-3-model-b/) | ARM64 (A53) | BCM2837 | 1GB | — |
| 2017 | [LicheePi Zero](https://wiki.sipeed.com/hardware/en/lichee/Zero/Zero.html) | ARMv7 (A7) | Allwinner V3s | 64MB | [Sipeed](https://sipeed.com/) |
| 2019 | [Raspberry Pi 4 Model B](https://www.raspberrypi.com/products/raspberry-pi-4-model-b/) | ARM64 (A72) | BCM2711 | 1~8GB | [RPi](https://www.raspberrypi.com/) |
| 2023 | [Raspberry Pi 5](https://www.raspberrypi.com/products/raspberry-pi-5/) | ARM64 (A76) | BCM2712 | 2~8GB | [RPi](https://www.raspberrypi.com/) |
| 2024 | [LicheeRV-Nano](https://wiki.sipeed.com/hardware/en/lichee/RV_Nano/1_intro.html) | RISC-V | SG2002 | 256MB | [AliExpress](https://www.aliexpress.com/item/1005006519668532.html) |
| 2024 | [MaixCAM-Pro](https://wiki.sipeed.com/hardware/en/maixcam/index.html) | RISC-V | SG2002 | 256MB | [Sipeed](https://sipeed.com/) |
| 2024 | [Milk-V Duo 64M](https://milkv.io/docs/duo/getting-started/duo) | RISC-V | CV1800B | 64MB | [Milk-V](https://milkv.io/) |
| 2024 | [CanMV-K230](https://developer.canaan-creative.com/k230_canmv/en/main/) | RISC-V | K230 | 512MB | [Canaan](https://www.canaan-creative.com/) |
---
## 4. 同样适用于
### Android 手机(通过 Termux
任何 ARM64 Android 手机2015 年以后1GB 以上内存。安装 [Termux](https://github.com/termux/termux-app),使用 `proot` 运行 PicoClaw。
> 参见 [README在旧 Android 手机上运行](../README.md#-run-on-old-android-phones) 获取设置说明。
### 桌面 / 服务器 / 云
| 平台 | 备注 |
|------|------|
| x86_64 Linux | 原生二进制文件,无依赖 |
| x86_64 Windows | 原生二进制文件 |
| macOS (Intel / Apple Silicon) | 原生二进制文件 |
| Docker (any platform) | `docker compose` 一行命令,参见 [Docker 指南](docker.md) |
| OpenWrt routers | MIPS/ARM 构建,需要 >32MB 可用内存 |
| FreeBSD / NetBSD | 提供 x86_64 和 arm64 构建 |
---
## 5. 最低要求
| 资源 | 最低要求 | 推荐配置 |
|------|----------|----------|
| 内存 | 10MB 可用 | 32MB 以上可用 |
| 存储 | 20MB二进制文件 | 50MB 以上(含工作区) |
| CPU | 任意(单核 0.6GHz 以上) | — |
| 操作系统 | Linux (kernel 3.x+) | Linux 5.x+ |
| 网络 | 必需(用于 LLM API 调用) | 以太网或 WiFi |
---
## 6. 如何测试与贡献
```bash
# 1. 下载适合你架构的版本
wget https://github.com/sipeed/picoclaw/releases/latest/download/picoclaw_Linux_arm64.tar.gz
tar xzf picoclaw_Linux_arm64.tar.gz
# 2. 初始化
./picoclaw onboard
# 3. 测试
./picoclaw agent -m "Hello, what board am I running on?"
```
可用构建版本:`linux-amd64`, `linux-arm64`, `linux-arm`, `linux-riscv64`, `linux-loong64`, `linux-mipsle`
### 添加你的硬件
1. Fork 本仓库
2. 将你的芯片/产品/开发板添加到相应的表格中
3. 包含名称、架构、SoC、内存、年份以及可用的链接
4. 提交 PR
硬件厂商:想要添加官方支持或联合推广?请提交 issue 或通过 [Discord](https://discord.gg/V4sAZ9XWpN) 联系我们。

View file

@ -2,13 +2,15 @@
> 返回 [README](../../README.zh.md)
### 使用 Spawn 的异步任务
PicoClaw 通过 `spawn` 工具支持**异步任务执行**。主要由 **Heartbeat心跳** 系统使用,在不阻塞主 Agent 循环的情况下运行耗时任务。
对于耗时较长的任务网络搜索、API 调用),使用 `spawn` 工具创建一个 **子 Agent (subagent)**
## Heartbeat
心跳系统会定期检查 `workspace/HEARTBEAT.md` 中的计划任务。首次运行时会自动生成默认模板,你可以自定义它来定义快速任务(内联处理)和长任务(通过 `spawn` 委派)。
**`HEARTBEAT.md` 示例:**
```markdown
# Periodic Tasks
## Quick Tasks (respond directly)
- Report current time

View file

@ -43,11 +43,12 @@ Web 工具用于网页搜索和抓取。
### Brave
| 配置项 | 类型 | 默认值 | 描述 |
|---------------|--------|--------|--------------------|
| `enabled` | bool | false | 启用 Brave 搜索 |
| `api_key` | string | - | Brave Search API 密钥 |
| `max_results` | int | 5 | 最大结果数 |
| 配置项 | 类型 | 默认值 | 描述 |
|---------------|----------|--------|------------------------------------------------|
| `enabled` | bool | false | 启用 Brave 搜索 |
| `api_key` | string | - | Brave Search API 密钥 |
| `api_keys` | string[] | - | 多个 API 密钥轮换(优先于 `api_key` |
| `max_results` | int | 5 | 最大结果数 |
### DuckDuckGo
@ -58,11 +59,46 @@ Web 工具用于网页搜索和抓取。
### Perplexity
| 配置项 | 类型 | 默认值 | 描述 |
|---------------|--------|--------|-----------------------|
| `enabled` | bool | false | 启用 Perplexity 搜索 |
| `api_key` | string | - | Perplexity API 密钥 |
| `max_results` | int | 5 | 最大结果数 |
| 配置项 | 类型 | 默认值 | 描述 |
|---------------|----------|--------|------------------------------------------------|
| `enabled` | bool | false | 启用 Perplexity 搜索 |
| `api_key` | string | - | Perplexity API 密钥 |
| `api_keys` | string[] | - | 多个 API 密钥轮换(优先于 `api_key` |
| `max_results` | int | 5 | 最大结果数 |
### Tavily
| 配置项 | 类型 | 默认值 | 描述 |
|---------------|--------|--------|-----------------------------------|
| `enabled` | bool | false | 启用 Tavily 搜索 |
| `api_key` | string | - | Tavily API 密钥 |
| `base_url` | string | - | 自定义 Tavily API 基础 URL |
| `max_results` | int | 0 | 最大结果数0 = 默认) |
### SearXNG
| 配置项 | 类型 | 默认值 | 描述 |
|---------------|--------|--------------------------|-----------------------|
| `enabled` | bool | false | 启用 SearXNG 搜索 |
| `base_url` | string | `http://localhost:8888` | SearXNG 实例 URL |
| `max_results` | int | 5 | 最大结果数 |
### GLM Search
| 配置项 | 类型 | 默认值 | 描述 |
|-----------------|--------|------------------------------------------------------|-----------------------|
| `enabled` | bool | false | 启用 GLM 搜索 |
| `api_key` | string | - | GLM API 密钥 |
| `base_url` | string | `https://open.bigmodel.cn/api/paas/v4/web_search` | GLM Search API URL |
| `search_engine` | string | `search_std` | 搜索引擎类型 |
| `max_results` | int | 5 | 最大结果数 |
### 其他 Web 设置
| 配置项 | 类型 | 默认值 | 描述 |
|--------------------------|----------|--------|-------------------------------------------------|
| `prefer_native` | bool | true | 优先使用 provider 原生搜索而非配置的搜索引擎 |
| `private_host_whitelist` | string[] | `[]` | 允许 Web 抓取的私有/内部主机白名单 |
## Exec 工具
@ -154,6 +190,7 @@ Cron 工具用于调度周期性任务。
| 配置项 | 类型 | 默认值 | 描述 |
|------------------------|------|--------|-------------------------------------|
| `exec_timeout_minutes` | int | 5 | 执行超时时间分钟0 表示无限制 |
| `allow_command` | bool | false | 允许 cron 任务执行 shell 命令 |
## MCP 工具
@ -320,9 +357,27 @@ Skills 工具配置通过 ClawHub 等注册表进行技能发现和安装。
| `registries.clawhub.enabled` | bool | true | 启用 ClawHub 注册表 |
| `registries.clawhub.base_url` | string | `https://clawhub.ai` | ClawHub 基础 URL |
| `registries.clawhub.auth_token` | string | `""` | 可选的 Bearer 令牌,用于更高速率限制 |
| `registries.clawhub.search_path` | string | `/api/v1/search` | 搜索 API 路径 |
| `registries.clawhub.skills_path` | string | `/api/v1/skills` | Skills API 路径 |
| `registries.clawhub.download_path` | string | `/api/v1/download` | 下载 API 路径 |
| `registries.clawhub.search_path` | string | `""` | 搜索 API 路径 |
| `registries.clawhub.skills_path` | string | `""` | Skills API 路径 |
| `registries.clawhub.download_path` | string | `""` | 下载 API 路径 |
| `registries.clawhub.timeout` | int | 0 | 请求超时时间0 = 默认 |
| `registries.clawhub.max_zip_size` | int | 0 | 技能 zip 最大大小字节0 = 默认 |
| `registries.clawhub.max_response_size` | int | 0 | API 响应最大大小字节0 = 默认 |
### GitHub 集成
| 配置项 | 类型 | 默认值 | 描述 |
|------------------|--------|--------|-------------------------------|
| `github.proxy` | string | `""` | GitHub API 请求的 HTTP 代理 |
| `github.token` | string | `""` | GitHub 个人访问令牌 |
### 搜索设置
| 配置项 | 类型 | 默认值 | 描述 |
|----------------------------|------|--------|--------------------------|
| `max_concurrent_searches` | int | 2 | 最大并发技能搜索请求数 |
| `search_cache.max_size` | int | 50 | 最大缓存搜索结果数 |
| `search_cache.ttl_seconds` | int | 300 | 缓存 TTL |
### 配置示例
@ -334,11 +389,17 @@ Skills 工具配置通过 ClawHub 等注册表进行技能发现和安装。
"clawhub": {
"enabled": true,
"base_url": "https://clawhub.ai",
"auth_token": "",
"search_path": "/api/v1/search",
"skills_path": "/api/v1/skills",
"download_path": "/api/v1/download"
"auth_token": ""
}
},
"github": {
"proxy": "",
"token": ""
},
"max_concurrent_searches": 2,
"search_cache": {
"max_size": 50,
"ttl_seconds": 300
}
}
}

View file

@ -16,7 +16,7 @@
**修复方法:** 在 `~/.picoclaw/config.json`(或你的配置路径)中:
1. **agents.defaults.model** 必须匹配 `model_list` 中的某个 `model_name`(例如 `"openrouter-free"`)。
1. **agents.defaults.model_name** 必须匹配 `model_list` 中的某个 `model_name`(例如 `"openrouter-free"`)。
2. 该条目的 **model** 必须是有效的 OpenRouter 模型 ID例如
- `"openrouter/free"` 自动免费层
- `"google/gemini-2.0-flash-exp:free"`
@ -28,7 +28,7 @@
{
"agents": {
"defaults": {
"model": "openrouter-free"
"model_name": "openrouter-free"
}
},
"model_list": [