@staff0rd/assist 0.745.0 → 0.747.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.745.0",
9
+ version: "0.747.0",
10
10
  type: "module",
11
11
  main: "dist/index.js",
12
12
  bin: {
@@ -567,6 +567,7 @@ import { z as z3 } from "zod";
567
567
 
568
568
  // src/shared/adviceFragmentNames.ts
569
569
  var adviceFragmentTitles = {
570
+ ask: "Asking for sign-off",
570
571
  "assist-global": "Using assist",
571
572
  "backlog-ids": "Backlog item IDs",
572
573
  "backlog-prs": "Backlog items, PRs, and commits",
@@ -583,6 +584,7 @@ var adviceFragmentTitles = {
583
584
  verify: "Verifying a change"
584
585
  };
585
586
  var adviceFragmentNames = [
587
+ "ask",
586
588
  "assist-global",
587
589
  "backlog-ids",
588
590
  "backlog-prs",
@@ -2863,6 +2865,215 @@ function registerAdvise(program2) {
2863
2865
  configHelp(adviseCommand, adviceConfigHelp);
2864
2866
  }
2865
2867
 
2868
+ // src/commands/ask.ts
2869
+ import { randomUUID } from "crypto";
2870
+
2871
+ // src/commands/backlog/import/readStdinBuffer.ts
2872
+ async function readStdinBuffer() {
2873
+ const chunks = [];
2874
+ for await (const chunk of process.stdin) {
2875
+ chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
2876
+ }
2877
+ return Buffer.concat(chunks);
2878
+ }
2879
+
2880
+ // src/commands/prs/readBodyArgument.ts
2881
+ async function readBodyArgument(value) {
2882
+ if (value !== "-") return value;
2883
+ const body = (await readStdinBuffer()).toString("utf8").replace(/\n+$/, "");
2884
+ if (body.trim().length === 0) {
2885
+ console.error("Error: No body was provided on stdin.");
2886
+ process.exit(1);
2887
+ }
2888
+ return body;
2889
+ }
2890
+
2891
+ // src/commands/sessions/shared/formatPreviewComments.ts
2892
+ function formatPreviewComments(comments3) {
2893
+ return comments3.map((c, i) => {
2894
+ const quoted = c.quote.split("\n").map((line) => ` > ${line}`).join("\n");
2895
+ return `${i + 1}. On:
2896
+ ${quoted}
2897
+ Comment: ${c.note}
2898
+ `;
2899
+ });
2900
+ }
2901
+
2902
+ // src/commands/sessions/shared/reportPreviewRejection.ts
2903
+ function reportPreviewRejection(subject, decision, advice) {
2904
+ console.error(
2905
+ `${subject} rejected${decision.reason ? `: ${decision.reason}` : "."}`
2906
+ );
2907
+ const comments3 = decision.comments ?? [];
2908
+ if (comments3.length > 0) {
2909
+ console.error(
2910
+ `
2911
+ The reviewer left ${comments3.length} comment${comments3.length === 1 ? "" : "s"} on the preview. Address each one, then re-run this command:
2912
+ `
2913
+ );
2914
+ for (const line of formatPreviewComments(comments3)) console.error(line);
2915
+ }
2916
+ if (advice) console.error(advice);
2917
+ process.exit(1);
2918
+ }
2919
+
2920
+ // src/commands/sessions/daemon/readSocketLines.ts
2921
+ function readSocketLines(socket, onLine) {
2922
+ let buffer = "";
2923
+ socket.on("data", (chunk) => {
2924
+ buffer += chunk.toString("utf8");
2925
+ let newline = buffer.indexOf("\n");
2926
+ while (newline !== -1) {
2927
+ onLine(buffer.slice(0, newline));
2928
+ buffer = buffer.slice(newline + 1);
2929
+ newline = buffer.indexOf("\n");
2930
+ }
2931
+ });
2932
+ }
2933
+
2934
+ // src/commands/sessions/shared/toPreviewDecision.ts
2935
+ function toSelection(value) {
2936
+ const selection = value;
2937
+ if (typeof selection?.topLeft !== "string" || typeof selection.bottomRight !== "string")
2938
+ return void 0;
2939
+ return { topLeft: selection.topLeft, bottomRight: selection.bottomRight };
2940
+ }
2941
+ function toChecklist(value) {
2942
+ if (!Array.isArray(value)) return void 0;
2943
+ return value.flatMap((entry) => {
2944
+ const { id, ticked, comment: comment3 } = entry ?? {};
2945
+ if (typeof id !== "string") return [];
2946
+ return [
2947
+ {
2948
+ id,
2949
+ ticked: ticked === true,
2950
+ ...typeof comment3 === "string" && comment3 !== "" ? { comment: comment3 } : {}
2951
+ }
2952
+ ];
2953
+ });
2954
+ }
2955
+ function toPreviewDecision(msg) {
2956
+ if (msg.decision !== "approve" && msg.decision !== "reject") return null;
2957
+ return {
2958
+ decision: msg.decision,
2959
+ reason: msg.reason,
2960
+ comments: Array.isArray(msg.comments) ? msg.comments : void 0,
2961
+ screenshots: Array.isArray(msg.screenshots) ? msg.screenshots : void 0,
2962
+ body: typeof msg.body === "string" ? msg.body : void 0,
2963
+ reviewAfter: msg.reviewAfter === true,
2964
+ announceAfter: msg.announceAfter === true,
2965
+ draft: typeof msg.draft === "boolean" ? msg.draft : void 0,
2966
+ autoMerge: msg.autoMerge === true,
2967
+ selection: toSelection(msg.selection),
2968
+ checklist: toChecklist(msg.checklist)
2969
+ };
2970
+ }
2971
+
2972
+ // src/commands/sessions/shared/parsePreviewDecision.ts
2973
+ function parsePreviewDecision(line, requestId) {
2974
+ try {
2975
+ const msg = JSON.parse(line);
2976
+ if (msg.type === "error" && (msg.message ?? "").includes("pr-preview"))
2977
+ return { kind: "error", message: msg.message ?? "pr-preview failed" };
2978
+ if (msg.type !== "pr-decision" || msg.requestId !== requestId) return null;
2979
+ const decision = toPreviewDecision(msg);
2980
+ return decision ? { kind: "decision", decision } : null;
2981
+ } catch {
2982
+ return null;
2983
+ }
2984
+ }
2985
+
2986
+ // src/commands/sessions/shared/requestPreviewDecision.ts
2987
+ function requestPreviewDecision(request) {
2988
+ return new Promise((resolve26, reject) => {
2989
+ connectToDaemon().then((socket) => {
2990
+ let settled = false;
2991
+ const finish2 = (error, decision) => {
2992
+ if (settled) return;
2993
+ settled = true;
2994
+ socket.destroy();
2995
+ if (error) reject(error);
2996
+ else resolve26(decision);
2997
+ };
2998
+ readSocketLines(socket, (line) => {
2999
+ const incoming = parsePreviewDecision(line, request.requestId);
3000
+ if (!incoming) return;
3001
+ if (incoming.kind === "error") finish2(new Error(incoming.message));
3002
+ else finish2(void 0, incoming.decision);
3003
+ });
3004
+ socket.on("error", (error) => finish2(error));
3005
+ socket.on(
3006
+ "close",
3007
+ () => finish2(new Error("daemon closed before a decision was made"))
3008
+ );
3009
+ socket.write(`${JSON.stringify({ type: "pr-preview", ...request })}
3010
+ `);
3011
+ }, reject);
3012
+ });
3013
+ }
3014
+
3015
+ // src/commands/sessions/shared/awaitPreviewApproval.ts
3016
+ async function awaitPreviewApproval(subject, request, options2 = {}) {
3017
+ console.log("Awaiting your approval in the assist web UI preview pane\u2026");
3018
+ let decision;
3019
+ try {
3020
+ decision = await requestPreviewDecision(request);
3021
+ } catch (error) {
3022
+ console.error(
3023
+ `Error: ${error instanceof Error ? error.message : String(error)}`
3024
+ );
3025
+ process.exit(1);
3026
+ }
3027
+ if (decision.body !== void 0) options2.saveEditedBody?.(decision.body);
3028
+ if (decision.decision === "reject" && !options2.rejectIsOutcome)
3029
+ reportPreviewRejection(subject, decision, options2.rejectionAdvice);
3030
+ return decision;
3031
+ }
3032
+
3033
+ // src/commands/ask.ts
3034
+ async function ask(options2) {
3035
+ const body = await readBodyArgument(options2.body);
3036
+ if (body.trim().length === 0) {
3037
+ console.error("Error: --body is empty; there is nothing to ask about.");
3038
+ process.exit(1);
3039
+ }
3040
+ const sessionId = process.env.ASSIST_SESSION_ID;
3041
+ if (process.env.ASSIST_SESSION !== "1" || !sessionId) {
3042
+ console.log(body);
3043
+ return;
3044
+ }
3045
+ const decision = await awaitPreviewApproval(
3046
+ options2.title,
3047
+ {
3048
+ sessionId,
3049
+ requestId: randomUUID(),
3050
+ title: options2.title,
3051
+ body,
3052
+ prNumber: null,
3053
+ kind: "ask"
3054
+ },
3055
+ {
3056
+ rejectionAdvice: "Revise the update to address the reason and every comment above, then re-run `assist ask` with the revision."
3057
+ }
3058
+ );
3059
+ console.log("Approved.");
3060
+ const comments3 = decision.comments ?? [];
3061
+ if (comments3.length === 0) return;
3062
+ console.log(
3063
+ `
3064
+ The reviewer left ${comments3.length} comment${comments3.length === 1 ? "" : "s"} on the preview. Act on each one:
3065
+ `
3066
+ );
3067
+ for (const line of formatPreviewComments(comments3)) console.log(line);
3068
+ }
3069
+
3070
+ // src/commands/registerAsk.ts
3071
+ function registerAsk(program2) {
3072
+ program2.command("ask").description(
3073
+ "Open markdown in the session's web preview pane for the user to approve or reject, with inline comments, and wait for the decision; prints it outside a web session"
3074
+ ).requiredOption("--title <title>", "Pane title").requiredOption("--body <markdown|->", "Markdown to review, or - for stdin").action(ask);
3075
+ }
3076
+
2866
3077
  // src/commands/registerBackup.ts
2867
3078
  import { mkdir as mkdir2, stat } from "fs/promises";
2868
3079
  import { join as join16, resolve as resolve7 } from "path";
@@ -5599,153 +5810,14 @@ async function appendComment(orm, itemId2, text18, opts = {}) {
5599
5810
  }
5600
5811
 
5601
5812
  // src/commands/backlog/comment/reviewProposedComment.ts
5602
- import { randomUUID } from "crypto";
5603
-
5604
- // src/commands/sessions/shared/reportPreviewRejection.ts
5605
- function reportPreviewRejection(subject, decision, advice) {
5606
- console.error(
5607
- `${subject} rejected${decision.reason ? `: ${decision.reason}` : "."}`
5608
- );
5609
- const comments3 = decision.comments ?? [];
5610
- if (comments3.length > 0) {
5611
- console.error(
5612
- `
5613
- The reviewer left ${comments3.length} comment${comments3.length === 1 ? "" : "s"} on the preview. Address each one, then re-run this command:
5614
- `
5615
- );
5616
- for (const [i, c] of comments3.entries()) {
5617
- const quoted = c.quote.split("\n").map((line) => ` > ${line}`).join("\n");
5618
- console.error(`${i + 1}. On:
5619
- ${quoted}
5620
- Comment: ${c.note}
5621
- `);
5622
- }
5623
- }
5624
- if (advice) console.error(advice);
5625
- process.exit(1);
5626
- }
5627
-
5628
- // src/commands/sessions/daemon/readSocketLines.ts
5629
- function readSocketLines(socket, onLine) {
5630
- let buffer = "";
5631
- socket.on("data", (chunk) => {
5632
- buffer += chunk.toString("utf8");
5633
- let newline = buffer.indexOf("\n");
5634
- while (newline !== -1) {
5635
- onLine(buffer.slice(0, newline));
5636
- buffer = buffer.slice(newline + 1);
5637
- newline = buffer.indexOf("\n");
5638
- }
5639
- });
5640
- }
5641
-
5642
- // src/commands/sessions/shared/toPreviewDecision.ts
5643
- function toSelection(value) {
5644
- const selection = value;
5645
- if (typeof selection?.topLeft !== "string" || typeof selection.bottomRight !== "string")
5646
- return void 0;
5647
- return { topLeft: selection.topLeft, bottomRight: selection.bottomRight };
5648
- }
5649
- function toChecklist(value) {
5650
- if (!Array.isArray(value)) return void 0;
5651
- return value.flatMap((entry) => {
5652
- const { id, ticked, comment: comment3 } = entry ?? {};
5653
- if (typeof id !== "string") return [];
5654
- return [
5655
- {
5656
- id,
5657
- ticked: ticked === true,
5658
- ...typeof comment3 === "string" && comment3 !== "" ? { comment: comment3 } : {}
5659
- }
5660
- ];
5661
- });
5662
- }
5663
- function toPreviewDecision(msg) {
5664
- if (msg.decision !== "approve" && msg.decision !== "reject") return null;
5665
- return {
5666
- decision: msg.decision,
5667
- reason: msg.reason,
5668
- comments: Array.isArray(msg.comments) ? msg.comments : void 0,
5669
- screenshots: Array.isArray(msg.screenshots) ? msg.screenshots : void 0,
5670
- body: typeof msg.body === "string" ? msg.body : void 0,
5671
- reviewAfter: msg.reviewAfter === true,
5672
- announceAfter: msg.announceAfter === true,
5673
- draft: typeof msg.draft === "boolean" ? msg.draft : void 0,
5674
- autoMerge: msg.autoMerge === true,
5675
- selection: toSelection(msg.selection),
5676
- checklist: toChecklist(msg.checklist)
5677
- };
5678
- }
5679
-
5680
- // src/commands/sessions/shared/parsePreviewDecision.ts
5681
- function parsePreviewDecision(line, requestId) {
5682
- try {
5683
- const msg = JSON.parse(line);
5684
- if (msg.type === "error" && (msg.message ?? "").includes("pr-preview"))
5685
- return { kind: "error", message: msg.message ?? "pr-preview failed" };
5686
- if (msg.type !== "pr-decision" || msg.requestId !== requestId) return null;
5687
- const decision = toPreviewDecision(msg);
5688
- return decision ? { kind: "decision", decision } : null;
5689
- } catch {
5690
- return null;
5691
- }
5692
- }
5693
-
5694
- // src/commands/sessions/shared/requestPreviewDecision.ts
5695
- function requestPreviewDecision(request) {
5696
- return new Promise((resolve26, reject) => {
5697
- connectToDaemon().then((socket) => {
5698
- let settled = false;
5699
- const finish2 = (error, decision) => {
5700
- if (settled) return;
5701
- settled = true;
5702
- socket.destroy();
5703
- if (error) reject(error);
5704
- else resolve26(decision);
5705
- };
5706
- readSocketLines(socket, (line) => {
5707
- const incoming = parsePreviewDecision(line, request.requestId);
5708
- if (!incoming) return;
5709
- if (incoming.kind === "error") finish2(new Error(incoming.message));
5710
- else finish2(void 0, incoming.decision);
5711
- });
5712
- socket.on("error", (error) => finish2(error));
5713
- socket.on(
5714
- "close",
5715
- () => finish2(new Error("daemon closed before a decision was made"))
5716
- );
5717
- socket.write(`${JSON.stringify({ type: "pr-preview", ...request })}
5718
- `);
5719
- }, reject);
5720
- });
5721
- }
5722
-
5723
- // src/commands/sessions/shared/awaitPreviewApproval.ts
5724
- async function awaitPreviewApproval(subject, request, options2 = {}) {
5725
- console.log("Awaiting your approval in the assist web UI preview pane\u2026");
5726
- let decision;
5727
- try {
5728
- decision = await requestPreviewDecision(request);
5729
- } catch (error) {
5730
- console.error(
5731
- `Error: ${error instanceof Error ? error.message : String(error)}`
5732
- );
5733
- process.exit(1);
5734
- }
5735
- if (decision.body !== void 0) options2.saveEditedBody?.(decision.body);
5736
- if (decision.decision === "reject" && !options2.rejectIsOutcome)
5737
- reportPreviewRejection(subject, decision, options2.rejectionAdvice);
5738
- return decision;
5739
- }
5740
-
5741
- // src/commands/backlog/comment/reviewProposedComment.ts
5813
+ import { randomUUID as randomUUID2 } from "crypto";
5742
5814
  async function reviewProposedComment(item, text18) {
5743
5815
  if (loadConfig().backlog?.previewComments !== true) return;
5744
5816
  const sessionId = process.env.ASSIST_SESSION_ID;
5745
5817
  if (process.env.ASSIST_SESSION !== "1" || !sessionId) return;
5746
5818
  await awaitPreviewApproval("Backlog comment preview", {
5747
5819
  sessionId,
5748
- requestId: randomUUID(),
5820
+ requestId: randomUUID2(),
5749
5821
  title: `Comment on ${formatItemId(item.id)}: ${item.name}`,
5750
5822
  body: text18,
5751
5823
  prNumber: null,
@@ -5964,15 +6036,6 @@ async function confirmReplace(client, tables, incoming, fromStdin) {
5964
6036
  return promptConfirm("Replace all backlog data with this dump?", false);
5965
6037
  }
5966
6038
 
5967
- // src/commands/backlog/import/readStdinBuffer.ts
5968
- async function readStdinBuffer() {
5969
- const chunks = [];
5970
- for await (const chunk of process.stdin) {
5971
- chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
5972
- }
5973
- return Buffer.concat(chunks);
5974
- }
5975
-
5976
6039
  // src/commands/backlog/dump/copyTableIn.ts
5977
6040
  import { finished } from "stream/promises";
5978
6041
  import { from as copyFrom } from "pg-copy-streams";
@@ -6292,7 +6355,7 @@ async function resolveInsertPosition(orm, itemId2, position) {
6292
6355
  }
6293
6356
 
6294
6357
  // src/commands/backlog/addPhase/reviewProposedPhase.ts
6295
- import { randomUUID as randomUUID2 } from "crypto";
6358
+ import { randomUUID as randomUUID3 } from "crypto";
6296
6359
 
6297
6360
  // src/commands/backlog/renderPhaseSection.ts
6298
6361
  function renderPhaseSection(phase, idx) {
@@ -6316,7 +6379,7 @@ async function reviewProposedPhase(item, phaseIdx, phase) {
6316
6379
  return;
6317
6380
  await awaitPreviewApproval("Backlog phase preview", {
6318
6381
  sessionId,
6319
- requestId: randomUUID2(),
6382
+ requestId: randomUUID3(),
6320
6383
  title: `Add a phase to ${formatItemId(item.id)}: ${item.name}`,
6321
6384
  body: renderPhaseSection(phase, phaseIdx),
6322
6385
  prNumber: null,
@@ -6669,7 +6732,7 @@ function readProposedItem(source) {
6669
6732
  }
6670
6733
 
6671
6734
  // src/commands/backlog/propose/reviewProposal.ts
6672
- import { randomUUID as randomUUID3 } from "crypto";
6735
+ import { randomUUID as randomUUID4 } from "crypto";
6673
6736
  import chalk52 from "chalk";
6674
6737
 
6675
6738
  // src/shared/renderMarkdownTerminal.ts
@@ -6711,7 +6774,7 @@ async function reviewProposal(item, sessionId, confirmed) {
6711
6774
  if (sessionId) {
6712
6775
  await awaitPreviewApproval("Backlog item preview", {
6713
6776
  sessionId,
6714
- requestId: randomUUID3(),
6777
+ requestId: randomUUID4(),
6715
6778
  title: item.name,
6716
6779
  body,
6717
6780
  prNumber: null,
@@ -8125,7 +8188,7 @@ Phase ${phaseNumber} completed.`));
8125
8188
  }
8126
8189
 
8127
8190
  // src/commands/backlog/preparePhaseSession.ts
8128
- import { randomUUID as randomUUID4 } from "crypto";
8191
+ import { randomUUID as randomUUID5 } from "crypto";
8129
8192
 
8130
8193
  // src/commands/backlog/persistPhaseSession.ts
8131
8194
  import os3 from "os";
@@ -8589,7 +8652,7 @@ async function verifyPhaseResume(itemId2, resumeSessionId, phaseLabel2) {
8589
8652
  // src/commands/backlog/preparePhaseSession.ts
8590
8653
  async function preparePhaseSession(item, phase, phaseIndex, phaseNumber, totalPhases, phaseLabel2, spawnOptions) {
8591
8654
  const resumeSessionId = spawnOptions?.resumeSessionId;
8592
- const claudeSessionId = resumeSessionId ?? randomUUID4();
8655
+ const claudeSessionId = resumeSessionId ?? randomUUID5();
8593
8656
  if (resumeSessionId && !await verifyPhaseResume(item.id, resumeSessionId, phaseLabel2)) {
8594
8657
  return void 0;
8595
8658
  }
@@ -8979,7 +9042,7 @@ import chalk76 from "chalk";
8979
9042
  import enquirer7 from "enquirer";
8980
9043
 
8981
9044
  // src/commands/backlog/launchMode.ts
8982
- import { randomUUID as randomUUID5 } from "crypto";
9045
+ import { randomUUID as randomUUID6 } from "crypto";
8983
9046
 
8984
9047
  // src/commands/backlog/handleLaunchSignal.ts
8985
9048
  import chalk75 from "chalk";
@@ -9176,7 +9239,7 @@ async function launchMode(slashCommand, options2) {
9176
9239
  const resumeSessionId = options2?.resumeSessionId;
9177
9240
  if (!resumeSessionId) pullIfConfigured();
9178
9241
  process.env.ASSIST_SESSION_ID ??= String(process.pid);
9179
- const claudeSessionId = resumeSessionId ?? randomUUID5();
9242
+ const claudeSessionId = resumeSessionId ?? randomUUID6();
9180
9243
  const harness = options2?.harness ?? "claude";
9181
9244
  reportLaunchActivity(slashCommand, claudeSessionId, harness, options2);
9182
9245
  const prompt = resumeSessionId ? resumeNudge() : buildSlashCommand(slashCommand, options2?.description);
@@ -10259,7 +10322,7 @@ async function replacePlan(orm, itemId2, phases, currentPhase) {
10259
10322
  }
10260
10323
 
10261
10324
  // src/commands/backlog/updatePlan/reviewPlanUpdate.ts
10262
- import { randomUUID as randomUUID6 } from "crypto";
10325
+ import { randomUUID as randomUUID7 } from "crypto";
10263
10326
  import chalk101 from "chalk";
10264
10327
 
10265
10328
  // src/commands/backlog/updatePlan/isCompleted.ts
@@ -10416,7 +10479,7 @@ async function reviewPlanUpdate(item, phases) {
10416
10479
  if (process.env.ASSIST_SESSION === "1" && sessionId) {
10417
10480
  await awaitPreviewApproval("Plan update preview", {
10418
10481
  sessionId,
10419
- requestId: randomUUID6(),
10482
+ requestId: randomUUID7(),
10420
10483
  title: `Update the plan for ${formatItemId(item.id)}: ${item.name}`,
10421
10484
  body,
10422
10485
  prNumber: null,
@@ -14907,10 +14970,10 @@ function findLinkSpec(name) {
14907
14970
  }
14908
14971
 
14909
14972
  // src/commands/sessions/shared/newTraceId.ts
14910
- import { randomUUID as randomUUID7 } from "crypto";
14973
+ import { randomUUID as randomUUID8 } from "crypto";
14911
14974
  var TRACE_HEADER = "x-assist-trace-id";
14912
14975
  function newTraceId() {
14913
- return randomUUID7().slice(0, 8);
14976
+ return randomUUID8().slice(0, 8);
14914
14977
  }
14915
14978
 
14916
14979
  // src/commands/sessions/web/forwardToPeer.ts
@@ -23599,17 +23662,6 @@ Anything nested below the leaf level fails the run before a single write, naming
23599
23662
  ).action(fixStructure);
23600
23663
  }
23601
23664
 
23602
- // src/commands/prs/readBodyArgument.ts
23603
- async function readBodyArgument(value) {
23604
- if (value !== "-") return value;
23605
- const body = (await readStdinBuffer()).toString("utf8").replace(/\n+$/, "");
23606
- if (body.trim().length === 0) {
23607
- console.error("Error: No body was provided on stdin.");
23608
- process.exit(1);
23609
- }
23610
- return body;
23611
- }
23612
-
23613
23665
  // src/commands/github/issue/commentIssue.ts
23614
23666
  import { execFileSync as execFileSync8 } from "child_process";
23615
23667
 
@@ -23639,13 +23691,13 @@ function validateProposedContent(labels, title, body) {
23639
23691
  }
23640
23692
 
23641
23693
  // src/commands/github/issue/reviewProposedIssueComment.ts
23642
- import { randomUUID as randomUUID8 } from "crypto";
23694
+ import { randomUUID as randomUUID9 } from "crypto";
23643
23695
  async function reviewProposedIssueComment(title, body) {
23644
23696
  const sessionId = process.env.ASSIST_SESSION_ID;
23645
23697
  if (process.env.ASSIST_SESSION !== "1" || !sessionId) return;
23646
23698
  await awaitPreviewApproval("GitHub issue comment preview", {
23647
23699
  sessionId,
23648
- requestId: randomUUID8(),
23700
+ requestId: randomUUID9(),
23649
23701
  title,
23650
23702
  body,
23651
23703
  prNumber: null,
@@ -24047,13 +24099,13 @@ function resolveCreateIssueMetadata(options2) {
24047
24099
  }
24048
24100
 
24049
24101
  // src/commands/github/issue/reviewProposedIssue.ts
24050
- import { randomUUID as randomUUID9 } from "crypto";
24102
+ import { randomUUID as randomUUID10 } from "crypto";
24051
24103
  async function reviewProposedIssue(title, body, metadata2 = []) {
24052
24104
  const sessionId = process.env.ASSIST_SESSION_ID;
24053
24105
  if (process.env.ASSIST_SESSION !== "1" || !sessionId) return void 0;
24054
24106
  return await awaitPreviewApproval("GitHub issue preview", {
24055
24107
  sessionId,
24056
- requestId: randomUUID9(),
24108
+ requestId: randomUUID10(),
24057
24109
  title,
24058
24110
  body,
24059
24111
  prNumber: null,
@@ -24276,7 +24328,7 @@ function pushUnchangedIssue(number, repo, target, fetchedAt, bodyPath) {
24276
24328
  }
24277
24329
 
24278
24330
  // src/commands/github/issue/reviewProposedIssueEdit.ts
24279
- import { randomUUID as randomUUID10 } from "crypto";
24331
+ import { randomUUID as randomUUID11 } from "crypto";
24280
24332
  async function reviewProposedIssueEdit(title, body, working) {
24281
24333
  const sessionId = process.env.ASSIST_SESSION_ID;
24282
24334
  if (process.env.ASSIST_SESSION !== "1" || !sessionId) return body;
@@ -24284,7 +24336,7 @@ async function reviewProposedIssueEdit(title, body, working) {
24284
24336
  "GitHub issue edit preview",
24285
24337
  {
24286
24338
  sessionId,
24287
- requestId: randomUUID10(),
24339
+ requestId: randomUUID11(),
24288
24340
  title,
24289
24341
  body,
24290
24342
  prNumber: null,
@@ -25004,7 +25056,7 @@ function registerRefineLaunch(program2, resumeFlag) {
25004
25056
  }
25005
25057
 
25006
25058
  // src/commands/reviewPrComments.ts
25007
- import { randomUUID as randomUUID11 } from "crypto";
25059
+ import { randomUUID as randomUUID12 } from "crypto";
25008
25060
 
25009
25061
  // src/commands/review/checkoutPr.ts
25010
25062
  import { execFileSync as execFileSync15 } from "child_process";
@@ -25710,7 +25762,7 @@ async function reviewPrComments(number, options2 = {}) {
25710
25762
  const resumeSessionId = options2.resumeSessionId;
25711
25763
  validateAnnounce(number, announce);
25712
25764
  if (number && !resumeSessionId) await checkoutPr(number);
25713
- const claudeSessionId = resumeSessionId ?? randomUUID11();
25765
+ const claudeSessionId = resumeSessionId ?? randomUUID12();
25714
25766
  emitActivity({
25715
25767
  kind: "command",
25716
25768
  name: "review-pr-comments",
@@ -25728,14 +25780,14 @@ async function reviewPrComments(number, options2 = {}) {
25728
25780
  }
25729
25781
 
25730
25782
  // src/commands/fixConflict.ts
25731
- import { randomUUID as randomUUID12 } from "crypto";
25783
+ import { randomUUID as randomUUID13 } from "crypto";
25732
25784
  function buildPrompt3(rebase) {
25733
25785
  return rebase ? "/fix-conflict --rebase" : "/fix-conflict";
25734
25786
  }
25735
25787
  async function fixConflict(number, options2 = {}) {
25736
25788
  const { resumeSessionId } = options2;
25737
25789
  if (number && !resumeSessionId) await checkoutPr(number);
25738
- const claudeSessionId = resumeSessionId ?? randomUUID12();
25790
+ const claudeSessionId = resumeSessionId ?? randomUUID13();
25739
25791
  emitActivity({
25740
25792
  kind: "command",
25741
25793
  name: "fix-conflict",
@@ -26279,7 +26331,7 @@ async function offerSaveExtract(extract2, options2, paths = {}) {
26279
26331
  }
26280
26332
 
26281
26333
  // src/commands/miro/pickAnchors.ts
26282
- import { randomUUID as randomUUID13 } from "crypto";
26334
+ import { randomUUID as randomUUID14 } from "crypto";
26283
26335
 
26284
26336
  // src/commands/miro/isBox.ts
26285
26337
  var boxTypes = /* @__PURE__ */ new Set(["shape", "sticky_note"]);
@@ -26300,7 +26352,7 @@ async function pickAnchors(sessionId, items2) {
26300
26352
  "Miro anchor selection",
26301
26353
  {
26302
26354
  sessionId,
26303
- requestId: randomUUID13(),
26355
+ requestId: randomUUID14(),
26304
26356
  title: "Pick the top-left then the bottom-right box",
26305
26357
  body: encodeMiroBoardPreview(items2),
26306
26358
  prNumber: null,
@@ -27490,13 +27542,13 @@ function postReviewComment(vars) {
27490
27542
  }
27491
27543
 
27492
27544
  // src/commands/prs/reviewProposedPrComment.ts
27493
- import { randomUUID as randomUUID14 } from "crypto";
27545
+ import { randomUUID as randomUUID15 } from "crypto";
27494
27546
  async function reviewProposedPrComment(title, body, prNumber) {
27495
27547
  const sessionId = process.env.ASSIST_SESSION_ID;
27496
27548
  if (process.env.ASSIST_SESSION !== "1" || !sessionId) return;
27497
27549
  await awaitPreviewApproval("PR comment preview", {
27498
27550
  sessionId,
27499
- requestId: randomUUID14(),
27551
+ requestId: randomUUID15(),
27500
27552
  title,
27501
27553
  body,
27502
27554
  prNumber,
@@ -28116,7 +28168,7 @@ function registerPrsComments(prsCommand) {
28116
28168
  }
28117
28169
 
28118
28170
  // src/commands/prs/edit.ts
28119
- import { randomUUID as randomUUID15 } from "crypto";
28171
+ import { randomUUID as randomUUID16 } from "crypto";
28120
28172
 
28121
28173
  // src/commands/prs/applyEdit.ts
28122
28174
  import { execFileSync as execFileSync16 } from "child_process";
@@ -28311,7 +28363,7 @@ async function edit(options2) {
28311
28363
  if (process.env.ASSIST_SESSION === "1" && sessionId) {
28312
28364
  const decision = await awaitPreviewApproval("PR preview", {
28313
28365
  sessionId,
28314
- requestId: randomUUID15(),
28366
+ requestId: randomUUID16(),
28315
28367
  title: options2.title ?? title,
28316
28368
  body: newBody,
28317
28369
  prNumber: number
@@ -28510,7 +28562,7 @@ async function placePr(prNumber, title, body, options2) {
28510
28562
  }
28511
28563
 
28512
28564
  // src/commands/prs/previewAndPlace.ts
28513
- import { randomUUID as randomUUID16 } from "crypto";
28565
+ import { randomUUID as randomUUID17 } from "crypto";
28514
28566
 
28515
28567
  // src/commands/sessions/shared/requestSession.ts
28516
28568
  function parseIncoming(line, type) {
@@ -28661,7 +28713,7 @@ function enableAutoMerge() {
28661
28713
  async function previewAndPlace(args) {
28662
28714
  const decision = await awaitPreviewApproval("PR preview", {
28663
28715
  sessionId: args.sessionId,
28664
- requestId: randomUUID16(),
28716
+ requestId: randomUUID17(),
28665
28717
  title: args.title,
28666
28718
  body: args.body,
28667
28719
  prNumber: args.prNumber,
@@ -32976,10 +33028,10 @@ function registerRefactor(program2) {
32976
33028
  }
32977
33029
 
32978
33030
  // src/commands/review/checkoutOnlySession.ts
32979
- import { randomUUID as randomUUID17 } from "crypto";
33031
+ import { randomUUID as randomUUID18 } from "crypto";
32980
33032
  async function checkoutOnlySession(number) {
32981
33033
  await checkoutPr(number);
32982
- const claudeSessionId = randomUUID17();
33034
+ const claudeSessionId = randomUUID18();
32983
33035
  emitActivity({ kind: "command", name: "review", claudeSessionId });
32984
33036
  const { done: done2 } = spawnClaude("", {
32985
33037
  permissionMode: "acceptEdits",
@@ -33716,7 +33768,7 @@ function gatherHighLevelSubject(prNumber, force) {
33716
33768
  }
33717
33769
 
33718
33770
  // src/commands/review/highLevel/openHighLevelOverlay.ts
33719
- import { randomUUID as randomUUID18 } from "crypto";
33771
+ import { randomUUID as randomUUID19 } from "crypto";
33720
33772
 
33721
33773
  // src/commands/review/highLevel/buildHighLevelRecord.ts
33722
33774
  function toItem2(check2, decision) {
@@ -33803,7 +33855,7 @@ async function openHighLevelOverlay(sessionId, subject) {
33803
33855
  "High-level review",
33804
33856
  {
33805
33857
  sessionId,
33806
- requestId: randomUUID18(),
33858
+ requestId: randomUUID19(),
33807
33859
  title: `${subject.repo}#${subject.prNumber} \u2014 ${subject.title}`,
33808
33860
  body: JSON.stringify(highLevelPreviewPayload(subject)),
33809
33861
  prNumber: subject.prNumber,
@@ -36681,7 +36733,7 @@ function registerSeq(program2) {
36681
36733
  }
36682
36734
 
36683
36735
  // src/commands/show.ts
36684
- import { randomUUID as randomUUID19 } from "crypto";
36736
+ import { randomUUID as randomUUID20 } from "crypto";
36685
36737
 
36686
36738
  // src/commands/sessions/shared/sendShowPreview.ts
36687
36739
  async function sendShowPreview(request) {
@@ -36733,7 +36785,7 @@ async function show2(options2) {
36733
36785
  try {
36734
36786
  await sendShowPreview({
36735
36787
  sessionId,
36736
- requestId: randomUUID19(),
36788
+ requestId: randomUUID20(),
36737
36789
  title: options2.title ?? "Show",
36738
36790
  body
36739
36791
  });
@@ -36808,7 +36860,7 @@ function readSlackParts(files) {
36808
36860
  }
36809
36861
 
36810
36862
  // src/commands/slack/reviewProposedSlackMessage.ts
36811
- import { randomUUID as randomUUID20 } from "crypto";
36863
+ import { randomUUID as randomUUID21 } from "crypto";
36812
36864
  async function reviewProposedSlackMessage(target, body, workingPath) {
36813
36865
  const sessionId = process.env.ASSIST_SESSION_ID;
36814
36866
  if (process.env.ASSIST_SESSION !== "1" || !sessionId) return;
@@ -36818,7 +36870,7 @@ async function reviewProposedSlackMessage(target, body, workingPath) {
36818
36870
  part ? `Slack message ${part.index} of ${part.total}` : "Slack message preview",
36819
36871
  {
36820
36872
  sessionId,
36821
- requestId: randomUUID20(),
36873
+ requestId: randomUUID21(),
36822
36874
  title: part ? `${destination} (${part.index}/${part.total})` : destination,
36823
36875
  body,
36824
36876
  prNumber: null,
@@ -41023,7 +41075,7 @@ var ClientHub = class extends Set {
41023
41075
  };
41024
41076
 
41025
41077
  // src/commands/sessions/daemon/createSession.ts
41026
- import { randomUUID as randomUUID21 } from "crypto";
41078
+ import { randomUUID as randomUUID22 } from "crypto";
41027
41079
 
41028
41080
  // src/commands/sessions/daemon/sessionBase.ts
41029
41081
  function sessionBase(id, status3) {
@@ -41229,7 +41281,7 @@ function spawnRun(opts) {
41229
41281
  function createSession(id, { prompt, cwd, design, auto, harness, holdPty } = {}) {
41230
41282
  if (harness && harness !== "claude")
41231
41283
  return createHarnessSession(id, harness, prompt, cwd, holdPty);
41232
- const claudeSessionId = randomUUID21();
41284
+ const claudeSessionId = randomUUID22();
41233
41285
  return {
41234
41286
  ...sessionBase(id, prompt ? "running" : "waiting"),
41235
41287
  name: `Session ${id}`,
@@ -41943,7 +41995,8 @@ var PREVIEW_KINDS = [
41943
41995
  "miro-board",
41944
41996
  "slack-post",
41945
41997
  "high-level-review",
41946
- "show"
41998
+ "show",
41999
+ "ask"
41947
42000
  ];
41948
42001
  function isPreviewKind(value) {
41949
42002
  return PREVIEW_KINDS.includes(value);
@@ -41960,6 +42013,7 @@ function previewTargetLabel(kind, itemType, prNumber, draft) {
41960
42013
  if (kind === "slack-post") return "slack post";
41961
42014
  if (kind === "high-level-review") return "high-level review";
41962
42015
  if (kind === "show") return "show";
42016
+ if (kind === "ask") return "ask";
41963
42017
  if (kind === "backlog-item") return `backlog ${itemType}`;
41964
42018
  if (prNumber !== null) return `edit #${prNumber}`;
41965
42019
  return draft ? "create draft" : "create";
@@ -43501,7 +43555,7 @@ function codexRespawnPlan(session) {
43501
43555
  }
43502
43556
 
43503
43557
  // src/commands/sessions/daemon/interactiveRespawnPlan.ts
43504
- import { randomUUID as randomUUID22 } from "crypto";
43558
+ import { randomUUID as randomUUID23 } from "crypto";
43505
43559
  function interactiveRespawnPlan(session, resumes) {
43506
43560
  const { claudeSessionId, cwd, initialPrompt, design, auto } = session;
43507
43561
  if (!resumes) return null;
@@ -43521,7 +43575,7 @@ function interactiveRespawnPlan(session, resumes) {
43521
43575
  return null;
43522
43576
  }
43523
43577
  function freshClaudePlan(session, prompt, cwd) {
43524
- const claudeSessionId = randomUUID22();
43578
+ const claudeSessionId = randomUUID23();
43525
43579
  return {
43526
43580
  spawn: () => {
43527
43581
  session.claudeSessionId = claudeSessionId;
@@ -44531,10 +44585,10 @@ function startReusedRunPty(session, assistArgs, itemId2, hold, clients, onStatus
44531
44585
  }
44532
44586
 
44533
44587
  // src/commands/sessions/daemon/createWatcherSession.ts
44534
- import { randomUUID as randomUUID23 } from "crypto";
44588
+ import { randomUUID as randomUUID24 } from "crypto";
44535
44589
  var WATCH_PROMPT = "/watch";
44536
44590
  function createWatcherSession(id, cwd) {
44537
- const claudeSessionId = randomUUID23();
44591
+ const claudeSessionId = randomUUID24();
44538
44592
  return {
44539
44593
  ...sessionBase(id, "running"),
44540
44594
  name: `Session ${id}`,
@@ -47916,6 +47970,7 @@ registerLitellm(program);
47916
47970
  registerRavendb(program);
47917
47971
  registerSeq(program);
47918
47972
  registerShow(program);
47973
+ registerAsk(program);
47919
47974
  registerSlack(program);
47920
47975
  registerSql(program);
47921
47976
  registerTranscript(program);