fix(termux): Android binary support + argv fix
- Add Android/arm64 build target to .goreleaser.yaml Produces picoclaw_Android_arm64.tar.gz (PIE/ET_DYN binary built with GOOS=android, CGO_ENABLED=0, -ldflags '-s -w') - Fix Bionic linker argv[0] duplication in cmd/picoclaw/main.go Android's dynamic linker inserts the full binary path as an extra argv[1], shifting real arguments. Detect and strip the duplicate when runtime.GOOS == "android". - Simplify picoclaw-manager.sh to download-only Downloads the pre-compiled Android binary from GitHub Releases instead of building from source. No golang/git deps needed. Fix missing closing brace in uninstall_picoclaw(). - Update docs/TERMUX_INSTALL.md for Android binary download - Add -ldflags '-s -w' to all release builds (26MB -> 19MB)
This commit is contained in:
parent
0ede534b45
commit
3d274ce16d
5 changed files with 164 additions and 61 deletions
|
|
@ -11,6 +11,8 @@ builds:
|
||||||
- id: picoclaw
|
- id: picoclaw
|
||||||
env:
|
env:
|
||||||
- CGO_ENABLED=0
|
- CGO_ENABLED=0
|
||||||
|
ldflags:
|
||||||
|
- -s -w
|
||||||
goos:
|
goos:
|
||||||
- linux
|
- linux
|
||||||
- windows
|
- windows
|
||||||
|
|
@ -28,6 +30,19 @@ builds:
|
||||||
- goos: windows
|
- goos: windows
|
||||||
goarch: arm
|
goarch: arm
|
||||||
|
|
||||||
|
# Android/Termux requires PIE executables (ET_DYN) built with GOOS=android.
|
||||||
|
# Standard Linux binaries (ET_EXEC) are rejected by Android's kernel.
|
||||||
|
- id: picoclaw-android
|
||||||
|
env:
|
||||||
|
- CGO_ENABLED=0
|
||||||
|
ldflags:
|
||||||
|
- -s -w
|
||||||
|
goos:
|
||||||
|
- android
|
||||||
|
goarch:
|
||||||
|
- arm64
|
||||||
|
main: ./cmd/picoclaw
|
||||||
|
|
||||||
dockers_v2:
|
dockers_v2:
|
||||||
- id: picoclaw
|
- id: picoclaw
|
||||||
dockerfile: Dockerfile.goreleaser
|
dockerfile: Dockerfile.goreleaser
|
||||||
|
|
@ -45,7 +60,10 @@ dockers_v2:
|
||||||
- linux/riscv64
|
- linux/riscv64
|
||||||
|
|
||||||
archives:
|
archives:
|
||||||
- formats: [tar.gz]
|
- ids:
|
||||||
|
- picoclaw
|
||||||
|
- picoclaw-android
|
||||||
|
formats: [tar.gz]
|
||||||
# this name template makes the OS and Arch compatible with the results of `uname`.
|
# this name template makes the OS and Arch compatible with the results of `uname`.
|
||||||
name_template: >-
|
name_template: >-
|
||||||
{{ .ProjectName }}_
|
{{ .ProjectName }}_
|
||||||
|
|
|
||||||
|
|
@ -9,8 +9,10 @@ BLUE='\033[0;34m'
|
||||||
YELLOW='\033[1;33m'
|
YELLOW='\033[1;33m'
|
||||||
NC='\033[0m' # No Color
|
NC='\033[0m' # No Color
|
||||||
|
|
||||||
|
GITHUB_REPO="sipeed/picoclaw"
|
||||||
CONFIG_FILE="$HOME/.picoclaw/config.json"
|
CONFIG_FILE="$HOME/.picoclaw/config.json"
|
||||||
REPO_DIR="$HOME/.picoclaw-repo"
|
DATA_DIR="$HOME/.picoclaw"
|
||||||
|
LOG_FILE="$DATA_DIR/picoclaw.log"
|
||||||
BIN_PATH="$PREFIX/bin/picoclaw"
|
BIN_PATH="$PREFIX/bin/picoclaw"
|
||||||
|
|
||||||
show_header() {
|
show_header() {
|
||||||
|
|
@ -29,9 +31,15 @@ EOF
|
||||||
echo -e "==========================================${NC}"
|
echo -e "==========================================${NC}"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
is_android() {
|
||||||
|
[[ "$(uname -o 2>/dev/null)" == "Android" ]] || [ -n "$ANDROID_ROOT" ] || [ -d "/data/data/com.termux" ]
|
||||||
|
}
|
||||||
|
|
||||||
check_dependencies() {
|
check_dependencies() {
|
||||||
echo -e "${YELLOW}[*] Checking dependencies...${NC}"
|
echo -e "${YELLOW}[*] Checking dependencies...${NC}"
|
||||||
deps=("golang" "git" "make" "jq" "tmux")
|
|
||||||
|
deps=("curl" "jq" "tmux" "tar")
|
||||||
|
|
||||||
to_install=()
|
to_install=()
|
||||||
for dep in "${deps[@]}"; do
|
for dep in "${deps[@]}"; do
|
||||||
if ! command -v "$dep" &> /dev/null; then
|
if ! command -v "$dep" &> /dev/null; then
|
||||||
|
|
@ -47,34 +55,100 @@ check_dependencies() {
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
detect_arch() {
|
||||||
|
local arch
|
||||||
|
arch=$(uname -m)
|
||||||
|
case "$arch" in
|
||||||
|
aarch64|arm64) echo "arm64" ;;
|
||||||
|
armv7l|armv6l) echo "armv6" ;;
|
||||||
|
x86_64|amd64) echo "x86_64" ;;
|
||||||
|
*)
|
||||||
|
echo -e "${RED}[!] Unsupported architecture: $arch${NC}" >&2
|
||||||
|
return 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
get_latest_version() {
|
||||||
|
curl -s "https://api.github.com/repos/${GITHUB_REPO}/releases/latest" | jq -r '.tag_name'
|
||||||
|
}
|
||||||
|
|
||||||
|
# Download prebuilt binary from GitHub Releases
|
||||||
|
install_from_release() {
|
||||||
|
local version="$1"
|
||||||
|
local arch="$2"
|
||||||
|
|
||||||
|
# Android/Termux uses a dedicated Android binary (GOOS=android, PIE).
|
||||||
|
# Standard Linux uses the regular Linux binary.
|
||||||
|
local os_name="Linux"
|
||||||
|
if is_android; then
|
||||||
|
os_name="Android"
|
||||||
|
fi
|
||||||
|
|
||||||
|
local filename="picoclaw_${os_name}_${arch}.tar.gz"
|
||||||
|
local url="https://github.com/${GITHUB_REPO}/releases/download/${version}/${filename}"
|
||||||
|
local tmpdir
|
||||||
|
tmpdir=$(mktemp -d -p "${TMPDIR:-/tmp}")
|
||||||
|
|
||||||
|
echo -e "${YELLOW}[*] Downloading ${filename}...${NC}"
|
||||||
|
if ! curl -fSL --progress-bar "$url" -o "${tmpdir}/${filename}"; then
|
||||||
|
echo -e "${RED}[!] Download failed. URL: ${url}${NC}"
|
||||||
|
rm -rf "$tmpdir"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo -e "${YELLOW}[*] Extracting binary...${NC}"
|
||||||
|
tar -xzf "${tmpdir}/${filename}" -C "$tmpdir"
|
||||||
|
|
||||||
|
if [ ! -f "${tmpdir}/picoclaw" ]; then
|
||||||
|
echo -e "${RED}[!] Binary not found in archive.${NC}"
|
||||||
|
rm -rf "$tmpdir"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
mkdir -p "$(dirname "$BIN_PATH")"
|
||||||
|
cp "${tmpdir}/picoclaw" "$BIN_PATH"
|
||||||
|
chmod +x "$BIN_PATH"
|
||||||
|
rm -rf "$tmpdir"
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
install_picoclaw() {
|
install_picoclaw() {
|
||||||
check_dependencies
|
check_dependencies
|
||||||
|
|
||||||
echo -e "${YELLOW}[*] Cloning repository...${NC}"
|
echo -e "${YELLOW}[*] Detecting architecture...${NC}"
|
||||||
if [ -d "$REPO_DIR" ]; then
|
local arch
|
||||||
cd "$REPO_DIR" && git pull
|
arch=$(detect_arch)
|
||||||
else
|
if [ $? -ne 0 ] || [ -z "$arch" ]; then
|
||||||
git clone https://github.com/sipeed/picoclaw.git "$REPO_DIR"
|
echo -e "${RED}[!] Could not detect architecture. Aborting.${NC}"
|
||||||
cd "$REPO_DIR"
|
read -p "Press Enter to return to menu..."
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
echo -e "${GREEN}[✓] Architecture: $arch${NC}"
|
||||||
|
|
||||||
|
echo -e "${YELLOW}[*] Fetching latest release...${NC}"
|
||||||
|
local version
|
||||||
|
version=$(get_latest_version)
|
||||||
|
if [ -z "$version" ] || [ "$version" = "null" ]; then
|
||||||
|
echo -e "${RED}[!] Could not fetch latest version. Check your internet connection.${NC}"
|
||||||
|
read -p "Press Enter to return to menu..."
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
echo -e "${GREEN}[✓] Latest version: $version${NC}"
|
||||||
|
|
||||||
|
install_from_release "$version" "$arch"
|
||||||
|
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
echo -e "${RED}[!] Installation failed.${NC}"
|
||||||
|
read -p "Press Enter to return to menu..."
|
||||||
|
return
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo -e "${YELLOW}[*] Building PicoClaw...${NC}"
|
|
||||||
# Adjust Go version
|
|
||||||
GO_VERSION=$(go version | awk '{print $3}' | sed 's/go//' | cut -d. -f1,2,3)
|
|
||||||
sed -i "s/go 1.25.7/go $GO_VERSION/" go.mod
|
|
||||||
|
|
||||||
export CGO_ENABLED=0
|
|
||||||
make deps
|
|
||||||
make build
|
|
||||||
|
|
||||||
echo -e "${YELLOW}[*] Installing to bin...${NC}"
|
|
||||||
cp build/picoclaw-linux-arm64 "$BIN_PATH"
|
|
||||||
chmod +x "$BIN_PATH"
|
|
||||||
|
|
||||||
if ! command -v picoclaw &> /dev/null; then
|
if ! command -v picoclaw &> /dev/null; then
|
||||||
echo -e "${RED}[!] Installation failed. Bin not in PATH?${NC}"
|
echo -e "${RED}[!] Installation failed. Is $PREFIX/bin in your PATH?${NC}"
|
||||||
else
|
else
|
||||||
echo -e "${GREEN}[✓] PicoClaw installed successfully!${NC}"
|
echo -e "${GREEN}[✓] PicoClaw ${version} installed successfully!${NC}"
|
||||||
|
echo -e "${YELLOW}[*] Running initial setup...${NC}"
|
||||||
picoclaw onboard
|
picoclaw onboard
|
||||||
fi
|
fi
|
||||||
read -p "Press Enter to return to menu..."
|
read -p "Press Enter to return to menu..."
|
||||||
|
|
@ -121,7 +195,8 @@ manage_service() {
|
||||||
if tmux has-session -t picoclaw 2>/dev/null; then
|
if tmux has-session -t picoclaw 2>/dev/null; then
|
||||||
echo -e "${YELLOW}[!] Session 'picoclaw' already exists.${NC}"
|
echo -e "${YELLOW}[!] Session 'picoclaw' already exists.${NC}"
|
||||||
else
|
else
|
||||||
tmux new-session -d -s picoclaw "picoclaw gateway | tee $REPO_DIR/picoclaw.log"
|
mkdir -p "$DATA_DIR"
|
||||||
|
tmux new-session -d -s picoclaw "picoclaw gateway 2>&1 | tee $LOG_FILE"
|
||||||
echo -e "${GREEN}[✓] Gateway started in tmux session 'picoclaw'.${NC}"
|
echo -e "${GREEN}[✓] Gateway started in tmux session 'picoclaw'.${NC}"
|
||||||
fi
|
fi
|
||||||
;;
|
;;
|
||||||
|
|
@ -134,11 +209,16 @@ manage_service() {
|
||||||
pkill -9 picoclaw
|
pkill -9 picoclaw
|
||||||
tmux kill-session -t picoclaw 2>/dev/null
|
tmux kill-session -t picoclaw 2>/dev/null
|
||||||
sleep 1
|
sleep 1
|
||||||
tmux new-session -d -s picoclaw "picoclaw gateway | tee $REPO_DIR/picoclaw.log"
|
mkdir -p "$DATA_DIR"
|
||||||
|
tmux new-session -d -s picoclaw "picoclaw gateway 2>&1 | tee $LOG_FILE"
|
||||||
echo -e "${GREEN}[✓] Gateway restarted.${NC}"
|
echo -e "${GREEN}[✓] Gateway restarted.${NC}"
|
||||||
;;
|
;;
|
||||||
4)
|
4)
|
||||||
tail -f "$REPO_DIR/picoclaw.log"
|
if [ -f "$LOG_FILE" ]; then
|
||||||
|
tail -f "$LOG_FILE"
|
||||||
|
else
|
||||||
|
echo -e "${YELLOW}[!] No log file found. Start the gateway first.${NC}"
|
||||||
|
fi
|
||||||
;;
|
;;
|
||||||
*) return ;;
|
*) return ;;
|
||||||
esac
|
esac
|
||||||
|
|
@ -150,12 +230,12 @@ uninstall_picoclaw() {
|
||||||
if [[ "$confirm" == "y" || "$confirm" == "Y" ]]; then
|
if [[ "$confirm" == "y" || "$confirm" == "Y" ]]; then
|
||||||
pkill -9 picoclaw
|
pkill -9 picoclaw
|
||||||
tmux kill-session -t picoclaw 2>/dev/null
|
tmux kill-session -t picoclaw 2>/dev/null
|
||||||
rm "$BIN_PATH"
|
rm -f "$BIN_PATH"
|
||||||
rm -rf "$REPO_DIR"
|
rm -rf "$DATA_DIR"
|
||||||
rm -rf "$HOME/.picoclaw"
|
|
||||||
echo -e "${GREEN}[✓] PicoClaw uninstalled.${NC}"
|
echo -e "${GREEN}[✓] PicoClaw uninstalled.${NC}"
|
||||||
fi
|
fi
|
||||||
read -p "Press Enter to return to menu..."
|
read -p "Press Enter to return to menu..."
|
||||||
|
}
|
||||||
|
|
||||||
network_diagnostics() {
|
network_diagnostics() {
|
||||||
echo -e "${BLUE}--- Network Diagnostics ---${NC}"
|
echo -e "${BLUE}--- Network Diagnostics ---${NC}"
|
||||||
|
|
|
||||||
|
|
@ -120,6 +120,17 @@ func copyDirectory(src, dst string) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
// Android's Bionic linker duplicates argv[0] when loading PIE executables,
|
||||||
|
// inserting the full binary path as argv[1] and shifting real arguments.
|
||||||
|
// For example: argv = ["picoclaw", "/data/.../bin/picoclaw", "onboard"]
|
||||||
|
// Detect this by checking if argv[1] is a path whose base name matches
|
||||||
|
// argv[0] (the program name).
|
||||||
|
if len(os.Args) >= 2 && runtime.GOOS == "android" {
|
||||||
|
if filepath.Base(os.Args[1]) == filepath.Base(os.Args[0]) && strings.Contains(os.Args[1], "/") {
|
||||||
|
os.Args = append(os.Args[:1], os.Args[2:]...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if len(os.Args) < 2 {
|
if len(os.Args) < 2 {
|
||||||
printHelp()
|
printHelp()
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
|
|
|
||||||
|
|
@ -26,31 +26,25 @@ If you prefer to set up everything manually, follow these steps:
|
||||||
Open Termux and install the necessary packages:
|
Open Termux and install the necessary packages:
|
||||||
```bash
|
```bash
|
||||||
pkg update && pkg upgrade
|
pkg update && pkg upgrade
|
||||||
pkg install -y golang git make jq tmux
|
pkg install -y curl jq tmux
|
||||||
```
|
```
|
||||||
|
|
||||||
## 2. Clone and Prepare PicoClaw
|
## 2. Download Pre-compiled Binary
|
||||||
```bash
|
PicoClaw provides pre-compiled Android binaries for every release — no build tools needed.
|
||||||
git clone https://github.com/sipeed/picoclaw.git ~/.picoclaw-repo
|
|
||||||
cd ~/.picoclaw-repo
|
|
||||||
```
|
|
||||||
|
|
||||||
### Fix Go Version Requirement
|
|
||||||
Termux might have a slightly older version of Go than required by `go.mod`. Use this command to automatically adjust the requirement to match your installed Go version:
|
|
||||||
```bash
|
```bash
|
||||||
sed -i "s/go 1.25.7/go $(go version | awk '{print $3}' | sed 's/go//' | cut -d. -f1,2,3)/" go.mod
|
# Fetch latest version tag
|
||||||
```
|
VERSION=$(curl -s https://api.github.com/repos/sipeed/picoclaw/releases/latest | jq -r '.tag_name')
|
||||||
|
echo "Installing PicoClaw $VERSION..."
|
||||||
|
|
||||||
### Build and Install PicoClaw
|
# Download the Android arm64 binary (built with GOOS=android for Termux compatibility)
|
||||||
Build the project with CGO disabled for maximum compatibility across different Android architectures, then move it to your system PATH:
|
curl -fSL "https://github.com/sipeed/picoclaw/releases/download/${VERSION}/picoclaw_Android_arm64.tar.gz" -o /tmp/picoclaw.tar.gz
|
||||||
```bash
|
tar -xzf /tmp/picoclaw.tar.gz -C /tmp picoclaw
|
||||||
export CGO_ENABLED=0
|
|
||||||
make deps
|
|
||||||
make build
|
|
||||||
|
|
||||||
# Install to Termux bin directory
|
# Install to Termux bin directory
|
||||||
cp build/picoclaw-linux-arm64 $PREFIX/bin/picoclaw
|
cp /tmp/picoclaw $PREFIX/bin/picoclaw
|
||||||
chmod +x $PREFIX/bin/picoclaw
|
chmod +x $PREFIX/bin/picoclaw
|
||||||
|
rm /tmp/picoclaw.tar.gz /tmp/picoclaw
|
||||||
```
|
```
|
||||||
|
|
||||||
Now you can run `picoclaw` from anywhere!
|
Now you can run `picoclaw` from anywhere!
|
||||||
|
|
|
||||||
|
|
@ -51,7 +51,7 @@ func TestRecordLastChannel(t *testing.T) {
|
||||||
// Create agent loop
|
// Create agent loop
|
||||||
msgBus := bus.NewMessageBus()
|
msgBus := bus.NewMessageBus()
|
||||||
provider := &mockProvider{}
|
provider := &mockProvider{}
|
||||||
al := NewAgentLoop(cfg, msgBus, provider)
|
al := NewAgentLoop(cfg, msgBus, provider, "")
|
||||||
|
|
||||||
// Test RecordLastChannel
|
// Test RecordLastChannel
|
||||||
testChannel := "test-channel"
|
testChannel := "test-channel"
|
||||||
|
|
@ -67,7 +67,7 @@ func TestRecordLastChannel(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify persistence by creating a new agent loop
|
// Verify persistence by creating a new agent loop
|
||||||
al2 := NewAgentLoop(cfg, msgBus, provider)
|
al2 := NewAgentLoop(cfg, msgBus, provider, "")
|
||||||
if al2.state.GetLastChannel() != testChannel {
|
if al2.state.GetLastChannel() != testChannel {
|
||||||
t.Errorf("Expected persistent channel '%s', got '%s'", testChannel, al2.state.GetLastChannel())
|
t.Errorf("Expected persistent channel '%s', got '%s'", testChannel, al2.state.GetLastChannel())
|
||||||
}
|
}
|
||||||
|
|
@ -96,7 +96,7 @@ func TestRecordLastChatID(t *testing.T) {
|
||||||
// Create agent loop
|
// Create agent loop
|
||||||
msgBus := bus.NewMessageBus()
|
msgBus := bus.NewMessageBus()
|
||||||
provider := &mockProvider{}
|
provider := &mockProvider{}
|
||||||
al := NewAgentLoop(cfg, msgBus, provider)
|
al := NewAgentLoop(cfg, msgBus, provider, "")
|
||||||
|
|
||||||
// Test RecordLastChatID
|
// Test RecordLastChatID
|
||||||
testChatID := "test-chat-id-123"
|
testChatID := "test-chat-id-123"
|
||||||
|
|
@ -112,7 +112,7 @@ func TestRecordLastChatID(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify persistence by creating a new agent loop
|
// Verify persistence by creating a new agent loop
|
||||||
al2 := NewAgentLoop(cfg, msgBus, provider)
|
al2 := NewAgentLoop(cfg, msgBus, provider, "")
|
||||||
if al2.state.GetLastChatID() != testChatID {
|
if al2.state.GetLastChatID() != testChatID {
|
||||||
t.Errorf("Expected persistent chat ID '%s', got '%s'", testChatID, al2.state.GetLastChatID())
|
t.Errorf("Expected persistent chat ID '%s', got '%s'", testChatID, al2.state.GetLastChatID())
|
||||||
}
|
}
|
||||||
|
|
@ -141,7 +141,7 @@ func TestNewAgentLoop_StateInitialized(t *testing.T) {
|
||||||
// Create agent loop
|
// Create agent loop
|
||||||
msgBus := bus.NewMessageBus()
|
msgBus := bus.NewMessageBus()
|
||||||
provider := &mockProvider{}
|
provider := &mockProvider{}
|
||||||
al := NewAgentLoop(cfg, msgBus, provider)
|
al := NewAgentLoop(cfg, msgBus, provider, "")
|
||||||
|
|
||||||
// Verify state manager is initialized
|
// Verify state manager is initialized
|
||||||
if al.state == nil {
|
if al.state == nil {
|
||||||
|
|
@ -176,7 +176,7 @@ func TestToolRegistry_ToolRegistration(t *testing.T) {
|
||||||
|
|
||||||
msgBus := bus.NewMessageBus()
|
msgBus := bus.NewMessageBus()
|
||||||
provider := &mockProvider{}
|
provider := &mockProvider{}
|
||||||
al := NewAgentLoop(cfg, msgBus, provider)
|
al := NewAgentLoop(cfg, msgBus, provider, "")
|
||||||
|
|
||||||
// Register a custom tool
|
// Register a custom tool
|
||||||
customTool := &mockCustomTool{}
|
customTool := &mockCustomTool{}
|
||||||
|
|
@ -222,7 +222,7 @@ func TestToolContext_Updates(t *testing.T) {
|
||||||
|
|
||||||
msgBus := bus.NewMessageBus()
|
msgBus := bus.NewMessageBus()
|
||||||
provider := &simpleMockProvider{response: "OK"}
|
provider := &simpleMockProvider{response: "OK"}
|
||||||
_ = NewAgentLoop(cfg, msgBus, provider)
|
_ = NewAgentLoop(cfg, msgBus, provider, "")
|
||||||
|
|
||||||
// Verify that ContextualTool interface is defined and can be implemented
|
// Verify that ContextualTool interface is defined and can be implemented
|
||||||
// This test validates the interface contract exists
|
// This test validates the interface contract exists
|
||||||
|
|
@ -253,7 +253,7 @@ func TestToolRegistry_GetDefinitions(t *testing.T) {
|
||||||
|
|
||||||
msgBus := bus.NewMessageBus()
|
msgBus := bus.NewMessageBus()
|
||||||
provider := &mockProvider{}
|
provider := &mockProvider{}
|
||||||
al := NewAgentLoop(cfg, msgBus, provider)
|
al := NewAgentLoop(cfg, msgBus, provider, "")
|
||||||
|
|
||||||
// Register a test tool and verify it shows up in startup info
|
// Register a test tool and verify it shows up in startup info
|
||||||
testTool := &mockCustomTool{}
|
testTool := &mockCustomTool{}
|
||||||
|
|
@ -297,7 +297,7 @@ func TestAgentLoop_GetStartupInfo(t *testing.T) {
|
||||||
|
|
||||||
msgBus := bus.NewMessageBus()
|
msgBus := bus.NewMessageBus()
|
||||||
provider := &mockProvider{}
|
provider := &mockProvider{}
|
||||||
al := NewAgentLoop(cfg, msgBus, provider)
|
al := NewAgentLoop(cfg, msgBus, provider, "")
|
||||||
|
|
||||||
info := al.GetStartupInfo()
|
info := al.GetStartupInfo()
|
||||||
|
|
||||||
|
|
@ -344,7 +344,7 @@ func TestAgentLoop_Stop(t *testing.T) {
|
||||||
|
|
||||||
msgBus := bus.NewMessageBus()
|
msgBus := bus.NewMessageBus()
|
||||||
provider := &mockProvider{}
|
provider := &mockProvider{}
|
||||||
al := NewAgentLoop(cfg, msgBus, provider)
|
al := NewAgentLoop(cfg, msgBus, provider, "")
|
||||||
|
|
||||||
// Note: running is only set to true when Run() is called
|
// Note: running is only set to true when Run() is called
|
||||||
// We can't test that without starting the event loop
|
// We can't test that without starting the event loop
|
||||||
|
|
@ -466,7 +466,7 @@ func TestToolResult_SilentToolDoesNotSendUserMessage(t *testing.T) {
|
||||||
|
|
||||||
msgBus := bus.NewMessageBus()
|
msgBus := bus.NewMessageBus()
|
||||||
provider := &simpleMockProvider{response: "File operation complete"}
|
provider := &simpleMockProvider{response: "File operation complete"}
|
||||||
al := NewAgentLoop(cfg, msgBus, provider)
|
al := NewAgentLoop(cfg, msgBus, provider, "")
|
||||||
helper := testHelper{al: al}
|
helper := testHelper{al: al}
|
||||||
|
|
||||||
// ReadFileTool returns SilentResult, which should not send user message
|
// ReadFileTool returns SilentResult, which should not send user message
|
||||||
|
|
@ -508,7 +508,7 @@ func TestToolResult_UserFacingToolDoesSendMessage(t *testing.T) {
|
||||||
|
|
||||||
msgBus := bus.NewMessageBus()
|
msgBus := bus.NewMessageBus()
|
||||||
provider := &simpleMockProvider{response: "Command output: hello world"}
|
provider := &simpleMockProvider{response: "Command output: hello world"}
|
||||||
al := NewAgentLoop(cfg, msgBus, provider)
|
al := NewAgentLoop(cfg, msgBus, provider, "")
|
||||||
helper := testHelper{al: al}
|
helper := testHelper{al: al}
|
||||||
|
|
||||||
// ExecTool returns UserResult, which should send user message
|
// ExecTool returns UserResult, which should send user message
|
||||||
|
|
@ -581,7 +581,7 @@ func TestAgentLoop_ContextExhaustionRetry(t *testing.T) {
|
||||||
successResp: "Recovered from context error",
|
successResp: "Recovered from context error",
|
||||||
}
|
}
|
||||||
|
|
||||||
al := NewAgentLoop(cfg, msgBus, provider)
|
al := NewAgentLoop(cfg, msgBus, provider, "")
|
||||||
|
|
||||||
// Inject some history to simulate a full context
|
// Inject some history to simulate a full context
|
||||||
sessionKey := "test-session-context"
|
sessionKey := "test-session-context"
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue