@@ -39,14 +39,17 @@ function pickJobId(text, fallbackJobId) {
3939export class GitHubSkill {
4040 constructor ( { config } ) {
4141 this . config = config ;
42- this . git = simpleGit ( {
43- baseDir : config . github . defaultWorkdir
44- } ) ;
4542 this . octokit = config . github . token ? new Octokit ( { auth : config . github . token } ) : null ;
4643 this . testJobs = new Map ( ) ;
4744 this . latestTestJobId = "" ;
4845 }
4946
47+ getGit ( workdir ) {
48+ return simpleGit ( {
49+ baseDir : workdir || this . config . github . defaultWorkdir
50+ } ) ;
51+ }
52+
5053 supports ( text ) {
5154 const normalized = text . toLowerCase ( ) ;
5255 return (
@@ -55,7 +58,7 @@ export class GitHubSkill {
5558 ) ;
5659 }
5760
58- async execute ( { text } ) {
61+ async execute ( { text, workdir } ) {
5962 const stripped = text . replace ( / ^ \/ g h ( @ \w + ) ? \s * / i, "" ) . trim ( ) ;
6063 const normalized = stripped . toLowerCase ( ) ;
6164
@@ -64,23 +67,23 @@ export class GitHubSkill {
6467 }
6568
6669 if ( / 创 建 仓 库 | c r e a t e r e p o | n e w r e p o / . test ( normalized ) ) {
67- return this . createRepoFromText ( stripped ) ;
70+ return this . createRepoFromText ( stripped , workdir ) ;
6871 }
6972
7073 if ( / 测 试 状 态 | t e s t s t a t u s | s t a t u s / . test ( normalized ) ) {
7174 return this . readTestStatusFromText ( stripped ) ;
7275 }
7376
7477 if ( / 运 行 测 试 | r u n t e s t | p l a y w r i g h t | e 2 e / . test ( normalized ) ) {
75- return this . startTests ( ) ;
78+ return this . startTests ( workdir ) ;
7679 }
7780
7881 if ( ( / 推 送 | \b p u s h \b / . test ( normalized ) && ! / 提 交 | c o m m i t / . test ( normalized ) ) ) {
79- return this . pushOnly ( ) ;
82+ return this . pushOnly ( workdir ) ;
8083 }
8184
8285 if ( / 提 交 | 推 送 | c o m m i t | p u s h / . test ( normalized ) ) {
83- return this . commitAndPush ( stripped ) ;
86+ return this . commitAndPush ( stripped , workdir ) ;
8487 }
8588
8689 return { text : this . helpText ( ) } ;
@@ -97,30 +100,37 @@ export class GitHubSkill {
97100 ] . join ( "\n" ) ;
98101 }
99102
100- async commitAndPush ( rawText ) {
101- const status = await this . git . status ( ) ;
103+ async commitAndPush ( rawText , workdir ) {
104+ const git = this . getGit ( workdir ) ;
105+ const status = await git . status ( ) ;
102106 if ( ! status . files . length ) {
103107 return { text : "没有检测到变更,跳过 commit。" } ;
104108 }
105109
106110 const explicitMessage = extractQuotedMessage ( rawText ) ;
107111 const commitMessage = explicitMessage || buildAutoCommitMessage ( status ) ;
108112
109- await this . git . add ( "." ) ;
110- await this . git . commit ( commitMessage ) ;
113+ await git . add ( "." ) ;
114+ await git . commit ( commitMessage ) ;
111115
112- const branchInfo = await this . git . branch ( ) ;
116+ const branchInfo = await git . branch ( ) ;
113117 const branch = branchInfo . current || this . config . github . defaultBranch ;
114118
115119 try {
116- await this . git . push ( "origin" , branch ) ;
120+ await git . push ( "origin" , branch ) ;
117121 return {
118- text : `提交并推送成功。\nbranch: ${ branch } \nmessage: ${ commitMessage } `
122+ text : [
123+ "提交并推送成功。" ,
124+ `workdir: ${ workdir || this . config . github . defaultWorkdir } ` ,
125+ `branch: ${ branch } ` ,
126+ `message: ${ commitMessage } `
127+ ] . join ( "\n" )
119128 } ;
120129 } catch ( error ) {
121130 return {
122131 text : [
123132 "提交完成,但推送失败。" ,
133+ `workdir: ${ workdir || this . config . github . defaultWorkdir } ` ,
124134 `branch: ${ branch } ` ,
125135 `message: ${ commitMessage } ` ,
126136 `error: ${ error . message } `
@@ -129,16 +139,17 @@ export class GitHubSkill {
129139 }
130140 }
131141
132- async pushOnly ( ) {
133- const branchInfo = await this . git . branch ( ) ;
142+ async pushOnly ( workdir ) {
143+ const git = this . getGit ( workdir ) ;
144+ const branchInfo = await git . branch ( ) ;
134145 const branch = branchInfo . current || this . config . github . defaultBranch ;
135- await this . git . push ( "origin" , branch ) ;
146+ await git . push ( "origin" , branch ) ;
136147 return {
137- text : `推送成功。\nbranch: ${ branch } `
148+ text : `推送成功。\nworkdir: ${ workdir || this . config . github . defaultWorkdir } \ nbranch: ${ branch } `
138149 } ;
139150 }
140151
141- async createRepoFromText ( rawText ) {
152+ async createRepoFromText ( rawText , workdir ) {
142153 if ( ! this . octokit ) {
143154 return { text : "缺少 GITHUB_TOKEN,无法调用 GitHub API 创建仓库。" } ;
144155 }
@@ -148,42 +159,45 @@ export class GitHubSkill {
148159 return { text : "无法解析仓库名。示例: /gh create repo codex-telegram-claws-demo" } ;
149160 }
150161
162+ const git = this . getGit ( workdir ) ;
151163 const isPrivate = ! / p u b l i c | 公 开 / . test ( rawText . toLowerCase ( ) ) ;
152164 const { data : repo } = await this . octokit . repos . createForAuthenticatedUser ( {
153165 name : repoName ,
154166 private : isPrivate ,
155167 auto_init : false
156168 } ) ;
157169
158- const remotes = await this . git . getRemotes ( true ) ;
170+ const remotes = await git . getRemotes ( true ) ;
159171 const origin = remotes . find ( ( remote ) => remote . name === "origin" ) ;
160172 if ( ! origin ) {
161- await this . git . addRemote ( "origin" , repo . clone_url ) ;
173+ await git . addRemote ( "origin" , repo . clone_url ) ;
162174 } else {
163- await this . git . remote ( [ "set-url" , "origin" , repo . clone_url ] ) ;
175+ await git . remote ( [ "set-url" , "origin" , repo . clone_url ] ) ;
164176 }
165177
166- const branchInfo = await this . git . branch ( ) ;
178+ const branchInfo = await git . branch ( ) ;
167179 const branch = branchInfo . current || this . config . github . defaultBranch ;
168180
169- await this . git . push ( [ "-u" , "origin" , branch ] ) ;
181+ await git . push ( [ "-u" , "origin" , branch ] ) ;
170182
171183 return {
172184 text : [
173185 "仓库创建并关联成功。" ,
186+ `workdir: ${ workdir || this . config . github . defaultWorkdir } ` ,
174187 `repo: ${ repo . full_name } ` ,
175188 `url: ${ repo . html_url } ` ,
176189 `branch: ${ branch } `
177190 ] . join ( "\n" )
178191 } ;
179192 }
180193
181- async startTests ( ) {
194+ async startTests ( workdir ) {
182195 const jobId = `job-${ Date . now ( ) } ` ;
183196 const command = this . config . github . e2eCommand ;
184197 const job = {
185198 jobId,
186199 status : "running" ,
200+ workdir : workdir || this . config . github . defaultWorkdir ,
187201 command,
188202 startedAt : new Date ( ) . toISOString ( ) ,
189203 finishedAt : "" ,
@@ -192,7 +206,7 @@ export class GitHubSkill {
192206 } ;
193207
194208 const child = spawn ( command , {
195- cwd : this . config . github . defaultWorkdir ,
209+ cwd : workdir || this . config . github . defaultWorkdir ,
196210 env : process . env ,
197211 shell : true
198212 } ) ;
@@ -225,6 +239,7 @@ export class GitHubSkill {
225239 text : [
226240 "已触发自动化测试任务。" ,
227241 `jobId: ${ jobId } ` ,
242+ `workdir: ${ job . workdir } ` ,
228243 `command: ${ command } ` ,
229244 "使用 /gh test status <jobId> 查询状态。"
230245 ] . join ( "\n" ) ,
@@ -247,6 +262,7 @@ export class GitHubSkill {
247262 text : [
248263 `jobId: ${ job . jobId } ` ,
249264 `status: ${ job . status } ` ,
265+ `workdir: ${ job . workdir } ` ,
250266 `startedAt: ${ job . startedAt } ` ,
251267 job . finishedAt ? `finishedAt: ${ job . finishedAt } ` : "finishedAt: running" ,
252268 job . exitCode === null ? "exitCode: running" : `exitCode: ${ job . exitCode } ` ,
0 commit comments