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.
- package/LICENSE +21 -0
- package/README.en.md +119 -0
- package/README.md +39 -50
- package/cordis.patch.yml +2 -6
- package/docs/architecture.md +69 -0
- package/docs/npm-publish-guide.md +100 -0
- package/lib/api/routes.d.ts +1 -2
- package/lib/api/routes.js +234 -202
- package/lib/client/style.d.ts +1 -1
- package/lib/client/style.js +431 -66
- package/lib/client.js +396 -99
- package/lib/commands/gh.d.ts +1 -1
- package/lib/commands/gh.js +40 -55
- package/lib/index.d.ts +2 -15
- package/lib/index.js +12 -39
- package/lib/main.d.ts +4 -0
- package/lib/main.js +30 -0
- package/lib/tools/api.d.ts +37 -1
- package/lib/tools/api.js +21 -5
- package/lib/tools/issue.d.ts +55 -1
- package/lib/tools/issue.js +30 -7
- package/lib/tools/pr.d.ts +59 -1
- package/lib/tools/pr.js +32 -9
- package/lib/tools/repo.d.ts +37 -1
- package/lib/tools/repo.js +31 -8
- package/lib/tools/run.d.ts +37 -1
- package/lib/tools/run.js +31 -8
- package/lib/types.d.ts +0 -13
- package/package.json +16 -11
- package/lib/service.d.ts +0 -28
- package/lib/service.js +0 -34
- package/lib/tools/define.d.ts +0 -6
- package/lib/tools/define.js +0 -15
package/lib/tools/repo.js
CHANGED
|
@@ -1,6 +1,14 @@
|
|
|
1
|
-
|
|
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 createRepoTool(executor) {
|
|
3
|
-
return
|
|
11
|
+
return {
|
|
4
12
|
name: 'github_repo',
|
|
5
13
|
description: '查看 GitHub 仓库元数据与跨仓库检索代码、Issue。默认查询当前工作区关联的仓库。',
|
|
6
14
|
parameters: {
|
|
@@ -29,7 +37,15 @@ export function createRepoTool(executor) {
|
|
|
29
37
|
output: {
|
|
30
38
|
schema: { type: 'object' },
|
|
31
39
|
render(args, value) {
|
|
32
|
-
|
|
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) {
|
|
@@ -37,11 +53,18 @@ export function createRepoTool(executor) {
|
|
|
37
53
|
const limitStr = String(args.limit || 10);
|
|
38
54
|
switch (args.action) {
|
|
39
55
|
case 'view': {
|
|
40
|
-
|
|
56
|
+
let repoTarget = args.repo;
|
|
57
|
+
if (!repoTarget) {
|
|
58
|
+
const meta = await executor.getRepoMetadata(cwd);
|
|
59
|
+
if (meta?.nameWithOwner) {
|
|
60
|
+
repoTarget = meta.nameWithOwner;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
const repoArgs = repoTarget ? [repoTarget] : [];
|
|
41
64
|
const res = await executor.run(['repo', 'view', ...repoArgs, '--json', 'nameWithOwner,description,defaultBranchRef,isPrivate,stargazerCount,forkCount,url'], { cwd });
|
|
42
65
|
if (!res.ok)
|
|
43
66
|
throw new Error(res.error);
|
|
44
|
-
return res.data || res.rawOutput;
|
|
67
|
+
return normalizeOutput(res.data || res.rawOutput);
|
|
45
68
|
}
|
|
46
69
|
case 'search_code': {
|
|
47
70
|
if (!args.query)
|
|
@@ -50,7 +73,7 @@ export function createRepoTool(executor) {
|
|
|
50
73
|
const res = await executor.run(['search', 'code', args.query, ...repoArgs, '--json', 'path,repository,textMatches', '-L', limitStr], { cwd });
|
|
51
74
|
if (!res.ok)
|
|
52
75
|
throw new Error(res.error);
|
|
53
|
-
return res.data || res.rawOutput;
|
|
76
|
+
return normalizeOutput(res.data || res.rawOutput);
|
|
54
77
|
}
|
|
55
78
|
case 'search_repos': {
|
|
56
79
|
if (!args.query)
|
|
@@ -58,11 +81,11 @@ export function createRepoTool(executor) {
|
|
|
58
81
|
const res = await executor.run(['search', 'repos', args.query, '--json', 'fullName,description,stargazersCount,updatedAt', '-L', limitStr], { cwd });
|
|
59
82
|
if (!res.ok)
|
|
60
83
|
throw new Error(res.error);
|
|
61
|
-
return res.data || res.rawOutput;
|
|
84
|
+
return normalizeOutput(res.data || res.rawOutput);
|
|
62
85
|
}
|
|
63
86
|
default:
|
|
64
87
|
throw new Error(`未知的 Repo 操作: ${args.action}`);
|
|
65
88
|
}
|
|
66
89
|
},
|
|
67
|
-
}
|
|
90
|
+
};
|
|
68
91
|
}
|
package/lib/tools/run.d.ts
CHANGED
|
@@ -1,2 +1,38 @@
|
|
|
1
1
|
import type { GhExecutor } from '../executor.js';
|
|
2
|
-
export declare function createRunTool(executor: GhExecutor):
|
|
2
|
+
export declare function createRunTool(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
|
+
run_id: {
|
|
14
|
+
type: string;
|
|
15
|
+
description: string;
|
|
16
|
+
};
|
|
17
|
+
repo: {
|
|
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
|
+
};
|
package/lib/tools/run.js
CHANGED
|
@@ -1,6 +1,14 @@
|
|
|
1
|
-
|
|
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 createRunTool(executor) {
|
|
3
|
-
return
|
|
11
|
+
return {
|
|
4
12
|
name: 'github_run',
|
|
5
13
|
description: '排查和诊断 GitHub Actions 工作流构建状态。特别优化了获取失败步骤日志能力(log_failed),专供 Agent 快速定位 CI 报错。',
|
|
6
14
|
parameters: {
|
|
@@ -29,18 +37,33 @@ export function createRunTool(executor) {
|
|
|
29
37
|
output: {
|
|
30
38
|
schema: { type: 'object' },
|
|
31
39
|
render(args, value) {
|
|
32
|
-
|
|
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) {
|
|
36
52
|
const cwd = execContext?.cwd || process.cwd();
|
|
37
|
-
|
|
53
|
+
let repoTarget = args.repo;
|
|
54
|
+
if (!repoTarget) {
|
|
55
|
+
const meta = await executor.getRepoMetadata(cwd);
|
|
56
|
+
if (meta?.nameWithOwner) {
|
|
57
|
+
repoTarget = meta.nameWithOwner;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
const repoArgs = repoTarget ? ['-R', repoTarget] : [];
|
|
38
61
|
switch (args.action) {
|
|
39
62
|
case 'list': {
|
|
40
63
|
const res = await executor.run(['run', 'list', ...repoArgs, '--json', 'databaseId,name,status,conclusion,event,headBranch,createdAt', '-L', String(args.limit || 10)], { cwd });
|
|
41
64
|
if (!res.ok)
|
|
42
65
|
throw new Error(res.error);
|
|
43
|
-
return res.data || res.rawOutput;
|
|
66
|
+
return normalizeOutput(res.data || res.rawOutput);
|
|
44
67
|
}
|
|
45
68
|
case 'view': {
|
|
46
69
|
if (!args.run_id)
|
|
@@ -48,7 +71,7 @@ export function createRunTool(executor) {
|
|
|
48
71
|
const res = await executor.run(['run', 'view', String(args.run_id), ...repoArgs, '--json', 'databaseId,name,status,conclusion,jobs,url'], { cwd });
|
|
49
72
|
if (!res.ok)
|
|
50
73
|
throw new Error(res.error);
|
|
51
|
-
return res.data || res.rawOutput;
|
|
74
|
+
return normalizeOutput(res.data || res.rawOutput);
|
|
52
75
|
}
|
|
53
76
|
case 'log_failed': {
|
|
54
77
|
if (!args.run_id)
|
|
@@ -61,7 +84,7 @@ export function createRunTool(executor) {
|
|
|
61
84
|
});
|
|
62
85
|
if (!res.ok)
|
|
63
86
|
throw new Error(res.error);
|
|
64
|
-
return res.rawOutput || '未找到失败步骤的日志';
|
|
87
|
+
return { result: res.rawOutput || '未找到失败步骤的日志' };
|
|
65
88
|
}
|
|
66
89
|
case 'rerun': {
|
|
67
90
|
if (!args.run_id)
|
|
@@ -83,5 +106,5 @@ export function createRunTool(executor) {
|
|
|
83
106
|
throw new Error(`未知的 Run 操作: ${args.action}`);
|
|
84
107
|
}
|
|
85
108
|
},
|
|
86
|
-
}
|
|
109
|
+
};
|
|
87
110
|
}
|
package/lib/types.d.ts
CHANGED
|
@@ -152,16 +152,3 @@ export interface GlobalOverviewData {
|
|
|
152
152
|
lastUpdated: string;
|
|
153
153
|
error?: string;
|
|
154
154
|
}
|
|
155
|
-
declare module '@deepseek-ai/cordis' {
|
|
156
|
-
interface Events {
|
|
157
|
-
'github/pr:create'(repo: string, pr: {
|
|
158
|
-
title: string;
|
|
159
|
-
url: string;
|
|
160
|
-
}): void;
|
|
161
|
-
'github/pr:merge'(repo: string, prNumber: number): void;
|
|
162
|
-
'github/issue:create'(repo: string, issue: {
|
|
163
|
-
title: string;
|
|
164
|
-
url: string;
|
|
165
|
-
}): void;
|
|
166
|
-
}
|
|
167
|
-
}
|
package/package.json
CHANGED
|
@@ -1,12 +1,21 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-github-flow",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
4
|
"icon": "icon.svg",
|
|
5
5
|
"description": "GitHub Flow: Native GitHub CLI (gh) integration for DeepSeek Harness — Agent Tools, Slash Commands, and Web UI Workspace",
|
|
6
6
|
"type": "module",
|
|
7
|
-
"main": "./lib/
|
|
7
|
+
"main": "./lib/main.js",
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "https://github.com/ItQianChen/dsh-github-flow.git"
|
|
11
|
+
},
|
|
12
|
+
"homepage": "https://github.com/ItQianChen/dsh-github-flow#readme",
|
|
13
|
+
"bugs": {
|
|
14
|
+
"url": "https://github.com/ItQianChen/dsh-github-flow/issues"
|
|
15
|
+
},
|
|
8
16
|
"exports": {
|
|
9
|
-
".": "./lib/
|
|
17
|
+
".": "./lib/main.js",
|
|
18
|
+
"./entry": "./lib/main.js",
|
|
10
19
|
"./client": "./lib/client.js",
|
|
11
20
|
"./package.json": "./package.json"
|
|
12
21
|
},
|
|
@@ -14,7 +23,10 @@
|
|
|
14
23
|
"lib",
|
|
15
24
|
"icon.svg",
|
|
16
25
|
"cordis.patch.yml",
|
|
17
|
-
"README.md"
|
|
26
|
+
"README.md",
|
|
27
|
+
"README.en.md",
|
|
28
|
+
"LICENSE",
|
|
29
|
+
"docs"
|
|
18
30
|
],
|
|
19
31
|
"scripts": {
|
|
20
32
|
"build": "tsc && node scripts/build.mjs",
|
|
@@ -42,13 +54,6 @@
|
|
|
42
54
|
"access": "public",
|
|
43
55
|
"registry": "https://registry.npmjs.org/"
|
|
44
56
|
},
|
|
45
|
-
"peerDependencies": {
|
|
46
|
-
"@deepseek-ai/cordis": "*",
|
|
47
|
-
"@deepseek-ai/schemastery": "^3.18.4"
|
|
48
|
-
},
|
|
49
|
-
"dependencies": {
|
|
50
|
-
"@deepseek-ai/schemastery": "^3.18.4"
|
|
51
|
-
},
|
|
52
57
|
"devDependencies": {
|
|
53
58
|
"@types/node": "^26.6.3",
|
|
54
59
|
"typescript": "^7.0.2"
|
package/lib/service.d.ts
DELETED
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
import type { GhExecutor } from './executor.js';
|
|
2
|
-
import type { GhExecutionOptions, GhResult, AuthStatus, RepoMetadata } from './types.js';
|
|
3
|
-
declare module '@deepseek-ai/cordis' {
|
|
4
|
-
interface Context {
|
|
5
|
-
github: GitHubService;
|
|
6
|
-
}
|
|
7
|
-
}
|
|
8
|
-
/**
|
|
9
|
-
* DSH GitHub 原生微内核服务
|
|
10
|
-
* 允许生态内其他插件通过 ctx.github 或 inject: ['github'] 消费 GitHub CLI 能力
|
|
11
|
-
*/
|
|
12
|
-
export declare class GitHubService {
|
|
13
|
-
private ctx;
|
|
14
|
-
executor: GhExecutor;
|
|
15
|
-
constructor(ctx: any, executor: GhExecutor);
|
|
16
|
-
/**
|
|
17
|
-
* 执行原生 gh 命令
|
|
18
|
-
*/
|
|
19
|
-
run<T = unknown>(args: string[], options?: GhExecutionOptions): Promise<GhResult<T>>;
|
|
20
|
-
/**
|
|
21
|
-
* 检查宿主机 GitHub CLI 认证状态
|
|
22
|
-
*/
|
|
23
|
-
checkAuth(cwd?: string): Promise<AuthStatus>;
|
|
24
|
-
/**
|
|
25
|
-
* 获取指定工作区路径下的 Git 关联元数据
|
|
26
|
-
*/
|
|
27
|
-
getRepoMetadata(cwd?: string): Promise<RepoMetadata | null>;
|
|
28
|
-
}
|
package/lib/service.js
DELETED
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* DSH GitHub 原生微内核服务
|
|
3
|
-
* 允许生态内其他插件通过 ctx.github 或 inject: ['github'] 消费 GitHub CLI 能力
|
|
4
|
-
*/
|
|
5
|
-
export class GitHubService {
|
|
6
|
-
ctx;
|
|
7
|
-
executor;
|
|
8
|
-
constructor(ctx, executor) {
|
|
9
|
-
this.ctx = ctx;
|
|
10
|
-
this.executor = executor;
|
|
11
|
-
// 挂载到 ctx 上
|
|
12
|
-
if (ctx) {
|
|
13
|
-
ctx.github = this;
|
|
14
|
-
}
|
|
15
|
-
}
|
|
16
|
-
/**
|
|
17
|
-
* 执行原生 gh 命令
|
|
18
|
-
*/
|
|
19
|
-
async run(args, options = {}) {
|
|
20
|
-
return this.executor.run(args, options);
|
|
21
|
-
}
|
|
22
|
-
/**
|
|
23
|
-
* 检查宿主机 GitHub CLI 认证状态
|
|
24
|
-
*/
|
|
25
|
-
async checkAuth(cwd) {
|
|
26
|
-
return this.executor.checkAuth(cwd);
|
|
27
|
-
}
|
|
28
|
-
/**
|
|
29
|
-
* 获取指定工作区路径下的 Git 关联元数据
|
|
30
|
-
*/
|
|
31
|
-
async getRepoMetadata(cwd) {
|
|
32
|
-
return this.executor.getRepoMetadata(cwd);
|
|
33
|
-
}
|
|
34
|
-
}
|
package/lib/tools/define.d.ts
DELETED
package/lib/tools/define.js
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* DSH Tool 定义规范包装器
|
|
3
|
-
* 优先使用 @deepseek-ai/dsh-tools 的 defineTool DSL
|
|
4
|
-
* 在独立环境无此包时提供标准的运行时安全包装
|
|
5
|
-
*/
|
|
6
|
-
export function defineSafeTool(spec) {
|
|
7
|
-
try {
|
|
8
|
-
const dshTools = globalThis.__DSH_TOOLS__;
|
|
9
|
-
if (dshTools && typeof dshTools.defineTool === 'function') {
|
|
10
|
-
return dshTools.defineTool(spec);
|
|
11
|
-
}
|
|
12
|
-
}
|
|
13
|
-
catch (e) { }
|
|
14
|
-
return spec;
|
|
15
|
-
}
|