@perrylink/dsh-github 0.4.0
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 +201 -0
- package/README.es.md +256 -0
- package/README.hi.md +256 -0
- package/README.md +257 -0
- package/README.pt.md +256 -0
- package/README.zh-CN.md +254 -0
- package/cordis.patch.yml +9 -0
- package/lib/approval-gate.d.ts +25 -0
- package/lib/approval-gate.d.ts.map +1 -0
- package/lib/approval-gate.js +75 -0
- package/lib/approval-gate.js.map +1 -0
- package/lib/commands.d.ts +12 -0
- package/lib/commands.d.ts.map +1 -0
- package/lib/commands.js +228 -0
- package/lib/commands.js.map +1 -0
- package/lib/config.d.ts +60 -0
- package/lib/config.d.ts.map +1 -0
- package/lib/config.js +64 -0
- package/lib/config.js.map +1 -0
- package/lib/credential.d.ts +42 -0
- package/lib/credential.d.ts.map +1 -0
- package/lib/credential.js +80 -0
- package/lib/credential.js.map +1 -0
- package/lib/git.d.ts +52 -0
- package/lib/git.d.ts.map +1 -0
- package/lib/git.js +113 -0
- package/lib/git.js.map +1 -0
- package/lib/github.d.ts +66 -0
- package/lib/github.d.ts.map +1 -0
- package/lib/github.js +153 -0
- package/lib/github.js.map +1 -0
- package/lib/index.d.ts +55 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +44 -0
- package/lib/index.js.map +1 -0
- package/lib/jobs.d.ts +34 -0
- package/lib/jobs.d.ts.map +1 -0
- package/lib/jobs.js +255 -0
- package/lib/jobs.js.map +1 -0
- package/lib/present.d.ts +254 -0
- package/lib/present.d.ts.map +1 -0
- package/lib/present.js +149 -0
- package/lib/present.js.map +1 -0
- package/lib/review.d.ts +53 -0
- package/lib/review.d.ts.map +1 -0
- package/lib/review.js +158 -0
- package/lib/review.js.map +1 -0
- package/lib/state.d.ts +96 -0
- package/lib/state.d.ts.map +1 -0
- package/lib/state.js +86 -0
- package/lib/state.js.map +1 -0
- package/lib/tools.d.ts +21 -0
- package/lib/tools.d.ts.map +1 -0
- package/lib/tools.js +937 -0
- package/lib/tools.js.map +1 -0
- package/lib/types.d.ts +147 -0
- package/lib/types.d.ts.map +1 -0
- package/lib/types.js +2 -0
- package/lib/types.js.map +1 -0
- package/package.json +78 -0
package/lib/present.js
ADDED
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
/** Pending card for pr_create. */
|
|
2
|
+
export function prCreateCall(args) {
|
|
3
|
+
return {
|
|
4
|
+
card: 'generic',
|
|
5
|
+
title: `Create pull request: ${args.title}`,
|
|
6
|
+
rawInput: {
|
|
7
|
+
title: args.title,
|
|
8
|
+
...args.base !== undefined ? { base: args.base } : {},
|
|
9
|
+
...args.head !== undefined ? { head: args.head } : {},
|
|
10
|
+
...args.draft !== undefined ? { draft: args.draft } : {},
|
|
11
|
+
...args.ownerRepo !== undefined ? { ownerRepo: args.ownerRepo } : {},
|
|
12
|
+
},
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
/** Completed card for pr_create: the PR link, or a readable failure. */
|
|
16
|
+
export function prCreateResult(_args, result) {
|
|
17
|
+
const value = result.meta;
|
|
18
|
+
if (value === undefined)
|
|
19
|
+
return undefined;
|
|
20
|
+
if (value.status === 'error') {
|
|
21
|
+
return { card: 'generic', title: 'Pull request not created', content: [{ type: 'text', text: `${value.message}${value.guidance !== undefined ? `\n${value.guidance}` : ''}` }] };
|
|
22
|
+
}
|
|
23
|
+
return {
|
|
24
|
+
card: 'generic',
|
|
25
|
+
title: `Created pull request #${value.number}`,
|
|
26
|
+
content: [{ type: 'text', text: `${value.url}\n${value.base} ← ${value.head}${value.draft ? ' (draft)' : ''}` }],
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
/** Pending card for review_post. */
|
|
30
|
+
export function reviewPostCall(args) {
|
|
31
|
+
return { card: 'generic', title: `Post review comments (job ${args.jobId})`, rawInput: { jobId: args.jobId, ...args.mode !== undefined ? { mode: args.mode } : {} } };
|
|
32
|
+
}
|
|
33
|
+
/** Completed card for review_post. */
|
|
34
|
+
export function reviewPostResult(_args, result) {
|
|
35
|
+
const value = result.meta;
|
|
36
|
+
if (value === undefined)
|
|
37
|
+
return undefined;
|
|
38
|
+
if (value.status === 'error') {
|
|
39
|
+
return { card: 'generic', title: 'Review comments not posted', content: [{ type: 'text', text: value.message }] };
|
|
40
|
+
}
|
|
41
|
+
const kind = value.mode === 'inline' ? 'Inline review' : 'Review comments';
|
|
42
|
+
return { card: 'generic', title: `${kind} posted`, content: [{ type: 'text', text: `${value.url}\n${value.findings} finding(s) reported` }] };
|
|
43
|
+
}
|
|
44
|
+
/** Pending card for issue_open. */
|
|
45
|
+
export function issueOpenCall(args) {
|
|
46
|
+
return { card: 'generic', title: `Create issue: ${args.title}`, rawInput: { title: args.title } };
|
|
47
|
+
}
|
|
48
|
+
/** Completed card for issue_open. */
|
|
49
|
+
export function issueOpenResult(_args, result) {
|
|
50
|
+
const value = result.meta;
|
|
51
|
+
if (value === undefined)
|
|
52
|
+
return undefined;
|
|
53
|
+
if (value.status === 'error') {
|
|
54
|
+
return { card: 'generic', title: 'Issue not created', content: [{ type: 'text', text: `${value.message}${value.guidance !== undefined ? `\n${value.guidance}` : ''}` }] };
|
|
55
|
+
}
|
|
56
|
+
return { card: 'generic', title: `Created issue #${value.number}`, content: [{ type: 'text', text: value.url }] };
|
|
57
|
+
}
|
|
58
|
+
/** Pending card for issue_comment. */
|
|
59
|
+
export function issueCommentCall(args) {
|
|
60
|
+
return { card: 'generic', title: `Comment on #${args.issueNumber}`, rawInput: { issueNumber: args.issueNumber, ...args.ownerRepo !== undefined ? { ownerRepo: args.ownerRepo } : {} } };
|
|
61
|
+
}
|
|
62
|
+
/** Completed card for issue_comment. */
|
|
63
|
+
export function issueCommentResult(_args, result) {
|
|
64
|
+
const value = result.meta;
|
|
65
|
+
if (value === undefined)
|
|
66
|
+
return undefined;
|
|
67
|
+
if (value.status === 'error') {
|
|
68
|
+
return { card: 'generic', title: 'Comment not posted', content: [{ type: 'text', text: `${value.message}${value.guidance !== undefined ? `\n${value.guidance}` : ''}` }] };
|
|
69
|
+
}
|
|
70
|
+
return { card: 'generic', title: `Commented on #${value.issueNumber}`, content: [{ type: 'text', text: value.url }] };
|
|
71
|
+
}
|
|
72
|
+
/** Pending card for issue_close. */
|
|
73
|
+
export function issueCloseCall(args) {
|
|
74
|
+
return { card: 'generic', title: `Close issue #${args.issueNumber}`, rawInput: { issueNumber: args.issueNumber, ...args.stateReason !== undefined ? { stateReason: args.stateReason } : {} } };
|
|
75
|
+
}
|
|
76
|
+
/** Completed card for issue_close. */
|
|
77
|
+
export function issueCloseResult(_args, result) {
|
|
78
|
+
const value = result.meta;
|
|
79
|
+
if (value === undefined)
|
|
80
|
+
return undefined;
|
|
81
|
+
if (value.status === 'error') {
|
|
82
|
+
return { card: 'generic', title: 'Issue not closed', content: [{ type: 'text', text: `${value.message}${value.guidance !== undefined ? `\n${value.guidance}` : ''}` }] };
|
|
83
|
+
}
|
|
84
|
+
return { card: 'generic', title: `Closed issue #${value.number}`, content: [{ type: 'text', text: value.url }] };
|
|
85
|
+
}
|
|
86
|
+
/** Pending card for gh_review. */
|
|
87
|
+
export function ghReviewCall(args) {
|
|
88
|
+
return { card: 'generic', title: `Review PR ${args.pr}`, rawInput: { pr: args.pr, fields: args.fields ?? 'all' } };
|
|
89
|
+
}
|
|
90
|
+
/** Completed card for gh_review: headline facts and CI state. */
|
|
91
|
+
export function ghReviewResult(_args, result) {
|
|
92
|
+
const value = result.meta;
|
|
93
|
+
if (value === undefined)
|
|
94
|
+
return undefined;
|
|
95
|
+
if ('status' in value) {
|
|
96
|
+
return { card: 'generic', title: 'PR review failed', content: [{ type: 'text', text: `${value.message}${value.guidance !== undefined ? `\n${value.guidance}` : ''}` }] };
|
|
97
|
+
}
|
|
98
|
+
return {
|
|
99
|
+
card: 'generic',
|
|
100
|
+
title: `PR #${value.number} — ${value.title}`,
|
|
101
|
+
content: [{
|
|
102
|
+
type: 'text',
|
|
103
|
+
text: `${value.repo} · ${value.state} · ${value.base} ← ${value.head}\n`
|
|
104
|
+
+ `+${value.additions} −${value.deletions} · ${value.comments.items?.length ?? 0} comment(s) · ${value.findings?.length ?? 0} finding(s)\n`
|
|
105
|
+
+ `CI: ${value.ci.summary}`,
|
|
106
|
+
}],
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
/** Pending card for gh_issue. */
|
|
110
|
+
export function ghIssueCall(args) {
|
|
111
|
+
return { card: 'generic', title: `GitHub issues: ${args.action}`, rawInput: args };
|
|
112
|
+
}
|
|
113
|
+
/** Completed card for gh_issue. */
|
|
114
|
+
export function ghIssueResult(_args, result) {
|
|
115
|
+
const value = result.meta;
|
|
116
|
+
if (value === undefined)
|
|
117
|
+
return undefined;
|
|
118
|
+
if ('status' in value) {
|
|
119
|
+
return { card: 'generic', title: 'Issue read failed', content: [{ type: 'text', text: `${value.message}${value.guidance !== undefined ? `\n${value.guidance}` : ''}` }] };
|
|
120
|
+
}
|
|
121
|
+
return {
|
|
122
|
+
card: 'generic',
|
|
123
|
+
title: `Issues (${value.action}) — ${value.repo}`,
|
|
124
|
+
content: [{ type: 'text', text: (value.items ?? []).map(item => `#${item.number} ${item.title} [${item.kind}/${item.state}]`).join('\n') || '(no issues)' }],
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
/** Pending card for gh_search. */
|
|
128
|
+
export function ghSearchCall(args) {
|
|
129
|
+
return { card: 'generic', title: `Search GitHub: ${args.q}`, rawInput: { q: args.q } };
|
|
130
|
+
}
|
|
131
|
+
/** Completed card for gh_search. */
|
|
132
|
+
export function ghSearchResult(_args, result) {
|
|
133
|
+
const value = result.meta;
|
|
134
|
+
if (value === undefined)
|
|
135
|
+
return undefined;
|
|
136
|
+
if ('status' in value) {
|
|
137
|
+
return { card: 'generic', title: 'Search failed', content: [{ type: 'text', text: `${value.message}${value.guidance !== undefined ? `\n${value.guidance}` : ''}` }] };
|
|
138
|
+
}
|
|
139
|
+
return {
|
|
140
|
+
card: 'generic',
|
|
141
|
+
title: `Search results — ${value.total} total`,
|
|
142
|
+
content: [{ type: 'text', text: value.items.map(item => `#${item.number} ${item.title} [${item.kind}/${item.state}] ${item.repo}`).join('\n') || '(no results)' }],
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
/** Identity projection: persist the whole canonical value for card replay. */
|
|
146
|
+
export function identityMeta(_args, value) {
|
|
147
|
+
return value;
|
|
148
|
+
}
|
|
149
|
+
//# sourceMappingURL=present.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"present.js","sourceRoot":"","sources":["../src/present.ts"],"names":[],"mappings":"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"}
|
package/lib/review.d.ts
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Deterministic multi-file PR analyzer: parses a unified diff and produces a
|
|
3
|
+
* structured finding list plus a ready-to-post Markdown comment body.
|
|
4
|
+
*
|
|
5
|
+
* The analyzer is intentionally model-free — it runs inside the background
|
|
6
|
+
* review job without spending tokens, is deterministic, and its output is the
|
|
7
|
+
* only content the `/review post` approval offers for posting. For an LLM
|
|
8
|
+
* review instead, configure `reviewMode: "model"` (src/jobs.ts delegates the
|
|
9
|
+
* capped diff to a one-shot subagent through the host's subagents seam).
|
|
10
|
+
* @module dsh-github/review
|
|
11
|
+
*/
|
|
12
|
+
export type FindingSeverity = 'info' | 'warning' | 'error';
|
|
13
|
+
/** One review finding anchored to a file (and a new-file line when known). */
|
|
14
|
+
export interface Finding {
|
|
15
|
+
file: string;
|
|
16
|
+
line: number | null;
|
|
17
|
+
severity: FindingSeverity;
|
|
18
|
+
/** Short stable rule id, shown in the posted comment. */
|
|
19
|
+
rule: string;
|
|
20
|
+
message: string;
|
|
21
|
+
}
|
|
22
|
+
/** Complete review result: findings, summary text, and the postable body. */
|
|
23
|
+
export interface ReviewReport {
|
|
24
|
+
findings: Finding[];
|
|
25
|
+
summary: string;
|
|
26
|
+
postBody: string;
|
|
27
|
+
/** Whether the analyzed diff exceeded the cap and was truncated. */
|
|
28
|
+
truncated: boolean;
|
|
29
|
+
}
|
|
30
|
+
/** Split a unified diff into per-file added lines with new-file line numbers. */
|
|
31
|
+
export declare function parseAddedLines(diff: string, maxChars: number): Array<{
|
|
32
|
+
file: string;
|
|
33
|
+
line: number;
|
|
34
|
+
text: string;
|
|
35
|
+
}>;
|
|
36
|
+
/** Per-file change sizes parsed from a unified diff. */
|
|
37
|
+
export interface DiffFileStat {
|
|
38
|
+
path: string;
|
|
39
|
+
added: number;
|
|
40
|
+
removed: number;
|
|
41
|
+
}
|
|
42
|
+
/** Parse per-file added/removed counts out of a unified diff. */
|
|
43
|
+
export declare function parseDiffStats(diff: string, maxChars: number): DiffFileStat[];
|
|
44
|
+
/**
|
|
45
|
+
* Analyze a unified diff into findings and a postable comment body.
|
|
46
|
+
* @param diff - unified diff text (already capped by the caller or capped here).
|
|
47
|
+
* @param maxChars - character cap applied before parsing.
|
|
48
|
+
* @returns findings (capped), one-line summary, and Markdown post body.
|
|
49
|
+
*/
|
|
50
|
+
export declare function analyzeDiff(diff: string, maxChars: number): ReviewReport;
|
|
51
|
+
/** Markdown comment body grouped by file, ready for a PR issue comment. */
|
|
52
|
+
export declare function formatPostBody(findings: readonly Finding[], truncated: boolean): string;
|
|
53
|
+
//# sourceMappingURL=review.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"review.d.ts","sourceRoot":"","sources":["../src/review.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,MAAM,MAAM,eAAe,GAAG,MAAM,GAAG,SAAS,GAAG,OAAO,CAAA;AAE1D,8EAA8E;AAC9E,MAAM,WAAW,OAAO;IACtB,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;IACnB,QAAQ,EAAE,eAAe,CAAA;IACzB,yDAAyD;IACzD,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,EAAE,MAAM,CAAA;CAChB;AAED,6EAA6E;AAC7E,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAE,OAAO,EAAE,CAAA;IACnB,OAAO,EAAE,MAAM,CAAA;IACf,QAAQ,EAAE,MAAM,CAAA;IAChB,oEAAoE;IACpE,SAAS,EAAE,OAAO,CAAA;CACnB;AA4BD,iFAAiF;AACjF,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,CA6BnH;AAED,wDAAwD;AACxD,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,MAAM,CAAA;IACb,OAAO,EAAE,MAAM,CAAA;CAChB;AAED,iEAAiE;AACjE,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,YAAY,EAAE,CAqB7E;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,YAAY,CA+BxE;AAgBD,2EAA2E;AAC3E,wBAAgB,cAAc,CAAC,QAAQ,EAAE,SAAS,OAAO,EAAE,EAAE,SAAS,EAAE,OAAO,GAAG,MAAM,CAuBvF"}
|
package/lib/review.js
ADDED
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Deterministic multi-file PR analyzer: parses a unified diff and produces a
|
|
3
|
+
* structured finding list plus a ready-to-post Markdown comment body.
|
|
4
|
+
*
|
|
5
|
+
* The analyzer is intentionally model-free — it runs inside the background
|
|
6
|
+
* review job without spending tokens, is deterministic, and its output is the
|
|
7
|
+
* only content the `/review post` approval offers for posting. For an LLM
|
|
8
|
+
* review instead, configure `reviewMode: "model"` (src/jobs.ts delegates the
|
|
9
|
+
* capped diff to a one-shot subagent through the host's subagents seam).
|
|
10
|
+
* @module dsh-github/review
|
|
11
|
+
*/
|
|
12
|
+
const MAX_FINDINGS = 50;
|
|
13
|
+
const LINE_RULES = [
|
|
14
|
+
{ rule: 'hardcoded-secret', severity: 'error', message: 'possible hardcoded secret (token/private key); inject via credentials instead', pattern: /(ghp_[A-Za-z0-9]{20,}|github_pat_[A-Za-z0-9_]{20,}|AKIA[0-9A-Z]{16}|sk-[A-Za-z0-9]{20,}|xox[baprs]-[A-Za-z0-9-]{10,}|-----BEGIN [A-Z ]*PRIVATE KEY-----)/ },
|
|
15
|
+
{ rule: 'google-api-key', severity: 'error', message: 'possible hardcoded Google API key; restrict it and load it from the environment', pattern: /AIza[0-9A-Za-z_-]{35}/ },
|
|
16
|
+
{ rule: 'hardcoded-credential', severity: 'warning', message: 'possible hardcoded credential assignment; read from the environment or the credentials seam instead', pattern: /\b(password|passwd|pwd|secret|api[_-]?key)\s*[:=]\s*['"][^'"]{6,}['"]/i },
|
|
17
|
+
{ rule: 'debug-artifact', severity: 'warning', message: 'debug statement; remove before merging', pattern: /\b(console\.(log|debug|warn)|debugger)\b/ },
|
|
18
|
+
{ rule: 'eval-usage', severity: 'warning', message: 'dynamic evaluation (eval/new Function); avoid unless necessary', pattern: /\beval\s*\(|new\s+Function\s*\(/ },
|
|
19
|
+
{ rule: 'todo-marker', severity: 'info', message: 'leftover marker (TODO/FIXME/XXX); confirm it is tracked', pattern: /\b(TODO|FIXME|XXX)\b/ },
|
|
20
|
+
];
|
|
21
|
+
const MAX_LINE_LENGTH = 300;
|
|
22
|
+
/** Split a unified diff into per-file added lines with new-file line numbers. */
|
|
23
|
+
export function parseAddedLines(diff, maxChars) {
|
|
24
|
+
const limited = diff.length > maxChars ? diff.slice(0, maxChars) : diff;
|
|
25
|
+
const lines = limited.split(/\r?\n/);
|
|
26
|
+
const added = [];
|
|
27
|
+
let hunk = null;
|
|
28
|
+
for (const line of lines) {
|
|
29
|
+
if (line.startsWith('+++ ')) {
|
|
30
|
+
const file = line.slice(4).trim().replace(/^b\//, '');
|
|
31
|
+
if (file !== '/dev/null')
|
|
32
|
+
hunk = { file, newStart: 0, newLine: 0 };
|
|
33
|
+
continue;
|
|
34
|
+
}
|
|
35
|
+
if (hunk === null)
|
|
36
|
+
continue;
|
|
37
|
+
const match = /^@@ -\d+(?:,\d+)? \+(\d+)(?:,\d+)? @@/.exec(line);
|
|
38
|
+
if (match) {
|
|
39
|
+
const start = Number(match[1]);
|
|
40
|
+
hunk.newStart = start;
|
|
41
|
+
hunk.newLine = start;
|
|
42
|
+
continue;
|
|
43
|
+
}
|
|
44
|
+
if (line.startsWith('+') && !line.startsWith('+++')) {
|
|
45
|
+
added.push({ file: hunk.file, line: hunk.newLine, text: line.slice(1) });
|
|
46
|
+
hunk.newLine += 1;
|
|
47
|
+
}
|
|
48
|
+
else if (line.startsWith('-') && !line.startsWith('---')) {
|
|
49
|
+
// Removed line: new-file numbering does not advance.
|
|
50
|
+
}
|
|
51
|
+
else if (line.startsWith(' ')) {
|
|
52
|
+
hunk.newLine += 1;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
return added;
|
|
56
|
+
}
|
|
57
|
+
/** Parse per-file added/removed counts out of a unified diff. */
|
|
58
|
+
export function parseDiffStats(diff, maxChars) {
|
|
59
|
+
const limited = diff.length > maxChars ? diff.slice(0, maxChars) : diff;
|
|
60
|
+
const lines = limited.split(/\r?\n/);
|
|
61
|
+
const stats = new Map();
|
|
62
|
+
let current = null;
|
|
63
|
+
for (const line of lines) {
|
|
64
|
+
if (line.startsWith('+++ ')) {
|
|
65
|
+
const file = line.slice(4).trim().replace(/^b\//, '');
|
|
66
|
+
if (file === '/dev/null') {
|
|
67
|
+
current = null;
|
|
68
|
+
continue;
|
|
69
|
+
}
|
|
70
|
+
current = stats.get(file) ?? { path: file, added: 0, removed: 0 };
|
|
71
|
+
stats.set(file, current);
|
|
72
|
+
}
|
|
73
|
+
else if (current !== null && line.startsWith('+') && !line.startsWith('+++')) {
|
|
74
|
+
current.added += 1;
|
|
75
|
+
}
|
|
76
|
+
else if (current !== null && line.startsWith('-') && !line.startsWith('---')) {
|
|
77
|
+
current.removed += 1;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
return [...stats.values()];
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Analyze a unified diff into findings and a postable comment body.
|
|
84
|
+
* @param diff - unified diff text (already capped by the caller or capped here).
|
|
85
|
+
* @param maxChars - character cap applied before parsing.
|
|
86
|
+
* @returns findings (capped), one-line summary, and Markdown post body.
|
|
87
|
+
*/
|
|
88
|
+
export function analyzeDiff(diff, maxChars) {
|
|
89
|
+
const added = parseAddedLines(diff, maxChars);
|
|
90
|
+
const findings = [];
|
|
91
|
+
const perFileAdded = new Map();
|
|
92
|
+
for (const item of added) {
|
|
93
|
+
perFileAdded.set(item.file, (perFileAdded.get(item.file) ?? 0) + 1);
|
|
94
|
+
if (findings.length >= MAX_FINDINGS)
|
|
95
|
+
break;
|
|
96
|
+
for (const rule of LINE_RULES) {
|
|
97
|
+
if (rule.pattern.test(item.text)) {
|
|
98
|
+
findings.push({ file: item.file, line: item.line, severity: rule.severity, rule: rule.rule, message: rule.message });
|
|
99
|
+
break;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
if (findings.length >= MAX_FINDINGS)
|
|
103
|
+
break;
|
|
104
|
+
if (item.text.length > MAX_LINE_LENGTH) {
|
|
105
|
+
findings.push({ file: item.file, line: item.line, severity: 'info', rule: 'long-line', message: `line exceeds ${MAX_LINE_LENGTH} characters; consider splitting it` });
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
for (const [file, count] of perFileAdded) {
|
|
109
|
+
if (findings.length >= MAX_FINDINGS)
|
|
110
|
+
break;
|
|
111
|
+
if (count > 400)
|
|
112
|
+
findings.push({ file, line: null, severity: 'info', rule: 'large-change', message: `this PR adds ${count} lines to this file; consider splitting the commit` });
|
|
113
|
+
}
|
|
114
|
+
const truncated = diff.length > maxChars;
|
|
115
|
+
const summary = findings.length === 0
|
|
116
|
+
? `review complete: ${added.length} added line(s), no obvious issues found${truncated ? ' (diff truncated)' : ''}`
|
|
117
|
+
: `review complete: ${findings.length} finding(s) (${countSeverity(findings, 'error')} error / ${countSeverity(findings, 'warning')} warning / ${countSeverity(findings, 'info')} info)${truncated ? ' (diff truncated)' : ''}`;
|
|
118
|
+
return { findings, summary, postBody: formatPostBody(findings, truncated), truncated };
|
|
119
|
+
}
|
|
120
|
+
function countSeverity(findings, severity) {
|
|
121
|
+
return findings.filter(finding => finding.severity === severity).length;
|
|
122
|
+
}
|
|
123
|
+
/** Make a diff-derived file name safe to interpolate into Markdown. */
|
|
124
|
+
function sanitizeFileName(file) {
|
|
125
|
+
return file
|
|
126
|
+
.replace(/\\/g, '\\\\')
|
|
127
|
+
.replace(/`/g, '\\`')
|
|
128
|
+
.replace(/[\r\n\t]/g, ch => ({ '\r': '\\r', '\n': '\\n', '\t': '\\t' })[ch] ?? '')
|
|
129
|
+
.replace(/</g, '<')
|
|
130
|
+
.replace(/>/g, '>');
|
|
131
|
+
}
|
|
132
|
+
/** Markdown comment body grouped by file, ready for a PR issue comment. */
|
|
133
|
+
export function formatPostBody(findings, truncated) {
|
|
134
|
+
if (findings.length === 0) {
|
|
135
|
+
return `## dsh-github review\n\nNo obvious issues found.${truncated ? '\n\n> Note: the diff exceeded the cap and was truncated.' : ''}`;
|
|
136
|
+
}
|
|
137
|
+
const byFile = new Map();
|
|
138
|
+
for (const finding of findings) {
|
|
139
|
+
const list = byFile.get(finding.file) ?? [];
|
|
140
|
+
list.push(finding);
|
|
141
|
+
byFile.set(finding.file, list);
|
|
142
|
+
}
|
|
143
|
+
const sections = ['## dsh-github review\n'];
|
|
144
|
+
for (const [file, fileFindings] of byFile) {
|
|
145
|
+
sections.push(`### \`${sanitizeFileName(file)}\`\n`);
|
|
146
|
+
for (const finding of fileFindings) {
|
|
147
|
+
const line = finding.line === null ? '' : `:${finding.line}`;
|
|
148
|
+
sections.push(`- **${finding.severity}** \`${finding.rule}\`${line}: ${finding.message}`);
|
|
149
|
+
}
|
|
150
|
+
sections.push('');
|
|
151
|
+
}
|
|
152
|
+
if (truncated)
|
|
153
|
+
sections.push('> Note: the diff exceeded the cap and was truncated; this report only covers the examined range.');
|
|
154
|
+
sections.push('');
|
|
155
|
+
sections.push('*Generated by [dsh-github](https://github.com/PerryLink/dsh-github); published after human approval.*');
|
|
156
|
+
return sections.join('\n');
|
|
157
|
+
}
|
|
158
|
+
//# sourceMappingURL=review.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"review.js","sourceRoot":"","sources":["../src/review.ts"],"names":[],"mappings":"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"}
|
package/lib/state.d.ts
ADDED
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared per-plugin-instance state handed to tools, commands, and the review
|
|
3
|
+
* job: configuration, the credentials seam, the in-memory review-job records,
|
|
4
|
+
* and repo / PR-reference resolution helpers.
|
|
5
|
+
*
|
|
6
|
+
* The records map is the only mutable state; it lives exactly as long as the
|
|
7
|
+
* plugin fiber, mirroring the process-local lifetime of the host job registry,
|
|
8
|
+
* and is capped by `maxReviewRecords` (oldest settled records evict first).
|
|
9
|
+
* @module dsh-github/state
|
|
10
|
+
*/
|
|
11
|
+
import type { CredentialProvider } from '@deepseek-ai/dsh-credentials';
|
|
12
|
+
import { GithubClient, type RateLimitInfo } from './github.ts';
|
|
13
|
+
import { type GitRunner } from './git.ts';
|
|
14
|
+
import { type GhRunner, type TokenResolution } from './credential.ts';
|
|
15
|
+
import type { SubagentsService } from './types.ts';
|
|
16
|
+
import type { ReviewReport } from './review.ts';
|
|
17
|
+
import type { Config } from './config.ts';
|
|
18
|
+
/** Result of resolving which repository a call targets. */
|
|
19
|
+
export type RepoResolution = {
|
|
20
|
+
ok: true;
|
|
21
|
+
repo: string;
|
|
22
|
+
} | {
|
|
23
|
+
ok: false;
|
|
24
|
+
code: string;
|
|
25
|
+
message: string;
|
|
26
|
+
guidance: string;
|
|
27
|
+
};
|
|
28
|
+
/** A parsed PR reference: repository (when explicit) plus the PR number. */
|
|
29
|
+
export interface PrRef {
|
|
30
|
+
number: number;
|
|
31
|
+
/** `owner/repo` when the reference names one explicitly. */
|
|
32
|
+
repo?: string;
|
|
33
|
+
}
|
|
34
|
+
/** In-memory record of one background review job, keyed by job id. */
|
|
35
|
+
export interface ReviewJobRecord {
|
|
36
|
+
status: 'running' | 'completed' | 'failed' | 'killed';
|
|
37
|
+
repo: string;
|
|
38
|
+
pr: number;
|
|
39
|
+
/** Head-commit SHA of the reviewed PR, captured for inline review posting. */
|
|
40
|
+
headSha?: string;
|
|
41
|
+
/** One-line CI check summary captured by the job (when requested). */
|
|
42
|
+
ciSummary?: string;
|
|
43
|
+
/** Count of existing review comments captured by the job (when requested). */
|
|
44
|
+
commentsCount?: number;
|
|
45
|
+
report: ReviewReport | null;
|
|
46
|
+
error?: string;
|
|
47
|
+
}
|
|
48
|
+
export interface GithubState {
|
|
49
|
+
config: Config;
|
|
50
|
+
credentials: CredentialProvider;
|
|
51
|
+
/** Host subagent seam; present when composed (used by model review). */
|
|
52
|
+
subagents?: SubagentsService;
|
|
53
|
+
records: Map<string, ReviewJobRecord>;
|
|
54
|
+
/** Read-only git runner (injectable in tests). */
|
|
55
|
+
runGit: GitRunner;
|
|
56
|
+
/** gh CLI runner (injectable in tests). */
|
|
57
|
+
runGh: GhRunner;
|
|
58
|
+
/** Resolves the token per operation; never cached across operations. */
|
|
59
|
+
resolveToken(signal?: AbortSignal): Promise<TokenResolution>;
|
|
60
|
+
/** Builds an authenticated client for one operation. */
|
|
61
|
+
client(token: string): GithubClient;
|
|
62
|
+
/** Resolves `owner/repo` from an explicit value, config, or git origin. */
|
|
63
|
+
resolveRepo(ownerRepo: string | undefined, signal?: AbortSignal): Promise<RepoResolution>;
|
|
64
|
+
/** Parses `123`, `#123`, `owner/repo#123`, or a pull-request URL. */
|
|
65
|
+
parsePrRef(input: string): PrRef | null;
|
|
66
|
+
/** Working directory for git inspection. */
|
|
67
|
+
workspaceDir: string;
|
|
68
|
+
/** Hostname of the configured REST API base, for origin-URL matching. */
|
|
69
|
+
apiHost: string;
|
|
70
|
+
/** Register one review-job record, evicting settled records past the cap. */
|
|
71
|
+
rememberRecord(id: string, record: ReviewJobRecord): void;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Create the shared plugin state. Called once per plugin instance (per
|
|
75
|
+
* cordis.yml row); config hot-reload creates a fresh instance.
|
|
76
|
+
* @param ctx - context holding the credentials seam and (optionally) the subagent seam.
|
|
77
|
+
* @param config - validated configuration.
|
|
78
|
+
* @param runGit - read-only git runner (injectable in tests).
|
|
79
|
+
* @param runGh - gh CLI runner (injectable in tests).
|
|
80
|
+
* @param fetchImpl - fetch implementation (injectable in tests).
|
|
81
|
+
*/
|
|
82
|
+
export declare function createState(ctx: {
|
|
83
|
+
credentials: CredentialProvider;
|
|
84
|
+
subagents?: SubagentsService;
|
|
85
|
+
}, config: Config, runGit: GitRunner, runGh: GhRunner, fetchImpl?: typeof fetch): GithubState;
|
|
86
|
+
/** Resolve the target repository: explicit value → config fallback → git origin. */
|
|
87
|
+
export declare function resolveRepo(state: GithubState, ownerRepo: string | undefined, signal?: AbortSignal): Promise<RepoResolution>;
|
|
88
|
+
/** Parses PR references: `123`, `#123`, `owner/repo#123`, or a pull URL. */
|
|
89
|
+
export declare function parsePrRef(input: string): PrRef | null;
|
|
90
|
+
/** Shared shape of rate-limit facts on tool results. */
|
|
91
|
+
export type RateLimitValue = {
|
|
92
|
+
remaining: number | null;
|
|
93
|
+
resetAt: number | null;
|
|
94
|
+
};
|
|
95
|
+
export declare function rateLimitValue(info: RateLimitInfo): RateLimitValue;
|
|
96
|
+
//# sourceMappingURL=state.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"state.d.ts","sourceRoot":"","sources":["../src/state.ts"],"names":[],"mappings":"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"}
|
package/lib/state.js
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { GithubClient, clientOptionsFromConfig } from "./github.js";
|
|
2
|
+
import { repoFromRemoteUrl } from "./git.js";
|
|
3
|
+
import { resolveToken } from "./credential.js";
|
|
4
|
+
const REPO_GUIDANCE = 'Name the repository with the ownerRepo parameter, set defaultOwnerRepo in cordis.yml, or run inside a checkout with a GitHub origin remote.';
|
|
5
|
+
const REPO_PATTERN = /^[A-Za-z0-9_.-]+\/[A-Za-z0-9_.-]+$/;
|
|
6
|
+
/**
|
|
7
|
+
* Create the shared plugin state. Called once per plugin instance (per
|
|
8
|
+
* cordis.yml row); config hot-reload creates a fresh instance.
|
|
9
|
+
* @param ctx - context holding the credentials seam and (optionally) the subagent seam.
|
|
10
|
+
* @param config - validated configuration.
|
|
11
|
+
* @param runGit - read-only git runner (injectable in tests).
|
|
12
|
+
* @param runGh - gh CLI runner (injectable in tests).
|
|
13
|
+
* @param fetchImpl - fetch implementation (injectable in tests).
|
|
14
|
+
*/
|
|
15
|
+
export function createState(ctx, config, runGit, runGh, fetchImpl) {
|
|
16
|
+
const clientOptions = clientOptionsFromConfig(config, fetchImpl);
|
|
17
|
+
const apiHost = new URL(config.apiBaseUrl).hostname.toLowerCase();
|
|
18
|
+
const records = new Map();
|
|
19
|
+
const state = {
|
|
20
|
+
config,
|
|
21
|
+
credentials: ctx.credentials,
|
|
22
|
+
subagents: ctx.subagents,
|
|
23
|
+
records,
|
|
24
|
+
runGit,
|
|
25
|
+
runGh,
|
|
26
|
+
workspaceDir: config.workspaceDir ?? process.cwd(),
|
|
27
|
+
apiHost,
|
|
28
|
+
resolveToken: (signal) => resolveToken(ctx.credentials, config.tokenSource, config.tokenRef, runGh, signal),
|
|
29
|
+
client: (token) => new GithubClient(token, clientOptions),
|
|
30
|
+
resolveRepo: (ownerRepo, signal) => resolveRepo(state, ownerRepo, signal),
|
|
31
|
+
parsePrRef: parsePrRef,
|
|
32
|
+
rememberRecord: (id, record) => {
|
|
33
|
+
records.set(id, record);
|
|
34
|
+
while (records.size > config.maxReviewRecords) {
|
|
35
|
+
const oldestSettled = [...records.entries()].find(([, item]) => item.status !== 'running');
|
|
36
|
+
if (oldestSettled === undefined)
|
|
37
|
+
break; // every record is running; the cap is best-effort.
|
|
38
|
+
records.delete(oldestSettled[0]);
|
|
39
|
+
}
|
|
40
|
+
},
|
|
41
|
+
};
|
|
42
|
+
return state;
|
|
43
|
+
}
|
|
44
|
+
/** Resolve the target repository: explicit value → config fallback → git origin. */
|
|
45
|
+
export async function resolveRepo(state, ownerRepo, signal) {
|
|
46
|
+
const candidate = ownerRepo?.trim();
|
|
47
|
+
if (candidate !== undefined && candidate.length > 0) {
|
|
48
|
+
return REPO_PATTERN.test(candidate)
|
|
49
|
+
? { ok: true, repo: candidate }
|
|
50
|
+
: { ok: false, code: 'invalid-repo', message: `"${candidate}" is not an owner/repo pair`, guidance: REPO_GUIDANCE };
|
|
51
|
+
}
|
|
52
|
+
const fallback = state.config.defaultOwnerRepo?.trim();
|
|
53
|
+
if (fallback !== undefined && fallback.length > 0)
|
|
54
|
+
return { ok: true, repo: fallback };
|
|
55
|
+
const { repoFromRemote } = await runGitRemote(state, state.workspaceDir, signal);
|
|
56
|
+
if (repoFromRemote !== null)
|
|
57
|
+
return { ok: true, repo: repoFromRemote };
|
|
58
|
+
return { ok: false, code: 'repo-unknown', message: 'could not determine the target repository', guidance: REPO_GUIDANCE };
|
|
59
|
+
}
|
|
60
|
+
/** Parses PR references: `123`, `#123`, `owner/repo#123`, or a pull URL. */
|
|
61
|
+
export function parsePrRef(input) {
|
|
62
|
+
const trimmed = input.trim();
|
|
63
|
+
const urlMatch = /^https?:\/\/[^/]+\/([A-Za-z0-9_.-]+\/[A-Za-z0-9_.-]+)\/pull\/(\d+)\/?$/.exec(trimmed);
|
|
64
|
+
if (urlMatch)
|
|
65
|
+
return { number: Number(urlMatch[2]), repo: urlMatch[1] };
|
|
66
|
+
const hashMatch = /^(?:([A-Za-z0-9_.-]+\/[A-Za-z0-9_.-]+))?#(\d+)$/.exec(trimmed);
|
|
67
|
+
if (hashMatch)
|
|
68
|
+
return hashMatch[1] === undefined ? { number: Number(hashMatch[2]) } : { number: Number(hashMatch[2]), repo: hashMatch[1] };
|
|
69
|
+
if (/^\d+$/.test(trimmed))
|
|
70
|
+
return { number: Number(trimmed) };
|
|
71
|
+
return null;
|
|
72
|
+
}
|
|
73
|
+
/** Read the git origin URL through the injected runner. */
|
|
74
|
+
async function runGitRemote(state, cwd, signal) {
|
|
75
|
+
try {
|
|
76
|
+
const { stdout } = await state.runGit(['remote', 'get-url', 'origin'], { cwd, signal });
|
|
77
|
+
return { repoFromRemote: repoFromRemoteUrl(stdout, state.apiHost) };
|
|
78
|
+
}
|
|
79
|
+
catch {
|
|
80
|
+
return { repoFromRemote: null };
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
export function rateLimitValue(info) {
|
|
84
|
+
return { remaining: info.remaining, resetAt: info.resetAt };
|
|
85
|
+
}
|
|
86
|
+
//# sourceMappingURL=state.js.map
|
package/lib/state.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"state.js","sourceRoot":"","sources":["../src/state.ts"],"names":[],"mappings":"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"}
|
package/lib/tools.d.ts
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { type GithubState, type RateLimitValue } from './state.ts';
|
|
2
|
+
import { type GithubErrorValue } from './present.ts';
|
|
3
|
+
/** Domain error canonical value, used by every tool. */
|
|
4
|
+
export declare function errorValue(code: string, message: string, guidance?: string, rateLimit?: RateLimitValue): GithubErrorValue;
|
|
5
|
+
/** `pr_create`: create a pull request (write; approval-gated upstream). */
|
|
6
|
+
export declare function prCreateTool(state: GithubState): import("@deepseek-ai/dsh-tools").ToolDefinition;
|
|
7
|
+
/** `gh_review`: read a PR's metadata, diff, comments, CI, and findings. */
|
|
8
|
+
export declare function ghReviewTool(state: GithubState): import("@deepseek-ai/dsh-tools").ToolDefinition;
|
|
9
|
+
/** `review_post`: publish a review job's drafted comment (write; approval-gated upstream). */
|
|
10
|
+
export declare function reviewPostTool(state: GithubState): import("@deepseek-ai/dsh-tools").ToolDefinition;
|
|
11
|
+
/** `gh_issue`: read issues (list / get / comments). Read-only. */
|
|
12
|
+
export declare function ghIssueTool(state: GithubState): import("@deepseek-ai/dsh-tools").ToolDefinition;
|
|
13
|
+
/** `issue_open`: create an issue (write; approval-gated upstream). */
|
|
14
|
+
export declare function issueOpenTool(state: GithubState): import("@deepseek-ai/dsh-tools").ToolDefinition;
|
|
15
|
+
/** `issue_comment`: comment on an issue or pull request (write; approval-gated upstream). */
|
|
16
|
+
export declare function issueCommentTool(state: GithubState): import("@deepseek-ai/dsh-tools").ToolDefinition;
|
|
17
|
+
/** `issue_close`: close an issue (write; approval-gated upstream). */
|
|
18
|
+
export declare function issueCloseTool(state: GithubState): import("@deepseek-ai/dsh-tools").ToolDefinition;
|
|
19
|
+
/** `gh_search`: search issues and pull requests (read; uses the search quota). */
|
|
20
|
+
export declare function ghSearchTool(state: GithubState): import("@deepseek-ai/dsh-tools").ToolDefinition;
|
|
21
|
+
//# sourceMappingURL=tools.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"AAiBA,OAAO,EAAkB,KAAK,WAAW,EAAE,KAAK,cAAc,EAAE,MAAM,YAAY,CAAA;AAClF,OAAO,EAIL,KAAK,gBAAgB,EACtB,MAAM,cAAc,CAAA;AA8BrB,wDAAwD;AACxD,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,cAAc,GAAG,gBAAgB,CAEzH;AA4FD,2EAA2E;AAC3E,wBAAgB,YAAY,CAAC,KAAK,EAAE,WAAW,mDAiG9C;AAED,2EAA2E;AAC3E,wBAAgB,YAAY,CAAC,KAAK,EAAE,WAAW,mDA4N9C;AAqCD,8FAA8F;AAC9F,wBAAgB,cAAc,CAAC,KAAK,EAAE,WAAW,mDAsFhD;AAED,kEAAkE;AAClE,wBAAgB,WAAW,CAAC,KAAK,EAAE,WAAW,mDAgI7C;AAED,sEAAsE;AACtE,wBAAgB,aAAa,CAAC,KAAK,EAAE,WAAW,mDA2D/C;AAED,6FAA6F;AAC7F,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,WAAW,mDAoDlD;AAED,sEAAsE;AACtE,wBAAgB,cAAc,CAAC,KAAK,EAAE,WAAW,mDAyDhD;AAID,kFAAkF;AAClF,wBAAgB,YAAY,CAAC,KAAK,EAAE,WAAW,mDAiG9C"}
|