1- import { mkdtempSync , rmSync , writeFileSync , mkdirSync } from 'fs'
1+ import { existsSync , mkdtempSync , rmSync , writeFileSync , mkdirSync } from 'fs'
22import os from 'os'
33import path from 'path'
44
5- import { describe , expect , test , beforeEach , afterEach , mock , spyOn } from 'bun:test'
5+ import {
6+ describe ,
7+ expect ,
8+ test ,
9+ beforeEach ,
10+ afterEach ,
11+ mock ,
12+ spyOn ,
13+ } from 'bun:test'
614
715import { loadLocalAgents } from '../agents/load-agents'
816
@@ -45,15 +53,19 @@ describe('loadLocalAgents', () => {
4553
4654 describe ( 'without validation (backward compatible)' , ( ) => {
4755 test ( 'returns empty object when agents directory does not exist' , async ( ) => {
48- const result : LoadedAgents = await loadLocalAgents ( { agentsPath : agentsDir } )
56+ const result : LoadedAgents = await loadLocalAgents ( {
57+ agentsPath : agentsDir ,
58+ } )
4959
5060 expect ( result ) . toEqual ( { } )
5161 } )
5262
5363 test ( 'returns empty object when agents directory is empty' , async ( ) => {
5464 mkdirSync ( agentsDir , { recursive : true } )
5565
56- const result : LoadedAgents = await loadLocalAgents ( { agentsPath : agentsDir } )
66+ const result : LoadedAgents = await loadLocalAgents ( {
67+ agentsPath : agentsDir ,
68+ } )
5769
5870 expect ( result ) . toEqual ( { } )
5971 } )
@@ -73,16 +85,16 @@ describe('loadLocalAgents', () => {
7385 ` ,
7486 )
7587
76- const result : LoadedAgents = await loadLocalAgents ( { agentsPath : agentsDir } )
88+ const result : LoadedAgents = await loadLocalAgents ( {
89+ agentsPath : agentsDir ,
90+ } )
7791
7892 const agent : LoadedAgentDefinition | undefined = result [ 'my-agent' ]
7993 expect ( agent ) . toBeDefined ( )
8094 expect ( agent ! . id ) . toBe ( 'my-agent' )
8195 expect ( agent ! . displayName ) . toBe ( 'My Agent' )
8296 expect ( agent ! . model ) . toBe ( MODEL_NAME )
83- expect ( agent ! . _sourceFilePath ) . toBe (
84- path . join ( agentsDir , 'my-agent.ts' ) ,
85- )
97+ expect ( agent ! . _sourceFilePath ) . toBe ( path . join ( agentsDir , 'my-agent.ts' ) )
8698 } )
8799
88100 test ( 'loads multiple agents from directory' , async ( ) => {
@@ -110,7 +122,9 @@ describe('loadLocalAgents', () => {
110122 ` ,
111123 )
112124
113- const result : LoadedAgents = await loadLocalAgents ( { agentsPath : agentsDir } )
125+ const result : LoadedAgents = await loadLocalAgents ( {
126+ agentsPath : agentsDir ,
127+ } )
114128 const agentIds : string [ ] = Object . keys ( result )
115129
116130 expect ( agentIds ) . toHaveLength ( 2 )
@@ -131,7 +145,9 @@ describe('loadLocalAgents', () => {
131145 ` ,
132146 )
133147
134- const result : LoadedAgents = await loadLocalAgents ( { agentsPath : agentsDir } )
148+ const result : LoadedAgents = await loadLocalAgents ( {
149+ agentsPath : agentsDir ,
150+ } )
135151
136152 expect ( Object . keys ( result ) ) . toHaveLength ( 0 )
137153 } )
@@ -149,7 +165,9 @@ describe('loadLocalAgents', () => {
149165 ` ,
150166 )
151167
152- const result : LoadedAgents = await loadLocalAgents ( { agentsPath : agentsDir } )
168+ const result : LoadedAgents = await loadLocalAgents ( {
169+ agentsPath : agentsDir ,
170+ } )
153171
154172 expect ( Object . keys ( result ) ) . toHaveLength ( 0 )
155173 } )
@@ -168,7 +186,9 @@ describe('loadLocalAgents', () => {
168186 ` ,
169187 )
170188
171- const result : LoadedAgents = await loadLocalAgents ( { agentsPath : agentsDir } )
189+ const result : LoadedAgents = await loadLocalAgents ( {
190+ agentsPath : agentsDir ,
191+ } )
172192
173193 expect ( result [ 'dts-agent' ] ) . toBeUndefined ( )
174194 } )
@@ -187,7 +207,9 @@ describe('loadLocalAgents', () => {
187207 ` ,
188208 )
189209
190- const result : LoadedAgents = await loadLocalAgents ( { agentsPath : agentsDir } )
210+ const result : LoadedAgents = await loadLocalAgents ( {
211+ agentsPath : agentsDir ,
212+ } )
191213
192214 expect ( result [ 'test-file-agent' ] ) . toBeUndefined ( )
193215 } )
@@ -207,7 +229,9 @@ describe('loadLocalAgents', () => {
207229 ` ,
208230 )
209231
210- const result : LoadedAgents = await loadLocalAgents ( { agentsPath : agentsDir } )
232+ const result : LoadedAgents = await loadLocalAgents ( {
233+ agentsPath : agentsDir ,
234+ } )
211235
212236 expect ( result [ 'nested-agent' ] ) . toBeDefined ( )
213237 } )
@@ -239,12 +263,115 @@ describe('loadLocalAgents', () => {
239263 ` ,
240264 )
241265
242- const result : LoadedAgents = await loadLocalAgents ( { agentsPath : agentsDir } )
266+ const result : LoadedAgents = await loadLocalAgents ( {
267+ agentsPath : agentsDir ,
268+ } )
243269
244270 expect ( result [ 'skill-agent' ] ) . toBeUndefined ( )
245271 expect ( result [ 'real-agent' ] ) . toBeDefined ( )
246272 } )
247273
274+ test ( 'loads valid agent definitions that use shorthand required fields' , async ( ) => {
275+ mkdirSync ( agentsDir , { recursive : true } )
276+ writeAgentFile (
277+ agentsDir ,
278+ 'shorthand-agent.ts' ,
279+ `
280+ const id = 'shorthand-agent'
281+ const model = '${ MODEL_NAME } '
282+
283+ export default {
284+ id,
285+ displayName: 'Shorthand Agent',
286+ model
287+ }
288+ ` ,
289+ )
290+
291+ const result : LoadedAgents = await loadLocalAgents ( {
292+ agentsPath : agentsDir ,
293+ } )
294+
295+ expect ( result [ 'shorthand-agent' ] ) . toBeDefined ( )
296+ expect ( result [ 'shorthand-agent' ] ! . model ) . toBe ( MODEL_NAME )
297+ } )
298+
299+ test ( 'skips quarantined skill directories without importing executable scripts' , async ( ) => {
300+ const quarantineScriptsDir = path . join (
301+ agentsDir ,
302+ 'skills-quarantine' ,
303+ '2026-02-23' ,
304+ 'youtube-data' ,
305+ 'scripts' ,
306+ )
307+ mkdirSync ( quarantineScriptsDir , { recursive : true } )
308+ const markerFile = path . join ( tempDir , 'quarantine-side-effect' )
309+ writeAgentFile (
310+ quarantineScriptsDir ,
311+ 'tapi-auth.cjs' ,
312+ `
313+ const { writeFileSync } = require('fs')
314+ writeFileSync(${ JSON . stringify ( markerFile ) } , 'imported')
315+ module.exports = {
316+ id: 'quarantined-agent',
317+ displayName: 'Quarantined Agent',
318+ model: '${ MODEL_NAME } '
319+ }
320+ ` ,
321+ )
322+ writeAgentFile (
323+ agentsDir ,
324+ 'real-agent.ts' ,
325+ `
326+ export default {
327+ id: 'real-agent',
328+ displayName: 'Real Agent',
329+ model: '${ MODEL_NAME } '
330+ }
331+ ` ,
332+ )
333+
334+ const result : LoadedAgents = await loadLocalAgents ( {
335+ agentsPath : agentsDir ,
336+ } )
337+
338+ expect ( result [ 'real-agent' ] ) . toBeDefined ( )
339+ expect ( result [ 'quarantined-agent' ] ) . toBeUndefined ( )
340+ expect ( existsSync ( markerFile ) ) . toBe ( false )
341+ } )
342+
343+ test ( 'skips support directories without importing executable scripts' , async ( ) => {
344+ const scriptsDir = path . join ( agentsDir , 'scripts' )
345+ mkdirSync ( scriptsDir , { recursive : true } )
346+ const markerFile = path . join ( tempDir , 'scripts-side-effect' )
347+ writeAgentFile (
348+ scriptsDir ,
349+ 'exa-api.cjs' ,
350+ `
351+ const { writeFileSync } = require('fs')
352+ writeFileSync(${ JSON . stringify ( markerFile ) } , 'imported')
353+ ` ,
354+ )
355+ writeAgentFile (
356+ agentsDir ,
357+ 'real-agent.ts' ,
358+ `
359+ export default {
360+ id: 'real-agent',
361+ displayName: 'Real Agent',
362+ model: '${ MODEL_NAME } '
363+ }
364+ ` ,
365+ )
366+
367+ const result : LoadedAgents = await loadLocalAgents ( {
368+ agentsPath : agentsDir ,
369+ } )
370+
371+ expect ( result [ 'real-agent' ] ) . toBeDefined ( )
372+ expect ( existsSync ( markerFile ) ) . toBe ( false )
373+ } )
374+
248375 test ( 'converts handleSteps function to string' , async ( ) => {
249376 mkdirSync ( agentsDir , { recursive : true } )
250377 writeAgentFile (
@@ -263,7 +390,9 @@ describe('loadLocalAgents', () => {
263390 ` ,
264391 )
265392
266- const result : LoadedAgents = await loadLocalAgents ( { agentsPath : agentsDir } )
393+ const result : LoadedAgents = await loadLocalAgents ( {
394+ agentsPath : agentsDir ,
395+ } )
267396 const agent : LoadedAgentDefinition | undefined = result [ 'generator-agent' ]
268397
269398 expect ( agent ) . toBeDefined ( )
@@ -299,7 +428,9 @@ describe('loadLocalAgents', () => {
299428 ` ,
300429 )
301430
302- const result : LoadedAgents = await loadLocalAgents ( { agentsPath : agentsDir } )
431+ const result : LoadedAgents = await loadLocalAgents ( {
432+ agentsPath : agentsDir ,
433+ } )
303434
304435 // Should still load the valid agent
305436 expect ( result [ 'valid-agent' ] ) . toBeDefined ( )
@@ -326,9 +457,7 @@ describe('loadLocalAgents', () => {
326457 await loadLocalAgents ( { agentsPath : agentsDir , verbose : true } )
327458
328459 expect ( consoleErrorSpy ) . toHaveBeenCalled ( )
329- const errorMessage : string = consoleErrorSpy . mock . calls
330- . flat ( )
331- . join ( ' ' )
460+ const errorMessage : string = consoleErrorSpy . mock . calls . flat ( ) . join ( ' ' )
332461 expect ( errorMessage ) . toContain ( 'missing required attributes' )
333462 } )
334463 } )
0 commit comments