Compare commits

...

283 Commits

Author SHA1 Message Date
sagitchu 73490a9be6 fix: use pnpm-workspace.yaml for onlyBuiltDependencies
Create pnpm-workspace.yaml inline in Dockerfile to allow
@tailwindcss/oxide build scripts in pnpm v11.
2026-05-07 20:55:42 +08:00
sagit 5a327459f7 fix: use .npmrc for pnpm onlyBuiltDependencies (#498)
Use .npmrc file for pnpm v11 build scripts approval.
2026-05-07 20:43:29 +08:00
sagitchu f307e7d5eb fix: use .npmrc for pnpm onlyBuiltDependencies config
pnpm config set doesn't support onlyBuiltDependencies in global config.
Use .npmrc file instead.
2026-05-07 20:41:05 +08:00
sagit fdd72979b6 fix: approve @tailwindcss/oxide build script for pnpm v11 (#497)
pnpm v11 blocks build scripts by default. Allow @tailwindcss/oxide via
onlyBuiltDependencies.
2026-05-07 20:26:24 +08:00
sagitchu ad33791a26 fix: approve @tailwindcss/oxide build script for pnpm v11
pnpm v11 blocks build scripts by default; explicitly allow
@tailwindcss/oxide via onlyBuiltDependencies config.
2026-05-07 20:24:17 +08:00
sagit 6320b1f0c1 fix: upgrade Node.js to 22-alpine for corepack/pnpm compat (#496)
## Summary

Node.js 20.19.0 + corepack + pnpm@11.0.8 hits
`ERR_VM_DYNAMIC_IMPORT_CALLBACK_MISSING` during Docker build. Upgrade
builder image to `node:22-alpine` (LTS).

## Verification

Frontend build passes locally with `pnpm run build`.
2026-05-07 20:11:46 +08:00
sagitchu 91d79b6b3a fix: upgrade Node.js to 22-alpine for corepack/pnpm compatibility
node:20.19.0 + corepack + pnpm@11.0.8 hits ERR_VM_DYNAMIC_IMPORT_CALLBACK_MISSING
2026-05-07 20:09:42 +08:00
sagit fc7df6bd64 fix: panel self-upgrade helper not recreating containers (#495)
## Summary

- **Helper container `docker compose up` 不会强制重建容器**:原脚本缺少
`--force-recreate`,Docker Compose
在检测不到配置变化时不会替换运行中的容器,导致拉取了新镜像但旧容器继续运行。新增 `--force-recreate
--remove-orphans` 确保容器被替换。
- **无错误日志**:helper 容器执行失败时没有任何可见反馈。新增 `upgrade.log` 写入部署目录,每一步操作和错误都有记录。
- **"立即升级"按钮永久禁用**:按钮 `isDisabled` 绑定了
`!canOpenSystemUpgradeModal`,该条件要求已完成检查更新且有可用更新,但页面本身有点击时自动检查的逻辑,导致按钮永远无法点击。改为
`!canTriggerSystemUpgrade` 允许自动检查流程触发。

## Verification

| Check | Result |
|-------|--------|
| `go test ./...` | ✅ 498 passed |
| `pnpm run build` | ✅ passed |
| `pnpm run lint` | ✅ passed |
2026-05-07 19:53:53 +08:00
sagitchu 25dfb84324 fix: panel self-upgrade helper not recreating containers
- Add --force-recreate --remove-orphans to docker compose up so helper
  actually replaces running containers with newly pulled images
- Add upgrade.log file for post-mortem debugging when helper fails
- Add pre-flight validation for docker-compose.yml and .env
- Fix "立即升级" button permanently disabled by relaxing the disabled
  condition so auto-check on click can fire
2026-05-07 19:51:18 +08:00
sagit 4ebd6703fe fix: harden proxy protocol rollout safety (#494) 2026-05-07 16:37:51 +08:00
sagit 1f53a39784 Update contact link from group to channel (#493) 2026-05-07 01:26:56 +00:00
sagit 5ebd4c2a91 feat: add panel self-upgrade workflow (#492) 2026-05-06 17:58:01 +08:00
sagit 6c93d829c6 fix: refine advanced settings layout
Merge PR #491
2026-05-04 17:33:56 +08:00
sagitchu 5d22d4cb06 fix: refine advanced settings layout 2026-05-04 17:25:58 +08:00
sagit e5cd5af550 Use custom probe targets for diagnostics 2026-05-02 14:27:20 +08:00
sagitchu cdcdfd8ff0 fix: use custom probe targets for diagnostics
Move custom probe target controls into the tunnel advanced settings and reuse the configured target in tunnel diagnosis output.
2026-05-02 14:23:51 +08:00
sagit 791773fd62 Add custom tunnel probe targets (#488) 2026-05-02 00:54:54 +08:00
sagitchu 13764b4615 fix: reject malformed probe target updates 2026-05-02 00:12:41 +08:00
sagitchu 4c882d907b fix: preserve probe targets on legacy updates 2026-05-02 00:08:24 +08:00
sagitchu 6033e39466 fix: preserve probe targets in backups 2026-05-02 00:02:23 +08:00
sagitchu 0f3242bf11 fix: reject raw probe target whitespace 2026-05-01 23:54:31 +08:00
sagitchu d97d91801d fix: reject leading zero probe IPv4 2026-05-01 23:50:41 +08:00
sagitchu 727ef56c67 fix: improve probe target form feedback 2026-05-01 23:46:56 +08:00
sagitchu a40150b136 fix: type tunnel probe target payloads 2026-05-01 23:42:21 +08:00
sagitchu a923ec4785 fix: validate probe target port input 2026-05-01 23:39:14 +08:00
sagitchu 42c5492c1d feat: add tunnel probe target UI 2026-05-01 23:36:14 +08:00
sagitchu 869d726b7a fix: preserve type one quality probe owner 2026-05-01 23:32:00 +08:00
sagitchu 55a931510b feat: use probe target for tunnel quality checks 2026-05-01 23:28:26 +08:00
sagitchu a259dd83b2 fix: load probe target with tunnel record 2026-05-01 23:24:48 +08:00
sagitchu cc0b8de2e1 feat: use probe target for best exit scoring 2026-05-01 23:20:50 +08:00
sagitchu 58ef260755 fix: migrate legacy tunnel probe target columns 2026-05-01 23:15:21 +08:00
sagitchu 521fe79b15 fix: validate tunnel probe target before cleanup 2026-05-01 23:10:47 +08:00
sagitchu 90012725cc feat: persist tunnel probe targets 2026-05-01 22:58:47 +08:00
sagitchu 615d9e67eb fix: validate probe target host shape 2026-05-01 22:53:37 +08:00
sagitchu a131b70613 fix: reject probe target scheme prefixes 2026-05-01 22:49:34 +08:00
sagitchu cbed4eab23 feat: add tunnel probe target normalization 2026-05-01 22:45:58 +08:00
sagitchu c2745dcd56 docs: add custom best exit probe target plan 2026-05-01 22:22:57 +08:00
sagitchu ad4109594a docs: add custom best exit probe target design 2026-05-01 22:14:02 +08:00
sagit efc8c75dcb Show current best exit state (#487)
## Summary
- Add backend display-state snapshots and response enrichment for best
multi-exit tunnels.
- Surface direct-entry and final-chain-hop owner choices, including
waiting, partial, multi-exit, and stale-exit safeguards.
- Render compact current best-exit text in tunnel table/card views with
native tooltip details.

## Test Plan
- [x] `rtk go test ./...` from `go-backend`
- [x] `pnpm run build` from `vite-frontend`
2026-05-01 13:58:30 +08:00
sagitchu e5acc49186 feat: show current best exit state 2026-05-01 13:30:46 +08:00
sagitchu d98377a297 docs: add best exit current display plan 2026-05-01 12:24:50 +08:00
sagitchu 950e9a9ba8 docs: add best exit current display design 2026-05-01 12:18:29 +08:00
sagit 3f3159aafd Add best exit selection (#486)
* docs: add best exit selection design

* feat: add best exit selection
2026-05-01 08:12:17 +08:00
sagit 5e8d0682c0 Modify wallet addresses in README.md (#485)
Updated wallet addresses for BNB(BEP20), TRC20, and polygon.
2026-04-30 07:43:34 +00:00
sagit 3c0e833cfc fix: reduce runtime sync disruptions (#484) 2026-04-30 14:36:26 +08:00
sagit 60311d3e47 fix: prune stale agent traffic counters (#483)
## Summary
- Prune stale agent traffic counters when services are deleted or config
is reloaded.
- Ignore late traffic updates from services no longer registered, while
preserving pending bytes until the next report flush.
- Add regression tests for stale traffic cleanup and
report-before-delete behavior.

## Test Plan
- rtk go test ./service
- rtk go test ./service ./socket ./api
- rtk go test ./...
- CGO_ENABLED=0 rtk go build .
- rtk git diff --check
2026-04-30 09:56:32 +08:00
sagitchu b4192c9e94 fix: prune stale agent traffic counters 2026-04-30 09:54:02 +08:00
sagit f05e9480ee Add monitoring retention planning docs (#482)
## Summary
- Add the design spec for monitoring retention and storage display.
- Add the implementation plan used for the monitoring retention feature.

## Test Plan
- Documentation-only change; no runtime tests required.
2026-04-29 15:16:35 +08:00
sagitchu 9861b44107 docs: add monitoring retention plan 2026-04-29 15:14:53 +08:00
sagit d8144821e6 Add monitoring retention controls (#481)
## Summary
- Add configurable monitoring retention days for node metrics, tunnel
metrics, service monitor results, and tunnel quality history.
- Add an admin-only storage summary endpoint and show database usage on
the config page.
- Keep tunnel quality cleanup active even when real-time quality probing
is disabled.

## Test Plan
- go test ./... (go-backend)
- pnpm run build (vite-frontend)
2026-04-28 13:27:44 +08:00
sagitchu 023be27287 feat: add monitoring retention controls 2026-04-28 11:41:07 +08:00
sagit e8d5687419 docs: add completed per-IP rule limits plan (#480)
## Summary
- Add the completed per-IP rule limits implementation plan to docs.
- Mark all task steps complete and reference PR #479 plus tag
3.0.0-beta2.

## Test Plan
- [x] Verified no unchecked plan step boxes remain
- [x] Reviewed docs diff for accidental secrets or unrelated content
2026-04-28 10:31:49 +08:00
sagitchu 0fbe570597 docs: add completed per-IP rule limits plan 2026-04-28 10:29:21 +08:00
sagit 4c52d7fec2 Add per-IP forward rule limits (#479)
## Summary
- Add per-forward per-IP connection and bandwidth limit fields across
backend persistence, APIs, backup/list paths, and the forward rule form.
- Sync per-IP runtime limiter payloads to GOST while preserving shared
user/total limiter semantics through composite limiter references.
- Add GOST/x coverage and UDP listener support for per-client limiters
without breaking packet semantics.

## Test Plan
- [x] `rtk go test ./...` in `go-backend` (392 passed)
- [x] `rtk go test ./...` in `go-gost/x` (42 passed)
- [x] `pnpm run build` in `vite-frontend`

## Notes
- Existing total `maxConn`/`speedId` behavior is preserved; per-IP
limits are additive.
- Normal users cannot set or modify per-IP bandwidth rules.
2026-04-28 00:29:00 +08:00
sagitchu 3373e5ade9 fix: preserve shared limiters with per-IP rules 2026-04-28 00:18:32 +08:00
sagitchu bd27b94909 fix: omit per-IP speed payload for users 2026-04-27 23:34:35 +08:00
sagitchu a5a500bc0f feat: add per-IP limit controls 2026-04-27 23:17:02 +08:00
sagitchu edfe2a2372 fix: preserve udp packet semantics with limiters 2026-04-27 23:13:16 +08:00
sagitchu 7a9ba8bd81 fix: apply per-client limits to udp listener 2026-04-27 23:05:31 +08:00
sagitchu 46394388b1 feat: sync per-IP runtime limiters 2026-04-27 22:32:35 +08:00
sagitchu dec337d46b fix: enforce per-IP speed update permissions 2026-04-27 22:26:34 +08:00
sagitchu 9e8d27d98e feat: expose per-IP forward limit fields 2026-04-27 22:20:26 +08:00
sagitchu a2000e4d98 fix: preserve per-IP forward limits during rollback 2026-04-27 22:16:38 +08:00
sagitchu 2b76a9f0be feat: persist per-IP forward limits 2026-04-27 22:07:04 +08:00
sagitchu 54d7dfb7c9 docs: design per-IP rule limits 2026-04-27 17:24:25 +08:00
sagit 9f19d5fe15 fix: send valid announcement update payload 2026-04-27 15:34:47 +08:00
sagit 2ca3849917 fix: apply proxy protocol and max connection settings 2026-04-27 10:54:25 +08:00
sagit 58d2e89147 fix: reduce reconnect redeploy and metrics load (#476)
* fix: reduce reconnect redeploy and metrics load

Throttle node-online redeploy retries and lower the agent metric cadence so brief reconnect churn no longer fans out into repeated runtime syncs and backend connection pressure.

* docs: add follow-up implementation design notes

Document the planned flow upload batching work and the local remote-address toggle so the next changesets can implement them against an agreed design.
2026-04-26 23:35:35 +08:00
sagit 87a1a34ad5 refactor: batch flow upload processing (#474)
* test: cover flow upload batch semantics

* refactor: batch flow upload persistence

* refactor: batch flow upload processing

* test: harden flow upload batch regression coverage
2026-04-26 20:45:48 +08:00
sagit a625884d61 fix: remove unwanted hover underline from forward advanced settings (#473)
* fix: remove forward advanced settings hover underline

* fix: clear frontend lint warnings
2026-04-26 19:12:38 +08:00
sagit 799bb66fe5 feat: add local remote address toggle (#472) 2026-04-26 16:30:05 +08:00
sagit 3f374df724 fix: 保留用户/规则高级设置并增强节点运行时恢复 (#468)
* fix: 用户编辑时 maxConn 字段未正确回填

- User 接口添加 maxConn 类型定义
- handleEdit 中回填 maxConn 值
- normalizeUserItem 添加 maxConn 字段处理

解决编辑用户时最大连接数显示为 0 的问题

* fix: 保留转发设置并增强节点运行时恢复
2026-04-25 18:12:13 +08:00
sagit 9b923a2d0b fix: remove duplicate maxConn input in user form (#467) 2026-04-24 21:56:46 +08:00
sagit d9f28f53c7 style: move advanced settings to bottom and optimize UI (#466) 2026-04-24 19:10:36 +08:00
sagit 1d08a1ccfc fix: ensure page refresh to login page upon logout (#465) 2026-04-23 20:43:27 +08:00
sagit db25ba2cbe style: move maxConn and speed limit inputs to advanced settings accordion (#464) 2026-04-23 20:29:52 +08:00
sagit a498067261 fix: properly initialize maxConn in forward rules (#463)
* fix: initialize maxConn in forward creation and edit forms

* fix: add maxConn to Forward interface
2026-04-23 20:23:18 +08:00
sagit b5922dccf2 fix: include maxConn when submitting forward forms (#462)
* fix: frontend missing maxConn setting during forward creation

* docs: check off plan
2026-04-23 20:11:20 +08:00
sagit c259645227 feat: implement user and forward max connection limit (#461)
* docs: add implementation plan for max conn limit

* feat: add CLimiters support for websocket reporter

* feat: add max_conn field to user and forward models

* feat: implement max conn limiter dispatching

* feat: add maxConn to user and forward CRUD API

* feat: add max conn UI to user management and forward rules

* fix: load MaxConn in get forward record and add e2e contract test for max conn limit
2026-04-23 17:35:39 +08:00
sagitchu bdc2c4ecbb fix(backend): dynamically start/stop tunnel quality prober based on config 2026-04-23 14:14:24 +08:00
sagitchu a070d0f4d3 fix(backend): allow setting reserved ip addresses as target
Only forbid internal networks (loopback and private ips), removing restrictions on reserved addresses like multicast or unspecified.
2026-04-22 19:00:21 +08:00
sagitchu eecdd62d3a perf(backend): optimize kcp tunnel parameters for high throughput and low latency 2026-04-22 16:29:02 +08:00
sagitchu e6d3b847bb fix(backend): properly identify and clean up orphaned tunnel_%d services 2026-04-22 16:18:57 +08:00
sagitchu 0b49cd720f fix(backend): use proper protocol for chain hop diagnosis and tcp for external targets 2026-04-22 14:02:59 +08:00
sagitchu 4f488ae7ef fix(backend): properly implement tunnel_%d cleanup that was lost during revert 2026-04-22 11:32:49 +08:00
sagitchu 2b2b417f91 fix(gost): ensure JSON floats are correctly converted in GetInt and remove accidental binary 2026-04-22 11:17:59 +08:00
sagitchu 01b4c3e3eb fix: add workbox-window as explicit dependency to resolve pnpm strict resolution in CI 2026-04-22 11:05:37 +08:00
sagitchu e7c967df00 chore: migrate frontend package manager from npm to pnpm 2026-04-22 11:02:43 +08:00
sagitchu efaf920e51 fix: ensure rollbackTunnelRuntime includes tunnel_%d in cleanup 2026-04-22 09:51:35 +08:00
sagitchu 9aff669c0e fix: ensure tunnel protocol and KCP config are correctly processed and cleaned up 2026-04-22 09:41:41 +08:00
sagitchu 6e60f5cfbd fix: add visually hidden DialogTitle to resolve a11y warning and fix modal background 2026-04-22 09:21:47 +08:00
sagitchu a03c320b89 fix(gost): prevent panic in service parsing with empty md 2026-04-21 22:11:22 +08:00
sagitchu 61dba0ae57 fix: remove trailing brace in tunnel.tsx to resolve CI error 2026-04-21 20:20:19 +08:00
sagitchu f3d6366471 fix: increase kcp tunnel bandwidth limit and fix modal backgrounds 2026-04-21 20:16:58 +08:00
sagitchu c431d79403 fix: correct tunnel protocol handling for KCP cleanup and diagnosis
- Fix KCP tunnel not reclaimed after deletion: service name was
  hardcoded to {id}_tls but services were created as {id}_kcp,
  causing DeleteService to never find the actual KCP service.
  Now reads tunnel.Protocol from DB and derives correct name.

- Fix KCP diagnosis using TCP ping instead of UDP ping:
  tunnel.Protocol was always hardcoded to 'tls' at creation,
  so isUDPBasedProtocol() never matched kcp tunnels. Now
  stores the actual protocol from entry node configuration.

- Fix addTunnelServiceOnNode to extract service name from
  serviceData instead of hardcoding _tls suffix.

- Fix rollbackTunnelRuntime to accept protocol parameter
  so retry cleanup uses correct service name.

- UpdateTunnelTx now persists protocol on tunnel updates.
2026-04-21 18:48:11 +08:00
sagitchu 5107f59d94 fix: tolerate offline nodes when controlling forward services and editing tunnels
- controlForwardServices: skip offline nodes instead of failing entire operation,
  so forward pause/resume/delete works when some entry nodes are offline
- onNodeOnline: always sync forward state on node reconnect (not just post-upgrade),
  so forwards that changed status while a node was offline get synced
- add ListForwardIDsByNode repo method to sync all forwards (including paused)
- tunnel edit UI: allow deselecting already-selected offline nodes in
  entry/chain/exit selectors, matching the backend's existing tolerance
2026-04-21 16:53:47 +08:00
sagitchu 431613cb6a fix(frontend): listen to session changes so logout redirects to login page 2026-04-21 16:24:46 +08:00
sagitchu a6b218f3ee fix(frontend): increase sidebar background opacity to reduce grayness 2026-04-21 16:12:28 +08:00
sagitchu d5d26d9cf9 fix(frontend): hide scrollbars on sidebar, modals, and secondary lists; fix diagnosis modal bg 2026-04-21 16:00:06 +08:00
sagitchu c1bc795674 fix(kcp): enable congestion control, add FEC, and fix remote node UDP diagnosis
- KCP: switch from fast3 to fast2 mode, enable FEC (10/3), enable
  congestion control (nc=0) for automatic rate adaptation
- go-gost/x: support kcp.nc metadata to override mode-initialized
  NoCongestion value in dialer and listener Init()
- Diagnosis: add udpPingViaRemoteNode, fix pingViaRemoteNode to
  dispatch based on protocol, add Protocol field to federation
  diagnose request structs
2026-04-21 15:41:32 +08:00
sagitchu 30e1473f06 fix(traffic): fix flow counter inflation from TOCTOU race in agent traffic reporter
Replace read-then-subtract pattern in collectAndReport with atomic
swap-to-zero to eliminate race where AddTraffic increments counters
between snapshot and clearReportedTraffic, causing residual traffic
to accumulate indefinitely and inflate user flow counters.

Also add defensive check in processFlowItem to skip AddFlow when
forward no longer exists, and send DeleteService to clean up orphaned
agent services.
2026-04-21 14:32:08 +08:00
sagitchu eaf16bf17b fix(frontend): enable horizontal scroll on all table lists for mobile
Change overflow-hidden to overflow-auto in table wrapper classNames
across all list pages (rules, tunnels, nodes, limits, groups, users,
monitor views). Also add table-fixed min-w to forward all-rules table
and fix unescaped entities in dashboard.
2026-04-21 14:18:44 +08:00
sagitchu e995d70be7 feat(diagnosis): add protocol-aware connectivity diagnosis for tunnel chains
- Pass tunnel protocol through diagnosis work items
- Support protocol-specific ping (TCP/UDP/KCP) via remote nodes
- Add KCP probe support in websocket_reporter for chain hop testing
2026-04-21 14:00:02 +08:00
sagitchu a968a10792 fix(frontend): fix dropdown padding, hide scrollbar, login input transparency
- Increase dropdown menu padding from p-1 to p-1.5
- Hide scrollbar in dropdown-menu-content and select listbox
- Change login page input bg from white/50 to white/10 for transparency
2026-04-21 12:41:49 +08:00
sagitchu ea156c33bc style(frontend): sync remaining glass UI theme files and cyberpunk theme 2026-04-21 12:40:00 +08:00
sagitchu 29407c90b6 perf(kcp): optimize tunnel transport defaults for high throughput
- Set KCP mode to fast3 (NoDelay:1, Interval:10ms) for lower latency
- Double SndWnd/RcvWnd from 1024 to 2048 for higher BDP
- Disable FEC (datashard:0, parityshard:0) to eliminate 30% overhead
- Disable compression for tunnel transport
- Increase relay mux MaxStreamBuffer to 2MB for better UDP throughput
- Add kcp.datashard/kcp.parityshard metadata keys support

Before: 210Mbps TCP / 35Mbps UDP (93% loss)
After:  should approach direct-connection speed (~400Mbps+)
2026-04-21 11:33:41 +08:00
sagitchu 37341af2d1 fix(kcp): prevent zero-value override of window/buffer params causing 10x perf drop
The metadata parser unconditionally assigned GetInt results (which
return 0 for missing keys) to all KCP config fields, overwriting
defaults like SndWnd=1024, RcvWnd=1024, StreamBuf=2097152 with 0.

KCP's WndSize only applies positive values, so snd_wnd=0 caused
the write path condition waitsnd < s.kcp.snd_wnd to never succeed,
effectively stalling throughput at ~10Mbps instead of 400Mbps+.

- Only apply metadata values when the key actually exists (IsExists check)
- Use Clone() instead of sharing the global DefaultConfig pointer
- Add Config.Clone() deep-copy method
2026-04-21 10:20:21 +08:00
sagitchu bb48ab00bd fix(udp): mark connection active on WriteQueue to prevent idle timeout race 2026-04-21 09:55:18 +08:00
sagitchu f6d2ab3270 fix(frontend): fix blank page after logout and login page branding 2026-04-21 09:33:04 +08:00
sagitchu b382caa347 refactor(frontend): remove deprecated /settings route, redirect to /config 2026-04-21 09:26:44 +08:00
sagitchu 288c5d7152 fix: restore SSRF/security protections after glass UI cherry-pick 2026-04-21 09:20:04 +08:00
sagitchu b42516cea1 fix(ui): refine glassmorphism and page transition animations
- Added custom light/dark background images to replace unsplash URLs.
- Enhanced active sidebar item shadow and backdrop blur for better visibility.
- Fixed double loading flickers on user, node, group, and panel-sharing pages.
- Removed opacity transitions from AnimatedPage to prevent backdrop-filter rendering issues during page navigation.
2026-04-21 09:19:02 +08:00
sagitchu 74ed74ba00 style: apply frosted glass backgrounds to inner cards and nested elements
- Replaced solid backgrounds (bg-white, bg-default-50) with high-blur translucent glass (backdrop-blur-3xl) inside tunnel topology nodes, dashboard forward rules, and flow charts.
- Matched the aesthetic of the inner components to inherit the adaptive light/dark mode root backgrounds.
2026-04-21 09:19:02 +08:00
sagitchu 7c1f5ca660 style: improve glassmorphism UI for background adaptability
- Increase backdrop blur and lower white/black background opacity on inner elements (tables, charts, tabs)
- Apply higher blur to admin layout sidebar and H5 layout navigation bar
- Remove solid backgrounds inside nested cards to inherit background themes
2026-04-21 09:19:02 +08:00
sagitchu 26013f8dfa fix(ui): improve background handling and PWA update prompts
- Add adaptive solid color background support for dark/light themes.
- Replace mesh gradient with semi-transparent blurred background images.
- Fix background scrolling issue on mobile browsers.
- Remove borders from specific cards for consistent UI styling.
- Prevent caching of PWA service worker files in Nginx.
- Introduce interactive toast prompt for PWA updates instead of silent refresh.
2026-04-21 09:19:02 +08:00
sagitchu ab0f36ba7b style: optimize card and table backgrounds for better custom background visibility 2026-04-21 09:19:02 +08:00
sagitchu cde379a1f4 fix: remove unused imports and leftover jsx in settings 2026-04-21 09:19:02 +08:00
sagitchu 96fc790ed7 feat: add global background image setting to config page 2026-04-21 09:19:02 +08:00
sagitchu f0351107dd fix: frontend browser caching issue
Disable caching for index.html and reduce static assets cache to 30d.
2026-04-21 09:19:02 +08:00
sagit 534d36f0a1 feat(ui): add persistent custom background image upload feature (#415) 2026-04-21 09:19:02 +08:00
sagit 7668e24f4b feat(ui): redesign with transparent liquid glass (#414)
* docs: add design spec for iOS 26 Liquid Glass UI redesign

* docs: add implementation plan for iOS 26 Liquid Glass UI redesign

* feat(ui): add liquid glass CSS variables and update root layouts

* feat(ui): update Card and Modal components to iOS 26 Liquid Glass style

* feat(ui): redesign dashboard page to Liquid Glass style

* feat(ui): redesign node management page cards and charts

* feat(ui): redesign monitor page to Liquid Glass style

* feat(ui): redesign group and panel-sharing cards to Liquid Glass

* feat(ui): redesign settings and user components to Liquid Glass

* feat(ui): redesign profile and auth pages to Liquid Glass

* fix(ui): revert to LineChart to fix compilation issues

* refactor(ui): extract dashboard user header and cleanup admin layout

* feat(ui): refine monitor page hero metrics and fix build

* fix(ui): real data for monitor hero metrics and card padding adjustments

* fix(ui): apply global card padding and fix index layouts

* feat(ui): implement liquid-glass-react for all Card components

* fix(ui): resolve liquid-glass-react rendering issues causing invisible text and broken layout

* fix(ui): native CSS liquid-glass effect replacing NPM package

* fix(ui): cleanup duplicate closing tags and complete liquid glass tables

* fix(ui): apply perfect rounded corners to list views and table headers in non-compact mode

* fix(ui): apply liquid glass styling to grouped rules view in forward page

* fix(ui): re-implement liquid-glass natively to prevent text distortion and remove package dependency

* fix(ui): remove mouse distortion and preserve proper liquid glass texture

* fix(ui): remove svg filter causing text distortion and replace with pure css liquid glass

* fix(ui): apply properly scoped border radius to table headers

* fix(ui): remove hardcoded bg-default-50/60 from TableHeader

* fix(ui): apply global liquid glass styling and transparent overlays to all modals and dialogs

* fix(ui): remove absolute/relative class conflicts hiding Dialog modales and implement pure transparent layout

* feat(ui): apply global liquid glass styling to cards, buttons, and diagnosis modals
2026-04-21 09:19:02 +08:00
sagitchu c1f96180f5 docs: simplify AGENTS.md files, remove stale info and redundancy 2026-04-21 00:17:31 +08:00
sagitchu 630e012ec1 fix(tunnel): resolve UDP stream interruption and add KCP protocol support
- Increase UDP listener default TTL from 5s to 30s to prevent idle disconnect
- Add mux keepalive config (15s interval, 45s timeout) to tunnel relay handler
- Add KCP as tunnel chain transport protocol with keepalive and UDP mode default
- Add KCP protocol option to tunnel UI (frontend)
- Remove generic 'tcp' fallback key from KCP metadata to prevent false TCP mode
- Simplify forward service config by removing unused tunnelTLSProtocol parameter
2026-04-20 23:57:43 +08:00
sagitchu 7f14bd30fa fix(ci): update Dockerfile to Go 1.25 2026-04-20 20:55:56 +08:00
sagitchu 8611748c46 fix(security): patch SSRF and info disclosure vulnerabilities 2026-04-20 11:31:17 +08:00
sagitchu 77b7f066f3 fix(security): update vulnerable dependencies in go-backend 2026-04-20 10:46:27 +08:00
sagitchu 1970a74f6a fix(security): update vulnerable dependencies in go-gost/x 2026-04-20 10:46:27 +08:00
sagitchu b66c4966ba fix(security): update vulnerable dependencies in go-gost 2026-04-20 10:46:27 +08:00
sagit ebf412b9df fix(ui): mobile modal scroll behavior (#412)
* docs: add announcement popup design spec

* docs: add announcement popup implementation plan

* fix(ui): change modal scroll behavior to inside for mobile screens

Fixes layout issue where modal footer and action buttons are pushed off screen on mobile devices.
2026-04-04 19:34:40 +08:00
sagit 9a85363e44 feat: Announcement Popup Notification (#411)
* docs: add announcement popup design spec

* docs: add announcement popup implementation plan

* feat(api): include update_time in announcement response

* feat(ui): add update_time to AnnouncementData interface

* feat(ui): create AnnouncementModal component

* feat(ui): manage announcement modal state in dashboard hook

* feat(ui): add announcement modal to dashboard layout
2026-04-04 13:00:11 +08:00
sagit 7b9b59644e fix(ui): restore missing UI transition animations (#408)
- Wrap `Routes` with `AnimatePresence` to enable framer-motion page transition exit animations and fix harsh route changes.
- Replace `tw-animate-css` with `tailwindcss-animate` to properly bundle transition classes (like `animate-in`, `animate-accordion-down`) under Tailwind v4.
- This restores animation to modals, accordions, and all page navigations.
- Fix accessibility warning on table cell span element.

Fixes #283
2026-04-03 20:55:43 +08:00
sagit 4e088afb29 feat: show license expiry date when commercial license is activated (#407)
## Summary
- Extracted the `expiry` attribute from Keygen's `ValidateResponse`.
- Updated `licenseActivate` and `validateLicenseJob` to store
`license_expiry` in the database.
- Read `license_expiry` into the frontend `siteConfig` map.
- Updated the description in the commercial license input to dynamically
show the expiry date: '已激活商业版授权 (有效期至: YYYY-MM-DD)' or '已激活商业版授权 (永久有效)'
if it doesn't expire.
2026-04-03 17:39:07 +08:00
sagitchu 1b3ae44940 feat: show license expiry date when commercial license is activated 2026-04-03 17:37:05 +08:00
sagit a91abbfebd feat(ui): move commercial brand settings to license card (#406)
## Summary
- Conditionally render brand settings (`app_name`, `app_logo`,
`app_favicon`, `hide_footer_brand`) inside the Commercial License card.
- Hide them from the main Basic Settings list.
- Only show these options if the user has successfully activated a
commercial license.
2026-04-03 17:31:00 +08:00
sagitchu 513591fe67 feat(ui): conditionally render brand settings inside commercial license card 2026-04-03 17:27:48 +08:00
sagit 9412d24c02 feat: show tunnel traffic ratio in forward list (#405)
## Summary
- Display the tunnel's traffic ratio in the forward (rules) list UI to
save administrators an extra click to the tunnels page.
- Resolves #forward-show-tunnel-ratio

## Changes
- Updated the table row in `forward.tsx` to show the traffic multiplier.
- It will only display when the ratio is not `1x` to prevent UI clutter.
- The backend `forwardList` API was already returning `trafficRatio`
from a `LEFT JOIN tunnel`, so no backend modifications were required.
2026-04-03 16:34:04 +08:00
sagit ab3ca019d2 fix: prevent idle transaction timeout in postgresql during tunnel update (#404)
## Summary
- Moved `tx := h.repo.BeginTx()` below `applyFederationRuntime` in
`tunnelUpdate`
- This prevents the database transaction from remaining idle for an
extended period of time while making HTTP network requests to federation
nodes, which can trigger the `idle_in_transaction_session_timeout` or
cause connection pool exhaustion in PostgreSQL.

## Test Plan
- [x] Backend tests passed (`go test ./...`)
- [ ] Verify tunnel updates no longer timeout with PostgreSQL
2026-04-03 16:30:35 +08:00
sagitchu b892b2640e feat(ui): display tunnel traffic ratio in forward list 2026-04-03 16:18:01 +08:00
sagitchu 3da9b14bfe fix(backend): prevent idle transaction timeout in postgresql during tunnel update 2026-04-03 15:52:48 +08:00
sagit 49ab2915ee feat: commercial white-label support (#403)
* fix: increase updateTunnel timeout to 120s

Editing tunnel entry nodes triggers forward sync to all entry nodes.
If nodes are offline or many forwards exist, the sync can exceed
the default 30s timeout. Match the timeout used by other heavy
operations like batchDeleteTunnels.

* docs: add commercial white-label design spec

* docs: add commercial white-label implementation plan

* feat: add license activation endpoint and authorization check for commercial config keys

* feat: add frontend api and update site config state for license

* feat: conditionally hide flvx footer brand

* feat: ui settings for commercial white-label and license activation

* fix: add missing licenseActivateRequest and fix GetConfig in handler.go

* docs: add keygen.sh license integration design spec

* docs: add keygen.sh integration implementation plan

* feat: add machine fingerprint generation

* feat: add keygen.sh api client

* feat: integrate keygen into license activation endpoint

* feat: add periodic license validation job

* fix: remove accidentally leaked dash kernel test codes that caused compilation failures

* fix: correct keygen validation scope and binding logic

* feat: hardcode Keygen.sh account ID

* fix: relax strict validation matching after successful machine activation
2026-04-03 07:23:22 +00:00
sagit becf87118f fix(backend): randomize new tunnel relay ports safely (#402)
## Summary
- randomize auto-assigned ports only for newly created tunnel relay and
exit nodes
- keep tunnel updates stable while tightening batch forward
tunnel-switch validation
- update contract coverage for deferred offline runtime handling and
missing entry-node fixtures

## Test Plan
- go test ./... -count=1
2026-04-01 20:19:10 +08:00
sagitchu 608fbf74de fix(backend): randomize new tunnel relay ports safely 2026-04-01 20:16:31 +08:00
sagit 8b9cdef0e4 feat: add configurable GitHub proxy settings (#401)
* docs: add GitHub proxy config design spec

* docs: add GitHub proxy config implementation plan

* feat(backend): use configurable github proxy for node upgrades

* feat(backend): use configurable github proxy for node install command

* feat(frontend): add github proxy config settings

* feat(script): support configurable github proxy in installer flows

Honor custom GitHub mirror settings across interactive and env-driven installer/update paths so script downloads match the panel configuration. Add shell regressions to lock down proxy prompting, URL recomputation, and non-interactive fallback behavior.
2026-04-01 15:59:44 +08:00
sagit 3c10727e08 feat(config): add floating save button (FAB) for issue #266 (#400)
* docs: add floating save button design spec for issue #266

* docs: add implementation plan for floating save button

* feat(config): add floating save button (FAB) for issue #266
2026-04-01 01:50:32 +00:00
qimaoww 841d43344a fix(backend): 修复转发监听 IP 为 IPv6 时报missing port in address (#397)
* fix(backend): handle IPv6 forward bind IP ports

* test(handler): add IPv6 bindIP test cases for forward service config

---------

Co-authored-by: sagit <36596628+Sagit-chu@users.noreply.github.com>
Co-authored-by: sagitchu <sagitchu@gmail.com>
2026-03-31 03:24:56 +00:00
sagit 5efe790937 fix: 实现用户端口数量限制验证 (#399)
- 在 ensureUserTunnelForwardAllowed 中添加 User.Num 限制验证
- 在 ensureUserTunnelForwardAllowed 中添加 UserTunnel.Num 限制验证
- 新增 CountActiveForwardsByUser 和 CountActiveForwardsByUserTunnel 函数
- 添加转发数量限制的契约测试

Closes #390
2026-03-31 02:52:49 +00:00
sagit eec6cb4298 fix(agent): add port cleanup before resuming paused services (#398)
When user traffic quota is exceeded, services are paused with
ForceClosePortConnections to kill active connections. However,
when admin resets quota and resumes services, the resume logic
was missing this cleanup, causing "address already in use" errors.

Changes:
- Add ForceClosePortConnections call in resumeServices (socket & api)
- Add ForceClosePortConnections call in resumeService (api single)
- Increase wait time from 100ms to 500ms for port release

Fixes #387
2026-03-31 10:28:28 +08:00
Misaka Master 352fc82907 fix(backend): include interfaceName in ListNodes API response (#395)
- Add missing interfaceName field to node list API response map
- Fixes bug where interface name value disappears after page refresh
- Field is correctly saved to DB but was not returned in API response

Co-authored-by: Alex-WU-Gen-9-png <github@enomria0785.eu.org>
2026-03-29 20:59:52 +08:00
sagit 87722e461c feat(monitor): hop-by-hop latency metrics for forwarding chain (#394) 2026-03-29 18:59:06 +08:00
sagit 701b4011cb feat: move tunnel quality monitor toggle from /settings to /config (#393)
将实时隧道质量检测开关从 /settings 移到 /config 页面,统一管理全局配置项。
2026-03-29 15:48:45 +08:00
sagitchu d128d2f657 feat: move tunnel quality monitor toggle from /settings to /config 2026-03-29 15:47:10 +08:00
sagit 400a40fe80 fix: 节点离线时允许删除隧道关联,但禁止新增隧道 (#392)
## 修复内容

修复 #342

### 问题
当节点离线时,用户无法编辑隧道配置(包括更换节点),也无法修改相关的转发规则。

### 变更

**Backend:**
- `prepareTunnelCreateState`: 更新隧道时,允许已关联的离线节点保留(用户可能在移除它们),仅拒绝新增的离线节点
- `syncForwardServicesWithWarnings`: 离线节点跳过下发并返回警告,不再硬性失败
- `applyTunnelRuntime`: 所有节点类型(入口/转发链/出口)均支持离线错误延迟处理
- 新增 `isNodeOfflineOrTimeoutError` 辅助函数

**Frontend:**
- `validateTunnelForm`: 新增 `isEdit` 参数,编辑模式下跳过离线节点验证
- `tunnel.tsx`: 传递 `isEdit` 标志到表单验证
2026-03-28 19:31:54 +08:00
sagitchu 103290ed35 fix: 节点离线时允许删除隧道关联,但禁止新增隧道 (#342)
- prepareTunnelCreateState: 更新隧道时允许已关联的离线节点,仅拒绝新增的离线节点
- syncForwardServicesWithWarnings: 离线节点跳过下发并返回警告,不再硬性失败
- applyTunnelRuntime: 所有节点类型均支持离线错误延迟处理
- 前端 validateTunnelForm: 编辑模式下跳过离线节点验证

Closes #342
2026-03-28 19:30:30 +08:00
sagitchu 363e714603 fix: 支持跨版本隧道链路 (v6入v4出 / v4入v6出)
问题:selectTunnelDialHost 只检查同版本兼容 (v4->v4, v6->v6),
导致 v6-only 入口节点连接 v4-only 出口节点时报错:
"节点链路不兼容"

修复:在 default 分支增加跨版本支持:
- fromV6 && toV4 → 返回出口 v4 地址
- fromV4 && toV6 → 返回出口 v6 地址

更新测试用例以反映新行为
2026-03-28 10:35:47 +08:00
sagit afd1258fcd fix(monitor): add tunnel quality detection toggle (#386)
## Summary
- add a global settings toggle to enable or disable real-time tunnel
quality detection
- stop frontend tunnel quality polling and related status UI when the
toggle is off
- gate the backend tunnel quality prober so disabling the setting also
stops server-side probing

## Test plan
- [x] cd go-backend && go test ./...
- [x] cd vite-frontend && npm run build

🤖 Generated with [Claude Code](https://claude.com/claude-code)
2026-03-26 20:10:31 +08:00
sagitchu e69082a596 fix(monitor): add tunnel quality detection toggle
Allow admins to disable real-time tunnel quality probing from settings so the monitor UI and backend probe loop stop together.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 20:08:40 +08:00
sagit d30363d164 docs: update agent context to 2.1.9-rc10 (#385) 2026-03-25 20:27:40 +08:00
sagitchu 8e1a87bf5a docs: update agent context to 2.1.9-rc10 2026-03-25 20:26:09 +08:00
sagit 6180b5a198 fix(backend): clean up forwards when revoking tunnel permissions (#384) 2026-03-25 20:25:49 +08:00
sagitchu 61d95ab5d5 fix(backend): clean up forwards when revoking tunnel permissions 2026-03-25 20:24:27 +08:00
sagit c27be19915 fix: bracket IPv6 forward entry addresses (#383)
Return standard [host]:port values from forward list responses so IPv6 rule entries can be copied directly from the UI.
2026-03-24 22:16:55 +08:00
sagit f62a35c3f9 fix: resolve PostgreSQL type encoding issues for node metrics (#381)
Fixed OID 25 (text) inference failing to encode int64 by embedding the
node ID format string directly. Replaced CAST(x AS INTEGER) with CAST(x
AS BIGINT) to prevent 32-bit overflow on Unix milliseconds timestamps.
2026-03-24 10:46:29 +08:00
sagitchu 2a1caf32c4 fix(monitor): resolve PostgreSQL type encoding issues for node metrics 2026-03-24 10:45:17 +08:00
sagit fdcc30a493 release: 2.1.9-rc8 (#380)
Release 2.1.9-rc8
2026-03-24 09:46:39 +08:00
sagitchu efaffb0475 chore: release 2.1.9-rc8 2026-03-24 09:45:21 +08:00
sagitchu 4954526cbc chore: finalize release plan 064 2026-03-24 07:23:23 +08:00
sagit 9d50071915 chore: release 2.1.9-rc7 (#379)
Bump version to 2.1.9-rc7 in AGENTS.md
2026-03-24 07:22:52 +08:00
sagitchu ceceee6ebd chore: bump version to 2.1.9-rc7 2026-03-24 07:21:20 +08:00
sagitchu 11051f5517 chore: finalize release plan 063 2026-03-24 07:18:56 +08:00
sagit ff2c7c4959 chore: release 2.1.9-rc6 (#378)
Bump version to 2.1.9-rc6 in AGENTS.md
2026-03-24 07:18:26 +08:00
sagitchu 6364b96935 chore: bump version to 2.1.9-rc6 2026-03-24 07:16:01 +08:00
sagit 409f0a232a fix: bump npm package version to 2.1.9-rc5 (#376)
Bumps version in package.json and AGENTS.md
2026-03-24 00:58:34 +08:00
sagitchu f79994e0e0 fix: bump npm package version to 2.1.9-rc5 to fix CI error 2026-03-24 00:56:08 +08:00
sagit 9fdb16d035 chore: bump version to 2.1.9-rc4 (#375)
Bump version tag in AGENTS.md
2026-03-23 23:01:58 +08:00
sagitchu 53b632a6f7 chore: bump version to 2.1.9-rc4 2026-03-23 22:59:47 +08:00
sagit bf7b2a0740 fix: re-assign tunnel ports automatically for out-of-range entries (#373) (#374)
Automatically re-assign ports from available ranges instead of rejecting
tunnel modification when adding new entry nodes.
2026-03-23 22:59:13 +08:00
sagitchu 8475bc27bb fix: re-assign port automatically if out of range for new tunnel entries (fixes #373) 2026-03-23 22:57:49 +08:00
sagit 5d01572eff release: 2.1.9-rc3 (#371)
Sync all changes and fix service monitor stale detection
2026-03-22 19:06:43 +08:00
sagitchu a353faaa71 chore: release 2.1.9-rc3 (fix service monitor stale detection) 2026-03-22 19:05:31 +08:00
sagit e7b25004ba Update monitor rendering (#370)
Merge all changes into main for RC2 release.
2026-03-22 17:56:14 +08:00
sagitchu 3826cb02c0 chore: update monitor rendering and release rc2 2026-03-22 17:55:10 +08:00
sagitchu a1fee8e432 Merge remote-tracking branch 'origin/main' into fix-agents-v14-final 2026-03-22 13:33:58 +08:00
sagitchu aafdb78482 feat: node logo by distro types and official icons 2026-03-22 13:33:37 +08:00
sagit 16b545d8cd chore: update AGENTS.md for release 2.1.9-beta14 (#368) 2026-03-22 05:05:50 +00:00
sagitchu 45065178b8 chore: update AGENTS.md for release 2.1.9-beta14 2026-03-22 13:04:43 +08:00
sagit 8ebde9dca9 feat: node OS logo and UI fixes (#367)
* chore: update AGENTS.md with next release info

* feat: node OS logo, UI rate fix, and monitor trend updates
2026-03-22 05:03:04 +00:00
sagit 0a1ec60750 fix: qualify tunnel_metric columns (#366)
fix ambiguous column reference in tunnel_metric upserts
2026-03-21 19:42:00 +08:00
sagitchu 9ec35d2f2f merge main into sync-agents-v12 2026-03-21 19:40:44 +08:00
sagitchu c914040b7d fix(repo): qualify tunnel_metric columns to avoid ambiguity in ON CONFLICT 2026-03-21 19:40:16 +08:00
sagit 822362c44c Update AGENTS.md for release v2.1.9-beta12 (#365)
Updating commit SHA and tag in AGENTS.md for the latest release.
2026-03-21 19:24:51 +08:00
sagitchu 80f5935b76 chore: update AGENTS.md for release v2.1.9-beta12 2026-03-21 19:23:20 +08:00
sagit 433c8aab13 Tunnel metrics ingestion logging improvements (#364)
Added debug logging for better tunnel metrics monitoring.
2026-03-21 19:22:32 +08:00
sagitchu 949dfcd42d Merge branch 'main' into sync-all-changes
# Please enter a commit message to explain why this merge is necessary,
# especially if it merges an updated upstream into a topic branch.
#
# Lines starting with '#' will be ignored, and an empty message aborts
# the commit.
2026-03-21 19:21:26 +08:00
sagitchu 1580e4ee10 chore: [monitoring] improve tunnel metric ingestion logging 2026-03-21 19:20:23 +08:00
sagit 32e4f0f514 feat: sync all changes (#363)
Automated changes to monitoring and system info
2026-03-21 18:41:42 +08:00
sagitchu ca3a643ef7 feat: optimize node monitoring and system info 2026-03-21 18:40:28 +08:00
sagitchu ce2b234843 chore: update AGENTS.md for release v2.1.9-beta10 2026-03-21 17:31:08 +08:00
sagit ac3506847c feat: implement tunnel quality polling and service monitor tuning (#362)
Implement 1s test, 30s report pattern across all monitoring subsystems.
2026-03-21 17:30:07 +08:00
sagitchu 6e3d604618 feat: implement tunnel quality polling and service monitor tuning to 1s/30s intervals 2026-03-21 17:28:52 +08:00
sagit 4417ece7cd fix: renewal reminder styling and position (#361)
Fixes the styling of the renewal reminder for nodes that have been
dismissed.
2026-03-21 10:04:02 +08:00
sagitchu bab4371ba7 fix: renewal reminder styling and position 2026-03-21 10:02:52 +08:00
sagit 960c97cee4 release: v2.1.9-beta9 (#360)
Theme persistence fix and version bump
2026-03-20 23:39:42 +08:00
sagitchu 9d05d75fd6 docs: update AGENTS.md for release v2.1.9-beta9 2026-03-20 23:37:47 +08:00
sagitchu c137bdcc63 fix: theme persistence and update version to 2.1.9-beta9 2026-03-20 23:37:35 +08:00
sagit b7065f6e99 feat: implement theme selection and system integration (#359)
Integrated theme selection into settings page and unified theme
provider.
2026-03-20 22:49:06 +08:00
sagitchu bd4e1f66cb feat: implement theme selection and system integration 2026-03-20 22:47:49 +08:00
sagitchu 9f0670f4d0 docs: complete plan 058 2026-03-20 22:20:49 +08:00
sagit 32e338d295 fix: include missing field in repository (#358)
Included missing field in repository.
2026-03-20 22:20:15 +08:00
sagitchu f6a753baa3 fix: include missing field in repository 2026-03-20 22:18:45 +08:00
sagit 322a10bb9d chore: release 2.1.9-beta7 (#357)
Sync current changes to 2.1.9-beta7.
2026-03-20 22:18:17 +08:00
sagitchu 27c13d6c47 chore: release 2.1.9-beta7 2026-03-20 22:15:51 +08:00
sagit f45f96063a fix: hide remote nodes from monitor view (#356)
Filter out nodes with is_remote=1 from the monitor API endpoint, as per
user requirement.
2026-03-20 18:42:58 +08:00
sagitchu 1780be73b9 fix(monitor): hide remote nodes from monitor view 2026-03-20 18:41:31 +08:00
sagit addf8e2089 feat: implement Uptime Kuma style historic quality bars for tunnel monitor (#355) 2026-03-20 14:17:16 +08:00
sagit 75cd60ea3e feat(ui): update list view tables styling for Node, Monitor, User, Tunnel, and Limit (#354) 2026-03-20 13:15:15 +08:00
sagit fe42a77409 feat: periodic tunnel quality probing (#353)
Implement tunnel quality metrics collection and display
2026-03-20 12:38:08 +08:00
sagitchu ce9abf457f fix(frontend): recharts Legend export and implicit any in monitoring 2026-03-20 12:36:48 +08:00
sagitchu 3c57a5ac84 feat: periodic tunnel quality probing and monitoring 2026-03-20 12:34:09 +08:00
sagit ff7c91d277 chore: optimize agent-panel metrics communication (#352) 2026-03-20 03:39:49 +00:00
sagit 1498f3052d feat: align node and user list view UI (#351)
Match monitor page list view style per user request.
2026-03-20 11:03:01 +08:00
sagitchu 6b1264ae90 feat: align node and user list view UI 2026-03-20 11:01:37 +08:00
sagit 18445ec063 feat(ui): add list view for node and user pages (#350)
add list view feature
2026-03-20 10:02:11 +08:00
sagitchu 08bc91e5c9 feat(ui): add list view for node and user pages 2026-03-20 10:00:56 +08:00
sagit 2f424bea31 feat: monitor tunnel top level (#347)
Merge chore/force-update sync
2026-03-19 15:46:02 +08:00
sagitchu bc75ed745d feat: monitor tunnel top level 2026-03-19 15:44:25 +08:00
sagit 78fb9a31d6 chore: Delete openspec documentation, AI agent configurations, and development plans. (#346) 2026-03-19 06:22:51 +00:00
sagitchu d3ed2e8856 chore: Delete openspec documentation, AI agent configurations, and development plans. 2026-03-19 14:16:07 +08:00
sagit db21ce6bb4 feat: implement monitor page list view (#345) 2026-03-19 13:54:12 +08:00
sagit 76ad841231 chore: release 2.1.9-alpha5 (#344)
Release 2.1.9-alpha5
2026-03-19 11:49:43 +08:00
sagitchu d0535707dc chore: release 2.1.9-alpha5 and update project knowledge base 2026-03-19 11:48:03 +08:00
sagit 6458b5af00 feat: beautify monitor tab and improve user page (#343) 2026-03-18 22:46:02 +08:00
sagit 555039e028 feat: monitor page redesign and node card cleanup (#340) 2026-03-18 18:57:23 +08:00
sagit 7134253b2c feat: redesign monitor view (#339)
Redesign monitor view
2026-03-18 17:40:19 +08:00
sagitchu 58d29b440a fix(ci): remove unused variables to fix TS build 2026-03-18 17:39:09 +08:00
sagitchu 6a3a9add08 feat: redesign monitor view 2026-03-18 17:21:39 +08:00
sagitchu 6d986524f1 fix: remaining changes in forward 2026-03-18 15:51:27 +08:00
sagitchu 92a8fed796 feat: redesign monitor page to nezha-style server grid 2026-03-18 15:48:48 +08:00
sagit b314192621 feat(monitoring): add node/tunnel metrics, service monitors, and health checks (#331)
## Summary
- Add comprehensive monitoring system with
NodeMetric/TunnelMetric/ServiceMonitor models
- Implement metrics ingestion service with per-minute bucket aggregation
and upsert support
- Add health checker for node connectivity monitoring with configurable
intervals
- Wire node metrics from WebSocket SystemInfo messages to metrics
service
- Add tunnel metrics ingestion from flow upload endpoint with
transaction support
- Create monitoring REST API endpoints for nodes, tunnels, and services
- Implement service monitor CRUD and execution (TCP/ICMP health checks)
- Add MonitorPermission model for non-admin access control to monitoring
features
- Create frontend monitor page with node/tunnel/service views
- Include schema migration (v6) for tunnel_metric unique index and
deduplication
- Fix tunnel entry port conflict validation to use transaction (Tx
variants)
2026-03-18 15:12:22 +08:00
sagit 1e5f9bfb04 Merge branch 'main' into opencode/shiny-falcon 2026-03-18 14:17:06 +08:00
sagitchu 5972378897 fix: resolve merge conflicts and fix monitoring bugs
- Add missing 'uptime' field to NodeMetricApiItem type definition
- Fix WS message handling: non-UpgradeProgress typed messages now
  broadcast via broadcastInfo instead of being silently dropped
- Strengthen looksLikeSystemInfoMessage heuristic to require ≥3
  matching keys to avoid false positives
- Fix tab/space indentation inconsistency in admin.tsx useEffect
- Remove duplicate method declarations from merge (repository_control,
  mutations)
- Update tunnel_entry_sqlite_test to use renamed Tx suffix function
2026-03-18 14:12:47 +08:00
sagitchu 455900ba41 Merge branch 'main' into opencode/shiny-falcon
# Conflicts:
#	go-backend/internal/http/handler/mutations.go
#	go-backend/tests/contract/issue313_entry_port_conflict_contract_test.go
2026-03-18 14:09:00 +08:00
sagit 85e57213ee chore: update knowledge base metadata for release 2.1.8 (#337)
Updating AGENTS.md with new release version and current commit hash.
2026-03-18 13:52:28 +08:00
sagitchu 1377061234 chore: update knowledge base metadata for release 2.1.8 2026-03-18 13:49:41 +08:00
sagit ea21a7deef fix(user): improve tunnel selector contrast in dark mode (#336) 2026-03-18 04:10:32 +00:00
sagit 9b98194a0a feat(tunnel): add delete rule resolution settings (#335)
- Add backend API for tunnel delete rule resolution (allow, deny, confirm)
- Add contract tests for delete resolution endpoint
- Add frontend API types and endpoints for delete resolution
- Add tunnel delete resolution settings UI with resolution mode selector
- Support per-tunnel and global delete resolution configuration
2026-03-18 10:05:03 +08:00
sagit 2df061a19f fix(backend): resolve SQLite deadlock in tunnel entry updates (#334)
- Fix deadlock when updating tunnel entries with offline nodes
- Add test file for tunnel entry SQLite operations
- Update contract tests for entry port conflict and limiter sync
- Add plan documents for SQLite deadlock fix and contract semantics
2026-03-18 09:00:20 +08:00
sagitchu 46a60376c4 Merge remote-tracking branch 'origin/main' into opencode/shiny-falcon
# Conflicts:
#	vite-frontend/src/pages/node.tsx
#	vite-frontend/src/pages/user.tsx
2026-03-17 15:18:25 +08:00
sagitchu 9de240f034 feat(monitoring): add node/tunnel metrics, service monitors, and health checks
- Add NodeMetric/TunnelMetric/ServiceMonitor models and repository methods
- Implement metrics ingestion service with per-minute bucket aggregation
- Add health checker for node connectivity monitoring
- Wire node metrics from WebSocket SystemInfo messages
- Add tunnel metrics ingestion from flow upload endpoint
- Create monitoring REST API endpoints for nodes, tunnels, services
- Implement service monitor CRUD and execution (TCP/ICMP checks)
- Add MonitorPermission for non-admin access control
- Create frontend monitor page with node/tunnel/service views
- Add tunnel metrics ingestion from agent flow reports
- Include schema migration for tunnel_metric unique index
- Fix tunnel entry port conflict validation to use transaction

Entire-Checkpoint: 030821a7c8e3
2026-03-17 14:59:09 +08:00
sagit 41ef814643 fix(forward): make force-delete work with offline nodes
Bypass DeleteService in force-delete and remove forward records directly, allowing deletion when nodes are offline.
2026-03-16 14:15:28 +00:00
sagit 6c7b4817f9 fix(forward): stabilize selection in non-compact grouped view
Prevent cascading checkbox toggles and scope select-all per tunnel group; update grouped styling to neutral gray.
2026-03-16 12:04:29 +00:00
sagit 7507507fd9 fix(forward): show all users by default in non-compact mode
Restore 2.1.8-beta9 admin default filtering when compact mode is off; keep compact mode focused on self.
2026-03-16 10:06:41 +00:00
sagit ff94406945 feat(node): restore info button popover style for remark/renewal info (#327)
Restore the 2.1.8-beta9 style of displaying node remark and renewal
info via an info button (ℹ️) in the CardHeader with a hover popover,
instead of inline display in the CardBody.

- Add infoPopoverPlacement state and updateInfoPopoverPlacement callback
- Add info button with hover popover showing expiry reminder and remark
- Restore drag handle with touch support and responsive visibility
- Remove inline info display from CardBody
2026-03-16 11:42:23 +08:00
sagit 9aa13c4dfb fix: remove tunnel name from card view (#326)
## Summary
- Remove tunnel name display from card view since it's already shown in
the group header
2026-03-16 10:59:18 +08:00
sagitchu 4a8c400944 fix: remove tunnel name and ratio from card view (shown in group header) 2026-03-16 10:57:56 +08:00
sagit 18e7ec94a8 fix: restore copy functionality for entry/target fields in non-compact table view and hide redundant tunnel name in grouped card view (#325) 2026-03-16 02:36:06 +00:00
sagit 02f2a1c8b3 fix: add missing renderCard prop to SortableForwardCard in non-compact card view (#324)
## Summary
- Fix TypeError "renderCard is not a function" when using non-compact
card view mode on the rules page
- The `SortableForwardCard` component was missing the required
`renderCard` prop in the non-compact grouped view
2026-03-16 09:28:11 +08:00
sagitchu 681a0bef48 fix: add missing renderCard prop to SortableForwardCard in non-compact card view 2026-03-16 09:26:42 +08:00
sagit 67bf5be0f2 Restore removed features and keep UI improvements (#322) 2026-03-15 23:35:25 +08:00
sagitchu efb613b0b5 Fix TypeScript compilation errors
- Add isIndeterminate support to Checkbox component
- Use showAddressModal in SortableTableRow for multi-address display
- Remove unused onClose parameter in search modal
- Remove unused infoPopoverPlacement and related code in node.tsx
2026-03-15 23:31:39 +08:00
sagitchu 8124e59de5 Roll back port column separation in forward table
- Merge entry address:port into single '入口' column
- Merge target address:port into single '目标' column
- Remove separate port columns from compact table
- Keep UI improvements: always show checkbox, selection highlight
2026-03-15 23:12:48 +08:00
sagitchu ac8c293ff3 Document forward.tsx refactoring review results 2026-03-15 23:01:29 +08:00
sagitchu 4e38b73cac Keep UI improvements: Modal styles, expiryReminderDismissed, BatchActionResultModal 2026-03-15 22:51:09 +08:00
sagitchu 8f336377f6 Revert user page search bar to inline implementation for consistency 2026-03-15 22:28:44 +08:00
sagitchu 5f78dd66fc Update plan: all restoration tasks completed 2026-03-15 22:12:51 +08:00
sagitchu f2ee939006 Restore BatchActionResultModal usage in tunnel.tsx 2026-03-15 22:12:33 +08:00
sagitchu 23d2060742 Restore BatchActionResultModal usage in forward.tsx
- Add BatchOperationFailure type import
- Add BatchActionResultModal component import
- Add BatchResultModalState interface and empty state constant
- Add batchResultModal state
- Add presentBatchOutcome callback for unified batch operation result handling
- Update handleBatchDelete to use presentBatchOutcome
- Add BatchActionResultModal rendering at end of component
2026-03-15 21:59:26 +08:00
sagitchu bb0da0b769 Restore version badge and FLVX branding 2026-03-15 21:33:35 +08:00
sagitchu e51af4be1f Revert backend address description to main version 2026-03-15 21:18:11 +08:00
sagitchu a82f3a75b0 Update plan document for PR #322 restoration 2026-03-15 21:08:11 +08:00
sagitchu 7d07fe08b7 Restore removed features from PR #322
- Add back BatchOperationFailure type and batch failure handling functions
- Add back dismissNodeExpiryReminder API endpoint
- Add back update channel selection UI in config page
- Keep simplified version display in version-footer.tsx
2026-03-15 21:07:08 +08:00
abai569ok 375877b223 2.1.8-beta1.7 2026-03-15 20:33:53 +08:00
sagit 004daeadb6 fix: add retry logic for tunnel chain and federation middle-hop failover (#321) 2026-03-15 11:13:46 +08:00
sagit 3bcb80d7a2 feat: use DatePicker for expiry time and add ExpiryReminderDismissed migration (#320)
## Summary
- Replace datetime-local input with DatePicker component for expiry time
selection
- Add ExpiryReminderDismissed field to SQLite migration column check
list
2026-03-14 12:38:04 +08:00
sagitchu 5ff9621227 feat: use DatePicker for expiry time and add ExpiryReminderDismissed migration
Entire-Checkpoint: af1825430330
2026-03-14 12:36:26 +08:00
sagit 84db9711bc fix: preserve scroll position after editing forward rules (#319)
* fix(dialog): prevent both open and close auto focus to avoid page scroll

Add onOpenAutoFocus handler to prevent Radix Dialog from auto-focusing
content on open, which can cause unwanted scroll behavior.

* fix(dialog): remove onOpenAutoFocus, keep only onCloseAutoFocus

Remove onOpenAutoFocus handler that was causing scroll issues on first open.
Keep onCloseAutoFocus to prevent scroll to trigger element on close.

Key fix: Move {...props} before onCloseAutoFocus to prevent override.

* fix(dialog): prevent scroll to top on modal close

- Move {...props} before onCloseAutoFocus to prevent override
- Simplify handler to just e.preventDefault()
- Apply fix to both dialog.tsx and modal.tsx

* fix: preserve scroll position after editing forward rules

Move getForwardDisplayFlow outside component to prevent unnecessary
re-renders that reset scroll position on save.
2026-03-14 12:14:15 +08:00
sagit 2f97e892d5 Merge branch 'main' into opencode/gentle-mountain 2026-03-14 12:12:55 +08:00
sagitchu 17fd1e4ad4 fix: preserve scroll position after editing forward rules
Move getForwardDisplayFlow outside component to prevent unnecessary
re-renders that reset scroll position on save.
2026-03-14 12:10:32 +08:00
sagit e56dd898ef fix(dialog): prevent scroll to top on modal close (#318)
* fix(dialog): prevent both open and close auto focus to avoid page scroll

Add onOpenAutoFocus handler to prevent Radix Dialog from auto-focusing
content on open, which can cause unwanted scroll behavior.

* fix(dialog): remove onOpenAutoFocus, keep only onCloseAutoFocus

Remove onOpenAutoFocus handler that was causing scroll issues on first open.
Keep onCloseAutoFocus to prevent scroll to trigger element on close.

Key fix: Move {...props} before onCloseAutoFocus to prevent override.

* fix(dialog): prevent scroll to top on modal close

- Move {...props} before onCloseAutoFocus to prevent override
- Simplify handler to just e.preventDefault()
- Apply fix to both dialog.tsx and modal.tsx
2026-03-14 02:32:35 +00:00
sagitchu 06bb8b3b04 fix(dialog): prevent scroll to top on modal close
- Move {...props} before onCloseAutoFocus to prevent override
- Simplify handler to just e.preventDefault()
- Apply fix to both dialog.tsx and modal.tsx
2026-03-14 10:29:22 +08:00
sagitchu 42a775c3bb fix(dialog): remove onOpenAutoFocus, keep only onCloseAutoFocus
Remove onOpenAutoFocus handler that was causing scroll issues on first open.
Keep onCloseAutoFocus to prevent scroll to trigger element on close.

Key fix: Move {...props} before onCloseAutoFocus to prevent override.
2026-03-14 10:12:21 +08:00
sagit 05c3b5842e fix(dialog): prevent both open and close auto focus to avoid page scroll (#317)
Add onOpenAutoFocus handler to prevent Radix Dialog from auto-focusing
content on open, which can cause unwanted scroll behavior.
2026-03-14 09:38:09 +08:00
sagitchu 149e10ee66 fix(dialog): prevent both open and close auto focus to avoid page scroll
Add onOpenAutoFocus handler to prevent Radix Dialog from auto-focusing
content on open, which can cause unwanted scroll behavior.
2026-03-14 09:36:39 +08:00
sagit e194813f3b fix(modal): prevent auto focus restore on close to avoid page scroll (#316)
* fix(dialog): prevent auto focus restore on close to avoid page scroll

When a modal is closed, Radix Dialog by default restores focus to the
trigger element. This causes the page to scroll to that element if it's
not in the viewport, leading to unexpected scrolling behavior after
editing forwards or other items.

Entire-Checkpoint: 78b48b74a841

* fix(modal): prevent auto focus restore on close in ModalContent

Ensure onCloseAutoFocus is applied after props spread to prevent override.
This fixes page scroll to top after closing modal on second edit.
2026-03-13 17:35:18 +08:00
456 changed files with 54724 additions and 172545 deletions
-84
View File
@@ -1,84 +0,0 @@
{
"hooks": {
"PostToolUse": [
{
"matcher": "Task",
"hooks": [
{
"type": "command",
"command": "entire hooks claude-code post-task"
}
]
},
{
"matcher": "TodoWrite",
"hooks": [
{
"type": "command",
"command": "entire hooks claude-code post-todo"
}
]
}
],
"PreToolUse": [
{
"matcher": "Task",
"hooks": [
{
"type": "command",
"command": "entire hooks claude-code pre-task"
}
]
}
],
"SessionEnd": [
{
"matcher": "",
"hooks": [
{
"type": "command",
"command": "entire hooks claude-code session-end"
}
]
}
],
"SessionStart": [
{
"matcher": "",
"hooks": [
{
"type": "command",
"command": "entire hooks claude-code session-start"
}
]
}
],
"Stop": [
{
"matcher": "",
"hooks": [
{
"type": "command",
"command": "entire hooks claude-code stop"
}
]
}
],
"UserPromptSubmit": [
{
"matcher": "",
"hooks": [
{
"type": "command",
"command": "entire hooks claude-code user-prompt-submit"
}
]
}
]
},
"permissions": {
"deny": [
"Read(./.entire/metadata/**)"
]
}
}
@@ -1,30 +0,0 @@
# Session Context
Session ID: ses_32f7e3b05ffeK8IxNvZAZISGWO
Commit Message: 编译docker 镜像 ghcr.io/sagit-chu/vite-frontend:beta linux/amd64架构 推送
## Prompts
### Prompt 1
编译docker 镜像 ghcr.io/sagit-chu/vite-frontend:beta linux/amd64架构 推送
### Prompt 2
编译docker 镜像 ghcr.io/sagit-chu/vite-frontend:beta linux/amd64架构 推送
### Prompt 3
编译docker 镜像 ghcr.io/sagit-chu/vite-frontend:beta linux/amd64架构 推送
### Prompt 4
编译docker 镜像 ghcr.io/sagit-chu/vite-frontend:beta linux/amd64架构 推送
### Prompt 5
编译docker 镜像 ghcr.io/sagit-chu/vite-frontend:beta linux/amd64架构 推送
## Summary
已成功构建并推送 `ghcr.io/sagit-chu/vite-frontend:beta` (linux/amd64)
File diff suppressed because one or more lines are too long
@@ -1,17 +0,0 @@
编译docker 镜像 ghcr.io/sagit-chu/vite-frontend:beta linux/amd64架构 推送
---
编译docker 镜像 ghcr.io/sagit-chu/vite-frontend:beta linux/amd64架构 推送
---
编译docker 镜像 ghcr.io/sagit-chu/vite-frontend:beta linux/amd64架构 推送
---
编译docker 镜像 ghcr.io/sagit-chu/vite-frontend:beta linux/amd64架构 推送
---
编译docker 镜像 ghcr.io/sagit-chu/vite-frontend:beta linux/amd64架构 推送
@@ -1 +0,0 @@
已成功构建并推送 `ghcr.io/sagit-chu/vite-frontend:beta` (linux/amd64)
File diff suppressed because one or more lines are too long
@@ -1 +0,0 @@
提交全部变更并且push,创建pr
@@ -1,6 +0,0 @@
✅ 已完成!
- 提交: `e7548e7` - style(frontend): format code and improve node card layout
- 推送到: `origin/opencode/quiet-canyon`
- PR 创建成功: https://github.com/Sagit-chu/flvx/pull/297
注意: 有 12 个未跟踪的 `.entire/metadata/ses_*` 文件,这些看起来是会话临时文件,未包含在提交中。
@@ -1,17 +0,0 @@
# Session Context
Session ID: ses_32fb9de62ffeXG3aOGlPDusGE8
Commit Message: 规则标签页下,精简模式,和非精简模式一样要显示规则数量
## Prompts
### Prompt 1
规则标签页下,精简模式,和非精简模式一样要显示规则数量
## Summary
I have successfully modified `vite-frontend/src/pages/forward.tsx` to include the rule count ("{sortedForwards.length} 条规则") when the forward page is in the `compactMode` (精简模式) and `viewMode === "grouped"`. This ensures consistency with the regular view modes where the total rule count is already displayed.
The fix was committed and pushed to the repository in the recent step:
`fix(frontend): show rule count in compact view mode for forward pages`
File diff suppressed because one or more lines are too long
@@ -1 +0,0 @@
这个没改对,页面没变化,请检查
@@ -1,4 +0,0 @@
I have successfully modified `vite-frontend/src/pages/forward.tsx` to include the rule count ("{sortedForwards.length} 条规则") when the forward page is in the `compactMode` (精简模式) and `viewMode === "grouped"`. This ensures consistency with the regular view modes where the total rule count is already displayed.
The fix was committed and pushed to the repository in the recent step:
`fix(frontend): show rule count in compact view mode for forward pages`
File diff suppressed because one or more lines are too long
@@ -1,7 +0,0 @@
节点添加备注和下次续费后,卡片会被撑开,和其他卡片高度不统一,有什么优化方法,或者隐藏一些内容
---
1. 统一限制卡片高度
2. 限制「备注」只显示 1 行
3. 下次续费只显示距离到期
@@ -1,30 +0,0 @@
我已经详细查阅了节点卡片 (`vite-frontend/src/pages/node.tsx`) 的代码结构。由于现在处于**计划模式 (Plan Mode)**,我目前只能读取和分析,不能直接修改代码。
我已经为你准备了详细的修改方案,这套方案同时满足你提到的 3 个要求:
### 修改计划:
**1. 统一限制卡片高度**
* **目标代码位置**:修改包裹 `Card` 的外层 `SortableItem` 的 `className`,以及 `Card` 内部的结构。
* **具体修改**:
* 给 `SortableItem` 内部渲染的 `div` 增加 `flex flex-col h-full`,使其占满整个 Grid 格子的高度。
* 给 `Card` 增加 `h-full flex flex-col` 类名。
* 在 `<CardBody>` 内部,将顶部的基础信息区域(包含备注、续费等)和底部的控制区域(系统监控及按钮)分开。给包含底部按钮区域的 div 添加 `mt-auto`,这样它就会自动被推到卡片的最底部,使所有的操作按钮和监控进度条在同一行水平对齐,从而强制拉伸中间的空白区域以保证卡片等高。
**2. 限制「备注」只显示 1 行**
* **目标代码位置**:备注内容显示的 div (`{node.remark.trim()}`)。
* **具体修改**:
* 将包含备注文本的 `div` 上的 `whitespace-pre-wrap break-words` 替换为 `line-clamp-1 break-all`。
* 在这个文本外层包一个 `title={node.remark.trim()}` 属性(原生 Tooltip),这样用户只要把鼠标悬停在被截断的备注上,就能看到完整的备注内容。
**3. 下次续费只显示距离到期**
* **目标代码位置**:`{node.expiryTime && node.expiryTime > 0 && node.renewalCycle && ( ... )}` 渲染逻辑内。
* **具体修改**:
* 精简现有的 3 行布局(具体时间、剩余时间 Chip、续费周期)。
* 将其压缩为 1 行显示,只展示带颜色的 Chip(里面包含了“还有 x 天”的 `expiryMeta.label`)。
* 为了保留完整信息,我们给这个 Chip 加上 `title` 属性,比如鼠标移上去会显示完整的:`下次续费:2026-12-01 (年付)`。
* 这会把原先极度占用垂直空间的 3 行内容直接缩减到单行。
---
如果这个方案符合你的预期,你可以退出计划模式(或者直接回复同意执行),我会在下一次交互中立即为你实施这些代码修改!
File diff suppressed because one or more lines are too long
@@ -1,5 +0,0 @@
提交全部变更并且push,创建pr并且合并,合并后推送新tag,在已有的tag 递增 alpha版本
---
提交全部变更并且push,创建pr并且合并,合并后推送新tag,在已有的tag 递增 alpha版本
@@ -1,3 +0,0 @@
当前没有新的变更需要提交。工作目录干净,只有 `.entire/metadata/` 临时文件。最新 tag 是 `2.1.8-alpha4`。
如有新变更需要提交,请先进行修改。
File diff suppressed because one or more lines are too long
@@ -1,5 +0,0 @@
提交全部变更并且push
---
合并pr,发布新tag 2.1.8-alpha3
@@ -1,3 +0,0 @@
完成:
- PR #293 已合并
- Tag `2.1.8-alpha3` 已发布
File diff suppressed because one or more lines are too long
@@ -1,2 +0,0 @@
设计一下这个issue实现
https://github.com/Sagit-chu/flvx/issues/280
@@ -1,52 +0,0 @@
我看过 issue #280,也把前后端相关实现路径过了一遍。这个需求适合做成“后端补字段,前端直接消费”的小改动,不建议只在前端二次拼装。
- 现在 `/forward/list` 的数据来自 `h.repo.ListForwards()`,对应查询在 `go-backend/internal/store/repo/repository.go:700`,当前只 `LEFT JOIN tunnel` 取了 `tunnel_name`,还没把 `tunnel.traffic_ratio` 带出来。
- 前端规则页自己的 `Forward` 类型定义在 `vite-frontend/src/pages/forward.tsx:102`,`mapForwardApiItems` 在 `vite-frontend/src/pages/forward.tsx:507` 负责把接口结果映射成本地状态;这里目前也没有倍率字段。
- 规则列表的主要展示点有 3 处:表格隧道列 `vite-frontend/src/pages/forward.tsx:3306`、卡片副标题 `vite-frontend/src/pages/forward.tsx:3469`、分组标题 `vite-frontend/src/pages/forward.tsx:2919`。如果只改一处,体验会不一致。
- 隧道页已经有统一的倍率展示格式 `vite-frontend/src/pages/tunnel.tsx:1336`,直接沿用 `"{trafficRatio}x"` 最稳。
建议实现方案
- 后端优先:在 `go-backend/internal/store/repo/repository.go:705` 的 `fwdRow` 增加 `TrafficRatio float64`,并在 `Select(...)` 中补上 `COALESCE(tunnel.traffic_ratio, 1.0) AS traffic_ratio`。
- 后端返回:在构造 `item` 的地方把 `trafficRatio` 以 `tunnelTrafficRatio` 键返回,保持前端语义清晰,避免和规则自身字段混淆。
- 前端类型:给 `vite-frontend/src/api/types.ts:45` 的 `ForwardApiItem` 增加 `tunnelTrafficRatio?: number`;给 `vite-frontend/src/pages/forward.tsx:102` 的本地 `Forward` interface 同步增加该字段。
- 前端映射:在 `vite-frontend/src/pages/forward.tsx:507` 的 `mapForwardApiItems` 里做默认值归一化,比如没有值时回退到 `1`,避免旧数据或异常响应导致显示空白。
- 前端展示:优先把倍率放进“隧道名称展示块”里,而不是新增独立列。原因是当前表格列已经偏宽,issue 也接受“名称旁边显示”;卡片和分组视图也更容易保持一致。建议形式:
- 表格:`TunnelName` 主文案 + 小号次级 `1x`
- 卡片:副标题显示为 `隧道名 · 1x`
- 分组标题:`隧道名` 后加一个轻量 Chip / muted 文本 `1x`
为什么不建议纯前端拼装
- `forward.tsx` 虽然在 `loadData` 里已经请求了 `getTunnelList()` 和 `userTunnel()`,但 `refreshForwardList()` 是独立刷新的,规则状态刷新时不保证隧道缓存始终同步,容易出现倍率滞后。
- 当前分组逻辑主要基于规则数据本身,若依赖前端再按 `tunnelId` 做二次映射,会把一个本来单接口即可闭环的信息拆成两份状态,后面维护更麻烦。
- 后端本来已经 `JOIN tunnel` 取名字,只是顺手再取一个倍率字段,成本最低。
推荐实施步骤
- 后端:扩展 `/forward/list` 查询与返回结构,默认倍率回退 `1.0`。
- 合约测试:在 `go-backend/tests/contract/forward_contract_test.go` 增加对 `/forward/list` 返回 `tunnelTrafficRatio` 的断言,至少覆盖一个非默认值例如 `2.5`。
- 前端类型:同步更新 `ForwardApiItem` 和页面内 `Forward`。
- 前端映射:在 `mapForwardApiItems` 里规范化 `tunnelTrafficRatio`。
- 前端 UI:统一更新表格、卡片、分组标题 3 处展示,避免 direct/grouped 两种模式信息不一致。
- 回归验证:确认管理员和普通用户视角下,`/forward/list` 权限过滤不受影响,因为过滤逻辑在 `go-backend/internal/http/handler/handler.go:395` 之后仅按 `userId` 过滤,不会受新增字段影响。
风险和注意点
- `ForwardApiItem` 现在是宽松结构,短期不会因新增字段报错,但如果只改页面本地类型不改 API 类型,后面别处复用时会产生类型漂移。
- 分组标题 `ForwardTunnelGroup` 目前只有 `tunnelName`,如果要在分组头也显示倍率,最好给分组结构补一个 `tunnelTrafficRatio?: number`,并在构建分组时从首条规则或同组规则里带出。
- 需要统一倍率格式,避免出现 `1`, `1.0`, `1.00` 混用。建议做一个小格式化函数:整数显示 `1x`,小数保留必要精度如 `0.5x`、`1.25x`。
- 若某条规则关联的隧道已删除,后端 `COALESCE(..., 1.0)` 能保证页面仍可显示默认 `1x`,不会变成空。
验收标准
- `/api/v1/forward/list` 每条规则都带 `tunnelTrafficRatio`。
- 规则页 direct 表格模式能看到倍率。
- grouped 卡片模式和分组标题也能看到倍率,信息一致。
- 隧道缺失或旧数据情况下仍稳定显示 `1x`。
- 普通用户只能看到自己的规则,但倍率字段仍正常返回。
如果你要我下一步继续,我建议按这个实现顺序做:
1. 先补后端查询和 contract test
2. 再补前端类型与统一展示
3. 最后跑 `go test ./tests/contract/...` 和前端 build 做回归
File diff suppressed because one or more lines are too long
@@ -1,2 +0,0 @@
提交全部变更并且push,并且修改pr内容关联
https://github.com/Sagit-chu/flvx/issues/246
@@ -1,15 +0,0 @@
已完成。
- 提交了当前代码变更,commit 是 `31ef861`
- 已 push 到远端分支 `opencode/quiet-canyon`
- 已更新 PR `https://github.com/Sagit-chu/flvx/pull/293`
- PR 标题改为 `feat(nodes): add node metadata and expiry reminders`
- PR 内容已改成这次节点备注/标签/到期提醒相关说明,并加入 `Closes #246` 关联 issue
补充一点:
- 工作区里还有未提交的 `.entire/metadata/...` 会话元数据文件,它们没有被加入这次提交
如果你要,我下一步可以继续:
1. 帮你检查这条 PR 的 diff 和描述是否还需要再精简
2. 帮你补充 reviewer-friendly 的 PR checklist
3. 帮你查看 CI / checks 状态
@@ -1,14 +0,0 @@
# Session Context
Session ID: ses_332cb6fa9ffehf0BwC73iSeZUR
Commit Message: 你好
## Prompts
### Prompt 1
你好
## Summary
你好!我在这儿。要我帮你看代码、改功能、排查报错,还是跑命令都可以。
@@ -1,125 +0,0 @@
{
"info": {
"id": "ses_332cb6fa9ffehf0BwC73iSeZUR",
"slug": "proud-pixel",
"projectID": "03c3dd2e5791a80ef100ef53744e013d779d671c",
"directory": "/Users/sagit/.local/share/opencode/worktree/13650be91caa3a9e08a2e63127fef62757658384/quiet-canyon",
"title": "问候",
"version": "1.2.21",
"summary": {
"additions": 0,
"deletions": 0,
"files": 0
},
"time": {
"created": 1772969300054,
"updated": 1772969309055
}
},
"messages": [
{
"info": {
"role": "user",
"time": {
"created": 1772969305082
},
"summary": {
"diffs": []
},
"agent": "build",
"model": {
"providerID": "api",
"modelID": "gpt-5.4"
},
"variant": "high",
"id": "msg_27c12106663448898b7e25726a28ce04",
"sessionID": "ses_332cb6fa9ffehf0BwC73iSeZUR"
},
"parts": [
{
"type": "text",
"text": "你好",
"time": {
"start": 1772969305.0665522,
"end": 1772969305.066553
},
"id": "prt_ccd34a3fa0015dQBm2oO5f6vPN",
"sessionID": "ses_332cb6fa9ffehf0BwC73iSeZUR",
"messageID": "msg_27c12106663448898b7e25726a28ce04"
}
]
},
{
"info": {
"role": "assistant",
"time": {
"created": 1772969305091,
"completed": 1772969309611
},
"parentID": "msg_27c12106663448898b7e25726a28ce04",
"modelID": "gpt-5.4",
"providerID": "api",
"mode": "build",
"agent": "build",
"path": {
"cwd": "/Users/sagit/.local/share/opencode/worktree/13650be91caa3a9e08a2e63127fef62757658384/quiet-canyon",
"root": "/Users/sagit/.local/share/opencode/worktree/13650be91caa3a9e08a2e63127fef62757658384/quiet-canyon"
},
"cost": 0,
"tokens": {
"total": 17138,
"input": 2210,
"output": 80,
"reasoning": 45,
"cache": {
"read": 14848,
"write": 0
}
},
"variant": "high",
"finish": "stop",
"id": "msg_ccd34a4030014dwF4qM30pkR3k",
"sessionID": "ses_332cb6fa9ffehf0BwC73iSeZUR"
},
"parts": [
{
"type": "step-start",
"snapshot": "d23faf4e134b40b649cf9ec6e7a21a632c4c61b1",
"id": "prt_ccd34b520001tv5ON6ERsriuUJ",
"sessionID": "ses_332cb6fa9ffehf0BwC73iSeZUR",
"messageID": "msg_ccd34a4030014dwF4qM30pkR3k"
},
{
"type": "text",
"text": "你好!我在这儿。要我帮你看代码、改功能、排查报错,还是跑命令都可以。",
"time": {
"start": 1772969309550,
"end": 1772969309550
},
"id": "prt_ccd34b521001WeBauxJnuorFa5",
"sessionID": "ses_332cb6fa9ffehf0BwC73iSeZUR",
"messageID": "msg_ccd34a4030014dwF4qM30pkR3k"
},
{
"type": "step-finish",
"reason": "stop",
"snapshot": "d23faf4e134b40b649cf9ec6e7a21a632c4c61b1",
"cost": 0,
"tokens": {
"total": 17138,
"input": 2210,
"output": 80,
"reasoning": 45,
"cache": {
"read": 14848,
"write": 0
}
},
"id": "prt_ccd34b56f001tUZXybdhjVzB22",
"sessionID": "ses_332cb6fa9ffehf0BwC73iSeZUR",
"messageID": "msg_ccd34a4030014dwF4qM30pkR3k"
}
]
}
]
}
@@ -1 +0,0 @@
你好
@@ -1 +0,0 @@
你好!我在这儿。要我帮你看代码、改功能、排查报错,还是跑命令都可以。
@@ -1,14 +0,0 @@
# Session Context
Session ID: ses_332ce68b1ffe0R9vUQZ6yq5gUd
Commit Message: 在agent.md中加上,尽量使用能使用的skills和mcp
## Prompts
### Prompt 1
在agent.md中加上,尽量使用能使用的skills和mcp
## Summary
已添加到 `AGENTS.md` 的 CONVENTIONS 部分。
File diff suppressed because one or more lines are too long
@@ -1 +0,0 @@
在agent.md中加上,尽量使用能使用的skills和mcp
@@ -1 +0,0 @@
已添加到 `AGENTS.md` 的 CONVENTIONS 部分。
@@ -1,11 +0,0 @@
# Session Context
Session ID: ses_332d83674ffeNMa9Z9UerwU3tq
Commit Message: 提交全部变更并且push,创建pr
## Prompts
### Prompt 1
提交全部变更并且push,创建pr
File diff suppressed because one or more lines are too long
@@ -1 +0,0 @@
提交全部变更并且push,创建pr
File diff suppressed because one or more lines are too long
@@ -1 +0,0 @@
提交全部变更并且push,创建pr
@@ -1,8 +0,0 @@
已完成!
**提交摘要:**
- 10 个文件变更(939 行新增,173 行删除)
- 新增计划文档 `plans/020-ajax-no-refresh-ux.md`
- 新增工具函数 `vite-frontend/src/utils/list-state.ts`
**PR 已创建:** https://github.com/Sagit-chu/flvx/pull/293
File diff suppressed because one or more lines are too long
@@ -1 +0,0 @@
You are auditing the FLVX frontend for GitHub issue #276 (AJAX no-refresh UX improvements). Read-only only. Focus on existing implementation status for: 1) dashboard traffic auto-refresh, 2) node status real-time updates, 3) form submissions without full page reload, 4) local/partial list refresh after CRUD/toggle, 5) batch operation progress UI, 6) search/filter instant response. Inspect relevant files under vite-frontend/src/pages and src/api. Return a concise report with: a) what already exists, b) what is missing or partial, c) specific file paths and functions to touch for an implementation plan, d) notable risks or edge cases. Do not edit anything.
@@ -1,230 +0,0 @@
Concise audit for issue #276, focused on `vite-frontend/src/pages` and `src/api`.
a) What already exists
1. Dashboard traffic auto-refresh
- Dashboard data is loaded via async API calls in a hook, not by page reload:
- `/Users/sagit/.local/share/opencode/worktree/13650be91caa3a9e08a2e63127fef62757658384/quiet-canyon/vite-frontend/src/pages/dashboard/use-dashboard-data.ts`
- `useDashboardData()` calls `getUserPackageInfo()` and `getAnnouncement()`.
- The 24h traffic chart is already rendered from `statisticsFlows`:
- `/Users/sagit/.local/share/opencode/worktree/13650be91caa3a9e08a2e63127fef62757658384/quiet-canyon/vite-frontend/src/pages/dashboard.tsx`
- `/Users/sagit/.local/share/opencode/worktree/13650be91caa3a9e08a2e63127fef62757658384/quiet-canyon/vite-frontend/src/pages/dashboard/components/flow-chart-card.tsx`
2. Node status real-time updates
- This is the strongest existing area.
- WebSocket realtime hook already exists:
- `/Users/sagit/.local/share/opencode/worktree/13650be91caa3a9e08a2e63127fef62757658384/quiet-canyon/vite-frontend/src/pages/node/use-node-realtime.ts`
- `useNodeRealtime()`
- Offline debounce exists:
- `/Users/sagit/.local/share/opencode/worktree/13650be91caa3a9e08a2e63127fef62757658384/quiet-canyon/vite-frontend/src/pages/node/use-node-offline-timers.ts`
- Node page consumes websocket messages and updates local state without reload:
- `/Users/sagit/.local/share/opencode/worktree/13650be91caa3a9e08a2e63127fef62757658384/quiet-canyon/vite-frontend/src/pages/node.tsx`
- `handleWebSocketMessage()`
- `loadNodes()`
- Realtime also includes system info updates and upgrade progress updates.
3. Form submissions without full page reload
- Broadly already implemented across main CRUD pages using async handlers + modal close + state refresh.
- Examples:
- Nodes: `/Users/sagit/.local/share/opencode/worktree/13650be91caa3a9e08a2e63127fef62757658384/quiet-canyon/vite-frontend/src/pages/node.tsx`
- `handleSubmit()`
- Tunnels: `/Users/sagit/.local/share/opencode/worktree/13650be91caa3a9e08a2e63127fef62757658384/quiet-canyon/vite-frontend/src/pages/tunnel.tsx`
- `handleSubmit()`
- Forwards: `/Users/sagit/.local/share/opencode/worktree/13650be91caa3a9e08a2e63127fef62757658384/quiet-canyon/vite-frontend/src/pages/forward.tsx`
- `handleSubmit()`
- Users: `/Users/sagit/.local/share/opencode/worktree/13650be91caa3a9e08a2e63127fef62757658384/quiet-canyon/vite-frontend/src/pages/user.tsx`
- `handleSubmitUser()`
- I did not find page reload patterns in these CRUD pages (`location.reload` / `window.location.reload` absent there).
4. Local/partial list refresh after CRUD/toggle
- Some local optimistic/partial updates already exist:
- Node delete updates local state directly:
- `/Users/sagit/.local/share/opencode/worktree/13650be91caa3a9e08a2e63127fef62757658384/quiet-canyon/vite-frontend/src/pages/node.tsx`
- `confirmDelete()`
- Node edit updates local item directly:
- `handleSubmit()` edit branch
- Forward service toggle uses optimistic local update + rollback on failure:
- `/Users/sagit/.local/share/opencode/worktree/13650be91caa3a9e08a2e63127fef62757658384/quiet-canyon/vite-frontend/src/pages/forward.tsx`
- `handleServiceToggle()`
- Sorting persists locally and updates item `inx` in-memory after success:
- Node `handleDragEnd()`
- Tunnel `handleDragEnd()`
- Forward `handleDragEnd()`
5. Batch operation progress UI
- Node upgrade has actual per-node progress UI:
- `/Users/sagit/.local/share/opencode/worktree/13650be91caa3a9e08a2e63127fef62757658384/quiet-canyon/vite-frontend/src/pages/node.tsx`
- `upgradeProgress` state
- websocket `type === "upgrade_progress"` handling in `handleWebSocketMessage()`
- `<Progress />` render around lines ~1307+
- Forward batch actions are factored and return structured outcomes:
- `/Users/sagit/.local/share/opencode/worktree/13650be91caa3a9e08a2e63127fef62757658384/quiet-canyon/vite-frontend/src/pages/forward/batch-actions.ts`
6. Search/filter instant response
- Instant client-side filtering already exists in:
- Nodes: `sortedNodes` memo filters by `searchKeyword`
- `/Users/sagit/.local/share/opencode/worktree/13650be91caa3a9e08a2e63127fef62757658384/quiet-canyon/vite-frontend/src/pages/node.tsx`
- Tunnels: `sortedTunnels`
- `/Users/sagit/.local/share/opencode/worktree/13650be91caa3a9e08a2e63127fef62757658384/quiet-canyon/vite-frontend/src/pages/tunnel.tsx`
- Forwards: `orderedForwards`
- `/Users/sagit/.local/share/opencode/worktree/13650be91caa3a9e08a2e63127fef62757658384/quiet-canyon/vite-frontend/src/pages/forward.tsx`
- Forward also has instant client-side filter dropdowns (`filterUserId`, `filterTunnelId`).
b) What is missing or partial
1. Dashboard traffic auto-refresh: missing
- `useDashboardData()` only fetches once on mount.
- No polling, websocket, refetch trigger, focus refresh, or manual refresh hook.
- So “AJAX no-refresh” exists only for initial load, not ongoing refresh.
2. Node realtime: partial but good
- Realtime status/system-info exists only for nodes.
- It reconnects with limited retries (5 attempts) and then stops.
- `loadNodes()` initially sets `systemInfo: null`, so a full reload can temporarily wipe metrics until WS catches up again.
- No obvious fallback polling if websocket dies permanently.
3. Form submission no full reload: mostly done
- CRUD forms are already async and modal-driven.
- But post-submit refresh style is inconsistent:
- some do local patch,
- many do full page-level list refetch (`loadData()`, `loadUsers()`, `loadNodes()`).
4. Local/partial list refresh after CRUD/toggle: partial/inconsistent
- Forward toggle is good and local.
- Node edit/delete are relatively local.
- But many operations still refetch the whole page dataset:
- Tunnel create/update/delete -> `loadData()`
- Forward create/update/delete -> `loadData()`
- User create/update/delete -> `loadUsers()`
- User tunnel assignment/update/remove -> `loadUserTunnels()`
- This is AJAX and avoids full browser reload, but not “partial/local refresh” in the stronger UX sense.
5. Batch operation progress UI: largely missing outside node upgrade
- Tunnel batch delete/redeploy: only loading spinner/toast + full reload, no per-item progress/result panel.
- Forward batch actions: summarized via toast and optional refresh, but no visible progress timeline/progress list.
- User batch tunnel assignment: no progress UI beyond loading state.
6. Search/filter instant response: mixed
- Nodes/tunnels/forwards are instant client-side.
- Users are not fully instant:
- `/Users/sagit/.local/share/opencode/worktree/13650be91caa3a9e08a2e63127fef62757658384/quiet-canyon/vite-frontend/src/pages/user.tsx`
- `loadUsers()` is server-driven and tied to `useEffect([pagination.current, pagination.size, searchKeyword])`
- Enter key also manually calls `handleSearch()`
- So user search is AJAX but not purely local/instant in the same way.
c) Specific file paths and functions to touch for an implementation plan
Primary targets
1. Dashboard auto-refresh
- `/Users/sagit/.local/share/opencode/worktree/13650be91caa3a9e08a2e63127fef62757658384/quiet-canyon/vite-frontend/src/pages/dashboard/use-dashboard-data.ts`
- `useDashboardData()`
- extract `loadPackageData()` / `loadAnnouncement()` into stable callbacks
- add polling or visibility/focus-based refetch
- `/Users/sagit/.local/share/opencode/worktree/13650be91caa3a9e08a2e63127fef62757658384/quiet-canyon/vite-frontend/src/pages/dashboard.tsx`
- if adding manual refresh indicator/button, this is the page entry
- API source already exists:
- `/Users/sagit/.local/share/opencode/worktree/13650be91caa3a9e08a2e63127fef62757658384/quiet-canyon/vite-frontend/src/api/index.ts`
- `getUserPackageInfo()`, `getAnnouncement()`
2. Node realtime hardening / fallback
- `/Users/sagit/.local/share/opencode/worktree/13650be91caa3a9e08a2e63127fef62757658384/quiet-canyon/vite-frontend/src/pages/node/use-node-realtime.ts`
- `useNodeRealtime()`
- retry policy, reconnect strategy, possible fallback refresh trigger
- `/Users/sagit/.local/share/opencode/worktree/13650be91caa3a9e08a2e63127fef62757658384/quiet-canyon/vite-frontend/src/pages/node.tsx`
- `handleWebSocketMessage()`
- `loadNodes()`
- `handleSubmit()`
- `confirmDelete()`
- `handleBatchDelete()`
3. Replace whole-list reloads with local/partial updates
- Tunnels:
- `/Users/sagit/.local/share/opencode/worktree/13650be91caa3a9e08a2e63127fef62757658384/quiet-canyon/vite-frontend/src/pages/tunnel.tsx`
- `loadData()`
- `handleSubmit()`
- `confirmDelete()`
- `handleBatchDelete()`
- `handleBatchRedeploy()`
- Forwards:
- `/Users/sagit/.local/share/opencode/worktree/13650be91caa3a9e08a2e63127fef62757658384/quiet-canyon/vite-frontend/src/pages/forward.tsx`
- `loadData()`
- `handleSubmit()`
- `confirmDelete()`
- `handleServiceToggle()`
- `handleBatchDelete()`
- `handleBatchToggleService()`
- `handleBatchRedeploy()`
- `handleBatchChangeTunnel()`
- Users:
- `/Users/sagit/.local/share/opencode/worktree/13650be91caa3a9e08a2e63127fef62757658384/quiet-canyon/vite-frontend/src/pages/user.tsx`
- `loadUsers()`
- `handleSubmitUser()`
- `handleConfirmDelete()`
- `loadUserTunnels()`
- `handleBatchAssignTunnel()`
- `handleUpdateTunnel()`
- `handleConfirmRemoveTunnel()`
- `handleConfirmResetFlow()`
- `handleConfirmResetTunnelFlow()`
4. Batch progress/result UX
- Nodes already have a model to copy:
- `/Users/sagit/.local/share/opencode/worktree/13650be91caa3a9e08a2e63127fef62757658384/quiet-canyon/vite-frontend/src/pages/node.tsx`
- `upgradeProgress`
- websocket `upgrade_progress`
- Forward batch abstraction:
- `/Users/sagit/.local/share/opencode/worktree/13650be91caa3a9e08a2e63127fef62757658384/quiet-canyon/vite-frontend/src/pages/forward/batch-actions.ts`
- likely extend return shape if backend can expose richer progress/events
- API endpoints involved:
- `/Users/sagit/.local/share/opencode/worktree/13650be91caa3a9e08a2e63127fef62757658384/quiet-canyon/vite-frontend/src/api/index.ts`
- `batchDeleteForwards()`
- `batchPauseForwards()`
- `batchResumeForwards()`
- `batchRedeployForwards()`
- `batchChangeTunnel()`
- `batchDeleteTunnels()`
- `batchRedeployTunnels()`
- `batchDeleteNodes()`
- `batchUpgradeNodes()`
5. Search/filter behavior normalization
- `/Users/sagit/.local/share/opencode/worktree/13650be91caa3a9e08a2e63127fef62757658384/quiet-canyon/vite-frontend/src/pages/user.tsx`
- `loadUsers()`
- `handleSearch()`
- search input around lines ~718+
- Nodes/tunnels/forwards already have memo-based client filtering and are the pattern to follow.
d) Notable risks / edge cases
1. Dashboard polling could spam toasts
- `checkExpirationNotifications()` runs inside package load flow.
- If polling is added naively, expiration toasts could repeat or localStorage notification keys could churn unexpectedly.
2. Dashboard chart semantics
- `statisticsFlows` appears to be a snapshot list, not a stream API.
- Frequent polling may redraw aggressively and may need dedupe/staleness handling.
3. Node websocket auth/security
- Realtime URL sends token in query string (`secret=${getToken()}`) in:
- `/Users/sagit/.local/share/opencode/worktree/13650be91caa3a9e08a2e63127fef62757658384/quiet-canyon/vite-frontend/src/pages/node/use-node-realtime.ts`
- Any changes should be careful not to break backend expectations.
4. Realtime/local state merge complexity
- `loadNodes()` normalizes nodes and clears `systemInfo`.
- If partial refetch is introduced, merging fetched node metadata with live websocket state must avoid wiping online metrics/progress.
5. Batch APIs may not provide granular progress
- Current batch helpers mostly return summary counts, not per-item progress.
- True progress UI may require backend support, not only frontend work.
6. Forward toggle consistency
- `handleServiceToggle()` optimistically flips `serviceRunning` and later patches `status`.
- If backend returns partial failure or delayed actual state, UI may drift until a refresh.
7. User search behavior currently depends on backend pagination/search
- Moving to fully instant local filtering may conflict with server-side pagination semantics and large datasets.
Bottom line
- Already present: async modal CRUD, no browser reloads, strong node realtime, optimistic forward toggle, instant search/filter on node/tunnel/forward pages.
- Missing/partial for #276: dashboard traffic auto-refresh, consistent partial/local state updates after CRUD, batch progress UI outside node upgrade, and more unified instant-search UX on the user page.
@@ -1,41 +0,0 @@
# Session Context
Session ID: ses_332fdb603ffeYxhpzgAB64sSTN
Commit Message: 开始实施
## Prompts
### Prompt 1
https://github.com/Sagit-chu/flvx/issues/276
计划一下这个issue实现
### Prompt 2
写出 plans/020-ajax-no-refresh-ux.md 的完整实施计划内容
### Prompt 3
开始实施
## Summary
我先把 Phase 1 落地了,重点做了仪表盘自动刷新和节点实时连接兜底,并把计划文档同步更新了。
- `vite-frontend/src/pages/dashboard/use-dashboard-data.ts:55` 现在加入了 5 秒静默轮询、标签页可见性恢复刷新,以及更稳定的加载回调拆分,避免每次刷新都走整套初始化逻辑。
- `vite-frontend/src/pages/dashboard/use-dashboard-data.ts:82` 把过期提醒的去重 key 改成基于用户/隧道到期信息的稳定标识,轮询刷新流量时不会反复弹 toast。
- `vite-frontend/src/pages/node/use-node-realtime.ts:13` 补强了 WebSocket 重连策略:前几次按递增延迟重连,超过阈值后进入长间隔 fallback 模式,而不是彻底停掉。
- `vite-frontend/src/pages/node.tsx:68` 增加了节点列表 merge 逻辑;fallback 刷新时会保留已有 `systemInfo`、升级/复制/回退 loading 状态,避免列表刷新把实时信息清空。
- `vite-frontend/src/pages/node.tsx:1160` 节点页断线提示现在会区分“正在重连”和“已切换为列表自动刷新兜底模式”。
- `vite-frontend/src/vite-env.d.ts:4` 补上了 `VITE_API_BASE` 类型声明,顺手消掉这次构建会碰到的环境变量类型报错。
- `plans/020-ajax-no-refresh-ux.md:19` 已把本次完成的 3 个 Phase 1 checklist 勾掉。
验证情况:
- 运行了 `cd vite-frontend && npm install`
- 运行了 `cd vite-frontend && npm run build`
- 前端构建已通过
这次额外生成了依赖文件:
- `vite-frontend/package-lock.json`
下一步自然就是继续 Phase 2,把 `forward` / `tunnel` / `user` 的“操作后整页数据重拉”改成局部 patch。你要我继续的话,我建议从 `vite-frontend/src/pages/forward.tsx` 开始,因为它已经有一部分本地更新模式,改起来最顺。
File diff suppressed because one or more lines are too long
@@ -1,10 +0,0 @@
https://github.com/Sagit-chu/flvx/issues/276
计划一下这个issue实现
---
写出 plans/020-ajax-no-refresh-ux.md 的完整实施计划内容
---
开始实施
@@ -1,19 +0,0 @@
我先把 Phase 1 落地了,重点做了仪表盘自动刷新和节点实时连接兜底,并把计划文档同步更新了。
- `vite-frontend/src/pages/dashboard/use-dashboard-data.ts:55` 现在加入了 5 秒静默轮询、标签页可见性恢复刷新,以及更稳定的加载回调拆分,避免每次刷新都走整套初始化逻辑。
- `vite-frontend/src/pages/dashboard/use-dashboard-data.ts:82` 把过期提醒的去重 key 改成基于用户/隧道到期信息的稳定标识,轮询刷新流量时不会反复弹 toast。
- `vite-frontend/src/pages/node/use-node-realtime.ts:13` 补强了 WebSocket 重连策略:前几次按递增延迟重连,超过阈值后进入长间隔 fallback 模式,而不是彻底停掉。
- `vite-frontend/src/pages/node.tsx:68` 增加了节点列表 merge 逻辑;fallback 刷新时会保留已有 `systemInfo`、升级/复制/回退 loading 状态,避免列表刷新把实时信息清空。
- `vite-frontend/src/pages/node.tsx:1160` 节点页断线提示现在会区分“正在重连”和“已切换为列表自动刷新兜底模式”。
- `vite-frontend/src/vite-env.d.ts:4` 补上了 `VITE_API_BASE` 类型声明,顺手消掉这次构建会碰到的环境变量类型报错。
- `plans/020-ajax-no-refresh-ux.md:19` 已把本次完成的 3 个 Phase 1 checklist 勾掉。
验证情况:
- 运行了 `cd vite-frontend && npm install`
- 运行了 `cd vite-frontend && npm run build`
- 前端构建已通过
这次额外生成了依赖文件:
- `vite-frontend/package-lock.json`
下一步自然就是继续 Phase 2,把 `forward` / `tunnel` / `user` 的“操作后整页数据重拉”改成局部 patch。你要我继续的话,我建议从 `vite-frontend/src/pages/forward.tsx` 开始,因为它已经有一部分本地更新模式,改起来最顺。
@@ -1,32 +0,0 @@
# Session Context
Session ID: ses_349a99cf4ffeQMqVmv7PqyI3y6
Commit Message: 普通用户添加转发的时候应该不能有权限设置限速和设置自定义端口,请检查并规划设计
## Prompts
### Prompt 1
普通用户添加转发的时候应该不能有权限设置限速和设置自定义端口,请检查并规划设计
## Summary
## 分析结果
### 当前状态
- **角色系统**: `roleID == 0` 为管理员,`roleID != 0` 为普通用户
- **问题**: 普通用户在创建/编辑转发时可设置 `speedId`(限速) 和 `inPort`(自定义端口)
### 实施方案
**后端修改** (`go-backend/internal/http/handler/mutations.go`):
- `forwardCreate`: 检查 `roleID != 0` 时拒绝 `speedId` 和 `inPort`
- `forwardUpdate`: 检查 `actorRole != 0` 时拒绝 `speedId` 和 `inPort`
**前端修改** (`vite-frontend/src/pages/forward.tsx`):
- 限速规则选择器和入口端口输入框使用 `{isAdmin && (...)}` 条件渲染
**测试**:
- 添加契约测试验证权限限制
计划文档: `plans/009-restrict-user-forward-permissions.md`
File diff suppressed because one or more lines are too long
@@ -1 +0,0 @@
普通用户添加转发的时候应该不能有权限设置限速和设置自定义端口,请检查并规划设计
@@ -1,19 +0,0 @@
## 分析结果
### 当前状态
- **角色系统**: `roleID == 0` 为管理员,`roleID != 0` 为普通用户
- **问题**: 普通用户在创建/编辑转发时可设置 `speedId`(限速) 和 `inPort`(自定义端口)
### 实施方案
**后端修改** (`go-backend/internal/http/handler/mutations.go`):
- `forwardCreate`: 检查 `roleID != 0` 时拒绝 `speedId` 和 `inPort`
- `forwardUpdate`: 检查 `actorRole != 0` 时拒绝 `speedId` 和 `inPort`
**前端修改** (`vite-frontend/src/pages/forward.tsx`):
- 限速规则选择器和入口端口输入框使用 `{isAdmin && (...)}` 条件渲染
**测试**:
- 添加契约测试验证权限限制
计划文档: `plans/009-restrict-user-forward-permissions.md`
File diff suppressed because it is too large Load Diff
@@ -1 +0,0 @@
提交全部变更并且push,创建pr合并,发布新tag,2.1.7-beta6
@@ -1,5 +0,0 @@
完成:
- 已提交并推送变更
- PR #259 已合并到 main
- 已创建并推送 tag `2.1.7-beta6`
- 已删除远程分支
File diff suppressed because one or more lines are too long
@@ -1 +0,0 @@
转发选择限速后保存,然后把限速删除,再次编辑转发报错会报错限速不存在,请保存的时候限速不存在直接删除限速,不阻断提示限速不存在
@@ -1,20 +0,0 @@
我已经定位到问题点了,确实在后端 `forward/update` 的限速校验会把“已被删除的限速ID”当成硬错误返回,导致你说的二次编辑报 `限速规则不存在`。
**定位结果**
- 触发点在 `go-backend/internal/http/handler/mutations.go:1259` 附近(`forwardUpdate`)和 `go-backend/internal/http/handler/mutations.go:1147` 附近(`forwardCreate`)。
- 当前逻辑是:只要请求里带了 `speedId`,且 `SpeedLimitExists=false`,就直接 `ErrDefault("限速规则不存在")` 返回。
- 前端编辑提交在 `vite-frontend/src/pages/forward.tsx:1403` 会一直带 `speedId`(包括编辑场景),所以很容易复现你说的问题。
**实施计划(不改动其他业务)**
- 新建计划文档:`plans/006-forward-save-missing-speed-limit-auto-clear.md`(按现有 001~005 递增)。
- 后端仅改转发保存逻辑,不改用户隧道限速逻辑:
- `forwardCreate`:若 `speedId` 不存在,自动当成 `nil`(即“不限速”)继续保存,不返回“限速不存在”错误。
- `forwardUpdate`:按“最终要写入的 speed_id”做一次兜底校验;若不存在则自动清空为 `NULL` 再继续保存,确保编辑不阻断。
- 不新增“限速不存在”阻断提示(符合你要求)。
- 增加/更新合约测试:`go-backend/tests/contract/forward_contract_test.go`
- 覆盖场景:转发绑定限速后,删除该限速,再编辑转发保存,应返回成功且 `forward.speed_id` 被清空。
- 验证命令(实施后执行):
- `cd go-backend && go test ./tests/contract/... -run Forward`
- 如有必要再跑 `cd go-backend && go test ./...`
如果你确认,我下一步就按这个方案进入实现。
File diff suppressed because one or more lines are too long
@@ -1 +0,0 @@
提交全部变更并且push,创建pr合并,发布新tag,2.1.7-beta5
@@ -1,7 +0,0 @@
✅ 已完成:
- 提交变更:feat: auto-fallback to default bind IP when invalid bind address detected
- 推送分支:opencode/mighty-nebula → origin
- 创建PR:#258(已自动合并)
- 发布tag:2.1.7-beta5
PR: https://github.com/Sagit-chu/flvx/pull/258
File diff suppressed because one or more lines are too long
@@ -1 +0,0 @@
提交全部变更并且push,创建pr合并,发布新tag,2.1.7-beta4
@@ -1,6 +0,0 @@
Tag `2.1.7-beta4` 已在 GitHub 远程创建成功。
**完成摘要:**
- 提交: `7efb49b` - fix: handle forward service rebind on self-occupied port
- PR: https://github.com/Sagit-chu/flvx/pull/257 (已合并)
- Tag: `2.1.7-beta4` 已推送到远程
File diff suppressed because one or more lines are too long
@@ -1,17 +0,0 @@
转发编辑保存报错create service 3_1_0_tcp failed: listen tcp4 13.228.170.187:16765: bind: cannot assign requested address
引发条件:当编辑选择入口IP原来是默认地址,选择成和默认地址一样的地址的时候报错
---
保持“只要用户选了IP就一定显式绑定”,如果选择的IP后发现端口占用,检测是否是当前转发占用的,如果是那就释放掉,避免原来是默认监听::所有地址后永远无法切换
---
按计划实现
---
节点 test-sg 下发失败: create service 3_1_0_tcp failed: listen tcp4 13.228.170.187:56025: bind: cannot assign requested address
还是不行啊,由默认入口IP创建的转发,然后编辑选择了唯一的一个IP后报错了
@@ -1,23 +0,0 @@
你这个新报错我确认了:这次**不是端口占用问题**,是 **IP 本机不可绑定** 问题。
- 报错是 `bind: cannot assign requested address`,含义是节点机器网卡上没有 `13.228.170.187` 这个本地地址;释放旧服务也不会解决。
- 你说“唯一一个IP可选”,很可能来自前端当前候选逻辑把 `serverIp/serverIpV4/serverIpV6` 当成监听候选(`vite-frontend/src/pages/forward.tsx:612` 一带),但这些字段在 NAT/云环境下常是“对外地址”,不一定是本机可 bind 地址。
- 我之前加的自占用释放逻辑会在冲突时尝试删旧服务再加新服务,但对 `cannot assign requested address` 这种错误会一直失败(因为 IP 本身不可绑定)。
我建议下一步这样改(这次是关键):
- 后端只把 `address already in use` 走“自占用释放重绑”流程;`cannot assign requested address` 不走该流程。
位置:`go-backend/internal/http/handler/control_plane.go`
- 前端监听 IP 下拉改为“可绑定地址优先”:优先 `extraIPs` + 明确配置的监听地址,**不再默认把 `serverIp*` 作为可绑定监听IP**。
位置:`vite-frontend/src/pages/forward.tsx`
- 后端增加快速校验并返回更明确提示:
`监听IP不是节点本机地址,请在节点 extraIPs 配置可绑定IP后再选择`。
位置:`go-backend/internal/http/handler/control_plane.go` + repo 查询辅助。
- 你的临时可用绕过:到节点配置里把真实网卡 IP 填到 `extraIPs`,然后在编辑转发时选该 IP。
一个需要你拍板的点(推荐第1个):
1. **推荐**:前端不再展示 `serverIp/serverIpV4/serverIpV6` 为监听IP候选,只展示 `extraIPs`(和明确监听地址)。
2. 继续展示 `serverIp*`,但加“可能不可绑定”标签和失败提示。
你回我 `1` 或 `2`,我就按这个继续落地。
File diff suppressed because one or more lines are too long
@@ -1 +0,0 @@
提交全部变更并且push,创建pr合并,发布新tag,2.1.7-beta3
@@ -1,8 +0,0 @@
完成!已成功:
1. **提交变更**: 5个文件(修复绑定IP保留问题 + 新增单元测试)
2. **推送分支**: opencode/mighty-nebula → origin
3. **创建PR**: #256 (已合并)
4. **发布tag**: 2.1.7-beta3
PR #256: https://github.com/Sagit-chu/flvx/pull/256
File diff suppressed because one or more lines are too long
@@ -1 +0,0 @@
编辑转发后保存报错 下发失败: create service 3_1_0_tcp failed: listen tcp4 13.228.170.187:16765: bind: cannot assign requested address,这个bug是因为增加了自定义IP功能后导致的,监听IP 不选择就会报错,应该根据原来的监听状态保存
@@ -1,23 +0,0 @@
你这个判断是对的,我已经把链路看清了,确实是“新增自定义监听 IP 后,编辑保存把原监听状态覆盖掉”导致的。
- 前端编辑表单会把 `forward.inIp` 直接回填到 `form.inIp`(`vite-frontend/src/pages/forward.tsx:1302`)。
- 保存时会把 `form.inIp` 带到更新请求(`vite-frontend/src/pages/forward.tsx:1391`)。
- 后端更新时无论是否真的改了监听 IP,都会用请求里的 `inIp` 全量重建 `forward_port`(`go-backend/internal/http/handler/mutations.go:1288`、`go-backend/internal/http/handler/mutations.go:1305`、`go-backend/internal/http/handler/mutations.go:3019`)。
- 而列表里的 `forward.inIp` 可能是“展示回退值”(隧道 IP/节点 IP),不一定是原始 `forward_port.in_ip`(`go-backend/internal/store/repo/repository.go:731`、`go-backend/internal/store/repo/repository.go:2778`、`go-backend/internal/store/repo/repository.go:2780`)。
- 这样就会在“没手动选监听 IP”时,把服务改成绑定不可用地址,触发 `bind: cannot assign requested address`。
我建议的修复方案(实现时会做成双保险):
- 前端:编辑模式下仅当用户“主动改过监听 IP”时才提交 `inIp` 字段;未触碰则不传,保持原状态。
- 后端:`forward/update` 中如果请求没带 `inIp`,就保留原 `forward_port.in_ip`(不清空、不覆盖);若带了 `inIp`(包括空串),按用户意图更新。
- 回归测试:
- 后端新增用例:未传 `inIp` 时更新不改变监听绑定。
- 后端新增用例:显式传空串时清空监听绑定。
- (可选)前端补充一个轻量逻辑测试/至少手工验证路径。
另外按仓库规则,这次会新增计划文档为:`plans/003-forward-edit-bind-ip-preserve.md`(当前是只读 Plan Mode,我还没动文件)。
一个需要你拍板的小点(我给默认建议):
- **推荐默认**:编辑时如果改了隧道但没有手动选“监听IP”,按“默认监听(空)”处理,不继承旧隧道的监听 IP。
这样能避免把旧隧道的 IP 误带到新隧道。
你是否同意按这个规则?
File diff suppressed because one or more lines are too long
@@ -1,13 +0,0 @@
提交全部变更并且push,创建pr合并,发布新tag,beta版本
---
不对,tag是2.1.7-beta2
---
2.1.8-beta1 标签没有被删除成功
---
2.1.8-alpha1 标签没有被删除成功
@@ -1 +0,0 @@
已删除 `2.1.8-alpha1` 标签。当前最新版本为 `2.1.7-beta2`。
@@ -1,41 +0,0 @@
# Session Context
Session ID: ses_34d1fa4b1ffeH4sVbjXkh5P6IY
Commit Message: 实施
## Prompts
### Prompt 1
转发导入,ny兼容格式,不要选择入口,改成选择隧道,修改兼容一下
### Prompt 2
自动分配端口(推荐)
### Prompt 3
实施
## Summary
已实施完成,这次改动把 `ny` 导入完全对齐到“选隧道”流程,并按你指定支持“端口缺失自动分配”。
- `ny` 解析兼容增强:支持字段别名、可选端口
- 修改 `vite-frontend/src/pages/forward/import-format.ts`
- `listen_port` 现在允许为 `null`(缺失即自动分配)
- 兼容字段:`dest/dst/target/targets`、`listen_port/listenPort/port/in_port/inPort`、`name/forward_name/forwardName`
- `dest` 支持数组或逗号分隔字符串,统一归一化
- 导入 UI 文案已同步更新(强调按所选隧道导入 + 端口可省略)
- 修改 `vite-frontend/src/pages/forward.tsx:4623`、`vite-frontend/src/pages/forward.tsx:4699`
- 测试已补齐并通过
- 修改 `vite-frontend/src/pages/forward/import-format.test.ts`
- 新增用例:缺失端口自动分配、别名字段兼容、`inPort: null` 映射
- 计划文档已新增并完成勾选
- `plans/002-ny-import-tunnel-selection-compat.md`
验证结果:
- `npm run build`(`vite-frontend`)通过
- `node --test src/pages/forward/import-format.test.ts` 7/7 通过
如果你要,我下一步可以直接帮你提交一个规范 commit。
File diff suppressed because one or more lines are too long
@@ -1,9 +0,0 @@
转发导入,ny兼容格式,不要选择入口,改成选择隧道,修改兼容一下
---
自动分配端口(推荐)
---
实施
@@ -1,20 +0,0 @@
已实施完成,这次改动把 `ny` 导入完全对齐到“选隧道”流程,并按你指定支持“端口缺失自动分配”。
- `ny` 解析兼容增强:支持字段别名、可选端口
- 修改 `vite-frontend/src/pages/forward/import-format.ts`
- `listen_port` 现在允许为 `null`(缺失即自动分配)
- 兼容字段:`dest/dst/target/targets`、`listen_port/listenPort/port/in_port/inPort`、`name/forward_name/forwardName`
- `dest` 支持数组或逗号分隔字符串,统一归一化
- 导入 UI 文案已同步更新(强调按所选隧道导入 + 端口可省略)
- 修改 `vite-frontend/src/pages/forward.tsx:4623`、`vite-frontend/src/pages/forward.tsx:4699`
- 测试已补齐并通过
- 修改 `vite-frontend/src/pages/forward/import-format.test.ts`
- 新增用例:缺失端口自动分配、别名字段兼容、`inPort: null` 映射
- 计划文档已新增并完成勾选
- `plans/002-ny-import-tunnel-selection-compat.md`
验证结果:
- `npm run build`(`vite-frontend`)通过
- `node --test src/pages/forward/import-format.test.ts` 7/7 通过
如果你要,我下一步可以直接帮你提交一个规范 commit。
File diff suppressed because one or more lines are too long
@@ -1,5 +0,0 @@
提交全部变更并且push,创建pr合并,发布新tag,alpha版本
---
不对,撤销tag,发布2.1.7-beta1
@@ -1,3 +0,0 @@
已完成:
- 删除标签 `2.1.8-alpha1`(本地+远程)
- 创建并推送标签 `2.1.7-beta1` 到 `origin/main`
File diff suppressed because one or more lines are too long
@@ -1 +0,0 @@
提交全部变更并且push,创建pr合并,发布新tag,alpha版本
@@ -1,13 +0,0 @@
完成!
**总结:**
- ✅ 提交变更:`feat: add ny format support for forward import with node-based tunnel matching`
- ✅ 推送到远程分支 `opencode/mighty-nebula`
- ✅ 创建 PR #250 并自动合并到 main
- ✅ 发布新 tag `2.1.7-alpha9`
**新版本特性:**
- 新增 ny 格式转发数据导入支持(JSON格式,多目标地址负载均衡)
- 入口节点选择功能,自动匹配端口转发类型隧道
- 多隧道匹配时提供选择界面
- 新增 import-format.ts 解析模块及测试文件
@@ -1,49 +0,0 @@
# Session Context
Session ID: ses_34d7fcdb8ffekb7lvyJwVvoS8T
Commit Message: 增加功能:转发规则批量导入格式,兼容ny的导入格式
ny格式如下:
{"dest":["151.241.129.52:23609"],"list
## Prompts
### Prompt 1
增加功能:转发规则批量导入格式,兼容ny的导入格式
ny格式如下:
{"dest":["151.241.129.52:23609"],"listen_port":20224,"name":"灵玥-JP-Lpt【三网通用】"}{"dest":["64.81.33.2:24577"],"listen_port":41034,"name":"Yolo-US-Lpt【三网通用】"}
ny导入的时候是选择入口的,flvx转发导入是选择隧道的,需要兼容一下,请设计计划
## Summary
计划文档已设计完成。以下是计划摘要:
## 计划摘要
### 格式对比
| 特性 | flvx格式 | ny格式 |
|------|----------|--------|
| 格式 | 管道分隔文本 | 紧凑JSON对象 |
| 示例 | `ip:port\|name\|port` | `{"dest":["ip:port"],"listen_port":port,"name":"name"}` |
| 多目标 | 逗号分隔 | dest数组 |
| 选择器 | 选择隧道 | 选择入口节点→匹配隧道 |
### 核心设计
1. **格式选择器**:手动选择"flvx格式"或"ny格式"
2. **ny格式流程**:选择入口节点 → 匹配端口转发隧道 → 匹配0个报错、1个直接用、多个弹窗选
3. **不自动创建隧道**:无匹配时提示用户先创建
### 任务清单
1. 新增`importFormat`、`selectedEntryNode`、`matchedTunnels`等状态
2. 重构导入模态框UI,添加格式选择器
3. 实现ny格式紧凑JSON解析函数
4. 实现入口节点选择与隧道匹配逻辑
5. 多隧道匹配时的选择器弹窗
6. 整合ny格式到`executeImport`函数
7. 更新提示文案
### 改动范围
- `vite-frontend/src/pages/forward.tsx` - 主要改动文件
是否需要我调整计划内容?
File diff suppressed because one or more lines are too long
@@ -1,5 +0,0 @@
增加功能:转发规则批量导入格式,兼容ny的导入格式
ny格式如下:
{"dest":["151.241.129.52:23609"],"listen_port":20224,"name":"灵玥-JP-Lpt【三网通用】"}{"dest":["64.81.33.2:24577"],"listen_port":41034,"name":"Yolo-US-Lpt【三网通用】"}
ny导入的时候是选择入口的,flvx转发导入是选择隧道的,需要兼容一下,请设计计划
@@ -1,30 +0,0 @@
计划文档已设计完成。以下是计划摘要:
## 计划摘要
### 格式对比
| 特性 | flvx格式 | ny格式 |
|------|----------|--------|
| 格式 | 管道分隔文本 | 紧凑JSON对象 |
| 示例 | `ip:port\|name\|port` | `{"dest":["ip:port"],"listen_port":port,"name":"name"}` |
| 多目标 | 逗号分隔 | dest数组 |
| 选择器 | 选择隧道 | 选择入口节点→匹配隧道 |
### 核心设计
1. **格式选择器**:手动选择"flvx格式"或"ny格式"
2. **ny格式流程**:选择入口节点 → 匹配端口转发隧道 → 匹配0个报错、1个直接用、多个弹窗选
3. **不自动创建隧道**:无匹配时提示用户先创建
### 任务清单
1. 新增`importFormat`、`selectedEntryNode`、`matchedTunnels`等状态
2. 重构导入模态框UI,添加格式选择器
3. 实现ny格式紧凑JSON解析函数
4. 实现入口节点选择与隧道匹配逻辑
5. 多隧道匹配时的选择器弹窗
6. 整合ny格式到`executeImport`函数
7. 更新提示文案
### 改动范围
- `vite-frontend/src/pages/forward.tsx` - 主要改动文件
是否需要我调整计划内容?
File diff suppressed because one or more lines are too long
@@ -1 +0,0 @@
提交全部变更并且push,创建pr合并,发布新tag,alpha版本
@@ -1,6 +0,0 @@
✅ 完成:
- **提交**: `fix: use configured connectIp for tunnel chain diagnosis` (1c10347)
- **PR**: #248 已合并 → https://github.com/Sagit-chu/flvx/pull/248
- **Tag**: `2.1.7-alpha8` 已创建并推送
变更内容:修复了隧道链诊断时使用配置的 connectIp、forward 绑定 IP 支持带端口的地址、添加了全面的测试覆盖。
@@ -1,24 +0,0 @@
# Session Context
Session ID: ses_34dfc44d5ffedfgo4G9wPONyXC
Commit Message: 在agent.md里规定,每次计划都必须写一个计划文档,md格式,按序号增加和以计划的总结命名,每次完成一个任务做好标记
## Prompts
### Prompt 1
在agent.md里规定,每次计划都必须写一个计划文档,md格式,按序号增加和以计划的总结命名,每次完成一个任务做好标记
## Summary
已按你的要求更新完成。
我在 `AGENTS.md` 里新增了 `## PLAN DOCUMENT RULE` 章节,内容包括:
- 每次新实现计划都必须有独立 Markdown 计划文档
- 计划文档统一放在 `plans/` 目录
- 文件名采用递增序号 + 计划摘要:`NNN-<plan-summary>.md`
- 序号必须每次 +1
- 文档内使用任务清单,并在每个任务完成后立即打勾标记
修改位置:`AGENTS.md`
File diff suppressed because one or more lines are too long
@@ -1 +0,0 @@
在agent.md里规定,每次计划都必须写一个计划文档,md格式,按序号增加和以计划的总结命名,每次完成一个任务做好标记
@@ -1,11 +0,0 @@
已按你的要求更新完成。
我在 `AGENTS.md` 里新增了 `## PLAN DOCUMENT RULE` 章节,内容包括:
- 每次新实现计划都必须有独立 Markdown 计划文档
- 计划文档统一放在 `plans/` 目录
- 文件名采用递增序号 + 计划摘要:`NNN-<plan-summary>.md`
- 序号必须每次 +1
- 文档内使用任务清单,并在每个任务完成后立即打勾标记
修改位置:`AGENTS.md`
@@ -1,71 +0,0 @@
# Session Context
Session ID: ses_34dfda207ffeiBV2rCgJW708ip
Commit Message: 配置下发也没兼容,请全量检查一下,哪些功能需要一起改造
## Prompts
### Prompt 1
211 任务的没有完全完成1. 选择IP后诊断还会诊断默认IP
2. 选择隧道出口IP后,入口还是会链接默认IP,没有链接选择的IP
请分析后制定修复计划
### Prompt 2
配置下发也没兼容,请全量检查一下,哪些功能需要一起改造
## Summary
你提得很对,我按“配置下发全链路”重新过了一遍(只读分析)。结论是:**需要一起改造的不是一个点,而是“诊断链路 + 重部署链路 + 回归测试链路”**。
目前状态可以分成三类:
- **已兼容(创建/更新时下发)**
- 隧道创建/更新时,`connectIp` 已进入运行时下发选择逻辑(`selectTunnelDialHost`)。
- 本地/联邦 runtime apply 都会吃 `target.ConnectIP`(前提是 state 里有值)。
- 参考:`go-backend/internal/http/handler/mutations.go:2588`, `go-backend/internal/http/handler/mutations.go:2348`
- **未兼容(你反馈的核心问题)**
- 诊断链路未传 `connectIp`,导致总走默认IP。
- 参考:`go-backend/internal/http/handler/control_plane.go:75`, `go-backend/internal/http/handler/control_plane.go:1102`
- **半兼容(配置重建时丢字段)**
- 重部署时从 DB 重建 runtime state,**没把 `ConnectIP` 带回去**,所以 redeploy 后会回退默认IP。
- 参考:`go-backend/internal/http/handler/mutations.go:883`, `go-backend/internal/http/handler/mutations.go:897`
---
**需要一起改造的功能范围(建议一次性做完)**
- `诊断(非流式 + 流式)`
- 隧道诊断、转发诊断都要改(共用 `prepare*Diagnosis` + `appendChainHopDiagnosis`)。
- 流式 start 预览项也要改,否则 UI 一开始仍显示默认IP。
- 目标文件:`go-backend/internal/http/handler/control_plane.go`, `go-backend/internal/http/handler/diagnosis_stream.go`
- `配置下发(重部署路径)`
- 单条重部署、批量重部署都依赖 `reconstructTunnelState`,必须补 `ConnectIP` 回填。
- 目标文件:`go-backend/internal/http/handler/mutations.go`
- `联邦节点运行时下发一致性`
- 逻辑本身已支持 `ConnectIP`,但受上一步 state 丢字段影响;修复后自动恢复一致。
- 重点验证:remote middle hop `ApplyRole.Targets` 的 Host 选取。
- `回归测试`
- 新增诊断用例:选了 `connectIp` 后,`targetIp` 必须是选中值(tunnel/forward + stream start/item)。
- 新增重部署用例:redeploy 后仍使用 `connectIp`,不回退默认IP。
- 目标文件建议:`go-backend/tests/contract/diagnosis_contract_test.go`,补 handler 级或 contract 级 redeploy 用例。
---
**实施计划(修复包)**
1. 修 `diagnosis` 调用链:所有 `resolveChainProbeTarget` 调用传入 `workItem.toNode.ConnectIP`。
2. 修 `reconstructTunnelState`:出口节点和中继节点都回填 `ConnectIP`。
3. 补测试:覆盖“诊断用选中IP”“重部署不丢IP”“connectIp为空仍走默认”的三组场景。
4. 联调验证:创建/更新、诊断、单重部署、批量重部署、联邦节点场景各跑一遍。
---
我建议按这个范围做成一次完整修复(避免只修诊断后你再次遇到“重部署又回退”的问题)。
如果你同意,我下一步就按这个“全量改造范围”进入实施。
File diff suppressed because one or more lines are too long

Some files were not shown because too many files have changed in this diff Show More