Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
83 changes: 0 additions & 83 deletions .agents/skills/classic-to-default-sync/SKILL.md

This file was deleted.

32 changes: 17 additions & 15 deletions .agents/skills/i18n-translate/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ name: i18n-translate
description: >-
Complete and maintain frontend i18n translations for this project. Covers
finding missing translation keys, detecting untranslated entries, and adding
translations for all supported locales (en, zh, fr, ja, ru, vi). Use for any
translations for all supported locales (en, zh, zh-TW, fr, ja, ru, vi). Use for any
task involving frontend locale files, missing translation keys, untranslated
UI text, `t(...)` keys, `useTranslation()`, static i18n keys, button/label/
toast/dialog/placeholder/validation copy, or adding/fixing even a single
Expand All @@ -24,12 +24,12 @@ description: >-

### Hard Constraint: Locale Writes Go Through the Script

- You MUST NOT edit `web/default/src/i18n/locales/*.json` directly with text-editing tools (StrReplace, Write, search-and-replace, manual JSON edits, etc.). This applies even to a single key.
- You MUST NOT edit `web/src/i18n/locales/*.json` directly with text-editing tools (StrReplace, Write, search-and-replace, manual JSON edits, etc.). This applies even to a single key.
- ALL locale writes MUST go through the `add-missing-keys.mjs` script, followed by `bun run i18n:sync`. The script is the only sanctioned way to add or change locale values.
- Why this is mandatory, not optional:
- Hand-editing reliably drops one or more of the six locales (`en`, `zh`, `fr`, `ja`, `ru`, `vi`), leaving keys missing in some languages.
- Hand-editing reliably drops one or more of the seven locales (`en`, `zh`, `zh-TW`, `fr`, `ja`, `ru`, `vi`), leaving keys missing in some languages.
- Hand-editing breaks the required alphabetical key order and introduces JSON syntax errors (trailing commas, mismatched quotes).
- The script writes all six files atomically with consistent sorting, so the locale set stays in sync by construction.
- The script writes all seven files atomically with consistent sorting, so the locale set stays in sync by construction.
- The script does not do the translation for you. You still must reason out each locale's copy and populate the script's `newKeys` object; the script only handles insertion, sorting, and writing. Do not skip the script just because the thinking happens regardless.

## Scope Checklist
Expand All @@ -45,18 +45,18 @@ Do not skip this workflow because the fix is "just one key".

## Overview

- Locale files: `web/default/src/i18n/locales/{en,zh,fr,ja,ru,vi}.json`
- Locale files: `web/src/i18n/locales/{en,zh,zh-TW,fr,ja,ru,vi}.json`
- Format: flat JSON under `"translation"` key, keys are English source strings
- Base locale: `en.json` (most keys), fallback: `zh` (Chinese)
- Sync script: `bun run i18n:sync` (from `web/default/`)
- Sync script: `bun run i18n:sync` (from `web/`)
- All `t()` calls must have corresponding keys in every locale file

## Small Fix Path

For a single known missing key (still script-only, no direct JSON edits):

1. Confirm the exact key at the call site and verify it is absent from all locale files.
2. Add the key via `add-missing-keys.mjs`, populating its `newKeys` object for every supported locale: `en`, `zh`, `fr`, `ja`, `ru`, `vi`. Even one key goes through the script; do not hand-edit the JSON.
2. Add the key via `add-missing-keys.mjs`, populating its `newKeys` object for every supported locale: `en`, `zh`, `zh-TW`, `fr`, `ja`, `ru`, `vi`. Even one key goes through the script; do not hand-edit the JSON.
3. The script preserves the flat `"translation"` object and keeps keys alphabetically sorted automatically.
4. Run a targeted search for the key in code and locale files.
5. Run `bun run i18n:sync` to normalize file order. This step is mandatory, not optional.
Expand All @@ -66,14 +66,14 @@ For a single known missing key (still script-only, no direct JSON edits):
### Step 1: Run sync and read report

```bash
cd web/default && bun run i18n:sync
cd web && bun run i18n:sync
```

Read `web/default/src/i18n/locales/_reports/_sync-report.json` to see per-locale status (missingCount, extrasCount, untranslatedCount).
Read `web/src/i18n/locales/_reports/_sync-report.json` to see per-locale status (missingCount, extrasCount, untranslatedCount).

### Step 2: Find missing keys (used in code but not in locale files)

Create and run `web/default/scripts/find-missing-keys.mjs`:
Create and run `web/scripts/find-missing-keys.mjs`:

```javascript
import fs from 'node:fs/promises'
Expand Down Expand Up @@ -136,7 +136,7 @@ if (missingKeys.size === 0) {

### Step 3: Find untranslated entries (value equals English)

Create and run `web/default/scripts/find-untranslated.mjs`:
Create and run `web/scripts/find-untranslated.mjs`:

```javascript
import fs from 'node:fs/promises'
Expand Down Expand Up @@ -167,7 +167,7 @@ const brandNames = new Set([
'WeChat','Xinference','Xunfei','AI Proxy','One API',
])

const locales = ['fr', 'ja', 'ru', 'zh', 'vi']
const locales = ['fr', 'ja', 'ru', 'zh', 'zh-TW', 'vi']

for (const locale of locales) {
const locFile = JSON.parse(await fs.readFile(path.join(LOCALES_DIR, `${locale}.json`), 'utf8'))
Expand Down Expand Up @@ -196,7 +196,7 @@ for (const locale of locales) {

### Step 4: Add translations

This script is the ONLY sanctioned way to write locale values. You MUST NOT bypass it by hand-filling the JSON files. Create `web/default/scripts/add-missing-keys.mjs` with this exact structure:
This script is the ONLY sanctioned way to write locale values. You MUST NOT bypass it by hand-filling the JSON files. Create `web/scripts/add-missing-keys.mjs` with this exact structure:

```javascript
import fs from 'node:fs/promises'
Expand All @@ -211,6 +211,7 @@ function stableStringify(obj) {
const newKeys = {
en: { /* "key": "English value" */ },
zh: { /* "key": "中文翻译" */ },
'zh-TW': { /* "key": "繁體中文翻譯" */ },
fr: { /* "key": "Traduction française" */ },
ja: { /* "key": "日本語翻訳" */ },
ru: { /* "key": "Русский перевод" */ },
Expand Down Expand Up @@ -257,7 +258,7 @@ Populate the `newKeys` object with actual translations for each locale.
### Step 5: Verify and clean up

```bash
cd web/default
cd web
node scripts/add-missing-keys.mjs # apply translations
node scripts/find-missing-keys.mjs # verify: should say "All t() keys found"
bun run i18n:sync # normalize file order
Expand Down Expand Up @@ -285,6 +286,7 @@ Delete temporary scripts after completion.
|----------|------|-------|
| English | en | Base locale, key = value |
| Chinese | zh | Fallback locale, must be complete |
| Traditional Chinese | zh-TW | Use natural Traditional Chinese wording |
| French | fr | Many English cognates are valid (e.g., "Configuration") |
| Japanese | ja | Use katakana for technical loanwords |
| Russian | ru | Use formal register |
Expand All @@ -303,7 +305,7 @@ Delete temporary scripts after completion.

## Key Rules

1. All scripts run from `web/default/` directory
1. All scripts run from `web/` directory
2. Use `node scripts/xxx.mjs` (ESM format with top-level await)
3. Sort keys alphabetically when writing locale files
4. Always run `bun run i18n:sync` as the final step
Expand Down
10 changes: 5 additions & 5 deletions .agents/skills/shadcn-ui/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ name: shadcn-ui
description: >-
Give the assistant project-aware shadcn/ui context: components.json,
composition patterns, CLI, registries, theming, and MCP. Use when working on
web/default UI, shadcn components, or presets. Overview aligns with
web UI, shadcn components, or presets. Overview aligns with
https://ui.shadcn.com/docs/skills.md; full upstream skill text is vendored
under vendor/shadcn/.
---
Expand Down Expand Up @@ -37,7 +37,7 @@ npx skills add shadcn/ui
That installs the skill where the `skills` CLI is available. **This repository** keeps the same intent under `.agents/skills/shadcn-ui/` (overview here + **vendored** upstream docs in [`vendor/shadcn/`](./vendor/shadcn/)) and runs the shadcn CLI from the frontend app root:

```bash
cd web/default && bunx shadcn@latest info --json
cd web && bunx shadcn@latest info --json
```

Learn more about skills at [skills.sh](https://skills.sh).
Expand All @@ -48,7 +48,7 @@ Learn more about skills at [skills.sh](https://skills.sh).

### Project context

Run **`shadcn info --json`** (here: `cd web/default && bunx shadcn@latest info --json`) for framework, Tailwind version, aliases, base (`radix` | `base`), icon library, installed components, and resolved paths.
Run **`shadcn info --json`** (here: `cd web && bunx shadcn@latest info --json`) for framework, Tailwind version, aliases, base (`radix` | `base`), icon library, installed components, and resolved paths.

### CLI commands

Expand All @@ -70,7 +70,7 @@ Vendored: [`vendor/shadcn/mcp.md`](./vendor/shadcn/mcp.md). Live docs: [MCP Serv

## How it works

1. **Project detection** — Applies when `components.json` exists (here: `web/default/components.json`).
1. **Project detection** — Applies when `components.json` exists (here: `web/components.json`).
2. **Context injection** — Use `shadcn info --json` as ground truth for imports and APIs.
3. **Pattern enforcement** — Use [`vendor/shadcn/rules/`](./vendor/shadcn/rules/) for concrete markup checks; the complete official workflow reference is listed below for deeper CLI, registry, and preset questions.
4. **Component discovery** — `shadcn docs`, `shadcn search`, MCP, or registries — see the official workflow reference and MCP doc when deeper context is needed.
Expand Down Expand Up @@ -102,4 +102,4 @@ Snapshot from [shadcn-ui/ui `skills/shadcn`](https://github.com/shadcn-ui/ui/tre
| Styling | [`vendor/shadcn/rules/styling.md`](./vendor/shadcn/rules/styling.md) |
| Base vs Radix | [`vendor/shadcn/rules/base-vs-radix.md`](./vendor/shadcn/rules/base-vs-radix.md) |

**Workflow:** Prefer this **root** `SKILL.md` for repo paths (`web/default`, Bun). Read **`vendor/shadcn/official-shadcn-ui-workflow.md`** only when you need the complete official component, registry, or preset workflow. Use **`vendor/shadcn/rules/*.md`** when validating concrete markup.
**Workflow:** Prefer this **root** `SKILL.md` for repo paths (`web`, Bun). Read **`vendor/shadcn/official-shadcn-ui-workflow.md`** only when you need the complete official component, registry, or preset workflow. Use **`vendor/shadcn/rules/*.md`** when validating concrete markup.
5 changes: 1 addition & 4 deletions .dockerignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,5 @@ docs
.eslintcache
.gocache
/web/node_modules
/web/default/node_modules
/web/default/dist
/web/classic/node_modules
/web/classic/dist
/web/dist
!THIRD-PARTY-LICENSES.md
21 changes: 20 additions & 1 deletion .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -64,14 +64,33 @@
# TLS / HTTP 跳过验证设置
# TLS_INSECURE_SKIP_VERIFY=false

# Gin 可信反向代理(逗号分隔的 IP/CIDR)
# 未配置/留空:默认信任 127.0.0.0/8、::1、RFC1918 私网和 fc00::/7,并打印启动告警。
# none:严格模式,不信任任何代理且必须单独使用;显式列表完全替代默认值,应填写代理自身地址。
# TRUSTED_PROXIES=none
# TRUSTED_PROXIES=127.0.0.1,172.20.0.0/16

# Gemini 识别图片 最大图片数量
# GEMINI_VISION_MAX_IMAGE_NUM=16

# 会话密钥
# SESSION_SECRET=random_string
# 启用 Secure session cookie,必须同时配置可信 HTTPS 入口地址;多个地址用英文逗号分隔
# false/未配置:本地 HTTP 模式,关闭 refresh/logout OriginGuard,且不得设置 TRUSTED_URL;兼容本地开发代理。
# true:启用 Secure Refresh Cookie 和严格 OriginGuard,必须同时列出全部可信 HTTPS Origin。
# SESSION_COOKIE_TRUSTED_URL 多项用英文逗号分隔;不支持通配符、路径或域名后缀匹配。
# 这些设置不修改 relay CORS。
# SESSION_COOKIE_SECURE=false
# SESSION_COOKIE_TRUSTED_URL=https://example.com,https://admin.example.com
# 每用户最多保留的活跃登录 Session
# USER_SESSION_ACTIVE_LIMIT=50
# 单用户在签发窗口内允许创建的 Session 总数(包含已撤销)
# USER_SESSION_ISSUANCE_LIMIT=100
# Session 签发计数窗口(秒);不得大于 revoked 保留期,超出时会自动钳制
# USER_SESSION_ISSUANCE_WINDOW_SECONDS=86400
# revoked Session 审计保留天数
# USER_SESSION_REVOKED_RETENTION_DAYS=7
# 最近一小时全局 Session 签发量超过此值时记录告警,不会拒绝登录
# USER_SESSION_HOURLY_ALERT_THRESHOLD=5000

# 其他配置
# 生成默认token
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/electron-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ jobs:
- name: Setup Node.js
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version: '20'
node-version: '22'

- name: Setup Go
uses: actions/setup-go@924ae3a1cded613372ab5595356fb5720e22ba16 # v6.5.0
Expand All @@ -47,7 +47,7 @@ jobs:
NODE_OPTIONS: "--max-old-space-size=4096"
run: |
cd web
bun install
bun install --frozen-lockfile
DISABLE_ESLINT_PLUGIN='true' VITE_REACT_APP_VERSION=$(git describe --tags) bun run build
cd ..

Expand Down
42 changes: 6 additions & 36 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,24 +29,14 @@ jobs:
- uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0
with:
bun-version: latest
- name: Build Frontend (default)
- name: Build Frontend
env:
CI: ""
run: |
cd web
bun install --frozen-lockfile
cd default
DISABLE_ESLINT_PLUGIN='true' VITE_REACT_APP_VERSION=$VERSION bun run build
cd ../..
- name: Build Frontend (classic)
env:
CI: ""
run: |
cd web
bun install --filter ./classic --frozen-lockfile
cd classic
VITE_REACT_APP_VERSION=$VERSION bun run build
cd ../..
cd ..
- name: Set up Go
uses: actions/setup-go@924ae3a1cded613372ab5595356fb5720e22ba16 # v6.5.0
with:
Expand Down Expand Up @@ -88,25 +78,15 @@ jobs:
- uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0
with:
bun-version: latest
- name: Build Frontend (default)
- name: Build Frontend
env:
CI: ""
NODE_OPTIONS: "--max-old-space-size=4096"
run: |
cd web
bun install --frozen-lockfile
cd default
DISABLE_ESLINT_PLUGIN='true' VITE_REACT_APP_VERSION=$VERSION bun run build
cd ../..
- name: Build Frontend (classic)
env:
CI: ""
run: |
cd web
bun install --filter ./classic --frozen-lockfile
cd classic
VITE_REACT_APP_VERSION=$VERSION bun run build
cd ../..
cd ..
- name: Set up Go
uses: actions/setup-go@924ae3a1cded613372ab5595356fb5720e22ba16 # v6.5.0
with:
Expand Down Expand Up @@ -146,24 +126,14 @@ jobs:
- uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0
with:
bun-version: latest
- name: Build Frontend (default)
- name: Build Frontend
env:
CI: ""
run: |
cd web
bun install --frozen-lockfile
cd default
DISABLE_ESLINT_PLUGIN='true' VITE_REACT_APP_VERSION=$VERSION bun run build
cd ../..
- name: Build Frontend (classic)
env:
CI: ""
run: |
cd web
bun install --filter ./classic --frozen-lockfile
cd classic
VITE_REACT_APP_VERSION=$VERSION bun run build
cd ../..
cd ..
- name: Set up Go
uses: actions/setup-go@924ae3a1cded613372ab5595356fb5720e22ba16 # v6.5.0
with:
Expand Down
Loading