feat(docs): initialize response wrapper and custom Pi documentation
This commit is contained in:
parent
1175f4a62b
commit
0400b31c8e
5 changed files with 162 additions and 1 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -69,3 +69,4 @@ web/backend/dist/*
|
|||
docker/data
|
||||
|
||||
.omc/
|
||||
/local_pi/
|
||||
|
|
|
|||
51
docs/custom/git-workflow.md
Normal file
51
docs/custom/git-workflow.md
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
# Git Workflow Guide
|
||||
|
||||
This guide breaks down how to manage your custom `picoclaw` logic alongside upstream official releases.
|
||||
|
||||
## Core Concepts
|
||||
- **Forking** is for **Taking Ownership**: It creates an independent copy of an entire project repository on your GitHub account so you have full read/write admin controls.
|
||||
- **Branching** is for **Making Changes**: It isolates a specific line of code history (e.g., `feature/wrapper`) so you can experiment without breaking your working `main` branch.
|
||||
|
||||
## The "One Custom Branch" Strategy (Best & Lowest Effort)
|
||||
|
||||
For maintaining a personal Raspberry Pi deployment, the cleanest, least confusing, and absolute lowest effort method is to literally never switch branches again. Instead of juggling dozens of feature branches, you maintain a single dedicated branch (e.g., `custom-pi`) that holds all your custom logic.
|
||||
|
||||
**Initial Setup:**
|
||||
1. **The Fork**: You forked `sipeed/picoclaw` to `TimZickenrott/picoclaw`.
|
||||
2. **The Clone**: You downloaded your fork to your PC.
|
||||
3. **The Branch**: You started on `feature/wrapper`. Let's rename this to be your permanent deploy branch:
|
||||
```bash
|
||||
git branch -m feature/wrapper custom-pi
|
||||
```
|
||||
|
||||
From now on, you always work on and deploy from `custom-pi`.
|
||||
|
||||
### How to Save Your Work (Pushing)
|
||||
When you write new custom code or edit features, just commit and push directly to `custom-pi` to save it:
|
||||
```bash
|
||||
git add .
|
||||
git commit -m "Added my new custom logic"
|
||||
git push origin custom-pi
|
||||
```
|
||||
|
||||
## How To Pull Official Updates (Merging)
|
||||
|
||||
When the official Sipeed developers release a new version (e.g., bugfixes or new capabilities), you want to pull those into your `custom-pi` branch so you get the newest features without losing your wrapper code.
|
||||
|
||||
Here is exactly how you do it, all from your `custom-pi` branch:
|
||||
*(Assuming you already added the original repo as an 'upstream' remote)*
|
||||
```bash
|
||||
# 1. Download the newest official code
|
||||
git fetch upstream
|
||||
|
||||
# 2. Smoothly merge the newest official features directly into your custom code
|
||||
git merge upstream/main
|
||||
```
|
||||
|
||||
### How Git Resolves This
|
||||
- **The Safe Merge:** If Sipeed changed completely different files than you did (e.g., they fixed a bug in `telegram.go`, but you modified `loop.go`), Git will automatically splice the files together perfectly silently. Your wrapper stays intact.
|
||||
- **The Merge Conflict:** If the developers modified the *exact same* lines of code in `loop.go` that you modified, Git will pause the merge and declare a "Merge Conflict."
|
||||
- You open `loop.go` in your IDE. You will see markers (`<<<<<<`) showing their new code alongside your custom code.
|
||||
- You manually edit that block to make sure your wrapper surrounds their new logic, save it, and run `git merge --continue`.
|
||||
|
||||
Since your custom wrapper is self-contained and small, adjusting the code during a conflict takes barely a minute!
|
||||
54
docs/custom/pi-build.md
Normal file
54
docs/custom/pi-build.md
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
# Raspberry Pi Build Guide
|
||||
|
||||
This guide details the step-by-step process for building a custom version of Picoclaw and transferring it to a Raspberry Pi Zero 2W running locally.
|
||||
|
||||
## Prerequisite: On Vulcan (Windows)
|
||||
|
||||
1. **Install Go**: Ensure Go is installed on your Windows machine (`https://go.dev/dl/`). Add it to your `PATH` or invoke it directly.
|
||||
2. **Clone repo**: Clone your custom fork of Picoclaw:
|
||||
```bash
|
||||
git clone https://github.com/<your-username>/picoclaw.git
|
||||
```
|
||||
3. **Modify code**: Make your custom logic changes (e.g., in `pkg/agent/metrics.go` and `pkg/agent/loop.go`).
|
||||
|
||||
## Step A: Compile for Raspberry Pi (ARM v7)
|
||||
|
||||
Since the Raspberry Pi Zero 2W is an ARM-based environment (running a 32-bit `armhf` OS usually), we use Go's powerful cross-compilation features natively on Windows.
|
||||
|
||||
Run this single command in PowerShell from the repository root:
|
||||
```powershell
|
||||
$env:CGO_ENABLED="0"; $env:GOOS="linux"; $env:GOARCH="arm"; $env:GOARM="7"; go build -o picoclaw-custom ./cmd/picoclaw
|
||||
```
|
||||
|
||||
This instructs the Go compiler to generate a standalone Linux executable tailored for the Pi's architecture.
|
||||
|
||||
## Step B: Transfer to Pi
|
||||
|
||||
Use `scp` (Secure Copy Protocol), which transfers files over an encrypted SSH connection.
|
||||
|
||||
```powershell
|
||||
scp picoclaw-custom tim@picoclaw.local:/tmp/
|
||||
```
|
||||
|
||||
*This copies your newly compiled `picoclaw-custom` file from Windows up to the `/tmp/` folder on your Pi.*
|
||||
|
||||
## Step C: Update the Raspberry Pi Service
|
||||
|
||||
Log into your Raspberry Pi terminal via SSH.
|
||||
|
||||
1. **Stop the current running service**:
|
||||
```bash
|
||||
sudo systemctl stop picoclaw
|
||||
```
|
||||
2. **Replace the old binary with the new custom one**:
|
||||
```bash
|
||||
sudo mv /tmp/picoclaw-custom /usr/local/bin/picoclaw
|
||||
```
|
||||
*(Ensure the binary is executable: `sudo chmod +x /usr/local/bin/picoclaw`)*
|
||||
3. **Restart the service to utilize the new brain**:
|
||||
```bash
|
||||
sudo systemctl start picoclaw
|
||||
```
|
||||
|
||||
### Why Cross-Compile?
|
||||
Cross-compiling on your powerful Windows desktop ("Vulcan") saves the Raspberry Pi Zero 2W from the massive heat, CPU stress, and time-consumption of downloading the Go SDK and compiling code with 512MB of RAM.
|
||||
|
|
@ -1589,10 +1589,37 @@ func (al *AgentLoop) runAgentLoop(
|
|||
}
|
||||
|
||||
if opts.SendResponse && result.finalContent != "" {
|
||||
var totalTokens, promptTokens, compTokens int
|
||||
if usage := ts.GetLastUsage(); usage != nil {
|
||||
totalTokens = usage.TotalTokens
|
||||
promptTokens = usage.PromptTokens
|
||||
compTokens = usage.CompletionTokens
|
||||
}
|
||||
|
||||
version := al.GetConfig().BuildInfo.Version
|
||||
if version == "" {
|
||||
version = "0.2.5"
|
||||
}
|
||||
|
||||
providerName := al.GetConfig().Agents.Defaults.Provider
|
||||
modelName := al.GetConfig().Agents.Defaults.GetModelName()
|
||||
|
||||
m := Metrics{
|
||||
Version: version,
|
||||
Agent: agent.ID,
|
||||
Route: providerName,
|
||||
Model: modelName,
|
||||
Complexity: calculateComplexity(promptTokens, compTokens),
|
||||
Tokens: totalTokens,
|
||||
Processing: time.Since(ts.startedAt),
|
||||
}
|
||||
|
||||
finalWrappedContent := WrapResponse(result.finalContent, m)
|
||||
|
||||
al.bus.PublishOutbound(ctx, bus.OutboundMessage{
|
||||
Channel: opts.Channel,
|
||||
ChatID: opts.ChatID,
|
||||
Content: result.finalContent,
|
||||
Content: finalWrappedContent,
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
|||
28
pkg/agent/metrics.go
Normal file
28
pkg/agent/metrics.go
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
package agent
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
)
|
||||
|
||||
type Metrics struct {
|
||||
Version string
|
||||
Agent string
|
||||
Route string
|
||||
Model string
|
||||
Complexity int
|
||||
Tokens int
|
||||
Processing time.Duration
|
||||
}
|
||||
|
||||
func WrapResponse(rawOutput string, m Metrics) string {
|
||||
header := fmt.Sprintf(
|
||||
"System: picoclaw-%s\nAgent: %s\nRoute: %s\nModel: %s\nComplexity: %d\nTokens: %d\nProcessing: %.1fs\n\n",
|
||||
m.Version, m.Agent, m.Route, m.Model, m.Complexity, m.Tokens, m.Processing.Seconds(),
|
||||
)
|
||||
return header + rawOutput
|
||||
}
|
||||
|
||||
func calculateComplexity(promptTokens, completionTokens int) int {
|
||||
return int(float64(promptTokens)*0.1 + float64(completionTokens)*0.5)
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue