Skip to content

feat(installer): perMachine writes userData to ProgramData; uninstall cleans both#114

Open
ACCSCI wants to merge 5 commits into
masterfrom
feat/userdata-permachine
Open

feat(installer): perMachine writes userData to ProgramData; uninstall cleans both#114
ACCSCI wants to merge 5 commits into
masterfrom
feat/userdata-permachine

Conversation

@ACCSCI

@ACCSCI ACCSCI commented Jul 4, 2026

Copy link
Copy Markdown
Owner

概述

把"perMachine 装"和"perUser 装"的语义对齐到数据路径:装到 C:\Program Files\AgentDock\ 时,数据写到 C:\ProgramData\AgentDock\所有 Windows 用户共享);装到 %LOCALAPPDATA%\Programs\AgentDock\ 时,数据写到 %APPDATA%\AgentDock\当前用户隔离)。安装时保留 install-mode 页面——用户明确知道自己在选什么。

改动

  • electron/main/userdata.ts(新增):resolveUserDataPath() 通过 process.execPath 路径判断安装模式;migrateLegacyUserData() 首次启动时把旧 %APPDATA%\AgentDock 内容复制到新路径(不删旧数据)
  • electron/main.ts:在 app.whenReady 之前调 app.setPath('userData', resolved),并把 openGlobalDb() 默认路径从 ~/.agentdock 切到 userData 同位置
  • plugins/db/global.ts:删除 os.homedir() fallback,global DB 永远跟着 userData 走
  • build/installer/custom-uninstall.nsh(新增):NSIS 宏,卸载时同时清 %APPDATA%\AgentDock(标准行为)和 %PROGRAMDATA%\AgentDock(perMachine 装的位置)
  • electron-builder.ymldeleteAppDataOnUninstall: true + 引入自定义卸载宏
  • electron/main/tests/userdata.test.ts(新增):8/8 单测覆盖决策逻辑

之前的问题

旧版 perMachine: true 装的 exe 装到 Program Files\AgentDock\,但 global projects DB 仍然在 %USERPROFILE%\.agentdock\projects.db(per-user 路径)——perMachine 装只是名义上"全局",数据其实每个用户独立。新方案让"装模式"和"数据模式"对齐。

验证

  • npx vitest run --project unit electron/main/__tests__/userdata.test.ts —— 8/8 passed
  • npx electron-vite build 通过
  • 实机验证 perMachine 装时数据真写到 ProgramData、其他用户能访问
  • 实机验证卸载时两个路径都清干净

CI 不跑 e2e,所以实机验证留给人工。

关联

… cleans both

This unblocks the install mode page (perUser / perMachine radio) and
makes the data path follow the user's install choice:

- perUser install    -> %APPDATA%\AgentDock\ (current user only)
- perMachine install -> %PROGRAMDATA%\AgentDock\ (shared by all users)

Before this change, the global projects DB always lived in
%USERPROFILE%\.agentdock regardless of install mode, which made
perMachine install misleading: the binary was perMachine but the
project list was per-user. Now both move together.

- electron/main/userdata.ts: resolveUserDataPath() picks
  ProgramData vs AppData based on process.execPath. Migration
  copies legacy perUser AppData into the new location on first
  launch after switching install modes.
- electron/main.ts: call app.setPath('userData', resolved) before
  any IPC handler registers. Co-locate the global DB with the
  rest of the userData.
- plugins/db/global.ts: drop the homedir fallback so the global
  DB always follows userData.
- build/installer/custom-uninstall.nsh: NSIS macro that also
  cleans %PROGRAMDATA%\AgentDock\ on top of the standard
  %APPDATA%\AgentDock\ path electron-builder cleans by default.
- electron-builder.yml: deleteAppDataOnUninstall: true +
  include the new uninstall macro.
- electron/main/__tests__/userdata.test.ts: unit coverage for
  the decision logic (8/8 tests pass). E2E coverage deferred —
  CI doesn't run e2e, so it'll be local-only.
Copilot AI review requested due to automatic review settings July 4, 2026 11:23

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces support for per-machine installation mode on Windows, dynamically resolving the application's user data path to either %PROGRAMDATA% or %APPDATA% depending on the install location, and adds a migration utility for legacy user data. The review feedback highlights a critical logical operator bug in the migration file filtering, potential fragility in detecting the installation mode via hardcoded path substrings, and an issue in the NSIS uninstaller where shared data could be deleted unconditionally during GUI uninstalls. Additionally, it suggests refactoring redundant detection logic in the main process.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread electron/main/userdata.ts Outdated
Comment thread electron/main/userdata.ts
Comment thread build/installer/custom-uninstall.nsh Outdated
Comment thread electron/main.ts Outdated
Comment thread electron/main.ts Outdated
Marco Taylor added 4 commits July 4, 2026 19:30
customUnInstallSection was compiled into uninstaller.nsh which is
inside a Section body, so commands like ${Silent} and ReadRegStr
(which are valid runtime checks in a Function body but NOT valid in
this Section context) caused compilation to fail with:

  'Error: command IfSilent not valid outside Section or Function'

Replace with ${FileExists} + RMDir /r, which are legal NSIS runtime
commands in a Section. The macro now unconditionally cleans
$PROGRAMDATA\AgentDock\ if it exists — regardless of install mode.
For perUser installs (no ProgramData path) the ${FileExists} guard
prevents errors. For perMachine installs it removes the shared data
directory.
… body)

customUnInstallSection is expanded at script top-level (after SectionEnd)
where runtime NSIS commands are forbidden —  and RMDir
both cause 'command not valid outside Section or Function' errors.

Rename to customUnInstall, which is expanded inside Section 'Uninstall'
(line 156-157 of uninstaller.nsh), where runtime commands are valid.
NSIS treats \AgentDock as a single variable lookup (not
string concatenation), causing warning 6000 which is fatal in CI.
Fix by assigning $PROGRAMDATA to $0 via StrCpy, then appending
\AgentDock via StrCpy $0 "$0\AgentDock".
1. userdata.ts:85 — ||→&& in filter (critical: always-true bug)
   The filter  was always
   true because every string satisfies at least one side. Fixed to &&
   so both files are correctly excluded.

2. custom-uninstall.nsh — replaced NSIS  (not a valid NSIS
   built-in variable, causes warning 6000) with hardcoded
   'C:\ProgramData\AgentDock' + StrCpy +  guard.
   This is safe because ProgramData is always English on all Windows
   locales, and the path doesn't change per-user.

3. electron/main.ts — removed duplicate install mode detection
   (was re-checking process.execPath manually instead of calling
   detectInstallMode()) and added the missing import.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants