@staff0rd/assist 0.78.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 +2 -0
- package/claude/commands/comment.md +39 -0
- package/dist/index.js +170 -89
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -31,6 +31,7 @@ After installation, the `assist` command will be available globally.
|
|
|
31
31
|
|
|
32
32
|
## Claude Commands
|
|
33
33
|
|
|
34
|
+
- `/comment` - Add pending review comments to the current PR
|
|
34
35
|
- `/commit` - Commit only relevant files from the session
|
|
35
36
|
- `/devlog` - Generate devlog entry for the next unversioned day
|
|
36
37
|
- `/next-backlog-item` - Pick and implement the next backlog item
|
|
@@ -54,6 +55,7 @@ After installation, the `assist` command will be available globally.
|
|
|
54
55
|
- `assist prs list-comments` - List all comments on the current branch's pull request
|
|
55
56
|
- `assist prs fixed <comment-id> <sha>` - Reply with commit link and resolve thread
|
|
56
57
|
- `assist prs wontfix <comment-id> <reason>` - Reply with reason and resolve thread
|
|
58
|
+
- `assist prs comment <path> <line> <body>` - Add a line comment to the pending review
|
|
57
59
|
- `assist backlog` - Start the backlog web UI (same as `backlog web`)
|
|
58
60
|
- `assist backlog init` - Create an empty assist.backlog.yml
|
|
59
61
|
- `assist backlog list [--status <type>] [-v]` - List all backlog items with status icons
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Add pending review comments to the current PR
|
|
3
|
+
allowed_args: "<item numbers, e.g. 1,2,3>"
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
Add pending review comments to the current branch's pull request for the specified items.
|
|
7
|
+
|
|
8
|
+
## Parsing Arguments
|
|
9
|
+
|
|
10
|
+
Parse `$ARGUMENTS` as a comma-separated list of item numbers (e.g. `1,2` or `1,2,3`). These refer to items in a numbered list from earlier in the conversation.
|
|
11
|
+
|
|
12
|
+
## Finding the Referenced List
|
|
13
|
+
|
|
14
|
+
Look back through the conversation for the most recent numbered list of issues, suggestions, or comments. Each item should have enough context to determine:
|
|
15
|
+
- **path**: the file path
|
|
16
|
+
- **line**: the line number
|
|
17
|
+
- **body**: a concise comment describing the issue
|
|
18
|
+
|
|
19
|
+
If any referenced item number doesn't exist in the list, report the error and skip it.
|
|
20
|
+
|
|
21
|
+
## Posting Comments
|
|
22
|
+
|
|
23
|
+
For each referenced item, run:
|
|
24
|
+
|
|
25
|
+
```
|
|
26
|
+
assist prs comment <path> <line> '<body>' 2>&1
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
**Important:** Always use single quotes around `<body>`, never double quotes. Double quotes cause shell escaping issues with backticks and special characters.
|
|
30
|
+
|
|
31
|
+
The body must:
|
|
32
|
+
- Be a clear, concise description of the issue (1-2 sentences)
|
|
33
|
+
- Not contain "claude" or "opus" (case-insensitive) — the command will reject it
|
|
34
|
+
- Not contain single quotes (reword to avoid them)
|
|
35
|
+
- Use backticks to wrap inline code or keywords (e.g. `functionName`)
|
|
36
|
+
|
|
37
|
+
## Report
|
|
38
|
+
|
|
39
|
+
After posting, summarise which comments were added and any that failed.
|
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: {
|
|
@@ -3269,37 +3269,11 @@ function registerDevlog(program2) {
|
|
|
3269
3269
|
devlogCommand.command("skip <date>").description("Add a date (YYYY-MM-DD) to the skip list").action(skip);
|
|
3270
3270
|
}
|
|
3271
3271
|
|
|
3272
|
-
// src/commands/prs/
|
|
3273
|
-
import {
|
|
3274
|
-
|
|
3275
|
-
// src/commands/prs/resolveCommentWithReply.ts
|
|
3276
|
-
import { execSync as execSync16 } from "child_process";
|
|
3277
|
-
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";
|
|
3278
3275
|
import { tmpdir as tmpdir2 } from "os";
|
|
3279
|
-
import { join as join13 } from "path";
|
|
3280
|
-
|
|
3281
|
-
// src/commands/prs/loadCommentsCache.ts
|
|
3282
|
-
import { existsSync as existsSync16, readFileSync as readFileSync14, unlinkSync as unlinkSync3 } from "fs";
|
|
3283
3276
|
import { join as join12 } from "path";
|
|
3284
|
-
import { parse } from "yaml";
|
|
3285
|
-
function getCachePath(prNumber) {
|
|
3286
|
-
return join12(process.cwd(), ".assist", `pr-${prNumber}-comments.yaml`);
|
|
3287
|
-
}
|
|
3288
|
-
function loadCommentsCache(prNumber) {
|
|
3289
|
-
const cachePath = getCachePath(prNumber);
|
|
3290
|
-
if (!existsSync16(cachePath)) {
|
|
3291
|
-
return null;
|
|
3292
|
-
}
|
|
3293
|
-
const content = readFileSync14(cachePath, "utf-8");
|
|
3294
|
-
return parse(content);
|
|
3295
|
-
}
|
|
3296
|
-
function deleteCommentsCache(prNumber) {
|
|
3297
|
-
const cachePath = getCachePath(prNumber);
|
|
3298
|
-
if (existsSync16(cachePath)) {
|
|
3299
|
-
unlinkSync3(cachePath);
|
|
3300
|
-
console.log("No more unresolved line comments. Cache dropped.");
|
|
3301
|
-
}
|
|
3302
|
-
}
|
|
3303
3277
|
|
|
3304
3278
|
// src/commands/prs/shared.ts
|
|
3305
3279
|
import { execSync as execSync15 } from "child_process";
|
|
@@ -3336,6 +3310,110 @@ function getCurrentPrNumber() {
|
|
|
3336
3310
|
throw error;
|
|
3337
3311
|
}
|
|
3338
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
|
+
}
|
|
3339
3417
|
|
|
3340
3418
|
// src/commands/prs/resolveCommentWithReply.ts
|
|
3341
3419
|
function replyToComment(org, repo, prNumber, commentId, message) {
|
|
@@ -3346,15 +3424,15 @@ function replyToComment(org, repo, prNumber, commentId, message) {
|
|
|
3346
3424
|
}
|
|
3347
3425
|
function resolveThread(threadId) {
|
|
3348
3426
|
const mutation = `mutation($threadId: ID!) { resolveReviewThread(input: {threadId: $threadId}) { thread { isResolved } } }`;
|
|
3349
|
-
const queryFile =
|
|
3350
|
-
|
|
3427
|
+
const queryFile = join14(tmpdir3(), `gh-mutation-${Date.now()}.graphql`);
|
|
3428
|
+
writeFileSync14(queryFile, mutation);
|
|
3351
3429
|
try {
|
|
3352
3430
|
execSync16(
|
|
3353
3431
|
`gh api graphql -F query=@${queryFile} -f threadId="${threadId}"`,
|
|
3354
3432
|
{ stdio: "inherit" }
|
|
3355
3433
|
);
|
|
3356
3434
|
} finally {
|
|
3357
|
-
|
|
3435
|
+
unlinkSync5(queryFile);
|
|
3358
3436
|
}
|
|
3359
3437
|
}
|
|
3360
3438
|
function requireCache(prNumber) {
|
|
@@ -3371,14 +3449,14 @@ function findLineComment(comments, commentId) {
|
|
|
3371
3449
|
return comments.find((c) => c.type === "line" && c.id === commentId);
|
|
3372
3450
|
}
|
|
3373
3451
|
function requireLineComment(cache, commentId) {
|
|
3374
|
-
const
|
|
3375
|
-
if (!
|
|
3452
|
+
const comment2 = findLineComment(cache.comments, commentId);
|
|
3453
|
+
if (!comment2 || comment2.type !== "line" || !comment2.threadId) {
|
|
3376
3454
|
console.error(
|
|
3377
3455
|
`Error: Comment #${commentId} not found or has no thread ID.`
|
|
3378
3456
|
);
|
|
3379
3457
|
process.exit(1);
|
|
3380
3458
|
}
|
|
3381
|
-
return
|
|
3459
|
+
return comment2;
|
|
3382
3460
|
}
|
|
3383
3461
|
function cleanupCacheIfDone(cache, prNumber, commentId) {
|
|
3384
3462
|
const hasRemaining = cache.comments.some(
|
|
@@ -3390,10 +3468,10 @@ function resolveCommentWithReply(commentId, message) {
|
|
|
3390
3468
|
const prNumber = getCurrentPrNumber();
|
|
3391
3469
|
const { org, repo } = getRepoInfo();
|
|
3392
3470
|
const cache = requireCache(prNumber);
|
|
3393
|
-
const
|
|
3471
|
+
const comment2 = requireLineComment(cache, commentId);
|
|
3394
3472
|
replyToComment(org, repo, prNumber, commentId, message);
|
|
3395
3473
|
console.log("Reply posted successfully.");
|
|
3396
|
-
resolveThread(
|
|
3474
|
+
resolveThread(comment2.threadId);
|
|
3397
3475
|
console.log("Thread resolved successfully.");
|
|
3398
3476
|
cleanupCacheIfDone(cache, prNumber, commentId);
|
|
3399
3477
|
}
|
|
@@ -3427,8 +3505,8 @@ function fixed(commentId, sha) {
|
|
|
3427
3505
|
}
|
|
3428
3506
|
|
|
3429
3507
|
// src/commands/prs/listComments/index.ts
|
|
3430
|
-
import { existsSync as existsSync17, mkdirSync as mkdirSync4, writeFileSync as
|
|
3431
|
-
import { join as
|
|
3508
|
+
import { existsSync as existsSync17, mkdirSync as mkdirSync4, writeFileSync as writeFileSync16 } from "fs";
|
|
3509
|
+
import { join as join16 } from "path";
|
|
3432
3510
|
import { stringify } from "yaml";
|
|
3433
3511
|
|
|
3434
3512
|
// src/lib/isClaudeCode.ts
|
|
@@ -3438,13 +3516,13 @@ function isClaudeCode2() {
|
|
|
3438
3516
|
|
|
3439
3517
|
// src/commands/prs/fetchThreadIds.ts
|
|
3440
3518
|
import { execSync as execSync18 } from "child_process";
|
|
3441
|
-
import { unlinkSync as
|
|
3442
|
-
import { tmpdir as
|
|
3443
|
-
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";
|
|
3444
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 } } } } } } }`;
|
|
3445
3523
|
function fetchThreadIds(org, repo, prNumber) {
|
|
3446
|
-
const queryFile =
|
|
3447
|
-
|
|
3524
|
+
const queryFile = join15(tmpdir4(), `gh-query-${Date.now()}.graphql`);
|
|
3525
|
+
writeFileSync15(queryFile, THREAD_QUERY);
|
|
3448
3526
|
try {
|
|
3449
3527
|
const result = execSync18(
|
|
3450
3528
|
`gh api graphql -F query=@${queryFile} -F owner="${org}" -F repo="${repo}" -F prNumber=${prNumber}`,
|
|
@@ -3457,13 +3535,13 @@ function fetchThreadIds(org, repo, prNumber) {
|
|
|
3457
3535
|
if (thread.isResolved) {
|
|
3458
3536
|
resolvedThreadIds.add(thread.id);
|
|
3459
3537
|
}
|
|
3460
|
-
for (const
|
|
3461
|
-
threadMap.set(
|
|
3538
|
+
for (const comment2 of thread.comments.nodes) {
|
|
3539
|
+
threadMap.set(comment2.databaseId, thread.id);
|
|
3462
3540
|
}
|
|
3463
3541
|
}
|
|
3464
3542
|
return { threadMap, resolvedThreadIds };
|
|
3465
3543
|
} finally {
|
|
3466
|
-
|
|
3544
|
+
unlinkSync6(queryFile);
|
|
3467
3545
|
}
|
|
3468
3546
|
}
|
|
3469
3547
|
|
|
@@ -3511,42 +3589,42 @@ function fetchLineComments(org, repo, prNumber, threadInfo) {
|
|
|
3511
3589
|
|
|
3512
3590
|
// src/commands/prs/listComments/formatForHuman.ts
|
|
3513
3591
|
import chalk43 from "chalk";
|
|
3514
|
-
function formatForHuman(
|
|
3515
|
-
if (
|
|
3516
|
-
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;
|
|
3517
3595
|
return [
|
|
3518
|
-
`${chalk43.cyan("Review")} by ${chalk43.bold(
|
|
3519
|
-
|
|
3596
|
+
`${chalk43.cyan("Review")} by ${chalk43.bold(comment2.user)} ${stateColor(`[${comment2.state}]`)}`,
|
|
3597
|
+
comment2.body,
|
|
3520
3598
|
""
|
|
3521
3599
|
].join("\n");
|
|
3522
3600
|
}
|
|
3523
|
-
const location =
|
|
3601
|
+
const location = comment2.line ? `:${comment2.line}` : "";
|
|
3524
3602
|
return [
|
|
3525
|
-
`${chalk43.cyan("Line comment")} by ${chalk43.bold(
|
|
3526
|
-
chalk43.dim(
|
|
3527
|
-
|
|
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,
|
|
3528
3606
|
""
|
|
3529
3607
|
].join("\n");
|
|
3530
3608
|
}
|
|
3531
3609
|
|
|
3532
3610
|
// src/commands/prs/listComments/index.ts
|
|
3533
|
-
function formatComment(
|
|
3534
|
-
return isClaudeCode2() ? JSON.stringify(
|
|
3611
|
+
function formatComment(comment2) {
|
|
3612
|
+
return isClaudeCode2() ? JSON.stringify(comment2) : formatForHuman(comment2);
|
|
3535
3613
|
}
|
|
3536
3614
|
function printComments(comments) {
|
|
3537
3615
|
if (comments.length === 0) {
|
|
3538
3616
|
console.log("No comments found.");
|
|
3539
3617
|
return;
|
|
3540
3618
|
}
|
|
3541
|
-
for (const
|
|
3542
|
-
console.log(formatComment(
|
|
3619
|
+
for (const comment2 of comments) {
|
|
3620
|
+
console.log(formatComment(comment2));
|
|
3543
3621
|
}
|
|
3544
3622
|
if (!comments.some((c) => c.type === "line")) {
|
|
3545
3623
|
console.log("No line comments to process.");
|
|
3546
3624
|
}
|
|
3547
3625
|
}
|
|
3548
3626
|
function writeCommentsCache(prNumber, comments) {
|
|
3549
|
-
const assistDir =
|
|
3627
|
+
const assistDir = join16(process.cwd(), ".assist");
|
|
3550
3628
|
if (!existsSync17(assistDir)) {
|
|
3551
3629
|
mkdirSync4(assistDir, { recursive: true });
|
|
3552
3630
|
}
|
|
@@ -3555,8 +3633,8 @@ function writeCommentsCache(prNumber, comments) {
|
|
|
3555
3633
|
fetchedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
3556
3634
|
comments
|
|
3557
3635
|
};
|
|
3558
|
-
const cachePath =
|
|
3559
|
-
|
|
3636
|
+
const cachePath = join16(assistDir, `pr-${prNumber}-comments.yaml`);
|
|
3637
|
+
writeFileSync16(cachePath, stringify(cacheData));
|
|
3560
3638
|
}
|
|
3561
3639
|
function handleKnownErrors(error) {
|
|
3562
3640
|
if (isGhNotInstalled(error)) {
|
|
@@ -3781,6 +3859,9 @@ function registerPrs(program2) {
|
|
|
3781
3859
|
prsCommand.command("wontfix <comment-id> <reason>").description("Reply with reason and resolve thread").action((commentId, reason) => {
|
|
3782
3860
|
wontfix(Number.parseInt(commentId, 10), reason);
|
|
3783
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
|
+
});
|
|
3784
3865
|
}
|
|
3785
3866
|
|
|
3786
3867
|
// src/commands/refactor/check/index.ts
|
|
@@ -4518,7 +4599,7 @@ function registerRefactor(program2) {
|
|
|
4518
4599
|
|
|
4519
4600
|
// src/commands/transcript/shared.ts
|
|
4520
4601
|
import { existsSync as existsSync18, readdirSync as readdirSync2, statSync } from "fs";
|
|
4521
|
-
import { basename as basename4, join as
|
|
4602
|
+
import { basename as basename4, join as join17, relative } from "path";
|
|
4522
4603
|
import * as readline2 from "readline";
|
|
4523
4604
|
var DATE_PREFIX_REGEX = /^\d{4}-\d{2}-\d{2}/;
|
|
4524
4605
|
function getDatePrefix(daysOffset = 0) {
|
|
@@ -4536,7 +4617,7 @@ function collectFiles(dir, extension) {
|
|
|
4536
4617
|
if (!existsSync18(dir)) return [];
|
|
4537
4618
|
const results = [];
|
|
4538
4619
|
for (const entry of readdirSync2(dir)) {
|
|
4539
|
-
const fullPath =
|
|
4620
|
+
const fullPath = join17(dir, entry);
|
|
4540
4621
|
if (statSync(fullPath).isDirectory()) {
|
|
4541
4622
|
results.push(...collectFiles(fullPath, extension));
|
|
4542
4623
|
} else if (entry.endsWith(extension)) {
|
|
@@ -4633,11 +4714,11 @@ async function configure() {
|
|
|
4633
4714
|
import { existsSync as existsSync20 } from "fs";
|
|
4634
4715
|
|
|
4635
4716
|
// src/commands/transcript/format/fixInvalidDatePrefixes/index.ts
|
|
4636
|
-
import { dirname as dirname13, join as
|
|
4717
|
+
import { dirname as dirname13, join as join19 } from "path";
|
|
4637
4718
|
|
|
4638
4719
|
// src/commands/transcript/format/fixInvalidDatePrefixes/promptForDateFix.ts
|
|
4639
4720
|
import { renameSync } from "fs";
|
|
4640
|
-
import { join as
|
|
4721
|
+
import { join as join18 } from "path";
|
|
4641
4722
|
async function resolveDate(rl, choice) {
|
|
4642
4723
|
if (choice === "1") return getDatePrefix(0);
|
|
4643
4724
|
if (choice === "2") return getDatePrefix(-1);
|
|
@@ -4652,7 +4733,7 @@ async function resolveDate(rl, choice) {
|
|
|
4652
4733
|
}
|
|
4653
4734
|
function renameWithPrefix(vttDir, vttFile, prefix) {
|
|
4654
4735
|
const newFilename = `${prefix}.${vttFile}`;
|
|
4655
|
-
renameSync(
|
|
4736
|
+
renameSync(join18(vttDir, vttFile), join18(vttDir, newFilename));
|
|
4656
4737
|
console.log(`Renamed to: ${newFilename}`);
|
|
4657
4738
|
return newFilename;
|
|
4658
4739
|
}
|
|
@@ -4686,12 +4767,12 @@ async function fixInvalidDatePrefixes(vttFiles) {
|
|
|
4686
4767
|
const vttFileDir = dirname13(vttFile.absolutePath);
|
|
4687
4768
|
const newFilename = await promptForDateFix(vttFile.filename, vttFileDir);
|
|
4688
4769
|
if (newFilename) {
|
|
4689
|
-
const newRelativePath =
|
|
4770
|
+
const newRelativePath = join19(
|
|
4690
4771
|
dirname13(vttFile.relativePath),
|
|
4691
4772
|
newFilename
|
|
4692
4773
|
);
|
|
4693
4774
|
vttFiles[i] = {
|
|
4694
|
-
absolutePath:
|
|
4775
|
+
absolutePath: join19(vttFileDir, newFilename),
|
|
4695
4776
|
relativePath: newRelativePath,
|
|
4696
4777
|
filename: newFilename
|
|
4697
4778
|
};
|
|
@@ -4704,8 +4785,8 @@ async function fixInvalidDatePrefixes(vttFiles) {
|
|
|
4704
4785
|
}
|
|
4705
4786
|
|
|
4706
4787
|
// src/commands/transcript/format/processVttFile/index.ts
|
|
4707
|
-
import { existsSync as existsSync19, mkdirSync as mkdirSync5, readFileSync as readFileSync15, writeFileSync as
|
|
4708
|
-
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";
|
|
4709
4790
|
|
|
4710
4791
|
// src/commands/transcript/cleanText.ts
|
|
4711
4792
|
function cleanText(text) {
|
|
@@ -4915,17 +4996,17 @@ function toMdFilename(vttFilename) {
|
|
|
4915
4996
|
return `${basename5(vttFilename, ".vtt").replace(/\s*Transcription\s*/g, " ").trim()}.md`;
|
|
4916
4997
|
}
|
|
4917
4998
|
function resolveOutputDir(relativeDir, transcriptsDir) {
|
|
4918
|
-
return relativeDir === "." ? transcriptsDir :
|
|
4999
|
+
return relativeDir === "." ? transcriptsDir : join20(transcriptsDir, relativeDir);
|
|
4919
5000
|
}
|
|
4920
5001
|
function buildOutputPaths(vttFile, transcriptsDir) {
|
|
4921
5002
|
const mdFile = toMdFilename(vttFile.filename);
|
|
4922
5003
|
const relativeDir = dirname14(vttFile.relativePath);
|
|
4923
5004
|
const outputDir = resolveOutputDir(relativeDir, transcriptsDir);
|
|
4924
|
-
const outputPath =
|
|
5005
|
+
const outputPath = join20(outputDir, mdFile);
|
|
4925
5006
|
return { outputDir, outputPath, mdFile, relativeDir };
|
|
4926
5007
|
}
|
|
4927
5008
|
function logSkipped(relativeDir, mdFile) {
|
|
4928
|
-
console.log(`Skipping (already exists): ${
|
|
5009
|
+
console.log(`Skipping (already exists): ${join20(relativeDir, mdFile)}`);
|
|
4929
5010
|
return "skipped";
|
|
4930
5011
|
}
|
|
4931
5012
|
function ensureDirectory(dir, label2) {
|
|
@@ -4955,7 +5036,7 @@ function readAndParseCues(inputPath) {
|
|
|
4955
5036
|
return processCues(readFileSync15(inputPath, "utf-8"));
|
|
4956
5037
|
}
|
|
4957
5038
|
function writeFormatted(outputPath, content) {
|
|
4958
|
-
|
|
5039
|
+
writeFileSync17(outputPath, content, "utf-8");
|
|
4959
5040
|
console.log(`Written: ${outputPath}`);
|
|
4960
5041
|
}
|
|
4961
5042
|
function convertVttToMarkdown(inputPath, outputPath) {
|
|
@@ -5024,7 +5105,7 @@ async function format() {
|
|
|
5024
5105
|
|
|
5025
5106
|
// src/commands/transcript/summarise/index.ts
|
|
5026
5107
|
import { existsSync as existsSync22 } from "fs";
|
|
5027
|
-
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";
|
|
5028
5109
|
|
|
5029
5110
|
// src/commands/transcript/summarise/processStagedFile/index.ts
|
|
5030
5111
|
import {
|
|
@@ -5034,7 +5115,7 @@ import {
|
|
|
5034
5115
|
renameSync as renameSync2,
|
|
5035
5116
|
rmSync
|
|
5036
5117
|
} from "fs";
|
|
5037
|
-
import { dirname as dirname15, join as
|
|
5118
|
+
import { dirname as dirname15, join as join21 } from "path";
|
|
5038
5119
|
|
|
5039
5120
|
// src/commands/transcript/summarise/processStagedFile/validateStagedContent.ts
|
|
5040
5121
|
import chalk50 from "chalk";
|
|
@@ -5063,7 +5144,7 @@ function validateStagedContent(filename, content) {
|
|
|
5063
5144
|
}
|
|
5064
5145
|
|
|
5065
5146
|
// src/commands/transcript/summarise/processStagedFile/index.ts
|
|
5066
|
-
var STAGING_DIR =
|
|
5147
|
+
var STAGING_DIR = join21(process.cwd(), ".assist", "transcript");
|
|
5067
5148
|
function processStagedFile() {
|
|
5068
5149
|
if (!existsSync21(STAGING_DIR)) {
|
|
5069
5150
|
return false;
|
|
@@ -5087,7 +5168,7 @@ function processStagedFile() {
|
|
|
5087
5168
|
);
|
|
5088
5169
|
process.exit(1);
|
|
5089
5170
|
}
|
|
5090
|
-
const destPath =
|
|
5171
|
+
const destPath = join21(summaryDir, matchingTranscript.relativePath);
|
|
5091
5172
|
const destDir = dirname15(destPath);
|
|
5092
5173
|
if (!existsSync21(destDir)) {
|
|
5093
5174
|
mkdirSync6(destDir, { recursive: true });
|
|
@@ -5103,7 +5184,7 @@ function processStagedFile() {
|
|
|
5103
5184
|
// src/commands/transcript/summarise/index.ts
|
|
5104
5185
|
function buildRelativeKey(relativePath, baseName) {
|
|
5105
5186
|
const relDir = dirname16(relativePath);
|
|
5106
|
-
return relDir === "." ? baseName :
|
|
5187
|
+
return relDir === "." ? baseName : join22(relDir, baseName);
|
|
5107
5188
|
}
|
|
5108
5189
|
function buildSummaryIndex(summaryDir) {
|
|
5109
5190
|
const summaryFiles = findMdFilesRecursive(summaryDir);
|
|
@@ -5137,8 +5218,8 @@ function summarise() {
|
|
|
5137
5218
|
}
|
|
5138
5219
|
const next2 = missing[0];
|
|
5139
5220
|
const outputFilename = `${getTranscriptBaseName(next2.filename)}.md`;
|
|
5140
|
-
const outputPath =
|
|
5141
|
-
const summaryFileDir =
|
|
5221
|
+
const outputPath = join22(STAGING_DIR, outputFilename);
|
|
5222
|
+
const summaryFileDir = join22(summaryDir, dirname16(next2.relativePath));
|
|
5142
5223
|
const relativeTranscriptPath = encodeURI(
|
|
5143
5224
|
relative2(summaryFileDir, next2.absolutePath).replace(/\\/g, "/")
|
|
5144
5225
|
);
|
|
@@ -5383,8 +5464,8 @@ function registerRoam(program2) {
|
|
|
5383
5464
|
import { spawn as spawn4 } from "child_process";
|
|
5384
5465
|
|
|
5385
5466
|
// src/commands/run/add.ts
|
|
5386
|
-
import { mkdirSync as mkdirSync7, writeFileSync as
|
|
5387
|
-
import { join as
|
|
5467
|
+
import { mkdirSync as mkdirSync7, writeFileSync as writeFileSync18 } from "fs";
|
|
5468
|
+
import { join as join23 } from "path";
|
|
5388
5469
|
function findAddIndex() {
|
|
5389
5470
|
const addIndex = process.argv.indexOf("add");
|
|
5390
5471
|
if (addIndex === -1 || addIndex + 2 >= process.argv.length) return -1;
|
|
@@ -5438,7 +5519,7 @@ function saveNewRunConfig(name, command, args) {
|
|
|
5438
5519
|
saveConfig(config);
|
|
5439
5520
|
}
|
|
5440
5521
|
function createCommandFile(name) {
|
|
5441
|
-
const dir =
|
|
5522
|
+
const dir = join23(".claude", "commands");
|
|
5442
5523
|
mkdirSync7(dir, { recursive: true });
|
|
5443
5524
|
const content = `---
|
|
5444
5525
|
description: Run ${name}
|
|
@@ -5446,8 +5527,8 @@ description: Run ${name}
|
|
|
5446
5527
|
|
|
5447
5528
|
Run \`assist run ${name} $ARGUMENTS 2>&1\`.
|
|
5448
5529
|
`;
|
|
5449
|
-
const filePath =
|
|
5450
|
-
|
|
5530
|
+
const filePath = join23(dir, `${name}.md`);
|
|
5531
|
+
writeFileSync18(filePath, content);
|
|
5451
5532
|
console.log(`Created command file: ${filePath}`);
|
|
5452
5533
|
}
|
|
5453
5534
|
function add2() {
|