@staff0rd/assist 0.77.0 → 0.79.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/README.md +3 -1
- package/claude/commands/comment.md +39 -0
- package/dist/commands/backlog/web/bundle.js +23 -23
- package/dist/index.js +221 -105
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -6,7 +6,7 @@ import { Command } from "commander";
|
|
|
6
6
|
// package.json
|
|
7
7
|
var package_default = {
|
|
8
8
|
name: "@staff0rd/assist",
|
|
9
|
-
version: "0.
|
|
9
|
+
version: "0.79.0",
|
|
10
10
|
type: "module",
|
|
11
11
|
main: "dist/index.js",
|
|
12
12
|
bin: {
|
|
@@ -1923,8 +1923,10 @@ import { parse as parseYaml2, stringify as stringifyYaml3 } from "yaml";
|
|
|
1923
1923
|
// src/commands/backlog/types.ts
|
|
1924
1924
|
import { z as z2 } from "zod";
|
|
1925
1925
|
var backlogStatusSchema = z2.enum(["todo", "in-progress", "done"]);
|
|
1926
|
+
var backlogTypeSchema = z2.enum(["story", "bug"]);
|
|
1926
1927
|
var backlogItemSchema = z2.strictObject({
|
|
1927
1928
|
id: z2.number(),
|
|
1929
|
+
type: backlogTypeSchema.default("story"),
|
|
1928
1930
|
name: z2.string(),
|
|
1929
1931
|
description: z2.string().optional(),
|
|
1930
1932
|
acceptanceCriteria: z2.array(z2.string()),
|
|
@@ -1997,6 +1999,16 @@ import { mkdtempSync, readFileSync as readFileSync10, unlinkSync as unlinkSync2,
|
|
|
1997
1999
|
import { tmpdir } from "os";
|
|
1998
2000
|
import { join as join9 } from "path";
|
|
1999
2001
|
import enquirer4 from "enquirer";
|
|
2002
|
+
async function promptType() {
|
|
2003
|
+
const { type } = await enquirer4.prompt({
|
|
2004
|
+
type: "select",
|
|
2005
|
+
name: "type",
|
|
2006
|
+
message: "Type:",
|
|
2007
|
+
choices: ["story", "bug"],
|
|
2008
|
+
initial: 0
|
|
2009
|
+
});
|
|
2010
|
+
return type;
|
|
2011
|
+
}
|
|
2000
2012
|
async function promptName() {
|
|
2001
2013
|
const { name } = await enquirer4.prompt({
|
|
2002
2014
|
type: "input",
|
|
@@ -2062,12 +2074,20 @@ async function add() {
|
|
|
2062
2074
|
);
|
|
2063
2075
|
return;
|
|
2064
2076
|
}
|
|
2077
|
+
const type = await promptType();
|
|
2065
2078
|
const name = await promptName();
|
|
2066
2079
|
const description = await promptDescription();
|
|
2067
2080
|
const acceptanceCriteria = await promptAcceptanceCriteria();
|
|
2068
2081
|
const items = loadBacklog();
|
|
2069
2082
|
const id = getNextId(items);
|
|
2070
|
-
items.push({
|
|
2083
|
+
items.push({
|
|
2084
|
+
id,
|
|
2085
|
+
type,
|
|
2086
|
+
name,
|
|
2087
|
+
description,
|
|
2088
|
+
acceptanceCriteria,
|
|
2089
|
+
status: "todo"
|
|
2090
|
+
});
|
|
2071
2091
|
saveBacklog(items);
|
|
2072
2092
|
console.log(chalk23.green(`Added item #${id}: ${name}`));
|
|
2073
2093
|
}
|
|
@@ -2116,6 +2136,26 @@ function statusIcon(status) {
|
|
|
2116
2136
|
return chalk27.green("[x]");
|
|
2117
2137
|
}
|
|
2118
2138
|
}
|
|
2139
|
+
function typeLabel(type) {
|
|
2140
|
+
switch (type) {
|
|
2141
|
+
case "bug":
|
|
2142
|
+
return chalk27.magenta("Bug");
|
|
2143
|
+
case "story":
|
|
2144
|
+
return chalk27.cyan("Story");
|
|
2145
|
+
}
|
|
2146
|
+
}
|
|
2147
|
+
function printVerboseDetails(item) {
|
|
2148
|
+
if (item.description) {
|
|
2149
|
+
console.log(` ${chalk27.dim("Description:")} ${item.description}`);
|
|
2150
|
+
}
|
|
2151
|
+
if (item.acceptanceCriteria.length > 0) {
|
|
2152
|
+
console.log(` ${chalk27.dim("Acceptance criteria:")}`);
|
|
2153
|
+
for (const criterion of item.acceptanceCriteria) {
|
|
2154
|
+
console.log(` - ${criterion}`);
|
|
2155
|
+
}
|
|
2156
|
+
}
|
|
2157
|
+
console.log();
|
|
2158
|
+
}
|
|
2119
2159
|
async function list2(options2) {
|
|
2120
2160
|
const backlogPath = getBacklogPath();
|
|
2121
2161
|
if (!existsSync14(backlogPath)) {
|
|
@@ -2136,19 +2176,10 @@ async function list2(options2) {
|
|
|
2136
2176
|
}
|
|
2137
2177
|
for (const item of items) {
|
|
2138
2178
|
console.log(
|
|
2139
|
-
`${statusIcon(item.status)} ${chalk27.dim(`#${item.id}`)} ${item.name}`
|
|
2179
|
+
`${statusIcon(item.status)} ${typeLabel(item.type)} ${chalk27.dim(`#${item.id}`)} ${item.name}`
|
|
2140
2180
|
);
|
|
2141
2181
|
if (options2.verbose) {
|
|
2142
|
-
|
|
2143
|
-
console.log(` ${chalk27.dim("Description:")} ${item.description}`);
|
|
2144
|
-
}
|
|
2145
|
-
if (item.acceptanceCriteria.length > 0) {
|
|
2146
|
-
console.log(` ${chalk27.dim("Acceptance criteria:")}`);
|
|
2147
|
-
for (const criterion of item.acceptanceCriteria) {
|
|
2148
|
-
console.log(` - ${criterion}`);
|
|
2149
|
-
}
|
|
2150
|
-
}
|
|
2151
|
-
console.log();
|
|
2182
|
+
printVerboseDetails(item);
|
|
2152
2183
|
}
|
|
2153
2184
|
}
|
|
2154
2185
|
}
|
|
@@ -2195,7 +2226,7 @@ function getHtml() {
|
|
|
2195
2226
|
</html>`;
|
|
2196
2227
|
}
|
|
2197
2228
|
|
|
2198
|
-
// src/commands/backlog/web/
|
|
2229
|
+
// src/commands/backlog/web/respondJson.ts
|
|
2199
2230
|
function respondJson(res, status, data) {
|
|
2200
2231
|
res.writeHead(status, { "Content-Type": "application/json" });
|
|
2201
2232
|
res.end(JSON.stringify(data));
|
|
@@ -2210,6 +2241,11 @@ function readBody(req) {
|
|
|
2210
2241
|
req.on("error", reject);
|
|
2211
2242
|
});
|
|
2212
2243
|
}
|
|
2244
|
+
async function parseItemBody(req) {
|
|
2245
|
+
return JSON.parse(await readBody(req));
|
|
2246
|
+
}
|
|
2247
|
+
|
|
2248
|
+
// src/commands/backlog/web/shared.ts
|
|
2213
2249
|
function listItems(_req, res) {
|
|
2214
2250
|
respondJson(res, 200, loadBacklog());
|
|
2215
2251
|
}
|
|
@@ -2226,14 +2262,12 @@ function getItemById(res, id) {
|
|
|
2226
2262
|
const result = findItemOr404(res, id);
|
|
2227
2263
|
if (result) respondJson(res, 200, result.item);
|
|
2228
2264
|
}
|
|
2229
|
-
async function parseItemBody(req) {
|
|
2230
|
-
return JSON.parse(await readBody(req));
|
|
2231
|
-
}
|
|
2232
2265
|
async function createItem(req, res) {
|
|
2233
2266
|
const body = await parseItemBody(req);
|
|
2234
2267
|
const items = loadBacklog();
|
|
2235
2268
|
const newItem = {
|
|
2236
2269
|
id: getNextId(items),
|
|
2270
|
+
type: body.type ?? "story",
|
|
2237
2271
|
name: body.name,
|
|
2238
2272
|
description: body.description,
|
|
2239
2273
|
acceptanceCriteria: body.acceptanceCriteria ?? [],
|
|
@@ -2254,6 +2288,7 @@ async function updateItem(req, res, id) {
|
|
|
2254
2288
|
const result = findItemOr404(res, id);
|
|
2255
2289
|
if (!result) return;
|
|
2256
2290
|
Object.assign(result.item, {
|
|
2291
|
+
type: body.type ?? result.item.type,
|
|
2257
2292
|
name: body.name,
|
|
2258
2293
|
description: body.description,
|
|
2259
2294
|
acceptanceCriteria: body.acceptanceCriteria ?? []
|
|
@@ -3234,37 +3269,11 @@ function registerDevlog(program2) {
|
|
|
3234
3269
|
devlogCommand.command("skip <date>").description("Add a date (YYYY-MM-DD) to the skip list").action(skip);
|
|
3235
3270
|
}
|
|
3236
3271
|
|
|
3237
|
-
// src/commands/prs/
|
|
3238
|
-
import {
|
|
3239
|
-
|
|
3240
|
-
// src/commands/prs/resolveCommentWithReply.ts
|
|
3241
|
-
import { execSync as execSync16 } from "child_process";
|
|
3242
|
-
import { unlinkSync as unlinkSync4, writeFileSync as writeFileSync13 } from "fs";
|
|
3272
|
+
// src/commands/prs/comment.ts
|
|
3273
|
+
import { spawnSync as spawnSync2 } from "child_process";
|
|
3274
|
+
import { unlinkSync as unlinkSync3, writeFileSync as writeFileSync13 } from "fs";
|
|
3243
3275
|
import { tmpdir as tmpdir2 } from "os";
|
|
3244
|
-
import { join as join13 } from "path";
|
|
3245
|
-
|
|
3246
|
-
// src/commands/prs/loadCommentsCache.ts
|
|
3247
|
-
import { existsSync as existsSync16, readFileSync as readFileSync14, unlinkSync as unlinkSync3 } from "fs";
|
|
3248
3276
|
import { join as join12 } from "path";
|
|
3249
|
-
import { parse } from "yaml";
|
|
3250
|
-
function getCachePath(prNumber) {
|
|
3251
|
-
return join12(process.cwd(), ".assist", `pr-${prNumber}-comments.yaml`);
|
|
3252
|
-
}
|
|
3253
|
-
function loadCommentsCache(prNumber) {
|
|
3254
|
-
const cachePath = getCachePath(prNumber);
|
|
3255
|
-
if (!existsSync16(cachePath)) {
|
|
3256
|
-
return null;
|
|
3257
|
-
}
|
|
3258
|
-
const content = readFileSync14(cachePath, "utf-8");
|
|
3259
|
-
return parse(content);
|
|
3260
|
-
}
|
|
3261
|
-
function deleteCommentsCache(prNumber) {
|
|
3262
|
-
const cachePath = getCachePath(prNumber);
|
|
3263
|
-
if (existsSync16(cachePath)) {
|
|
3264
|
-
unlinkSync3(cachePath);
|
|
3265
|
-
console.log("No more unresolved line comments. Cache dropped.");
|
|
3266
|
-
}
|
|
3267
|
-
}
|
|
3268
3277
|
|
|
3269
3278
|
// src/commands/prs/shared.ts
|
|
3270
3279
|
import { execSync as execSync15 } from "child_process";
|
|
@@ -3301,6 +3310,110 @@ function getCurrentPrNumber() {
|
|
|
3301
3310
|
throw error;
|
|
3302
3311
|
}
|
|
3303
3312
|
}
|
|
3313
|
+
function getCurrentPrNodeId() {
|
|
3314
|
+
try {
|
|
3315
|
+
const prInfo = JSON.parse(
|
|
3316
|
+
execSync15("gh pr view --json id", { encoding: "utf-8" })
|
|
3317
|
+
);
|
|
3318
|
+
return prInfo.id;
|
|
3319
|
+
} catch (error) {
|
|
3320
|
+
if (error instanceof Error && error.message.includes("no pull requests")) {
|
|
3321
|
+
console.error("Error: No pull request found for the current branch.");
|
|
3322
|
+
process.exit(1);
|
|
3323
|
+
}
|
|
3324
|
+
throw error;
|
|
3325
|
+
}
|
|
3326
|
+
}
|
|
3327
|
+
|
|
3328
|
+
// src/commands/prs/comment.ts
|
|
3329
|
+
var MUTATION = `mutation($prId: ID!, $body: String!, $path: String!, $line: Int!) { addPullRequestReviewThread(input: { pullRequestId: $prId, body: $body, path: $path, line: $line, side: RIGHT }) { thread { id } } }`;
|
|
3330
|
+
function validateBody(body) {
|
|
3331
|
+
const lower = body.toLowerCase();
|
|
3332
|
+
if (lower.includes("claude") || lower.includes("opus")) {
|
|
3333
|
+
console.error('Error: Body must not contain "claude" or "opus"');
|
|
3334
|
+
process.exit(1);
|
|
3335
|
+
}
|
|
3336
|
+
}
|
|
3337
|
+
function validateLine(line) {
|
|
3338
|
+
if (!Number.isInteger(line) || line < 1) {
|
|
3339
|
+
console.error("Error: Line must be a positive integer");
|
|
3340
|
+
process.exit(1);
|
|
3341
|
+
}
|
|
3342
|
+
}
|
|
3343
|
+
function comment(path31, line, body) {
|
|
3344
|
+
validateBody(body);
|
|
3345
|
+
validateLine(line);
|
|
3346
|
+
try {
|
|
3347
|
+
const prId = getCurrentPrNodeId();
|
|
3348
|
+
const queryFile = join12(tmpdir2(), `gh-query-${Date.now()}.graphql`);
|
|
3349
|
+
writeFileSync13(queryFile, MUTATION);
|
|
3350
|
+
try {
|
|
3351
|
+
const result = spawnSync2(
|
|
3352
|
+
"gh",
|
|
3353
|
+
[
|
|
3354
|
+
"api",
|
|
3355
|
+
"graphql",
|
|
3356
|
+
"-F",
|
|
3357
|
+
`query=@${queryFile}`,
|
|
3358
|
+
"-f",
|
|
3359
|
+
`prId=${prId}`,
|
|
3360
|
+
"-f",
|
|
3361
|
+
`body=${body}`,
|
|
3362
|
+
"-f",
|
|
3363
|
+
`path=${path31}`,
|
|
3364
|
+
"-F",
|
|
3365
|
+
`line=${line}`
|
|
3366
|
+
],
|
|
3367
|
+
{ encoding: "utf-8" }
|
|
3368
|
+
);
|
|
3369
|
+
if (result.status !== 0) {
|
|
3370
|
+
throw new Error(result.stderr || result.stdout);
|
|
3371
|
+
}
|
|
3372
|
+
console.log(`Added review comment on ${path31}:${line}`);
|
|
3373
|
+
} finally {
|
|
3374
|
+
unlinkSync3(queryFile);
|
|
3375
|
+
}
|
|
3376
|
+
} catch (error) {
|
|
3377
|
+
if (isGhNotInstalled(error)) {
|
|
3378
|
+
console.error("Error: GitHub CLI (gh) is not installed.");
|
|
3379
|
+
console.error("Install it from https://cli.github.com/");
|
|
3380
|
+
process.exit(1);
|
|
3381
|
+
}
|
|
3382
|
+
throw error;
|
|
3383
|
+
}
|
|
3384
|
+
}
|
|
3385
|
+
|
|
3386
|
+
// src/commands/prs/fixed.ts
|
|
3387
|
+
import { execSync as execSync17 } from "child_process";
|
|
3388
|
+
|
|
3389
|
+
// src/commands/prs/resolveCommentWithReply.ts
|
|
3390
|
+
import { execSync as execSync16 } from "child_process";
|
|
3391
|
+
import { unlinkSync as unlinkSync5, writeFileSync as writeFileSync14 } from "fs";
|
|
3392
|
+
import { tmpdir as tmpdir3 } from "os";
|
|
3393
|
+
import { join as join14 } from "path";
|
|
3394
|
+
|
|
3395
|
+
// src/commands/prs/loadCommentsCache.ts
|
|
3396
|
+
import { existsSync as existsSync16, readFileSync as readFileSync14, unlinkSync as unlinkSync4 } from "fs";
|
|
3397
|
+
import { join as join13 } from "path";
|
|
3398
|
+
import { parse } from "yaml";
|
|
3399
|
+
function getCachePath(prNumber) {
|
|
3400
|
+
return join13(process.cwd(), ".assist", `pr-${prNumber}-comments.yaml`);
|
|
3401
|
+
}
|
|
3402
|
+
function loadCommentsCache(prNumber) {
|
|
3403
|
+
const cachePath = getCachePath(prNumber);
|
|
3404
|
+
if (!existsSync16(cachePath)) {
|
|
3405
|
+
return null;
|
|
3406
|
+
}
|
|
3407
|
+
const content = readFileSync14(cachePath, "utf-8");
|
|
3408
|
+
return parse(content);
|
|
3409
|
+
}
|
|
3410
|
+
function deleteCommentsCache(prNumber) {
|
|
3411
|
+
const cachePath = getCachePath(prNumber);
|
|
3412
|
+
if (existsSync16(cachePath)) {
|
|
3413
|
+
unlinkSync4(cachePath);
|
|
3414
|
+
console.log("No more unresolved line comments. Cache dropped.");
|
|
3415
|
+
}
|
|
3416
|
+
}
|
|
3304
3417
|
|
|
3305
3418
|
// src/commands/prs/resolveCommentWithReply.ts
|
|
3306
3419
|
function replyToComment(org, repo, prNumber, commentId, message) {
|
|
@@ -3311,15 +3424,15 @@ function replyToComment(org, repo, prNumber, commentId, message) {
|
|
|
3311
3424
|
}
|
|
3312
3425
|
function resolveThread(threadId) {
|
|
3313
3426
|
const mutation = `mutation($threadId: ID!) { resolveReviewThread(input: {threadId: $threadId}) { thread { isResolved } } }`;
|
|
3314
|
-
const queryFile =
|
|
3315
|
-
|
|
3427
|
+
const queryFile = join14(tmpdir3(), `gh-mutation-${Date.now()}.graphql`);
|
|
3428
|
+
writeFileSync14(queryFile, mutation);
|
|
3316
3429
|
try {
|
|
3317
3430
|
execSync16(
|
|
3318
3431
|
`gh api graphql -F query=@${queryFile} -f threadId="${threadId}"`,
|
|
3319
3432
|
{ stdio: "inherit" }
|
|
3320
3433
|
);
|
|
3321
3434
|
} finally {
|
|
3322
|
-
|
|
3435
|
+
unlinkSync5(queryFile);
|
|
3323
3436
|
}
|
|
3324
3437
|
}
|
|
3325
3438
|
function requireCache(prNumber) {
|
|
@@ -3336,14 +3449,14 @@ function findLineComment(comments, commentId) {
|
|
|
3336
3449
|
return comments.find((c) => c.type === "line" && c.id === commentId);
|
|
3337
3450
|
}
|
|
3338
3451
|
function requireLineComment(cache, commentId) {
|
|
3339
|
-
const
|
|
3340
|
-
if (!
|
|
3452
|
+
const comment2 = findLineComment(cache.comments, commentId);
|
|
3453
|
+
if (!comment2 || comment2.type !== "line" || !comment2.threadId) {
|
|
3341
3454
|
console.error(
|
|
3342
3455
|
`Error: Comment #${commentId} not found or has no thread ID.`
|
|
3343
3456
|
);
|
|
3344
3457
|
process.exit(1);
|
|
3345
3458
|
}
|
|
3346
|
-
return
|
|
3459
|
+
return comment2;
|
|
3347
3460
|
}
|
|
3348
3461
|
function cleanupCacheIfDone(cache, prNumber, commentId) {
|
|
3349
3462
|
const hasRemaining = cache.comments.some(
|
|
@@ -3355,10 +3468,10 @@ function resolveCommentWithReply(commentId, message) {
|
|
|
3355
3468
|
const prNumber = getCurrentPrNumber();
|
|
3356
3469
|
const { org, repo } = getRepoInfo();
|
|
3357
3470
|
const cache = requireCache(prNumber);
|
|
3358
|
-
const
|
|
3471
|
+
const comment2 = requireLineComment(cache, commentId);
|
|
3359
3472
|
replyToComment(org, repo, prNumber, commentId, message);
|
|
3360
3473
|
console.log("Reply posted successfully.");
|
|
3361
|
-
resolveThread(
|
|
3474
|
+
resolveThread(comment2.threadId);
|
|
3362
3475
|
console.log("Thread resolved successfully.");
|
|
3363
3476
|
cleanupCacheIfDone(cache, prNumber, commentId);
|
|
3364
3477
|
}
|
|
@@ -3392,8 +3505,8 @@ function fixed(commentId, sha) {
|
|
|
3392
3505
|
}
|
|
3393
3506
|
|
|
3394
3507
|
// src/commands/prs/listComments/index.ts
|
|
3395
|
-
import { existsSync as existsSync17, mkdirSync as mkdirSync4, writeFileSync as
|
|
3396
|
-
import { join as
|
|
3508
|
+
import { existsSync as existsSync17, mkdirSync as mkdirSync4, writeFileSync as writeFileSync16 } from "fs";
|
|
3509
|
+
import { join as join16 } from "path";
|
|
3397
3510
|
import { stringify } from "yaml";
|
|
3398
3511
|
|
|
3399
3512
|
// src/lib/isClaudeCode.ts
|
|
@@ -3403,13 +3516,13 @@ function isClaudeCode2() {
|
|
|
3403
3516
|
|
|
3404
3517
|
// src/commands/prs/fetchThreadIds.ts
|
|
3405
3518
|
import { execSync as execSync18 } from "child_process";
|
|
3406
|
-
import { unlinkSync as
|
|
3407
|
-
import { tmpdir as
|
|
3408
|
-
import { join as
|
|
3519
|
+
import { unlinkSync as unlinkSync6, writeFileSync as writeFileSync15 } from "fs";
|
|
3520
|
+
import { tmpdir as tmpdir4 } from "os";
|
|
3521
|
+
import { join as join15 } from "path";
|
|
3409
3522
|
var THREAD_QUERY = `query($owner: String!, $repo: String!, $prNumber: Int!) { repository(owner: $owner, name: $repo) { pullRequest(number: $prNumber) { reviewThreads(first: 100) { nodes { id isResolved comments(first: 100) { nodes { databaseId } } } } } } }`;
|
|
3410
3523
|
function fetchThreadIds(org, repo, prNumber) {
|
|
3411
|
-
const queryFile =
|
|
3412
|
-
|
|
3524
|
+
const queryFile = join15(tmpdir4(), `gh-query-${Date.now()}.graphql`);
|
|
3525
|
+
writeFileSync15(queryFile, THREAD_QUERY);
|
|
3413
3526
|
try {
|
|
3414
3527
|
const result = execSync18(
|
|
3415
3528
|
`gh api graphql -F query=@${queryFile} -F owner="${org}" -F repo="${repo}" -F prNumber=${prNumber}`,
|
|
@@ -3422,13 +3535,13 @@ function fetchThreadIds(org, repo, prNumber) {
|
|
|
3422
3535
|
if (thread.isResolved) {
|
|
3423
3536
|
resolvedThreadIds.add(thread.id);
|
|
3424
3537
|
}
|
|
3425
|
-
for (const
|
|
3426
|
-
threadMap.set(
|
|
3538
|
+
for (const comment2 of thread.comments.nodes) {
|
|
3539
|
+
threadMap.set(comment2.databaseId, thread.id);
|
|
3427
3540
|
}
|
|
3428
3541
|
}
|
|
3429
3542
|
return { threadMap, resolvedThreadIds };
|
|
3430
3543
|
} finally {
|
|
3431
|
-
|
|
3544
|
+
unlinkSync6(queryFile);
|
|
3432
3545
|
}
|
|
3433
3546
|
}
|
|
3434
3547
|
|
|
@@ -3476,42 +3589,42 @@ function fetchLineComments(org, repo, prNumber, threadInfo) {
|
|
|
3476
3589
|
|
|
3477
3590
|
// src/commands/prs/listComments/formatForHuman.ts
|
|
3478
3591
|
import chalk43 from "chalk";
|
|
3479
|
-
function formatForHuman(
|
|
3480
|
-
if (
|
|
3481
|
-
const stateColor =
|
|
3592
|
+
function formatForHuman(comment2) {
|
|
3593
|
+
if (comment2.type === "review") {
|
|
3594
|
+
const stateColor = comment2.state === "APPROVED" ? chalk43.green : comment2.state === "CHANGES_REQUESTED" ? chalk43.red : chalk43.yellow;
|
|
3482
3595
|
return [
|
|
3483
|
-
`${chalk43.cyan("Review")} by ${chalk43.bold(
|
|
3484
|
-
|
|
3596
|
+
`${chalk43.cyan("Review")} by ${chalk43.bold(comment2.user)} ${stateColor(`[${comment2.state}]`)}`,
|
|
3597
|
+
comment2.body,
|
|
3485
3598
|
""
|
|
3486
3599
|
].join("\n");
|
|
3487
3600
|
}
|
|
3488
|
-
const location =
|
|
3601
|
+
const location = comment2.line ? `:${comment2.line}` : "";
|
|
3489
3602
|
return [
|
|
3490
|
-
`${chalk43.cyan("Line comment")} by ${chalk43.bold(
|
|
3491
|
-
chalk43.dim(
|
|
3492
|
-
|
|
3603
|
+
`${chalk43.cyan("Line comment")} by ${chalk43.bold(comment2.user)} on ${chalk43.dim(`${comment2.path}${location}`)}`,
|
|
3604
|
+
chalk43.dim(comment2.diff_hunk.split("\n").slice(-3).join("\n")),
|
|
3605
|
+
comment2.body,
|
|
3493
3606
|
""
|
|
3494
3607
|
].join("\n");
|
|
3495
3608
|
}
|
|
3496
3609
|
|
|
3497
3610
|
// src/commands/prs/listComments/index.ts
|
|
3498
|
-
function formatComment(
|
|
3499
|
-
return isClaudeCode2() ? JSON.stringify(
|
|
3611
|
+
function formatComment(comment2) {
|
|
3612
|
+
return isClaudeCode2() ? JSON.stringify(comment2) : formatForHuman(comment2);
|
|
3500
3613
|
}
|
|
3501
3614
|
function printComments(comments) {
|
|
3502
3615
|
if (comments.length === 0) {
|
|
3503
3616
|
console.log("No comments found.");
|
|
3504
3617
|
return;
|
|
3505
3618
|
}
|
|
3506
|
-
for (const
|
|
3507
|
-
console.log(formatComment(
|
|
3619
|
+
for (const comment2 of comments) {
|
|
3620
|
+
console.log(formatComment(comment2));
|
|
3508
3621
|
}
|
|
3509
3622
|
if (!comments.some((c) => c.type === "line")) {
|
|
3510
3623
|
console.log("No line comments to process.");
|
|
3511
3624
|
}
|
|
3512
3625
|
}
|
|
3513
3626
|
function writeCommentsCache(prNumber, comments) {
|
|
3514
|
-
const assistDir =
|
|
3627
|
+
const assistDir = join16(process.cwd(), ".assist");
|
|
3515
3628
|
if (!existsSync17(assistDir)) {
|
|
3516
3629
|
mkdirSync4(assistDir, { recursive: true });
|
|
3517
3630
|
}
|
|
@@ -3520,8 +3633,8 @@ function writeCommentsCache(prNumber, comments) {
|
|
|
3520
3633
|
fetchedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
3521
3634
|
comments
|
|
3522
3635
|
};
|
|
3523
|
-
const cachePath =
|
|
3524
|
-
|
|
3636
|
+
const cachePath = join16(assistDir, `pr-${prNumber}-comments.yaml`);
|
|
3637
|
+
writeFileSync16(cachePath, stringify(cacheData));
|
|
3525
3638
|
}
|
|
3526
3639
|
function handleKnownErrors(error) {
|
|
3527
3640
|
if (isGhNotInstalled(error)) {
|
|
@@ -3746,6 +3859,9 @@ function registerPrs(program2) {
|
|
|
3746
3859
|
prsCommand.command("wontfix <comment-id> <reason>").description("Reply with reason and resolve thread").action((commentId, reason) => {
|
|
3747
3860
|
wontfix(Number.parseInt(commentId, 10), reason);
|
|
3748
3861
|
});
|
|
3862
|
+
prsCommand.command("comment <path> <line> <body>").description("Add a line comment to the pending review").action((path31, line, body) => {
|
|
3863
|
+
comment(path31, Number.parseInt(line, 10), body);
|
|
3864
|
+
});
|
|
3749
3865
|
}
|
|
3750
3866
|
|
|
3751
3867
|
// src/commands/refactor/check/index.ts
|
|
@@ -4483,7 +4599,7 @@ function registerRefactor(program2) {
|
|
|
4483
4599
|
|
|
4484
4600
|
// src/commands/transcript/shared.ts
|
|
4485
4601
|
import { existsSync as existsSync18, readdirSync as readdirSync2, statSync } from "fs";
|
|
4486
|
-
import { basename as basename4, join as
|
|
4602
|
+
import { basename as basename4, join as join17, relative } from "path";
|
|
4487
4603
|
import * as readline2 from "readline";
|
|
4488
4604
|
var DATE_PREFIX_REGEX = /^\d{4}-\d{2}-\d{2}/;
|
|
4489
4605
|
function getDatePrefix(daysOffset = 0) {
|
|
@@ -4501,7 +4617,7 @@ function collectFiles(dir, extension) {
|
|
|
4501
4617
|
if (!existsSync18(dir)) return [];
|
|
4502
4618
|
const results = [];
|
|
4503
4619
|
for (const entry of readdirSync2(dir)) {
|
|
4504
|
-
const fullPath =
|
|
4620
|
+
const fullPath = join17(dir, entry);
|
|
4505
4621
|
if (statSync(fullPath).isDirectory()) {
|
|
4506
4622
|
results.push(...collectFiles(fullPath, extension));
|
|
4507
4623
|
} else if (entry.endsWith(extension)) {
|
|
@@ -4598,11 +4714,11 @@ async function configure() {
|
|
|
4598
4714
|
import { existsSync as existsSync20 } from "fs";
|
|
4599
4715
|
|
|
4600
4716
|
// src/commands/transcript/format/fixInvalidDatePrefixes/index.ts
|
|
4601
|
-
import { dirname as dirname13, join as
|
|
4717
|
+
import { dirname as dirname13, join as join19 } from "path";
|
|
4602
4718
|
|
|
4603
4719
|
// src/commands/transcript/format/fixInvalidDatePrefixes/promptForDateFix.ts
|
|
4604
4720
|
import { renameSync } from "fs";
|
|
4605
|
-
import { join as
|
|
4721
|
+
import { join as join18 } from "path";
|
|
4606
4722
|
async function resolveDate(rl, choice) {
|
|
4607
4723
|
if (choice === "1") return getDatePrefix(0);
|
|
4608
4724
|
if (choice === "2") return getDatePrefix(-1);
|
|
@@ -4617,7 +4733,7 @@ async function resolveDate(rl, choice) {
|
|
|
4617
4733
|
}
|
|
4618
4734
|
function renameWithPrefix(vttDir, vttFile, prefix) {
|
|
4619
4735
|
const newFilename = `${prefix}.${vttFile}`;
|
|
4620
|
-
renameSync(
|
|
4736
|
+
renameSync(join18(vttDir, vttFile), join18(vttDir, newFilename));
|
|
4621
4737
|
console.log(`Renamed to: ${newFilename}`);
|
|
4622
4738
|
return newFilename;
|
|
4623
4739
|
}
|
|
@@ -4651,12 +4767,12 @@ async function fixInvalidDatePrefixes(vttFiles) {
|
|
|
4651
4767
|
const vttFileDir = dirname13(vttFile.absolutePath);
|
|
4652
4768
|
const newFilename = await promptForDateFix(vttFile.filename, vttFileDir);
|
|
4653
4769
|
if (newFilename) {
|
|
4654
|
-
const newRelativePath =
|
|
4770
|
+
const newRelativePath = join19(
|
|
4655
4771
|
dirname13(vttFile.relativePath),
|
|
4656
4772
|
newFilename
|
|
4657
4773
|
);
|
|
4658
4774
|
vttFiles[i] = {
|
|
4659
|
-
absolutePath:
|
|
4775
|
+
absolutePath: join19(vttFileDir, newFilename),
|
|
4660
4776
|
relativePath: newRelativePath,
|
|
4661
4777
|
filename: newFilename
|
|
4662
4778
|
};
|
|
@@ -4669,8 +4785,8 @@ async function fixInvalidDatePrefixes(vttFiles) {
|
|
|
4669
4785
|
}
|
|
4670
4786
|
|
|
4671
4787
|
// src/commands/transcript/format/processVttFile/index.ts
|
|
4672
|
-
import { existsSync as existsSync19, mkdirSync as mkdirSync5, readFileSync as readFileSync15, writeFileSync as
|
|
4673
|
-
import { basename as basename5, dirname as dirname14, join as
|
|
4788
|
+
import { existsSync as existsSync19, mkdirSync as mkdirSync5, readFileSync as readFileSync15, writeFileSync as writeFileSync17 } from "fs";
|
|
4789
|
+
import { basename as basename5, dirname as dirname14, join as join20 } from "path";
|
|
4674
4790
|
|
|
4675
4791
|
// src/commands/transcript/cleanText.ts
|
|
4676
4792
|
function cleanText(text) {
|
|
@@ -4880,17 +4996,17 @@ function toMdFilename(vttFilename) {
|
|
|
4880
4996
|
return `${basename5(vttFilename, ".vtt").replace(/\s*Transcription\s*/g, " ").trim()}.md`;
|
|
4881
4997
|
}
|
|
4882
4998
|
function resolveOutputDir(relativeDir, transcriptsDir) {
|
|
4883
|
-
return relativeDir === "." ? transcriptsDir :
|
|
4999
|
+
return relativeDir === "." ? transcriptsDir : join20(transcriptsDir, relativeDir);
|
|
4884
5000
|
}
|
|
4885
5001
|
function buildOutputPaths(vttFile, transcriptsDir) {
|
|
4886
5002
|
const mdFile = toMdFilename(vttFile.filename);
|
|
4887
5003
|
const relativeDir = dirname14(vttFile.relativePath);
|
|
4888
5004
|
const outputDir = resolveOutputDir(relativeDir, transcriptsDir);
|
|
4889
|
-
const outputPath =
|
|
5005
|
+
const outputPath = join20(outputDir, mdFile);
|
|
4890
5006
|
return { outputDir, outputPath, mdFile, relativeDir };
|
|
4891
5007
|
}
|
|
4892
5008
|
function logSkipped(relativeDir, mdFile) {
|
|
4893
|
-
console.log(`Skipping (already exists): ${
|
|
5009
|
+
console.log(`Skipping (already exists): ${join20(relativeDir, mdFile)}`);
|
|
4894
5010
|
return "skipped";
|
|
4895
5011
|
}
|
|
4896
5012
|
function ensureDirectory(dir, label2) {
|
|
@@ -4920,7 +5036,7 @@ function readAndParseCues(inputPath) {
|
|
|
4920
5036
|
return processCues(readFileSync15(inputPath, "utf-8"));
|
|
4921
5037
|
}
|
|
4922
5038
|
function writeFormatted(outputPath, content) {
|
|
4923
|
-
|
|
5039
|
+
writeFileSync17(outputPath, content, "utf-8");
|
|
4924
5040
|
console.log(`Written: ${outputPath}`);
|
|
4925
5041
|
}
|
|
4926
5042
|
function convertVttToMarkdown(inputPath, outputPath) {
|
|
@@ -4989,7 +5105,7 @@ async function format() {
|
|
|
4989
5105
|
|
|
4990
5106
|
// src/commands/transcript/summarise/index.ts
|
|
4991
5107
|
import { existsSync as existsSync22 } from "fs";
|
|
4992
|
-
import { basename as basename6, dirname as dirname16, join as
|
|
5108
|
+
import { basename as basename6, dirname as dirname16, join as join22, relative as relative2 } from "path";
|
|
4993
5109
|
|
|
4994
5110
|
// src/commands/transcript/summarise/processStagedFile/index.ts
|
|
4995
5111
|
import {
|
|
@@ -4999,7 +5115,7 @@ import {
|
|
|
4999
5115
|
renameSync as renameSync2,
|
|
5000
5116
|
rmSync
|
|
5001
5117
|
} from "fs";
|
|
5002
|
-
import { dirname as dirname15, join as
|
|
5118
|
+
import { dirname as dirname15, join as join21 } from "path";
|
|
5003
5119
|
|
|
5004
5120
|
// src/commands/transcript/summarise/processStagedFile/validateStagedContent.ts
|
|
5005
5121
|
import chalk50 from "chalk";
|
|
@@ -5028,7 +5144,7 @@ function validateStagedContent(filename, content) {
|
|
|
5028
5144
|
}
|
|
5029
5145
|
|
|
5030
5146
|
// src/commands/transcript/summarise/processStagedFile/index.ts
|
|
5031
|
-
var STAGING_DIR =
|
|
5147
|
+
var STAGING_DIR = join21(process.cwd(), ".assist", "transcript");
|
|
5032
5148
|
function processStagedFile() {
|
|
5033
5149
|
if (!existsSync21(STAGING_DIR)) {
|
|
5034
5150
|
return false;
|
|
@@ -5052,7 +5168,7 @@ function processStagedFile() {
|
|
|
5052
5168
|
);
|
|
5053
5169
|
process.exit(1);
|
|
5054
5170
|
}
|
|
5055
|
-
const destPath =
|
|
5171
|
+
const destPath = join21(summaryDir, matchingTranscript.relativePath);
|
|
5056
5172
|
const destDir = dirname15(destPath);
|
|
5057
5173
|
if (!existsSync21(destDir)) {
|
|
5058
5174
|
mkdirSync6(destDir, { recursive: true });
|
|
@@ -5068,7 +5184,7 @@ function processStagedFile() {
|
|
|
5068
5184
|
// src/commands/transcript/summarise/index.ts
|
|
5069
5185
|
function buildRelativeKey(relativePath, baseName) {
|
|
5070
5186
|
const relDir = dirname16(relativePath);
|
|
5071
|
-
return relDir === "." ? baseName :
|
|
5187
|
+
return relDir === "." ? baseName : join22(relDir, baseName);
|
|
5072
5188
|
}
|
|
5073
5189
|
function buildSummaryIndex(summaryDir) {
|
|
5074
5190
|
const summaryFiles = findMdFilesRecursive(summaryDir);
|
|
@@ -5102,8 +5218,8 @@ function summarise() {
|
|
|
5102
5218
|
}
|
|
5103
5219
|
const next2 = missing[0];
|
|
5104
5220
|
const outputFilename = `${getTranscriptBaseName(next2.filename)}.md`;
|
|
5105
|
-
const outputPath =
|
|
5106
|
-
const summaryFileDir =
|
|
5221
|
+
const outputPath = join22(STAGING_DIR, outputFilename);
|
|
5222
|
+
const summaryFileDir = join22(summaryDir, dirname16(next2.relativePath));
|
|
5107
5223
|
const relativeTranscriptPath = encodeURI(
|
|
5108
5224
|
relative2(summaryFileDir, next2.absolutePath).replace(/\\/g, "/")
|
|
5109
5225
|
);
|
|
@@ -5348,8 +5464,8 @@ function registerRoam(program2) {
|
|
|
5348
5464
|
import { spawn as spawn4 } from "child_process";
|
|
5349
5465
|
|
|
5350
5466
|
// src/commands/run/add.ts
|
|
5351
|
-
import { mkdirSync as mkdirSync7, writeFileSync as
|
|
5352
|
-
import { join as
|
|
5467
|
+
import { mkdirSync as mkdirSync7, writeFileSync as writeFileSync18 } from "fs";
|
|
5468
|
+
import { join as join23 } from "path";
|
|
5353
5469
|
function findAddIndex() {
|
|
5354
5470
|
const addIndex = process.argv.indexOf("add");
|
|
5355
5471
|
if (addIndex === -1 || addIndex + 2 >= process.argv.length) return -1;
|
|
@@ -5403,7 +5519,7 @@ function saveNewRunConfig(name, command, args) {
|
|
|
5403
5519
|
saveConfig(config);
|
|
5404
5520
|
}
|
|
5405
5521
|
function createCommandFile(name) {
|
|
5406
|
-
const dir =
|
|
5522
|
+
const dir = join23(".claude", "commands");
|
|
5407
5523
|
mkdirSync7(dir, { recursive: true });
|
|
5408
5524
|
const content = `---
|
|
5409
5525
|
description: Run ${name}
|
|
@@ -5411,8 +5527,8 @@ description: Run ${name}
|
|
|
5411
5527
|
|
|
5412
5528
|
Run \`assist run ${name} $ARGUMENTS 2>&1\`.
|
|
5413
5529
|
`;
|
|
5414
|
-
const filePath =
|
|
5415
|
-
|
|
5530
|
+
const filePath = join23(dir, `${name}.md`);
|
|
5531
|
+
writeFileSync18(filePath, content);
|
|
5416
5532
|
console.log(`Created command file: ${filePath}`);
|
|
5417
5533
|
}
|
|
5418
5534
|
function add2() {
|