@zibby/skills 0.1.87 → 0.1.89

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/github.d.ts CHANGED
@@ -45,6 +45,9 @@ export namespace githubSkill {
45
45
  comments?: undefined;
46
46
  branch?: undefined;
47
47
  path?: undefined;
48
+ since?: undefined;
49
+ until?: undefined;
50
+ page?: undefined;
48
51
  sha?: undefined;
49
52
  ref?: undefined;
50
53
  head?: undefined;
@@ -56,7 +59,6 @@ export namespace githubSkill {
56
59
  commitMessage?: undefined;
57
60
  state?: undefined;
58
61
  labels?: undefined;
59
- since?: undefined;
60
62
  assignee?: undefined;
61
63
  stateReason?: undefined;
62
64
  mode?: undefined;
@@ -106,6 +108,9 @@ export namespace githubSkill {
106
108
  comments?: undefined;
107
109
  branch?: undefined;
108
110
  path?: undefined;
111
+ since?: undefined;
112
+ until?: undefined;
113
+ page?: undefined;
109
114
  sha?: undefined;
110
115
  ref?: undefined;
111
116
  head?: undefined;
@@ -117,7 +122,6 @@ export namespace githubSkill {
117
122
  commitMessage?: undefined;
118
123
  state?: undefined;
119
124
  labels?: undefined;
120
- since?: undefined;
121
125
  assignee?: undefined;
122
126
  stateReason?: undefined;
123
127
  mode?: undefined;
@@ -155,6 +159,9 @@ export namespace githubSkill {
155
159
  comments?: undefined;
156
160
  branch?: undefined;
157
161
  path?: undefined;
162
+ since?: undefined;
163
+ until?: undefined;
164
+ page?: undefined;
158
165
  sha?: undefined;
159
166
  ref?: undefined;
160
167
  head?: undefined;
@@ -166,7 +173,6 @@ export namespace githubSkill {
166
173
  commitMessage?: undefined;
167
174
  state?: undefined;
168
175
  labels?: undefined;
169
- since?: undefined;
170
176
  assignee?: undefined;
171
177
  stateReason?: undefined;
172
178
  mode?: undefined;
@@ -201,6 +207,9 @@ export namespace githubSkill {
201
207
  comments?: undefined;
202
208
  branch?: undefined;
203
209
  path?: undefined;
210
+ since?: undefined;
211
+ until?: undefined;
212
+ page?: undefined;
204
213
  sha?: undefined;
205
214
  ref?: undefined;
206
215
  head?: undefined;
@@ -212,7 +221,6 @@ export namespace githubSkill {
212
221
  commitMessage?: undefined;
213
222
  state?: undefined;
214
223
  labels?: undefined;
215
- since?: undefined;
216
224
  assignee?: undefined;
217
225
  stateReason?: undefined;
218
226
  mode?: undefined;
@@ -253,6 +261,9 @@ export namespace githubSkill {
253
261
  comments?: undefined;
254
262
  branch?: undefined;
255
263
  path?: undefined;
264
+ since?: undefined;
265
+ until?: undefined;
266
+ page?: undefined;
256
267
  sha?: undefined;
257
268
  ref?: undefined;
258
269
  head?: undefined;
@@ -264,7 +275,6 @@ export namespace githubSkill {
264
275
  commitMessage?: undefined;
265
276
  state?: undefined;
266
277
  labels?: undefined;
267
- since?: undefined;
268
278
  assignee?: undefined;
269
279
  stateReason?: undefined;
270
280
  mode?: undefined;
@@ -302,6 +312,9 @@ export namespace githubSkill {
302
312
  comments?: undefined;
303
313
  branch?: undefined;
304
314
  path?: undefined;
315
+ since?: undefined;
316
+ until?: undefined;
317
+ page?: undefined;
305
318
  sha?: undefined;
306
319
  ref?: undefined;
307
320
  head?: undefined;
@@ -313,7 +326,6 @@ export namespace githubSkill {
313
326
  commitMessage?: undefined;
314
327
  state?: undefined;
315
328
  labels?: undefined;
316
- since?: undefined;
317
329
  assignee?: undefined;
318
330
  stateReason?: undefined;
319
331
  mode?: undefined;
@@ -354,6 +366,9 @@ export namespace githubSkill {
354
366
  comments?: undefined;
355
367
  branch?: undefined;
356
368
  path?: undefined;
369
+ since?: undefined;
370
+ until?: undefined;
371
+ page?: undefined;
357
372
  sha?: undefined;
358
373
  ref?: undefined;
359
374
  head?: undefined;
@@ -365,7 +380,6 @@ export namespace githubSkill {
365
380
  commitMessage?: undefined;
366
381
  state?: undefined;
367
382
  labels?: undefined;
368
- since?: undefined;
369
383
  assignee?: undefined;
370
384
  stateReason?: undefined;
371
385
  mode?: undefined;
@@ -409,6 +423,9 @@ export namespace githubSkill {
409
423
  comments?: undefined;
410
424
  branch?: undefined;
411
425
  path?: undefined;
426
+ since?: undefined;
427
+ until?: undefined;
428
+ page?: undefined;
412
429
  sha?: undefined;
413
430
  ref?: undefined;
414
431
  head?: undefined;
@@ -420,7 +437,6 @@ export namespace githubSkill {
420
437
  commitMessage?: undefined;
421
438
  state?: undefined;
422
439
  labels?: undefined;
423
- since?: undefined;
424
440
  assignee?: undefined;
425
441
  stateReason?: undefined;
426
442
  mode?: undefined;
@@ -461,6 +477,9 @@ export namespace githubSkill {
461
477
  comments?: undefined;
462
478
  branch?: undefined;
463
479
  path?: undefined;
480
+ since?: undefined;
481
+ until?: undefined;
482
+ page?: undefined;
464
483
  sha?: undefined;
465
484
  ref?: undefined;
466
485
  head?: undefined;
@@ -472,7 +491,6 @@ export namespace githubSkill {
472
491
  commitMessage?: undefined;
473
492
  state?: undefined;
474
493
  labels?: undefined;
475
- since?: undefined;
476
494
  assignee?: undefined;
477
495
  stateReason?: undefined;
478
496
  mode?: undefined;
@@ -543,6 +561,9 @@ export namespace githubSkill {
543
561
  commentId?: undefined;
544
562
  branch?: undefined;
545
563
  path?: undefined;
564
+ since?: undefined;
565
+ until?: undefined;
566
+ page?: undefined;
546
567
  sha?: undefined;
547
568
  ref?: undefined;
548
569
  head?: undefined;
@@ -554,7 +575,6 @@ export namespace githubSkill {
554
575
  commitMessage?: undefined;
555
576
  state?: undefined;
556
577
  labels?: undefined;
557
- since?: undefined;
558
578
  assignee?: undefined;
559
579
  stateReason?: undefined;
560
580
  mode?: undefined;
@@ -587,6 +607,18 @@ export namespace githubSkill {
587
607
  type: string;
588
608
  description: string;
589
609
  };
610
+ since: {
611
+ type: string;
612
+ description: string;
613
+ };
614
+ until: {
615
+ type: string;
616
+ description: string;
617
+ };
618
+ page: {
619
+ type: string;
620
+ description: string;
621
+ };
590
622
  query?: undefined;
591
623
  type?: undefined;
592
624
  sort?: undefined;
@@ -609,7 +641,6 @@ export namespace githubSkill {
609
641
  commitMessage?: undefined;
610
642
  state?: undefined;
611
643
  labels?: undefined;
612
- since?: undefined;
613
644
  assignee?: undefined;
614
645
  stateReason?: undefined;
615
646
  mode?: undefined;
@@ -648,6 +679,9 @@ export namespace githubSkill {
648
679
  comments?: undefined;
649
680
  branch?: undefined;
650
681
  path?: undefined;
682
+ since?: undefined;
683
+ until?: undefined;
684
+ page?: undefined;
651
685
  ref?: undefined;
652
686
  head?: undefined;
653
687
  base?: undefined;
@@ -658,7 +692,6 @@ export namespace githubSkill {
658
692
  commitMessage?: undefined;
659
693
  state?: undefined;
660
694
  labels?: undefined;
661
- since?: undefined;
662
695
  assignee?: undefined;
663
696
  stateReason?: undefined;
664
697
  mode?: undefined;
@@ -700,6 +733,9 @@ export namespace githubSkill {
700
733
  event?: undefined;
701
734
  comments?: undefined;
702
735
  branch?: undefined;
736
+ since?: undefined;
737
+ until?: undefined;
738
+ page?: undefined;
703
739
  sha?: undefined;
704
740
  head?: undefined;
705
741
  base?: undefined;
@@ -710,7 +746,6 @@ export namespace githubSkill {
710
746
  commitMessage?: undefined;
711
747
  state?: undefined;
712
748
  labels?: undefined;
713
- since?: undefined;
714
749
  assignee?: undefined;
715
750
  stateReason?: undefined;
716
751
  mode?: undefined;
@@ -764,6 +799,9 @@ export namespace githubSkill {
764
799
  comments?: undefined;
765
800
  branch?: undefined;
766
801
  path?: undefined;
802
+ since?: undefined;
803
+ until?: undefined;
804
+ page?: undefined;
767
805
  sha?: undefined;
768
806
  ref?: undefined;
769
807
  mergeMethod?: undefined;
@@ -771,7 +809,6 @@ export namespace githubSkill {
771
809
  commitMessage?: undefined;
772
810
  state?: undefined;
773
811
  labels?: undefined;
774
- since?: undefined;
775
812
  assignee?: undefined;
776
813
  stateReason?: undefined;
777
814
  mode?: undefined;
@@ -822,6 +859,9 @@ export namespace githubSkill {
822
859
  comments?: undefined;
823
860
  branch?: undefined;
824
861
  path?: undefined;
862
+ since?: undefined;
863
+ until?: undefined;
864
+ page?: undefined;
825
865
  sha?: undefined;
826
866
  ref?: undefined;
827
867
  head?: undefined;
@@ -830,7 +870,6 @@ export namespace githubSkill {
830
870
  draft?: undefined;
831
871
  state?: undefined;
832
872
  labels?: undefined;
833
- since?: undefined;
834
873
  assignee?: undefined;
835
874
  stateReason?: undefined;
836
875
  mode?: undefined;
@@ -872,6 +911,9 @@ export namespace githubSkill {
872
911
  comments?: undefined;
873
912
  branch?: undefined;
874
913
  path?: undefined;
914
+ since?: undefined;
915
+ until?: undefined;
916
+ page?: undefined;
875
917
  sha?: undefined;
876
918
  ref?: undefined;
877
919
  head?: undefined;
@@ -882,7 +924,6 @@ export namespace githubSkill {
882
924
  commitMessage?: undefined;
883
925
  state?: undefined;
884
926
  labels?: undefined;
885
- since?: undefined;
886
927
  assignee?: undefined;
887
928
  stateReason?: undefined;
888
929
  mode?: undefined;
@@ -948,6 +989,8 @@ export namespace githubSkill {
948
989
  comments?: undefined;
949
990
  branch?: undefined;
950
991
  path?: undefined;
992
+ until?: undefined;
993
+ page?: undefined;
951
994
  sha?: undefined;
952
995
  ref?: undefined;
953
996
  head?: undefined;
@@ -996,6 +1039,9 @@ export namespace githubSkill {
996
1039
  comments?: undefined;
997
1040
  branch?: undefined;
998
1041
  path?: undefined;
1042
+ since?: undefined;
1043
+ until?: undefined;
1044
+ page?: undefined;
999
1045
  sha?: undefined;
1000
1046
  ref?: undefined;
1001
1047
  head?: undefined;
@@ -1007,7 +1053,6 @@ export namespace githubSkill {
1007
1053
  commitMessage?: undefined;
1008
1054
  state?: undefined;
1009
1055
  labels?: undefined;
1010
- since?: undefined;
1011
1056
  assignee?: undefined;
1012
1057
  stateReason?: undefined;
1013
1058
  mode?: undefined;
@@ -1050,6 +1095,9 @@ export namespace githubSkill {
1050
1095
  comments?: undefined;
1051
1096
  branch?: undefined;
1052
1097
  path?: undefined;
1098
+ since?: undefined;
1099
+ until?: undefined;
1100
+ page?: undefined;
1053
1101
  sha?: undefined;
1054
1102
  ref?: undefined;
1055
1103
  head?: undefined;
@@ -1061,7 +1109,6 @@ export namespace githubSkill {
1061
1109
  commitMessage?: undefined;
1062
1110
  state?: undefined;
1063
1111
  labels?: undefined;
1064
- since?: undefined;
1065
1112
  assignee?: undefined;
1066
1113
  mode?: undefined;
1067
1114
  };
@@ -1110,6 +1157,9 @@ export namespace githubSkill {
1110
1157
  comments?: undefined;
1111
1158
  branch?: undefined;
1112
1159
  path?: undefined;
1160
+ since?: undefined;
1161
+ until?: undefined;
1162
+ page?: undefined;
1113
1163
  sha?: undefined;
1114
1164
  ref?: undefined;
1115
1165
  head?: undefined;
@@ -1120,7 +1170,6 @@ export namespace githubSkill {
1120
1170
  commitTitle?: undefined;
1121
1171
  commitMessage?: undefined;
1122
1172
  state?: undefined;
1123
- since?: undefined;
1124
1173
  assignee?: undefined;
1125
1174
  stateReason?: undefined;
1126
1175
  };
package/dist/github.js CHANGED
@@ -1,4 +1,4 @@
1
- import{existsSync as E}from"fs";import{fileURLToPath as G}from"url";import{dirname as I,resolve as J}from"path";import{resolveIntegrationToken as T}from"@zibby/core/backend-client.js";var A=Object.freeze({SENTRY:"sentry",JIRA:"jira",GITHUB:"github",GITLAB:"gitlab",SLACK:"slack",LARK:"lark",OPENAI_BILLING:"openai_billing",ANTHROPIC_BILLING:"anthropic_billing",CURSOR_ADMIN:"cursor_admin",NOTION:"notion",GOOGLE:"google",PLANE:"plane",LINEAR:"linear",FIGMA:"figma",HUBSPOT:"hubspot",OPEN_DESIGN:"open_design",LINKEDIN_PERSONAL:"linkedin_personal",LINKEDIN_BUSINESS:"linkedin_business",DISCORD:"discord"}),x=Object.freeze({sentry:{id:"sentry",name:"Sentry",connectPath:"/integrations?provider=sentry"},jira:{id:"jira",name:"Jira",connectPath:"/integrations?provider=jira"},github:{id:"github",name:"GitHub",connectPath:"/integrations?provider=github"},gitlab:{id:"gitlab",name:"GitLab",connectPath:"/integrations?provider=gitlab"},slack:{id:"slack",name:"Slack",connectPath:"/integrations?provider=slack"},lark:{id:"lark",name:"Lark",connectPath:"/integrations?provider=lark"},openai_billing:{id:"openai_billing",name:"OpenAI Admin",connectPath:"/integrations?provider=openai_billing"},anthropic_billing:{id:"anthropic_billing",name:"Anthropic Admin",connectPath:"/integrations?provider=anthropic_billing"},cursor_admin:{id:"cursor_admin",name:"Cursor Admin",connectPath:"/integrations?provider=cursor_admin"},notion:{id:"notion",name:"Notion",connectPath:"/integrations?provider=notion"},google:{id:"google",name:"Google Docs",connectPath:"/integrations?provider=google"},plane:{id:"plane",name:"Plane",connectPath:"/integrations?provider=plane"},linear:{id:"linear",name:"Linear",connectPath:"/integrations?provider=linear"},figma:{id:"figma",name:"Figma",connectPath:"/integrations?provider=figma"},hubspot:{id:"hubspot",name:"HubSpot",connectPath:"/integrations?provider=hubspot"},open_design:{id:"open_design",name:"OpenDesign",connectPath:"/integrations?provider=open_design"},linkedin_personal:{id:"linkedin_personal",name:"LinkedIn (Personal)",connectPath:"/integrations?provider=linkedin_personal"},linkedin_business:{id:"linkedin_business",name:"LinkedIn (Business)",connectPath:"/integrations?provider=linkedin_business"},discord:{id:"discord",name:"Discord",connectPath:"/integrations?provider=discord"}});import{spawn as U,execSync as D}from"child_process";import{existsSync as F,mkdirSync as B,readdirSync as z,statSync as K,readFileSync as W}from"fs";import{resolve as V,join as Y,basename as Z}from"path";function P(b,a,t,i,s="clone"){try{b(`git -C "${a}" remote set-url origin "${t}"`,{stdio:"pipe"})}catch(e){let r=String(e?.message||e);i&&(r=r.split(i).join("***")),console.error(`[${s}] WARNING: failed to strip token from .git/config: ${r}`)}}function C(){if(process.env.MCP_SKILL_PATH)return process.env.MCP_SKILL_PATH;let b=I(G(import.meta.url)),a=J(b,"..","bin","mcp-skill.mjs");return E(a)?a:null}async function u(b,a={}){let{token:t}=await T("github"),i=b.startsWith("https://")?b:`https://api.github.com${b}`,s={Authorization:`Bearer ${t}`,Accept:a.accept||"application/vnd.github.v3+json","User-Agent":"Zibby-App",...a.body?{"Content-Type":"application/json"}:{}},e=await fetch(i,{method:a.method||"GET",headers:s,body:a.body?JSON.stringify(a.body):void 0});if(!e.ok){let r=await e.text().catch(()=>"");throw new Error(`GitHub API ${e.status}: ${r.slice(0,300)}`)}return a.raw?e.text():e.json()}var oe={id:"github",serverName:"github",allowedTools:["mcp__github__*"],requiresIntegration:A.GITHUB,envKeys:["GITHUB_TOKEN"],description:"GitHub \u2014 issues, PRs, commits, code search, file reading",promptFragment:`## GitHub (connected)
1
+ import{existsSync as q}from"fs";import{fileURLToPath as I}from"url";import{dirname as G,resolve as C}from"path";import{resolveIntegrationToken as T}from"@zibby/core/backend-client.js";var P=Object.freeze({SENTRY:"sentry",JIRA:"jira",GITHUB:"github",GITLAB:"gitlab",SLACK:"slack",LARK:"lark",OPENAI_BILLING:"openai_billing",ANTHROPIC_BILLING:"anthropic_billing",CURSOR_ADMIN:"cursor_admin",NOTION:"notion",GOOGLE:"google",PLANE:"plane",LINEAR:"linear",FIGMA:"figma",HUBSPOT:"hubspot",OPEN_DESIGN:"open_design",LINKEDIN_PERSONAL:"linkedin_personal",LINKEDIN_BUSINESS:"linkedin_business",DISCORD:"discord"}),x=Object.freeze({sentry:{id:"sentry",name:"Sentry",connectPath:"/integrations?provider=sentry"},jira:{id:"jira",name:"Jira",connectPath:"/integrations?provider=jira"},github:{id:"github",name:"GitHub",connectPath:"/integrations?provider=github"},gitlab:{id:"gitlab",name:"GitLab",connectPath:"/integrations?provider=gitlab"},slack:{id:"slack",name:"Slack",connectPath:"/integrations?provider=slack"},lark:{id:"lark",name:"Lark",connectPath:"/integrations?provider=lark"},openai_billing:{id:"openai_billing",name:"OpenAI Admin",connectPath:"/integrations?provider=openai_billing"},anthropic_billing:{id:"anthropic_billing",name:"Anthropic Admin",connectPath:"/integrations?provider=anthropic_billing"},cursor_admin:{id:"cursor_admin",name:"Cursor Admin",connectPath:"/integrations?provider=cursor_admin"},notion:{id:"notion",name:"Notion",connectPath:"/integrations?provider=notion"},google:{id:"google",name:"Google Docs",connectPath:"/integrations?provider=google"},plane:{id:"plane",name:"Plane",connectPath:"/integrations?provider=plane"},linear:{id:"linear",name:"Linear",connectPath:"/integrations?provider=linear"},figma:{id:"figma",name:"Figma",connectPath:"/integrations?provider=figma"},hubspot:{id:"hubspot",name:"HubSpot",connectPath:"/integrations?provider=hubspot"},open_design:{id:"open_design",name:"OpenDesign",connectPath:"/integrations?provider=open_design"},linkedin_personal:{id:"linkedin_personal",name:"LinkedIn (Personal)",connectPath:"/integrations?provider=linkedin_personal"},linkedin_business:{id:"linkedin_business",name:"LinkedIn (Business)",connectPath:"/integrations?provider=linkedin_business"},discord:{id:"discord",name:"Discord",connectPath:"/integrations?provider=discord"}});import{spawn as U,execSync as M}from"child_process";import{existsSync as F,mkdirSync as B,readdirSync as z,statSync as K,readFileSync as W}from"fs";import{resolve as V,join as Y,basename as Z}from"path";function A(b,a,t,i,n="clone"){try{b(`git -C "${a}" remote set-url origin "${t}"`,{stdio:"pipe"})}catch(e){let r=String(e?.message||e);i&&(r=r.split(i).join("***")),console.error(`[${n}] WARNING: failed to strip token from .git/config: ${r}`)}}function J(){if(process.env.MCP_SKILL_PATH)return process.env.MCP_SKILL_PATH;let b=G(I(import.meta.url)),a=C(b,"..","bin","mcp-skill.mjs");return q(a)?a:null}async function u(b,a={}){let{token:t}=await T("github"),i=b.startsWith("https://")?b:`https://api.github.com${b}`,n={Authorization:`Bearer ${t}`,Accept:a.accept||"application/vnd.github.v3+json","User-Agent":"Zibby-App",...a.body?{"Content-Type":"application/json"}:{}},e=await fetch(i,{method:a.method||"GET",headers:n,body:a.body?JSON.stringify(a.body):void 0});if(!e.ok){let r=await e.text().catch(()=>"");throw new Error(`GitHub API ${e.status}: ${r.slice(0,300)}`)}return a.raw?e.text():e.json()}var oe={id:"github",serverName:"github",allowedTools:["mcp__github__*"],requiresIntegration:P.GITHUB,envKeys:["GITHUB_TOKEN"],description:"GitHub \u2014 issues, PRs, commits, code search, file reading",promptFragment:`## GitHub (connected)
2
2
  You have access to the user's GitHub repositories. Available tools:
3
3
 
4
4
  ### Discovery
@@ -41,6 +41,6 @@ When user says "check out repo-name" or "clone repo-name":
41
41
  3. STOP. Do not offer to inspect files or ask what to do next.
42
42
 
43
43
  When user just wants to "look at" or "read" files (not clone):
44
- - Use github_get_file to read individual files via API`,resolve(){let b=C();if(!b)return{command:null,args:[],env:{},description:this.description};let a={};for(let t of this.envKeys)process.env[t]&&(a[t]=process.env[t]);return{type:"stdio",command:"node",args:[b,"../dist/github.js","githubSkill"],env:a,description:this.description,alwaysLoad:!0}},async handleToolCall(b,a){try{switch(b){case"github_search_issues":{let t=a.query;if(!t)return JSON.stringify({error:"query is required"});let i=await u(`/search/issues?q=${encodeURIComponent(t)}&per_page=${a.limit||20}`),s=(i.items||[]).map(e=>({number:e.number,title:e.title,state:e.state,repo:e.repository_url?.split("/").slice(-2).join("/"),url:e.html_url,user:e.user?.login,isPR:!!e.pull_request,labels:(e.labels||[]).map(r=>r.name),createdAt:e.created_at}));return JSON.stringify({total:i.total_count,items:s})}case"github_search_code":{let t=a.query;if(!t)return JSON.stringify({error:"query is required"});let i=a.repo?`+repo:${a.repo}`:"",s=a.language?`+language:${a.language}`:"",e=await u(`/search/code?q=${encodeURIComponent(t)}${i}${s}&per_page=${a.limit||15}`),r=(e.items||[]).map(n=>({name:n.name,path:n.path,repo:n.repository?.full_name,url:n.html_url,score:n.score}));return JSON.stringify({total:e.total_count,items:r})}case"github_get_pr":{let{owner:t,repo:i,number:s}=a;if(!t||!i||!s)return JSON.stringify({error:"owner, repo, and number are required"});let e=await u(`/repos/${t}/${i}/pulls/${s}`);return JSON.stringify({number:e.number,title:e.title,state:e.state,merged:e.merged,body:e.body?.slice(0,5e3),user:e.user?.login,branch:e.head?.ref,headSha:e.head?.sha,base:e.base?.ref,changedFiles:e.changed_files,additions:e.additions,deletions:e.deletions,createdAt:e.created_at,mergedAt:e.merged_at,url:e.html_url,labels:(e.labels||[]).map(r=>r.name)})}case"github_get_pr_diff":{let{owner:t,repo:i,number:s}=a;if(!t||!i||!s)return JSON.stringify({error:"owner, repo, and number are required"});let e=await u(`/repos/${t}/${i}/pulls/${s}`,{accept:"application/vnd.github.v3.diff",raw:!0}),r=e.length>15e3;return JSON.stringify({number:s,diff:r?e.slice(0,15e3):e,truncated:r,totalLength:e.length})}case"github_list_pr_files":{let{owner:t,repo:i,number:s}=a;if(!t||!i||!s)return JSON.stringify({error:"owner, repo, and number are required"});let e=await u(`/repos/${t}/${i}/pulls/${s}/files?per_page=100`);return JSON.stringify({total:e.length,files:e.map(r=>({filename:r.filename,status:r.status,additions:r.additions,deletions:r.deletions,patch:r.patch?.slice(0,3e3)}))})}case"github_list_pr_comments":{let{owner:t,repo:i,number:s}=a;if(!t||!i||!s)return JSON.stringify({error:"owner, repo, and number are required"});let e=await u(`/repos/${t}/${i}/pulls/${s}/comments?per_page=50`),r=await u(`/repos/${t}/${i}/issues/${s}/comments?per_page=50`),n=[...e.map(o=>({type:"review",user:o.user?.login,body:o.body?.slice(0,1e3),path:o.path,line:o.line,createdAt:o.created_at})),...r.map(o=>({type:"issue",user:o.user?.login,body:o.body?.slice(0,1e3),createdAt:o.created_at}))].sort((o,d)=>new Date(o.createdAt)-new Date(d.createdAt));return JSON.stringify({total:n.length,comments:n})}case"github_get_review_thread":{let{owner:t,repo:i,number:s,commentId:e}=a||{};if(!t||!i||!s||!e)return JSON.stringify({error:"owner, repo, number, and commentId are required"});let r=await u(`/repos/${t}/${i}/pulls/comments/${e}`),n=r.in_reply_to_id||r.id,o=[];try{o=await u(`/repos/${t}/${i}/pulls/${s}/comments?per_page=100`)}catch{o=[r]}(!Array.isArray(o)||o.length===0)&&(o=[r]);let d=o.filter(c=>c.id===n||c.in_reply_to_id===n).sort((c,y)=>new Date(c.created_at)-new Date(y.created_at)),l=d.length?d:[r],p=l.find(c=>c.id===n)||l[0];return JSON.stringify({rootCommentId:n,path:p.path,line:p.line??p.original_line??null,side:p.side||"RIGHT",diffHunk:typeof p.diff_hunk=="string"?p.diff_hunk.slice(0,3e3):null,commitId:p.commit_id||p.original_commit_id||null,notes:l.map(c=>({id:c.id,user:c.user?.login,body:(c.body||"").slice(0,4e3),createdAt:c.created_at,isRoot:c.id===n,url:c.html_url}))})}case"github_reply_review_thread":{let{owner:t,repo:i,number:s,commentId:e,body:r}=a||{};if(!t||!i||!s||!e||!r)return JSON.stringify({error:"owner, repo, number, commentId, and body are required"});let n=await u(`/repos/${t}/${i}/pulls/${s}/comments/${e}/replies`,{method:"POST",body:{body:String(r)}});return JSON.stringify({ok:!0,id:n.id,url:n.html_url,inReplyTo:n.in_reply_to_id})}case"github_reply_issue_comment":{let{owner:t,repo:i,number:s,body:e}=a||{};if(!t||!i||!s||!e)return JSON.stringify({error:"owner, repo, number, and body are required"});let r=await u(`/repos/${t}/${i}/issues/${s}/comments`,{method:"POST",body:{body:String(e)}});return JSON.stringify({ok:!0,id:r.id,url:r.html_url})}case"github_create_review":{let{owner:t,repo:i,number:s,body:e,event:r,comments:n}=a||{};if(!t||!i||!s)return JSON.stringify({error:"owner, repo, and number are required"});let o=(r||"COMMENT").toUpperCase();if(!["COMMENT","APPROVE","REQUEST_CHANGES"].includes(o))return JSON.stringify({error:`event must be COMMENT, APPROVE, or REQUEST_CHANGES (got ${r})`});let d=Array.isArray(n)?n.filter(c=>c&&c.path&&c.body&&(c.line!=null||c.position!=null)).map(c=>{let y={path:c.path,body:String(c.body)};return c.line!=null?(y.line=Number(c.line),y.side=c.side==="LEFT"?"LEFT":"RIGHT"):y.position=Number(c.position),y}):[];if(o!=="APPROVE"&&!e&&d.length===0)return JSON.stringify({error:"a COMMENT or REQUEST_CHANGES review needs a body and/or inline comments"});let l={event:o};e&&(l.body=String(e)),d.length>0&&(l.comments=d);let p=await u(`/repos/${t}/${i}/pulls/${s}/reviews`,{method:"POST",body:l});return JSON.stringify({ok:!0,id:p.id,state:p.state,event:o,commentsPosted:d.length,url:p.html_url})}case"github_list_commits":{let{owner:t,repo:i,branch:s,path:e,limit:r}=a;if(!t||!i)return JSON.stringify({error:"owner and repo are required"});let n=`/repos/${t}/${i}/commits?per_page=${r||20}`;s&&(n+=`&sha=${encodeURIComponent(s)}`),e&&(n+=`&path=${encodeURIComponent(e)}`);let o=await u(n);return JSON.stringify({total:o.length,commits:o.map(d=>({sha:d.sha?.slice(0,8),fullSha:d.sha,message:d.commit?.message?.slice(0,300),author:d.commit?.author?.name,date:d.commit?.author?.date,url:d.html_url}))})}case"github_get_commit":{let{owner:t,repo:i,sha:s}=a;if(!t||!i||!s)return JSON.stringify({error:"owner, repo, and sha are required"});let e=await u(`/repos/${t}/${i}/commits/${s}`);return JSON.stringify({sha:e.sha?.slice(0,8),message:e.commit?.message,author:e.commit?.author?.name,date:e.commit?.author?.date,stats:e.stats,files:(e.files||[]).map(r=>({filename:r.filename,status:r.status,additions:r.additions,deletions:r.deletions,patch:r.patch?.slice(0,3e3)}))})}case"github_get_file":{let{owner:t,repo:i,path:s,ref:e}=a;if(!t||!i||!s)return JSON.stringify({error:"owner, repo, and path are required"});let r=`/repos/${t}/${i}/contents/${encodeURIComponent(s)}`;e&&(r+=`?ref=${encodeURIComponent(e)}`);let n=await u(r);if(n.type!=="file")return Array.isArray(n)?JSON.stringify({type:"directory",path:s,entries:n.map(l=>({name:l.name,type:l.type,size:l.size,path:l.path}))}):JSON.stringify({error:`Not a file: ${n.type}`});let o=Buffer.from(n.content||"","base64").toString("utf-8"),d=o.length>2e4;return JSON.stringify({path:n.path,size:n.size,sha:n.sha?.slice(0,8),content:d?o.slice(0,2e4):o,truncated:d})}case"github_get_user":try{let t=await u("/installation/repositories?per_page=1");if(t.repositories&&t.repositories.length>0){let i=t.repositories[0],s=i.owner.login,e=i.owner.type,r=e==="Organization"?`/orgs/${s}`:`/users/${s}`,n=await u(r);return JSON.stringify({login:n.login,name:n.name||n.login,avatar:n.avatar_url,bio:n.bio||n.description,type:e,isOrg:e==="Organization",publicRepos:n.public_repos,message:"Showing GitHub App installation owner (GitHub Apps cannot access /user endpoint)"})}return JSON.stringify({error:"No repositories accessible to this GitHub App installation"})}catch(t){return JSON.stringify({error:`GitHub App cannot access /user endpoint. Use github_list_repos instead. (${t.message})`})}case"github_list_orgs":try{let i=(await u("/installation/repositories?per_page=100")).repositories||[],s=new Map;for(let r of i)r.owner.type==="Organization"&&(s.has(r.owner.login)||s.set(r.owner.login,{login:r.owner.login,description:null,url:r.owner.url}));let e=Array.from(s.values());return JSON.stringify({count:e.length,orgs:e,message:"Extracted from accessible repositories (GitHub Apps cannot access /user/orgs directly)"})}catch(t){return JSON.stringify({error:`GitHub App cannot list orgs via /user/orgs. Error: ${t.message}`})}case"github_clone":{let g=function(w){let m=w.replace(/^~(?=$|\/|\\)/,y);return n(m)},{owner:t,repo:i,destination:s}=a;if(!t||!i)return JSON.stringify({error:"owner and repo are required"});let{execSync:e}=await import("child_process"),{join:r,resolve:n}=await import("path"),{existsSync:o,mkdirSync:d}=await import("fs"),{homedir:l,platform:p}=await import("os"),{token:c}=await T("github"),y=l(),_=s?g(s):r(y,"zibby-repos"),f=r(_,i);if(d(_,{recursive:!0}),o(f))return JSON.stringify({error:`Directory ${f} already exists. Remove it first or use a different destination.`,existingPath:f});let R=`https://x-access-token:${c}@github.com/${t}/${i}.git`;try{e(`git clone ${R} "${f}"`,{stdio:"pipe"});let w=`https://github.com/${t}/${i}.git`;P(e,f,w,c,"github_clone");let m=p()==="win32",h;return m?h=e(`dir "${f}"`,{encoding:"utf-8",shell:"cmd.exe"}):h=e(`ls -la "${f}"`,{encoding:"utf-8"}),JSON.stringify({success:!0,path:f,message:`Cloned ${t}/${i} to ${f}`,contents:h.split(`
44
+ - Use github_get_file to read individual files via API`,resolve(){let b=J();if(!b)return{command:null,args:[],env:{},description:this.description};let a={};for(let t of this.envKeys)process.env[t]&&(a[t]=process.env[t]);return{type:"stdio",command:"node",args:[b,"../dist/github.js","githubSkill"],env:a,description:this.description,alwaysLoad:!0}},async handleToolCall(b,a){try{switch(b){case"github_search_issues":{let t=a.query;if(!t)return JSON.stringify({error:"query is required"});let i=await u(`/search/issues?q=${encodeURIComponent(t)}&per_page=${a.limit||20}`),n=(i.items||[]).map(e=>({number:e.number,title:e.title,state:e.state,repo:e.repository_url?.split("/").slice(-2).join("/"),url:e.html_url,user:e.user?.login,isPR:!!e.pull_request,labels:(e.labels||[]).map(r=>r.name),createdAt:e.created_at}));return JSON.stringify({total:i.total_count,items:n})}case"github_search_code":{let t=a.query;if(!t)return JSON.stringify({error:"query is required"});let i=a.repo?`+repo:${a.repo}`:"",n=a.language?`+language:${a.language}`:"",e=await u(`/search/code?q=${encodeURIComponent(t)}${i}${n}&per_page=${a.limit||15}`),r=(e.items||[]).map(s=>({name:s.name,path:s.path,repo:s.repository?.full_name,url:s.html_url,score:s.score}));return JSON.stringify({total:e.total_count,items:r})}case"github_get_pr":{let{owner:t,repo:i,number:n}=a;if(!t||!i||!n)return JSON.stringify({error:"owner, repo, and number are required"});let e=await u(`/repos/${t}/${i}/pulls/${n}`);return JSON.stringify({number:e.number,title:e.title,state:e.state,merged:e.merged,body:e.body?.slice(0,5e3),user:e.user?.login,branch:e.head?.ref,headSha:e.head?.sha,base:e.base?.ref,changedFiles:e.changed_files,additions:e.additions,deletions:e.deletions,createdAt:e.created_at,mergedAt:e.merged_at,url:e.html_url,labels:(e.labels||[]).map(r=>r.name)})}case"github_get_pr_diff":{let{owner:t,repo:i,number:n}=a;if(!t||!i||!n)return JSON.stringify({error:"owner, repo, and number are required"});let e=await u(`/repos/${t}/${i}/pulls/${n}`,{accept:"application/vnd.github.v3.diff",raw:!0}),r=e.length>15e3;return JSON.stringify({number:n,diff:r?e.slice(0,15e3):e,truncated:r,totalLength:e.length})}case"github_list_pr_files":{let{owner:t,repo:i,number:n}=a;if(!t||!i||!n)return JSON.stringify({error:"owner, repo, and number are required"});let e=await u(`/repos/${t}/${i}/pulls/${n}/files?per_page=100`);return JSON.stringify({total:e.length,files:e.map(r=>({filename:r.filename,status:r.status,additions:r.additions,deletions:r.deletions,patch:r.patch?.slice(0,3e3)}))})}case"github_list_pr_comments":{let{owner:t,repo:i,number:n}=a;if(!t||!i||!n)return JSON.stringify({error:"owner, repo, and number are required"});let e=await u(`/repos/${t}/${i}/pulls/${n}/comments?per_page=50`),r=await u(`/repos/${t}/${i}/issues/${n}/comments?per_page=50`),s=[...e.map(o=>({type:"review",user:o.user?.login,body:o.body?.slice(0,1e3),path:o.path,line:o.line,createdAt:o.created_at})),...r.map(o=>({type:"issue",user:o.user?.login,body:o.body?.slice(0,1e3),createdAt:o.created_at}))].sort((o,m)=>new Date(o.createdAt)-new Date(m.createdAt));return JSON.stringify({total:s.length,comments:s})}case"github_get_review_thread":{let{owner:t,repo:i,number:n,commentId:e}=a||{};if(!t||!i||!n||!e)return JSON.stringify({error:"owner, repo, number, and commentId are required"});let r=await u(`/repos/${t}/${i}/pulls/comments/${e}`),s=r.in_reply_to_id||r.id,o=[];try{o=await u(`/repos/${t}/${i}/pulls/${n}/comments?per_page=100`)}catch{o=[r]}(!Array.isArray(o)||o.length===0)&&(o=[r]);let m=o.filter(c=>c.id===s||c.in_reply_to_id===s).sort((c,g)=>new Date(c.created_at)-new Date(g.created_at)),l=m.length?m:[r],p=l.find(c=>c.id===s)||l[0];return JSON.stringify({rootCommentId:s,path:p.path,line:p.line??p.original_line??null,side:p.side||"RIGHT",diffHunk:typeof p.diff_hunk=="string"?p.diff_hunk.slice(0,3e3):null,commitId:p.commit_id||p.original_commit_id||null,notes:l.map(c=>({id:c.id,user:c.user?.login,body:(c.body||"").slice(0,4e3),createdAt:c.created_at,isRoot:c.id===s,url:c.html_url}))})}case"github_reply_review_thread":{let{owner:t,repo:i,number:n,commentId:e,body:r}=a||{};if(!t||!i||!n||!e||!r)return JSON.stringify({error:"owner, repo, number, commentId, and body are required"});let s=await u(`/repos/${t}/${i}/pulls/${n}/comments/${e}/replies`,{method:"POST",body:{body:String(r)}});return JSON.stringify({ok:!0,id:s.id,url:s.html_url,inReplyTo:s.in_reply_to_id})}case"github_reply_issue_comment":{let{owner:t,repo:i,number:n,body:e}=a||{};if(!t||!i||!n||!e)return JSON.stringify({error:"owner, repo, number, and body are required"});let r=await u(`/repos/${t}/${i}/issues/${n}/comments`,{method:"POST",body:{body:String(e)}});return JSON.stringify({ok:!0,id:r.id,url:r.html_url})}case"github_create_review":{let{owner:t,repo:i,number:n,body:e,event:r,comments:s}=a||{};if(!t||!i||!n)return JSON.stringify({error:"owner, repo, and number are required"});let o=(r||"COMMENT").toUpperCase();if(!["COMMENT","APPROVE","REQUEST_CHANGES"].includes(o))return JSON.stringify({error:`event must be COMMENT, APPROVE, or REQUEST_CHANGES (got ${r})`});let m=Array.isArray(s)?s.filter(c=>c&&c.path&&c.body&&(c.line!=null||c.position!=null)).map(c=>{let g={path:c.path,body:String(c.body)};return c.line!=null?(g.line=Number(c.line),g.side=c.side==="LEFT"?"LEFT":"RIGHT"):g.position=Number(c.position),g}):[];if(o!=="APPROVE"&&!e&&m.length===0)return JSON.stringify({error:"a COMMENT or REQUEST_CHANGES review needs a body and/or inline comments"});let l={event:o};e&&(l.body=String(e)),m.length>0&&(l.comments=m);let p=await u(`/repos/${t}/${i}/pulls/${n}/reviews`,{method:"POST",body:l});return JSON.stringify({ok:!0,id:p.id,state:p.state,event:o,commentsPosted:m.length,url:p.html_url})}case"github_list_commits":{let{owner:t,repo:i,branch:n,path:e,limit:r,since:s,until:o,page:m}=a;if(!t||!i)return JSON.stringify({error:"owner and repo are required"});let l=Math.min(Number(r)||20,100),p=`/repos/${t}/${i}/commits?per_page=${l}&page=${Number(m)||1}`;n&&(p+=`&sha=${encodeURIComponent(n)}`),e&&(p+=`&path=${encodeURIComponent(e)}`),s&&(p+=`&since=${encodeURIComponent(s)}`),o&&(p+=`&until=${encodeURIComponent(o)}`);let c=await u(p);return JSON.stringify({total:c.length,page:Number(m)||1,hasMore:c.length>=l,commits:c.map(g=>({sha:g.sha?.slice(0,8),fullSha:g.sha,message:g.commit?.message?.slice(0,300),author:g.commit?.author?.name,authorEmail:g.commit?.author?.email,date:g.commit?.author?.date,url:g.html_url}))})}case"github_get_commit":{let{owner:t,repo:i,sha:n}=a;if(!t||!i||!n)return JSON.stringify({error:"owner, repo, and sha are required"});let e=await u(`/repos/${t}/${i}/commits/${n}`);return JSON.stringify({sha:e.sha?.slice(0,8),message:e.commit?.message,author:e.commit?.author?.name,date:e.commit?.author?.date,stats:e.stats,files:(e.files||[]).map(r=>({filename:r.filename,status:r.status,additions:r.additions,deletions:r.deletions,patch:r.patch?.slice(0,3e3)}))})}case"github_get_file":{let{owner:t,repo:i,path:n,ref:e}=a;if(!t||!i||!n)return JSON.stringify({error:"owner, repo, and path are required"});let r=`/repos/${t}/${i}/contents/${encodeURIComponent(n)}`;e&&(r+=`?ref=${encodeURIComponent(e)}`);let s=await u(r);if(s.type!=="file")return Array.isArray(s)?JSON.stringify({type:"directory",path:n,entries:s.map(l=>({name:l.name,type:l.type,size:l.size,path:l.path}))}):JSON.stringify({error:`Not a file: ${s.type}`});let o=Buffer.from(s.content||"","base64").toString("utf-8"),m=o.length>2e4;return JSON.stringify({path:s.path,size:s.size,sha:s.sha?.slice(0,8),content:m?o.slice(0,2e4):o,truncated:m})}case"github_get_user":try{let t=await u("/installation/repositories?per_page=1");if(t.repositories&&t.repositories.length>0){let i=t.repositories[0],n=i.owner.login,e=i.owner.type,r=e==="Organization"?`/orgs/${n}`:`/users/${n}`,s=await u(r);return JSON.stringify({login:s.login,name:s.name||s.login,avatar:s.avatar_url,bio:s.bio||s.description,type:e,isOrg:e==="Organization",publicRepos:s.public_repos,message:"Showing GitHub App installation owner (GitHub Apps cannot access /user endpoint)"})}return JSON.stringify({error:"No repositories accessible to this GitHub App installation"})}catch(t){return JSON.stringify({error:`GitHub App cannot access /user endpoint. Use github_list_repos instead. (${t.message})`})}case"github_list_orgs":try{let i=(await u("/installation/repositories?per_page=100")).repositories||[],n=new Map;for(let r of i)r.owner.type==="Organization"&&(n.has(r.owner.login)||n.set(r.owner.login,{login:r.owner.login,description:null,url:r.owner.url}));let e=Array.from(n.values());return JSON.stringify({count:e.length,orgs:e,message:"Extracted from accessible repositories (GitHub Apps cannot access /user/orgs directly)"})}catch(t){return JSON.stringify({error:`GitHub App cannot list orgs via /user/orgs. Error: ${t.message}`})}case"github_clone":{let h=function(w){let d=w.replace(/^~(?=$|\/|\\)/,g);return s(d)},{owner:t,repo:i,destination:n}=a;if(!t||!i)return JSON.stringify({error:"owner and repo are required"});let{execSync:e}=await import("child_process"),{join:r,resolve:s}=await import("path"),{existsSync:o,mkdirSync:m}=await import("fs"),{homedir:l,platform:p}=await import("os"),{token:c}=await T("github"),g=l(),_=n?h(n):r(g,"zibby-repos"),f=r(_,i);if(m(_,{recursive:!0}),o(f))return JSON.stringify({error:`Directory ${f} already exists. Remove it first or use a different destination.`,existingPath:f});let R=`https://x-access-token:${c}@github.com/${t}/${i}.git`;try{e(`git clone ${R} "${f}"`,{stdio:"pipe"});let w=`https://github.com/${t}/${i}.git`;A(e,f,w,c,"github_clone");let d=p()==="win32",y;return d?y=e(`dir "${f}"`,{encoding:"utf-8",shell:"cmd.exe"}):y=e(`ls -la "${f}"`,{encoding:"utf-8"}),JSON.stringify({success:!0,path:f,message:`Cloned ${t}/${i} to ${f}`,contents:y.split(`
45
45
  `).slice(0,30).join(`
46
- `),instructions:"IMPORTANT: Show the contents field to the user - it contains the directory listing."})}catch(w){let h=String(w.message||w).split(c).join("***").replace(/x-access-token:[^@]*@/g,"x-access-token:***@");return JSON.stringify({error:`Clone failed: ${h}`})}}case"github_search_repos":{let{query:t,limit:i}=a;if(!t)return JSON.stringify({error:"query is required"});let s=await this.handleToolCall("github_list_repos",{limit:200},{}),e=JSON.parse(s);if(e.error)return JSON.stringify(e);let r=t.toLowerCase(),n=e.repos.filter(o=>o.name.toLowerCase().includes(r)||o.fullName.toLowerCase().includes(r)||o.description&&o.description.toLowerCase().includes(r));return JSON.stringify({query:t,count:n.length,repos:n.slice(0,i||20)})}case"github_list_repos":{let{owner:t,type:i,sort:s,direction:e,limit:r,query:n}=a,o=100,d=r||200,l=[],p=m=>({name:m.name,fullName:m.full_name,private:m.private,description:m.description,language:m.language,defaultBranch:m.default_branch,updatedAt:m.updated_at,stars:m.stargazers_count,url:m.html_url,fullPath:m.full_name,webUrl:m.html_url,visibility:m.visibility||(m.private?"private":"public")}),c=m=>{if(!n)return!0;let h=String(n).toLowerCase();return m.name&&m.name.toLowerCase().includes(h)||m.fullName&&m.fullName.toLowerCase().includes(h)||m.description&&m.description.toLowerCase().includes(h)};if(!t){let m=1,h=!0;for(;h&&l.length<d;){let v=`/installation/repositories?per_page=${o}&page=${m}`,O=(await u(v)).repositories||[];if(O.length===0)break;l=l.concat(O),h=O.length===o,m++}let S=l.map(p).filter(c),$=S.slice(0,d),q=S.length>$.length,N=$.filter(v=>v.private).length,k=$.filter(v=>!v.private).length;return JSON.stringify({count:$.length,repos:$,truncated:q,privateCount:N,publicCount:k,message:`Found ${N} private and ${k} public repos`})}let y=await u(`/orgs/${t}`).then(()=>!0).catch(()=>!1),g=1,_=!0;for(;_&&l.length<d;){let m;y?m=`/orgs/${t}/repos?per_page=${o}&page=${g}&type=${i||"all"}&sort=${s||"updated"}&direction=${e||"desc"}`:m=`/users/${t}/repos?per_page=${o}&page=${g}&type=${i||"all"}&sort=${s||"updated"}&direction=${e||"desc"}`;let h=await u(m),S=Array.isArray(h)?h:[];if(S.length===0)break;l=l.concat(S),_=S.length===o,g++}let f=l.map(p).filter(c),R=f.slice(0,d),w=f.length>R.length;return JSON.stringify({count:R.length,repos:R,truncated:w})}case"github_create_pr":{let{owner:t,repo:i,head:s,title:e}=a||{};if(!t||!i||!s||!e)return JSON.stringify({error:"owner, repo, head (source branch), and title are required"});let r=a.base;if(!r)try{r=(await u(`/repos/${t}/${i}`)).default_branch||"main"}catch{r="main"}let n={title:String(e),head:String(s),base:String(r),body:a.body?String(a.body):"",draft:!!a.draft};try{let o=await u(`/repos/${t}/${i}/pulls`,{method:"POST",body:n});return JSON.stringify({success:!0,pr_url:o.html_url,number:o.number,branch:s,base:r,repo:`${t}/${i}`,provider:"github",draft:!!o.draft,state:o.state})}catch(o){let d=String(o.message||o);if(/GitHub API 422/.test(d))return JSON.stringify({success:!1,branch:s,base:r,repo:`${t}/${i}`,provider:"github",skippedReason:d});throw o}}case"github_merge_pr":{let{owner:t,repo:i,number:s}=a||{};if(!t||!i||!s)return JSON.stringify({error:"owner, repo, and number are required"});let e=a.mergeMethod||"squash";if(!["merge","squash","rebase"].includes(e))return JSON.stringify({error:`mergeMethod must be merge, squash, or rebase (got ${e})`});let r={merge_method:e};a.commitTitle&&(r.commit_title=String(a.commitTitle)),a.commitMessage&&(r.commit_message=String(a.commitMessage));try{let n=await u(`/repos/${t}/${i}/pulls/${s}/merge`,{method:"PUT",body:r});return JSON.stringify({success:!0,merged:!0,sha:n.sha,number:s,provider:"github"})}catch(n){let o=String(n.message||n);if(/GitHub API (405|409|404)/.test(o))return JSON.stringify({success:!1,number:s,provider:"github",skippedReason:o});throw n}}case"github_create_issue":{let{owner:t,repo:i,title:s,body:e}=a;if(!t||!i||!s)return JSON.stringify({error:"owner, repo, and title are required"});let r=await u(`/repos/${t}/${i}/issues`,{method:"POST",body:{title:s,body:e||""}});return JSON.stringify({number:r.number,url:r.html_url,title:r.title})}case"github_list_issues":{let{owner:t,repo:i,state:s,labels:e,since:r,assignee:n,sort:o,direction:d,limit:l}=a||{};if(!t||!i)return JSON.stringify({error:"owner and repo are required"});let p=new URLSearchParams;p.set("state",s||"open"),p.set("per_page",String(l||30)),p.set("sort",o||"updated"),p.set("direction",d||"desc"),e&&p.set("labels",Array.isArray(e)?e.join(","):e),r&&p.set("since",r),n&&p.set("assignee",n);let c=await u(`/repos/${t}/${i}/issues?${p.toString()}`),y=(Array.isArray(c)?c:[]).filter(g=>!g.pull_request).map(g=>({number:g.number,title:g.title,state:g.state,labels:(g.labels||[]).map(_=>typeof _=="string"?_:_.name),assignee:g.assignee?.login||null,assignees:(g.assignees||[]).map(_=>_.login),user:g.user?.login,comments:g.comments,url:g.html_url,createdAt:g.created_at,updatedAt:g.updated_at}));return JSON.stringify({count:y.length,issues:y})}case"github_get_issue":{let{owner:t,repo:i,number:s}=a||{};if(!t||!i||!s)return JSON.stringify({error:"owner, repo, and number are required"});let e=await u(`/repos/${t}/${i}/issues/${s}`);return e.pull_request?JSON.stringify({error:`#${s} is a pull request, not an issue`,isPR:!0}):JSON.stringify({number:e.number,title:e.title,body:e.body||"",state:e.state,stateReason:e.state_reason||null,labels:(e.labels||[]).map(r=>typeof r=="string"?r:r.name),assignee:e.assignee?.login||null,assignees:(e.assignees||[]).map(r=>r.login),user:e.user?.login,milestone:e.milestone?.title||null,comments:e.comments,url:e.html_url,createdAt:e.created_at,updatedAt:e.updated_at,closedAt:e.closed_at})}case"github_get_issue_comments":{let{owner:t,repo:i,number:s,limit:e}=a||{};if(!t||!i||!s)return JSON.stringify({error:"owner, repo, and number are required"});let r=await u(`/repos/${t}/${i}/issues/${s}/comments?per_page=${e||100}`),n=(Array.isArray(r)?r:[]).map(o=>({id:o.id,user:o.user?.login,body:o.body||"",createdAt:o.created_at,updatedAt:o.updated_at,url:o.html_url}));return JSON.stringify({count:n.length,comments:n})}case"github_add_issue_comment":{let{owner:t,repo:i,number:s,body:e}=a||{};if(!t||!i||!s||!e)return JSON.stringify({error:"owner, repo, number, and body are required"});let r=await u(`/repos/${t}/${i}/issues/${s}/comments`,{method:"POST",body:{body:e}});return JSON.stringify({ok:!0,id:r.id,url:r.html_url})}case"github_close_issue":{let{owner:t,repo:i,number:s,stateReason:e}=a||{};if(!t||!i||!s)return JSON.stringify({error:"owner, repo, and number are required"});let r={state:"closed"};e&&(r.state_reason=e);let n=await u(`/repos/${t}/${i}/issues/${s}`,{method:"PATCH",body:r});return JSON.stringify({ok:!0,number:n.number,state:n.state,stateReason:n.state_reason||null,url:n.html_url})}case"github_reopen_issue":{let{owner:t,repo:i,number:s}=a||{};if(!t||!i||!s)return JSON.stringify({error:"owner, repo, and number are required"});let e=await u(`/repos/${t}/${i}/issues/${s}`,{method:"PATCH",body:{state:"open"}});return JSON.stringify({ok:!0,number:e.number,state:e.state,url:e.html_url})}case"github_label_issue":{let{owner:t,repo:i,number:s,labels:e,mode:r}=a||{};if(!t||!i||!s)return JSON.stringify({error:"owner, repo, and number are required"});let n=Array.isArray(e)?e:e?[e]:[];if(!n.length)return JSON.stringify({error:"labels (string or array) is required"});let o=r||"add";if(o==="set"){let l=await u(`/repos/${t}/${i}/issues/${s}`,{method:"PATCH",body:{labels:n}});return JSON.stringify({ok:!0,number:l.number,labels:(l.labels||[]).map(p=>typeof p=="string"?p:p.name)})}if(o==="remove"){for(let p of n)await u(`/repos/${t}/${i}/issues/${s}/labels/${encodeURIComponent(p)}`,{method:"DELETE"});let l=await u(`/repos/${t}/${i}/issues/${s}`);return JSON.stringify({ok:!0,number:l.number,labels:(l.labels||[]).map(p=>typeof p=="string"?p:p.name)})}let d=await u(`/repos/${t}/${i}/issues/${s}/labels`,{method:"POST",body:{labels:n}});return JSON.stringify({ok:!0,number:s,labels:(Array.isArray(d)?d:[]).map(l=>typeof l=="string"?l:l.name)})}default:return JSON.stringify({error:`Unknown tool: ${b}`})}}catch(t){return JSON.stringify({error:t.message})}},tools:[{name:"github_get_user",description:"Get the authenticated GitHub user profile and their organizations",input_schema:{type:"object",properties:{}}},{name:"github_list_orgs",description:"List GitHub organizations the authenticated user belongs to",input_schema:{type:"object",properties:{}}},{name:"github_list_repos",description:"List the repositories this token/installation can access (omit owner) \u2014 or a specific user/org's repos (pass owner). Use this to discover a RELATED repo worth cloning when a change's correctness depends on another accessible repo. Each repo carries a normalized { fullPath, name, webUrl, defaultBranch, visibility } shape (identical to gitlab_list_projects) alongside legacy fields, plus a truncated flag.",input_schema:{type:"object",properties:{owner:{type:"string",description:"Org or user login. Omit to list every repo your token/installation can access."},query:{type:"string",description:"Optional term matched against repo name/full-name/description"},type:{type:"string",enum:["all","public","private","forks","sources","member"],description:"Filter by type (default: all)"},sort:{type:"string",enum:["created","updated","pushed","full_name"],description:"Sort field (default: updated)"},direction:{type:"string",enum:["asc","desc"],description:"Sort direction (default: desc)"},limit:{type:"number",description:"Max repos to return (default: 200, hard-capped at the fetch ceiling)"}}}},{name:"github_clone",description:'Clone a GitHub repository to the local filesystem. Use when user says "check out" or "clone" a repo.',input_schema:{type:"object",properties:{owner:{type:"string",description:"Repository owner (user or org name)"},repo:{type:"string",description:"Repository name"},destination:{type:"string",description:"Destination directory. Accepts absolute paths, ~-prefixed paths, or relative names. Defaults to ~/zibby-repos/<repo>."}},required:["owner","repo"]}},{name:"github_search_repos",description:"Search accessible repositories by name or description. Use this when the user asks to find a specific repo.",input_schema:{type:"object",properties:{query:{type:"string",description:'Search term to match against repo name or description (e.g., "electron", "my-app")'},limit:{type:"number",description:"Max results (default: 20)"}},required:["query"]}},{name:"github_search_issues",description:"Search GitHub issues and pull requests",input_schema:{type:"object",properties:{query:{type:"string",description:'GitHub search query (e.g. "SCRUM-123", "login bug repo:org/app")'},limit:{type:"number",description:"Max results (default: 20)"}},required:["query"]}},{name:"github_search_code",description:"Search code across GitHub repositories by keyword",input_schema:{type:"object",properties:{query:{type:"string",description:'Code search query (e.g. "handleLogin", "class AuthService")'},repo:{type:"string",description:'Scope to a specific repo (e.g. "org/app"). Optional.'},language:{type:"string",description:'Filter by language (e.g. "javascript", "python"). Optional.'},limit:{type:"number",description:"Max results (default: 15)"}},required:["query"]}},{name:"github_get_pr",description:"Get details of a pull request \u2014 title, description, branch, stats",input_schema:{type:"object",properties:{owner:{type:"string",description:"Repository owner"},repo:{type:"string",description:"Repository name"},number:{type:"number",description:"PR number"}},required:["owner","repo","number"]}},{name:"github_get_pr_diff",description:"Get the unified diff of a pull request \u2014 the actual code changes",input_schema:{type:"object",properties:{owner:{type:"string",description:"Repository owner"},repo:{type:"string",description:"Repository name"},number:{type:"number",description:"PR number"}},required:["owner","repo","number"]}},{name:"github_list_pr_files",description:"List files changed in a PR with per-file patches",input_schema:{type:"object",properties:{owner:{type:"string",description:"Repository owner"},repo:{type:"string",description:"Repository name"},number:{type:"number",description:"PR number"}},required:["owner","repo","number"]}},{name:"github_list_pr_comments",description:"Get all review and issue comments on a PR",input_schema:{type:"object",properties:{owner:{type:"string",description:"Repository owner"},repo:{type:"string",description:"Repository name"},number:{type:"number",description:"PR number"}},required:["owner","repo","number"]}},{name:"github_get_review_thread",description:"Read a PR review-comment THREAD given any comment id in it: the root review comment + all its replies, plus the anchored diff context (file, line, the original diff hunk). Use this to understand a human's reply to a previous review comment before replying in-thread.",input_schema:{type:"object",properties:{owner:{type:"string",description:"Repository owner"},repo:{type:"string",description:"Repository name"},number:{type:"number",description:"PR number"},commentId:{type:"number",description:"Any review-comment id in the thread (the root or any reply)"}},required:["owner","repo","number","commentId"]}},{name:"github_reply_review_thread",description:"Reply IN-THREAD to an existing PR review-comment thread (a conversational reply nested under the thread the human commented on \u2014 NOT a fresh full review). Pass any comment id in the thread.",input_schema:{type:"object",properties:{owner:{type:"string",description:"Repository owner"},repo:{type:"string",description:"Repository name"},number:{type:"number",description:"PR number"},commentId:{type:"number",description:"Any review-comment id in the thread to reply to"},body:{type:"string",description:"The reply text (markdown)"}},required:["owner","repo","number","commentId","body"]}},{name:"github_reply_issue_comment",description:"Post a reply on a PR's top-level conversation (a new issue comment on the PR). Use when the human replied to a non-inline/summary comment rather than an inline review thread. Quote or @-mention for context since issue comments are not threaded.",input_schema:{type:"object",properties:{owner:{type:"string",description:"Repository owner"},repo:{type:"string",description:"Repository name"},number:{type:"number",description:"PR number"},body:{type:"string",description:"The reply text (markdown)"}},required:["owner","repo","number","body"]}},{name:"github_create_review",description:"Post a review on a pull request: a summary body plus optional inline comments anchored to file/line, with an event (COMMENT, APPROVE, or REQUEST_CHANGES). Use this to deliver a code review back to the PR.",input_schema:{type:"object",properties:{owner:{type:"string",description:"Repository owner"},repo:{type:"string",description:"Repository name"},number:{type:"number",description:"PR number"},body:{type:"string",description:"The review summary (markdown). Shown as the top-level review comment."},event:{type:"string",enum:["COMMENT","APPROVE","REQUEST_CHANGES"],description:"Review verdict. Default COMMENT (no approval state). Use REQUEST_CHANGES for blocking issues."},comments:{type:"array",description:"Optional inline comments, each anchored to a changed line.",items:{type:"object",properties:{path:{type:"string",description:"File path as it appears in the diff"},line:{type:"number",description:"Line number in the file's NEW version (the right side of the diff)"},side:{type:"string",enum:["LEFT","RIGHT"],description:"RIGHT (new) or LEFT (old). Default RIGHT."},body:{type:"string",description:"The inline comment text (markdown)"}},required:["path","line","body"]}}},required:["owner","repo","number"]}},{name:"github_list_commits",description:"List recent commits on a branch, optionally filtered by file path",input_schema:{type:"object",properties:{owner:{type:"string",description:"Repository owner"},repo:{type:"string",description:"Repository name"},branch:{type:"string",description:"Branch name (default: repo default branch)"},path:{type:"string",description:"Filter commits touching this file path"},limit:{type:"number",description:"Max commits (default: 20)"}},required:["owner","repo"]}},{name:"github_get_commit",description:"Get details of a specific commit \u2014 message, stats, file diffs",input_schema:{type:"object",properties:{owner:{type:"string",description:"Repository owner"},repo:{type:"string",description:"Repository name"},sha:{type:"string",description:"Commit SHA (full or short)"}},required:["owner","repo","sha"]}},{name:"github_get_file",description:"Read a file (or list a directory) from a GitHub repo. Works on any branch/ref.",input_schema:{type:"object",properties:{owner:{type:"string",description:"Repository owner"},repo:{type:"string",description:"Repository name"},path:{type:"string",description:'File or directory path (e.g. "src/auth/login.ts")'},ref:{type:"string",description:"Branch, tag, or commit SHA (default: repo default branch)"}},required:["owner","repo","path"]}},{name:"github_create_pr",description:"Open a pull request on GitHub (POST /repos/{owner}/{repo}/pulls). The head (source) branch must already be pushed. Returns the REAL pr_url from GitHub \u2014 never fabricate a PR url. Expected business outcomes (no commits between base and head, a PR already exists for this branch, base==head, missing head) return { success:false, skippedReason } rather than erroring.",input_schema:{type:"object",properties:{owner:{type:"string",description:"Repository owner"},repo:{type:"string",description:"Repository name"},head:{type:"string",description:'Source branch to merge FROM (must already be pushed). For a cross-fork PR use "fork-owner:branch".'},base:{type:"string",description:"Target branch to merge INTO (default: the repo's default branch)"},title:{type:"string",description:"PR title"},body:{type:"string",description:"PR description (markdown)"},draft:{type:"boolean",description:"Open as a draft PR (default: false)"}},required:["owner","repo","head","title"]}},{name:"github_merge_pr",description:"Merge a pull request on GitHub (PUT /repos/{owner}/{repo}/pulls/{number}/merge). mergeMethod is merge | squash | rebase (default squash). Returns { success:true, merged:true, sha } with the REAL merge SHA from GitHub. Expected non-mergeable outcomes (405 = draft / failing checks / branch protection, 409 = head sha moved / conflict, 404 = not found) return { success:false, skippedReason } rather than erroring.",input_schema:{type:"object",properties:{owner:{type:"string",description:"Repository owner"},repo:{type:"string",description:"Repository name"},number:{type:"number",description:"PR number to merge"},mergeMethod:{type:"string",enum:["merge","squash","rebase"],description:"How to merge (default: squash)"},commitTitle:{type:"string",description:"Title for the merge/squash commit (optional)"},commitMessage:{type:"string",description:"Body for the merge/squash commit (optional)"}},required:["owner","repo","number"]}},{name:"github_create_issue",description:"Create a GitHub issue",input_schema:{type:"object",properties:{owner:{type:"string",description:"Repository owner"},repo:{type:"string",description:"Repository name"},title:{type:"string",description:"Issue title"},body:{type:"string",description:"Issue body (markdown)"}},required:["owner","repo","title"]}},{name:"github_list_issues",description:"List issues in a repo (excludes pull requests). Filter by state, labels, and an updated-since cursor for polling.",input_schema:{type:"object",properties:{owner:{type:"string",description:"Repository owner"},repo:{type:"string",description:"Repository name"},state:{type:"string",enum:["open","closed","all"],description:"Filter by state (default: open)"},labels:{type:"array",items:{type:"string"},description:"Only issues carrying ALL of these labels"},since:{type:"string",description:"ISO-8601 timestamp; only issues updated at/after this (polling cursor)"},assignee:{type:"string",description:'Filter by assignee login, "none", or "*"'},sort:{type:"string",enum:["created","updated","comments"],description:"Sort field (default: updated)"},direction:{type:"string",enum:["asc","desc"],description:"Sort direction (default: desc)"},limit:{type:"number",description:"Max issues (default: 30, max 100 per page)"}},required:["owner","repo"]}},{name:"github_get_issue",description:"Get a single GitHub issue with full detail (title, body, state, labels, assignee, url)",input_schema:{type:"object",properties:{owner:{type:"string",description:"Repository owner"},repo:{type:"string",description:"Repository name"},number:{type:"number",description:"Issue number"}},required:["owner","repo","number"]}},{name:"github_get_issue_comments",description:"Get the comment thread on a GitHub issue (chronological)",input_schema:{type:"object",properties:{owner:{type:"string",description:"Repository owner"},repo:{type:"string",description:"Repository name"},number:{type:"number",description:"Issue number"},limit:{type:"number",description:"Max comments (default: 100)"}},required:["owner","repo","number"]}},{name:"github_add_issue_comment",description:"Add a comment to a GitHub issue. Also the way to record a PR link on an issue (post a markdown link).",input_schema:{type:"object",properties:{owner:{type:"string",description:"Repository owner"},repo:{type:"string",description:"Repository name"},number:{type:"number",description:"Issue number"},body:{type:"string",description:"Comment body (markdown)"}},required:["owner","repo","number","body"]}},{name:"github_close_issue",description:"Close a GitHub issue. Optionally set the close reason (completed or not_planned).",input_schema:{type:"object",properties:{owner:{type:"string",description:"Repository owner"},repo:{type:"string",description:"Repository name"},number:{type:"number",description:"Issue number"},stateReason:{type:"string",enum:["completed","not_planned"],description:"Why the issue was closed (optional)"}},required:["owner","repo","number"]}},{name:"github_reopen_issue",description:"Reopen a closed GitHub issue",input_schema:{type:"object",properties:{owner:{type:"string",description:"Repository owner"},repo:{type:"string",description:"Repository name"},number:{type:"number",description:"Issue number"}},required:["owner","repo","number"]}},{name:"github_label_issue",description:"Add, set (replace all), or remove labels on a GitHub issue. Labels back state-like transitions on GitHub.",input_schema:{type:"object",properties:{owner:{type:"string",description:"Repository owner"},repo:{type:"string",description:"Repository name"},number:{type:"number",description:"Issue number"},labels:{type:"array",items:{type:"string"},description:"Label name(s)"},mode:{type:"string",enum:["add","set","remove"],description:"add appends, set replaces all, remove deletes (default: add)"}},required:["owner","repo","number","labels"]}}]};export{u as ghFetch,oe as githubSkill};
46
+ `),instructions:"IMPORTANT: Show the contents field to the user - it contains the directory listing."})}catch(w){let y=String(w.message||w).split(c).join("***").replace(/x-access-token:[^@]*@/g,"x-access-token:***@");return JSON.stringify({error:`Clone failed: ${y}`})}}case"github_search_repos":{let{query:t,limit:i}=a;if(!t)return JSON.stringify({error:"query is required"});let n=await this.handleToolCall("github_list_repos",{limit:200},{}),e=JSON.parse(n);if(e.error)return JSON.stringify(e);let r=t.toLowerCase(),s=e.repos.filter(o=>o.name.toLowerCase().includes(r)||o.fullName.toLowerCase().includes(r)||o.description&&o.description.toLowerCase().includes(r));return JSON.stringify({query:t,count:s.length,repos:s.slice(0,i||20)})}case"github_list_repos":{let{owner:t,type:i,sort:n,direction:e,limit:r,query:s}=a,o=100,m=r||200,l=[],p=d=>({name:d.name,fullName:d.full_name,private:d.private,description:d.description,language:d.language,defaultBranch:d.default_branch,updatedAt:d.updated_at,stars:d.stargazers_count,url:d.html_url,fullPath:d.full_name,webUrl:d.html_url,visibility:d.visibility||(d.private?"private":"public")}),c=d=>{if(!s)return!0;let y=String(s).toLowerCase();return d.name&&d.name.toLowerCase().includes(y)||d.fullName&&d.fullName.toLowerCase().includes(y)||d.description&&d.description.toLowerCase().includes(y)};if(!t){let d=1,y=!0;for(;y&&l.length<m;){let O=`/installation/repositories?per_page=${o}&page=${d}`,v=(await u(O)).repositories||[];if(v.length===0)break;l=l.concat(v),y=v.length===o,d++}let S=l.map(p).filter(c),$=S.slice(0,m),E=S.length>$.length,N=$.filter(O=>O.private).length,k=$.filter(O=>!O.private).length;return JSON.stringify({count:$.length,repos:$,truncated:E,privateCount:N,publicCount:k,message:`Found ${N} private and ${k} public repos`})}let g=await u(`/orgs/${t}`).then(()=>!0).catch(()=>!1),h=1,_=!0;for(;_&&l.length<m;){let d;g?d=`/orgs/${t}/repos?per_page=${o}&page=${h}&type=${i||"all"}&sort=${n||"updated"}&direction=${e||"desc"}`:d=`/users/${t}/repos?per_page=${o}&page=${h}&type=${i||"all"}&sort=${n||"updated"}&direction=${e||"desc"}`;let y=await u(d),S=Array.isArray(y)?y:[];if(S.length===0)break;l=l.concat(S),_=S.length===o,h++}let f=l.map(p).filter(c),R=f.slice(0,m),w=f.length>R.length;return JSON.stringify({count:R.length,repos:R,truncated:w})}case"github_create_pr":{let{owner:t,repo:i,head:n,title:e}=a||{};if(!t||!i||!n||!e)return JSON.stringify({error:"owner, repo, head (source branch), and title are required"});let r=a.base;if(!r)try{r=(await u(`/repos/${t}/${i}`)).default_branch||"main"}catch{r="main"}let s={title:String(e),head:String(n),base:String(r),body:a.body?String(a.body):"",draft:!!a.draft};try{let o=await u(`/repos/${t}/${i}/pulls`,{method:"POST",body:s});return JSON.stringify({success:!0,pr_url:o.html_url,number:o.number,branch:n,base:r,repo:`${t}/${i}`,provider:"github",draft:!!o.draft,state:o.state})}catch(o){let m=String(o.message||o);if(/GitHub API 422/.test(m))return JSON.stringify({success:!1,branch:n,base:r,repo:`${t}/${i}`,provider:"github",skippedReason:m});throw o}}case"github_merge_pr":{let{owner:t,repo:i,number:n}=a||{};if(!t||!i||!n)return JSON.stringify({error:"owner, repo, and number are required"});let e=a.mergeMethod||"squash";if(!["merge","squash","rebase"].includes(e))return JSON.stringify({error:`mergeMethod must be merge, squash, or rebase (got ${e})`});let r={merge_method:e};a.commitTitle&&(r.commit_title=String(a.commitTitle)),a.commitMessage&&(r.commit_message=String(a.commitMessage));try{let s=await u(`/repos/${t}/${i}/pulls/${n}/merge`,{method:"PUT",body:r});return JSON.stringify({success:!0,merged:!0,sha:s.sha,number:n,provider:"github"})}catch(s){let o=String(s.message||s);if(/GitHub API (405|409|404)/.test(o))return JSON.stringify({success:!1,number:n,provider:"github",skippedReason:o});throw s}}case"github_create_issue":{let{owner:t,repo:i,title:n,body:e}=a;if(!t||!i||!n)return JSON.stringify({error:"owner, repo, and title are required"});let r=await u(`/repos/${t}/${i}/issues`,{method:"POST",body:{title:n,body:e||""}});return JSON.stringify({number:r.number,url:r.html_url,title:r.title})}case"github_list_issues":{let{owner:t,repo:i,state:n,labels:e,since:r,assignee:s,sort:o,direction:m,limit:l}=a||{};if(!t||!i)return JSON.stringify({error:"owner and repo are required"});let p=new URLSearchParams;p.set("state",n||"open"),p.set("per_page",String(l||30)),p.set("sort",o||"updated"),p.set("direction",m||"desc"),e&&p.set("labels",Array.isArray(e)?e.join(","):e),r&&p.set("since",r),s&&p.set("assignee",s);let c=await u(`/repos/${t}/${i}/issues?${p.toString()}`),g=(Array.isArray(c)?c:[]).filter(h=>!h.pull_request).map(h=>({number:h.number,title:h.title,state:h.state,labels:(h.labels||[]).map(_=>typeof _=="string"?_:_.name),assignee:h.assignee?.login||null,assignees:(h.assignees||[]).map(_=>_.login),user:h.user?.login,comments:h.comments,url:h.html_url,createdAt:h.created_at,updatedAt:h.updated_at}));return JSON.stringify({count:g.length,issues:g})}case"github_get_issue":{let{owner:t,repo:i,number:n}=a||{};if(!t||!i||!n)return JSON.stringify({error:"owner, repo, and number are required"});let e=await u(`/repos/${t}/${i}/issues/${n}`);return e.pull_request?JSON.stringify({error:`#${n} is a pull request, not an issue`,isPR:!0}):JSON.stringify({number:e.number,title:e.title,body:e.body||"",state:e.state,stateReason:e.state_reason||null,labels:(e.labels||[]).map(r=>typeof r=="string"?r:r.name),assignee:e.assignee?.login||null,assignees:(e.assignees||[]).map(r=>r.login),user:e.user?.login,milestone:e.milestone?.title||null,comments:e.comments,url:e.html_url,createdAt:e.created_at,updatedAt:e.updated_at,closedAt:e.closed_at})}case"github_get_issue_comments":{let{owner:t,repo:i,number:n,limit:e}=a||{};if(!t||!i||!n)return JSON.stringify({error:"owner, repo, and number are required"});let r=await u(`/repos/${t}/${i}/issues/${n}/comments?per_page=${e||100}`),s=(Array.isArray(r)?r:[]).map(o=>({id:o.id,user:o.user?.login,body:o.body||"",createdAt:o.created_at,updatedAt:o.updated_at,url:o.html_url}));return JSON.stringify({count:s.length,comments:s})}case"github_add_issue_comment":{let{owner:t,repo:i,number:n,body:e}=a||{};if(!t||!i||!n||!e)return JSON.stringify({error:"owner, repo, number, and body are required"});let r=await u(`/repos/${t}/${i}/issues/${n}/comments`,{method:"POST",body:{body:e}});return JSON.stringify({ok:!0,id:r.id,url:r.html_url})}case"github_close_issue":{let{owner:t,repo:i,number:n,stateReason:e}=a||{};if(!t||!i||!n)return JSON.stringify({error:"owner, repo, and number are required"});let r={state:"closed"};e&&(r.state_reason=e);let s=await u(`/repos/${t}/${i}/issues/${n}`,{method:"PATCH",body:r});return JSON.stringify({ok:!0,number:s.number,state:s.state,stateReason:s.state_reason||null,url:s.html_url})}case"github_reopen_issue":{let{owner:t,repo:i,number:n}=a||{};if(!t||!i||!n)return JSON.stringify({error:"owner, repo, and number are required"});let e=await u(`/repos/${t}/${i}/issues/${n}`,{method:"PATCH",body:{state:"open"}});return JSON.stringify({ok:!0,number:e.number,state:e.state,url:e.html_url})}case"github_label_issue":{let{owner:t,repo:i,number:n,labels:e,mode:r}=a||{};if(!t||!i||!n)return JSON.stringify({error:"owner, repo, and number are required"});let s=Array.isArray(e)?e:e?[e]:[];if(!s.length)return JSON.stringify({error:"labels (string or array) is required"});let o=r||"add";if(o==="set"){let l=await u(`/repos/${t}/${i}/issues/${n}`,{method:"PATCH",body:{labels:s}});return JSON.stringify({ok:!0,number:l.number,labels:(l.labels||[]).map(p=>typeof p=="string"?p:p.name)})}if(o==="remove"){for(let p of s)await u(`/repos/${t}/${i}/issues/${n}/labels/${encodeURIComponent(p)}`,{method:"DELETE"});let l=await u(`/repos/${t}/${i}/issues/${n}`);return JSON.stringify({ok:!0,number:l.number,labels:(l.labels||[]).map(p=>typeof p=="string"?p:p.name)})}let m=await u(`/repos/${t}/${i}/issues/${n}/labels`,{method:"POST",body:{labels:s}});return JSON.stringify({ok:!0,number:n,labels:(Array.isArray(m)?m:[]).map(l=>typeof l=="string"?l:l.name)})}default:return JSON.stringify({error:`Unknown tool: ${b}`})}}catch(t){return JSON.stringify({error:t.message})}},tools:[{name:"github_get_user",description:"Get the authenticated GitHub user profile and their organizations",input_schema:{type:"object",properties:{}}},{name:"github_list_orgs",description:"List GitHub organizations the authenticated user belongs to",input_schema:{type:"object",properties:{}}},{name:"github_list_repos",description:"List the repositories this token/installation can access (omit owner) \u2014 or a specific user/org's repos (pass owner). Use this to discover a RELATED repo worth cloning when a change's correctness depends on another accessible repo. Each repo carries a normalized { fullPath, name, webUrl, defaultBranch, visibility } shape (identical to gitlab_list_projects) alongside legacy fields, plus a truncated flag.",input_schema:{type:"object",properties:{owner:{type:"string",description:"Org or user login. Omit to list every repo your token/installation can access."},query:{type:"string",description:"Optional term matched against repo name/full-name/description"},type:{type:"string",enum:["all","public","private","forks","sources","member"],description:"Filter by type (default: all)"},sort:{type:"string",enum:["created","updated","pushed","full_name"],description:"Sort field (default: updated)"},direction:{type:"string",enum:["asc","desc"],description:"Sort direction (default: desc)"},limit:{type:"number",description:"Max repos to return (default: 200, hard-capped at the fetch ceiling)"}}}},{name:"github_clone",description:'Clone a GitHub repository to the local filesystem. Use when user says "check out" or "clone" a repo.',input_schema:{type:"object",properties:{owner:{type:"string",description:"Repository owner (user or org name)"},repo:{type:"string",description:"Repository name"},destination:{type:"string",description:"Destination directory. Accepts absolute paths, ~-prefixed paths, or relative names. Defaults to ~/zibby-repos/<repo>."}},required:["owner","repo"]}},{name:"github_search_repos",description:"Search accessible repositories by name or description. Use this when the user asks to find a specific repo.",input_schema:{type:"object",properties:{query:{type:"string",description:'Search term to match against repo name or description (e.g., "electron", "my-app")'},limit:{type:"number",description:"Max results (default: 20)"}},required:["query"]}},{name:"github_search_issues",description:"Search GitHub issues and pull requests",input_schema:{type:"object",properties:{query:{type:"string",description:'GitHub search query (e.g. "SCRUM-123", "login bug repo:org/app")'},limit:{type:"number",description:"Max results (default: 20)"}},required:["query"]}},{name:"github_search_code",description:"Search code across GitHub repositories by keyword",input_schema:{type:"object",properties:{query:{type:"string",description:'Code search query (e.g. "handleLogin", "class AuthService")'},repo:{type:"string",description:'Scope to a specific repo (e.g. "org/app"). Optional.'},language:{type:"string",description:'Filter by language (e.g. "javascript", "python"). Optional.'},limit:{type:"number",description:"Max results (default: 15)"}},required:["query"]}},{name:"github_get_pr",description:"Get details of a pull request \u2014 title, description, branch, stats",input_schema:{type:"object",properties:{owner:{type:"string",description:"Repository owner"},repo:{type:"string",description:"Repository name"},number:{type:"number",description:"PR number"}},required:["owner","repo","number"]}},{name:"github_get_pr_diff",description:"Get the unified diff of a pull request \u2014 the actual code changes",input_schema:{type:"object",properties:{owner:{type:"string",description:"Repository owner"},repo:{type:"string",description:"Repository name"},number:{type:"number",description:"PR number"}},required:["owner","repo","number"]}},{name:"github_list_pr_files",description:"List files changed in a PR with per-file patches",input_schema:{type:"object",properties:{owner:{type:"string",description:"Repository owner"},repo:{type:"string",description:"Repository name"},number:{type:"number",description:"PR number"}},required:["owner","repo","number"]}},{name:"github_list_pr_comments",description:"Get all review and issue comments on a PR",input_schema:{type:"object",properties:{owner:{type:"string",description:"Repository owner"},repo:{type:"string",description:"Repository name"},number:{type:"number",description:"PR number"}},required:["owner","repo","number"]}},{name:"github_get_review_thread",description:"Read a PR review-comment THREAD given any comment id in it: the root review comment + all its replies, plus the anchored diff context (file, line, the original diff hunk). Use this to understand a human's reply to a previous review comment before replying in-thread.",input_schema:{type:"object",properties:{owner:{type:"string",description:"Repository owner"},repo:{type:"string",description:"Repository name"},number:{type:"number",description:"PR number"},commentId:{type:"number",description:"Any review-comment id in the thread (the root or any reply)"}},required:["owner","repo","number","commentId"]}},{name:"github_reply_review_thread",description:"Reply IN-THREAD to an existing PR review-comment thread (a conversational reply nested under the thread the human commented on \u2014 NOT a fresh full review). Pass any comment id in the thread.",input_schema:{type:"object",properties:{owner:{type:"string",description:"Repository owner"},repo:{type:"string",description:"Repository name"},number:{type:"number",description:"PR number"},commentId:{type:"number",description:"Any review-comment id in the thread to reply to"},body:{type:"string",description:"The reply text (markdown)"}},required:["owner","repo","number","commentId","body"]}},{name:"github_reply_issue_comment",description:"Post a reply on a PR's top-level conversation (a new issue comment on the PR). Use when the human replied to a non-inline/summary comment rather than an inline review thread. Quote or @-mention for context since issue comments are not threaded.",input_schema:{type:"object",properties:{owner:{type:"string",description:"Repository owner"},repo:{type:"string",description:"Repository name"},number:{type:"number",description:"PR number"},body:{type:"string",description:"The reply text (markdown)"}},required:["owner","repo","number","body"]}},{name:"github_create_review",description:"Post a review on a pull request: a summary body plus optional inline comments anchored to file/line, with an event (COMMENT, APPROVE, or REQUEST_CHANGES). Use this to deliver a code review back to the PR.",input_schema:{type:"object",properties:{owner:{type:"string",description:"Repository owner"},repo:{type:"string",description:"Repository name"},number:{type:"number",description:"PR number"},body:{type:"string",description:"The review summary (markdown). Shown as the top-level review comment."},event:{type:"string",enum:["COMMENT","APPROVE","REQUEST_CHANGES"],description:"Review verdict. Default COMMENT (no approval state). Use REQUEST_CHANGES for blocking issues."},comments:{type:"array",description:"Optional inline comments, each anchored to a changed line.",items:{type:"object",properties:{path:{type:"string",description:"File path as it appears in the diff"},line:{type:"number",description:"Line number in the file's NEW version (the right side of the diff)"},side:{type:"string",enum:["LEFT","RIGHT"],description:"RIGHT (new) or LEFT (old). Default RIGHT."},body:{type:"string",description:"The inline comment text (markdown)"}},required:["path","line","body"]}}},required:["owner","repo","number"]}},{name:"github_list_commits",description:"List commits on a branch \u2014 optionally bounded by since/until ISO dates (date-window listing) and paginated (keep calling with page+1 while hasMore is true). Optionally filtered by file path.",input_schema:{type:"object",properties:{owner:{type:"string",description:"Repository owner"},repo:{type:"string",description:"Repository name"},branch:{type:"string",description:"Branch name (default: repo default branch)"},path:{type:"string",description:"Filter commits touching this file path"},limit:{type:"number",description:"Commits per page, max 100 (default: 20)"},since:{type:"string",description:'Only commits after this ISO-8601 date/time, e.g. "2026-01-01T00:00:00Z"'},until:{type:"string",description:"Only commits before this ISO-8601 date/time"},page:{type:"number",description:"Page number, 1-based (default 1)"}},required:["owner","repo"]}},{name:"github_get_commit",description:"Get details of a specific commit \u2014 message, stats, file diffs",input_schema:{type:"object",properties:{owner:{type:"string",description:"Repository owner"},repo:{type:"string",description:"Repository name"},sha:{type:"string",description:"Commit SHA (full or short)"}},required:["owner","repo","sha"]}},{name:"github_get_file",description:"Read a file (or list a directory) from a GitHub repo. Works on any branch/ref.",input_schema:{type:"object",properties:{owner:{type:"string",description:"Repository owner"},repo:{type:"string",description:"Repository name"},path:{type:"string",description:'File or directory path (e.g. "src/auth/login.ts")'},ref:{type:"string",description:"Branch, tag, or commit SHA (default: repo default branch)"}},required:["owner","repo","path"]}},{name:"github_create_pr",description:"Open a pull request on GitHub (POST /repos/{owner}/{repo}/pulls). The head (source) branch must already be pushed. Returns the REAL pr_url from GitHub \u2014 never fabricate a PR url. Expected business outcomes (no commits between base and head, a PR already exists for this branch, base==head, missing head) return { success:false, skippedReason } rather than erroring.",input_schema:{type:"object",properties:{owner:{type:"string",description:"Repository owner"},repo:{type:"string",description:"Repository name"},head:{type:"string",description:'Source branch to merge FROM (must already be pushed). For a cross-fork PR use "fork-owner:branch".'},base:{type:"string",description:"Target branch to merge INTO (default: the repo's default branch)"},title:{type:"string",description:"PR title"},body:{type:"string",description:"PR description (markdown)"},draft:{type:"boolean",description:"Open as a draft PR (default: false)"}},required:["owner","repo","head","title"]}},{name:"github_merge_pr",description:"Merge a pull request on GitHub (PUT /repos/{owner}/{repo}/pulls/{number}/merge). mergeMethod is merge | squash | rebase (default squash). Returns { success:true, merged:true, sha } with the REAL merge SHA from GitHub. Expected non-mergeable outcomes (405 = draft / failing checks / branch protection, 409 = head sha moved / conflict, 404 = not found) return { success:false, skippedReason } rather than erroring.",input_schema:{type:"object",properties:{owner:{type:"string",description:"Repository owner"},repo:{type:"string",description:"Repository name"},number:{type:"number",description:"PR number to merge"},mergeMethod:{type:"string",enum:["merge","squash","rebase"],description:"How to merge (default: squash)"},commitTitle:{type:"string",description:"Title for the merge/squash commit (optional)"},commitMessage:{type:"string",description:"Body for the merge/squash commit (optional)"}},required:["owner","repo","number"]}},{name:"github_create_issue",description:"Create a GitHub issue",input_schema:{type:"object",properties:{owner:{type:"string",description:"Repository owner"},repo:{type:"string",description:"Repository name"},title:{type:"string",description:"Issue title"},body:{type:"string",description:"Issue body (markdown)"}},required:["owner","repo","title"]}},{name:"github_list_issues",description:"List issues in a repo (excludes pull requests). Filter by state, labels, and an updated-since cursor for polling.",input_schema:{type:"object",properties:{owner:{type:"string",description:"Repository owner"},repo:{type:"string",description:"Repository name"},state:{type:"string",enum:["open","closed","all"],description:"Filter by state (default: open)"},labels:{type:"array",items:{type:"string"},description:"Only issues carrying ALL of these labels"},since:{type:"string",description:"ISO-8601 timestamp; only issues updated at/after this (polling cursor)"},assignee:{type:"string",description:'Filter by assignee login, "none", or "*"'},sort:{type:"string",enum:["created","updated","comments"],description:"Sort field (default: updated)"},direction:{type:"string",enum:["asc","desc"],description:"Sort direction (default: desc)"},limit:{type:"number",description:"Max issues (default: 30, max 100 per page)"}},required:["owner","repo"]}},{name:"github_get_issue",description:"Get a single GitHub issue with full detail (title, body, state, labels, assignee, url)",input_schema:{type:"object",properties:{owner:{type:"string",description:"Repository owner"},repo:{type:"string",description:"Repository name"},number:{type:"number",description:"Issue number"}},required:["owner","repo","number"]}},{name:"github_get_issue_comments",description:"Get the comment thread on a GitHub issue (chronological)",input_schema:{type:"object",properties:{owner:{type:"string",description:"Repository owner"},repo:{type:"string",description:"Repository name"},number:{type:"number",description:"Issue number"},limit:{type:"number",description:"Max comments (default: 100)"}},required:["owner","repo","number"]}},{name:"github_add_issue_comment",description:"Add a comment to a GitHub issue. Also the way to record a PR link on an issue (post a markdown link).",input_schema:{type:"object",properties:{owner:{type:"string",description:"Repository owner"},repo:{type:"string",description:"Repository name"},number:{type:"number",description:"Issue number"},body:{type:"string",description:"Comment body (markdown)"}},required:["owner","repo","number","body"]}},{name:"github_close_issue",description:"Close a GitHub issue. Optionally set the close reason (completed or not_planned).",input_schema:{type:"object",properties:{owner:{type:"string",description:"Repository owner"},repo:{type:"string",description:"Repository name"},number:{type:"number",description:"Issue number"},stateReason:{type:"string",enum:["completed","not_planned"],description:"Why the issue was closed (optional)"}},required:["owner","repo","number"]}},{name:"github_reopen_issue",description:"Reopen a closed GitHub issue",input_schema:{type:"object",properties:{owner:{type:"string",description:"Repository owner"},repo:{type:"string",description:"Repository name"},number:{type:"number",description:"Issue number"}},required:["owner","repo","number"]}},{name:"github_label_issue",description:"Add, set (replace all), or remove labels on a GitHub issue. Labels back state-like transitions on GitHub.",input_schema:{type:"object",properties:{owner:{type:"string",description:"Repository owner"},repo:{type:"string",description:"Repository name"},number:{type:"number",description:"Issue number"},labels:{type:"array",items:{type:"string"},description:"Label name(s)"},mode:{type:"string",enum:["add","set","remove"],description:"add appends, set replaces all, remove deletes (default: add)"}},required:["owner","repo","number","labels"]}}]};export{u as ghFetch,oe as githubSkill};