@@ -3,6 +3,7 @@ import { dirname, join } from "node:path";
33import { parseArgs } from "node:util" ;
44import { lstat , readFile } from "node:fs/promises" ;
55import { z } from "zod" ;
6+ import { downloadFileToCacheDir , type RepoDesignation } from "@huggingface/hub" ;
67import { PROVIDERS_OR_POLICIES } from "@huggingface/inference" ;
78import { Agent } from "@huggingface/mcp-client" ;
89import { version as packageVersion } from "../package.json" ;
@@ -25,6 +26,11 @@ Flags:
2526 -v, --version Show version information
2627` . trim ( ) ;
2728
29+ interface TinyAgentConfig {
30+ configJson: string ;
31+ prompt ? : string ;
32+ }
33+
2834const CLI_COMMANDS = [ "run" , "serve" ] as const ;
2935function isValidCommand ( command : string ) : command is ( typeof CLI_COMMANDS ) [ number ] {
3036 return ( CLI_COMMANDS as unknown as string [ ] ) . includes ( command ) ;
@@ -34,51 +40,102 @@ const FILENAME_CONFIG = "agent.json";
3440// eslint-disable-next-line @typescript-eslint/no-unused-vars
3541const FILENAME_PROMPT = "PROMPT.md" ;
3642
37- async function loadConfigFrom ( loadFrom : string ) : Promise < { configJson: string ; prompt ? : string } > {
43+ const TINY_AGENTS_HUB_REPO : RepoDesignation = {
44+ name : "huggingface/tiny-agents" ,
45+ type : "dataset" ,
46+ } ;
47+
48+ async function tryLoadFromFile ( filePath : string ) : Promise < TinyAgentConfig | undefined > {
49+ try {
50+ const configJson = await readFile ( filePath , { encoding : "utf8" } ) ;
51+ return { configJson } ;
52+ } catch {
53+ return undefined ;
54+ }
55+ }
56+
57+ async function tryLoadFromDirectory ( dirPath : string ) : Promise < TinyAgentConfig | undefined > {
58+ const stats = await lstat ( dirPath ) . catch ( ( ) => undefined ) ;
59+ if ( ! stats ?. isDirectory ( ) ) {
60+ return undefined ;
61+ }
62+
63+ let prompt : string | undefined ;
64+ try {
65+ prompt = await readFile ( join ( dirPath , FILENAME_PROMPT ) , { encoding : "utf8" } ) ;
66+ } catch {
67+ debug ( `PROMPT.md not found in ${ dirPath } , continuing without prompt template` ) ;
68+ }
69+
3870 try {
39- /// First try it as a local file path, then as a local directory, then we will try as a path inside the repo itself
4071 return {
41- configJson : await readFile ( loadFrom , { encoding : "utf8" } ) ,
72+ configJson : await readFile ( join ( dirPath , FILENAME_CONFIG ) , { encoding : "utf8" } ) ,
73+ prompt ,
4274 } ;
4375 } catch {
44- if ( ( await lstat ( loadFrom ) ) . isDirectory ( ) ) {
45- /// local directory
46- try {
47- let prompt : string | undefined ;
48- try {
49- prompt = await readFile ( join ( loadFrom , FILENAME_PROMPT ) , { encoding : "utf8" } ) ;
50- } catch {
51- debug ( `PROMPT.md not found in ${ loadFrom } , continuing without prompt template` ) ;
52- }
53- return {
54- configJson : await readFile ( join ( loadFrom , FILENAME_CONFIG ) , { encoding : "utf8" } ) ,
55- prompt,
56- } ;
57- } catch {
58- error ( `Config file not found in specified local directory.` ) ;
59- process . exit ( 1 ) ;
60- }
61- }
62- const srcDir = dirname ( __filename ) ;
63- const configDir = join ( srcDir , "agents" , loadFrom ) ;
64- try {
65- let prompt : string | undefined ;
66- try {
67- prompt = await readFile ( join ( configDir , FILENAME_PROMPT ) , { encoding : "utf8" } ) ;
68- } catch {
69- debug ( `PROMPT.md not found in ${ configDir } , continuing without prompt template` ) ;
70- }
71- return {
72- configJson : await readFile ( join ( configDir , FILENAME_CONFIG ) , { encoding : "utf8" } ) ,
73- prompt,
74- } ;
75- } catch {
76- error ( `Config file not found in tiny-agents repo! Loading from the HF Hub is not implemented yet` ) ;
77- process . exit ( 1 ) ;
78- }
76+ error ( `Config file not found in specified local directory.` ) ;
77+ process . exit ( 1 ) ;
7978 }
8079}
8180
81+ async function tryLoadFromHub ( agentId : string ) : Promise < TinyAgentConfig | undefined > {
82+ let configJson : string ;
83+ try {
84+ const configPath = await downloadFileToCacheDir ( {
85+ repo : TINY_AGENTS_HUB_REPO ,
86+ path : `${ agentId } /${ FILENAME_CONFIG } ` ,
87+ accessToken : process . env . HF_TOKEN ,
88+ } ) ;
89+ configJson = await readFile ( configPath , { encoding : "utf8" } ) ;
90+ } catch {
91+ return undefined ;
92+ }
93+
94+ let prompt : string | undefined ;
95+ try {
96+ const promptPath = await downloadFileToCacheDir ( {
97+ repo : TINY_AGENTS_HUB_REPO ,
98+ path : `${ agentId } /${ FILENAME_PROMPT } ` ,
99+ accessToken : process . env . HF_TOKEN ,
100+ } ) ;
101+ prompt = await readFile ( promptPath , { encoding : "utf8" } ) ;
102+ } catch {
103+ debug (
104+ `PROMPT.md not found in https://huggingface.co/datasets/huggingface/tiny-agents/tree/main/${ agentId } , continuing without prompt template`
105+ ) ;
106+ }
107+
108+ return {
109+ configJson ,
110+ prompt ,
111+ } ;
112+ }
113+
114+ async function loadConfigFrom ( loadFrom : string ) : Promise < TinyAgentConfig > {
115+ // First try as a local file
116+ const fileConfig = await tryLoadFromFile ( loadFrom ) ;
117+ if ( fileConfig ) {
118+ return fileConfig ;
119+ }
120+
121+ // Then try as a local directory
122+ const dirConfig = await tryLoadFromDirectory ( loadFrom ) ;
123+ if ( dirConfig ) {
124+ return dirConfig ;
125+ }
126+
127+ // Finally try loading from repo
128+ const repoConfig = await tryLoadFromHub ( loadFrom ) ;
129+ if ( repoConfig ) {
130+ return repoConfig ;
131+ }
132+
133+ error (
134+ `Config file not found in tiny-agents! Please make sure it exists locally or in https://huggingface.co/datasets/huggingface/tiny-agents.`
135+ ) ;
136+ process . exit ( 1 ) ;
137+ }
138+
82139async function main ( ) {
83140 const {
84141 values : { help , version } ,
0 commit comments