diff --git a/.gitignore b/.gitignore index 3ee526c..d2903ee 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,26 @@ -node_modules -database.sqlite -.env.local +**/node_modules/ +# build outputs +dist/ +out/ +packages/**/dist/ +packages/**/out/ +packages/**/.vite/ +packages/**/.turbo/ +packages/**/.cache/ + +# OS / logs +.DS_Store +*.log +*.log.* + +# local examples (often large/volatile) +examples/ + +# runtime data / secrets +database.sqlite +*.sqlite +*.sqlite3 +*.db +*.db-journal +.env.local.worktrees diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..7a52e3e --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,121 @@ +# CLAUDE.md + +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. + +## Package Manager + +Use bare `pnpm` (v8 or v10+ both work). The `engines.pnpm` constraint is `>=8.15.9`. + +```bash +pnpm install +pnpm -F geekgeekrun-ui dev +``` + +## Key Commands + +All UI development happens in `packages/ui`. The `dev`/`build`/`start` scripts automatically rebuild `sqlite-plugin` first. + +```bash +# Electron app (main entry point for users) +pnpm -F geekgeekrun-ui dev # development mode +pnpm -F geekgeekrun-ui build # production build +pnpm -F geekgeekrun-ui build:win # Windows installer + +# Lint & format (run from packages/ui) +pnpm -F geekgeekrun-ui lint # eslint --fix +pnpm -F geekgeekrun-ui format # prettier --write + +# Type checking (run from packages/ui) +pnpm -F geekgeekrun-ui typecheck # both node + web + +# SQLite plugin (must build before UI if changed) +pnpm -F @geekgeekrun/sqlite-plugin build +pnpm -F @geekgeekrun/sqlite-plugin dev # watch mode +``` + +## Architecture + +This is a **pnpm monorepo** (`packages/*`) — a desktop automation tool for BOSS Zhipin (job platform) built on Electron + Puppeteer. + +### Two Sides + +**Job-seeker side** (older, more complete): +- `packages/geek-auto-start-chat-with-boss` — core automation: LLM-based resume matching, auto-chat +- `packages/run-core-of-geek-auto-start-chat-with-boss` — headless daemon entry point + +**Recruiter side** (newer, under active development): +- `packages/boss-auto-browse-and-chat` — core automation: browse candidates, filter, send greetings, extract resumes via Canvas hook +- `packages/run-core-of-boss-auto-browse` — headless daemon entry point + +### Electron App (`packages/ui`) + +The app uses **mode-based process routing**: every worker subprocess is actually the same Electron binary launched with a `--mode` flag. `src/main/index.ts` switches on `runMode`: + +- No `--mode` (default) → opens the settings GUI window (`OPEN_SETTING_WINDOW`) +- `bossRecommendMain` / `bossChatPageMain` / `bossAutoBrowseAndChatMain` → recruiter workers +- `geekAutoStartWithBossMain` → job-seeker worker +- `launchDaemon` → background daemon process (manages worker subprocesses via `@geekgeekrun/pm`) + +The GUI renderer is **Vue 3 + Pinia + Vue Router** served by electron-vite. IPC handlers live in `src/main/flow/OPEN_SETTING_WINDOW/ipc/index.ts`. + +### Plugin/Hook System + +All automation cores (both sides) use **tapable** (`AsyncSeriesHook`, `AsyncSeriesWaterfallHook`) for extensibility. The sqlite-plugin and webhook features attach to these hooks: + +``` +Worker flow file + → constructs hooks object + → new SqlitePlugin(dbPath).apply(hooks) + → calls core function (startBossAutoBrowse / startBossChatPageProcess / startGeekAutoChat) +``` + +### Shared Packages + +- `packages/sqlite-plugin` — TypeORM + better-sqlite3, compiled TypeScript (`dist/`). Entities: `CandidateInfo`, `CandidateContactLog`, `ChatStartupLog`. **Must be built before UI.** +- `packages/utils` — ESM utilities: sleep, OpenAI/GPT requests, Puppeteer helpers +- `packages/pm` — Electron multi-process daemon/worker management +- `packages/laodeng` / `packages/puppeteer-extra-plugin-laodeng` — anti-bot-detection Puppeteer plugin + +### Storage Layout + +``` +~/.geekgeekrun/ + config/ + boss-recruiter.json # recruiter automation config + candidate-filter.json # candidate filter criteria + webhook.json # webhook integration config + storage/ + boss-cookies.json # persisted BOSS Zhipin cookies + boss-local-storage.json # persisted localStorage + public.db # SQLite database +``` + +### Recruiter Automation Stack (boss-auto-browse-and-chat) + +Key files and their roles: +- `index.mjs` — `startBossAutoBrowse()`: browser launch, login, main loop +- `candidate-processor.mjs` — DOM parsing (`#recommend-list > div > ul > li`), candidate filtering +- `chat-handler.mjs` — clicking 打招呼 (`button.btn-greet`), handling popup (`button.btn-sure-v2`), processCandidate +- `resume-extractor.mjs` — network intercept + iframe Canvas fillText hook (MutationObserver pattern, see `plan/cv_canvas_solution.md`) +- `constant.mjs` — all CSS selectors and URLs; **update here first when BOSS site HTML changes** + +Anti-detection: stealth + laodeng + anonymize-ua plugins; all clicks via `ghost-cursor` (`createHumanCursor`); random delays via `sleepWithRandomDelay`. + +**Known post-login popups** — all must be auto-dismissed or automation will hang: +- **Governance notice** (`dialog-uninstall-extension`) — appears every login; handled by `dismissGovernanceNoticeDialog(page)` in `index.mjs`, called after login in both `launchBrowserAndNavigateToChat` and `startBossAutoBrowse`. Confirm button is `div.confirm-btn` (a `
~/.geekgeekrun/storage/boss-chrome-profile/
+ 按队列逐职位自动执行「推荐牛人」和「沟通页」两个任务。各自的运行策略请分别在对应页面配置: +
boss-llm.json
{{ jobRubricPreview }}
chatPage.attachmentResume.skipDownload: true
{{ testResult.formattedBody }}