diff --git a/contrib/luci-app-picoclaw/LICENSE b/contrib/luci-app-picoclaw/LICENSE new file mode 100644 index 000000000..050662185 --- /dev/null +++ b/contrib/luci-app-picoclaw/LICENSE @@ -0,0 +1,66 @@ +MIT License + +Copyright (c) 2026 GennKann + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +--- + +## Disclaimer & Third-Party Notice + +### Relationship to PicoClaw + +This project (**luci-app-picoclaw**) is an **independently created** LuCI web +management interface designed for OpenWrt routers. It provides a convenient +graphical frontend to manage the [PicoClaw](https://github.com/sipeed/picoclaw) +service via the OpenWrt LuCI web interface. + +**This project is NOT a derivative work of PicoClaw.** All source code in this +repository (Lua controller, HTML template, installation scripts, init.d service +file) was originally written by the author and is licensed under the MIT License +above. No source code from PicoClaw is included, copied, or modified in this +repository. + +### What This Project Does + +- Provides a LuCI web UI (controller + view) for managing the PicoClaw service +- Includes installation scripts and init.d service configuration for OpenWrt +- Communicates with PicoClaw via its standard CLI/API interface only + +### PicoClaw License + +PicoClaw is developed by [Sipeed](https://www.sipeed.com/) and is licensed under +the MIT License. If you use this management interface, you must also comply with +the PicoClaw license terms when using PicoClaw itself. + +- PicoClaw repository: https://github.com/sipeed/picoclaw +- PicoClaw license: https://github.com/sipeed/picoclaw/blob/main/LICENSE + +### Trademark Notice + +"PicoClaw" and "Sipeed" are trademarks of their respective owners. +This project is **not affiliated with, endorsed by, or sponsored by** Sipeed +or the PicoClaw project. + +### No Warranty + +This management interface is provided as-is. The author makes no guarantees +about its compatibility with current or future versions of PicoClaw or OpenWrt. +Users are responsible for ensuring that their use of PicoClaw complies with +PicoClaw's own license terms. diff --git a/contrib/luci-app-picoclaw/README.de.md b/contrib/luci-app-picoclaw/README.de.md new file mode 100644 index 000000000..23c66a931 --- /dev/null +++ b/contrib/luci-app-picoclaw/README.de.md @@ -0,0 +1,161 @@ +
+
+
+ Eine schöne LuCI-Weboberfläche zur Verwaltung von PicoClaw auf OpenWrt-Routern +
+ +
+
+
+
+
+
+ English · + 简体中文 · + 日本語 · + Deutsch · + Português +
+ +--- + +## 📸 Screenshots + +| Desktop | Mobil | +|:---:|:---:| +|  |  | +|  | — | + +## ✨ Funktionen + +- 🖥️ **Modernes Dashboard** — Echtzeit-Service-Status, PID, Speichernutzung und Port-Überwachung +- 🚀 **Service-Steuerung** — PicoClaw mit einem Klick starten / stoppen / neu starten +- ⚡ **Autostart-Umschalter** — Autostart direkt in der Weboberfläche aktivieren/deaktivieren +- 📡 **Kanalverwaltung** — Alle Kanäle anzeigen und verwalten (Feishu, Telegram, Discord, WeChat, WeCom, Slack, QQ, LINE, DingTalk, WhatsApp, MaixCam) +- 🔧 **Formular-Konfiguration** — Intuitive Formular-Benutzeroberfläche für AI-Modell, Anbieter, Systemeinstellungen und Tools +- 📝 **JSON-Editor** — Direkte JSON-Bearbeitung mit Formatierung und Validierung +- 🌍 **5 Sprachen** — Eingebauter i18n: English, 简体中文, 日本語, Português, Deutsch +- 🔄 **Online-Update** — Neue Versionen prüfen und direkt aktualisieren +- 🔑 **Multi-Anbieter** — API-Schlüssel für Zhipu, OpenAI, ChatGPT, Claude, DeepSeek, Anthropic, Ollama, Azure OpenAI + +## 📋 Voraussetzungen + +| Anforderung | Details | +|---|---| +| **OpenWrt** | 24.10 / 25.xx (mit LuCI) | +| **Architektur** | ARM64, AMD64, ARMv7 | +| **SSH** | Für das Installationsskript erforderlich | +| **Python** | 3.6+ (auf dem PC) | +| **PicoClaw** | [sipeed/picoclaw](https://github.com/sipeed/picoclaw) neueste Version | + +## 🚀 Installation + +### Methode 1: Python-Installer (Empfohlen) + +```bash +pip install paramiko +wget https://github.com/GennKann/luci-app-picoclaw/releases/latest/download/install_picoclaw_luci.py +python install_picoclaw_luci.py +``` + +### Methode 2: Paket-Installation + +> **Hinweis:** OpenWrt 24.10 verwendet `.ipk` (opkg), OpenWrt 25.xx verwendet `.apk` (apk-tools). Dies sind **unterschiedliche** Paketformate. + +#### OpenWrt 24.10(opkg / .ipk) + +```bash +opkg install luci-compat +wget -O /tmp/luci-app-picoclaw.ipk https://github.com/GennKann/luci-app-picoclaw/releases/latest/download/luci-app-picoclaw_24.10_all.ipk +opkg install /tmp/luci-app-picoclaw.ipk +``` + +#### OpenWrt 25.xx(apk / .apk) + +OpenWrt 25.x hat den Paketmanager von `opkg` auf `apk-tools` umgestellt. Das Format änderte sich von `.ipk` zu `.apk`. Bauen Sie das Paket direkt auf dem Router: + +```bash +# Build-Skript herunterladen +wget -O /tmp/build-apk-25xx.sh https://raw.githubusercontent.com/GennKann/luci-app-picoclaw/main/scripts/build-apk-25xx.sh +chmod +x /tmp/build-apk-25xx.sh + +# .apk-Paket bauen +/tmp/build-apk-25xx.sh + +# Generiertes Paket installieren +apk add --allow-untrusted /root/luci-app-picoclaw_1.0.0_all.apk +``` + +### Methode 3: Manuelle Installation + +```bash +# PicoClaw installieren +ARCH=$(uname -m) +if echo "$ARCH" | grep -q "x86"; then PLAT="linux_amd64"; +elif echo "$ARCH" | grep -q "armv7"; then PLAT="linux_armv7"; +else PLAT="linux_arm64"; fi +wget -O /tmp/picoclaw "https://github.com/sipeed/picoclaw/releases/latest/download/picoclaw_${PLAT}" +chmod +x /tmp/picoclaw && mv /tmp/picoclaw /usr/bin/picoclaw + +# LuCI-Dateien und init.d Service einrichten +# (Dateien aus diesem Repository kopieren) +``` + +## 🎯 Zugriff + +``` +http://+ Wenn Sie dieses Projekt nützlich finden, geben Sie ihm bitte einen ⭐! +
+ + + ++ Made with ❤️ by GennKann +
diff --git a/contrib/luci-app-picoclaw/README.ja.md b/contrib/luci-app-picoclaw/README.ja.md new file mode 100644 index 000000000..e9781dc47 --- /dev/null +++ b/contrib/luci-app-picoclaw/README.ja.md @@ -0,0 +1,172 @@ +
+
+
+ PicoClaw 専用 OpenWrt LuCI 美しい管理パネル +
+ +
+
+
+
+
+
+ English · + 简体中文 · + 日本語 · + Deutsch · + Português +
+ +--- + +## 📸 スクリーンショット + +| デスクトップ | モバイル | +|:---:|:---:| +|  |  | +|  | — | + +## ✨ 機能 + +- 🖥️ **モダンダッシュボード** — サービス状態、PID、メモリ使用量、ポート監視をリアルタイム表示 +- 🚀 **サービス制御** — PicoClawの開始/停止/再起動をワンクリック +- ⚡ **自動起動切替** — Web UIから起動時自動開始の有効/無効を切り替え +- 📡 **チャンネル管理** — 全チャンネルの表示・管理(Feishu、Telegram、Discord、WeChat、WeCom、Slack、QQ、LINE、DingTalk、WhatsApp、MaixCam) +- 🔧 **フォーム設定エディタ** — 直感的なフォームUIでAIモデル、プロバイダー、システム設定、ツールを設定 +- 📝 **JSON設定エディタ** — JSON直接編集、フォーマット、バリデーション対応 +- 🌍 **5言語対応** — 組み込みi18n:English、简体中文、日本語、Português、Deutsch +- 🔄 **オンライン更新** — 新バージョンの確認とUIからの直接更新 +- 📊 **システムログ** — PicoClawシステムログをリアルタイム表示 +- 🔑 **マルチプロバイダー対応** — Zhipu、OpenAI、ChatGPT、Claude、DeepSeek、Anthropic、Ollama、Azure OpenAIのAPIキー設定 +- 🎨 **レスポンシブデザイン** — デスクトップとモバイルブラウザの両方に対応 + +## 📋 動作要件 + +| 要件 | 詳細 | +|---|---| +| **OpenWrt** | 24.10 / 25.xx(LuCI導入済み) | +| **アーキテクチャ** | ARM64、AMD64 (x86_64)、ARMv7 | +| **LuCI** | 標準LuCIインストール | +| **SSH** | インストーラースクリプトに必要 | +| **Python** | 3.6+(PC環境) | +| **PicoClaw** | [sipeed/picoclaw](https://github.com/sipeed/picoclaw) 最新版 | + +## 🚀 インストール + +### 方法1:ワンクリックPythonインストーラー(推奨) + +PC上で実行 — SSH経由でルーターに自動インストールします。 + +```bash +pip install paramiko +wget https://github.com/GennKann/luci-app-picoclaw/releases/latest/download/install_picoclaw_luci.py +python install_picoclaw_luci.py +``` + +### 方法2:パッケージインストール + +> **注意:** OpenWrt 24.10は`.ipk`(opkg)、OpenWrt 25.xxは`.apk`(apk-tools)を使用します。**別の**パッケージ形式です。 + +#### OpenWrt 24.10(opkg / .ipk) + +```bash +opkg install luci-compat +wget -O /tmp/luci-app-picoclaw.ipk https://github.com/GennKann/luci-app-picoclaw/releases/latest/download/luci-app-picoclaw_24.10_all.ipk +opkg install /tmp/luci-app-picoclaw.ipk +``` + +#### OpenWrt 25.xx(apk / .apk) + +OpenWrt 25.xではパッケージマネージャーが`opkg`から`apk-tools`に変更され、形式も`.ipk`から`.apk`になりました。ルーター上で直接ビルドします: + +```bash +# ビルドスクリプトをダウンロード +wget -O /tmp/build-apk-25xx.sh https://raw.githubusercontent.com/GennKann/luci-app-picoclaw/main/scripts/build-apk-25xx.sh +chmod +x /tmp/build-apk-25xx.sh + +# .apkパッケージをビルド +/tmp/build-apk-25xx.sh + +# 生成されたパッケージをインストール +apk add --allow-untrusted /root/luci-app-picoclaw_1.0.0_all.apk +``` + +### 方法3:手動インストール + +```bash +# PicoClawインストール +ARCH=$(uname -m) +if echo "$ARCH" | grep -q "x86"; then PLAT="linux_amd64"; +elif echo "$ARCH" | grep -q "armv7"; then PLAT="linux_armv7"; +else PLAT="linux_arm64"; fi +wget -O /tmp/picoclaw "https://github.com/sipeed/picoclaw/releases/latest/download/picoclaw_${PLAT}" +chmod +x /tmp/picoclaw && mv /tmp/picoclaw /usr/bin/picoclaw + +# LuCIファイル配置 +# controller → /usr/lib/lua/luci/controller/picoclaw.lua +# template → /usr/lib/lua/luci/view/picoclaw/main.htm + +# init.dサービス設定 +cp scripts/picoclaw.init /etc/init.d/picoclaw +chmod +x /etc/init.d/picoclaw && /etc/init.d/picoclaw enable +rm -rf /tmp/luci-* && /etc/init.d/picoclaw start +``` + +## 🎯 アクセス + +``` +http://<ルーターIP>/cgi-bin/luci/admin/services/picoclaw +``` + +## ⚠️ 免責事項 + +このプロジェクトはコミュニティ駆動のPicoClaw管理インターフェースであり、PicoClaw公式プロジェクトの一部ではありません。 + +- **PicoClaw**は[Sipeed](https://github.com/sipeed)によってMITライセンスで開発されています +- 本LuCIインターフェースは独立したオープンソースツールです +- "PicoClaw"および"Sipeed"は各所有者の商標です + +## 📄 ライセンス + +[MIT License](LICENSE) + +## 🙏 クレジット + +- [PicoClaw](https://github.com/sipeed/picoclaw) by Sipeed — このプロジェクトが管理する素晴らしいAIアシスタント +- [OpenWrt](https://openwrt.org/) — 実行環境 +- [LuCI](https://github.com/openwrt/luci) — Webインターフェースフレームワーク + +## 🤝 コントリビューション + +コントリビューションをお待ちしています!お気軽にPull Requestをどうぞ。 + +1. リポジトリをフォーク +2. フィーチャーブランチを作成 (`git checkout -b feature/amazing-feature`) +3. 変更をコミット (`git commit -m 'Add amazing feature'`) +4. ブランチをプッシュ (`git push origin feature/amazing-feature`) +5. Pull Requestを作成 + +--- + ++ このプロジェクトが役立つと思ったら、⭐ をお願いします! +
+ + + ++ Made with ❤️ by GennKann +
diff --git a/contrib/luci-app-picoclaw/README.md b/contrib/luci-app-picoclaw/README.md new file mode 100644 index 000000000..6080fee60 --- /dev/null +++ b/contrib/luci-app-picoclaw/README.md @@ -0,0 +1,69 @@ +# LuCI Management Interface for PicoClaw on OpenWrt + +A beautiful LuCI web interface to manage PicoClaw on OpenWrt routers. + +## Features + +- **Modern Dashboard** — Real-time service status, PID, memory usage, and port monitoring +- **Service Control** — Start / Stop / Restart PicoClaw with one click +- **Auto-Start Toggle** — Enable or disable boot-on-start from the web UI +- **Channel Management** — View and manage all connected channels +- **Form-based Config Editor** — Intuitive form UI for AI model, providers, system settings, and tools configuration +- **JSON Config Editor** — Direct JSON editing with format and validation +- **5 Languages** — Built-in i18n: English, 简体中文, 日本語, Português, Deutsch +- **Online Update** — Check for new versions and update directly from the UI +- **System Logs** — View PicoClaw system logs in real-time +- **Responsive Design** — Works on both desktop and mobile browsers + +## Installation + +### One-Click Python Installer (Recommended) + +```bash +pip install paramiko +python contrib/luci-app-picoclaw/install.py +``` + +### Manual Installation + +```bash +# Copy LuCI controller +cp contrib/luci-app-picoclaw/luci/controller/picoclaw.lua /usr/lib/lua/luci/controller/ + +# Copy LuCI template +mkdir -p /usr/lib/lua/luci/view/picoclaw +cp contrib/luci-app-picoclaw/luci/view/picoclaw/main.htm /usr/lib/lua/luci/view/picoclaw/ + +# Set up init.d service +cp contrib/luci-app-picoclaw/scripts/picoclaw.init /etc/init.d/picoclaw +chmod +x /etc/init.d/picoclaw +/etc/init.d/picoclaw enable +``` + +## Requirements + +- OpenWrt 24.10 / 25.xx with LuCI installed +- ARM64 / AMD64 / ARMv7 +- PicoClaw latest version + +## Screenshots + +| Desktop | Mobile | +|:---:|:---:| +|  |  | +|  | — | + +## Access + +``` +http://
+
+
+ Uma interface web LuCI bonita para gerenciar o PicoClaw em roteadores OpenWrt +
+ +
+
+
+
+
+
+ English · + 简体中文 · + 日本語 · + Deutsch · + Português +
+ +--- + +## 📸 Capturas de Tela + +| Desktop | Mobile | +|:---:|:---:| +|  |  | +|  | — | + +## ✨ Funcionalidades + +- 🖥️ **Painel Moderno** — Status do serviço em tempo real, PID, uso de memória e monitoramento de porta +- 🚀 **Controle de Serviço** — Iniciar / Parar / Reiniciar o PicoClaw com um clique +- ⚡ **Alternar Auto-início** — Ativar/desativar inicialização automática pela interface web +- 📡 **Gerenciamento de Canais** — Visualizar e gerenciar todos os canais (Feishu, Telegram, Discord, WeChat, WeCom, Slack, QQ, LINE, DingTalk, WhatsApp, MaixCam) +- 🔧 **Editor de Configuração** — Interface de formulário intuitiva para modelo AI, provedores, configurações do sistema e ferramentas +- 📝 **Editor JSON** — Edição direta JSON com formatação e validação +- 🌍 **5 Idiomas** — i18n integrado: English, 简体中文, 日本語, Português, Deutsch +- 🔄 **Atualização Online** — Verificar novas versões e atualizar diretamente pela interface +- 🔑 **Multi-provedor** — Chaves API para Zhipu, OpenAI, ChatGPT, Claude, DeepSeek, Anthropic, Ollama, Azure OpenAI + +## 📋 Requisitos + +| Requisito | Detalhes | +|---|---| +| **OpenWrt** | 24.10 / 25.xx (com LuCI) | +| **Arquitetura** | ARM64, AMD64, ARMv7 | +| **SSH** | Necessário para o script de instalação | +| **Python** | 3.6+ (no PC) | +| **PicoClaw** | [sipeed/picoclaw](https://github.com/sipeed/picoclaw) versão mais recente | + +## 🚀 Instalação + +### Método 1: Instalador Python (Recomendado) + +```bash +pip install paramiko +wget https://github.com/GennKann/luci-app-picoclaw/releases/latest/download/install_picoclaw_luci.py +python install_picoclaw_luci.py +``` + +### Método 2: Instalação por Pacote + +> **Nota:** OpenWrt 24.10 usa `.ipk` (opkg), OpenWrt 25.xx usa `.apk` (apk-tools). São **formatos diferentes** de pacotes. + +#### OpenWrt 24.10(opkg / .ipk) + +```bash +opkg install luci-compat +wget -O /tmp/luci-app-picoclaw.ipk https://github.com/GennKann/luci-app-picoclaw/releases/latest/download/luci-app-picoclaw_24.10_all.ipk +opkg install /tmp/luci-app-picoclaw.ipk +``` + +#### OpenWrt 25.xx(apk / .apk) + +OpenWrt 25.x mudou o gerenciador de pacotes de `opkg` para `apk-tools`, e o formato de `.ipk` para `.apk`. Construa o pacote diretamente no roteador: + +```bash +# Baixar script de compilação +wget -O /tmp/build-apk-25xx.sh https://raw.githubusercontent.com/GennKann/luci-app-picoclaw/main/scripts/build-apk-25xx.sh +chmod +x /tmp/build-apk-25xx.sh + +# Compilar pacote .apk +/tmp/build-apk-25xx.sh + +# Instalar pacote gerado +apk add --allow-untrusted /root/luci-app-picoclaw_1.0.0_all.apk +``` + +### Método 3: Instalação Manual + +```bash +# Instalar PicoClaw +ARCH=$(uname -m) +if echo "$ARCH" | grep -q "x86"; then PLAT="linux_amd64"; +elif echo "$ARCH" | grep -q "armv7"; then PLAT="linux_armv7"; +else PLAT="linux_arm64"; fi +wget -O /tmp/picoclaw "https://github.com/sipeed/picoclaw/releases/latest/download/picoclaw_${PLAT}" +chmod +x /tmp/picoclaw && mv /tmp/picoclaw /usr/bin/picoclaw + +# Configurar arquivos LuCI e serviço init.d +# (copiar arquivos deste repositório) +``` + +## 🎯 Acesso + +``` +http://+ Se você achar este projeto útil, por favor, dê uma ⭐! +
+ + + ++ Made with ❤️ by GennKann +
diff --git a/contrib/luci-app-picoclaw/README.zh.md b/contrib/luci-app-picoclaw/README.zh.md new file mode 100644 index 000000000..0798f0b43 --- /dev/null +++ b/contrib/luci-app-picoclaw/README.zh.md @@ -0,0 +1,199 @@ +
+
+
+ 为 PicoClaw 量身打造的 OpenWrt LuCI 美化管理面板 +
+ +
+
+
+
+
+
+ English · + 简体中文 · + 日本語 · + Deutsch · + Português +
+ +--- + +## 📸 截图预览 + +| 桌面端 | 移动端 | +|:---:|:---:| +|  |  | +|  | — | + +## ✨ 功能特性 + +- 🖥️ **现代化仪表盘** — 实时显示服务状态、PID、内存占用、端口监听 +- 🚀 **服务控制** — 一键启动 / 停止 / 重启 PicoClaw +- ⚡ **开机自启开关** — 在网页上直接控制开机自动启动 +- 📡 **通道管理** — 查看和管理所有通道(飞书、Telegram、Discord、微信、企业微信、Slack、QQ、LINE、钉钉、WhatsApp、MaixCam) +- 🔧 **表单化配置编辑** — 直观的表单界面配置 AI 模型、API 密钥、系统设置和工具 +- 📝 **JSON 配置编辑** — 支持 JSON 直接编辑、格式化和验证 +- 🌍 **5 种语言** — 内置国际化:简体中文、English、日本語、Português、Deutsch +- 🔄 **在线更新** — 检查新版本并直接在界面上更新 +- 📊 **系统日志** — 实时查看 PicoClaw 系统日志 +- 💬 **微信接入引导** — 微信个人号接入步骤引导 +- 🔑 **多 AI 供应商支持** — 配置智谱、OpenAI、ChatGPT、Claude、DeepSeek、Anthropic、Ollama、Azure OpenAI +- 🎨 **响应式设计** — 完美适配桌面和手机浏览器 +- 📦 **一键安装** — Python 安装脚本,通过 SSH 自动部署到任意 OpenWrt 设备 + +## 📋 系统要求 + +| 要求 | 说明 | +|---|---| +| **OpenWrt** | 24.10 / 25.xx(需安装 LuCI) | +| **架构** | ARM64、AMD64 (x86_64)、ARMv7 | +| **LuCI** | 标准 LuCI 安装即可 | +| **SSH** | 安装脚本需要路由器开启 SSH | +| **Python** | 3.6+(在电脑上运行安装脚本) | +| **PicoClaw** | [sipeed/picoclaw](https://github.com/sipeed/picoclaw) 最新版 | + +## 🚀 安装方式 + +### 方式一:一键 Python 安装(推荐) + +在你的电脑上运行,脚本会通过 SSH 自动完成所有操作。 + +```bash +# 安装依赖 +pip install paramiko + +# 下载安装脚本 +wget https://github.com/GennKann/luci-app-picoclaw/releases/latest/download/install_picoclaw_luci.py + +# 运行 — 按提示输入路由器信息 +python install_picoclaw_luci.py +``` + +安装脚本会自动完成: +1. ✅ 检测系统架构(ARM64 / AMD64 / ARMv7) +2. ✅ 下载并安装最新版 PicoClaw +3. ✅ 创建 procd init.d 开机自启服务 +4. ✅ 部署 LuCI 网页管理界面 +5. ✅ 初始化 PicoClaw 配置 +6. ✅ 启动服务并验证 + +### 方式二:手动安装 + +SSH 登录你的 OpenWrt 路由器: + +```bash +# 1. 下载并安装 PicoClaw +ARCH=$(uname -m) +if echo "$ARCH" | grep -q "x86"; then PLAT="linux_amd64"; +elif echo "$ARCH" | grep -q "armv7"; then PLAT="linux_armv7"; +else PLAT="linux_arm64"; fi + +wget -O /tmp/picoclaw "https://github.com/sipeed/picoclaw/releases/latest/download/picoclaw_${PLAT}" +chmod +x /tmp/picoclaw && mv /tmp/picoclaw /usr/bin/picoclaw + +# 2. 部署 LuCI 文件(从本仓库复制) +# controller → /usr/lib/lua/luci/controller/picoclaw.lua +# template → /usr/lib/lua/luci/view/picoclaw/main.htm + +# 3. 设置 init.d 服务 +cp scripts/picoclaw.init /etc/init.d/picoclaw +chmod +x /etc/init.d/picoclaw && /etc/init.d/picoclaw enable + +# 4. 清理缓存并启动 +rm -rf /tmp/luci-* && /etc/init.d/picoclaw start +``` + +### 方式三:包管理器安装 + +> **注意:** OpenWrt 24.10 使用 `.ipk`(opkg 包管理器),OpenWrt 25.xx 使用 `.apk`(apk-tools 包管理器),两者是**不同的**包格式。 + +#### OpenWrt 24.10(opkg / .ipk) + +```bash +opkg install luci-compat +wget -O /tmp/luci-app-picoclaw.ipk https://github.com/GennKann/luci-app-picoclaw/releases/latest/download/luci-app-picoclaw_24.10_all.ipk +opkg install /tmp/luci-app-picoclaw.ipk +``` + +#### OpenWrt 25.xx(apk / .apk) + +OpenWrt 25.x 已将包管理器从 `opkg` 切换为 `apk-tools`,包格式从 `.ipk` 变为 `.apk`。需要在路由器上直接构建: + +```bash +# 下载构建脚本 +wget -O /tmp/build-apk-25xx.sh https://raw.githubusercontent.com/GennKann/luci-app-picoclaw/main/scripts/build-apk-25xx.sh +chmod +x /tmp/build-apk-25xx.sh + +# 运行构建 .apk 包 +/tmp/build-apk-25xx.sh + +# 安装生成的包 +apk add --allow-untrusted /root/luci-app-picoclaw_1.0.0_all.apk +``` + +> **为什么需要在路由器上构建?** OpenWrt 25.xx 使用 APKv3(Alpine Package Keeper)格式,需要 `apk-tools` 来正确构建。在路由器上构建可确保完全兼容。 + +## 🎯 访问地址 + +安装完成后,通过以下地址访问管理界面: + +``` +http://<路由器IP>/cgi-bin/luci/admin/services/picoclaw +``` + +例如:`http://192.168.1.1/cgi-bin/luci/admin/services/picoclaw` + +## ⚠️ 免责声明 + +本项目是社区驱动的 PicoClaw LuCI 管理界面,**不是** PicoClaw 官方项目的一部分。 + +- **PicoClaw** 由 [Sipeed](https://github.com/sipeed) 使用 MIT 许可证开发 +- 本 LuCI 界面是独立的开源工具 +- 我们尊重原始项目的所有知识产权 +- "PicoClaw" 和 "Sipeed" 是其各自所有者的商标 + +## 📄 许可证 + +本项目使用 [MIT 许可证](LICENSE)。 + +## 🙏 鸣谢 + +- [PicoClaw](https://github.com/sipeed/picoclaw) by Sipeed — 本项目所管理的出色 AI 助手 +- [OpenWrt](https://openwrt.org/) — 运行基础 +- [LuCI](https://github.com/openwrt/luci) — Web 界面框架 + +## 🤝 参与贡献 + +欢迎贡献!请随时提交 Pull Request。 + +1. Fork 本仓库 +2. 创建功能分支 (`git checkout -b feature/amazing-feature`) +3. 提交更改 (`git commit -m 'Add amazing feature'`) +4. 推送分支 (`git push origin feature/amazing-feature`) +5. 发起 Pull Request + +--- + ++ 如果这个项目对你有帮助,请给一个 ⭐ 支持一下! +
+ + + ++ ❤️ 由 GennKann 用心制作 +
diff --git a/contrib/luci-app-picoclaw/Screenshots/logo.svg b/contrib/luci-app-picoclaw/Screenshots/logo.svg new file mode 100644 index 000000000..b4230f004 --- /dev/null +++ b/contrib/luci-app-picoclaw/Screenshots/logo.svg @@ -0,0 +1,35 @@ + diff --git a/contrib/luci-app-picoclaw/Screenshots/screenshot_config.png b/contrib/luci-app-picoclaw/Screenshots/screenshot_config.png new file mode 100644 index 000000000..a729e76b4 Binary files /dev/null and b/contrib/luci-app-picoclaw/Screenshots/screenshot_config.png differ diff --git a/contrib/luci-app-picoclaw/Screenshots/screenshot_main.png b/contrib/luci-app-picoclaw/Screenshots/screenshot_main.png new file mode 100644 index 000000000..fd86256c0 Binary files /dev/null and b/contrib/luci-app-picoclaw/Screenshots/screenshot_main.png differ diff --git a/contrib/luci-app-picoclaw/Screenshots/screenshot_mobile.png b/contrib/luci-app-picoclaw/Screenshots/screenshot_mobile.png new file mode 100644 index 000000000..77863a088 Binary files /dev/null and b/contrib/luci-app-picoclaw/Screenshots/screenshot_mobile.png differ diff --git a/contrib/luci-app-picoclaw/install.py b/contrib/luci-app-picoclaw/install.py new file mode 100644 index 000000000..34796fc18 --- /dev/null +++ b/contrib/luci-app-picoclaw/install.py @@ -0,0 +1,194 @@ +#!/usr/bin/env python3 +""" +PicoClaw + LuCI One-Click Installer for OpenWrt +Supports OpenWrt 24.10 / 25.xx (ARM64 / AMD64 / ARMv7) + +Usage: + pip install paramiko + python install.py +""" + +import paramiko +import sys +import os +import time +import io + +sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8', errors='replace') + +# NOTE: The LuCI controller and view template are deployed from the actual files +# in this repository (luci/controller/picoclaw.lua and luci/view/picoclaw/main.htm), +# NOT from inline string literals. This ensures the deployed code always matches +# the latest version in the repo. +# +# LuCI controller: luci/controller/picoclaw.lua +# LuCI view template: luci/view/picoclaw/main.htm + + +def print_step(msg): + print(f"\n{'='*55}") + print(f" {msg}") + print(f"{'='*55}") + + +def run_cmd(client, cmd, timeout=120): + stdin, stdout, stderr = client.exec_command(cmd, timeout=timeout) + try: + out = stdout.read().decode('utf-8', errors='replace').strip() + except: + out = "(timeout)" + try: + err = stderr.read().decode('utf-8', errors='replace').strip() + except: + err = "" + if out: + print(f" {out}") + if err and 'warning' not in err.lower(): + print(f" [ERR] {err}") + return out, err + + +def main(): + print(""" +╔══════════════════════════════════════════════════════════╗ +║ PicoClaw + LuCI One-Click Installer ║ +║ OpenWrt 24.10 / 25.xx (ARM64/AMD64/ARMv7) ║ +║ https://github.com/sipeed/picoclaw ║ +╚══════════════════════════════════════════════════════════╝ + """) + + host = input("Router IP [default: 192.168.1.1]: ").strip() or "192.168.1.1" + port = int(input("SSH Port [default: 22]: ").strip() or "22") + user = input("SSH User [default: root]: ").strip() or "root" + pwd = input("SSH Password: ").strip() + if not pwd: + print("Error: password required") + sys.exit(1) + + print(f"\nConnecting to {user}@{host}:{port} ...") + client = paramiko.SSHClient() + client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) + try: + client.connect(host, port=port, username=user, password=pwd, timeout=15) + except Exception as e: + print(f"Connection failed: {e}") + sys.exit(1) + print("Connected!") + + def run(cmd, timeout=120): + return run_cmd(client, cmd, timeout) + + # Step 1: Detect system + print_step("Step 1/6: Detect System") + arch_out, _ = run("uname -m") + arch = "linux_arm64" + if "x86" in arch_out: + arch = "linux_amd64" + elif "armv7" in arch_out: + arch = "linux_armv7" + print(f" Architecture: {arch_out} -> {arch}") + + release_out, _ = run("cat /etc/openwrt_release 2>/dev/null | grep DISTRIB_DESCRIPTION") + print(f" System: {release_out}") + + has_luci, _ = run("test -d /usr/lib/lua/luci && echo 'yes' || echo 'no'") + + # Step 2: Install PicoClaw + print_step("Step 2/6: Install PicoClaw") + existing_ver, _ = run("picoclaw version 2>&1 || echo 'not installed'") + if 'not installed' not in existing_ver and existing_ver: + print(f" Already installed: {existing_ver}") + reinstall = input(" Reinstall? (y/N): ").strip().lower() + if reinstall != 'y': + print(" Skipped") + else: + run(f"curl -L -o /tmp/picoclaw_new 'https://github.com/sipeed/picoclaw/releases/latest/download/picoclaw_{arch}' --max-time 120") + run("chmod +x /tmp/picoclaw_new; cp /usr/bin/picoclaw /usr/bin/picoclaw.bak 2>/dev/null; mv /tmp/picoclaw_new /usr/bin/picoclaw") + run("picoclaw version 2>&1") + else: + print(" Downloading PicoClaw...") + run(f"curl -L -o /tmp/picoclaw 'https://github.com/sipeed/picoclaw/releases/latest/download/picoclaw_{arch}' --max-time 120") + run("chmod +x /tmp/picoclaw; mkdir -p /usr/bin; cp /tmp/picoclaw /usr/bin/picoclaw; rm -f /tmp/picoclaw") + run("picoclaw version 2>&1") + + # Step 3: init.d service + print_step("Step 3/6: Create init.d Service") + sftp = client.open_sftp() + initd_script = open(os.path.join(os.path.dirname(__file__), 'scripts', 'picoclaw.init'), 'r').read() + with sftp.open('/etc/init.d/picoclaw', 'w') as f: + f.write(initd_script) + print(" Written /etc/init.d/picoclaw") + run("chmod +x /etc/init.d/picoclaw; /etc/init.d/picoclaw enable 2>&1") + print(" Auto-start enabled") + + # Step 4: Deploy LuCI + if has_luci.strip() == 'yes': + print_step("Step 4/6: Deploy LuCI Interface") + controller_path = os.path.join(os.path.dirname(__file__), 'luci', 'controller', 'picoclaw.lua') + template_path = os.path.join(os.path.dirname(__file__), 'luci', 'view', 'picoclaw', 'main.htm') + + with sftp.open('/usr/lib/lua/luci/controller/picoclaw.lua', 'w') as f: + f.write(open(controller_path, 'r').read()) + print(" Controller deployed") + + run("mkdir -p /usr/lib/lua/luci/view/picoclaw") + with sftp.open('/usr/lib/lua/luci/view/picoclaw/main.htm', 'w') as f: + f.write(open(template_path, 'r').read()) + print(" Template deployed") + + run("rm -rf /tmp/luci-* 2>/dev/null") + print(" LuCI cache cleared") + luci_url = f"http://{host}/cgi-bin/luci/admin/services/picoclaw" + else: + print_step("Step 4/6: Skipped (LuCI not detected)") + luci_url = "" + + sftp.close() + + # Step 5: Init config + print_step("Step 5/6: Initialize Config") + run("mkdir -p /root/.picoclaw") + has_config, _ = run("test -f /root/.picoclaw/config.json && echo 'yes' || echo 'no'") + if has_config.strip() != 'yes': + print(" Running picoclaw gateway to generate default config...") + run("picoclaw gateway >/dev/null 2>&1 &") + time.sleep(3) + run("pkill -f 'picoclaw gateway' 2>/dev/null") + time.sleep(1) + print(" Default config generated") + else: + print(" Config exists, skipped") + + # Step 6: Start service + print_step("Step 6/6: Start PicoClaw") + run("pkill -f 'picoclaw gateway' 2>/dev/null") + time.sleep(1) + run("/etc/init.d/picoclaw start 2>&1") + time.sleep(3) + + ps_out, _ = run("ps | grep 'picoclaw gateway' | grep -v grep") + print(f"\n{'='*55}") + print(f" Installation Complete!") + print(f"{'='*55}") + if ps_out: + print(f" [OK] PicoClaw is running") + else: + print(f" [!] PicoClaw not detected, check: picoclaw gateway") + if luci_url: + print(f"\n LuCI Manager: {luci_url}") + print(f" API: http://{host}:18790") + print(f" Config: /root/.picoclaw/config.json") + + client.close() + print("\nDone!") + + +if __name__ == '__main__': + try: + main() + except KeyboardInterrupt: + print("\nCancelled") + sys.exit(0) + except Exception as e: + print(f"\nError: {e}") + sys.exit(1) diff --git a/contrib/luci-app-picoclaw/luci/controller/picoclaw.lua b/contrib/luci-app-picoclaw/luci/controller/picoclaw.lua new file mode 100644 index 000000000..28e8087ad --- /dev/null +++ b/contrib/luci-app-picoclaw/luci/controller/picoclaw.lua @@ -0,0 +1,333 @@ +module("luci.controller.picoclaw", package.seeall) + +function index() + entry({"admin", "services", "picoclaw"}, call("action_main"), "PicoClaw", 60) + entry({"admin", "services", "picoclaw", "action"}, call("action_do"), nil) +end + +function get_status() + local pid = "" + local running = false + local memory_kb = 0 + local port_active = false + local f = io.popen("ps | grep 'picoclaw gateway' | grep -v grep | head -1 2>/dev/null") + if f then + local line = f:read("*l") or "" + f:close() + local p = line:match("^%s*(%d+)") + if p and p ~= "" then + pid = p + running = true + end + end + if running and pid ~= "" then + local mf = io.open("/proc/" .. pid .. "/status", "r") + if mf then + local c = mf:read("*a") + mf:close() + local vm = c:match("VmRSS:%s*(%d+)") + if vm then memory_kb = tonumber(vm) or 0 end + end + end + local nf = io.open("/proc/net/tcp6", "r") + if not nf then nf = io.open("/proc/net/tcp", "r") end + if nf then + local c = nf:read("*a") + nf:close() + if c:find(":4966") then port_active = true end + end + return {running=running, pid=pid, memory_kb=memory_kb, port_active=port_active} +end + +function get_config() + local f = io.open("/root/.picoclaw/config.json", "r") + if not f then return nil, "Config file not found" end + local c = f:read("*a") + f:close() + return c, nil +end + +function get_version_info() + local cur_ver = "N/A" + local build_time = "" + local git_commit = "" + local f = io.open("/root/.picoclaw/config.json", "r") + if f then + local c = f:read("*a") + f:close() + local v = c:match('"version"%s*:%s*"([^"]+)"') + if v then cur_ver = v end + local bt = c:match('"build_time"%s*:%s*"([^"]+)"') + if bt then build_time = bt end + local gc = c:match('"git_commit"%s*:%s*"([^"]+)"') + if gc then git_commit = gc end + end + return cur_ver, build_time, git_commit +end + +function check_latest_version() + local latest_ver = "" + local latest_url = "" + local err_msg = "" + local cache_file = "/tmp/picoclaw_latest_ver" + local cf = io.open(cache_file, "r") + if cf then + local cached = cf:read("*a") + cf:close() + local v = cached:match("^([%d.]+)") + local u = cached:match("\n(.+)$") + local ts = 0 + local tf = io.open(cache_file .. ".ts", "r") + if tf then + ts = tonumber(tf:read("*l")) or 0 + tf:close() + end + if v and ts and (os.time() - ts < 3600) then + return v, u or "", "" + end + end + local f = io.popen("curl -sL --max-time 5 'https://api.github.com/repos/sipeed/picoclaw/releases/latest' 2>/dev/null") + if f then + local body = f:read("*a") + f:close() + local v = body:match('"tag_name"%s*:%s*"v?([^"]+)"') + if v then latest_ver = v end + local u = body:match('"browser_download_url"%s*:%s*"(.-linux_arm64)"') + if u then latest_url = u end + else + err_msg = "curl failed" + end + if latest_ver ~= "" then + local cf2 = io.open(cache_file, "w") + if cf2 then + cf2:write(latest_ver .. "\n" .. latest_url) + cf2:close() + end + local tf = io.open(cache_file .. ".ts", "w") + if tf then + tf:write(tostring(os.time())) + tf:close() + end + end + if latest_ver == "" then err_msg = "checking" end + return latest_ver, latest_url, err_msg +end + +function get_logs() + local f = io.popen("logread 2>/dev/null | grep -i picoclaw | tail -50") + if not f then return "" end + local l = f:read("*a") or "" + f:close() + if l == "" then + local f2 = io.popen("logread 2>/dev/null | tail -30") + if f2 then + l = f2:read("*a") or "" + f2:close() + end + end + return l +end + +function html_escape(s) + if not s then return "" end + s = tostring(s) + s = s:gsub("&", "&") + s = s:gsub("<", "<") + s = s:gsub(">", ">") + s = s:gsub('"', """) + return s +end + +function do_update() + local arch = "linux_arm64" + local f = io.popen("uname -m 2>/dev/null") + if f then + local m = f:read("*l") or "" + f:close() + if m:find("x86") then arch = "linux_amd64" end + end + local dl_url = "https://github.com/sipeed/picoclaw/releases/latest/download/picoclaw_" .. arch + os.execute("pkill -f 'picoclaw gateway' 2>/dev/null") + os.execute("sleep 1") + os.execute("curl -L -o /tmp/picoclaw_new '" .. dl_url .. "' --max-time 120 2>&1") + os.execute("chmod +x /tmp/picoclaw_new") + os.execute("cp /usr/bin/picoclaw /usr/bin/picoclaw.bak 2>/dev/null") + os.execute("mv /tmp/picoclaw_new /usr/bin/picoclaw") + os.execute("picoclaw gateway >/dev/null 2>&1 &") + os.execute("sleep 3") +end + +function action_do() + local http = require("luci.http") + local action = http.formvalue("action") or "" + local msg = "" + local ok = true + + if action == "start" then + os.execute("picoclaw gateway >/dev/null 2>&1 &") + os.execute("sleep 2") + msg = "服务正在启动..." + elseif action == "stop" then + os.execute("pkill -f 'picoclaw gateway' 2>/dev/null") + os.execute("sleep 1") + msg = "服务已停止。" + elseif action == "restart" then + os.execute("pkill -f 'picoclaw gateway' 2>/dev/null") + os.execute("sleep 1") + os.execute("picoclaw gateway >/dev/null 2>&1 &") + os.execute("sleep 2") + msg = "服务已重启。" + elseif action == "autostart_on" then + os.execute("/etc/init.d/picoclaw enable 2>/dev/null; ln -sf /etc/init.d/picoclaw /etc/rc.d/S99picoclaw 2>/dev/null") + msg = "已启用开机自动启动。" + elseif action == "autostart_off" then + os.execute("/etc/init.d/picoclaw disable 2>/dev/null; rm -f /etc/rc.d/S99picoclaw 2>/dev/null") + msg = "已关闭开机自动启动。" + elseif action == "save_config" then + local config = http.formvalue("config") or "" + if config ~= "" then + local f = io.open("/root/.picoclaw/config.json", "w") + if f then + f:write(config) + f:close() + os.execute("pkill -f 'picoclaw gateway' 2>/dev/null; sleep 1; picoclaw gateway >/dev/null 2>&1 &") + msg = "配置已保存,服务已重启!" + else + msg = "错误:无法写入配置文件" + ok = false + end + else + msg = "错误:配置内容为空" + ok = false + end + elseif action == "save_form_config" then + local config = http.formvalue("config") or "" + if config ~= "" then + local f = io.open("/root/.picoclaw/config.json", "w") + if f then + f:write(config) + f:close() + os.execute("pkill -f 'picoclaw gateway' 2>/dev/null; sleep 1; picoclaw gateway >/dev/null 2>&1 &") + msg = "配置已保存,服务已重启!" + else + msg = "错误:无法写入配置文件" + ok = false + end + else + msg = "错误:配置内容为空" + ok = false + end + elseif action == "update" then + do_update() + msg = "更新完成,服务已重启!" + end + + local dispatcher = require("luci.dispatcher") + local url = dispatcher.build_url("admin", "services", "picoclaw") + if msg ~= "" then + url = url .. "?msg=" .. luci.http.urlencode(msg) .. "&ok=" .. (ok and "1" or "0") + end + luci.http.redirect(url) +end + +function action_main() + local http = require("luci.http") + local status = get_status() + local config_content, config_err = get_config() + local logs = get_logs() + + local cur_ver, build_time, git_commit = get_version_info() + local latest_ver, latest_url, check_err = check_latest_version() + + local has_update = false + if latest_ver ~= "" and cur_ver ~= "N/A" then + local function ver_parts(v) + local t = {} + for n in v:gmatch("%d+") do + t[#t + 1] = tonumber(n) + end + return t + end + local cv = ver_parts(cur_ver) + local lv = ver_parts(latest_ver) + for i = 1, math.max(#cv, #lv) do + local a = cv[i] or 0 + local b = lv[i] or 0 + if b > a then + has_update = true + break + end + if a > b then + break + end + end + end + + local memory_mb = "0.0" + if status.memory_kb and tonumber(status.memory_kb) then + memory_mb = string.format("%.1f", tonumber(status.memory_kb) / 1024) + end + local pid_str = "-" + if status.pid and status.pid ~= "" then + pid_str = tostring(status.pid) + end + + local weixin_status = "none" + local weixin_configured = false + if config_content then + local ws = config_content:find('"weixin"') + if ws then + local wblock = config_content:sub(ws, ws + 2000) + local wenabled = false + local wep = wblock:find('"enabled"') + if wep then + local wrest = wblock:sub(wep + 9) + wrest = wrest:match("^[%s]*:[%s]*(.*)") + if wrest and wrest:sub(1, 4) == "true" then + local wnc = wrest:sub(5, 5) + if wnc == "" or wnc == "," or wnc == "}" or wnc:match("%s") then + wenabled = true + end + end + end + local burl = wblock:match('"base_url"%s*:%s*"([^"]+)"') + weixin_configured = (burl ~= nil and burl ~= "") + if wenabled then + weixin_status = "connected" + elseif weixin_configured then + weixin_status = "configured" + end + end + end + + local flash_msg = http.formvalue("msg") or "" + local flash_ok = http.formvalue("ok") or "1" + + local autostart = false + local asf = io.open("/etc/rc.d/S99picoclaw", "r") + if asf then asf:close() autostart = true end + + luci.template.render("picoclaw/main", { + running = status.running, + pid = pid_str, + memory_mb = memory_mb, + port_active = status.port_active or false, + cur_ver = html_escape(cur_ver), + latest_ver = html_escape(latest_ver), + build_time = html_escape(build_time), + git_commit = html_escape(git_commit), + latest_url = html_escape(latest_url), + has_update = has_update, + check_err = check_err, + config_content = html_escape(config_content or ""), + config_raw = (config_content or ""), + weixin_status = weixin_status, + weixin_configured = weixin_configured, + channels_html = "", + logs = html_escape(logs), + flash_msg = html_escape(flash_msg), + flash_ok = flash_ok, + action_url = luci.dispatcher.build_url("admin", "services", "picoclaw", "action"), + autostart = autostart + }) +end diff --git a/contrib/luci-app-picoclaw/luci/view/picoclaw/main.htm b/contrib/luci-app-picoclaw/luci/view/picoclaw/main.htm new file mode 100644 index 000000000..f4dee163a --- /dev/null +++ b/contrib/luci-app-picoclaw/luci/view/picoclaw/main.htm @@ -0,0 +1,810 @@ +<%+header%> + +<% +local flash_msg = flash_msg or "" +local flash_ok = flash_ok or "1" +if flash_msg ~= "" then +%> +picoclaw auth weixin 命令扫码授权后,即可通过微信个人号与 AI 助手对话
+ picoclaw auth weixin