diff --git a/.github/workflows/create_dmg.yml b/.github/workflows/create_dmg.yml index b47247fc2..e03357566 100644 --- a/.github/workflows/create_dmg.yml +++ b/.github/workflows/create_dmg.yml @@ -54,9 +54,9 @@ jobs: "dist/picoclaw-${{ matrix.arch }}.dmg" \ "build/PicoClaw Launcher.app" - # 6. 上传文件到 GitHub Artifacts (供你下载) + # 7. 上传文件到 GitHub Artifacts (供你下载) - name: Upload DMG - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v7 with: name: macos-dmg-${{ matrix.arch }} - path: dist/*.dmg \ No newline at end of file + path: dist/*.dmg diff --git a/.gitignore b/.gitignore index b869ecc33..135867842 100644 --- a/.gitignore +++ b/.gitignore @@ -67,3 +67,5 @@ web/backend/dist/* .claude/ docker/data + +.omc/ diff --git a/.golangci.yaml b/.golangci.yaml index b2b772406..052e4c0dd 100644 --- a/.golangci.yaml +++ b/.golangci.yaml @@ -12,6 +12,7 @@ linters: - exhaustruct - funcorder - gochecknoglobals + - gosmopolitan # Project legitimately uses CJK text in tests (FTS5, token counting) - godot - intrange - ireturn diff --git a/Makefile b/Makefile index 21d8bdeac..f7ebc7411 100644 --- a/Makefile +++ b/Makefile @@ -5,6 +5,7 @@ BINARY_NAME=picoclaw BUILD_DIR=build CMD_DIR=cmd/$(BINARY_NAME) MAIN_GO=$(CMD_DIR)/main.go +EXT= # Version VERSION?=$(shell git describe --tags --always --dirty 2>/dev/null || echo "dev") @@ -69,9 +70,11 @@ WORKSPACE_DIR?=$(PICOCLAW_HOME)/workspace WORKSPACE_SKILLS_DIR=$(WORKSPACE_DIR)/skills BUILTIN_SKILLS_DIR=$(CURDIR)/skills +LNCMD=ln -sf + # OS detection -UNAME_S:=$(shell uname -s) -UNAME_M:=$(shell uname -m) +UNAME_S?=$(shell uname -s) +UNAME_M?=$(shell uname -m) # Platform-specific settings ifeq ($(UNAME_S),Linux) @@ -103,7 +106,20 @@ else ifeq ($(UNAME_S),Darwin) endif else PLATFORM=$(UNAME_S) - ARCH=$(UNAME_M) + ifeq ($(UNAME_M),x86_64) + ARCH?=amd64 + else + ARCH?=$(UNAME_M) + endif + # Detect Windows (Git Bash / MSYS2) + IS_WINDOWS:=$(if $(findstring MINGW,$(UNAME_S)),yes,$(if $(findstring MSYS,$(UNAME_S)),yes,$(if $(findstring CYGWIN,$(UNAME_S)),yes,no))) + ifeq ($(IS_WINDOWS),yes) + EXT=.exe + LNCMD=cp + else ifeq ($(UNAME_S),windows) # failsafe for force windows build in other OS using UNAME_S=windows + EXT=.exe + endif + endif BINARY_PATH=$(BUILD_DIR)/$(BINARY_NAME)-$(PLATFORM)-$(ARCH) @@ -120,23 +136,23 @@ generate: ## build: Build the picoclaw binary for current platform build: generate - @echo "Building $(BINARY_NAME) for $(PLATFORM)/$(ARCH)..." + @echo "Building $(BINARY_NAME)$(EXT) for $(PLATFORM)/$(ARCH)..." @mkdir -p $(BUILD_DIR) - @GOARCH=${ARCH} $(GO) build $(GOFLAGS) -ldflags "$(LDFLAGS)" -o $(BINARY_PATH) ./$(CMD_DIR) - @echo "Build complete: $(BINARY_PATH)" - @ln -sf $(BINARY_NAME)-$(PLATFORM)-$(ARCH) $(BUILD_DIR)/$(BINARY_NAME) + @GOARCH=${ARCH} $(GO) build $(GOFLAGS) -ldflags "$(LDFLAGS)" -o $(BINARY_PATH)$(EXT) ./$(CMD_DIR) + @echo "Build complete: $(BINARY_PATH)$(EXT)" + @$(LNCMD) $(BINARY_NAME)-$(PLATFORM)-$(ARCH)$(EXT) $(BUILD_DIR)/$(BINARY_NAME)$(EXT) ## build-launcher: Build the picoclaw-launcher (web console) binary build-launcher: @echo "Building picoclaw-launcher for $(PLATFORM)/$(ARCH)..." @mkdir -p $(BUILD_DIR) @GOARCH=${ARCH} $(MAKE) -C web build \ - OUTPUT="$(CURDIR)/$(BUILD_DIR)/picoclaw-launcher-$(PLATFORM)-$(ARCH)" \ + OUTPUT="$(CURDIR)/$(BUILD_DIR)/picoclaw-launcher-$(PLATFORM)-$(ARCH)$(EXT)" \ WEB_GO='$(WEB_GO)' \ GO_BUILD_TAGS='$(GO_BUILD_TAGS)' \ LDFLAGS='$(LDFLAGS)' - @ln -sf picoclaw-launcher-$(PLATFORM)-$(ARCH) $(BUILD_DIR)/picoclaw-launcher - @echo "Build complete: $(BUILD_DIR)/picoclaw-launcher" + @$(LNCMD) picoclaw-launcher-$(PLATFORM)-$(ARCH)$(EXT) $(BUILD_DIR)/picoclaw-launcher$(EXT) + @echo "Build complete: $(BUILD_DIR)/picoclaw-launcher$(EXT)" build-launcher-frontend: @$(MAKE) -C web build-frontend @@ -333,6 +349,25 @@ build-macos-app:build-launcher @./scripts/build-macos-app.sh $(PLATFORM)-$(ARCH) @echo "macOS .app bundle created: $(BUILD_DIR)/PicoClaw.app" +## mem: Build membench, download LOCOMO data (if needed), run benchmark, and show results +mem: + @echo "Building membench..." + @mkdir -p $(BUILD_DIR) + @$(GO) build -o $(BUILD_DIR)/membench ./cmd/membench + @echo "Build complete: $(BUILD_DIR)/membench" + @if [ ! -f $(BUILD_DIR)/memdata/locomo10.json ]; then \ + echo "Downloading LOCOMO dataset..."; \ + mkdir -p $(BUILD_DIR)/memdata; \ + curl -sfL "https://raw.githubusercontent.com/snap-research/locomo/main/data/locomo10.json" \ + -o $(BUILD_DIR)/memdata/locomo10.json && [ -s $(BUILD_DIR)/memdata/locomo10.json ] || { echo "Error: LOCOMO download failed"; exit 1; }; \ + echo "Download complete"; \ + else \ + echo "LOCOMO dataset already exists, skipping download"; \ + fi + @echo "Running benchmark..." + @rm -rf $(BUILD_DIR)/memout + @$(BUILD_DIR)/membench run --data $(BUILD_DIR)/memdata --out $(BUILD_DIR)/memout --budget 4000 + ## help: Show this help message help: @echo "picoclaw Makefile" diff --git a/README.fr.md b/README.fr.md index a0cb84ce3..a26c89f14 100644 --- a/README.fr.md +++ b/README.fr.md @@ -306,7 +306,25 @@ Pour la documentation détaillée du TUI, voir [docs.picoclaw.io](https://docs.p Donnez une seconde vie à votre téléphone vieux de dix ans ! Transformez-le en assistant IA intelligent avec PicoClaw. -**Option 1 : Termux (disponible maintenant)** +**Option 1 : Installation APK** + +Aperçu : + +
![]() |
+ ![]() |
+ ![]() |
+ ![]() |
+
-**Option 2 : Installation APK**
-
-Téléchargez l'APK depuis [picoclaw.io](https://picoclaw.io/download/) et installez-le directement. Pas besoin de Termux !
-
-![]() |
+ ![]() |
+ ![]() |
+ ![]() |
+
-**Opsi 2: Instal APK**
-
-Unduh APK dari [picoclaw.io](https://picoclaw.io/download/) dan instal langsung. Tanpa Termux!
-
-![]() |
+ ![]() |
+ ![]() |
+ ![]() |
+
-**Opzione 2: Installazione APK**
-
-Scarica l'APK da [picoclaw.io](https://picoclaw.io/download/) e installa direttamente. Senza Termux!
-
-![]() |
+ ![]() |
+ ![]() |
+ ![]() |
+
-**オプション 2: APK インストール**
-
-[picoclaw.io](https://picoclaw.io/download/) から APK をダウンロードして直接インストール。Termux 不要!
-
-![]() |
+ ![]() |
+ ![]() |
+ ![]() |
+
-**Option 2: APK Install**
-
-Download the APK from [picoclaw.io](https://picoclaw.io/download/) and install directly. No Termux required!
-
-![]() |
+ ![]() |
+ ![]() |
+ ![]() |
+
-**Pilihan 2: Pasang APK**
-
-Muat turun APK dari [picoclaw.io](https://picoclaw.io/download/) dan pasang secara langsung. Tiada Termux diperlukan!
-
-![]() |
+ ![]() |
+ ![]() |
+ ![]() |
+
-**Opção 2: Instalação via APK**
-
-Baixe o APK de [picoclaw.io](https://picoclaw.io/download/) e instale diretamente. Sem necessidade de Termux!
-
-![]() |
+ ![]() |
+ ![]() |
+ ![]() |
+
-**Tùy chọn 2: Cài đặt APK**
-
-Tải APK từ [picoclaw.io](https://picoclaw.io/download/) và cài đặt trực tiếp. Không cần Termux!
-
-![]() |
+ ![]() |
+ ![]() |
+ ![]() |
+
-**方式二:APK 安装**
-
-从 [picoclaw.io](https://picoclaw.io/download/) 下载 APK 并直接安装,无需 Termux!
-
-- {t("channels.edit", { - name: channelDisplayName, - })} -
- {channel && docsUrl && ( - - {t("channels.page.docLink")} - - )} -- {t("channels.weixin.warningTitle")} -
-- {t("channels.weixin.warningDesc")} -
-{t("channels.page.enableLabel")}
diff --git a/web/frontend/src/components/channels/channel-forms/discord-form.tsx b/web/frontend/src/components/channels/channel-forms/discord-form.tsx index 300175e20..f72e1c5c7 100644 --- a/web/frontend/src/components/channels/channel-forms/discord-form.tsx +++ b/web/frontend/src/components/channels/channel-forms/discord-form.tsx @@ -1,14 +1,15 @@ import { useTranslation } from "react-i18next" import type { ChannelConfig } from "@/api/channels" -import { maskedSecretPlaceholder } from "@/components/secret-placeholder" +import { getSecretInputPlaceholder } from "@/components/channels/channel-config-fields" import { Field, KeyInput, SwitchCardField } from "@/components/shared-form" +import { Card, CardContent } from "@/components/ui/card" import { Input } from "@/components/ui/input" interface DiscordFormProps { config: ChannelConfig onChange: (key: string, value: unknown) => void - isEdit: boolean + configuredSecrets: string[] fieldErrors?: Record- {t("channels.page.enableLabel")} -
-- {isBound - ? t("channels.wecom.enableDesc") - : t("channels.wecom.enableBindFirst")} -
-{t("channels.page.enableLabel")}
++ {toggleError} +
+ )}{toggleError}
- )}{t("channels.wecom.bindTitle")}
-- {t("channels.wecom.bindDesc")} -
-+
- {t("channels.weixin.bindDesc")} -
-{label}
++ {label} +
{hint && ( -+
{hint}
)}+
{error}
)} @@ -168,7 +181,11 @@ export function SwitchCardField({ } return ( -{label}
@@ -185,7 +202,7 @@ export function SwitchCardField({ aria-label={ariaLabel ?? label} />{error}
)} diff --git a/web/frontend/src/components/tour/tour-guide.tsx b/web/frontend/src/components/tour/tour-guide.tsx index cc1e6e3a1..bd3761096 100644 --- a/web/frontend/src/components/tour/tour-guide.tsx +++ b/web/frontend/src/components/tour/tour-guide.tsx @@ -7,14 +7,14 @@ import { useAtom } from "jotai" import { useTranslation } from "react-i18next" import { Button } from "@/components/ui/button" +import { cn } from "@/lib/utils" import { + type TourStep, tourAtom, tourCurrentStepAtom, tourIsActiveAtom, - type TourStep, useTourActions, } from "@/store/tour" -import { cn } from "@/lib/utils" interface TourStepConfig { title: string @@ -177,7 +177,7 @@ export function TourGuide() { {targetElement && (