cc-haha/.gitignore
小橙子 355b7294b9
feat(desktop): seed cc-haha-builtin marketplace into Electron package (#50)
* feat(desktop): seed cc-haha-builtin marketplace into Electron package

Wires the missing desktop side of the plugin-seed mechanism. The CLI
side (src/utils/plugins/{pluginDirectories,marketplaceManager}.ts) has
been on main for a while and exposes `getPluginSeedDirs()` +
`registerSeedMarketplaces()` reading `CLAUDE_CODE_PLUGIN_SEED_DIR`. But
the desktop side never set that env var or copied any seed into the
Electron package, so:

- v0.5.11 packaged users see whatever marketplaces they manually
  registered (typically just `reverse-engineering` from a one-off
  `plugin marketplace add ./plugins`).
- The image-gen plugin added in PR #49 was invisible after install
  because no mechanism shipped it inside the Electron bundle.

What this commit adds

- `desktop/scripts/build-plugin-seed.ts` (new)
  - Mirrors the repo's `plugins/` directory into
    `desktop/plugin-seed/marketplaces/cc-haha-builtin/`.
  - Generates `desktop/plugin-seed/known_marketplaces.json` with a
    placeholder `installLocation`. registerSeedMarketplaces() recomputes
    the real path at runtime via findSeedMarketplaceLocation(), so the
    placeholder is intentional — handles cases like multi-stage Docker
    builds where the seed lives at a different path than where it was
    built.

- `desktop/package.json`
  - Adds `build:plugin-seed` script.
  - Prepends it to `electron:dev` and `electron:build` so the seed is
    always fresh before the app starts (or is packaged).
  - Adds `plugin-seed/**` to electron-builder `files` and `asarUnpack`
    so the seed dir ships inside the .app/.exe but stays outside the
    asar archive (CC reads files from disk, not from asar).

- `desktop/electron/services/sidecarManager.ts`
  - Threads `desktopRoot` through `buildSidecarEnv(...)` and adds
    `CLAUDE_CODE_PLUGIN_SEED_DIR=<desktopRoot>/plugin-seed` so the
    spawned server sidecar finds the seed.

- `src/server/index.ts`
  - Calls `registerSeedMarketplaces()` at server boot so the seeded
    marketplace appears in `~/.claude/plugins/known_marketplaces.json`
    and the desktop's Settings → Plugins page picks it up.
  - Fire-and-forget (`void ...`) rather than `await`, since
    `startServer` is sync and the registration takes ~ms; the seeded
    marketplace appears in the UI within 1-2 seconds of server boot.
    (The original drafted version used `await` inside a sync function,
    which doesn't compile — fixed in this commit.)

- `.gitignore` — excludes `desktop/plugin-seed/` from version control
  (regenerated on every electron build, never committed).

End-to-end flow after this lands

  build time:
    bun run electron:build
      → bun run build:plugin-seed
          → desktop/plugin-seed/marketplaces/cc-haha-builtin/{plugin/,...}
          → desktop/plugin-seed/known_marketplaces.json
      → bun run build:sidecars + electron-builder
          → packages plugin-seed/** into .app/.exe (asarUnpack ensures
            the dir is on disk, not inside asar)

  runtime (first launch):
    Electron main → spawn server sidecar with
      CLAUDE_CODE_PLUGIN_SEED_DIR=<resourcesDir>/plugin-seed
    Server sidecar starts → registerSeedMarketplaces()
      → reads seed/known_marketplaces.json
      → calls findSeedMarketplaceLocation() to resolve real path
      → writes resolved entry into ~/.claude/plugins/known_marketplaces.json
    Desktop Settings → Plugins reads ~/.claude/plugins/known_marketplaces.json
      → shows cc-haha-builtin marketplace with both reverse-engineering
        and image-gen plugins available to install.

Verification

- `bun run desktop/scripts/build-plugin-seed.ts` produces the seed
  with both plugins present, valid JSON, in expected dir layout.
- `bun run lint` (desktop): tsc --noEmit clean — no remaining type
  errors from the await→void change or the buildSidecarEnv signature
  change.
- Seed marketplace.json plugins array confirmed includes both
  reverse-engineering (v0.4.6, post-#33) and image-gen (v1.0.0, from
  #49).

Tested: build script runs locally; tsc clean.
Not-tested: live `bun run electron:package` end-to-end pack on this
host (no codesign, slow). The packaging-side wiring (asarUnpack +
files) is configuration-only and matches established patterns
(node_modules/node-pty/**, src-tauri/binaries/**); no behaviour change
to the existing package layout besides adding plugin-seed/.

Risk: low — additive across the board, no existing path changes
behaviour. The fire-and-forget marketplace registration cannot block
boot; if it fails, the worst case is the user sees no seeded
marketplace and can manually re-add it (existing flow).

Confidence: high
Scope-risk: narrow — desktop wiring + 1 server-side hook call.

* test(server): add seed-marketplaces-startup integration tests

Covers the registerSeedMarketplaces() integration that startServer()

now invokes at boot. Four cases:

- env var unset → returns false, no write

- valid seed → returns true, writes primary entry with resolved (non-placeholder) installLocation

- repeat call → primary entry stays intact (returns false on the no-op call but the previously-written entry survives)

- nonexistent seed dir → returns false, no crash

Resolves the change-policy 'Server product files changed without a server test file in the PR' block on PR #50.

* test(desktop): pass desktopRoot to buildSidecarEnv in sidecar test

buildSidecarEnv now requires desktopRoot to derive CLAUDE_CODE_PLUGIN_SEED_DIR. The existing 'passes portable config' test still called the old 2-arg signature, breaking both desktop-checks (vitest) and desktop-native-checks (tsc) on PR #50.

Tested:

  - bunx vitest run electron/services/sidecarManager.test.ts -t 'passes portable config' — 1 passed

  - tsc -p electron/tsconfig.json — clean

Confidence: high

Scope-risk: narrow

---------

Co-authored-by: 你的姓名 <you@example.com>
2026-06-15 23:18:34 +08:00

100 lines
1.7 KiB
Plaintext

.env
.env.*
!.env.example
node_modules
openspec
.DS_Store
# Computer Use runtime (auto-generated)
.runtime/
extracted-natives/
# Adapter attachment cache (created at runtime by AttachmentStore when
# running adapter tests or the feishu/telegram adapters locally)
.lark-attachments/
.tg-attachments/
# Playwright MCP snapshots & logs
.playwright-mcp/
# OMX state/logs
.omx/
# E2E screenshots
e2e-*.png
# Local/generated artifacts
artifacts/
# Desktop build output
desktop/dist/
desktop/electron-dist/
desktop/build-artifacts/
desktop/src-tauri/binaries/
desktop/src-tauri/target/
desktop/src-tauri/gen/
desktop/package-lock.json
# Desktop brand asset candidates (keep only selected ones in public/)
desktop/brand-assets/
# Claude local config & auto-generated
.claude/*
# …but project-level agents under .claude/agents/ are part of the repo and
# should be shared with other contributors. Whitelist them explicitly.
!.claude/agents/
!.claude/agents/**
# Kiro IDE local config (steering, specs, hooks) — local only
.kiro/
# Superpowers plans & specs (local only)
docs/superpowers/
.superpowers/
# Temp server/web logs
.tmp-*.log
# Editor / IDE local config
.vscode/
# codegraph local index (generated by the codegraph tool, not a build artifact)
.codegraph/
# Debug / temp screenshots (root dir only)
/*.png
bug_attachments/
# Private keys & credentials
*.pem
*.key
*.p12
credentials*.json
# TS build cache
*.tsbuildinfo
# Temp markdown snapshots
sidebar-snapshot.md
# VitePress
docs/.vitepress/dist
docs/.vitepress/cache
runtime/__pycache__
# IDE
.idea
# Codex logs
.codex-logs/
# Local AI assistant artifacts (graph, notes)
CLAUDE.md
.mavis/
.opencode/
graphify-out/
.gitignore
# desktop/scripts/build-plugin-seed.ts output
desktop/plugin-seed/