Merge branch 'main' into fix-config-model-list-override-13448010885405533147

This commit is contained in:
Nhat Tan 2026-03-27 10:44:41 +07:00 committed by GitHub
commit 3db3bf879c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 64 additions and 10 deletions

View file

@ -223,6 +223,25 @@ install: build
@echo "Installed uninstaller script to $(INSTALL_BIN_DIR)/$(BINARY_NAME)-uninstall" @echo "Installed uninstaller script to $(INSTALL_BIN_DIR)/$(BINARY_NAME)-uninstall"
@echo "Installation complete!" @echo "Installation complete!"
## install-pico: Build core, web and install picoclaw and picoclaw-launcher to system
install-pico: build build-launcher
@echo "Installing $(BINARY_NAME) and picoclaw-launcher..."
@mkdir -p $(INSTALL_BIN_DIR)
# Copy core binary with temporary suffix to ensure atomic update
@cp $(BUILD_DIR)/$(BINARY_NAME) $(INSTALL_BIN_DIR)/$(BINARY_NAME)$(INSTALL_TMP_SUFFIX)
@chmod +x $(INSTALL_BIN_DIR)/$(BINARY_NAME)$(INSTALL_TMP_SUFFIX)
@mv -f $(INSTALL_BIN_DIR)/$(BINARY_NAME)$(INSTALL_TMP_SUFFIX) $(INSTALL_BIN_DIR)/$(BINARY_NAME)
@echo "Installed binary to $(INSTALL_BIN_DIR)/$(BINARY_NAME)"
# Copy launcher binary with temporary suffix
@cp $(BUILD_DIR)/picoclaw-launcher $(INSTALL_BIN_DIR)/picoclaw-launcher$(INSTALL_TMP_SUFFIX)
@chmod +x $(INSTALL_BIN_DIR)/picoclaw-launcher$(INSTALL_TMP_SUFFIX)
@mv -f $(INSTALL_BIN_DIR)/picoclaw-launcher$(INSTALL_TMP_SUFFIX) $(INSTALL_BIN_DIR)/picoclaw-launcher
@echo "Installed launcher to $(INSTALL_BIN_DIR)/picoclaw-launcher"
@cp scripts/uninstall.sh $(INSTALL_BIN_DIR)/$(BINARY_NAME)-uninstall
@chmod +x $(INSTALL_BIN_DIR)/$(BINARY_NAME)-uninstall
@echo "Installed uninstaller script to $(INSTALL_BIN_DIR)/$(BINARY_NAME)-uninstall"
@echo "Installation complete!"
## uninstall: Remove picoclaw from system ## uninstall: Remove picoclaw from system
uninstall: uninstall:
@echo "Uninstalling $(BINARY_NAME)..." @echo "Uninstalling $(BINARY_NAME)..."

View file

@ -1279,7 +1279,10 @@ func LoadConfig(path string) (*Config, error) {
data, err := os.ReadFile(path) data, err := os.ReadFile(path)
if err != nil { if err != nil {
if os.IsNotExist(err) { if os.IsNotExist(err) {
logger.WarnF("config file not found, using default config", map[string]any{"path": path}) logger.WarnF(
"config file not found, using default config",
map[string]any{"path": path},
)
return DefaultConfig(), nil return DefaultConfig(), nil
} }
logger.Errorf("failed to read config file: %v", err) logger.Errorf("failed to read config file: %v", err)
@ -1302,7 +1305,10 @@ func LoadConfig(path string) (*Config, error) {
var cfg *Config var cfg *Config
switch versionInfo.Version { switch versionInfo.Version {
case 0: case 0:
logger.InfoF("config migrate start", map[string]any{"from": versionInfo.Version, "to": CurrentVersion}) logger.InfoF(
"config migrate start",
map[string]any{"from": versionInfo.Version, "to": CurrentVersion},
)
// Legacy config (no version field) // Legacy config (no version field)
v, e := loadConfigV0(data) v, e := loadConfigV0(data)
if e != nil { if e != nil {
@ -1310,10 +1316,16 @@ func LoadConfig(path string) (*Config, error) {
} }
cfg, e = v.Migrate() cfg, e = v.Migrate()
if e != nil { if e != nil {
logger.ErrorF("config migrate fail", map[string]any{"from": versionInfo.Version, "to": CurrentVersion}) logger.ErrorF(
"config migrate fail",
map[string]any{"from": versionInfo.Version, "to": CurrentVersion},
)
return nil, e return nil, e
} }
logger.InfoF("config migrate success", map[string]any{"from": versionInfo.Version, "to": CurrentVersion}) logger.InfoF(
"config migrate success",
map[string]any{"from": versionInfo.Version, "to": CurrentVersion},
)
err = makeBackup(path) err = makeBackup(path)
if err != nil { if err != nil {
return nil, err return nil, err
@ -1321,13 +1333,19 @@ func LoadConfig(path string) (*Config, error) {
// Load existing security config and merge with migrated one to prevent data loss // Load existing security config and merge with migrated one to prevent data loss
existingSec, secErr := loadSecurityConfig(securityPath(path)) existingSec, secErr := loadSecurityConfig(securityPath(path))
if secErr != nil { if secErr != nil {
logger.WarnF("failed to load existing security config during migration", map[string]any{"error": secErr}) logger.WarnF(
"failed to load existing security config during migration",
map[string]any{"error": secErr},
)
} }
if existingSec != nil && cfg.security != nil { if existingSec != nil && cfg.security != nil {
cfg.security = mergeSecurityConfig(existingSec, cfg.security) cfg.security = mergeSecurityConfig(existingSec, cfg.security)
// Re-apply the merged security config to update all channels and models // Re-apply the merged security config to update all channels and models
if err = applySecurityConfig(cfg, cfg.security); err != nil { if err = applySecurityConfig(cfg, cfg.security); err != nil {
logger.WarnF("failed to re-apply merged security config during migration", map[string]any{"error": err}) logger.WarnF(
"failed to re-apply merged security config during migration",
map[string]any{"error": err},
)
} }
} }
defer func(cfg *Config) { defer func(cfg *Config) {
@ -1348,7 +1366,10 @@ func LoadConfig(path string) (*Config, error) {
tmpCfgMigrated, e := tmpCfg.Migrate() tmpCfgMigrated, e := tmpCfg.Migrate()
if e != nil { if e != nil {
logger.ErrorF("config migrate fail", map[string]any{"from": versionInfo.Version, "to": CurrentVersion}) logger.ErrorF(
"config migrate fail",
map[string]any{"from": versionInfo.Version, "to": CurrentVersion},
)
return nil, e return nil, e
} }
@ -1371,9 +1392,11 @@ func LoadConfig(path string) (*Config, error) {
for _, m := range cfg.ModelList { for _, m := range cfg.ModelList {
for _, k := range m.apiKeys { for _, k := range m.apiKeys {
if k != "" && !strings.HasPrefix(k, "enc://") && !strings.HasPrefix(k, "file://") { if k != "" && !strings.HasPrefix(k, "enc://") && !strings.HasPrefix(k, "file://") {
fmt.Fprintf(os.Stderr, fmt.Fprintf(
os.Stderr,
"picoclaw: warning: model %q has a plaintext api_key; call SaveConfig to encrypt it\n", "picoclaw: warning: model %q has a plaintext api_key; call SaveConfig to encrypt it\n",
m.ModelName) m.ModelName,
)
break // Only warn once per model break // Only warn once per model
} }
} }

View file

@ -445,7 +445,11 @@ func (p *Provider) ChatStream(
if part.FunctionCall != nil { if part.FunctionCall != nil {
argsJSON, _ := json.Marshal(part.FunctionCall.Args) argsJSON, _ := json.Marshal(part.FunctionCall.Args)
toolCall := ToolCall{ toolCall := ToolCall{
ID: fmt.Sprintf("call_%s_%d", part.FunctionCall.Name, time.Now().UnixNano()), ID: fmt.Sprintf(
"call_%s_%d",
part.FunctionCall.Name,
time.Now().UnixNano(),
),
Name: part.FunctionCall.Name, Name: part.FunctionCall.Name,
Arguments: part.FunctionCall.Args, Arguments: part.FunctionCall.Args,
Function: &FunctionCall{ Function: &FunctionCall{

View file

@ -20,6 +20,14 @@ else
echo "Executable ${INSTALL_BIN_DIR}/${BINARY_NAME} not found. Skipping." echo "Executable ${INSTALL_BIN_DIR}/${BINARY_NAME} not found. Skipping."
fi fi
# Remove the launcher binary
if [ -f "${INSTALL_BIN_DIR}/picoclaw-launcher" ]; then
rm -f "${INSTALL_BIN_DIR}/picoclaw-launcher"
echo "Removed executable: ${INSTALL_BIN_DIR}/picoclaw-launcher"
else
echo "Executable ${INSTALL_BIN_DIR}/picoclaw-launcher not found. Skipping."
fi
# Remove the workspace and configurations # Remove the workspace and configurations
if [ -d "${PICOCLAW_HOME}" ]; then if [ -d "${PICOCLAW_HOME}" ]; then
rm -rf "${PICOCLAW_HOME}" rm -rf "${PICOCLAW_HOME}"