@staff0rd/assist 0.565.2 → 0.567.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.565.2",
9
+ version: "0.567.0",
10
10
  type: "module",
11
11
  main: "dist/index.js",
12
12
  bin: {
@@ -468,6 +468,9 @@ var DEFAULT_MODELS_DIR = "~/.assist/voice/models";
468
468
  var DEFAULT_BACKUP_DIR = "~/.assist/backups";
469
469
  var DEFAULT_CLONE_DIR = "~/git";
470
470
  var assistConfigShape = {
471
+ backlog: z3.strictObject({
472
+ previewComments: z3.boolean().default(false)
473
+ }).optional(),
471
474
  backup: z3.strictObject({
472
475
  dir: z3.string().default(DEFAULT_BACKUP_DIR)
473
476
  }).default({ dir: DEFAULT_BACKUP_DIR }),
@@ -4329,6 +4332,11 @@ var backlogConfigHelp = [
4329
4332
  setter: 'assist config set subtasks.0.title "Review"',
4330
4333
  note: "default sub-tasks seeded onto every new backlog item"
4331
4334
  },
4335
+ {
4336
+ key: "backlog.previewComments",
4337
+ setter: "assist config set backlog.previewComments true",
4338
+ note: "review 'backlog comment' in the web preview pane before it is written (default: off)"
4339
+ },
4332
4340
  {
4333
4341
  key: "clone.baseDir",
4334
4342
  setter: "assist config set clone.baseDir ~/git",
@@ -13991,6 +13999,7 @@ async function awaitPreviewApproval(subject, request) {
13991
13999
 
13992
14000
  // src/commands/backlog/comment/reviewProposedComment.ts
13993
14001
  async function reviewProposedComment(item, text18) {
14002
+ if (loadConfig().backlog?.previewComments !== true) return;
13994
14003
  const sessionId = process.env.ASSIST_SESSION_ID;
13995
14004
  if (process.env.ASSIST_SESSION !== "1" || !sessionId) return;
13996
14005
  await awaitPreviewApproval("Backlog comment preview", {
@@ -22699,6 +22708,44 @@ function registerPrompts(program2) {
22699
22708
  program2.command("prompts").description("Show top denied tool calls by frequency").action(prompts2);
22700
22709
  }
22701
22710
 
22711
+ // src/commands/prs/postReviewComment.ts
22712
+ var MUTATION_SINGLE = `mutation($prId: ID!, $body: String!, $path: String!, $line: Int!) { addPullRequestReviewThread(input: { pullRequestId: $prId, body: $body, path: $path, line: $line, side: RIGHT }) { thread { id } } }`;
22713
+ var MUTATION_MULTI = `mutation($prId: ID!, $body: String!, $path: String!, $line: Int!, $startLine: Int!) { addPullRequestReviewThread(input: { pullRequestId: $prId, body: $body, path: $path, line: $line, startLine: $startLine, side: RIGHT, startSide: RIGHT }) { thread { id } } }`;
22714
+ function assertThreadCreated(stdout) {
22715
+ let parsed;
22716
+ try {
22717
+ parsed = JSON.parse(stdout);
22718
+ } catch {
22719
+ throw new Error(`GitHub returned an unparseable response: ${stdout}`);
22720
+ }
22721
+ const id = parsed.data?.addPullRequestReviewThread?.thread?.id;
22722
+ if (typeof id !== "string" || id.length === 0) {
22723
+ throw new Error(
22724
+ "GitHub did not create a review thread (no thread id returned); the line is likely outside the PR diff."
22725
+ );
22726
+ }
22727
+ }
22728
+ function postReviewComment(vars) {
22729
+ const { startLine, ...base } = vars;
22730
+ const stdout = startLine === void 0 ? runGhGraphql(MUTATION_SINGLE, base) : runGhGraphql(MUTATION_MULTI, { ...base, startLine });
22731
+ assertThreadCreated(stdout);
22732
+ }
22733
+
22734
+ // src/commands/prs/reviewProposedPrComment.ts
22735
+ import { randomUUID as randomUUID9 } from "crypto";
22736
+ async function reviewProposedPrComment(title, body, prNumber) {
22737
+ const sessionId = process.env.ASSIST_SESSION_ID;
22738
+ if (process.env.ASSIST_SESSION !== "1" || !sessionId) return;
22739
+ await awaitPreviewApproval("PR comment preview", {
22740
+ sessionId,
22741
+ requestId: randomUUID9(),
22742
+ title,
22743
+ body,
22744
+ prNumber,
22745
+ kind: "pr-comment"
22746
+ });
22747
+ }
22748
+
22702
22749
  // src/commands/prs/shared.ts
22703
22750
  import { execSync as execSync43 } from "child_process";
22704
22751
  function isGhNotInstalled(error) {
@@ -22783,8 +22830,6 @@ function findCurrentPrNumber() {
22783
22830
  }
22784
22831
 
22785
22832
  // src/commands/prs/comment.ts
22786
- var MUTATION_SINGLE = `mutation($prId: ID!, $body: String!, $path: String!, $line: Int!) { addPullRequestReviewThread(input: { pullRequestId: $prId, body: $body, path: $path, line: $line, side: RIGHT }) { thread { id } } }`;
22787
- var MUTATION_MULTI = `mutation($prId: ID!, $body: String!, $path: String!, $line: Int!, $startLine: Int!) { addPullRequestReviewThread(input: { pullRequestId: $prId, body: $body, path: $path, line: $line, startLine: $startLine, side: RIGHT, startSide: RIGHT }) { thread { id } } }`;
22788
22833
  function validateBody(body) {
22789
22834
  const lower = body.toLowerCase();
22790
22835
  if (lower.includes("claude") || lower.includes("opus")) {
@@ -22798,33 +22843,15 @@ function validateLine(line) {
22798
22843
  process.exit(1);
22799
22844
  }
22800
22845
  }
22801
- function assertThreadCreated(stdout) {
22802
- let parsed;
22803
- try {
22804
- parsed = JSON.parse(stdout);
22805
- } catch {
22806
- throw new Error(`GitHub returned an unparseable response: ${stdout}`);
22807
- }
22808
- const id = parsed.data?.addPullRequestReviewThread?.thread?.id;
22809
- if (typeof id !== "string" || id.length === 0) {
22810
- throw new Error(
22811
- "GitHub did not create a review thread (no thread id returned); the line is likely outside the PR diff."
22812
- );
22813
- }
22814
- }
22815
- function postComment(vars) {
22816
- const { startLine, ...base } = vars;
22817
- const stdout = startLine === void 0 ? runGhGraphql(MUTATION_SINGLE, base) : runGhGraphql(MUTATION_MULTI, { ...base, startLine });
22818
- assertThreadCreated(stdout);
22819
- }
22820
- function comment2(path80, line, body, startLine) {
22846
+ async function comment2(path80, line, body, startLine) {
22821
22847
  validateBody(body);
22822
22848
  validateLine(line);
22823
22849
  if (startLine !== void 0) validateLine(startLine);
22850
+ const range = startLine !== void 0 ? `${startLine}-${line}` : `${line}`;
22851
+ await reviewProposedPrComment(`Comment on ${path80}:${range}`, body, null);
22824
22852
  try {
22825
22853
  const prId = getCurrentPrNodeId();
22826
- postComment({ prId, body, path: path80, line, startLine });
22827
- const range = startLine !== void 0 ? `${startLine}-${line}` : `${line}`;
22854
+ postReviewComment({ prId, body, path: path80, line, startLine });
22828
22855
  console.log(`Added review comment on ${path80}:${range}`);
22829
22856
  } catch (error) {
22830
22857
  if (isGhNotInstalled(error)) {
@@ -22837,7 +22864,7 @@ function comment2(path80, line, body, startLine) {
22837
22864
  }
22838
22865
 
22839
22866
  // src/commands/prs/edit.ts
22840
- import { randomUUID as randomUUID9 } from "crypto";
22867
+ import { randomUUID as randomUUID10 } from "crypto";
22841
22868
 
22842
22869
  // src/commands/prs/appendScreenshots.ts
22843
22870
  function appendScreenshots(body, screenshots) {
@@ -23051,7 +23078,7 @@ async function edit(options2) {
23051
23078
  if (process.env.ASSIST_SESSION === "1" && sessionId) {
23052
23079
  const decision = await awaitPreviewApproval("PR preview", {
23053
23080
  sessionId,
23054
- requestId: randomUUID9(),
23081
+ requestId: randomUUID10(),
23055
23082
  title: options2.title ?? title,
23056
23083
  body: newBody,
23057
23084
  prNumber: number
@@ -23762,7 +23789,7 @@ async function placePr(prNumber, title, body, options2) {
23762
23789
  }
23763
23790
 
23764
23791
  // src/commands/prs/previewAndPlace.ts
23765
- import { randomUUID as randomUUID10 } from "crypto";
23792
+ import { randomUUID as randomUUID11 } from "crypto";
23766
23793
 
23767
23794
  // src/commands/sessions/shared/requestSession.ts
23768
23795
  function parseIncoming(line, type) {
@@ -23897,7 +23924,7 @@ function warn(reason4) {
23897
23924
  async function previewAndPlace(args) {
23898
23925
  const decision = await awaitPreviewApproval("PR preview", {
23899
23926
  sessionId: args.sessionId,
23900
- requestId: randomUUID10(),
23927
+ requestId: randomUUID11(),
23901
23928
  title: args.title,
23902
23929
  body: args.body,
23903
23930
  prNumber: args.prNumber,
@@ -23950,8 +23977,9 @@ function validateBody2(body) {
23950
23977
  process.exit(1);
23951
23978
  }
23952
23979
  }
23953
- function reply(commentId, body) {
23980
+ async function reply(commentId, body) {
23954
23981
  validateBody2(body);
23982
+ await reviewProposedPrComment(`Reply to comment #${commentId}`, body, null);
23955
23983
  try {
23956
23984
  const prNumber = getCurrentPrNumber();
23957
23985
  const { org, repo } = getRepoInfo();
@@ -23997,9 +24025,14 @@ function validateShaReferences(reason4) {
23997
24025
  process.exit(1);
23998
24026
  }
23999
24027
  }
24000
- function wontfix(commentId, reason4) {
24028
+ async function wontfix(commentId, reason4) {
24001
24029
  validateReason(reason4);
24002
24030
  validateShaReferences(reason4);
24031
+ await reviewProposedPrComment(
24032
+ `Won't fix comment #${commentId}`,
24033
+ reason4,
24034
+ null
24035
+ );
24003
24036
  try {
24004
24037
  resolveCommentWithReply(commentId, reason4);
24005
24038
  } catch (error) {
@@ -24034,7 +24067,7 @@ function registerPrsComments(prsCommand) {
24034
24067
  prsCommand.command("wontfix <comment-id> <reason>").description(
24035
24068
  "Reply with reason and resolve thread (reason of - reads it from stdin)"
24036
24069
  ).action(async (commentId, reason4) => {
24037
- wontfix(
24070
+ await wontfix(
24038
24071
  Number.parseInt(commentId, 10),
24039
24072
  await readBodyArgument(reason4)
24040
24073
  );
@@ -24042,12 +24075,19 @@ function registerPrsComments(prsCommand) {
24042
24075
  prsCommand.command("reply <comment-id> <body>").description(
24043
24076
  "Reply to a comment thread without resolving it (body of - reads it from stdin)"
24044
24077
  ).action(async (commentId, body) => {
24045
- reply(Number.parseInt(commentId, 10), await readBodyArgument(body));
24078
+ await reply(
24079
+ Number.parseInt(commentId, 10),
24080
+ await readBodyArgument(body)
24081
+ );
24046
24082
  });
24047
24083
  prsCommand.command("comment <path> <line> <body>").description(
24048
24084
  "Add a line comment to the pending review (body of - reads it from stdin)"
24049
24085
  ).action(async (path80, line, body) => {
24050
- comment2(path80, Number.parseInt(line, 10), await readBodyArgument(body));
24086
+ await comment2(
24087
+ path80,
24088
+ Number.parseInt(line, 10),
24089
+ await readBodyArgument(body)
24090
+ );
24051
24091
  });
24052
24092
  }
24053
24093
 
@@ -26367,10 +26407,10 @@ function registerRefactor(program2) {
26367
26407
  }
26368
26408
 
26369
26409
  // src/commands/review/checkoutOnlySession.ts
26370
- import { randomUUID as randomUUID11 } from "crypto";
26410
+ import { randomUUID as randomUUID12 } from "crypto";
26371
26411
  async function checkoutOnlySession(number) {
26372
26412
  await checkoutPr(number);
26373
- const claudeSessionId = randomUUID11();
26413
+ const claudeSessionId = randomUUID12();
26374
26414
  emitActivity({ kind: "command", name: "review", claudeSessionId });
26375
26415
  const { done: done2 } = spawnClaude("", {
26376
26416
  permissionMode: "acceptEdits",
@@ -31732,7 +31772,7 @@ var ClientHub = class extends Set {
31732
31772
  };
31733
31773
 
31734
31774
  // src/commands/sessions/daemon/createSession.ts
31735
- import { randomUUID as randomUUID12 } from "crypto";
31775
+ import { randomUUID as randomUUID13 } from "crypto";
31736
31776
 
31737
31777
  // src/commands/sessions/daemon/sessionBase.ts
31738
31778
  function sessionBase(id, status3) {
@@ -31928,7 +31968,7 @@ function spawnRun(opts) {
31928
31968
  function createSession(id, prompt, cwd, design, harness, holdPty) {
31929
31969
  if (harness && harness !== "claude")
31930
31970
  return createHarnessSession(id, harness, prompt, cwd, holdPty);
31931
- const claudeSessionId = randomUUID12();
31971
+ const claudeSessionId = randomUUID13();
31932
31972
  return {
31933
31973
  ...sessionBase(id, prompt ? "running" : "waiting"),
31934
31974
  name: `Session ${id}`,
@@ -32507,9 +32547,21 @@ function decidePrPreview(sessions, waiters, notify2, d) {
32507
32547
  notify2();
32508
32548
  }
32509
32549
 
32550
+ // src/commands/sessions/daemon/isPreviewKind.ts
32551
+ var PREVIEW_KINDS = [
32552
+ "pr",
32553
+ "backlog-item",
32554
+ "backlog-comment",
32555
+ "pr-comment"
32556
+ ];
32557
+ function isPreviewKind(value) {
32558
+ return PREVIEW_KINDS.includes(value);
32559
+ }
32560
+
32510
32561
  // src/commands/sessions/daemon/previewTargetLabel.ts
32511
32562
  function previewTargetLabel(kind, itemType, prNumber, draft) {
32512
32563
  if (kind === "backlog-comment") return "backlog comment";
32564
+ if (kind === "pr-comment") return "pr comment";
32513
32565
  if (kind === "backlog-item") return `backlog ${itemType}`;
32514
32566
  if (prNumber !== null) return `edit #${prNumber}`;
32515
32567
  return draft ? "create draft" : "create";
@@ -32528,7 +32580,7 @@ function setPrPreview(sessions, waiters, notify2, client, d) {
32528
32580
  return;
32529
32581
  }
32530
32582
  const prNumber = typeof d.prNumber === "number" ? d.prNumber : null;
32531
- const kind = d.kind === "backlog-item" || d.kind === "backlog-comment" ? d.kind : "pr";
32583
+ const kind = isPreviewKind(d.kind) ? d.kind : "pr";
32532
32584
  const itemType = d.itemType === "bug" ? "bug" : "story";
32533
32585
  const draft = d.draft === true;
32534
32586
  session.pendingPrPreview = {
@@ -33969,7 +34021,7 @@ function codexRespawnPlan(session) {
33969
34021
  }
33970
34022
 
33971
34023
  // src/commands/sessions/daemon/interactiveRespawnPlan.ts
33972
- import { randomUUID as randomUUID13 } from "crypto";
34024
+ import { randomUUID as randomUUID14 } from "crypto";
33973
34025
  function interactiveRespawnPlan(session, resumes) {
33974
34026
  const { claudeSessionId, cwd, initialPrompt } = session;
33975
34027
  if (!resumes) return null;
@@ -33987,7 +34039,7 @@ function interactiveRespawnPlan(session, resumes) {
33987
34039
  return null;
33988
34040
  }
33989
34041
  function freshClaudePlan(session, prompt, cwd) {
33990
- const claudeSessionId = randomUUID13();
34042
+ const claudeSessionId = randomUUID14();
33991
34043
  return {
33992
34044
  spawn: () => {
33993
34045
  session.claudeSessionId = claudeSessionId;
@@ -34865,10 +34917,10 @@ function startReusedRunPty(session, assistArgs, itemId2, hold, clients, onStatus
34865
34917
  }
34866
34918
 
34867
34919
  // src/commands/sessions/daemon/createWatcherSession.ts
34868
- import { randomUUID as randomUUID14 } from "crypto";
34920
+ import { randomUUID as randomUUID15 } from "crypto";
34869
34921
  var WATCH_PROMPT = "/watch";
34870
34922
  function createWatcherSession(id, cwd) {
34871
- const claudeSessionId = randomUUID14();
34923
+ const claudeSessionId = randomUUID15();
34872
34924
  return {
34873
34925
  ...sessionBase(id, "running"),
34874
34926
  name: `Session ${id}`,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@staff0rd/assist",
3
- "version": "0.565.2",
3
+ "version": "0.567.0",
4
4
  "type": "module",
5
5
  "main": "dist/index.js",
6
6
  "bin": {