@a9n-shoji/rvw 0.8.0 → 0.8.1
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/CHANGELOG.md +10 -0
- package/README.md +3 -2
- package/dist/cli.mjs +137 -14
- package/dist/cli.mjs.map +2 -2
- package/dist/web/assets/{StructureViewer-H6GjgwjT.js → StructureViewer-CfKcqesY.js} +1 -1
- package/dist/web/assets/index-Djf7DVF4.js +11 -0
- package/dist/web/index.html +1 -1
- package/package.json +1 -1
- package/dist/web/assets/index--jtTJT6K.js +0 -11
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,16 @@
|
|
|
5
5
|
|
|
6
6
|
## [Unreleased]
|
|
7
7
|
|
|
8
|
+
## [0.8.1] - 2026-09-14
|
|
9
|
+
|
|
10
|
+
### Changed
|
|
11
|
+
|
|
12
|
+
- コメント対象とコメント内のcode参照を、現在選択中のcommitへ安全に配置できる場合はその比較documentで直接開き、変更・削除・曖昧な場合は投稿時点のsourceへfallbackするようにした
|
|
13
|
+
|
|
14
|
+
### Fixed
|
|
15
|
+
|
|
16
|
+
- 承認後にコメントのみのreviewが追加されたPull Requestで、GitHub上の現在の承認数が0件として表示される問題を修正
|
|
17
|
+
|
|
8
18
|
## [0.8.0] - 2026-09-13
|
|
9
19
|
|
|
10
20
|
### Added
|
package/README.md
CHANGED
|
@@ -112,7 +112,7 @@ viewerはこの流れのために次を提供します。
|
|
|
112
112
|
- ファイル名fuzzy検索、Gitによるrealtime全文fixed-string検索(case / whole-word、file grouping、行jump)
|
|
113
113
|
- PR全体、PR本文、ファイル全体、行範囲、Walkthrough全体へのコメント
|
|
114
114
|
- コメントと返信のsafe GFM表示(repository内link/同一commit相対画像、表示専用Mermaid、
|
|
115
|
-
exact commit
|
|
115
|
+
global対象commitへ安全に配置し、できなければexact commitへfallbackするinline code referenceを含む)
|
|
116
116
|
- 未解決/解決済み、返信、Outdated追跡
|
|
117
117
|
- Agentへ渡す一件・一覧・複数選択した`rvw://comment/<uuid>`参照のコピー
|
|
118
118
|
- Agentが提示したWalkthrough、exact code reference、選択可能なMermaid node
|
|
@@ -291,7 +291,8 @@ rvw Skillを使って、https://github.com/owner/repository/pull/123 の未解
|
|
|
291
291
|
Agentにreview結果をRVWへ残してもらう場合は、対象PRとコメント作成を明示します。Agentはcommit済みの
|
|
292
292
|
exact sourceを確認し、通常の未解決threadを一件ずつ作成します。指摘や回答の理解に別の実装箇所が
|
|
293
293
|
必要なら、投稿本文の`rvw-ref:<id>` linkと同じ投稿に保存したtyped referenceから、その時点のcommitを
|
|
294
|
-
globalなcommit選択を変えずに開けます。
|
|
294
|
+
globalなcommit選択を変えずに開けます。global対象commitへ安全に配置できるreferenceは現在の比較で直接開き、
|
|
295
|
+
内容変更や削除などで配置できない場合は投稿時点のexact sourceへfallbackします。
|
|
295
296
|
|
|
296
297
|
```text
|
|
297
298
|
rvw Skillを使って、https://github.com/owner/repository/pull/123 をreviewし、見つけた指摘をRVWのコメントとして作成してください。
|
package/dist/cli.mjs
CHANGED
|
@@ -18762,7 +18762,7 @@ function parseWalkthroughUri(uri) {
|
|
|
18762
18762
|
}
|
|
18763
18763
|
|
|
18764
18764
|
// src/shared/constants.ts
|
|
18765
|
-
var APP_VERSION = "0.8.
|
|
18765
|
+
var APP_VERSION = "0.8.1";
|
|
18766
18766
|
var PROTOCOL_VERSION = 5;
|
|
18767
18767
|
var VIEWER_ID_HEADER = "x-rvw-viewer-id";
|
|
18768
18768
|
var VIEWER_OPEN_LEASE_HEADER = "x-rvw-viewer-open-lease";
|
|
@@ -21493,6 +21493,7 @@ function imageContentTypeHeader(contentType2) {
|
|
|
21493
21493
|
|
|
21494
21494
|
// src/infrastructure/github/github-client.ts
|
|
21495
21495
|
var ghPullRequestSchema = external_exports.object({
|
|
21496
|
+
id: external_exports.string().min(1),
|
|
21496
21497
|
author: external_exports.object({ login: external_exports.string().min(1) }).nullable(),
|
|
21497
21498
|
headRepository: external_exports.object({ name: external_exports.string().min(1) }).nullable(),
|
|
21498
21499
|
headRepositoryOwner: external_exports.object({ login: external_exports.string().min(1) }).nullable(),
|
|
@@ -21507,17 +21508,36 @@ var ghPullRequestSchema = external_exports.object({
|
|
|
21507
21508
|
baseRefOid: external_exports.string().regex(GIT_OBJECT_ID_PATTERN),
|
|
21508
21509
|
headRefName: external_exports.string().min(1),
|
|
21509
21510
|
headRefOid: external_exports.string().regex(GIT_OBJECT_ID_PATTERN),
|
|
21510
|
-
createdAt: external_exports.string()
|
|
21511
|
-
latestReviews: external_exports.array(external_exports.object({ state: external_exports.string() }))
|
|
21511
|
+
createdAt: external_exports.string()
|
|
21512
21512
|
});
|
|
21513
21513
|
var ghPullRequestStatusSchema = external_exports.object({
|
|
21514
|
+
id: external_exports.string().min(1),
|
|
21514
21515
|
state: external_exports.enum(["OPEN", "CLOSED", "MERGED"]),
|
|
21515
|
-
isDraft: external_exports.boolean()
|
|
21516
|
-
latestReviews: external_exports.array(external_exports.object({ state: external_exports.string() }))
|
|
21516
|
+
isDraft: external_exports.boolean()
|
|
21517
21517
|
});
|
|
21518
|
-
|
|
21519
|
-
|
|
21520
|
-
|
|
21518
|
+
var ghOpinionatedReviewsSchema = external_exports.object({
|
|
21519
|
+
data: external_exports.object({
|
|
21520
|
+
node: external_exports.object({
|
|
21521
|
+
latestOpinionatedReviews: external_exports.object({
|
|
21522
|
+
nodes: external_exports.array(external_exports.object({ state: external_exports.string() })),
|
|
21523
|
+
pageInfo: external_exports.object({
|
|
21524
|
+
hasNextPage: external_exports.boolean(),
|
|
21525
|
+
endCursor: external_exports.string().nullable()
|
|
21526
|
+
})
|
|
21527
|
+
})
|
|
21528
|
+
}).nullable()
|
|
21529
|
+
})
|
|
21530
|
+
});
|
|
21531
|
+
var opinionatedReviewsQuery = `query PullRequestOpinionatedReviews($id: ID!, $after: String) {
|
|
21532
|
+
node(id: $id) {
|
|
21533
|
+
... on PullRequest {
|
|
21534
|
+
latestOpinionatedReviews(first: 100, after: $after) {
|
|
21535
|
+
nodes { state }
|
|
21536
|
+
pageInfo { hasNextPage endCursor }
|
|
21537
|
+
}
|
|
21538
|
+
}
|
|
21539
|
+
}
|
|
21540
|
+
}`;
|
|
21521
21541
|
function parsePullRequestUrl(url2) {
|
|
21522
21542
|
const match2 = /^https:\/\/github\.com\/([^/]+)\/([^/]+)\/pull\/(\d+)(?:\/.*)?$/.exec(url2);
|
|
21523
21543
|
if (!match2?.[1] || !match2[2] || !match2[3]) {
|
|
@@ -21547,12 +21567,80 @@ var GitHubClient = class {
|
|
|
21547
21567
|
});
|
|
21548
21568
|
}
|
|
21549
21569
|
}
|
|
21570
|
+
async getApprovalCount(pullRequestId) {
|
|
21571
|
+
let approvalCount = 0;
|
|
21572
|
+
let after = null;
|
|
21573
|
+
const seenCursors = /* @__PURE__ */ new Set();
|
|
21574
|
+
let hasNextPage = true;
|
|
21575
|
+
while (hasNextPage) {
|
|
21576
|
+
const args = [
|
|
21577
|
+
"api",
|
|
21578
|
+
"graphql",
|
|
21579
|
+
"--hostname",
|
|
21580
|
+
"github.com",
|
|
21581
|
+
"-f",
|
|
21582
|
+
`query=${opinionatedReviewsQuery}`,
|
|
21583
|
+
"-f",
|
|
21584
|
+
`id=${pullRequestId}`
|
|
21585
|
+
];
|
|
21586
|
+
if (after !== null) args.push("-f", `after=${after}`);
|
|
21587
|
+
let output;
|
|
21588
|
+
try {
|
|
21589
|
+
const result = await this.processRunner("gh", args, { timeoutMs: 6e4 });
|
|
21590
|
+
output = result.stdout.toString("utf8").trimEnd();
|
|
21591
|
+
} catch (error51) {
|
|
21592
|
+
if (error51 instanceof RvwError && error51.code === "PROCESS_FAILED") {
|
|
21593
|
+
throw new RvwError(
|
|
21594
|
+
"GITHUB_ERROR",
|
|
21595
|
+
"Pull Request\u306EApprove\u6570\u3092GitHub\u304B\u3089\u53D6\u5F97\u3067\u304D\u307E\u305B\u3093\u3067\u3057\u305F\u3002",
|
|
21596
|
+
{
|
|
21597
|
+
cause: error51,
|
|
21598
|
+
details: error51.details,
|
|
21599
|
+
suggestions: ["PR\u306E\u95B2\u89A7\u6A29\u9650\u3068gh\u8A8D\u8A3C\u3092\u78BA\u8A8D\u3057\u3066\u304F\u3060\u3055\u3044\u3002"]
|
|
21600
|
+
}
|
|
21601
|
+
);
|
|
21602
|
+
}
|
|
21603
|
+
throw error51;
|
|
21604
|
+
}
|
|
21605
|
+
let decoded;
|
|
21606
|
+
try {
|
|
21607
|
+
decoded = JSON.parse(output);
|
|
21608
|
+
} catch (error51) {
|
|
21609
|
+
throw new RvwError("GITHUB_ERROR", "GitHub CLI\u306EPull Request review\u5FDC\u7B54\u304C\u4E0D\u6B63\u3067\u3059\u3002", {
|
|
21610
|
+
cause: error51
|
|
21611
|
+
});
|
|
21612
|
+
}
|
|
21613
|
+
const parsed = ghOpinionatedReviewsSchema.safeParse(decoded);
|
|
21614
|
+
if (!parsed.success || parsed.data.data.node === null) {
|
|
21615
|
+
throw new RvwError("GITHUB_ERROR", "GitHub CLI\u306EPull Request review\u5FDC\u7B54\u304C\u4E0D\u6B63\u3067\u3059\u3002", {
|
|
21616
|
+
details: parsed.success ? { pullRequestId } : parsed.error.flatten()
|
|
21617
|
+
});
|
|
21618
|
+
}
|
|
21619
|
+
const reviews = parsed.data.data.node.latestOpinionatedReviews;
|
|
21620
|
+
approvalCount += reviews.nodes.filter((review) => review.state === "APPROVED").length;
|
|
21621
|
+
hasNextPage = reviews.pageInfo.hasNextPage;
|
|
21622
|
+
if (!hasNextPage) break;
|
|
21623
|
+
const nextCursor = reviews.pageInfo.endCursor;
|
|
21624
|
+
if (nextCursor === null || seenCursors.has(nextCursor)) {
|
|
21625
|
+
throw new RvwError(
|
|
21626
|
+
"GITHUB_ERROR",
|
|
21627
|
+
"GitHub CLI\u306EPull Request review pagination\u5FDC\u7B54\u304C\u4E0D\u6B63\u3067\u3059\u3002",
|
|
21628
|
+
{
|
|
21629
|
+
details: { pullRequestId }
|
|
21630
|
+
}
|
|
21631
|
+
);
|
|
21632
|
+
}
|
|
21633
|
+
seenCursors.add(nextCursor);
|
|
21634
|
+
after = nextCursor;
|
|
21635
|
+
}
|
|
21636
|
+
return approvalCount;
|
|
21637
|
+
}
|
|
21550
21638
|
async getPullRequestStatus(reference) {
|
|
21551
21639
|
let output;
|
|
21552
21640
|
try {
|
|
21553
21641
|
const result = await this.processRunner(
|
|
21554
21642
|
"gh",
|
|
21555
|
-
["pr", "view", reference, "--json", "state,isDraft
|
|
21643
|
+
["pr", "view", reference, "--json", "id,state,isDraft"],
|
|
21556
21644
|
{ timeoutMs: 6e4 }
|
|
21557
21645
|
);
|
|
21558
21646
|
output = result.stdout.toString("utf8").trimEnd();
|
|
@@ -21583,7 +21671,7 @@ var GitHubClient = class {
|
|
|
21583
21671
|
return {
|
|
21584
21672
|
state: parsed.data.state,
|
|
21585
21673
|
isDraft: parsed.data.isDraft,
|
|
21586
|
-
approvalCount:
|
|
21674
|
+
approvalCount: await this.getApprovalCount(parsed.data.id)
|
|
21587
21675
|
};
|
|
21588
21676
|
}
|
|
21589
21677
|
async getPullRequestStatuses(references) {
|
|
@@ -21625,6 +21713,7 @@ var GitHubClient = class {
|
|
|
21625
21713
|
async getPullRequest(reference, cwd, options = {}) {
|
|
21626
21714
|
await this.assertAuthenticated();
|
|
21627
21715
|
const fields = [
|
|
21716
|
+
"id",
|
|
21628
21717
|
"author",
|
|
21629
21718
|
"number",
|
|
21630
21719
|
"url",
|
|
@@ -21639,15 +21728,15 @@ var GitHubClient = class {
|
|
|
21639
21728
|
"headRefName",
|
|
21640
21729
|
"headRefOid",
|
|
21641
21730
|
"headRepository",
|
|
21642
|
-
"headRepositoryOwner"
|
|
21643
|
-
"latestReviews"
|
|
21731
|
+
"headRepositoryOwner"
|
|
21644
21732
|
].join(",");
|
|
21645
21733
|
const args = ["pr", "view"];
|
|
21646
21734
|
if (reference !== void 0 && reference.length > 0) args.push(reference);
|
|
21647
21735
|
args.push("--json", fields);
|
|
21648
21736
|
let output;
|
|
21649
21737
|
try {
|
|
21650
|
-
|
|
21738
|
+
const result = await this.processRunner("gh", args, { cwd, timeoutMs: 6e4 });
|
|
21739
|
+
output = result.stdout.toString("utf8").trimEnd();
|
|
21651
21740
|
} catch (error51) {
|
|
21652
21741
|
if (error51 instanceof RvwError && error51.code === "PROCESS_FAILED") {
|
|
21653
21742
|
throw new RvwError("GITHUB_ERROR", "Pull Request\u60C5\u5831\u3092GitHub\u304B\u3089\u53D6\u5F97\u3067\u304D\u307E\u305B\u3093\u3067\u3057\u305F\u3002", {
|
|
@@ -21690,7 +21779,7 @@ var GitHubClient = class {
|
|
|
21690
21779
|
updatedAt: parsed.data.updatedAt,
|
|
21691
21780
|
state: parsed.data.state,
|
|
21692
21781
|
isDraft: parsed.data.isDraft,
|
|
21693
|
-
approvalCount:
|
|
21782
|
+
approvalCount: await this.getApprovalCount(parsed.data.id)
|
|
21694
21783
|
};
|
|
21695
21784
|
}
|
|
21696
21785
|
async getAttachment(absoluteUrl) {
|
|
@@ -44315,6 +44404,23 @@ var RvwService = class {
|
|
|
44315
44404
|
this.createCommentPlacementRequestContext()
|
|
44316
44405
|
);
|
|
44317
44406
|
}
|
|
44407
|
+
async placeCodeReferenceAtCommit(pullRequestId, sourceOid, reference, destinationOid) {
|
|
44408
|
+
assertCodeReferencePath(reference.path);
|
|
44409
|
+
return await this.placeCommentAtCommit(
|
|
44410
|
+
{
|
|
44411
|
+
pullRequestId,
|
|
44412
|
+
target: {
|
|
44413
|
+
kind: "document",
|
|
44414
|
+
documentKind: "repository-file",
|
|
44415
|
+
sourceOid,
|
|
44416
|
+
path: reference.path,
|
|
44417
|
+
startLine: reference.startLine,
|
|
44418
|
+
endLine: reference.endLine
|
|
44419
|
+
}
|
|
44420
|
+
},
|
|
44421
|
+
destinationOid
|
|
44422
|
+
);
|
|
44423
|
+
}
|
|
44318
44424
|
async resolveCommentPlacements(pullRequestId, commentIds, destinations, expectedPullRequestContentFingerprint) {
|
|
44319
44425
|
const pullRequest = this.getPullRequest(pullRequestId);
|
|
44320
44426
|
const contentFingerprint = this.assertPullRequestContentFingerprint(
|
|
@@ -49477,6 +49583,11 @@ var resolveCommentPlacementsSchema = external_exports.object({
|
|
|
49477
49583
|
])
|
|
49478
49584
|
).min(1).max(4)
|
|
49479
49585
|
});
|
|
49586
|
+
var resolveCodeReferencePlacementSchema = external_exports.object({
|
|
49587
|
+
sourceOid: external_exports.string().regex(GIT_OBJECT_ID_PATTERN),
|
|
49588
|
+
destinationOid: external_exports.string().regex(GIT_OBJECT_ID_PATTERN),
|
|
49589
|
+
reference: codeReferenceInputSchema
|
|
49590
|
+
});
|
|
49480
49591
|
|
|
49481
49592
|
// src/server/app.ts
|
|
49482
49593
|
var oidSchema = external_exports.string().regex(GIT_OBJECT_ID_PATTERN);
|
|
@@ -49954,6 +50065,18 @@ function createApp(service, options) {
|
|
|
49954
50065
|
)
|
|
49955
50066
|
});
|
|
49956
50067
|
});
|
|
50068
|
+
app.post("/api/pull-requests/:pullRequestId/code-reference-placement", async (context) => {
|
|
50069
|
+
const input = resolveCodeReferencePlacementSchema.parse(await context.req.json());
|
|
50070
|
+
return context.json({
|
|
50071
|
+
ok: true,
|
|
50072
|
+
placement: await service.placeCodeReferenceAtCommit(
|
|
50073
|
+
context.req.param("pullRequestId"),
|
|
50074
|
+
input.sourceOid,
|
|
50075
|
+
input.reference,
|
|
50076
|
+
input.destinationOid
|
|
50077
|
+
)
|
|
50078
|
+
});
|
|
50079
|
+
});
|
|
49957
50080
|
app.get("/api/comments/:id/placement", async (context) => {
|
|
49958
50081
|
const comment3 = service.database.getComment(context.req.param("id"));
|
|
49959
50082
|
if (!comment3)
|