{"owner":"gaozhangmin","repo":"aliyunpan","hasSkills":true,"hasMcp":false,"mcpConfig":null,"found":["CLAUDE.md","AGENTS.md"],"skills":{"CLAUDE.md":"# CLAUDE.md\n\nThis file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.\n\n## Quick commands\n\n```bash\npnpm install          # pnpm only — never npm/yarn\npnpm dev              # hot-reload Electron dev server (Vite + vue-tsc)\npnpm run build        # version bump → typecheck → vite bundle\npnpm run build:electron  # full build + electron-builder packaging\npnpm run test         # focused Vitest suite (Node env, aria2 + motrix + utils)\npnpm run test:clouddrive-cli  # clouddrive-cli tests only\npnpm run build:mac    # unsigned macOS .dmg/.zip\npnpm run build:mac:signed  # signed + notarized macOS\npnpm run build:linux  # Linux .deb/.AppImage/.pacman\npnpm run build:windows  # Windows .exe/.zip\npnpm run build:all    # cross-platform sequentially\npnpm run config:clean     # blank API keys in src/config.ts (pre-commit hook)\npnpm run config:restore   # restore real keys after commit\n```\n\n## Architecture (Electron + Vue 3 + Vite)\n\n```\nelectron/main/       Electron main process (entry: electron/main/index.ts)\n  core/              Window lifecycle, IPC, auto-update, protocol, dialogs\n  aria/              Aria2c download engine (config, UPnP, runtime)\nelectron/preload/    Preload scripts (IPC bridge)\n\nsrc/                 Vue 3 renderer\n  aliapi/            Alibaba Cloud Drive SDK (files, share, user, etc.)\n  cloudbaidu/        Baidu Netdisk provider\n  cloud123/          123Pan provider\n  cloud115/          115Pan provider\n  pikpak/            PikPak provider\n  onedrive/          OneDrive provider\n  dropbox/           Dropbox provider\n  box/               Box provider\n  quark/             Quark provider\n  cloud139/          CMCloud provider\n  cloud189/          Tianyi Cloud provider\n  pan/               File manager UI (tree, menus, dialogs)\n  media-server/      Jellyfin/Emby/Plex integration\n  down/              Download manager + Aria2 integration\n  layout/            Main layout views (PageVideo, PageMusic, etc.)\n  module/            Feature modules (audioplayer, musicsdk, lyricplayer, theme)\n  store/             Pinia stores\n  components/        Shared Vue components\n  utils/             Shared utilities\n  user/              Auth, account management UI\n\nshared/              Code shared between main + renderer (constants, config keys, UA)\nscripts/             Build scripts, CLI entry points (clouddrive-cli.mjs, clouddrive-mcp.mjs)\nclouddrive-cli/      Standalone CLI + MCP server package (npm: clouddrive-cli)\n  core/              Command implementations, MCP server, upload planning\n  providers/         8 cloud-drive provider implementations\n  media/             Media matching + rename logic\n```\n\nPath aliases: `@shared/*` → `shared/*`, `@main/*` → `electron/main/*`\n\n## Key patterns\n\n- **pnpm only** — lockfile is `pnpm-lock.yaml`; `package-lock.json`/`yarn.lock` are gitignored\n- **Node ≥ 18**\n- **Pre-commit hooks** (`nano-staged.mjs`): prettier + eslint on JS/TS, stylelint + prettier on Vue/CSS, typecheck on changed `src/` files\n- **Formatting**: single quotes, no semicolons, 260 printWidth, no trailing commas, LF, `sortAttributes: true` in Vue\n- **TypeScript**: strict mode, ESNext target, node moduleResolution\n- **Sensitive config**: `scripts/clean-config.js` blanks API keys pre-commit; restore with `pnpm run config:restore`\n- **Vitest**: Node environment only, explicit test directory list in `vitest.config.ts` (not glob patterns). Add new test dirs to config.\n- **CI**: Manual trigger only via `.github/workflows/release.yml`, publishes draft GitHub Release\n\n## clouddrive-cli (AI agent integration)\n\nStandalone CLI + MCP server for agent-driven cloud-drive operations. Supports 8 providers: aliyun, cloud123, 115, baidu, pikpak, onedrive, box, dropbox.\n\nKey bins: `clouddrive-cli` (CLI), `clouddrive-mcp` (MCP server). Both point to `scripts/clouddrive-cli.mjs` and `scripts/clouddrive-mcp.mjs` respectively.\n\nAgent rules when using the CLI:\n1. Discover commands first: `clouddrive-cli list --format json`\n2. Check capabilities: `clouddrive-cli providers capabilities --format json`\n3. Always dry-run before destructive ops\n4. Never invent file IDs — they must come from `files list`/`walk`/`search`/`tree`\n5. Use `--output <file.json>` for large results\n\n## Adding a new cloud-drive provider\n\nFollow the 15-step checklist in `AGENT.md` (OAuth → provider detection → file listing → download/playback → search → thumbnails → file operations → sharing → upload → media scan → folder picker → menu boundaries → properties/recycle bin → tests → verification). The checklist is authoritative — do not ship a provider that only does file listing.\n","AGENTS.md":"# AGENTS.md — BoxPlayer (aliyunpan)\n\n## Quick reference\n\n```bash\npnpm install          # install deps (pnpm only, never npm/yarn)\npnpm dev              # hot-reload Electron dev server\npnpm run build        # typecheck + bundle (vue-tsc --noEmit && vite build)\npnpm run test         # focused Vitest suite (not full repo)\npnpm run test:clouddrive-cli  # clouddrive-cli tests only\n```\n\n## Package manager: pnpm only\n\nLockfile is `pnpm-lock.yaml`. `package-lock.json` and `yarn.lock` are in `.gitignore`.\nNever use `npm install` or `yarn`.\n\n## Node version\n\n`engines.node >= 22.12.0` in package.json. Electron 40 requires Node 22.12+ during install/build.\n\n## Build pipeline order matters\n\n`pnpm run build` runs **version bump → typecheck → vite bundle**. The version bump (`version.mjs`) auto-increments the patch version in package.json before every build. The build removes `dist/` and `release/` directories on start.\n\n`pnpm run build:electron` calls `build` first, then runs `electron-builder`.\n\nFor platform-specific packaging:\n```bash\npnpm run build:mac       # unsigned macOS\npnpm run build:mac:signed  # signed + notarized\npnpm run build:linux\npnpm run build:windows\npnpm run build:all       # cross-platform, sequential\n```\n\n## Sensitive config: generated secrets\n\nPrivate client IDs, client secrets, API keys, and private API URLs live outside git:\n\n```bash\npnpm run secrets:generate\n```\n\nLocal development reads them from `.env.local` and generates `src/secrets.generated.ts`. GitHub Actions reads the same keys from GitHub Secrets and runs `scripts/generate-secrets.mjs --mode=ci --strict` before building.\n\n`.env.local` and `src/secrets.generated.ts` are ignored and must never be committed. `src/config.ts` should import generated secrets or use placeholders, not contain real private values.\n\n## Architecture: Electron + Vue 3 + Vite\n\n| Directory | Purpose |\n|---|---|\n| `electron/main/` | Electron main process (entry: `electron/main/index.ts`) |\n| `electron/preload/` | Preload scripts |\n| `src/` | Vue 3 renderer (components, views, stores, API modules) |\n| `shared/` | Code shared between main + renderer |\n| `scripts/` | Build, CLI entry points, config management |\n| `clouddrive-cli/` | Standalone CLI package (published to npm as `clouddrive-cli`) |\n\nPath aliases (set in `tsconfig.json`, `vite.config.ts`, `vitest.config.ts`):\n- `@shared/*` → `shared/*`\n- `@main/*` → `electron/main/*`\n\nCloud provider API modules in `src/`: `aliapi/`, `cloudbaidu/`, `cloud123/`, `cloud115/`, `pikpak/`, `onedrive/`, `box/`, `dropbox/`, `quark/`, `cloud139/`, `cloud189/`.\n\n## Testing: Vitest, Node environment, selective includes\n\nTests run in Node environment (not jsdom). The `vitest.config.ts` lists explicit test directories — not a glob over `**/*.test.ts`. Tests outside these paths are not picked up:\n\n- `electron/main/core/__tests__/`, `electron/main/aria/__tests__/`\n- `shared/__tests__/`, `scripts/__tests__/`\n- `src/down/motrix-integration/`, `src/media-server/__tests__/`\n- `src/utils/__tests__/`, `src/aliapi/__tests__/`\n- `src/pikpak/__tests__/`, `src/quark/__tests__/`\n- `src/dropbox/__tests__/`, `src/onedrive/__tests__/`, `src/box/__tests__/`\n- `clouddrive-cli/__tests__/`\n\nDefault `pnpm run test` runs only a subset (aria2 tests, motrix integration, a couple utils files).\n\nWhen adding tests in a new directory, update `vitest.config.ts`.\n\n## Pre-commit hooks\n\nDo not rely on pre-commit cleanup for secrets. Secret safety is handled by keeping real values in ignored/generated files and GitHub Secrets.\n\n## Formatting conventions\n\nFrom `.prettierrc`:\n- Single quotes, no semicolons\n- 260 printWidth (very wide)\n- No trailing commas\n- LF line endings\n- `sortAttributes: true` on HTML/Vue\n\n## TypeScript\n\n- `tsconfig.json` targets ESNext, moduleResolution node, strict mode, `@shared/*` and `@main/*` path aliases\n- Includes `src/` and `shared/`, excludes `shared/__tests__`\n- References `tsconfig.node.json` for Electron-side code\n\n## Provider Integration Checklist\n\nWhen adding a new cloud-drive provider, implement the following in order unless the user explicitly excludes a step. Do not stop after only wiring file listing. Sync/change-listening is not required by default.\n\n### 1. Account And Auth\n\n- Read the official OAuth/API documentation and prefer stable API versions.\n- Add `src/<provider>/auth.ts` with auth URL, authorization-code token exchange, and refresh token support.\n- Define `CLIENT_ID` / `CLIENT_SECRET` placeholder constants, defaulting to empty strings.\n- Add app key / secret fields to `.env.example`, `src/secrets.example.ts`, and `scripts/generate-secrets.mjs`.\n- Add the provider to `tokenfrom` in `src/user/userstore.ts`.\n- Wire login, token refresh, and drive loading in `src/user/userdal.ts`.\n- Add login entry points in `src/user/UserLogin.vue` and `src/user/UserInfo.vue`.\n\n### 2. Provider Detection And Drive Model\n\n- Add `is<Provider>User` in `src/aliapi/utils.ts`.\n- Update `GetDriveID` and `GetDriveType`, modeling third-party drives as a single-root drive.\n- Filter unsupported virtual directories in `src/pan/PanLeft.vue` and `src/pan/pantreestore.ts`.\n\n### 3. File List And Detail\n\n- Add `src/<provider>/dirfilelist.ts`.\n- Implement root listing, child directory pagination, and file detail.\n- Map official file models to `IAliGetFileModel`; at minimum fill `drive_id`, `file_id`, `parent_file_id`, `name`, `isDir`, `category`, `icon`, `size`, `time`, `thumbnail`, and `content_hash`.\n- Store provider-specific path, parent id, download URL, or similar metadata in `description`.\n- Wire root loading, directory listing, and search-listing branches in `src/pan/pandal.ts`.\n- Wire provider file detail in `src/aliapi/file.ts` `ApiFileInfo`.\n\n### 4. Download And Playback\n\n- Wire provider direct download URLs in `src/aliapi/file.ts` `ApiFileDownloadUrl`.\n- Third-party drives usually do not have Aliyun transcode APIs; `ApiVideoPreviewUrl` / `ApiAudioPreviewUrl` should return `暂无转码信息` or `undefined`, letting playback use the raw download URL.\n- Wire same-directory playlist loading in `src/layout/PageVideo.vue`, `src/utils/openfile.ts`, and `src/utils/playerhelper.ts`.\n- Confirm clicking provider videos does not call Aliyun APIs.\n\n### 5. Search\n\n- Add `src/<provider>/search.ts`.\n- Support keyword search.\n- If the existing UI uses special `file_id` values for search conditions, implement parse/build/filter helpers.\n- Wire search-directory branches in `src/pan/pandal.ts`.\n\n### 6. Thumbnails And Preview\n\n- Prefer thumbnails returned by list/detail APIs.\n- If the provider needs a separate thumbnail API, add `src/<provider>/thumbnail.ts`.\n- Fill `thumbnail` during file mapping so media library and file lists can use it directly.\n\n### 7. File Operations\n\n- Add `src/<provider>/filecmd.ts`.\n- Implement create folder, move to recycle bin, permanent delete, rename, move, and copy. Clearly report unsupported official capabilities.\n- Wire `ApiCreatNewForder`, `ApiTrashBatch`, `ApiDeleteBatch`, `ApiRenameBatch`, `ApiMoveBatch`, and `ApiCopyBatch` in `src/aliapi/filecmd.ts`.\n- Unsupported capabilities must not fall through to the Aliyun default branch.\n\n### 8. Sharing\n\n- Add `src/<provider>/share.ts` with share-link creation.\n- If the provider does not support password, expiration, or multi-file sharing, block it clearly in `src/aliapi/share.ts`.\n- Update context-menu and top-menu share visibility.\n\n### 9. Upload And New Files\n\n- Add or extend `src/<provider>/upload.ts`.\n- Implement in-memory upload for new text files.\n- Implement local-file upload worker support for ordinary file/folder uploads.\n- Implement large files using the provider-recommended session/chunk API.\n- Wire `src/aliapi/uploadmem.ts` and `src/workerpage/uploader.ts`.\n- Third-party drives do not support app custom encrypted/private uploads by default; hide those menu items.\n\n### 10. Media Library Scanning\n\n- Wire provider folder traversal in `src/utils/mediaScanner.ts`.\n- Wire provider subfolder entry in `src/components/MediaLibrary.vue`.\n- Show the provider name in media-library source labels.\n- Confirm scanning does not call Aliyun list APIs.\n\n### 11. Folder Picker Modal\n\n- Treat the provider as a single-root drive in `src/pan/topbtns/SelectPanDirModal.vue`.\n- Wire lazy child directory loading.\n- Move, copy, and save-location picker modals must browse provider directories.\n\n### 12. Menu Capability Boundaries\n\n- Update `src/pan/menus/FileRightMenu.vue`, `src/pan/menus/FileTopbtn.vue`, `src/pan/menus/DirLeftMenu.vue`, and `src/pan/menus/PanTopbtn.vue`.\n- Show common capabilities: download, share, rename, move to, copy to, delete, properties, scan media library, normal upload, and normal new file/folder.\n- Hide Aliyun-only capabilities: lucky bottle, fast transfer, favorite, transcode-related actions, mark encrypted, clear history, color labels, copy directory tree, encrypted/private new file, encrypted/private upload, and import share.\n\n### 13. Properties, Versions, And Recycle Bin\n\n- Wire provider file detail in `src/pan/topbtns/ShuXingModal.vue`.\n- If folder size has no official API, return 0 or hide it; do not call Aliyun folder-size APIs.\n- If the provider supports file versions, add `src/<provider>/revisions.ts` and expose version listing/restoration in properties.\n- If the provider supports recycle bin list/restore, add `src/<provider>/recyclebin.ts` and wire recycle-bin directory, restore, and permanent delete.\n- If the official API supports only some account types or needs higher permissions, record the limitation and keep it disabled by default.\n\n### 14. Tests\n\n- Add provider helper tests under `src/<provider>/__tests__/`.\n- Cover at least OAuth URL/token body, file-list path/body, model mapping, search path/body, share body/result mapping, file-operation body, upload session/chunk path, and version/recycle-bin path where applicable.\n- Update `vitest.config.ts` to include provider tests.\n\n### 15. Verification\n\n- Run provider unit tests.\n- Run `pnpm run build`.\n- If playback/media library is involved, verify provider videos use provider download URLs, same-directory playlists use provider list APIs, media-library scans use provider list APIs, and context menus do not expose unsupported capabilities.\n\n### Recommended File Structure\n\n```text\nsrc/<provider>/\n  auth.ts\n  dirfilelist.ts\n  filecmd.ts\n  search.ts\n  share.ts\n  upload.ts\n  revisions.ts       # optional\n  recyclebin.ts      # optional\n  thumbnail.ts       # optional\n  __tests__/\n```\n\n### Completion Criteria\n\n- Login and token refresh work.\n- The left tree shows root and folders.\n- File list opens root, subdirectories, and search results.\n- File detail, download, and video playback do not call the wrong provider API.\n- Context menus and top menus expose only supported capabilities.\n- Create folder, rename, move, copy, and delete call provider APIs.\n- Share, upload, and media-library scanning are wired or explicitly reported unsupported.\n- Provider unit tests pass.\n- `pnpm run build` passes.\n\n### Current Experience Notes\n\n- Dropbox and OneDrive should both be treated as single-root third-party drives.\n- Third-party drive video playback should prefer raw download URLs and must not reuse Aliyun transcode APIs.\n- Media-library scanning and same-directory playlists are the easiest provider branches to miss.\n- Auth pages should usually open in the system browser unless the provider explicitly requires an embedded flow.\n- App key / secret placeholder constants must be included in the generated-secrets flow, not committed as real values.\n\n## Cloud Download URL And Subtitle Contract\n\nTreat a cloud download URL and its request headers as one value. `ApiFileDownloadUrl` must return every provider-required header in `IDownloadUrl.headers`; callers must preserve those headers through playback, downloads, previews, and subtitles.\n\n| Provider | Download request requirements |\n|---|---|\n| Aliyun / Alipan | Signed CDN URL; Electron may add the Aliyun Referer/Origin for direct renderer requests. |\n| 115 | `Authorization: Bearer <account token>` and `DRIVE115_DOWN_AGENT`. The User-Agent used to consume the URL must match the one used to obtain it. Direct renderer playback must register URL-to-account auth context; never rely only on the currently selected account. |\n| Baidu | URL includes `access_token`; send `User-Agent: pan.baidu.com` and `Referer: https://pan.baidu.com/`. |\n| 123 | The returned signed download URL is self-authorizing; API Authorization is only for obtaining the URL. |\n| Quark | Account Cookie plus Quark download User-Agent, `Referer: https://pan.quark.cn/`, `Origin: https://pan.quark.cn`, and `x-urlp` when required by the OSS URL. |\n| 139 | `cloud139DownloadHeaders()`: provider User-Agent, Referer, and Origin. |\n| 189 | `cloud189DownloadHeaders()`: provider User-Agent and Referer. |\n| PikPak | Temporary download/stream URL returned by the provider. |\n| Dropbox / OneDrive | Temporary or pre-authenticated download URL returned by the provider. |\n| Box | Access token is encoded into the constructed download URL. |\n\nSubtitle rules:\n- Same-directory cloud subtitles must use `ApiFileDownloadUrl`; never fetch a guessed provider URL directly.\n- The web player and external players must use the subtitle-specific local proxy URL and pass `IDownloadUrl.headers` as `proxy_headers`.\n- The subtitle proxy must identify the account with `user_id` and the provider with `drive_id`; do not use a global/current-account token when an account-specific token is available.\n- Video streams remain direct URLs unless encryption requires the proxy. DLNA behavior is separate and must not be changed as part of subtitle or direct-play fixes.\n- Any provider download-header change requires regression coverage for both the video/download URL contract and same-directory subtitle loading.\n\n## clouddrive-cli\n\nStandalone CLI + MCP server for agent-driven cloud-drive operations. Docs: `clouddrive-cli/README.md`. The CLI supports 8 providers and has its own npm package (`clouddrive-cli`). Separate test command: `pnpm run test:clouddrive-cli`.\n\n## CI\n\nManual trigger only (`workflow_dispatch`) via `.github/workflows/release.yml`. Builds on `windows-latest` + `ubuntu-latest`, publishes draft GitHub Release. No automatic CI on push/PR.\n\n## Subprojects (gitignored, referenced locally)\n\n`Motrix/`, `koodo-reader/`, `CloudServiceKit/`, `XbyVideoHub/`, `OpenCLI/`, `QuarkPan/`, `PikPakAPI/` — these are local-only and not part of the main repo build.\n"},"files":{"CLAUDE.md":"# CLAUDE.md\n\nThis file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.\n\n## Quick commands\n\n```bash\npnpm install          # pnpm only — never npm/yarn\npnpm dev              # hot-reload Electron dev server (Vite + vue-tsc)\npnpm run build        # version bump → typecheck → vite bundle\npnpm run build:electron  # full build + electron-builder packaging\npnpm run test         # focused Vitest suite (Node env, aria2 + motrix + utils)\npnpm run test:clouddrive-cli  # clouddrive-cli tests only\npnpm run build:mac    # unsigned macOS .dmg/.zip\npnpm run build:mac:signed  # signed + notarized macOS\npnpm run build:linux  # Linux .deb/.AppImage/.pacman\npnpm run build:windows  # Windows .exe/.zip\npnpm run build:all    # cross-platform sequentially\npnpm run config:clean     # blank API keys in src/config.ts (pre-commit hook)\npnpm run config:restore   # restore real keys after commit\n```\n\n## Architecture (Electron + Vue 3 + Vite)\n\n```\nelectron/main/       Electron main process (entry: electron/main/index.ts)\n  core/              Window lifecycle, IPC, auto-update, protocol, dialogs\n  aria/              Aria2c download engine (config, UPnP, runtime)\nelectron/preload/    Preload scripts (IPC bridge)\n\nsrc/                 Vue 3 renderer\n  aliapi/            Alibaba Cloud Drive SDK (files, share, user, etc.)\n  cloudbaidu/        Baidu Netdisk provider\n  cloud123/          123Pan provider\n  cloud115/          115Pan provider\n  pikpak/            PikPak provider\n  onedrive/          OneDrive provider\n  dropbox/           Dropbox provider\n  box/               Box provider\n  quark/             Quark provider\n  cloud139/          CMCloud provider\n  cloud189/          Tianyi Cloud provider\n  pan/               File manager UI (tree, menus, dialogs)\n  media-server/      Jellyfin/Emby/Plex integration\n  down/              Download manager + Aria2 integration\n  layout/            Main layout views (PageVideo, PageMusic, etc.)\n  module/            Feature modules (audioplayer, musicsdk, lyricplayer, theme)\n  store/             Pinia stores\n  components/        Shared Vue components\n  utils/             Shared utilities\n  user/              Auth, account management UI\n\nshared/              Code shared between main + renderer (constants, config keys, UA)\nscripts/             Build scripts, CLI entry points (clouddrive-cli.mjs, clouddrive-mcp.mjs)\nclouddrive-cli/      Standalone CLI + MCP server package (npm: clouddrive-cli)\n  core/              Command implementations, MCP server, upload planning\n  providers/         8 cloud-drive provider implementations\n  media/             Media matching + rename logic\n```\n\nPath aliases: `@shared/*` → `shared/*`, `@main/*` → `electron/main/*`\n\n## Key patterns\n\n- **pnpm only** — lockfile is `pnpm-lock.yaml`; `package-lock.json`/`yarn.lock` are gitignored\n- **Node ≥ 18**\n- **Pre-commit hooks** (`nano-staged.mjs`): prettier + eslint on JS/TS, stylelint + prettier on Vue/CSS, typecheck on changed `src/` files\n- **Formatting**: single quotes, no semicolons, 260 printWidth, no trailing commas, LF, `sortAttributes: true` in Vue\n- **TypeScript**: strict mode, ESNext target, node moduleResolution\n- **Sensitive config**: `scripts/clean-config.js` blanks API keys pre-commit; restore with `pnpm run config:restore`\n- **Vitest**: Node environment only, explicit test directory list in `vitest.config.ts` (not glob patterns). Add new test dirs to config.\n- **CI**: Manual trigger only via `.github/workflows/release.yml`, publishes draft GitHub Release\n\n## clouddrive-cli (AI agent integration)\n\nStandalone CLI + MCP server for agent-driven cloud-drive operations. Supports 8 providers: aliyun, cloud123, 115, baidu, pikpak, onedrive, box, dropbox.\n\nKey bins: `clouddrive-cli` (CLI), `clouddrive-mcp` (MCP server). Both point to `scripts/clouddrive-cli.mjs` and `scripts/clouddrive-mcp.mjs` respectively.\n\nAgent rules when using the CLI:\n1. Discover commands first: `clouddrive-cli list --format json`\n2. Check capabilities: `clouddrive-cli providers capabilities --format json`\n3. Always dry-run before destructive ops\n4. Never invent file IDs — they must come from `files list`/`walk`/`search`/`tree`\n5. Use `--output <file.json>` for large results\n\n## Adding a new cloud-drive provider\n\nFollow the 15-step checklist in `AGENT.md` (OAuth → provider detection → file listing → download/playback → search → thumbnails → file operations → sharing → upload → media scan → folder picker → menu boundaries → properties/recycle bin → tests → verification). The checklist is authoritative — do not ship a provider that only does file listing.\n","AGENTS.md":"# AGENTS.md — BoxPlayer (aliyunpan)\n\n## Quick reference\n\n```bash\npnpm install          # install deps (pnpm only, never npm/yarn)\npnpm dev              # hot-reload Electron dev server\npnpm run build        # typecheck + bundle (vue-tsc --noEmit && vite build)\npnpm run test         # focused Vitest suite (not full repo)\npnpm run test:clouddrive-cli  # clouddrive-cli tests only\n```\n\n## Package manager: pnpm only\n\nLockfile is `pnpm-lock.yaml`. `package-lock.json` and `yarn.lock` are in `.gitignore`.\nNever use `npm install` or `yarn`.\n\n## Node version\n\n`engines.node >= 22.12.0` in package.json. Electron 40 requires Node 22.12+ during install/build.\n\n## Build pipeline order matters\n\n`pnpm run build` runs **version bump → typecheck → vite bundle**. The version bump (`version.mjs`) auto-increments the patch version in package.json before every build. The build removes `dist/` and `release/` directories on start.\n\n`pnpm run build:electron` calls `build` first, then runs `electron-builder`.\n\nFor platform-specific packaging:\n```bash\npnpm run build:mac       # unsigned macOS\npnpm run build:mac:signed  # signed + notarized\npnpm run build:linux\npnpm run build:windows\npnpm run build:all       # cross-platform, sequential\n```\n\n## Sensitive config: generated secrets\n\nPrivate client IDs, client secrets, API keys, and private API URLs live outside git:\n\n```bash\npnpm run secrets:generate\n```\n\nLocal development reads them from `.env.local` and generates `src/secrets.generated.ts`. GitHub Actions reads the same keys from GitHub Secrets and runs `scripts/generate-secrets.mjs --mode=ci --strict` before building.\n\n`.env.local` and `src/secrets.generated.ts` are ignored and must never be committed. `src/config.ts` should import generated secrets or use placeholders, not contain real private values.\n\n## Architecture: Electron + Vue 3 + Vite\n\n| Directory | Purpose |\n|---|---|\n| `electron/main/` | Electron main process (entry: `electron/main/index.ts`) |\n| `electron/preload/` | Preload scripts |\n| `src/` | Vue 3 renderer (components, views, stores, API modules) |\n| `shared/` | Code shared between main + renderer |\n| `scripts/` | Build, CLI entry points, config management |\n| `clouddrive-cli/` | Standalone CLI package (published to npm as `clouddrive-cli`) |\n\nPath aliases (set in `tsconfig.json`, `vite.config.ts`, `vitest.config.ts`):\n- `@shared/*` → `shared/*`\n- `@main/*` → `electron/main/*`\n\nCloud provider API modules in `src/`: `aliapi/`, `cloudbaidu/`, `cloud123/`, `cloud115/`, `pikpak/`, `onedrive/`, `box/`, `dropbox/`, `quark/`, `cloud139/`, `cloud189/`.\n\n## Testing: Vitest, Node environment, selective includes\n\nTests run in Node environment (not jsdom). The `vitest.config.ts` lists explicit test directories — not a glob over `**/*.test.ts`. Tests outside these paths are not picked up:\n\n- `electron/main/core/__tests__/`, `electron/main/aria/__tests__/`\n- `shared/__tests__/`, `scripts/__tests__/`\n- `src/down/motrix-integration/`, `src/media-server/__tests__/`\n- `src/utils/__tests__/`, `src/aliapi/__tests__/`\n- `src/pikpak/__tests__/`, `src/quark/__tests__/`\n- `src/dropbox/__tests__/`, `src/onedrive/__tests__/`, `src/box/__tests__/`\n- `clouddrive-cli/__tests__/`\n\nDefault `pnpm run test` runs only a subset (aria2 tests, motrix integration, a couple utils files).\n\nWhen adding tests in a new directory, update `vitest.config.ts`.\n\n## Pre-commit hooks\n\nDo not rely on pre-commit cleanup for secrets. Secret safety is handled by keeping real values in ignored/generated files and GitHub Secrets.\n\n## Formatting conventions\n\nFrom `.prettierrc`:\n- Single quotes, no semicolons\n- 260 printWidth (very wide)\n- No trailing commas\n- LF line endings\n- `sortAttributes: true` on HTML/Vue\n\n## TypeScript\n\n- `tsconfig.json` targets ESNext, moduleResolution node, strict mode, `@shared/*` and `@main/*` path aliases\n- Includes `src/` and `shared/`, excludes `shared/__tests__`\n- References `tsconfig.node.json` for Electron-side code\n\n## Provider Integration Checklist\n\nWhen adding a new cloud-drive provider, implement the following in order unless the user explicitly excludes a step. Do not stop after only wiring file listing. Sync/change-listening is not required by default.\n\n### 1. Account And Auth\n\n- Read the official OAuth/API documentation and prefer stable API versions.\n- Add `src/<provider>/auth.ts` with auth URL, authorization-code token exchange, and refresh token support.\n- Define `CLIENT_ID` / `CLIENT_SECRET` placeholder constants, defaulting to empty strings.\n- Add app key / secret fields to `.env.example`, `src/secrets.example.ts`, and `scripts/generate-secrets.mjs`.\n- Add the provider to `tokenfrom` in `src/user/userstore.ts`.\n- Wire login, token refresh, and drive loading in `src/user/userdal.ts`.\n- Add login entry points in `src/user/UserLogin.vue` and `src/user/UserInfo.vue`.\n\n### 2. Provider Detection And Drive Model\n\n- Add `is<Provider>User` in `src/aliapi/utils.ts`.\n- Update `GetDriveID` and `GetDriveType`, modeling third-party drives as a single-root drive.\n- Filter unsupported virtual directories in `src/pan/PanLeft.vue` and `src/pan/pantreestore.ts`.\n\n### 3. File List And Detail\n\n- Add `src/<provider>/dirfilelist.ts`.\n- Implement root listing, child directory pagination, and file detail.\n- Map official file models to `IAliGetFileModel`; at minimum fill `drive_id`, `file_id`, `parent_file_id`, `name`, `isDir`, `category`, `icon`, `size`, `time`, `thumbnail`, and `content_hash`.\n- Store provider-specific path, parent id, download URL, or similar metadata in `description`.\n- Wire root loading, directory listing, and search-listing branches in `src/pan/pandal.ts`.\n- Wire provider file detail in `src/aliapi/file.ts` `ApiFileInfo`.\n\n### 4. Download And Playback\n\n- Wire provider direct download URLs in `src/aliapi/file.ts` `ApiFileDownloadUrl`.\n- Third-party drives usually do not have Aliyun transcode APIs; `ApiVideoPreviewUrl` / `ApiAudioPreviewUrl` should return `暂无转码信息` or `undefined`, letting playback use the raw download URL.\n- Wire same-directory playlist loading in `src/layout/PageVideo.vue`, `src/utils/openfile.ts`, and `src/utils/playerhelper.ts`.\n- Confirm clicking provider videos does not call Aliyun APIs.\n\n### 5. Search\n\n- Add `src/<provider>/search.ts`.\n- Support keyword search.\n- If the existing UI uses special `file_id` values for search conditions, implement parse/build/filter helpers.\n- Wire search-directory branches in `src/pan/pandal.ts`.\n\n### 6. Thumbnails And Preview\n\n- Prefer thumbnails returned by list/detail APIs.\n- If the provider needs a separate thumbnail API, add `src/<provider>/thumbnail.ts`.\n- Fill `thumbnail` during file mapping so media library and file lists can use it directly.\n\n### 7. File Operations\n\n- Add `src/<provider>/filecmd.ts`.\n- Implement create folder, move to recycle bin, permanent delete, rename, move, and copy. Clearly report unsupported official capabilities.\n- Wire `ApiCreatNewForder`, `ApiTrashBatch`, `ApiDeleteBatch`, `ApiRenameBatch`, `ApiMoveBatch`, and `ApiCopyBatch` in `src/aliapi/filecmd.ts`.\n- Unsupported capabilities must not fall through to the Aliyun default branch.\n\n### 8. Sharing\n\n- Add `src/<provider>/share.ts` with share-link creation.\n- If the provider does not support password, expiration, or multi-file sharing, block it clearly in `src/aliapi/share.ts`.\n- Update context-menu and top-menu share visibility.\n\n### 9. Upload And New Files\n\n- Add or extend `src/<provider>/upload.ts`.\n- Implement in-memory upload for new text files.\n- Implement local-file upload worker support for ordinary file/folder uploads.\n- Implement large files using the provider-recommended session/chunk API.\n- Wire `src/aliapi/uploadmem.ts` and `src/workerpage/uploader.ts`.\n- Third-party drives do not support app custom encrypted/private uploads by default; hide those menu items.\n\n### 10. Media Library Scanning\n\n- Wire provider folder traversal in `src/utils/mediaScanner.ts`.\n- Wire provider subfolder entry in `src/components/MediaLibrary.vue`.\n- Show the provider name in media-library source labels.\n- Confirm scanning does not call Aliyun list APIs.\n\n### 11. Folder Picker Modal\n\n- Treat the provider as a single-root drive in `src/pan/topbtns/SelectPanDirModal.vue`.\n- Wire lazy child directory loading.\n- Move, copy, and save-location picker modals must browse provider directories.\n\n### 12. Menu Capability Boundaries\n\n- Update `src/pan/menus/FileRightMenu.vue`, `src/pan/menus/FileTopbtn.vue`, `src/pan/menus/DirLeftMenu.vue`, and `src/pan/menus/PanTopbtn.vue`.\n- Show common capabilities: download, share, rename, move to, copy to, delete, properties, scan media library, normal upload, and normal new file/folder.\n- Hide Aliyun-only capabilities: lucky bottle, fast transfer, favorite, transcode-related actions, mark encrypted, clear history, color labels, copy directory tree, encrypted/private new file, encrypted/private upload, and import share.\n\n### 13. Properties, Versions, And Recycle Bin\n\n- Wire provider file detail in `src/pan/topbtns/ShuXingModal.vue`.\n- If folder size has no official API, return 0 or hide it; do not call Aliyun folder-size APIs.\n- If the provider supports file versions, add `src/<provider>/revisions.ts` and expose version listing/restoration in properties.\n- If the provider supports recycle bin list/restore, add `src/<provider>/recyclebin.ts` and wire recycle-bin directory, restore, and permanent delete.\n- If the official API supports only some account types or needs higher permissions, record the limitation and keep it disabled by default.\n\n### 14. Tests\n\n- Add provider helper tests under `src/<provider>/__tests__/`.\n- Cover at least OAuth URL/token body, file-list path/body, model mapping, search path/body, share body/result mapping, file-operation body, upload session/chunk path, and version/recycle-bin path where applicable.\n- Update `vitest.config.ts` to include provider tests.\n\n### 15. Verification\n\n- Run provider unit tests.\n- Run `pnpm run build`.\n- If playback/media library is involved, verify provider videos use provider download URLs, same-directory playlists use provider list APIs, media-library scans use provider list APIs, and context menus do not expose unsupported capabilities.\n\n### Recommended File Structure\n\n```text\nsrc/<provider>/\n  auth.ts\n  dirfilelist.ts\n  filecmd.ts\n  search.ts\n  share.ts\n  upload.ts\n  revisions.ts       # optional\n  recyclebin.ts      # optional\n  thumbnail.ts       # optional\n  __tests__/\n```\n\n### Completion Criteria\n\n- Login and token refresh work.\n- The left tree shows root and folders.\n- File list opens root, subdirectories, and search results.\n- File detail, download, and video playback do not call the wrong provider API.\n- Context menus and top menus expose only supported capabilities.\n- Create folder, rename, move, copy, and delete call provider APIs.\n- Share, upload, and media-library scanning are wired or explicitly reported unsupported.\n- Provider unit tests pass.\n- `pnpm run build` passes.\n\n### Current Experience Notes\n\n- Dropbox and OneDrive should both be treated as single-root third-party drives.\n- Third-party drive video playback should prefer raw download URLs and must not reuse Aliyun transcode APIs.\n- Media-library scanning and same-directory playlists are the easiest provider branches to miss.\n- Auth pages should usually open in the system browser unless the provider explicitly requires an embedded flow.\n- App key / secret placeholder constants must be included in the generated-secrets flow, not committed as real values.\n\n## Cloud Download URL And Subtitle Contract\n\nTreat a cloud download URL and its request headers as one value. `ApiFileDownloadUrl` must return every provider-required header in `IDownloadUrl.headers`; callers must preserve those headers through playback, downloads, previews, and subtitles.\n\n| Provider | Download request requirements |\n|---|---|\n| Aliyun / Alipan | Signed CDN URL; Electron may add the Aliyun Referer/Origin for direct renderer requests. |\n| 115 | `Authorization: Bearer <account token>` and `DRIVE115_DOWN_AGENT`. The User-Agent used to consume the URL must match the one used to obtain it. Direct renderer playback must register URL-to-account auth context; never rely only on the currently selected account. |\n| Baidu | URL includes `access_token`; send `User-Agent: pan.baidu.com` and `Referer: https://pan.baidu.com/`. |\n| 123 | The returned signed download URL is self-authorizing; API Authorization is only for obtaining the URL. |\n| Quark | Account Cookie plus Quark download User-Agent, `Referer: https://pan.quark.cn/`, `Origin: https://pan.quark.cn`, and `x-urlp` when required by the OSS URL. |\n| 139 | `cloud139DownloadHeaders()`: provider User-Agent, Referer, and Origin. |\n| 189 | `cloud189DownloadHeaders()`: provider User-Agent and Referer. |\n| PikPak | Temporary download/stream URL returned by the provider. |\n| Dropbox / OneDrive | Temporary or pre-authenticated download URL returned by the provider. |\n| Box | Access token is encoded into the constructed download URL. |\n\nSubtitle rules:\n- Same-directory cloud subtitles must use `ApiFileDownloadUrl`; never fetch a guessed provider URL directly.\n- The web player and external players must use the subtitle-specific local proxy URL and pass `IDownloadUrl.headers` as `proxy_headers`.\n- The subtitle proxy must identify the account with `user_id` and the provider with `drive_id`; do not use a global/current-account token when an account-specific token is available.\n- Video streams remain direct URLs unless encryption requires the proxy. DLNA behavior is separate and must not be changed as part of subtitle or direct-play fixes.\n- Any provider download-header change requires regression coverage for both the video/download URL contract and same-directory subtitle loading.\n\n## clouddrive-cli\n\nStandalone CLI + MCP server for agent-driven cloud-drive operations. Docs: `clouddrive-cli/README.md`. The CLI supports 8 providers and has its own npm package (`clouddrive-cli`). Separate test command: `pnpm run test:clouddrive-cli`.\n\n## CI\n\nManual trigger only (`workflow_dispatch`) via `.github/workflows/release.yml`. Builds on `windows-latest` + `ubuntu-latest`, publishes draft GitHub Release. No automatic CI on push/PR.\n\n## Subprojects (gitignored, referenced locally)\n\n`Motrix/`, `koodo-reader/`, `CloudServiceKit/`, `XbyVideoHub/`, `OpenCLI/`, `QuarkPan/`, `PikPakAPI/` — these are local-only and not part of the main repo build.\n"},"items":[{"name":"CLAUDE.md","path":"CLAUDE.md","title":"CLAUDE.md","content":"# CLAUDE.md\n\nThis file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.\n\n## Quick commands\n\n```bash\npnpm install          # pnpm only — never npm/yarn\npnpm dev              # hot-reload Electron dev server (Vite + vue-tsc)\npnpm run build        # version bump → typecheck → vite bundle\npnpm run build:electron  # full build + electron-builder packaging\npnpm run test         # focused Vitest suite (Node env, aria2 + motrix + utils)\npnpm run test:clouddrive-cli  # clouddrive-cli tests only\npnpm run build:mac    # unsigned macOS .dmg/.zip\npnpm run build:mac:signed  # signed + notarized macOS\npnpm run build:linux  # Linux .deb/.AppImage/.pacman\npnpm run build:windows  # Windows .exe/.zip\npnpm run build:all    # cross-platform sequentially\npnpm run config:clean     # blank API keys in src/config.ts (pre-commit hook)\npnpm run config:restore   # restore real keys after commit\n```\n\n## Architecture (Electron + Vue 3 + Vite)\n\n```\nelectron/main/       Electron main process (entry: electron/main/index.ts)\n  core/              Window lifecycle, IPC, auto-update, protocol, dialogs\n  aria/              Aria2c download engine (config, UPnP, runtime)\nelectron/preload/    Preload scripts (IPC bridge)\n\nsrc/                 Vue 3 renderer\n  aliapi/            Alibaba Cloud Drive SDK (files, share, user, etc.)\n  cloudbaidu/        Baidu Netdisk provider\n  cloud123/          123Pan provider\n  cloud115/          115Pan provider\n  pikpak/            PikPak provider\n  onedrive/          OneDrive provider\n  dropbox/           Dropbox provider\n  box/               Box provider\n  quark/             Quark provider\n  cloud139/          CMCloud provider\n  cloud189/          Tianyi Cloud provider\n  pan/               File manager UI (tree, menus, dialogs)\n  media-server/      Jellyfin/Emby/Plex integration\n  down/              Download manager + Aria2 integration\n  layout/            Main layout views (PageVideo, PageMusic, etc.)\n  module/            Feature modules (audioplayer, musicsdk, lyricplayer, theme)\n  store/             Pinia stores\n  components/        Shared Vue components\n  utils/             Shared utilities\n  user/              Auth, account management UI\n\nshared/              Code shared between main + renderer (constants, config keys, UA)\nscripts/             Build scripts, CLI entry points (clouddrive-cli.mjs, clouddrive-mcp.mjs)\nclouddrive-cli/      Standalone CLI + MCP server package (npm: clouddrive-cli)\n  core/              Command implementations, MCP server, upload planning\n  providers/         8 cloud-drive provider implementations\n  media/             Media matching + rename logic\n```\n\nPath aliases: `@shared/*` → `shared/*`, `@main/*` → `electron/main/*`\n\n## Key patterns\n\n- **pnpm only** — lockfile is `pnpm-lock.yaml`; `package-lock.json`/`yarn.lock` are gitignored\n- **Node ≥ 18**\n- **Pre-commit hooks** (`nano-staged.mjs`): prettier + eslint on JS/TS, stylelint + prettier on Vue/CSS, typecheck on changed `src/` files\n- **Formatting**: single quotes, no semicolons, 260 printWidth, no trailing commas, LF, `sortAttributes: true` in Vue\n- **TypeScript**: strict mode, ESNext target, node moduleResolution\n- **Sensitive config**: `scripts/clean-config.js` blanks API keys pre-commit; restore with `pnpm run config:restore`\n- **Vitest**: Node environment only, explicit test directory list in `vitest.config.ts` (not glob patterns). Add new test dirs to config.\n- **CI**: Manual trigger only via `.github/workflows/release.yml`, publishes draft GitHub Release\n\n## clouddrive-cli (AI agent integration)\n\nStandalone CLI + MCP server for agent-driven cloud-drive operations. Supports 8 providers: aliyun, cloud123, 115, baidu, pikpak, onedrive, box, dropbox.\n\nKey bins: `clouddrive-cli` (CLI), `clouddrive-mcp` (MCP server). Both point to `scripts/clouddrive-cli.mjs` and `scripts/clouddrive-mcp.mjs` respectively.\n\nAgent rules when using the CLI:\n1. Discover commands first: `clouddrive-cli list --format json`\n2. Check capabilities: `clouddrive-cli providers capabilities --format json`\n3. Always dry-run before destructive ops\n4. Never invent file IDs — they must come from `files list`/`walk`/`search`/`tree`\n5. Use `--output <file.json>` for large results\n\n## Adding a new cloud-drive provider\n\nFollow the 15-step checklist in `AGENT.md` (OAuth → provider detection → file listing → download/playback → search → thumbnails → file operations → sharing → upload → media scan → folder picker → menu boundaries → properties/recycle bin → tests → verification). The checklist is authoritative — do not ship a provider that only does file listing.\n","category":"root","tokens":1158},{"name":"AGENTS.md","path":"AGENTS.md","title":"AGENTS.md","content":"# AGENTS.md — BoxPlayer (aliyunpan)\n\n## Quick reference\n\n```bash\npnpm install          # install deps (pnpm only, never npm/yarn)\npnpm dev              # hot-reload Electron dev server\npnpm run build        # typecheck + bundle (vue-tsc --noEmit && vite build)\npnpm run test         # focused Vitest suite (not full repo)\npnpm run test:clouddrive-cli  # clouddrive-cli tests only\n```\n\n## Package manager: pnpm only\n\nLockfile is `pnpm-lock.yaml`. `package-lock.json` and `yarn.lock` are in `.gitignore`.\nNever use `npm install` or `yarn`.\n\n## Node version\n\n`engines.node >= 22.12.0` in package.json. Electron 40 requires Node 22.12+ during install/build.\n\n## Build pipeline order matters\n\n`pnpm run build` runs **version bump → typecheck → vite bundle**. The version bump (`version.mjs`) auto-increments the patch version in package.json before every build. The build removes `dist/` and `release/` directories on start.\n\n`pnpm run build:electron` calls `build` first, then runs `electron-builder`.\n\nFor platform-specific packaging:\n```bash\npnpm run build:mac       # unsigned macOS\npnpm run build:mac:signed  # signed + notarized\npnpm run build:linux\npnpm run build:windows\npnpm run build:all       # cross-platform, sequential\n```\n\n## Sensitive config: generated secrets\n\nPrivate client IDs, client secrets, API keys, and private API URLs live outside git:\n\n```bash\npnpm run secrets:generate\n```\n\nLocal development reads them from `.env.local` and generates `src/secrets.generated.ts`. GitHub Actions reads the same keys from GitHub Secrets and runs `scripts/generate-secrets.mjs --mode=ci --strict` before building.\n\n`.env.local` and `src/secrets.generated.ts` are ignored and must never be committed. `src/config.ts` should import generated secrets or use placeholders, not contain real private values.\n\n## Architecture: Electron + Vue 3 + Vite\n\n| Directory | Purpose |\n|---|---|\n| `electron/main/` | Electron main process (entry: `electron/main/index.ts`) |\n| `electron/preload/` | Preload scripts |\n| `src/` | Vue 3 renderer (components, views, stores, API modules) |\n| `shared/` | Code shared between main + renderer |\n| `scripts/` | Build, CLI entry points, config management |\n| `clouddrive-cli/` | Standalone CLI package (published to npm as `clouddrive-cli`) |\n\nPath aliases (set in `tsconfig.json`, `vite.config.ts`, `vitest.config.ts`):\n- `@shared/*` → `shared/*`\n- `@main/*` → `electron/main/*`\n\nCloud provider API modules in `src/`: `aliapi/`, `cloudbaidu/`, `cloud123/`, `cloud115/`, `pikpak/`, `onedrive/`, `box/`, `dropbox/`, `quark/`, `cloud139/`, `cloud189/`.\n\n## Testing: Vitest, Node environment, selective includes\n\nTests run in Node environment (not jsdom). The `vitest.config.ts` lists explicit test directories — not a glob over `**/*.test.ts`. Tests outside these paths are not picked up:\n\n- `electron/main/core/__tests__/`, `electron/main/aria/__tests__/`\n- `shared/__tests__/`, `scripts/__tests__/`\n- `src/down/motrix-integration/`, `src/media-server/__tests__/`\n- `src/utils/__tests__/`, `src/aliapi/__tests__/`\n- `src/pikpak/__tests__/`, `src/quark/__tests__/`\n- `src/dropbox/__tests__/`, `src/onedrive/__tests__/`, `src/box/__tests__/`\n- `clouddrive-cli/__tests__/`\n\nDefault `pnpm run test` runs only a subset (aria2 tests, motrix integration, a couple utils files).\n\nWhen adding tests in a new directory, update `vitest.config.ts`.\n\n## Pre-commit hooks\n\nDo not rely on pre-commit cleanup for secrets. Secret safety is handled by keeping real values in ignored/generated files and GitHub Secrets.\n\n## Formatting conventions\n\nFrom `.prettierrc`:\n- Single quotes, no semicolons\n- 260 printWidth (very wide)\n- No trailing commas\n- LF line endings\n- `sortAttributes: true` on HTML/Vue\n\n## TypeScript\n\n- `tsconfig.json` targets ESNext, moduleResolution node, strict mode, `@shared/*` and `@main/*` path aliases\n- Includes `src/` and `shared/`, excludes `shared/__tests__`\n- References `tsconfig.node.json` for Electron-side code\n\n## Provider Integration Checklist\n\nWhen adding a new cloud-drive provider, implement the following in order unless the user explicitly excludes a step. Do not stop after only wiring file listing. Sync/change-listening is not required by default.\n\n### 1. Account And Auth\n\n- Read the official OAuth/API documentation and prefer stable API versions.\n- Add `src/<provider>/auth.ts` with auth URL, authorization-code token exchange, and refresh token support.\n- Define `CLIENT_ID` / `CLIENT_SECRET` placeholder constants, defaulting to empty strings.\n- Add app key / secret fields to `.env.example`, `src/secrets.example.ts`, and `scripts/generate-secrets.mjs`.\n- Add the provider to `tokenfrom` in `src/user/userstore.ts`.\n- Wire login, token refresh, and drive loading in `src/user/userdal.ts`.\n- Add login entry points in `src/user/UserLogin.vue` and `src/user/UserInfo.vue`.\n\n### 2. Provider Detection And Drive Model\n\n- Add `is<Provider>User` in `src/aliapi/utils.ts`.\n- Update `GetDriveID` and `GetDriveType`, modeling third-party drives as a single-root drive.\n- Filter unsupported virtual directories in `src/pan/PanLeft.vue` and `src/pan/pantreestore.ts`.\n\n### 3. File List And Detail\n\n- Add `src/<provider>/dirfilelist.ts`.\n- Implement root listing, child directory pagination, and file detail.\n- Map official file models to `IAliGetFileModel`; at minimum fill `drive_id`, `file_id`, `parent_file_id`, `name`, `isDir`, `category`, `icon`, `size`, `time`, `thumbnail`, and `content_hash`.\n- Store provider-specific path, parent id, download URL, or similar metadata in `description`.\n- Wire root loading, directory listing, and search-listing branches in `src/pan/pandal.ts`.\n- Wire provider file detail in `src/aliapi/file.ts` `ApiFileInfo`.\n\n### 4. Download And Playback\n\n- Wire provider direct download URLs in `src/aliapi/file.ts` `ApiFileDownloadUrl`.\n- Third-party drives usually do not have Aliyun transcode APIs; `ApiVideoPreviewUrl` / `ApiAudioPreviewUrl` should return `暂无转码信息` or `undefined`, letting playback use the raw download URL.\n- Wire same-directory playlist loading in `src/layout/PageVideo.vue`, `src/utils/openfile.ts`, and `src/utils/playerhelper.ts`.\n- Confirm clicking provider videos does not call Aliyun APIs.\n\n### 5. Search\n\n- Add `src/<provider>/search.ts`.\n- Support keyword search.\n- If the existing UI uses special `file_id` values for search conditions, implement parse/build/filter helpers.\n- Wire search-directory branches in `src/pan/pandal.ts`.\n\n### 6. Thumbnails And Preview\n\n- Prefer thumbnails returned by list/detail APIs.\n- If the provider needs a separate thumbnail API, add `src/<provider>/thumbnail.ts`.\n- Fill `thumbnail` during file mapping so media library and file lists can use it directly.\n\n### 7. File Operations\n\n- Add `src/<provider>/filecmd.ts`.\n- Implement create folder, move to recycle bin, permanent delete, rename, move, and copy. Clearly report unsupported official capabilities.\n- Wire `ApiCreatNewForder`, `ApiTrashBatch`, `ApiDeleteBatch`, `ApiRenameBatch`, `ApiMoveBatch`, and `ApiCopyBatch` in `src/aliapi/filecmd.ts`.\n- Unsupported capabilities must not fall through to the Aliyun default branch.\n\n### 8. Sharing\n\n- Add `src/<provider>/share.ts` with share-link creation.\n- If the provider does not support password, expiration, or multi-file sharing, block it clearly in `src/aliapi/share.ts`.\n- Update context-menu and top-menu share visibility.\n\n### 9. Upload And New Files\n\n- Add or extend `src/<provider>/upload.ts`.\n- Implement in-memory upload for new text files.\n- Implement local-file upload worker support for ordinary file/folder uploads.\n- Implement large files using the provider-recommended session/chunk API.\n- Wire `src/aliapi/uploadmem.ts` and `src/workerpage/uploader.ts`.\n- Third-party drives do not support app custom encrypted/private uploads by default; hide those menu items.\n\n### 10. Media Library Scanning\n\n- Wire provider folder traversal in `src/utils/mediaScanner.ts`.\n- Wire provider subfolder entry in `src/components/MediaLibrary.vue`.\n- Show the provider name in media-library source labels.\n- Confirm scanning does not call Aliyun list APIs.\n\n### 11. Folder Picker Modal\n\n- Treat the provider as a single-root drive in `src/pan/topbtns/SelectPanDirModal.vue`.\n- Wire lazy child directory loading.\n- Move, copy, and save-location picker modals must browse provider directories.\n\n### 12. Menu Capability Boundaries\n\n- Update `src/pan/menus/FileRightMenu.vue`, `src/pan/menus/FileTopbtn.vue`, `src/pan/menus/DirLeftMenu.vue`, and `src/pan/menus/PanTopbtn.vue`.\n- Show common capabilities: download, share, rename, move to, copy to, delete, properties, scan media library, normal upload, and normal new file/folder.\n- Hide Aliyun-only capabilities: lucky bottle, fast transfer, favorite, transcode-related actions, mark encrypted, clear history, color labels, copy directory tree, encrypted/private new file, encrypted/private upload, and import share.\n\n### 13. Properties, Versions, And Recycle Bin\n\n- Wire provider file detail in `src/pan/topbtns/ShuXingModal.vue`.\n- If folder size has no official API, return 0 or hide it; do not call Aliyun folder-size APIs.\n- If the provider supports file versions, add `src/<provider>/revisions.ts` and expose version listing/restoration in properties.\n- If the provider supports recycle bin list/restore, add `src/<provider>/recyclebin.ts` and wire recycle-bin directory, restore, and permanent delete.\n- If the official API supports only some account types or needs higher permissions, record the limitation and keep it disabled by default.\n\n### 14. Tests\n\n- Add provider helper tests under `src/<provider>/__tests__/`.\n- Cover at least OAuth URL/token body, file-list path/body, model mapping, search path/body, share body/result mapping, file-operation body, upload session/chunk path, and version/recycle-bin path where applicable.\n- Update `vitest.config.ts` to include provider tests.\n\n### 15. Verification\n\n- Run provider unit tests.\n- Run `pnpm run build`.\n- If playback/media library is involved, verify provider videos use provider download URLs, same-directory playlists use provider list APIs, media-library scans use provider list APIs, and context menus do not expose unsupported capabilities.\n\n### Recommended File Structure\n\n```text\nsrc/<provider>/\n  auth.ts\n  dirfilelist.ts\n  filecmd.ts\n  search.ts\n  share.ts\n  upload.ts\n  revisions.ts       # optional\n  recyclebin.ts      # optional\n  thumbnail.ts       # optional\n  __tests__/\n```\n\n### Completion Criteria\n\n- Login and token refresh work.\n- The left tree shows root and folders.\n- File list opens root, subdirectories, and search results.\n- File detail, download, and video playback do not call the wrong provider API.\n- Context menus and top menus expose only supported capabilities.\n- Create folder, rename, move, copy, and delete call provider APIs.\n- Share, upload, and media-library scanning are wired or explicitly reported unsupported.\n- Provider unit tests pass.\n- `pnpm run build` passes.\n\n### Current Experience Notes\n\n- Dropbox and OneDrive should both be treated as single-root third-party drives.\n- Third-party drive video playback should prefer raw download URLs and must not reuse Aliyun transcode APIs.\n- Media-library scanning and same-directory playlists are the easiest provider branches to miss.\n- Auth pages should usually open in the system browser unless the provider explicitly requires an embedded flow.\n- App key / secret placeholder constants must be included in the generated-secrets flow, not committed as real values.\n\n## Cloud Download URL And Subtitle Contract\n\nTreat a cloud download URL and its request headers as one value. `ApiFileDownloadUrl` must return every provider-required header in `IDownloadUrl.headers`; callers must preserve those headers through playback, downloads, previews, and subtitles.\n\n| Provider | Download request requirements |\n|---|---|\n| Aliyun / Alipan | Signed CDN URL; Electron may add the Aliyun Referer/Origin for direct renderer requests. |\n| 115 | `Authorization: Bearer <account token>` and `DRIVE115_DOWN_AGENT`. The User-Agent used to consume the URL must match the one used to obtain it. Direct renderer playback must register URL-to-account auth context; never rely only on the currently selected account. |\n| Baidu | URL includes `access_token`; send `User-Agent: pan.baidu.com` and `Referer: https://pan.baidu.com/`. |\n| 123 | The returned signed download URL is self-authorizing; API Authorization is only for obtaining the URL. |\n| Quark | Account Cookie plus Quark download User-Agent, `Referer: https://pan.quark.cn/`, `Origin: https://pan.quark.cn`, and `x-urlp` when required by the OSS URL. |\n| 139 | `cloud139DownloadHeaders()`: provider User-Agent, Referer, and Origin. |\n| 189 | `cloud189DownloadHeaders()`: provider User-Agent and Referer. |\n| PikPak | Temporary download/stream URL returned by the provider. |\n| Dropbox / OneDrive | Temporary or pre-authenticated download URL returned by the provider. |\n| Box | Access token is encoded into the constructed download URL. |\n\nSubtitle rules:\n- Same-directory cloud subtitles must use `ApiFileDownloadUrl`; never fetch a guessed provider URL directly.\n- The web player and external players must use the subtitle-specific local proxy URL and pass `IDownloadUrl.headers` as `proxy_headers`.\n- The subtitle proxy must identify the account with `user_id` and the provider with `drive_id`; do not use a global/current-account token when an account-specific token is available.\n- Video streams remain direct URLs unless encryption requires the proxy. DLNA behavior is separate and must not be changed as part of subtitle or direct-play fixes.\n- Any provider download-header change requires regression coverage for both the video/download URL contract and same-directory subtitle loading.\n\n## clouddrive-cli\n\nStandalone CLI + MCP server for agent-driven cloud-drive operations. Docs: `clouddrive-cli/README.md`. The CLI supports 8 providers and has its own npm package (`clouddrive-cli`). Separate test command: `pnpm run test:clouddrive-cli`.\n\n## CI\n\nManual trigger only (`workflow_dispatch`) via `.github/workflows/release.yml`. Builds on `windows-latest` + `ubuntu-latest`, publishes draft GitHub Release. No automatic CI on push/PR.\n\n## Subprojects (gitignored, referenced locally)\n\n`Motrix/`, `koodo-reader/`, `CloudServiceKit/`, `XbyVideoHub/`, `OpenCLI/`, `QuarkPan/`, `PikPakAPI/` — these are local-only and not part of the main repo build.\n","category":"root","tokens":3612}]}