@difflab/pi 0.3.0-rc.202609201610.cddc7d6 → 0.3.0-rc.202609201720.4138cef
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/dist/extensions/index.js +69 -14
- package/dist/index.js +18 -11
- package/dist/review/github-review-backend.d.ts.map +1 -1
- package/dist/review/gitlab-review-backend.d.ts.map +1 -1
- package/dist/review/index.d.ts +2 -2
- package/dist/review/index.d.ts.map +1 -1
- package/dist/review/types.d.ts +6 -0
- package/dist/review/types.d.ts.map +1 -1
- package/dist/tools/index.js +69 -14
- package/dist/tools/review.d.ts.map +1 -1
- package/package.json +1 -1
- package/skills/review/references/workflows/publish.md +2 -2
package/dist/extensions/index.js
CHANGED
|
@@ -16861,6 +16861,15 @@ function localResponseMarker(threadId) {
|
|
|
16861
16861
|
function isLocalResponse(body) {
|
|
16862
16862
|
return /^<!-- diffpi(?:-local-response:[A-Za-z0-9_-]+)? -->\n/m.test(body);
|
|
16863
16863
|
}
|
|
16864
|
+
function parseReviewThreadAction(body) {
|
|
16865
|
+
const match = body.match(/^\[(REOPEN|RESOLVE)\]\s*/i);
|
|
16866
|
+
if (!match)
|
|
16867
|
+
return { body };
|
|
16868
|
+
return {
|
|
16869
|
+
action: match[1].toLowerCase(),
|
|
16870
|
+
body: body.slice(match[0].length)
|
|
16871
|
+
};
|
|
16872
|
+
}
|
|
16864
16873
|
function dedupeFindings(findings) {
|
|
16865
16874
|
const rank = { BLOCKING: 3, CONSIDER: 2, NOTE: 1 };
|
|
16866
16875
|
const byKey = new Map;
|
|
@@ -17199,16 +17208,18 @@ function GitHubReviewBackend(vcs, number) {
|
|
|
17199
17208
|
`body=${input.body}`
|
|
17200
17209
|
]);
|
|
17201
17210
|
}
|
|
17202
|
-
if (input.resolve)
|
|
17203
|
-
await
|
|
17204
|
-
|
|
17205
|
-
|
|
17206
|
-
|
|
17207
|
-
|
|
17208
|
-
|
|
17209
|
-
|
|
17210
|
-
|
|
17211
|
-
|
|
17211
|
+
if (input.resolve)
|
|
17212
|
+
await this.setResolved?.(input.threadId, true);
|
|
17213
|
+
},
|
|
17214
|
+
async setResolved(threadId, resolved) {
|
|
17215
|
+
await ghChecked([
|
|
17216
|
+
"api",
|
|
17217
|
+
"graphql",
|
|
17218
|
+
"-f",
|
|
17219
|
+
`query=${resolved ? GITHUB_RESOLVE_MUTATION : GITHUB_UNRESOLVE_MUTATION}`,
|
|
17220
|
+
"-f",
|
|
17221
|
+
`threadId=${threadId}`
|
|
17222
|
+
]);
|
|
17212
17223
|
},
|
|
17213
17224
|
async publish(event) {
|
|
17214
17225
|
const pending = await pendingReview();
|
|
@@ -17229,6 +17240,7 @@ var GITHUB_THREADS_QUERY = `query($owner:String!,$repo:String!,$number:Int!,$aft
|
|
|
17229
17240
|
var GITHUB_ADD_THREAD_MUTATION = `mutation($reviewId:ID!,$body:String!,$path:String!,$line:Int!,$side:DiffSide!){addPullRequestReviewThread(input:{pullRequestReviewId:$reviewId,body:$body,path:$path,line:$line,side:$side}){thread{id}}}`;
|
|
17230
17241
|
var GITHUB_REPLY_MUTATION = `mutation($threadId:ID!,$body:String!){addPullRequestReviewThreadReply(input:{pullRequestReviewThreadId:$threadId,body:$body}){comment{id}}}`;
|
|
17231
17242
|
var GITHUB_RESOLVE_MUTATION = `mutation($threadId:ID!){resolveReviewThread(input:{threadId:$threadId}){thread{isResolved}}}`;
|
|
17243
|
+
var GITHUB_UNRESOLVE_MUTATION = `mutation($threadId:ID!){unresolveReviewThread(input:{threadId:$threadId}){thread{isResolved}}}`;
|
|
17232
17244
|
|
|
17233
17245
|
// src/review/gitlab-review-backend.ts
|
|
17234
17246
|
function GitLabReviewBackend(vcs, number) {
|
|
@@ -17335,7 +17347,11 @@ function GitLabReviewBackend(vcs, number) {
|
|
|
17335
17347
|
});
|
|
17336
17348
|
}
|
|
17337
17349
|
if (input.resolve)
|
|
17338
|
-
await
|
|
17350
|
+
await this.setResolved?.(input.threadId, true);
|
|
17351
|
+
},
|
|
17352
|
+
async setResolved(threadId, resolved) {
|
|
17353
|
+
const endpoint = `${mergeRequestEndpoint()}/discussions/${encodeURIComponent(threadId)}`;
|
|
17354
|
+
await glabChecked(["api", "--method", "PUT", `${endpoint}?resolved=${resolved}`]);
|
|
17339
17355
|
},
|
|
17340
17356
|
async publish(event) {
|
|
17341
17357
|
assertReviewEventSupported(vcs.provider, event);
|
|
@@ -17749,7 +17765,16 @@ function createReviewTools() {
|
|
|
17749
17765
|
review.pr ? `PR/MR: #${review.pr.number} ${review.pr.url}` : "PR/MR: none",
|
|
17750
17766
|
session ? `tuicr: ${session.slug} (${session.commentCount} comments)` : "tuicr: none"
|
|
17751
17767
|
].join(`
|
|
17752
|
-
`), {
|
|
17768
|
+
`), {
|
|
17769
|
+
cwd: review.cwd,
|
|
17770
|
+
vcs: review.vcs,
|
|
17771
|
+
pr: review.pr,
|
|
17772
|
+
env,
|
|
17773
|
+
store,
|
|
17774
|
+
session,
|
|
17775
|
+
baseRef,
|
|
17776
|
+
backend
|
|
17777
|
+
});
|
|
17753
17778
|
}
|
|
17754
17779
|
}),
|
|
17755
17780
|
defineTool4({
|
|
@@ -18236,7 +18261,12 @@ async function promoteLocalReview(review, remote, model) {
|
|
|
18236
18261
|
author: localReviewAuthor(model)
|
|
18237
18262
|
});
|
|
18238
18263
|
const draft = await local.readDraft();
|
|
18239
|
-
const
|
|
18264
|
+
const remoteThreads = await remote.listThreads();
|
|
18265
|
+
const threadReplies = sessionIsWorkingTree ? [] : draft.comments.flatMap((comment) => {
|
|
18266
|
+
const thread = remoteThreads.find((candidate) => candidate.file === comment.file && candidate.line === comment.line && candidate.line !== undefined && !candidate.body.includes("Generated review by Diffpi using"));
|
|
18267
|
+
return thread ? [{ comment, thread }] : [];
|
|
18268
|
+
});
|
|
18269
|
+
const comments = draft.comments.filter(({ file, line }) => !threadReplies.some((reply) => reply.comment.file === file && reply.comment.line === line)).map((comment) => ({
|
|
18240
18270
|
...comment,
|
|
18241
18271
|
body: withRemoteProvenance(comment.body, comment.author?.replace(/^Agent:\s*/, "") || model)
|
|
18242
18272
|
}));
|
|
@@ -18252,7 +18282,7 @@ async function promoteLocalReview(review, remote, model) {
|
|
|
18252
18282
|
const unpublished = unpublishedReviewComments(comments, known);
|
|
18253
18283
|
if (unpublished.length > 0 || unpublishedBody)
|
|
18254
18284
|
await remote.stage({ comments: unpublished, body: unpublishedBody });
|
|
18255
|
-
const promotedReplies = await promoteLocalReplies(review, remote, publication, model, sessionIsWorkingTree);
|
|
18285
|
+
const promotedReplies = await promoteLocalReplies(review, remote, publication, model, sessionIsWorkingTree) + await promoteLocationReplies(remote, publication, threadReplies, model);
|
|
18256
18286
|
return {
|
|
18257
18287
|
publication,
|
|
18258
18288
|
bodyFingerprints,
|
|
@@ -18262,6 +18292,31 @@ async function promoteLocalReview(review, remote, model) {
|
|
|
18262
18292
|
promotedReplies
|
|
18263
18293
|
};
|
|
18264
18294
|
}
|
|
18295
|
+
async function promoteLocationReplies(remote, publication, replies, model) {
|
|
18296
|
+
let count = 0;
|
|
18297
|
+
for (const { comment, thread } of replies) {
|
|
18298
|
+
const parsed = parseReviewThreadAction(comment.body);
|
|
18299
|
+
const body = parsed.body.trim();
|
|
18300
|
+
const action = parsed.action;
|
|
18301
|
+
const fingerprint = reviewReplyFingerprint(thread.id, `${action ?? "reply"}\x00${body}`);
|
|
18302
|
+
if (publication.state.replies.includes(fingerprint))
|
|
18303
|
+
continue;
|
|
18304
|
+
const remoteBody = withRemoteProvenance(body, comment.author?.replace(/^Agent:\s*/, "") || model);
|
|
18305
|
+
if (body && !thread.replies?.some((reply) => reply === body || reply === remoteBody)) {
|
|
18306
|
+
await remote.reply({
|
|
18307
|
+
threadId: thread.id,
|
|
18308
|
+
body: remoteBody,
|
|
18309
|
+
resolve: false
|
|
18310
|
+
});
|
|
18311
|
+
}
|
|
18312
|
+
if (action && remote.setResolved)
|
|
18313
|
+
await remote.setResolved(thread.id, action === "resolve");
|
|
18314
|
+
publication.state.replies.push(fingerprint);
|
|
18315
|
+
await saveReviewPublicationState(publication.path, publication.state);
|
|
18316
|
+
count += 1;
|
|
18317
|
+
}
|
|
18318
|
+
return count;
|
|
18319
|
+
}
|
|
18265
18320
|
async function promoteLocalReplies(review, remote, publication, model, workingTree) {
|
|
18266
18321
|
const target = workingTree ? "uncommitted" : await reviewTargetId(review);
|
|
18267
18322
|
const artifact = workingTree ? await latestThreadArtifact(review.cwd, review, target) : publication.state.overlayPath ?? await latestThreadArtifact(review.cwd, review, target);
|
package/dist/index.js
CHANGED
|
@@ -1355,16 +1355,18 @@ function GitHubReviewBackend(vcs, number) {
|
|
|
1355
1355
|
`body=${input.body}`
|
|
1356
1356
|
]);
|
|
1357
1357
|
}
|
|
1358
|
-
if (input.resolve)
|
|
1359
|
-
await
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1358
|
+
if (input.resolve)
|
|
1359
|
+
await this.setResolved?.(input.threadId, true);
|
|
1360
|
+
},
|
|
1361
|
+
async setResolved(threadId, resolved) {
|
|
1362
|
+
await ghChecked([
|
|
1363
|
+
"api",
|
|
1364
|
+
"graphql",
|
|
1365
|
+
"-f",
|
|
1366
|
+
`query=${resolved ? GITHUB_RESOLVE_MUTATION : GITHUB_UNRESOLVE_MUTATION}`,
|
|
1367
|
+
"-f",
|
|
1368
|
+
`threadId=${threadId}`
|
|
1369
|
+
]);
|
|
1368
1370
|
},
|
|
1369
1371
|
async publish(event) {
|
|
1370
1372
|
const pending = await pendingReview();
|
|
@@ -1385,6 +1387,7 @@ var GITHUB_THREADS_QUERY = `query($owner:String!,$repo:String!,$number:Int!,$aft
|
|
|
1385
1387
|
var GITHUB_ADD_THREAD_MUTATION = `mutation($reviewId:ID!,$body:String!,$path:String!,$line:Int!,$side:DiffSide!){addPullRequestReviewThread(input:{pullRequestReviewId:$reviewId,body:$body,path:$path,line:$line,side:$side}){thread{id}}}`;
|
|
1386
1388
|
var GITHUB_REPLY_MUTATION = `mutation($threadId:ID!,$body:String!){addPullRequestReviewThreadReply(input:{pullRequestReviewThreadId:$threadId,body:$body}){comment{id}}}`;
|
|
1387
1389
|
var GITHUB_RESOLVE_MUTATION = `mutation($threadId:ID!){resolveReviewThread(input:{threadId:$threadId}){thread{isResolved}}}`;
|
|
1390
|
+
var GITHUB_UNRESOLVE_MUTATION = `mutation($threadId:ID!){unresolveReviewThread(input:{threadId:$threadId}){thread{isResolved}}}`;
|
|
1388
1391
|
|
|
1389
1392
|
// src/review/gitlab-review-backend.ts
|
|
1390
1393
|
function GitLabReviewBackend(vcs, number) {
|
|
@@ -1491,7 +1494,11 @@ function GitLabReviewBackend(vcs, number) {
|
|
|
1491
1494
|
});
|
|
1492
1495
|
}
|
|
1493
1496
|
if (input.resolve)
|
|
1494
|
-
await
|
|
1497
|
+
await this.setResolved?.(input.threadId, true);
|
|
1498
|
+
},
|
|
1499
|
+
async setResolved(threadId, resolved) {
|
|
1500
|
+
const endpoint = `${mergeRequestEndpoint()}/discussions/${encodeURIComponent(threadId)}`;
|
|
1501
|
+
await glabChecked(["api", "--method", "PUT", `${endpoint}?resolved=${resolved}`]);
|
|
1495
1502
|
},
|
|
1496
1503
|
async publish(event) {
|
|
1497
1504
|
assertReviewEventSupported(vcs.provider, event);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"github-review-backend.d.ts","sourceRoot":"","sources":["../../src/review/github-review-backend.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAE9C,OAAO,KAAK,EAAE,aAAa,EAAsB,MAAM,SAAS,CAAC;AAEjE,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,GAAG,aAAa,
|
|
1
|
+
{"version":3,"file":"github-review-backend.d.ts","sourceRoot":"","sources":["../../src/review/github-review-backend.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAE9C,OAAO,KAAK,EAAE,aAAa,EAAsB,MAAM,SAAS,CAAC;AAEjE,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,GAAG,aAAa,CA4M/E;AAED,wBAAgB,8BAA8B,CAC5C,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,MAAM,EACZ,EAAE,EAAE,MAAM,EACV,eAAe,EAAE,MAAM,GACtB,MAAM,CAIR"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gitlab-review-backend.d.ts","sourceRoot":"","sources":["../../src/review/gitlab-review-backend.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAE7D,OAAO,KAAK,EAAE,aAAa,EAAiB,WAAW,EAAsB,MAAM,SAAS,CAAC;AAE7F,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,GAAG,aAAa,
|
|
1
|
+
{"version":3,"file":"gitlab-review-backend.d.ts","sourceRoot":"","sources":["../../src/review/gitlab-review-backend.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAE7D,OAAO,KAAK,EAAE,aAAa,EAAiB,WAAW,EAAsB,MAAM,SAAS,CAAC;AAE7F,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,GAAG,aAAa,CA+H/E;AAED,wBAAgB,0BAA0B,CAAC,QAAQ,EAAE,aAAa,EAAE,KAAK,EAAE,WAAW,GAAG,IAAI,CAM5F;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,cAAc,CAYjE;AAED,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAO1D"}
|
package/dist/review/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
export { dedupeFindings, findingSchema, findingsSchema, isLocalResponse, localResponseMarker, localReviewAuthor, reviewRecordName, reviewSlug, severitySchema, toReviewComments, withRemoteProvenance, yymmdd, } from './types';
|
|
2
|
-
export type { Finding, LocalReviewBackendOptions, ReviewBackend, ReviewComment, ReviewDocInput, ReviewDraft, ReviewEvent, ReviewReply, ReviewSide, ReviewThreadArtifactOptions, ReviewThreadRecord, Severity, } from './types';
|
|
1
|
+
export { dedupeFindings, findingSchema, findingsSchema, isLocalResponse, localResponseMarker, parseReviewThreadAction, localReviewAuthor, reviewRecordName, reviewSlug, severitySchema, toReviewComments, withRemoteProvenance, yymmdd, } from './types';
|
|
2
|
+
export type { Finding, LocalReviewBackendOptions, ReviewBackend, ReviewComment, ReviewDocInput, ReviewDraft, ReviewEvent, ReviewReply, ReviewSide, ReviewThreadAction, ReviewThreadArtifactOptions, ReviewThreadRecord, Severity, } from './types';
|
|
3
3
|
export { parseThreadArtifact, renderReviewDoc, renderThreadArtifact, upsertThreadReply } from './review-markdown';
|
|
4
4
|
export { assertReviewEventSupported, createLocalReviewBackend, createRemoteReviewBackend, githubReviewSubmissionEndpoint, hasGitlabDraftNotes, parseGitlabDiffRefs, } from './review-backend';
|
|
5
5
|
export type { GitlabDiffRefs } from './review-backend';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/review/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,cAAc,EACd,aAAa,EACb,cAAc,EACd,eAAe,EACf,mBAAmB,EACnB,iBAAiB,EACjB,gBAAgB,EAChB,UAAU,EACV,cAAc,EACd,gBAAgB,EAChB,oBAAoB,EACpB,MAAM,GACP,MAAM,SAAS,CAAC;AACjB,YAAY,EACV,OAAO,EACP,yBAAyB,EACzB,aAAa,EACb,aAAa,EACb,cAAc,EACd,WAAW,EACX,WAAW,EACX,WAAW,EACX,UAAU,EACV,2BAA2B,EAC3B,kBAAkB,EAClB,QAAQ,GACT,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,mBAAmB,EAAE,eAAe,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAClH,OAAO,EACL,0BAA0B,EAC1B,wBAAwB,EACxB,yBAAyB,EACzB,8BAA8B,EAC9B,mBAAmB,EACnB,mBAAmB,GACpB,MAAM,kBAAkB,CAAC;AAC1B,YAAY,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,EACL,0BAA0B,EAC1B,qBAAqB,EACrB,wBAAwB,EACxB,sBAAsB,EACtB,0BAA0B,EAC1B,yBAAyB,GAC1B,MAAM,gBAAgB,CAAC;AACxB,YAAY,EAAE,sBAAsB,EAAE,MAAM,gBAAgB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/review/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,cAAc,EACd,aAAa,EACb,cAAc,EACd,eAAe,EACf,mBAAmB,EACnB,uBAAuB,EACvB,iBAAiB,EACjB,gBAAgB,EAChB,UAAU,EACV,cAAc,EACd,gBAAgB,EAChB,oBAAoB,EACpB,MAAM,GACP,MAAM,SAAS,CAAC;AACjB,YAAY,EACV,OAAO,EACP,yBAAyB,EACzB,aAAa,EACb,aAAa,EACb,cAAc,EACd,WAAW,EACX,WAAW,EACX,WAAW,EACX,UAAU,EACV,kBAAkB,EAClB,2BAA2B,EAC3B,kBAAkB,EAClB,QAAQ,GACT,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,mBAAmB,EAAE,eAAe,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAClH,OAAO,EACL,0BAA0B,EAC1B,wBAAwB,EACxB,yBAAyB,EACzB,8BAA8B,EAC9B,mBAAmB,EACnB,mBAAmB,GACpB,MAAM,kBAAkB,CAAC;AAC1B,YAAY,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,EACL,0BAA0B,EAC1B,qBAAqB,EACrB,wBAAwB,EACxB,sBAAsB,EACtB,0BAA0B,EAC1B,yBAAyB,GAC1B,MAAM,gBAAgB,CAAC;AACxB,YAAY,EAAE,sBAAsB,EAAE,MAAM,gBAAgB,CAAC"}
|
package/dist/review/types.d.ts
CHANGED
|
@@ -37,6 +37,7 @@ export interface ReviewBackend {
|
|
|
37
37
|
readDraft(): Promise<ReviewDraft>;
|
|
38
38
|
listThreads(): Promise<ReviewThreadRecord[]>;
|
|
39
39
|
reply(input: ReviewReply): Promise<void>;
|
|
40
|
+
setResolved?(threadId: string, resolved: boolean): Promise<void>;
|
|
40
41
|
publish(event: ReviewEvent): Promise<void>;
|
|
41
42
|
}
|
|
42
43
|
export interface LocalReviewBackendOptions {
|
|
@@ -100,6 +101,11 @@ export declare function yymmdd(date?: Date): string;
|
|
|
100
101
|
export declare function reviewRecordName(target: string, date?: Date): string;
|
|
101
102
|
export declare function localResponseMarker(threadId: string): string;
|
|
102
103
|
export declare function isLocalResponse(body: string): boolean;
|
|
104
|
+
export type ReviewThreadAction = 'reopen' | 'resolve';
|
|
105
|
+
export declare function parseReviewThreadAction(body: string): {
|
|
106
|
+
action?: ReviewThreadAction;
|
|
107
|
+
body: string;
|
|
108
|
+
};
|
|
103
109
|
export declare function dedupeFindings(findings: Finding[]): Finding[];
|
|
104
110
|
export declare function toReviewComments(findings: Finding[], model?: string): ReviewComment[];
|
|
105
111
|
export declare function withRemoteProvenance(body: string, model: string): string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/review/types.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/review/types.ts"],"names":[],"mappings":"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"}
|
package/dist/tools/index.js
CHANGED
|
@@ -2852,6 +2852,15 @@ function localResponseMarker(threadId) {
|
|
|
2852
2852
|
function isLocalResponse(body) {
|
|
2853
2853
|
return /^<!-- diffpi(?:-local-response:[A-Za-z0-9_-]+)? -->\n/m.test(body);
|
|
2854
2854
|
}
|
|
2855
|
+
function parseReviewThreadAction(body) {
|
|
2856
|
+
const match = body.match(/^\[(REOPEN|RESOLVE)\]\s*/i);
|
|
2857
|
+
if (!match)
|
|
2858
|
+
return { body };
|
|
2859
|
+
return {
|
|
2860
|
+
action: match[1].toLowerCase(),
|
|
2861
|
+
body: body.slice(match[0].length)
|
|
2862
|
+
};
|
|
2863
|
+
}
|
|
2855
2864
|
function dedupeFindings(findings) {
|
|
2856
2865
|
const rank = { BLOCKING: 3, CONSIDER: 2, NOTE: 1 };
|
|
2857
2866
|
const byKey = new Map;
|
|
@@ -3190,16 +3199,18 @@ function GitHubReviewBackend(vcs, number) {
|
|
|
3190
3199
|
`body=${input.body}`
|
|
3191
3200
|
]);
|
|
3192
3201
|
}
|
|
3193
|
-
if (input.resolve)
|
|
3194
|
-
await
|
|
3195
|
-
|
|
3196
|
-
|
|
3197
|
-
|
|
3198
|
-
|
|
3199
|
-
|
|
3200
|
-
|
|
3201
|
-
|
|
3202
|
-
|
|
3202
|
+
if (input.resolve)
|
|
3203
|
+
await this.setResolved?.(input.threadId, true);
|
|
3204
|
+
},
|
|
3205
|
+
async setResolved(threadId, resolved) {
|
|
3206
|
+
await ghChecked([
|
|
3207
|
+
"api",
|
|
3208
|
+
"graphql",
|
|
3209
|
+
"-f",
|
|
3210
|
+
`query=${resolved ? GITHUB_RESOLVE_MUTATION : GITHUB_UNRESOLVE_MUTATION}`,
|
|
3211
|
+
"-f",
|
|
3212
|
+
`threadId=${threadId}`
|
|
3213
|
+
]);
|
|
3203
3214
|
},
|
|
3204
3215
|
async publish(event) {
|
|
3205
3216
|
const pending = await pendingReview();
|
|
@@ -3220,6 +3231,7 @@ var GITHUB_THREADS_QUERY = `query($owner:String!,$repo:String!,$number:Int!,$aft
|
|
|
3220
3231
|
var GITHUB_ADD_THREAD_MUTATION = `mutation($reviewId:ID!,$body:String!,$path:String!,$line:Int!,$side:DiffSide!){addPullRequestReviewThread(input:{pullRequestReviewId:$reviewId,body:$body,path:$path,line:$line,side:$side}){thread{id}}}`;
|
|
3221
3232
|
var GITHUB_REPLY_MUTATION = `mutation($threadId:ID!,$body:String!){addPullRequestReviewThreadReply(input:{pullRequestReviewThreadId:$threadId,body:$body}){comment{id}}}`;
|
|
3222
3233
|
var GITHUB_RESOLVE_MUTATION = `mutation($threadId:ID!){resolveReviewThread(input:{threadId:$threadId}){thread{isResolved}}}`;
|
|
3234
|
+
var GITHUB_UNRESOLVE_MUTATION = `mutation($threadId:ID!){unresolveReviewThread(input:{threadId:$threadId}){thread{isResolved}}}`;
|
|
3223
3235
|
|
|
3224
3236
|
// src/review/gitlab-review-backend.ts
|
|
3225
3237
|
function GitLabReviewBackend(vcs, number) {
|
|
@@ -3326,7 +3338,11 @@ function GitLabReviewBackend(vcs, number) {
|
|
|
3326
3338
|
});
|
|
3327
3339
|
}
|
|
3328
3340
|
if (input.resolve)
|
|
3329
|
-
await
|
|
3341
|
+
await this.setResolved?.(input.threadId, true);
|
|
3342
|
+
},
|
|
3343
|
+
async setResolved(threadId, resolved) {
|
|
3344
|
+
const endpoint = `${mergeRequestEndpoint()}/discussions/${encodeURIComponent(threadId)}`;
|
|
3345
|
+
await glabChecked(["api", "--method", "PUT", `${endpoint}?resolved=${resolved}`]);
|
|
3330
3346
|
},
|
|
3331
3347
|
async publish(event) {
|
|
3332
3348
|
assertReviewEventSupported(vcs.provider, event);
|
|
@@ -3740,7 +3756,16 @@ function createReviewTools() {
|
|
|
3740
3756
|
review.pr ? `PR/MR: #${review.pr.number} ${review.pr.url}` : "PR/MR: none",
|
|
3741
3757
|
session ? `tuicr: ${session.slug} (${session.commentCount} comments)` : "tuicr: none"
|
|
3742
3758
|
].join(`
|
|
3743
|
-
`), {
|
|
3759
|
+
`), {
|
|
3760
|
+
cwd: review.cwd,
|
|
3761
|
+
vcs: review.vcs,
|
|
3762
|
+
pr: review.pr,
|
|
3763
|
+
env,
|
|
3764
|
+
store,
|
|
3765
|
+
session,
|
|
3766
|
+
baseRef,
|
|
3767
|
+
backend
|
|
3768
|
+
});
|
|
3744
3769
|
}
|
|
3745
3770
|
}),
|
|
3746
3771
|
defineTool4({
|
|
@@ -4227,7 +4252,12 @@ async function promoteLocalReview(review, remote, model) {
|
|
|
4227
4252
|
author: localReviewAuthor(model)
|
|
4228
4253
|
});
|
|
4229
4254
|
const draft = await local.readDraft();
|
|
4230
|
-
const
|
|
4255
|
+
const remoteThreads = await remote.listThreads();
|
|
4256
|
+
const threadReplies = sessionIsWorkingTree ? [] : draft.comments.flatMap((comment) => {
|
|
4257
|
+
const thread = remoteThreads.find((candidate) => candidate.file === comment.file && candidate.line === comment.line && candidate.line !== undefined && !candidate.body.includes("Generated review by Diffpi using"));
|
|
4258
|
+
return thread ? [{ comment, thread }] : [];
|
|
4259
|
+
});
|
|
4260
|
+
const comments = draft.comments.filter(({ file, line }) => !threadReplies.some((reply) => reply.comment.file === file && reply.comment.line === line)).map((comment) => ({
|
|
4231
4261
|
...comment,
|
|
4232
4262
|
body: withRemoteProvenance(comment.body, comment.author?.replace(/^Agent:\s*/, "") || model)
|
|
4233
4263
|
}));
|
|
@@ -4243,7 +4273,7 @@ async function promoteLocalReview(review, remote, model) {
|
|
|
4243
4273
|
const unpublished = unpublishedReviewComments(comments, known);
|
|
4244
4274
|
if (unpublished.length > 0 || unpublishedBody)
|
|
4245
4275
|
await remote.stage({ comments: unpublished, body: unpublishedBody });
|
|
4246
|
-
const promotedReplies = await promoteLocalReplies(review, remote, publication, model, sessionIsWorkingTree);
|
|
4276
|
+
const promotedReplies = await promoteLocalReplies(review, remote, publication, model, sessionIsWorkingTree) + await promoteLocationReplies(remote, publication, threadReplies, model);
|
|
4247
4277
|
return {
|
|
4248
4278
|
publication,
|
|
4249
4279
|
bodyFingerprints,
|
|
@@ -4253,6 +4283,31 @@ async function promoteLocalReview(review, remote, model) {
|
|
|
4253
4283
|
promotedReplies
|
|
4254
4284
|
};
|
|
4255
4285
|
}
|
|
4286
|
+
async function promoteLocationReplies(remote, publication, replies, model) {
|
|
4287
|
+
let count = 0;
|
|
4288
|
+
for (const { comment, thread } of replies) {
|
|
4289
|
+
const parsed = parseReviewThreadAction(comment.body);
|
|
4290
|
+
const body = parsed.body.trim();
|
|
4291
|
+
const action = parsed.action;
|
|
4292
|
+
const fingerprint = reviewReplyFingerprint(thread.id, `${action ?? "reply"}\x00${body}`);
|
|
4293
|
+
if (publication.state.replies.includes(fingerprint))
|
|
4294
|
+
continue;
|
|
4295
|
+
const remoteBody = withRemoteProvenance(body, comment.author?.replace(/^Agent:\s*/, "") || model);
|
|
4296
|
+
if (body && !thread.replies?.some((reply) => reply === body || reply === remoteBody)) {
|
|
4297
|
+
await remote.reply({
|
|
4298
|
+
threadId: thread.id,
|
|
4299
|
+
body: remoteBody,
|
|
4300
|
+
resolve: false
|
|
4301
|
+
});
|
|
4302
|
+
}
|
|
4303
|
+
if (action && remote.setResolved)
|
|
4304
|
+
await remote.setResolved(thread.id, action === "resolve");
|
|
4305
|
+
publication.state.replies.push(fingerprint);
|
|
4306
|
+
await saveReviewPublicationState(publication.path, publication.state);
|
|
4307
|
+
count += 1;
|
|
4308
|
+
}
|
|
4309
|
+
return count;
|
|
4310
|
+
}
|
|
4256
4311
|
async function promoteLocalReplies(review, remote, publication, model, workingTree) {
|
|
4257
4312
|
const target = workingTree ? "uncommitted" : await reviewTargetId(review);
|
|
4258
4313
|
const artifact = workingTree ? await latestThreadArtifact(review.cwd, review, target) : publication.state.overlayPath ?? await latestThreadArtifact(review.cwd, review, target);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"review.d.ts","sourceRoot":"","sources":["../../src/tools/review.ts"],"names":[],"mappings":"AAGA,OAAO,EAAqC,KAAK,cAAc,EAAE,MAAM,iCAAiC,CAAC;AAMzG,OAAO,
|
|
1
|
+
{"version":3,"file":"review.d.ts","sourceRoot":"","sources":["../../src/tools/review.ts"],"names":[],"mappings":"AAGA,OAAO,EAAqC,KAAK,cAAc,EAAE,MAAM,iCAAiC,CAAC;AAMzG,OAAO,EAwBL,KAAK,aAAa,EAClB,KAAK,kBAAkB,EACxB,MAAM,WAAW,CAAC;AAwEnB,wBAAgB,cAAc,CAAC,QAAQ,EAAE,SAAS,aAAa,EAAE,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAExF;AAED,wBAAsB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAalE;AAID,wBAAgB,iBAAiB,IAAI,SAAS,cAAc,EAAE,CAkc7D;AAID,wBAAsB,uBAAuB,CAC3C,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,EACb,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,SAAS,kBAAkB,EAAE,GACrC,OAAO,CAAC,kBAAkB,EAAE,CAAC,CAwB/B"}
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
1. Parse an optional PR/MR id or URL, `--local`, and one status: `--comment`, `--approve`, `--request-changes`, or `--close`. The default is comment.
|
|
4
4
|
2. Call `review_context` with the target and backend selection.
|
|
5
|
-
3. For `--local`, call `review_publish` with `local: true`. The tool reads the exact tuicr session,
|
|
5
|
+
3. For `--local`, call `review_publish` with `local: true`. The tool reads the exact tuicr session. A local line comment on the same file and line as an existing remote thread is treated as a response, not a new comment. A leading `[REOPEN]` or `[RESOLVE]` changes the thread state; the marker is removed from the response body. Other unpublished line comments become new review comments. The tool follows the stored local overlay path, posts unpublished replies to their remote threads, and then publishes the selected status. Question replies remain open. The tool does not post an overall review comment.
|
|
6
6
|
4. For a remote review, call `review_publish` without `local`. The existing pending forge comments already contain provenance, so the tool only publishes them with the selected status and no overall comment.
|
|
7
7
|
5. Comment, approve, and request-changes mark a draft PR/MR ready before publication. Close publishes pending work as comment status and then closes the PR/MR. GitLab rejects request-changes because it has no equivalent review state.
|
|
8
|
-
6. Report promoted comment and reply counts, the public status, and the final PR/MR state. Publishing never merges.
|
|
8
|
+
6. Report promoted comment and reply counts, the public status, and the final PR/MR state. Publishing never merges. If a response cannot be matched by file and line, report it as a new comment rather than silently attaching it to the wrong thread.
|