@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/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.77.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({ id, name, description, acceptanceCriteria, status: "todo" });
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
- if (item.description) {
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/shared.ts
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/fixed.ts
3238
- import { execSync as execSync17 } from "child_process";
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 = join13(tmpdir2(), `gh-mutation-${Date.now()}.graphql`);
3315
- writeFileSync13(queryFile, mutation);
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
- unlinkSync4(queryFile);
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 comment = findLineComment(cache.comments, commentId);
3340
- if (!comment || comment.type !== "line" || !comment.threadId) {
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 comment;
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 comment = requireLineComment(cache, commentId);
3471
+ const comment2 = requireLineComment(cache, commentId);
3359
3472
  replyToComment(org, repo, prNumber, commentId, message);
3360
3473
  console.log("Reply posted successfully.");
3361
- resolveThread(comment.threadId);
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 writeFileSync15 } from "fs";
3396
- import { join as join15 } from "path";
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 unlinkSync5, writeFileSync as writeFileSync14 } from "fs";
3407
- import { tmpdir as tmpdir3 } from "os";
3408
- import { join as join14 } from "path";
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 = join14(tmpdir3(), `gh-query-${Date.now()}.graphql`);
3412
- writeFileSync14(queryFile, THREAD_QUERY);
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 comment of thread.comments.nodes) {
3426
- threadMap.set(comment.databaseId, thread.id);
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
- unlinkSync5(queryFile);
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(comment) {
3480
- if (comment.type === "review") {
3481
- const stateColor = comment.state === "APPROVED" ? chalk43.green : comment.state === "CHANGES_REQUESTED" ? chalk43.red : chalk43.yellow;
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(comment.user)} ${stateColor(`[${comment.state}]`)}`,
3484
- comment.body,
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 = comment.line ? `:${comment.line}` : "";
3601
+ const location = comment2.line ? `:${comment2.line}` : "";
3489
3602
  return [
3490
- `${chalk43.cyan("Line comment")} by ${chalk43.bold(comment.user)} on ${chalk43.dim(`${comment.path}${location}`)}`,
3491
- chalk43.dim(comment.diff_hunk.split("\n").slice(-3).join("\n")),
3492
- comment.body,
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(comment) {
3499
- return isClaudeCode2() ? JSON.stringify(comment) : formatForHuman(comment);
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 comment of comments) {
3507
- console.log(formatComment(comment));
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 = join15(process.cwd(), ".assist");
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 = join15(assistDir, `pr-${prNumber}-comments.yaml`);
3524
- writeFileSync15(cachePath, stringify(cacheData));
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 join16, relative } from "path";
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 = join16(dir, entry);
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 join18 } from "path";
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 join17 } from "path";
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(join17(vttDir, vttFile), join17(vttDir, newFilename));
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 = join18(
4770
+ const newRelativePath = join19(
4655
4771
  dirname13(vttFile.relativePath),
4656
4772
  newFilename
4657
4773
  );
4658
4774
  vttFiles[i] = {
4659
- absolutePath: join18(vttFileDir, newFilename),
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 writeFileSync16 } from "fs";
4673
- import { basename as basename5, dirname as dirname14, join as join19 } from "path";
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 : join19(transcriptsDir, relativeDir);
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 = join19(outputDir, mdFile);
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): ${join19(relativeDir, mdFile)}`);
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
- writeFileSync16(outputPath, content, "utf-8");
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 join21, relative as relative2 } from "path";
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 join20 } from "path";
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 = join20(process.cwd(), ".assist", "transcript");
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 = join20(summaryDir, matchingTranscript.relativePath);
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 : join21(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 = join21(STAGING_DIR, outputFilename);
5106
- const summaryFileDir = join21(summaryDir, dirname16(next2.relativePath));
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 writeFileSync17 } from "fs";
5352
- import { join as join22 } from "path";
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 = join22(".claude", "commands");
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 = join22(dir, `${name}.md`);
5415
- writeFileSync17(filePath, content);
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() {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@staff0rd/assist",
3
- "version": "0.77.0",
3
+ "version": "0.79.0",
4
4
  "type": "module",
5
5
  "main": "dist/index.js",
6
6
  "bin": {