feat(cli): prefer jane-ai runtime naming\n\n- Rename CLI and launcher-facing help text from picoclaw to Jane AI across root, gateway, onboard, status, migrate, and version commands\n- Make launcher startup and process detection prefer the jane-ai binary while keeping picoclaw fallback support\n- Update container entrypoint and backend launcher usage text to default to jane-ai paths and binary names\n- Add runtime binary resolution in pkg/runtimepaths for shared jane-ai/picoclaw fallback behavior\n- Tests passed for pkg/runtimepaths and pkg/auth; targeted search confirmed the edited runtime strings no longer use picoclaw
This commit is contained in:
parent
dd69cbeb16
commit
da25deeae0
22 changed files with 104 additions and 88 deletions
|
|
@ -12,6 +12,7 @@ import (
|
|||
|
||||
configstore "jane/cmd/picoclaw-launcher-tui/internal/config"
|
||||
picoclawconfig "jane/pkg/config"
|
||||
"jane/pkg/runtimepaths"
|
||||
)
|
||||
|
||||
type appState struct {
|
||||
|
|
@ -204,7 +205,7 @@ func refreshMainMenu(menu *Menu, s *appState) {
|
|||
},
|
||||
{
|
||||
Label: "Start Talk",
|
||||
Description: "Open picoclaw agent in terminal",
|
||||
Description: "Open Jane AI agent in terminal",
|
||||
Action: func() {
|
||||
s.requestStartTalk()
|
||||
},
|
||||
|
|
@ -359,7 +360,7 @@ func (s *appState) startTalk() {
|
|||
return
|
||||
}
|
||||
s.app.Suspend(func() {
|
||||
cmd := exec.Command("picoclaw", "agent")
|
||||
cmd := exec.Command(runtimepaths.BinaryPath(), "agent")
|
||||
cmd.Stdin = os.Stdin
|
||||
cmd.Stdout = os.Stdout
|
||||
cmd.Stderr = os.Stderr
|
||||
|
|
@ -380,7 +381,7 @@ func (s *appState) startGateway() {
|
|||
return
|
||||
}
|
||||
_ = stopGatewayProcess()
|
||||
cmd := exec.Command("picoclaw", "gateway")
|
||||
cmd := exec.Command(runtimepaths.BinaryPath(), "gateway")
|
||||
logFile, err := os.OpenFile(s.logPath, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0o644)
|
||||
if err != nil {
|
||||
s.showMessage("Gateway failed", err.Error())
|
||||
|
|
|
|||
|
|
@ -8,11 +8,11 @@ import "os/exec"
|
|||
var execCommand = exec.Command
|
||||
|
||||
func isGatewayProcessRunning() bool {
|
||||
cmd := execCommand("sh", "-c", "pgrep -f 'picoclaw\\s+gateway' >/dev/null 2>&1")
|
||||
cmd := execCommand("sh", "-c", "pgrep -f '(jane-ai|picoclaw)\\s+gateway' >/dev/null 2>&1")
|
||||
return cmd.Run() == nil
|
||||
}
|
||||
|
||||
func stopGatewayProcess() error {
|
||||
cmd := execCommand("sh", "-c", "pkill -f 'picoclaw\\s+gateway' >/dev/null 2>&1")
|
||||
cmd := execCommand("sh", "-c", "pkill -f '(jane-ai|picoclaw)\\s+gateway' >/dev/null 2>&1")
|
||||
return cmd.Run()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,11 +8,11 @@ import "os/exec"
|
|||
var execCommand = exec.Command
|
||||
|
||||
func isGatewayProcessRunning() bool {
|
||||
cmd := execCommand("tasklist", "/FI", "IMAGENAME eq picoclaw.exe")
|
||||
cmd := execCommand("cmd", "/C", `tasklist /FI "IMAGENAME eq jane-ai.exe" | findstr /I /C:"jane-ai.exe" >NUL || tasklist /FI "IMAGENAME eq picoclaw.exe" | findstr /I /C:"picoclaw.exe" >NUL`)
|
||||
return cmd.Run() == nil
|
||||
}
|
||||
|
||||
func stopGatewayProcess() error {
|
||||
cmd := execCommand("taskkill", "/F", "/IM", "picoclaw.exe")
|
||||
cmd := execCommand("cmd", "/C", `taskkill /F /IM jane-ai.exe >NUL 2>&1 || taskkill /F /IM picoclaw.exe >NUL 2>&1`)
|
||||
return cmd.Run()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -53,10 +53,10 @@ func TestIsGatewayProcessRunning(t *testing.T) {
|
|||
if got != tt.wantResult {
|
||||
t.Errorf("isGatewayProcessRunning() = %v, want %v", got, tt.wantResult)
|
||||
}
|
||||
if gotName != "tasklist" {
|
||||
t.Errorf("expected command name tasklist, got %s", gotName)
|
||||
if gotName != "cmd" {
|
||||
t.Errorf("expected command name cmd, got %s", gotName)
|
||||
}
|
||||
expectedArgs := []string{"/FI", "IMAGENAME eq picoclaw.exe"}
|
||||
expectedArgs := []string{"/C", `tasklist /FI "IMAGENAME eq jane-ai.exe" | findstr /I /C:"jane-ai.exe" >NUL || tasklist /FI "IMAGENAME eq picoclaw.exe" | findstr /I /C:"picoclaw.exe" >NUL`}
|
||||
if !reflect.DeepEqual(gotArgs, expectedArgs) {
|
||||
t.Errorf("expected args %v, got %v", expectedArgs, gotArgs)
|
||||
}
|
||||
|
|
@ -106,10 +106,10 @@ func TestStopGatewayProcess(t *testing.T) {
|
|||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("stopGatewayProcess() error = %v, wantErr %v", err, tt.wantErr)
|
||||
}
|
||||
if gotName != "taskkill" {
|
||||
t.Errorf("expected command name taskkill, got %s", gotName)
|
||||
if gotName != "cmd" {
|
||||
t.Errorf("expected command name cmd, got %s", gotName)
|
||||
}
|
||||
expectedArgs := []string{"/F", "/IM", "picoclaw.exe"}
|
||||
expectedArgs := []string{"/C", `taskkill /F /IM jane-ai.exe >NUL 2>&1 || taskkill /F /IM picoclaw.exe >NUL 2>&1`}
|
||||
if !reflect.DeepEqual(gotArgs, expectedArgs) {
|
||||
t.Errorf("expected args %v, got %v", expectedArgs, gotArgs)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -162,7 +162,7 @@ func authLoginGoogleAntigravity() error {
|
|||
|
||||
fmt.Println("\n✓ Google Antigravity login successful!")
|
||||
fmt.Println("Default model set to: gemini-flash")
|
||||
fmt.Println("Try it: picoclaw agent -m \"Hello world\"")
|
||||
fmt.Println("Try it: jane-ai agent -m \"Hello world\"")
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
@ -412,7 +412,7 @@ func authStatusCmd() error {
|
|||
|
||||
if len(store.Credentials) == 0 {
|
||||
fmt.Println("No authenticated providers.")
|
||||
fmt.Println("Run: picoclaw auth login --provider <name>")
|
||||
fmt.Println("Run: jane-ai auth login --provider <name>")
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
@ -460,7 +460,7 @@ func authModelsCmd() error {
|
|||
cred, err := auth.GetCredential("google-antigravity")
|
||||
if err != nil || cred == nil {
|
||||
return fmt.Errorf(
|
||||
"not logged in to Google Antigravity.\nrun: picoclaw auth login --provider google-antigravity",
|
||||
"not logged in to Google Antigravity.\nrun: jane-ai auth login --provider google-antigravity",
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ func NewGatewayCommand() *cobra.Command {
|
|||
cmd := &cobra.Command{
|
||||
Use: "gateway",
|
||||
Aliases: []string{"g"},
|
||||
Short: "Start picoclaw gateway",
|
||||
Short: "Start the Jane AI gateway",
|
||||
Args: cobra.NoArgs,
|
||||
PreRunE: func(_ *cobra.Command, _ []string) error {
|
||||
if noTruncate && !debug {
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ func TestNewGatewayCommand(t *testing.T) {
|
|||
require.NotNil(t, cmd)
|
||||
|
||||
assert.Equal(t, "gateway", cmd.Use)
|
||||
assert.Equal(t, "Start picoclaw gateway", cmd.Short)
|
||||
assert.Equal(t, "Start the Jane AI gateway", cmd.Short)
|
||||
|
||||
assert.Len(t, cmd.Aliases, 1)
|
||||
assert.True(t, cmd.HasAlias("g"))
|
||||
|
|
|
|||
|
|
@ -11,13 +11,13 @@ func NewMigrateCommand() *cobra.Command {
|
|||
|
||||
cmd := &cobra.Command{
|
||||
Use: "migrate",
|
||||
Short: "Migrate from xxxclaw(openclaw, etc.) to picoclaw",
|
||||
Short: "Migrate from xxxclaw(openclaw, etc.) to Jane AI",
|
||||
Args: cobra.NoArgs,
|
||||
Example: ` picoclaw migrate
|
||||
picoclaw migrate --from openclaw
|
||||
picoclaw migrate --dry-run
|
||||
picoclaw migrate --refresh
|
||||
picoclaw migrate --force`,
|
||||
Example: ` jane-ai migrate
|
||||
jane-ai migrate --from openclaw
|
||||
jane-ai migrate --dry-run
|
||||
jane-ai migrate --refresh
|
||||
jane-ai migrate --force`,
|
||||
RunE: func(cmd *cobra.Command, _ []string) error {
|
||||
m := migrate.NewMigrateInstance(opts)
|
||||
result, err := m.Run(opts)
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ func TestNewMigrateCommand(t *testing.T) {
|
|||
require.NotNil(t, cmd)
|
||||
|
||||
assert.Equal(t, "migrate", cmd.Use)
|
||||
assert.Equal(t, "Migrate from xxxclaw(openclaw, etc.) to picoclaw", cmd.Short)
|
||||
assert.Equal(t, "Migrate from xxxclaw(openclaw, etc.) to Jane AI", cmd.Short)
|
||||
|
||||
assert.Len(t, cmd.Aliases, 0)
|
||||
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ func NewOnboardCommand() *cobra.Command {
|
|||
cmd := &cobra.Command{
|
||||
Use: "onboard",
|
||||
Aliases: []string{"o"},
|
||||
Short: "Initialize picoclaw configuration and workspace",
|
||||
Short: "Initialize Jane AI configuration and workspace",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
onboard()
|
||||
},
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ func TestNewOnboardCommand(t *testing.T) {
|
|||
require.NotNil(t, cmd)
|
||||
|
||||
assert.Equal(t, "onboard", cmd.Use)
|
||||
assert.Equal(t, "Initialize picoclaw configuration and workspace", cmd.Short)
|
||||
assert.Equal(t, "Initialize Jane AI configuration and workspace", cmd.Short)
|
||||
|
||||
assert.Len(t, cmd.Aliases, 1)
|
||||
assert.True(t, cmd.HasAlias("o"))
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ func onboard() {
|
|||
workspace := cfg.WorkspacePath()
|
||||
createWorkspaceTemplates(workspace)
|
||||
|
||||
fmt.Printf("%s picoclaw is ready!\n", internal.Logo)
|
||||
fmt.Printf("%s Jane AI is ready!\n", internal.Logo)
|
||||
fmt.Println("\nNext steps:")
|
||||
fmt.Println(" 1. Add your API key to", configPath)
|
||||
fmt.Println("")
|
||||
|
|
@ -43,7 +43,7 @@ func onboard() {
|
|||
fmt.Println("")
|
||||
fmt.Println(" See README.md for 17+ supported providers.")
|
||||
fmt.Println("")
|
||||
fmt.Println(" 2. Chat: picoclaw agent -m \"Hello!\"")
|
||||
fmt.Println(" 2. Chat: jane-ai agent -m \"Hello!\"")
|
||||
}
|
||||
|
||||
func createWorkspaceTemplates(workspace string) {
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ func NewStatusCommand() *cobra.Command {
|
|||
cmd := &cobra.Command{
|
||||
Use: "status",
|
||||
Aliases: []string{"s"},
|
||||
Short: "Show picoclaw status",
|
||||
Short: "Show Jane AI status",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
statusCmd()
|
||||
},
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ func TestNewStatusCommand(t *testing.T) {
|
|||
assert.Len(t, cmd.Aliases, 1)
|
||||
assert.True(t, cmd.HasAlias("s"))
|
||||
|
||||
assert.Equal(t, "Show picoclaw status", cmd.Short)
|
||||
assert.Equal(t, "Show Jane AI status", cmd.Short)
|
||||
|
||||
assert.False(t, cmd.HasSubCommands())
|
||||
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ func statusCmd() {
|
|||
|
||||
configPath := internal.GetConfigPath()
|
||||
|
||||
fmt.Printf("%s picoclaw Status\n", internal.Logo)
|
||||
fmt.Printf("%s Jane AI Status\n", internal.Logo)
|
||||
fmt.Printf("Version: %s\n", config.FormatVersion())
|
||||
build, _ := config.FormatBuildInfo()
|
||||
if build != "" {
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ func NewVersionCommand() *cobra.Command {
|
|||
}
|
||||
|
||||
func printVersion() {
|
||||
fmt.Printf("%s picoclaw %s\n", internal.Logo, config.FormatVersion())
|
||||
fmt.Printf("%s jane-ai %s\n", internal.Logo, config.FormatVersion())
|
||||
build, goVer := config.FormatBuildInfo()
|
||||
if build != "" {
|
||||
fmt.Printf(" Build: %s\n", build)
|
||||
|
|
|
|||
|
|
@ -27,12 +27,12 @@ import (
|
|||
)
|
||||
|
||||
func NewPicoclawCommand() *cobra.Command {
|
||||
short := fmt.Sprintf("%s picoclaw - Personal AI Assistant v%s\n\n", internal.Logo, config.GetVersion())
|
||||
short := fmt.Sprintf("%s jane-ai - Personal AI Assistant v%s\n\n", internal.Logo, config.GetVersion())
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "picoclaw",
|
||||
Use: "jane-ai",
|
||||
Short: short,
|
||||
Example: "picoclaw version",
|
||||
Example: "jane-ai version",
|
||||
}
|
||||
|
||||
cmd.AddCommand(
|
||||
|
|
|
|||
|
|
@ -4,12 +4,22 @@ set -e
|
|||
# First-run: neither config nor workspace exists.
|
||||
# If config.json is already mounted but workspace is missing we skip onboard to
|
||||
# avoid the interactive "Overwrite? (y/n)" prompt hanging in a non-TTY container.
|
||||
if [ ! -d "${HOME}/.picoclaw/workspace" ] && [ ! -f "${HOME}/.picoclaw/config.json" ]; then
|
||||
picoclaw onboard
|
||||
BIN="${JANE_AI_BINARY:-jane-ai}"
|
||||
if ! command -v "$BIN" >/dev/null 2>&1; then
|
||||
BIN="picoclaw"
|
||||
fi
|
||||
|
||||
HOME_DIR="${JANE_AI_HOME:-${PICOCLAW_HOME:-${HOME}/.jane-ai}}"
|
||||
if [ ! -e "${HOME_DIR}/config.json" ] && [ -e "${HOME}/.picoclaw/config.json" ]; then
|
||||
HOME_DIR="${HOME}/.picoclaw"
|
||||
fi
|
||||
|
||||
if [ ! -d "${HOME_DIR}/workspace" ] && [ ! -f "${HOME_DIR}/config.json" ]; then
|
||||
"$BIN" onboard
|
||||
echo ""
|
||||
echo "First-run setup complete."
|
||||
echo "Edit ${HOME}/.picoclaw/config.json (add your API key, etc.) then restart the container."
|
||||
echo "Edit ${HOME_DIR}/config.json (add your API key, etc.) then restart the container."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
exec picoclaw gateway "$@"
|
||||
exec "$BIN" gateway "$@"
|
||||
|
|
|
|||
|
|
@ -79,9 +79,9 @@ func (cb *ContextBuilder) getIdentity() string {
|
|||
version := config.FormatVersion()
|
||||
|
||||
return fmt.Sprintf(
|
||||
`# picoclaw 🦞 (%s)
|
||||
`# Jane AI (%s)
|
||||
|
||||
You are picoclaw, a helpful AI assistant.
|
||||
You are Jane AI, a helpful AI assistant.
|
||||
|
||||
## Workspace
|
||||
Your workspace is at: %s
|
||||
|
|
|
|||
32
pkg/runtimepaths/binary.go
Normal file
32
pkg/runtimepaths/binary.go
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
package runtimepaths
|
||||
|
||||
import (
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
)
|
||||
|
||||
func BinaryPath() string {
|
||||
if path := firstEnv("JANE_AI_BINARY", "PICOCLAW_BINARY"); path != "" {
|
||||
return path
|
||||
}
|
||||
names := []string{"jane-ai", "picoclaw"}
|
||||
if runtime.GOOS == "windows" {
|
||||
names = []string{"jane-ai.exe", "picoclaw.exe"}
|
||||
}
|
||||
if exe, err := os.Executable(); err == nil {
|
||||
for _, name := range names {
|
||||
path := filepath.Join(filepath.Dir(exe), name)
|
||||
if info, err := os.Stat(path); err == nil && !info.IsDir() {
|
||||
return path
|
||||
}
|
||||
}
|
||||
}
|
||||
for _, name := range names {
|
||||
if path, err := exec.LookPath(name); err == nil {
|
||||
return path
|
||||
}
|
||||
}
|
||||
return names[len(names)-1]
|
||||
}
|
||||
|
|
@ -1,13 +1,13 @@
|
|||
// PicoClaw Web Console - Web-based chat and management interface
|
||||
// Jane AI Web Console - Web-based chat and management interface
|
||||
//
|
||||
// Provides a web UI for chatting with PicoClaw via the Pico Channel WebSocket,
|
||||
// Provides a web UI for chatting with Jane AI via the Pico Channel WebSocket,
|
||||
// with configuration management and gateway process control.
|
||||
//
|
||||
// Usage:
|
||||
//
|
||||
// go build -o picoclaw-web ./web/backend/
|
||||
// ./picoclaw-web [config.json]
|
||||
// ./picoclaw-web -public config.json
|
||||
// go build -o jane-ai-web ./web/backend/
|
||||
// ./jane-ai-web [config.json]
|
||||
// ./jane-ai-web -public config.json
|
||||
|
||||
package main
|
||||
|
||||
|
|
@ -34,10 +34,10 @@ func main() {
|
|||
noBrowser := flag.Bool("no-browser", false, "Do not auto-open browser on startup")
|
||||
|
||||
flag.Usage = func() {
|
||||
fmt.Fprintf(os.Stderr, "PicoClaw Launcher - A web-based configuration editor\n\n")
|
||||
fmt.Fprintf(os.Stderr, "Jane AI Launcher - A web-based configuration editor\n\n")
|
||||
fmt.Fprintf(os.Stderr, "Usage: %s [options] [config.json]\n\n", os.Args[0])
|
||||
fmt.Fprintf(os.Stderr, "Arguments:\n")
|
||||
fmt.Fprintf(os.Stderr, " config.json Path to the configuration file (default: ~/.picoclaw/config.json)\n\n")
|
||||
fmt.Fprintf(os.Stderr, " config.json Path to the configuration file (default: ~/.jane-ai/config.json)\n\n")
|
||||
fmt.Fprintf(os.Stderr, "Options:\n")
|
||||
flag.PrintDefaults()
|
||||
fmt.Fprintf(os.Stderr, "\nExamples:\n")
|
||||
|
|
@ -63,7 +63,7 @@ func main() {
|
|||
}
|
||||
err = utils.EnsureOnboarded(absPath)
|
||||
if err != nil {
|
||||
logger.WarnCF("main", "Failed to initialize PicoClaw config automatically", map[string]any{"error": err.Error()})
|
||||
logger.WarnCF("main", "Failed to initialize Jane AI config automatically", map[string]any{"error": err.Error()})
|
||||
}
|
||||
|
||||
var explicitPort bool
|
||||
|
|
|
|||
|
|
@ -34,34 +34,7 @@ func GetDefaultConfigPath() string {
|
|||
// 2. Same directory as the current executable
|
||||
// 3. Falls back to "jane-ai" or "picoclaw" on $PATH
|
||||
func FindPicoclawBinary() string {
|
||||
if p := os.Getenv("JANE_AI_BINARY"); p != "" {
|
||||
if info, _ := os.Stat(p); info != nil && !info.IsDir() {
|
||||
return p
|
||||
}
|
||||
}
|
||||
if p := os.Getenv("PICOCLAW_BINARY"); p != "" {
|
||||
if info, _ := os.Stat(p); info != nil && !info.IsDir() {
|
||||
return p
|
||||
}
|
||||
}
|
||||
|
||||
binaryNames := []string{"jane-ai", "picoclaw"}
|
||||
if runtime.GOOS == "windows" {
|
||||
binaryNames = []string{"jane-ai.exe", "picoclaw.exe"}
|
||||
}
|
||||
if exe, err := os.Executable(); err == nil {
|
||||
for _, binaryName := range binaryNames {
|
||||
candidate := filepath.Join(filepath.Dir(exe), binaryName)
|
||||
if info, err := os.Stat(candidate); err == nil && !info.IsDir() {
|
||||
return candidate
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if path, err := exec.LookPath(binaryNames[0]); err == nil {
|
||||
return path
|
||||
}
|
||||
return "picoclaw"
|
||||
return runtimepaths.BinaryPath()
|
||||
}
|
||||
|
||||
// GetLocalIP returns the local IP address of the machine.
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue