display-name.test.ts 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. import { describe, expect, test } from 'bun:test';
  2. import type { PluginConfig } from '../config';
  3. import { createAgents, getAgentConfigs } from './index';
  4. describe('displayName', () => {
  5. test('stores displayName on agent when configured', () => {
  6. const config: PluginConfig = {
  7. agents: {
  8. explorer: { displayName: 'researcher' },
  9. },
  10. };
  11. const agents = createAgents(config);
  12. const explorer = agents.find((a) => a.name === 'explorer');
  13. expect(explorer?.displayName).toBe('researcher');
  14. const sdkConfigs = getAgentConfigs(config);
  15. expect((sdkConfigs.explorer as { displayName?: string }).displayName).toBe(
  16. 'researcher',
  17. );
  18. });
  19. test('injects configured displayName into orchestrator prompt mentions', () => {
  20. const config: PluginConfig = {
  21. agents: {
  22. explorer: { displayName: 'researcher' },
  23. },
  24. };
  25. const agents = createAgents(config);
  26. const orchestrator = agents.find((a) => a.name === 'orchestrator');
  27. const prompt = orchestrator?.config.prompt ?? '';
  28. expect(prompt).toContain('@researcher');
  29. expect(prompt).not.toMatch(/@explorer\b/);
  30. });
  31. test('normalizes @-prefixed displayName in prompt injection', () => {
  32. const config: PluginConfig = {
  33. agents: {
  34. explorer: { displayName: '@researcher' },
  35. },
  36. };
  37. const agents = createAgents(config);
  38. const orchestrator = agents.find((a) => a.name === 'orchestrator');
  39. const prompt = orchestrator?.config.prompt ?? '';
  40. expect(prompt).toContain('@researcher');
  41. expect(prompt).not.toContain('@@researcher');
  42. expect(prompt).not.toMatch(/@explorer\b/);
  43. });
  44. test('normalizes whitespace-padded displayName in prompt injection', () => {
  45. const config: PluginConfig = {
  46. agents: {
  47. explorer: { displayName: ' researcher ' },
  48. },
  49. };
  50. const agents = createAgents(config);
  51. const orchestrator = agents.find((a) => a.name === 'orchestrator');
  52. const prompt = orchestrator?.config.prompt ?? '';
  53. expect(prompt).toContain('@researcher');
  54. expect(prompt).not.toContain('@ researcher ');
  55. expect(prompt).not.toMatch(/@explorer\b/);
  56. });
  57. test('throws when duplicate displayName is assigned', () => {
  58. const config: PluginConfig = {
  59. agents: {
  60. explorer: { displayName: 'helper' },
  61. librarian: { displayName: 'helper' },
  62. },
  63. };
  64. expect(() => createAgents(config)).toThrow(
  65. "Duplicate displayName 'helper' assigned to multiple agents",
  66. );
  67. });
  68. test('throws when normalized duplicate displayName is assigned', () => {
  69. const config: PluginConfig = {
  70. agents: {
  71. explorer: { displayName: 'advisor' },
  72. librarian: { displayName: ' @advisor ' },
  73. },
  74. };
  75. expect(() => createAgents(config)).toThrow(
  76. "Duplicate displayName 'advisor' assigned to multiple agents",
  77. );
  78. });
  79. test('throws when displayName conflicts with internal agent name', () => {
  80. const config: PluginConfig = {
  81. agents: {
  82. explorer: { displayName: 'oracle' },
  83. },
  84. };
  85. expect(() => createAgents(config)).toThrow(
  86. "displayName 'oracle' conflicts with an agent name",
  87. );
  88. });
  89. test('throws when normalized displayName conflicts with internal agent name', () => {
  90. const config: PluginConfig = {
  91. agents: {
  92. explorer: { displayName: ' @oracle ' },
  93. },
  94. };
  95. expect(() => createAgents(config)).toThrow(
  96. "displayName 'oracle' conflicts with an agent name",
  97. );
  98. });
  99. test('throws when orchestrator displayName conflicts with internal agent name', () => {
  100. const config: PluginConfig = {
  101. agents: {
  102. orchestrator: { displayName: 'oracle' },
  103. },
  104. };
  105. expect(() => createAgents(config)).toThrow(
  106. /displayName.*conflicts with an agent name/,
  107. );
  108. });
  109. test('resolves legacy alias for explorer displayName override', () => {
  110. const config: PluginConfig = {
  111. agents: {
  112. explore: { displayName: 'researcher' },
  113. },
  114. };
  115. const agents = createAgents(config);
  116. const explorer = agents.find((a) => a.name === 'explorer');
  117. expect(explorer?.displayName).toBe('researcher');
  118. });
  119. test('uses displayName as host-facing registry key with hidden internal alias', () => {
  120. const config: PluginConfig = {
  121. agents: {
  122. oracle: { displayName: 'advisor' },
  123. },
  124. };
  125. const sdkConfigs = getAgentConfigs(config) as Record<
  126. string,
  127. { hidden?: boolean; mode?: string }
  128. >;
  129. expect(sdkConfigs.advisor).toBeDefined();
  130. expect(sdkConfigs.advisor.mode).toBe('subagent');
  131. expect(sdkConfigs.advisor.hidden).toBeUndefined();
  132. expect(sdkConfigs.oracle).toBeDefined();
  133. expect(sdkConfigs.oracle.mode).toBe('subagent');
  134. expect(sdkConfigs.oracle.hidden).toBe(true);
  135. });
  136. test('uses orchestrator displayName as host-facing key with hidden internal alias', () => {
  137. const config: PluginConfig = {
  138. agents: {
  139. orchestrator: { displayName: 'engineer' },
  140. },
  141. };
  142. const sdkConfigs = getAgentConfigs(config) as Record<
  143. string,
  144. { hidden?: boolean; mode?: string }
  145. >;
  146. expect(sdkConfigs.engineer).toBeDefined();
  147. expect(sdkConfigs.engineer.mode).toBe('primary');
  148. expect(sdkConfigs.engineer.hidden).toBeUndefined();
  149. expect(sdkConfigs.orchestrator).toBeDefined();
  150. expect(sdkConfigs.orchestrator.mode).toBe('primary');
  151. expect(sdkConfigs.orchestrator.hidden).toBe(true);
  152. });
  153. test('keeps internal-only council agents hidden even with displayName configured', () => {
  154. const config: PluginConfig = {
  155. disabled_agents: [],
  156. agents: {
  157. councillor: { displayName: 'reviewer' },
  158. },
  159. };
  160. const sdkConfigs = getAgentConfigs(config);
  161. expect(sdkConfigs.reviewer).toBeUndefined();
  162. expect(sdkConfigs.councillor?.hidden).toBe(true);
  163. });
  164. });