ai-helper-agent 2.0.0 → 2.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. package/README.md +28 -5
  2. package/README.zh-CN.md +28 -5
  3. package/bin/agent.js +150 -0
  4. package/dist/assets/{agent-store-BFaBECYz.js → agent-store-DOyMdB_7.js} +2 -2
  5. package/dist/assets/{agent-store-BFaBECYz.js.map → agent-store-DOyMdB_7.js.map} +1 -1
  6. package/dist/assets/background.js +86 -87
  7. package/dist/assets/background.js.map +1 -1
  8. package/dist/assets/content.js +84 -80
  9. package/dist/assets/{i18n-CohqPkkN.js → i18n-MmYITlVj.js} +9 -7
  10. package/dist/assets/i18n-MmYITlVj.js.map +1 -0
  11. package/dist/assets/model-profiles-CV_sUuPf.js +25 -0
  12. package/dist/assets/model-profiles-CV_sUuPf.js.map +1 -0
  13. package/dist/assets/options-Df_1Dtn8.css +1 -0
  14. package/dist/assets/options.js +78 -63
  15. package/dist/assets/options.js.map +1 -1
  16. package/dist/assets/page-snapshot-renderer-CE53ibi-.js +4 -0
  17. package/dist/assets/page-snapshot-renderer-CE53ibi-.js.map +1 -0
  18. package/dist/assets/session-store-B0ZPGm7d.js +77 -0
  19. package/dist/assets/session-store-B0ZPGm7d.js.map +1 -0
  20. package/dist/assets/side_panel.css +1 -1
  21. package/dist/assets/side_panel.js +478 -439
  22. package/dist/assets/side_panel.js.map +1 -1
  23. package/dist/icons/badges/version.svg +4 -4
  24. package/dist/manifest.json +6 -3
  25. package/dist/offscreen/offscreen.js +10 -8
  26. package/dist/options.html +3 -12
  27. package/dist/side_panel.html +120 -32
  28. package/package.json +1 -1
  29. package/src/install-mode.js +128 -0
  30. package/src/locales/cli.json +24 -0
  31. package/src/rag/install.js +4 -0
  32. package/src/server.js +3 -1
  33. package/dist/assets/i18n-CohqPkkN.js.map +0 -1
  34. package/dist/assets/model-profiles-BS2LIjxf.js +0 -2
  35. package/dist/assets/model-profiles-BS2LIjxf.js.map +0 -1
  36. package/dist/assets/options-CE9-fjJV.css +0 -1
  37. package/dist/assets/session-store-DwXNnVF5.js +0 -100
  38. package/dist/assets/session-store-DwXNnVF5.js.map +0 -1
package/README.md CHANGED
@@ -2,15 +2,31 @@
2
2
 
3
3
  # AI Helper Agent
4
4
 
5
- AI Helper Agent — a local proxy service that provides the [AI Helper Chrome Extension](https://github.com/xiweicheng/ai-helper) ([Edge Add-ons](https://microsoftedge.microsoft.com/addons/detail/ai-helper-%E7%BD%91%E9%A1%B5%E6%99%BA%E8%83%BD%E5%8A%A9%E6%89%8B/kabhmgfbkhpbfhhnokaafhkdbckeipcl)) with local file read/write, system command execution, Skill system, and MCP protocol extension capabilities.
5
+ AI Helper Agent — a local proxy service that provides the [AI Helper Chrome Extension](https://github.com/xiweicheng/ai-helper) ([Edge Add-ons](https://microsoftedge.microsoft.com/addons/detail/ai-helper-%E7%BD%91%E9%A1%B5%E6%99%BA%E8%83%BD%E5%8A%A9%E6%89%8B/kabhmgfbkhpbfhhnokaafhkdbckeipcl)) with local file read/write, system command execution, Skill system, MCP protocol extension, and an optional local knowledge base (RAG) capability.
6
6
 
7
7
  ## Installation
8
8
 
9
+ ### One-click install (recommended)
10
+
11
+ Automatically detects network environment, downloads Node.js runtime, installs Agent, and configures auto-start — no Node.js knowledge required.
12
+
13
+ **macOS / Linux:**
14
+ ```bash
15
+ curl -fsSL https://raw.githubusercontent.com/xiweicheng/ai-helper/main/install.sh | bash
16
+ ```
17
+
18
+ **Windows (PowerShell):**
19
+ ```powershell
20
+ irm https://raw.githubusercontent.com/xiweicheng/ai-helper/main/install.ps1 | iex
21
+ ```
22
+
23
+ ### Manual install (npm)
24
+
9
25
  ```bash
10
26
  npm install -g ai-helper-agent
11
27
  ```
12
28
 
13
- Requires Node.js >= 18.0.0.
29
+ Requires Node.js >= 18.0.0 (>= 22.13.0 for Knowledge Base / RAG features).
14
30
 
15
31
  ## Quick Start
16
32
 
@@ -39,6 +55,10 @@ After startup, the terminal will display a 6-digit pairing code. Enter it in the
39
55
  | `status` | Check running status |
40
56
  | `paircode` | Show pairing code |
41
57
  | `config` | View current configuration |
58
+ | `rag status` / `rag install` | Check RAG dependency availability / one-click install |
59
+ | `update` | Check and update to latest version (`--check` for info only) |
60
+ | `uninstall` | One-click uninstall (keeps user data) |
61
+ | `autostart off` | Disable auto-start at boot |
42
62
  | `help` | Show help information |
43
63
  | `--version` / `-v` | Show version number |
44
64
 
@@ -75,6 +95,8 @@ The agent manages process lifecycle via a PID file (`~/.ai-helper-agent/agent.pi
75
95
  - `stop` command prefers graceful shutdown via API, falls back to killing process via PID file
76
96
  - Automatically cleans up PID file on normal shutdown
77
97
 
98
+ Command termination targets the **entire process tree** — grandchild processes spawned by `npm` etc. (download / build subtasks) are cleaned up together, so stopping a command (`/api/exec/stop`) or timing out never leaves orphan processes writing to disk; POSIX signals the process group, Windows uses `taskkill /T`.
99
+
78
100
  ## Security
79
101
 
80
102
  ### File Sandbox
@@ -361,12 +383,12 @@ Configuration file path: `~/.ai-helper-agent/config.json`
361
383
 
362
384
  ## Knowledge Base (RAG)
363
385
 
364
- Optional local retrieval-augmented generation. Turn documents into searchable knowledge bases so the extension can answer with cited sources. The RAG stack ships as optional dependencies — the agent detects availability at startup and reports it via `/api/rag/status`; when dependencies are missing, RAG requests return `503` and the extension offers one-click installation (whitelisted packages, progress polled from `/api/rag/install/status`).
386
+ Optional local retrieval-augmented generation. Turn documents into searchable knowledge bases so the extension can answer with cited sources. The RAG stack ships as optional dependencies — the agent detects availability at startup and reports it via `/api/rag/status`; when dependencies are missing, RAG requests return `503` and the extension offers one-click installation (whitelisted packages, progress polled from `/api/rag/install/status`). Installation is also available from the CLI: `ai-helper-agent rag status` / `ai-helper-agent rag install`. Users who have installed the dependencies successfully before get **automatic recovery on startup**: `npm -g` upgrades prune manually-installed packages inside the package directory, so the agent re-installs them automatically (marked `trigger=auto`) — no manual action needed; users who never installed successfully are not prompted.
365
387
 
366
388
  - **Data location** — knowledge bases are stored under `~/.ai-helper-agent/rag/` (override with the `AI_HELPER_RAG_ROOT` environment variable)
367
- - **Multiple knowledge bases** — create / update / delete collections, each keeping its own embedding config and statistics
389
+ - **Multiple knowledge bases** — create / update / delete / enable / disable collections, each keeping its own embedding config and statistics
368
390
  - **Multi-format ingestion** — `.txt` `.md` `.json` `.csv` `.html` / PDF / Word (`mammoth`) / PPT (`officeparser`) / Excel; ingest by raw text, file (base64), or URL, with staged parsing → chunking → embedding → storage progress
369
- - **Hybrid retrieval** — vector similarity with keyword-hit boosting; searching multiple bases splits the `topK` quota across them
391
+ - **Hybrid retrieval** — vector similarity with keyword-hit boosting (mixed Chinese/English keyword extraction); searching multiple bases splits the `topK` quota across them
370
392
  - **Pluggable embeddings** — local model (`Xenova/bge-small-zh-v1.5`, 512-dim, runs locally via `@huggingface/transformers`) by default, or any OpenAI-compatible embedding endpoint (with a connectivity test returning actual dimensions)
371
393
  - **Index rebuild** — changing a collection's embedding space rebuilds its index in the background (temporary-directory replay → atomic swap)
372
394
 
@@ -385,6 +407,7 @@ Endpoints are registered inside the authenticated region (Bearer token required)
385
407
  | POST | `/api/rag/collections` | Create a knowledge base |
386
408
  | PUT | `/api/rag/collections/{id}` | Update name / description / embedding config (rebuilds index on embedding-space change) |
387
409
  | DELETE | `/api/rag/collections/{id}` | Delete a knowledge base |
410
+ | POST | `/api/rag/collections/{id}/toggle` | Enable / disable a knowledge base |
388
411
  | GET | `/api/rag/collections/{id}/stats` | Document / chunk statistics |
389
412
  | POST | `/api/rag/collections/{id}/ingest` | Ingest text / file / URL (synchronous) |
390
413
  | GET | `/api/rag/collections/{id}/ingest/status` | Ingestion progress snapshot (for polling) |
package/README.zh-CN.md CHANGED
@@ -2,15 +2,31 @@
2
2
 
3
3
  # AI Helper Agent
4
4
 
5
- AI Helper 代理服务,为 [AI Helper Chrome 扩展](https://github.com/xiweicheng/ai-helper)([Edge 扩展商店](https://microsoftedge.microsoft.com/addons/detail/ai-helper-%E7%BD%91%E9%A1%B5%E6%99%BA%E8%83%BD%E5%8A%A9%E6%89%8B/kabhmgfbkhpbfhhnokaafhkdbckeipcl))提供本地文件读写、系统命令执行、Skill 技能系统和 MCP 协议扩展能力。
5
+ AI Helper 代理服务,为 [AI Helper Chrome 扩展](https://github.com/xiweicheng/ai-helper)([Edge 扩展商店](https://microsoftedge.microsoft.com/addons/detail/ai-helper-%E7%BD%91%E9%A1%B5%E6%99%BA%E8%83%BD%E5%8A%A9%E6%89%8B/kabhmgfbkhpbfhhnokaafhkdbckeipcl))提供本地文件读写、系统命令执行、Skill 技能系统、MCP 协议扩展与可选本地知识库(RAG)能力。
6
6
 
7
7
  ## 安装
8
8
 
9
+ ### 一键安装(推荐)
10
+
11
+ 自动检测网络环境、下载 Node.js 运行时、安装 Agent 并配置开机自启——无需任何 Node.js 知识。
12
+
13
+ **macOS / Linux:**
14
+ ```bash
15
+ curl -fsSL https://raw.githubusercontent.com/xiweicheng/ai-helper/main/install.sh | bash
16
+ ```
17
+
18
+ **Windows(PowerShell):**
19
+ ```powershell
20
+ irm https://raw.githubusercontent.com/xiweicheng/ai-helper/main/install.ps1 | iex
21
+ ```
22
+
23
+ ### 手动安装(npm)
24
+
9
25
  ```bash
10
26
  npm install -g ai-helper-agent
11
27
  ```
12
28
 
13
- 要求 Node.js >= 18.0.0。
29
+ 要求 Node.js >= 18.0.0(知识库/RAG 功能要求 >= 22.13.0)。
14
30
 
15
31
  ## 快速开始
16
32
 
@@ -39,6 +55,10 @@ ai-helper-agent start --workdir /path/to/your/project --port 18911
39
55
  | `status` | 查看运行状态 |
40
56
  | `paircode` | 查看配对码提示 |
41
57
  | `config` | 查看当前配置 |
58
+ | `rag status` / `rag install` | 检测 RAG 依赖可用性 / 一键安装 RAG 依赖 |
59
+ | `update` | 检查并更新到最新版本(`--check` 仅查看) |
60
+ | `uninstall` | 一键卸载(保留用户数据) |
61
+ | `autostart off` | 关闭开机自启 |
42
62
  | `help` | 显示帮助信息 |
43
63
  | `--version` / `-v` | 显示版本号 |
44
64
 
@@ -75,6 +95,8 @@ Agent 通过 PID 文件(`~/.ai-helper-agent/agent.pid`)管理进程生命周
75
95
  - `stop` 命令优先通过 API 优雅关闭,失败则通过 PID 文件 kill 进程
76
96
  - 正常关闭时自动清理 PID 文件
77
97
 
98
+ 命令终止按**整棵进程树**清理 —— `npm` 等派生出的孙进程(下载 / 编译子任务)一并终止,停止命令(`/api/exec/stop`)或超时终止后不会留下孤儿进程继续写磁盘;POSIX 对进程组发信号,Windows 使用 `taskkill /T`。
99
+
78
100
  ## 安全机制
79
101
 
80
102
  ### 文件沙箱
@@ -361,12 +383,12 @@ enabled: true
361
383
 
362
384
  ## 知识库(RAG)
363
385
 
364
- 可选的本地检索增强生成(RAG)能力:将文档索引为可检索的知识库,让插件回答时附带引用来源。RAG 依赖为可选安装 —— Agent 启动时自动检测可用性,并通过 `/api/rag/status` 对外暴露;依赖缺失时 RAG 请求返回 `503`,插件端提供一键安装(白名单依赖,进度可经 `/api/rag/install/status` 轮询)。
386
+ 可选的本地检索增强生成(RAG)能力:将文档索引为可检索的知识库,让插件回答时附带引用来源。RAG 依赖为可选安装 —— Agent 启动时自动检测可用性,并通过 `/api/rag/status` 对外暴露;依赖缺失时 RAG 请求返回 `503`,插件端提供一键安装(白名单依赖,进度可经 `/api/rag/install/status` 轮询)。也可通过 CLI 安装:`ai-helper-agent rag status` / `ai-helper-agent rag install`。曾成功安装过依赖的用户享受**启动自动恢复**:`npm -g` 更新代理会清理包目录内手动安装的依赖,Agent 启动检测到缺失时自动重新安装(标记 `trigger=auto`),用户零操作;从未安装成功过的用户不触发。
365
387
 
366
388
  - **数据位置** —— 知识库存储于 `~/.ai-helper-agent/rag/`(可用环境变量 `AI_HELPER_RAG_ROOT` 覆盖)
367
- - **多知识库管理** —— 创建 / 更新 / 删除知识库,各自维护向量配置与统计信息
389
+ - **多知识库管理** —— 创建 / 更新 / 删除 / 启用 / 停用知识库,各自维护向量配置与统计信息
368
390
  - **多格式导入** —— `.txt` `.md` `.json` `.csv` `.html` / PDF / Word(`mammoth`)/ PPT(`officeparser`)/ Excel;支持文本、文件(base64)、URL 三种导入方式,解析 → 分块 → 向量化 → 存储分阶段进度可查
369
- - **混合检索** —— 向量相似度 + 关键词命中抬分;跨库检索时 `topK` 配额按库均分
391
+ - **混合检索** —— 向量相似度 + 关键词命中抬分(中英文混合关键词提取);跨库检索时 `topK` 配额按库均分
370
392
  - **可插拔向量化** —— 默认本地模型(`Xenova/bge-small-zh-v1.5`,512 维,经 `@huggingface/transformers` 本地运行),也可接入任意 OpenAI 兼容向量服务(支持连通性测试并返回实际维度)
371
393
  - **索引重建** —— 知识库向量空间变更时后台自动重建(临时目录重放 → 原子换入)
372
394
 
@@ -385,6 +407,7 @@ enabled: true
385
407
  | POST | `/api/rag/collections` | 创建知识库 |
386
408
  | PUT | `/api/rag/collections/{id}` | 更新名称 / 描述 / 向量配置(向量空间变更自动重建索引) |
387
409
  | DELETE | `/api/rag/collections/{id}` | 删除知识库 |
410
+ | POST | `/api/rag/collections/{id}/toggle` | 启用 / 停用知识库 |
388
411
  | GET | `/api/rag/collections/{id}/stats` | 文档数 / 分块数统计 |
389
412
  | POST | `/api/rag/collections/{id}/ingest` | 导入文本 / 文件 / URL(同步执行) |
390
413
  | GET | `/api/rag/collections/{id}/ingest/status` | 导入进度快照(供轮询) |
package/bin/agent.js CHANGED
@@ -237,6 +237,9 @@ function printHelp() {
237
237
  console.log(t('cmdPaircode'));
238
238
  console.log(t('cmdConfig'));
239
239
  console.log(t('cmdRag'));
240
+ console.log(t('cmdUpdate'));
241
+ console.log(t('cmdUninstall'));
242
+ console.log(t('cmdAutostart'));
240
243
  console.log(t('cmdHelp'));
241
244
  console.log('');
242
245
  console.log(t('startupOptions'));
@@ -300,6 +303,9 @@ if (command === '--version' || command === '-v') {
300
303
  if (command === 'start') {
301
304
  const isBg = process.argv.includes('--background') || process.argv.includes('-b');
302
305
 
306
+ // 用户主动启动时清除 .stopped 标记(否则 autostart guard 会阻止启动)
307
+ try { const stopped = join(AGENT_DIR, '.stopped'); if (existsSync(stopped)) unlinkSync(stopped); } catch {}
308
+
303
309
  if (isBg) {
304
310
  ensureAgentDir();
305
311
 
@@ -677,6 +683,150 @@ if (command === 'start') {
677
683
  console.log(JSON.stringify(config, null, 2));
678
684
  console.log(`[Agent] ${t('configFileLocation', { path: CONFIG_FILE })}`);
679
685
 
686
+ // ==================== update ====================
687
+ } else if (command === 'update') {
688
+ const checkOnly = rawArgs.includes('--check');
689
+ const { getRegistryUrl, getNpmPath, isEmbedded, getAgentPackageRoot } = await import('../src/install-mode.js');
690
+ const { spawnSync } = await import('child_process');
691
+
692
+ const npmPath = getNpmPath();
693
+ const registry = getRegistryUrl();
694
+ const registryArg = registry ? [`--registry=${registry}`] : [];
695
+ const pkgRoot = getAgentPackageRoot();
696
+
697
+ // 当前版本
698
+ const pkgJson = JSON.parse(readFileSync(join(pkgRoot, 'package.json'), 'utf-8'));
699
+ const currentVersion = pkgJson.version;
700
+
701
+ // 查询最新版
702
+ const viewArgs = ['view', 'ai-helper-agent', 'version', ...registryArg];
703
+ const viewResult = spawnSync(npmPath, viewArgs, { encoding: 'utf-8', shell: process.platform === 'win32' });
704
+ const latestVersion = (viewResult.stdout || '').trim().split('\n').pop();
705
+
706
+ if (!latestVersion || latestVersion === currentVersion) {
707
+ console.log(`[Agent] ${t('updateLatest', { version: currentVersion })}`);
708
+ process.exit(0);
709
+ }
710
+
711
+ if (checkOnly) {
712
+ console.log(`[Agent] ${t('updateAvailable', { current: currentVersion, latest: latestVersion })}`);
713
+ process.exit(0);
714
+ }
715
+
716
+ console.log(`[Agent] ${t('updateInstalling', { current: currentVersion, latest: latestVersion })}`);
717
+
718
+ // 停止服务
719
+ const config = readAgentConfig();
720
+ if (await isRunning(config)) {
721
+ try { await fetch(`http://${config.host}:${config.port}/api/shutdown`, { method: 'POST' }); } catch {}
722
+ await waitForExit(config, 5000);
723
+ }
724
+
725
+ // 执行更新
726
+ let installArgs;
727
+ if (isEmbedded()) {
728
+ // 内嵌模式:更新到 app/ 目录
729
+ const appDir = join(AGENT_DIR, 'app');
730
+ installArgs = ['install', 'ai-helper-agent@latest', ...registryArg, '--no-audit', '--no-fund', '--prefix', appDir];
731
+ } else {
732
+ // npm -g 模式:全局更新
733
+ installArgs = ['install', '-g', 'ai-helper-agent@latest', ...registryArg, '--no-audit', '--no-fund'];
734
+ }
735
+
736
+ const installResult = spawnSync(npmPath, installArgs, { stdio: 'inherit', shell: process.platform === 'win32' });
737
+ if (installResult.status !== 0) {
738
+ console.error(`[Agent] ${t('updateFailed')}`);
739
+ process.exit(1);
740
+ }
741
+
742
+ // 重启
743
+ console.log(`[Agent] ${t('updateSuccess', { version: latestVersion })}`);
744
+ const agentScript = resolve(process.argv[1]);
745
+ spawn(process.execPath, [agentScript, 'start', '-b'], { detached: true, stdio: 'ignore', windowsHide: true }).unref();
746
+
747
+ // ==================== uninstall ====================
748
+ } else if (command === 'uninstall') {
749
+ const isWin = process.platform === 'win32';
750
+
751
+ // 停止服务
752
+ const config = readAgentConfig();
753
+ if (await isRunning(config)) {
754
+ try { await fetch(`http://${config.host}:${config.port}/api/shutdown`, { method: 'POST' }); } catch {}
755
+ await waitForExit(config, 5000);
756
+ }
757
+ const pid = getPidFromFile();
758
+ if (pid) { killByPid(pid); removePidFile(); }
759
+
760
+ // 移除自启
761
+ const { homedir } = await import('os');
762
+ if (!isWin) {
763
+ const plist = join(homedir(), 'Library', 'LaunchAgents', 'com.ai-helper.agent.plist');
764
+ if (existsSync(plist)) {
765
+ spawnSync('launchctl', ['unload', plist], { stdio: 'ignore' });
766
+ try { unlinkSync(plist); } catch {}
767
+ }
768
+ const service = join(homedir(), '.config', 'systemd', 'user', 'ai-helper-agent.service');
769
+ if (existsSync(service)) {
770
+ spawnSync('systemctl', ['--user', 'disable', 'ai-helper-agent'], { stdio: 'ignore' });
771
+ try { unlinkSync(service); } catch {}
772
+ }
773
+ } else {
774
+ spawnSync('schtasks', ['/Delete', '/TN', 'AIHelperAgent', '/F'], { windowsHide: true, stdio: 'ignore' });
775
+ }
776
+
777
+ console.log(`[Agent] ${t('uninstallAutostartRemoved')}`);
778
+
779
+ // 移除 runtime/ app/ bin/ (保留数据)
780
+ const { rmSync } = await import('fs');
781
+ const dirsToRemove = [join(AGENT_DIR, 'runtime'), join(AGENT_DIR, 'app'), join(AGENT_DIR, 'bin')];
782
+ for (const dir of dirsToRemove) {
783
+ try { rmSync(dir, { recursive: true, force: true }); } catch {}
784
+ }
785
+ try { unlinkSync(join(AGENT_DIR, 'INSTALL_MANIFEST.json')); } catch {}
786
+ try { unlinkSync(join(AGENT_DIR, 'mirrors.json')); } catch {}
787
+ try { unlinkSync(join(AGENT_DIR, '.stopped')); } catch {}
788
+
789
+ console.log(`[Agent] ${t('uninstallComplete', { dataDir: AGENT_DIR })}`);
790
+ process.exit(0);
791
+
792
+ // ==================== autostart ====================
793
+ } else if (command === 'autostart') {
794
+ const sub = rawArgs[1]; // 'on' | 'off'
795
+ const isWin = process.platform === 'win32';
796
+ const { homedir } = await import('os');
797
+
798
+ if (sub === 'off') {
799
+ if (!isWin && process.platform === 'darwin') {
800
+ const plist = join(homedir(), 'Library', 'LaunchAgents', 'com.ai-helper.agent.plist');
801
+ spawnSync('launchctl', ['unload', plist], { stdio: 'ignore' });
802
+ try { unlinkSync(plist); } catch {}
803
+ } else if (!isWin) {
804
+ spawnSync('systemctl', ['--user', 'disable', 'ai-helper-agent'], { stdio: 'ignore' });
805
+ const service = join(homedir(), '.config', 'systemd', 'user', 'ai-helper-agent.service');
806
+ try { unlinkSync(service); } catch {}
807
+ } else {
808
+ spawnSync('schtasks', ['/Delete', '/TN', 'AIHelperAgent', '/F'], { windowsHide: true, stdio: 'ignore' });
809
+ }
810
+ console.log(`[Agent] ${t('autostartDisabled')}`);
811
+ } else {
812
+ console.log(`[Agent] ${t('autostartUseScript')}`);
813
+ }
814
+ process.exit(0);
815
+
816
+ // ==================== _autostart-guard (internal, autostart wrapper) ====================
817
+ } else if (command === '_autostart-guard') {
818
+ // 检查 .stopped 标记:用户主动停止后不自启
819
+ const stoppedFile = join(AGENT_DIR, '.stopped');
820
+ if (existsSync(stoppedFile)) {
821
+ process.exit(0);
822
+ }
823
+ // 正常启动
824
+ const agentScript = resolve(process.argv[1]);
825
+ spawn(process.execPath, [agentScript, 'start', '-b'], {
826
+ detached: true, stdio: 'ignore', windowsHide: true
827
+ }).unref();
828
+ process.exit(0);
829
+
680
830
  // ==================== rag ====================
681
831
  } else if (command === 'rag') {
682
832
  // 子命令:status(检测能力)/ install(一键安装 RAG 依赖)
@@ -1,2 +1,2 @@
1
- import{r as e}from"./rolldown-runtime-C0FnF6B9.js";import{a as t,c as n}from"./i18n-CohqPkkN.js";import{_ as r,g as i}from"./session-store-DwXNnVF5.js";var a=e({createAgent:()=>m,deleteAgent:()=>g,getActiveAgentId:()=>_,getAgent:()=>p,getAllAgents:()=>d,getCustomAgents:()=>f,setActiveAgentId:()=>v,updateAgent:()=>h});t(`zh`,{agentStore:{unnamedAgent:`未命名Agent`}}),t(`en`,{agentStore:{unnamedAgent:`Unnamed Agent`}});var o=`customAgents`,s=`activeAssistantId`,c=`activeAgentId`,l=!1;async function u(){if(l)return;l=!0;let e=await chrome.storage.local.get([c,s]),t=e[c],n=e[s];t&&!n&&!t.startsWith(`pa_`)&&(await chrome.storage.local.set({[s]:t}),await chrome.storage.local.remove(c))}async function d(){let e=(await chrome.storage.local.get([o]))[o]||[];return[...i,...e]}async function f(){return(await chrome.storage.local.get([o]))[o]||[]}async function p(e){return e&&(await d()).find(t=>t.id===e)||null}async function m(e){let t=await f(),i={id:r(),name:e.name||n(`agentStore.unnamedAgent`),description:e.description||``,icon:e.icon||`🤖`,systemPrompt:e.systemPrompt||``,toolIds:e.toolIds||null,skillIds:e.skillIds||null,mcpExcludedServerIds:e.mcpExcludedServerIds??null,isBuiltin:!1,allowSubDispatch:e.allowSubDispatch!==void 0&&e.allowSubDispatch,model:e.model||null,temperature:e.temperature===void 0?null:e.temperature,topP:e.topP===void 0?null:e.topP,createdAt:new Date().toISOString(),updatedAt:new Date().toISOString()};return t.push(i),await chrome.storage.local.set({[o]:t}),i}async function h(e,t){let n=await f(),r=n.findIndex(t=>t.id===e);return r===-1?null:(n[r]={...n[r],...t,id:e,isBuiltin:!1,updatedAt:new Date().toISOString()},await chrome.storage.local.set({[o]:n}),n[r])}async function g(e){let t=await f(),n=t.findIndex(t=>t.id===e);return n!==-1&&(t.splice(n,1),await chrome.storage.local.set({[o]:t}),(await chrome.storage.local.get([s]))[s]===e&&await chrome.storage.local.remove(s),!0)}async function _(){return await u(),(await chrome.storage.local.get([s]))[s]||null}async function v(e){e?await chrome.storage.local.set({[s]:e}):await chrome.storage.local.remove(s)}export{p as a,h as c,_ as i,m as n,d as o,g as r,v as s,a as t};
2
- //# sourceMappingURL=agent-store-BFaBECYz.js.map
1
+ import{r as e}from"./rolldown-runtime-C0FnF6B9.js";import{a as t,c as n}from"./i18n-MmYITlVj.js";import{_ as r,g as i}from"./session-store-B0ZPGm7d.js";var a=e({createAgent:()=>m,deleteAgent:()=>g,getActiveAgentId:()=>_,getAgent:()=>p,getAllAgents:()=>d,getCustomAgents:()=>f,setActiveAgentId:()=>v,updateAgent:()=>h});t(`zh`,{agentStore:{unnamedAgent:`未命名Agent`}}),t(`en`,{agentStore:{unnamedAgent:`Unnamed Agent`}});var o=`customAgents`,s=`activeAssistantId`,c=`activeAgentId`,l=!1;async function u(){if(l)return;l=!0;let e=await chrome.storage.local.get([c,s]),t=e[c],n=e[s];t&&!n&&!t.startsWith(`pa_`)&&(await chrome.storage.local.set({[s]:t}),await chrome.storage.local.remove(c))}async function d(){let e=(await chrome.storage.local.get([o]))[o]||[];return[...i,...e]}async function f(){return(await chrome.storage.local.get([o]))[o]||[]}async function p(e){return e&&(await d()).find(t=>t.id===e)||null}async function m(e){let t=await f(),i={id:r(),name:e.name||n(`agentStore.unnamedAgent`),description:e.description||``,icon:e.icon||`🤖`,systemPrompt:e.systemPrompt||``,toolIds:e.toolIds||null,skillIds:e.skillIds||null,mcpExcludedServerIds:e.mcpExcludedServerIds??null,isBuiltin:!1,allowSubDispatch:e.allowSubDispatch!==void 0&&e.allowSubDispatch,model:e.model||null,temperature:e.temperature===void 0?null:e.temperature,topP:e.topP===void 0?null:e.topP,createdAt:new Date().toISOString(),updatedAt:new Date().toISOString()};return t.push(i),await chrome.storage.local.set({[o]:t}),i}async function h(e,t){let n=await f(),r=n.findIndex(t=>t.id===e);return r===-1?null:(n[r]={...n[r],...t,id:e,isBuiltin:!1,updatedAt:new Date().toISOString()},await chrome.storage.local.set({[o]:n}),n[r])}async function g(e){let t=await f(),n=t.findIndex(t=>t.id===e);return n!==-1&&(t.splice(n,1),await chrome.storage.local.set({[o]:t}),(await chrome.storage.local.get([s]))[s]===e&&await chrome.storage.local.remove(s),!0)}async function _(){return await u(),(await chrome.storage.local.get([s]))[s]||null}async function v(e){e?await chrome.storage.local.set({[s]:e}):await chrome.storage.local.remove(s)}export{p as a,h as c,_ as i,m as n,d as o,g as r,v as s,a as t};
2
+ //# sourceMappingURL=agent-store-DOyMdB_7.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"agent-store-BFaBECYz.js","names":[],"sources":["../../src/side_panel/agent-store.js"],"sourcesContent":["// side_panel/agent-store.js - Agent 数据持久化\nimport { BUILTIN_AGENTS, generateAgentId } from '../shared/agent-defaults.js';\nimport { t, registerTranslations } from '../shared/i18n.js';\n\nregisterTranslations('zh', {\n agentStore: {\n unnamedAgent: '未命名Agent',\n },\n});\nregisterTranslations('en', {\n agentStore: {\n unnamedAgent: 'Unnamed Agent',\n },\n});\n\nconst STORAGE_KEY = 'customAgents';\nconst ACTIVE_KEY = 'activeAssistantId';\nconst LEGACY_ACTIVE_KEY = 'activeAgentId';\n\nlet migratedActiveKey = false;\n\nasync function migrateLegacyActiveKey() {\n if (migratedActiveKey) return;\n migratedActiveKey = true;\n\n const result = await chrome.storage.local.get([LEGACY_ACTIVE_KEY, ACTIVE_KEY]);\n const legacyValue = result[LEGACY_ACTIVE_KEY];\n const newValue = result[ACTIVE_KEY];\n\n if (legacyValue && !newValue && !legacyValue.startsWith('pa_')) {\n await chrome.storage.local.set({ [ACTIVE_KEY]: legacyValue });\n await chrome.storage.local.remove(LEGACY_ACTIVE_KEY);\n }\n}\n\n/**\n * 获取所有 Agent(内置 + 用户自定义)\n * @returns {Promise<Array>}\n */\nexport async function getAllAgents() {\n const result = await chrome.storage.local.get([STORAGE_KEY]);\n const customAgents = result[STORAGE_KEY] || [];\n return [...BUILTIN_AGENTS, ...customAgents];\n}\n\n/**\n * 仅获取用户自定义的 Agent\n * @returns {Promise<Array>}\n */\nexport async function getCustomAgents() {\n const result = await chrome.storage.local.get([STORAGE_KEY]);\n return result[STORAGE_KEY] || [];\n}\n\n/**\n * 根据 ID 获取单个 Agent\n * @param {string} agentId\n * @returns {Promise<Object|null>}\n */\nexport async function getAgent(agentId) {\n if (!agentId) return null;\n const all = await getAllAgents();\n return all.find(a => a.id === agentId) || null;\n}\n\n/**\n * 创建新的自定义 Agent\n * @param {Object} agentData - 不含 id 的 Agent 数据\n * @returns {Promise<Object>}\n */\nexport async function createAgent(agentData) {\n const agents = await getCustomAgents();\n const newAgent = {\n id: generateAgentId(),\n name: agentData.name || t('agentStore.unnamedAgent'),\n description: agentData.description || '',\n icon: agentData.icon || '🤖',\n systemPrompt: agentData.systemPrompt || '',\n toolIds: agentData.toolIds || null, // null = 继承全局\n skillIds: agentData.skillIds || null, // null = 继承全部启用技能\n mcpExcludedServerIds: agentData.mcpExcludedServerIds ?? null, // MCP 服务排除列表(服务级 deny-list)\n isBuiltin: false,\n allowSubDispatch: agentData.allowSubDispatch !== undefined ? agentData.allowSubDispatch : false,\n model: agentData.model || null,\n temperature: agentData.temperature !== undefined ? agentData.temperature : null,\n topP: agentData.topP !== undefined ? agentData.topP : null,\n createdAt: new Date().toISOString(),\n updatedAt: new Date().toISOString(),\n };\n agents.push(newAgent);\n await chrome.storage.local.set({ [STORAGE_KEY]: agents });\n return newAgent;\n}\n\n/**\n * 更新已有的自定义 Agent\n * @param {string} agentId\n * @param {Object} updates\n * @returns {Promise<Object|null>}\n */\nexport async function updateAgent(agentId, updates) {\n const agents = await getCustomAgents();\n const idx = agents.findIndex(a => a.id === agentId);\n if (idx === -1) return null;\n \n agents[idx] = {\n ...agents[idx],\n ...updates,\n id: agentId, // id 不可变\n isBuiltin: false, // 不可变\n updatedAt: new Date().toISOString(),\n };\n await chrome.storage.local.set({ [STORAGE_KEY]: agents });\n return agents[idx];\n}\n\n/**\n * 删除自定义 Agent\n * @param {string} agentId\n * @returns {Promise<boolean>}\n */\nexport async function deleteAgent(agentId) {\n const agents = await getCustomAgents();\n const idx = agents.findIndex(a => a.id === agentId);\n if (idx === -1) return false;\n \n agents.splice(idx, 1);\n await chrome.storage.local.set({ [STORAGE_KEY]: agents });\n\n // 如果删除的 Agent 是当前选中的,重置为默认\n const result = await chrome.storage.local.get([ACTIVE_KEY]);\n if (result[ACTIVE_KEY] === agentId) {\n await chrome.storage.local.remove(ACTIVE_KEY);\n }\n \n return true;\n}\n\n/**\n * 获取当前选中的 Agent ID\n * @returns {Promise<string|null>}\n */\nexport async function getActiveAgentId() {\n await migrateLegacyActiveKey();\n const result = await chrome.storage.local.get([ACTIVE_KEY]);\n return result[ACTIVE_KEY] || null;\n}\n\n/**\n * 设置当前选中的 Agent ID\n * @param {string|null} agentId\n */\nexport async function setActiveAgentId(agentId) {\n if (agentId) {\n await chrome.storage.local.set({ [ACTIVE_KEY]: agentId });\n } else {\n await chrome.storage.local.remove(ACTIVE_KEY);\n }\n}\n\n/**\n * 从模板创建 Agent\n * @param {Object} template\n * @returns {Promise<Object>}\n */\nexport async function createAgentFromTemplate(template) {\n return createAgent({\n name: template.name,\n icon: template.icon,\n description: template.description,\n systemPrompt: template.systemPrompt,\n toolIds: template.toolIds ? [...template.toolIds] : null,\n allowSubDispatch: template.allowSubDispatch || false,\n });\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"agent-store-DOyMdB_7.js","names":[],"sources":["../../src/side_panel/agent-store.js"],"sourcesContent":["// side_panel/agent-store.js - Agent 数据持久化\nimport { BUILTIN_AGENTS, generateAgentId } from '../shared/agent-defaults.js';\nimport { t, registerTranslations } from '../shared/i18n.js';\n\nregisterTranslations('zh', {\n agentStore: {\n unnamedAgent: '未命名Agent',\n },\n});\nregisterTranslations('en', {\n agentStore: {\n unnamedAgent: 'Unnamed Agent',\n },\n});\n\nconst STORAGE_KEY = 'customAgents';\nconst ACTIVE_KEY = 'activeAssistantId';\nconst LEGACY_ACTIVE_KEY = 'activeAgentId';\n\nlet migratedActiveKey = false;\n\nasync function migrateLegacyActiveKey() {\n if (migratedActiveKey) return;\n migratedActiveKey = true;\n\n const result = await chrome.storage.local.get([LEGACY_ACTIVE_KEY, ACTIVE_KEY]);\n const legacyValue = result[LEGACY_ACTIVE_KEY];\n const newValue = result[ACTIVE_KEY];\n\n if (legacyValue && !newValue && !legacyValue.startsWith('pa_')) {\n await chrome.storage.local.set({ [ACTIVE_KEY]: legacyValue });\n await chrome.storage.local.remove(LEGACY_ACTIVE_KEY);\n }\n}\n\n/**\n * 获取所有 Agent(内置 + 用户自定义)\n * @returns {Promise<Array>}\n */\nexport async function getAllAgents() {\n const result = await chrome.storage.local.get([STORAGE_KEY]);\n const customAgents = result[STORAGE_KEY] || [];\n return [...BUILTIN_AGENTS, ...customAgents];\n}\n\n/**\n * 仅获取用户自定义的 Agent\n * @returns {Promise<Array>}\n */\nexport async function getCustomAgents() {\n const result = await chrome.storage.local.get([STORAGE_KEY]);\n return result[STORAGE_KEY] || [];\n}\n\n/**\n * 根据 ID 获取单个 Agent\n * @param {string} agentId\n * @returns {Promise<Object|null>}\n */\nexport async function getAgent(agentId) {\n if (!agentId) return null;\n const all = await getAllAgents();\n return all.find(a => a.id === agentId) || null;\n}\n\n/**\n * 创建新的自定义 Agent\n * @param {Object} agentData - 不含 id 的 Agent 数据\n * @returns {Promise<Object>}\n */\nexport async function createAgent(agentData) {\n const agents = await getCustomAgents();\n const newAgent = {\n id: generateAgentId(),\n name: agentData.name || t('agentStore.unnamedAgent'),\n description: agentData.description || '',\n icon: agentData.icon || '🤖',\n systemPrompt: agentData.systemPrompt || '',\n toolIds: agentData.toolIds || null, // null = 继承全局\n skillIds: agentData.skillIds || null, // null = 继承全部启用技能\n mcpExcludedServerIds: agentData.mcpExcludedServerIds ?? null, // MCP 服务排除列表(服务级 deny-list)\n isBuiltin: false,\n allowSubDispatch: agentData.allowSubDispatch !== undefined ? agentData.allowSubDispatch : false,\n model: agentData.model || null,\n temperature: agentData.temperature !== undefined ? agentData.temperature : null,\n topP: agentData.topP !== undefined ? agentData.topP : null,\n createdAt: new Date().toISOString(),\n updatedAt: new Date().toISOString(),\n };\n agents.push(newAgent);\n await chrome.storage.local.set({ [STORAGE_KEY]: agents });\n return newAgent;\n}\n\n/**\n * 更新已有的自定义 Agent\n * @param {string} agentId\n * @param {Object} updates\n * @returns {Promise<Object|null>}\n */\nexport async function updateAgent(agentId, updates) {\n const agents = await getCustomAgents();\n const idx = agents.findIndex(a => a.id === agentId);\n if (idx === -1) return null;\n \n agents[idx] = {\n ...agents[idx],\n ...updates,\n id: agentId, // id 不可变\n isBuiltin: false, // 不可变\n updatedAt: new Date().toISOString(),\n };\n await chrome.storage.local.set({ [STORAGE_KEY]: agents });\n return agents[idx];\n}\n\n/**\n * 删除自定义 Agent\n * @param {string} agentId\n * @returns {Promise<boolean>}\n */\nexport async function deleteAgent(agentId) {\n const agents = await getCustomAgents();\n const idx = agents.findIndex(a => a.id === agentId);\n if (idx === -1) return false;\n \n agents.splice(idx, 1);\n await chrome.storage.local.set({ [STORAGE_KEY]: agents });\n\n // 如果删除的 Agent 是当前选中的,重置为默认\n const result = await chrome.storage.local.get([ACTIVE_KEY]);\n if (result[ACTIVE_KEY] === agentId) {\n await chrome.storage.local.remove(ACTIVE_KEY);\n }\n \n return true;\n}\n\n/**\n * 获取当前选中的 Agent ID\n * @returns {Promise<string|null>}\n */\nexport async function getActiveAgentId() {\n await migrateLegacyActiveKey();\n const result = await chrome.storage.local.get([ACTIVE_KEY]);\n return result[ACTIVE_KEY] || null;\n}\n\n/**\n * 设置当前选中的 Agent ID\n * @param {string|null} agentId\n */\nexport async function setActiveAgentId(agentId) {\n if (agentId) {\n await chrome.storage.local.set({ [ACTIVE_KEY]: agentId });\n } else {\n await chrome.storage.local.remove(ACTIVE_KEY);\n }\n}\n\n/**\n * 从模板创建 Agent\n * @param {Object} template\n * @returns {Promise<Object>}\n */\nexport async function createAgentFromTemplate(template) {\n return createAgent({\n name: template.name,\n icon: template.icon,\n description: template.description,\n systemPrompt: template.systemPrompt,\n toolIds: template.toolIds ? [...template.toolIds] : null,\n allowSubDispatch: template.allowSubDispatch || false,\n });\n}\n"],"mappings":"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"}