@trim21/personal-pi-extensions 0.1.689 → 0.1.691
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/README.md +3 -3
- package/package.json +2 -2
- package/src/bwrap/dcg-scan.ts +2 -8
- package/src/bwrap/html.ts +13 -0
- package/src/bwrap/network-stack.ts +2 -1
- package/src/bwrap/runtime.ts +1 -8
- package/src/claude-code/grep.ts +2 -1
- package/src/claude-code/shell.ts +13 -42
- package/src/codemode/declarations.ts +3 -8
- package/src/codemode/worker.js +11 -7
- package/src/codemode/worker.ts +10 -6
- package/src/gh/base.ts +91 -23
- package/src/gh/index.ts +8 -5
- package/src/gh/tools/download-release-assets.ts +6 -3
- package/src/gh/tools/get-workflow-jobs.ts +4 -7
- package/src/gh/tools/list-issues.ts +6 -39
- package/src/gh/tools/list-prs.ts +6 -39
- package/src/gh/tools/list-releases.ts +6 -9
- package/src/gh/tools/list-workflow-runs.ts +6 -9
- package/src/gh/tools/read-ci-logs.ts +8 -19
- package/src/gh/tools/read-issue-comments.ts +4 -12
- package/src/gh/tools/read-issue.ts +4 -12
- package/src/gh/tools/read-pr-comments.ts +6 -14
- package/src/gh/tools/read-pr-diff.ts +8 -8
- package/src/gh/tools/read-pr-status.ts +6 -4
- package/src/gh/tools/read-pr.ts +4 -12
- package/src/gh/tools/read-release.ts +5 -8
- package/src/gh/tools/read-repo.ts +5 -9
- package/src/gh/tools/wait-commit-checks.ts +2 -4
- package/src/gh/tools/wait-pr-checks.ts +2 -4
- package/src/gh/tools/watch-run.ts +7 -4
- package/src/lib/abort.ts +10 -0
- package/src/lib/bash-tool.ts +48 -0
- package/src/lib/github-reads.ts +3 -23
- package/src/lib/github.ts +81 -41
- package/src/lib/lsp/client.ts +1 -1
- package/src/lib/lsp/server-config.ts +1 -0
- package/src/lib/model-call.ts +3 -7
- package/src/lib/tools-config.ts +2 -4
- package/src/opencode/bash.ts +11 -42
- package/src/opencode/files.ts +1 -0
- package/src/opencode/glob.ts +1 -6
- package/src/opencode/grep.ts +1 -6
- package/src/opencode/ripgrep.ts +5 -0
- package/src/talk/policy.ts +4 -4
- package/src/web/fetch.ts +2 -6
- package/src/web/search.ts +2 -6
- package/src/orphan-worker-cleaner.ts +0 -38
|
@@ -1,20 +1,19 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* `list-github-issues`:两条取数分支(关键词搜索走 octokit
|
|
3
|
-
*
|
|
2
|
+
* `list-github-issues`:两条取数分支(关键词搜索走 octokit 的 `/search/issues`,浏览走
|
|
3
|
+
* REST 列表端点)归一成同一套 `SearchHit`,因此文本渲染与结构化载荷只有一份实现。
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import { Type } from "typebox";
|
|
7
|
-
|
|
8
6
|
import { defineStructuredTool, type ToolBus } from "../../lib/tool-bus.js";
|
|
9
7
|
import {
|
|
10
8
|
browseList,
|
|
11
9
|
type GhClient,
|
|
10
|
+
listFilterParameters,
|
|
12
11
|
type ListFilters,
|
|
13
12
|
renderHitList,
|
|
14
13
|
type StructuredResultOf,
|
|
15
|
-
subtitlePendant,
|
|
16
14
|
type ToolCall,
|
|
17
15
|
toToolResult,
|
|
16
|
+
withPendant,
|
|
18
17
|
withStructuredResult,
|
|
19
18
|
} from "../base.js";
|
|
20
19
|
import { ghHitListPayloadSchema } from "../schemas.js";
|
|
@@ -29,9 +28,8 @@ async function listIssues(
|
|
|
29
28
|
: await browseList(gh, "issue", params, { cwd: ctx.cwd, signal, input: params });
|
|
30
29
|
const text = renderHitList("issue", hits, { repo, fields: params.fields });
|
|
31
30
|
const result = toToolResult(text, params);
|
|
32
|
-
result.details.pendant = subtitlePendant(params);
|
|
33
31
|
// 文本可能被行数/字节预算截断,载荷给全部命中
|
|
34
|
-
return withStructuredResult(result, { text, items: hits });
|
|
32
|
+
return withStructuredResult(withPendant(result, params), { text, items: hits });
|
|
35
33
|
}
|
|
36
34
|
|
|
37
35
|
export function addListIssuesTool(gh: GhClient, bus: ToolBus) {
|
|
@@ -42,38 +40,7 @@ export function addListIssuesTool(gh: GhClient, bus: ToolBus) {
|
|
|
42
40
|
description:
|
|
43
41
|
'List GitHub issues with optional filters and keyword search. When repo is omitted, keyword search runs across GitHub. Keyword search defaults to open issues — pass state="all" to include closed ones. Set fields to choose the columns of each result row.',
|
|
44
42
|
promptSnippet: "List or search GitHub issues",
|
|
45
|
-
parameters:
|
|
46
|
-
repo: Type.Optional(Type.String({ description: "OWNER/REPO (defaults to current repo)" })),
|
|
47
|
-
keywords: Type.Optional(Type.String({ description: "Search keywords (free text)" })),
|
|
48
|
-
state: Type.Optional(
|
|
49
|
-
Type.String({
|
|
50
|
-
description:
|
|
51
|
-
"open, closed, all (default: open; all applies to keyword search and covers closed too)",
|
|
52
|
-
}),
|
|
53
|
-
),
|
|
54
|
-
label: Type.Optional(Type.String({ description: "Filter by label" })),
|
|
55
|
-
// `@me` 只在关键词搜索分支可用:搜索 API 自己把它解析成当前登录用户。浏览分支走
|
|
56
|
-
// REST 列表端点,`@me` 按字面量转发,不会匹配到当前用户(本仓库不做展开)。
|
|
57
|
-
author: Type.Optional(
|
|
58
|
-
Type.String({
|
|
59
|
-
description: "Filter by author ('@me' works with keywords; browse takes it literally)",
|
|
60
|
-
}),
|
|
61
|
-
),
|
|
62
|
-
assignee: Type.Optional(
|
|
63
|
-
Type.String({
|
|
64
|
-
description:
|
|
65
|
-
"Filter by assignee ('@me' works with keywords; browse takes it literally)",
|
|
66
|
-
}),
|
|
67
|
-
),
|
|
68
|
-
milestone: Type.Optional(Type.String({ description: "Filter by milestone" })),
|
|
69
|
-
limit: Type.Optional(Type.Number({ description: "Max results (default 30, max 100)" })),
|
|
70
|
-
fields: Type.Optional(
|
|
71
|
-
Type.String({
|
|
72
|
-
description:
|
|
73
|
-
"Comma-separated columns for the rows (default: number,state,title,labels,updatedAt; adds repo when no repo given). Valid: number,state,title,url,author,labels,milestone,assignees,comments,repo,createdAt,updatedAt,closedAt",
|
|
74
|
-
}),
|
|
75
|
-
),
|
|
76
|
-
}),
|
|
43
|
+
parameters: listFilterParameters("issue"),
|
|
77
44
|
structuredSchema: ghHitListPayloadSchema,
|
|
78
45
|
async execute(_id, params, signal, onUpdate, ctx) {
|
|
79
46
|
return listIssues(gh, { params, ctx, signal, onUpdate });
|
package/src/gh/tools/list-prs.ts
CHANGED
|
@@ -1,20 +1,19 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* `list-github-prs`:与 `list-github-issues` 同一套两条分支(关键词搜索走 octokit
|
|
3
|
-
*
|
|
2
|
+
* `list-github-prs`:与 `list-github-issues` 同一套两条分支(关键词搜索走 octokit 的
|
|
3
|
+
* `/search/issues`,浏览走 REST 列表端点),归一成同一套 `SearchHit`。
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import { Type } from "typebox";
|
|
7
|
-
|
|
8
6
|
import { defineStructuredTool, type ToolBus } from "../../lib/tool-bus.js";
|
|
9
7
|
import {
|
|
10
8
|
browseList,
|
|
11
9
|
type GhClient,
|
|
10
|
+
listFilterParameters,
|
|
12
11
|
type ListFilters,
|
|
13
12
|
renderHitList,
|
|
14
13
|
type StructuredResultOf,
|
|
15
|
-
subtitlePendant,
|
|
16
14
|
type ToolCall,
|
|
17
15
|
toToolResult,
|
|
16
|
+
withPendant,
|
|
18
17
|
withStructuredResult,
|
|
19
18
|
} from "../base.js";
|
|
20
19
|
import { ghHitListPayloadSchema } from "../schemas.js";
|
|
@@ -29,9 +28,8 @@ async function listPrs(
|
|
|
29
28
|
: await browseList(gh, "pr", params, { cwd: ctx.cwd, signal, input: params });
|
|
30
29
|
const text = renderHitList("pr", hits, { repo, fields: params.fields });
|
|
31
30
|
const result = toToolResult(text, params);
|
|
32
|
-
result.details.pendant = subtitlePendant(params);
|
|
33
31
|
// 文本可能被行数/字节预算截断,载荷给全部命中
|
|
34
|
-
return withStructuredResult(result, { text, items: hits });
|
|
32
|
+
return withStructuredResult(withPendant(result, params), { text, items: hits });
|
|
35
33
|
}
|
|
36
34
|
|
|
37
35
|
export function addListPrsTool(gh: GhClient, bus: ToolBus) {
|
|
@@ -42,38 +40,7 @@ export function addListPrsTool(gh: GhClient, bus: ToolBus) {
|
|
|
42
40
|
description:
|
|
43
41
|
'List GitHub pull requests with optional filters and keyword search. When repo is omitted, keyword search runs across GitHub. Keyword search defaults to open PRs — pass state="merged", state="closed" (merged excluded) or state="all" to broaden. Set fields to choose the columns of each result row.',
|
|
44
42
|
promptSnippet: "List or search GitHub PRs",
|
|
45
|
-
parameters:
|
|
46
|
-
repo: Type.Optional(Type.String({ description: "OWNER/REPO (defaults to current repo)" })),
|
|
47
|
-
keywords: Type.Optional(Type.String({ description: "Search keywords (free text)" })),
|
|
48
|
-
state: Type.Optional(
|
|
49
|
-
Type.String({
|
|
50
|
-
description:
|
|
51
|
-
"open, closed, merged, all (default: open; all applies to keyword search and covers open + closed + merged)",
|
|
52
|
-
}),
|
|
53
|
-
),
|
|
54
|
-
label: Type.Optional(Type.String({ description: "Filter by label" })),
|
|
55
|
-
// `@me` 只在关键词搜索分支可用:搜索 API 自己把它解析成当前登录用户。浏览分支走
|
|
56
|
-
// REST 列表端点,`@me` 按字面量转发,不会匹配到当前用户(本仓库不做展开)。
|
|
57
|
-
author: Type.Optional(
|
|
58
|
-
Type.String({
|
|
59
|
-
description: "Filter by author ('@me' works with keywords; browse takes it literally)",
|
|
60
|
-
}),
|
|
61
|
-
),
|
|
62
|
-
assignee: Type.Optional(
|
|
63
|
-
Type.String({
|
|
64
|
-
description:
|
|
65
|
-
"Filter by assignee ('@me' works with keywords; browse takes it literally)",
|
|
66
|
-
}),
|
|
67
|
-
),
|
|
68
|
-
milestone: Type.Optional(Type.String({ description: "Filter by milestone" })),
|
|
69
|
-
limit: Type.Optional(Type.Number({ description: "Max results (default 30, max 100)" })),
|
|
70
|
-
fields: Type.Optional(
|
|
71
|
-
Type.String({
|
|
72
|
-
description:
|
|
73
|
-
"Comma-separated columns for the rows (default: number,state,title,labels,updatedAt; adds repo when no repo given). Valid: number,state,title,url,author,labels,milestone,assignees,comments,repo,createdAt,updatedAt,closedAt,mergedAt",
|
|
74
|
-
}),
|
|
75
|
-
),
|
|
76
|
-
}),
|
|
43
|
+
parameters: listFilterParameters("pr"),
|
|
77
44
|
structuredSchema: ghHitListPayloadSchema,
|
|
78
45
|
async execute(_id, params, signal, onUpdate, ctx) {
|
|
79
46
|
return listPrs(gh, { params, ctx, signal, onUpdate });
|
|
@@ -4,10 +4,9 @@ import { parseWithSchema } from "../../lib/parse-with-schema.js";
|
|
|
4
4
|
import { defineStructuredTool, type ToolBus } from "../../lib/tool-bus.js";
|
|
5
5
|
import {
|
|
6
6
|
type GhClient,
|
|
7
|
-
|
|
8
|
-
splitRepo,
|
|
9
|
-
subtitlePendant,
|
|
7
|
+
resolveRepoTarget,
|
|
10
8
|
toToolResult,
|
|
9
|
+
withPendant,
|
|
11
10
|
withStructuredResult,
|
|
12
11
|
} from "../base.js";
|
|
13
12
|
import { renderReleaseList } from "../render.js";
|
|
@@ -27,10 +26,9 @@ export function addListReleasesTool(gh: GhClient, bus: ToolBus) {
|
|
|
27
26
|
}),
|
|
28
27
|
structuredSchema: ghReleaseListPayloadSchema,
|
|
29
28
|
async execute(_id, params, signal, _onUpdate, ctx) {
|
|
30
|
-
const {
|
|
31
|
-
const
|
|
32
|
-
const
|
|
33
|
-
const items = await gh.reads.listReleases(owner, repoName, limit, signal);
|
|
29
|
+
const { limit } = params;
|
|
30
|
+
const { owner, name } = await resolveRepoTarget(params.repo, signal, ctx.cwd, params);
|
|
31
|
+
const items = await gh.reads.listReleases(owner, name, limit, signal);
|
|
34
32
|
const releases = parseWithSchema(Type.Array(ghReleaseSummarySchema), items);
|
|
35
33
|
// REST 没有 isLatest:按列表顺序取第一个非 draft / prerelease 的条目
|
|
36
34
|
const latestIndex = releases.findIndex(
|
|
@@ -40,8 +38,7 @@ export function addListReleasesTool(gh: GhClient, bus: ToolBus) {
|
|
|
40
38
|
releases.map((release, index) => ({ ...release, latest: index === latestIndex })),
|
|
41
39
|
);
|
|
42
40
|
const result = toToolResult(text, params);
|
|
43
|
-
result
|
|
44
|
-
return withStructuredResult(result, { text, releases });
|
|
41
|
+
return withStructuredResult(withPendant(result, params), { text, releases });
|
|
45
42
|
},
|
|
46
43
|
}),
|
|
47
44
|
);
|
|
@@ -4,10 +4,9 @@ import { parseWithSchema } from "../../lib/parse-with-schema.js";
|
|
|
4
4
|
import { defineStructuredTool, type ToolBus } from "../../lib/tool-bus.js";
|
|
5
5
|
import {
|
|
6
6
|
type GhClient,
|
|
7
|
-
|
|
8
|
-
splitRepo,
|
|
9
|
-
subtitlePendant,
|
|
7
|
+
resolveRepoTarget,
|
|
10
8
|
toToolResult,
|
|
9
|
+
withPendant,
|
|
11
10
|
withStructuredResult,
|
|
12
11
|
} from "../base.js";
|
|
13
12
|
import { renderRunList } from "../render.js";
|
|
@@ -31,15 +30,13 @@ export function addListWorkflowRunsTool(gh: GhClient, bus: ToolBus) {
|
|
|
31
30
|
}),
|
|
32
31
|
structuredSchema: ghRunListPayloadSchema,
|
|
33
32
|
async execute(_id, params, signal, _onUpdate, ctx) {
|
|
34
|
-
const {
|
|
35
|
-
const
|
|
36
|
-
const
|
|
37
|
-
const items = await gh.reads.listRuns(owner, repoName, { workflow, status, limit }, signal);
|
|
33
|
+
const { limit, status, workflow } = params;
|
|
34
|
+
const { owner, name } = await resolveRepoTarget(params.repo, signal, ctx.cwd, params);
|
|
35
|
+
const items = await gh.reads.listRuns(owner, name, { workflow, status, limit }, signal);
|
|
38
36
|
const runs = parseWithSchema(Type.Array(ghRunSummarySchema), items);
|
|
39
37
|
const text = renderRunList(runs);
|
|
40
38
|
const result = toToolResult(text, params);
|
|
41
|
-
result
|
|
42
|
-
return withStructuredResult(result, { text, runs });
|
|
39
|
+
return withStructuredResult(withPendant(result, params), { text, runs });
|
|
43
40
|
},
|
|
44
41
|
}),
|
|
45
42
|
);
|
|
@@ -9,12 +9,12 @@ import { dirname, join } from "node:path";
|
|
|
9
9
|
|
|
10
10
|
import { Type } from "typebox";
|
|
11
11
|
|
|
12
|
-
import type
|
|
12
|
+
import { isNotFound, type RunJob } from "../../lib/github.js";
|
|
13
13
|
import { createSeqState } from "../../lib/seq-state.js";
|
|
14
14
|
import { defineStructuredTool, type ToolBus } from "../../lib/tool-bus.js";
|
|
15
15
|
import {
|
|
16
16
|
type GhClient,
|
|
17
|
-
|
|
17
|
+
resolveRepoTarget,
|
|
18
18
|
splitRepo,
|
|
19
19
|
structuredFailure,
|
|
20
20
|
type StructuredFailureResult,
|
|
@@ -299,19 +299,6 @@ export function stepLineSpans(log: string, apiSteps: readonly StepRef[]): Map<nu
|
|
|
299
299
|
return spans;
|
|
300
300
|
}
|
|
301
301
|
|
|
302
|
-
/** Text of `stepNumber` in its raw log, or null when the step never ran. */
|
|
303
|
-
export function extractStepFromLog(
|
|
304
|
-
log: string,
|
|
305
|
-
stepNumber: number,
|
|
306
|
-
apiSteps: readonly { number: number; name: string }[],
|
|
307
|
-
): string | null {
|
|
308
|
-
const span = stepLineSpans(log, apiSteps).get(stepNumber);
|
|
309
|
-
if (span === undefined) {
|
|
310
|
-
return null;
|
|
311
|
-
}
|
|
312
|
-
return log.split("\n").slice(span.start, span.end).join("\n").trimEnd();
|
|
313
|
-
}
|
|
314
|
-
|
|
315
302
|
/** One step of a job, indexed into the job's raw log file. */
|
|
316
303
|
export interface CiLogsStepIndex {
|
|
317
304
|
number: number;
|
|
@@ -374,8 +361,11 @@ async function ciLogs(gh: GhClient, call: ToolCall<JobIdParams>): Promise<CiLogs
|
|
|
374
361
|
const jobId = toPositiveId(job_id, "job_id");
|
|
375
362
|
|
|
376
363
|
const pendant = subtitlePendant(params, "job_id");
|
|
377
|
-
const
|
|
378
|
-
|
|
364
|
+
const {
|
|
365
|
+
fullName: effectiveRepo,
|
|
366
|
+
owner,
|
|
367
|
+
name,
|
|
368
|
+
} = await resolveRepoTarget(repo, signal, ctx.cwd, params);
|
|
379
369
|
|
|
380
370
|
const failure = (text: string): StructuredFailureResult => ({
|
|
381
371
|
content: [{ type: "text", text }],
|
|
@@ -387,8 +377,7 @@ async function ciLogs(gh: GhClient, call: ToolCall<JobIdParams>): Promise<CiLogs
|
|
|
387
377
|
try {
|
|
388
378
|
target = await gh.checks.job(owner, name, jobId, signal);
|
|
389
379
|
} catch (error) {
|
|
390
|
-
|
|
391
|
-
if (status !== 404) {
|
|
380
|
+
if (!isNotFound(error)) {
|
|
392
381
|
throw error;
|
|
393
382
|
}
|
|
394
383
|
return failure(
|
|
@@ -1,13 +1,7 @@
|
|
|
1
1
|
import { Type } from "typebox";
|
|
2
2
|
|
|
3
3
|
import { defineStructuredTool, type ToolBus } from "../../lib/tool-bus.js";
|
|
4
|
-
import {
|
|
5
|
-
type GhClient,
|
|
6
|
-
resolveRepo,
|
|
7
|
-
splitRepo,
|
|
8
|
-
subtitlePendant,
|
|
9
|
-
toStructuredJsonResult,
|
|
10
|
-
} from "../base.js";
|
|
4
|
+
import { type GhClient, resolveRepoTarget, toStructuredJsonResult, withPendant } from "../base.js";
|
|
11
5
|
import { issueCommentsSchema } from "../schemas.js";
|
|
12
6
|
|
|
13
7
|
export function addReadIssueCommentsTool(gh: GhClient, bus: ToolBus) {
|
|
@@ -24,16 +18,14 @@ export function addReadIssueCommentsTool(gh: GhClient, bus: ToolBus) {
|
|
|
24
18
|
structuredSchema: issueCommentsSchema,
|
|
25
19
|
async execute(_id, params, signal, _onUpdate, ctx) {
|
|
26
20
|
const { number, repo } = params;
|
|
27
|
-
const
|
|
28
|
-
const
|
|
29
|
-
const comments = await gh.reads.issueComments(owner, repoName, Number(number), signal);
|
|
21
|
+
const { owner, name } = await resolveRepoTarget(repo, signal, ctx.cwd, params);
|
|
22
|
+
const comments = await gh.reads.issueComments(owner, name, Number(number), signal);
|
|
30
23
|
const result = toStructuredJsonResult(
|
|
31
24
|
JSON.stringify({ comments }, null, 2),
|
|
32
25
|
params,
|
|
33
26
|
issueCommentsSchema,
|
|
34
27
|
);
|
|
35
|
-
result
|
|
36
|
-
return result;
|
|
28
|
+
return withPendant(result, params, "number");
|
|
37
29
|
},
|
|
38
30
|
}),
|
|
39
31
|
);
|
|
@@ -1,13 +1,7 @@
|
|
|
1
1
|
import { Type } from "typebox";
|
|
2
2
|
|
|
3
3
|
import { defineStructuredTool, type ToolBus } from "../../lib/tool-bus.js";
|
|
4
|
-
import {
|
|
5
|
-
type GhClient,
|
|
6
|
-
resolveRepo,
|
|
7
|
-
splitRepo,
|
|
8
|
-
subtitlePendant,
|
|
9
|
-
toStructuredJsonResult,
|
|
10
|
-
} from "../base.js";
|
|
4
|
+
import { type GhClient, resolveRepoTarget, toStructuredJsonResult, withPendant } from "../base.js";
|
|
11
5
|
import { issueViewSchema } from "../schemas.js";
|
|
12
6
|
|
|
13
7
|
export function addReadIssueTool(gh: GhClient, bus: ToolBus) {
|
|
@@ -24,16 +18,14 @@ export function addReadIssueTool(gh: GhClient, bus: ToolBus) {
|
|
|
24
18
|
structuredSchema: issueViewSchema,
|
|
25
19
|
async execute(_id, params, signal, _onUpdate, ctx) {
|
|
26
20
|
const { number, repo } = params;
|
|
27
|
-
const
|
|
28
|
-
const
|
|
29
|
-
const data = await gh.reads.issue(owner, repoName, Number(number), signal);
|
|
21
|
+
const { owner, name } = await resolveRepoTarget(repo, signal, ctx.cwd, params);
|
|
22
|
+
const data = await gh.reads.issue(owner, name, Number(number), signal);
|
|
30
23
|
const result = toStructuredJsonResult(
|
|
31
24
|
JSON.stringify(data, null, 2),
|
|
32
25
|
params,
|
|
33
26
|
issueViewSchema,
|
|
34
27
|
);
|
|
35
|
-
result
|
|
36
|
-
return result;
|
|
28
|
+
return withPendant(result, params, "number");
|
|
37
29
|
},
|
|
38
30
|
}),
|
|
39
31
|
);
|
|
@@ -1,13 +1,7 @@
|
|
|
1
1
|
import { Type } from "typebox";
|
|
2
2
|
|
|
3
3
|
import { defineStructuredTool, type ToolBus } from "../../lib/tool-bus.js";
|
|
4
|
-
import {
|
|
5
|
-
type GhClient,
|
|
6
|
-
resolveRepo,
|
|
7
|
-
splitRepo,
|
|
8
|
-
subtitlePendant,
|
|
9
|
-
toStructuredJsonResult,
|
|
10
|
-
} from "../base.js";
|
|
4
|
+
import { type GhClient, resolveRepoTarget, toStructuredJsonResult, withPendant } from "../base.js";
|
|
11
5
|
import { prCommentsSchema } from "../schemas.js";
|
|
12
6
|
|
|
13
7
|
export function addReadPrCommentsTool(gh: GhClient, bus: ToolBus) {
|
|
@@ -31,18 +25,17 @@ export function addReadPrCommentsTool(gh: GhClient, bus: ToolBus) {
|
|
|
31
25
|
structuredSchema: prCommentsSchema,
|
|
32
26
|
async execute(_id, params, signal, _onUpdate, ctx) {
|
|
33
27
|
const { number, repo, reviews } = params;
|
|
34
|
-
const
|
|
35
|
-
const { owner, repo: repoName } = splitRepo(effectiveRepo);
|
|
28
|
+
const { owner, name } = await resolveRepoTarget(repo, signal, ctx.cwd, params);
|
|
36
29
|
const pullNumber = Number(number);
|
|
37
30
|
|
|
38
31
|
// reviews=true 给行内评审评论 + 评审摘要;缺省给 PR 上的普通(issue)评论
|
|
39
32
|
const payload = reviews
|
|
40
33
|
? {
|
|
41
|
-
reviews: await gh.reads.pullReviews(owner,
|
|
42
|
-
comments: await gh.reads.pullReviewComments(owner,
|
|
34
|
+
reviews: await gh.reads.pullReviews(owner, name, pullNumber, signal),
|
|
35
|
+
comments: await gh.reads.pullReviewComments(owner, name, pullNumber, signal),
|
|
43
36
|
}
|
|
44
37
|
: {
|
|
45
|
-
comments: await gh.reads.issueComments(owner,
|
|
38
|
+
comments: await gh.reads.issueComments(owner, name, pullNumber, signal),
|
|
46
39
|
};
|
|
47
40
|
|
|
48
41
|
const result = toStructuredJsonResult(
|
|
@@ -50,8 +43,7 @@ export function addReadPrCommentsTool(gh: GhClient, bus: ToolBus) {
|
|
|
50
43
|
params,
|
|
51
44
|
prCommentsSchema,
|
|
52
45
|
);
|
|
53
|
-
result
|
|
54
|
-
return result;
|
|
46
|
+
return withPendant(result, params, "number");
|
|
55
47
|
},
|
|
56
48
|
}),
|
|
57
49
|
);
|
|
@@ -3,10 +3,9 @@ import { Type } from "typebox";
|
|
|
3
3
|
import { defineStructuredTool, type ToolBus } from "../../lib/tool-bus.js";
|
|
4
4
|
import {
|
|
5
5
|
type GhClient,
|
|
6
|
-
|
|
7
|
-
splitRepo,
|
|
8
|
-
subtitlePendant,
|
|
6
|
+
resolveRepoTarget,
|
|
9
7
|
toToolResult,
|
|
8
|
+
withPendant,
|
|
10
9
|
withStructuredResult,
|
|
11
10
|
} from "../base.js";
|
|
12
11
|
import { parseDiffStats } from "../render.js";
|
|
@@ -26,13 +25,14 @@ export function addReadPrDiffTool(gh: GhClient, bus: ToolBus) {
|
|
|
26
25
|
structuredSchema: ghDiffPayloadSchema,
|
|
27
26
|
async execute(_id, params, signal, _onUpdate, ctx) {
|
|
28
27
|
const { number, repo } = params;
|
|
29
|
-
const
|
|
30
|
-
const
|
|
31
|
-
const diff = await gh.reads.pullDiff(owner, repoName, Number(number), signal);
|
|
28
|
+
const { owner, name } = await resolveRepoTarget(repo, signal, ctx.cwd, params);
|
|
29
|
+
const diff = await gh.reads.pullDiff(owner, name, Number(number), signal);
|
|
32
30
|
const result = toToolResult(diff, params);
|
|
33
|
-
result.details.pendant = subtitlePendant(params, "number");
|
|
34
31
|
// 文本是原始 diff(没有 JSON 形式),载荷从同一份 diff 解析出变更统计
|
|
35
|
-
return withStructuredResult(result,
|
|
32
|
+
return withStructuredResult(withPendant(result, params, "number"), {
|
|
33
|
+
text: diff,
|
|
34
|
+
...parseDiffStats(diff),
|
|
35
|
+
});
|
|
36
36
|
},
|
|
37
37
|
}),
|
|
38
38
|
);
|
|
@@ -4,8 +4,7 @@ import { defineStructuredTool, type ToolBus } from "../../lib/tool-bus.js";
|
|
|
4
4
|
import {
|
|
5
5
|
type GhClient,
|
|
6
6
|
mergeChecks,
|
|
7
|
-
|
|
8
|
-
splitRepo,
|
|
7
|
+
resolveRepoTarget,
|
|
9
8
|
type StructuredResultOf,
|
|
10
9
|
subtitlePendant,
|
|
11
10
|
type ToolCall,
|
|
@@ -32,8 +31,11 @@ export async function prStatus(
|
|
|
32
31
|
const { number, repo } = params;
|
|
33
32
|
const pullNumber = toPositiveId(number, "number");
|
|
34
33
|
const pendant = subtitlePendant(params, "number");
|
|
35
|
-
const
|
|
36
|
-
|
|
34
|
+
const {
|
|
35
|
+
fullName: effectiveRepo,
|
|
36
|
+
owner,
|
|
37
|
+
name,
|
|
38
|
+
} = await resolveRepoTarget(repo, signal, ctx.cwd, params);
|
|
37
39
|
|
|
38
40
|
const pollSignal = signal ?? new AbortController().signal;
|
|
39
41
|
const headSha = await gh.checks.pullHead(owner, name, pullNumber, pollSignal);
|
package/src/gh/tools/read-pr.ts
CHANGED
|
@@ -1,13 +1,7 @@
|
|
|
1
1
|
import { Type } from "typebox";
|
|
2
2
|
|
|
3
3
|
import { defineStructuredTool, type ToolBus } from "../../lib/tool-bus.js";
|
|
4
|
-
import {
|
|
5
|
-
type GhClient,
|
|
6
|
-
resolveRepo,
|
|
7
|
-
splitRepo,
|
|
8
|
-
subtitlePendant,
|
|
9
|
-
toStructuredJsonResult,
|
|
10
|
-
} from "../base.js";
|
|
4
|
+
import { type GhClient, resolveRepoTarget, toStructuredJsonResult, withPendant } from "../base.js";
|
|
11
5
|
import { prViewSchema } from "../schemas.js";
|
|
12
6
|
|
|
13
7
|
export function addReadPrTool(gh: GhClient, bus: ToolBus) {
|
|
@@ -24,12 +18,10 @@ export function addReadPrTool(gh: GhClient, bus: ToolBus) {
|
|
|
24
18
|
structuredSchema: prViewSchema,
|
|
25
19
|
async execute(_id, params, signal, _onUpdate, ctx) {
|
|
26
20
|
const { number, repo } = params;
|
|
27
|
-
const
|
|
28
|
-
const
|
|
29
|
-
const data = await gh.reads.pull(owner, repoName, Number(number), signal);
|
|
21
|
+
const { owner, name } = await resolveRepoTarget(repo, signal, ctx.cwd, params);
|
|
22
|
+
const data = await gh.reads.pull(owner, name, Number(number), signal);
|
|
30
23
|
const result = toStructuredJsonResult(JSON.stringify(data, null, 2), params, prViewSchema);
|
|
31
|
-
result
|
|
32
|
-
return result;
|
|
24
|
+
return withPendant(result, params, "number");
|
|
33
25
|
},
|
|
34
26
|
}),
|
|
35
27
|
);
|
|
@@ -4,10 +4,9 @@ import { parseWithSchema } from "../../lib/parse-with-schema.js";
|
|
|
4
4
|
import { defineStructuredTool, type ToolBus } from "../../lib/tool-bus.js";
|
|
5
5
|
import {
|
|
6
6
|
type GhClient,
|
|
7
|
-
|
|
8
|
-
splitRepo,
|
|
9
|
-
subtitlePendant,
|
|
7
|
+
resolveRepoTarget,
|
|
10
8
|
toToolResult,
|
|
9
|
+
withPendant,
|
|
11
10
|
withStructuredResult,
|
|
12
11
|
} from "../base.js";
|
|
13
12
|
import { renderReleaseView } from "../render.js";
|
|
@@ -28,14 +27,12 @@ export function addReadReleaseTool(gh: GhClient, bus: ToolBus) {
|
|
|
28
27
|
structuredSchema: ghReleaseViewPayloadSchema,
|
|
29
28
|
async execute(_id, params, signal, _onUpdate, ctx) {
|
|
30
29
|
const { tag, repo } = params;
|
|
31
|
-
const
|
|
32
|
-
const
|
|
33
|
-
const data = await gh.reads.release(owner, repoName, tag, signal);
|
|
30
|
+
const { owner, name } = await resolveRepoTarget(repo, signal, ctx.cwd, params);
|
|
31
|
+
const data = await gh.reads.release(owner, name, tag, signal);
|
|
34
32
|
const view = parseWithSchema(ghReleaseViewSchema, data);
|
|
35
33
|
const text = renderReleaseView(view);
|
|
36
34
|
const result = toToolResult(text, params);
|
|
37
|
-
result
|
|
38
|
-
return withStructuredResult(result, { text, release: view });
|
|
35
|
+
return withStructuredResult(withPendant(result, params, "tag"), { text, release: view });
|
|
39
36
|
},
|
|
40
37
|
}),
|
|
41
38
|
);
|
|
@@ -4,10 +4,9 @@ import { parseWithSchema } from "../../lib/parse-with-schema.js";
|
|
|
4
4
|
import { defineStructuredTool, type ToolBus } from "../../lib/tool-bus.js";
|
|
5
5
|
import {
|
|
6
6
|
type GhClient,
|
|
7
|
-
|
|
8
|
-
splitRepo,
|
|
9
|
-
subtitlePendant,
|
|
7
|
+
resolveRepoTarget,
|
|
10
8
|
toToolResult,
|
|
9
|
+
withPendant,
|
|
11
10
|
withStructuredResult,
|
|
12
11
|
} from "../base.js";
|
|
13
12
|
import { renderRepoView } from "../render.js";
|
|
@@ -25,15 +24,12 @@ export function addReadRepoTool(gh: GhClient, bus: ToolBus) {
|
|
|
25
24
|
}),
|
|
26
25
|
structuredSchema: ghRepoPayloadSchema,
|
|
27
26
|
async execute(_id, params, signal, _onUpdate, ctx) {
|
|
28
|
-
const {
|
|
29
|
-
const
|
|
30
|
-
const { owner, repo: repoName } = splitRepo(effectiveRepo);
|
|
31
|
-
const data = await gh.reads.repository(owner, repoName, signal);
|
|
27
|
+
const { owner, name } = await resolveRepoTarget(params.repo, signal, ctx.cwd, params);
|
|
28
|
+
const data = await gh.reads.repository(owner, name, signal);
|
|
32
29
|
const view = parseWithSchema(ghRepoViewSchema, data);
|
|
33
30
|
const text = renderRepoView(view);
|
|
34
31
|
const result = toToolResult(text, params);
|
|
35
|
-
result
|
|
36
|
-
return withStructuredResult(result, { text, repo: view });
|
|
32
|
+
return withStructuredResult(withPendant(result, params), { text, repo: view });
|
|
37
33
|
},
|
|
38
34
|
}),
|
|
39
35
|
);
|
|
@@ -3,8 +3,7 @@ import { Type } from "typebox";
|
|
|
3
3
|
import { defineStructuredTool, type ToolBus } from "../../lib/tool-bus.js";
|
|
4
4
|
import {
|
|
5
5
|
type GhClient,
|
|
6
|
-
|
|
7
|
-
splitRepo,
|
|
6
|
+
resolveRepoTarget,
|
|
8
7
|
type StructuredResultOf,
|
|
9
8
|
subtitlePendant,
|
|
10
9
|
type ToolCall,
|
|
@@ -33,8 +32,7 @@ async function waitCommitChecks(
|
|
|
33
32
|
details: {},
|
|
34
33
|
});
|
|
35
34
|
|
|
36
|
-
const
|
|
37
|
-
const { owner, repo: repoName } = splitRepo(effectiveRepo);
|
|
35
|
+
const { owner, name: repoName } = await resolveRepoTarget(repo, signal, ctx.cwd, params);
|
|
38
36
|
|
|
39
37
|
const pollSignal = signal ?? new AbortController().signal;
|
|
40
38
|
const sha = await gh.checks.headSha(owner, repoName, String(commit), pollSignal);
|
|
@@ -4,8 +4,7 @@ import { Value } from "typebox/value";
|
|
|
4
4
|
import { defineStructuredTool, type ToolBus } from "../../lib/tool-bus.js";
|
|
5
5
|
import {
|
|
6
6
|
type GhClient,
|
|
7
|
-
|
|
8
|
-
splitRepo,
|
|
7
|
+
resolveRepoTarget,
|
|
9
8
|
type StructuredResultOf,
|
|
10
9
|
subtitlePendant,
|
|
11
10
|
type ToolCall,
|
|
@@ -36,8 +35,7 @@ async function waitPrChecks(
|
|
|
36
35
|
details: {},
|
|
37
36
|
});
|
|
38
37
|
|
|
39
|
-
const
|
|
40
|
-
const { owner, repo: repoName } = splitRepo(effectiveRepo);
|
|
38
|
+
const { owner, name: repoName } = await resolveRepoTarget(repo, signal, ctx.cwd, params);
|
|
41
39
|
|
|
42
40
|
const pull = Value.Parse(
|
|
43
41
|
pullHeadSchema,
|
|
@@ -4,8 +4,7 @@ import { defineStructuredTool, type ToolBus } from "../../lib/tool-bus.js";
|
|
|
4
4
|
import {
|
|
5
5
|
type GhClient,
|
|
6
6
|
renderRunStatus,
|
|
7
|
-
|
|
8
|
-
splitRepo,
|
|
7
|
+
resolveRepoTarget,
|
|
9
8
|
subtitlePendant,
|
|
10
9
|
type ToolResult,
|
|
11
10
|
watchRun,
|
|
@@ -38,8 +37,12 @@ export function addWatchRunTool(gh: GhClient, bus: ToolBus) {
|
|
|
38
37
|
|
|
39
38
|
// 轮询循环要求非空 signal(与两个 wait 工具一致:没有就自建一个)
|
|
40
39
|
const pollSignal = signal ?? new AbortController().signal;
|
|
41
|
-
const
|
|
42
|
-
|
|
40
|
+
const { owner, name: repoName } = await resolveRepoTarget(
|
|
41
|
+
repo,
|
|
42
|
+
pollSignal,
|
|
43
|
+
ctx.cwd,
|
|
44
|
+
params,
|
|
45
|
+
);
|
|
43
46
|
const outcome = await watchRun({
|
|
44
47
|
owner,
|
|
45
48
|
repo: repoName,
|
package/src/lib/abort.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 把调用方的取消信号与一个本地超时合并成单个 AbortSignal。
|
|
3
|
+
*
|
|
4
|
+
* 调用方可能不传 signal(例如 agent 空闲时的 `ctx.signal`),那时仍然要有超时兜底,
|
|
5
|
+
* 所以本地 `AbortSignal.timeout` 始终生效,两者都触发时以先到者为准。
|
|
6
|
+
*/
|
|
7
|
+
export function withTimeoutSignal(signal: AbortSignal | undefined, ms: number): AbortSignal {
|
|
8
|
+
const timeout = AbortSignal.timeout(ms);
|
|
9
|
+
return signal ? AbortSignal.any([signal, timeout]) : timeout;
|
|
10
|
+
}
|