ai-helper-agent 2.1.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 (33) hide show
  1. package/README.md +20 -1
  2. package/README.zh-CN.md +20 -1
  3. package/bin/agent.js +150 -0
  4. package/dist/assets/{agent-store-C4hZkQT5.js → agent-store-DOyMdB_7.js} +2 -2
  5. package/dist/assets/{agent-store-C4hZkQT5.js.map → agent-store-DOyMdB_7.js.map} +1 -1
  6. package/dist/assets/background.js +84 -85
  7. package/dist/assets/background.js.map +1 -1
  8. package/dist/assets/content.js +80 -78
  9. package/dist/assets/{i18n-CAh-vB_T.js → i18n-MmYITlVj.js} +5 -5
  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.js +56 -56
  14. package/dist/assets/options.js.map +1 -1
  15. package/dist/assets/page-snapshot-renderer-CE53ibi-.js +4 -0
  16. package/dist/assets/page-snapshot-renderer-CE53ibi-.js.map +1 -0
  17. package/dist/assets/{session-store-uZ_LNasH.js → session-store-B0ZPGm7d.js} +4 -4
  18. package/dist/assets/{session-store-uZ_LNasH.js.map → session-store-B0ZPGm7d.js.map} +1 -1
  19. package/dist/assets/side_panel.css +1 -1
  20. package/dist/assets/side_panel.js +177 -171
  21. package/dist/assets/side_panel.js.map +1 -1
  22. package/dist/manifest.json +6 -3
  23. package/dist/offscreen/offscreen.js +6 -6
  24. package/dist/options.html +2 -11
  25. package/dist/side_panel.html +6 -6
  26. package/package.json +1 -1
  27. package/src/install-mode.js +128 -0
  28. package/src/locales/cli.json +24 -0
  29. package/src/rag/install.js +4 -0
  30. package/src/server.js +3 -1
  31. package/dist/assets/i18n-CAh-vB_T.js.map +0 -1
  32. package/dist/assets/model-profiles-CGxULM3O.js +0 -25
  33. package/dist/assets/model-profiles-CGxULM3O.js.map +0 -1
package/README.md CHANGED
@@ -6,11 +6,27 @@ AI Helper Agent — a local proxy service that provides the [AI Helper Chrome Ex
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
 
@@ -40,6 +56,9 @@ After startup, the terminal will display a 6-digit pairing code. Enter it in the
40
56
  | `paircode` | Show pairing code |
41
57
  | `config` | View current configuration |
42
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 |
43
62
  | `help` | Show help information |
44
63
  | `--version` / `-v` | Show version number |
45
64
 
package/README.zh-CN.md CHANGED
@@ -6,11 +6,27 @@ AI Helper 代理服务,为 [AI Helper Chrome 扩展](https://github.com/xiweic
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
 
@@ -40,6 +56,9 @@ ai-helper-agent start --workdir /path/to/your/project --port 18911
40
56
  | `paircode` | 查看配对码提示 |
41
57
  | `config` | 查看当前配置 |
42
58
  | `rag status` / `rag install` | 检测 RAG 依赖可用性 / 一键安装 RAG 依赖 |
59
+ | `update` | 检查并更新到最新版本(`--check` 仅查看) |
60
+ | `uninstall` | 一键卸载(保留用户数据) |
61
+ | `autostart off` | 关闭开机自启 |
43
62
  | `help` | 显示帮助信息 |
44
63
  | `--version` / `-v` | 显示版本号 |
45
64
 
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-CAh-vB_T.js";import{_ as r,g as i}from"./session-store-uZ_LNasH.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-C4hZkQT5.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-C4hZkQT5.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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"}