feat: 增加共享 Agent Browser 调试能力
需求:在 AI 编程会话中让用户与 Agent 共享同一浏览器页面,并查看控制台与网络信息。 实现:新增沙箱浏览器内核、Host API/渲染器面板、OpenCode 工具接入及安全边界测试。
This commit is contained in:
@@ -15,6 +15,7 @@ import { afterEach, describe, expect, it, vi } from 'vitest';
|
||||
import { OpencodeManager } from '@electron/opencode/manager';
|
||||
import {
|
||||
ensureBundledSuperpowersPlugin,
|
||||
resolveBundledAgentBrowserPluginPath,
|
||||
resolveBundledSuperpowersDir,
|
||||
} from '@electron/opencode/superpowers';
|
||||
import { logger } from '@electron/utils/logger';
|
||||
@@ -82,6 +83,23 @@ describe('OpencodeManager', () => {
|
||||
})).toBe(join(resourcesPath, 'resources', 'skills', 'superpowers'));
|
||||
});
|
||||
|
||||
it('resolves the bundled Agent Browser plugin from the course skills bundle', () => {
|
||||
const resourcesPath = 'C:\\Program Files\\Makelore\\resources';
|
||||
|
||||
expect(resolveBundledAgentBrowserPluginPath({
|
||||
isPackaged: true,
|
||||
resourcesPath,
|
||||
appPath: 'C:\\Program Files\\Makelore\\resources\\app.asar',
|
||||
})).toBe(join(
|
||||
resourcesPath,
|
||||
'course-skills',
|
||||
'agent-browser',
|
||||
'.opencode',
|
||||
'plugins',
|
||||
'niancode-agent-browser.js',
|
||||
));
|
||||
});
|
||||
|
||||
it('spawns the bundled opencode server and becomes running after listening output', async () => {
|
||||
const { children, calls, spawn } = createSpawnHarness();
|
||||
const manager = new OpencodeManager({
|
||||
@@ -858,6 +876,50 @@ describe('OpencodeManager', () => {
|
||||
}
|
||||
});
|
||||
|
||||
it('installs the bundled Agent Browser tool plugin before spawning', async () => {
|
||||
const userDataDir = mkdtempSync(join(tmpdir(), 'niancode-opencode-manager-'));
|
||||
const sourceDir = mkdtempSync(join(tmpdir(), 'niancode-agent-browser-plugin-source-'));
|
||||
const sourcePluginPath = join(sourceDir, 'niancode-agent-browser.js');
|
||||
try {
|
||||
writeFileSync(
|
||||
sourcePluginPath,
|
||||
'export const NianCodeAgentBrowserPlugin = async () => ({});\n',
|
||||
);
|
||||
|
||||
const { children, spawn } = createSpawnHarness();
|
||||
const manager = new OpencodeManager({
|
||||
port: 4337,
|
||||
binPath: '/opt/opencode',
|
||||
userDataDir,
|
||||
bundledAgentBrowserPluginPath: sourcePluginPath,
|
||||
runtimeConfigProvider: () => ({ config: {}, env: {} }),
|
||||
spawn,
|
||||
});
|
||||
|
||||
const startPromise = manager.start();
|
||||
children[0].stdout.emit(
|
||||
'data',
|
||||
Buffer.from('opencode server listening on http://127.0.0.1:4337\n'),
|
||||
);
|
||||
await startPromise;
|
||||
|
||||
const installedPluginPath = join(
|
||||
userDataDir,
|
||||
'opencode',
|
||||
'niancode-config',
|
||||
'plugins',
|
||||
'niancode-agent-browser.js',
|
||||
);
|
||||
expect(existsSync(installedPluginPath)).toBe(true);
|
||||
expect(readFileSync(installedPluginPath, 'utf8')).toContain(
|
||||
'NianCodeAgentBrowserPlugin',
|
||||
);
|
||||
} finally {
|
||||
rmSync(userDataDir, { recursive: true, force: true });
|
||||
rmSync(sourceDir, { recursive: true, force: true });
|
||||
}
|
||||
});
|
||||
|
||||
it('removes retired bundled skills from the managed config before spawning', async () => {
|
||||
const userDataDir = mkdtempSync(join(tmpdir(), 'niancode-opencode-manager-'));
|
||||
const bundledCourseSkillsDir = mkdtempSync(join(tmpdir(), 'niancode-course-skills-source-'));
|
||||
|
||||
Reference in New Issue
Block a user