77 "io"
88 "net/http"
99 "os"
10- "os/exec"
1110 "path/filepath"
12- "strings"
1311 "time"
1412
1513 "github.com/databricks/cli/experimental/aitools/lib/agents"
@@ -33,41 +31,16 @@ func getSkillsBranch() string {
3331 return defaultSkillsRepoBranch
3432}
3533
36- // getGitHubToken returns GitHub token from environment or gh CLI.
37- // TODO: once databricks-agent-skills repo is public, replace GitHub API calls
38- // with raw.githubusercontent.com URLs and remove authentication logic.
39- func getGitHubToken () string {
40- // check environment variables first
41- if token := os .Getenv ("GITHUB_TOKEN" ); token != "" {
42- return token
43- }
44- if token := os .Getenv ("GH_TOKEN" ); token != "" {
45- return token
46- }
47- // try gh CLI
48- out , err := exec .Command ("gh" , "auth" , "token" ).Output ()
49- if err == nil {
50- return strings .TrimSpace (string (out ))
51- }
52- return ""
53- }
54-
55- // addGitHubAuth adds authentication header if token is available.
56- func addGitHubAuth (req * http.Request ) {
57- if token := getGitHubToken (); token != "" {
58- req .Header .Set ("Authorization" , "Bearer " + token )
59- }
60- }
61-
6234type Manifest struct {
6335 Version string `json:"version"`
6436 UpdatedAt string `json:"updated_at"`
6537 Skills map [string ]SkillMeta `json:"skills"`
6638}
6739
6840type SkillMeta struct {
69- Version string `json:"version"`
70- UpdatedAt string `json:"updated_at"`
41+ Version string `json:"version"`
42+ UpdatedAt string `json:"updated_at"`
43+ Files []string `json:"files"`
7144}
7245
7346func newSkillsCmd () * cobra.Command {
@@ -114,16 +87,12 @@ Supported agents: Claude Code, Cursor, Codex CLI, OpenCode, GitHub Copilot, Anti
11487}
11588
11689func fetchManifest (ctx context.Context ) (* Manifest , error ) {
117- // use GitHub API for private repo support
118- // manifest.json is at repo root, skills are in skillsRepoPath subdirectory
119- url := fmt .Sprintf ("https://api.github.com/repos/%s/%s/contents/manifest.json?ref=%s" ,
90+ url := fmt .Sprintf ("https://raw.githubusercontent.com/%s/%s/%s/manifest.json" ,
12091 skillsRepoOwner , skillsRepoName , getSkillsBranch ())
12192 req , err := http .NewRequestWithContext (ctx , http .MethodGet , url , nil )
12293 if err != nil {
12394 return nil , fmt .Errorf ("failed to create request: %w" , err )
12495 }
125- req .Header .Set ("Accept" , "application/vnd.github.raw+json" )
126- addGitHubAuth (req )
12796
12897 client := & http.Client {Timeout : 30 * time .Second }
12998 resp , err := client .Do (req )
@@ -145,16 +114,13 @@ func fetchManifest(ctx context.Context) (*Manifest, error) {
145114}
146115
147116func fetchSkillFile (ctx context.Context , skillName , filePath string ) ([]byte , error ) {
148- // use GitHub API for private repo support
149- url := fmt .Sprintf ("https://api.github.com/repos/%s/%s/contents/%s/%s/%s?ref=%s" ,
150- skillsRepoOwner , skillsRepoName , skillsRepoPath , skillName , filePath , getSkillsBranch ())
117+ url := fmt .Sprintf ("https://raw.githubusercontent.com/%s/%s/%s/%s/%s/%s" ,
118+ skillsRepoOwner , skillsRepoName , getSkillsBranch (), skillsRepoPath , skillName , filePath )
151119
152120 req , err := http .NewRequestWithContext (ctx , http .MethodGet , url , nil )
153121 if err != nil {
154122 return nil , fmt .Errorf ("failed to create request: %w" , err )
155123 }
156- req .Header .Set ("Accept" , "application/vnd.github.raw+json" )
157- addGitHubAuth (req )
158124
159125 client := & http.Client {Timeout : 30 * time .Second }
160126 resp , err := client .Do (req )
@@ -170,108 +136,6 @@ func fetchSkillFile(ctx context.Context, skillName, filePath string) ([]byte, er
170136 return io .ReadAll (resp .Body )
171137}
172138
173- func fetchSkillFileList (ctx context.Context , skillName string ) ([]string , error ) {
174- // use GitHub API to list files in skill directory
175- skillPath := skillsRepoPath + "/" + skillName
176- url := fmt .Sprintf ("https://api.github.com/repos/%s/%s/contents/%s?ref=%s" ,
177- skillsRepoOwner , skillsRepoName , skillPath , getSkillsBranch ())
178-
179- req , err := http .NewRequestWithContext (ctx , http .MethodGet , url , nil )
180- if err != nil {
181- return nil , err
182- }
183- req .Header .Set ("Accept" , "application/vnd.github.v3+json" )
184- addGitHubAuth (req )
185-
186- client := & http.Client {Timeout : 30 * time .Second }
187- resp , err := client .Do (req )
188- if err != nil {
189- return nil , err
190- }
191- defer resp .Body .Close ()
192-
193- if resp .StatusCode != http .StatusOK {
194- return nil , fmt .Errorf ("failed to list skill files: HTTP %d" , resp .StatusCode )
195- }
196-
197- var items []struct {
198- Path string `json:"path"`
199- Type string `json:"type"`
200- }
201- if err := json .NewDecoder (resp .Body ).Decode (& items ); err != nil {
202- return nil , err
203- }
204-
205- var files []string
206- for _ , item := range items {
207- switch item .Type {
208- case "file" :
209- // strip skills/skill-name prefix from path
210- relPath := strings .TrimPrefix (item .Path , skillPath + "/" )
211- files = append (files , relPath )
212- case "dir" :
213- // recursively list subdirectory
214- subFiles , err := fetchSubdirFiles (ctx , item .Path )
215- if err != nil {
216- return nil , err
217- }
218- for _ , sf := range subFiles {
219- relPath := strings .TrimPrefix (sf , skillPath + "/" )
220- files = append (files , relPath )
221- }
222- }
223- }
224-
225- return files , nil
226- }
227-
228- func fetchSubdirFiles (ctx context.Context , dirPath string ) ([]string , error ) {
229- url := fmt .Sprintf ("https://api.github.com/repos/%s/%s/contents/%s?ref=%s" ,
230- skillsRepoOwner , skillsRepoName , dirPath , getSkillsBranch ())
231-
232- req , err := http .NewRequestWithContext (ctx , http .MethodGet , url , nil )
233- if err != nil {
234- return nil , err
235- }
236- req .Header .Set ("Accept" , "application/vnd.github.v3+json" )
237- addGitHubAuth (req )
238-
239- client := & http.Client {Timeout : 30 * time .Second }
240- resp , err := client .Do (req )
241- if err != nil {
242- return nil , err
243- }
244- defer resp .Body .Close ()
245-
246- if resp .StatusCode != http .StatusOK {
247- return nil , fmt .Errorf ("failed to list directory %s: HTTP %d" , dirPath , resp .StatusCode )
248- }
249-
250- var items []struct {
251- Path string `json:"path"`
252- Type string `json:"type"`
253- }
254- if err := json .NewDecoder (resp .Body ).Decode (& items ); err != nil {
255- return nil , err
256- }
257-
258- var files []string
259- for _ , item := range items {
260- switch item .Type {
261- case "file" :
262- files = append (files , item .Path )
263- case "dir" :
264- subFiles , err := fetchSubdirFiles (ctx , item .Path )
265- if err != nil {
266- return nil , err
267- }
268- files = append (files , subFiles ... )
269- }
270- }
271-
272- return files , nil
273- }
274-
275139func listSkills (ctx context.Context ) error {
276140 manifest , err := fetchManifest (ctx )
277141 if err != nil {
@@ -306,8 +170,8 @@ func installAllSkills(ctx context.Context) error {
306170
307171 printDetectedAgents (ctx , detectedAgents )
308172
309- for name := range manifest .Skills {
310- if err := installSkillForAgents (ctx , name , detectedAgents ); err != nil {
173+ for name , meta := range manifest .Skills {
174+ if err := installSkillForAgents (ctx , name , meta . Files , detectedAgents ); err != nil {
311175 return err
312176 }
313177 }
@@ -347,16 +211,10 @@ func installSkill(ctx context.Context, skillName string) error {
347211
348212 printDetectedAgents (ctx , detectedAgents )
349213
350- return installSkillForAgents (ctx , skillName , detectedAgents )
214+ return installSkillForAgents (ctx , skillName , manifest . Skills [ skillName ]. Files , detectedAgents )
351215}
352216
353- func installSkillForAgents (ctx context.Context , skillName string , detectedAgents []* agents.Agent ) error {
354- // get list of files in skill
355- files , err := fetchSkillFileList (ctx , skillName )
356- if err != nil {
357- return fmt .Errorf ("failed to list skill files: %w" , err )
358- }
359-
217+ func installSkillForAgents (ctx context.Context , skillName string , files []string , detectedAgents []* agents.Agent ) error {
360218 homeDir , err := os .UserHomeDir ()
361219 if err != nil {
362220 return fmt .Errorf ("failed to get home directory: %w" , err )
0 commit comments