From f7e768152e076d863ce3bd20019256dc96fad44e Mon Sep 17 00:00:00 2001 From: Liu Yuan Date: Mon, 13 Apr 2026 11:04:45 +0800 Subject: [PATCH 1/6] feat(agent): /clear now clears seahorse DB in addition to JSONL - Add Clear(ctx, sessionKey) to ContextManager interface - Implement Clear for legacy (JSONL) and seahorse (DB + JSONL) - Add Engine.ClearSession + Store.ClearConversation - Fix FTS5 DELETE trigger syntax in schema (was using wrong external-content FTS5 syntax; now uses standard DELETE FROM) - Fix ClearSession to skip sessions never ingested (was creating blank conversations record via GetOrCreateConversation) - Simplify summary_parents DELETE into single OR statement - Add TestStoreClearConversation unit test --- pkg/agent/context_legacy.go | 10 ++++ pkg/agent/context_manager.go | 4 ++ pkg/agent/context_manager_test.go | 3 ++ pkg/agent/context_seahorse.go | 13 +++++ pkg/agent/loop.go | 17 +++--- pkg/seahorse/schema.go | 4 +- pkg/seahorse/short_engine.go | 13 +++++ pkg/seahorse/store.go | 51 ++++++++++++++++++ pkg/seahorse/store_test.go | 90 ++++++++++++++++++++++++++++++- 9 files changed, 192 insertions(+), 13 deletions(-) diff --git a/pkg/agent/context_legacy.go b/pkg/agent/context_legacy.go index 0f10decb3..85e331ae9 100644 --- a/pkg/agent/context_legacy.go +++ b/pkg/agent/context_legacy.go @@ -61,6 +61,16 @@ func (m *legacyContextManager) Ingest(_ context.Context, _ *IngestRequest) error return nil } +func (m *legacyContextManager) Clear(_ context.Context, sessionKey string) error { + agent := m.al.registry.GetDefaultAgent() + if agent == nil || agent.Sessions == nil { + return fmt.Errorf("sessions not initialized") + } + agent.Sessions.SetHistory(sessionKey, []providers.Message{}) + agent.Sessions.SetSummary(sessionKey, "") + return agent.Sessions.Save(sessionKey) +} + // maybeSummarize triggers summarization if the session history exceeds thresholds. // It runs asynchronously in a goroutine. func (m *legacyContextManager) maybeSummarize(sessionKey string) { diff --git a/pkg/agent/context_manager.go b/pkg/agent/context_manager.go index 5f8701812..5a5dfe97c 100644 --- a/pkg/agent/context_manager.go +++ b/pkg/agent/context_manager.go @@ -24,6 +24,10 @@ type ContextManager interface { // Ingest records a message into the ContextManager's own storage. // Called after each message is persisted to session JSONL. Ingest(ctx context.Context, req *IngestRequest) error + + // Clear removes all stored context for a session (messages, summaries, etc.). + // Called when the user issues /clear or /reset. + Clear(ctx context.Context, sessionKey string) error } // AssembleRequest is the input to Assemble. diff --git a/pkg/agent/context_manager_test.go b/pkg/agent/context_manager_test.go index 6bde5e1a9..629d11fcb 100644 --- a/pkg/agent/context_manager_test.go +++ b/pkg/agent/context_manager_test.go @@ -690,6 +690,7 @@ func (m *noopContextManager) Assemble(_ context.Context, req *AssembleRequest) ( } func (m *noopContextManager) Compact(_ context.Context, _ *CompactRequest) error { return nil } func (m *noopContextManager) Ingest(_ context.Context, _ *IngestRequest) error { return nil } +func (m *noopContextManager) Clear(_ context.Context, _ string) error { return nil } // trackingContextManager tracks call counts for each method. type trackingContextManager struct { @@ -726,6 +727,8 @@ func (m *trackingContextManager) Ingest(_ context.Context, req *IngestRequest) e return nil } +func (m *trackingContextManager) Clear(_ context.Context, _ string) error { return nil } + // resetCMRegistry clears the global factory registry and returns a cleanup // function that restores the original state after the test. func resetCMRegistry() func() { diff --git a/pkg/agent/context_seahorse.go b/pkg/agent/context_seahorse.go index 327c6162a..c6e5b30ac 100644 --- a/pkg/agent/context_seahorse.go +++ b/pkg/agent/context_seahorse.go @@ -154,6 +154,19 @@ func (m *seahorseContextManager) Ingest(ctx context.Context, req *IngestRequest) return err } +// Clear removes all stored context for a session (seahorse DB + JSONL). +func (m *seahorseContextManager) Clear(ctx context.Context, sessionKey string) error { + if err := m.engine.ClearSession(ctx, sessionKey); err != nil { + return err + } + if m.sessions != nil { + m.sessions.SetHistory(sessionKey, []providers.Message{}) + m.sessions.SetSummary(sessionKey, "") + return m.sessions.Save(sessionKey) + } + return nil +} + // bootstrapSession reconciles JSONL session history into seahorse SQLite. func (m *seahorseContextManager) bootstrapSession(ctx context.Context, sessionKey string) { if m.sessions == nil { diff --git a/pkg/agent/loop.go b/pkg/agent/loop.go index a856c0fca..f67802663 100644 --- a/pkg/agent/loop.go +++ b/pkg/agent/loop.go @@ -3368,7 +3368,7 @@ func (al *AgentLoop) handleCommand( return "", false } - rt := al.buildCommandsRuntime(agent, opts) + rt := al.buildCommandsRuntime(ctx, agent, opts) executor := commands.NewExecutor(al.cmdRegistry, rt) var commandReply string @@ -3488,7 +3488,11 @@ func (al *AgentLoop) applyExplicitSkillCommand( return true, false, "" } -func (al *AgentLoop) buildCommandsRuntime(agent *AgentInstance, opts *processOptions) *commands.Runtime { +func (al *AgentLoop) buildCommandsRuntime( + ctx context.Context, + agent *AgentInstance, + opts *processOptions, +) *commands.Runtime { registry := al.GetRegistry() cfg := al.GetConfig() rt := &commands.Runtime{ @@ -3570,14 +3574,7 @@ func (al *AgentLoop) buildCommandsRuntime(agent *AgentInstance, opts *processOpt if opts == nil { return fmt.Errorf("process options not available") } - if agent.Sessions == nil { - return fmt.Errorf("sessions not initialized for agent") - } - - agent.Sessions.SetHistory(opts.SessionKey, make([]providers.Message, 0)) - agent.Sessions.SetSummary(opts.SessionKey, "") - agent.Sessions.Save(opts.SessionKey) - return nil + return al.contextManager.Clear(ctx, opts.SessionKey) } } return rt diff --git a/pkg/seahorse/schema.go b/pkg/seahorse/schema.go index effa6d60d..bf32d548b 100644 --- a/pkg/seahorse/schema.go +++ b/pkg/seahorse/schema.go @@ -123,10 +123,10 @@ func runSchema(db *sql.DB) error { INSERT INTO summaries_fts (summary_id, content) VALUES (new.summary_id, new.content); END`, `CREATE TRIGGER IF NOT EXISTS summaries_ad AFTER DELETE ON summaries BEGIN - INSERT INTO summaries_fts (summaries_fts, summary_id, content) VALUES ('delete', old.summary_id, old.content); + DELETE FROM summaries_fts WHERE summary_id = old.summary_id; END`, `CREATE TRIGGER IF NOT EXISTS summaries_au AFTER UPDATE ON summaries BEGIN - INSERT INTO summaries_fts (summaries_fts, summary_id, content) VALUES ('delete', old.summary_id, old.content); + DELETE FROM summaries_fts WHERE summary_id = old.summary_id; INSERT INTO summaries_fts (summary_id, content) VALUES (new.summary_id, new.content); END`, diff --git a/pkg/seahorse/short_engine.go b/pkg/seahorse/short_engine.go index 4cd4d3887..f584788ce 100644 --- a/pkg/seahorse/short_engine.go +++ b/pkg/seahorse/short_engine.go @@ -377,6 +377,19 @@ func (e *Engine) IngestMessages(ctx context.Context, sessionKey string, messages return e.Ingest(ctx, sessionKey, messages) } +// ClearSession removes all stored data for a session (messages, summaries, context). +// If the session has no prior seahorse record, it is a no-op. +func (e *Engine) ClearSession(ctx context.Context, sessionKey string) error { + conv, err := e.store.GetConversationBySessionKey(ctx, sessionKey) + if err != nil { + return err + } + if conv == nil { + return nil // session never ingested, nothing to clear + } + return e.store.ClearConversation(ctx, conv.ConversationID) +} + // Bootstrap reconciles a session's messages with the database. // Called once at startup for each known session. // Bootstrap reconciles JSONL history with SQLite by ingesting only the delta. diff --git a/pkg/seahorse/store.go b/pkg/seahorse/store.go index 3026533b2..c84aaaf07 100644 --- a/pkg/seahorse/store.go +++ b/pkg/seahorse/store.go @@ -728,6 +728,57 @@ func (s *Store) DeleteMessagesAfterID(ctx context.Context, convID int64, afterID return tx.Commit() } +// ClearConversation removes all data for a conversation from all tables. +// Deletes context_items, summary_messages, summary_parents (via subquery), summaries, +// message_parts, and messages. FTS entries are handled automatically by triggers. +// Uses a transaction for atomicity. +func (s *Store) ClearConversation(ctx context.Context, convID int64) error { + tx, err := s.db.BeginTx(ctx, nil) + if err != nil { + return err + } + defer tx.Rollback() + + // Delete in child→parent order. FTS tables (messages_fts, summaries_fts) are + // kept in sync by DELETE triggers, so we just delete from the parent tables. + + if _, err := tx.ExecContext(ctx, + "DELETE FROM context_items WHERE conversation_id = ?", convID); err != nil { + return fmt.Errorf("context_items: %w", err) + } + if _, err := tx.ExecContext(ctx, + `DELETE FROM summary_messages WHERE summary_id IN ( + SELECT summary_id FROM summaries WHERE conversation_id = ? + )`, convID); err != nil { + return fmt.Errorf("summary_messages: %w", err) + } + // Note: summary_parents has no convID column; delete via subquery on summaries + if _, err := tx.ExecContext(ctx, + `DELETE FROM summary_parents WHERE summary_id IN ( + SELECT summary_id FROM summaries WHERE conversation_id = ? + ) OR parent_summary_id IN ( + SELECT summary_id FROM summaries WHERE conversation_id = ? + )`, convID, convID); err != nil { + return fmt.Errorf("summary_parents: %w", err) + } + if _, err := tx.ExecContext(ctx, + "DELETE FROM summaries WHERE conversation_id = ?", convID); err != nil { + return fmt.Errorf("summaries: %w", err) + } + if _, err := tx.ExecContext(ctx, + `DELETE FROM message_parts WHERE message_id IN ( + SELECT message_id FROM messages WHERE conversation_id = ? + )`, convID); err != nil { + return fmt.Errorf("message_parts: %w", err) + } + if _, err := tx.ExecContext(ctx, + "DELETE FROM messages WHERE conversation_id = ?", convID); err != nil { + return fmt.Errorf("messages: %w", err) + } + + return tx.Commit() +} + // AppendContextMessage appends a single message to context_items at next ordinal. func (s *Store) AppendContextMessage(ctx context.Context, convID int64, messageID int64) error { return s.appendContextItems(ctx, convID, []ContextItem{ diff --git a/pkg/seahorse/store_test.go b/pkg/seahorse/store_test.go index fd55379c6..89635cc9a 100644 --- a/pkg/seahorse/store_test.go +++ b/pkg/seahorse/store_test.go @@ -79,7 +79,95 @@ func TestStoreGetConversationBySessionKey(t *testing.T) { } } -// --- Message Operations --- +// --- Conversation Clear --- + +func TestStoreClearConversation(t *testing.T) { + s := openTestStore(t) + ctx := context.Background() + + conv, err := s.GetOrCreateConversation(ctx, "agent:clear-test") + if err != nil { + t.Fatalf("create conversation: %v", err) + } + + // Add messages + msg1, err := s.AddMessage(ctx, conv.ConversationID, "user", "hello", 5) + if err != nil { + t.Fatalf("add message 1: %v", err) + } + msg2, err := s.AddMessage(ctx, conv.ConversationID, "assistant", "hi", 5) + if err != nil { + t.Fatalf("add message 2: %v", err) + } + + // Add a summary + _, err = s.CreateSummary(ctx, CreateSummaryInput{ + ConversationID: conv.ConversationID, + Content: "test summary", + TokenCount: 10, + Kind: SummaryKindLeaf, + }) + if err != nil { + t.Fatalf("create summary: %v", err) + } + + // Verify data exists + msgs, err := s.GetMessages(ctx, conv.ConversationID, 0, 0) + if err != nil { + t.Fatalf("get messages before clear: %v", err) + } + if len(msgs) != 2 { + t.Fatalf("expected 2 messages before clear, got %d", len(msgs)) + } + + sums, err := s.GetSummariesByConversation(ctx, conv.ConversationID) + if err != nil { + t.Fatalf("get summaries before clear: %v", err) + } + if len(sums) != 1 { + t.Fatalf("expected 1 summary before clear, got %d", len(sums)) + } + + // Clear + if err = s.ClearConversation(ctx, conv.ConversationID); err != nil { + t.Fatalf("clear conversation: %v", err) + } + + // Verify all data is gone + msgs, err = s.GetMessages(ctx, conv.ConversationID, 0, 0) + if err != nil { + t.Fatalf("get messages after clear: %v", err) + } + if len(msgs) != 0 { + t.Fatalf("expected 0 messages after clear, got %d", len(msgs)) + } + + sums, err = s.GetSummariesByConversation(ctx, conv.ConversationID) + if err != nil { + t.Fatalf("get summaries after clear: %v", err) + } + if len(sums) != 0 { + t.Fatalf("expected 0 summaries after clear, got %d", len(sums)) + } + + items, err := s.GetContextItems(ctx, conv.ConversationID) + if err != nil { + t.Fatalf("get context items after clear: %v", err) + } + if len(items) != 0 { + t.Fatalf("expected 0 context items after clear, got %d", len(items)) + } + + var count int + if err := s.db.QueryRowContext(ctx, + "SELECT COUNT(*) FROM message_parts WHERE message_id = ? OR message_id = ?", + msg1.ID, msg2.ID).Scan(&count); err != nil { + t.Fatalf("count message parts: %v", err) + } + if count != 0 { + t.Fatalf("expected 0 message parts after clear, got %d", count) + } +} func TestStoreAddAndGetMessages(t *testing.T) { s := openTestStore(t) From ea2107e8a939a07621a8866f0757e504d081cec0 Mon Sep 17 00:00:00 2001 From: wenjie Date: Mon, 13 Apr 2026 11:23:55 +0800 Subject: [PATCH 2/6] build(release): split core builds from release-only artifacts - add a dedicated build-release-artifacts target for Android bundle packaging - switch CI and release workflows to Corepack-managed pnpm with cache support - pin the frontend pnpm version and make dependency installs deterministic - inject version metadata into launcher binaries in GoReleaser - update build documentation to reflect the new workflow --- .github/workflows/build.yml | 10 ++++++++++ .github/workflows/create_dmg.yml | 24 +++++++++++++++--------- .github/workflows/nightly.yml | 12 +++++++++--- .github/workflows/release.yml | 8 +++++--- .goreleaser.yaml | 16 +++++++++++----- Makefile | 20 ++++++++++++++------ README.fr.md | 18 ++++++++++++++++-- README.id.md | 17 ++++++++++++++++- README.it.md | 17 ++++++++++++++++- README.ja.md | 17 ++++++++++++++++- README.ko.md | 17 ++++++++++++++++- README.md | 25 +++++++++++++++++++++---- README.my.md | 17 ++++++++++++++++- README.pt-br.md | 17 ++++++++++++++++- README.vi.md | 21 ++++++++++++++++++--- README.zh.md | 18 ++++++++++++++++-- web/Makefile | 12 ++++++++---- web/frontend/package.json | 1 + 18 files changed, 240 insertions(+), 47 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 9b89b69ae..a7c066677 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -16,5 +16,15 @@ jobs: with: go-version-file: go.mod + - name: Setup Node.js + uses: actions/setup-node@v6 + with: + node-version: 22 + cache: pnpm + cache-dependency-path: web/frontend/pnpm-lock.yaml + + - name: Setup pnpm + run: corepack enable && corepack install + - name: Build run: make build-all diff --git a/.github/workflows/create_dmg.yml b/.github/workflows/create_dmg.yml index e03357566..a2221bb70 100644 --- a/.github/workflows/create_dmg.yml +++ b/.github/workflows/create_dmg.yml @@ -17,29 +17,35 @@ jobs: with: ref: main - # 1. 安装指定版本的 Go (可选,但推荐) + # 1. Install Go from go.mod - name: Setup Go uses: actions/setup-go@v6 with: go-version-file: go.mod - # 2. 安装 pnpm - - name: Install pnpm - run: brew install pnpm + - name: Setup Node.js + uses: actions/setup-node@v6 + with: + node-version: 22 + cache: pnpm + cache-dependency-path: web/frontend/pnpm-lock.yaml - # 3. 运行你的 Makefile 编译二进制文件 + - name: Setup pnpm + run: corepack enable && corepack install + + # 3. Build the application bundle - name: Build with Make run: make build ARCH=${{ matrix.arch }} && make build-macos-app ARCH=${{ matrix.arch }} - # 4. 签名 + # 4. Apply ad-hoc signing - name: Ad-hoc Sign run: codesign --force --deep --sign - "build/PicoClaw Launcher.app" - # 5. 安装打包工具 + # 5. Install the DMG packaging tool - name: Install create-dmg run: brew install create-dmg - # 6. 执行打包命令 + # 6. Create the DMG - name: Create DMG run: | mkdir -p dist @@ -54,7 +60,7 @@ jobs: "dist/picoclaw-${{ matrix.arch }}.dmg" \ "build/PicoClaw Launcher.app" - # 7. 上传文件到 GitHub Artifacts (供你下载) + # 7. Upload the DMG as a GitHub artifact - name: Upload DMG uses: actions/upload-artifact@v7 with: diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index a5002fec5..7e8c7111c 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -51,9 +51,11 @@ jobs: uses: actions/setup-node@v6 with: node-version: 22 + cache: pnpm + cache-dependency-path: web/frontend/pnpm-lock.yaml - name: Setup pnpm - run: corepack enable && corepack prepare pnpm@latest --activate + run: corepack enable && corepack install - name: Set up QEMU uses: docker/setup-qemu-action@v4 @@ -97,6 +99,11 @@ jobs: MACOS_NOTARY_KEY_ID: ${{ secrets.MACOS_NOTARY_KEY_ID }} MACOS_NOTARY_KEY: ${{ secrets.MACOS_NOTARY_KEY }} + - name: Build release-only artifacts + run: | + sudo apt-get install -y zip + make build-release-artifacts + - name: Update nightly release env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} @@ -123,7 +130,7 @@ jobs: # Collect release artifacts from goreleaser dist/ ASSETS=() - for f in dist/*.tar.gz dist/*.zip dist/*.deb dist/*.rpm dist/checksums.txt; do + for f in dist/*.tar.gz dist/*.zip dist/*.deb dist/*.rpm dist/checksums.txt build/picoclaw-android-universal.zip; do [ -f "$f" ] && ASSETS+=("$f") done @@ -135,4 +142,3 @@ jobs: --prerelease \ --latest=false \ "${ASSETS[@]}" - diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index aab9cf874..8d7bc02ad 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -69,9 +69,11 @@ jobs: uses: actions/setup-node@v6 with: node-version: 22 + cache: pnpm + cache-dependency-path: web/frontend/pnpm-lock.yaml - name: Setup pnpm - run: corepack enable && corepack prepare pnpm@latest --activate + run: corepack enable && corepack install - name: Set up QEMU uses: docker/setup-qemu-action@v4 @@ -110,13 +112,13 @@ jobs: MACOS_NOTARY_KEY_ID: ${{ secrets.MACOS_NOTARY_KEY_ID }} MACOS_NOTARY_KEY: ${{ secrets.MACOS_NOTARY_KEY }} - - name: Build and upload Android arm64 + - name: Build and upload release-only artifacts shell: bash env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | sudo apt-get install -y zip - make build-android-bundle + make build-release-artifacts gh release upload "${{ inputs.tag }}" \ build/picoclaw-android-universal.zip \ --clobber diff --git a/.goreleaser.yaml b/.goreleaser.yaml index 9c26de34f..b20856110 100644 --- a/.goreleaser.yaml +++ b/.goreleaser.yaml @@ -9,11 +9,9 @@ git: before: hooks: - - go mod tidy - go generate ./... - - sh -c 'cd web/frontend && pnpm install && pnpm build:backend' - - go install github.com/tc-hib/go-winres@latest - - go-winres make --in web/backend/winres/winres.json --out web/backend/rsrc --product-version={{ .Version }} --file-version={{ .Version }} + - sh -c 'cd web/frontend && CI=true pnpm install --frozen-lockfile && pnpm build:backend' + - sh -c 'GOBIN="$(go env GOPATH)/bin"; mkdir -p "$GOBIN"; go install github.com/tc-hib/go-winres@v0.3.3 && "$GOBIN/go-winres" make --in web/backend/winres/winres.json --out web/backend/rsrc --product-version={{ .Version }} --file-version={{ .Version }}' builds: - id: picoclaw @@ -27,7 +25,7 @@ builds: - -X github.com/sipeed/picoclaw/pkg/config.Version={{ .Version }} - -X github.com/sipeed/picoclaw/pkg/config.GitCommit={{ .ShortCommit }} - -X github.com/sipeed/picoclaw/pkg/config.BuildTime={{ .Date }} - - -X github.com/sipeed/picoclaw/pkg/config.GoVersion={{ .Env.GOVERSION }} + - -X github.com/sipeed/picoclaw/pkg/config.GoVersion={{ with index .Env "GOVERSION" }}{{ . }}{{ else }}unknown{{ end }} goos: - linux - windows @@ -67,6 +65,10 @@ builds: - stdjson ldflags: - -s -w + - -X github.com/sipeed/picoclaw/pkg/config.Version={{ .Version }} + - -X github.com/sipeed/picoclaw/pkg/config.GitCommit={{ .ShortCommit }} + - -X github.com/sipeed/picoclaw/pkg/config.BuildTime={{ .Date }} + - -X github.com/sipeed/picoclaw/pkg/config.GoVersion={{ with index .Env "GOVERSION" }}{{ . }}{{ else }}unknown{{ end }} goos: - linux - windows @@ -106,6 +108,10 @@ builds: - stdjson ldflags: - -s -w + - -X github.com/sipeed/picoclaw/pkg/config.Version={{ .Version }} + - -X github.com/sipeed/picoclaw/pkg/config.GitCommit={{ .ShortCommit }} + - -X github.com/sipeed/picoclaw/pkg/config.BuildTime={{ .Date }} + - -X github.com/sipeed/picoclaw/pkg/config.GoVersion={{ with index .Env "GOVERSION" }}{{ . }}{{ else }}unknown{{ end }} goos: - linux - windows diff --git a/Makefile b/Makefile index beddd1138..717273efa 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -.PHONY: all build install uninstall clean help test +.PHONY: all build install uninstall clean help test build-core-all build-release-artifacts # Build variables BINARY_NAME=picoclaw @@ -217,7 +217,9 @@ build-launcher-android-arm64: @echo "Building picoclaw-launcher for android/arm64..." @mkdir -p $(BUILD_DIR) @$(MAKE) -C web build-android-arm64 \ - OUTPUT="$(CURDIR)/$(BUILD_DIR)/picoclaw-launcher-android-arm64" + OUTPUT_ANDROID_ARM64="$(CURDIR)/$(BUILD_DIR)/picoclaw-launcher-android-arm64" \ + GO='$(GO)' \ + LDFLAGS='$(LDFLAGS)' @echo "Build complete: $(BUILD_DIR)/picoclaw-launcher-android-arm64" ## build-android-bundle: Build core and launcher for all Android architectures and package as universal zip @@ -240,8 +242,8 @@ build-android-bundle: generate build-pi-zero: build-linux-arm build-linux-arm64 @echo "Pi Zero 2 W builds: $(BUILD_DIR)/$(BINARY_NAME)-linux-arm (32-bit), $(BUILD_DIR)/$(BINARY_NAME)-linux-arm64 (64-bit)" -## build-all: Build picoclaw for all platforms -build-all: generate +## build-core-all: Build the picoclaw core binary for all Makefile-managed platforms +build-core-all: generate @echo "Building for multiple platforms..." @mkdir -p $(BUILD_DIR) GOOS=linux GOARCH=amd64 $(GO) build $(GOFLAGS) -ldflags "$(LDFLAGS)" -o $(BUILD_DIR)/$(BINARY_NAME)-linux-amd64 ./$(CMD_DIR) @@ -257,8 +259,14 @@ build-all: generate GOOS=windows GOARCH=amd64 $(GO) build $(GOFLAGS) -ldflags "$(LDFLAGS)" -o $(BUILD_DIR)/$(BINARY_NAME)-windows-amd64.exe ./$(CMD_DIR) GOOS=netbsd GOARCH=amd64 $(GO) build $(GOFLAGS) -ldflags "$(LDFLAGS)" -o $(BUILD_DIR)/$(BINARY_NAME)-netbsd-amd64 ./$(CMD_DIR) GOOS=netbsd GOARCH=arm64 $(GO) build $(GOFLAGS) -ldflags "$(LDFLAGS)" -o $(BUILD_DIR)/$(BINARY_NAME)-netbsd-arm64 ./$(CMD_DIR) - @$(MAKE) build-android-bundle - @echo "All builds complete" + @echo "Core builds complete" + +## build-all: Build the picoclaw core binary for all Makefile-managed platforms +build-all: build-core-all + +## build-release-artifacts: Build release-only artifacts that sit outside GoReleaser +build-release-artifacts: build-android-bundle + @echo "Release artifact builds complete" ## install: Install picoclaw to system and copy builtin skills install: build diff --git a/README.fr.md b/README.fr.md index 3b2552f6d..ecafefdc7 100644 --- a/README.fr.md +++ b/README.fr.md @@ -167,21 +167,32 @@ Vous pouvez aussi télécharger le binaire pour votre plateforme depuis la page ### Compiler depuis les sources (pour le développement) +Prérequis : + +- Go 1.25+ +- Node.js 22+ avec Corepack activé pour les builds Web UI / launcher + ```bash git clone https://github.com/sipeed/picoclaw.git cd picoclaw make deps +# Installer le gestionnaire de paquets frontend déclaré par le dépôt +(cd web/frontend && corepack install) + # Compiler le binaire principal make build # Compiler le Web UI Launcher (requis pour le mode WebUI) make build-launcher -# Compiler pour plusieurs plateformes +# Compiler les binaires core pour toutes les plateformes gérées par le Makefile make build-all +# Compiler les artefacts de release empaquetés séparément des sorties principales de GoReleaser +make build-release-artifacts + # Compiler pour Raspberry Pi Zero 2 W (32 bits : make build-linux-arm ; 64 bits : make build-linux-arm64) make build-pi-zero @@ -189,6 +200,10 @@ make build-pi-zero make install ``` +`make build-all` compile les binaires core de `picoclaw` pour toutes les plateformes gérées par le Makefile. + +`make build-release-artifacts` compile les artefacts de release empaquetés séparément des sorties principales de GoReleaser. + **Raspberry Pi Zero 2 W :** Utilisez le binaire correspondant à votre OS : Raspberry Pi OS 32 bits -> `make build-linux-arm` ; 64 bits -> `make build-linux-arm64`. Ou exécutez `make build-pi-zero` pour compiler les deux. ## 🚀 Guide de démarrage rapide @@ -621,4 +636,3 @@ WeChat : WeChat group QR code - diff --git a/README.id.md b/README.id.md index 5aa7b58f5..f57d2f0bc 100644 --- a/README.id.md +++ b/README.id.md @@ -164,21 +164,32 @@ Atau, unduh binary untuk platform Anda dari halaman [GitHub Releases](https://gi ### Build dari source (untuk pengembangan) +Prasyarat: + +- Go 1.25+ +- Node.js 22+ dengan Corepack aktif untuk build Web UI / launcher + ```bash git clone https://github.com/sipeed/picoclaw.git cd picoclaw make deps +# Instal package manager frontend yang dideklarasikan repo +(cd web/frontend && corepack install) + # Build binary inti make build # Build Web UI Launcher (diperlukan untuk mode WebUI) make build-launcher -# Build untuk berbagai platform +# Build binary inti untuk semua platform yang dikelola Makefile make build-all +# Build artefak rilis yang dikemas terpisah dari output utama GoReleaser +make build-release-artifacts + # Build untuk Raspberry Pi Zero 2 W (32-bit: make build-linux-arm; 64-bit: make build-linux-arm64) make build-pi-zero @@ -186,6 +197,10 @@ make build-pi-zero make install ``` +`make build-all` membangun binary inti `picoclaw` untuk semua platform yang dikelola Makefile. + +`make build-release-artifacts` membangun artefak rilis yang dikemas terpisah dari output utama GoReleaser. + **Raspberry Pi Zero 2 W:** Gunakan binary yang sesuai dengan OS Anda: Raspberry Pi OS 32-bit -> `make build-linux-arm`; 64-bit -> `make build-linux-arm64`. Atau jalankan `make build-pi-zero` untuk build keduanya. ## 🚀 Panduan Memulai Cepat diff --git a/README.it.md b/README.it.md index 57dd014b3..4c18f6f5b 100644 --- a/README.it.md +++ b/README.it.md @@ -164,21 +164,32 @@ In alternativa, scarica il binario per la tua piattaforma dalla pagina delle [Gi ### Compila dai sorgenti (per lo sviluppo) +Prerequisiti: + +- Go 1.25+ +- Node.js 22+ con Corepack abilitato per le build Web UI / launcher + ```bash git clone https://github.com/sipeed/picoclaw.git cd picoclaw make deps +# Installa il package manager frontend dichiarato dal repository +(cd web/frontend && corepack install) + # Compila il binario core make build # Compila il Web UI Launcher (necessario per la modalità WebUI) make build-launcher -# Compila per più piattaforme +# Compila i binari core per tutte le piattaforme gestite dal Makefile make build-all +# Compila gli artefatti di release impacchettati separatamente dagli output principali di GoReleaser +make build-release-artifacts + # Compila per Raspberry Pi Zero 2 W (32-bit: make build-linux-arm; 64-bit: make build-linux-arm64) make build-pi-zero @@ -186,6 +197,10 @@ make build-pi-zero make install ``` +`make build-all` compila i binari core di `picoclaw` per tutte le piattaforme gestite dal Makefile. + +`make build-release-artifacts` compila gli artefatti di release impacchettati separatamente dagli output principali di GoReleaser. + **Raspberry Pi Zero 2 W:** Usa il binario che corrisponde al tuo OS: Raspberry Pi OS 32-bit -> `make build-linux-arm`; 64-bit -> `make build-linux-arm64`. Oppure esegui `make build-pi-zero` per compilare entrambi. ## 🚀 Guida Rapida diff --git a/README.ja.md b/README.ja.md index 64bff9ee9..0ad159a53 100644 --- a/README.ja.md +++ b/README.ja.md @@ -164,21 +164,32 @@ PicoClaw はほぼすべての Linux デバイスにデプロイできます! ### ソースからビルド(開発用) +前提条件: + +- Go 1.25+ +- Web UI / launcher のビルドには Corepack を有効にした Node.js 22+ + ```bash git clone https://github.com/sipeed/picoclaw.git cd picoclaw make deps +# リポジトリで宣言されたフロントエンド用パッケージマネージャーをインストール +(cd web/frontend && corepack install) + # コアバイナリをビルド make build # Web UI Launcher をビルド(WebUI モードに必要) make build-launcher -# 複数プラットフォーム向けビルド +# Makefile が管理するすべてのプラットフォーム向けにコアバイナリをビルド make build-all +# メインの GoReleaser 出力とは別にパッケージ化されるリリース専用成果物をビルド +make build-release-artifacts + # Raspberry Pi Zero 2 W 向けビルド(32-bit: make build-linux-arm; 64-bit: make build-linux-arm64) make build-pi-zero @@ -186,6 +197,10 @@ make build-pi-zero make install ``` +`make build-all` は、Makefile が管理するすべてのプラットフォーム向けにコアの `picoclaw` バイナリをビルドします。 + +`make build-release-artifacts` は、メインの GoReleaser 出力とは別にパッケージ化されるリリース専用成果物をビルドします。 + **Raspberry Pi Zero 2 W:** OS に合ったバイナリを使用してください:32-bit Raspberry Pi OS → `make build-linux-arm`、64-bit → `make build-linux-arm64`。または `make build-pi-zero` で両方をビルド。 ## 🚀 クイックスタートガイド diff --git a/README.ko.md b/README.ko.md index 341c09812..5f99dd32e 100644 --- a/README.ko.md +++ b/README.ko.md @@ -164,21 +164,32 @@ PicoClaw는 사실상 거의 모든 Linux 장치에 배포할 수 있습니다! ### 소스에서 빌드(개발용) +필수 사항: + +- Go 1.25+ +- Web UI / launcher 빌드를 위한 Corepack 활성화된 Node.js 22+ + ```bash git clone https://github.com/sipeed/picoclaw.git cd picoclaw make deps +# 저장소에 선언된 프런트엔드 패키지 매니저 설치 +(cd web/frontend && corepack install) + # 코어 바이너리 빌드 make build # WebUI 런처 빌드 (WebUI 모드에 필요) make build-launcher -# 여러 플랫폼용 빌드 +# Makefile이 관리하는 모든 플랫폼용 코어 바이너리 빌드 make build-all +# 메인 GoReleaser 출력과 별도로 패키징되는 릴리스 전용 산출물 빌드 +make build-release-artifacts + # Raspberry Pi Zero 2 W용 빌드 (32비트: make build-linux-arm, 64비트: make build-linux-arm64) make build-pi-zero @@ -186,6 +197,10 @@ make build-pi-zero make install ``` +`make build-all`은 Makefile이 관리하는 모든 플랫폼용 핵심 `picoclaw` 바이너리를 빌드합니다. + +`make build-release-artifacts`는 메인 GoReleaser 출력과 별도로 패키징되는 릴리스 전용 산출물을 빌드합니다. + **Raspberry Pi Zero 2 W:** OS에 맞는 바이너리를 사용하세요. 32비트 Raspberry Pi OS는 `make build-linux-arm`, 64비트는 `make build-linux-arm64`입니다. 또는 `make build-pi-zero`로 둘 다 빌드할 수 있습니다. ## 🚀 빠른 시작 가이드 diff --git a/README.md b/README.md index eb0d389d2..fd082f6bf 100644 --- a/README.md +++ b/README.md @@ -164,28 +164,45 @@ Alternatively, download the binary for your platform from the [GitHub Releases]( ### Build from source (for development) +Prerequisites: + +- Go 1.25+ +- Node.js 22+ with Corepack enabled for Web UI / launcher builds + ```bash git clone https://github.com/sipeed/picoclaw.git cd picoclaw make deps -# Build core binary +# Install frontend package manager declared by the repo +(cd web/frontend && corepack install) + +# Build the core binary for the current platform make build -# Build Web UI Launcher (required for WebUI mode) +# Build the Web UI Launcher (required for WebUI mode) make build-launcher -# Build for multiple platforms +# Build core binaries for all Makefile-managed platforms make build-all -# Build for Raspberry Pi Zero 2 W (32-bit: make build-linux-arm; 64-bit: make build-linux-arm64) +# Build release-only artifacts packaged separately from the main GoReleaser outputs +make build-release-artifacts + +# Build for Raspberry Pi Zero 2 W +# 32-bit: make build-linux-arm +# 64-bit: make build-linux-arm64 make build-pi-zero # Build and install make install ``` +`make build-all` builds the core `picoclaw` binaries for all Makefile-managed platforms. + +`make build-release-artifacts` builds release-only artifacts that are packaged separately from the main GoReleaser outputs. + **Raspberry Pi Zero 2 W:** Use the binary that matches your OS: 32-bit Raspberry Pi OS -> `make build-linux-arm`; 64-bit -> `make build-linux-arm64`. Or run `make build-pi-zero` to build both. ## 🚀 Quick Start Guide diff --git a/README.my.md b/README.my.md index f8e602f83..a5719c696 100644 --- a/README.my.md +++ b/README.my.md @@ -165,20 +165,31 @@ Muat turun binari untuk platform anda dari halaman [GitHub Releases](https://git ### Bina dari sumber (untuk pembangunan) +Prasyarat: + +- Go 1.25+ +- Node.js 22+ dengan Corepack diaktifkan untuk binaan Web UI / launcher + ```bash git clone https://github.com/sipeed/picoclaw.git cd picoclaw make deps +# Pasang pengurus pakej frontend yang diisytiharkan oleh repositori +(cd web/frontend && corepack install) + # Bina binari teras make build # Bina Pelancar Web UI (diperlukan untuk mod WebUI) make build-launcher -# Bina untuk pelbagai platform +# Bina binari teras untuk semua platform yang diuruskan oleh Makefile make build-all +# Bina artifak keluaran yang dibungkus berasingan daripada output utama GoReleaser +make build-release-artifacts + # Bina untuk Raspberry Pi Zero 2 W (32-bit: make build-linux-arm; 64-bit: make build-linux-arm64) make build-pi-zero @@ -186,6 +197,10 @@ make build-pi-zero make install ``` +`make build-all` membina binari teras `picoclaw` untuk semua platform yang diuruskan oleh Makefile. + +`make build-release-artifacts` membina artifak keluaran yang dibungkus berasingan daripada output utama GoReleaser. + **Raspberry Pi Zero 2 W:** Gunakan binari yang sepadan dengan OS anda: Raspberry Pi OS 32-bit -> `make build-linux-arm`; 64-bit -> `make build-linux-arm64`. Atau jalankan `make build-pi-zero` untuk membina kedua-duanya. ## 🚀 Panduan Permulaan Pantas diff --git a/README.pt-br.md b/README.pt-br.md index 65d23d1d1..d9b64c959 100644 --- a/README.pt-br.md +++ b/README.pt-br.md @@ -164,21 +164,32 @@ Alternativamente, baixe o binário para sua plataforma na página de [GitHub Rel ### Compilar a partir do código-fonte (para desenvolvimento) +Pré-requisitos: + +- Go 1.25+ +- Node.js 22+ com Corepack habilitado para builds do Web UI / launcher + ```bash git clone https://github.com/sipeed/picoclaw.git cd picoclaw make deps +# Instalar o gerenciador de pacotes de frontend declarado pelo repositório +(cd web/frontend && corepack install) + # Compilar o binário principal make build # Compilar o Web UI Launcher (necessário para o modo WebUI) make build-launcher -# Compilar para múltiplas plataformas +# Compilar os binários core para todas as plataformas gerenciadas pelo Makefile make build-all +# Compilar os artefatos de release empacotados separadamente das saídas principais do GoReleaser +make build-release-artifacts + # Compilar para Raspberry Pi Zero 2 W (32-bit: make build-linux-arm; 64-bit: make build-linux-arm64) make build-pi-zero @@ -186,6 +197,10 @@ make build-pi-zero make install ``` +`make build-all` compila os binários core do `picoclaw` para todas as plataformas gerenciadas pelo Makefile. + +`make build-release-artifacts` compila os artefatos de release empacotados separadamente das saídas principais do GoReleaser. + **Raspberry Pi Zero 2 W:** Use o binário que corresponde ao seu SO: Raspberry Pi OS 32-bit -> `make build-linux-arm`; 64-bit -> `make build-linux-arm64`. Ou execute `make build-pi-zero` para compilar ambos. ## 🚀 Guia de Início Rápido diff --git a/README.vi.md b/README.vi.md index 1d70d0615..3475830fb 100644 --- a/README.vi.md +++ b/README.vi.md @@ -164,21 +164,32 @@ Ngoài ra, tải binary cho nền tảng của bạn từ trang [GitHub Releases ### Xây dựng từ mã nguồn (để phát triển) +Yêu cầu: + +- Go 1.25+ +- Node.js 22+ với Corepack được bật cho các bản build Web UI / launcher + ```bash git clone https://github.com/sipeed/picoclaw.git cd picoclaw make deps -# Build core binary +# Cài đặt trình quản lý gói frontend được khai báo bởi repo +(cd web/frontend && corepack install) + +# Build binary lõi make build -# Build Web UI Launcher (required for WebUI mode) +# Build Web UI Launcher (cần cho chế độ WebUI) make build-launcher -# Build for multiple platforms +# Build các binary lõi cho mọi nền tảng do Makefile quản lý make build-all +# Build các release artifact được đóng gói tách biệt với các đầu ra chính của GoReleaser +make build-release-artifacts + # Build for Raspberry Pi Zero 2 W (32-bit: make build-linux-arm; 64-bit: make build-linux-arm64) make build-pi-zero @@ -186,6 +197,10 @@ make build-pi-zero make install ``` +`make build-all` build các binary lõi `picoclaw` cho mọi nền tảng do Makefile quản lý. + +`make build-release-artifacts` build các release artifact được đóng gói tách biệt với các đầu ra chính của GoReleaser. + **Raspberry Pi Zero 2 W:** Sử dụng binary phù hợp với hệ điều hành của bạn: Raspberry Pi OS 32-bit -> `make build-linux-arm`; 64-bit -> `make build-linux-arm64`. Hoặc chạy `make build-pi-zero` để xây dựng cả hai. ## 🚀 Hướng dẫn Khởi động Nhanh diff --git a/README.zh.md b/README.zh.md index e61ff7e28..ddb3bb230 100644 --- a/README.zh.md +++ b/README.zh.md @@ -164,21 +164,32 @@ PicoClaw 几乎可以部署在任何 Linux 设备上! ### 从源码构建(开发用) +前置要求: + +- Go 1.25+ +- Node.js 22+,并启用 Corepack(用于 Web UI / launcher 构建) + ```bash git clone https://github.com/sipeed/picoclaw.git cd picoclaw make deps +# 安装仓库声明的前端包管理器 +(cd web/frontend && corepack install) + # 构建核心二进制文件 make build # 构建 Web UI Launcher(WebUI 模式必需) make build-launcher -# 为多平台构建 +# 为 Makefile 管理的所有平台构建核心二进制文件 make build-all +# 构建独立于主 GoReleaser 输出之外的发布附加产物 +make build-release-artifacts + # 为 Raspberry Pi Zero 2 W 构建(32位: make build-linux-arm; 64位: make build-linux-arm64) make build-pi-zero @@ -186,6 +197,10 @@ make build-pi-zero make install ``` +`make build-all` 会为所有由 Makefile 管理的平台构建核心 `picoclaw` 二进制文件。 + +`make build-release-artifacts` 会构建独立于主 GoReleaser 输出之外打包的发布附加产物。 + **Raspberry Pi Zero 2 W:** 请使用与系统匹配的二进制文件:32 位 Raspberry Pi OS → `make build-linux-arm`;64 位 → `make build-linux-arm64`。或运行 `make build-pi-zero` 同时构建两者。 ## 🚀 快速开始 @@ -619,4 +634,3 @@ WeChat: - diff --git a/web/Makefile b/web/Makefile index cf5ea774a..4dca810e7 100644 --- a/web/Makefile +++ b/web/Makefile @@ -12,6 +12,7 @@ BUILD_DIR=build OUTPUT?=$(BUILD_DIR)/picoclaw-launcher OUTPUT_ANDROID_ARM64?=$(BUILD_DIR)/picoclaw-launcher-android-arm64 FRONTEND_DIR=frontend +FRONTEND_INSTALL_STAMP=$(FRONTEND_DIR)/node_modules/.picoclaw-install-stamp BACKEND_DIR=backend BACKEND_DIST=$(BACKEND_DIR)/dist PICOCLAW_BINARY_NAME=picoclaw @@ -105,11 +106,14 @@ build-android-bundle: build-frontend @echo "All Android launcher builds complete" build-frontend: - @if [ ! -d $(FRONTEND_DIR)/node_modules ] || \ - [ $(FRONTEND_DIR)/package.json -nt $(FRONTEND_DIR)/node_modules ] || \ - [ $(FRONTEND_DIR)/pnpm-lock.yaml -nt $(FRONTEND_DIR)/node_modules ]; then \ + @expected_stamp="$$(cat $(FRONTEND_DIR)/package.json $(FRONTEND_DIR)/pnpm-lock.yaml | cksum | awk '{print $$1 ":" $$2}')"; \ + if [ ! -d $(FRONTEND_DIR)/node_modules ] || \ + [ ! -x $(FRONTEND_DIR)/node_modules/.bin/tsc ] || \ + [ ! -f $(FRONTEND_INSTALL_STAMP) ] || \ + [ "$$(cat $(FRONTEND_INSTALL_STAMP) 2>/dev/null)" != "$$expected_stamp" ]; then \ echo "Installing frontend dependencies..."; \ - cd $(FRONTEND_DIR) && pnpm install --frozen-lockfile; \ + (cd $(FRONTEND_DIR) && CI=true pnpm install --frozen-lockfile) && \ + printf '%s\n' "$$expected_stamp" > $(FRONTEND_INSTALL_STAMP); \ fi @echo "Building frontend..." @cd $(FRONTEND_DIR) && pnpm build:backend diff --git a/web/frontend/package.json b/web/frontend/package.json index 51e6f1dd9..40d5cf3d8 100644 --- a/web/frontend/package.json +++ b/web/frontend/package.json @@ -3,6 +3,7 @@ "private": true, "version": "0.0.0", "type": "module", + "packageManager": "pnpm@10.33.0", "engines": { "node": "^20.19.0 || ^22.13.0 || >=24" }, From b8819bdbffcd59835544db1682e5b90e7c478533 Mon Sep 17 00:00:00 2001 From: Liu Yuan Date: Mon, 13 Apr 2026 11:29:02 +0800 Subject: [PATCH 3/6] fix(seahorse): drop/recreate FTS5 triggers so existing DBs get corrected bodies MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `CREATE TRIGGER IF NOT EXISTS` does not replace an existing trigger body. On databases created with the old (buggy) DELETE-FROM-FTS syntax, the bad trigger body persisted after code updates. Now we explicitly DROP each trigger before CREATE, so any existing DB gets the corrected body on next startup — no manual DB deletion required. --- pkg/seahorse/schema.go | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/pkg/seahorse/schema.go b/pkg/seahorse/schema.go index bf32d548b..aa829358b 100644 --- a/pkg/seahorse/schema.go +++ b/pkg/seahorse/schema.go @@ -118,26 +118,35 @@ func runSchema(db *sql.DB) error { `CREATE INDEX IF NOT EXISTS idx_summary_messages_message ON summary_messages(message_id)`, `CREATE INDEX IF NOT EXISTS idx_context_items_conv ON context_items(conversation_id, ordinal)`, + // Drop old triggers before creating new ones so existing DBs get updated bodies. + // (CREATE TRIGGER IF NOT EXISTS does NOT replace an existing trigger body.) + `DROP TRIGGER IF EXISTS summaries_ai`, + `DROP TRIGGER IF EXISTS summaries_ad`, + `DROP TRIGGER IF EXISTS summaries_au`, + `DROP TRIGGER IF EXISTS messages_ai`, + `DROP TRIGGER IF EXISTS messages_ad`, + `DROP TRIGGER IF EXISTS messages_au`, + // FTS5 triggers to keep summaries_fts in sync with summaries table - `CREATE TRIGGER IF NOT EXISTS summaries_ai AFTER INSERT ON summaries BEGIN + `CREATE TRIGGER summaries_ai AFTER INSERT ON summaries BEGIN INSERT INTO summaries_fts (summary_id, content) VALUES (new.summary_id, new.content); END`, - `CREATE TRIGGER IF NOT EXISTS summaries_ad AFTER DELETE ON summaries BEGIN + `CREATE TRIGGER summaries_ad AFTER DELETE ON summaries BEGIN DELETE FROM summaries_fts WHERE summary_id = old.summary_id; END`, - `CREATE TRIGGER IF NOT EXISTS summaries_au AFTER UPDATE ON summaries BEGIN + `CREATE TRIGGER summaries_au AFTER UPDATE ON summaries BEGIN DELETE FROM summaries_fts WHERE summary_id = old.summary_id; INSERT INTO summaries_fts (summary_id, content) VALUES (new.summary_id, new.content); END`, // FTS5 triggers to keep messages_fts in sync with messages table - `CREATE TRIGGER IF NOT EXISTS messages_ai AFTER INSERT ON messages BEGIN + `CREATE TRIGGER messages_ai AFTER INSERT ON messages BEGIN INSERT INTO messages_fts (message_id, content) VALUES (new.message_id, new.content); END`, - `CREATE TRIGGER IF NOT EXISTS messages_ad AFTER DELETE ON messages BEGIN + `CREATE TRIGGER messages_ad AFTER DELETE ON messages BEGIN DELETE FROM messages_fts WHERE message_id = old.message_id; END`, - `CREATE TRIGGER IF NOT EXISTS messages_au AFTER UPDATE ON messages BEGIN + `CREATE TRIGGER messages_au AFTER UPDATE ON messages BEGIN DELETE FROM messages_fts WHERE message_id = old.message_id; INSERT INTO messages_fts (message_id, content) VALUES (new.message_id, new.content); END`, From 4532627f715310a96fb894b8dccde62a0d35c1de Mon Sep 17 00:00:00 2001 From: Liu Yuan Date: Mon, 13 Apr 2026 11:37:50 +0800 Subject: [PATCH 4/6] test(seahorse): add TestTriggerMigration for old-DB trigger upgrade path Verifies that databases created with the old buggy FTS5 DELETE trigger body are correctly migrated by runSchema: the old trigger causes DELETE to fail, and after re-running runSchema (which drops and recreates the triggers with the corrected body) DELETE works normally. --- pkg/seahorse/schema_test.go | 78 +++++++++++++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) diff --git a/pkg/seahorse/schema_test.go b/pkg/seahorse/schema_test.go index e11e6e96e..f3d6a3650 100644 --- a/pkg/seahorse/schema_test.go +++ b/pkg/seahorse/schema_test.go @@ -194,6 +194,84 @@ func TestMigrationSummaryParentsPK(t *testing.T) { } } +func TestTriggerMigration(t *testing.T) { + db := openTestDB(t) + + // Run schema once to create tables and (correct) triggers + if err := runSchema(db); err != nil { + t.Fatalf("runSchema: %v", err) + } + + // Drop correct triggers and recreate them with the old buggy body. + // The old trigger used INSERT INTO fts VALUES('delete', ...) which is wrong + // for non-external-content FTS5 tables. + oldSummariesDelete := `CREATE TRIGGER summaries_ad AFTER DELETE ON summaries BEGIN + INSERT INTO summaries_fts (summaries_fts, summary_id, content) VALUES('delete', old.summary_id, old.content); + END` + oldMessagesDelete := `CREATE TRIGGER messages_ad AFTER DELETE ON messages BEGIN + INSERT INTO messages_fts (messages_fts, message_id, content) VALUES('delete', old.message_id, old.content); + END` + + for _, sql := range []string{ + `DROP TRIGGER IF EXISTS summaries_ad`, + `DROP TRIGGER IF EXISTS messages_ad`, + oldSummariesDelete, + oldMessagesDelete, + } { + if _, err := db.Exec(sql); err != nil { + t.Fatalf("setup old trigger: %v", err) + } + } + + // Insert a conversation and summary so we have something to delete + _, err := db.Exec(`INSERT INTO conversations (session_key) VALUES ('old-db-test')`) + if err != nil { + t.Fatalf("insert conversation: %v", err) + } + _, err = db.Exec(`INSERT INTO summaries (summary_id, conversation_id, kind, depth, content, token_count) + VALUES ('old-sum', 1, 'leaf', 0, 'old content', 5)`) + if err != nil { + t.Fatalf("insert summary: %v", err) + } + + // The old trigger body is wrong for normal FTS5 — DELETE should fail. + _, err = db.Exec(`DELETE FROM summaries WHERE summary_id = 'old-sum'`) + if err == nil { + t.Error("expected error from old buggy trigger, but DELETE succeeded") + } else { + t.Logf("old trigger correctly causes error: %v", err) + } + + // Now runSchema again — this drops and recreates the triggers with correct bodies. + err = runSchema(db) + if err != nil { + t.Fatalf("runSchema migration: %v", err) + } + + // Insert again so we have data to delete + _, err = db.Exec(`INSERT INTO summaries (summary_id, conversation_id, kind, depth, content, token_count) + VALUES ('migrated-sum', 1, 'leaf', 0, 'new content', 5)`) + if err != nil { + t.Fatalf("insert after migration: %v", err) + } + + // DELETE should now work with the corrected trigger body. + _, err = db.Exec(`DELETE FROM summaries WHERE summary_id = 'migrated-sum'`) + if err != nil { + t.Fatalf("DELETE after migration failed (trigger not corrected): %v", err) + } + + // Verify the summary is gone + var count int + err = db.QueryRow(`SELECT count(*) FROM summaries WHERE summary_id = 'migrated-sum'`).Scan(&count) + if err != nil { + t.Fatalf("query after delete: %v", err) + } + if count != 0 { + t.Errorf("summary should be gone after DELETE, got count=%d", count) + } +} + func TestFTS5SQLConstants(t *testing.T) { db := openTestDB(t) From d73a0e89b4780ca0cc7816e069e61beffd7f12aa Mon Sep 17 00:00:00 2001 From: wenjie Date: Mon, 13 Apr 2026 11:52:35 +0800 Subject: [PATCH 5/6] build(release): move Android bundle publishing into GoReleaser - build the Android universal bundle from GoReleaser hooks - attach the bundle as a release asset - remove the separate post-release upload step - simplify Make targets around cross-platform builds --- .github/workflows/build.yml | 2 +- .github/workflows/nightly.yml | 9 ++++----- .github/workflows/release.yml | 15 ++++----------- .goreleaser.yaml | 3 +++ Makefile | 13 +++---------- README.fr.md | 8 -------- README.id.md | 7 ------- README.it.md | 7 ------- README.ja.md | 7 ------- README.ko.md | 7 ------- README.md | 13 +++---------- README.my.md | 7 ------- README.pt-br.md | 7 ------- README.vi.md | 7 ------- README.zh.md | 8 -------- 15 files changed, 18 insertions(+), 102 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index a7c066677..f21e3ef5f 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -26,5 +26,5 @@ jobs: - name: Setup pnpm run: corepack enable && corepack install - - name: Build + - name: Build core binaries run: make build-all diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index 7e8c7111c..f713c4db2 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -77,6 +77,9 @@ jobs: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} + - name: Install zip + run: sudo apt-get install -y zip + - name: Create local tag for GoReleaser run: git tag "${{ steps.version.outputs.version }}" @@ -92,6 +95,7 @@ jobs: DOCKERHUB_IMAGE_NAME: ${{ vars.DOCKERHUB_REPOSITORY }} GOVERSION: ${{ steps.setup-go.outputs.go-version }} GORELEASER_CURRENT_TAG: ${{ steps.version.outputs.version }} + INCLUDE_ANDROID_BUNDLE: "true" NIGHTLY_BUILD: "true" MACOS_SIGN_P12: ${{ secrets.MACOS_SIGN_P12 }} MACOS_SIGN_PASSWORD: ${{ secrets.MACOS_SIGN_PASSWORD }} @@ -99,11 +103,6 @@ jobs: MACOS_NOTARY_KEY_ID: ${{ secrets.MACOS_NOTARY_KEY_ID }} MACOS_NOTARY_KEY: ${{ secrets.MACOS_NOTARY_KEY }} - - name: Build release-only artifacts - run: | - sudo apt-get install -y zip - make build-release-artifacts - - name: Update nightly release env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 8d7bc02ad..41218032c 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -95,6 +95,9 @@ jobs: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} + - name: Install zip + run: sudo apt-get install -y zip + - name: Run GoReleaser uses: goreleaser/goreleaser-action@v7 with: @@ -106,23 +109,13 @@ jobs: GITHUB_REPOSITORY_OWNER: ${{ github.repository_owner }} DOCKERHUB_IMAGE_NAME: ${{ vars.DOCKERHUB_REPOSITORY }} GOVERSION: ${{ steps.setup-go.outputs.go-version }} + INCLUDE_ANDROID_BUNDLE: "true" MACOS_SIGN_P12: ${{ secrets.MACOS_SIGN_P12 }} MACOS_SIGN_PASSWORD: ${{ secrets.MACOS_SIGN_PASSWORD }} MACOS_NOTARY_ISSUER_ID: ${{ secrets.MACOS_NOTARY_ISSUER_ID }} MACOS_NOTARY_KEY_ID: ${{ secrets.MACOS_NOTARY_KEY_ID }} MACOS_NOTARY_KEY: ${{ secrets.MACOS_NOTARY_KEY }} - - name: Build and upload release-only artifacts - shell: bash - env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: | - sudo apt-get install -y zip - make build-release-artifacts - gh release upload "${{ inputs.tag }}" \ - build/picoclaw-android-universal.zip \ - --clobber - - name: Apply release flags shell: bash env: diff --git a/.goreleaser.yaml b/.goreleaser.yaml index b20856110..d8c51b069 100644 --- a/.goreleaser.yaml +++ b/.goreleaser.yaml @@ -12,6 +12,7 @@ before: - go generate ./... - sh -c 'cd web/frontend && CI=true pnpm install --frozen-lockfile && pnpm build:backend' - sh -c 'GOBIN="$(go env GOPATH)/bin"; mkdir -p "$GOBIN"; go install github.com/tc-hib/go-winres@v0.3.3 && "$GOBIN/go-winres" make --in web/backend/winres/winres.json --out web/backend/rsrc --product-version={{ .Version }} --file-version={{ .Version }}' + - sh -c 'if [ "${INCLUDE_ANDROID_BUNDLE:-}" = "true" ]; then make build-android-bundle; fi' builds: - id: picoclaw @@ -251,6 +252,8 @@ changelog: release: disable: '{{ isEnvSet "NIGHTLY_BUILD" }}' + extra_files: + - glob: ./build/picoclaw-android-universal.zip footer: >- --- diff --git a/Makefile b/Makefile index 717273efa..afaa7c29a 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -.PHONY: all build install uninstall clean help test build-core-all build-release-artifacts +.PHONY: all build install uninstall clean help test build-all # Build variables BINARY_NAME=picoclaw @@ -242,8 +242,8 @@ build-android-bundle: generate build-pi-zero: build-linux-arm build-linux-arm64 @echo "Pi Zero 2 W builds: $(BUILD_DIR)/$(BINARY_NAME)-linux-arm (32-bit), $(BUILD_DIR)/$(BINARY_NAME)-linux-arm64 (64-bit)" -## build-core-all: Build the picoclaw core binary for all Makefile-managed platforms -build-core-all: generate +## build-all: Build the picoclaw core binary for all Makefile-managed platforms +build-all: generate @echo "Building for multiple platforms..." @mkdir -p $(BUILD_DIR) GOOS=linux GOARCH=amd64 $(GO) build $(GOFLAGS) -ldflags "$(LDFLAGS)" -o $(BUILD_DIR)/$(BINARY_NAME)-linux-amd64 ./$(CMD_DIR) @@ -261,13 +261,6 @@ build-core-all: generate GOOS=netbsd GOARCH=arm64 $(GO) build $(GOFLAGS) -ldflags "$(LDFLAGS)" -o $(BUILD_DIR)/$(BINARY_NAME)-netbsd-arm64 ./$(CMD_DIR) @echo "Core builds complete" -## build-all: Build the picoclaw core binary for all Makefile-managed platforms -build-all: build-core-all - -## build-release-artifacts: Build release-only artifacts that sit outside GoReleaser -build-release-artifacts: build-android-bundle - @echo "Release artifact builds complete" - ## install: Install picoclaw to system and copy builtin skills install: build @echo "Installing $(BINARY_NAME)..." diff --git a/README.fr.md b/README.fr.md index ecafefdc7..570365d00 100644 --- a/README.fr.md +++ b/README.fr.md @@ -190,9 +190,6 @@ make build-launcher # Compiler les binaires core pour toutes les plateformes gérées par le Makefile make build-all -# Compiler les artefacts de release empaquetés séparément des sorties principales de GoReleaser -make build-release-artifacts - # Compiler pour Raspberry Pi Zero 2 W (32 bits : make build-linux-arm ; 64 bits : make build-linux-arm64) make build-pi-zero @@ -200,10 +197,6 @@ make build-pi-zero make install ``` -`make build-all` compile les binaires core de `picoclaw` pour toutes les plateformes gérées par le Makefile. - -`make build-release-artifacts` compile les artefacts de release empaquetés séparément des sorties principales de GoReleaser. - **Raspberry Pi Zero 2 W :** Utilisez le binaire correspondant à votre OS : Raspberry Pi OS 32 bits -> `make build-linux-arm` ; 64 bits -> `make build-linux-arm64`. Ou exécutez `make build-pi-zero` pour compiler les deux. ## 🚀 Guide de démarrage rapide @@ -635,4 +628,3 @@ Discord : WeChat : WeChat group QR code - diff --git a/README.id.md b/README.id.md index f57d2f0bc..f4257f338 100644 --- a/README.id.md +++ b/README.id.md @@ -187,9 +187,6 @@ make build-launcher # Build binary inti untuk semua platform yang dikelola Makefile make build-all -# Build artefak rilis yang dikemas terpisah dari output utama GoReleaser -make build-release-artifacts - # Build untuk Raspberry Pi Zero 2 W (32-bit: make build-linux-arm; 64-bit: make build-linux-arm64) make build-pi-zero @@ -197,10 +194,6 @@ make build-pi-zero make install ``` -`make build-all` membangun binary inti `picoclaw` untuk semua platform yang dikelola Makefile. - -`make build-release-artifacts` membangun artefak rilis yang dikemas terpisah dari output utama GoReleaser. - **Raspberry Pi Zero 2 W:** Gunakan binary yang sesuai dengan OS Anda: Raspberry Pi OS 32-bit -> `make build-linux-arm`; 64-bit -> `make build-linux-arm64`. Atau jalankan `make build-pi-zero` untuk build keduanya. ## 🚀 Panduan Memulai Cepat diff --git a/README.it.md b/README.it.md index 4c18f6f5b..b559cda2e 100644 --- a/README.it.md +++ b/README.it.md @@ -187,9 +187,6 @@ make build-launcher # Compila i binari core per tutte le piattaforme gestite dal Makefile make build-all -# Compila gli artefatti di release impacchettati separatamente dagli output principali di GoReleaser -make build-release-artifacts - # Compila per Raspberry Pi Zero 2 W (32-bit: make build-linux-arm; 64-bit: make build-linux-arm64) make build-pi-zero @@ -197,10 +194,6 @@ make build-pi-zero make install ``` -`make build-all` compila i binari core di `picoclaw` per tutte le piattaforme gestite dal Makefile. - -`make build-release-artifacts` compila gli artefatti di release impacchettati separatamente dagli output principali di GoReleaser. - **Raspberry Pi Zero 2 W:** Usa il binario che corrisponde al tuo OS: Raspberry Pi OS 32-bit -> `make build-linux-arm`; 64-bit -> `make build-linux-arm64`. Oppure esegui `make build-pi-zero` per compilare entrambi. ## 🚀 Guida Rapida diff --git a/README.ja.md b/README.ja.md index 0ad159a53..0e6483be6 100644 --- a/README.ja.md +++ b/README.ja.md @@ -187,9 +187,6 @@ make build-launcher # Makefile が管理するすべてのプラットフォーム向けにコアバイナリをビルド make build-all -# メインの GoReleaser 出力とは別にパッケージ化されるリリース専用成果物をビルド -make build-release-artifacts - # Raspberry Pi Zero 2 W 向けビルド(32-bit: make build-linux-arm; 64-bit: make build-linux-arm64) make build-pi-zero @@ -197,10 +194,6 @@ make build-pi-zero make install ``` -`make build-all` は、Makefile が管理するすべてのプラットフォーム向けにコアの `picoclaw` バイナリをビルドします。 - -`make build-release-artifacts` は、メインの GoReleaser 出力とは別にパッケージ化されるリリース専用成果物をビルドします。 - **Raspberry Pi Zero 2 W:** OS に合ったバイナリを使用してください:32-bit Raspberry Pi OS → `make build-linux-arm`、64-bit → `make build-linux-arm64`。または `make build-pi-zero` で両方をビルド。 ## 🚀 クイックスタートガイド diff --git a/README.ko.md b/README.ko.md index 5f99dd32e..e520ffd29 100644 --- a/README.ko.md +++ b/README.ko.md @@ -187,9 +187,6 @@ make build-launcher # Makefile이 관리하는 모든 플랫폼용 코어 바이너리 빌드 make build-all -# 메인 GoReleaser 출력과 별도로 패키징되는 릴리스 전용 산출물 빌드 -make build-release-artifacts - # Raspberry Pi Zero 2 W용 빌드 (32비트: make build-linux-arm, 64비트: make build-linux-arm64) make build-pi-zero @@ -197,10 +194,6 @@ make build-pi-zero make install ``` -`make build-all`은 Makefile이 관리하는 모든 플랫폼용 핵심 `picoclaw` 바이너리를 빌드합니다. - -`make build-release-artifacts`는 메인 GoReleaser 출력과 별도로 패키징되는 릴리스 전용 산출물을 빌드합니다. - **Raspberry Pi Zero 2 W:** OS에 맞는 바이너리를 사용하세요. 32비트 Raspberry Pi OS는 `make build-linux-arm`, 64비트는 `make build-linux-arm64`입니다. 또는 `make build-pi-zero`로 둘 다 빌드할 수 있습니다. ## 🚀 빠른 시작 가이드 diff --git a/README.md b/README.md index fd082f6bf..bbe48061a 100644 --- a/README.md +++ b/README.md @@ -187,9 +187,6 @@ make build-launcher # Build core binaries for all Makefile-managed platforms make build-all -# Build release-only artifacts packaged separately from the main GoReleaser outputs -make build-release-artifacts - # Build for Raspberry Pi Zero 2 W # 32-bit: make build-linux-arm # 64-bit: make build-linux-arm64 @@ -199,10 +196,6 @@ make build-pi-zero make install ``` -`make build-all` builds the core `picoclaw` binaries for all Makefile-managed platforms. - -`make build-release-artifacts` builds release-only artifacts that are packaged separately from the main GoReleaser outputs. - **Raspberry Pi Zero 2 W:** Use the binary that matches your OS: 32-bit Raspberry Pi OS -> `make build-linux-arm`; 64-bit -> `make build-linux-arm64`. Or run `make build-pi-zero` to build both. ## 🚀 Quick Start Guide @@ -232,7 +225,7 @@ picoclaw-launcher WebUI Launcher

-**Getting started:** +**Getting started:** Open the WebUI, then: **1)** Configure a Provider (add your LLM API key) -> **2)** Configure a Channel (e.g., Telegram) -> **3)** Start the Gateway -> **4)** Chat! @@ -310,7 +303,7 @@ picoclaw-launcher-tui TUI Launcher

-**Getting started:** +**Getting started:** Use the TUI menus to: **1)** Configure a Provider -> **2)** Configure a Channel -> **3)** Start the Gateway -> **4)** Chat! @@ -385,7 +378,7 @@ This creates `~/.picoclaw/config.json` and the workspace directory. ``` > See `config/config.example.json` in the repo for a complete configuration template with all available options. -> +> > Please note: config.example.json format is version 0, with sensitive codes in it, and will be auto migrated to version 1+, then, the config.json will only store insensitive data, the sensitive codes will be stored in .security.yml, if you need manually modify the codes, please see `docs/security_configuration.md` for more details. diff --git a/README.my.md b/README.my.md index a5719c696..255773263 100644 --- a/README.my.md +++ b/README.my.md @@ -187,9 +187,6 @@ make build-launcher # Bina binari teras untuk semua platform yang diuruskan oleh Makefile make build-all -# Bina artifak keluaran yang dibungkus berasingan daripada output utama GoReleaser -make build-release-artifacts - # Bina untuk Raspberry Pi Zero 2 W (32-bit: make build-linux-arm; 64-bit: make build-linux-arm64) make build-pi-zero @@ -197,10 +194,6 @@ make build-pi-zero make install ``` -`make build-all` membina binari teras `picoclaw` untuk semua platform yang diuruskan oleh Makefile. - -`make build-release-artifacts` membina artifak keluaran yang dibungkus berasingan daripada output utama GoReleaser. - **Raspberry Pi Zero 2 W:** Gunakan binari yang sepadan dengan OS anda: Raspberry Pi OS 32-bit -> `make build-linux-arm`; 64-bit -> `make build-linux-arm64`. Atau jalankan `make build-pi-zero` untuk membina kedua-duanya. ## 🚀 Panduan Permulaan Pantas diff --git a/README.pt-br.md b/README.pt-br.md index d9b64c959..36d65d8c4 100644 --- a/README.pt-br.md +++ b/README.pt-br.md @@ -187,9 +187,6 @@ make build-launcher # Compilar os binários core para todas as plataformas gerenciadas pelo Makefile make build-all -# Compilar os artefatos de release empacotados separadamente das saídas principais do GoReleaser -make build-release-artifacts - # Compilar para Raspberry Pi Zero 2 W (32-bit: make build-linux-arm; 64-bit: make build-linux-arm64) make build-pi-zero @@ -197,10 +194,6 @@ make build-pi-zero make install ``` -`make build-all` compila os binários core do `picoclaw` para todas as plataformas gerenciadas pelo Makefile. - -`make build-release-artifacts` compila os artefatos de release empacotados separadamente das saídas principais do GoReleaser. - **Raspberry Pi Zero 2 W:** Use o binário que corresponde ao seu SO: Raspberry Pi OS 32-bit -> `make build-linux-arm`; 64-bit -> `make build-linux-arm64`. Ou execute `make build-pi-zero` para compilar ambos. ## 🚀 Guia de Início Rápido diff --git a/README.vi.md b/README.vi.md index 3475830fb..67845d073 100644 --- a/README.vi.md +++ b/README.vi.md @@ -187,9 +187,6 @@ make build-launcher # Build các binary lõi cho mọi nền tảng do Makefile quản lý make build-all -# Build các release artifact được đóng gói tách biệt với các đầu ra chính của GoReleaser -make build-release-artifacts - # Build for Raspberry Pi Zero 2 W (32-bit: make build-linux-arm; 64-bit: make build-linux-arm64) make build-pi-zero @@ -197,10 +194,6 @@ make build-pi-zero make install ``` -`make build-all` build các binary lõi `picoclaw` cho mọi nền tảng do Makefile quản lý. - -`make build-release-artifacts` build các release artifact được đóng gói tách biệt với các đầu ra chính của GoReleaser. - **Raspberry Pi Zero 2 W:** Sử dụng binary phù hợp với hệ điều hành của bạn: Raspberry Pi OS 32-bit -> `make build-linux-arm`; 64-bit -> `make build-linux-arm64`. Hoặc chạy `make build-pi-zero` để xây dựng cả hai. ## 🚀 Hướng dẫn Khởi động Nhanh diff --git a/README.zh.md b/README.zh.md index ddb3bb230..329fedb86 100644 --- a/README.zh.md +++ b/README.zh.md @@ -187,9 +187,6 @@ make build-launcher # 为 Makefile 管理的所有平台构建核心二进制文件 make build-all -# 构建独立于主 GoReleaser 输出之外的发布附加产物 -make build-release-artifacts - # 为 Raspberry Pi Zero 2 W 构建(32位: make build-linux-arm; 64位: make build-linux-arm64) make build-pi-zero @@ -197,10 +194,6 @@ make build-pi-zero make install ``` -`make build-all` 会为所有由 Makefile 管理的平台构建核心 `picoclaw` 二进制文件。 - -`make build-release-artifacts` 会构建独立于主 GoReleaser 输出之外打包的发布附加产物。 - **Raspberry Pi Zero 2 W:** 请使用与系统匹配的二进制文件:32 位 Raspberry Pi OS → `make build-linux-arm`;64 位 → `make build-linux-arm64`。或运行 `make build-pi-zero` 同时构建两者。 ## 🚀 快速开始 @@ -633,4 +626,3 @@ WeChat: WeChat group QR code - From 6a870cb2601828c95bec790a752947119708028b Mon Sep 17 00:00:00 2001 From: wenjie Date: Mon, 13 Apr 2026 11:56:43 +0800 Subject: [PATCH 6/6] ci(build): remove unused Node.js and pnpm setup from core build workflow --- .github/workflows/build.yml | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index f21e3ef5f..def19c3e5 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -16,15 +16,5 @@ jobs: with: go-version-file: go.mod - - name: Setup Node.js - uses: actions/setup-node@v6 - with: - node-version: 22 - cache: pnpm - cache-dependency-path: web/frontend/pnpm-lock.yaml - - - name: Setup pnpm - run: corepack enable && corepack install - - name: Build core binaries run: make build-all