dsh-github-flow 0.1.0 → 0.1.3

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.
@@ -1,2 +1,2 @@
1
1
  import type { GhExecutor } from '../executor.js';
2
- export declare function registerGhCommand(ctx: any, executor: GhExecutor): void;
2
+ export declare function registerGhCommand(commandsService: any, executor: GhExecutor): void;
@@ -1,63 +1,48 @@
1
- export function registerGhCommand(ctx, executor) {
2
- const commandsService = ctx.get ? ctx.get('commands') : ctx.commands;
1
+ export function registerGhCommand(commandsService, executor) {
3
2
  if (!commandsService || typeof commandsService.register !== 'function')
4
3
  return;
5
- const doRegister = () => {
6
- return commandsService.register({
7
- name: 'gh',
8
- description: 'GitHub CLI 状态与诊断快捷指令',
9
- async handler({ rawInput }) {
10
- const trimmed = (rawInput || '').trim();
11
- if (!trimmed || trimmed === 'status') {
12
- const auth = await executor.checkAuth();
13
- const repo = await executor.getRepoMetadata();
14
- let md = `### GitHub 集成状态\n\n`;
15
- if (auth.loggedIn) {
16
- md += `- **登录账号**: \`${auth.user || '已登录'}\`\n`;
17
- md += `- **授权作用域**: ${auth.scopes?.map((s) => `\`${s}\``).join(', ') || '标准权限'}\n`;
18
- }
19
- else {
20
- md += `- **登录状态**: ❌ 未登录 GitHub\n`;
21
- md += `> 提示:请在系统终端执行 \`gh auth login\` 进行登录。\n`;
22
- }
23
- if (repo) {
24
- md += `\n**当前关联仓库**:\n`;
25
- md += `- 仓库名: [${repo.nameWithOwner}](${repo.url})\n`;
26
- md += `- 默认分支: \`${repo.defaultBranch}\`\n`;
27
- if (repo.description)
28
- md += `- 简介: ${repo.description}\n`;
29
- }
30
- else {
31
- md += `\n*当前目录尚未关联 Git 远程仓库或未托管在 GitHub。*\n`;
32
- }
33
- return {
34
- kind: 'markdown',
35
- text: md,
36
- };
4
+ commandsService.register({
5
+ name: 'gh',
6
+ description: 'GitHub CLI 状态与诊断快捷指令',
7
+ async handler({ rawInput }) {
8
+ const trimmed = (rawInput || '').trim();
9
+ if (!trimmed || trimmed === 'status') {
10
+ const auth = await executor.checkAuth();
11
+ const repo = await executor.getRepoMetadata();
12
+ let md = `### GitHub 集成状态\n\n`;
13
+ if (auth.loggedIn) {
14
+ md += `- **登录账号**: \`${auth.user || '已登录'}\`\n`;
15
+ md += `- **授权作用域**: ${auth.scopes?.map((s) => `\`${s}\``).join(', ') || '标准权限'}\n`;
37
16
  }
38
- if (trimmed === 'help') {
39
- return {
40
- kind: 'markdown',
41
- text: `### DSH GitHub Flow 帮助\n\n- \`/gh status\`: 检查当前 GitHub CLI 账号与仓库连接\n- \`/gh help\`: 显示此帮助信息\n\n可以在对话中直接让 Agent 操作 GitHub,如:\n- *"查看当前仓库有哪些开放的 PR"* \n- *"查看最近一次 CI 失败的原因"* \n- *"帮我给当前分支创建 PR"*`,
42
- };
17
+ else {
18
+ md += `- **登录状态**: ❌ 未登录 GitHub\n`;
19
+ md += `> 提示:请在系统终端执行 \`gh auth login\` 进行登录。\n`;
43
20
  }
21
+ if (repo) {
22
+ md += `\n**当前关联仓库**:\n`;
23
+ md += `- 仓库名: [${repo.nameWithOwner}](${repo.url})\n`;
24
+ md += `- 默认分支: \`${repo.defaultBranch}\`\n`;
25
+ if (repo.description)
26
+ md += `- 简介: ${repo.description}\n`;
27
+ }
28
+ else {
29
+ md += `\n*当前目录尚未关联 Git 远程仓库或未托管在 GitHub。*\n`;
30
+ }
31
+ return {
32
+ kind: 'success',
33
+ text: md,
34
+ };
35
+ }
36
+ if (trimmed === 'help') {
44
37
  return {
45
- kind: 'error',
46
- text: `未知命令选项: /gh ${trimmed}。可用用法: /gh status, /gh help`,
38
+ kind: 'success',
39
+ text: `### DSH GitHub Flow 帮助\n\n- \`/gh status\`: 检查当前 GitHub CLI 账号与仓库连接\n- \`/gh help\`: 显示此帮助信息\n\n可以在对话中直接让 Agent 操作 GitHub,如:\n- *"查看当前仓库有哪些开放的 PR"* \n- *"查看最近一次 CI 失败的原因"* \n- *"帮我给当前分支创建 PR"*`,
47
40
  };
48
- },
49
- });
50
- };
51
- if (ctx.effect) {
52
- ctx.effect(() => {
53
- const dispose = doRegister();
54
- return () => {
55
- if (typeof dispose === 'function')
56
- dispose();
41
+ }
42
+ return {
43
+ kind: 'error',
44
+ text: `未知命令选项: /gh ${trimmed}。可用用法: /gh status, /gh help`,
57
45
  };
58
- }, 'github-flow: gh command');
59
- }
60
- else {
61
- doRegister();
62
- }
46
+ },
47
+ });
63
48
  }
package/lib/index.d.ts CHANGED
@@ -1,17 +1,4 @@
1
- import Schema from '@deepseek-ai/schemastery';
2
- import type { PluginConfig } from './types.js';
3
1
  export declare const name = "dsh-github-flow";
4
- /**
5
- * 仅将核心基础服务作为硬性依赖,解绑 webServer 与 commands。
6
- * 在无 Web 界面环境(如 Headless、纯终端、CI 自动化模式)下也能即刻激活,杜绝 PENDING 卡死。
7
- */
8
- export declare const inject: readonly ['tools'];
9
- /**
10
- * 遵循官方 Cordis 规范导出的强类型配置接口与运行时校验器
11
- */
12
- export interface Config extends PluginConfig {
13
- }
14
- export declare const Config: Schema<Config>;
15
- export declare function apply(ctx: any, config?: Config): void;
16
- export { GitHubService } from './service.js';
2
+ export declare const inject: readonly ['tools', 'commands', 'webServer', 'workspaceRegistry'];
3
+ export declare function apply(ctx: any): void;
17
4
  export * from './types.js';
package/lib/index.js CHANGED
@@ -1,6 +1,4 @@
1
- import Schema from '@deepseek-ai/schemastery';
2
1
  import { GhExecutor } from './executor.js';
3
- import { GitHubService } from './service.js';
4
2
  import { createPrTool } from './tools/pr.js';
5
3
  import { createIssueTool } from './tools/issue.js';
6
4
  import { createRunTool } from './tools/run.js';
@@ -9,49 +7,24 @@ import { createApiTool } from './tools/api.js';
9
7
  import { registerGhCommand } from './commands/gh.js';
10
8
  import { registerApiRoutes } from './api/routes.js';
11
9
  export const name = 'dsh-github-flow';
12
- /**
13
- * 仅将核心基础服务作为硬性依赖,解绑 webServer 与 commands。
14
- * 在无 Web 界面环境(如 Headless、纯终端、CI 自动化模式)下也能即刻激活,杜绝 PENDING 卡死。
15
- */
16
- export const inject = ['tools'];
17
- export const Config = Schema.object({
18
- ghPath: Schema.string().default('gh').description('GitHub CLI (gh) 二进制可执行文件路径'),
19
- defaultTimeoutMs: Schema.number().default(30000).description('CLI 命令执行超时毫秒数'),
20
- maxOutputChars: Schema.number().default(24000).description('防止 Token 溢出的单次截断安全阈值字符数'),
21
- cacheTtlMs: Schema.number().default(15000).description('Web API 概览数据缓存有效时长 (ms)'),
22
- defaultListLimit: Schema.number().default(20).description('默认查询列表返回条数'),
23
- });
24
- export function apply(ctx, config = {}) {
25
- // 1. 初始化具备动态配置能力的执行引擎
26
- const executor = new GhExecutor(config);
27
- // 2. 将核心能力提升挂载为 Cordis 原生微内核服务 (ctx.github)
28
- new GitHubService(ctx, executor);
29
- // 3. 注册 Agent 模型工具集(5 大核心领域工具)
30
- if (ctx.tools && typeof ctx.tools.register === 'function') {
10
+ export const inject = ['tools', 'commands', 'webServer', 'workspaceRegistry'];
11
+ export function apply(ctx) {
12
+ const executor = new GhExecutor();
13
+ // 1. 注册人类 Slash 命令 (/gh status, /gh help)
14
+ if (ctx.commands) {
15
+ registerGhCommand(ctx.commands, executor);
16
+ }
17
+ // 2. 注册 Agent 模型工具集(5 大核心领域工具)
18
+ if (ctx.tools) {
31
19
  ctx.tools.register(createPrTool(executor));
32
20
  ctx.tools.register(createIssueTool(executor));
33
21
  ctx.tools.register(createRunTool(executor));
34
22
  ctx.tools.register(createRepoTool(executor));
35
23
  ctx.tools.register(createApiTool(executor));
36
24
  }
37
- // 4. 可选依赖:命令服务(存在时动态激活,不阻塞主流程)
38
- if (ctx.inject && typeof ctx.inject === 'function') {
39
- ctx.inject(['commands'], (innerCtx) => {
40
- registerGhCommand(innerCtx, executor);
41
- });
42
- }
43
- else if (ctx.commands) {
44
- registerGhCommand(ctx, executor);
45
- }
46
- // 5. 可选依赖:Web 界面服务(存在时动态注入路由并由 effect 管理生命周期)
47
- if (ctx.inject && typeof ctx.inject === 'function') {
48
- ctx.inject(['webServer'], (innerCtx) => {
49
- registerApiRoutes(innerCtx, executor, config);
50
- });
51
- }
52
- else if (ctx.webServer) {
53
- registerApiRoutes(ctx, executor, config);
25
+ // 3. 注册面向 Client 端的 WebServer HTTP 路由
26
+ if (ctx.webServer) {
27
+ registerApiRoutes(ctx.webServer, executor, ctx.workspaceRegistry);
54
28
  }
55
29
  }
56
- export { GitHubService } from './service.js';
57
30
  export * from './types.js';
package/lib/main.d.ts ADDED
@@ -0,0 +1,4 @@
1
+ export declare const name = "dsh-github-flow";
2
+ export declare const inject: readonly ['tools', 'commands', 'webServer', 'workspaceRegistry'];
3
+ export declare function apply(ctx: any): void;
4
+ export * from './types.js';
package/lib/main.js ADDED
@@ -0,0 +1,30 @@
1
+ import { GhExecutor } from './executor.js';
2
+ import { createPrTool } from './tools/pr.js';
3
+ import { createIssueTool } from './tools/issue.js';
4
+ import { createRunTool } from './tools/run.js';
5
+ import { createRepoTool } from './tools/repo.js';
6
+ import { createApiTool } from './tools/api.js';
7
+ import { registerGhCommand } from './commands/gh.js';
8
+ import { registerApiRoutes } from './api/routes.js';
9
+ export const name = 'dsh-github-flow';
10
+ export const inject = ['tools', 'commands', 'webServer', 'workspaceRegistry'];
11
+ export function apply(ctx) {
12
+ const executor = new GhExecutor();
13
+ // 1. 注册人类 Slash 命令 (/gh status, /gh help)
14
+ if (ctx.commands) {
15
+ registerGhCommand(ctx.commands, executor);
16
+ }
17
+ // 2. 注册 Agent 模型工具集(5 大核心领域工具)
18
+ if (ctx.tools) {
19
+ ctx.tools.register(createPrTool(executor));
20
+ ctx.tools.register(createIssueTool(executor));
21
+ ctx.tools.register(createRunTool(executor));
22
+ ctx.tools.register(createRepoTool(executor));
23
+ ctx.tools.register(createApiTool(executor));
24
+ }
25
+ // 3. 注册面向 Client 端的 WebServer HTTP 路由
26
+ if (ctx.webServer) {
27
+ registerApiRoutes(ctx.webServer, executor, ctx.workspaceRegistry);
28
+ }
29
+ }
30
+ export * from './types.js';
@@ -1,2 +1,38 @@
1
1
  import type { GhExecutor } from '../executor.js';
2
- export declare function createApiTool(executor: GhExecutor): any;
2
+ export declare function createApiTool(executor: GhExecutor): {
3
+ name: string;
4
+ description: string;
5
+ parameters: {
6
+ type: string;
7
+ properties: {
8
+ endpoint: {
9
+ type: string;
10
+ description: string;
11
+ };
12
+ method: {
13
+ type: string;
14
+ enum: string[];
15
+ description: string;
16
+ };
17
+ jq: {
18
+ type: string;
19
+ description: string;
20
+ };
21
+ fields: {
22
+ type: string;
23
+ description: string;
24
+ };
25
+ };
26
+ required: string[];
27
+ };
28
+ output: {
29
+ schema: {
30
+ type: string;
31
+ };
32
+ render(args: any, value: any): {
33
+ type: string;
34
+ text: any;
35
+ }[];
36
+ };
37
+ execute(args: any, execContext: any): Promise<Record<string, any>>;
38
+ };
package/lib/tools/api.js CHANGED
@@ -1,6 +1,14 @@
1
- import { defineSafeTool } from './define.js';
1
+ function normalizeOutput(data) {
2
+ if (data && typeof data === 'object' && !Array.isArray(data)) {
3
+ return data;
4
+ }
5
+ if (Array.isArray(data)) {
6
+ return { items: data, count: data.length };
7
+ }
8
+ return { result: data !== undefined && data !== null ? data : '' };
9
+ }
2
10
  export function createApiTool(executor) {
3
- return defineSafeTool({
11
+ return {
4
12
  name: 'github_api',
5
13
  description: '通过 GitHub CLI 认证环境直接调用任意 GitHub REST 或 GraphQL API 端点(兜底逃生门)。支持 --jq 过滤。',
6
14
  parameters: {
@@ -29,7 +37,15 @@ export function createApiTool(executor) {
29
37
  output: {
30
38
  schema: { type: 'object' },
31
39
  render(args, value) {
32
- return [{ type: 'text', text: typeof value === 'string' ? value : JSON.stringify(value, null, 2) }];
40
+ if (!value)
41
+ return [{ type: 'text', text: '无返回内容' }];
42
+ if (typeof value.result === 'string') {
43
+ return [{ type: 'text', text: value.result }];
44
+ }
45
+ if (Array.isArray(value.items)) {
46
+ return [{ type: 'text', text: JSON.stringify(value.items, null, 2) }];
47
+ }
48
+ return [{ type: 'text', text: JSON.stringify(value, null, 2) }];
33
49
  },
34
50
  },
35
51
  async execute(args, execContext) {
@@ -49,7 +65,7 @@ export function createApiTool(executor) {
49
65
  const res = await executor.run(cmd, { cwd });
50
66
  if (!res.ok)
51
67
  throw new Error(res.error);
52
- return res.data || res.rawOutput;
68
+ return normalizeOutput(res.data !== undefined ? res.data : res.rawOutput);
53
69
  },
54
- });
70
+ };
55
71
  }
@@ -1,2 +1,56 @@
1
1
  import type { GhExecutor } from '../executor.js';
2
- export declare function createIssueTool(executor: GhExecutor): any;
2
+ export declare function createIssueTool(executor: GhExecutor): {
3
+ name: string;
4
+ description: string;
5
+ parameters: {
6
+ type: string;
7
+ properties: {
8
+ action: {
9
+ type: string;
10
+ enum: string[];
11
+ description: string;
12
+ };
13
+ issue_number: {
14
+ type: string;
15
+ description: string;
16
+ };
17
+ repo: {
18
+ type: string;
19
+ description: string;
20
+ };
21
+ title: {
22
+ type: string;
23
+ description: string;
24
+ };
25
+ body: {
26
+ type: string;
27
+ description: string;
28
+ };
29
+ labels: {
30
+ type: string;
31
+ items: {
32
+ type: string;
33
+ };
34
+ description: string;
35
+ };
36
+ assignees: {
37
+ type: string;
38
+ items: {
39
+ type: string;
40
+ };
41
+ description: string;
42
+ };
43
+ };
44
+ required: string[];
45
+ };
46
+ output: {
47
+ schema: {
48
+ type: string;
49
+ };
50
+ render(args: any, value: any): {
51
+ type: string;
52
+ text: any;
53
+ }[];
54
+ };
55
+ execute(args: any, execContext: any): Promise<Record<string, any>>;
56
+ };
@@ -1,6 +1,14 @@
1
- import { defineSafeTool } from './define.js';
1
+ function normalizeOutput(data) {
2
+ if (data && typeof data === 'object' && !Array.isArray(data)) {
3
+ return data;
4
+ }
5
+ if (Array.isArray(data)) {
6
+ return { items: data, count: data.length };
7
+ }
8
+ return { result: data !== undefined && data !== null ? data : '' };
9
+ }
2
10
  export function createIssueTool(executor) {
3
- return defineSafeTool({
11
+ return {
4
12
  name: 'github_issue',
5
13
  description: '管理 GitHub Issues。支持查看 Issue 列表、详情、创建新 Issue、追加评论以及关闭 Issue。',
6
14
  parameters: {
@@ -43,18 +51,33 @@ export function createIssueTool(executor) {
43
51
  output: {
44
52
  schema: { type: 'object' },
45
53
  render(args, value) {
46
- return [{ type: 'text', text: typeof value === 'string' ? value : JSON.stringify(value, null, 2) }];
54
+ if (!value)
55
+ return [{ type: 'text', text: '无返回内容' }];
56
+ if (typeof value.result === 'string') {
57
+ return [{ type: 'text', text: value.result }];
58
+ }
59
+ if (Array.isArray(value.items)) {
60
+ return [{ type: 'text', text: JSON.stringify(value.items, null, 2) }];
61
+ }
62
+ return [{ type: 'text', text: JSON.stringify(value, null, 2) }];
47
63
  },
48
64
  },
49
65
  async execute(args, execContext) {
50
66
  const cwd = execContext?.cwd || process.cwd();
51
- const repoArgs = args.repo ? ['-R', args.repo] : [];
67
+ let repoTarget = args.repo;
68
+ if (!repoTarget) {
69
+ const meta = await executor.getRepoMetadata(cwd);
70
+ if (meta?.nameWithOwner) {
71
+ repoTarget = meta.nameWithOwner;
72
+ }
73
+ }
74
+ const repoArgs = repoTarget ? ['-R', repoTarget] : [];
52
75
  switch (args.action) {
53
76
  case 'list': {
54
77
  const res = await executor.run(['issue', 'list', ...repoArgs, '--json', 'number,title,state,author,labels,updatedAt', '-L', '20'], { cwd });
55
78
  if (!res.ok)
56
79
  throw new Error(res.error);
57
- return res.data || res.rawOutput;
80
+ return normalizeOutput(res.data || res.rawOutput);
58
81
  }
59
82
  case 'view': {
60
83
  if (!args.issue_number)
@@ -62,7 +85,7 @@ export function createIssueTool(executor) {
62
85
  const res = await executor.run(['issue', 'view', String(args.issue_number), ...repoArgs, '--json', 'number,title,body,state,author,labels,assignees,comments,url'], { cwd });
63
86
  if (!res.ok)
64
87
  throw new Error(res.error);
65
- return res.data || res.rawOutput;
88
+ return normalizeOutput(res.data || res.rawOutput);
66
89
  }
67
90
  case 'create': {
68
91
  const cmd = ['issue', 'create', ...repoArgs, '--title', args.title || '', '--body', args.body || ''];
@@ -105,5 +128,5 @@ export function createIssueTool(executor) {
105
128
  throw new Error(`未知的 Issue 操作: ${args.action}`);
106
129
  }
107
130
  },
108
- });
131
+ };
109
132
  }
package/lib/tools/pr.d.ts CHANGED
@@ -1,2 +1,60 @@
1
1
  import type { GhExecutor } from '../executor.js';
2
- export declare function createPrTool(executor: GhExecutor): any;
2
+ export declare function createPrTool(executor: GhExecutor): {
3
+ name: string;
4
+ description: string;
5
+ parameters: {
6
+ type: string;
7
+ properties: {
8
+ action: {
9
+ type: string;
10
+ enum: string[];
11
+ description: string;
12
+ };
13
+ pr_number: {
14
+ type: string;
15
+ description: string;
16
+ };
17
+ repo: {
18
+ type: string;
19
+ description: string;
20
+ };
21
+ title: {
22
+ type: string;
23
+ description: string;
24
+ };
25
+ body: {
26
+ type: string;
27
+ description: string;
28
+ };
29
+ base: {
30
+ type: string;
31
+ description: string;
32
+ };
33
+ draft: {
34
+ type: string;
35
+ description: string;
36
+ };
37
+ review_decision: {
38
+ type: string;
39
+ enum: string[];
40
+ description: string;
41
+ };
42
+ merge_method: {
43
+ type: string;
44
+ enum: string[];
45
+ description: string;
46
+ };
47
+ };
48
+ required: string[];
49
+ };
50
+ output: {
51
+ schema: {
52
+ type: string;
53
+ };
54
+ render(args: any, value: any): {
55
+ type: string;
56
+ text: any;
57
+ }[];
58
+ };
59
+ execute(args: any, execContext: any): Promise<Record<string, any>>;
60
+ };
package/lib/tools/pr.js CHANGED
@@ -1,6 +1,14 @@
1
- import { defineSafeTool } from './define.js';
1
+ function normalizeOutput(data) {
2
+ if (data && typeof data === 'object' && !Array.isArray(data)) {
3
+ return data;
4
+ }
5
+ if (Array.isArray(data)) {
6
+ return { items: data, count: data.length };
7
+ }
8
+ return { result: data !== undefined && data !== null ? data : '' };
9
+ }
2
10
  export function createPrTool(executor) {
3
- return defineSafeTool({
11
+ return {
4
12
  name: 'github_pr',
5
13
  description: '管理与审查 GitHub Pull Request (PR)。支持查看列表、详情、差异比对、CI 检查状态、代码审查与合并操作。默认针对当前工作区关联的仓库。',
6
14
  parameters: {
@@ -51,39 +59,54 @@ export function createPrTool(executor) {
51
59
  output: {
52
60
  schema: { type: 'object' },
53
61
  render(args, value) {
54
- return [{ type: 'text', text: typeof value === 'string' ? value : JSON.stringify(value, null, 2) }];
62
+ if (!value)
63
+ return [{ type: 'text', text: '无返回内容' }];
64
+ if (typeof value.result === 'string') {
65
+ return [{ type: 'text', text: value.result }];
66
+ }
67
+ if (Array.isArray(value.items)) {
68
+ return [{ type: 'text', text: JSON.stringify(value.items, null, 2) }];
69
+ }
70
+ return [{ type: 'text', text: JSON.stringify(value, null, 2) }];
55
71
  },
56
72
  },
57
73
  async execute(args, execContext) {
58
74
  const cwd = execContext?.cwd || process.cwd();
59
- const repoArgs = args.repo ? ['-R', args.repo] : [];
75
+ let repoTarget = args.repo;
76
+ if (!repoTarget) {
77
+ const meta = await executor.getRepoMetadata(cwd);
78
+ if (meta?.nameWithOwner) {
79
+ repoTarget = meta.nameWithOwner;
80
+ }
81
+ }
82
+ const repoArgs = repoTarget ? ['-R', repoTarget] : [];
60
83
  switch (args.action) {
61
84
  case 'list': {
62
85
  const res = await executor.run(['pr', 'list', ...repoArgs, '--json', 'number,title,author,headRefName,isDraft,state,updatedAt', '-L', '20'], { cwd });
63
86
  if (!res.ok)
64
87
  throw new Error(res.error);
65
- return res.data || res.rawOutput;
88
+ return normalizeOutput(res.data || res.rawOutput);
66
89
  }
67
90
  case 'view': {
68
91
  const target = args.pr_number ? [String(args.pr_number)] : [];
69
92
  const res = await executor.run(['pr', 'view', ...target, ...repoArgs, '--json', 'number,title,body,state,author,labels,assignees,reviewDecision,mergeable,statusCheckRollup,url'], { cwd });
70
93
  if (!res.ok)
71
94
  throw new Error(res.error);
72
- return res.data || res.rawOutput;
95
+ return normalizeOutput(res.data || res.rawOutput);
73
96
  }
74
97
  case 'checks': {
75
98
  const target = args.pr_number ? [String(args.pr_number)] : [];
76
99
  const res = await executor.run(['pr', 'checks', ...target, ...repoArgs, '--json', 'name,state,conclusion,detailsUrl'], { cwd });
77
100
  if (!res.ok)
78
101
  throw new Error(res.error);
79
- return res.data || res.rawOutput;
102
+ return normalizeOutput(res.data || res.rawOutput);
80
103
  }
81
104
  case 'diff': {
82
105
  const target = args.pr_number ? [String(args.pr_number)] : [];
83
106
  const res = await executor.run(['pr', 'diff', ...target, ...repoArgs], { cwd });
84
107
  if (!res.ok)
85
108
  throw new Error(res.error);
86
- return res.rawOutput || '无差异内容';
109
+ return { result: res.rawOutput || '无差异内容' };
87
110
  }
88
111
  case 'create': {
89
112
  const createCmd = ['pr', 'create', ...repoArgs, '--title', args.title || '', '--body', args.body || ''];
@@ -126,5 +149,5 @@ export function createPrTool(executor) {
126
149
  throw new Error(`未知的 PR 操作: ${args.action}`);
127
150
  }
128
151
  },
129
- });
152
+ };
130
153
  }
@@ -1,2 +1,38 @@
1
1
  import type { GhExecutor } from '../executor.js';
2
- export declare function createRepoTool(executor: GhExecutor): any;
2
+ export declare function createRepoTool(executor: GhExecutor): {
3
+ name: string;
4
+ description: string;
5
+ parameters: {
6
+ type: string;
7
+ properties: {
8
+ action: {
9
+ type: string;
10
+ enum: string[];
11
+ description: string;
12
+ };
13
+ repo: {
14
+ type: string;
15
+ description: string;
16
+ };
17
+ query: {
18
+ type: string;
19
+ description: string;
20
+ };
21
+ limit: {
22
+ type: string;
23
+ description: string;
24
+ };
25
+ };
26
+ required: string[];
27
+ };
28
+ output: {
29
+ schema: {
30
+ type: string;
31
+ };
32
+ render(args: any, value: any): {
33
+ type: string;
34
+ text: any;
35
+ }[];
36
+ };
37
+ execute(args: any, execContext: any): Promise<Record<string, any>>;
38
+ };