99 lines
3.5 KiB
TypeScript
99 lines
3.5 KiB
TypeScript
import { mkdtemp, readFile, rm } from 'node:fs/promises';
|
|
import { join } from 'node:path';
|
|
import { tmpdir } from 'node:os';
|
|
import { describe, expect, it } from 'vitest';
|
|
import { createRuntimeSubagent, updateRuntimeSubagent } from '@electron/opencode/agent-writer';
|
|
|
|
describe('agent writer', () => {
|
|
it('creates a built-in game-dev runtime subagent from the bundled markdown template', async () => {
|
|
const projectPath = await mkdtemp(join(tmpdir(), 'niancode-agent-writer-'));
|
|
|
|
try {
|
|
const subagent = await createRuntimeSubagent({
|
|
projectPath,
|
|
displayName: '小游戏开发伙伴',
|
|
templateRoleId: 'game-dev',
|
|
});
|
|
|
|
const markdown = await readFile(subagent.filePath, 'utf8');
|
|
|
|
expect(subagent.id).toMatch(/^nitu-game-dev-/);
|
|
expect(subagent.templateRoleId).toBe('game-dev');
|
|
expect(subagent.skillIds).toEqual([
|
|
'youth-plain-language',
|
|
'dev-build-test',
|
|
'ui-ux-course-quality',
|
|
]);
|
|
expect(markdown).toContain('GDD.md');
|
|
expect(markdown).toContain('聊天总结不能代替项目文件');
|
|
expect(markdown).not.toContain('selectionStatus');
|
|
expect(markdown).toContain('Phaser');
|
|
expect(markdown).not.toContain('把起步模板小游戏直接当成目标作品');
|
|
} finally {
|
|
await rm(projectPath, { recursive: true, force: true });
|
|
}
|
|
});
|
|
|
|
it('creates a built-in game-showcase runtime subagent from the bundled markdown template', async () => {
|
|
const projectPath = await mkdtemp(join(tmpdir(), 'niancode-agent-writer-'));
|
|
|
|
try {
|
|
const subagent = await createRuntimeSubagent({
|
|
projectPath,
|
|
displayName: '宣传展示伙伴',
|
|
templateRoleId: 'game-showcase',
|
|
});
|
|
|
|
const markdown = await readFile(subagent.filePath, 'utf8');
|
|
|
|
expect(subagent.id).toMatch(/^nitu-game-showcase-/);
|
|
expect(subagent.templateRoleId).toBe('game-showcase');
|
|
expect(subagent.skillIds).toEqual([
|
|
'youth-plain-language',
|
|
'marketing-launch-story',
|
|
'ui-ux-course-quality',
|
|
]);
|
|
expect(markdown).toContain('SHOWCASE_PACKAGE.md');
|
|
expect(markdown).toContain('宣传展示');
|
|
} finally {
|
|
await rm(projectPath, { recursive: true, force: true });
|
|
}
|
|
});
|
|
|
|
it('keeps template-required skills when creating and updating a runtime subagent', async () => {
|
|
const projectPath = await mkdtemp(join(tmpdir(), 'niancode-agent-writer-required-'));
|
|
|
|
try {
|
|
const created = await createRuntimeSubagent({
|
|
projectPath,
|
|
displayName: '结对开发伙伴',
|
|
templateRoleId: 'game-dev',
|
|
requiredSkillIds: ['nianxxgame-skill'],
|
|
});
|
|
expect(created.skillIds).toEqual([
|
|
'youth-plain-language',
|
|
'dev-build-test',
|
|
'ui-ux-course-quality',
|
|
'nianxxgame-skill',
|
|
]);
|
|
|
|
const updated = await updateRuntimeSubagent({
|
|
projectPath,
|
|
agentId: created.id,
|
|
displayName: created.displayName,
|
|
templateRoleId: 'game-dev',
|
|
skillIds: ['dev-build-test'],
|
|
requiredSkillIds: ['nianxxgame-skill'],
|
|
});
|
|
const markdown = await readFile(updated.filePath, 'utf8');
|
|
|
|
expect(updated.skillIds).toEqual(['dev-build-test', 'nianxxgame-skill', 'youth-plain-language']);
|
|
expect(markdown).toContain('nianxxgame-skill: allow');
|
|
expect(markdown).toContain('youth-plain-language: allow');
|
|
expect(markdown).not.toContain('youth-ai-product-course: allow');
|
|
} finally {
|
|
await rm(projectPath, { recursive: true, force: true });
|
|
}
|
|
});
|
|
});
|